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

SRI-CSL / yices2 / 25367146742

05 May 2026 08:57AM UTC coverage: 66.842% (+0.2%) from 66.687%
25367146742

Pull #607

github

web-flow
Merge branch 'master' into context_delegates
Pull Request #607: QF_BV context delegates (#453): config/param selection, incremental state, assumptions, and delegate regressions

34 of 43 new or added lines in 3 files covered. (79.07%)

1137 existing lines in 6 files now uncovered.

83676 of 125184 relevant lines covered (66.84%)

1645504.39 hits per line

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

81.37
/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 "context/context.h"
26
#include "context/context_simplifier.h"
27
#include "context/context_utils.h"
28
#include "context/internalization_codes.h"
29
#include "context/ite_flattener.h"
30
#include "solvers/bv/bvsolver.h"
31
#include "solvers/floyd_warshall/idl_floyd_warshall.h"
32
#include "solvers/floyd_warshall/rdl_floyd_warshall.h"
33
#include "solvers/funs/fun_solver.h"
34
#include "solvers/quant/quant_solver.h"
35
#include "solvers/simplex/simplex.h"
36
#include "terms/poly_buffer_terms.h"
37
#include "terms/term_utils.h"
38
#include "utils/memalloc.h"
39

40
#include "mcsat/solver.h"
41
#include "mt/thread_macros.h"
42

43
#include "api/yices_globals.h"
44

45
#define TRACE 0
46

47
#if TRACE
48

49
#include <stdio.h>
50

51
#include "io/term_printer.h"
52
#include "solvers/cdcl/smt_core_printer.h"
53

54
#endif
55

56

57

58

59

60
/**********************
61
 *  INTERNALIZATION   *
62
 *********************/
63

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

76

77

78
/****************************************
79
 *  CONSTRUCTION OF EGRAPH OCCURRENCES  *
80
 ***************************************/
81

82
/*
83
 * Create a new egraph constant of the given type
84
 */
85
static eterm_t make_egraph_constant(context_t *ctx, type_t type, int32_t id) {
1,164✔
86
  assert(type_kind(ctx->types, type) == UNINTERPRETED_TYPE ||
87
         type_kind(ctx->types, type) == SCALAR_TYPE);
88
  return egraph_make_constant(ctx->egraph, type, id);
1,164✔
89
}
90

91

92
/*
93
 * Create a new egraph variable
94
 * - type = its type
95
 */
96
static eterm_t make_egraph_variable(context_t *ctx, type_t type) {
14,085✔
97
  eterm_t u;
98
  bvar_t v;
99

100
  if (type == bool_type(ctx->types)) {
14,085✔
101
    v = create_boolean_variable(ctx->core);
×
102
    u = egraph_bvar2term(ctx->egraph, v);
×
103
  } else {
104
    //    u = egraph_make_variable(ctx->egraph, type);
105
    // it's better to use skolem_term in case type is (tuple ...)
106
    u = egraph_skolem_term(ctx->egraph, type);
14,085✔
107
  }
108
  return u;
14,085✔
109
}
110

111

112
/*
113
 * Type of arithmetic variable x
114
 */
115
static type_t type_of_arithvar(context_t *ctx, thvar_t x) {
1,562✔
116
  type_t tau;
117

118
  tau = real_type(ctx->types);
1,562✔
119
  if (ctx->arith.arith_var_is_int(ctx->arith_solver, x)) {
1,562✔
120
    tau = int_type(ctx->types);
1,425✔
121
  }
122

123
  return tau;
1,562✔
124
}
125

126

127
/*
128
 * Convert arithmetic variable x to an egraph term
129
 */
130
static occ_t translate_arithvar_to_eterm(context_t *ctx, thvar_t x) {
1,571✔
131
  eterm_t u;
132
  type_t tau;
133

134
  u = ctx->arith.eterm_of_var(ctx->arith_solver, x);
1,571✔
135
  if (u == null_eterm) {
1,571✔
136
    tau = type_of_arithvar(ctx, x);
1,562✔
137
    u = egraph_thvar2term(ctx->egraph, x, tau);
1,562✔
138
  }
139

140
  return pos_occ(u);
1,571✔
141
}
142

143
/*
144
 * Convert bit-vector variable x to an egraph term
145
 * - tau = type of x
146
 */
147
static occ_t translate_bvvar_to_eterm(context_t *ctx, thvar_t x, type_t tau) {
3,693✔
148
  eterm_t u;
149

150
  u = ctx->bv.eterm_of_var(ctx->bv_solver, x);
3,693✔
151
  if (u == null_eterm) {
3,693✔
152
    u = egraph_thvar2term(ctx->egraph, x, tau);
3,672✔
153
  }
154

155
  return pos_occ(u);
3,693✔
156
}
157

158

159
/*
160
 * Convert variable x into an eterm internalization for t
161
 * - tau = type of t
162
 * - if x is mapped to an existing eterm u, return pos_occ(u)
163
 * - otherwise, create an egraph variable u and attach x to u
164
 *   then record the converse mapping [x --> u] in the relevant
165
 *   theory solver
166
 */
167
static occ_t translate_thvar_to_eterm(context_t *ctx, thvar_t x, type_t tau) {
3,348✔
168
  if (is_arithmetic_type(tau)) {
3,348✔
169
    return translate_arithvar_to_eterm(ctx, x);
619✔
170
  } else if (is_bv_type(ctx->types, tau)) {
2,729✔
171
    return translate_bvvar_to_eterm(ctx, x, tau);
2,729✔
172
  } else {
173
    longjmp(ctx->env, INTERNAL_ERROR);
×
174
  }
175
}
176

177

178
/*
179
 * Convert internalization code x for a term t into an egraph term
180
 * - t must be a root in the internalization table and must have
181
 *   positive polarity
182
 */
183
static occ_t translate_code_to_eterm(context_t *ctx, term_t t, int32_t x) {
64,982✔
184
  occ_t u;
185
  type_t tau;
186

187
  assert(is_pos_term(t) && intern_tbl_is_root(&ctx->intern, t) &&
188
         intern_tbl_map_of_root(&ctx->intern, t) == x);
189

190
  if (code_is_eterm(x)) {
64,982✔
191
    u = code2occ(x);
64,233✔
192
  } else {
193
    // x encodes a theory variable or a literal
194
    // convert that to an egraph term
195
    tau = type_of_root(ctx, t);
749✔
196
    switch (type_kind(ctx->types, tau)) {
749✔
197
    case BOOL_TYPE:
×
198
      u = egraph_literal2occ(ctx->egraph, code2literal(x));
×
199
      break;
×
200

201
    case INT_TYPE:
611✔
202
    case REAL_TYPE:
203
      u = translate_arithvar_to_eterm(ctx, code2thvar(x));
611✔
204
      break;
611✔
205

206
    case BITVECTOR_TYPE:
138✔
207
      u = translate_bvvar_to_eterm(ctx, code2thvar(x), tau);
138✔
208
      break;
138✔
209

210
    default:
×
211
      assert(false);
212
      longjmp(ctx->env, INTERNAL_ERROR);
×
213
    }
214

215
    // remap t to u
216
    intern_tbl_remap_root(&ctx->intern, t, occ2code(u));
749✔
217
  }
218

219
  return u;
64,982✔
220
}
221

222

223
/*
224
 * Internalization error for term t
225
 * - t can't be processed because there's no egraph
226
 * - the error code depends on t's type
227
 */
228
static int32_t uf_error_code(context_t *ctx, term_t t) {
×
229
  int32_t code;
230

231
  assert(! context_has_egraph(ctx));
232

233
  switch (term_type_kind(ctx->terms, t)) {
×
234
  case UNINTERPRETED_TYPE:
×
235
    code = UTYPE_NOT_SUPPORTED;
×
236
    break;
×
237

238
  case SCALAR_TYPE:
×
239
    code = SCALAR_NOT_SUPPORTED;
×
240
    break;
×
241

242
  case FUNCTION_TYPE:
×
243
    code = UF_NOT_SUPPORTED;
×
244
    break;
×
245

246
  case TUPLE_TYPE:
×
247
    code = TUPLE_NOT_SUPPORTED;
×
248
    break;
×
249

250
  default:
×
251
    assert(false);
252
    code = INTERNAL_ERROR;
×
253
    break;
×
254
  }
255

256
  return code;
×
257
}
258

259

260
/*
261
 * Utility to filter out high-order terms:
262
 * - check whether any term in a[0 ... n-1] has function type.
263
 * - if so throw an exception (via lonjmp) if the context does not include
264
 *   the array solver.
265
 */
266
static void check_high_order_support(context_t *ctx, const term_t *a, uint32_t n) {
18,026✔
267
  uint32_t i;
268

269
  if (! context_has_fun_solver(ctx)) {
18,026✔
270
    for (i=0; i<n; i++) {
30,058✔
271
      if (is_function_term(ctx->terms, a[i])) {
17,192✔
272
        longjmp(ctx->env, HIGH_ORDER_FUN_NOT_SUPPORTED);
3✔
273
      }
274
    }
275
  }
276
}
18,023✔
277

278

279
/***********************************************
280
 *  CONVERSION OF COMPOSITES TO EGRAPH TERMS   *
281
 **********************************************/
282

283
/*
284
 * Map apply term to an eterm
285
 * - tau = type of that term
286
 */
287
static occ_t map_apply_to_eterm(context_t *ctx, composite_term_t *app, type_t tau) {
9,685✔
288
  eterm_t u;
289
  occ_t *a;
290
  uint32_t i, n;
291

292
  assert(app->arity > 0);
293
  n = app->arity;
9,685✔
294

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

297
  a = alloc_istack_array(&ctx->istack, n);
9,685✔
298
  for (i=0; i<n; i++) {
34,029✔
299
    a[i] = internalize_to_eterm(ctx, app->arg[i]);
24,344✔
300
  }
301

302
  // a[0] = function
303
  // a[1 ... n-1] are the arguments
304
  u = egraph_make_apply(ctx->egraph, a[0], n-1, a+1, tau);
9,685✔
305
  free_istack_array(&ctx->istack, a);
9,685✔
306

307
  //  add_type_constraints(ctx, pos_occ(u), tau);
308

309
  return pos_occ(u);
9,685✔
310
}
311

312

313
/*
314
 * Build a tuple of same type as t then assert that it's equal to u1
315
 * - t must be a root in the internalization table
316
 * - u1 must be equal to t's internalization (as stored in intern_table)
317
 * This is the skolemization of (exist (x1...x_n) u1 == (tuple x1 ... x_n))
318
 *
319
 * - return the eterm u := (tuple x1 ... x_n)
320
 */
321
static eterm_t skolem_tuple(context_t *ctx, term_t t, occ_t u1) {
×
322
  type_t tau;
323
  eterm_t u;
324

325
  assert(intern_tbl_is_root(&ctx->intern, t) && is_pos_term(t) &&
326
         intern_tbl_map_of_root(&ctx->intern, t) == occ2code(u1));
327

328
  tau = intern_tbl_type_of_root(&ctx->intern, t);
×
329
  u = egraph_skolem_term(ctx->egraph, tau);
×
330
  egraph_assert_eq_axiom(ctx->egraph, u1, pos_occ(u));
×
331

332
  return u;
×
333
}
334

335

336
/*
337
 * Convert (select i t) to an egraph term
338
 * - tau must be the type of that term (should not be bool)
339
 * - if a new eterm u is created, attach a theory variable to it
340
 */
341
static occ_t map_select_to_eterm(context_t *ctx, select_term_t *s, type_t tau) {
245✔
342
  occ_t u1;
343
  eterm_t tuple;
344
  composite_t *tp;
345

346
  u1 = internalize_to_eterm(ctx, s->arg);
245✔
347
  tuple = egraph_get_tuple_in_class(ctx->egraph, term_of_occ(u1));
245✔
348
  if (tuple == null_eterm) {
245✔
349
    tuple = skolem_tuple(ctx, s->arg, u1);
×
350
  }
351

352
  tp = egraph_term_body(ctx->egraph, tuple);
245✔
353
  assert(composite_body(tp) && tp != NULL && composite_kind(tp) == COMPOSITE_TUPLE);
354

355
  return tp->child[s->idx];
245✔
356
}
357

358

359
/*
360
 * Convert a conditional expression to an egraph term
361
 * - c = conditional descriptor
362
 * - tau = type of c
363
 */
364
static occ_t map_conditional_to_eterm(context_t *ctx, conditional_t *c, type_t tau) {
12✔
365
  literal_t *a;
366
  occ_t u, v;
367
  uint32_t i, n;
368
  literal_t l;
369
  bool all_false;
370
  term_t t;
371

372
#if 0
373
  printf("---> conditional to eterm\n");
374
#endif
375

376
  t = simplify_conditional(ctx, c);
12✔
377
  if (t != NULL_TERM) {
12✔
378
    return internalize_to_eterm(ctx, t);
4✔
379
  }
380

381
  n = c->nconds;
8✔
382
  a = alloc_istack_array(&ctx->istack, n + 1);
8✔
383

384
  all_false = true;
8✔
385
  u = null_occurrence;
8✔
386

387
  for (i=0; i<n; i++) {
24✔
388
    a[i] = internalize_to_literal(ctx, c->pair[i].cond);
16✔
389
    if (a[i] == true_literal) {
16✔
390
      /*
391
       * a[0] ... a[i-1] are all reducible to false
392
       * but we can't assume that a[0] ... a[i-1] are all false_literals
393
       * since we don't know how the theory solver internalizes the
394
       * conditions.
395
       */
396
      v = internalize_to_eterm(ctx, c->pair[i].val);
×
397
      if (all_false) {
×
398
        // all previous conditions a[0 ... i-1] are false
399
        assert(u == null_occurrence);
400
        u = v;
×
401
      } else {
402
        // we assert (u == v) as a top-level equality
403
        egraph_assert_eq_axiom(ctx->egraph, u, v);
×
404
      }
405
      goto done;
×
406
    }
407
    if (a[i] != false_literal) {
16✔
408
      if (all_false) {
13✔
409
        assert(u == null_occurrence);
410
        u = pos_occ(make_egraph_variable(ctx, tau));
7✔
411
        all_false = false;
7✔
412
      }
413
      // one clause for a[i] => (u = v[i])
414
      v = internalize_to_eterm(ctx, c->pair[i].val);
13✔
415
      l = egraph_make_eq(ctx->egraph, u, v);
13✔
416
      add_binary_clause(ctx->core, not(a[i]), l);
13✔
417
    }
418
  }
419

420
  if (all_false) {
8✔
421
    assert(u == null_occurrence);
422
    u = internalize_to_eterm(ctx, c->defval);
1✔
423
    goto done;
1✔
424
  }
425

426
  // clause for the default value
427
  assert(u != null_occurrence);
428
  v = internalize_to_eterm(ctx, c->defval);
7✔
429
  l = egraph_make_eq(ctx->egraph, u, v);
7✔
430
  a[n] = l;
7✔
431
  add_clause(ctx->core, n+1, a);
7✔
432

433
 done:
8✔
434
  free_istack_array(&ctx->istack, a);
8✔
435

436
  return u;
8✔
437
}
438

439

440
/*
441
 * Auxiliary function for flattening if-then-else
442
 * - v contains a conjunction of n literals: l0 /\ ... /\ l_n
443
 * - we something like (l0 /\ ... /\ l_n implies (x = y))
444
 *   (i.e., (not l0) \/ ... \/ (not l_n) \/ (x = y)
445
 * - this function negates all the literals in place
446
 */
447
static void ite_prepare_antecedents(ivector_t *v) {
8,348✔
448
  uint32_t i, n;
449

450
  n = v->size;
8,348✔
451
  for (i=0; i<n; i++) {
20,408✔
452
    v->data[i] = not(v->data[i]);
12,060✔
453
  }
454
}
8,348✔
455

456

457
/*
458
 * Convert nested if-then-else to  an egraph term
459
 * - ite = term of the form (ite c1 t1 t2)
460
 * - c = internalization of c1
461
 * - tau = type of the term (ite c1 t1 t2)
462
 */
463
static occ_t flatten_ite_to_eterm(context_t *ctx, composite_term_t *ite, literal_t c, type_t tau) {
1,168✔
464
  ite_flattener_t *flattener;
465
  ivector_t *buffer;
466
  term_t x;
467
  occ_t u, v;
468
  literal_t l;
469

470
  u = pos_occ(make_egraph_variable(ctx, tau));
1,168✔
471

472
  flattener = objstack_alloc(&ctx->ostack, sizeof(ite_flattener_t), (cleaner_t) delete_ite_flattener);
1,168✔
473
  init_ite_flattener(flattener);
1,168✔
474

475
  ite_flattener_push(flattener, ite, c);
1,168✔
476

477
  while (ite_flattener_is_nonempty(flattener)) {
4,210✔
478
    if (ite_flattener_last_lit_false(flattener)) {
3,042✔
479
      // dead branch
480
      ite_flattener_next_branch(flattener);
6✔
481
      continue;
6✔
482
    }
483
    assert(ite_flattener_branch_is_live(flattener));
484

485
    x = ite_flattener_leaf(flattener);
3,036✔
486
    x = intern_tbl_get_root(&ctx->intern, x);
3,036✔
487

488
    /*
489
     * x is the current leaf.
490
     * If it's (ite ...) then we can expand the tree by pushing x.
491
     *
492
     * Heuristic: we don't do it if x is a shared term or if it's
493
     * already internalized.
494
     * - we also need a cutoff since the number of branches grows
495
     *   exponentially.
496
     */
497
    if (is_pos_term(x) &&
6,072✔
498
        is_ite_term(ctx->terms, x) &&
3,036✔
499
        !intern_tbl_root_is_mapped(&ctx->intern, x) &&
2,473✔
500
        term_is_not_shared(&ctx->sharing, x)) {
774✔
501
      /*
502
       * x is of the form (ite c a b) and not internalized already,
503
       * we push (ite c a b) on the flattener.
504
       */
505
      ite = ite_term_desc(ctx->terms, x);
353✔
506
      assert(ite->arity == 3);
507
      c = internalize_to_literal(ctx, ite->arg[0]);
353✔
508
      ite_flattener_push(flattener, ite, c);
353✔
509
    } else {
510
      /*
511
       * Add the clause [branch conditions => x = u]
512
       */
513
      v = internalize_to_eterm(ctx, x);
2,683✔
514
      l = egraph_make_eq(ctx->egraph, u, v);
2,683✔
515

516
      buffer = &ctx->aux_vector;
2,683✔
517
      assert(buffer->size == 0);
518
      ite_flattener_get_clause(flattener, buffer);
2,683✔
519
      ite_prepare_antecedents(buffer);
2,683✔
520
      ivector_push(buffer, l);
2,683✔
521
      add_clause(ctx->core, buffer->size, buffer->data);
2,683✔
522
      ivector_reset(buffer);
2,683✔
523

524
      ite_flattener_next_branch(flattener);
2,683✔
525
    }
526
  }
527

528
  //  delete_ite_flattener(&flattener);
529
  objstack_pop(&ctx->ostack);
1,168✔
530

531
  return u;
1,168✔
532
}
533

534

535
/*
536
 * Convert (ite c t1 t2) to an egraph term
537
 * - tau = type of (ite c t1 t2)
538
 */
539
static occ_t map_ite_to_eterm(context_t *ctx, composite_term_t *ite, type_t tau) {
2,168✔
540
  conditional_t *d;
541
  eterm_t u;
542
  occ_t u1, u2, u3;
543
  literal_t c, l1, l2;
544

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

549
  d = context_make_conditional(ctx, ite);
2,168✔
550
  if (d != NULL) {
2,168✔
551
    u1 = map_conditional_to_eterm(ctx, d, tau);
12✔
552
    context_free_conditional(ctx, d);
12✔
553
    return u1;
12✔
554
  }
555

556
  c = internalize_to_literal(ctx, ite->arg[0]);
2,156✔
557
  if (c == true_literal) {
2,156✔
558
    return internalize_to_eterm(ctx, ite->arg[1]);
110✔
559
  }
560
  if (c == false_literal) {
2,046✔
561
    return internalize_to_eterm(ctx, ite->arg[2]);
15✔
562
  }
563

564
  if (context_ite_flattening_enabled(ctx)) {
2,031✔
565
    return flatten_ite_to_eterm(ctx, ite, c, tau);
1,168✔
566
  }
567

568
  u2 = internalize_to_eterm(ctx, ite->arg[1]);
863✔
569
  u3 = internalize_to_eterm(ctx, ite->arg[2]);
863✔
570

571
  if (context_keep_ite_enabled(ctx)) {
863✔
572
    // build the if-then-else in the egraph
573
    u1 = egraph_literal2occ(ctx->egraph, c);
2✔
574
    u = egraph_make_ite(ctx->egraph, u1, u2, u3, tau);
2✔
575
  } else {
576
    // eliminate the if-then-else
577
    u = make_egraph_variable(ctx, tau);
861✔
578
    l1 = egraph_make_eq(ctx->egraph, pos_occ(u), u2);
861✔
579
    l2 = egraph_make_eq(ctx->egraph, pos_occ(u), u3);
861✔
580

581
    assert_ite(&ctx->gate_manager, c, l1, l2, true);
861✔
582
  }
583

584
  return pos_occ(u);
863✔
585
}
586

587

588

589
/*
590
 * Convert (update f t_1 ... t_n v) to a term
591
 * - tau = type of that term
592
 */
593
static occ_t map_update_to_eterm(context_t *ctx, composite_term_t *update, type_t tau) {
11,470✔
594
  eterm_t u;
595
  occ_t *a;
596
  uint32_t i, n;
597

598
  assert(update->arity > 2);
599

600
  n = update->arity;
11,470✔
601
  a = alloc_istack_array(&ctx->istack, n);
11,470✔
602
  for (i=0; i<n; i++) {
45,880✔
603
    a[i] = internalize_to_eterm(ctx, update->arg[i]);
34,410✔
604
  }
605

606
  // a[0]: function f
607
  // a[1] ... a[n-2]: t_1 .. t_{n-2}
608
  // a[n-1]: new value v
609
  u = egraph_make_update(ctx->egraph, a[0], n-2, a+1, a[n-1], tau);
11,470✔
610

611
  free_istack_array(&ctx->istack, a);
11,470✔
612

613
  return pos_occ(u);
11,470✔
614
}
615

616

617

618
/*
619
 * Convert (tuple t_1 ... t_n) to a term
620
 * - tau = type of the tuple
621
 */
622
static occ_t map_tuple_to_eterm(context_t *ctx, composite_term_t *tuple, type_t tau) {
190✔
623
  eterm_t u;
624
  occ_t *a;
625
  uint32_t i, n;
626

627
  n = tuple->arity;
190✔
628

629
  check_high_order_support(ctx, tuple->arg, n);
190✔
630

631
  a = alloc_istack_array(&ctx->istack, n);
190✔
632
  for (i=0; i<n; i++) {
560✔
633
    a[i] = internalize_to_eterm(ctx, tuple->arg[i]);
370✔
634
  }
635

636
  u = egraph_make_tuple(ctx->egraph, n, a, tau);
190✔
637
  free_istack_array(&ctx->istack, a);
190✔
638

639
  return pos_occ(u);
190✔
640
}
641

642

643
/*
644
 * Convert arithmetic and bitvector constants to eterm
645
 * - check whether the relevant solver exists first
646
 * - then map the constant to a solver variable x
647
 *   and convert x to an egraph occurrence
648
 */
649
static occ_t map_arith_constant_to_eterm(context_t *ctx, rational_t *q) {
339✔
650
  thvar_t x;
651

652
  if (! context_has_arith_solver(ctx)) {
339✔
653
    longjmp(ctx->env, ARITH_NOT_SUPPORTED);
×
654
  }
655

656
  x = ctx->arith.create_const(ctx->arith_solver, q);
339✔
657
  return translate_arithvar_to_eterm(ctx, x);
339✔
658
}
659

660
static occ_t map_bvconst64_to_eterm(context_t *ctx, bvconst64_term_t *c) {
808✔
661
  thvar_t x;
662
  type_t tau;
663

664
  if (! context_has_bv_solver(ctx)) {
808✔
665
    longjmp(ctx->env, BV_NOT_SUPPORTED);
×
666
  }
667

668
  x = ctx->bv.create_const64(ctx->bv_solver, c);
808✔
669
  tau = bv_type(ctx->types, c->bitsize);
808✔
670

671
  return translate_bvvar_to_eterm(ctx, x, tau);
808✔
672
}
673

674
static occ_t map_bvconst_to_eterm(context_t *ctx, bvconst_term_t *c) {
18✔
675
  thvar_t x;
676
  type_t tau;
677

678
  if (! context_has_bv_solver(ctx)) {
18✔
679
    longjmp(ctx->env, BV_NOT_SUPPORTED);
×
680
  }
681

682
  x = ctx->bv.create_const(ctx->bv_solver, c);
18✔
683
  tau = bv_type(ctx->types, c->bitsize);
18✔
684

685
  return translate_bvvar_to_eterm(ctx, x, tau);
18✔
686
}
687

688

689

690
/***************************************
691
 *  AXIOMS FOR DIV/MOD/FLOOR/CEIL/ABS  *
692
 **************************************/
693

694
/*
695
 * Auxiliary function: p and map to represent (x - y)
696
 * - in polynomial p, only the coefficients are relevant
697
 * - map[0] stores x and map[1] stores y
698
 * - both p map must be large enough (at least 2 elements)
699
 */
700
static void context_store_diff_poly(polynomial_t *p, thvar_t *map, thvar_t x, thvar_t y) {
×
701
  p->nterms = 2;
×
702
  p->mono[0].var = 1;
×
703
  q_set_one(&p->mono[0].coeff);       // coeff of x = 1
×
704
  p->mono[1].var = 2;
×
705
  q_set_minus_one(&p->mono[1].coeff); // coeff of y = -1
×
706
  p->mono[2].var = max_idx; // end marker
×
707

708
  map[0] = x;
×
709
  map[1] = y;
×
710
}
×
711

712

713
/*
714
 * Same thing for the polynomial (x - y - 1)
715
 */
716
static void context_store_diff_minus_one_poly(polynomial_t *p, thvar_t *map, thvar_t x, thvar_t y) {
×
717
  p->nterms = 3;
×
718
  p->mono[0].var = const_idx;
×
719
  q_set_minus_one(&p->mono[0].coeff);  // constant = -1
×
720
  p->mono[1].var = 1;
×
721
  q_set_one(&p->mono[1].coeff);        // coeff of x = 1
×
722
  p->mono[2].var = 2;
×
723
  q_set_minus_one(&p->mono[2].coeff);  // coeff of y = -1
×
724
  p->mono[3].var = max_idx;
×
725

726
  map[0] = null_thvar; // constant
×
727
  map[1] = x;
×
728
  map[2] = y;
×
729
}
×
730

731

732
/*
733
 * Same thing for the polynomial (x + y)
734
 */
735
static void context_store_sum_poly(polynomial_t *p, thvar_t *map, thvar_t x, thvar_t y) {
4✔
736
  p->nterms = 2;
4✔
737
  p->mono[0].var = 1;
4✔
738
  q_set_one(&p->mono[0].coeff); // coeff of x = 1
4✔
739
  p->mono[1].var = 2;
4✔
740
  q_set_one(&p->mono[1].coeff); // coeff of y = 1
4✔
741
  p->mono[2].var = max_idx;
4✔
742

743
  map[0] = x;
4✔
744
  map[1] = y;
4✔
745
}
4✔
746

747

748
/*
749
 * The lower bound on y = (div x k)  is (k * y <= x) or (x - k * y >= 0)
750
 * We store the polynomial x - k * y
751
 */
752
static void context_store_div_lower_bound(polynomial_t *p, thvar_t *map, thvar_t x, thvar_t y, const rational_t *k) {
21✔
753
  p->nterms = 2;
21✔
754
  p->mono[0].var = 1;
21✔
755
  q_set_one(&p->mono[0].coeff);    // coeff of x = 1
21✔
756
  p->mono[1].var = 2;
21✔
757
  q_set_neg(&p->mono[1].coeff, k); // coeff of y = -k
21✔
758
  p->mono[2].var = max_idx;
21✔
759

760
  map[0] = x;
21✔
761
  map[1] = y;
21✔
762
}
21✔
763

764

765
/*
766
 * For converting (divides k x), we use (divides k x) <=> (x <= k * (div x k))
767
 * or (k * y - x >= 0) for y = (div x k).
768
 * We store the polynomial - x + k * y.
769
 */
770
static void context_store_divides_constraint(polynomial_t *p, thvar_t *map, thvar_t x, thvar_t y, const rational_t *k) {
8✔
771
  p->nterms = 2;
8✔
772
  p->mono[0].var = 1;
8✔
773
  q_set_minus_one(&p->mono[0].coeff);  // coeff of x = -1
8✔
774
  p->mono[1].var = 2;
8✔
775
  q_set(&p->mono[1].coeff, k);         // coeff of y = k
8✔
776
  p->mono[2].var = max_idx;
8✔
777

778
  map[0] = x;
8✔
779
  map[1] = y;
8✔
780
}
8✔
781

782
/*
783
 * Upper bound on y = (div x k) when both x and y are integer:
784
 * We have x <= k * y + |k| - 1 or (-x + k y + |k| - 1 >= 0).
785
 *
786
 * We store the polynomial - x + k y + |k| - 1
787
 *
788
 * NOTE: we don't normalize the constant (|k| - 1) to zero if |k| = 1.
789
 * This is safe as the simplex solver does not care.
790
 */
791
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✔
792
  p->nterms = 3;
20✔
793
  p->mono[0].var = const_idx;
20✔
794
  q_set_abs(&p->mono[0].coeff, k);
20✔
795
  q_sub_one(&p->mono[0].coeff);        // constant term = |k| - 1
20✔
796
  p->mono[1].var = 1;
20✔
797
  q_set_minus_one(&p->mono[1].coeff);  // coeff of x = -1
20✔
798
  p->mono[2].var = 2;
20✔
799
  q_set(&p->mono[2].coeff, k);         // coeff of y = k
20✔
800
  p->mono[3].var = max_idx;
20✔
801

802
  map[0] = null_thvar;
20✔
803
  map[1] = x;
20✔
804
  map[2] = y;
20✔
805
}
20✔
806

807
/*
808
 * Upper bound on y = (div x k) when x or k is not an integer.
809
 * We have x < k * y + |k| or x - k*y - |k| < 0 or (not (x - k*y - |k| >= 0))
810
 *
811
 * We store the polynomial x - ky - |k|
812
 */
813
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✔
814
  p->nterms = 3;
1✔
815
  p->mono[0].var = const_idx;
1✔
816
  q_set_abs(&p->mono[0].coeff, k);
1✔
817
  q_neg(&p->mono[0].coeff);           // constant term: -|k|
1✔
818
  p->mono[1].var = 1;
1✔
819
  q_set_one(&p->mono[1].coeff);       // coeff of x = +1
1✔
820
  p->mono[2].var = 2;
1✔
821
  q_set_neg(&p->mono[2].coeff, k);    // coeff of y = -k
1✔
822
  p->mono[3].var = max_idx;
1✔
823

824
  map[0] = null_thvar;
1✔
825
  map[1] = x;
1✔
826
  map[2] = y;
1✔
827
}
1✔
828

829

830
/*
831
 * Polynomial x - y + k d (for asserting y = k * (div y k) + (mod y k)
832
 * - d is assumed to be (div y k)
833
 * - x is assumed to be (mod y k)
834
 */
835
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✔
836
  p->nterms = 3;
11✔
837
  p->mono[0].var = 1;
11✔
838
  q_set_one(&p->mono[0].coeff);       // coefficient of x = 1
11✔
839
  p->mono[1].var = 2;
11✔
840
  q_set_minus_one(&p->mono[1].coeff); // coefficient of y = -1
11✔
841
  p->mono[2].var = 3;
11✔
842
  q_set(&p->mono[2].coeff, k);        // coefficient of d = k
11✔
843
  p->mono[3].var = max_idx;
11✔
844

845
  map[0] = x;
11✔
846
  map[1] = y;
11✔
847
  map[2] = d;
11✔
848
}
11✔
849

850

851
/*
852
 * Bound on x = (mod y k) assuming x and k are integer:
853
 * - the bound is x <= |k| - 1 (i.e., |k| - 1 - x >= 0)
854
 *   so we construct |k| - 1 - x
855
 */
856
static void context_store_integer_mod_bound(polynomial_t *p, thvar_t *map, thvar_t x, const rational_t *k) {
10✔
857
  p->nterms = 2;
10✔
858
  p->mono[0].var = const_idx;
10✔
859
  q_set_abs(&p->mono[0].coeff, k);
10✔
860
  q_sub_one(&p->mono[0].coeff);        // constant = |k| - 1
10✔
861
  p->mono[1].var = 1;
10✔
862
  q_set_minus_one(&p->mono[1].coeff);  // coeff of x = -1
10✔
863
  p->mono[2].var = max_idx;
10✔
864

865
  map[0] = null_thvar;
10✔
866
  map[1] = x;
10✔
867
}
10✔
868

869

870
/*
871
 * Bound on x = (mod y k) when x or k are rational
872
 * - the bound is x < |k| or x - |k| < 0 or (not (x - |k| >= 0))
873
 *   so we construct x - |k|
874
 */
875
static void context_store_rational_mod_bound(polynomial_t *p, thvar_t *map, thvar_t x, const rational_t *k) {
1✔
876
  p->nterms = 2;
1✔
877
  p->mono[0].var = const_idx;
1✔
878
  q_set_abs(&p->mono[0].coeff, k);
1✔
879
  q_neg(&p->mono[0].coeff);            // constant = -|k|
1✔
880
  p->mono[1].var = 1;
1✔
881
  q_set_one(&p->mono[1].coeff);        // coeff of x = +1
1✔
882
  p->mono[2].var = max_idx;
1✔
883

884
  map[0] = null_thvar;
1✔
885
  map[1] = x;
1✔
886
}
1✔
887

888

889
/*
890
 * Assert constraints for x := floor(y)
891
 * - both x and y are variables in the arithmetic solver
892
 * - x has type integer
893
 *
894
 * We assert (x <= y && y < x+1)
895
 */
896
static void assert_floor_axioms(context_t *ctx, thvar_t x, thvar_t y) {
×
897
  polynomial_t *p;
898
  thvar_t map[3];
899

900
  assert(ctx->arith.arith_var_is_int(ctx->arith_solver, x));
901

902
  p = context_get_aux_poly(ctx, 4);
×
903

904
  // assert (y - x >= 0)
905
  context_store_diff_poly(p, map, y, x);
×
906
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, true);
×
907

908
  // assert (y - x - 1 < 0) <=> (not (y - x - 1) >= 0)
909
  context_store_diff_minus_one_poly(p, map, y, x);
×
910
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, false);
×
911
}
×
912

913

914
/*
915
 * Assert constraints for x == ceil(y)
916
 * - both x and y are variables in the arithmetic solver
917
 * - x has type integer
918
 *
919
 * We assert (x - 1 < y && y <= x)
920
 */
