2025-08-24 02:01:24 +02:00
|
|
|
use serde::{Deserialize, Serialize};
|
2025-08-23 23:40:19 +02:00
|
|
|
use std::collections::VecDeque;
|
2025-08-29 17:59:49 +02:00
|
|
|
use std::fmt::Debug;
|
2025-08-23 23:40:19 +02:00
|
|
|
use std::hash::Hash;
|
|
|
|
|
use std::rc::Rc;
|
|
|
|
|
|
2025-08-29 17:59:49 +02:00
|
|
|
use super::reaction::{PositiveReaction, Reaction};
|
|
|
|
|
use super::set::{BasicSet, PositiveSet, Set};
|
|
|
|
|
use super::element::{IdState, IdType};
|
2025-08-27 23:58:43 +02:00
|
|
|
use super::translator::{Translator, PrintableWithTranslator, Formatter};
|
2025-08-23 23:40:19 +02:00
|
|
|
|
2025-08-29 17:59:49 +02:00
|
|
|
pub trait BasicProcess
|
|
|
|
|
where Self: Clone + Debug + Default + PartialEq + Eq + Hash + Serialize +
|
|
|
|
|
PrintableWithTranslator,
|
|
|
|
|
for<'a> Self: Deserialize<'a> {
|
|
|
|
|
type Id;
|
|
|
|
|
type Set: BasicSet;
|
|
|
|
|
|
|
|
|
|
fn concat(&self, new: &Self) -> Self;
|
|
|
|
|
fn all_elements(&self) -> Self::Set;
|
|
|
|
|
fn filter_delta(&self, id: &Self::Id) -> Option<&Self::Set>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
2025-08-23 23:40:19 +02:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
|
|
|
pub enum Process {
|
|
|
|
|
Nill,
|
|
|
|
|
RecursiveIdentifier {
|
|
|
|
|
identifier: IdType,
|
|
|
|
|
},
|
|
|
|
|
EntitySet {
|
|
|
|
|
entities: Set,
|
|
|
|
|
next_process: Rc<Process>,
|
|
|
|
|
},
|
|
|
|
|
Guarded {
|
|
|
|
|
reaction: Reaction,
|
|
|
|
|
next_process: Rc<Process>,
|
|
|
|
|
},
|
|
|
|
|
WaitEntity {
|
|
|
|
|
repeat: i64,
|
|
|
|
|
repeated_process: Rc<Process>,
|
|
|
|
|
next_process: Rc<Process>,
|
|
|
|
|
},
|
|
|
|
|
Summation {
|
|
|
|
|
children: Vec<Rc<Process>>,
|
|
|
|
|
},
|
|
|
|
|
NondeterministicChoice {
|
|
|
|
|
children: Vec<Rc<Process>>,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-29 17:59:49 +02:00
|
|
|
impl BasicProcess for Process {
|
|
|
|
|
type Id = IdType;
|
|
|
|
|
type Set = Set;
|
|
|
|
|
|
|
|
|
|
fn concat(&self, new: &Self) -> Self {
|
2025-08-23 23:40:19 +02:00
|
|
|
match (self, new) {
|
|
|
|
|
(
|
2025-08-29 17:59:49 +02:00
|
|
|
Self::NondeterministicChoice { children: c1 },
|
|
|
|
|
Self::NondeterministicChoice { children: c2 },
|
|
|
|
|
) => Self::NondeterministicChoice {
|
2025-08-23 23:40:19 +02:00
|
|
|
children: [c1.clone(), c2.clone()].concat(),
|
|
|
|
|
},
|
2025-08-29 17:59:49 +02:00
|
|
|
(Self::NondeterministicChoice { children }, new)
|
|
|
|
|
| (new, Self::NondeterministicChoice { children }) => {
|
2025-08-23 23:40:19 +02:00
|
|
|
let mut new_children = children.clone();
|
|
|
|
|
new_children.push(Rc::new(new.clone()));
|
2025-08-29 17:59:49 +02:00
|
|
|
Self::NondeterministicChoice {
|
2025-08-23 23:40:19 +02:00
|
|
|
children: new_children,
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-29 17:59:49 +02:00
|
|
|
(_, _) => Self::NondeterministicChoice {
|
2025-08-23 23:40:19 +02:00
|
|
|
children: vec![Rc::new(self.clone()), Rc::new(new.clone())],
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// returns all elements used
|
2025-08-29 17:59:49 +02:00
|
|
|
fn all_elements(&self) -> Self::Set {
|
2025-08-23 23:40:19 +02:00
|
|
|
let mut queue = VecDeque::from([self]);
|
2025-08-29 17:59:49 +02:00
|
|
|
let mut elements = Self::Set::default();
|
2025-08-23 23:40:19 +02:00
|
|
|
|
|
|
|
|
while let Some(el) = queue.pop_front() {
|
|
|
|
|
match el {
|
|
|
|
|
Self::Nill => {}
|
|
|
|
|
Self::RecursiveIdentifier { identifier: _ } => {}
|
|
|
|
|
Self::EntitySet {
|
|
|
|
|
entities,
|
|
|
|
|
next_process,
|
|
|
|
|
} => {
|
|
|
|
|
elements.push(entities);
|
|
|
|
|
queue.push_back(next_process);
|
|
|
|
|
}
|
|
|
|
|
Self::Guarded { reaction, next_process } => {
|
|
|
|
|
elements.push(&reaction.reactants);
|
|
|
|
|
elements.push(&reaction.inhibitors);
|
|
|
|
|
elements.push(&reaction.products);
|
|
|
|
|
queue.push_back(next_process);
|
|
|
|
|
}
|
|
|
|
|
Self::WaitEntity {
|
|
|
|
|
repeat: _,
|
|
|
|
|
repeated_process,
|
|
|
|
|
next_process,
|
|
|
|
|
} => {
|
|
|
|
|
queue.push_back(repeated_process);
|
|
|
|
|
queue.push_back(next_process);
|
|
|
|
|
}
|
|
|
|
|
Self::Summation { children } => {
|
|
|
|
|
for c in children {
|
|
|
|
|
queue.push_back(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Self::NondeterministicChoice { children } => {
|
|
|
|
|
for c in children {
|
|
|
|
|
queue.push_back(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
elements
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Finds only the rules X = pre(Q, rec(X)), but not only x = pre(Q, rec(x))
|
|
|
|
|
/// to use in filter_map.
|
2025-08-29 17:59:49 +02:00
|
|
|
fn filter_delta<'a>(
|
2025-08-23 23:40:19 +02:00
|
|
|
&'a self,
|
2025-08-29 17:59:49 +02:00
|
|
|
id: &Self::Id
|
|
|
|
|
) -> Option<&'a Self::Set> {
|
2025-08-23 23:40:19 +02:00
|
|
|
if let Self::EntitySet { entities, next_process } = self
|
|
|
|
|
&& let Self::RecursiveIdentifier { identifier } = &**next_process
|
|
|
|
|
&& identifier == id
|
|
|
|
|
{
|
|
|
|
|
return Some(entities);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-24 02:01:24 +02:00
|
|
|
|
2025-08-29 17:59:49 +02:00
|
|
|
impl Default for Process {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self::Nill
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-24 02:01:24 +02:00
|
|
|
impl PrintableWithTranslator for Process {
|
|
|
|
|
fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator)
|
|
|
|
|
-> std::fmt::Result {
|
|
|
|
|
match self {
|
|
|
|
|
Self::Nill => {
|
|
|
|
|
write!(f, "Nill")
|
|
|
|
|
},
|
|
|
|
|
Self::RecursiveIdentifier { identifier } => {
|
|
|
|
|
write!(f,
|
|
|
|
|
"[{}]",
|
|
|
|
|
translator
|
|
|
|
|
.decode(*identifier)
|
|
|
|
|
.unwrap_or("Missing".into()))
|
|
|
|
|
},
|
|
|
|
|
Self::EntitySet { entities, next_process, } => {
|
|
|
|
|
write!(
|
|
|
|
|
f,
|
|
|
|
|
"{}.{}",
|
|
|
|
|
Formatter::from(translator, entities),
|
|
|
|
|
Formatter::from(translator, &**next_process)
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
Self::Guarded { reaction, next_process } => {
|
|
|
|
|
write!(f,
|
|
|
|
|
"?{}?.{}",
|
|
|
|
|
Formatter::from(translator, reaction),
|
|
|
|
|
Formatter::from(translator, &**next_process))
|
|
|
|
|
},
|
|
|
|
|
Self::WaitEntity { repeat, repeated_process, next_process, } => {
|
|
|
|
|
write!(
|
|
|
|
|
f,
|
|
|
|
|
"({})^{repeat}.{}",
|
|
|
|
|
Formatter::from(translator, &**repeated_process),
|
|
|
|
|
Formatter::from(translator, &**next_process)
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
Self::Summation { children } => {
|
|
|
|
|
write!(f, "[")?;
|
|
|
|
|
let mut it = children.iter().peekable();
|
|
|
|
|
while let Some(child) = it.next() {
|
|
|
|
|
if it.peek().is_none() {
|
|
|
|
|
write!(
|
|
|
|
|
f,
|
|
|
|
|
"{}",
|
|
|
|
|
Formatter::from(translator, &**child)
|
|
|
|
|
)?;
|
|
|
|
|
} else {
|
|
|
|
|
write!(
|
|
|
|
|
f,
|
|
|
|
|
"{} + ",
|
|
|
|
|
Formatter::from(translator, &**child)
|
|
|
|
|
)?;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
write!(f, "]")
|
|
|
|
|
}
|
|
|
|
|
Self::NondeterministicChoice { children } => {
|
|
|
|
|
write!(f, "[")?;
|
|
|
|
|
let mut it = children.iter().peekable();
|
|
|
|
|
while let Some(child) = it.next() {
|
|
|
|
|
if it.peek().is_none() {
|
|
|
|
|
write!(
|
|
|
|
|
f,
|
|
|
|
|
"{}",
|
|
|
|
|
Formatter::from(translator, &**child)
|
|
|
|
|
)?;
|
|
|
|
|
} else {
|
|
|
|
|
write!(
|
|
|
|
|
f,
|
|
|
|
|
"{}, ",
|
|
|
|
|
Formatter::from(translator, &**child)
|
|
|
|
|
)?;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
write!(f, "]")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-29 17:59:49 +02:00
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
|
|
|
pub enum PositiveProcess {
|
|
|
|
|
Nill,
|
|
|
|
|
RecursiveIdentifier {
|
|
|
|
|
identifier: IdType,
|
|
|
|
|
},
|
|
|
|
|
EntitySet {
|
|
|
|
|
entities: PositiveSet,
|
|
|
|
|
next_process: Rc<PositiveProcess>,
|
|
|
|
|
},
|
|
|
|
|
Guarded {
|
|
|
|
|
reaction: PositiveReaction,
|
|
|
|
|
next_process: Rc<PositiveProcess>,
|
|
|
|
|
},
|
|
|
|
|
WaitEntity {
|
|
|
|
|
repeat: i64,
|
|
|
|
|
repeated_process: Rc<PositiveProcess>,
|
|
|
|
|
next_process: Rc<PositiveProcess>,
|
|
|
|
|
},
|
|
|
|
|
Summation {
|
|
|
|
|
children: Vec<Rc<PositiveProcess>>,
|
|
|
|
|
},
|
|
|
|
|
NondeterministicChoice {
|
|
|
|
|
children: Vec<Rc<PositiveProcess>>,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl BasicProcess for PositiveProcess {
|
|
|
|
|
type Id = IdType;
|
|
|
|
|
type Set = PositiveSet;
|
|
|
|
|
|
|
|
|
|
fn concat(&self, new: &Self) -> Self {
|
|
|
|
|
match (self, new) {
|
|
|
|
|
(
|
|
|
|
|
Self::NondeterministicChoice { children: c1 },
|
|
|
|
|
Self::NondeterministicChoice { children: c2 },
|
|
|
|
|
) => Self::NondeterministicChoice {
|
|
|
|
|
children: [c1.clone(), c2.clone()].concat(),
|
|
|
|
|
},
|
|
|
|
|
(Self::NondeterministicChoice { children }, new)
|
|
|
|
|
| (new, Self::NondeterministicChoice { children }) => {
|
|
|
|
|
let mut new_children = children.clone();
|
|
|
|
|
new_children.push(Rc::new(new.clone()));
|
|
|
|
|
Self::NondeterministicChoice {
|
|
|
|
|
children: new_children,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
(_, _) => Self::NondeterministicChoice {
|
|
|
|
|
children: vec![Rc::new(self.clone()), Rc::new(new.clone())],
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// returns all elements used
|
|
|
|
|
fn all_elements(&self) -> Self::Set {
|
|
|
|
|
let mut queue = VecDeque::from([self]);
|
|
|
|
|
let mut elements = Self::Set::default();
|
|
|
|
|
|
|
|
|
|
while let Some(el) = queue.pop_front() {
|
|
|
|
|
match el {
|
|
|
|
|
Self::Nill => {}
|
|
|
|
|
Self::RecursiveIdentifier { identifier: _ } => {}
|
|
|
|
|
Self::EntitySet {
|
|
|
|
|
entities,
|
|
|
|
|
next_process,
|
|
|
|
|
} => {
|
|
|
|
|
elements.push(entities);
|
|
|
|
|
queue.push_back(next_process);
|
|
|
|
|
}
|
|
|
|
|
Self::Guarded { reaction, next_process } => {
|
|
|
|
|
elements.push(&reaction.reactants);
|
|
|
|
|
elements.push(&reaction.products);
|
|
|
|
|
queue.push_back(next_process);
|
|
|
|
|
}
|
|
|
|
|
Self::WaitEntity {
|
|
|
|
|
repeat: _,
|
|
|
|
|
repeated_process,
|
|
|
|
|
next_process,
|
|
|
|
|
} => {
|
|
|
|
|
queue.push_back(repeated_process);
|
|
|
|
|
queue.push_back(next_process);
|
|
|
|
|
}
|
|
|
|
|
Self::Summation { children } => {
|
|
|
|
|
for c in children {
|
|
|
|
|
queue.push_back(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Self::NondeterministicChoice { children } => {
|
|
|
|
|
for c in children {
|
|
|
|
|
queue.push_back(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
elements
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Finds only the rules X = pre(Q, rec(X)), but not only x = pre(Q, rec(x))
|
|
|
|
|
/// to use in filter_map.
|
|
|
|
|
fn filter_delta(&self, id: &Self::Id) -> Option<&Self::Set> {
|
|
|
|
|
if let Self::EntitySet { entities, next_process } = self
|
|
|
|
|
&& let Self::RecursiveIdentifier { identifier } = &**next_process
|
|
|
|
|
&& identifier == id
|
|
|
|
|
{
|
|
|
|
|
return Some(entities);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for PositiveProcess {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self::Nill
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PrintableWithTranslator for PositiveProcess {
|
|
|
|
|
fn print(&self, f: &mut std::fmt::Formatter, translator: &Translator)
|
|
|
|
|
-> std::fmt::Result {
|
|
|
|
|
match self {
|
|
|
|
|
Self::Nill => {
|
|
|
|
|
write!(f, "Nill")
|
|
|
|
|
},
|
|
|
|
|
Self::RecursiveIdentifier { identifier } => {
|
|
|
|
|
write!(f,
|
|
|
|
|
"[{}]",
|
|
|
|
|
translator
|
|
|
|
|
.decode(*identifier)
|
|
|
|
|
.unwrap_or("Missing".into()))
|
|
|
|
|
},
|
|
|
|
|
Self::EntitySet { entities, next_process, } => {
|
|
|
|
|
write!(
|
|
|
|
|
f,
|
|
|
|
|
"{}.{}",
|
|
|
|
|
Formatter::from(translator, entities),
|
|
|
|
|
Formatter::from(translator, &**next_process)
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
Self::Guarded { reaction, next_process } => {
|
|
|
|
|
write!(f,
|
|
|
|
|
"?{}?.{}",
|
|
|
|
|
Formatter::from(translator, reaction),
|
|
|
|
|
Formatter::from(translator, &**next_process))
|
|
|
|
|
},
|
|
|
|
|
Self::WaitEntity { repeat, repeated_process, next_process, } => {
|
|
|
|
|
write!(
|
|
|
|
|
f,
|
|
|
|
|
"({})^{repeat}.{}",
|
|
|
|
|
Formatter::from(translator, &**repeated_process),
|
|
|
|
|
Formatter::from(translator, &**next_process)
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
Self::Summation { children } => {
|
|
|
|
|
write!(f, "[")?;
|
|
|
|
|
let mut it = children.iter().peekable();
|
|
|
|
|
while let Some(child) = it.next() {
|
|
|
|
|
if it.peek().is_none() {
|
|
|
|
|
write!(
|
|
|
|
|
f,
|
|
|
|
|
"{}",
|
|
|
|
|
Formatter::from(translator, &**child)
|
|
|
|
|
)?;
|
|
|
|
|
} else {
|
|
|
|
|
write!(
|
|
|
|
|
f,
|
|
|
|
|
"{} + ",
|
|
|
|
|
Formatter::from(translator, &**child)
|
|
|
|
|
)?;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
write!(f, "]")
|
|
|
|
|
}
|
|
|
|
|
Self::NondeterministicChoice { children } => {
|
|
|
|
|
write!(f, "[")?;
|
|
|
|
|
let mut it = children.iter().peekable();
|
|
|
|
|
while let Some(child) = it.next() {
|
|
|
|
|
if it.peek().is_none() {
|
|
|
|
|
write!(
|
|
|
|
|
f,
|
|
|
|
|
"{}",
|
|
|
|
|
Formatter::from(translator, &**child)
|
|
|
|
|
)?;
|
|
|
|
|
} else {
|
|
|
|
|
write!(
|
|
|
|
|
f,
|
|
|
|
|
"{}, ",
|
|
|
|
|
Formatter::from(translator, &**child)
|
|
|
|
|
)?;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
write!(f, "]")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<&Process> for PositiveProcess {
|
|
|
|
|
fn from(value: &Process) -> Self {
|
|
|
|
|
match value {
|
|
|
|
|
Process::Nill => Self::Nill,
|
|
|
|
|
Process::EntitySet { entities, next_process } =>
|
|
|
|
|
Self::EntitySet {
|
|
|
|
|
entities: entities.to_positive_set(IdState::Positive),
|
|
|
|
|
next_process: Rc::new((&**next_process).into()) },
|
|
|
|
|
Process::RecursiveIdentifier { identifier } =>
|
|
|
|
|
Self::RecursiveIdentifier { identifier: *identifier },
|
|
|
|
|
Process::Guarded { reaction, next_process } => // TODO: is this right?
|
|
|
|
|
Self::Guarded {
|
|
|
|
|
reaction: PositiveReaction {
|
|
|
|
|
reactants: reaction.reactants
|
|
|
|
|
.to_positive_set(IdState::Positive)
|
|
|
|
|
.union(&reaction.inhibitors
|
|
|
|
|
.to_positive_set(IdState::Negative)),
|
|
|
|
|
products: reaction.products
|
|
|
|
|
.to_positive_set(IdState::Positive)
|
|
|
|
|
},
|
|
|
|
|
next_process: Rc::new((&**next_process).into())},
|
|
|
|
|
Process::WaitEntity { repeat, repeated_process, next_process } =>
|
|
|
|
|
Self::WaitEntity {
|
|
|
|
|
repeat: *repeat,
|
|
|
|
|
repeated_process: Rc::new((&**repeated_process).into()),
|
|
|
|
|
next_process: Rc::new((&**next_process).into()) },
|
|
|
|
|
Process::Summation { children } =>
|
|
|
|
|
Self::Summation {
|
|
|
|
|
children: children.iter().map(|c| Rc::new((&**c).into()))
|
|
|
|
|
.collect() },
|
|
|
|
|
Process::NondeterministicChoice { children } =>
|
|
|
|
|
Self::NondeterministicChoice {
|
|
|
|
|
children: children.iter().map(|c| Rc::new((&**c).into()))
|
|
|
|
|
.collect() }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<Process>for PositiveProcess {
|
|
|
|
|
fn from(value: Process) -> Self {
|
|
|
|
|
(&value).into()
|
|
|
|
|
}
|
|
|
|
|
}
|