81#ifndef LIBLTS_BISIM_DNJ_H
82#define LIBLTS_BISIM_DNJ_H
99#define USE_SIMPLE_LIST
101#ifndef USE_SIMPLE_LIST
103 #include <type_traits>
106#define USE_POOL_ALLOCATOR
108#ifdef USE_POOL_ALLOCATOR
110 #include <type_traits>
113 #define ONLY_IF_POOL_ALLOCATOR(...) __VA_ARGS__
114 #ifndef USE_SIMPLE_LIST
115 #error "Using the pool allocator also requires using the simple list"
118 #define ONLY_IF_POOL_ALLOCATOR(...)
134 #define ONLY_IF_DEBUG(...) __VA_ARGS__
136 #define ONLY_IF_DEBUG(...)
159template <
class Iterator>
175 new (&
begin) Iterator(other);
184class block_bunch_entry;
185class action_block_entry;
201#ifdef USE_POOL_ALLOCATOR
217 template <
class T,
size_t BLOCKSIZE = 1000>
219 {
static_assert(std::is_trivially_destructible<T>::value);
220 private:
static_assert(
sizeof(
void*) <=
sizeof(T));
244 return *
static_cast<void**
>(addr);
266 while(
nullptr != block);
273 template <
class U,
class... Args>
275 {
static_assert(
sizeof(T) ==
sizeof(U));
297 return new(new_el) U(std::forward<Args>(args)...);
303 template <
class U,
class... Args>
305 {
static_assert(
sizeof(U) !=
sizeof(T));
315 if constexpr (
sizeof(T) * 2 <
sizeof(U))
327 else if constexpr (
sizeof(T) <
sizeof(U))
344 return new(new_el) U(std::forward<Args>(args)...);
348 template <
class U,
class... Args>
350 {
static_assert(std::is_trivially_destructible<U>::value);
351 if constexpr (
sizeof(U) ==
sizeof(T))
353 return construct_samesize<U>(std::forward<Args>(args)...);
357 return construct_othersize<U>(std::forward<Args>(args)...);
370 {
static_assert(
sizeof(T) ==
sizeof(U));
371 old_el->~U();
static_assert(std::is_trivially_destructible<U>::value);
374 static std::less<const void*>
const total_order;
376 assert(
nullptr != block),
377 total_order(old_el, block->data) ||
378 total_order(&block->data[
sizeof(block->data)], old_el + 1);
379 block = block->next_block )
388#ifdef USE_SIMPLE_LIST
434 template <
class... Args>
438 data(
std::forward<Args>(args)...)
467 return static_cast<const entry*
>(
ptr)->data;
471 return &
static_cast<const entry*
>(
ptr)->data;
549 { assert(
nullptr != other);
568 {
static_assert(std::is_trivially_destructible<entry>::value);
571 #ifndef USE_POOL_ALLOCATOR
575 for (iterator iter =
begin();
end() != iter; )
577 iterator next = std::next(iter);
578 delete static_cast<entry*
>(iter.ptr);
618 template<
class... Args>
623 entry*
const new_entry(
625 pool.template construct<entry>
629 (pos.ptr, pos.ptr->prev, std::forward<Args>(args)...));
630 pos.ptr->prev->next = new_entry;
631 pos.ptr->prev = new_entry;
636 template<
class... Args>
641 entry*
const new_entry(
643 pool.template construct<entry>
647 (pos.ptr->next, pos.ptr, std::forward<Args>(args)...));
648 pos.ptr->next->prev = new_entry;
649 pos.ptr->next = new_entry;
654 template<
class... Args>
659 entry*
const new_entry(
661 pool.template construct<entry>
672 template<
class... Args>
677 entry*
const new_entry(
679 pool.template construct<entry>
709 pos.ptr->prev->next = pos.ptr->next;
710 pos.ptr->next->prev = pos.ptr->prev;
711 #ifdef USE_POOL_ALLOCATOR
712 pool.destroy(
static_cast<entry*
>(pos.ptr));
714 delete static_cast<entry*
>(pos.ptr);
719 #define simple_list std::list
744class state_info_entry;
745class permutation_entry;
767#ifdef USE_SIMPLE_LIST
780 if constexpr (!std::is_trivially_destructible<
809 if (!is_null()) iter.~block_bunch_slice_iter_t();
813 { assert(
nullptr != null);
814 return iter.operator->();
817 { assert(
nullptr != null);
818 return iter.operator*();
821 void operator=(nullptr_t)
823 if (!is_null()) iter.~block_bunch_slice_iter_t();
829 { assert(
nullptr != null);
835 { assert(
nullptr != null);
842 if (!is_null()) iter.~block_bunch_slice_iter_t();
851 if constexpr (
sizeof(null) ==
sizeof(iter))
853 return &*iter == &*other.iter;
857 return (is_null() && other.is_null()) ||
858 (!is_null() && !other.is_null() && &*iter == &*other.iter);
875 return (
sizeof(null) ==
sizeof(iter) || !is_null()) &&
890 { assert(
nullptr != other);
891 return (
sizeof(null) ==
sizeof(iter) || !is_null()) &&
903 bool is_null()
const {
return nullptr == null; }
967 template<
class LTS_TYPE>
976 template<
class LTS_TYPE>
1087 { assert(new_begin < new_end);
1166 { assert(
begin <= s);
1196 template<
class LTS_TYPE>
1208 ") (#" + std::to_string(
seqnr) +
")";
1247 { assert(0 < num_states);
1249 static_assert(std::is_trivially_destructible<block_t>::value); )
1253 state_iter->pos = perm_iter;
1254 perm_iter->
st = state_iter;
1256 while (++state_iter, ++perm_iter <= &
permutation.back()); assert(state_iter == 1 + &
state_info.back());
1260 #ifndef USE_POOL_ALLOCATOR
1271 block_t*
const B(perm_iter[-1].st->bl.ock); assert(B->end == perm_iter);
1301 template<
class LTS_TYPE>
1303 const char*
const message,
1307 { assert(B->
begin <= begin_print); assert(end_print <= B->end);
1308 if (end_print == begin_print)
return;
1311 << (1 < end_print - begin_print ?
"s:\n" :
":\n");
1312 assert(begin_print < end_print);
1317 if (B != begin_print->
st->
bl.
ock)
1322 if (begin_print != begin_print->
st->
pos)
1325 <<
", inconsistent pointer to state_info_entry";
1329 while (++begin_print < end_print);
1336 template<
class LTS_TYPE>
1360 template<
class LTS_TYPE>
1392 if (perm_iter < block->nonbottom_begin)
1413 assert(perm_iter ==
state->pos);
1415 while (++perm_iter < block->end);
1417 ++true_nr_of_blocks;
1432 bool operator()(
const iterator_or_counter<action_block_entry*> p1,
1433 const action_block_entry*
const action_block)
const
1435 return p1.begin > action_block;
1514 template <
class LTS_TYPE>
1555 template <
class LTS_TYPE>
1564 template <
class LTS_TYPE>
1578 return pp(partitioner.
aut.action_label(
label)) +
"-transition " +
1624 assert(
nullptr !=
succ); assert(
nullptr != result->
succ);
1626 assert(result == action_block_begin ||
nullptr == result[-1].
succ ||
1627 action_block_orig_inert_begin <= result ||
1704 template <
class LTS_TYPE>
1710 return "bunch [" + std::to_string(
begin -
1716 template <
class LTS_TYPE>
1719 { assert(
nullptr !=
end[-1].succ);
1721 assert(
nullptr != iter->
succ);
1724 result +=
" containing transition";
1725 result += iter <
end - 1 ?
"s " :
" ";
1728 if (
end <= iter)
return result;
1729 while (
nullptr == iter->
succ) ++iter;
1739 while (++iter <
end)
1741 if (
nullptr != iter->
succ)
1756 template <
class LTS_TYPE>
1836 bunch_t*
const new_bunch,
bool const new_is_stable)
1863 template <
class LTS_TYPE>
1871 return p1.
slice != p2;
1873 }
const block_bunch_not_equal;
1877 std::string
const index_string(std::to_string(
end -
1881 return "empty block_bunch_slice [" + index_string +
"," +
1889 begin =
end - bunch_size;
1893 this, block_bunch_not_equal);
1894 assert(begin->
slice ==
this);
1895 assert(begin[-1].slice !=
this);
1896 return (
is_stable() ?
"stable block_bunch-slice ["
1897 :
"unstable block_bunch_slice [") +
1899 "," + index_string +
") containing transitions from " +
1911 template <
class LTS_TYPE>
1913 counter_type const ctr, unsigned const max_value,
1916 assert(1U == max_value);
1920 assert(partitioner.part_tr.block_bunch.front().slice !=
this);
1921 assert(block_bunch[-1].slice ==
this);
1926 assert(source->
bl.
ock == block);
1927 if (source->
pos < block->nonbottom_begin
1937 while (block_bunch[-1].slice ==
this);
1960 assert(&succ.cbegin()[1] == result ||
1981 template <
class LTS_TYPE>
1987 const succ_entry*
const out_slice_before_end(
1989 assert(
nullptr != out_slice_before_end);
1992 add_work(ctr, max_value), partitioner);
1997 add_work_notemporary(ctr, max_value), partitioner);
2052 #ifdef USE_POOL_ALLOCATOR
2053 static_assert(std::is_trivially_destructible<bunch_t>::value);
2054 static_assert(std::is_trivially_destructible<
2079 :
succ(num_transitions + 2),
2081 pred(num_transitions + 2),
2099 pred.front().source =
nullptr;
2100 pred.front().target =
nullptr;
2101 pred.back() .source =
nullptr;
2102 pred.back() .target =
nullptr;
2109 #ifndef USE_POOL_ALLOCATOR
2128 action_block_iter = bunch->
end;
2199 bunch_t*
const bunch_T_a_Bprime,
2200 bool const first_transition_of_state)
2205 succ_entry*
const old_succ_pos(action_block_iter->
succ); assert(
nullptr != old_succ_pos);
2212 assert(new_succ_pos<old_succ_pos->
block_bunch->pred->source->succ_inert.begin);
2214 if (old_succ_pos < new_succ_pos)
2218 action_block_iter->
succ = new_succ_pos;
2219 }
else assert(old_succ_pos == new_succ_pos);
2232 if (first_transition_of_state)
2239 new_succ_pos[1].begin_or_before_end); assert(
nullptr != out_slice_before_end);
2240 assert(new_succ_pos < out_slice_before_end);
2242 out_slice_before_end);
2246 new_succ_pos->
begin_or_before_end = out_slice_before_end; assert(bunch_T_a_Bprime == out_slice_before_end->
bunch());
2249 assert(new_succ_pos == action_block_iter->
succ);
2255 old_block_bunch_pos->
slice);
2257 old_block_bunch_slice->end - 1); assert(
nullptr != new_block_bunch_pos->
pred->
action_block->
succ);
2259 new_block_bunch_pos);
2264 new_block_bunch_pos[1].slice, assert(!new_block_bunch_pos[1].slice.is_null()),
2265 bunch_T_a_Bprime != new_block_bunch_slice->bunch ||
2266 source_block != new_block_bunch_slice->source_block()))
2267 { assert(first_transition_of_state);
2274 #ifdef USE_SIMPLE_LIST
2277 new_block_bunch_pos + 1, bunch_T_a_Bprime,
false);
2280 bunch_T_a_Bprime,
false);
2284 old_block_bunch_slice->work_counter; )
2287 old_block_bunch_slice->make_unstable();
2288 } assert(!new_block_bunch_slice->is_stable());
2291 if (old_block_bunch_pos < new_block_bunch_pos)
2297 }
else assert(new_block_bunch_pos == old_block_bunch_pos);
2298 assert(new_block_bunch_pos->
slice == old_block_bunch_slice);
2299 new_block_bunch_pos->
slice = new_block_bunch_slice;
2301 assert(new_block_bunch_pos + 1 == old_block_bunch_slice->marked_begin);
2302 old_block_bunch_slice->end = new_block_bunch_pos;
2303 old_block_bunch_slice->marked_begin = new_block_bunch_pos; assert(
nullptr != new_block_bunch_pos);
2304 if (old_block_bunch_slice->empty())
2305 { assert(!old_block_bunch_slice->is_stable());
2307 old_block_bunch_slice); assert(!new_block_bunch_slice->is_stable());
2317 new_block_bunch_slice->make_stable();
2352 bunch_t* const bunch_T_a_Bprime, )
2353 bunch_t* const large_splitter_bunch)
2354 { assert(
nullptr != bunch_T_a_Bprime);
2361 succ_entry*
const new_succ_pos(action_block_iter->succ); assert(
nullptr != new_succ_pos);
2365 assert(new_succ_pos < source->succ_inert.begin);
2366 assert(source == &partitioner.part_st.state_info.front() ||
2367 source[-1].
succ_inert.begin <= new_succ_pos);
2372 new_begin_or_before_end);
2373 if (new_begin_or_before_end < new_succ_pos)
2374 { assert(source == &partitioner.part_st.state_info.front() ||
2375 source[-1].
succ_inert.begin <= new_begin_or_before_end);
2379 { assert(new_begin_or_before_end == new_succ_pos);
2383 if (new_begin_or_before_end <= new_before_end)
2384 { assert(&partitioner.part_tr.succ.cbegin()[1] == new_begin_or_before_end ||
2386 new_begin_or_before_end[-1].
bunch() != bunch_T_a_Bprime);
2387 assert(new_before_end + 1 == source->
succ_inert.begin ||
2388 bunch_T_a_Bprime != new_before_end[1].
bunch());
2389 if (source == new_succ_pos[-1].
block_bunch->pred->source &&
2390 new_succ_pos[-1].
bunch() == large_splitter_bunch)
2394 new_succ_pos[-1].
block_bunch); assert(!old_block_bunch_pos->
slice.is_null());
2397 old_block_bunch_pos->
slice);
2398 if (!large_splitter_slice->is_stable())
2401 large_splitter_slice->marked_begin - 1); assert(
nullptr != new_block_bunch_pos->
pred->
action_block->
succ);
2403 new_block_bunch_pos);
2404 if (old_block_bunch_pos < new_block_bunch_pos)
2407 new_block_bunch_pos->
pred);
2409 succ->block_bunch = old_block_bunch_pos; assert(new_block_bunch_pos->
pred->
action_block->
succ == new_succ_pos - 1);
2410 new_succ_pos[-1].
block_bunch = new_block_bunch_pos;
2412 large_splitter_slice->marked_begin=new_block_bunch_pos; assert(
nullptr != new_block_bunch_pos);
2413 }
else assert(1 >= source->
bl.
ock->
size());
2415 }
else assert(source == &partitioner.part_st.state_info.front() ||
2416 source[-1].
succ_inert.begin <= new_before_end);
2421 assert(!new_block_bunch_pos->
slice.is_null());
2423 new_block_bunch_pos->
slice);
2424 assert(new_block_bunch_pos < new_block_bunch_slice->end);
2425 assert(bunch_T_a_Bprime == new_block_bunch_slice->bunch);
2426 if (new_block_bunch_pos + 1 < new_block_bunch_slice->end)
return;
2432 while ((--new_block_bunch_pos)->slice == new_block_bunch_slice);
2433 assert(new_block_bunch_pos <= &partitioner.part_tr.block_bunch.front() ||
2435 bunch_T_a_Bprime != new_block_bunch_pos->
slice->bunch);
2471 #ifndef USE_SIMPLE_LIST
2475 { assert(&
succ.cbegin()[1] < out_slice_end);
2477 out_slice_end[-1].begin_or_before_end); assert(
nullptr != out_slice_begin);
2478 assert(out_slice_begin < out_slice_end);
2482 assert(!old_block_bunch_pos->
slice.is_null());
2485 old_block_bunch_pos);
2486 if (&*splitter_T == &*old_block_bunch_slice)
return out_slice_begin;
2489 old_block_bunch_slice->end);
2491 assert(&partitioner.part_st.state_info.front() == source ||
2492 source[-1].
succ_inert.begin < out_slice_end);
2498 old_block_bunch_slice_end->
slice, assert(!old_block_bunch_slice_end->
slice.is_null()),
2499 old_block_bunch_slice->bunch != new_block_bunch_slice->bunch))
2503 if (old_block_bunch_slice->is_stable())
2506 #ifdef USE_SIMPLE_LIST
2507 new_block_bunch_slice =
2510 old_block_bunch_slice->end,
2511 old_block_bunch_slice->bunch,
true);
2514 old_block_bunch_slice->end,
2515 old_block_bunch_slice->bunch,
true);
2516 new_block_bunch_slice =
2522 #ifdef USE_SIMPLE_LIST
2525 old_block_bunch_slice,
2526 old_block_bunch_slice->end,
2527 old_block_bunch_slice->bunch,
false);
2530 std::next(old_block_bunch_slice),
2531 old_block_bunch_slice->end,
2532 old_block_bunch_slice->bunch,
false);
2536 old_block_bunch_slice->work_counter; )
2540 assert(out_slice_begin < out_slice_end);
2542 { assert(old_block_bunch_pos == out_slice_end[-1].
block_bunch);
2543 --out_slice_end; assert(old_block_bunch_pos->
slice == old_block_bunch_slice);
2544 assert(source == out_slice_end->block_bunch->pred->source);
2545 --old_block_bunch_slice_end;
2549 if (old_block_bunch_slice->is_stable() || ( assert(!new_block_bunch_slice->is_stable()),
2550 old_block_bunch_slice->marked_begin >
2551 old_block_bunch_slice_end &&
2552 ( assert(
nullptr != old_block_bunch_slice_end),
2555 old_block_bunch_slice->marked_begin =
2556 old_block_bunch_slice_end,
true)))
2561 old_block_bunch_slice_end->
pred);
2568 if (old_block_bunch_pos < old_block_bunch_slice->marked_begin)
2575 old_block_bunch_slice->marked_begin - 1; assert(old_block_bunch_pos < old_block_bunch_slice_end);
2576 old_block_bunch_slice->marked_begin = old_marked_begin;
2578 old_block_bunch_pos->
pred = old_marked_begin->
pred;
2579 old_marked_begin->
pred = old_block_bunch_slice_end->
pred;
2590 new_block_bunch_slice->marked_begin - 1;
2591 new_block_bunch_slice->marked_begin = new_marked_begin; assert(old_block_bunch_pos < new_marked_begin ||
2592 old_block_bunch_pos == old_block_bunch_slice_end);
2593 old_block_bunch_pos->
pred=old_block_bunch_slice_end->
pred; assert(old_block_bunch_slice_end <= new_marked_begin);
2594 old_block_bunch_slice_end->
pred = new_marked_begin->
pred;
2597 out_slice_end->block_bunch = new_marked_begin;
2603 old_block_bunch_pos;
2605 while (out_slice_begin < out_slice_end &&
2606 (old_block_bunch_pos = out_slice_end[-1].
block_bunch,
true));
2607 old_block_bunch_slice->end = old_block_bunch_slice_end;
2609 if (old_block_bunch_slice->empty())
2611 #ifdef USE_SIMPLE_LIST
2614 old_block_bunch_slice);
2616 if (old_block_bunch_slice->is_stable())
2641 return out_slice_begin;
2661 )); assert(
nullptr != action_block_slice_begin->
succ);
2663 action_block_slice_begin);
2667 assert(
nullptr != new_action_block_pos->
succ);
2669 new_action_block_pos);
2670 if (old_action_block_pos < new_action_block_pos)
2672 succ_entry*
const temp(new_action_block_pos->
succ); assert(
nullptr != temp); assert(
nullptr != old_action_block_pos->
succ);
2673 new_action_block_pos->
succ = old_action_block_pos->
succ;
2674 old_action_block_pos->
succ = temp;
2680 new_action_block_pos - 1;
2683 { assert(old_action_block_pos == new_action_block_pos);
2684 if (action_block_slice_begin < new_action_block_pos)
2690 new_action_block_pos - 1;
2693 } assert(
nullptr != new_action_block_pos->
succ);
2701 nullptr == new_action_block_pos[1].
succ ||
2702 new_action_block_pos[1].
succ->bunch() !=
2715 new_action_block_pos[1].begin_or_before_end); assert(
nullptr != action_block_slice_before_end);
2716 assert(new_action_block_pos < action_block_slice_before_end);
2717 assert(
nullptr != action_block_slice_before_end->
succ);
2719 action_block_slice_before_end);
2720 assert(new_action_block_pos + 1 ==
2723 new_action_block_pos; assert(action_block_slice_before_end->
succ->
block_bunch->
2745 assert(
nullptr != old_begin_or_before_end->
succ);
2747 old_begin_or_before_end);
2749 old_begin_or_before_end->
begin_or_before_end); assert(
nullptr != new_begin_or_before_end),
2750 assert(
nullptr != new_begin_or_before_end->succ),
2751 assert(new_begin_or_before_end->succ->block_bunch->pred->action_block ==
2752 new_begin_or_before_end),
2753 new_begin_or_before_end < new_action_block_pos)
2756 new_begin_or_before_end; assert(new_action_block_pos <= old_begin_or_before_end);
2758 }
else assert(new_begin_or_before_end == new_action_block_pos);
2759 if (old_begin_or_before_end < new_action_block_pos)
return;
2764 if (!bunch->
is_trivial()) {
return; } assert(old_begin_or_before_end + 1 == bunch->
end);
2765 if (bunch->
begin < new_action_block_pos)
2805 new_action_block_pos);
2810 new_block_bunch_pos);
2812 old_pred_pos->
action_block); assert(new_action_block_pos <= old_action_block_pos);
2814 succ_entry*
const old_succ_pos(old_action_block_pos->
succ); assert(
nullptr != old_succ_pos);
2816 old_succ_pos->
block_bunch); assert(old_pred_pos == old_block_bunch_pos->
pred);
2821 if (new_action_block_pos < old_action_block_pos)
2823 old_action_block_pos->
succ = new_action_block_pos->
succ; assert(
nullptr != old_action_block_pos->
succ);
2825 new_action_block_pos);
2827 old_action_block_pos;
2828 }
else assert(new_action_block_pos == old_action_block_pos);
2829 new_action_block_pos->
succ = new_succ_pos; assert(
nullptr != new_succ_pos);
2833 if (new_succ_pos < old_succ_pos)
2837 }
else assert(new_succ_pos == old_succ_pos);
2841 assert(new_block_bunch_pos->
slice.is_null());
2842 if (new_block_bunch_pos < old_block_bunch_pos)
2843 { assert(old_block_bunch_pos->
slice.is_null());
2846 new_block_bunch_pos);
2849 old_block_bunch_pos;
2850 }
else assert(new_block_bunch_pos == old_block_bunch_pos);
2851 new_block_bunch_pos->
pred = new_pred_pos;
2855 if (new_pred_pos < old_pred_pos)
2862 }
else assert(new_pred_pos == old_pred_pos);
2866 bool became_bottom(
false); assert(
succ.back().block_bunch->pred->source != source);
2867 if (source != source->
succ_inert.begin->block_bunch->pred->source)
2878 became_bottom =
true;
2881 bunch_t* new_noninert_bunch; assert(
nullptr != new_action_block_pos);
2882 if (!new_noninert_block_bunch_ptr->is_null())
2891 new_noninert_bunch = (*new_noninert_block_bunch_ptr)->bunch; assert(new_action_block_pos >= new_noninert_bunch->
end);
2894 temp_action_block_pos > new_noninert_bunch->
end ; )
2896 assert(
nullptr == (--temp_action_block_pos)->
succ);
2900 assert((*new_noninert_block_bunch_ptr)->end == new_block_bunch_pos);
2902 if (!(*new_noninert_block_bunch_ptr)->is_stable())
2903 { assert((*new_noninert_block_bunch_ptr)->marked_begin == new_block_bunch_pos);
2904 (*new_noninert_block_bunch_ptr)->marked_begin =
2907 new_block_bunch_pos->
slice = *new_noninert_block_bunch_ptr;
2909 assert(new_noninert_bunch->
begin < new_action_block_pos);
2910 if (
nullptr != new_action_block_pos[-1].
succ &&
2911 target->bl.ock == new_action_block_pos[-1].
2912 succ->block_bunch->pred->target->bl.ock)
2916 new_action_block_pos[-1].begin_or_before_end); assert(
nullptr != action_block_slice_begin);
2918 assert(
nullptr != action_block_slice_begin->
succ);
2920 action_block_slice_begin);
2922 new_action_block_pos;
2924 action_block_slice_begin;
2941 iter < new_noninert_bunch->
begin; ++iter)
2943 assert(
nullptr == iter->succ);
2944 assert(
nullptr == iter->begin_or_before_end);
2951 assert(source !=
succ.front().block_bunch->pred->source);
2952 if (source == new_succ_pos[-1].
block_bunch->pred->source &&
2953 new_succ_pos[-1].
bunch() == new_noninert_bunch)
2957 new_succ_pos[-1].begin_or_before_end); assert(
nullptr != out_slice_begin);
2962 return became_bottom;
2968 new_noninert_bunch =
2969 #ifdef USE_POOL_ALLOCATOR
2970 storage.template construct<bunch_t>
2978 #ifdef USE_SIMPLE_LIST
2985 new_noninert_bunch,
false);
2990 new_block_bunch_pos->
slice = new_noninert_block_bunch;
2991 *new_noninert_block_bunch_ptr = new_noninert_block_bunch;
2994 new_action_block_pos->begin_or_before_end = new_action_block_pos;
2996 } assert(&
succ.cbegin()[1] == new_succ_pos ||
2998 new_succ_pos[-1].
bunch() != new_noninert_bunch);
3000 return became_bottom;
3030 bool const add_new_noninert_to_splitter,
3033 { assert(splitter_T->is_stable());
3040 assert(s->
pos == s_iter);
3042 assert(s !=
succ.front().block_bunch->pred->source);
3044 s == succ_iter[-1].block_bunch->pred->source; )
3050 splitter_T); assert(succ_iter->block_bunch->pred->action_block->succ == succ_iter);
3051 assert(s == succ_iter->block_bunch->pred->source);
3056 assert(s !=
pred.front().target);
3058 s == (--pred_iter)->
target; )
3059 { assert(&
pred.front() < pred_iter);
3060 assert(
nullptr != pred_iter->action_block->succ);
3061 assert(pred_iter->action_block->succ->block_bunch->pred == pred_iter);
3065 while (++s_iter < new_block->end);
3068 { assert(splitter_T->source_block() == new_block);
3071 new_block->stable_block_bunch.splice(
3072 new_block->stable_block_bunch.begin(),
3073 old_block->stable_block_bunch, splitter_T);
3074 }
else assert(splitter_T->source_block() == old_block);
3079 s_iter = new_block->begin; assert(s_iter < new_block->end);
3084 s == (--pred_iter)->
target; )
3085 { assert(&
pred.front() < pred_iter);
3086 assert(
nullptr != pred_iter->action_block->succ);
3087 assert(pred_iter->action_block->succ->block_bunch->pred == pred_iter);
3091 while (++s_iter < new_block->end);
3092 assert(0 == new_block->marked_size()); assert(0 == old_block->marked_size());
3098 if (add_new_noninert_to_splitter)
3100 new_noninert_block_bunch = splitter_T;
3104 new_noninert_block_bunch =
nullptr;
3107 { assert(old_block == new_block->end->st->bl.ock);
3108 assert(new_block->end <= &partitioner.part_st.permutation.back());
3109 permutation_entry* target_iter(new_block->begin); assert(target_iter < new_block->end);
3114 assert(s !=
pred.back().target);
3116 s == pred_iter->target; ++pred_iter)
3117 { assert(pred_iter < &
pred.back());
3118 assert(
nullptr != pred_iter->action_block->succ);
3119 state_info_entry*
const t(pred_iter->source); assert(pred_iter->action_block->succ->block_bunch->pred == pred_iter);
3120 assert(t->
pos->
st == t);
3121 if (new_block != t->
bl.
ock)
3122 { assert(old_block == t->
bl.
ock);
3124 &new_noninert_block_bunch))
3127 old_block->mark_nonbottom(t->
pos);
3133 while (++target_iter < new_block->end); assert(0 < old_block->bottom_size());
3137 assert(&partitioner.part_st.permutation.front() < new_block->begin);
3138 assert(old_block == new_block->begin[-1].st->bl.ock);
3139 assert(0 < old_block->bottom_size());
3141 source_iter < new_block->marked_nonbottom_begin; )
3145 assert(
succ.back().block_bunch->pred->source != s);
3155 &new_noninert_block_bunch);
3159 while (s == (++succ_iter)->
block_bunch->pred->source);
3160 if (dont_mark) ++source_iter;
3162 { assert(s->
pos == source_iter);
3163 new_block->mark_nonbottom(source_iter);
3164 } assert(new_block->nonbottom_begin <= source_iter);
3176 template <
class LTS_TYPE>
3182 if (succ_iter >= &
succ.back())
3194 { assert(source < succ_iter->
block_bunch->pred->source);
3197 << source->
debug_id(partitioner) <<
":\n";
3202 { assert(!current_out_bunch.is_null());
3204 { assert(succ_iter == source->
succ_inert.begin);
3206 current_out_bunch =
nullptr;
3209 { assert(succ_iter < source->succ_inert.begin);
3210 assert(!current_out_bunch.is_null());
3212 current_out_bunch->bunch != succ_iter->
bunch());
3221 while (++succ_iter < &
succ.back());
3226 while (
nullptr == action_block_iter->
succ &&
3228 ++action_block_iter,
true));
3233 assert(
nullptr != action_block_iter->
succ);
3242 assert(
nullptr != bunch);
3244 partitioner) <<
":\n\taction_block-slice [";
3245 assert(bunch->
begin == action_block_iter);
3246 bunch_end = bunch->
end;
3249 action_block_slice_end =
3252 assert(action_block_slice_end <= bunch_end);
3260 assert(action_block_iter < action_block_slice_end);
3263 assert(
nullptr != action_block_iter->
succ);
3266 pred->debug_id(partitioner) <<
'\n';
3268 while (++action_block_iter < action_block_slice_end);
3270 while (action_block_iter < bunch_end &&
3271 nullptr == action_block_iter->
succ)
3274 ++action_block_iter;
3275 assert(action_block_iter < bunch_end);
3277 if (action_block_iter >= bunch_end)
break;
3279 action_block_slice_end =
3284 assert(action_block_iter == bunch_end);
3286 nullptr == action_block_iter->
succ)
3289 ++action_block_iter;
3315{ assert(0 < marked_size()); assert(0 < unmarked_bottom_size());
3318 state_type swapcount(std::min(marked_bottom_size(),
3319 unmarked_nonbottom_size()));
3321 unmarked_nonbottom_size()); assert(begin < splitpoint), assert(splitpoint < end),
3322 assert(splitpoint->st->pos == splitpoint),
3324 { assert((
state_type) (splitpoint - begin) <= size()/2);
3326 #ifdef USE_POOL_ALLOCATOR
3327 storage.template construct<block_t>
3331 (begin, splitpoint, new_seqnr);
3336 nonbottom_begin = marked_nonbottom_begin;
3341 #ifdef USE_POOL_ALLOCATOR
3342 storage.template construct<block_t>
3346 (splitpoint, end, new_seqnr);
3351 nonbottom_begin = marked_bottom_begin;
3374 --pos2; assert(pos1 < pos2);
3375 *pos1 = std::move(*pos2);
3377 if (0 >= --swapcount) {
break; } assert(pos1 < pos2);
3378 *pos2 = std::move(*pos1);
3380 *pos2 = std::move(temp);
3384 do assert(s_iter->
st->
pos == s_iter);
3385 while (++s_iter < end); }
3388 marked_nonbottom_begin = end;
3389 marked_bottom_begin = nonbottom_begin;
3395 { assert(s_iter->
st->
pos == s_iter);
3396 s_iter->
st->
bl.
ock = new_block;
3420 action_block_entry*
const last_slice_begin(
end[-1].begin_or_before_end); assert(
begin < first_slice_end); assert(first_slice_end <= last_slice_begin);
3422 assert(last_slice_begin <
end); assert(
nullptr != first_slice_end[-1].succ);
3423 assert(
nullptr != last_slice_begin->
succ);
3424 if (first_slice_end -
begin >
end - last_slice_begin)
3428 #ifdef USE_POOL_ALLOCATOR
3429 part_tr.
storage.template construct<bunch_t>
3433 (last_slice_begin,
end); assert(
nullptr != bunch_T_a_Bprime);
3434 end = last_slice_begin;
3435 while (
nullptr ==
end[-1].succ)
3438 } assert(
nullptr !=
end[-1].begin_or_before_end);
3445 #ifdef USE_POOL_ALLOCATOR
3446 part_tr.
storage.template construct<bunch_t>
3450 (
begin, first_slice_end); assert(
nullptr != bunch_T_a_Bprime);
3451 begin = first_slice_end;
3459 return bunch_T_a_Bprime;
3496template <
class LTS_TYPE>
3553 bool const new_preserve_divergence =
false)
3555 part_st(new_aut.num_states()),
3556 part_tr(new_aut.num_transitions(), new_aut.num_action_labels()),
3620 { assert(block_bunch.is_stable()); assert(!block_bunch.empty());
3622 pred(block_bunch.end[-1].
pred); assert(pred->source->bl.ock == B);
3623 assert(
nullptr != pred->action_block->succ);
3624 assert(pred->action_block->succ->block_bunch->pred == pred);
3625 assert(pred->action_block->succ->block_bunch->slice == &block_bunch);
3629 pred->target->bl.ock->seqnr));
3638 if (
aut.has_state_info())
3650 new_labels[new_index]=new_labels[new_index]+
aut.state_label(i);
3658 aut.set_state_label(i, new_labels[i]);
3709 ?
"divergence-preserving branching "
3713 <<
" states and " <<
aut.num_transitions() <<
" transitions.\n";
3718 "without incoming or outgoing transition. It is not "
3719 "guaranteed that branching bisimulation minimisation runs in "
3720 "time O(m log n).\n";
3753 ++inert_transitions;
3786 next_pred_begin += state_iter->
pred_inert.count;
3787 state_iter->
pred_inert.convert_to_iterator(next_pred_begin);
3790 assert(
nullptr != next_succ_begin);
3793 if (next_succ_begin < state_iter->untested_to_U_eqv.begin)
3798 out_slice_begin(next_succ_begin);
3806 state_iter->
succ_inert.convert_to_iterator(next_succ_begin +
3809 while (next_succ_begin < state_iter->succ_inert.begin)
3814 next_succ_begin = state_iter->
succ_inert.begin;
3829 #ifdef USE_POOL_ALLOCATOR
3863 { assert(
nullptr != bunch);
3874 <<
pp(
aut.action_label(
label)) <<
"-transitions. "
3875 "This is more than n^2 (= " << n_square <<
"). It is "
3876 "not guaranteed that branching bisimulation "
3887 action_block_slice_begin(next_action_label_begin); assert(
nullptr != action_block_slice_begin);
3891 action_block_slice_begin;
3897 next_action_label_begin);
3902 "transitions, and the number of action labels exceeds "
3903 "the number of transitions. It is not guaranteed that "
3904 "branching bisimulation minimisation runs in time "
3910 next_action_label_begin->
succ =
nullptr,
3938 pred_pos = --
target->pred_inert.begin; assert(block_bunch_pos->
slice.is_null());
3941 --inert_transitions;
3954 pred_pos =
target->bl.ed_noninert_end++;
3960 begin_or_before_end == action_block_pos);
3963 } assert(
target->bl.ed_noninert_end <=
target->pred_inert.begin);
3965 block_bunch_pos->
pred = pred_pos;
3967 pred_pos->
source = source;
3968 pred_pos->
target =
target; assert(
nullptr != succ_pos);
3969 action_block_pos->
succ = succ_pos;
3970 } assert(0 == inert_transitions);
3973 aut.clear_transitions();
3978 state_iter->
bl.
ock = B;
3982 if (
nullptr != bunch)
3988 while (
nullptr == bunch->
end[-1].
succ)
4019 slice->make_stable();
4065 std::unordered_set<const bisim_dnj::block_bunch_slice_t*>
4066 block_bunch_check_set;
4067 #ifndef USE_SIMPLE_LIST
4068 block_bunch_check_set.reserve(
4069 block->stable_block_bunch.size());
4074 block->stable_block_bunch)
4076 assert(block_bunch.source_block() == block);
4077 assert(block_bunch.is_stable());
4078 block_bunch_check_set.insert(&block_bunch);
4080 block_bunch.bunch->max_work_counter(*
this)), *
this);
4081 ++true_nr_of_block_bunch_slices;
4093 state == out_slice_end[-1].block_bunch->pred->source; )
4094 { assert(!out_slice_end[-1].block_bunch->
slice.is_null());
4096 block_bunch_slice(out_slice_end[-1].block_bunch->
slice);
4098 block_bunch_slice->bunch);
4099 assert(block == block_bunch_slice->source_block());
4100 if (block_bunch_slice->is_stable())
4102 assert(1 == block_bunch_check_set.count(
4103 &*block_bunch_slice));
4104 ++block_bunch_count;
4109 out_slice_end[-1].begin_or_before_end);
4110 assert(
nullptr != out_slice_begin);
4111 assert(out_slice_begin < out_slice_end);
4120 assert(bunch->
begin <=
4121 out_slice_end->block_bunch->pred->action_block);
4122 assert(out_slice_end->block_bunch->pred->
4123 action_block < bunch->end);
4124 assert(out_slice_end->block_bunch->slice ==
4126 assert(
nullptr != out_slice_end->begin_or_before_end);
4127 if (out_slice_end->block_bunch + 1 !=
4128 block_bunch_slice->end)
4130 assert(out_slice_end->block_bunch + 1 <
4131 block_bunch_slice->end);
4132 assert(out_slice_end->block_bunch[1].slice ==
4136 no_temporary_work(max_block,
4140 perm_iter < block->nonbottom_begin),*
this);
4142 while (out_slice_begin < out_slice_end &&
4143 (assert(out_slice_begin ==
4146 if (perm_iter < block->nonbottom_begin)
4148 assert(block_bunch_check_set.size() == block_bunch_count);
4151 while (++perm_iter < block->end);
4155 true_nr_of_block_bunch_slices);
4171 { assert(
nullptr == action_block->begin_or_before_end);
4173 succ_iter(action_block->succ);
4174 assert(
nullptr != succ_iter);
4192 max_block,
false), *
this);
4206 trans_type true_nr_of_action_block_slices(0);
4218 action_block_slice_end(action_slice_end);
4222 action_block_slice_begin(
4223 action_block_slice_end[-1].begin_or_before_end);
4224 assert(
nullptr != action_block_slice_begin);
4225 assert(action_block_slice_begin < action_block_slice_end);
4226 assert(action_block_slice_end <= action_slice_end);
4227 assert(
nullptr != action_block_slice_begin->
succ);
4229 target_block(action_block_slice_begin->
4230 succ->block_bunch->pred->target->bl.ock);
4232 bunch(action_block_slice_begin->
succ->
bunch());
4233 if (previous_bunch != bunch)
4235 assert(
nullptr == previous_bunch);
4236 previous_bunch = bunch;
4237 assert(bunch->
end == action_block_slice_end);
4238 if (bunch->
begin == action_block_slice_begin)
4248 ++true_nr_of_nontrivial_bunches;
4252 ++true_nr_of_bunches;
4254 if(bunch->
begin == action_block_slice_begin)
4256 previous_bunch =
nullptr;
4258 else assert(bunch->
begin < action_block_slice_begin);
4261 action_block_slice_end);
4264 action_block(action_block_slice_end);
4269 succ_iter(action_block->
succ);
4270 assert(
nullptr != succ_iter);
4280 assert(succ_iter < pred_iter->source->succ_inert.begin);
4284 assert(pred_iter < pred_iter->
target->pred_inert.begin);
4287 assert(target_block == pred_iter->
target->
bl.
ock);
4288 assert(bunch == succ_iter->
bunch());
4290 while (action_block_slice_begin < action_block &&
4294 action_block_slice_begin),
true));
4295 action_block_slice_end = action_block_slice_begin;
4296 ++true_nr_of_action_block_slices;
4301 assert(
nullptr == action_slice_end->
succ);
4307 assert(
nullptr == previous_bunch);
4310 true_nr_of_nontrivial_bunches);
4312 true_nr_of_action_block_slices);
4335 clock_t next_print_time = clock();
4336 const clock_t rounded_start_time = next_print_time - CLOCKS_PER_SEC/2;