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

SRI-CSL / yices2 / 28389220151

29 Jun 2026 05:03PM UTC coverage: 69.402% (+0.009%) from 69.393%
28389220151

push

github

web-flow
Merge pull request #636 from SRI-CSL/reduce-cdclt

New ReduceDB cdclt

44 of 73 new or added lines in 5 files covered. (60.27%)

8 existing lines in 5 files now uncovered.

91813 of 132292 relevant lines covered (69.4%)

1505418.88 hits per line

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

78.06
/src/context/context_solver.c
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
 * SEARCH AND SOLVING PROCEDURES
21
 *
22
 * This module implements the check_context function (and variants).
23
 * It also implements model construction.
24
 */
25

26
#include <stdbool.h>
27
#include <assert.h>
28
#include <stdint.h>
29
#include <inttypes.h>
30
#include <stdio.h>
31
#include <math.h>
32
#include <string.h>
33

34
#include "context/context.h"
35
#include "context/internalization_codes.h"
36
#include "model/models.h"
37
#include "mcsat/solver.h"
38
#include "solvers/bv/dimacs_printer.h"
39
#include "solvers/cdcl/delegate.h"
40
#include "solvers/mcsat_satellite.h"
41
#include "solvers/funs/fun_solver.h"
42
#include "solvers/simplex/simplex.h"
43
#include "terms/term_explorer.h"
44
#include "terms/term_manager.h"
45
#include "terms/term_substitution.h"
46
#include "utils/int_hash_map.h"
47
#include "utils/int_hash_sets.h"
48
#include "utils/memalloc.h"
49

50
#include "api/yices_globals.h"
51
#include "api/yices_api_lock_free.h"
52
#include "mt/thread_macros.h"
53

54

55

56
/*
57
 * TRACE FUNCTIONS
58
 */
59

60
/*
61
 * Basic statistics
62
 */
63
static void trace_stats(smt_core_t *core, const char *when, uint32_t level) {
95,083✔
64
  trace_printf(core->trace, level,
95,083✔
65
               "(%-10s %8"PRIu64" %10"PRIu64" %8"PRIu64" %8"PRIu32" %8"PRIu32" %8"PRIu64" %8"PRIu32" %8"PRIu64" %7.1f)\n",
66
               when, core->stats.conflicts, core->stats.decisions, core->stats.random_decisions,
67
               num_binary_clauses(core), num_prob_clauses(core), num_prob_literals(core),
68
               num_learned_clauses(core), num_learned_literals(core), avg_learned_clause_size(core));
69
#if 0
70
  fprintf(stderr,
71
          "(%-10s %8"PRIu64" %10"PRIu64" %8"PRIu64" %8"PRIu32" %8"PRIu32" %8"PRIu64" %8"PRIu32" %8"PRIu64" %7.1f)\n",
72
          when, core->stats.conflicts, core->stats.decisions, core->stats.random_decisions,
73
          num_binary_clauses(core), num_prob_clauses(core), num_prob_literals(core),
74
          num_learned_clauses(core), num_learned_literals(core), avg_learned_clause_size(core));
75
#endif
76
}
95,083✔
77

78
/*
79
 * On start_search
80
 */
81
static void trace_start(smt_core_t *core) {
46,185✔
82
  trace_stats(core, "start:", 1);
46,185✔
83
}
46,185✔
84

85

86
/*
87
 * On restart
88
 */
89
static void trace_restart(smt_core_t *core) {
2,401✔
90
  trace_stats(core, "restart:", 1);
2,401✔
91
}
2,401✔
92

93
static void trace_inner_restart(smt_core_t *core) {
86✔
94
  trace_stats(core, "inner restart:", 5);
86✔
95
}
86✔
96

97

98
/*
99
 * On reduce clause database
100
 */
101
static void trace_reduce(smt_core_t *core, uint64_t deleted) {
226✔
102
  trace_stats(core, "reduce:", 3);
226✔
103
  trace_printf(core->trace, 4, "(%"PRIu64" clauses deleted)\n", deleted);
226✔
104
}
226✔
105

106

107

108
/*
109
 * End of search
110
 */
111
static void trace_done(smt_core_t *core) {
46,185✔
112
  trace_stats(core, "done:", 1);
46,185✔
113
  trace_newline(core->trace, 1);
46,185✔
114
}
46,185✔
115

116

117

118
/*
119
 * PROCESS AN ASSUMPTION
120
 */
121

122
/*
123
 * l = assumption for the current decision level
124
 * If l is unassigned, we assign it and perform one round of propagation
125
 * If l is false, we record the conflict. The context is unsat under the
126
 * current set of assumptions.
127
 */
128
static void process_assumption(smt_core_t *core, literal_t l) {
102,552✔
129
  switch (literal_value(core, l)) {
102,552✔
130
  case VAL_UNDEF_FALSE:
99,259✔
131
  case VAL_UNDEF_TRUE:
132
    decide_literal(core, l);
99,259✔
133
    smt_process(core);
99,259✔
134
    break;
99,259✔
135

136
  case VAL_TRUE:
×
137
    break;
×
138

139
  case VAL_FALSE:
3,293✔
140
    save_conflicting_assumption(core, l);
3,293✔
141
    break;
3,293✔
142
  }
143
}
102,552✔
144

145

146
/*
147
 * MAIN SEARCH FUNCTIONS
148
 */
149

150
/*
151
 * Handle the reduce heuristic (CaDiCaL-style):
152
 * - if the number of conflicts has reached the threshold, reduce the clause database
153
 * - set the next threshold to num_conflicts + r_interval * sqrt(num_conflicts)
154
 */
155
static inline void try_reduce_heuristic(smt_core_t *core, uint64_t *r_threshold, uint32_t r_interval) {
7,533,863✔
156
  uint64_t conflicts, deletions;
157

158
  assert(r_interval > 0);
159

160
  conflicts = num_conflicts(core);
7,533,863✔
161
  if (conflicts >= *r_threshold) {
7,533,863✔
162
    deletions = core->stats.learned_clauses_deleted;
226✔
163
    reduce_clause_database(core);
226✔
164
    *r_threshold = conflicts + (uint64_t) (r_interval * sqrt((double) conflicts));
226✔
165
    trace_reduce(core, core->stats.learned_clauses_deleted - deletions);
226✔
166
  }
167
}
7,533,863✔
168

169
/*
170
 * Bounded search with the default branching heuristic (picosat-like)
171
 * - search until the conflict bound is reached or until the problem is solved.
172
 * - reduce_threshold: conflict count above which reduce_clause_database is called
173
 * - r_interval = coefficient in threshold update: next = conflicts + r_interval * sqrt(conflicts)
174
 * - use the default branching heuristic implemented by the core
175
 */
176
static void search(smt_core_t *core, uint32_t conflict_bound, uint64_t *reduce_threshold, uint32_t r_interval) {
13,457✔
177
  uint64_t max_conflicts;
178
  literal_t l;
179

180
  assert(smt_status(core) == YICES_STATUS_SEARCHING || smt_status(core) == YICES_STATUS_INTERRUPTED);
181

182
  max_conflicts = num_conflicts(core) + conflict_bound;
13,457✔
183

184
  smt_process(core);
13,457✔
185
  while (smt_status(core) == YICES_STATUS_SEARCHING && num_conflicts(core) <= max_conflicts) {
6,265,624✔
186
    // reduce heuristic
187
    try_reduce_heuristic(core, reduce_threshold, r_interval);
6,252,167✔
188

189
    // assumption
190
    if (core->has_assumptions) {
6,252,167✔
191
      l = get_next_assumption(core);
12✔
192
      if (l != null_literal) {
12✔
193
        process_assumption(core, l);
5✔
194
        continue;
5✔
195
      }
196
    }
197

198
    // decision
199
    l = select_unassigned_literal(core);
6,252,162✔
200
    if (l == null_literal) {
6,252,162✔
201
      // all variables assigned: Call final_check
202
      smt_final_check(core);
16,600✔
203
    } else {
204
      decide_literal(core, l);
6,235,562✔
205
      smt_process(core);
6,235,562✔
206
    }
207
  }
208
}
13,457✔
209

210

211
/*
212
 * HACK: Variant for Luby restart:
213
 * - search until the conflict bound is reached or until the problem is solved.
214
 * - reduce_threshold: conflict count above which reduce_clause_database is called
215
 * - r_interval = coefficient in threshold update: next = conflicts + r_interval * sqrt(conflicts)
216
 * - use the default branching heuristic implemented by the core
217
 *
218
 * This uses smt_bounded_process to force more frequent restarts.
219
 */
220
static void luby_search(smt_core_t *core, uint32_t conflict_bound, uint64_t *reduce_threshold, uint32_t r_interval) {
14,331✔
221
  uint64_t max_conflicts;
222
  literal_t l;
223

224
  assert(smt_status(core) == YICES_STATUS_SEARCHING || smt_status(core) == YICES_STATUS_INTERRUPTED);
225

226
  max_conflicts = num_conflicts(core) + conflict_bound;
14,331✔
227
  smt_bounded_process(core, max_conflicts);
14,331✔
228
  while (smt_status(core) == YICES_STATUS_SEARCHING && num_conflicts(core) < max_conflicts) {
691,139✔
229
    // reduce heuristic
230
    try_reduce_heuristic(core, reduce_threshold, r_interval);
676,808✔
231

232
    // assumption
233
    if (core->has_assumptions) {
676,808✔
234
      l = get_next_assumption(core);
113,834✔
235
      if (l != null_literal) {
113,834✔
236
        process_assumption(core, l);
102,543✔
237
        continue;
102,543✔
238
      }
239
    }
240

241
    // decision
242
    l = select_unassigned_literal(core);
574,265✔
243
    if (l == null_literal) {
574,265✔
244
      // all variables assigned: Call final_check
245
      smt_final_check(core);
8,803✔
246
    } else {
247
      decide_literal(core, l);
565,462✔
248
      smt_bounded_process(core, max_conflicts);
565,462✔
249
    }
250
  }
251
}
14,331✔
252

253
/*
254
 * Polarity selection (implements branching heuristics)
255
 * - filter is given a literal l + core and must return either l or not l
256
 */
257
typedef literal_t (*branching_fun_t)(smt_core_t *core, literal_t l);
258

259

260
/*
261
 * Bounded search with a non-default branching heuristics
262
 * - search until the conflict bound is reached or until the problem is solved.
263
 * - reduce_threshold: conflict count above which reduce_clause_database is called
264
 * - r_interval = coefficient in threshold update: next = conflicts + r_interval * sqrt(conflicts)
265
 * - use the branching heuristic implemented by branch
266
 */
267
static void special_search(smt_core_t *core, uint32_t conflict_bound, uint64_t *reduce_threshold,
20,884✔
268
                           uint32_t r_interval, branching_fun_t branch) {
269
  uint64_t max_conflicts;
270
  literal_t l;
271

272
  assert(smt_status(core) == YICES_STATUS_SEARCHING || smt_status(core) == YICES_STATUS_INTERRUPTED);
273

274
  max_conflicts = num_conflicts(core) + conflict_bound;
20,884✔
275
  smt_process(core);
20,884✔
276
  while (smt_status(core) == YICES_STATUS_SEARCHING && num_conflicts(core) <= max_conflicts) {
625,772✔
277
    // reduce heuristic
278
    try_reduce_heuristic(core, reduce_threshold, r_interval);
604,888✔
279

280
    // assumption
281
    if (core->has_assumptions) {
604,888✔
282
      l = get_next_assumption(core);
4✔
283
      if (l != null_literal) {
4✔
284
        process_assumption(core, l);
4✔
285
        continue;
4✔
286
      }
287
    }
288

289
    // decision
290
    l = select_unassigned_literal(core);
604,884✔
291
    if (l == null_literal) {
604,884✔
292
      // all variables assigned: call final check
293
      smt_final_check(core);
22,648✔
294
    } else {
295
      // apply the branching heuristic
296
      l = branch(core, l);
582,236✔
297
      // propagation
298
      decide_literal(core, l);
582,236✔
299
      smt_process(core);
582,236✔
300
    }
301
  }
302
}
20,884✔
303

304

305

306

307

308
/*
309
 * SUPPORTED BRANCHING
310
 */
311

312
/*
313
 * Simple branching heuristics:
314
 * - branch to the negative polarity
315
 * - branch to the positive polarity
316
 */
317
static literal_t negative_branch(smt_core_t *core, literal_t l) {
179,790✔
318
  return l | 1; // force the sign bit to 1
179,790✔
319
}
320

