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

SRI-CSL / yices2 / 26675300141

29 May 2026 08:46PM UTC coverage: 68.798% (+3.4%) from 65.375%
26675300141

push

github

ahmed-irfan
Rework clause-deletion heuristic to CaDiCaL-style schedule

Replace the geometric, learned-clause-count-triggered reduce schedule
with a CaDiCaL-style one: trigger on conflict count and rebase the
reduction bound to num_conflicts + r-interval * sqrt(num_conflicts).

- context_solver.c: factor the reduce step into try_reduce_heuristic();
  trigger on num_conflicts instead of num_learned_clauses; widen the
  running reduce_threshold to uint64_t (conflict count is unbounded).
- search_parameters: drop r-threshold/r-fraction/r-factor, add
  r-initial-threshold and r-interval (defaults 300 / 25, matching
  CaDiCaL's reduceinit / reduceint).
- Update doc/YICES-LANGUAGE, doc/sphinx parameters table, and the
  interactive (help ...) entries for the renamed parameters.

10 of 10 new or added lines in 1 file covered. (100.0%)

8005 existing lines in 44 files now uncovered.

87475 of 127148 relevant lines covered (68.8%)

1646632.75 hits per line

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

81.43
/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/cdcl/delegate.h"
36
#include "solvers/simplex/simplex.h"
37
#include "terms/poly_buffer_terms.h"
38
#include "terms/term_utils.h"
39
#include "utils/memalloc.h"
40

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

44
#include "api/yices_globals.h"
45

46
#define TRACE 0
47

48
#if TRACE
49

50
#include <stdio.h>
51

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

55
#endif
56

57

58

59

60

61
/**********************
62
 *  INTERNALIZATION   *
63
 *********************/
64

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

77

78

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

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

92

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

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

112

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

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

124
  return tau;
1,582✔
125
}
126

127

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

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

141
  return pos_occ(u);
1,591✔
142
}
143

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

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

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

159

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

178

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

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

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

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

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

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

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

220
  return u;
64,990✔
221
}
222

223

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

232
  assert(! context_has_egraph(ctx));
233

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

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

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

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

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

UNCOV
257
  return code;
×
258
}
259

260

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

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

279

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

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

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

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

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

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

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

310
  return pos_occ(u);
9,697✔
311
}
312

313

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

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

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

UNCOV
333
  return u;
×
334
}
335

336

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

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

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

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

359

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

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

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

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

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

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

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

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

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

437
  return u;
8✔
438
}
439

440

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

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

457

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

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

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

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

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

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

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

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

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

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

532
  return u;
1,168✔
533
}
534

535

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

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

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

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

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

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

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

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

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

588

589

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

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

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

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

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

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

617

618

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

628
  n = tuple->arity;
190✔
629

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

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

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

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

643

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

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

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

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

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

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

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

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

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

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

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

689

690

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

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

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

713

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

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

732

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

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

748

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

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

765

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

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

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

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

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

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

830

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

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

851

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

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

870

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

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

889

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

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

UNCOV
903
  p = context_get_aux_poly(ctx, 4);
×
904

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

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

914

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

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

UNCOV
928
  p = context_get_aux_poly(ctx, 4);
×
929

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

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

939

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

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

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

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

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

966

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

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

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

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

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

1002

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

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

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

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

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

1041

1042

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

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

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

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

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

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

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

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

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

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

1123

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

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

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

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

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

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

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

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

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

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

1190
  return u;
2,521✔
1191
}
1192

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

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

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

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

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

1224

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

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

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

1237
  return v;
71✔
1238
}
1239

1240

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

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

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

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

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

1283

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

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

1295

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

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

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

UNCOV
1313
  return x;
×
1314
}
1315

1316

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

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

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

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

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

1345
  return x;
1,762✔
1346
}
1347

1348

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

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

UNCOV
1367
  return y;
×
1368
}
1369

1370

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

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

1389
  return y;
25✔
1390
}
1391

1392

1393

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

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

UNCOV
1408
  return y;
×
1409
}
1410

1411

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

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

UNCOV
1431
  return y;
×
1432
}
1433

1434

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

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

1447
  return y;
4✔
1448
}
1449

1450

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

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

1465

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

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

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

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

1493

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

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

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

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

1518
  return y;
6✔
1519
}
1520

1521

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

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

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

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

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

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

1556
  q_clear(&k);
11✔
1557

1558
  return r;
11✔
1559
}
1560

1561

1562

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

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

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

1576
  c = internalize_to_literal(ctx, ite->arg[0]);
19,499✔
1577
  if (c == true_literal) {
19,499✔
1578
    return internalize_to_bv(ctx, ite->arg[1]);
23✔
1579
  }
1580
  if (c == false_literal) {
19,476✔
1581
    return internalize_to_bv(ctx, ite->arg[2]);
1,976✔
1582
  }
1583

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

1588
  return ctx->bv.create_bvite(ctx->bv_solver, c, x, y);
17,500✔
1589
}
1590

1591

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

1602
  n = b->arity;
17,020✔
1603
  a = alloc_istack_array(&ctx->istack, n);
17,020✔
1604

1605
  save_options = ctx->options;
17,020✔
1606
  disable_diseq_and_or_flattening(ctx);
17,020✔
1607
  for (i=0; i<n; i++) {
497,999✔
1608
    a[i] = internalize_to_literal(ctx, b->arg[i]);
480,979✔
1609
  }
1610
  ctx->options = save_options;
17,020✔
1611

1612
  x = ctx->bv.create_bvarray(ctx->bv_solver, a, n);
17,020✔
1613

1614
  free_istack_array(&ctx->istack, a);
17,020✔
1615

1616
  return x;
17,020✔
1617
}
1618

1619

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

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

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

1633

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

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

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

1647

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

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

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

1661

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

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

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

1675

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

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

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

1689

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

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

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

1703

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

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

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

1717

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

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

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

1731

1732

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

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

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

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

1757
  return x;
585✔
1758
}
1759

1760

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

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

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

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

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

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

1790
  return x;
12,163✔
1791
}
1792

1793

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

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

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

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

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

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

1823
  return x;
607✔
1824
}
1825

1826

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

1838
  n = bvpoly_buffer_bitsize(b);
1839

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

1852
  return x;
1853
}
1854

1855
#endif
1856

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

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

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

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

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

1882

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

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

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

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

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

1908
  return l;
14,519✔
1909
}
1910

1911

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

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

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

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

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

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

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

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

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

1968
  return l;
80,820✔
1969
}
1970

1971

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

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

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

1989
  return l;
1✔
1990
}
1991

1992

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

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

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

2014
  return l;
4,368✔
2015
}
2016

2017

2018

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

2030
  assert(n >= 2);
2031

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

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

2046

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

2058
  assert(n >= 2);
2059

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

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

2074

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

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

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

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

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

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

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

2116
  return l;
9✔
2117
}
2118

2119

2120

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

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

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

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

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

2149
  return l;
1,192✔
2150
}
2151

2152

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

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

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

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

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

2181
  return l;
33,493✔
2182
}
2183

2184

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

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

2201
  return l;
33,841✔
2202
}
2203

2204

2205

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

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

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

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

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

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

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

2265
  return l;
53,504✔
2266
}
2267

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

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

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

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

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

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

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

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

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

2332
  return l;
92,139✔
2333
}
2334

2335

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

2341

2342

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

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

2363

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

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

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

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

UNCOV
2393
  return l;
×
2394
}
2395

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

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

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

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

2421
    q_clear(&k);
8✔
2422

2423
    return l;
8✔
2424

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

2431

2432
/*
2433
 * BITVECTOR ATOMS
2434
 */
2435

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

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

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

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

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

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

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

2477
  case BVEQ_CODE_FALSE:
×
UNCOV
2478
    return false_literal;
×
2479

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

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

2490
  default:
4,771✔
2491
    break;
4,771✔
2492
  }
2493

2494
  if (equal_bitvector_factors(ctx, t1, t2)) {
4,782✔
UNCOV
2495
    return true_literal;
×
2496
  }
2497

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

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

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

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

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

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

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

2526

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

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

2547

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2806
  // fix the polarity
2807
  return u ^ polarity;
103,401✔
2808

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

2813

2814

2815

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

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

2831
  assert(code_is_valid(x));
2832

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

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

2845

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2969
  }
2970

2971
  return x;
120,783✔
2972

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

2977

2978

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

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

2993
  assert(code_is_valid(x));
2994

2995
  if (code_is_eterm(x)) {
297,889✔
2996
    u = code2eterm(x);
29,164✔
2997
    assert(ctx->egraph != NULL && egraph_term_is_bv(ctx->egraph, u));
2998
    v = egraph_term_base_thvar(ctx->egraph, u);
29,164✔
2999
  } else {
3000
    v = code2thvar(x);
268,725✔
3001
  }
3002

3003
  assert(v != null_thvar);
3004

3005
  return v;
297,889✔
3006
}
3007

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

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

3021
  if (! context_has_bv_solver(ctx)) {
373,541✔
UNCOV
3022
    exception = BV_NOT_SUPPORTED;
×
UNCOV
3023
    goto abort;
×
3024
  }
