Skip to content

Commit 5592d84

Browse files
Factor out goto_symex_property_decider
1 parent 8d68f6d commit 5592d84

5 files changed

+282
-182
lines changed

src/goto-checker/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
SRC = bmc_util.cpp \
22
counterexample_beautification.cpp \
33
incremental_goto_checker.cpp \
4+
goto_symex_property_decider.cpp \
45
goto_trace_storage.cpp \
56
goto_verifier.cpp \
67
multi_path_symex_checker.cpp \
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/*******************************************************************\
2+
3+
Module: Property Decider for Goto-Symex
4+
5+
Author: Daniel Kroening, Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Property Decider for Goto-Symex
11+
12+
#include "goto_symex_property_decider.h"
13+
14+
goto_symex_property_decidert::goto_symex_property_decidert(
15+
const optionst &options,
16+
ui_message_handlert &ui_message_handler,
17+
symex_target_equationt &equation,
18+
const namespacet &ns)
19+
: options(options),
20+
ui_message_handler(ui_message_handler),
21+
equation(equation)
22+
{
23+
solver_factoryt solvers(
24+
options,
25+
ns,
26+
ui_message_handler,
27+
ui_message_handler.get_ui() == ui_message_handlert::uit::XML_UI);
28+
solver = solvers.get_solver();
29+
solver->prop_conv().set_message_handler(ui_message_handler);
30+
}
31+
32+
exprt goto_symex_property_decidert::goalt::as_expr() const
33+
{
34+
std::vector<exprt> tmp;
35+
tmp.reserve(instances.size());
36+
for(const auto &inst : instances)
37+
tmp.push_back(literal_exprt(inst->cond_literal));
38+
return conjunction(tmp);
39+
}
40+
41+
void goto_symex_property_decidert::
42+
update_properties_goals_from_symex_target_equation(propertiest &properties)
43+
{
44+
for(symex_target_equationt::SSA_stepst::iterator it =
45+
equation.SSA_steps.begin();
46+
it != equation.SSA_steps.end();
47+
++it)
48+
{
49+
if(it->is_assert())
50+
{
51+
irep_idt property_id = it->get_property_id();
52+
CHECK_RETURN(!property_id.empty());
53+
54+
// consider goal instance if it is in the given properties
55+
auto property_pair_it = properties.find(property_id);
56+
if(
57+
property_pair_it != properties.end() &&
58+
is_property_to_check(property_pair_it->second.status))
59+
{
60+
// it's going to be checked, but we don't know the status yet
61+
property_pair_it->second.status |= property_statust::UNKNOWN;
62+
goal_map[property_id].instances.push_back(it);
63+
}
64+
}
65+
}
66+
}
67+
68+
void goto_symex_property_decidert::convert_goals()
69+
{
70+
for(auto &goal_pair : goal_map)
71+
{
72+
// Our goal is to falsify a property, i.e., we will
73+
// add the negation of the property as goal.
74+
goal_pair.second.condition =
75+
!solver->prop_conv().convert(goal_pair.second.as_expr());
76+
}
77+
}
78+
79+
void goto_symex_property_decidert::freeze_goal_variables()
80+
{
81+
for(const auto &goal_pair : goal_map)
82+
{
83+
if(!goal_pair.second.condition.is_constant())
84+
solver->prop_conv().set_frozen(goal_pair.second.condition);
85+
}
86+
}
87+
88+
void goto_symex_property_decidert::add_constraint_from_goals(
89+
std::function<bool(const irep_idt &)> select_property)
90+
{
91+
exprt::operandst disjuncts;
92+
93+
for(const auto &goal_pair : goal_map)
94+
{
95+
if(
96+
select_property(goal_pair.first) &&
97+
!goal_pair.second.condition.is_false())
98+
{
99+
disjuncts.push_back(literal_exprt(goal_pair.second.condition));
100+
}
101+
}
102+
103+
// this is 'false' if there are no disjuncts
104+
solver->prop_conv().set_to_true(disjunction(disjuncts));
105+
}
106+
107+
decision_proceduret::resultt goto_symex_property_decidert::solve()
108+
{
109+
return solver->prop_conv().dec_solve();
110+
}
111+
112+
prop_convt &goto_symex_property_decidert::get_solver() const
113+
{
114+
return solver->prop_conv();
115+
}
116+
117+
symex_target_equationt &goto_symex_property_decidert::get_equation() const
118+
{
119+
return equation;
120+
}
121+
122+
void goto_symex_property_decidert::update_properties_status_from_goals(
123+
propertiest &properties,
124+
std::unordered_set<irep_idt> &updated_properties,
125+
decision_proceduret::resultt dec_result,
126+
bool set_pass) const
127+
{
128+
switch(dec_result)
129+
{
130+
case decision_proceduret::resultt::D_SATISFIABLE:
131+
for(auto &goal_pair : goal_map)
132+
{
133+
if(solver->prop_conv().l_get(goal_pair.second.condition).is_true())
134+
{
135+
properties.at(goal_pair.first).status |= property_statust::FAIL;
136+
updated_properties.insert(goal_pair.first);
137+
}
138+
}
139+
break;
140+
case decision_proceduret::resultt::D_UNSATISFIABLE:
141+
if(!set_pass)
142+
break;
143+
144+
for(auto &property_pair : properties)
145+
{
146+
if(property_pair.second.status == property_statust::UNKNOWN)
147+
{
148+
property_pair.second.status |= property_statust::PASS;
149+
updated_properties.insert(property_pair.first);
150+
}
151+
}
152+
break;
153+
case decision_proceduret::resultt::D_ERROR:
154+
for(auto &property_pair : properties)
155+
{
156+
if(property_pair.second.status == property_statust::UNKNOWN)
157+
{
158+
property_pair.second.status |= property_statust::ERROR;
159+
updated_properties.insert(property_pair.first);
160+
}
161+
}
162+
break;
163+
}
164+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*******************************************************************\
2+
3+
Module: Property Decider for Goto-Symex
4+
5+
Author: Daniel Kroening, Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Property Decider for Goto-Symex
11+
12+
#ifndef CPROVER_GOTO_CHECKER_GOTO_SYMEX_PROPERTY_DECIDER_H
13+
#define CPROVER_GOTO_CHECKER_GOTO_SYMEX_PROPERTY_DECIDER_H
14+
15+
#include <util/ui_message.h>
16+
17+
#include <goto-symex/symex_target_equation.h>
18+
19+
#include "properties.h"
20+
#include "solver_factory.h"
21+
22+
/// Provides management of goal variables that encode properties
23+
class goto_symex_property_decidert
24+
{
25+
public:
26+
goto_symex_property_decidert(
27+
const optionst &options,
28+
ui_message_handlert &ui_message_handler,
29+
symex_target_equationt &equation,
30+
const namespacet &ns);
31+
32+
/// Get the conditions for the properties from the equation
33+
/// and collect all 'instances' of the properties in the `goal_map`
34+
void
35+
update_properties_goals_from_symex_target_equation(propertiest &properties);
36+
37+
/// Convert the instances of a property into a goal variable
38+
void convert_goals();
39+
40+
/// Prevent the solver to optimize-away the goal variables
41+
/// (necessary for incremental solving)
42+
void freeze_goal_variables();
43+
44+
/// Add disjunction of negated selected properties to the equation
45+
void add_constraint_from_goals(
46+
std::function<bool(const irep_idt &property_id)> select_property);
47+
48+
/// Calls solve() on the solver instance
49+
decision_proceduret::resultt solve();
50+
51+
/// Returns the solver instance
52+
prop_convt &get_solver() const;
53+
54+
/// Return the equation associated with this instance
55+
symex_target_equationt &get_equation() const;
56+
57+
/// Update the property status from the truth value of the goal variable
58+
/// \param [inout] properties: The status is updated in this data structure
59+
/// \param [inout] updated_properties: The set of property IDs of
60+
/// updated properties
61+
/// \param dec_result: The result returned by the solver
62+
void update_properties_status_from_goals(
63+
propertiest &properties,
64+
std::unordered_set<irep_idt> &updated_properties,
65+
decision_proceduret::resultt dec_result,
66+
bool set_pass = true) const;
67+
68+
protected:
69+
const optionst &options;
70+
ui_message_handlert &ui_message_handler;
71+
symex_target_equationt &equation;
72+
std::unique_ptr<solver_factoryt::solvert> solver;
73+
74+
struct goalt
75+
{
76+
/// A property holds if all instances of it are true
77+
std::vector<symex_target_equationt::SSA_stepst::iterator> instances;
78+
79+
/// The goal variable
80+
literalt condition;
81+
82+
exprt as_expr() const;
83+
};
84+
85+
/// Maintains the relation between a property ID and
86+
/// the corresponding goal variable that encodes
87+
/// the negation of the conjunction of the instances of the property
88+
std::map<irep_idt, goalt> goal_map;
89+
};
90+
91+
#endif // CPROVER_GOTO_CHECKER_GOTO_SYMEX_PROPERTY_DECIDER_H

0 commit comments

Comments
 (0)