921
static void assert_ceil_axioms(context_t *ctx, thvar_t x, thvar_t y) {
×
922
  polynomial_t *p;
923
  thvar_t map[3];
924

925
  assert(ctx->arith.arith_var_is_int(ctx->arith_solver, x));
926

927
  p = context_get_aux_poly(ctx, 4);
×
928

929
  // assert (x - y >= 0)
930
  context_store_diff_poly(p, map, x, y);
×
931
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, true);
×
932

933
  // assert (x - y - 1 < 0) <=> (not (x - y - 1) >= 0)
934
  context_store_diff_minus_one_poly(p, map, x, y);
×
935
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, false);
×
936
}
×
937

938

939
/*
940
 * Assert constraints for x == abs(y)
941
 * - x and y must be variables in the arithmetic solver
942
 *
943
 * We assert (x >= 0) AND ((x == y) or (x == -y))
944
 */
945
static void assert_abs_axioms(context_t *ctx, thvar_t x, thvar_t y) {
4✔
946
  polynomial_t *p;
947
  thvar_t map[2];
948
  literal_t l1, l2;
949

950
  // assert (x >= 0)
951
  ctx->arith.assert_ge_axiom(ctx->arith_solver, x, true);
4✔
952

953
  // create l1 := (x == y)
954
  l1 = ctx->arith.create_vareq_atom(ctx->arith_solver, x, y);
4✔
955

956
  // create l2 := (x == -y) that is (x + y == 0)
957
  p = context_get_aux_poly(ctx, 3);
4✔
958
  context_store_sum_poly(p, map, x, y);
4✔
959
  l2 = ctx->arith.create_poly_eq_atom(ctx->arith_solver, p, map);
4✔
960

961
  // assert (or l1 l2)
962
  add_binary_clause(ctx->core, l1, l2);
4✔
963
}
4✔
964

965

966
/*
967
 * Constraints for x == (div y k)
968
 * - x and y must be variables in the arithmetic solver
969
 * - x must be an integer variable
970
 * - k is a non-zero rational constant
971
 *
972
 * If k and y are integer, we assert
973
 *   k * x <= y <= k * x + |k| - 1
974
 *
975
 * Otherwise, we assert
976
 *   k * x <= y < k * x + |k|
977
 */
978
static void assert_div_axioms(context_t *ctx, thvar_t x, thvar_t y, const rational_t *k) {
21✔
979
  polynomial_t *p;
980
  thvar_t map[3];
981

982
  p = context_get_aux_poly(ctx, 4);
21✔
983

984
  // assert k*x <= y (i.e., y - k*x >= 0)
985
  context_store_div_lower_bound(p, map, y, x, k);
21✔
986
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, true);
21✔
987

988
  if (ctx->arith.arith_var_is_int(ctx->arith_solver, y) && q_is_integer(k)) {
21✔
989
    // y and k are both integer
990
    // assert y <= k*x + |k| - 1 (i.e., - y + k x + |k| - 1 >= 0)
991
    context_store_integer_div_upper_bound(p, map, y, x, k);
20✔
992
    ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, true);
20✔
993

994
  } else {
995
    // assert y < k*x + |k| (i.e., y - k*x - |k| < 0) or (not (y - k*x - |k| >= 0))
996
    context_store_rational_div_upper_bound(p, map, y, x, k);
1✔
997
    ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, false);
1✔
998
  }
999
}
21✔
1000

1001

1002
/*
1003
 * Constraints for x == (mod y k)
1004
 * - d must be the variable equal to (div y k)
1005
 * - x and y must be variables in the arithmetic solver
1006
 * - k is a non-zero rational constant.
1007
 *
1008
 * We assert x = y - k * d (i.e., (mod y k) = x - k * (div y k))
1009
 * and 0 <= x < |k|.
1010
 *
1011
 * NOTE: The 0 <= x < |k| part is redundant. It's implied by the
1012
 * div_axioms for d = (div y k). It's cheap enough that I can't
1013
 * see a problem with adding it anyway (it's just an interval for x).
1014
 */
1015
static void assert_mod_axioms(context_t *ctx, thvar_t x, thvar_t y, thvar_t d, const rational_t *k) {
11✔
1016
  polynomial_t *p;
1017
  thvar_t map[3];
1018

1019
  p = context_get_aux_poly(ctx, 4);
11✔
1020

1021
  // assert y = k * d + x (i.e., x - y + k *d = 0)
1022
  context_store_divmod_eq(p, map, x, y, d, k);
11✔
1023
  ctx->arith.assert_poly_eq_axiom(ctx->arith_solver, p, map, true);
11✔
1024

1025
  // assert x >= 0
1026
  ctx->arith.assert_ge_axiom(ctx->arith_solver, x, true);
11✔
1027

1028
  if (ctx->arith.arith_var_is_int(ctx->arith_solver, x) && q_is_integer(k)) {
11✔
1029
    // both x and |k| are integer
1030
    // assert x <= |k| - 1, i.e., -x + |k| - 1 >= 0
1031
    context_store_integer_mod_bound(p, map, x, k);
10✔
1032
    ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, true);
10✔
1033
  } else {
1034
    // assert x < |k|, i.e., x - |k| <0, i.e., (not (x - |k| >= 0))
1035
    context_store_rational_mod_bound(p, map, x, k);
1✔
1036
    ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, false);
1✔
1037
  }
1038
}
11✔
1039

1040

1041

1042
/******************************************************
1043
 *  CONVERSION OF COMPOSITES TO ARITHMETIC VARIABLES  *
1044
 *****************************************************/
1045

1046
/*
1047
 * Convert a conditional to an arithmetic variable
1048
 * - if is_int is true, the variable is integer otherwise, it's real
1049
 */
1050
static thvar_t map_conditional_to_arith(context_t *ctx, conditional_t *c, bool is_int) {
239✔
1051
  literal_t *a;
1052
  uint32_t i, n;
1053
  thvar_t x, v;
1054
  bool all_false;
1055
  term_t t;
1056

1057
#if 0
1058
  printf("---> conditional to arith\n");
1059
#endif
1060

1061
  t = simplify_conditional(ctx, c);
239✔
1062
  if (t != NULL_TERM) {
239✔
1063
    return internalize_to_arith(ctx, t);
13✔
1064
  }
1065

1066
  n = c->nconds;
226✔
1067
  a = alloc_istack_array(&ctx->istack, n);
226✔
1068

1069
  all_false = true;
226✔
1070
  v = null_thvar;
226✔
1071

1072
  for (i=0; i<n; i++) {
703✔
1073
    a[i] = internalize_to_literal(ctx, c->pair[i].cond);
485✔
1074
    if (a[i] == true_literal) {
485✔
1075
      /*
1076
       * a[0] ... a[i-1] are all reducible to false
1077
       * but we can't assume v == null_thvar, since
1078
       * we don't know how the theory solver internalizes
1079
       * the conditions (i.e., some of them may not be false_literal).
1080
       */
1081
      x = internalize_to_arith(ctx, c->pair[i].val);
8✔
1082
      if (all_false) {
8✔
1083
        assert(v == null_thvar);
1084
        v = x;
6✔
1085
      } else {
1086
        // assert (v == x) in the arithmetic solver
1087
        ctx->arith.assert_vareq_axiom(ctx->arith_solver, v, x, true);
2✔
1088
      }
1089
      goto done;
8✔
1090
    }
1091
    if (a[i] != false_literal) {
477✔
1092
      if (all_false) {
460✔
1093
        assert(v == null_thvar);
1094
        v = ctx->arith.create_var(ctx->arith_solver, is_int);
215✔
1095
        all_false = false;
215✔
1096
      }
1097
      // clause for a[i] => (v = c->pair[i].val)
1098
      x = internalize_to_arith(ctx, c->pair[i].val);
460✔
1099
      ctx->arith.assert_cond_vareq_axiom(ctx->arith_solver, a[i], v, x);
460✔
1100
    }
1101
  }
1102

1103
  if (all_false) {
218✔
1104
    assert(v == null_thvar);
1105
    v = internalize_to_arith(ctx, c->defval);
5✔
1106
    goto done;
5✔
1107
  }
1108

1109
  /*
1110
   * last clause (only if some a[i] isn't false):
1111
   * (a[0] \/ ... \/ a[n-1] \/ v == c->defval)
1112
   */
1113
  assert(v != null_thvar);
1114
  x = internalize_to_arith(ctx, c->defval);
213✔
1115
  ctx->arith.assert_clause_vareq_axiom(ctx->arith_solver, n, a, v, x);
213✔
1116

1117
 done:
226✔
1118
  free_istack_array(&ctx->istack, a);
226✔
1119
  return v;
226✔
1120
}
1121

1122

1123
/*
1124
 * Convert nested if-then-else to  an arithmetic variable
1125
 * - ite = term of the form (ite c1 t1 t2)
1126
 * - c = internalization of c1
1127
 * - is_int = true if the if-then-else term is integer (otherwise it's real)
1128
 */
1129
static thvar_t flatten_ite_to_arith(context_t *ctx, composite_term_t *ite, literal_t c, bool is_int) {
2,521✔
1130
  ite_flattener_t *flattener;
1131
  ivector_t *buffer;
1132
  term_t x;
1133
  thvar_t u, v;
1134

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

1137
  flattener = objstack_alloc(&ctx->ostack, sizeof(ite_flattener_t), (cleaner_t) delete_ite_flattener);
2,521✔
1138
  init_ite_flattener(flattener);
2,521✔
1139

1140
  ite_flattener_push(flattener, ite, c);
2,521✔
1141

1142
  while (ite_flattener_is_nonempty(flattener)) {
8,823✔
1143
    if (ite_flattener_last_lit_false(flattener)) {
6,302✔
1144
      // dead branch
1145
      ite_flattener_next_branch(flattener);
7✔
1146
      continue;
7✔
1147
    }
1148
    assert(ite_flattener_branch_is_live(flattener));
1149

1150
    x = ite_flattener_leaf(flattener);
6,295✔
1151
    x = intern_tbl_get_root(&ctx->intern, x);
6,295✔
1152

1153
    /*
1154
     * x is the current leaf
1155
     * If x is of the form (ite c a b) we can push (ite c a b) on the flattener.
1156
     *
1157
     * Heuristics: don't push the term if x is already internalized or if it's
1158
     * shared.
1159
     */
1160
    if (is_pos_term(x) &&
12,590✔
1161
        is_ite_term(ctx->terms, x) &&
6,295✔
1162
        !intern_tbl_root_is_mapped(&ctx->intern, x) &&
3,934✔
1163
        term_is_not_shared(&ctx->sharing, x)) {
1,256✔
1164
      ite = ite_term_desc(ctx->terms, x);
630✔
1165
      assert(ite->arity == 3);
1166
      c = internalize_to_literal(ctx, ite->arg[0]);
630✔
1167
      ite_flattener_push(flattener, ite, c);
630✔
1168
    } else {
1169
      /*
1170
       * Add the clause [branch conditions => x = u]
1171
       */
1172
      v = internalize_to_arith(ctx, x);
5,665✔
1173

1174
      buffer = &ctx->aux_vector;
5,665✔
1175
      assert(buffer->size == 0);
1176
      ite_flattener_get_clause(flattener, buffer);
5,665✔
1177
      ite_prepare_antecedents(buffer);
5,665✔
1178
      // assert [buffer \/ v = u]
1179
      ctx->arith.assert_clause_vareq_axiom(ctx->arith_solver, buffer->size, buffer->data, v, u);
5,665✔
1180
      ivector_reset(buffer);
5,665✔
1181

1182
      ite_flattener_next_branch(flattener);
5,665✔
1183
    }
1184
  }
1185

1186
  //  delete_ite_flattener(&flattener);
1187
   objstack_pop(&ctx->ostack);
2,521✔
1188

1189
  return u;
2,521✔
1190
}
1191

1192
/*
1193
 * Convert if-then-else to an arithmetic variable
1194
 * - if is_int is true, the if-then-else term is integer
1195
 * - otherwise, it's real
1196
 */
1197
static thvar_t map_ite_to_arith(context_t *ctx, composite_term_t *ite, bool is_int) {
3,023✔
1198
  conditional_t *d;
1199
  literal_t c;
1200
  thvar_t v, x;
1201

1202
  assert(ite->arity == 3);
1203

1204
  d = context_make_conditional(ctx, ite);
3,023✔
1205
  if (d != NULL) {
3,023✔
1206
    v = map_conditional_to_arith(ctx, d, is_int);
239✔
1207
    context_free_conditional(ctx, d);
239✔
1208
    return v;
239✔
1209
  }
1210

1211
  c = internalize_to_literal(ctx, ite->arg[0]); // condition
2,784✔
1212
  if (c == true_literal) {
2,784✔
1213
    return internalize_to_arith(ctx, ite->arg[1]);
77✔
1214
  }
1215
  if (c == false_literal) {
2,707✔
1216
    return internalize_to_arith(ctx, ite->arg[2]);
115✔
1217
  }
1218

1219
  if (context_ite_flattening_enabled(ctx)) {
2,592✔
1220
    return flatten_ite_to_arith(ctx, ite, c, is_int);
2,521✔
1221
  }
1222

1223

1224
  /*
1225
   * no simplification: create a fresh variable v and assert (c ==> v = t1)
1226
   * and (not c ==> v = t2)
1227
   */
1228
  v = ctx->arith.create_var(ctx->arith_solver, is_int);
71✔
1229

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

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

1236
  return v;
71✔
1237
}
1238

1239

1240
/*
1241
 * Assert the bounds on t when t is an arithmetic, special if-then-else
1242
 * - x = arithmetic variable mapped to t in the arithmetic solver
1243
 */
1244
static void assert_ite_bounds(context_t *ctx, term_t t, thvar_t x) {
793✔
1245
  term_table_t *terms;
1246
  polynomial_t *p;
1247
  term_t lb, ub;
1248
  thvar_t map[2];
1249

1250
  terms = ctx->terms;
793✔
1251
  assert(is_arithmetic_term(terms, t));
1252

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

1256
#if 0
1257
  printf("assert ite bound:\n  term: ");
1258
  print_term_name(stdout, terms, t);
1259
  printf("\n");
1260
  printf("  lower bound: ");
1261
  print_term_full(stdout, terms, lb);
1262
  printf("\n");
1263
  printf("  upper bound: ");
1264
  print_term_full(stdout, terms, ub);
1265
  printf("\n");
1266
#endif
1267

1268
  /*
1269
   * prepare polynomial p:
1270
   * first monomial is a constant, second monomial is either +t or -t
1271
   * map[0] = null (what's mapped to const_idx)
1272
   * map[1] = x = (what's mapped to t)
1273
   */
1274
  p = context_get_aux_poly(ctx, 3);
793✔
1275
  p->nterms = 2;
793✔
1276
  p->mono[0].var = const_idx;
793✔
1277
  p->mono[1].var = t;
793✔
1278
  p->mono[2].var = max_idx;
793✔
1279
  map[0] = null_thvar;
793✔
1280
  map[1] = x;
793✔
1281

1282

1283
  // first bound: t >= lb
1284
  q_set_neg(&p->mono[0].coeff, rational_term_desc(terms, lb)); // -lb
793✔
1285
  q_set_one(&p->mono[1].coeff); // +t
793✔
1286
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, true); // assert -lb + t >= 0
793✔
1287

1288
  // second bound: t <= ub
1289
  q_set(&p->mono[0].coeff, rational_term_desc(terms, ub));  // +ub
793✔
1290
  q_set_minus_one(&p->mono[1].coeff);  // -t
793✔
1291
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, true); // assert +ub - t >= 0
793✔
1292
}
793✔
1293

1294

1295
/*
1296
 * Convert a power product to an arithmetic variable
1297
 */
1298
static thvar_t map_pprod_to_arith(context_t *ctx, pprod_t *p) {
×
1299
  uint32_t i, n;
1300
  thvar_t *a;
1301
  thvar_t x;
1302

1303
  n = p->len;
×
1304
  a = alloc_istack_array(&ctx->istack, n);
×
1305
  for (i=0; i<n; i++) {
×
1306
    a[i] = internalize_to_arith(ctx, p->prod[i].var);
×
1307
  }
1308

1309
  x = ctx->arith.create_pprod(ctx->arith_solver, p, a);
×
1310
  free_istack_array(&ctx->istack, a);
×
1311

1312
  return x;
×
1313
}
1314

1315

1316
/*
1317
 * Convert polynomial p to an arithmetic variable
1318
 */
1319
static thvar_t map_poly_to_arith(context_t *ctx, polynomial_t *p) {
1,762✔
1320
  uint32_t i, n;
1321
  thvar_t *a;
1322
  thvar_t x;
1323

1324
  n = p->nterms;
1,762✔
1325
  a = alloc_istack_array(&ctx->istack, n);
1,762✔
1326

1327
  // skip the constant if any
1328
  i = 0;
1,762✔
1329
  if (p->mono[0].var == const_idx) {
1,762✔
1330
    a[0] = null_thvar;
467✔
1331
    i ++;
467✔
1332
  }
1333

1334
  // deal with the non-constant monomials
1335
  while (i<n) {
5,035✔
1336
    a[i] = internalize_to_arith(ctx, p->mono[i].var);
3,273✔
1337
    i ++;
3,273✔
1338
  }
1339

1340
  // build the polynomial
1341
  x = ctx->arith.create_poly(ctx->arith_solver, p, a);
1,762✔
1342
  free_istack_array(&ctx->istack, a);
1,762✔
1343

1344
  return x;
1,762✔
1345
}
1346

1347

1348
/*
1349
 * Auxiliary function: return y := (floor x)
1350
 * - check the divmod table first.
1351
 *   If there's a record for (floor x), return the corresponding variable.
1352
 * - Otherwise, create a fresh integer variable y,
1353
 *   assert the axioms for y = (floor x)
1354
 *   add a record to the divmod table and return y.
1355
 */
1356
static thvar_t get_floor(context_t *ctx, thvar_t x) {
×
1357
  thvar_t y;
1358

1359
  y = context_find_var_for_floor(ctx, x);
×
1360
  if (y == null_thvar) {
×
1361
    y = ctx->arith.create_var(ctx->arith_solver, true); // y is an integer variable
×
1362
    assert_floor_axioms(ctx, y, x); // assert y = floor(x)
×
1363
    context_record_floor(ctx, x, y); // save the mapping y --> floor(x)
×
1364
  }
1365

1366
  return y;
×
1367
}
1368

1369

1370
/*
1371
 * Return y := (div x k)
1372
 * - check the divmod table first
1373
 * - if (div x k) has already been processed, return the corresponding variable
1374
 * - otherwise create a new variable y, assert the axioms for y = (div x k)
1375
 *   add a record in the divmod table, and return y.
1376
 */
1377
static thvar_t get_div(context_t *ctx, thvar_t x, const rational_t *k) {
25✔
1378
  thvar_t y;
1379

1380
  y = context_find_var_for_div(ctx, x, k);
25✔
1381
  if (y == null_thvar) {
25✔
1382
    // create y := (div x k)
1383
    y = ctx->arith.create_var(ctx->arith_solver, true); // y is an integer
21✔
1384
    assert_div_axioms(ctx, y, x, k);
21✔
1385
    context_record_div(ctx, x, k, y);
21✔
1386
  }
1387

1388
  return y;
25✔
1389
}
1390

1391

1392

1393
/*
1394
 * Convert (floor t) to an arithmetic variable
1395
 */
1396
static thvar_t map_floor_to_arith(context_t *ctx, term_t t) {
×
1397
  thvar_t x, y;
1398

1399
  x = internalize_to_arith(ctx, t);
×
1400
  if (ctx->arith.arith_var_is_int(ctx->arith_solver, x)) {
×
1401
    // x is integer so (floor x) = x
1402
    y = x;
×
1403
  } else {
1404
    y = get_floor(ctx, x);
×
1405
  }
1406

1407
  return y;
×
1408
}
1409

1410

1411
/*
1412
 * Convert (ceil t) to an arithmetic variable
1413
 */
1414
static thvar_t map_ceil_to_arith(context_t *ctx, term_t t) {
×
1415
  thvar_t x, y;
1416

1417
  x = internalize_to_arith(ctx, t);
×
1418
  if (ctx->arith.arith_var_is_int(ctx->arith_solver, x)) {
×
1419
    // x is integer so (ceil x) = x
1420
    y = x;
×
1421
  } else {
1422
    y = context_find_var_for_ceil(ctx, x);
×
1423
    if (y == null_thvar) {
×
1424
      y = ctx->arith.create_var(ctx->arith_solver, true); // y is an integer variable
×
1425
      assert_ceil_axioms(ctx, y, x); // assert y = ceil(x)
×
1426
      context_record_ceil(ctx, x, y); // save the mapping y --> ceil(x)
×
1427
    }
1428
  }
1429

1430
  return y;
×
1431
}
1432

1433

1434
/*
1435
 * Convert (abs t) to an arithmetic variable
1436
 */
1437
static thvar_t map_abs_to_arith(context_t *ctx, term_t t) {
4✔
1438
  thvar_t x, y;
1439
  bool is_int;
1440

1441
  x = internalize_to_arith(ctx, t);
4✔
1442
  is_int = ctx->arith.arith_var_is_int(ctx->arith_solver, x);
4✔
1443
  y = ctx->arith.create_var(ctx->arith_solver, is_int); // y := abs(x) has the same type as x
4✔
1444
  assert_abs_axioms(ctx, y, x);
4✔
1445

1446
  return y;
4✔
1447
}
1448

1449

1450
/*
1451
 * Auxiliary function: check whether t is a non-zero arithmetic constant
1452
 * - if so, store t's value in *val
1453
 */
1454
static bool is_non_zero_rational(term_table_t *tbl, term_t t, rational_t *val) {
17✔
1455
  assert(is_arithmetic_term(tbl, t));
1456

1457
  if (term_kind(tbl, t) == ARITH_CONSTANT) {
17✔
1458
    q_set(val, rational_term_desc(tbl, t));
17✔
1459
    return q_is_nonzero(val);
17✔
1460
  }
1461
  return false;
×
1462
}
1463

1464

1465
/*
1466
 * Error in division: either the divisor is zero or is non-constant
1467
 */
1468
static void __attribute__((noreturn))  bad_divisor(context_t *ctx, term_t t) {
2✔
1469
  term_table_t *tbl;
1470
  int code;
1471

1472
  tbl = ctx->terms;
2✔
1473
  assert(is_arithmetic_term(tbl, t) && is_pos_term(t));
1474

1475
  code = FORMULA_NOT_LINEAR;
2✔
1476
  if (term_kind(tbl, t) == ARITH_CONSTANT && q_is_zero(rational_term_desc(tbl, t))) {
2✔
1477
    code = DIV_BY_ZERO;
2✔
1478
  }
1479
  longjmp(ctx->env, code);
2✔
1480
}
1481

1482
/*
1483
 * Convert (/ t1 t2) to an arithmetic variable
1484
 * - t2 must be a non-zero arithmetic constant
1485
 */
1486
static thvar_t map_rdiv_to_arith(context_t *ctx, composite_term_t *div) {
2✔
1487
  // Could try to evaluate t2 then check whether that's a constant
1488
  assert(div->arity == 2);
1489
  bad_divisor(ctx, div->arg[1]);
2✔
1490
}
1491

1492

1493
/*
1494
 * Convert (div t1 t2) to an arithmetic variable.
1495
 * - fails if t2 is not an arithmetic constant or if it's zero
1496
 */
1497
static thvar_t map_idiv_to_arith(context_t *ctx, composite_term_t *div) {
6✔
1498
  rational_t k;
1499
  thvar_t x, y;
1500

1501
  assert(div->arity == 2);
1502

1503
  q_init(&k);
6✔
1504
  if (is_non_zero_rational(ctx->terms, div->arg[1], &k)) { // k := value of t2
6✔
1505
    assert(q_is_nonzero(&k));
1506
    x = internalize_to_arith(ctx, div->arg[0]); // t1
6✔
1507
    y = get_div(ctx, x, &k);
6✔
1508

1509
  } else {
1510
    // division by a non-constant or by zero: not supported by default
1511
    // arithmetic solver for now
1512
    q_clear(&k);
×
1513
    bad_divisor(ctx, div->arg[1]);
×
1514
  }
1515
  q_clear(&k);
6✔
1516

1517
  return y;
6✔
1518
}
1519

1520

1521
/*
1522
 * Convert (mod t1 t2) to an arithmetic variable
1523
 * - t2 must be a non-zero constant
1524
 */
1525
static thvar_t map_mod_to_arith(context_t *ctx, composite_term_t *mod) {
11✔
1526
  rational_t k;
1527
  thvar_t x, y, r;
1528
  bool is_int;
1529

1530
  assert(mod->arity == 2);
1531

1532
  q_init(&k);
11✔
1533
  if (is_non_zero_rational(ctx->terms, mod->arg[1], &k)) { // k := divider
11✔
1534
    x = internalize_to_arith(ctx, mod->arg[0]);
11✔
1535

1536
    // get y := (div x k)
1537
    assert(q_is_nonzero(&k));
1538
    y = get_div(ctx, x, &k);
11✔
1539

1540
    /*
1541
     * r := (mod x k) is x - k * y where y is an integer.
1542
     * If both x and k are integer, then r has integer type. Otherwise,
1543
     * r is a real variable.
1544
     */
1545
    is_int = ctx->arith.arith_var_is_int(ctx->arith_solver, x) && q_is_integer(&k);
11✔
1546
    r = ctx->arith.create_var(ctx->arith_solver, is_int);
11✔
1547
    assert_mod_axioms(ctx, r, x, y, &k);
11✔
1548

1549
  } else {
1550
    // Non-constant or zero divider
1551
    q_clear(&k);
×
1552
    bad_divisor(ctx, mod->arg[1]);
×
1553
  }
1554

1555
  q_clear(&k);
11✔
1556

1557
  return r;
11✔
1558
}
1559

1560

1561

1562
/******************************************************
1563
 *  CONVERSION OF COMPOSITES TO BIT-VECTOR VARIABLES  *
1564
 *****************************************************/
1565

1566
/*
1567
 * Convert if-then-else to a bitvector variable
1568
 */
1569
static thvar_t map_ite_to_bv(context_t *ctx, composite_term_t *ite) {
20,779✔
1570
  literal_t c;
1571
  thvar_t x, y;
1572

1573
  assert(ite->arity == 3);
1574

1575
  c = internalize_to_literal(ctx, ite->arg[0]);
20,779✔
1576
  if (c == true_literal) {
20,779✔
1577
    return internalize_to_bv(ctx, ite->arg[1]);
23✔
1578
  }
1579
  if (c == false_literal) {
20,756✔
1580
    return internalize_to_bv(ctx, ite->arg[2]);
2,082✔
1581
  }
1582

1583
  // no simplification
1584
  x = internalize_to_bv(ctx, ite->arg[1]);
18,674✔
1585
  y = internalize_to_bv(ctx, ite->arg[2]);
18,674✔
1586

1587
  return ctx->bv.create_bvite(ctx->bv_solver, c, x, y);
18,674✔
1588
}
1589

1590

1591
/*
1592
 * Array of bits b
1593
 * - hackish: we locally disable flattening here
1594
 */
1595
static thvar_t map_bvarray_to_bv(context_t *ctx, composite_term_t *b) {
16,993✔
1596
  uint32_t i, n;
1597
  uint32_t save_options;
1598
  literal_t *a;
1599
  thvar_t x;
1600

1601
  n = b->arity;
16,993✔
1602
  a = alloc_istack_array(&ctx->istack, n);
16,993✔
1603

1604
  save_options = ctx->options;
16,993✔
1605
  disable_diseq_and_or_flattening(ctx);
16,993✔
1606
  for (i=0; i<n; i++) {
497,868✔
1607
    a[i] = internalize_to_literal(ctx, b->arg[i]);
480,875✔
1608
  }
1609
  ctx->options = save_options;
16,993✔
1610

1611
  x = ctx->bv.create_bvarray(ctx->bv_solver, a, n);
16,993✔
1612

1613
  free_istack_array(&ctx->istack, a);
16,993✔
1614

1615
  return x;
16,993✔
1616
}
1617

1618

1619
/*
1620
 * Unsigned division: quotient (div u v)
1621
 */
1622
static thvar_t map_bvdiv_to_bv(context_t *ctx, composite_term_t *div) {
97✔
1623
  thvar_t x, y;
1624

1625
  assert(div->arity == 2);
1626
  x = internalize_to_bv(ctx, div->arg[0]);
97✔
1627
  y = internalize_to_bv(ctx, div->arg[1]);
97✔
1628

1629
  return ctx->bv.create_bvdiv(ctx->bv_solver, x, y);
97✔
1630
}
1631

1632

1633
/*
1634
 * Unsigned division: remainder (rem u v)
1635
 */
1636
static thvar_t map_bvrem_to_bv(context_t *ctx, composite_term_t *rem) {
148✔
1637
  thvar_t x, y;
1638

1639
  assert(rem->arity == 2);
1640
  x = internalize_to_bv(ctx, rem->arg[0]);
148✔
1641
  y = internalize_to_bv(ctx, rem->arg[1]);
148✔
1642

1643
  return ctx->bv.create_bvrem(ctx->bv_solver, x, y);
148✔
1644
}
1645

1646

1647
/*
1648
 * Signed division/rounding toward 0: quotient (sdiv u v)
1649
 */
1650
static thvar_t map_bvsdiv_to_bv(context_t *ctx, composite_term_t *sdiv) {
87✔
1651
  thvar_t x, y;
1652

1653
  assert(sdiv->arity == 2);
1654
  x = internalize_to_bv(ctx, sdiv->arg[0]);
87✔
1655
  y = internalize_to_bv(ctx, sdiv->arg[1]);
87✔
1656

1657
  return ctx->bv.create_bvsdiv(ctx->bv_solver, x, y);
87✔
1658
}
1659

1660

1661
/*
1662
 * Signed division/rounding toward 0: remainder (srem u v)
1663
 */
1664
static thvar_t map_bvsrem_to_bv(context_t *ctx, composite_term_t *srem) {
78✔
1665
  thvar_t x, y;
1666

1667
  assert(srem->arity == 2);
1668
  x = internalize_to_bv(ctx, srem->arg[0]);
78✔
1669
  y = internalize_to_bv(ctx, srem->arg[1]);
78✔
1670

1671
  return ctx->bv.create_bvsrem(ctx->bv_solver, x, y);
78✔
1672
}
1673

1674

1675
/*
1676
 * Signed division/rounding toward -infinity: remainder (smod u v)
1677
 */
1678
static thvar_t map_bvsmod_to_bv(context_t *ctx, composite_term_t *smod) {
×
1679
  thvar_t x, y;
1680

1681
  assert(smod->arity == 2);
1682
  x = internalize_to_bv(ctx, smod->arg[0]);
×
1683
  y = internalize_to_bv(ctx, smod->arg[1]);
×
1684

1685
  return ctx->bv.create_bvsmod(ctx->bv_solver, x, y);
×
1686
}
1687

1688

1689
/*
1690
 * Left shift: (shl u v)
1691
 */
1692
static thvar_t map_bvshl_to_bv(context_t *ctx, composite_term_t *shl) {
85✔
1693
  thvar_t x, y;
1694

1695
  assert(shl->arity == 2);
1696
  x = internalize_to_bv(ctx, shl->arg[0]);
85✔
1697
  y = internalize_to_bv(ctx, shl->arg[1]);
85✔
1698

1699
  return ctx->bv.create_bvshl(ctx->bv_solver, x, y);
85✔
1700
}
1701

1702

1703
/*
1704
 * Logical shift right: (lshr u v)
1705
 */
1706
static thvar_t map_bvlshr_to_bv(context_t *ctx, composite_term_t *lshr) {
1,428✔
1707
  thvar_t x, y;
1708

1709
  assert(lshr->arity == 2);
1710
  x = internalize_to_bv(ctx, lshr->arg[0]);
1,428✔
1711
  y = internalize_to_bv(ctx, lshr->arg[1]);
1,428✔
1712

1713
  return ctx->bv.create_bvlshr(ctx->bv_solver, x, y);
1,428✔
1714
}
1715

1716

1717
/*
1718
 * Arithmetic shift right: (ashr u v)
1719
 */
1720
static thvar_t map_bvashr_to_bv(context_t *ctx, composite_term_t *ashr) {
296✔
1721
  thvar_t x, y;
1722

1723
  assert(ashr->arity == 2);
1724
  x = internalize_to_bv(ctx, ashr->arg[0]);
296✔
1725
  y = internalize_to_bv(ctx, ashr->arg[1]);
296✔
1726

1727
  return ctx->bv.create_bvashr(ctx->bv_solver, x, y);
296✔
1728
}
1729

1730

1731

1732
/*
1733
 * TODO: check for simplifications in bitvector arithmetic
1734
 * before translation to bitvector variables.
1735
 *
1736
 * This matters for the wienand-cav2008 benchmarks.
1737
 */
1738

1739
/*
1740
 * Power product
1741
 */
1742
static thvar_t map_pprod_to_bv(context_t *ctx, pprod_t *p) {
585✔
1743
  uint32_t i, n;
1744
  thvar_t *a;
1745
  thvar_t x;
1746

1747
  n = p->len;
585✔
1748
  a = alloc_istack_array(&ctx->istack, n);
585✔
1749
  for (i=0; i<n; i++) {
1,730✔
1750
    a[i] = internalize_to_bv(ctx, p->prod[i].var);
1,145✔
1751
  }
1752

1753
  x = ctx->bv.create_pprod(ctx->bv_solver, p, a);
585✔
1754
  free_istack_array(&ctx->istack, a);
585✔
1755

1756
  return x;
585✔
1757
}
1758

1759

1760
/*
1761
 * Bitvector polynomial, 64bit coefficients
1762
 */
1763
static thvar_t map_bvpoly64_to_bv(context_t *ctx, bvpoly64_t *p) {
12,153✔
1764
  uint32_t i, n;
1765
  thvar_t *a;
1766
  thvar_t x;
1767

1768
  assert(p->nterms > 0);
1769

1770
  n = p->nterms;
12,153✔
1771
  a = alloc_istack_array(&ctx->istack, n);
12,153✔
1772

1773
  // skip the constant if any
1774
  i = 0;
12,153✔
1775
  if (p->mono[0].var == const_idx) {
12,153✔
1776
    a[0] = null_thvar;
3,164✔
1777
    i ++;
3,164✔
1778
  }
1779

1780
  // non-constant monomials
1781
  while (i < n) {
28,311✔
1782
    a[i] = internalize_to_bv(ctx, p->mono[i].var);
16,158✔
1783
    i ++;
16,158✔
1784
  }
1785

1786
  x = ctx->bv.create_poly64(ctx->bv_solver, p, a);
12,153✔
1787
  free_istack_array(&ctx->istack, a);
12,153✔
1788

1789
  return x;
12,153✔
1790
}
1791

1792

1793
/*
1794
 * Bitvector polynomial, coefficients have more than 64bits
1795
 */
