1 /*
2 * This file is part of the Yices SMT Solver.
3 * Copyright (C) 2017 SRI International.
4 *
5 * Yices is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Yices is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Yices. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "mcsat/trail.h"
20 #include "io/term_printer.h"
21 #include "io/yices_pp.h"
22
trail_construct(mcsat_trail_t * trail,const variable_db_t * var_db)23 void trail_construct(mcsat_trail_t* trail, const variable_db_t* var_db) {
24 trail->var_db = var_db;
25 init_ivector(&trail->elements, 0);
26 init_ivector(&trail->to_repropagate, 0);
27 init_ivector(&trail->level_sizes, 0);
28 trail->decision_level = 0;
29 trail->decision_level_base = 0;
30 mcsat_model_construct(&trail->model);
31 init_ivector(&trail->type, 0);
32 init_ivector(&trail->level, 0);
33 init_ivector(&trail->index, 0);
34 init_ivector(&trail->id, 0);
35 init_ivector(&trail->unassigned, 0);
36 trail->inconsistent = false;
37 }
38
trail_destruct(mcsat_trail_t * trail)39 void trail_destruct(mcsat_trail_t* trail) {
40 trail->var_db = NULL;
41 delete_ivector(&trail->elements);
42 delete_ivector(&trail->to_repropagate);
43 delete_ivector(&trail->level_sizes);
44 trail->decision_level = 0;
45 mcsat_model_destruct(&trail->model);
46 delete_ivector(&trail->type);
47 delete_ivector(&trail->level);
48 delete_ivector(&trail->index);
49 delete_ivector(&trail->id);
50 delete_ivector(&trail->unassigned);
51 }
52
trail_new_variable_notify(mcsat_trail_t * trail,variable_t x)53 void trail_new_variable_notify(mcsat_trail_t* trail, variable_t x) {
54 // Notify the model
55 mcsat_model_new_variable_notify(&trail->model, x);
56 // Resize variable info
57 while (trail->type.size <= x) {
58 ivector_push(&trail->type, UNASSIGNED);
59 ivector_push(&trail->level, -1);
60 ivector_push(&trail->index, -1);
61 ivector_push(&trail->id, -1);
62 }
63 }
64
trail_print(const mcsat_trail_t * trail,FILE * out)65 void trail_print(const mcsat_trail_t* trail, FILE* out) {
66 uint32_t i;
67 variable_t var;
68 assignment_type_t var_type;
69
70 fprintf(out, "[\n");
71 for (i = 0; i < trail->elements.size; ++ i) {
72 if (i) {
73 fprintf(out, ", ");
74 }
75 var = trail->elements.data[i];
76 var_type = trail_get_assignment_type(trail, var);
77
78 if (var_type == DECISION) {
79 fprintf(out, "\n");
80 } else if (i > 0) {
81 variable_t prev_var = trail->elements.data[i-1];
82 uint32_t l = trail_get_level(trail, prev_var);
83 uint32_t l_end = trail_get_level(trail, var);
84 for (; l < l_end; ++ l) {
85 fprintf(out, "\n ----------- PUSH -------------- \n");
86 }
87 }
88
89 variable_db_print_variable(trail->var_db, var, out);
90
91 switch (var_type) {
92 case DECISION:
93 fprintf(out, " *= ");
94 break;
95 case PROPAGATION:
96 fprintf(out, " == ");
97 break;
98 default:
99 assert(false);
100 }
101 mcsat_value_print(trail->model.values + var, out);
102 }
103 fprintf(out, "\n]\n");
104 }
105
106 static inline
trail_new_decision(mcsat_trail_t * trail)107 void trail_new_decision(mcsat_trail_t* trail) {
108 assert(trail_is_consistent(trail));
109 trail->decision_level ++;
110 ivector_push(&trail->level_sizes, trail->elements.size);
111 }
112
trail_new_base_level(mcsat_trail_t * trail)113 void trail_new_base_level(mcsat_trail_t* trail) {
114 assert(trail->decision_level == trail->decision_level_base);
115 trail_new_decision(trail);
116 trail->decision_level_base = trail->decision_level;
117 }
118
trail_pop_base_level(mcsat_trail_t * trail)119 uint32_t trail_pop_base_level(mcsat_trail_t* trail) {
120 assert(trail->decision_level == trail->decision_level_base);
121 assert(trail->decision_level_base > 0);
122 trail->decision_level_base --;
123 return trail->decision_level_base;
124 }
125
126 static inline
trail_undo_decision(mcsat_trail_t * trail)127 void trail_undo_decision(mcsat_trail_t* trail) {
128 trail->decision_level --;
129 ivector_pop(&trail->level_sizes);
130 }
131
132 static inline
trail_set_value(mcsat_trail_t * trail,variable_t x,const mcsat_value_t * value,uint32_t id,assignment_type_t type,uint32_t level)133 void trail_set_value(mcsat_trail_t* trail, variable_t x, const mcsat_value_t* value, uint32_t id, assignment_type_t type, uint32_t level) {
134 assert(trail->index.data[x] == -1);
135 assert(trail->type.data[x] == UNASSIGNED);
136 assert(trail->level.data[x] == -1);
137 assert(trail->id.data[x] == -1);
138 assert((type == DECISION && level == trail->decision_level) || (type == PROPAGATION && level <= trail->decision_level));
139
140 // Remember the index
141 trail->index.data[x] = trail->elements.size;
142 // Set the type
143 trail->type.data[x] = type;
144 // Set the level
145 trail->level.data[x] = level;
146 // Set the id of the decision
147 trail->id.data[x] = id;
148
149 // Set the value
150 assert(value->type != VALUE_BOOLEAN || variable_db_is_boolean(trail->var_db, x));
151 mcsat_model_set_value(&trail->model, x, value);
152 }
153
154 static inline
trail_undo_value(mcsat_trail_t * trail,variable_t x)155 void trail_undo_value(mcsat_trail_t* trail, variable_t x) {
156 trail->type.data[x] = UNASSIGNED;
157 trail->index.data[x] = -1;
158 trail->level.data[x] = -1;
159 trail->id.data[x] = -1;
160 ivector_push(&trail->unassigned, x);
161 }
162
trail_add_decision(mcsat_trail_t * trail,variable_t x,const mcsat_value_t * value,uint32_t id)163 void trail_add_decision(mcsat_trail_t* trail, variable_t x, const mcsat_value_t* value, uint32_t id) {
164 assert(x >= 0);
165 assert(!trail_has_value(trail, x));
166
167 // Mark new decision
168 trail_new_decision(trail);
169 // Set the value
170 trail_set_value(trail, x, value, id, DECISION, trail->decision_level);
171 // Push the element
172 ivector_push(&trail->elements, x);
173 }
174
trail_pop_decision(mcsat_trail_t * trail)175 void trail_pop_decision(mcsat_trail_t* trail) {
176 variable_t x;
177 // Undo the value with the addition of decision unmark
178 x = ivector_last(&trail->elements);
179 trail_undo_value(trail, x);
180 // Don't unset value, keep for caching: mcsat_model_unset_value(&trail->model, x);
181 trail_undo_decision(trail);
182 ivector_pop(&trail->elements);
183 // Also, we're back into consistent
184 trail->inconsistent = false;
185 // Repropagate
186 while (trail->to_repropagate.size > 0) {
187 x = ivector_last(&trail->to_repropagate);
188 ivector_pop(&trail->to_repropagate);
189 trail->index.data[x] = trail->elements.size;
190 ivector_push(&trail->elements, x);
191 }
192 }
193
trail_add_propagation(mcsat_trail_t * trail,variable_t x,const mcsat_value_t * value,uint32_t id,uint32_t level)194 void trail_add_propagation(mcsat_trail_t* trail, variable_t x, const mcsat_value_t* value, uint32_t id, uint32_t level) {
195 assert(x >= 0);
196 assert(!trail_has_value(trail, x));
197 assert(level >= trail->decision_level_base);
198 // Set the value
199 trail_set_value(trail, x, value, id, PROPAGATION, level);
200 // Push the element
201 ivector_push(&trail->elements, x);
202 }
203
204
trail_pop_propagation(mcsat_trail_t * trail)205 void trail_pop_propagation(mcsat_trail_t* trail) {
206 variable_t x;
207 uint32_t x_level;
208 // Undo the value with the addition of decision unmark
209 x = ivector_last(&trail->elements);
210 x_level = trail_get_level(trail, x);
211 if (x_level == trail->decision_level) {
212 trail_undo_value(trail, x);
213 // Don't unset model value, keep for caching: mcsat_model_unset_value(&trail->model, x);
214 } else {
215 // Propagations at lower levels, remember and re-propagate during on pop-decision
216 assert(x_level < trail->decision_level);
217 ivector_push(&trail->to_repropagate, x);
218 }
219 ivector_pop(&trail->elements);
220 }
221
trail_pop(mcsat_trail_t * trail)222 void trail_pop(mcsat_trail_t* trail) {
223 assert(trail->decision_level >= trail->decision_level_base);
224 assert(trail->level_sizes.size > 0);
225 uint32_t target_size = ivector_last(&trail->level_sizes);
226 while (trail->elements.size > target_size && trail_get_assignment_type(trail, trail_back(trail)) != DECISION) {
227 trail_pop_propagation(trail);
228 };
229 if (trail->elements.size > target_size) {
230 trail_pop_decision(trail);
231 } else {
232 // Fake push, no decision, so we just undo
233 trail_undo_decision(trail);
234 // Also, we're back into consistent
235 trail->inconsistent = false;
236 }
237 }
238
trail_gc_mark(mcsat_trail_t * trail,gc_info_t * gc_vars)239 void trail_gc_mark(mcsat_trail_t* trail, gc_info_t* gc_vars) {
240
241 uint32_t i;
242 variable_t var;
243
244 assert(trail->to_repropagate.size == 0);
245 assert(trail->unassigned.size == 0);
246 assert(trail->decision_level == trail->decision_level_base);
247
248 for (i = 0; i < trail->elements.size; ++ i) {
249 var = trail->elements.data[i];
250 assert(variable_db_is_variable(trail->var_db, var, true));
251 gc_info_mark(gc_vars, var);
252 }
253 }
254
trail_gc_sweep(mcsat_trail_t * trail,const gc_info_t * gc_vars)255 void trail_gc_sweep(mcsat_trail_t* trail, const gc_info_t* gc_vars) {
256 variable_t var;
257
258 assert(gc_vars->is_id);
259
260 // Remove from the model cache, otherwise the cache might contain wrongly
261 // typed variables
262 for (var = 0; var < trail->model.size; ++ var) {
263 if (var != variable_null && gc_info_get_reloc(gc_vars, var) == variable_null) {
264 assert(!trail_has_value(trail, var));
265 if (mcsat_model_has_value(&trail->model, var)) {
266 mcsat_model_unset_value(&trail->model, var);
267 }
268 assert(!trail_has_value(trail, var));
269 }
270 }
271 }
272