3025

3026
  /*
3027
   * Apply the term substitution: t --> r
3028
   */
3029
  r = intern_tbl_get_root(&ctx->intern, t);
373,541✔
3030
  if (intern_tbl_root_is_mapped(&ctx->intern, r)) {
373,541✔
3031
    // r is already internalized
3032
    code = intern_tbl_map_of_root(&ctx->intern, r);
297,889✔
3033
    x = translate_code_to_bv(ctx, code);
297,889✔
3034
  } else {
3035
    // compute r's internalization
3036
    terms = ctx->terms;
75,652✔
3037

3038
    switch (term_kind(terms, r)) {
75,652✔
3039
    case BV64_CONSTANT:
7,001✔
3040
      x = ctx->bv.create_const64(ctx->bv_solver, bvconst64_term_desc(terms, r));
7,001✔
3041
      intern_tbl_map_root(&ctx->intern, r, thvar2code(x));
7,001✔
3042
      break;
7,001✔
3043

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3146
  return x;
373,541✔
3147

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

3152

3153

3154

3155

3156

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

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

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

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

3187
  return l;
1,396,320✔
3188
}
3189

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3302
    case BIT_TERM:
264,144✔
3303
      l = map_bit_select_to_literal(ctx, bit_term_desc(terms, r));
264,144✔
3304
      break;
264,144✔
3305

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

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

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

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

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

3327
 done:
1,824,095✔
3328
  return l ^ polarity;
1,824,095✔
3329
}
3330

3331

3332

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

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

3344
  assert(code_is_valid(x));
3345

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

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

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

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

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

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

3391

3392

3393

3394

3395

3396

3397
/********************************
3398
 *   ARITHMETIC SUBSTITUTIONS   *
3399
 *******************************/
3400

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

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

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

3421

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

3430
  reset_poly_buffer(buffer);
544✔
3431

3432
  assert(poly_buffer_is_zero(buffer));
3433

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

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

3449

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

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

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

3470

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

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

3496
  return NULL_TERM;
79✔
3497
}
3498

3499

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

3512
  n = buffer->nterms;
465✔
3513

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

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

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

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

3542
  return q;
465✔
3543
}
3544

3545

3546

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

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

3576

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

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

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

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

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

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

3619
  return true;
465✔
3620
}
3621

3622

3623

3624

3625

3626

3627

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

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

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

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

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

3658

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

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

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

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

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

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

3705

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

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

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

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

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

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

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

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

3758
  }
3759

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

3788

3789

3790

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

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

3803

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

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

3815
  n = app->arity;
252✔
3816

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

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

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

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

3842

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

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

3863

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

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

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

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

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

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

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

3949

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

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

3964

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

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

3979

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

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

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

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

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

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

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

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

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

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

4040

4041

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

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

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

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

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

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

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

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

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

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

4115

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

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

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

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

4145

4146

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

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

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

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

4185

4186

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

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

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

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

4216

4217

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

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

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

4239

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

4251

4252

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

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

4283

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

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

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

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

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

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

4327

4328

4329

4330

4331

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

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

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

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

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

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

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

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

4393

4394

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

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

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

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

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

4427

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

4438
  if (tt) {
42,973✔
4439
    if (context_flatten_or_enabled(ctx)) {
42,957✔
4440
      // Flatten into vector v
4441
      v = &ctx->aux_vector;
15,021✔
4442
      assert(v->size == 0);
4443
      flatten_or_term(ctx, v, or);
15,021✔
4444

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

4452
      // make a copy of v
4453
      a = alloc_istack_array(&ctx->istack, n);
14,050✔
4454
      for (i=0; i<n; i++) {
58,769✔
4455
        a[i] = v->data[i];
44,719✔
4456
      }
4457
      ivector_reset(v);
14,050✔
4458

4459
      for (i=0; i<n; i++) {
58,446✔
4460
        a[i] = internalize_to_literal(ctx, a[i]);
44,549✔
4461
        if (a[i] == true_literal) goto done;
44,549✔
4462
      }
4463

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

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

4480
    // assert (or a[0] ... a[n-1])
4481
    add_clause(ctx->core, n, a);
39,230✔
4482

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

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

4498
}
4499

4500

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

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

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

4518

4519

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

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

4542

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

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

4558

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

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

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

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

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

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

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

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

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

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

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

4629
    // flattening failed
4630
    ivector_reset(v);
7,512✔
4631
  }
4632

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

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

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

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

4656
  default:
9,230✔
4657
    break;
9,230✔
4658
  }
4659

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

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

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

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

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

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

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

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

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

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

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

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

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

4719

4720

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

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

4735
  tt = is_pos_term(t);
125,379✔
4736
  t = unsigned_term(t);
125,379✔
4737

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

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

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

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

4765
  case EQ_TERM:
5,145✔
4766
    assert_toplevel_eq(ctx, eq_term_desc(terms, t), tt);
5,145✔
4767
    break;
5,143✔
4768

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

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

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

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

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

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

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

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

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

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

4812
  case BIT_TERM:
32,260✔
4813
    assert_toplevel_bit_select(ctx, bit_term_desc(terms, t), tt);
32,260✔
4814
    break;
32,260✔
4815

4816
  case BV_EQ_ATOM:
9,292✔
4817
    assert_toplevel_bveq(ctx, bveq_atom_desc(terms, t), tt);
9,292✔
4818
    break;
9,284✔
4819

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

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

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

4833
  return;
125,365✔
4834

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

4839

4840

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4967
  return;
993✔
4968

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

4973

4974

4975

4976
/************************
4977
 *  PARAMETERS/OPTIONS  *
4978
 ***********************/
4979

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

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

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

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

5005

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

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

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

5037
  0,                        //  CTX_ARCH_AUTO_IDL
5038
  0,                        //  CTX_ARCH_AUTO_RDL
5039

5040
  MCSAT                     //  CTX_ARCH_MCSAT
5041
};
5042

5043

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

5054

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

5065

5066

5067

5068

5069

5070
/*
5071
 * SIMPLEX OPTIONS
5072
 */
5073

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

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

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

5095

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

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

5115

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

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

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

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

5144

5145

5146

5147
/******************
5148
 *  EMPTY SOLVER  *
5149
 *****************/
5150

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

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

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

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

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

5182

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

5188

5189

5190

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

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

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

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

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

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

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

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

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

5230

5231
/****************************
5232
 *  SOLVER INITIALIZATION   *
5233
 ***************************/
5234

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

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

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

5249

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

5258

5259

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

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

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

5289

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

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

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

5319

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

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

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

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

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

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

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

5372

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

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

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

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

5406
  } else {
5407

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

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

5427

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

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

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

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

5464

5465

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

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

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

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

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

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

5501

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

5508
  assert(ctx->egraph != NULL && ctx->fun_solver == NULL);
5509

5510
  solver = (fun_solver_t *) safe_malloc(sizeof(fun_solver_t));
4,432✔
5511
  init_fun_solver(solver, ctx->core, &ctx->gate_manager, ctx->egraph, ctx->types);
4,432✔
5512
  egraph_attach_funsolver(ctx->egraph, solver, fun_solver_ctrl_interface(solver),
4,432✔
5513
                          fun_solver_egraph_interface(solver),
5514
                          fun_solver_fun_egraph_interface(solver));
5515

5516
  ctx->fun_solver = solver;
4,432✔
5517
}
4,432✔
5518

5519

5520
/*
5521
 * Allocate and initialize solvers based on architecture and mode
5522
 * - core and gate manager must exist at this point
5523
 * - if the architecture is either AUTO_IDL or AUTO_RDL, no theory solver
5524
 *   is allocated yet, and the core is initialized for Boolean only
5525
 * - otherwise, all components are ready and initialized, including the core.
5526
 */
