← All examples The Mackey-Glass equation models the regulation of red blood cells and
becomes chaotic at the right delay. With β = 2, γ = 1, n = 9.65, τ = 2 it produces a classic chaotic time series that’s been used as a
benchmark in everything from neural networks to time-series forecasting.
y'(t) = β y(t-τ) / (1 + y(t-τ)^n) - γ y(t)
This example uses numra::dde::MethodOfSteps and prints the trajectory
at fixed intervals so you can plot it.
Run it:
cargo run --release --example mackey_glass numra/examples/mackey_glass.rs on GitHub ↗ · Related book chapter ↗
use numra :: dde :: { DdeOptions , DdeSolver , DdeSystem , MethodOfSteps };
/// Mackey-Glass equation
struct MackeyGlass {
/// Production rate
beta : f64 ,
/// Decay rate
gamma : f64 ,
/// Hill coefficient (nonlinearity)
n : f64 ,
/// Time delay
tau : f64 ,
}
impl DdeSystem < f64 > for MackeyGlass {
fn dim ( & self ) -> usize {
1
}
fn delays ( & self ) -> Vec < f64 > {
vec! [ self . tau]
}
fn rhs ( & self , _t : f64 , y : & [ f64 ], y_delayed : & [ & [ f64 ]], dydt : &mut [ f64 ]) {
let y_tau = y_delayed[ 0 ][ 0 ]; // y(t - tau)
// dy/dt = β * y(t-τ) / (1 + y(t-τ)^n) - γ * y(t)
dydt[ 0 ] = self . beta * y_tau / ( 1.0 + y_tau . powf ( self . n)) - self . gamma * y[ 0 ];
}
}
fn main () {
println! ( "=== Mackey-Glass Delay Differential Equation === \n " );
// Standard chaotic parameters
let system = MackeyGlass {
beta : 2.0 ,
gamma : 1.0 ,
n : 9.65 ,
tau : 2.0 ,
};
println! ( "Parameters:" );
println! ( " β (production rate): {}" , system . beta);
println! ( " γ (decay rate): {}" , system . gamma);
println! ( " n (Hill coefficient): {}" , system . n);
println! ( " τ (delay): {}" , system . tau);
println! ();
// Constant history function
let history = | _t : f64 | vec! [ 0.5 ];
// Solver options
let options = DdeOptions :: default ()
. rtol ( 1 e- 6 )
. atol ( 1 e- 9 )
. max_steps ( 100000 );
println! ( "Solving from t=0 to t=500... \n " );
let result = MethodOfSteps :: solve ( & system, 0.0 , 500.0 , & history, & options)
. expect ( "Failed to solve Mackey-Glass equation" );
println! ( "Solution computed successfully!" );
println! ( " Number of time points: {}" , result . len ());
println! ( " Accepted steps: {}" , result . stats . n_accept);
println! ( " Rejected steps: {}" , result . stats . n_reject);
println! ();
// Find min, max, and final value
let mut y_min = f64 :: INFINITY ;
let mut y_max = f64 :: NEG_INFINITY ;
for y in result . y . iter () {
if * y < y_min {
y_min = * y;
}
if * y > y_max {
y_max = * y;
}
}
let y_final = result . y_final () . unwrap ()[ 0 ];
println! ( "Solution statistics:" );
println! ( " Minimum y: {:.6}" , y_min);
println! ( " Maximum y: {:.6}" , y_max);
println! ( " Range: {:.6}" , y_max - y_min);
println! ( " Final y(500): {:.6}" , y_final);
println! ();
// Sample some values for the trajectory
println! ( "Sample trajectory points:" );
println! ( " {:>10} | {:>12}" , "t" , "y(t)" );
println! ( " {:-<10}|{:-<13}" , "" , "" );
let sample_times = [ 0.0 , 50.0 , 100.0 , 200.0 , 300.0 , 400.0 , 500.0 ];
let mut sample_idx = 0 ;
for (i, & t) in result . t . iter () . enumerate () {
if sample_idx < sample_times . len () && t >= sample_times[sample_idx] {
let y = result . y_at (i)[ 0 ];
println! ( " {:>10.1} | {:>12.6}" , t, y);
sample_idx += 1 ;
}
}
println! ();
println! ( "The Mackey-Glass equation with τ=2 exhibits chaotic oscillations." );
println! (
"The solution oscillates irregularly between approximately {} and {}." ,
y_min . round () as i32 ,
y_max . round () as i32
);
}