Bisimilarity with assert in presets

This commit is contained in:
elvis
2025-08-15 00:32:58 +02:00
parent d48f352bfa
commit a4da8aec8d
6 changed files with 77 additions and 41 deletions

View File

@ -1,27 +1,10 @@
fn main() { fn main() {
let now = std::time::Instant::now(); let now = std::time::Instant::now();
// use reactionsystems::rsprocess::presets; use reactionsystems::rsprocess::presets;
// match presets::run("testing/first.system".into()) { match presets::run("testing/first.system".into()) {
// Ok(_) => {}, Ok(_) => {},
// Err(e) => {println!("{e}")} 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}")
} }
println!("{} milliseconds elapsed", now.elapsed().as_millis()); println!("{} milliseconds elapsed", now.elapsed().as_millis());

View File

@ -668,7 +668,7 @@ enum AssertionTypes {
Edge, Edge,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum AssertReturnValue { pub enum AssertReturnValue {
Boolean(bool), Boolean(bool),
Integer(IntegerType), Integer(IntegerType),

View File

@ -55,6 +55,7 @@ match {
"::", "substr", "min", "max", "commonsubstr", "::", "substr", "min", "max", "commonsubstr",
"SystemEntities", "SystemContext", "SystemEntities", "SystemContext",
"AvailableEntities", "AllReactants", "AllInhibitors", "AvailableEntities", "AllReactants", "AllInhibitors",
"relabel",
} else { } else {
r"[0-9]+" => NUMBER r"[0-9]+" => NUMBER
} else { } else {
@ -726,8 +727,9 @@ Instruction: presets::Instruction = {
presets::Instruction::FastFrequency { experiment: p, so }, presets::Instruction::FastFrequency { experiment: p, so },
"Digraph" ">" <gso: Separated_Or<GraphSaveOptions, "|">> => "Digraph" ">" <gso: Separated_Or<GraphSaveOptions, "|">> =>
presets::Instruction::Digraph { gso }, presets::Instruction::Digraph { gso },
"Bisimilarity" "(" <p: Path> ")" ">" <so: SaveOptions> => "Bisimilarity" "(" <p: Path> ")" "relabel" <edge_relabeler: Assert>
presets::Instruction::Bisimilarity { system_b: p, so }, ">" <so: SaveOptions> =>
presets::Instruction::Bisimilarity { system_b: p, edge_relabeler, so },
} }
pub Run: presets::Instructions = { pub Run: presets::Instructions = {

View File

@ -119,6 +119,49 @@ common_label!(
// helper functions // 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<Graph<RSsystem, super::assert::AssertReturnValue, Ty, Ix>, 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<Graph<RSsystem, super::assert::AssertReturnValue, Directed, u32>, 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::<Result<Vec<_>, _>>()?;
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 ----------------------------------------------------------------------- // Nodes -----------------------------------------------------------------------

View File

@ -8,10 +8,12 @@ use std::io::prelude::*;
use std::rc::Rc; use std::rc::Rc;
use lalrpop_util::ParseError; use lalrpop_util::ParseError;
use petgraph::Graph;
// grammar is defined in lib.rs, calling lalrpop_mod! twice, generates twice // grammar is defined in lib.rs, calling lalrpop_mod! twice, generates twice
// the code // the code
use crate::grammar; use crate::grammar;
use crate::rsprocess::graph::MapEdges;
use super::structure::{RSset, RSsystem}; use super::structure::{RSset, RSsystem};
use super::translator::Translator; use super::translator::Translator;
@ -86,7 +88,9 @@ pub enum Instruction {
LimitFrequency { experiment: String, so: SaveOptions }, LimitFrequency { experiment: String, so: SaveOptions },
FastFrequency { experiment: String, so: SaveOptions }, FastFrequency { experiment: String, so: SaveOptions },
Digraph { gso: Vec<GraphSaveOptions> }, Digraph { gso: Vec<GraphSaveOptions> },
Bisimilarity { system_b: String, so: SaveOptions } Bisimilarity { system_b: String,
edge_relabeler: Box<super::assert::RSassert>,
so: SaveOptions }
} }
/// Describes a system or a graph. /// Describes a system or a graph.
@ -495,13 +499,15 @@ pub fn digraph(system: &mut EvaluatedSystem) -> Result<(), String> {
/// Computes bisimularity of two provided systems /// Computes bisimularity of two provided systems
pub fn bisimilar( pub fn bisimilar(
system_a: &mut EvaluatedSystem, system_a: &mut EvaluatedSystem,
edge_relabeler: &super::assert::RSassert,
system_b: String system_b: String
) -> Result<String, String> ) -> Result<String, String>
{ {
use super::assert::AssertReturnValue;
let system_b = read_file(system_a.get_translator(), let system_b = read_file(system_a.get_translator(),
system_b.to_string(), system_b.to_string(),
parser_instructions)?; parser_instructions)?;
let mut system_b = let mut system_b =
match system_b.system.compute(system_a.get_translator().clone())? { match system_b.system.compute(system_a.get_translator().clone())? {
EvaluatedSystem::System { sys, translator } => EvaluatedSystem::System { sys, translator } =>
@ -520,18 +526,18 @@ pub fn bisimilar(
digraph(&mut system_b)?; digraph(&mut system_b)?;
// since we ran digraph on both they have to be graphs // 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: a, translator: _ },
EvaluatedSystem::Graph { graph: b, translator: _ }) => { EvaluatedSystem::Graph { graph: b, translator: translator_b }) => {
// needed because rust cant see that we want to use &graph::RSgraph let a: Graph<RSsystem, AssertReturnValue> =
// and not &mut graph::RSgraph a.map_edges(edge_relabeler, translator_b)?;
let a: &graph::RSgraph = a; let b: Graph<RSsystem, AssertReturnValue> =
let b: &graph::RSgraph = b; b.map_edges(edge_relabeler, translator_b)?;
Ok(format!( Ok(format!(
"{}", "{}",
// super::bisimilarity::bisimilarity_kanellakis_smolka(&a, &b) // super::bisimilarity::bisimilarity_kanellakis_smolka(&&a, &&b)
// super::bisimilarity::bisimilarity_paige_tarjan_ignore_labels(&a, &b) // super::bisimilarity::bisimilarity_paige_tarjan_ignore_labels(&&a, &&b)
super::bisimilarity::bisimilarity_paige_tarjan(&a, &b) super::bisimilarity::bisimilarity_paige_tarjan(&&a, &&b)
)) ))
}, },
_ => { unreachable!() } _ => { unreachable!() }
@ -540,8 +546,6 @@ pub fn bisimilar(
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Output Functions // Output Functions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -745,8 +749,9 @@ fn execute(
} }
} }
} }
Instruction::Bisimilarity { system_b, so } => { Instruction::Bisimilarity { system_b, edge_relabeler, so } => {
save_options!(bisimilar(system, system_b)?, so); edge_relabeler.typecheck()?;
save_options!(bisimilar(system, &edge_relabeler, system_b)?, so);
} }
} }
Ok(()) Ok(())

View File

@ -4,11 +4,14 @@ Context: [({a,b}.{a}.{a,c}.x + {a,b}.{a}.{a}.nill)]
Reactions: ([{a,b}, {c}, {b}]) Reactions: ([{a,b}, {c}, {b}])
Bisimilarity ("testing/adversarial.system") > Print, Bisimilarity ("testing/adversarial.system")
relabel label { return true }
> Print,
Digraph > Dot Digraph > Dot
| Entities " - " Context " - entities masked: " MaskEntities {a} | Entities " - " Context " - entities masked: " MaskEntities {a}
| Entities | Entities
| EntitiesDeleted {a} ? "blue" ! "white" | Entities < {a} ? "blue" ! "white"
| ! "black" | ! "black"
> Print, > Print,