@@ -3,46 +3,56 @@ import arraymancer
33
44
55type
6+ RbfFunc * = proc (r: Tensor [float ], epsilon: float ): Tensor [float ]
67 RbfType * [T] = object
78 points* : Tensor [float ] # (n_points, n_dim)
89 values* : Tensor [T] # (n_points, n_values)
910 coeffs* : Tensor [float ] # (n_points, n_values)
1011 epsilon* : float
12+ f* : RbfFunc
1113
14+ # Idea: blocked distance matrix for better cache friendliness
1215proc distanceMatrix (p1, p2: Tensor [float ]): Tensor [float ] =
1316 # # Returns distance matrix of shape (n_points, n_points)
14- let n_points = p1.shape[0 ]
17+ let n_points1 = p1.shape[0 ]
18+ let n_points2 = p2.shape[0 ]
1519 let n_dims = p1.shape[1 ]
16- result = newTensor [float ](n_points, n_points )
17- for i in 0 ..< n_points :
18- for j in 0 ..< n_points :
20+ result = newTensor [float ](n_points2, n_points1 )
21+ for i in 0 ..< n_points2 :
22+ for j in 0 ..< n_points1 :
1923 var r2 = 0.0
2024 for k in 0 ..< n_dims:
21- let diff = p1 [i,k] - p2 [j,k]
25+ let diff = p2 [i,k] - p1 [j,k]
2226 r2 += diff * diff
2327 result [i, j] = sqrt (r2)
2428
2529proc compactRbfFunc * (r: Tensor [float ], epsilon: float ): Tensor [float ] =
2630 result = map_inline (r):
2731 (1 - x/ epsilon) ^ 4 * (4 * x/ epsilon + 1 ) * float (x < epsilon)
2832
29- proc newRbf * [T](points: Tensor [float ], values: Tensor [T], rbfFunc: proc (r: Tensor [ float ], epsilon: float ): Tensor [ float ] = compactRbfFunc, epsilon: float = 1 ): RbfType [T] =
33+ proc newRbf * [T](points: Tensor [float ], values: Tensor [T], rbfFunc: RbfFunc = compactRbfFunc, epsilon: float = 1 ): RbfType [T] =
3034 assert points.shape[0 ] == values.shape[0 ]
3135 let dist = distanceMatrix (points, points)
3236 let A = rbfFunc (dist, epsilon)
3337 let coeffs = solve (A, values)
34- result = RbfType [T](points: points, values: values, coeffs: coeffs, epsilon: epsilon)
35-
36- let x1 = @ [@ [0.0 , 0.0 , 0.0 ], @ [1.0 , 1.0 , 0.0 ], @ [1.0 , 2.0 , 0.0 ]].toTensor
37- let x2 = @ [@ [0.0 , 0.0 , 1.0 ], @ [1.0 , 1.0 , 2.0 ], @ [1.0 , 2.0 , 3.0 ]].toTensor
38- echo distanceMatrix (x1, x1)
39- let values = @ [0.0 , 1.0 , 2.0 ].toTensor
40- echo newRbf (x1, values, epsilon= 10 )
41-
42- import benchy
43-
44- let pos = randomTensor (5000 , 3 , 1.0 )
45- let vals = randomTensor (5000 , 1 , 1.0 )
46- timeIt " Rbf" :
47- keep newRbf (pos, vals)
38+ result = RbfType [T](points: points, values: values, coeffs: coeffs, epsilon: epsilon, f: rbfFunc)
39+
40+ proc eval * [T](rbf: RbfType [T], x: Tensor [float ]): Tensor [T] =
41+ let dist = distanceMatrix (rbf.points, x)
42+ let A = rbf.f (dist, rbf.epsilon)
43+ result = A * rbf.coeffs
44+
45+ when isMainModule :
46+ let x1 = @ [@ [0.0 , 0.0 , 0.0 ], @ [1.0 , 1.0 , 0.0 ], @ [1.0 , 2.0 , 0.0 ]].toTensor
47+ let x2 = @ [@ [0.0 , 0.0 , 1.0 ], @ [1.0 , 1.0 , 2.0 ], @ [1.0 , 2.0 , 3.0 ]].toTensor
48+ echo distanceMatrix (x1, x1)
49+ let values = @ [0.0 , 1.0 , 2.0 ].toTensor
50+ echo newRbf (x1, values, epsilon= 10 )
51+
52+ import benchy
53+
54+ let pos = randomTensor (5000 , 3 , 1.0 )
55+ let vals = randomTensor (5000 , 1 , 1.0 )
56+ timeIt " Rbf" :
57+ keep newRbf (pos, vals)
4858
0 commit comments