5527
static void init_solvers(context_t *ctx) {
22,368✔
5528
  uint8_t solvers;
5529
  smt_core_t *core;
5530
  smt_mode_t cmode;
5531
  egraph_t *egraph;
5532

5533
  solvers = arch_components[ctx->arch];
22,368✔
5534

5535
  ctx->egraph = NULL;
22,368✔
5536
  ctx->arith_solver = NULL;
22,368✔
5537
  ctx->bv_solver = NULL;
22,368✔
5538
  ctx->fun_solver = NULL;
22,368✔
5539
  ctx->quant_solver = NULL;
22,368✔
5540

5541
  // Create egraph first, then satellite solvers
5542
  if (solvers & EGRPH) {
22,368✔
5543
    create_egraph(ctx);
4,795✔
5544
  }
5545

5546
  // Create mcsat
5547
  if (solvers & MCSAT) {
22,368✔
5548
    create_mcsat(ctx);
738✔
5549
  }
5550

5551
  // Arithmetic solver
5552
  if (solvers & SPLX) {
22,368✔
5553
    create_simplex_solver(ctx, false);
14,910✔
5554
  } else if (solvers & IFW) {
7,458✔
UNCOV
5555
    create_idl_solver(ctx, false);
×
5556
  } else if (solvers & RFW) {
7,458✔
UNCOV
5557
    create_rdl_solver(ctx, false);
×
5558
  }
5559

5560
  // Bitvector solver
5561
  if (solvers & BVSLVR) {
22,368✔
5562
    create_bv_solver(ctx);
10,646✔
5563
  }
5564

5565
  // Array solver
5566
  if (solvers & FSLVR) {
22,368✔
5567
    create_fun_solver(ctx);
4,432✔
5568
  }
5569

5570
  /*
5571
   * At this point all solvers are ready and initialized, except the
5572
   * egraph and core if the egraph is present or the core if there are
5573
   * no solvers, or if arch is AUTO_IDL or AUTO_RDL.
5574
   */
5575
  cmode = core_mode[ctx->mode];   // initialization mode for the core
22,368✔
5576
  egraph = ctx->egraph;
22,368✔
5577
  core = ctx->core;
22,368✔
5578
  if (egraph != NULL) {
22,368✔
5579
    init_smt_core(core, CTX_DEFAULT_CORE_SIZE, egraph, egraph_ctrl_interface(egraph),
4,795✔
5580
                  egraph_smt_interface(egraph), cmode);
5581
    egraph_attach_core(egraph, core);
4,795✔
5582

5583
  } else if (solvers == 0) {
17,573✔
5584
    /*
5585
     * Boolean solver only. If arch if AUTO_IDL or AUTO_RDL, the
5586
     * theory solver will be changed later by create_auto_idl_solver
5587
     * or create_auto_rdl_solver.
5588
     */
5589
    assert(ctx->arith_solver == NULL && ctx->bv_solver == NULL && ctx->fun_solver == NULL);
5590
    init_smt_core(core, CTX_DEFAULT_CORE_SIZE, NULL, &null_ctrl, &null_smt, cmode);
36✔
5591
  } else if (solvers == MCSAT) {
17,537✔
5592
    /*
5593
     * MCsat solver only, we create the core, but never use it.
5594
     */
5595
    assert(ctx->egraph == NULL && ctx->arith_solver == NULL &&
5596
           ctx->bv_solver == NULL && ctx->fun_solver == NULL);
5597
    init_smt_core(core, CTX_DEFAULT_CORE_SIZE, NULL, &null_ctrl, &null_smt, cmode);
738✔
5598
  }
5599

5600
  /*
5601
   * Optimization: if the arch is NOSOLVERS or BV then we set bool_only in the core
5602
   */
5603
  if (ctx->arch == CTX_ARCH_NOSOLVERS || ctx->arch == CTX_ARCH_BV) {
22,368✔
5604
    smt_core_set_bool_only(core);
6,227✔
5605
  }
5606
}
22,368✔
5607

5608

5609

5610

5611
/*
5612
 * Delete the arithmetic solver
5613
 */
5614
static void delete_arith_solver(context_t *ctx) {
14,944✔
5615
  uint8_t solvers;
5616

5617
  assert(ctx->arith_solver != NULL);
5618

5619
  solvers = arch_components[ctx->arch];
14,944✔
5620
  if (solvers & IFW) {
14,944✔
5621
    delete_idl_solver(ctx->arith_solver);
26✔
5622
  } else if (solvers & RFW) {
14,918✔
5623
    delete_rdl_solver(ctx->arith_solver);
8✔
5624
  } else if (solvers & SPLX) {
14,910✔
5625
    delete_simplex_solver(ctx->arith_solver);
14,910✔
5626
  }
5627
  safe_free(ctx->arith_solver);
14,944✔
5628
  ctx->arith_solver = NULL;
14,944✔
5629
}
14,944✔
5630

5631

5632

5633

5634
/*****************************
5635
 *  CONTEXT INITIALIZATION   *
5636
 ****************************/
5637

5638
/*
5639
 * Check mode and architecture
5640
 */
5641
#ifndef NDEBUG
5642
static inline bool valid_mode(context_mode_t mode) {
5643
  return CTX_MODE_ONECHECK <= mode && mode <= CTX_MODE_INTERACTIVE;
5644
}
5645

5646
static inline bool valid_arch(context_arch_t arch) {
5647
  return CTX_ARCH_NOSOLVERS <= arch && arch <= CTX_ARCH_MCSAT;
5648
}
5649
#endif
5650

5651

5652
/*
5653
 * Initialize ctx for the given mode and architecture
5654
 * - terms = term table for that context
5655
 * - qflag = true means quantifiers allowed
5656
 * - qflag = false means no quantifiers
5657
 */
5658
void init_context(context_t *ctx, term_table_t *terms, smt_logic_t logic,
22,368✔
5659
                  context_mode_t mode, context_arch_t arch, bool qflag) {
5660
  assert(valid_mode(mode) && valid_arch(arch));
5661

5662
  /*
5663
   * Set architecture and options
5664
   */
5665
  ctx->mode = mode;
22,368✔
5666
  ctx->arch = arch;
22,368✔
5667
  ctx->logic = logic;
22,368✔
5668
  ctx->sat_delegate = SAT_DELEGATE_NONE;
22,368✔
5669
  ctx->sat_delegate_incremental_mode = SAT_DELEGATE_MODE_REBUILD;
22,368✔
5670
  ctx->sat_delegate_incremental_mode_set = false;
22,368✔
5671
  ctx->theories = arch2theories[arch];
22,368✔
5672
  ctx->options = mode2options[mode];
22,368✔
5673
  if (qflag) {
22,368✔
5674
    // quantifiers require egraph
5675
    assert((ctx->theories & UF_MASK) != 0);
UNCOV
5676
    ctx->theories |= QUANT_MASK;
×
5677
  }
5678

5679
  ctx->base_level = 0;
22,368✔
5680
  context_reset_sat_delegate_stats(ctx);
22,368✔
5681

5682
  /*
5683
   * The core is always needed: allocate it here. It's not initialized yet.
5684
   * The other solver are optionals.
5685
   *
5686
   * TODO: we could skip this when we use MCSAT (since then the core is
5687
   * not needed).
5688
   */
5689
  ctx->core = (smt_core_t *) safe_malloc(sizeof(smt_core_t));
22,368✔
5690
  ctx->egraph = NULL;
22,368✔
5691
  ctx->mcsat = NULL;
22,368✔
5692
  ctx->arith_solver = NULL;
22,368✔
5693
  ctx->bv_solver = NULL;
22,368✔
5694
  ctx->fun_solver = NULL;
22,368✔
5695
  ctx->quant_solver = NULL;
22,368✔
5696

5697
  /*
5698
   * Global tables + gate manager
5699
   */
5700
  ctx->types = terms->types;
22,368✔
5701
  ctx->terms = terms;
22,368✔
5702
  init_gate_manager(&ctx->gate_manager, ctx->core);
22,368✔
5703

5704
  /*
5705
   * Simplification/internalization support
5706
   */
5707
  init_intern_tbl(&ctx->intern, 0, terms);
22,368✔
5708
  init_ivector(&ctx->top_eqs, CTX_DEFAULT_VECTOR_SIZE);
22,368✔
5709
  init_ivector(&ctx->top_atoms, CTX_DEFAULT_VECTOR_SIZE);
22,368✔
5710
  init_ivector(&ctx->top_formulas, CTX_DEFAULT_VECTOR_SIZE);
22,368✔
5711
  init_ivector(&ctx->top_interns, CTX_DEFAULT_VECTOR_SIZE);
22,368✔
5712

5713
  /*
5714
   * Force the internalization mapping for true and false
5715
   * - true  term --> true_occ
5716
   * - false term --> false_occ
5717
   * This mapping holds even if there's no egraph.
5718
   */
5719
  intern_tbl_map_root(&ctx->intern, true_term, bool2code(true));
22,368✔
5720

5721
  /*
5722
   * Auxiliary internalization buffers
5723
   */
5724
  init_ivector(&ctx->subst_eqs, CTX_DEFAULT_VECTOR_SIZE);
22,368✔
5725
  init_ivector(&ctx->aux_eqs, CTX_DEFAULT_VECTOR_SIZE);
22,368✔
5726
  init_ivector(&ctx->aux_atoms, CTX_DEFAULT_VECTOR_SIZE);
22,368✔
5727
  init_ivector(&ctx->aux_vector, CTX_DEFAULT_VECTOR_SIZE);
22,368✔
5728
  init_int_queue(&ctx->queue, 0);
22,368✔
5729
  init_istack(&ctx->istack);
22,368✔
5730
  init_objstack(&ctx->ostack);
22,368✔
5731
  init_sharing_map(&ctx->sharing, &ctx->intern);
22,368✔
5732
  init_objstore(&ctx->cstore, sizeof(conditional_t), 32);
22,368✔
5733
  init_assumption_stack(&ctx->assumptions);
22,368✔
5734

5735
  ctx->subst = NULL;
22,368✔
5736
  ctx->marks = NULL;
22,368✔
5737
  ctx->cache = NULL;
22,368✔
5738
  ctx->small_cache = NULL;
22,368✔
5739
  ctx->edge_map = NULL;
22,368✔
5740
  ctx->eq_cache = NULL;
22,368✔
5741
  ctx->divmod_table = NULL;
22,368✔
5742
  ctx->explorer = NULL;
22,368✔
5743
  ctx->unsat_core_cache = NULL;
22,368✔
5744
  ctx->sat_delegate_state = NULL;
22,368✔
5745

5746
  ctx->dl_profile = NULL;
22,368✔
5747
  ctx->arith_buffer = NULL;
22,368✔
5748
  ctx->poly_buffer = NULL;
22,368✔
5749
  ctx->aux_poly = NULL;
22,368✔
5750
  ctx->aux_poly_size = 0;
22,368✔
5751

5752
  ctx->bvpoly_buffer = NULL;
22,368✔
5753

5754
  q_init(&ctx->aux);
22,368✔
5755
  init_bvconstant(&ctx->bv_buffer);
22,368✔
5756

5757
  ctx->trace = NULL;
22,368✔
5758

5759
  // mcsat options default
5760
  init_mcsat_options(&ctx->mcsat_options);
22,368✔
5761
  init_ivector(&ctx->mcsat_var_order, CTX_DEFAULT_VECTOR_SIZE);
22,368✔
5762
  init_ivector(&ctx->mcsat_initial_var_order, CTX_DEFAULT_VECTOR_SIZE);
22,368✔
5763
  /*
5764
   * Allocate and initialize the solvers and core
5765
   * NOTE: no theory solver yet if arch is AUTO_IDL or AUTO_RDL
5766
   */
5767
  init_solvers(ctx);
22,368✔
5768

5769
  ctx->en_quant = false;
22,368✔
5770
}
22,368✔
5771

5772

5773

5774

5775
/*
5776
 * Delete ctx
5777
 */
5778
void delete_context(context_t *ctx) {
22,367✔
5779
  context_sat_delegate_state_cleanup(ctx);
22,367✔
5780

5781
  if (ctx->core != NULL) {
22,367✔
5782
    delete_smt_core(ctx->core);
22,367✔
5783
    safe_free(ctx->core);
22,367✔
5784
    ctx->core = NULL;
22,367✔
5785
  }
5786

5787
  if (ctx->mcsat != NULL) {
22,367✔
5788
    mcsat_destruct(ctx->mcsat);
738✔
5789
    safe_free(ctx->mcsat);
738✔
5790
    ctx->mcsat = NULL;
738✔
5791
  }
5792

5793
  if (ctx->egraph != NULL) {
22,367✔
5794
    delete_egraph(ctx->egraph);
4,794✔
5795
    safe_free(ctx->egraph);
4,794✔
5796
    ctx->egraph = NULL;
4,794✔
5797
  }
5798

5799
  if (ctx->arith_solver != NULL) {
22,367✔
5800
    delete_arith_solver(ctx);
14,944✔
5801
  }
5802

5803
  if (ctx->fun_solver != NULL) {
22,367✔
5804
    delete_fun_solver(ctx->fun_solver);
4,431✔
5805
    safe_free(ctx->fun_solver);
4,431✔
5806
    ctx->fun_solver = NULL;
4,431✔
5807
  }
5808

5809
  if (ctx->quant_solver != NULL) {
22,367✔
5810
    delete_quant_solver(ctx->quant_solver);
52✔
5811
    safe_free(ctx->quant_solver);
52✔
5812
    ctx->quant_solver = NULL;
52✔
5813
  }
5814

5815
  if (ctx->bv_solver != NULL) {
22,367✔
5816
    delete_bv_solver(ctx->bv_solver);
10,645✔
5817
    safe_free(ctx->bv_solver);
10,645✔
5818
    ctx->bv_solver = NULL;
10,645✔
5819
  }
5820

5821
  delete_gate_manager(&ctx->gate_manager);
22,367✔
5822
  /* delete_mcsat_options(&ctx->mcsat_options); // if used then the same memory is freed twice */
5823
  delete_ivector(&ctx->mcsat_var_order);
22,367✔
5824
  delete_ivector(&ctx->mcsat_initial_var_order);
22,367✔
5825

5826
  delete_intern_tbl(&ctx->intern);
22,367✔
5827
  delete_ivector(&ctx->top_eqs);
22,367✔
5828
  delete_ivector(&ctx->top_atoms);
22,367✔
5829
  delete_ivector(&ctx->top_formulas);
22,367✔
5830
  delete_ivector(&ctx->top_interns);
22,367✔
5831

5832
  delete_ivector(&ctx->subst_eqs);
22,367✔
5833
  delete_ivector(&ctx->aux_eqs);
22,367✔
5834
  delete_ivector(&ctx->aux_atoms);
22,367✔
5835
  delete_ivector(&ctx->aux_vector);
22,367✔
5836
  delete_int_queue(&ctx->queue);
22,367✔
5837
  delete_istack(&ctx->istack);
22,367✔
5838
  delete_objstack(&ctx->ostack);
22,367✔
5839
  delete_sharing_map(&ctx->sharing);
22,367✔
5840
  delete_objstore(&ctx->cstore);
22,367✔
5841
  delete_assumption_stack(&ctx->assumptions);
22,367✔
5842

5843
  context_free_subst(ctx);
22,367✔
5844
  context_free_marks(ctx);
22,367✔
5845
  context_free_cache(ctx);
22,367✔
5846
  context_free_small_cache(ctx);
22,367✔
5847
  context_free_eq_cache(ctx);
22,367✔
5848
  context_free_divmod_table(ctx);
22,367✔
5849
  context_free_explorer(ctx);
22,367✔
5850

5851
  context_free_dl_profile(ctx);
22,367✔
5852
  context_free_edge_map(ctx);
22,367✔
5853
  context_free_arith_buffer(ctx);
22,367✔
5854
  context_free_poly_buffer(ctx);
22,367✔
5855
  context_free_aux_poly(ctx);
22,367✔
5856

5857
  context_free_bvpoly_buffer(ctx);
22,367✔
5858
  context_invalidate_unsat_core_cache(ctx);
22,367✔
5859

5860
  q_clear(&ctx->aux);
22,367✔
5861
  delete_bvconstant(&ctx->bv_buffer);
22,367✔
5862
}
22,367✔
5863

5864
void context_invalidate_unsat_core_cache(context_t *ctx) {
88,138✔
5865
  if (ctx->unsat_core_cache != NULL) {
88,138✔
5866
    delete_ivector(ctx->unsat_core_cache);
2,713✔
5867
    safe_free(ctx->unsat_core_cache);
2,713✔
5868
    ctx->unsat_core_cache = NULL;
2,713✔
5869
  }
5870
}
88,138✔
5871

5872

5873

5874
/*
5875
 * Reset: remove all assertions and clear all internalization tables
5876
 */
5877
void reset_context(context_t *ctx) {
3✔
5878
  ctx->base_level = 0;
3✔
5879
  context_reset_sat_delegate_stats(ctx);
3✔
5880
  context_invalidate_unsat_core_cache(ctx);
3✔
5881
  context_sat_delegate_state_cleanup(ctx);
3✔
5882

5883
  reset_smt_core(ctx->core); // this propagates reset to all solvers
3✔
5884

5885
  if (ctx->mcsat != NULL) {
3✔
5886
    mcsat_reset(ctx->mcsat);
2✔
5887
  }
5888

5889
  reset_gate_manager(&ctx->gate_manager);
3✔
5890

5891
  ivector_reset(&ctx->mcsat_var_order);
3✔
5892
  ivector_reset(&ctx->mcsat_initial_var_order);
3✔
5893

5894
  reset_intern_tbl(&ctx->intern);
3✔
5895
  ivector_reset(&ctx->top_eqs);
3✔
5896
  ivector_reset(&ctx->top_atoms);
3✔
5897
  ivector_reset(&ctx->top_formulas);
3✔
5898
  ivector_reset(&ctx->top_interns);
3✔
5899

5900
  // Force the internalization mapping for true and false
5901
  intern_tbl_map_root(&ctx->intern, true_term, bool2code(true));
3✔
5902

5903
  ivector_reset(&ctx->subst_eqs);
3✔
5904
  ivector_reset(&ctx->aux_eqs);
3✔
5905
  ivector_reset(&ctx->aux_atoms);
3✔
5906
  ivector_reset(&ctx->aux_vector);
3✔
5907
  int_queue_reset(&ctx->queue);
3✔
5908
  reset_istack(&ctx->istack);
3✔
5909
  reset_objstack(&ctx->ostack);
3✔
5910
  reset_sharing_map(&ctx->sharing);
3✔
5911
  reset_objstore(&ctx->cstore);
3✔
5912
  reset_assumption_stack(&ctx->assumptions);
3✔
5913

5914
  context_free_subst(ctx);
3✔
5915
  context_free_marks(ctx);
3✔
5916
  context_reset_small_cache(ctx);
3✔
5917
  context_reset_eq_cache(ctx);
3✔
5918
  context_reset_divmod_table(ctx);
3✔
5919
  context_reset_explorer(ctx);
3✔
5920

5921
  context_free_arith_buffer(ctx);
3✔
5922
  context_reset_poly_buffer(ctx);
3✔
5923
  context_free_aux_poly(ctx);
3✔
5924
  context_free_dl_profile(ctx);
3✔
5925

5926
  context_free_bvpoly_buffer(ctx);
3✔
5927

5928
  q_clear(&ctx->aux);
3✔
5929
}
3✔
5930

5931

5932
/*
5933
 * Add tracer to ctx and ctx->core
5934
 */
5935
void context_set_trace(context_t *ctx, tracer_t *trace) {
285✔
5936
  assert(ctx->trace == NULL);
5937
  ctx->trace = trace;
285✔
5938
  smt_core_set_trace(ctx->core, trace);
285✔
5939
  if (ctx->mcsat != NULL) {
285✔
5940
    mcsat_set_tracer(ctx->mcsat, trace);
284✔
5941
  }
5942
}
285✔
5943

5944

5945
/*
5946
 * Push and pop
5947
 */
5948
void context_push(context_t *ctx) {
18,592✔
5949
  assert(context_supports_pushpop(ctx));
5950
  context_invalidate_unsat_core_cache(ctx);
18,592✔
5951
  smt_push(ctx->core);  // propagates to all solvers
18,592✔
5952
  if (ctx->mcsat != NULL) {
18,592✔
5953
    mcsat_push(ctx->mcsat);
1,342✔
5954
  }
5955
  intern_tbl_push(&ctx->intern);
18,592✔
5956
  assumption_stack_push(&ctx->assumptions);
18,592✔
5957
  context_eq_cache_push(ctx);
18,592✔
5958
  context_divmod_table_push(ctx);
18,592✔
5959

5960
  ctx->base_level ++;
18,592✔
5961
}
18,592✔
5962

5963
void context_pop(context_t *ctx) {
1,573✔
5964
  assert(context_supports_pushpop(ctx) && ctx->base_level > 0);
5965
  context_invalidate_unsat_core_cache(ctx);
1,573✔
5966
  smt_pop(ctx->core);   // propagates to all solvers
1,573✔
5967
  if (ctx->mcsat != NULL) {
1,573✔
5968
    mcsat_pop(ctx->mcsat);
1,258✔
5969
  }
5970
  intern_tbl_pop(&ctx->intern);
1,573✔
5971
  assumption_stack_pop(&ctx->assumptions);
1,573✔
5972
  context_eq_cache_pop(ctx);
1,573✔
5973
  context_divmod_table_pop(ctx);
1,573✔
5974

5975
  context_sat_delegate_state_pop(ctx, ctx->base_level);
1,573✔
5976

5977
  ctx->base_level --;
1,573✔
5978
}
1,573✔
5979

5980

5981

5982

5983

5984
/****************************
5985
 *   ASSERTIONS AND CHECK   *
5986
 ***************************/
5987

5988
/*
5989
 * Build the sharing data
5990
 * - processes all the assertions in vectors top_eqs, top_atoms, top_formulas
5991
 * - this function should be called after building the substitutions
5992
 */
5993
static void context_build_sharing_data(context_t *ctx) {
71,889✔
5994
  sharing_map_t *map;
5995

5996
  map = &ctx->sharing;
71,889✔
5997
  reset_sharing_map(map);
71,889✔
5998
  sharing_map_add_terms(map, ctx->top_eqs.data, ctx->top_eqs.size);
71,889✔
5999
  sharing_map_add_terms(map, ctx->top_atoms.data, ctx->top_atoms.size);
71,889✔
6000
  sharing_map_add_terms(map, ctx->top_formulas.data, ctx->top_formulas.size);
71,889✔
6001
}
71,889✔
6002

6003

6004
#if 0
6005
/*
6006
 * PROVISIONAL: SHOW ASSERTIONS
6007
 */
6008
static void context_show_assertions(const context_t *ctx, uint32_t n, const term_t *a) {
6009
  pp_area_t area;
6010
  yices_pp_t printer;
6011
  uint32_t i;
6012

6013
  area.width = 80;
6014
  area.height = UINT32_MAX;
6015
  area.offset = 0;
6016
  area.stretch = false;
6017
  area.truncate = false;
6018
  init_yices_pp(&printer, stdout, &area, PP_VMODE, 0);
6019

6020
  for (i=0; i<n; i++) {
6021
    pp_term_full(&printer, ctx->terms, a[i]);
6022
    flush_yices_pp(&printer);
6023
  }
6024
  delete_yices_pp(&printer, true);
6025
}
6026
#endif
6027

6028
/*
6029
 * Flatten and internalize assertions a[0 ... n-1]
6030
 * - all elements a[i] must be valid boolean term in ctx->terms
6031
 * - return code:
6032
 *   TRIVIALLY_UNSAT if there's an easy contradiction
6033
 *   CTX_NO_ERROR if the assertions were processed without error
6034
 *   a negative error code otherwise.
6035
 */
6036
static int32_t context_process_assertions(context_t *ctx, uint32_t n, const term_t *a) {
74,703✔
6037
  ivector_t *v;
6038
  uint32_t i;
6039
  int code;
6040

6041
  ivector_reset(&ctx->top_eqs);
74,703✔
6042
  ivector_reset(&ctx->top_atoms);
74,703✔
6043
  ivector_reset(&ctx->top_formulas);
74,703✔
6044
  ivector_reset(&ctx->top_interns);
74,703✔
6045
  ivector_reset(&ctx->subst_eqs);
74,703✔
6046
  ivector_reset(&ctx->aux_eqs);
74,703✔
6047
  ivector_reset(&ctx->aux_atoms);
74,703✔
6048

6049
  code = setjmp(ctx->env);
74,703✔
6050
  if (code == 0) {
75,100✔
6051

6052
    // If using MCSAT, just check and done
6053
    if (ctx->mcsat != NULL) {
74,703✔
6054
      // TBD: quant support
6055
      assert(!context_quant_enabled(ctx));
6056
      code = mcsat_assert_formulas(ctx->mcsat, n, a);
2,442✔
6057
      goto done;
2,431✔
6058
    }
6059

6060
#if 0
6061
    printf("\n=== Context: process assertions ===\n");
6062
    context_show_assertions(ctx, n, a);
6063
    printf("===\n\n");
6064
#endif
6065

6066
    // flatten
6067
    for (i=0; i<n; i++) {
195,608✔
6068
      flatten_assertion(ctx, a[i]);
123,718✔
6069
    }
6070

6071
    trace_printf(ctx->trace, 6, "(done flattening)\n");
71,890✔
6072

6073
    /*
6074
     * At this point, the assertions are stored into the vectors
6075
     * top_eqs, top_atoms, top_formulas, and top_interns
6076
     * - more top-level equalities may be in subst_eqs
6077
     * - ctx->intern stores the internalized terms and the variable
6078
     *   substitutions.
6079
     */
6080

6081
    switch (ctx->arch) {
71,890✔
6082
    // TBD: make sure following preprocessings work with quant enabled
6083
    case CTX_ARCH_EG:
3,329✔
6084
      /*
6085
       * UF problem: we must process subst_eqs last since the
6086
       * preprocessing may add new equalities in aux_eqs that may end
6087
       * up in subst_eqs after the call to process_aux_eqs.
6088
       */
6089
      if (context_breaksym_enabled(ctx)) {
3,329✔
6090
        break_uf_symmetries(ctx);
30✔
6091
      }
6092
      if (context_eq_abstraction_enabled(ctx)) {
3,329✔
6093
        analyze_uf(ctx);
64✔
6094
      }
6095
      if (ctx->aux_eqs.size > 0) {
3,329✔
6096
        process_aux_eqs(ctx);
6✔
6097
      }
6098
      if (ctx->subst_eqs.size > 0) {
3,328✔
6099
        context_process_candidate_subst(ctx);
10✔
6100
      }
6101
      break;
3,328✔
6102

6103
    case CTX_ARCH_AUTO_IDL:
27✔
6104
      /*
6105
       * For difference logic, we must process the subst_eqs first
6106
       * (otherwise analyze_diff_logic may give wrong results).
6107
       */
6108
      if (ctx->subst_eqs.size > 0) {
27✔
UNCOV
6109
        context_process_candidate_subst(ctx);
×
6110
      }
6111
      analyze_diff_logic(ctx, true);
27✔
6112
      create_auto_idl_solver(ctx);
27✔
6113
      break;
27✔
6114

6115
    case CTX_ARCH_AUTO_RDL:
8✔
6116
      /*
6117
       * Difference logic, we must process the subst_eqs first
6118
       */
6119
      trace_printf(ctx->trace, 6, "(auto-idl solver)\n");
8✔
6120
      if (ctx->subst_eqs.size > 0) {
8✔
UNCOV
6121
        context_process_candidate_subst(ctx);
×
6122
      }
6123
      analyze_diff_logic(ctx, false);
8✔
6124
      create_auto_rdl_solver(ctx);
8✔
6125
      break;
8✔
6126

6127
    case CTX_ARCH_SPLX:
30,674✔
6128
      /*
6129
       * Simplex, like EG, may add aux_atoms so we must process
6130
       * subst_eqs last here.
6131
       */
6132
      trace_printf(ctx->trace, 6, "(Simplex solver)\n");
30,674✔
6133
      // more optional processing
6134
      if (context_cond_def_preprocessing_enabled(ctx)) {
30,674✔
6135
        process_conditional_definitions(ctx);
52✔
6136
        if (ctx->aux_eqs.size > 0) {
52✔
6137
          process_aux_eqs(ctx);
2✔
6138
        }
6139
        if (ctx->aux_atoms.size > 0) {
52✔
6140
          process_aux_atoms(ctx);
3✔
6141
        }
6142
      }
6143
      if (ctx->subst_eqs.size > 0) {
30,674✔
6144
        context_process_candidate_subst(ctx);
16✔
6145
      }
6146
      break;
30,674✔
6147

6148
    default:
37,852✔
6149
      /*
6150
       * Process the candidate variable substitutions if any
6151
       */
6152
      if (ctx->subst_eqs.size > 0) {
37,852✔
6153
        context_process_candidate_subst(ctx);
2,749✔
6154
      }
6155
      break;
37,852✔
6156
    }
6157

6158
    /*
6159
     * Sharing
6160
     */
6161
    context_build_sharing_data(ctx);
71,889✔
6162

6163
    /*
6164
     * Notify the core + solver(s)
6165
     */
6166
    if (!context_quant_enabled(ctx)) {
71,889✔
6167
        // TBD: make sure this is correct
6168
      internalization_start(ctx->core);
69,356✔
6169
    }
6170

6171
    /*
6172
     * Assert top_eqs, top_atoms, top_formulas, top_interns
6173
     */
6174
    code = CTX_NO_ERROR;
71,889✔
6175

6176
    // first: all terms that are already internalized
6177
    v = &ctx->top_interns;
71,889✔
6178
    n = v->size;
71,889✔
6179
    if (n > 0) {
71,889✔
6180
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" existing terms)\n", n);
283✔
6181
      i = 0;
283✔
6182
      do {
6183
        assert_toplevel_intern(ctx, v->data[i]);
738✔
6184
        i ++;
738✔
6185
      } while (i < n);
738✔
6186

6187
      // one round of propagation
6188
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
283✔
6189
        code = TRIVIALLY_UNSAT;
10✔
6190
        goto done;
10✔
6191
      }
6192
    }
6193

6194
    // second: all top-level equalities
6195
    v = &ctx->top_eqs;
71,879✔
6196
    n = v->size;
71,879✔
6197
    if (n > 0) {
71,879✔
6198
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" top-level equalities)\n", n);
6,767✔
6199
      i = 0;
6,767✔
6200
      do {
6201
        assert_toplevel_formula(ctx, v->data[i]);
10,833✔
6202
        i ++;
10,830✔
6203
      } while (i < n);
10,830✔
6204

6205
      // one round of propagation
6206
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
6,764✔
6207
        code = TRIVIALLY_UNSAT;
65✔
6208
        goto done;
65✔
6209
      }
6210
    }
6211

6212
    // third: all top-level atoms (other than equalities)
6213
    v = &ctx->top_atoms;
71,811✔
6214
    n = v->size;
71,811✔
6215
    if (n > 0) {
71,811✔
6216
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" top-level atoms)\n", n);
15,509✔
6217
      i = 0;
15,509✔
6218
      do {
6219
        assert_toplevel_formula(ctx, v->data[i]);
68,797✔
6220
        i ++;
68,786✔
6221
      } while (i < n);
68,786✔
6222

6223
      // one round of propagation
6224
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
15,498✔
6225
        code = TRIVIALLY_UNSAT;
75✔
6226
        goto done;
75✔
6227
      }
6228
    }
6229

6230
    // last: all non-atomic, formulas
6231
    v =  &ctx->top_formulas;
71,725✔
6232
    n = v->size;
71,725✔
6233
    if (n > 0) {
71,725✔
6234
      trace_printf(ctx->trace, 6, "(asserting  %"PRIu32" top-level formulas)\n", n);
22,023✔
6235
      i = 0;
22,023✔
6236
      do {
6237
        assert_toplevel_formula(ctx, v->data[i]);
45,749✔
6238
        i ++;
45,749✔
6239
      } while (i < n);
45,749✔
6240

6241
      // one round of propagation
6242
      if (!context_quant_enabled(ctx) && ! base_propagate(ctx->core)) {
22,023✔
6243
        code = TRIVIALLY_UNSAT;
63✔
6244
        goto done;
63✔
6245
      }
6246
    }
6247

6248
  } else {
6249
    /*
6250
     * Exception: return from longjmp(ctx->env, code);
6251
     */
6252
    ivector_reset(&ctx->aux_vector);
397✔
6253
    reset_istack(&ctx->istack);
397✔
6254
    reset_objstack(&ctx->ostack);
397✔
6255
    int_queue_reset(&ctx->queue);
397✔
6256
    context_free_subst(ctx);
397✔
6257
    context_free_marks(ctx);
397✔
6258
  }
6259

6260
 done:
74,703✔
6261
  return code;
74,703✔
6262
}
6263

6264
/*
6265
 * Assert all formulas f[0] ... f[n-1]
6266
 * The context status must be IDLE.
6267
 *
6268
 * Return code:
6269
 * - TRIVIALLY_UNSAT means that an inconsistency is detected
6270
 *   (in that case the context status is set to UNSAT)
6271
 * - CTX_NO_ERROR means no internalization error and status not
6272
 *   determined
6273
 * - otherwise, the code is negative to report an error.
6274
 */
6275
int32_t _o_assert_formulas(context_t *ctx, uint32_t n, const term_t *f) {
72,169✔
6276
  int32_t code;
6277

6278
  assert(ctx->arch == CTX_ARCH_AUTO_IDL ||
6279
         ctx->arch == CTX_ARCH_AUTO_RDL ||
6280
         smt_status(ctx->core) == YICES_STATUS_IDLE);
6281
  assert(!context_quant_enabled(ctx));
6282

6283
  code = context_process_assertions(ctx, n, f);
72,169✔
6284
  if (code == TRIVIALLY_UNSAT) {
72,169✔
6285
    if (ctx->arch == CTX_ARCH_AUTO_IDL || ctx->arch == CTX_ARCH_AUTO_RDL) {
592✔
6286
      // cleanup: reset arch/config to 'no theory'
6287
      assert(ctx->arith_solver == NULL && ctx->bv_solver == NULL && ctx->fun_solver == NULL &&
6288
             ctx->mode == CTX_MODE_ONECHECK);
6289
      ctx->arch = CTX_ARCH_NOSOLVERS;
1✔
6290
      ctx->theories = 0;
1✔
6291
      ctx->options = 0;
1✔
6292
    }
6293

6294
    if( smt_status(ctx->core) != YICES_STATUS_UNSAT) {
592✔
6295
      // force UNSAT in the core
6296
      add_empty_clause(ctx->core);
379✔
6297
      ctx->core->status = YICES_STATUS_UNSAT;
379✔
6298
    }
6299
  }
6300

6301
  return code;
72,169✔
6302
}
6303

6304
/*
6305
 * Assert all formulas f[0] ... f[n-1] during quantifier instantiation
6306
 * The context status must be SEARCHING.
6307
 *
6308
 * Return code:
6309
 * - TRIVIALLY_UNSAT means that an inconsistency is detected
6310
 *   (in that case the context status is set to UNSAT)
6311
 * - CTX_NO_ERROR means no internalization error and status not
6312
 *   determined
6313
 * - otherwise, the code is negative to report an error.
6314
 */
6315
int32_t quant_assert_formulas(context_t *ctx, uint32_t n, const term_t *f) {
2,534✔
6316
  int32_t code;
6317

6318
  assert(context_quant_enabled(ctx));
6319
  assert(smt_status(ctx->core) == YICES_STATUS_SEARCHING);
6320

6321
  code = context_process_assertions(ctx, n, f);
2,534✔
6322
  if (code == TRIVIALLY_UNSAT) {
2,534✔
6323
    if (ctx->arch == CTX_ARCH_AUTO_IDL || ctx->arch == CTX_ARCH_AUTO_RDL) {
1✔
6324
      // cleanup: reset arch/config to 'no theory'
6325
      assert(ctx->arith_solver == NULL && ctx->bv_solver == NULL && ctx->fun_solver == NULL &&
6326
      ctx->mode == CTX_MODE_ONECHECK);
UNCOV
6327
      ctx->arch = CTX_ARCH_NOSOLVERS;
×
UNCOV
6328
      ctx->theories = 0;
×
UNCOV
6329
      ctx->options = 0;
×
6330
    }
6331

6332
    if( smt_status(ctx->core) != YICES_STATUS_UNSAT) {
1✔
6333
      // force UNSAT in the core
6334
      add_empty_clause(ctx->core);
1✔
6335
      ctx->core->status = YICES_STATUS_UNSAT;
1✔
6336
    }
6337
  }
6338

6339
  return code;
2,534✔
6340
}
6341