1796
static thvar_t map_bvpoly_to_bv(context_t *ctx, bvpoly_t *p) {
607✔
1797
  uint32_t i, n;
1798
  thvar_t *a;
1799
  thvar_t x;
1800

1801
  assert(p->nterms > 0);
1802

1803
  n = p->nterms;
607✔
1804
  a = alloc_istack_array(&ctx->istack, n);
607✔
1805

1806
  // skip the constant if any
1807
  i = 0;
607✔
1808
  if (p->mono[0].var == const_idx) {
607✔
1809
    a[0] = null_thvar;
539✔
1810
    i ++;
539✔
1811
  }
1812

1813
  // non-constant monomials
1814
  while (i < n) {
1,268✔
1815
    a[i] = internalize_to_bv(ctx, p->mono[i].var);
661✔
1816
    i ++;
661✔
1817
  }
1818

1819
  x = ctx->bv.create_poly(ctx->bv_solver, p, a);
607✔
1820
  free_istack_array(&ctx->istack, a);
607✔
1821

1822
  return x;
607✔
1823
}
1824

1825

1826
#if 0
1827
/*
1828
 * Bvpoly buffer: b must be normalized.
1829
 * - not optimal but this shouldn't be called often.
1830
 */
1831
static thvar_t map_bvpoly_buffer_to_bv(context_t *ctx, bvpoly_buffer_t *b) {
1832
  bvpoly64_t *p;
1833
  bvpoly_t *q;
1834
  uint32_t n;
1835
  thvar_t x;
1836

1837
  n = bvpoly_buffer_bitsize(b);
1838

1839
  if (bvpoly_buffer_is_zero(b)) {
1840
    x = ctx->bv.create_zero(ctx->bv_solver, n);
1841
  } else if (n <= 64) {
1842
    p = bvpoly_buffer_getpoly64(b);
1843
    x = map_bvpoly64_to_bv(ctx, p);
1844
    free_bvpoly64(p);
1845
  } else {
1846
    q = bvpoly_buffer_getpoly(b);
1847
    x = map_bvpoly_to_bv(ctx, q);
1848
    free_bvpoly(q);
1849
  }
1850

1851
  return x;
1852
}
1853

1854
#endif
1855

1856
/****************************
1857
 *  CONVERSION TO LITERALS  *
1858
 ***************************/
1859

1860
/*
1861
 * Boolean if-then-else
1862
 */
1863
static literal_t map_ite_to_literal(context_t *ctx, composite_term_t *ite) {
1,863✔
1864
  literal_t l1, l2, l3;
1865

1866
  assert(ite->arity == 3);
1867
  l1 = internalize_to_literal(ctx, ite->arg[0]); // condition
1,863✔
1868
  if (l1 == true_literal) {
1,863✔
1869
    return internalize_to_literal(ctx, ite->arg[1]);
32✔
1870
  }
1871
  if (l1 == false_literal) {
1,831✔
1872
    return internalize_to_literal(ctx, ite->arg[2]);
71✔
1873
  }
1874

1875
  l2 = internalize_to_literal(ctx, ite->arg[1]);
1,760✔
1876
  l3 = internalize_to_literal(ctx, ite->arg[2]);
1,760✔
1877

1878
  return mk_ite_gate(&ctx->gate_manager, l1, l2, l3);
1,760✔
1879
}
1880

1881

1882
/*
1883
 * Generic equality: (eq t1 t2)
1884
 * - t1 and t2 are not arithmetic or bitvector terms
1885
 */
1886
static literal_t map_eq_to_literal(context_t *ctx, composite_term_t *eq) {
14,519✔
1887
  occ_t u, v;
1888
  literal_t l1, l2, l;
1889

1890
  assert(eq->arity == 2);
1891

1892
  if (is_boolean_term(ctx->terms, eq->arg[0])) {
14,519✔
1893
    assert(is_boolean_term(ctx->terms, eq->arg[1]));
1894

1895
    l1 = internalize_to_literal(ctx, eq->arg[0]);
9,058✔
1896
    l2 = internalize_to_literal(ctx, eq->arg[1]);
9,058✔
1897
    l = mk_iff_gate(&ctx->gate_manager, l1, l2);
9,058✔
1898
  } else {
1899
    // filter out high-order terms. It's enough to check eq->arg[0]
1900
    check_high_order_support(ctx, eq->arg, 1);
5,461✔
1901

1902
    u = internalize_to_eterm(ctx, eq->arg[0]);
5,461✔
1903
    v = internalize_to_eterm(ctx, eq->arg[1]);
5,461✔
1904
    l = egraph_make_eq(ctx->egraph, u, v);
5,461✔
1905
  }
1906

1907
  return l;
14,519✔
1908
}
1909

1910

1911
/*
1912
 * (or t1 ... t_n)
1913
 */
1914
static literal_t map_or_to_literal(context_t *ctx, composite_term_t *or) {
81,300✔
1915
  int32_t *a;
1916
  ivector_t *v;
1917
  literal_t l;
1918
  uint32_t i, n;
1919

1920
  if (context_flatten_or_enabled(ctx)) {
81,300✔
1921
    // flatten (or ...): store result in v
1922
    v = &ctx->aux_vector;
13,220✔
1923
    assert(v->size == 0);
1924
    flatten_or_term(ctx, v, or);
13,220✔
1925

1926
    // try easy simplification
1927
    n = v->size;
13,220✔
1928
    if (disjunct_is_true(ctx, v->data, n)) {
13,220✔
1929
      ivector_reset(v);
335✔
1930
      return true_literal;
335✔
1931
    }
1932

1933
    // make a copy of v
1934
    a = alloc_istack_array(&ctx->istack, n);
12,885✔
1935
    for (i=0; i<n; i++) {
70,797✔
1936
      a[i] = v->data[i];
57,912✔
1937
    }
1938
    ivector_reset(v);
12,885✔
1939

1940
    // internalize a[0 ... n-1]
1941
    for (i=0; i<n; i++) {
69,824✔
1942
      l = internalize_to_literal(ctx, a[i]);
57,221✔
1943
      if (l == true_literal) goto done;
57,221✔
1944
      a[i] = l;
56,939✔
1945
    }
1946

1947
  } else {
1948
    // no flattening
1949
    n = or->arity;
68,080✔
1950
    if (disjunct_is_true(ctx, or->arg, n)) {
68,080✔
1951
      return true_literal;
204✔
1952
    }
1953

1954
    a = alloc_istack_array(&ctx->istack, n);
67,876✔
1955
    for (i=0; i<n; i++) {
254,012✔
1956
      l = internalize_to_literal(ctx, or->arg[i]);
186,452✔
1957
      if (l == true_literal) goto done;
186,452✔
1958
      a[i] = l;
186,136✔
1959
    }
1960
  }
1961

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

1964
 done:
80,761✔
1965
  free_istack_array(&ctx->istack, a);
80,761✔
1966

1967
  return l;
80,761✔
1968
}
1969

1970

1971
/*
1972
 * (xor t1 ... t_n)
1973
 */
1974
static literal_t map_xor_to_literal(context_t *ctx, composite_term_t *xor) {
1✔
1975
  int32_t *a;
1976
  literal_t l;
1977
  uint32_t i, n;
1978

1979
  n = xor->arity;
1✔
1980
  a = alloc_istack_array(&ctx->istack, n);
1✔
1981
  for (i=0; i<n; i++) {
4✔
1982
    a[i] = internalize_to_literal(ctx, xor->arg[i]);
3✔
1983
  }
1984

1985
  l = mk_xor_gate(&ctx->gate_manager, n, a);
1✔
1986
  free_istack_array(&ctx->istack, a);
1✔
1987

1988
  return l;
1✔
1989
}
1990

1991

1992
/*
1993
 * Convert (p t_1 .. t_n) to a literal
1994
 * - create an egraph atom
1995
 */
1996
static literal_t map_apply_to_literal(context_t *ctx, composite_term_t *app) {
4,368✔
1997
  occ_t *a;
1998
  uint32_t i, n;
1999
  literal_t l;
2000

2001
  assert(app->arity > 0);
2002
  n = app->arity;
4,368✔
2003
  a = alloc_istack_array(&ctx->istack, n);
4,368✔
2004
  for (i=0; i<n; i++) {
16,325✔
2005
    a[i] = internalize_to_eterm(ctx, app->arg[i]);
11,957✔
2006
  }
2007

2008
  // a[0] = predicate
2009
  // a[1 ...n-1] = arguments
2010
  l = egraph_make_pred(ctx->egraph, a[0], n-1, a + 1);
4,368✔
2011
  free_istack_array(&ctx->istack, a);
4,368✔
2012

2013
  return l;
4,368✔
2014
}
2015

2016

2017

2018
/*
2019
 * Auxiliary function: translate (distinct a[0 ... n-1]) to a literal,
2020
 * when a[0] ... a[n-1] are arithmetic variables.
2021
 *
2022
 * We expand this into a quadratic number of disequalities.
2023
 */
2024
static literal_t make_arith_distinct(context_t *ctx, uint32_t n, thvar_t *a) {
158✔
2025
  uint32_t i, j;
2026
  ivector_t *v;
2027
  literal_t l;
2028

2029
  assert(n >= 2);
2030

2031
  v = &ctx->aux_vector;
158✔
2032
  assert(v->size == 0);
2033
  for (i=0; i<n-1; i++) {
3,776✔
2034
    for (j=i+1; j<n; j++) {
48,648✔
2035
      l = ctx->arith.create_vareq_atom(ctx->arith_solver, a[i], a[j]);
45,030✔
2036
      ivector_push(v, l);
45,030✔
2037
    }
2038
  }
2039
  l = mk_or_gate(&ctx->gate_manager, v->size, v->data);
158✔
2040
  ivector_reset(v);
158✔
2041

2042
  return not(l);
158✔
2043
}
2044

2045

2046
/*
2047
 * Auxiliary function: translate (distinct a[0 ... n-1]) to a literal,
2048
 * when a[0] ... a[n-1] are bitvector variables.
2049
 *
2050
 * We expand this into a quadratic number of disequalities.
2051
 */
2052
static literal_t make_bv_distinct(context_t *ctx, uint32_t n, thvar_t *a) {
2✔
2053
  uint32_t i, j;
2054
  ivector_t *v;
2055
  literal_t l;
2056

2057
  assert(n >= 2);
2058

2059
  v = &ctx->aux_vector;
2✔
2060
  assert(v->size == 0);
2061
  for (i=0; i<n-1; i++) {
11✔
2062
    for (j=i+1; j<n; j++) {
40✔
2063
      l = ctx->bv.create_eq_atom(ctx->bv_solver, a[i], a[j]);
31✔
2064
      ivector_push(v, l);
31✔
2065
    }
2066
  }
2067
  l = mk_or_gate(&ctx->gate_manager, v->size, v->data);
2✔
2068
  ivector_reset(v);
2✔
2069

2070
  return not(l);
2✔
2071
}
2072

2073

2074
/*
2075
 * Convert (distinct t_1 ... t_n) to a literal
2076
 */
2077
static literal_t map_distinct_to_literal(context_t *ctx, composite_term_t *distinct) {
9✔
2078
  int32_t *a;
2079
  literal_t l;
2080
  uint32_t i, n;
2081

2082
  n = distinct->arity;
9✔
2083
  a = alloc_istack_array(&ctx->istack, n);
9✔
2084
  if (context_has_egraph(ctx)) {
9✔
2085
    // fail if arguments are functions and we don't support high-order terms
2086
    // checking the first argument is enough since they all have the same type
2087
    check_high_order_support(ctx, distinct->arg, 1);
6✔
2088

2089
    // default: translate to the egraph
2090
    for (i=0; i<n; i++) {
25✔
2091
      a[i] = internalize_to_eterm(ctx, distinct->arg[i]);
19✔
2092
    }
2093
    l = egraph_make_distinct(ctx->egraph, n, a);
6✔
2094

2095
  } else if (is_arithmetic_term(ctx->terms, distinct->arg[0])) {
3✔
2096
    // translate to arithmetic variables
2097
    for (i=0; i<n; i++) {
12✔
2098
      a[i] = internalize_to_arith(ctx, distinct->arg[i]);
9✔
2099
    }
2100
    l = make_arith_distinct(ctx, n, a);
3✔
2101

2102
  } else if (is_bitvector_term(ctx->terms, distinct->arg[0])) {
×
2103
    // translate to bitvector variables
2104
    for (i=0; i<n; i++) {
×
2105
      a[i] = internalize_to_bv(ctx, distinct->arg[i]);
×
2106
    }
2107
    l = make_bv_distinct(ctx, n, a);
×
2108

2109
  } else {
2110
    longjmp(ctx->env, uf_error_code(ctx, distinct->arg[0]));
×
2111
  }
2112

2113
  free_istack_array(&ctx->istack, a);
9✔
2114

2115
  return l;
9✔
2116
}
2117

2118

2119

2120
/*
2121
 * Arithmetic atom: p == 0
2122
 */
2123
static literal_t map_poly_eq_to_literal(context_t *ctx, polynomial_t *p) {
1,192✔
2124
  uint32_t i, n;
2125
  thvar_t *a;
2126
  literal_t l;
2127

2128
  n = p->nterms;
1,192✔
2129
  a = alloc_istack_array(&ctx->istack, n);
1,192✔
2130

2131
  // skip the constant if any
2132
  i = 0;
1,192✔
2133
  if (p->mono[0].var == const_idx) {
1,192✔
2134
    a[0] = null_thvar;
570✔
2135
    i ++;
570✔
2136
  }
2137

2138
  // deal with the non-constant monomials
2139
  while (i<n) {
4,166✔
2140
    a[i] = internalize_to_arith(ctx, p->mono[i].var);
2,974✔
2141
    i ++;
2,974✔
2142
  }
2143

2144
  // build the atom
2145
  l = ctx->arith.create_poly_eq_atom(ctx->arith_solver, p, a);
1,192✔
2146
  free_istack_array(&ctx->istack, a);
1,192✔
2147

2148
  return l;
1,192✔
2149
}
2150

2151

2152
/*
2153
 * Arithmetic atom: (p >= 0)
2154
 */
2155
static literal_t map_poly_ge_to_literal(context_t *ctx, polynomial_t *p) {
33,493✔
2156
  uint32_t i, n;
2157
  thvar_t *a;
2158
  literal_t l;
2159

2160
  n = p->nterms;
33,493✔
2161
  a = alloc_istack_array(&ctx->istack, n);
33,493✔
2162

2163
  // skip the constant if any
2164
  i = 0;
33,493✔
2165
  if (p->mono[0].var == const_idx) {
33,493✔
2166
    a[0] = null_thvar;
26,318✔
2167
    i ++;
26,318✔
2168
  }
2169

2170
  // deal with the non-constant monomials
2171
  while (i<n) {
84,648✔
2172
    a[i] = internalize_to_arith(ctx, p->mono[i].var);
51,155✔
2173
    i ++;
51,155✔
2174
  }
2175

2176
  // build the atom
2177
  l = ctx->arith.create_poly_ge_atom(ctx->arith_solver, p, a);
33,493✔
2178
  free_istack_array(&ctx->istack, a);
33,493✔
2179

2180
  return l;
33,493✔
2181
}
2182

2183

2184
/*
2185
 * Arithmetic atom: (t >= 0)
2186
 */
2187
static literal_t map_arith_geq_to_literal(context_t *ctx, term_t t) {
33,841✔
2188
  term_table_t *terms;
2189
  thvar_t x;
2190
  literal_t l;
2191

2192
  terms = ctx->terms;
33,841✔
2193
  if (term_kind(terms, t) == ARITH_POLY) {
33,841✔
2194
    l = map_poly_ge_to_literal(ctx, poly_term_desc(terms, t));
33,493✔
2195
  } else {
2196
    x = internalize_to_arith(ctx, t);
348✔
2197
    l = ctx->arith.create_ge_atom(ctx->arith_solver, x);
348✔
2198
  }
2199

2200
  return l;
33,841✔
2201
}
2202

2203

2204

2205
/*
2206
 * Arithmetic equalities (eq t1 t2)
2207
 * 1) try to flatten the if-then-elses
2208
 * 2) also apply cheap lift-if rule: (eq (ite c t1 t2) u1) --> (ite c (eq t1 u1) (eq t2 u1))
2209
 */
2210
static literal_t map_arith_bineq(context_t *ctx, term_t t1, term_t u1);
2211

2212
/*
2213
 * Lift equality: (eq (ite c u1 u2) t) --> (ite c (eq u1 t) (eq u2 t))
2214
 */
2215
static literal_t map_ite_arith_bineq(context_t *ctx, composite_term_t *ite, term_t t) {
42,609✔
2216
  literal_t l1, l2, l3;
2217

2218
  assert(ite->arity == 3);
2219
  l1 = internalize_to_literal(ctx, ite->arg[0]);
42,609✔
2220
  if (l1 == true_literal) {
42,609✔
2221
    // (eq (ite true u1 u2) t) --> (eq u1 t)
2222
    return map_arith_bineq(ctx, ite->arg[1], t);
7✔
2223
  }
2224
  if (l1 == false_literal) {
42,602✔
2225
    // (eq (ite true u1 u2) t) --> (eq u2 t)
2226
    return map_arith_bineq(ctx, ite->arg[2], t);
109✔
2227
  }
2228

2229
  // apply lift-if here
2230
  l2 = map_arith_bineq(ctx, ite->arg[1], t);
42,493✔
2231
  l3 = map_arith_bineq(ctx, ite->arg[2], t);
42,493✔
2232

2233
  return mk_ite_gate(&ctx->gate_manager, l1, l2, l3);
42,493✔
2234
}
2235

2236
static literal_t map_arith_bineq_aux(context_t *ctx, term_t t1, term_t t2) {
53,504✔
2237
  term_table_t *terms;
2238
  thvar_t x, y;
2239
  occ_t u, v;
2240
  literal_t l;
2241

2242
  /*
2243
   * Try to apply lift-if rule: (eq (ite c u1 u2) t2) --> (ite c (eq u1 t2) (eq u2 t2))
2244
   * do this only if t2 is not an if-then-else term.
2245
   *
2246
   * Otherwise add the atom (eq t1 t2) to the egraph if possible
2247
   * or create (eq t1 t2) in the arithmetic solver.
2248
   */
2249
  terms = ctx->terms;
53,504✔
2250
  if (is_ite_term(terms, t1) && ! is_ite_term(terms, t2)) {
53,504✔
2251
    l = map_ite_arith_bineq(ctx, ite_term_desc(terms, t1), t2);
38,573✔
2252
  } else if (is_ite_term(terms, t2) && !is_ite_term(terms, t1)) {
14,931✔
2253
    l = map_ite_arith_bineq(ctx, ite_term_desc(terms, t2), t1);
4,036✔
2254
  } else if (context_has_egraph(ctx)) {
10,895✔
2255
    u = internalize_to_eterm(ctx, t1);
3,774✔
2256
    v = internalize_to_eterm(ctx, t2);
3,774✔
2257
    l = egraph_make_eq(ctx->egraph, u, v);
3,774✔
2258
  } else {
2259
    x = internalize_to_arith(ctx, t1);
7,121✔
2260
    y = internalize_to_arith(ctx, t2);
7,121✔
2261
    l = ctx->arith.create_vareq_atom(ctx->arith_solver, x, y);
7,121✔
2262
  }
2263

2264
  return l;
53,504✔
2265
}
2266

2267
static literal_t map_arith_bineq(context_t *ctx, term_t t1, term_t u1) {
95,361✔
2268
  ivector_t *v;
2269
  int32_t *a;
2270
  uint32_t i, n;
2271
  term_t t2, u2;
2272
  literal_t l;
2273

2274
  t1 = intern_tbl_get_root(&ctx->intern, t1);
95,361✔
2275
  u1 = intern_tbl_get_root(&ctx->intern, u1);
95,361✔
2276

2277
  if (t1 == u1) {
95,361✔
2278
    return true_literal;
3,222✔
2279
  }
2280

2281
  /*
2282
   * Check the cache
2283
   */
2284
  l = find_in_eq_cache(ctx, t1, u1);
92,139✔
2285
  if (l == null_literal) {
92,139✔
2286
    /*
2287
     * The pair (t1, u1) is not mapped already.
2288
     * Try to flatten the if-then-else equalities
2289
     */
2290
    v = &ctx->aux_vector;
53,431✔
2291
    assert(v->size == 0);
2292
    t2 = flatten_ite_equality(ctx, v, t1, u1);
53,431✔
2293
    u2 = flatten_ite_equality(ctx, v, u1, t2);
53,431✔
2294

2295
    /*
2296
     * (t1 == u1) is equivalent to (and (t2 == u2) v[0] ... v[n-1])
2297
     * where v[i] = element i of v
2298
     */
2299
    n = v->size;
53,431✔
2300
    if (n == 0) {
53,431✔
2301
      // empty v: return (t2 == u2)
2302
      assert(t1 == t2 && u1 == u2);
2303
      l = map_arith_bineq_aux(ctx, t2, u2);
10,680✔
2304

2305
    } else {
2306
      // build (and (t2 == u2) v[0] ... v[n-1])
2307
      // first make a copy of v into a[0 .. n-1]
2308
      a = alloc_istack_array(&ctx->istack, n+1);
42,751✔
2309
      for (i=0; i<n; i++) {
766,594✔
2310
        a[i] = v->data[i];
723,843✔
2311
      }
2312
      ivector_reset(v);
42,751✔
2313

2314
      // build the internalization of a[0 .. n-1]
2315
      for (i=0; i<n; i++) {
766,594✔
2316
        a[i] = internalize_to_literal(ctx, a[i]);
723,843✔
2317
      }
2318
      a[n] = map_arith_bineq_aux(ctx, t2, u2);
42,751✔
2319

2320
      // build (and a[0] ... a[n])
2321
      l = mk_and_gate(&ctx->gate_manager, n+1, a);
42,751✔
2322
      free_istack_array(&ctx->istack, a);
42,751✔
2323
    }
2324

2325
    /*
2326
     * Store the mapping (t1, u1) --> l in the cache
2327
     */
2328
    add_to_eq_cache(ctx, t1, u1, l);
53,431✔
2329
  }
2330

2331
  return l;
92,139✔
2332
}
2333

2334

2335
static inline literal_t map_arith_bineq_to_literal(context_t *ctx, composite_term_t *eq) {
8,967✔
2336
  assert(eq->arity == 2);
2337
  return map_arith_bineq(ctx, eq->arg[0], eq->arg[1]);
8,967✔
2338
}
2339

2340

2341

2342
/*
2343
 * Arithmetic atom: (t == 0)
2344
 */
2345
static literal_t map_arith_eq_to_literal(context_t *ctx, term_t t) {
2,249✔
2346
  term_table_t *terms;
2347
  thvar_t x;
2348
  literal_t l;
2349

2350
  terms = ctx->terms;
2,249✔
2351
  if (term_kind(terms, t) == ARITH_POLY) {
2,249✔
2352
    l = map_poly_eq_to_literal(ctx, poly_term_desc(terms, t));
1,192✔
2353
  } else if (is_ite_term(terms, t)) {
1,057✔
2354
    l = map_arith_bineq(ctx, t, zero_term);
426✔
2355
  } else {
2356
    x = internalize_to_arith(ctx, t);
631✔
2357
    l = ctx->arith.create_eq_atom(ctx->arith_solver, x);
631✔
2358
  }
2359
  return l;
2,249✔
2360
}
2361

2362

2363
/*
2364
 * DIVIDES AND IS_INT ATOMS
2365
 */
2366

2367
/*
2368
 * We use the rules
2369
 * - (is_int x)    <=> (x <= floor(x))
2370
 * - (divides k x) <=> (x <= k * div(x, k))
2371
 */
2372

2373
// atom (is_int t)
2374
static literal_t map_arith_is_int_to_literal(context_t *ctx, term_t t) {
×
2375
  polynomial_t *p;
2376
  thvar_t map[2];
2377
  thvar_t x, y;
2378
  literal_t l;
2379

2380
  x = internalize_to_arith(ctx, t);
×
2381
  if (ctx->arith.arith_var_is_int(ctx->arith_solver, x)) {
×
2382
    l = true_literal;
×
2383
  } else {
2384
    // we convert (is_int x) to (x <= floor(x))
2385
    y = get_floor(ctx, x); // y is floor x
×
2386
    p = context_get_aux_poly(ctx, 3);
×
2387
    context_store_diff_poly(p, map, y, x); // (p, map) := (y - x)
×
2388
    // atom (x <= y) is the same as (p >= 0)
2389
    l = ctx->arith.create_poly_ge_atom(ctx->arith_solver, p, map);
×
2390
  }
2391

2392
  return l;
×
2393
}
2394

2395
// atom (divides k t)  we assume k != 0
2396
static literal_t map_arith_divides_to_literal(context_t *ctx, composite_term_t *divides) {
8✔
2397
  rational_t k;
2398
  polynomial_t *p;
2399
  thvar_t map[2];
2400
  thvar_t x, y;
2401
  term_t d;
2402
  literal_t l;
2403

2404
  assert(divides->arity == 2);
2405

2406
  d = divides->arg[0];
8✔
2407
  if (term_kind(ctx->terms, d) == ARITH_CONSTANT) {
8✔
2408
    // make a copy of divides->arg[0] in k
2409
    q_init(&k);
8✔
2410
    q_set(&k, rational_term_desc(ctx->terms, d));
8✔
2411
    assert(q_is_nonzero(&k));
2412

2413
    x = internalize_to_arith(ctx, divides->arg[1]); // this is t
8✔
2414
    y = get_div(ctx, x, &k);  // y := (div x k)
8✔
2415
    p = context_get_aux_poly(ctx, 3);
8✔
2416
    context_store_divides_constraint(p, map, x, y, &k); // p is (- x + k * y)
8✔
2417
    // atom (x <= k * y) is (p >= 0)
2418
    l = ctx->arith.create_poly_ge_atom(ctx->arith_solver, p, map);
8✔
2419

2420
    q_clear(&k);
8✔
2421

2422
    return l;
8✔
2423

2424
  } else {
2425
    // k is not a constant: not supported
2426
    longjmp(ctx->env, FORMULA_NOT_LINEAR);
×
2427
  }
2428
}
2429

2430

2431
/*
2432
 * BITVECTOR ATOMS
2433
 */
2434

2435
/*
2436
 * Auxiliary function: atom for (t == 0)
2437
 */
2438
static literal_t map_bveq0_to_literal(context_t *ctx, term_t t) {
10✔
2439
  uint32_t n;
2440
  thvar_t x, y;
2441

2442
  t = intern_tbl_get_root(&ctx->intern, t);
10✔
2443
  n = term_bitsize(ctx->terms, t);
10✔
2444
  x = internalize_to_bv(ctx, t);
10✔
2445
  y = ctx->bv.create_zero(ctx->bv_solver, n);
10✔
2446

2447
  return ctx->bv.create_eq_atom(ctx->bv_solver, x, y);
10✔
2448
}
2449

2450
static literal_t map_bveq_to_literal(context_t *ctx, composite_term_t *eq) {
4,860✔
2451
  bveq_simp_t simp;
2452
  term_t t, t1, t2;
2453
  thvar_t x, y;
2454

2455
  assert(eq->arity == 2);
2456

2457
  /*
2458
   * Apply substitution then check for simplifications
2459
   */
2460
  t1 = intern_tbl_get_root(&ctx->intern, eq->arg[0]);
4,860✔
2461
  t2 = intern_tbl_get_root(&ctx->intern, eq->arg[1]);
4,860✔
2462
  t = simplify_bitvector_eq(ctx, t1, t2);
4,860✔
2463
  if (t != NULL_TERM) {
4,860✔
2464
    // (bveq t1 t2) is equivalent to t
2465
    return internalize_to_literal(ctx, t);
74✔
2466
  }
2467

2468
  /*
2469
   * More simplifications
2470
   */
2471
  try_arithmetic_bveq_simplification(ctx, &simp, t1, t2);
4,786✔
2472
  switch (simp.code) {
4,786✔
2473
  case BVEQ_CODE_TRUE:
×
2474
    return true_literal;
×
2475

2476
  case BVEQ_CODE_FALSE:
×
2477
    return false_literal;
×
2478

2479
  case BVEQ_CODE_REDUCED:
11✔
2480
    t1 = intern_tbl_get_root(&ctx->intern, simp.left);
11✔
2481
    t2 = intern_tbl_get_root(&ctx->intern, simp.right);
11✔
2482
    break;
11✔
2483

2484
  case BVEQ_CODE_REDUCED0:
10✔
2485
    // (t1 == t2) is reduced to (simp.left == 0)
2486
    // we create the atom directly here:
2487
    return map_bveq0_to_literal(ctx, simp.left);
10✔
2488

2489
  default:
4,765✔
2490
    break;
4,765✔
2491
  }
2492

2493
  if (equal_bitvector_factors(ctx, t1, t2)) {
4,776✔
2494
    return true_literal;
×
2495
  }
2496

2497
  /*
2498
   * NOTE: creating (eq t1 t2) in the egraph instead makes things worse
2499
   */
2500
  x = internalize_to_bv(ctx, t1);
4,776✔
2501
  y = internalize_to_bv(ctx, t2);
4,776✔
2502
  return ctx->bv.create_eq_atom(ctx->bv_solver, x, y);
4,776✔
2503
}
2504

2505
static literal_t map_bvge_to_literal(context_t *ctx, composite_term_t *ge) {
2,301✔
2506
  thvar_t x, y;
2507

2508
  assert(ge->arity == 2);
2509
  x = internalize_to_bv(ctx, ge->arg[0]);
2,301✔
2510
  y = internalize_to_bv(ctx, ge->arg[1]);
2,301✔
2511

2512
  return ctx->bv.create_ge_atom(ctx->bv_solver, x, y);
2,301✔
2513
}
2514

2515
static literal_t map_bvsge_to_literal(context_t *ctx, composite_term_t *sge) {
2,907✔
2516
  thvar_t x, y;
2517

2518
  assert(sge->arity == 2);
2519
  x = internalize_to_bv(ctx, sge->arg[0]);
2,907✔
2520
  y = internalize_to_bv(ctx, sge->arg[1]);
2,907✔
2521

2522
  return ctx->bv.create_sge_atom(ctx->bv_solver, x, y);
2,907✔
2523
}
2524

2525

2526
// Select bit
2527
static literal_t map_bit_select_to_literal(context_t *ctx, select_term_t *select) {
263,792✔
2528
  term_t t, s;
2529
  thvar_t x;
2530

2531
  /*
2532
   * Apply substitution then try to simplify
2533
   */
2534
  t = intern_tbl_get_root(&ctx->intern, select->arg);
263,792✔
2535
  s = extract_bit(ctx->terms, t, select->idx);
263,792✔
2536
  if (s != NULL_TERM) {
263,792✔
2537
    // (select t i) is s
2538
    return internalize_to_literal(ctx, s);
25,181✔
2539
  } else {
2540
    // no simplification
2541
    x = internalize_to_bv(ctx, t);
238,611✔
2542
    return ctx->bv.select_bit(ctx->bv_solver, x, select->idx);
238,611✔
2543
  }
2544
}
2545

2546

2547
/****************************************
2548
 *  INTERNALIZATION TO ETERM: TOPLEVEL  *
2549
 ***************************************/
2550

