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

SRI-CSL / yices2 / 25368527405

05 May 2026 09:28AM UTC coverage: 66.87% (+0.2%) from 66.687%
25368527405

Pull #611

github

disteph
Merge branch 'master' into mcsat-supplement-cdclt

Conflicts resolved with a hybrid of both sides:

- tests/regress/run_test.sh: keep this branch's explicit --dpllt for
  the non-mcsat side of /both/ tests (symmetric with --mcsat), because
  yices' default solver path is heuristically chosen and is not
  guaranteed to be DPLL(T) for every logic. Also adopt master's new
  per-mode .mcsat.gold / .dpllt.gold override mechanism so tests that
  intentionally differ between the two solvers can supply separate
  gold files.

- tests/regress/both/README.md: document the symmetric --mcsat /
  --dpllt pair and the per-mode gold-override convention in one place.
Pull Request #611: Wrap MCSAT as a Nelson-Oppen theory solver in CDCL(T) architecture

690 of 1006 new or added lines in 15 files covered. (68.59%)

2 existing lines in 2 files now uncovered.

84342 of 126128 relevant lines covered (66.87%)

1634859.8 hits per line

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

78.81
/src/mcsat/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
#if defined(CYGWIN) || defined(MINGW)
20
#ifndef __YICES_DLLSPEC__
21
#define __YICES_DLLSPEC__ __declspec(dllexport)
22
#endif
23
#endif
24

25
#include "mcsat/solver.h"
26

27
#include "context/context.h"
28
#include "model/models.h"
29
#include "model/concrete_values.h"
30
#include "model/model_queries.h"
31
#include "io/concrete_value_printer.h"
32

33
#include "mcsat/variable_db.h"
34
#include "mcsat/variable_queue.h"
35
#include "mcsat/trail.h"
36
#include "mcsat/conflict.h"
37
#include "mcsat/plugin.h"
38
#include "mcsat/tracing.h"
39

40
#include "utils/int_queues.h"
41
#include "utils/bitvectors.h"
42
#include "utils/int_hash_sets.h"
43

44
#include "mcsat/bool/bool_plugin.h"
45
#include "mcsat/ite/ite_plugin.h"
46
#include "mcsat/uf/uf_plugin.h"
47
#include "mcsat/bv/bv_plugin.h"
48
#include "mcsat/ff/ff_plugin.h"
49
#include "mcsat/na/na_plugin.h"
50

51
#include "mcsat/preprocessor.h"
52

53
#include "mcsat/utils/statistics.h"
54

55
#include "utils/dprng.h"
56
#include "model/model_queries.h"
57
#include "io/model_printer.h"
58

59
#include "yices.h"
60
#include "api/yices_api_lock_free.h"
61
#include <inttypes.h>
62
#include <math.h>
63

64
/**
65
 * Notification of new variables for the main solver.
66
 */
67
typedef struct solver_new_variable_notify_s {
68
  void (*new_variable) (struct solver_new_variable_notify_s* self, variable_t x);
69
  mcsat_solver_t* mcsat;
70
} solver_new_variable_notify_t;
71

72
/**
73
 * Context of each plugin encapsulates its essential information, including
74
 * the solver itself, its index in the solver and its name (for debugging
75
 * purposes).
76
 */
77
typedef struct mcsat_plugin_context_s {
78
  /** The regular plugin context */
79
  plugin_context_t ctx;
80
  /** The solver reference */
81
  mcsat_solver_t* mcsat;
82
  /** The name of the plugin */
83
  const char* plugin_name;
84
} mcsat_plugin_context_t;
85

86
/**
87
 * The token is passed to plugins for trail operations (propagation and
88
 * decisions) and encapsulates additional information for debugging purposes.
89
 */
90
typedef struct {
91
  /** The token interface */
92
  trail_token_t token_interface;
93
  /** Link to the context */
94
  mcsat_plugin_context_t* ctx;
95
  /** If this is a decision token, this is the suggested variable to decide */
96
  variable_t x;
97
  /** How many times has the token been used */
98
  uint32_t used;
99
} plugin_trail_token_t;
100

101
/** Type of lemma weight for adding to restart counter */
102
typedef enum {
103
  /** Just add 1 */
104
  LEMMA_WEIGHT_UNIT,
105
  /** Add the size of the lemma */
106
  LEMMA_WEIGHT_SIZE,
107
  /** Add the glue of the lemma */
108
  LEMMA_WEIGHT_GLUE
109
} lemma_weight_type_t;
110

111
#define MCSAT_MAX_PLUGINS 10
112

113
typedef struct {
114
  /** Main evaluation method */
115
  bool (*evaluates_at) (const mcsat_evaluator_interface_t* data, term_t t, int_mset_t* vars, mcsat_value_t* value, uint32_t trail_size);
116
  /** The solver */
117
  mcsat_solver_t* solver;
118
} mcsat_evaluator_t;
119

120
struct mcsat_solver_s {
121

122
  /** Context of the solver */
123
  const context_t* ctx;
124

125
  /** Flag to stop the search */
126
  bool stop_search;
127

128
  /** Exception handler */
129
  jmp_buf* exception;
130

131
  /** Term manager for everyone to use */
132
  term_manager_t tm;
133

134
  /** Input types are are from this table */
135
  type_table_t* types;
136

137
  /** Input terms are from this table */
138
  term_table_t* terms;
139

140
  /** Size of the input table at entry to solve() */
141
  uint32_t terms_size_on_solver_entry;
142

143
  /** The status (real status is in trail, this is for context integration) */
144
  smt_status_t status;
145

146
  /** Number of inconsistent push calls */
147
  uint32_t inconsistent_push_calls;
148

149
  /** Notifications for new variables */
150
  solver_new_variable_notify_t var_db_notify;
151

152
  /** Variable database */
153
  variable_db_t* var_db;
154

155
  /** List of assertions (positive variables) asserted to true. */
156
  ivector_t assertion_vars;
157

158
  /**
159
   * List of assertions (terms) as sent to the solver through the API. These
160
   * terms have not been pre-processed.
161
   */
162
  ivector_t assertion_terms_original;
163

164
  /** Temp assertion vector while preprocessing */
165
  ivector_t assertions_tmp;
166

167
  /** The trail */
168
  mcsat_trail_t* trail;
169

170
  /** Mark when adding an assertion */
171
  bool registration_is_assertion;
172

173
  /** Queue for registering new variables */
174
  int_queue_t registration_queue;
175

176
  /** Has a term been registered already */
177
  int_hset_t registration_cache;
178

179
  /** Array of individual plugins, and the additional info */
180
  struct {
181
    plugin_t* plugin;
182
    mcsat_plugin_context_t* plugin_ctx;
183
    char* plugin_name;
184
  } plugins[MCSAT_MAX_PLUGINS];
185

186
  /** The evaluator */
187
  mcsat_evaluator_t evaluator;
188

189
  /** The preprocessor */
190
  preprocessor_t preprocessor;
191

192
  /**
193
   * Array of owners for each term kind. If there are more than one, they
194
   * continue at indices mod NUM_TERM_KINDS.
195
   */
196
  uint32_t kind_owners[NUM_TERM_KINDS * MCSAT_MAX_PLUGINS];
197

198
  /**
199
   * Which of the kinds are 'internal': not for external use.
200
   */
201
  int_hset_t internal_kinds;
202

203
  /**
204
   * Array of owners for each type. If there are more than one, they
205
   * continue at indices mod NUM_TYPE_KINDS.
206
   */
207
  uint32_t type_owners[NUM_TYPE_KINDS * MCSAT_MAX_PLUGINS];
208

209
  /**
210
   * Array of decision makers for each type. There can be only one.
211
   */
212
  uint32_t decision_makers[NUM_TYPE_KINDS];
213

214
  /** Plugin the reported a conflict */
215
  mcsat_plugin_context_t* plugin_in_conflict;
216

217
  /** Variable that is in conflict (if found during assumption decisions) */
218
  variable_t variable_in_conflict;
219

220
  /** Lemmas reported by plugins  */
221
  ivector_t plugin_lemmas;
222

223
  /** Lemmas defining a variable. Will be re-asserted on pop if the variable is still there */
224
  ivector_t plugin_definition_lemmas;
225

226
  /** Variables of definition lemmas (as terms) */
227
  ivector_t plugin_definition_vars;
228

229
  /** Last processed definition lemma */
230
  uint32_t plugin_definition_lemmas_i;
231

232
  /** Number of plugins */
233
  uint32_t plugins_count;
234

235
  /** Variable to decide on first */
236
  ivector_t top_decision_vars;
237

238
  /** Variables hinted by the plugins to decide next */
239
  int_queue_t hinted_decision_vars;
240

241
  /** The queue for variable decisions */
242
  var_queue_t var_queue;
243

244
  /** All pending requests */
245
  struct {
246
    bool restart;
247
    bool gc_calls;
248
    bool recache;
249
  } pending_requests_all;
250

251
  /** Any pending requests */
252
  bool pending_requests;
253

254
  /** Assumption variables */
255
  ivector_t assumption_vars;
256

257
  /** Index of the assumption to process next */
258
  uint32_t assumption_i;
259

260
  /** Level at which last assumption has been decided (-1 if not yet) */
261
  int32_t assumptions_decided_level;
262

263
  /** Model used for assumptions solving */
264
  model_t* assumptions_model;
265

266
  /** Interpolant */
267
  term_t interpolant;
268

269
  /** Statistics */
270
  statistics_t stats;
271

272
  struct {
273
    // Assertions added
274
    statistic_int_t* assertions;
275
    // Lemmas added
276
    statistic_int_t* lemmas;
277
    // Decisions performed
278
    statistic_int_t* decisions;
279
    // Restarts performed
280
    statistic_int_t* restarts;
281
    // Partial restarts performed
282
    statistic_int_t* partial_restarts;
283
    // Conflicts handled
284
    statistic_int_t* conflicts;
285
    // Average conflict size
286
    statistic_avg_t* avg_conflict_size;
287
    // GC calls
288
    statistic_int_t* gc_calls;
289
    // Recache calls
290
    statistic_int_t* recaches;
291
  } solver_stats;
292

293
  struct {
294
    // Restart interval (used as multiplier in luby sequence)
295
    uint32_t restart_interval;
296
    // Type of weight to use for restart counter
297
    lemma_weight_type_t lemma_restart_weight_type;
298
    // recache interval
299
    uint32_t recache_interval;
300
    // Random decision frequency
301
    double random_decision_freq;
302
    // Random decision seed
303
    double random_decision_seed;
304
  } heuristic_params;
305

306
  /** Scope holder for backtracking int variables */
307
  scope_holder_t scope;
308

309
  /** IDs of various plugins, if added */
310
  uint32_t bool_plugin_id;
311
  uint32_t uf_plugin_id;
312
  uint32_t ite_plugin_id;
313
  uint32_t na_plugin_id;
314
  uint32_t bv_plugin_id;
315
  uint32_t ff_plugin_id;
316
};
317

318
static
319
bool mcsat_is_consistent(mcsat_solver_t* mcsat) {
13,590,456✔
320
  return trail_is_consistent(mcsat->trail) && mcsat->variable_in_conflict == variable_null;
13,590,456✔
321
}
322

323
static
324
void mcsat_add_lemma(mcsat_solver_t* mcsat, ivector_t* lemma, term_t decision_bound);
325

326
static
327
void propagation_check(const ivector_t* reasons, term_t x, term_t subst);
328

329
static
330
void mcsat_stats_init(mcsat_solver_t* mcsat) {
702✔
331
  mcsat->solver_stats.assertions = statistics_new_int(&mcsat->stats, "mcsat::assertions");
702✔
332
  mcsat->solver_stats.conflicts = statistics_new_int(&mcsat->stats, "mcsat::conflicts");
702✔
333
  mcsat->solver_stats.avg_conflict_size = statistics_new_avg(&mcsat->stats, "mcsat::avg_conflict_size");
702✔
334
  mcsat->solver_stats.decisions = statistics_new_int(&mcsat->stats, "mcsat::decisions");
702✔
335
  mcsat->solver_stats.gc_calls = statistics_new_int(&mcsat->stats, "mcsat::gc_calls");
702✔
336
  mcsat->solver_stats.lemmas = statistics_new_int(&mcsat->stats, "mcsat::lemmas");
702✔
337
  mcsat->solver_stats.restarts = statistics_new_int(&mcsat->stats, "mcsat::restarts");
702✔
338
  mcsat->solver_stats.partial_restarts = statistics_new_int(&mcsat->stats, "mcsat::partial_restarts");
702✔
339
  mcsat->solver_stats.recaches = statistics_new_int(&mcsat->stats, "mcsat::recaches");
702✔
340
}
702✔
341

342
static
343
void mcsat_heuristics_init(mcsat_solver_t* mcsat, const param_t *params) {
1,033✔
344
  mcsat->heuristic_params.restart_interval = 10;
1,033✔
345
  mcsat->heuristic_params.lemma_restart_weight_type = LEMMA_WEIGHT_SIZE;
1,033✔
346
  mcsat->heuristic_params.recache_interval = 300;
1,033✔
347
  // Use params for random decision parameters
348
  mcsat->heuristic_params.random_decision_freq = params->randomness;
1,033✔
349
  mcsat->heuristic_params.random_decision_seed = params->random_seed;
1,033✔
350
}
1,033✔
351

352
static
353
bool mcsat_evaluates_at(const mcsat_evaluator_interface_t* self, term_t t, int_mset_t* vars, mcsat_value_t* value, uint32_t trail_size) {
969,528✔
354

355
  const mcsat_solver_t* mcsat = ((const mcsat_evaluator_t*) self)->solver;
969,528✔
356
  assert(value != NULL);
357

358
  if (trace_enabled(mcsat->ctx->trace, "mcsat::resolve")) {
969,528✔
359
    FILE* out = trace_out(mcsat->ctx->trace);
×
360
    fprintf(out, "explaining eval of: ");
×
361
    term_print_to_file(out, mcsat->terms, t);
×
362
    fprintf(out, " -> ");
×
363
    mcsat_value_print(value, out);
×
364
    fprintf(out, "\n");
×
365
  }
366

367
  uint32_t i;
368
  term_kind_t kind;
369
  type_kind_t type_kind;
370
  bool evaluates = false;
969,528✔
371
  plugin_t* plugin;
372

373
  kind = term_kind(mcsat->terms, t);
969,528✔
374
  bool is_equality = false;
969,528✔
375
  switch (kind) {
969,528✔
376
  case EQ_TERM:
194,421✔
377
  case BV_EQ_ATOM:
378
  case ARITH_BINEQ_ATOM:
379
  case ARITH_FF_BINEQ_ATOM:
380
    is_equality = true;
194,421✔
381
    break;
194,421✔
382
  default:
775,107✔
383
    // Nothing
384
    break;
775,107✔
385
  }
386

387
  if (!is_equality) {
969,528✔
388
    for (i = kind; mcsat->kind_owners[i] != MCSAT_MAX_PLUGINS; i += NUM_TERM_KINDS) {
821,978✔
389
      int_mset_clear(vars);
177,773✔
390
      plugin = mcsat->plugins[mcsat->kind_owners[i]].plugin;
177,773✔
391
      if (plugin->explain_evaluation) {
177,773✔
392
        if (trace_enabled(mcsat->ctx->trace, "mcsat::resolve")) {
177,773✔
393
          FILE* out = trace_out(mcsat->ctx->trace);
×
394
          fprintf(out, "explaining eval with: %s\n", mcsat->plugins[mcsat->kind_owners[i]].plugin_name);
×
395
        }
396
        evaluates = plugin->explain_evaluation(plugin, t, vars, value);
177,773✔
397
        if (evaluates) {
177,773✔
398
          return true;
130,902✔
399
        }
400
      }
401
    }
402
  } else {
403
    composite_term_t* eq_desc = composite_term_desc(mcsat->terms, t);
194,421✔
404
    type_kind = term_type_kind(mcsat->terms, eq_desc->arg[0]);
194,421✔
405
    for (i = type_kind; mcsat->type_owners[i] != MCSAT_MAX_PLUGINS; i += NUM_TERM_KINDS) {
337,134✔
406
      int_mset_clear(vars);
194,421✔
407
      plugin = mcsat->plugins[mcsat->type_owners[i]].plugin;
194,421✔
408
      if (plugin->explain_evaluation) {
194,421✔
409
        if (trace_enabled(mcsat->ctx->trace, "mcsat::resolve")) {
194,421✔
410
          FILE* out = trace_out(mcsat->ctx->trace);
×
411
          fprintf(out, "explaining eval with: %s\n", mcsat->plugins[mcsat->type_owners[i]].plugin_name);
×
412
        }
413
        evaluates = plugin->explain_evaluation(plugin, t, vars, value);
194,421✔
414
        if (evaluates) {
194,421✔
415
          return true;
51,708✔
416
        }
417
      }
418
    }
419
  }
420

421
  if (!evaluates) {
786,918✔
422
    // Maybe the term itself evaluates
423
    term_t t_unsigned = unsigned_term(t);
786,918✔
424
    variable_t t_var = variable_db_get_variable_if_exists(mcsat->var_db, t_unsigned);
786,918✔
425
    if (t_var != variable_null) {
786,918✔
426
      if (trail_has_value(mcsat->trail, t_var)) {
786,855✔
427
        const mcsat_value_t* t_var_value = trail_get_value(mcsat->trail, t_var);
786,408✔
428
        bool negated = is_neg_term(t);
786,408✔
429
        if ((negated && t_var_value->b != value->b)
786,408✔
430
            || (!negated && t_var_value->b == value->b)) {
376,035✔
431
          int_mset_clear(vars);
786,360✔
432
          int_mset_add(vars, t_var);
786,360✔
433
          return true;
786,360✔
434
        }
435
      }
436
      if (vars->size == 0) {
495✔
437
        int_mset_add(vars, t_var);
394✔
438
      }
439
    }
440
  }
441

442
  return false;
558✔
443
}
444

445
/** Construct the mcsat evaluator */
446
void mcsat_evaluator_construct(mcsat_evaluator_t* evaluator, mcsat_solver_t* solver) {
702✔
447
  evaluator->evaluates_at = mcsat_evaluates_at;
702✔
448
  evaluator->solver = solver;
702✔
449
}
702✔
450

