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
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
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
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(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
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)
|