Skip to content

Commit a1be118

Browse files
committed
Merge branch 'master' into issue-1294-functional-testing-module
2 parents 5e14e66 + 288488e commit a1be118

File tree

9 files changed

+151
-74
lines changed

9 files changed

+151
-74
lines changed

.github/workflows/copyright-test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
branches:
66
- master
77
pull_request:
8+
if: github.event.pull_request.draft == false
89
branches:
910
- '**'
1011

.github/workflows/coverage-test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
branches:
66
- master
77
pull_request:
8+
if: github.event.pull_request.draft == false
89
branches:
910
- '**'
1011

.github/workflows/docs-test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
branches:
66
- master
77
pull_request:
8+
if: github.event.pull_request.draft == false
89
branches:
910
- '**'
1011

.github/workflows/style-test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
branches:
66
- master
77
pull_request:
8+
if: github.event.pull_request.draft == false
89
branches:
910
- '**'
1011

.github/workflows/unit-test-os-coverage.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
branches:
66
- master
77
pull_request:
8+
if: github.event.pull_request.draft == false
89
branches:
910
- '**'
1011

.github/workflows/unit-test-python-coverage.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
branches:
66
- master
77
pull_request:
8+
if: github.event.pull_request.draft == false
89
branches:
910
- '**'
1011

pints/_mcmc/_differential_evolution.py

Lines changed: 98 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,25 @@ def current_log_pdfs(self):
129129
""" See :meth:`MultiChainMCMC.current_log_pdfs()`. """
130130
return self._current_log_pdfs
131131

132-
def set_gaussian_error(self, gaussian_error):
132+
def gamma(self):
133133
"""
134-
If ``True`` sets the error process to be a gaussian error,
135-
``N(0, b*)``; if ``False``, it uses a uniform error ``U(-b*, b*)``;
136-
where ``b* = b`` if absolute scaling used and ``b* = mu * b`` if
137-
relative scaling is used instead.
134+
Returns the coefficient ``gamma`` used in updating the position of each
135+
chain.
138136
"""
139-
gaussian_error = bool(gaussian_error)
140-
self._gaussian_error = gaussian_error
137+
return self._gamma
138+
139+
def gamma_switch_rate(self):
140+
"""
141+
Returns the number of steps between iterations where gamma is set to 1
142+
(then reset immediately afterwards).
143+
"""
144+
return self._gamma_switch_rate
145+
146+
def gaussian_error(self):
147+
"""
148+
Returns whether a Gaussian versus uniform error process is used.
149+
"""
150+
return self._gaussian_error
141151

142152
def _initialise(self):
143153
"""
@@ -167,10 +177,52 @@ def _initialise(self):
167177
# Update sampler state
168178
self._running = True
169179

180+
def n_hyper_parameters(self):
181+
""" See :meth:`TunableMethod.n_hyper_parameters()`. """
182+
return 5
183+
184+
def name(self):
185+
""" See :meth:`pints.MCMCSampler.name()`. """
186+
return 'Differential Evolution MCMC'
187+
188+
def _r_draw(self, i, num_chains):
189+
"""
190+
Chooses two chain indexes uniformly at random such that they are
191+
not the same nor do they equal `i`.
192+
"""
193+
indexes = list(range(num_chains))
194+
indexes.pop(i)
195+
r1, r2 = np.random.choice(indexes, 2, replace=False)
196+
return r1, r2
197+
198+
def relative_scaling(self):
199+
"""
200+
Returns whether an error process whose standard deviation scales
201+
relatively is used (False indicates absolute scale).
202+
"""
203+
return self._relative_scaling
204+
205+
def scale_coefficient(self):
206+
"""
207+
Sets the scale coefficient ``b`` of the error process used in updating
208+
the position of each chain.
209+
"""
210+
return self._b
211+
212+
def set_gamma(self, gamma):
213+
"""
214+
Sets the coefficient ``gamma`` used in updating the position of each
215+
chain.
216+
"""
217+
gamma = float(gamma)
218+
if gamma < 0:
219+
raise ValueError('Gamma must be non-negative.')
220+
self._gamma = gamma
221+
170222
def set_gamma_switch_rate(self, gamma_switch_rate):
171223
"""
172224
Sets the number of steps between iterations where gamma is set to 1
173-
(then reset immediately afterwards)
225+
(then reset immediately afterwards).
174226
"""
175227
if gamma_switch_rate < 1:
176228
raise ValueError('The interval number of steps between ' +
@@ -180,6 +232,35 @@ def set_gamma_switch_rate(self, gamma_switch_rate):
180232
' gamma=1 iterations must be an integer.')
181233
self._gamma_switch_rate = gamma_switch_rate
182234

235+
def set_gaussian_error(self, gaussian_error):
236+
"""
237+
If ``True`` sets the error process to be a gaussian error,
238+
``N(0, b*)``; if ``False``, it uses a uniform error ``U(-b*, b*)``;
239+
where ``b* = b`` if absolute scaling used and ``b* = mu * b`` if
240+
relative scaling is used instead.
241+
"""
242+
gaussian_error = bool(gaussian_error)
243+
self._gaussian_error = gaussian_error
244+
245+
def set_hyper_parameters(self, x):
246+
"""
247+
The hyper-parameter vector is ``[gamma, gaussian_scale_coefficient,
248+
gamma_switch_rate, gaussian_error, relative_scaling]``.
249+
250+
See :meth:`TunableMethod.set_hyper_parameters()`.
251+
"""
252+
self.set_gamma(x[0])
253+
self.set_scale_coefficient(x[1])
254+
try:
255+
int_x2 = int(x[2])
256+
except (ValueError, TypeError):
257+
raise ValueError('The interval number of steps between ' +
258+
'gamma=1 iterations must be convertable ' +
259+
'to an integer.')
260+
self.set_gamma_switch_rate(int_x2)
261+
self.set_gaussian_error(x[3])
262+
self.set_relative_scaling(x[4])
263+
183264
def set_relative_scaling(self, relative_scaling):
184265
"""
185266
Sets whether to use an error process whose standard deviation scales
@@ -193,9 +274,15 @@ def set_relative_scaling(self, relative_scaling):
193274
else:
194275
self._b_star = np.repeat(self._b, self._n_parameters)
195276

