interval analysis¶
import pyuncertainnumber as pun
from pyuncertainnumber import pba
Interval analysis plays a key role in uncertainty quantification, especially regarding the epistemic uncertainty. pyuncertainnumber builds upon a pioneering project Intervals which provides a wide spectrum of low-level calculations, and significantly extend to further provide additional functionalities for such as propagation and optimisation in the presence of epistemic uncertainty. One appealing characteristic of interval analysis is that it provides a rigorous computational environment.
Intervals are typically used to characterise an uncertain varible when only the range is known. No probability distribution (i.e. relative likelihood within this range) can be justified. There are many ways an interval representation can be constructed.
Canonically, an interval is constructed by a lower bound and an upper bound. In addition, pyuncertainnumber provides many more constructors to allow construcutions in intuitive manners.
For example, natural language support allows one to specify an interval as in “[2 +- 10%]”, and linguistic hedges such as “about 7”. See Interpret linguisitc hedges about additional details of linguistic hedges. Moreover, significant digits frequent in engineering analysis also indicate measurement uncertainties and can thus be modelled as intervals as well.
# canonical construction
pun.I(2, 3)
UncertainNumber(essence='interval', intervals=[2.0,3.0], _construct=[2.0,3.0], nominal_value=2.5)
pun.I("[2 +- 10%]")
UncertainNumber(essence='interval', intervals=[1.8,2.2], _construct=[1.8,2.2], nominal_value=2.0)
pun.I("about 7.")
UncertainNumber(essence='interval', intervals=[6.8,7.2], _construct=[6.8,7.2], nominal_value=7.0)
Interval arrays¶
Additional capabilities are provided when working with the pba API. Similar to numpy, high dimentional interval objects (i.e. interval arrays) can be created with ease, and one can get the hint about the interval array i with attributes such as i.scalar, i.ndim, i.shape.
s = pba.I(2,3)
s.scalar
True
v = pba.I(lo=[2., 3., 4.], hi=[7., 8., 9.])
v.ndim
1
v.shape
(3,)
Any array-like structure whose shape is (n,…,2) can be cast to an interval structure.
a = [[[1,2], [2,3], [4,5]],
[[-1,2],[-2,1],[3,5]],
[[0,2], [3,4], [6,8]]]
m = pba.intervalise(a)
print(m)
[1. 2.] [2. 3.] [4. 5.]
[-1. 2.] [-2. 1.] [3. 5.]
[0. 2.] [3. 4.] [6. 8.]
margin-of-error notation¶
Intervals can also be created with the common conception of error bars. Common in scientific computations, a margin of error, in the form of [x +- half_width] is employed as ballpark estimates.
s = pba.I.from_meanform(
x=2, half_width=0.3
)
print(s)
[1.7,2.3]
v = pba.I.from_meanform(
[2, 3, 4], [0.2, 0.3, 0.4]
)
print(v)
[1.8,2.2]
[2.7,3.3]
[3.6,4.4]
**convertion to p-box**
Interval can also be deemed as a p-box whose bounds are unit step functions.
Such conversion can be easily done in pyuncertainnumber
pba.I(2, 3).to_pbox()
Pbox ~ (range=[2.000, 3.000], mean=[2.000, 3.000], var=[0.000, 0.250])
interval propagation¶
Abundant strategies exist for propagating intervals through functions, and it is desired to be acomplished in a rigorous way. See this guide for an overview of such strategies. Besides a high-level API Propagation which allows users to conduct uncertainty propagation whatever the uncertainty representations are, pyuncertainnumber also provides a low-level bespoke function b2b to support such operations with detailed controls.
In some simple cases, one can directly do interval arithmeic calculations intrusively when the function/equation is accessible. Through duck-typing, pyuncertainnumber allows drop-in replacements of uncertain number objects in Python function. But note that interval dependency presents as a critical issue, see Interval dependency for additional details and the take-away message is pyuncertainnumber provide strategies to solve this issue.
See xxx for a realistic engineering example demonstrating uncertainty propagation
def foo(x,y):
return x*3 + y**3
x, y = pba.I(2., 3.), pba.I(4, 5)
foo(x,y)
[70.0,134.0]