12
12
#include < util/bitvector_types.h>
13
13
#include < util/console.h>
14
14
#include < util/expr_util.h>
15
+ #include < util/find_symbols.h>
15
16
#include < util/string2int.h>
16
17
#include < util/unicode.h>
17
18
@@ -59,21 +60,35 @@ class random_tracest
59
60
const namespacet ns;
60
61
messaget message;
61
62
62
- using inputst = std::vector<symbol_exprt>;
63
+ using symbolst = std::vector<symbol_exprt>;
63
64
64
65
std::vector<exprt> random_input_constraints (
65
66
decision_proceduret &,
66
- const inputst & ,
67
+ const symbolst &inputs ,
67
68
size_t number_of_timeframes);
68
69
70
+ std::vector<exprt> random_initial_state_constraints (
71
+ decision_proceduret &,
72
+ const symbolst &state_variables);
73
+
74
+ static std::vector<exprt>
75
+ merge_constraints (const std::vector<exprt> &a, const std::vector<exprt> &b)
76
+ {
77
+ std::vector<exprt> result;
78
+ result.reserve (a.size () + b.size ());
79
+ result.insert (result.end (), a.begin (), a.end ());
80
+ result.insert (result.end (), b.begin (), b.end ());
81
+ return result;
82
+ }
83
+
69
84
constant_exprt random_value (const typet &);
70
85
71
- inputst inputs () const ;
86
+ symbolst inputs () const ;
87
+ symbolst state_variables () const ;
88
+ symbolst remove_constrained (const symbolst &) const ;
72
89
73
- void freeze_inputs (
74
- const inputst &,
75
- std::size_t number_of_timeframes,
76
- boolbvt &) const ;
90
+ void
91
+ freeze (const symbolst &, std::size_t number_of_timeframes, boolbvt &) const ;
77
92
78
93
// Random number generator. These are fully specified in
79
94
// the C++ standard, and produce the same values on compliant
@@ -261,10 +276,15 @@ int random_trace(const cmdlinet &cmdline, message_handlert &message_handler)
261
276
262
277
auto consumer = [&](trans_tracet trace) -> void {
263
278
namespacet ns (transition_system.symbol_table );
264
- if (cmdline.isset (" random-waveform" ))
279
+ if (cmdline.isset (" random-waveform" ) || cmdline. isset ( " waveform " ) )
265
280
{
266
281
show_waveform (trace, ns);
267
282
}
283
+ else if (cmdline.isset (" numbered-trace" ))
284
+ {
285
+ messaget message (message_handler);
286
+ show_trans_trace_numbered (trace, message, ns, consolet::out ());
287
+ }
268
288
else // default
269
289
{
270
290
messaget message (message_handler);
@@ -406,9 +426,9 @@ Function: random_tracest::inputs
406
426
407
427
\*******************************************************************/
408
428
409
- random_tracest::inputst random_tracest::inputs () const
429
+ random_tracest::symbolst random_tracest::inputs () const
410
430
{
411
- inputst inputs;
431
+ symbolst inputs;
412
432
413
433
const auto &module_symbol = *transition_system.main_symbol ;
414
434
@@ -435,7 +455,7 @@ random_tracest::inputst random_tracest::inputs() const
435
455
436
456
/* ******************************************************************\
437
457
438
- Function: random_tracest::freeze_inputs
458
+ Function: random_tracest::state_variables
439
459
440
460
Inputs:
441
461
@@ -445,17 +465,81 @@ Function: random_tracest::freeze_inputs
445
465
446
466
\*******************************************************************/
447
467
448
- void random_tracest::freeze_inputs (
449
- const inputst &inputs,
468
+ random_tracest::symbolst random_tracest::state_variables () const
469
+ {
470
+ symbolst state_variables;
471
+
472
+ const auto &module_symbol = *transition_system.main_symbol ;
473
+ const namespacet ns (transition_system.symbol_table );
474
+
475
+ const auto &symbol_module_map =
476
+ transition_system.symbol_table .symbol_module_map ;
477
+ auto lower = symbol_module_map.lower_bound (module_symbol.name );
478
+ auto upper = symbol_module_map.upper_bound (module_symbol.name );
479
+
480
+ for (auto it = lower; it != upper; it++)
481
+ {
482
+ const symbolt &symbol = ns.lookup (it->second );
483
+
484
+ if (symbol.is_state_var )
485
+ state_variables.push_back (symbol.symbol_expr ());
486
+ }
487
+
488
+ return state_variables;
489
+ }
490
+
491
+ /* ******************************************************************\
492
+
493
+ Function: random_tracest::remove_constrained
494
+
495
+ Inputs:
496
+
497
+ Outputs:
498
+
499
+ Purpose:
500
+
501
+ \*******************************************************************/
502
+
503
+ random_tracest::symbolst
504
+ random_tracest::remove_constrained (const symbolst &symbols) const
505
+ {
506
+ auto constrained_symbols = find_symbols (transition_system.trans_expr .init ());
507
+
508
+ symbolst result;
509
+ result.reserve (symbols.size ());
510
+
511
+ // this is symbols setminus constrained_symbols
512
+ for (auto &symbol : symbols)
513
+ if (constrained_symbols.find (symbol) == constrained_symbols.end ())
514
+ result.push_back (symbol);
515
+
516
+ return result;
517
+ }
518
+
519
+ /* ******************************************************************\
520
+
521
+ Function: random_tracest::freeze
522
+
523
+ Inputs:
524
+
525
+ Outputs:
526
+
527
+ Purpose:
528
+
529
+ \*******************************************************************/
530
+
531
+ void random_tracest::freeze (
532
+ const symbolst &symbols,
450
533
std::size_t number_of_timeframes,
451
534
boolbvt &boolbv) const
452
535
{
453
536
for (std::size_t i = 0 ; i < number_of_timeframes; i++)
454
537
{
455
- for (auto &input : inputs )
538
+ for (auto &symbol : symbols )
456
539
{
457
- auto input_in_timeframe = instantiate (input, i, number_of_timeframes, ns);
458
- boolbv.set_frozen (boolbv.convert_bv (input_in_timeframe));
540
+ auto symbol_in_timeframe =
541
+ instantiate (symbol, i, number_of_timeframes, ns);
542
+ boolbv.set_frozen (boolbv.convert_bv (symbol_in_timeframe));
459
543
}
460
544
}
461
545
}
@@ -495,6 +579,35 @@ std::vector<exprt> random_tracest::random_input_constraints(
495
579
496
580
/* ******************************************************************\
497
581
582
+ Function: random_tracest::random_initial_state_constraints
583
+
584
+ Inputs:
585
+
586
+ Outputs:
587
+
588
+ Purpose:
589
+
590
+ \*******************************************************************/
591
+
592
+ std::vector<exprt> random_tracest::random_initial_state_constraints (
593
+ decision_proceduret &solver,
594
+ const symbolst &state_variables)
595
+ {
596
+ std::vector<exprt> result;
597
+
598
+ for (auto &symbol : state_variables)
599
+ {
600
+ auto symbol_in_timeframe = instantiate (symbol, 0 , 1 , ns);
601
+ auto constraint =
602
+ equal_exprt (symbol_in_timeframe, random_value (symbol.type ()));
603
+ result.push_back (std::move (constraint));
604
+ }
605
+
606
+ return result;
607
+ }
608
+
609
+ /* ******************************************************************\
610
+
498
611
Function: random_tracest::operator()()
499
612
500
613
Inputs:
@@ -533,10 +646,16 @@ void random_tracest::operator()(
533
646
if (inputs.empty ())
534
647
throw ebmc_errort () << " module does not have inputs" ;
535
648
536
- message.statistics () << " Found " << inputs.size () << " input(s)"
649
+ auto state_variables = this ->state_variables ();
650
+
651
+ message.statistics () << " Found " << inputs.size () << " input(s) and "
652
+ << state_variables.size () << " state variable(s)"
537
653
<< messaget::eom;
538
654
539
- freeze_inputs (inputs, number_of_timeframes, solver);
655
+ auto unconstrained_state_variables = remove_constrained (state_variables);
656
+
657
+ freeze (inputs, number_of_timeframes, solver);
658
+ freeze (unconstrained_state_variables, 1 , solver);
540
659
541
660
message.status () << " Solving with " << solver.decision_procedure_text ()
542
661
<< messaget::eom;
@@ -546,7 +665,13 @@ void random_tracest::operator()(
546
665
auto input_constraints =
547
666
random_input_constraints (solver, inputs, number_of_timeframes);
548
667
549
- solver.push (input_constraints);
668
+ auto initial_state_constraints =
669
+ random_initial_state_constraints (solver, unconstrained_state_variables);
670
+
671
+ auto merged =
672
+ merge_constraints (input_constraints, initial_state_constraints);
673
+
674
+ solver.push (merged);
550
675
auto dec_result = solver ();
551
676
solver.pop ();
552
677
0 commit comments