Created
January 28, 2020 06:33
-
-
Save makoConstruct/0c835eda538cd772fcf75bd61699a627 to your computer and use it in GitHub Desktop.
a battery of tests for comparing different mathematical specifications of comparison aggregation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait MetricaWire { | |
fn sign(&self)-> f32; | |
// fn controversy(&self)-> f32; | |
// fn certainty(&self)-> f32; | |
fn negate(&self)-> Self; | |
fn zero()-> Self; | |
fn unit()-> Self; | |
fn of_strength(v:f32)-> Self; | |
} | |
trait Metrica { | |
type Wire:MetricaWire; | |
fn serial(&self, a: &Self::Wire, b: &Self::Wire)-> Self::Wire; | |
fn parallel(&self, a: &Self::Wire, b: &Self::Wire)-> Self::Wire; | |
// fn triangle_to_y(&self, a: &Wire, b: &Wire, c: &Wire)-> (Wire, Wire, Wire); //anticlockwise | |
} | |
fn equalish(a:f32, b:f32)-> bool { | |
(a - b).abs() < 0.00001 | |
} | |
// I can't fucking do this | |
// this was supposed to allow you to build wire reduction expressions by typing things like "p(p(1 1) s(1 p(2 2)))". But macros are too horrible to work for that. | |
// macro_rules! reduction_test { | |
// ($M:ty, $m:expr) => (); | |
// ($M:ty, $m:expr, u) => { | |
// &<$M>::Wire::unit() | |
// }; | |
// ($M:ty, $m:expr, (p )) => (); | |
// ($M:ty, $m:expr, (p $first:tt )) => { | |
// reduction_test!($M, $m, $first) | |
// }; | |
// ($M:ty, $m:expr, (p $first:tt, $($ir:tt),+ )) => { | |
// &$m.parallel( | |
// reduction_test!($M, $m, $first), | |
// reduction_test!($M, $m, (p $($ir),* )) | |
// ) | |
// }; | |
// ($M:ty, $m:expr, (p $($ir:tt),* ), $($rest:tt),*) => { | |
// reduction_test!($M, $m, (p $($ir),* )) | |
// reduction_test!($M, $m, $($rest),*) | |
// }; | |
// ($M:ty, $m:expr, (s )) => (); | |
// ($M:ty, $m:expr, (s $first:tt )) => { | |
// reduction_test!($M, $m, $first) | |
// }; | |
// ($M:ty, $m:expr, (s $first:tt, $($ir:tt),+ )) => { | |
// &$m.serial( | |
// reduction_test!($M, $m, $first), | |
// reduction_test!($M, $m, (s $($ir),* )) | |
// ) | |
// }; | |
// ($M:ty, $m:expr, (s $($ir:tt),* ), $($rest:tt),*) => { | |
// reduction_test!($M, $m, (s $($ir),* )) | |
// reduction_test!($M, $m, $($rest),*) | |
// }; | |
// ($M:ty, $m:expr, $n:expr) => { | |
// &<$M>::Wire::of_strength($n as f32) | |
// }; | |
// } | |
macro_rules! test { | |
{$name:expr, $handler:ident, $($test:expr,)*} => { | |
$( | |
if !($test) { | |
if $handler(format!("{}:{}", $name, stringify!($test))) { | |
return; | |
} | |
} | |
)* | |
}; | |
} | |
fn test_metrica<M:Metrica, F:FnMut(String)-> bool>(m:&M, mut error_handler:F){ | |
let nunit = M::Wire::unit(); | |
let ndub = M::Wire::of_strength(2f32); | |
// a b | |
test!{ | |
"single edge", error_handler, | |
m.serial(&nunit, &nunit).sign() > 0.0, | |
m.parallel( | |
&m.serial(&nunit, &nunit), | |
&m.serial(&nunit, &nunit), | |
).sign() > 0.0, | |
}; | |
// a b | |
// b c | |
// c a | |
test!{ | |
"tricycle", error_handler, | |
//comparing a c | |
equalish(m.parallel(&m.serial(&nunit, &nunit), &nunit.negate()).sign(), 0.0), | |
}; | |
// a b | |
// c b | |
// d a | |
// d c | |
test!{ | |
"forward square", error_handler, | |
// d < a | |
m.parallel( | |
&m.serial(&nunit, &nunit), | |
&m.serial(&nunit, &nunit), | |
).sign() > 0.0, | |
// a == c | |
equalish(m.parallel( | |
&m.serial(&nunit.negate(), &nunit), | |
&m.serial(&nunit, &nunit.negate()), | |
).sign(), 0.0), | |
// c < b | |
m.parallel( | |
&nunit, | |
&m.serial(&m.serial(&nunit.negate(), &nunit), &nunit), | |
).sign() > 0.0, | |
}; | |
// a b | |
// b c | |
// c a 2 | |
test!{ | |
"tri strong return", error_handler, | |
// c < b | |
m.parallel( | |
&nunit.negate(), | |
&m.serial(&ndub, &nunit) | |
).sign() > 0.0, | |
// b < a | |
m.parallel( | |
&nunit.negate(), | |
&m.serial(&nunit, &ndub) | |
).sign() > 0.0, | |
}; | |
// a b 2 | |
// b c | |
// c d 2 | |
// d a | |
test!{ | |
"uneven cycle square", error_handler, | |
// a == c | |
equalish(m.parallel( | |
&m.serial(&ndub, &nunit), | |
&m.serial(&nunit.negate(), &ndub.negate()), | |
).sign(), 0.0), | |
// a < b | |
m.parallel( | |
&ndub, | |
&m.serial(&m.serial(&nunit.negate(), &ndub.negate()), &nunit.negate()), | |
).sign() > 0.0, | |
} | |
// a b c | |
// c e1 | |
// c e2 | |
// c e3 | |
// c e4 | |
test!{ | |
"broom", error_handler, | |
equalish() | |
} | |
} | |
fn print_test_metrica<M:Metrica>(m:&M){ | |
let counter = |v:String|-> bool { | |
println!("failure: {}", &v); | |
false | |
}; | |
test_metrica(m, counter); | |
} | |
fn count_test_metrica<M:Metrica>(m:&M)-> usize { | |
let mut count = 0; | |
let counter = |_:String|-> bool { | |
count += 1; | |
false | |
}; | |
test_metrica(m, counter); | |
count | |
} | |
fn strict_test_metrica<M:Metrica>(m:&M)-> bool { | |
let mut count = false; | |
let counter = |_:String|-> bool { | |
count = true; | |
true | |
}; | |
test_metrica(m, counter); | |
count | |
} | |
struct DuWire { | |
up: f32, | |
down: f32, | |
} | |
struct DuMetric(); | |
impl MetricaWire for DuWire { | |
fn sign(&self)-> f32 { self.up - self.down } | |
// fn controversy(&self)-> f32 { (self.up + self.down)/(self.up - self.down).abs() } //1 is minimum, infinite is maximum | |
// fn certainty(&self)-> f32 { log((self.up + self.down)/self.controversy()) } | |
fn negate(&self)-> Self { DuWire{ up:self.down, down:self.up } } | |
fn zero()-> Self { DuWire{ up:0.0, down:0.0 } } | |
fn unit()-> Self { DuWire{ up:1.0, down:0.0 } } | |
fn of_strength(v:f32)-> Self { | |
if v >= 0.0 { | |
DuWire{ up:v, down:0.0 } | |
}else{ | |
DuWire{ up:0.0, down:-v } | |
} | |
} | |
} | |
impl Metrica for DuMetric { | |
type Wire = DuWire; | |
fn serial(&self, a: &Self::Wire, b: &Self::Wire)-> Self::Wire { DuWire{ up: a.up.min(b.up), down: a.down.min(b.down) } } | |
fn parallel(&self, a: &Self::Wire, b: &Self::Wire)-> Self::Wire { DuWire{ up: a.up + b.up, down: a.down + b.down } } | |
// fn triangle_to_y(&self, a: &Wire, b: &Wire, c: &Wire)-> (Wire, Wire, Wire) { } //anticlockwise | |
} | |
struct AvMetric(); | |
impl Metrica for AvMetric { | |
type Wire = DuWire; | |
fn serial(&self, a: &Self::Wire, b: &Self::Wire)-> Self::Wire { | |
let ap = a.up + a.down; | |
let bp = b.up + b.down; | |
let tp = ap + bp; | |
DuWire{ | |
up: (a.up*ap + b.up*bp)/tp, | |
down: (a.down*ap + b.down*bp)/tp, | |
} | |
} | |
fn parallel(&self, a: &Self::Wire, b: &Self::Wire)-> Self::Wire { DuWire{ up: a.up + b.up, down: a.down + b.down } } | |
// fn triangle_to_y(&self, a: &Wire, b: &Wire, c: &Wire)-> (Wire, Wire, Wire) { } //anticlockwise | |
} | |
fn main(){ | |
print_test_metrica(&AvMetric()); | |
// let m = DuMetric(); | |
// let nunit = <DuMetric as Metrica>::Wire::unit(); | |
// println!("{}", m.parallel(&m.serial(&nunit, &nunit), &nunit.negate()).sign()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment