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

SRI-CSL / yices2 / 12367760548

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

push

github

web-flow
Fixes GitHub coverage issue (#544)

* Update action.yml

* Update action.yml

81020 of 124102 relevant lines covered (65.29%)

1509382.01 hits per line

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

78.18
/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/nra/nra_plugin.h"
47
#include "mcsat/uf/uf_plugin.h"
48
#include "mcsat/bv/bv_plugin.h"
49
#include "mcsat/ff/ff_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 <inttypes.h>
61

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

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

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

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

109
#define MCSAT_MAX_PLUGINS 10
110

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

118
struct mcsat_solver_s {
119

120
  /** Context of the solver */
121
  const context_t* ctx;
122

123
  /** Flag to stop the search */
124
  bool stop_search;
125

126
  /** Exception handler */
127
  jmp_buf* exception;
128

129
  /** Term manager for everyone to use */
130
  term_manager_t tm;
131

132
  /** Input types are are from this table */
133
  type_table_t* types;
134

135
  /** Input terms are from this table */
136
  term_table_t* terms;
137

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

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

144
  /** Number of inconsistent push calls */
145
  uint32_t inconsistent_push_calls;
146

147
  /** Notifications for new variables */
148
  solver_new_variable_notify_t var_db_notify;
149

150
  /** Variable database */
151
  variable_db_t* var_db;
152

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

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

162
  /** Temp assertion vector while preprocessing */
163
  ivector_t assertions_tmp;
164

165
  /** The trail */
166
  mcsat_trail_t* trail;
167

168
  /** Mark when adding an assertion */
169
  bool registration_is_assertion;
170

171
  /** Queue for registering new variables */
172
  int_queue_t registration_queue;
173

174
  /** Has a term been registered already */
175
  int_hset_t registration_cache;
176

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

184
  /** The evaluator */
185
  mcsat_evaluator_t evaluator;
186

187
  /** The preprocessor */
188
  preprocessor_t preprocessor;
189

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

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

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

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

212
  /** Plugin the reported a conflict */
213
  mcsat_plugin_context_t* plugin_in_conflict;
214

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

218
  /** Lemmas reported by plugins  */
219
  ivector_t plugin_lemmas;
220

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

224
  /** Variables of definition lemmas (as terms) */
225
  ivector_t plugin_definition_vars;
226

227
  /** Last processed definition lemma */
228
  uint32_t plugin_definition_lemmas_i;
229

230
  /** Number of plugins */
231
  uint32_t plugins_count;
232

233
  /** Variable to decide on first */
234
  ivector_t top_decision_vars;
235

236
  /** Variables hinted by the plugins to decide next */
237
  int_queue_t hinted_decision_vars;
238

239
  /** The queue for variable decisions */
240
  var_queue_t var_queue;
241

242
  /** All pending requests */
243
  struct {
244
    bool restart;
245
    bool gc_calls;
246
  } pending_requests_all;
247

248
  /** Any pending requests */
249
  bool pending_requests;
250

251
  /** Assumption variables */
252
  ivector_t assumption_vars;
253

254
  /** Index of the assumption to process next */
255
  uint32_t assumption_i;
256

257
  /** Level at which last assumption has been decided (-1 if not yet) */
258
  int32_t assumptions_decided_level;
259

260
  /** Model used for assumptions solving */
261
  model_t* assumptions_model;
262

263
  /** Interpolant */
264
  term_t interpolant;
265

266
  /** Statistics */
267
  statistics_t stats;
268

269
  struct {
270
    // Assertions added
271
    statistic_int_t* assertions;
272
    // Lemmas added
273
    statistic_int_t* lemmas;
274
    // Decisions performed
275
    statistic_int_t* decisions;
276
    // Restarts performed
277
    statistic_int_t* restarts;
278
    // Conflicts handled
279
    statistic_int_t* conflicts;
280
    // Average conflict size
281
    statistic_avg_t* avg_conflict_size;
282
    // GC calls
283
    statistic_int_t* gc_calls;
284
  } solver_stats;
285

286
  struct {
287
    // Restart interval (used as multiplier in luby sequence)
288
    uint32_t restart_interval;
289
    // Type of weight to use for restart counter
290
    lemma_weight_type_t lemma_restart_weight_type;
291
    // Random decision frequency
292
    double random_decision_freq;
293
    // Random decision seed
294
    double random_decision_seed;
295
  } heuristic_params;
296

297
  /** Scope holder for backtracking int variables */
298
  scope_holder_t scope;
299

300
  /** IDs of various plugins, if added */
301
  uint32_t bool_plugin_id;
302
  uint32_t uf_plugin_id;
303
  uint32_t ite_plugin_id;
304
  uint32_t nra_plugin_id;
305
  uint32_t bv_plugin_id;
306
  uint32_t ff_plugin_id;
307
};
308

309
static
310
bool mcsat_is_consistent(mcsat_solver_t* mcsat) {
11,471,541✔
311
  return trail_is_consistent(mcsat->trail) && mcsat->variable_in_conflict == variable_null;
11,471,541✔
312
}
313

314
static
315
void mcsat_add_lemma(mcsat_solver_t* mcsat, ivector_t* lemma, term_t decision_bound);
316

317
static
318
void propagation_check(const ivector_t* reasons, term_t x, term_t subst);
319

320
static
321
void mcsat_stats_init(mcsat_solver_t* mcsat) {
634✔
322
  mcsat->solver_stats.assertions = statistics_new_int(&mcsat->stats, "mcsat::assertions");
634✔
323
  mcsat->solver_stats.conflicts = statistics_new_int(&mcsat->stats, "mcsat::conflicts");
634✔
324
  mcsat->solver_stats.avg_conflict_size = statistics_new_avg(&mcsat->stats, "mcsat::avg_conflict_size");
634✔
325
  mcsat->solver_stats.decisions = statistics_new_int(&mcsat->stats, "mcsat::decisions");
634✔
326
  mcsat->solver_stats.gc_calls = statistics_new_int(&mcsat->stats, "mcsat::gc_calls");
634✔
327
  mcsat->solver_stats.lemmas = statistics_new_int(&mcsat->stats, "mcsat::lemmas");
634✔
328
  mcsat->solver_stats.restarts = statistics_new_int(&mcsat->stats, "mcsat::restarts");
634✔
329
}
634✔
330

331
static
332
void mcsat_heuristics_init(mcsat_solver_t* mcsat) {
965✔
333
  mcsat->heuristic_params.restart_interval = 10;
965✔
334
  mcsat->heuristic_params.lemma_restart_weight_type = LEMMA_WEIGHT_SIZE;
965✔
335
  mcsat->heuristic_params.random_decision_freq = mcsat->ctx->mcsat_options.rand_dec_freq;
965✔
336
  mcsat->heuristic_params.random_decision_seed = mcsat->ctx->mcsat_options.rand_dec_seed;
965✔
337
}
965✔
338

339
static
340
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) {
1,172,603✔
341

342
  const mcsat_solver_t* mcsat = ((const mcsat_evaluator_t*) self)->solver;
1,172,603✔
343
  assert(value != NULL);
344

345
  if (trace_enabled(mcsat->ctx->trace, "mcsat::resolve")) {
1,172,603✔
346
    FILE* out = trace_out(mcsat->ctx->trace);
×
347
    fprintf(out, "explaining eval of: ");
×
348
    term_print_to_file(out, mcsat->terms, t);
×
349
    fprintf(out, " -> ");
×
350
    mcsat_value_print(value, out);
×
351
    fprintf(out, "\n");
×
352
  }
353

354
  uint32_t i;
355
  term_kind_t kind;
356
  type_kind_t type_kind;
357
  bool evaluates = false;
1,172,603✔
358
  plugin_t* plugin;
359

360
  kind = term_kind(mcsat->terms, t);
1,172,603✔
361
  bool is_equality = false;
1,172,603✔
362
  switch (kind) {
1,172,603✔
363
  case EQ_TERM:
340,716✔
364
  case BV_EQ_ATOM:
365
  case ARITH_BINEQ_ATOM:
366
  case ARITH_FF_BINEQ_ATOM:
367
    is_equality = true;
340,716✔
368
    break;
340,716✔
369
  default:
831,887✔
370
    // Nothing
371
    break;
831,887✔
372
  }
373

374
  if (!is_equality) {
1,172,603✔
375
    for (i = kind; mcsat->kind_owners[i] != MCSAT_MAX_PLUGINS; i += NUM_TERM_KINDS) {
870,133✔
376
      int_mset_clear(vars);
221,280✔
377
      plugin = mcsat->plugins[mcsat->kind_owners[i]].plugin;
221,280✔
378
      if (plugin->explain_evaluation) {
221,280✔
379
        if (trace_enabled(mcsat->ctx->trace, "mcsat::resolve")) {
221,280✔
380
          FILE* out = trace_out(mcsat->ctx->trace);
×
381
          fprintf(out, "explaining eval with: %s\n", mcsat->plugins[mcsat->kind_owners[i]].plugin_name);
×
382
        }
383
        evaluates = plugin->explain_evaluation(plugin, t, vars, value);
221,280✔
384
        if (evaluates) {
221,280✔
385
          return true;
183,034✔
386
        }
387
      }
388
    }
389
  } else {
390
    composite_term_t* eq_desc = composite_term_desc(mcsat->terms, t);
340,716✔
391
    type_kind = term_type_kind(mcsat->terms, eq_desc->arg[0]);
340,716✔
392
    for (i = type_kind; mcsat->type_owners[i] != MCSAT_MAX_PLUGINS; i += NUM_TERM_KINDS) {
433,861✔
393
      int_mset_clear(vars);
340,716✔
394
      plugin = mcsat->plugins[mcsat->type_owners[i]].plugin;
340,716✔
395
      if (plugin->explain_evaluation) {
340,716✔
396
        if (trace_enabled(mcsat->ctx->trace, "mcsat::resolve")) {
340,716✔
397
          FILE* out = trace_out(mcsat->ctx->trace);
×
398
          fprintf(out, "explaining eval with: %s\n", mcsat->plugins[mcsat->type_owners[i]].plugin_name);
×
399
        }
400
        evaluates = plugin->explain_evaluation(plugin, t, vars, value);
340,716✔
401
        if (evaluates) {
340,716✔
402
          return true;
247,571✔
403
        }
404
      }
405
    }
406
  }
407

408
  if (!evaluates) {
741,998✔
409
    // Maybe the term itself evaluates
410
    term_t t_unsigned = unsigned_term(t);
741,998✔
411
    variable_t t_var = variable_db_get_variable_if_exists(mcsat->var_db, t_unsigned);
741,998✔
412
    if (t_var != variable_null) {
741,998✔
413
      if (trail_has_value(mcsat->trail, t_var)) {
741,937✔
414
        const mcsat_value_t* t_var_value = trail_get_value(mcsat->trail, t_var);
741,867✔
415
        bool negated = is_neg_term(t);
741,867✔
416
        if ((negated && t_var_value->b != value->b)
741,867✔
417
            || (!negated && t_var_value->b == value->b)) {
381,047✔
418
          int_mset_clear(vars);
741,827✔
419
          int_mset_add(vars, t_var);
741,827✔
420
          return true;
741,827✔
421
        }
422
      }
423
      if (vars->size == 0) {
110✔
424
        int_mset_add(vars, t_var);
11✔
425
      }
426
    }
427
  }
428

429
  return false;
171✔
430
}
431

432
/** Construct the mcsat evaluator */
433
void mcsat_evaluator_construct(mcsat_evaluator_t* evaluator, mcsat_solver_t* solver) {
634✔
434
  evaluator->evaluates_at = mcsat_evaluates_at;
634✔
435
  evaluator->solver = solver;
634✔
436
}
634✔
437

438
/** Callback on propagations */
439
static
440
bool trail_token_add(trail_token_t* token, variable_t x, const mcsat_value_t* value) {
5,119,534✔
441
  plugin_trail_token_t* tk = (plugin_trail_token_t*) token;
5,119,534✔
442
  mcsat_solver_t* mcsat = tk->ctx->mcsat;
5,119,534✔
443
  mcsat_trail_t* trail = mcsat->trail;
5,119,534✔
444
  bool is_decision;
445

446
  is_decision = tk->x != variable_null;
5,119,534✔
447

448
  if (ctx_trace_enabled(&tk->ctx->ctx, "trail::add")) {
5,119,534✔
449
    if (is_decision) {
×
450
      ctx_trace_printf(&tk->ctx->ctx, "plugin %s deciding ", tk->ctx->plugin_name);\
×
451
    } else {
452
      ctx_trace_printf(&tk->ctx->ctx, "plugin %s propagating ", tk->ctx->plugin_name);\
×
453
    }
454
    variable_db_print_variable(mcsat->var_db, x, ctx_trace_out(&tk->ctx->ctx));
×
455
    ctx_trace_printf(&tk->ctx->ctx, " -> ");
×
456
    mcsat_value_print(value, ctx_trace_out(&tk->ctx->ctx));
×
457
    ctx_trace_printf(&tk->ctx->ctx, "\n");
×
458
  }
459

460
  if (trail_has_value(trail, x)) {
5,119,534✔
461
    return false;
×
462
  }
463

464
  tk->used ++;
5,119,534✔
465

466
  if (is_decision) {
5,119,534✔
467
    trail_add_decision(trail, x, value, tk->ctx->ctx.plugin_id);
660,774✔
468
  } else {
469
    trail_add_propagation(trail, x, value, tk->ctx->ctx.plugin_id, trail->decision_level);
4,458,760✔
470
  }
471

472
  if (ctx_trace_enabled(&tk->ctx->ctx, "mcsat::propagation::check") && !is_decision) {
5,119,534✔
473
    uint32_t plugin_id = tk->ctx->ctx.plugin_id;
×
474
    if (plugin_id != mcsat->bool_plugin_id) {
×
475
      ivector_t reason;
476
      init_ivector(&reason, 0);
×
477
      plugin_t* plugin = mcsat->plugins[plugin_id].plugin;
×
478
      term_t substitution = plugin->explain_propagation(plugin, x, &reason);
×
479
      term_t x_term = variable_db_get_term(mcsat->var_db, x);
×
480
      propagation_check(&reason, x_term, substitution);
×
481
      delete_ivector(&reason);
×
482
    }
483
  }
484

485
  return true;
5,119,534✔
486
}
487

488
/** Callback on propagations at lower levels */
489
static
490
bool trail_token_add_at_level(trail_token_t* token, variable_t x, const mcsat_value_t* value, uint32_t level) {
2,661,955✔
491
  plugin_trail_token_t* tk = (plugin_trail_token_t*) token;
2,661,955✔
492
  mcsat_solver_t* mcsat = tk->ctx->mcsat;
2,661,955✔
493
  mcsat_trail_t* trail = mcsat->trail;
2,661,955✔
494

495
  if (ctx_trace_enabled(&tk->ctx->ctx, "trail::add")) {
2,661,955✔
496
    ctx_trace_printf(&tk->ctx->ctx, "plugin %s propagating ", tk->ctx->plugin_name);
×
497
    variable_db_print_variable(mcsat->var_db, x, ctx_trace_out(&tk->ctx->ctx));
×
498
    ctx_trace_printf(&tk->ctx->ctx, " -> ");
×
499
    mcsat_value_print(value, ctx_trace_out(&tk->ctx->ctx));
×
500
    ctx_trace_printf(&tk->ctx->ctx, "\n");
×
501
  }
502

503
  // Only for propagations, we can't decide on lower levels
504
  assert(tk->x == variable_null);
505

506
  if (trail_has_value(trail, x)) {
2,661,955✔
507
    return false;
×
508
  }
509

510
  tk->used ++;
2,661,955✔
511

512
  // Check for trail level
513
  if (level < trail->decision_level_base) {
2,661,955✔
514
    level = trail->decision_level_base;
10✔
515
  }
516

517
  // Add the propagation
518
  trail_add_propagation(trail, x, value, tk->ctx->ctx.plugin_id, level);
2,661,955✔
519

520
  return true;
2,661,955✔
521
}
522

523

524
static
525
void trail_token_conflict(trail_token_t* token) {
86,934✔
526
  plugin_trail_token_t* tk = (plugin_trail_token_t*) token;
86,934✔
527

528
  if (ctx_trace_enabled(&tk->ctx->ctx, "trail::conflict")) {
86,934✔
529
    ctx_trace_printf(&tk->ctx->ctx, "plugin %s reporting a conflict\n", tk->ctx->plugin_name);
×
530
  }
531

532
  tk->used ++;
86,934✔
533

534
  // Remember the plugin that reported the
535
  tk->ctx->mcsat->plugin_in_conflict = tk->ctx;
86,934✔
536

537
  // Set the trail to be inconsistent
538
  trail_set_inconsistent(tk->ctx->mcsat->trail);
86,934✔
539
}
86,934✔
540

541
static
542
void trail_token_lemma(trail_token_t* token, term_t lemma) {
38,115✔
543
  plugin_trail_token_t* tk = (plugin_trail_token_t*) token;
38,115✔
544

545
  if (ctx_trace_enabled(&tk->ctx->ctx, "trail::lemma")) {
38,115✔
546
    ctx_trace_printf(&tk->ctx->ctx, "plugin %s reporting a lemma\n", tk->ctx->plugin_name);
×
547
    ctx_trace_term(&tk->ctx->ctx, lemma);
×
548
  }
549

550
  tk->used ++;
38,115✔
551

552
  // Remember the lemma
553
  ivector_push(&tk->ctx->mcsat->plugin_lemmas, lemma);
38,115✔
554
}
38,115✔
555

