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

SRI-CSL / yices2 / 25368527405

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

Pull #611

github

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

Conflicts resolved with a hybrid of both sides:

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

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

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

2 existing lines in 2 files now uncovered.

84342 of 126128 relevant lines covered (66.87%)

1634859.8 hits per line

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

80.52
/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/simplex/simplex.h"
38
#include "terms/poly_buffer_terms.h"
39
#include "terms/term_explorer.h"
40
#include "terms/term_utils.h"
41
#include "utils/int_hash_map.h"
42
#include "utils/memalloc.h"
43

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

47
#include "api/yices_globals.h"
48

49
#define TRACE 0
50

51
#if TRACE
52

53
#include <stdio.h>
54

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

58
#endif
59

60

61

62

63

64
/**********************
65
 *  INTERNALIZATION   *
66
 *********************/
67

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

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

88

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

205
  terms = ctx->terms;
826,074✔
206
  trigger = false;
826,074✔
207

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

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

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

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

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

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

239
    default:
826,060✔
240
      break;
826,060✔
241
    }
242
  }
243

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

249
  if (!trigger) {
826,074✔
250
    if (term_is_projection(terms, t)) {
826,060✔
251
      trigger = term_requires_mcsat_supplement(ctx, proj_term_arg(terms, t), cache);
352,607✔
252

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

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

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

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

287
    } else if (term_is_composite(terms, t)) {
462,964✔
288
      nchildren = term_num_children(terms, t);
293,775✔
289
      for (i=0; i<nchildren && !trigger; i++) {
1,577,137✔
290
        trigger = term_requires_mcsat_supplement(ctx, term_child(terms, t, i), cache);
1,283,362✔
291
      }
292
    }
293
  }
294

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

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

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

312
  return trigger;
25,776✔
313
}
314

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

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

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

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

339
  return CTX_NO_ERROR;
10✔
340
}
341

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

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

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

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

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

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

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

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

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

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

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

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

425
  return CTX_NO_ERROR;
10✔
426
}
427

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

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

447
static bool context_atom_requires_mcsat(context_t *ctx, term_t atom) {
552,679✔
448
  int_hmap_t cache;
449
  bool trigger, all_arith_mode;
450

451
  atom = unsigned_term(atom);
552,679✔
452
  if (!ctx->mcsat_supplement_active || !is_boolean_term(ctx->terms, atom)) {
552,679✔
453
    return false;
552,641✔
454
  }
455
  if (!mcsat_satellite_candidate_atom(ctx->terms, atom)) {
38✔
456
    return false;
18✔
457
  }
458

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

472
  return trigger;
20✔
473
}
474

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

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

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

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

495

496

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

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

510

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

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

530

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

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

542
  return tau;
1,562✔
543
}
544

545

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

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

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

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

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

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

577

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

596

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

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

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

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

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

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

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

638
  return u;
64,982✔
639
}
640

641

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

650
  assert(! context_has_egraph(ctx));
651

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

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

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

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

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

675
  return code;
×
676
}
677

678

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

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

697

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

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

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

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

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

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

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

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

731

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

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

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

751
  return u;
×
752
}
753

754

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

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

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

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

777

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

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

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

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

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

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

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

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

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

855
  return u;
8✔
856
}
857

858

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

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

875

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

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

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

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

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

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

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

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

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

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

950
  return u;
1,168✔
951
}
952

953

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

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

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

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

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

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

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

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

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

1006

1007

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

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

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

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

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

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

1035

1036

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

1046
  n = tuple->arity;
190✔
1047

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

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

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

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

1061

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

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

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

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

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

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

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

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

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

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

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

1107

1108

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

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

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

1131

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

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

1150

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

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

1166

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

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

1183

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

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

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

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

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

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

1248

1249
/*
1250
 * Polynomial x - y + k d (for asserting y = k * (div y k) + (mod y k)
1251
 * - d is assumed to be (div y k)
1252
 * - x is assumed to be (mod y k)
1253
 */
1254
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✔
1255
  p->nterms = 3;
11✔
1256
  p->mono[0].var = 1;
11✔
1257
  q_set_one(&p->mono[0].coeff);       // coefficient of x = 1
11✔
1258
  p->mono[1].var = 2;
11✔
1259
  q_set_minus_one(&p->mono[1].coeff); // coefficient of y = -1
11✔
1260
  p->mono[2].var = 3;
11✔
1261
  q_set(&p->mono[2].coeff, k);        // coefficient of d = k
11✔
1262
  p->mono[3].var = max_idx;
11✔
1263

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

1269

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

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

1288

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

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

1307

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

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

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

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

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

1332

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

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

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

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

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

1357

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

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

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

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

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

1384

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

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

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

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

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

1420

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

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

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

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

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

1459

1460

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

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

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

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

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

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

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

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

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

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

1541

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

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

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

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

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

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

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

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

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

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

1608
  return u;
2,521✔
1609
}
1610

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

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

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

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

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

1642

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

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

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

1655
  return v;
71✔
1656
}
1657

1658

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

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

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

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

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

1701

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

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

1713

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

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

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

1731
  return x;
×
1732
}
1733

1734

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

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

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

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

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

1763
  return x;
1,762✔
1764
}
1765

1766

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

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

1785
  return y;
×
1786
}
1787

1788

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

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

1807
  return y;
25✔
1808
}
1809

1810

1811

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

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

1826
  return y;
×
1827
}
1828

1829

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

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

1849
  return y;
×
1850
}
1851

1852

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

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

1865
  return y;
4✔
1866
}
1867

1868

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

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

1883

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

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

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

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

1911

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

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

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

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

1936
  return y;
6✔
1937
}
1938

1939

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

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

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

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

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

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

1974
  q_clear(&k);
11✔
1975

1976
  return r;
11✔
1977
}
1978

1979

1980

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

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

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

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

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

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

2009

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

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

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

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

2032
  free_istack_array(&ctx->istack, a);
16,992✔
2033

2034
  return x;
16,992✔
2035
}
2036

2037

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

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

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

2051

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

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

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

2065

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

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

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

2079

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

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

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

2093

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

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

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

2107

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

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

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

2121

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

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

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

2135

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

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

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

2149

2150

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

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

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

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

2175
  return x;
585✔
2176
}
2177

2178

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

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

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

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

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

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

2208
  return x;
12,151✔
2209
}
2210

2211

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

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

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

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

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

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

2241
  return x;
607✔
2242
}
2243

2244

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

2256
  n = bvpoly_buffer_bitsize(b);
2257

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

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

2277
  return x;
2278
}
2279

2280
#endif
2281

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

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

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

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

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

2307

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

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

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

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

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

2333
  return l;
14,519✔
2334
}
2335

2336

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

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

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

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

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

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

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

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

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

2393
  return l;
80,761✔
2394
}
2395

2396

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

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

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

2414
  return l;
1✔
2415
}
2416

2417

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

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

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

2439
  return l;
4,368✔
2440
}
2441

2442

2443

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

2455
  assert(n >= 2);
2456

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

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

2471

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

2483
  assert(n >= 2);
2484

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

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

2499

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

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

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

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

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

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

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

2541
  return l;
9✔
2542
}
2543

2544

2545

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

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

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

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

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

2574
  return l;
1,192✔
2575
}
2576

2577

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

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

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

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

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

2606
  return l;
33,493✔
2607
}
2608

2609

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

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

2626
  return l;
33,841✔
2627
}
2628

2629

2630

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

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

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

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

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

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

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

2690
  return l;
53,504✔
2691
}
2692

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

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

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

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

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

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

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

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

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

2757
  return l;
92,139✔
2758
}
2759

2760

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

2766

2767

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

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

2788

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

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

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

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

2818
  return l;
×
2819
}
2820

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

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

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

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

2846
    q_clear(&k);
8✔
2847

2848
    return l;
8✔
2849

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

2856

2857
/*
2858
 * BITVECTOR ATOMS
2859
 */
2860

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

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

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

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

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

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

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

2902
  case BVEQ_CODE_FALSE:
×
2903
    return false_literal;
×
2904

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

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

2915
  default:
4,765✔
2916
    break;
4,765✔
2917
  }
2918

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

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

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

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

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

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

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

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

2951

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

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

2972

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3231
  // fix the polarity
3232
  return u ^ polarity;
103,351✔
3233

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

3238

3239

3240

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

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

3256
  assert(code_is_valid(x));
3257

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

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

3270

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3394
  }
3395

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

3404
  return x;
120,783✔
3405

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

3410

3411

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

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

3426
  assert(code_is_valid(x));
3427

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

3436
  assert(v != null_thvar);
3437

3438
  return v;
298,431✔
3439
}
3440

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3579
  return x;
375,187✔
3580

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

3585

3586

3587

3588

3589

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

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

3604
  assert(code_is_valid(x));
3605
  if (code_is_eterm(x)) {
1,396,807✔
3606
    u = code2occ(x);
129,807✔
3607
    if (term_of_occ(u) == true_eterm) {
129,807✔
3608
      l = mk_lit(const_bvar, polarity_of(u));
129,807✔
3609

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

3620
  return l;
1,396,807✔
3621
}
3622

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

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

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

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

3648
  if (intern_tbl_root_is_mapped(&ctx->intern, r)) {
1,824,143✔
3649
    /*
3650
     * r already internalized
3651
     */
3652
    code = intern_tbl_map_of_root(&ctx->intern, r);
1,396,807✔
3653
    l = translate_code_to_literal(ctx, code);
1,396,807✔
3654

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3750
    case BIT_TERM:
263,776✔
3751
      l = map_bit_select_to_literal(ctx, bit_term_desc(terms, r));
263,776✔
3752
      break;
263,776✔
3753

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

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

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

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

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

3775
 done:
1,824,143✔
3776
  return l ^ polarity;
1,824,143✔
3777
}
3778

3779

3780

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

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

3792
  assert(code_is_valid(x));
3793

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

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

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

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

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

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

3839

3840

3841

3842

3843

3844

3845
/********************************
3846
 *   ARITHMETIC SUBSTITUTIONS   *
3847
 *******************************/
3848

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

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

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

3869

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

3878
  reset_poly_buffer(buffer);
544✔
3879

3880
  assert(poly_buffer_is_zero(buffer));
3881

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

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

3897

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

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

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

3918

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

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

3944
  return NULL_TERM;
79✔
3945
}
3946

3947

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

3960
  n = buffer->nterms;
465✔
3961

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

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

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

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

3990
  return q;
465✔
3991
}
3992

3993

3994

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

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

4024

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

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

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

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

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

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

4067
  return true;
465✔
4068
}
4069

4070

4071

4072

4073

4074

4075

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

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

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

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

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

4106

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

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

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

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

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

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

4153

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

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

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

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

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

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

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

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

4206
  }
4207

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

4236

4237

4238

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

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

4251

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

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

4263
  n = app->arity;
252✔
4264

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

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

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

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

4290

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

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

4311

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

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

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

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

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

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

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

4397

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

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

4412

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

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

4427

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

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

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

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

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

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

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

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

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

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

4488

4489

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

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

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

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

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

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

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

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

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

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

4563

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

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

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

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

4593

4594

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

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

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

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

4633

4634

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

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

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

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

4664

4665

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

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

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

4687

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

4699

4700

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

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

4731

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

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

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

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

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

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

4775

4776

4777

4778

4779

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

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

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

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

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

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

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

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

4841

4842

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

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

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

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

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

4875

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

4886
  if (tt) {
42,467✔
4887
    if (context_flatten_or_enabled(ctx)) {
42,451✔
4888
      // Flatten into vector v
4889
      v = &ctx->aux_vector;
14,515✔
4890
      assert(v->size == 0);
4891
      flatten_or_term(ctx, v, or);
14,515✔
4892

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

4900
      // make a copy of v
4901
      a = alloc_istack_array(&ctx->istack, n);
13,712✔
4902
      for (i=0; i<n; i++) {
57,751✔
4903
        a[i] = v->data[i];
44,039✔
4904
      }
4905
      ivector_reset(v);
13,712✔
4906

4907
      for (i=0; i<n; i++) {
57,428✔
4908
        a[i] = internalize_to_literal(ctx, a[i]);
43,869✔
4909
        if (a[i] == true_literal) goto done;
43,869✔
4910
      }
4911

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

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

4928
    // assert (or a[0] ... a[n-1])
4929
    add_clause(ctx->core, n, a);
38,892✔
4930

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

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

4946
}
4947

4948

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

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

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

4966

4967

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

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

4990

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

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

5006

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

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

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

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

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

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

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

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

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

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

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

5077
    // flattening failed
5078
    ivector_reset(v);
7,492✔
5079
  }
5080

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

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

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

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

5104
  default:
9,202✔
5105
    break;
9,202✔
5106
  }
5107

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

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

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

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

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

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

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

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

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

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

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

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

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

5167

5168

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

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

5184
  tt = is_pos_term(t);
124,502✔
5185
  t = unsigned_term(t);
124,502✔
5186

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

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

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

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

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

5222
  case EQ_TERM:
5,144✔
5223
    assert_toplevel_eq(ctx, eq_term_desc(terms, t), tt);
5,144✔
5224
    break;
5,142✔
5225

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

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

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

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

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

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

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

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

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

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

5269
  case BIT_TERM:
31,924✔
5270
    assert_toplevel_bit_select(ctx, bit_term_desc(terms, t), tt);
31,924✔
5271
    break;
31,924✔
5272

5273
  case BV_EQ_ATOM:
9,264✔
5274
    assert_toplevel_bveq(ctx, bveq_atom_desc(terms, t), tt);
9,264✔
5275
    break;
9,256✔
5276

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

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

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

5290
  return;
124,474✔
5291

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

5296

5297

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

5433
  return;
993✔
5434

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

5439

5440

5441

5442
/************************
5443
 *  PARAMETERS/OPTIONS  *
5444
 ***********************/
5445

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

5452
  UF_MASK,                     //  CTX_ARCH_EG
5453
  ARITH_MASK,                  //  CTX_ARCH_SPLX
5454
  IDL_MASK,                    //  CTX_ARCH_IFW
5455
  RDL_MASK,                    //  CTX_ARCH_RFW
5456
  BV_MASK,                     //  CTX_ARCH_BV
5457
  UF_MASK|FUN_MASK,            //  CTX_ARCH_EGFUN
5458
  UF_MASK|ARITH_MASK,          //  CTX_ARCH_EGSPLX
5459
  UF_MASK|BV_MASK,             //  CTX_ARCH_EGBV
5460
  UF_MASK|ARITH_MASK|FUN_MASK, //  CTX_ARCH_EGFUNSPLX
5461
  UF_MASK|BV_MASK|FUN_MASK,    //  CTX_ARCH_EGFUNBV
5462
  UF_MASK|BV_MASK|ARITH_MASK,  //  CTX_ARCH_EGSPLXBV
5463
  ALLTH_MASK,                  //  CTX_ARCH_EGFUNSPLXBV
5464

5465
  IDL_MASK,                    //  CTX_ARCH_AUTO_IDL
5466
  RDL_MASK,                    //  CTX_ARCH_AUTO_RDL
5467

5468
  UF_MASK|ARITH_MASK|FUN_MASK  //  CTX_ARCH_MCSAT
5469
};
5470

5471

5472
/*
5473
 * Each architecture has a fixed set of solver components:
5474
 * - the set of components is stored as a bit vector (on 8bits)
5475
 * - this uses the following bit-masks
5476
 * For the AUTO_xxx architecture, nothing is required initially,
5477
 * so the bitmask is 0.
5478
 */
5479
#define EGRPH  0x1
5480
#define SPLX   0x2
5481
#define IFW    0x4
5482
#define RFW    0x8
5483
#define BVSLVR 0x10
5484
#define FSLVR  0x20
5485
#define MCSAT  0x40
5486

5487
static const uint8_t arch_components[NUM_ARCH] = {
5488
  0,                        //  CTX_ARCH_NOSOLVERS
5489

5490
  EGRPH,                    //  CTX_ARCH_EG
5491
  SPLX,                     //  CTX_ARCH_SPLX
5492
  IFW,                      //  CTX_ARCH_IFW
5493
  RFW,                      //  CTX_ARCH_RFW
5494
  BVSLVR,                   //  CTX_ARCH_BV
5495
  EGRPH|FSLVR,              //  CTX_ARCH_EGFUN
5496
  EGRPH|SPLX,               //  CTX_ARCH_EGSPLX
5497
  EGRPH|BVSLVR,             //  CTX_ARCH_EGBV
5498
  EGRPH|SPLX|FSLVR,         //  CTX_ARCH_EGFUNSPLX
5499
  EGRPH|BVSLVR|FSLVR,       //  CTX_ARCH_EGFUNBV
5500
  EGRPH|SPLX|BVSLVR,        //  CTX_ARCH_EGSPLXBV
5501
  EGRPH|SPLX|BVSLVR|FSLVR,  //  CTX_ARCH_EGFUNSPLXBV
5502

5503
  0,                        //  CTX_ARCH_AUTO_IDL
5504
  0,                        //  CTX_ARCH_AUTO_RDL
5505

5506
  MCSAT                     //  CTX_ARCH_MCSAT
5507
};
5508

5509

5510
/*
5511
 * Smt mode for a context mode
5512
 */
5513
static const smt_mode_t core_mode[NUM_MODES] = {
5514
  SMT_MODE_BASIC,       // one check
5515
  SMT_MODE_BASIC,       // multichecks
5516
  SMT_MODE_PUSHPOP,     // push/pop
5517
  SMT_MODE_INTERACTIVE, // interactive
5518
};
5519

5520

5521
/*
5522
 * Flags for a context mode
5523
 */
5524
static const uint32_t mode2options[NUM_MODES] = {
5525
  0,
5526
  MULTICHECKS_OPTION_MASK,
5527
  MULTICHECKS_OPTION_MASK|PUSHPOP_OPTION_MASK,
5528
  MULTICHECKS_OPTION_MASK|PUSHPOP_OPTION_MASK|CLEANINT_OPTION_MASK,
5529
};
5530

5531

5532

5533

5534

5535

5536
/*
5537
 * SIMPLEX OPTIONS
5538
 */
5539

5540
/*
5541
 * Which version of the arithmetic solver is present
5542
 */
5543
bool context_has_idl_solver(context_t *ctx) {
8✔
5544
  uint8_t solvers;
5545
  solvers = arch_components[ctx->arch];
8✔
5546
  return ctx->arith_solver != NULL && (solvers & IFW);
8✔
5547
}
5548

5549
bool context_has_rdl_solver(context_t *ctx) {
×
5550
  uint8_t solvers;
5551
  solvers = arch_components[ctx->arch];
×
5552
  return ctx->arith_solver != NULL && (solvers & RFW);
×
5553
}
5554

5555
bool context_has_simplex_solver(context_t *ctx) {
45,814✔
5556
  uint8_t solvers;
5557
  solvers = arch_components[ctx->arch];
45,814✔
5558
  return ctx->arith_solver != NULL && (solvers & SPLX);
45,814✔
5559
}
5560

5561

5562
/*
5563
 * If the simplex solver already exists, the options are propagated.
5564
 * Otherwise, they are recorded into the option flags. They will
5565
 * be set up when the simplex solver is created.
5566
 */
5567
void enable_splx_eager_lemmas(context_t *ctx) {
177✔
5568
  ctx->options |= SPLX_EGRLMAS_OPTION_MASK;
177✔
5569
  if (context_has_simplex_solver(ctx)) {
177✔
5570
    simplex_enable_eager_lemmas(ctx->arith_solver);
177✔
5571
  }
5572
}
177✔
5573

5574
void disable_splx_eager_lemmas(context_t *ctx) {
×
5575
  ctx->options &= ~SPLX_EGRLMAS_OPTION_MASK;
×
5576
  if (context_has_simplex_solver(ctx)) {
×
5577
    simplex_disable_eager_lemmas(ctx->arith_solver);
×
5578
  }
5579
}
×
5580

5581

5582
void enable_splx_periodic_icheck(context_t *ctx) {
149✔
5583
  ctx->options |= SPLX_ICHECK_OPTION_MASK;
149✔
5584
  if (context_has_simplex_solver(ctx)) {
149✔
5585
    simplex_enable_periodic_icheck(ctx->arith_solver);
138✔
5586
  }
5587
}
149✔
5588

5589
void disable_splx_periodic_icheck(context_t *ctx) {
×
5590
  ctx->options &= ~SPLX_ICHECK_OPTION_MASK;
×
5591
  if (context_has_simplex_solver(ctx)) {
×
5592
    simplex_disable_periodic_icheck(ctx->arith_solver);
×
5593
  }
5594
}
×
5595

5596
void enable_splx_eqprop(context_t *ctx) {
77✔
5597
  ctx->options |= SPLX_EQPROP_OPTION_MASK;
77✔
5598
  if (context_has_simplex_solver(ctx)) {
77✔
5599
    simplex_enable_eqprop(ctx->arith_solver);
77✔
5600
  }
5601
}
77✔
5602

5603
void disable_splx_eqprop(context_t *ctx) {
×
5604
  ctx->options &= ~SPLX_EQPROP_OPTION_MASK;
×
5605
  if (context_has_simplex_solver(ctx)) {
×
5606
    simplex_disable_eqprop(ctx->arith_solver);
×
5607
  }
5608
}
×
5609

5610

5611

5612

5613
/******************
5614
 *  EMPTY SOLVER  *
5615
 *****************/
5616

5617
/*
5618
 * We need an empty theory solver for initializing
5619
 * the core if the architecture is NOSOLVERS.
5620
 */
5621
static void donothing(void *solver) {
2,573✔
5622
}
2,573✔
5623

5624
static void null_backtrack(void *solver, uint32_t backlevel) {
×
5625
}
×
5626

5627
static bool null_propagate(void *solver) {
×
5628
  return true;
×
5629
}
5630

5631
static fcheck_code_t null_final_check(void *solver) {
×
5632
  return FCHECK_SAT;
×
5633
}
5634

5635
static th_ctrl_interface_t null_ctrl = {
5636
  donothing,        // start_internalization
5637
  donothing,        // start_search
5638
  null_propagate,   // propagate
5639
  null_final_check, // final check
5640
  donothing,        // increase_decision_level
5641
  null_backtrack,   // backtrack
5642
  donothing,        // push
5643
  donothing,        // pop
5644
  donothing,        // reset
5645
  donothing,        // clear
5646
};
5647

5648

5649
// for the smt interface, nothing should be called since there are no atoms
5650
static th_smt_interface_t null_smt = {
5651
  NULL, NULL, NULL, NULL, NULL,
5652
};
5653

5654

5655

5656

5657
/****************************
5658
 *  ARCHITECTURE & SOLVERS  *
5659
 ***************************/
5660

5661
/*
5662
 * Check whether a given architecture includes a specific solver
5663
 */
5664
bool context_arch_has_egraph(context_arch_t arch) {
417✔
5665
  return arch_components[arch] & EGRPH;
417✔
5666
}
5667

5668
bool context_arch_has_bv(context_arch_t arch) {
×
5669
  return arch_components[arch] & BVSLVR;
×
5670
}
5671

5672
bool context_arch_has_fun(context_arch_t arch) {
×
5673
  return arch_components[arch] & FSLVR;
×
5674
}
5675

5676
bool context_arch_has_arith(context_arch_t arch) {
×
5677
  return arch_components[arch] & (SPLX|IFW|RFW);
×
5678
}
5679

5680
bool context_arch_has_mcsat(context_arch_t arch) {
×
5681
  return arch_components[arch] & MCSAT;
×
5682
}
5683

5684
bool context_arch_has_simplex(context_arch_t arch) {
×
5685
  return arch_components[arch] & SPLX;
×
5686
}
5687

5688
bool context_arch_has_ifw(context_arch_t arch) {
×
5689
  return arch_components[arch] & IFW;
×
5690
}
5691

5692
bool context_arch_has_rfw(context_arch_t arch) {
×
5693
  return arch_components[arch] & RFW;
×
5694
}
5695

5696

5697
/****************************
5698
 *  SOLVER INITIALIZATION   *
5699
 ***************************/
5700

5701
/*
5702
 * Create and initialize the egraph
5703
 * - the core must be created first
5704
 */
5705
static void create_egraph(context_t *ctx) {
4,792✔
5706
  egraph_t *egraph;
5707

5708
  assert(ctx->egraph == NULL);
5709

5710
  egraph = (egraph_t *) safe_malloc(sizeof(egraph_t));
4,792✔
5711
  init_egraph(egraph, ctx->types);
4,792✔
5712
  ctx->egraph = egraph;
4,792✔
5713
}
4,792✔
5714

5715

5716
/*
5717
 * Create and initialize the mcsat solver
5718
 */
5719
static void create_mcsat(context_t *ctx) {
695✔
5720
  assert(ctx->mcsat == NULL);
5721
  ctx->mcsat = mcsat_new(ctx);
695✔
5722
}
695✔
5723

5724

5725

5726
/*
5727
 * Create and initialize the idl solver and attach it to the core
5728
 * - there must be no other solvers and no egraph
5729
 * - if automatic is true, attach the solver to the core, otherwise
5730
 *   initialize the core
5731
 * - copy the solver's internalization interface into arith
5732
 */
5733
static void create_idl_solver(context_t *ctx, bool automatic) {
26✔
5734
  idl_solver_t *solver;
5735
  smt_mode_t cmode;
5736

5737
  assert(ctx->egraph == NULL && ctx->arith_solver == NULL && ctx->bv_solver == NULL &&
5738
         ctx->fun_solver == NULL && ctx->core != NULL);
5739

5740
  cmode = core_mode[ctx->mode];
26✔
5741
  solver = (idl_solver_t *) safe_malloc(sizeof(idl_solver_t));
26✔
5742
  init_idl_solver(solver, ctx->core, &ctx->gate_manager);
26✔
5743
  if (automatic) {
26✔
5744
    smt_core_reset_thsolver(ctx->core, solver, idl_ctrl_interface(solver),
26✔
5745
                            idl_smt_interface(solver));
5746
  } else {
5747
    init_smt_core(ctx->core, CTX_DEFAULT_CORE_SIZE, solver, idl_ctrl_interface(solver),
×
5748
                  idl_smt_interface(solver), cmode);
5749
  }
5750
  idl_solver_init_jmpbuf(solver, &ctx->env);
26✔
5751
  ctx->arith_solver = solver;
26✔
5752
  ctx->arith = *idl_arith_interface(solver);
26✔
5753
}
26✔
5754

5755

5756
/*
5757
 * Create and initialize the rdl solver and attach it to the core.
5758
 * - there must be no other solvers and no egraph
5759
 * - if automatic is true, attach rdl to the core, otherwise
5760
 *   initialize the core
5761
 * - copy the solver's internalization interface in ctx->arith
5762
 */
5763
static void create_rdl_solver(context_t *ctx, bool automatic) {
8✔
5764
  rdl_solver_t *solver;
5765
  smt_mode_t cmode;
5766

5767
  assert(ctx->egraph == NULL && ctx->arith_solver == NULL && ctx->bv_solver == NULL &&
5768
         ctx->fun_solver == NULL && ctx->core != NULL);
5769

5770
  cmode = core_mode[ctx->mode];
8✔
5771
  solver = (rdl_solver_t *) safe_malloc(sizeof(rdl_solver_t));
8✔
5772
  init_rdl_solver(solver, ctx->core, &ctx->gate_manager);
8✔
5773
  if (automatic) {
8✔
5774
    smt_core_reset_thsolver(ctx->core, solver, rdl_ctrl_interface(solver),
8✔
5775
                            rdl_smt_interface(solver));
5776
  } else {
5777
    init_smt_core(ctx->core, CTX_DEFAULT_CORE_SIZE, solver, rdl_ctrl_interface(solver),
×
5778
                  rdl_smt_interface(solver), cmode);
5779
  }
5780
  rdl_solver_init_jmpbuf(solver, &ctx->env);
8✔
5781
  ctx->arith_solver = solver;
8✔
5782
  ctx->arith = *rdl_arith_interface(solver);
8✔
5783
}
8✔
5784

5785

5786
/*
5787
 * Create an initialize the simplex solver and attach it to the core
5788
 * or to the egraph if the egraph exists.
5789
 * - if automatic is true, this is part of auto_idl or auto_rdl. So the
5790
 *   core is already initialized.
5791
 */
5792
static void create_simplex_solver(context_t *ctx, bool automatic) {
14,907✔
5793
  simplex_solver_t *solver;
5794
  smt_mode_t cmode;
5795

5796
  assert(ctx->arith_solver == NULL && ctx->core != NULL);
5797

5798
  cmode = core_mode[ctx->mode];
14,907✔
5799
  solver = (simplex_solver_t *) safe_malloc(sizeof(simplex_solver_t));
14,907✔
5800
  init_simplex_solver(solver, ctx->core, &ctx->gate_manager, ctx->egraph);
14,907✔
5801

5802
  // set simplex options
5803
  if (splx_eager_lemmas_enabled(ctx)) {
14,907✔
5804
    simplex_enable_eager_lemmas(solver);
×
5805
  }
5806
  if (splx_periodic_icheck_enabled(ctx)) {
14,907✔
5807
    simplex_enable_periodic_icheck(solver);
×
5808
  }
5809
  if (splx_eqprop_enabled(ctx)) {
14,907✔
5810
    simplex_enable_eqprop(solver);
×
5811
  }
5812

5813
  // row saving must be enabled unless we're in ONECHECK mode
5814
  if (ctx->mode != CTX_MODE_ONECHECK) {
14,907✔
5815
    simplex_enable_row_saving(solver);
14,756✔
5816
  }
5817

5818
  if (ctx->egraph != NULL) {
14,907✔
5819
    // attach the simplex solver as a satellite solver to the egraph
5820
    egraph_attach_arithsolver(ctx->egraph, solver, simplex_ctrl_interface(solver),
4,335✔
5821
                              simplex_smt_interface(solver), simplex_egraph_interface(solver),
5822
                              simplex_arith_egraph_interface(solver));
5823
  } else if (!automatic) {
10,572✔
5824
    // attach simplex to the core and initialize the core
5825
    init_smt_core(ctx->core, CTX_DEFAULT_CORE_SIZE, solver, simplex_ctrl_interface(solver),
10,571✔
5826
                  simplex_smt_interface(solver), cmode);
5827
  } else {
5828
    // the core is already initialized: attach simplex
5829
    smt_core_reset_thsolver(ctx->core, solver, simplex_ctrl_interface(solver),
1✔
5830
                            simplex_smt_interface(solver));
5831
  }
5832

5833
  simplex_solver_init_jmpbuf(solver, &ctx->env);
14,907✔
5834
  ctx->arith_solver = solver;
14,907✔
5835
  ctx->arith = *simplex_arith_interface(solver);
14,907✔
5836
}
14,907✔
5837

5838

5839
/*
5840
 * Create IDL/SIMPLEX solver based on ctx->dl_profile
5841
 */
5842
static void create_auto_idl_solver(context_t *ctx) {
27✔
5843
  dl_data_t *profile;
5844
  int32_t bound;
5845
  double atom_density;
5846

5847
  assert(ctx->dl_profile != NULL);
5848
  profile = ctx->dl_profile;
27✔
5849

5850
  if (q_is_smallint(&profile->path_bound)) {
27✔
5851
    bound = q_get_smallint(&profile->path_bound);
26✔
5852
  } else {
5853
    bound = INT32_MAX;
1✔
5854
  }
5855

5856
  if (bound >= 1073741824) {
27✔
5857
    // simplex required because of arithmetic overflow
5858
    create_simplex_solver(ctx, true);
1✔
5859
    ctx->arch = CTX_ARCH_SPLX;
1✔
5860
  } else if (profile->num_vars >= 1000) {
26✔
5861
    // too many variables for FW
5862
    create_simplex_solver(ctx, true);
×
5863
    ctx->arch = CTX_ARCH_SPLX;
×
5864
  } else if (profile->num_vars <= 200 || profile->num_eqs == 0) {
26✔
5865
    // use FW for now, until we've tested SIMPLEX more
5866
    // 0 equalities usually means a scheduling problem
5867
    // --flatten works better on IDL/FW
5868
    create_idl_solver(ctx, true);
26✔
5869
    ctx->arch = CTX_ARCH_IFW;
26✔
5870
    enable_diseq_and_or_flattening(ctx);
26✔
5871

5872
  } else {
5873

5874
    // problem density
5875
    if (profile->num_vars > 0) {
×
5876
      atom_density = ((double) profile->num_atoms)/profile->num_vars;
×
5877
    } else {
5878
      atom_density = 0;
×
5879
    }
5880

5881
    if (atom_density >= 10.0) {
×
5882
      // high density: use FW
5883
      create_idl_solver(ctx, true);
×
5884
      ctx->arch = CTX_ARCH_IFW;
×
5885
      enable_diseq_and_or_flattening(ctx);
×
5886
    } else {
5887
      create_simplex_solver(ctx, true);
×
5888
      ctx->arch = CTX_ARCH_SPLX;
×
5889
    }
5890
  }
5891
}
27✔
5892

5893

5894
/*
5895
 * Create RDL/SIMPLEX solver based on ctx->dl_profile
5896
 */
5897
static void create_auto_rdl_solver(context_t *ctx) {
8✔
5898
  dl_data_t *profile;
5899
  double atom_density;
5900

5901
  assert(ctx->dl_profile != NULL);
5902
  profile = ctx->dl_profile;
8✔
5903

5904
  if (profile->num_vars >= 1000) {
8✔
5905
    create_simplex_solver(ctx, true);
×
5906
    ctx->arch = CTX_ARCH_SPLX;
×
5907
  } else if (profile->num_vars <= 200 || profile->num_eqs == 0) {
8✔
5908
    create_rdl_solver(ctx, true);
8✔
5909
    ctx->arch = CTX_ARCH_RFW;
8✔
5910
  } else {
5911
    // problem density
5912
    if (profile->num_vars > 0) {
×
5913
      atom_density = ((double) profile->num_atoms)/profile->num_vars;
×
5914
    } else {
5915
      atom_density = 0;
×
5916
    }
5917

5918
    if (atom_density >= 7.0) {
×
5919
      // high density: use FW
5920
      create_rdl_solver(ctx, true);
×
5921
      ctx->arch = CTX_ARCH_RFW;
×
5922
    } else {
5923
      // low-density: use SIMPLEX
5924
      create_simplex_solver(ctx, true);
×
5925
      ctx->arch = CTX_ARCH_SPLX;
×
5926
    }
5927
  }
5928
}
8✔
5929

5930

5931

5932
/*
5933
 * Create the bitvector solver
5934
 * - attach it to the egraph if there's an egraph
5935
 * - attach it to the core and initialize the core otherwise
5936
 */
