fuzzytags-sim/src/oracle.rs

125 lines
4.6 KiB
Rust
Raw Normal View History

2021-02-03 13:05:59 +00:00
// todo would be neat to just make this a subscriber of the tracing log, but there doesn't
// seem to be a nice way for that API to do what we want.. so until then...
2021-02-03 22:46:52 +00:00
use hashbrown::HashMap;
2021-02-03 13:05:59 +00:00
use rand::{thread_rng, Rng};
use std::fs::File;
use std::io::Write;
2021-02-10 07:23:50 +00:00
use rand_distr::num_traits::FloatConst;
2021-02-03 13:05:59 +00:00
#[derive(Clone)]
pub struct Event {
sender: String,
intended_receiver: String,
entangled_receiver: Option<String>,
confidence: f64
2021-02-03 13:05:59 +00:00
}
#[derive(Clone)]
pub struct Oracle {
parties: Vec<String>,
actual_events: Vec<Event>,
}
impl Oracle {
pub fn new() -> Oracle {
Oracle {
parties: vec![],
actual_events: vec![],
}
}
pub fn register_party(&mut self, party: String) {
self.parties.push(party);
}
pub fn add_event(&mut self, sender: String, intended_receiver: String, entangled_receiver: Option<String>, confidence: f64) {
2021-02-03 13:05:59 +00:00
self.actual_events.push(Event {
sender,
intended_receiver,
entangled_receiver,
confidence,
2021-02-03 13:05:59 +00:00
});
}
pub fn compile_to_dot(&self, filename: &str, strict: bool, inverse: bool, max: f64) -> f64 {
2021-02-03 13:05:59 +00:00
let mut output = File::create(filename).unwrap();
write!(output, "strict digraph {{\n");
2021-02-03 13:05:59 +00:00
write!(
output,
r##"
K=1.3;
repulsiveforce=0.00001;
dpi=2400;
bgcolor = "#111111ff";
"##
2021-02-03 13:05:59 +00:00
);
2021-02-10 07:23:50 +00:00
for (i, party) in self.parties.iter().enumerate() {
let x = (((f64::PI()*2.0)/self.parties.len() as f64) * (i as f64)).cos()*10.0;
let y = (((f64::PI()*2.0)/self.parties.len() as f64) * (i as f64)).sin()*10.0;
2021-02-03 13:05:59 +00:00
let r = hex::decode(party).unwrap()[0];
let g = hex::decode(party).unwrap()[1];
let b = hex::decode(party).unwrap()[2];
writeln!(output, "\"{}\" [shape=point, penwidth=0, fixedsize=true, width=0.005,height=0.005,peripheries=0,style=\"filled,setlinewidth(0)\", color=\"#{:02x}{:02x}{:02x}\"]", party, r, g, b);
//writeln!(output, "\"{}\" [shape=point, color=\"#{:x}{:x}{:x}\",pos=\"{},{}!\"]", party, r, g, b,x,y);
2021-02-03 13:05:59 +00:00
}
let mut real_connection_map: HashMap<(String, String), f64> = HashMap::new();
let mut entangled_connection_map: HashMap<(String, String), f64> = HashMap::new();
let mut max_conn = 1.0;
2021-02-03 13:05:59 +00:00
for event in self.actual_events.iter() {
2021-02-03 22:46:52 +00:00
let key = (event.sender.clone(), event.intended_receiver.clone());
if real_connection_map.contains_key(&key) {
*real_connection_map.get_mut(&key).unwrap() += (1.0 * (1.0-event.confidence));
2021-02-03 22:46:52 +00:00
if real_connection_map[&key] > max_conn {
max_conn = real_connection_map[&key];
}
} else {
real_connection_map.insert(key, 1.0 * (1.0-event.confidence));
2021-02-03 22:46:52 +00:00
}
2021-02-03 13:05:59 +00:00
match &event.entangled_receiver {
Some(entangled_receiver) => {
2021-02-03 22:46:52 +00:00
let key = (event.sender.clone(), entangled_receiver.clone());
if entangled_connection_map.contains_key(&key) {
*entangled_connection_map.get_mut(&key).unwrap() += 1.0;
2021-02-03 22:46:52 +00:00
if entangled_connection_map[&key] > max_conn {
max_conn = entangled_connection_map[&key];
}
} else {
entangled_connection_map.insert(key, 1.0);
2021-02-03 22:46:52 +00:00
}
2021-02-03 13:05:59 +00:00
}
_ => {}
};
}
2021-02-03 22:46:52 +00:00
for ((sender, receiver), size) in real_connection_map.iter() {
let normalized = (*size as f64 / max_conn as f64);
let mut transparency = (normalized * 64.0) as u8 + 172;
let mut penwidth = (normalized * 0.01) as f64;
2021-02-10 07:23:50 +00:00
2021-02-03 22:46:52 +00:00
writeln!(
output,
"\"{}\" -> \"{}\" [arrowhead=none, penwidth={}, color=\"#ffffff{:02x}\", weight={}]",
sender, receiver, f64::max(0.005, penwidth), transparency, penwidth
2021-02-03 22:46:52 +00:00
);
}
for ((sender, receiver), size) in entangled_connection_map.iter() {
let normalized = (*size as f64 / max_conn as f64);
2021-02-10 07:23:50 +00:00
let transparency = (normalized * 172.0) as u8 + 64;
let penwidth = ((normalized * 32.0) as f64).log2();
2021-02-03 22:46:52 +00:00
writeln!(
output,
"\"{}\" -> \"{}\" [arrowhead=none, style=dashed, penwidth={}, color=\"#ffffff{:02x}\"]",
2021-02-03 22:46:52 +00:00
sender, receiver, penwidth, transparency
);
}
2021-02-03 13:05:59 +00:00
write!(output, "}}");
2021-02-10 07:23:50 +00:00
max_conn
2021-02-03 13:05:59 +00:00
}
}