2551
static occ_t internalize_to_eterm(context_t *ctx, term_t t) {
103,353✔
2552
  term_table_t *terms;
2553
  term_t root;
2554
  term_t r;
2555
  uint32_t polarity;
2556
  int32_t code;
2557
  int32_t exception;
2558
  type_t tau;
2559
  occ_t u;
2560
  literal_t l;
2561
  thvar_t x;
2562

2563
  if (! context_has_egraph(ctx)) {
103,353✔
2564
    exception = uf_error_code(ctx, t);
×
2565
    goto abort;
×
2566
  }
2567

2568
  root = intern_tbl_get_root(&ctx->intern, t);
103,353✔
2569
  polarity = polarity_of(root);
103,353✔
2570
  root = unsigned_term(root);
103,353✔
2571
  r = root;
103,353✔
2572

2573
  /*
2574
   * r is a positive root in the internalization table
2575
   * polarity is 0 or 1
2576
   * if polarity is 0, then t is equal to r by substitution
2577
   * if polarity is 1, then t is equal to (not r)
2578
   */
2579
  if (intern_tbl_root_is_mapped(&ctx->intern, r)) {
103,353✔
2580
    /*
2581
     * r already internalized
2582
     */
2583
    code = intern_tbl_map_of_root(&ctx->intern, r);
64,981✔
2584
    u = translate_code_to_eterm(ctx, r, code);
64,981✔
2585
  } else {
2586
    /*
2587
     * Compute r's internalization:
2588
     * - if it's a boolean term, convert r to a literal l then
2589
     *   remap l to an egraph term
2590
     * - otherwise, recursively construct an egraph term and map it to r
2591
     */
2592
    terms = ctx->terms;
38,372✔
2593
    tau = type_of_root(ctx, r);
38,372✔
2594
    if (is_unit_type(ctx->types, tau)) {
38,372✔
2595
      // Canonicalize singleton types to one representative term.
2596
      r = get_unit_type_rep(terms, tau);
7✔
2597
      r = intern_tbl_get_root(&ctx->intern, r);
7✔
2598
      r = unsigned_term(r);
7✔
2599
      assert(is_pos_term(r) && intern_tbl_is_root(&ctx->intern, r));
2600
      if (intern_tbl_root_is_mapped(&ctx->intern, r)) {
7✔
2601
        code = intern_tbl_map_of_root(&ctx->intern, r);
1✔
2602
        u = translate_code_to_eterm(ctx, r, code);
1✔
2603
        if (root != r) {
1✔
2604
          if (intern_tbl_root_is_free(&ctx->intern, root)) {
1✔
2605
            intern_tbl_map_root(&ctx->intern, root, occ2code(u));
1✔
2606
          } else {
2607
            // If root is already mapped, it must map to the same egraph
2608
            // occurrence we are about to return for the unit-type rep.
2609
            assert(intern_tbl_map_of_root(&ctx->intern, root) == occ2code(u));  // LCOV_EXCL_LINE - consistency check, unreachable on well-formed inputs
2610
          }
2611
        }
2612
        return u ^ polarity;
1✔
2613
      }
2614
    }
2615

2616
    if (is_boolean_type(tau)) {
38,371✔
2617
      l = internalize_to_literal(ctx, r);
38✔
2618
      u = egraph_literal2occ(ctx->egraph, l);
38✔
2619
      intern_tbl_remap_root(&ctx->intern, r, occ2code(u));
38✔
2620
    } else {
2621
      /*
2622
       * r is not a boolean term
2623
       */
2624
      assert(polarity == 0);
2625

2626
      switch (term_kind(terms, r)) {
38,333✔
2627
      case CONSTANT_TERM:
1,164✔
2628
        u = pos_occ(make_egraph_constant(ctx, tau, constant_term_index(terms, r)));
1,164✔
2629
        break;
1,164✔
2630

2631
      case ARITH_CONSTANT:
339✔
2632
        u = map_arith_constant_to_eterm(ctx, rational_term_desc(terms, r));
339✔
2633
        break;
339✔
2634

2635
      case BV64_CONSTANT:
808✔
2636
        u = map_bvconst64_to_eterm(ctx, bvconst64_term_desc(terms, r));
808✔
2637
        break;
808✔
2638

2639
      case BV_CONSTANT:
18✔
2640
        u = map_bvconst_to_eterm(ctx, bvconst_term_desc(terms, r));
18✔
2641
        break;
18✔
2642

2643
      case VARIABLE:
×
2644
        exception = FREE_VARIABLE_IN_FORMULA;
×
2645
        goto abort;
×
2646

2647
      case UNINTERPRETED_TERM:
12,049✔
2648
        u = pos_occ(make_egraph_variable(ctx, tau));
12,049✔
2649
        //        add_type_constraints(ctx, u, tau);
2650
        break;
12,049✔
2651

2652
      case ARITH_FLOOR:
×
2653
        assert(is_integer_type(tau));
2654
        x = map_floor_to_arith(ctx, arith_floor_arg(terms, r));
×
2655
        u = translate_arithvar_to_eterm(ctx, x);
×
2656
        break;
×
2657

2658
      case ARITH_CEIL:
×
2659
        assert(is_integer_type(tau));
2660
        x = map_ceil_to_arith(ctx, arith_ceil_arg(terms, r));
×
2661
        u = translate_arithvar_to_eterm(ctx, x);
×
2662
        break;
×
2663

2664
      case ARITH_ABS:
×
2665
        x = map_abs_to_arith(ctx, arith_abs_arg(terms, r));
×
2666
        u = translate_arithvar_to_eterm(ctx, x);
×
2667
        break;
×
2668

2669
      case ITE_TERM:
2,168✔
2670
      case ITE_SPECIAL:
2671
        u = map_ite_to_eterm(ctx, ite_term_desc(terms, r), tau);
2,168✔
2672
        break;
2,168✔
2673

2674
      case APP_TERM:
6,531✔
2675
        u = map_apply_to_eterm(ctx, app_term_desc(terms, r), tau);
6,531✔
2676
        break;
6,531✔
2677

2678
      case ARITH_RDIV:
×
2679
        assert(is_arithmetic_type(tau));
2680
        x = map_rdiv_to_arith(ctx, arith_rdiv_term_desc(terms, r));
×
2681
        u = translate_arithvar_to_eterm(ctx, x);
×
2682
        break;
×
2683

2684
      case ARITH_IDIV:
×
2685
        assert(is_integer_type(tau));
2686
        x = map_idiv_to_arith(ctx, arith_idiv_term_desc(terms, r));
×
2687
        u = translate_arithvar_to_eterm(ctx, x); // (div t u) has type int
×
2688
        break;
×
2689

2690
      case ARITH_MOD:
2✔
2691
        x = map_mod_to_arith(ctx, arith_mod_term_desc(terms, r));
2✔
2692
        u = translate_arithvar_to_eterm(ctx, x);
2✔
2693
        break;
2✔
2694

2695
      case TUPLE_TERM:
190✔
2696
        u = map_tuple_to_eterm(ctx, tuple_term_desc(terms, r), tau);
190✔
2697
        break;
190✔
2698

2699
      case SELECT_TERM:
245✔
2700
        u = map_select_to_eterm(ctx, select_term_desc(terms, r), tau);
245✔
2701
        break;
245✔
2702

2703
      case UPDATE_TERM:
11,470✔
2704
        u = map_update_to_eterm(ctx, update_term_desc(terms, r), tau);
11,470✔
2705
        break;
11,470✔
2706

2707
      case LAMBDA_TERM:
1✔
2708
        // not ready for lambda terms yet:
2709
        exception = LAMBDAS_NOT_SUPPORTED;
1✔
2710
        goto abort;
1✔
2711

2712
      case BV_ARRAY:
1,711✔
2713
        x = map_bvarray_to_bv(ctx, bvarray_term_desc(terms, r));
1,711✔
2714
        u = translate_thvar_to_eterm(ctx, x, tau);
1,711✔
2715
        break;
1,711✔
2716

2717
      case BV_DIV:
1✔
2718
        x = map_bvdiv_to_bv(ctx, bvdiv_term_desc(terms, r));
1✔
2719
        u = translate_thvar_to_eterm(ctx, x, tau);
1✔
2720
        break;
1✔
2721

2722
      case BV_REM:
2✔
2723
        x = map_bvrem_to_bv(ctx, bvrem_term_desc(terms, r));
2✔
2724
        u = translate_thvar_to_eterm(ctx, x, tau);
2✔
2725
        break;
2✔
2726

2727
      case BV_SDIV:
1✔
2728
        x = map_bvsdiv_to_bv(ctx, bvsdiv_term_desc(terms, r));
1✔
2729
        u = translate_thvar_to_eterm(ctx, x, tau);
1✔
2730
        break;
1✔
2731

2732
      case BV_SREM:
1✔
2733
        x = map_bvsrem_to_bv(ctx, bvsrem_term_desc(terms, r));
1✔
2734
        u = translate_thvar_to_eterm(ctx, x, tau);
1✔
2735
        break;
1✔
2736

2737
      case BV_SMOD:
×
2738
        x = map_bvsmod_to_bv(ctx, bvsmod_term_desc(terms, r));
×
2739
        u = translate_thvar_to_eterm(ctx, x, tau);
×
2740
        break;
×
2741

2742
      case BV_SHL:
×
2743
        x = map_bvshl_to_bv(ctx, bvshl_term_desc(terms, r));
×
2744
        u = translate_thvar_to_eterm(ctx, x, tau);
×
2745
        break;
×
2746

2747
      case BV_LSHR:
1✔
2748
        x = map_bvlshr_to_bv(ctx, bvlshr_term_desc(terms, r));
1✔
2749
        u = translate_thvar_to_eterm(ctx, x, tau);
1✔
2750
        break;
1✔
2751

2752
      case BV_ASHR:
1✔
2753
        x = map_bvashr_to_bv(ctx, bvashr_term_desc(terms, r));
1✔
2754
        u = translate_thvar_to_eterm(ctx, x, tau);
1✔
2755
        break;
1✔
2756

2757
      case POWER_PRODUCT:
1✔
2758
        if (is_arithmetic_type(tau)) {
1✔
2759
          x = map_pprod_to_arith(ctx, pprod_term_desc(terms, r));
×
2760
        } else {
2761
          assert(is_bv_type(ctx->types, tau));
2762
          x = map_pprod_to_bv(ctx, pprod_term_desc(terms, r));
1✔
2763
        }
2764
        u = translate_thvar_to_eterm(ctx, x, tau);
1✔
2765
        break;
1✔
2766

2767
      case ARITH_POLY:
619✔
2768
        x = map_poly_to_arith(ctx, poly_term_desc(terms, r));
619✔
2769
        u = translate_thvar_to_eterm(ctx, x, tau);
619✔
2770
        break;
619✔
2771

2772
      case BV64_POLY:
1,008✔
2773
        x = map_bvpoly64_to_bv(ctx, bvpoly64_term_desc(terms, r));
1,008✔
2774
        u = translate_thvar_to_eterm(ctx, x, tau);
1,008✔
2775
        break;
1,008✔
2776

2777
      case BV_POLY:
2✔
2778
        x = map_bvpoly_to_bv(ctx, bvpoly_term_desc(terms, r));
2✔
2779
        u = translate_thvar_to_eterm(ctx, x, tau);
2✔
2780
        break;
2✔
2781

2782
      default:
×
2783
        exception = INTERNAL_ERROR;
×
2784
        goto abort;
×
2785
      }
2786

2787
      // store the mapping r --> u
2788
      intern_tbl_map_root(&ctx->intern, r, occ2code(u));
38,332✔
2789
    }
2790
  }
2791

2792
  // If we canonicalized root to a different unit-type representative r,
2793
  // remember that root internalizes to the same egraph occurrence.
2794
  if (root != r) {
103,351✔
2795
    if (intern_tbl_root_is_free(&ctx->intern, root)) {
1✔
2796
      intern_tbl_map_root(&ctx->intern, root, occ2code(u));
1✔
2797
    } else {
2798
      // If root was mapped during the recursive internalization of r (e.g.,
2799
      // because root was reached as a sub-term), the mapping must agree
2800
      // with the occurrence we are about to return.
2801
      assert(intern_tbl_map_of_root(&ctx->intern, root) == occ2code(u));  // LCOV_EXCL_LINE - consistency check, unreachable on well-formed inputs
2802
    }
2803
  }
2804

2805
  // fix the polarity
2806
  return u ^ polarity;
103,351✔
2807

2808
 abort:
1✔
2809
  longjmp(ctx->env, exception);
1✔
2810
}
2811

2812

2813

2814

2815
/****************************************
2816
 *  CONVERSION TO ARITHMETIC VARIABLES  *
2817
 ***************************************/
2818

2819
/*
2820
 * Translate internalization code x to an arithmetic variable
2821
 * - if the code is for an egraph term u, then we return the
2822
 *   theory variable attached to u in the egraph.
2823
 * - otherwise, x must be the code of an arithmetic variable v,
2824
 *   we return v.
2825
 */
2826
static thvar_t translate_code_to_arith(context_t *ctx, int32_t x) {
99,879✔
2827
  eterm_t u;
2828
  thvar_t v;
2829

2830
  assert(code_is_valid(x));
2831

2832
  if (code_is_eterm(x)) {
99,879✔
2833
    u = code2eterm(x);
6,521✔
2834
    assert(ctx->egraph != NULL && egraph_term_is_arith(ctx->egraph, u));
2835
    v = egraph_term_base_thvar(ctx->egraph, u);
6,521✔
2836
  } else {
2837
    v = code2thvar(x);
93,358✔
2838
  }
2839

2840
  assert(v != null_thvar);
2841
  return v;
99,879✔
2842
}
2843

2844

2845
static thvar_t internalize_to_arith(context_t *ctx, term_t t) {
120,785✔
2846
  term_table_t *terms;
2847
  int32_t exception;
2848
  int32_t code;
2849
  term_t r;
2850
  occ_t u;
2851
  thvar_t x;
2852

2853
  assert(is_arithmetic_term(ctx->terms, t));
2854

2855
  if (! context_has_arith_solver(ctx)) {
120,785✔
2856
    exception = ARITH_NOT_SUPPORTED;
×
2857
    goto abort;
×
2858
  }
2859

2860
  /*
2861
   * Apply term substitution: t --> r
2862
   */
2863
  r = intern_tbl_get_root(&ctx->intern, t);
120,785✔
2864
  if (intern_tbl_root_is_mapped(&ctx->intern, r)) {
120,785✔
2865
    /*
2866
     * r already internalized
2867
     */
2868
    code = intern_tbl_map_of_root(&ctx->intern, r);
99,720✔
2869
    x = translate_code_to_arith(ctx, code);
99,720✔
2870

2871
  } else {
2872
    /*
2873
     * Compute the internalization
2874
     */
2875
    terms = ctx->terms;
21,065✔
2876

2877
    switch (term_kind(terms, r)) {
21,065✔
2878
    case ARITH_CONSTANT:
1,270✔
2879
      x = ctx->arith.create_const(ctx->arith_solver, rational_term_desc(terms, r));
1,270✔
2880
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
1,270✔
2881
      break;
1,270✔
2882

2883
    case UNINTERPRETED_TERM:
15,371✔
2884
      x = ctx->arith.create_var(ctx->arith_solver, is_integer_root(ctx, r));
15,371✔
2885
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
15,371✔
2886
      //      printf("mapping: %s --> i!%d\n", term_name(ctx->terms, r), (int) x);
2887
      //      fflush(stdout);
2888
      break;
15,371✔
2889

2890
    case ARITH_FLOOR:
×
2891
      x = map_floor_to_arith(ctx, arith_floor_arg(terms, r));
×
2892
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
×
2893
      break;
×
2894

2895
    case ARITH_CEIL:
×
2896
      x = map_ceil_to_arith(ctx, arith_ceil_arg(terms, r));
×
2897
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
×
2898
      break;
×
2899

2900
    case ARITH_ABS:
4✔
2901
      x = map_abs_to_arith(ctx, arith_abs_arg(terms, r));
4✔
2902
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
4✔
2903
      break;
4✔
2904

2905
    case ITE_TERM:
2,230✔
2906
      x = map_ite_to_arith(ctx, ite_term_desc(terms, r), is_integer_root(ctx, r));
2,230✔
2907
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
2,230✔
2908
      break;
2,230✔
2909

2910
    case ITE_SPECIAL:
793✔
2911
      x = map_ite_to_arith(ctx, ite_term_desc(terms, r), is_integer_root(ctx, r));
793✔
2912
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
793✔
2913
      if (context_ite_bounds_enabled(ctx)) {
793✔
2914
        assert_ite_bounds(ctx, r, x);
793✔
2915
      }
2916
      break;
793✔
2917

2918
    case APP_TERM:
702✔
2919
      u = map_apply_to_eterm(ctx, app_term_desc(terms, r), type_of_root(ctx, r));
702✔
2920
      assert(egraph_term_is_arith(ctx->egraph, term_of_occ(u)));
2921
      intern_tbl_map_root(&ctx->intern, r, occ2code(u));
702✔
2922
      x = egraph_term_base_thvar(ctx->egraph, term_of_occ(u));
702✔
2923
      assert(x != null_thvar);
2924
      break;
702✔
2925

2926
    case ARITH_RDIV:
2✔
2927
      x = map_rdiv_to_arith(ctx, arith_rdiv_term_desc(terms, r));
2✔
2928
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
×
2929
      break;
×
2930

2931
    case ARITH_IDIV:
6✔
2932
      x = map_idiv_to_arith(ctx, arith_idiv_term_desc(terms, r));
6✔
2933
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
6✔
2934
      break;
6✔
2935

2936
    case ARITH_MOD:
9✔
2937
      x = map_mod_to_arith(ctx, arith_mod_term_desc(terms, r));
9✔
2938
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
9✔
2939
      break;
9✔
2940

2941
    case SELECT_TERM:
×
2942
      u = map_select_to_eterm(ctx, select_term_desc(terms, r), type_of_root(ctx, r));
×
2943
      assert(egraph_term_is_arith(ctx->egraph, term_of_occ(u)));
2944
      intern_tbl_map_root(&ctx->intern, r, occ2code(u));
×
2945
      x = egraph_term_base_thvar(ctx->egraph, term_of_occ(u));
×
2946
      assert(x != null_thvar);
2947
      break;
×
2948

2949
    case POWER_PRODUCT:
×
2950
      x = map_pprod_to_arith(ctx, pprod_term_desc(terms, r));
×
2951
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
×
2952
      break;
×
2953

2954
    case ARITH_POLY:
678✔
2955
      x = map_poly_to_arith(ctx, poly_term_desc(terms, r));
678✔
2956
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
678✔
2957
      break;
678✔
2958

2959
    case VARIABLE:
×
2960
      exception = FREE_VARIABLE_IN_FORMULA;
×
2961
      goto abort;
×
2962

2963
    default:
×
2964
      exception = INTERNAL_ERROR;
×
2965
      goto abort;
×
2966
    }
2967

2968
  }
2969

2970
  return x;
120,783✔
2971

2972
 abort:
×
2973
  longjmp(ctx->env, exception);
×
2974
}
2975

2976

2977

2978
/***************************************
2979
 *  CONVERSION TO BITVECTOR VARIABLES  *
2980
 **************************************/
2981

2982
/*
2983
 * Translate internalization code x to a bitvector variable
2984
 * - if x is for an egraph term u, then we return the theory variable
2985
 *   attached to u in the egraph.
2986
 * - otherwise, x must be the code of a bitvector variable v, so we return v.
2987
 */
2988
static thvar_t translate_code_to_bv(context_t *ctx, int32_t x) {
298,454✔
2989
  eterm_t u;
2990
  thvar_t v;
2991

2992
  assert(code_is_valid(x));
2993

2994
  if (code_is_eterm(x)) {
298,454✔
2995
    u = code2eterm(x);
29,164✔
2996
    assert(ctx->egraph != NULL && egraph_term_is_bv(ctx->egraph, u));
2997
    v = egraph_term_base_thvar(ctx->egraph, u);
29,164✔
2998
  } else {
2999
    v = code2thvar(x);
269,290✔
3000
  }
3001

3002
  assert(v != null_thvar);
3003

3004
  return v;
298,454✔
3005
}
3006

3007
/*
3008
 * Place holders for now
3009
 */
3010
static thvar_t internalize_to_bv(context_t *ctx, term_t t) {
375,223✔
3011
  term_table_t *terms;
3012
  int32_t exception;
3013
  int32_t code;
3014
  term_t r;
3015
  occ_t u;
3016
  thvar_t x;
3017

3018
  assert(is_bitvector_term(ctx->terms, t));
3019

3020
  if (! context_has_bv_solver(ctx)) {
375,223✔
3021
    exception = BV_NOT_SUPPORTED;
×
3022
    goto abort;
×
3023
  }
3024

3025
  /*
3026
   * Apply the term substitution: t --> r
3027
   */
3028
  r = intern_tbl_get_root(&ctx->intern, t);
375,223✔
3029
  if (intern_tbl_root_is_mapped(&ctx->intern, r)) {
375,223✔
3030
    // r is already internalized
3031
    code = intern_tbl_map_of_root(&ctx->intern, r);
298,454✔
3032
    x = translate_code_to_bv(ctx, code);
298,454✔
3033
  } else {
3034
    // compute r's internalization
3035
    terms = ctx->terms;
76,769✔
3036

3037
    switch (term_kind(terms, r)) {
76,769✔
3038
    case BV64_CONSTANT:
6,977✔
3039
      x = ctx->bv.create_const64(ctx->bv_solver, bvconst64_term_desc(terms, r));
6,977✔
3040
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
6,977✔
3041
      break;
6,977✔
3042

3043
    case BV_CONSTANT:
440✔
3044
      x = ctx->bv.create_const(ctx->bv_solver, bvconst_term_desc(terms, r));
440✔
3045
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
440✔
3046
      break;
440✔
3047

3048
    case UNINTERPRETED_TERM:
16,293✔
3049
      x = ctx->bv.create_var(ctx->bv_solver, term_bitsize(terms, r));
16,293✔
3050
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
16,293✔
3051
      break;
16,293✔
3052

3053
    case ITE_TERM:
20,779✔
3054
    case ITE_SPECIAL:
3055
      x = map_ite_to_bv(ctx, ite_term_desc(terms, r));
20,779✔
3056
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
20,779✔
3057
      break;
20,779✔
3058

3059
    case APP_TERM:
2,452✔
3060
      u = map_apply_to_eterm(ctx, app_term_desc(terms, r), type_of_root(ctx, r));
2,452✔
3061
      assert(egraph_term_is_bv(ctx->egraph, term_of_occ(u)));
3062
      intern_tbl_map_root(&ctx->intern, r, occ2code(u));
2,452✔
3063
      x = egraph_term_base_thvar(ctx->egraph, term_of_occ(u));
2,452✔
3064
      assert(x != null_thvar);
3065
      break;
2,452✔
3066

3067
    case BV_ARRAY:
15,282✔
3068
      x = map_bvarray_to_bv(ctx, bvarray_term_desc(terms, r));
15,282✔
3069
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
15,282✔
3070
      break;
15,282✔
3071

3072
    case BV_DIV:
96✔
3073
      x = map_bvdiv_to_bv(ctx, bvdiv_term_desc(terms, r));
96✔
3074
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
96✔
3075
      break;
96✔
3076

3077
    case BV_REM:
146✔
3078
      x = map_bvrem_to_bv(ctx, bvrem_term_desc(terms, r));
146✔
3079
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
146✔
3080
      break;
146✔
3081

3082
    case BV_SDIV:
86✔
3083
      x = map_bvsdiv_to_bv(ctx, bvsdiv_term_desc(terms, r));
86✔
3084
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
86✔
3085
      break;
86✔
3086

3087
    case BV_SREM:
77✔
3088
      x = map_bvsrem_to_bv(ctx, bvsrem_term_desc(terms, r));
77✔
3089
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
77✔
3090
      break;
77✔
3091

3092
    case BV_SMOD:
×
3093
      x = map_bvsmod_to_bv(ctx, bvsmod_term_desc(terms, r));
×
3094
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
×
3095
      break;
×
3096

3097
    case BV_SHL:
85✔
3098
      x = map_bvshl_to_bv(ctx, bvshl_term_desc(terms, r));
85✔
3099
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
85✔
3100
      break;
85✔
3101

3102
    case BV_LSHR:
1,427✔
3103
      x = map_bvlshr_to_bv(ctx, bvlshr_term_desc(terms, r));
1,427✔
3104
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
1,427✔
3105
      break;
1,427✔
3106

3107
    case BV_ASHR:
295✔
3108
      x = map_bvashr_to_bv(ctx, bvashr_term_desc(terms, r));
295✔
3109
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
295✔
3110
      break;
295✔
3111

3112
    case SELECT_TERM:
×
3113
      u = map_select_to_eterm(ctx, select_term_desc(terms, r), type_of_root(ctx, r));
×
3114
      assert(egraph_term_is_bv(ctx->egraph, term_of_occ(u)));
3115
      intern_tbl_map_root(&ctx->intern, r, occ2code(u));
×
3116
      x = egraph_term_base_thvar(ctx->egraph, term_of_occ(u));
×
3117
      assert(x != null_thvar);
3118
      break;
×
3119

3120
    case POWER_PRODUCT:
584✔
3121
      x = map_pprod_to_bv(ctx, pprod_term_desc(terms, r));
584✔
3122
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
584✔
3123
      break;
584✔
3124

3125
    case BV64_POLY:
11,145✔
3126
      x = map_bvpoly64_to_bv(ctx, bvpoly64_term_desc(terms, r));
11,145✔
3127
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
11,145✔
3128
      break;
11,145✔
3129

3130
    case BV_POLY:
605✔
3131
      x = map_bvpoly_to_bv(ctx, bvpoly_term_desc(terms, r));
605✔
3132
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
605✔
3133
      break;
605✔
3134

3135
    case VARIABLE:
×
3136
      exception = FREE_VARIABLE_IN_FORMULA;
×
3137
      goto abort;
×
3138

3139
    default:
×
3140
      exception = INTERNAL_ERROR;
×
3141
      goto abort;
×
3142
    }
3143
  }
3144

3145
  return x;
375,223✔
3146

3147
 abort:
×
3148
  longjmp(ctx->env, exception);
×
3149
}
3150

3151

3152

3153

3154

3155

3156
/****************************
3157
 *  CONVERSION TO LITERALS  *
3158
 ***************************/
3159

3160
/*
3161
 * Translate an internalization code x to a literal
3162
 * - if x is the code of an egraph occurrence u, we return the
3163
 *   theory variable for u in the egraph
3164
 * - otherwise, x should be the code of a literal l in the core
3165
 */
3166
static literal_t translate_code_to_literal(context_t *ctx, int32_t x) {
1,396,810✔
3167
  occ_t u;
3168
  literal_t l;
3169

3170
  assert(code_is_valid(x));
3171
  if (code_is_eterm(x)) {
1,396,810✔
3172
    u = code2occ(x);
129,807✔
3173
    if (term_of_occ(u) == true_eterm) {
129,807✔
3174
      l = mk_lit(const_bvar, polarity_of(u));
129,807✔
3175

3176
      assert((u == true_occ && l == true_literal) ||
3177
             (u == false_occ && l == false_literal));
3178
    } else {
3179
      assert(ctx->egraph != NULL);
3180
      l = egraph_occ2literal(ctx->egraph, u);
×
3181
    }
3182
  } else {
3183
    l = code2literal(x);
1,267,003✔
3184
  }
3185

3186
  return l;
1,396,810✔
3187
}
3188

3189
static literal_t internalize_to_literal(context_t *ctx, term_t t) {
1,824,155✔
3190
  term_table_t *terms;
3191
  int32_t code;
3192
  uint32_t polarity;
3193
  term_t r;
3194
  literal_t l;
3195
  occ_t u;
3196

3197
  assert(is_boolean_term(ctx->terms, t));
3198

3199
  r = intern_tbl_get_root(&ctx->intern, t);
1,824,155✔
3200
  polarity = polarity_of(r);
1,824,155✔
3201
  r = unsigned_term(r);
1,824,155✔
3202

3203
  /*
3204
   * At this point:
3205
   * 1) r is a positive root in the internalization table
3206
   * 2) polarity is 1 or 0
3207
   * 3) if polarity is 0, then t is equal to r by substitution
3208
   *    if polarity is 1, then t is equal to (not r)
3209
   *
3210
   * We get l := internalization of r
3211
   * then return l or (not l) depending on polarity.
3212
   */
3213

3214
  if (intern_tbl_root_is_mapped(&ctx->intern, r)) {
1,824,155✔
3215
    /*
3216
     * r already internalized
3217
     */
3218
    code = intern_tbl_map_of_root(&ctx->intern, r);
1,396,810✔
3219
    l = translate_code_to_literal(ctx, code);
1,396,810✔
3220

3221
  } else {
3222
    /*
3223
     * Recursively compute r's internalization
3224
     */
3225
    terms = ctx->terms;
427,345✔
3226
    switch (term_kind(terms, r)) {
427,345✔
3227
    case CONSTANT_TERM:
×
3228
      assert(r == true_term);
3229
      l = true_literal;
×
3230
      break;
×
3231

3232
    case VARIABLE:
×
3233
      longjmp(ctx->env, FREE_VARIABLE_IN_FORMULA);
×
3234
      break;
3235

3236
    case UNINTERPRETED_TERM:
6,360✔
3237
      l = pos_lit(create_boolean_variable(ctx->core));
6,360✔
3238
      break;
6,360✔
3239

3240
    case ITE_TERM:
1,863✔
3241
    case ITE_SPECIAL:
3242
      l = map_ite_to_literal(ctx, ite_term_desc(terms, r));
1,863✔
3243
      break;
1,863✔
3244

3245
    case EQ_TERM:
14,519✔
3246
      l = map_eq_to_literal(ctx, eq_term_desc(terms, r));
14,519✔
3247
      break;
14,519✔
3248

3249
    case OR_TERM:
81,300✔
3250
      l = map_or_to_literal(ctx, or_term_desc(terms, r));
81,300✔
3251
      break;
81,300✔
3252

3253
    case XOR_TERM:
1✔
3254
      l = map_xor_to_literal(ctx, xor_term_desc(terms, r));
1✔
3255
      break;
1✔
3256

3257
    case ARITH_IS_INT_ATOM:
×
3258
      l = map_arith_is_int_to_literal(ctx, arith_is_int_arg(terms, r));
×
3259
      break;
×
3260

3261
    case ARITH_EQ_ATOM:
2,249✔
3262
      l = map_arith_eq_to_literal(ctx, arith_eq_arg(terms, r));
2,249✔
3263
      break;
2,249✔
3264

3265
    case ARITH_GE_ATOM:
33,841✔
3266
      l = map_arith_geq_to_literal(ctx, arith_ge_arg(terms, r));
33,841✔
3267
      break;
33,841✔
3268

3269
    case ARITH_BINEQ_ATOM:
8,967✔
3270
      l = map_arith_bineq_to_literal(ctx, arith_bineq_atom_desc(terms, r));
8,967✔
3271
      break;
8,967✔
3272

3273
    case ARITH_DIVIDES_ATOM:
8✔
3274
      l = map_arith_divides_to_literal(ctx, arith_divides_atom_desc(terms, r));
8✔
3275
      break;
8✔
3276

3277
    case APP_TERM:
4,368✔
3278
      l = map_apply_to_literal(ctx, app_term_desc(terms, r));
4,368✔
3279
      break;
4,368✔
3280

3281
    case SELECT_TERM:
×
3282
      u = map_select_to_eterm(ctx, select_term_desc(terms, r), bool_type(ctx->types));
×
3283
      assert(egraph_term_is_bool(ctx->egraph, term_of_occ(u)));
3284
      intern_tbl_map_root(&ctx->intern, r, occ2code(u));
×
3285
      l = egraph_occ2literal(ctx->egraph, u);
×
3286
      // we don't want to map r to l here
3287
      goto done;
×
3288

3289
    case DISTINCT_TERM:
9✔
3290
      l = map_distinct_to_literal(ctx, distinct_term_desc(terms, r));
9✔
3291
      break;
9✔
3292

3293
    case FORALL_TERM:
×
3294
      if (context_in_strict_mode(ctx)) {
×
3295
        longjmp(ctx->env, QUANTIFIERS_NOT_SUPPORTED);
×
3296
      }
3297
      // lax mode: turn forall into a proposition
3298
      l = pos_lit(create_boolean_variable(ctx->core));
×
3299
      break;
×
3300

3301
    case BIT_TERM:
263,792✔
3302
      l = map_bit_select_to_literal(ctx, bit_term_desc(terms, r));
263,792✔
3303
      break;
263,792✔
3304

3305
    case BV_EQ_ATOM:
4,860✔
3306
      l = map_bveq_to_literal(ctx, bveq_atom_desc(terms, r));
4,860✔
3307
      break;
4,860✔
3308

3309
    case BV_GE_ATOM:
2,301✔
3310
      l = map_bvge_to_literal(ctx, bvge_atom_desc(terms, r));
2,301✔
3311
      break;
2,301✔
3312

3313
    case BV_SGE_ATOM:
2,907✔
3314
      l = map_bvsge_to_literal(ctx, bvsge_atom_desc(terms, r));
2,907✔
3315
      break;
2,907✔
3316

3317
    default:
×
3318
      longjmp(ctx->env, INTERNAL_ERROR);
×
3319
      break;
3320
    }
3321

3322
    // map r to l in the internalization table
3323
    intern_tbl_map_root(&ctx->intern, r, literal2code(l));
427,345✔
3324
  }
3325

3326
 done:
1,824,155✔
3327
  return l ^ polarity;
1,824,155✔
3328
}
3329

3330

3331

3332
/******************************************************
3333
 *  TOP-LEVEL ASSERTIONS: TERMS ALREADY INTERNALIZED  *
3334
 *****************************************************/
3335

3336
/*
3337
 * Assert (x == tt) for an internalization code x
3338
 */
3339
static void assert_internalization_code(context_t *ctx, int32_t x, bool tt) {
909✔
3340
  occ_t g;
3341
  literal_t l;
3342

3343
  assert(code_is_valid(x));
3344

3345
  if (code_is_eterm(x)) {
909✔
3346
    // normalize to assertion (g == true)
3347
    g = code2occ(x);
10✔
3348
    if (! tt) g = opposite_occ(g);
10✔
3349

3350
    // We must deal with 'true_occ/false_occ' separately
3351
    // since they may be used even if there's no actual egraph.
3352
    if (g == false_occ) {
10✔
3353
      longjmp(ctx->env, TRIVIALLY_UNSAT);
4✔
3354
    } else if (g != true_occ) {
6✔
3355
      assert(ctx->egraph != NULL);
3356
      if (!context_quant_enabled(ctx) || egraph_is_at_base_level(ctx->egraph)) {
×
3357
        egraph_assert_axiom(ctx->egraph, g);
×
3358
      } else {
3359
        l = egraph_make_eq(ctx->egraph, g, true_occ);
×
3360
        add_unit_clause(ctx->core, l);
×
3361
      }
3362
    }
3363
  } else {
3364
    l = code2literal(x);
899✔
3365
    if (! tt) l = not(l);
899✔
3366
    add_unit_clause(ctx->core, l);
899✔
3367
  }
3368
}
905✔
3369

3370
/*
3371
 * Assert t == true where t is a term that's already mapped
3372
 * either to a literal or to an egraph occurrence.
3373
 * - t must be a root in the internalization table
3374
 */
3375
static void assert_toplevel_intern(context_t *ctx, term_t t) {
738✔
3376
  int32_t code;
3377
  bool tt;
3378

3379
  assert(is_boolean_term(ctx->terms, t) &&
3380
         intern_tbl_is_root(&ctx->intern, t) &&
3381
         intern_tbl_root_is_mapped(&ctx->intern, t));
3382

3383
  tt = is_pos_term(t);
738✔
3384
  t = unsigned_term(t);
738✔
3385
  code = intern_tbl_map_of_root(&ctx->intern, t);
738✔
3386

3387
  assert_internalization_code(ctx, code, tt);
738✔
3388
}
738✔
3389

3390

3391

3392

3393

3394

3395

3396
/********************************
3397
 *   ARITHMETIC SUBSTITUTIONS   *
3398
 *******************************/
3399

3400
/*
3401
 * TODO: improve this in the integer case:
3402
 * - all_int is based on p's type in the term table and does
3403
 *   not take the context's substitutions into account.
3404
 * - integral_poly_after_div requires all coefficients
3405
 *   to be integer. This could be generalized to polynomials
3406
 *   with integer variables and rational coefficients.
3407
 */
3408

3409
/*
3410
 * Check whether term t can be eliminated by an arithmetic substitution
3411
 * - t's root must be uninterpreted and not internalized yet
3412
 */
3413
static bool is_elimination_candidate(context_t *ctx, term_t t) {
2,742✔
3414
  term_t r;
3415

3416
  r = intern_tbl_get_root(&ctx->intern, t);
2,742✔
3417
  return intern_tbl_root_is_free(&ctx->intern, r);
2,742✔
3418
}
3419

3420

3421
/*
3422
 * Replace every variable of t by the root of t in the internalization table
3423
 * - the result is stored in buffer
3424
 */
3425
static void apply_renaming_to_poly(context_t *ctx, polynomial_t *p,  poly_buffer_t *buffer) {
544✔
3426
  uint32_t i, n;
3427
  term_t t;
3428

3429
  reset_poly_buffer(buffer);
544✔
3430

3431
  assert(poly_buffer_is_zero(buffer));
3432

3433
  n = p->nterms;
544✔
3434
  for (i=0; i<n; i++) {
2,599✔
3435
    t = p->mono[i].var;
2,055✔
3436
    if (t == const_idx) {
2,055✔
3437
      poly_buffer_add_const(buffer, &p->mono[i].coeff);
180✔
3438
    } else {
3439
      // replace t by its root
3440
      t = intern_tbl_get_root(&ctx->intern, t);
1,875✔
3441
      poly_buffer_addmul_term(ctx->terms, buffer, t, &p->mono[i].coeff);
1,875✔
3442
    }
3443
  }
3444

3445
  normalize_poly_buffer(buffer);
544✔
3446
}
544✔
3447

3448

3449
/*
3450
 * Auxiliary function: check whether p/a is an integral polynomial
3451
 * assuming all variables and coefficients of p are integer.
3452
 * - check whether all coefficients are multiple of a
3453
 * - a must be non-zero
3454
 */
3455
static bool integralpoly_after_div(poly_buffer_t *buffer, rational_t *a) {
318✔
3456
  uint32_t i, n;
3457

3458
  if (q_is_one(a) || q_is_minus_one(a)) {
318✔
3459
    return true;
265✔
3460
  }
3461

3462
  n = buffer->nterms;
53✔
3463
  for (i=0; i<n; i++) {
64✔
3464
    if (! q_divides(a, &buffer->mono[i].coeff)) return false;
63✔
3465
  }
3466
  return true;
1✔
3467
}
3468

3469

