4 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_liveness, mc,
5 "Logging specific to algorithms for liveness properties verification");
7 xbt_dynar_t initial_pairs = NULL;
9 xbt_dynar_t reached_pairs;
11 mc_pair_t new_pair(mc_snapshot_t sn, mc_state_t sg, xbt_state_t st){
13 p = xbt_new0(s_mc_pair_t, 1);
15 p->automaton_state = st;
19 mc_stats_pair->expanded_pairs++;
25 int reached(mc_pair_t pair){
27 char* hash_reached = malloc(sizeof(char)*160);
31 char *hash = malloc(sizeof(char)*160);
32 xbt_sha((char *)&pair, hash);
33 xbt_dynar_foreach(reached_pairs, c, hash_reached){
34 if(strcmp(hash, hash_reached) == 0){
44 void set_pair_reached(mc_pair_t pair){
46 if(reached(pair) == 0){
48 char *hash = malloc(sizeof(char)*160) ;
49 xbt_sha((char *)&pair, hash);
50 xbt_dynar_push(reached_pairs, &hash);
56 void MC_show_snapshot_stack(xbt_fifo_t stack){
63 for (item = xbt_fifo_get_last_item(stack);
64 (item ? (pair = (mc_pair_t) (xbt_fifo_get_item_content(item)))
65 : (NULL)); item = xbt_fifo_get_prev_item(item)) {
66 req = MC_state_get_executed_request(pair->graph_state, &value);
68 req_str = MC_request_to_string(req, value);
69 XBT_INFO("%s", req_str);
75 void MC_dump_snapshot_stack(xbt_fifo_t stack){
79 while ((pair = (mc_pair_t) xbt_fifo_pop(stack)) != NULL)
84 void MC_pair_delete(mc_pair_t pair){
85 xbt_free(pair->graph_state->proc_status);
86 xbt_free(pair->graph_state);
87 //xbt_free(pair->automaton_state); -> FIXME : à implémenter
92 int MC_automaton_evaluate_label(xbt_automaton_t a, xbt_exp_label_t l){
96 int left_res = MC_automaton_evaluate_label(a, l->u.or_and.left_exp);
97 int right_res = MC_automaton_evaluate_label(a, l->u.or_and.right_exp);
98 return (left_res || right_res);
102 int left_res = MC_automaton_evaluate_label(a, l->u.or_and.left_exp);
103 int right_res = MC_automaton_evaluate_label(a, l->u.or_and.right_exp);
104 return (left_res && right_res);
108 int res = MC_automaton_evaluate_label(a, l->u.exp_not);
113 unsigned int cursor = 0;
114 xbt_propositional_symbol_t p = NULL;
115 xbt_dynar_foreach(a->propositional_symbols, cursor, p){
116 if(strcmp(p->pred, l->u.predicat) == 0){
117 int (*f)() = p->function;
135 /******************************* DFS with visited state *******************************/
137 xbt_dynar_t visited_pairs;
139 void set_pair_visited(mc_pair_t pair, int sc){
142 mc_visited_pair_t p = NULL;
143 p = xbt_new0(s_mc_visited_pair_t, 1);
145 p->search_cycle = sc;
146 char *hash = malloc(sizeof(char)*160);
147 xbt_sha((char *)&p, hash);
148 xbt_dynar_push(visited_pairs, &hash);
153 int visited(mc_pair_t pair, int sc){
155 char* hash_visited = malloc(sizeof(char)*160);
159 mc_visited_pair_t p = NULL;
160 p = xbt_new0(s_mc_visited_pair_t, 1);
162 p->search_cycle = sc;
163 char *hash = malloc(sizeof(char)*160);
164 xbt_sha((char *)&p, hash);
165 xbt_dynar_foreach(visited_pairs, c, hash_visited){
166 if(strcmp(hash, hash_visited) == 0){
178 void MC_vddfs_with_restore_snapshot_init(xbt_automaton_t a){
180 XBT_DEBUG("**************************************************");
181 XBT_DEBUG("Double-DFS with visited state and restore snapshot init");
182 XBT_DEBUG("**************************************************");
184 mc_pair_t mc_initial_pair;
185 mc_state_t initial_graph_state;
186 smx_process_t process;
187 mc_snapshot_t init_snapshot;
189 MC_wait_for_requests();
193 init_snapshot = xbt_new0(s_mc_snapshot_t, 1);
195 initial_graph_state = MC_state_pair_new();
196 xbt_swag_foreach(process, simix_global->process_list){
197 if(MC_process_is_enabled(process)){
198 MC_state_interleave_process(initial_graph_state, process);
202 visited_pairs = xbt_dynar_new(sizeof(char *), NULL);
203 reached_pairs = xbt_dynar_new(sizeof(char *), NULL);
205 MC_take_snapshot(init_snapshot);
209 /* regarder dans l'automate toutes les transitions activables grâce à l'état initial du système
210 -> donnera les états initiaux de la propriété consistants avec l'état initial du système */
212 unsigned int cursor = 0;
213 unsigned int cursor2 = 0;
214 xbt_state_t state = NULL;
216 xbt_transition_t transition_succ;
217 xbt_dynar_t successors = xbt_dynar_new(sizeof(mc_pair_t), NULL);
220 xbt_dynar_foreach(a->states, cursor, state){
221 if(state->type == -1){
222 xbt_dynar_foreach(state->out, cursor2, transition_succ){
223 res = MC_automaton_evaluate_label(a, transition_succ->label);
225 if((res == 1) || (res == 2)){
229 mc_initial_pair = new_pair(init_snapshot, initial_graph_state, transition_succ->dst);
230 xbt_dynar_push(successors, &mc_initial_pair);
241 if(xbt_dynar_length(successors) == 0){
242 xbt_dynar_foreach(a->states, cursor, state){
243 if(state->type == -1){
246 mc_initial_pair = new_pair(init_snapshot, initial_graph_state, transition_succ->dst);
247 xbt_dynar_push(successors, &mc_initial_pair);
255 xbt_dynar_foreach(successors, cursor, pair_succ){
258 xbt_fifo_unshift(mc_snapshot_stack, pair_succ);
259 set_pair_visited(pair_succ, 0);
264 MC_vddfs_with_restore_snapshot(a, 0, 0);
266 MC_vddfs_with_restore_snapshot(a, 0, 1);
272 void MC_vddfs_with_restore_snapshot(xbt_automaton_t a, int search_cycle, int restore){
274 smx_process_t process = NULL;
277 if(xbt_fifo_size(mc_snapshot_stack) == 0)
281 MC_restore_snapshot(((mc_pair_t)xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_snapshot_stack)))->system_state);
286 /* Get current state */
287 mc_pair_t current_pair = (mc_pair_t)xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_snapshot_stack));
290 xbt_swag_foreach(process, simix_global->process_list){
291 if(MC_process_is_enabled(process)){
292 MC_state_interleave_process(current_pair->graph_state, process);
297 XBT_DEBUG("************************************************** ( search_cycle = %d )", search_cycle);
298 XBT_DEBUG("Pair : graph=%p, automaton=%p(%s), %u interleave", current_pair->graph_state, current_pair->automaton_state, current_pair->automaton_state->id,MC_state_interleave_size(current_pair->graph_state));
301 mc_stats_pair->visited_pairs++;
304 mc_state_t next_graph_state = NULL;
305 smx_req_t req = NULL;
309 xbt_transition_t transition_succ;
313 xbt_dynar_t successors = xbt_dynar_new(sizeof(mc_pair_t), NULL);
316 mc_snapshot_t next_snapshot;
317 mc_snapshot_t current_snapshot;
320 while((req = MC_state_get_request(current_pair->graph_state, &value)) != NULL){
323 current_snapshot = xbt_new0(s_mc_snapshot_t, 1);
324 MC_take_snapshot(current_snapshot);
328 /* Debug information */
329 if(XBT_LOG_ISENABLED(mc_liveness, xbt_log_priority_debug)){
330 req_str = MC_request_to_string(req, value);
331 XBT_DEBUG("Execute: %s", req_str);
335 MC_state_set_executed_request(current_pair->graph_state, req, value);
337 /* Answer the request */
338 SIMIX_request_pre(req, value);
340 /* Wait for requests (schedules processes) */
341 MC_wait_for_requests();
344 /* Create the new expanded graph_state */
347 next_graph_state = MC_state_pair_new();
349 /* Get enabled process and insert it in the interleave set of the next graph_state */
350 xbt_swag_foreach(process, simix_global->process_list){
351 if(MC_process_is_enabled(process)){
352 MC_state_interleave_process(next_graph_state, process);
356 next_snapshot = xbt_new0(s_mc_snapshot_t, 1);
357 MC_take_snapshot(next_snapshot);
361 xbt_dynar_reset(successors);
364 xbt_dynar_foreach(current_pair->automaton_state->out, cursor, transition_succ){
366 res = MC_automaton_evaluate_label(a, transition_succ->label);
370 if((res == 1) || (res == 2)){ // enabled transition in automaton
371 next_pair = new_pair(next_snapshot,next_graph_state, transition_succ->dst);
372 xbt_dynar_push(successors, &next_pair);
379 if(xbt_dynar_length(successors) == 0){
382 next_pair = new_pair(next_snapshot, next_graph_state, current_pair->automaton_state);
383 xbt_dynar_push(successors, &next_pair);
390 xbt_dynar_foreach(successors, cursor, pair_succ){
392 //XBT_DEBUG("Search visited pair : graph=%p, automaton=%p", pair_succ->graph_state, pair_succ->automaton_state);
394 if((search_cycle == 1) && (reached(pair_succ) == 1)){
395 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
396 XBT_INFO("| ACCEPTANCE CYCLE |");
397 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
398 XBT_INFO("Counter-example that violates formula :");
399 MC_show_snapshot_stack(mc_snapshot_stack);
400 MC_dump_snapshot_stack(mc_snapshot_stack);
401 MC_print_statistics_pairs(mc_stats_pair);
405 if(visited(pair_succ, search_cycle) == 0){
407 mc_stats_pair->executed_transitions++;
410 xbt_fifo_unshift(mc_snapshot_stack, pair_succ);
411 set_pair_visited(pair_succ, search_cycle);
414 MC_vddfs_with_restore_snapshot(a, search_cycle, 0);
416 if((search_cycle == 0) && (current_pair->automaton_state->type == 1)){
418 MC_restore_snapshot(current_pair->system_state);
421 xbt_swag_foreach(process, simix_global->process_list){
422 if(MC_process_is_enabled(process)){
423 MC_state_interleave_process(current_pair->graph_state, process);
427 set_pair_reached(current_pair);
428 XBT_DEBUG("Acceptance pair : graph=%p, automaton=%p(%s)", current_pair->graph_state, current_pair->automaton_state, current_pair->automaton_state->id);
429 MC_vddfs_with_restore_snapshot(a, 1, 1);
434 XBT_DEBUG("Pair already visited !");
440 if(MC_state_interleave_size(current_pair->graph_state) > 0){
441 MC_restore_snapshot(current_snapshot);
448 xbt_fifo_shift(mc_snapshot_stack);
449 XBT_DEBUG("Pair (graph=%p, automaton =%p) shifted in snapshot_stack", current_pair->graph_state, current_pair->automaton_state);
456 /********************* Double-DFS without visited state *******************/
459 void MC_ddfs_with_restore_snapshot_init(xbt_automaton_t a){
461 XBT_DEBUG("**************************************************");
462 XBT_DEBUG("Double-DFS without visited state and with restore snapshot init");
463 XBT_DEBUG("**************************************************");
465 mc_pair_t mc_initial_pair;
466 mc_state_t initial_graph_state;
467 smx_process_t process;
468 mc_snapshot_t init_snapshot;
470 MC_wait_for_requests();
474 init_snapshot = xbt_new0(s_mc_snapshot_t, 1);
476 initial_graph_state = MC_state_pair_new();
477 xbt_swag_foreach(process, simix_global->process_list){
478 if(MC_process_is_enabled(process)){
479 MC_state_interleave_process(initial_graph_state, process);
483 reached_pairs = xbt_dynar_new(sizeof(char *), NULL);
485 MC_take_snapshot(init_snapshot);
489 /* regarder dans l'automate toutes les transitions activables grâce à l'état initial du système
490 -> donnera les états initiaux de la propriété consistants avec l'état initial du système */
492 unsigned int cursor = 0;
493 unsigned int cursor2 = 0;
494 xbt_state_t state = NULL;
496 xbt_transition_t transition_succ;
497 xbt_dynar_t successors = xbt_dynar_new(sizeof(mc_pair_t), NULL);
500 xbt_dynar_foreach(a->states, cursor, state){
501 if(state->type == -1){
502 xbt_dynar_foreach(state->out, cursor2, transition_succ){
503 res = MC_automaton_evaluate_label(a, transition_succ->label);
505 if((res == 1) || (res == 2)){
509 mc_initial_pair = new_pair(init_snapshot, initial_graph_state, transition_succ->dst);
510 xbt_dynar_push(successors, &mc_initial_pair);
521 if(xbt_dynar_length(successors) == 0){
522 xbt_dynar_foreach(a->states, cursor, state){
523 if(state->type == -1){
526 mc_initial_pair = new_pair(init_snapshot, initial_graph_state, transition_succ->dst);
527 xbt_dynar_push(successors, &mc_initial_pair);
535 xbt_dynar_foreach(successors, cursor, pair_succ){
538 xbt_fifo_unshift(mc_snapshot_stack, pair_succ);
543 MC_ddfs_with_restore_snapshot(a, 0, 0);
545 MC_ddfs_with_restore_snapshot(a, 0, 1);
551 void MC_ddfs_with_restore_snapshot(xbt_automaton_t a, int search_cycle, int restore){
553 smx_process_t process = NULL;
556 if(xbt_fifo_size(mc_snapshot_stack) == 0)
560 MC_restore_snapshot(((mc_pair_t)xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_snapshot_stack)))->system_state);
565 /* Get current state */
566 mc_pair_t current_pair = (mc_pair_t)xbt_fifo_get_item_content(xbt_fifo_get_first_item(mc_snapshot_stack));
569 xbt_swag_foreach(process, simix_global->process_list){
570 if(MC_process_is_enabled(process)){
571 MC_state_interleave_process(current_pair->graph_state, process);
576 XBT_DEBUG("************************************************** ( search_cycle = %d )", search_cycle);
577 XBT_DEBUG("Pair : graph=%p, automaton=%p(%s), %u interleave", current_pair->graph_state, current_pair->automaton_state, current_pair->automaton_state->id,MC_state_interleave_size(current_pair->graph_state));
580 mc_stats_pair->visited_pairs++;
583 mc_state_t next_graph_state = NULL;
584 smx_req_t req = NULL;
588 xbt_transition_t transition_succ;
592 xbt_dynar_t successors = xbt_dynar_new(sizeof(mc_pair_t), NULL);
595 mc_snapshot_t next_snapshot;
596 mc_snapshot_t current_snapshot;
599 while((req = MC_state_get_request(current_pair->graph_state, &value)) != NULL){
602 current_snapshot = xbt_new0(s_mc_snapshot_t, 1);
603 MC_take_snapshot(current_snapshot);
607 /* Debug information */
608 if(XBT_LOG_ISENABLED(mc_liveness, xbt_log_priority_debug)){
609 req_str = MC_request_to_string(req, value);
610 XBT_DEBUG("Execute: %s", req_str);
614 MC_state_set_executed_request(current_pair->graph_state, req, value);
616 /* Answer the request */
617 SIMIX_request_pre(req, value);
619 /* Wait for requests (schedules processes) */
620 MC_wait_for_requests();
623 /* Create the new expanded graph_state */
626 next_graph_state = MC_state_pair_new();
628 /* Get enabled process and insert it in the interleave set of the next graph_state */
629 xbt_swag_foreach(process, simix_global->process_list){
630 if(MC_process_is_enabled(process)){
631 MC_state_interleave_process(next_graph_state, process);
635 next_snapshot = xbt_new0(s_mc_snapshot_t, 1);
636 MC_take_snapshot(next_snapshot);
640 xbt_dynar_reset(successors);
643 xbt_dynar_foreach(current_pair->automaton_state->out, cursor, transition_succ){
645 res = MC_automaton_evaluate_label(a, transition_succ->label);
649 if((res == 1) || (res == 2)){ // enabled transition in automaton
650 next_pair = new_pair(next_snapshot,next_graph_state, transition_succ->dst);
651 xbt_dynar_push(successors, &next_pair);
658 if(xbt_dynar_length(successors) == 0){
661 next_pair = new_pair(next_snapshot, next_graph_state, current_pair->automaton_state);
662 xbt_dynar_push(successors, &next_pair);
669 xbt_dynar_foreach(successors, cursor, pair_succ){
671 //XBT_DEBUG("Search visited pair : graph=%p, automaton=%p", pair_succ->graph_state, pair_succ->automaton_state);
673 if((search_cycle == 1) && (reached(pair_succ) == 1)){
674 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
675 XBT_INFO("| ACCEPTANCE CYCLE |");
676 XBT_INFO("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
677 XBT_INFO("Counter-example that violates formula :");
678 MC_show_snapshot_stack(mc_snapshot_stack);
679 MC_dump_snapshot_stack(mc_snapshot_stack);
680 MC_print_statistics_pairs(mc_stats_pair);
684 mc_stats_pair->executed_transitions++;
687 xbt_fifo_unshift(mc_snapshot_stack, pair_succ);
690 MC_ddfs_with_restore_snapshot(a, search_cycle, 0);
692 if((search_cycle == 0) && (current_pair->automaton_state->type == 1)){
694 MC_restore_snapshot(current_pair->system_state);
697 xbt_swag_foreach(process, simix_global->process_list){
698 if(MC_process_is_enabled(process)){
699 MC_state_interleave_process(current_pair->graph_state, process);
703 set_pair_reached(current_pair);
704 XBT_DEBUG("Acceptance pair : graph=%p, automaton=%p(%s)", current_pair->graph_state, current_pair->automaton_state, current_pair->automaton_state->id);
705 MC_ddfs_with_restore_snapshot(a, 1, 1);
711 if(MC_state_interleave_size(current_pair->graph_state) > 0){
712 MC_restore_snapshot(current_snapshot);
719 xbt_fifo_shift(mc_snapshot_stack);
720 XBT_DEBUG("Pair (graph=%p, automaton =%p) shifted in snapshot_stack", current_pair->graph_state, current_pair->automaton_state);