Skip to content

Rates

Rates are used to control the application frequency of alters. They can be static (fixed) or dynamic (changing over time). Radiate provides several built-in rate strategies to help you fine-tune the behavior of the alterers. Each mutator and crossover in Radiate accepts a rate parameter. In Python, the rate parameter can be either a float (for fixed rates) or an instance of the Rate class (for dynamic rates). In Rust, the rate parameter is anything that implements Into<Rate>. Beyond the fixed and scheduled rates below, a rate can also be driven by live metrics via an expression.

Every schedule exposes its value at a given generation through .value(i) — this is how the engine reads the current rate each generation, and how the curves below were plotted. For example, sampling a fixed rate across 100 generations:

import radiate as rd

rate = rd.Rate.fixed(0.1)

rates = []
for i in range(100):
    rates.append(rate.value(i))

Use the table below to pick a schedule, then see its section for the parameters and curve.

Strategy Behavior Reach for it when…
Fixed constant rate you want one steady rate (the default)
Linear smooth ramp from start → end you want to shift exploration ↔ exploitation gradually
Stepwise jumps to a new rate at set generations your run has distinct phases
Sine Cyclical smooth oscillation between min/max you want to periodically re-inject exploration (escape local optima)
Triangular Cyclical oscillation with linear ramps same as sine, but with sharper turns
Exponential fast change that levels off you want a high starting rate to decay quickly

Fixed

  • Purpose: Applies a constant rate throughout the evolution process - this is the default behavior and can be thought of as the "standard" rate.
import radiate as rd

rate = rd.Rate.fixed(0.1)
let fixed_rate = Rate::Fixed(0.01);
fixed rate

Linear

  • Purpose: Gradually changes the rate from a starting value to an ending value over a specified duration, allowing for a smooth transition in the application frequency of the alterer.
import radiate as rd

rate = rd.Rate.linear(start=0.1, end=0.9, duration=25)
// start, end, steps
let linear_rate = Rate::Linear(0.1, 0.001, 100);
linear rate

Stepwise

  • Purpose: Changes the rate at specified intervals, allowing for abrupt changes in the application frequency of the alterer.
import radiate as rd

steps = [(0, 0.1), (25, 0.5), (75, 0.9)]
rate = rd.Rate.stepwise(steps)
// vec [(step_idx, rate)]
let steps = vec![(0, 0.1), (25, 0.5), (75, 0.9)];
let step_rate = Rate::Stepwise(steps);
stepwise

Sine Cyclical

  • Purpose: Oscillates the rate between a minimum and maximum value over a specified period, allowing for periodic changes in the application frequency of the alterer.
import radiate as rd

rate = rd.Rate.sine(min=0.1, max=0.9, periods=10)
// min, max, period, shape
let sine_rate = Rate::Cyclical(0.1, 0.9, 25, rate::CycleShape::Sine);
sine

Triangular Cyclical

  • Purpose: Oscillates the rate between a minimum and maximum value over a specified period using a triangular wave, allowing for periodic changes in the application frequency of the alterer.
import radiate as rd

rate = rd.Rate.triangular(min=0.1, max=0.9, periods=10)
// min, max, period, shape
let triangular_rate = Rate::Cyclical(0.1, 0.9, 25, rate::CycleShape::Triangle);
triangular

Exponential

  • Purpose: Changes the rate exponentially from a starting value to an ending value with a specified half-life, allowing for rapid changes in the application frequency of the alterer.
import radiate as rd

rate = rd.Rate.exp(start=0.5, end=0.1, half_life=25)
// start, end, half_life
let exp_rate = Rate::Exponential(0.5, 0.1, 25);
exp