6342
int32_t assert_formulas(context_t *ctx, uint32_t n, const term_t *f) {
18,473✔
6343
  MT_PROTECT(int32_t, __yices_globals.lock, _o_assert_formulas(ctx, n, f));
18,473✔
6344
}
6345

6346

6347

6348

6349
/*
6350
 * Assert a boolean formula f.
6351
 *
6352
 * The context status must be IDLE.
6353
 *
6354
 * Return code:
6355
 * - TRIVIALLY_UNSAT means that an inconsistency is detected
6356
 *   (in that case the context status is set to UNSAT)
6357
 * - CTX_NO_ERROR means no internalization error and status not
6358
 *   determined
6359
 * - otherwise, the code is negative. The assertion could
6360
 *   not be processed.
6361
 */
6362
int32_t _o_assert_formula(context_t *ctx, term_t f) {
53,696✔
6363
  return _o_assert_formulas(ctx, 1, &f);
53,696✔
6364
}
6365

6366
int32_t assert_formula(context_t *ctx, term_t f) {
49,317✔
6367
  MT_PROTECT(int32_t, __yices_globals.lock, _o_assert_formula(ctx, f));
49,317✔
6368
}
6369

6370

6371
/*
6372
 * Convert boolean term t to a literal l in context ctx
6373
 * - t must be a boolean term
6374
 * - return a negative code if there's an error
6375
 * - return a literal (l >= 0) otherwise.
6376
 */
6377
int32_t context_internalize(context_t *ctx, term_t t) {
87,602✔
6378
  int code;
6379
  literal_t l;
6380

6381
  ivector_reset(&ctx->top_eqs);
87,602✔
6382
  ivector_reset(&ctx->top_atoms);
87,602✔
6383
  ivector_reset(&ctx->top_formulas);
87,602✔
6384
  ivector_reset(&ctx->top_interns);
87,602✔
6385
  ivector_reset(&ctx->subst_eqs);
87,602✔
6386
  ivector_reset(&ctx->aux_eqs);
87,602✔
6387

6388
  code = setjmp(ctx->env);
87,602✔
6389
  if (code == 0) {
87,602✔
6390
    // we must call internalization start first
6391
    if (!context_quant_enabled(ctx)) {
87,602✔
6392
      // TBD: make sure this is correct
6393
      internalization_start(ctx->core);
87,498✔
6394
    }
6395
    l = internalize_to_literal(ctx, t);
87,602✔
6396
  } else {
6397
    assert(code < 0);
6398
    /*
6399
     * Clean up
6400
     */
6401
    ivector_reset(&ctx->aux_vector);
×
6402
    reset_istack(&ctx->istack);
×
6403
    int_queue_reset(&ctx->queue);
×
6404
    context_free_subst(ctx);
×
UNCOV
6405
    context_free_marks(ctx);
×
6406
    l = code;
×
6407
  }
6408

6409
  return l;
87,602✔
6410
}
6411

6412

6413
/*
6414
 * Build an assumption for Boolean term t:
6415
 * - this converts t to a literal l in context ctx
6416
 *   then create an indicator variable x in the core
6417
 *   and add the clause (x => l) in the core.
6418
 * - return a negative code if t can't be internalized
6419
 * - return the literal x otherwise (where x>=0).
6420
 */
6421
int32_t context_add_assumption(context_t *ctx, term_t t) {
87,507✔
6422
  int32_t l, x;
6423

6424
  // check if we already have an assumption literal for t
6425
  x = assumption_literal_for_term(&ctx->assumptions, t);
87,507✔
6426
  if (x < 0) {
87,507✔
6427
    l = context_internalize(ctx, t);
87,498✔
6428
    if (l < 0) return l; // error code
87,498✔
6429

6430
    x = pos_lit(create_boolean_variable(ctx->core));
87,498✔
6431
    add_binary_clause(ctx->core, not(x), l); // clause (x implies l)
87,498✔
6432

6433
    assumption_stack_add(&ctx->assumptions, t, x);
87,498✔
6434
  }
6435

6436
  return x;
87,507✔
6437
}
6438

6439

6440

6441
/*
6442
 * PROVISIONAL: FOR TESTING/DEBUGGING
6443
 */
6444

6445
/*
6446
 * Preprocess formula f or array of formulas f[0 ... n-1]
6447
 * - this does flattening + build substitutions
6448
 * - return code: as in assert_formulas
6449
 * - the result is stored in the internal vectors
6450
 *     ctx->top_interns
6451
 *     ctx->top_eqs
6452
 *     ctx->top_atoms
6453
 *     ctx->top_formulas
6454
 *   + ctx->intern stores substitutions
6455
 */
UNCOV
6456
int32_t context_process_formulas(context_t *ctx, uint32_t n, term_t *f) {
×
6457
  uint32_t i;
6458
  int code;
6459

UNCOV
6460
  ivector_reset(&ctx->top_eqs);
×
6461
  ivector_reset(&ctx->top_atoms);
×
6462
  ivector_reset(&ctx->top_formulas);
×
6463
  ivector_reset(&ctx->top_interns);
×
UNCOV
6464
  ivector_reset(&ctx->subst_eqs);
×
6465
  ivector_reset(&ctx->aux_eqs);
×
UNCOV
6466
  ivector_reset(&ctx->aux_atoms);
×
6467

UNCOV
6468
  code = setjmp(ctx->env);
×
UNCOV
6469
  if (code == 0) {
×
6470
    // flatten
6471
    for (i=0; i<n; i++) {
×
6472
      flatten_assertion(ctx, f[i]);
×
6473
    }
6474

6475
    /*
6476
     * At this point, the assertions are stored into the vectors
6477
     * top_eqs, top_atoms, top_formulas, and top_interns
6478
     * - more top-level equalities may be in subst_eqs
6479
     * - ctx->intern stores the internalized terms and the variable
6480
     *   substitutions.
6481
     */
6482

6483
    switch (ctx->arch) {
×
UNCOV
6484
    case CTX_ARCH_EG:
×
6485
      /*
6486
       * UF problem: we must process subst_eqs last since the
6487
       * preprocessing may add new equalities in aux_eqs that may end
6488
       * up in subst_eqs after the call to process_aux_eqs.
6489
       */
6490
      if (context_breaksym_enabled(ctx)) {
×
UNCOV
6491
        break_uf_symmetries(ctx);
×
6492
      }
UNCOV
6493
      if (context_eq_abstraction_enabled(ctx)) {
×
UNCOV
6494
        analyze_uf(ctx);
×
6495
      }
UNCOV
6496
      if (ctx->aux_eqs.size > 0) {
×
UNCOV
6497
        process_aux_eqs(ctx);
×
6498
      }
UNCOV
6499
      if (ctx->subst_eqs.size > 0) {
×
6500
        context_process_candidate_subst(ctx);
×
6501
      }
UNCOV
6502
      break;
×
6503

UNCOV
6504
    case CTX_ARCH_AUTO_IDL:
×
6505
      /*
6506
       * For difference logic, we must process the subst_eqs first
6507
       * (otherwise analyze_diff_logic may give wrong results).
6508
       */
6509
      if (ctx->subst_eqs.size > 0) {
×
6510
        context_process_candidate_subst(ctx);
×
6511
      }
UNCOV
6512
      analyze_diff_logic(ctx, true);
×
6513
      create_auto_idl_solver(ctx);
×
UNCOV
6514
      break;
×
6515

6516
    case CTX_ARCH_AUTO_RDL:
×
6517
      /*
6518
       * Difference logic, we must process the subst_eqs first
6519
       */
UNCOV
6520
      if (ctx->subst_eqs.size > 0) {
×
UNCOV
6521
        context_process_candidate_subst(ctx);
×
6522
      }
UNCOV
6523
      analyze_diff_logic(ctx, false);
×
UNCOV
6524
      create_auto_rdl_solver(ctx);
×
UNCOV
6525
      break;
×
6526

UNCOV
6527
    case CTX_ARCH_SPLX:
×
6528
      /*
6529
       * Simplex, like EG, may add aux_atoms so we must process
6530
       * subst_eqs last here.
6531
       */
6532
      // more optional processing
UNCOV
6533
      if (context_cond_def_preprocessing_enabled(ctx)) {
×
UNCOV
6534
        process_conditional_definitions(ctx);
×
UNCOV
6535
        if (ctx->aux_eqs.size > 0) {
×
UNCOV
6536
          process_aux_eqs(ctx);
×
6537
        }
UNCOV
6538
        if (ctx->aux_atoms.size > 0) {
×
UNCOV
6539
          process_aux_atoms(ctx);
×
6540
        }
6541
      }
UNCOV
6542
      if (ctx->subst_eqs.size > 0) {
×
UNCOV
6543
        context_process_candidate_subst(ctx);
×
6544
      }
UNCOV
6545
      break;
×
6546

UNCOV
6547
    default:
×
6548
      /*
6549
       * Process the candidate variable substitutions if any
6550
       */
UNCOV
6551
      if (ctx->subst_eqs.size > 0) {
×
UNCOV
6552
        context_process_candidate_subst(ctx);
×
6553
      }
UNCOV
6554
      break;
×
6555
    }
6556

6557
    /*
6558
     * Sharing
6559
     */
UNCOV
6560
    context_build_sharing_data(ctx);
×
6561

UNCOV
6562
    code = CTX_NO_ERROR;
×
6563

6564
  } else {
6565
    /*
6566
     * Exception: return from longjmp(ctx->env, code);
6567
     */
UNCOV
6568
    ivector_reset(&ctx->aux_vector);
×
UNCOV
6569
    reset_istack(&ctx->istack);
×
UNCOV
6570
    int_queue_reset(&ctx->queue);
×
UNCOV
6571
    context_free_subst(ctx);
×
UNCOV
6572
    context_free_marks(ctx);
×
6573
  }
6574

UNCOV
6575
  return code;
×
6576
}
6577

