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

SRI-CSL / yices2 / 26150511973

20 May 2026 08:06AM UTC coverage: 67.598% (+0.1%) from 67.453%
26150511973

Pull #611

github

disteph
Merge branch 'master' into mcsat-supplement-cdclt
Pull Request #611: Wrap MCSAT as a Nelson-Oppen theory solver in CDCL(T) architecture

682 of 994 new or added lines in 15 files covered. (68.61%)

2 existing lines in 2 files now uncovered.

86598 of 128107 relevant lines covered (67.6%)

1614128.85 hits per line

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

80.58
/src/context/context.c
1
/*
2
 * This file is part of the Yices SMT Solver.
3
 * Copyright (C) 2017 SRI International.
4
 *
5
 * Yices is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * Yices is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with Yices.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18

19
/*
20
 * ASSERTION CONTEXT
21
 */
22

23
#include <inttypes.h>
24

25
#include "api/context_config.h"
26
#include "context/context.h"
27
#include "context/context_simplifier.h"
28
#include "context/context_utils.h"
29
#include "context/internalization_codes.h"
30
#include "context/ite_flattener.h"
31
#include "solvers/bv/bvsolver.h"
32
#include "solvers/floyd_warshall/idl_floyd_warshall.h"
33
#include "solvers/floyd_warshall/rdl_floyd_warshall.h"
34
#include "solvers/funs/fun_solver.h"
35
#include "solvers/mcsat_satellite.h"
36
#include "solvers/quant/quant_solver.h"
37
#include "solvers/cdcl/delegate.h"
38
#include "solvers/simplex/simplex.h"
39
#include "terms/poly_buffer_terms.h"
40
#include "terms/term_explorer.h"
41
#include "terms/term_utils.h"
42
#include "utils/int_hash_map.h"
43
#include "utils/memalloc.h"
44

45
#include "mcsat/solver.h"
46
#include "mt/thread_macros.h"
47

48
#include "api/yices_globals.h"
49

50
#define TRACE 0
51

52
#if TRACE
53

54
#include <stdio.h>
55

56
#include "io/term_printer.h"
57
#include "solvers/cdcl/smt_core_printer.h"
58

59
#endif
60

61

62

63

64

65
/**********************
66
 *  INTERNALIZATION   *
67
 *********************/
68

69
/*
70
 * Main internalization functions:
71
 * - convert a term t to an egraph term
72
 * - convert a boolean term t to a literal
73
 * - convert an integer or real term t to an arithmetic variable
74
 * - convert a bitvector term t to a bitvector variable
75
 */
76
static occ_t internalize_to_eterm(context_t *ctx, term_t t);
77
static literal_t internalize_to_literal(context_t *ctx, term_t t);
78
static thvar_t internalize_to_arith(context_t *ctx, term_t t);
79
static thvar_t internalize_to_bv(context_t *ctx, term_t t);
80

81
static inline mcsat_satellite_t *context_mcsat_satellite(context_t *ctx);
82
static bool context_atom_requires_mcsat(context_t *ctx, term_t atom);
83
static literal_t map_mcsat_atom_to_literal(context_t *ctx, term_t atom);
84
static int32_t context_enable_mcsat_supplement(context_t *ctx);
85
static void context_disable_mcsat_supplement(context_t *ctx);
86
static bool context_assertions_need_mcsat_supplement(context_t *ctx, uint32_t n, const term_t *a);
87
static int32_t context_seed_mcsat_satellite(context_t *ctx);
88

89

90
/*
91
 * Supplementary MCSAT support (CDCL(T) mode)
92
 */
93
static inline mcsat_satellite_t *context_mcsat_satellite(context_t *ctx) {
54✔
94
  if (ctx->egraph == NULL) {
54✔
NEW
95
    return NULL;
×
96
  }
97
  return (mcsat_satellite_t *) ctx->egraph->th[ETYPE_MCSAT];
54✔
98
}
99

100
static inline bool divisor_requires_mcsat(term_table_t *terms, term_t t) {
9✔
101
  t = unsigned_term(t);
9✔
102
  return term_kind(terms, t) != ARITH_CONSTANT;
9✔
103
}
104

105
/*
106
 * Detect whether t contains arithmetic or finite-field subterms.
107
 * This is used to route all relevant arithmetic/FF atoms to the supplementary
108
 * MCSAT context once supplementation is active.
109
 */
110
static bool term_contains_arith_or_ff(context_t *ctx, term_t t, int_hmap_t *cache) {
40✔
111
  term_table_t *terms;
112
  int_hmap_pair_t *p;
113
  type_t tau;
114
  type_kind_t tkind;
115
  bool found;
116
  uint32_t i, nchildren;
117

118
  if (t < 0) {
40✔
NEW
119
    return false;
×
120
  }
121

122
  t = unsigned_term(t);
40✔
123
  p = int_hmap_find(cache, t);
40✔
124
  if (p != NULL) {
40✔
NEW
125
    return p->val != 0;
×
126
  }
127

128
  terms = ctx->terms;
40✔
129
  tau = term_type(terms, t);
40✔
130
  tkind = type_kind(terms->types, tau);
40✔
131

132
  /*
133
   * Variables of arithmetic/finite-field type may not satisfy
134
   * is_arithmetic_term/is_finitefield_term, so include type-based detection.
135
   */
136
  found = is_arithmetic_term(terms, t) || is_finitefield_term(terms, t) ||
63✔
137
          tkind == INT_TYPE || tkind == REAL_TYPE || is_ff_type(terms->types, tau);
63✔
138

139
  if (!found) {
40✔
140
    if (term_is_projection(terms, t)) {
20✔
NEW
141
      found = term_contains_arith_or_ff(ctx, proj_term_arg(terms, t), cache);
×
142

143
    } else if (term_is_sum(terms, t)) {
20✔
NEW
144
      nchildren = term_num_children(terms, t);
×
NEW
145
      for (i = 0; i < nchildren && !found; i++) {
×
146
        term_t child;
147
        mpq_t q;
NEW
148
        mpq_init(q);
×
NEW
149
        sum_term_component(terms, t, i, q, &child);
×
NEW
150
        found = term_contains_arith_or_ff(ctx, child, cache);
×
NEW
151
        mpq_clear(q);
×
152
      }
153

154
    } else if (term_is_bvsum(terms, t)) {
20✔
155
      int32_t *aux;
156
      uint32_t nbits;
157
      term_t child;
158

NEW
159
      nbits = term_bitsize(terms, t);
×
NEW
160
      aux = (int32_t *) safe_malloc(nbits * sizeof(int32_t));
×
NEW
161
      nchildren = term_num_children(terms, t);
×
NEW
162
      for (i = 0; i < nchildren && !found; i++) {
×
NEW
163
        bvsum_term_component(terms, t, i, aux, &child);
×
NEW
164
        found = term_contains_arith_or_ff(ctx, child, cache);
×
165
      }
NEW
166
      safe_free(aux);
×
167

168
    } else if (term_is_product(terms, t)) {
20✔
NEW
169
      nchildren = term_num_children(terms, t);
×
NEW
170
      for (i = 0; i < nchildren && !found; i++) {
×
171
        term_t child;
172
        uint32_t exp;
NEW
173
        product_term_component(terms, t, i, &child, &exp);
×
NEW
174
        found = term_contains_arith_or_ff(ctx, child, cache);
×
175
      }
176

177
    } else if (term_is_composite(terms, t)) {
20✔
178
      nchildren = term_num_children(terms, t);
20✔
179
      for (i = 0; i < nchildren && !found; i++) {
40✔
180
        found = term_contains_arith_or_ff(ctx, term_child(terms, t, i), cache);
20✔
181
      }
182
    }
183
  }
184

185
  p = int_hmap_get(cache, t);
40✔
186
  p->val = found ? 1 : 0;
40✔
187
  return found;
40✔
188
}
189

190
static bool term_requires_mcsat_supplement(context_t *ctx, term_t t, int_hmap_t *cache) {
1,703,295✔
191
  term_table_t *terms;
192
  int_hmap_pair_t *p;
193
  bool trigger;
194
  uint32_t i, nchildren;
195

196
  if (t < 0) {
1,703,295✔
197
    return false;
3,579✔
198
  }
199

200
  t = unsigned_term(t);
1,699,716✔
201
  p = int_hmap_find(cache, t);
1,699,716✔
202
  if (p != NULL) {
1,699,716✔
203
    return p->val != 0;
873,639✔
204
  }
205

206
  terms = ctx->terms;
826,077✔
207
  trigger = false;
826,077✔
208

209
  // finite-field usage
210
  if (is_finitefield_term(terms, t)) {
826,077✔
NEW
211
    trigger = true;
×
212
  }
213

214
  if (!trigger) {
826,077✔
215
    switch (term_kind(terms, t)) {
826,077✔
216
    case ARITH_ROOT_ATOM:
5✔
217
    case ARITH_FF_CONSTANT:
218
    case ARITH_FF_POLY:
219
    case ARITH_FF_EQ_ATOM:
220
    case ARITH_FF_BINEQ_ATOM:
221
      trigger = true;
5✔
222
      break;
5✔
223

224
    case ARITH_RDIV:
5✔
225
      trigger = divisor_requires_mcsat(terms, arith_rdiv_term_desc(terms, t)->arg[1]);
5✔
226
      break;
5✔
227

NEW
228
    case ARITH_IDIV:
×
NEW
229
      trigger = divisor_requires_mcsat(terms, arith_idiv_term_desc(terms, t)->arg[1]);
×
NEW
230
      break;
×
231

232
    case ARITH_MOD:
4✔
233
      trigger = divisor_requires_mcsat(terms, arith_mod_term_desc(terms, t)->arg[1]);
4✔
234
      break;
4✔
235

NEW
236
    case ARITH_DIVIDES_ATOM:
×
NEW
237
      trigger = divisor_requires_mcsat(terms, arith_divides_atom_desc(terms, t)->arg[0]);
×
NEW
238
      break;
×
239

240
    default:
826,063✔
241
      break;
826,063✔
242
    }
243
  }
244

245
  // arithmetic nonlinearity (including deep products in arithmetic predicates)
246
  if (!trigger && is_arithmetic_term(terms, t) && term_degree(terms, t) > 1) {
826,077✔
247
    trigger = true;
7✔
248
  }
249

250
  if (!trigger) {
826,077✔
251
    if (term_is_projection(terms, t)) {
826,063✔
252
      trigger = term_requires_mcsat_supplement(ctx, proj_term_arg(terms, t), cache);
352,607✔
253

254
    } else if (term_is_sum(terms, t)) {
473,456✔
255
      nchildren = term_num_children(terms, t);
4,591✔
256
      for (i=0; i<nchildren && !trigger; i++) {
16,538✔
257
        term_t child;
258
        mpq_t q;
259
        mpq_init(q);
11,947✔
260
        sum_term_component(terms, t, i, q, &child);
11,947✔
261
        trigger = term_requires_mcsat_supplement(ctx, child, cache);
11,947✔
262
        mpq_clear(q);
11,947✔
263
      }
264

265
    } else if (term_is_bvsum(terms, t)) {
468,865✔
266
      int32_t *aux;
267
      uint32_t nbits;
268
      term_t child;
269

270
      nbits = term_bitsize(terms, t);
5,832✔
271
      aux = (int32_t *) safe_malloc(nbits * sizeof(int32_t));
5,832✔
272
      nchildren = term_num_children(terms, t);
5,832✔
273
      for (i=0; i<nchildren && !trigger; i++) {
13,394✔
274
        bvsum_term_component(terms, t, i, aux, &child);
7,562✔
275
        trigger = term_requires_mcsat_supplement(ctx, child, cache);
7,562✔
276
      }
277
      safe_free(aux);
5,832✔
278

279
    } else if (term_is_product(terms, t)) {
463,033✔
280
      nchildren = term_num_children(terms, t);
66✔
281
      for (i=0; i<nchildren && !trigger; i++) {
196✔
282
        term_t child;
283
        uint32_t exp;
284
        product_term_component(terms, t, i, &child, &exp);
130✔
285
        trigger = term_requires_mcsat_supplement(ctx, child, cache);
130✔
286
      }
287

288
    } else if (term_is_composite(terms, t)) {
462,967✔
289
      nchildren = term_num_children(terms, t);
293,776✔
290
      for (i=0; i<nchildren && !trigger; i++) {
1,577,140✔
291
        trigger = term_requires_mcsat_supplement(ctx, term_child(terms, t, i), cache);
1,283,364✔
292
      }
293
    }
294
  }
295

296
  p = int_hmap_get(cache, t);
826,077✔
297
  p->val = trigger ? 1 : 0;
826,077✔
298
  return trigger;
826,077✔
299
}
300

301
static bool context_assertions_need_mcsat_supplement(context_t *ctx, uint32_t n, const term_t *a) {
25,777✔
302
  int_hmap_t cache;
303
  uint32_t i;
304
  bool trigger;
305

306
  init_int_hmap(&cache, 0);
25,777✔
307
  trigger = false;
25,777✔
308
  for (i=0; i<n && !trigger; i++) {
73,462✔
309
    trigger = term_requires_mcsat_supplement(ctx, a[i], &cache);
47,685✔
310
  }
311
  delete_int_hmap(&cache);
25,777✔
312

313
  return trigger;
25,777✔
314
}
315

316
static int32_t context_enable_mcsat_supplement(context_t *ctx) {
14✔
317
  mcsat_satellite_t *sat;
318
  int32_t code;
319

320
  if (ctx->mcsat_supplement_active) {
14✔
321
    return CTX_NO_ERROR;
4✔
322
  }
323
  if (ctx->arch == CTX_ARCH_MCSAT || ctx->egraph == NULL) {
10✔
NEW
324
    return CONTEXT_UNSUPPORTED_THEORY;
×
325
  }
326

327
  sat = new_mcsat_satellite(ctx);
10✔
328
  egraph_attach_mcsat_solver(ctx->egraph, sat,
10✔
329
                             mcsat_satellite_ctrl_interface(sat),
330
                             mcsat_satellite_smt_interface(sat),
331
                             mcsat_satellite_egraph_interface(sat));
332
  ctx->mcsat_supplement_active = true;
10✔
333

334
  code = context_seed_mcsat_satellite(ctx);
10✔
335
  if (code < 0) {
10✔
NEW
336
    context_disable_mcsat_supplement(ctx);
×
NEW
337
    return code;
×
338
  }
339

340
  return CTX_NO_ERROR;
10✔
341
}
342

343
static void context_disable_mcsat_supplement(context_t *ctx) {
10✔
344
  mcsat_satellite_t *sat;
345

346
  if (!ctx->mcsat_supplement_active || ctx->egraph == NULL) {
10✔
NEW
347
    return;
×
348
  }
349

350
  sat = context_mcsat_satellite(ctx);
10✔
351
  egraph_detach_mcsat_solver(ctx->egraph);
10✔
352
  delete_mcsat_satellite(sat);
10✔
353
  ctx->mcsat_supplement_active = false;
10✔
354
}
355

356
/*
357
 * Import already-internalized arithmetic/FF atoms when supplementary MCSAT
358
 * is activated after earlier assertions.
359
 */
360
static int32_t context_seed_mcsat_satellite(context_t *ctx) {
10✔
361
  mcsat_satellite_t *sat;
362
  term_table_t *terms;
363
  uint32_t i, n;
364
  uint32_t seeded = 0;
10✔
365
  bool trace_seed;
366

367
  sat = context_mcsat_satellite(ctx);
10✔
368
  if (sat == NULL) {
10✔
NEW
369
    return CTX_NO_ERROR;
×
370
  }
371

372
  terms = ctx->terms;
10✔
373
  trace_seed = tracing_tag(ctx->trace, "mcsat::supplement::seed");
10✔
374
  n = intern_tbl_num_terms(&ctx->intern);
10✔
375
  for (i = 1; i < n; i++) {
156✔
376
    term_t t;
377
    int32_t code;
378
    literal_t l;
379

380
    if (!good_term_idx(terms, i)) {
146✔
NEW
381
      continue;
×
382
    }
383

384
    t = pos_term(i);
146✔
385
    if (!is_boolean_term(terms, t) ||
146✔
386
        !intern_tbl_is_root(&ctx->intern, t) ||
110✔
387
        !intern_tbl_root_is_mapped(&ctx->intern, t)) {
110✔
388
      continue;
132✔
389
    }
390

391
    if (!context_atom_requires_mcsat(ctx, t)) {
14✔
392
      continue;
10✔
393
    }
394

395
    code = intern_tbl_map_of_root(&ctx->intern, t);
4✔
396
    if (code_is_var(code)) {
4✔
NEW
397
      l = code2literal(code);
×
398
    } else {
399
      occ_t u = code2occ(code);
4✔
400
      if (u == true_occ) {
4✔
401
        l = true_literal;
4✔
NEW
402
      } else if (u == false_occ) {
×
NEW
403
        l = false_literal;
×
NEW
404
      } else if (ctx->egraph != NULL) {
×
NEW
405
        l = egraph_occ2literal(ctx->egraph, u);
×
406
      } else {
NEW
407
        continue;
×
408
      }
409
    }
410

411
    code = mcsat_satellite_register_atom(sat, t, l, NULL);
4✔
412
    if (code < 0) {
4✔
NEW
413
      return code;
×
414
    }
415
    seeded ++;
4✔
416
    if (trace_seed) {
4✔
NEW
417
      trace_printf(ctx->trace, 1, "mcsat supplement seed: lit=%"PRId32" atom=", l);
×
NEW
418
      trace_pp_term(ctx->trace, 1, terms, t);
×
419
    }
420
  }
421

422
  if (trace_seed) {
10✔
NEW
423
    trace_printf(ctx->trace, 1, "mcsat supplement seeded %"PRIu32" atoms\n", seeded);
×
424
  }
425

426
  return CTX_NO_ERROR;
10✔
427
}
428

429
static bool mcsat_satellite_candidate_atom(term_table_t *terms, term_t atom) {
38✔
430
  switch (term_kind(terms, atom)) {
38✔
431
  case EQ_TERM:
20✔
432
  case DISTINCT_TERM:
433
  case ARITH_ROOT_ATOM:
434
  case ARITH_FF_EQ_ATOM:
435
  case ARITH_FF_BINEQ_ATOM:
436
  case ARITH_IS_INT_ATOM:
437
  case ARITH_EQ_ATOM:
438
  case ARITH_GE_ATOM:
439
  case ARITH_BINEQ_ATOM:
440
  case ARITH_DIVIDES_ATOM:
441
    return true;
20✔
442

443
  default:
18✔
444
    return false;
18✔
445
  }
446
}
447

448
static bool context_atom_requires_mcsat(context_t *ctx, term_t atom) {
553,934✔
449
  int_hmap_t cache;
450
  bool trigger, all_arith_mode;
451

452
  atom = unsigned_term(atom);
553,934✔
453
  if (!ctx->mcsat_supplement_active || !is_boolean_term(ctx->terms, atom)) {
553,934✔
454
    return false;
553,896✔
455
  }
456
  if (!mcsat_satellite_candidate_atom(ctx->terms, atom)) {
38✔
457
    return false;
18✔
458
  }
459

460
  init_int_hmap(&cache, 0);
20✔
461
  /*
462
   * In supplementary mode, route every arithmetic/FF atom to MCSAT so that
463
   * MCSAT sees the complete arithmetic conjunction (not just unsupported atoms).
464
   */
465
  all_arith_mode = true;
20✔
466
  if (all_arith_mode) {
20✔
467
    trigger = term_contains_arith_or_ff(ctx, atom, &cache);
20✔
468
  } else {
NEW
469
    trigger = term_requires_mcsat_supplement(ctx, atom, &cache);
×
470
  }
471
  delete_int_hmap(&cache);
20✔
472

473
  return trigger;
20✔
474
}
475

476
static literal_t map_mcsat_atom_to_literal(context_t *ctx, term_t atom) {
16✔
477
  mcsat_satellite_t *sat;
478
  literal_t l;
479
  void *obj;
480
  int32_t code;
481

482
  sat = context_mcsat_satellite(ctx);
16✔
483
  assert(sat != NULL);
484

485
  l = pos_lit(create_boolean_variable(ctx->core));
16✔
486
  obj = NULL;
16✔
487
  code = mcsat_satellite_register_atom(sat, atom, l, &obj);
16✔
488
  if (code < 0) {
16✔
NEW
489
    longjmp(ctx->env, code);
×
490
  }
491

492
  attach_atom_to_bvar(ctx->core, var_of(l), tagged_mcsat_atom(obj));
16✔
493
  return l;
16✔
494
}
495

496

497

498
/****************************************
499
 *  CONSTRUCTION OF EGRAPH OCCURRENCES  *
500
 ***************************************/
501

502
/*
503
 * Create a new egraph constant of the given type
504
 */
505
static eterm_t make_egraph_constant(context_t *ctx, type_t type, int32_t id) {
1,164✔
506
  assert(type_kind(ctx->types, type) == UNINTERPRETED_TYPE ||
507
         type_kind(ctx->types, type) == SCALAR_TYPE);
508
  return egraph_make_constant(ctx->egraph, type, id);
1,164✔
509
}
510

511

512
/*
513
 * Create a new egraph variable
514
 * - type = its type
515
 */
516
static eterm_t make_egraph_variable(context_t *ctx, type_t type) {
14,087✔
517
  eterm_t u;
518
  bvar_t v;
519

520
  if (type == bool_type(ctx->types)) {
14,087✔
521
    v = create_boolean_variable(ctx->core);
×
522
    u = egraph_bvar2term(ctx->egraph, v);
×
523
  } else {
524
    //    u = egraph_make_variable(ctx->egraph, type);
525
    // it's better to use skolem_term in case type is (tuple ...)
526
    u = egraph_skolem_term(ctx->egraph, type);
14,087✔
527
  }
528
  return u;
14,087✔
529
}
530

531

532
/*
533
 * Type of arithmetic variable x
534
 */
535
static type_t type_of_arithvar(context_t *ctx, thvar_t x) {
1,562✔
536
  type_t tau;
537

538
  tau = real_type(ctx->types);
1,562✔
539
  if (ctx->arith.arith_var_is_int(ctx->arith_solver, x)) {
1,562✔
540
    tau = int_type(ctx->types);
1,425✔
541
  }
542

543
  return tau;
1,562✔
544
}
545

546

547
/*
548
 * Convert arithmetic variable x to an egraph term
549
 */
550
static occ_t translate_arithvar_to_eterm(context_t *ctx, thvar_t x) {
1,571✔
551
  eterm_t u;
552
  type_t tau;
553

554
  u = ctx->arith.eterm_of_var(ctx->arith_solver, x);
1,571✔
555
  if (u == null_eterm) {
1,571✔
556
    tau = type_of_arithvar(ctx, x);
1,562✔
557
    u = egraph_thvar2term(ctx->egraph, x, tau);
1,562✔
558
  }
559

560
  return pos_occ(u);
1,571✔
561
}
562

563
/*
564
 * Convert bit-vector variable x to an egraph term
565
 * - tau = type of x
566
 */
567
static occ_t translate_bvvar_to_eterm(context_t *ctx, thvar_t x, type_t tau) {
3,693✔
568
  eterm_t u;
569

570
  u = ctx->bv.eterm_of_var(ctx->bv_solver, x);
3,693✔
571
  if (u == null_eterm) {
3,693✔
572
    u = egraph_thvar2term(ctx->egraph, x, tau);
3,672✔
573
  }
574

575
  return pos_occ(u);
3,693✔
576
}
577

578

579
/*
580
 * Convert variable x into an eterm internalization for t
581
 * - tau = type of t
582
 * - if x is mapped to an existing eterm u, return pos_occ(u)
583
 * - otherwise, create an egraph variable u and attach x to u
584
 *   then record the converse mapping [x --> u] in the relevant
585
 *   theory solver
586
 */
587
static occ_t translate_thvar_to_eterm(context_t *ctx, thvar_t x, type_t tau) {
3,348✔
588
  if (is_arithmetic_type(tau)) {
3,348✔
589
    return translate_arithvar_to_eterm(ctx, x);
619✔
590
  } else if (is_bv_type(ctx->types, tau)) {
2,729✔
591
    return translate_bvvar_to_eterm(ctx, x, tau);
2,729✔
592
  } else {
593
    longjmp(ctx->env, INTERNAL_ERROR);
×
594
  }
595
}
596

597

598
/*
599
 * Convert internalization code x for a term t into an egraph term
600
 * - t must be a root in the internalization table and must have
601
 *   positive polarity
602
 */
603
static occ_t translate_code_to_eterm(context_t *ctx, term_t t, int32_t x) {
64,982✔
604
  occ_t u;
605
  type_t tau;
606

607
  assert(is_pos_term(t) && intern_tbl_is_root(&ctx->intern, t) &&
608
         intern_tbl_map_of_root(&ctx->intern, t) == x);
609

610
  if (code_is_eterm(x)) {
64,982✔
611
    u = code2occ(x);
64,233✔
612
  } else {
613
    // x encodes a theory variable or a literal
614
    // convert that to an egraph term
615
    tau = type_of_root(ctx, t);
749✔
616
    switch (type_kind(ctx->types, tau)) {
749✔
617
    case BOOL_TYPE:
×
618
      u = egraph_literal2occ(ctx->egraph, code2literal(x));
×
619
      break;
×
620

621
    case INT_TYPE:
611✔
622
    case REAL_TYPE:
623
      u = translate_arithvar_to_eterm(ctx, code2thvar(x));
611✔
624
      break;
611✔
625

626
    case BITVECTOR_TYPE:
138✔
627
      u = translate_bvvar_to_eterm(ctx, code2thvar(x), tau);
138✔
628
      break;
138✔
629

630
    default:
×
631
      assert(false);
632
      longjmp(ctx->env, INTERNAL_ERROR);
×
633
    }
634

635
    // remap t to u
636
    intern_tbl_remap_root(&ctx->intern, t, occ2code(u));
749✔
637
  }
638

639
  return u;
64,982✔
640
}
641

642

643
/*
644
 * Internalization error for term t
645
 * - t can't be processed because there's no egraph
646
 * - the error code depends on t's type
647
 */
648
static int32_t uf_error_code(context_t *ctx, term_t t) {
×
649
  int32_t code;
650

651
  assert(! context_has_egraph(ctx));
652

653
  switch (term_type_kind(ctx->terms, t)) {
×
654
  case UNINTERPRETED_TYPE:
×
655
    code = UTYPE_NOT_SUPPORTED;
×
656
    break;
×
657

658
  case SCALAR_TYPE:
×
659
    code = SCALAR_NOT_SUPPORTED;
×
660
    break;
×
661

662
  case FUNCTION_TYPE:
×
663
    code = UF_NOT_SUPPORTED;
×
664
    break;
×
665

666
  case TUPLE_TYPE:
×
667
    code = TUPLE_NOT_SUPPORTED;
×
668
    break;
×
669

670
  default:
×
671
    assert(false);
672
    code = INTERNAL_ERROR;
×
673
    break;
×
674
  }
675

676
  return code;
×
677
}
678

679

680
/*
681
 * Utility to filter out high-order terms:
682
 * - check whether any term in a[0 ... n-1] has function type.
683
 * - if so throw an exception (via lonjmp) if the context does not include
684
 *   the array solver.
685
 */
686
static void check_high_order_support(context_t *ctx, const term_t *a, uint32_t n) {
18,027✔
687
  uint32_t i;
688

689
  if (! context_has_fun_solver(ctx)) {
18,027✔
690
    for (i=0; i<n; i++) {
30,058✔
691
      if (is_function_term(ctx->terms, a[i])) {
17,192✔
692
        longjmp(ctx->env, HIGH_ORDER_FUN_NOT_SUPPORTED);
3✔
693
      }
694
    }
695
  }
696
}
18,024✔
697

698

699
/***********************************************
700
 *  CONVERSION OF COMPOSITES TO EGRAPH TERMS   *
701
 **********************************************/
702

703
/*
704
 * Map apply term to an eterm
705
 * - tau = type of that term
706
 */
707
static occ_t map_apply_to_eterm(context_t *ctx, composite_term_t *app, type_t tau) {
9,685✔
708
  eterm_t u;
709
  occ_t *a;
710
  uint32_t i, n;
711

712
  assert(app->arity > 0);
713
  n = app->arity;
9,685✔
714

715
  check_high_order_support(ctx, app->arg+1, n-1);
9,685✔
716

717
  a = alloc_istack_array(&ctx->istack, n);
9,685✔
718
  for (i=0; i<n; i++) {
34,029✔
719
    a[i] = internalize_to_eterm(ctx, app->arg[i]);
24,344✔
720
  }
721

722
  // a[0] = function
723
  // a[1 ... n-1] are the arguments
724
  u = egraph_make_apply(ctx->egraph, a[0], n-1, a+1, tau);
9,685✔
725
  free_istack_array(&ctx->istack, a);
9,685✔
726

727
  //  add_type_constraints(ctx, pos_occ(u), tau);
728

729
  return pos_occ(u);
9,685✔
730
}
731

732

733
/*
734
 * Build a tuple of same type as t then assert that it's equal to u1
735
 * - t must be a root in the internalization table
736
 * - u1 must be equal to t's internalization (as stored in intern_table)
737
 * This is the skolemization of (exist (x1...x_n) u1 == (tuple x1 ... x_n))
738
 *
739
 * - return the eterm u := (tuple x1 ... x_n)
740
 */
741
static eterm_t skolem_tuple(context_t *ctx, term_t t, occ_t u1) {
×
742
  type_t tau;
743
  eterm_t u;
744

745
  assert(intern_tbl_is_root(&ctx->intern, t) && is_pos_term(t) &&
746
         intern_tbl_map_of_root(&ctx->intern, t) == occ2code(u1));
747

748
  tau = intern_tbl_type_of_root(&ctx->intern, t);
×
749
  u = egraph_skolem_term(ctx->egraph, tau);
×
750
  egraph_assert_eq_axiom(ctx->egraph, u1, pos_occ(u));
×
751

752
  return u;
×
753
}
754

755

756
/*
757
 * Convert (select i t) to an egraph term
758
 * - tau must be the type of that term (should not be bool)
759
 * - if a new eterm u is created, attach a theory variable to it
760
 */
761
static occ_t map_select_to_eterm(context_t *ctx, select_term_t *s, type_t tau) {
245✔
762
  occ_t u1;
763
  eterm_t tuple;
764
  composite_t *tp;
765

766
  u1 = internalize_to_eterm(ctx, s->arg);
245✔
767
  tuple = egraph_get_tuple_in_class(ctx->egraph, term_of_occ(u1));
245✔
768
  if (tuple == null_eterm) {
245✔
769
    tuple = skolem_tuple(ctx, s->arg, u1);
×
770
  }
771

772
  tp = egraph_term_body(ctx->egraph, tuple);
245✔
773
  assert(composite_body(tp) && tp != NULL && composite_kind(tp) == COMPOSITE_TUPLE);
774

775
  return tp->child[s->idx];
245✔
776
}
777

778

779
/*
780
 * Convert a conditional expression to an egraph term
781
 * - c = conditional descriptor
782
 * - tau = type of c
783
 */
784
static occ_t map_conditional_to_eterm(context_t *ctx, conditional_t *c, type_t tau) {
12✔
785
  literal_t *a;
786
  occ_t u, v;
787
  uint32_t i, n;
788
  literal_t l;
789
  bool all_false;
790
  term_t t;
791

792
#if 0
793
  printf("---> conditional to eterm\n");
794
#endif
795

796
  t = simplify_conditional(ctx, c);
12✔
797
  if (t != NULL_TERM) {
12✔
798
    return internalize_to_eterm(ctx, t);
4✔
799
  }
800

801
  n = c->nconds;
8✔
802
  a = alloc_istack_array(&ctx->istack, n + 1);
8✔
803

804
  all_false = true;
8✔
805
  u = null_occurrence;
8✔
806

807
  for (i=0; i<n; i++) {
24✔
808
    a[i] = internalize_to_literal(ctx, c->pair[i].cond);
16✔
809
    if (a[i] == true_literal) {
16✔
810
      /*
811
       * a[0] ... a[i-1] are all reducible to false
812
       * but we can't assume that a[0] ... a[i-1] are all false_literals
813
       * since we don't know how the theory solver internalizes the
814
       * conditions.
815
       */
816
      v = internalize_to_eterm(ctx, c->pair[i].val);
×
817
      if (all_false) {
×
818
        // all previous conditions a[0 ... i-1] are false
819
        assert(u == null_occurrence);
820
        u = v;
×
821
      } else {
822
        // we assert (u == v) as a top-level equality
823
        egraph_assert_eq_axiom(ctx->egraph, u, v);
×
824
      }
825
      goto done;
×
826
    }
827
    if (a[i] != false_literal) {
16✔
828
      if (all_false) {
13✔
829
        assert(u == null_occurrence);
830
        u = pos_occ(make_egraph_variable(ctx, tau));
7✔
831
        all_false = false;
7✔
832
      }
833
      // one clause for a[i] => (u = v[i])
834
      v = internalize_to_eterm(ctx, c->pair[i].val);
13✔
835
      l = egraph_make_eq(ctx->egraph, u, v);
13✔
836
      add_binary_clause(ctx->core, not(a[i]), l);
13✔
837
    }
838
  }
839

840
  if (all_false) {
8✔
841
    assert(u == null_occurrence);
842
    u = internalize_to_eterm(ctx, c->defval);
1✔
843
    goto done;
1✔
844
  }
845

846
  // clause for the default value
847
  assert(u != null_occurrence);
848
  v = internalize_to_eterm(ctx, c->defval);
7✔
849
  l = egraph_make_eq(ctx->egraph, u, v);
7✔
850
  a[n] = l;
7✔
851
  add_clause(ctx->core, n+1, a);
7✔
852

853
 done:
8✔
854
  free_istack_array(&ctx->istack, a);
8✔
855

856
  return u;
8✔
857
}
858

859

860
/*
861
 * Auxiliary function for flattening if-then-else
862
 * - v contains a conjunction of n literals: l0 /\ ... /\ l_n
863
 * - we something like (l0 /\ ... /\ l_n implies (x = y))
864
 *   (i.e., (not l0) \/ ... \/ (not l_n) \/ (x = y)
865
 * - this function negates all the literals in place
866
 */
867
static void ite_prepare_antecedents(ivector_t *v) {
8,348✔
868
  uint32_t i, n;
869

870
  n = v->size;
8,348✔
871
  for (i=0; i<n; i++) {
20,408✔
872
    v->data[i] = not(v->data[i]);
12,060✔
873
  }
874
}
8,348✔
875

876

877
/*
878
 * Convert nested if-then-else to  an egraph term
879
 * - ite = term of the form (ite c1 t1 t2)
880
 * - c = internalization of c1
881
 * - tau = type of the term (ite c1 t1 t2)
882
 */
883
static occ_t flatten_ite_to_eterm(context_t *ctx, composite_term_t *ite, literal_t c, type_t tau) {
1,168✔
884
  ite_flattener_t *flattener;
885
  ivector_t *buffer;
886
  term_t x;
887
  occ_t u, v;
888
  literal_t l;
889

890
  u = pos_occ(make_egraph_variable(ctx, tau));
1,168✔
891

892
  flattener = objstack_alloc(&ctx->ostack, sizeof(ite_flattener_t), (cleaner_t) delete_ite_flattener);
1,168✔
893
  init_ite_flattener(flattener);
1,168✔
894

895
  ite_flattener_push(flattener, ite, c);
1,168✔
896

897
  while (ite_flattener_is_nonempty(flattener)) {
4,210✔
898
    if (ite_flattener_last_lit_false(flattener)) {
3,042✔
899
      // dead branch
900
      ite_flattener_next_branch(flattener);
6✔
901
      continue;
6✔
902
    }
903
    assert(ite_flattener_branch_is_live(flattener));
904

905
    x = ite_flattener_leaf(flattener);
3,036✔
906
    x = intern_tbl_get_root(&ctx->intern, x);
3,036✔
907

908
    /*
909
     * x is the current leaf.
910
     * If it's (ite ...) then we can expand the tree by pushing x.
911
     *
912
     * Heuristic: we don't do it if x is a shared term or if it's
913
     * already internalized.
914
     * - we also need a cutoff since the number of branches grows
915
     *   exponentially.
916
     */
917
    if (is_pos_term(x) &&
6,072✔
918
        is_ite_term(ctx->terms, x) &&
3,036✔
919
        !intern_tbl_root_is_mapped(&ctx->intern, x) &&
2,473✔
920
        term_is_not_shared(&ctx->sharing, x)) {
774✔
921
      /*
922
       * x is of the form (ite c a b) and not internalized already,
923
       * we push (ite c a b) on the flattener.
924
       */
925
      ite = ite_term_desc(ctx->terms, x);
353✔
926
      assert(ite->arity == 3);
927
      c = internalize_to_literal(ctx, ite->arg[0]);
353✔
928
      ite_flattener_push(flattener, ite, c);
353✔
929
    } else {
930
      /*
931
       * Add the clause [branch conditions => x = u]
932
       */
933
      v = internalize_to_eterm(ctx, x);
2,683✔
934
      l = egraph_make_eq(ctx->egraph, u, v);
2,683✔
935

936
      buffer = &ctx->aux_vector;
2,683✔
937
      assert(buffer->size == 0);
938
      ite_flattener_get_clause(flattener, buffer);
2,683✔
939
      ite_prepare_antecedents(buffer);
2,683✔
940
      ivector_push(buffer, l);
2,683✔
941
      add_clause(ctx->core, buffer->size, buffer->data);
2,683✔
942
      ivector_reset(buffer);
2,683✔
943

944
      ite_flattener_next_branch(flattener);
2,683✔
945
    }
946
  }
947

948
  //  delete_ite_flattener(&flattener);
949
  objstack_pop(&ctx->ostack);
1,168✔
950

951
  return u;
1,168✔
952
}
953

954

955
/*
956
 * Convert (ite c t1 t2) to an egraph term
957
 * - tau = type of (ite c t1 t2)
958
 */
