wip: coeff

This commit is contained in:
Youngjoon Lee 2024-09-09 09:01:01 +09:00
parent 2e26142ab5
commit c8ed2fa304
No known key found for this signature in database
GPG Key ID: 167546E2D1712F8C
8 changed files with 322 additions and 294 deletions

View File

@ -0,0 +1,274 @@
use ordering::message::{DataMessage, SenderIdx};
pub enum Entry {
Data(DataMessage),
Noise(u32), // the number of consecutive noises
}
fn load_sequence(path: &str) -> Vec<Entry> {
let mut entries: Vec<Entry> = Vec::new();
let mut reader = csv::ReaderBuilder::new()
.has_headers(false)
.from_path(path)
.unwrap();
for result in reader.records() {
let record = result.unwrap();
let value = &record[0];
if let Ok(num) = value.parse::<i32>() {
assert!(num < 0);
entries.push(Entry::Noise(num.unsigned_abs()));
} else {
entries.push(Entry::Data(parse_data_msg(value)));
}
}
entries
}
fn parse_data_msg(value: &str) -> DataMessage {
let parts: Vec<&str> = value.split(':').collect();
assert_eq!(parts.len(), 2);
DataMessage {
sender: parts[0].parse::<SenderIdx>().unwrap(),
msg_id: parts[1].parse::<u32>().unwrap(),
}
}
pub fn casual_coeff(seq1: &[Entry], seq2: &[Entry]) -> u64 {
let mut i = 0;
let mut j = 0;
let mut coeff = 0;
while i < seq1.len() && j < seq2.len() {
let mut found_pair = false;
if let (Entry::Data(msg1), Entry::Data(msg2)) = (&seq1[i], &seq2[j]) {
if msg1 == msg2 {
// Try to find the next pair of Data messages
let mut next_i = i + 1;
let mut next_j = j + 1;
while next_i < seq1.len() && next_j < seq2.len() {
match (&seq1[next_i], &seq2[next_j]) {
// If there's matching noise, continue to the next element
(Entry::Noise(n1), Entry::Noise(n2)) => {
if n1 == n2 {
next_i += 1;
next_j += 1;
} else {
break;
}
}
// If there's a matching Data message, count the pair
(Entry::Data(next_msg1), Entry::Data(next_msg2)) => {
if next_msg1 == next_msg2 {
coeff += 1; // Count the adjacent pair
i = next_i; // Move i and j to the next DataMessage
j = next_j;
found_pair = true;
}
break;
}
_ => break,
}
}
}
}
// Increment only if no matching pair was found
if !found_pair {
i += 1;
j += 1;
}
}
coeff
}
fn weak_coeff(seq1: &[Entry], seq2: &[Entry]) -> u64 {
let mut i = 0;
let mut j = 0;
let mut coeff = 0;
while i < seq1.len() && j < seq2.len() {
// Skip noise in both sequences
while i < seq1.len() && matches!(seq1[i], Entry::Noise(_)) {
i += 1;
}
while j < seq2.len() && matches!(seq2[j], Entry::Noise(_)) {
j += 1;
}
// Compare the DataMessages
if i < seq1.len() && j < seq2.len() {
if let (Entry::Data(msg1), Entry::Data(msg2)) = (&seq1[i], &seq2[j]) {
if msg1 == msg2 {
// Now check the next pair
let mut next_i = i + 1;
let mut next_j = j + 1;
// Skip noise in both sequences for the next pair
while next_i < seq1.len() && matches!(seq1[next_i], Entry::Noise(_)) {
next_i += 1;
}
while next_j < seq2.len() && matches!(seq2[next_j], Entry::Noise(_)) {
next_j += 1;
}
// If the next pair of DataMessages match, count it
if next_i < seq1.len() && next_j < seq2.len() {
if let (Entry::Data(next_msg1), Entry::Data(next_msg2)) =
(&seq1[next_i], &seq2[next_j])
{
if next_msg1 == next_msg2 {
coeff += 1; // Found a matching adjacent pair
i = next_i;
j = next_j;
continue;
}
}
}
}
}
}
i += 1;
j += 1;
}
coeff
}
fn main() {
let seq1 = load_sequence("/Users/yjlee/repos/nomos-simulations/mixnet-rs/results/ordering_e5s1_PureCoinFlipping_2024-09-01T19:30:03.957310+00:00_0d0h12m25s/paramset_1/iteration_0_0d0h0m2s/sent_seq_0.csv");
let seq2 = load_sequence("/Users/yjlee/repos/nomos-simulations/mixnet-rs/results/ordering_e5s1_PureCoinFlipping_2024-09-01T19:30:03.957310+00:00_0d0h12m25s/paramset_1/iteration_0_0d0h0m2s/recv_seq_0.csv");
println!("casual:{:?}", casual_coeff(&seq1, &seq2));
println!("weak:{:?}", weak_coeff(&seq1, &seq2));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_casual_coeff() {
// Empty sequences
assert_eq!(casual_coeff(&[], &[]), 0);
// One matching pair without noise
let seq = vec![data(1), data(2)];
assert_eq!(casual_coeff(&seq, &seq), 1);
// One matching pair with noise
let seq = vec![data(1), noise(10), data(2)];
assert_eq!(casual_coeff(&seq, &seq), 1);
// One matching pair without noise from different sequences
let seq1 = vec![data(1), data(2), data(3)];
let seq2 = vec![data(1), data(2), data(4)];
assert_eq!(casual_coeff(&seq1, &seq2), 1);
let seq1 = vec![data(4), data(2), data(3)];
let seq2 = vec![data(1), data(2), data(3)];
assert_eq!(casual_coeff(&seq1, &seq2), 1);
// One matching pair with noise from different sequences
let seq1 = vec![data(1), noise(10), data(2), data(3)];
let seq2 = vec![data(1), noise(10), data(2), data(4)];
assert_eq!(casual_coeff(&seq1, &seq2), 1);
let seq1 = vec![data(4), data(2), noise(10), data(3)];
let seq2 = vec![data(1), data(2), noise(10), data(3)];
assert_eq!(casual_coeff(&seq1, &seq2), 1);
// Two pairs with noise
let seq1 = vec![data(1), noise(10), data(2), data(3)];
let seq2 = vec![data(1), noise(10), data(2), data(3), data(4)];
assert_eq!(casual_coeff(&seq1, &seq2), 2);
// No match
let seq1 = vec![data(1), data(2)];
let seq2 = vec![data(2), data(3)];
assert_eq!(casual_coeff(&seq1, &seq2), 0);
let seq1 = vec![data(1), data(2)];
let seq2 = vec![data(3), data(4)];
assert_eq!(casual_coeff(&seq1, &seq2), 0);
// No match because of noise
let seq1 = vec![data(1), noise(10), data(2)];
let seq2 = vec![data(1), data(2)];
assert_eq!(casual_coeff(&seq1, &seq2), 0);
let seq1 = vec![data(1), noise(10), data(2)];
let seq2 = vec![data(1), noise(5), data(2)];
assert_eq!(casual_coeff(&seq1, &seq2), 0);
// No match because of mixed order
let seq1 = vec![data(1), data(2), data(3)];
let seq2 = vec![data(2), data(3), data(4)];
assert_eq!(casual_coeff(&seq1, &seq2), 0);
}
#[test]
fn test_weak_coeff() {
// Empty sequences
assert_eq!(weak_coeff(&[], &[]), 0);
// One matching pair without noise
let seq = vec![data(1), data(2)];
assert_eq!(weak_coeff(&seq, &seq), 1);
// One matching pair with noise
let seq = vec![data(1), noise(10), data(2)];
assert_eq!(weak_coeff(&seq, &seq), 1);
// One matching pair without noise from different sequences
let seq1 = vec![data(1), data(2), data(3)];
let seq2 = vec![data(1), data(2), data(4)];
assert_eq!(weak_coeff(&seq1, &seq2), 1);
let seq1 = vec![data(4), data(2), data(3)];
let seq2 = vec![data(1), data(2), data(3)];
assert_eq!(weak_coeff(&seq1, &seq2), 1);
// One matching pair with noise from different sequences
let seq1 = vec![data(1), noise(10), data(2), data(3)];
let seq2 = vec![data(1), noise(5), data(2), data(4)];
assert_eq!(weak_coeff(&seq1, &seq2), 1);
let seq1 = vec![data(4), data(2), noise(10), data(3)];
let seq2 = vec![data(1), data(2), noise(5), data(3)];
assert_eq!(weak_coeff(&seq1, &seq2), 1);
let seq1 = vec![data(4), data(2), noise(10), data(3)];
let seq2 = vec![data(1), data(2), data(3)];
assert_eq!(weak_coeff(&seq1, &seq2), 1);
// Two pairs with noise
let seq1 = vec![data(1), noise(10), data(2), data(3)];
let seq2 = vec![data(1), noise(5), data(2), data(3), data(4)];
assert_eq!(weak_coeff(&seq1, &seq2), 2);
// No match
let seq1 = vec![data(1), data(2)];
let seq2 = vec![data(2), data(3)];
assert_eq!(weak_coeff(&seq1, &seq2), 0);
let seq1 = vec![data(1), data(2)];
let seq2 = vec![data(3), data(4)];
assert_eq!(weak_coeff(&seq1, &seq2), 0);
// No match because of mixed order
let seq1 = vec![data(1), data(2), data(3)];
let seq2 = vec![data(2), data(3), data(4)];
assert_eq!(weak_coeff(&seq1, &seq2), 0);
// One pair despite mixed order, because the order is mixed due to only noises.
let seq1 = vec![data(1), data(2), data(3)];
let seq2 = vec![noise(10), data(1), data(2)];
assert_eq!(weak_coeff(&seq1, &seq2), 1);
}
fn data(msg_id: u32) -> Entry {
Entry::Data(DataMessage { sender: 0, msg_id })
}
fn noise(count: u32) -> Entry {
Entry::Noise(count)
}
}

View File

@ -9,11 +9,11 @@ use rustc_hash::FxHashMap;
use crate::{
format_duration,
message::{DataMessage, DataMessageGenerator},
outputs::Outputs,
paramset::ParamSet,
topology::{build_random_network, build_striped_network, RECEIVER_NODE_ID},
};
use ordering::message::{DataMessage, DataMessageGenerator};
pub struct Iteration {
pub paramset: ParamSet,

View File

@ -0,0 +1 @@
pub mod message;

View File

@ -1,8 +1,7 @@
mod iteration;
mod message;
mod ordercoeff;
mod outputs;
mod paramset;
mod sequence;
mod topology;
use std::{

View File

@ -1,285 +0,0 @@
use std::fs::File;
use crate::message::DataMessage;
#[derive(Debug)]
pub struct SequenceWriter {
noise_buf: u32,
writer: csv::Writer<File>,
}
impl SequenceWriter {
pub fn new(path: &str) -> Self {
Self {
noise_buf: 0,
writer: csv::Writer::from_path(path).unwrap(),
}
}
pub fn flush(&mut self) {
self.clear_buf();
self.writer.flush().unwrap();
}
fn clear_buf(&mut self) {
if self.noise_buf > 0 {
self.writer
.write_record(&[format!("-{}", self.noise_buf)])
.unwrap();
self.noise_buf = 0;
}
}
pub fn add_message(&mut self, msg: &DataMessage) {
self.clear_buf();
self.writer.write_record(&[msg.to_string()]).unwrap();
}
pub fn add_noise(&mut self) {
self.noise_buf += 1;
}
}
// impl Sequence {
// pub fn ordering_coefficient(&self, other: &Sequence, casual: bool) -> u64 {
// let mut coeff = 0;
// let mut i = 0;
// while i < self.0.len() {
// if let Entry::Data(_) = &self.0[i] {
// let (c, next_i) = self.ordering_coefficient_from(i, other, casual);
// coeff += c;
// if next_i != i {
// i = next_i;
// } else {
// i += 1;
// }
// } else {
// i += 1;
// }
// }
// coeff
// }
// fn ordering_coefficient_from(
// &self,
// start_idx: usize,
// other: &Sequence,
// casual: bool,
// ) -> (u64, usize) {
// let msg1 = match self.0[start_idx] {
// Entry::Data(msg) => msg,
// _ => panic!("Entry at {start_idx} must be Message"),
// };
// for (j, entry) in other.iter().enumerate() {
// if let Entry::Data(msg2) = entry {
// if msg1 == *msg2 {
// // Found the 1st matching msg. Start finding the next adjacent matching msg.
// if casual {
// return self.casual_ordering_coefficient_from(start_idx, other, j);
// } else {
// return self.weak_ordering_coefficient_from(start_idx, other, j);
// }
// }
// }
// }
// (0, start_idx)
// }
// fn casual_ordering_coefficient_from(
// &self,
// start_idx: usize,
// other: &Sequence,
// other_start_idx: usize,
// ) -> (u64, usize) {
// let mut coeff = 0;
// let mut i = start_idx + 1;
// let mut j = other_start_idx + 1;
// while i < self.0.len() && j < other.0.len() {
// match (&self.0[i], &other.0[j]) {
// (Entry::Noise(cnt1), Entry::Noise(cnt2)) => {
// if cnt1 == cnt2 {
// i += 1;
// j += 1;
// } else {
// break;
// }
// }
// (Entry::Data(msg1), Entry::Data(msg2)) => {
// if msg1 == msg2 {
// coeff += 1;
// i += 1;
// j += 1;
// } else {
// break;
// }
// }
// _ => break,
// }
// }
// (coeff, i)
// }
// fn weak_ordering_coefficient_from(
// &self,
// start_idx: usize,
// other: &Sequence,
// other_start_idx: usize,
// ) -> (u64, usize) {
// let mut coeff = 0;
// let mut i = start_idx + 1;
// let mut j = other_start_idx + 1;
// while i < self.0.len() && j < other.0.len() {
// i = self.skip_noise(i);
// j = other.skip_noise(j);
// if i < self.0.len() && j < other.0.len() && self.0[i] == other.0[j] {
// coeff += 1;
// i += 1;
// j += 1;
// } else {
// break;
// }
// }
// (coeff, i)
// }
// fn skip_noise(&self, mut index: usize) -> usize {
// while index < self.0.len() {
// if let Entry::Data(_) = self.0[index] {
// break;
// }
// index += 1;
// }
// index
// }
// }
// #[cfg(test)]
// mod tests {
// use super::*;
// fn test_ordering_coefficient_common(casual: bool) {
// // Case 0: Empty sequences
// let seq = Sequence(vec![]);
// assert_eq!(seq.ordering_coefficient(&seq, casual), 0);
// // Case 1: Exact one matched pair with no noise
// let seq = Sequence(vec![Entry::Data(1), Entry::Data(2)]);
// assert_eq!(seq.ordering_coefficient(&seq, casual), 1);
// // Case 2: Exact one matched pair with noise
// let seq = Sequence(vec![Entry::Data(1), Entry::Noise(10), Entry::Data(2)]);
// assert_eq!(seq.ordering_coefficient(&seq, casual), 1);
// // Case 3: One matched pair with no noise
// let seq1 = Sequence(vec![Entry::Data(1), Entry::Data(2), Entry::Data(3)]);
// let seq2 = Sequence(vec![Entry::Data(1), Entry::Data(2), Entry::Data(4)]);
// assert_eq!(seq1.ordering_coefficient(&seq2, casual), 1);
// assert_eq!(seq2.ordering_coefficient(&seq1, casual), 1);
// // Case 4: One matched pair with noise
// let seq1 = Sequence(vec![
// Entry::Data(1),
// Entry::Noise(10),
// Entry::Data(2),
// Entry::Data(3),
// ]);
// let seq2 = Sequence(vec![Entry::Data(1), Entry::Noise(10), Entry::Data(2)]);
// assert_eq!(seq1.ordering_coefficient(&seq2, casual), 1);
// assert_eq!(seq2.ordering_coefficient(&seq1, casual), 1);
// // Case 5: Two matched pairs with noise
// let seq1 = Sequence(vec![
// Entry::Data(1),
// Entry::Noise(10),
// Entry::Data(2),
// Entry::Data(3),
// ]);
// let seq2 = Sequence(vec![
// Entry::Data(1),
// Entry::Noise(10),
// Entry::Data(2),
// Entry::Data(3),
// Entry::Data(4),
// ]);
// assert_eq!(seq1.ordering_coefficient(&seq2, casual), 2);
// assert_eq!(seq2.ordering_coefficient(&seq1, casual), 2);
// // Case 6: Only partial match with no noise
// let seq1 = Sequence(vec![Entry::Data(1), Entry::Data(2)]);
// let seq2 = Sequence(vec![Entry::Data(2), Entry::Data(3)]);
// assert_eq!(seq1.ordering_coefficient(&seq2, casual), 0);
// assert_eq!(seq2.ordering_coefficient(&seq1, casual), 0);
// // Case 7: Only partial match with noise
// let seq1 = Sequence(vec![Entry::Data(1), Entry::Data(2), Entry::Noise(10)]);
// let seq2 = Sequence(vec![Entry::Data(2), Entry::Noise(10), Entry::Data(3)]);
// assert_eq!(seq1.ordering_coefficient(&seq2, casual), 0);
// assert_eq!(seq2.ordering_coefficient(&seq1, casual), 0);
// // Case 8: No match at all
// let seq1 = Sequence(vec![Entry::Data(1), Entry::Data(2), Entry::Noise(10)]);
// let seq2 = Sequence(vec![Entry::Data(3), Entry::Noise(10), Entry::Data(4)]);
// assert_eq!(seq1.ordering_coefficient(&seq2, casual), 0);
// assert_eq!(seq2.ordering_coefficient(&seq1, casual), 0);
// // Case 9: Matches with noise but mixed orders
// let seq1 = Sequence(vec![
// Entry::Data(1),
// Entry::Data(2),
// Entry::Noise(10),
// Entry::Data(3),
// Entry::Data(4),
// Entry::Data(5),
// Entry::Data(6),
// ]);
// let seq2 = Sequence(vec![
// Entry::Data(4),
// Entry::Data(5),
// Entry::Data(1),
// Entry::Data(2),
// Entry::Noise(10),
// Entry::Data(3),
// Entry::Data(6),
// ]);
// assert_eq!(seq1.ordering_coefficient(&seq2, casual), 3);
// assert_eq!(seq2.ordering_coefficient(&seq1, casual), 3);
// }
// #[test]
// fn test_casual_ordering_coefficient() {
// test_ordering_coefficient_common(true);
// // Case 0: No match because of noise
// let seq1 = Sequence(vec![Entry::Data(1), Entry::Noise(10), Entry::Data(2)]);
// let seq2 = Sequence(vec![Entry::Data(1), Entry::Data(2)]);
// assert_eq!(seq1.ordering_coefficient(&seq2, true), 0);
// assert_eq!(seq2.ordering_coefficient(&seq1, true), 0);
// // Case 1: No match because of different count of noises
// let seq1 = Sequence(vec![Entry::Data(1), Entry::Noise(10), Entry::Data(2)]);
// let seq2 = Sequence(vec![Entry::Data(1), Entry::Noise(5), Entry::Data(2)]);
// assert_eq!(seq1.ordering_coefficient(&seq2, true), 0);
// assert_eq!(seq2.ordering_coefficient(&seq1, true), 0);
// }
// #[test]
// fn test_weak_ordering_coefficient() {
// test_ordering_coefficient_common(false);
// // Case 0: Match ignoring noises
// let seq1 = Sequence(vec![Entry::Data(1), Entry::Noise(10), Entry::Data(2)]);
// let seq2 = Sequence(vec![Entry::Data(1), Entry::Data(2)]);
// assert_eq!(seq1.ordering_coefficient(&seq2, false), 1);
// assert_eq!(seq2.ordering_coefficient(&seq1, false), 1);
// // Case 1: Match ignoring noise count
// let seq1 = Sequence(vec![Entry::Data(1), Entry::Noise(10), Entry::Data(2)]);
// let seq2 = Sequence(vec![Entry::Data(1), Entry::Noise(5), Entry::Data(2)]);
// assert_eq!(seq1.ordering_coefficient(&seq2, false), 1);
// assert_eq!(seq2.ordering_coefficient(&seq1, false), 1);
// }
// }

View File

@ -5,11 +5,8 @@ use protocol::{
topology::Topology,
};
use crate::{
message::{DataMessage, SenderIdx},
ordercoeff::SequenceWriter,
topology::AllSenderPeers,
};
use crate::{sequence::SequenceWriter, topology::AllSenderPeers};
use ordering::message::{DataMessage, SenderIdx};
pub struct Outputs {
closed: bool,

View File

@ -0,0 +1,41 @@
use std::fs::File;
use ordering::message::DataMessage;
#[derive(Debug)]
pub struct SequenceWriter {
noise_buf: u32,
writer: csv::Writer<File>,
}
impl SequenceWriter {
pub fn new(path: &str) -> Self {
Self {
noise_buf: 0,
writer: csv::Writer::from_path(path).unwrap(),
}
}
pub fn flush(&mut self) {
self.clear_buf();
self.writer.flush().unwrap();
}
fn clear_buf(&mut self) {
if self.noise_buf > 0 {
self.writer
.write_record(&[format!("-{}", self.noise_buf)])
.unwrap();
self.noise_buf = 0;
}
}
pub fn add_message(&mut self, msg: &DataMessage) {
self.clear_buf();
self.writer.write_record(&[msg.to_string()]).unwrap();
}
pub fn add_noise(&mut self) {
self.noise_buf += 1;
}
}

View File

@ -8,7 +8,8 @@ use protocol::{
use rand::{rngs::StdRng, seq::SliceRandom, RngCore, SeedableRng};
use rustc_hash::FxHashMap;
use crate::{message::SenderIdx, outputs::Outputs, paramset::ParamSet};
use crate::{outputs::Outputs, paramset::ParamSet};
use ordering::message::SenderIdx;
pub const RECEIVER_NODE_ID: NodeId = NodeId::MAX;