321
static literal_t positive_branch(smt_core_t *core, literal_t l) {
26,776✔
322
  return l & ~1; // force the sign bit to 0
26,776✔
323
}
324

325

326
/*
327
 * For literals with no atom, use the default, otherwise let the theory solver decide
328
 */
329
static literal_t theory_branch(smt_core_t *core, literal_t l) {
375,670✔
330
  if (bvar_has_atom(core, var_of(l))) {
375,670✔
331
    l =  core->th_smt.select_polarity(core->th_solver, get_bvar_atom(core, var_of(l)), l);
306,767✔
332
  }
333
  return l;
375,670✔
334
}
335

336
// variants
337
static literal_t theory_or_neg_branch(smt_core_t *core, literal_t l) {
×
338
  if (bvar_has_atom(core, var_of(l))) {
×
339
    return core->th_smt.select_polarity(core->th_solver, get_bvar_atom(core, var_of(l)), l);
×
340
  } else {
341
    return l | 1;
×
342
  }
343
}
344

345
static literal_t theory_or_pos_branch(smt_core_t *core, literal_t l) {
×
346
  if (bvar_has_atom(core, var_of(l))) {
×
347
    return core->th_smt.select_polarity(core->th_solver, get_bvar_atom(core, var_of(l)), l);
×
348
  } else {
349
    return l & ~1;
×
350
  }
351
}
352

353

354

355

356

357
/*
358
 * CORE SOLVER
359
 */
360

361
/*
362
 * Full solver:
363
 * - params: heuristic parameters.
364
 * - n = number of assumptions
365
 * - a = array of n assumptions: a[0 ... n-1] must all be literals
366
 */
367
static void solve(smt_core_t *core, const param_t *params, uint32_t n, const literal_t *a) {
46,185✔
368
  bool luby;
369
  uint32_t c_threshold, d_threshold; // Picosat-style
370
  uint32_t u, v, period;             // for Luby-style
371
  uint64_t reduce_threshold;
372

373
  c_threshold = params->c_threshold;
46,185✔
374
  d_threshold = c_threshold; // required by trace_start in slow_restart mode
46,185✔
375
  luby = false;
46,185✔
376
  u = 1;
46,185✔
377
  v = 1;
46,185✔
378
  period = c_threshold;
46,185✔
379

380
  if (params->fast_restart) {
46,185✔
381
    d_threshold = params->d_threshold;
12,450✔
382
    // HACK to activate the Luby heuristic:
383
    // c_factor must be 0.0 and fast_restart must be true
384
    luby = params->c_factor == 0.0;
12,450✔
385
  }
386

387
  reduce_threshold = params->r_initial_threshold;
46,185✔
388

389
  // initialize then do a propagation + simplification step.
390
  start_search(core, n, a);
46,185✔
391
  trace_start(core);
46,185✔
392
  if (smt_status(core) == YICES_STATUS_SEARCHING) {
46,185✔
393
    // loop
394
    for (;;) {
395
      switch (params->branching) {
48,672✔
396
      case BRANCHING_DEFAULT:
27,788✔
397
        if (luby) {
27,788✔
398
          luby_search(core, c_threshold, &reduce_threshold, params->r_interval);
14,331✔
399
        } else {
400
          search(core, c_threshold, &reduce_threshold, params->r_interval);
13,457✔
401
        }
402
        break;
27,788✔
403
      case BRANCHING_NEGATIVE:
192✔
404
        special_search(core, c_threshold, &reduce_threshold, params->r_interval, negative_branch);
192✔
405
        break;
192✔
406
      case BRANCHING_POSITIVE:
176✔
407
        special_search(core, c_threshold, &reduce_threshold, params->r_interval, positive_branch);
176✔
408
        break;
176✔
409
      case BRANCHING_THEORY:
20,516✔
410
        special_search(core, c_threshold, &reduce_threshold, params->r_interval, theory_branch);
20,516✔
411
        break;
20,516✔
412
      case BRANCHING_TH_NEG:
×
NEW
413
        special_search(core, c_threshold, &reduce_threshold, params->r_interval, theory_or_neg_branch);
×
414
        break;
×
415
      case BRANCHING_TH_POS:
×
NEW
416
        special_search(core, c_threshold, &reduce_threshold, params->r_interval, theory_or_pos_branch);
×
417
        break;
×
418
      }
419

420
      if (smt_status(core) != YICES_STATUS_SEARCHING) break;
48,672✔
421

422
      smt_restart(core);
2,487✔
423
      //      smt_partial_restart_var(core);
424

425
      if (luby) {
2,487✔
426
        // Luby-style restart
427
        if ((u & -u) == v) {
2,097✔
428
          u ++;
1,127✔
429
          v = 1;
1,127✔
430
        } else {
431
          v <<= 1;
970✔
432
        }
433
        c_threshold = v * period;
2,097✔
434
        trace_restart(core);
2,097✔
435

436
      } else {
437
        // Either Minisat or Picosat-like restart
438

439
        // inner restart: increase c_threshold
440
        c_threshold = (uint32_t) (c_threshold * params->c_factor);
390✔
441

442
        if (c_threshold >= d_threshold) {
390✔
443
          d_threshold = c_threshold; // Minisat-style
304✔
444
          if (params->fast_restart) {
304✔
445
            // Picosat style
446
            // outer restart: reset c_threshold and increase d_threshold
447
            c_threshold = params->c_threshold;
47✔
448
            d_threshold = (uint32_t) (d_threshold * params->d_factor);
47✔
449
          }
450
          trace_restart(core);
304✔
451
        } else {
452
          trace_inner_restart(core);
86✔
453
        }
454
      }
455
    }
456
  }
457

458
  trace_done(core);
46,185✔
459
}
46,185✔
460

461

462
/*
463
 * Initialize the search parameters based on params.
464
 */
465
static void context_set_search_parameters(context_t *ctx, const param_t *params) {
46,185✔
466
  smt_core_t *core;
467
  egraph_t *egraph;
468
  simplex_solver_t *simplex;
469
  fun_solver_t *fsolver;
470
  uint32_t quota;
471

472
  /*
473
   * Set core parameters
474
   */
475
  core = ctx->core;
46,185✔
476
  set_randomness(core, params->randomness);
46,185✔
477
  set_random_seed(core, params->random_seed);
46,185✔
478
  set_var_decay_factor(core, params->var_decay);
46,185✔
479
  set_clause_decay_factor(core, params->clause_decay);
46,185✔
480
  if (params->cache_tclauses) {
46,185✔
481
    enable_theory_cache(core, params->tclause_size);
33,715✔
482
  } else {
483
    disable_theory_cache(core);
12,470✔
484
  }
485

486
  /*
487
   * Set egraph parameters
488
   */
489
  egraph = ctx->egraph;
46,185✔
490
  if (egraph != NULL) {
46,185✔
491
    if (params->use_optimistic_fcheck) {
13,483✔
492
      egraph_enable_optimistic_final_check(egraph);
13,480✔
493
    } else {
494
      egraph_disable_optimistic_final_check(egraph);
3✔
495
    }
496
    if (params->use_dyn_ack) {
13,483✔
497
      egraph_enable_dyn_ackermann(egraph, params->max_ackermann);
13,286✔
498
      egraph_set_ackermann_threshold(egraph, params->dyn_ack_threshold);
13,286✔
499
    } else {
500
      egraph_disable_dyn_ackermann(egraph);
197✔
501
    }
502
    if (params->use_bool_dyn_ack) {
13,483✔
503
      egraph_enable_dyn_boolackermann(egraph, params->max_boolackermann);
13,286✔
504
      egraph_set_boolack_threshold(egraph, params->dyn_bool_ack_threshold);
13,286✔
505
    } else {
506
      egraph_disable_dyn_boolackermann(egraph);
197✔
507
    }
508
    quota = egraph_num_terms(egraph) * params->aux_eq_ratio;
13,483✔
509
    if (quota < params->aux_eq_quota) {
13,483✔
510
      quota = params->aux_eq_quota;
13,422✔
511
    }
512
    egraph_set_aux_eq_quota(egraph, quota);
13,483✔
513
    egraph_set_max_interface_eqs(egraph, params->max_interface_eqs);
13,483✔
514
  }
515

516
  if (ctx->mcsat_supplement && egraph != NULL && egraph->th[ETYPE_MCSAT] != NULL) {
46,185✔
517
    mcsat_satellite_set_search_parameters((mcsat_satellite_t *) egraph->th[ETYPE_MCSAT], params);
10✔
518
  }
519

520
  /*
521
   * Set simplex parameters
522
   */
523
  if (context_has_simplex_solver(ctx)) {
46,185✔
524
    simplex = ctx->arith_solver;
33,273✔
525
    if (params->use_simplex_prop) {
33,273✔
526
      simplex_enable_propagation(simplex);
12,886✔
527
      simplex_set_prop_threshold(simplex, params->max_prop_row_size);
12,886✔
528
    }
529
    if (params->adjust_simplex_model) {
33,273✔
530
      simplex_enable_adjust_model(simplex);
12,833✔
531
    }
532
    simplex_set_bland_threshold(simplex, params->bland_threshold);
33,273✔
533
    if (params->integer_check) {
33,273✔
534
      simplex_enable_periodic_icheck(simplex);
×
535
      simplex_set_integer_check_period(simplex, params->integer_check_period);
×
536
    }
537
  }
538

539
  /*
540
   * Set array solver parameters
541
   */
542
  if (context_has_fun_solver(ctx)) {
46,185✔
543
    fsolver = ctx->fun_solver;
12,886✔
544
    fun_solver_set_max_update_conflicts(fsolver, params->max_update_conflicts);
12,886✔
545
    fun_solver_set_max_extensionality(fsolver, params->max_extensionality);
12,886✔
546
  }
547
}
46,185✔
548

549
static smt_status_t _o_call_mcsat_solver(context_t *ctx, const param_t *params) {
1,150✔
550
  smt_status_t stat;
551

552
  mcsat_solve(ctx->mcsat, params, NULL, 0, NULL);
1,150✔
553
  stat = mcsat_status(ctx->mcsat);
1,150✔
554

555
  /*
556
   * For plain UNSAT results (without explicit model assumptions), keep the
557
   * interpolant API usable by providing the canonical false interpolant.
558
   */
559
  if (stat == YICES_STATUS_UNSAT &&
1,466✔
560
      context_supports_model_interpolation(ctx) &&
325✔
561
      mcsat_get_unsat_model_interpolant(ctx->mcsat) == NULL_TERM) {
9✔
562
    mcsat_set_unsat_result_from_labeled_interpolant(ctx->mcsat, false_term, 0, NULL, NULL);
×
563
  }
564

565
  return stat;
1,150✔
566
}
567

568
static smt_status_t call_mcsat_solver(context_t *ctx, const param_t *params) {
1,150✔
569
  MT_PROTECT(smt_status_t, __yices_globals.lock, _o_call_mcsat_solver(ctx, params));
1,150✔
570
}
571

572
/*
573
 * Initialize search parameters then call solve
574
 * - if ctx->status is not IDLE, return the status.
575
 * - if params is NULL, we use default values.
576
 */
577
smt_status_t check_context(context_t *ctx, const param_t *params) {
60,766✔
578
  smt_core_t *core;
579
  smt_status_t stat;
580
  mcsat_satellite_t *sat;
581

582
  if (params == NULL) {
60,766✔
583
    params = get_default_params();
×
584
  }
585

586
  if (ctx->mcsat != NULL) {
60,766✔
587
    return call_mcsat_solver(ctx, params);
1,150✔
588
  }
589

590
  core = ctx->core;
59,616✔
591
  stat = smt_status(core);
59,616✔
592
  if (stat == YICES_STATUS_IDLE) {
59,616✔
593
    // clean state: the search can proceed
594
    context_set_search_parameters(ctx, params);
42,791✔
595
    solve(core, params, 0, NULL);
42,791✔
596
    stat = smt_status(core);
42,791✔
597
  }
598

599
  sat = NULL;
59,616✔
600
  if (ctx->mcsat_supplement &&
59,616✔
601
      ctx->egraph != NULL &&
9✔
602
      ctx->egraph->th[ETYPE_MCSAT] != NULL) {
9✔
603
    sat = (mcsat_satellite_t *) ctx->egraph->th[ETYPE_MCSAT];
9✔
604
  }
605
  if (stat == YICES_STATUS_UNSAT &&
59,616✔
606
      sat != NULL &&
2✔
607
      context_supports_model_interpolation(ctx) &&
2✔
608
      mcsat_satellite_get_unsat_model_interpolant(sat) == NULL_TERM) {
×
609
    mcsat_satellite_set_unsat_model_interpolant(sat, false_term);
×
610
  }
611

612
  return stat;
59,616✔
613
}
614

