Source code for eclypse.graph.assets.convex
"""Module for the Convex Asset class.
It represents a numeric asset where the aggregation is convex,
i.e. the minimum value of the assets. It provides the interface
for the basic algebraic functions between assets:
- `aggregate`: Aggregate the assets into a single asset via the minimum value.
- `satisfies`: Check if the asset contains another asset.
- `is_consistent`: Check if the asset belongs to the interval
[lower_bound, upper_bound].
"""
from __future__ import annotations
from typing import (
TYPE_CHECKING,
Any,
)
from .asset import Asset
if TYPE_CHECKING:
from collections.abc import (
Callable,
)
from eclypse.utils.types import PrimitiveType
from .space import AssetSpace
[docs]
class Convex(Asset):
"""ConvexAsset represents a numeric asset where the aggregation is convex."""
[docs]
def __init__(
self,
lower_bound: float,
upper_bound: float,
init_fn_or_value: PrimitiveType | AssetSpace | Callable[[], Any] | None = None,
functional: bool = True,
):
"""Create a new Convex asset.
Args:
lower_bound (float): The lower bound of the asset.
upper_bound (float): The upper bound of the asset.
init_fn_or_value (PrimitiveType | AssetSpace | Callable[[], Any] | None):
The function to initialize the asset. It can be a primitive type, a
callable with no arguments or an `AssetSpace` object. If it is not
provided, the asset will be initialized with the lower bound.
Defaults to None.
functional (bool, optional): If True, the asset is functional. Defaults
to True.
Raises:
ValueError: If $lower_bound < upper_bound$.
"""
super().__init__(
lower_bound=lower_bound,
upper_bound=upper_bound,
init_fn_or_value=init_fn_or_value,
functional=functional,
)
[docs]
def aggregate(self, *assets) -> float:
"""Aggregate the assets into a single asset by taking the minimum value.
If no assets are provided, the upper bound is returned.
Args:
assets (Iterable[NumericAsset]): The assets to aggregate.
Returns:
NumericAsset: The aggregated asset.
"""
return min(assets, default=self.upper_bound)
[docs]
def satisfies(self, asset: float, constraint: float) -> bool:
"""Check if `asset` contains `constraint`.
In the ordering of a convex asset, the higher value contains the other.
Args:
asset (NumericAsset): The "container" asset.
constraint (NumericAsset): The "contained" asset.
Returns:
bool: True if asset >= constraint, False otherwise.
"""
return asset >= constraint
[docs]
def is_consistent(self, asset: float) -> bool:
"""Check if the asset belongs to the interval [lower_bound, upper_bound].
Args:
asset (NumericAsset): The asset to check.
Returns:
bool: True if the asset is within the interval, False otherwise.
"""
return self.lower_bound <= asset <= self.upper_bound
[docs]
def flip(self):
"""Flip the convex asset into a concave asset.
Returns:
Concave: The flipped concave asset.
"""
from .concave import Concave # pylint: disable=import-outside-toplevel
return Concave(
self.upper_bound,
self.lower_bound,
self.init_fn,
self.functional,
)