Files
ReactionSystems/src/rsprocess/confluence.rs

148 lines
4.1 KiB
Rust
Raw Normal View History

2025-06-22 16:09:31 +02:00
#![allow(dead_code)]
use super::perpetual::{
2025-06-22 19:37:57 +02:00
lollipops_decomposed_named,
lollipops_named,
lollipops_only_loop_decomposed,
lollipops_only_loop_decomposed_named,
lollipops_prefix_len_loop_decomposed,
lollipops_prefix_len_loop_decomposed_named
};
2025-06-22 16:09:31 +02:00
use super::structure::{RSenvironment, RSreaction, RSset};
use super::translator::IdType;
use std::cmp;
2025-06-23 17:07:46 +02:00
use std::collections::HashSet;
2025-06-22 16:09:31 +02:00
2025-06-22 18:57:35 +02:00
// see confluent, confluents
2025-06-22 16:09:31 +02:00
pub fn confluent(
delta: &RSenvironment,
reaction_rules: &[RSreaction],
entities: &[RSset],
) -> Option<(usize, usize, Vec<RSset>)> {
2025-06-22 19:37:57 +02:00
let all_loops = lollipops_prefix_len_loop_decomposed(delta,
reaction_rules,
entities.first()?);
let (prefix_len, hoop) = all_loops.first()?.clone();
let dimension = hoop.len();
let mut max_distance = prefix_len;
2025-06-22 16:09:31 +02:00
for available_entities in entities.iter().skip(1) {
2025-06-22 19:37:57 +02:00
let all_loops = lollipops_prefix_len_loop_decomposed(delta,
reaction_rules,
available_entities);
2025-06-22 16:09:31 +02:00
// FIXME we take just the first? do we compare all?
2025-06-22 19:37:57 +02:00
let (prefix_len, new_hoop) = all_loops.first()?;
2025-06-22 20:55:35 +02:00
if new_hoop.len() != dimension || !hoop.contains(new_hoop.first()?) {
2025-06-22 16:09:31 +02:00
return None;
}
2025-06-22 19:37:57 +02:00
max_distance = cmp::max(max_distance, *prefix_len);
2025-06-22 16:09:31 +02:00
}
Some((max_distance, dimension, hoop))
}
2025-06-22 18:57:35 +02:00
// see confluent, confluents
2025-06-22 16:09:31 +02:00
pub fn confluent_named(
delta: &RSenvironment,
reaction_rules: &[RSreaction],
entities: &[RSset],
symb: IdType
) -> Option<(usize, usize, Vec<RSset>)> {
2025-06-22 19:37:57 +02:00
let (prefix_len, first_hoop) =
lollipops_prefix_len_loop_decomposed_named(delta,
reaction_rules,
entities.first()?,
symb)?;
let dimension = first_hoop.len();
let mut max_distance = prefix_len;
let hoop = first_hoop;
2025-06-22 16:09:31 +02:00
for available_entities in entities.iter().skip(1) {
2025-06-22 19:37:57 +02:00
let (prefix_len, new_hoop) =
2025-06-22 18:57:35 +02:00
lollipops_prefix_len_loop_decomposed_named(delta,
reaction_rules,
available_entities,
2025-06-22 19:37:57 +02:00
symb)?;
2025-06-22 20:55:35 +02:00
if new_hoop.len() != dimension || !hoop.contains(new_hoop.first()?) {
2025-06-22 16:09:31 +02:00
return None;
}
2025-06-22 19:37:57 +02:00
max_distance = cmp::max(max_distance, prefix_len);
2025-06-22 16:09:31 +02:00
}
Some((max_distance, dimension, hoop))
}
2025-06-22 20:55:35 +02:00
// -----------------------------------------------------------------------------
pub fn invariant_named(
delta: &RSenvironment,
reaction_rules: &[RSreaction],
entities: &[RSset],
symb: IdType
) -> Option<(Vec<RSset>, Vec<RSset>)> {
let (prefix, hoop) = lollipops_decomposed_named(delta,
reaction_rules,
entities.first()?,
symb)?;
let mut invariant = vec![];
invariant.append(&mut prefix.clone());
invariant.append(&mut hoop.clone());
let dimension = hoop.len();
for available_entities in entities {
let (new_prefix, new_hoop) = lollipops_decomposed_named(delta,
reaction_rules,
available_entities,
symb)?;
if new_hoop.len() != dimension || !hoop.contains(new_hoop.first()?) {
return None
}
invariant.append(&mut new_prefix.clone());
}
2025-06-23 17:07:46 +02:00
// remove duplicates, maybe better with sorting?
invariant =
invariant
.iter()
.cloned()
.collect::<HashSet<_>>()
.iter()
.cloned()
.collect::<Vec<_>>();
2025-06-22 20:55:35 +02:00
Some((invariant, hoop))
}
2025-06-23 17:07:46 +02:00
// -----------------------------------------------------------------------------
pub fn loop_confluent_named(
deltas: &[RSenvironment],
reaction_rules: &[RSreaction],
entities: &[RSset],
symb: IdType
) -> Option<Vec<(usize, usize, Vec<RSset>)>> {
deltas.iter()
.map(|q| confluent_named(q, reaction_rules, entities, symb))
.collect::<Option<Vec<_>>>()
}
#[allow(clippy::type_complexity)]
pub fn strong_confluent_named(
deltas: &[RSenvironment],
reaction_rules: &[RSreaction],
entities: &[RSset],
symb: IdType
) -> Option<Vec<(Vec<RSset>, usize, Vec<RSset>)>> {
deltas.iter()
.map(|q| {
let (invariant, hoop) = invariant_named(q,
reaction_rules,
entities,
symb)?;
let length = invariant.len();
Some((invariant, length, hoop)) }
)
.collect::<Option<Vec<_>>>()
}