• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SRI-CSL / yices2 / 12367760548

17 Dec 2024 06:41AM UTC coverage: 65.285% (-0.6%) from 65.92%
12367760548

push

github

web-flow
Fixes GitHub coverage issue (#544)

* Update action.yml

* Update action.yml

81020 of 124102 relevant lines covered (65.29%)

1509382.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/solvers/cdcl/new_sat_solver.h
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
 * STAND-ALONE SAT SOLVER
21
 */
22

23
/*
24
 * This is a new implementation based on Hadrien Barral's work.
25
 * Hadrien's original code is in sat_solver.h/sat_solver.c.
26
 * This is a cleanup but similar implementation.
27
 */
28

29
#ifndef __NEW_SAT_SOLVER_H
30
#define __NEW_SAT_SOLVER_H
31

32
#include <stdint.h>
33
#include <stdio.h>
34
#include <stdbool.h>
35
#include <assert.h>
36

37
#include "solvers/cdcl/smt_core_base_types.h"
38
#include "solvers/cdcl/new_gates.h"
39
#include "utils/tag_map.h"
40

41

42
/****************
43
 *  UTILITIES   *
44
 ***************/
45

46
/*
47
 * We use arrays of 32bit integers in several places.
48
 * The following macro is intended to define the maximal
49
 * number of elements in such an array (assuming we store the
50
 * array size as an unsigned 32bit integer).
51
 *
52
 * Not sure this definition is portable, but it should work
53
 * with gcc and clang.
54
 */
55
#if (SIZE_MAX/4) < UINT32_MAX
56
#define MAX_ARRAY32_SIZE (SIZE_MAX/4)
57
#else
58
#define MAX_ARRAY32_SIZE UINT32_MAX
59
#endif
60

61

62

63
/********************
64
 *  INTEGER VECTOR  *
65
 *******************/
66

67
/*
68
 * This is a resizable array of unsigned integers
69
 * - capacity = maximal size
70
 * - size = current size
71
 * - data = array
72
 */
73
typedef struct vector_s {
74
  uint32_t *data;
75
  uint32_t capacity;
76
  uint32_t size;
77
} vector_t;
78

79
// Default and maximal size
80
#define DEF_VECTOR_SIZE 64
81
#define MAX_VECTOR_SIZE (UINT32_MAX/sizeof(uint32_t))
82

83

84

85
/*******************
86
 *  INTEGER QUEUE  *
87
 ******************/
88

89
/*
90
 * This is a circular buffer:
91
 * - data = array to store the integers
92
 * - capacity = size of this array
93
 * - head, tail = indices between 0 and capacity - 1
94
 *
95
 * If head = tail, the queue is empty.
96
 * If head < tail, the queue's content is data[head ... tail - 1]
97
 * If head > tail, the queue's content is data[head, ... size - 1]
98
 * plus data[0 ... tail-1].
99
 */
100
typedef struct queue_s {
101
  uint32_t *data;
102
  uint32_t capacity;
103
  uint32_t head;
104
  uint32_t tail;
105
} queue_t;
106

107
// Default and maximal size
108
#define DEF_QUEUE_SIZE 64
109
#define MAX_QUEUE_SIZE (UINT32_MAX/sizeof(literal_t))
110

111

112

113
/*********************************************
114
 *  STACK FOR DEPTH-FIRST GRAPH EXPLORATION  *
115
 ********************************************/
116

117
/*
118
 * This is used in two places.
119
 *
120
 * 1) Minimization of the learned clauses after a conflict
121
 *
122
 * The implication graph is formed by the true literals.
123
 * There's an edge in this graph from l0 to l1 if l1 is implied by
124
 * a clause that contains l0:
125
 * - either l1 is implied by the clause { l1, ~l0 }
126
 * - or l1 is implied by a clause of the form { l1, ... ~l0, ... }
127
 *
128
 * To explore this graph backward, we use a stack. Each element of
129
 * the stack contains a boolean variable var + an index i.
130
 * - the var is an assigned variable and represents a literal l1 in the graph
131
 * - the index i is the index of the next antecedents of l1 to explore.
132
 *
133
 * If l1 is implied by a binary clause { l1, ~l0 } then it has one antecedent
134
 * (of index 0). If l1 is implied by a clause with n literals then if has
135
 * n-1 antecedents, indexed from 0 to n-2.
136
 *
137
 * 2) Search for strongly connected components in a the binary implication
138
 * graph.
139
 *
140
 * This graph is formed by the binary clauses in the problem. Given a binary
141
 * clause {l0, l1}, there's an edge from ~l0 to l1 and from ~l1 to l0. To
142
 * explore this graph, we use the watch vectors: watch[l0] contains all the
143
 * clauses of the form {l0, l1} (i.e., the successors of ~l0 in the binary
144
 * implication graph). To enumerate the successors of ~l0, we store an index
145
 * i in the vector watch[l0].
146
 */
147
typedef struct gstack_elem_s {
148
  uint32_t vertex;
149
  uint32_t index;
150
} gstack_elem_t;
151

152
typedef struct gstack_s {
153
  gstack_elem_t *data;
154
  uint32_t top;
155
  uint32_t size;
156
} gstack_t;
157

158
#define DEF_GSTACK_SIZE 20
159
#define MAX_GSTACK_SIZE (UINT32_MAX/sizeof(gstack_elem_t))
160

161

162

163
/*****************
164
 *  CLAUSE POOL  *
165
 ****************/
166

167
/*
168
 * Clauses are stored in a big array of integers.
169
 *
170
 * Each clause consists of
171
 * - header: clause length + auxiliary data
172
 * - for a learned clause, the auxiliary data is the clause's activity.
173
 * - for a problem clause, the auxiliary data is a bitmask to accelerate
174
 *   subsumption checks.
175
 * - the rest is an array of literals
176
 * - the first two elements of this array are the watched literals.
177
 *
178
 * The pool is divided into three regions:
179
 * - data[0 ... learned-1]           contains the problem clauses
180
 * - data[learned_base ... size - 1] contains the learned clauses
181
 * - data[size ... capacity-1]       unused
182
 *
183
 * Each clause is identified by an index i:
184
 * - data[i]   is the clause length
185
 * - data[i+1] is the auxiliary data
186
 * - data[i+2] is the first watched literal
187
 * - data[i+3] is the second watched literal
188
 * - data[i+4 ... i+n+2] = rest of the clause = array of n-2 literals
189
 *   where n = data[i] = clause length.
190
 *
191
 * Each clause starts at an index that's a multiple of 4. This ensures
192
 * that header + two watched literals are in the same cache line.
193
 *
194
 * If a clause starts at index i, the next clause starts
195
 * at index j = ((i + data[i] + 2 + 3) & ~3). That's i + length of the
196
 * clause + size of the header rounded up to the next multiple of 4.
197
 *
198
 * Simplification/in-processing may delete or shrink a clause. This
199
 * introduces gaps in the data array.  To deal with these gaps, we add
200
 * padding blocks. A padding block at index i is a block of unused
201
 * elements in the array.  Its length is a multiple of four.  The
202
 * first two elements of a padding block are as follows:
203
 * - data[i] = 0
204
 * - data[i+1] = length of the padding block.
205
 * This distinguishes padding blocks from clauses since a clause starts with
206
 * data[i] >= 2.
207
 *
208
 * Some operations require marking clauses. We do this by setting the high-order
209
 * bit of the length field to 1. This is safe as a clause can't have more than
210
 * MAX_VARIABLES literals and that's less than 2^31.
211
 */
212

213
// clause structure
214
typedef struct nclause_s {
215
  uint32_t len;
216
  union {
217
    uint32_t d;
218
    float f;
219
  } aux;
220
  literal_t c[0]; // real size is equal to len
221
} nclause_t;
222

223
/*
224
 * Pool structure:
225
 * - capacity = length of the array data
226
 * - invariants:
227
 *     learned <= size <= capacity
228
 *     available = capacity - size
229
 *     padding = number of padding cells
230
 *     learned, size, capacity, available, padding are all multiple of four.
231
 * - counters: number of clauses/literals
232
 */
233
typedef struct clause_pool_s {
234
  uint32_t *data;
235
  uint32_t learned;
236
  uint32_t size;
237
  uint32_t capacity;
238
  uint32_t available;
239
  uint32_t padding;
240
  //  statistics
241
  uint32_t num_prob_clauses;      // number of problem clauses
242
  uint32_t num_prob_literals;     // sum of the length of these clauses
243
  uint32_t num_learned_clauses;   // number of learned clauses
244
  uint32_t num_learned_literals;  // sum of the length of these clauses
245
} clause_pool_t;
246

247

248
/*
249
 * Initial and maximal capacity of a pool
250
 * - initial size = 1Mb
251
 */
252
#define DEF_CLAUSE_POOL_CAPACITY 262144
253
#define MAX_CLAUSE_POOL_CAPACITY (MAX_ARRAY32_SIZE & ~3)
254

255

256
// clause index
257
typedef uint32_t cidx_t;
258

259

260

261
/*******************
262
 *  WATCH VECTORS  *
263
 ******************/
264

265
/*
266
 * Watch vectors play two roles.
267
 *
268
 * 1) During search
269
 *
270
 * For a literal l, watch[l] stores index/clauses in
271
 * which l is a watched literal. The information is stored as a
272
 * sequence of records, in an integer array.
273
 *
274
 * VERSION 1:
275
 * - if l is watched literal in a clause cidx of length >= 3, then
276
 *   the record is cidx.
277
 * - if l occurs in a binary clause { l, l1 } then the record is the
278
 *   literal l1
279
 *
280
 * To tell the difference, we use the lower-order bit of the integer:
281
 * - [cidx] is stored as is. The two low-order bits of cidx are 00.
282
 * - [l1] is stored as (l1 << 1)|1  (lower-order bit = 1)
283
 *
284
 *
285
 * VERSION 2:
286
 * - add a 'blocker' literal: for a clause cidx, we store the pair
287
 *   [cidx, l2] where l2 is a blocker. It's a literal that occurs in
288
 *   the clause. If l2 is true, we don't need to visit the clause
289
 *   to see that it can't propagate anything.
290
 *
291
 *
292
 * 2) During preprocessing
293
 *
294
 * Watch[l] stores all the clauses in which l occurs. In this mode,
295
 * both binary clauses and larger clauses are stored in the clause pool.
296
 * The vector watch[l] contains then an array of clause indices.
297
 *
298
 * The watch structure is a vector:
299
 * - capacity = full length of the data array
300
 * - size = number of array elements actually used
301
 */
302
typedef struct watch_s {
303
  uint32_t capacity;
304
  uint32_t size;
305
  uint32_t data[0]; // real length = capacity
306
} watch_t;
307

308

309

310
/*******************
311
 *  SAVED CLAUSES  *
312
 ******************/
313

314
/*
315
 * When variables/clauses are eliminated, we may need to keep a copy of some
316
 * of the clauses to recover the truth value of eliminated variables.
317
 * The saved data is a set of clauses of the form C_1 \/ l ... C_k \/ l
318
 * where l is either pos_lit(x) or neg_lit(x) and x is an eliminated variable.
319
 *
320
 * If we have a model M that doesn't give a value to x, we extend the assignment
321
 * by checking whether C_1, ..., C_k are all true in M. It they are, we set l := false
322
 * Otherwise, we set l := true (to force C_1 \/ l .... C_k \/ l to all be true in the
323
 * extended model. For this to work, we must process the variables in reverse order of
324
 * elimination, so that C_1 ... C_k have a value in M when we process x.
325
 *
326
 * The saved clauses are stored in a vector and are organized in blocks.
327
 * Each block stores k clauses C_1 \/ l ... C_k \/ l as above. The eliminated literal 'l'
328
 * is the last element of each clause. We then store the length of the block.
329
 * This looks like this:
330
 *
331
 *   -----------------------------------------------------------------------------
332
 *    previous block | C_1 ... l | C_2 ... l | ... | C_k ... l | n |  next block
333
 *   -----------------------------------------------------------------------------
334
 *
335
 * where n = total number of literals in C1 \/ l .... C_k \/ l.
336
 */
337
typedef struct nclause_vector_s {
338
  uint32_t *data;    // array to store the clauses
339
  uint32_t top;      // end of the last block (0 if there's nothing saved)
340
  uint32_t capacity; // full size of the data array
341
} nclause_vector_t;
342

343
#define DEF_CLAUSE_VECTOR_CAPACITY 10240
344
#define MAX_CLAUSE_VECTOR_CAPACITY MAX_ARRAY32_SIZE
345

346

347

348
/**********************
349
 *  ELIMINATION HEAP  *
350
 *********************/
351

352
/*
353
 * During preprocessing, we try to eliminate variables by full resolution.
354
 * We use a heuristic based on the number of positive/negative occurrences
355
 * of x to order the variables to eliminate. To store the variables in
356
 * order, we use a binary heap:
357
 * - data: heap proper as an array of variables
358
 * - elim_idx: position of variables in the data array
359
 * - size = number of elements stored in the data array
360
 * - capacity = full size of the data array
361
 *
362
 * For every i in [0 ... size-1], data[i] is a variable
363
 * - data[0] is always equal to 0 (it's used as a marker)
364
 * - for i>0 data[i] = a candidate variable for elimination
365
 *
366
 * For every variable x,
367
 * - elim_idx[x] = i iff data[i] = x
368
 * - elim_idx[x] = -1 if x is not stored in the heap
369
 */
370
typedef struct elim_heap_s {
371
  bvar_t *data;
372
  int32_t *elim_idx;
373
  uint32_t size;
374
  uint32_t capacity;
375
} elim_heap_t;
376

377
#define DEF_ELIM_HEAP_SIZE 1024
378
#define MAX_ELIM_HEAP_SIZE (UINT32_MAX/sizeof(bvar_t))
379

380

381

382
/**********************
383
 *  ASSIGNMENT STACK  *
384
 *********************/
385

386
/*
387
 * Assignment stack/propagation queue
388
 * - an array of literals (the literals assigned to true)
389
 * - two pointers: top of the stack, beginning of the propagation queue
390
 * - for each decision level, an index into the stack points
391
 *   to the literal decided at that level (for backtracking)
392
 */
393
typedef struct {
394
  literal_t *lit;
395
  uint32_t top;
396
  uint32_t prop_ptr;
397
  uint32_t *level_index;
398
  uint32_t nlevels; // size of level_index array
399
} sol_stack_t;
400

401

402
/*
403
 * Initial size of level_index
404
 */
405
#define DEFAULT_NLEVELS 100
406

407

408

409
/*******************
410
 *  CLAUSE STACK   *
411
 ******************/
412

413
/*
414
 * Experimental data structure to store clauses in a stack,
415
 * organized by decision levels.
416
 *
417
 * Clauses are stored in array data using the same format as clause_pool.
418
 * A clause is identified by an index i (which is a multiple of four)
419
 *   data[i] = clause length
420
 *   data[i+1] = auxiliary data (clause LDB)
421
 *   data[i+2,... i+n+2] = array of n literals = the clause
422
 * The first literal (in data[i+2]) is true.
423
 * The other literals in data[i+3 ... i+n+2] are all false.
424
 *
425
 * The stack is organize in levels:
426
 * - level[i] = index of the first clause learned at decision level i
427
 * - nlevels = number of levels
428
 *
429
 * Rest of the stack:
430
 * - capacity = full size of array data
431
 * - top = index in array data where the next clause will be stored
432
 */
433
typedef struct {
434
  uint32_t *data;
435
  uint32_t top;
436
  uint32_t capacity; // size of array data
437
  uint32_t *level;
438
  uint32_t nlevels; // size of array level
439
} clause_stack_t;
440

441

442
/*
443
 * Initial and maximal capacity
444
 * DEFAULT_NLEVELS is 100.
445
 */
446
#define DEF_CLAUSE_STACK_CAPACITY 16384
447
#define MAX_CLAUSE_STACK_CAPACITY (MAX_ARRAY32_SIZE & ~3)
448

449

450

451

452
/******************************
453
 *  HEAP/VARIABLE ACTIVITIES  *
454
 *****************************/
455

456
/*
457
 * Heap and variable activities for the variable-selection heuristic
458
 * - activity[x]: for every variable x between 1 and nvars - 1
459
 * - index 0 is used as a marker:
460
 *    activity[0] = DBL_MAX (higher than any activity)
461
 * - heap_index[x]: for every variable x,
462
 *      heap_index[x] = i if x is in the heap and heap[i] = x
463
 *   or heap_index[x] = -1 if x is not in the heap
464
 * - heap: array of nvars variables
465
 * - heap_last: index of last element in the heap
466
 *   heap[0] = 0,
467
 *   for i=1 to heap_last, heap[i] = x for some variable x
468
 * - size = size of arrays activity, heap_index and heap
469
 * - nvars = actual number of variables (must be <= size)
470
 * - vmax = variable index (last variable not in the heap)
471
 * - act_inc: variable activity increment
472
 * - inv_act_decay: inverse of variable activity decay (e.g., 1/0.95)
473
 *
474
 * Variable 0 is special: it corresponds to the two literals 0 and 1:
475
 * - literal 0 --> true_literal
476
 * - literal 1 --> false_literal
477
 *
478
 * The set of variables is split into two segments:
479
 * - [1 ... vmax-1] = variables that are in the heap or have been in the heap
480
 * - [vmax ... size-1] = variables that may not have been in the heap
481
 *
482
 * To pick a decision variable:
483
 * - search for the most active unassigned variable in the heap
484
 * - if the heap is empty or all its variables are already assigned,
485
 *   search for the first unassigned variables in [vmax ... size-1]
486
 *
487
 * Initially: we set vmax to 1 (nothing in the heap yet) so decision
488
 * variables are picked in increasing order, starting from 1.
489
 */
490
typedef struct nvar_heap_s {
491
  double *activity;
492
  int32_t *heap_index;
493
  bvar_t *heap;
494
  uint32_t heap_last;
495
  uint32_t size;
496
  uint32_t nvars;
497
  uint32_t vmax;
498
  double act_increment;
499
  double inv_act_decay;
500
} nvar_heap_t;
501

502

503

504
/******************************************
505
 * EXPERIMENTAL: MOVE-TO-FRONT HEURISTIC  *
506
 *****************************************/
507

508
/*
509
 * An alternative to scoring variables by activities as above, is to
510
 * keep them ordered in a list, with more important variables near the
511
 * front of the list. At every conflict, the variables involved in that
512
 * conflict are moved to the end of the list. This idea is due to
513
 * Lawrence Ryan (2004). Implementation tricks are based on Biere &
514
 * Froehlich, 2015.
515
 *
516
 * To support this, we build a doubly-linked list of variables
517
 * and we keep track of variables ranks in this list. More important
518
 * variables are stored at the end of the list, so it's "move to
519
 * back" rather than "move to front" but that's the same thing.
520
 * We also keep a pointer to the first variable that may be unassigned.
521
 *
522
 * Data structures:
523
 * - link[i].pre = predecessor of variable i in the list
524
 *   link[i].next = successor of variable i in the list
525
 * - rank[i] = rank of variable i
526
 * We maintain the invariant:
527
 *   rank[i] < rank[j] if i is before j in the list
528
 *
529
 * Index 0 is a special marker:
530
 * - link[0].pre = last element of the list
531
 *   link]0].next = first element of the list
532
 *   (so the list is circular if we include index 0)
533
 *   rank[0] = 0
534
 *
535
 * Other components:
536
 * - size = size of arrays link and rank
537
 * - nvars = actual number of variables (nvars <= size)
538
 * - max_rank = rank of the last element
539
 * - unassigned_index = variable index i. All successors of variable i are
540
 *   known to be assigned.
541
 * - unassigned_rank = rank of the unassigned index variable
542
 * - active_vars = auxiliary vector to store variables involved in a conflict.
543
 */
544
typedef struct vlink_s {
545
  uint32_t pre;
546
  uint32_t next;
547
} vlink_t;
548

549
typedef struct nvar_list_s {
550
  vlink_t *link;
551
  uint32_t *rank;
552
  uint32_t size;
553
  uint32_t nvars;
554
  uint32_t max_rank;
555
  uint32_t unassigned_index;
556
  uint32_t unassigned_rank;
557
  vector_t active_vars;
558
} nvar_list_t;
559

560

561
/****************
562
 *  STATISTICS  *
563
 ***************/
564

565
typedef struct solver_stats_s {
566
  uint64_t decisions;                // number of decisions
567
  uint64_t random_decisions;         // number of random decisions
568
  uint64_t propagations;             // number of boolean propagations
569
  uint64_t conflicts;                // number of conflicts/backtracking
570
  uint64_t local_subsumptions;       //
571
  uint64_t prob_clauses_deleted;     // number of problem clauses deleted
572
  uint64_t learned_clauses_deleted;  // number of learned clauses deleted
573
  uint64_t subsumed_literals;        // removed from learned clause (cf. simplify_learned_clause)
574

575
  uint32_t starts;                   // 1 + number of restarts
576
  uint32_t stabilizations;           // number of stabilization intervals
577
  uint32_t simplify_calls;           // number of calls to simplify_clause_database
578
  uint32_t reduce_calls;             // number of calls to reduce_learned_clause_set
579
  uint32_t scc_calls;                // number of calls to try_scc_simplification
580
  uint32_t try_equiv_calls;          // number of calls to try_equivalent_vars (includes preprocessing)
581
  uint32_t subst_calls;              // number of calls to apply_substitution
582
  uint32_t probe_calls;              // number of calls to failed_literal_probing
583

584
  // Substitutions
585
  uint32_t subst_vars;               // number of variables eliminated by substitution
586
  uint32_t subst_units;              // number of unit literals found by equivalence tests
587
  uint32_t equivs;                   // number of equivalences detected
588

589
  // Probing
590
  uint64_t probed_literals;          // number of probes
591
  uint64_t probing_propagations;     // propagations during probing
592
  uint32_t failed_literals;          // failed literals
593

594
  // Preprocessing statistics
595
  uint32_t pp_pure_lits;             // number of pure literals removed
596
  uint32_t pp_unit_lits;             // number of unit literals removed
597
  uint32_t pp_subst_vars;            // number of variables eliminated by substitution
598
  uint32_t pp_subst_units;           // number of unit literals found by equivalence checks
599
  uint32_t pp_equivs;                // number of equivalences detected
600
  uint32_t pp_scc_calls;             // number of calls to pp_scc_simplication
601
  uint32_t pp_clauses_deleted;       // number of clauses deleted during preprocessing
602
  uint32_t pp_subsumptions;          // number of subsumed clauses
603
  uint32_t pp_strengthenings;        // number of strengthened clauses
604
  uint32_t pp_unit_strengthenings;   // number of clauses strengthened to unit
605
  uint32_t pp_cheap_elims;           // cheap variable eliminations
606
  uint32_t pp_var_elims;             // less cheap variable eliminations
607
} solver_stats_t;
608

609

610
/**************************
611
 *  HEURISTIC PARAMETERS  *
612
 *************************/
613

614
typedef struct solver_param_s {
615
  /*
616
   * Search/restart/reduce heuristics
617
   */
618
  uint32_t seed;               // Seed for the pseudo-random number generator
619
  uint32_t randomness;         // 0x1000000 * random_factor
620
  float inv_cla_decay;         // Inverse of clause decay (1/0.999)
621

622
  uint32_t stack_threshold;    // Size of learned clause to preserve
623
  uint32_t keep_lbd;           // Clauses of LBD no more than this are preserved during reduce
624
  uint32_t reduce_fraction;    // Fraction of learned clauses to delete (scaled by 32)
625
  uint32_t reduce_interval;    // Number of conflicts between two calls to reduce
626
  uint32_t reduce_delta;       // Adjustment to reduce_interval
627
  uint32_t restart_interval;   // Minimal number of conflicts between two restarts
628

629
  /*
630
   * Heuristics/parameters for preprocessing
631
   * (these have no effect if the 'preprocess' flag is false)
632
   *
633
   * - subsume_skip: when checking whether a clause cl can subsume something,
634
   *   we visit clauses that share a variable with cl. It the number of clauses to
635
   *   visit is larger than subsume_skip  we skip clause cl. The subsumption check would
636
   *   be too expensive. This parameter is 3000 by default.
637
   *
638
   * - var_elim_skip controls which variables we try to eliminate. It's 10 by default.
639
   *   x is not considered if it has more than var_elim_skip positive and negative occurrences.
640
   *
641
   * - res_clause_limit: if eliminating a variable x would create a clause of size
642
   *   larger than res_clause_limit, we keep x. Default value = 20.
643
   *
644
   * - res_extra: if x occurs in n clauses, then we don't eliminat x if that would create more than
645
   *   (n + res_extra) clauses.
646
   */
647
  uint32_t subsume_skip;
648
  uint32_t var_elim_skip;
649
  uint32_t res_clause_limit;
650
  uint32_t res_extra;
651

652
  /*
653
   * Simplify heuristics
654
   */
655
  uint32_t simplify_interval;   // Minimal number of conflicts between two calls to simplify
656
  uint32_t simplify_bin_delta;  // Number of new binary clauses between two SCC computations
657
  uint32_t simplify_subst_delta;   // Number of substitutions before trying cut sweeping
658

659
  /*
660
   * Probing
661
   */
662
  uint32_t probing_interval;    // Number of conflicts between two calls to probing
663
  uint64_t probing_min_budget;  // Minimal budget (number of propagations)
664
  uint64_t probing_max_budget;  // Maximal budget (number of propagations_
665
  double probing_ratio;         // Fraction of propagations for probing (relative to search).
666

667
} solver_param_t;
668

669

670
/**********************
671
 *  ANTECEDENT TAGS   *
672
 *********************/
673

674
/*
675
 * When a variable is assigned, we store a tag to identify the reason
676
 * for the assignment. There are four cases:
677
 * - unit clause
678
 * - decision literal
679
 * - propagated from a binary clause
680
 * - propagated from a non-binary clause
681
 * + another one for variables not assigned
682
 * + another one for variables propagated from a stacked clause.
683
 *
684
 * If preprocessing is enabled, we also use this tag to keep track of
685
 * eliminated variables:
686
 * - pure literals
687
 * - variables eliminated by resolution
688
 *
689
 * We also support variable elimination by substitution. If variable x
690
 * is mapped to a literal l then we set ante_tag[x] = ATAG_SUBST and
691
 * ante_data[x] = l.
692
 */
693
typedef enum antecedent_tag {
694
  ATAG_NONE,
695
  ATAG_UNIT,
696
  ATAG_DECISION,
697
  ATAG_BINARY,
698
  ATAG_CLAUSE,
699
  ATAG_STACKED,
700

701
  ATAG_PURE,
702
  ATAG_ELIM,
703
  ATAG_SUBST,
704
} antecedent_tag_t;
705

706
#define NUM_ATAGS (ATAG_SUBST+1)
707

708
/*
709
 * Conflict tag:  when a clause is false, we store it for conflict analysis
710
 * and backtracking. The conflict tag records the type of clauses that's false.
711
 * There are two cases: binary clause + non-binary clause
712
 * + another tag for no conflict.
713
 *
714
 * For a binary clause conflict, the clause is stored in conflict_buffer.
715
 * For a non-binary clause, the clause index is stored in conflict_idx.
716
 */
717
typedef enum conflict_tag {
718
  CTAG_NONE,
719
  CTAG_BINARY,
720
  CTAG_CLAUSE,
721
} conflict_tag_t;
722

723

724
/*
725
 * SOLVER STATUS
726
 */
727
typedef enum solver_status {
728
  STAT_UNKNOWN,
729
  STAT_SAT,
730
  STAT_UNSAT,
731
} solver_status_t;
732

733

734

735
/****************************************
736
 *  EXPERIMENTAL: VARIABLE DESCRIPTORS  *
737
 ***************************************/
738

739
/*
740
 * For each variable, we optionally support metadata about where the
741
 * variable came from. This allows us to select which variables may be
742
 * eliminated or not and to attach a definition to a variable.
743
 *
744
 * For each variable x:
745
 * - tag[x] = NONE, TO_KEEP, or GATE
746
 * - desc[x] = index in the gate table if tag[x] == GATE, not used otherwise.
747
 */
748
typedef struct descriptors_s {
749
  uint8_t *tag;
750
  uint32_t *desc;
751
  uint32_t size;       // number of variables with a tag
752
  uint32_t capacity;   // size of arrays tag and desc
753
} descriptors_t;
754

755
#define DEF_DESCRIPTORS_SIZE 1024
756
#define MAX_DESCRIPTORS_SIZE (UINT32_MAX/sizeof(uint32_t))
757

758
typedef enum descriptor_tag_s {
759
  DTAG_NONE,
760
  DTAG_TO_KEEP,
761
  DTAG_GATE,
762
} descriptor_tag_t;
763

764

765
/******************************************
766
 *  EXPERIMENTAL: STACK FOR NAIVE SEARCH  *
767
 *****************************************/
768

769
/*
770
 * We can try to find a satisfiying assignment by trying to set
771
 * one literal in each clause (that's not already true). To do
772
 * this, we use a stack that stores pairs (cidx, index in the clause).
773
 */
774
typedef struct naive_pair_s {
775
  cidx_t cidx;
776
  uint32_t scan;
777
} naive_pair_t;
778

779

780
/*
781
 * Stack:
782
 * - each element in the stack are pairs [clause idx, scan idx]
783
 * - for the elements below top_binary, the clause idx points to a binary clause,
784
 *   the scan index is either 0 or 1.
785
 * - for the elements above top_binary, cidx points to a regular problem
786
 *   clause stored in solver->pool and scan index in integer between 0 and 
787
 *   length of the clause -1.
788
 */
789
typedef struct naive_stack_s {
790
  naive_pair_t *data;
791
  uint32_t top;
792
  uint32_t top_binary;
793
  uint32_t size;
794
} naive_stack_t;
795

796
#define DEF_NAIVE_STACK_SIZE 1024
797
#define MAX_NAIVE_STACK_SIZE (UINT32_MAX/sizeof(naive_pair_t))
798

799
/*
800
 * Search structure
801
 * - a stack as above
802
 * - bvector stores the binary clauses to satisfy
803
 * - cvector stores the problem clauses to satisfy
804
 * - scan index to identify the next clause to explore
805
 *   bindex = index in the bvector
806
 *   cindex = index in the cvector
807
 */
808
typedef struct naive_s {
809
  naive_stack_t stack;
810
  vector_t bvector;
811
  vector_t cvector;
812
  uint64_t decisions;
813
  uint64_t max_decisions;
814
  uint64_t conflicts;
815
  uint64_t max_conflicts;
816
} naive_t;
817

818

819

820
/******************
821
 *  FULL SOLVER   *
822
 *****************/
823

824
/*
825
 * For each variable x, we store
826
 * - ante_tag[x]  = tag for assigned variables + marks
827
 * - ante_data[x] = antecedent index
828
 * - level[x]     = assignment level
829
 *
830
 * For each literal l, we keep
831
 * - watch[l] = watch vector for l
832
 * - value[l] = assigned value
833
 *
834
 * If preprocessing is enabled:
835
 * - occ[l] = number of clauses that contain l
836
 */
837
typedef struct sat_solver_s {
838
  solver_status_t status;
839
  uint32_t decision_level;
840
  uint32_t backtrack_level;
841
  bool preprocess;             // True if preprocessing is enabled
842

843
  uint32_t verbosity;          // Verbosity level: 0 means quiet
844
  uint32_t reports;            // Counter
845

846
  /*
847
   * Variables and literals
848
   */
849
  uint32_t nvars;              // Number of variables
850
  uint32_t nliterals;          // Number of literals = twice nvars
851
  uint32_t vsize;              // Size of the variable-indexed arrays (>= nvars)
852
  uint32_t lsize;              // Size of the watch array (>= nlits)
853

854
  uint8_t *value;
855
  uint8_t *ante_tag;
856
  uint32_t *ante_data;
857
  uint32_t *level;
858
  watch_t **watch;
859
  uint32_t *occ;              // Occurrence counts
860

861
  //  nvar_heap_t heap;           // Variable heap
862
  nvar_list_t list;           // Move-to-front heuristic
863
  sol_stack_t stack;          // Assignment/propagation queue
864

865
  /*
866
   * Clause database and related stuff
867
   *
868
   * In default mode:
869
   * - unit clauses are stored implicitly in the assignment stack
870
   * - binary clauses are stored implicitly in the watch vectors
871
   * - all other clauses are in the pool
872
   *
873
   * In preprocessing mode
874
   * - unit clauses are in the assignment stack
875
   * - all other clauses are in the pool (including binary clauses).
876
   */
877
  bool has_empty_clause;      // Whether the empty clause was added
878
  uint32_t units;             // Number of unit clauses
879
  uint32_t binaries;          // Number of binary clauses
880
  clause_pool_t pool;         // Pool for non-binary/non-unit clauses
881

882
  /*
883
   * Clause stack (experimental)
884
   */
885
  clause_stack_t stash;
886

887
  /*
888
   * Conflict data
889
   */
890
  conflict_tag_t conflict_tag;
891
  uint32_t conflict_buffer[2];
892
  cidx_t conflict_index;
893

894
  cidx_t last_learned;
895
  uint32_t last_level;
896

897
  /*
898
   * Parameters
899
   */
900
  solver_param_t params;
901

902
  /*
903
   * Counters/variables used by the search heuristics
904
   */
905
  float cla_inc;               // Clause activity increment
906

907
  uint32_t prng;               // State of the pseudo-random number generator
908

909
  uint64_t reduce_next;        // Number of conflicts before the next call to reduce
910
  uint32_t reduce_inc;         // Increment to reduce_threshold
911
  uint32_t reduce_inc2;        // Increment to reduce_inc
912

913
  uint32_t simplify_assigned;  // Number of literals assigned at level0 after the last call to simplify_clause_database
914
  uint32_t simplify_binaries;  // Number of binary clauses after the last call to simplify_clause_database
915
  uint32_t simplify_new_bins;  // Number of binary clauses created by simplification
916
  uint32_t simplify_new_units; // number of unit clauses create by simplification
917
  uint32_t simplify_subst_next; // Number of substitutions before the next call to try_equiv
918
  uint64_t simplify_next;      // Number of conflicts before the next call to simplify
919

920
  uint64_t probing_next;       // Number of conflicts before the next call to probe
921
  uint64_t probing_budget;     // Max number of propagations in a single probe
922
  uint64_t probing_last;       // NUmber of propagations since the last probe
923
  uint64_t probing_inc;        // Increment to probing next
924

925
  /*
926
   * Exponential moving averages for restarts
927
   * (based on "Evaluating CDCL Restart Schemes" by Biere & Froehlich, 2015).
928
   */
929
  uint64_t slow_ema;
930
  uint64_t fast_ema;
931
  uint64_t restart_next;
932
  uint32_t fast_count;
933

934
  /*
935
   * More counters and averages. Used only for statistics for now.
936
   */
937
  uint32_t max_depth;
938
  uint64_t level_ema;
939

940
  /*
941
   * Experimental: "stabilizing" periods
942
   * (based on Cadical). During a stabilizing period, we don't restart.
943
   */
944
  bool stabilizing;
945
  uint64_t stab_next;
946
  uint64_t stab_length;
947

948
  /*
949
   * Probing flag
950
   */
951
  bool probing;
952
  bool try_assignment;
953
  bool try_naive_search;
954

955
  /*
956
   * Statistics record
957
   */
958
  solver_stats_t stats;
959

960
  /*
961
   * Auxiliary array to save assignment
962
   */
963
  uint8_t *saved_values;
964

965
  /*
966
   * Auxiliary array for clause deletion
967
   */
968
  cidx_t *cidx_array;
969

970
  /*
971
   * Buffers and other data structures to build and simplify clauses.
972
   */
973
  vector_t buffer;
974
  vector_t aux;
975
  gstack_t gstack;
976
  tag_map_t map;
977

978
  /*
979
   * Saved clauses
980
   */
981
  nclause_vector_t saved_clauses;
982

983
  /*
984
   * Data structures used during preprocessing:
985
   * 1) lqueue: queue of pure and unit literals to eliminate
986
   * 2) elim: heap of candidate variables to eliminate
987
   * 3) for clause subsumption:
988
   *    - we visit clauses sequentially
989
   *    - scan_index = index of the next clause to visit
990
   *    - cqueue = more clauses that have to be revisited
991
   *    - every clause in cqueue is marked
992
   */
993
  queue_t lqueue;
994
  elim_heap_t elim;
995
  queue_t cqueue;
996
  vector_t cvector;
997
  uint32_t scan_index;
998

999
  /*
1000
   * Data structures to compute SCC in the binary implication graph.
1001
   */
1002
  vector_t vertex_stack;
1003
  gstack_t dfs_stack;
1004
  uint32_t *label;
1005
  uint32_t *visit;
1006

1007
  vector_t subst_vars;  // all variables eliminated in an SCC round
1008
  vector_t subst_units; // literals found equal to true by SCC/EQ
1009
  vector_t subst_pure;  // literals that become pure after substitution
1010

1011
  /*
1012
   * Variable descriptors + gates
1013
   */
1014
  descriptors_t descriptors;
1015
  bgate_array_t gates;
1016

1017
  /*
1018
   * File for data collection (used only when macro DATA is non-zero)
1019
   */
1020
  FILE *data;
1021

1022
} sat_solver_t;
1023

1024

1025
// Default size for the variable array
1026
#define SAT_SOLVER_DEFAULT_VSIZE 1024
1027

1028
// Default buffer size
1029
#define SAT_SOLVER_BUFFER_SIZE 60
1030

1031

1032

1033
/********************
1034
 *  MAIN FUNCTIONS  *
1035
 *******************/
1036

1037
/*
1038
 * Initialization:
1039
 * - sz = initial size of the variable-indexed arrays.
1040
 * - pp = whether to use preprocessing
1041
 *
1042
 * - if sz is zero, the default size is used.
1043
 * - if pp is true, the solver is initialized for preprocessing,
1044
 *   otherwise no preprocessing is used.
1045
 * - the solver is initialized with one variable (the reserved variable 0).
1046
 * - verbosity is 0.
1047
 */
1048
extern void init_nsat_solver(sat_solver_t *solver, uint32_t sz, bool pp);
1049

1050
/*
1051
 * Set the verbosity level
1052
 * - this determines how much stuff is printed (on stderr) during the search.
1053
 * - level == 0 --> print nothing (this is the default)
1054
 * - level >= 1 --> print statistics about preprocessing
1055
 * - level >= 2 --> print statistics at every restart
1056
 */
1057
extern void nsat_set_verbosity(sat_solver_t *solver, uint32_t level);
1058

1059
/*
1060
 * Deletion: free memory
1061
 */
1062
extern void delete_nsat_solver(sat_solver_t *solver);
1063

1064
/*
1065
 * Reset: remove all variables and clauses
1066
 */
1067
extern void reset_nsat_solver(sat_solver_t *solver);
1068

1069
/*
1070
 * Add n fresh variables:
1071
 * - they are indexed from nv, ..., nv + n-1 where nv = number of
1072
 *   variables in solver (on entry to this function).
1073
 */
1074
extern void nsat_solver_add_vars(sat_solver_t *solver, uint32_t n);
1075

1076
/*
1077
 * Allocate a fresh Boolean variable and return its index.
1078
 */
1079
extern bvar_t nsat_solver_new_var(sat_solver_t *solver);
1080

1081

1082
/*
1083
 * EXPERIMENTAL
1084
 */
1085

1086
/*
1087
 * Update activity and polarity for variable x
1088
 * - polarity true: means true is preferred
1089
 * - act must be positive
1090
 */
1091
extern void nsat_solver_activate_var(sat_solver_t *solver, bvar_t x, double act, bool polarity);
1092

1093
/*
1094
 * Mark variable x as a variable to keep. It will not be deleted during
1095
 * preprocessing. By default, all variables are considered candidates for
1096
 * elimination.
1097
 */
1098
extern void nsat_solver_keep_var(sat_solver_t *solver, bvar_t x);
1099

1100
/*
1101
 * Add a definition for variable x.
1102
 * There are two forms: binary and ternary definitions.
1103
 *
1104
 * A binary definition is x = (OP l1 l2) where l1 and l2 are literals
1105
 * and OP is a binary operator defined by a truth table.
1106
 *
1107
 * A ternary definition is similar, but with three literals:
1108
 * x = (OP l1 l2 l3).
1109
 *
1110
 * The truth table is defined by the  8 low-order bit of parameter b.
1111
 * The conventions are the same as in new_gates.h.
1112
 */
1113
extern void nsat_solver_add_def2(sat_solver_t *solver, bvar_t x, uint32_t b, literal_t l1, literal_t l2);
1114
extern void nsat_solver_add_def3(sat_solver_t *solver, bvar_t x, uint32_t b, literal_t l1, literal_t l2, literal_t l3);
1115

1116

1117

1118
/*********************************
1119
 *  CHANGE HEURISTIC PARAMETERS  *
1120
 ********************************/
1121

1122
/*
1123
 * Variable activity decay: must be between 0 and 1.0
1124
 * - smaller number means faster decay
1125
 */
1126
extern void nsat_set_var_decay_factor(sat_solver_t *solver, double factor);
1127

1128
/*
1129
 * Clause activity decay: must be between 0 and 1.0
1130
 * - smaller means faster decay
1131
 */
1132
extern void nsat_set_clause_decay_factor(sat_solver_t *solver, float factor);
1133

1134
/*
1135
 * Randomness: the parameter is approximately the ratio of random
1136
 * decisions.
1137
 * - randomness = 0: no random decisions
1138
 * - randomness = 1.0: all decisions are random
1139
 */
1140
extern void nsat_set_randomness(sat_solver_t *solver, float randomness);
1141

1142
/*
1143
 * Set the prng seed
1144
 */
1145
extern void nsat_set_random_seed(sat_solver_t *solver, uint32_t seed);
1146

1147
/*
1148
 * Stack clause threshold: learned clauses of LBD greater than threshold are
1149
 * treated as temporary clauses (not stored in the clause database).
1150
 */
1151
extern void nsat_set_stack_threshold(sat_solver_t *solver, uint32_t f);
1152

1153
/*
1154
 * LBD threshold for clause deletion. Clauses of lbd <= keep_lbd are not deleted.
1155
 */
1156
extern void nsat_set_keep_lbd(sat_solver_t *solver, uint32_t threshold);
1157

1158
/*
1159
 * Reduce fraction for clause deletion. f must be between 0 and 32.
1160
 * Each call to reduce_learned_clause_set removes a fraction (f/32) of the clauses
1161
 */
1162
extern void nsat_set_reduce_fraction(sat_solver_t *solver, uint32_t f);
1163

1164
/*
1165
 * Interval between two calls to reduce (number of conflicts)
1166
 */
1167
extern void nsat_set_reduce_interval(sat_solver_t *solver, uint32_t n);
1168

1169
/*
1170
 * Adjustment to the reduce interval (check init_reduce and done_reduce).
1171
 */
1172
extern void nsat_set_reduce_delta(sat_solver_t *solver, uint32_t d);
1173

1174

1175
/*
1176
 * Minimal number of conflicts between two calls to restart
1177
 */
1178
extern void nsat_set_restart_interval(sat_solver_t *solver, uint32_t n);
1179

1180

1181

1182
/*
1183
 * PREPROCESSING PARAMETERS
1184
 */
1185

1186
/*
1187
 * Subsumption limit: skip subsumption checks for a clause cls if that
1188
 * would require visiting more than subsume_skip clauses.
1189
 */
1190
extern void nsat_set_subsume_skip(sat_solver_t *solver, uint32_t limit);
1191

1192
/*
1193
 * Var-elimination limit: if x has too many positive and negative occurrences,
1194
 * we don't try to eliminate x.
1195
 */
1196
extern void nsat_set_var_elim_skip(sat_solver_t *solver, uint32_t limit);
1197

1198
/*
1199
 * Resolvent limit: if eliminating x would create a clause larger than
1200
 * res_clause_limit, we keep x.
1201
 */
1202
extern void nsat_set_res_clause_limit(sat_solver_t *solver, uint32_t limit);
1203

1204
/*
1205
 * Limit on number of new clauses after eliminating x.
1206
 * - x is not * eliminated if that would create more than res_extra new clauses
1207
 * - so if x occurs in n clauses, it's not eliminated if it has more than n
1208
 *   + res_extra non-trivial resolvants.
1209
 */
1210
extern void nsat_set_res_extra(sat_solver_t *solver, uint32_t extra);
1211

1212
/*
1213
 * SIMPLIFY PARAMETERS
1214
 */
1215

1216
/*
1217
 * Minimal number of conflicts between two calls to simplify
1218
 */
1219
extern void nsat_set_simplify_interval(sat_solver_t *solver, uint32_t n);
1220

1221
/*
1222
 * Number of new binary clauses before two SCC computations
1223
 */
1224
extern void nsat_set_simplify_bin_delta(sat_solver_t *solver, uint32_t d);
1225

1226
/*
1227
 * Number of new substitutions before cut sweeping round
1228
 */
1229
extern void nsat_set_simplify_subst_delta(sat_solver_t *solver, uint32_t d);
1230

1231

1232
/*********************
1233
 *  CLAUSE ADDITION  *
1234
 ********************/
1235

1236
/*
1237
 * A clause is an array of literals (integers between 0 and nlits - 1)
1238
 * - a clause is simplified if it satisfies the following conditions:
1239
 *   1) it doesn't contain assigned literals (including the reserved
1240
 *      literals 0 and 1)
1241
 *   2) it doesn't include duplicates or complementary literals
1242
 *
1243
 * This function simplifies the clause then adds it
1244
 * - n = number of literals
1245
 * - l = array of n literals
1246
 * - the array is modified
1247
 */
1248
extern void nsat_solver_simplify_and_add_clause(sat_solver_t *solver, uint32_t n, literal_t *l);
1249

1250

1251
/*************
1252
 *  SOLVING  *
1253
 ************/
1254

1255
/*
1256
 * Check satisfiability of the set of clauses
1257
 * - result = either STAT_SAT or STAT_UNSAT
1258
 */
1259
extern solver_status_t nsat_solve(sat_solver_t *solver);
1260

1261

1262
/*
1263
 * Read the status
1264
 */
1265
static inline solver_status_t nsat_status(sat_solver_t *solver) {
1266
  return solver->status;
1267
}
1268

1269
/*
1270
 * Only run the preprocessor
1271
 * - this must be called after clause addition
1272
 * - the type of preprocessing performed depends on flag solver->preprocess.
1273
 *   if the flag is false, we just do basic simplications
1274
 *   if the flag is true, we do SCC + equality detection based on cut sweeping.
1275
 * - result = either STAT_SAT or STAT_UNSAT or STAT_UNKNOWN
1276
 * - the amount of preprocessing pefromed
1277
 */
1278
extern solver_status_t nsat_apply_preprocessing(sat_solver_t *solver);
1279

1280

1281
/********************
1282
 * EXPORT TO DIMACS *
1283
 *******************/
1284

1285
/*
1286
 * Export the clauses of solver to file f
1287
 * Use the DIMACS format.
1288
 * - f must be open and writable
1289
 */
1290
extern void nsat_export_to_dimacs(FILE *f, const sat_solver_t *solver);
1291

1292

1293

1294
/**************************
1295
 *  VARIABLE ASSIGNMENTS  *
1296
 *************************/
1297

1298
static inline bval_t lit_value(const sat_solver_t *solver, literal_t l) {
×
1299
  assert(l < solver->nliterals);
1300
  return solver->value[l];
×
1301
}
1302

1303
static inline bval_t var_value(const sat_solver_t *solver, bvar_t x) {
×
1304
  assert(x < solver->nvars);
1305
  return solver->value[pos_lit(x)];
×
1306
}
1307

1308
static inline bool lit_is_unassigned(const sat_solver_t *solver, literal_t l) {
×
1309
  return bval_is_undef(lit_value(solver, l));
×
1310
}
1311

1312
static inline bool var_is_unassigned(const sat_solver_t *solver, bvar_t x) {
×
1313
  return bval_is_undef(var_value(solver, x));
×
1314
}
1315

1316
static inline bool var_is_assigned(const sat_solver_t *solver, bvar_t x) {
×
1317
  return ! var_is_unassigned(solver, x);
×
1318
}
1319

1320
static inline bool lit_is_assigned(const sat_solver_t *solver, literal_t l) {
×
1321
  return ! lit_is_unassigned(solver, l);
×
1322
}
1323

1324
static inline bool lit_prefers_true(const sat_solver_t *solver, literal_t l) {
1325
  return true_preferred(lit_value(solver, l));
1326
}
1327

1328
static inline bool lit_is_true(const sat_solver_t *solver, literal_t l) {
×
1329
  return lit_value(solver, l) == VAL_TRUE;
×
1330
}
1331

1332
static inline bool lit_is_false(const sat_solver_t *solver, literal_t l) {
×
1333
  return lit_value(solver, l) == VAL_FALSE;
×
1334
}
1335

1336

1337
static inline bool var_prefers_true(const sat_solver_t *solver, bvar_t x) {
1338
  return true_preferred(var_value(solver, x));
1339
}
1340

1341
static inline bool var_is_true(const sat_solver_t *solver, bvar_t x) {
×
1342
  return var_value(solver, x) == VAL_TRUE;
×
1343
}
1344

1345
static inline bool var_is_false(const sat_solver_t *solver, bvar_t x) {
1346
  return var_value(solver, x) == VAL_FALSE;
1347
}
1348

1349

1350

1351
/************
1352
 *  MODELS  *
1353
 ***********/
1354

1355
/*
1356
 * Return the model: copy all variable value into val
1357
 * - val's size must be at least solver->nvars
1358
 * - val[0] is always true
1359
 */
1360
extern void nsat_get_allvars_assignment(const sat_solver_t *solver, bval_t *val);
1361

1362
/*
1363
 * Copy all true literals in array a:
1364
 * - a must have size >= solver->nvars.
1365
 * return the number of literals added to a.
1366
 */
1367
extern uint32_t nsat_get_true_literals(const sat_solver_t *solver, literal_t *a);
1368

1369

1370

1371
/******************************
1372
 * PRINT INTERNAL STRUCTURES  *
1373
 *****************************/
1374

1375
extern void show_state(FILE *f, const sat_solver_t *solver);
1376

1377

1378

1379
/*******************************
1380
 * STATISTICS/DATA COLLECTION  *
1381
 ******************************/
1382

1383
/*
1384
 * Print statistics
1385
 */
1386
extern void nsat_show_statistics(FILE *f, const sat_solver_t *solver);
1387

1388
/*
1389
 * If the solver is compiled with DATA enabled,
1390
 * then data is collected in a file after every conflict.
1391
 * - this function opens the data file
1392
 * - name = name of the file to use
1393
 * - if the file can't be created, no error is produced
1394
 *   (and no data will be collected).
1395
 *
1396
 * If DATA is disabled, the function does nothing.
1397
 */
1398
extern void nsat_open_datafile(sat_solver_t *solver, const char *name);
1399

1400

1401

1402
#endif /* __NEW_SAT_SOLVER_H */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc