Intervals#
- class pba.interval.Interval#
An interval is an uncertain number for which only the endpoints are known, \(x=[a,b]\). This is interpreted as \(x\) being between \(a\) and \(b\) but with no more information about the value of \(x\).
Intervals embody epistemic uncertainty within PBA.
Creation#
Intervals can be created using either of the following:
>>> pba.Interval(0,1) Interval [0,1] >>> pba.I(2,3) Interval [2,3]
Tip
The shorthand
I
is an alias forInterval
Intervals can also be created from a single value ± half-width:
>>> pba.PM(0,1) Interval [-1,1]
By default intervals are displayed as
Interval [a,b]
wherea
andb
are the left and right endpoints respectively. This can be changed using the interval.pm_repr and interval.lr_repr functions.Arithmetic#
For two intervals [a,b] and [c,d] the following arithmetic operations are defined:
Addition
\([a,b] + [c,d] = [a+c,b+d]\)
Subtraction
\([a,b] - [c,d] = [a-d,b-c]\)
Multiplication
\([a,b] * [c,d] = [\min(ac,ad,bc,bd),\max(ac,ad,bc,bd)]\)
Division
\([a,b] / [c,d] = [a,b] * \frac{1}{[c,d]} \equiv [\min(a/c,a/d,b/c,b/d),\max(a/c,a/d,b/c,b/d)]\)
Alternative arithmetic methods are described in interval.add, interval.sub, interval.mul, interval.div.
Attributes:
left
: The left boundary of the interval.right
: The right boundary of the interval.Default values
If only 1 argument is given then the interval is assumed to be zero width around this value.
If no arguments are given then the interval is assumed to be vaccous (i.e. \([-\infty,\infty]\)). This is implemented as
Interval(-np.inf,np.inf)
.- __init__(left=None, right=None)#
Attributes:
left
: The left boundary of the interval.right
: The right boundary of the interval.Default values
If only 1 argument is given then the interval is assumed to be zero width around this value.
If no arguments are given then the interval is assumed to be vaccous (i.e. \([-\infty,\infty]\)). This is implemented as
Interval(-np.inf,np.inf)
.
- add(other, method=None)#
Adds the interval and another object together.
Args:
other
: The interval or numeric value to be added. This value must be transformable into an Interval object.Methods:
p - perfect arithmetic \([a,b]+[c,d] = [a + c, b + d]\)
o - opposite arithmetic \([a,b]+[c,d] = [a + d, b + c]\)
None, i, f - Standard interval arithmetic is used.
Returns:
Interval
- padd(other)#
Warning
This method is deprecated. Use add(other, method=’p’) instead.
- oadd(other)#
Warning
This method is deprecated. Use add(other, method=’o’) instead.
- sub(other, method=None)#
Subtracts other from self.
Args:
other
: The interval or numeric value to be subracted. This value must be transformable into an Interval object.Methods:
p
: perfect arithmetic \(a+b = [a.left - b.left, a.right - b.right]\)o
: opposite arithmetic \(a+b = [a.left - b.right, a.right - b.left]\)None, i, f - Standard interval arithmetic is used.
Returns:
Interval
- psub(other)#
Warning
Depreciated use self.sub(other, method = ‘p’) instead
- osub(other)#
Warning
Depreciated use self.sub(other, method = ‘o’) instead
- mul(other, method=None)#
Multiplies self by other.
Args:
other
: The interval or numeric value to be multiplied. This value must be transformable into an Interval object.- Methods:
p
: perfect arithmetic \([a,b],[c,d] = [a * c, b * d]\)o
: opposite arithmetic \([a,b],[c,d] = [a * d, b * c]\)None, i, f - Standard interval arithmetic is used.
- Returns:
Interval: The result of the multiplication.
- pmul(other)#
Warning
Depreciated use self.mul(other, method = ‘p’) instead
- omul(other)#
Warning
Depreciated use self.mul(other, method = ‘o’) instead
- div(other, method=None)#
Divides self by other
If \(0 \in other\) it returns a division by zero error
Args:
other
(Interval or numeric): The interval or numeric value to be multiplied. This value must be transformable into an Interval object.Methods:
p
: perfect arithmetic \([a,b],[c,d] = [a * 1/c, b * 1/d]\)o
: opposite arithmetic \([a,b],[c,d] = [a * 1/d, b * 1/c]\)None
,i
,f
- Standard interval arithmetic is used.Implementation
>>> self.add(1/other, method = method)
Error
If \(0 \in [a,b]\) it returns a division by zero error
- pdiv(other)#
Warning
Depreciated use self.div(other, method = ‘p’) instead
- odiv(other)#
Warning
Depreciated use self.div(other, method = ‘o’) instead
- recip()#
Calculates the reciprocle of the interval.
Returns:
Interval
: Equal to \([1/b,1/a]\)Example:
>>> pba.Interval(2,4).recip() Interval [0.25, 0.5]
Error
If \(0 \in [a,b]\) it returns a division by zero error
- equiv(other: Interval) bool #
Checks whether two intervals are equivalent.
Parameters:
other
: The interval to check against.Returns
True
if:self.left == other.right
andself.right == other.right
False
otherwise.Error
TypeError
: Ifother
is not an instance ofInterval
See also
is_same_as()
Examples:
>>> a = Interval(0,1) >>> b = Interval(0.5,1.5) >>> c = I(0,1) >>> a.equiv(b) False >>> a.equiv(c) True
- lo()#
- Returns:
self.left
Tip
This function is redundant but exists to match Pbox class for possible internal reasons.
- hi()#
- Returns:
self.right
Tip
This function is redundant but exists to match Pbox class for possible internal reasons.
- width() float #
Returns:
float
: The width of the interval, \(\mathrm{right} - \mathrm{left}\)Example:
>>> pba.Interval(0,3).width() 3
- halfwidth() float #
Returns:
float
: The half-width of the interval, \((\mathrm{right} - \mathrm{left})/2\)Example:
>>> pba.Interval(0,3).halfwidth() 1.5
Implementation
>>> self.width()/2
- midpoint() float #
Returns:
float
: The midpoint of the interval, \((\mathrm{right} + \mathrm{left})/2\)Example:
>>> pba.Interval(0,2).midpoint() 1.0
- to_logical()#
Turns the interval into a logical interval, this is done by chacking the truth value of the ends of the interval
Returns:
Logical
: The logical intervalImplementation
>>> left = self.left.__bool__() >>> right = self.right.__bool__() >>> Logical(left,right)
- env(other: list | Interval) Interval #
Calculates the envelope between two intervals
Parameters:
other
: Interval or list. The interval to envelope with selfHint
If other is a list then the envelope is calculated between self and each element of the list. In this case the envelope is calculated recursively and pba.envelope() may be more efficient.
Important
If other is a Pbox then
Pbox.env()
is calledReturns:
Interval
: The envelope of self and other
- straddles(N: int | float | Interval, endpoints: bool = True) bool #
Parameters:
N
: Number to check. If N is an interval checks whether the whole interval is within self.endpoints
: Whether to include the endpoints within the checkReturns
True
if:\(\mathrm{left} \leq N \leq \mathrm{right}\) (Assuming
endpoints=True
).For interval values. \(\mathrm{left} \leq N.left \leq \mathrm{right}\) and \(\mathrm{left} \leq N.right \leq \mathrm{right}\) (Assuming
endpoints=True
).False
otherwise.Tip
N in self
is equivalent toself.straddles(N)
- straddles_zero(endpoints=True)#
Checks whether \(0\) is within the interval
Implementation
Equivalent to
self.straddles(0,endpoints)
See also
- intersection(other: Interval | list) Interval #
Calculates the intersection between intervals
Parameters:
other
: The interval to intersect with self. If an interval is not given will try to cast as an interval. If a list is given will calculate the intersection between self and each element of the list.Returns:
Interval
: The intersection of self and other. If no intersection is found returnsNone
Example:
>>> a = Interval(0,1) >>> b = Interval(0.5,1.5) >>> a.intersection(b) Interval [0.5, 1]
- exp()#
- log()#
- sqrt()#
- sample(seed=None, numpy_rng: Generator | None = None) float #
Generate a random sample within the interval.
Parameters:
seed
(int, optional): Seed value for random number generation. Defaults to None.numpy_rng
(numpy.random.Generator, optional): Numpy random number generator. Defaults to None.Returns:
float
: Random sample within the interval.Implementation
If
numpy_rng
is given:>>> numpy_rng.uniform(self.left, self.right)
Otherwise the following is used:
>>> import random >>> random.seed(seed) >>> self.left + random.random() * self.width()
Examples:
>>> pba.Interval(0,1).sample() 0.6160988752201705 >>> pba.I(0,1).sample(seed = 1) 0.13436424411240122
If a numpy random number generator is given then it is used instead of the default python random number generator. It has to be initialised first.
>>> import numpy as np >>> rng = np.random.default_rng(seed = 0) >>> pba.I(0,1).sample(numpy_rng = rng) 0.6369616873214543
Plus-Minus Intervals#
- pba.interval.PM(x, hw)#
Create an interval centered around x with a half-width of hw.
Parameters:
x
(float): The center value of the interval.hw
(float): The half-width of the interval.Returns:
Interval
: An interval object with lower bound x-hw and upper bound x+hw.Error
ValueError
: If hw is less than 0.- Example:
>>> pba.pm(0, 1) Interval [-1, 1]
- pba.interval.pm_repr()#
Modifies the interval class to display the interval in [midpoint ± half-width] format.
Example:
>>> import pba >>> pba.interval.pm_repr() >>> a = pba.Interval(0,1) # defined using left and right. This cannot be overriden. >>> b = pba.PM(0,1) # defined using midpoint and half-width >>> print(a) Interval [0.5 ± 0.5] >>> print(b) Interval [0 ± 1]
See also
lr_interval_repr()
- pba.interval.lr_repr()#
Modifies the interval class to display the interval in [left, right] format.
Note
This function primarily exists to undo the effects of
pm_interval_repr()
. By default the interval class displays in this format.Example:
>>> import pba >>> pba.interval.pm_repr() >>> a = pba.Interval(0,1) # defined using left and right, this cannot be overriden. >>> print(a) Interval [0.5±0.5] >>> pba.interval.lr_repr() >>> b = pba.PM(0,1) # defined using midpoint and half-width >>> print(b) Interval [-1,1]