pyuncertainnumber.propagation.b2b

Functions

b2b(→ pyuncertainnumber.pba.intervals.number.Interval)

General implementation of interval propagation through a function:

endpoints(...)

Implementation of endpoints method, a.k.a vertex method.

subinterval_method(...)

Implmentation of subinterval method which splits subintervals and reconstitutes later.

vec_cartesian_product(*arrays)

a vectorised version of the cartesian product

i_cartesian_product(a, b)

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_strategy suggests the method of interval propagation (e.g. ‘direct’ or ‘endpoints’, or ‘subinterval’, or ‘ga’, or ‘bo’), whhile subinterval_style is 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, vars shuld just be a scalar Interval object rather than a list.

Danger

There are some subtleties about the calling signature of the propagating function. For endpoints strategy/subinterval_style, the function func should have a vectorised signature as it is expecting a 2D numpy array, whereas for the direct strategy/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:

Interval

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 endpoints subinterval_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 inputs

Example

>>> 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