3470
/*
3471
 * Check whether a top-level assertion (p == 0) can be
3472
 * rewritten (t == q) where t is not internalized yet.
3473
 * - all_int is true if p is an integer polynomial (i.e.,
3474
 *   all coefficients and all terms of p are integer).
3475
 * - p = input polynomial
3476
 * - return t or null_term if no adequate t is found
3477
 */
3478
static term_t try_poly_substitution(context_t *ctx, poly_buffer_t *buffer, bool all_int) {
544✔
3479
  uint32_t i, n;
3480
  term_t t;
3481

3482
  // check for a free variable in buffer
3483
  n = buffer->nterms;
544✔
3484
  for (i=0; i<n; i++) {
1,128✔
3485
    t = buffer->mono[i].var;
1,049✔
3486
    if (t != const_idx && is_elimination_candidate(ctx, t)) {
1,049✔
3487
      if (in_real_class(ctx, t) ||
518✔
3488
          (all_int && integralpoly_after_div(buffer, &buffer->mono[i].coeff))) {
318✔
3489
        // t is candidate for elimination
3490
        return t;
465✔
3491
      }
3492
    }
3493
  }
3494

3495
  return NULL_TERM;
79✔
3496
}
3497

3498

3499
/*
3500
 * Build polynomial - p/a + x in the context's aux_poly buffer
3501
 * where a = coefficient of x in p
3502
 * - x must occur in p
3503
 */
3504
static polynomial_t *build_poly_substitution(context_t *ctx, poly_buffer_t *buffer, term_t x) {
465✔
3505
  polynomial_t *q;
3506
  monomial_t *mono;
3507
  uint32_t i, n;
3508
  term_t y;
3509
  rational_t *a;
3510

3511
  n = buffer->nterms;
465✔
3512

3513
  // first get coefficient of x in buffer
3514
  a = NULL; // otherwise GCC complains
465✔
3515
  for (i=0; i<n; i++) {
2,283✔
3516
    y = buffer->mono[i].var;
1,818✔
3517
    if (y == x) {
1,818✔
3518
      a = &buffer->mono[i].coeff;
465✔
3519
    }
3520
  }
3521
  assert(a != NULL && n > 0);
3522

3523
  q = context_get_aux_poly(ctx, n);
465✔
3524
  q->nterms = n-1;
465✔
3525
  mono = q->mono;
465✔
3526

3527
  // compute - buffer/a (but skip monomial a.x)
3528
  for (i=0; i<n; i++) {
2,283✔
3529
    y = buffer->mono[i].var;
1,818✔
3530
    if (y != x) {
1,818✔
3531
      mono->var = y;
1,353✔
3532
      q_set_neg(&mono->coeff, &buffer->mono[i].coeff);
1,353✔
3533
      q_div(&mono->coeff, a);
1,353✔
3534
      mono ++;
1,353✔
3535
    }
3536
  }
3537

3538
  // end marker
3539
  mono->var = max_idx;
465✔
3540

3541
  return q;
465✔
3542
}
3543

3544

3545

3546
/*
3547
 * Try to eliminate a toplevel equality (p == 0) by variable substitution:
3548
 * - i.e., try to rewrite p == 0 into (x - q) == 0 where x is a free variable
3549
 *   then store the substitution x --> q in the internalization table.
3550
 * - all_int is true if p is an integer polynomial (i.e., all variables and all
3551
 *   coefficients of p are integer)
3552
 *
3553
 * - return true if the elimination succeeds
3554
 * - return false otherwise
3555
 */
3556
static bool try_arithvar_elim(context_t *ctx, polynomial_t *p, bool all_int) {
544✔
3557
  poly_buffer_t *buffer;
3558
  polynomial_t *q;
3559
  uint32_t i, n;
3560
  term_t t, u, r;
3561
  thvar_t x;
3562

3563
  /*
3564
   * First pass: internalize every term of p that's not a variable
3565
   * - we do that first to avoid circular substitutions (occurs-check)
3566
   */
3567
  n = p->nterms;
544✔
3568
  for (i=0; i<n; i++) {
2,599✔
3569
    t = p->mono[i].var;
2,055✔
3570
    if (t != const_idx && ! is_elimination_candidate(ctx, t)) {
2,055✔
3571
      (void) internalize_to_arith(ctx, t);
599✔
3572
    }
3573
  }
3574

3575

3576
  /*
3577
   * Apply variable renaming: this is to avoid circularities
3578
   * if p is of the form ... + a x + ... + b y + ...
3579
   * where both x and y are variables in the same class (i.e.,
3580
   * both are elimination candidates).
3581
   */
3582
  buffer = context_get_poly_buffer(ctx);
544✔
3583
  apply_renaming_to_poly(ctx, p, buffer);
544✔
3584

3585
  /*
3586
   * Search for a variable to substitute
3587
   */
3588
  u = try_poly_substitution(ctx, buffer, all_int);
544✔
3589
  if (u == NULL_TERM) {
544✔
3590
    return false; // no substitution found
79✔
3591
  }
3592

3593
  /*
3594
   * buffer is of the form a.u + p0, we rewrite (buffer == 0) to (u == q)
3595
   * where q = -1/a * p0
3596
   */
3597
  q = build_poly_substitution(ctx, buffer, u); // q is in ctx->aux_poly
465✔
3598

3599
  // convert q to a theory variable in the arithmetic solver
3600
  x = map_poly_to_arith(ctx, q);
465✔
3601

3602
  // map u (and its root) to x
3603
  r = intern_tbl_get_root(&ctx->intern, u);
465✔
3604
  assert(intern_tbl_root_is_free(&ctx->intern, r) && is_pos_term(r));
3605
  intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
465✔
3606

3607
#if TRACE
3608
  printf("---> toplevel equality: ");
3609
  print_polynomial(stdout, p);
3610
  printf(" == 0\n");
3611
  printf("     simplified to ");
3612
  print_term(stdout, ctx->terms, u);
3613
  printf(" := ");
3614
  print_polynomial(stdout, q);
3615
  printf("\n");
3616
#endif
3617

3618
  return true;
465✔
3619
}
3620

3621

3622

3623

3624

3625

3626

3627
/******************************************************
3628
 *  TOP-LEVEL ARITHMETIC EQUALITIES OR DISEQUALITIES  *
3629
 *****************************************************/
3630

3631
static void assert_arith_bineq(context_t *ctx, term_t t1, term_t t2, bool tt);
3632

3633
/*
3634
 * Top-level equality: t == (ite c u1 u2) between arithmetic terms
3635
 * - apply lift-if rule: (t == (ite c u1 u2)) --> (ite c (t == u1) (t == u2)
3636
 * - if tt is true: assert the equality otherwise assert the disequality
3637
 */
3638
static void assert_ite_arith_bineq(context_t *ctx, composite_term_t *ite, term_t t, bool tt) {
451✔
3639
  literal_t l1, l2, l3;
3640

3641
  assert(ite->arity == 3);
3642

3643
  l1 = internalize_to_literal(ctx, ite->arg[0]);
451✔
3644
  if (l1 == true_literal) {
451✔
3645
    // (ite c u1 u2) --> u1
3646
    assert_arith_bineq(ctx, ite->arg[1], t, tt);
3✔
3647
  } else if (l1 == false_literal) {
448✔
3648
    // (ite c u1 u2) --> u2
3649
    assert_arith_bineq(ctx, ite->arg[2], t, tt);
15✔
3650
  } else {
3651
    l2 = map_arith_bineq(ctx, ite->arg[1], t); // (u1 == t)
433✔
3652
    l3 = map_arith_bineq(ctx, ite->arg[2], t); // (u2 == t)
433✔
3653
    assert_ite(&ctx->gate_manager, l1, l2, l3, tt);
433✔
3654
  }
3655
}
451✔
3656

3657

3658
/*
3659
 * Try substitution t1 := t2
3660
 * - both are arithmetic terms and roots in the internalization table
3661
 */
3662
static void try_arithvar_bineq_elim(context_t *ctx, term_t t1, term_t t2) {
164✔
3663
  intern_tbl_t *intern;
3664
  thvar_t x, y;
3665
  int32_t code;
3666

3667
  assert(is_pos_term(t1) && intern_tbl_is_root(&ctx->intern, t1) &&
3668
         intern_tbl_root_is_free(&ctx->intern, t1));
3669

3670
  intern = &ctx->intern;
164✔
3671

3672
  if (is_constant_term(ctx->terms, t2)) {
164✔
3673
    if (intern_tbl_valid_const_subst(intern, t1, t2)) {
2✔
3674
      intern_tbl_add_subst(intern, t1, t2);
2✔
3675
    } else {
3676
      // unsat by type incompatibility
3677
      longjmp(ctx->env, TRIVIALLY_UNSAT);
×
3678
    }
3679

3680
  } else if (intern_tbl_sound_subst(intern, t1, t2)) {
162✔
3681
    /*
3682
     * Internalize t2 to x.
3683
     * If t1 is still free after that, we can map t1 to x
3684
     * otherwise, t2 depends on t1 so we can't substitute.
3685
     */
3686
    x = internalize_to_arith(ctx, t2);
161✔
3687
    if (intern_tbl_root_is_free(intern, t1)) {
161✔
3688
      intern_tbl_map_root(&ctx->intern, t1, thvar2code(x));
2✔
3689
    } else {
3690
      assert(intern_tbl_root_is_mapped(intern, t1));
3691
      code = intern_tbl_map_of_root(intern, t1);
159✔
3692
      y = translate_code_to_arith(ctx, code);
159✔
3693

3694
      // assert x == y in the arithmetic solver
3695
      ctx->arith.assert_vareq_axiom(ctx->arith_solver, x, y, true);
159✔
3696
    }
3697
  } else {
3698
    x = internalize_to_arith(ctx, t1);
1✔
3699
    y = internalize_to_arith(ctx, t2);
1✔
3700
    ctx->arith.assert_vareq_axiom(ctx->arith_solver, x, y, true);
1✔
3701
  }
3702
}
164✔
3703

3704

3705
/*
3706
 * Top-level arithmetic equality t1 == t2:
3707
 * - if tt is true: assert t1 == t2 otherwise assert (t1 != t2)
3708
 * - both t1 and t2 are arithmetic terms and roots in the internalization table
3709
 * - the equality (t1 == t2) is not reducible by if-then-else flattening
3710
 */
3711
static void assert_arith_bineq_aux(context_t *ctx, term_t t1, term_t t2, bool tt) {
3,335✔
3712
  term_table_t *terms;
3713
  intern_tbl_t *intern;;
3714
  bool free1, free2;
3715
  thvar_t x, y;
3716
  occ_t u, v;
3717

3718
  assert(is_pos_term(t1) && intern_tbl_is_root(&ctx->intern, t1) &&
3719
         is_pos_term(t2) && intern_tbl_is_root(&ctx->intern, t2));
3720

3721
  terms = ctx->terms;
3,335✔
3722
  if (is_ite_term(terms, t1) && !is_ite_term(terms, t2)) {
3,335✔
3723
    assert_ite_arith_bineq(ctx, ite_term_desc(terms, t1), t2, tt);
112✔
3724
    return;
112✔
3725
  }
3726

3727
  if (is_ite_term(terms, t2) && !is_ite_term(terms, t1)) {
3,223✔
3728
    assert_ite_arith_bineq(ctx, ite_term_desc(terms, t2), t1, tt);
339✔
3729
    return;
339✔
3730
  }
3731

3732
  if (tt && context_arith_elim_enabled(ctx)) {
2,884✔
3733
    /*
3734
     * try a substitution
3735
     */
3736
    intern = &ctx->intern;
340✔
3737
    free1 = intern_tbl_root_is_free(intern, t1);
340✔
3738
    free2 = intern_tbl_root_is_free(intern, t2);
340✔
3739

3740
    if (free1 && free2) {
340✔
3741
      if (t1 != t2) {
1✔
3742
        intern_tbl_merge_classes(intern, t1, t2);
1✔
3743
      }
3744
      return;
1✔
3745
    }
3746

3747
    if (free1) {
339✔
3748
      try_arithvar_bineq_elim(ctx, t1, t2);
162✔
3749
      return;
162✔
3750
    }
3751

3752
    if (free2) {
177✔
3753
      try_arithvar_bineq_elim(ctx, t2, t1);
2✔
3754
      return;
2✔
3755
    }
3756

3757
  }
3758

3759
  /*
3760
   * Default: assert the constraint in the egraph or in the arithmetic
3761
   * solver if there's no egraph.
3762
   */
3763
  if (context_has_egraph(ctx)) {
2,719✔
3764
    u = internalize_to_eterm(ctx, t1);
1,658✔
3765
    v = internalize_to_eterm(ctx, t2);
1,658✔
3766
    if (!context_quant_enabled(ctx) || egraph_is_at_base_level(ctx->egraph)) {
1,658✔
3767
      if (tt) {
1,658✔
3768
        egraph_assert_eq_axiom(ctx->egraph, u, v);
162✔
3769
      } else {
3770
        egraph_assert_diseq_axiom(ctx->egraph, u, v);
1,496✔
3771
      }
3772
    } else {
3773
      literal_t l = egraph_make_eq(ctx->egraph, u, v);
×
3774
      if (tt) {
×
3775
        add_unit_clause(ctx->core, l);
×
3776
      } else {
3777
        add_unit_clause(ctx->core, not(l));
×
3778
      }
3779
    }
3780
  } else {
3781
    x = internalize_to_arith(ctx, t1);
1,061✔
3782
    y = internalize_to_arith(ctx, t2);
1,061✔
3783
    ctx->arith.assert_vareq_axiom(ctx->arith_solver, x, y, tt);
1,061✔
3784
  }
3785
}
3786

3787

3788

3789

3790
/*****************************************************
3791
 *  INTERNALIZATION OF TOP-LEVEL ATOMS AND FORMULAS  *
3792
 ****************************************************/
3793

3794
/*
3795
 * Recursive function: assert (t == tt) for a boolean term t
3796
 * - this is used when a toplevel formula simplifies to t
3797
 *   For example (ite c t u) --> t if c is true.
3798
 * - t is not necessarily a root in the internalization table
3799
 */
3800
static void assert_term(context_t *ctx, term_t t, bool tt);
3801

3802

3803
/*
3804
 * Top-level predicate: (p t_1 .. t_n)
3805
 * - if tt is true: assert (p t_1 ... t_n)
3806
 * - if tt is false: assert (not (p t_1 ... t_n))
3807
 */
3808
static void assert_toplevel_apply(context_t *ctx, composite_term_t *app, bool tt) {
252✔
3809
  occ_t *a;
3810
  uint32_t i, n;
3811

3812
  assert(app->arity > 0);
3813

3814
  n = app->arity;
252✔
3815

3816
  check_high_order_support(ctx, app->arg+1, n-1);
252✔
3817

3818
  a = alloc_istack_array(&ctx->istack, n);
252✔
3819
  for (i=0; i<n; i++) {
1,030✔
3820
    a[i] = internalize_to_eterm(ctx, app->arg[i]);
778✔
3821
  }
3822

3823
  if (!context_quant_enabled(ctx) || egraph_is_at_base_level(ctx->egraph)) {
252✔
3824
    if (tt) {
242✔
3825
      egraph_assert_pred_axiom(ctx->egraph, a[0], n-1, a+1);
214✔
3826
    } else {
3827
      egraph_assert_notpred_axiom(ctx->egraph, a[0], n-1, a+1);
28✔
3828
    }
3829
  } else {
3830
    literal_t l = egraph_make_pred(ctx->egraph, a[0], n-1, a+1);
10✔
3831
    if (tt) {
10✔
3832
      add_unit_clause(ctx->core, l);
3✔
3833
    } else {
3834
      add_unit_clause(ctx->core, not(l));
7✔
3835
    }
3836
  }
3837

3838
  free_istack_array(&ctx->istack, a);
252✔
3839
}
252✔
3840

3841

3842
/*
3843
 * Top-level (select i t)
3844
 * - if tt is true: assert (select i t)
3845
 * - if tt is false: assert (not (select i t))
3846
 */
3847
static void assert_toplevel_select(context_t *ctx, select_term_t *select, bool tt) {
×
3848
  occ_t u;
3849

3850
  u = map_select_to_eterm(ctx, select, bool_type(ctx->types));
×
3851
  if (! tt) {
×
3852
    u = opposite_occ(u);
×
3853
  }
3854
  if (!context_quant_enabled(ctx) || egraph_is_at_base_level(ctx->egraph)) {
×
3855
    egraph_assert_axiom(ctx->egraph, u);
×
3856
  } else {
3857
    literal_t l = egraph_make_eq(ctx->egraph, u, true_occ);
×
3858
    add_unit_clause(ctx->core, l);
×
3859
  }
3860
}
×
3861

3862

3863
/*
3864
 * Top-level equality between Boolean terms
3865
 * - if tt is true, assert t1 == t2
3866
 * - if tt is false, assert t1 != t2
3867
 */
3868
static void assert_toplevel_iff(context_t *ctx, term_t t1, term_t t2, bool tt) {
2,739✔
3869
  term_t t;
3870
  literal_t l1, l2;
3871

3872
  /*
3873
   * Apply substitution then try flattening
3874
   */
3875
  t1 = intern_tbl_get_root(&ctx->intern, t1);
2,739✔
3876
  t2 = intern_tbl_get_root(&ctx->intern, t2);
2,739✔
3877
  if (t1 == t2) {
2,739✔
3878
    // (eq t1 t2) is true
3879
    if (!tt) {
×
3880
      longjmp(ctx->env, TRIVIALLY_UNSAT);
×
3881
    }
3882
  }
3883
  // try simplification
3884
  t = simplify_bool_eq(ctx, t1, t2);
2,739✔
3885
  if (t != NULL_TERM) {
2,739✔
3886
    // (eq t1 t2) is equivalent to t
3887
    assert_term(ctx, t, tt) ;
17✔
3888
  } else {
3889
    // no simplification
3890
    l1 = internalize_to_literal(ctx, t1);
2,722✔
3891
    l2 = internalize_to_literal(ctx, t2);
2,722✔
3892
    assert_iff(&ctx->gate_manager, l1, l2, tt);
2,722✔
3893

3894
#if 0
3895
    if (tt) {
3896
      printf("top assert: (eq ");
3897
      print_literal(stdout, l1);
3898
      printf(" ");
3899
      print_literal(stdout, l2);
3900
      printf(")\n");
3901
    } else {
3902
      printf("top assert: (xor ");
3903
      print_literal(stdout, l1);
3904
      printf(" ");
3905
      print_literal(stdout, l2);
3906
      printf(")\n");
3907
    }
3908
#endif
3909
  }
3910
}
2,739✔
3911

3912
/*
3913
 * Top-level equality assertion (eq t1 t2):
3914
 * - if tt is true, assert (t1 == t2)
3915
 *   if tt is false, assert (t1 != t2)
3916
 */
3917
static void assert_toplevel_eq(context_t *ctx, composite_term_t *eq, bool tt) {
5,155✔
3918
  occ_t u1, u2;
3919

3920
  assert(eq->arity == 2);
3921

3922
  if (is_boolean_term(ctx->terms, eq->arg[0])) {
5,155✔
3923
    assert(is_boolean_term(ctx->terms, eq->arg[1]));
3924
    assert_toplevel_iff(ctx, eq->arg[0], eq->arg[1], tt);
2,739✔
3925
  } else {
3926
    // filter out high-order terms. It's enough to check eq->arg[0]
3927
    check_high_order_support(ctx, eq->arg, 1);
2,416✔
3928

3929
    u1 = internalize_to_eterm(ctx, eq->arg[0]);
2,415✔
3930
    u2 = internalize_to_eterm(ctx, eq->arg[1]);
2,415✔
3931
    if (!context_quant_enabled(ctx) || egraph_is_at_base_level(ctx->egraph)) {
2,414✔
3932
      if (tt) {
2,400✔
3933
        egraph_assert_eq_axiom(ctx->egraph, u1, u2);
1,323✔
3934
      } else {
3935
        egraph_assert_diseq_axiom(ctx->egraph, u1, u2);
1,077✔
3936
      }
3937
    } else {
3938
      literal_t l = egraph_make_eq(ctx->egraph, u1, u2);
14✔
3939
      if (tt) {
14✔
3940
        add_unit_clause(ctx->core, l);
9✔
3941
      } else {
3942
        add_unit_clause(ctx->core, not(l));
5✔
3943
      }
3944
    }
3945
  }
3946
}
5,153✔
3947

3948

3949
/*
3950
 * Assertion (distinct a[0] .... a[n-1]) == tt
3951
 * when a[0] ... a[n-1] are arithmetic variables.
3952
 */
3953
static void assert_arith_distinct(context_t *ctx, uint32_t n, thvar_t *a, bool tt) {
155✔
3954
  literal_t l;
3955

3956
  l = make_arith_distinct(ctx, n, a);
155✔
3957
  if (! tt) {
155✔
3958
    l = not(l);
4✔
3959
  }
3960
  add_unit_clause(ctx->core, l);
155✔
3961
}
155✔
3962

3963

3964
/*
3965
 * Assertion (distinct a[0] .... a[n-1]) == tt
3966
 * when a[0] ... a[n-1] are bitvector variables.
3967
 */
3968
static void assert_bv_distinct(context_t *ctx, uint32_t n, thvar_t *a, bool tt) {
2✔
3969
  literal_t l;
3970

3971
  l = make_bv_distinct(ctx, n, a);
2✔
3972
  if (! tt) {
2✔
3973
    l = not(l);
1✔
3974
  }
3975
  add_unit_clause(ctx->core, l);
2✔
3976
}
2✔
3977

3978

3979
/*
3980
 * Generic (distinct t1 .. t_n)
3981
 * - if tt: assert (distinct t_1 ... t_n)
3982
 * - otherwise: assert (not (distinct t_1 ... t_n))
3983
 */
3984
static void assert_toplevel_distinct(context_t *ctx, composite_term_t *distinct, bool tt) {
173✔
3985
  uint32_t i, n;
3986
  int32_t *a;
3987

3988
  n = distinct->arity;
173✔
3989
  assert(n >= 2);
3990

3991
  a = alloc_istack_array(&ctx->istack, n);
173✔
3992

3993
  if (context_has_egraph(ctx)) {
173✔
3994
    // fail if arguments have function types and we don't
3995
    // have a function/array solver
3996
    check_high_order_support(ctx, distinct->arg, 1);
16✔
3997

3998
    // forward the assertion to the egraph
3999
    for (i=0; i<n; i++) {
69✔
4000
      a[i] = internalize_to_eterm(ctx, distinct->arg[i]);
55✔
4001
    }
4002

4003
    if (!context_quant_enabled(ctx) || egraph_is_at_base_level(ctx->egraph)) {
14✔
4004
      if (tt) {
14✔
4005
        egraph_assert_distinct_axiom(ctx->egraph, n, a);
10✔
4006
      } else {
4007
        egraph_assert_notdistinct_axiom(ctx->egraph, n, a);
4✔
4008
      }
4009
    } else {
4010
      literal_t l = egraph_make_distinct(ctx->egraph, n, a);
×
4011
      if (tt) {
×
4012
        add_unit_clause(ctx->core, l);
×
4013
      } else {
4014
        add_unit_clause(ctx->core, not(l));
×
4015
      }
4016
    }
4017

4018
  } else if (is_arithmetic_term(ctx->terms, distinct->arg[0])) {
157✔
4019
    // translate to arithmetic then assert
4020
    for (i=0; i<n; i++) {
3,922✔
4021
      a[i] = internalize_to_arith(ctx, distinct->arg[i]);
3,767✔
4022
    }
4023
    assert_arith_distinct(ctx, n, a, tt);
155✔
4024

4025
  } else if (is_bitvector_term(ctx->terms, distinct->arg[0])) {
2✔
4026
    // translate to bitvectors then assert
4027
    for (i=0; i<n; i++) {
13✔
4028
      a[i] = internalize_to_bv(ctx, distinct->arg[i]);
11✔
4029
    }
4030
    assert_bv_distinct(ctx, n, a, tt);
2✔
4031

4032
  } else {
4033
    longjmp(ctx->env, uf_error_code(ctx, distinct->arg[0]));
×
4034
  }
4035

4036
  free_istack_array(&ctx->istack, a);
171✔
4037
}
171✔
4038

4039

4040

4041
/*
4042
 * Top-level arithmetic equality t1 == u1:
4043
 * - t1 and u1 are arithmetic terms
4044
 * - if tt is true assert (t1 == u1) otherwise assert (t1 != u1)
4045
 * - apply lift-if simplifications and variable elimination
4046
 */
4047
static void assert_arith_bineq(context_t *ctx, term_t t1, term_t u1, bool tt) {
3,408✔
4048
  ivector_t *v;
4049
  int32_t *a;
4050
  uint32_t i, n;
4051
  term_t t2, u2;
4052

4053
  /*
4054
   * Apply substitutions then try if-then-else flattening
4055
   */
4056
  t1 = intern_tbl_get_root(&ctx->intern, t1);
3,408✔
4057
  u1 = intern_tbl_get_root(&ctx->intern, u1);
3,408✔
4058

4059
  v = &ctx->aux_vector;
3,408✔
4060
  assert(v->size == 0);
4061
  t2 = flatten_ite_equality(ctx, v, t1, u1);
3,408✔
4062
  u2 = flatten_ite_equality(ctx, v, u1, t2);
3,408✔
4063

4064
  /*
4065
   * (t1 == u1) is now equivalent to
4066
   * the conjunction of (t2 == u2) and all the terms in v
4067
   */
4068
  n = v->size;
3,408✔
4069
  if (n == 0) {
3,408✔
4070
    /*
4071
     * The simple flattening did not work.
4072
     */
4073
    assert(t1 == t2 && u1 == u2);
4074
    assert_arith_bineq_aux(ctx, t2, u2, tt);
3,322✔
4075

4076
  } else {
4077
    // make a copy of v[0 ... n-1]
4078
    // and reserve a[n] for the literal (eq t2 u2)
4079
    a = alloc_istack_array(&ctx->istack, n+1);
86✔
4080
    for (i=0; i<n; i++) {
1,531✔
4081
      a[i] = v->data[i];
1,445✔
4082
    }
4083
    ivector_reset(v);
86✔
4084

4085
    if (tt) {
86✔
4086
      // assert (and a[0] ... a[n-1] (eq t2 u2))
4087
      for (i=0; i<n; i++) {
340✔
4088
        assert_term(ctx, a[i], true);
327✔
4089
      }
4090

4091
      /*
4092
       * The assertions a[0] ... a[n-1] may have
4093
       * caused roots to be merged. So we must
4094
       * apply term substitution again.
4095
       */
4096
      t2 = intern_tbl_get_root(&ctx->intern, t2);
13✔
4097
      u2 = intern_tbl_get_root(&ctx->intern, u2);
13✔
4098
      assert_arith_bineq_aux(ctx, t2, u2, true);
13✔
4099

4100
    } else {
4101
      // assert (or (not a[0]) ... (not a[n-1]) (not (eq t2 u2)))
4102
      for (i=0; i<n; i++) {
1,191✔
4103
        a[i] = not(internalize_to_literal(ctx, a[i]));
1,118✔
4104
      }
4105
      a[n] = not(map_arith_bineq_aux(ctx, t2, u2));
73✔
4106

4107
      add_clause(ctx->core, n+1, a);
73✔
4108
    }
4109

4110
    free_istack_array(&ctx->istack, a);
86✔
4111
  }
4112
}
3,408✔
4113

4114

4115
/*
4116
 * Top-level arithmetic assertion:
4117
 * - if tt is true, assert p == 0
4118
 * - if tt is false, assert p != 0
4119
 */
4120
static void assert_toplevel_poly_eq(context_t *ctx, polynomial_t *p, bool tt) {
1,273✔
4121
  uint32_t i, n;
4122
  thvar_t *a;
4123

4124
  n = p->nterms;
1,273✔
4125
  a = alloc_istack_array(&ctx->istack, n);;
1,273✔
4126
  // skip the constant if any
4127
  i = 0;
1,273✔
4128
  if (p->mono[0].var == const_idx) {
1,273✔
4129
    a[0] = null_thvar;
1,208✔
4130
    i ++;
1,208✔
4131
  }
4132

4133
  // deal with the non-constant monomials
4134
  while (i<n) {
3,928✔
4135
    a[i] = internalize_to_arith(ctx, p->mono[i].var);
2,655✔
4136
    i ++;
2,655✔
4137
  }
4138

4139
  // assertion
4140
  ctx->arith.assert_poly_eq_axiom(ctx->arith_solver, p, a, tt);
1,273✔
4141
  free_istack_array(&ctx->istack, a);
1,273✔
4142
}
1,273✔
4143

4144

4145

4146
/*
4147
 * Top-level arithmetic equality:
4148
 * - t is an arithmetic term
4149
 * - if tt is true, assert (t == 0)
4150
 * - otherwise, assert (t != 0)
4151
 */
4152
static void assert_toplevel_arith_eq(context_t *ctx, term_t t, bool tt) {
2,267✔
4153
  term_table_t *terms;
4154
  polynomial_t *p;
4155
  bool all_int;
4156
  thvar_t x;
4157

4158
  assert(is_arithmetic_term(ctx->terms, t));
4159

4160
  terms = ctx->terms;
2,267✔
4161
  if (tt && context_arith_elim_enabled(ctx) && term_kind(terms, t) == ARITH_POLY) {
2,267✔
4162
    /*
4163
     * Polynomial equality: a_1 t_1 + ... + a_n t_n = 0
4164
     * attempt to eliminate one of t_1 ... t_n
4165
     */
4166
    p = poly_term_desc(terms, t);
544✔
4167
    all_int = is_integer_term(terms, t);
544✔
4168
    if (try_arithvar_elim(ctx, p, all_int)) { // elimination worked
544✔
4169
      return;
465✔
4170
    }
4171
  }
4172

4173
  // default
4174
  if (term_kind(terms, t) == ARITH_POLY) {
1,802✔
4175
    assert_toplevel_poly_eq(ctx, poly_term_desc(terms, t), tt);
1,273✔
4176
  } else if (is_ite_term(terms, t)) {
529✔
4177
    assert_arith_bineq(ctx, t, zero_term, tt);
8✔
4178
  } else {
4179
    x = internalize_to_arith(ctx, t);
521✔
4180
    ctx->arith.assert_eq_axiom(ctx->arith_solver, x, tt);
520✔
4181
  }
4182
}
4183

4184

4185

4186
/*
4187
 * Top-level arithmetic assertion:
4188
 * - if tt is true, assert p >= 0
4189
 * - if tt is false, assert p < 0
4190
 */
4191
static void assert_toplevel_poly_geq(context_t *ctx, polynomial_t *p, bool tt) {
25,930✔
4192
  uint32_t i, n;
4193
  thvar_t *a;
4194

4195
  n = p->nterms;
25,930✔
4196
  a = alloc_istack_array(&ctx->istack, n);;
25,930✔
4197
  // skip the constant if any
4198
  i = 0;
25,930✔
4199
  if (p->mono[0].var == const_idx) {
25,930✔
4200
    a[0] = null_thvar;
25,104✔
4201
    i ++;
25,104✔
4202
  }
4203

4204
  // deal with the non-constant monomials
4205
  while (i<n) {
55,603✔
4206
    a[i] = internalize_to_arith(ctx, p->mono[i].var);
29,674✔
4207
    i ++;
29,673✔
4208
  }
4209

4210
  // assertion
4211
  ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, a, tt);
25,929✔
4212
  free_istack_array(&ctx->istack, a);
25,929✔
4213
}
25,929✔
4214

4215

4216

4217
/*
4218
 * Top-level arithmetic inequality:
4219
 * - t is an arithmetic term
4220
 * - if tt is true, assert (t >= 0)
4221
 * - if tt is false, assert (t < 0)
4222
 */
4223
static void assert_toplevel_arith_geq(context_t *ctx, term_t t, bool tt) {
27,855✔
4224
  term_table_t *terms;
4225
  thvar_t x;
4226

4227
  assert(is_arithmetic_term(ctx->terms, t));
4228

4229
  terms = ctx->terms;
27,855✔
4230
  if (term_kind(terms, t) == ARITH_POLY) {
27,855✔
4231
    assert_toplevel_poly_geq(ctx, poly_term_desc(terms, t), tt);
25,930✔
4232
  } else {
4233
    x = internalize_to_arith(ctx, t);
1,925✔
4234
    ctx->arith.assert_ge_axiom(ctx->arith_solver, x, tt);
1,925✔
4235
  }
4236
}
27,854✔
4237

4238

4239
/*
4240
 * Top-level binary equality: (eq t u)
4241
 * - both t and u are arithmetic terms
4242
 * - if tt is true, assert (t == u)
4243
 * - if tt is false, assert (t != u)
4244
 */
4245
static void assert_toplevel_arith_bineq(context_t *ctx, composite_term_t *eq, bool tt) {
3,382✔
4246
  assert(eq->arity == 2);
4247
  assert_arith_bineq(ctx, eq->arg[0], eq->arg[1], tt);
3,382✔
4248
}
3,382✔
4249

4250

4251

4252
/*
4253
 * Top-level (is_int t)
4254
 * - t is an arithmetic term
4255
 * - if tt is true, assert (t <= (floor t))
4256
 * - if tt is false, asssert (t > (floor t))
4257
 *
4258
 * NOTE: instead of asserting (t <= (floor t)) we could create a fresh
4259
 * integer variable z and assert (t = z).
4260
 */
4261
static void assert_toplevel_arith_is_int(context_t *ctx, term_t t, bool tt) {
×
4262
  polynomial_t *p;
4263
  thvar_t map[2];
4264
  thvar_t x, y;
4265

4266
  x = internalize_to_arith(ctx, t);
×
4267
  if (ctx->arith.arith_var_is_int(ctx->arith_solver, x)) {
×
4268
    if (!tt) {
×
4269
      longjmp(ctx->env, TRIVIALLY_UNSAT);
×
4270
    }
4271
  } else {
4272
    // x is not an integer variable
4273
    y = get_floor(ctx, x); // y := (floor x)
×
4274
    p = context_get_aux_poly(ctx, 3);
×
4275
    context_store_diff_poly(p, map, y, x); // (p, map) stores (y - x)
×
4276
    // assert either (p >= 0) --> (x <= floor(x))
4277
    // or (p < 0) --> (x > (floor x)
4278
    ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, tt);
×
4279
  }
4280
}
×
4281

4282

4283
/*
4284
 * Top-level (divides k t)
4285
 * - if tt is true, assert (t <= k * (div t k))
4286
 * - if tt is false, assert (t > k * (div t k))
4287
 *
4288
 * We assume (k != 0) since (divides 0 t) is rewritten to (t == 0) by
4289
 * the term manager.
4290
 *
4291
 * NOTE: instead of asserting (t <= k * (div t k)) we could create a fresh
4292
 * integer variable z and assert (t = k * z).
4293
 */