5937
static void create_bv_solver(context_t *ctx) {
10,551✔
5938
  bv_solver_t *solver;
5939
  smt_mode_t cmode;
5940

5941
  assert(ctx->bv_solver == NULL && ctx->core != NULL);
5942

5943
  cmode = core_mode[ctx->mode];
10,551✔
5944
  solver = (bv_solver_t *) safe_malloc(sizeof(bv_solver_t));
10,551✔
5945
  init_bv_solver(solver, ctx->core, ctx->egraph);
10,551✔
5946

5947
  if (ctx->egraph != NULL) {
10,551✔
5948
    // attach as a satellite to the egraph
5949
    egraph_attach_bvsolver(ctx->egraph, solver, bv_solver_ctrl_interface(solver),
4,418✔
5950
                           bv_solver_smt_interface(solver), bv_solver_egraph_interface(solver),
5951
                           bv_solver_bv_egraph_interface(solver));
5952
  } else {
5953
    // attach to the core and initialize the core
5954
    init_smt_core(ctx->core, CTX_DEFAULT_CORE_SIZE, solver, bv_solver_ctrl_interface(solver),
6,133✔
5955
                  bv_solver_smt_interface(solver), cmode);
5956
  }
5957

5958
  // EXPERIMENT
5959
  //  smt_core_make_etable(ctx->core);
5960
  // END
5961

5962
  bv_solver_init_jmpbuf(solver, &ctx->env);
10,551✔
5963
  ctx->bv_solver = solver;
10,551✔
5964
  ctx->bv = *bv_solver_bv_interface(solver);
10,551✔
5965
}
10,551✔
5966

5967

5968
/*
5969
 * Create the array/function theory solver and attach it to the egraph
5970
 */
5971
static void create_fun_solver(context_t *ctx) {
4,425✔
5972
  fun_solver_t *solver;
5973

5974
  assert(ctx->egraph != NULL && ctx->fun_solver == NULL);
5975

5976
  solver = (fun_solver_t *) safe_malloc(sizeof(fun_solver_t));
4,425✔
5977
  init_fun_solver(solver, ctx->core, &ctx->gate_manager, ctx->egraph, ctx->types);
4,425✔
5978
  egraph_attach_funsolver(ctx->egraph, solver, fun_solver_ctrl_interface(solver),
4,425✔
5979
                          fun_solver_egraph_interface(solver),
5980
                          fun_solver_fun_egraph_interface(solver));
5981

5982
  ctx->fun_solver = solver;
4,425✔
5983
}
4,425✔
5984

5985

5986
/*
5987
 * Allocate and initialize solvers based on architecture and mode
5988
 * - core and gate manager must exist at this point
5989
 * - if the architecture is either AUTO_IDL or AUTO_RDL, no theory solver
5990
 *   is allocated yet, and the core is initialized for Boolean only
5991
 * - otherwise, all components are ready and initialized, including the core.
5992
 */
5993
static void init_solvers(context_t *ctx) {
22,227✔
5994
  uint8_t solvers;
5995
  smt_core_t *core;
5996
  smt_mode_t cmode;
5997
  egraph_t *egraph;
5998

5999
  solvers = arch_components[ctx->arch];
22,227✔
6000

6001
  ctx->egraph = NULL;
22,227✔
6002
  ctx->arith_solver = NULL;
22,227✔
6003
  ctx->bv_solver = NULL;
22,227✔
6004
  ctx->fun_solver = NULL;
22,227✔
6005
  ctx->quant_solver = NULL;
22,227✔
6006
  ctx->mcsat_supplement_active = false;
22,227✔
6007

6008
  // Create egraph first, then satellite solvers
6009
  if (solvers & EGRPH) {
22,227✔
6010
    create_egraph(ctx);
4,792✔
6011
  }
6012

6013
  // Create mcsat
6014
  if (solvers & MCSAT) {
22,227✔
6015
    create_mcsat(ctx);
695✔
6016
  }
6017

6018
  // Arithmetic solver
6019
  if (solvers & SPLX) {
22,227✔
6020
    create_simplex_solver(ctx, false);
14,906✔
6021
  } else if (solvers & IFW) {
7,321✔
6022
    create_idl_solver(ctx, false);
×
6023
  } else if (solvers & RFW) {
7,321✔
6024
    create_rdl_solver(ctx, false);
×
6025
  }
6026

6027
  // Bitvector solver
6028
  if (solvers & BVSLVR) {
22,227✔
6029
    create_bv_solver(ctx);
10,551✔
6030
  }
6031

6032
  // Array solver
6033
  if (solvers & FSLVR) {
22,227✔
6034
    create_fun_solver(ctx);
4,425✔
6035
  }
6036

6037
  /*
6038
   * At this point all solvers are ready and initialized, except the
6039
   * egraph and core if the egraph is present or the core if there are
6040
   * no solvers, or if arch is AUTO_IDL or AUTO_RDL.
6041
   */
6042
  cmode = core_mode[ctx->mode];   // initialization mode for the core
22,227✔
6043
  egraph = ctx->egraph;
22,227✔
6044
  core = ctx->core;
22,227✔
6045
  if (egraph != NULL) {
22,227✔
6046
    init_smt_core(core, CTX_DEFAULT_CORE_SIZE, egraph, egraph_ctrl_interface(egraph),
4,792✔
6047
                  egraph_smt_interface(egraph), cmode);
6048
    egraph_attach_core(egraph, core);
4,792✔
6049

6050
  } else if (solvers == 0) {
17,435✔
6051
    /*
6052
     * Boolean solver only. If arch if AUTO_IDL or AUTO_RDL, the
6053
     * theory solver will be changed later by create_auto_idl_solver
6054
     * or create_auto_rdl_solver.
6055
     */
6056
    assert(ctx->arith_solver == NULL && ctx->bv_solver == NULL && ctx->fun_solver == NULL);
6057
    init_smt_core(core, CTX_DEFAULT_CORE_SIZE, NULL, &null_ctrl, &null_smt, cmode);
36✔
6058
  } else if (solvers == MCSAT) {
17,399✔
6059
    /*
6060
     * MCsat solver only, we create the core, but never use it.
6061
     */
6062
    assert(ctx->egraph == NULL && ctx->arith_solver == NULL &&
6063
           ctx->bv_solver == NULL && ctx->fun_solver == NULL);
6064
    init_smt_core(core, CTX_DEFAULT_CORE_SIZE, NULL, &null_ctrl, &null_smt, cmode);
695✔
6065
  }
6066

6067
  /*
6068
   * Optimization: if the arch is NOSOLVERS or BV then we set bool_only in the core
6069
   */
6070
  if (ctx->arch == CTX_ARCH_NOSOLVERS || ctx->arch == CTX_ARCH_BV) {
22,227✔
6071
    smt_core_set_bool_only(core);
6,133✔
6072
  }
6073
}
22,227✔
6074

6075

6076

6077

6078
/*
6079
 * Delete the arithmetic solver
6080
 */
6081
static void delete_arith_solver(context_t *ctx) {
14,940✔
6082
  uint8_t solvers;
6083

6084
  assert(ctx->arith_solver != NULL);
6085

6086
  solvers = arch_components[ctx->arch];
14,940✔
6087
  if (solvers & IFW) {
14,940✔
6088
    delete_idl_solver(ctx->arith_solver);
26✔
6089
  } else if (solvers & RFW) {
14,914✔
6090
    delete_rdl_solver(ctx->arith_solver);
8✔
6091
  } else if (solvers & SPLX) {
14,906✔
6092
    delete_simplex_solver(ctx->arith_solver);
14,906✔
6093
  }
6094
  safe_free(ctx->arith_solver);
14,940✔
6095
  ctx->arith_solver = NULL;
14,940✔
6096
}
14,940✔
6097

6098

6099

6100

6101
/*****************************
6102
 *  CONTEXT INITIALIZATION   *
6103
 ****************************/
6104

6105
/*
6106
 * Check mode and architecture
6107
 */
6108
#ifndef NDEBUG
6109
static inline bool valid_mode(context_mode_t mode) {
6110
  return CTX_MODE_ONECHECK <= mode && mode <= CTX_MODE_INTERACTIVE;
6111
}
6112

6113
static inline bool valid_arch(context_arch_t arch) {
6114
  return CTX_ARCH_NOSOLVERS <= arch && arch <= CTX_ARCH_MCSAT;
6115
}
6116
#endif
6117

6118

6119
/*
6120
 * Initialize ctx for the given mode and architecture
6121
 * - terms = term table for that context
6122
 * - qflag = true means quantifiers allowed
6123
 * - qflag = false means no quantifiers
6124
 */
6125
void init_context(context_t *ctx, term_table_t *terms, smt_logic_t logic,
22,227✔
6126
                  context_mode_t mode, context_arch_t arch, bool qflag) {
6127
  assert(valid_mode(mode) && valid_arch(arch));
6128

6129
  /*
6130
   * Set architecture and options
6131
   */
6132
  ctx->mode = mode;
22,227✔
6133
  ctx->arch = arch;
22,227✔
6134
  ctx->logic = logic;
22,227✔
6135
  ctx->theories = arch2theories[arch];
22,227✔
6136
  ctx->options = mode2options[mode];
22,227✔
6137
  if (qflag) {
22,227✔
6138
    // quantifiers require egraph
6139
    assert((ctx->theories & UF_MASK) != 0);
6140
    ctx->theories |= QUANT_MASK;
×
6141
  }
6142

6143
  ctx->base_level = 0;
22,227✔
6144

6145
  /*
6146
   * The core is always needed: allocate it here. It's not initialized yet.
6147
   * The other solver are optionals.
6148
   *
6149
   * TODO: we could skip this when we use MCSAT (since then the core is
6150
   * not needed).
6151
   */
6152
  ctx->core = (smt_core_t *) safe_malloc(sizeof(smt_core_t));
22,227✔
6153
  ctx->egraph = NULL;
22,227✔
6154
  ctx->mcsat = NULL;
22,227✔
6155
  ctx->arith_solver = NULL;
22,227✔
6156
  ctx->bv_solver = NULL;
22,227✔
6157
  ctx->fun_solver = NULL;
22,227✔
6158
  ctx->quant_solver = NULL;
22,227✔
6159

6160
  /*
6161
   * Global tables + gate manager
6162
   */
6163
  ctx->types = terms->types;
22,227✔
6164
  ctx->terms = terms;
22,227✔
6165
  init_gate_manager(&ctx->gate_manager, ctx->core);
22,227✔
6166

6167
  /*
6168
   * Simplification/internalization support
6169
   */
6170
  init_intern_tbl(&ctx->intern, 0, terms);
22,227✔
6171
  init_ivector(&ctx->top_eqs, CTX_DEFAULT_VECTOR_SIZE);
22,227✔
6172
  init_ivector(&ctx->top_atoms, CTX_DEFAULT_VECTOR_SIZE);
22,227✔
6173
  init_ivector(&ctx->top_formulas, CTX_DEFAULT_VECTOR_SIZE);
22,227✔
6174
  init_ivector(&ctx->top_interns, CTX_DEFAULT_VECTOR_SIZE);
22,227✔
6175

6176
  /*
6177
   * Force the internalization mapping for true and false
6178
   * - true  term --> true_occ
6179
   * - false term --> false_occ
6180
   * This mapping holds even if there's no egraph.
6181
   */
6182
  intern_tbl_map_root(&ctx->intern, true_term, bool2code(true));
22,227✔
6183

6184
  /*
6185
   * Auxiliary internalization buffers
6186
   */
6187
  init_ivector(&ctx->subst_eqs, CTX_DEFAULT_VECTOR_SIZE);
22,227✔
6188
  init_ivector(&ctx->aux_eqs, CTX_DEFAULT_VECTOR_SIZE);
22,227✔
6189
  init_ivector(&ctx->aux_atoms, CTX_DEFAULT_VECTOR_SIZE);
22,227✔
6190
  init_ivector(&ctx->aux_vector, CTX_DEFAULT_VECTOR_SIZE);
22,227✔
6191
  init_int_queue(&ctx->queue, 0);
22,227✔
6192
  init_istack(&ctx->istack);
22,227✔
6193
  init_objstack(&ctx->ostack);
22,227✔
6194
  init_sharing_map(&ctx->sharing, &ctx->intern);
22,227✔
6195
  init_objstore(&ctx->cstore, sizeof(conditional_t), 32);
22,227✔
6196
  init_assumption_stack(&ctx->assumptions);
22,227✔
6197

6198
  ctx->subst = NULL;
22,227✔
6199
  ctx->marks = NULL;
22,227✔
6200
  ctx->cache = NULL;
22,227✔
6201
  ctx->small_cache = NULL;
22,227✔
6202
  ctx->edge_map = NULL;
22,227✔
6203
  ctx->eq_cache = NULL;
22,227✔
6204
  ctx->divmod_table = NULL;
22,227✔
6205
  ctx->explorer = NULL;
22,227✔
6206
  ctx->unsat_core_cache = NULL;
22,227✔
6207

6208
  ctx->dl_profile = NULL;
22,227✔
6209
  ctx->arith_buffer = NULL;
22,227✔
6210
  ctx->poly_buffer = NULL;
22,227✔
6211
  ctx->aux_poly = NULL;
22,227✔
6212
  ctx->aux_poly_size = 0;
22,227✔
6213

6214
  ctx->bvpoly_buffer = NULL;
22,227✔
6215

6216
  q_init(&ctx->aux);
22,227✔
6217
  init_bvconstant(&ctx->bv_buffer);
22,227✔
6218

6219
  ctx->trace = NULL;
22,227✔
6220

6221
  // mcsat options default
6222
  init_mcsat_options(&ctx->mcsat_options);
22,227✔
6223
  init_ivector(&ctx->mcsat_var_order, CTX_DEFAULT_VECTOR_SIZE);
22,227✔
6224
  init_ivector(&ctx->mcsat_initial_var_order, CTX_DEFAULT_VECTOR_SIZE);
22,227✔
6225
  /*
6226
   * Allocate and initialize the solvers and core
6227
   * NOTE: no theory solver yet if arch is AUTO_IDL or AUTO_RDL
6228
   */
6229
  init_solvers(ctx);
22,227✔
6230

6231
  ctx->en_quant = false;
22,227✔
6232
}
22,227✔
6233

6234

6235

6236

6237
/*
6238
 * Delete ctx
6239
 */
6240
void delete_context(context_t *ctx) {
22,226✔
6241
  if (ctx->core != NULL) {
22,226✔
6242
    delete_smt_core(ctx->core);
22,226✔
6243
    safe_free(ctx->core);
22,226✔
6244
    ctx->core = NULL;
22,226✔
6245
  }
6246

6247
  if (ctx->mcsat != NULL) {
22,226✔
6248
    mcsat_destruct(ctx->mcsat);
695✔
6249
    safe_free(ctx->mcsat);
695✔
6250
    ctx->mcsat = NULL;
695✔
6251
  }
6252

6253
  if (ctx->mcsat_supplement_active) {
22,226✔
6254
    context_disable_mcsat_supplement(ctx);
5✔
6255
  }
6256

6257
  if (ctx->egraph != NULL) {
22,226✔
6258
    delete_egraph(ctx->egraph);
4,791✔
6259
    safe_free(ctx->egraph);
4,791✔
6260
    ctx->egraph = NULL;
4,791✔
6261
  }
6262

6263
  if (ctx->arith_solver != NULL) {
22,226✔
6264
    delete_arith_solver(ctx);
14,940✔
6265
  }
6266

6267
  if (ctx->fun_solver != NULL) {
22,226✔
6268
    delete_fun_solver(ctx->fun_solver);
4,424✔
6269
    safe_free(ctx->fun_solver);
4,424✔
6270
    ctx->fun_solver = NULL;
4,424✔
6271
  }
6272

6273
  if (ctx->quant_solver != NULL) {
22,226✔
6274
    delete_quant_solver(ctx->quant_solver);
52✔
6275
    safe_free(ctx->quant_solver);
52✔
6276
    ctx->quant_solver = NULL;
52✔
6277
  }
6278

6279
  if (ctx->bv_solver != NULL) {
22,226✔
6280
    delete_bv_solver(ctx->bv_solver);
10,550✔
6281
    safe_free(ctx->bv_solver);
10,550✔
6282
    ctx->bv_solver = NULL;
10,550✔
6283
  }
6284

6285
  delete_gate_manager(&ctx->gate_manager);
22,226✔
6286
  /* delete_mcsat_options(&ctx->mcsat_options); // if used then the same memory is freed twice */
6287
  delete_ivector(&ctx->mcsat_var_order);
22,226✔
6288
  delete_ivector(&ctx->mcsat_initial_var_order);
22,226✔
6289

6290
  delete_intern_tbl(&ctx->intern);
22,226✔
6291
  delete_ivector(&ctx->top_eqs);
22,226✔
6292
  delete_ivector(&ctx->top_atoms);
22,226✔
6293
  delete_ivector(&ctx->top_formulas);
22,226✔
6294
  delete_ivector(&ctx->top_interns);
22,226✔
6295

6296
  delete_ivector(&ctx->subst_eqs);
22,226✔
6297
  delete_ivector(&ctx->aux_eqs);
22,226✔
6298
  delete_ivector(&ctx->aux_atoms);
22,226✔
6299
  delete_ivector(&ctx->aux_vector);
22,226✔
6300
  delete_int_queue(&ctx->queue);
22,226✔
6301
  delete_istack(&ctx->istack);
22,226✔
6302
  delete_objstack(&ctx->ostack);
22,226✔
6303
  delete_sharing_map(&ctx->sharing);
22,226✔
6304
  delete_objstore(&ctx->cstore);
22,226✔
6305
  delete_assumption_stack(&ctx->assumptions);
22,226✔
6306

6307
  context_free_subst(ctx);
22,226✔
6308
  context_free_marks(ctx);
22,226✔
6309
  context_free_cache(ctx);
22,226✔
6310
  context_free_small_cache(ctx);
22,226✔
6311
  context_free_eq_cache(ctx);
22,226✔
6312
  context_free_divmod_table(ctx);
22,226✔
6313
  context_free_explorer(ctx);
22,226✔
6314

6315
  context_free_dl_profile(ctx);
22,226✔
6316
  context_free_edge_map(ctx);
22,226✔
6317
  context_free_arith_buffer(ctx);
22,226✔
6318
  context_free_poly_buffer(ctx);
22,226✔
6319
  context_free_aux_poly(ctx);
22,226✔
6320

6321
  context_free_bvpoly_buffer(ctx);
22,226✔
6322
  context_invalidate_unsat_core_cache(ctx);
22,226✔
6323

6324
  q_clear(&ctx->aux);
22,226✔
6325
  delete_bvconstant(&ctx->bv_buffer);
22,226✔
6326
}
22,226✔
6327

6328
void context_invalidate_unsat_core_cache(context_t *ctx) {
87,630✔
6329
  if (ctx->unsat_core_cache != NULL) {
87,630✔
6330
    delete_ivector(ctx->unsat_core_cache);
2,706✔
6331
    safe_free(ctx->unsat_core_cache);
2,706✔
6332
    ctx->unsat_core_cache = NULL;
2,706✔
6333
  }
6334
}
87,630✔
6335

6336

6337

6338
/*
6339
 * Reset: remove all assertions and clear all internalization tables
6340
 */
6341
void reset_context(context_t *ctx) {
13✔
6342
  ctx->base_level = 0;
13✔
6343
  context_invalidate_unsat_core_cache(ctx);
13✔
6344

6345
  reset_smt_core(ctx->core); // this propagates reset to all solvers
13✔
6346

6347
  if (ctx->mcsat_supplement_active) {
13✔
6348
    context_disable_mcsat_supplement(ctx);
5✔
6349
  }
6350

6351
  if (ctx->mcsat != NULL) {
13✔
6352
    mcsat_reset(ctx->mcsat);
7✔
6353
  }
6354

6355
  reset_gate_manager(&ctx->gate_manager);
13✔
6356

6357
  ivector_reset(&ctx->mcsat_var_order);
13✔
6358
  ivector_reset(&ctx->mcsat_initial_var_order);
13✔
6359

6360
  reset_intern_tbl(&ctx->intern);
13✔
6361
  ivector_reset(&ctx->top_eqs);
13✔
6362
  ivector_reset(&ctx->top_atoms);
13✔
6363
  ivector_reset(&ctx->top_formulas);
13✔
6364
  ivector_reset(&ctx->top_interns);
13✔
6365

6366
  // Force the internalization mapping for true and false
6367
  intern_tbl_map_root(&ctx->intern, true_term, bool2code(true));
13✔
6368

6369
  ivector_reset(&ctx->subst_eqs);
13✔
6370
  ivector_reset(&ctx->aux_eqs);
13✔
6371
  ivector_reset(&ctx->aux_atoms);
13✔
6372
  ivector_reset(&ctx->aux_vector);
13✔
6373
  int_queue_reset(&ctx->queue);
13✔
6374
  reset_istack(&ctx->istack);
13✔
6375
  reset_objstack(&ctx->ostack);
13✔
6376
  reset_sharing_map(&ctx->sharing);
13✔
6377
  reset_objstore(&ctx->cstore);
13✔
6378
  reset_assumption_stack(&ctx->assumptions);
13✔
6379

6380
  context_free_subst(ctx);
13✔
6381
  context_free_marks(ctx);
13✔
6382
  context_reset_small_cache(ctx);
13✔
6383
  context_reset_eq_cache(ctx);
13✔
6384
  context_reset_divmod_table(ctx);
13✔
6385
  context_reset_explorer(ctx);
13✔
6386

6387
  context_free_arith_buffer(ctx);
13✔
6388
  context_reset_poly_buffer(ctx);
13✔
6389
  context_free_aux_poly(ctx);
13✔
6390
  context_free_dl_profile(ctx);
13✔
6391

6392
  context_free_bvpoly_buffer(ctx);
13✔
6393

6394
  q_clear(&ctx->aux);
13✔
6395
}
13✔
6396

6397

6398
/*
6399
 * Add tracer to ctx and ctx->core
6400
 */
6401
void context_set_trace(context_t *ctx, tracer_t *trace) {
285✔
6402
  assert(ctx->trace == NULL);
6403
  ctx->trace = trace;
285✔
6404
  smt_core_set_trace(ctx->core, trace);
285✔
6405
  if (ctx->mcsat != NULL) {
285✔
6406
    mcsat_set_tracer(ctx->mcsat, trace);
284✔
6407
  }
6408
  if (ctx->mcsat_supplement_active) {
285✔
NEW
6409
    mcsat_satellite_t *sat = context_mcsat_satellite(ctx);
×
NEW
6410
    if (sat != NULL) {
×
NEW
6411
      mcsat_satellite_set_trace(sat, trace);
×
6412
    }
6413
  }
6414
}
285✔
6415

6416

6417
/*
6418
 * Push and pop
6419
 */
6420
void context_push(context_t *ctx) {
18,490✔
6421
  assert(context_supports_pushpop(ctx));
6422
  context_invalidate_unsat_core_cache(ctx);
18,490✔
6423
  smt_push(ctx->core);  // propagates to all solvers
18,490✔
6424
  if (ctx->mcsat != NULL) {
18,490✔
6425
    mcsat_push(ctx->mcsat);
1,325✔
6426
  }
6427
  intern_tbl_push(&ctx->intern);
18,490✔
6428
  assumption_stack_push(&ctx->assumptions);
18,490✔
6429
  context_eq_cache_push(ctx);
18,490✔
6430
  context_divmod_table_push(ctx);
18,490✔
6431

6432
  ctx->base_level ++;
18,490✔
6433
}
18,490✔
6434

