OED Core Classes#
This package implements the core components of OED algorithms. Implementations here are to be extended by OED algoirthms are not intended to be instantiated by the user directly.
- class BayesianInversionCriterion(configs=None)[source]#
Bases:
InversionCriterion
Class for utility functions / optimality criteria defined for Bayesian inverse problems. This class is a subclass of
InversionCriterion
and thus inherits all its methods and attributes.- __init__(configs=None)[source]#
Constructor for utility functions / optimality criteria.
- Parameters:
configs (dict) – Object holding configurations for the criterion.
- validate_configurations(configs, raise_for_invalid=True)[source]#
Each simulation model MUST implement it’s own function that validates its own configurations. If the validation is self contained (validates all configuations), then that’s it. However, one can just validate the configurations of of the immediate class and call super to validate configurations associated with the parent class.
If one does not wish to do any validation (we strongly advise against that), simply add the signature of this function to the model class.
Note
The purposed of this method is to make sure that the settings in the configurations object self._CONFIGURATIONS are of the right type/values and are conformable with each other. This function is called upon instantiation of the object, and each time a configuration value is updated. Thus, this function need to be inexpensive and should not do heavy computations.
- Parameters:
configs (dict | BayesianInversionCriterionConfigs) – configurations to validate. If a PyOEDConfigs object is passed, validation is performed on the entire set of configurations. However, if a dictionary is passed, validation is performed only on the configurations corresponding to the keys in the dictionary.
- Raises:
PyOEDConfigsValidationError – if the configurations are invalid and raise_for_invalid is set to True.
AttributeError – if any (or a group) of the configurations does not exist in the model configurations
PyOEDConfigs
.
- class BayesianInversionCriterionConfigs(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', oed_problem=None, lp_behavior=LP_Behavior.MAP)[source]#
Bases:
InversionCriterionConfigs
Configuration class for Bayesian utility functions / optimality criteria. Subclass of
InversionCriterionConfigs
, thus inherits all its attributes.- Parameters:
verbose (bool) – a boolean flag to control verbosity of the object.
debug (bool) – a boolean flag that enables adding extra functionlity in a debug mode
output_dir (str | Path) – the base directory where the output files will be saved.
oed_problem (InversionOED | None) – OED problem for which the utility function is defined. This must be an instance of
InversionOED
.lp_behavior (LP_Behavior | str) – behavior of the linearization point (MAP, prior, manual). By default, it is set to MAP. However, if the oed problem is linear, the passed parameter is ignored and is changed to LINEAR instead. If you wish to forcefully choose the linearization point despite the linearity of the problem, set the field after instantiation.
- __init__(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', oed_problem=None, lp_behavior=LP_Behavior.MAP)#
- BayesianInversionUtility#
alias of
BayesianInversionCriterion
- BayesianInversionUtilityConfigs#
alias of
BayesianInversionCriterionConfigs
- class Criterion(configs=None)[source]#
Bases:
PyOEDObject
Base class for utility functions and optimality criteria used in OED.
Note
The term ‘utility function’ is associated with rewards and is thus used in the context of maximization. Examples include expected information gain, expected KL-divergence, Fisher content, etc.
Conversly, the term ‘optimality criterion’ is usually associated with a minimization problem. Examples include posterior uncertainty; e.g., posterior covariance trace (A-opt), and log-det (D-opt).
instances of ‘Utility’ or its alias OptimalityCriterion can be used for both maximization and minimization equally. One has to be only aware of the difference and how the utility/criterion is developed.
- abstract evaluate(*args, **kwargs)[source]#
Evaluate the utility function / optimality criterion at the given point(s). Typically
*args
will just be \(\zeta\) (the design variable) and**kwargs
will be empty. However, some utility functions may require additional, hence the abstract interface is left open.
- class CriterionConfigs(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_')[source]#
Bases:
PyOEDConfigs
Configuration class for utility functions / optimality criteria. There are no default configurations at this stage.
- Parameters:
verbose (bool) – a boolean flag to control verbosity of the object.
debug (bool) – a boolean flag that enables adding extra functionlity in a debug mode
output_dir (str | Path) – the base directory where the output files will be saved.
- __init__(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_')#
- class InversionCriterion(configs=None)[source]#
Bases:
Criterion
Class for utility functions / optimality criteria defined for inverse problems. This class is a subclass of
Criterion
and thus inherits all its methods and attributes. In addition, it provides a method to to check/update the current linearization point.Note
A linearization point is the point at which the model is linearized (if nonlinear) to construct a Laplacian approximation of the posterior.
- __init__(configs=None)[source]#
Constructor for inversion utility functions / optimality criteria.
- Parameters:
configs (dict) – Object holding configurations for the criterion.
- validate_configurations(configs, raise_for_invalid=True)[source]#
Each simulation model MUST implement it’s own function that validates its own configurations. If the validation is self contained (validates all configuations), then that’s it. However, one can just validate the configurations of of the immediate class and call super to validate configurations associated with the parent class.
If one does not wish to do any validation (we strongly advise against that), simply add the signature of this function to the model class.
Note
The purposed of this method is to make sure that the settings in the configurations object self._CONFIGURATIONS are of the right type/values and are conformable with each other. This function is called upon instantiation of the object, and each time a configuration value is updated. Thus, this function need to be inexpensive and should not do heavy computations.
- Parameters:
configs (dict | InversionCriterionConfigs) – configurations to validate. If a PyOEDConfigs object is passed, validation is performed on the entire set of configurations. However, if a dictionary is passed, validation is performed only on the configurations corresponding to the keys in the dictionary.
- Raises:
PyOEDConfigsValidationError – if the configurations are invalid and raise_for_invalid is set to True.
AttributeError – if any (or a group) of the configurations does not exist in the model configurations
PyOEDConfigs
.
- update_configurations(**kwargs)[source]#
Take any set of keyword arguments, and lookup each in the configurations object, and update the values accordingly.
Note
This method is elementary and does not do any type of casting. If the user want to do any processing on the data, this method need to be overriden with custom implementation.
Warning
This method can be only called after the PyOEDObject is fully instantiated. Thus, it cannot be called withing __init__ method of the PyOED object.
- update_linearization(design=None, linearization_point=None)[source]#
Update the point at which Gaussian approximation (linearization) is taken. This is carried out (if no linearization point is passed) by solving the inverse problem for maximum a posterior (MAP) estimate. Note that is needed only if the problem is nonlinear, thus this method should be called only if the problem is nonlinear, otherwise, evaluating MAP estimate is unnecessary.
- Parameters:
design – an observational design conformable with the observation models. Default is None.
linearization_point – If passed, this is used as the linearization point. Default is None.
- Returns:
the resulting linearization point (MAP estimate if computed).
- Return type:
ndarray
Note
If the the design is None it is set to the current design associated with the OED problem self.design. If`linearization_point` is None, the inverse problem is solved (after setting the design of the OED problem to design), and the MAP estiamte is set as the linearization point
- check_linearization(design)[source]#
Check availability of linearization point if needed for evaluation of the utility function. If the problem is linear, the linearization point is not required and this method returns None. If the problem is nonlinear, and the tracked design is different from the passed one, a new linearization point is computed and returned.
- Parameters:
design – an observational design vector conformable with the observation.
- Returns:
the map estimate (linearization point)
- Return type:
ndarray | None
- property configurations: InversionCriterionConfigs#
- property linearization: Linearization#
Return the linearization data
- property lp_behavior: LP_Behavior#
Return the linearization point behavior
- property oed_problem#
Return the underlying OED problem
- class InversionCriterionConfigs(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', oed_problem=None, lp_behavior=LP_Behavior.MAP)[source]#
Bases:
CriterionConfigs
Configuration class for inversion utility functions / optimality criteria.
- Parameters:
verbose (bool) – a boolean flag to control verbosity of the object.
debug (bool) – a boolean flag that enables adding extra functionlity in a debug mode
output_dir (str | Path) – the base directory where the output files will be saved.
oed_problem (InversionOED | None) – OED problem for which the utility function is defined. This must be an instance of
InversionOED
.lp_behavior (LP_Behavior | str) – behavior of the linearization point (MAP, prior, manual). By default, it is set to MAP. However, if the oed problem is linear, the passed parameter is ignored and is changed to LINEAR instead. If you wish to forcefully choose the linearization point despite the linearity of the problem, set the field after instantiation.
- oed_problem: InversionOED | None#
- lp_behavior: LP_Behavior | str#
- __init__(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', oed_problem=None, lp_behavior=LP_Behavior.MAP)#
- class InversionOED(configs=None)[source]#
Bases:
OED
The main class for all implementations of OED for Inverse Problems (Bayesian of not). This class requires an inverse problem, an optimality criterion, and (optional) regularization term to configure the underlying OED optimization problem.
Note
The experimental design here is abstract and is only dectated by how the optimality criterion is defined. Thus, InversionOED is a generic class in which one can choose different experimental design.
- ..note::
This class can be inherited and:
update the
update_design()
definition to define an experimental design of any nature.Implement
solve()
method to solve the OED problem.
All other functionality is not restricted to a specific type of design.
Warning
This class is very much gradual by construction, we will continue to change and improve.
- Parameters:
configs (dict | OEDConfigs | None) – (optional) configurations for the inversion OED object.
- Raises:
PyOEDConfigsValidationError – if passed invalid configs
- validate_configurations(configs, raise_for_invalid=True)[source]#
Validate the passed configurations object.
- Parameters:
configs (dict | OEDConfigs) – configurations to validate. If a
OEDConfigs
object is passed, validation is performed on the entire set of configurations. However, if a dictionary is passed, validation is performed only on the configurations corresponding to the keys in the dictionary.- Raises:
PyOEDConfigsValidationError – if the configurations are invalid and raise_for_invalid is set to True.
AttributeError – if any (or a group) of the configurations does not exist in the optimizer configurations
OEDConfigs
.
- update_configurations(**kwargs)[source]#
Take any set of keyword arguments, and lookup each in the configurations, and update as nessesary/possible/valid
- Raises:
PyOEDConfigsValidationError – if invalid configurations passed
- register_penalty_term(penalty_function=None, penalty_function_gradient=None, penalty_weight=None)[source]#
Validate and set (in the configurations) the elements of the penalty term in the OED optimizaiton objective. These are (penalty function, the gradient of the penalty function, and regularization parameter)
- ..note::
This method does the following:
Transform the input to standardized formats/types. The penalty function and its gradient are assured to be callables, and the penalty weight is a float.
Update the underlying configurations self.configurations object
Return the standardized forms of the input.
- ..note::
This method checks that the passed combination is compatible with each others and with the settings/configuration of this OED object. If the penalty_function is None, it is set to a zero-valued lambda function. If the penalty_function_gradient is None, it is calculated by using finite differences if called. If penalty_function is None the gradient penalty_function_gradient is set to a zero-valued delta function. If the penalty_weight is None, it is set to 0.
- Parameters:
penalty_function (None | Callable) – function to evaluate the regularization/sparsification penalty (soft constraint)
penalty_function_gradient (None | Callable) – gradient of the penalty function.
penalty_weight (None | float) – scalar penalty/regularization
- Returns:
standardized version of the passed arguments - penalty_function: callable - penalty_function_gradient: callable - penalty_weight: float
- Raises:
TypeError – if any of the passed arguments is of the wrong type
- Return type:
None
- solve_inverse_problem(init_guess=None, skip_map_estimate=False, update_posterior=False)[source]#
Solve the underlying inverse problem, i.e., find the analysis state given the registered observation and prior information.
Note
This is a wrapper of (with the same signature as) the solve_inverse_problem method of the underlying inverse problem. This interface increments the counter _PROBLEM_NUM_SOLVES which keeps track of number of time the inverse problem is solved.
- Parameters:
init_guess – initial state/guess of the model state/parameter; if not passed (i.e., None), the solution starts at the prior mean as the initial guess
bounds – None or valid interval bounds to pass to the optimization routine
skip_map_estimate (bool) – use the prior mean as a map estimte (ignore observations) and upate posterior. This useful for OED when the model is linear
update_posterior (bool) – if True, the posterior mean and covariance operator are updated (given/around the solution of the inverse problem)
- Returns:
the analysis state (MAP estimate of the posterior)
- Raises:
TypeError if any of the 4D-Var elements (model, observation operator, prior, solver, or data) is missing
ValueError if the underlying optimization routine is not supported yet
- objective_function_value(design)[source]#
Evaluate the value of the OED objective function given the passed experimental design The objective function is defined as follows:
\[\mathcal{J}(d) = \mathcal{U}(d) + \alpha \Phi(d)\]where the objective function :math:mathcal{J}`` is a real-valued function composed of \(\mathcal{U}\) is the registered optimality criterion (utility function), \(\Phi\) is the real-valued penalty function (e.g., sparsity promoting function), \(\alpha\) is the penalty parameter.
Note
The experimental design here is abstract and is only dectated by how the optimality criterion is defined.
- Parameters:
design – an experimental design to evaluate the objectiv function at.
- Returns:
value of the registered OED optimality criterion
- Raises:
TypeError is raised if no optimality criterion has been registered yet
- solve(init_guess=None)[source]#
Start solving the OED optimization problem. This methods SHOULD be overridden by child derived classes with additional functionality. Here, the registered optimizer is inspected and is used to solve the optimization problem (if registered.)
- Parameters:
init_guess – The initial guess of the design to be used as starting point of the optimization routine
- Returns:
an instance of (derived from)
InversionOEDResults
holding results obtained by solving the OED problem- Raises:
TypeError – if no valid optimizer is registered
- plot_results(results, overwrite=False, bruteforce=False, show_legend=True, output_dir=None, keep_plots=False, fontsize=20, line_width=2, usetex=True, show_axis_grids=True, axis_grids_alpha=(0.25, 0.4), plots_format='pdf', **kwargs)[source]#
Plot results of solving the OED optimization problem. This function calls super’s plotter (which calls the optimizer plotter), and then attempts to use the inverse problem to plot domain, observations, etc.
The signature of this method is identical to that of the OED’s base class method
pyoed.oed.OED.plot_results()
.
- property inverse_problem#
- property problem_is_linear#
A flag that identifies linearity of the OED problem by checking linearity of the inverse problem
- property number_of_forward_solves#
Number of forward solves (simulation + observation) applied so far
- property penalty_function#
Give access to the underlying inverse problem
- property penalty_function_gradient#
Give access to the underlying inverse problem
- property penalty_weight#
Give access to the underlying inverse problem
- property design_size#
Design size; e.g., number of candidate sensor locations
- class InversionOEDConfigs(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name=None, design=None, optimizer=None, optimizer_configs=None, criterion=None, inverse_problem=None, problem_is_linear=None, penalty_function=None, penalty_function_gradient=None, penalty_weight=0.0)[source]#
Bases:
OEDConfigs
Configurations class for the
InversionOED
class. This class inherits functionality fromOEDConfigs
and only adds new class-level variables which can be updated as needed.See
OEDConfigs
for more details on the functionality of this class along with a few additional fields. OtherwiseInversionOEDConfigs
provides the following fields:- Parameters:
verbose (bool) – a boolean flag to control verbosity of the object.
debug (bool) – a boolean flag that enables adding extra functionlity in a debug mode
output_dir (str | Path) – the base directory where the output files will be saved.
name (str | None) – name of the OED approach/method.
optimizer (None | Optimizer | Type[Optimizer]) –
the optimization routine (optimizer) to be registered and later used for solving the OED problem. This can be one of the following:
None: In this case, no optimizer is registered, and the
solve()
won’t be functional until an optimization routine is registered.An optimizer instance (object that inherits :py:class`Optimizer`). In this case, the optimizer is registered as is and is updated with the passed configurations if available.
The class (subclass of
Optimizer
) to be used to instantiate the optimizer.
optimizer_configs (None | dict | OptimizerConfigs | Type[OptimizerConfigs]) –
the configurations of the optimization routine. This can be one of the following:
None, in this case configurations are discarded, and whatever default configurations of the selected/passed optimizer are employed.
A dict holding full/partial configurations of the selected optimizer. These are either used to instantiate or update the optimizer configurations based on the type of the passed optimizer.
A class providing implementations of the configurations (this must be a subclass of
OptimizerConfigs
.An instance of a subclass of
OptimizerConfigs
which is to set/udpate optimizer configurations.
inverse_problem (InverseProblem | None) –
an instance of an inverse problem
InverseProblem
. This can be a filter or a smoother object with access to underlying properties/methods/attributes of the inverse problems:prior
posterior
solve_inverse_problem()
observation_operator
observation_error_model
problem_is_linear (bool | None) –
a flag that defines how to regard the inverse problem, and consequently the OED problem. The following values are accepted:
If not set (None is passed), it will be detected by testing the linearity of the inverse problem upon instantiation.
If set to True, the underlying forward problem (both simulation model and observation operator) are linear. In this case, the posterior is Gaussian, and the posterior uncertainties (covariances) are independent from the data. Thus, the inverse problem is solved once to find the MAP point (posterior mean/mode), and the posterior covariance is defined/constructed. Note that finding the MAP point is not necessary since posterior covariances are independent from it.
If ‘False’, either the simulation model, the observation operator or both are nonlinear; In this case, the posterior is non-Gaussian, and the posterior uncertainties (covariances) are dependent on the data (through the MAP estimate). To deal with this situation, we follow one of two approaches:
The inverse problem is solved to find the MAP point (posterior mean/mode), approximate the posterior covariance (assuming a Gaussian) around the MAP, find an optimal design, and repeat.
Use KL-divergence between prior and posterior using MC estimate of KL.
criterion (None | str | Criterion) –
The optimality criterion to be optimized when solving the OED problem. This overrides the criterion in the base OED class with additional type. Specifically, this can be:
None; in this case, no criterion will be associated with the inversion OED instance (the object) upon instantiation. Thus, OED criterion association is lazy, and the user is allowed to assign the criterion after creating the inversion OED object by calling
register_optimality_criterion()
.an instance of
Criterion
which provides access to an evaluate method which evaluates the value of the optimality criterion.a string holding the name of the optimality criterion (if widely popular and implemented by PyOED). For more about passing string representation of the criterion, check the documentation of
register_optimality_criterion()
penalty_function (None | Callable) – function to evaluate the regularization/sparsification penalty (soft constraint) in the popular regularized OED optimization formulation.
penalty_function_gradient (None | Callable) – gradient/derivative of the penalty_function with respect to the design. For example, this is used for the relaxation approach where a binary design is allowed to take values in the continuous interval
[0, 1]
.penalty_weight (None | float) –
scalar penalty/regularization parameter multiplied by the penalty_function in the objective function.
Note
The OED optimization objective function is defined as the sum of optimality criterion plus a regularization term. The regularization term is the product of a penalty function with a pnalty weight.
- inverse_problem: InverseProblem | None#
- problem_is_linear: bool | None#
- penalty_function: None | Callable#
- penalty_function_gradient: None | Callable#
- penalty_weight: None | float#
- __init__(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name=None, design=None, optimizer=None, optimizer_configs=None, criterion=None, inverse_problem=None, problem_is_linear=None, penalty_function=None, penalty_function_gradient=None, penalty_weight=0.0)#
- class InversionOEDResults(*, oed_problem=None, optimization_results=None)[source]#
Bases:
OEDResults
An implementation for an object to properly store OED results. In addition to parameters/attributes in
OEDResults
, this class provides the following attributes:- Parameters:
optimization_results (Type[OptimizerResults] | None) – the results object returned from calling the optimizer.
oed_problem (Type[InversionOED] | None) – instance of a class derived from
OED
, such asInversionOED
- __init__(*, oed_problem=None, optimization_results=None)#
- InversionUtility#
alias of
InversionCriterion
- InversionUtilityConfigs#
alias of
InversionCriterionConfigs
- class LP_Behavior(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]#
Bases:
StrEnum
- LINEAR = '\\Alinear\\Z'#
- MANUAL = '\\Amanual\\Z'#
- MAP = '\\Amap\\Z'#
- PRIOR = '\\Aprior\\Z'#
- class Linearization(*, point=None, design=None)[source]#
Bases:
PyOEDData
Data class for linearization point (MAP estimate) and its corresponding design.
- Parameters:
linearization_point – MAP estimate (linearization point) of the posterior.
design (ndarray | None) – design vector corresponding to the linearization point.
- point: ndarray | None#
- design: ndarray | None#
- __init__(*, point=None, design=None)#
- class OED(configs=None)[source]#
Bases:
PyOEDObject
Base class for implementations of OED (Optimal Experimental Design) methods/approaches.
- Parameters:
configs (dict | OEDConfigs | None) – (optional) configurations for the optimization object
- Raises:
PyOEDConfigsValidationError – if passed invalid configs
- validate_configurations(configs, raise_for_invalid=True)[source]#
Each simulation optimizer SHOULD implement it’s own function that validates its own configurations. If the validation is self contained (validates all configuations), then that’s it. However, one can just validate the configurations of of the immediate class and call super to validate configurations associated with the parent class.
If one does not wish to do any validation (we strongly advise against that), simply add the signature of this function to the optimizer class.
Note
The purpose of this method is to make sure that the settings in the configurations object self._CONFIGURATIONS are of the right type/values and are conformable with each other. This function is called upon instantiation of the object, and each time a configuration value is updated. Thus, this function need to be inexpensive and should not do heavy computations.
- Parameters:
configs (dict | OEDConfigs) – configurations to validate. If a
OEDConfigs
object is passed, validation is performed on the entire set of configurations. However, if a dictionary is passed, validation is performed only on the configurations corresponding to the keys in the dictionary.- Raises:
PyOEDConfigsValidationError – if the configurations are invalid and raise_for_invalid is set to True.
AttributeError – if any (or a group) of the configurations does not exist in the optimizer configurations
OEDConfigs
.
- update_configurations(**kwargs)[source]#
Take any set of keyword arguments, and lookup each in the configurations, and update as nessesary/possible/valid
- Raises:
PyOEDConfigsValidationError – if invalid configurations passed
- register_optimality_criterion(criterion=None)[source]#
Validate and set the OED optimality criterion as described by criterion, update the configurations object with the criterion, and return the new criterion.
- Parameters:
criterion (Criterion | None) – This can be an instance that inherits from the base class
Criterion
and implements the methodCriterion.evaluate()
(or at-least duck-types it); or a string that describes a well-known optimality criterion. Users can use the implementations provided in the moduleutility_functions
or implement their own. If criterion is None, no criterion is created. It is left as None.
- ..note::
We allow criterion to be None initially since some optimality criteria implementations take an OED problem object as one of their configurations. This requires creating an OED problem first, and then creating the criterion and attaching it to the OED problem. Though, solving the OED problem won’t be possible without a valid criterion.
- ..note::
This method should be replaced with specific implementations (in derived classes) where the criterion is created and managed by the specific OED paradigm. In that case, more flexibility can be granted, such as passing string representation of the criterion.
- Reutrns:
the registered criterion
- Raises:
TypeError – If criterion is not a valid input.
- register_optimizer(optimizer=None)[source]#
Register (and return) the passed optimizer.
Note
This method does not create a new optimizer instance. It just takes the created optimizer, makes sure it is an instance derived from the
pyoed.optimization.Optimizer
and associates it with this assimilation (DA) object.Note
A derived class is expected to create this optimizer, and pass it up by calling super().register_optimizer(optimizer) so that it can be registered properly.
- Returns:
the registered optimizer.
- Raises:
TypeError – if the type of passed optimizer is not supported
- Return type:
None | Optimizer
- is_valid_design(design)[source]#
Check if the passed design is valid. This method is provided to check whether the passed design has the right type/shape. This is important for validation. Here, no validation is really carried out. This method should overriden with proper validation/check of the passed design.
- Parameters:
design – a data structure containing the proposed experimental design.
- Returns:
True/False indicating whether design should be accepted as a design or not.
- Return type:
bool
- update_design(design)[source]#
Update the experimental design based on the passed design value. This method takes a new experimental design, validates its type/shape/… by calling
is_valid_design()
and then update references to that design. This method does not apply the design to the components of the OED problem as each design is different in nature and applies to the OED problem based on the specific type of the OED problem at hand. Of course this is problem specific.Note
This method is expected to be called by derived classes at the end of the implementation of the overriding method. The driven method provides specific implementation of the effect of the design on the components of the OED problem. For example, sensor placement OED problems apply the design to the observtion operator and/or the observation error model.
In Bayesian inversion, and observational experimental design can change the observaiton vector, the observation operator, the parameter-to-observable-map, and/or the observation error covariance/precision matrix.
Note
This method udpates the design configurations so that proper access to aexperimental design is always guaranteed.
- Parameters:
design – the new experimental design.
- Returns:
the passed design is returned
- Raises:
TypeError – if the design validation failes (i.e., the passed design is invalid)
- design_manager(design)[source]#
Creat an return a context manager that enables updating the design to the passed value, execute needed code and then reset the design to the original value.
Assuming obj is this object, and val is the passed design value, one wants to run the method obj.run_code(), the following code can be used
with obj.design_manager(val) as mngr: mngr.run_code()
- Returns:
a reference to self that enables calling any function under self and then automatically after executing the code, the design is reset.
- Raises:
TypeError – if the passed design is invalid (i.e., didn’t pass
validate_design()
).
- objective_function_value(*args, **kwargs)[source]#
Evaluate the value of the OED objective function given the passed arguments, and given the underlying configurations.
- oed_objective(*args, **kwargs)[source]#
Evaluate the value of the OED objective function given the passed arguments, and given the underlying configurations.
Warning
This method is added for backward compatibility, and it will be deprecated soon. User need to call
objective_function_value()
instead.
- plot_results(results, *args, **kwargs)[source]#
Generic plotting function for OED problems. Given the results returned by
solve()
, visualize the results. Additional plotters can be added to this method or derived methods…- Raises:
TypeError – if no valid optimizer is registered
- solve_oed_problem(*args, **kwargs)[source]#
Start solving the OED problem for the registered configuration with passed arguments.
Warning
This method is added for backward compatibility, and it will be deprecated soon. User need to call
solve()
instead.
- solve(init_guess=None)[source]#
Start solving the OED optimization problem.
Note
This method needs to be replicated (rewritten) for any OED object so that it can replace the returned results object with teh appropriate one.
- Parameters:
init_guess – The initial guess of the design to be used as starting point of the optimization routine
- Returns:
an instance of (derived from) OEDResults holding results obtained by solving the OED problem
- Raises:
TypeError – if no valid optimizer is registered
- property optimizer#
Handle to the optimizer (optimization object) that solves the robust optimization problem
- property oed_criterion#
The OED optimality criterion
- property design#
Return the underlying design
- property design_size#
The dimension of the design space. Generally speaking, this should return the length/size of the design vector. Once can create a design vector then return its length, but the size should inferable without need to create a design vector.
- class OEDConfigs(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name=None, design=None, optimizer=None, optimizer_configs=None, criterion=None)[source]#
Bases:
PyOEDConfigs
Configurations class for the
OED
abstract base class. This class inherits functionality fromPyOEDConfigs
and only adds new class-level variables which can be updated as needed.See
PyOEDConfigs
for more details on the functionality of this class along with a few additional fields. OtherwiseOEDConfigs
provides the following fields:- Parameters:
verbose (bool) – a boolean flag to control verbosity of the object.
debug (bool) – a boolean flag that enables adding extra functionlity in a debug mode
output_dir (str | Path) – the base directory where the output files will be saved.
name (str | None) – name of the OED approach/method.
optimizer (None | Optimizer | Type[Optimizer]) –
the optimization routine (optimizer) to be registered and later used for solving the OED problem. This can be one of the following:
None: In this case, no optimizer is registered, and the
solve()
won’t be functional until an optimization routine is registered.An optimizer instance (object that inherits :py:class`Optimizer`). In this case, the optimizer is registered as is and is updated with the passed configurations if available.
The class (subclass of
Optimizer
) to be used to instantiate the optimizer.
optimizer_configs (None | dict | OptimizerConfigs | Type[OptimizerConfigs]) –
the configurations of the optimization routine. This can be one of the following:
None, in this case configurations are discarded, and whatever default configurations of the selected/passed optimizer are employed.
A dict holding full/partial configurations of the selected optimizer. These are either used to instantiate or update the optimizer configurations based on the type of the passed optimizer.
A class providing implementations of the configurations (this must be a subclass of
OptimizerConfigs
.An instance of a subclass of
OptimizerConfigs
which is to set/udpate optimizer configurations.
criterion (None | str | Criterion) –
The optimality criterion to be optimized when solving the OED problem. This can be:
None; in this case, no criterion will be associated with the inversion OED instance (the object) upon instantiation. Thus, OED criterion association is lazy, and the user is allowed to assign the criterion after creating the inversion OED object by calling
register_optimality_criterion()
.an instance of
Criterion
which provides access to an evaluate method which evaluates the value of the optimality criterion.
- name: str | None#
- design: None | Iterable#
- optimizer_configs: None | dict | OptimizerConfigs | Type[OptimizerConfigs]#
- __init__(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name=None, design=None, optimizer=None, optimizer_configs=None, criterion=None)#
- class OEDResults(*, oed_problem=None, optimization_results=None)[source]#
Bases:
PyOEDData
Base class to hold OED data/results
- Parameters:
optimization_results (Type[OptimizerResults] | None) – the results object returned from calling the optimizer.
oed_problem (Type[OED] | None) – instance of a class derived from
OED
, such asInversionOED
- optimization_results: Type[OptimizerResults] | None#
- data_dictionary()[source]#
Return a dictionary containing picklable results without class dependencies
Warning
This method is added for backward compatibility, and it will be deprecated soon. User need to call
asdict()
instead.
- write_results(saveto)[source]#
Save the underlying OED results to pickled dictionary.
Warning
This is a very elementary class method that requires all object attributes to be serializable (picklable). Each specific derived class should provide a more tailored implementation.
- Parameters:
saveto – name/path of the file to save data to.
- Raises:
TypeError – if saveto is not a valid file path
IOError – if writing failed
- __init__(*, oed_problem=None, optimization_results=None)#
- property optimal_design#
A copy of the optimal design extracted from the optimization results object
- classmethod load_results(readfrom)[source]#
Inspect pickled file, and load OED results;
Warning
This is a very elementary class method that requires all object attributes to be serializable (picklable). Each specific derived class should provide a more tailored implementation.
- Raises:
IOError – if loading failed
- class RobustInversionOED(configs=None)[source]#
Bases:
InversionOED
Base class for robust OED for inverse problems.
- class RobustInversionOEDConfigs(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name=None, design=None, optimizer=None, optimizer_configs=None, criterion=None, inverse_problem=None, problem_is_linear=None, penalty_function=None, penalty_function_gradient=None, penalty_weight=0.0)[source]#
Bases:
InversionOEDConfigs
Configurations class for the
RobustInversionOED
class. This class inherits functionality fromInversionOEDConfigs
and only adds new class-level variables which can be updated as needed.- Parameters:
verbose (bool) – a boolean flag to control verbosity of the object.
debug (bool) – a boolean flag that enables adding extra functionlity in a debug mode
output_dir (str | Path) – the base directory where the output files will be saved.
name (str | None) – name of the OED approach/method.
optimizer (None | Optimizer | Type[Optimizer]) –
the optimization routine (optimizer) to be registered and later used for solving the OED problem. This can be one of the following:
None: In this case, no optimizer is registered, and the
solve()
won’t be functional until an optimization routine is registered.An optimizer instance (object that inherits :py:class`Optimizer`). In this case, the optimizer is registered as is and is updated with the passed configurations if available.
The class (subclass of
Optimizer
) to be used to instantiate the optimizer.
optimizer_configs (None | dict | OptimizerConfigs | Type[OptimizerConfigs]) –
the configurations of the optimization routine. This can be one of the following:
None, in this case configurations are discarded, and whatever default configurations of the selected/passed optimizer are employed.
A dict holding full/partial configurations of the selected optimizer. These are either used to instantiate or update the optimizer configurations based on the type of the passed optimizer.
A class providing implementations of the configurations (this must be a subclass of
OptimizerConfigs
.An instance of a subclass of
OptimizerConfigs
which is to set/udpate optimizer configurations.
inverse_problem (InverseProblem | None) –
an instance of an inverse problem
InverseProblem
. This can be a filter or a smoother object with access to underlying properties/methods/attributes of the inverse problems:prior
posterior
solve_inverse_problem()
observation_operator
observation_error_model
problem_is_linear (bool | None) –
a flag that defines how to regard the inverse problem, and consequently the OED problem. The following values are accepted:
If not set (None is passed), it will be detected by testing the linearity of the inverse problem upon instantiation.
If set to True, the underlying forward problem (both simulation model and observation operator) are linear. In this case, the posterior is Gaussian, and the posterior uncertainties (covariances) are independent from the data. Thus, the inverse problem is solved once to find the MAP point (posterior mean/mode), and the posterior covariance is defined/constructed. Note that finding the MAP point is not necessary since posterior covariances are independent from it.
If ‘False’, either the simulation model, the observation operator or both are nonlinear; In this case, the posterior is non-Gaussian, and the posterior uncertainties (covariances) are dependent on the data (through the MAP estimate). To deal with this situation, we follow one of two approaches:
The inverse problem is solved to find the MAP point (posterior mean/mode), approximate the posterior covariance (assuming a Gaussian) around the MAP, find an optimal design, and repeat.
Use KL-divergence between prior and posterior using MC estimate of KL.
criterion (None | str | Criterion) –
The optimality criterion to be optimized when solving the OED problem. This overrides the criterion in the base OED class with additional type. Specifically, this can be:
None; in this case, no criterion will be associated with the inversion OED instance (the object) upon instantiation. Thus, OED criterion association is lazy, and the user is allowed to assign the criterion after creating the inversion OED object by calling
register_optimality_criterion()
.an instance of
Criterion
which provides access to an evaluate method which evaluates the value of the optimality criterion.a string holding the name of the optimality criterion (if widely popular and implemented by PyOED). For more about passing string representation of the criterion, check the documentation of
register_optimality_criterion()
penalty_function (None | Callable) – function to evaluate the regularization/sparsification penalty (soft constraint) in the popular regularized OED optimization formulation.
penalty_function_gradient (None | Callable) – gradient/derivative of the penalty_function with respect to the design. For example, this is used for the relaxation approach where a binary design is allowed to take values in the continuous interval
[0, 1]
.penalty_weight (None | float) –
scalar penalty/regularization parameter multiplied by the penalty_function in the objective function.
Note
The OED optimization objective function is defined as the sum of optimality criterion plus a regularization term. The regularization term is the product of a penalty function with a pnalty weight.
- __init__(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name=None, design=None, optimizer=None, optimizer_configs=None, criterion=None, inverse_problem=None, problem_is_linear=None, penalty_function=None, penalty_function_gradient=None, penalty_weight=0.0)#
- class RobustInversionOEDResults(*, oed_problem=None, optimization_results=None)[source]#
Bases:
InversionOEDResults
Base class for objects holding results of
RobustInversionOED
- Parameters:
optimization_results (Type[OptimizerResults] | None) – the results object returned from calling the optimizer.
oed_problem (Type[InversionOED] | None) – instance of a class derived from
OED
, such asInversionOED
- __init__(*, oed_problem=None, optimization_results=None)#
- class RobustOEDConfigs(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name=None, design=None, optimizer=None, optimizer_configs=None, criterion=None)[source]#
Bases:
OEDConfigs
Configurations class for the
RobustOED
class. This class inherits functionality fromOEDConfigs
and only adds new class-level variables which can be updated as needed.- Parameters:
verbose (bool) – a boolean flag to control verbosity of the object.
debug (bool) – a boolean flag that enables adding extra functionlity in a debug mode
output_dir (str | Path) – the base directory where the output files will be saved.
name (str | None) – name of the OED approach/method.
optimizer (None | Optimizer | Type[Optimizer]) –
the optimization routine (optimizer) to be registered and later used for solving the OED problem. This can be one of the following:
None: In this case, no optimizer is registered, and the
solve()
won’t be functional until an optimization routine is registered.An optimizer instance (object that inherits :py:class`Optimizer`). In this case, the optimizer is registered as is and is updated with the passed configurations if available.
The class (subclass of
Optimizer
) to be used to instantiate the optimizer.
optimizer_configs (None | dict | OptimizerConfigs | Type[OptimizerConfigs]) –
the configurations of the optimization routine. This can be one of the following:
None, in this case configurations are discarded, and whatever default configurations of the selected/passed optimizer are employed.
A dict holding full/partial configurations of the selected optimizer. These are either used to instantiate or update the optimizer configurations based on the type of the passed optimizer.
A class providing implementations of the configurations (this must be a subclass of
OptimizerConfigs
.An instance of a subclass of
OptimizerConfigs
which is to set/udpate optimizer configurations.
criterion (None | str | Criterion) –
The optimality criterion to be optimized when solving the OED problem. This can be:
None; in this case, no criterion will be associated with the inversion OED instance (the object) upon instantiation. Thus, OED criterion association is lazy, and the user is allowed to assign the criterion after creating the inversion OED object by calling
register_optimality_criterion()
.an instance of
Criterion
which provides access to an evaluate method which evaluates the value of the optimality criterion.
- __init__(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name=None, design=None, optimizer=None, optimizer_configs=None, criterion=None)#
- class RobustOEDResults(*, oed_problem=None, optimization_results=None)[source]#
Bases:
OEDResults
Base class for objects holding results of
RobustOED
- Parameters:
optimization_results (Type[OptimizerResults] | None) – the results object returned from calling the optimizer.
oed_problem (Type[OED] | None) – instance of a class derived from
OED
, such asInversionOED
- __init__(*, oed_problem=None, optimization_results=None)#
- class SensorPlacementInversionOED(configs=None)[source]#
Bases:
InversionOED
Base class for sensor placement OED for inverse problems.
- class SensorPlacementInversionOEDConfigs(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name=None, design=None, optimizer=None, optimizer_configs=None, criterion=None, inverse_problem=None, problem_is_linear=None, penalty_function=None, penalty_function_gradient=None, penalty_weight=0.0)[source]#
Bases:
InversionOEDConfigs
Configurations class for the
SensorPlacementInversionOED
class. This class inherits functionality fromInversionOEDConfigs
and only adds new class-level variables which can be updated as needed.- Parameters:
verbose (bool) – a boolean flag to control verbosity of the object.
debug (bool) – a boolean flag that enables adding extra functionlity in a debug mode
output_dir (str | Path) – the base directory where the output files will be saved.
name (str | None) – name of the OED approach/method.
optimizer (None | Optimizer | Type[Optimizer]) –
the optimization routine (optimizer) to be registered and later used for solving the OED problem. This can be one of the following:
None: In this case, no optimizer is registered, and the
solve()
won’t be functional until an optimization routine is registered.An optimizer instance (object that inherits :py:class`Optimizer`). In this case, the optimizer is registered as is and is updated with the passed configurations if available.
The class (subclass of
Optimizer
) to be used to instantiate the optimizer.
optimizer_configs (None | dict | OptimizerConfigs | Type[OptimizerConfigs]) –
the configurations of the optimization routine. This can be one of the following:
None, in this case configurations are discarded, and whatever default configurations of the selected/passed optimizer are employed.
A dict holding full/partial configurations of the selected optimizer. These are either used to instantiate or update the optimizer configurations based on the type of the passed optimizer.
A class providing implementations of the configurations (this must be a subclass of
OptimizerConfigs
.An instance of a subclass of
OptimizerConfigs
which is to set/udpate optimizer configurations.
inverse_problem (InverseProblem | None) –
an instance of an inverse problem
InverseProblem
. This can be a filter or a smoother object with access to underlying properties/methods/attributes of the inverse problems:prior
posterior
solve_inverse_problem()
observation_operator
observation_error_model
problem_is_linear (bool | None) –
a flag that defines how to regard the inverse problem, and consequently the OED problem. The following values are accepted:
If not set (None is passed), it will be detected by testing the linearity of the inverse problem upon instantiation.
If set to True, the underlying forward problem (both simulation model and observation operator) are linear. In this case, the posterior is Gaussian, and the posterior uncertainties (covariances) are independent from the data. Thus, the inverse problem is solved once to find the MAP point (posterior mean/mode), and the posterior covariance is defined/constructed. Note that finding the MAP point is not necessary since posterior covariances are independent from it.
If ‘False’, either the simulation model, the observation operator or both are nonlinear; In this case, the posterior is non-Gaussian, and the posterior uncertainties (covariances) are dependent on the data (through the MAP estimate). To deal with this situation, we follow one of two approaches:
The inverse problem is solved to find the MAP point (posterior mean/mode), approximate the posterior covariance (assuming a Gaussian) around the MAP, find an optimal design, and repeat.
Use KL-divergence between prior and posterior using MC estimate of KL.
criterion (None | str | Criterion) –
The optimality criterion to be optimized when solving the OED problem. This overrides the criterion in the base OED class with additional type. Specifically, this can be:
None; in this case, no criterion will be associated with the inversion OED instance (the object) upon instantiation. Thus, OED criterion association is lazy, and the user is allowed to assign the criterion after creating the inversion OED object by calling
register_optimality_criterion()
.an instance of
Criterion
which provides access to an evaluate method which evaluates the value of the optimality criterion.a string holding the name of the optimality criterion (if widely popular and implemented by PyOED). For more about passing string representation of the criterion, check the documentation of
register_optimality_criterion()
penalty_function (None | Callable) – function to evaluate the regularization/sparsification penalty (soft constraint) in the popular regularized OED optimization formulation.
penalty_function_gradient (None | Callable) – gradient/derivative of the penalty_function with respect to the design. For example, this is used for the relaxation approach where a binary design is allowed to take values in the continuous interval
[0, 1]
.penalty_weight (None | float) –
scalar penalty/regularization parameter multiplied by the penalty_function in the objective function.
Note
The OED optimization objective function is defined as the sum of optimality criterion plus a regularization term. The regularization term is the product of a penalty function with a pnalty weight.
- __init__(*, debug=False, verbose=False, output_dir='./_PYOED_RESULTS_', name=None, design=None, optimizer=None, optimizer_configs=None, criterion=None, inverse_problem=None, problem_is_linear=None, penalty_function=None, penalty_function_gradient=None, penalty_weight=0.0)#
- class SensorPlacementInversionOEDResults(*, oed_problem=None, optimization_results=None)[source]#
Bases:
InversionOEDResults
Base class for objects holding results of
SensorPlacementInversionOED
- Parameters:
optimization_results (Type[OptimizerResults] | None) – the results object returned from calling the optimizer.
oed_problem (Type[InversionOED] | None) – instance of a class derived from
OED
, such asInversionOED
- __init__(*, oed_problem=None, optimization_results=None)#
- class SupportsRelaxedOptimization(*args, **kwargs)[source]#
Bases:
Protocol
Protocol to check if a utility function supports relaxed optimization. To do so, an object must support the method grad_design along with getters/setters for formulation_approach and pcw_scheme. You can use regular python isinstance to check with this protocol.
- property formulation_approach#
- property pcw_scheme#
- __init__(*args, **kwargs)#
- class SupportsRobustOptimization(*args, **kwargs)[source]#
Bases:
Protocol
Protocol to check if a utility function supports robust optimization. To do so, an object must support the method grad_uncertainty.
- __init__(*args, **kwargs)#
- grad_uncertainty(design, uncertain_param, reset_param=False)[source]#
Evaluate the derivative of the utility function with respect to the uncertain parameter. The utility function takes two arguments (design, uncertain_param_val) as its input. The design is fixed, and diferences are calculated over the uncertain parameter.
- Parameters:
design – an observational design vector conformable with the observation.
uncertain_param_val – the value of the uncertain parameter.
- Returns:
The gradient of the utility function criterion with respect to the uncertain parameter.
- Return type:
np.ndarray
- UtilityConfigs#
alias of
CriterionConfigs