use arco::rules::{NoContext, Rule};
use arco::schedule::Schedule;
use arco::state::State;
use rand::{Rng, RngExt, SeedableRng};
use std::fmt;
use std::hash::{Hash, Hasher};
#[derive(Clone)]
struct Counter {
value: u8,
max_value: u8,
}
impl Counter {
fn new(value: u8, max_value: u8) -> Self {
assert!(value <= max_value);
Self { value, max_value }
}
#[allow(dead_code)]
fn increment(&self) -> Self {
if self.value >= self.max_value {
Self { value: 0, ..*self }
} else {
Self {
value: self.value + 1,
..*self
}
}
}
#[allow(dead_code)]
fn reset(&self) -> Self {
Self { value: 0, ..*self }
}
}
impl State for Counter {
type Encoding = Vec<u8>;
fn canonical_encoding(&self) -> Self::Encoding {
vec![self.value, self.max_value]
}
fn distance(&self, other: &Self) -> u32 {
let mut diff = 0u32;
if self.value != other.value {
diff += 1;
}
if self.max_value != other.max_value {
diff += 1;
}
diff
}
}
impl PartialEq for Counter {
fn eq(&self, other: &Self) -> bool {
self.value == other.value && self.max_value == other.max_value
}
}
impl Eq for Counter {}
impl Hash for Counter {
fn hash<H: Hasher>(&self, state: &mut H) {
self.value.hash(state);
self.max_value.hash(state);
}
}
impl fmt::Debug for Counter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Counter({}/{})", self.value, self.max_value)
}
}
impl fmt::Display for Counter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.value)
}
}
#[derive(Debug, Clone)]
struct IncrementRule;
impl Rule<Counter> for IncrementRule {
type Context = NoContext;
fn name(&self) -> &str {
"Increment"
}
fn apply(&self, state: &Counter, _ctx: &NoContext, _rng: &mut dyn Rng) -> Counter {
state.increment()
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
struct ResetRule;
impl Rule<Counter> for ResetRule {
type Context = NoContext;
fn name(&self) -> &str {
"Reset"
}
fn apply(&self, state: &Counter, _ctx: &NoContext, _rng: &mut dyn Rng) -> Counter {
state.reset()
}
}
#[derive(Debug, Clone, Default)]
struct SequentialSchedule;
impl Schedule<Counter, IncrementRule> for SequentialSchedule {
fn name(&self) -> &str {
"sequential"
}
fn timing(&self) -> &str {
"asynchronous"
}
fn selection(&self) -> &str {
"exhaustive"
}
fn step(&self, state: &Counter, rules: &[IncrementRule], rng: &mut dyn Rng) -> Counter {
let mut current = state.clone();
let ctx = NoContext;
for rule in rules {
current = rule.apply(¤t, &ctx, rng);
}
current
}
}
#[derive(Debug, Clone, Default)]
struct RandomRuleSchedule;
impl Schedule<Counter, IncrementRule> for RandomRuleSchedule {
fn name(&self) -> &str {
"random_rule"
}
fn timing(&self) -> &str {
"asynchronous"
}
fn selection(&self) -> &str {
"stochastic"
}
fn step(&self, state: &Counter, rules: &[IncrementRule], rng: &mut dyn Rng) -> Counter {
if rules.is_empty() {
return state.clone();
}
let idx = rng.random_range(0..rules.len());
let ctx = NoContext;
rules[idx].apply(state, &ctx, rng)
}
}
fn main() {
println!("=== Example 04: Custom Schedules ===\n");
let state = Counter::new(0, 5);
let rules = vec![IncrementRule, IncrementRule, IncrementRule];
let mut rng = rand::rngs::StdRng::seed_from_u64(42);
let seq = SequentialSchedule;
let s1 = seq.step(&state, &rules, &mut rng);
println!("Sequential schedule (3 Increment rules):");
println!(" Start: {}", state);
println!(" After 1 step: {} (incremented 3 times)", s1);
let rand_sched = RandomRuleSchedule;
print!("\nRandom schedule (10 timesteps): ");
let mut current = state.clone();
for _ in 0..10 {
current = rand_sched.step(¤t, &rules, &mut rng);
print!("{} ", current);
}
println!();
println!(" (each step applies one random increment)");
println!("\nSchedule metadata:");
println!(
" Sequential: {} ({}, {})",
seq.name(),
seq.timing(),
seq.selection()
);
println!(
" Random: {} ({}, {})",
rand_sched.name(),
rand_sched.timing(),
rand_sched.selection()
);
println!("\n✓ Two schedules implemented:");
println!(" - SequentialSchedule: applies every rule, in order");
println!(" - RandomRuleSchedule: picks one rule at random");
}