615

616
/*
617
 * Check with assumptions a[0] ... a[n-1]
618
 * - if ctx->status is not IDLE, return the status.
619
 */
620
smt_status_t check_context_with_assumptions(context_t *ctx, const param_t *params, uint32_t n, const literal_t *a) {
3,394✔
621
  smt_core_t *core;
622
  smt_status_t stat;
623
  mcsat_satellite_t *sat;
624

625
  assert(ctx->mcsat == NULL);
626

627
  core = ctx->core;
3,394✔
628
  stat = smt_status(core);
3,394✔
629
  if (stat == YICES_STATUS_IDLE) {
3,394✔
630
    // clean state
631
    if (params == NULL) {
3,394✔
632
      params = get_default_params();
×
633
    }
634
    context_set_search_parameters(ctx, params);
3,394✔
635
    solve(core, params, n, a);
3,394✔
636
    stat = smt_status(core);
3,394✔
637
  }
638

639
  sat = NULL;
3,394✔
640
  if (ctx->mcsat_supplement &&
3,394✔
641
      ctx->egraph != NULL &&
2✔
642
      ctx->egraph->th[ETYPE_MCSAT] != NULL) {
2✔
643
    sat = (mcsat_satellite_t *) ctx->egraph->th[ETYPE_MCSAT];
2✔
644
  }
645
  if (stat == YICES_STATUS_UNSAT &&
3,394✔
646
      sat != NULL &&
2✔
647
      context_supports_model_interpolation(ctx) &&
2✔
648
      mcsat_satellite_get_unsat_model_interpolant(sat) == NULL_TERM) {
×
649
    mcsat_satellite_set_unsat_model_interpolant(sat, false_term);
×
650
  }
651

652
  return stat;
3,394✔
653
}
654

655
typedef struct sat_delegate_state_s {
656
  delegate_t delegate;
657
  sat_delegate_t mode;
658
  sat_delegate_incremental_mode_t exec_mode;
659
  bool live;
660
  bool stale;
661
  bool true_forwarded;
662
  bool checked_once;
663
  uint32_t delegate_nvars;
664
  uint32_t size;
665
  bvar_t *act_var;
666
  uint32_t *fwd_units;
667
  uint32_t *fwd_bins;
668
  uint32_t *fwd_clauses;
669
  ivector_t assumptions;
670
  ivector_t failed;
671
} sat_delegate_state_t;
672

673
void context_reset_sat_delegate_stats(context_t *ctx) {
23,257✔
674
  ctx->sat_delegate_stats.rebuild_checks = 0;
23,257✔
675
  ctx->sat_delegate_stats.append_checks = 0;
23,257✔
676
  ctx->sat_delegate_stats.selector_frame_checks = 0;
23,257✔
677
  ctx->sat_delegate_stats.delegate_initializations = 0;
23,257✔
678
  ctx->sat_delegate_stats.delegate_reinitializations = 0;
23,257✔
679
  ctx->sat_delegate_stats.selector_variables = 0;
23,257✔
680
  ctx->sat_delegate_stats.selector_assumptions = 0;
23,257✔
681
  ctx->sat_delegate_stats.selector_retirements = 0;
23,257✔
682
  ctx->sat_delegate_stats.post_check_clause_forwards = 0;
23,257✔
683
}
23,257✔
684

685
void context_get_sat_delegate_stats(const context_t *ctx, sat_delegate_stats_t *stats) {
12✔
686
  *stats = ctx->sat_delegate_stats;
12✔
687
}
12✔
688

689
void context_sat_delegate_state_cleanup(context_t *ctx) {
23,256✔
690
  sat_delegate_state_t *st;
691

692
  st = (sat_delegate_state_t *) ctx->sat_delegate_state;
23,256✔
693
  if (st == NULL) {
23,256✔
694
    return;
23,247✔
695
  }
696

697
  if (st->live) {
9✔
698
    delete_delegate(&st->delegate);
9✔
699
    st->live = false;
9✔
700
  }
701
  safe_free(st->act_var);
9✔
702
  safe_free(st->fwd_units);
9✔
703
  safe_free(st->fwd_bins);
9✔
704
  safe_free(st->fwd_clauses);
9✔
705
  delete_ivector(&st->assumptions);
9✔
706
  delete_ivector(&st->failed);
9✔
707
  safe_free(st);
9✔
708
  ctx->sat_delegate_state = NULL;
9✔
709
}
710

711
static sat_delegate_state_t *context_get_sat_delegate_state(context_t *ctx) {
42✔
712
  sat_delegate_state_t *st;
713

714
  st = (sat_delegate_state_t *) ctx->sat_delegate_state;
42✔
715
  if (st == NULL) {
42✔
716
    st = (sat_delegate_state_t *) safe_malloc(sizeof(sat_delegate_state_t));
9✔
717
    st->mode = SAT_DELEGATE_NONE;
9✔
718
    st->exec_mode = SAT_DELEGATE_MODE_REBUILD;
9✔
719
    st->live = false;
9✔
720
    st->stale = false;
9✔
721
    st->true_forwarded = false;
9✔
722
    st->checked_once = false;
9✔
723
    st->delegate_nvars = 0;
9✔
724
    st->size = 0;
9✔
725
    st->act_var = NULL;
9✔
726
    st->fwd_units = NULL;
9✔
727
    st->fwd_bins = NULL;
9✔
728
    st->fwd_clauses = NULL;
9✔
729
    init_ivector(&st->assumptions, 0);
9✔
730
    init_ivector(&st->failed, 0);
9✔
731
    ctx->sat_delegate_state = st;
9✔
732
  }
733
  return st;
42✔
734
}
735

736
static void sat_delegate_state_reset_cursors(sat_delegate_state_t *st) {
11✔
737
  uint32_t i;
738

739
  st->true_forwarded = false;
11✔
740
  for (i=0; i<st->size; i++) {
99✔
741
    st->act_var[i] = 0;
88✔
742
    st->fwd_units[i] = 0;
88✔
743
    st->fwd_bins[i] = 0;
88✔
744
    st->fwd_clauses[i] = 0;
88✔
745
  }
746
}
11✔
747

748
static void sat_delegate_state_grow(sat_delegate_state_t *st, uint32_t min_size) {
52✔
749
  uint32_t old_size, new_size, i;
750

751
  if (st->size > min_size) {
52✔
752
    return;
43✔
753
  }
754

755
  old_size = st->size;
9✔
756
  new_size = old_size == 0 ? 8 : old_size;
9✔
757
  while (new_size <= min_size) {
9✔
758
    new_size <<= 1;
×
759
  }
760

761
  st->act_var = (bvar_t *) safe_realloc(st->act_var, new_size * sizeof(bvar_t));
9✔
762
  st->fwd_units = (uint32_t *) safe_realloc(st->fwd_units, new_size * sizeof(uint32_t));
9✔
763
  st->fwd_bins = (uint32_t *) safe_realloc(st->fwd_bins, new_size * sizeof(uint32_t));
9✔
764
  st->fwd_clauses = (uint32_t *) safe_realloc(st->fwd_clauses, new_size * sizeof(uint32_t));
9✔
765
  for (i=old_size; i<new_size; i++) {
81✔
766
    st->act_var[i] = 0;
72✔
767
    st->fwd_units[i] = 0;
72✔
768
    st->fwd_bins[i] = 0;
72✔
769
    st->fwd_clauses[i] = 0;
72✔
770
  }
771
  st->size = new_size;
9✔
772
}
773

774
static void context_import_delegate_model(smt_core_t *core, delegate_t *d) {
37✔
775
  bvar_t x;
776

777
  for (x=0; x<num_vars(core); x++) {
1,088✔
778
    set_bvar_value(core, x, delegate_get_value(d, x));
1,051✔
779
  }
780
}
37✔
781

782
static void set_delegate_assumption_state(smt_core_t *core, uint32_t n, const literal_t *assumptions,
42✔
783
                                          smt_status_t stat, const ivector_t *failed) {
784
  if (n == 0) {
42✔
785
    core->has_assumptions = false;
3✔
786
    core->num_assumptions = 0;
3✔
787
    core->assumption_index = 0;
3✔
788
    core->assumptions = NULL;
3✔
789
    core->bad_assumption = null_literal;
3✔
790
    return;
3✔
791
  }
792

793
  core->has_assumptions = true;
39✔
794
  core->num_assumptions = n;
39✔
795
  core->assumption_index = n;
39✔
796
  core->assumptions = NULL;
39✔
797
  core->bad_assumption = null_literal;
39✔
798

799
  if (stat == YICES_STATUS_UNSAT && failed != NULL && failed->size > 0) {
39✔
800
    core->bad_assumption = failed->data[0];
5✔
801
  }
802
}
803

804
static void delegate_add_clause_with_guard(delegate_t *delegate, const clause_t *c, literal_t guard) {
10✔
805
  uint32_t i;
806
  literal_t l;
807

808
  ivector_reset(&delegate->buffer);
10✔
809
  if (guard != true_literal) {
10✔
810
    ivector_push(&delegate->buffer, guard);
×
811
  }
812
  i = 0;
10✔
813
  l = c->cl[0];
10✔
814
  while (l >= 0) {
76✔
815
    ivector_push(&delegate->buffer, l);
66✔
816
    i ++;
66✔
817
    l = c->cl[i];
66✔
818
  }
819
  delegate->add_clause(delegate->solver, delegate->buffer.size, delegate->buffer.data);
10✔
820
}
10✔
821

822
static void delegate_forward_clause_range(sat_delegate_state_t *st, smt_core_t *core, sat_delegate_stats_t *stats,
71✔
823
                                          uint32_t level,
824
                                          uint32_t end_units, uint32_t end_bins, uint32_t end_clauses,
825
                                          literal_t guard) {
826
  uint32_t i;
827
  bool forwarded;
828

829
  if (!st->true_forwarded) {
71✔
830
    st->delegate.add_unit_clause(st->delegate.solver, true_literal);
10✔
831
    st->true_forwarded = true;
10✔
832
  }
833

834
  forwarded = (core->inconsistent && st->fwd_units[level] == 0 && st->fwd_bins[level] == 0 && st->fwd_clauses[level] == 0) ||
×
835
              st->fwd_units[level] < end_units ||
71✔
836
              st->fwd_bins[level] < end_bins ||
175✔
837
              st->fwd_clauses[level] < end_clauses;
33✔
838
  if (st->checked_once && forwarded) {
71✔
839
    stats->post_check_clause_forwards ++;
29✔
840
  }
841

842
  if (core->inconsistent && st->fwd_units[level] == 0 && st->fwd_bins[level] == 0 && st->fwd_clauses[level] == 0) {
71✔
843
    if (guard == true_literal) {
×
844
      st->delegate.add_empty_clause(st->delegate.solver);
×
845
    } else {
846
      st->delegate.add_unit_clause(st->delegate.solver, guard);
×
847
    }
848
  }
849

850
  for (i=st->fwd_units[level]; i<end_units; i++) {
333✔
851
    if (guard == true_literal) {
262✔
852
      st->delegate.add_unit_clause(st->delegate.solver, core->stack.lit[i]);
41✔
853
    } else {
854
      st->delegate.add_binary_clause(st->delegate.solver, guard, core->stack.lit[i]);
221✔
855
    }
856
  }
857
  st->fwd_units[level] = end_units;
71✔
858

859
  for (i=st->fwd_bins[level]; i<end_bins; i += 2) {
401✔
860
    if (guard == true_literal) {
330✔
861
      st->delegate.add_binary_clause(st->delegate.solver, core->binary_clauses.data[i], core->binary_clauses.data[i+1]);
97✔
862
    } else {
863
      st->delegate.add_ternary_clause(st->delegate.solver, guard, core->binary_clauses.data[i], core->binary_clauses.data[i+1]);
233✔
864
    }
865
  }
866
  st->fwd_bins[level] = end_bins;
71✔
867

868
  if (level == 0 && st->fwd_clauses[level] > end_clauses) {
71✔
869
    st->fwd_clauses[level] = end_clauses;
×
870
  }
871
  for (i=st->fwd_clauses[level]; i<end_clauses; i++) {
81✔
872
    delegate_add_clause_with_guard(&st->delegate, core->problem_clauses[i], guard);
10✔
873
  }
874
  st->fwd_clauses[level] = end_clauses;
71✔
875
}
71✔
876