UNCOV
6578
int32_t context_process_formula(context_t *ctx, term_t f) {
×
UNCOV
6579
  return context_process_formulas(ctx, 1, &f);
×
6580
}
6581

6582

6583

6584
/*
6585
 * The search function 'check_context' is defined in context_solver.c
6586
 */
6587

6588

6589
/*
6590
 * Interrupt the search.
6591
 */
6592
void context_stop_search(context_t *ctx) {
3✔
6593
  if (ctx->mcsat == NULL) {
3✔
6594
    stop_search(ctx->core);
3✔
6595
    if (context_has_simplex_solver(ctx)) {
3✔
6596
      simplex_stop_search(ctx->arith_solver);
3✔
6597
    }
6598
  } else {
UNCOV
6599
    mcsat_stop_search(ctx->mcsat);
×
6600
  }
6601
}
3✔
6602

6603

6604

6605
/*
6606
 * Cleanup: restore ctx to a good state after check_context
6607
 * is interrupted.
6608
 */
6609
void context_cleanup(context_t *ctx) {
1✔
6610
  // restore the state to IDLE, propagate to all solvers (via pop)
6611
  assert(context_supports_cleaninterrupt(ctx));
6612
  context_invalidate_unsat_core_cache(ctx);
1✔
6613
  if (ctx->mcsat == NULL) {
1✔
6614
    smt_cleanup(ctx->core);
1✔
6615
  } else {
UNCOV
6616
    mcsat_clear(ctx->mcsat);
×
6617
  }
6618
}
1✔
6619

6620

6621

6622
/*
6623
 * Clear: prepare for more assertions and checks
6624
 * - free the boolean assignment
6625
 * - reset the status to IDLE
6626
 */
6627
void context_clear(context_t *ctx) {
42,263✔
6628
  assert(context_supports_multichecks(ctx));
6629
  context_invalidate_unsat_core_cache(ctx);
42,263✔
6630
  if (ctx->mcsat == NULL) {
42,263✔
6631
    smt_clear(ctx->core);
41,903✔
6632
  } else {
6633
    mcsat_clear(ctx->mcsat);
360✔
6634
  }
6635
}
42,263✔
6636

6637

6638

6639
/*
6640
 * Clear_unsat: prepare for pop if the status is UNSAT
6641
 * - remove assumptions if any
6642
 *
6643
 * - if clean interrupt is enabled, then there may be a mismatch between
6644
 *   the context's base_level and the core base_level.
6645
 * - it's possible to have ctx->core.base_level = ctx->base_level + 1
6646
 * - this happens because start_search in smt_core does an internal smt_push
6647
 *   to allow the core to be restored to a clean state if search is interrupted.
6648
 * - if search is not interrupted and the search returns UNSAT, then we're
6649
 *   in a state with core base level = context base level + 1.
6650
 */
6651
void context_clear_unsat(context_t *ctx) {
647✔
6652
  context_invalidate_unsat_core_cache(ctx);
647✔
6653
  if (ctx->mcsat == NULL) {
647✔
6654
    smt_clear_unsat(ctx->core);
411✔
6655
    assert(smt_base_level(ctx->core) == ctx->base_level);
6656
  } else {
6657
    mcsat_clear(ctx->mcsat);
236✔
6658
  }
6659
}
647✔
6660

6661

6662

6663
/*
6664
 * Add the blocking clause to ctx
6665
 * - ctx->status must be either SAT or UNKNOWN
6666
 * - this collects all decision literals in the current truth assignment
6667
 *   (say l_1, ..., l_k) then clears the current assignment and adds the
6668
 *  clause ((not l_1) \/ ... \/ (not l_k)).
6669
 *
6670
 * Return code:
6671
 * - TRIVIALLY_UNSAT: means that the blocking clause is empty (i.e., k = 0)
6672
 *   (in that case, the context status is set to UNSAT)
6673
 * - CTX_NO_ERROR: means that the blocking clause is not empty (i.e., k > 0)
6674
 *   (In this case, the context status is set to IDLE)
6675
 */
6676
int32_t assert_blocking_clause(context_t *ctx) {
24,859✔
6677
  ivector_t *v;
6678
  uint32_t i, n;
6679
  int32_t code;
6680

6681
  assert(smt_status(ctx->core) == YICES_STATUS_SAT ||
6682
         smt_status(ctx->core) == YICES_STATUS_UNKNOWN);
6683

6684
  // get decision literals and build the blocking clause
6685
  v = &ctx->aux_vector;
24,859✔
6686
  assert(v->size == 0);
6687
  collect_decision_literals(ctx->core, v);
24,859✔
6688
  n = v->size;
24,859✔
6689
  for (i=0; i<n; i++) {
36,197✔
6690
    v->data[i] = not(v->data[i]);
11,338✔
6691
  }
6692

6693
  // prepare for the new assertion + notify solvers of a new assertion
6694
  context_clear(ctx);
24,859✔
6695
  internalization_start(ctx->core);
24,859✔
6696

6697
  // add the blocking clause
6698
  add_clause(ctx->core, n, v->data);
24,859✔
6699
  ivector_reset(v);
24,859✔
6700

6701
  // force UNSAT if n = 0
6702
  code = CTX_NO_ERROR;
24,859✔
6703
  if (n == 0) {
24,859✔
6704
    code = TRIVIALLY_UNSAT;
16,817✔
6705
    ctx->core->status = YICES_STATUS_UNSAT;
16,817✔
6706
  }
6707

6708
  assert(n == 0 || smt_status(ctx->core) == YICES_STATUS_IDLE);
6709

6710
  return code;
24,859✔
6711
}
6712

6713

6714

6715

6716
/********************************
6717
 *  GARBAGE COLLECTION SUPPORT  *
6718
 *******************************/
6719

6720
/*
6721
 * Marker for all terms present in the eq_map
6722
 * - aux = the relevant term table.
6723
 * - each record p stores <k0, k1, val> where k0 and k1 are both
6724
 *   terms in aux and val is a literal in the core
6725
 */
UNCOV
6726
static void ctx_mark_eq(void *aux, const pmap2_rec_t *p) {
×
UNCOV
6727
  term_table_set_gc_mark(aux, index_of(p->k0));
×
UNCOV
6728
  term_table_set_gc_mark(aux, index_of(p->k1));
×
UNCOV
6729
}
×
6730

6731

6732
/*
6733
 * Go through all data structures in ctx and mark all terms and types
6734
 * that they use.
6735
 */
6736
void context_gc_mark(context_t *ctx) {
12✔
6737
  if (ctx->egraph != NULL) {
12✔
6738
    egraph_gc_mark(ctx->egraph);
1✔
6739
  }
6740
  if (ctx->fun_solver != NULL) {
12✔
6741
    fun_solver_gc_mark(ctx->fun_solver);
1✔
6742
  }
6743

6744
  intern_tbl_gc_mark(&ctx->intern);
12✔
6745

6746
  // empty all the term vectors to be safe
6747
  ivector_reset(&ctx->top_eqs);
12✔
6748
  ivector_reset(&ctx->top_atoms);
12✔
6749
  ivector_reset(&ctx->top_formulas);
12✔
6750
  ivector_reset(&ctx->top_interns);
12✔
6751
  ivector_reset(&ctx->subst_eqs);
12✔
6752
  ivector_reset(&ctx->aux_eqs);
12✔
6753

6754
  if (ctx->eq_cache != NULL) {
12✔
UNCOV
6755
    pmap2_iterate(ctx->eq_cache, ctx->terms, ctx_mark_eq);
×
6756
  }
6757

6758
  if (ctx->unsat_core_cache != NULL) {
12✔
6759
    uint32_t i, n;
UNCOV
6760
    n = ctx->unsat_core_cache->size;
×
UNCOV
6761
    for (i=0; i<n; i++) {
×
UNCOV
6762
      term_table_set_gc_mark(ctx->terms, index_of(ctx->unsat_core_cache->data[i]));
×
6763
    }
6764
  }
6765

6766
  if (ctx->mcsat != NULL) {
12✔
6767
    mcsat_gc_mark(ctx->mcsat);
11✔
6768
  }
6769
}
12✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc