diff --git a/src/main.rs b/src/main.rs index 38ad9f1..73aa7d4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,27 +1,10 @@ fn main() { let now = std::time::Instant::now(); - // use reactionsystems::rsprocess::presets; - // match presets::run("testing/first.system".into()) { - // Ok(_) => {}, - // Err(e) => {println!("{e}")} - // } - - use reactionsystems::grammar::AssertParser; - use reactionsystems::rsprocess::translator::Translator; - - let contents = r#"label { if (substr("e", ('e').tostr)) then {return 'e'} else {return (("e").toel)} }"#; - let mut translator = Translator::new(); - let tree = AssertParser::new().parse(&mut translator, contents).unwrap(); - - println!("{tree}"); - match tree.typecheck() { - Ok(_) => println!("ok"), - Err(e) => println!("error: {e}") - } - match tree.execute(&reactionsystems::rsprocess::structure::RSlabel::new(), &mut translator) { - Ok(val) => println!("ok: {val}"), - Err(e) => println!("error: {e}") + use reactionsystems::rsprocess::presets; + match presets::run("testing/first.system".into()) { + Ok(_) => {}, + Err(e) => {println!("{e}")} } println!("{} milliseconds elapsed", now.elapsed().as_millis()); diff --git a/src/rsprocess/assert.rs b/src/rsprocess/assert.rs index 7ba3696..d76b981 100644 --- a/src/rsprocess/assert.rs +++ b/src/rsprocess/assert.rs @@ -668,7 +668,7 @@ enum AssertionTypes { Edge, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash, PartialEq, Eq)] pub enum AssertReturnValue { Boolean(bool), Integer(IntegerType), diff --git a/src/rsprocess/grammar.lalrpop b/src/rsprocess/grammar.lalrpop index 1177c3a..613d856 100644 --- a/src/rsprocess/grammar.lalrpop +++ b/src/rsprocess/grammar.lalrpop @@ -55,6 +55,7 @@ match { "::", "substr", "min", "max", "commonsubstr", "SystemEntities", "SystemContext", "AvailableEntities", "AllReactants", "AllInhibitors", + "relabel", } else { r"[0-9]+" => NUMBER } else { @@ -726,8 +727,9 @@ Instruction: presets::Instruction = { presets::Instruction::FastFrequency { experiment: p, so }, "Digraph" ">" > => presets::Instruction::Digraph { gso }, - "Bisimilarity" "(" ")" ">" => - presets::Instruction::Bisimilarity { system_b: p, so }, + "Bisimilarity" "(" ")" "relabel" + ">" => + presets::Instruction::Bisimilarity { system_b: p, edge_relabeler, so }, } pub Run: presets::Instructions = { diff --git a/src/rsprocess/graph.rs b/src/rsprocess/graph.rs index 73f2dab..306836b 100644 --- a/src/rsprocess/graph.rs +++ b/src/rsprocess/graph.rs @@ -119,6 +119,49 @@ common_label!( // helper functions // ----------------------------------------------------------------------------- +/// Very inelegant way to provide our graph with a map method where the edges +/// are mapped until the first error. +pub trait MapEdges<'a, N: 'a, E, Ty, Ix> +where + Ty: petgraph::EdgeType, + Ix: petgraph::graph::IndexType +{ + fn map_edges( + &self, + edge_map: &super::assert::RSassert, + translator: &mut super::translator::Translator + ) -> Result, String>; +} + +impl<'a> MapEdges<'a, RSsystem, RSlabel, Directed, u32> + for RSgraph +{ + fn map_edges( + &self, + edge_map: &super::assert::RSassert, + translator: &mut super::translator::Translator + )-> Result, String> { + use petgraph::graph::EdgeIndex; + + let mut g = Graph::with_capacity(self.node_count(), self.edge_count()); + let nodes = self.raw_nodes(); + let edges = self.raw_edges(); + + let edges = edges.iter().enumerate().map( + |(i, edge)| + match edge_map.execute(self, &EdgeIndex::new(i), translator) { + Err(e) => Err(e), + Ok(val) => Ok((edge.source(), edge.target(), val)) + } + ).collect::, _>>()?; + nodes.iter().for_each(|node| { g.add_node(node.weight.clone()); }); + + edges.into_iter().for_each(|(source, target, v)| { g.add_edge(source, target, v); }); + + Ok(g) + } +} + // Nodes ----------------------------------------------------------------------- diff --git a/src/rsprocess/presets.rs b/src/rsprocess/presets.rs index 57a04d7..7dd9feb 100644 --- a/src/rsprocess/presets.rs +++ b/src/rsprocess/presets.rs @@ -8,10 +8,12 @@ use std::io::prelude::*; use std::rc::Rc; use lalrpop_util::ParseError; +use petgraph::Graph; // grammar is defined in lib.rs, calling lalrpop_mod! twice, generates twice // the code use crate::grammar; +use crate::rsprocess::graph::MapEdges; use super::structure::{RSset, RSsystem}; use super::translator::Translator; @@ -86,7 +88,9 @@ pub enum Instruction { LimitFrequency { experiment: String, so: SaveOptions }, FastFrequency { experiment: String, so: SaveOptions }, Digraph { gso: Vec }, - Bisimilarity { system_b: String, so: SaveOptions } + Bisimilarity { system_b: String, + edge_relabeler: Box, + so: SaveOptions } } /// Describes a system or a graph. @@ -495,13 +499,15 @@ pub fn digraph(system: &mut EvaluatedSystem) -> Result<(), String> { /// Computes bisimularity of two provided systems pub fn bisimilar( system_a: &mut EvaluatedSystem, + edge_relabeler: &super::assert::RSassert, system_b: String ) -> Result { + use super::assert::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 } => @@ -520,18 +526,18 @@ pub fn bisimilar( digraph(&mut system_b)?; // since we ran digraph on both they have to be graphs - match (system_a, &system_b) { + match (system_a, &mut system_b) { (EvaluatedSystem::Graph { graph: a, translator: _ }, - EvaluatedSystem::Graph { graph: b, translator: _ }) => { - // needed because rust cant see that we want to use &graph::RSgraph - // and not &mut graph::RSgraph - let a: &graph::RSgraph = a; - let b: &graph::RSgraph = b; + EvaluatedSystem::Graph { graph: b, translator: translator_b }) => { + let a: Graph = + a.map_edges(edge_relabeler, translator_b)?; + let b: Graph = + b.map_edges(edge_relabeler, translator_b)?; Ok(format!( "{}", - // super::bisimilarity::bisimilarity_kanellakis_smolka(&a, &b) - // super::bisimilarity::bisimilarity_paige_tarjan_ignore_labels(&a, &b) - super::bisimilarity::bisimilarity_paige_tarjan(&a, &b) + // super::bisimilarity::bisimilarity_kanellakis_smolka(&&a, &&b) + // super::bisimilarity::bisimilarity_paige_tarjan_ignore_labels(&&a, &&b) + super::bisimilarity::bisimilarity_paige_tarjan(&&a, &&b) )) }, _ => { unreachable!() } @@ -540,8 +546,6 @@ pub fn bisimilar( - - // ----------------------------------------------------------------------------- // Output Functions // ----------------------------------------------------------------------------- @@ -745,8 +749,9 @@ fn execute( } } } - Instruction::Bisimilarity { system_b, so } => { - save_options!(bisimilar(system, system_b)?, so); + Instruction::Bisimilarity { system_b, edge_relabeler, so } => { + edge_relabeler.typecheck()?; + save_options!(bisimilar(system, &edge_relabeler, system_b)?, so); } } Ok(()) diff --git a/testing/first.system b/testing/first.system index 3bf3642..ade9aa5 100644 --- a/testing/first.system +++ b/testing/first.system @@ -4,11 +4,14 @@ Context: [({a,b}.{a}.{a,c}.x + {a,b}.{a}.{a}.nill)] Reactions: ([{a,b}, {c}, {b}]) -Bisimilarity ("testing/adversarial.system") > Print, +Bisimilarity ("testing/adversarial.system") + relabel label { return true } + > Print, + Digraph > Dot | Entities " - " Context " - entities masked: " MaskEntities {a} | Entities - | EntitiesDeleted {a} ? "blue" ! "white" + | Entities < {a} ? "blue" ! "white" | ! "black" > Print,