556
static
557
void trail_token_definition_lemma(trail_token_t* token, term_t lemma, term_t t) {
1,027✔
558
  plugin_trail_token_t* tk = (plugin_trail_token_t*) token;
1,027✔
559

560
  if (ctx_trace_enabled(&tk->ctx->ctx, "trail::lemma")) {
1,027✔
561
    ctx_trace_printf(&tk->ctx->ctx, "plugin %s reporting a definition lemma\n", tk->ctx->plugin_name);
×
562
    ctx_trace_term(&tk->ctx->ctx, lemma);
×
563
  }
564

565
  tk->used ++;
1,027✔
566

567
  // Remember the definition
568
  ivector_push(&tk->ctx->mcsat->plugin_definition_lemmas, lemma);
1,027✔
569
  ivector_push(&tk->ctx->mcsat->plugin_definition_vars, t);
1,027✔
570
}
1,027✔
571

572
/** Construct the trail token */
573
static inline
574
void trail_token_construct(plugin_trail_token_t* token, mcsat_plugin_context_t* ctx, variable_t x) {
8,524,248✔
575
  token->token_interface.add = trail_token_add;
8,524,248✔
576
  token->token_interface.add_at_level = trail_token_add_at_level;
8,524,248✔
577
  token->token_interface.conflict = trail_token_conflict;
8,524,248✔
578
  token->token_interface.lemma = trail_token_lemma;
8,524,248✔
579
  token->token_interface.definition_lemma = trail_token_definition_lemma;
8,524,248✔
580
  token->ctx = ctx;
8,524,248✔
581
  token->x = x;
8,524,248✔
582
  token->used = 0;
8,524,248✔
583
}
8,524,248✔
584

585
void mcsat_plugin_term_notification_by_kind(plugin_context_t* self, term_kind_t kind, bool is_internal) {
30,432✔
586
  uint32_t i;
587
  mcsat_plugin_context_t* mctx;
588

589
  mctx = (mcsat_plugin_context_t*) self;
30,432✔
590
  assert(self->plugin_id != MCSAT_MAX_PLUGINS);
591
  for (i = kind; mctx->mcsat->kind_owners[i] != MCSAT_MAX_PLUGINS; i += NUM_TERM_KINDS) {}
36,138✔
592
  mctx->mcsat->kind_owners[i] = self->plugin_id;
30,432✔
593
  if (is_internal) {
30,432✔
594
    int_hset_add(&mctx->mcsat->internal_kinds, kind);
634✔
595
  }
596
}
30,432✔
597

598
void mcsat_plugin_term_notification_by_type(plugin_context_t* self, type_kind_t kind) {
5,072✔
599
  uint32_t i;
600
  mcsat_plugin_context_t* mctx;
601

602
  mctx = (mcsat_plugin_context_t*) self;
5,072✔
603
  assert(self->plugin_id != MCSAT_MAX_PLUGINS);
604
  for (i = kind; mctx->mcsat->type_owners[i] != MCSAT_MAX_PLUGINS; i += NUM_TYPE_KINDS) {}
5,072✔
605
  mctx->mcsat->type_owners[i] = self->plugin_id;
5,072✔
606
}
5,072✔
607

608
static
609
void mcsat_request_restart(mcsat_solver_t* mcsat) {
17,409✔
610
  mcsat->pending_requests = true;
17,409✔
611
  mcsat->pending_requests_all.restart = true;
17,409✔
612
}
17,409✔
613

614
static
615
void mcsat_request_gc(mcsat_solver_t* mcsat) {
132✔
616
  mcsat->pending_requests = true;
132✔
617
  mcsat->pending_requests_all.gc_calls = true;
132✔
618
}
132✔
619

620
static
621
void mcsat_plugin_context_restart(plugin_context_t* self) {
×
622
  mcsat_plugin_context_t* mctx;
623

624
  mctx = (mcsat_plugin_context_t*) self;
×
625
  mcsat_request_restart(mctx->mcsat);
×
626
}
×
627

628
static
629
void mcsat_plugin_context_gc(plugin_context_t* self) {
132✔
630
  mcsat_plugin_context_t* mctx;
631

632
  mctx = (mcsat_plugin_context_t*) self;
132✔
633
  mcsat_request_gc(mctx->mcsat);
132✔
634
}
132✔
635

636
static inline
637
void mcsat_add_top_decision(mcsat_solver_t* mcsat, variable_t x) {
2✔
638
  for (int i = 0; i < mcsat->top_decision_vars.size; ++i) {
2✔
639
    if (mcsat->top_decision_vars.data[i] == x) {
×
640
      return;
×
641
    }
642
  }
643
  ivector_push(&mcsat->top_decision_vars, x);
2✔
644
}
645

646
static inline
647
void mcsat_add_decision_hint(mcsat_solver_t* mcsat, variable_t x) {
79,097✔
648
  int_queue_push(&mcsat->hinted_decision_vars, x);
79,097✔
649
}
79,097✔
650

651
static inline
652
void mcsat_bump_variable(mcsat_solver_t* mcsat, variable_t x, uint32_t factor) {
4,943,181✔
653
  var_queue_bump_variable(&mcsat->var_queue, x, factor);
4,943,181✔
654
}
4,943,181✔
655

656
#if 0
657
static inline
658
void mcsat_bump_variables_vector(mcsat_solver_t* mcsat, const ivector_t* vars) {
659
  uint32_t i;
660
  for (i = 0; i < vars->size; ++ i) {
661
    mcsat_bump_variable(mcsat, vars->data[i], 1);
662
  }
663
}
664
#endif
665

666
static inline
667
void mcsat_bump_variables_mset(mcsat_solver_t* mcsat, const int_mset_t* vars) {
86,731✔
668
  uint32_t i;
669
  for (i = 0; i < vars->element_list.size; ++ i) {
1,918,150✔
670
    variable_t x = vars->element_list.data[i];
1,831,419✔
671
    uint32_t n = int_mset_contains(vars, x);
1,831,419✔
672
    mcsat_bump_variable(mcsat, x, n);
1,831,419✔
673
  }
674
}
86,731✔
675

676
static
677
void mcsat_plugin_context_bump_variable(plugin_context_t* self, variable_t x) {
×
678
  mcsat_plugin_context_t* mctx;
679

680
  mctx = (mcsat_plugin_context_t*) self;
×
681
  mcsat_bump_variable(mctx->mcsat, x, 1);
×
682
}
×
683

684
static
685
void mcsat_plugin_context_bump_variable_n(plugin_context_t* self, variable_t x, uint32_t n) {
3,111,762✔
686
  mcsat_plugin_context_t* mctx;
687

688
  mctx = (mcsat_plugin_context_t*) self;
3,111,762✔
689
  mcsat_bump_variable(mctx->mcsat, x, n);
3,111,762✔
690
}
3,111,762✔
691

692
static
693
int mcsat_plugin_context_cmp_variables(plugin_context_t* self, variable_t x, variable_t y) {
1,868,193✔
694
  mcsat_plugin_context_t* mctx;
695
  mctx = (mcsat_plugin_context_t*) self;
1,868,193✔
696
  return var_queue_cmp_variables(&mctx->mcsat->var_queue, x, y);
1,868,193✔
697
}
698

699
static
700
void mcsat_plugin_context_request_top_decision(plugin_context_t* self, variable_t x) {
2✔
701
  mcsat_plugin_context_t* mctx;
702
  mctx = (mcsat_plugin_context_t*) self;
2✔
703
  mcsat_add_top_decision(mctx->mcsat, x);
2✔
704
}
2✔
705

706
static
707
void mcsat_plugin_context_hint_next_decision(plugin_context_t* self, variable_t x) {
79,097✔
708
  mcsat_plugin_context_t* mctx;
709
  mctx = (mcsat_plugin_context_t*) self;
79,097✔
710
  mcsat_add_decision_hint(mctx->mcsat, x);
79,097✔
711
}
79,097✔
712

713
/*
714
 * Provide hint to the trail cache.
715
 */
716
static
717
void mcsat_plugin_context_hint_value(plugin_context_t* self, variable_t x, const mcsat_value_t* val) {
42✔
718
  mcsat_plugin_context_t* mctx;
719
  mctx = (mcsat_plugin_context_t*) self;
42✔
720
  // update only if the x value is not set in the trail
721
  if (!trail_has_value(mctx->mcsat->trail, x)) {
42✔
722
    // we set the value in the model of the trail.
723
    // Remark: This is not making a decision in the trail. The model
724
    // in the trail is used as a cache for unassigned variables.
725
    mcsat_model_set_value(&mctx->mcsat->trail->model, x, val);
42✔
726
  }
727
}
42✔
728

729
static
730
void mcsat_plugin_context_decision_calls(plugin_context_t* self, type_kind_t type) {
5,072✔
731
  mcsat_plugin_context_t* mctx;
732

733
  mctx = (mcsat_plugin_context_t*) self;
5,072✔
734
  assert(mctx->mcsat->decision_makers[type] == MCSAT_MAX_PLUGINS);
735
  mctx->mcsat->decision_makers[type] = self->plugin_id;
5,072✔
736
}
5,072✔
737

738
void mcsat_plugin_context_construct(mcsat_plugin_context_t* ctx, mcsat_solver_t* mcsat, uint32_t plugin_i, const char* plugin_name) {
3,804✔
739
  ctx->ctx.plugin_id = plugin_i;
3,804✔
740
  ctx->ctx.var_db = mcsat->var_db;
3,804✔
741
  ctx->ctx.tm = &mcsat->tm;
3,804✔
742
  ctx->ctx.terms = mcsat->terms;
3,804✔
743
  ctx->ctx.types = mcsat->types;
3,804✔
744
  ctx->ctx.exception = mcsat->exception;
3,804✔
745
  ctx->ctx.options = &mcsat->ctx->mcsat_options;
3,804✔
746
  ctx->ctx.trail = mcsat->trail;
3,804✔
747
  ctx->ctx.stats = &mcsat->stats;
3,804✔
748
  ctx->ctx.tracer = mcsat->ctx->trace;
3,804✔
749
  ctx->ctx.stop_search = &mcsat->stop_search;
3,804✔
750
  ctx->ctx.request_decision_calls = mcsat_plugin_context_decision_calls;
3,804✔
751
  ctx->ctx.request_term_notification_by_kind = mcsat_plugin_term_notification_by_kind;
3,804✔
752
  ctx->ctx.request_term_notification_by_type = mcsat_plugin_term_notification_by_type;
3,804✔
753
  ctx->ctx.request_restart = mcsat_plugin_context_restart;
3,804✔
754
  ctx->ctx.request_gc = mcsat_plugin_context_gc;
3,804✔
755
  ctx->ctx.bump_variable = mcsat_plugin_context_bump_variable;
3,804✔
756
  ctx->ctx.bump_variable_n = mcsat_plugin_context_bump_variable_n;
3,804✔
757
  ctx->ctx.cmp_variables = mcsat_plugin_context_cmp_variables;
3,804✔
758
  ctx->ctx.request_top_decision = mcsat_plugin_context_request_top_decision;
3,804✔
759
  ctx->ctx.hint_next_decision = mcsat_plugin_context_hint_next_decision;
3,804✔
760
  ctx->ctx.hint_value = mcsat_plugin_context_hint_value;
3,804✔
761
  ctx->mcsat = mcsat;
3,804✔
762
  ctx->plugin_name = plugin_name;
3,804✔
763
}
3,804✔
764

765
static
766
void mcsat_term_registration_enqueue(mcsat_solver_t* mcsat, term_t t) {
169,289✔
767
  // Make sure it's positive polarity
768
  t = unsigned_term(t);
169,289✔
769

770
  // Enqueue if not processed already
771
  if (!int_hset_member(&mcsat->registration_cache, t)) {
169,289✔
772
    int_hset_add(&mcsat->registration_cache, t);
169,289✔
773
    int_queue_push(&mcsat->registration_queue, t);
169,289✔
774
  }
775
}
169,289✔
776

777
static
778
void mcsat_new_variable_notify(solver_new_variable_notify_t* self, variable_t x) {
169,289✔
779
  term_t t;
780
  uint32_t size;
781

782
  // Enqueue for registration
783
  t = variable_db_get_term(self->mcsat->var_db, x);
169,289✔
784
  mcsat_term_registration_enqueue(self->mcsat, t);
169,289✔
785

786
  // Ensure that the trail/model is aware of this
787
  trail_new_variable_notify(self->mcsat->trail, x);
169,289✔
788

789
  // Add the variable to the queue
790
  if (x >= self->mcsat->var_queue.size) {
169,289✔
791
    size = x + x/2 + 1;
487✔
792
    assert(size > x);
793
    var_queue_extend(&self->mcsat->var_queue, size);
487✔
794
  }
795
  var_queue_insert(&self->mcsat->var_queue, x);
169,289✔
796
}
169,289✔
797

798
static
799
uint32_t mcsat_add_plugin(mcsat_solver_t* mcsat, plugin_allocator_t plugin_allocator, const char* plugin_name) {
3,804✔
800

801
  // Allocate the plugin
802
  plugin_t* plugin = plugin_allocator();
3,804✔
803
  // The index of the plugin
804
  uint32_t plugin_i = mcsat->plugins_count;
3,804✔
805
  // Allocate the request
806
  mcsat_plugin_context_t* plugin_ctx = safe_malloc(sizeof(mcsat_plugin_context_t));
3,804✔
807
  mcsat_plugin_context_construct(plugin_ctx, mcsat, plugin_i, plugin_name);
3,804✔
808
  // Construct the plugin
809
  plugin->construct(plugin, (plugin_context_t*) plugin_ctx);
3,804✔
810

811
  // Add the plugin to the list of plugins
812
  mcsat->plugins[plugin_i].plugin = plugin;
3,804✔
813
  mcsat->plugins[plugin_i].plugin_ctx = plugin_ctx;
3,804✔
814
  mcsat->plugins[plugin_i].plugin_name = safe_strdup(plugin_name);
3,804✔
815
  mcsat->plugins_count ++;
3,804✔
816

817
  return plugin_i;
3,804✔
818
}
819

820
static
821
void mcsat_add_plugins(mcsat_solver_t* mcsat) {
634✔
822
  mcsat->bool_plugin_id = mcsat_add_plugin(mcsat, bool_plugin_allocator, "bool_plugin");
634✔
823
  mcsat->uf_plugin_id = mcsat_add_plugin(mcsat, uf_plugin_allocator, "uf_plugin");
634✔
824
  mcsat->ite_plugin_id = mcsat_add_plugin(mcsat, ite_plugin_allocator, "ite_plugin");
634✔
825
  mcsat->nra_plugin_id = mcsat_add_plugin(mcsat, nra_plugin_allocator, "nra_plugin");
634✔
826
  mcsat->bv_plugin_id = mcsat_add_plugin(mcsat, bv_plugin_allocator, "bv_plugin");
634✔
827
  mcsat->ff_plugin_id = mcsat_add_plugin(mcsat, ff_plugin_allocator, "ff_plugin");
634✔
828
}
634✔
829

