@@ -121,6 +121,10 @@ class bdd_enginet
121
121
void compute_counterexample (
122
122
propertyt &,
123
123
unsigned number_of_timeframes);
124
+
125
+ void AGp (propertyt &);
126
+ void AGAFp (propertyt &);
127
+ void just_p (propertyt &);
124
128
};
125
129
126
130
/* ******************************************************************\
@@ -425,100 +429,229 @@ void bdd_enginet::check_property(propertyt &property)
425
429
!has_temporal_operator (to_unary_expr (expr).op ());
426
430
};
427
431
432
+ // special treatment for AG AFp
433
+ auto is_AG_AFp = [](const exprt &expr) {
434
+ return (expr.id () == ID_AG || expr.id () == ID_sva_always) &&
435
+ (to_unary_expr (expr).op ().id () == ID_AF ||
436
+ to_unary_expr (expr).op ().id () == ID_sva_eventually) &&
437
+ !has_temporal_operator (to_unary_expr (to_unary_expr (expr).op ()).op ());
438
+ };
439
+
428
440
if (is_AGp (property.expr ))
429
441
{
430
- const exprt &sub_expr = to_unary_expr (property.expr ).op ();
431
- BDD p=property2BDD (sub_expr);
442
+ AGp (property);
443
+ }
444
+ else if (is_AG_AFp (property.expr ))
445
+ {
446
+ AGAFp (property);
447
+ }
448
+ else if (!has_temporal_operator (property.expr ))
449
+ {
450
+ just_p (property);
451
+ }
452
+ }
432
453
433
- // Start with !p, and go backwards until saturation or we hit an
434
- // initial state.
435
-
436
- BDD states=!p;
437
- unsigned iteration=0 ;
438
-
439
- for (const auto &c : constraints_BDDs)
440
- states = states & c;
454
+ /* ******************************************************************\
441
455
442
- std:: size_t peak_bdd_nodes= 0 ;
456
+ Function: bdd_enginet::AGp
443
457
444
- while (true )
445
- {
446
- iteration++;
447
- message.statistics () << " Iteration " << iteration << messaget::eom;
458
+ Inputs:
448
459
449
- // do we have an initial state?
450
- BDD intersection=states;
451
-
452
- for (const auto &i : initial_BDDs)
453
- intersection=intersection & i;
460
+ Outputs:
454
461
455
- peak_bdd_nodes= std::max (peak_bdd_nodes, mgr. number_of_nodes ());
462
+ Purpose:
456
463
457
- if (!intersection.is_false ())
458
- {
459
- property.refuted ();
460
- message.status () << " Property refuted" << messaget::eom;
461
- compute_counterexample (property, iteration);
462
- break ;
463
- }
464
-
465
- // make the states be expressed in terms of 'next' variables
466
- BDD states_next=current_to_next (states);
464
+ \*******************************************************************/
467
465
468
- // now conjoin with transition relation
469
- BDD conjunction=states_next;
470
-
471
- for (const auto &t : transition_BDDs)
472
- conjunction = conjunction & t;
473
-
474
- for (const auto &c : constraints_BDDs)
475
- conjunction = conjunction & c;
466
+ void bdd_enginet::AGp (propertyt &property)
467
+ {
468
+ const exprt &sub_expr = to_unary_expr (property.expr ).op ();
469
+ BDD p = property2BDD (sub_expr);
476
470
477
- // now project away 'next' variables
478
- BDD pre_image=project_next (conjunction);
479
-
480
- // compute union
481
- BDD set_union=states | pre_image;
471
+ // Start with !p, and go backwards until saturation or we hit an
472
+ // initial state.
482
473
483
- // have we saturated?
484
- if ((set_union==states).is_true ())
485
- {
486
- property.proved ();
487
- message.status () << " Property proved" << messaget::eom;
488
- break ;
489
- }
474
+ BDD states = !p;
475
+ unsigned iteration = 0 ;
490
476
491
- states=set_union;
477
+ for (const auto &c : constraints_BDDs)
478
+ states = states & c;
492
479
493
- peak_bdd_nodes=std::max (peak_bdd_nodes, mgr.number_of_nodes ());
494
- }
495
- }
496
- else if (!has_temporal_operator (property.expr ))
480
+ std::size_t peak_bdd_nodes = 0 ;
481
+
482
+ while (true )
497
483
{
498
- // We check whether the BDD for the negation of the property
499
- // contains an initial state.
500
- exprt negation=negate_property (property.expr );
501
- BDD states=property2BDD (negation);
484
+ iteration++;
485
+ message.statistics () << " Iteration " << iteration << messaget::eom;
502
486
503
487
// do we have an initial state?
504
- BDD intersection= states;
505
-
488
+ BDD intersection = states;
489
+
506
490
for (const auto &i : initial_BDDs)
507
491
intersection = intersection & i;
508
492
509
- for (const auto &c : constraints_BDDs)
510
- intersection = intersection & c;
493
+ peak_bdd_nodes = std::max (peak_bdd_nodes, mgr.number_of_nodes ());
511
494
512
495
if (!intersection.is_false ())
513
496
{
514
497
property.refuted ();
515
498
message.status () << " Property refuted" << messaget::eom;
499
+ compute_counterexample (property, iteration);
500
+ break ;
516
501
}
517
- else
502
+
503
+ // make the states be expressed in terms of 'next' variables
504
+ BDD states_next = current_to_next (states);
505
+
506
+ // now conjoin with transition relation
507
+ BDD conjunction = states_next;
508
+
509
+ for (const auto &t : transition_BDDs)
510
+ conjunction = conjunction & t;
511
+
512
+ for (const auto &c : constraints_BDDs)
513
+ conjunction = conjunction & c;
514
+
515
+ // now project away 'next' variables
516
+ BDD pre_image = project_next (conjunction);
517
+
518
+ // compute union
519
+ BDD set_union = states | pre_image;
520
+
521
+ // have we saturated?
522
+ if ((set_union == states).is_true ())
518
523
{
519
524
property.proved ();
520
525
message.status () << " Property proved" << messaget::eom;
526
+ break ;
527
+ }
528
+
529
+ states = set_union;
530
+
531
+ peak_bdd_nodes = std::max (peak_bdd_nodes, mgr.number_of_nodes ());
532
+ }
533
+ }
534
+
535
+ /* ******************************************************************\
536
+
537
+ Function: bdd_enginet::AGAFp
538
+
539
+ Inputs:
540
+
541
+ Outputs:
542
+
543
+ Purpose:
544
+
545
+ \*******************************************************************/
546
+
547
+ void bdd_enginet::AGAFp (propertyt &property)
548
+ {
549
+ const exprt &sub_expr = to_unary_expr (to_unary_expr (property.expr ).op ()).op ();
550
+ BDD p = property2BDD (sub_expr);
551
+
552
+ // Start with p, and go backwards until saturation.
553
+ // AG AFp holds iff this includes all initial states.
554
+
555
+ BDD good_states = p;
556
+ unsigned iteration = 0 ;
557
+
558
+ for (const auto &c : constraints_BDDs)
559
+ good_states = good_states & c;
560
+
561
+ std::size_t peak_bdd_nodes = 0 ;
562
+
563
+ while (true )
564
+ {
565
+ iteration++;
566
+ message.statistics () << " Iteration " << iteration << messaget::eom;
567
+
568
+ // make the states be expressed in terms of 'next' variables
569
+ BDD good_states_next = current_to_next (good_states);
570
+
571
+ // now conjoin with transition relation
572
+ BDD conjunction = good_states_next;
573
+
574
+ for (const auto &t : transition_BDDs)
575
+ conjunction = conjunction & t;
576
+
577
+ for (const auto &c : constraints_BDDs)
578
+ conjunction = conjunction & c;
579
+
580
+ // now project away 'next' variables
581
+ BDD pre_image = project_next (conjunction);
582
+
583
+ // compute union
584
+ BDD set_union = good_states | pre_image;
585
+
586
+ // have we saturated?
587
+ if ((set_union == good_states).is_true ())
588
+ {
589
+ message.progress () << " Fixedpoint reached" << messaget::eom;
590
+ break ;
521
591
}
592
+
593
+ good_states = set_union;
594
+
595
+ peak_bdd_nodes = std::max (peak_bdd_nodes, mgr.number_of_nodes ());
596
+ }
597
+
598
+ // Does 'good_states' include all initial states?
599
+ BDD union_with_initial = good_states;
600
+
601
+ for (const auto &i : initial_BDDs)
602
+ union_with_initial = union_with_initial | i;
603
+
604
+ if ((union_with_initial == good_states).is_true ())
605
+ {
606
+ // proved
607
+ property.proved ();
608
+ message.status () << " Property proved" << messaget::eom;
609
+ }
610
+ else
611
+ {
612
+ // refuted
613
+ property.refuted ();
614
+ message.status () << " Property refuted" << messaget::eom;
615
+ }
616
+ }
617
+
618
+ /* ******************************************************************\
619
+
620
+ Function: bdd_enginet::just_p
621
+
622
+ Inputs:
623
+
624
+ Outputs:
625
+
626
+ Purpose:
627
+
628
+ \*******************************************************************/
629
+
630
+ void bdd_enginet::just_p (propertyt &property)
631
+ {
632
+ // We check whether the BDD for the negation of the property
633
+ // contains an initial state.
634
+ exprt negation = negate_property (property.expr );
635
+ BDD states = property2BDD (negation);
636
+
637
+ // do we have an initial state?
638
+ BDD intersection = states;
639
+
640
+ for (const auto &i : initial_BDDs)
641
+ intersection = intersection & i;
642
+
643
+ for (const auto &c : constraints_BDDs)
644
+ intersection = intersection & c;
645
+
646
+ if (!intersection.is_false ())
647
+ {
648
+ property.refuted ();
649
+ message.status () << " Property refuted" << messaget::eom;
650
+ }
651
+ else
652
+ {
653
+ property.proved ();
654
+ message.status () << " Property proved" << messaget::eom;
522
655
}
523
656
}
524
657
0 commit comments