451
/** Callback on propagations */
452
static
453
bool trail_token_add(trail_token_t* token, variable_t x, const mcsat_value_t* value) {
5,683,625✔
454
  plugin_trail_token_t* tk = (plugin_trail_token_t*) token;
5,683,625✔
455
  mcsat_solver_t* mcsat = tk->ctx->mcsat;
5,683,625✔
456
  mcsat_trail_t* trail = mcsat->trail;
5,683,625✔
457
  bool is_decision;
458

459
  is_decision = tk->x != variable_null;
5,683,625✔
460

461
  if (ctx_trace_enabled(&tk->ctx->ctx, "trail::add")) {
5,683,625✔
462
    if (is_decision) {
×
463
      ctx_trace_printf(&tk->ctx->ctx, "plugin %s deciding ", tk->ctx->plugin_name);\
×
464
    } else {
465
      ctx_trace_printf(&tk->ctx->ctx, "plugin %s propagating ", tk->ctx->plugin_name);\
×
466
    }
467
    variable_db_print_variable(mcsat->var_db, x, ctx_trace_out(&tk->ctx->ctx));
×
468
    ctx_trace_printf(&tk->ctx->ctx, " -> ");
×
469
    mcsat_value_print(value, ctx_trace_out(&tk->ctx->ctx));
×
470
    ctx_trace_printf(&tk->ctx->ctx, "\n");
×
471
  }
472

473
  if (trail_has_value(trail, x)) {
5,683,625✔
474
    return false;
×
475
  }
476

477
  tk->used ++;
5,683,625✔
478

479
  if (is_decision) {
5,683,625✔
480
    trail_add_decision(trail, x, value, tk->ctx->ctx.plugin_id);
764,072✔
481
  } else {
482
    trail_add_propagation(trail, x, value, tk->ctx->ctx.plugin_id, trail->decision_level);
4,919,553✔
483
  }
484

485
  if (ctx_trace_enabled(&tk->ctx->ctx, "mcsat::propagation::check") && !is_decision) {
5,683,625✔
486
    uint32_t plugin_id = tk->ctx->ctx.plugin_id;
×
487
    if (plugin_id != mcsat->bool_plugin_id) {
×
488
      ivector_t reason;
489
      init_ivector(&reason, 0);
×
490
      plugin_t* plugin = mcsat->plugins[plugin_id].plugin;
×
491
      term_t substitution = plugin->explain_propagation(plugin, x, &reason);
×
492
      term_t x_term = variable_db_get_term(mcsat->var_db, x);
×
493
      propagation_check(&reason, x_term, substitution);
×
494
      delete_ivector(&reason);
×
495
    }
496
  }
497

498
  return true;
5,683,625✔
499
}
500

501
/** Callback on propagations at lower levels */
502
static
503
bool trail_token_add_at_level(trail_token_t* token, variable_t x, const mcsat_value_t* value, uint32_t level) {
1,329,937✔
504
  plugin_trail_token_t* tk = (plugin_trail_token_t*) token;
1,329,937✔
505
  mcsat_solver_t* mcsat = tk->ctx->mcsat;
1,329,937✔
506
  mcsat_trail_t* trail = mcsat->trail;
1,329,937✔
507

508
  if (ctx_trace_enabled(&tk->ctx->ctx, "trail::add")) {
1,329,937✔
509
    ctx_trace_printf(&tk->ctx->ctx, "plugin %s propagating ", tk->ctx->plugin_name);
×
510
    variable_db_print_variable(mcsat->var_db, x, ctx_trace_out(&tk->ctx->ctx));
×
511
    ctx_trace_printf(&tk->ctx->ctx, " -> ");
×
512
    mcsat_value_print(value, ctx_trace_out(&tk->ctx->ctx));
×
513
    ctx_trace_printf(&tk->ctx->ctx, "\n");
×
514
  }
515

516
  // Only for propagations, we can't decide on lower levels
517
  assert(tk->x == variable_null);
518

519
  if (trail_has_value(trail, x)) {
1,329,937✔
520
    return false;
×
521
  }
522

523
  tk->used ++;
1,329,937✔
524

525
  // Check for trail level
526
  if (level < trail->decision_level_base) {
1,329,937✔
527
    level = trail->decision_level_base;
×
528
  }
529

530
  // Add the propagation
531
  trail_add_propagation(trail, x, value, tk->ctx->ctx.plugin_id, level);
1,329,937✔
532

533
  return true;
1,329,937✔
534
}
535

536

537
static
538
void trail_token_conflict(trail_token_t* token) {
95,677✔
539
  plugin_trail_token_t* tk = (plugin_trail_token_t*) token;
95,677✔
540

541
  if (ctx_trace_enabled(&tk->ctx->ctx, "trail::conflict")) {
95,677✔
542
    ctx_trace_printf(&tk->ctx->ctx, "plugin %s reporting a conflict\n", tk->ctx->plugin_name);
×
543
  }
544

545
  tk->used ++;
95,677✔
546

547
  // Remember the plugin that reported the
548
  tk->ctx->mcsat->plugin_in_conflict = tk->ctx;
95,677✔
549

550
  // Set the trail to be inconsistent
551
  trail_set_inconsistent(tk->ctx->mcsat->trail);
95,677✔
552
}
95,677✔
553

554
static
555
void trail_token_lemma(trail_token_t* token, term_t lemma) {
39,049✔
556
  plugin_trail_token_t* tk = (plugin_trail_token_t*) token;
39,049✔
557

558
  if (ctx_trace_enabled(&tk->ctx->ctx, "trail::lemma")) {
39,049✔
559
    ctx_trace_printf(&tk->ctx->ctx, "plugin %s reporting a lemma\n", tk->ctx->plugin_name);
×
560
    ctx_trace_term(&tk->ctx->ctx, lemma);
×
561
  }
562

563
  tk->used ++;
39,049✔
564

565
  // Remember the lemma
566
  ivector_push(&tk->ctx->mcsat->plugin_lemmas, lemma);
39,049✔
567
}
39,049✔
568

569
static
570
void trail_token_definition_lemma(trail_token_t* token, term_t lemma, term_t t) {
1,031✔
571
  plugin_trail_token_t* tk = (plugin_trail_token_t*) token;
1,031✔
572

573
  if (ctx_trace_enabled(&tk->ctx->ctx, "trail::lemma")) {
1,031✔
574
    ctx_trace_printf(&tk->ctx->ctx, "plugin %s reporting a definition lemma\n", tk->ctx->plugin_name);
×
575
    ctx_trace_term(&tk->ctx->ctx, lemma);
×
576
  }
577

578
  tk->used ++;
1,031✔
579

580
  // Remember the definition
581
  ivector_push(&tk->ctx->mcsat->plugin_definition_lemmas, lemma);
1,031✔
582
  ivector_push(&tk->ctx->mcsat->plugin_definition_vars, t);
1,031✔
583
}
1,031✔
584

585
/** Construct the trail token */
586
static inline
587
void trail_token_construct(plugin_trail_token_t* token, mcsat_plugin_context_t* ctx, variable_t x) {
10,076,896✔
588
  token->token_interface.add = trail_token_add;
10,076,896✔
589
  token->token_interface.add_at_level = trail_token_add_at_level;
10,076,896✔
590
  token->token_interface.conflict = trail_token_conflict;
10,076,896✔
591
  token->token_interface.lemma = trail_token_lemma;
10,076,896✔
592
  token->token_interface.definition_lemma = trail_token_definition_lemma;
10,076,896✔
593
  token->ctx = ctx;
10,076,896✔
594
  token->x = x;
10,076,896✔
595
  token->used = 0;
10,076,896✔
596
}
10,076,896✔
597

598
void mcsat_plugin_term_notification_by_kind(plugin_context_t* self, term_kind_t kind, bool is_internal) {
33,696✔
599
  uint32_t i;
600
  mcsat_plugin_context_t* mctx;
601

602
  mctx = (mcsat_plugin_context_t*) self;
33,696✔
603
  assert(self->plugin_id != MCSAT_MAX_PLUGINS);
604
  for (i = kind; mctx->mcsat->kind_owners[i] != MCSAT_MAX_PLUGINS; i += NUM_TERM_KINDS) {}
40,014✔
605
  mctx->mcsat->kind_owners[i] = self->plugin_id;
33,696✔
606
  if (is_internal) {
33,696✔
607
    int_hset_add(&mctx->mcsat->internal_kinds, kind);
702✔
608
  }
609
}
33,696✔
610

611
void mcsat_plugin_term_notification_by_type(plugin_context_t* self, type_kind_t kind) {
5,616✔
612
  uint32_t i;
613
  mcsat_plugin_context_t* mctx;
614

615
  mctx = (mcsat_plugin_context_t*) self;
5,616✔
616
  assert(self->plugin_id != MCSAT_MAX_PLUGINS);
617
  for (i = kind; mctx->mcsat->type_owners[i] != MCSAT_MAX_PLUGINS; i += NUM_TYPE_KINDS) {}
5,616✔
618
  mctx->mcsat->type_owners[i] = self->plugin_id;
5,616✔
619
}
5,616✔
620

621
static
622
void mcsat_request_restart(mcsat_solver_t* mcsat) {
20,891✔
623
  mcsat->pending_requests = true;
20,891✔
624
  mcsat->pending_requests_all.restart = true;
20,891✔
625
}
20,891✔
626

627
static
628
void mcsat_request_gc(mcsat_solver_t* mcsat) {
87✔
629
  mcsat->pending_requests = true;
87✔
630
  mcsat->pending_requests_all.gc_calls = true;
87✔
631
}
87✔
632

633
static
634
void mcsat_request_recache(mcsat_solver_t* mcsat) {
94✔
635
  mcsat->pending_requests = true;
94✔
636
  mcsat->pending_requests_all.recache = true;
94✔
637
}
94✔
638

639
static
640
void mcsat_plugin_context_restart(plugin_context_t* self) {
×
641
  mcsat_plugin_context_t* mctx;
642

643
  mctx = (mcsat_plugin_context_t*) self;
×
644
  mcsat_request_restart(mctx->mcsat);
×
645
}
×
646

647
static
648
void mcsat_plugin_context_gc(plugin_context_t* self) {
87✔
649
  mcsat_plugin_context_t* mctx;
650

651
  mctx = (mcsat_plugin_context_t*) self;
87✔
652
  mcsat_request_gc(mctx->mcsat);
87✔
653
}
87✔
654

655
static inline
656
void mcsat_add_top_decision(mcsat_solver_t* mcsat, variable_t x) {
3✔
657
  for (int i = 0; i < mcsat->top_decision_vars.size; ++i) {
3✔
658
    if (mcsat->top_decision_vars.data[i] == x) {
×
659
      return;
×
660
    }
661
  }
662
  ivector_push(&mcsat->top_decision_vars, x);
3✔
663
}
664

665
static inline
666
void mcsat_add_decision_hint(mcsat_solver_t* mcsat, variable_t x) {
454,167✔
667
  int_queue_push(&mcsat->hinted_decision_vars, x);
454,167✔
668
}
454,167✔
669

670
static inline
671
void mcsat_bump_variable(mcsat_solver_t* mcsat, variable_t x, uint32_t factor) {
6,271,499✔
672
  var_queue_bump_variable(&mcsat->var_queue, x, factor);
6,271,499✔
673
}
6,271,499✔
674

675
#if 0
676
static inline
677
void mcsat_bump_variables_vector(mcsat_solver_t* mcsat, const ivector_t* vars) {
678
  uint32_t i;
679
  for (i = 0; i < vars->size; ++ i) {
680
    mcsat_bump_variable(mcsat, vars->data[i], 1);
681
  }
682
}
683
#endif
684

685
static inline
686
void mcsat_bump_variables_mset(mcsat_solver_t* mcsat, const int_mset_t* vars) {
95,456✔
687
  uint32_t i;
688
  for (i = 0; i < vars->element_list.size; ++ i) {
2,311,274✔
689
    variable_t x = vars->element_list.data[i];
2,215,818✔
690
    uint32_t n = int_mset_contains(vars, x);
2,215,818✔
691
    mcsat_bump_variable(mcsat, x, n);
2,215,818✔
692
  }
693
}
95,456✔
694

695
static
696
void mcsat_plugin_context_bump_variable(plugin_context_t* self, variable_t x) {
×
697
  mcsat_plugin_context_t* mctx;
698

699
  mctx = (mcsat_plugin_context_t*) self;
×
700
  mcsat_bump_variable(mctx->mcsat, x, 1);
×
701
}
×
702

703
static
704
void mcsat_plugin_context_bump_variable_n(plugin_context_t* self, variable_t x, uint32_t n) {
4,055,681✔
705
  mcsat_plugin_context_t* mctx;
706

707
  mctx = (mcsat_plugin_context_t*) self;
4,055,681✔
708
  mcsat_bump_variable(mctx->mcsat, x, n);
4,055,681✔
709
}
4,055,681✔
710

711
static
712
int mcsat_plugin_context_cmp_variables(plugin_context_t* self, variable_t x, variable_t y) {
1,556,222✔
713
  mcsat_plugin_context_t* mctx;
714
  mctx = (mcsat_plugin_context_t*) self;
1,556,222✔
715
  return var_queue_cmp_variables(&mctx->mcsat->var_queue, x, y);
1,556,222✔
716
}
717

718
static
719
void mcsat_plugin_context_request_top_decision(plugin_context_t* self, variable_t x) {
3✔
720
  mcsat_plugin_context_t* mctx;
721
  mctx = (mcsat_plugin_context_t*) self;
3✔
722
  mcsat_add_top_decision(mctx->mcsat, x);
3✔
723
}
3✔
724

725
static
726
void mcsat_plugin_context_hint_next_decision(plugin_context_t* self, variable_t x) {
454,167✔
727
  mcsat_plugin_context_t* mctx;
728
  mctx = (mcsat_plugin_context_t*) self;
454,167✔
729
  mcsat_add_decision_hint(mctx->mcsat, x);
454,167✔
730
}
454,167✔
731

732
/*
733
 * Provide hint to the trail cache.
734
 */
735
static
736
void mcsat_plugin_context_hint_value(plugin_context_t* self, variable_t x, const mcsat_value_t* val) {
51✔
737
  mcsat_plugin_context_t* mctx;
738
  mctx = (mcsat_plugin_context_t*) self;
51✔
739
  trail_set_cached_value(mctx->mcsat->trail, x, val);
51✔
740
}
51✔
741

742
static
743
void mcsat_plugin_context_decision_calls(plugin_context_t* self, type_kind_t type) {
5,616✔
744
  mcsat_plugin_context_t* mctx;
745

746
  mctx = (mcsat_plugin_context_t*) self;
5,616✔
747
  assert(mctx->mcsat->decision_makers[type] == MCSAT_MAX_PLUGINS);
748
  mctx->mcsat->decision_makers[type] = self->plugin_id;
5,616✔
749
}
5,616✔
750

751
void mcsat_plugin_context_construct(mcsat_plugin_context_t* ctx, mcsat_solver_t* mcsat, uint32_t plugin_i, const char* plugin_name) {
4,212✔
752
  ctx->ctx.plugin_id = plugin_i;
4,212✔
753
  ctx->ctx.var_db = mcsat->var_db;
4,212✔
754
  ctx->ctx.tm = &mcsat->tm;
4,212✔
755
  ctx->ctx.terms = mcsat->terms;
4,212✔
756
  ctx->ctx.types = mcsat->types;
4,212✔
757
  ctx->ctx.exception = mcsat->exception;
4,212✔
758
  ctx->ctx.options = &mcsat->ctx->mcsat_options;
4,212✔
759
  ctx->ctx.trail = mcsat->trail;
4,212✔
760
  ctx->ctx.stats = &mcsat->stats;
4,212✔
761
  ctx->ctx.tracer = mcsat->ctx->trace;
4,212✔
762
  ctx->ctx.stop_search = &mcsat->stop_search;
4,212✔
763
  ctx->ctx.request_decision_calls = mcsat_plugin_context_decision_calls;
4,212✔
764
  ctx->ctx.request_term_notification_by_kind = mcsat_plugin_term_notification_by_kind;
4,212✔
765
  ctx->ctx.request_term_notification_by_type = mcsat_plugin_term_notification_by_type;
4,212✔
766
  ctx->ctx.request_restart = mcsat_plugin_context_restart;
4,212✔
767
  ctx->ctx.request_gc = mcsat_plugin_context_gc;
4,212✔
768
  ctx->ctx.bump_variable = mcsat_plugin_context_bump_variable;
4,212✔
769
  ctx->ctx.bump_variable_n = mcsat_plugin_context_bump_variable_n;
4,212✔
770
  ctx->ctx.cmp_variables = mcsat_plugin_context_cmp_variables;
4,212✔
771
  ctx->ctx.request_top_decision = mcsat_plugin_context_request_top_decision;
4,212✔
772
  ctx->ctx.hint_next_decision = mcsat_plugin_context_hint_next_decision;
4,212✔
773
  ctx->ctx.hint_value = mcsat_plugin_context_hint_value;
4,212✔
774
  ctx->mcsat = mcsat;
4,212✔
775
  ctx->plugin_name = plugin_name;
4,212✔
776
}
4,212✔
777

778
static
779
void mcsat_term_registration_enqueue(mcsat_solver_t* mcsat, term_t t) {
175,764✔
780
  // Make sure it's positive polarity
781
  t = unsigned_term(t);
175,764✔
782

783
  // Enqueue if not processed already
784
  if (!int_hset_member(&mcsat->registration_cache, t)) {
175,764✔
785
    int_hset_add(&mcsat->registration_cache, t);
175,764✔
786
    int_queue_push(&mcsat->registration_queue, t);
175,764✔
787
  }
788
}
175,764✔
789

790
static
791
void mcsat_new_variable_notify(solver_new_variable_notify_t* self, variable_t x) {
175,764✔
792
  term_t t;
793
  uint32_t size;
794

795
  // Enqueue for registration
796
  t = variable_db_get_term(self->mcsat->var_db, x);
175,764✔
797
  mcsat_term_registration_enqueue(self->mcsat, t);
175,764✔
798

799
  // Ensure that the trail/model is aware of this
800
  trail_new_variable_notify(self->mcsat->trail, x);
175,764✔
801

802
  // Add the variable to the queue
803
  if (x >= self->mcsat->var_queue.size) {
175,764✔
804
    size = x + x/2 + 1;
498✔
805
    assert(size > x);
806
    var_queue_extend(&self->mcsat->var_queue, size);
498✔
807
  }
808
  var_queue_insert(&self->mcsat->var_queue, x);
175,764✔
809
}
175,764✔
810

811
static
812
uint32_t mcsat_add_plugin(mcsat_solver_t* mcsat, plugin_allocator_t plugin_allocator, const char* plugin_name) {
4,212✔
813

814
  // Allocate the plugin
815
  plugin_t* plugin = plugin_allocator();
4,212✔
816
  // The index of the plugin
817
  uint32_t plugin_i = mcsat->plugins_count;
4,212✔
818
  // Allocate the request
819
  mcsat_plugin_context_t* plugin_ctx = safe_malloc(sizeof(mcsat_plugin_context_t));
4,212✔
820
  mcsat_plugin_context_construct(plugin_ctx, mcsat, plugin_i, plugin_name);
4,212✔
821
  // Construct the plugin
822
  plugin->construct(plugin, (plugin_context_t*) plugin_ctx);
4,212✔
823

824
  // Add the plugin to the list of plugins
825
  mcsat->plugins[plugin_i].plugin = plugin;
4,212✔
826
  mcsat->plugins[plugin_i].plugin_ctx = plugin_ctx;
4,212✔
827
  mcsat->plugins[plugin_i].plugin_name = safe_strdup(plugin_name);
4,212✔
828
  mcsat->plugins_count ++;
4,212✔
829

830
  return plugin_i;
4,212✔
831
}
832

833
static
834
void mcsat_add_plugins(mcsat_solver_t* mcsat) {
702✔
835
  mcsat->bool_plugin_id = mcsat_add_plugin(mcsat, bool_plugin_allocator, "bool_plugin");
702✔
836
  mcsat->uf_plugin_id = mcsat_add_plugin(mcsat, uf_plugin_allocator, "uf_plugin");
702✔
837
  mcsat->ite_plugin_id = mcsat_add_plugin(mcsat, ite_plugin_allocator, "ite_plugin");
702✔
838
  mcsat->na_plugin_id = mcsat_add_plugin(mcsat, na_plugin_allocator, "na_plugin");
702✔
839
  mcsat->bv_plugin_id = mcsat_add_plugin(mcsat, bv_plugin_allocator, "bv_plugin");
702✔
840
  mcsat->ff_plugin_id = mcsat_add_plugin(mcsat, ff_plugin_allocator, "ff_plugin");
702✔
841
}
702✔
842

843
static
844
void mcsat_construct(mcsat_solver_t* mcsat, const context_t* ctx) {
702✔
845
  uint32_t i;
846

847
  assert(ctx != NULL);
848
  assert(ctx->arch == CTX_ARCH_MCSAT);
849
  assert(ctx->terms != NULL);
850
  assert(ctx->types != NULL);
851

852
  mcsat->stop_search = false;
702✔
853
  mcsat->ctx = ctx;
702✔
854
  mcsat->exception = (jmp_buf*) &ctx->env;
702✔
855
  mcsat->types = ctx->types;
702✔
856
  mcsat->terms = ctx->terms;
702✔
857
  mcsat->terms_size_on_solver_entry = 0;
702✔
858
  mcsat->status = YICES_STATUS_IDLE;
702✔
859
  mcsat->inconsistent_push_calls = 0;
702✔
860

861
  // New term manager
862
  init_term_manager(&mcsat->tm, mcsat->terms);
702✔
863
  mcsat->tm.simplify_bveq1 = false;
702✔
864
  mcsat->tm.simplify_ite = false;
702✔
865

866
  // The new variable listener
867
  mcsat->var_db_notify.mcsat = mcsat;
702✔
868
  mcsat->var_db_notify.new_variable = mcsat_new_variable_notify;
702✔
869

870
  // The variable database
871
  mcsat->var_db = safe_malloc(sizeof(variable_db_t));
702✔
872
  variable_db_construct(mcsat->var_db, mcsat->terms, mcsat->types, mcsat->ctx->trace);
702✔
873
  variable_db_add_new_variable_listener(mcsat->var_db, (variable_db_new_variable_notify_t*)&mcsat->var_db_notify);
702✔
874

875
  // List of assertions
876
  init_ivector(&mcsat->assertion_vars, 0);
702✔
877
  init_ivector(&mcsat->assertion_terms_original, 0);
702✔
878
  init_ivector(&mcsat->assertions_tmp, 0);
702✔
879

880
  // The trail
881
  mcsat->trail = safe_malloc(sizeof(mcsat_trail_t));
702✔
882
  trail_construct(mcsat->trail, mcsat->var_db);
702✔
883

884
  // Variable registration queue
885
  init_int_queue(&mcsat->registration_queue, 0);
702✔
886
  init_int_hset(&mcsat->registration_cache, 0);
702✔
887

888
  // Init all the term owners to NULL
889
  for (i = 0; i < NUM_TERM_KINDS * MCSAT_MAX_PLUGINS; ++ i) {
372,762✔
890
    mcsat->kind_owners[i] = MCSAT_MAX_PLUGINS;
372,060✔
891
  }
892

893
  // Internal kinds
894
  init_int_hset(&mcsat->internal_kinds, 0);
702✔
895

896
  // Init all the type owners to NULL
897
  for (i = 0; i < NUM_TYPE_KINDS * MCSAT_MAX_PLUGINS; ++ i) {
84,942✔
898
    mcsat->type_owners[i] = MCSAT_MAX_PLUGINS;
84,240✔
899
  }
900

901
  // Init all the decision makers to NULL
902
  for (i = 0; i < NUM_TYPE_KINDS; ++ i) {
9,126✔
903
    mcsat->decision_makers[i] = MCSAT_MAX_PLUGINS;
8,424✔
904
  }
905

906
  // Plugin vectors
907
  mcsat->plugins_count = 0;
702✔
908
  mcsat->plugin_in_conflict = 0;
702✔
909

910
  // Construct the evaluator
911
  mcsat_evaluator_construct(&mcsat->evaluator, mcsat);
702✔
912

913
  // Construct the preprocessor
914
  preprocessor_construct(&mcsat->preprocessor, mcsat->terms, mcsat->exception, &mcsat->ctx->mcsat_options);
702✔
915

916
  // The variable queue
917
  init_ivector(&mcsat->top_decision_vars, 0);
702✔
918
  init_int_queue(&mcsat->hinted_decision_vars, 0);
702✔
919
  var_queue_construct(&mcsat->var_queue);
702✔
920

921
  mcsat->pending_requests_all.restart = false;
702✔
922
  mcsat->pending_requests_all.gc_calls = false;
702✔
923
  mcsat->pending_requests_all.recache = false;
702✔
924
  mcsat->pending_requests = false;
702✔
925

926
  mcsat->variable_in_conflict = variable_null;
702✔
927
  mcsat->assumption_i = 0;
702✔
928
  mcsat->assumptions_decided_level = -1;
702✔
929
  mcsat->interpolant = NULL_TERM;
702✔
930

931
  // Assumptions vector
932
  init_ivector(&mcsat->assumption_vars, 0);
702✔
933

934
  // Lemmas vector
935
  init_ivector(&mcsat->plugin_lemmas, 0);
702✔
936
  init_ivector(&mcsat->plugin_definition_lemmas, 0);
702✔
937
  init_ivector(&mcsat->plugin_definition_vars, 0);
702✔
938
  mcsat->plugin_definition_lemmas_i = 0;
702✔
939

940
  // Construct stats
941
  statistics_construct(&mcsat->stats);
702✔
942
  mcsat_stats_init(mcsat);
702✔
943

944
  // Scope for backtracking
945
  scope_holder_construct(&mcsat->scope);
702✔
946

947
  // Construct the plugins
948
  mcsat_add_plugins(mcsat);
702✔
949
}
702✔
950

951
void mcsat_destruct(mcsat_solver_t* mcsat) {
702✔
952
  uint32_t i;
953
  plugin_t* plugin;
954

955
  // Delete the plugin data
956
  for (i = 0; i < mcsat->plugins_count; ++ i) {
4,914✔
957
    // Plugin
958
    plugin = mcsat->plugins[i].plugin;
4,212✔
959
    plugin->destruct(mcsat->plugins[i].plugin);
4,212✔
960
    safe_free(plugin);
4,212✔
961
    // Plugin context
962
    safe_free(mcsat->plugins[i].plugin_ctx);
4,212✔
963
    // The name
964
    safe_free(mcsat->plugins[i].plugin_name);
4,212✔
965
  }
966

967
  delete_term_manager(&mcsat->tm);
702✔
968
  delete_int_queue(&mcsat->registration_queue);
702✔
969
  delete_int_hset(&mcsat->registration_cache);
702✔
970
  delete_ivector(&mcsat->assertion_vars);
702✔
971
  delete_ivector(&mcsat->assertion_terms_original);
702✔
972
  delete_ivector(&mcsat->assertions_tmp);
702✔
973
  trail_destruct(mcsat->trail);
702✔
974
  safe_free(mcsat->trail);
702✔
975
  variable_db_destruct(mcsat->var_db);
702✔
976
  safe_free(mcsat->var_db);
702✔
977
  preprocessor_destruct(&mcsat->preprocessor);
702✔
978
  delete_ivector(&mcsat->top_decision_vars);
702✔
979
  delete_int_queue(&mcsat->hinted_decision_vars);
702✔
980
  var_queue_destruct(&mcsat->var_queue);
702✔
981
  delete_ivector(&mcsat->plugin_lemmas);
702✔
982
  delete_ivector(&mcsat->plugin_definition_lemmas);
702✔
983
  delete_ivector(&mcsat->plugin_definition_vars);
702✔
984
  statistics_destruct(&mcsat->stats);
702✔
985
  scope_holder_destruct(&mcsat->scope);
702✔
986
  delete_ivector(&mcsat->assumption_vars);
702✔
987
  delete_int_hset(&mcsat->internal_kinds);
702✔
988
}
702✔
989

990
mcsat_solver_t* mcsat_new(const context_t* ctx) {
695✔
991
  mcsat_solver_t* mcsat = (mcsat_solver_t*) safe_malloc(sizeof(mcsat_solver_t));
695✔
992
  mcsat_construct(mcsat, ctx);
695✔
993
  return mcsat;
695✔
994
}
995

996

997
smt_status_t mcsat_status(const mcsat_solver_t* mcsat) {
11,301✔
998
  return mcsat->status;
11,301✔
999
}
1000

1001
static
1002
void mcsat_notify_plugins(mcsat_solver_t* mcsat, plugin_notify_kind_t kind) {
118,034✔
1003
  uint32_t i;
1004
  plugin_t* plugin;
1005

1006
  for (i = 0; i < mcsat->plugins_count; ++ i) {
826,238✔
1007
    plugin = mcsat->plugins[i].plugin;
708,204✔
1008
    if (plugin->event_notify) {
708,204✔
1009
      plugin->event_notify(plugin, kind);
354,102✔
1010
    }
1011
  }
1012
}
118,034✔
1013

1014
void mcsat_reset(mcsat_solver_t* mcsat) {
7✔
1015
  // Reset everything
1016
  const context_t* ctx = mcsat->ctx;
7✔
1017
  mcsat_destruct(mcsat);
7✔
1018
  mcsat_construct(mcsat, ctx);
7✔
1019
}
7✔
1020

1021
static
1022
void mcsat_push_internal(mcsat_solver_t* mcsat) {
774,257✔
1023
  uint32_t i;
1024
  plugin_t* plugin;
1025

1026
  // Push the plugins
1027
  for (i = 0; i < mcsat->plugins_count; ++ i) {
5,419,799✔
1028
    plugin = mcsat->plugins[i].plugin;
4,645,542✔
1029
    if (plugin->push) {
4,645,542✔
1030
      plugin->push(plugin);
3,871,285✔
1031
    }
1032
  }
1033
}
774,257✔
1034

1035
static
1036
void mcsat_pop_internal(mcsat_solver_t* mcsat) {
766,438✔
1037
  uint32_t i;
1038
  plugin_t* plugin;
1039
  ivector_t* unassigned;
1040

1041
  // Pop the plugins
1042
  for (i = 0; i < mcsat->plugins_count; ++ i) {
5,365,066✔
1043
    plugin = mcsat->plugins[i].plugin;
4,598,628✔
1044
    if (plugin->pop) {
4,598,628✔
1045
      plugin->pop(plugin);
3,832,190✔
1046
    }
1047
  }
1048

1049
  // Re-add the variables that were unassigned
1050
  unassigned = trail_get_unassigned(mcsat->trail);
766,438✔
1051
  for (i = 0; i < unassigned->size; ++ i) {
7,695,260✔
1052
    var_queue_insert(&mcsat->var_queue, unassigned->data[i]);
6,928,822✔
1053
  }
1054
  ivector_reset(unassigned);
766,438✔
1055

1056
  // remove all the hints
1057
  int_queue_reset(&mcsat->hinted_decision_vars);
766,438✔
1058
}
766,438✔
1059

1060
static
1061
void mcsat_backtrack_to(mcsat_solver_t* mcsat, uint32_t level, bool update_cache);
1062

1063
static
1064
void mcsat_gc(mcsat_solver_t* mcsat, bool mark_and_gc_internal);
1065

1066
void mcsat_push(mcsat_solver_t* mcsat) {
1,325✔
1067

1068
  assert(mcsat->status == YICES_STATUS_IDLE); // We must have clear before
1069

1070
  if (trace_enabled(mcsat->ctx->trace, "mcsat::push")) {
1,325✔
1071
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat::push start\n");
×
1072
    trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1073
  }
1074

1075
  if (!mcsat_is_consistent(mcsat)) {
1,325✔
1076
    mcsat->inconsistent_push_calls ++;
798✔
1077
    return;
798✔
1078
  }
1079

1080
  // Internal stuff push
1081
  scope_holder_push(&mcsat->scope,
527✔
1082
      &mcsat->assertion_vars.size,
1083
      &mcsat->assertion_terms_original.size,
1084
      &mcsat->plugin_definition_lemmas.size,
1085
      NULL);
1086
  // Regular push for the internal data structures
1087
  mcsat_push_internal(mcsat);
527✔
1088
  // Push and set the base level on the trail
1089
  trail_new_base_level(mcsat->trail);
527✔
1090
  // Push the preprocessor
1091
  preprocessor_push(&mcsat->preprocessor);
527✔
1092

1093
  if (trace_enabled(mcsat->ctx->trace, "mcsat::push")) {
527✔
1094
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat::pop end\n");
×
1095
    trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1096
  }
1097

1098
  mcsat->interpolant = NULL_TERM;
527✔
1099
}
1100

1101

1102
void mcsat_pop(mcsat_solver_t* mcsat) {
1,241✔
1103

1104
  // External pop:
1105
  // - internal pop
1106
  // - assertions
1107
  // - variables and terms
1108

1109
  if (trace_enabled(mcsat->ctx->trace, "mcsat::pop")) {
1,241✔
1110
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat::pop start\n");
×
1111
    trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1112
  }
1113

1114
  if (mcsat->inconsistent_push_calls > 0) {
1,241✔
1115
    mcsat->inconsistent_push_calls --;
788✔
1116
    mcsat->status = YICES_STATUS_IDLE;
788✔
1117
    return;
788✔
1118
  }
1119

1120
  // Backtrack trail
1121
  uint32_t new_base_level = trail_pop_base_level(mcsat->trail);
453✔
1122

1123
  // Backtrack solver
1124
  mcsat_backtrack_to(mcsat, new_base_level, false);
453✔
1125

1126
  // Internal stuff pop
1127
  uint32_t assertion_vars_size = 0;
453✔
1128
  uint32_t assertion_terms_size = 0;
453✔
1129
  uint32_t definition_lemmas_size = 0;
453✔
1130
  scope_holder_pop(&mcsat->scope,
453✔
1131
      &assertion_vars_size,
1132
      &assertion_terms_size,
1133
      &definition_lemmas_size,
1134
      NULL);
1135
  ivector_shrink(&mcsat->assertion_vars, assertion_vars_size);
453✔
1136
  ivector_shrink(&mcsat->assertion_terms_original, assertion_terms_size);
453✔
1137

1138
  // Pop the preprocessor
1139
  preprocessor_pop(&mcsat->preprocessor);
453✔
1140

1141
  // Notify all the plugins that we just popped
1142
  mcsat_notify_plugins(mcsat, MCSAT_SOLVER_POP);
453✔
1143

1144
  // Garbage collect
1145
  mcsat_gc(mcsat, false);
453✔
1146
  (*mcsat->solver_stats.gc_calls) ++;
453✔
1147

1148
  // Definition lemmas (keep the ones that need the definition (variable still active)
1149
  uint32_t lemma_i = definition_lemmas_size, lemma_to_keep = definition_lemmas_size;
453✔
1150
  for (; lemma_i < mcsat->plugin_definition_lemmas.size; ++ lemma_i) {
1,016✔
1151
    term_t lemma = mcsat->plugin_definition_lemmas.data[lemma_i];
563✔
1152
    term_t variable = mcsat->plugin_definition_vars.data[lemma_i];
563✔
1153
    if (variable_db_has_variable(mcsat->var_db, variable)) {
563✔
1154
      mcsat->plugin_definition_lemmas.data[lemma_to_keep] = lemma;
563✔
1155
      mcsat->plugin_definition_vars.data[lemma_to_keep] = variable;
563✔
1156
      lemma_to_keep ++;
563✔
1157
    }
1158
  }
1159
  ivector_shrink(&mcsat->plugin_definition_lemmas, lemma_to_keep);
453✔
1160
  ivector_shrink(&mcsat->plugin_definition_vars, lemma_to_keep);
453✔
1161
  mcsat->plugin_definition_lemmas_i = definition_lemmas_size;
453✔
1162
  if (definition_lemmas_size < mcsat->plugin_definition_lemmas.size) {
453✔
1163
    mcsat_assert_formulas(mcsat, 0, NULL);
81✔
1164
  }
1165

1166
  // Set the status back to idle
1167
  mcsat->status = YICES_STATUS_IDLE;
453✔
1168
  mcsat->interpolant = NULL_TERM;
453✔
1169

1170
  if (trace_enabled(mcsat->ctx->trace, "mcsat::pop")) {
453✔
1171
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat::pop end\n");
×
1172
    trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1173
  }
1174
}
1175

1176
void mcsat_clear(mcsat_solver_t* mcsat) {
632✔
1177
  // Clear to be ready for more assertions:
1178
  // - Pop internal to base level
1179
  mcsat->assumption_i = 0;
632✔
1180
  mcsat->assumptions_decided_level = -1;
632✔
1181
  mcsat_backtrack_to(mcsat, mcsat->trail->decision_level_base, true);
632✔
1182
  mcsat->status = YICES_STATUS_IDLE;
632✔
1183
  mcsat->interpolant = NULL_TERM; // BD
632✔
1184
}
632✔
1185

1186
/**
1187
 * Get the indices of the plugins that claim to own the term t by type.
1188
 */
1189
static inline
1190
void mcsat_get_type_owners(mcsat_solver_t* mcsat, term_t t, int_mset_t* owners) {
194,830✔
1191
  uint32_t i, plugin_i;
1192
  i = type_kind(mcsat->types, term_type(mcsat->terms, t));
194,830✔
1193
  plugin_i = mcsat->type_owners[i];
194,830✔
1194
  assert(plugin_i != MCSAT_MAX_PLUGINS);
1195
  do  {
1196
    int_mset_add(owners, plugin_i);
194,830✔
1197
    i += NUM_TYPE_KINDS;
194,830✔
1198
    plugin_i = mcsat->type_owners[i];
194,830✔
1199
  } while (plugin_i != MCSAT_MAX_PLUGINS);
194,830✔
1200
}
194,830✔
1201

1202
/**
1203
 * Get the indices of the plugins that claim to own the term t by kind.
1204
 */
1205
static inline
1206
void mcsat_get_kind_owners(mcsat_solver_t* mcsat, term_t t, int_mset_t* owners) {
166,231✔
1207
  uint32_t i, plugin_i;
1208
  i = term_kind(mcsat->terms, t);
166,231✔
1209
  plugin_i = mcsat->kind_owners[i];
166,231✔
1210
  if (trace_enabled(mcsat->ctx->trace, "mcsat::get_kind_owner")) {
166,231✔
1211
    mcsat_trace_printf(mcsat->ctx->trace, "get_kind_owner: ");
×
1212
    trace_term_ln(mcsat->ctx->trace, mcsat->terms, t);
×
1213
  }
1214
  assert(plugin_i != MCSAT_MAX_PLUGINS || i == UNINTERPRETED_TERM || i == CONSTANT_TERM);
1215
  while (plugin_i != MCSAT_MAX_PLUGINS) {
332,055✔
1216
    int_mset_add(owners, plugin_i);
165,824✔
1217
    i += NUM_TERM_KINDS;
165,824✔
1218
    plugin_i = mcsat->kind_owners[i];
165,824✔
1219
  };
1220
}
166,231✔
1221

1222

1223
static void mcsat_process_registration_queue(mcsat_solver_t* mcsat) {
1,424,761✔
1224
  term_t t;
1225
  uint32_t i, plugin_i;
1226
  plugin_t* plugin;
1227
  plugin_trail_token_t prop_token;
1228
  int_mset_t to_notify;
1229
  ivector_t* to_notify_list;
1230

1231
  int_mset_construct(&to_notify, MCSAT_MAX_PLUGINS);
1,424,761✔
1232

1233
  while (!int_queue_is_empty(&mcsat->registration_queue)) {
1,600,525✔
1234
    // Next term to register
1235
    t = int_queue_pop(&mcsat->registration_queue);
175,764✔
1236
    assert(is_pos_term(t));
1237

1238
    if (trace_enabled(mcsat->ctx->trace, "mcsat::registration")) {
175,764✔
1239
      mcsat_trace_printf(mcsat->ctx->trace, "term registration: ");
×
1240
      trace_term_ln(mcsat->ctx->trace, mcsat->terms, t);
×
1241
    }
1242

1243
    // Get who to notify
1244
    int_mset_clear(&to_notify);
175,764✔
1245

1246
    // We notify the owners of the term type
1247
    mcsat_get_type_owners(mcsat, t, &to_notify);
175,764✔
1248

1249
    // We also notify the term kind owners, except for equality
1250
    term_kind_t kind = term_kind(mcsat->terms, t);
175,764✔
1251
    if (kind == EQ_TERM) {
175,764✔
1252
      mcsat_get_type_owners(mcsat, composite_term_arg(mcsat->terms, t, 0), &to_notify);
9,533✔
1253
      mcsat_get_type_owners(mcsat, composite_term_arg(mcsat->terms, t, 1), &to_notify);
9,533✔
1254
    } else {
1255
      mcsat_get_kind_owners(mcsat, t, &to_notify);
166,231✔
1256
    }
1257

1258
    // Notify
1259
    to_notify_list = int_mset_get_list(&to_notify);
175,764✔
1260
    for (i = 0; i < to_notify_list->size; ++i) {
450,587✔
1261
      plugin_i = to_notify_list->data[i];
274,823✔
1262
      plugin = mcsat->plugins[plugin_i].plugin;
274,823✔
1263
      trail_token_construct(&prop_token, mcsat->plugins[plugin_i].plugin_ctx, variable_null);
274,823✔
1264
      plugin->new_term_notify(plugin, t, (trail_token_t*) &prop_token);
274,823✔
1265
    }
1266
  }
1267

1268
  int_mset_destruct(&to_notify);
1,424,761✔
1269
}
1,424,761✔
1270

1271
/** Pass true to mark terms and types in the internal yices term tables */
1272
static
1273
void mcsat_gc(mcsat_solver_t* mcsat, bool mark_and_gc_internal) {
545✔
1274

1275
  uint32_t i;
1276
  variable_t var;
1277
  gc_info_t gc_vars;
1278
  plugin_t* plugin;
1279

1280
  if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
545✔
1281
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc():\n");
×
1282
    mcsat_show_stats(mcsat, mcsat->ctx->trace->file);
×
1283
  }
1284

1285
  // Mark previously used term in the term table
1286
  // set_bitvector(mcsat->terms->mark, mcsat->terms_size_on_solver_entry);
1287

1288
  // Construct the variable info
1289
  gc_info_construct(&gc_vars, variable_null, true);
545✔
1290

1291
  if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
545✔
1292
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc(): marking\n");
×
1293
  }
1294

1295
  // Mark the assertion variables as needed
1296
  for (i = 0; i < mcsat->assertion_vars.size; ++ i) {
27,121✔
1297
    var = mcsat->assertion_vars.data[i];
26,576✔
1298
    assert(variable_db_is_variable(mcsat->var_db, var, true));
1299
    gc_info_mark(&gc_vars, var);
26,576✔
1300
    if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
26,576✔
1301
      mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc(): marking ");
×
1302
      trace_term_ln(mcsat->ctx->trace, mcsat->terms, variable_db_get_term(mcsat->var_db, var));
×
1303
    }
1304
  }
1305
  for (i = 0; i < mcsat->assumption_vars.size; ++ i) {
548✔
1306
    var = mcsat->assumption_vars.data[i];
3✔
1307
    assert(variable_db_is_variable(mcsat->var_db, var, true));
1308
    gc_info_mark(&gc_vars, var);
3✔
1309
    if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
3✔
1310
      mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc(): marking ");
×
1311
      trace_term_ln(mcsat->ctx->trace, mcsat->terms, variable_db_get_term(mcsat->var_db, var));
×
1312
    }
1313
  }
1314

1315
  // Mark the decision hints if there are any
1316
  for (i = 0; i < int_queue_size(&mcsat->hinted_decision_vars); ++ i) {
545✔
1317
    gc_info_mark(&gc_vars, int_queue_at(&mcsat->hinted_decision_vars, i));
×
1318
  }
1319
  for (i = 0; i < mcsat->top_decision_vars.size; ++i) {
548✔
1320
    gc_info_mark(&gc_vars, mcsat->top_decision_vars.data[i]);
3✔
1321
  }
1322

1323
  // Mark the trail variables as needed
1324
  trail_gc_mark(mcsat->trail, &gc_vars);
545✔
1325

1326
  // Mark variables by plugins
1327
  for (;;) {
1328

1329
    // Mark with each plugin
1330
    for (i = 0; i < mcsat->plugins_count; ++ i) {
9,212✔
1331
      if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
7,896✔
1332
        mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc(): marking with %s\n", mcsat->plugins[i].plugin_name);
×
1333
      }
1334
      plugin = mcsat->plugins[i].plugin;
7,896✔
1335
      if (plugin->gc_mark) {
7,896✔
1336
        plugin->gc_mark(plugin, &gc_vars);
6,580✔
1337
      }
1338
    }
1339

1340
    // If any new ones marked, go to the new level and continue marking
1341
    if (gc_info_get_level_size(&gc_vars) > 0) {
1,316✔
1342
      gc_info_new_level(&gc_vars);
771✔
1343
    } else {
1344
      // Nothing new marked
1345
      break;
545✔
1346
    }
1347
  }
1348

1349
  if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
545✔
1350
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc(): sweeping\n");
×
1351
  }
1352

1353
  // Collect the unused variables
1354
  variable_db_gc_sweep(mcsat->var_db, &gc_vars);
545✔
1355

1356
  // Do the sweep
1357
  for (i = 0; i < mcsat->plugins_count; ++ i) {
3,815✔
1358
    plugin = mcsat->plugins[i].plugin;
3,270✔
1359
    if (plugin->gc_sweep) {
3,270✔
1360
      plugin->gc_sweep(plugin, &gc_vars);
2,725✔
1361
    }
1362
  }
1363

1364
  // Trail sweep
1365
  trail_gc_sweep(mcsat->trail, &gc_vars);
545✔
1366

1367
  // Variable queue sweep
1368
  var_queue_gc_sweep(&mcsat->var_queue, &gc_vars);
545✔
1369

1370
  // If asked mark all the terms
1371
  if (mark_and_gc_internal) {
545✔
1372
    for (i = 0; i < gc_vars.marked.size; ++ i) {
24✔
1373
      variable_t x = gc_vars.marked.data[i];
19✔
1374
      term_t x_term = variable_db_get_term(mcsat->var_db, x);
19✔
1375
      term_t x_type = term_type(mcsat->terms, x_term);
19✔
1376
      term_table_set_gc_mark(mcsat->terms, index_of(x_term));
19✔
1377
      type_table_set_gc_mark(mcsat->types, x_type);
19✔
1378
    }
1379

1380
    // Mark with each plugin
1381
    for (i = 0; i < mcsat->plugins_count; ++ i) {
35✔
1382
      if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
30✔
1383
        mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc(): marking with %s\n", mcsat->plugins[i].plugin_name);
×
1384
      }
1385
      plugin = mcsat->plugins[i].plugin;
30✔
1386
      if (plugin->gc_mark_and_clear) {
30✔
1387
        plugin->gc_mark_and_clear(plugin);
5✔
1388
      }
1389
    }
1390

1391
    // Mark with the preprocessor
1392
    preprocessor_gc_mark(&mcsat->preprocessor);
5✔
1393
  }
1394

1395
  // Done, destruct
1396
  gc_info_destruct(&gc_vars);
545✔
1397

1398
  // Remove terms from registration cache
1399
  int_hset_t new_registration_cache;
1400
  init_int_hset(&new_registration_cache, 0);
545✔
1401
  int_hset_close(&mcsat->registration_cache);
545✔
1402
  for (i = 0; i < mcsat->registration_cache.nelems; ++ i) {
288,381✔
1403
    term_t t = mcsat->registration_cache.data[i];
287,836✔
1404
    variable_t x = variable_db_get_variable_if_exists(mcsat->var_db, t);
287,836✔
1405
    if (x != variable_null) {
287,836✔
1406
      int_hset_add(&new_registration_cache, t);
271,300✔
1407
    }
1408
  }
1409
  delete_int_hset(&mcsat->registration_cache);
545✔
1410
  mcsat->registration_cache = new_registration_cache;
545✔
1411

1412
  // Garbage collect with yices
1413
  // term_table_gc(mcsat->terms, 1);
1414

1415
  if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
545✔
1416
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc(): done\n");
×
1417
  }
1418
}
545✔
1419

1420
static
1421
void mcsat_backtrack_to(mcsat_solver_t* mcsat, uint32_t level, bool update_cache) {
298,581✔
1422
  assert((int32_t) level >= mcsat->assumptions_decided_level);
1423
  while (mcsat->trail->decision_level > level) {
1,065,018✔
1424

1425
    if (trace_enabled(mcsat->ctx->trace, "mcsat::incremental")) {
766,437✔
1426
      trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1427
    }
1428

1429
    // Pop the trail
1430
    trail_pop(mcsat->trail);
766,437✔
1431

1432
    if (trace_enabled(mcsat->ctx->trace, "mcsat::incremental")) {
766,437✔
1433
      trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1434
    }
1435

1436
    // Pop the plugins
1437
    mcsat_pop_internal(mcsat);
766,437✔
1438
  }
1439

1440
  // save target cache (when backtracking)
1441
  if (update_cache) trail_update_extra_cache(mcsat->trail);
298,581✔
1442
}
298,581✔
1443

1444
static 
1445
uint32_t mcsat_partial_restart_level(mcsat_solver_t *mcsat) {
×
1446
  // If heap is empty, we go to base level
1447
  if (var_queue_is_empty(&mcsat->var_queue)) {
×
1448
    return mcsat->trail->decision_level_base;
×
1449
  }
1450

1451
  uint32_t base = mcsat->trail->decision_level_base;
×
1452
  uint32_t n = mcsat->trail->decision_level;
×
1453
  uint32_t target_level = UINT32_MAX;
×
1454
  variable_t x = mcsat->var_queue.heap[1];
×
1455
  double ax = var_queue_get_activity(&mcsat->var_queue, x);
×
1456
  // Most active unassigned variable in the heap
1457
  while (!var_queue_is_empty(&mcsat->var_queue)) {
×
1458
    x = var_queue_pop(&mcsat->var_queue);
×
1459
    if (!trail_has_value(mcsat->trail, x)) {
×
1460
      ax = var_queue_get_activity(&mcsat->var_queue, x);
×
1461
      var_queue_insert(&mcsat->var_queue, x);
×
1462
      break;
×
1463
    }
1464
  }
1465

1466
  // Scan the trail for decision variables
1467
  for (uint32_t i = 0; i < mcsat->trail->elements.size; ++i) {
×
1468
    variable_t v = mcsat->trail->elements.data[i];
×
1469
    if (trail_get_assignment_type(mcsat->trail, v) == DECISION) {
×
1470
      uint32_t level = trail_get_level(mcsat->trail, v);
×
1471
      if (level > base && level <= n) {
×
1472
        double v_activity = var_queue_get_activity(&mcsat->var_queue, v);
×
1473
        //printf("  Level %u: decision var %d (activity %g)\n", level, v, v_activity);
1474
        if (v_activity < ax) {
×
1475
          //printf("  Backtracking to level %u\n", level - 1);
1476
          target_level = level - 1;
×
1477
          break;
×
1478
        }
1479
      }
1480
    }
1481
  }
1482
  if (target_level != UINT32_MAX) {
×
1483
    return target_level;
×
1484
  }
1485

1486
  return base;
×
1487
}
1488

1489
static
1490
void mcsat_process_requests(mcsat_solver_t* mcsat) {
860,561✔
1491

1492
  if (mcsat->pending_requests) {
860,561✔
1493

1494
    // Restarts
1495
    if (mcsat->pending_requests_all.restart) {
20,985✔
1496
      // save target cache before restart
1497
      trail_update_extra_cache(mcsat->trail);
20,891✔
1498

1499
      if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
20,891✔
1500
        mcsat_trace_printf(mcsat->ctx->trace, "restarting\n");
×
1501
      }
1502

1503
      // Determine the backtrack level for restart:
1504
      // If partial_restart is enabled, use mcsat_partial_restart_level to compute the level.
1505
      // Otherwise, perform a full restart by backtracking to the base level.
1506
      uint32_t backtrack_level = mcsat->trail->decision_level_base;
20,891✔
1507
      if (mcsat->ctx->mcsat_options.partial_restart) {
20,891✔
1508
        backtrack_level = mcsat_partial_restart_level(mcsat);
×
1509
      }
1510
      if (backtrack_level == mcsat->trail->decision_level_base) {
20,891✔
1511
        mcsat->assumptions_decided_level = -1;
20,891✔
1512
        mcsat->assumption_i = 0;
20,891✔
1513
      }
1514
      mcsat_backtrack_to(mcsat, backtrack_level, false);
20,891✔
1515
      mcsat->pending_requests_all.restart = false;
20,891✔
1516
      // notify if backtracked to base level
1517
      if (backtrack_level == mcsat->trail->decision_level_base) {
20,891✔
1518
        (*mcsat->solver_stats.restarts) ++;
20,891✔
1519
        mcsat_notify_plugins(mcsat, MCSAT_SOLVER_RESTART);
20,891✔
1520
      } else {
1521
        (*mcsat->solver_stats.partial_restarts) ++;
×
1522
      }
1523
    }
1524

1525
    // GC
1526
    if (mcsat->pending_requests_all.gc_calls) {
20,985✔
1527
      if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
87✔
1528
        mcsat_trace_printf(mcsat->ctx->trace, "garbage collection\n");
×
1529
      }
1530
      mcsat_gc(mcsat, false);
87✔
1531
      mcsat->pending_requests_all.gc_calls = false;
87✔
1532
      (*mcsat->solver_stats.gc_calls) ++;
87✔
1533
    }
1534

1535
    // recache target cache
1536
    if (mcsat->pending_requests_all.recache) {
20,985✔
1537
      mcsat->pending_requests_all.recache = false;
94✔
1538
      trail_recache(mcsat->trail, (*mcsat->solver_stats.recaches));
94✔
1539
      (*mcsat->solver_stats.recaches) ++;
94✔
1540
    }
1541

1542
    // All services
1543
    mcsat->pending_requests = false;
20,985✔
1544
  }
1545
}
860,561✔
1546

1547
/**
1548
 * Perform propagation by running all plugins in sequence. Stop if a conflict
1549
 * is encountered.
1550
 */
1551
static
1552
bool mcsat_propagate(mcsat_solver_t* mcsat, bool run_learning) {
1,034,512✔
1553

1554
  assert(int_queue_is_empty(&mcsat->registration_queue));
1555

1556
  uint32_t plugin_i;
1557
  plugin_t* plugin;
1558
  plugin_trail_token_t prop_token;
1559
  bool someone_propagated;
1560

1561
  do {
1562
    // Repeat until no plugin makes any progress
1563
    someone_propagated = false;
1,557,275✔
1564
    // Propagate with all the plugins in turn
1565
    for (plugin_i = 0; mcsat_is_consistent(mcsat) && plugin_i < mcsat->plugins_count; ++ plugin_i) {
10,302,559✔
1566
      if (trace_enabled(mcsat->ctx->trace, "mcsat::propagate")) {
8,745,284✔
1567
        mcsat_trace_printf(mcsat->ctx->trace, "mcsat_propagate(): propagating with %s\n", mcsat->plugins[plugin_i].plugin_name);
×
1568
      }
1569
      // Make the token
1570
      trail_token_construct(&prop_token, mcsat->plugins[plugin_i].plugin_ctx, variable_null);
8,745,284✔
1571
      // Propagate
1572
      plugin = mcsat->plugins[plugin_i].plugin;
8,745,284✔
1573
      if (plugin->propagate) {
8,745,284✔
1574
        plugin->propagate(plugin, (trail_token_t*) &prop_token);
7,298,614✔
1575
      }
1576
      if (prop_token.used > 0) {
8,745,284✔
1577
        someone_propagated = true;
724,377✔
1578
      }
1579
    }
1580
    // If at base level, plugins can do some more expensive learning/propagation
1581
    if (run_learning && !someone_propagated && trail_is_at_base_level(mcsat->trail)) {
1,557,275✔
1582
      // Propagate with all the plugins in turn
1583
      for (plugin_i = 0; mcsat_is_consistent(mcsat) && plugin_i < mcsat->plugins_count; ++ plugin_i) {
7,411✔
1584
        if (trace_enabled(mcsat->ctx->trace, "mcsat::propagate")) {
6,348✔
1585
          mcsat_trace_printf(mcsat->ctx->trace, "mcsat_propagate(): learning with %s\n", mcsat->plugins[plugin_i].plugin_name);
×
1586
        }
1587
        // Make the token
1588
        trail_token_construct(&prop_token, mcsat->plugins[plugin_i].plugin_ctx, variable_null);
6,348✔
1589
        // Propagate
1590
        plugin = mcsat->plugins[plugin_i].plugin;
6,348✔
1591
        if (plugin->learn) {
6,348✔
1592
          plugin->learn(plugin, (trail_token_t*) &prop_token);
2,126✔
1593
        }
1594
        if (prop_token.used > 0) {
6,348✔
1595
          someone_propagated = true;
46✔
1596
        }
1597
      }
1598
    }
1599
  } while (someone_propagated && mcsat_is_consistent(mcsat));
1,557,275✔
1600

1601
  return someone_propagated;
1,034,512✔
1602
}
1603

1604
static
1605
void mcsat_assert_formula(mcsat_solver_t* mcsat, term_t f) {
78,711✔
1606

1607
  term_t f_pos;
1608
  variable_t f_pos_var;
1609

1610
  if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
78,711✔
1611
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_assert_formula()\n");
×
1612
    trace_term_ln(mcsat->ctx->trace, mcsat->terms, f);
×
1613
  }
1614

1615
  // If we're unsat, no more assertions
1616
  if (!mcsat_is_consistent(mcsat)) {
78,711✔
1617
    return;
172✔
1618
  }
1619

1620
  (*mcsat->solver_stats.assertions) ++;
78,539✔
1621

1622
  assert(trail_is_at_base_level(mcsat->trail));
1623
  assert(int_queue_is_empty(&mcsat->registration_queue));
1624

1625
  // Add the terms
1626
  f_pos = unsigned_term(f);
78,539✔
1627
  f_pos_var = variable_db_get_variable(mcsat->var_db, f_pos);
78,539✔
1628
  mcsat_process_registration_queue(mcsat);
78,539✔
1629

1630
  // Remember the assertion
1631
  ivector_push(&mcsat->assertion_vars, f_pos_var);
78,539✔
1632

1633
  // Assert the formula
1634
  if (f_pos == f) {
78,539✔
1635
    // f = true
1636
    if (!trail_has_value(mcsat->trail, f_pos_var)) {
75,505✔
1637
      trail_add_propagation(mcsat->trail, f_pos_var, &mcsat_value_true, MCSAT_MAX_PLUGINS, mcsat->trail->decision_level);
50,520✔
1638
    } else {
1639
      // If negative already, we're inconsistent
1640
      if (!trail_get_boolean_value(mcsat->trail, f_pos_var)) {
24,985✔
1641
        trail_set_inconsistent(mcsat->trail);
4✔
1642
        return;
4✔
1643
      }
1644
    }
1645
  } else {
1646
    // f = false
1647
    if (!trail_has_value(mcsat->trail, f_pos_var)) {
3,034✔
1648
      trail_add_propagation(mcsat->trail, f_pos_var, &mcsat_value_false, MCSAT_MAX_PLUGINS, mcsat->trail->decision_level);
2,965✔
1649
    } else {
1650
      // If positive already, we're inconsistent
1651
      if (trail_get_boolean_value(mcsat->trail, f_pos_var)) {
69✔
1652
        trail_set_inconsistent(mcsat->trail);
40✔
1653
        return;
40✔
1654
      }
1655
    }
1656
  }
1657

1658
  // Do propagation
1659
  mcsat_propagate(mcsat, false);
78,495✔
1660
}
1661

1662
/**
1663
 * Decide one of the unassigned literals. Decide the first literal that is bigger
1664
 * than the given bound (to make sure we decide on t(x) instead of x).
1665
 */
1666
static
1667
bool mcsat_decide_one_of(mcsat_solver_t* mcsat, ivector_t* literals, term_t bound) {
61,850✔
1668

1669
  uint32_t i, unassigned_count;
1670
  term_t literal;
1671
  term_t literal_pos;
1672
  variable_t literal_var;
1673

1674
  term_t to_decide_lit = NULL_TERM;
61,850✔
1675
  term_t to_decide_atom = NULL_TERM;
61,850✔
1676
  variable_t to_decide_var = variable_null;
61,850✔
1677

1678
  for (i = 0, unassigned_count = 0; i < literals->size; ++ i) {
114,354✔
1679

1680
    literal = literals->data[i];
62,161✔
1681
    literal_pos = unsigned_term(literal);
62,161✔
1682
    literal_var = variable_db_get_variable_if_exists(mcsat->var_db, literal_pos);
62,161✔
1683

1684
    assert(literal_var != variable_null);
1685

1686
    if (trace_enabled(mcsat->ctx->trace, "mcsat::lemma")) {
62,161✔
1687
      mcsat_trace_printf(mcsat->ctx->trace, "trying undecided :\n");
×
1688
      trace_term_ln(mcsat->ctx->trace, mcsat->ctx->terms, literal);
×
1689
    }
1690

1691
    // Can be decided?
1692
    if (!trail_has_value(mcsat->trail, literal_var)) {
62,161✔
1693
      unassigned_count ++;
9,660✔
1694
      if (trace_enabled(mcsat->ctx->trace, "mcsat::lemma")) {
9,660✔
1695
        mcsat_trace_printf(mcsat->ctx->trace, "unassigned!\n");
×
1696
      }
1697
      if (bound == NULL_TERM || literal_pos > bound) {
9,660✔
1698
        to_decide_lit = literal;
9,657✔
1699
        to_decide_atom = literal_pos;
9,657✔
1700
        to_decide_var = literal_var;
9,657✔
1701
        break;
9,657✔
1702
      }
1703
    } else {
1704
      if (trace_enabled(mcsat->ctx->trace, "mcsat::lemma")) {
52,501✔
1705
        mcsat_trace_printf(mcsat->ctx->trace, "assigned!\n");
×
1706
      }
1707
    }
1708
  }
1709

1710
  if (to_decide_var != variable_null) {
61,850✔
1711
    if (trace_enabled(mcsat->ctx->trace, "mcsat::lemma")) {
9,657✔
1712
      mcsat_trace_printf(mcsat->ctx->trace, "picked:\n");
×
1713
      trace_term_ln(mcsat->ctx->trace, mcsat->ctx->terms, to_decide_lit);
×
1714
    }
1715
    mcsat_push_internal(mcsat);
9,657✔
1716
    const mcsat_value_t* value = to_decide_atom == to_decide_lit ? &mcsat_value_true : &mcsat_value_false;
9,657✔
1717
    trail_add_decision(mcsat->trail, to_decide_var, value, MCSAT_MAX_PLUGINS);
9,657✔
1718
    return true;
9,657✔
1719
  } else {
1720
    if (unassigned_count > 0) {
52,193✔
1721
      // Couldn't find a bound decision, do arbitrary
1722
      return mcsat_decide_one_of(mcsat, literals, NULL_TERM);
×
1723
    }
1724
    return false;
52,193✔
1725
  }
1726
}
1727

1728
/**
1729
 * Add a lemma (a disjunction). Each lemma needs to lead to some progress. This
1730
 * means that:
1731
 *  * no literal should evaluate to true
1732
 *  * if only one literal is false, it should be propagated by one of the plugins
1733
 *  * if more then one literals is false, one of them should be decided to true
1734
 *    by one of the plugins
1735
 */
1736
static
1737
void mcsat_add_lemma(mcsat_solver_t* mcsat, ivector_t* lemma, term_t decision_bound) {
95,456✔
1738

1739
  uint32_t i, level, top_level;
1740
  ivector_t unassigned;
1741
  term_t disjunct, disjunct_pos;
1742
  variable_t disjunct_pos_var;
1743
  plugin_t* plugin;
1744

1745
  (*mcsat->solver_stats.lemmas)++;
95,456✔
1746

1747
  // assert(int_queue_is_empty(&mcsat->registration_queue));
1748
  // TODO: revisit this. it's done in integer solver to do splitting in
1749
  // conflict analysis
1750

1751
  if (trace_enabled(mcsat->ctx->trace, "mcsat::lemma")) {
95,456✔
1752
    mcsat_trace_printf(mcsat->ctx->trace, "lemma:\n");
×
1753
    for (i = 0; i < lemma->size; ++ i) {
×
1754
      mcsat_trace_printf(mcsat->ctx->trace, "\t");
×
1755
      trace_term_ln(mcsat->ctx->trace, mcsat->ctx->terms, lemma->data[i]);
×
1756
    }
1757
    trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1758
  }
1759

1760
  init_ivector(&unassigned, 0);
95,456✔
1761

1762
  top_level = mcsat->trail->decision_level_base;
95,456✔
1763
  for (i = 0; i < lemma->size; ++ i) {
1,439,417✔
1764

1765
    // Get the variables for the disjunct
1766
    disjunct = lemma->data[i];
1,343,961✔
1767
    assert(term_type_kind(mcsat->terms, disjunct) == BOOL_TYPE);
1768
    disjunct_pos = unsigned_term(disjunct);
1,343,961✔
1769
    disjunct_pos_var = variable_db_get_variable(mcsat->var_db, disjunct_pos);
1,343,961✔
1770
    if (trace_enabled(mcsat->ctx->trace, "mcsat::lemma")) {
1,343,961✔
1771
      mcsat_trace_printf(mcsat->ctx->trace, "literal: ");
×
1772
      variable_db_print_variable(mcsat->var_db, disjunct_pos_var, stderr);
×
1773
      if (trail_has_value(mcsat->trail, disjunct_pos_var)) {
×
1774
        mcsat_trace_printf(mcsat->ctx->trace, "\nvalue: ");
×
1775
        const mcsat_value_t* value = trail_get_value(mcsat->trail, disjunct_pos_var);
×
1776
        mcsat_value_print(value, stderr);
×
1777
        mcsat_trace_printf(mcsat->ctx->trace, "\n");
×
1778
      } else {
1779
        mcsat_trace_printf(mcsat->ctx->trace, "\nno value\n");
×
1780
      }
1781
    }
1782

1783
    // Process any newly registered variables
1784
    mcsat_process_registration_queue(mcsat);
1,343,961✔
1785

1786
    // Check if the literal has value (only negative allowed)
1787
    if (trail_has_value(mcsat->trail, disjunct_pos_var)) {
1,343,961✔
1788
      assert(trail_get_value(mcsat->trail, disjunct_pos_var)->type == VALUE_BOOLEAN);
1789
      assert(trail_get_value(mcsat->trail, disjunct_pos_var)->b == (disjunct != disjunct_pos));
1790
      level = trail_get_level(mcsat->trail, disjunct_pos_var);
1,204,960✔
1791
      if (level > top_level) {
1,204,960✔
1792
        top_level = level;
175,133✔
1793
      }
1794
    } else {
1795
      ivector_push(&unassigned, lemma->data[i]);
139,001✔
1796
    }
1797
  }
1798

1799
  assert(unassigned.size > 0);
1800
  assert(top_level <= mcsat->trail->decision_level);
1801

1802
  // Backtrack to the appropriate level and do some progress
1803
  if (unassigned.size == 1) {
95,456✔
1804
    // UIP, just make sure we're not going below assumptions
1805
    if ((int32_t) top_level >= mcsat->assumptions_decided_level) {
85,454✔
1806
      mcsat_backtrack_to(mcsat, top_level, false);
85,426✔
1807
    }
1808
  } else {
1809
    // Non-UIP, we're already below, and we'll split on a new term, that's enough
1810
  }
1811

1812
  uint32_t old_trail_size = mcsat->trail->elements.size;
95,456✔
1813

1814
  // Notify the plugins about the lemma
1815
  for (i = 0; i < mcsat->plugins_count; ++ i) {
668,192✔
1816
    plugin = mcsat->plugins[i].plugin;
572,736✔
1817
    if (plugin->new_lemma_notify) {
572,736✔
1818
      // Make the token
1819
      plugin_trail_token_t prop_token;
1820
      trail_token_construct(&prop_token, mcsat->plugins[i].plugin_ctx, variable_null);
286,368✔
1821
      plugin->new_lemma_notify(plugin, lemma, (trail_token_t*) &prop_token);
286,368✔
1822
    }
1823
  }
1824

1825
  // Propagate any
1826
  mcsat_propagate(mcsat, false);
95,456✔
1827
  bool propagated = old_trail_size < mcsat->trail->elements.size;
95,456✔
1828

1829
  // Decide a literal if necessary. At this point, if it was UIP they are all
1830
  // assigned. If not, we assign arbitrary.
1831
  bool decided = false;
95,456✔
1832
  bool consistent = mcsat_is_consistent(mcsat);
95,456✔
1833
  if (consistent) {
95,456✔
1834
    decided = mcsat_decide_one_of(mcsat, &unassigned, decision_bound);
61,850✔
1835
  }
1836
  if(trace_enabled(mcsat->ctx->trace, "mcsat::lemma") && !(propagated || !consistent || decided)) {
95,456✔
1837
    trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1838
  }
1839
  assert(propagated || !consistent || decided);
1840

1841
  delete_ivector(&unassigned);
95,456✔
1842
}
95,456✔
1843

1844
uint32_t mcsat_get_lemma_weight(mcsat_solver_t* mcsat, const ivector_t* lemma, lemma_weight_type_t type) {
95,456✔
1845
  uint32_t i, weight = 0;
95,456✔
1846
  term_t atom;
1847
  variable_t atom_var;
1848
  int_mset_t levels;
1849

1850
  switch(type) {
95,456✔
1851
  case LEMMA_WEIGHT_UNIT:
×
1852
    weight = 1;
×
1853
    break;
×
1854
  case LEMMA_WEIGHT_SIZE:
95,456✔
1855
    weight = lemma->size;
95,456✔
1856
    break;
95,456✔
1857
  case LEMMA_WEIGHT_GLUE:
×
1858
    int_mset_construct(&levels, UINT32_MAX);
×
1859
    for (i = 0; i < lemma->size; ++ i) {
×
1860
      atom = unsigned_term(lemma->data[i]);
×
1861
      atom_var = variable_db_get_variable_if_exists(mcsat->var_db, atom);
×
1862
      assert(atom_var != variable_null);
1863
      if (trail_has_value(mcsat->trail, atom_var)) {
×
1864
        int_mset_add(&levels, trail_get_level(mcsat->trail, atom_var));
×
1865
      }
1866
    }
1867
    weight = int_mset_get_list(&levels)->size;
×
1868
    int_mset_destruct(&levels);
×
1869
    break;
×
1870
  }
1871

1872
  return weight;
95,456✔
1873
}
1874

1875
/** Check propagation with Yices: reasons => x = subst */
1876
static
1877
void propagation_check(const ivector_t* reasons, term_t x, term_t subst) {
×
1878
#ifdef THREAD_SAFE
1879
   (void) reasons;
1880
   (void) x;
1881
   (void) subst;
1882
   return;
1883
#else
1884
   context_t* ctx = _o_yices_new_context(NULL);
×
1885
   uint32_t i;
1886
   for (i = 0; i < reasons->size; ++i) {
×
1887
     term_t literal = reasons->data[i];
×
1888
     int32_t ret = _o_yices_assert_formula(ctx, literal);
×
1889
     if (ret != 0) {
×
1890
       // unsupported by regular yices
1891
       fprintf(stderr, "skipping propagation (ret 1)\n");
×
1892
       yices_print_error(stderr);
×
1893
       _o_yices_free_context(ctx);
×
1894
       return;
×
1895
     }
1896
   }
1897
   term_t eq = _o_yices_eq(x, subst);
×
1898
   int32_t ret = _o_yices_assert_formula(ctx, opposite_term(eq));
×
1899
   if (ret != 0) {
×
1900
     fprintf(stderr, "skipping propagation (ret 2)\n");
×
1901
     yices_print_error(stderr);
×
1902
     _o_yices_free_context(ctx);
×
1903
     return;
×
1904
   }
1905
   smt_status_t result = check_context(ctx, NULL);
×
1906
   (void) result;
1907
   assert(result == YICES_STATUS_UNSAT);
1908
   _o_yices_free_context(ctx);
×
1909
#endif
1910
}
1911

1912
static
1913
uint32_t mcsat_compute_backtrack_level(mcsat_solver_t* mcsat, uint32_t level) {
95,664✔
1914
  uint32_t backtrack_level = mcsat->trail->decision_level_base;
95,664✔
1915
  if (backtrack_level < level)
95,664✔
1916
    backtrack_level = level;
95,628✔
1917
  if ((int32_t) backtrack_level <= mcsat->assumptions_decided_level)
95,664✔
1918
    backtrack_level = mcsat->assumptions_decided_level;
46✔
1919
  return backtrack_level;
95,664✔
1920
}
1921

1922
/**
1923
 * Input: literals that can evaluate to true (or false if negated)
1924
 * Output: simplified literals that can evaluate to true and imply the input literals
1925
 */
1926
static
1927
void mcsat_simplify_literals(mcsat_solver_t* mcsat, ivector_t* literals, bool literals_negated, ivector_t* out_literals) {
44✔
1928
  uint32_t i;
1929
  for (i = 0; i < literals->size; ++ i) {
174✔
1930
    term_t disjunct = literals->data[i];
130✔
1931
    if (literals_negated) {
130✔
1932
      disjunct = opposite_term(disjunct);
130✔
1933
    }
1934
    term_kind_t kind = term_kind(mcsat->terms, disjunct);
130✔
1935
    if (int_hset_member(&mcsat->internal_kinds, kind)) {
130✔
1936
      uint32_t kind_i = kind;
15✔
1937
      bool simplified = false;
15✔
1938
      for (; !simplified && mcsat->kind_owners[kind_i] != MCSAT_MAX_PLUGINS; kind_i += NUM_TERM_KINDS) {
30✔
1939
        plugin_t* plugin = mcsat->plugins[mcsat->kind_owners[kind_i]].plugin;
15✔
1940
        if (plugin->simplify_conflict_literal) {
15✔
1941
          simplified = plugin->simplify_conflict_literal(plugin, disjunct, out_literals);
15✔
1942
        }
1943
      }
1944
      assert(simplified);
1945
    } else {
1946
      ivector_push(out_literals, disjunct);
115✔
1947
    }
1948
  }
1949
}
44✔
1950

