11#ifndef _LIBLTS_PBISIM_BEM_H
12#define _LIBLTS_PBISIM_BEM_H
23template <
class LTS_TYPE>
35 << l.num_states() <<
" states and " <<
36 l.num_transitions() <<
" transitions\n";
37 timer.
start(
"bisimulation_reduce (bem)");
40 timer.
finish(
"bisimulation_reduce (bem)");
77 std::set < transition > resulting_transitions;
79 const std::vector<transition>& trans =
aut.get_transitions();
82 resulting_transitions.insert(
89 aut.clear_transitions();
92 for (
const transition& t : resulting_transitions)
94 aut.add_transition(t);
103 std::vector<typename LTS_TYPE::probabilistic_state_t> new_probabilistic_states;
109 new_probabilistic_states.push_back(equivalent_ps);
113 aut.clear_probabilistic_states();
116 for (
const typename LTS_TYPE::probabilistic_state_t& new_ps : new_probabilistic_states)
118 aut.add_probabilistic_state(new_ps);
121 typename LTS_TYPE::probabilistic_state_t old_initial_prob_state =
aut.initial_probabilistic_state();
123 aut.set_initial_probabilistic_state(new_initial_prob_state);
198 std::vector< std::vector< std::list<distribution_type*> > > steps;
199 std::vector<transition>& transitions =
aut.get_transitions();
200 std::vector< std::vector<bool> > distribution_per_step_class;
202 distribution_per_step_class.resize(
aut.num_action_labels());
203 for (std::vector<bool>& i : distribution_per_step_class)
205 i.resize(
aut.num_probabilistic_states());
215 distribution.key = key;
216 distribution.incoming_transitions_per_label.resize(
aut.num_action_labels());
221 steps.resize(
aut.num_states());
222 for (std::size_t i = 0; i < steps.size(); i++)
224 steps[i].resize(
aut.num_action_labels());
229 steps[t.from()][t.label()].push_back(&
distributions[t.to()]);
230 distributions[t.to()].incoming_transitions_per_label[t.label()].push_back(&t);
240 sc.prev_states.resize(
aut.num_states());
244 std::size_t max_block_size = 0;
246 std::deque<tree_type> tree_nodes;
247 std::vector<tree_type*> leaves;
250 tree_nodes.push_back(v0);
259 for (std::size_t i = 0; i <
aut.num_action_labels(); i++)
263 if (steps[s][i].size() > 0)
267 if (distribution_per_step_class[i][d->key] ==
false)
270 distribution_per_step_class[i][d->key] =
true;
281 tree_nodes.push_back(w);
282 v->
left = &tree_nodes.back();
285 if (i ==
aut.num_action_labels() - 1)
287 leaves.push_back(v->
left);
295 if (v->
right == NULL)
300 tree_nodes.push_back(w);
301 v->
right = &tree_nodes.back();
304 if (i ==
aut.num_action_labels() - 1)
306 leaves.push_back(v->
right);
318 if (v->
count > max_block_size)
321 max_block_size = v->
count;
326 blocks.resize(leaves.size());
329 std::size_t larger_key = 0;
334 block.states.splice(block.states.end(), leaf_ptr->states);
336 if (leaf_ptr == max_block)
348 if (b.key != larger_key)
351 b.is_in_new_blocks =
true;
357 b.is_in_new_blocks =
false;
366 if (sc.distributions.size() > 0)
369 sc.is_in_new_step_classes =
true;
391 const typename LTS_TYPE::probabilistic_state_t& prob_state =
aut.probabilistic_state(d.
key);
394 if (prob_state.size()>1)
396 for (
const typename LTS_TYPE::probabilistic_state_t::state_probability_pair& prob_pair : prob_state)
401 prob_to_block = prob_to_block + prob_pair.probability();
410 prob_to_block = prob_to_block + LTS_TYPE::probabilistic_state_t::probability_t::one();
414 return prob_to_block;
419 typename LTS_TYPE::probabilistic_state_t new_prob_state;
424 std::map<state_type, probability_fraction_type> prob_state_map;
425 for (
const typename LTS_TYPE::probabilistic_state_t::state_probability_pair& sp_pair : ps)
430 if (prob_state_map.count(new_state) == 0)
433 prob_state_map[new_state] = sp_pair.probability();
438 prob_state_map[new_state] = prob_state_map[new_state] + sp_pair.probability();
443 typename std::map<state_type, probability_fraction_type>::const_iterator i = prob_state_map.begin();
444 if (++i==prob_state_map.end())
446 new_prob_state.set(prob_state_map.begin()->first);
451 for (
const std::pair<const state_type, probability_fraction_type>& i: prob_state_map)
453 new_prob_state.add(i.first, i.second);
464 return new_prob_state;
469 typename LTS_TYPE::probabilistic_state_t equivalent_prob_state;
474 typename LTS_TYPE::probabilistic_state_t old_prob_state =
aut.probabilistic_state(d->
key);
478 return equivalent_prob_state;
487 std::list<step_class_type*> step_partition_old;
488 std::list<block_type*> state_partition_old;
507 static std::vector<typename std::list<step_class_type*>::iterator> pending_new_step_classes;
508 pending_new_step_classes.clear();
511 for (
typename std::list<step_class_type*>::iterator sc_iter = step_partition_old.begin();
512 sc_iter != step_partition_old.end(); ++sc_iter)
518 static std::map< probability_fraction_type, std::list<distribution_type*> > distributions_ordered_by_prob;
519 distributions_ordered_by_prob.clear();
525 distributions_ordered_by_prob[probability].push_back(d);
530 if (distributions_ordered_by_prob.size() >= 2)
536 std::size_t new_class_count = 0;
539 std::list<distribution_type*>& distribution_list = ordered_dist.second;
541 if (new_class_count == 0)
548 for (std::size_t i = 0; i < sc_ptr->
prev_states.size(); i++)
567 pending_new_step_classes.push_back(sc_iter);
585 for (
transition* t_ptr : d->incoming_transitions_per_label[new_step_class_ptr->
action])
587 new_step_class_ptr->
prev_states[t_ptr->from()] =
true;
600 for (
typename std::list<step_class_type*>::iterator sc_iter : pending_new_step_classes)
621 static std::vector<typename std::list<block_type*>::iterator > blocks_to_move_to_front;
622 static std::vector<block_type*> new_blocks_to_move_to_front;
623 blocks_to_move_to_front.clear();
624 new_blocks_to_move_to_front.clear();
627 for (
typename std::list<block_type*>::iterator block_iter = state_partition_old.begin();
628 block_iter != state_partition_old.end(); ++block_iter)
643 new_block.
states.push_back(s);
647 temp_block.
states.push_back(s);
652 if (new_block.
states.size() > 0 && temp_block.
states.size() > 0)
661 blocks.push_back(new_block);
662 new_block_ptr = &
blocks.back();
672 if (new_block_ptr->
states.size() < b_to_split->
states.size())
674 new_blocks_to_move_to_front.push_back(new_block_ptr);
680 blocks_to_move_to_front.push_back(block_iter);
695 new_blocks_to_move_to_front.push_back(new_block_ptr);
704 for (
typename std::list<block_type*>::iterator block_iter : blocks_to_move_to_front)
710 for (
block_type* block_ptr : new_blocks_to_move_to_front)
734 sc.equivalent_step_class = sc.key;
745 typename LTS_TYPE::probabilistic_state_t new_prob_state;
746 std::unordered_map<typename LTS_TYPE::probabilistic_state_t, std::vector<step_class_type*> > reduced_step_partition;
751 if (sc.distributions.size() > 0)
756 reduced_step_partition[new_prob_state].push_back(&sc);
761 for (
typename std::unordered_map<
typename LTS_TYPE::probabilistic_state_t,
762 std::vector<step_class_type*> >::iterator i = reduced_step_partition.begin();
763 i != reduced_step_partition.end(); ++i)
765 std::vector<step_class_type*>& sc_vector = i->second;
770 sc->equivalent_step_class = equivalent_class_key;
772 equivalent_class_key++;
783template <
class LTS_TYPE>
791template <
class LTS_TYPE>
802template <
class LTS_TYPE>
806template <
class LTS_TYPE>
814 l.clear_state_labels();
822template <
class LTS_TYPE>
828 LTS_TYPE l1_copy(l1);
829 LTS_TYPE l2_copy(l2);
833template <
class LTS_TYPE>
839 std::size_t initial_probabilistic_state_key_l1;
840 std::size_t initial_probabilistic_state_key_l2;
848 initial_probabilistic_state_key_l2 = l1.num_probabilistic_states() - 1;
849 initial_probabilistic_state_key_l1 = l1.num_probabilistic_states() - 2;
854 initial_probabilistic_state_key_l1);
LTS_TYPE::probabilistic_state_t::probability_t probability_fraction_type
std::size_t num_eq_classes() const
Gives the number of bisimulation equivalence classes of the LTS.
std::list< block_type * > state_partition
std::size_t get_eq_step_class(const std::size_t d) const
Gives the bisimulation equivalence step class number of a probabilistic state.
LTS_TYPE::probabilistic_state_t calculate_new_probabilistic_state(typename LTS_TYPE::probabilistic_state_t ps)
std::vector< block_key_type > block_index_of_a_state
void refine_partition_until_it_becomes_stable(void)
Two-phased partitioning algorithm described in page 204. Fig 9. Baier. \detail Refinement of state pa...
std::deque< block_type > blocks
std::vector< step_class_key_type > step_class_index_of_a_distribution
std::list< step_class_type * > step_partition
void create_initial_partition(void)
Creates the initial partition of step classes and blocks. \detail The blocks are initially partitione...
std::deque< step_class_type > step_classes
probability_fraction_type probability_to_block(distribution_type &d, block_type &b)
Calculates the probability to reach block b from distribution d.
bool in_same_probabilistic_class(const std::size_t s, const std::size_t t) const
Returns whether two states are in the same probabilistic bisimulation equivalence class.
std::size_t block_key_type
std::size_t get_eq_class(const std::size_t s) const
Gives the bisimulation equivalence class number of a state.
prob_bisim_partitioner_bem(LTS_TYPE &l, utilities::execution_timer &timer)
Creates a probabilistic bisimulation partitioner for an PLTS.
std::deque< step_class_type > equivalent_step_classes
std::size_t step_class_key_type
void replace_transitions()
Replaces the transition relation of the current lts by the transitions of the bisimulation reduced tr...
LTS_TYPE::probabilistic_state_t calculate_equivalent_probabilistic_state(step_class_type &sc)
std::vector< distribution_type > distributions
void postprocessing_stage(void)
void replace_probabilistic_states()
Replaces the probabilistic states of the current lts by the probabilistic states of the bisimulation ...
std::size_t distribution_key_type
A class containing triples, source label and target representing transitions.
Simple timer to time the CPU time used by a piece of code.
void start(const std::string &timing_name)
Start measurement with a hint.
void finish(const std::string &timing_name)
Finish a measurement with a hint.
Class to obtain running times of code.
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
bool probabilistic_bisimulation_compare_bem(const LTS_TYPE &l1, const LTS_TYPE &l2, utilities::execution_timer &timer)
Checks whether the two initial states of two plts's are probabilistic bisimilar.
bool destructive_probabilistic_bisimulation_compare_bem(LTS_TYPE &l1, LTS_TYPE &l2, utilities::execution_timer &timer)
Checks whether the two initial states of two plts's are probabilistic bisimilar.
void plts_merge(LTS_TYPE &l1, const LTS_TYPE &l2)
void probabilistic_bisimulation_reduce_bem(LTS_TYPE &l, utilities::execution_timer &timer)
Reduce transition system l with respect to probabilistic bisimulation.
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...
std::list< state_type > states
std::vector< std::list< transition * > > incoming_transitions_per_label
distribution_key_type key
std::vector< bool > prev_states
std::size_t equivalent_step_class
std::list< distribution_type * > distributions
bool is_in_new_step_classes
std::list< state_type > states