959
static occ_t map_ite_to_eterm(context_t *ctx, composite_term_t *ite, type_t tau) {
2,168✔
960
  conditional_t *d;
961
  eterm_t u;
962
  occ_t u1, u2, u3;
963
  literal_t c, l1, l2;
964

965
  // NOTE: we could reject (ite c t1 t2) when t1 and t2 are functions and we
966
  // don't have a function/array solver. But it looks like the egraph can
967
  // handle it so we accept it. Strictly, it's not a part of UF or QF_UF.
968

969
  d = context_make_conditional(ctx, ite);
2,168✔
970
  if (d != NULL) {
2,168✔
971
    u1 = map_conditional_to_eterm(ctx, d, tau);
12✔
972
    context_free_conditional(ctx, d);
12✔
973
    return u1;
12✔
974
  }
975

976
  c = internalize_to_literal(ctx, ite->arg[0]);
2,156✔
977
  if (c == true_literal) {
2,156✔
978
    return internalize_to_eterm(ctx, ite->arg[1]);
110✔
979
  }
980
  if (c == false_literal) {
2,046✔
981
    return internalize_to_eterm(ctx, ite->arg[2]);
15✔
982
  }
983

984
  if (context_ite_flattening_enabled(ctx)) {
2,031✔
985
    return flatten_ite_to_eterm(ctx, ite, c, tau);
1,168✔
986
  }
987

988
  u2 = internalize_to_eterm(ctx, ite->arg[1]);
863✔
989
  u3 = internalize_to_eterm(ctx, ite->arg[2]);
863✔
990

991
  if (context_keep_ite_enabled(ctx)) {
863✔
992
    // build the if-then-else in the egraph
993
    u1 = egraph_literal2occ(ctx->egraph, c);
2✔
994
    u = egraph_make_ite(ctx->egraph, u1, u2, u3, tau);
2✔
995
  } else {
996
    // eliminate the if-then-else
997
    u = make_egraph_variable(ctx, tau);
861✔
998
    l1 = egraph_make_eq(ctx->egraph, pos_occ(u), u2);
861✔
999
    l2 = egraph_make_eq(ctx->egraph, pos_occ(u), u3);
861✔
1000

1001
    assert_ite(&ctx->gate_manager, c, l1, l2, true);
861✔
1002
  }
1003

1004
  return pos_occ(u);
863✔
1005
}
1006

1007

1008

1009
/*
1010
 * Convert (update f t_1 ... t_n v) to a term
1011
 * - tau = type of that term
1012
 */
1013
static occ_t map_update_to_eterm(context_t *ctx, composite_term_t *update, type_t tau) {
11,470✔
1014
  eterm_t u;
1015
  occ_t *a;
1016
  uint32_t i, n;
1017

1018
  assert(update->arity > 2);
1019

1020
  n = update->arity;
11,470✔
1021
  a = alloc_istack_array(&ctx->istack, n);
11,470✔
1022
  for (i=0; i<n; i++) {
45,880✔
1023
    a[i] = internalize_to_eterm(ctx, update->arg[i]);
34,410✔
1024
  }
1025

1026
  // a[0]: function f
1027
  // a[1] ... a[n-2]: t_1 .. t_{n-2}
1028
  // a[n-1]: new value v
1029
  u = egraph_make_update(ctx->egraph, a[0], n-2, a+1, a[n-1], tau);
11,470✔
1030

1031
  free_istack_array(&ctx->istack, a);
11,470✔
1032

1033
  return pos_occ(u);
11,470✔
1034
}
1035

1036

1037

1038
/*
1039
 * Convert (tuple t_1 ... t_n) to a term
1040
 * - tau = type of the tuple
1041
 */
1042
static occ_t map_tuple_to_eterm(context_t *ctx, composite_term_t *tuple, type_t tau) {
190✔
1043
  eterm_t u;
1044
  occ_t *a;
1045
  uint32_t i, n;
1046

1047
  n = tuple->arity;
190✔
1048

1049
  check_high_order_support(ctx, tuple->arg, n);
190✔
1050

1051
  a = alloc_istack_array(&ctx->istack, n);
190✔
1052
  for (i=0; i<n; i++) {
560✔
1053
    a[i] = internalize_to_eterm(ctx, tuple->arg[i]);
370✔
1054
  }
1055

1056
  u = egraph_make_tuple(ctx->egraph, n, a, tau);
190✔
1057
  free_istack_array(&ctx->istack, a);
190✔
1058

1059
  return pos_occ(u);
190✔
1060
}
1061

1062

1063
/*
1064
 * Convert arithmetic and bitvector constants to eterm
1065
 * - check whether the relevant solver exists first
1066
 * - then map the constant to a solver variable x
1067
 *   and convert x to an egraph occurrence
1068
 */
1069
static occ_t map_arith_constant_to_eterm(context_t *ctx, rational_t *q) {
339✔
1070
  thvar_t x;
1071

1072
  if (! context_has_arith_solver(ctx)) {
339✔
1073
    longjmp(ctx->env, ARITH_NOT_SUPPORTED);
×
1074
  }
1075

1076
  x = ctx->arith.create_const(ctx->arith_solver, q);
339✔
1077
  return translate_arithvar_to_eterm(ctx, x);
339✔
1078
}
1079

1080
static occ_t map_bvconst64_to_eterm(context_t *ctx, bvconst64_term_t *c) {
808✔
1081
  thvar_t x;
1082
  type_t tau;
1083

1084
  if (! context_has_bv_solver(ctx)) {
808✔
1085
    longjmp(ctx->env, BV_NOT_SUPPORTED);
×
1086
  }
1087

1088
  x = ctx->bv.create_const64(ctx->bv_solver, c);
808✔
1089
  tau = bv_type(ctx->types, c->bitsize);
808✔
1090

1091
  return translate_bvvar_to_eterm(ctx, x, tau);
808✔
1092
}
1093

1094
static occ_t map_bvconst_to_eterm(context_t *ctx, bvconst_term_t *c) {
18✔
1095
  thvar_t x;
1096
  type_t tau;
1097

1098
  if (! context_has_bv_solver(ctx)) {
18✔
1099
    longjmp(ctx->env, BV_NOT_SUPPORTED);
×
1100
  }
1101

1102
  x = ctx->bv.create_const(ctx->bv_solver, c);
18✔
1103
  tau = bv_type(ctx->types, c->bitsize);
18✔
1104

1105
  return translate_bvvar_to_eterm(ctx, x, tau);
18✔
1106
}
1107

1108

1109

1110
/***************************************
1111
 *  AXIOMS FOR DIV/MOD/FLOOR/CEIL/ABS  *
1112
 **************************************/
1113

1114
/*
1115
 * Auxiliary function: p and map to represent (x - y)
1116
 * - in polynomial p, only the coefficients are relevant
1117
 * - map[0] stores x and map[1] stores y
1118
 * - both p map must be large enough (at least 2 elements)
1119
 */
1120
static void context_store_diff_poly(polynomial_t *p, thvar_t *map, thvar_t x, thvar_t y) {
×
1121
  p->nterms = 2;
×
1122
  p->mono[0].var = 1;
×
1123
  q_set_one(&p->mono[0].coeff);       // coeff of x = 1
×
1124
  p->mono[1].var = 2;
×
1125
  q_set_minus_one(&p->mono[1].coeff); // coeff of y = -1
×
1126
  p->mono[2].var = max_idx; // end marker
×
1127

1128
  map[0] = x;
×
1129
  map[1] = y;
×
1130
}
×
1131

1132

1133
/*
1134
 * Same thing for the polynomial (x - y - 1)
1135
 */
1136
static void context_store_diff_minus_one_poly(polynomial_t *p, thvar_t *map, thvar_t x, thvar_t y) {
×
1137
  p->nterms = 3;
×
1138
  p->mono[0].var = const_idx;
×
1139
  q_set_minus_one(&p->mono[0].coeff);  // constant = -1
×
1140
  p->mono[1].var = 1;
×
1141
  q_set_one(&p->mono[1].coeff);        // coeff of x = 1
×
1142
  p->mono[2].var = 2;
×
1143
  q_set_minus_one(&p->mono[2].coeff);  // coeff of y = -1
×
1144
  p->mono[3].var = max_idx;
×
1145

1146
  map[0] = null_thvar; // constant
×
1147
  map[1] = x;
×
1148
  map[2] = y;
×
1149
}
×
1150

1151

1152
/*
1153
 * Same thing for the polynomial (x + y)
1154
 */
1155
static void context_store_sum_poly(polynomial_t *p, thvar_t *map, thvar_t x, thvar_t y) {
4✔
1156
  p->nterms = 2;
4✔
1157
  p->mono[0].var = 1;
4✔
1158
  q_set_one(&p->mono[0].coeff); // coeff of x = 1
4✔
1159
  p->mono[1].var = 2;
4✔
1160
  q_set_one(&p->mono[1].coeff); // coeff of y = 1
4✔
1161
  p->mono[2].var = max_idx;
4✔
1162

1163
  map[0] = x;
4✔
1164
  map[1] = y;
4✔
1165
}
4✔
1166

1167

1168
/*
1169
 * The lower bound on y = (div x k)  is (k * y <= x) or (x - k * y >= 0)
1170
 * We store the polynomial x - k * y
1171
 */
1172
static void context_store_div_lower_bound(polynomial_t *p, thvar_t *map, thvar_t x, thvar_t y, const rational_t *k) {
21✔
1173
  p->nterms = 2;
21✔
1174
  p->mono[0].var = 1;
21✔
1175
  q_set_one(&p->mono[0].coeff);    // coeff of x = 1
21✔
1176
  p->mono[1].var = 2;
21✔
1177
  q_set_neg(&p->mono[1].coeff, k); // coeff of y = -k
21✔
1178
  p->mono[2].var = max_idx;
21✔
1179

1180
  map[0] = x;
21✔
1181
  map[1] = y;
21✔
1182
}
21✔
1183

1184

1185
/*
1186
 * For converting (divides k x), we use (divides k x) <=> (x <= k * (div x k))
1187
 * or (k * y - x >= 0) for y = (div x k).
1188
 * We store the polynomial - x + k * y.
1189
 */
1190
static void context_store_divides_constraint(polynomial_t *p, thvar_t *map, thvar_t x, thvar_t y, const rational_t *k) {
8✔
1191
  p->nterms = 2;
8✔
1192
  p->mono[0].var = 1;
8✔
1193
  q_set_minus_one(&p->mono[0].coeff);  // coeff of x = -1
8✔
1194
  p->mono[1].var = 2;
8✔
1195
  q_set(&p->mono[1].coeff, k);         // coeff of y = k
8✔
1196
  p->mono[2].var = max_idx;
8✔
1197

1198
  map[0] = x;
8✔
1199
  map[1] = y;
8✔
1200
}
8✔
1201

1202
/*
1203
 * Upper bound on y = (div x k) when both x and y are integer:
1204
 * We have x <= k * y + |k| - 1 or (-x + k y + |k| - 1 >= 0).
1205
 *
1206
 * We store the polynomial - x + k y + |k| - 1
1207
 *
1208
 * NOTE: we don't normalize the constant (|k| - 1) to zero if |k| = 1.
1209
 * This is safe as the simplex solver does not care.
1210
 */
1211
static void context_store_integer_div_upper_bound(polynomial_t *p, thvar_t *map, thvar_t x, thvar_t y, const rational_t *k) {
20✔
1212
  p->nterms = 3;
20✔
1213
  p->mono[0].var = const_idx;
20✔
1214
  q_set_abs(&p->mono[0].coeff, k);
20✔
1215
  q_sub_one(&p->mono[0].coeff);        // constant term = |k| - 1
20✔
1216
  p->mono[1].var = 1;
20✔
1217
  q_set_minus_one(&p->mono[1].coeff);  // coeff of x = -1
20✔
1218
  p->mono[2].var = 2;
20✔
1219
  q_set(&p->mono[2].coeff, k);         // coeff of y = k
20✔
1220
  p->mono[3].var = max_idx;
20✔
1221

1222
  map[0] = null_thvar;
20✔
1223
  map[1] = x;
20✔
1224
  map[2] = y;
20✔
1225
}
20✔
1226

1227
/*
1228
 * Upper bound on y = (div x k) when x or k is not an integer.
1229
 * We have x < k * y + |k| or x - k*y - |k| < 0 or (not (x - k*y - |k| >= 0))
1230
 *
1231
 * We store the polynomial x - ky - |k|
1232
 */
1233
static void context_store_rational_div_upper_bound(polynomial_t *p, thvar_t *map, thvar_t x, thvar_t y, const rational_t *k) {
1✔
1234
  p->nterms = 3;
1✔
1235
  p->mono[0].var = const_idx;
1✔
1236
  q_set_abs(&p->mono[0].coeff, k);
1✔
1237
  q_neg(&p->mono[0].coeff);           // constant term: -|k|
1✔
1238
  p->mono[1].var = 1;
1✔
1239
  q_set_one(&p->mono[1].coeff);       // coeff of x = +1
1✔
1240
  p->mono[2].var = 2;
1✔
1241
  q_set_neg(&p->mono[2].coeff, k);    // coeff of y = -k
1✔
1242
  p->mono[3].var = max_idx;
1✔
1243

1244
  map[0] = null_thvar;
1✔
1245
  map[1] = x;
1✔
1246
  map[2] = y;
1✔
1247
}
1✔
1248

1249

1250
/*
1251
 * Polynomial x - y + k d (for asserting y = k * (div y k) + (mod y k)
1252
 * - d is assumed to be (div y k)
1253
 * - x is assumed to be (mod y k)
1254
 */
1255
static void context_store_divmod_eq(polynomial_t *p, thvar_t *map, thvar_t x, thvar_t y, thvar_t d, const rational_t *k) {
11✔
1256
  p->nterms = 3;
11✔
1257
  p->mono[0].var = 1;
11✔
1258
  q_set_one(&p->mono[0].coeff);       // coefficient of x = 1
11✔
1259
  p->mono[1].var = 2;
11✔
1260
  q_set_minus_one(&p->mono[1].coeff); // coefficient of y = -1
11✔
1261
  p->mono[2].var = 3;
11✔
1262
  q_set(&p->mono[2].coeff, k);        // coefficient of d = k
11✔
1263
  p->mono[3].var = max_idx;
11✔
1264

1265
  map[0] = x;
11✔
1266
  map[1] = y;
11✔
1267
  map[2] = d;
11✔
1268
}
11✔
1269

1270

1271
/*
1272
 * Bound on x = (mod y k) assuming x and k are integer:
1273
 * - the bound is x <= |k| - 1 (i.e., |k| - 1 - x >= 0)
1274
 *   so we construct |k| - 1 - x
1275
 */
1276
static void context_store_integer_mod_bound(polynomial_t *p, thvar_t *map, thvar_t x, const rational_t *k) {
10✔
1277
  p->nterms = 2;
10✔
1278
  p->mono[0].var = const_idx;
10✔
1279
  q_set_abs(&p->mono[0].coeff, k);
10✔
1280
  q_sub_one(&p->mono[0].coeff);        // constant = |k| - 1
10✔
1281
  p->mono[1].var = 1;
10✔
1282
  q_set_minus_one(&p->mono[1].coeff);  // coeff of x = -1
10✔
1283
  p->mono[2].var = max_idx;
10✔
1284

1285
  map[0] = null_thvar;
10✔
1286
  map[1] = x;
10✔
1287
}
10✔
1288

1289

1290
/*
1291
 * Bound on x = (mod y k) when x or k are rational
1292
 * - the bound is x < |k| or x - |k| < 0 or (not (x - |k| >= 0))
1293
 *   so we construct x - |k|
1294
 */
1295
static void context_store_rational_mod_bound(polynomial_t *p, thvar_t *map, thvar_t x, const rational_t *k) {
1✔
1296
  p->nterms = 2;
1✔
1297
  p->mono[0].var = const_idx;
1✔
1298
  q_set_abs(&p->mono[0].coeff, k);
1✔
1299
  q_neg(&p->mono[0].coeff);            // constant = -|k|
1✔
1300
  p->mono[1].var = 1;
1✔
1301
  q_set_one(&p->mono[1].coeff);        // coeff of x = +1
1✔
1302
  p->mono[2].var = max_idx;
1✔
1303

1304
  map[0] = null_thvar;
1✔
1305
  map[1] = x;
1✔
1306
}
1✔
1307

1308

1309
/*
1310
 * Assert constraints for x := floor(y)
1311
 * - both x and y are variables in the arithmetic solver
1312
 * - x has type integer
1313
 *
1314
 * We assert (x <= y && y < x+1)
1315
 */
1316
static void assert_floor_axioms(context_t *ctx, thvar_t x, thvar_t y) {
×
1317
  polynomial_t *p;
1318
  thvar_t map[3];
1319

1320
  assert(ctx->arith.arith_var_is_int(ctx->arith_solver, x));
1321

1322
  p = context_get_aux_poly(ctx, 4);
×
1323

1324
  // assert (y - x >= 0)
1325
  context_store_diff_poly(p, map, y, x);
×
1326
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, true);
×
1327

1328
  // assert (y - x - 1 < 0) <=> (not (y - x - 1) >= 0)
1329
  context_store_diff_minus_one_poly(p, map, y, x);
×
1330
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, false);
×
1331
}
×
1332

1333

1334
/*
1335
 * Assert constraints for x == ceil(y)
1336
 * - both x and y are variables in the arithmetic solver
1337
 * - x has type integer
1338
 *
1339
 * We assert (x - 1 < y && y <= x)
1340
 */
1341
static void assert_ceil_axioms(context_t *ctx, thvar_t x, thvar_t y) {
×
1342
  polynomial_t *p;
1343
  thvar_t map[3];
1344

1345
  assert(ctx->arith.arith_var_is_int(ctx->arith_solver, x));
1346

1347
  p = context_get_aux_poly(ctx, 4);
×
1348

1349
  // assert (x - y >= 0)
1350
  context_store_diff_poly(p, map, x, y);
×
1351
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, true);
×
1352

1353
  // assert (x - y - 1 < 0) <=> (not (x - y - 1) >= 0)
1354
  context_store_diff_minus_one_poly(p, map, x, y);
×
1355
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, false);
×
1356
}
×
1357

1358

1359
/*
1360
 * Assert constraints for x == abs(y)
1361
 * - x and y must be variables in the arithmetic solver
1362
 *
1363
 * We assert (x >= 0) AND ((x == y) or (x == -y))
1364
 */
1365
static void assert_abs_axioms(context_t *ctx, thvar_t x, thvar_t y) {
4✔
1366
  polynomial_t *p;
1367
  thvar_t map[2];
1368
  literal_t l1, l2;
1369

1370
  // assert (x >= 0)
1371
  ctx->arith.assert_ge_axiom(ctx->arith_solver, x, true);
4✔
1372

1373
  // create l1 := (x == y)
1374
  l1 = ctx->arith.create_vareq_atom(ctx->arith_solver, x, y);
4✔
1375

1376
  // create l2 := (x == -y) that is (x + y == 0)
1377
  p = context_get_aux_poly(ctx, 3);
4✔
1378
  context_store_sum_poly(p, map, x, y);
4✔
1379
  l2 = ctx->arith.create_poly_eq_atom(ctx->arith_solver, p, map);
4✔
1380

1381
  // assert (or l1 l2)
1382
  add_binary_clause(ctx->core, l1, l2);
4✔
1383
}
4✔
1384

1385

1386
/*
1387
 * Constraints for x == (div y k)
1388
 * - x and y must be variables in the arithmetic solver
1389
 * - x must be an integer variable
1390
 * - k is a non-zero rational constant
1391
 *
1392
 * If k and y are integer, we assert
1393
 *   k * x <= y <= k * x + |k| - 1
1394
 *
1395
 * Otherwise, we assert
1396
 *   k * x <= y < k * x + |k|
1397
 */
1398
static void assert_div_axioms(context_t *ctx, thvar_t x, thvar_t y, const rational_t *k) {
21✔
1399
  polynomial_t *p;
1400
  thvar_t map[3];
1401

1402
  p = context_get_aux_poly(ctx, 4);
21✔
1403

1404
  // assert k*x <= y (i.e., y - k*x >= 0)
1405
  context_store_div_lower_bound(p, map, y, x, k);
21✔
1406
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, true);
21✔
1407

1408
  if (ctx->arith.arith_var_is_int(ctx->arith_solver, y) && q_is_integer(k)) {
21✔
1409
    // y and k are both integer
1410
    // assert y <= k*x + |k| - 1 (i.e., - y + k x + |k| - 1 >= 0)
1411
    context_store_integer_div_upper_bound(p, map, y, x, k);
20✔
1412
    ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, true);
20✔
1413

1414
  } else {
1415
    // assert y < k*x + |k| (i.e., y - k*x - |k| < 0) or (not (y - k*x - |k| >= 0))
1416
    context_store_rational_div_upper_bound(p, map, y, x, k);
1✔
1417
    ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, false);
1✔
1418
  }
1419
}
21✔
1420

1421

1422
/*
1423
 * Constraints for x == (mod y k)
1424
 * - d must be the variable equal to (div y k)
1425
 * - x and y must be variables in the arithmetic solver
1426
 * - k is a non-zero rational constant.
1427
 *
1428
 * We assert x = y - k * d (i.e., (mod y k) = x - k * (div y k))
1429
 * and 0 <= x < |k|.
1430
 *
1431
 * NOTE: The 0 <= x < |k| part is redundant. It's implied by the
1432
 * div_axioms for d = (div y k). It's cheap enough that I can't
1433
 * see a problem with adding it anyway (it's just an interval for x).
1434
 */
1435
static void assert_mod_axioms(context_t *ctx, thvar_t x, thvar_t y, thvar_t d, const rational_t *k) {
11✔
1436
  polynomial_t *p;
1437
  thvar_t map[3];
1438

1439
  p = context_get_aux_poly(ctx, 4);
11✔
1440

1441
  // assert y = k * d + x (i.e., x - y + k *d = 0)
1442
  context_store_divmod_eq(p, map, x, y, d, k);
11✔
1443
  ctx->arith.assert_poly_eq_axiom(ctx->arith_solver, p, map, true);
11✔
1444

1445
  // assert x >= 0
1446
  ctx->arith.assert_ge_axiom(ctx->arith_solver, x, true);
11✔
1447

1448
  if (ctx->arith.arith_var_is_int(ctx->arith_solver, x) && q_is_integer(k)) {
11✔
1449
    // both x and |k| are integer
1450
    // assert x <= |k| - 1, i.e., -x + |k| - 1 >= 0
1451
    context_store_integer_mod_bound(p, map, x, k);
10✔
1452
    ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, true);
10✔
1453
  } else {
1454
    // assert x < |k|, i.e., x - |k| <0, i.e., (not (x - |k| >= 0))
1455
    context_store_rational_mod_bound(p, map, x, k);
1✔
1456
    ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, false);
1✔
1457
  }
1458
}
11✔
1459

1460

1461

1462
/******************************************************
1463
 *  CONVERSION OF COMPOSITES TO ARITHMETIC VARIABLES  *
1464
 *****************************************************/
1465

1466
/*
1467
 * Convert a conditional to an arithmetic variable
1468
 * - if is_int is true, the variable is integer otherwise, it's real
1469
 */
1470
static thvar_t map_conditional_to_arith(context_t *ctx, conditional_t *c, bool is_int) {
239✔
1471
  literal_t *a;
1472
  uint32_t i, n;
1473
  thvar_t x, v;
1474
  bool all_false;
1475
  term_t t;
1476

1477
#if 0
1478
  printf("---> conditional to arith\n");
1479
#endif
1480

1481
  t = simplify_conditional(ctx, c);
239✔
1482
  if (t != NULL_TERM) {
239✔
1483
    return internalize_to_arith(ctx, t);
13✔
1484
  }
1485

1486
  n = c->nconds;
226✔
1487
  a = alloc_istack_array(&ctx->istack, n);
226✔
1488

1489
  all_false = true;
226✔
1490
  v = null_thvar;
226✔
1491

1492
  for (i=0; i<n; i++) {
703✔
1493
    a[i] = internalize_to_literal(ctx, c->pair[i].cond);
485✔
1494
    if (a[i] == true_literal) {
485✔
1495
      /*
1496
       * a[0] ... a[i-1] are all reducible to false
1497
       * but we can't assume v == null_thvar, since
1498
       * we don't know how the theory solver internalizes
1499
       * the conditions (i.e., some of them may not be false_literal).
1500
       */
1501
      x = internalize_to_arith(ctx, c->pair[i].val);
8✔
1502
      if (all_false) {
8✔
1503
        assert(v == null_thvar);
1504
        v = x;
6✔
1505
      } else {
1506
        // assert (v == x) in the arithmetic solver
1507
        ctx->arith.assert_vareq_axiom(ctx->arith_solver, v, x, true);
2✔
1508
      }
1509
      goto done;
8✔
1510
    }
1511
    if (a[i] != false_literal) {
477✔
1512
      if (all_false) {
460✔
1513
        assert(v == null_thvar);
1514
        v = ctx->arith.create_var(ctx->arith_solver, is_int);
215✔
1515
        all_false = false;
215✔
1516
      }
1517
      // clause for a[i] => (v = c->pair[i].val)
1518
      x = internalize_to_arith(ctx, c->pair[i].val);
460✔
1519
      ctx->arith.assert_cond_vareq_axiom(ctx->arith_solver, a[i], v, x);
460✔
1520
    }
1521
  }
1522

1523
  if (all_false) {
218✔
1524
    assert(v == null_thvar);
1525
    v = internalize_to_arith(ctx, c->defval);
5✔
1526
    goto done;
5✔
1527
  }
1528

1529
  /*
1530
   * last clause (only if some a[i] isn't false):
1531
   * (a[0] \/ ... \/ a[n-1] \/ v == c->defval)
1532
   */
1533
  assert(v != null_thvar);
1534
  x = internalize_to_arith(ctx, c->defval);
213✔
1535
  ctx->arith.assert_clause_vareq_axiom(ctx->arith_solver, n, a, v, x);
213✔
1536

1537
 done:
226✔
1538
  free_istack_array(&ctx->istack, a);
226✔
1539
  return v;
226✔
1540
}
1541

1542

1543
/*
1544
 * Convert nested if-then-else to  an arithmetic variable
1545
 * - ite = term of the form (ite c1 t1 t2)
1546
 * - c = internalization of c1
1547
 * - is_int = true if the if-then-else term is integer (otherwise it's real)
1548
 */
1549
static thvar_t flatten_ite_to_arith(context_t *ctx, composite_term_t *ite, literal_t c, bool is_int) {
2,521✔
1550
  ite_flattener_t *flattener;
1551
  ivector_t *buffer;
1552
  term_t x;
1553
  thvar_t u, v;
1554

1555
  u = ctx->arith.create_var(ctx->arith_solver, is_int);
2,521✔
1556

1557
  flattener = objstack_alloc(&ctx->ostack, sizeof(ite_flattener_t), (cleaner_t) delete_ite_flattener);
2,521✔
1558
  init_ite_flattener(flattener);
2,521✔
1559

1560
  ite_flattener_push(flattener, ite, c);
2,521✔
1561

1562
  while (ite_flattener_is_nonempty(flattener)) {
8,823✔
1563
    if (ite_flattener_last_lit_false(flattener)) {
6,302✔
1564
      // dead branch
1565
      ite_flattener_next_branch(flattener);
7✔
1566
      continue;
7✔
1567
    }
1568
    assert(ite_flattener_branch_is_live(flattener));
1569

1570
    x = ite_flattener_leaf(flattener);
6,295✔
1571
    x = intern_tbl_get_root(&ctx->intern, x);
6,295✔
1572

1573
    /*
1574
     * x is the current leaf
1575
     * If x is of the form (ite c a b) we can push (ite c a b) on the flattener.
1576
     *
1577
     * Heuristics: don't push the term if x is already internalized or if it's
1578
     * shared.
1579
     */
1580
    if (is_pos_term(x) &&
12,590✔
1581
        is_ite_term(ctx->terms, x) &&
6,295✔
1582
        !intern_tbl_root_is_mapped(&ctx->intern, x) &&
3,934✔
1583
        term_is_not_shared(&ctx->sharing, x)) {
1,256✔
1584
      ite = ite_term_desc(ctx->terms, x);
630✔
1585
      assert(ite->arity == 3);
1586
      c = internalize_to_literal(ctx, ite->arg[0]);
630✔
1587
      ite_flattener_push(flattener, ite, c);
630✔
1588
    } else {
1589
      /*
1590
       * Add the clause [branch conditions => x = u]
1591
       */
1592
      v = internalize_to_arith(ctx, x);
5,665✔
1593

1594
      buffer = &ctx->aux_vector;
5,665✔
1595
      assert(buffer->size == 0);
1596
      ite_flattener_get_clause(flattener, buffer);
5,665✔
1597
      ite_prepare_antecedents(buffer);
5,665✔
1598
      // assert [buffer \/ v = u]
1599
      ctx->arith.assert_clause_vareq_axiom(ctx->arith_solver, buffer->size, buffer->data, v, u);
5,665✔
1600
      ivector_reset(buffer);
5,665✔
1601

1602
      ite_flattener_next_branch(flattener);
5,665✔
1603
    }
1604
  }
1605

1606
  //  delete_ite_flattener(&flattener);
1607
   objstack_pop(&ctx->ostack);
2,521✔
1608

1609
  return u;
2,521✔
1610
}
1611

1612
/*
1613
 * Convert if-then-else to an arithmetic variable
1614
 * - if is_int is true, the if-then-else term is integer
1615
 * - otherwise, it's real
1616
 */
1617
static thvar_t map_ite_to_arith(context_t *ctx, composite_term_t *ite, bool is_int) {
3,023✔
1618
  conditional_t *d;
1619
  literal_t c;
1620
  thvar_t v, x;
1621

1622
  assert(ite->arity == 3);
1623

1624
  d = context_make_conditional(ctx, ite);
3,023✔
1625
  if (d != NULL) {
3,023✔
1626
    v = map_conditional_to_arith(ctx, d, is_int);
239✔
1627
    context_free_conditional(ctx, d);
239✔
1628
    return v;
239✔
1629
  }
1630

1631
  c = internalize_to_literal(ctx, ite->arg[0]); // condition
2,784✔
1632
  if (c == true_literal) {
2,784✔
1633
    return internalize_to_arith(ctx, ite->arg[1]);
77✔
1634
  }
1635
  if (c == false_literal) {
2,707✔
1636
    return internalize_to_arith(ctx, ite->arg[2]);
115✔
1637
  }
1638

1639
  if (context_ite_flattening_enabled(ctx)) {
2,592✔
1640
    return flatten_ite_to_arith(ctx, ite, c, is_int);
2,521✔
1641
  }
1642

1643

1644
  /*
1645
   * no simplification: create a fresh variable v and assert (c ==> v = t1)
1646
   * and (not c ==> v = t2)
1647
   */
1648
  v = ctx->arith.create_var(ctx->arith_solver, is_int);
71✔
1649

1650
  x = internalize_to_arith(ctx, ite->arg[1]);
71✔
1651
  ctx->arith.assert_cond_vareq_axiom(ctx->arith_solver, c, v, x); // c ==> v = t1
71✔
1652

1653
  x = internalize_to_arith(ctx, ite->arg[2]);
71✔
1654
  ctx->arith.assert_cond_vareq_axiom(ctx->arith_solver, not(c), v, x); // (not c) ==> v = t2
71✔
1655

1656
  return v;
71✔
1657
}
1658

1659

1660
/*
1661
 * Assert the bounds on t when t is an arithmetic, special if-then-else
1662
 * - x = arithmetic variable mapped to t in the arithmetic solver
1663
 */
1664
static void assert_ite_bounds(context_t *ctx, term_t t, thvar_t x) {
793✔
1665
  term_table_t *terms;
1666
  polynomial_t *p;
1667
  term_t lb, ub;
1668
  thvar_t map[2];
1669

1670
  terms = ctx->terms;
793✔
1671
  assert(is_arithmetic_term(terms, t));
1672

1673
  // get lower and upper bound on t. Both are rational constants
1674
  term_finite_domain_bounds(terms, t, &lb, &ub);
793✔
1675

1676
#if 0
1677
  printf("assert ite bound:\n  term: ");
1678
  print_term_name(stdout, terms, t);
1679
  printf("\n");
1680
  printf("  lower bound: ");
1681
  print_term_full(stdout, terms, lb);
1682
  printf("\n");
1683
  printf("  upper bound: ");
1684
  print_term_full(stdout, terms, ub);
1685
  printf("\n");
1686
#endif
1687

1688
  /*
1689
   * prepare polynomial p:
1690
   * first monomial is a constant, second monomial is either +t or -t
1691
   * map[0] = null (what's mapped to const_idx)
1692
   * map[1] = x = (what's mapped to t)
1693
   */
1694
  p = context_get_aux_poly(ctx, 3);
793✔
1695
  p->nterms = 2;
793✔
1696
  p->mono[0].var = const_idx;
793✔
1697
  p->mono[1].var = t;
793✔
1698
  p->mono[2].var = max_idx;
793✔
1699
  map[0] = null_thvar;
793✔
1700
  map[1] = x;
793✔
1701

1702

1703
  // first bound: t >= lb
1704
  q_set_neg(&p->mono[0].coeff, rational_term_desc(terms, lb)); // -lb
793✔
1705
  q_set_one(&p->mono[1].coeff); // +t
793✔
1706
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, true); // assert -lb + t >= 0
793✔
1707

1708
  // second bound: t <= ub
1709
  q_set(&p->mono[0].coeff, rational_term_desc(terms, ub));  // +ub
793✔
1710
  q_set_minus_one(&p->mono[1].coeff);  // -t
793✔
1711
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, true); // assert +ub - t >= 0
793✔
1712
}
793✔
1713

1714

1715
/*
1716
 * Convert a power product to an arithmetic variable
1717
 */
1718
static thvar_t map_pprod_to_arith(context_t *ctx, pprod_t *p) {
×
1719
  uint32_t i, n;
1720
  thvar_t *a;
1721
  thvar_t x;
1722

1723
  n = p->len;
×
1724
  a = alloc_istack_array(&ctx->istack, n);
×
1725
  for (i=0; i<n; i++) {
×
1726
    a[i] = internalize_to_arith(ctx, p->prod[i].var);
×
1727
  }
1728

1729
  x = ctx->arith.create_pprod(ctx->arith_solver, p, a);
×
1730
  free_istack_array(&ctx->istack, a);
×
1731

1732
  return x;
×
1733
}
1734

1735

1736
/*
1737
 * Convert polynomial p to an arithmetic variable
1738
 */
1739
static thvar_t map_poly_to_arith(context_t *ctx, polynomial_t *p) {
1,762✔
1740
  uint32_t i, n;
1741
  thvar_t *a;
1742
  thvar_t x;
1743

1744
  n = p->nterms;
1,762✔
1745
  a = alloc_istack_array(&ctx->istack, n);
1,762✔
1746

1747
  // skip the constant if any
1748
  i = 0;
1,762✔
1749
  if (p->mono[0].var == const_idx) {
1,762✔
1750
    a[0] = null_thvar;
467✔
1751
    i ++;
467✔
1752
  }
1753

1754
  // deal with the non-constant monomials
1755
  while (i<n) {
5,035✔
1756
    a[i] = internalize_to_arith(ctx, p->mono[i].var);
3,273✔
1757
    i ++;
3,273✔
1758
  }
1759

1760
  // build the polynomial
1761
  x = ctx->arith.create_poly(ctx->arith_solver, p, a);
1,762✔
1762
  free_istack_array(&ctx->istack, a);
1,762✔
1763

1764
  return x;
1,762✔
1765
}
1766

1767

1768
/*
1769
 * Auxiliary function: return y := (floor x)
1770
 * - check the divmod table first.
1771
 *   If there's a record for (floor x), return the corresponding variable.
1772
 * - Otherwise, create a fresh integer variable y,
1773
 *   assert the axioms for y = (floor x)
1774
 *   add a record to the divmod table and return y.
1775
 */
1776
static thvar_t get_floor(context_t *ctx, thvar_t x) {
×
1777
  thvar_t y;
1778

1779
  y = context_find_var_for_floor(ctx, x);
×
1780
  if (y == null_thvar) {
×
1781
    y = ctx->arith.create_var(ctx->arith_solver, true); // y is an integer variable
×
1782
    assert_floor_axioms(ctx, y, x); // assert y = floor(x)
×
1783
    context_record_floor(ctx, x, y); // save the mapping y --> floor(x)
×
1784
  }
1785

1786
  return y;
×
1787
}
1788

1789

1790
/*
1791
 * Return y := (div x k)
1792
 * - check the divmod table first
1793
 * - if (div x k) has already been processed, return the corresponding variable
1794
 * - otherwise create a new variable y, assert the axioms for y = (div x k)
1795
 *   add a record in the divmod table, and return y.
1796
 */
1797
static thvar_t get_div(context_t *ctx, thvar_t x, const rational_t *k) {
25✔
1798
  thvar_t y;
1799

1800
  y = context_find_var_for_div(ctx, x, k);
25✔
1801
  if (y == null_thvar) {
25✔
1802
    // create y := (div x k)
1803
    y = ctx->arith.create_var(ctx->arith_solver, true); // y is an integer
21✔
1804
    assert_div_axioms(ctx, y, x, k);
21✔
1805
    context_record_div(ctx, x, k, y);
21✔
1806
  }
1807

1808
  return y;
25✔
1809
}
1810

1811

1812

1813
/*
1814
 * Convert (floor t) to an arithmetic variable
1815
 */
1816
static thvar_t map_floor_to_arith(context_t *ctx, term_t t) {
×
1817
  thvar_t x, y;
1818

1819
  x = internalize_to_arith(ctx, t);
×
1820
  if (ctx->arith.arith_var_is_int(ctx->arith_solver, x)) {
×
1821
    // x is integer so (floor x) = x
1822
    y = x;
×
1823
  } else {
1824
    y = get_floor(ctx, x);
×
1825
  }
1826

1827
  return y;
×
1828
}
1829

1830

1831
/*
1832
 * Convert (ceil t) to an arithmetic variable
1833
 */
1834
static thvar_t map_ceil_to_arith(context_t *ctx, term_t t) {
×
1835
  thvar_t x, y;
1836

1837
  x = internalize_to_arith(ctx, t);
×
1838
  if (ctx->arith.arith_var_is_int(ctx->arith_solver, x)) {
×
1839
    // x is integer so (ceil x) = x
1840
    y = x;
×
1841
  } else {
1842
    y = context_find_var_for_ceil(ctx, x);
×
1843
    if (y == null_thvar) {
×
1844
      y = ctx->arith.create_var(ctx->arith_solver, true); // y is an integer variable
×
1845
      assert_ceil_axioms(ctx, y, x); // assert y = ceil(x)
×
1846
      context_record_ceil(ctx, x, y); // save the mapping y --> ceil(x)
×
1847
    }
1848
  }
1849

1850
  return y;
×
1851
}
1852