4294
static void assert_toplevel_arith_divides(context_t *ctx, composite_term_t *divides, bool tt) {
×
4295
  rational_t k;
4296
  polynomial_t *p;
4297
  thvar_t map[2];
4298
  thvar_t x, y;
4299
  term_t d;
4300

4301
  assert(divides->arity == 2);
4302

4303
  d = divides->arg[0];
×
4304
  if (term_kind(ctx->terms, d) == ARITH_CONSTANT) {
×
4305
    // copy the divider
4306
    q_init(&k);
×
4307
    q_set(&k, rational_term_desc(ctx->terms, d));
×
4308
    assert(q_is_nonzero(&k));
4309

4310
    x = internalize_to_arith(ctx, divides->arg[1]);
×
4311
    y = get_div(ctx, x, &k);  // y := (div x k);
×
4312
    p = context_get_aux_poly(ctx, 3);
×
4313
    context_store_divides_constraint(p, map, x, y, &k); // p is (- x + k * y)
×
4314

4315
    // if tt, assert (p >= 0) <=> x <= k * y
4316
    // if not tt, assert (p < 0) <=> x > k * y
4317
    ctx->arith.assert_poly_ge_axiom(ctx->arith_solver, p, map, tt);
×
4318

4319
    q_clear(&k);
×
4320
  } else {
4321
    // not a constant divider: not supported
4322
    longjmp(ctx->env, FORMULA_NOT_LINEAR);
×
4323
  }
4324
}
×
4325

4326

4327

4328

4329

4330

4331
/*
4332
 * Top-level conditional
4333
 * - c = conditional descriptor
4334
 * - if tt is true: assert c otherwise assert not c
4335
 *
4336
 * - c->nconds = number of clauses in the conditional
4337
 * - for each clause i: c->pair[i] = <cond, val>
4338
 * - c->defval = default value
4339
 */
4340
static void assert_toplevel_conditional(context_t *ctx, conditional_t *c, bool tt) {
13✔
4341
  uint32_t i, n;
4342
  literal_t *a;
4343
  literal_t l;
4344
  bool all_false;
4345
  term_t t;
4346

4347
#if 0
4348
  printf("---> toplevel conditional\n");
4349
#endif
4350

4351
  t = simplify_conditional(ctx, c);
13✔
4352
  if (t != NULL_TERM) {
13✔
4353
    assert_term(ctx, t, tt);
2✔
4354
    return;
2✔
4355
  }
4356

4357
  n = c->nconds;
11✔
4358
  a = alloc_istack_array(&ctx->istack, n + 1);
11✔
4359

4360
  all_false = true;
11✔
4361
  for (i=0; i<n; i++) {
72✔
4362
    // a[i] = condition for pair[i]
4363
    a[i] = internalize_to_literal(ctx, c->pair[i].cond);
62✔
4364
    if (a[i] == true_literal) {
62✔
4365
      // if a[i] is true, all other conditions must be false
4366
      assert_term(ctx, c->pair[i].val, tt);
1✔
4367
      goto done;
1✔
4368
    }
4369
    if (a[i] != false_literal) {
61✔
4370
      // l = value for pair[i]
4371
      l = signed_literal(internalize_to_literal(ctx, c->pair[i].val), tt);
58✔
4372
      add_binary_clause(ctx->core, not(a[i]), l); // a[i] => v[i]
58✔
4373
      all_false = false;
58✔
4374
    }
4375
  }
4376

4377
  if (all_false) {
10✔
4378
    // all a[i]s are false: no need for a clause
4379
    assert_term(ctx, c->defval, tt);
1✔
4380
    goto done;
1✔
4381
  }
4382

4383
  // last clause: (a[0] \/ .... \/ a[n] \/ +/-defval)
4384
  a[n] = signed_literal(internalize_to_literal(ctx, c->defval), tt);
9✔
4385
  add_clause(ctx->core, n+1, a);
9✔
4386

4387
  // cleanup
4388
 done:
11✔
4389
  free_istack_array(&ctx->istack, a);
11✔
4390
}
4391

4392

4393

4394
/*
4395
 * Top-level boolean if-then-else (ite c t1 t2)
4396
 * - if tt is true: assert (ite c t1 t2)
4397
 * - if tt is false: assert (not (ite c t1 t2))
4398
 */
4399
static void assert_toplevel_ite(context_t *ctx, composite_term_t *ite, bool tt) {
70✔
4400
  conditional_t *d;
4401
  literal_t l1, l2, l3;
4402

4403
  assert(ite->arity == 3);
4404

4405
  // high-order ite should work. See map_ite_to_eterm
4406

4407
  d = context_make_conditional(ctx, ite);
70✔
4408
  if (d != NULL) {
70✔
4409
    assert_toplevel_conditional(ctx, d, tt);
13✔
4410
    context_free_conditional(ctx, d);
13✔
4411
    return;
13✔
4412
  }
4413

4414
  l1 = internalize_to_literal(ctx, ite->arg[0]);
57✔
4415
  if (l1 == true_literal) {
57✔
4416
    assert_term(ctx, ite->arg[1], tt);
5✔
4417
  } else if (l1 == false_literal) {
52✔
4418
    assert_term(ctx, ite->arg[2], tt);
2✔
4419
  } else {
4420
    l2 = internalize_to_literal(ctx, ite->arg[1]);
50✔
4421
    l3 = internalize_to_literal(ctx, ite->arg[2]);
50✔
4422
    assert_ite(&ctx->gate_manager, l1, l2, l3, tt);
50✔
4423
  }
4424
}
4425

4426

4427
/*
4428
 * Top-level (or t1 ... t_n)
4429
 * - it tt is true: add a clause
4430
 * - it tt is false: assert (not t1) ... (not t_n)
4431
 */
4432
static void assert_toplevel_or(context_t *ctx, composite_term_t *or, bool tt) {
42,475✔
4433
  ivector_t *v;
4434
  int32_t *a;
4435
  uint32_t i, n;
4436

4437
  if (tt) {
42,475✔
4438
    if (context_flatten_or_enabled(ctx)) {
42,459✔
4439
      // Flatten into vector v
4440
      v = &ctx->aux_vector;
14,523✔
4441
      assert(v->size == 0);
4442
      flatten_or_term(ctx, v, or);
14,523✔
4443

4444
      // if v contains a true_term, ignore the clause
4445
      n = v->size;
14,523✔
4446
      if (disjunct_is_true(ctx, v->data, n)) {
14,523✔
4447
        ivector_reset(v);
807✔
4448
        return;
807✔
4449
      }
4450

4451
      // make a copy of v
4452
      a = alloc_istack_array(&ctx->istack, n);
13,716✔
4453
      for (i=0; i<n; i++) {
57,763✔
4454
        a[i] = v->data[i];
44,047✔
4455
      }
4456
      ivector_reset(v);
13,716✔
4457

4458
      for (i=0; i<n; i++) {
57,440✔
4459
        a[i] = internalize_to_literal(ctx, a[i]);
43,877✔
4460
        if (a[i] == true_literal) goto done;
43,877✔
4461
      }
4462

4463
    } else {
4464
      /*
4465
       * No flattening
4466
       */
4467
      n = or->arity;
27,936✔
4468
      if (disjunct_is_true(ctx, or->arg, n)) {
27,936✔
4469
        return;
2,503✔
4470
      }
4471

4472
      a = alloc_istack_array(&ctx->istack, n);
25,433✔
4473
      for (i=0; i<n; i++) {
143,590✔
4474
        a[i] = internalize_to_literal(ctx, or->arg[i]);
118,257✔
4475
        if (a[i] == true_literal) goto done;
118,257✔
4476
      }
4477
    }
4478

4479
    // assert (or a[0] ... a[n-1])
4480
    add_clause(ctx->core, n, a);
38,896✔
4481

4482
  done:
39,149✔
4483
    free_istack_array(&ctx->istack, a);
39,149✔
4484

4485
  } else {
4486
    /*
4487
     * Propagate to children:
4488
     *  (or t_0 ... t_n-1) is false
4489
     * so all children must be false too
4490
     */
4491
    n = or->arity;
16✔
4492
    for (i=0; i<n; i++) {
48✔
4493
      assert_term(ctx, or->arg[i], false);
32✔
4494
    }
4495
  }
4496

4497
}
4498

4499

4500
/*
4501
 * Top-level (xor t1 ... t_n) == tt
4502
 */
4503
static void assert_toplevel_xor(context_t *ctx, composite_term_t *xor, bool tt) {
7✔
4504
  int32_t *a;
4505
  uint32_t i, n;
4506

4507
  n = xor->arity;
7✔
4508
  a = alloc_istack_array(&ctx->istack, n);
7✔
4509
  for (i=0; i<n; i++) {
58✔
4510
    a[i] = internalize_to_literal(ctx, xor->arg[i]);
51✔
4511
  }
4512

4513
  assert_xor(&ctx->gate_manager, n, a, tt);
7✔
4514
  free_istack_array(&ctx->istack, a);
7✔
4515
}
7✔
4516

4517

4518

4519
/*
4520
 * Top-level bit select
4521
 */
4522
static void assert_toplevel_bit_select(context_t *ctx, select_term_t *select, bool tt) {
32,475✔
4523
  term_t t, s;
4524
  thvar_t x;
4525

4526
  /*
4527
   * Check for simplification
4528
   */
4529
  t = intern_tbl_get_root(&ctx->intern, select->arg);
32,475✔
4530
  s = extract_bit(ctx->terms, t, select->idx);
32,475✔
4531
  if (s != NULL_TERM) {
32,475✔
4532
    // (select t i) is s
4533
    assert_term(ctx, s, tt);
63✔
4534
  } else {
4535
    // no simplification
4536
    x = internalize_to_bv(ctx, select->arg);
32,412✔
4537
    ctx->bv.set_bit(ctx->bv_solver, x, select->idx, tt);
32,412✔
4538
  }
4539
}
32,474✔
4540

4541

4542
/*
4543
 * Top-level bitvector atoms
4544
 */
4545
// Auxiliary function: assert (t == 0) or (t != 0) depending on tt
4546
static void assert_toplevel_bveq0(context_t *ctx, term_t t, bool tt) {
28✔
4547
  uint32_t n;
4548
  thvar_t x, y;
4549

4550
  t = intern_tbl_get_root(&ctx->intern, t);
28✔
4551
  n = term_bitsize(ctx->terms, t);
28✔
4552
  x = internalize_to_bv(ctx, t);
28✔
4553
  y = ctx->bv.create_zero(ctx->bv_solver, n);
28✔
4554
  ctx->bv.assert_eq_axiom(ctx->bv_solver, x, y, tt);
28✔
4555
}
28✔
4556

4557

4558
/*
4559
 * Experimental: when t1 and t2 have a common factor C:
4560
 *   t1 = C * u1
4561
 *   t2 = C * u2
4562
 * then we have (t1 /= t2) implies (u1 /= u2).
4563
 * So we can add (u1 /= u2) when (t1 /= t2) is asserted.
4564
 * This is redundant but it may help solving the problem, especially if C is a
4565
 * complex expression.
4566
 */
4567
static void assert_factored_inequality(context_t *ctx, bvfactoring_t *f) {
9✔
4568
  term_t u1, u2;
4569
  thvar_t x, y;
4570

4571
  assert(f->code == BVFACTOR_FOUND);
4572

4573
  //  printf("Asserting factored inequality\n\n");
4574

4575
  u1 = bitvector_factoring_left_term(ctx, f);
9✔
4576
  u2 = bitvector_factoring_right_term(ctx, f);
9✔
4577
  x = internalize_to_bv(ctx, u1);
9✔
4578
  y = internalize_to_bv(ctx, u2);
9✔
4579
  ctx->bv.assert_eq_axiom(ctx->bv_solver, x,  y, false);
9✔
4580
}
9✔
4581

4582
static void assert_toplevel_bveq(context_t *ctx, composite_term_t *eq, bool tt) {
9,308✔
4583
  bveq_simp_t simp;
4584
  ivector_t *v;
4585
  int32_t *a;
4586
  term_t t, t1, t2;
4587
  thvar_t x, y;
4588
  uint32_t i, n;
4589

4590
  assert(eq->arity == 2);
4591

4592
  t1 = intern_tbl_get_root(&ctx->intern, eq->arg[0]);
9,308✔
4593
  t2 = intern_tbl_get_root(&ctx->intern, eq->arg[1]);
9,308✔
4594
  t = simplify_bitvector_eq(ctx, t1, t2);
9,308✔
4595
  if (t != NULL_TERM) {
9,308✔
4596
    // (bveq t1 t2) is equivalent to t
4597
    assert_term(ctx, t, tt);
18✔
4598
    return;
61✔
4599
  }
4600

4601
  if (tt) {
9,290✔
4602
    // try to flatten to a conjunction of terms
4603
    v = &ctx->aux_vector;
7,515✔
4604
    assert(v->size == 0);
4605
    if (bveq_flattens(ctx->terms, t1, t2, v)) {
7,515✔
4606
      /*
4607
       * (bveq t1 t2) is equivalent to (and v[0] ... v[k])
4608
       * (bveq t1 t2) is true at the toplevel so v[0] ... v[k] must all be true
4609
       */
4610

4611
      // make a copy of v
4612
      n = v->size;
19✔
4613
      a = alloc_istack_array(&ctx->istack, n);
19✔
4614
      for (i=0; i<n; i++) {
579✔
4615
        a[i] = v->data[i];
560✔
4616
      }
4617
      ivector_reset(v);
19✔
4618

4619
      // assert
4620
      for (i=0; i<n; i++) {
548✔
4621
        assert_term(ctx, a[i], true);
530✔
4622
      }
4623

4624
      free_istack_array(&ctx->istack, a);
18✔
4625
      return;
18✔
4626
    }
4627

4628
    // flattening failed
4629
    ivector_reset(v);
7,496✔
4630
  }
4631

4632
  /*
4633
   * Try more simplifications
4634
   */
4635
  try_arithmetic_bveq_simplification(ctx, &simp, t1, t2);
9,271✔
4636
  switch (simp.code) {
9,271✔
4637
  case BVEQ_CODE_TRUE:
×
4638
    if (!tt) longjmp(ctx->env, TRIVIALLY_UNSAT);
×
4639
    break;
×
4640

4641
  case BVEQ_CODE_FALSE:
×
4642
    if (tt) longjmp(ctx->env, TRIVIALLY_UNSAT);
×
4643
    break;
×
4644

4645
  case BVEQ_CODE_REDUCED:
36✔
4646
    t1 = intern_tbl_get_root(&ctx->intern, simp.left);
36✔
4647
    t2 = intern_tbl_get_root(&ctx->intern, simp.right);
36✔
4648
    break;
36✔
4649

4650
  case BVEQ_CODE_REDUCED0:
28✔
4651
    // reduced to simp.left == 0
4652
    assert_toplevel_bveq0(ctx, simp.left, tt);
28✔
4653
    return;
28✔
4654

4655
  default:
9,207✔
4656
    break;
9,207✔
4657
  }
4658

4659
  /*
4660
   * Try Factoring
4661
   */
4662
  if (!tt) {
9,243✔
4663
    bvfactoring_t *factoring;
4664
    bool eq = false;
1,751✔
4665

4666
    factoring = objstack_alloc(&ctx->ostack, sizeof(bvfactoring_t), (cleaner_t) delete_bvfactoring);
1,751✔
4667
    init_bvfactoring(factoring);
1,751✔
4668

4669
    try_bitvector_factoring(ctx, factoring, t1, t2);
1,751✔
4670
    switch (factoring->code) {
1,751✔
4671
    case BVFACTOR_EQUAL:
4✔
4672
      eq = true;
4✔
4673
      break;
4✔
4674

4675
    case BVFACTOR_FOUND:
9✔
4676
      assert_factored_inequality(ctx, factoring);
9✔
4677
      break;
9✔
4678

4679
    default:
1,738✔
4680
      break;
1,738✔
4681
    }
4682
    // delete_bvfactoring(&factoring);
4683
    objstack_pop(&ctx->ostack);
1,751✔
4684

4685
    if (eq) {
1,751✔
4686
      longjmp(ctx->env, TRIVIALLY_UNSAT);
4✔
4687
    }
4688
  }
4689

4690
  /*
4691
   * NOTE: asserting (eq t1 t2) in the egraph instead makes things worse
4692
   */
4693
  x = internalize_to_bv(ctx, t1);
9,239✔
4694
  y = internalize_to_bv(ctx, t2);
9,239✔
4695
  ctx->bv.assert_eq_axiom(ctx->bv_solver, x,  y, tt);
9,239✔
4696
}
4697

4698
static void assert_toplevel_bvge(context_t *ctx, composite_term_t *ge, bool tt) {
1,457✔
4699
  thvar_t x, y;
4700

4701
  assert(ge->arity == 2);
4702

4703
  x = internalize_to_bv(ctx, ge->arg[0]);
1,457✔
4704
  y = internalize_to_bv(ctx, ge->arg[1]);
1,457✔
4705
  ctx->bv.assert_ge_axiom(ctx->bv_solver, x,  y, tt);
1,457✔
4706
}
1,457✔
4707

4708
static void assert_toplevel_bvsge(context_t *ctx, composite_term_t *sge, bool tt) {
459✔
4709
  thvar_t x, y;
4710

4711
  assert(sge->arity == 2);
4712

4713
  x = internalize_to_bv(ctx, sge->arg[0]);
459✔
4714
  y = internalize_to_bv(ctx, sge->arg[1]);
459✔
4715
  ctx->bv.assert_sge_axiom(ctx->bv_solver, x,  y, tt);
459✔
4716
}
459✔
4717

4718

4719

4720
/*
4721
 * Top-level formula t:
4722
 * - t is a boolean term (or the negation of a boolean term)
4723
 * - t must be a root in the internalization table and must be mapped to true
4724
 */
4725
static void assert_toplevel_formula(context_t *ctx, term_t t) {
124,509✔
4726
  term_table_t *terms;
4727
  int32_t code;
4728
  bool tt;
4729

4730
  assert(is_boolean_term(ctx->terms, t) &&
4731
         intern_tbl_is_root(&ctx->intern, t) &&
4732
         term_is_true(ctx, t));
4733

4734
  tt = is_pos_term(t);
124,509✔
4735
  t = unsigned_term(t);
124,509✔
4736

4737
  /*
4738
   * Now: t is a root and has positive polarity
4739
   * - tt indicates whether we assert t or (not t):
4740
   *   tt true: assert t
4741
   *   tt false: assert (not t)
4742
   */
4743
  terms = ctx->terms;
124,509✔
4744
  switch (term_kind(terms, t)) {
124,509✔
4745
  case CONSTANT_TERM:
×
4746
  case UNINTERPRETED_TERM:
4747
    // should be eliminated by flattening
4748
    code = INTERNAL_ERROR;
×
4749
    goto abort;
×
4750

4751
  case ITE_TERM:
68✔
4752
  case ITE_SPECIAL:
4753
    assert_toplevel_ite(ctx, ite_term_desc(terms, t), tt);
68✔
4754
    break;
68✔
4755

4756
  case OR_TERM:
42,444✔
4757
    assert_toplevel_or(ctx, or_term_desc(terms, t), tt);
42,444✔
4758
    break;
42,444✔
4759

4760
  case XOR_TERM:
7✔
4761
    assert_toplevel_xor(ctx, xor_term_desc(terms, t), tt);
7✔
4762
    break;
7✔
4763

4764
  case EQ_TERM:
5,144✔
4765
    assert_toplevel_eq(ctx, eq_term_desc(terms, t), tt);
5,144✔
4766
    break;
5,142✔
4767

4768
  case ARITH_IS_INT_ATOM:
×
4769
    assert_toplevel_arith_is_int(ctx, arith_is_int_arg(terms, t), tt);
×
4770
    break;
×
4771

4772
  case ARITH_EQ_ATOM:
2,263✔
4773
    assert_toplevel_arith_eq(ctx, arith_eq_arg(terms, t), tt);
2,263✔
4774
    break;
2,262✔
4775

4776
  case ARITH_GE_ATOM:
27,848✔
4777
    assert_toplevel_arith_geq(ctx, arith_ge_arg(terms, t), tt);
27,848✔
4778
    break;
27,847✔
4779

4780
  case ARITH_BINEQ_ATOM:
3,201✔
4781
    assert_toplevel_arith_bineq(ctx, arith_bineq_atom_desc(terms, t), tt);
3,201✔
4782
    break;
3,201✔
4783

4784
  case ARITH_DIVIDES_ATOM:
×
4785
    assert_toplevel_arith_divides(ctx, arith_divides_atom_desc(terms, t), tt);
×
4786
    break;
×
4787

4788
  case APP_TERM:
250✔
4789
    assert_toplevel_apply(ctx, app_term_desc(terms, t), tt);
250✔
4790
    break;
250✔
4791

4792
  case SELECT_TERM:
×
4793
    assert_toplevel_select(ctx, select_term_desc(terms, t), tt);
×
4794
    break;
×
4795

4796
  case DISTINCT_TERM:
173✔
4797
    assert_toplevel_distinct(ctx, distinct_term_desc(terms, t), tt);
173✔
4798
    break;
171✔
4799

4800
  case VARIABLE:
×
4801
    code = FREE_VARIABLE_IN_FORMULA;
×
4802
    goto abort;
×
4803

4804
  case FORALL_TERM:
×
4805
    if (context_in_strict_mode(ctx)) {
×
4806
      code = QUANTIFIERS_NOT_SUPPORTED;
×
4807
      goto abort;
×
4808
    }
4809
    break;
×
4810

4811
  case BIT_TERM:
31,932✔
4812
    assert_toplevel_bit_select(ctx, bit_term_desc(terms, t), tt);
31,932✔
4813
    break;
31,932✔
4814

4815
  case BV_EQ_ATOM:
9,269✔
4816
    assert_toplevel_bveq(ctx, bveq_atom_desc(terms, t), tt);
9,269✔
4817
    break;
9,261✔
4818

4819
  case BV_GE_ATOM:
1,455✔
4820
    assert_toplevel_bvge(ctx, bvge_atom_desc(terms, t), tt);
1,455✔
4821
    break;
1,455✔
4822

4823
  case BV_SGE_ATOM:
455✔
4824
    assert_toplevel_bvsge(ctx, bvsge_atom_desc(terms, t), tt);
455✔
4825
    break;
455✔
4826

4827
  default:
×
4828
    code = INTERNAL_ERROR;
×
4829
    goto abort;
×
4830
  }
4831

4832
  return;
124,495✔
4833

4834
 abort:
×
4835
  longjmp(ctx->env, code);
×
4836
}
4837

4838

4839

4840
/*
4841
 * Assert (t == tt) for a boolean term t:
4842
 * - if t is not internalized, record the mapping
4843
 *   (root t) --> tt in the internalization table
4844
 */
4845
static void assert_term(context_t *ctx, term_t t, bool tt) {
998✔
4846
  term_table_t *terms;
4847
  int32_t code;
4848

4849
  assert(is_boolean_term(ctx->terms, t));
4850

4851
  /*
4852
   * Apply substitution + fix polarity
4853
   */
4854
  t = intern_tbl_get_root(&ctx->intern, t);
998✔
4855
  tt ^= is_neg_term(t);
998✔
4856
  t = unsigned_term(t);
998✔
4857

4858
  if (intern_tbl_root_is_mapped(&ctx->intern, t)) {
998✔
4859
    /*
4860
     * The root is already mapped:
4861
     * Either t is already internalized, or it occurs in
4862
     * one of the vectors top_eqs, top_atoms, top_formulas
4863
     * and it will be internalized/asserted later.
4864
     */
4865
    code = intern_tbl_map_of_root(&ctx->intern, t);
171✔
4866
    assert_internalization_code(ctx, code, tt);
171✔
4867

4868
  } else {
4869
    // store the mapping t --> tt
4870
    intern_tbl_map_root(&ctx->intern, t, bool2code(tt));
827✔
4871

4872
    // internalize and assert
4873
    terms = ctx->terms;
827✔
4874
    switch (term_kind(terms, t)) {
827✔
4875
    case CONSTANT_TERM:
×
4876
      // should always be internalized
4877
      code = INTERNAL_ERROR;
×
4878
      goto abort;
×
4879

4880
    case UNINTERPRETED_TERM:
1✔
4881
      // nothing to do: t --> true/false in the internalization table
4882
      break;
1✔
4883

4884
    case ITE_TERM:
2✔
4885
    case ITE_SPECIAL:
4886
      assert_toplevel_ite(ctx, ite_term_desc(terms, t), tt);
2✔
4887
      break;
2✔
4888

4889
    case OR_TERM:
31✔
4890
      assert_toplevel_or(ctx, or_term_desc(terms, t), tt);
31✔
4891
      break;
31✔
4892

4893
    case XOR_TERM:
×
4894
      assert_toplevel_xor(ctx, xor_term_desc(terms, t), tt);
×
4895
      break;
×
4896

4897
    case EQ_TERM:
11✔
4898
      assert_toplevel_eq(ctx, eq_term_desc(terms, t), tt);
11✔
4899
      break;
11✔
4900

4901
    case ARITH_IS_INT_ATOM:
×
4902
      assert_toplevel_arith_is_int(ctx, arith_is_int_arg(terms, t), tt);
×
4903
      break;
×
4904

4905
    case ARITH_EQ_ATOM:
4✔
4906
      assert_toplevel_arith_eq(ctx, arith_eq_arg(terms, t), tt);
4✔
4907
      break;
4✔
4908

4909
    case ARITH_GE_ATOM:
7✔
4910
      assert_toplevel_arith_geq(ctx, arith_ge_arg(terms, t), tt);
7✔
4911
      break;
7✔
4912

4913
    case ARITH_BINEQ_ATOM:
181✔
4914
      assert_toplevel_arith_bineq(ctx, arith_bineq_atom_desc(terms, t), tt);
181✔
4915
      break;
181✔
4916

4917
    case ARITH_DIVIDES_ATOM:
×
4918
      assert_toplevel_arith_divides(ctx, arith_divides_atom_desc(terms, t), tt);
×
4919
      break;
×
4920

4921
    case APP_TERM:
2✔
4922
      assert_toplevel_apply(ctx, app_term_desc(terms, t), tt);
2✔
4923
      break;
2✔
4924

4925
    case SELECT_TERM:
×
4926
      assert_toplevel_select(ctx, select_term_desc(terms, t), tt);
×
4927
      break;
×
4928

4929
    case DISTINCT_TERM:
×
4930
      assert_toplevel_distinct(ctx, distinct_term_desc(terms, t), tt);
×
4931
      break;
×
4932

4933
    case VARIABLE:
×
4934
      code = FREE_VARIABLE_IN_FORMULA;
×
4935
      goto abort;
×
4936

4937
    case FORALL_TERM:
×
4938
      if (context_in_strict_mode(ctx)) {
×
4939
        code = QUANTIFIERS_NOT_SUPPORTED;
×
4940
        goto abort;
×
4941
      }
4942
      break;
×
4943

4944
    case BIT_TERM:
543✔
4945
      assert_toplevel_bit_select(ctx, bit_term_desc(terms, t), tt);
543✔
4946
      break;
542✔
4947

4948
    case BV_EQ_ATOM:
39✔
4949
      assert_toplevel_bveq(ctx, bveq_atom_desc(terms, t), tt);
39✔
4950
      break;
39✔
4951

4952
    case BV_GE_ATOM:
2✔
4953
      assert_toplevel_bvge(ctx, bvge_atom_desc(terms, t), tt);
2✔
4954
      break;
2✔
4955

4956
    case BV_SGE_ATOM:
4✔
4957
      assert_toplevel_bvsge(ctx, bvsge_atom_desc(terms, t), tt);
4✔
4958
      break;
4✔
4959

4960
    default:
×
4961
      code = INTERNAL_ERROR;
×
4962
      goto abort;
×
4963
    }
4964
  }
4965

4966
  return;
993✔
4967

4968
 abort:
×
4969
  longjmp(ctx->env, code);
×
4970
}
4971

4972

4973

4974

4975
/************************
4976
 *  PARAMETERS/OPTIONS  *
4977
 ***********************/
4978

4979
/*
4980
 * Map architecture id to theories word
4981
 */
4982
static const uint32_t arch2theories[NUM_ARCH] = {
4983
  0,                           //  CTX_ARCH_NOSOLVERS --> empty theory
4984

4985
  UF_MASK,                     //  CTX_ARCH_EG
4986
  ARITH_MASK,                  //  CTX_ARCH_SPLX
4987
  IDL_MASK,                    //  CTX_ARCH_IFW
4988
  RDL_MASK,                    //  CTX_ARCH_RFW
4989
  BV_MASK,                     //  CTX_ARCH_BV
4990
  UF_MASK|FUN_MASK,            //  CTX_ARCH_EGFUN
4991
  UF_MASK|ARITH_MASK,          //  CTX_ARCH_EGSPLX
4992
  UF_MASK|BV_MASK,             //  CTX_ARCH_EGBV
4993
  UF_MASK|ARITH_MASK|FUN_MASK, //  CTX_ARCH_EGFUNSPLX
4994
  UF_MASK|BV_MASK|FUN_MASK,    //  CTX_ARCH_EGFUNBV
4995
  UF_MASK|BV_MASK|ARITH_MASK,  //  CTX_ARCH_EGSPLXBV
4996
  ALLTH_MASK,                  //  CTX_ARCH_EGFUNSPLXBV
4997

4998
  IDL_MASK,                    //  CTX_ARCH_AUTO_IDL
4999
  RDL_MASK,                    //  CTX_ARCH_AUTO_RDL
5000

5001
  UF_MASK|ARITH_MASK|FUN_MASK  //  CTX_ARCH_MCSAT
5002
};
5003

5004

5005
/*
5006
 * Each architecture has a fixed set of solver components:
5007
 * - the set of components is stored as a bit vector (on 8bits)
5008
 * - this uses the following bit-masks
5009
 * For the AUTO_xxx architecture, nothing is required initially,
5010
 * so the bitmask is 0.
5011
 */
5012
#define EGRPH  0x1
5013
#define SPLX   0x2
5014
#define IFW    0x4
5015
#define RFW    0x8
5016
#define BVSLVR 0x10
5017
#define FSLVR  0x20
5018
#define MCSAT  0x40
5019

5020
static const uint8_t arch_components[NUM_ARCH] = {
5021
  0,                        //  CTX_ARCH_NOSOLVERS
5022

5023
  EGRPH,                    //  CTX_ARCH_EG
5024
  SPLX,                     //  CTX_ARCH_SPLX
5025
  IFW,                      //  CTX_ARCH_IFW
5026
  RFW,                      //  CTX_ARCH_RFW
5027
  BVSLVR,                   //  CTX_ARCH_BV
5028
  EGRPH|FSLVR,              //  CTX_ARCH_EGFUN
5029
  EGRPH|SPLX,               //  CTX_ARCH_EGSPLX
5030
  EGRPH|BVSLVR,             //  CTX_ARCH_EGBV
5031
  EGRPH|SPLX|FSLVR,         //  CTX_ARCH_EGFUNSPLX
5032
  EGRPH|BVSLVR|FSLVR,       //  CTX_ARCH_EGFUNBV
5033
  EGRPH|SPLX|BVSLVR,        //  CTX_ARCH_EGSPLXBV
5034
  EGRPH|SPLX|BVSLVR|FSLVR,  //  CTX_ARCH_EGFUNSPLXBV
5035

5036
  0,                        //  CTX_ARCH_AUTO_IDL
5037
  0,                        //  CTX_ARCH_AUTO_RDL
5038

5039
  MCSAT                     //  CTX_ARCH_MCSAT
5040
};
5041

5042

5043
/*
5044
 * Smt mode for a context mode
5045
 */
5046
static const smt_mode_t core_mode[NUM_MODES] = {
5047
  SMT_MODE_BASIC,       // one check
5048
  SMT_MODE_BASIC,       // multichecks
5049
  SMT_MODE_PUSHPOP,     // push/pop
5050
  SMT_MODE_INTERACTIVE, // interactive
5051
};
5052

5053

5054
/*
5055
 * Flags for a context mode
5056
 */
5057
static const uint32_t mode2options[NUM_MODES] = {
5058
  0,
5059
  MULTICHECKS_OPTION_MASK,
5060
  MULTICHECKS_OPTION_MASK|PUSHPOP_OPTION_MASK,
5061
  MULTICHECKS_OPTION_MASK|PUSHPOP_OPTION_MASK|CLEANINT_OPTION_MASK,
5062
};
5063

5064

5065

5066

5067

5068

5069
/*
5070
 * SIMPLEX OPTIONS
5071
 */
5072

5073
/*
5074
 * Which version of the arithmetic solver is present
5075
 */
5076
bool context_has_idl_solver(context_t *ctx) {
8✔
5077
  uint8_t solvers;
5078
  solvers = arch_components[ctx->arch];
8✔
5079
  return ctx->arith_solver != NULL && (solvers & IFW);
8✔
5080
}
5081

5082
bool context_has_rdl_solver(context_t *ctx) {
×
5083
  uint8_t solvers;
5084
  solvers = arch_components[ctx->arch];
×
5085
  return ctx->arith_solver != NULL && (solvers & RFW);
×
5086
}
5087

5088
bool context_has_simplex_solver(context_t *ctx) {
45,798✔
5089
  uint8_t solvers;
5090
  solvers = arch_components[ctx->arch];
45,798✔
5091
  return ctx->arith_solver != NULL && (solvers & SPLX);
45,798✔
5092
}
5093

5094

5095
/*
5096
 * If the simplex solver already exists, the options are propagated.
5097
 * Otherwise, they are recorded into the option flags. They will
5098
 * be set up when the simplex solver is created.
5099
 */
5100
void enable_splx_eager_lemmas(context_t *ctx) {
173✔
5101
  ctx->options |= SPLX_EGRLMAS_OPTION_MASK;
173✔
5102
  if (context_has_simplex_solver(ctx)) {
173✔
5103
    simplex_enable_eager_lemmas(ctx->arith_solver);
173✔
5104
  }
5105
}
173✔
5106

5107
void disable_splx_eager_lemmas(context_t *ctx) {
×
5108
  ctx->options &= ~SPLX_EGRLMAS_OPTION_MASK;
×
5109
  if (context_has_simplex_solver(ctx)) {
×
5110
    simplex_disable_eager_lemmas(ctx->arith_solver);
×
5111
  }
5112
}
×
5113

5114

5115
void enable_splx_periodic_icheck(context_t *ctx) {
146✔
5116
  ctx->options |= SPLX_ICHECK_OPTION_MASK;
146✔
5117
  if (context_has_simplex_solver(ctx)) {
146✔
5118
    simplex_enable_periodic_icheck(ctx->arith_solver);
135✔
5119
  }
5120
}
146✔
5121

5122
void disable_splx_periodic_icheck(context_t *ctx) {
×
5123
  ctx->options &= ~SPLX_ICHECK_OPTION_MASK;
×
5124
  if (context_has_simplex_solver(ctx)) {
×
5125
    simplex_disable_periodic_icheck(ctx->arith_solver);
×
5126
  }
5127
}
×
5128

5129
void enable_splx_eqprop(context_t *ctx) {
72✔
5130
  ctx->options |= SPLX_EQPROP_OPTION_MASK;
72✔
5131
  if (context_has_simplex_solver(ctx)) {
72✔
5132
    simplex_enable_eqprop(ctx->arith_solver);
72✔
5133
  }
5134
}
72✔
5135

5136
void disable_splx_eqprop(context_t *ctx) {
×
5137
  ctx->options &= ~SPLX_EQPROP_OPTION_MASK;
×
5138
  if (context_has_simplex_solver(ctx)) {
×
5139
    simplex_disable_eqprop(ctx->arith_solver);
×
5140
  }
5141
}
×
5142

5143

5144

5145

5146
/******************
5147
 *  EMPTY SOLVER  *
5148
 *****************/
5149

5150
/*
5151
 * We need an empty theory solver for initializing
5152
 * the core if the architecture is NOSOLVERS.
5153
 */
5154
static void donothing(void *solver) {
2,560✔
5155
}
2,560✔
5156

5157
static void null_backtrack(void *solver, uint32_t backlevel) {
×
5158
}
×
5159

5160
static bool null_propagate(void *solver) {
×
5161
  return true;
×
5162
}
5163

5164
static fcheck_code_t null_final_check(void *solver) {
×
5165
  return FCHECK_SAT;
×
5166
}
5167

5168
static th_ctrl_interface_t null_ctrl = {
5169
  donothing,        // start_internalization
5170
  donothing,        // start_search
5171
  null_propagate,   // propagate
5172
  null_final_check, // final check
5173
  donothing,        // increase_decision_level
5174
  null_backtrack,   // backtrack
5175
  donothing,        // push
5176
  donothing,        // pop
5177
  donothing,        // reset
5178
  donothing,        // clear
5179
};
5180

5181

5182
// for the smt interface, nothing should be called since there are no atoms
5183
static th_smt_interface_t null_smt = {
5184
  NULL, NULL, NULL, NULL, NULL,
5185
};
5186

5187

5188

5189

5190
/****************************
5191
 *  ARCHITECTURE & SOLVERS  *
5192
 ***************************/
5193

5194
/*
5195
 * Check whether a given architecture includes a specific solver
5196
 */
5197
bool context_arch_has_egraph(context_arch_t arch) {
417✔
5198
  return arch_components[arch] & EGRPH;
417✔
5199
}
5200

5201
bool context_arch_has_bv(context_arch_t arch) {
×
5202
  return arch_components[arch] & BVSLVR;
×
5203
}
5204

5205
bool context_arch_has_fun(context_arch_t arch) {
×
5206
  return arch_components[arch] & FSLVR;
×
5207
}
5208

5209
bool context_arch_has_arith(context_arch_t arch) {
×
5210
  return arch_components[arch] & (SPLX|IFW|RFW);
×
5211
}
5212

5213
bool context_arch_has_mcsat(context_arch_t arch) {
×
5214
  return arch_components[arch] & MCSAT;
×
5215
}
5216

5217
bool context_arch_has_simplex(context_arch_t arch) {
×
5218
  return arch_components[arch] & SPLX;
×
5219
}
5220

5221
bool context_arch_has_ifw(context_arch_t arch) {
×
5222
  return arch_components[arch] & IFW;
×
5223
}
5224

5225
bool context_arch_has_rfw(context_arch_t arch) {
×
5226
  return arch_components[arch] & RFW;
×
5227
}
5228

5229

5230
/****************************
5231
 *  SOLVER INITIALIZATION   *
5232
 ***************************/
5233

5234
/*
5235
 * Create and initialize the egraph
5236
 * - the core must be created first
5237
 */
5238
static void create_egraph(context_t *ctx) {
4,786✔
5239
  egraph_t *egraph;
5240

5241
  assert(ctx->egraph == NULL);
5242

5243
  egraph = (egraph_t *) safe_malloc(sizeof(egraph_t));
4,786✔
5244
  init_egraph(egraph, ctx->types);
4,786✔
5245
  ctx->egraph = egraph;
4,786✔
5246
}
4,786✔
5247

5248

5249
/*
5250
 * Create and initialize the mcsat solver
5251
 */
5252
static void create_mcsat(context_t *ctx) {
685✔
5253
  assert(ctx->mcsat == NULL);
5254
  ctx->mcsat = mcsat_new(ctx);
685✔
5255
}
685✔
5256

5257

5258

5259
/*
5260
 * Create and initialize the idl solver and attach it to the core
5261
 * - there must be no other solvers and no egraph
5262
 * - if automatic is true, attach the solver to the core, otherwise
5263
 *   initialize the core
5264
 * - copy the solver's internalization interface into arith
5265
 */
5266
static void create_idl_solver(context_t *ctx, bool automatic) {
26✔
5267
  idl_solver_t *solver;
5268
  smt_mode_t cmode;
5269

5270
  assert(ctx->egraph == NULL && ctx->arith_solver == NULL && ctx->bv_solver == NULL &&
5271
         ctx->fun_solver == NULL && ctx->core != NULL);
5272

5273
  cmode = core_mode[ctx->mode];
26✔
5274
  solver = (idl_solver_t *) safe_malloc(sizeof(idl_solver_t));
26✔
5275
  init_idl_solver(solver, ctx->core, &ctx->gate_manager);
26✔
5276
  if (automatic) {
26✔
5277
    smt_core_reset_thsolver(ctx->core, solver, idl_ctrl_interface(solver),
26✔
5278
                            idl_smt_interface(solver));
5279
  } else {
5280
    init_smt_core(ctx->core, CTX_DEFAULT_CORE_SIZE, solver, idl_ctrl_interface(solver),
×
5281
                  idl_smt_interface(solver), cmode);
5282
  }
5283
  idl_solver_init_jmpbuf(solver, &ctx->env);
26✔
5284
  ctx->arith_solver = solver;
26✔
5285
  ctx->arith = *idl_arith_interface(solver);
26✔
5286
}
26✔
5287

5288

5289
/*
5290
 * Create and initialize the rdl solver and attach it to the core.
5291
 * - there must be no other solvers and no egraph
5292
 * - if automatic is true, attach rdl to the core, otherwise
5293
 *   initialize the core
5294
 * - copy the solver's internalization interface in ctx->arith
5295
 */
5296
static void create_rdl_solver(context_t *ctx, bool automatic) {
8✔
5297
  rdl_solver_t *solver;
5298
  smt_mode_t cmode;
5299

5300
  assert(ctx->egraph == NULL && ctx->arith_solver == NULL && ctx->bv_solver == NULL &&
5301
         ctx->fun_solver == NULL && ctx->core != NULL);
5302

5303
  cmode = core_mode[ctx->mode];
8✔
5304
  solver = (rdl_solver_t *) safe_malloc(sizeof(rdl_solver_t));
8✔
5305
  init_rdl_solver(solver, ctx->core, &ctx->gate_manager);
8✔
5306
  if (automatic) {
8✔
5307
    smt_core_reset_thsolver(ctx->core, solver, rdl_ctrl_interface(solver),
8✔
5308
                            rdl_smt_interface(solver));
5309
  } else {
5310
    init_smt_core(ctx->core, CTX_DEFAULT_CORE_SIZE, solver, rdl_ctrl_interface(solver),
×
5311
                  rdl_smt_interface(solver), cmode);
5312
  }
5313
  rdl_solver_init_jmpbuf(solver, &ctx->env);
8✔
5314
  ctx->arith_solver = solver;
8✔
5315
  ctx->arith = *rdl_arith_interface(solver);
8✔
5316
}
8✔
5317

5318

5319
/*
5320
 * Create an initialize the simplex solver and attach it to the core
5321
 * or to the egraph if the egraph exists.
5322
 * - if automatic is true, this is part of auto_idl or auto_rdl. So the
5323
 *   core is already initialized.
5324
 */
5325
static void create_simplex_solver(context_t *ctx, bool automatic) {
14,902✔
5326
  simplex_solver_t *solver;
5327
  smt_mode_t cmode;
5328

5329
  assert(ctx->arith_solver == NULL && ctx->core != NULL);
5330

5331
  cmode = core_mode[ctx->mode];
14,902✔
5332
  solver = (simplex_solver_t *) safe_malloc(sizeof(simplex_solver_t));
14,902✔
5333
  init_simplex_solver(solver, ctx->core, &ctx->gate_manager, ctx->egraph);
14,902✔
5334

5335
  // set simplex options
5336
  if (splx_eager_lemmas_enabled(ctx)) {
14,902✔
5337
    simplex_enable_eager_lemmas(solver);
×
5338
  }
5339
  if (splx_periodic_icheck_enabled(ctx)) {
14,902✔
5340
    simplex_enable_periodic_icheck(solver);
×
5341
  }
5342
  if (splx_eqprop_enabled(ctx)) {
14,902✔
5343
    simplex_enable_eqprop(solver);
×
5344
  }
5345

5346
  // row saving must be enabled unless we're in ONECHECK mode
5347
  if (ctx->mode != CTX_MODE_ONECHECK) {
14,902✔
5348
    simplex_enable_row_saving(solver);
14,750✔
5349
  }
5350

5351
  if (ctx->egraph != NULL) {
14,902✔
5352
    // attach the simplex solver as a satellite solver to the egraph
5353
    egraph_attach_arithsolver(ctx->egraph, solver, simplex_ctrl_interface(solver),
4,329✔
5354
                              simplex_smt_interface(solver), simplex_egraph_interface(solver),
5355
                              simplex_arith_egraph_interface(solver));
5356
  } else if (!automatic) {
10,573✔
5357
    // attach simplex to the core and initialize the core
5358
    init_smt_core(ctx->core, CTX_DEFAULT_CORE_SIZE, solver, simplex_ctrl_interface(solver),
10,572✔
5359
                  simplex_smt_interface(solver), cmode);
5360
  } else {
5361
    // the core is already initialized: attach simplex
5362
    smt_core_reset_thsolver(ctx->core, solver, simplex_ctrl_interface(solver),
1✔
5363
                            simplex_smt_interface(solver));
5364
  }
5365

5366
  simplex_solver_init_jmpbuf(solver, &ctx->env);
14,902✔
5367
  ctx->arith_solver = solver;
14,902✔
5368
  ctx->arith = *simplex_arith_interface(solver);
14,902✔
5369
}
14,902✔
5370

5371

5372
/*
5373
 * Create IDL/SIMPLEX solver based on ctx->dl_profile
5374
 */
5375
static void create_auto_idl_solver(context_t *ctx) {
27✔
5376
  dl_data_t *profile;
5377
  int32_t bound;
5378
  double atom_density;
5379

5380
  assert(ctx->dl_profile != NULL);
5381
  profile = ctx->dl_profile;
27✔
5382

5383
  if (q_is_smallint(&profile->path_bound)) {
27✔
5384
    bound = q_get_smallint(&profile->path_bound);
26✔
5385
  } else {
5386
    bound = INT32_MAX;
1✔
5387
  }
5388

5389
  if (bound >= 1073741824) {
27✔
5390
    // simplex required because of arithmetic overflow
5391
    create_simplex_solver(ctx, true);
1✔
5392
    ctx->arch = CTX_ARCH_SPLX;
1✔
5393
  } else if (profile->num_vars >= 1000) {
26✔
5394
    // too many variables for FW
5395
    create_simplex_solver(ctx, true);
×
5396
    ctx->arch = CTX_ARCH_SPLX;
×
5397
  } else if (profile->num_vars <= 200 || profile->num_eqs == 0) {
26✔
5398
    // use FW for now, until we've tested SIMPLEX more
5399
    // 0 equalities usually means a scheduling problem
5400
    // --flatten works better on IDL/FW
5401
    create_idl_solver(ctx, true);
26✔
5402
    ctx->arch = CTX_ARCH_IFW;
26✔
5403
    enable_diseq_and_or_flattening(ctx);
26✔
5404

5405
  } else {
5406

5407
    // problem density
5408
    if (profile->num_vars > 0) {
×
5409
      atom_density = ((double) profile->num_atoms)/profile->num_vars;
×
5410
    } else {
5411
      atom_density = 0;
×
5412
    }
5413

5414
    if (atom_density >= 10.0) {
×
5415
      // high density: use FW
5416
      create_idl_solver(ctx, true);
×
5417
      ctx->arch = CTX_ARCH_IFW;
×
5418
      enable_diseq_and_or_flattening(ctx);
×
5419
    } else {
5420
      create_simplex_solver(ctx, true);
×
5421
      ctx->arch = CTX_ARCH_SPLX;
×
5422
    }
5423
  }
5424
}
27✔
5425

5426

5427
/*
5428
 * Create RDL/SIMPLEX solver based on ctx->dl_profile
5429
 */
5430
static void create_auto_rdl_solver(context_t *ctx) {
8✔
5431
  dl_data_t *profile;
5432
  double atom_density;
5433

5434
  assert(ctx->dl_profile != NULL);
5435
  profile = ctx->dl_profile;
8✔
5436

5437
  if (profile->num_vars >= 1000) {
8✔
5438
    create_simplex_solver(ctx, true);
×
5439
    ctx->arch = CTX_ARCH_SPLX;
×
5440
  } else if (profile->num_vars <= 200 || profile->num_eqs == 0) {
8✔
5441
    create_rdl_solver(ctx, true);
8✔
5442
    ctx->arch = CTX_ARCH_RFW;
8✔
5443
  } else {
5444
    // problem density
5445
    if (profile->num_vars > 0) {
×
5446
      atom_density = ((double) profile->num_atoms)/profile->num_vars;
×
5447
    } else {
5448
      atom_density = 0;
×
5449
    }
5450

5451
    if (atom_density >= 7.0) {
×
5452
      // high density: use FW
5453
      create_rdl_solver(ctx, true);
×
5454
      ctx->arch = CTX_ARCH_RFW;
×
5455
    } else {
5456
      // low-density: use SIMPLEX
5457
      create_simplex_solver(ctx, true);
×
5458
      ctx->arch = CTX_ARCH_SPLX;
×
5459
    }
5460
  }
5461
}
8✔
5462

5463

5464

5465
/*
5466
 * Create the bitvector solver
5467
 * - attach it to the egraph if there's an egraph
5468
 * - attach it to the core and initialize the core otherwise
5469
 */
5470
static void create_bv_solver(context_t *ctx) {
10,547✔
5471
  bv_solver_t *solver;
5472
  smt_mode_t cmode;
5473

5474
  assert(ctx->bv_solver == NULL && ctx->core != NULL);
5475

5476
  cmode = core_mode[ctx->mode];
10,547✔
5477
  solver = (bv_solver_t *) safe_malloc(sizeof(bv_solver_t));
10,547✔
5478
  init_bv_solver(solver, ctx->core, ctx->egraph);
10,547✔
5479

5480
  if (ctx->egraph != NULL) {
10,547✔
5481
    // attach as a satellite to the egraph
5482
    egraph_attach_bvsolver(ctx->egraph, solver, bv_solver_ctrl_interface(solver),
4,417✔
5483
                           bv_solver_smt_interface(solver), bv_solver_egraph_interface(solver),
5484
                           bv_solver_bv_egraph_interface(solver));
5485
  } else {
5486
    // attach to the core and initialize the core
5487
    init_smt_core(ctx->core, CTX_DEFAULT_CORE_SIZE, solver, bv_solver_ctrl_interface(solver),
6,130✔
5488
                  bv_solver_smt_interface(solver), cmode);
5489
  }
5490

5491
  // EXPERIMENT
5492
  //  smt_core_make_etable(ctx->core);
5493
  // END
5494

5495
  bv_solver_init_jmpbuf(solver, &ctx->env);
10,547✔
5496
  ctx->bv_solver = solver;
10,547✔
5497
  ctx->bv = *bv_solver_bv_interface(solver);
10,547✔
5498
}
10,547✔
5499

5500

5501
/*
5502
 * Create the array/function theory solver and attach it to the egraph
5503
 */
5504
static void create_fun_solver(context_t *ctx) {
4,423✔
5505
  fun_solver_t *solver;
5506

5507
  assert(ctx->egraph != NULL && ctx->fun_solver == NULL);
5508

5509
  solver = (fun_solver_t *) safe_malloc(sizeof(fun_solver_t));
4,423✔
5510
  init_fun_solver(solver, ctx->core, &ctx->gate_manager, ctx->egraph, ctx->types);
4,423✔
5511
  egraph_attach_funsolver(ctx->egraph, solver, fun_solver_ctrl_interface(solver),
4,423✔
5512
                          fun_solver_egraph_interface(solver),
5513
                          fun_solver_fun_egraph_interface(solver));
5514

5515
  ctx->fun_solver = solver;
4,423✔
5516
}
4,423✔
5517

5518

5519
/*
5520
 * Allocate and initialize solvers based on architecture and mode
5521
 * - core and gate manager must exist at this point
5522
 * - if the architecture is either AUTO_IDL or AUTO_RDL, no theory solver
5523
 *   is allocated yet, and the core is initialized for Boolean only
5524
 * - otherwise, all components are ready and initialized, including the core.
5525
 */
5526
static void init_solvers(context_t *ctx) {
22,209✔
5527
  uint8_t solvers;
5528
  smt_core_t *core;
5529
  smt_mode_t cmode;
5530
  egraph_t *egraph;
5531

5532
  solvers = arch_components[ctx->arch];
22,209✔
5533

5534
  ctx->egraph = NULL;
22,209✔
5535
  ctx->arith_solver = NULL;
22,209✔
5536
  ctx->bv_solver = NULL;
22,209✔
5537
  ctx->fun_solver = NULL;
22,209✔
5538
  ctx->quant_solver = NULL;
22,209✔
5539

5540
  // Create egraph first, then satellite solvers
5541
  if (solvers & EGRPH) {
22,209✔
5542
    create_egraph(ctx);
4,786✔
5543
  }
5544

5545
  // Create mcsat
5546
  if (solvers & MCSAT) {
22,209✔
5547
    create_mcsat(ctx);
685✔
5548
  }
5549

5550
  // Arithmetic solver
5551
  if (solvers & SPLX) {
22,209✔
5552
    create_simplex_solver(ctx, false);
14,901✔
5553
  } else if (solvers & IFW) {
7,308✔
5554
    create_idl_solver(ctx, false);
×
5555
  } else if (solvers & RFW) {
7,308✔
5556
    create_rdl_solver(ctx, false);
×
5557
  }
5558

5559
  // Bitvector solver
5560
  if (solvers & BVSLVR) {
22,209✔
5561
    create_bv_solver(ctx);
10,547✔
5562
  }
5563

5564
  // Array solver
5565
  if (solvers & FSLVR) {
22,209✔
5566
    create_fun_solver(ctx);
4,423✔
5567
  }
5568

5569
  /*
5570
   * At this point all solvers are ready and initialized, except the
5571
   * egraph and core if the egraph is present or the core if there are
5572
   * no solvers, or if arch is AUTO_IDL or AUTO_RDL.
5573
   */
5574
  cmode = core_mode[ctx->mode];   // initialization mode for the core
22,209✔
5575
  egraph = ctx->egraph;
22,209✔
5576
  core = ctx->core;
22,209✔
5577
  if (egraph != NULL) {
22,209✔
5578
    init_smt_core(core, CTX_DEFAULT_CORE_SIZE, egraph, egraph_ctrl_interface(egraph),
4,786✔
5579
                  egraph_smt_interface(egraph), cmode);
5580
    egraph_attach_core(egraph, core);
4,786✔
5581

5582
  } else if (solvers == 0) {
17,423✔
5583
    /*
5584
     * Boolean solver only. If arch if AUTO_IDL or AUTO_RDL, the
5585
     * theory solver will be changed later by create_auto_idl_solver
5586
     * or create_auto_rdl_solver.
5587
     */
5588
    assert(ctx->arith_solver == NULL && ctx->bv_solver == NULL && ctx->fun_solver == NULL);
5589
    init_smt_core(core, CTX_DEFAULT_CORE_SIZE, NULL, &null_ctrl, &null_smt, cmode);
36✔
5590
  } else if (solvers == MCSAT) {
17,387✔
5591
    /*
5592
     * MCsat solver only, we create the core, but never use it.
5593
     */
5594
    assert(ctx->egraph == NULL && ctx->arith_solver == NULL &&
5595
           ctx->bv_solver == NULL && ctx->fun_solver == NULL);
5596
    init_smt_core(core, CTX_DEFAULT_CORE_SIZE, NULL, &null_ctrl, &null_smt, cmode);
685✔
5597
  }
5598

5599
  /*
5600
   * Optimization: if the arch is NOSOLVERS or BV then we set bool_only in the core
5601
   */
5602
  if (ctx->arch == CTX_ARCH_NOSOLVERS || ctx->arch == CTX_ARCH_BV) {
22,209✔
5603
    smt_core_set_bool_only(core);
6,130✔
5604
  }
5605
}
22,209✔
5606

5607

5608

5609

5610
/*
5611
 * Delete the arithmetic solver
5612
 */
5613
static void delete_arith_solver(context_t *ctx) {
14,935✔
5614
  uint8_t solvers;
5615

5616
  assert(ctx->arith_solver != NULL);
5617

5618
  solvers = arch_components[ctx->arch];
14,935✔
5619
  if (solvers & IFW) {
14,935✔
5620
    delete_idl_solver(ctx->arith_solver);
26✔
5621
  } else if (solvers & RFW) {
14,909✔
5622
    delete_rdl_solver(ctx->arith_solver);
8✔
5623
  } else if (solvers & SPLX) {
14,901✔
5624
    delete_simplex_solver(ctx->arith_solver);
14,901✔
5625
  }
5626
  safe_free(ctx->arith_solver);
14,935✔
5627
  ctx->arith_solver = NULL;
14,935✔
5628
}
14,935✔
5629

5630

5631

5632

5633
/*****************************
5634
 *  CONTEXT INITIALIZATION   *
5635
 ****************************/
5636

5637
/*
5638
 * Check mode and architecture
5639
 */
5640
#ifndef NDEBUG
5641
static inline bool valid_mode(context_mode_t mode) {
5642
  return CTX_MODE_ONECHECK <= mode && mode <= CTX_MODE_INTERACTIVE;
5643
}
5644

5645
static inline bool valid_arch(context_arch_t arch) {
5646
  return CTX_ARCH_NOSOLVERS <= arch && arch <= CTX_ARCH_MCSAT;
5647
}
5648
#endif
5649

5650

5651
/*
5652
 * Initialize ctx for the given mode and architecture
5653
 * - terms = term table for that context
5654
 * - qflag = true means quantifiers allowed
5655
 * - qflag = false means no quantifiers
5656
 */
5657
void init_context(context_t *ctx, term_table_t *terms, smt_logic_t logic,
22,209✔
5658
                  context_mode_t mode, context_arch_t arch, bool qflag) {
5659
  assert(valid_mode(mode) && valid_arch(arch));
5660

5661
  /*
5662
   * Set architecture and options
5663
   */
5664
  ctx->mode = mode;
22,209✔
5665
  ctx->arch = arch;
22,209✔
5666
  ctx->logic = logic;
22,209✔
5667
  ctx->theories = arch2theories[arch];
22,209✔
5668
  ctx->options = mode2options[mode];
22,209✔
5669
  if (qflag) {
22,209✔
5670
    // quantifiers require egraph
5671
    assert((ctx->theories & UF_MASK) != 0);
UNCOV
5672
    ctx->theories |= QUANT_MASK;
×
5673
  }
5674

5675
  ctx->base_level = 0;
22,209✔
5676

5677
  /*
5678
   * The core is always needed: allocate it here. It's not initialized yet.
5679
   * The other solver are optionals.
5680
   *
5681
   * TODO: we could skip this when we use MCSAT (since then the core is
5682
   * not needed).
5683
   */
5684
  ctx->core = (smt_core_t *) safe_malloc(sizeof(smt_core_t));
22,209✔
5685
  ctx->egraph = NULL;
22,209✔
5686
  ctx->mcsat = NULL;
22,209✔
5687
  ctx->arith_solver = NULL;
22,209✔
5688
  ctx->bv_solver = NULL;
22,209✔
5689
  ctx->fun_solver = NULL;
22,209✔
5690
  ctx->quant_solver = NULL;
22,209✔
5691

5692
  /*
5693
   * Global tables + gate manager
5694
   */
5695
  ctx->types = terms->types;
22,209✔
5696
  ctx->terms = terms;
22,209✔
5697
  init_gate_manager(&ctx->gate_manager, ctx->core);
22,209✔
5698

5699
  /*
5700
   * Simplification/internalization support
5701
   */
5702
  init_intern_tbl(&ctx->intern, 0, terms);
22,209✔
5703
  init_ivector(&ctx->top_eqs, CTX_DEFAULT_VECTOR_SIZE);
22,209✔
5704
  init_ivector(&ctx->top_atoms, CTX_DEFAULT_VECTOR_SIZE);
22,209✔
5705
  init_ivector(&ctx->top_formulas, CTX_DEFAULT_VECTOR_SIZE);
22,209✔
5706
  init_ivector(&ctx->top_interns, CTX_DEFAULT_VECTOR_SIZE);
22,209✔
5707

5708
  /*
5709
   * Force the internalization mapping for true and false
5710
   * - true  term --> true_occ
5711
   * - false term --> false_occ
5712
   * This mapping holds even if there's no egraph.
5713
   */
5714
  intern_tbl_map_root(&ctx->intern, true_term, bool2code(true));
22,209✔
5715

5716
  /*
5717
   * Auxiliary internalization buffers
5718
   */
5719
  init_ivector(&ctx->subst_eqs, CTX_DEFAULT_VECTOR_SIZE);
22,209✔
5720
  init_ivector(&ctx->aux_eqs, CTX_DEFAULT_VECTOR_SIZE);
22,209✔
5721
  init_ivector(&ctx->aux_atoms, CTX_DEFAULT_VECTOR_SIZE);
22,209✔
5722
  init_ivector(&ctx->aux_vector, CTX_DEFAULT_VECTOR_SIZE);
22,209✔
5723
  init_int_queue(&ctx->queue, 0);
22,209✔
5724
  init_istack(&ctx->istack);
22,209✔
5725
  init_objstack(&ctx->ostack);
22,209✔
5726
  init_sharing_map(&ctx->sharing, &ctx->intern);
22,209✔
5727
  init_objstore(&ctx->cstore, sizeof(conditional_t), 32);
22,209✔
5728
  init_assumption_stack(&ctx->assumptions);
22,209✔
5729

5730
  ctx->subst = NULL;
22,209✔
5731
  ctx->marks = NULL;
22,209✔
5732
  ctx->cache = NULL;
22,209✔
5733
  ctx->small_cache = NULL;
22,209✔
5734
  ctx->edge_map = NULL;
22,209✔
5735
  ctx->eq_cache = NULL;
22,209✔
5736
  ctx->divmod_table = NULL;
22,209✔
5737
  ctx->explorer = NULL;
22,209✔
5738
  ctx->unsat_core_cache = NULL;
22,209✔
5739

5740
  ctx->dl_profile = NULL;
22,209✔
5741
  ctx->arith_buffer = NULL;
22,209✔
5742
  ctx->poly_buffer = NULL;
22,209✔
5743
  ctx->aux_poly = NULL;
22,209✔
5744
  ctx->aux_poly_size = 0;
22,209✔
5745

5746
  ctx->bvpoly_buffer = NULL;
22,209✔
5747

5748
  q_init(&ctx->aux);
22,209✔
5749
  init_bvconstant(&ctx->bv_buffer);
22,209✔
5750

5751
  ctx->trace = NULL;
22,209✔
5752

5753
  // mcsat options default
5754
  init_mcsat_options(&ctx->mcsat_options);
22,209✔
5755
  init_ivector(&ctx->mcsat_var_order, CTX_DEFAULT_VECTOR_SIZE);
22,209✔
5756
  init_ivector(&ctx->mcsat_initial_var_order, CTX_DEFAULT_VECTOR_SIZE);
22,209✔
5757
  /*
5758
   * Allocate and initialize the solvers and core
5759
   * NOTE: no theory solver yet if arch is AUTO_IDL or AUTO_RDL
5760
   */
5761
  init_solvers(ctx);
22,209✔
5762

5763
  ctx->en_quant = false;
22,209✔
5764
}
22,209✔
5765

5766

5767

5768

5769
/*
5770
 * Delete ctx
5771
 */
5772
void delete_context(context_t *ctx) {
22,208✔
5773
  if (ctx->core != NULL) {
22,208✔
5774
    delete_smt_core(ctx->core);
22,208✔
5775
    safe_free(ctx->core);
22,208✔
5776
    ctx->core = NULL;
22,208✔
5777
  }
5778

5779
  if (ctx->mcsat != NULL) {
22,208✔
5780
    mcsat_destruct(ctx->mcsat);
685✔
5781
    safe_free(ctx->mcsat);
685✔
5782
    ctx->mcsat = NULL;
685✔
5783
  }
5784

5785
  if (ctx->egraph != NULL) {
22,208✔
5786
    delete_egraph(ctx->egraph);
4,785✔
5787
    safe_free(ctx->egraph);
4,785✔
5788
    ctx->egraph = NULL;
4,785✔
5789
  }
5790

5791
  if (ctx->arith_solver != NULL) {
22,208✔
5792
    delete_arith_solver(ctx);
14,935✔
5793
  }
5794

5795
  if (ctx->fun_solver != NULL) {
22,208✔
5796
    delete_fun_solver(ctx->fun_solver);
4,422✔
5797
    safe_free(ctx->fun_solver);
4,422✔
5798
    ctx->fun_solver = NULL;
4,422✔
5799
  }
5800

5801
  if (ctx->quant_solver != NULL) {
22,208✔
5802
    delete_quant_solver(ctx->quant_solver);
52✔
5803
    safe_free(ctx->quant_solver);
52✔
5804
    ctx->quant_solver = NULL;
52✔
5805
  }
5806

5807
  if (ctx->bv_solver != NULL) {
22,208✔
5808
    delete_bv_solver(ctx->bv_solver);
10,546✔
5809
    safe_free(ctx->bv_solver);
10,546✔
5810
    ctx->bv_solver = NULL;
10,546✔
5811
  }
5812

5813
  delete_gate_manager(&ctx->gate_manager);
22,208✔
5814
  /* delete_mcsat_options(&ctx->mcsat_options); // if used then the same memory is freed twice */
5815
  delete_ivector(&ctx->mcsat_var_order);
22,208✔
5816
  delete_ivector(&ctx->mcsat_initial_var_order);
22,208✔
5817

5818
  delete_intern_tbl(&ctx->intern);
22,208✔
5819
  delete_ivector(&ctx->top_eqs);
22,208✔
5820
  delete_ivector(&ctx->top_atoms);
22,208✔
5821
  delete_ivector(&ctx->top_formulas);
22,208✔
5822
  delete_ivector(&ctx->top_interns);
22,208✔
5823

5824
  delete_ivector(&ctx->subst_eqs);
22,208✔
5825
  delete_ivector(&ctx->aux_eqs);
22,208✔
5826
  delete_ivector(&ctx->aux_atoms);
22,208✔
5827
  delete_ivector(&ctx->aux_vector);
22,208✔
5828
  delete_int_queue(&ctx->queue);
22,208✔
5829
  delete_istack(&ctx->istack);
22,208✔
5830
  delete_objstack(&ctx->ostack);
22,208✔
5831
  delete_sharing_map(&ctx->sharing);
22,208✔
5832
  delete_objstore(&ctx->cstore);
22,208✔
5833
  delete_assumption_stack(&ctx->assumptions);
22,208✔
5834

5835
  context_free_subst(ctx);
22,208✔
5836
  context_free_marks(ctx);
22,208✔
5837
  context_free_cache(ctx);
22,208✔
5838
  context_free_small_cache(ctx);
22,208✔
5839
  context_free_eq_cache(ctx);
22,208✔
5840
  context_free_divmod_table(ctx);
22,208✔
5841
  context_free_explorer(ctx);
22,208✔
5842

5843
  context_free_dl_profile(ctx);
22,208✔
5844
  context_free_edge_map(ctx);
22,208✔
5845
  context_free_arith_buffer(ctx);
22,208✔
5846
  context_free_poly_buffer(ctx);
22,208✔
5847
  context_free_aux_poly(ctx);
22,208✔
5848

5849
  context_free_bvpoly_buffer(ctx);
22,208✔
5850
  context_invalidate_unsat_core_cache(ctx);
22,208✔
5851

5852
  q_clear(&ctx->aux);
22,208✔
5853
  delete_bvconstant(&ctx->bv_buffer);
22,208✔
5854
}
22,208✔
5855

5856
void context_invalidate_unsat_core_cache(context_t *ctx) {
87,611✔
5857
  if (ctx->unsat_core_cache != NULL) {
87,611✔
5858
    delete_ivector(ctx->unsat_core_cache);
2,704✔
5859
    safe_free(ctx->unsat_core_cache);
2,704✔
5860
    ctx->unsat_core_cache = NULL;
2,704✔
5861
  }
5862
}
87,611✔
5863

5864

5865

5866
/*
5867
 * Reset: remove all assertions and clear all internalization tables
5868
 */
5869
void reset_context(context_t *ctx) {
3✔
5870
  ctx->base_level = 0;
3✔
5871
  context_invalidate_unsat_core_cache(ctx);
3✔
5872

5873
  reset_smt_core(ctx->core); // this propagates reset to all solvers
3✔
5874

5875
  if (ctx->mcsat != NULL) {
3✔
5876
    mcsat_reset(ctx->mcsat);
2✔
5877
  }
5878

5879
  reset_gate_manager(&ctx->gate_manager);
3✔
5880

5881
  ivector_reset(&ctx->mcsat_var_order);
3✔
5882
  ivector_reset(&ctx->mcsat_initial_var_order);
3✔
5883

5884
  reset_intern_tbl(&ctx->intern);
3✔
5885
  ivector_reset(&ctx->top_eqs);
3✔
5886
  ivector_reset(&ctx->top_atoms);
3✔
5887
  ivector_reset(&ctx->top_formulas);
3✔
5888
  ivector_reset(&ctx->top_interns);
3✔
5889

5890
  // Force the internalization mapping for true and false
5891
  intern_tbl_map_root(&ctx->intern, true_term, bool2code(true));
3✔
5892

5893
  ivector_reset(&ctx->subst_eqs);
3✔
5894
  ivector_reset(&ctx->aux_eqs);
3✔
5895
  ivector_reset(&ctx->aux_atoms);
3✔
5896
  ivector_reset(&ctx->aux_vector);
3✔
5897
  int_queue_reset(&ctx->queue);
3✔
5898
  reset_istack(&ctx->istack);
3✔
5899
  reset_objstack(&ctx->ostack);
3✔
5900
  reset_sharing_map(&ctx->sharing);
3✔
5901
  reset_objstore(&ctx->cstore);
3✔
5902
  reset_assumption_stack(&ctx->assumptions);
3✔
5903

5904
  context_free_subst(ctx);
3✔
5905
  context_free_marks(ctx);
3✔
5906
  context_reset_small_cache(ctx);
3✔
5907
  context_reset_eq_cache(ctx);
3✔
5908
  context_reset_divmod_table(ctx);
3✔
5909
  context_reset_explorer(ctx);
3✔
5910

5911
  context_free_arith_buffer(ctx);
3✔
5912
  context_reset_poly_buffer(ctx);
3✔
5913
  context_free_aux_poly(ctx);
3✔
5914
  context_free_dl_profile(ctx);
3✔
5915

5916
  context_free_bvpoly_buffer(ctx);
3✔
5917

5918
  q_clear(&ctx->aux);
3✔
5919
}
3✔
5920