6435
void context_pop(context_t *ctx) {
1,474✔
6436
  assert(context_supports_pushpop(ctx) && ctx->base_level > 0);
6437
  context_invalidate_unsat_core_cache(ctx);
1,474✔
6438
  smt_pop(ctx->core);   // propagates to all solvers
1,474✔
6439
  if (ctx->mcsat != NULL) {
1,474✔
6440
    mcsat_pop(ctx->mcsat);
1,241✔
6441
  }
6442
  intern_tbl_pop(&ctx->intern);
1,474✔
6443
  assumption_stack_pop(&ctx->assumptions);
1,474✔
6444
  context_eq_cache_pop(ctx);
1,474✔
6445
  context_divmod_table_pop(ctx);
1,474✔
6446

6447
  ctx->base_level --;
1,474✔
6448
}
1,474✔
6449

6450

6451

6452

6453

6454
/****************************
6455
 *   ASSERTIONS AND CHECK   *
6456
 ***************************/
6457

6458
/*
6459
 * Build the sharing data
6460
 * - processes all the assertions in vectors top_eqs, top_atoms, top_formulas
6461
 * - this function should be called after building the substitutions
6462
 */
6463
static void context_build_sharing_data(context_t *ctx) {
71,777✔
6464
  sharing_map_t *map;
6465

6466
  map = &ctx->sharing;
71,777✔
6467
  reset_sharing_map(map);
71,777✔
6468
  sharing_map_add_terms(map, ctx->top_eqs.data, ctx->top_eqs.size);
71,777✔
6469
  sharing_map_add_terms(map, ctx->top_atoms.data, ctx->top_atoms.size);
71,777✔
6470
  sharing_map_add_terms(map, ctx->top_formulas.data, ctx->top_formulas.size);
71,777✔
6471
}
71,777✔
6472

6473

6474
#if 0
6475
/*
6476
 * PROVISIONAL: SHOW ASSERTIONS
6477
 */
6478
static void context_show_assertions(const context_t *ctx, uint32_t n, const term_t *a) {
6479
  pp_area_t area;
6480
  yices_pp_t printer;
6481
  uint32_t i;
6482

6483
  area.width = 80;
6484
  area.height = UINT32_MAX;
6485
  area.offset = 0;
6486
  area.stretch = false;
6487
  area.truncate = false;
6488
  init_yices_pp(&printer, stdout, &area, PP_VMODE, 0);
6489

6490
  for (i=0; i<n; i++) {
6491
    pp_term_full(&printer, ctx->terms, a[i]);
6492
    flush_yices_pp(&printer);
6493
  }
6494
  delete_yices_pp(&printer, true);
6495
}
6496
#endif
6497

6498
/*
6499
 * Flatten and internalize assertions a[0 ... n-1]
6500
 * - all elements a[i] must be valid boolean term in ctx->terms
6501
 * - return code:
6502
 *   TRIVIALLY_UNSAT if there's an easy contradiction
6503
 *   CTX_NO_ERROR if the assertions were processed without error
6504
 *   a negative error code otherwise.
6505
 */
6506
static int32_t context_process_assertions(context_t *ctx, uint32_t n, const term_t *a) {
74,433✔
6507
  ivector_t *v;
6508
  uint32_t i;
6509
  int code;
6510

6511
  ivector_reset(&ctx->top_eqs);
74,433✔
6512
  ivector_reset(&ctx->top_atoms);
74,433✔
6513
  ivector_reset(&ctx->top_formulas);
74,433✔
6514
  ivector_reset(&ctx->top_interns);
74,433✔
6515
  ivector_reset(&ctx->subst_eqs);
74,433✔
6516
  ivector_reset(&ctx->aux_eqs);
74,433✔
6517
  ivector_reset(&ctx->aux_atoms);
74,433✔
6518

6519
  if (ctx->arch != CTX_ARCH_MCSAT && context_has_egraph(ctx)) {
74,433✔
6520
    if (context_assertions_need_mcsat_supplement(ctx, n, a)) {
25,668✔
6521
      code = context_enable_mcsat_supplement(ctx);
14✔
6522
      if (code < 0) {
14✔
NEW
6523
        return code;
×
6524
      }
6525
    }
6526
  }
6527

6528
  if (ctx->mcsat_supplement_active) {
74,433✔
6529
    mcsat_satellite_t *sat = context_mcsat_satellite(ctx);
18✔
6530
    if (sat != NULL) {
18✔
6531
      code = mcsat_satellite_assert_formulas(sat, n, a);
18✔
6532
      if (code < 0) {
18✔
NEW
6533
        return code;
×
6534
      }
6535
    }
6536
  }
6537

6538
  code = setjmp(ctx->env);
74,433✔
6539
  if (code == 0) {
74,813✔
6540

6541
    // If using MCSAT, just check and done
6542
    if (ctx->mcsat != NULL) {
74,433✔
6543
      // TBD: quant support
6544
      assert(!context_quant_enabled(ctx));
6545
      code = mcsat_assert_formulas(ctx->mcsat, n, a);
2,302✔
6546
      goto done;
2,291✔
6547
    }
6548

6549
#if 0
6550
    printf("\n=== Context: process assertions ===\n");
6551
    context_show_assertions(ctx, n, a);
6552
    printf("===\n\n");
6553
#endif
6554

6555
    // flatten
6556
    for (i=0; i<n; i++) {
195,358✔
6557
      flatten_assertion(ctx, a[i]);
123,580✔
6558
    }
6559

6560
    trace_printf(ctx->trace, 6, "(done flattening)\n");
71,778✔
6561

6562
    /*
6563
     * At this point, the assertions are stored into the vectors
6564
     * top_eqs, top_atoms, top_formulas, and top_interns
6565
     * - more top-level equalities may be in subst_eqs
6566
     * - ctx->intern stores the internalized terms and the variable
6567
     *   substitutions.
6568
     */
6569

6570
    switch (ctx->arch) {
71,778✔
6571
    // TBD: make sure following preprocessings work with quant enabled
6572
    case CTX_ARCH_EG:
3,329✔
6573
      /*
6574
       * UF problem: we must process subst_eqs last since the
6575
       * preprocessing may add new equalities in aux_eqs that may end
6576
       * up in subst_eqs after the call to process_aux_eqs.
6577
       */
6578
      if (context_breaksym_enabled(ctx)) {
3,329✔
6579
        break_uf_symmetries(ctx);
30✔
6580
      }
6581
      if (context_eq_abstraction_enabled(ctx)) {
3,329✔
6582
        analyze_uf(ctx);
64✔
6583
      }
6584
      if (ctx->aux_eqs.size > 0) {
3,329✔
6585
        process_aux_eqs(ctx);
6✔
6586
      }
6587
      if (ctx->subst_eqs.size > 0) {
3,328✔
6588
        context_process_candidate_subst(ctx);
10✔
6589
      }
6590
      break;
3,328✔
6591

6592
    case CTX_ARCH_AUTO_IDL:
27✔
6593
      /*
6594
       * For difference logic, we must process the subst_eqs first
6595
       * (otherwise analyze_diff_logic may give wrong results).
6596
       */
6597
      if (ctx->subst_eqs.size > 0) {
27✔
6598
        context_process_candidate_subst(ctx);
×
6599
      }
6600
      analyze_diff_logic(ctx, true);
27✔
6601
      create_auto_idl_solver(ctx);
27✔
6602
      break;
27✔
6603

6604
    case CTX_ARCH_AUTO_RDL:
8✔
6605
      /*
6606
       * Difference logic, we must process the subst_eqs first
6607
       */
6608
      trace_printf(ctx->trace, 6, "(auto-idl solver)\n");
8✔
6609
      if (ctx->subst_eqs.size > 0) {
8✔
6610
        context_process_candidate_subst(ctx);
×
6611
      }
6612
      analyze_diff_logic(ctx, false);
8✔
6613
      create_auto_rdl_solver(ctx);
8✔
6614
      break;
8✔
6615

6616
    case CTX_ARCH_SPLX:
30,674✔
6617
      /*
6618
       * Simplex, like EG, may add aux_atoms so we must process
6619
       * subst_eqs last here.
6620
       */
6621
      trace_printf(ctx->trace, 6, "(Simplex solver)\n");
30,674✔
6622
      // more optional processing
6623
      if (context_cond_def_preprocessing_enabled(ctx)) {
30,674✔
6624
        process_conditional_definitions(ctx);
52✔
6625
        if (ctx->aux_eqs.size > 0) {
52✔
6626
          process_aux_eqs(ctx);
2✔
6627
        }
6628
        if (ctx->aux_atoms.size > 0) {
52✔
6629
          process_aux_atoms(ctx);
3✔
6630
        }
6631
      }
6632
      if (ctx->subst_eqs.size > 0) {
30,674✔
6633
        context_process_candidate_subst(ctx);
16✔
6634
      }
6635
      break;
30,674✔
6636

6637
    default:
37,740✔
6638
      /*
6639
       * Process the candidate variable substitutions if any
6640
       */
6641
      if (ctx->subst_eqs.size > 0) {
37,740✔
6642
        context_process_candidate_subst(ctx);
2,745✔
6643
      }
6644
      break;
37,740✔
6645
    }
6646

6647
    /*
6648
     * Sharing
6649
     */
6650
    context_build_sharing_data(ctx);
71,777✔
6651

6652
    /*
6653
     * Notify the core + solver(s)
6654
     */
6655
    if (!context_quant_enabled(ctx)) {
71,777✔
6656
        // TBD: make sure this is correct
6657
      internalization_start(ctx->core);
69,244✔
6658
    }
6659

6660
    /*
6661
     * Assert top_eqs, top_atoms, top_formulas, top_interns
6662
     */
6663
    code = CTX_NO_ERROR;
71,777✔
6664

6665
    // first: all terms that are already internalized
6666
    v = &ctx->top_interns;
71,777✔
6667
    n = v->size;
71,777✔
6668
    if (n > 0) {
71,777✔
6669
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" existing terms)\n", n);
284✔
6670
      i = 0;
284✔
6671
      do {
6672
        assert_toplevel_intern(ctx, v->data[i]);
739✔
6673
        i ++;
739✔
6674
      } while (i < n);
739✔
6675

6676
      // one round of propagation
6677
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
284✔
6678
        code = TRIVIALLY_UNSAT;
11✔
6679
        goto done;
11✔
6680
      }
6681
    }
6682

6683
    // second: all top-level equalities
6684
    v = &ctx->top_eqs;
71,766✔
6685
    n = v->size;
71,766✔
6686
    if (n > 0) {
71,766✔
6687
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" top-level equalities)\n", n);
6,748✔
6688
      i = 0;
6,748✔
6689
      do {
6690
        assert_toplevel_formula(ctx, v->data[i]);
10,809✔
6691
        i ++;
10,805✔
6692
      } while (i < n);
10,805✔
6693

6694
      // one round of propagation
6695
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
6,744✔
6696
        code = TRIVIALLY_UNSAT;
68✔
6697
        goto done;
68✔
6698
      }
6699
    }
6700

6701
    // third: all top-level atoms (other than equalities)
6702
    v = &ctx->top_atoms;
71,694✔
6703
    n = v->size;
71,694✔
6704
    if (n > 0) {
71,694✔
6705
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" top-level atoms)\n", n);
15,457✔
6706
      i = 0;
15,457✔
6707
      do {
6708
        assert_toplevel_formula(ctx, v->data[i]);
68,450✔
6709
        i ++;
68,439✔
6710
      } while (i < n);
68,439✔
6711

6712
      // one round of propagation
6713
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
15,446✔
6714
        code = TRIVIALLY_UNSAT;