1853

1854
/*
1855
 * Convert (abs t) to an arithmetic variable
1856
 */
1857
static thvar_t map_abs_to_arith(context_t *ctx, term_t t) {
4✔
1858
  thvar_t x, y;
1859
  bool is_int;
1860

1861
  x = internalize_to_arith(ctx, t);
4✔
1862
  is_int = ctx->arith.arith_var_is_int(ctx->arith_solver, x);
4✔
1863
  y = ctx->arith.create_var(ctx->arith_solver, is_int); // y := abs(x) has the same type as x
4✔
1864
  assert_abs_axioms(ctx, y, x);
4✔
1865

1866
  return y;
4✔
1867
}
1868

1869

1870
/*
1871
 * Auxiliary function: check whether t is a non-zero arithmetic constant
1872
 * - if so, store t's value in *val
1873
 */
1874
static bool is_non_zero_rational(term_table_t *tbl, term_t t, rational_t *val) {
17✔
1875
  assert(is_arithmetic_term(tbl, t));
1876

1877
  if (term_kind(tbl, t) == ARITH_CONSTANT) {
17✔
1878
    q_set(val, rational_term_desc(tbl, t));
17✔
1879
    return q_is_nonzero(val);
17✔
1880
  }
1881
  return false;
×
1882
}
1883

1884

1885
/*
1886
 * Error in division: either the divisor is zero or is non-constant
1887
 */
1888
static void __attribute__((noreturn))  bad_divisor(context_t *ctx, term_t t) {
3✔
1889
  term_table_t *tbl;
1890
  int code;
1891

1892
  tbl = ctx->terms;
3✔
1893
  assert(is_arithmetic_term(tbl, t) && is_pos_term(t));
1894

1895
  code = FORMULA_NOT_LINEAR;
3✔
1896
  if (term_kind(tbl, t) == ARITH_CONSTANT && q_is_zero(rational_term_desc(tbl, t))) {
3✔
1897
    code = DIV_BY_ZERO;
3✔
1898
  }
1899
  longjmp(ctx->env, code);
3✔
1900
}
1901

1902
/*
1903
 * Convert (/ t1 t2) to an arithmetic variable
1904
 * - t2 must be a non-zero arithmetic constant
1905
 */
1906
static thvar_t map_rdiv_to_arith(context_t *ctx, composite_term_t *div) {
3✔
1907
  // Could try to evaluate t2 then check whether that's a constant
1908
  assert(div->arity == 2);
1909
  bad_divisor(ctx, div->arg[1]);
3✔
1910
}
1911

1912

1913
/*
1914
 * Convert (div t1 t2) to an arithmetic variable.
1915
 * - fails if t2 is not an arithmetic constant or if it's zero
1916
 */
1917
static thvar_t map_idiv_to_arith(context_t *ctx, composite_term_t *div) {
6✔
1918
  rational_t k;
1919
  thvar_t x, y;
1920

1921
  assert(div->arity == 2);
1922

1923
  q_init(&k);
6✔
1924
  if (is_non_zero_rational(ctx->terms, div->arg[1], &k)) { // k := value of t2
6✔
1925
    assert(q_is_nonzero(&k));
1926
    x = internalize_to_arith(ctx, div->arg[0]); // t1
6✔
1927
    y = get_div(ctx, x, &k);
6✔
1928

1929
  } else {
1930
    // division by a non-constant or by zero: not supported by default
1931
    // arithmetic solver for now
1932
    q_clear(&k);
×
1933
    bad_divisor(ctx, div->arg[1]);
×
1934
  }
1935
  q_clear(&k);
6✔
1936

1937
  return y;
6✔
1938
}
1939

1940

1941
/*
1942
 * Convert (mod t1 t2) to an arithmetic variable
1943
 * - t2 must be a non-zero constant
1944
 */
1945
static thvar_t map_mod_to_arith(context_t *ctx, composite_term_t *mod) {
11✔
1946
  rational_t k;
1947
  thvar_t x, y, r;
1948
  bool is_int;
1949

1950
  assert(mod->arity == 2);
1951

1952
  q_init(&k);
11✔
1953
  if (is_non_zero_rational(ctx->terms, mod->arg[1], &k)) { // k := divider
11✔
1954
    x = internalize_to_arith(ctx, mod->arg[0]);
11✔
1955

1956
    // get y := (div x k)
1957
    assert(q_is_nonzero(&k));
1958
    y = get_div(ctx, x, &k);
11✔
1959

1960
    /*
1961
     * r := (mod x k) is x - k * y where y is an integer.
1962
     * If both x and k are integer, then r has integer type. Otherwise,
1963
     * r is a real variable.
1964
     */
1965
    is_int = ctx->arith.arith_var_is_int(ctx->arith_solver, x) && q_is_integer(&k);
11✔
1966
    r = ctx->arith.create_var(ctx->arith_solver, is_int);
11✔
1967
    assert_mod_axioms(ctx, r, x, y, &k);
11✔
1968

1969
  } else {
1970
    // Non-constant or zero divider
1971
    q_clear(&k);
×
1972
    bad_divisor(ctx, mod->arg[1]);
×
1973
  }
1974

1975
  q_clear(&k);
11✔
1976

1977
  return r;
11✔
1978
}
1979

1980

1981

1982
/******************************************************
1983
 *  CONVERSION OF COMPOSITES TO BIT-VECTOR VARIABLES  *
1984
 *****************************************************/
1985

1986
/*
1987
 * Convert if-then-else to a bitvector variable
1988
 */
1989
static thvar_t map_ite_to_bv(context_t *ctx, composite_term_t *ite) {
20,779✔
1990
  literal_t c;
1991
  thvar_t x, y;
1992

1993
  assert(ite->arity == 3);
1994

1995
  c = internalize_to_literal(ctx, ite->arg[0]);
20,779✔
1996
  if (c == true_literal) {
20,779✔
1997
    return internalize_to_bv(ctx, ite->arg[1]);
23✔
1998
  }
1999
  if (c == false_literal) {
20,756✔
2000
    return internalize_to_bv(ctx, ite->arg[2]);
2,082✔
2001
  }
2002

2003
  // no simplification
2004
  x = internalize_to_bv(ctx, ite->arg[1]);
18,674✔
2005
  y = internalize_to_bv(ctx, ite->arg[2]);
18,674✔
2006

2007
  return ctx->bv.create_bvite(ctx->bv_solver, c, x, y);
18,674✔
2008
}
2009

2010

2011
/*
2012
 * Array of bits b
2013
 * - hackish: we locally disable flattening here
2014
 */
2015
static thvar_t map_bvarray_to_bv(context_t *ctx, composite_term_t *b) {
16,994✔
2016
  uint32_t i, n;
2017
  uint32_t save_options;
2018
  literal_t *a;
2019
  thvar_t x;
2020

2021
  n = b->arity;
16,994✔
2022
  a = alloc_istack_array(&ctx->istack, n);
16,994✔
2023

2024
  save_options = ctx->options;
16,994✔
2025
  disable_diseq_and_or_flattening(ctx);
16,994✔
2026
  for (i=0; i<n; i++) {
497,877✔
2027
    a[i] = internalize_to_literal(ctx, b->arg[i]);
480,883✔
2028
  }
2029
  ctx->options = save_options;
16,994✔
2030

2031
  x = ctx->bv.create_bvarray(ctx->bv_solver, a, n);
16,994✔
2032

2033
  free_istack_array(&ctx->istack, a);
16,994✔
2034

2035
  return x;
16,994✔
2036
}
2037

2038

2039
/*
2040
 * Unsigned division: quotient (div u v)
2041
 */
2042
static thvar_t map_bvdiv_to_bv(context_t *ctx, composite_term_t *div) {
97✔
2043
  thvar_t x, y;
2044

2045
  assert(div->arity == 2);
2046
  x = internalize_to_bv(ctx, div->arg[0]);
97✔
2047
  y = internalize_to_bv(ctx, div->arg[1]);
97✔
2048

2049
  return ctx->bv.create_bvdiv(ctx->bv_solver, x, y);
97✔
2050
}
2051

2052

2053
/*
2054
 * Unsigned division: remainder (rem u v)
2055
 */
2056
static thvar_t map_bvrem_to_bv(context_t *ctx, composite_term_t *rem) {
148✔
2057
  thvar_t x, y;
2058

2059
  assert(rem->arity == 2);
2060
  x = internalize_to_bv(ctx, rem->arg[0]);
148✔
2061
  y = internalize_to_bv(ctx, rem->arg[1]);
148✔
2062

2063
  return ctx->bv.create_bvrem(ctx->bv_solver, x, y);
148✔
2064
}
2065

2066

2067
/*
2068
 * Signed division/rounding toward 0: quotient (sdiv u v)
2069
 */
2070
static thvar_t map_bvsdiv_to_bv(context_t *ctx, composite_term_t *sdiv) {
87✔
2071
  thvar_t x, y;
2072

2073
  assert(sdiv->arity == 2);
2074
  x = internalize_to_bv(ctx, sdiv->arg[0]);
87✔
2075
  y = internalize_to_bv(ctx, sdiv->arg[1]);
87✔
2076

2077
  return ctx->bv.create_bvsdiv(ctx->bv_solver, x, y);
87✔
2078
}
2079

2080

2081
/*
2082
 * Signed division/rounding toward 0: remainder (srem u v)
2083
 */
2084
static thvar_t map_bvsrem_to_bv(context_t *ctx, composite_term_t *srem) {
78✔
2085
  thvar_t x, y;
2086

2087
  assert(srem->arity == 2);
2088
  x = internalize_to_bv(ctx, srem->arg[0]);
78✔
2089
  y = internalize_to_bv(ctx, srem->arg[1]);
78✔
2090

2091
  return ctx->bv.create_bvsrem(ctx->bv_solver, x, y);
78✔
2092
}
2093

2094

2095
/*
2096
 * Signed division/rounding toward -infinity: remainder (smod u v)
2097
 */
2098
static thvar_t map_bvsmod_to_bv(context_t *ctx, composite_term_t *smod) {
×
2099
  thvar_t x, y;
2100

2101
  assert(smod->arity == 2);
2102
  x = internalize_to_bv(ctx, smod->arg[0]);
×
2103
  y = internalize_to_bv(ctx, smod->arg[1]);
×
2104

2105
  return ctx->bv.create_bvsmod(ctx->bv_solver, x, y);
×
2106
}
2107

2108

2109
/*
2110
 * Left shift: (shl u v)
2111
 */
2112
static thvar_t map_bvshl_to_bv(context_t *ctx, composite_term_t *shl) {
85✔
2113
  thvar_t x, y;
2114

2115
  assert(shl->arity == 2);
2116
  x = internalize_to_bv(ctx, shl->arg[0]);
85✔
2117
  y = internalize_to_bv(ctx, shl->arg[1]);
85✔
2118

2119
  return ctx->bv.create_bvshl(ctx->bv_solver, x, y);
85✔
2120
}
2121

2122

2123
/*
2124
 * Logical shift right: (lshr u v)
2125
 */
2126
static thvar_t map_bvlshr_to_bv(context_t *ctx, composite_term_t *lshr) {
1,428✔
2127
  thvar_t x, y;
2128

2129
  assert(lshr->arity == 2);
2130
  x = internalize_to_bv(ctx, lshr->arg[0]);
1,428✔
2131
  y = internalize_to_bv(ctx, lshr->arg[1]);
1,428✔
2132

2133
  return ctx->bv.create_bvlshr(ctx->bv_solver, x, y);
1,428✔
2134
}
2135

2136

2137
/*
2138
 * Arithmetic shift right: (ashr u v)
2139
 */
2140
static thvar_t map_bvashr_to_bv(context_t *ctx, composite_term_t *ashr) {
296✔
2141
  thvar_t x, y;
2142

2143
  assert(ashr->arity == 2);
2144
  x = internalize_to_bv(ctx, ashr->arg[0]);
296✔
2145
  y = internalize_to_bv(ctx, ashr->arg[1]);
296✔
2146

2147
  return ctx->bv.create_bvashr(ctx->bv_solver, x, y);
296✔
2148
}
2149

2150

2151

2152
/*
2153
 * TODO: check for simplifications in bitvector arithmetic
2154
 * before translation to bitvector variables.
2155
 *
2156
 * This matters for the wienand-cav2008 benchmarks.
2157
 */
2158

2159
/*
2160
 * Power product
2161
 */
2162
static thvar_t map_pprod_to_bv(context_t *ctx, pprod_t *p) {
585✔
2163
  uint32_t i, n;
2164
  thvar_t *a;
2165
  thvar_t x;
2166

2167
  n = p->len;
585✔
2168
  a = alloc_istack_array(&ctx->istack, n);
585✔
2169
  for (i=0; i<n; i++) {
1,730✔
2170
    a[i] = internalize_to_bv(ctx, p->prod[i].var);
1,145✔
2171
  }
2172

2173
  x = ctx->bv.create_pprod(ctx->bv_solver, p, a);
585✔
2174
  free_istack_array(&ctx->istack, a);
585✔
2175

2176
  return x;
585✔
2177
}
2178

2179

2180
/*
2181
 * Bitvector polynomial, 64bit coefficients
2182
 */
2183
static thvar_t map_bvpoly64_to_bv(context_t *ctx, bvpoly64_t *p) {
12,157✔
2184
  uint32_t i, n;
2185
  thvar_t *a;
2186
  thvar_t x;
2187

2188
  assert(p->nterms > 0);
2189

2190
  n = p->nterms;
12,157✔
2191
  a = alloc_istack_array(&ctx->istack, n);
12,157✔
2192

2193
  // skip the constant if any
2194
  i = 0;
12,157✔
2195
  if (p->mono[0].var == const_idx) {
12,157✔
2196
    a[0] = null_thvar;
3,168✔
2197
    i ++;
3,168✔
2198
  }
2199

2200
  // non-constant monomials
2201
  while (i < n) {
28,319✔
2202
    a[i] = internalize_to_bv(ctx, p->mono[i].var);
16,162✔
2203
    i ++;
16,162✔
2204
  }
2205

2206
  x = ctx->bv.create_poly64(ctx->bv_solver, p, a);
12,157✔
2207
  free_istack_array(&ctx->istack, a);
12,157✔
2208

2209
  return x;
12,157✔
2210
}
2211

2212

2213
/*
2214
 * Bitvector polynomial, coefficients have more than 64bits
2215
 */
2216
static thvar_t map_bvpoly_to_bv(context_t *ctx, bvpoly_t *p) {
607✔
2217
  uint32_t i, n;
2218
  thvar_t *a;
2219
  thvar_t x;
2220

2221
  assert(p->nterms > 0);
2222

2223
  n = p->nterms;
607✔
2224
  a = alloc_istack_array(&ctx->istack, n);
607✔
2225

2226
  // skip the constant if any
2227
  i = 0;
607✔
2228
  if (p->mono[0].var == const_idx) {
607✔
2229
    a[0] = null_thvar;
539✔
2230
    i ++;
539✔
2231
  }
2232

2233
  // non-constant monomials
2234
  while (i < n) {
1,268✔
2235
    a[i] = internalize_to_bv(ctx, p->mono[i].var);
661✔
2236
    i ++;
661✔
2237
  }
2238

2239
  x = ctx->bv.create_poly(ctx->bv_solver, p, a);
607✔
2240
  free_istack_array(&ctx->istack, a);
607✔
2241

2242
  return x;
607✔
2243
}
2244

2245

2246
#if 0
2247
/*
2248
 * Bvpoly buffer: b must be normalized.
2249
 * - not optimal but this shouldn't be called often.
2250
 */
2251
static thvar_t map_bvpoly_buffer_to_bv(context_t *ctx, bvpoly_buffer_t *b) {
2252
  bvpoly64_t *p;
2253
  bvpoly_t *q;
2254
  uint32_t n;
2255
  thvar_t x;
2256

2257
  n = bvpoly_buffer_bitsize(b);
2258

2259
  if (bvpoly_buffer_is_zero(b)) {
2260
    x = ctx->bv.create_zero(ctx->bv_solver, n);
2261
  } else if (n <= 64) {
2262
    p = bvpoly_buffer_getpoly64(b);
2263
    x = map_bvpoly64_to_bv(ctx, p);
2264
    free_bvpoly64(p);
2265
  } else {
2266
    q = bvpoly_buffer_getpoly(b);
2267
    x = map_bvpoly_to_bv(ctx, q);
2268
    free_bvpoly(q);
2269
  }
2270

2271
  if (ctx->mcsat_supplement_active) {
2272
    mcsat_satellite_t *sat = context_mcsat_satellite(ctx);
2273
    if (sat != NULL) {
2274
      mcsat_satellite_register_arith_term(sat, x, r);
2275
    }
2276
  }
2277

2278
  return x;
2279
}
2280

2281
#endif
2282

2283
/****************************
2284
 *  CONVERSION TO LITERALS  *
2285
 ***************************/
2286

2287
/*
2288
 * Boolean if-then-else
2289
 */
2290
static literal_t map_ite_to_literal(context_t *ctx, composite_term_t *ite) {
1,863✔
2291
  literal_t l1, l2, l3;
2292

2293
  assert(ite->arity == 3);
2294
  l1 = internalize_to_literal(ctx, ite->arg[0]); // condition
1,863✔
2295
  if (l1 == true_literal) {
1,863✔
2296
    return internalize_to_literal(ctx, ite->arg[1]);
32✔
2297
  }
2298
  if (l1 == false_literal) {
1,831✔
2299
    return internalize_to_literal(ctx, ite->arg[2]);
71✔
2300
  }
2301

2302
  l2 = internalize_to_literal(ctx, ite->arg[1]);
1,760✔
2303
  l3 = internalize_to_literal(ctx, ite->arg[2]);
1,760✔
2304

2305
  return mk_ite_gate(&ctx->gate_manager, l1, l2, l3);
1,760✔
2306
}
2307

2308

2309
/*
2310
 * Generic equality: (eq t1 t2)
2311
 * - t1 and t2 are not arithmetic or bitvector terms
2312
 */
2313
static literal_t map_eq_to_literal(context_t *ctx, composite_term_t *eq) {
14,519✔
2314
  occ_t u, v;
2315
  literal_t l1, l2, l;
2316

2317
  assert(eq->arity == 2);
2318

2319
  if (is_boolean_term(ctx->terms, eq->arg[0])) {
14,519✔
2320
    assert(is_boolean_term(ctx->terms, eq->arg[1]));
2321

2322
    l1 = internalize_to_literal(ctx, eq->arg[0]);
9,058✔
2323
    l2 = internalize_to_literal(ctx, eq->arg[1]);
9,058✔
2324
    l = mk_iff_gate(&ctx->gate_manager, l1, l2);
9,058✔
2325
  } else {
2326
    // filter out high-order terms. It's enough to check eq->arg[0]
2327
    check_high_order_support(ctx, eq->arg, 1);
5,461✔
2328

2329
    u = internalize_to_eterm(ctx, eq->arg[0]);
5,461✔
2330
    v = internalize_to_eterm(ctx, eq->arg[1]);
5,461✔
2331
    l = egraph_make_eq(ctx->egraph, u, v);
5,461✔
2332
  }
2333

2334
  return l;
14,519✔
2335
}
2336

2337

2338
/*
2339
 * (or t1 ... t_n)
2340
 */
2341
static literal_t map_or_to_literal(context_t *ctx, composite_term_t *or) {
81,300✔
2342
  int32_t *a;
2343
  ivector_t *v;
2344
  literal_t l;
2345
  uint32_t i, n;
2346

2347
  if (context_flatten_or_enabled(ctx)) {
81,300✔
2348
    // flatten (or ...): store result in v
2349
    v = &ctx->aux_vector;
13,220✔
2350
    assert(v->size == 0);
2351
    flatten_or_term(ctx, v, or);
13,220✔
2352

2353
    // try easy simplification
2354
    n = v->size;
13,220✔
2355
    if (disjunct_is_true(ctx, v->data, n)) {
13,220✔
2356
      ivector_reset(v);
335✔
2357
      return true_literal;
335✔
2358
    }
2359

2360
    // make a copy of v
2361
    a = alloc_istack_array(&ctx->istack, n);
12,885✔
2362
    for (i=0; i<n; i++) {
70,797✔
2363
      a[i] = v->data[i];
57,912✔
2364
    }
2365
    ivector_reset(v);
12,885✔
2366

2367
    // internalize a[0 ... n-1]
2368
    for (i=0; i<n; i++) {
69,824✔
2369
      l = internalize_to_literal(ctx, a[i]);
57,221✔
2370
      if (l == true_literal) goto done;
57,221✔
2371
      a[i] = l;
56,939✔
2372
    }
2373

2374
  } else {
2375
    // no flattening
2376
    n = or->arity;
68,080✔
2377
    if (disjunct_is_true(ctx, or->arg, n)) {
68,080✔
2378
      return true_literal;
204✔
2379
    }
2380

2381
    a = alloc_istack_array(&ctx->istack, n);
67,876✔
2382
    for (i=0; i<n; i++) {
254,012✔
2383
      l = internalize_to_literal(ctx, or->arg[i]);
186,452✔
2384
      if (l == true_literal) goto done;
186,452✔
2385
      a[i] = l;
186,136✔
2386
    }
2387
  }
2388

2389
  l = mk_or_gate(&ctx->gate_manager, n, a);
80,163✔
2390

2391
 done:
80,761✔
2392
  free_istack_array(&ctx->istack, a);
80,761✔
2393

2394
  return l;
80,761✔
2395
}
2396

2397

2398
/*
2399
 * (xor t1 ... t_n)
2400
 */
2401
static literal_t map_xor_to_literal(context_t *ctx, composite_term_t *xor) {
1✔
2402
  int32_t *a;
2403
  literal_t l;
2404
  uint32_t i, n;
2405

2406
  n = xor->arity;
1✔
2407
  a = alloc_istack_array(&ctx->istack, n);
1✔
2408
  for (i=0; i<n; i++) {
4✔
2409
    a[i] = internalize_to_literal(ctx, xor->arg[i]);
3✔
2410
  }
2411

2412
  l = mk_xor_gate(&ctx->gate_manager, n, a);
1✔
2413
  free_istack_array(&ctx->istack, a);
1✔
2414

2415
  return l;
1✔
2416
}
2417

2418

2419
/*
2420
 * Convert (p t_1 .. t_n) to a literal
2421
 * - create an egraph atom
2422
 */
2423
static literal_t map_apply_to_literal(context_t *ctx, composite_term_t *app) {
4,368✔
2424
  occ_t *a;
2425
  uint32_t i, n;
2426
  literal_t l;
2427

2428
  assert(app->arity > 0);
2429
  n = app->arity;
4,368✔
2430
  a = alloc_istack_array(&ctx->istack, n);
4,368✔
2431
  for (i=0; i<n; i++) {
16,325✔
2432
    a[i] = internalize_to_eterm(ctx, app->arg[i]);
11,957✔
2433
  }
2434

2435
  // a[0] = predicate
2436
  // a[1 ...n-1] = arguments
2437
  l = egraph_make_pred(ctx->egraph, a[0], n-1, a + 1);
4,368✔
2438
  free_istack_array(&ctx->istack, a);
4,368✔
2439

2440
  return l;
4,368✔
2441
}
2442

2443

2444

2445
/*
2446
 * Auxiliary function: translate (distinct a[0 ... n-1]) to a literal,
2447
 * when a[0] ... a[n-1] are arithmetic variables.
2448
 *
2449
 * We expand this into a quadratic number of disequalities.
2450
 */
2451
static literal_t make_arith_distinct(context_t *ctx, uint32_t n, thvar_t *a) {
158✔
2452
  uint32_t i, j;
2453
  ivector_t *v;
2454
  literal_t l;
2455

2456
  assert(n >= 2);
2457

2458
  v = &ctx->aux_vector;
158✔
2459
  assert(v->size == 0);
2460
  for (i=0; i<n-1; i++) {
3,776✔
2461
    for (j=i+1; j<n; j++) {
48,648✔
2462
      l = ctx->arith.create_vareq_atom(ctx->arith_solver, a[i], a[j]);
45,030✔
2463
      ivector_push(v, l);
45,030✔
2464
    }
2465
  }
2466
  l = mk_or_gate(&ctx->gate_manager, v->size, v->data);
158✔
2467
  ivector_reset(v);
158✔
2468

2469
  return not(l);
158✔
2470
}
2471

2472

2473
/*
2474
 * Auxiliary function: translate (distinct a[0 ... n-1]) to a literal,
2475
 * when a[0] ... a[n-1] are bitvector variables.
2476
 *
2477
 * We expand this into a quadratic number of disequalities.
2478
 */
2479
static literal_t make_bv_distinct(context_t *ctx, uint32_t n, thvar_t *a) {
2✔
2480
  uint32_t i, j;
2481
  ivector_t *v;
2482
  literal_t l;
2483

2484
  assert(n >= 2);
2485

2486
  v = &ctx->aux_vector;
2✔
2487
  assert(v->size == 0);
2488
  for (i=0; i<n-1; i++) {
11✔
2489
    for (j=i+1; j<n; j++) {
40✔
2490
      l = ctx->bv.create_eq_atom(ctx->bv_solver, a[i], a[j]);
31✔
2491
      ivector_push(v, l);
31✔
2492
    }
2493
  }
2494
  l = mk_or_gate(&ctx->gate_manager, v->size, v->data);
2✔
2495
  ivector_reset(v);
2✔
2496

2497
  return not(l);
2✔
2498
}
2499

2500

2501
/*
2502
 * Convert (distinct t_1 ... t_n) to a literal
2503
 */
2504
static literal_t map_distinct_to_literal(context_t *ctx, composite_term_t *distinct) {
9✔
2505
  int32_t *a;
2506
  literal_t l;
2507
  uint32_t i, n;
2508

2509
  n = distinct->arity;
9✔
2510
  a = alloc_istack_array(&ctx->istack, n);
9✔
2511
  if (context_has_egraph(ctx)) {
9✔
2512
    // fail if arguments are functions and we don't support high-order terms
2513
    // checking the first argument is enough since they all have the same type
2514
    check_high_order_support(ctx, distinct->arg, 1);
6✔
2515

2516
    // default: translate to the egraph
2517
    for (i=0; i<n; i++) {
25✔
2518
      a[i] = internalize_to_eterm(ctx, distinct->arg[i]);
19✔
2519
    }
2520
    l = egraph_make_distinct(ctx->egraph, n, a);
6✔
2521

2522
  } else if (is_arithmetic_term(ctx->terms, distinct->arg[0])) {
3✔
2523
    // translate to arithmetic variables
2524
    for (i=0; i<n; i++) {
12✔
2525
      a[i] = internalize_to_arith(ctx, distinct->arg[i]);
9✔
2526
    }
2527
    l = make_arith_distinct(ctx, n, a);
3✔
2528

2529
  } else if (is_bitvector_term(ctx->terms, distinct->arg[0])) {
×
2530
    // translate to bitvector variables
2531
    for (i=0; i<n; i++) {
×
2532
      a[i] = internalize_to_bv(ctx, distinct->arg[i]);
×
2533
    }
2534
    l = make_bv_distinct(ctx, n, a);
×
2535

2536
  } else {
2537
    longjmp(ctx->env, uf_error_code(ctx, distinct->arg[0]));
×
2538
  }
2539

2540
  free_istack_array(&ctx->istack, a);
9✔
2541

2542
  return l;
9✔
2543
}
2544

2545

2546

2547
/*
2548
 * Arithmetic atom: p == 0
2549
 */
2550
static literal_t map_poly_eq_to_literal(context_t *ctx, polynomial_t *p) {
1,192✔
2551
  uint32_t i, n;
2552
  thvar_t *a;
2553
  literal_t l;
2554

2555
  n = p->nterms;
1,192✔
2556
  a = alloc_istack_array(&ctx->istack, n);
1,192✔
2557

2558
  // skip the constant if any
2559
  i = 0;
1,192✔
2560
  if (p->mono[0].var == const_idx) {
1,192✔
2561
    a[0] = null_thvar;
570✔
2562
    i ++;
570✔
2563
  }
2564

2565
  // deal with the non-constant monomials
2566
  while (i<n) {
4,166✔
2567
    a[i] = internalize_to_arith(ctx, p->mono[i].var);
2,974✔
2568
    i ++;
2,974✔
2569
  }
2570

2571
  // build the atom
2572
  l = ctx->arith.create_poly_eq_atom(ctx->arith_solver, p, a);
1,192✔
2573
  free_istack_array(&ctx->istack, a);
1,192✔
2574

2575
  return l;
1,192✔
2576
}
2577

2578

2579
/*
2580
 * Arithmetic atom: (p >= 0)
2581
 */
2582
static literal_t map_poly_ge_to_literal(context_t *ctx, polynomial_t *p) {
33,493✔
2583
  uint32_t i, n;
2584
  thvar_t *a;
2585
  literal_t l;
2586

2587
  n = p->nterms;
33,493✔
2588
  a = alloc_istack_array(&ctx->istack, n);
33,493✔
2589

2590
  // skip the constant if any
2591
  i = 0;
33,493✔
2592
  if (p->mono[0].var == const_idx) {
33,493✔
2593
    a[0] = null_thvar;
26,318✔
2594
    i ++;
26,318✔
2595
  }
2596

2597
  // deal with the non-constant monomials
2598
  while (i<n) {
84,648✔
2599
    a[i] = internalize_to_arith(ctx, p->mono[i].var);
51,155✔
2600
    i ++;
51,155✔
2601
  }
2602

2603
  // build the atom
2604
  l = ctx->arith.create_poly_ge_atom(ctx->arith_solver, p, a);
33,493✔
2605
  free_istack_array(&ctx->istack, a);
33,493✔
2606

2607
  return l;
33,493✔
2608
}
2609

2610

2611
/*
2612
 * Arithmetic atom: (t >= 0)
2613
 */
2614
static literal_t map_arith_geq_to_literal(context_t *ctx, term_t t) {
33,841✔
2615
  term_table_t *terms;
2616
  thvar_t x;
2617
  literal_t l;
2618

2619
  terms = ctx->terms;
33,841✔
2620
  if (term_kind(terms, t) == ARITH_POLY) {
33,841✔
2621
    l = map_poly_ge_to_literal(ctx, poly_term_desc(terms, t));
33,493✔
2622
  } else {
2623
    x = internalize_to_arith(ctx, t);
348✔
2624
    l = ctx->arith.create_ge_atom(ctx->arith_solver, x);
348✔
2625
  }
2626

2627
  return l;
33,841✔
2628
}
2629

2630

2631

2632
/*
2633
 * Arithmetic equalities (eq t1 t2)
2634
 * 1) try to flatten the if-then-elses
2635
 * 2) also apply cheap lift-if rule: (eq (ite c t1 t2) u1) --> (ite c (eq t1 u1) (eq t2 u1))
2636
 */
2637
static literal_t map_arith_bineq(context_t *ctx, term_t t1, term_t u1);
2638

2639
/*
2640
 * Lift equality: (eq (ite c u1 u2) t) --> (ite c (eq u1 t) (eq u2 t))
2641
 */
2642
static literal_t map_ite_arith_bineq(context_t *ctx, composite_term_t *ite, term_t t) {
42,609✔
2643
  literal_t l1, l2, l3;
2644

2645
  assert(ite->arity == 3);
2646
  l1 = internalize_to_literal(ctx, ite->arg[0]);
42,609✔
2647
  if (l1 == true_literal) {
42,609✔
2648
    // (eq (ite true u1 u2) t) --> (eq u1 t)
2649
    return map_arith_bineq(ctx, ite->arg[1], t);
7✔
2650
  }
2651
  if (l1 == false_literal) {
42,602✔
2652
    // (eq (ite true u1 u2) t) --> (eq u2 t)
2653
    return map_arith_bineq(ctx, ite->arg[2], t);
109✔
2654
  }
2655

2656
  // apply lift-if here
2657
  l2 = map_arith_bineq(ctx, ite->arg[1], t);
42,493✔
2658
  l3 = map_arith_bineq(ctx, ite->arg[2], t);
42,493✔
2659

2660
  return mk_ite_gate(&ctx->gate_manager, l1, l2, l3);
42,493✔
2661
}
2662

2663
static literal_t map_arith_bineq_aux(context_t *ctx, term_t t1, term_t t2) {
53,504✔
2664
  term_table_t *terms;
2665
  thvar_t x, y;
2666
  occ_t u, v;
2667
  literal_t l;
2668

2669
  /*
2670
   * Try to apply lift-if rule: (eq (ite c u1 u2) t2) --> (ite c (eq u1 t2) (eq u2 t2))
2671
   * do this only if t2 is not an if-then-else term.
2672
   *
2673
   * Otherwise add the atom (eq t1 t2) to the egraph if possible
2674
   * or create (eq t1 t2) in the arithmetic solver.
2675
   */
2676
  terms = ctx->terms;
53,504✔
2677
  if (is_ite_term(terms, t1) && ! is_ite_term(terms, t2)) {
53,504✔
2678
    l = map_ite_arith_bineq(ctx, ite_term_desc(terms, t1), t2);
38,573✔
2679
  } else if (is_ite_term(terms, t2) && !is_ite_term(terms, t1)) {
14,931✔
2680
    l = map_ite_arith_bineq(ctx, ite_term_desc(terms, t2), t1);
4,036✔
2681
  } else if (context_has_egraph(ctx)) {
10,895✔
2682
    u = internalize_to_eterm(ctx, t1);
3,774✔
2683
    v = internalize_to_eterm(ctx, t2);
3,774✔
2684
    l = egraph_make_eq(ctx->egraph, u, v);
3,774✔
2685
  } else {
2686
    x = internalize_to_arith(ctx, t1);
7,121✔
2687
    y = internalize_to_arith(ctx, t2);
7,121✔
2688
    l = ctx->arith.create_vareq_atom(ctx->arith_solver, x, y);
7,121✔
2689
  }
2690

2691
  return l;
53,504✔
2692
}
2693

2694
static literal_t map_arith_bineq(context_t *ctx, term_t t1, term_t u1) {
95,361✔
2695
  ivector_t *v;
2696
  int32_t *a;
2697
  uint32_t i, n;
2698
  term_t t2, u2;
2699
  literal_t l;
2700

2701
  t1 = intern_tbl_get_root(&ctx->intern, t1);
95,361✔
2702
  u1 = intern_tbl_get_root(&ctx->intern, u1);
95,361✔
2703

2704
  if (t1 == u1) {
95,361✔
2705
    return true_literal;
3,222✔
2706
  }
2707

2708
  /*
2709
   * Check the cache
2710
   */
2711
  l = find_in_eq_cache(ctx, t1, u1);
92,139✔
2712
  if (l == null_literal) {
92,139✔
2713
    /*
2714
     * The pair (t1, u1) is not mapped already.
2715
     * Try to flatten the if-then-else equalities
2716
     */
2717
    v = &ctx->aux_vector;
53,431✔
2718
    assert(v->size == 0);
2719
    t2 = flatten_ite_equality(ctx, v, t1, u1);
53,431✔
2720
    u2 = flatten_ite_equality(ctx, v, u1, t2);
53,431✔
2721

2722
    /*
2723
     * (t1 == u1) is equivalent to (and (t2 == u2) v[0] ... v[n-1])
2724
     * where v[i] = element i of v
2725
     */
2726
    n = v->size;
53,431✔
2727
    if (n == 0) {
53,431✔
2728
      // empty v: return (t2 == u2)
2729
      assert(t1 == t2 && u1 == u2);
2730
      l = map_arith_bineq_aux(ctx, t2, u2);
10,680✔
2731

2732
    } else {
2733
      // build (and (t2 == u2) v[0] ... v[n-1])
2734
      // first make a copy of v into a[0 .. n-1]
2735
      a = alloc_istack_array(&ctx->istack, n+1);
42,751✔
2736
      for (i=0; i<n; i++) {
766,594✔
2737
        a[i] = v->data[i];
723,843✔
2738
      }
2739
      ivector_reset(v);
42,751✔
2740

2741
      // build the internalization of a[0 .. n-1]
2742
      for (i=0; i<n; i++) {
766,594✔
2743
        a[i] = internalize_to_literal(ctx, a[i]);
723,843✔
2744
      }
2745
      a[n] = map_arith_bineq_aux(ctx, t2, u2);
42,751✔
2746

2747
      // build (and a[0] ... a[n])
2748
      l = mk_and_gate(&ctx->gate_manager, n+1, a);
42,751✔
2749
      free_istack_array(&ctx->istack, a);
42,751✔
2750
    }
2751

2752
    /*
2753
     * Store the mapping (t1, u1) --> l in the cache
2754
     */
2755
    add_to_eq_cache(ctx, t1, u1, l);
53,431✔
2756
  }
2757

2758
  return l;
92,139✔
2759
}
2760

2761

2762
static inline literal_t map_arith_bineq_to_literal(context_t *ctx, composite_term_t *eq) {
8,967✔
2763
  assert(eq->arity == 2);
2764
  return map_arith_bineq(ctx, eq->arg[0], eq->arg[1]);
8,967✔
2765
}
2766

2767

2768

2769
/*
2770
 * Arithmetic atom: (t == 0)
2771
 */
2772
static literal_t map_arith_eq_to_literal(context_t *ctx, term_t t) {
2,249✔
2773
  term_table_t *terms;
2774
  thvar_t x;
2775
  literal_t l;
2776

2777
  terms = ctx->terms;
2,249✔
2778
  if (term_kind(terms, t) == ARITH_POLY) {
2,249✔
2779
    l = map_poly_eq_to_literal(ctx, poly_term_desc(terms, t));
1,192✔
2780
  } else if (is_ite_term(terms, t)) {
1,057✔
2781
    l = map_arith_bineq(ctx, t, zero_term);
426✔
2782
  } else {
2783
    x = internalize_to_arith(ctx, t);
631✔
2784
    l = ctx->arith.create_eq_atom(ctx->arith_solver, x);
631✔
2785
  }
2786
  return l;
2,249✔
2787
}
2788

2789

2790
/*
2791
 * DIVIDES AND IS_INT ATOMS
2792
 */