196-
def name(self):
197-
""" See :meth:`pints.MCMCSampler.name()`. """
198-
return 'Differential Evolution MCMC'
277+
def set_scale_coefficient(self, b):
278+
"""
279+
Sets the scale coefficient ``b`` of the error process used in updating
280+
the position of each chain.
281+
"""
282+
b = float(b)
283+
if b < 0:
284+
raise ValueError('Scale coefficient must be non-negative.')
285+
self._b = b
199286

200287
def tell(self, proposed_log_pdfs):
201288
""" See :meth:`pints.MultiChainMCMC.tell()`. """
@@ -246,56 +333,3 @@ def tell(self, proposed_log_pdfs):
246333
# Return samples to add to chains
247334
self._current.setflags(write=False)
248335
return self._current
249-
250-
def set_scale_coefficient(self, b):
251-
"""
252-
Sets the scale coefficient ``b`` of the error process used in updating
253-
the position of each chain.
254-
"""
255-
b = float(b)
256-
if b < 0:
257-
raise ValueError('Scale coefficient must be non-negative.')
258-
self._b = b
259-
260-
def set_gamma(self, gamma):
261-
"""
262-
Sets the coefficient ``gamma`` used in updating the position of each
263-
chain.
264-
"""
265-
gamma = float(gamma)
266-
if gamma < 0:
267-
raise ValueError('Gamma must be non-negative.')
268-
self._gamma = gamma
269-
270-
def n_hyper_parameters(self):
271-
""" See :meth:`TunableMethod.n_hyper_parameters()`. """
272-
return 5
273-
274-
def set_hyper_parameters(self, x):
275-
"""
276-
The hyper-parameter vector is ``[gamma, gaussian_scale_coefficient,
277-
gamma_switch_rate, gaussian_error, relative_scaling]``.
278-
279-
See :meth:`TunableMethod.set_hyper_parameters()`.
280-
"""
281-
self.set_gamma(x[0])
282-
self.set_scale_coefficient(x[1])
283-
try:
284-
int_x2 = int(x[2])
285-
except (ValueError, TypeError):
286-
raise ValueError('The interval number of steps between ' +
287-
'gamma=1 iterations must be convertable ' +
288-
'to an integer.')
289-
self.set_gamma_switch_rate(int_x2)
290-
self.set_gaussian_error(x[3])
291-
self.set_relative_scaling(x[4])
292-
293-
def _r_draw(self, i, num_chains):
294-
"""
295-
Chooses two chain indexes uniformly at random such that they are
296-
not the same nor do they equal `i`.
297-
"""
298-
indexes = list(range(num_chains))
299-
indexes.pop(i)
300-
r1, r2 = np.random.choice(indexes, 2, replace=False)
301-
return r1, r2

pints/tests/test_mcmc_controller.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,43 @@ def f(x):
231231
self.assertEqual(chains.shape[2], n_parameters)
232232
self.assertIs(chains, mcmc.chains())
233233

234+
def test_hyperparameters_constant(self):
235+
# Test that sampler hyperparameter remain same before and after run
236+
237+
# single chain method
238+
n_chains = 1
239+
x0 = np.array(self.real_parameters) * 1.1
240+
xs = [x0]
241+
mcmc = pints.MCMCController(
242+
self.log_posterior, n_chains, xs, method=pints.HamiltonianMCMC)
243+
step_size = 0.77
244+
for sampler in mcmc.samplers():
245+
sampler.set_leapfrog_step_size(step_size)
246+
mcmc.set_max_iterations(5)
247+
mcmc.set_log_to_screen(False)
248+
mcmc.run()
249+
for sampler in mcmc.samplers():
250+
self.assertEqual(sampler.leapfrog_step_size()[0], step_size)
251+
252+
# test multiple chain method
253+
# Set up problem for 10 chains
254+
x0 = np.array(self.real_parameters)
255+
xs = []
256+
for i in range(10):
257+
f = 0.9 + 0.2 * np.random.rand()
258+
xs.append(x0 * f)
259+
n_chains = len(xs)
260+
261+
meth = pints.DifferentialEvolutionMCMC
262+
mcmc = pints.MCMCController(
263+
self.log_posterior, n_chains, xs, method=meth)
264+
switch_rate = 4
265+
mcmc.samplers()[0].set_gamma_switch_rate(switch_rate)
266+
mcmc.set_max_iterations(5)
267+
mcmc.set_log_to_screen(False)
268+
mcmc.run()
269+
self.assertEqual(mcmc.samplers()[0].gamma_switch_rate(), switch_rate)
270+
234271
def test_multi(self):
235272
# Test with a multi-chain method
236273

pints/tests/test_mcmc_differential_evolution.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -149,31 +149,31 @@ def test_set_hyper_parameters(self):
149149
self.assertEqual(mcmc.n_hyper_parameters(), 5)
150150

151151
mcmc.set_hyper_parameters([0.5, 0.6, 20, 0, 0])
152-
self.assertEqual(mcmc._gamma, 0.5)
153-
self.assertEqual(mcmc._b, 0.6)
154-
self.assertEqual(mcmc._gamma_switch_rate, 20)
155-
self.assertTrue(not mcmc._gaussian_error)
156-
self.assertTrue(not mcmc._relative_scaling)
152+
self.assertEqual(mcmc.gamma(), 0.5)
153+
self.assertEqual(mcmc.scale_coefficient(), 0.6)
154+
self.assertEqual(mcmc.gamma_switch_rate(), 20)
155+
self.assertTrue(not mcmc.gaussian_error())
156+
self.assertTrue(not mcmc.relative_scaling())
157157

158158
mcmc.set_gamma(0.5)
159-
self.assertEqual(mcmc._gamma, 0.5)
159+
self.assertEqual(mcmc.gamma(), 0.5)
160160
self.assertRaisesRegex(ValueError,
161161
'non-negative', mcmc.set_gamma, -1)
162162

163163
mcmc.set_scale_coefficient(1)
164-
self.assertTrue(not mcmc._relative_scaling)
164+
self.assertTrue(not mcmc.relative_scaling())
165165
self.assertRaisesRegex(ValueError,
166166
'non-negative', mcmc.set_scale_coefficient, -1)
167167

168168
mcmc.set_gamma_switch_rate(11)
169-
self.assertEqual(mcmc._gamma_switch_rate, 11)
169+
self.assertEqual(mcmc.gamma_switch_rate(), 11)
170170
self.assertRaisesRegex(
171171
ValueError, 'integer', mcmc.set_gamma_switch_rate, 11.5)
172172
self.assertRaisesRegex(
173173
ValueError, 'exceed 1', mcmc.set_gamma_switch_rate, 0)
174174

175175
mcmc.set_gaussian_error(False)
176-
self.assertTrue(not mcmc._gaussian_error)
176+
self.assertTrue(not mcmc.gaussian_error())
177177

178178
mcmc.set_relative_scaling(0)
179179
self.assertTrue(np.array_equal(mcmc._b_star,
@@ -184,7 +184,7 @@ def test_set_hyper_parameters(self):
184184

185185
# test implicit conversion to int
186186
mcmc.set_hyper_parameters([0.5, 0.6, 20.2, 0, 0])
187-
self.assertEqual(mcmc._gamma_switch_rate, 20)
187+
self.assertEqual(mcmc.gamma_switch_rate(), 20)
188188
self.assertRaisesRegex(
189189
ValueError, 'convertable to an integer',
190190
mcmc.set_hyper_parameters, (0.5, 0.6, 'sdf', 0, 0))

0 commit comments

Comments
 (0)