pyuncertainnumber.propagation.b2b¶
Functions¶
|
General implementation of interval propagation through a function: |
|
Implementation of endpoints method, a.k.a vertex method. |
|
Implmentation of subinterval method which splits subintervals and reconstitutes later. |
|
a vectorised version of the cartesian product |
|
a vectorisation of the interval cartesian product |
Module Contents¶
- pyuncertainnumber.propagation.b2b.b2b(vars: pyuncertainnumber.pba.intervals.number.Interval | list[pyuncertainnumber.pba.intervals.number.Interval], func: callable, interval_strategy: str = None, subinterval_style: str = None, n_sub: int = None, n_sam: int = 200, **kwargs) pyuncertainnumber.pba.intervals.number.Interval¶
General implementation of interval propagation through a function:
\[Y = g(I_{x1}, I_{x2}, ..., I_{xn})\]where \(I_{x1}, I_{x2}, ..., I_{xn}\) are intervals.
In a general case, the function \(g\) is not necessarily monotonic and \(g\) may be a black-box model. Optimisation to the rescue and two of them particularly: Genetic Algorithm and Bayesian Optimisation.
- Parameters:
vars (Interval | list[Interval]) – a vector Interval or a list or tuple of scalar Intervals, or an EpistemicDomain object, or a scalar Interval;
func (callable) – performance or response function or a black-box model as in subprocess. Expect 2D inputs therefore func shall have the matrix signature. See Notes for additional details.
interval_strategy (str) –
the interval_strategy used for interval propagation. The choice shall be compatible with the response function signature. Seethe notes below for additional details.
’endpoints’: only the endpoints
’ga’: genetic algorithm
’bo’: bayesian optimisation
’direct’: directly apply function to the input intervals (the default)
’subinterval’: apply function to subintervals
’cauchy_deviate’: use the Cauchy Deviate Method for interval propagation
subinterval_style (str) – the subinterval_style only used for subinterval propagation, including {‘’direct’’, ‘’endpoints’’}.
n_sub (int) – number of subintervals, only used for subinterval propagation.
n_sam (int) – number of samples, only used for Cauchy deviate method
**kwargs – additional keyword arguments to be passed to the function, which provides extra control for the algorithm used. For example, for GA, one can pass in ‘algorithm_param’ for BO, one can pass in ‘acquisition_function’, ‘num_iterations’ etc. Typically, one would try the optimisation harder (e.g. more iterations) for a more accurate result.
Tip
This serves as a top-level for generic interval propagation .
Caution
interval_strategysuggests the method of interval propagation (e.g. ‘direct’ or ‘endpoints’, or ‘subinterval’, or ‘ga’, or ‘bo’), whhilesubinterval_styleis only used for ‘subinterval’ propagation. This is to say that what strategy (whether ‘direct’ or ‘endpoints’) will be further chosen for the sub-intervals. For scalar function propagation,varsshuld just be a scalar Interval object rather than a list.Danger
There are some subtleties about the calling signature of the propagating function. For
endpointsstrategy/subinterval_style, the function func should have a vectorised signature as it is expecting a 2D numpy array, whereas for thedirectstrategy/subinterval_style, it is expecting to take individual scalar inputs. It is recommended to write a function which implements both signature, as seen in the example below.- Returns:
the low and upper bound of the response
- Return type:
Example
>>> from pyuncertainnumber import b2b >>> import numpy as np >>> import pyuncertainnumber as pba
>>> # Define a universal function that handles a performance function with both `vectorised` and `iterable` signatures >>> def bar_universal(x): ... if isinstance(x, np.ndarray): # foo_vectorised signature ... if x.ndim == 1: ... x = x[None, :] ... return x[:, 0] ** 3 + x[:, 1] + 5 ... else: ... return x[0] ** 3 + x[1] + 5 # foo_iterable signature
>>> # Define input intervals >>> a = pba.I(3., 5.) >>> b = pba.I(6., 26.)
>>> # using the {'endpoints', "direct", ga", "bo"} strategy >>> b2b(vars=[a, b], ... func=bar_universal, ... interval_strategy='endpoints') # replace with {"direct", ga", "bo"}
>>> # using the 'subinterval' strategy >>> b2b(vars=[a, b], ... func=bar_universal, ... interval_strategy='subinterval', ... subinterval_style='endpoints', ... n_sub=2)
>>> # using the 'cauchy_deviate' strategy >>> b2b(vars=[a, b], ... func=bar_universal, ... interval_strategy='cauchy_deviate', ... n_sam=1000)
>>> # in comparison, one can compare with the result of interval arithmetic >>> def bar_individual(x1, x2): ... return x1 ** 3 + x2 + 5 # individual signature >>> bar_individual(a, b) [38.0, 156.0]
- pyuncertainnumber.propagation.b2b.endpoints(vec_itvl: pyuncertainnumber.pba.intervals.number.Interval, func) pyuncertainnumber.pba.intervals.number.Interval¶
Implementation of endpoints method, a.k.a vertex method.
- Parameters:
vec_itvl (Interval) – a vector type Interval object
func (callable) – the function to be evaluated. See notes about function signature.
Note
The function func is expected to accept a 2D numpy array of shape \((2^d, d)\) where d is the dimension of the vector interval. Therefore, the function should have a vectorised signature, as opposted to taking individual scalar inputs.
Example
>>> from pyuncertainnumber import pba >>> v = pba.I([1, 2], [3, 4]) # a vector interval with two dimensions >>> def bar(x): return x[:, 0] ** 3 + x[:, 1] + 5 >>> endpoints(v, bar) Interval(8.0, 36.0)
- pyuncertainnumber.propagation.b2b.subinterval_method(vec_itvl: pyuncertainnumber.pba.intervals.number.Interval, func, subinterval_style=None, n_sub=None, parallel=False) pyuncertainnumber.pba.intervals.number.Interval¶
Implmentation of subinterval method which splits subintervals and reconstitutes later.
- Parameters:
vec_itvl (Interval) – a vector type Interval object
func (callable) – the function to be evaluated. See notes about function signature.
n_sub (int) – number of subintervals
subinterval_style (str) –
the subinterval_style used for interval propagation which shall be compatible with the response function signature.
’direct’: direct apply function
’endpoints’: only the endpoints are propagated
Danger
There are some subtleties about function signature. For
endpointssubinterval_style, the function func should have a vectorised signature as it is expecting a 2D numpy array, whereas for the direct subinterval_style, it is expecting to take individual scalar inputsExample
>>> from pyuncertainnumber import pba >>> v = pba.I([1, 2], [3, 4]) >>> def bar(x): return x[0] ** 3 + x[1] + 5 >>> b2b.subinterval_method(vec_itvl=v, func=bar, subinterval_style='direct', n_sub=2) >>> def bar_vec(x): return x[:, 0] ** 3 + x[:, 1] + 5 >>> b2b.subinterval_method(vec_itvl=v, func=bar_vec, subinterval_style='endpoints', n_sub=2)
- pyuncertainnumber.propagation.b2b.vec_cartesian_product(*arrays)¶
a vectorised version of the cartesian product
- Parameters:
arrays – a couple of 1D np.ndarray objects
- pyuncertainnumber.propagation.b2b.i_cartesian_product(a, b)¶
a vectorisation of the interval cartesian product