877
static void sat_delegate_state_close(sat_delegate_state_t *st) {
1✔
878
  if (st->live) {
1✔
879
    delete_delegate(&st->delegate);
1✔
880
    st->live = false;
1✔
881
  }
882
  st->mode = SAT_DELEGATE_NONE;
1✔
883
  st->exec_mode = SAT_DELEGATE_MODE_REBUILD;
1✔
884
  st->stale = false;
1✔
885
  st->checked_once = false;
1✔
886
  st->delegate_nvars = 0;
1✔
887
  sat_delegate_state_reset_cursors(st);
1✔
888
}
1✔
889

890
static bool context_prepare_append_delegate(context_t *ctx, sat_delegate_state_t *st, const char *sat_solver,
8✔
891
                                            uint32_t verbosity) {
892
  smt_core_t *core;
893
  uint32_t nvars;
894
  uint32_t nnew;
895

896
  core = ctx->core;
8✔
897
  nvars = num_vars(core);
8✔
898

899
  if (st->live && (st->mode != ctx->sat_delegate || st->exec_mode != SAT_DELEGATE_MODE_APPEND)) {
8✔
900
    sat_delegate_state_close(st);
×
901
  }
902

903
  if (!st->live || st->stale) {
8✔
904
    if (st->live) {
5✔
905
      ctx->sat_delegate_stats.delegate_reinitializations ++;
1✔
906
      sat_delegate_state_close(st);
1✔
907
    }
908
    sat_delegate_state_grow(st, 0);
5✔
909
    if (!init_delegate_incremental(&st->delegate, sat_solver, nvars)) {
5✔
910
      return false;
×
911
    }
912
    ctx->sat_delegate_stats.delegate_initializations ++;
5✔
913
    delegate_set_verbosity(&st->delegate, verbosity);
5✔
914
    st->mode = ctx->sat_delegate;
5✔
915
    st->exec_mode = SAT_DELEGATE_MODE_APPEND;
5✔
916
    st->stale = false;
5✔
917
    st->delegate_nvars = nvars;
5✔
918
    st->live = true;
5✔
919
    sat_delegate_state_reset_cursors(st);
5✔
920
  }
921

922
  if (st->delegate_nvars < nvars) {
8✔
923
    nnew = nvars - st->delegate_nvars;
2✔
924
    delegate_add_vars(&st->delegate, nnew);
2✔
925
    st->delegate_nvars = nvars;
2✔
926
  }
927

928
  sat_delegate_state_grow(st, 0);
8✔
929
  delegate_forward_clause_range(st, core, &ctx->sat_delegate_stats, 0, core->nb_unit_clauses,
8✔
930
                                (uint32_t) core->binary_clauses.size,
8✔
931
                                (uint32_t) get_cv_size(core->problem_clauses),
8✔
932
                                true_literal);
933

934
  return true;
8✔
935
}
936

937
static bool context_prepare_selector_delegate(context_t *ctx, sat_delegate_state_t *st, const char *sat_solver,
34✔
938
                                              uint32_t verbosity) {
939
  smt_core_t *core;
940
  uint32_t d, k, nvars, nnew;
941
  uint32_t end_units, end_bins, end_clauses;
942
  trail_t *trail_data;
943
  literal_t guard;
944

945
  core = ctx->core;
34✔
946
  nvars = num_vars(core);
34✔
947
  d = smt_base_level(core);
34✔
948
  trail_data = core->trail_stack.data;
34✔
949

950
  if (st->live && (st->mode != ctx->sat_delegate || st->exec_mode != SAT_DELEGATE_MODE_SELECTOR_FRAMES)) {
34✔
951
    sat_delegate_state_close(st);
×
952
  }
953

954
  if (!st->live) {
34✔
955
    sat_delegate_state_grow(st, d);
5✔
956
    if (!init_delegate_incremental(&st->delegate, sat_solver, nvars)) {
5✔
957
      return false;
×
958
    }
959
    ctx->sat_delegate_stats.delegate_initializations ++;
5✔
960
    delegate_set_verbosity(&st->delegate, verbosity);
5✔
961
    st->mode = ctx->sat_delegate;
5✔
962
    st->exec_mode = SAT_DELEGATE_MODE_SELECTOR_FRAMES;
5✔
963
    st->stale = false;
5✔
964
    st->delegate_nvars = nvars;
5✔
965
    st->live = true;
5✔
966
    sat_delegate_state_reset_cursors(st);
5✔
967
  }
968

969
  if (st->delegate_nvars < nvars) {
34✔
970
    nnew = nvars - st->delegate_nvars;
2✔
971
    delegate_add_vars(&st->delegate, nnew);
2✔
972
    st->delegate_nvars = nvars;
2✔
973
  }
974

975
  sat_delegate_state_grow(st, d);
34✔
976
  for (k=1; k<=d; k++) {
63✔
977
    if (st->act_var[k] == 0) {
29✔
978
      /*
979
       * Selectors must live in the SMT core's variable namespace too:
980
       * otherwise a later bit-blasted assertion could reuse the same bvar.
981
       */
982
      do {
983
        st->act_var[k] = create_boolean_variable(core);
303✔
984
      } while (st->act_var[k] < st->delegate_nvars);
303✔
985
      delegate_add_vars(&st->delegate, st->act_var[k] + 1 - st->delegate_nvars);
27✔
986
      delegate_freeze_literal(&st->delegate, pos_lit(st->act_var[k]));
27✔
987
      ctx->sat_delegate_stats.selector_variables ++;
27✔
988
      st->delegate_nvars = st->act_var[k] + 1;
27✔
989
      st->fwd_units[k] = trail_data[k-1].nunits;
27✔
990
      st->fwd_bins[k] = trail_data[k-1].nbins;
27✔
991
      st->fwd_clauses[k] = trail_data[k-1].nclauses;
27✔
992
    }
993
  }
994

995
  for (k=0; k<=d; k++) {
97✔
996
    guard = (k == 0) ? true_literal : neg_lit(st->act_var[k]);
63✔
997
    end_units = (k < d) ? trail_data[k].nunits : core->nb_unit_clauses;
63✔
998
    end_bins = (k < d) ? trail_data[k].nbins : (uint32_t) core->binary_clauses.size;
63✔
999
    end_clauses = (k < d) ? trail_data[k].nclauses : (uint32_t) get_cv_size(core->problem_clauses);
63✔
1000
    delegate_forward_clause_range(st, core, &ctx->sat_delegate_stats, k, end_units, end_bins, end_clauses, guard);
63✔
1001
  }
1002

1003
  return true;
34✔
1004
}
1005

1006
void context_sat_delegate_state_pop(context_t *ctx, uint32_t level) {
1,575✔
1007
  sat_delegate_state_t *st;
1008

1009
  st = (sat_delegate_state_t *) ctx->sat_delegate_state;
1,575✔
1010
  if (st == NULL || !st->live) {
1,575✔
1011
    return;
1,549✔
1012
  }
1013

1014
  if (st->exec_mode == SAT_DELEGATE_MODE_APPEND) {
26✔
1015
    st->stale = true;
1✔
1016
  } else if (st->exec_mode == SAT_DELEGATE_MODE_SELECTOR_FRAMES) {
25✔
1017
    if (level < st->size && st->act_var[level] != 0) {
25✔
1018
      delegate_melt_literal(&st->delegate, pos_lit(st->act_var[level]));
25✔
1019
      st->delegate.add_unit_clause(st->delegate.solver, neg_lit(st->act_var[level]));
25✔
1020
      ctx->sat_delegate_stats.selector_retirements ++;
25✔
1021
      st->act_var[level] = 0;
25✔
1022
    }
1023
  }
1024
}
1025

1026
static smt_status_t check_with_persistent_delegate(context_t *ctx, const char *sat_solver, uint32_t verbosity,
60✔
1027
                                                   sat_delegate_incremental_mode_t exec_mode,
1028
                                                   uint32_t n, const literal_t *assumptions, ivector_t *failed) {
1029
  smt_status_t stat;
1030
  smt_core_t *core;
1031
  sat_delegate_state_t *st;
1032
  ivector_t visible_failed;
1033
  uint32_t i;
1034

1035
  core = ctx->core;
60✔
1036
  stat = smt_status(core);
60✔
1037
  if (stat != YICES_STATUS_IDLE) {
60✔
1038
    return stat;
×
1039
  }
1040

1041
  start_search(core, 0, NULL);
60✔
1042
  smt_process(core);
60✔
1043
  stat = smt_status(core);
60✔
1044

1045
  assert(stat == YICES_STATUS_UNSAT || stat == YICES_STATUS_SEARCHING ||
1046
         stat == YICES_STATUS_INTERRUPTED);
1047

1048
  if (stat != YICES_STATUS_SEARCHING) {
60✔
1049
    return stat;
×
1050
  }
1051

1052
  if (n == 0 && smt_easy_sat(core)) {
60✔
1053
    stat = YICES_STATUS_SAT;
18✔
1054
    set_smt_status(core, stat);
18✔
1055
    return stat;
18✔
1056
  }
1057

1058
  st = context_get_sat_delegate_state(ctx);
42✔
1059
  if (exec_mode == SAT_DELEGATE_MODE_APPEND) {
42✔
1060
    if (!context_prepare_append_delegate(ctx, st, sat_solver, verbosity)) {
8✔
1061
      return YICES_STATUS_UNKNOWN;
×
1062
    }
1063
  } else {
1064
    assert(exec_mode == SAT_DELEGATE_MODE_SELECTOR_FRAMES);
1065
    if (!context_prepare_selector_delegate(ctx, st, sat_solver, verbosity)) {
34✔
1066
      return YICES_STATUS_UNKNOWN;
×
1067
    }
1068
  }
1069

1070
  if (n > 0 && !delegate_supports_assumptions(&st->delegate)) {
42✔
1071
    return YICES_STATUS_UNKNOWN;
×
1072
  }
1073

1074
  init_ivector(&visible_failed, 0);
42✔
1075
  ivector_reset(&st->assumptions);
42✔
1076
  ivector_reset(&st->failed);
42✔
1077
  if (exec_mode == SAT_DELEGATE_MODE_SELECTOR_FRAMES) {
42✔
1078
    uint32_t k, d;
1079
    d = smt_base_level(core);
34✔
1080
    for (k=1; k<=d; k++) {
63✔
1081
      if (k < st->size && st->act_var[k] != 0) {
29✔
1082
        ivector_push(&st->assumptions, pos_lit(st->act_var[k]));
29✔
1083
        ctx->sat_delegate_stats.selector_assumptions ++;
29✔
1084
      }
1085
    }
1086
  }
1087
  for (i=0; i<n; i++) {
82✔
1088
    ivector_push(&st->assumptions, assumptions[i]);
40✔
1089
  }
1090

1091
  if (st->assumptions.size == 0) {
42✔
1092
    stat = st->delegate.check(st->delegate.solver);
3✔
1093
  } else if (delegate_supports_assumptions(&st->delegate)) {
39✔
1094
    stat = delegate_check_with_assumptions(&st->delegate, st->assumptions.size,
39✔
1095
                                           (literal_t *) st->assumptions.data, &st->failed);
39✔
1096
    if (stat == YICES_STATUS_UNSAT) {
39✔
1097
      for (i=0; i<st->failed.size; i++) {
14✔
1098
        literal_t l = st->failed.data[i];
9✔
1099
        uint32_t j;
1100
        for (j=0; j<n; j++) {
13✔
1101
          if (l == assumptions[j]) {
10✔
1102
            ivector_push(&visible_failed, l);
6✔
1103
            break;
6✔
1104
          }
1105
        }
1106
      }
1107
      if (failed != NULL) {
5✔
1108
        ivector_reset(failed);
5✔
1109
        ivector_add(failed, visible_failed.data, visible_failed.size);
5✔
1110
      }
1111
    }
1112
  } else {
1113
    stat = YICES_STATUS_UNKNOWN;
×
1114
  }
1115

1116
  set_smt_status(core, stat);
42✔
1117
  set_delegate_assumption_state(core, n, assumptions, stat, &visible_failed);
42✔
1118
  if (stat == YICES_STATUS_SAT) {
42✔
1119
    context_import_delegate_model(core, &st->delegate);
37✔
1120
  }
1121
  st->checked_once = true;
42✔
1122

1123
  delete_ivector(&visible_failed);
42✔
1124
  return stat;
42✔
1125
}
1126

1127
static smt_status_t check_with_delegate_assumptions(context_t *ctx, const char *sat_solver, uint32_t verbosity,
1128
                                                    uint32_t n, const literal_t *assumptions, ivector_t *failed);
1129

1130
smt_status_t check_with_sat_delegate(context_t *ctx, const char *sat_solver,
98✔
1131
                                     sat_delegate_incremental_mode_t mode,
1132
                                     uint32_t verbosity, uint32_t n,
1133
                                     const literal_t *assumptions, ivector_t *failed) {
1134
  switch (mode) {
98✔
1135
  case SAT_DELEGATE_MODE_REBUILD:
38✔
1136
    ctx->sat_delegate_stats.rebuild_checks ++;
38✔
1137
    if (n == 0) {
38✔
1138
      return check_with_delegate(ctx, sat_solver, verbosity);
38✔
1139
    } else {
1140
      return check_with_delegate_assumptions(ctx, sat_solver, verbosity, n, assumptions, failed);
×
1141
    }
1142

1143
  case SAT_DELEGATE_MODE_APPEND:
18✔
1144
    ctx->sat_delegate_stats.append_checks ++;
18✔
1145
    return check_with_persistent_delegate(ctx, sat_solver, verbosity, SAT_DELEGATE_MODE_APPEND,
18✔
1146
                                          n, assumptions, failed);
1147

1148
  case SAT_DELEGATE_MODE_SELECTOR_FRAMES:
42✔
1149
    ctx->sat_delegate_stats.selector_frame_checks ++;
42✔
1150
    return check_with_persistent_delegate(ctx, sat_solver, verbosity, SAT_DELEGATE_MODE_SELECTOR_FRAMES,
42✔
1151
                                          n, assumptions, failed);
1152

1153
  default:
×
1154
    return YICES_STATUS_UNKNOWN;
×
1155
  }
1156
}
1157

1158
/*
1159
 * Explore term t and collect all Boolean atoms into atoms.
1160
 */
1161
static void collect_boolean_atoms(context_t *ctx, term_t t, int_hset_t *atoms, int_hset_t *visited) {
64✔
1162
  term_table_t *terms;
1163
  uint32_t i, nchildren;
1164

1165
  if (t < 0) {
64✔
1166
    t = not(t);
×
1167
  }
1168

1169
  if (int_hset_member(visited, t)) {
64✔
1170
    return;
×
1171
  }
1172
  int_hset_add(visited, t);
64✔
1173

1174
  terms = ctx->terms;
64✔
1175
  if (term_type(terms, t) == bool_type(terms->types)) {
64✔
1176
    int_hset_add(atoms, t);
64✔
1177
  }
1178

1179
  if (term_is_projection(terms, t)) {
64✔
1180
    collect_boolean_atoms(ctx, proj_term_arg(terms, t), atoms, visited);
×
1181
  } else if (term_is_sum(terms, t)) {
64✔
1182
    nchildren = term_num_children(terms, t);
×
1183
    for (i=0; i<nchildren; i++) {
×
1184
      term_t child;
1185
      mpq_t q;
1186
      mpq_init(q);
×
1187
      sum_term_component(terms, t, i, q, &child);
×
1188
      collect_boolean_atoms(ctx, child, atoms, visited);
×
1189
      mpq_clear(q);
×
1190
    }
1191
  } else if (term_is_bvsum(terms, t)) {
64✔
1192
    uint32_t nbits = term_bitsize(terms, t);
×
1193
    int32_t *aux = (int32_t*) safe_malloc(nbits * sizeof(int32_t));
×
1194
    nchildren = term_num_children(terms, t);
×
1195
    for (i=0; i<nchildren; i++) {
×
1196
      term_t child;
1197
      bvsum_term_component(terms, t, i, aux, &child);
×
1198
      collect_boolean_atoms(ctx, child, atoms, visited);
×
1199
    }
1200
    safe_free(aux);
×
1201
  } else if (term_is_product(terms, t)) {
64✔
1202
    nchildren = term_num_children(terms, t);
×
1203
    for (i=0; i<nchildren; i++) {
×
1204
      term_t child;
1205
      uint32_t exp;
1206
      product_term_component(terms, t, i, &child, &exp);
×
1207
      collect_boolean_atoms(ctx, child, atoms, visited);
×
1208
    }
1209
  } else if (term_is_composite(terms, t)) {
64✔
1210
    nchildren = term_num_children(terms, t);
34✔
1211
    for (i=0; i<nchildren; i++) {
89✔
1212
      collect_boolean_atoms(ctx, term_child(terms, t, i), atoms, visited);
55✔
1213
    }
1214
  }
1215
}
1216

1217
/*
1218
 * Extract assumptions whose labels appear in term t.
1219
 */
1220
static void core_from_labeled_interpolant(context_t *ctx, term_t t, const ivector_t *labels, const int_hmap_t *label_map, ivector_t *core) {
9✔
1221
  int_hset_t atoms, visited;
1222
  uint32_t i;
1223

1224
  init_int_hset(&atoms, 0);
9✔
1225
  init_int_hset(&visited, 0);
9✔
1226
  collect_boolean_atoms(ctx, t, &atoms, &visited);
9✔
1227

1228
  ivector_reset(core);
9✔
1229
  for (i=0; i<labels->size; i++) {
83✔
1230
    term_t label = labels->data[i];
74✔
1231
    if (int_hset_member(&atoms, label)) {
74✔
1232
      int_hmap_pair_t *p = int_hmap_find((int_hmap_t *) label_map, label);
30✔
1233
      if (p != NULL) {
30✔
1234
        ivector_push(core, p->val);
30✔
1235
      }
1236
    }
1237
  }
1238

1239
  delete_int_hset(&visited);
9✔
1240
  delete_int_hset(&atoms);
9✔
1241
}
9✔
1242

1243
/*
1244
 * Cache a core vector in the context.
1245
 */
1246
static void cache_unsat_core(context_t *ctx, const ivector_t *core) {
3,469✔
1247
  if (ctx->unsat_core_cache == NULL) {
3,469✔
1248
    ctx->unsat_core_cache = (ivector_t *) safe_malloc(sizeof(ivector_t));
3,469✔
1249
    init_ivector(ctx->unsat_core_cache, core->size);
3,469✔
1250
  } else {
1251
    ivector_reset(ctx->unsat_core_cache);
×
1252
  }
1253
  ivector_copy(ctx->unsat_core_cache, core->data, core->size);
3,469✔
1254
}
3,469✔
1255

1256
static void cache_failed_assumptions_core(context_t *ctx, uint32_t n, const term_t *a,
5✔
1257
                                          const ivector_t *assumption_literals,
1258
                                          const ivector_t *failed_literals) {
1259
  ivector_t core_terms;
1260
  int_hset_t failed;
1261
  uint32_t i;
1262

1263
  init_ivector(&core_terms, 0);
5✔
1264
  init_int_hset(&failed, 0);
5✔
1265
  for (i=0; i<failed_literals->size; i++) {
11✔
1266
    int_hset_add(&failed, failed_literals->data[i]);
6✔
1267
  }
1268
  for (i=0; i<n; i++) {
11✔
1269
    if (int_hset_member(&failed, assumption_literals->data[i])) {
6✔
1270
      ivector_push(&core_terms, a[i]);
6✔
1271
    }
1272
  }
1273
  cache_unsat_core(ctx, &core_terms);
5✔
1274
  delete_int_hset(&failed);
5✔
1275
  delete_ivector(&core_terms);
5✔
1276
}
5✔
1277

1278
/*
1279
 * MCSAT variant of check_context_with_term_assumptions.
1280
 * Caller must hold __yices_globals.lock.
1281
 */
1282
static smt_status_t _o_check_context_with_term_assumptions_mcsat(context_t *ctx, const param_t *params, uint32_t n, const term_t *a, int32_t *error) {
10✔
1283
  smt_status_t stat;
1284
  ivector_t assumptions;
1285
  uint32_t i;
1286

1287
  /*
1288
   * MCSAT: create fresh labels b_i, assert (b_i => a_i), then solve with model b_i=true.
1289
   * We extract interpolant/core before cleanup, then restore sticky UNSAT artifacts.
1290
   */
1291
  if (!context_supports_model_interpolation(ctx)) {
10✔
1292
    if (error != NULL) {
×
1293
      *error = CTX_OPERATION_NOT_SUPPORTED;
×
1294
    }
1295
    return YICES_STATUS_ERROR;
×
1296
  }
1297

1298
  {
1299
    model_t mdl;               // temporary model: sets all label terms b_i to true
1300
    int_hmap_t label_map;      // map label b_i -> original assumption a_i
1301
    ivector_t mapped_core;     // translated core over original assumptions
1302
    term_t interpolant = NULL_TERM; // raw/substituted interpolant for sticky UNSAT result
10✔
1303
    int32_t code;              // return code from assert_formula (negative on internalization error)
1304
    bool pushed;               // whether we pushed a temporary scope and must pop it
1305
    term_manager_t tm;
1306

1307
    init_model(&mdl, ctx->terms, true);
10✔
1308
    init_int_hmap(&label_map, 0);
10✔
1309
    init_ivector(&assumptions, n);
10✔
1310
    init_ivector(&mapped_core, 0);
10✔
1311
    init_term_manager(&tm, ctx->terms);
10✔
1312
    stat = YICES_STATUS_IDLE;
10✔
1313

1314
    pushed = false;
10✔
1315
    if (context_supports_pushpop(ctx)) {
10✔
1316
      context_push(ctx);
9✔
1317
      pushed = true;
9✔
1318
    }
1319

1320
    for (i=0; i<n; i++) {
85✔
1321
      term_t b = new_uninterpreted_term(ctx->terms, bool_id);
75✔
1322
      term_t implication = mk_implies(&tm, b, a[i]);
75✔
1323

1324
      int_hmap_add(&label_map, b, a[i]);
75✔
1325
      code = _o_assert_formula(ctx, implication);
75✔
1326
      if (code < 0) {
75✔
1327
        if (error != NULL) {
×
1328
          *error = code;
×
1329
        }
1330
        stat = YICES_STATUS_ERROR;
×
1331
        break;
×
1332
      }
1333
      model_map_term(&mdl, b, vtbl_mk_bool(&mdl.vtbl, true));
75✔
1334
      ivector_push(&assumptions, b);
75✔
1335
    }
1336

1337
    if (stat != YICES_STATUS_ERROR) {
10✔
1338
      stat = check_context_with_model(ctx, params, &mdl, n, assumptions.data);
10✔
1339
      if (stat == YICES_STATUS_UNSAT) {
10✔
1340
        interpolant = context_get_unsat_model_interpolant(ctx);
9✔
1341
        assert(interpolant != NULL_TERM);
1342
        core_from_labeled_interpolant(ctx, interpolant, &assumptions, &label_map, &mapped_core);
9✔
1343
      }
1344
    }
1345

1346
    if (pushed) {
10✔
1347
      mcsat_cleanup_assumptions(ctx->mcsat);
9✔
1348
      context_pop(ctx);
9✔
1349
    }
1350
    if (stat == YICES_STATUS_UNSAT) {
10✔
1351
      mcsat_set_unsat_result_from_labeled_interpolant(ctx->mcsat, interpolant, n, assumptions.data, a);
9✔
1352
      cache_unsat_core(ctx, &mapped_core);
9✔
1353
    }
1354

1355
    delete_term_manager(&tm);
10✔
1356
    delete_ivector(&mapped_core);
10✔
1357
    delete_ivector(&assumptions);
10✔
1358
    delete_int_hmap(&label_map);
10✔
1359
    delete_model(&mdl);
10✔
1360

1361
    return stat;
10✔
1362
  }
1363
}
1364

1365
static smt_status_t check_context_with_term_assumptions_mcsat(context_t *ctx, const param_t *params, uint32_t n, const term_t *a, int32_t *error) {
10✔
1366
  MT_PROTECT(smt_status_t, __yices_globals.lock, _o_check_context_with_term_assumptions_mcsat(ctx, params, n, a, error));
10✔
1367
}
1368

1369
/*
1370
 * Supplemental-MCSAT variant for term assumptions in CDCL(T) mode.
1371
 * We encode assumptions via fresh labels b_i with implications (b_i => a_i),
1372
 * then solve under assumptions b_i = true.
1373
 *
1374
 * Labels are kept in the context (no push/pop) so the regular context status
1375
 * and multicheck protocol remain unchanged.
1376
 */