5921

5922
/*
5923
 * Add tracer to ctx and ctx->core
5924
 */
5925
void context_set_trace(context_t *ctx, tracer_t *trace) {
285✔
5926
  assert(ctx->trace == NULL);
5927
  ctx->trace = trace;
285✔
5928
  smt_core_set_trace(ctx->core, trace);
285✔
5929
  if (ctx->mcsat != NULL) {
285✔
5930
    mcsat_set_tracer(ctx->mcsat, trace);
284✔
5931
  }
5932
}
285✔
5933

5934

5935
/*
5936
 * Push and pop
5937
 */
5938
void context_push(context_t *ctx) {
18,490✔
5939
  assert(context_supports_pushpop(ctx));
5940
  context_invalidate_unsat_core_cache(ctx);
18,490✔
5941
  smt_push(ctx->core);  // propagates to all solvers
18,490✔
5942
  if (ctx->mcsat != NULL) {
18,490✔
5943
    mcsat_push(ctx->mcsat);
1,321✔
5944
  }
5945
  intern_tbl_push(&ctx->intern);
18,490✔
5946
  assumption_stack_push(&ctx->assumptions);
18,490✔
5947
  context_eq_cache_push(ctx);
18,490✔
5948
  context_divmod_table_push(ctx);
18,490✔
5949

5950
  ctx->base_level ++;
18,490✔
5951
}
18,490✔
5952

5953
void context_pop(context_t *ctx) {
1,474✔
5954
  assert(context_supports_pushpop(ctx) && ctx->base_level > 0);
5955
  context_invalidate_unsat_core_cache(ctx);
1,474✔
5956
  smt_pop(ctx->core);   // propagates to all solvers
1,474✔
5957
  if (ctx->mcsat != NULL) {
1,474✔
5958
    mcsat_pop(ctx->mcsat);
1,237✔
5959
  }
5960
  intern_tbl_pop(&ctx->intern);
1,474✔
5961
  assumption_stack_pop(&ctx->assumptions);
1,474✔
5962
  context_eq_cache_pop(ctx);
1,474✔
5963
  context_divmod_table_pop(ctx);
1,474✔
5964

5965
  ctx->base_level --;
1,474✔
5966
}
1,474✔
5967

5968

5969

5970

5971

5972
/****************************
5973
 *   ASSERTIONS AND CHECK   *
5974
 ***************************/
5975

5976
/*
5977
 * Build the sharing data
5978
 * - processes all the assertions in vectors top_eqs, top_atoms, top_formulas
5979
 * - this function should be called after building the substitutions
5980
 */
5981
static void context_build_sharing_data(context_t *ctx) {
71,771✔
5982
  sharing_map_t *map;
5983

5984
  map = &ctx->sharing;
71,771✔
5985
  reset_sharing_map(map);
71,771✔
5986
  sharing_map_add_terms(map, ctx->top_eqs.data, ctx->top_eqs.size);
71,771✔
5987
  sharing_map_add_terms(map, ctx->top_atoms.data, ctx->top_atoms.size);
71,771✔
5988
  sharing_map_add_terms(map, ctx->top_formulas.data, ctx->top_formulas.size);
71,771✔
5989
}
71,771✔
5990

5991

5992
#if 0
5993
/*
5994
 * PROVISIONAL: SHOW ASSERTIONS
5995
 */
5996
static void context_show_assertions(const context_t *ctx, uint32_t n, const term_t *a) {
5997
  pp_area_t area;
5998
  yices_pp_t printer;
5999
  uint32_t i;
6000

6001
  area.width = 80;
6002
  area.height = UINT32_MAX;
6003
  area.offset = 0;
6004
  area.stretch = false;
6005
  area.truncate = false;
6006
  init_yices_pp(&printer, stdout, &area, PP_VMODE, 0);
6007

6008
  for (i=0; i<n; i++) {
6009
    pp_term_full(&printer, ctx->terms, a[i]);
6010
    flush_yices_pp(&printer);
6011
  }
6012
  delete_yices_pp(&printer, true);
6013
}
6014
#endif
6015

6016
/*
6017
 * Flatten and internalize assertions a[0 ... n-1]
6018
 * - all elements a[i] must be valid boolean term in ctx->terms
6019
 * - return code:
6020
 *   TRIVIALLY_UNSAT if there's an easy contradiction
6021
 *   CTX_NO_ERROR if the assertions were processed without error
6022
 *   a negative error code otherwise.
6023
 */
6024
static int32_t context_process_assertions(context_t *ctx, uint32_t n, const term_t *a) {
74,435✔
6025
  ivector_t *v;
6026
  uint32_t i;
6027
  int code;
6028

6029
  ivector_reset(&ctx->top_eqs);
74,435✔
6030
  ivector_reset(&ctx->top_atoms);
74,435✔
6031
  ivector_reset(&ctx->top_formulas);
74,435✔
6032
  ivector_reset(&ctx->top_interns);
74,435✔
6033
  ivector_reset(&ctx->subst_eqs);
74,435✔
6034
  ivector_reset(&ctx->aux_eqs);
74,435✔
6035
  ivector_reset(&ctx->aux_atoms);
74,435✔
6036

6037
  code = setjmp(ctx->env);
74,435✔
6038
  if (code == 0) {
74,822✔
6039

6040
    // If using MCSAT, just check and done
6041
    if (ctx->mcsat != NULL) {
74,435✔
6042
      // TBD: quant support
6043
      assert(!context_quant_enabled(ctx));
6044
      code = mcsat_assert_formulas(ctx->mcsat, n, a);
2,302✔
6045
      goto done;
2,291✔
6046
    }
6047

6048
#if 0
6049
    printf("\n=== Context: process assertions ===\n");
6050
    context_show_assertions(ctx, n, a);
6051
    printf("===\n\n");
6052
#endif
6053

6054
    // flatten
6055
    for (i=0; i<n; i++) {
195,354✔
6056
      flatten_assertion(ctx, a[i]);
123,582✔
6057
    }
6058

6059
    trace_printf(ctx->trace, 6, "(done flattening)\n");
71,772✔
6060

6061
    /*
6062
     * At this point, the assertions are stored into the vectors
6063
     * top_eqs, top_atoms, top_formulas, and top_interns
6064
     * - more top-level equalities may be in subst_eqs
6065
     * - ctx->intern stores the internalized terms and the variable
6066
     *   substitutions.
6067
     */
6068

6069
    switch (ctx->arch) {
71,772✔
6070
    // TBD: make sure following preprocessings work with quant enabled
6071
    case CTX_ARCH_EG:
3,329✔
6072
      /*
6073
       * UF problem: we must process subst_eqs last since the
6074
       * preprocessing may add new equalities in aux_eqs that may end
6075
       * up in subst_eqs after the call to process_aux_eqs.
6076
       */
6077
      if (context_breaksym_enabled(ctx)) {
3,329✔
6078
        break_uf_symmetries(ctx);
30✔
6079
      }
6080
      if (context_eq_abstraction_enabled(ctx)) {
3,329✔
6081
        analyze_uf(ctx);
64✔
6082
      }
6083
      if (ctx->aux_eqs.size > 0) {
3,329✔
6084
        process_aux_eqs(ctx);
6✔
6085
      }
6086
      if (ctx->subst_eqs.size > 0) {
3,328✔
6087
        context_process_candidate_subst(ctx);
10✔
6088
      }
6089
      break;
3,328✔
6090

6091
    case CTX_ARCH_AUTO_IDL:
27✔
6092
      /*
6093
       * For difference logic, we must process the subst_eqs first
6094
       * (otherwise analyze_diff_logic may give wrong results).
6095
       */
6096
      if (ctx->subst_eqs.size > 0) {
27✔
UNCOV
6097
        context_process_candidate_subst(ctx);
×
6098
      }
6099
      analyze_diff_logic(ctx, true);
27✔
6100
      create_auto_idl_solver(ctx);
27✔
6101
      break;
27✔
6102

6103
    case CTX_ARCH_AUTO_RDL:
8✔
6104
      /*
6105
       * Difference logic, we must process the subst_eqs first
6106
       */
6107
      trace_printf(ctx->trace, 6, "(auto-idl solver)\n");
8✔
6108
      if (ctx->subst_eqs.size > 0) {
8✔
UNCOV
6109
        context_process_candidate_subst(ctx);
×
6110
      }
6111
      analyze_diff_logic(ctx, false);
8✔
6112
      create_auto_rdl_solver(ctx);
8✔
6113
      break;
8✔
6114

6115
    case CTX_ARCH_SPLX:
30,674✔
6116
      /*
6117
       * Simplex, like EG, may add aux_atoms so we must process
6118
       * subst_eqs last here.
6119
       */
6120
      trace_printf(ctx->trace, 6, "(Simplex solver)\n");
30,674✔
6121
      // more optional processing
6122
      if (context_cond_def_preprocessing_enabled(ctx)) {
30,674✔
6123
        process_conditional_definitions(ctx);
52✔
6124
        if (ctx->aux_eqs.size > 0) {
52✔
6125
          process_aux_eqs(ctx);
2✔
6126
        }
6127
        if (ctx->aux_atoms.size > 0) {
52✔
6128
          process_aux_atoms(ctx);
3✔
6129
        }
6130
      }
6131
      if (ctx->subst_eqs.size > 0) {
30,674✔
6132
        context_process_candidate_subst(ctx);
16✔
6133
      }
6134
      break;
30,674✔
6135

6136
    default:
37,734✔
6137
      /*
6138
       * Process the candidate variable substitutions if any
6139
       */
6140
      if (ctx->subst_eqs.size > 0) {
37,734✔
6141
        context_process_candidate_subst(ctx);
2,746✔
6142
      }
6143
      break;
37,734✔
6144
    }
6145

6146
    /*
6147
     * Sharing
6148
     */
6149
    context_build_sharing_data(ctx);
71,771✔
6150

6151
    /*
6152
     * Notify the core + solver(s)
6153
     */
6154
    if (!context_quant_enabled(ctx)) {
71,771✔
6155
        // TBD: make sure this is correct
6156
      internalization_start(ctx->core);
69,238✔
6157
    }
6158

6159
    /*
6160
     * Assert top_eqs, top_atoms, top_formulas, top_interns
6161
     */
6162
    code = CTX_NO_ERROR;
71,771✔
6163

6164
    // first: all terms that are already internalized
6165
    v = &ctx->top_interns;
71,771✔
6166
    n = v->size;
71,771✔
6167
    if (n > 0) {
71,771✔
6168
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" existing terms)\n", n);
283✔
6169
      i = 0;
283✔
6170
      do {
6171
        assert_toplevel_intern(ctx, v->data[i]);
738✔
6172
        i ++;
738✔
6173
      } while (i < n);
738✔
6174

6175
      // one round of propagation
6176
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
283✔
6177
        code = TRIVIALLY_UNSAT;
10✔
6178
        goto done;
10✔
6179
      }
6180
    }
6181

6182
    // second: all top-level equalities
6183
    v = &ctx->top_eqs;
71,761✔
6184
    n = v->size;
71,761✔
6185
    if (n > 0) {
71,761✔
6186
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" top-level equalities)\n", n);
6,744✔
6187
      i = 0;
6,744✔
6188
      do {
6189
        assert_toplevel_formula(ctx, v->data[i]);
10,805✔
6190
        i ++;
10,802✔
6191
      } while (i < n);
10,802✔
6192

6193
      // one round of propagation
6194
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
6,741✔
6195
        code = TRIVIALLY_UNSAT;
65✔
6196
        goto done;
65✔
6197
      }
6198
    }
6199

6200
    // third: all top-level atoms (other than equalities)
6201
    v = &ctx->top_atoms;
71,693✔
6202
    n = v->size;
71,693✔
6203
    if (n > 0) {
71,693✔
6204
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" top-level atoms)\n", n);
15,453✔
6205
      i = 0;
15,453✔
6206
      do {
6207
        assert_toplevel_formula(ctx, v->data[i]);
68,453✔
6208
        i ++;
68,442✔
6209
      } while (i < n);
68,442✔
6210

6211
      // one round of propagation
6212
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
15,442✔
6213
        code = TRIVIALLY_UNSAT;
74✔
6214
        goto done;
74✔
6215
      }
6216
    }
6217

6218
    // last: all non-atomic, formulas
6219
    v =  &ctx->top_formulas;
71,608✔
6220
    n = v->size;
71,608✔
6221
    if (n > 0) {
71,608✔
6222
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" top-level formulas)\n", n);
21,975✔
6223
      i = 0;
21,975✔
6224
      do {
6225
        assert_toplevel_formula(ctx, v->data[i]);
45,251✔
6226
        i ++;
45,251✔
6227
      } while (i < n);
45,251✔
6228

6229
      // one round of propagation
6230
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
21,975✔
6231
        code = TRIVIALLY_UNSAT;
63✔
6232
        goto done;
63✔
6233
      }
6234
    }
6235

6236
  } else {
6237
    /*
6238
     * Exception: return from longjmp(ctx->env, code);
6239
     */
6240
    ivector_reset(&ctx->aux_vector);
387✔
6241
    reset_istack(&ctx->istack);
387✔
6242
    reset_objstack(&ctx->ostack);
387✔
6243
    int_queue_reset(&ctx->queue);
387✔
6244
    context_free_subst(ctx);
387✔
6245
    context_free_marks(ctx);
387✔
6246
  }
6247

6248
 done:
74,435✔
6249
  return code;
74,435✔
6250
}
6251

6252
/*
6253
 * Assert all formulas f[0] ... f[n-1]
6254
 * The context status must be IDLE.
6255
 *
6256
 * Return code:
6257
 * - TRIVIALLY_UNSAT means that an inconsistency is detected
6258
 *   (in that case the context status is set to UNSAT)
6259
 * - CTX_NO_ERROR means no internalization error and status not
6260
 *   determined
6261
 * - otherwise, the code is negative to report an error.
6262
 */
6263
int32_t _o_assert_formulas(context_t *ctx, uint32_t n, const term_t *f) {
71,901✔
6264
  int32_t code;
6265

6266
  assert(ctx->arch == CTX_ARCH_AUTO_IDL ||
6267
         ctx->arch == CTX_ARCH_AUTO_RDL ||
6268
         smt_status(ctx->core) == YICES_STATUS_IDLE);
6269
  assert(!context_quant_enabled(ctx));
6270

6271
  code = context_process_assertions(ctx, n, f);
71,901✔
6272
  if (code == TRIVIALLY_UNSAT) {
71,901✔
6273
    if (ctx->arch == CTX_ARCH_AUTO_IDL || ctx->arch == CTX_ARCH_AUTO_RDL) {
581✔
6274
      // cleanup: reset arch/config to 'no theory'
6275
      assert(ctx->arith_solver == NULL && ctx->bv_solver == NULL && ctx->fun_solver == NULL &&
6276
             ctx->mode == CTX_MODE_ONECHECK);
6277
      ctx->arch = CTX_ARCH_NOSOLVERS;
1✔
6278
      ctx->theories = 0;
1✔
6279
      ctx->options = 0;
1✔
6280
    }
6281

6282
    if( smt_status(ctx->core) != YICES_STATUS_UNSAT) {
581✔
6283
      // force UNSAT in the core
6284
      add_empty_clause(ctx->core);
369✔
6285
      ctx->core->status = YICES_STATUS_UNSAT;
369✔
6286
    }
6287
  }
6288

6289
  return code;
71,901✔
6290
}
6291

6292
/*
6293
 * Assert all formulas f[0] ... f[n-1] during quantifier instantiation
6294
 * The context status must be SEARCHING.
6295
 *
6296
 * Return code:
6297
 * - TRIVIALLY_UNSAT means that an inconsistency is detected
6298
 *   (in that case the context status is set to UNSAT)
6299
 * - CTX_NO_ERROR means no internalization error and status not
6300
 *   determined
6301
 * - otherwise, the code is negative to report an error.
6302
 */
6303
int32_t quant_assert_formulas(context_t *ctx, uint32_t n, const term_t *f) {
2,534✔
6304
  int32_t code;
6305

6306
  assert(context_quant_enabled(ctx));
6307
  assert(smt_status(ctx->core) == YICES_STATUS_SEARCHING);
6308

6309
  code = context_process_assertions(ctx, n, f);
2,534✔
6310
  if (code == TRIVIALLY_UNSAT) {
2,534✔
6311
    if (ctx->arch == CTX_ARCH_AUTO_IDL || ctx->arch == CTX_ARCH_AUTO_RDL) {
1✔
6312
      // cleanup: reset arch/config to 'no theory'
6313
      assert(ctx->arith_solver == NULL && ctx->bv_solver == NULL && ctx->fun_solver == NULL &&
6314
      ctx->mode == CTX_MODE_ONECHECK);
UNCOV
6315
      ctx->arch = CTX_ARCH_NOSOLVERS;
×
UNCOV
6316
      ctx->theories = 0;
×
UNCOV
6317
      ctx->options = 0;
×
6318
    }
6319

6320
    if( smt_status(ctx->core) != YICES_STATUS_UNSAT) {
1✔
6321
      // force UNSAT in the core
6322
      add_empty_clause(ctx->core);
1✔
6323
      ctx->core->status = YICES_STATUS_UNSAT;
1✔
6324
    }
6325
  }
6326

6327
  return code;
2,534✔
6328
}
6329

6330
int32_t assert_formulas(context_t *ctx, uint32_t n, const term_t *f) {
18,466✔
6331
  MT_PROTECT(int32_t, __yices_globals.lock, _o_assert_formulas(ctx, n, f));
18,466✔
6332
}
6333

6334

6335

6336

6337
/*
6338
 * Assert a boolean formula f.
6339
 *
6340
 * The context status must be IDLE.
6341
 *
6342
 * Return code:
6343
 * - TRIVIALLY_UNSAT means that an inconsistency is detected
6344
 *   (in that case the context status is set to UNSAT)
6345
 * - CTX_NO_ERROR means no internalization error and status not
6346
 *   determined
6347
 * - otherwise, the code is negative. The assertion could
6348
 *   not be processed.
6349
 */
6350
int32_t _o_assert_formula(context_t *ctx, term_t f) {
53,435✔
6351
  return _o_assert_formulas(ctx, 1, &f);
53,435✔
6352
}
6353

6354
int32_t assert_formula(context_t *ctx, term_t f) {
49,221✔
6355
  MT_PROTECT(int32_t, __yices_globals.lock, _o_assert_formula(ctx, f));
49,221✔
6356
}
6357

6358

6359
/*
6360
 * Convert boolean term t to a literal l in context ctx
6361
 * - t must be a boolean term
6362
 * - return a negative code if there's an error
6363
 * - return a literal (l >= 0) otherwise.
6364
 */
6365
int32_t context_internalize(context_t *ctx, term_t t) {
87,570✔
6366
  int code;
6367
  literal_t l;
6368

6369
  ivector_reset(&ctx->top_eqs);
87,570✔
6370
  ivector_reset(&ctx->top_atoms);
87,570✔
6371
  ivector_reset(&ctx->top_formulas);
87,570✔
6372
  ivector_reset(&ctx->top_interns);
87,570✔
6373
  ivector_reset(&ctx->subst_eqs);
87,570✔
6374
  ivector_reset(&ctx->aux_eqs);
87,570✔
6375

6376
  code = setjmp(ctx->env);
87,570✔
6377
  if (code == 0) {
87,570✔
6378
    // we must call internalization start first
6379
    if (!context_quant_enabled(ctx)) {
87,570✔
6380
      // TBD: make sure this is correct
6381
      internalization_start(ctx->core);
87,466✔
6382
    }
6383
    l = internalize_to_literal(ctx, t);
87,570✔
6384
  } else {
6385
    assert(code < 0);
6386
    /*
6387
     * Clean up
6388
     */
UNCOV
6389
    ivector_reset(&ctx->aux_vector);
×
UNCOV
6390
    reset_istack(&ctx->istack);
×
UNCOV
6391
    int_queue_reset(&ctx->queue);
×
UNCOV
6392
    context_free_subst(ctx);
×
UNCOV
6393
    context_free_marks(ctx);
×
UNCOV
6394
    l = code;
×
6395
  }
6396

6397
  return l;
87,570✔
6398
}
6399

6400

6401
/*
6402
 * Build an assumption for Boolean term t:
6403
 * - this converts t to a literal l in context ctx
6404
 *   then create an indicator variable x in the core
6405
 *   and add the clause (x => l) in the core.
6406
 * - return a negative code if t can't be internalized
6407
 * - return the literal x otherwise (where x>=0).
6408
 */
6409
int32_t context_add_assumption(context_t *ctx, term_t t) {
87,466✔
6410
  int32_t l, x;
6411

6412
  // check if we already have an assumption literal for t
6413
  x = assumption_literal_for_term(&ctx->assumptions, t);
87,466✔
6414
  if (x < 0) {
87,466✔
6415
    l = context_internalize(ctx, t);
87,466✔
6416
    if (l < 0) return l; // error code
87,466✔
6417

6418
    x = pos_lit(create_boolean_variable(ctx->core));
87,466✔
6419
    add_binary_clause(ctx->core, not(x), l); // clause (x implies l)
87,466✔
6420

6421
    assumption_stack_add(&ctx->assumptions, t, x);
87,466✔
6422
  }
6423

6424
  return x;
87,466✔
6425
}
6426

6427

6428

6429
/*
6430
 * PROVISIONAL: FOR TESTING/DEBUGGING
6431
 */
6432

6433
/*
6434
 * Preprocess formula f or array of formulas f[0 ... n-1]
6435
 * - this does flattening + build substitutions
6436
 * - return code: as in assert_formulas
6437
 * - the result is stored in the internal vectors
6438
 *     ctx->top_interns
6439
 *     ctx->top_eqs
6440
 *     ctx->top_atoms
6441
 *     ctx->top_formulas
6442
 *   + ctx->intern stores substitutions
6443
 */
UNCOV
6444
int32_t context_process_formulas(context_t *ctx, uint32_t n, term_t *f) {
×
6445
  uint32_t i;
6446
  int code;
6447

UNCOV
6448
  ivector_reset(&ctx->top_eqs);
×
UNCOV
6449
  ivector_reset(&ctx->top_atoms);
×
UNCOV
6450
  ivector_reset(&ctx->top_formulas);
×
UNCOV
6451
  ivector_reset(&ctx->top_interns);
×
UNCOV
6452
  ivector_reset(&ctx->subst_eqs);
×
UNCOV
6453
  ivector_reset(&ctx->aux_eqs);
×
UNCOV
6454
  ivector_reset(&ctx->aux_atoms);
×
6455

UNCOV
6456
  code = setjmp(ctx->env);
×
UNCOV
6457
  if (code == 0) {
×
6458
    // flatten
UNCOV
6459
    for (i=0; i<n; i++) {
×
UNCOV
6460
      flatten_assertion(ctx, f[i]);
×
6461
    }
6462

6463
    /*
6464
     * At this point, the assertions are stored into the vectors
6465
     * top_eqs, top_atoms, top_formulas, and top_interns
6466
     * - more top-level equalities may be in subst_eqs
6467
     * - ctx->intern stores the internalized terms and the variable
6468
     *   substitutions.
6469
     */
6470

6471
    switch (ctx->arch) {
×
UNCOV
6472
    case CTX_ARCH_EG:
×
6473
      /*
6474
       * UF problem: we must process subst_eqs last since the
6475
       * preprocessing may add new equalities in aux_eqs that may end
6476
       * up in subst_eqs after the call to process_aux_eqs.
6477
       */
UNCOV
6478
      if (context_breaksym_enabled(ctx)) {
×
UNCOV
6479
        break_uf_symmetries(ctx);
×
6480
      }
UNCOV
6481
      if (context_eq_abstraction_enabled(ctx)) {
×
UNCOV
6482
        analyze_uf(ctx);
×
6483
      }
UNCOV
6484
      if (ctx->aux_eqs.size > 0) {
×
6485
        process_aux_eqs(ctx);
×
6486
      }
UNCOV
6487
      if (ctx->subst_eqs.size > 0) {
×
UNCOV
6488
        context_process_candidate_subst(ctx);
×
6489
      }
UNCOV
6490
      break;
×
6491

6492
    case CTX_ARCH_AUTO_IDL:
×
6493
      /*
6494
       * For difference logic, we must process the subst_eqs first
6495
       * (otherwise analyze_diff_logic may give wrong results).
6496
       */
UNCOV
6497
      if (ctx->subst_eqs.size > 0) {
×
6498
        context_process_candidate_subst(ctx);
×
6499
      }
UNCOV
6500
      analyze_diff_logic(ctx, true);
×
6501
      create_auto_idl_solver(ctx);
×
6502
      break;
×
6503

6504
    case CTX_ARCH_AUTO_RDL:
×
6505
      /*
6506
       * Difference logic, we must process the subst_eqs first
6507
       */
UNCOV
6508
      if (ctx->subst_eqs.size > 0) {
×
UNCOV
6509
        context_process_candidate_subst(ctx);
×
6510
      }
6511
      analyze_diff_logic(ctx, false);
×
6512
      create_auto_rdl_solver(ctx);
×
UNCOV
6513
      break;
×
6514

6515
    case CTX_ARCH_SPLX:
×
6516
      /*
6517
       * Simplex, like EG, may add aux_atoms so we must process
6518
       * subst_eqs last here.
6519
       */
6520
      // more optional processing
UNCOV
6521
      if (context_cond_def_preprocessing_enabled(ctx)) {
×
6522
        process_conditional_definitions(ctx);
×
6523
        if (ctx->aux_eqs.size > 0) {
×
UNCOV
6524
          process_aux_eqs(ctx);
×
6525
        }
6526
        if (ctx->aux_atoms.size > 0) {
×
6527
          process_aux_atoms(ctx);
×
6528
        }
6529
      }
UNCOV
6530
      if (ctx->subst_eqs.size > 0) {
×
UNCOV
6531
        context_process_candidate_subst(ctx);
×
6532
      }
UNCOV
6533
      break;
×
6534

6535
    default:
×
6536
      /*
6537
       * Process the candidate variable substitutions if any
6538
       */
UNCOV
6539
      if (ctx->subst_eqs.size > 0) {
×
6540
        context_process_candidate_subst(ctx);
×
6541
      }
UNCOV
6542
      break;
×
6543
    }
6544

6545
    /*
6546
     * Sharing
6547
     */
UNCOV
6548
    context_build_sharing_data(ctx);
×
6549

UNCOV
6550
    code = CTX_NO_ERROR;
×
6551

6552
  } else {
6553
    /*
6554
     * Exception: return from longjmp(ctx->env, code);
6555
     */
6556
    ivector_reset(&ctx->aux_vector);
×
UNCOV
6557
    reset_istack(&ctx->istack);
×
UNCOV
6558
    int_queue_reset(&ctx->queue);
×
UNCOV
6559
    context_free_subst(ctx);
×
UNCOV
6560
    context_free_marks(ctx);
×
6561
  }
6562

UNCOV
6563
  return code;
×
6564
}
6565

UNCOV
6566
int32_t context_process_formula(context_t *ctx, term_t f) {
×
UNCOV
6567
  return context_process_formulas(ctx, 1, &f);
×
6568
}
6569

6570

6571

6572
/*
6573
 * The search function 'check_context' is defined in context_solver.c
6574
 */
6575

6576

6577
/*
6578
 * Interrupt the search.
6579
 */
6580
void context_stop_search(context_t *ctx) {
3✔
6581
  if (ctx->mcsat == NULL) {
3✔
6582
    stop_search(ctx->core);
3✔
6583
    if (context_has_simplex_solver(ctx)) {
3✔
6584
      simplex_stop_search(ctx->arith_solver);
3✔
6585
    }
6586
  } else {
UNCOV
6587
    mcsat_stop_search(ctx->mcsat);
×
6588
  }
6589
}
3✔
6590

6591

6592

6593
/*
6594
 * Cleanup: restore ctx to a good state after check_context
6595
 * is interrupted.
6596
 */
6597
void context_cleanup(context_t *ctx) {
1✔
6598
  // restore the state to IDLE, propagate to all solvers (via pop)
6599
  assert(context_supports_cleaninterrupt(ctx));
6600
  context_invalidate_unsat_core_cache(ctx);
1✔
6601
  if (ctx->mcsat == NULL) {
1✔
6602
    smt_cleanup(ctx->core);
1✔
6603
  } else {
UNCOV
6604
    mcsat_clear(ctx->mcsat);
×
6605
  }
6606
}
1✔
6607

6608

6609

6610
/*
6611
 * Clear: prepare for more assertions and checks
6612
 * - free the boolean assignment
6613
 * - reset the status to IDLE
6614
 */
6615
void context_clear(context_t *ctx) {
42,171✔
6616
  assert(context_supports_multichecks(ctx));
6617
  context_invalidate_unsat_core_cache(ctx);
42,171✔
6618
  if (ctx->mcsat == NULL) {
42,171✔
6619
    smt_clear(ctx->core);
41,821✔
6620
  } else {
6621
    mcsat_clear(ctx->mcsat);
350✔
6622
  }
6623
}
42,171✔
6624

6625

6626

6627
/*
6628
 * Clear_unsat: prepare for pop if the status is UNSAT
6629
 * - remove assumptions if any
6630
 *
6631
 * - if clean interrupt is enabled, then there may be a mismatch between
6632
 *   the context's base_level and the core base_level.
6633
 * - it's possible to have ctx->core.base_level = ctx->base_level + 1
6634
 * - this happens because start_search in smt_core does an internal smt_push
6635
 *   to allow the core to be restored to a clean state if search is interrupted.
6636
 * - if search is not interrupted and the search returns UNSAT, then we're
6637
 *   in a state with core base level = context base level + 1.
6638
 */
6639
void context_clear_unsat(context_t *ctx) {
616✔
6640
  context_invalidate_unsat_core_cache(ctx);
616✔
6641
  if (ctx->mcsat == NULL) {
616✔
6642
    smt_clear_unsat(ctx->core);
387✔
6643
    assert(smt_base_level(ctx->core) == ctx->base_level);
6644
  } else {
6645
    mcsat_clear(ctx->mcsat);
229✔
6646
  }
6647
}
616✔
6648

6649

6650

6651
/*
6652
 * Add the blocking clause to ctx
6653
 * - ctx->status must be either SAT or UNKNOWN
6654
 * - this collects all decision literals in the current truth assignment
6655
 *   (say l_1, ..., l_k) then clears the current assignment and adds the
6656
 *  clause ((not l_1) \/ ... \/ (not l_k)).
6657
 *
6658
 * Return code:
6659
 * - TRIVIALLY_UNSAT: means that the blocking clause is empty (i.e., k = 0)
6660
 *   (in that case, the context status is set to UNSAT)
6661
 * - CTX_NO_ERROR: means that the blocking clause is not empty (i.e., k > 0)
6662
 *   (In this case, the context status is set to IDLE)
6663
 */
6664
int32_t assert_blocking_clause(context_t *ctx) {
24,855✔
6665
  ivector_t *v;
6666
  uint32_t i, n;
6667
  int32_t code;
6668

6669
  assert(smt_status(ctx->core) == YICES_STATUS_SAT ||
6670
         smt_status(ctx->core) == YICES_STATUS_UNKNOWN);
6671

6672
  // get decision literals and build the blocking clause
6673
  v = &ctx->aux_vector;
24,855✔
6674
  assert(v->size == 0);
6675
  collect_decision_literals(ctx->core, v);
24,855✔
6676
  n = v->size;
24,855✔
6677
  for (i=0; i<n; i++) {
36,264✔
6678
    v->data[i] = not(v->data[i]);
11,409✔
6679
  }
6680

6681
  // prepare for the new assertion + notify solvers of a new assertion
6682
  context_clear(ctx);
24,855✔
6683
  internalization_start(ctx->core);
24,855✔
6684

6685
  // add the blocking clause
6686
  add_clause(ctx->core, n, v->data);
24,855✔
6687
  ivector_reset(v);
24,855✔
6688

6689
  // force UNSAT if n = 0
6690
  code = CTX_NO_ERROR;
24,855✔
6691
  if (n == 0) {
24,855✔
6692
    code = TRIVIALLY_UNSAT;
16,817✔
6693
    ctx->core->status = YICES_STATUS_UNSAT;
16,817✔
6694
  }
6695

6696
  assert(n == 0 || smt_status(ctx->core) == YICES_STATUS_IDLE);
6697

6698
  return code;
24,855✔
6699
}
6700

6701

6702

6703

6704
/********************************
6705
 *  GARBAGE COLLECTION SUPPORT  *
6706
 *******************************/
6707

6708
/*
6709
 * Marker for all terms present in the eq_map
6710
 * - aux = the relevant term table.
6711
 * - each record p stores <k0, k1, val> where k0 and k1 are both
6712
 *   terms in aux and val is a literal in the core
6713
 */
UNCOV
6714
static void ctx_mark_eq(void *aux, const pmap2_rec_t *p) {
×
UNCOV
6715
  term_table_set_gc_mark(aux, index_of(p->k0));
×
UNCOV
6716
  term_table_set_gc_mark(aux, index_of(p->k1));
×
UNCOV
6717
}
×
6718

6719

6720
/*
6721
 * Go through all data structures in ctx and mark all terms and types
6722
 * that they use.
6723
 */
6724
void context_gc_mark(context_t *ctx) {
6✔
6725
  if (ctx->egraph != NULL) {
6✔
6726
    egraph_gc_mark(ctx->egraph);
1✔
6727
  }
6728
  if (ctx->fun_solver != NULL) {
6✔
6729
    fun_solver_gc_mark(ctx->fun_solver);
1✔
6730
  }
6731

6732
  intern_tbl_gc_mark(&ctx->intern);
6✔
6733

6734
  // empty all the term vectors to be safe
6735
  ivector_reset(&ctx->top_eqs);
6✔
6736
  ivector_reset(&ctx->top_atoms);
6✔
6737
  ivector_reset(&ctx->top_formulas);
6✔
6738
  ivector_reset(&ctx->top_interns);
6✔
6739
  ivector_reset(&ctx->subst_eqs);
6✔
6740
  ivector_reset(&ctx->aux_eqs);
6✔
6741

6742
  if (ctx->eq_cache != NULL) {
6✔
UNCOV
6743
    pmap2_iterate(ctx->eq_cache, ctx->terms, ctx_mark_eq);
×
6744
  }
6745

6746
  if (ctx->unsat_core_cache != NULL) {
6✔
6747
    uint32_t i, n;
UNCOV
6748
    n = ctx->unsat_core_cache->size;
×
UNCOV
6749
    for (i=0; i<n; i++) {
×
UNCOV
6750
      term_table_set_gc_mark(ctx->terms, index_of(ctx->unsat_core_cache->data[i]));
×
6751
    }
6752
  }
6753

6754
  if (ctx->mcsat != NULL) {
6✔
6755
    mcsat_gc_mark(ctx->mcsat);
5✔
6756
  }
6757
}
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