15#ifndef MCRl2_LTS_LIBLTS_BRANCHING_BISIM_MINIMAL_DEPTH
16#define MCRl2_LTS_LIBLTS_BRANCHING_BISIM_MINIMAL_DEPTH
33template <
class LTS_TYPE>
51 trans_out[trans.from()].push_back(std::make_pair(trans.label(), trans.to()));
55 silent_in[trans.to()].insert(trans.from());
75 blocks[0].parent_block_index = 0;
80 std::size_t num_old_blocks = 0;
81 std::size_t num_blocks_created = 1;
82 std::size_t level = 0;
87 num_old_blocks = num_blocks_created;
90 state2sig = std::map<state_type, signature_type>();
92 <<
" blocks on level " << level <<
"."
131 std::map<state_type, std::vector<observation>>
trans_out;
139 std::map<std::pair<block_index_type, block_index_type>, std::set<block_index_type>>
blockpair2truths;
164 return !(*
this == other);
174 return m_lts.is_tau(
m_lts.apply_hidden_label_map(l));
201 std::queue<state_type> frontier;
207 std::map<signature_type, block_index_type> sig2block;
208 std::map<state_type, block_index_type> state2block_new;
209 std::size_t num_blocks_created = 0;
211 while (!frontier.empty())
216 if (sig2block.find(sig) == sig2block.end())
220 num_blocks_created += 1;
222 sig2block[sig] = new_block_id;
224 blocks[new_block_id].block_index = new_block_id;
227 blocks[new_block_id].sig = sig;
231 state2block_new[
state] = sig2block[sig];
240 frontier.push(backward);
246 return num_blocks_created;
252 while (
blocks[b1].parent_block_index !=
blocks[b2].parent_block_index)
254 b1 =
blocks[b1].parent_block_index;
255 b2 =
blocks[b2].parent_block_index;
257 return std::make_pair(b1, b2);
267 return utilities::detail::join<mcrl2::state_formulas::state_formula>(
268 conjunctions.begin(),
271 { return mcrl2::state_formulas::and_(a, b); },
306 void split_and_intersect(std::set<block_index_type>& truths, std::pair<block_index_type, block_index_type> liftedB1B2)
311 std::set<block_index_type> truths_new;
316 while (
blocks[b].level > split_level)
318 b =
blocks[b].parent_block_index;
322 truths_new.insert(b_og);
335 bool is_dist(std::set<blockpair_type>& dist_blockpairs,
336 std::set<block_index_type>& to_dist)
343 return is_dist(dist_blockpairs, to_dist, truths);
350 bool is_dist(
const std::set<blockpair_type>& dist_blockpairs,
const std::set<block_index_type>& to_dist, std::set<block_index_type>& truths)
364 if (truths.find(b) != truths.end())
374 std::map<blockpair_type, mcrl2::state_formulas::state_formula>& Phi,
375 std::set<block_index_type>& Tdist,
376 std::set<block_index_type>& Truths)
378 std::vector<mcrl2::state_formulas::state_formula> returnPhi;
379 std::set<blockpair_type> phi_pairs_og;
380 for (
auto& phi_pair : Phi) {
381 phi_pairs_og.insert(phi_pair.first);
384 for (
auto& phi_pair : Phi) {
386 phi_pairs_og.erase(phi_pair.first);
388 if (!
is_dist(phi_pairs_og, Tdist))
390 phi_pairs_og.insert(phi_pair.first);
391 returnPhi.push_back(phi_pair.second);
394 is_dist(phi_pairs_og, Tdist, Truths);
403 assert(block_index1 != block_index2);
421 std::tuple<block_index_type, label_type, block_index_type> dist_obs;
422 bool found_obs =
false;
425 if (!
is_tau(std::get<1>(path)) or std::get<0>(path) != std::get<2>(path))
427 if (dt.find(path) == dt.end())
452 label_type dist_label = std::get<1>(dist_obs);
456 std::vector<std::pair<block_index_type, block_index_type>> T;
460 if (std::get<1>(path) == dist_label and (!
is_tau(dist_label) or std::get<0>(path) != std::get<2>(path)))
463 T.push_back(std::make_pair(std::get<0>(path), std::get<2>(path)));
467 T.push_back(std::make_pair(std::get<2>(path), std::get<2>(path)));
478 std::set<blockpair_type> T_og;
487 std::sort(T.begin(), T.end(),
488 [
this, B2](std::pair<block_index_type, block_index_type> a, std::pair<block_index_type, block_index_type> b)
490 if (a.second == B2) {
499 return blocks[alift.first].level <
blocks[blift.first].level;
503 std::map<blockpair_type, mcrl2::state_formulas::state_formula> Phi1;
504 std::map<blockpair_type, mcrl2::state_formulas::state_formula> Phi2;
508 std::set<block_index_type> Truths1 =
level2blocksidx[block1.level - 1];
509 std::set<block_index_type> Truths2 =
level2blocksidx[block1.level - 1];
513 std::pair<block_index_type, block_index_type> Bt1_Bt2 = T.back();
515 if (Bt1_Bt2.second != B2)
517 std::pair<block_index_type, block_index_type> liftedPair =
min_split_blockpair(B2, Bt1_Bt2.second);
518 Phi1[liftedPair] =
dist_formula(liftedPair.first, liftedPair.second);
524 std::pair<block_index_type, block_index_type> liftedPair =
min_split_blockpair(B1, Bt1_Bt2.first);
525 Phi2[liftedPair] =
dist_formula(liftedPair.first, liftedPair.second);
530 std::vector<std::pair<block_index_type, block_index_type>> T_new;
531 for (
auto bt1_bt2 : T)
534 if (Truths1.find(bt1_bt2.second) != Truths1.end() && Truths2.find(bt1_bt2.first) != Truths2.end())
536 T_new.push_back(bt1_bt2);
543 std::set<block_index_type> Tset;
545 for (
auto B_Bp : T_og)
547 if (Truths2.find(B_Bp.first) != Truths2.end()) {
548 Tset.insert(B_Bp.second);
557 for (
auto B_Bp : T_og)
559 if (Truths1.find(B_Bp.second) != Truths1.end()) {
560 Tset.insert(B_Bp.first);
567 blockpair2truths[std::make_pair(block_index1, block_index2)] = std::set<block_index_type>();
571 for (
auto path : sig)
573 if (std::get<1>(path) == dist_label)
577 if (Truths1.find(Bt2) != Truths1.end() && Truths2.find(Bt1) != Truths2.end())
579 blockpair2truths[std::make_pair(block1.block_index, block2.block_index)].insert(b);
598 if (!returnPhi2.empty())
607 return blockpair2formula[std::make_pair(block1.block_index, block2.block_index)];
612template <
class LTS_TYPE>
615 const std::string& counter_example_file)
617 std::size_t init_l2 = l2.initial_state() + l1.num_states();
622 bool preserve_divergences =
false;
630 if (branching_bisim_part.
in_same_class(l1.initial_state(), init_l2))
642 assert(!branching_bisim_min.
in_same_class(l1.initial_state(), init_l2));
645 std::string filename =
"Counterexample.mcf";
646 if (!counter_example_file.empty())
648 filename = counter_example_file;
654 std::ofstream counter_file(filename);
Read-only balanced binary tree of terms.
\brief A timed multi-action
const process::action_list & actions() const
This class contains strings to be used as values for action labels in lts's.
implements the main algorithm for the branching bisimulation quotient
bool in_same_class(state_type const s, state_type const t) const
Check whether two states are in the same equivalence class.
state_type get_eq_class(state_type const s) const
Get the equivalence class of a state.
void finalize_minimized_LTS()
Adapt the LTS after minimisation.
std::map< state_type, std::size_t > state2num_touched
mcrl2::state_formulas::state_formula conjunction(std::vector< mcrl2::state_formulas::state_formula > &conjunctions)
conjunction Creates a conjunction of state formulas
regular_formulas::regular_formula make_tau_hat(regular_formulas::regular_formula &f)
void split_and_intersect(std::set< block_index_type > &truths, std::pair< block_index_type, block_index_type > liftedB1B2)
std::set< branching_observation_type > signature_type
std::map< state_type, std::set< state_type > > silent_out
state_type max_state_index
branching_bisim_partitioner_minimal_depth(LTS_TYPE &l, const std::size_t init_l2)
Creates a branching bisimulation partitioner for an LTS.
mcrl2::state_formulas::state_formula dist_formula(block_index_type block_index1, block_index_type block_index2)
std::map< std::pair< block_index_type, block_index_type >, std::set< block_index_type > > blockpair2truths
std::map< state_type, block_index_type > state2block
bool in_same_class(const std::size_t s, const std::size_t t)
std::map< std::pair< block_index_type, block_index_type >, mcrl2::state_formulas::state_formula > blockpair2formula
std::vector< state_type > bottom_states
std::vector< block > blocks
std::size_t refine_partition()
std::map< state_type, signature_type > state2sig
regular_formulas::regular_formula create_regular_formula(const mcrl2::lps::multi_action &a) const
create_regular_formula Creates a regular formula that represents action a
regular_formulas::regular_formula create_regular_formula(const mcrl2::lts::action_label_string &a) const
create_regular_formula Creates a regular formula that represents action a
std::size_t block_index_type
bool is_dist(std::set< blockpair_type > &dist_blockpairs, std::set< block_index_type > &to_dist)
is_dist Checks if a given conjunction correctly exludes a set of blocks.
std::vector< mcrl2::state_formulas::state_formula > filtered_dist_conjunction(std::map< blockpair_type, mcrl2::state_formulas::state_formula > &Phi, std::set< block_index_type > &Tdist, std::set< block_index_type > &Truths)
mcrl2::state_formulas::state_formula dist_formula_mindepth(size_t s, size_t t)
Creates a state formula that distinguishes state s from state t.
std::pair< label_type, state_type > observation
std::map< state_type, std::vector< observation > > trans_out
std::map< state_type, std::set< state_type > > silent_in
bool is_tau(label_type l)
bool is_dist(const std::set< blockpair_type > &dist_blockpairs, const std::set< block_index_type > &to_dist, std::set< block_index_type > &truths)
is_dist overloaded to also maintain the truth values computed at the end.
std::tuple< block_index_type, label_type, block_index_type > branching_observation_type
signature_type get_signature(state_type s)
std::pair< block_index_type, block_index_type > min_split_blockpair(block_index_type b1, block_index_type b2)
std::map< level_type, std::set< block_index_type > > level2blocksidx
std::pair< block_index_type, block_index_type > blockpair_type
This class contains an scc partitioner removing inert tau loops.
std::size_t get_eq_class(const std::size_t s) const
Gives the equivalence class number of a state. The equivalence class numbers range from 0 upto (and e...
void replace_transition_system(const bool preserve_divergence_loops)
The lts for which this partioner is created is replaced by the lts modulo the calculated partition.
A class containing triples, source label and target representing transitions.
O(m log n)-time branching bisimulation algorithm.
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
This file contains a class that contains labelled transition systems in aut format.
This file contains a class that contains labelled transition systems in dot format.
This file contains a class that contains labelled transition systems in fsm format.
This file contains some utility functions to manipulate lts's.
atermpp::term_balanced_tree< data::data_expression > state
A base class for the lts_dot labelled transition system.
void merge(LTS_TYPE &l1, const LTS_TYPE &l2)
bool destructive_branching_bisimulation_compare_minimal_depth(LTS_TYPE &l1, LTS_TYPE &l2, const std::string &counter_example_file)
std::size_t state_type
type used to store state (numbers and) counts
std::size_t label_type
type used to store label numbers and counts
void swap(atermpp::unprotected_aterm_core &t1, atermpp::unprotected_aterm_core &t2) noexcept
Swaps two aterms.
bool operator==(const block &other)
block_index_type parent_block_index
block_index_type block_index
bool operator!=(const block &other)