Skip to content

pygx.algo.scalars

Step-based scalars used as hyper-parameters for PyGX algorithms.

scalars

Step-based scalars used as hyper-parameters for PyGX algorithms.

A scalar is a deferred numerical expression that produces a float when sampled at a given step. They are useful as hyper-parameters in evolutionary algorithms when a value should change over the course of a search — for example, a mutation rate that anneals from 1.0 down to 0.1 over 1000 steps.

This module provides:

  • The Scalar base type plus Constant for trivial cases.
  • Arithmetic combinators (Addition, Multiplication, Division, Mod, ...) so scalars compose with +/*/etc.
  • Elementary functions (Cosine, Exp, Log, ...).
  • Stochastic primitives (Gaussian, LogNormal).
  • make_scalar for converting a plain Python value into a Scalar when an API accepts either.

Absolute

Absolute(x: ScalarValue, **kwargs)

Bases: UnaryOp

Absolute operator.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, **kwargs):
    super().__init__(**dict(x=x), **kwargs)

Addition

Addition(x: ScalarValue, y: ScalarValue, **kwargs)

Bases: BinaryOp

Add operation.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, y: ScalarValue, **kwargs):
    super().__init__(**dict(x=x, y=y), **kwargs)

BinaryOp

BinaryOp(x: ScalarValue, y: ScalarValue, **kwargs)

Bases: Scalar

Binary operation for computing scheduled value.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, y: ScalarValue, **kwargs):
    super().__init__(**dict(x=x, y=y), **kwargs)

operate abstractmethod

operate(x: int | float, y: int | float) -> int | float

Implementation of the operation on two computed value.

Source code in pygx/algo/scalars/_base.py
@abc.abstractmethod
def operate(self, x: int | float, y: int | float) -> int | float:
    """Implementation of the operation on two computed value."""

Ceiling

Ceiling(x: ScalarValue, **kwargs)

Bases: UnaryOp

Ceil operator.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, **kwargs):
    super().__init__(**dict(x=x), **kwargs)

Constant

Constant(value: Any, **kwargs)

Bases: Scalar

A constant number.

Source code in pygx/algo/scalars/_base.py
def __init__(self, value: Any, **kwargs):
    super().__init__(**dict(value=value), **kwargs)

Division

Division(x: ScalarValue, y: ScalarValue, **kwargs)

Bases: BinaryOp

Divide operation.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, y: ScalarValue, **kwargs):
    super().__init__(**dict(x=x, y=y), **kwargs)

Floor

Floor(x: ScalarValue, **kwargs)

Bases: UnaryOp

Floor operator.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, **kwargs):
    super().__init__(**dict(x=x), **kwargs)

Lambda

Lambda(fn: Callable[[int], Any], **kwargs)

Bases: Scalar

Lambda operation.

Source code in pygx/algo/scalars/_base.py
def __init__(self, fn: Callable[[int], Any], **kwargs):
    super().__init__(**dict(fn=fn), **kwargs)

Mod

Mod(x: ScalarValue, y: ScalarValue, **kwargs)

Bases: BinaryOp

Mod operation.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, y: ScalarValue, **kwargs):
    super().__init__(**dict(x=x, y=y), **kwargs)

Multiplication

Multiplication(x: ScalarValue, y: ScalarValue, **kwargs)

Bases: BinaryOp

Multiply operation.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, y: ScalarValue, **kwargs):
    super().__init__(**dict(x=x, y=y), **kwargs)

Negation

Negation(x: ScalarValue, **kwargs)

Bases: UnaryOp

Negation operator.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, **kwargs):
    super().__init__(**dict(x=x), **kwargs)

Power

Power(x: ScalarValue, y: ScalarValue, **kwargs)

Bases: BinaryOp

Power operation.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, y: ScalarValue, **kwargs):
    super().__init__(**dict(x=x, y=y), **kwargs)

Scalar

Bases: Object

Interface for step-based scalar.

call abstractmethod

call(step: int) -> Any

Implementation. Subclass should override this method.

Source code in pygx/algo/scalars/_base.py
@abc.abstractmethod
def call(self, step: int) -> Any:
    """Implementation. Subclass should override this method."""

floor

floor()

Returns the floor of current scalar.

Source code in pygx/algo/scalars/_base.py
def floor(self):
    """Returns the floor of current scalar."""
    return Floor(x=self)

ceil

ceil()

Returns the ceiling of current scalar.

Source code in pygx/algo/scalars/_base.py
def ceil(self):
    """Returns the ceiling of current scalar."""
    return Ceiling(x=self)

Substraction

Substraction(x: ScalarValue, y: ScalarValue, **kwargs)

Bases: BinaryOp

Substract operation.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, y: ScalarValue, **kwargs):
    super().__init__(**dict(x=x, y=y), **kwargs)

UnaryOp

UnaryOp(x: ScalarValue, **kwargs)

Bases: Scalar

Unary scalar operators.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, **kwargs):
    super().__init__(**dict(x=x), **kwargs)

operate abstractmethod

operate(x: int | float) -> int | float

Implementation of the operation on a computed value.

Source code in pygx/algo/scalars/_base.py
@abc.abstractmethod
def operate(self, x: int | float) -> int | float:
    """Implementation of the operation on a computed value."""

Cosine

Cosine(x: ScalarValue, **kwargs)

Bases: UnaryOp

Cosine that works for scalars.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, **kwargs):
    super().__init__(**dict(x=x), **kwargs)

Exp

Exp(x: ScalarValue, **kwargs)

Bases: UnaryOp

More accurate version for math.e ** x.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, **kwargs):
    super().__init__(**dict(x=x), **kwargs)

Log

Log(x: ScalarValue, base: ScalarValue = e, **kwargs)

Bases: Scalar

A log scheduled float.

Source code in pygx/algo/scalars/_maths.py
def __init__(
    self,
    x: base.ScalarValue,  # pyright: ignore[reportInvalidTypeForm]
    base: base.ScalarValue = math.e,  # pylint: disable=redefined-outer-name  # pyright: ignore[reportInvalidTypeForm]
    **kwargs,
):
    super().__init__(**dict(x=x, base=base), **kwargs)

Sine

Sine(x: ScalarValue, **kwargs)

Bases: UnaryOp

Sine that works for scalars.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, **kwargs):
    super().__init__(**dict(x=x), **kwargs)

SquareRoot

SquareRoot(x: ScalarValue, **kwargs)

Bases: UnaryOp

The square root scalar.

Source code in pygx/algo/scalars/_base.py
def __init__(self, x: ScalarValue, **kwargs):
    super().__init__(**dict(x=x), **kwargs)

Gaussian

Gaussian(mean: float, std: float, **kwargs)

Bases: _MeanStdRandom

Generate a random float number in gaussian distribution.

Source code in pygx/algo/scalars/_randoms.py
def __init__(self, mean: float, std: float, **kwargs):
    super().__init__(**dict(mean=mean, std=std), **kwargs)

LogNormal

LogNormal(mean: float, std: float, **kwargs)

Bases: _MeanStdRandom

Generate a random float number in log normal distribution.

Source code in pygx/algo/scalars/_randoms.py
def __init__(self, mean: float, std: float, **kwargs):
    super().__init__(**dict(mean=mean, std=std), **kwargs)

Normal

Normal(mean: float, std: float, **kwargs)

Bases: _MeanStdRandom

Generate a random float number in normal distribution.

Source code in pygx/algo/scalars/_randoms.py
def __init__(self, mean: float, std: float, **kwargs):
    super().__init__(**dict(mean=mean, std=std), **kwargs)

RandomScalar

Bases: Scalar

Base class for random operation for computing scheduled value.

next_value abstractmethod

next_value() -> int | float

Return next value..

Source code in pygx/algo/scalars/_randoms.py
@abc.abstractmethod
def next_value(self) -> int | float:
    """Return next value.."""

Triangular

Triangular(
    low: int | float = 0.0,
    high: int | float = 1.0,
    mode: int | float | None = None,
    **kwargs
)

Bases: RandomScalar

Generate a random float number in a triangular distribution.

Source code in pygx/algo/scalars/_randoms.py
def __init__(
    self,
    low: int | float = 0.0,
    high: int | float = 1.0,
    mode: int | float | None = None,
    **kwargs,
):
    super().__init__(**dict(low=low, high=high, mode=mode), **kwargs)

Uniform

Uniform(low: int | float = 0.0, high: int | float = 1.0, **kwargs)

Bases: RandomScalar

Generate a random number in uniform distribution.

Source code in pygx/algo/scalars/_randoms.py
def __init__(
    self,
    low: int | float = 0.0,
    high: int | float = 1.0,
    **kwargs,
):
    super().__init__(**dict(low=low, high=high), **kwargs)

StepWise

StepWise(
    phases: list[tuple[int | float, Any]],
    total_steps: int | None = None,
    **kwargs
)

Bases: Scalar

A step-wise schedule that is specified via multiple phases.

Source code in pygx/algo/scalars/_step_wise.py
def __init__(
    self,
    phases: list[tuple[int | float, Any]],
    total_steps: int | None = None,
    **kwargs,
):
    super().__init__(
        **dict(phases=phases, total_steps=total_steps), **kwargs
    )

make_scalar

make_scalar(value: Any) -> Scalar

Make a scalar from a value.

Source code in pygx/algo/scalars/_base.py
def make_scalar(value: Any) -> 'Scalar':
    """Make a scalar from a value."""
    if isinstance(value, Scalar):
        return value
    elif callable(value):
        return Lambda(fn=value)  # pytype: disable=bad-return-type
    else:
        return Constant(value=value)  # pytype: disable=bad-return-type

scalar_spec

scalar_spec(value_spec: ValueSpec) -> ValueSpec

Returns the value spec for a schedule scalar.

Parameters:

Name Type Description Default
value_spec ValueSpec

a value spec for the schedule-based scalar type.

required

Returns:

Type Description
ValueSpec

A value spec for either the value itself or a callable that produces such value based on a step (integer).

Source code in pygx/algo/scalars/_base.py
def scalar_spec(value_spec: pg.typing.ValueSpec) -> pg.typing.ValueSpec:
    """Returns the value spec for a schedule scalar.

    Args:
      value_spec: a value spec for the schedule-based scalar type.

    Returns:
      A value spec for either the value itself or a callable that produces such
        value based on a step (integer).
    """
    return pg.typing.Union(
        [value_spec, pg.typing.Callable([pg.typing.Int()], returns=value_spec)]
    )

scalar_value

scalar_value(value: Any, step: int) -> Any

Returns a scheduled value based on a step.

Source code in pygx/algo/scalars/_base.py
def scalar_value(value: Any, step: int) -> Any:
    """Returns a scheduled value based on a step."""
    if callable(value):
        return value(step)
    return value

cosine_decay

cosine_decay(total_steps: int, start: float = 1.0, end: float = 0.0)

Returns a cosine decayed scalar from start to end.

Source code in pygx/algo/scalars/_maths.py
def cosine_decay(total_steps: int, start: float = 1.0, end: float = 0.0):
    """Returns a cosine decayed scalar from start to end."""
    return (
        0.5 * (start - end) * (1 + cos(math.pi * base.STEP / total_steps)) + end  # pyright: ignore[reportCallIssue]
    )

cyclic

cyclic(
    cycle: int,
    initial_radiant: float = 0.0,
    high: float = 1.0,
    low: float = 0.0,
)

Returns a cyclic scalar using sin/cos.

Source code in pygx/algo/scalars/_maths.py
def cyclic(
    cycle: int,
    initial_radiant: float = 0.0,
    high: float = 1.0,
    low: float = 0.0,
):
    """Returns a cyclic scalar using sin/cos."""
    return (
        0.5
        * (high - low)
        * (1 + cos(initial_radiant + math.pi * 2 * base.STEP / cycle))  # pyright: ignore[reportCallIssue]
        + low
    )

exponential_decay

exponential_decay(
    decay_rate: float,
    decay_interval: int,
    start: float = 1.0,
    staircase: bool = True,
)

Returns a scalar that exponentially decays from start to end.

Source code in pygx/algo/scalars/_maths.py
def exponential_decay(
    decay_rate: float,
    decay_interval: int,
    start: float = 1.0,
    staircase: bool = True,
):
    """Returns a scalar that exponentially decays from start to end."""
    exponent = base.STEP / float(decay_interval)
    if staircase:
        exponent = exponent.floor()
    return start * (decay_rate**exponent)

linear

linear(total_steps: int, start: float = 1.0, end: float = 0.0)

Returns a linear scalar from start to end.

Source code in pygx/algo/scalars/_maths.py
def linear(total_steps: int, start: float = 1.0, end: float = 0.0):
    """Returns a linear scalar from start to end."""
    return start + base.STEP * ((end - start) / total_steps)

options: show_root_heading: false show_root_toc_entry: false members_order: source heading_level: 2