pub trait ArqSpec {
type S: Clone;
type F: Clone;
fn op(a: &Self::S, b: &Self::S) -> Self::S;
fn identity() -> Self::S;
fn compose(f: &Self::F, g: &Self::F) -> Self::F;
fn apply(f: &Self::F, a: &Self::S, size: i64) -> Self::S;
}
pub enum AssignMin {}
impl ArqSpec for AssignMin {
type S = i64;
type F = i64;
fn op(&a: &Self::S, &b: &Self::S) -> Self::S {
a.min(b)
}
fn identity() -> Self::S {
i64::max_value()
}
fn compose(&f: &Self::F, _: &Self::F) -> Self::F {
f
}
fn apply(&f: &Self::F, _: &Self::S, _: i64) -> Self::S {
f
}
}
pub enum AssignSum {}
impl ArqSpec for AssignSum {
type S = i64;
type F = i64;
fn op(&a: &Self::S, &b: &Self::S) -> Self::S {
a + b
}
fn identity() -> Self::S {
0
}
fn compose(&f: &Self::F, _: &Self::F) -> Self::F {
f
}
fn apply(&f: &Self::F, _: &Self::S, size: i64) -> Self::S {
f * size
}
}
pub enum SupplyDemand {}
impl ArqSpec for SupplyDemand {
type S = (i64, i64, i64); type F = (i64, i64);
fn op((p1, o1, s1): &Self::S, (p2, o2, s2): &Self::S) -> Self::S {
let extra = (p1 - s1).min(o2 - s2);
(p1 + p2, o1 + o2, s1 + s2 + extra)
}
fn identity() -> Self::S {
(0, 0, 0)
}
fn compose(_: &Self::F, _: &Self::F) -> Self::F {
unimplemented!()
}
fn apply(&(p_add, o_add): &Self::F, &(p, o, _): &Self::S, s: i64) -> Self::S {
assert_eq!(s, 1);
let p = p + p_add;
let o = o + o_add;
(p, o, p.min(o))
}
}