CBMC
goto_symex_property_decider.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Property Decider for Goto-Symex
4 
5 Author: Daniel Kroening, Peter Schrammel
6 
7 \*******************************************************************/
8 
11 
13 
14 #include <util/ui_message.h>
15 
17 #include <solvers/prop/prop.h> // IWYU pragma: keep
18 
20  const optionst &options,
21  ui_message_handlert &ui_message_handler,
22  symex_target_equationt &equation,
23  const namespacet &ns)
24  : options(options), ui_message_handler(ui_message_handler), equation(equation)
25 {
26  solver_factoryt solvers(
27  options,
28  ns,
31  solver = solvers.get_solver();
32 }
33 
35 {
36  exprt::operandst conjuncts;
37  conjuncts.reserve(instances.size());
38  for(const auto &inst : instances)
39  conjuncts.push_back(inst->cond_handle);
40  return conjunction(conjuncts);
41 }
42 
45 {
46  goal_map.clear();
47 
48  for(symex_target_equationt::SSA_stepst::iterator it =
49  equation.SSA_steps.begin();
50  it != equation.SSA_steps.end();
51  ++it)
52  {
53  if(it->is_assert())
54  {
55  const irep_idt &property_id = it->property_id;
56  CHECK_RETURN(!property_id.empty());
57 
58  // consider goal instance if it is in the given properties
59  auto property_pair_it = properties.find(property_id);
60  if(
61  property_pair_it != properties.end() &&
62  is_property_to_check(property_pair_it->second.status))
63  {
64  // it's going to be checked, but we don't know the status yet
65  property_pair_it->second.status |= property_statust::UNKNOWN;
66  goal_map[property_id].instances.push_back(it);
67  }
68  }
69  }
70 }
71 
73 {
74  for(auto &goal_pair : goal_map)
75  {
76  // Our goal is to falsify a property, i.e., we will
77  // add the negation of the property as goal.
78  goal_pair.second.condition = solver->decision_procedure().handle(
79  not_exprt(goal_pair.second.as_expr()));
80  }
81 }
82 
84  std::function<bool(const irep_idt &)> select_property)
85 {
86  exprt::operandst disjuncts;
87  decision_proceduret &decision_procedure = solver->decision_procedure();
88 
89  for(const auto &goal_pair : goal_map)
90  {
91  if(
92  select_property(goal_pair.first) &&
93  !goal_pair.second.condition.is_false())
94  {
95  disjuncts.push_back(goal_pair.second.condition);
96  }
97  }
98 
99  // this is 'false' if there are no disjuncts
100  exprt goal_disjunction = disjunction(disjuncts);
101  decision_procedure.set_to_true(goal_disjunction);
102 
103  with_solver_hardness(decision_procedure, [](solver_hardnesst &hardness) {
104  // SSA expr and involved steps have already been collected
105  // in symex_target_equationt::convert_assertions
106  exprt ssa_expr_unused;
107  std::vector<goto_programt::const_targett> involved_steps_unused;
108  hardness.register_assertion_ssas(ssa_expr_unused, involved_steps_unused);
109  });
110 }
111 
113 {
114  return solver->decision_procedure()();
115 }
116 
119 {
120  return solver->decision_procedure();
121 }
122 
125 {
126  return solver->stack_decision_procedure();
127 }
128 
130 {
131  return equation;
132 }
133 
135  propertiest &properties,
136  std::unordered_set<irep_idt> &updated_properties,
137  decision_proceduret::resultt dec_result,
138  bool set_pass) const
139 {
140  switch(dec_result)
141  {
143  for(auto &goal_pair : goal_map)
144  {
145  auto &status = properties.at(goal_pair.first).status;
146  if(
147  solver->decision_procedure()
148  .get(goal_pair.second.condition)
149  .is_true() &&
150  status != property_statust::FAIL)
151  {
152  status |= property_statust::FAIL;
153  updated_properties.insert(goal_pair.first);
154  }
155  }
156  break;
158  if(!set_pass)
159  break;
160 
161  for(auto &property_pair : properties)
162  {
163  if(property_pair.second.status == property_statust::UNKNOWN)
164  {
165  property_pair.second.status |= property_statust::PASS;
166  updated_properties.insert(property_pair.first);
167  }
168  }
169  break;
171  for(auto &property_pair : properties)
172  {
173  if(property_pair.second.status == property_statust::UNKNOWN)
174  {
175  property_pair.second.status |= property_statust::ERROR;
176  updated_properties.insert(property_pair.first);
177  }
178  }
179  break;
180  }
181 }
An interface for a decision procedure for satisfiability problems.
resultt
Result of running the decision procedure.
void set_to_true(const exprt &)
For a Boolean expression expr, add the constraint 'expr'.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
bool empty() const
Definition: dstring.h:89
Base class for all expressions.
Definition: expr.h:56
std::vector< exprt > operandst
Definition: expr.h:58
symex_target_equationt & get_equation() const
Return the equation associated with this instance.
goto_symex_property_decidert(const optionst &options, ui_message_handlert &ui_message_handler, symex_target_equationt &equation, const namespacet &ns)
decision_proceduret & get_decision_procedure() const
Returns the solver instance.
decision_proceduret::resultt solve()
Calls solve() on the solver instance.
std::unique_ptr< solver_factoryt::solvert > solver
void update_properties_goals_from_symex_target_equation(propertiest &properties)
Get the conditions for the properties from the equation and collect all 'instances' of the properties...
void update_properties_status_from_goals(propertiest &properties, std::unordered_set< irep_idt > &updated_properties, decision_proceduret::resultt dec_result, bool set_pass=true) const
Update the property status from the truth value of the goal variable.
void add_constraint_from_goals(std::function< bool(const irep_idt &property_id)> select_property)
Add disjunction of negated selected properties to the equation.
void convert_goals()
Convert the instances of a property into a goal variable.
std::map< irep_idt, goalt > goal_map
Maintains the relation between a property ID and the corresponding goal variable that encodes the neg...
stack_decision_proceduret & get_stack_decision_procedure() const
Returns the solver instance.
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
Boolean negation.
Definition: std_expr.h:2327
virtual std::unique_ptr< solvert > get_solver()
Returns a solvert object.
Inheriting the interface of symex_targett this class represents the SSA form of the input program as ...
virtual uit get_ui() const
Definition: ui_message.h:33
Property Decider for Goto-Symex.
bool is_property_to_check(property_statust status)
Return true if the status is NOT_CHECKED or UNKNOWN.
Definition: properties.cpp:175
@ UNKNOWN
The checker was unable to determine the status of the property.
@ PASS
The property was not violated.
@ ERROR
An error occurred during goto checking.
@ FAIL
The property was violated.
std::map< irep_idt, property_infot > propertiest
A map of property IDs to property infos.
Definition: properties.h:76
static void with_solver_hardness(decision_proceduret &maybe_hardness_collector, std::function< void(solver_hardnesst &hardness)> handler)
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
exprt conjunction(const exprt::operandst &op)
1) generates a conjunction for two or more operands 2) for one operand, returns the operand 3) return...
Definition: std_expr.cpp:66
exprt disjunction(const exprt::operandst &op)
1) generates a disjunction for two or more operands 2) for one operand, returns the operand 3) return...
Definition: std_expr.cpp:54
std::vector< symex_target_equationt::SSA_stepst::iterator > instances
A property holds if all instances of it are true.
A structure that facilitates collecting the complexity statistics from a decision procedure.
void register_assertion_ssas(const exprt &ssa_expression, const std::vector< goto_programt::const_targett > &pcs)
Called from the symtex_target_equationt::convert_assertions, this function associates the disjunction...