15#ifndef _LIBLTS_BISIM_M
16#define _LIBLTS_BISIM_M
33template <
class LTS_TYPE>
53 initial_block.
states.push_back(i);
56 const std::vector<transition>& trans =
aut.get_transitions();
57 for (std::vector<transition>::const_iterator r = trans.begin(); r != trans.end(); ++r)
65 initial_block.
level = 0;
66 blocks.emplace_back(initial_block);
82 for (
typename std::vector<block>::reverse_iterator i =
blocks.rbegin();
83 i !=
blocks.rend() && (*i).level == lvl - 1;
100 <<
" blocks, the history contains " << lvl - 1 <<
" levels." << std::endl;
177 max_depth = std::max(max_depth, f.depth() + 1);
190 std::vector<block_index_type>
BL;
203 blocks[sourceBlock].outgoing_observations.insert(std::make_pair(
aut.apply_hidden_label_map(t.label()), targetBlock));
213 std::set<block_index_type> image_truths;
214 std::set<block_index_type> pre_image_truths;
215 std::set<block_index_type> intersection;
221 std::set_intersection(image_truths.begin(),
225 std::inserter(intersection, intersection.
begin()));
226 image_truths.swap(intersection);
227 intersection.clear();
244 image_truths.
swap(pre_image_truths);
245 pre_image_truths.clear();
248 image_truths.begin(),
250 std::inserter(pre_image_truths, pre_image_truths.begin()));
252 f.
truths.swap(pre_image_truths);
268 if (
blocks[splitter_index].level == lvl)
273 std::vector<transition> transitions_to_process =
blocks[splitter_index].transitions;
274 for (std::vector<transition>::const_iterator i = transitions_to_process.begin();
275 i != transitions_to_process.end();
284 BL.push_back(marked_block_index);
287 if ((i != transitions_to_process.end() && next(i) == transitions_to_process.end())
288 ||
aut.apply_hidden_label_map(t.
label()) !=
aut.apply_hidden_label_map(next(i)->
label()))
304 std::vector<state_type> flagged_states;
305 std::vector<state_type> non_flagged_states;
306 std::vector<state_type> Bsplit_states;
307 Bsplit_states.swap(
blocks[Bsplit].states);
313 flagged_states.push_back(s);
318 non_flagged_states.push_back(s);
324 while (
blocks[Bparent].level == lvl)
326 Bparent =
blocks[Bparent].parent_block_index;
330 if (!non_flagged_states.empty())
336 const std::size_t m =
static_cast<std::size_t
>(
337 std::pow(10.0, std::floor(std::log10(
static_cast<double>((
blocks.size() + 1) / 2)))));
338 if ((
blocks.size() + 1) / 2 % m == 0)
348 blocks.back().block_index = new_block1;
349 blocks.back().level = lvl;
351 blocks.back().parent_block_index = Bparent;
352 non_flagged_states.swap(
blocks.back().states);
359 std::vector<transition> old_transitions;
360 std::vector<transition> flagged_transitions;
361 std::vector<transition> non_flagged_transitions;
363 old_transitions =
blocks[Bsplit].transitions;
364 for (std::vector<transition>::iterator k = old_transitions.begin(); k != old_transitions.end(); ++k)
368 flagged_transitions.push_back(*k);
372 non_flagged_transitions.push_back(*k);
381 BlockLeft.
level = lvl;
384 BlockLeft.
states.swap(flagged_states);
385 if (
blocks[Bsplit].level == lvl)
389 blocks[Bsplit].swap(BlockLeft);
396 blocks.push_back(BlockLeft);
404 blocks[new_block1].transitions.swap(non_flagged_transitions);
409 std::vector<state_type>& reference_to_flagged_states_of_block2 =
blocks.back().states;
410 for (std::vector<state_type>::const_iterator j = reference_to_flagged_states_of_block2.begin();
411 j != reference_to_flagged_states_of_block2.end();
420 reset_state_flags_block = Bsplit;
421 blocks[Bsplit].states.swap(flagged_states);
424 std::vector<state_type>& flagged_states_to_be_unflagged =
blocks[reset_state_flags_block].states;
425 for (
state_type s : flagged_states_to_be_unflagged)
453 bool found_dist_obs =
false;
458 found_dist_obs =
true;
474 std::set<block_index_type> dT;
482 std::vector<formula> conjunctions;
497 conjunctions.push_back(f);
499 std::set<block_index_type> dTleft;
500 std::set_intersection(dT.begin(),
504 std::inserter(dTleft, dTleft.begin()));
505 assert(dT.size() > dTleft.size());
526 std::pair<block_index_type, block_index_type> bpair(b1, b2);
541 B2parent =
blocks[b2].parent_block_index;
545 B1parent =
blocks[b1].parent_block_index;
547 if (B1parent == B2parent)
562 while (
blocks[B].level > goal)
564 B =
blocks[B].parent_block_index;
593 std::vector<mcrl2::state_formulas::state_formula> terms;
594 for (
formula& f : conjunctions)
598 return utilities::detail::join<mcrl2::state_formulas::state_formula>(
602 { return mcrl2::state_formulas::and_(a, b); },
630template <
class LTS_TYPE>
633 std::size_t init_l2 = l2.initial_state() + l1.num_states();
643 std::string filename =
"Counterexample.mcf";
644 if (!counter_example_file.empty())
646 filename = counter_example_file;
652 std::ofstream counter_file(filename);
654 counter_file.close();
void swap(unprotected_aterm_core &t) noexcept
Swaps this term with its argument.
const_iterator begin() const
\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.
void set_truths(formula &f)
Compute and set the truth values of a formula f.
block_index_type target(observation_t obs)
state_type max_state_index
std::pair< label_type, block_index_type > observation_t
std::size_t block_index_type
level_type gca_level(const block_index_type B1, const block_index_type B2)
Auxiliarry function that computes the level of the greatest common ancestor. In other words a lvl i s...
std::vector< block > blocks
std::vector< state_type > block_index_of_a_state
std::set< observation_t > derivatives_t
label_type label(observation_t obs)
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
bisim_partitioner_minimal_depth(LTS_TYPE &l, const std::size_t init_l2)
Creates a bisimulation partitioner for an LTS.
std::set< block_index_type > partition
mcrl2::state_formulas::state_formula dist_formula_mindepth(const std::size_t s, const std::size_t t)
Creates a state formula that distinguishes state s from state t.
formula distinguish(const block_index_type b1, const block_index_type b2)
Creates a formula that distinguishes a block b1 from the block b2.
std::vector< block_index_type > BL
~bisim_partitioner_minimal_depth()=default
Destroys this partitioner.
std::map< std::pair< block_index_type, block_index_type >, level_type > greatest_common_ancestor
std::vector< bool > block_flags
std::vector< block_index_type > to_be_processed
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
bool in_same_class(const std::size_t s, const std::size_t t)
std::size_t formula_index_type
block_index_type lift_block(const block_index_type B1, level_type goal)
mcrl2::state_formulas::state_formula conjunction(std::vector< formula > &conjunctions)
conjunction Creates a conjunction of state formulas
std::vector< bool > state_flags
mcrl2::state_formulas::state_formula convert_formula(formula &f)
void split_BL(level_type lvl)
Performs the splits based on the blocks in Bsplit and the flags set in state_flags.
bool refine_partition(level_type lvl)
A class containing triples, source label and target representing transitions.
size_type from() const
The source of the transition.
size_type label() const
The label of the transition.
#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.
void merge(LTS_TYPE &l1, const LTS_TYPE &l2)
bool destructive_bisimulation_compare_minimal_depth(LTS_TYPE &l1, LTS_TYPE &l2, const std::string &counter_example_file)
void sort_transitions(std::vector< transition > &transitions, const std::set< transition::size_type > &hidden_label_set, transition_sort_style ts=src_lbl_tgt)
Sorts the transitions using a sort style.
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...
void swap(atermpp::unprotected_aterm_core &t1, atermpp::unprotected_aterm_core &t2) noexcept
Swaps two aterms.
std::vector< state_type > states
block_index_type block_index
std::vector< transition > transitions
std::set< std::pair< label_type, block_index_type > > outgoing_observations
block_index_type parent_block_index