2793

2794
/*
2795
 * We use the rules
2796
 * - (is_int x)    <=> (x <= floor(x))
2797
 * - (divides k x) <=> (x <= k * div(x, k))
2798
 */
2799

2800
// atom (is_int t)
2801
static literal_t map_arith_is_int_to_literal(context_t *ctx, term_t t) {
×
2802
  polynomial_t *p;
2803
  thvar_t map[2];
2804
  thvar_t x, y;
2805
  literal_t l;
2806

2807
  x = internalize_to_arith(ctx, t);
×
2808
  if (ctx->arith.arith_var_is_int(ctx->arith_solver, x)) {
×
2809
    l = true_literal;
×
2810
  } else {
2811
    // we convert (is_int x) to (x <= floor(x))
2812
    y = get_floor(ctx, x); // y is floor x
×
2813
    p = context_get_aux_poly(ctx, 3);
×
2814
    context_store_diff_poly(p, map, y, x); // (p, map) := (y - x)
×
2815
    // atom (x <= y) is the same as (p >= 0)
2816
    l = ctx->arith.create_poly_ge_atom(ctx->arith_solver, p, map);
×
2817
  }
2818

2819
  return l;
×
2820
}
2821

2822
// atom (divides k t)  we assume k != 0
2823
static literal_t map_arith_divides_to_literal(context_t *ctx, composite_term_t *divides) {
8✔
2824
  rational_t k;
2825
  polynomial_t *p;
2826
  thvar_t map[2];
2827
  thvar_t x, y;
2828
  term_t d;
2829
  literal_t l;
2830

2831
  assert(divides->arity == 2);
2832

2833
  d = divides->arg[0];
8✔
2834
  if (term_kind(ctx->terms, d) == ARITH_CONSTANT) {
8✔
2835
    // make a copy of divides->arg[0] in k
2836
    q_init(&k);
8✔
2837
    q_set(&k, rational_term_desc(ctx->terms, d));
8✔
2838
    assert(q_is_nonzero(&k));
2839

2840
    x = internalize_to_arith(ctx, divides->arg[1]); // this is t
8✔
2841
    y = get_div(ctx, x, &k);  // y := (div x k)
8✔
2842
    p = context_get_aux_poly(ctx, 3);
8✔
2843
    context_store_divides_constraint(p, map, x, y, &k); // p is (- x + k * y)
8✔
2844
    // atom (x <= k * y) is (p >= 0)
2845
    l = ctx->arith.create_poly_ge_atom(ctx->arith_solver, p, map);
8✔
2846

2847
    q_clear(&k);
8✔
2848

2849
    return l;
8✔
2850

2851
  } else {
2852
    // k is not a constant: not supported
2853
    longjmp(ctx->env, FORMULA_NOT_LINEAR);
×
2854
  }
2855
}
2856

2857

2858
/*
2859
 * BITVECTOR ATOMS
2860
 */
2861

2862
/*
2863
 * Auxiliary function: atom for (t == 0)
2864
 */
2865
static literal_t map_bveq0_to_literal(context_t *ctx, term_t t) {
10✔
2866
  uint32_t n;
2867
  thvar_t x, y;
2868

2869
  t = intern_tbl_get_root(&ctx->intern, t);
10✔
2870
  n = term_bitsize(ctx->terms, t);
10✔
2871
  x = internalize_to_bv(ctx, t);
10✔
2872
  y = ctx->bv.create_zero(ctx->bv_solver, n);
10✔
2873

2874
  return ctx->bv.create_eq_atom(ctx->bv_solver, x, y);
10✔
2875
}
2876

2877
static literal_t map_bveq_to_literal(context_t *ctx, composite_term_t *eq) {
4,864✔
2878
  bveq_simp_t simp;
2879
  term_t t, t1, t2;
2880
  thvar_t x, y;
2881

2882
  assert(eq->arity == 2);
2883

2884
  /*
2885
   * Apply substitution then check for simplifications
2886
   */
2887
  t1 = intern_tbl_get_root(&ctx->intern, eq->arg[0]);
4,864✔
2888
  t2 = intern_tbl_get_root(&ctx->intern, eq->arg[1]);
4,864✔
2889
  t = simplify_bitvector_eq(ctx, t1, t2);
4,864✔
2890
  if (t != NULL_TERM) {
4,864✔
2891
    // (bveq t1 t2) is equivalent to t
2892
    return internalize_to_literal(ctx, t);
77✔
2893
  }
2894

2895
  /*
2896
   * More simplifications
2897
   */
2898
  try_arithmetic_bveq_simplification(ctx, &simp, t1, t2);
4,787✔
2899
  switch (simp.code) {
4,787✔
2900
  case BVEQ_CODE_TRUE:
×
2901
    return true_literal;
×
2902

2903
  case BVEQ_CODE_FALSE:
×
2904
    return false_literal;
×
2905

2906
  case BVEQ_CODE_REDUCED:
11✔
2907
    t1 = intern_tbl_get_root(&ctx->intern, simp.left);
11✔
2908
    t2 = intern_tbl_get_root(&ctx->intern, simp.right);
11✔
2909
    break;
11✔
2910

2911
  case BVEQ_CODE_REDUCED0:
10✔
2912
    // (t1 == t2) is reduced to (simp.left == 0)
2913
    // we create the atom directly here:
2914
    return map_bveq0_to_literal(ctx, simp.left);
10✔
2915

2916
  default:
4,766✔
2917
    break;
4,766✔
2918
  }
2919

2920
  if (equal_bitvector_factors(ctx, t1, t2)) {
4,777✔
2921
    return true_literal;
×
2922
  }
2923

2924
  /*
2925
   * NOTE: creating (eq t1 t2) in the egraph instead makes things worse
2926
   */
2927
  x = internalize_to_bv(ctx, t1);
4,777✔
2928
  y = internalize_to_bv(ctx, t2);
4,777✔
2929
  return ctx->bv.create_eq_atom(ctx->bv_solver, x, y);
4,777✔
2930
}
2931

2932
static literal_t map_bvge_to_literal(context_t *ctx, composite_term_t *ge) {
2,302✔
2933
  thvar_t x, y;
2934

2935
  assert(ge->arity == 2);
2936
  x = internalize_to_bv(ctx, ge->arg[0]);
2,302✔
2937
  y = internalize_to_bv(ctx, ge->arg[1]);
2,302✔
2938

2939
  return ctx->bv.create_ge_atom(ctx->bv_solver, x, y);
2,302✔
2940
}
2941

2942
static literal_t map_bvsge_to_literal(context_t *ctx, composite_term_t *sge) {
2,907✔
2943
  thvar_t x, y;
2944

2945
  assert(sge->arity == 2);
2946
  x = internalize_to_bv(ctx, sge->arg[0]);
2,907✔
2947
  y = internalize_to_bv(ctx, sge->arg[1]);
2,907✔
2948

2949
  return ctx->bv.create_sge_atom(ctx->bv_solver, x, y);
2,907✔
2950
}
2951

2952

2953
// Select bit
2954
static literal_t map_bit_select_to_literal(context_t *ctx, select_term_t *select) {
264,128✔
2955
  term_t t, s;
2956
  thvar_t x;
2957

2958
  /*
2959
   * Apply substitution then try to simplify
2960
   */
2961
  t = intern_tbl_get_root(&ctx->intern, select->arg);
264,128✔
2962
  s = extract_bit(ctx->terms, t, select->idx);
264,128✔
2963
  if (s != NULL_TERM) {
264,128✔
2964
    // (select t i) is s
2965
    return internalize_to_literal(ctx, s);
25,181✔
2966
  } else {
2967
    // no simplification
2968
    x = internalize_to_bv(ctx, t);
238,947✔
2969
    return ctx->bv.select_bit(ctx->bv_solver, x, select->idx);
238,947✔
2970
  }
2971
}
2972

2973

2974
/****************************************
2975
 *  INTERNALIZATION TO ETERM: TOPLEVEL  *
2976
 ***************************************/
2977

2978
static occ_t internalize_to_eterm(context_t *ctx, term_t t) {
103,355✔
2979
  term_table_t *terms;
2980
  term_t root;
2981
  term_t r;
2982
  uint32_t polarity;
2983
  int32_t code;
2984
  int32_t exception;
2985
  type_t tau;
2986
  occ_t u;
2987
  literal_t l;
2988
  thvar_t x;
2989

2990
  if (! context_has_egraph(ctx)) {
103,355✔
2991
    exception = uf_error_code(ctx, t);
×
2992
    goto abort;
×
2993
  }
2994

2995
  root = intern_tbl_get_root(&ctx->intern, t);
103,355✔
2996
  polarity = polarity_of(root);
103,355✔
2997
  root = unsigned_term(root);
103,355✔
2998
  r = root;
103,355✔
2999

3000
  /*
3001
   * r is a positive root in the internalization table
3002
   * polarity is 0 or 1
3003
   * if polarity is 0, then t is equal to r by substitution
3004
   * if polarity is 1, then t is equal to (not r)
3005
   */
3006
  if (intern_tbl_root_is_mapped(&ctx->intern, r)) {
103,355✔
3007
    /*
3008
     * r already internalized
3009
     */
3010
    code = intern_tbl_map_of_root(&ctx->intern, r);
64,981✔
3011
    u = translate_code_to_eterm(ctx, r, code);
64,981✔
3012
  } else {
3013
    /*
3014
     * Compute r's internalization:
3015
     * - if it's a boolean term, convert r to a literal l then
3016
     *   remap l to an egraph term
3017
     * - otherwise, recursively construct an egraph term and map it to r
3018
     */
3019
    terms = ctx->terms;
38,374✔
3020
    tau = type_of_root(ctx, r);
38,374✔
3021
    if (is_unit_type(ctx->types, tau)) {
38,374✔
3022
      // Canonicalize singleton types to one representative term.
3023
      r = get_unit_type_rep(terms, tau);
7✔
3024
      r = intern_tbl_get_root(&ctx->intern, r);
7✔
3025
      r = unsigned_term(r);
7✔
3026
      assert(is_pos_term(r) && intern_tbl_is_root(&ctx->intern, r));
3027
      if (intern_tbl_root_is_mapped(&ctx->intern, r)) {
7✔
3028
        code = intern_tbl_map_of_root(&ctx->intern, r);
1✔
3029
        u = translate_code_to_eterm(ctx, r, code);
1✔
3030
        if (root != r) {
1✔
3031
          if (intern_tbl_root_is_free(&ctx->intern, root)) {
1✔
3032
            intern_tbl_map_root(&ctx->intern, root, occ2code(u));
1✔
3033
          } else {
3034
            // If root is already mapped, it must map to the same egraph
3035
            // occurrence we are about to return for the unit-type rep.
3036
            assert(intern_tbl_map_of_root(&ctx->intern, root) == occ2code(u));  // LCOV_EXCL_LINE - consistency check, unreachable on well-formed inputs
3037
          }
3038
        }
3039
        return u ^ polarity;
1✔
3040
      }
3041
    }
3042

3043
    if (is_boolean_type(tau)) {
38,373✔
3044
      l = internalize_to_literal(ctx, r);
38✔
3045
      u = egraph_literal2occ(ctx->egraph, l);
38✔
3046
      intern_tbl_remap_root(&ctx->intern, r, occ2code(u));
38✔
3047
    } else {
3048
      /*
3049
       * r is not a boolean term
3050
       */
3051
      assert(polarity == 0);
3052

3053
      switch (term_kind(terms, r)) {
38,335✔
3054
      case CONSTANT_TERM:
1,164✔
3055
        u = pos_occ(make_egraph_constant(ctx, tau, constant_term_index(terms, r)));
1,164✔
3056
        break;
1,164✔
3057

3058
      case ARITH_CONSTANT:
339✔
3059
        u = map_arith_constant_to_eterm(ctx, rational_term_desc(terms, r));
339✔
3060
        break;
339✔
3061

3062
      case BV64_CONSTANT:
808✔
3063
        u = map_bvconst64_to_eterm(ctx, bvconst64_term_desc(terms, r));
808✔
3064
        break;
808✔
3065

3066
      case BV_CONSTANT:
18✔
3067
        u = map_bvconst_to_eterm(ctx, bvconst_term_desc(terms, r));
18✔
3068
        break;
18✔
3069

3070
      case VARIABLE:
×
3071
        exception = FREE_VARIABLE_IN_FORMULA;
×
3072
        goto abort;
×
3073

3074
      case UNINTERPRETED_TERM:
12,051✔
3075
        u = pos_occ(make_egraph_variable(ctx, tau));
12,051✔
3076
        //        add_type_constraints(ctx, u, tau);
3077
        break;
12,051✔
3078

3079
      case ARITH_FLOOR:
×
3080
        assert(is_integer_type(tau));
3081
        x = map_floor_to_arith(ctx, arith_floor_arg(terms, r));
×
3082
        u = translate_arithvar_to_eterm(ctx, x);
×
3083
        break;
×
3084

3085
      case ARITH_CEIL:
×
3086
        assert(is_integer_type(tau));
3087
        x = map_ceil_to_arith(ctx, arith_ceil_arg(terms, r));
×
3088
        u = translate_arithvar_to_eterm(ctx, x);
×
3089
        break;
×
3090

3091
      case ARITH_ABS:
×
3092
        x = map_abs_to_arith(ctx, arith_abs_arg(terms, r));
×
3093
        u = translate_arithvar_to_eterm(ctx, x);
×
3094
        break;
×
3095

3096
      case ITE_TERM:
2,168✔
3097
      case ITE_SPECIAL:
3098
        u = map_ite_to_eterm(ctx, ite_term_desc(terms, r), tau);
2,168✔
3099
        break;
2,168✔
3100

3101
      case APP_TERM:
6,531✔
3102
        u = map_apply_to_eterm(ctx, app_term_desc(terms, r), tau);
6,531✔
3103
        break;
6,531✔
3104

3105
      case ARITH_RDIV:
×
3106
        assert(is_arithmetic_type(tau));
3107
        x = map_rdiv_to_arith(ctx, arith_rdiv_term_desc(terms, r));
×
3108
        u = translate_arithvar_to_eterm(ctx, x);
×
3109
        break;
×
3110

3111
      case ARITH_IDIV:
×
3112
        assert(is_integer_type(tau));
3113
        x = map_idiv_to_arith(ctx, arith_idiv_term_desc(terms, r));
×
3114
        u = translate_arithvar_to_eterm(ctx, x); // (div t u) has type int
×
3115
        break;
×
3116

3117
      case ARITH_MOD:
2✔
3118
        x = map_mod_to_arith(ctx, arith_mod_term_desc(terms, r));
2✔
3119
        u = translate_arithvar_to_eterm(ctx, x);
2✔
3120
        break;
2✔
3121

3122
      case TUPLE_TERM:
190✔
3123
        u = map_tuple_to_eterm(ctx, tuple_term_desc(terms, r), tau);
190✔
3124
        break;
190✔
3125

3126
      case SELECT_TERM:
245✔
3127
        u = map_select_to_eterm(ctx, select_term_desc(terms, r), tau);
245✔
3128
        break;
245✔
3129

3130
      case UPDATE_TERM:
11,470✔
3131
        u = map_update_to_eterm(ctx, update_term_desc(terms, r), tau);
11,470✔
3132
        break;
11,470✔
3133

3134
      case LAMBDA_TERM:
1✔
3135
        // not ready for lambda terms yet:
3136
        exception = LAMBDAS_NOT_SUPPORTED;
1✔
3137
        goto abort;
1✔
3138

3139
      case BV_ARRAY:
1,711✔
3140
        x = map_bvarray_to_bv(ctx, bvarray_term_desc(terms, r));
1,711✔
3141
        u = translate_thvar_to_eterm(ctx, x, tau);
1,711✔
3142
        break;
1,711✔
3143

3144
      case BV_DIV:
1✔
3145
        x = map_bvdiv_to_bv(ctx, bvdiv_term_desc(terms, r));
1✔
3146
        u = translate_thvar_to_eterm(ctx, x, tau);
1✔
3147
        break;
1✔
3148

3149
      case BV_REM:
2✔
3150
        x = map_bvrem_to_bv(ctx, bvrem_term_desc(terms, r));
2✔
3151
        u = translate_thvar_to_eterm(ctx, x, tau);
2✔
3152
        break;
2✔
3153

3154
      case BV_SDIV:
1✔
3155
        x = map_bvsdiv_to_bv(ctx, bvsdiv_term_desc(terms, r));
1✔
3156
        u = translate_thvar_to_eterm(ctx, x, tau);
1✔
3157
        break;
1✔
3158

3159
      case BV_SREM:
1✔
3160
        x = map_bvsrem_to_bv(ctx, bvsrem_term_desc(terms, r));
1✔
3161
        u = translate_thvar_to_eterm(ctx, x, tau);
1✔
3162
        break;
1✔
3163

3164
      case BV_SMOD:
×
3165
        x = map_bvsmod_to_bv(ctx, bvsmod_term_desc(terms, r));
×
3166
        u = translate_thvar_to_eterm(ctx, x, tau);
×
3167
        break;
×
3168

3169
      case BV_SHL:
×
3170
        x = map_bvshl_to_bv(ctx, bvshl_term_desc(terms, r));
×
3171
        u = translate_thvar_to_eterm(ctx, x, tau);
×
3172
        break;
×
3173

3174
      case BV_LSHR:
1✔
3175
        x = map_bvlshr_to_bv(ctx, bvlshr_term_desc(terms, r));
1✔
3176
        u = translate_thvar_to_eterm(ctx, x, tau);
1✔
3177
        break;
1✔
3178

3179
      case BV_ASHR:
1✔
3180
        x = map_bvashr_to_bv(ctx, bvashr_term_desc(terms, r));
1✔
3181
        u = translate_thvar_to_eterm(ctx, x, tau);
1✔
3182
        break;
1✔
3183

3184
      case POWER_PRODUCT:
1✔
3185
        if (is_arithmetic_type(tau)) {
1✔
3186
          x = map_pprod_to_arith(ctx, pprod_term_desc(terms, r));
×
3187
        } else {
3188
          assert(is_bv_type(ctx->types, tau));
3189
          x = map_pprod_to_bv(ctx, pprod_term_desc(terms, r));
1✔
3190
        }
3191
        u = translate_thvar_to_eterm(ctx, x, tau);
1✔
3192
        break;
1✔
3193

3194
      case ARITH_POLY:
619✔
3195
        x = map_poly_to_arith(ctx, poly_term_desc(terms, r));
619✔
3196
        u = translate_thvar_to_eterm(ctx, x, tau);
619✔
3197
        break;
619✔
3198

3199
      case BV64_POLY:
1,008✔
3200
        x = map_bvpoly64_to_bv(ctx, bvpoly64_term_desc(terms, r));
1,008✔
3201
        u = translate_thvar_to_eterm(ctx, x, tau);
1,008✔
3202
        break;
1,008✔
3203

3204
      case BV_POLY:
2✔
3205
        x = map_bvpoly_to_bv(ctx, bvpoly_term_desc(terms, r));
2✔
3206
        u = translate_thvar_to_eterm(ctx, x, tau);
2✔
3207
        break;
2✔
3208

3209
      default:
×
3210
        exception = INTERNAL_ERROR;
×
3211
        goto abort;
×
3212
      }
3213

3214
      // store the mapping r --> u
3215
      intern_tbl_map_root(&ctx->intern, r, occ2code(u));
38,334✔
3216
    }
3217
  }
3218

3219
  // If we canonicalized root to a different unit-type representative r,
3220
  // remember that root internalizes to the same egraph occurrence.
3221
  if (root != r) {
103,353✔
3222
    if (intern_tbl_root_is_free(&ctx->intern, root)) {
1✔
3223
      intern_tbl_map_root(&ctx->intern, root, occ2code(u));
1✔
3224
    } else {
3225
      // If root was mapped during the recursive internalization of r (e.g.,
3226
      // because root was reached as a sub-term), the mapping must agree
3227
      // with the occurrence we are about to return.
3228
      assert(intern_tbl_map_of_root(&ctx->intern, root) == occ2code(u));  // LCOV_EXCL_LINE - consistency check, unreachable on well-formed inputs
3229
    }
3230
  }
3231

3232
  // fix the polarity
3233
  return u ^ polarity;
103,353✔
3234

3235
 abort:
1✔
3236
  longjmp(ctx->env, exception);
1✔
3237
}
3238

3239

3240

3241

3242
/****************************************
3243
 *  CONVERSION TO ARITHMETIC VARIABLES  *
3244
 ***************************************/
3245

3246
/*
3247
 * Translate internalization code x to an arithmetic variable
3248
 * - if the code is for an egraph term u, then we return the
3249
 *   theory variable attached to u in the egraph.
3250
 * - otherwise, x must be the code of an arithmetic variable v,
3251
 *   we return v.
3252
 */
3253
static thvar_t translate_code_to_arith(context_t *ctx, int32_t x) {
99,879✔
3254
  eterm_t u;
3255
  thvar_t v;
3256

3257
  assert(code_is_valid(x));
3258

3259
  if (code_is_eterm(x)) {
99,879✔
3260
    u = code2eterm(x);
6,521✔
3261
    assert(ctx->egraph != NULL && egraph_term_is_arith(ctx->egraph, u));
3262
    v = egraph_term_base_thvar(ctx->egraph, u);
6,521✔
3263
  } else {
3264
    v = code2thvar(x);
93,358✔
3265
  }
3266

3267
  assert(v != null_thvar);
3268
  return v;
99,879✔
3269
}
3270

3271

3272
static thvar_t internalize_to_arith(context_t *ctx, term_t t) {
120,786✔
3273
  term_table_t *terms;
3274
  int32_t exception;
3275
  int32_t code;
3276
  term_t r;
3277
  occ_t u;
3278
  thvar_t x;
3279

3280
  assert(is_arithmetic_term(ctx->terms, t));
3281

3282
  if (! context_has_arith_solver(ctx)) {
120,786✔
3283
    exception = ARITH_NOT_SUPPORTED;
×
3284
    goto abort;
×
3285
  }
3286

3287
  /*
3288
   * Apply term substitution: t --> r
3289
   */
3290
  r = intern_tbl_get_root(&ctx->intern, t);
120,786✔
3291
  if (intern_tbl_root_is_mapped(&ctx->intern, r)) {
120,786✔
3292
    /*
3293
     * r already internalized
3294
     */
3295
    code = intern_tbl_map_of_root(&ctx->intern, r);
99,720✔
3296
    x = translate_code_to_arith(ctx, code);
99,720✔
3297

3298
  } else {
3299
    /*
3300
     * Compute the internalization
3301
     */
3302
    terms = ctx->terms;
21,066✔
3303

3304
    switch (term_kind(terms, r)) {
21,066✔
3305
    case ARITH_CONSTANT:
1,270✔
3306
      x = ctx->arith.create_const(ctx->arith_solver, rational_term_desc(terms, r));
1,270✔
3307
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
1,270✔
3308
      break;
1,270✔
3309

3310
    case UNINTERPRETED_TERM:
15,371✔
3311
      x = ctx->arith.create_var(ctx->arith_solver, is_integer_root(ctx, r));
15,371✔
3312
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
15,371✔
3313
      //      printf("mapping: %s --> i!%d\n", term_name(ctx->terms, r), (int) x);
3314
      //      fflush(stdout);
3315
      break;
15,371✔
3316

3317
    case ARITH_FLOOR:
×
3318
      x = map_floor_to_arith(ctx, arith_floor_arg(terms, r));
×
3319
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
×
3320
      break;
×
3321

3322
    case ARITH_CEIL:
×
3323
      x = map_ceil_to_arith(ctx, arith_ceil_arg(terms, r));
×
3324
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
×
3325
      break;
×
3326

3327
    case ARITH_ABS:
4✔
3328
      x = map_abs_to_arith(ctx, arith_abs_arg(terms, r));
4✔
3329
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
4✔
3330
      break;
4✔
3331

3332
    case ITE_TERM:
2,230✔
3333
      x = map_ite_to_arith(ctx, ite_term_desc(terms, r), is_integer_root(ctx, r));
2,230✔
3334
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
2,230✔
3335
      break;
2,230✔
3336

3337
    case ITE_SPECIAL:
793✔
3338
      x = map_ite_to_arith(ctx, ite_term_desc(terms, r), is_integer_root(ctx, r));
793✔
3339
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
793✔
3340
      if (context_ite_bounds_enabled(ctx)) {
793✔
3341
        assert_ite_bounds(ctx, r, x);
793✔
3342
      }
3343
      break;
793✔
3344

3345
    case APP_TERM:
702✔
3346
      u = map_apply_to_eterm(ctx, app_term_desc(terms, r), type_of_root(ctx, r));
702✔
3347
      assert(egraph_term_is_arith(ctx->egraph, term_of_occ(u)));
3348
      intern_tbl_map_root(&ctx->intern, r, occ2code(u));
702✔
3349
      x = egraph_term_base_thvar(ctx->egraph, term_of_occ(u));
702✔
3350
      assert(x != null_thvar);
3351
      break;
702✔
3352

3353
    case ARITH_RDIV:
3✔
3354
      x = map_rdiv_to_arith(ctx, arith_rdiv_term_desc(terms, r));
3✔
3355
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
×
3356
      break;
×
3357

3358
    case ARITH_IDIV:
6✔
3359
      x = map_idiv_to_arith(ctx, arith_idiv_term_desc(terms, r));
6✔
3360
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
6✔
3361
      break;
6✔
3362

3363
    case ARITH_MOD:
9✔
3364
      x = map_mod_to_arith(ctx, arith_mod_term_desc(terms, r));
9✔
3365
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
9✔
3366
      break;
9✔
3367

3368
    case SELECT_TERM:
×
3369
      u = map_select_to_eterm(ctx, select_term_desc(terms, r), type_of_root(ctx, r));
×
3370
      assert(egraph_term_is_arith(ctx->egraph, term_of_occ(u)));
3371
      intern_tbl_map_root(&ctx->intern, r, occ2code(u));
×
3372
      x = egraph_term_base_thvar(ctx->egraph, term_of_occ(u));
×
3373
      assert(x != null_thvar);
3374
      break;
×
3375

3376
    case POWER_PRODUCT:
×
3377
      x = map_pprod_to_arith(ctx, pprod_term_desc(terms, r));
×
3378
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
×
3379
      break;
×
3380

3381
    case ARITH_POLY:
678✔
3382
      x = map_poly_to_arith(ctx, poly_term_desc(terms, r));
678✔
3383
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
678✔
3384
      break;
678✔
3385

3386
    case VARIABLE:
×
3387
      exception = FREE_VARIABLE_IN_FORMULA;
×
3388
      goto abort;
×
3389

3390
    default:
×
3391
      exception = INTERNAL_ERROR;
×
3392
      goto abort;
×
3393
    }
3394

3395
  }
3396

3397
  if (ctx->mcsat_supplement_active) {
120,783✔
3398
    mcsat_satellite_t *sat;
NEW
3399
    sat = context_mcsat_satellite(ctx);
×
NEW
3400
    if (sat != NULL) {
×
NEW
3401
      mcsat_satellite_register_arith_term(sat, x, unsigned_term(r));
×
3402
    }
3403
  }
3404

3405
  return x;
120,783✔
3406

3407
 abort:
×
3408
  longjmp(ctx->env, exception);
×
3409
}
3410

3411

3412

3413
/***************************************
3414
 *  CONVERSION TO BITVECTOR VARIABLES  *
3415
 **************************************/
3416

3417
/*
3418
 * Translate internalization code x to a bitvector variable
3419
 * - if x is for an egraph term u, then we return the theory variable
3420
 *   attached to u in the egraph.
3421
 * - otherwise, x must be the code of a bitvector variable v, so we return v.
3422
 */
3423
static thvar_t translate_code_to_bv(context_t *ctx, int32_t x) {
299,052✔
3424
  eterm_t u;
3425
  thvar_t v;
3426

3427
  assert(code_is_valid(x));
3428

3429
  if (code_is_eterm(x)) {
299,052✔
3430
    u = code2eterm(x);
29,164✔
3431
    assert(ctx->egraph != NULL && egraph_term_is_bv(ctx->egraph, u));
3432
    v = egraph_term_base_thvar(ctx->egraph, u);
29,164✔
3433
  } else {
3434
    v = code2thvar(x);
269,888✔
3435
  }
3436

3437
  assert(v != null_thvar);
3438

3439
  return v;
299,052✔
3440
}
3441

3442
/*
3443
 * Place holders for now
3444
 */
3445
static thvar_t internalize_to_bv(context_t *ctx, term_t t) {
375,945✔
3446
  term_table_t *terms;
3447
  int32_t exception;
3448
  int32_t code;
3449
  term_t r;
3450
  occ_t u;
3451
  thvar_t x;
3452

3453
  assert(is_bitvector_term(ctx->terms, t));
3454

3455
  if (! context_has_bv_solver(ctx)) {
375,945✔
3456
    exception = BV_NOT_SUPPORTED;
×
3457
    goto abort;
×
3458
  }
3459

3460
  /*
3461
   * Apply the term substitution: t --> r
3462
   */
3463
  r = intern_tbl_get_root(&ctx->intern, t);
375,945✔
3464
  if (intern_tbl_root_is_mapped(&ctx->intern, r)) {
375,945✔
3465
    // r is already internalized
3466
    code = intern_tbl_map_of_root(&ctx->intern, r);
299,052✔
3467
    x = translate_code_to_bv(ctx, code);
299,052✔
3468
  } else {
3469
    // compute r's internalization
3470
    terms = ctx->terms;
76,893✔
3471

3472
    switch (term_kind(terms, r)) {
76,893✔
3473
    case BV64_CONSTANT:
6,999✔
3474
      x = ctx->bv.create_const64(ctx->bv_solver, bvconst64_term_desc(terms, r));
6,999✔
3475
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
6,999✔
3476
      break;
6,999✔
3477

3478
    case BV_CONSTANT:
440✔
3479
      x = ctx->bv.create_const(ctx->bv_solver, bvconst_term_desc(terms, r));
440✔
3480
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
440✔
3481
      break;
440✔
3482

3483
    case UNINTERPRETED_TERM:
16,390✔
3484
      x = ctx->bv.create_var(ctx->bv_solver, term_bitsize(terms, r));
16,390✔
3485
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
16,390✔
3486
      break;
16,390✔
3487

3488
    case ITE_TERM:
20,779✔
3489
    case ITE_SPECIAL:
3490
      x = map_ite_to_bv(ctx, ite_term_desc(terms, r));
20,779✔
3491
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
20,779✔
3492
      break;
20,779✔
3493

3494
    case APP_TERM:
2,452✔
3495
      u = map_apply_to_eterm(ctx, app_term_desc(terms, r), type_of_root(ctx, r));
2,452✔
3496
      assert(egraph_term_is_bv(ctx->egraph, term_of_occ(u)));
3497
      intern_tbl_map_root(&ctx->intern, r, occ2code(u));
2,452✔
3498
      x = egraph_term_base_thvar(ctx->egraph, term_of_occ(u));
2,452✔
3499
      assert(x != null_thvar);
3500
      break;
2,452✔
3501

3502
    case BV_ARRAY:
15,283✔
3503
      x = map_bvarray_to_bv(ctx, bvarray_term_desc(terms, r));
15,283✔
3504
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
15,283✔
3505
      break;
15,283✔
3506

3507
    case BV_DIV:
96✔
3508
      x = map_bvdiv_to_bv(ctx, bvdiv_term_desc(terms, r));
96✔
3509
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
96✔
3510
      break;
96✔
3511

3512
    case BV_REM:
146✔
3513
      x = map_bvrem_to_bv(ctx, bvrem_term_desc(terms, r));
146✔
3514
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
146✔
3515
      break;
146✔
3516

3517
    case BV_SDIV:
86✔
3518
      x = map_bvsdiv_to_bv(ctx, bvsdiv_term_desc(terms, r));
86✔
3519
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
86✔
3520
      break;
86✔
3521

3522
    case BV_SREM:
77✔
3523
      x = map_bvsrem_to_bv(ctx, bvsrem_term_desc(terms, r));
77✔
3524
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
77✔
3525
      break;
77✔
3526

3527
    case BV_SMOD:
×
3528
      x = map_bvsmod_to_bv(ctx, bvsmod_term_desc(terms, r));
×
3529
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
×
3530
      break;
×
3531

3532
    case BV_SHL:
85✔
3533
      x = map_bvshl_to_bv(ctx, bvshl_term_desc(terms, r));
85✔
3534
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
85✔
3535
      break;
85✔
3536

3537
    case BV_LSHR:
1,427✔
3538
      x = map_bvlshr_to_bv(ctx, bvlshr_term_desc(terms, r));
1,427✔
3539
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
1,427✔
3540
      break;
1,427✔
3541

3542
    case BV_ASHR:
295✔
3543
      x = map_bvashr_to_bv(ctx, bvashr_term_desc(terms, r));
295✔
3544
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
295✔
3545
      break;
295✔
3546

3547
    case SELECT_TERM:
×
3548
      u = map_select_to_eterm(ctx, select_term_desc(terms, r), type_of_root(ctx, r));
×
3549
      assert(egraph_term_is_bv(ctx->egraph, term_of_occ(u)));
3550
      intern_tbl_map_root(&ctx->intern, r, occ2code(u));
×
3551
      x = egraph_term_base_thvar(ctx->egraph, term_of_occ(u));
×
3552
      assert(x != null_thvar);
3553
      break;
×
3554

3555
    case POWER_PRODUCT:
584✔
3556
      x = map_pprod_to_bv(ctx, pprod_term_desc(terms, r));
584✔
3557
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
584✔
3558
      break;
584✔
3559

3560
    case BV64_POLY:
11,149✔
3561
      x = map_bvpoly64_to_bv(ctx, bvpoly64_term_desc(terms, r));
11,149✔
3562
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
11,149✔
3563
      break;
11,149✔
3564

3565
    case BV_POLY:
605✔
3566
      x = map_bvpoly_to_bv(ctx, bvpoly_term_desc(terms, r));
605✔
3567
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
605✔
3568
      break;
605✔
3569

3570
    case VARIABLE:
×
3571
      exception = FREE_VARIABLE_IN_FORMULA;
×
3572
      goto abort;
×
3573

3574
    default:
×
3575
      exception = INTERNAL_ERROR;
×
3576
      goto abort;
×
3577
    }
3578
  }
3579

3580
  return x;
375,945✔
3581

3582
 abort:
×
3583
  longjmp(ctx->env, exception);
×
3584
}
3585

3586

3587

3588

3589

3590

3591
/****************************
3592
 *  CONVERSION TO LITERALS  *
3593
 ***************************/
3594

3595
/*
3596
 * Translate an internalization code x to a literal
3597
 * - if x is the code of an egraph occurrence u, we return the
3598
 *   theory variable for u in the egraph
3599
 * - otherwise, x should be the code of a literal l in the core
3600
 */
3601
static literal_t translate_code_to_literal(context_t *ctx, int32_t x) {
1,397,146✔
3602
  occ_t u;
3603
  literal_t l;
3604

3605
  assert(code_is_valid(x));
3606
  if (code_is_eterm(x)) {
1,397,146✔
3607
    u = code2occ(x);
129,810✔
3608
    if (term_of_occ(u) == true_eterm) {
129,810✔
3609
      l = mk_lit(const_bvar, polarity_of(u));
129,810✔
3610

3611
      assert((u == true_occ && l == true_literal) ||
3612
             (u == false_occ && l == false_literal));
3613
    } else {
3614
      assert(ctx->egraph != NULL);
3615
      l = egraph_occ2literal(ctx->egraph, u);
×
3616
    }
3617
  } else {
3618
    l = code2literal(x);
1,267,336✔
3619
  }
3620

3621
  return l;
1,397,146✔
3622
}
3623