830
static
831
void mcsat_construct(mcsat_solver_t* mcsat, const context_t* ctx) {
634✔
832
  uint32_t i;
833

834
  assert(ctx != NULL);
835
  assert(ctx->arch == CTX_ARCH_MCSAT);
836
  assert(ctx->terms != NULL);
837
  assert(ctx->types != NULL);
838

839
  mcsat->stop_search = false;
634✔
840
  mcsat->ctx = ctx;
634✔
841
  mcsat->exception = (jmp_buf*) &ctx->env;
634✔
842
  mcsat->types = ctx->types;
634✔
843
  mcsat->terms = ctx->terms;
634✔
844
  mcsat->terms_size_on_solver_entry = 0;
634✔
845
  mcsat->status = STATUS_IDLE;
634✔
846
  mcsat->inconsistent_push_calls = 0;
634✔
847

848
  // New term manager
849
  init_term_manager(&mcsat->tm, mcsat->terms);
634✔
850
  mcsat->tm.simplify_bveq1 = false;
634✔
851
  mcsat->tm.simplify_ite = false;
634✔
852

853
  // The new variable listener
854
  mcsat->var_db_notify.mcsat = mcsat;
634✔
855
  mcsat->var_db_notify.new_variable = mcsat_new_variable_notify;
634✔
856

857
  // The variable database
858
  mcsat->var_db = safe_malloc(sizeof(variable_db_t));
634✔
859
  variable_db_construct(mcsat->var_db, mcsat->terms, mcsat->types, mcsat->ctx->trace);
634✔
860
  variable_db_add_new_variable_listener(mcsat->var_db, (variable_db_new_variable_notify_t*)&mcsat->var_db_notify);
634✔
861

862
  // List of assertions
863
  init_ivector(&mcsat->assertion_vars, 0);
634✔
864
  init_ivector(&mcsat->assertion_terms_original, 0);
634✔
865
  init_ivector(&mcsat->assertions_tmp, 0);
634✔
866

867
  // The trail
868
  mcsat->trail = safe_malloc(sizeof(mcsat_trail_t));
634✔
869
  trail_construct(mcsat->trail, mcsat->var_db);
634✔
870

871
  // Variable registration queue
872
  init_int_queue(&mcsat->registration_queue, 0);
634✔
873
  init_int_hset(&mcsat->registration_cache, 0);
634✔
874

875
  // Init all the term owners to NULL
876
  for (i = 0; i < NUM_TERM_KINDS * MCSAT_MAX_PLUGINS; ++ i) {
336,654✔
877
    mcsat->kind_owners[i] = MCSAT_MAX_PLUGINS;
336,020✔
878
  }
879

880
  // Internal kinds
881
  init_int_hset(&mcsat->internal_kinds, 0);
634✔
882

883
  // Init all the type owners to NULL
884
  for (i = 0; i < NUM_TYPE_KINDS * MCSAT_MAX_PLUGINS; ++ i) {
76,714✔
885
    mcsat->type_owners[i] = MCSAT_MAX_PLUGINS;
76,080✔
886
  }
887

888
  // Init all the decision makers to NULL
889
  for (i = 0; i < NUM_TYPE_KINDS; ++ i) {
8,242✔
890
    mcsat->decision_makers[i] = MCSAT_MAX_PLUGINS;
7,608✔
891
  }
892

893
  // Plugin vectors
894
  mcsat->plugins_count = 0;
634✔
895
  mcsat->plugin_in_conflict = 0;
634✔
896

897
  // Construct the evaluator
898
  mcsat_evaluator_construct(&mcsat->evaluator, mcsat);
634✔
899

900
  // Construct the preprocessor
901
  preprocessor_construct(&mcsat->preprocessor, mcsat->terms, mcsat->exception, &mcsat->ctx->mcsat_options);
634✔
902

903
  // The variable queue
904
  init_ivector(&mcsat->top_decision_vars, 0);
634✔
905
  init_int_queue(&mcsat->hinted_decision_vars, 0);
634✔
906
  var_queue_construct(&mcsat->var_queue);
634✔
907

908
  mcsat->pending_requests_all.restart = false;
634✔
909
  mcsat->pending_requests_all.gc_calls = false;
634✔
910
  mcsat->pending_requests = false;
634✔
911

912
  mcsat->variable_in_conflict = variable_null;
634✔
913
  mcsat->assumption_i = 0;
634✔
914
  mcsat->assumptions_decided_level = -1;
634✔
915
  mcsat->interpolant = NULL_TERM;
634✔
916

917
  // Assumptions vector
918
  init_ivector(&mcsat->assumption_vars, 0);
634✔
919

920
  // Lemmas vector
921
  init_ivector(&mcsat->plugin_lemmas, 0);
634✔
922
  init_ivector(&mcsat->plugin_definition_lemmas, 0);
634✔
923
  init_ivector(&mcsat->plugin_definition_vars, 0);
634✔
924
  mcsat->plugin_definition_lemmas_i = 0;
634✔
925

926
  // Construct stats
927
  statistics_construct(&mcsat->stats);
634✔
928
  mcsat_stats_init(mcsat);
634✔
929

930
  // Scope for backtracking
931
  scope_holder_construct(&mcsat->scope);
634✔
932

933
  // Construct the plugins
934
  mcsat_add_plugins(mcsat);
634✔
935
}
634✔
936

937
void mcsat_destruct(mcsat_solver_t* mcsat) {
634✔
938
  uint32_t i;
939
  plugin_t* plugin;
940

941
  // Delete the plugin data
942
  for (i = 0; i < mcsat->plugins_count; ++ i) {
4,438✔
943
    // Plugin
944
    plugin = mcsat->plugins[i].plugin;
3,804✔
945
    plugin->destruct(mcsat->plugins[i].plugin);
3,804✔
946
    safe_free(plugin);
3,804✔
947
    // Plugin context
948
    safe_free(mcsat->plugins[i].plugin_ctx);
3,804✔
949
    // The name
950
    safe_free(mcsat->plugins[i].plugin_name);
3,804✔
951
  }
952

953
  delete_term_manager(&mcsat->tm);
634✔
954
  delete_int_queue(&mcsat->registration_queue);
634✔
955
  delete_int_hset(&mcsat->registration_cache);
634✔
956
  delete_ivector(&mcsat->assertion_vars);
634✔
957
  delete_ivector(&mcsat->assertion_terms_original);
634✔
958
  delete_ivector(&mcsat->assertions_tmp);
634✔
959
  trail_destruct(mcsat->trail);
634✔
960
  safe_free(mcsat->trail);
634✔
961
  variable_db_destruct(mcsat->var_db);
634✔
962
  safe_free(mcsat->var_db);
634✔
963
  preprocessor_destruct(&mcsat->preprocessor);
634✔
964
  delete_ivector(&mcsat->top_decision_vars);
634✔
965
  delete_int_queue(&mcsat->hinted_decision_vars);
634✔
966
  var_queue_destruct(&mcsat->var_queue);
634✔
967
  delete_ivector(&mcsat->plugin_lemmas);
634✔
968
  delete_ivector(&mcsat->plugin_definition_lemmas);
634✔
969
  delete_ivector(&mcsat->plugin_definition_vars);
634✔
970
  statistics_destruct(&mcsat->stats);
634✔
971
  scope_holder_destruct(&mcsat->scope);
634✔
972
  delete_ivector(&mcsat->assumption_vars);
634✔
973
  delete_int_hset(&mcsat->internal_kinds);
634✔
974
}
634✔
975

976
mcsat_solver_t* mcsat_new(const context_t* ctx) {
633✔
977
  mcsat_solver_t* mcsat = (mcsat_solver_t*) safe_malloc(sizeof(mcsat_solver_t));
633✔
978
  mcsat_construct(mcsat, ctx);
633✔
979
  return mcsat;
633✔
980
}
981

982

983
smt_status_t mcsat_status(const mcsat_solver_t* mcsat) {
11,042✔
984
  return mcsat->status;
11,042✔
985
}
986

987
static
988
void mcsat_notify_plugins(mcsat_solver_t* mcsat, plugin_notify_kind_t kind) {
105,734✔
989
  uint32_t i;
990
  plugin_t* plugin;
991

992
  for (i = 0; i < mcsat->plugins_count; ++ i) {
740,138✔
993
    plugin = mcsat->plugins[i].plugin;
634,404✔
994
    if (plugin->event_notify) {
634,404✔
995
      plugin->event_notify(plugin, kind);
317,202✔
996
    }
997
  }
998
}
105,734✔
999

1000
void mcsat_reset(mcsat_solver_t* mcsat) {
1✔
1001
  // Reset everything
1002
  const context_t* ctx = mcsat->ctx;
1✔
1003
  mcsat_destruct(mcsat);
1✔
1004
  mcsat_construct(mcsat, ctx);
1✔
1005
}
1✔
1006

1007
static
1008
void mcsat_push_internal(mcsat_solver_t* mcsat) {
682,198✔
1009
  uint32_t i;
1010
  plugin_t* plugin;
1011

1012
  // Push the plugins
1013
  for (i = 0; i < mcsat->plugins_count; ++ i) {
4,775,386✔
1014
    plugin = mcsat->plugins[i].plugin;
4,093,188✔
1015
    if (plugin->push) {
4,093,188✔
1016
      plugin->push(plugin);
3,410,990✔
1017
    }
1018
  }
1019
}
682,198✔
1020

1021
static
1022
void mcsat_pop_internal(mcsat_solver_t* mcsat) {
675,143✔
1023
  uint32_t i;
1024
  plugin_t* plugin;
1025
  ivector_t* unassigned;
1026

1027
  // Pop the plugins
1028
  for (i = 0; i < mcsat->plugins_count; ++ i) {
4,726,001✔
1029
    plugin = mcsat->plugins[i].plugin;
4,050,858✔
1030
    if (plugin->pop) {
4,050,858✔
1031
      plugin->pop(plugin);
3,375,715✔
1032
    }
1033
  }
1034

1035
  // Re-add the variables that were unassigned
1036
  unassigned = trail_get_unassigned(mcsat->trail);
675,143✔
1037
  for (i = 0; i < unassigned->size; ++ i) {
8,384,486✔
1038
    var_queue_insert(&mcsat->var_queue, unassigned->data[i]);
7,709,343✔
1039
  }
1040
  ivector_reset(unassigned);
675,143✔
1041

1042
  // remove all the hints
1043
  int_queue_reset(&mcsat->hinted_decision_vars);
675,143✔
1044
}
675,143✔
1045

1046
static
1047
void mcsat_backtrack_to(mcsat_solver_t* mcsat, uint32_t level);
1048

1049
static
1050
void mcsat_gc(mcsat_solver_t* mcsat, bool mark_and_gc_internal);
1051

1052
void mcsat_push(mcsat_solver_t* mcsat) {
1,315✔
1053

1054
  assert(mcsat->status == STATUS_IDLE); // We must have clear before
1055

1056
  if (trace_enabled(mcsat->ctx->trace, "mcsat::push")) {
1,315✔
1057
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat::push start\n");
×
1058
    trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1059
  }
1060

1061
  if (!mcsat_is_consistent(mcsat)) {
1,315✔
1062
    mcsat->inconsistent_push_calls ++;
798✔
1063
    return;
798✔
1064
  }
1065

1066
  // Internal stuff push
1067
  scope_holder_push(&mcsat->scope,
517✔
1068
      &mcsat->assertion_vars.size,
1069
      &mcsat->assertion_terms_original.size,
1070
      &mcsat->plugin_definition_lemmas.size,
1071
      NULL);
1072
  // Regular push for the internal data structures
1073
  mcsat_push_internal(mcsat);
517✔
1074
  // Push and set the base level on the trail
1075
  trail_new_base_level(mcsat->trail);
517✔
1076
  // Push the preprocessor
1077
  preprocessor_push(&mcsat->preprocessor);
517✔
1078

1079
  if (trace_enabled(mcsat->ctx->trace, "mcsat::push")) {
517✔
1080
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat::pop end\n");
×
1081
    trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1082
  }
1083

1084
  mcsat->interpolant = NULL_TERM;
517✔
1085
}
1086

1087

1088
void mcsat_pop(mcsat_solver_t* mcsat) {
1,231✔
1089

1090
  // External pop:
1091
  // - internal pop
1092
  // - assertions
1093
  // - variables and terms
1094

1095
  if (trace_enabled(mcsat->ctx->trace, "mcsat::pop")) {
1,231✔
1096
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat::pop start\n");
×
1097
    trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1098
  }
1099

1100
  if (mcsat->inconsistent_push_calls > 0) {
1,231✔
1101
    mcsat->inconsistent_push_calls --;
788✔
1102
    mcsat->status = STATUS_IDLE;
788✔
1103
    return;
788✔
1104
  }
1105

1106
  // Backtrack trail
1107
  uint32_t new_base_level = trail_pop_base_level(mcsat->trail);
443✔
1108

1109
  // Backtrack solver
1110
  mcsat_backtrack_to(mcsat, new_base_level);
443✔
1111

1112
  // Internal stuff pop
1113
  uint32_t assertion_vars_size = 0;
443✔
1114
  uint32_t assertion_terms_size = 0;
443✔
1115
  uint32_t definition_lemmas_size = 0;
443✔
1116
  scope_holder_pop(&mcsat->scope,
443✔
1117
      &assertion_vars_size,
1118
      &assertion_terms_size,
1119
      &definition_lemmas_size,
1120
      NULL);
1121
  ivector_shrink(&mcsat->assertion_vars, assertion_vars_size);
443✔
1122
  ivector_shrink(&mcsat->assertion_terms_original, assertion_terms_size);
443✔
1123

1124
  // Pop the preprocessor
1125
  preprocessor_pop(&mcsat->preprocessor);
443✔
1126

1127
  // Notify all the plugins that we just popped
1128
  mcsat_notify_plugins(mcsat, MCSAT_SOLVER_POP);
443✔
1129

1130
  // Garbage collect
1131
  mcsat_gc(mcsat, false);
443✔
1132
  (*mcsat->solver_stats.gc_calls) ++;
443✔
1133

1134
  // Definition lemmas (keep the ones that need the definition (variable still active)
1135
  uint32_t lemma_i = definition_lemmas_size, lemma_to_keep = definition_lemmas_size;
443✔
1136
  for (; lemma_i < mcsat->plugin_definition_lemmas.size; ++ lemma_i) {
1,027✔
1137
    term_t lemma = mcsat->plugin_definition_lemmas.data[lemma_i];
584✔
1138
    term_t variable = mcsat->plugin_definition_vars.data[lemma_i];
584✔
1139
    if (variable_db_has_variable(mcsat->var_db, variable)) {
584✔
1140
      mcsat->plugin_definition_lemmas.data[lemma_to_keep] = lemma;
584✔
1141
      mcsat->plugin_definition_vars.data[lemma_to_keep] = variable;
584✔
1142
      lemma_to_keep ++;
584✔
1143
    }
1144
  }
1145
  ivector_shrink(&mcsat->plugin_definition_lemmas, lemma_to_keep);
443✔
1146
  ivector_shrink(&mcsat->plugin_definition_vars, lemma_to_keep);
443✔
1147
  mcsat->plugin_definition_lemmas_i = definition_lemmas_size;
443✔
1148
  if (definition_lemmas_size < mcsat->plugin_definition_lemmas.size) {
443✔
1149
    mcsat_assert_formulas(mcsat, 0, NULL);
82✔
1150
  }
1151

1152
  // Set the status back to idle
1153
  mcsat->status = STATUS_IDLE;
443✔
1154
  mcsat->interpolant = NULL_TERM;
443✔
1155

1156
  if (trace_enabled(mcsat->ctx->trace, "mcsat::pop")) {
443✔
1157
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat::pop end\n");
×
1158
    trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1159
  }
1160
}
1161

1162
void mcsat_clear(mcsat_solver_t* mcsat) {
584✔
1163
  // Clear to be ready for more assertions:
1164
  // - Pop internal to base level
1165
  mcsat->assumption_i = 0;
584✔
1166
  mcsat->assumptions_decided_level = -1;
584✔
1167
  mcsat_backtrack_to(mcsat, mcsat->trail->decision_level_base);
584✔
1168
  mcsat->status = STATUS_IDLE;
584✔
1169
  mcsat->interpolant = NULL_TERM; // BD
584✔
1170
}
584✔
1171

1172
/**
1173
 * Get the indices of the plugins that claim to own the term t by type.
1174
 */
1175
static inline
1176
void mcsat_get_type_owners(mcsat_solver_t* mcsat, term_t t, int_mset_t* owners) {
188,831✔
1177
  uint32_t i, plugin_i;
1178
  i = type_kind(mcsat->types, term_type(mcsat->terms, t));
188,831✔
1179
  plugin_i = mcsat->type_owners[i];
188,831✔
1180
  assert(plugin_i != MCSAT_MAX_PLUGINS);
1181
  do  {
1182
    int_mset_add(owners, plugin_i);
188,831✔
1183
    i += NUM_TYPE_KINDS;
188,831✔
1184
    plugin_i = mcsat->type_owners[i];
188,831✔
1185
  } while (plugin_i != MCSAT_MAX_PLUGINS);
188,831✔
1186
}
188,831✔
1187

1188
/**
1189
 * Get the indices of the plugins that claim to own the term t by kind.
1190
 */
1191
static inline
1192
void mcsat_get_kind_owners(mcsat_solver_t* mcsat, term_t t, int_mset_t* owners) {
159,518✔
1193
  uint32_t i, plugin_i;
1194
  i = term_kind(mcsat->terms, t);
159,518✔
1195
  plugin_i = mcsat->kind_owners[i];
159,518✔
1196
  if (trace_enabled(mcsat->ctx->trace, "mcsat::get_kind_owner")) {
159,518✔
1197
    mcsat_trace_printf(mcsat->ctx->trace, "get_kind_owner: ");
×
1198
    trace_term_ln(mcsat->ctx->trace, mcsat->terms, t);
×
1199
  }
1200
  assert(plugin_i != MCSAT_MAX_PLUGINS || i == UNINTERPRETED_TERM || i == CONSTANT_TERM);
1201
  while (plugin_i != MCSAT_MAX_PLUGINS) {
318,162✔
1202
    int_mset_add(owners, plugin_i);
158,644✔
1203
    i += NUM_TERM_KINDS;
158,644✔
1204
    plugin_i = mcsat->kind_owners[i];
158,644✔
1205
  };
1206
}
159,518✔
1207

1208

1209
static void mcsat_process_registration_queue(mcsat_solver_t* mcsat) {
1,099,623✔
1210
  term_t t;
1211
  uint32_t i, plugin_i;
1212
  plugin_t* plugin;
1213
  plugin_trail_token_t prop_token;
1214
  int_mset_t to_notify;
1215
  ivector_t* to_notify_list;
1216

1217
  int_mset_construct(&to_notify, MCSAT_MAX_PLUGINS);
1,099,623✔
1218

1219
  while (!int_queue_is_empty(&mcsat->registration_queue)) {
1,268,912✔
1220
    // Next term to register
1221
    t = int_queue_pop(&mcsat->registration_queue);
169,289✔
1222
    assert(is_pos_term(t));
1223

1224
    if (trace_enabled(mcsat->ctx->trace, "mcsat::registration")) {
169,289✔
1225
      mcsat_trace_printf(mcsat->ctx->trace, "term registration: ");
×
1226
      trace_term_ln(mcsat->ctx->trace, mcsat->terms, t);
×
1227
    }
1228

1229
    // Get who to notify
1230
    int_mset_clear(&to_notify);
169,289✔
1231

1232
    // We notify the owners of the term type
1233
    mcsat_get_type_owners(mcsat, t, &to_notify);
169,289✔
1234

1235
    // We also notify the term kind owners, except for equality
1236
    term_kind_t kind = term_kind(mcsat->terms, t);
169,289✔
1237
    if (kind == EQ_TERM) {
169,289✔
1238
      mcsat_get_type_owners(mcsat, composite_term_arg(mcsat->terms, t, 0), &to_notify);
9,771✔
1239
      mcsat_get_type_owners(mcsat, composite_term_arg(mcsat->terms, t, 1), &to_notify);
9,771✔
1240
    } else {
1241
      mcsat_get_kind_owners(mcsat, t, &to_notify);
159,518✔
1242
    }
1243

1244
    // Notify
1245
    to_notify_list = int_mset_get_list(&to_notify);
169,289✔
1246
    for (i = 0; i < to_notify_list->size; ++i) {
430,440✔
1247
      plugin_i = to_notify_list->data[i];
261,151✔
1248
      plugin = mcsat->plugins[plugin_i].plugin;
261,151✔
1249
      trail_token_construct(&prop_token, mcsat->plugins[plugin_i].plugin_ctx, variable_null);
261,151✔
1250
      plugin->new_term_notify(plugin, t, (trail_token_t*) &prop_token);
261,151✔
1251
    }
1252
  }
1253

1254
  int_mset_destruct(&to_notify);
1,099,623✔
1255
}
1,099,623✔
1256

