use pnets::standard::Net;
use pnets::{arc, TransitionId};
use crate::modifications::{Agglomeration, Modification};
use crate::reducers::reduce::{ConservativeReduce, TransitionReduce};
use crate::reducers::Reduce;
pub struct SimpleChainReducer;
impl ConservativeReduce<Net> for SimpleChainReducer {}
impl Reduce<Net> for SimpleChainReducer {
fn reduce(net: &mut Net, modifications: &mut Vec<Modification>) {
if !net.transitions.is_empty() {
for tr in (0..net.transitions.len()).map(|v| TransitionId::from(v)) {
Self::transition_reduce(net, tr, modifications);
}
}
}
}
impl TransitionReduce<Net> for SimpleChainReducer {
fn transition_reduce(net: &mut Net, tr: TransitionId, modifications: &mut Vec<Modification>) {
if net[tr].produce.len() == 1 && net[tr].consume.len() == 1 {
let pl_dest = net[tr].produce.iter().next().unwrap().0;
if net[pl_dest].produced_by.len() == 1 && net[pl_dest].initial == 0 {
let pl_source = net[tr].consume.iter().next().unwrap().0;
let new_pl = net.create_place();
for old_arc in net[pl_source]
.get_arcs()
.iter()
.chain(net[pl_dest].get_arcs().iter())
{
match *old_arc {
arc::Kind::Consume(_, tr, w) => {
net.add_arc(arc::Kind::Consume(new_pl, tr, w)).unwrap();
}
arc::Kind::Produce(_, tr, w) => {
net.add_arc(arc::Kind::Produce(new_pl, tr, w)).unwrap();
}
_ => {}
}
}
net[new_pl].initial = net[pl_source].initial;
net.delete_place(pl_dest);
net.delete_place(pl_source);
net.delete_transition(tr);
modifications.push(Modification::Agglomeration(Agglomeration {
deleted_places: vec![(pl_source, 1), (pl_dest, 1)],
new_place: new_pl,
constant: 0,
factor: 1,
}));
}
}
}
}