1951
static
1952
term_t mcsat_analyze_final(mcsat_solver_t* mcsat, conflict_t* input_conflict) {
44✔
1953

1954
  variable_t var;
1955
  plugin_t* plugin = NULL;
44✔
1956
  //  uint32_t plugin_i = MCSAT_MAX_PLUGINS; // BD: infer dead store
1957
  uint32_t plugin_i;
1958
  tracer_t* trace = mcsat->ctx->trace;
44✔
1959
  term_t substitution;
1960

1961
  // First we try to massage the conflict into presentable form
1962
  ivector_t literals;
1963
  init_ivector(&literals, 0);
44✔
1964
  conflict_get_negated_literals(input_conflict, &literals);
44✔
1965

1966
  ivector_t reason_literals;
1967
  init_ivector(&reason_literals, 0);
44✔
1968

1969
  assert(mcsat->trail->elements.size > 0);
1970

1971
  mcsat_trail_t* trail = mcsat->trail;
44✔
1972

1973
  conflict_t conflict;
1974
  conflict_construct(&conflict, &literals, false, (mcsat_evaluator_interface_t*) &mcsat->evaluator, mcsat->var_db, trail, &mcsat->tm, trace);
44✔
1975

1976
  // We save the trail, and then restore at the end
1977
  mcsat_trail_t saved_trail;
1978
  trail_construct_copy(&saved_trail, mcsat->trail);
44✔
1979

1980
  // Analyze while at least one variable at conflict level
1981
  while (trail_size(mcsat->trail) > 0) {
1,296✔
1982

1983
    // Variable we might be resolving
1984
    var = trail_back(mcsat->trail);
1,252✔
1985

1986
    if (trace_enabled(trace, "mcsat::conflict")) {
1,252✔
1987
      mcsat_trace_printf(trace, "current trail:\n");
×
1988
      trail_print(trail, trace->file);
×
1989
      mcsat_trace_printf(trace, "current conflict: ");
×
1990
      conflict_print(&conflict, trace->file);
×
1991
      mcsat_trace_printf(trace, "var: ");
×
1992
      variable_db_print_variable(mcsat->var_db, var, trace->file);
×
1993
      mcsat_trace_printf(trace, "\n");
×
1994
    }
1995

1996
    // Skip decisions
1997
    if (trail_get_assignment_type(mcsat->trail, var) == DECISION) {
1,252✔
1998
      trail_pop_decision(mcsat->trail);
156✔
1999
      conflict_recompute_level_info(&conflict);
156✔
2000
      continue;
156✔
2001
    }
2002

2003
    // Skip the conflict variable (it was propagated)
2004
    if (var == mcsat->variable_in_conflict) {
1,096✔
2005
      trail_pop_propagation(mcsat->trail);
7✔
2006
      conflict_recompute_level_info(&conflict);
7✔
2007
      continue;
7✔
2008
    }
2009

2010
    if (conflict_contains(&conflict, var)) {
1,089✔
2011
      // Get the plugin that performed the propagation
2012
      plugin_i = trail_get_source_id(trail, var);
309✔
2013
      if (plugin_i != MCSAT_MAX_PLUGINS) {
309✔
2014
        plugin = mcsat->plugins[plugin_i].plugin;
280✔
2015
      } else {
2016
        plugin = NULL;
29✔
2017
      }
2018

2019
      if (trace_enabled(trace, "mcsat::conflict")) {
309✔
2020
        mcsat_trace_printf(trace, "resolving ");
×
2021
        variable_db_print_variable(mcsat->var_db, var, trace->file);
×
2022
        if (plugin) {
×
2023
          mcsat_trace_printf(trace, " with %s\n", mcsat->plugins[plugin_i].plugin_name);
×
2024
        } else {
2025
          mcsat_trace_printf(trace, " with assertion\n");
×
2026
        }
2027
        mcsat_trace_printf(trace, "current conflict:\n");
×
2028
        conflict_print(&conflict, trace->file);
×
2029
      }
2030

2031
      // Resolve the variable
2032
      ivector_reset(&literals);
309✔
2033
      if (plugin) {
309✔
2034
        assert(plugin->explain_propagation);
2035
        substitution = plugin->explain_propagation(plugin, var, &literals);
280✔
2036
      } else {
2037
        bool value = trail_get_boolean_value(trail, var);
29✔
2038
        substitution = value ? true_term : false_term;
29✔
2039
      }
2040
      conflict_resolve_propagation(&conflict, var, substitution, &literals);
309✔
2041
    } else {
2042
      // Continue with resolution
2043
      trail_pop_propagation(mcsat->trail);
780✔
2044
    }
2045
  }
2046

2047
  if (trace_enabled(trace, "mcsat::conflict")) {
44✔
2048
    mcsat_trace_printf(trace, "final conflict:\n");
×
2049
    conflict_print(&conflict, trace->file);
×
2050
  }
2051

2052
  // Restore the trail
2053
  mcsat_trail_t tmp;
2054
  tmp = *mcsat->trail;
44✔
2055
  *mcsat->trail = saved_trail;
44✔
2056
  saved_trail = tmp;
44✔
2057
  trail_destruct(&saved_trail);
44✔
2058

2059
  // Simplify the conflict literals
2060
  ivector_t* final_literals = conflict_get_literals(&conflict);
44✔
2061
  ivector_reset(&literals);
44✔
2062
  mcsat_simplify_literals(mcsat, final_literals, true, &literals);
44✔
2063

2064
  // Construct the interpolant
2065
  term_t interpolant = literals.size == 0 ? true_term : mk_and(&mcsat->tm, literals.size, literals.data);
44✔
2066
  interpolant = opposite_term(interpolant);
44✔
2067

2068
  if (trace_enabled(trace, "mcsat::interpolant::check")) {
44✔
2069
    value_t v = model_get_term_value(mcsat->assumptions_model, interpolant);
×
2070
    bool interpolant_is_false = is_false(&mcsat->assumptions_model->vtbl, v);
×
2071
    if (!interpolant_is_false) {
×
2072
      fprintf(trace_out(trace), "model:\n");
×
2073
      model_print(trace_out(trace), mcsat->assumptions_model);
×
2074
      fprintf(trace_out(trace), "interpolant:\n");
×
2075
      trace_term_ln(trace, conflict.terms, interpolant);
×
2076
    }
2077
    assert(interpolant_is_false);
2078
  }
2079

2080
  // Remove temps
2081
  delete_ivector(&literals);
44✔
2082
  delete_ivector(&reason_literals);
44✔
2083
  conflict_destruct(&conflict);
44✔
2084

2085
  if (trace_enabled(trace, "mcsat::conflict")) {
44✔
2086
    mcsat_trace_printf(trace, "interpolant:\n");
×
2087
    trace_term_ln(trace, conflict.terms, interpolant);
×
2088
  }
2089

2090
  return interpolant;
44✔
2091
}
2092

2093
static
2094
bool mcsat_conflict_with_assumptions(mcsat_solver_t* mcsat, uint32_t conflict_level) {
2,667,795✔
2095
  // If we decided some assumptions, then backtracked under that level
2096
  if ((int32_t) conflict_level <= mcsat->assumptions_decided_level) {
2,667,795✔
2097
    return true;
92✔
2098
  }
2099
  // If we haven't decided any assumptions yet but there is a conflict
2100
  if (trail_is_at_base_level(mcsat->trail) && mcsat->assumption_vars.size > 0) {
2,667,703✔
2101
    return true;
4✔
2102
  }
2103
  return false;
2,667,699✔
2104
}
2105

2106
static
2107
void mcsat_analyze_conflicts(mcsat_solver_t* mcsat, uint32_t* restart_resource) {
95,551✔
2108

2109
  conflict_t conflict;
2110
  plugin_t* plugin = NULL;
95,551✔
2111
  uint32_t plugin_i = MCSAT_MAX_PLUGINS;
95,551✔
2112
  tracer_t* trace;
2113

2114
  uint32_t conflict_level, backtrack_level;
2115
  variable_t var;
2116

2117
  term_t decision_bound = NULL_TERM;
95,551✔
2118

2119
  ivector_t reason;
2120
  term_t substitution;
2121

2122
  ivector_t* conflict_disjuncts;
2123

2124
  init_ivector(&reason, 0);
95,551✔
2125
  trace = mcsat->ctx->trace;
95,551✔
2126

2127
  // Plugin that's in conflict
2128
  if (mcsat->plugin_in_conflict) {
95,551✔
2129
    plugin_i = mcsat->plugin_in_conflict->ctx.plugin_id;
95,548✔
2130
    plugin = mcsat->plugins[plugin_i].plugin;
95,548✔
2131
  }
2132

2133
  if (trace_enabled(trace, "mcsat::conflict")) {
95,551✔
2134
    if (plugin_i != MCSAT_MAX_PLUGINS) {
×
2135
      mcsat_trace_printf(trace, "analyzing conflict from %s\n", mcsat->plugins[plugin_i].plugin_name);
×
2136
    } else {
2137
      mcsat_trace_printf(trace, "analyzing conflict from assertion\n");
×
2138
    }
2139
    mcsat_trace_printf(trace, "trail: ");
×
2140
    trail_print(mcsat->trail, trace->file);
×
2141
  }
2142

2143
  // Get the initial conflict
2144
  if (mcsat->variable_in_conflict != variable_null) {
95,551✔
2145
    // This conflict happened because an assumption conflicts with an already
2146
    // propagated value. We're unsat here, but we need to produce a clause
2147
    if (mcsat->ctx->mcsat_options.model_interpolation) {
14✔
2148
      if (plugin) {
8✔
2149
        term_t t = plugin->explain_propagation(plugin, mcsat->variable_in_conflict, &reason);
7✔
2150
        term_t x = variable_db_get_term(mcsat->var_db, mcsat->variable_in_conflict);
7✔
2151
        term_t x_eq_t = mk_eq(&mcsat->tm, x, t);
7✔
2152
        // reason => x_eq_t is valid
2153
        // reason && x_eq_t evaluates to false with assumptions
2154
        // but x_eq_t evaluates to true with trail
2155
        ivector_push(&reason, opposite_term(x_eq_t));
7✔
2156
        conflict_construct(&conflict, &reason, false, (mcsat_evaluator_interface_t*) &mcsat->evaluator, mcsat->var_db, mcsat->trail, &mcsat->tm, mcsat->ctx->trace);
7✔
2157
        mcsat->interpolant = mcsat_analyze_final(mcsat, &conflict);
7✔
2158
        conflict_destruct(&conflict);
7✔
2159
      } else {
2160
        // an assertion, interpolant is !assertion
2161
        mcsat->interpolant = variable_db_get_term(mcsat->var_db, mcsat->variable_in_conflict);
1✔
2162
        bool value = trail_get_boolean_value(mcsat->trail, mcsat->variable_in_conflict);
1✔
2163
        if (!value) {
1✔
2164
          mcsat->interpolant = opposite_term(mcsat->interpolant);
1✔
2165
        }
2166
      }
2167
    }
2168
    mcsat->status = YICES_STATUS_UNSAT;
14✔
2169
    mcsat->variable_in_conflict = variable_null;
14✔
2170
    // Assumption conflict can trigger this fast-path before the generic
2171
    // assumption-conflict cleanup below. Restore the trail to base level so
2172
    // context_pop remains valid after check-with-assumptions.
2173
    if (mcsat->assumptions_decided_level >= 0) {
14✔
2174
      mcsat->assumptions_decided_level = -1;
11✔
2175
      mcsat_backtrack_to(mcsat, mcsat->trail->decision_level_base, false);
11✔
2176
    }
2177
    delete_ivector(&reason);
14✔
2178
    return;
14✔
2179
  } else {
2180
    assert(plugin->get_conflict);
2181
    plugin->get_conflict(plugin, &reason);
95,537✔
2182
  }
2183

2184
  // Construct the conflict
2185
  conflict_construct(&conflict, &reason, true, (mcsat_evaluator_interface_t*) &mcsat->evaluator, mcsat->var_db, mcsat->trail, &mcsat->tm, mcsat->ctx->trace);
95,537✔
2186
  if (trace_enabled(trace, "mcsat::conflict::check")) {
95,537✔
2187
    // Don't check bool conflicts: they are implied by the formula (clauses)
2188
    if (plugin_i != mcsat->bool_plugin_id) {
×
2189
      conflict_check(&conflict);
×
2190
    }
2191
  }
2192
  statistic_avg_add(mcsat->solver_stats.avg_conflict_size, conflict.disjuncts.element_list.size);
95,537✔
2193

2194
  if (trace_enabled(trace, "mcsat::conflict") || trace_enabled(trace, "mcsat::lemma")) {
95,537✔
2195
    mcsat_trace_printf(trace, "conflict from %s\n", mcsat->plugins[plugin_i].plugin_name);
×
2196
    conflict_print(&conflict, trace->file);
×
2197
  }
2198

2199
  // Get the level of the conflict and backtrack to it
2200
  conflict_level = conflict_get_level(&conflict);
95,537✔
2201
  // Backtrack max(base, assumptions, conflict)
2202
  backtrack_level = mcsat_compute_backtrack_level(mcsat, conflict_level);
95,537✔
2203
  mcsat_backtrack_to(mcsat, backtrack_level, false);
95,537✔
2204

2205
  // Analyze while at least one variable at conflict level
2206
  while (true) {
2207

2208
    if (mcsat_conflict_with_assumptions(mcsat, conflict_level)) {
2,572,258✔
2209
      // Resolved below assumptions, we're done
2210
      break;
48✔
2211
    }
2212

2213
    if (conflict_level <= mcsat->trail->decision_level_base) {
2,572,210✔
2214
      // Resolved all the way
2215
      break;
33✔
2216
    }
2217

2218
    if (conflict_get_top_level_vars_count(&conflict) == 1) {
2,572,177✔
2219
      // UIP-like situation, we can quit as long as we make progress, as in
2220
      // the following cases:
2221
      //
2222
      // Assume finite basis B, with max{ term_size(t) | t in B } = M
2223
      //
2224
      // Termination based on weight(trail) = [..., weight(e), ...]
2225
      // - weight(propagation) = M + 1
2226
      // - weight(t -> d) = term_size(t)
2227
      //
2228
      // Max lex trail assuming finite basis:
2229
      // - [prop, ..., prop, decide variables/terms by term size]
2230
      //
2231
      // Termination, after we resolve, the weight goes up:
2232
      //
2233
      // Examples:
2234
      //   weight([b  , x -> T, y -> 0, (y + x < 0) -> 0]) =
2235
      //          [M+1, 1     , 1     , 5]
2236
      //
2237
      // [backjump-learn]
2238
      //   - Only one conflict literal contains the top variable.
2239
      //   * weight increases by replacing decision with propagation (M+1)
2240
      // [backjump-decide]
2241
      //   - More then one conflict literal contains the top variable.
2242
      //   - Top variable is decision t1 -> v
2243
      //   - Replace with decision t2 -> v where t2 is larger than t1
2244
      //   * weight increases by replacing decision with a heavier decision
2245
      ivector_t* conflict_top_vars = conflict_get_variables(&conflict);
97,671✔
2246
      assert(conflict_top_vars->size == 1);
2247
      variable_t top_var = conflict_top_vars->data[0];
97,671✔
2248
      if (trace_enabled(trace, "mcsat::conflict")) {
97,671✔
2249
        mcsat_trace_printf(trace, "potential UIP:\n");
×
2250
        variable_db_print_variable(mcsat->var_db, top_var, trace_out(trace));
×
2251
        mcsat_trace_printf(trace, "conflict:\n");
×
2252
        conflict_print(&conflict, trace->file);
×
2253
        mcsat_trace_printf(trace, "trail:\n");
×
2254
        trail_print(mcsat->trail, trace_out(trace));
×
2255
      }
2256
      // [backjump-learn]
2257
      uint32_t top_var_lits = conflict_get_literal_count_of(&conflict, top_var);
97,671✔
2258
      if (top_var_lits == 1) break;
97,671✔
2259
      // [backjump-decide]
2260
      assignment_type_t top_var_type = trail_get_assignment_type(mcsat->trail, top_var);
11,768✔
2261
      if (top_var_type == DECISION) {
11,768✔
2262
        // assert(variable_db_get_term(mcsat->var_db, top_var) < conflict_get_max_literal_of(&conflict, top_var));
2263
        decision_bound = variable_db_get_term(mcsat->var_db, top_var);
9,553✔
2264
        break;
9,553✔
2265
      }
2266
    }
2267

2268
    if (trace_enabled(trace, "mcsat::conflict")) {
2,476,721✔
2269
      mcsat_trace_printf(trace, "current trail:\n");
×
2270
      trail_print(mcsat->trail, trace->file);
×
2271
      mcsat_trace_printf(trace, "current conflict: ");
×
2272
      conflict_print(&conflict, trace->file);
×
2273
    }
2274

2275
    // Current variable
2276
    var = trail_back(mcsat->trail);
2,476,721✔
2277
    assert(trail_get_assignment_type(mcsat->trail, var) != DECISION);
2278

2279
    // Resolve if in the conflict and current level
2280
    if (conflict_contains(&conflict, var)) {
2,476,721✔
2281

2282
      // Get the plugin that performed the propagation
2283
      plugin_i = trail_get_source_id(mcsat->trail, var);
887,145✔
2284
      plugin = mcsat->plugins[plugin_i].plugin;
887,145✔
2285

2286
      if (trace_enabled(trace, "mcsat::conflict")) {
887,145✔
2287
        mcsat_trace_printf(trace, "resolving ");
×
2288
        variable_db_print_variable(mcsat->var_db, var, trace->file);
×
2289
        mcsat_trace_printf(trace, " with %s\n", mcsat->plugins[plugin_i].plugin_name);
×
2290
        mcsat_trace_printf(trace, "current conflict:\n");
×
2291
        conflict_print(&conflict, trace->file);
×
2292
      }
2293

2294
      // Resolve the variable
2295
      ivector_reset(&reason);
887,145✔
2296
      assert(plugin->explain_propagation);
2297
      substitution = plugin->explain_propagation(plugin, var, &reason);
887,145✔
2298
      if (trace_enabled(trace, "mcsat::propagation::check")) {
887,145✔
2299
        if (plugin_i != mcsat->bool_plugin_id) {
×
2300
          term_t var_term = variable_db_get_term(mcsat->var_db, var);
×
2301
          propagation_check(&reason, var_term, substitution);
×
2302
        } else {
2303
//          fprintf(stderr, "skipping propagation (bool)\n");
2304
        }
2305
      }
2306
      conflict_resolve_propagation(&conflict, var, substitution, &reason);
887,145✔
2307
      // The trail pops with the resolution step
2308
    } else {
2309
      // Have to pop the trail manually
2310
      trail_pop_propagation(mcsat->trail);
1,589,576✔
2311
      assert(!conflict_contains_as_top(&conflict, var));
2312
    }
2313

2314
    if (conflict_get_top_level_vars_count(&conflict) == 0) {
2,476,721✔
2315
      // We have resolved the conflict even lower
2316
      conflict_recompute_level_info(&conflict);
127✔
2317
      conflict_level = conflict_get_level(&conflict);
127✔
2318
      backtrack_level = mcsat_compute_backtrack_level(mcsat, conflict_level);
127✔
2319
      mcsat_backtrack_to(mcsat, backtrack_level, false);
127✔
2320
    }
2321
  }
2322

2323
  if (trace_enabled(trace, "mcsat::conflict")) {
95,537✔
2324
    mcsat_trace_printf(trace, "current conflict: ");
×
2325
    conflict_print(&conflict, trace->file);
×
2326
  }
2327

2328
  if (mcsat_conflict_with_assumptions(mcsat, conflict_level)) {
95,537✔
2329
    mcsat->status = YICES_STATUS_UNSAT;
48✔
2330
    if (mcsat->ctx->mcsat_options.model_interpolation) {
48✔
2331
      mcsat->interpolant = mcsat_analyze_final(mcsat, &conflict);
37✔
2332
    }
2333
    mcsat->assumptions_decided_level = -1;
48✔
2334
    mcsat_backtrack_to(mcsat, mcsat->trail->decision_level_base, false);
48✔
2335
  } else if (conflict_level <= mcsat->trail->decision_level_base) {
95,489✔
2336
    mcsat->status = YICES_STATUS_UNSAT;
33✔
2337
  } else {
2338
    assert(conflict_get_top_level_vars_count(&conflict) == 1);
2339
    // We should still be in conflict, so back out
2340
    assert(conflict.level == mcsat->trail->decision_level);
2341
    mcsat_backtrack_to(mcsat, mcsat->trail->decision_level - 1, true);
95,456✔
2342

2343
    // Get the literals
2344
    conflict_disjuncts = conflict_get_literals(&conflict);
95,456✔
2345

2346
    if (trace_enabled(trace, "mcsat::conflict")) {
95,456✔
2347
      mcsat_trace_printf(trace, "conflict_disjuncts:\n");
×
2348
      uint32_t i;
2349
      for (i = 0; i < conflict_disjuncts->size; ++i) {
×
2350
        mcsat_trace_printf(trace, "[%u]: ", i);
×
2351
        trace_term_ln(trace, mcsat->ctx->terms, conflict_disjuncts->data[i]);
×
2352
      }
2353
    }
2354

2355
    // Now add the lemma
2356
    mcsat_add_lemma(mcsat, conflict_disjuncts, decision_bound);
95,456✔
2357

2358
    // Use resources based on conflict size
2359
    *restart_resource += mcsat_get_lemma_weight(mcsat, conflict_disjuncts,
95,456✔
2360
        mcsat->heuristic_params.lemma_restart_weight_type);
2361

2362
    // Bump the variables
2363
    mcsat_bump_variables_mset(mcsat, conflict_get_variables_all(&conflict));
95,456✔
2364

2365
    if (trace_enabled(trace, "mcsat::conflict::trail")) {
95,456✔
2366
      mcsat_trace_printf(trace, "trail: ");
×
2367
      trail_print(mcsat->trail, trace->file);
×
2368
    }
2369
  }
2370

2371
  delete_ivector(&reason);
95,537✔
2372
  conflict_destruct(&conflict);
95,537✔
2373
}
2374

2375
static
2376
bool mcsat_decide_assumption(mcsat_solver_t* mcsat, model_t* mdl, uint32_t n_assumptions, const term_t assumptions[]) {
764,918✔
2377
  assert(!mcsat->trail->inconsistent);
2378

2379
  variable_t var;
2380
  term_t var_term;
2381
  mcsat_value_t var_mdl_value;
2382

2383
  uint32_t plugin_i;
2384
  plugin_t* plugin;
2385

2386
  plugin_trail_token_t decision_token;
2387

2388
  bool assumption_decided = false;
764,918✔
2389
  for (; !assumption_decided && mcsat->assumption_i < n_assumptions; mcsat->assumption_i ++) {
766,494✔
2390

2391
    // Break if any conflicts
2392
    if (mcsat->trail->inconsistent) {
1,577✔
2393
      break;
×
2394
    }
2395
    if (mcsat->variable_in_conflict != variable_null) {
1,577✔
2396
      break;
1✔
2397
    }
2398

2399
    // The variable (should exist already)
2400
    var_term = assumptions[mcsat->assumption_i];
1,576✔
2401
    var = variable_db_get_variable_if_exists(mcsat->var_db, var_term);
1,576✔
2402
    assert(var != variable_null);
2403
    // Get the owner that will 'decide' the value of the variable
2404
    plugin_i = mcsat->decision_makers[variable_db_get_type_kind(mcsat->var_db, var)];
1,576✔
2405
    assert(plugin_i != MCSAT_MAX_PLUGINS);
2406
    // The given value the variable in the provided model
2407
    value_t value = model_get_term_value(mdl, var_term);
1,576✔
2408
    mcsat_value_construct_from_value(&var_mdl_value, &mdl->vtbl, value);
1,576✔
2409

2410
    if (trace_enabled(mcsat->ctx->trace, "mcsat::decide")) {
1,576✔
2411
      mcsat_trace_printf(mcsat->ctx->trace, "mcsat_decide_assumption(): with %s\n", mcsat->plugins[plugin_i].plugin_name);
×
2412
      mcsat_trace_printf(mcsat->ctx->trace, "mcsat_decide_assumption(): variable ");
×
2413
      variable_db_print_variable(mcsat->var_db, var, trace_out(mcsat->ctx->trace));
×
2414
      mcsat_trace_printf(mcsat->ctx->trace, "\n");
×
2415
    }
2416

2417
    // If the variable already has a value in the trail check for consistency
2418
    if (trail_has_value(mcsat->trail, var)) {
1,576✔
2419
      // If the value is different from given value, we are in conflict
2420
      assert(trail_get_assignment_type(mcsat->trail, var) == PROPAGATION);
2421
      const mcsat_value_t* var_trail_value = trail_get_value(mcsat->trail, var);
14✔
2422
      bool eq = mcsat_value_eq(&var_mdl_value, var_trail_value);
14✔
2423
      if (!eq) {
14✔
2424
        // Who propagated the value (MCSAT_MAX_PLUGINS if an assertion)
2425
        plugin_i = trail_get_source_id(mcsat->trail, var);
14✔
2426
        if (plugin_i == MCSAT_MAX_PLUGINS) {
14✔
2427
          mcsat->plugin_in_conflict = NULL;
3✔
2428
        } else {
2429
          mcsat->plugin_in_conflict = mcsat->plugins[plugin_i].plugin_ctx;
11✔
2430
        }
2431
        mcsat->variable_in_conflict = var;
14✔
2432
      }
2433
    } else {
2434
      // Plugin used to check/decide
2435
      plugin = mcsat->plugins[plugin_i].plugin;
1,562✔
2436
      // Check if the decision is consistent (will report conflict if not)
2437
      if (!mcsat->trail->inconsistent) {
1,562✔
2438
        // Construct the token
2439
        trail_token_construct(&decision_token, mcsat->plugins[plugin_i].plugin_ctx, var);
1,562✔
2440
        // Decide with the owner plugin
2441
        mcsat_push_internal(mcsat);
1,562✔
2442
        assert(plugin->decide_assignment);
2443
        plugin->decide_assignment(plugin, var, &var_mdl_value, (trail_token_t*) &decision_token);
1,562✔
2444

2445
        // If decided, we're done
2446
        assert(decision_token.used);
2447
        if (trace_enabled(mcsat->ctx->trace, "mcsat::decide")) {
1,562✔
2448
          FILE* out = trace_out(mcsat->ctx->trace);
×
2449
          fprintf(out, "mcsat_decide_assumption(): value = ");
×
2450
          mcsat_value_print(trail_get_value(mcsat->trail, var), out);
×
2451
          fprintf(out, "\n");
×
2452
        }
2453
        // We've decided something!
2454
        assumption_decided = true;
1,562✔
2455
        mcsat->assumptions_decided_level = mcsat->trail->decision_level;
1,562✔
2456
      }
2457
    }
2458

2459
    // Remove temp
2460
    mcsat_value_destruct(&var_mdl_value);
1,576✔
2461
  }
2462

2463
  return assumption_decided;
764,918✔
2464
}
2465

2466
/**
2467
 * Finds the correct plugin for var and asks it to make a decision.
2468
 * Returns true if a decision was made on var.
2469
 */
2470
static
2471
bool mcsat_decide_var(mcsat_solver_t* mcsat, variable_t var, bool force_decision) {
762,511✔
2472
  // must be a valid variable that is not yet decided upon
2473
  assert(var != variable_null);
2474
  assert(!trail_has_value(mcsat->trail, var));
2475

2476
  uint32_t i;
2477
  plugin_t* plugin;
2478
  plugin_trail_token_t decision_token;
2479
  bool made_decision = false;
762,511✔
2480

2481
  // Get the owner that will decide that value of the variable
2482
  i = mcsat->decision_makers[variable_db_get_type_kind(mcsat->var_db, var)];
762,511✔
2483
  assert(i != MCSAT_MAX_PLUGINS);
2484
  // Construct the token
2485
  trail_token_construct(&decision_token, mcsat->plugins[i].plugin_ctx, var);
762,511✔
2486
  // Decide
2487
  if (trace_enabled(mcsat->ctx->trace, "mcsat::decide")) {
762,511✔
2488
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_decide(): with %s\n", mcsat->plugins[i].plugin_name);
×
2489
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_decide(): variable ");
×
2490
    variable_db_print_variable(mcsat->var_db, var, trace_out(mcsat->ctx->trace));
×
2491
    mcsat_trace_printf(mcsat->ctx->trace, "\n");
×
2492
  }
2493
  plugin = mcsat->plugins[i].plugin;
762,511✔
2494

2495
  // Ask the owner to decide
2496
  mcsat_push_internal(mcsat);
762,511✔
2497
  assert(plugin->decide);
2498
  plugin->decide(plugin, var, (trail_token_t*) &decision_token, force_decision);
762,511✔
2499

2500
  if (decision_token.used == 0) {
762,511✔
2501
    // If not decided, remember and go on
2502
    made_decision = false;
1✔
2503
    mcsat_pop_internal(mcsat);
1✔
2504
  } else {
2505
    made_decision = true;
762,510✔
2506
    // Decided, we can continue with the search
2507
    (*mcsat->solver_stats.decisions)++;
762,510✔
2508
    // Plugins are not allowed to cheat and decide on another variable
2509
    assert(trail_has_value(mcsat->trail, var));
2510
    if (trace_enabled(mcsat->ctx->trace, "mcsat::decide")) {
762,510✔
2511
      FILE* out = trace_out(mcsat->ctx->trace);
×
2512
      fprintf(out, "mcsat_decide(): value = ");
×
2513
      mcsat_value_print(trail_get_value(mcsat->trail, var), out);
×
2514
      fprintf(out, "\n");
×
2515
    }
2516
  }
2517

2518
  // a forced decision implies a made decision
2519
  assert(!force_decision || made_decision);
2520
  return made_decision;
762,511✔
2521
}
2522

2523
/**
2524
 * Decides a variable using one of the plugins. Returns true if a variable
2525
 * has been decided, or a conflict detected.
2526
 */
2527
static
2528
bool mcsat_decide(mcsat_solver_t* mcsat) {
763,342✔
2529

2530
  assert(!mcsat->trail->inconsistent);
2531

2532
  ivector_t skipped_variables; // Variables we took from the queue but plugin didn't decide
2533
  init_ivector(&skipped_variables, 0);
763,342✔
2534

2535
  variable_t var;
2536
  bool aux_choice; // indicates that var was not taken from the queue
2537
  bool force_decision = false;
763,342✔
2538
  double rand_freq = mcsat->heuristic_params.random_decision_freq;
763,342✔
2539

2540
  while (true) {
2541
    var = variable_null;
763,344✔
2542
    aux_choice = true;
763,344✔
2543

2544
    // Use the top variables first
2545
    for (uint32_t i = 0; i < mcsat->top_decision_vars.size; ++i) {
798,156✔
2546
      var = mcsat->top_decision_vars.data[i];
35,226✔
2547
      assert(var != variable_null);
2548
      if (!trail_has_value(mcsat->trail, var)) {
35,226✔
2549
        force_decision = true;
414✔
2550
        break;
414✔
2551
      }
2552
      var = variable_null;
34,812✔
2553
    }
2554

2555
    // If there is a fixed order that was passed in, try that
2556
    if (var == variable_null) {
763,344✔
2557
      const ivector_t* order = &mcsat->ctx->mcsat_var_order;
762,930✔
2558
      if (order->size > 0) {
762,930✔
2559
        if (trace_enabled(mcsat->ctx->trace, "mcsat::decide")) {
16✔
2560
          FILE* out = trace_out(mcsat->ctx->trace);
×
2561
          fprintf(out, "mcsat_decide(): var_order is ");
×
2562
          for (uint32_t i = 0; i < order->size; ++ i) {
×
2563
            term_print_to_file(out, mcsat->ctx->terms, order->data[i]);
×
2564
            fprintf(out, " ");
×
2565
          }
2566
          fprintf(out, "\n");
×
2567
        }
2568
        for (uint32_t i = 0; var == variable_null && i < order->size; ++i) {
43✔
2569
          term_t ovar_term = order->data[i];
27✔
2570
          variable_t ovar = variable_db_get_variable_if_exists(mcsat->var_db, ovar_term);
27✔
2571
          if (ovar == variable_null) continue; // Some variables are not used
27✔
2572
          if (!trail_has_value(mcsat->trail, ovar)) {
27✔
2573
            var = ovar;
13✔
2574
            force_decision = true;
13✔
2575
          }
2576
        }
2577
      }
2578
    }
2579

2580
    // then try the variables a plugin requested
2581
    if (var == variable_null) {
763,344✔
2582
      while (!int_queue_is_empty(&mcsat->hinted_decision_vars)) {
978,254✔
2583
        var = int_queue_pop(&mcsat->hinted_decision_vars);
352,569✔
2584
        assert(var != variable_null);
2585
        if (!trail_has_value(mcsat->trail, var)) {
352,569✔
2586
          force_decision = true;
137,232✔
2587
          break;
137,232✔
2588
        }
2589
        var = variable_null;
215,337✔
2590
      }
2591
    }
2592

2593
    // Random decision
2594
    if (var == variable_null && rand_freq > 0.0) {
763,344✔
2595
      double* seed = &mcsat->heuristic_params.random_decision_seed;
625,685✔
2596
      if (drand(seed) < rand_freq && !var_queue_is_empty(&mcsat->var_queue)) {
625,685✔
2597
        var = var_queue_random(&mcsat->var_queue, seed);
11,559✔
2598
        if (trail_has_value(mcsat->trail, var)) {
11,559✔
2599
          var = variable_null;
3,590✔
2600
        }
2601
      }
2602
    }
2603

2604
    if (var == variable_null) {
763,344✔
2605
      // No auxiliary choice performed
2606
      aux_choice = false;
617,716✔
2607
    }
2608

2609
    // Use the queue
2610
    while (!var_queue_is_empty(&mcsat->var_queue) && var == variable_null) {
2,813,469✔
2611
      // Get the next variable from the queue
2612
      var = var_queue_pop(&mcsat->var_queue);
1,286,781✔
2613
      // If already assigned go on
2614
      if (trail_has_value(mcsat->trail, var)) {
1,286,781✔
2615
        if (trace_enabled(mcsat->ctx->trace, "mcsat::decide")) {
669,898✔
2616
          FILE *out = trace_out(mcsat->ctx->trace);
×
2617
          fprintf(out, "mcsat_decide(): skipping ");
×
2618
          variable_db_print_variable(mcsat->var_db, var, out);
×
2619
          fprintf(out, "\n");
×
2620
        }
2621
        var = variable_null;
669,898✔
2622
        continue;
669,898✔
2623
      }
2624
    }
2625

2626
    if (var != variable_null) {
763,344✔
2627
      bool made_decision = mcsat_decide_var(mcsat, var, force_decision);
762,511✔
2628
      if (made_decision) {
762,511✔
2629
        break;
762,510✔
2630
      } else if (!aux_choice) {
1✔
2631
        ivector_push(&skipped_variables, var);
1✔
2632
      }
2633
    } else {
2634
      assert(!aux_choice);
2635
      // No variables left to decide
2636
      if (skipped_variables.size == 0) {
833✔
2637
        // Didn't skip any, we're done
2638
        break;
832✔
2639
      } else {
2640
        // Put the skipped back in the queue, and continue but force next decision
2641
        for (uint32_t i = 0; i < skipped_variables.size; ++ i) {
2✔
2642
          var_queue_insert(&mcsat->var_queue, skipped_variables.data[i]);
1✔
2643
        }
2644
        ivector_reset(&skipped_variables);
1✔
2645
        force_decision = true;
1✔
2646
      }
2647
    }
2648
  }
2649

2650
  // Put any skipped variables back into the queue
2651
  if (skipped_variables.size > 0) {
763,342✔
2652
    // If we skipped some, we had to decided one, we put the skipped scores to
2653
    // the decided score
2654
    assert(var != variable_null);
2655
    double var_score = var_queue_get_activity(&mcsat->var_queue, var);
×
2656
    for (uint32_t i = 0; i < skipped_variables.size; ++ i) {
×
2657
      variable_t skipped_var = skipped_variables.data[i];
×
2658
      var_queue_set_activity(&mcsat->var_queue, skipped_var, var_score);
×
2659
      var_queue_insert(&mcsat->var_queue, skipped_var);
×
2660
    }
2661
  }
2662

2663
  delete_ivector(&skipped_variables);
763,342✔
2664

2665
  return var != variable_null;
763,342✔
2666
}
2667

2668
typedef struct {
2669
  uint32_t u, v;
2670
  uint32_t restart_threshold;
2671
  uint32_t interval;
2672
} luby_t;
2673

2674
static inline
2675
void luby_init(luby_t* luby, uint32_t interval) {
1,033✔
2676
  luby->u = 1;
1,033✔
2677
  luby->v = 1;
1,033✔
2678
  luby->restart_threshold = interval;
1,033✔
2679
  luby->interval = interval;
1,033✔
2680
}
1,033✔
2681

2682
static inline
2683
void luby_next(luby_t* luby) {
20,891✔
2684
  if ((luby->u & -luby->u) == luby->v) {
20,891✔
2685
    luby->u ++;
10,581✔
2686
    luby->v = 1;
10,581✔
2687
  } else {
2688
    luby->v <<= 1;
10,310✔
2689
  }
2690
  luby->restart_threshold = luby->v * luby->interval;
20,891✔
2691
}
20,891✔
2692

2693
static
2694
void mcsat_check_model(mcsat_solver_t* mcsat, bool assert) {
×
2695
  // Check models
2696
  model_t model;
2697
  init_model(&model, mcsat->terms, true);
×
2698
  mcsat_build_model(mcsat, &model);
×
2699
  uint32_t i = 0;
×
2700
  for (i = 0; i < mcsat->assertion_terms_original.size; ++i) {
×
2701
    term_t assertion = mcsat->assertion_terms_original.data[i];
×
2702
    int32_t code = 0;
×
2703
    bool assertion_is_true = formula_holds_in_model(&model, assertion, &code);
×
2704
    if (false && !assertion_is_true) {
2705
      FILE *out = trace_out(mcsat->ctx->trace);
2706
      fprintf(out, "Assertion not true in model: ");
2707
      trace_term_ln(mcsat->ctx->trace, mcsat->terms, assertion);
2708
      fprintf(out, "In model:\n");
2709
      model_print(out, &model);
2710
    }
2711
    assert(!assert || assertion_is_true);
2712
  }
2713
  delete_model(&model);
×
2714
}
×
2715

2716
static
2717
void mcsat_assert_formulas_internal(mcsat_solver_t* mcsat, uint32_t n, const term_t *f, bool preprocess);
2718

2719
void mcsat_set_model_hint(mcsat_solver_t* mcsat, model_t* mdl, uint32_t n_mdl_filter,
12✔
2720
                          const term_t mdl_filter[]) {
2721
  if (n_mdl_filter == 0) {
12✔
2722
    return;
3✔
2723
  }
2724

2725
  assert(mdl != NULL);
2726
  assert(mdl_filter != NULL);
2727

2728
  value_table_t* vtbl = model_get_vtbl(mdl);
9✔
2729

2730
  trail_clear_cache(mcsat->trail);
9✔
2731
  trail_update_extra_cache(mcsat->trail);
9✔
2732

2733
  for (uint32_t i = 0; i < n_mdl_filter; ++i) {
18✔
2734
    term_t x = mdl_filter[i];
9✔
2735
    assert(term_kind(mcsat->terms, x) == UNINTERPRETED_TERM || term_kind(mcsat->terms, x) == VARIABLE);
2736
    assert(is_pos_term(x));
2737

2738
    variable_t x_var = variable_db_get_variable(mcsat->var_db, unsigned_term(x));    
9✔
2739
    value_t x_value = model_get_term_value(mdl, x);
9✔
2740
    mcsat_value_t value;
2741

2742
    mcsat_value_construct_from_value(&value, vtbl, x_value);
9✔
2743
    assert(x_value >= 0);
2744

2745
    trail_set_cached_value(mcsat->trail, x_var, &value);
9✔
2746
  }
2747

2748
  mcsat_process_registration_queue(mcsat);
9✔
2749
}
2750

2751
static
2752
void mcsat_set_initial_var_order(mcsat_solver_t* mcsat) {
1,033✔
2753
  const ivector_t* vars = &mcsat->ctx->mcsat_initial_var_order;
1,033✔
2754
  uint32_t n = vars->size;
1,033✔
2755
  if (n == 0) {
1,033✔
2756
    return;
1,032✔
2757
  }
2758

2759
  assert(vars != NULL);
2760

2761
  uint32_t i;
2762
  for (i = 0; i < n; ++i) {
3✔
2763
    term_t x = vars->data[i];
2✔
2764
    assert(term_kind(mcsat->terms, x) == UNINTERPRETED_TERM || term_kind(mcsat->terms, x) == VARIABLE);
2765
    variable_t v = variable_db_get_variable(mcsat->var_db, unsigned_term(x));
2✔
2766
    int_queue_push(&mcsat->hinted_decision_vars, v);
2✔
2767
    mcsat_process_registration_queue(mcsat);
2✔
2768
  }
2769
}
2770

2771
void mcsat_solve(mcsat_solver_t* mcsat, const param_t *params, model_t* mdl, uint32_t n_assumptions, const term_t assumptions[]) {
1,261✔
2772

2773
  uint32_t restart_resource;
2774
  luby_t luby;
2775

2776
  // Make sure we have variables for all the assumptions
2777
  if (n_assumptions > 0) {
1,261✔
2778
    if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
161✔
2779
      mcsat_trace_printf(mcsat->ctx->trace, "solving with assumptions\n");
×
2780
    }
2781
    assert(mcsat->assumption_vars.size == 0);
2782
    uint32_t i;
2783
    for (i = 0; i < n_assumptions; ++ i) {
1,378✔
2784
      // Apply the pre-processor. If the variable is substituted, we
2785
      // need to add the equality x = t
2786
      term_t x = assumptions[i];
1,217✔
2787
      assert(term_kind(mcsat->terms, x) == UNINTERPRETED_TERM || term_kind(mcsat->terms, x) == VARIABLE);
2788
      assert(is_pos_term(x));
2789
      term_t x_pre = preprocessor_apply(&mcsat->preprocessor, x, NULL, true);
1,217✔
2790
      if (x != x_pre) {
1,217✔
2791
        // Assert x = t although we solved it already :(
2792
        term_t eq = mk_eq(&mcsat->tm, x, x_pre);
4✔
2793
        mcsat_assert_formulas_internal(mcsat, 1, &eq, false);
4✔
2794
      }
2795
      // Make sure the variable is registered (maybe it doesn't appear in assertions)
2796
      variable_t x_var = variable_db_get_variable(mcsat->var_db, unsigned_term(x));
1,217✔
2797
      ivector_push(&mcsat->assumption_vars, x_var);
1,217✔
2798
      mcsat_process_registration_queue(mcsat);
1,217✔
2799
    }
2800
  }
2801

2802
  // Initialize assumption info
2803
  mcsat->interpolant = NULL_TERM;
1,261✔
2804
  mcsat->variable_in_conflict = variable_null;
1,261✔
2805
  mcsat->assumption_i = 0;
1,261✔
2806
  mcsat->assumptions_decided_level = -1;
1,261✔
2807
  mcsat->assumptions_model = mdl;
1,261✔
2808

2809
  // Start the search
2810
  mcsat->status = YICES_STATUS_SEARCHING;
1,261✔
2811

2812
  // If we're already unsat, just return
2813
  if (!mcsat_is_consistent(mcsat)) {
1,261✔
2814
    mcsat->interpolant = false_term;
228✔
2815
    mcsat->status = YICES_STATUS_UNSAT;
228✔
2816
    assert(int_queue_is_empty(&mcsat->registration_queue));
2817
    goto solve_done;
228✔
2818
  }
2819

2820
  if (trace_enabled(mcsat->ctx->trace, "mcsat::solve")) {
1,033✔
2821
    static int count = 0;
2822
    mcsat_trace_printf(mcsat->ctx->trace, "solve %d\n", count ++);
×
2823
  }
2824

2825
  // Remember existing terms
2826
  mcsat->terms_size_on_solver_entry = nterms(mcsat->terms);
1,033✔
2827

2828
  // Initialize for search
2829
  mcsat_heuristics_init(mcsat, params);
1,033✔
2830
  mcsat_notify_plugins(mcsat, MCSAT_SOLVER_START);
1,033✔
2831

2832
  // set initial variable order
2833
  mcsat_set_initial_var_order(mcsat);
1,033✔
2834

2835
  // Initialize the Luby sequence with interval 10
2836
  restart_resource = 0;
1,033✔
2837
  luby_init(&luby, mcsat->heuristic_params.restart_interval);
1,033✔
2838

2839
  // recache parameters
2840
  uint32_t recache_limit = (*mcsat->solver_stats.conflicts) + mcsat->heuristic_params.recache_interval;
1,033✔
2841
  uint32_t recache_round = 0;
1,033✔
2842

2843
  // Whether to run learning
2844
  bool learning = true;
1,033✔
2845

2846
  while (!mcsat->stop_search) {
860,561✔
2847

2848
    // Do we restart
2849
    if (mcsat_is_consistent(mcsat) && restart_resource > luby.restart_threshold) {
860,561✔
2850
      restart_resource = 0;
20,891✔
2851
      luby_next(&luby);
20,891✔
2852
      mcsat_request_restart(mcsat);
20,891✔
2853

2854
    } else if ((*mcsat->solver_stats.conflicts) > recache_limit) {
839,670✔
2855
      // recache
2856
      ++recache_round;
94✔
2857
      mcsat_request_recache(mcsat);
94✔
2858
      double l = log10(recache_round + 9);
94✔
2859
      recache_limit = (*mcsat->solver_stats.conflicts) +
94✔
2860
        (recache_round * l * l * l *  mcsat->heuristic_params.recache_interval);
94✔
2861
    }
2862

2863
    // Process any outstanding requests
2864
    mcsat_process_requests(mcsat);
860,561✔
2865

2866
    // Do propagation
2867
    mcsat_propagate(mcsat, learning);
860,561✔
2868
    learning = false;
860,561✔
2869

2870
    // If inconsistent, analyze the conflict
2871
    if (!mcsat_is_consistent(mcsat)) {
860,561✔
2872
      goto conflict;
95,643✔
2873
    }
2874

2875
    // If any requests, process them and go again
2876
    if (mcsat->pending_requests) {
764,918✔
2877
      continue;
×
2878
    }
2879

2880
    // Should we decide on an assumption
2881
    bool assumption_decided = mcsat_decide_assumption(mcsat, mdl, n_assumptions, assumptions);
764,918✔
2882
    if (assumption_decided) {
764,918✔
2883
      continue;
1,562✔
2884
    }
2885

2886
    // If inconsistent, analyze the conflict
2887
    if (!mcsat_is_consistent(mcsat)) {
763,356✔
2888
      goto conflict;
14✔
2889
    }
2890

2891
    // Time to make a decision
2892
    bool variable_decided = mcsat_decide(mcsat);
763,342✔
2893

2894
    // Decision made, continue with the search
2895
    if (variable_decided) {
763,342✔
2896
      continue;
762,510✔
2897
    }
2898

2899
    // If inconsistent, analyze the conflict
2900
    if (!mcsat_is_consistent(mcsat)) {
832✔
2901
      goto conflict;
×
2902
    }
2903

2904
    // Nothing to decide, we're satisfiable
2905
    mcsat->status = YICES_STATUS_SAT;
832✔
2906
    if (trace_enabled(mcsat->ctx->trace, "mcsat::model::check")) {
832✔
2907
      mcsat_check_model(mcsat, true);
×
2908
    }
2909

2910
    break;
832✔
2911

2912
  conflict:
95,657✔
2913

2914
    (*mcsat->solver_stats.conflicts)++;
95,657✔
2915
    mcsat_notify_plugins(mcsat, MCSAT_SOLVER_CONFLICT);
95,657✔
2916

2917
    // If at level 0 we're unsat
2918
    if (n_assumptions == 0 && trail_is_at_base_level(mcsat->trail)) {
95,657✔
2919
      mcsat->interpolant = false_term;
106✔
2920
      mcsat->status = YICES_STATUS_UNSAT;
106✔
2921
      break;
106✔
2922
    }
2923

2924
    // Analyze the conflicts
2925
    mcsat_analyze_conflicts(mcsat, &restart_resource);
95,551✔
2926

2927
    // Analysis might have discovered base level conflict
2928
    if (mcsat->status == YICES_STATUS_UNSAT) {
95,551✔
2929
      if (n_assumptions == 0) {
95✔
2930
        mcsat->interpolant = false_term;
33✔
2931
      }
2932
      break;
95✔
2933
    }
2934

2935
    // update the variable selection heuristic
2936
    var_queue_decay_activities(&mcsat->var_queue);
95,456✔
2937
  }
2938

2939
  if (mcsat->stop_search) {
1,033✔
2940
    if (mcsat->status == YICES_STATUS_SEARCHING) {
×
2941
      mcsat->status = YICES_STATUS_INTERRUPTED;
×
2942
    }
2943
    mcsat->stop_search = false;
×
2944
  }
2945

2946
  // Make sure any additional terms are registered
2947
  mcsat_process_registration_queue(mcsat);
1,033✔
2948

2949
solve_done:
1,261✔
2950
  ivector_reset(&mcsat->assumption_vars);
1,261✔
2951
}
1,261✔
2952

2953
void mcsat_cleanup_assumptions(mcsat_solver_t* mcsat) {
7✔
2954
  mcsat->assumptions_decided_level = -1;
7✔
2955
  if (!trail_is_at_base_level(mcsat->trail)) {
7✔
2956
    mcsat_backtrack_to(mcsat, mcsat->trail->decision_level_base, false);
×
2957
  }
2958
}
7✔
2959

2960
void mcsat_set_tracer(mcsat_solver_t* mcsat, tracer_t* tracer) {
284✔
2961
  uint32_t i;
2962
  mcsat_plugin_context_t* ctx;
2963

2964
  // Update the contexts with the new tracer
2965
  variable_db_set_tracer(mcsat->var_db, tracer);
284✔
2966
  for (i = 0; i < mcsat->plugins_count; ++ i) {
1,988✔
2967
    ctx = mcsat->plugins[i].plugin_ctx;
1,704✔
2968
    ctx->ctx.tracer = tracer;
1,704✔
2969
  }
2970

2971
  // Set the trace for the preprocessor
2972
  preprocessor_set_tracer(&mcsat->preprocessor, tracer);
284✔
2973
}
284✔
2974

2975

2976
void mcsat_flush_lemmas(mcsat_solver_t* mcsat, ivector_t* out) {
81,160✔
2977
  // Flush regular lemmas
2978
  ivector_add(out, mcsat->plugin_lemmas.data, mcsat->plugin_lemmas.size);
81,160✔
2979
  ivector_reset(&mcsat->plugin_lemmas);
81,160✔
2980

2981
  // Copy definition lemmas
2982
  uint32_t i = mcsat->plugin_definition_lemmas_i;
81,160✔
2983
  for (; i < mcsat->plugin_definition_lemmas.size; ++ i) {
82,754✔
2984
    ivector_push(out, mcsat->plugin_definition_lemmas.data[i]);
1,594✔
2985
  }
2986
  mcsat->plugin_definition_lemmas_i = mcsat->plugin_definition_lemmas.size;
81,160✔
2987
}
81,160✔
2988

2989
static
2990
void mcsat_assert_formulas_internal(mcsat_solver_t* mcsat, uint32_t n, const term_t *f, bool preprocess) {
2,449✔
2991
  uint32_t i;
2992

2993
  // Remember the original assertions
2994
  for (i = 0; i < n; ++ i) {
40,008✔
2995
    ivector_push(&mcsat->assertion_terms_original, f[i]);
37,559✔
2996
  }
2997

2998
  // Add any leftover lemmas
2999
  ivector_t* assertions = &mcsat->assertions_tmp;
2,449✔
3000
  ivector_reset(assertions);
2,449✔
3001
  mcsat_flush_lemmas(mcsat, assertions);
2,449✔
3002

3003
  // Preprocess the formulas (preprocessor might throw)
3004
  ivector_add(assertions, f, n);
2,449✔
3005

3006
  // Preprocess the formulas (preprocessor might throw)
3007
  if (preprocess) {
2,449✔
3008
    for (i = 0; i < assertions->size; ++ i) {
41,072✔
3009
      term_t f = assertions->data[i];
38,638✔
3010
      term_t f_pre = preprocessor_apply(&mcsat->preprocessor, f, assertions, true);
38,638✔
3011
      assertions->data[i] = f_pre;
38,627✔
3012
    }
3013
  }
3014

3015
  // Assert individual formulas
3016
  for (i = 0; i < assertions->size; ++ i) {
81,149✔
3017
    // Assert it
3018
    mcsat_assert_formula(mcsat, assertions->data[i]);
78,711✔
3019
    // Add any lemmas that were added
3020
    mcsat_flush_lemmas(mcsat, assertions);
78,711✔
3021
  }
3022

3023
  // Delete the temp
3024
  ivector_reset(assertions);
2,438✔
3025
}
2,438✔
3026

3027
int32_t mcsat_assert_formulas(mcsat_solver_t* mcsat, uint32_t n, const term_t *f) {
2,445✔
3028
  mcsat_assert_formulas_internal(mcsat, n, f, true);
2,445✔
3029
  mcsat->interpolant = NULL_TERM;
2,434✔
3030
  return CTX_NO_ERROR;
2,434✔
3031
}
3032

3033
void mcsat_show_stats(mcsat_solver_t* mcsat, FILE* out) {
×
3034
  int fd = fileno(out);
×
3035
  assert(fd >= 0);
3036
  statistics_print(&mcsat->stats, fd);
×
3037
}
×
3038

3039
void mcsat_show_stats_fd(mcsat_solver_t* mcsat, int out) {
×
3040
  statistics_print(&mcsat->stats, out);
×
3041
}
×
3042

3043
void mcsat_build_model(mcsat_solver_t* mcsat, model_t* model) {
36✔
3044

3045
  value_table_t* vtbl = model_get_vtbl(model);
36✔
3046

3047
  if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
36✔
3048
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_build_model()\n");
×
3049
    trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
3050
  }
3051

3052
  // Just copy the trail into the model
3053
  uint32_t i;
3054
  ivector_t* trail_elements = &mcsat->trail->elements;
36✔
3055
  for (i = 0; i < trail_elements->size; ++ i) {
522✔
3056
    variable_t x = trail_elements->data[i];
486✔
3057
    term_t x_term = variable_db_get_term(mcsat->var_db, x);
486✔
3058
    term_kind_t x_kind = term_kind(mcsat->terms, x_term);
486✔
3059

3060
    if (x_kind == UNINTERPRETED_TERM &&
592✔
3061
        term_type_kind(mcsat->terms, x_term) != FUNCTION_TYPE) {
106✔
3062

3063
      if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
70✔
3064
        mcsat_trace_printf(mcsat->ctx->trace, "var = ");
×
3065
        trace_term_ln(mcsat->ctx->trace, mcsat->terms, x_term);
×
3066
      }
3067

3068
      // Type of the variable
3069
      type_t x_type = term_type(mcsat->terms, x_term);
70✔
3070

3071
      // Get mcsat value (have to case to remove const because yices api doesn't care for const)
3072
      mcsat_value_t* x_value_mcsat = (mcsat_value_t*) trail_get_value(mcsat->trail, x);
70✔
3073

3074
      if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
70✔
3075
        mcsat_trace_printf(mcsat->ctx->trace, "value = ");
×
3076
        mcsat_value_print(x_value_mcsat, trace_out(mcsat->ctx->trace));
×
3077
        mcsat_trace_printf(mcsat->ctx->trace, "\n");
×
3078
      }
3079

3080
      // Set up the yices value
3081
      value_t x_value = mcsat_value_to_value(x_value_mcsat, mcsat->types, x_type, vtbl);
70✔
3082

3083
      if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
70✔
3084
        mcsat_trace_printf(mcsat->ctx->trace, "value = ");
×
3085
        vtbl_print_object(trace_out(mcsat->ctx->trace), vtbl, x_value);
×
3086
        mcsat_trace_printf(mcsat->ctx->trace, "\n");
×
3087
      }
3088

3089
              // Add to model
3090
              {
3091
                int_hmap_pair_t *entry = int_hmap_get(&model->map, x_term);
70✔
3092
                if (entry->val < 0) {
70✔
3093
                  model_map_term(model, x_term, x_value);
70✔
3094
                } else {
3095
                  /*
3096
                   * Supplemental use may overlay values onto a model that already
3097
                   * contains assignments from other CDCL(T) satellites.
3098
                   */
NEW
3099
                  entry->val = x_value;
×
3100
                }
3101
              }
3102
            }
3103
          }
3104

3105
  // Let the plugins run add to the model (e.g. UF, division, ...)
3106
  for (i = 0; i < mcsat->plugins_count; ++ i) {
252✔
3107
    plugin_t* plugin = mcsat->plugins[i].plugin;
216✔
3108
    if (plugin->build_model) {
216✔
3109
      plugin->build_model(plugin, model);
36✔
3110
    }
3111
  }
3112

3113
  // Let the preprocessor add to the model
3114
  preprocessor_build_model(&mcsat->preprocessor, model);
36✔
3115
}
36✔
3116

3117
void mcsat_set_exception_handler(mcsat_solver_t* mcsat, jmp_buf* handler) {
×
3118
  uint32_t i;
3119
  mcsat->exception = handler;
×
3120
  preprocessor_set_exception_handler(&mcsat->preprocessor, handler);
×
3121
  for (i = 0; i < mcsat->plugins_count; ++ i) {
×
3122
    plugin_t* plugin = mcsat->plugins[i].plugin;
×
3123
    plugin->set_exception_handler(plugin, handler);
×
3124
  }
3125
}
×
3126

3127
void mcsat_gc_mark(mcsat_solver_t* mcsat) {
5✔
3128
  mcsat_clear(mcsat);
5✔
3129
  mcsat_gc(mcsat, true);
5✔
3130
}
5✔
3131

3132
void mcsat_stop_search(mcsat_solver_t* mcsat) {
×
3133
  mcsat->stop_search = true;
×
3134
}
×
3135

3136
term_t mcsat_get_unsat_model_interpolant(mcsat_solver_t* mcsat) {
67✔
3137
  return mcsat->interpolant;
67✔
3138
}
3139

3140
void mcsat_set_unsat_result(mcsat_solver_t* mcsat, term_t interpolant) {
9✔
3141
  mcsat->status = YICES_STATUS_UNSAT;
9✔
3142
  mcsat->interpolant = interpolant;
9✔
3143
}
9✔
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