1257
/** Pass true to mark terms and types in the internal yices term tables */
1258
static
1259
void mcsat_gc(mcsat_solver_t* mcsat, bool mark_and_gc_internal) {
581✔
1260

1261
  uint32_t i;
1262
  variable_t var;
1263
  gc_info_t gc_vars;
1264
  plugin_t* plugin;
1265

1266
  if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
581✔
1267
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc():\n");
×
1268
    mcsat_show_stats(mcsat, mcsat->ctx->trace->file);
×
1269
  }
1270

1271
  // Mark previously used term in the term table
1272
  // set_bitvector(mcsat->terms->mark, mcsat->terms_size_on_solver_entry);
1273

1274
  // Construct the variable info
1275
  gc_info_construct(&gc_vars, variable_null, true);
581✔
1276

1277
  if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
581✔
1278
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc(): marking\n");
×
1279
  }
1280

1281
  // Mark the assertion variables as needed
1282
  for (i = 0; i < mcsat->assertion_vars.size; ++ i) {
27,390✔
1283
    var = mcsat->assertion_vars.data[i];
26,809✔
1284
    assert(variable_db_is_variable(mcsat->var_db, var, true));
1285
    gc_info_mark(&gc_vars, var);
26,809✔
1286
    if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
26,809✔
1287
      mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc(): marking ");
×
1288
      trace_term_ln(mcsat->ctx->trace, mcsat->terms, variable_db_get_term(mcsat->var_db, var));
×
1289
    }
1290
  }
1291
  for (i = 0; i < mcsat->assumption_vars.size; ++ i) {
581✔
1292
    var = mcsat->assumption_vars.data[i];
×
1293
    assert(variable_db_is_variable(mcsat->var_db, var, true));
1294
    gc_info_mark(&gc_vars, var);
×
1295
    if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
×
1296
      mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc(): marking ");
×
1297
      trace_term_ln(mcsat->ctx->trace, mcsat->terms, variable_db_get_term(mcsat->var_db, var));
×
1298
    }
1299
  }
1300

1301
  // Mark the decision hints if there are any
1302
  for (i = 0; i < int_queue_size(&mcsat->hinted_decision_vars); ++ i) {
581✔
1303
    gc_info_mark(&gc_vars, int_queue_at(&mcsat->hinted_decision_vars, i));
×
1304
  }
1305
  for (i = 0; i < mcsat->top_decision_vars.size; ++i) {
581✔
1306
    gc_info_mark(&gc_vars, mcsat->top_decision_vars.data[i]);
×
1307
  }
1308

1309
  // Mark the trail variables as needed
1310
  trail_gc_mark(mcsat->trail, &gc_vars);
581✔
1311

1312
  // Mark variables by plugins
1313
  for (;;) {
1314

1315
    // Mark with each plugin
1316
    for (i = 0; i < mcsat->plugins_count; ++ i) {
9,667✔
1317
      if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
8,286✔
1318
        mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc(): marking with %s\n", mcsat->plugins[i].plugin_name);
×
1319
      }
1320
      plugin = mcsat->plugins[i].plugin;
8,286✔
1321
      if (plugin->gc_mark) {
8,286✔
1322
        plugin->gc_mark(plugin, &gc_vars);
6,905✔
1323
      }
1324
    }
1325

1326
    // If any new ones marked, go to the new level and continue marking
1327
    if (gc_info_get_level_size(&gc_vars) > 0) {
1,381✔
1328
      gc_info_new_level(&gc_vars);
800✔
1329
    } else {
1330
      // Nothing new marked
1331
      break;
581✔
1332
    }
1333
  }
1334

1335
  if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
581✔
1336
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc(): sweeping\n");
×
1337
  }
1338

1339
  // Collect the unused variables
1340
  variable_db_gc_sweep(mcsat->var_db, &gc_vars);
581✔
1341

1342
  // Do the sweep
1343
  for (i = 0; i < mcsat->plugins_count; ++ i) {
4,067✔
1344
    plugin = mcsat->plugins[i].plugin;
3,486✔
1345
    if (plugin->gc_sweep) {
3,486✔
1346
      plugin->gc_sweep(plugin, &gc_vars);
2,905✔
1347
    }
1348
  }
1349

1350
  // Trail sweep
1351
  trail_gc_sweep(mcsat->trail, &gc_vars);
581✔
1352

1353
  // Variable queue sweep
1354
  var_queue_gc_sweep(&mcsat->var_queue, &gc_vars);
581✔
1355

1356
  // If asked mark all the terms
1357
  if (mark_and_gc_internal) {
581✔
1358
    for (i = 0; i < gc_vars.marked.size; ++ i) {
251✔
1359
      variable_t x = gc_vars.marked.data[i];
245✔
1360
      term_t x_term = variable_db_get_term(mcsat->var_db, x);
245✔
1361
      term_t x_type = term_type(mcsat->terms, x_term);
245✔
1362
      term_table_set_gc_mark(mcsat->terms, index_of(x_term));
245✔
1363
      type_table_set_gc_mark(mcsat->types, x_type);
245✔
1364
    }
1365

1366
    // Mark with each plugin
1367
    for (i = 0; i < mcsat->plugins_count; ++ i) {
42✔
1368
      if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
36✔
1369
        mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc(): marking with %s\n", mcsat->plugins[i].plugin_name);
×
1370
      }
1371
      plugin = mcsat->plugins[i].plugin;
36✔
1372
      if (plugin->gc_mark_and_clear) {
36✔
1373
        plugin->gc_mark_and_clear(plugin);
6✔
1374
      }
1375
    }
1376

1377
    // Mark with the preprocessor
1378
    preprocessor_gc_mark(&mcsat->preprocessor);
6✔
1379
  }
1380

1381
  // Done, destruct
1382
  gc_info_destruct(&gc_vars);
581✔
1383

1384
  // Remove terms from registration cache
1385
  int_hset_t new_registration_cache;
1386
  init_int_hset(&new_registration_cache, 0);
581✔
1387
  int_hset_close(&mcsat->registration_cache);
581✔
1388
  for (i = 0; i < mcsat->registration_cache.nelems; ++ i) {
330,894✔
1389
    term_t t = mcsat->registration_cache.data[i];
330,313✔
1390
    variable_t x = variable_db_get_variable_if_exists(mcsat->var_db, t);
330,313✔
1391
    if (x != variable_null) {
330,313✔
1392
      int_hset_add(&new_registration_cache, t);
319,000✔
1393
    }
1394
  }
1395
  delete_int_hset(&mcsat->registration_cache);
581✔
1396
  mcsat->registration_cache = new_registration_cache;
581✔
1397

1398
  // Garbage collect with yices
1399
  // term_table_gc(mcsat->terms, 1);
1400

1401
  if (trace_enabled(mcsat->ctx->trace, "mcsat::gc")) {
581✔
1402
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_gc(): done\n");
×
1403
  }
1404
}
581✔
1405

1406
static
1407
void mcsat_backtrack_to(mcsat_solver_t* mcsat, uint32_t level) {
257,392✔
1408
  assert((int32_t) level >= mcsat->assumptions_decided_level);
1409
  while (mcsat->trail->decision_level > level) {
932,534✔
1410

1411
    if (trace_enabled(mcsat->ctx->trace, "mcsat::incremental")) {
675,142✔
1412
      trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1413
    }
1414

1415
    // Pop the trail
1416
    trail_pop(mcsat->trail);
675,142✔
1417

1418
    if (trace_enabled(mcsat->ctx->trace, "mcsat::incremental")) {
675,142✔
1419
      trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1420
    }
1421

1422
    // Pop the plugins
1423
    mcsat_pop_internal(mcsat);
675,142✔
1424
  }
1425
}
257,392✔
1426

1427
static
1428
void mcsat_process_requests(mcsat_solver_t* mcsat) {
748,470✔
1429

1430
  if (mcsat->pending_requests) {
748,470✔
1431

1432
    // Restarts
1433
    if (mcsat->pending_requests_all.restart) {
17,409✔
1434
      if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
17,409✔
1435
        mcsat_trace_printf(mcsat->ctx->trace, "restarting\n");
×
1436
      }
1437
      mcsat->assumptions_decided_level = -1;
17,409✔
1438
      mcsat->assumption_i = 0;
17,409✔
1439
      mcsat_backtrack_to(mcsat, mcsat->trail->decision_level_base);
17,409✔
1440
      mcsat->pending_requests_all.restart = false;
17,409✔
1441
      (*mcsat->solver_stats.restarts) ++;
17,409✔
1442
      mcsat_notify_plugins(mcsat, MCSAT_SOLVER_RESTART);
17,409✔
1443
    }
1444

1445
    // GC
1446
    if (mcsat->pending_requests_all.gc_calls) {
17,409✔
1447
      if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
132✔
1448
        mcsat_trace_printf(mcsat->ctx->trace, "garbage collection\n");
×
1449
      }
1450
      mcsat_gc(mcsat, false);
132✔
1451
      mcsat->pending_requests_all.gc_calls = false;
132✔
1452
      (*mcsat->solver_stats.gc_calls) ++;
132✔
1453
    }
1454

1455
    // All services
1456
    mcsat->pending_requests = false;
17,409✔
1457
  }
1458
}
748,470✔
1459

1460
/**
1461
 * Perform propagation by running all plugins in sequence. Stop if a conflict
1462
 * is encountered.
1463
 */
1464
static
1465
bool mcsat_propagate(mcsat_solver_t* mcsat, bool run_learning) {
912,413✔
1466

1467
  assert(int_queue_is_empty(&mcsat->registration_queue));
1468

1469
  uint32_t plugin_i;
1470
  plugin_t* plugin;
1471
  plugin_trail_token_t prop_token;
1472
  bool someone_propagated;
1473

1474
  do {
1475
    // Repeat until no plugin makes any progress
1476
    someone_propagated = false;
1,314,071✔
1477
    // Propagate with all the plugins in turn
1478
    for (plugin_i = 0; mcsat_is_consistent(mcsat) && plugin_i < mcsat->plugins_count; ++ plugin_i) {
8,650,262✔
1479
      if (trace_enabled(mcsat->ctx->trace, "mcsat::propagate")) {
7,336,191✔
1480
        mcsat_trace_printf(mcsat->ctx->trace, "mcsat_propagate(): propagating with %s\n", mcsat->plugins[plugin_i].plugin_name);
×
1481
      }
1482
      // Make the token
1483
      trail_token_construct(&prop_token, mcsat->plugins[plugin_i].plugin_ctx, variable_null);
7,336,191✔
1484
      // Propagate
1485
      plugin = mcsat->plugins[plugin_i].plugin;
7,336,191✔
1486
      if (plugin->propagate) {
7,336,191✔
1487
        plugin->propagate(plugin, (trail_token_t*) &prop_token);
6,125,624✔
1488
      }
1489
      if (prop_token.used > 0) {
7,336,191✔
1490
        someone_propagated = true;
591,122✔
1491
      }
1492
    }
1493
    // If at base level, plugins can do some more expensive learning/propagation
1494
    if (run_learning && !someone_propagated && trail_is_at_base_level(mcsat->trail)) {
1,314,071✔
1495
      // Propagate with all the plugins in turn
1496
      for (plugin_i = 0; mcsat_is_consistent(mcsat) && plugin_i < mcsat->plugins_count; ++ plugin_i) {
6,932✔
1497
        if (trace_enabled(mcsat->ctx->trace, "mcsat::propagate")) {
5,938✔
1498
          mcsat_trace_printf(mcsat->ctx->trace, "mcsat_propagate(): learning with %s\n", mcsat->plugins[plugin_i].plugin_name);
×
1499
        }
1500
        // Make the token
1501
        trail_token_construct(&prop_token, mcsat->plugins[plugin_i].plugin_ctx, variable_null);
5,938✔
1502
        // Propagate
1503
        plugin = mcsat->plugins[plugin_i].plugin;
5,938✔
1504
        if (plugin->learn) {
5,938✔
1505
          plugin->learn(plugin, (trail_token_t*) &prop_token);
1,988✔
1506
        }
1507
        if (prop_token.used > 0) {
5,938✔
1508
          someone_propagated = true;
43✔
1509
        }
1510
      }
1511
    }
1512
  } while (someone_propagated && mcsat_is_consistent(mcsat));
1,314,071✔
1513

1514
  return someone_propagated;
912,413✔
1515
}
1516

1517
static
1518
void mcsat_assert_formula(mcsat_solver_t* mcsat, term_t f) {
77,416✔
1519

1520
  term_t f_pos;
1521
  variable_t f_pos_var;
1522

1523
  if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
77,416✔
1524
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_assert_formula()\n");
×
1525
    trace_term_ln(mcsat->ctx->trace, mcsat->terms, f);
×
1526
  }
1527

1528
  // If we're unsat, no more assertions
1529
  if (!mcsat_is_consistent(mcsat)) {
77,416✔
1530
    return;
162✔
1531
  }
1532

1533
  (*mcsat->solver_stats.assertions) ++;
77,254✔
1534

1535
  assert(trail_is_at_base_level(mcsat->trail));
1536
  assert(int_queue_is_empty(&mcsat->registration_queue));
1537

1538
  // Add the terms
1539
  f_pos = unsigned_term(f);
77,254✔
1540
  f_pos_var = variable_db_get_variable(mcsat->var_db, f_pos);
77,254✔
1541
  mcsat_process_registration_queue(mcsat);
77,254✔
1542

1543
  // Remember the assertion
1544
  ivector_push(&mcsat->assertion_vars, f_pos_var);
77,254✔
1545

1546
  // Assert the formula
1547
  if (f_pos == f) {
77,254✔
1548
    // f = true
1549
    if (!trail_has_value(mcsat->trail, f_pos_var)) {
74,373✔
1550
      trail_add_propagation(mcsat->trail, f_pos_var, &mcsat_value_true, MCSAT_MAX_PLUGINS, mcsat->trail->decision_level);
49,403✔
1551
    } else {
1552
      // If negative already, we're inconsistent
1553
      if (!trail_get_boolean_value(mcsat->trail, f_pos_var)) {
24,970✔
1554
        trail_set_inconsistent(mcsat->trail);
4✔
1555
        return;
4✔
1556
      }
1557
    }
1558
  } else {
1559
    // f = false
1560
    if (!trail_has_value(mcsat->trail, f_pos_var)) {
2,881✔
1561
      trail_add_propagation(mcsat->trail, f_pos_var, &mcsat_value_false, MCSAT_MAX_PLUGINS, mcsat->trail->decision_level);
2,816✔
1562
    } else {
1563
      // If positive already, we're inconsistent
1564
      if (trail_get_boolean_value(mcsat->trail, f_pos_var)) {
65✔
1565
        trail_set_inconsistent(mcsat->trail);
38✔
1566
        return;
38✔
1567
      }
1568
    }
1569
  }
1570

1571
  // Do propagation
1572
  mcsat_propagate(mcsat, false);
77,212✔
1573
}
1574

1575
/**
1576
 * Decide one of the unassigned literals. Decide the first literal that is bigger
1577
 * than the given bound (to make sure we decide on t(x) instead of x).
1578
 */
