CBMC
solver.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Solver
4 
5 Author: Daniel Kroening, dkr@amazon.com
6 
7 \*******************************************************************/
8 
11 
12 #include "solver.h"
13 
14 #include <util/format_expr.h>
15 
16 #include "address_taken.h"
17 #include "generalization.h"
18 #include "inductiveness.h"
19 #include "report_properties.h"
20 #include "report_traces.h"
21 #include "solver_progress.h"
22 #include "solver_types.h"
23 
24 #include <iostream>
25 
27 {
28 public:
30  std::chrono::time_point<std::chrono::steady_clock> &_dest)
31  : dest(_dest)
32  {
33  }
34 
36  {
37  dest = std::chrono::steady_clock::now();
38  }
39 
40 protected:
41  std::chrono::time_point<std::chrono::steady_clock> &dest;
42 };
43 
44 void solver(
45  std::vector<framet> &frames,
46  const std::unordered_set<symbol_exprt, irep_hash> &address_taken,
47  const solver_optionst &solver_options,
48  const namespacet &ns,
49  std::vector<propertyt> &properties,
50  std::size_t property_index)
51 {
52  auto &property = properties[property_index];
53 
54  property.start = std::chrono::steady_clock::now();
55  take_time_resourcet stop_time(property.stop);
56 
57  // Clean up
58  for(auto &frame : frames)
59  frame.reset();
60 
61  // We start with I = P.
62  frames[property.frame.index].add_invariant(property.condition);
63 
64  for(unsigned iteration = 0; true; iteration++)
65  {
66  if(iteration == 3) // limit the effort
67  {
68  property.status = propertyt::DROPPED;
69  return; // give up
70  }
71 
72  if(solver_options.verbose)
73  std::cout << "Doing " << format(property.condition) << " iteration "
74  << iteration + 1 << '\n';
75 
76  auto result = inductiveness_check(
77  frames, address_taken, solver_options, ns, properties, property_index);
78 
79  switch(result.outcome)
80  {
82  property.status = propertyt::PASS;
83  return; // done
84 
86  if(iteration == 0)
87  {
88  // no generalization done, so this is a counterexample
89  property.status = propertyt::REFUTED;
90  return; // DONE
91  }
92  else
93  {
94  // Invariant was generalized too much. Try something weaker.
95  property.status = propertyt::DROPPED;
96  return;
97  }
98 
100  // Invariant is too weak or too strong to be inductive.
101  generalization(frames, *result.work, property, solver_options);
102  break;
103  }
104  }
105 }
106 
108  const std::vector<exprt> &constraints,
109  const solver_optionst &solver_options,
110  const namespacet &ns)
111 {
112  const auto address_taken = ::address_taken(constraints);
113 
114 #if 0
115  if(solver_options.verbose)
116  {
117  for(auto &a : address_taken)
118  std::cout << "address_taken: " << format(a) << '\n';
119  }
120 #endif
121 
122  auto frames = setup_frames(constraints);
123 
124  find_implications(constraints, frames);
125 
126  auto properties = find_properties(constraints, frames);
127 
128  if(properties.empty())
129  {
130  std::cout << "\nThere are no properties to show.\n";
132  }
133 
134  solver_progresst solver_progress(properties.size(), solver_options.verbose);
135 
136  // solve each property separately, in order of occurence
137  for(std::size_t i = 0; i < properties.size(); i++)
138  {
139  solver_progress(i);
140  solver(frames, address_taken, solver_options, ns, properties, i);
141  }
142 
143  solver_progress.finished();
144 
145  // reporting
146  report_properties(properties);
147 
148  if(solver_options.trace)
149  report_traces(frames, properties, solver_options.verbose, ns);
150 
151  // overall outcome
152  return overall_outcome(properties);
153 }
std::unordered_set< symbol_exprt, irep_hash > address_taken(const std::vector< exprt > &src)
Address Taken.
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
bool verbose
Definition: solver.h:31
bool trace
Definition: solver.h:30
std::chrono::time_point< std::chrono::steady_clock > & dest
Definition: solver.cpp:41
take_time_resourcet(std::chrono::time_point< std::chrono::steady_clock > &_dest)
Definition: solver.cpp:29
static format_containert< T > format(const T &o)
Definition: format.h:37
void generalization(std::vector< framet > &frames, const workt &dropped, const propertyt &property, const solver_optionst &solver_options)
Generalization.
inductiveness_resultt inductiveness_check(std::vector< framet > &frames, const std::unordered_set< symbol_exprt, irep_hash > &address_taken, const solver_optionst &solver_options, const namespacet &ns, std::vector< propertyt > &properties, std::size_t property_index)
Inductiveness.
solver_resultt overall_outcome(const std::vector< propertyt > &properties)
void report_properties(const std::vector< propertyt > &properties)
Property Reporting.
void report_traces(const std::vector< framet > &frames, const std::vector< propertyt > &properties, bool verbose, const namespacet &ns)
Report Traces.
void solver(std::vector< framet > &frames, const std::unordered_set< symbol_exprt, irep_hash > &address_taken, const solver_optionst &solver_options, const namespacet &ns, std::vector< propertyt > &properties, std::size_t property_index)
Definition: solver.cpp:44
Equality Propagation.
solver_resultt
Definition: solver.h:21
Solver Progress Reporting.
std::vector< propertyt > find_properties(const std::vector< exprt > &constraints, const std::vector< framet > &frames)
void find_implications(const std::vector< exprt > &constraints, std::vector< framet > &frames)
std::vector< framet > setup_frames(const std::vector< exprt > &constraints)