73#ifndef _CHECK_COMPLEXITY_H
74#define _CHECK_COMPLEXITY_H
113#define STATE_TYPE_MIN (std::numeric_limits<state_type>::min())
114#define STATE_TYPE_MAX (std::numeric_limits<state_type>::max())
123#define TRANS_TYPE_MIN (std::numeric_limits<trans_type>::min())
124#define TRANS_TYPE_MAX (std::numeric_limits<trans_type>::max())
126#if !defined(NDEBUG) || defined(COUNT_WORK_BALANCE)
461 #define DONT_COUNT_TEMPORARY (std::numeric_limits<unsigned char>::max()-1)
482 if constexpr (
sizeof(unsigned) ==
sizeof(size))
484 return sizeof(size) * CHAR_BIT - 1 - __builtin_clz(size);
486 else if constexpr (
sizeof(
unsigned long) ==
sizeof(size))
488 return sizeof(size) * CHAR_BIT - 1 - __builtin_clzl(size);
490 else if constexpr(
sizeof(
unsigned long long) ==
sizeof(size))
492 return sizeof(size) * CHAR_BIT - 1 - __builtin_clzll(size);
508 return (
int) std::log2(size);
589 enum counter_type FirstPostprocessCounter = FirstTempCounter>
592 static_assert(FirstCounter < FirstTempCounter);
593 static_assert(FirstTempCounter <= FirstPostprocessCounter);
594 static_assert(FirstPostprocessCounter <=
598 unsigned char counters[LastCounter - FirstCounter + 1];
613 assert(FirstTempCounter <= ctr);
614 assert(ctr < FirstPostprocessCounter);
623 assert(
counters[ctr - FirstCounter] <= 1);
708 unsigned const max_value)
711 if (ctr < FirstTempCounter || ctr >= FirstPostprocessCounter)
716 if (FirstCounter > ctr || ctr > LastCounter)
722 assert(max_value <= (ctr < FirstTempCounter ?
log_n : 1U));
723 if (
counters[ctr - FirstCounter] >= max_value)
727 "maximum value (" << max_value <<
") for ";
731 counters[ctr - FirstCounter] = max_value;
758 assert(FirstTempCounter <=
from);
759 assert(
from < FirstPostprocessCounter);
760 assert(FirstCounter <=
to);
761 assert(
to < FirstTempCounter || FirstPostprocessCounter <=
to);
762 assert(
to <= LastCounter);
763 assert(max_value <= (
to < FirstTempCounter ?
log_n : 1U));
769 "maximum value (" << max_value <<
") for ";
790 (void)
to; (void) max_value;
836 unsigned const max_B)
839 assert(max_C <= max_B);
847 assert(max_B <=
log_n);
856 (void) max_C; (void) max_B;
867 B_TO_C_MIN_TEMP, (enum counter_type) (B_TO_C_MAX_TEMP + 1)>
887 assert(max_targetC <=
log_n);
901 "maximum value (" << 0 <<
") for ";
957 STATE_MIN_TEMP, (enum counter_type) (STATE_MAX_TEMP + 1)>
985 assert(max_B <=
log_n);
1001 "maximum value (" << 0 <<
") for ";
1015 "maximum value (" << (unsigned) bottom <<
") for ";
1021 (void) max_B; (void) bottom;
1028 TRANS_MIN_TEMP, (enum counter_type) (TRANS_MAX_TEMP + 1)>
1065 unsigned const max_targetC,
1066 unsigned const max_targetB,
bool const source_bottom)
1069 assert(max_targetC <= max_targetB);
1077 assert(max_sourceB <=
log_n);
1085 assert(max_targetB <=
log_n);
1100 "maximum value (" << 0 <<
") for ";
1106 assert((
unsigned) source_bottom <= 1);
1114 "maximum value (" << (unsigned) source_bottom <<
") for ";
1120 (void) max_sourceB; (void) max_targetC; (void) max_targetB;
1121 (void) source_bottom;
1147 unsigned const max_value)
1155 assert(1 == max_value);
1164 "maximum value (" << max_value <<
") for ";
1167 (void) ctr; (void) max_value;
1176 create_initial_partition>
1198 assert((
log_n + 1U) / 2U <= max_block);
1199 if (max_block >
log_n)
1202 << max_block <<
" exceeded log_n == "
1203 << (unsigned)
log_n <<
" for ";
1206 assert(max_block <=
log_n);
1228 STATE_dnj_MIN_TEMP, (enum counter_type) (STATE_dnj_MAX_TEMP + 1)>
1251 assert((
log_n + 1U) / 2U <= max_block);
1252 assert(max_block <=
log_n);
1273 (void) max_block; (void) bottom;
1301 assert(max_bunch <=
log_n);
1316 BLOCK_BUNCH_dnj_MAX, BLOCK_BUNCH_dnj_MIN_TEMP,
1317 (enum counter_type) (BLOCK_BUNCH_dnj_MAX_TEMP + 1)>
1339 assert(max_bunch <=
log_n);
1348 "maximum value (" << (unsigned) max_bunch <<
") for ";
1361 "maximum value (" << (unsigned) 0 <<
") for ";
1386 TRANS_dnj_MIN_TEMP, (enum counter_type) (TRANS_dnj_MAX_TEMP + 1)>
1408 unsigned const max_target_block,
bool const bottom)
1411 assert((
log_n + 1U) / 2U <= max_source_block);
1412 assert(max_source_block <=
log_n);
1420 assert((
log_n + 1U) / 2U <= max_target_block);
1421 assert(max_target_block <=
log_n);
1443 "maximum value (" << (unsigned) bottom <<
") for ";
1449 (void) max_source_block; (void) max_target_block; (void) bottom;
1475 unsigned const max_value)
1483 assert(1 == max_value);
1492 "maximum value (" << max_value <<
") for ";
1495 (void) ctr; (void) max_value;
1523 unsigned const max_B)
1526 assert(max_C <= max_B);
1527 assert(max_B <=
log_n);
1542 (void) max_C; (void) max_B;
1570 unsigned max_targetC)
1573 assert(max_sourceC <=
log_n);
1574 assert(max_targetC <=
log_n);
1589 (void) max_sourceC; (void) max_targetC;
1597 STATE_gj_MIN_TEMP, (enum counter_type) (STATE_gj_MAX_TEMP + 1)>
1625 assert(max_B <=
log_n);
1634 "maximum value (" << max_B <<
") for ";
1648 "maximum value (" << 0 <<
") for ";
1655 assert((
unsigned) bottom <= 1);
1663 "maximum value (" << (unsigned) bottom <<
") for ";
1675 (void) max_B; (void) bottom;
1682 TRANS_gj_MIN_TEMP, (enum counter_type) (TRANS_gj_MAX_TEMP + 1)>
1719 unsigned const max_targetC,
1720 unsigned const max_targetB,
bool const source_bottom)
1723 assert(max_sourceB <=
log_n);
1724 assert(max_targetB <=
log_n);
1725 assert(max_targetC <= max_targetB);
1760 "maximum value (" << 0 <<
") for ";
1773 "maximum value (" << (unsigned) source_bottom <<
") for ";
1779 assert((
unsigned) source_bottom <= 1);
1786 <<
"\" exceeded maximum value (" << 1 <<
") for ";
1791 (void) max_sourceB; (void) max_targetC; (void) max_targetB;
1792 (void) source_bottom;
1818 unsigned const max_value)
1826 assert(1 == max_value);
1835 "maximum value (" << max_value <<
") for ";
1838 (void) ctr; (void) max_value;
1845 #ifdef TEST_WORK_COUNTER_NAMES
1850 static void test_work_names();
1860 #ifdef TEST_WORK_COUNTER_NAMES
1882 #define percentage(steps,total) \
1884 (std::numeric_limits<trans_type>::max()-(total))/200), \
1885 ((steps)*(trans_type)200+(total))/(total)/2)
1886 if (0 != overall_total)
1892 <<
" states and transitions were inspected. ";
1898 <<
"% of all steps and cycles).\n";
1903 <<
"% of all steps";
1912 <<
"% of the steps have been cancelled.\n";
1941 #define mCRL2complexity(unit, call, info_for_debug) \
1944 const enum check_complexity::result_type \
1945 GG00OCOC0GQQ0COG00GQQQQOCOGQCO=((unit)->work_counter. call ); \
1946 switch (GG00OCOC0GQQ0COG00GQQQQOCOGQCO) \
1948 case check_complexity::complexity_ok: break; \
1950 mCRL2log(log::error) << "Unexpected return value " \
1951 << (int)GG00OCOC0GQQ0COG00GQQQQOCOGQCO << " for ";\
1953 case check_complexity::complexity_error: \
1954 case check_complexity::complexity_print: \
1955 mCRL2log(log::error) \
1956 << (unit)->debug_id(info_for_debug) << '\n'; \
1957 if (check_complexity::complexity_print != \
1958 GG00OCOC0GQQ0COG00GQQQQOCOGQCO) \
1959 exit(EXIT_FAILURE); \
1965 #define mCRL2complexity(unit, call, info_for_debug) \
1968 if (check_complexity::complexity_ok != \
1969 ((unit)->work_counter. call )) \
1971 mCRL2log(log::error) << __FILE__ << ':' << __LINE__ \
1972 << " Error in mCRL2complexity()\n"; \
1973 exit(EXIT_FAILURE); \
1983 #define mCRL2complexity(unit, call, info_for_debug) do {} while (0)
#define DONT_COUNT_TEMPORARY
special value for temporary work without changing the balance
#define percentage(steps, total)
result_type no_temporary_work(unsigned max_sourceC, unsigned max_targetC)
ensures there is no orphaned temporary work counter
counters for a B_to_C slice
void reset_work_counter_4_4()
sets the temporary counter associated with line 4.4 to zero
result_type no_temporary_work(unsigned const max_targetC)
ensures there is no orphaned temporary work counter
unsigned char get_work_counter_4_4() const
returns the temporary counter associated with line 4.4
void reset_temporary_work()
result_type no_temporary_work(unsigned const max_bunch)
ensures there is no orphaned temporary work counter
bool has_temporary_work()
result_type no_temporary_work(unsigned const max_C, unsigned const max_B)
ensures there is no orphaned temporary work counter
result_type no_temporary_work(unsigned const max_block)
ensures there is no orphaned temporary work counter
result_type no_temporary_work(unsigned const max_C, unsigned const max_B)
ensures there is no orphaned temporary work counter
result_type no_temporary_work(unsigned const max_bunch)
ensures there is no orphaned temporary work counter
subset of counters (to be associated with a state or transition)
result_type add_work(enum counter_type const ctr, unsigned const max_value)
register work with some counter
counter_t()
constructor, initializes all counters to 0
result_type finalise_work(enum counter_type const from, enum counter_type const to, unsigned const max_value)
move temporary work to its final counter
unsigned char counters[LastCounter - FirstCounter+1]
actual space to store the counters
result_type move_work(enum counter_type const from, enum counter_type const to, unsigned const max_value)
move temporary work to another counter
result_type cancel_work(enum counter_type const ctr)
cancel temporary work
result_type no_temporary_work(unsigned const max_B, bool const bottom)
ensures there is no orphaned temporary work counter
result_type no_temporary_work(unsigned const max_block, bool const bottom)
ensures there is no orphaned temporary work counter
result_type no_temporary_work(unsigned const max_B, bool const bottom)
ensures there is no orphaned temporary work counter
result_type add_work_notemporary(enum counter_type const ctr, unsigned const max_value)
register work with some temporary counter without changing the balance between sensible and superfluo...
result_type no_temporary_work(unsigned const max_sourceB, unsigned const max_targetC, unsigned const max_targetB, bool const source_bottom)
ensures there is no orphaned temporary work counter
result_type no_temporary_work(unsigned const max_source_block, unsigned const max_target_block, bool const bottom)
ensures there is no orphaned temporary work counter
result_type add_work_notemporary(enum counter_type const ctr, unsigned const max_value)
register work with some temporary counter without changing the balance between sensible and superfluo...
result_type no_temporary_work(unsigned const max_sourceB, unsigned const max_targetC, unsigned const max_targetB, bool const source_bottom)
ensures there is no orphaned temporary work counter
result_type add_work_notemporary(enum counter_type const ctr, unsigned const max_value)
register work with some temporary counter without changing the balance between sensible and superfluo...
class for time complexity checks
static int ilog2(state_type size)
calculate the base-2 logarithm, rounded down
static void cancel_work_units(trans_type units=1)
static signed_trans_type sensible_work
counter to register the work balance for coroutines
static void wait(trans_type units=1)
do some work that cannot be assigned directly
static void check_waiting_cycles()
static unsigned char log_n
value of floor(log2(n)) for easy access
counter_type
Type for complexity budget counters.
@ split_U__find_predecessors_of_U_state
@ split_R__handle_transition_to_R_state
@ refine_incoming_transition_3_18
@ stabilizeB__distribute_states_over_Phat
@ refine_partition_until_stable__stabilize_for_large_splitter
@ refine_partition_until_it_becomes_stable__find_cotransition
@ for_all_s_prime_in_pred_s_3_32l
@ for_all_s_prime_in_succ_s_3_32r
@ Move_Blue_or_Red_to_a_new_block_states_3_29
@ while_Test_is_not_empty_3_6l_s_is_blue_3_11l
@ split_block_B_into_R_and_BminR__carry_out_split
@ for_all_old_bottom_states_s_in_RedB_selfloop_4_15
@ refine_outgoing_transition_to_marked_state_3_6l
@ BLOCK_BUNCH_dnj_MIN_TEMP
@ refine_partition_until_it_becomes_stable__prepare_cosplit
@ multiple_swap_states_in_block__swap_state_in_small_block
@ while_Red_contains_unvisited_states_3_15r
@ Move_Blue_or_Red_to_a_new_block_succ_3_29
@ simple_splitB_U__handle_transition_to_U_state
@ simple_splitB__handle_transition_to_R_or_U_state
@ while_Blue_contains_unvisited_states_3_15l
@ for_all_s_prime_in_pred_s_setminus_Red_3_18l
@ for_all_transitions_from_bottom_states_a_posteriori_4_4
@ simple_splitB__find_bottom_state
@ refine_partition_until_stable__stabilize_new_noninert_a_posteriori
@ simple_splitB__test_outgoing_transitions_found_new_bottom_state
@ split__handle_transition_to_R_or_U_state
@ adapt_transitions_for_new_block
@ for_all_bottom_states_s_in_RfnB_4_8
@ for_all_s_prime_in_pred_s_3_18r
@ Move_Blue_or_Red_to_a_new_block_NewB_swap_3_29
@ refine_visited_state_3_15
@ refine_partition_until_stable__stabilize
@ multiple_swap_states_in_block__account_for_swap_in_aborted_block
@ create_initial_partition
@ for_all_transitions_from_bottom_states_a_priori_4_4
@ Move_Blue_or_Red_to_a_new_block_NewB_pointer_3_29
@ while_Test_is_not_empty_3_6l_s_is_red_3_9l_postprocessing
@ refine_outgoing_transition_from_new_bottom_3_23l
@ stabilizeB__initialize_Qhat_afterwards
@ split_block_B_into_R_and_BminR__skip_over_state
@ if___s_prime_has_transition_to_SpC_3_23l
@ Register_that_inert_transitions_from_s_go_to_NewC_swap_2_17
@ stabilizeB__prepare_block
@ handle_new_noninert_transns__make_unstable_temp
@ for_all_s_prime_in_pred_s_2_11
@ simple_splitB_R__handle_transition_to_R_state
@ simple_splitB__handle_transition_from_R_or_U_state
@ refine_partition_until_it_becomes_stable__find_splitter
@ for_all_transitions_that_need_postproc_a_posteriori_4_12
@ simple_splitB__find_predecessors_of_R_or_U_state
@ Register_that_inert_transitions_from_s_go_to_NewC_succ_2_17
@ split__test_noninert_transitions_found_new_bottom_state
@ four_way_splitB__handle_transitions_in_main_splitter
@ Register_that_inert_transitions_from_s_go_to_NewC_B_to_C_2_17
@ splitB__update_BLC_of_smaller_subblock
@ splitB__unmark_transitions_out_of_new_bottom_block
@ for_all_old_bottom_states_s_in_RedB_4_15
@ for_all_refinable_blocks_RfnB_2_20
@ splitB__unmark_transitions_out_of_new_bottom_block_afterwards
@ refine_outgoing_transition_postprocess_new_bottom_3_6l
@ stabilizeB__initialize_Qhat
@ refine_partition_until_stable__stabilize_new_noninert_a_priori
@ split_R__find_predecessors_of_R_state
@ refine_partition_until_it_becomes_stable__execute_main_split
@ simple_splitB_R__handle_transition_from_R_state
@ create_initial_partition__refine_block
@ simple_splitB_R__find_predecessors
@ create_initial_partition__set_start_incoming_transitions
@ split__handle_transition_from_R_or_U_state
@ handle_new_noninert_transns__make_unstable_a_priori
@ move_out_slice_to_new_block
@ split_U__handle_transition_to_U_state
@ split_R__handle_transition_from_R_state
@ split_U__test_noninert_transitions
@ handle_new_noninert_transns
@ order_BLC_transitions__sort_transition
@ refine_outgoing_transition_3_6_or_23l
@ simple_splitB_U__handle_transition_from_potential_U_state
@ for_all_transitions_that_need_postproc_a_priori_4_12
@ refine_partition_until_stable__find_pred
@ BLOCK_BUNCH_dnj_MAX_TEMP
@ handle_new_noninert_transns__make_unstable_a_posteriori
@ refine_partition_until_it_becomes_stable__correct_end_of_calM
@ while_Test_is_not_empty_3_6l_s_is_red_3_9l
@ stabilizeB__main_loop_afterwards
@ refine_bottom_state_3_6l
@ for_all_constellations_C_not_in_R_from_RfnB_4_4
@ simple_splitB_U__find_predecessors
@ while_C_contains_a_nontrivial_constellation_2_4
@ while_FromRed_is_not_empty_3_6r
@ split__find_predecessors_of_R_or_U_state
static trans_type sensible_work_grand_total
the number of useful steps in the course of the whole algorithm
static trans_type no_of_waiting_cycles_grand_total
the number of waiting cycles in the course of the whole algorithm
static trans_type cancelled_work_grand_total
the number of cancelled steps (in aborted coroutines) in the course of the whole algorithm
static const char * work_names[TRANS_gj_MAX - BLOCK_MIN+1]
printable names of the counter types (for error messages)
static void check_temporary_work()
check that not too much superfluous work has been done
static void finalise_work_units(trans_type units=1)
static void print_grand_totals()
print grand total of work in the coroutines (to measure overhead)
static void init(state_type n)
starts counting for a new refinement run
static bool cannot_wait_before_reset
indicates whether waiting cycles are allowed
static trans_type no_of_waiting_cycles
the number of waiting cycles that have been done in the current accounting period
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
std::size_t state_type
type used to store state (numbers and) counts
std::size_t trans_type
type used to store transition (numbers and) counts
std::make_signed< trans_type >::type signed_trans_type
type used to store differences between transition counters
std::size_t to(const outgoing_pair_t &p)
Target state of a label state pair.
std::size_t from(const outgoing_transitions_per_state_action_t::const_iterator &i)
From state of an iterator exploring transitions per outgoing state and action.
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...