Skip to content

Commit 6c83718

Browse files
author
Benjamin Chrétien
committed
Improve performance of simple finite differences.
1 parent 801f248 commit 6c83718

3 files changed

Lines changed: 51 additions & 4 deletions

File tree

src/roboptim/core/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ def impl_compute (self, result, x):
176176
def impl_gradient (self, result, x, functionId):
177177
gradient (self._fd, result, x, functionId)
178178

179+
def impl_jacobian (self, result, x):
180+
jacobian (self._fd, result, x)
181+
179182

180183
class PyProblem(object):
181184
def __init__(self, cost):

src/wrap.hh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,13 @@ namespace roboptim
194194
{
195195
fd_t::impl_gradient (gradient, argument, functionId);
196196
}
197+
198+
virtual void impl_jacobian (jacobian_ref jacobian,
199+
const_argument_ref argument)
200+
const
201+
{
202+
fd_t::impl_jacobian (jacobian, argument);
203+
}
197204
};
198205

199206

tests/function_pool.py

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ def __init__ (self, n):
1515
self.n = n
1616
self.data = np.zeros (n)
1717
self.jac = np.zeros ((n, 2*n))
18+
self.compute_counter = 0
19+
self.jacobian_counter = 0
20+
21+
def reset (self):
22+
self.compute_counter = 0
23+
self.jacobian_counter = 0
1824

1925
def impl_compute (self, result, x):
2026
print("Engine: impl_compute")
@@ -33,11 +39,14 @@ def jacobian (self, x):
3339

3440
def computeData (self, x):
3541
print("Engine: computing data")
42+
self.compute_counter += 1
43+
# For each square function
3644
for i in range(self.n):
3745
self.data[i] = x[2*i]**2 + x[2*i+1]**2
3846

3947
def computeJacobian (self, x):
4048
print("Engine: computing Jacobian")
49+
self.jacobian_counter += 1
4150
self.jac.fill (0.)
4251
# For each square function
4352
for i in range(self.n):
@@ -77,6 +86,9 @@ def test_engine(self):
7786
engine (x)
7887
np.testing.assert_almost_equal (engine.data,
7988
[xi**2 + yi**2 for xi,yi in x.reshape(engine.n, 2) ])
89+
assert engine.compute_counter == 1
90+
assert engine.jacobian_counter == 0
91+
engine.reset ()
8092

8193
np.testing.assert_almost_equal (engine.jac, np.zeros ((engine.n, 2*engine.n)))
8294
engine.jacobian (x)
@@ -85,46 +97,71 @@ def test_engine(self):
8597
for j in range(2):
8698
jac[i,2*i+j] = 2. * x[2*i+j]
8799
np.testing.assert_almost_equal (engine.jac, jac)
100+
assert engine.compute_counter == 0
101+
assert engine.jacobian_counter == 1
102+
engine.reset ()
88103

89104
def test_pool(self):
90-
engine = Engine (3)
105+
n = 3
106+
engine = Engine (n)
91107
np.testing.assert_almost_equal (engine.data, np.zeros (engine.n))
92-
functions = [Square (engine, 0.), Square (engine, 1.), Square (engine, 2.)]
108+
functions = [Square (engine, float(i)) for i in range (n)]
93109
print(engine)
110+
94111
pool = roboptim.core.PyFunctionPool (engine, functions, "Dummy pool")
95112
print(pool)
113+
96114
x = np.array([10., -5., 1., 2., -1., 1.])
115+
assert len(x) == 2 * n
116+
97117
res = pool (x)
98118
np.testing.assert_almost_equal (engine.data,
99119
[xi**2 + yi**2 for xi,yi in x.reshape(engine.n, 2) ])
120+
assert engine.compute_counter == 1
121+
assert engine.jacobian_counter == 0
122+
engine.reset ()
123+
100124
pool_jac = pool.jacobian (x)
101125
jac = np.zeros ((engine.n, 2*engine.n))
102126
for i in range(engine.n):
103127
for j in range(2):
104128
jac[i,2*i+j] = 2. * x[2*i+j]
105129
np.testing.assert_almost_equal (pool_jac, jac)
130+
assert engine.compute_counter == 0
131+
assert engine.jacobian_counter == 1
132+
engine.reset ()
106133

107134
def test_pool_fd(self):
108-
engine = Engine (3)
135+
n = 3
136+
engine = Engine (n)
109137
print(engine)
110-
functions = [Square (engine, 0.), Square (engine, 1.), Square (engine, 2.)]
138+
functions = [Square (engine, float(i)) for i in range (n)]
111139
pool = roboptim.core.PyFunctionPool (engine, functions, "Dummy FD pool")
112140

113141
fd_rule = roboptim.core.FiniteDifferenceRule.SIMPLE
114142
fd_pool = roboptim.core.PyFiniteDifference (pool, rule = fd_rule)
115143
print(fd_pool)
116144

117145
x = np.array([10., -5., 1., 2., -1., 1.])
146+
assert len(x) == 2 * n
147+
118148
res = fd_pool (x)
119149
np.testing.assert_almost_equal (engine.data,
120150
[xi**2 + yi**2 for xi,yi in x.reshape(engine.n, 2) ])
151+
assert engine.compute_counter == 1
152+
assert engine.jacobian_counter == 0
153+
engine.reset ()
121154

122155
fd_pool_jac = fd_pool.jacobian (x)
123156
jac = np.zeros ((engine.n, 2*engine.n))
124157
for i in range(engine.n):
125158
for j in range(2):
126159
jac[i,2*i+j] = 2. * x[2*i+j]
127160
np.testing.assert_almost_equal (fd_pool_jac, jac, 5)
161+
print(engine.compute_counter)
162+
assert engine.compute_counter == 1 + len(x) # simple rule: (f(x+h)-f(x))/h
163+
assert engine.jacobian_counter == 0
164+
engine.reset ()
128165

129166
if __name__ == '__main__':
130167
unittest.main()

0 commit comments

Comments
 (0)