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  * INCREMENTAL FORM OF THE FLOYD-WARSHALL ALGORITHM,
21  * ONLY FOR REAL-DIFFERENCE LOGIC.
22  */
23 
24 /*
25  * Most of the algorithms and data structures are copied from
26  * idl_floyd_warshall. The main difference is the use of
27  * rational constants as edge labels.
28  */
29 
30 /*
31  * Graph representation
32  * - edges are stored in a stack (added and removed in FIFO order)
33  * - each edge has source and destination vertices and a cost of the form (a + k delta)
34  * - edges are indexed from 0 to n-1
35  * - edge 0 is not really an edge. It's used as a mark.
36  *
37  * Matrix:
38  * - for each pair of vertices (x, y), we maintain the distance from x to y and
39  *   edge index M[x,y].id
40  * - for each vertex x, M[x, x].id = 0 and M[x, x].dist = 0
41  * - if there's no path from x to y, we set M[x, y] = null_edge (-1)
42  * - if there's a path from x to y then M[x, y].id is an index between 1 and n-1
43  * Invariant: a
44  * - if M[x, y].id = i and edge i is from u to v then
45  *   0 <= M[x, u].id < i and 0 <= M[u, y].id < i
46  *
47  * - Based on this, we can define the path from x to y represented by M
48  *     path(x, y) =
49  *       if x = y then empty-path
50  *       else (concat path(x, u)  i path(v, y))
51  *    where i = M[x, y].id and that edge is from u to v.
52  *
53  *   this recursion is well-founded by the Main invariant,
54  *
55  *   Then the length of path(x, y) can also be computed recursively:
56  *     len(x, y) = if x = y then 0 else len(x, u) + c(i) + len(v, y)
57  *   where i = M[x, y].m_edge_id and edge i has cost c(i) and goes from u to v.
58  *
59  *   That length is stored in M[x, y].dist
60  *
61  * - The data structure is constructed so that path(x, y) is a shortest
62  *   path from x to y in the current graph.
63  *   M[x, y].m_val is then the distance from x to y.
64  *
65  * The graph encodes the constraints asserted so far:
66  * - an edge from x to y of cost d encodes the assertion (x - y <= d)
67  * - if there's a path of length D from x to y, then the assertions imply (x - y <= D)
68  */
69 
70 
71 #ifndef __RDL_FLOYD_WARSHALL_H
72 #define __RDL_FLOYD_WARSHALL_H
73 
74 #include <stdint.h>
75 #include <stdbool.h>
76 #include <stddef.h>
77 #include <setjmp.h>
78 
79 #include "context/context_types.h"
80 #include "solvers/cdcl/smt_core.h"
81 #include "solvers/floyd_warshall/dl_vartable.h"
82 #include "terms/poly_buffer.h"
83 #include "terms/rationals.h"
84 #include "utils/arena.h"
85 #include "utils/bitvectors.h"
86 #include "utils/int_hash_tables.h"
87 #include "utils/int_vectors.h"
88 
89 
90 
91 /***************
92  *  CONSTANTS  *
93  **************/
94 
95 /*
96  * The edges in the graph are labeled by a rational
97  * constant a/b + an optional infinitesimal delta.
98  * The delta is used for strict inequalities:
99  * - the constraint x - y <= a/b is encoded by an
100  *   edge x ---> y with label a/b
101  * - the constraint x - y < a/b is encoded by an
102  *   edge x ---> y with label a/b - delta.
103  *   (i.e., it's translated to x - y <= a/b - delta)
104  *
105  * Then the path from x ----> z has a length of the form
106  *   a/b + k.delta (where k is a negative integer).
107  * The length is stored in the following structure:
108  */
109 typedef struct rdl_const_s {
110   rational_t q;
111   int32_t delta;
112 } rdl_const_t;
113 
114 
115 
116 
117 
118 /***********
119  *  GRAPH  *
120  **********/
121 
122 /*
123  * Edge indices = signed 32 bit integers
124  * - null_rdl_edge = -1 is a marker
125  * Vertex index = signed 32 bit integers
126  * - null_rdl_vertex = -1
127  */
128 enum {
129   null_rdl_edge = -1,
130   null_rdl_vertex = -1,
131 };
132 
133 
134 /*
135  * Edge descriptor: don't need the cost.
136  */
137 typedef struct rdl_edge_s {
138   int32_t source;
139   int32_t target;
140 } rdl_edge_t;
141 
142 
143 /*
144  * Stack of edges + a literal for each edge
145  * - for edge i: lit[i] == true_literal if i was asserted as an axiom
146  * - otherwise lit[i] = a literal l in the smt_core, such that l is true
147  *   and l is attached to an rdl atom
148  */
149 typedef struct rdl_edge_stack_s {
150   uint32_t size;
151   uint32_t top;
152   rdl_edge_t *data;
153   literal_t *lit;
154 } rdl_edge_stack_t;
155 
156 #define DEFAULT_RDL_EDGE_STACK_SIZE 100
157 #define MAX_RDL_EDGE_STACK_SIZE (UINT32_MAX/sizeof(rdl_edge_t))
158 
159 
160 /*
161  * Cell in the matrix
162  * - cell[x, y].id = largest edge index along the shortest path from x to y
163  *   (null_rdl_edge if there's no path from x to y)
164  * - cell[x, y].dist = length of the shortest path from x to y
165  */
166 typedef struct rdl_cell_s {
167   int32_t id;
168   rdl_const_t dist;
169 } rdl_cell_t;
170 
171 
172 /*
173  * Matrix:
174  * - data is an array of (size * size) cells
175  * - the matrix itself is stored in data[0 ... dim*dim-1]
176  */
177 typedef struct rdl_matrix_s {
178   uint32_t size;
179   uint32_t dim;
180   rdl_cell_t *data;
181 } rdl_matrix_t;
182 
183 
184 /*
185  * Maximal dimension: we want (dim * x + y) to fit a 32bit unsigned integer
186  * where 0 <= x < dim and 0 <= y < dim
187  */
188 #define MAX_RDL_MATRIX_DIMENSION 65535
189 
190 
191 /*
192  * Stack for restoring cells in the matrix
193  */
194 typedef struct rdl_saved_cell_s {
195   uint32_t index;   // cell index: M[x, y] has index (nvertices * x + y)
196   rdl_cell_t saved; // content to restore
197 } rdl_saved_cell_t;
198 
199 typedef struct rdl_cell_stack_s {
200   uint32_t size;
201   uint32_t top;
202   rdl_saved_cell_t *data;
203 } rdl_cell_stack_t;
204 
205 
206 #define DEFAULT_RDL_CELL_STACK_SIZE 100
207 #define MAX_RDL_CELL_STACK_SIZE (UINT32_MAX/sizeof(rdl_saved_cell_t))
208 
209 
210 /*
211  * Graph
212  */
213 typedef struct rdl_graph_s {
214   rdl_matrix_t matrix;
215   rdl_edge_stack_t edges;
216   rdl_cell_stack_t cstack;
217   ivector_t    buffer;
218   rdl_const_t  c0;      // auxiliary variables for internal computations
219 } rdl_graph_t;
220 
221 
222 
223 /***********
224  *  ATOMS  *
225  **********/
226 
227 /*
228  * Each atom has an index i (in the global atom table)
229  * - the atom includes <source vertex, target vertex, cost, boolean variable>
230  * - the atom is (source - target <= cost) so cost is a rational
231  * - if atom->boolvar = v then the atom index is attached to v in the smt_core
232  *   (Hack: this is done by converting the int32_t index to void*).
233  */
234 typedef struct rdl_atom_s {
235   int32_t source;
236   int32_t target;
237   rational_t cost;
238   bvar_t boolvar;
239 } rdl_atom_t;
240 
241 
242 /*
243  * Conversion from atom index to void* (and back)
244  * TODO: add a 2bit tag to make this consistent with the egraph
245  * tagging of atoms??
246  */
rdl_index2atom(int32_t i)247 static inline void *rdl_index2atom(int32_t i) {
248   return (void *) ((size_t) i);
249 }
250 
rdl_atom2index(void * a)251 static inline int32_t rdl_atom2index(void *a) {
252   return (int32_t) ((size_t) a);
253 }
254 
255 
256 /*
257  * Record for doubly-linked list of free atoms
258  */
259 typedef struct rdl_listelem_s {
260   int32_t pre;
261   int32_t next;
262 } rdl_listelem_t;
263 
264 
265 /*
266  * Atom table: current set of atoms have indices between 0 and natoms-1
267  * For theory propagation, we maintain a list of free atoms
268  * (all atoms not assigned a truth value yet)
269  * - size = size of the atoms and next array
270  * - mark = one bit per atom
271  *   mark = 1 means that the atom is assigned (present in the atom stack)
272  *   mark = 0 means that the atom is unassigned (present in the free list)
273  * - free_list is an array of n+1 list elements, indexed from -1 to n-1
274  */
275 typedef struct rdl_atbl_s {
276   uint32_t size;
277   uint32_t natoms;
278   rdl_atom_t *atoms;
279   rdl_listelem_t *free_list;
280   byte_t *mark;
281 } rdl_atbl_t;
282 
283 
284 /*
285  * Atom stack & propagation queue:
286  * - for all assigned atom, the queue contains its index + a sign bit
287  * - this follows our usual encoding of index+sign in 32bit:
288  *     sign bit = lowest order bit of data[k]
289  *     if sign bit = 0, then atom k is true
290  *     if sign bit = 1, then atom k is false
291  * - every atom in the stack has its mark bit set to 1 in the atom table
292  * - the propagation queue consists of the atoms in
293  *   data[prop_ptr ... top -1]
294  */
295 typedef struct rdl_astack_s {
296   uint32_t size;
297   uint32_t top;
298   uint32_t prop_ptr;
299   int32_t *data;
300 } rdl_astack_t;
301 
302 
303 
304 #define DEFAULT_RDL_ATBL_SIZE 100
305 #define MAX_RDL_ATBL_SIZE (UINT32_MAX/sizeof(rdl_atom_t))
306 
307 #define DEFAULT_RDL_ASTACK_SIZE 100
308 #define MAX_RDL_ASTACK_SIZE (UINT32_MAX/sizeof(int32_t))
309 
310 
311 /*
312  * Maximal number of atoms: same as MAX_RDL_ATBL_SIZE
313  * (so any atom index fits in 30 bits).
314  */
315 #define MAX_RDL_ATOMS MAX_RDL_ATBL_SIZE
316 
317 
318 
319 /****************
320  *  UNDO STACK  *
321  ***************/
322 
323 /*
324  * For backtracking: on entry to each decision level k we store:
325  * - edge_id = id of the first edge of level k
326  *   for level 0, edge_id must be -1.
327  *   for level k>0, edge_id is the number of edges in the graph
328  *   when the level k was entered.
329  * - top of cell stack, top of atom stack
330  */
331 typedef struct rdl_undo_record_s {
332   int32_t edge_id;
333   uint32_t nsaved;
334   uint32_t natoms;
335 } rdl_undo_record_t;
336 
337 typedef struct rdl_undo_stack_s {
338   uint32_t size;
339   uint32_t top;
340   rdl_undo_record_t *data;
341 } rdl_undo_stack_t;
342 
343 #define DEFAULT_RDL_UNDO_STACK_SIZE 100
344 #define MAX_RDL_UNDO_STACK_SIZE (UINT32_MAX/sizeof(rdl_undo_record_t))
345 
346 
347 
348 
349 /******************
350  * PUSH/POP STACK *
351  *****************/
352 
353 /*
354  * For each base level, we keep the number of vertices and atoms
355  * on entry to that level.
356  */
357 typedef struct rdl_trail_s {
358   uint32_t nvertices;
359   uint32_t natoms;
360 } rdl_trail_t;
361 
362 typedef struct rdl_trail_stack_s {
363   uint32_t size;
364   uint32_t top;
365   rdl_trail_t *data;
366 } rdl_trail_stack_t;
367 
368 #define DEFAULT_RDL_TRAIL_SIZE  20
369 #define MAX_RDL_TRAIL_SIZE (UINT32_MAX/sizeof(rdl_trail_t))
370 
371 
372 
373 
374 /***************************
375  *  FLOYD-WARHSALL SOLVER  *
376  **************************/
377 
378 typedef struct rdl_solver_s {
379   /*
380    * Attached smt core and gate manager
381    */
382   smt_core_t *core;
383   gate_manager_t *gate_manager;
384 
385   /*
386    * Base level and decision level (same interpretation as in smt_core)
387    */
388   uint32_t base_level;
389   uint32_t decision_level;
390 
391   /*
392    * Unsat flag: set to true if asserted axioms are inconsistent
393    */
394   bool unsat_before_search;
395 
396   /*
397    * Variable table
398    * - every variable (used by the context) is mapped to a
399    *   difference logic triple (x - y + c) where x and y are vertices
400    *   in the graph.
401    */
402   dl_vartable_t vtbl;
403 
404   /*
405    * Graph
406    */
407   uint32_t nvertices;  // number of vertices
408   int32_t zero_vertex; // index of the zero vertex (or null)
409   rdl_graph_t graph;
410 
411   /*
412    * Atom table and stack
413    */
414   rdl_atbl_t atoms;
415   rdl_astack_t astack;
416 
417   /*
418    * Backtracking stack
419    */
420   rdl_undo_stack_t stack;
421 
422   /*
423    * Push/pop stack
424    */
425   rdl_trail_stack_t trail_stack;
426 
427   /*
428    * Auxiliary buffers and data structures
429    */
430   int_htbl_t htbl;       // for hash-consing of atoms
431   arena_t arena;         // for storing explanations of implied atoms
432   ivector_t expl_buffer; // for constructing explanations
433   ivector_t aux_vector;  // general-purpose vector
434   rdl_const_t c1;        // for internal use
435   rational_t q;          // for internalization
436 
437   dl_triple_t triple;     // for variable construction
438   poly_buffer_t buffer;   // for internal polynomial operations
439 
440   /*
441    * Structures used for building a model
442    * - value = rational value for each vertex. The array is allocated when needed.
443    * - epsilon = safe value for delta
444    * - aux = auxiliary rational buffer
445    */
446   rational_t epsilon;
447   rational_t factor;
448   rational_t aux;
449   rational_t aux2;
450   rational_t *value;
451 
452   /*
453    * Jump buffer for exception handling during internalization
454    */
455   jmp_buf *env;
456 } rdl_solver_t;
457 
458 
459 
460 /*
461  * Maximal number of vertices: same as maximal matrix dimension
462  */
463 #define MAX_RDL_VERTICES MAX_RDL_MATRIX_DIMENSION
464 
465 #define DEFAULT_RDL_BUFFER_SIZE 20
466 
467 
468 
469 
470 /*********************
471  *  MAIN OPERATIONS  *
472  ********************/
473 
474 /*
475  * Initialize an rdl solver
476  * - core = the attached smt-core object
477  * - gates = the attached gate manager
478  */
479 extern void init_rdl_solver(rdl_solver_t *solver, smt_core_t *core, gate_manager_t *gates);
480 
481 
482 /*
483  * Attach a jump buffer for exceptions
484  */
485 extern void rdl_solver_init_jmpbuf(rdl_solver_t *solver, jmp_buf *buffer);
486 
487 
488 /*
489  * Delete: free all allocated memory
490  */
491 extern void delete_rdl_solver(rdl_solver_t *solver);
492 
493 
494 /*
495  * Get interface descriptors to attach solver to a core
496  */
497 extern th_ctrl_interface_t *rdl_ctrl_interface(rdl_solver_t *solver);
498 extern th_smt_interface_t  *rdl_smt_interface(rdl_solver_t *solver);
499 
500 
501 /*
502  * Get interface descriptor for the internalization functions.
503  */
504 extern arith_interface_t *rdl_arith_interface(rdl_solver_t *solver);
505 
506 
507 
508 /******************************
509  *  VERTEX AND ATOM CREATION  *
510  *****************************/
511 
512 /*
513  * Create a new theory variable = a new vertex
514  * - return null_rdl_vertex if there are too many vertices
515  */
516 extern int32_t rdl_new_vertex(rdl_solver_t *solver);
517 
518 
519 /*
520  * Return the zero_vertex (create it if needed)
521  * - return null_rdl_vertex if the vertex can't be created
522  *   (i.e. too many vertices)
523  */
524 extern int32_t rdl_zero_vertex(rdl_solver_t *solver);
525 
526 
527 /*
528  * Create the atom (x - y <= c) and return the corresponding literal
529  * - x and y must be vertices in the solver
530  * - if x - y <= c simplifies to true or false (given the current graph)
531  *   return true_literal or false_literal
532  */
533 extern literal_t rdl_make_atom(rdl_solver_t *solver, int32_t x, int32_t y, rational_t *c);
534 
535 
536 /*
537  * Assert (x - y <= c) or (x - y < c) as an axiom
538  * - x and y must be vertices in solver
539  * - the solver must be at base level (i.e., solver->decision_level == solver->base_level)
540  * - strict true means  assert (x - y < c)
541  *   strict false means assert (x - y <= c)
542  *
543  * - this adds an edge from x to y with cost c to the graph
544  * - if the edge causes a conflict, then solver->unsat_before_search is set to true
545  */
546 extern void rdl_add_axiom_edge(rdl_solver_t *solver, int32_t x, int32_t y, rational_t *c, bool strict);
547 
548 
549 /*
550  * Assert (x - y == d) as an axiom:
551  * - add edge x ---> y with cost d   (x - y <= d)
552  *   and edge y ---> x with cost -d  (y - x <= -d)
553  */
554 extern void rdl_add_axiom_eq(rdl_solver_t *solver, int32_t x, int32_t y, rational_t *d);
555 
556 
557 
558 
559 
560 /*******************************
561  *  INTERNALIZATION FUNCTIONS  *
562  ******************************/
563 
564 /*
565  * These functions are used by the context to convert terms to
566  * variables and literals. They form the arith_interface descriptor.
567  */
568 
569 /*
570  * Create a new theory variable
571  * - is_int indicates whether the variable should be an integer,
572  *   so it should always be true for this solver.
573  * - raise exception NOT_RDL if is_int is true
574  * - raise exception TOO_MANY_VARS if we can't create a new vertex
575  *   for that variable
576  */
577 extern thvar_t rdl_create_var(rdl_solver_t *solver, bool is_int);
578 
579 
580 /*
581  * Create a variable that represents the constant q
582  */
583 extern thvar_t rdl_create_const(rdl_solver_t *solver, rational_t *q);
584 
585 
586 /*
587  * Create a variable for a polynomial p, with variables defined by map:
588  * - p is of the form a_0 t_0 + ... + a_n t_n where t_0, ..., t_n
589  *   are arithmetic terms.
590  * - map[i] is the theory variable x_i for t_i
591  *   (with map[0] = null_thvar if t_0 is const_idx)
592  * - the function constructs a variable equal to a_0 x_0 + ... + a_n x_n
593  *
594  * - fails if a_0 x_0 + ... + a_n x_n is not an RDL polynomial
595  *   (i.e., not of the form x - y + c)
596  */
597 extern thvar_t rdl_create_poly(rdl_solver_t *solver, polynomial_t *p, thvar_t *map);
598 
599 
600 /*
601  * Internalization for a product: always fails with NOT_RDL exception
602  */
603 extern thvar_t rdl_create_pprod(rdl_solver_t *solver, pprod_t *p, thvar_t *map);
604 
605 
606 /*
607  * Create the atom x = 0
608  */
609 extern literal_t rdl_create_eq_atom(rdl_solver_t *solver, thvar_t x);
610 
611 
612 /*
613  * Create the atom x >= 0
614  */
615 extern literal_t rdl_create_ge_atom(rdl_solver_t *solver, thvar_t x);
616 
617 
618 /*
619  * Create the atom p = 0
620  * - map is used as in create_poly
621  * - fails if p is not of the form (x - y + c)
622  */
623 extern literal_t rdl_create_poly_eq_atom(rdl_solver_t *solver, polynomial_t *p, thvar_t *map);
624 
625 
626 /*
627  * Create the atom p >= 0
628  * - map is used as in create_poly
629  * - fails if p is not of the form (x - y + c)
630  */
631 extern literal_t rdl_create_poly_ge_atom(rdl_solver_t *solver, polynomial_t *p, thvar_t *map);
632 
633 
634 /*
635  * Create the atom (x = y)
636  */
637 extern literal_t rdl_create_vareq_atom(rdl_solver_t *solver, thvar_t x, thvar_t y);
638 
639 
640 /*
641  * Assert the top-level constraint (x == 0) or (x != 0)
642  * - if tt is true: assert x == 0
643  * - if tt is false: assert x != 0
644  */
645 extern void rdl_assert_eq_axiom(rdl_solver_t *solver, thvar_t x, bool tt);
646 
647 
648 /*
649  * Assert the top-level constraint (x >= 0) or (x < 0)
650  * - if tt is true: assert (x >= 0)
651  * - if tt is false: assert (x < 0)
652  */
653 extern void rdl_assert_ge_axiom(rdl_solver_t *solver, thvar_t x, bool tt);
654 
655 
656 /*
657  * Assert the top-level constraint (p == 0) or (p != 0)
658  * - map is as in create_poly
659  * - if tt is true: assert p == 0
660  * - if tt is false: assert p != 0
661  * - fails if p is not of the form (x - y + c)
662  */
663 extern void rdl_assert_poly_eq_axiom(rdl_solver_t *solver, polynomial_t *p, thvar_t *map, bool tt);
664 
665 
666 /*
667  * Assert the top-level constraint (p >= 0) or (p < 0)
668  * - map is as in create_poly
669  * - if tt is true: assert (p >= 0)
670  * - if tt is false: assert (p < 0)
671  * - fails if p is not of the form (x - y + c)
672  */
673 extern void rdl_assert_poly_ge_axiom(rdl_solver_t *solver, polynomial_t *p, thvar_t *map, bool tt);
674 
675 
676 /*
677  * Assert (x == y) or (x != y)
678  * - if tt is true: assert (x == y)
679  * - if tt is false: assert (x != y)
680  */
681 extern void rdl_assert_vareq_axiom(rdl_solver_t *solver, thvar_t x, thvar_t y, bool tt);
682 
683 
684 /*
685  * Assert (c ==> x == y)
686  */
687 extern void rdl_assert_cond_vareq_axiom(rdl_solver_t *solver, literal_t c, thvar_t x, thvar_t y);
688 
689 
690 /*
691  * Assert (c[0] \/ ... \/ c[n-1] \/ x == y)
692  */
693 extern void rdl_assert_clause_vareq_axiom(rdl_solver_t *solver, uint32_t n, literal_t *c, thvar_t x, thvar_t y);
694 
695 
696 
697 
698 /***********************
699  *  SOLVER FUNCTIONS   *
700  **********************/
701 
702 /*
703  * These functions are used by the core. They form the th_ctrl and
704  * th_smt interfaces.
705  */
706 
707 /*
708  * Start the search
709  */
710 extern void rdl_start_search(rdl_solver_t *solver);
711 
712 /*
713  * Increase the decision level/backtrack
714  */
715 extern void rdl_increase_decision_level(rdl_solver_t *solver);
716 extern void rdl_backtrack(rdl_solver_t *solver, uint32_t back_level);
717 
718 
719 /*
720  * Push/pop/reset
721  */
722 extern void rdl_push(rdl_solver_t *solver);
723 extern void rdl_pop(rdl_solver_t *solver);
724 extern void rdl_reset(rdl_solver_t *solver);
725 
726 
727 /*
728  * Push an assertion into the queue
729  * - atom is the index of an rdl_atom with boolean variable v
730  * - l is either pos_lit(v) or neg_lit(v)
731  * - if l == pos_lit(v), the atom is asserted true, otherwise it's false
732  * - return false if a conflict is detected
733  *   return true otherwise
734  */
735 extern bool rdl_assert_atom(rdl_solver_t *solver, void *atom, literal_t l);
736 
737 
738 /*
739  * Propagate: process the assertion queue
740  * - return false if a conflict is detected
741  * - return true otherwise.
742  */
743 extern bool rdl_propagate(rdl_solver_t *solver);
744 
745 /*
746  * Support for theory-branching heuristic
747  * - evaluate atom attached to l in the current model
748  * - the result is either l or (not l)
749  * - if atom is true, return pos_lit(var_of(l))
750  * - if atom is false, return neg_lit(var_of(l))
751  */
752 extern literal_t rdl_select_polarity(rdl_solver_t *solver, void *atom, literal_t l);
753 
754 
755 /*
756  * Final check: do nothing and return SAT
757  */
758 extern fcheck_code_t rdl_final_check(rdl_solver_t *solver);
759 
760 
761 
762 /*
763  * Explain why literal l is true.
764  * - l is a literal set true by solver in the core (via implied_literal)
765  * - expl is the explanation object given to implied_literal,
766  *   (expl is an array of literals terminated by null_literal).
767  * - expl must be expanded into a conjunction of literals l_0 ... l_k
768  *   such that (l_0 and ... and l_k) implies l
769  * - literals l_0 ... l_k that must be stored into v
770  */
771 extern void rdl_expand_explanation(rdl_solver_t *solver, literal_t l, literal_t *expl, ivector_t *v);
772 
773 
774 
775 
776 /************************
777  *  MODEL CONSTRUCTION  *
778  ***********************/
779 
780 /*
781  * Build a model: assign an integer value to all vertices
782  * - the zero vertex has value 0 (if it exists)
783  * - the solver must be in a consistent state
784  * - the mapping is stored internally in solver->value
785  */
786 extern void rdl_build_model(rdl_solver_t *solver);
787 
788 
789 /*
790  * Return (a pointer to) the value of edge x in the model
791  */
rdl_vertex_value(rdl_solver_t * solver,int32_t x)792 static inline rational_t *rdl_vertex_value(rdl_solver_t *solver, int32_t x) {
793   assert(solver->value != NULL && 0 <= x && x < solver->nvertices);
794   return solver->value + x;
795 }
796 
797 
798 /*
799  * Value of variable v in the model
800  * - copy the value into q and return true
801  */
802 extern bool rdl_value_in_model(rdl_solver_t *solver, thvar_t v, rational_t *q);
803 
804 
805 
806 /*
807  * Free the model
808  */
809 extern void rdl_free_model(rdl_solver_t *solver);
810 
811 
812 /*****************
813  *  STATISTICS   *
814  ****************/
815 
816 // we don't maintain any search statistics
rdl_num_vars(rdl_solver_t * solver)817 static inline uint32_t rdl_num_vars(rdl_solver_t *solver) {
818   return solver->vtbl.nvars;
819 }
820 
rdl_num_atoms(rdl_solver_t * solver)821 static inline uint32_t rdl_num_atoms(rdl_solver_t *solver) {
822   return solver->atoms.natoms;
823 }
824 
rdl_num_vertices(rdl_solver_t * solver)825 static inline uint32_t rdl_num_vertices(rdl_solver_t *solver) {
826   return solver->nvertices;
827 }
828 
829 
830 
831 
832 
833 #endif /* __RDL_FLOYD_WARSHALL_H */
834