rustfmt
This commit is contained in:
@ -19,34 +19,36 @@ use super::structure::{RSset, RSsystem};
|
|||||||
use super::translator::Translator;
|
use super::translator::Translator;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Structures
|
// Structures
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
pub struct SaveOptions {
|
pub struct SaveOptions {
|
||||||
pub print: bool,
|
pub print: bool,
|
||||||
pub save: Option<Vec<String>>
|
pub save: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SaveOptions {
|
impl SaveOptions {
|
||||||
pub fn combine(&mut self, other: &mut Self) {
|
pub fn combine(&mut self, other: &mut Self) {
|
||||||
self.print = self.print || other.print;
|
self.print = self.print || other.print;
|
||||||
match (self.save.is_some(), other.save.is_some()) {
|
match (self.save.is_some(), other.save.is_some()) {
|
||||||
(false, false) |
|
(false, false) | (true, false) => {}
|
||||||
(true, false) => {}
|
|
||||||
(false, true) => {
|
(false, true) => {
|
||||||
self.save = other.save.to_owned();
|
self.save = other.save.to_owned();
|
||||||
},
|
}
|
||||||
(true, true) => {
|
(true, true) => {
|
||||||
self.save
|
self.save
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.append(other.save.as_mut().unwrap());}
|
.append(other.save.as_mut().unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
SaveOptions { print: false, save: None }
|
SaveOptions {
|
||||||
|
print: false,
|
||||||
|
save: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,23 +61,29 @@ impl Default for SaveOptions {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum NodeDisplay {
|
pub enum NodeDisplay {
|
||||||
Separator(String),
|
Separator(String),
|
||||||
Display(graph::GraphMapNodes)
|
Display(graph::GraphMapNodes),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum EdgeDisplay {
|
pub enum EdgeDisplay {
|
||||||
Separator(String),
|
Separator(String),
|
||||||
Display(graph::GraphMapEdges)
|
Display(graph::GraphMapEdges),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum GraphSaveOptions {
|
pub enum GraphSaveOptions {
|
||||||
Dot { node_display: Vec<NodeDisplay>,
|
Dot {
|
||||||
|
node_display: Vec<NodeDisplay>,
|
||||||
edge_display: Vec<EdgeDisplay>,
|
edge_display: Vec<EdgeDisplay>,
|
||||||
so: SaveOptions },
|
so: SaveOptions,
|
||||||
GraphML { node_display: Vec<NodeDisplay>,
|
},
|
||||||
|
GraphML {
|
||||||
|
node_display: Vec<NodeDisplay>,
|
||||||
edge_display: Vec<EdgeDisplay>,
|
edge_display: Vec<EdgeDisplay>,
|
||||||
so: SaveOptions },
|
so: SaveOptions,
|
||||||
Serialize { path: String }
|
},
|
||||||
|
Serialize {
|
||||||
|
path: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
@ -91,17 +99,20 @@ pub enum Instruction {
|
|||||||
|
|
||||||
pub enum System {
|
pub enum System {
|
||||||
Deserialize { path: String },
|
Deserialize { path: String },
|
||||||
RSsystem { sys: RSsystem }
|
RSsystem { sys: RSsystem },
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum EvaluatedSystem {
|
pub enum EvaluatedSystem {
|
||||||
Graph { graph: Graph<RSsystem, RSlabel>,
|
Graph {
|
||||||
translator: Translator },
|
graph: Graph<RSsystem, RSlabel>,
|
||||||
System { sys: RSsystem,
|
translator: Translator,
|
||||||
translator: Translator }
|
},
|
||||||
|
System {
|
||||||
|
sys: RSsystem,
|
||||||
|
translator: Translator,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl System {
|
impl System {
|
||||||
pub fn compute(
|
pub fn compute(
|
||||||
&self,
|
&self,
|
||||||
@ -109,14 +120,13 @@ impl System {
|
|||||||
) -> Result<EvaluatedSystem, String>
|
) -> Result<EvaluatedSystem, String>
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Self::RSsystem { sys } => {
|
Self::RSsystem { sys } => Ok(EvaluatedSystem::System {
|
||||||
Ok(EvaluatedSystem::System { sys: sys.to_owned(),
|
sys: sys.to_owned(),
|
||||||
translator })
|
translator,
|
||||||
},
|
}),
|
||||||
Self::Deserialize { path } => {
|
Self::Deserialize { path } => {
|
||||||
let (graph, translator) = deserialize(path.into())?;
|
let (graph, translator) = deserialize(path.into())?;
|
||||||
Ok(EvaluatedSystem::Graph { graph,
|
Ok(EvaluatedSystem::Graph { graph, translator })
|
||||||
translator })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,7 +134,7 @@ impl System {
|
|||||||
|
|
||||||
pub struct Instructions {
|
pub struct Instructions {
|
||||||
pub system: System,
|
pub system: System,
|
||||||
pub instructions: Vec<Instruction>
|
pub instructions: Vec<Instruction>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -137,25 +147,25 @@ fn read_file<T, F>(
|
|||||||
parser: F
|
parser: F
|
||||||
) -> Result<T, String>
|
) -> Result<T, String>
|
||||||
where
|
where
|
||||||
F: Fn(&mut Translator, String) -> Result<T, String>
|
F: Fn(&mut Translator, String) -> Result<T, String>,
|
||||||
{
|
{
|
||||||
// relative path
|
// relative path
|
||||||
let mut path = match env::current_dir() {
|
let mut path = match env::current_dir() {
|
||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
Err(_) => return Err("Error getting current directory.".into())
|
Err(_) => return Err("Error getting current directory.".into()),
|
||||||
};
|
};
|
||||||
path = path.join(path_string);
|
path = path.join(path_string);
|
||||||
|
|
||||||
// we read the file with a buffer
|
// we read the file with a buffer
|
||||||
let f = match fs::File::open(path) {
|
let f = match fs::File::open(path) {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(_) => return Err("Error opening file.".into())
|
Err(_) => return Err("Error opening file.".into()),
|
||||||
};
|
};
|
||||||
let mut buf_reader = io::BufReader::new(f);
|
let mut buf_reader = io::BufReader::new(f);
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
match buf_reader.read_to_string(&mut contents) {
|
match buf_reader.read_to_string(&mut contents) {
|
||||||
Ok(_) => {},
|
Ok(_) => {}
|
||||||
Err(_) => return Err("Error reading file.".into())
|
Err(_) => return Err("Error reading file.".into()),
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse
|
// parse
|
||||||
@ -168,86 +178,73 @@ fn reformat_error<T, S>(
|
|||||||
e: ParseError<usize, T, &'static str>
|
e: ParseError<usize, T, &'static str>
|
||||||
) -> Result<S, String>
|
) -> Result<S, String>
|
||||||
where
|
where
|
||||||
T: Display
|
T: Display,
|
||||||
{
|
{
|
||||||
match e {
|
match e {
|
||||||
ParseError::ExtraToken { token: (l, t, r) } => {
|
ParseError::ExtraToken { token: (l, t, r) } => Err(format!(
|
||||||
Err(format!(
|
|
||||||
"Unexpected token \"{t}\" \
|
"Unexpected token \"{t}\" \
|
||||||
between positions {l} and {r}."
|
between positions {l} and {r}."
|
||||||
))
|
)),
|
||||||
},
|
ParseError::UnrecognizedEof {
|
||||||
ParseError::UnrecognizedEof { location: _, expected: _ } => {
|
location: _,
|
||||||
Err("End of file encountered while parsing.".into())
|
expected: _,
|
||||||
},
|
} => Err("End of file encountered while parsing.".into()),
|
||||||
ParseError::InvalidToken { location } => {
|
ParseError::InvalidToken { location } => {
|
||||||
Err(format!("Invalid token at position {location}."))
|
Err(format!("Invalid token at position {location}."))
|
||||||
},
|
}
|
||||||
ParseError::UnrecognizedToken { token: (l, t, r), expected }
|
ParseError::UnrecognizedToken {
|
||||||
=> {
|
token: (l, t, r),
|
||||||
Err(format!(
|
expected,
|
||||||
|
} => Err(format!(
|
||||||
"Unrecognized token \"{t}\" \
|
"Unrecognized token \"{t}\" \
|
||||||
between positions {l} and {r}. Expected: {expected:?}"
|
between positions {l} and {r}. Expected: {expected:?}"
|
||||||
))
|
)),
|
||||||
},
|
ParseError::User { error } => Err(error.to_string()),
|
||||||
ParseError::User { error } => {
|
|
||||||
Err(error.to_string())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parser_experiment(
|
fn parser_experiment(
|
||||||
translator: &mut Translator,
|
translator: &mut Translator,
|
||||||
contents: String
|
contents: String,
|
||||||
) -> Result<(Vec<u32>, Vec<RSset>), String>
|
) -> Result<(Vec<u32>, Vec<RSset>), String> {
|
||||||
{
|
match grammar::ExperimentParser::new().parse(translator, &contents) {
|
||||||
match grammar::ExperimentParser::new()
|
|
||||||
.parse(translator, &contents)
|
|
||||||
{
|
|
||||||
Ok(sys) => Ok(sys),
|
Ok(sys) => Ok(sys),
|
||||||
Err(e) => reformat_error(e)
|
Err(e) => reformat_error(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parser_instructions(
|
fn parser_instructions(
|
||||||
translator: &mut Translator,
|
translator: &mut Translator,
|
||||||
contents: String
|
contents: String,
|
||||||
) -> Result<Instructions, String>
|
) -> Result<Instructions, String> {
|
||||||
{
|
match grammar::RunParser::new().parse(translator, &contents) {
|
||||||
match grammar::RunParser::new()
|
|
||||||
.parse(translator, &contents)
|
|
||||||
{
|
|
||||||
Ok(sys) => Ok(sys),
|
Ok(sys) => Ok(sys),
|
||||||
Err(e) => reformat_error(e)
|
Err(e) => reformat_error(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_file(
|
fn save_file(contents: &String, path_string: String) -> Result<(), String> {
|
||||||
contents: &String,
|
|
||||||
path_string: String
|
|
||||||
) -> Result<(), String>
|
|
||||||
{
|
|
||||||
// relative path
|
// relative path
|
||||||
let mut path = match env::current_dir() {
|
let mut path = match env::current_dir() {
|
||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
Err(_) => return Err("Error getting current directory.".into())
|
Err(_) => return Err("Error getting current directory.".into()),
|
||||||
};
|
};
|
||||||
path = path.join(path_string);
|
path = path.join(path_string);
|
||||||
|
|
||||||
let mut f = match fs::File::create(&path) {
|
let mut f = match fs::File::create(&path) {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(_) => return Err(format!("Error creating file {}.",
|
Err(_) =>
|
||||||
path.to_str().unwrap()))
|
return Err(
|
||||||
|
format!("Error creating file {}.", path.to_str().unwrap())
|
||||||
|
),
|
||||||
};
|
};
|
||||||
match write!(f, "{contents}") {
|
match write!(f, "{contents}") {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(_) => return Err("Error writing to file.".into())
|
Err(_) => return Err("Error writing to file.".into()),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// main_do
|
// main_do
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -256,12 +253,10 @@ fn save_file(
|
|||||||
/// Equivalent main_do(stat) or main_do(stat, MissingE)
|
/// Equivalent main_do(stat) or main_do(stat, MissingE)
|
||||||
pub fn stats(system: &EvaluatedSystem) -> Result<String, String> {
|
pub fn stats(system: &EvaluatedSystem) -> Result<String, String> {
|
||||||
match system {
|
match system {
|
||||||
EvaluatedSystem::System { sys, translator } => {
|
EvaluatedSystem::System { sys, translator } =>
|
||||||
Ok(statistics::of_RSsystem(translator, sys))
|
Ok(statistics::of_RSsystem(translator, sys)),
|
||||||
},
|
|
||||||
EvaluatedSystem::Graph { graph, translator } => {
|
EvaluatedSystem::Graph { graph, translator } => {
|
||||||
let Some(sys) = graph.node_weights().next()
|
let Some(sys) = graph.node_weights().next() else {
|
||||||
else {
|
|
||||||
return Err("No node found in graph".into());
|
return Err("No node found in graph".into());
|
||||||
};
|
};
|
||||||
Ok(statistics::of_RSsystem(translator, sys))
|
Ok(statistics::of_RSsystem(translator, sys))
|
||||||
@ -269,18 +264,15 @@ pub fn stats(system: &EvaluatedSystem) -> Result<String, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Prints a final set of entities in a terminating Reaction System.
|
/// Prints a final set of entities in a terminating Reaction System.
|
||||||
/// The system needs to terminate to return.
|
/// The system needs to terminate to return.
|
||||||
/// Equivalent to main_do(target, E)
|
/// Equivalent to main_do(target, E)
|
||||||
pub fn target(system: &EvaluatedSystem) -> Result<String, String> {
|
pub fn target(system: &EvaluatedSystem) -> Result<String, String> {
|
||||||
let (res, translator) = match system {
|
let (res, translator) = match system {
|
||||||
EvaluatedSystem::System { sys, translator } => {
|
EvaluatedSystem::System { sys, translator } =>
|
||||||
(transitions::target(sys)?, translator)
|
(transitions::target(sys)?, translator),
|
||||||
},
|
|
||||||
EvaluatedSystem::Graph { graph, translator } => {
|
EvaluatedSystem::Graph { graph, translator } => {
|
||||||
let Some(sys) = graph.node_weights().next()
|
let Some(sys) = graph.node_weights().next() else {
|
||||||
else {
|
|
||||||
return Err("No node found in graph".into());
|
return Err("No node found in graph".into());
|
||||||
};
|
};
|
||||||
(transitions::target(sys)?, translator)
|
(transitions::target(sys)?, translator)
|
||||||
@ -293,7 +285,6 @@ pub fn target(system: &EvaluatedSystem) -> Result<String, String> {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Finds the list of traversed states in a (deterministic) terminating
|
/// Finds the list of traversed states in a (deterministic) terminating
|
||||||
/// reaction.
|
/// reaction.
|
||||||
/// The system needs to terminate to return.
|
/// The system needs to terminate to return.
|
||||||
@ -302,10 +293,9 @@ pub fn traversed(system: &EvaluatedSystem) -> Result<String, String> {
|
|||||||
let (res, translator) = match system {
|
let (res, translator) = match system {
|
||||||
EvaluatedSystem::System { sys, translator } => {
|
EvaluatedSystem::System { sys, translator } => {
|
||||||
(transitions::run_separated(sys)?, translator)
|
(transitions::run_separated(sys)?, translator)
|
||||||
},
|
}
|
||||||
EvaluatedSystem::Graph { graph, translator } => {
|
EvaluatedSystem::Graph { graph, translator } => {
|
||||||
let Some(sys) = graph.node_weights().next()
|
let Some(sys) = graph.node_weights().next() else {
|
||||||
else {
|
|
||||||
return Err("No node found in graph".into());
|
return Err("No node found in graph".into());
|
||||||
};
|
};
|
||||||
(transitions::run_separated(sys)?, translator)
|
(transitions::run_separated(sys)?, translator)
|
||||||
@ -316,45 +306,36 @@ pub fn traversed(system: &EvaluatedSystem) -> Result<String, String> {
|
|||||||
|
|
||||||
output.push_str("The trace is composed by the set of entities:");
|
output.push_str("The trace is composed by the set of entities:");
|
||||||
for (e, _c, _t) in res {
|
for (e, _c, _t) in res {
|
||||||
output.push_str(
|
output.push_str(&format!(
|
||||||
&format!(
|
|
||||||
"{}",
|
"{}",
|
||||||
translator::RSsetDisplay::from(translator, &e)
|
translator::RSsetDisplay::from(translator, &e)
|
||||||
)
|
));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Ok(output)
|
Ok(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Finds the looping list of states in a reaction system with a perpetual
|
/// Finds the looping list of states in a reaction system with a perpetual
|
||||||
/// context. IMPORTANT: for loops, we assume Delta defines the process constant
|
/// context. IMPORTANT: for loops, we assume Delta defines the process constant
|
||||||
/// x = Q.x and the context process is x .
|
/// x = Q.x and the context process is x .
|
||||||
/// equivalent to main_do(loop,Es)
|
/// equivalent to main_do(loop,Es)
|
||||||
pub fn hoop(
|
pub fn hoop(
|
||||||
system: &EvaluatedSystem, symbol: String
|
system: &EvaluatedSystem,
|
||||||
) -> Result<String, String>
|
symbol: String
|
||||||
{
|
) -> Result<String, String> {
|
||||||
let (res, translator) = match system {
|
let (res, translator) = match system {
|
||||||
EvaluatedSystem::System { sys, translator } => {
|
EvaluatedSystem::System { sys, translator } => (sys, translator),
|
||||||
(sys, translator)
|
|
||||||
},
|
|
||||||
EvaluatedSystem::Graph { graph, translator } => {
|
EvaluatedSystem::Graph { graph, translator } => {
|
||||||
let Some(sys) = graph.node_weights().next()
|
let Some(sys) = graph.node_weights().next() else {
|
||||||
else {
|
|
||||||
return Err("No node found in graph".into());
|
return Err("No node found in graph".into());
|
||||||
};
|
};
|
||||||
(sys, translator)
|
(sys, translator)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// we retrieve the id for "x" and use it to find the corresponding loop
|
// we retrieve the id for "x" and use it to find the corresponding loop
|
||||||
let Some(id) = translator.encode_not_mut(&symbol)
|
let Some(id) = translator.encode_not_mut(&symbol) else {
|
||||||
else {
|
|
||||||
return Err(format!("Symbol {symbol} not found"));
|
return Err(format!("Symbol {symbol} not found"));
|
||||||
};
|
};
|
||||||
let res =
|
let res = match perpetual::lollipops_only_loop_named(res, id) {
|
||||||
match perpetual::lollipops_only_loop_named(res, id) {
|
|
||||||
Some(o) => o,
|
Some(o) => o,
|
||||||
None => {
|
None => {
|
||||||
return Err("No loop found.".into());
|
return Err("No loop found.".into());
|
||||||
@ -365,9 +346,10 @@ pub fn hoop(
|
|||||||
|
|
||||||
output.push_str("The loop is composed by the sets:");
|
output.push_str("The loop is composed by the sets:");
|
||||||
for e in res {
|
for e in res {
|
||||||
output.push_str(
|
output.push_str(&format!(
|
||||||
&format!( "{}", translator::RSsetDisplay::from(translator, &e))
|
"{}",
|
||||||
);
|
translator::RSsetDisplay::from(translator, &e)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(output)
|
Ok(output)
|
||||||
@ -376,16 +358,11 @@ pub fn hoop(
|
|||||||
/// Finds the frequency of each entity in the traversed states for a
|
/// Finds the frequency of each entity in the traversed states for a
|
||||||
/// (deterministic) terminating Reaction System.
|
/// (deterministic) terminating Reaction System.
|
||||||
/// equivalent to main_do(freq, PairList)
|
/// equivalent to main_do(freq, PairList)
|
||||||
pub fn freq(
|
pub fn freq(system: &EvaluatedSystem) -> Result<String, String> {
|
||||||
system: &EvaluatedSystem
|
|
||||||
) -> Result<String, String> {
|
|
||||||
let (sys, translator) = match system {
|
let (sys, translator) = match system {
|
||||||
EvaluatedSystem::System { sys, translator } => {
|
EvaluatedSystem::System { sys, translator } => (sys, translator),
|
||||||
(sys, translator)
|
|
||||||
},
|
|
||||||
EvaluatedSystem::Graph { graph, translator } => {
|
EvaluatedSystem::Graph { graph, translator } => {
|
||||||
let Some(sys) = graph.node_weights().next()
|
let Some(sys) = graph.node_weights().next() else {
|
||||||
else {
|
|
||||||
return Err("No node found in graph".into());
|
return Err("No node found in graph".into());
|
||||||
};
|
};
|
||||||
(sys, translator)
|
(sys, translator)
|
||||||
@ -400,37 +377,35 @@ pub fn freq(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Finds the frequency of each entity in the limit loop of a nonterminating
|
/// 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 ...
|
/// Reaction System whose context has the form Q1 ... Q1.Q2 ... Q2 ... Qn ...
|
||||||
/// equivalent to main_do(limitfreq, PairList)
|
/// equivalent to main_do(limitfreq, PairList)
|
||||||
pub fn limit_freq(
|
pub fn limit_freq(
|
||||||
system: &mut EvaluatedSystem,
|
system: &mut EvaluatedSystem,
|
||||||
experiment: String
|
experiment: String
|
||||||
) -> Result<String, String>
|
) -> Result<String, String> {
|
||||||
{
|
|
||||||
let (sys, translator): (&RSsystem, &mut Translator) = match system {
|
let (sys, translator): (&RSsystem, &mut Translator) = match system {
|
||||||
EvaluatedSystem::System { sys, translator } => {
|
EvaluatedSystem::System { sys, translator } => (sys, translator),
|
||||||
(sys, translator)
|
|
||||||
},
|
|
||||||
EvaluatedSystem::Graph { graph, translator } => {
|
EvaluatedSystem::Graph { graph, translator } => {
|
||||||
let Some(sys) = graph.node_weights().next()
|
let Some(sys) = graph.node_weights().next() else {
|
||||||
else {
|
|
||||||
return Err("No node found in graph".into());
|
return Err("No node found in graph".into());
|
||||||
};
|
};
|
||||||
(sys, translator)
|
(sys, translator)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (_, sets) = read_file(translator,
|
let (_, sets) = read_file(translator, experiment, parser_experiment)?;
|
||||||
experiment,
|
|
||||||
parser_experiment)?;
|
|
||||||
|
|
||||||
let res = match frequency::limit_frequency(&sets,
|
let res =
|
||||||
|
match frequency::limit_frequency(
|
||||||
|
&sets,
|
||||||
&sys.reaction_rules,
|
&sys.reaction_rules,
|
||||||
&sys.available_entities) {
|
&sys.available_entities)
|
||||||
|
{
|
||||||
Some(e) => e,
|
Some(e) => e,
|
||||||
None => {return Err("Error calculating frequency.".into());}
|
None => {
|
||||||
|
return Err("Error calculating frequency.".into());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(format!(
|
Ok(format!(
|
||||||
@ -439,7 +414,6 @@ pub fn limit_freq(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Finds the frequency of each entity in the traversed loops of a terminating
|
/// Finds the frequency of each entity in the traversed loops of a terminating
|
||||||
/// reaction system whose context has the form
|
/// reaction system whose context has the form
|
||||||
/// Q1 ... Q1.Q2 ... Q2 ... Qn ... Qn.nil and each Qi is repeated Wi times
|
/// Q1 ... Q1.Q2 ... Q2 ... Qn ... Qn.nil and each Qi is repeated Wi times
|
||||||
@ -451,28 +425,27 @@ pub fn fast_freq(
|
|||||||
) -> Result<String, String>
|
) -> Result<String, String>
|
||||||
{
|
{
|
||||||
let (sys, translator): (&RSsystem, &mut Translator) = match system {
|
let (sys, translator): (&RSsystem, &mut Translator) = match system {
|
||||||
EvaluatedSystem::System { sys, translator } => {
|
EvaluatedSystem::System { sys, translator } => (sys, translator),
|
||||||
(sys, translator)
|
|
||||||
},
|
|
||||||
EvaluatedSystem::Graph { graph, translator } => {
|
EvaluatedSystem::Graph { graph, translator } => {
|
||||||
let Some(sys) = graph.node_weights().next()
|
let Some(sys) = graph.node_weights().next() else {
|
||||||
else {
|
|
||||||
return Err("No node found in graph".into());
|
return Err("No node found in graph".into());
|
||||||
};
|
};
|
||||||
(sys, translator)
|
(sys, translator)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (weights, sets) = read_file(translator,
|
let (weights, sets) = read_file(translator, experiment, parser_experiment)?;
|
||||||
experiment,
|
|
||||||
parser_experiment)?;
|
|
||||||
|
|
||||||
let res = match frequency::fast_frequency(&sets,
|
let res = match frequency::fast_frequency(
|
||||||
|
&sets,
|
||||||
&sys.reaction_rules,
|
&sys.reaction_rules,
|
||||||
&sys.available_entities,
|
&sys.available_entities,
|
||||||
&weights) {
|
&weights,
|
||||||
|
) {
|
||||||
Some(e) => e,
|
Some(e) => e,
|
||||||
None => {return Err("Error calculating frequency.".into());}
|
None => {
|
||||||
|
return Err("Error calculating frequency.".into());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(format!(
|
Ok(format!(
|
||||||
@ -483,13 +456,11 @@ pub fn fast_freq(
|
|||||||
|
|
||||||
/// Computes the LTS.
|
/// Computes the LTS.
|
||||||
/// equivalent to main_do(digraph, Arcs) or to main_do(advdigraph, Arcs)
|
/// equivalent to main_do(digraph, Arcs) or to main_do(advdigraph, Arcs)
|
||||||
pub fn digraph(
|
pub fn digraph(system: &mut EvaluatedSystem) -> Result<(), String> {
|
||||||
system: &mut EvaluatedSystem
|
|
||||||
) -> Result<(), String> {
|
|
||||||
*system = if let EvaluatedSystem::System { sys, translator } = system {
|
*system = if let EvaluatedSystem::System { sys, translator } = system {
|
||||||
EvaluatedSystem::Graph {
|
EvaluatedSystem::Graph {
|
||||||
graph: graph::digraph(sys.clone())?,
|
graph: graph::digraph(sys.clone())?,
|
||||||
translator: translator.to_owned()
|
translator: translator.to_owned(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -497,7 +468,6 @@ pub fn digraph(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Output Functions
|
// Output Functions
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -505,33 +475,28 @@ pub fn digraph(
|
|||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
fn generate_node_pringting_fn<'a>(
|
fn generate_node_pringting_fn<'a>(
|
||||||
node_display: &'a Vec<NodeDisplay>,
|
node_display: &'a Vec<NodeDisplay>,
|
||||||
translator: Rc<Translator>
|
translator: Rc<Translator>,
|
||||||
) -> Box<dyn Fn(petgraph::prelude::NodeIndex, &'a RSsystem) -> String + 'a> {
|
) -> Box<dyn Fn(petgraph::prelude::NodeIndex, &'a RSsystem) -> String + 'a> {
|
||||||
// The type cannot be aliased since rust doesnt like generics.
|
// The type cannot be aliased since rust doesnt like generics.
|
||||||
// We are iterating over the node_display and constructing a function
|
// We are iterating over the node_display and constructing a function
|
||||||
// (accumulator) that prints out our formatted nodes. So at each step we
|
// (accumulator) that prints out our formatted nodes. So at each step we
|
||||||
// call the previous function and add the next string or function.
|
// call the previous function and add the next string or function.
|
||||||
let mut accumulator:
|
let mut accumulator: Box<dyn Fn(petgraph::prelude::NodeIndex, &RSsystem) -> String> =
|
||||||
Box<dyn Fn(petgraph::prelude::NodeIndex, &RSsystem) -> String>
|
Box::new(|_, _| String::new());
|
||||||
= Box::new(|_, _| String::new());
|
|
||||||
for nd in node_display {
|
for nd in node_display {
|
||||||
accumulator =
|
accumulator = match nd {
|
||||||
match nd {
|
NodeDisplay::Display(d) => {
|
||||||
NodeDisplay::Display(d) => { // retrieve from the graph module
|
// retrieve from the graph module the correct formatting
|
||||||
// the correct formatting function
|
// function
|
||||||
let val = translator.clone();
|
let val = translator.clone();
|
||||||
Box::new(
|
Box::new(move |i, n| {
|
||||||
move |i, n| (accumulator)(i, n) +
|
(accumulator)(i, n)
|
||||||
&graph::GraphMapNodesTy::from(
|
+ &graph::GraphMapNodesTy::from(d.clone(), val.clone()).get()(i, n)
|
||||||
d.clone(),
|
})
|
||||||
val.clone()
|
}
|
||||||
).get()(i, n))
|
NodeDisplay::Separator(s) => {
|
||||||
},
|
// we have a string so simply add it at the end
|
||||||
NodeDisplay::Separator(s) => { // we have a string so simply
|
Box::new(move |i, n| (accumulator)(i, n) + s)
|
||||||
// add it at the end
|
|
||||||
Box::new(
|
|
||||||
move |i, n| (accumulator)(i, n) + s
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -541,33 +506,28 @@ fn generate_node_pringting_fn<'a>(
|
|||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
fn generate_edge_pringting_fn<'a>(
|
fn generate_edge_pringting_fn<'a>(
|
||||||
edge_display: &'a Vec<EdgeDisplay>,
|
edge_display: &'a Vec<EdgeDisplay>,
|
||||||
translator: Rc<Translator>
|
translator: Rc<Translator>,
|
||||||
) -> Box<dyn Fn(petgraph::prelude::EdgeIndex, &'a RSlabel) -> String + 'a> {
|
) -> Box<dyn Fn(petgraph::prelude::EdgeIndex, &'a RSlabel) -> String + 'a> {
|
||||||
// The type cannot be aliased since rust doesnt like generics.
|
// The type cannot be aliased since rust doesnt like generics.
|
||||||
// We are iterating over the edge_display and constructing a function
|
// We are iterating over the edge_display and constructing a function
|
||||||
// (accumulator) that prints out our formatted nodes. So at each step we
|
// (accumulator) that prints out our formatted nodes. So at each step we
|
||||||
// call the previous function and add the next string or function.
|
// call the previous function and add the next string or function.
|
||||||
let mut accumulator:
|
let mut accumulator: Box<dyn Fn(petgraph::prelude::EdgeIndex, &RSlabel) -> String> =
|
||||||
Box<dyn Fn(petgraph::prelude::EdgeIndex, &RSlabel) -> String>
|
Box::new(|_, _| String::new());
|
||||||
= Box::new(|_, _| String::new());
|
|
||||||
for nd in edge_display {
|
for nd in edge_display {
|
||||||
accumulator =
|
accumulator = match nd {
|
||||||
match nd {
|
EdgeDisplay::Display(d) => {
|
||||||
EdgeDisplay::Display(d) => { // retrieve from the graph module
|
// retrieve from the graph module the correct formatting
|
||||||
// the correct formatting function
|
// function
|
||||||
let val = translator.clone();
|
let val = translator.clone();
|
||||||
Box::new(
|
Box::new(move |i, n| {
|
||||||
move |i, n| (accumulator)(i, n) +
|
(accumulator)(i, n)
|
||||||
&graph::GraphMapEdgesTy::from(
|
+ &graph::GraphMapEdgesTy::from(d.clone(), val.clone()).get()(i, n)
|
||||||
d.clone(),
|
})
|
||||||
val.clone()
|
}
|
||||||
).get()(i, n))
|
EdgeDisplay::Separator(s) => {
|
||||||
},
|
// we have a string so simply add it at the end
|
||||||
EdgeDisplay::Separator(s) => { // we have a string so simply
|
Box::new(move |i, n| (accumulator)(i, n) + s)
|
||||||
// add it at the end
|
|
||||||
Box::new(
|
|
||||||
move |i, n| (accumulator)(i, n) + s
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -578,30 +538,31 @@ fn generate_edge_pringting_fn<'a>(
|
|||||||
pub fn dot(
|
pub fn dot(
|
||||||
system: &EvaluatedSystem,
|
system: &EvaluatedSystem,
|
||||||
node_display: Vec<NodeDisplay>,
|
node_display: Vec<NodeDisplay>,
|
||||||
edge_display: Vec<EdgeDisplay>
|
edge_display: Vec<EdgeDisplay>,
|
||||||
) -> Result<String, String>
|
) -> Result<String, String> {
|
||||||
{
|
|
||||||
match system {
|
match system {
|
||||||
EvaluatedSystem::System { sys:_, translator:_ } =>
|
EvaluatedSystem::System {
|
||||||
Err("Supplied system is not a graph".into()),
|
sys: _,
|
||||||
|
translator: _,
|
||||||
|
} => Err("Supplied system is not a graph".into()),
|
||||||
EvaluatedSystem::Graph { graph, translator } => {
|
EvaluatedSystem::Graph { graph, translator } => {
|
||||||
let rc_translator = Rc::new(translator.clone());
|
let rc_translator = Rc::new(translator.clone());
|
||||||
// map each value to the corresponding value we want to display
|
// map each value to the corresponding value we want to display
|
||||||
// this is awful but rust is not a functional language so its all
|
// this is awful but rust is not a functional language so its all
|
||||||
// fine...
|
// fine...
|
||||||
let modified_graph = graph.map(
|
let modified_graph = graph.map(
|
||||||
generate_node_pringting_fn(&node_display, Rc::clone(&rc_translator)),
|
generate_node_pringting_fn(&node_display,
|
||||||
generate_edge_pringting_fn(&edge_display, rc_translator)
|
Rc::clone(&rc_translator)),
|
||||||
|
generate_edge_pringting_fn(&edge_display,
|
||||||
|
rc_translator),
|
||||||
);
|
);
|
||||||
|
|
||||||
let graph = Rc::new(graph.to_owned());
|
let graph = Rc::new(graph.to_owned());
|
||||||
|
|
||||||
let edge_formatter = graph::default_edge_formatter(
|
let edge_formatter =
|
||||||
Rc::clone(&graph)
|
graph::default_edge_formatter(Rc::clone(&graph));
|
||||||
);
|
let node_formatter =
|
||||||
let node_formatter = graph::default_node_formatter(
|
graph::default_node_formatter(Rc::clone(&graph));
|
||||||
Rc::clone(&graph)
|
|
||||||
);
|
|
||||||
|
|
||||||
let dot = rsdot::RSDot::with_attr_getters(
|
let dot = rsdot::RSDot::with_attr_getters(
|
||||||
&modified_graph,
|
&modified_graph,
|
||||||
@ -618,25 +579,33 @@ pub fn dot(
|
|||||||
/// Writes the specified graph to a file in .graphml format.
|
/// Writes the specified graph to a file in .graphml format.
|
||||||
pub fn graphml(system: &EvaluatedSystem) -> Result<String, String> {
|
pub fn graphml(system: &EvaluatedSystem) -> Result<String, String> {
|
||||||
match system {
|
match system {
|
||||||
EvaluatedSystem::System { sys:_, translator:_ } =>
|
EvaluatedSystem::System {
|
||||||
Err("Supplied system is not a graph".into()),
|
sys: _,
|
||||||
|
translator: _,
|
||||||
|
} => Err("Supplied system is not a graph".into()),
|
||||||
EvaluatedSystem::Graph { graph, translator } => {
|
EvaluatedSystem::Graph { graph, translator } => {
|
||||||
let rc_translator = Rc::new(translator.to_owned());
|
let rc_translator = Rc::new(translator.to_owned());
|
||||||
|
|
||||||
// map each value to the corresponding value we want to display
|
// map each value to the corresponding value we want to display
|
||||||
let modified_graph = graph.map(
|
let modified_graph = graph.map(
|
||||||
|id, node|
|
|id, node| {
|
||||||
graph::GraphMapNodesTy::from(
|
graph::GraphMapNodesTy::from(
|
||||||
graph::GraphMapNodes::Entities,
|
graph::GraphMapNodes::Entities,
|
||||||
Rc::clone(&rc_translator)
|
Rc::clone(&rc_translator),
|
||||||
).get()(id, node)
|
)
|
||||||
+ "; " +
|
.get()(id, node)
|
||||||
&graph::GraphMapNodesTy::from(
|
+ "; "
|
||||||
|
+ &graph::GraphMapNodesTy::from(
|
||||||
graph::GraphMapNodes::Context,
|
graph::GraphMapNodes::Context,
|
||||||
Rc::clone(&rc_translator)
|
Rc::clone(&rc_translator),
|
||||||
).get()(id, node),
|
)
|
||||||
graph::GraphMapEdgesTy::from(graph::GraphMapEdges::EntitiesAdded,
|
.get()(id, node)
|
||||||
Rc::clone(&rc_translator)).get()
|
},
|
||||||
|
graph::GraphMapEdgesTy::from(
|
||||||
|
graph::GraphMapEdges::EntitiesAdded,
|
||||||
|
Rc::clone(&rc_translator),
|
||||||
|
)
|
||||||
|
.get(),
|
||||||
);
|
);
|
||||||
|
|
||||||
use petgraph_graphml::GraphMl;
|
use petgraph_graphml::GraphMl;
|
||||||
@ -653,14 +622,12 @@ pub fn graphml(system: &EvaluatedSystem) -> Result<String, String> {
|
|||||||
/// Writes the specified graph, translator tuple to file.
|
/// Writes the specified graph, translator tuple to file.
|
||||||
/// N.B. graph size in memory might be much larger after serialization and
|
/// N.B. graph size in memory might be much larger after serialization and
|
||||||
/// deserialization.
|
/// deserialization.
|
||||||
pub fn serialize(
|
pub fn serialize(system: &EvaluatedSystem, path: String) -> Result<(), String> {
|
||||||
system: &EvaluatedSystem,
|
|
||||||
path: String
|
|
||||||
) -> Result<(), String>
|
|
||||||
{
|
|
||||||
match system {
|
match system {
|
||||||
EvaluatedSystem::System { sys:_, translator:_ } =>
|
EvaluatedSystem::System {
|
||||||
Err("Supplied system is not a graph".into()),
|
sys: _,
|
||||||
|
translator: _,
|
||||||
|
} => Err("Supplied system is not a graph".into()),
|
||||||
EvaluatedSystem::Graph { graph, translator } => {
|
EvaluatedSystem::Graph { graph, translator } => {
|
||||||
// relative path
|
// relative path
|
||||||
let mut path = std::path::PathBuf::from(path);
|
let mut path = std::path::PathBuf::from(path);
|
||||||
@ -669,12 +636,12 @@ pub fn serialize(
|
|||||||
let f = match fs::File::create(&path) {
|
let f = match fs::File::create(&path) {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(_) => return Err(format!("Error creating file {}.",
|
Err(_) => return Err(format!("Error creating file {}.",
|
||||||
path.to_str().unwrap()))
|
path.to_str().unwrap())),
|
||||||
};
|
};
|
||||||
|
|
||||||
match serialize::ser(f, graph, translator) {
|
match serialize::ser(f, graph, translator) {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(_) => Err("Error during serialization.".into())
|
Err(_) => Err("Error during serialization.".into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -690,7 +657,7 @@ pub fn deserialize(
|
|||||||
// relative path
|
// relative path
|
||||||
let mut path = match env::current_dir() {
|
let mut path = match env::current_dir() {
|
||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
Err(_) => return Err("Error getting current directory.".into())
|
Err(_) => return Err("Error getting current directory.".into()),
|
||||||
};
|
};
|
||||||
path = path.join(input_path);
|
path = path.join(input_path);
|
||||||
path.set_extension("cbor");
|
path.set_extension("cbor");
|
||||||
@ -698,16 +665,15 @@ pub fn deserialize(
|
|||||||
let f = match fs::File::open(&path) {
|
let f = match fs::File::open(&path) {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(_) => return Err(format!("Error opening file {}.",
|
Err(_) => return Err(format!("Error opening file {}.",
|
||||||
path.to_str().unwrap()))
|
path.to_str().unwrap())),
|
||||||
};
|
};
|
||||||
|
|
||||||
match serialize::de(f) {
|
match serialize::de(f) {
|
||||||
Ok(a) => Ok(a),
|
Ok(a) => Ok(a),
|
||||||
Err(_) => Err("Error during deserialization.".into())
|
Err(_) => Err("Error during deserialization.".into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Interpreting Instructions
|
// Interpreting Instructions
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -737,32 +703,40 @@ fn execute(
|
|||||||
}
|
}
|
||||||
Instruction::Target { so } => {
|
Instruction::Target { so } => {
|
||||||
save_options!(target(system)?, so);
|
save_options!(target(system)?, so);
|
||||||
},
|
}
|
||||||
Instruction::Run { so } => {
|
Instruction::Run { so } => {
|
||||||
save_options!(traversed(system)?, so);
|
save_options!(traversed(system)?, so);
|
||||||
},
|
}
|
||||||
Instruction::Loop { symbol, so } => {
|
Instruction::Loop { symbol, so } => {
|
||||||
save_options!(hoop(system, symbol)?, so);
|
save_options!(hoop(system, symbol)?, so);
|
||||||
},
|
}
|
||||||
Instruction::Frequency { so } => {
|
Instruction::Frequency { so } => {
|
||||||
save_options!(freq(system)?, so);
|
save_options!(freq(system)?, so);
|
||||||
},
|
}
|
||||||
Instruction::LimitFrequency { experiment, so } => {
|
Instruction::LimitFrequency { experiment, so } => {
|
||||||
save_options!(limit_freq(system, experiment)?, so);
|
save_options!(limit_freq(system, experiment)?, so);
|
||||||
},
|
}
|
||||||
Instruction::FastFrequency { experiment, so } => {
|
Instruction::FastFrequency { experiment, so } => {
|
||||||
save_options!(fast_freq(system, experiment)?, so);
|
save_options!(fast_freq(system, experiment)?, so);
|
||||||
},
|
}
|
||||||
Instruction::Digraph { gso } => {
|
Instruction::Digraph { gso } => {
|
||||||
for save in gso {
|
for save in gso {
|
||||||
digraph(system)?;
|
digraph(system)?;
|
||||||
match save {
|
match save {
|
||||||
GraphSaveOptions::Dot { node_display, edge_display, so } => {
|
GraphSaveOptions::Dot {
|
||||||
save_options!(dot(system, node_display, edge_display)?, so);
|
node_display: nd,
|
||||||
},
|
edge_display: ed,
|
||||||
GraphSaveOptions::GraphML { node_display:_, edge_display:_, so } => {
|
so,
|
||||||
|
} => {
|
||||||
|
save_options!(dot(system, nd, ed)?, so);
|
||||||
|
}
|
||||||
|
GraphSaveOptions::GraphML {
|
||||||
|
node_display: _,
|
||||||
|
edge_display: _,
|
||||||
|
so,
|
||||||
|
} => {
|
||||||
save_options!(graphml(system)?, so);
|
save_options!(graphml(system)?, so);
|
||||||
},
|
}
|
||||||
GraphSaveOptions::Serialize { path } => {
|
GraphSaveOptions::Serialize { path } => {
|
||||||
serialize(system, path)?;
|
serialize(system, path)?;
|
||||||
}
|
}
|
||||||
@ -776,8 +750,10 @@ fn execute(
|
|||||||
pub fn run(path: String) -> Result<(), String> {
|
pub fn run(path: String) -> Result<(), String> {
|
||||||
let mut translator = Translator::new();
|
let mut translator = Translator::new();
|
||||||
|
|
||||||
let Instructions { system, instructions } =
|
let Instructions {
|
||||||
read_file(&mut translator, path, parser_instructions)?;
|
system,
|
||||||
|
instructions,
|
||||||
|
} = read_file(&mut translator, path, parser_instructions)?;
|
||||||
|
|
||||||
let mut system = system.compute(translator)?;
|
let mut system = system.compute(translator)?;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user