2
2
3
3
#include " smt2_incremental_decision_procedure.h"
4
4
5
+ #include < solvers/smt2_incremental/convert_expr_to_smt.h>
6
+ #include < solvers/smt2_incremental/smt_commands.h>
7
+ #include < solvers/smt2_incremental/smt_core_theory.h>
8
+ #include < solvers/smt2_incremental/smt_solver_process.h>
9
+ #include < solvers/smt2_incremental/smt_terms.h>
5
10
#include < util/expr.h>
11
+ #include < util/namespace.h>
12
+ #include < util/range.h>
13
+ #include < util/std_expr.h>
14
+ #include < util/string_utils.h>
15
+ #include < util/symbol.h>
16
+
17
+ #include < stack>
18
+
19
+ // / \brief Find all sub expressions of the given \p expr which need to be
20
+ // / expressed as separate smt commands.
21
+ // / \return A collection of sub expressions, which need to be expressed as
22
+ // / separate smt commands. This collection is in traversal order. It will
23
+ // / include duplicate subexpressions, which need to be removed by the caller
24
+ // / in order to avoid duplicate definitions.
25
+ // / \note This pass over \p expr is tightly coupled to the implementation of
26
+ // / `convert_expr_to_smt`. This is because any sub expressions which
27
+ // / `convert_expr_to_smt` translates into function applications, must also be
28
+ // / returned by this`gather_dependent_expressions` function.
29
+ static std::vector<exprt> gather_dependent_expressions (const exprt &expr)
30
+ {
31
+ std::vector<exprt> dependent_expressions;
32
+ expr.visit_pre ([&](const exprt &expr_node) {
33
+ if (can_cast_expr<symbol_exprt>(expr_node))
34
+ {
35
+ dependent_expressions.push_back (expr_node);
36
+ }
37
+ });
38
+ return dependent_expressions;
39
+ }
40
+
41
+ // / \brief Defines any functions which \p expr depends on, which have not yet
42
+ // / been defined, along with their dependencies in turn.
43
+ void smt2_incremental_decision_proceduret::define_dependent_functions (
44
+ const exprt &expr)
45
+ {
46
+ std::unordered_set<exprt, irep_hash> seen_expressions =
47
+ make_range (expression_identifiers)
48
+ .map ([](const std::pair<exprt, smt_identifier_termt> &expr_identifier) {
49
+ return expr_identifier.first ;
50
+ });
51
+ std::stack<exprt> to_be_defined;
52
+ const auto dependencies_needed = [&](const exprt &expr) {
53
+ bool result = false ;
54
+ for (const auto &dependency : gather_dependent_expressions (expr))
55
+ {
56
+ if (!seen_expressions.insert (dependency).second )
57
+ continue ;
58
+ result = true ;
59
+ to_be_defined.push (dependency);
60
+ }
61
+ return result;
62
+ };
63
+ dependencies_needed (expr);
64
+ while (!to_be_defined.empty ())
65
+ {
66
+ const exprt current = to_be_defined.top ();
67
+ if (dependencies_needed (current))
68
+ continue ;
69
+ if (const auto symbol_expr = expr_try_dynamic_cast<symbol_exprt>(current))
70
+ {
71
+ const irep_idt &identifier = symbol_expr->get_identifier ();
72
+ const symbolt *symbol = nullptr ;
73
+ if (ns.lookup (identifier, symbol) || symbol->value .is_nil ())
74
+ {
75
+ const smt_declare_function_commandt function{
76
+ smt_identifier_termt (
77
+ identifier, convert_type_to_smt_sort (symbol_expr->type ())),
78
+ {}};
79
+ expression_identifiers.emplace (*symbol_expr, function.identifier ());
80
+ solver_process->send (function);
81
+ }
82
+ else
83
+ {
84
+ if (dependencies_needed (symbol->value ))
85
+ continue ;
86
+ const smt_define_function_commandt function{
87
+ symbol->name , {}, convert_expr_to_smt (symbol->value )};
88
+ expression_identifiers.emplace (*symbol_expr, function.identifier ());
89
+ solver_process->send (function);
90
+ }
91
+ }
92
+ to_be_defined.pop ();
93
+ }
94
+ }
6
95
7
96
smt2_incremental_decision_proceduret::smt2_incremental_decision_proceduret (
8
- std::string solver_command)
9
- : solver_command{std::move (solver_command)}, number_of_solver_calls{0 }
97
+ const namespacet &_ns,
98
+ std::unique_ptr<smt_base_solver_processt> _solver_process,
99
+ message_handlert &message_handler)
100
+ : ns{_ns},
101
+ number_of_solver_calls{0 },
102
+ solver_process (std::move(_solver_process)),
103
+ log{message_handler}
104
+ {
105
+ solver_process->send (
106
+ smt_set_option_commandt{smt_option_produce_modelst{true }});
107
+ solver_process->send (smt_set_logic_commandt{
108
+ smt_logic_quantifier_free_uninterpreted_functions_bit_vectorst{}});
109
+ }
110
+
111
+ void smt2_incremental_decision_proceduret::ensure_handle_for_expr_defined (
112
+ const exprt &expr)
10
113
{
114
+ if (
115
+ expression_handle_identifiers.find (expr) !=
116
+ expression_handle_identifiers.cend ())
117
+ {
118
+ return ;
119
+ }
120
+
121
+ define_dependent_functions (expr);
122
+ smt_define_function_commandt function{
123
+ " B" + std::to_string (handle_sequence ()), {}, convert_expr_to_smt (expr)};
124
+ expression_handle_identifiers.emplace (expr, function.identifier ());
125
+ solver_process->send (function);
11
126
}
12
127
13
128
exprt smt2_incremental_decision_proceduret::handle (const exprt &expr)
14
129
{
130
+ log .debug () << " `handle` -\n " << expr.pretty (2 , 0 ) << messaget::eom;
131
+ ensure_handle_for_expr_defined (expr);
15
132
return expr;
16
133
}
17
134
@@ -29,7 +146,7 @@ void smt2_incremental_decision_proceduret::print_assignment(
29
146
std::string
30
147
smt2_incremental_decision_proceduret::decision_procedure_text () const
31
148
{
32
- return " incremental SMT2 solving via \" " + solver_command + " \" " ;
149
+ return " incremental SMT2 solving via " + solver_process-> description () ;
33
150
}
34
151
35
152
std::size_t
@@ -40,9 +157,22 @@ smt2_incremental_decision_proceduret::get_number_of_solver_calls() const
40
157
41
158
void smt2_incremental_decision_proceduret::set_to (const exprt &expr, bool value)
42
159
{
43
- UNIMPLEMENTED_FEATURE (
44
- " `set_to` (" + std::string{value ? " true" : " false" } + " ):\n " +
45
- expr.pretty (2 , 0 ));
160
+ PRECONDITION (can_cast_type<bool_typet>(expr.type ()));
161
+ log .debug () << " `set_to` (" << std::string{value ? " true" : " false" }
162
+ << " ) -\n " << expr.pretty (2 , 0 ) << messaget::eom;
163
+
164
+ define_dependent_functions (expr);
165
+ auto converted_term = [&]() -> smt_termt {
166
+ const auto expression_handle_identifier =
167
+ expression_handle_identifiers.find (expr);
168
+ if (expression_handle_identifier != expression_handle_identifiers.cend ())
169
+ return expression_handle_identifier->second ;
170
+ else
171
+ return convert_expr_to_smt (expr);
172
+ }();
173
+ if (!value)
174
+ converted_term = smt_core_theoryt::make_not (converted_term);
175
+ solver_process->send (smt_assert_commandt{converted_term});
46
176
}
47
177
48
178
void smt2_incremental_decision_proceduret::push (
@@ -69,5 +199,7 @@ void smt2_incremental_decision_proceduret::pop()
69
199
decision_proceduret::resultt smt2_incremental_decision_proceduret::dec_solve ()
70
200
{
71
201
++number_of_solver_calls;
72
- UNIMPLEMENTED_FEATURE (" solving." );
202
+ solver_process->send (smt_check_sat_commandt{});
203
+ const smt_responset result = solver_process->receive_response ();
204
+ UNIMPLEMENTED_FEATURE (" handling solver response." );
73
205
}
0 commit comments