Welcome to asymintervals’ documentation!
The asymintervals library introduces a novel and unique approach with Asymmetric Interval Numbers (AINs), combining the simplicity of classical interval numbers with advanced capabilities for modeling uncertainty.
AINs integrate the expected value with the interval, offering a more accurate representation of data uncertainty compared to traditional interval numbers. This library provides a complete toolkit, including basic arithmetic operations. The theoretical foundations of AINs, along with detailed discussions on properties, rigorous mathematical proofs, and theorems on symmetry and asymmetry for both binary and unary operations, are introduced in [1], further enhancing the mathematical framework of AINs. Practical examples illustrate the versatility of AINs in various scientific and technical applications. AINs represent a significant advancement in interval arithmetic, paving the way for further research and applications across diverse fields.
Reference
If the asymintervals library has contributed to a scientific publication, we kindly request acknowledgment by citing it.
[1] Sałabun, W. (2025). Asymmetric Interval Numbers: a new approach to modeling uncertainty.
Fuzzy Sets and Systems, 499, 109169. https://doi.org/10.1016/j.fss.2024.109169
@article{salabun2025,
title={Asymmetric Interval Numbers: a new approach to modeling uncertainty},
author={Sałabun, Wojciech},
journal={Fuzzy sets and systems},
volume={499},
pages={109169},
year={2025},
publisher={Elsevier},
doi={10.1016/j.fss.2024.109169}
}
[2] Sałabun, W. (2025). AsymIntervals: A Python library for uncertainty modeling with asymmetric
interval numbers. SoftwareX, 32, 102380. https://doi.org/10.1016/j.softx.2025.102380
@article{salabun2025asymintervals,
title={AsymIntervals: A Python library for uncertainty modeling with asymmetric interval numbers},
author={Sa{\l}abun, Wojciech},
journal={SoftwareX},
volume={32},
pages={102380},
year={2025},
publisher={Elsevier},
doi={10.1016/j.softx.2025.102380}
}
Example
A simple example demonstrating how to use the library.
# Import the AIN (Asymmetric Interval Number) class from the asymintervals module
from asymintervals import AIN
import matplotlib.pyplot as plt
# Initialize two AIN instances with specified lower, upper, and expected values
a = AIN(0, 10, 2) # Interval 'a' with lower=0, upper=10, expected=2
b = AIN(2, 8, 3) # Interval 'b' with lower=2, upper=8, expected=3
# Perform arithmetic operations between interval 'a' and interval 'b'
c = a + b # Addition of intervals 'a' and 'b'
d = a * b # Multiplication of intervals 'a' and 'b'
e = a / b # Division of interval 'c' by interval 'd'
# Plot the resulting intervals from the arithmetic operations
c.plot() # Plot interval 'c' resulting from addition
d.plot() # Plot interval 'd' resulting from multiplication
e.plot() # Plot interval 'e' resulting from division
# Print the results of the operations for each interval
print(c) # Output the details of interval 'c'
print(d) # Output the details of interval 'd'
print(e) # Output the details of interval 'e'
# Print summaries for each interval to provide key statistics or characteristics
print("Summary for interval 'a':")
a.summary()
print("Summary for interval 'b':")
b.summary()
print("Summary for interval 'c':")
c.summary()
print("Summary for interval 'd':")
d.summary()
print("Summary for interval 'e':")
e.summary()
Full class description
- class asymintervals.AIN(lower: float, upper: float, expected: float = None)
Bases:
object- __repr__()
Return an unambiguous string representation of the AIN instance. The representation includes the class name AIN, followed by the lower, upper, and expected values enclosed in parentheses.
- Returns:
A string that accurately reflects the construction of the instance.
- Return type:
str
Examples
>>> a = AIN(0, 10, 8) >>> repr(a) 'AIN(0, 10, 8)'
>>> b = AIN(0, 10) >>> repr(b) 'AIN(0, 10, 5.0)'
- __str__()
Return a human-readable string representation of the AIN instance.
The string is formatted as ‘[lower, upper]_{expected}’ where ‘lower’, ‘upper’, and ‘expected’ are displayed with four decimal places. This format is designed to be clear, concise, and user-friendly, making it well-suited for printing and easy interpretation by end-users.
- Returns:
A string representation of the AIN instance, formatted to four decimal places for each numeric value.
- Return type:
str
Examples
>>> a = AIN(0, 10, 8) >>> print(a) [0.0000, 10.0000]_{8.0000}
>>> b = AIN(0, 10) >>> print(b) [0.0000, 10.0000]_{5.0000}
- __neg__()
Returns a new AIN instance representing the negation of the current instance (the additive inverse of the interval).
The negation of an AIN instance is achieved by reversing the signs of the lower, upper, and expected values: - The new lower bound becomes the negation of the original upper bound. - The new upper bound becomes the negation of the original lower bound. - The new expected value becomes the negation of the original expected value.
- Returns:
A new AIN instance representing the additive inverse of the interval.
- Return type:
Examples
>>> a = AIN(1, 10, 8) >>> print(-a) [-10.0000, -1.0000]_{-8.0000}
>>> a = AIN(2, 10) >>> print(-a) [-10.0000, -2.0000]_{-6.0000}
>>> a = np.array([AIN(0, 10), AIN(2, 8, 7)]) >>> print(-a) [AIN(-10, 0, -5.0) AIN(-8, -2, -7)]
- __add__(other)
Adds either another AIN instance or a value of type int or float to the current AIN instance. Returns a new AIN instance representing the result.
When adding another AIN instance, the resulting lower, upper, and expected
values are calculated by summing the corresponding values of both AIN instances. - When adding a value of type int or float, the value is added to each component (lower, upper, and expected) of the current AIN instance.
- Parameters:
other (AIN, float, or int) – The value to be added, which can be AIN instance, a float, or an int.
- Returns:
Returns a new AIN instance representing the result of the addition, with the lower, upper, and expected values updated accordingly based on the operation.
- Return type:
- Raises:
TypeError – If other is not an instance of AIN, float, or int.
Examples
Addition with another AIN instance: >>> a = AIN(1, 10, 8) >>> b = AIN(0, 5, 2) >>> print(a + b) [1.0000, 15.0000]_{10.0000}
Addition with a float or int: >>> a = AIN(1, 10, 8) >>> b = 2 >>> print(a + b) [3.0000, 12.0000]_{10.0000}
Performing addition with a np.array of AIN instances: >>> a = np.array([AIN(0, 10), AIN(2, 8, 7)]) >>> print(a + 2) [AIN(2, 12, 7.0) AIN(4, 10, 9)]
- __radd__(other)
Perform reflected (reverse) addition for an AIN instance.
This method handles the addition of an Asymmetric Interval Number (AIN) instance to a value of type float or int when the AIN appears on the right-hand side of the addition (i.e., other + self).
It computes other + self, ensuring commutative addition between AIN instances and numeric values (float or int).
- Parameters:
other (float or int) – The value to add to the current AIN instance.
- Returns:
A new AIN instance representing the result of the addition, with lower, upper, and expected values equal to the sum of other and the corresponding values of the current AIN instance.
- Return type:
- Raises:
TypeError – If other is not a float or int.
Examples
>>> a = AIN(1, 10, 8) >>> b = 5 >>> print(b + a) [6.0000, 15.0000]_{13.0000}
>>> a = np.array([AIN(0, 10), AIN(2, 8, 7)]) >>> b = 2 >>> print(2 + a) [AIN(2, 12, 7.0) AIN(4, 10, 9)]
- __sub__(other)
Subtract an AIN instance or a float or int from the current AIN instance.
This method allows subtraction of either another AIN or a float or int from the current AIN instance, returning a new AIN instance with the result. When subtracting another AIN, the resulting bounds and expected value are computed by subtracting the corresponding values of the operands. If subtracting a float or int, the value is subtracted from each component of the current AIN instance.
- Parameters:
other (AIN, float, or int) – The value to subtract, which can be an AIN instance, a float, or an int.
- Returns:
A new AIN instance representing the result of the subtraction, with adjusted lower, upper, and expected values based on the operation.
- Return type:
- Raises:
TypeError – If other is not an instance of AIN, float, or int.
Examples
Subtracting an AIN instance: >>> a = AIN(1, 10, 8) >>> b = AIN(0, 5, 2) >>> print(a - b) [-4.0000, 10.0000]_{6.0000}
Subtracting a float or int: >>> a = AIN(1, 10, 8) >>> b = 2 >>> print(a - b) [-1.0000, 8.0000]_{6.0000}
Performing subtraction with a np.array of AIN instances: >>> a = np.array([AIN(0, 10), AIN(2, 8, 7)]) >>> b = AIN(0, 5, 4) >>> print(a - b) [AIN(-5, 10, 1.0) AIN(-3, 8, 3)]
- __rsub__(other)
Perform reflected (reverse) subtraction for an AIN instance.
This method is invoked when an AIN instance appears on the right-hand side of a subtraction operation (i.e., other - self) and the left operand (other) does not support subtraction with an AIN. It calculates the result of other - self.
- Parameters:
other (float or int) – The value from which the current AIN instance is subtracted.
- Returns:
A new AIN instance representing the result of the subtraction. The resulting AIN has its lower, upper, and expected values computed as the difference between other and the respective values of the AIN instance.
- Return type:
- Raises:
TypeError – If other is not a float or int.
Examples
>>> a = AIN(1, 10, 8) >>> b = 5 >>> print(b - a) [-5.0000, 4.0000]_{-3.0000}
>>> a = np.array([AIN(0, 10), AIN(2, 8, 7)]) >>> print(2 - a) [AIN(-8, 2, -3.0) AIN(-6, 0, -5)]
- __mul__(other)
Perform multiplication of the current AIN instance with another AIN or a float or int.
This method allows the multiplication of an AIN instance with another AIN instance or a float or int, returning a new AIN instance that represents the result. When multiplying with another AIN, the interval boundaries are computed based on the combinations of bounds from both AIN instances.
- Parameters:
other (AIN, float, or int) – The value to multiply with, which can be another AIN instance, a float, or an int.
- Returns:
A new AIN instance representing the product of the multiplication.
- Return type:
- Raises:
TypeError – If other is not an instance of AIN, float, or int.
Examples
Multiplying with another AIN instance: >>> a = AIN(1, 3, 2) >>> b = AIN(2, 4, 3) >>> print(a * b) [2.0000, 12.0000]_{6.0000}
Multiplying with a float or int: >>> a = AIN(1, 3, 2) >>> b = 2 >>> print(a * b) [2.0000, 6.0000]_{4.0000}
Performing multiplication with a np.array of AIN instances: >>> a = np.array([AIN(0, 10), AIN(2, 8, 7)]) >>> b = AIN(1,4,2) >>> print(a * b) [AIN(0, 40, 10.0) AIN(2, 32, 14)]
- __rmul__(other)
Perform reverse multiplication for an AIN instance with a float or int.
This method allows an AIN instance to be multiplied by a float or int in cases where the float or int appears on the left side of the multiplication (i.e., other * self). This enables commutative multiplication between AIN and float or int values.
- Parameters:
other (float or int) – An float or int value to multiply with the AIN instance.
- Returns:
A new AIN instance representing the result of the multiplication.
- Return type:
- Raises:
TypeError – If other is not a float or int.
Examples
>>> a = AIN(1, 3, 2) >>> b = 2 >>> result = b * a >>> print(result) [2.0000, 6.0000]_{4.0000}
>>> a = np.array([AIN(0, 10), AIN(2, 8, 7)]) >>> b = 2 >>> print(b * a) [AIN(0, 20, 10.0) AIN(4, 16, 14)]
- __truediv__(other)
Perform division of the current AIN instance by another AIN instance or a float or int.
This method supports division by either another AIN or a float or int, returning a new AIN instance as the result. When dividing by an AIN, interval boundaries are calculated by dividing the respective boundaries, while the expected value is adjusted based on logarithmic calculations if the bounds differ.
- Parameters:
other (AIN, float, or int) – The divisor, which can be an AIN instance, a float, or an int.
- Returns:
A new AIN instance representing the result of the division.
- Return type:
- Raises:
TypeError – If other is not an instance of AIN, float, or int.
Examples
Division with another AIN instance: >>> a = AIN(4, 8, 6) >>> b = AIN(2, 4, 3) >>> print(a / b) [1.0000, 4.0000]_{2.0794}
Division with a float or int: >>> a = AIN(4, 8, 6) >>> b = 2 >>> print(a / b) [2.0000, 4.0000]_{3.0000}
Performing division with a np.array of AIN instances: >>> a = np.array([AIN(0, 10), AIN(2, 8, 7)]) >>> b = AIN(1, 4, 2) >>> print(a / b) [AIN(0.0, 10.0, 2.8881132523331052) AIN(0.5, 8.0, 4.043358553266348)]
- __rtruediv__(other)
Perform reverse true division of a float or int by an AIN instance.
This method enables division where a float or int other is divided by an AIN instance (self), calculating the reciprocal of self and then scaling it by other. It returns a new AIN instance representing the outcome.
- Parameters:
other (float or int) – The float or int to divide by the AIN instance.
- Returns:
A new AIN instance representing other divided by self.
- Return type:
- Raises:
TypeError – If other is not a float or int.
Examples
>>> a = AIN(2, 4, 3) >>> result = 10 / a >>> print(result) [2.5000, 5.0000]_{3.4657}
>>> a = np.array([AIN(2,10), AIN(2,8, 7)]) >>> result = 2 / a >>> print(result) [AIN(0.2, 1.0, 0.4023594781085251) AIN(0.25, 1.0, 0.3060698522738955)]
- __pow__(n)
Raise an AIN instance to the power n.
This method computes the result of raising the AIN instance to the specified exponent n.
- Parameters:
n (int or float) – The exponent to which the AIN is raised. Valid values include positive or negative real numbers.
- Raises:
TypeError – If n is not a float or int.
ValueError – If the operation would result in a complex number (e.g., taking the square root of a negative value), or if n = -1 and the interval includes 0, as division by zero is undefined.
- Returns:
A new AIN instance representing the interval raised to the power of n.
- Return type:
Notes
For n = -1, the method checks if 0 is within the interval. If it is, the operation is undefined (division by zero) and raises a ValueError.
When n results in a complex output (e.g., fractional exponents for negative values), a ValueError is raised to indicate that complex results are unsupported.
For other exponents, the power is applied individually to self.lower, self.upper, and self.expected, with appropriate handling for intervals containing 0 to avoid undefined behaviors.
Examples
>>> a = AIN(4, 8, 5) >>> print(a**2) [16.0000, 64.0000]_{26.0000}
>>> b = AIN(-2, 10, 3) >>> print(b**(-1)) Traceback (most recent call last): ... ValueError: The operation cannot be execute because 0 is included in the interval.
>>> c = AIN(-2, 10, 3) >>> print(c**(0.5)) Traceback (most recent call last): ... ValueError: The operation cannot be execute because it will be complex number in result for n = 0.5
>>> a = np.array([AIN(0, 9), AIN(2, 8, 5)]) >>> print(a ** 2) [AIN(0, 81, 27.0) AIN(4, 64, 28.0)]
- pdf(x)
Calculate the probability density function (PDF) value for the AIN at a given point x.
This method calculates the probability density at x within the AIN-defined interval. The PDF describes how the density is distributed across the AIN interval, with distinct values in different segments: - Outside the interval [self.lower, self.upper], the density is 0. - Between self.lower and self.expected, the density is equal to self.alpha. - Between self.expected and self.upper, the density is equal to self.beta.
- Parameters:
x (int or float) – The point at which to evaluate the PDF. Should be a numeric value.
- Returns:
The PDF value at the specified point x. The return value will be: - 0 if x is outside the interval [self.lower, self.upper]. - self.alpha if x is within the interval [self.lower, self.expected]. - self.beta if x is within the interval [self.expected, self.upper].
- Return type:
float
- Raises:
TypeError – If x is not an int or float.
Examples
>>> a = AIN(0, 10, 5) >>> a.pdf(-1) 0.0
>>> a.pdf(3) 0.1
>>> a.pdf(7) 0.1
>>> a.pdf(11) 0.0
- cdf(x)
Calculate the cumulative distribution function (CDF) value for a specified input x.
This method evaluates the cumulative distribution function (CDF) of the AIN instance at the given value x, indicating the probability that a random variable takes a value less than or equal to x. The CDF value is computed based on the position of x relative to the instance’s defined bounds (self.lower, self.expected, self.upper).
- Parameters:
x (int or float) – The point at which to evaluate the CDF. This should be a numeric value.
- Returns:
The computed CDF value at x, representing the cumulative probability up to x. The output will follow these cases: - 0 if x is less than the lower bound (self.lower). - A linearly interpolated value between the lower bound and the expected value
if x is between self.lower and self.expected.
A linearly interpolated value between the expected value and the upper bound if x is between self.expected and self.upper.
1 if x is greater than or equal to the upper bound (self.upper).
- Return type:
float
- Raises:
TypeError – If x is not an int or float.
Notes
This method calculates the CDF using a piecewise approach: - For x < self.lower, it returns 0. - For self.lower <= x < self.expected, the CDF is calculated as self.alpha * (x - self.lower). - For self.expected <= x < self.upper, the CDF is calculated as
self.alpha * (self.expected - self.lower) + self.beta * (x - self.expected).
For x >= self.upper, it returns 1.
Examples
>>> a = AIN(0, 10, 3) >>> a.cdf(1.5) 0.35
>>> a.cdf(3) 0.7
>>> a.cdf(8.5) 0.9357142857142857
>>> a.cdf(20) 1
- quantile(y)
Compute the quantile value (inverse cumulative distribution function) for a given probability.
This method calculates the quantile, or the inverse cumulative distribution function (CDF), for the AIN instance at a specified probability level y. The quantile represents the value below which a given percentage of observations fall, based on the AIN instance’s parameters. The function only operates within the probability range [0, 1].
- Parameters:
y (int or float) – The probability level at which to compute the quantile. Must be within the range [0, 1], where 0 represents the minimum and 1 represents the maximum of the distribution.
- Returns:
The quantile value corresponding to the given probability y.
- Return type:
float
- Raises:
ValueError – If y is outside the valid range [0, 1].
TypeError – If y is not a float or int value.
Notes
The method uses self.alpha, self.beta, self.expected, and self.lower attributes to compute the quantile based on a piecewise formula: - For values of y below self.alpha * (self.expected - self.lower), the quantile
is calculated as y / self.alpha + self.lower.
Otherwise, it is calculated as (y - self.alpha * (self.expected - self.lower)) / self.beta + self.expected.
Examples
>>> a = AIN(0, 10, 3) >>> a.quantile(0.25) 1.0714285714285714
>>> a.quantile(0.85) 6.5
>>> a.quantile(1.1) Traceback (most recent call last): ... ValueError: Argument y = 1.1 is out of range; it should be between 0 and 1.
- summary(precision=6)
Print a detailed, aligned summary of the AIN object’s key attributes with specified precision.
This method displays a formatted summary of the AIN object’s primary attributes, including alpha, beta, asymmetry, expected value, variance, standard deviation, and midpoint. Each attribute is displayed with the specified number of decimal places, allowing for a concise or detailed view.
- Parameters:
precision (int, optional) – The number of decimal places to display for floating-point values (default is 6). Must be an integer; otherwise, a ValueError is raised.
- Raises:
TypeError – If precision is not an int, a ValueError is raised with an informative message.
Example
>>> a = AIN(0, 10, 2) >>> a.summary(precision=4) === AIN ============================ [0.0000, 10.0000]_{2.0000} === Summary ======================== Alpha = 0.4000 Beta = 0.0250 Asymmetry = 0.6000 Exp. val. = 2.0000 Variance = 5.3333 Std. dev. = 2.3094 Midpoint = 5.0000 ====================================
Notes
This method ensures a clean, easy-to-read summary by aligning values based on the longest entry, making it particularly useful for inspecting the AIN object’s main parameters in detail.
- midpoint()
Return the midpoint of the interval.
- Returns:
The midpoint ((upper + lower) / 2).
- Return type:
float
Examples
>>> x = AIN(1, 10, 5) >>> print(x.midpoint()) 5.5
- width()
Return the width of the interval.
- Returns:
The width (upper - lower).
- Return type:
float
Examples
>>> x = AIN(1, 10, 5) >>> print(x.width()) 9
- radius()
Return the radius of the interval.
- Returns:
The radius ((upper - lower) / 2).
- Return type:
float
Examples
>>> x = AIN(1, 10, 5) >>> print(x.radius()) 4.5
- is_degenerate()
Check if the interval is degenerate (a single point).
- Returns:
True if lower == upper, False otherwise.
- Return type:
bool
Examples
>>> x = AIN(5, 5, 5) >>> print(x.is_degenerate()) True
>>> x = AIN(1, 10, 5) >>> print(x.is_degenerate()) False
- is_positive()
Check if the entire interval is positive.
- Returns:
True if lower > 0, False otherwise.
- Return type:
bool
Examples
>>> x = AIN(1, 10, 5) >>> print(x.is_positive()) True
>>> x = AIN(-5, 10, 2) >>> print(x.is_positive()) False
- is_negative()
Check if the entire interval is negative.
- Returns:
True if upper < 0, False otherwise.
- Return type:
bool
Examples
>>> x = AIN(-10, -1, -5) >>> print(x.is_negative()) True
>>> x = AIN(-5, 10, 2) >>> print(x.is_negative()) False
- is_zero()
Check if the interval represents exactly zero.
- Returns:
True if AIN(0, 0, 0), False otherwise.
- Return type:
bool
Examples
>>> x = AIN(0, 0, 0) >>> print(x.is_zero()) True
>>> x = AIN(-1, 1, 0) >>> print(x.is_zero()) False
- isclose_to_zero(atol=1e-09)
Check if the interval is close to zero within a specified absolute tolerance.
- Parameters:
atol (float, optional) – The absolute tolerance level (default is 1e-9).
- Returns:
True if both lower and upper bounds are within the absolute tolerance of zero, False otherwise.
- Return type:
bool
Examples
>>> x = AIN(-1e-10, 1e-10, 0) >>> print(x.isclose_to_zero()) True
>>> x = AIN(-1e-5, 1e-5, 0) >>> print(x.isclose_to_zero(atol=1e-6)) False
- has_zero()
Check if the interval contains zero.
- Returns:
True if lower <= 0 <= upper, False otherwise.
- Return type:
bool
Examples
>>> x = AIN(-5, 5, 0) >>> print(x.has_zero()) True
>>> x = AIN(1, 10, 5) >>> print(x.has_zero()) False
- is_symmetric()
Check if the interval is symmetric (expected at midpoint).
- Returns:
True if expected is at the midpoint (asymmetry ≈ 0), False otherwise.
- Return type:
bool
Examples
>>> x = AIN(0, 10, 5) >>> print(x.is_symmetric()) True
>>> x = AIN(0, 10, 3) >>> print(x.is_symmetric()) False
- overlaps(other)
Check if two intervals overlap.
- Parameters:
other (AIN) – Another AIN instance.
- Returns:
True if intervals overlap, False otherwise.
- Return type:
bool
Examples
>>> x = AIN(0, 10, 5) >>> y = AIN(5, 15, 10) >>> print(x.overlaps(y)) True
>>> x = AIN(0, 5, 2) >>> y = AIN(10, 15, 12) >>> print(x.overlaps(y)) False
- is_subset_of(other)
Check if this interval is a subset of another interval.
An interval A is a subset of B if A is completely contained within B: B.lower <= A.lower and A.upper <= B.upper
- Parameters:
other (AIN) – Another AIN instance.
- Returns:
True if self is a subset of other, False otherwise.
- Return type:
bool
Examples
>>> x = AIN(2, 8, 5) >>> y = AIN(0, 10, 5) >>> print(x.is_subset_of(y)) True
>>> x = AIN(0, 10, 5) >>> y = AIN(2, 8, 5) >>> print(x.is_subset_of(y)) False
- is_disjoint(other)
Check if two intervals are disjoint (do not overlap).
Two intervals are disjoint if they have no common points.
- Parameters:
other (AIN) – Another AIN instance.
- Returns:
True if intervals are disjoint, False otherwise.
- Return type:
bool
Examples
>>> x = AIN(0, 5, 2) >>> y = AIN(10, 15, 12) >>> print(x.is_disjoint(y)) True
>>> x = AIN(0, 10, 5) >>> y = AIN(5, 15, 10) >>> print(x.is_disjoint(y)) False
- contains(value)
Check if a value is contained in the interval.
- Parameters:
value (float or int) – The value to check.
- Returns:
True if lower <= value <= upper, False otherwise.
- Return type:
bool
Examples
>>> x = AIN(0, 10, 5) >>> print(x.contains(5)) True >>> print(x.contains(15)) False
- winsorize(min_val, max_val)
The winsorize operator returns an AIN whose expected value equals the expectation of the clipped random variable. Clip the interval to [min_val, max_val].
- Parameters:
min_val (float) – Minimum value.
max_val (float) – Maximum value.
- Returns:
A new AIN instance with values clamped to [min_val, max_val].
- Return type:
- Raises:
ValueError – If min_val >= max_val.
Examples
>>> x = AIN(-5, 10, 2) >>> result = x.winsorize(0, 5) >>> print(result) [0.0000, 5.0000]_{2.2232}
Notes
Due to the nonlinear saturation introduced by the clipping operator, the expected value of the winsorized AIN is a non-monotonic function of the characteristic parameter, as directly implied by the LOTUS formulation.
- copy()
Create a deep copy of the AIN instance.
- Returns:
A new AIN instance with the same values.
- Return type:
Examples
>>> x = AIN(0, 10, 5) >>> y = x.copy() >>> print(y) [0.0000, 10.0000]_{5.0000}
- plot(ain_lw=2.0, ain_c='k', ain_label='')
Plot the intervals and key values of an AIN instance.
Visualizes the AIN instance by plotting its lower, expected, and upper values, along with corresponding alpha and beta levels.
- Parameters:
ain_lw (float, optional) – Line width for the alpha and beta lines. Must be a positive float or integer. Default is 2.0.
ain_c (str, optional) – Color for the interval lines. Accepts any valid matplotlib color string. Default is ‘k’ (black).
ain_label (str, optional) – Label for the x-axis, representing the AIN instance. Default is an empty string.
- Returns:
The Axes object containing the plot.
- Return type:
matplotlib.axes.Axes
- Raises:
ValueError – If ain_lw is not a positive float or int.
TypeError – If ain_c or ain_label is not a string.
Examples
>>> # Uncomment to show this functionality >>> # ain = AIN(1, 10, 3) >>> # ain.plot(ain_label='Example') >>> # plt.show()
Notes
Vertical dashed lines are placed at the lower, expected, and upper interval bounds.
Horizontal solid lines represent the alpha level between the lower and expected values, and the beta level between the expected and upper values.
Y-axis limits are automatically adjusted based on the maximum of alpha and beta, while the x-axis extends slightly beyond the interval bounds for readability.
The default y-axis label is set to ‘pdf’, and the x-axis label displays ain_label.
- static get_y_scale_max(ains_list)
Calculate the maximum scale value (y-axis) from a list of AIN objects.
- Parameters:
ains_list (list) – A list of AIN objects.
- Returns:
The maximum scale value found in the list of AIN objects.
- Return type:
float
- Raises:
TypeError – If ains_list is not a list or if any element in the list is not an AIN object.
Notes
This function computes the maximum of the alpha and beta values across all AIN objects in the provided list to determine the maximum scale value on the y-axis.
Example
Assuming ains_list is a list of AIN objects:
>>> ains_list = [AIN(1, 10), AIN(2, 10, 4)] >>> max_value = AIN.get_y_scale_max(ains_list) >>> print(max_value) 0.375
- add_to_plot(ain_lw=2.0, ain_c='k', ain_label='', ax=None, y_scale_max=None)
Plot the intervals and key values of an AIN instance.
Visualizes the AIN instance by plotting its lower, expected, and upper values, along with corresponding alpha and beta levels. The plot includes:
Vertical dashed lines at the lower, expected, and upper bounds of the interval.
Horizontal solid lines representing the alpha and beta values across the intervals.
Dynamically scales the x- and y-axes for clarity, with an optional global maximum for y-axis scaling.
- Parameters:
ain_lw (float, optional) – Line width for the alpha and beta interval lines. Default is 2.0.
ain_c (str, optional) – Color for the interval lines. Default is ‘k’ (black).
ain_label (str, optional) – Label for the x-axis describing the plotted AIN instance. Default is ‘’.
ax (matplotlib.axes.Axes, optional) – Matplotlib axis to add the plot to. If not provided, the current axis (plt.gca()) is used.
y_scale_max (float or int, optional) – Maximum value for the y-axis to ensure consistent scaling across multiple AIN plots. If not provided, the y-axis is scaled to 1.1 times the maximum of alpha or beta for this AIN instance.
- Returns:
The matplotlib axis with the AIN plot.
- Return type:
matplotlib.axes.Axes
- Raises:
ValueError – If ain_lw is non-positive or if y_scale_max is negative.
TypeError – If ain_lw or y_scale_max are not numeric, or if ain_c or ain_label are not strings.
Examples
>>> # Uncomment to show this functionality >>> # ain = AIN(1, 10, 5) >>> # ain.add_to_plot(ain_label='Example Interval') >>> # plt.show() >>> # a = AIN(0, 10, 4.5) >>> # b = AIN(0, 10, 7.5) >>> # value_y_scale_max = AIN.get_y_scale_max([a, b]) >>> # plt.figure(figsize=(8, 3)) >>> # plt.subplot(1, 2, 1) >>> # a.add_to_plot(y_scale_max=value_y_scale_max) >>> # plt.subplot(1, 2, 2) >>> # b.add_to_plot(y_scale_max=value_y_scale_max) >>> # plt.tight_layout() >>> # plt.show() # Uncomment to display the plot
Notes
Vertical dashed lines are positioned at the lower, expected, and upper bounds of the interval.
Horizontal solid lines represent the alpha level between the lower and expected values, and the beta level between the expected and upper values.
The y-axis limits are automatically adjusted based on the maximum of alpha and beta values unless y_scale_max is specified. The x-axis extends slightly beyond the interval bounds for readability.
The default y-axis label is set to ‘$pdf$’, and the x-axis label is set to ain_label.
- __abs__()
Compute the absolute value of an AIN instance.
The absolute value operation handles three cases based on the position of the interval relative to zero. This implementation follows the LOTUS (Law of the Unconscious Statistician) methodology to compute the expected value of |X|.
- Returns:
A new AIN instance representing the absolute value of the interval.
- Return type:
- Raises:
None –
Notes
The method handles three distinct cases:
Case 1: If the entire interval is non-negative (a ≥ 0), the absolute value does not change the interval: |[a, b]_c| = [a, b]_c
Case 2: If the entire interval is non-positive (b ≤ 0), the absolute value negates and reverses the bounds: |[a, b]_c| = [-b, -a]_{-c}
Case 3: If the interval contains zero (a < 0 < b), the absolute value results in an interval starting at zero. The expected value is computed using LOTUS:
- For c > 0 (expected value in positive part):
E(|X|) = α(c²/2 - a²/2) + β(b²/2 - c²/2)
- For c ≤ 0 (expected value in negative part):
E(|X|) = α(0 - a²/2) + β(b²/2 - 0)
The upper bound becomes max(-a, b) to capture the maximum absolute value.
Examples
Case 1: Non-negative interval >>> a = AIN(1, 4, 2) >>> print(abs(a)) [1.0000, 4.0000]_{2.0000}
Case 2: Non-positive interval >>> b = AIN(-4, -1, -2) >>> print(abs(b)) [1.0000, 4.0000]_{2.0000}
Case 3: Interval containing zero (c > 0) >>> c = AIN(-2, 3, 1) >>> result = abs(c) >>> print(result) [0.0000, 3.0000]_{1.5333}
Case 3: Interval containing zero (c ≤ 0) >>> d = AIN(-3, 2, -1) >>> result = abs(d) >>> print(result) [0.0000, 3.0000]_{1.5333}
Symmetric interval around zero >>> e = AIN(-2, 2, 0) >>> result = abs(e) >>> print(result) [0.0000, 2.0000]_{1.0000}
- __rpow__(a)
Compute a^x where a is the base and self (x) is the AIN instance.
Allows expressions like 2 ** AIN(1, 2, 1.5).
- Parameters:
a (float or int) – The base of the power function. Must be positive and not equal to 1.
- Returns:
A new AIN instance representing the result of a^x operation.
- Return type:
- Raises:
TypeError – If a is not a number (int or float).
ValueError – If a <= 0 or a == 1.
Examples
>>> a = AIN(1, 2, 1.5) >>> print(2 ** a) [2.0000, 4.0000]_{2.8854}
- log()
Computes the natural logarithm (ln(x)) of the current AIN instance. Returns a new AIN instance representing the result.
When computing ln(x) of an AIN instance, the resulting lower and upper
values are calculated by applying the natural logarithm function to the corresponding bounds of the current AIN instance. - The expected value is calculated using the formula:
c_ln = α(c·ln(c) - c - a·ln(a) + a) + β(b·ln(b) - b - c·ln(c) + c) where a = lower, b = upper, c = expected, α = alpha, β = beta
- Parameters:
None
- Returns:
Returns a new AIN instance representing the result of the natural logarithm operation, with the lower, upper, and expected values updated accordingly based on the operation.
- Return type:
- Raises:
TypeError – If self is not an instance of AIN.
ValueError – If lower <= 0, as the natural logarithm is undefined for non-positive values.
Examples
Natural logarithm of an AIN instance: >>> a = AIN(1, np.e, 2) >>> print(a.log()) [0.0000, 1.0000]_{0.6587}
- log2()
Compute base-2 logarithm of an AIN instance.
- Returns:
A new AIN instance representing log2(X).
- Return type:
- Raises:
ValueError – If lower bound is non-positive.
Examples
>>> x = AIN(1, 8, 4) >>> result = x.log2() >>> print(result) [0.0000, 3.0000]_{1.7954}
- log10()
Compute base-10 logarithm of an AIN instance.
- Returns:
A new AIN instance representing log10(X).
- Return type:
- Raises:
ValueError – If lower bound is non-positive.
Examples
>>> x = AIN(1, 100, 10) >>> result = x.log10() >>> print(result) [0.0000, 2.0000]_{0.7677}
- exp()
Computes the exponential (e^x) of the current AIN instance. Returns a new AIN instance representing the result.
When computing exp() of an AIN instance, the resulting lower and upper
values are calculated by applying the exponential function to the corresponding values. - The expected value is calculated as the mean value of exp(x) over the interval [lower, upper], given by (e^upper - e^lower) / (upper - lower).
- Parameters:
None
- Returns:
Returns a new AIN instance representing the result of the exponential operation, with the lower, upper, and expected values updated accordingly.
- Return type:
- Raises:
TypeError – If self is not an instance of AIN.
ValueError – If lower >= upper.
Examples
Exponential of an AIN instance: >>> a = AIN(0, 1, 0.5) >>> print(a.exp()) [1.0000, 2.7183]_{1.7183}
- sin()
Compute sine of an AIN instance.
- Returns:
A new AIN instance representing sin(X).
- Return type:
Examples
>>> x = AIN(0, np.pi/2, np.pi/4) >>> result = x.sin() >>> print(result) [0.0000, 1.0000]_{0.6366}
>>> x = AIN(0, 0, 0) >>> result = x.sin() >>> print(result) [0.0000, 0.0000]_{0.0000}
- cos()
Compute cosine of an AIN instance.
- Returns:
A new AIN instance representing cos(X).
- Return type:
Examples
>>> x = AIN(0, np.pi/2, np.pi/4) >>> result = x.cos() >>> print(result) [0.0000, 1.0000]_{0.6366}
>>> x = AIN(0, np.pi, np.pi/2) >>> result = x.cos() >>> print(result) [-1.0000, 1.0000]_{0.0000}
- tan()
Compute tangent of an AIN instance.
- Returns:
A new AIN instance representing tan(X).
- Return type:
- Raises:
ValueError – If the interval contains or touches a discontinuity (asymptote) of tan(x). tan(x) has asymptotes at x = π/2 + kπ for any integer k.
Examples
>>> x = AIN(0, np.pi/4, np.pi/8) >>> result = x.tan() >>> print(result) [0.0000, 1.0000]_{0.4413}
>>> x = AIN(-np.pi/4, np.pi/4, 0) >>> result = x.tan() >>> print(result) [-1.0000, 1.0000]_{0.0000}
- classmethod from_samples(data, method='minmax', clip_outliers=False)
Create AIN from empirical data using various methods.
This method constructs an AIN instance from a collection of samples, offering multiple strategies for determining interval bounds and handling outliers.
- Parameters:
data (array-like) – Sample data (list, numpy array, etc.)
method (str, optional) – Method for determining bounds (default: ‘minmax’): - ‘minmax’: Use minimum and maximum values - ‘percentile’: Use 1st and 99th percentiles - ‘iqr’: Use interquartile range (Q1-Q3) - ‘std’: Use mean ± 3*sigma - ‘mad’: Use median ± 3*MAD (Median Absolute Deviation)
clip_outliers (bool, optional) – Whether to remove outliers before calculations using IQR method (default: False)
- Returns:
A new AIN instance with bounds determined by the chosen method and expected value equal to the sample mean.
- Return type:
- Raises:
ValueError – If data is empty or method is unknown.
TypeError – If data cannot be converted to numpy array.
Examples
Basic usage with default method: >>> data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> x = AIN.from_samples(data) >>> print(x) [1.0000, 10.0000]_{5.5000}
Using percentile method (robust to outliers): >>> data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 100] # 100 is outlier >>> x = AIN.from_samples(data, method=’percentile’) >>> print(x) [1.0900, 91.8100]_{14.5000}
Using IQR method (focuses on central 50%): >>> data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> x = AIN.from_samples(data, method=’iqr’) >>> print(x) [3.2500, 7.7500]_{5.5000}
Removing outliers before analysis: >>> data = [100, 102, 98, 101, 99, 103, 500, 97, 102, 100] >>> x = AIN.from_samples(data, method=’minmax’, clip_outliers=True) >>> print(x) [97.0000, 103.0000]_{100.2222}
Using MAD method (most robust): >>> data = [10, 11, 10.5, 11.2, 10.8, 999] >>> x = AIN.from_samples(data, method=’mad’) >>> print(x) [9.8500, 11.9500]_{10.7000}
Notes
Method selection guide: - ‘minmax’: Best for clean data without outliers - ‘percentile’: Good balance between robustness and data retention - ‘iqr’: Very robust, focuses on central tendency - ‘std’: Assumes normal distribution, good for theoretical bounds - ‘mad’: Most robust to outliers, works with any distribution
The clip_outliers option uses the IQR method with 1.5*IQR rule to identify and remove outliers before applying the selected method.
- samples(n, rounding_precision=4, rng=None)
Generate random samples from the AIN distribution.
- Parameters:
n (int) – Number of random samples to generate.
rounding_precision (int, optional) – Number of decimal places to round the samples (default is 4).
rng (numpy.random.Generator, optional) – A NumPy random number generator instance for reproducibility (default is None, which uses the global random state).
- Returns:
An array of n random samples drawn from the AIN distribution.
- Return type:
numpy.ndarray
- Raises:
ValueError – If n is not a positive integer.
Examples
>>> ain = AIN(0, 10, 5) >>> rng = np.random.default_rng(seed=42) >>> data = ain.samples(5, 4, rng) >>> print(data) [7.7396 4.3888 8.586 6.9737 0.9418]
Notes
This method uses inverse transform sampling to generate samples according to the AIN distribution.
- to_list()
Convert AIN to list [lower, upper, expected].
- Returns:
[lower, upper, expected]
- Return type:
list
Examples
>>> x = AIN(0, 10, 5) >>> print(x.to_list()) [0, 10, 5]
- classmethod from_list(lst)
Create AIN from list [lower, upper, expected].
- Parameters:
lst (list) – List containing [lower, upper, expected]
- Returns:
AIN instance created from the list.
- Return type:
- Raises:
ValueError – If the list does not contain exactly three elements.
Examples
>>> lst = [0, 10, 5] >>> x = AIN.from_list(lst) >>> print(x) [0.0000, 10.0000]_{5.0000}
- to_numpy()
Convert AIN to numpy array [lower, upper, expected].
- Returns:
Array containing [lower, upper, expected]
- Return type:
numpy.ndarray
Examples
>>> x = AIN(0., 10., 5.) >>> arr = x.to_numpy() >>> print(arr) [ 0. 10. 5.] >>> print(type(arr)) <class 'numpy.ndarray'>
- classmethod from_numpy(arr)
Create AIN from numpy array [lower, upper, expected].
- Parameters:
arr (numpy.ndarray) – Numpy array containing [lower, upper, expected]
- Returns:
AIN instance created from the numpy array.
- Return type:
- Raises:
ValueError – If the array does not contain exactly three elements.
Examples
>>> arr = np.array([0., 10., 5.]) >>> x = AIN.from_numpy(arr) >>> print(x) [0.0000, 10.0000]_{5.0000}
- to_dict()
Export AIN to a dictionary.
- Returns:
Dictionary containing all AIN attributes.
- Return type:
dict
Examples
>>> x = AIN(0, 4, 2) >>> d = x.to_dict() >>> print(d) {'lower': 0, 'upper': 4, 'expected': 2}
- classmethod from_dict(d)
Create AIN from a dictionary.
- Parameters:
d (dict) – Dictionary containing at least ‘lower’, ‘upper’, and optionally ‘expected’.
- Returns:
A new AIN instance.
- Return type:
Examples
>>> d = {'lower': 0, 'upper': 10, 'expected': 5} >>> x = AIN.from_dict(d) >>> print(x) [0.0000, 10.0000]_{5.0000}
- to_tuple()
Convert AIN to tuple (lower, upper, expected).
- Returns:
(lower, upper, expected)
- Return type:
tuple
Examples
>>> x = AIN(0, 10, 5) >>> print(x.to_tuple()) (0, 10, 5)
- classmethod from_tuple(t)
- Parameters:
t (tuple) – Tuple containing at least ‘lower’, ‘upper’, and optionally ‘expected’.
- Returns:
A new AIN instance.
- Return type:
Examples
>>> x = (0, 10, 5) >>> ain = AIN.from_tuple(x) >>> ain AIN(0, 10, 5)
- to_json()
Convert AIN to JSON string.
- Returns:
JSON string representation of the AIN
- Return type:
str
Examples
>>> x = AIN(0, 10, 5) >>> j = x.to_json() >>> print(j) {"lower": 0, "upper": 10, "expected": 5}
- classmethod from_json(json_str)
Create AIN from a JSON string.
This is the inverse of to_json(). Parses a JSON string and creates an AIN instance from the data.
- Parameters:
json_str (str) – JSON string containing AIN data. Must contain at least ‘lower’ and ‘upper’ keys.
- Returns:
A new AIN instance.
- Return type:
- Raises:
TypeError – If json_str is not a string
ValueError – If JSON is invalid or missing required keys
Examples
>>> json_str = '{"lower": 0, "upper": 10, "expected": 5}' >>> x = AIN.from_json(json_str) >>> print(x) [0.0000, 10.0000]_{5.0000}
>>> # Round-trip conversion >>> original = AIN(1, 5, 3) >>> json_str = original.to_json() >>> restored = AIN.from_json(json_str) >>> print(restored) [1.0000, 5.0000]_{3.0000}
- classmethod normalize_ains_list(list_ain, mode='minmax', type='profit')
Normalize a list of AIN instances.
- Parameters:
list_ain (list) – List of AIN instances to normalize.
mode (str, optional) – Normalization mode. Reserved for future use; currently, only the default behavior is applied regardless of the mode. Defaults to ‘minmax’.
- Returns:
List of normalized AIN instances representing a probability distribution.
- Return type:
list
- Raises:
ValueError – If the input list is empty or contains non-AIN elements.
Examples
>>> a1 = AIN(2, 10, 5) >>> a2 = AIN(10, 20, 15) >>> normalized = AIN.normalize_ains_list([a1, a2]) >>> for ain in normalized: ... print(ain) [0.0000, 0.4444]_{0.1667} [0.4444, 1.0000]_{0.7222}