use crate::ActFrm;
use crate::Action;
use crate::FixedPointOperator;
use crate::ModalityOperator;
use crate::MultiAction;
use crate::RegFrm;
use crate::Span;
use crate::StateFrm;
use crate::StateFrmOp;
use crate::StateVarDecl;
use merc_lts::TransitionLabel;
use merc_refinement::CounterExample;
pub fn generate_formula<L: TransitionLabel>(counter_example: &CounterExample<L>) -> StateFrm {
match counter_example {
CounterExample::Trace(trace) => {
let mut expr = StateFrm::True;
for label in trace.iter().rev() {
expr = StateFrm::Modality {
operator: ModalityOperator::Diamond,
formula: RegFrm::Action(ActFrm::MultAct(label_to_multi_action(label))),
expr: Box::new(expr),
}
}
expr
}
CounterExample::WeakTrace(trace) => weaktrace_formula(trace, StateFrm::True, ModalityOperator::Diamond),
CounterExample::Divergence(trace) => weaktrace_formula(
trace,
StateFrm::FixedPoint {
operator: FixedPointOperator::Greatest,
variable: StateVarDecl {
identifier: "X".to_string(),
arguments: Vec::new(),
span: Span::default(),
},
body: Box::new(StateFrm::Modality {
operator: ModalityOperator::Diamond,
formula: RegFrm::Action(ActFrm::MultAct(MultiAction::tau())),
expr: Box::new(StateFrm::Id("X".to_string(), Vec::new())),
}),
},
ModalityOperator::Diamond,
),
CounterExample::StableFailures(trace, refusals) => {
let inner = refusals
.iter()
.map(|l| StateFrm::Modality {
operator: ModalityOperator::Box,
formula: RegFrm::Action(ActFrm::MultAct(label_to_multi_action(l))),
expr: Box::new(StateFrm::False),
})
.fold(
StateFrm::Modality {
operator: ModalityOperator::Box,
formula: RegFrm::Action(ActFrm::MultAct(MultiAction::tau())),
expr: Box::new(StateFrm::False),
},
|acc, expr| StateFrm::Binary {
op: StateFrmOp::Conjunction,
lhs: Box::new(acc),
rhs: Box::new(expr),
},
);
weaktrace_formula(trace, inner, ModalityOperator::Diamond)
}
CounterExample::ImpossibleFutures(trace, futures) => {
let expressions = futures
.iter()
.map(|future| weaktrace_formula(future, StateFrm::False, ModalityOperator::Box))
.collect::<Vec<_>>();
let expr = expressions
.into_iter()
.fold(StateFrm::True, |acc, expr| StateFrm::Binary {
op: StateFrmOp::Conjunction,
lhs: Box::new(acc),
rhs: Box::new(expr),
});
weaktrace_formula(trace, expr, ModalityOperator::Diamond)
}
}
}
fn weaktrace_formula<L: TransitionLabel>(trace: &[L], expr: StateFrm, modality: ModalityOperator) -> StateFrm {
let tau_star = RegFrm::Iteration(Box::new(RegFrm::Action(ActFrm::MultAct(MultiAction::tau()))));
let mut result = StateFrm::Modality {
operator: modality,
formula: tau_star.clone(),
expr: Box::new(expr),
};
for label in trace.iter().rev().filter(|l| !l.is_tau_label()) {
result = StateFrm::Modality {
operator: modality,
formula: tau_star.clone(),
expr: Box::new(StateFrm::Modality {
operator: modality,
formula: RegFrm::Action(ActFrm::MultAct(label_to_multi_action(label))),
expr: Box::new(result),
}),
}
}
result
}
fn label_to_multi_action<L: TransitionLabel>(label: &L) -> MultiAction {
if label.is_tau_label() {
MultiAction::tau()
} else {
MultiAction::new(vec![Action::new(label.to_string(), Vec::new())])
}
}