3624
static literal_t internalize_to_literal(context_t *ctx, term_t t) {
1,824,866✔
3625
  term_table_t *terms;
3626
  int32_t code;
3627
  uint32_t polarity;
3628
  term_t r;
3629
  literal_t l;
3630
  occ_t u;
3631

3632
  assert(is_boolean_term(ctx->terms, t));
3633

3634
  r = intern_tbl_get_root(&ctx->intern, t);
1,824,866✔
3635
  polarity = polarity_of(r);
1,824,866✔
3636
  r = unsigned_term(r);
1,824,866✔
3637

3638
  /*
3639
   * At this point:
3640
   * 1) r is a positive root in the internalization table
3641
   * 2) polarity is 1 or 0
3642
   * 3) if polarity is 0, then t is equal to r by substitution
3643
   *    if polarity is 1, then t is equal to (not r)
3644
   *
3645
   * We get l := internalization of r
3646
   * then return l or (not l) depending on polarity.
3647
   */
3648

3649
  if (intern_tbl_root_is_mapped(&ctx->intern, r)) {
1,824,866✔
3650
    /*
3651
     * r already internalized
3652
     */
3653
    code = intern_tbl_map_of_root(&ctx->intern, r);
1,397,146✔
3654
    l = translate_code_to_literal(ctx, code);
1,397,146✔
3655

3656
  } else {
3657
    /*
3658
     * Recursively compute r's internalization
3659
     */
3660
    if (context_atom_requires_mcsat(ctx, r)) {
427,720✔
3661
      l = map_mcsat_atom_to_literal(ctx, r);
3✔
3662
      intern_tbl_map_root(&ctx->intern, r, literal2code(l));
3✔
3663
      goto done;
3✔
3664
    }
3665

3666
    terms = ctx->terms;
427,717✔
3667
    switch (term_kind(terms, r)) {
427,717✔
3668
    case CONSTANT_TERM:
×
3669
      assert(r == true_term);
3670
      l = true_literal;
×
3671
      break;
×
3672

3673
    case VARIABLE:
×
3674
      longjmp(ctx->env, FREE_VARIABLE_IN_FORMULA);
×
3675
      break;
3676

3677
    case UNINTERPRETED_TERM:
6,391✔
3678
      l = pos_lit(create_boolean_variable(ctx->core));
6,391✔
3679
      break;
6,391✔
3680

3681
    case ITE_TERM:
1,863✔
3682
    case ITE_SPECIAL:
3683
      l = map_ite_to_literal(ctx, ite_term_desc(terms, r));
1,863✔
3684
      break;
1,863✔
3685

3686
    case EQ_TERM:
14,519✔
3687
      l = map_eq_to_literal(ctx, eq_term_desc(terms, r));
14,519✔
3688
      break;
14,519✔
3689

3690
    case OR_TERM:
81,300✔
3691
      l = map_or_to_literal(ctx, or_term_desc(terms, r));
81,300✔
3692
      break;
81,300✔
3693

3694
    case XOR_TERM:
1✔
3695
      l = map_xor_to_literal(ctx, xor_term_desc(terms, r));
1✔
3696
      break;
1✔
3697

3698
    case ARITH_IS_INT_ATOM:
×
3699
      l = map_arith_is_int_to_literal(ctx, arith_is_int_arg(terms, r));
×
3700
      break;
×
3701

3702
    case ARITH_EQ_ATOM:
2,249✔
3703
      l = map_arith_eq_to_literal(ctx, arith_eq_arg(terms, r));
2,249✔
3704
      break;
2,249✔
3705

3706
    case ARITH_GE_ATOM:
33,841✔
3707
      l = map_arith_geq_to_literal(ctx, arith_ge_arg(terms, r));
33,841✔
3708
      break;
33,841✔
3709

3710
    case ARITH_BINEQ_ATOM:
8,967✔
3711
      l = map_arith_bineq_to_literal(ctx, arith_bineq_atom_desc(terms, r));
8,967✔
3712
      break;
8,967✔
3713

3714
    case ARITH_DIVIDES_ATOM:
8✔
3715
      l = map_arith_divides_to_literal(ctx, arith_divides_atom_desc(terms, r));
8✔
3716
      break;
8✔
3717

NEW
3718
    case ARITH_ROOT_ATOM:
×
NEW
3719
      longjmp(ctx->env, FORMULA_NOT_LINEAR);
×
3720
      break;
3721

NEW
3722
    case ARITH_FF_EQ_ATOM:
×
3723
    case ARITH_FF_BINEQ_ATOM:
NEW
3724
      longjmp(ctx->env, CONTEXT_UNSUPPORTED_THEORY);
×
3725
      break;
3726

3727
    case APP_TERM:
4,368✔
3728
      l = map_apply_to_literal(ctx, app_term_desc(terms, r));
4,368✔
3729
      break;
4,368✔
3730

3731
    case SELECT_TERM:
×
3732
      u = map_select_to_eterm(ctx, select_term_desc(terms, r), bool_type(ctx->types));
×
3733
      assert(egraph_term_is_bool(ctx->egraph, term_of_occ(u)));
3734
      intern_tbl_map_root(&ctx->intern, r, occ2code(u));
×
3735
      l = egraph_occ2literal(ctx->egraph, u);
×
3736
      // we don't want to map r to l here
3737
      goto done;
×
3738

3739
    case DISTINCT_TERM:
9✔
3740
      l = map_distinct_to_literal(ctx, distinct_term_desc(terms, r));
9✔
3741
      break;
9✔
3742

3743
    case FORALL_TERM:
×
3744
      if (context_in_strict_mode(ctx)) {
×
3745
        longjmp(ctx->env, QUANTIFIERS_NOT_SUPPORTED);
×
3746
      }
3747
      // lax mode: turn forall into a proposition
3748
      l = pos_lit(create_boolean_variable(ctx->core));
×
3749
      break;
×
3750

3751
    case BIT_TERM:
264,128✔
3752
      l = map_bit_select_to_literal(ctx, bit_term_desc(terms, r));
264,128✔
3753
      break;
264,128✔
3754

3755
    case BV_EQ_ATOM:
4,864✔
3756
      l = map_bveq_to_literal(ctx, bveq_atom_desc(terms, r));
4,864✔
3757
      break;
4,864✔
3758

3759
    case BV_GE_ATOM:
2,302✔
3760
      l = map_bvge_to_literal(ctx, bvge_atom_desc(terms, r));
2,302✔
3761
      break;
2,302✔
3762

3763
    case BV_SGE_ATOM:
2,907✔
3764
      l = map_bvsge_to_literal(ctx, bvsge_atom_desc(terms, r));
2,907✔
3765
      break;
2,907✔
3766

3767
    default:
×
3768
      longjmp(ctx->env, INTERNAL_ERROR);
×
3769
      break;
3770
    }
3771

3772
    // map r to l in the internalization table
3773
    intern_tbl_map_root(&ctx->intern, r, literal2code(l));
427,717✔
3774
  }
3775

3776
 done:
1,824,866✔
3777
  return l ^ polarity;
1,824,866✔
3778
}
3779

3780

3781

3782
/******************************************************
3783
 *  TOP-LEVEL ASSERTIONS: TERMS ALREADY INTERNALIZED  *
3784
 *****************************************************/
3785

3786
/*
3787
 * Assert (x == tt) for an internalization code x
3788
 */
3789
static void assert_internalization_code(context_t *ctx, int32_t x, bool tt) {
923✔
3790
  occ_t g;
3791
  literal_t l;
3792

3793
  assert(code_is_valid(x));
3794

3795
  if (code_is_eterm(x)) {
923✔
3796
    // normalize to assertion (g == true)
3797
    g = code2occ(x);
10✔
3798
    if (! tt) g = opposite_occ(g);
10✔
3799

3800
    // We must deal with 'true_occ/false_occ' separately
3801
    // since they may be used even if there's no actual egraph.
3802
    if (g == false_occ) {
10✔
3803
      longjmp(ctx->env, TRIVIALLY_UNSAT);
4✔
3804
    } else if (g != true_occ) {
6✔
3805
      assert(ctx->egraph != NULL);
3806
      if (!context_quant_enabled(ctx) || egraph_is_at_base_level(ctx->egraph)) {
×
3807
        egraph_assert_axiom(ctx->egraph, g);
×
3808
      } else {
3809
        l = egraph_make_eq(ctx->egraph, g, true_occ);
×
3810
        add_unit_clause(ctx->core, l);
×
3811
      }
3812
    }
3813
  } else {
3814
    l = code2literal(x);
913✔
3815
    if (! tt) l = not(l);
913✔
3816
    add_unit_clause(ctx->core, l);
913✔
3817
  }
3818
}
919✔
3819

3820
/*
3821
 * Assert t == true where t is a term that's already mapped
3822
 * either to a literal or to an egraph occurrence.
3823
 * - t must be a root in the internalization table
3824
 */
3825
static void assert_toplevel_intern(context_t *ctx, term_t t) {
739✔
3826
  int32_t code;
3827
  bool tt;
3828

3829
  assert(is_boolean_term(ctx->terms, t) &&
3830
         intern_tbl_is_root(&ctx->intern, t) &&
3831
         intern_tbl_root_is_mapped(&ctx->intern, t));
3832

3833
  tt = is_pos_term(t);
739✔
3834
  t = unsigned_term(t);
739✔
3835
  code = intern_tbl_map_of_root(&ctx->intern, t);
739✔
3836

3837
  assert_internalization_code(ctx, code, tt);
739✔
3838
}
739✔
3839

3840

3841

3842

3843

3844

3845

3846
/********************************
3847
 *   ARITHMETIC SUBSTITUTIONS   *
3848
 *******************************/
3849

3850
/*
3851
 * TODO: improve this in the integer case:
3852
 * - all_int is based on p's type in the term table and does
3853
 *   not take the context's substitutions into account.
3854
 * - integral_poly_after_div requires all coefficients
3855
 *   to be integer. This could be generalized to polynomials
3856
 *   with integer variables and rational coefficients.
3857
 */
3858

3859
/*
3860
 * Check whether term t can be eliminated by an arithmetic substitution
3861
 * - t's root must be uninterpreted and not internalized yet
3862
 */
3863
static bool is_elimination_candidate(context_t *ctx, term_t t) {
2,742✔
3864
  term_t r;
3865

3866
  r = intern_tbl_get_root(&ctx->intern, t);
2,742✔
3867
  return intern_tbl_root_is_free(&ctx->intern, r);
2,742✔
3868
}
3869

3870

3871
/*
3872
 * Replace every variable of t by the root of t in the internalization table
3873
 * - the result is stored in buffer
3874
 */
3875
static void apply_renaming_to_poly(context_t *ctx, polynomial_t *p,  poly_buffer_t *buffer) {
544✔
3876
  uint32_t i, n;
3877
  term_t t;
3878

3879
  reset_poly_buffer(buffer);
544✔
3880

3881
  assert(poly_buffer_is_zero(buffer));
3882

3883
  n = p->nterms;
544✔
3884
  for (i=0; i<n; i++) {
2,599✔
3885
    t = p->mono[i].var;
2,055✔
3886
    if (t == const_idx) {
2,055✔
3887
      poly_buffer_add_const(buffer, &p->mono[i].coeff);
180✔
3888
    } else {
3889
      // replace t by its root
3890
      t = intern_tbl_get_root(&ctx->intern, t);
1,875✔
3891
      poly_buffer_addmul_term(ctx->terms, buffer, t, &p->mono[i].coeff);
1,875✔
3892
    }
3893
  }
3894

3895
  normalize_poly_buffer(buffer);
544✔
3896
}
544✔
3897

3898

3899
/*
3900
 * Auxiliary function: check whether p/a is an integral polynomial
3901
 * assuming all variables and coefficients of p are integer.
3902
 * - check whether all coefficients are multiple of a
3903
 * - a must be non-zero
3904
 */
3905
static bool integralpoly_after_div(poly_buffer_t *buffer, rational_t *a) {
318✔
3906
  uint32_t i, n;
3907

3908
  if (q_is_one(a) || q_is_minus_one(a)) {
318✔
3909
    return true;
265✔
3910
  }
3911

3912
  n = buffer->nterms;
53✔
3913
  for (i=0; i<n; i++) {
64✔
3914
    if (! q_divides(a, &buffer->mono[i].coeff)) return false;
63✔
3915
  }
3916
  return true;
1✔
3917
}
3918

3919

3920
/*
3921
 * Check whether a top-level assertion (p == 0) can be
3922
 * rewritten (t == q) where t is not internalized yet.
3923
 * - all_int is true if p is an integer polynomial (i.e.,
3924
 *   all coefficients and all terms of p are integer).
3925
 * - p = input polynomial
3926
 * - return t or null_term if no adequate t is found
3927
 */
3928
static term_t try_poly_substitution(context_t *ctx, poly_buffer_t *buffer, bool all_int) {
544✔
3929
  uint32_t i, n;
3930
  term_t t;
3931

3932
  // check for a free variable in buffer
3933
  n = buffer->nterms;
544✔
3934
  for (i=0; i<n; i++) {
1,128✔
3935
    t = buffer->mono[i].var;
1,049✔
3936
    if (t != const_idx && is_elimination_candidate(ctx, t)) {
1,049✔
3937
      if (in_real_class(ctx, t) ||
518✔
3938
          (all_int && integralpoly_after_div(buffer, &buffer->mono[i].coeff))) {
318✔
3939
        // t is candidate for elimination
3940
        return t;
465✔
3941
      }
3942
    }
3943
  }
3944

3945
  return NULL_TERM;
79✔
3946
}
3947

3948

3949
/*
3950
 * Build polynomial - p/a + x in the context's aux_poly buffer
3951
 * where a = coefficient of x in p
3952
 * - x must occur in p
3953
 */
3954
static polynomial_t *build_poly_substitution(context_t *ctx, poly_buffer_t *buffer, term_t x) {
465✔
3955
  polynomial_t *q;
3956
  monomial_t *mono;
3957
  uint32_t i, n;
3958
  term_t y;
3959
  rational_t *a;
3960

3961
  n = buffer->nterms;
465✔
3962

3963
  // first get coefficient of x in buffer
3964
  a = NULL; // otherwise GCC complains
465✔
3965
  for (i=0; i<n; i++) {
2,283✔
3966
    y = buffer->mono[i].var;
1,818✔
3967
    if (y == x) {
1,818✔
3968
      a = &buffer->mono[i].coeff;
465✔
3969
    }
3970
  }
3971
  assert(a != NULL && n > 0);
3972

3973
  q = context_get_aux_poly(ctx, n);
465✔
3974
  q->nterms = n-1;
465✔
3975
  mono = q->mono;
465✔
3976

3977
  // compute - buffer/a (but skip monomial a.x)
3978
  for (i=0; i<n; i++) {
2,283✔
3979
    y = buffer->mono[i].var;
1,818✔
3980
    if (y != x) {
1,818✔
3981
      mono->var = y;
1,353✔
3982
      q_set_neg(&mono->coeff, &buffer->mono[i].coeff);
1,353✔
3983
      q_div(&mono->coeff, a);
1,353✔
3984
      mono ++;
1,353✔
3985
    }
3986
  }
3987

3988
  // end marker
3989
  mono->var = max_idx;
465✔
3990

3991
  return q;
465✔
3992
}
3993

3994

3995

3996
/*
3997
 * Try to eliminate a toplevel equality (p == 0) by variable substitution:
3998
 * - i.e., try to rewrite p == 0 into (x - q) == 0 where x is a free variable
3999
 *   then store the substitution x --> q in the internalization table.
4000
 * - all_int is true if p is an integer polynomial (i.e., all variables and all
4001
 *   coefficients of p are integer)
4002
 *
4003
 * - return true if the elimination succeeds
4004
 * - return false otherwise
4005
 */
4006
static bool try_arithvar_elim(context_t *ctx, polynomial_t *p, bool all_int) {
544✔
4007
  poly_buffer_t *buffer;
4008
  polynomial_t *q;
4009
  uint32_t i, n;
4010
  term_t t, u, r;
4011
  thvar_t x;
4012

4013
  /*
4014
   * First pass: internalize every term of p that's not a variable
4015
   * - we do that first to avoid circular substitutions (occurs-check)
4016
   */
4017
  n = p->nterms;
544✔
4018
  for (i=0; i<n; i++) {
2,599✔
4019
    t = p->mono[i].var;
2,055✔
4020
    if (t != const_idx && ! is_elimination_candidate(ctx, t)) {
2,055✔
4021
      (void) internalize_to_arith(ctx, t);
599✔
4022
    }
4023
  }
4024

4025

4026
  /*
4027
   * Apply variable renaming: this is to avoid circularities
4028
   * if p is of the form ... + a x + ... + b y + ...
4029
   * where both x and y are variables in the same class (i.e.,
4030
   * both are elimination candidates).
4031
   */
4032
  buffer = context_get_poly_buffer(ctx);
544✔
4033
  apply_renaming_to_poly(ctx, p, buffer);
544✔
4034

4035
  /*
4036
   * Search for a variable to substitute
4037
   */
4038
  u = try_poly_substitution(ctx, buffer, all_int);
544✔
4039
  if (u == NULL_TERM) {
544✔
4040
    return false; // no substitution found
79✔
4041
  }
4042

4043
  /*
4044
   * buffer is of the form a.u + p0, we rewrite (buffer == 0) to (u == q)
4045
   * where q = -1/a * p0
4046
   */
4047
  q = build_poly_substitution(ctx, buffer, u); // q is in ctx->aux_poly
465✔
4048

4049
  // convert q to a theory variable in the arithmetic solver
4050
  x = map_poly_to_arith(ctx, q);
465✔
4051

4052
  // map u (and its root) to x
4053
  r = intern_tbl_get_root(&ctx->intern, u);
465✔
4054
  assert(intern_tbl_root_is_free(&ctx->intern, r) && is_pos_term(r));
4055
  intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
465✔
4056

4057
#if TRACE
4058
  printf("---> toplevel equality: ");
4059
  print_polynomial(stdout, p);
4060
  printf(" == 0\n");
4061
  printf("     simplified to ");
4062
  print_term(stdout, ctx->terms, u);
4063
  printf(" := ");
4064
  print_polynomial(stdout, q);
4065
  printf("\n");
4066
#endif
4067

4068
  return true;
465✔
4069
}
4070

4071

4072

4073

4074

4075

4076

4077
/******************************************************
4078
 *  TOP-LEVEL ARITHMETIC EQUALITIES OR DISEQUALITIES  *
4079
 *****************************************************/
4080

4081
static void assert_arith_bineq(context_t *ctx, term_t t1, term_t t2, bool tt);
4082

4083
/*
4084
 * Top-level equality: t == (ite c u1 u2) between arithmetic terms
4085
 * - apply lift-if rule: (t == (ite c u1 u2)) --> (ite c (t == u1) (t == u2)
4086
 * - if tt is true: assert the equality otherwise assert the disequality
4087
 */
4088
static void assert_ite_arith_bineq(context_t *ctx, composite_term_t *ite, term_t t, bool tt) {
451✔
4089
  literal_t l1, l2, l3;
4090

4091
  assert(ite->arity == 3);
4092

4093
  l1 = internalize_to_literal(ctx, ite->arg[0]);
451✔
4094
  if (l1 == true_literal) {
451✔
4095
    // (ite c u1 u2) --> u1
4096
    assert_arith_bineq(ctx, ite->arg[1], t, tt);
3✔
4097
  } else if (l1 == false_literal) {
448✔
4098
    // (ite c u1 u2) --> u2
4099
    assert_arith_bineq(ctx, ite->arg[2], t, tt);
15✔
4100
  } else {
4101
    l2 = map_arith_bineq(ctx, ite->arg[1], t); // (u1 == t)
433✔
4102
    l3 = map_arith_bineq(ctx, ite->arg[2], t); // (u2 == t)
433✔
4103
    assert_ite(&ctx->gate_manager, l1, l2, l3, tt);
433✔
4104
  }
4105
}
451✔
4106

4107

4108
/*
4109
 * Try substitution t1 := t2
4110
 * - both are arithmetic terms and roots in the internalization table
4111
 */
4112
static void try_arithvar_bineq_elim(context_t *ctx, term_t t1, term_t t2) {
164✔
4113
  intern_tbl_t *intern;
4114
  thvar_t x, y;
4115
  int32_t code;
4116

4117
  assert(is_pos_term(t1) && intern_tbl_is_root(&ctx->intern, t1) &&
4118
         intern_tbl_root_is_free(&ctx->intern, t1));
4119

4120
  intern = &ctx->intern;
164✔
4121

4122
  if (is_constant_term(ctx->terms, t2)) {
164✔
4123
    if (intern_tbl_valid_const_subst(intern, t1, t2)) {
2✔
4124
      intern_tbl_add_subst(intern, t1, t2);
2✔
4125
    } else {
4126
      // unsat by type incompatibility
4127
      longjmp(ctx->env, TRIVIALLY_UNSAT);
×
4128
    }
4129

4130
  } else if (intern_tbl_sound_subst(intern, t1, t2)) {
162✔
4131
    /*
4132
     * Internalize t2 to x.
4133
     * If t1 is still free after that, we can map t1 to x
4134
     * otherwise, t2 depends on t1 so we can't substitute.
4135
     */
4136
    x = internalize_to_arith(ctx, t2);
161✔
4137
    if (intern_tbl_root_is_free(intern, t1)) {
161✔
4138
      intern_tbl_map_root(&ctx->intern, t1, thvar2code(x));
2✔
4139
    } else {
4140
      assert(intern_tbl_root_is_mapped(intern, t1));
4141
      code = intern_tbl_map_of_root(intern, t1);
159✔
4142
      y = translate_code_to_arith(ctx, code);
159✔
4143

4144
      // assert x == y in the arithmetic solver
4145
      ctx->arith.assert_vareq_axiom(ctx->arith_solver, x, y, true);
159✔
4146
    }
4147
  } else {
4148
    x = internalize_to_arith(ctx, t1);
1✔
4149
    y = internalize_to_arith(ctx, t2);
1✔
4150
    ctx->arith.assert_vareq_axiom(ctx->arith_solver, x, y, true);
1✔
4151
  }
4152
}
164✔
4153

4154

4155
/*
4156
 * Top-level arithmetic equality t1 == t2:
4157
 * - if tt is true: assert t1 == t2 otherwise assert (t1 != t2)
4158
 * - both t1 and t2 are arithmetic terms and roots in the internalization table
4159
 * - the equality (t1 == t2) is not reducible by if-then-else flattening
4160
 */
4161
static void assert_arith_bineq_aux(context_t *ctx, term_t t1, term_t t2, bool tt) {
3,335✔
4162
  term_table_t *terms;
4163
  intern_tbl_t *intern;;
4164
  bool free1, free2;
4165
  thvar_t x, y;
4166
  occ_t u, v;
4167

4168
  assert(is_pos_term(t1) && intern_tbl_is_root(&ctx->intern, t1) &&
4169
         is_pos_term(t2) && intern_tbl_is_root(&ctx->intern, t2));
4170

4171
  terms = ctx->terms;
3,335✔
4172
  if (is_ite_term(terms, t1) && !is_ite_term(terms, t2)) {
3,335✔
4173
    assert_ite_arith_bineq(ctx, ite_term_desc(terms, t1), t2, tt);
112✔
4174
    return;
112✔
4175
  }
4176

4177
  if (is_ite_term(terms, t2) && !is_ite_term(terms, t1)) {
3,223✔
4178
    assert_ite_arith_bineq(ctx, ite_term_desc(terms, t2), t1, tt);
339✔
4179
    return;
339✔
4180
  }
4181

4182
  if (tt && context_arith_elim_enabled(ctx)) {
2,884✔
4183
    /*
4184
     * try a substitution
4185
     */
4186
    intern = &ctx->intern;
340✔
4187
    free1 = intern_tbl_root_is_free(intern, t1);
340✔
4188
    free2 = intern_tbl_root_is_free(intern, t2);
340✔
4189

4190
    if (free1 && free2) {
340✔
4191
      if (t1 != t2) {
1✔
4192
        intern_tbl_merge_classes(intern, t1, t2);
1✔
4193
      }
4194
      return;
1✔
4195
    }
4196

4197
    if (free1) {
339✔
4198
      try_arithvar_bineq_elim(ctx, t1, t2);
162✔
4199
      return;
162✔
4200
    }
4201

4202
    if (free2) {
177✔
4203
      try_arithvar_bineq_elim(ctx, t2, t1);
2✔
4204
      return;
2✔
4205
    }
4206

4207
  }
4208

4209
  /*
4210
   * Default: assert the constraint in the egraph or in the arithmetic
4211
   * solver if there's no egraph.
4212
   */
4213
  if (context_has_egraph(ctx)) {
2,719✔
4214
    u = internalize_to_eterm(ctx, t1);
1,658✔
4215
    v = internalize_to_eterm(ctx, t2);
1,658✔
4216
    if (!context_quant_enabled(ctx) || egraph_is_at_base_level(ctx->egraph)) {
1,658✔
4217
      if (tt) {
1,658✔
4218
        egraph_assert_eq_axiom(ctx->egraph, u, v);
162✔
4219
      } else {
4220
        egraph_assert_diseq_axiom(ctx->egraph, u, v);
1,496✔
4221
      }
4222
    } else {
4223
      literal_t l = egraph_make_eq(ctx->egraph, u, v);
×
4224
      if (tt) {
×
4225
        add_unit_clause(ctx->core, l);
×
4226
      } else {
4227
        add_unit_clause(ctx->core, not(l));
×
4228
      }
4229
    }
4230
  } else {
4231
    x = internalize_to_arith(ctx, t1);
1,061✔
4232
    y = internalize_to_arith(ctx, t2);
1,061✔
4233
    ctx->arith.assert_vareq_axiom(ctx->arith_solver, x, y, tt);
1,061✔
4234
  }
4235
}
4236

4237

4238

4239

4240
/*****************************************************
4241
 *  INTERNALIZATION OF TOP-LEVEL ATOMS AND FORMULAS  *
4242
 ****************************************************/
4243

4244
/*
4245
 * Recursive function: assert (t == tt) for a boolean term t
4246
 * - this is used when a toplevel formula simplifies to t
4247
 *   For example (ite c t u) --> t if c is true.
4248
 * - t is not necessarily a root in the internalization table
4249
 */
4250
static void assert_term(context_t *ctx, term_t t, bool tt);
4251

4252

4253
/*
4254
 * Top-level predicate: (p t_1 .. t_n)
4255
 * - if tt is true: assert (p t_1 ... t_n)
4256
 * - if tt is false: assert (not (p t_1 ... t_n))
4257
 */
4258
static void assert_toplevel_apply(context_t *ctx, composite_term_t *app, bool tt) {
252✔
4259
  occ_t *a;
4260
  uint32_t i, n;
4261

4262
  assert(app->arity > 0);
4263

4264
  n = app->arity;
252✔
4265

4266
  check_high_order_support(ctx, app->arg+1, n-1);
252✔
4267

4268
  a = alloc_istack_array(&ctx->istack, n);
252✔
4269
  for (i=0; i<n; i++) {
1,030✔
4270
    a[i] = internalize_to_eterm(ctx, app->arg[i]);
778✔
4271
  }
4272

4273
  if (!context_quant_enabled(ctx) || egraph_is_at_base_level(ctx->egraph)) {
252✔
4274
    if (tt) {
242✔
4275
      egraph_assert_pred_axiom(ctx->egraph, a[0], n-1, a+1);
214✔
4276
    } else {
4277
      egraph_assert_notpred_axiom(ctx->egraph, a[0], n-1, a+1);
28✔
4278
    }
4279
  } else {
4280
    literal_t l = egraph_make_pred(ctx->egraph, a[0], n-1, a+1);
10✔
4281
    if (tt) {
10✔
4282
      add_unit_clause(ctx->core, l);
3✔
4283
    } else {
4284
      add_unit_clause(ctx->core, not(l));
7✔
4285
    }
4286
  }
4287

4288
  free_istack_array(&ctx->istack, a);
252✔
4289
}
252✔
4290

4291

4292
/*
4293
 * Top-level (select i t)
4294
 * - if tt is true: assert (select i t)
4295
 * - if tt is false: assert (not (select i t))
4296
 */
4297
static void assert_toplevel_select(context_t *ctx, select_term_t *select, bool tt) {
×
4298
  occ_t u;
4299

4300
  u = map_select_to_eterm(ctx, select, bool_type(ctx->types));
×
4301
  if (! tt) {
×
4302
    u = opposite_occ(u);
×
4303
  }
4304
  if (!context_quant_enabled(ctx) || egraph_is_at_base_level(ctx->egraph)) {
×
4305
    egraph_assert_axiom(ctx->egraph, u);
×
4306
  } else {
4307
    literal_t l = egraph_make_eq(ctx->egraph, u, true_occ);
×
4308
    add_unit_clause(ctx->core, l);
×
4309
  }
4310
}
×
4311

4312

4313
/*
4314
 * Top-level equality between Boolean terms
4315
 * - if tt is true, assert t1 == t2
4316
 * - if tt is false, assert t1 != t2
4317
 */
4318
static void assert_toplevel_iff(context_t *ctx, term_t t1, term_t t2, bool tt) {
2,739✔
4319
  term_t t;
4320
  literal_t l1, l2;
4321

4322
  /*
4323
   * Apply substitution then try flattening
4324
   */
4325
  t1 = intern_tbl_get_root(&ctx->intern, t1);
2,739✔
4326
  t2 = intern_tbl_get_root(&ctx->intern, t2);
2,739✔
4327
  if (t1 == t2) {
2,739✔
4328
    // (eq t1 t2) is true
4329
    if (!tt) {
×
4330
      longjmp(ctx->env, TRIVIALLY_UNSAT);
×
4331
    }
4332
  }
4333
  // try simplification
4334
  t = simplify_bool_eq(ctx, t1, t2);
2,739✔
4335
  if (t != NULL_TERM) {
2,739✔
4336
    // (eq t1 t2) is equivalent to t
4337
    assert_term(ctx, t, tt) ;
17✔
4338
  } else {
4339
    // no simplification
4340
    l1 = internalize_to_literal(ctx, t1);
2,722✔
4341
    l2 = internalize_to_literal(ctx, t2);
2,722✔
4342
    assert_iff(&ctx->gate_manager, l1, l2, tt);
2,722✔
4343

4344
#if 0
4345
    if (tt) {
4346
      printf("top assert: (eq ");
4347
      print_literal(stdout, l1);
4348
      printf(" ");
4349
      print_literal(stdout, l2);
4350
      printf(")\n");
4351
    } else {
4352
      printf("top assert: (xor ");
4353
      print_literal(stdout, l1);
4354
      printf(" ");
4355
      print_literal(stdout, l2);
4356
      printf(")\n");
4357
    }
4358
#endif
4359
  }
4360
}
2,739✔
4361

4362
/*
4363
 * Top-level equality assertion (eq t1 t2):
4364
 * - if tt is true, assert (t1 == t2)
4365
 *   if tt is false, assert (t1 != t2)
4366
 */
4367
static void assert_toplevel_eq(context_t *ctx, composite_term_t *eq, bool tt) {
5,156✔
4368
  occ_t u1, u2;
4369

4370
  assert(eq->arity == 2);
4371

4372
  if (is_boolean_term(ctx->terms, eq->arg[0])) {
5,156✔
4373
    assert(is_boolean_term(ctx->terms, eq->arg[1]));
4374
    assert_toplevel_iff(ctx, eq->arg[0], eq->arg[1], tt);
2,739✔
4375
  } else {
4376
    // filter out high-order terms. It's enough to check eq->arg[0]
4377
    check_high_order_support(ctx, eq->arg, 1);
2,417✔
4378

4379
    u1 = internalize_to_eterm(ctx, eq->arg[0]);
2,416✔
4380
    u2 = internalize_to_eterm(ctx, eq->arg[1]);
2,416✔
4381
    if (!context_quant_enabled(ctx) || egraph_is_at_base_level(ctx->egraph)) {
2,415✔
4382
      if (tt) {
2,401✔
4383
        egraph_assert_eq_axiom(ctx->egraph, u1, u2);
1,323✔
4384
      } else {
4385
        egraph_assert_diseq_axiom(ctx->egraph, u1, u2);
1,078✔
4386
      }
4387
    } else {
4388
      literal_t l = egraph_make_eq(ctx->egraph, u1, u2);
14✔
4389
      if (tt) {
14✔
4390
        add_unit_clause(ctx->core, l);
9✔
4391
      } else {
4392
        add_unit_clause(ctx->core, not(l));
5✔
4393
      }
4394
    }
4395
  }
4396
}
5,154✔
4397

4398

4399
/*
4400
 * Assertion (distinct a[0] .... a[n-1]) == tt
4401
 * when a[0] ... a[n-1] are arithmetic variables.
4402
 */
4403
static void assert_arith_distinct(context_t *ctx, uint32_t n, thvar_t *a, bool tt) {
155✔
4404
  literal_t l;
4405

4406
  l = make_arith_distinct(ctx, n, a);
155✔
4407
  if (! tt) {
155✔
4408
    l = not(l);
4✔
4409
  }
4410
  add_unit_clause(ctx->core, l);
155✔
4411
}
155✔
4412

4413

4414
/*
4415
 * Assertion (distinct a[0] .... a[n-1]) == tt
4416
 * when a[0] ... a[n-1] are bitvector variables.
4417
 */
4418
static void assert_bv_distinct(context_t *ctx, uint32_t n, thvar_t *a, bool tt) {
2✔
4419
  literal_t l;
4420

4421
  l = make_bv_distinct(ctx, n, a);
2✔
4422
  if (! tt) {
2✔
4423
    l = not(l);
1✔
4424
  }
4425
  add_unit_clause(ctx->core, l);
2✔
4426
}
2✔
4427

4428

4429
/*
4430
 * Generic (distinct t1 .. t_n)
4431
 * - if tt: assert (distinct t_1 ... t_n)
4432
 * - otherwise: assert (not (distinct t_1 ... t_n))
4433
 */
4434
static void assert_toplevel_distinct(context_t *ctx, composite_term_t *distinct, bool tt) {
173✔
4435
  uint32_t i, n;
4436
  int32_t *a;
4437

4438
  n = distinct->arity;
173✔
4439
  assert(n >= 2);
4440

4441
  a = alloc_istack_array(&ctx->istack, n);
173✔
4442

4443
  if (context_has_egraph(ctx)) {
173✔
4444
    // fail if arguments have function types and we don't
4445
    // have a function/array solver
4446
    check_high_order_support(ctx, distinct->arg, 1);
16✔
4447

4448
    // forward the assertion to the egraph
4449
    for (i=0; i<n; i++) {
69✔
4450
      a[i] = internalize_to_eterm(ctx, distinct->arg[i]);
55✔
4451
    }
4452

4453
    if (!context_quant_enabled(ctx) || egraph_is_at_base_level(ctx->egraph)) {
14✔
4454
      if (tt) {
14✔
4455
        egraph_assert_distinct_axiom(ctx->egraph, n, a);
10✔
4456
      } else {
4457
        egraph_assert_notdistinct_axiom(ctx->egraph, n, a);
4✔
4458
      }
4459
    } else {
4460
      literal_t l = egraph_make_distinct(ctx->egraph, n, a);
×
4461
      if (tt) {
×
4462
        add_unit_clause(ctx->core, l);
×
4463
      } else {
4464
        add_unit_clause(ctx->core, not(l));
×
4465
      }
4466
    }
4467

4468
  } else if (is_arithmetic_term(ctx->terms, distinct->arg[0])) {
157✔
4469
    // translate to arithmetic then assert
4470
    for (i=0; i<n; i++) {
3,922✔
4471
      a[i] = internalize_to_arith(ctx, distinct->arg[i]);
3,767✔
4472
    }
4473
    assert_arith_distinct(ctx, n, a, tt);
155✔
4474

4475
  } else if (is_bitvector_term(ctx->terms, distinct->arg[0])) {
2✔
4476
    // translate to bitvectors then assert
4477
    for (i=0; i<n; i++) {
13✔
4478
      a[i] = internalize_to_bv(ctx, distinct->arg[i]);
11✔
4479
    }
4480
    assert_bv_distinct(ctx, n, a, tt);
2✔
4481

4482
  } else {
4483
    longjmp(ctx->env, uf_error_code(ctx, distinct->arg[0]));
×
4484
  }
4485

4486
  free_istack_array(&ctx->istack, a);
171✔
4487
}
171✔
4488

4489

4490

4491
/*
4492
 * Top-level arithmetic equality t1 == u1:
4493
 * - t1 and u1 are arithmetic terms
4494
 * - if tt is true assert (t1 == u1) otherwise assert (t1 != u1)
4495
 * - apply lift-if simplifications and variable elimination
4496
 */
4497
static void assert_arith_bineq(context_t *ctx, term_t t1, term_t u1, bool tt) {
3,408✔
4498
  ivector_t *v;
4499
  int32_t *a;
4500
  uint32_t i, n;
4501
  term_t t2, u2;
4502

4503
  /*
4504
   * Apply substitutions then try if-then-else flattening
4505
   */
4506
  t1 = intern_tbl_get_root(&ctx->intern, t1);
3,408✔
4507
  u1 = intern_tbl_get_root(&ctx->intern, u1);
3,408✔
4508

4509
  v = &ctx->aux_vector;
3,408✔
4510
  assert(v->size == 0);
4511
  t2 = flatten_ite_equality(ctx, v, t1, u1);
3,408✔
4512
  u2 = flatten_ite_equality(ctx, v, u1, t2);
3,408✔
4513

4514
  /*
4515
   * (t1 == u1) is now equivalent to
4516
   * the conjunction of (t2 == u2) and all the terms in v
4517
   */
4518
  n = v->size;
3,408✔
4519
  if (n == 0) {
3,408✔
4520
    /*
4521
     * The simple flattening did not work.
4522
     */
4523
    assert(t1 == t2 && u1 == u2);
4524
    assert_arith_bineq_aux(ctx, t2, u2, tt);
3,322✔
4525

4526
  } else {
4527
    // make a copy of v[0 ... n-1]
4528
    // and reserve a[n] for the literal (eq t2 u2)
4529
    a = alloc_istack_array(&ctx->istack, n+1);
86✔
4530
    for (i=0; i<n; i++) {
1,531✔
4531
      a[i] = v->data[i];
1,445✔
4532
    }
4533
    ivector_reset(v);
86✔
4534

4535
    if (tt) {
86✔
4536
      // assert (and a[0] ... a[n-1] (eq t2 u2))
4537
      for (i=0; i<n; i++) {
340✔
4538
        assert_term(ctx, a[i], true);
327✔
4539
      }
4540

4541
      /*
4542
       * The assertions a[0] ... a[n-1] may have
4543
       * caused roots to be merged. So we must
4544
       * apply term substitution again.
4545
       */
4546
      t2 = intern_tbl_get_root(&ctx->intern, t2);
13✔
4547
      u2 = intern_tbl_get_root(&ctx->intern, u2);
13✔
4548
      assert_arith_bineq_aux(ctx, t2, u2, true);
13✔
4549

4550
    } else {
4551
      // assert (or (not a[0]) ... (not a[n-1]) (not (eq t2 u2)))
4552
      for (i=0; i<n; i++) {
1,191✔
4553
        a[i] = not(internalize_to_literal(ctx, a[i]));
1,118✔
4554
      }
4555
      a[n] = not(map_arith_bineq_aux(ctx, t2, u2));
73✔
4556

4557
      add_clause(ctx->core, n+1, a);
73✔
4558
    }
4559

4560
    free_istack_array(&ctx->istack, a);
86✔
4561
  }
4562
}
3,408✔
4563

4564

4565
/*
4566
 * Top-level arithmetic assertion:
4567
 * - if tt is true, assert p == 0
4568
 * - if tt is false, assert p != 0
4569
 */
4570
static void assert_toplevel_poly_eq(context_t *ctx, polynomial_t *p, bool tt) {
1,273✔
4571
  uint32_t i, n;
4572
  thvar_t *a;
4573

4574
  n = p->nterms;
1,273✔
4575
  a = alloc_istack_array(&ctx->istack, n);;
1,273✔
4576
  // skip the constant if any
4577
  i = 0;
1,273✔
4578
  if (p->mono[0].var == const_idx) {
1,273✔
4579
    a[0] = null_thvar;
1,208✔
4580
    i ++;
1,208✔
4581
  }
4582

4583
  // deal with the non-constant monomials
4584
  while (i<n) {
3,928✔
4585
    a[i] = internalize_to_arith(ctx, p->mono[i].var);
2,655✔
4586
    i ++;
2,655✔
4587
  }
4588

4589
  // assertion
4590
  ctx->arith.assert_poly_eq_axiom(ctx->arith_solver, p, a, tt);
1,273✔
4591
  free_istack_array(&ctx->istack, a);
1,273✔
4592
}
1,273✔
4593

4594

4595