75✔
6715
        goto done;
75✔
6716
      }
6717
    }
6718

6719
    // last: all non-atomic, formulas
6720
    v =  &ctx->top_formulas;
71,608✔
6721
    n = v->size;
71,608✔
6722
    if (n > 0) {
71,608✔
6723
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" top-level formulas)\n", n);
21,977✔
6724
      i = 0;
21,977✔
6725
      do {
6726
        assert_toplevel_formula(ctx, v->data[i]);
45,243✔
6727
        i ++;
45,243✔
6728
      } while (i < n);
45,243✔
6729

6730
      // one round of propagation
6731
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
21,977✔
6732
        code = TRIVIALLY_UNSAT;
63✔
6733
        goto done;
63✔
6734
      }
6735
    }
6736

6737
  } else {
6738
    /*
6739
     * Exception: return from longjmp(ctx->env, code);
6740
     */
6741
    ivector_reset(&ctx->aux_vector);
380✔
6742
    reset_istack(&ctx->istack);
380✔
6743
    reset_objstack(&ctx->ostack);
380✔
6744
    int_queue_reset(&ctx->queue);
380✔
6745
    context_free_subst(ctx);
380✔
6746
    context_free_marks(ctx);
380✔
6747
  }
6748

6749
 done:
74,433✔
6750
  return code;
74,433✔
6751
}
6752

6753
/*
6754
 * Assert all formulas f[0] ... f[n-1]
6755
 * The context status must be IDLE.
6756
 *
6757
 * Return code:
6758
 * - TRIVIALLY_UNSAT means that an inconsistency is detected
6759
 *   (in that case the context status is set to UNSAT)
6760
 * - CTX_NO_ERROR means no internalization error and status not
6761
 *   determined
6762
 * - otherwise, the code is negative to report an error.
6763
 */
6764
int32_t _o_assert_formulas(context_t *ctx, uint32_t n, const term_t *f) {
71,899✔
6765
  int32_t code;
6766

6767
  assert(ctx->arch == CTX_ARCH_AUTO_IDL ||
6768
         ctx->arch == CTX_ARCH_AUTO_RDL ||
6769
         smt_status(ctx->core) == YICES_STATUS_IDLE);
6770
  assert(!context_quant_enabled(ctx));
6771

6772
  code = context_process_assertions(ctx, n, f);
71,899✔
6773
  if (code == TRIVIALLY_UNSAT) {
71,899✔
6774
    if (ctx->arch == CTX_ARCH_AUTO_IDL || ctx->arch == CTX_ARCH_AUTO_RDL) {
578✔
6775
      // cleanup: reset arch/config to 'no theory'
6776
      assert(ctx->arith_solver == NULL && ctx->bv_solver == NULL && ctx->fun_solver == NULL &&
6777
             ctx->mode == CTX_MODE_ONECHECK);
6778
      ctx->arch = CTX_ARCH_NOSOLVERS;
1✔
6779
      ctx->theories = 0;
1✔
6780
      ctx->options = 0;
1✔
6781
    }
6782

6783
    if( smt_status(ctx->core) != YICES_STATUS_UNSAT) {
578✔
6784
      // force UNSAT in the core
6785
      add_empty_clause(ctx->core);
361✔
6786
      ctx->core->status = YICES_STATUS_UNSAT;
361✔
6787
    }
6788
  }
6789

6790
  return code;
71,899✔
6791
}
6792

6793
/*
6794
 * Assert all formulas f[0] ... f[n-1] during quantifier instantiation
6795
 * The context status must be SEARCHING.
6796
 *
6797
 * Return code:
6798
 * - TRIVIALLY_UNSAT means that an inconsistency is detected
6799
 *   (in that case the context status is set to UNSAT)
6800
 * - CTX_NO_ERROR means no internalization error and status not
6801
 *   determined
6802
 * - otherwise, the code is negative to report an error.
6803
 */
6804
int32_t quant_assert_formulas(context_t *ctx, uint32_t n, const term_t *f) {
2,534✔
6805
  int32_t code;
6806

6807
  assert(context_quant_enabled(ctx));
6808
  assert(smt_status(ctx->core) == YICES_STATUS_SEARCHING);
6809

6810
  code = context_process_assertions(ctx, n, f);
2,534✔
6811
  if (code == TRIVIALLY_UNSAT) {
2,534✔
6812
    if (ctx->arch == CTX_ARCH_AUTO_IDL || ctx->arch == CTX_ARCH_AUTO_RDL) {
1✔
6813
      // cleanup: reset arch/config to 'no theory'
6814
      assert(ctx->arith_solver == NULL && ctx->bv_solver == NULL && ctx->fun_solver == NULL &&
6815
      ctx->mode == CTX_MODE_ONECHECK);
6816
      ctx->arch = CTX_ARCH_NOSOLVERS;
×
6817
      ctx->theories = 0;
×
6818
      ctx->options = 0;
×
6819
    }
6820

6821
    if( smt_status(ctx->core) != YICES_STATUS_UNSAT) {
1✔
6822
      // force UNSAT in the core
6823
      add_empty_clause(ctx->core);
1✔
6824
      ctx->core->status = YICES_STATUS_UNSAT;
1✔
6825
    }
6826
  }
6827

6828
  return code;
2,534✔
6829
}
6830

6831
int32_t assert_formulas(context_t *ctx, uint32_t n, const term_t *f) {
18,466✔
6832
  MT_PROTECT(int32_t, __yices_globals.lock, _o_assert_formulas(ctx, n, f));
18,466✔
6833
}
6834

6835

6836

6837

6838
/*
6839
 * Assert a boolean formula f.
6840
 *
6841
 * The context status must be IDLE.
6842
 *
6843
 * Return code:
6844
 * - TRIVIALLY_UNSAT means that an inconsistency is detected
6845
 *   (in that case the context status is set to UNSAT)
6846
 * - CTX_NO_ERROR means no internalization error and status not
6847
 *   determined
6848
 * - otherwise, the code is negative. The assertion could
6849
 *   not be processed.
6850
 */
6851
int32_t _o_assert_formula(context_t *ctx, term_t f) {
53,433✔
6852
  return _o_assert_formulas(ctx, 1, &f);
53,433✔
6853
}
6854

6855
int32_t assert_formula(context_t *ctx, term_t f) {
49,218✔
6856
  MT_PROTECT(int32_t, __yices_globals.lock, _o_assert_formula(ctx, f));
49,218✔
6857
}
6858

6859

6860
/*
6861
 * Convert boolean term t to a literal l in context ctx
6862
 * - t must be a boolean term
6863
 * - return a negative code if there's an error
6864
 * - return a literal (l >= 0) otherwise.
6865
 */
6866
int32_t context_internalize(context_t *ctx, term_t t) {
87,574✔
6867
  int code;
6868
  literal_t l;
6869

6870
  ivector_reset(&ctx->top_eqs);
87,574✔
6871
  ivector_reset(&ctx->top_atoms);
87,574✔
6872
  ivector_reset(&ctx->top_formulas);
87,574✔
6873
  ivector_reset(&ctx->top_interns);
87,574✔
6874
  ivector_reset(&ctx->subst_eqs);
87,574✔
6875
  ivector_reset(&ctx->aux_eqs);
87,574✔
6876

6877
  if (ctx->arch != CTX_ARCH_MCSAT && context_has_egraph(ctx) && !ctx->mcsat_supplement_active) {
87,574✔
6878
    if (context_assertions_need_mcsat_supplement(ctx, 1, &t)) {
108✔
NEW
6879
      code = context_enable_mcsat_supplement(ctx);
×
NEW
6880
      if (code < 0) {
×
NEW
6881
        return code;
×
6882
      }
6883
    }
6884
  }
6885

6886
  code = setjmp(ctx->env);
87,574✔
6887
  if (code == 0) {
87,574✔
6888
    // we must call internalization start first
6889
    if (!context_quant_enabled(ctx)) {
87,574✔
6890
      // TBD: make sure this is correct
6891
      internalization_start(ctx->core);
87,470✔
6892
    }
6893
    l = internalize_to_literal(ctx, t);
87,574✔
6894
  } else {
6895
    assert(code < 0);
6896
    /*
6897
     * Clean up
6898
     */
6899
    ivector_reset(&ctx->aux_vector);
×
6900
    reset_istack(&ctx->istack);
×
6901
    int_queue_reset(&ctx->queue);
×
6902
    context_free_subst(ctx);
×
6903
    context_free_marks(ctx);
×
6904
    l = code;
×
6905
  }
6906

6907
  return l;
87,574✔
6908
}
6909

6910

6911
/*
6912
 * Build an assumption for Boolean term t:
6913
 * - this converts t to a literal l in context ctx
6914
 *   then create an indicator variable x in the core
6915
 *   and add the clause (x => l) in the core.
6916
 * - return a negative code if t can't be internalized
6917
 * - return the literal x otherwise (where x>=0).
6918
 */
6919
int32_t context_add_assumption(context_t *ctx, term_t t) {
87,470✔
6920
  int32_t l, x;
6921

6922
  // check if we already have an assumption literal for t
6923
  x = assumption_literal_for_term(&ctx->assumptions, t);
87,470✔
6924
  if (x < 0) {
87,470✔
6925
    l = context_internalize(ctx, t);
87,470✔
6926
    if (l < 0) return l; // error code
87,470✔
6927

6928
    x = pos_lit(create_boolean_variable(ctx->core));
87,470✔
6929
    add_binary_clause(ctx->core, not(x), l); // clause (x implies l)
87,470✔
6930

6931
    assumption_stack_add(&ctx->assumptions, t, x);
87,470✔
6932
  }
6933

6934
  return x;
87,470✔
6935
}
6936

6937

6938

6939
/*
6940
 * PROVISIONAL: FOR TESTING/DEBUGGING
6941
 */
6942

6943
/*
6944
 * Preprocess formula f or array of formulas f[0 ... n-1]
6945
 * - this does flattening + build substitutions
6946
 * - return code: as in assert_formulas
6947
 * - the result is stored in the internal vectors
6948
 *     ctx->top_interns
6949
 *     ctx->top_eqs
6950
 *     ctx->top_atoms
6951
 *     ctx->top_formulas
6952
 *   + ctx->intern stores substitutions
6953
 */
