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 /*
20  * SOLVER FOR FUNCTION/ARRAY THEORY
21  */
22 
23 /*
24  * The solver maintains a graph: vertices denote arrays and edges
25  * represent array updates. An edge x ---> y labeled with terms (i_1, ..., i_n)
26  * means that x and y must be equal, except possibly at point (i_1,...,i_n).
27  */
28 
29 #ifndef __FUN_SOLVER_H
30 #define __FUN_SOLVER_H
31 
32 #include <stdint.h>
33 #include <stdbool.h>
34 #include <assert.h>
35 
36 #include "context/context_types.h"
37 #include "solvers/cdcl/smt_core.h"
38 #include "solvers/egraph/diseq_stacks.h"
39 #include "solvers/egraph/egraph.h"
40 #include "terms/types.h"
41 #include "utils/bitvectors.h"
42 #include "utils/int_hash_map2.h"
43 #include "utils/int_vectors.h"
44 #include "utils/ptr_vectors.h"
45 
46 
47 
48 /*
49  * GRAPH/VARIABLES
50  */
51 
52 /*
53  * Edges: one edge for each update term.
54  * (update f i_1 ... i_n v) creates an edge x ---> y labeled by i_1,.., i_n
55  * where source x = variable with term[x] = f
56  *       target y = variable with term[y] = (update f i_1 ... i_n v)
57  */
58 typedef struct fun_edge_s {
59   thvar_t source;
60   thvar_t target;
61   occ_t index[0]; // real size = arity n of source and target
62 } fun_edge_t;
63 
64 
65 /*
66  * Edge table:
67  * - resizable array: nedges = number of actual edges
68  * - data[i] = pointer to descriptor for edge i
69  */
70 typedef struct fun_edgetable_s {
71   uint32_t size;
72   uint32_t nedges;
73   fun_edge_t **data;
74 } fun_edgetable_t;
75 
76 #define DEF_FUN_EDGETABLE_SIZE  100
77 #define MAX_FUN_EDGETABLE_SIZE  (UINT32_MAX/8)
78 
79 
80 
81 /*
82  * Special edge indices:
83  * - null_fun_edge = -1
84  * - null_fun_pred = large index (used as a mark as pred[x] when x is a source variable)
85  */
86 enum {
87   null_fun_edge = -1,
88   null_fun_pred = INT32_MAX,
89 };
90 
91 
92 
93 /*
94  * Variable table
95  * - each variable is a vertex in the graph
96  * - for each variable x we store
97  *     type[x] = its type (as an index in the type table)
98  *    arity[x] = arity as defined by type[x] (not clear this is useful)
99  *     fdom[x] = one bit: fdom[x] = 1 iff x has a finite domain
100  *    eterm[x] = corresponding egraph term
101  *    edges[x] = vector of edge indices (edges with x as an extremity)
102  * - these structures are set when the graph and variables are constructed
103  *
104  * For constructing array models and generating axiom instances:
105  * - we group variables into equivalence classes:
106  *   x and y are in the same class if eterm[x] and eterm[y] are equal in the egraph
107  * - we use a breadth-first exploration of the graph from a source node z
108  * The following structures are used:
109  *    root[x] = root variable in the same equivalence class as x
110  *    next[x] = next element in the same class as x (or null if x is last)
111  *     pre[x] = last edge on a path from z to x (identified by its edge id)
112  *    base[x] = label to identify connected components: base[x] = base[y] means
113  *              that x and y are connected in the graph
114  *     app[x] = if x is a root, vector of composite terms (used for model construction)
115  *    mark[x] = bit used in propagation
116  */
117 typedef struct fun_vartable_s {
118   uint32_t size;
119   uint32_t nvars;
120   // static
121   type_t *type;
122   uint32_t *arity;
123   byte_t *fdom;
124   eterm_t *eterm;
125   int32_t **edges;
126   // dynamic
127   thvar_t *root;
128   thvar_t *next;
129   int32_t *pre;
130   int32_t *base;
131   void ***app;
132   byte_t *mark;
133 } fun_vartable_t;
134 
135 
136 #define DEF_FUN_VARTABLE_SIZE 100
137 #define MAX_FUN_VARTABLE_SIZE (UINT32_MAX/8)
138 
139 
140 
141 /*
142  * Queue for visiting the graph from a source node
143  * - data[0 ... top-1] = visited vertices (data[0] = source)
144  * - ptr = next node to process
145  * - size = size of the data array
146  * If x is and x != source, then pre[x] = k such that edge[k] is the last
147  * edge from the path source ... y ---> x. pre[x] = -1 otherwise.
148  */
149 typedef struct fun_queue_s {
150   uint32_t size;
151   uint32_t top;
152   uint32_t ptr;
153   thvar_t *data;
154 } fun_queue_t;
155 
156 #define DEF_FUN_QUEUE_SIZE 20
157 #define MAX_FUN_QUEUE_SIZE (UINT32_MAX/4)
158 
159 
160 
161 
162 /*
163  * PUSH/POP STACK
164  */
165 
166 /*
167  * Trailer stack:
168  * - for every push: keep number of variables + number of edges
169  */
170 typedef struct fun_trail_s {
171   uint32_t nvars;
172   uint32_t nedges;
173 } fun_trail_t;
174 
175 typedef struct fun_trail_stack_s {
176   uint32_t size;
177   uint32_t top;
178   fun_trail_t *data;
179 } fun_trail_stack_t;
180 
181 #define DEF_FUN_TRAIL_SIZE 20
182 #define MAX_FUN_TRAIL_SIZE (UINT32_MAX/sizeof(fun_trail_t))
183 
184 
185 
186 /*
187  * STATISTICS
188  */
189 typedef struct fun_solver_stats_s {
190   // initial size
191   uint32_t num_init_vars;
192   uint32_t num_init_edges;
193 
194   // number of axioms generated
195   uint32_t num_update_axiom1;
196   uint32_t num_update_axiom2;
197   uint32_t num_extensionality_axiom;
198 } fun_solver_stats_t;
199 
200 
201 
202 /*
203  * FULL SOLVER
204  */
205 typedef struct fun_solver_s {
206   /*
207    * Attached core + egraph + gate manager + type table
208    */
209   smt_core_t *core;
210   gate_manager_t *gate_manager;
211   egraph_t *egraph;
212   type_table_t *types;
213 
214   /*
215    * Base level/decision level
216    */
217   uint32_t base_level;
218   uint32_t decision_level;
219 
220   /*
221    * Statistics
222    */
223   fun_solver_stats_t stats;
224 
225   /*
226    * Search parameters
227    * - bound on the number of update conflicts generated in each call to final_check
228    * - bound on the number of extensionality axioms generated in reconcile_model
229    */
230   uint32_t max_update_conflicts;
231   uint32_t max_extensionality;
232 
233   /*
234    * Main components
235    */
236   fun_vartable_t vtbl;
237   fun_edgetable_t etbl;
238   fun_queue_t queue;
239   diseq_stack_t dstack;
240 
241   /*
242    * Push/pop stack
243    */
244   fun_trail_stack_t trail_stack;
245 
246   /*
247    * Buffers
248    */
249   ivector_t aux_vector;
250   ivector_t lemma_vector;
251   pvector_t app_vector;
252 
253 
254   /*
255    * apps_ready = true if the app_vectors are available and normalized
256    * bases_ready = true if the bases are set
257    */
258   bool apps_ready;
259   bool bases_ready;
260 
261 
262   /*
263    * reconciled = true if the solver model agrees with the egraph
264    * - if this flag is true then we have to ensure that two variables
265    *   in different classes are mapped to different arrays in the model.
266    * - if this flag is false, then it's possible that two equal array
267    *   variables are in different egraph classes.
268    */
269   bool reconciled;
270 
271   /*
272    * Components used for interface equalities/model building
273    * - num_bases = number of connected components:
274    *   for every root variable x base[x] is between 0 and num_bases-1
275    * - base_value[i] encodes the default value assigned to every array
276    *   variable x such that base[x] = i.
277    * The base_value for i is either the label of an egraph term u or a special
278    * code (a negative integer). All variables with the same base have a type
279    * [domain --> sigma] and base_value[i] denotes some object of type sigma.
280    * (Note: all variables have the same type).
281    * - base_value[i] can be an egraph class of type sigma: in this
282    *   case. We set base_value[i] = label of some class (>= 0)
283    * - base_value[i] can be a fresh object of type sigma (i.e., a fresh
284    *   particle in the pstore. We encode this by setting base_value[i] = -(k+1)
285    *   for some non-negative index k.
286    *
287    * We use the following rules to assign base_values:
288    * - If sigma is infinite, we  can assign a fresh value to base_value[i]
289    *   (i.e., a value distinct from that of any other object in the egraph).
290    *   This is encoded by setting base[i] = - (i+1).
291    * - If sigma is finite, we search for distinct egraph terms (as many as we can)
292    *   and use them as base values. If there are not enough egraph terms, then
293    *   we create fresh_values (but we make sure the total number of elements
294    *   used as base values is not more than card(sigma)). The fresh values
295    *   are encoded as negative integers in the range [-p... -1] where
296    *   p = card(sigma).
297    *
298    * When building the model, we convert the base values to particles.
299    * For a finite type, sigma we must make sure that all base values with
300    * the same negative index are converted to the same fresh particle.
301    * To support this, we allocate a hash map if needed.
302    */
303   uint32_t num_bases;
304   int32_t *base_value;
305 
306   /*
307    * Model:
308    * - value[x] = map for variable x
309    * - base_map[i] = default map for all variables x such that base[x] = i
310    * Value and base_map are allocated only when the model is constructed
311    * For robustness, we store the size of these two arrays when they are allocated.
312    * We can then delete at any time without having to worry about changes in
313    * the number of variables or number of bases.
314    */
315   map_t **value;
316   map_t **base_map;
317   uint32_t value_size;
318   uint32_t base_map_size;
319 
320   /*
321    * Hash map used to convert integer codes to fresh particles (for finite types).
322    */
323   int_hmap2_t *fresh_hmap;
324 
325 } fun_solver_t;
326 
327 
328 
329 /*
330  * Default bounds
331  */
332 #define DEFAULT_MAX_UPDATE_CONFLICTS 20
333 #define DEFAULT_MAX_EXTENSIONALITY    1
334 
335 
336 
337 
338 /*********************
339  *  MAIN OPERATIONS  *
340  ********************/
341 
342 /*
343  * Initialize the function solver
344  * - core = attached smt_core
345  * - gates = gate manager for the core
346  * - egraph = attached egraph
347  * - ttbl = attached type table
348  */
349 extern void init_fun_solver(fun_solver_t *solver, smt_core_t *core,
350                             gate_manager_t *gates, egraph_t *egraph, type_table_t *ttbl);
351 
352 
353 /*
354  * Delete the solver
355  */
356 extern void delete_fun_solver(fun_solver_t *solver);
357 
358 
359 /*
360  * Get the control interface
361  */
362 extern th_ctrl_interface_t *fun_solver_ctrl_interface(fun_solver_t *solver);
363 
364 /*
365  * Get the egraph interfaces
366  */
367 extern th_egraph_interface_t *fun_solver_egraph_interface(fun_solver_t *solver);
368 extern fun_egraph_interface_t *fun_solver_fun_egraph_interface(fun_solver_t *solver);
369 
370 
371 
372 
373 /*******************************
374  *  INTERNALIZATION FUNCTIONS  *
375  ******************************/
376 
377 /*
378  * These functions are exported for testing only.
379  * They are used via the funsolver_interface.
380  */
381 
382 /*
383  * Create a new array variable.
384  * - tau = its type in the solver's internal type table
385  */
386 extern thvar_t fun_solver_create_var(fun_solver_t *solver, type_t tau);
387 
388 /*
389  * Attach egraph term t to array variable v
390  */
391 extern void fun_solver_attach_eterm(fun_solver_t *solver, thvar_t v, eterm_t t);
392 
393 /*
394  * Get the egraph term attached to v
395  */
fun_solver_eterm_of_var(fun_solver_t * solver,thvar_t v)396 static inline eterm_t fun_solver_eterm_of_var(fun_solver_t *solver, thvar_t v) {
397   assert(0 <= v && v < solver->vtbl.nvars);
398   return solver->vtbl.eterm[v];
399 }
400 
401 
402 
403 /***********************
404  *  CONTROL FUNCTIONS  *
405  **********************/
406 
407 /*
408  * These functions are used by the egraph. They are declared here for testing.
409  */
410 
411 /*
412  * Prepare for search after internalization.
413  */
414 extern void fun_solver_start_search(fun_solver_t *solver);
415 
416 /*
417  * Perform a round of propagations (do nothing)
418  */
419 extern bool fun_solver_propagate(fun_solver_t *solver);
420 
421 /*
422  * Final check
423  * - find necessary instances of the array axioms and add them to the egraph.
424  * - return FCHECK_SAT if no instance is generated, FCHECK_CONTINUE otherwise.
425  */
426 extern fcheck_code_t fun_solver_final_check(fun_solver_t *solver);
427 
428 
429 /*
430  * Start a new decision level
431  */
432 extern void fun_solver_increase_decision_level(fun_solver_t *solver);
433 
434 /*
435  * Backtrack to back level
436  */
437 extern void fun_solver_backtrack(fun_solver_t *solver, uint32_t back_level);
438 
439 /*
440  * Push/pop/reset
441  */
442 extern void fun_solver_push(fun_solver_t *solver);
443 extern void fun_solver_pop(fun_solver_t *solver);
444 extern void fun_solver_reset(fun_solver_t *solver);
445 
446 
447 
448 /********************************
449  *  EGRAPH INTERFACE FUNCTIONS  *
450  *******************************/
451 
452 /*
453  * Assert that x1 and x2 are equal
454  * - id = edge index to be used in a subsequent call to egraph_explain_term_eq
455  * - x1 and x2 are two variables attached to two egraph terms t1 and t2
456  * - this function is called when t1 and t2 become equal in the egraph
457  */
458 extern void fun_solver_assert_var_eq(fun_solver_t *solver, thvar_t x1, thvar_t x2, int32_t id);
459 
460 
461 /*
462  * Assert that x1 and x2 are distinct
463  * - x1 and x2 are two variables attached to two egraph terms t1 and t2
464  * - this function is called when t1 and t2 become distinct in the egraph
465  */
466 extern void fun_solver_assert_var_diseq(fun_solver_t *solver, thvar_t x1, thvar_t x2, composite_t *hint);
467 
468 
469 /*
470  * Assert that all variables a[0] ... a[n-1] are pairwise distinct
471  * - they are attached to egraph terms t[0] ... t[n-1]
472  * - the function is called when (distinct t[0] ... t[n-1]) is asserted in the egraph
473  */
474 extern void fun_solver_assert_var_distinct(fun_solver_t *solver, uint32_t n, thvar_t *a, composite_t *hint);
475 
476 
477 /*
478  * Check whether x1 and x2 are distinct at the base level
479  */
480 extern bool fun_solver_check_disequality(fun_solver_t *solver, thvar_t x1, thvar_t x2);
481 
482 
483 
484 
485 
486 /**********************
487  *  MODEL GENERATION  *
488  *********************/
489 
490 /*
491  * These functions are exported for testing only.
492  * The egraph uses the fun_egraph interface.
493  */
494 
495 /*
496  * Assign a map to all root variables
497  * - each map is of type map_t *
498  * - it's built as a map from abstract values to abstract values (particles)
499  * - all particles used in the construction must be created in store
500  */
501 extern void fun_solver_build_model(fun_solver_t *solver, pstore_t *store);
502 
503 
504 /*
505  * Return the map assigned to theory variable x
506  * - that's the map of root[x]
507  * - return NULL if the construction fails in some way
508  */
509 extern map_t *fun_solver_value_in_model(fun_solver_t *solver, thvar_t x);
510 
511 
512 /*
513  * Free all internal structures used in the model construction
514  */
515 extern void fun_solver_free_model(fun_solver_t *solver);
516 
517 
518 
519 
520 /***************************
521  *  SET THE SEARCH BOUNDS  *
522  **************************/
523 
524 /*
525  * Max number of extensionality instances (per call to reconcile model)
526  */
fun_solver_set_max_extensionality(fun_solver_t * solver,uint32_t n)527 static inline void fun_solver_set_max_extensionality(fun_solver_t *solver, uint32_t n) {
528   assert(n > 0);
529   solver->max_extensionality = n;
530 }
531 
fun_solver_get_max_extensionality(fun_solver_t * solver)532 static inline uint32_t fun_solver_get_max_extensionality(fun_solver_t *solver) {
533   return solver->max_extensionality;
534 }
535 
536 
537 /*
538  * Maximal number of update axiom (per call to final_check)
539  */
fun_solver_set_max_update_conflicts(fun_solver_t * solver,uint32_t n)540 static inline void fun_solver_set_max_update_conflicts(fun_solver_t *solver, uint32_t n) {
541   assert(n > 0);
542   solver->max_update_conflicts = n;
543 }
544 
fun_solver_get_max_update_conflicts(fun_solver_t * solver)545 static inline uint32_t fun_solver_get_max_update_conflicts(fun_solver_t *solver) {
546   return solver->max_update_conflicts;
547 }
548 
549 
550 
551 /****************
552  *  STATISTICS  *
553  ***************/
554 
555 /*
556  * Number of variables and edges
557  */
fun_solver_num_vars(fun_solver_t * solver)558 static inline uint32_t fun_solver_num_vars(fun_solver_t *solver) {
559   return solver->stats.num_init_vars;
560 }
561 
fun_solver_num_edges(fun_solver_t * solver)562 static inline uint32_t fun_solver_num_edges(fun_solver_t *solver) {
563   return solver->stats.num_init_edges;
564 }
565 
566 /*
567  * Number of instances of each axiom
568  */
fun_solver_num_update1_axioms(fun_solver_t * solver)569 static inline uint32_t fun_solver_num_update1_axioms(fun_solver_t *solver) {
570   return solver->stats.num_update_axiom1;
571 }
572 
fun_solver_num_update2_axioms(fun_solver_t * solver)573 static inline uint32_t fun_solver_num_update2_axioms(fun_solver_t *solver) {
574   return solver->stats.num_update_axiom2;
575 }
576 
fun_solver_num_extensionality_axioms(fun_solver_t * solver)577 static inline uint32_t fun_solver_num_extensionality_axioms(fun_solver_t *solver) {
578   return solver->stats.num_extensionality_axiom;
579 }
580 
581 
582 /********************************
583  *  GARBAGE COLLECTION SUPPORT  *
584  *******************************/
585 
586 /*
587  * Mark all types used by solver (protect them from deletion in type_table_gc)
588  * - scan the variable table and mark every type in table->type[x]
589  */
590 extern void fun_solver_gc_mark(fun_solver_t *solver);
591 
592 
593 
594 #endif /* __FUN_SOLVER_H */
595