rustfmt and now grouping working

This commit is contained in:
elvis
2025-09-10 22:41:40 +02:00
parent 355857abff
commit 91f69c9e6d
30 changed files with 2368 additions and 1188 deletions

View File

@ -2,6 +2,7 @@
use lalrpop_util::ParseError;
use petgraph::Graph;
use std::collections::HashMap;
use std::env;
use std::fmt::Display;
use std::fs;
@ -103,16 +104,18 @@ pub enum Instruction {
so: SaveOptions,
},
Digraph {
group: Option<Box<assert::grouping::Assert>>,
gso: Vec<GraphSaveOptions>,
},
Bisimilarity {
system_b: String,
edge_relabeler: Box<super::assert::types::Assert>,
edge_relabeler: Box<assert::relabel::Assert>,
so: SaveOptions,
},
}
/// Describes a system or a graph.
#[derive(Clone)]
pub enum System {
Deserialize { path: String },
System { sys: system::System },
@ -120,7 +123,10 @@ pub enum System {
impl System {
/// Deserialize the graph if applicable.
pub fn compute(&self, translator: Translator) -> Result<EvaluatedSystem, String> {
pub fn compute(
&self,
translator: Translator,
) -> Result<EvaluatedSystem, String> {
match self {
Self::System { sys } => Ok(EvaluatedSystem::System {
sys: sys.to_owned(),
@ -134,6 +140,7 @@ impl System {
}
}
#[derive(Clone)]
pub enum EvaluatedSystem {
Graph {
graph: graph::SystemGraph,
@ -167,7 +174,11 @@ pub struct Instructions {
// IO Helper Functions
// -----------------------------------------------------------------------------
fn read_file<T, F>(translator: &mut Translator, path_string: String, parser: F) -> Result<T, String>
fn read_file<T, F>(
translator: &mut Translator,
path_string: String,
parser: F,
) -> Result<T, String>
where
F: Fn(&mut Translator, String) -> Result<T, String>,
{
@ -196,14 +207,17 @@ where
Ok(result)
}
fn reformat_error<T, S>(e: ParseError<usize, T, &'static str>, input_str: &str) -> Result<S, String>
fn reformat_error<T, S>(
e: ParseError<usize, T, &'static str>,
input_str: &str,
) -> Result<S, String>
where
T: Display,
{
match e {
ParseError::ExtraToken { token: (l, t, r) } => Err(format!(
"Unexpected token \"{t}\" \
between positions {l} and {r}."
between positions {l} and {r}."
)),
ParseError::UnrecognizedEof {
location: _,
@ -214,30 +228,30 @@ where
}
ParseError::UnrecognizedToken {
token: (l, t, r),
expected: _,
expected,
} => {
use colored::Colorize;
let mut err = format!(
"Unrecognized token {}{}{} \
between positions {l} and {r}.",
between positions {l} and {r}.",
"\"".red(),
t.to_string().red(),
"\"".red(),
);
// // Temporary debug.
// err.push_str("Expected: ");
// let mut it = expected.iter().peekable();
// while let Some(s) = it.next() {
// err.push('(');
// err.push_str(&format!("{}", s.green()));
// err.push(')');
// if it.peek().is_some() {
// err.push(',');
// err.push(' ');
// }
// }
// Temporary debug.
err.push_str("Expected: ");
let mut it = expected.iter().peekable();
while let Some(s) = it.next() {
err.push('(');
err.push_str(&format!("{}", s.green()));
err.push(')');
if it.peek().is_some() {
err.push(',');
err.push(' ');
}
}
let right_new_line = input_str[l..]
.find("\n")
.map(|pos| pos + l)
@ -310,7 +324,12 @@ fn save_file(contents: &String, path_string: String) -> Result<(), String> {
let mut f = match fs::File::create(&path) {
Ok(f) => f,
Err(_) => return Err(format!("Error creating file {}.", path.to_str().unwrap())),
Err(_) => {
return Err(format!(
"Error creating file {}.",
path.to_str().unwrap()
));
}
};
match write!(f, "{contents}") {
Ok(_) => {}
@ -327,7 +346,9 @@ fn save_file(contents: &String, path_string: String) -> Result<(), String> {
/// Equivalent main_do(stat) or main_do(stat, MissingE)
pub fn stats(system: &EvaluatedSystem) -> Result<String, String> {
match system {
EvaluatedSystem::System { sys, translator } => Ok(sys.statistics(translator)),
EvaluatedSystem::System { sys, translator } => {
Ok(sys.statistics(translator))
}
EvaluatedSystem::Graph { graph, translator } => {
let Some(sys) = graph.node_weights().next() else {
return Err("No node found in graph.".into());
@ -342,7 +363,9 @@ pub fn stats(system: &EvaluatedSystem) -> Result<String, String> {
/// Equivalent to main_do(target, E)
pub fn target(system: &EvaluatedSystem) -> Result<String, String> {
let (res, translator) = match system {
EvaluatedSystem::System { sys, translator } => (sys.target()?, translator),
EvaluatedSystem::System { sys, translator } => {
(sys.target()?, translator)
}
EvaluatedSystem::Graph { graph, translator } => {
let Some(sys) = graph.node_weights().next() else {
return Err("No node found in graph.".into());
@ -363,7 +386,9 @@ pub fn target(system: &EvaluatedSystem) -> Result<String, String> {
/// equivalent to main_do(run,Es)
pub fn traversed(system: &EvaluatedSystem) -> Result<String, String> {
let (res, translator) = match system {
EvaluatedSystem::System { sys, translator } => (sys.run_separated()?, translator),
EvaluatedSystem::System { sys, translator } => {
(sys.run_separated()?, translator)
}
EvaluatedSystem::Graph { graph, translator } => {
let Some(sys) = graph.node_weights().next() else {
return Err("No node found in graph.".into());
@ -376,7 +401,10 @@ pub fn traversed(system: &EvaluatedSystem) -> Result<String, String> {
output.push_str("The trace is composed by the set of entities: ");
for (e, _c, _t) in res {
output.push_str(&format!("{}", translator::Formatter::from(translator, &e)));
output.push_str(&format!(
"{}",
translator::Formatter::from(translator, &e)
));
}
Ok(output)
}
@ -385,7 +413,10 @@ pub fn traversed(system: &EvaluatedSystem) -> Result<String, String> {
/// context. IMPORTANT: for loops, we assume Delta defines the process constant
/// x = Q.x and the context process is x .
/// equivalent to main_do(loop,Es)
pub fn hoop(system: &EvaluatedSystem, symbol: String) -> Result<String, String> {
pub fn hoop(
system: &EvaluatedSystem,
symbol: String,
) -> Result<String, String> {
use system::LoopSystem;
let (res, translator) = match system {
@ -412,7 +443,10 @@ pub fn hoop(system: &EvaluatedSystem, symbol: String) -> Result<String, String>
output.push_str("The loop is composed by the sets: ");
for e in res {
output.push_str(&format!("{}", translator::Formatter::from(translator, &e)));
output.push_str(&format!(
"{}",
translator::Formatter::from(translator, &e)
));
}
Ok(output)
@ -445,7 +479,10 @@ pub fn freq(system: &EvaluatedSystem) -> Result<String, String> {
/// Finds the frequency of each entity in the limit loop of a nonterminating
/// Reaction System whose context has the form Q1 ... Q1.Q2 ... Q2 ... Qn ...
/// equivalent to main_do(limitfreq, PairList)
pub fn limit_freq(system: &mut EvaluatedSystem, experiment: String) -> Result<String, String> {
pub fn limit_freq(
system: &mut EvaluatedSystem,
experiment: String,
) -> Result<String, String> {
use frequency::BasicFrequency;
let (sys, translator): (&system::System, &mut Translator) = match system {
@ -482,7 +519,10 @@ pub fn limit_freq(system: &mut EvaluatedSystem, experiment: String) -> Result<St
/// Q1 ... Q1.Q2 ... Q2 ... Qn ... Qn.nil and each Qi is repeated Wi times
/// read from a corresponding file.
/// equivalent to main_do(fastfreq, PairList)
pub fn fast_freq(system: &mut EvaluatedSystem, experiment: String) -> Result<String, String> {
pub fn fast_freq(
system: &mut EvaluatedSystem,
experiment: String,
) -> Result<String, String> {
use frequency::BasicFrequency;
let (sys, translator): (&system::System, &mut Translator) = match system {
@ -520,33 +560,91 @@ pub fn fast_freq(system: &mut EvaluatedSystem, experiment: String) -> Result<Str
pub fn digraph(system: &mut EvaluatedSystem) -> Result<(), String> {
if let EvaluatedSystem::System { sys, translator } = system {
*system = EvaluatedSystem::Graph {
graph: sys.clone().digraph()?,
graph: sys.digraph()?,
translator: translator.to_owned(),
};
}
Ok(())
}
pub fn grouping(
system: &mut EvaluatedSystem,
group: &assert::grouping::Assert,
) -> Result<(), String> {
let mut buckets = HashMap::new();
let mut leader: HashMap<petgraph::prelude::NodeIndex, _> = HashMap::new();
if let EvaluatedSystem::Graph { graph, translator } = system {
for node in graph.node_indices() {
let val = group.execute(graph, &node, translator)?;
buckets.entry(val.clone()).or_insert(vec![]).push(node);
let l = buckets.get(&val).unwrap().first().unwrap();
leader.insert(node, (*l, val));
}
for node in graph.node_indices().rev() {
let (origin, val) = leader.get(&node).unwrap();
if *origin == node {
continue;
}
if buckets.get(val).unwrap().len() <= 1 {
continue;
}
let mut edges =
graph.neighbors_directed(node, petgraph::Outgoing).detach();
while let Some(edge) = edges.next_edge(graph) {
graph.add_edge(
*origin,
graph.edge_endpoints(edge).unwrap().1,
graph.edge_weight(edge).unwrap().clone(),
);
}
let mut edges =
graph.neighbors_directed(node, petgraph::Incoming).detach();
while let Some(edge) = edges.next_edge(graph) {
graph.add_edge(
graph.edge_endpoints(edge).unwrap().0,
*origin,
graph.edge_weight(edge).unwrap().clone(),
);
}
graph
.remove_node(node)
.ok_or(format!("Could not remove node {node:?}"))?;
}
Ok(())
} else {
Err("Grouping can be done only on graphs.".into())
}
}
/// Computes bisimularity of two provided systems
pub fn bisimilar(
system_a: &mut EvaluatedSystem,
edge_relabeler: &super::assert::types::Assert,
edge_relabeler: &assert::relabel::Assert,
system_b: String,
) -> Result<String, String> {
use super::assert::types::AssertReturnValue;
use assert::relabel::AssertReturnValue;
let system_b = read_file(
system_a.get_translator(),
system_b.to_string(),
parser_instructions,
)?;
let mut system_b = match system_b.system.compute(system_a.get_translator().clone())? {
EvaluatedSystem::System { sys, translator } => EvaluatedSystem::System { sys, translator },
let mut system_b = match system_b
.system
.compute(system_a.get_translator().clone())?
{
EvaluatedSystem::System { sys, translator } => {
EvaluatedSystem::System { sys, translator }
}
EvaluatedSystem::Graph { graph, translator } => {
if translator != *system_a.get_translator() {
return Err("Bisimilarity not implemented for systems with \
different encodings. Serialize the systems \
with the same translator."
different encodings. Serialize the systems \
with the same translator."
.into());
}
EvaluatedSystem::Graph { graph, translator }
@ -574,9 +672,9 @@ pub fn bisimilar(
b.map_edges(edge_relabeler, translator_b)?;
Ok(format!(
"{}",
// super::bisimilarity::bisimilarity_kanellakis_smolka::bisimilarity(&&a, &&b)
// super::bisimilarity::bisimilarity_paige_tarjan::bisimilarity_ignore_labels(&&a, &&b)
super::bisimilarity::bisimilarity_paige_tarkan::bisimilarity(&&a, &&b)
// bisimilarity::bisimilarity_kanellakis_smolka::bisimilarity(&&a, &&b)
// bisimilarity::bisimilarity_paige_tarjan::bisimilarity_ignore_labels(&&a, &&b)
bisimilarity::bisimilarity_paige_tarkan::bisimilarity(&&a, &&b)
))
}
_ => {
@ -611,12 +709,16 @@ pub fn dot(
let graph = Rc::new(graph.to_owned());
let node_formatter =
node_color.generate(Rc::clone(&graph), translator.encode_not_mut("*"));
let node_formatter = node_color
.generate(Rc::clone(&graph), translator.encode_not_mut("*"));
let edge_formatter = edge_color.generate(Rc::clone(&graph));
let dot =
dot::Dot::with_attr_getters(&modified_graph, &[], &edge_formatter, &node_formatter);
let dot = dot::Dot::with_attr_getters(
&modified_graph,
&[],
&edge_formatter,
&node_formatter,
);
Ok(format!("{dot}"))
}
@ -670,7 +772,12 @@ pub fn serialize(system: &EvaluatedSystem, path: String) -> Result<(), String> {
let f = match fs::File::create(&path) {
Ok(f) => f,
Err(_) => return Err(format!("Error creating file {}.", path.to_str().unwrap())),
Err(_) => {
return Err(format!(
"Error creating file {}.",
path.to_str().unwrap()
));
}
};
match serialize::ser(f, graph, translator) {
@ -684,7 +791,9 @@ pub fn serialize(system: &EvaluatedSystem, path: String) -> Result<(), String> {
/// Reads the specified serialized system from a file.
/// N.B. graph size in memory might be much larger after serialization and
/// deserialization
pub fn deserialize(input_path: String) -> Result<(graph::SystemGraph, Translator), String> {
pub fn deserialize(
input_path: String,
) -> Result<(graph::SystemGraph, Translator), String> {
// relative path
let mut path = match env::current_dir() {
Ok(p) => p,
@ -695,7 +804,12 @@ pub fn deserialize(input_path: String) -> Result<(graph::SystemGraph, Translator
let f = match fs::File::open(&path) {
Ok(f) => f,
Err(_) => return Err(format!("Error opening file {}.", path.to_str().unwrap())),
Err(_) => {
return Err(format!(
"Error opening file {}.",
path.to_str().unwrap()
));
}
};
match serialize::de(f) {
@ -723,7 +837,10 @@ macro_rules! save_options {
};
}
fn execute(instruction: Instruction, system: &mut EvaluatedSystem) -> Result<(), String> {
fn execute(
instruction: Instruction,
system: &mut EvaluatedSystem,
) -> Result<(), String> {
match instruction {
Instruction::Stats { so } => {
save_options!(stats(system)?, so);
@ -746,9 +863,14 @@ fn execute(instruction: Instruction, system: &mut EvaluatedSystem) -> Result<(),
Instruction::FastFrequency { experiment, so } => {
save_options!(fast_freq(system, experiment)?, so);
}
Instruction::Digraph { gso } => {
Instruction::Digraph { group, gso } => {
let mut graph = system.clone();
digraph(&mut graph)?;
if let Some(group) = group {
group.typecheck()?;
grouping(&mut graph, &group)?;
}
for save in gso {
digraph(system)?;
match save {
GraphSaveOptions::Dot {
node_display: nd,
@ -757,17 +879,17 @@ fn execute(instruction: Instruction, system: &mut EvaluatedSystem) -> Result<(),
edge_color: ec,
so,
} => {
save_options!(dot(system, nd, ed, nc, ec)?, so);
save_options!(dot(&graph, nd, ed, nc, ec)?, so);
}
GraphSaveOptions::GraphML {
node_display: nd,
edge_display: ed,
so,
} => {
save_options!(graphml(system, nd, ed)?, so);
save_options!(graphml(&graph, nd, ed)?, so);
}
GraphSaveOptions::Serialize { path } => {
serialize(system, path)?;
serialize(&graph, path)?;
}
}
}