6954
int32_t context_process_formulas(context_t *ctx, uint32_t n, term_t *f) {
×
6955
  uint32_t i;
6956
  int code;
6957

6958
  ivector_reset(&ctx->top_eqs);
×
6959
  ivector_reset(&ctx->top_atoms);
×
6960
  ivector_reset(&ctx->top_formulas);
×
6961
  ivector_reset(&ctx->top_interns);
×
6962
  ivector_reset(&ctx->subst_eqs);
×
6963
  ivector_reset(&ctx->aux_eqs);
×
6964
  ivector_reset(&ctx->aux_atoms);
×
6965

NEW
6966
  if (ctx->arch != CTX_ARCH_MCSAT && context_has_egraph(ctx)) {
×
NEW
6967
    if (context_assertions_need_mcsat_supplement(ctx, n, f)) {
×
NEW
6968
      code = context_enable_mcsat_supplement(ctx);
×
NEW
6969
      if (code < 0) {
×
NEW
6970
        return code;
×
6971
      }
6972
    }
6973
  }
6974

6975
  code = setjmp(ctx->env);
×
6976
  if (code == 0) {
×
6977
    // flatten
6978
    for (i=0; i<n; i++) {
×
6979
      flatten_assertion(ctx, f[i]);
×
6980
    }
6981

6982
    /*
6983
     * At this point, the assertions are stored into the vectors
6984
     * top_eqs, top_atoms, top_formulas, and top_interns
6985
     * - more top-level equalities may be in subst_eqs
6986
     * - ctx->intern stores the internalized terms and the variable
6987
     *   substitutions.
6988
     */
6989

6990
    switch (ctx->arch) {
×
6991
    case CTX_ARCH_EG:
×
6992
      /*
6993
       * UF problem: we must process subst_eqs last since the
6994
       * preprocessing may add new equalities in aux_eqs that may end
6995
       * up in subst_eqs after the call to process_aux_eqs.
6996
       */
6997
      if (context_breaksym_enabled(ctx)) {
×
6998
        break_uf_symmetries(ctx);
×
6999
      }
7000
      if (context_eq_abstraction_enabled(ctx)) {
×
7001
        analyze_uf(ctx);
×
7002
      }
7003
      if (ctx->aux_eqs.size > 0) {
×
7004
        process_aux_eqs(ctx);
×
7005
      }
7006
      if (ctx->subst_eqs.size > 0) {
×
7007
        context_process_candidate_subst(ctx);
×
7008
      }
7009
      break;
×
7010

7011
    case CTX_ARCH_AUTO_IDL:
×
7012
      /*
7013
       * For difference logic, we must process the subst_eqs first
7014
       * (otherwise analyze_diff_logic may give wrong results).
7015
       */
7016
      if (ctx->subst_eqs.size > 0) {
×
7017
        context_process_candidate_subst(ctx);
×
7018
      }
7019
      analyze_diff_logic(ctx, true);
×
7020
      create_auto_idl_solver(ctx);
×
7021
      break;
×
7022

7023
    case CTX_ARCH_AUTO_RDL:
×
7024
      /*
7025
       * Difference logic, we must process the subst_eqs first
7026
       */
7027
      if (ctx->subst_eqs.size > 0) {
×
7028
        context_process_candidate_subst(ctx);
×
7029
      }
7030
      analyze_diff_logic(ctx, false);
×
7031
      create_auto_rdl_solver(ctx);
×
7032
      break;
×
7033

7034
    case CTX_ARCH_SPLX:
×
7035
      /*
7036
       * Simplex, like EG, may add aux_atoms so we must process
7037
       * subst_eqs last here.
7038
       */
7039
      // more optional processing
7040
      if (context_cond_def_preprocessing_enabled(ctx)) {
×
7041
        process_conditional_definitions(ctx);
×
7042
        if (ctx->aux_eqs.size > 0) {
×
7043
          process_aux_eqs(ctx);
×
7044
        }
7045
        if (ctx->aux_atoms.size > 0) {
×
7046
          process_aux_atoms(ctx);
×
7047
        }
7048
      }
7049
      if (ctx->subst_eqs.size > 0) {
×
7050
        context_process_candidate_subst(ctx);
×
7051
      }
7052
      break;
×
7053

7054
    default:
×
7055
      /*
7056
       * Process the candidate variable substitutions if any
7057
       */
7058
      if (ctx->subst_eqs.size > 0) {
×
7059
        context_process_candidate_subst(ctx);
×
7060
      }
7061
      break;
×
7062
    }
7063

7064
    /*
7065
     * Sharing
7066
     */
7067
    context_build_sharing_data(ctx);
×
7068

7069
    code = CTX_NO_ERROR;
×
7070

7071
  } else {
7072
    /*
7073
     * Exception: return from longjmp(ctx->env, code);
7074
     */
7075
    ivector_reset(&ctx->aux_vector);
×
7076
    reset_istack(&ctx->istack);
×
7077
    int_queue_reset(&ctx->queue);
×
7078
    context_free_subst(ctx);
×
7079
    context_free_marks(ctx);
×
7080
  }
7081

7082
  return code;
×
7083
}
7084

7085
int32_t context_process_formula(context_t *ctx, term_t f) {
×
7086
  return context_process_formulas(ctx, 1, &f);
×
7087
}
7088

7089

7090

7091
/*
7092
 * The search function 'check_context' is defined in context_solver.c
7093
 */
7094

7095

7096
/*
7097
 * Interrupt the search.
7098
 */
7099
void context_stop_search(context_t *ctx) {
3✔
7100
  if (ctx->mcsat == NULL) {
3✔
7101
    stop_search(ctx->core);
3✔
7102
    if (context_has_simplex_solver(ctx)) {
3✔
7103
      simplex_stop_search(ctx->arith_solver);
3✔
7104
    }
7105
  } else {
7106
    mcsat_stop_search(ctx->mcsat);
×
7107
  }
7108
}
3✔
7109

7110

7111

7112
/*
7113
 * Cleanup: restore ctx to a good state after check_context
7114
 * is interrupted.
7115
 */
7116
void context_cleanup(context_t *ctx) {
1✔
7117
  // restore the state to IDLE, propagate to all solvers (via pop)
7118
  assert(context_supports_cleaninterrupt(ctx));
7119
  context_invalidate_unsat_core_cache(ctx);
1✔
7120
  if (ctx->mcsat == NULL) {
1✔
7121
    smt_cleanup(ctx->core);
1✔
7122
  } else {
7123
    mcsat_clear(ctx->mcsat);
×
7124
  }
7125
}
1✔
7126

7127

7128

7129
/*
7130
 * Clear: prepare for more assertions and checks
7131
 * - free the boolean assignment
7132
 * - reset the status to IDLE
7133
 */
7134
void context_clear(context_t *ctx) {
42,163✔
7135
  assert(context_supports_multichecks(ctx));
7136
  context_invalidate_unsat_core_cache(ctx);
42,163✔
7137
  if (ctx->mcsat == NULL) {
42,163✔
7138
    smt_clear(ctx->core);
41,812✔
7139
  } else {
7140
    mcsat_clear(ctx->mcsat);
351✔
7141
  }
7142
}
42,163✔
7143

7144

7145

7146
/*
7147
 * Clear_unsat: prepare for pop if the status is UNSAT
7148
 * - remove assumptions if any
7149
 *
7150
 * - if clean interrupt is enabled, then there may be a mismatch between
7151
 *   the context's base_level and the core base_level.
7152
 * - it's possible to have ctx->core.base_level = ctx->base_level + 1
7153
 * - this happens because start_search in smt_core does an internal smt_push
7154
 *   to allow the core to be restored to a clean state if search is interrupted.
7155
 * - if search is not interrupted and the search returns UNSAT, then we're
7156
 *   in a state with core base level = context base level + 1.
7157
 */
7158
void context_clear_unsat(context_t *ctx) {
613✔
7159
  context_invalidate_unsat_core_cache(ctx);
613✔
7160
  if (ctx->mcsat == NULL) {
613✔
7161
    smt_clear_unsat(ctx->core);
384✔
7162
    assert(smt_base_level(ctx->core) == ctx->base_level);
7163
  } else {
7164
    mcsat_clear(ctx->mcsat);
229✔
7165
  }
7166
}
613✔
7167

7168

7169

7170
/*
7171
 * Add the blocking clause to ctx
7172
 * - ctx->status must be either SAT or UNKNOWN
7173
 * - this collects all decision literals in the current truth assignment
7174
 *   (say l_1, ..., l_k) then clears the current assignment and adds the
7175
 *  clause ((not l_1) \/ ... \/ (not l_k)).
7176
 *
7177
 * Return code:
7178
 * - TRIVIALLY_UNSAT: means that the blocking clause is empty (i.e., k = 0)
7179
 *   (in that case, the context status is set to UNSAT)
7180
 * - CTX_NO_ERROR: means that the blocking clause is not empty (i.e., k > 0)
7181
 *   (In this case, the context status is set to IDLE)
7182
 */
7183
int32_t assert_blocking_clause(context_t *ctx) {
24,855✔
7184
  ivector_t *v;
7185
  uint32_t i, n;
7186
  int32_t code;
7187

7188
  assert(smt_status(ctx->core) == YICES_STATUS_SAT ||
7189
         smt_status(ctx->core) == YICES_STATUS_UNKNOWN);
7190

7191
  // get decision literals and build the blocking clause
7192
  v = &ctx->aux_vector;
24,855✔
7193
  assert(v->size == 0);
7194
  collect_decision_literals(ctx->core, v);
24,855✔
7195
  n = v->size;
24,855✔
7196
  for (i=0; i<n; i++) {
36,264✔
7197
    v->data[i] = not(v->data[i]);
11,409✔
7198
  }
7199

7200
  // prepare for the new assertion + notify solvers of a new assertion
7201
  context_clear(ctx);
24,855✔
7202
  internalization_start(ctx->core);
24,855✔
7203

7204
  // add the blocking clause
7205
  add_clause(ctx->core, n, v->data);
24,855✔
7206
  ivector_reset(v);
24,855✔
7207

7208
  // force UNSAT if n = 0
7209
  code = CTX_NO_ERROR;
24,855✔
7210
  if (n == 0) {
24,855✔
7211
    code = TRIVIALLY_UNSAT;
16,817✔
7212
    ctx->core->status = YICES_STATUS_UNSAT;
16,817✔
7213
  }
7214

7215
  assert(n == 0 || smt_status(ctx->core) == YICES_STATUS_IDLE);
7216

7217
  return code;
24,855✔
7218
}
7219

7220

7221

7222

7223
/********************************
7224
 *  GARBAGE COLLECTION SUPPORT  *
7225
 *******************************/
7226

7227
/*
7228
 * Marker for all terms present in the eq_map
7229
 * - aux = the relevant term table.
7230
 * - each record p stores <k0, k1, val> where k0 and k1 are both
7231
 *   terms in aux and val is a literal in the core
7232
 */
7233
static void ctx_mark_eq(void *aux, const pmap2_rec_t *p) {
×
7234
  term_table_set_gc_mark(aux, index_of(p->k0));
×
7235
  term_table_set_gc_mark(aux, index_of(p->k1));
×
7236
}
×
7237

7238

7239
/*
7240
 * Go through all data structures in ctx and mark all terms and types
7241
 * that they use.
7242
 */
7243
void context_gc_mark(context_t *ctx) {
6✔
7244
  if (ctx->egraph != NULL) {
6✔
7245
    egraph_gc_mark(ctx->egraph);
1✔
7246
  }
7247
  if (ctx->fun_solver != NULL) {
6✔
7248
    fun_solver_gc_mark(ctx->fun_solver);
1✔
7249
  }
7250

7251
  intern_tbl_gc_mark(&ctx->intern);
6✔
7252

7253
  // empty all the term vectors to be safe
7254
  ivector_reset(&ctx->top_eqs);
6✔
7255
  ivector_reset(&ctx->top_atoms);
6✔
7256
  ivector_reset(&ctx->top_formulas);
6✔
7257
  ivector_reset(&ctx->top_interns);
6✔
7258
  ivector_reset(&ctx->subst_eqs);
6✔
7259
  ivector_reset(&ctx->aux_eqs);
6✔
7260

7261
  if (ctx->eq_cache != NULL) {
6✔
7262
    pmap2_iterate(ctx->eq_cache, ctx->terms, ctx_mark_eq);
×
7263
  }
7264

7265
  if (ctx->unsat_core_cache != NULL) {
6✔
7266
    uint32_t i, n;
7267
    n = ctx->unsat_core_cache->size;
×
7268
    for (i=0; i<n; i++) {
×
7269
      term_table_set_gc_mark(ctx->terms, index_of(ctx->unsat_core_cache->data[i]));
×
7270
    }
7271
  }
7272

7273
  if (ctx->mcsat != NULL) {
6✔
7274
    mcsat_gc_mark(ctx->mcsat);
5✔
7275
  }
7276
  if (ctx->mcsat_supplement_active) {
6✔
NEW
7277
    mcsat_satellite_t *sat = context_mcsat_satellite(ctx);
×
NEW
7278
    if (sat != NULL) {
×
NEW
7279
      mcsat_satellite_gc_mark(sat);
×
7280
    }
7281
  }
7282
}
6✔
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