1377
static smt_status_t _o_check_context_with_term_assumptions_supplement(context_t *ctx, const param_t *params, uint32_t n, const term_t *a, int32_t *error) {
2✔
1378
  smt_status_t stat;
1379
  ivector_t assumptions;
1380
  term_t interpolant;
1381
  uint32_t i;
1382
  literal_t l;
1383
  mcsat_satellite_t *sat;
1384

1385
  init_ivector(&assumptions, n);
2✔
1386

1387
  stat = YICES_STATUS_IDLE;
2✔
1388
  interpolant = NULL_TERM;
2✔
1389
  sat = NULL;
2✔
1390

1391
  if (ctx->mcsat_supplement &&
2✔
1392
      ctx->egraph != NULL &&
2✔
1393
      ctx->egraph->th[ETYPE_MCSAT] != NULL) {
2✔
1394
    sat = (mcsat_satellite_t *) ctx->egraph->th[ETYPE_MCSAT];
2✔
1395
  }
1396

1397
  for (i=0; i<n; i++) {
6✔
1398
    l = context_add_assumption(ctx, a[i]);
4✔
1399
    if (l < 0) {
4✔
1400
      if (error != NULL) {
×
1401
        *error = l;
×
1402
      }
1403
      stat = YICES_STATUS_ERROR;
×
1404
      break;
×
1405
    }
1406

1407
    ivector_push(&assumptions, l);
4✔
1408
  }
1409

1410
  if (stat != YICES_STATUS_ERROR) {
2✔
1411
    stat = check_context_with_assumptions(ctx, params, assumptions.size, (const literal_t *) assumptions.data);
2✔
1412
    if (stat == YICES_STATUS_UNSAT) {
2✔
1413
      if (sat != NULL) {
2✔
1414
        interpolant = mcsat_satellite_compute_unsat_model_interpolant(sat, params, n, a);
2✔
1415
      }
1416
      if (interpolant == NULL_TERM && context_supports_model_interpolation(ctx)) {
2✔
1417
        interpolant = context_get_unsat_model_interpolant(ctx);
×
1418
      }
1419
      if (interpolant == NULL_TERM && context_supports_model_interpolation(ctx)) {
2✔
1420
        interpolant = false_term;
×
1421
      }
1422
    }
1423
  }
1424

1425
  if (stat == YICES_STATUS_UNSAT && interpolant != NULL_TERM && sat != NULL) {
2✔
1426
    mcsat_satellite_set_unsat_model_interpolant(sat, interpolant);
×
1427
  }
1428

1429
  delete_ivector(&assumptions);
2✔
1430

1431
  return stat;
2✔
1432
}
1433

1434
static smt_status_t check_context_with_term_assumptions_supplement(context_t *ctx, const param_t *params, uint32_t n, const term_t *a, int32_t *error) {
2✔
1435
  /*
1436
   * Do not MT_PROTECT the whole CDCL(T) search here.  The supplemental MCSAT
1437
   * satellite serializes only its embedded MCSAT/term-construction calls.
1438
   */
1439
  return _o_check_context_with_term_assumptions_supplement(ctx, params, n, a, error);
2✔
1440
}
1441

1442
/*
1443
 * Check under assumptions given as terms.
1444
 * - if MCSAT is enabled, this uses temporary labels + model interpolation.
1445
 * - otherwise terms are converted to literals and handled by the CDCL(T) path.
1446
 *
1447
 * Preconditions:
1448
 * - context status must be IDLE.
1449
 */
1450
smt_status_t check_context_with_term_assumptions(context_t *ctx, const param_t *params, uint32_t n, const term_t *a, int32_t *error) {
3,444✔
1451
  if (error != NULL) {
3,444✔
1452
    *error = CTX_NO_ERROR;
3,444✔
1453
  }
1454

1455
  /*
1456
   * Clear any prior term-assumption core before all paths below. Delegate
1457
   * checks cache a new core only on UNSAT.
1458
   */
1459
  context_invalidate_unsat_core_cache(ctx);
3,444✔
1460

1461
  if (ctx->mcsat == NULL) {
3,444✔
1462
    if (ctx->mcsat_supplement) {
3,434✔
1463
      return check_context_with_term_assumptions_supplement(ctx, params, n, a, error);
2✔
1464
    }
1465
    smt_status_t stat;
1466
    sat_delegate_t mode;
1467
    sat_delegate_incremental_mode_t exec_mode;
1468
    bool one_shot;
1469
    const char *delegate;
1470
    bool unknown;
1471
    ivector_t assumptions;
1472
    ivector_t failed;
1473
    uint32_t i;
1474
    literal_t l;
1475

1476
    init_ivector(&assumptions, n);
3,432✔
1477
    for (i=0; i<n; i++) {
106,709✔
1478
      l = context_add_assumption(ctx, a[i]);
103,277✔
1479
      if (l < 0) {
103,277✔
1480
        if (error != NULL) {
×
1481
          *error = l;
×
1482
        }
1483
        delete_ivector(&assumptions);
×
1484
        return YICES_STATUS_ERROR;
×
1485
      }
1486
      ivector_push(&assumptions, l);
103,277✔
1487
    }
1488

1489
    mode = effective_sat_delegate_mode(ctx->sat_delegate, params, &one_shot);
3,432✔
1490
    delegate = sat_delegate_name(mode);
3,432✔
1491
    if (delegate == NULL) {
3,432✔
1492
      stat = check_context_with_assumptions(ctx, params, n, assumptions.data);
3,392✔
1493
      delete_ivector(&assumptions);
3,392✔
1494
      return stat;
3,392✔
1495
    }
1496

1497
    if (ctx->logic != QF_BV) {
40✔
1498
      if (error != NULL) {
×
1499
        *error = CTX_OPERATION_NOT_SUPPORTED;
×
1500
      }
1501
      delete_ivector(&assumptions);
×
1502
      return YICES_STATUS_ERROR;
×
1503
    }
1504

1505
    if (!supported_delegate(delegate, &unknown)) {
40✔
1506
      if (error != NULL) {
×
1507
        *error = unknown ? CTX_UNKNOWN_DELEGATE : CTX_DELEGATE_NOT_AVAILABLE;
×
1508
      }
1509
      delete_ivector(&assumptions);
×
1510
      return YICES_STATUS_ERROR;
×
1511
    }
1512

1513
    if (!delegate_supports_assumptions_name(delegate)) {
40✔
1514
      if (error != NULL) {
1✔
1515
        *error = CTX_OPERATION_NOT_SUPPORTED;
1✔
1516
      }
1517
      delete_ivector(&assumptions);
1✔
1518
      return YICES_STATUS_ERROR;
1✔
1519
    }
1520

1521
    init_ivector(&failed, 0);
39✔
1522
    if (!effective_sat_delegate_incremental_mode(mode, ctx->sat_delegate_incremental_mode,
39✔
1523
                                                ctx->sat_delegate_incremental_mode_set,
39✔
1524
                                                ctx->mode == CTX_MODE_ONECHECK,
39✔
1525
                                                one_shot, &exec_mode)) {
1526
      if (error != NULL) {
×
1527
        *error = CTX_OPERATION_NOT_SUPPORTED;
×
1528
      }
1529
      delete_ivector(&failed);
×
1530
      delete_ivector(&assumptions);
×
1531
      return YICES_STATUS_ERROR;
×
1532
    }
1533
    stat = check_with_sat_delegate(ctx, delegate, exec_mode, 0, n, assumptions.data, &failed);
39✔
1534
    if (stat == YICES_STATUS_UNSAT) {
39✔
1535
      cache_failed_assumptions_core(ctx, n, a, &assumptions, &failed);
5✔
1536
    }
1537
    delete_ivector(&failed);
39✔
1538
    delete_ivector(&assumptions);
39✔
1539
    return stat;
39✔
1540
  }
1541

1542
  return check_context_with_term_assumptions_mcsat(ctx, params, n, a, error);
10✔
1543
}
1544

1545
/*
1546
 * Check with given model
1547
 * - if mcsat status is not IDLE, return the status
1548
 */
1549
smt_status_t check_context_with_model(context_t *ctx, const param_t *params, model_t* mdl, uint32_t n, const term_t t[]) {
161✔
1550
  smt_status_t stat;
1551

1552
  assert(ctx->mcsat != NULL);
1553

1554
  stat = mcsat_status(ctx->mcsat);
161✔
1555
  if (stat == YICES_STATUS_IDLE) {
161✔
1556
    mcsat_solve(ctx->mcsat, params, mdl, n, t);
161✔
1557
    stat = mcsat_status(ctx->mcsat);
161✔
1558

1559
    // BD: this looks wrong. We shouldn't call clear yet.
1560
    // we want the status to remain STATUS_UNSAT until the next call to check or assert.
1561
    //    if (n > 0 && stat == STATUS_UNSAT && context_supports_multichecks(ctx)) {
1562
    //      context_clear(ctx);
1563
    //    }
1564
  }
1565

1566
  if (stat == YICES_STATUS_UNSAT && n == 0 &&
165✔
1567
      context_supports_model_interpolation(ctx) &&
6✔
1568
      mcsat_get_unsat_model_interpolant(ctx->mcsat) == NULL_TERM) {
2✔
1569
    // With no model assumptions, false is the canonical interpolant.
1570
    mcsat_set_unsat_result_from_labeled_interpolant(ctx->mcsat, false_term, 0, NULL, NULL);
×
1571
  }
1572

1573
  return stat;
161✔
1574
}
1575

1576
/*
1577
 * Check with given model and hints
1578
 * - set the model hint and call check_context_with_model
1579
 */
1580
smt_status_t check_context_with_model_and_hint(context_t *ctx, const param_t *params, model_t* mdl, uint32_t n, const term_t t[], uint32_t m) {
14✔
1581
  assert(m <= n);
1582

1583
  mcsat_set_model_hint(ctx->mcsat, mdl, n, t);
14✔
1584

1585
  return check_context_with_model(ctx, params, mdl, m, t);
14✔
1586
}
1587

1588

1589
/*
1590
 * Precheck: force generation of clauses and other stuff that's
1591
 * constructed lazily by the solvers. For example, this
1592
 * can be used to convert all the constraints asserted in the
1593
 * bitvector to clauses so that we can export the result to DIMACS.
1594
 *
1595
 * If ctx status is IDLE:
1596
 * - the function calls 'start_search' and does one round of propagation.
1597
 * - if this results in UNSAT, the function returns UNSAT
1598
 * - if the precheck is interrupted, the function returns INTERRUPTED
1599
 * - otherwise the function returns UNKNOWN and sets the status to
1600
 *   UNKNOWN.
1601
 *
1602
 * IMPORTANT: call smt_clear or smt_cleanup to restore the context to
1603
 * IDLE before doing anything else with this context.
1604
 *
1605
 * If ctx status is not IDLE, the function returns it and does nothing
1606
 * else.
1607
 */
1608
smt_status_t precheck_context(context_t *ctx) {
×
1609
  smt_status_t stat;
1610
  smt_core_t *core;
1611

1612
  core = ctx->core;
×
1613

1614
  stat = smt_status(core);
×
1615
  if (stat == YICES_STATUS_IDLE) {
×
1616
    start_search(core, 0, NULL);
×
1617
    smt_process(core);
×
1618
    stat = smt_status(core);
×
1619

1620
    assert(stat == YICES_STATUS_UNSAT || stat == YICES_STATUS_SEARCHING ||
1621
           stat == YICES_STATUS_INTERRUPTED);
1622

1623
    if (stat == YICES_STATUS_SEARCHING) {
×
1624
      end_search_unknown(core);
×
1625
      stat = YICES_STATUS_UNKNOWN;
×
1626
    }
1627
  }
1628

1629
  return stat;
×
1630
}
1631

1632

1633

1634
/*
1635
 * Solve using another SAT solver
1636
 * - sat_solver = name of the solver to use
1637
 * - verbosity = verbosity level (0 means quiet)
1638
 * - this may be used only for BV or pure SAT problems
1639
 * - we perform one round of propagation to convert the problem to CNF
1640
 * - then we call an external SAT solver on the CNF problem
1641
 */
1642
smt_status_t check_with_delegate(context_t *ctx, const char *sat_solver, uint32_t verbosity) {
38✔
1643
  smt_status_t stat;
1644
  smt_core_t *core;
1645
  delegate_t delegate;
1646
  bvar_t x;
1647
  bval_t v;
1648

1649
  core = ctx->core;
38✔
1650

1651
  stat = smt_status(core);
38✔
1652
  if (stat == YICES_STATUS_IDLE) {
38✔
1653
    start_search(core, 0, NULL);
38✔
1654
    smt_process(core);
38✔
1655
    stat = smt_status(core);
38✔
1656

1657
    assert(stat == YICES_STATUS_UNSAT || stat == YICES_STATUS_SEARCHING ||
1658
           stat == YICES_STATUS_INTERRUPTED);
1659

1660
    if (stat == YICES_STATUS_SEARCHING) {
38✔
1661
      if (smt_easy_sat(core)) {
36✔
1662
        stat = YICES_STATUS_SAT;
36✔
1663
      } else {
1664
        // call the delegate
1665
        init_delegate(&delegate, sat_solver, num_vars(core));
×
1666
        ctx->sat_delegate_stats.delegate_initializations ++;
×
1667
        delegate_set_verbosity(&delegate, verbosity);
×
1668

1669
        stat = solve_with_delegate(&delegate, core);
×
1670
        set_smt_status(core, stat);
×
1671
        if (stat == YICES_STATUS_SAT) {
×
1672
          for (x=0; x<num_vars(core); x++) {
×
1673
            v = delegate_get_value(&delegate, x);
×
1674
            set_bvar_value(core, x, v);
×
1675
          }
1676
        }
1677
        delete_delegate(&delegate);
×
1678
      }
1679
    }
1680
  }
1681

1682
  return stat;
38✔
1683
}
1684

1685
/*
1686
 * One-shot check with delegate and assumptions.
1687
 * - assumptions are literals in core encoding.
1688
 * - if failed != NULL and result is UNSAT, failed assumptions are appended to *failed.
1689
 */
1690
static smt_status_t check_with_delegate_assumptions(context_t *ctx, const char *sat_solver, uint32_t verbosity,
×
1691
                                                    uint32_t n, const literal_t *assumptions, ivector_t *failed) {
1692
  smt_status_t stat;
1693
  smt_core_t *core;
1694
  delegate_t delegate;
1695

1696
  core = ctx->core;
×
1697

1698
  stat = smt_status(core);
×
1699
  if (stat != YICES_STATUS_IDLE) {
×
1700
    return stat;
×
1701
  }
1702

1703
  start_search(core, 0, NULL);
×
1704
  smt_process(core);
×
1705
  stat = smt_status(core);
×
1706

1707
  assert(stat == YICES_STATUS_UNSAT || stat == YICES_STATUS_SEARCHING ||
1708
         stat == YICES_STATUS_INTERRUPTED);
1709

1710
  if (stat != YICES_STATUS_SEARCHING) {
×
1711
    return stat;
×
1712
  }
1713

1714
  if (!init_delegate(&delegate, sat_solver, num_vars(core))) {
×
1715
    return YICES_STATUS_UNKNOWN;
×
1716
  }
1717
  ctx->sat_delegate_stats.delegate_initializations ++;
×
1718
  delegate_set_verbosity(&delegate, verbosity);
×
1719

1720
  stat = solve_with_delegate_assumptions(&delegate, core, n, assumptions, failed);
×
1721
  set_smt_status(core, stat);
×
1722
  set_delegate_assumption_state(core, n, assumptions, stat, failed);
×
1723
  if (stat == YICES_STATUS_SAT) {
×
1724
    context_import_delegate_model(core, &delegate);
×
1725
  }
1726

1727
  delete_delegate(&delegate);
×
1728
  return stat;
×
1729
}
1730

1731

1732
/*
1733
 * Bit-blast then export to DIMACS
1734
 * - filename = name of the output file
1735
 * - status = status of the context after bit-blasting
1736
 *
1737
 * If ctx status is IDLE
1738
 * - perform one round of propagation to conver the problem to CNF
1739
 * - export the CNF to DIMACS
1740
 *
1741
 * If ctx status is not IDLE,
1742
 * - store the stauts in *status and do nothing else
1743
 *
1744
 * Return code:
1745
 *  1 if the DIMACS file was created
1746
 *  0 if the problem was solved by the propagation round
1747
 * -1 if there was an error in creating or writing to the file.
1748
 */
1749
int32_t bitblast_then_export_to_dimacs(context_t *ctx, const char *filename, smt_status_t *status) {
×
1750
  smt_core_t *core;
1751
  FILE *f;
1752
  smt_status_t stat;
1753
  int32_t code;
1754

1755
  core = ctx->core;
×
1756

1757
  code = 0;
×
1758
  stat = smt_status(core);
×
1759
  if (stat == YICES_STATUS_IDLE) {
×
1760
    start_search(core, 0, NULL);
×
1761
    smt_process(core);
×
1762
    stat = smt_status(core);
×
1763

1764
    assert(stat == YICES_STATUS_UNSAT || stat == YICES_STATUS_SEARCHING ||
1765
           stat == YICES_STATUS_INTERRUPTED);
1766

1767
    if (stat == YICES_STATUS_SEARCHING) {
×
1768
      code = 1;
×
1769
      f = fopen(filename, "w");
×
1770
      if (f == NULL) {
×
1771
        code = -1;
×
1772
      } else {
1773
        dimacs_print_bvcontext(f, ctx);
×
1774
        if (ferror(f)) code = -1;
×
1775
        fclose(f);
×
1776
      }
1777
    }
1778
  }
1779

1780
  *status = stat;
×
1781

1782
  return code;
×
1783
}
1784

1785

1786
/*
1787
 * Simplify then export to Dimacs:
1788
 * - filename = name of the output file
1789
 * - status = status of the context after CNF conversion + preprocessing
1790
 *
1791
 * If ctx status is IDLE
1792
 * - perform one round of propagation to convert the problem to CNF
1793
 * - export the CNF to y2sat for extra preprocessing then export that to DIMACS
1794
 *
1795
 * If ctx status is not IDLE, the function stores that in *status
1796
 * If y2sat preprocessing solves the formula, return the status also in *status
1797
 *
1798
 * Return code:
1799
 *  1 if the DIMACS file was created
1800
 *  0 if the problems was solved by preprocessing (or if ctx status is not IDLE)
1801
 * -1 if there was an error creating or writing to the file.
1802
 */
1803
int32_t process_then_export_to_dimacs(context_t *ctx, const char *filename, smt_status_t *status) {
×
1804
  smt_core_t *core;
1805
  FILE *f;
1806
  smt_status_t stat;
1807
  delegate_t delegate;
1808
  bvar_t x;
1809
  bval_t v;
1810
  int32_t code;
1811

1812
  core = ctx->core;
×
1813

1814
  code = 0;
×
1815
  stat = smt_status(core);
×
1816
  if (stat == YICES_STATUS_IDLE) {
×
1817
    start_search(core, 0, NULL);
×
1818
    smt_process(core);
×
1819
    stat = smt_status(core);
×
1820

1821
    assert(stat == YICES_STATUS_UNSAT || stat == YICES_STATUS_SEARCHING ||
1822
           stat == YICES_STATUS_INTERRUPTED);
1823

1824
    if (stat == YICES_STATUS_SEARCHING) {
×
1825
      if (smt_easy_sat(core)) {
×
1826
        stat = YICES_STATUS_SAT;
×
1827
      } else {
1828
        // call the delegate
1829
        init_delegate(&delegate, "y2sat", num_vars(core));
×
1830
        delegate_set_verbosity(&delegate, 0);
×
1831

1832
        stat = preprocess_with_delegate(&delegate, core);
×
1833
        set_smt_status(core, stat);
×
1834
        if (stat == YICES_STATUS_SAT) {
×
1835
          for (x=0; x<num_vars(core); x++) {
×
1836
            v = delegate_get_value(&delegate, x);
×
1837
            set_bvar_value(core, x, v);
×
1838
          }
1839
        } else if (stat == YICES_STATUS_UNKNOWN) {
×
1840
          code = 1;
×
1841
          f = fopen(filename, "w");
×
1842
          if (f == NULL) {
×
1843
            code = -1;
×
1844
          } else {
1845
            export_to_dimacs_with_delegate(&delegate, f);
×
1846
            if (ferror(f)) code = -1;
×
1847
            fclose(f);
×
1848
          }
1849
        }
1850

1851
        delete_delegate(&delegate);
×
1852
      }
1853
    }
1854
  }
1855

1856
  *status = stat;
×
1857

1858
  return code;
×
1859
}
1860

1861

1862

1863
/*
1864
 * MODEL CONSTRUCTION
1865
 */
1866

1867
/*
1868
 * Value of literal l in ctx->core
1869
 */
1870
static value_t bool_value(context_t *ctx, value_table_t *vtbl, literal_t l) {
65,450✔
1871
  value_t v;
1872

1873
  v = null_value; // prevent GCC warning
65,450✔
1874
  switch (literal_value(ctx->core, l)) {
65,450✔
1875
  case VAL_FALSE:
38,884✔
1876
    v = vtbl_mk_false(vtbl);
38,884✔
1877
    break;
38,884✔
1878
  case VAL_UNDEF_FALSE:
×
1879
  case VAL_UNDEF_TRUE:
1880
    v = vtbl_mk_unknown(vtbl);
×
1881
    break;
×
1882
  case VAL_TRUE:
26,566✔
1883
    v = vtbl_mk_true(vtbl);
26,566✔
1884
    break;
26,566✔
1885
  }
1886
  return v;
65,450✔
1887
}
1888

1889

1890
/*
1891
 * Value of arithmetic variable x in ctx->arith_solver
1892
 */
1893
static value_t arith_value(context_t *ctx, value_table_t *vtbl, thvar_t x) {
22,641✔
1894
  rational_t *a;
1895
  value_t v;
1896

1897
  assert(context_has_arith_solver(ctx));
1898

1899
  a = &ctx->aux;
22,641✔
1900
  if (ctx->arith.value_in_model(ctx->arith_solver, x, a)) {
22,641✔
1901
    v = vtbl_mk_rational(vtbl, a);
22,641✔
1902
  } else {
1903
    v = vtbl_mk_unknown(vtbl);
×
1904
  }
1905

1906
  return v;
22,641✔
1907
}
1908

1909

1910

1911
/*
1912
 * Value of bitvector variable x in ctx->bv_solver
1913
 */
1914
static value_t bv_value(context_t *ctx, value_table_t *vtbl, thvar_t x) {
18,168✔
1915
  bvconstant_t *b;
1916
  value_t v;
1917

1918
  assert(context_has_bv_solver(ctx));
1919

1920
  b = &ctx->bv_buffer;
18,168✔
1921
  if (ctx->bv.value_in_model(ctx->bv_solver, x, b)) {
18,168✔
1922
    v = vtbl_mk_bv_from_constant(vtbl, b);
18,168✔
1923
  } else {
1924
    v = vtbl_mk_unknown(vtbl);
×
1925
  }
1926

1927
  return v;
18,168✔
1928
}
1929

1930

1931
/*
1932
 * Get a value for term t in the solvers or egraph
1933
 * - attach the mapping from t to that value in model
1934
 * - if we don't have a concrete object for t but t is
1935
 *   mapped to a term u and the model->has_alias is true,
1936
 *   then we store the mapping [t --> u] in the model's
1937
 *   alias map.
1938
 */
1939
static void build_term_value(context_t *ctx, model_t *model, term_t t, mcsat_satellite_t *mcsat_model) {
323,155✔
1940
  value_table_t *vtbl;
1941
  term_t r;
1942
  uint32_t polarity;
1943
  int32_t x;
1944
  type_t tau;
1945
  value_t v;
1946

1947
  if (mcsat_model != NULL && model_find_term_value(model, t) != null_value) {
323,155✔
1948
    return;
29✔
1949
  }
1950

1951
  /*
1952
   * Get the root of t in the substitution table
1953
   */
1954
  r = intern_tbl_get_root(&ctx->intern, t);
323,126✔
1955
  if (intern_tbl_root_is_mapped(&ctx->intern, r)) {
323,126✔
1956
    /*
1957
     * r is mapped to some object x in egraph/core/or theory solvers
1958
     * - keep track of polarity then force r to positive polarity
1959
     */
1960
    vtbl = model_get_vtbl(model);
111,110✔
1961
    polarity = polarity_of(r);
111,110✔
1962
    r = unsigned_term(r);
111,110✔
1963

1964
    /*
1965
     * Convert x to a concrete value
1966
     */
1967
    x = intern_tbl_map_of_root(&ctx->intern, r);
111,110✔
1968
    if (code_is_eterm(x)) {
111,110✔
1969
      // x refers to an egraph object or true_occ/false_occ
1970
      if (x == bool2code(true)) {
4,846✔
1971
        v = vtbl_mk_true(vtbl);
481✔
1972
      } else if (x == bool2code(false)) {
4,365✔
1973
        v = vtbl_mk_false(vtbl);
1,480✔
1974
      } else {
1975
        assert(context_has_egraph(ctx));
1976
        v = egraph_get_value(ctx->egraph, vtbl, code2occ(x));
2,885✔
1977
      }
1978

1979
    } else {
1980
      // x refers to a literal or a theory variable
1981
      tau = term_type(ctx->terms, r);
106,264✔
1982
      switch (type_kind(ctx->types, tau)) {
106,264✔
1983
      case BOOL_TYPE:
65,450✔
1984
        v = bool_value(ctx, vtbl, code2literal(x));
65,450✔
1985
        break;
65,450✔
1986

1987
      case INT_TYPE:
22,646✔
1988
      case REAL_TYPE:
1989
        if (mcsat_model != NULL) {
22,646✔
1990
          if (!mcsat_satellite_term_value(mcsat_model, model, r, &v)) {
5✔
1991
            assert(false && "MCSAT supplement has no value for an arithmetic model term");
1992
            v = vtbl_mk_unknown(vtbl);
×
1993
          }
1994
        } else {
1995
          v = arith_value(ctx, vtbl, code2thvar(x));
22,641✔
1996
        }
1997
        break;
22,646✔
1998

1999
      case BITVECTOR_TYPE:
18,168✔
2000
        v = bv_value(ctx, vtbl, code2thvar(x));
18,168✔
2001
        break;
18,168✔
2002

2003
      default:
×
2004
        /*
2005
         * This should never happen:
2006
         * scalar, uninterpreted, tuple, function terms
2007
         * are mapped to egraph terms.
2008
         */
2009
        assert(false);
2010
        v = vtbl_mk_unknown(vtbl); // prevent GCC warning
×
2011
        break;
×
2012
      }
2013
    }
2014

2015
    /*
2016
     * Restore polarity then add mapping [t --> v] in the model
2017
     */
2018
    if (! object_is_unknown(vtbl, v)) {
111,110✔
2019
      if (object_is_boolean(vtbl, v)) {
111,110✔
2020
        if (polarity) {
67,411✔
2021
          // negate the value
2022
          v = vtbl_mk_not(vtbl, v);
25✔
2023
        }
2024
      }
2025
      model_map_term(model, t, v);
111,110✔
2026
    }
2027

2028
  } else {
2029
    /*
2030
     * r is not mapped to anything:
2031
     *
2032
     * 1) If t == r and t is present in the internalization table
2033
     *    then t is relevant. So we should display its value
2034
     *    when we print the model. To do this, we assign an
2035
     *    arbitrary value v to t and store [t := v] in the map.
2036
     *
2037
     * 2) If t != r then we keep the mapping [t --> r] in
2038
     *    the alias table (provided the model supports aliases).
2039
     */
2040
    if (t == r) {
212,016✔
2041
      if (intern_tbl_term_present(&ctx->intern, t)) {
211,362✔
2042
        tau = term_type(ctx->terms, t);
×
2043
        vtbl = model_get_vtbl(model);
×
2044
        v = vtbl_make_object(vtbl, tau);
×
2045
        model_map_term(model, t, v);
×
2046
      }
2047
    } else if (model->has_alias) {
654✔
2048
      // t != r: keep the substitution [t --> r] in the model
2049
      model_add_substitution(model, t, r);
654✔
2050
    }
2051
  }
2052
}
2053

2054

2055

2056

2057
/*
2058
 * Build a model for the current context (including all satellite solvers)
2059
 * - the context status must be SAT (or UNKNOWN)
2060
 * - if model->has_alias is true, we store the term substitution
2061
 *   defined by ctx->intern_tbl into the model
2062
 * - cleanup of satellite models needed using clean_solver_models()
2063
 */
2064
void build_model(model_t *model, context_t *ctx) {
42,201✔
2065
  term_table_t *terms;
2066
  mcsat_satellite_t *mcsat_model;
2067
  uint32_t i, n;
2068
  term_t t;
2069
  bool use_mcsat_arith_model;
2070

2071
  assert(smt_status(ctx->core) == YICES_STATUS_SAT ||
2072
         smt_status(ctx->core) == YICES_STATUS_UNKNOWN ||
2073
         (context_has_mcsat(ctx) && mcsat_status(ctx->mcsat) == YICES_STATUS_SAT));
2074

2075
  ctx->arith_model_built = false;
42,201✔
2076
  use_mcsat_arith_model = ctx->mcsat_supplement &&
6✔
2077
    context_has_egraph(ctx) && ctx->egraph->th[ETYPE_MCSAT] != NULL;
42,207✔
2078
  mcsat_model = NULL;
42,201✔
2079
  if (use_mcsat_arith_model) {
42,201✔
2080
    mcsat_model = (mcsat_satellite_t *) ctx->egraph->th[ETYPE_MCSAT];
6✔
2081
    if (!mcsat_satellite_prepare_model(mcsat_model, model)) {
6✔
2082
      assert(false && "supplemental MCSAT failed to rebuild a SAT model");
2083
    }
2084
  }
2085

2086
  /*
2087
   * First build assignments in the satellite solvers
2088
   * and get the val_in_model functions for the egraph
2089
   */
2090
  if (!use_mcsat_arith_model && context_has_arith_solver(ctx)) {
42,201✔
2091
    ctx->arith.build_model(ctx->arith_solver);
32,934✔
2092
    ctx->arith_model_built = true;
32,934✔
2093
  }
2094
  if (context_has_bv_solver(ctx)) {
42,201✔
2095
    ctx->bv.build_model(ctx->bv_solver);
21,429✔
2096
  }
2097

2098
  /*
2099
   * Construct the egraph model
2100
   */
2101
  if (context_has_egraph(ctx)) {
42,201✔
2102
    if (use_mcsat_arith_model) {
13,055✔
2103
      egraph_build_model_with_arith_provider(ctx->egraph, model, mcsat_model, mcsat_satellite_arith_value_in_model);
6✔
2104
    } else {
2105
      egraph_build_model(ctx->egraph, model_get_vtbl(model));
13,049✔
2106
    }
2107
  }
2108

2109
  /*
2110
   * Construct the mcsat model.
2111
   */
2112
  if (context_has_mcsat(ctx)) {
42,201✔
2113
    mcsat_build_model(ctx->mcsat, model);
54✔
2114
  }
2115

2116
  // scan the internalization table
2117
  terms = ctx->terms;
42,201✔
2118
  n = intern_tbl_num_terms(&ctx->intern);
42,201✔
2119
  for (i=1; i<n; i++) { // first real term has index 1 (i.e. true_term)
1,235,193,168✔
2120
    if (good_term_idx(terms, i)) {
1,235,150,967✔
2121
      t = pos_occ(i);
1,235,150,967✔
2122
      if (term_kind(terms, t) == UNINTERPRETED_TERM) {
1,235,150,967✔
2123
        build_term_value(ctx, model, t, mcsat_model);
323,155✔
2124
      }
2125
    }
2126
  }
2127

2128
  if (mcsat_model != NULL) {
42,201✔
2129
    mcsat_satellite_export_model(mcsat_model, model);
6✔
2130
  }
2131
}
42,201✔
2132

2133

2134
/*
2135
 * Cleanup solver models
2136
 */
2137
void clean_solver_models(context_t *ctx) {
42,201✔
2138
  if (ctx->arith_model_built) {
42,201✔
2139
    ctx->arith.free_model(ctx->arith_solver);
32,934✔
2140
    ctx->arith_model_built = false;
32,934✔
2141
  }
2142
  if (context_has_bv_solver(ctx)) {
42,201✔
2143
    ctx->bv.free_model(ctx->bv_solver);
21,429✔
2144
  }
2145
  if (context_has_egraph(ctx)) {
42,201✔
2146
    egraph_free_model(ctx->egraph);
13,055✔
2147
  }
2148
}
42,201✔
2149

2150

2151

2152
/*
2153
 * Build a model for the current context
2154
 * - the context status must be SAT (or UNKNOWN)
2155
 * - if model->has_alias is true, we store the term substitution
2156
 *   defined by ctx->intern_tbl into the model
2157
 */
2158
void context_build_model(model_t *model, context_t *ctx) {
294✔
2159
  // Build solver models and term values
2160
  build_model(model, ctx);
294✔
2161

2162
  // Cleanup
2163
  clean_solver_models(ctx);
294✔
2164
}
294✔
2165

2166

2167

2168
/*
2169
 * Read the value of a Boolean term t
2170
 * - return VAL_TRUE/VAL_FALSE or VAL_UNDEF_FALSE/VAL_UNDEF_TRUE if t's value is not known
2171
 */
2172
bval_t context_bool_term_value(context_t *ctx, term_t t) {
×
2173
  term_t r;
2174
  uint32_t polarity;
2175
  int32_t x;
2176
  bval_t v;
2177

2178
  assert(is_boolean_term(ctx->terms, t));
2179

2180
  // default value if t is not in the internalization table
2181
  v = VAL_UNDEF_FALSE;
×
2182
  r = intern_tbl_get_root(&ctx->intern, t);
×
2183
  if (intern_tbl_root_is_mapped(&ctx->intern, r)) {
×
2184
    // r is mapped to some object x
2185
    polarity = polarity_of(r);
×
2186
    r = unsigned_term(r);
×
2187

2188
    x  = intern_tbl_map_of_root(&ctx->intern, r);
×
2189
    if (code_is_eterm(x)) {
×
2190
      // x must be either true_occ or false_occ
2191
      if (x == bool2code(true)) {
×
2192
        v = VAL_TRUE;
×
2193
      } else {
2194
        assert(x == bool2code(false));
2195
        v = VAL_FALSE;
×
2196
      }
2197
    } else {
2198
      // x refers to a literal in the smt core
2199
      v = literal_value(ctx->core, code2literal(x));
×
2200
    }
2201

2202
    // negate v if polarity is 1 (cf. smt_core_base_types.h)
2203
    v ^= polarity;
×
2204
  }
2205

2206
  return v;
×
2207
}
2208

2209

2210
/*
2211
 * UNSAT CORE
2212
 */
2213

2214
/*
2215
 * Build an unsat core:
2216
 * - store the result in v
2217
 * - first reuse a cached term core if available.
2218
 * - otherwise:
2219
 *   CDCL(T): build from smt_core then cache as terms
2220
 *   MCSAT: return empty unless check-with-term-assumptions populated the cache.
2221
 */
2222
void context_build_unsat_core(context_t *ctx, ivector_t *v) {
3,465✔
2223
  smt_core_t *core;
2224
  uint32_t i, n;
2225
  term_t t;
2226

2227
  if (ctx->unsat_core_cache != NULL) {
3,465✔
2228
    // Fast path: repeated get_unsat_core returns the cached term vector.
2229
    ivector_reset(v);
10✔
2230
    ivector_copy(v, ctx->unsat_core_cache->data, ctx->unsat_core_cache->size);
10✔
2231
    return;
10✔
2232
  }
2233

2234
  if (ctx->mcsat != NULL) {
3,455✔
2235
    // MCSAT core extraction is done in check-with-term-assumptions; without cache
2236
    // there is no generic context-level core structure to rebuild from here.
2237
    ivector_reset(v);
×
2238
    return;
×
2239
  }
2240

2241
  core = ctx->core;
3,455✔
2242
  assert(core != NULL && core->status == YICES_STATUS_UNSAT);
2243
  build_unsat_core(core, v);
3,455✔
2244

2245
  // convert from literals to terms
2246
  n = v->size;
3,455✔
2247
  for (i=0; i<n; i++) {
46,128✔
2248
    t = assumption_term_for_literal(&ctx->assumptions, v->data[i]);
42,673✔
2249
    assert(t >= 0);
2250
    v->data[i] = t;
42,673✔
2251
  }
2252

2253
  // Cache the converted term core for subsequent queries.
2254
  cache_unsat_core(ctx, v);
3,455✔
2255
}
2256

2257

2258
/*
2259
 * MODEL INTERPOLANT
2260
 */
2261
term_t context_get_unsat_model_interpolant(context_t *ctx) {
61✔
2262
  if (ctx->mcsat != NULL) {
61✔
2263
    return mcsat_get_unsat_model_interpolant(ctx->mcsat);
61✔
2264
  }
2265

2266
  if (ctx->mcsat_supplement && ctx->egraph != NULL && ctx->egraph->th[ETYPE_MCSAT] != NULL) {
×
2267
    return mcsat_satellite_get_unsat_model_interpolant((mcsat_satellite_t *) ctx->egraph->th[ETYPE_MCSAT]);
×
2268
  }
2269

2270
  if (context_supports_model_interpolation(ctx) &&
×
2271
      ctx->core != NULL &&
×
2272
      smt_status(ctx->core) == YICES_STATUS_UNSAT) {
×
2273
    return false_term;
×
2274
  }
2275

2276
  return NULL_TERM;
×
2277
}
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

© 2026 Coveralls, Inc