Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions autofit/non_linear/fitness.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,17 +168,18 @@ def call(self, parameters):
-------
The figure of merit returned to the non-linear search, which is either the log likelihood or log posterior.
"""
# Get instance from model
instance = self.model.instance_from_vector(vector=parameters, xp=self._xp)

if self._xp.__name__.startswith("jax"):

# Get instance from model (must be side-effect free and exception-free under JAX)
instance = self.model.instance_from_vector(vector=parameters, xp=self._xp)

# Evaluate log likelihood (must be side-effect free and exception-free)
log_likelihood = self.analysis.log_likelihood_function(instance=instance)

else:

try:
instance = self.model.instance_from_vector(vector=parameters, xp=self._xp)
log_likelihood = self.analysis.log_likelihood_function(instance=instance)
except exc.FitException:
return self.resample_figure_of_merit
Expand Down
32 changes: 32 additions & 0 deletions test_autofit/non_linear/test_fitness_assertions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import numpy as np

import autofit as af
from autofit.non_linear.fitness import Fitness


def test_fitness_returns_resample_fom_on_assertion_failure():
"""
If an added assertion rejects a sampled parameter vector, ``Fitness.call``
must return ``resample_figure_of_merit`` rather than letting the
``FitException`` escape into the non-linear search. Regression for
the DynestyStatic-blocking bug where ``instance_from_vector`` was
called outside the ``try/except FitException`` block.
"""
gaussian_0 = af.Model(af.ex.Gaussian)
gaussian_1 = af.Model(af.ex.Gaussian)
gaussian_0.add_assertion(gaussian_0.centre > gaussian_1.centre)
model = af.Collection(gaussian_0=gaussian_0, gaussian_1=gaussian_1)

data = np.ones(20)
noise_map = np.ones(20) * 0.1
analysis = af.ex.Analysis(data=data, noise_map=noise_map)

fitness = Fitness(model=model, analysis=analysis)

# centre_0 (index 0) = 10 < centre_1 (index 3) = 20 → assertion violated
violating = [10.0, 1.0, 1.0, 20.0, 1.0, 1.0]
assert fitness.call(violating) == fitness.resample_figure_of_merit

# centre_0 = 20 > centre_1 = 10 → assertion satisfied, real FOM returned
satisfying = [20.0, 1.0, 1.0, 10.0, 1.0, 1.0]
assert fitness.call(satisfying) != fitness.resample_figure_of_merit
Loading