4596
/*
4597
 * Top-level arithmetic equality:
4598
 * - t is an arithmetic term
4599
 * - if tt is true, assert (t == 0)
4600
 * - otherwise, assert (t != 0)
4601
 */
4602
static void assert_toplevel_arith_eq(context_t *ctx, term_t t, bool tt) {
2,268✔
4603
  term_table_t *terms;
4604
  polynomial_t *p;
4605
  bool all_int;
4606
  thvar_t x;
4607

4608
  assert(is_arithmetic_term(ctx->terms, t));
4609

4610
  terms = ctx->terms;
2,268✔
4611
  if (tt && context_arith_elim_enabled(ctx) && term_kind(terms, t) == ARITH_POLY) {
2,268✔
4612
    /*
4613
     * Polynomial equality: a_1 t_1 + ... + a_n t_n = 0
4614
     * attempt to eliminate one of t_1 ... t_n
4615
     */
4616
    p = poly_term_desc(terms, t);
544✔
4617
    all_int = is_integer_term(terms, t);
544✔
4618
    if (try_arithvar_elim(ctx, p, all_int)) { // elimination worked
544✔
4619
      return;
465✔
4620
    }
4621
  }
4622

4623
  // default
4624
  if (term_kind(terms, t) == ARITH_POLY) {
1,803✔
4625
    assert_toplevel_poly_eq(ctx, poly_term_desc(terms, t), tt);
1,273✔
4626
  } else if (is_ite_term(terms, t)) {
530✔
4627
    assert_arith_bineq(ctx, t, zero_term, tt);
8✔
4628
  } else {
4629
    x = internalize_to_arith(ctx, t);
522✔
4630
    ctx->arith.assert_eq_axiom(ctx->arith_solver, x, tt);
520✔
4631
  }
4632
}
4633

4634

4635

4636
/*
4637
 * Top-level arithmetic assertion:
4638
 * - if tt is true, assert p >= 0
4639
 * - if tt is false, assert p < 0
4640
 */
4641
static void assert_toplevel_poly_geq(context_t *ctx, polynomial_t *p, bool tt) {
25,930✔
4642
  uint32_t i, n;
4643
  thvar_t *a;
4644

4645
  n = p->nterms;
25,930✔
4646
  a = alloc_istack_array(&ctx->istack, n);;
25,930✔
4647
  // skip the constant if any
4648
  i = 0;
25,930✔
4649
  if (p->mono[0].var == const_idx) {
25,930✔
4650
    a[0] = null_thvar;
25,104✔
4651
    i ++;
25,104✔
4652
  }
4653

4654
  // deal with the non-constant monomials
4655
  while (i<n) {
55,603✔
4656
    a[i] = internalize_to_arith(ctx, p->mono[i].var);
29,674✔
4657
    i ++;
29,673✔
4658
  }
4659

4660
  // assertion
4661
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, a, tt);
25,929✔
4662
  free_istack_array(&ctx->istack, a);
25,929✔
4663
}
25,929✔
4664

4665

4666

4667
/*
4668
 * Top-level arithmetic inequality:
4669
 * - t is an arithmetic term
4670
 * - if tt is true, assert (t >= 0)
4671
 * - if tt is false, assert (t < 0)
4672
 */
4673
static void assert_toplevel_arith_geq(context_t *ctx, term_t t, bool tt) {
27,855✔
4674
  term_table_t *terms;
4675
  thvar_t x;
4676

4677
  assert(is_arithmetic_term(ctx->terms, t));
4678

4679
  terms = ctx->terms;
27,855✔
4680
  if (term_kind(terms, t) == ARITH_POLY) {
27,855✔
4681
    assert_toplevel_poly_geq(ctx, poly_term_desc(terms, t), tt);
25,930✔
4682
  } else {
4683
    x = internalize_to_arith(ctx, t);
1,925✔
4684
    ctx->arith.assert_ge_axiom(ctx->arith_solver, x, tt);
1,925✔
4685
  }
4686
}
27,854✔
4687

4688

4689
/*
4690
 * Top-level binary equality: (eq t u)
4691
 * - both t and u are arithmetic terms
4692
 * - if tt is true, assert (t == u)
4693
 * - if tt is false, assert (t != u)
4694
 */
4695
static void assert_toplevel_arith_bineq(context_t *ctx, composite_term_t *eq, bool tt) {
3,382✔
4696
  assert(eq->arity == 2);
4697
  assert_arith_bineq(ctx, eq->arg[0], eq->arg[1], tt);
3,382✔
4698
}
3,382✔
4699

4700

4701

4702
/*
4703
 * Top-level (is_int t)
4704
 * - t is an arithmetic term
4705
 * - if tt is true, assert (t <= (floor t))
4706
 * - if tt is false, asssert (t > (floor t))
4707
 *
4708
 * NOTE: instead of asserting (t <= (floor t)) we could create a fresh
4709
 * integer variable z and assert (t = z).
4710
 */
4711
static void assert_toplevel_arith_is_int(context_t *ctx, term_t t, bool tt) {
×
4712
  polynomial_t *p;
4713
  thvar_t map[2];
4714
  thvar_t x, y;
4715

4716
  x = internalize_to_arith(ctx, t);
×
4717
  if (ctx->arith.arith_var_is_int(ctx->arith_solver, x)) {
×
4718
    if (!tt) {
×
4719
      longjmp(ctx->env, TRIVIALLY_UNSAT);
×
4720
    }
4721
  } else {
4722
    // x is not an integer variable
4723
    y = get_floor(ctx, x); // y := (floor x)
×
4724
    p = context_get_aux_poly(ctx, 3);
×
4725
    context_store_diff_poly(p, map, y, x); // (p, map) stores (y - x)
×
4726
    // assert either (p >= 0) --> (x <= floor(x))
4727
    // or (p < 0) --> (x > (floor x)
4728
    ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, tt);
×
4729
  }
4730
}
×
4731

4732

4733
/*
4734
 * Top-level (divides k t)
4735
 * - if tt is true, assert (t <= k * (div t k))
4736
 * - if tt is false, assert (t > k * (div t k))
4737
 *
4738
 * We assume (k != 0) since (divides 0 t) is rewritten to (t == 0) by
4739
 * the term manager.
4740
 *
4741
 * NOTE: instead of asserting (t <= k * (div t k)) we could create a fresh
4742
 * integer variable z and assert (t = k * z).
4743
 */
4744
static void assert_toplevel_arith_divides(context_t *ctx, composite_term_t *divides, bool tt) {
×
4745
  rational_t k;
4746
  polynomial_t *p;
4747
  thvar_t map[2];
4748
  thvar_t x, y;
4749
  term_t d;
4750

4751
  assert(divides->arity == 2);
4752

4753
  d = divides->arg[0];
×
4754
  if (term_kind(ctx->terms, d) == ARITH_CONSTANT) {
×
4755
    // copy the divider
4756
    q_init(&k);
×
4757
    q_set(&k, rational_term_desc(ctx->terms, d));
×
4758
    assert(q_is_nonzero(&k));
4759

4760
    x = internalize_to_arith(ctx, divides->arg[1]);
×
4761
    y = get_div(ctx, x, &k);  // y := (div x k);
×
4762
    p = context_get_aux_poly(ctx, 3);
×
4763
    context_store_divides_constraint(p, map, x, y, &k); // p is (- x + k * y)
×
4764

4765
    // if tt, assert (p >= 0) <=> x <= k * y
4766
    // if not tt, assert (p < 0) <=> x > k * y
4767
    ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, tt);
×
4768

4769
    q_clear(&k);
×
4770
  } else {
4771
    // not a constant divider: not supported
4772
    longjmp(ctx->env, FORMULA_NOT_LINEAR);
×
4773
  }
4774
}
×
4775

4776

4777

4778

4779

4780

4781
/*
4782
 * Top-level conditional
4783
 * - c = conditional descriptor
4784
 * - if tt is true: assert c otherwise assert not c
4785
 *
4786
 * - c->nconds = number of clauses in the conditional
4787
 * - for each clause i: c->pair[i] = <cond, val>
4788
 * - c->defval = default value
4789
 */
4790
static void assert_toplevel_conditional(context_t *ctx, conditional_t *c, bool tt) {
13✔
4791
  uint32_t i, n;
4792
  literal_t *a;
4793
  literal_t l;
4794
  bool all_false;
4795
  term_t t;
4796

4797
#if 0
4798
  printf("---> toplevel conditional\n");
4799
#endif
4800

4801
  t = simplify_conditional(ctx, c);
13✔
4802
  if (t != NULL_TERM) {
13✔
4803
    assert_term(ctx, t, tt);
2✔
4804
    return;
2✔
4805
  }
4806

4807
  n = c->nconds;
11✔
4808
  a = alloc_istack_array(&ctx->istack, n + 1);
11✔
4809

4810
  all_false = true;
11✔
4811
  for (i=0; i<n; i++) {
72✔
4812
    // a[i] = condition for pair[i]
4813
    a[i] = internalize_to_literal(ctx, c->pair[i].cond);
62✔
4814
    if (a[i] == true_literal) {
62✔
4815
      // if a[i] is true, all other conditions must be false
4816
      assert_term(ctx, c->pair[i].val, tt);
1✔
4817
      goto done;
1✔
4818
    }
4819
    if (a[i] != false_literal) {
61✔
4820
      // l = value for pair[i]
4821
      l = signed_literal(internalize_to_literal(ctx, c->pair[i].val), tt);
58✔
4822
      add_binary_clause(ctx->core, not(a[i]), l); // a[i] => v[i]
58✔
4823
      all_false = false;
58✔
4824
    }
4825
  }
4826

4827
  if (all_false) {
10✔
4828
    // all a[i]s are false: no need for a clause
4829
    assert_term(ctx, c->defval, tt);
1✔
4830
    goto done;
1✔
4831
  }
4832

4833
  // last clause: (a[0] \/ .... \/ a[n] \/ +/-defval)
4834
  a[n] = signed_literal(internalize_to_literal(ctx, c->defval), tt);
9✔
4835
  add_clause(ctx->core, n+1, a);
9✔
4836

4837
  // cleanup
4838
 done:
11✔
4839
  free_istack_array(&ctx->istack, a);
11✔
4840
}
4841

4842

4843

4844
/*
4845
 * Top-level boolean if-then-else (ite c t1 t2)
4846
 * - if tt is true: assert (ite c t1 t2)
4847
 * - if tt is false: assert (not (ite c t1 t2))
4848
 */
4849
static void assert_toplevel_ite(context_t *ctx, composite_term_t *ite, bool tt) {
70✔
4850
  conditional_t *d;
4851
  literal_t l1, l2, l3;
4852

4853
  assert(ite->arity == 3);
4854

4855
  // high-order ite should work. See map_ite_to_eterm
4856

4857
  d = context_make_conditional(ctx, ite);
70✔
4858
  if (d != NULL) {
70✔
4859
    assert_toplevel_conditional(ctx, d, tt);
13✔
4860
    context_free_conditional(ctx, d);
13✔
4861
    return;
13✔
4862
  }
4863

4864
  l1 = internalize_to_literal(ctx, ite->arg[0]);
57✔
4865
  if (l1 == true_literal) {
57✔
4866
    assert_term(ctx, ite->arg[1], tt);
5✔
4867
  } else if (l1 == false_literal) {
52✔
4868
    assert_term(ctx, ite->arg[2], tt);
2✔
4869
  } else {
4870
    l2 = internalize_to_literal(ctx, ite->arg[1]);
50✔
4871
    l3 = internalize_to_literal(ctx, ite->arg[2]);
50✔
4872
    assert_ite(&ctx->gate_manager, l1, l2, l3, tt);
50✔
4873
  }
4874
}
4875

4876

4877
/*
4878
 * Top-level (or t1 ... t_n)
4879
 * - it tt is true: add a clause
4880
 * - it tt is false: assert (not t1) ... (not t_n)
4881
 */
4882
static void assert_toplevel_or(context_t *ctx, composite_term_t *or, bool tt) {
42,971✔
4883
  ivector_t *v;
4884
  int32_t *a;
4885
  uint32_t i, n;
4886

4887
  if (tt) {
42,971✔
4888
    if (context_flatten_or_enabled(ctx)) {
42,955✔
4889
      // Flatten into vector v
4890
      v = &ctx->aux_vector;
15,019✔
4891
      assert(v->size == 0);
4892
      flatten_or_term(ctx, v, or);
15,019✔
4893

4894
      // if v contains a true_term, ignore the clause
4895
      n = v->size;
15,019✔
4896
      if (disjunct_is_true(ctx, v->data, n)) {
15,019✔
4897
        ivector_reset(v);
971✔
4898
        return;
971✔
4899
      }
4900

4901
      // make a copy of v
4902
      a = alloc_istack_array(&ctx->istack, n);
14,048✔
4903
      for (i=0; i<n; i++) {
58,759✔
4904
        a[i] = v->data[i];
44,711✔
4905
      }
4906
      ivector_reset(v);
14,048✔
4907

4908
      for (i=0; i<n; i++) {
58,436✔
4909
        a[i] = internalize_to_literal(ctx, a[i]);
44,541✔
4910
        if (a[i] == true_literal) goto done;
44,541✔
4911
      }
4912

4913
    } else {
4914
      /*
4915
       * No flattening
4916
       */
4917
      n = or->arity;
27,936✔
4918
      if (disjunct_is_true(ctx, or->arg, n)) {
27,936✔
4919
        return;
2,503✔
4920
      }
4921

4922
      a = alloc_istack_array(&ctx->istack, n);
25,433✔
4923
      for (i=0; i<n; i++) {
143,590✔
4924
        a[i] = internalize_to_literal(ctx, or->arg[i]);
118,257✔
4925
        if (a[i] == true_literal) goto done;
118,257✔
4926
      }
4927
    }
4928

4929
    // assert (or a[0] ... a[n-1])
4930
    add_clause(ctx->core, n, a);
39,228✔
4931

4932
  done:
39,481✔
4933
    free_istack_array(&ctx->istack, a);
39,481✔
4934

4935
  } else {
4936
    /*
4937
     * Propagate to children:
4938
     *  (or t_0 ... t_n-1) is false
4939
     * so all children must be false too
4940
     */
4941
    n = or->arity;
16✔
4942
    for (i=0; i<n; i++) {
48✔
4943
      assert_term(ctx, or->arg[i], false);
32✔
4944
    }
4945
  }
4946

4947
}
4948

4949

4950
/*
4951
 * Top-level (xor t1 ... t_n) == tt
4952
 */
4953
static void assert_toplevel_xor(context_t *ctx, composite_term_t *xor, bool tt) {
7✔
4954
  int32_t *a;
4955
  uint32_t i, n;
4956

4957
  n = xor->arity;
7✔
4958
  a = alloc_istack_array(&ctx->istack, n);
7✔
4959
  for (i=0; i<n; i++) {
58✔
4960
    a[i] = internalize_to_literal(ctx, xor->arg[i]);
51✔
4961
  }
4962

4963
  assert_xor(&ctx->gate_manager, n, a, tt);
7✔
4964
  free_istack_array(&ctx->istack, a);
7✔
4965
}
7✔
4966

4967

4968

4969
/*
4970
 * Top-level bit select
4971
 */
4972
static void assert_toplevel_bit_select(context_t *ctx, select_term_t *select, bool tt) {
32,803✔
4973
  term_t t, s;
4974
  thvar_t x;
4975

4976
  /*
4977
   * Check for simplification
4978
   */
4979
  t = intern_tbl_get_root(&ctx->intern, select->arg);
32,803✔
4980
  s = extract_bit(ctx->terms, t, select->idx);
32,803✔
4981
  if (s != NULL_TERM) {
32,803✔
4982
    // (select t i) is s
4983
    assert_term(ctx, s, tt);
63✔
4984
  } else {
4985
    // no simplification
4986
    x = internalize_to_bv(ctx, select->arg);
32,740✔
4987
    ctx->bv.set_bit(ctx->bv_solver, x, select->idx, tt);
32,740✔
4988
  }
4989
}
32,802✔
4990

4991

4992
/*
4993
 * Top-level bitvector atoms
4994
 */
4995
// Auxiliary function: assert (t == 0) or (t != 0) depending on tt
4996
static void assert_toplevel_bveq0(context_t *ctx, term_t t, bool tt) {
28✔
4997
  uint32_t n;
4998
  thvar_t x, y;
4999

5000
  t = intern_tbl_get_root(&ctx->intern, t);
28✔
5001
  n = term_bitsize(ctx->terms, t);
28✔
5002
  x = internalize_to_bv(ctx, t);
28✔
5003
  y = ctx->bv.create_zero(ctx->bv_solver, n);
28✔
5004
  ctx->bv.assert_eq_axiom(ctx->bv_solver, x, y, tt);
28✔
5005
}
28✔
5006

5007

5008
/*
5009
 * Experimental: when t1 and t2 have a common factor C:
5010
 *   t1 = C * u1
5011
 *   t2 = C * u2
5012
 * then we have (t1 /= t2) implies (u1 /= u2).
5013
 * So we can add (u1 /= u2) when (t1 /= t2) is asserted.
5014
 * This is redundant but it may help solving the problem, especially if C is a
5015
 * complex expression.
5016
 */
5017
static void assert_factored_inequality(context_t *ctx, bvfactoring_t *f) {
9✔
5018
  term_t u1, u2;
5019
  thvar_t x, y;
5020

5021
  assert(f->code == BVFACTOR_FOUND);
5022

5023
  //  printf("Asserting factored inequality\n\n");
5024

5025
  u1 = bitvector_factoring_left_term(ctx, f);
9✔
5026
  u2 = bitvector_factoring_right_term(ctx, f);
9✔
5027
  x = internalize_to_bv(ctx, u1);
9✔
5028
  y = internalize_to_bv(ctx, u2);
9✔
5029
  ctx->bv.assert_eq_axiom(ctx->bv_solver, x,  y, false);
9✔
5030
}
9✔
5031

5032
static void assert_toplevel_bveq(context_t *ctx, composite_term_t *eq, bool tt) {
9,325✔
5033
  bveq_simp_t simp;
5034
  ivector_t *v;
5035
  int32_t *a;
5036
  term_t t, t1, t2;
5037
  thvar_t x, y;
5038
  uint32_t i, n;
5039

5040
  assert(eq->arity == 2);
5041

5042
  t1 = intern_tbl_get_root(&ctx->intern, eq->arg[0]);
9,325✔
5043
  t2 = intern_tbl_get_root(&ctx->intern, eq->arg[1]);
9,325✔
5044
  t = simplify_bitvector_eq(ctx, t1, t2);
9,325✔
5045
  if (t != NULL_TERM) {
9,325✔
5046
    // (bveq t1 t2) is equivalent to t
5047
    assert_term(ctx, t, tt);
18✔
5048
    return;
61✔
5049
  }
5050

5051
  if (tt) {
9,307✔
5052
    // try to flatten to a conjunction of terms
5053
    v = &ctx->aux_vector;
7,526✔
5054
    assert(v->size == 0);
5055
    if (bveq_flattens(ctx->terms, t1, t2, v)) {
7,526✔
5056
      /*
5057
       * (bveq t1 t2) is equivalent to (and v[0] ... v[k])
5058
       * (bveq t1 t2) is true at the toplevel so v[0] ... v[k] must all be true
5059
       */
5060

5061
      // make a copy of v
5062
      n = v->size;
19✔
5063
      a = alloc_istack_array(&ctx->istack, n);
19✔
5064
      for (i=0; i<n; i++) {
579✔
5065
        a[i] = v->data[i];
560✔
5066
      }
5067
      ivector_reset(v);
19✔
5068

5069
      // assert
5070
      for (i=0; i<n; i++) {
548✔
5071
        assert_term(ctx, a[i], true);
530✔
5072
      }
5073

5074
      free_istack_array(&ctx->istack, a);
18✔
5075
      return;
18✔
5076
    }
5077

5078
    // flattening failed
5079
    ivector_reset(v);
7,507✔
5080
  }
5081

5082
  /*
5083
   * Try more simplifications
5084
   */
5085
  try_arithmetic_bveq_simplification(ctx, &simp, t1, t2);
9,288✔
5086
  switch (simp.code) {
9,288✔
5087
  case BVEQ_CODE_TRUE:
×
5088
    if (!tt) longjmp(ctx->env, TRIVIALLY_UNSAT);
×
5089
    break;
×
5090

5091
  case BVEQ_CODE_FALSE:
×
5092
    if (tt) longjmp(ctx->env, TRIVIALLY_UNSAT);
×
5093
    break;
×
5094

5095
  case BVEQ_CODE_REDUCED:
36✔
5096
    t1 = intern_tbl_get_root(&ctx->intern, simp.left);
36✔
5097
    t2 = intern_tbl_get_root(&ctx->intern, simp.right);
36✔
5098
    break;
36✔
5099

5100
  case BVEQ_CODE_REDUCED0:
28✔
5101
    // reduced to simp.left == 0
5102
    assert_toplevel_bveq0(ctx, simp.left, tt);
28✔
5103
    return;
28✔
5104

5105
  default:
9,224✔
5106
    break;
9,224✔
5107
  }
5108

5109
  /*
5110
   * Try Factoring
5111
   */
5112
  if (!tt) {
9,260✔
5113
    bvfactoring_t *factoring;
5114
    bool eq = false;
1,757✔
5115

5116
    factoring = objstack_alloc(&ctx->ostack, sizeof(bvfactoring_t), (cleaner_t) delete_bvfactoring);
1,757✔
5117
    init_bvfactoring(factoring);
1,757✔
5118

5119
    try_bitvector_factoring(ctx, factoring, t1, t2);
1,757✔
5120
    switch (factoring->code) {
1,757✔
5121
    case BVFACTOR_EQUAL:
4✔
5122
      eq = true;
4✔
5123
      break;
4✔
5124

5125
    case BVFACTOR_FOUND:
9✔
5126
      assert_factored_inequality(ctx, factoring);
9✔
5127
      break;
9✔
5128

5129
    default:
1,744✔
5130
      break;
1,744✔
5131
    }
5132
    // delete_bvfactoring(&factoring);
5133
    objstack_pop(&ctx->ostack);
1,757✔
5134

5135
    if (eq) {
1,757✔
5136
      longjmp(ctx->env, TRIVIALLY_UNSAT);
4✔
5137
    }
5138
  }
5139

5140
  /*
5141
   * NOTE: asserting (eq t1 t2) in the egraph instead makes things worse
5142
   */
5143
  x = internalize_to_bv(ctx, t1);
9,256✔
5144
  y = internalize_to_bv(ctx, t2);
9,256✔
5145
  ctx->bv.assert_eq_axiom(ctx->bv_solver, x,  y, tt);
9,256✔
5146
}
5147

5148
static void assert_toplevel_bvge(context_t *ctx, composite_term_t *ge, bool tt) {
1,465✔
5149
  thvar_t x, y;
5150

5151
  assert(ge->arity == 2);
5152

5153
  x = internalize_to_bv(ctx, ge->arg[0]);
1,465✔
5154
  y = internalize_to_bv(ctx, ge->arg[1]);
1,465✔
5155
  ctx->bv.assert_ge_axiom(ctx->bv_solver, x,  y, tt);
1,465✔
5156
}
1,465✔
5157

5158
static void assert_toplevel_bvsge(context_t *ctx, composite_term_t *sge, bool tt) {
459✔
5159
  thvar_t x, y;
5160

5161
  assert(sge->arity == 2);
5162

5163
  x = internalize_to_bv(ctx, sge->arg[0]);
459✔
5164
  y = internalize_to_bv(ctx, sge->arg[1]);
459✔
5165
  ctx->bv.assert_sge_axiom(ctx->bv_solver, x,  y, tt);
459✔
5166
}
459✔
5167

5168

5169

5170
/*
5171
 * Top-level formula t:
5172
 * - t is a boolean term (or the negation of a boolean term)
5173
 * - t must be a root in the internalization table and must be mapped to true
5174
 */
5175
static void assert_toplevel_formula(context_t *ctx, term_t t) {
125,373✔
5176
  term_table_t *terms;
5177
  int32_t code;
5178
  literal_t l;
5179
  bool tt;
5180

5181
  assert(is_boolean_term(ctx->terms, t) &&
5182
         intern_tbl_is_root(&ctx->intern, t) &&
5183
         term_is_true(ctx, t));
5184

5185
  tt = is_pos_term(t);
125,373✔
5186
  t = unsigned_term(t);
125,373✔
5187

5188
  /*
5189
   * Now: t is a root and has positive polarity
5190
   * - tt indicates whether we assert t or (not t):
5191
   *   tt true: assert t
5192
   *   tt false: assert (not t)
5193
   */
5194
  terms = ctx->terms;
125,373✔
5195
  if (context_atom_requires_mcsat(ctx, t)) {
125,373✔
5196
    l = map_mcsat_atom_to_literal(ctx, t);
13✔
5197
    code = literal2code(l);
13✔
5198
    intern_tbl_remap_root(&ctx->intern, t, code);
13✔
5199
    assert_internalization_code(ctx, code, tt);
13✔
5200
    return;
13✔
5201
  }
5202

5203
  switch (term_kind(terms, t)) {
125,360✔
5204
  case CONSTANT_TERM:
×
5205
  case UNINTERPRETED_TERM:
5206
    // should be eliminated by flattening
5207
    code = INTERNAL_ERROR;
×
5208
    goto abort;
×
5209

5210
  case ITE_TERM:
68✔
5211
  case ITE_SPECIAL:
5212
    assert_toplevel_ite(ctx, ite_term_desc(terms, t), tt);
68✔
5213
    break;
68✔
5214

5215
  case OR_TERM:
42,940✔
5216
    assert_toplevel_or(ctx, or_term_desc(terms, t), tt);
42,940✔
5217
    break;
42,940✔
5218

5219
  case XOR_TERM:
7✔
5220
    assert_toplevel_xor(ctx, xor_term_desc(terms, t), tt);
7✔
5221
    break;
7✔
5222

5223
  case EQ_TERM:
5,145✔
5224
    assert_toplevel_eq(ctx, eq_term_desc(terms, t), tt);
5,145✔
5225
    break;
5,143✔
5226

5227
  case ARITH_IS_INT_ATOM:
×
5228
    assert_toplevel_arith_is_int(ctx, arith_is_int_arg(terms, t), tt);
×
5229
    break;
×
5230

5231
  case ARITH_EQ_ATOM:
2,264✔
5232
    assert_toplevel_arith_eq(ctx, arith_eq_arg(terms, t), tt);
2,264✔
5233
    break;
2,262✔
5234

5235
  case ARITH_GE_ATOM:
27,848✔
5236
    assert_toplevel_arith_geq(ctx, arith_ge_arg(terms, t), tt);
27,848✔
5237
    break;
27,847✔
5238

5239
  case ARITH_BINEQ_ATOM:
3,201✔
5240
    assert_toplevel_arith_bineq(ctx, arith_bineq_atom_desc(terms, t), tt);
3,201✔
5241
    break;
3,201✔
5242

5243
  case ARITH_DIVIDES_ATOM:
×
5244
    assert_toplevel_arith_divides(ctx, arith_divides_atom_desc(terms, t), tt);
×
5245
    break;
×
5246

5247
  case APP_TERM:
250✔
5248
    assert_toplevel_apply(ctx, app_term_desc(terms, t), tt);
250✔
5249
    break;
250✔
5250

5251
  case SELECT_TERM:
×
5252
    assert_toplevel_select(ctx, select_term_desc(terms, t), tt);
×
5253
    break;
×
5254

5255
  case DISTINCT_TERM:
173✔
5256
    assert_toplevel_distinct(ctx, distinct_term_desc(terms, t), tt);
173✔
5257
    break;
171✔
5258

5259
  case VARIABLE:
×
5260
    code = FREE_VARIABLE_IN_FORMULA;
×
5261
    goto abort;
×
5262

5263
  case FORALL_TERM:
×
5264
    if (context_in_strict_mode(ctx)) {
×
5265
      code = QUANTIFIERS_NOT_SUPPORTED;
×
5266
      goto abort;
×
5267
    }
5268
    break;
×
5269

5270
  case BIT_TERM:
32,260✔
5271
    assert_toplevel_bit_select(ctx, bit_term_desc(terms, t), tt);
32,260✔
5272
    break;
32,260✔
5273

5274
  case BV_EQ_ATOM:
9,286✔
5275
    assert_toplevel_bveq(ctx, bveq_atom_desc(terms, t), tt);
9,286✔
5276
    break;
9,278✔
5277

5278
  case BV_GE_ATOM:
1,463✔
5279
    assert_toplevel_bvge(ctx, bvge_atom_desc(terms, t), tt);
1,463✔
5280
    break;
1,463✔
5281

5282
  case BV_SGE_ATOM:
455✔
5283
    assert_toplevel_bvsge(ctx, bvsge_atom_desc(terms, t), tt);
455✔
5284
    break;
455✔
5285

5286
  default:
×
5287
    code = INTERNAL_ERROR;
×
5288
    goto abort;
×
5289
  }
5290

5291
  return;
125,345✔
5292

5293
 abort:
×
5294
  longjmp(ctx->env, code);
×
5295
}
5296

5297

5298

5299
/*
5300
 * Assert (t == tt) for a boolean term t:
5301
 * - if t is not internalized, record the mapping
5302
 *   (root t) --> tt in the internalization table
5303
 */
5304
static void assert_term(context_t *ctx, term_t t, bool tt) {
998✔
5305
  term_table_t *terms;
5306
  int32_t code;
5307
  literal_t l;
5308

5309
  assert(is_boolean_term(ctx->terms, t));
5310

5311
  /*
5312
   * Apply substitution + fix polarity
5313
   */
5314
  t = intern_tbl_get_root(&ctx->intern, t);
998✔
5315
  tt ^= is_neg_term(t);
998✔
5316
  t = unsigned_term(t);
998✔
5317

5318
  if (intern_tbl_root_is_mapped(&ctx->intern, t)) {
998✔
5319
    /*
5320
     * The root is already mapped:
5321
     * Either t is already internalized, or it occurs in
5322
     * one of the vectors top_eqs, top_atoms, top_formulas
5323
     * and it will be internalized/asserted later.
5324
     */
5325
    code = intern_tbl_map_of_root(&ctx->intern, t);
171✔
5326
    assert_internalization_code(ctx, code, tt);
171✔
5327

5328
  } else {
5329
    if (context_atom_requires_mcsat(ctx, t)) {
827✔
NEW
5330
      l = map_mcsat_atom_to_literal(ctx, t);
×
NEW
5331
      code = literal2code(l);
×
NEW
5332
      intern_tbl_map_root(&ctx->intern, t, code);
×
NEW
5333
      assert_internalization_code(ctx, code, tt);
×
NEW
5334
      return;
×
5335
    }
5336

5337
    // store the mapping t --> tt
5338
    intern_tbl_map_root(&ctx->intern, t, bool2code(tt));
827✔
5339

5340
    // internalize and assert
5341
    terms = ctx->terms;
827✔
5342
    switch (term_kind(terms, t)) {
827✔
5343
    case CONSTANT_TERM:
×
5344
      // should always be internalized
5345
      code = INTERNAL_ERROR;
×
5346
      goto abort;
×
5347

5348
    case UNINTERPRETED_TERM:
1✔
5349
      // nothing to do: t --> true/false in the internalization table
5350
      break;
1✔
5351

5352
    case ITE_TERM:
2✔
5353
    case ITE_SPECIAL:
5354
      assert_toplevel_ite(ctx, ite_term_desc(terms, t), tt);
2✔
5355
      break;
2✔
5356

5357
    case OR_TERM:
31✔
5358
      assert_toplevel_or(ctx, or_term_desc(terms, t), tt);
31✔
5359
      break;
31✔
5360

5361
    case XOR_TERM:
×
5362
      assert_toplevel_xor(ctx, xor_term_desc(terms, t), tt);
×
5363
      break;
×
5364

5365
    case EQ_TERM:
11✔
5366
      assert_toplevel_eq(ctx, eq_term_desc(terms, t), tt);
11✔
5367
      break;
11✔
5368

5369
    case ARITH_IS_INT_ATOM:
×
5370
      assert_toplevel_arith_is_int(ctx, arith_is_int_arg(terms, t), tt);
×
5371
      break;
×
5372

5373
    case ARITH_EQ_ATOM:
4✔
5374
      assert_toplevel_arith_eq(ctx, arith_eq_arg(terms, t), tt);
4✔
5375
      break;
4✔
5376

5377
    case ARITH_GE_ATOM:
7✔
5378
      assert_toplevel_arith_geq(ctx, arith_ge_arg(terms, t), tt);
7✔
5379
      break;
7✔
5380

5381
    case ARITH_BINEQ_ATOM:
181✔
5382
      assert_toplevel_arith_bineq(ctx, arith_bineq_atom_desc(terms, t), tt);
181✔
5383
      break;
181✔
5384

5385
    case ARITH_DIVIDES_ATOM:
×
5386
      assert_toplevel_arith_divides(ctx, arith_divides_atom_desc(terms, t), tt);
×
5387
      break;
×
5388

5389
    case APP_TERM:
2✔
5390
      assert_toplevel_apply(ctx, app_term_desc(terms, t), tt);
2✔
5391
      break;
2✔
5392

5393
    case SELECT_TERM:
×
5394
      assert_toplevel_select(ctx, select_term_desc(terms, t), tt);
×
5395
      break;
×
5396

5397
    case DISTINCT_TERM:
×
5398
      assert_toplevel_distinct(ctx, distinct_term_desc(terms, t), tt);
×
5399
      break;
×
5400

5401
    case VARIABLE:
×
5402
      code = FREE_VARIABLE_IN_FORMULA;
×
5403
      goto abort;
×
5404

5405
    case FORALL_TERM:
×
5406
      if (context_in_strict_mode(ctx)) {
×
5407
        code = QUANTIFIERS_NOT_SUPPORTED;
×
5408
        goto abort;
×
5409
      }
5410
      break;
×
5411

5412
    case BIT_TERM:
543✔
5413
      assert_toplevel_bit_select(ctx, bit_term_desc(terms, t), tt);
543✔
5414
      break;
542✔
5415

5416
    case BV_EQ_ATOM:
39✔
5417
      assert_toplevel_bveq(ctx, bveq_atom_desc(terms, t), tt);
39✔
5418
      break;
39✔
5419

5420
    case BV_GE_ATOM:
2✔
5421
      assert_toplevel_bvge(ctx, bvge_atom_desc(terms, t), tt);
2✔
5422
      break;
2✔
5423

5424
    case BV_SGE_ATOM:
4✔
5425
      assert_toplevel_bvsge(ctx, bvsge_atom_desc(terms, t), tt);
4✔
5426
      break;
4✔
5427

5428
    default:
×
5429
      code = INTERNAL_ERROR;
×
5430
      goto abort;
×
5431
    }
5432
  }
5433

5434
  return;
993✔
5435

5436
 abort:
×
5437
  longjmp(ctx->env, code);
×
5438
}
5439

5440

5441

5442

5443
/************************
5444
 *  PARAMETERS/OPTIONS  *
5445
 ***********************/
5446

5447
/*
5448
 * Map architecture id to theories word
5449
 */
5450
static const uint32_t arch2theories[NUM_ARCH] = {
5451
  0,                           //  CTX_ARCH_NOSOLVERS --> empty theory
5452

5453
  UF_MASK,                     //  CTX_ARCH_EG
5454
  ARITH_MASK,                  //  CTX_ARCH_SPLX
5455
  IDL_MASK,                    //  CTX_ARCH_IFW
5456
  RDL_MASK,                    //  CTX_ARCH_RFW
5457
  BV_MASK,                     //  CTX_ARCH_BV
5458
  UF_MASK|FUN_MASK,            //  CTX_ARCH_EGFUN
5459
  UF_MASK|ARITH_MASK,          //  CTX_ARCH_EGSPLX
5460
  UF_MASK|BV_MASK,             //  CTX_ARCH_EGBV
5461
  UF_MASK|ARITH_MASK|FUN_MASK, //  CTX_ARCH_EGFUNSPLX
5462
  UF_MASK|BV_MASK|FUN_MASK,    //  CTX_ARCH_EGFUNBV
5463
  UF_MASK|BV_MASK|ARITH_MASK,  //  CTX_ARCH_EGSPLXBV
5464
  ALLTH_MASK,                  //  CTX_ARCH_EGFUNSPLXBV
5465

5466
  IDL_MASK,                    //  CTX_ARCH_AUTO_IDL
5467
  RDL_MASK,                    //  CTX_ARCH_AUTO_RDL
5468

5469
  UF_MASK|ARITH_MASK|FUN_MASK  //  CTX_ARCH_MCSAT
5470
};
5471

5472

5473
/*
5474
 * Each architecture has a fixed set of solver components:
5475
 * - the set of components is stored as a bit vector (on 8bits)
5476
 * - this uses the following bit-masks
5477
 * For the AUTO_xxx architecture, nothing is required initially,
5478
 * so the bitmask is 0.
5479
 */
5480
#define EGRPH  0x1
5481
#define SPLX   0x2
5482
#define IFW    0x4
5483
#define RFW    0x8
5484
#define BVSLVR 0x10
5485
#define FSLVR  0x20
5486
#define MCSAT  0x40
5487

5488
static const uint8_t arch_components[NUM_ARCH] = {
5489
  0,                        //  CTX_ARCH_NOSOLVERS
5490

5491
  EGRPH,                    //  CTX_ARCH_EG
5492
  SPLX,                     //  CTX_ARCH_SPLX
5493
  IFW,                      //  CTX_ARCH_IFW
5494
  RFW,                      //  CTX_ARCH_RFW
5495
  BVSLVR,                   //  CTX_ARCH_BV
5496
  EGRPH|FSLVR,              //  CTX_ARCH_EGFUN
5497
  EGRPH|SPLX,               //  CTX_ARCH_EGSPLX
5498
  EGRPH|BVSLVR,             //  CTX_ARCH_EGBV
5499
  EGRPH|SPLX|FSLVR,         //  CTX_ARCH_EGFUNSPLX
5500
  EGRPH|BVSLVR|FSLVR,       //  CTX_ARCH_EGFUNBV
5501
  EGRPH|SPLX|BVSLVR,        //  CTX_ARCH_EGSPLXBV
5502
  EGRPH|SPLX|BVSLVR|FSLVR,  //  CTX_ARCH_EGFUNSPLXBV
5503

5504
  0,                        //  CTX_ARCH_AUTO_IDL
5505
  0,                        //  CTX_ARCH_AUTO_RDL
5506

5507
  MCSAT                     //  CTX_ARCH_MCSAT
5508
};
5509

5510

5511
/*
5512
 * Smt mode for a context mode
5513
 */
5514
static const smt_mode_t core_mode[NUM_MODES] = {
5515
  SMT_MODE_BASIC,       // one check
5516
  SMT_MODE_BASIC,       // multichecks
5517
  SMT_MODE_PUSHPOP,     // push/pop
5518
  SMT_MODE_INTERACTIVE, // interactive
5519
};
5520

5521

5522
/*
5523
 * Flags for a context mode
5524
 */
5525
static const uint32_t mode2options[NUM_MODES] = {
5526
  0,
5527
  MULTICHECKS_OPTION_MASK,
5528
  MULTICHECKS_OPTION_MASK|PUSHPOP_OPTION_MASK,
5529
  MULTICHECKS_OPTION_MASK|PUSHPOP_OPTION_MASK|CLEANINT_OPTION_MASK,
5530
};
5531

5532

5533

5534

5535

5536

5537
/*
5538
 * SIMPLEX OPTIONS
5539
 */
5540

5541
/*
5542
 * Which version of the arithmetic solver is present
5543
 */
5544
bool context_has_idl_solver(context_t *ctx) {
8✔
5545
  uint8_t solvers;
5546
  solvers = arch_components[ctx->arch];
8✔
5547
  return ctx->arith_solver != NULL && (solvers & IFW);
8✔
5548
}
5549

5550
bool context_has_rdl_solver(context_t *ctx) {
×
5551
  uint8_t solvers;
5552
  solvers = arch_components[ctx->arch];
×
5553
  return ctx->arith_solver != NULL && (solvers & RFW);
×
5554
}
5555

5556
bool context_has_simplex_solver(context_t *ctx) {
45,845✔
5557
  uint8_t solvers;
5558
  solvers = arch_components[ctx->arch];
45,845✔
5559
  return ctx->arith_solver != NULL && (solvers & SPLX);
45,845✔
5560
}
5561

5562

5563
/*
5564
 * If the simplex solver already exists, the options are propagated.
5565
 * Otherwise, they are recorded into the option flags. They will
5566
 * be set up when the simplex solver is created.
5567
 */
5568
void enable_splx_eager_lemmas(context_t *ctx) {
178✔
5569
  ctx->options |= SPLX_EGRLMAS_OPTION_MASK;
178✔
5570
  if (context_has_simplex_solver(ctx)) {
178✔
5571
    simplex_enable_eager_lemmas(ctx->arith_solver);
178✔
5572
  }
5573
}
178✔
5574

5575
void disable_splx_eager_lemmas(context_t *ctx) {
×
5576
  ctx->options &= ~SPLX_EGRLMAS_OPTION_MASK;
×
5577
  if (context_has_simplex_solver(ctx)) {
×
5578
    simplex_disable_eager_lemmas(ctx->arith_solver);
×
5579
  }
5580
}
×
5581

5582

5583
void enable_splx_periodic_icheck(context_t *ctx) {
151✔
5584
  ctx->options |= SPLX_ICHECK_OPTION_MASK;
151✔
5585
  if (context_has_simplex_solver(ctx)) {
151✔
5586
    simplex_enable_periodic_icheck(ctx->arith_solver);
140✔
5587
  }
5588
}
151✔
5589

5590
void disable_splx_periodic_icheck(context_t *ctx) {
×
5591
  ctx->options &= ~SPLX_ICHECK_OPTION_MASK;
×
5592
  if (context_has_simplex_solver(ctx)) {
×
5593
    simplex_disable_periodic_icheck(ctx->arith_solver);
×
5594
  }
5595
}
×
5596

5597
void enable_splx_eqprop(context_t *ctx) {
77✔
5598
  ctx->options |= SPLX_EQPROP_OPTION_MASK;
77✔
5599
  if (context_has_simplex_solver(ctx)) {
77✔
5600
    simplex_enable_eqprop(ctx->arith_solver);
77✔
5601
  }
5602
}
77✔
5603

5604
void disable_splx_eqprop(context_t *ctx) {
×
5605
  ctx->options &= ~SPLX_EQPROP_OPTION_MASK;
×
5606
  if (context_has_simplex_solver(ctx)) {
×
5607
    simplex_disable_eqprop(ctx->arith_solver);
×
5608
  }
5609
}
×
5610

5611

5612

5613

5614
/******************
5615
 *  EMPTY SOLVER  *
5616
 *****************/
5617

5618
/*
5619
 * We need an empty theory solver for initializing
5620
 * the core if the architecture is NOSOLVERS.
5621
 */
5622
static void donothing(void *solver) {
2,615✔
5623
}
2,615✔
5624

5625
static void null_backtrack(void *solver, uint32_t backlevel) {
×
5626
}
×
5627

5628
static bool null_propagate(void *solver) {
×
5629
  return true;
×
5630
}
5631

5632
static fcheck_code_t null_final_check(void *solver) {
×
5633
  return FCHECK_SAT;
×
5634
}
5635

5636
static th_ctrl_interface_t null_ctrl = {
5637
  donothing,        // start_internalization
5638
  donothing,        // start_search
5639
  null_propagate,   // propagate
5640
  null_final_check, // final check
5641
  donothing,        // increase_decision_level
5642
  null_backtrack,   // backtrack
5643
  donothing,        // push
5644
  donothing,        // pop
5645
  donothing,        // reset
5646
  donothing,        // clear
5647
};
5648

5649

5650
// for the smt interface, nothing should be called since there are no atoms
5651
static th_smt_interface_t null_smt = {
5652
  NULL, NULL, NULL, NULL, NULL,
5653
};
5654

5655

5656

5657

5658
/****************************
5659
 *  ARCHITECTURE & SOLVERS  *
5660
 ***************************/
5661

5662
/*
5663
 * Check whether a given architecture includes a specific solver
5664
 */
5665
bool context_arch_has_egraph(context_arch_t arch) {
417✔
5666
  return arch_components[arch] & EGRPH;
417✔
5667
}
5668

5669
bool context_arch_has_bv(context_arch_t arch) {
×
5670
  return arch_components[arch] & BVSLVR;
×
5671
}
5672

5673
bool context_arch_has_fun(context_arch_t arch) {
×
5674
  return arch_components[arch] & FSLVR;
×
5675
}
5676

5677
bool context_arch_has_arith(context_arch_t arch) {
×
5678
  return arch_components[arch] & (SPLX|IFW|RFW);
×
5679
}
5680

5681
bool context_arch_has_mcsat(context_arch_t arch) {
×
5682
  return arch_components[arch] & MCSAT;
×
5683
}
5684

5685
bool context_arch_has_simplex(context_arch_t arch) {
×
5686
  return arch_components[arch] & SPLX;
×
5687
}
5688

5689
bool context_arch_has_ifw(context_arch_t arch) {
×
5690
  return arch_components[arch] & IFW;
×
5691
}
5692

5693
bool context_arch_has_rfw(context_arch_t arch) {
×
5694
  return arch_components[arch] & RFW;
×
5695
}
5696

5697

5698
/****************************
5699
 *  SOLVER INITIALIZATION   *
5700
 ***************************/
5701

5702
/*
5703
 * Create and initialize the egraph
5704
 * - the core must be created first
5705
 */
5706
static void create_egraph(context_t *ctx) {
4,793✔
5707
  egraph_t *egraph;
5708

5709
  assert(ctx->egraph == NULL);
5710

5711
  egraph = (egraph_t *) safe_malloc(sizeof(egraph_t));
4,793✔
5712
  init_egraph(egraph, ctx->types);
4,793✔
5713
  ctx->egraph = egraph;
4,793✔
5714
}
4,793✔
5715

5716

5717
/*
5718
 * Create and initialize the mcsat solver
5719
 */
5720
static void create_mcsat(context_t *ctx) {
748✔
5721
  assert(ctx->mcsat == NULL);
5722
  ctx->mcsat = mcsat_new(ctx);
748✔
5723
}
748✔
5724

5725

5726

5727
/*
5728
 * Create and initialize the idl solver and attach it to the core
5729
 * - there must be no other solvers and no egraph
5730
 * - if automatic is true, attach the solver to the core, otherwise
5731
 *   initialize the core
5732
 * - copy the solver's internalization interface into arith
5733
 */
5734
static void create_idl_solver(context_t *ctx, bool automatic) {
26✔
5735
  idl_solver_t *solver;
5736
  smt_mode_t cmode;
5737

5738
  assert(ctx->egraph == NULL && ctx->arith_solver == NULL && ctx->bv_solver == NULL &&
5739
         ctx->fun_solver == NULL && ctx->core != NULL);
5740

5741
  cmode = core_mode[ctx->mode];
26✔
5742
  solver = (idl_solver_t *) safe_malloc(sizeof(idl_solver_t));
26✔
5743
  init_idl_solver(solver, ctx->core, &ctx->gate_manager);
26✔
5744
  if (automatic) {
26✔
5745
    smt_core_reset_thsolver(ctx->core, solver, idl_ctrl_interface(solver),
26✔
5746
                            idl_smt_interface(solver));
5747
  } else {
5748
    init_smt_core(ctx->core, CTX_DEFAULT_CORE_SIZE, solver, idl_ctrl_interface(solver),
×
5749
                  idl_smt_interface(solver), cmode);
5750
  }
5751
  idl_solver_init_jmpbuf(solver, &ctx->env);
26✔
5752
  ctx->arith_solver = solver;
26✔
5753
  ctx->arith = *idl_arith_interface(solver);
26✔
5754
}
26✔
5755

5756

5757
/*
5758
 * Create and initialize the rdl solver and attach it to the core.
5759
 * - there must be no other solvers and no egraph
5760
 * - if automatic is true, attach rdl to the core, otherwise
5761
 *   initialize the core
5762
 * - copy the solver's internalization interface in ctx->arith
5763
 */
5764
static void create_rdl_solver(context_t *ctx, bool automatic) {
8✔
5765
  rdl_solver_t *solver;
5766
  smt_mode_t cmode;
5767

5768
  assert(ctx->egraph == NULL && ctx->arith_solver == NULL && ctx->bv_solver == NULL &&
5769
         ctx->fun_solver == NULL && ctx->core != NULL);
5770

5771
  cmode = core_mode[ctx->mode];
8✔
5772
  solver = (rdl_solver_t *) safe_malloc(sizeof(rdl_solver_t));
8✔
5773
  init_rdl_solver(solver, ctx->core, &ctx->gate_manager);
8✔
5774
  if (automatic) {
8✔
5775
    smt_core_reset_thsolver(ctx->core, solver, rdl_ctrl_interface(solver),
8✔
5776
                            rdl_smt_interface(solver));
5777
  } else {
5778
    init_smt_core(ctx->core, CTX_DEFAULT_CORE_SIZE, solver, rdl_ctrl_interface(solver),
×
5779
                  rdl_smt_interface(solver), cmode);
5780
  }
5781
  rdl_solver_init_jmpbuf(solver, &ctx->env);
8✔
5782
  ctx->arith_solver = solver;
8✔
5783
  ctx->arith = *rdl_arith_interface(solver);
8✔
5784
}
8✔
5785

5786

5787
/*
5788
 * Create an initialize the simplex solver and attach it to the core
5789
 * or to the egraph if the egraph exists.
5790
 * - if automatic is true, this is part of auto_idl or auto_rdl. So the
5791
 *   core is already initialized.
5792
 */
5793
static void create_simplex_solver(context_t *ctx, bool automatic) {
14,909✔
5794
  simplex_solver_t *solver;
5795
  smt_mode_t cmode;
5796

5797
  assert(ctx->arith_solver == NULL && ctx->core != NULL);
5798

5799
  cmode = core_mode[ctx->mode];
14,909✔
5800
  solver = (simplex_solver_t *) safe_malloc(sizeof(simplex_solver_t));
14,909✔
5801
  init_simplex_solver(solver, ctx->core, &ctx->gate_manager, ctx->egraph);
14,909✔
5802

5803
  // set simplex options
5804
  if (splx_eager_lemmas_enabled(ctx)) {
14,909✔
5805
    simplex_enable_eager_lemmas(solver);
×
5806
  }
5807
  if (splx_periodic_icheck_enabled(ctx)) {
14,909✔
5808
    simplex_enable_periodic_icheck(solver);
×
5809
  }
5810
  if (splx_eqprop_enabled(ctx)) {
14,909✔
5811
    simplex_enable_eqprop(solver);
×
5812
  }
5813

5814
  // row saving must be enabled unless we're in ONECHECK mode
5815
  if (ctx->mode != CTX_MODE_ONECHECK) {
14,909✔
5816
    simplex_enable_row_saving(solver);
14,757✔
5817
  }
5818

5819
  if (ctx->egraph != NULL) {
14,909✔
5820
    // attach the simplex solver as a satellite solver to the egraph
5821
    egraph_attach_arithsolver(ctx->egraph, solver, simplex_ctrl_interface(solver),
4,336✔
5822
                              simplex_smt_interface(solver), simplex_egraph_interface(solver),
5823
                              simplex_arith_egraph_interface(solver));
5824
  } else if (!automatic) {
10,573✔
5825
    // attach simplex to the core and initialize the core
5826
    init_smt_core(ctx->core, CTX_DEFAULT_CORE_SIZE, solver, simplex_ctrl_interface(solver),
10,572✔
5827
                  simplex_smt_interface(solver), cmode);
5828
  } else {
5829
    // the core is already initialized: attach simplex
5830
    smt_core_reset_thsolver(ctx->core, solver, simplex_ctrl_interface(solver),
1✔
5831
                            simplex_smt_interface(solver));
5832
  }
5833

5834
  simplex_solver_init_jmpbuf(solver, &ctx->env);
14,909✔
5835
  ctx->arith_solver = solver;
14,909✔
5836
  ctx->arith = *simplex_arith_interface(solver);
14,909✔
5837
}
14,909✔
5838

5839

5840
/*
5841
 * Create IDL/SIMPLEX solver based on ctx->dl_profile
5842
 */
5843
static void create_auto_idl_solver(context_t *ctx) {
27✔
5844
  dl_data_t *profile;
5845
  int32_t bound;
5846
  double atom_density;
5847

5848
  assert(ctx->dl_profile != NULL);
5849
  profile = ctx->dl_profile;
27✔
5850

5851
  if (q_is_smallint(&profile->path_bound)) {
27✔
5852
    bound = q_get_smallint(&profile->path_bound);
26✔
5853
  } else {
5854
    bound = INT32_MAX;
1✔
5855
  }
5856

5857
  if (bound >= 1073741824) {
27✔
5858
    // simplex required because of arithmetic overflow
5859
    create_simplex_solver(ctx, true);
1✔
5860
    ctx->arch = CTX_ARCH_SPLX;
1✔
5861
  } else if (profile->num_vars >= 1000) {
26✔
5862
    // too many variables for FW
5863
    create_simplex_solver(ctx, true);
×
5864
    ctx->arch = CTX_ARCH_SPLX;
×
5865
  } else if (profile->num_vars <= 200 || profile->num_eqs == 0) {
26✔
5866
    // use FW for now, until we've tested SIMPLEX more
5867
    // 0 equalities usually means a scheduling problem
5868
    // --flatten works better on IDL/FW
5869
    create_idl_solver(ctx, true);
26✔
5870
    ctx->arch = CTX_ARCH_IFW;
26✔
5871
    enable_diseq_and_or_flattening(ctx);
26✔
5872

5873
  } else {
5874

5875
    // problem density
5876
    if (profile->num_vars > 0) {
×
5877
      atom_density = ((double) profile->num_atoms)/profile->num_vars;
×
5878
    } else {
5879
      atom_density = 0;
×
5880
    }
5881

5882
    if (atom_density >= 10.0) {
×
5883
      // high density: use FW
5884
      create_idl_solver(ctx, true);
×
5885
      ctx->arch = CTX_ARCH_IFW;
×
5886
      enable_diseq_and_or_flattening(ctx);
×
5887
    } else {
5888
      create_simplex_solver(ctx, true);
×
5889
      ctx->arch = CTX_ARCH_SPLX;
×
5890
    }
5891
  }
5892
}
27✔
5893

5894

5895
/*
5896
 * Create RDL/SIMPLEX solver based on ctx->dl_profile
5897
 */
5898
static void create_auto_rdl_solver(context_t *ctx) {
8✔
5899
  dl_data_t *profile;
5900
  double atom_density;
5901

5902
  assert(ctx->dl_profile != NULL);
5903
  profile = ctx->dl_profile;
8✔
5904

5905
  if (profile->num_vars >= 1000) {
8✔
5906
    create_simplex_solver(ctx, true);
×
5907
    ctx->arch = CTX_ARCH_SPLX;
×
5908
  } else if (profile->num_vars <= 200 || profile->num_eqs == 0) {
8✔
5909
    create_rdl_solver(ctx, true);
8✔
5910
    ctx->arch = CTX_ARCH_RFW;
8✔
5911
  } else {
5912
    // problem density
5913
    if (profile->num_vars > 0) {
×
5914
      atom_density = ((double) profile->num_atoms)/profile->num_vars;
×
5915
    } else {
5916
      atom_density = 0;
×
5917
    }
5918

5919
    if (atom_density >= 7.0) {
×
5920
      // high density: use FW
5921
      create_rdl_solver(ctx, true);
×
5922
      ctx->arch = CTX_ARCH_RFW;
×
5923
    } else {
5924
      // low-density: use SIMPLEX
5925
      create_simplex_solver(ctx, true);
×
5926
      ctx->arch = CTX_ARCH_SPLX;
×
5927
    }
5928
  }
5929
}
8✔
5930

5931

5932

5933
/*
5934
 * Create the bitvector solver
5935
 * - attach it to the egraph if there's an egraph
5936
 * - attach it to the core and initialize the core otherwise
5937
 */
5938
static void create_bv_solver(context_t *ctx) {
10,659✔
5939
  bv_solver_t *solver;
5940
  smt_mode_t cmode;
5941

5942
  assert(ctx->bv_solver == NULL && ctx->core != NULL);
5943

5944
  cmode = core_mode[ctx->mode];
10,659✔
5945
  solver = (bv_solver_t *) safe_malloc(sizeof(bv_solver_t));
10,659✔
5946
  init_bv_solver(solver, ctx->core, ctx->egraph);
10,659✔
5947

5948
  if (ctx->egraph != NULL) {
10,659✔
5949
    // attach as a satellite to the egraph
5950
    egraph_attach_bvsolver(ctx->egraph, solver, bv_solver_ctrl_interface(solver),
4,419✔
5951
                           bv_solver_smt_interface(solver), bv_solver_egraph_interface(solver),
5952
                           bv_solver_bv_egraph_interface(solver));
5953
  } else {
5954
    // attach to the core and initialize the core
5955
    init_smt_core(ctx->core, CTX_DEFAULT_CORE_SIZE, solver, bv_solver_ctrl_interface(solver),
6,240✔
5956
                  bv_solver_smt_interface(solver), cmode);
5957
  }
5958

5959
  // EXPERIMENT
5960
  //  smt_core_make_etable(ctx->core);
5961
  // END
5962

5963
  bv_solver_init_jmpbuf(solver, &ctx->env);
10,659✔
5964
  ctx->bv_solver = solver;
10,659✔
5965
  ctx->bv = *bv_solver_bv_interface(solver);
10,659✔
5966
}
10,659✔
5967

5968

5969
/*
5970
 * Create the array/function theory solver and attach it to the egraph
5971
 */
5972
static void create_fun_solver(context_t *ctx) {
4,426✔
5973
  fun_solver_t *solver;
5974

5975
  assert(ctx->egraph != NULL && ctx->fun_solver == NULL);
5976

5977
  solver = (fun_solver_t *) safe_malloc(sizeof(fun_solver_t));
4,426✔
5978
  init_fun_solver(solver, ctx->core, &ctx->gate_manager, ctx->egraph, ctx->types);
4,426✔
5979
  egraph_attach_funsolver(ctx->egraph, solver, fun_solver_ctrl_interface(solver),
4,426✔
5980
                          fun_solver_egraph_interface(solver),
5981
                          fun_solver_fun_egraph_interface(solver));
5982

5983
  ctx->fun_solver = solver;
4,426✔
5984
}
4,426✔
5985

5986

5987
/*
5988
 * Allocate and initialize solvers based on architecture and mode
5989
 * - core and gate manager must exist at this point
5990
 * - if the architecture is either AUTO_IDL or AUTO_RDL, no theory solver
5991
 *   is allocated yet, and the core is initialized for Boolean only
5992
 * - otherwise, all components are ready and initialized, including the core.
5993
 */
5994
static void init_solvers(context_t *ctx) {
22,389✔
5995
  uint8_t solvers;
5996
  smt_core_t *core;
5997
  smt_mode_t cmode;
5998
  egraph_t *egraph;
5999

6000
  solvers = arch_components[ctx->arch];
22,389✔
6001

6002
  ctx->egraph = NULL;
22,389✔
6003
  ctx->arith_solver = NULL;
22,389✔
6004
  ctx->bv_solver = NULL;
22,389✔
6005
  ctx->fun_solver = NULL;
22,389✔
6006
  ctx->quant_solver = NULL;
22,389✔
6007
  ctx->mcsat_supplement_active = false;
22,389✔
6008

6009
  // Create egraph first, then satellite solvers
6010
  if (solvers & EGRPH) {
22,389✔
6011
    create_egraph(ctx);
4,793✔
6012
  }
6013

6014
  // Create mcsat
6015
  if (solvers & MCSAT) {
22,389✔
6016
    create_mcsat(ctx);
748✔
6017
  }
6018

6019
  // Arithmetic solver
6020
  if (solvers & SPLX) {
22,389✔
6021
    create_simplex_solver(ctx, false);
14,908✔
6022
  } else if (solvers & IFW) {
7,481✔
6023
    create_idl_solver(ctx, false);
×
6024
  } else if (solvers & RFW) {
7,481✔
6025
    create_rdl_solver(ctx, false);
×
6026
  }
6027

6028
  // Bitvector solver
6029
  if (solvers & BVSLVR) {
22,389✔
6030
    create_bv_solver(ctx);
10,659✔
6031
  }
6032

6033
  // Array solver
6034
  if (solvers & FSLVR) {
22,389✔
6035
    create_fun_solver(ctx);
4,426✔
6036
  }
6037

6038
  /*
6039
   * At this point all solvers are ready and initialized, except the
6040
   * egraph and core if the egraph is present or the core if there are
6041
   * no solvers, or if arch is AUTO_IDL or AUTO_RDL.
6042
   */
6043
  cmode = core_mode[ctx->mode];   // initialization mode for the core
22,389✔
6044
  egraph = ctx->egraph;
22,389✔
6045
  core = ctx->core;
22,389✔
6046
  if (egraph != NULL) {
22,389✔
6047
    init_smt_core(core, CTX_DEFAULT_CORE_SIZE, egraph, egraph_ctrl_interface(egraph),
4,793✔
6048
                  egraph_smt_interface(egraph), cmode);
6049
    egraph_attach_core(egraph, core);
4,793✔
6050

6051
  } else if (solvers == 0) {
17,596✔
6052
    /*
6053
     * Boolean solver only. If arch if AUTO_IDL or AUTO_RDL, the
6054
     * theory solver will be changed later by create_auto_idl_solver
6055
     * or create_auto_rdl_solver.
6056
     */
6057
    assert(ctx->arith_solver == NULL && ctx->bv_solver == NULL && ctx->fun_solver == NULL);
6058
    init_smt_core(core, CTX_DEFAULT_CORE_SIZE, NULL, &null_ctrl, &null_smt, cmode);
36✔
6059
  } else if (solvers == MCSAT) {
17,560✔
6060
    /*
6061
     * MCsat solver only, we create the core, but never use it.
6062
     */
6063
    assert(ctx->egraph == NULL && ctx->arith_solver == NULL &&
6064
           ctx->bv_solver == NULL && ctx->fun_solver == NULL);
6065
    init_smt_core(core, CTX_DEFAULT_CORE_SIZE, NULL, &null_ctrl, &null_smt, cmode);
748✔
6066
  }
6067

6068
  /*
6069
   * Optimization: if the arch is NOSOLVERS or BV then we set bool_only in the core
6070
   */
6071
  if (ctx->arch == CTX_ARCH_NOSOLVERS || ctx->arch == CTX_ARCH_BV) {
22,389✔
6072
    smt_core_set_bool_only(core);
6,240✔
6073
  }
6074
}
22,389✔
6075

6076

6077

6078

6079
/*
6080
 * Delete the arithmetic solver
6081
 */
6082
static void delete_arith_solver(context_t *ctx) {
14,942✔
6083
  uint8_t solvers;
6084

6085
  assert(ctx->arith_solver != NULL);
6086

6087
  solvers = arch_components[ctx->arch];
14,942✔
6088
  if (solvers & IFW) {
14,942✔
6089
    delete_idl_solver(ctx->arith_solver);
26✔
6090
  } else if (solvers & RFW) {
14,916✔
6091
    delete_rdl_solver(ctx->arith_solver);
8✔
6092
  } else if (solvers & SPLX) {
14,908✔
6093
    delete_simplex_solver(ctx->arith_solver);
14,908✔
6094
  }
6095
  safe_free(ctx->arith_solver);
14,942✔
6096
  ctx->arith_solver = NULL;
14,942✔
6097
}
14,942✔
6098

6099

6100

6101

6102
/*****************************
6103
 *  CONTEXT INITIALIZATION   *
6104
 ****************************/
6105

6106
/*
6107
 * Check mode and architecture
6108
 */
6109
#ifndef NDEBUG
6110
static inline bool valid_mode(context_mode_t mode) {
6111
  return CTX_MODE_ONECHECK <= mode && mode <= CTX_MODE_INTERACTIVE;
6112
}
6113

6114
static inline bool valid_arch(context_arch_t arch) {
6115
  return CTX_ARCH_NOSOLVERS <= arch && arch <= CTX_ARCH_MCSAT;
6116
}
6117
#endif
6118

6119

6120
/*
6121
 * Initialize ctx for the given mode and architecture
6122
 * - terms = term table for that context
6123
 * - qflag = true means quantifiers allowed
6124
 * - qflag = false means no quantifiers
6125
 */
6126
void init_context(context_t *ctx, term_table_t *terms, smt_logic_t logic,
22,389✔
6127
                  context_mode_t mode, context_arch_t arch, bool qflag) {
6128
  assert(valid_mode(mode) && valid_arch(arch));
6129

6130
  /*
6131
   * Set architecture and options
6132
   */
6133
  ctx->mode = mode;
22,389✔
6134
  ctx->arch = arch;
22,389✔
6135
  ctx->logic = logic;
22,389✔
6136
  ctx->sat_delegate = SAT_DELEGATE_NONE;
22,389✔
6137
  ctx->sat_delegate_incremental_mode = SAT_DELEGATE_MODE_REBUILD;
22,389✔
6138
  ctx->sat_delegate_incremental_mode_set = false;
22,389✔
6139
  ctx->theories = arch2theories[arch];
22,389✔
6140
  ctx->options = mode2options[mode];
22,389✔
6141
  if (qflag) {
22,389✔
6142
    // quantifiers require egraph
6143
    assert((ctx->theories & UF_MASK) != 0);
6144
    ctx->theories |= QUANT_MASK;
×
6145
  }
6146

6147
  ctx->base_level = 0;
22,389✔
6148
  context_reset_sat_delegate_stats(ctx);
22,389✔
6149

6150
  /*
6151
   * The core is always needed: allocate it here. It's not initialized yet.
6152
   * The other solver are optionals.
6153
   *
6154
   * TODO: we could skip this when we use MCSAT (since then the core is
6155
   * not needed).
6156
   */
6157
  ctx->core = (smt_core_t *) safe_malloc(sizeof(smt_core_t));
22,389✔
6158
  ctx->egraph = NULL;
22,389✔
6159
  ctx->mcsat = NULL;
22,389✔
6160
  ctx->arith_solver = NULL;
22,389✔
6161
  ctx->bv_solver = NULL;
22,389✔
6162
  ctx->fun_solver = NULL;
22,389✔
6163
  ctx->quant_solver = NULL;
22,389✔
6164

6165
  /*
6166
   * Global tables + gate manager
6167
   */
6168
  ctx->types = terms->types;
22,389✔
6169
  ctx->terms = terms;
22,389✔
6170
  init_gate_manager(&ctx->gate_manager, ctx->core);
22,389✔
6171

6172
  /*
6173
   * Simplification/internalization support
6174
   */
6175
  init_intern_tbl(&ctx->intern, 0, terms);
22,389✔
6176
  init_ivector(&ctx->top_eqs, CTX_DEFAULT_VECTOR_SIZE);
22,389✔
6177
  init_ivector(&ctx->top_atoms, CTX_DEFAULT_VECTOR_SIZE);
22,389✔
6178
  init_ivector(&ctx->top_formulas, CTX_DEFAULT_VECTOR_SIZE);
22,389✔
6179
  init_ivector(&ctx->top_interns, CTX_DEFAULT_VECTOR_SIZE);
22,389✔
6180

6181
  /*
6182
   * Force the internalization mapping for true and false
6183
   * - true  term --> true_occ
6184
   * - false term --> false_occ
6185
   * This mapping holds even if there's no egraph.
6186
   */
6187
  intern_tbl_map_root(&ctx->intern, true_term, bool2code(true));
22,389✔
6188

6189
  /*
6190
   * Auxiliary internalization buffers
6191
   */
6192
  init_ivector(&ctx->subst_eqs, CTX_DEFAULT_VECTOR_SIZE);
22,389✔
6193
  init_ivector(&ctx->aux_eqs, CTX_DEFAULT_VECTOR_SIZE);
22,389✔
6194
  init_ivector(&ctx->aux_atoms, CTX_DEFAULT_VECTOR_SIZE);
22,389✔
6195
  init_ivector(&ctx->aux_vector, CTX_DEFAULT_VECTOR_SIZE);
22,389✔
6196
  init_int_queue(&ctx->queue, 0);
22,389✔
6197
  init_istack(&ctx->istack);
22,389✔
6198
  init_objstack(&ctx->ostack);
22,389✔
6199
  init_sharing_map(&ctx->sharing, &ctx->intern);
22,389✔
6200
  init_objstore(&ctx->cstore, sizeof(conditional_t), 32);
22,389✔
6201
  init_assumption_stack(&ctx->assumptions);
22,389✔
6202

6203
  ctx->subst = NULL;
22,389✔
6204
  ctx->marks = NULL;
22,389✔
6205
  ctx->cache = NULL;
22,389✔
6206
  ctx->small_cache = NULL;
22,389✔
6207
  ctx->edge_map = NULL;
22,389✔
6208
  ctx->eq_cache = NULL;
22,389✔
6209
  ctx->divmod_table = NULL;
22,389✔
6210
  ctx->explorer = NULL;
22,389✔
6211
  ctx->unsat_core_cache = NULL;
22,389✔
6212
  ctx->sat_delegate_state = NULL;
22,389✔
6213

6214
  ctx->dl_profile = NULL;
22,389✔
6215
  ctx->arith_buffer = NULL;
22,389✔
6216
  ctx->poly_buffer = NULL;
22,389✔
6217
  ctx->aux_poly = NULL;
22,389✔
6218
  ctx->aux_poly_size = 0;
22,389✔
6219

6220
  ctx->bvpoly_buffer = NULL;
22,389✔
6221

6222
  q_init(&ctx->aux);
22,389✔
6223
  init_bvconstant(&ctx->bv_buffer);
22,389✔
6224

6225
  ctx->trace = NULL;
22,389✔
6226

6227
  // mcsat options default
6228
  init_mcsat_options(&ctx->mcsat_options);
22,389✔
6229
  init_ivector(&ctx->mcsat_var_order, CTX_DEFAULT_VECTOR_SIZE);
22,389✔
6230
  init_ivector(&ctx->mcsat_initial_var_order, CTX_DEFAULT_VECTOR_SIZE);
22,389✔
6231
  /*
6232
   * Allocate and initialize the solvers and core
6233
   * NOTE: no theory solver yet if arch is AUTO_IDL or AUTO_RDL
6234
   */
6235
  init_solvers(ctx);
22,389✔
6236

6237
  ctx->en_quant = false;
22,389✔
6238
}
22,389✔
6239

6240

6241

6242

6243
/*
6244
 * Delete ctx
6245
 */
6246
void delete_context(context_t *ctx) {
22,388✔
6247
  context_sat_delegate_state_cleanup(ctx);
22,388✔
6248

6249
  if (ctx->core != NULL) {
22,388✔
6250
    delete_smt_core(ctx->core);
22,388✔
6251
    safe_free(ctx->core);
22,388✔
6252
    ctx->core = NULL;
22,388✔
6253
  }
6254

6255
  if (ctx->mcsat != NULL) {
22,388✔
6256
    mcsat_destruct(ctx->mcsat);
748✔
6257
    safe_free(ctx->mcsat);
748✔
6258
    ctx->mcsat = NULL;
748✔
6259
  }
6260

6261
  if (ctx->mcsat_supplement_active) {
22,388✔
6262
    context_disable_mcsat_supplement(ctx);
5✔
6263
  }
6264

6265
  if (ctx->egraph != NULL) {
22,388✔
6266
    delete_egraph(ctx->egraph);
4,792✔
6267
    safe_free(ctx->egraph);
4,792✔
6268
    ctx->egraph = NULL;
4,792✔
6269
  }
6270

6271
  if (ctx->arith_solver != NULL) {
22,388✔
6272
    delete_arith_solver(ctx);
14,942✔
6273
  }
6274

6275
  if (ctx->fun_solver != NULL) {
22,388✔
6276
    delete_fun_solver(ctx->fun_solver);
4,425✔
6277
    safe_free(ctx->fun_solver);
4,425✔
6278
    ctx->fun_solver = NULL;
4,425✔
6279
  }
6280

6281
  if (ctx->quant_solver != NULL) {
22,388✔
6282
    delete_quant_solver(ctx->quant_solver);
52✔
6283
    safe_free(ctx->quant_solver);
52✔
6284
    ctx->quant_solver = NULL;
52✔
6285
  }
6286

6287
  if (ctx->bv_solver != NULL) {
22,388✔
6288
    delete_bv_solver(ctx->bv_solver);
10,658✔
6289
    safe_free(ctx->bv_solver);
10,658✔
6290
    ctx->bv_solver = NULL;
10,658✔
6291
  }
6292

6293
  delete_gate_manager(&ctx->gate_manager);
22,388✔
6294
  /* delete_mcsat_options(&ctx->mcsat_options); // if used then the same memory is freed twice */
6295
  delete_ivector(&ctx->mcsat_var_order);
22,388✔
6296
  delete_ivector(&ctx->mcsat_initial_var_order);
22,388✔
6297

6298
  delete_intern_tbl(&ctx->intern);
22,388✔
6299
  delete_ivector(&ctx->top_eqs);
22,388✔
6300
  delete_ivector(&ctx->top_atoms);
22,388✔
6301
  delete_ivector(&ctx->top_formulas);
22,388✔
6302
  delete_ivector(&ctx->top_interns);
22,388✔
6303

6304
  delete_ivector(&ctx->subst_eqs);
22,388✔
6305
  delete_ivector(&ctx->aux_eqs);
22,388✔
6306
  delete_ivector(&ctx->aux_atoms);
22,388✔
6307
  delete_ivector(&ctx->aux_vector);
22,388✔
6308
  delete_int_queue(&ctx->queue);
22,388✔
6309
  delete_istack(&ctx->istack);
22,388✔
6310
  delete_objstack(&ctx->ostack);
22,388✔
6311
  delete_sharing_map(&ctx->sharing);
22,388✔
6312
  delete_objstore(&ctx->cstore);
22,388✔
6313
  delete_assumption_stack(&ctx->assumptions);
22,388✔
6314

6315
  context_free_subst(ctx);
22,388✔
6316
  context_free_marks(ctx);
22,388✔
6317
  context_free_cache(ctx);
22,388✔
6318
  context_free_small_cache(ctx);
22,388✔
6319
  context_free_eq_cache(ctx);
22,388✔
6320
  context_free_divmod_table(ctx);
22,388✔
6321
  context_free_explorer(ctx);
22,388✔
6322

6323
  context_free_dl_profile(ctx);
22,388✔
6324
  context_free_edge_map(ctx);
22,388✔
6325
  context_free_arith_buffer(ctx);
22,388✔
6326
  context_free_poly_buffer(ctx);
22,388✔
6327
  context_free_aux_poly(ctx);
22,388✔
6328

6329
  context_free_bvpoly_buffer(ctx);
22,388✔
6330
  context_invalidate_unsat_core_cache(ctx);
22,388✔
6331

6332
  q_clear(&ctx->aux);
22,388✔
6333
  delete_bvconstant(&ctx->bv_buffer);
22,388✔
6334
}
22,388✔
6335

6336
void context_invalidate_unsat_core_cache(context_t *ctx) {
88,180✔
6337
  if (ctx->unsat_core_cache != NULL) {
88,180✔
6338
    delete_ivector(ctx->unsat_core_cache);
2,715✔
6339
    safe_free(ctx->unsat_core_cache);
2,715✔
6340
    ctx->unsat_core_cache = NULL;
2,715✔
6341
  }
6342
}
88,180✔
6343

6344

6345

6346
/*
6347
 * Reset: remove all assertions and clear all internalization tables
6348
 */
6349
void reset_context(context_t *ctx) {
13✔
6350
  ctx->base_level = 0;
13✔
6351
  context_reset_sat_delegate_stats(ctx);
13✔
6352
  context_invalidate_unsat_core_cache(ctx);
13✔
6353
  context_sat_delegate_state_cleanup(ctx);
13✔
6354

6355
  reset_smt_core(ctx->core); // this propagates reset to all solvers
13✔
6356

6357
  if (ctx->mcsat_supplement_active) {
13✔
6358
    context_disable_mcsat_supplement(ctx);
5✔
6359
  }
6360

6361
  if (ctx->mcsat != NULL) {
13✔
6362
    mcsat_reset(ctx->mcsat);
7✔
6363
  }
6364

6365
  reset_gate_manager(&ctx->gate_manager);
13✔
6366

6367
  ivector_reset(&ctx->mcsat_var_order);
13✔
6368
  ivector_reset(&ctx->mcsat_initial_var_order);
13✔
6369

6370
  reset_intern_tbl(&ctx->intern);
13✔
6371
  ivector_reset(&ctx->top_eqs);
13✔
6372
  ivector_reset(&ctx->top_atoms);
13✔
6373
  ivector_reset(&ctx->top_formulas);
13✔
6374
  ivector_reset(&ctx->top_interns);
13✔
6375

6376
  // Force the internalization mapping for true and false
6377
  intern_tbl_map_root(&ctx->intern, true_term, bool2code(true));
13✔
6378

6379
  ivector_reset(&ctx->subst_eqs);
13✔
6380
  ivector_reset(&ctx->aux_eqs);
13✔
6381
  ivector_reset(&ctx->aux_atoms);
13✔
6382
  ivector_reset(&ctx->aux_vector);
13✔
6383
  int_queue_reset(&ctx->queue);
13✔
6384
  reset_istack(&ctx->istack);
13✔
6385
  reset_objstack(&ctx->ostack);
13✔
6386
  reset_sharing_map(&ctx->sharing);
13✔
6387
  reset_objstore(&ctx->cstore);
13✔
6388
  reset_assumption_stack(&ctx->assumptions);
13✔
6389

6390
  context_free_subst(ctx);
13✔
6391
  context_free_marks(ctx);
13✔
6392
  context_reset_small_cache(ctx);
13✔
6393
  context_reset_eq_cache(ctx);
13✔
6394
  context_reset_divmod_table(ctx);
13✔
6395
  context_reset_explorer(ctx);
13✔
6396

6397
  context_free_arith_buffer(ctx);
13✔
6398
  context_reset_poly_buffer(ctx);
13✔
6399
  context_free_aux_poly(ctx);
13✔
6400
  context_free_dl_profile(ctx);
13✔
6401

6402
  context_free_bvpoly_buffer(ctx);
13✔
6403

6404
  q_clear(&ctx->aux);
13✔
6405
}
13✔
6406

6407

6408
/*
6409
 * Add tracer to ctx and ctx->core
6410
 */
6411
void context_set_trace(context_t *ctx, tracer_t *trace) {
285✔
6412
  assert(ctx->trace == NULL);
6413
  ctx->trace = trace;
285✔
6414
  smt_core_set_trace(ctx->core, trace);
285✔
6415
  if (ctx->mcsat != NULL) {
285✔
6416
    mcsat_set_tracer(ctx->mcsat, trace);
284✔
6417
  }
6418
  if (ctx->mcsat_supplement_active) {
285✔
NEW
6419
    mcsat_satellite_t *sat = context_mcsat_satellite(ctx);
×
NEW
6420
    if (sat != NULL) {
×
NEW
6421
      mcsat_satellite_set_trace(sat, trace);
×
6422
    }
6423
  }
6424
}
285✔
6425

6426

6427
/*
6428
 * Push and pop
6429
 */
6430
void context_push(context_t *ctx) {
18,596✔
6431
  assert(context_supports_pushpop(ctx));
6432
  context_invalidate_unsat_core_cache(ctx);
18,596✔
6433
  smt_push(ctx->core);  // propagates to all solvers
18,596✔
6434
  if (ctx->mcsat != NULL) {
18,596✔
6435
    mcsat_push(ctx->mcsat);
1,346✔
6436
  }
6437
  intern_tbl_push(&ctx->intern);
18,596✔
6438
  assumption_stack_push(&ctx->assumptions);
18,596✔
6439
  context_eq_cache_push(ctx);
18,596✔
6440
  context_divmod_table_push(ctx);
18,596✔
6441

6442
  ctx->base_level ++;
18,596✔
6443
}
18,596✔
6444

6445
void context_pop(context_t *ctx) {
1,578✔
6446
  assert(context_supports_pushpop(ctx) && ctx->base_level > 0);
6447
  context_invalidate_unsat_core_cache(ctx);
1,578✔
6448
  smt_pop(ctx->core);   // propagates to all solvers
1,578✔
6449
  if (ctx->mcsat != NULL) {
1,578✔
6450
    mcsat_pop(ctx->mcsat);
1,262✔
6451
  }
6452
  intern_tbl_pop(&ctx->intern);
1,578✔
6453
  assumption_stack_pop(&ctx->assumptions);
1,578✔
6454
  context_eq_cache_pop(ctx);
1,578✔
6455
  context_divmod_table_pop(ctx);
1,578✔
6456

6457
  context_sat_delegate_state_pop(ctx, ctx->base_level);
1,578✔
6458

6459
  ctx->base_level --;
1,578✔
6460
}
1,578✔
6461

6462

6463

6464

6465

6466
/****************************
6467
 *   ASSERTIONS AND CHECK   *
6468
 ***************************/
6469

6470
/*
6471
 * Build the sharing data
6472
 * - processes all the assertions in vectors top_eqs, top_atoms, top_formulas
6473
 * - this function should be called after building the substitutions
6474
 */
6475
static void context_build_sharing_data(context_t *ctx) {
71,891✔
6476
  sharing_map_t *map;
6477

6478
  map = &ctx->sharing;
71,891✔
6479
  reset_sharing_map(map);
71,891✔
6480
  sharing_map_add_terms(map, ctx->top_eqs.data, ctx->top_eqs.size);
71,891✔
6481
  sharing_map_add_terms(map, ctx->top_atoms.data, ctx->top_atoms.size);
71,891✔
6482
  sharing_map_add_terms(map, ctx->top_formulas.data, ctx->top_formulas.size);
71,891✔
6483
}
71,891✔
6484

6485

6486
#if 0
6487
/*
6488
 * PROVISIONAL: SHOW ASSERTIONS
6489
 */
6490
static void context_show_assertions(const context_t *ctx, uint32_t n, const term_t *a) {
6491
  pp_area_t area;
6492
  yices_pp_t printer;
6493
  uint32_t i;
6494

6495
  area.width = 80;
6496
  area.height = UINT32_MAX;
6497
  area.offset = 0;
6498
  area.stretch = false;
6499
  area.truncate = false;
6500
  init_yices_pp(&printer, stdout, &area, PP_VMODE, 0);
6501

6502
  for (i=0; i<n; i++) {
6503
    pp_term_full(&printer, ctx->terms, a[i]);
6504
    flush_yices_pp(&printer);
6505
  }
6506
  delete_yices_pp(&printer, true);
6507
}
6508
#endif
6509

6510
/*
6511
 * Flatten and internalize assertions a[0 ... n-1]
6512
 * - all elements a[i] must be valid boolean term in ctx->terms
6513
 * - return code:
6514
 *   TRIVIALLY_UNSAT if there's an easy contradiction
6515
 *   CTX_NO_ERROR if the assertions were processed without error
6516
 *   a negative error code otherwise.
6517
 */
6518
static int32_t context_process_assertions(context_t *ctx, uint32_t n, const term_t *a) {
74,705✔
6519
  ivector_t *v;
6520
  uint32_t i;
6521
  int code;
6522

6523
  ivector_reset(&ctx->top_eqs);
74,705✔
6524
  ivector_reset(&ctx->top_atoms);
74,705✔
6525
  ivector_reset(&ctx->top_formulas);
74,705✔
6526
  ivector_reset(&ctx->top_interns);
74,705✔
6527
  ivector_reset(&ctx->subst_eqs);
74,705✔
6528
  ivector_reset(&ctx->aux_eqs);
74,705✔
6529
  ivector_reset(&ctx->aux_atoms);
74,705✔
6530

6531
  if (ctx->arch != CTX_ARCH_MCSAT && context_has_egraph(ctx)) {
74,705✔
6532
    if (context_assertions_need_mcsat_supplement(ctx, n, a)) {
25,669✔
6533
      code = context_enable_mcsat_supplement(ctx);
14✔
6534
      if (code < 0) {
14✔
NEW
6535
        return code;
×
6536
      }
6537
    }
6538
  }
6539

6540
  if (ctx->mcsat_supplement_active) {
74,705✔
6541
    mcsat_satellite_t *sat = context_mcsat_satellite(ctx);
18✔
6542
    if (sat != NULL) {
18✔
6543
      code = mcsat_satellite_assert_formulas(sat, n, a);
18✔
6544
      if (code < 0) {
18✔
NEW
6545
        return code;
×
6546
      }
6547
    }
6548
  }
6549

6550
  code = setjmp(ctx->env);
74,705✔
6551
  if (code == 0) {
75,103✔
6552

6553
    // If using MCSAT, just check and done
6554
    if (ctx->mcsat != NULL) {
74,705✔
6555
      // TBD: quant support
6556
      assert(!context_quant_enabled(ctx));
6557
      code = mcsat_assert_formulas(ctx->mcsat, n, a);
2,442✔
6558
      goto done;
2,431✔
6559
    }
6560

6561
#if 0
6562
    printf("\n=== Context: process assertions ===\n");
6563
    context_show_assertions(ctx, n, a);
6564
    printf("===\n\n");
6565
#endif
6566

6567
    // flatten
6568
    for (i=0; i<n; i++) {
195,604✔
6569
      flatten_assertion(ctx, a[i]);
123,712✔
6570
    }
6571

6572
    trace_printf(ctx->trace, 6, "(done flattening)\n");
71,892✔
6573

6574
    /*
6575
     * At this point, the assertions are stored into the vectors
6576
     * top_eqs, top_atoms, top_formulas, and top_interns
6577
     * - more top-level equalities may be in subst_eqs
6578
     * - ctx->intern stores the internalized terms and the variable
6579
     *   substitutions.
6580
     */
6581

6582
    switch (ctx->arch) {
71,892✔
6583
    // TBD: make sure following preprocessings work with quant enabled
6584
    case CTX_ARCH_EG:
3,329✔
6585
      /*
6586
       * UF problem: we must process subst_eqs last since the
6587
       * preprocessing may add new equalities in aux_eqs that may end
6588
       * up in subst_eqs after the call to process_aux_eqs.
6589
       */
6590
      if (context_breaksym_enabled(ctx)) {
3,329✔
6591
        break_uf_symmetries(ctx);
30✔
6592
      }
6593
      if (context_eq_abstraction_enabled(ctx)) {
3,329✔
6594
        analyze_uf(ctx);
64✔
6595
      }
6596
      if (ctx->aux_eqs.size > 0) {
3,329✔
6597
        process_aux_eqs(ctx);
6✔
6598
      }
6599
      if (ctx->subst_eqs.size > 0) {
3,328✔
6600
        context_process_candidate_subst(ctx);
10✔
6601
      }
6602
      break;
3,328✔
6603

6604
    case CTX_ARCH_AUTO_IDL:
27✔
6605
      /*
6606
       * For difference logic, we must process the subst_eqs first
6607
       * (otherwise analyze_diff_logic may give wrong results).
6608
       */
6609
      if (ctx->subst_eqs.size > 0) {
27✔
6610
        context_process_candidate_subst(ctx);
×
6611
      }
6612
      analyze_diff_logic(ctx, true);
27✔
6613
      create_auto_idl_solver(ctx);
27✔
6614
      break;
27✔
6615

6616
    case CTX_ARCH_AUTO_RDL:
8✔
6617
      /*
6618
       * Difference logic, we must process the subst_eqs first
6619
       */
6620
      trace_printf(ctx->trace, 6, "(auto-idl solver)\n");
8✔
6621
      if (ctx->subst_eqs.size > 0) {
8✔
6622
        context_process_candidate_subst(ctx);
×
6623
      }
6624
      analyze_diff_logic(ctx, false);
8✔
6625
      create_auto_rdl_solver(ctx);
8✔
6626
      break;
8✔
6627

6628
    case CTX_ARCH_SPLX:
30,674✔
6629
      /*
6630
       * Simplex, like EG, may add aux_atoms so we must process
6631
       * subst_eqs last here.
6632
       */
6633
      trace_printf(ctx->trace, 6, "(Simplex solver)\n");
30,674✔
6634
      // more optional processing
6635
      if (context_cond_def_preprocessing_enabled(ctx)) {
30,674✔
6636
        process_conditional_definitions(ctx);
52✔
6637
        if (ctx->aux_eqs.size > 0) {
52✔
6638
          process_aux_eqs(ctx);
2✔
6639
        }
6640
        if (ctx->aux_atoms.size > 0) {
52✔
6641
          process_aux_atoms(ctx);
3✔
6642
        }
6643
      }
6644
      if (ctx->subst_eqs.size > 0) {
30,674✔
6645
        context_process_candidate_subst(ctx);
16✔
6646
      }
6647
      break;
30,674✔
6648

6649
    default:
37,854✔
6650
      /*
6651
       * Process the candidate variable substitutions if any
6652
       */
6653
      if (ctx->subst_eqs.size > 0) {
37,854✔
6654
        context_process_candidate_subst(ctx);
2,749✔
6655
      }
6656
      break;
37,854✔
6657
    }
6658

6659
    /*
6660
     * Sharing
6661
     */
6662
    context_build_sharing_data(ctx);
71,891✔
6663

6664
    /*
6665
     * Notify the core + solver(s)
6666
     */
6667
    if (!context_quant_enabled(ctx)) {
71,891✔
6668
        // TBD: make sure this is correct
6669
      internalization_start(ctx->core);
69,358✔
6670
    }
6671

6672
    /*
6673
     * Assert top_eqs, top_atoms, top_formulas, top_interns
6674
     */
6675
    code = CTX_NO_ERROR;
71,891✔
6676

6677
    // first: all terms that are already internalized
6678
    v = &ctx->top_interns;
71,891✔
6679
    n = v->size;
71,891✔
6680
    if (n > 0) {
71,891✔
6681
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" existing terms)\n", n);
284✔
6682
      i = 0;
284✔
6683
      do {
6684
        assert_toplevel_intern(ctx, v->data[i]);
739✔
6685
        i ++;
739✔
6686
      } while (i < n);
739✔
6687

6688
      // one round of propagation
6689
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
284✔
6690
        code = TRIVIALLY_UNSAT;
11✔
6691
        goto done;
11✔
6692
      }
6693
    }
6694

6695
    // second: all top-level equalities
6696
    v = &ctx->top_eqs;
71,880✔
6697
    n = v->size;
71,880✔
6698
    if (n > 0) {
71,880✔
6699
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" top-level equalities)\n", n);
6,763✔
6700
      i = 0;
6,763✔
6701
      do {
6702
        assert_toplevel_formula(ctx, v->data[i]);
10,824✔
6703
        i ++;
10,820✔
6704
      } while (i < n);
10,820✔
6705

6706
      // one round of propagation
6707
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
6,759✔
6708
        code = TRIVIALLY_UNSAT;
68✔
6709
        goto done;
68✔
6710
      }
6711
    }
6712

6713
    // third: all top-level atoms (other than equalities)
6714
    v = &ctx->top_atoms;
71,808✔
6715
    n = v->size;
71,808✔
6716
    if (n > 0) {
71,808✔
6717
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" top-level atoms)\n", n);
15,514✔
6718
      i = 0;
15,514✔
6719
      do {
6720
        assert_toplevel_formula(ctx, v->data[i]);
68,802✔
6721
        i ++;
68,791✔
6722
      } while (i < n);
68,791✔
6723

6724
      // one round of propagation
6725
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
15,503✔
6726
        code = TRIVIALLY_UNSAT;
76✔
6727
        goto done;
76✔
6728
      }
6729
    }
6730

6731
    // last: all non-atomic, formulas
6732
    v =  &ctx->top_formulas;
71,721✔
6733
    n = v->size;
71,721✔
6734
    if (n > 0) {
71,721✔
6735
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" top-level formulas)\n", n);
22,021✔
6736
      i = 0;
22,021✔
6737
      do {
6738
        assert_toplevel_formula(ctx, v->data[i]);
45,747✔
6739
        i ++;
45,747✔
6740
      } while (i < n);
45,747✔
6741

6742
      // one round of propagation
6743
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
22,021✔
6744
        code = TRIVIALLY_UNSAT;
63✔
6745
        goto done;
63✔
6746
      }
6747
    }
6748

6749
  } else {
6750
    /*
6751
     * Exception: return from longjmp(ctx->env, code);
6752
     */
6753
    ivector_reset(&ctx->aux_vector);
398✔
6754
    reset_istack(&ctx->istack);
398✔
6755
    reset_objstack(&ctx->ostack);
398✔
6756
    int_queue_reset(&ctx->queue);
398✔
6757
    context_free_subst(ctx);
398✔
6758
    context_free_marks(ctx);
398✔
6759
  }
6760

6761
 done:
74,705✔
6762
  return code;
74,705✔
6763
}
6764

6765
/*
6766
 * Assert all formulas f[0] ... f[n-1]
6767
 * The context status must be IDLE.
6768
 *
6769
 * Return code:
6770
 * - TRIVIALLY_UNSAT means that an inconsistency is detected
6771
 *   (in that case the context status is set to UNSAT)
6772
 * - CTX_NO_ERROR means no internalization error and status not
6773
 *   determined
6774
 * - otherwise, the code is negative to report an error.
6775
 */
6776
int32_t _o_assert_formulas(context_t *ctx, uint32_t n, const term_t *f) {
72,171✔
6777
  int32_t code;
6778

6779
  assert(ctx->arch == CTX_ARCH_AUTO_IDL ||
6780
         ctx->arch == CTX_ARCH_AUTO_RDL ||
6781
         smt_status(ctx->core) == YICES_STATUS_IDLE);
6782
  assert(!context_quant_enabled(ctx));
6783

6784
  code = context_process_assertions(ctx, n, f);
72,171✔
6785
  if (code == TRIVIALLY_UNSAT) {
72,171✔
6786
    if (ctx->arch == CTX_ARCH_AUTO_IDL || ctx->arch == CTX_ARCH_AUTO_RDL) {
597✔
6787
      // cleanup: reset arch/config to 'no theory'
6788
      assert(ctx->arith_solver == NULL && ctx->bv_solver == NULL && ctx->fun_solver == NULL &&
6789
             ctx->mode == CTX_MODE_ONECHECK);
6790
      ctx->arch = CTX_ARCH_NOSOLVERS;
1✔
6791
      ctx->theories = 0;
1✔
6792
      ctx->options = 0;
1✔
6793
    }
6794

6795
    if( smt_status(ctx->core) != YICES_STATUS_UNSAT) {
597✔
6796
      // force UNSAT in the core
6797
      add_empty_clause(ctx->core);
379✔
6798
      ctx->core->status = YICES_STATUS_UNSAT;
379✔
6799
    }
6800
  }
6801

6802
  return code;
72,171✔
6803
}
6804

6805
/*
6806
 * Assert all formulas f[0] ... f[n-1] during quantifier instantiation
6807
 * The context status must be SEARCHING.
6808
 *
6809
 * Return code:
6810
 * - TRIVIALLY_UNSAT means that an inconsistency is detected
6811
 *   (in that case the context status is set to UNSAT)
6812
 * - CTX_NO_ERROR means no internalization error and status not
6813
 *   determined
6814
 * - otherwise, the code is negative to report an error.
6815
 */
6816
int32_t quant_assert_formulas(context_t *ctx, uint32_t n, const term_t *f) {
2,534✔
6817
  int32_t code;
6818

6819
  assert(context_quant_enabled(ctx));
6820
  assert(smt_status(ctx->core) == YICES_STATUS_SEARCHING);
6821

6822
  code = context_process_assertions(ctx, n, f);
2,534✔
6823
  if (code == TRIVIALLY_UNSAT) {
2,534✔
6824
    if (ctx->arch == CTX_ARCH_AUTO_IDL || ctx->arch == CTX_ARCH_AUTO_RDL) {
1✔
6825
      // cleanup: reset arch/config to 'no theory'
6826
      assert(ctx->arith_solver == NULL && ctx->bv_solver == NULL && ctx->fun_solver == NULL &&
6827
      ctx->mode == CTX_MODE_ONECHECK);
6828
      ctx->arch = CTX_ARCH_NOSOLVERS;
×
6829
      ctx->theories = 0;
×
6830
      ctx->options = 0;
×
6831
    }
6832

6833
    if( smt_status(ctx->core) != YICES_STATUS_UNSAT) {
1✔
6834
      // force UNSAT in the core
6835
      add_empty_clause(ctx->core);
1✔
6836
      ctx->core->status = YICES_STATUS_UNSAT;
1✔
6837
    }
6838
  }
6839

6840
  return code;
2,534✔
6841
}
6842

6843
int32_t assert_formulas(context_t *ctx, uint32_t n, const term_t *f) {
18,468✔
6844
  MT_PROTECT(int32_t, __yices_globals.lock, _o_assert_formulas(ctx, n, f));
18,468✔
6845
}
6846

6847

6848

6849

6850
/*
6851
 * Assert a boolean formula f.
6852
 *
6853
 * The context status must be IDLE.
6854
 *
6855
 * Return code:
6856
 * - TRIVIALLY_UNSAT means that an inconsistency is detected
6857
 *   (in that case the context status is set to UNSAT)
6858
 * - CTX_NO_ERROR means no internalization error and status not
6859
 *   determined
6860
 * - otherwise, the code is negative. The assertion could
6861
 *   not be processed.
6862
 */
6863
int32_t _o_assert_formula(context_t *ctx, term_t f) {
53,703✔
6864
  return _o_assert_formulas(ctx, 1, &f);
53,703✔
6865
}
6866

6867
int32_t assert_formula(context_t *ctx, term_t f) {
49,307✔
6868
  MT_PROTECT(int32_t, __yices_globals.lock, _o_assert_formula(ctx, f));
49,307✔
6869
}
6870

6871

6872
/*
6873
 * Convert boolean term t to a literal l in context ctx
6874
 * - t must be a boolean term
6875
 * - return a negative code if there's an error
6876
 * - return a literal (l >= 0) otherwise.
6877
 */
6878
int32_t context_internalize(context_t *ctx, term_t t) {
87,606✔
6879
  int code;
6880
  literal_t l;
6881

6882
  ivector_reset(&ctx->top_eqs);
87,606✔
6883
  ivector_reset(&ctx->top_atoms);
87,606✔
6884
  ivector_reset(&ctx->top_formulas);
87,606✔
6885
  ivector_reset(&ctx->top_interns);
87,606✔
6886
  ivector_reset(&ctx->subst_eqs);
87,606✔
6887
  ivector_reset(&ctx->aux_eqs);
87,606✔
6888

6889
  if (ctx->arch != CTX_ARCH_MCSAT && context_has_egraph(ctx) && !ctx->mcsat_supplement_active) {
87,606✔
6890
    if (context_assertions_need_mcsat_supplement(ctx, 1, &t)) {
108✔
NEW
6891
      code = context_enable_mcsat_supplement(ctx);
×
NEW
6892
      if (code < 0) {
×
NEW
6893
        return code;
×
6894
      }
6895
    }
6896
  }
6897

6898
  code = setjmp(ctx->env);
87,606✔
6899
  if (code == 0) {
87,606✔
6900
    // we must call internalization start first
6901
    if (!context_quant_enabled(ctx)) {
87,606✔
6902
      // TBD: make sure this is correct
6903
      internalization_start(ctx->core);
87,502✔
6904
    }
6905
    l = internalize_to_literal(ctx, t);
87,606✔
6906
  } else {
6907
    assert(code < 0);
6908
    /*
6909
     * Clean up
6910
     */
6911
    ivector_reset(&ctx->aux_vector);
×
6912
    reset_istack(&ctx->istack);
×
6913
    int_queue_reset(&ctx->queue);
×
6914
    context_free_subst(ctx);
×
6915
    context_free_marks(ctx);
×
6916
    l = code;
×
6917
  }
6918

6919
  return l;
87,606✔
6920
}
6921

6922

6923
/*
6924
 * Build an assumption for Boolean term t:
6925
 * - this converts t to a literal l in context ctx
6926
 *   then create an indicator variable x in the core
6927
 *   and add the clause (x => l) in the core.
6928
 * - return a negative code if t can't be internalized
6929
 * - return the literal x otherwise (where x>=0).
6930
 */
6931
int32_t context_add_assumption(context_t *ctx, term_t t) {
87,511✔
6932
  int32_t l, x;
6933

6934
  // check if we already have an assumption literal for t
6935
  x = assumption_literal_for_term(&ctx->assumptions, t);
87,511✔
6936
  if (x < 0) {
87,511✔
6937
    l = context_internalize(ctx, t);
87,502✔
6938
    if (l < 0) return l; // error code
87,502✔
6939

6940
    x = pos_lit(create_boolean_variable(ctx->core));
87,502✔
6941
    add_binary_clause(ctx->core, not(x), l); // clause (x implies l)
87,502✔
6942

6943
    assumption_stack_add(&ctx->assumptions, t, x);
87,502✔
6944
  }
6945

6946
  return x;
87,511✔
6947
}
6948

6949

6950

6951
/*
6952
 * PROVISIONAL: FOR TESTING/DEBUGGING
6953
 */
6954

6955
/*
6956
 * Preprocess formula f or array of formulas f[0 ... n-1]
6957
 * - this does flattening + build substitutions
6958
 * - return code: as in assert_formulas
6959
 * - the result is stored in the internal vectors
6960
 *     ctx->top_interns
6961
 *     ctx->top_eqs
6962
 *     ctx->top_atoms
6963
 *     ctx->top_formulas
6964
 *   + ctx->intern stores substitutions
6965
 */
6966
int32_t context_process_formulas(context_t *ctx, uint32_t n, term_t *f) {
×
6967
  uint32_t i;
6968
  int code;
6969

6970
  ivector_reset(&ctx->top_eqs);
×
6971
  ivector_reset(&ctx->top_atoms);
×
6972
  ivector_reset(&ctx->top_formulas);
×
6973
  ivector_reset(&ctx->top_interns);
×
6974
  ivector_reset(&ctx->subst_eqs);
×
6975
  ivector_reset(&ctx->aux_eqs);
×
6976
  ivector_reset(&ctx->aux_atoms);
×
6977

NEW
6978
  if (ctx->arch != CTX_ARCH_MCSAT && context_has_egraph(ctx)) {
×
NEW
6979
    if (context_assertions_need_mcsat_supplement(ctx, n, f)) {
×
NEW
6980
      code = context_enable_mcsat_supplement(ctx);
×
NEW
6981
      if (code < 0) {
×
NEW
6982
        return code;
×
6983
      }
6984
    }
6985
  }
6986

6987
  code = setjmp(ctx->env);
×
6988
  if (code == 0) {
×
6989
    // flatten
6990
    for (i=0; i<n; i++) {
×
6991
      flatten_assertion(ctx, f[i]);
×
6992
    }
6993

6994
    /*
6995
     * At this point, the assertions are stored into the vectors
6996
     * top_eqs, top_atoms, top_formulas, and top_interns
6997
     * - more top-level equalities may be in subst_eqs
6998
     * - ctx->intern stores the internalized terms and the variable
6999
     *   substitutions.
7000
     */
7001

7002
    switch (ctx->arch) {
×
7003
    case CTX_ARCH_EG:
×
7004
      /*
7005
       * UF problem: we must process subst_eqs last since the
7006
       * preprocessing may add new equalities in aux_eqs that may end
7007
       * up in subst_eqs after the call to process_aux_eqs.
7008
       */
7009
      if (context_breaksym_enabled(ctx)) {
×
7010
        break_uf_symmetries(ctx);
×
7011
      }
7012
      if (context_eq_abstraction_enabled(ctx)) {
×
7013
        analyze_uf(ctx);
×
7014
      }
7015
      if (ctx->aux_eqs.size > 0) {
×
7016
        process_aux_eqs(ctx);
×
7017
      }
7018
      if (ctx->subst_eqs.size > 0) {
×
7019
        context_process_candidate_subst(ctx);
×
7020
      }
7021
      break;
×
7022

7023
    case CTX_ARCH_AUTO_IDL:
×
7024
      /*
7025
       * For difference logic, we must process the subst_eqs first
7026
       * (otherwise analyze_diff_logic may give wrong results).
7027
       */
7028
      if (ctx->subst_eqs.size > 0) {
×
7029
        context_process_candidate_subst(ctx);
×
7030
      }
7031
      analyze_diff_logic(ctx, true);
×
7032
      create_auto_idl_solver(ctx);
×
7033
      break;
×
7034

7035
    case CTX_ARCH_AUTO_RDL:
×
7036
      /*
7037
       * Difference logic, we must process the subst_eqs first
7038
       */
7039
      if (ctx->subst_eqs.size > 0) {
×
7040
        context_process_candidate_subst(ctx);
×
7041
      }
7042
      analyze_diff_logic(ctx, false);
×
7043
      create_auto_rdl_solver(ctx);
×
7044
      break;
×
7045

7046
    case CTX_ARCH_SPLX:
×
7047
      /*
7048
       * Simplex, like EG, may add aux_atoms so we must process
7049
       * subst_eqs last here.
7050
       */
7051
      // more optional processing
7052
      if (context_cond_def_preprocessing_enabled(ctx)) {
×
7053
        process_conditional_definitions(ctx);
×
7054
        if (ctx->aux_eqs.size > 0) {
×
7055
          process_aux_eqs(ctx);
×
7056
        }
7057
        if (ctx->aux_atoms.size > 0) {
×
7058
          process_aux_atoms(ctx);
×
7059
        }
7060
      }
7061
      if (ctx->subst_eqs.size > 0) {
×
7062
        context_process_candidate_subst(ctx);
×
7063
      }
7064
      break;
×
7065

7066
    default:
×
7067
      /*
7068
       * Process the candidate variable substitutions if any
7069
       */
7070
      if (ctx->subst_eqs.size > 0) {
×
7071
        context_process_candidate_subst(ctx);
×
7072
      }
7073
      break;
×
7074
    }
7075

7076
    /*
7077
     * Sharing
7078
     */
7079
    context_build_sharing_data(ctx);
×
7080

7081
    code = CTX_NO_ERROR;
×
7082

7083
  } else {
7084
    /*
7085
     * Exception: return from longjmp(ctx->env, code);
7086
     */
7087
    ivector_reset(&ctx->aux_vector);
×
7088
    reset_istack(&ctx->istack);
×
7089
    int_queue_reset(&ctx->queue);
×
7090
    context_free_subst(ctx);
×
7091
    context_free_marks(ctx);
×
7092
  }
7093

7094
  return code;
×
7095
}
7096

7097
int32_t context_process_formula(context_t *ctx, term_t f) {
×
7098
  return context_process_formulas(ctx, 1, &f);
×
7099
}
7100

7101

7102

7103
/*
7104
 * The search function 'check_context' is defined in context_solver.c
7105
 */
7106

7107

7108
/*
7109
 * Interrupt the search.
7110
 */
7111
void context_stop_search(context_t *ctx) {
3✔
7112
  if (ctx->mcsat == NULL) {
3✔
7113
    stop_search(ctx->core);
3✔
7114
    if (context_has_simplex_solver(ctx)) {
3✔
7115
      simplex_stop_search(ctx->arith_solver);
3✔
7116
    }
7117
  } else {
7118
    mcsat_stop_search(ctx->mcsat);
×
7119
  }
7120
}
3✔
7121

7122

7123

7124
/*
7125
 * Cleanup: restore ctx to a good state after check_context
7126
 * is interrupted.
7127
 */
7128
void context_cleanup(context_t *ctx) {
1✔
7129
  // restore the state to IDLE, propagate to all solvers (via pop)
7130
  assert(context_supports_cleaninterrupt(ctx));
7131
  context_invalidate_unsat_core_cache(ctx);
1✔
7132
  if (ctx->mcsat == NULL) {
1✔
7133
    smt_cleanup(ctx->core);
1✔
7134
  } else {
7135
    mcsat_clear(ctx->mcsat);
×
7136
  }
7137
}
1✔
7138

7139

7140

7141
/*
7142
 * Clear: prepare for more assertions and checks
7143
 * - free the boolean assignment
7144
 * - reset the status to IDLE
7145
 */
7146
void context_clear(context_t *ctx) {
42,255✔
7147
  assert(context_supports_multichecks(ctx));
7148
  context_invalidate_unsat_core_cache(ctx);
42,255✔
7149
  if (ctx->mcsat == NULL) {
42,255✔
7150
    smt_clear(ctx->core);
41,894✔
7151
  } else {
7152
    mcsat_clear(ctx->mcsat);
361✔
7153
  }
7154
}
42,255✔
7155

7156

7157

7158
/*
7159
 * Clear_unsat: prepare for pop if the status is UNSAT
7160
 * - remove assumptions if any
7161
 *
7162
 * - if clean interrupt is enabled, then there may be a mismatch between
7163
 *   the context's base_level and the core base_level.
7164
 * - it's possible to have ctx->core.base_level = ctx->base_level + 1
7165
 * - this happens because start_search in smt_core does an internal smt_push
7166
 *   to allow the core to be restored to a clean state if search is interrupted.
7167
 * - if search is not interrupted and the search returns UNSAT, then we're
7168
 *   in a state with core base level = context base level + 1.
7169
 */
7170
void context_clear_unsat(context_t *ctx) {
655✔
7171
  context_invalidate_unsat_core_cache(ctx);
655✔
7172
  if (ctx->mcsat == NULL) {
655✔
7173
    smt_clear_unsat(ctx->core);
419✔
7174
    assert(smt_base_level(ctx->core) == ctx->base_level);
7175
  } else {
7176
    mcsat_clear(ctx->mcsat);
236✔
7177
  }
7178
}
655✔
7179

7180

7181

7182
/*
7183
 * Add the blocking clause to ctx
7184
 * - ctx->status must be either SAT or UNKNOWN
7185
 * - this collects all decision literals in the current truth assignment
7186
 *   (say l_1, ..., l_k) then clears the current assignment and adds the
7187
 *  clause ((not l_1) \/ ... \/ (not l_k)).
7188
 *
7189
 * Return code:
7190
 * - TRIVIALLY_UNSAT: means that the blocking clause is empty (i.e., k = 0)
7191
 *   (in that case, the context status is set to UNSAT)
7192
 * - CTX_NO_ERROR: means that the blocking clause is not empty (i.e., k > 0)
7193
 *   (In this case, the context status is set to IDLE)
7194
 */
7195
int32_t assert_blocking_clause(context_t *ctx) {
24,855✔
7196
  ivector_t *v;
7197
  uint32_t i, n;
7198
  int32_t code;
7199

7200
  assert(smt_status(ctx->core) == YICES_STATUS_SAT ||
7201
         smt_status(ctx->core) == YICES_STATUS_UNKNOWN);
7202

7203
  // get decision literals and build the blocking clause
7204
  v = &ctx->aux_vector;
24,855✔
7205
  assert(v->size == 0);
7206
  collect_decision_literals(ctx->core, v);
24,855✔
7207
  n = v->size;
24,855✔
7208
  for (i=0; i<n; i++) {
36,264✔
7209
    v->data[i] = not(v->data[i]);
11,409✔
7210
  }
7211

7212
  // prepare for the new assertion + notify solvers of a new assertion
7213
  context_clear(ctx);
24,855✔
7214
  internalization_start(ctx->core);
24,855✔
7215

7216
  // add the blocking clause
7217
  add_clause(ctx->core, n, v->data);
24,855✔
7218
  ivector_reset(v);
24,855✔
7219

7220
  // force UNSAT if n = 0
7221
  code = CTX_NO_ERROR;
24,855✔
7222
  if (n == 0) {
24,855✔
7223
    code = TRIVIALLY_UNSAT;
16,817✔
7224
    ctx->core->status = YICES_STATUS_UNSAT;
16,817✔
7225
  }
7226

7227
  assert(n == 0 || smt_status(ctx->core) == YICES_STATUS_IDLE);
7228

7229
  return code;
24,855✔
7230
}
7231

7232

7233

7234

7235
/********************************
7236
 *  GARBAGE COLLECTION SUPPORT  *
7237
 *******************************/
7238

7239
/*
7240
 * Marker for all terms present in the eq_map
7241
 * - aux = the relevant term table.
7242
 * - each record p stores <k0, k1, val> where k0 and k1 are both
7243
 *   terms in aux and val is a literal in the core
7244
 */
7245
static void ctx_mark_eq(void *aux, const pmap2_rec_t *p) {
×
7246
  term_table_set_gc_mark(aux, index_of(p->k0));
×
7247
  term_table_set_gc_mark(aux, index_of(p->k1));
×
7248
}
×
7249

7250

7251
/*
7252
 * Go through all data structures in ctx and mark all terms and types
7253
 * that they use.
7254
 */
7255
void context_gc_mark(context_t *ctx) {
12✔
7256
  if (ctx->egraph != NULL) {
12✔
7257
    egraph_gc_mark(ctx->egraph);
1✔
7258
  }
7259
  if (ctx->fun_solver != NULL) {
12✔
7260
    fun_solver_gc_mark(ctx->fun_solver);
1✔
7261
  }
7262

7263
  intern_tbl_gc_mark(&ctx->intern);
12✔
7264

7265
  // empty all the term vectors to be safe
7266
  ivector_reset(&ctx->top_eqs);
12✔
7267
  ivector_reset(&ctx->top_atoms);
12✔
7268
  ivector_reset(&ctx->top_formulas);
12✔
7269
  ivector_reset(&ctx->top_interns);
12✔
7270
  ivector_reset(&ctx->subst_eqs);
12✔
7271
  ivector_reset(&ctx->aux_eqs);
12✔
7272

7273
  if (ctx->eq_cache != NULL) {
12✔
7274
    pmap2_iterate(ctx->eq_cache, ctx->terms, ctx_mark_eq);
×
7275
  }
7276

7277
  if (ctx->unsat_core_cache != NULL) {
12✔
7278
    uint32_t i, n;
7279
    n = ctx->unsat_core_cache->size;
×
7280
    for (i=0; i<n; i++) {
×
7281
      term_table_set_gc_mark(ctx->terms, index_of(ctx->unsat_core_cache->data[i]));
×
7282
    }
7283
  }
7284

7285
  if (ctx->mcsat != NULL) {
12✔
7286
    mcsat_gc_mark(ctx->mcsat);
11✔
7287
  }
7288
  if (ctx->mcsat_supplement_active) {
12✔
NEW
7289
    mcsat_satellite_t *sat = context_mcsat_satellite(ctx);
×
NEW
7290
    if (sat != NULL) {
×
NEW
7291
      mcsat_satellite_gc_mark(sat);
×
7292
    }
7293
  }
7294
}
12✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc