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