1579
static
1580
bool mcsat_decide_one_of(mcsat_solver_t* mcsat, ivector_t* literals, term_t bound) {
57,999✔
1581

1582
  uint32_t i, unassigned_count;
1583
  term_t literal;
1584
  term_t literal_pos;
1585
  variable_t literal_var;
1586

1587
  term_t to_decide_lit = NULL_TERM;
57,999✔
1588
  term_t to_decide_atom = NULL_TERM;
57,999✔
1589
  variable_t to_decide_var = variable_null;
57,999✔
1590

1591
  for (i = 0, unassigned_count = 0; i < literals->size; ++ i) {
95,548✔
1592

1593
    literal = literals->data[i];
58,455✔
1594
    literal_pos = unsigned_term(literal);
58,455✔
1595
    literal_var = variable_db_get_variable_if_exists(mcsat->var_db, literal_pos);
58,455✔
1596

1597
    assert(literal_var != variable_null);
1598

1599
    if (trace_enabled(mcsat->ctx->trace, "mcsat::lemma")) {
58,455✔
1600
      mcsat_trace_printf(mcsat->ctx->trace, "trying undecided :\n");
×
1601
      trace_term_ln(mcsat->ctx->trace, mcsat->ctx->terms, literal);
×
1602
    }
1603

1604
    // Can be decided?
1605
    if (!trail_has_value(mcsat->trail, literal_var)) {
58,455✔
1606
      unassigned_count ++;
20,910✔
1607
      if (trace_enabled(mcsat->ctx->trace, "mcsat::lemma")) {
20,910✔
1608
        mcsat_trace_printf(mcsat->ctx->trace, "unassigned!\n");
×
1609
      }
1610
      if (bound == NULL_TERM || literal_pos > bound) {
20,910✔
1611
        to_decide_lit = literal;
20,906✔
1612
        to_decide_atom = literal_pos;
20,906✔
1613
        to_decide_var = literal_var;
20,906✔
1614
        break;
20,906✔
1615
      }
1616
    } else {
1617
      if (trace_enabled(mcsat->ctx->trace, "mcsat::lemma")) {
37,545✔
1618
        mcsat_trace_printf(mcsat->ctx->trace, "assigned!\n");
×
1619
      }
1620
    }
1621
  }
1622

1623
  if (to_decide_var != variable_null) {
57,999✔
1624
    if (trace_enabled(mcsat->ctx->trace, "mcsat::lemma")) {
20,906✔
1625
      mcsat_trace_printf(mcsat->ctx->trace, "picked:\n");
×
1626
      trace_term_ln(mcsat->ctx->trace, mcsat->ctx->terms, to_decide_lit);
×
1627
    }
1628
    mcsat_push_internal(mcsat);
20,906✔
1629
    const mcsat_value_t* value = to_decide_atom == to_decide_lit ? &mcsat_value_true : &mcsat_value_false;
20,906✔
1630
    trail_add_decision(mcsat->trail, to_decide_var, value, MCSAT_MAX_PLUGINS);
20,906✔
1631
    return true;
20,906✔
1632
  } else {
1633
    if (unassigned_count > 0) {
37,093✔
1634
      // Couldn't find a bound decision, do arbitrary
1635
      return mcsat_decide_one_of(mcsat, literals, NULL_TERM);
×
1636
    }
1637
    return false;
37,093✔
1638
  }
1639
}
1640

1641
/**
1642
 * Add a lemma (a disjunction). Each lemma needs to lead to some progress. This
1643
 * means that:
1644
 *  * no literal should evaluate to true
1645
 *  * if only one literal is false, it should be propagated by one of the plugins
1646
 *  * if more then one literals is false, one of them should be decided to true
1647
 *    by one of the plugins
1648
 */
1649
static
1650
void mcsat_add_lemma(mcsat_solver_t* mcsat, ivector_t* lemma, term_t decision_bound) {
86,731✔
1651

1652
  uint32_t i, level, top_level;
1653
  ivector_t unassigned;
1654
  term_t disjunct, disjunct_pos;
1655
  variable_t disjunct_pos_var;
1656
  plugin_t* plugin;
1657

1658
  (*mcsat->solver_stats.lemmas)++;
86,731✔
1659

1660
  // assert(int_queue_is_empty(&mcsat->registration_queue));
1661
  // TODO: revisit this. it's done in integer solver to do splitting in
1662
  // conflict analysis
1663

1664
  if (trace_enabled(mcsat->ctx->trace, "mcsat::lemma")) {
86,731✔
1665
    mcsat_trace_printf(mcsat->ctx->trace, "lemma:\n");
×
1666
    for (i = 0; i < lemma->size; ++ i) {
×
1667
      mcsat_trace_printf(mcsat->ctx->trace, "\t");
×
1668
      trace_term_ln(mcsat->ctx->trace, mcsat->ctx->terms, lemma->data[i]);
×
1669
    }
1670
    trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1671
  }
1672

1673
  init_ivector(&unassigned, 0);
86,731✔
1674

1675
  top_level = mcsat->trail->decision_level_base;
86,731✔
1676
  for (i = 0; i < lemma->size; ++ i) {
1,107,038✔
1677

1678
    // Get the variables for the disjunct
1679
    disjunct = lemma->data[i];
1,020,307✔
1680
    assert(term_type_kind(mcsat->terms, disjunct) == BOOL_TYPE);
1681
    disjunct_pos = unsigned_term(disjunct);
1,020,307✔
1682
    disjunct_pos_var = variable_db_get_variable(mcsat->var_db, disjunct_pos);
1,020,307✔
1683
    if (trace_enabled(mcsat->ctx->trace, "mcsat::lemma")) {
1,020,307✔
1684
      mcsat_trace_printf(mcsat->ctx->trace, "literal: ");
×
1685
      variable_db_print_variable(mcsat->var_db, disjunct_pos_var, stderr);
×
1686
      if (trail_has_value(mcsat->trail, disjunct_pos_var)) {
×
1687
        mcsat_trace_printf(mcsat->ctx->trace, "\nvalue: ");
×
1688
        const mcsat_value_t* value = trail_get_value(mcsat->trail, disjunct_pos_var);
×
1689
        mcsat_value_print(value, stderr);
×
1690
        mcsat_trace_printf(mcsat->ctx->trace, "\n");
×
1691
      } else {
1692
        mcsat_trace_printf(mcsat->ctx->trace, "\nno value\n");
×
1693
      }
1694
    }
1695

1696
    // Process any newly registered variables
1697
    mcsat_process_registration_queue(mcsat);
1,020,307✔
1698

1699
    // Check if the literal has value (only negative allowed)
1700
    if (trail_has_value(mcsat->trail, disjunct_pos_var)) {
1,020,307✔
1701
      assert(trail_get_value(mcsat->trail, disjunct_pos_var)->type == VALUE_BOOLEAN);
1702
      assert(trail_get_value(mcsat->trail, disjunct_pos_var)->b == (disjunct != disjunct_pos));
1703
      level = trail_get_level(mcsat->trail, disjunct_pos_var);
782,730✔
1704
      if (level > top_level) {
782,730✔
1705
        top_level = level;
144,451✔
1706
      }
1707
    } else {
1708
      ivector_push(&unassigned, lemma->data[i]);
237,577✔
1709
    }
1710
  }
1711

1712
  assert(unassigned.size > 0);
1713
  assert(top_level <= mcsat->trail->decision_level);
1714

1715
  // Backtrack to the appropriate level and do some progress
1716
  if (unassigned.size == 1) {
86,731✔
1717
    // UIP, just make sure we're not going below assumptions
1718
    if ((int32_t) top_level >= mcsat->assumptions_decided_level) {
65,280✔
1719
      mcsat_backtrack_to(mcsat, top_level);
65,272✔
1720
    }
1721
  } else {
1722
    // Non-UIP, we're already below, and we'll split on a new term, that's enough
1723
  }
1724

1725
  uint32_t old_trail_size = mcsat->trail->elements.size;
86,731✔
1726

1727
  // Notify the plugins about the lemma
1728
  for (i = 0; i < mcsat->plugins_count; ++ i) {
607,117✔
1729
    plugin = mcsat->plugins[i].plugin;
520,386✔
1730
    if (plugin->new_lemma_notify) {
520,386✔
1731
      // Make the token
1732
      plugin_trail_token_t prop_token;
1733
      trail_token_construct(&prop_token, mcsat->plugins[i].plugin_ctx, variable_null);
260,193✔
1734
      plugin->new_lemma_notify(plugin, lemma, (trail_token_t*) &prop_token);
260,193✔
1735
    }
1736
  }
1737

1738
  // Propagate any
1739
  mcsat_propagate(mcsat, false);
86,731✔
1740
  bool propagated = old_trail_size < mcsat->trail->elements.size;
86,731✔
1741

1742
  // Decide a literal if necessary. At this point, if it was UIP they are all
1743
  // assigned. If not, we assign arbitrary.
1744
  bool decided = false;
86,731✔
1745
  bool consistent = mcsat_is_consistent(mcsat);
86,731✔
1746
  if (consistent) {
86,731✔
1747
    decided = mcsat_decide_one_of(mcsat, &unassigned, decision_bound);
57,999✔
1748
  }
1749
  if(trace_enabled(mcsat->ctx->trace, "mcsat::lemma") && !(propagated || !consistent || decided)) {
86,731✔
1750
    trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
1751
  }
1752
  assert(propagated || !consistent || decided);
1753

1754
  delete_ivector(&unassigned);
86,731✔
1755
}
86,731✔
1756

1757
uint32_t mcsat_get_lemma_weight(mcsat_solver_t* mcsat, const ivector_t* lemma, lemma_weight_type_t type) {
86,731✔
1758
  uint32_t i, weight = 0;
86,731✔
1759
  term_t atom;
1760
  variable_t atom_var;
1761
  int_mset_t levels;
1762

1763
  switch(type) {
86,731✔
1764
  case LEMMA_WEIGHT_UNIT:
×
1765
    weight = 1;
×
1766
    break;
×
1767
  case LEMMA_WEIGHT_SIZE:
86,731✔
1768
    weight = lemma->size;
86,731✔
1769
    break;
86,731✔
1770
  case LEMMA_WEIGHT_GLUE:
×
1771
    int_mset_construct(&levels, UINT32_MAX);
×
1772
    for (i = 0; i < lemma->size; ++ i) {
×
1773
      atom = unsigned_term(lemma->data[i]);
×
1774
      atom_var = variable_db_get_variable_if_exists(mcsat->var_db, atom);
×
1775
      assert(atom_var != variable_null);
1776
      if (trail_has_value(mcsat->trail, atom_var)) {
×
1777
        int_mset_add(&levels, trail_get_level(mcsat->trail, atom_var));
×
1778
      }
1779
    }
1780
    weight = int_mset_get_list(&levels)->size;
×
1781
    int_mset_destruct(&levels);
×
1782
    break;
×
1783
  }
1784

1785
  return weight;
86,731✔
1786
}
1787

1788
/** Check propagation with Yices: reasons => x = subst */
1789
static
1790
void propagation_check(const ivector_t* reasons, term_t x, term_t subst) {
×
1791
  ctx_config_t* config = yices_new_config();
×
1792
   context_t* ctx = yices_new_context(config);
×
1793
   uint32_t i;
1794
   for (i = 0; i < reasons->size; ++i) {
×
1795
     term_t literal = reasons->data[i];
×
1796
     int32_t ret = yices_assert_formula(ctx, literal);
×
1797
     if (ret != 0) {
×
1798
       // unsupported by regular yices
1799
       fprintf(stderr, "skipping propagation (ret 1)\n");
×
1800
       yices_print_error(stderr);
×
1801
       return;
×
1802
     }
1803
   }
1804
   term_t eq = yices_eq(x, subst);
×
1805
   int32_t ret = yices_assert_formula(ctx, opposite_term(eq));
×
1806
   if (ret != 0) {
×
1807
     fprintf(stderr, "skipping propagation (ret 2)\n");
×
1808
     yices_print_error(stderr);
×
1809
     return;
×
1810
   }
1811
   smt_status_t result = yices_check_context(ctx, NULL);
×
1812
   (void) result;
1813
   assert(result == STATUS_UNSAT);
1814
   yices_free_context(ctx);
×
1815
   yices_free_config(config);
×
1816
}
1817

1818
static
1819
uint32_t mcsat_compute_backtrack_level(mcsat_solver_t* mcsat, uint32_t level) {
86,913✔
1820
  uint32_t backtrack_level = mcsat->trail->decision_level_base;
86,913✔
1821
  if (backtrack_level < level)
86,913✔
1822
    backtrack_level = level;
86,877✔
1823
  if ((int32_t) backtrack_level <= mcsat->assumptions_decided_level)
86,913✔
1824
    backtrack_level = mcsat->assumptions_decided_level;
39✔
1825
  return backtrack_level;
86,913✔
1826
}
1827

1828
/**
1829
 * Input: literals that can evaluate to true (or false if negated)
1830
 * Output: simplified literals that can evaluate to true and imply the input literals
1831
 */
1832
static
1833
void mcsat_simplify_literals(mcsat_solver_t* mcsat, ivector_t* literals, bool literals_negated, ivector_t* out_literals) {
34✔
1834
  uint32_t i;
1835
  for (i = 0; i < literals->size; ++ i) {
129✔
1836
    term_t disjunct = literals->data[i];
95✔
1837
    if (literals_negated) {
95✔
1838
      disjunct = opposite_term(disjunct);
95✔
1839
    }
1840
    term_kind_t kind = term_kind(mcsat->terms, disjunct);
95✔
1841
    if (int_hset_member(&mcsat->internal_kinds, kind)) {
95✔
1842
      uint32_t kind_i = kind;
15✔
1843
      bool simplified = false;
15✔
1844
      for (; !simplified && mcsat->kind_owners[kind_i] != MCSAT_MAX_PLUGINS; kind_i += NUM_TERM_KINDS) {
30✔
1845
        plugin_t* plugin = mcsat->plugins[mcsat->kind_owners[kind_i]].plugin;
15✔
1846
        if (plugin->simplify_conflict_literal) {
15✔
1847
          simplified = plugin->simplify_conflict_literal(plugin, disjunct, out_literals);
15✔
1848
        }
1849
      }
1850
      assert(simplified);
1851
    } else {
1852
      ivector_push(out_literals, disjunct);
80✔
1853
    }
1854
  }
1855
}
34✔
1856

1857
static
1858
term_t mcsat_analyze_final(mcsat_solver_t* mcsat, conflict_t* input_conflict) {
34✔
1859

1860
  variable_t var;
1861
  plugin_t* plugin = NULL;
34✔
1862
  //  uint32_t plugin_i = MCSAT_MAX_PLUGINS; // BD: infer dead store
1863
  uint32_t plugin_i;
1864
  tracer_t* trace = mcsat->ctx->trace;
34✔
1865
  term_t substitution;
1866

1867
  // First we try to massage the conflict into presentable form
1868
  ivector_t literals;
1869
  init_ivector(&literals, 0);
34✔
1870
  conflict_get_negated_literals(input_conflict, &literals);
34✔
1871

1872
  ivector_t reason_literals;
1873
  init_ivector(&reason_literals, 0);
34✔
1874

1875
  assert(mcsat->trail->elements.size > 0);
1876

1877
  mcsat_trail_t* trail = mcsat->trail;
34✔
1878

1879
  conflict_t conflict;
1880
  conflict_construct(&conflict, &literals, false, (mcsat_evaluator_interface_t*) &mcsat->evaluator, mcsat->var_db, trail, &mcsat->tm, trace);
34✔
1881

1882
  // We save the trail, and then restore at the end
1883
  mcsat_trail_t saved_trail;
1884
  trail_construct_copy(&saved_trail, mcsat->trail);
34✔
1885

1886
  // Analyze while at least one variable at conflict level
1887
  while (trail_size(mcsat->trail) > 0) {
928✔
1888

1889
    // Variable we might be resolving
1890
    var = trail_back(mcsat->trail);
894✔
1891

1892
    if (trace_enabled(trace, "mcsat::conflict")) {
894✔
1893
      mcsat_trace_printf(trace, "current trail:\n");
×
1894
      trail_print(trail, trace->file);
×
1895
      mcsat_trace_printf(trace, "current conflict: ");
×
1896
      conflict_print(&conflict, trace->file);
×
1897
      mcsat_trace_printf(trace, "var: ");
×
1898
      variable_db_print_variable(mcsat->var_db, var, trace->file);
×
1899
      mcsat_trace_printf(trace, "\n");
×
1900
    }
1901

1902
    // Skip decisions
1903
    if (trail_get_assignment_type(mcsat->trail, var) == DECISION) {
894✔
1904
      trail_pop_decision(mcsat->trail);
81✔
1905
      conflict_recompute_level_info(&conflict);
81✔
1906
      continue;
81✔
1907
    }
1908

1909
    // Skip the conflict variable (it was propagated)
1910
    if (var == mcsat->variable_in_conflict) {
813✔
1911
      trail_pop_propagation(mcsat->trail);
4✔
1912
      conflict_recompute_level_info(&conflict);
4✔
1913
      continue;
4✔
1914
    }
1915

1916
    if (conflict_contains(&conflict, var)) {
809✔
1917
      // Get the plugin that performed the propagation
1918
      plugin_i = trail_get_source_id(trail, var);
201✔
1919
      if (plugin_i != MCSAT_MAX_PLUGINS) {
201✔
1920
        plugin = mcsat->plugins[plugin_i].plugin;
173✔
1921
      } else {
1922
        plugin = NULL;
28✔
1923
      }
1924

1925
      if (trace_enabled(trace, "mcsat::conflict")) {
201✔
1926
        mcsat_trace_printf(trace, "resolving ");
×
1927
        variable_db_print_variable(mcsat->var_db, var, trace->file);
×
1928
        if (plugin) {
×
1929
          mcsat_trace_printf(trace, " with %s\n", mcsat->plugins[plugin_i].plugin_name);
×
1930
        } else {
1931
          mcsat_trace_printf(trace, " with assertion\n");
×
1932
        }
1933
        mcsat_trace_printf(trace, "current conflict:\n");
×
1934
        conflict_print(&conflict, trace->file);
×
1935
      }
1936

1937
      // Resolve the variable
1938
      ivector_reset(&literals);
201✔
1939
      if (plugin) {
201✔
1940
        assert(plugin->explain_propagation);
1941
        substitution = plugin->explain_propagation(plugin, var, &literals);
173✔
1942
      } else {
1943
        bool value = trail_get_boolean_value(trail, var);
28✔
1944
        substitution = value ? true_term : false_term;
28✔
1945
      }
1946
      conflict_resolve_propagation(&conflict, var, substitution, &literals);
201✔
1947
    } else {
1948
      // Continue with resolution
1949
      trail_pop_propagation(mcsat->trail);
608✔
1950
    }
1951
  }
1952

1953
  if (trace_enabled(trace, "mcsat::conflict")) {
34✔
1954
    mcsat_trace_printf(trace, "final conflict:\n");
×
1955
    conflict_print(&conflict, trace->file);
×
1956
  }
1957

1958
  // Restore the trail
1959
  mcsat_trail_t tmp;
1960
  tmp = *mcsat->trail;
34✔
1961
  *mcsat->trail = saved_trail;
34✔
1962
  saved_trail = tmp;
34✔
1963
  trail_destruct(&saved_trail);
34✔
1964

1965
  // Simplify the conflict literals
1966
  ivector_t* final_literals = conflict_get_literals(&conflict);
34✔
1967
  ivector_reset(&literals);
34✔
1968
  mcsat_simplify_literals(mcsat, final_literals, true, &literals);
34✔
1969

1970
  // Construct the interpolant
1971
  term_t interpolant = literals.size == 0 ? true_term : mk_and(&mcsat->tm, literals.size, literals.data);
34✔
1972
  interpolant = opposite_term(interpolant);
34✔
1973

1974
  if (trace_enabled(trace, "mcsat::interpolant::check")) {
34✔
1975
    value_t v = model_get_term_value(mcsat->assumptions_model, interpolant);
×
1976
    bool interpolant_is_false = is_false(&mcsat->assumptions_model->vtbl, v);
×
1977
    if (!interpolant_is_false) {
×
1978
      fprintf(trace_out(trace), "model:\n");
×
1979
      model_print(trace_out(trace), mcsat->assumptions_model);
×
1980
      fprintf(trace_out(trace), "interpolant:\n");
×
1981
      trace_term_ln(trace, conflict.terms, interpolant);
×
1982
    }
1983
    assert(interpolant_is_false);
1984
  }
1985

1986
  // Remove temps
1987
  delete_ivector(&literals);
34✔
1988
  delete_ivector(&reason_literals);
34✔
1989
  conflict_destruct(&conflict);
34✔
1990

1991
  if (trace_enabled(trace, "mcsat::conflict")) {
34✔
1992
    mcsat_trace_printf(trace, "interpolant:\n");
×
1993
    trace_term_ln(trace, conflict.terms, interpolant);
×
1994
  }
1995

1996
  return interpolant;
34✔
1997
}
1998

