fips.Problem.simulate#
- Problem.simulate(rng=None, truth=None)[source]#
Return a truth and the observations it would give, \(H x + c + e\).
The problem as a world that makes data: the truth is drawn from the prior, \(x \sim N(x_0, S_0)\), and the observations are its noise-free prediction (
predict()) plus an error drawn from the model-data mismatch, \(e \sim N(0, S_z)\). Solving the problem on these observations,post.with_data(obs), and comparing the estimate with the truth tests an inversion on data whose answer is known; a loop of them over one generator is a Monte Carlo of how often the posterior’s intervals hold the truth.- Parameters:
rng (
int|Generator|None) – A seed, or the generator to draw from (used as given, so one generator passed to every call gives independent trials). None draws from fresh entropy. It goes throughnumpy.random.default_rng(), as SciPy’srngargument does. The truth is drawn first and the error second, so a given truth draws the error alone.truth (
Vector|None) – A state to use as the truth instead of drawing one, on the prior’s labels in any order: another inventory, 1.5 times the prior. Its observations still carry the error.
- Return type:
- Returns:
truth (Vector) – The truth, on the prior’s space (the given one, put in the prior’s order).
obs (Vector) – The synthetic observations, on the observations’ space and named as the problem’s. They are ready for
Posterior.with_data.
- Raises:
TypeError – If truth is not a Vector.
ValueError – If truth does not have exactly the prior’s labels; the message names those on one side only.
numpy.linalg.LinAlgError – If a covariance has a clearly negative eigenvalue.
See also
predictThe observations without the error.
Covariance.sampleThe draw of the truth and of the error.
Posterior.with_dataThe posterior of other observations, one product.
Posterior.recoveryThe exact mean and spread of the error over such trials.
Notes
The problem’s own observations are not used, only their labels and name. A different world (another background, another forward operator, an observation error four times the assumed one) is another
Problem, made the way the first was with one input changed:world.simulate(rng)gives its data, andpost.with_data(obs)solves them with the assumptions of post’s problem.Examples
>>> import numpy as np >>> import pandas as pd >>> import fips >>> cells = pd.Index(["a", "b"], name="cell") >>> obs_id = pd.Index(["o1", "o2", "o3"], name="obs_id") >>> prior = fips.Vector.from_series(pd.Series(0.0, index=cells), block="flux") >>> obs = fips.Vector.from_series(pd.Series(0.0, index=obs_id), block="co2") >>> problem = fips.Problem( ... prior=prior, ... prior_cov=fips.Independent().with_std(1.0), ... obs=obs, ... obs_cov=fips.Independent().with_std(0.1), ... forward=fips.Operator( ... np.array([[1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]), ... obs.space, ... prior.space, ... ), ... ) >>> truth, synthetic = problem.simulate(rng=0) >>> truth.values.round(2) array([ 0.13, -0.13]) >>> synthetic.values.round(2) array([ 0.19, -0.12, -0.06]) >>> fips.solve(problem).with_data(synthetic).estimate.values.round(2) array([ 0.15, -0.16])