diff --git a/.gitignore b/.gitignore index ba483eb..15b4593 100644 --- a/.gitignore +++ b/.gitignore @@ -114,3 +114,4 @@ Temporary Items # .nfs files are created when an open file is removed but is still being accessed .nfs* +*.cbor diff --git a/Cargo.toml b/Cargo.toml index 468aa45..4fe3d54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,9 @@ edition = "2024" lalrpop = "0.22" [dependencies] -petgraph = { version = "0.8" } regex = { version = "1.11", features = ["unicode-bool"] } lalrpop-util = { version = "0.22", features = ["lexer", "unicode"] } +petgraph = { version = "0.8", features = ["serde-1"] } +# petgraph-graphml = { version = "4" } +serde = { version = "1", features = ["derive", "rc"] } +serde_cbor_2 = { version = "*" } diff --git a/src/examples.rs b/src/examples.rs index 27e8880..283c5a7 100644 --- a/src/examples.rs +++ b/src/examples.rs @@ -1,12 +1,11 @@ -#![allow(dead_code)] - -use crate::rsprocess::structure::{RSset, RSsystem}; -use crate::rsprocess::{graph, rsdot, translator}; -use crate::rsprocess::translator::Translator; -use crate::rsprocess::{frequency, perpetual, statistics, transitions}; +use super::rsprocess::structure::{RSset, RSsystem}; +use super::rsprocess::{graph, rsdot, translator}; +use super::rsprocess::translator::Translator; +use super::rsprocess::{frequency, perpetual, statistics, transitions}; +use super::rsprocess::serialize; use std::env; -use std::fs; +use std::fs::{self, File}; use std::io; use std::io::prelude::*; use std::rc::Rc; @@ -322,3 +321,66 @@ pub fn adversarial() -> std::io::Result<()> { Ok(()) } + +pub fn serialize() -> std::io::Result<()> { + let mut translator = Translator::new(); + + let mut path = env::current_dir()?; + // file to read is inside testing/ + path = path.join("testing/adversarial.system"); + let system = read_file(&mut translator, path, parser_system)?; + + // the system needs to terminate to return + let graph = match graph::digraph(system) { + Ok(o) => o, + Err(e) => { + println!("Error computing target: {e}"); + return Ok(()); + } + }; + + let mut file = env::current_dir()?; + file = file.join("testing/adversarial.cbor"); + + let file = File::create(file)?; + + serialize::sr(file, &graph, &translator).unwrap(); + + Ok(()) +} + +pub fn deserialize() -> std::io::Result<()> { + let mut path = env::current_dir()?; + path = path.join("testing/adversarial.cbor"); + + let file = File::open(path)?; + + let (graph, translator) = serialize::dsr(file).unwrap(); + + let rc_translator = Rc::new(translator); + + let old_res = Rc::new(graph.clone()); + + // map each value to the corresponding value we want to display + let graph = graph.map( + |id, node| + graph::GraphMapNodesTy::from(graph::GraphMapNodes::Entities, + Rc::clone(&rc_translator)).get()(id, node) + + "; " + + &graph::GraphMapNodesTy::from(graph::GraphMapNodes::Context, + Rc::clone(&rc_translator)).get()(id, node), + graph::GraphMapEdgesTy::from(graph::GraphMapEdges::EntitiesAdded, + Rc::clone(&rc_translator)).get() + ); + + println!("Generated graph in dot notation:\n{}", + rsdot::RSDot::with_attr_getters( + &graph, + &[], + &graph::default_edge_formatter(Rc::clone(&old_res)), + &graph::default_node_formatter(Rc::clone(&old_res)), + ) + ); + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index 6b1a64d..02f2aa5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,9 +2,7 @@ fn main() -> std::io::Result<()> { // let now = std::time::Instant::now(); // println!("{}", now.elapsed().as_micros()); - reactionsystems::examples::digraph()?; - - reactionsystems::examples::adversarial()?; + reactionsystems::examples::deserialize()?; Ok(()) } diff --git a/src/rsprocess/mod.rs b/src/rsprocess/mod.rs index 0249f56..099beb3 100644 --- a/src/rsprocess/mod.rs +++ b/src/rsprocess/mod.rs @@ -9,3 +9,4 @@ pub mod transitions; pub mod translator; pub mod graph; pub mod rsdot; +pub mod serialize; diff --git a/src/rsprocess/serialize.rs b/src/rsprocess/serialize.rs new file mode 100644 index 0000000..8f3d8a9 --- /dev/null +++ b/src/rsprocess/serialize.rs @@ -0,0 +1,33 @@ +use std::io; + +use petgraph::Graph; +use serde::{Deserialize, Serialize}; + +use super::{structure::{RSlabel, RSsystem}, translator::Translator}; + +#[derive(Serialize, Deserialize)] +struct GraphAndTranslator { + graph: Graph, + translator: Translator +} + +pub fn sr(writer: W, graph: &Graph, translator: &Translator) -> Result<(), serde_cbor_2::Error> +where + W: io::Write, +{ + serde_cbor_2::to_writer(writer, + &GraphAndTranslator { + graph: graph.clone(), + translator: translator.clone() + }) +} + +pub fn dsr( + reader: R +) -> Result<(Graph, Translator), serde_cbor_2::Error> +where + R: io::Read, +{ + let gat: GraphAndTranslator = serde_cbor_2::from_reader(reader)?; + Ok((gat.graph, gat.translator)) +} diff --git a/src/rsprocess/structure.rs b/src/rsprocess/structure.rs index e125470..66469a5 100644 --- a/src/rsprocess/structure.rs +++ b/src/rsprocess/structure.rs @@ -2,12 +2,13 @@ use super::translator::IdType; use std::collections::{BTreeSet, HashMap, VecDeque}; use std::hash::Hash; use std::rc::Rc; +use serde::{Deserialize, Serialize}; // ----------------------------------------------------------------------------- // RSset // ----------------------------------------------------------------------------- -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] pub struct RSset { pub identifiers: BTreeSet, } @@ -125,7 +126,7 @@ impl IntoIterator for RSset { // ----------------------------------------------------------------------------- // RSreaction // ----------------------------------------------------------------------------- -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct RSreaction { pub reactants: RSset, pub inihibitors: RSset, @@ -166,7 +167,7 @@ impl Default for RSreaction { // ----------------------------------------------------------------------------- // RSprocess // ----------------------------------------------------------------------------- -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum RSprocess { Nill, RecursiveIdentifier { @@ -355,7 +356,7 @@ impl From, Rc)>> for RSchoices { // ----------------------------------------------------------------------------- // RSenvironment // ----------------------------------------------------------------------------- -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct RSenvironment { definitions: HashMap, } @@ -417,7 +418,7 @@ impl From> for RSenvironment { // ----------------------------------------------------------------------------- // RSsystem // ----------------------------------------------------------------------------- -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Deserialize, Serialize)] pub struct RSsystem { pub delta: Rc, pub available_entities: RSset, @@ -483,7 +484,7 @@ impl Default for RSsystem { // ----------------------------------------------------------------------------- // RSlabel // ----------------------------------------------------------------------------- -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct RSlabel { pub available_entities: RSset, pub context: RSset, diff --git a/src/rsprocess/translator.rs b/src/rsprocess/translator.rs index cc03253..186e091 100644 --- a/src/rsprocess/translator.rs +++ b/src/rsprocess/translator.rs @@ -1,12 +1,13 @@ //! Module for translation and keeping track of strings. use std::{cmp::max, collections::HashMap}; +use serde::{Serialize, Deserialize}; /// precision for printing frequencies static PRECISION: &usize = &2; pub type IdType = u32; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct Translator { strings: HashMap, reverse: HashMap, diff --git a/testing/first.system b/testing/first.system index c9a79b1..bc19b3a 100644 --- a/testing/first.system +++ b/testing/first.system @@ -1,4 +1,4 @@ -Environment: [x = {a}.😵, 😵 =({a}.x + {b}.😵)] +Environment: [x = {a}.y, y =({a}.x + {b}.y)] Initial Entities: {a, b} Context: [({a,b}.{a}.{a,c}.x + {a,b}.{a}.{a}.nill)] Reactions: ([{a,b}, {c}, {b}])