1999
static
2000
bool mcsat_conflict_with_assumptions(mcsat_solver_t* mcsat, uint32_t conflict_level) {
4,302,968✔
2001
  // If we decided some assumptions, then backtracked under that level
2002
  if ((int32_t) conflict_level <= mcsat->assumptions_decided_level) {
4,302,968✔
2003
    return true;
78✔
2004
  }
2005
  // If we haven't decided any assumptions yet but there is a conflict
2006
  if (trail_is_at_base_level(mcsat->trail) && mcsat->assumption_vars.size > 0) {
4,302,890✔
2007
    return true;
2✔
2008
  }
2009
  return false;
4,302,888✔
2010
}
2011

2012
static
2013
void mcsat_analyze_conflicts(mcsat_solver_t* mcsat, uint32_t* restart_resource) {
86,816✔
2014

2015
  conflict_t conflict;
2016
  plugin_t* plugin = NULL;
86,816✔
2017
  uint32_t plugin_i = MCSAT_MAX_PLUGINS;
86,816✔
2018
  tracer_t* trace;
2019

2020
  uint32_t conflict_level, backtrack_level;
2021
  variable_t var;
2022

2023
  term_t decision_bound = NULL_TERM;
86,816✔
2024

2025
  ivector_t reason;
2026
  term_t substitution;
2027

2028
  ivector_t* conflict_disjuncts;
2029

2030
  init_ivector(&reason, 0);
86,816✔
2031
  trace = mcsat->ctx->trace;
86,816✔
2032

2033
  // Plugin that's in conflict
2034
  if (mcsat->plugin_in_conflict) {
86,816✔
2035
    plugin_i = mcsat->plugin_in_conflict->ctx.plugin_id;
86,813✔
2036
    plugin = mcsat->plugins[plugin_i].plugin;
86,813✔
2037
  }
2038

2039
  if (trace_enabled(trace, "mcsat::conflict")) {
86,816✔
2040
    if (plugin_i != MCSAT_MAX_PLUGINS) {
×
2041
      mcsat_trace_printf(trace, "analyzing conflict from %s\n", mcsat->plugins[plugin_i].plugin_name);
×
2042
    } else {
2043
      mcsat_trace_printf(trace, "analyzing conflict from assertion\n");
×
2044
    }
2045
    mcsat_trace_printf(trace, "trail: ");
×
2046
    trail_print(mcsat->trail, trace->file);
×
2047
  }
2048

2049
  // Get the initial conflict
2050
  if (mcsat->variable_in_conflict != variable_null) {
86,816✔
2051
    // This conflict happened because an assumption conflicts with an already
2052
    // propagated value. We're unsat here, but we need to produce a clause
2053
    if (mcsat->ctx->mcsat_options.model_interpolation) {
11✔
2054
      if (plugin) {
5✔
2055
        term_t t = plugin->explain_propagation(plugin, mcsat->variable_in_conflict, &reason);
4✔
2056
        term_t x = variable_db_get_term(mcsat->var_db, mcsat->variable_in_conflict);
4✔
2057
        term_t x_eq_t = mk_eq(&mcsat->tm, x, t);
4✔
2058
        // reason => x_eq_t is valid
2059
        // reason && x_eq_t evaluates to false with assumptions
2060
        // but x_eq_t evaluates to true with trail
2061
        ivector_push(&reason, opposite_term(x_eq_t));
4✔
2062
        conflict_construct(&conflict, &reason, false, (mcsat_evaluator_interface_t*) &mcsat->evaluator, mcsat->var_db, mcsat->trail, &mcsat->tm, mcsat->ctx->trace);
4✔
2063
        mcsat->interpolant = mcsat_analyze_final(mcsat, &conflict);
4✔
2064
        conflict_destruct(&conflict);
4✔
2065
      } else {
2066
        // an assertion, interpolant is !assertion
2067
        mcsat->interpolant = variable_db_get_term(mcsat->var_db, mcsat->variable_in_conflict);
1✔
2068
        bool value = trail_get_boolean_value(mcsat->trail, mcsat->variable_in_conflict);
1✔
2069
        if (!value) {
1✔
2070
          mcsat->interpolant = opposite_term(mcsat->interpolant);
1✔
2071
        }
2072
      }
2073
    }
2074
    mcsat->status = STATUS_UNSAT;
11✔
2075
    mcsat->variable_in_conflict = variable_null;
11✔
2076
    delete_ivector(&reason);
11✔
2077
    return;
11✔
2078
  } else {
2079
    assert(plugin->get_conflict);
2080
    plugin->get_conflict(plugin, &reason);
86,805✔
2081
  }
2082

2083
  // Construct the conflict
2084
  conflict_construct(&conflict, &reason, true, (mcsat_evaluator_interface_t*) &mcsat->evaluator, mcsat->var_db, mcsat->trail, &mcsat->tm, mcsat->ctx->trace);
86,805✔
2085
  if (trace_enabled(trace, "mcsat::conflict::check")) {
86,805✔
2086
    // Don't check bool conflicts: they are implied by the formula (clauses)
2087
    if (plugin_i != mcsat->bool_plugin_id) {
×
2088
      conflict_check(&conflict);
×
2089
    }
2090
  }
2091
  statistic_avg_add(mcsat->solver_stats.avg_conflict_size, conflict.disjuncts.element_list.size);
86,805✔
2092

2093
  if (trace_enabled(trace, "mcsat::conflict") || trace_enabled(trace, "mcsat::lemma")) {
86,805✔
2094
    mcsat_trace_printf(trace, "conflict from %s\n", mcsat->plugins[plugin_i].plugin_name);
×
2095
    conflict_print(&conflict, trace->file);
×
2096
  }
2097

2098
  // Get the level of the conflict and backtrack to it
2099
  conflict_level = conflict_get_level(&conflict);
86,805✔
2100
  // Backtrack max(base, assumptions, conflict)
2101
  backtrack_level = mcsat_compute_backtrack_level(mcsat, conflict_level);
86,805✔
2102
  mcsat_backtrack_to(mcsat, backtrack_level);
86,805✔
2103

2104
  // Analyze while at least one variable at conflict level
2105
  while (true) {
2106

2107
    if (mcsat_conflict_with_assumptions(mcsat, conflict_level)) {
4,216,163✔
2108
      // Resolved below assumptions, we're done
2109
      break;
40✔
2110
    }
2111

2112
    if (conflict_level <= mcsat->trail->decision_level_base) {
4,216,123✔
2113
      // Resolved all the way
2114
      break;
34✔
2115
    }
2116

2117
    if (conflict_get_top_level_vars_count(&conflict) == 1) {
4,216,089✔
2118
      // UIP-like situation, we can quit as long as we make progress, as in
2119
      // the following cases:
2120
      //
2121
      // Assume finite basis B, with max{ term_size(t) | t in B } = M
2122
      //
2123
      // Termination based on weight(trail) = [..., weight(e), ...]
2124
      // - weight(propagation) = M + 1
2125
      // - weight(t -> d) = term_size(t)
2126
      //
2127
      // Max lex trail assuming finite basis:
2128
      // - [prop, ..., prop, decide variables/terms by term size]
2129
      //
2130
      // Termination, after we resolve, the weight goes up:
2131
      //
2132
      // Examples:
2133
      //   weight([b  , x -> T, y -> 0, (y + x < 0) -> 0]) =
2134
      //          [M+1, 1     , 1     , 5]
2135
      //
2136
      // [backjump-learn]
2137
      //   - Only one conflict literal contains the top variable.
2138
      //   * weight increases by replacing decision with propagation (M+1)
2139
      // [backjump-decide]
2140
      //   - More then one conflict literal contains the top variable.
2141
      //   - Top variable is decision t1 -> v
2142
      //   - Replace with decision t2 -> v where t2 is larger than t1
2143
      //   * weight increases by replacing decision with a heavier decision
2144
      ivector_t* conflict_top_vars = conflict_get_variables(&conflict);
92,751✔
2145
      assert(conflict_top_vars->size == 1);
2146
      variable_t top_var = conflict_top_vars->data[0];
92,751✔
2147
      if (trace_enabled(trace, "mcsat::conflict")) {
92,751✔
2148
        mcsat_trace_printf(trace, "potential UIP:\n");
×
2149
        variable_db_print_variable(mcsat->var_db, top_var, trace_out(trace));
×
2150
        mcsat_trace_printf(trace, "conflict:\n");
×
2151
        conflict_print(&conflict, trace->file);
×
2152
        mcsat_trace_printf(trace, "trail:\n");
×
2153
        trail_print(mcsat->trail, trace_out(trace));
×
2154
      }
2155
      // [backjump-learn]
2156
      uint32_t top_var_lits = conflict_get_literal_count_of(&conflict, top_var);
92,751✔
2157
      if (top_var_lits == 1) break;
92,751✔
2158
      // [backjump-decide]
2159
      assignment_type_t top_var_type = trail_get_assignment_type(mcsat->trail, top_var);
23,742✔
2160
      if (top_var_type == DECISION) {
23,742✔
2161
        // assert(variable_db_get_term(mcsat->var_db, top_var) < conflict_get_max_literal_of(&conflict, top_var));
2162
        decision_bound = variable_db_get_term(mcsat->var_db, top_var);
17,722✔
2163
        break;
17,722✔
2164
      }
2165
    }
2166

2167
    if (trace_enabled(trace, "mcsat::conflict")) {
4,129,358✔
2168
      mcsat_trace_printf(trace, "current trail:\n");
×
2169
      trail_print(mcsat->trail, trace->file);
×
2170
      mcsat_trace_printf(trace, "current conflict: ");
×
2171
      conflict_print(&conflict, trace->file);
×
2172
    }
2173

2174
    // Current variable
2175
    var = trail_back(mcsat->trail);
4,129,358✔
2176
    assert(trail_get_assignment_type(mcsat->trail, var) != DECISION);
2177

2178
    // Resolve if in the conflict and current level
2179
    if (conflict_contains(&conflict, var)) {
4,129,358✔
2180

2181
      // Get the plugin that performed the propagation
2182
      plugin_i = trail_get_source_id(mcsat->trail, var);
941,691✔
2183
      plugin = mcsat->plugins[plugin_i].plugin;
941,691✔
2184

2185
      if (trace_enabled(trace, "mcsat::conflict")) {
941,691✔
2186
        mcsat_trace_printf(trace, "resolving ");
×
2187
        variable_db_print_variable(mcsat->var_db, var, trace->file);
×
2188
        mcsat_trace_printf(trace, " with %s\n", mcsat->plugins[plugin_i].plugin_name);
×
2189
        mcsat_trace_printf(trace, "current conflict:\n");
×
2190
        conflict_print(&conflict, trace->file);
×
2191
      }
2192

2193
      // Resolve the variable
2194
      ivector_reset(&reason);
941,691✔
2195
      assert(plugin->explain_propagation);
2196
      substitution = plugin->explain_propagation(plugin, var, &reason);
941,691✔
2197
      if (trace_enabled(trace, "mcsat::propagation::check")) {
941,691✔
2198
        if (plugin_i != mcsat->bool_plugin_id) {
×
2199
          term_t var_term = variable_db_get_term(mcsat->var_db, var);
×
2200
          propagation_check(&reason, var_term, substitution);
×
2201
        } else {
2202
//          fprintf(stderr, "skipping propagation (bool)\n");
2203
        }
2204
      }
2205
      conflict_resolve_propagation(&conflict, var, substitution, &reason);
941,691✔
2206
      // The trail pops with the resolution step
2207
    } else {
2208
      // Have to pop the trail manually
2209
      trail_pop_propagation(mcsat->trail);
3,187,667✔
2210
      assert(!conflict_contains_as_top(&conflict, var));
2211
    }
2212

2213
    if (conflict_get_top_level_vars_count(&conflict) == 0) {
4,129,358✔
2214
      // We have resolved the conflict even lower
2215
      conflict_recompute_level_info(&conflict);
108✔
2216
      conflict_level = conflict_get_level(&conflict);
108✔
2217
      backtrack_level = mcsat_compute_backtrack_level(mcsat, conflict_level);
108✔
2218
      mcsat_backtrack_to(mcsat, backtrack_level);
108✔
2219
    }
2220
  }
2221

2222
  if (trace_enabled(trace, "mcsat::conflict")) {
86,805✔
2223
    mcsat_trace_printf(trace, "current conflict: ");
×
2224
    conflict_print(&conflict, trace->file);
×
2225
  }
2226

2227
  if (mcsat_conflict_with_assumptions(mcsat, conflict_level)) {
86,805✔
2228
    mcsat->status = STATUS_UNSAT;
40✔
2229
    if (mcsat->ctx->mcsat_options.model_interpolation) {
40✔
2230
      mcsat->interpolant = mcsat_analyze_final(mcsat, &conflict);
30✔
2231
    }
2232
    mcsat->assumptions_decided_level = -1;
40✔
2233
    mcsat_backtrack_to(mcsat, mcsat->trail->decision_level_base);
40✔
2234
  } else if (conflict_level <= mcsat->trail->decision_level_base) {
86,765✔
2235
    mcsat->status = STATUS_UNSAT;
34✔
2236
  } else {
2237
    assert(conflict_get_top_level_vars_count(&conflict) == 1);
2238
    // We should still be in conflict, so back out
2239
    assert(conflict.level == mcsat->trail->decision_level);
2240
    mcsat_backtrack_to(mcsat, mcsat->trail->decision_level - 1);
86,731✔
2241

2242
    // Get the literals
2243
    conflict_disjuncts = conflict_get_literals(&conflict);
86,731✔
2244

2245
    if (trace_enabled(trace, "mcsat::conflict")) {
86,731✔
2246
      mcsat_trace_printf(trace, "conflict_disjuncts:\n");
×
2247
      uint32_t i;
2248
      for (i = 0; i < conflict_disjuncts->size; ++i) {
×
2249
        mcsat_trace_printf(trace, "[%u]: ", i);
×
2250
        trace_term_ln(trace, mcsat->ctx->terms, conflict_disjuncts->data[i]);
×
2251
      }
2252
    }
2253

2254
    // Now add the lemma
2255
    mcsat_add_lemma(mcsat, conflict_disjuncts, decision_bound);
86,731✔
2256

2257
    // Use resources based on conflict size
2258
    *restart_resource += mcsat_get_lemma_weight(mcsat, conflict_disjuncts,
86,731✔
2259
        mcsat->heuristic_params.lemma_restart_weight_type);
2260

2261
    // Bump the variables
2262
    mcsat_bump_variables_mset(mcsat, conflict_get_variables_all(&conflict));
86,731✔
2263

2264
    if (trace_enabled(trace, "mcsat::conflict::trail")) {
86,731✔
2265
      mcsat_trace_printf(trace, "trail: ");
×
2266
      trail_print(mcsat->trail, trace->file);
×
2267
    }
2268
  }
2269

2270
  delete_ivector(&reason);
86,805✔
2271
  conflict_destruct(&conflict);
86,805✔
2272
}
2273

2274
static
2275
bool mcsat_decide_assumption(mcsat_solver_t* mcsat, model_t* mdl, uint32_t n_assumptions, const term_t assumptions[]) {
661,564✔
2276
  assert(!mcsat->trail->inconsistent);
2277

2278
  variable_t var;
2279
  term_t var_term;
2280
  mcsat_value_t var_mdl_value;
2281

2282
  uint32_t plugin_i;
2283
  plugin_t* plugin;
2284

2285
  plugin_trail_token_t decision_token;
2286

2287
  bool assumption_decided = false;
661,564✔
2288
  for (; !assumption_decided && mcsat->assumption_i < n_assumptions; mcsat->assumption_i ++) {
661,733✔
2289

2290
    // Break if any conflicts
2291
    if (mcsat->trail->inconsistent) {
170✔
2292
      break;
×
2293
    }
2294
    if (mcsat->variable_in_conflict != variable_null) {
170✔
2295
      break;
1✔
2296
    }
2297

2298
    // The variable (should exist already)
2299
    var_term = assumptions[mcsat->assumption_i];
169✔
2300
    var = variable_db_get_variable_if_exists(mcsat->var_db, var_term);
169✔
2301
    assert(var != variable_null);
2302
    // Get the owner that will 'decide' the value of the variable
2303
    plugin_i = mcsat->decision_makers[variable_db_get_type_kind(mcsat->var_db, var)];
169✔
2304
    assert(plugin_i != MCSAT_MAX_PLUGINS);
2305
    // The given value the variable in the provided model
2306
    value_t value = model_get_term_value(mdl, var_term);
169✔
2307
    mcsat_value_construct_from_value(&var_mdl_value, &mdl->vtbl, value);
169✔
2308

2309
    if (trace_enabled(mcsat->ctx->trace, "mcsat::decide")) {
169✔
2310
      mcsat_trace_printf(mcsat->ctx->trace, "mcsat_decide_assumption(): with %s\n", mcsat->plugins[plugin_i].plugin_name);
×
2311
      mcsat_trace_printf(mcsat->ctx->trace, "mcsat_decide_assumption(): variable ");
×
2312
      variable_db_print_variable(mcsat->var_db, var, trace_out(mcsat->ctx->trace));
×
2313
      mcsat_trace_printf(mcsat->ctx->trace, "\n");
×
2314
    }
2315

2316
    // If the variable already has a value in the trail check for consistency
2317
    if (trail_has_value(mcsat->trail, var)) {
169✔
2318
      // If the value is different from given value, we are in conflict
2319
      assert(trail_get_assignment_type(mcsat->trail, var) == PROPAGATION);
2320
      const mcsat_value_t* var_trail_value = trail_get_value(mcsat->trail, var);
11✔
2321
      bool eq = mcsat_value_eq(&var_mdl_value, var_trail_value);
11✔
2322
      if (!eq) {
11✔
2323
        // Who propagated the value (MCSAT_MAX_PLUGINS if an assertion)
2324
        plugin_i = trail_get_source_id(mcsat->trail, var);
11✔
2325
        if (plugin_i == MCSAT_MAX_PLUGINS) {
11✔
2326
          mcsat->plugin_in_conflict = NULL;
3✔
2327
        } else {
2328
          mcsat->plugin_in_conflict = mcsat->plugins[plugin_i].plugin_ctx;
8✔
2329
        }
2330
        mcsat->variable_in_conflict = var;
11✔
2331
      }
2332
    } else {
2333
      // Plugin used to check/decide
2334
      plugin = mcsat->plugins[plugin_i].plugin;
158✔
2335
      // Check if the decision is consistent (will report conflict if not)
2336
      if (!mcsat->trail->inconsistent) {
158✔
2337
        // Construct the token
2338
        trail_token_construct(&decision_token, mcsat->plugins[plugin_i].plugin_ctx, var);
158✔
2339
        // Decide with the owner plugin
2340
        mcsat_push_internal(mcsat);
158✔
2341
        assert(plugin->decide_assignment);
2342
        plugin->decide_assignment(plugin, var, &var_mdl_value, (trail_token_t*) &decision_token);
158✔
2343

2344
        // If decided, we're done
2345
        assert(decision_token.used);
2346
        if (trace_enabled(mcsat->ctx->trace, "mcsat::decide")) {
158✔
2347
          FILE* out = trace_out(mcsat->ctx->trace);
×
2348
          fprintf(out, "mcsat_decide_assumption(): value = ");
×
2349
          mcsat_value_print(trail_get_value(mcsat->trail, var), out);
×
2350
          fprintf(out, "\n");
×
2351
        }
2352
        // We've decided something!
2353
        assumption_decided = true;
158✔
2354
        mcsat->assumptions_decided_level = mcsat->trail->decision_level;
158✔
2355
      }
2356
    }
2357

2358
    // Remove temp
2359
    mcsat_value_destruct(&var_mdl_value);
169✔
2360
  }
2361

2362
  return assumption_decided;
661,564✔
2363
}
2364

2365
/**
2366
 * Finds the correct plugin for var and asks it to make a decision.
2367
 * Returns true if a decision was made on var.
2368
 */
2369
static
2370
bool mcsat_decide_var(mcsat_solver_t* mcsat, variable_t var, bool force_decision) {
660,617✔
2371
  // must be a valid variable that is not yet decided upon
2372
  assert(var != variable_null);
2373
  assert(!trail_has_value(mcsat->trail, var));
2374

2375
  uint32_t i;
2376
  plugin_t* plugin;
2377
  plugin_trail_token_t decision_token;
2378
  bool made_decision = false;
660,617✔
2379

2380
  // Get the owner that will decide that value of the variable
2381
  i = mcsat->decision_makers[variable_db_get_type_kind(mcsat->var_db, var)];
660,617✔
2382
  assert(i != MCSAT_MAX_PLUGINS);
2383
  // Construct the token
2384
  trail_token_construct(&decision_token, mcsat->plugins[i].plugin_ctx, var);
660,617✔
2385
  // Decide
2386
  if (trace_enabled(mcsat->ctx->trace, "mcsat::decide")) {
660,617✔
2387
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_decide(): with %s\n", mcsat->plugins[i].plugin_name);
×
2388
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_decide(): variable ");
×
2389
    variable_db_print_variable(mcsat->var_db, var, trace_out(mcsat->ctx->trace));
×
2390
    mcsat_trace_printf(mcsat->ctx->trace, "\n");
×
2391
  }
2392
  plugin = mcsat->plugins[i].plugin;
660,617✔
2393

2394
  // Ask the owner to decide
2395
  mcsat_push_internal(mcsat);
660,617✔
2396
  assert(plugin->decide);
2397
  plugin->decide(plugin, var, (trail_token_t*) &decision_token, force_decision);
660,617✔
2398

2399
  if (decision_token.used == 0) {
660,617✔
2400
    // If not decided, remember and go on
2401
    made_decision = false;
1✔
2402
    mcsat_pop_internal(mcsat);
1✔
2403
  } else {
2404
    made_decision = true;
660,616✔
2405
    // Decided, we can continue with the search
2406
    (*mcsat->solver_stats.decisions)++;
660,616✔
2407
    // Plugins are not allowed to cheat and decide on another variable
2408
    assert(trail_has_value(mcsat->trail, var));
2409
    if (trace_enabled(mcsat->ctx->trace, "mcsat::decide")) {
660,616✔
2410
      FILE* out = trace_out(mcsat->ctx->trace);
×
2411
      fprintf(out, "mcsat_decide(): value = ");
×
2412
      mcsat_value_print(trail_get_value(mcsat->trail, var), out);
×
2413
      fprintf(out, "\n");
×
2414
    }
2415
  }
2416

2417
  // a forced decision implies a made decision
2418
  assert(!force_decision || made_decision);
2419
  return made_decision;
660,617✔
2420
}
2421

2422
/**
2423
 * Decides a variable using one of the plugins. Returns true if a variable
2424
 * has been decided, or a conflict detected.
2425
 */
2426
static
2427
bool mcsat_decide(mcsat_solver_t* mcsat) {
661,395✔
2428

2429
  assert(!mcsat->trail->inconsistent);
2430

2431
  ivector_t skipped_variables; // Variables we took from the queue but plugin didn't decide
2432
  init_ivector(&skipped_variables, 0);
661,395✔
2433

2434
  variable_t var;
2435
  bool aux_choice; // indicates that var was not taken from the queue
2436
  bool force_decision = false;
661,395✔
2437
  double rand_freq = mcsat->heuristic_params.random_decision_freq;
661,395✔
2438

2439
  while (true) {
2440
    var = variable_null;
661,397✔
2441
    aux_choice = true;
661,397✔
2442

2443
    // Use the top variables first
2444
    for (uint32_t i = 0; i < mcsat->top_decision_vars.size; ++i) {
662,436✔
2445
      var = mcsat->top_decision_vars.data[i];
1,116✔
2446
      assert(var != variable_null);
2447
      if (!trail_has_value(mcsat->trail, var)) {
1,116✔
2448
        force_decision = true;
77✔
2449
        break;
77✔
2450
      }
2451
      var = variable_null;
1,039✔
2452
    }
2453

2454
    // If there is a fixed order that was passed in, try that
2455
    if (var == variable_null) {
661,397✔
2456
      const ivector_t* order = &mcsat->ctx->mcsat_var_order;
661,320✔
2457
      if (order->size > 0) {
661,320✔
2458
        if (trace_enabled(mcsat->ctx->trace, "mcsat::decide")) {
13✔
2459
          FILE* out = trace_out(mcsat->ctx->trace);
×
2460
          fprintf(out, "mcsat_decide(): var_order is ");
×
2461
          for (uint32_t i = 0; i < order->size; ++ i) {
×
2462
            term_print_to_file(out, mcsat->ctx->terms, order->data[i]);
×
2463
            fprintf(out, " ");
×
2464
          }
2465
          fprintf(out, "\n");
×
2466
        }
2467
        for (uint32_t i = 0; var == variable_null && i < order->size; ++i) {
35✔
2468
          term_t ovar_term = order->data[i];
22✔
2469
          variable_t ovar = variable_db_get_variable_if_exists(mcsat->var_db, ovar_term);
22✔
2470
          if (ovar == variable_null) continue; // Some variables are not used
22✔
2471
          if (!trail_has_value(mcsat->trail, ovar)) {
22✔
2472
            var = ovar;
11✔
2473
            force_decision = true;
11✔
2474
          }
2475
        }
2476
      }
2477
    }
2478

2479
    // then try the variables a plugin requested
2480
    if (var == variable_null) {
661,397✔
2481
      while (!int_queue_is_empty(&mcsat->hinted_decision_vars)) {
670,977✔
2482
        var = int_queue_pop(&mcsat->hinted_decision_vars);
69,991✔
2483
        assert(var != variable_null);
2484
        if (!trail_has_value(mcsat->trail, var)) {
69,991✔
2485
          force_decision = true;
60,323✔
2486
          break;
60,323✔
2487
        }
2488
        var = variable_null;
9,668✔
2489
      }
2490
    }
2491

2492
    // Random decision
2493
    if (var == variable_null && rand_freq > 0.0) {
661,397✔
2494
      double* seed = &mcsat->heuristic_params.random_decision_seed;
600,986✔
2495
      if (drand(seed) < rand_freq && !var_queue_is_empty(&mcsat->var_queue)) {
600,986✔
2496
        var = var_queue_random(&mcsat->var_queue, seed);
11,116✔
2497
        if (trail_has_value(mcsat->trail, var)) {
11,116✔
2498
          var = variable_null;
3,709✔
2499
        }
2500
      }
2501
    }
2502

2503
    if (var == variable_null) {
661,397✔
2504
      // No auxiliary choice performed
2505
      aux_choice = false;
593,579✔
2506
    }
2507

2508
    // Use the queue
2509
    while (!var_queue_is_empty(&mcsat->var_queue) && var == variable_null) {
2,569,614✔
2510
      // Get the next variable from the queue
2511
      var = var_queue_pop(&mcsat->var_queue);
1,246,820✔
2512
      // If already assigned go on
2513
      if (trail_has_value(mcsat->trail, var)) {
1,246,820✔
2514
        if (trace_enabled(mcsat->ctx->trace, "mcsat::decide")) {
654,021✔
2515
          FILE *out = trace_out(mcsat->ctx->trace);
×
2516
          fprintf(out, "mcsat_decide(): skipping ");
×
2517
          variable_db_print_variable(mcsat->var_db, var, out);
×
2518
          fprintf(out, "\n");
×
2519
        }
2520
        var = variable_null;
654,021✔
2521
        continue;
654,021✔
2522
      }
2523
    }
2524

2525
    if (var != variable_null) {
661,397✔
2526
      bool made_decision = mcsat_decide_var(mcsat, var, force_decision);
660,617✔
2527
      if (made_decision) {
660,617✔
2528
        break;
660,616✔
2529
      } else if (!aux_choice) {
1✔
2530
        ivector_push(&skipped_variables, var);
1✔
2531
      }
2532
    } else {
2533
      assert(!aux_choice);
2534
      // No variables left to decide
2535
      if (skipped_variables.size == 0) {
780✔
2536
        // Didn't skip any, we're done
2537
        break;
779✔
2538
      } else {
2539
        // Put the skipped back in the queue, and continue but force next decision
2540
        for (uint32_t i = 0; i < skipped_variables.size; ++ i) {
2✔
2541
          var_queue_insert(&mcsat->var_queue, skipped_variables.data[i]);
1✔
2542
        }
2543
        ivector_reset(&skipped_variables);
1✔
2544
        force_decision = true;
1✔
2545
      }
2546
    }
2547
  }
2548

2549
  // Put any skipped variables back into the queue
2550
  if (skipped_variables.size > 0) {
661,395✔
2551
    // If we skipped some, we had to decided one, we put the skipped scores to
2552
    // the decided score
2553
    assert(var != variable_null);
2554
    double var_score = var_queue_get_activity(&mcsat->var_queue, var);
×
2555
    for (uint32_t i = 0; i < skipped_variables.size; ++ i) {
×
2556
      variable_t skipped_var = skipped_variables.data[i];
×
2557
      var_queue_set_activity(&mcsat->var_queue, skipped_var, var_score);
×
2558
      var_queue_insert(&mcsat->var_queue, skipped_var);
×
2559
    }
2560
  }
2561

2562
  delete_ivector(&skipped_variables);
661,395✔
2563

2564
  return var != variable_null;
661,395✔
2565
}
2566

2567
typedef struct {
2568
  uint32_t u, v;
2569
  uint32_t restart_threshold;
2570
  uint32_t interval;
2571
} luby_t;
2572

2573
static inline
2574
void luby_init(luby_t* luby, uint32_t interval) {
965✔
2575
  luby->u = 1;
965✔
2576
  luby->v = 1;
965✔
2577
  luby->restart_threshold = interval;
965✔
2578
  luby->interval = interval;
965✔
2579
}
965✔
2580

2581
static inline
2582
void luby_next(luby_t* luby) {
17,409✔
2583
  if ((luby->u & -luby->u) == luby->v) {
17,409✔
2584
    luby->u ++;
8,816✔
2585
    luby->v = 1;
8,816✔
2586
  } else {
2587
    luby->v <<= 1;
8,593✔
2588
  }
2589
  luby->restart_threshold = luby->v * luby->interval;
17,409✔
2590
}
17,409✔
2591

2592
static
2593
void mcsat_check_model(mcsat_solver_t* mcsat, bool assert) {
×
2594
  // Check models
2595
  model_t model;
2596
  init_model(&model, mcsat->terms, true);
×
2597
  mcsat_build_model(mcsat, &model);
×
2598
  uint32_t i = 0;
×
2599
  for (i = 0; i < mcsat->assertion_terms_original.size; ++i) {
×
2600
    term_t assertion = mcsat->assertion_terms_original.data[i];
×
2601
    int32_t code = 0;
×
2602
    bool assertion_is_true = formula_holds_in_model(&model, assertion, &code);
×
2603
    if (false && !assertion_is_true) {
2604
      FILE *out = trace_out(mcsat->ctx->trace);
2605
      fprintf(out, "Assertion not true in model: ");
2606
      trace_term_ln(mcsat->ctx->trace, mcsat->terms, assertion);
2607
      fprintf(out, "In model:\n");
2608
      model_print(out, &model);
2609
    }
2610
    assert(!assert || assertion_is_true);
2611
  }
2612
  delete_model(&model);
×
2613
}
×
2614

2615
static
2616
void mcsat_assert_formulas_internal(mcsat_solver_t* mcsat, uint32_t n, const term_t *f, bool preprocess);
2617

2618
void mcsat_set_model_hint(mcsat_solver_t* mcsat, model_t* mdl, uint32_t n_mdl_filter,
×
2619
                          const term_t mdl_filter[]) {
2620
  if (n_mdl_filter == 0) {
×
2621
    return;
×
2622
  }
2623

2624
  assert(mdl != NULL);
2625
  assert(mdl_filter != NULL);
2626

2627
  value_table_t* vtbl = model_get_vtbl(mdl);
×
2628

2629
  mcsat_push(mcsat);
×
2630

2631
  uint32_t i;
2632
  for (i = 0; i < n_mdl_filter; ++i) {
×
2633
    term_t x = mdl_filter[i];
×
2634
    assert(term_kind(mcsat->terms, x) == UNINTERPRETED_TERM || term_kind(mcsat->terms, x) == VARIABLE);
2635
    assert(is_pos_term(x));
2636

2637
    variable_t x_var = variable_db_get_variable(mcsat->var_db, unsigned_term(x));
×
2638
    if (trail_has_value(mcsat->trail, x_var)) {
×
2639
      continue;
×
2640
    }
2641

2642
    uint32_t plugin_i = mcsat->decision_makers[variable_db_get_type_kind(mcsat->var_db, x_var)];
×
2643
    value_t x_value = model_get_term_value(mdl, x);
×
2644
    mcsat_value_t value;
2645
    mcsat_value_construct_from_value(&value, vtbl, x_value);
×
2646
    assert(x_value >= 0);
2647
    trail_add_propagation(mcsat->trail, x_var, &value, plugin_i, mcsat->trail->decision_level);
×
2648
    mcsat_value_destruct(&value);
×
2649
    mcsat_process_registration_queue(mcsat);
×
2650
  }
2651

2652
  mcsat_pop(mcsat);
×
2653
}
2654

2655
static
2656
void mcsat_set_initial_var_order(mcsat_solver_t* mcsat) {
965✔
2657
  const ivector_t* vars = &mcsat->ctx->mcsat_initial_var_order;
965✔
2658
  uint32_t n = vars->size;
965✔
2659
  if (n == 0) {
965✔
2660
    return;
965✔
2661
  }
2662

2663
  assert(vars != NULL);
2664

2665
  uint32_t i;
2666
  for (i = 0; i < n; ++i) {
×
2667
    term_t x = vars->data[i];
×
2668
    assert(term_kind(mcsat->terms, x) == UNINTERPRETED_TERM || term_kind(mcsat->terms, x) == VARIABLE);
2669
    variable_t v = variable_db_get_variable(mcsat->var_db, unsigned_term(x));
×
2670
    int_queue_push(&mcsat->hinted_decision_vars, v);
×
2671
    mcsat_process_registration_queue(mcsat);
×
2672
  }
2673
}
2674

2675
void mcsat_solve(mcsat_solver_t* mcsat, const param_t *params, model_t* mdl, uint32_t n_assumptions, const term_t assumptions[]) {
1,187✔
2676

2677
  uint32_t restart_resource;
2678
  luby_t luby;
2679

2680
  // Make sure we have variables for all the assumptions
2681
  if (n_assumptions > 0) {
1,187✔
2682
    if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
126✔
2683
      mcsat_trace_printf(mcsat->ctx->trace, "solving with assumptions\n");
×
2684
    }
2685
    assert(mcsat->assumption_vars.size == 0);
2686
    uint32_t i;
2687
    for (i = 0; i < n_assumptions; ++ i) {
1,223✔
2688
      // Apply the pre-processor. If the variable is substituted, we
2689
      // need to add the equality x = t
2690
      term_t x = assumptions[i];
1,097✔
2691
      assert(term_kind(mcsat->terms, x) == UNINTERPRETED_TERM || term_kind(mcsat->terms, x) == VARIABLE);
2692
      assert(is_pos_term(x));
2693
      term_t x_pre = preprocessor_apply(&mcsat->preprocessor, x, NULL, true);
1,097✔
2694
      if (x != x_pre) {
1,097✔
2695
        // Assert x = t although we solved it already :(
2696
        term_t eq = mk_eq(&mcsat->tm, x, x_pre);
4✔
2697
        mcsat_assert_formulas_internal(mcsat, 1, &eq, false);
4✔
2698
      }
2699
      // Make sure the variable is registered (maybe it doesn't appear in assertions)
2700
      variable_t x_var = variable_db_get_variable(mcsat->var_db, unsigned_term(x));
1,097✔
2701
      ivector_push(&mcsat->assumption_vars, x_var);
1,097✔
2702
      mcsat_process_registration_queue(mcsat);
1,097✔
2703
    }
2704
  }
2705

2706
  // Initialize assumption info
2707
  mcsat->interpolant = NULL_TERM;
1,187✔
2708
  mcsat->variable_in_conflict = variable_null;
1,187✔
2709
  mcsat->assumption_i = 0;
1,187✔
2710
  mcsat->assumptions_decided_level = -1;
1,187✔
2711
  mcsat->assumptions_model = mdl;
1,187✔
2712

2713
  // Start the search
2714
  mcsat->status = STATUS_SEARCHING;
1,187✔
2715

2716
  // If we're already unsat, just return
2717
  if (!mcsat_is_consistent(mcsat)) {
1,187✔
2718
    mcsat->interpolant = false_term;
222✔
2719
    mcsat->status = STATUS_UNSAT;
222✔
2720
    assert(int_queue_is_empty(&mcsat->registration_queue));
2721
    goto solve_done;
222✔
2722
  }
2723

2724
  if (trace_enabled(mcsat->ctx->trace, "mcsat::solve")) {
965✔
2725
    static int count = 0;
2726
    mcsat_trace_printf(mcsat->ctx->trace, "solve %d\n", count ++);
×
2727
  }
2728

2729
  // Remember existing terms
2730
  mcsat->terms_size_on_solver_entry = nterms(mcsat->terms);
965✔
2731

2732
  // Initialize for search
2733
  mcsat_heuristics_init(mcsat);
965✔
2734
  mcsat_notify_plugins(mcsat, MCSAT_SOLVER_START);
965✔
2735

2736
  // set initial variable order
2737
  mcsat_set_initial_var_order(mcsat);
965✔
2738

2739
  // Initialize the Luby sequence with interval 10
2740
  restart_resource = 0;
965✔
2741
  luby_init(&luby, mcsat->heuristic_params.restart_interval);
965✔
2742

2743
  // Whether to run learning
2744
  bool learning = true;
965✔
2745

2746
  while (!mcsat->stop_search) {
748,470✔
2747

2748
    // Do we restart
2749
    if (mcsat_is_consistent(mcsat) && restart_resource > luby.restart_threshold) {
748,470✔
2750
      restart_resource = 0;
17,409✔
2751
      luby_next(&luby);
17,409✔
2752
      mcsat_request_restart(mcsat);
17,409✔
2753
    }
2754

2755
    // Process any outstanding requests
2756
    mcsat_process_requests(mcsat);
748,470✔
2757

2758
    // Do propagation
2759
    mcsat_propagate(mcsat, learning);
748,470✔
2760
    learning = false;
748,470✔
2761

2762
    // If inconsistent, analyze the conflict
2763
    if (!mcsat_is_consistent(mcsat)) {
748,470✔
2764
      goto conflict;
86,906✔
2765
    }
2766

2767
    // If any requests, process them and go again
2768
    if (mcsat->pending_requests) {
661,564✔
2769
      continue;
×
2770
    }
2771

2772
    // Should we decide on an assumption
2773
    bool assumption_decided = mcsat_decide_assumption(mcsat, mdl, n_assumptions, assumptions);
661,564✔
2774
    if (assumption_decided) {
661,564✔
2775
      continue;
158✔
2776
    }
2777

2778
    // If inconsistent, analyze the conflict
2779
    if (!mcsat_is_consistent(mcsat)) {
661,406✔
2780
      goto conflict;
11✔
2781
    }
2782

2783
    // Time to make a decision
2784
    bool variable_decided = mcsat_decide(mcsat);
661,395✔
2785

2786
    // Decision made, continue with the search
2787
    if (variable_decided) {
661,395✔
2788
      continue;
660,616✔
2789
    }
2790

2791
    // If inconsistent, analyze the conflict
2792
    if (!mcsat_is_consistent(mcsat)) {
779✔
2793
      goto conflict;
×
2794
    }
2795

2796
    // Nothing to decide, we're satisfiable
2797
    mcsat->status = STATUS_SAT;
779✔
2798
    if (trace_enabled(mcsat->ctx->trace, "mcsat::model::check")) {
779✔
2799
      mcsat_check_model(mcsat, true);
×
2800
    }
2801

2802
    break;
779✔
2803

2804
  conflict:
86,917✔
2805

2806
    (*mcsat->solver_stats.conflicts)++;
86,917✔
2807
    mcsat_notify_plugins(mcsat, MCSAT_SOLVER_CONFLICT);
86,917✔
2808

2809
    // If at level 0 we're unsat
2810
    if (n_assumptions == 0 && trail_is_at_base_level(mcsat->trail)) {
86,917✔
2811
      mcsat->interpolant = false_term;
101✔
2812
      mcsat->status = STATUS_UNSAT;
101✔
2813
      break;
101✔
2814
    }
2815

2816
    // Analyze the conflicts
2817
    mcsat_analyze_conflicts(mcsat, &restart_resource);
86,816✔
2818

2819
    // Analysis might have discovered base level conflict
2820
    if (mcsat->status == STATUS_UNSAT) {
86,816✔
2821
      if (n_assumptions == 0) {
85✔
2822
        mcsat->interpolant = false_term;
34✔
2823
      }
2824
      break;
85✔
2825
    }
2826

2827
    // update the variable selection heuristic
2828
    var_queue_decay_activities(&mcsat->var_queue);
86,731✔
2829
  }
2830

2831
  if (mcsat->stop_search) {
965✔
2832
    if (mcsat->status == STATUS_SEARCHING) {
×
2833
      mcsat->status = YICES_STATUS_INTERRUPTED;
×
2834
    }
2835
    mcsat->stop_search = false;
×
2836
  }
2837

2838
  // Make sure any additional terms are registered
2839
  mcsat_process_registration_queue(mcsat);
965✔
2840

2841
solve_done:
1,187✔
2842

2843
  ivector_reset(&mcsat->assumption_vars);
1,187✔
2844
}
1,187✔
2845

2846
void mcsat_set_tracer(mcsat_solver_t* mcsat, tracer_t* tracer) {
282✔
2847
  uint32_t i;
2848
  mcsat_plugin_context_t* ctx;
2849

2850
  // Update the contexts with the new tracer
2851
  variable_db_set_tracer(mcsat->var_db, tracer);
282✔
2852
  for (i = 0; i < mcsat->plugins_count; ++ i) {
1,974✔
2853
    ctx = mcsat->plugins[i].plugin_ctx;
1,692✔
2854
    ctx->ctx.tracer = tracer;
1,692✔
2855
  }
2856

2857
  // Set the trace for the preprocessor
2858
  preprocessor_set_tracer(&mcsat->preprocessor, tracer);
282✔
2859
}
282✔
2860

2861

2862
void mcsat_flush_lemmas(mcsat_solver_t* mcsat, ivector_t* out) {
79,669✔
2863
  // Flush regular lemmas
2864
  ivector_add(out, mcsat->plugin_lemmas.data, mcsat->plugin_lemmas.size);
79,669✔
2865
  ivector_reset(&mcsat->plugin_lemmas);
79,669✔
2866

2867
  // Copy definition lemmas
2868
  uint32_t i = mcsat->plugin_definition_lemmas_i;
79,669✔
2869
  for (; i < mcsat->plugin_definition_lemmas.size; ++ i) {
81,280✔
2870
    ivector_push(out, mcsat->plugin_definition_lemmas.data[i]);
1,611✔
2871
  }
2872
  mcsat->plugin_definition_lemmas_i = mcsat->plugin_definition_lemmas.size;
79,669✔
2873
}
79,669✔
2874

2875
static
2876
void mcsat_assert_formulas_internal(mcsat_solver_t* mcsat, uint32_t n, const term_t *f, bool preprocess) {
2,253✔
2877
  uint32_t i;
2878

2879
  // Remember the original assertions
2880
  for (i = 0; i < n; ++ i) {
39,553✔
2881
    ivector_push(&mcsat->assertion_terms_original, f[i]);
37,300✔
2882
  }
2883

2884
  // Add any leftover lemmas
2885
  ivector_t* assertions = &mcsat->assertions_tmp;
2,253✔
2886
  ivector_reset(assertions);
2,253✔
2887
  mcsat_flush_lemmas(mcsat, assertions);
2,253✔
2888

2889
  // Preprocess the formulas (preprocessor might throw)
2890
  ivector_add(assertions, f, n);
2,253✔
2891

2892
  // Preprocess the formulas (preprocessor might throw)
2893
  if (preprocess) {
2,253✔
2894
    for (i = 0; i < assertions->size; ++ i) {
40,519✔
2895
      term_t f = assertions->data[i];
38,271✔
2896
      term_t f_pre = preprocessor_apply(&mcsat->preprocessor, f, assertions, true);
38,271✔
2897
      assertions->data[i] = f_pre;
38,270✔
2898
    }
2899
  }
2900

2901
  // Assert individual formulas
2902
  for (i = 0; i < assertions->size; ++ i) {
79,668✔
2903
    // Assert it
2904
    mcsat_assert_formula(mcsat, assertions->data[i]);
77,416✔
2905
    // Add any lemmas that were added
2906
    mcsat_flush_lemmas(mcsat, assertions);
77,416✔
2907
  }
2908

2909
  // Delete the temp
2910
  ivector_reset(assertions);
2,252✔
2911
}
2,252✔
2912

2913
int32_t mcsat_assert_formulas(mcsat_solver_t* mcsat, uint32_t n, const term_t *f) {
2,249✔
2914
  mcsat_assert_formulas_internal(mcsat, n, f, true);
2,249✔
2915
  mcsat->interpolant = NULL_TERM;
2,248✔
2916
  return CTX_NO_ERROR;
2,248✔
2917
}
2918

2919
void mcsat_show_stats(mcsat_solver_t* mcsat, FILE* out) {
×
2920
  int fd = fileno(out);
×
2921
  assert(fd >= 0);
2922
  statistics_print(&mcsat->stats, fd);
×
2923
}
×
2924

2925
void mcsat_show_stats_fd(mcsat_solver_t* mcsat, int out) {
×
2926
  statistics_print(&mcsat->stats, out);
×
2927
}
×
2928

2929
void mcsat_build_model(mcsat_solver_t* mcsat, model_t* model) {
23✔
2930

2931
  value_table_t* vtbl = model_get_vtbl(model);
23✔
2932

2933
  if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
23✔
2934
    mcsat_trace_printf(mcsat->ctx->trace, "mcsat_build_model()\n");
×
2935
    trail_print(mcsat->trail, trace_out(mcsat->ctx->trace));
×
2936
  }
2937

2938
  // Just copy the trail into the model
2939
  uint32_t i;
2940
  ivector_t* trail_elements = &mcsat->trail->elements;
23✔
2941
  for (i = 0; i < trail_elements->size; ++ i) {
283✔
2942
    variable_t x = trail_elements->data[i];
260✔
2943
    term_t x_term = variable_db_get_term(mcsat->var_db, x);
260✔
2944
    term_kind_t x_kind = term_kind(mcsat->terms, x_term);
260✔
2945

2946
    if (x_kind == UNINTERPRETED_TERM &&
319✔
2947
        term_type_kind(mcsat->terms, x_term) != FUNCTION_TYPE) {
59✔
2948

2949
      if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
50✔
2950
        mcsat_trace_printf(mcsat->ctx->trace, "var = ");
×
2951
        trace_term_ln(mcsat->ctx->trace, mcsat->terms, x_term);
×
2952
      }
2953

2954
      // Type of the variable
2955
      type_t x_type = term_type(mcsat->terms, x_term);
50✔
2956

2957
      // Get mcsat value (have to case to remove const because yices api doesn't care for const)
2958
      mcsat_value_t* x_value_mcsat = (mcsat_value_t*) trail_get_value(mcsat->trail, x);
50✔
2959

2960
      if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
50✔
2961
        mcsat_trace_printf(mcsat->ctx->trace, "value = ");
×
2962
        mcsat_value_print(x_value_mcsat, trace_out(mcsat->ctx->trace));
×
2963
        mcsat_trace_printf(mcsat->ctx->trace, "\n");
×
2964
      }
2965

2966
      // Set up the yices value
2967
      value_t x_value = mcsat_value_to_value(x_value_mcsat, mcsat->types, x_type, vtbl);
50✔
2968

2969
      if (trace_enabled(mcsat->ctx->trace, "mcsat")) {
50✔
2970
        mcsat_trace_printf(mcsat->ctx->trace, "value = ");
×
2971
        vtbl_print_object(trace_out(mcsat->ctx->trace), vtbl, x_value);
×
2972
        mcsat_trace_printf(mcsat->ctx->trace, "\n");
×
2973
      }
2974

2975
      // Add to model
2976
      model_map_term(model, x_term, x_value);
50✔
2977
    }
2978
  }
2979

2980
  // Let the plugins run add to the model (e.g. UF, division, ...)
2981
  for (i = 0; i < mcsat->plugins_count; ++ i) {
161✔
2982
    plugin_t* plugin = mcsat->plugins[i].plugin;
138✔
2983
    if (plugin->build_model) {
138✔
2984
      plugin->build_model(plugin, model);
23✔
2985
    }
2986
  }
2987

2988
  // Let the preprocessor add to the model
2989
  preprocessor_build_model(&mcsat->preprocessor, model);
23✔
2990
}
23✔
2991

2992
void mcsat_set_exception_handler(mcsat_solver_t* mcsat, jmp_buf* handler) {
×
2993
  uint32_t i;
2994
  mcsat->exception = handler;
×
2995
  preprocessor_set_exception_handler(&mcsat->preprocessor, handler);
×
2996
  for (i = 0; i < mcsat->plugins_count; ++ i) {
×
2997
    plugin_t* plugin = mcsat->plugins[i].plugin;
×
2998
    plugin->set_exception_handler(plugin, handler);
×
2999
  }
3000
}
×
3001

3002
void mcsat_gc_mark(mcsat_solver_t* mcsat) {
6✔
3003
  mcsat_clear(mcsat);
6✔
3004
  mcsat_gc(mcsat, true);
6✔
3005
}
6✔
3006

3007
void mcsat_stop_search(mcsat_solver_t* mcsat) {
×
3008
  mcsat->stop_search = true;
×
3009
}
×
3010

3011
term_t mcsat_get_unsat_model_interpolant(mcsat_solver_t* mcsat) {
45✔
3012
  return mcsat->interpolant;
45✔
3013
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc