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

SRI-CSL / yices2 / 6439378463

07 Oct 2023 05:49AM UTC coverage: 65.097% (-0.001%) from 65.098%
6439378463

push

github

web-flow
Update action.yml

79159 of 121602 relevant lines covered (65.1%)

1505389.34 hits per line

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

89.13
/src/solvers/simplex/simplex.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
 * SIMPLEX SOLVER
21
 *
22
 * Version 3: started 2008/11/03
23
 */
24

25
#include <inttypes.h>
26

27
#include "io/tracer.h"
28
#include "solvers/egraph/theory_explanations.h"
29
#include "solvers/simplex/integrality_constraints.h"
30
#include "solvers/simplex/simplex.h"
31
#include "terms/rational_hash_maps.h"
32
#include "utils/assert_utils.h"
33
#include "utils/bitvectors.h"
34
#include "utils/dep_tables.h"
35
#include "utils/dprng.h"
36
#include "utils/hash_functions.h"
37
#include "utils/int_hash_classes.h"
38

39

40
/*
41
 * To enable general trace, set TRACE to 1
42
 * To enable the debugging code, set DEBUG to 1
43
 * To dump the initial tableau, set DUMP to 1
44
 *
45
 * To trace simplifications and tableau initialization set TRACE_INIT to 1
46
 * To trace the theory propagation set TRACE_PROPAGATION to 1 (in
47
 * To trace the branch&bound algorithm set TRACE_BB to 1
48
 * To get a summary of general solution + bounds: TRACE_INTFEAS to 1
49
 */
50
#define TRACE   0
51
#define DEBUG   0
52
#define DUMP    0
53

54
#define TRACE_INIT 0
55
#define TRACE_PROPAGATION 0
56
#define TRACE_BB 0
57
#define TRACE_INTFEAS 0
58

59
#if TRACE || DEBUG || DUMP || TRACE_INIT || TRACE_PROPAGATION || TRACE_BB || TRACE_INTFEAS || !defined(NDEBUG)
60

61
#include <stdio.h>
62

63
#include "io/term_printer.h"
64
#include "solvers/simplex/dsolver_printer.h"
65
#include "solvers/egraph/egraph_printer.h"
66
#include "solvers/cdcl/gates_printer.h"
67
#include "solvers/cdcl/smt_core_printer.h"
68
#include "solvers/simplex/simplex_printer.h"
69

70
#endif
71

72

73
/*
74
 * Debugging functions are defined at the end of this file
75
 */
76
#if DUMP
77

78
static void print_simplex(FILE *f, simplex_solver_t *solver);
79
static void dump_state(simplex_solver_t *solver);
80

81
#endif
82

83

84
#if DEBUG
85

86
static void check_assignment(simplex_solver_t *solver);
87
static void check_nonbasic_assignment(simplex_solver_t *solver);
88
static void check_vartags(simplex_solver_t *solver);
89
static void check_infeasible_vars(simplex_solver_t *solver);
90
static void check_integer_bounds(simplex_solver_t *solver);
91
static void check_bound_marks(simplex_solver_t *solver);
92

93
static void check_equation_satisfied(simplex_solver_t *solver, uint32_t r);
94

95
#endif
96

97

98
#if TRACE
99

100
static void show_heap(FILE *f, simplex_solver_t *solver);
101

102
#endif
103

104

105

106
/**********
107
 *  PRNG  *
108
 *********/
109

110
/*
111
 * PARAMETERS FOR THE PSEUDO RANDOM NUMBER GENERATOR
112
 *
113
 * We  use the same linear congruence as in prng.h,
114
 * but we use a local implementation so that different
115
 * solvers can use different seeds.
116
 */
117
#define SPLX_PRNG_MULTIPLIER 1664525
118
#define SPLX_PRNG_CONSTANT   1013904223
119
#define SPLX_PRNG_SEED       0xabcdef98
120

121

122
/*
123
 * Return a 32bit unsigned int
124
 */
125
static inline uint32_t random_uint32(simplex_solver_t *s) {
55,690✔
126
  uint32_t x;
127

128
  x = s->prng;
55,690✔
129
  s->prng = x * ((uint32_t) SPLX_PRNG_MULTIPLIER) + ((uint32_t) SPLX_PRNG_CONSTANT);
55,690✔
130
  return x;
55,690✔
131
}
132

133

134
/*
135
 * Return a 32bit integer between 0 and n-1
136
 * - n must be positive
137
 */
138
static inline uint32_t random_uint(simplex_solver_t *s, uint32_t n) {
55,690✔
139
  assert(n > 0);
140
  return (random_uint32(s) >> 8) % n;
55,690✔
141
}
142

143

144

145

146
/*************************
147
 *   BOUND QUEUE/STACK   *
148
 ************************/
149

150
/*
151
 * Each element i in the stack is an assertion of the form (x <= u) or (x >= l)
152
 * - x is an arithmetic variable  (stored in var[i])
153
 * - u or l is an extended rational (of the form a + b\delta) stored in bound[i]
154
 * - the assertion has an explanation stored in expl[i]
155
 *   - expl[i].lit = null_literal means that's an axiom (asserted at level 0)
156
 *   - expl[i].lit = literal l such that atom l is the bound
157
 *   - expl[i].ptr = array of bound indices that imply bound i (terminated by -1)
158
 *   - expl[i].v = a pair of variables (v[0], v[1]) if the bound is asserted
159
 *                 as the result of the egraph propagating v[0] == v[1]
160
 * - for backtracking, pre[i] stores the previous assertion of the same type,
161
 *   on the same variable.
162
 * - bit upper[i] identifies the constraint type: upper[i] = 1 means (x <= u)
163
 *   upper[i] = 0 means (x >= l)
164
 *
165
 * Other components:
166
 * - top = top of the stack
167
 * - prop_ptr = index of the first assertion to process for literal propagation
168
 *   (all bounds of index prop_ptr to top-1 are unprocessed)
169
 * - fix_ptr = index of the first assertion to process for updating assignments
170
 *   (all bound of index fix_ptr to top-1 are to be processed)
171
 * - size = size of all subarrays
172
 */
173

174

175
/*
176
 * Initialize the stack
177
 * - n = initial size
178
 * All extended rationals in array bounds are initialized
179
 */
180
static void init_arith_bstack(arith_bstack_t *stack, uint32_t n) {
4,880✔
181
  xrational_t *tmp;
182
  uint32_t i;
183

184
  assert(n < MAX_ARITH_BSTACK_SIZE);
185

186
  tmp = (xrational_t *) safe_malloc(n * sizeof(xrational_t));
4,880✔
187
  for (i=0; i<n; i++) {
492,880✔
188
    xq_init(tmp + i);
488,000✔
189
  }
190
  stack->bound = tmp;
4,880✔
191
  stack->var = (thvar_t *) safe_malloc(n * sizeof(thvar_t));
4,880✔
192
  stack->expl = (arith_expl_t *) safe_malloc(n * sizeof(arith_expl_t));
4,880✔
193
  stack->pre = (int32_t *) safe_malloc(n * sizeof(int32_t));
4,880✔
194
  stack->tag = (uint8_t *) safe_malloc(n * sizeof(uint8_t));
4,880✔
195

196
  stack->top = 0;
4,880✔
197
  stack->prop_ptr = 0;
4,880✔
198
  stack->fix_ptr = 0;
4,880✔
199
  stack->size = n;
4,880✔
200
}
4,880✔
201

202

203
/*
204
 * Extend the stack by 50%
205
 * - initialize all the new extended rationals
206
 */
207
static void extend_arith_bstack(arith_bstack_t *stack) {
213✔
208
  xrational_t *tmp;
209
  uint32_t i ,n;
210

211
  n = stack->size + 1;
213✔
212
  n += n>>1;
213✔
213

214
  if (n >= MAX_ARITH_BSTACK_SIZE) {
213✔
215
    out_of_memory();
×
216
  }
217

218
  tmp = (xrational_t *) safe_realloc(stack->bound, n * sizeof(xrational_t));
213✔
219
  for (i=stack->size; i<n; i++) {
37,035✔
220
    xq_init(tmp + i);
36,822✔
221
  }
222
  stack->bound = tmp;
213✔
223
  stack->var = (thvar_t *) safe_realloc(stack->var, n * sizeof(thvar_t));
213✔
224
  stack->expl = (arith_expl_t *) safe_realloc(stack->expl, n * sizeof(arith_expl_t));
213✔
225
  stack->pre = (int32_t *) safe_realloc(stack->pre, n * sizeof(int32_t));
213✔
226
  stack->tag = (uint8_t *) safe_realloc(stack->tag, n * sizeof(uint8_t));
213✔
227
  stack->size = n;
213✔
228
}
213✔
229

230

231
/*
232
 * Allocate a new constraint descriptor on top of the stack
233
 * - return its index
234
 * - none of the constraint components is initialized
235
 */
236
static int32_t arith_bstack_new_constraint(arith_bstack_t *stack) {
1,881,571✔
237
  uint32_t i;
238

239
  i = stack->top;
1,881,571✔
240
  if (i == stack->size) {
1,881,571✔
241
    extend_arith_bstack(stack);
213✔
242
  }
243
  assert(i < stack->size);
244
  stack->top = i+1;
1,881,571✔
245
  return i;
1,881,571✔
246
}
247

248

249

250
/*
251
 * Delete the stack: free all rationals and all allocated arrays
252
 */
253
static void delete_arith_bstack(arith_bstack_t *stack) {
4,880✔
254
  uint32_t i, n;
255

256
  n = stack->size;
4,880✔
257
  for (i=0; i<n; i++) {
529,702✔
258
    xq_clear(stack->bound + i);
524,822✔
259
  }
260

261
  safe_free(stack->bound);
4,880✔
262
  safe_free(stack->var);
4,880✔
263
  safe_free(stack->expl);
4,880✔
264
  safe_free(stack->pre);
4,880✔
265
  safe_free(stack->tag);
4,880✔
266

267
  stack->bound = NULL;
4,880✔
268
  stack->var = NULL;
4,880✔
269
  stack->expl = NULL;
4,880✔
270
  stack->pre = NULL;
4,880✔
271
  stack->tag = NULL;
4,880✔
272
}
4,880✔
273

274

275

276
/*
277
 * Empty the stack. Also free all the rationals.
278
 */
279
static void reset_arith_bstack(arith_bstack_t *stack) {
1✔
280
  uint32_t i, n;
281

282
  n = stack->size;
1✔
283
  for (i=0; i<n; i++) {
101✔
284
    xq_clear(stack->bound + i);
100✔
285
  }
286

287
  stack->top = 0;
1✔
288
  stack->prop_ptr = 0;
1✔
289
  stack->fix_ptr = 0;
1✔
290
}
1✔
291

292

293

294
/*
295
 * Check a constraint's type
296
 */
297
static inline bool constraint_is_lower_bound(arith_bstack_t *stack, uint32_t i) {
4,943,869✔
298
  assert(i < stack->top);
299
  return arith_tag_get_type(stack->tag[i]) == ATYPE_LB;
4,943,869✔
300
}
301

302
static inline bool constraint_is_upper_bound(arith_bstack_t *stack, uint32_t i) {
1,001,604✔
303
  assert(i < stack->top);
304
  return arith_tag_get_type(stack->tag[i]) == ATYPE_UB;
1,001,604✔
305
}
306

307

308

309

310

311
/***************************************
312
 *  ASSERTION STACK/PROPAGATION QUEUE  *
313
 **************************************/
314

315
/*
316
 * Initialize the stack
317
 * - n = initial size (must be less than max size)
318
 */
319
static void init_arith_astack(arith_astack_t *stack, uint32_t n) {
4,880✔
320
  assert(n < MAX_ARITH_ASTACK_SIZE);
321
  stack->size = n;
4,880✔
322
  stack->top = 0;
4,880✔
323
  stack->prop_ptr = 0;
4,880✔
324
  stack->data = (int32_t *) safe_malloc(n * sizeof(int32_t));
4,880✔
325
}
4,880✔
326

327

328
/*
329
 * Make the stack 50% larger
330
 */
331
static void extend_arith_astack(arith_astack_t *stack) {
171✔
332
  uint32_t n;
333

334
  n = stack->size + 1;
171✔
335
  n += n >> 1;
171✔
336
  if (n >= MAX_ARITH_ASTACK_SIZE) {
171✔
337
    out_of_memory();
×
338
  }
339

340
  stack->data = (int32_t *) safe_realloc(stack->data, n * sizeof(int32_t));
171✔
341
  stack->size = n;
171✔
342
}
171✔
343

344

345
/*
346
 * Add an assertion a on top of the stack
347
 */
348
static void push_assertion(arith_astack_t *stack, int32_t a) {
2,274,543✔
349
  uint32_t i;
350

351
  i = stack->top;
2,274,543✔
352
  if (i == stack->size) {
2,274,543✔
353
    extend_arith_astack(stack);
171✔
354
  }
355
  assert(i < stack->size);
356
  stack->data[i] = a;
2,274,543✔
357
  stack->top = i+1;
2,274,543✔
358
}
2,274,543✔
359

360

361
/*
362
 * Empty the stack
363
 */
364
static void reset_arith_astack(arith_astack_t *stack) {
1✔
365
  stack->top = 0;
1✔
366
  stack->prop_ptr = 0;
1✔
367
}
1✔
368

369

370
/*
371
 * Delete the stack
372
 */
373
static void delete_arith_astack(arith_astack_t *stack) {
4,880✔
374
  safe_free(stack->data);
4,880✔
375
  stack->data = NULL;
4,880✔
376
}
4,880✔
377

378

379

380
/*
381
 * Assertion encoding:
382
 * - an atom is identified by its 32bit index in the atom table
383
 * - there are no more than UINT32_MAX/16 atoms so atom ids fit in 28bits
384
 * - an assertion is an atom id + a sign bit packed into 32bits
385
 * The sign bit is the lower-order bit of the assertion:
386
 * - sign bit = 0 means atom asserted true
387
 * - sign bit = 1 means atom asserted false
388
 *
389
 * The following functions convert between atom_id+sign and 32bit code
390
 */
391
static inline int32_t mk_assertion(int32_t atom_id, uint32_t sign) {
2,274,543✔
392
  assert(sign == 0 || sign == 1);
393
  return (atom_id << 1) | sign;
2,274,543✔
394
}
395

396
static inline int32_t atom_of_assertion(int32_t a) {
4,060,077✔
397
  return a>>1;
4,060,077✔
398
}
399

400
static inline uint32_t sign_of_assertion(int32_t a) {
1,810,980✔
401
  return ((uint32_t) a) & 1;
1,810,980✔
402
}
403

404
#if DEBUG || TRACE
405
static inline bool assertion_is_true(int32_t a) {
406
  return sign_of_assertion(a) == 0;
407
}
408
#endif
409

410
#if DEBUG
411
static inline bool assertion_is_false(int32_t a) {
412
  return sign_of_assertion(a) == 1;
413
}
414
#endif
415

416

417

418
/****************
419
 *  UNDO STACK  *
420
 ***************/
421

422
/*
423
 * Initialize: n = initial size
424
 */
425
static void init_arith_undo_stack(arith_undo_stack_t *stack, uint32_t n) {
4,880✔
426
  assert(n < MAX_ARITH_UNDO_STACK_SIZE);
427

428
  stack->size = n;
4,880✔
429
  stack->top = 0;
4,880✔
430
  stack->data = (arith_undo_record_t *) safe_malloc(n * sizeof(arith_undo_record_t));
4,880✔
431
}
4,880✔
432

433
/*
434
 * Make the stack 50% larger
435
 */
436
static void extend_arith_undo_stack(arith_undo_stack_t *stack) {
103✔
437
  uint32_t n;
438

439
  n = stack->size + 1;
103✔
440
  n += n >> 1;
103✔
441
  if (n >= MAX_ARITH_UNDO_STACK_SIZE) {
103✔
442
    out_of_memory();
×
443
  }
444
  stack->size = n;
103✔
445
  stack->data = (arith_undo_record_t *) safe_realloc(stack->data, n * sizeof(arith_undo_record_t));
103✔
446
}
103✔
447

448

449
/*
450
 * Push (n_b, n_a) on top of the stack
451
 * - n_b = number of bounds in the bstack
452
 * - n_a = number of assertions in the astack
453
 */
454
static void arith_push_undo_record(arith_undo_stack_t *stack, uint32_t n_b, uint32_t n_a) {
654,409✔
455
  uint32_t i;
456

457
  i = stack->top;
654,409✔
458
  if (i == stack->size) {
654,409✔
459
    extend_arith_undo_stack(stack);
103✔
460
  }
461
  assert(i < stack->size);
462
  stack->data[i].n_bounds = n_b;
654,409✔
463
  stack->data[i].n_assertions = n_a;
654,409✔
464
  stack->top = i+1;
654,409✔
465
}
654,409✔
466

467

468
/*
469
 * Empty the stack
470
 */
471
static void reset_arith_undo_stack(arith_undo_stack_t *stack) {
1✔
472
  stack->top = 0;
1✔
473
}
1✔
474

475

476

477
/*
478
 * Delete the stack
479
 */
480
static void delete_arith_undo_stack(arith_undo_stack_t *stack) {
4,880✔
481
  safe_free(stack->data);
4,880✔
482
  stack->data = NULL;
4,880✔
483
}
4,880✔
484

485

486

487

488

489
/********************
490
 *  PUSH/POP STACK  *
491
 *******************/
492

493
/*
494
 * Initialize: initial size = 0
495
 */
496
static void init_arith_trail(arith_trail_stack_t *stack) {
4,880✔
497
  stack->size = 0;
4,880✔
498
  stack->top = 0;
4,880✔
499
  stack->data = NULL;
4,880✔
500
}
4,880✔
501

502
/*
503
 * Save a base-level:
504
 * - nv = number of variables
505
 * - na = number of atoms
506
 * - nr = number of saved rows
507
 * - pa = propagation pointer in the assertion stack
508
 * - pb = propagation pointer in the bound stack
509
 */
510
static void arith_trail_save(arith_trail_stack_t *stack, uint32_t nv, uint32_t na, uint32_t nr, uint32_t pa, uint32_t pb) {
4,400✔
511
  uint32_t i, n;
512

513
  i = stack->top;
4,400✔
514
  n = stack->size;
4,400✔
515
  if (i == n) {
4,400✔
516
    if (n == 0) {
4,234✔
517
      n = DEF_SIMPLEX_TRAIL_SIZE;
4,234✔
518
    } else {
519
      n += n;
×
520
      if (n >= MAX_SIMPLEX_TRAIL_SIZE) {
×
521
        out_of_memory();
×
522
      }
523
    }
524
    stack->data = (arith_trail_t *) safe_realloc(stack->data, n * sizeof(arith_trail_t));
4,234✔
525
    stack->size = n;
4,234✔
526
  }
527
  assert(i < stack->size);
528

529
  stack->data[i].nvars = nv;
4,400✔
530
  stack->data[i].natoms = na;
4,400✔
531
  stack->data[i].nsaved_rows = nr;
4,400✔
532
  stack->data[i].bound_ptr = pb;
4,400✔
533
  stack->data[i].assertion_ptr = pa;
4,400✔
534

535
  stack->top = i+1;
4,400✔
536
}
4,400✔
537

538

539
/*
540
 * Get the top record
541
 */
542
static arith_trail_t *arith_trail_top(arith_trail_stack_t *stack) {
172✔
543
  assert(stack->top > 0);
544
  return stack->data + (stack->top - 1);
172✔
545
}
546

547
/*
548
 * Remove the top record
549
 */
550
static void arith_trail_pop(arith_trail_stack_t *stack) {
172✔
551
  assert(stack->top > 0);
552
  stack->top --;
172✔
553
}
172✔
554

555
/*
556
 * Delete the stack
557
 */
558
static void delete_arith_trail(arith_trail_stack_t *stack) {
4,880✔
559
  safe_free(stack->data);
4,880✔
560
  stack->data = NULL;
4,880✔
561
}
4,880✔
562

563

564
/*
565
 * Empty the stack
566
 */
567
static void reset_arith_trail(arith_trail_stack_t *stack) {
1✔
568
  stack->top = 0;
1✔
569
}
1✔
570

571

572

573

574

575
/*****************
576
 *  SAVED ROWS   *
577
 ****************/
578

579
/*
580
 * Delete polynomials in vector *v
581
 * - n = number of polynomials to keep
582
 */
583
static void delete_saved_rows(pvector_t *v, uint32_t n) {
5,053✔
584
  uint32_t i, k;
585

586
  k = v->size;
5,053✔
587
  assert(n <= k);
588

589
  for (i=n; i<k; i++) {
5,828✔
590
    free_polynomial(v->data[i]);
775✔
591
    v->data[i] = NULL;
775✔
592
  }
593
  pvector_shrink(v, n);
5,053✔
594
}
5,053✔
595

596

597
/***********************
598
 *  STATISTICS RECORD  *
599
 **********************/
600

601
/*
602
 * Initialize/reset all counters to 0
603
 */
604
static void init_simplex_statistics(simplex_stats_t *stat) {
4,881✔
605
  stat->num_init_vars = 0;
4,881✔
606
  stat->num_init_rows = 0;
4,881✔
607
  stat->num_atoms = 0;
4,881✔
608
  stat->num_elim_candidates = 0;
4,881✔
609
  stat->num_elim_rows = 0;
4,881✔
610
  stat->num_simpl_fvars = 0;
4,881✔
611
  stat->num_simpl_rows = 0;
4,881✔
612
  stat->num_fixed_vars = 0;
4,881✔
613
  stat->num_rows = 0;
4,881✔
614
  stat->num_end_rows = 0;
4,881✔
615
  stat->num_end_atoms = 0;
4,881✔
616
  stat->num_binary_lemmas = 0;
4,881✔
617
  stat->num_prop_lemmas = 0;
4,881✔
618
  stat->num_props = 0;
4,881✔
619
  stat->num_bound_props = 0;
4,881✔
620
  stat->num_prop_expl = 0;
4,881✔
621
  stat->num_interface_lemmas = 0;
4,881✔
622
  stat->num_reduced_inter_lemmas = 0;
4,881✔
623
  stat->num_tricho_lemmas = 0;
4,881✔
624
  stat->num_reduced_tricho = 0;
4,881✔
625
  stat->num_make_feasible = 0;
4,881✔
626
  stat->num_pivots = 0;
4,881✔
627
  stat->num_blands = 0;
4,881✔
628
  stat->num_conflicts = 0;
4,881✔
629

630
  stat->num_make_intfeasible = 0;
4,881✔
631
  stat->num_bound_conflicts = 0;
4,881✔
632
  stat->num_bound_recheck_conflicts = 0;
4,881✔
633
  stat->num_itest_conflicts = 0;
4,881✔
634
  stat->num_itest_bound_conflicts = 0;
4,881✔
635
  stat->num_itest_recheck_conflicts = 0;
4,881✔
636
  stat->num_dioph_checks = 0;
4,881✔
637
  stat->num_dioph_gcd_conflicts = 0;
4,881✔
638
  stat->num_dioph_conflicts = 0;
4,881✔
639
  stat->num_dioph_bound_conflicts = 0;
4,881✔
640
  stat->num_dioph_recheck_conflicts = 0;
4,881✔
641

642
  stat->num_branch_atoms = 0;
4,881✔
643
  stat->num_gomory_cuts = 0;
4,881✔
644
}
4,881✔
645

646

647
static void reset_simplex_statistics(simplex_stats_t *stat) {
1✔
648
  init_simplex_statistics(stat);
1✔
649
}
1✔
650

651

652

653
/**********************
654
 *  INTERVAL RECORDS  *
655
 *********************/
656

657
/*
658
 * Initialize the record:
659
 * - all rationals are zero, no bounds
660
 * - tag, k_min, k_max are not initialized yet
661
 */
662
static void init_interval(interval_t *s) {
888✔
663
  s->has_lb = false;
888✔
664
  s->has_ub = false;
888✔
665
  xq_init(&s->lb);
888✔
666
  xq_init(&s->ub);
888✔
667
  q_init(&s->period);
888✔
668
}
888✔
669

670

671
/*
672
 * Reset all to zero, no bounds
673
 */
674
static void reset_interval(interval_t *s) {
35,833✔
675
  s->has_lb = false;
35,833✔
676
  s->has_ub = false;
35,833✔
677
  xq_clear(&s->lb);
35,833✔
678
  xq_clear(&s->ub);
35,833✔
679
  q_clear(&s->period);
35,833✔
680
}
35,833✔
681

682

683
/*
684
 * Delete: free the rationals
685
 */
686
static void delete_interval(interval_t *s) {
888✔
687
  xq_clear(&s->lb);
888✔
688
  xq_clear(&s->ub);
888✔
689
  q_clear(&s->period);
888✔
690
}
888✔
691

692

693
/*
694
 * Update the lower bound to max(s->lb, a)
695
 */
696
static void interval_update_lb(interval_t *s, xrational_t *a) {
17,763✔
697
  if (!s->has_lb || xq_gt(a, &s->lb)) {
17,763✔
698
    s->has_lb = true;
6,456✔
699
    xq_set(&s->lb, a);
6,456✔
700
  }
701
}
17,763✔
702

703

704
/*
705
 * Update the upper bound to min(s->lb, a)
706
 */
707
static void interval_update_ub(interval_t *s, xrational_t *a) {
45,667✔
708
  if (!s->has_ub || xq_lt(a, &s->ub)) {
45,667✔
709
    s->has_ub = true;
9,539✔
710
    xq_set(&s->ub, a);
9,539✔
711
  }
712
}
45,667✔
713

714

715
/*
716
 * Update the period to LCM(s->period, a)
717
 * - if s->period is (b/c) and a is (d/e)
718
 *   then LCM = lcm(b, d)/gcd(c, e)
719
 * (this is a generalized LCM for rationals)
720
 */
721
static void interval_update_period(interval_t *s, rational_t *a) {
303,329✔
722
  if (q_is_zero(&s->period)) {
303,329✔
723
    q_set_abs(&s->period, a);
×
724
  } else {
725
    q_generalized_lcm(&s->period, a);
303,329✔
726
  }
727
  assert(q_is_pos(&s->period));
728
}
303,329✔
729

730

731
/*
732
 * Check whether the interval is reduced to a single point
733
 */
734
static bool singleton_interval(interval_t *s) {
35,833✔
735
  return s->has_ub && s->has_lb && xq_eq(&s->lb, &s->ub);
35,833✔
736
}
737

738

739
/*
740
 * Check whether the interval is empty
741
 */
742
static bool empty_interval(interval_t *s) {
340✔
743
  return s->has_ub && s->has_lb && xq_gt(&s->lb, &s->ub);
340✔
744
}
745

746

747
#ifndef NDEBUG
748
/*
749
 * For debugging: check whether delta is between s->lb and s->ub
750
 */
751
static bool sample_in_interval(interval_t *s, rational_t *delta) {
752
  return (!s->has_lb || xq_le_q(&s->lb, delta)) && (!s->has_ub || xq_ge_q(&s->ub, delta));
753
}
754
#endif
755

756

757
/*
758
 * Prepare the interval s for sampling:
759
 * - this sets tag, k_min, and k_max
760
 * - if the period is 0, then it's replaced by a non-zero number
761
 * - input: n = max number of samples
762
 */
763
static void interval_prepare_for_sampling(interval_t *s, uint32_t n) {
32,797✔
764
  xrational_t aux;
765
  rational_t div;
766

767
  assert(n > 0 && !singleton_interval(s));
768

769
  if (q_is_zero(&s->period)) {
32,797✔
770
    /*
771
     * Force a non-zero period: try (ub - lb)/n
772
     */
773
    if (s->has_ub && s->has_lb && q_neq(&s->lb.main, &s->ub.main)) {
1,425✔
774
      q_init(&div);
55✔
775
      q_set_int32(&div, 1, n);
55✔
776
      q_set(&s->period, &s->ub.main);
55✔
777
      q_sub(&s->period, &s->lb.main);
55✔
778
      q_mul(&s->period, &div);  // period = (ub - lb)/n
55✔
779
    } else {
780
      q_set_one(&s->period);
1,370✔
781
    }
782
  }
783

784
  assert(q_is_pos(&s->period));
785

786
  /*
787
   * Compute k_min = ceil(lb/period) and k_max = floor(up/period)
788
   */
789
  xq_init(&aux);
32,797✔
790
  s->k_min = INT32_MIN;
32,797✔
791
  if (s->has_lb) {
32,797✔
792
    xq_set(&aux, &s->lb);
2,454✔
793
    xq_div(&aux, &s->period);
2,454✔
794
    xq_ceil(&aux);
2,454✔
795
    assert(xq_sgn(&aux) <= 0 && xq_is_integer(&aux));
796
    q_normalize(&aux.main);
2,454✔
797
    if (q_is_smallint(&aux.main)) {
2,454✔
798
      s->k_min = q_get_smallint(&aux.main);
2,454✔
799
    } // else leave k_min = INT32_MIN
800
  }
801

802
  s->k_max = INT32_MAX;
32,797✔
803
  if (s->has_ub) {
32,797✔
804
    xq_set(&aux, &s->ub);
5,548✔
805
    xq_div(&aux, &s->period);
5,548✔
806
    xq_floor(&aux);
5,548✔
807
    assert(xq_sgn(&aux) >= 0 && xq_is_integer(&aux));
808
    q_normalize(&aux.main);
5,548✔
809
    if (q_is_smallint(&aux.main)) {
5,548✔
810
      s->k_max = q_get_smallint(&aux.main);
5,548✔
811
    } // else leave k_max = INT32_MAX
812
  }
813

814
  xq_clear(&aux);
32,797✔
815
  assert(s->k_min <= 0 && 0 <= s->k_max);
816
}
32,797✔
817

818

819

820
/*********************************
821
 *  ASSERT BOUNDS ON A VARIABLE  *
822
 ********************************/
823

824
/*
825
 * All push operation add a new constraint to the queue
826
 * - they update the upper/lower index in vartable
827
 * - they add a tag and an explanation
828
 */
829

830
// axiom x <= b
831
static void push_ub_axiom(simplex_solver_t *solver, thvar_t x, xrational_t *b) {
9,104✔
832
  arith_bstack_t *stack;
833
  int32_t k;
834

835
  stack = &solver->bstack;
9,104✔
836
  k = arith_bstack_new_constraint(stack);
9,104✔
837

838
  xq_set(stack->bound + k, b);
9,104✔
839
  stack->var[k] = x;
9,104✔
840
  stack->pre[k] = arith_var_upper_index(&solver->vtbl, x);
9,104✔
841
  stack->expl[k].lit = null_literal;
9,104✔
842
  stack->tag[k] = ARITH_AXIOM_UB;
9,104✔
843
  set_arith_var_upper_index(&solver->vtbl, x, k);
9,104✔
844
}
9,104✔
845

846
// axiom x >= b
847
static void push_lb_axiom(simplex_solver_t *solver, thvar_t x, xrational_t *b) {
9,767✔
848
  arith_bstack_t *stack;
849
  int32_t k;
850

851
  stack = &solver->bstack;
9,767✔
852
  k = arith_bstack_new_constraint(stack);
9,767✔
853

854
  xq_set(stack->bound + k, b);
9,767✔
855
  stack->var[k] = x;
9,767✔
856
  stack->pre[k] = arith_var_lower_index(&solver->vtbl, x);
9,767✔
857
  stack->expl[k].lit = null_literal;
9,767✔
858
  stack->tag[k] = ARITH_AXIOM_LB;
9,767✔
859
  set_arith_var_lower_index(&solver->vtbl, x, k);
9,767✔
860
}
9,767✔
861

862
// assertion x <= b with literal l as explanation
863
static void push_ub_assertion(simplex_solver_t *solver, thvar_t x, xrational_t *b, literal_t l) {
684,129✔
864
  arith_bstack_t *stack;
865
  int32_t k;
866

867
  stack = &solver->bstack;
684,129✔
868
  k = arith_bstack_new_constraint(stack);
684,129✔
869

870
  xq_set(stack->bound + k, b);
684,129✔
871
  stack->var[k] = x;
684,129✔
872
  stack->pre[k] = arith_var_upper_index(&solver->vtbl, x);
684,129✔
873
  stack->expl[k].lit = l;
684,129✔
874
  stack->tag[k] = ARITH_ASSERTED_UB;
684,129✔
875
  set_arith_var_upper_index(&solver->vtbl, x, k);
684,129✔
876
}
684,129✔
877

878
// assertion x >= b with literal l as explanation
879
static void push_lb_assertion(simplex_solver_t *solver, thvar_t x, xrational_t *b, literal_t l) {
670,630✔
880
  arith_bstack_t *stack;
881
  int32_t k;
882

883
  stack = &solver->bstack;
670,630✔
884
  k = arith_bstack_new_constraint(stack);
670,630✔
885

886
  xq_set(stack->bound + k, b);
670,630✔
887
  stack->var[k] = x;
670,630✔
888
  stack->pre[k] = arith_var_lower_index(&solver->vtbl, x);
670,630✔
889
  stack->expl[k].lit = l;
670,630✔
890
  stack->tag[k] = ARITH_ASSERTED_LB;
670,630✔
891
  set_arith_var_lower_index(&solver->vtbl, x, k);
670,630✔
892
}
670,630✔
893

894

895
// assertion x <= b with e as explanation: e is an array of bound indices, terminated by -1
896
static void push_ub_derived(simplex_solver_t *solver, thvar_t x, xrational_t *b, int32_t *e) {
127,293✔
897
  arith_bstack_t *stack;
898
  int32_t k;
899

900
  stack = &solver->bstack;
127,293✔
901
  k = arith_bstack_new_constraint(stack);
127,293✔
902

903
  xq_set(stack->bound + k, b);
127,293✔
904
  stack->var[k] = x;
127,293✔
905
  stack->pre[k] = arith_var_upper_index(&solver->vtbl, x);
127,293✔
906
  stack->expl[k].ptr = e;
127,293✔
907
  stack->tag[k] = ARITH_DERIVED_UB;
127,293✔
908
  set_arith_var_upper_index(&solver->vtbl, x, k);
127,293✔
909
}
127,293✔
910

911
// assertion x >= b with e as explanation: e is an array of bound indices, terminated by -1
912
static void push_lb_derived(simplex_solver_t *solver, thvar_t x, xrational_t *b, int32_t *e) {
111,856✔
913
  arith_bstack_t *stack;
914
  int32_t k;
915

916
  stack = &solver->bstack;
111,856✔
917
  k = arith_bstack_new_constraint(stack);
111,856✔
918

919
  xq_set(stack->bound + k, b);
111,856✔
920
  stack->var[k] = x;
111,856✔
921
  stack->pre[k] = arith_var_lower_index(&solver->vtbl, x);
111,856✔
922
  stack->expl[k].ptr = e;
111,856✔
923
  stack->tag[k] = ARITH_DERIVED_LB;
111,856✔
924
  set_arith_var_lower_index(&solver->vtbl, x, k);
111,856✔
925
}
111,856✔
926

927

928

929
// assertion x <= c with triple as an explanation:
930
static void push_ub_egraph(simplex_solver_t *solver, thvar_t x, rational_t *c, egraph_expl_triple_t *triple) {
136,164✔
931
  arith_bstack_t *stack;
932
  int32_t k;
933

934
  stack = &solver->bstack;
136,164✔
935
  k = arith_bstack_new_constraint(stack);
136,164✔
936

937
  xq_set_q(stack->bound + k, c);
136,164✔
938
  stack->var[k] = x;
136,164✔
939
  stack->pre[k] = arith_var_upper_index(&solver->vtbl, x);
136,164✔
940
  stack->expl[k].ptr = triple;
136,164✔
941
  stack->tag[k] = ARITH_EGRAPHEQ_UB;
136,164✔
942
  set_arith_var_upper_index(&solver->vtbl, x, k);
136,164✔
943
}
136,164✔
944

945

946
// assertion x >= c with triple as explanation
947
static void push_lb_egraph(simplex_solver_t *solver, thvar_t x, rational_t *c, egraph_expl_triple_t *triple) {
132,628✔
948
  arith_bstack_t *stack;
949
  int32_t k;
950

951
  stack = &solver->bstack;
132,628✔
952
  k = arith_bstack_new_constraint(stack);
132,628✔
953

954
  xq_set_q(stack->bound + k, c);
132,628✔
955
  stack->var[k] = x;
132,628✔
956
  stack->pre[k] = arith_var_lower_index(&solver->vtbl, x);
132,628✔
957
  stack->expl[k].ptr = triple;
132,628✔
958
  stack->tag[k] = ARITH_EGRAPHEQ_LB;
132,628✔
959
  set_arith_var_lower_index(&solver->vtbl, x, k);
132,628✔
960
}
132,628✔
961

962

963

964

965

966
/********************************
967
 *  CHECK BOUNDS ON A VARIABLE  *
968
 *******************************/
969

970
/*
971
 * Check whether v is a fixed variable
972
 */
973
static bool simplex_fixed_variable(simplex_solver_t *solver, thvar_t x) {
258,650✔
974
  int32_t l, u;
975

976
  l = arith_var_lower_index(&solver->vtbl, x);
258,650✔
977
  u = arith_var_upper_index(&solver->vtbl, x);
258,650✔
978
  return (l >= 0) && (u >= 0) && xq_eq(&solver->bstack.bound[l], &solver->bstack.bound[u]);
258,650✔
979
}
980

981
/*
982
 * Return the bound on v if v is a fixed variable
983
 */
984
static rational_t *fixed_variable_value(simplex_solver_t *solver, thvar_t x) {
245,603✔
985
  int32_t l;
986

987
  l = arith_var_lower_index(&solver->vtbl, x);
245,603✔
988
  assert(l >= 0);
989
  return &solver->bstack.bound[l].main;
245,603✔
990
}
991

992

993
/*
994
 * Check whether x is a free variable
995
 * - i.e., there's no lower or upper bound asserted on x
996
 */
997
static inline bool simplex_free_variable(simplex_solver_t *solver, thvar_t x) {
36,242,888✔
998
  return arith_var_lower_index(&solver->vtbl, x) < 0 && arith_var_upper_index(&solver->vtbl, x) < 0;
36,242,888✔
999
}
1000

1001

1002
#ifndef NDEBUG
1003

1004
/*
1005
 * Check whether x can be eliminated
1006
 * - x must be free and it must have no atoms and no egraph term attached
1007
 * NOTE: this is a necessary but not sufficient condition.
1008
 * See simplex_simplify_matrix.
1009
 */
1010
static bool simplex_eliminable_variable(simplex_solver_t *solver, thvar_t x) {
1011
  return simplex_free_variable(solver, x) && arith_var_num_atoms(&solver->vtbl, x) == 0
1012
    && ! arith_var_has_eterm(&solver->vtbl, x);
1013
}
1014
#endif
1015

1016

1017

1018
/*
1019
 * Check whether value v is between the bounds on x
1020
 */
1021
static bool value_ge_lower_bound(simplex_solver_t *solver, thvar_t x, xrational_t *v) {
10,660,920✔
1022
  int32_t k;
1023

1024
  k = arith_var_lower_index(&solver->vtbl, x);
10,660,920✔
1025
  return k < 0 || xq_ge(v, solver->bstack.bound + k);
10,660,920✔
1026
}
1027

1028
static bool value_le_upper_bound(simplex_solver_t *solver, thvar_t x, xrational_t *v) {
10,334,102✔
1029
  int32_t k;
1030

1031
  k = arith_var_upper_index(&solver->vtbl, x);
10,334,102✔
1032
  return k < 0 || xq_le(v, solver->bstack.bound + k);
10,334,102✔
1033
}
1034

1035
static bool value_within_bounds(simplex_solver_t *solver, thvar_t x, xrational_t *v) {
10,660,920✔
1036
  return value_ge_lower_bound(solver, x, v) && value_le_upper_bound(solver, x, v);
10,660,920✔
1037
}
1038

1039

1040

1041
/*
1042
 * Check whether the value of x is between its bound
1043
 */
1044
static bool value_satisfies_lower_bound(simplex_solver_t *solver, thvar_t x) {
25,559✔
1045
  int32_t k;
1046

1047
  k = arith_var_lower_index(&solver->vtbl, x);
25,559✔
1048
  return k < 0 || xq_le(solver->bstack.bound + k, arith_var_value(&solver->vtbl, x));
25,559✔
1049
}
1050

1051
static bool value_satisfies_upper_bound(simplex_solver_t *solver, thvar_t x) {
25,314✔
1052
  int32_t k;
1053

1054
  k = arith_var_upper_index(&solver->vtbl, x);
25,314✔
1055
  return k < 0 || xq_ge(solver->bstack.bound + k, arith_var_value(&solver->vtbl, x));
25,314✔
1056
}
1057

1058
static bool value_satisfies_bounds(simplex_solver_t *solver, thvar_t x) {
25,559✔
1059
  return value_satisfies_lower_bound(solver, x) && value_satisfies_upper_bound(solver, x);
25,559✔
1060
}
1061

1062

1063

1064
/*
1065
 * Check whether x is at its lower or upper bound
1066
 */
1067
static bool variable_at_lower_bound(simplex_solver_t *solver, thvar_t x) {
102,317✔
1068
  int32_t k;
1069

1070
  k = arith_var_lower_index(&solver->vtbl, x);
102,317✔
1071
  return k >= 0 && xq_eq(solver->bstack.bound + k, arith_var_value(&solver->vtbl, x));
102,317✔
1072
}
1073

1074
static bool variable_at_upper_bound(simplex_solver_t *solver, thvar_t x) {
257,678✔
1075
  int32_t k;
1076

1077
  k = arith_var_upper_index(&solver->vtbl, x);
257,678✔
1078
  return k >= 0 && xq_eq(solver->bstack.bound + k, arith_var_value(&solver->vtbl, x));
257,678✔
1079
}
1080

1081

1082
/*
1083
 * Check whether x < its lower bound or x > its upper bound
1084
 */
1085
static bool variable_below_lower_bound(simplex_solver_t *solver, thvar_t x) {
475,898✔
1086
  int32_t k;
1087

1088
  k = arith_var_lower_index(&solver->vtbl, x);
475,898✔
1089
  return k >= 0 && xq_gt(solver->bstack.bound + k, arith_var_value(&solver->vtbl, x));
475,898✔
1090
}
1091

1092
static bool variable_above_upper_bound(simplex_solver_t *solver, thvar_t x) {
243,572✔
1093
  int32_t k;
1094

1095
  k = arith_var_upper_index(&solver->vtbl, x);
243,572✔
1096
  return k >= 0 && xq_lt(solver->bstack.bound + k, arith_var_value(&solver->vtbl, x));
243,572✔
1097
}
1098

1099

1100

1101

1102

1103

1104

1105
/*********************************
1106
 *  THEORY PROPAGATION OBJECTS   *
1107
 ********************************/
1108

1109
/*
1110
 * Allocate a simple propagation object for bound index k
1111
 * - the object is allocated in the arena
1112
 */
1113
static aprop_t *make_simplex_prop_object(simplex_solver_t *solver, int32_t k) {
451,120✔
1114
  aprop_t *tmp;
1115

1116
  tmp = (aprop_t *) arena_alloc(&solver->arena, sizeof(aprop_t));
451,120✔
1117
  tmp->tag = APROP_BOUND;
451,120✔
1118
  tmp->bound = k;
451,120✔
1119

1120
  return tmp;
451,120✔
1121
}
1122

1123

1124

1125
/*******************************
1126
 *  PROPAGATION TO THE EGRAPH  *
1127
 ******************************/
1128

1129
/*
1130
 * Callback: called when equality between two egraph term is detected
1131
 */
1132
static void prop_eq_to_egraph(void *s, eterm_t t1, eterm_t t2) {
124,437✔
1133
  simplex_solver_t *solver;
1134
  egraph_t *egraph;
1135

1136
  solver = s;
124,437✔
1137
  egraph = solver->egraph;
124,437✔
1138
  assert(egraph != NULL);
1139

1140
#if 0
1141
  printf("---> eq prop: g!%"PRId32" == g!%"PRId32"\n", t1, t2);
1142
#endif
1143
  egraph_propagate_equality(egraph, t1, t2, EXPL_ARITH_PROPAGATION, NULL);
124,437✔
1144
}
124,437✔
1145

1146

1147
/*
1148
 * Check whether p is of the form c + y - z or y - z
1149
 * where c is a constant and y and z are variables.
1150
 */
1151
static bool offset_poly(polynomial_t *p) {
126,594✔
1152
  monomial_t *mono;
1153
  uint32_t n;
1154

1155
  n = p->nterms;
126,594✔
1156
  mono = p->mono;
126,594✔
1157
  if (n > 0 && mono[0].var == const_idx) {
126,594✔
1158
    // skip the constant
1159
    mono ++;
529✔
1160
    n --;
529✔
1161
  }
1162

1163
  if (n == 2) {
126,594✔
1164
    assert(mono[0].var != const_idx && mono[1].var != const_idx);
1165
    return (q_is_one(&mono[0].coeff) && q_is_minus_one(&mono[1].coeff))
124,083✔
1166
      || (q_is_minus_one(&mono[0].coeff) && q_is_one(&mono[1].coeff));
124,083✔
1167
  }
1168

1169
  return false;
4,533✔
1170
}
1171

1172

1173
/*
1174
 * Check whether variable x is relevant for offset equality propagation
1175
 */
1176
static bool eqprop_relevant_var(simplex_solver_t *solver, thvar_t x) {
171,774✔
1177
  arith_vartable_t *vtbl;
1178
  polynomial_t *p;
1179

1180
  vtbl = &solver->vtbl;
171,774✔
1181

1182
  assert(arith_var_kind(vtbl, x) == AVAR_FREE || arith_var_kind(vtbl, x) == AVAR_POLY);
1183

1184
  p = arith_var_def(vtbl, x);
171,774✔
1185

1186
  /*
1187
   * If p is NULL, then x is a variable => relevant?
1188
   * Otherwise, p is a polynomial. x is relevant if p is of the
1189
   * form (c + z - y) where c is a constant (possibly 0).
1190
   *
1191
   * Note: if p is of the form (c + z) or (c - y), then x is
1192
   * a trivial_variable so it's eliminated from all definitions.
1193
   * This means that x is not relevant here.
1194
   */
1195
  return (p == NULL) || offset_poly(p);
171,774✔
1196
}
1197

1198

1199
/*
1200
 * Increase the size of bitarray eqprop->relevant to store relevance bit for variable i
1201
 */
1202
static void resize_eqprop(eq_propagator_t *eqprop, uint32_t i) {
14,658✔
1203
  uint32_t n;
1204

1205
  n = eqprop->size;
14,658✔
1206
  if (n <= i) {
14,658✔
1207
    n += n;
48✔
1208
    if (n <= i) {
48✔
1209
      n = i+1;
×
1210
    }
1211
    eqprop->relevant = extend_bitvector0(eqprop->relevant, n, eqprop->size);
48✔
1212
    eqprop->size = n;
48✔
1213
  }
1214
}
14,658✔
1215

1216

1217
/*
1218
 * Set the relevance bit for variable x
1219
 * - x must be in the vartable and different from const_idx
1220
 * - solver->eqprop must be initialized
1221
 */
1222
static void eqprop_set_relevance(simplex_solver_t *solver, thvar_t x) {
14,658✔
1223
  eq_propagator_t *eqprop;
1224

1225
  assert(0 < x && x < solver->vtbl.nvars && solver->eqprop != NULL);
1226

1227
  eqprop = solver->eqprop;
14,658✔
1228
  resize_eqprop(eqprop, x);
14,658✔
1229
  assert(x < eqprop->size);
1230

1231
  if (eqprop_relevant_var(solver, x)) {
14,658✔
1232
    set_bit(eqprop->relevant, x);
12,620✔
1233
  }
1234
}
14,658✔
1235

1236

1237
/*
1238
 * Allocate and initialize the propagator object
1239
 */
1240
static void simplex_alloc_eqprop(simplex_solver_t *solver) {
71✔
1241
  eq_propagator_t *tmp;
1242
  uint32_t i, n;
1243

1244
  assert(solver->eqprop == NULL);
1245

1246
  tmp = (eq_propagator_t *) safe_malloc(sizeof(eq_propagator_t));
71✔
1247
  init_offset_manager(&tmp->mngr, solver, prop_eq_to_egraph);
71✔
1248

1249
  n = DEF_EQPROP_SIZE;
71✔
1250
  assert(n > 0);
1251

1252
  tmp->relevant = allocate_bitvector0(n);
71✔
1253
  tmp->nvars = 1;
71✔
1254
  tmp->size = n;
71✔
1255
  tmp->prop_ptr = 2; // skip bounds on const_idx (cf. create_constant)
71✔
1256
  init_ivector(&tmp->aux, 20);
71✔
1257
  init_ivector(&tmp->expl_queue, 20);
71✔
1258
  q_init(&tmp->q_aux);
71✔
1259

1260
  solver->eqprop = tmp;
71✔
1261

1262
  // initialize the relevance bits of all other variables if any
1263
  // for variable 0 = const_idx, relevant[0] stays 0
1264
  n = solver->vtbl.nvars;
71✔
1265
  for (i=1; i<n; i++) {
71✔
1266
    eqprop_set_relevance(solver, i);
×
1267
  }
1268
}
71✔
1269

1270

1271
/*
1272
 * Delete the propagator
1273
 */
1274
static void simplex_delete_eqprop(simplex_solver_t *solver) {
71✔
1275
  eq_propagator_t *eqprop;
1276

1277
  eqprop = solver->eqprop;
71✔
1278
  assert(eqprop != NULL);
1279
  delete_offset_manager(&eqprop->mngr);
71✔
1280
  delete_bitvector(eqprop->relevant);
71✔
1281
  delete_ivector(&eqprop->aux);
71✔
1282
  delete_ivector(&eqprop->expl_queue);
71✔
1283
  q_clear(&eqprop->q_aux);
71✔
1284

1285
  safe_free(eqprop);
71✔
1286
  solver->eqprop = NULL;
71✔
1287
}
71✔
1288

1289

1290
/*
1291
 * Reset
1292
 */
1293
static void simplex_reset_eqprop(simplex_solver_t *solver) {
×
1294
  eq_propagator_t *eqprop;
1295

1296
  eqprop = solver->eqprop;
×
1297
  assert(eqprop != NULL);
1298
  reset_offset_manager(&eqprop->mngr);
×
1299
  clear_bitvector(eqprop->relevant, eqprop->size);
×
1300
  ivector_reset(&eqprop->aux);
×
1301
  ivector_reset(&eqprop->expl_queue);
×
1302
  q_clear(&eqprop->q_aux);
×
1303
}
×
1304

1305

1306

1307
/*
1308
 * Push
1309
 */
1310
static void simplex_push_eqprop(simplex_solver_t *solver) {
153✔
1311
  eq_propagator_t *eqprop;
1312

1313
  eqprop = solver->eqprop;
153✔
1314
  assert(eqprop != NULL);
1315
  offset_manager_push(&eqprop->mngr);
153✔
1316
}
153✔
1317

1318

1319
/*
1320
 * Pop is divided in two steps
1321
 * - before we remove variables from solver->vtbl, we must
1322
 *   call pop on solver->eqprop.mngr to remove offset variables
1323
 *   and their definitions. This must be done first because
1324
 *   polynomials may be shared between solver->vtbl and
1325
 *   solver->eqprop.mngr.
1326
 * - after we remove variables from solver->vtbl, we must
1327
 *   mark all deleted variables as irrelevant in solver->eqprop.
1328
 */
1329
static void simplex_pop_eqprop(simplex_solver_t *solver) {
141✔
1330
  eq_propagator_t *eqprop;
1331

1332
  eqprop = solver->eqprop;
141✔
1333
  assert(eqprop != NULL);
1334
  offset_manager_pop(&eqprop->mngr);
141✔
1335
}
141✔
1336

1337
static void simplex_eqprop_cleanup(simplex_solver_t *solver) {
141✔
1338
  eq_propagator_t *eqprop;
1339
  uint32_t i, n;
1340

1341
  eqprop = solver->eqprop;
141✔
1342
  assert(eqprop != NULL);
1343

1344
  // clear bits (of deleted variables)
1345
  n = eqprop->size;
141✔
1346
  for (i = solver->vtbl.nvars; i<n; i++) {
15,544✔
1347
    clr_bit(eqprop->relevant, i);
15,403✔
1348
  }
1349

1350
  // reset the propagation pointer (same as in solver)
1351
  assert(solver->bstack.prop_ptr == solver->bstack.fix_ptr);
1352
  eqprop->prop_ptr = solver->bstack.prop_ptr;
141✔
1353
}
141✔
1354

1355

1356

1357
/*
1358
 * Enable eqprop option: the option is ignored if solver->egraph is NULL
1359
 */
1360
void simplex_enable_eqprop(simplex_solver_t *solver) {
71✔
1361
  if (solver->egraph != NULL) {
71✔
1362
    simplex_enable_options(solver, SIMPLEX_EQPROP);
71✔
1363
    if (solver->eqprop == NULL) {
71✔
1364
      simplex_alloc_eqprop(solver);
71✔
1365
    }
1366
  }
1367
}
71✔
1368

1369
void simplex_disable_eqprop(simplex_solver_t *solver) {
×
1370
  if (solver->egraph != NULL) {
×
1371
    simplex_disable_options(solver, SIMPLEX_EQPROP);
×
1372
    if (solver->eqprop != NULL) {
×
1373
      simplex_delete_eqprop(solver);
×
1374
    }
1375
  }
1376
}
×
1377

1378

1379
/*
1380
 * Record that x is attached to eterm t
1381
 */
1382
static void eqprop_record_eterm(simplex_solver_t *solver, thvar_t x, eterm_t t) {
5,427✔
1383
  eq_propagator_t *eqprop;
1384
  arith_vartable_t *vtbl;
1385
  polynomial_t *p;
1386

1387
  vtbl = &solver->vtbl;
5,427✔
1388
  eqprop = solver->eqprop;
5,427✔
1389

1390
  assert(eqprop != NULL && (arith_var_kind(vtbl, x) == AVAR_FREE || arith_var_kind(vtbl, x) == AVAR_POLY));
1391
  p = arith_var_def(vtbl, x);
5,427✔
1392

1393
  record_offset_poly(&eqprop->mngr, t, x, p);
5,427✔
1394
}
5,427✔
1395

1396

1397
/*
1398
 * Check whether bound i freezes the value of variable x
1399
 * - this returns true if x's lower and upper bound are equal and if i is the last bound
1400
 *   asserted
1401
 */
1402
static bool bound_freezes_var(simplex_solver_t *solver, thvar_t x, int32_t i) {
393,884✔
1403
  int32_t l, u;
1404

1405
  assert(i >= 0);
1406

1407
  l = arith_var_lower_index(&solver->vtbl, x); // lower bound on x
393,884✔
1408
  u = arith_var_upper_index(&solver->vtbl, x); // upper bound on x
393,884✔
1409

1410
  if (u < l) {
393,884✔
1411
    // l = last bound on x
1412
    return (l == i) && (u >= 0) && xq_eq(&solver->bstack.bound[l], &solver->bstack.bound[u]);
68,200✔
1413
  } else {
1414
    // u = last bound on x
1415
    return (u == i) && (l >= 0) && xq_eq(&solver->bstack.bound[l], &solver->bstack.bound[u]);
325,684✔
1416
  }
1417
}
1418

1419

1420
/*
1421
 * Process frozen variable x
1422
 * - x is relevant to eqprop
1423
 */
1424
static void eqprop_process_frozen_var(simplex_solver_t *solver, thvar_t x) {
151,933✔
1425
  eq_propagator_t *eqprop;
1426
  polynomial_t *p;
1427
  monomial_t *mono;
1428
  rational_t *a;
1429
  thvar_t y, z;
1430

1431
  assert(eqprop_relevant_var(solver, x) && simplex_fixed_variable(solver, x));
1432

1433
  eqprop = solver->eqprop;
151,933✔
1434
  assert(eqprop != NULL);
1435

1436
  /*
1437
   * We have (a == x) and (x == c + y - z):
1438
   * - we propagate x == a and y == z + (a - c)
1439
   */
1440
  a = fixed_variable_value(solver, x);
151,933✔
1441
  p = arith_var_def(&solver->vtbl, x);
151,933✔
1442

1443
  assert_offset_equality(&eqprop->mngr, x, -1, a, x); // x == a with id = x
151,933✔
1444

1445
  if (p != NULL) {
151,933✔
1446
    mono = p->mono;
111,876✔
1447
    assert((p->nterms == 3 && mono[0].var == const_idx) ||
1448
           (p->nterms == 2 && mono[0].var > const_idx));
1449

1450
    // store a - c in q_aux
1451
    q_set(&eqprop->q_aux, a);
111,876✔
1452
    if (mono[0].var == const_idx) {
111,876✔
1453
      q_sub(&eqprop->q_aux, &mono[0].coeff);
11✔
1454
      mono ++;
11✔
1455
    }
1456

1457
    if (q_is_one(&mono[0].coeff)) {
111,876✔
1458
      assert(q_is_minus_one(&mono[1].coeff));
1459
      y = mono[0].var;
7✔
1460
      z = mono[1].var;
7✔
1461
    } else {
1462
      assert(q_is_minus_one(&mono[0].coeff) && q_is_one(&mono[1].coeff));
1463
      y = mono[1].var;
111,869✔
1464
      z = mono[0].var;
111,869✔
1465
    }
1466

1467
    // propagate (y == z + q_aux) to manager; use x as id
1468
    assert_offset_equality(&eqprop->mngr, y, z, &eqprop->q_aux, x);
111,876✔
1469
  }
1470
}
151,933✔
1471

1472

1473
/*
1474
 * Scan all new bounds in solver->bstack
1475
 * - for each frozen variable, add an offset equality to the offset manager
1476
 */
1477
static void simplex_propagate_equalities(simplex_solver_t *solver) {
161,266✔
1478
  eq_propagator_t *eqprop;
1479
  arith_bstack_t *bstack;
1480
  uint32_t i, n, eqs;
1481
  thvar_t x;
1482

1483
  bstack = &solver->bstack;
161,266✔
1484
  eqprop = solver->eqprop;
161,266✔
1485
  assert(eqprop != NULL);
1486

1487
  n = bstack->top;
161,266✔
1488
  eqs = 0;
161,266✔
1489
  for (i=eqprop->prop_ptr; i<n; i++) {
555,150✔
1490
    x = bstack->var[i];
393,884✔
1491
    if (bound_freezes_var(solver, x, i) && eqprop_relevant_var(solver, x)) {
393,884✔
1492
      /*
1493
       * x is frozen and relevant: propagate the constraint x == value
1494
       * to the offset manager.
1495
       */
1496
      assert(tst_bit(eqprop->relevant, x));
1497
      assert(simplex_fixed_variable(solver, x));
1498
#if 0
1499
      printf("---> fixed var: ");
1500
      print_simplex_var(stdout, solver, x);
1501
      printf(" == ");
1502
      print_simplex_var_value(stdout, solver, x);
1503
      printf(" (bound = %"PRIu32")\n", i);
1504
      if (!arith_var_is_free(&solver->vtbl, x)) {
1505
        printf("     ");
1506
        print_simplex_vardef(stdout, solver, x);
1507
      }
1508
#endif
1509

1510
      eqprop_process_frozen_var(solver, x);
151,933✔
1511
      eqs ++;
151,933✔
1512
    }
1513
  }
1514

1515
  if (eqs > 0) {
161,266✔
1516
    assert_true(offset_manager_propagate(&eqprop->mngr));
41,195✔
1517
  }
1518

1519
  eqprop->prop_ptr = n;
161,266✔
1520
}
161,266✔
1521

1522

1523

1524
/****************************
1525
 *  SOLVER INITIALIZATION   *
1526
 ***************************/
1527

1528
/*
1529
 * Create the constant:
1530
 * - variable of index 0 in vartable, with definition = 1
1531
 *   (as a rational constant)
1532
 * - set its value to 1
1533
 * - assert that its lower and upper bound are 1
1534
 * This must be done before any other variable is created,
1535
 * but after the poly_buffer and vartable are initialized
1536
 */
1537
static void simplex_create_constant(simplex_solver_t *solver) {
4,881✔
1538
  xrational_t *v;
1539
  bool new_var;
1540
  thvar_t x;
1541

1542
  assert(solver->vtbl.nvars == 0 && solver->matrix.ncolumns == 0);
1543

1544
  // create the variable in vtbl
1545
  q_set_one(&solver->constant);
4,881✔
1546
  x = get_var_for_constant(&solver->vtbl, &solver->constant, &new_var);
4,881✔
1547
  assert(new_var && x == const_idx);
1548

1549
  // create column 0 for const_idx
1550
  matrix_add_column(&solver->matrix);
4,881✔
1551

1552
  // assignment and tags: lower-bound = upper-bound = 1
1553
  v = arith_var_value(&solver->vtbl, x);
4,881✔
1554
  xq_set_one(v);
4,881✔
1555
  set_arith_var_lb(&solver->vtbl, x);
4,881✔
1556
  set_arith_var_ub(&solver->vtbl, x);
4,881✔
1557

1558
  // lower and upper bounds
1559
  xq_set_one(&solver->bound);
4,881✔
1560
  push_lb_axiom(solver, x, &solver->bound);
4,881✔
1561
  push_ub_axiom(solver, x, &solver->bound);
4,881✔
1562

1563
  // skip these two bounds
1564
  assert(solver->bstack.top == 2);
1565
  solver->bstack.prop_ptr = 2;
4,881✔
1566
  solver->bstack.fix_ptr = 2;
4,881✔
1567
}
4,881✔
1568

1569

1570
/*
1571
 * Initialize a simplex solver
1572
 * - core = attached smt_core
1573
 * - gates = attached gate manager
1574
 * - egraph = attached egraph (or NULL)
1575
 */
1576
void init_simplex_solver(simplex_solver_t *solver, smt_core_t *core, gate_manager_t *gates, egraph_t *egraph) {
4,880✔
1577
  solver->core = core;
4,880✔
1578
  solver->gate_manager = gates;
4,880✔
1579
  solver->egraph = egraph;
4,880✔
1580
  solver->base_level = 0;
4,880✔
1581
  solver->decision_level = 0;
4,880✔
1582
  solver->unsat_before_search = false;
4,880✔
1583

1584
  solver->options = SIMPLEX_DEFAULT_OPTIONS;
4,880✔
1585
  solver->interrupted = false;
4,880✔
1586
  solver->use_blands_rule = false;
4,880✔
1587
  solver->bland_threshold = SIMPLEX_DEFAULT_BLAND_THRESHOLD;
4,880✔
1588
  solver->prop_row_size = SIMPLEX_DEFAULT_PROP_ROW_SIZE;
4,880✔
1589
  solver->last_conflict_row = -1;
4,880✔
1590
  solver->recheck = false;
4,880✔
1591

1592
  solver->prng = SPLX_PRNG_SEED;
4,880✔
1593

1594
  solver->integer_solving = false;
4,880✔
1595
  solver->enable_dfeas = false;
4,880✔
1596
  solver->check_counter = 0;
4,880✔
1597
  solver->check_period = SIMPLEX_DEFAULT_CHECK_PERIOD;
4,880✔
1598
  solver->last_branch_atom = null_bvar;
4,880✔
1599
  solver->dsolver = NULL;     // allocated later if needed
4,880✔
1600

1601
  solver->cache = NULL;       // allocated later if needed
4,880✔
1602

1603
  init_simplex_statistics(&solver->stats);
4,880✔
1604

1605
  init_arith_atomtable(&solver->atbl, core);
4,880✔
1606
  init_arith_vartable(&solver->vtbl);
4,880✔
1607

1608
  solver->propagator = NULL; // allocated if needed in start search
4,880✔
1609

1610
  solver->eqprop = NULL; // allocated by simplex_enable_eqprop
4,880✔
1611

1612
  init_matrix(&solver->matrix, 0, 0);
4,880✔
1613
  solver->tableau_ready = false;
4,880✔
1614
  solver->matrix_ready = true;
4,880✔
1615
  solver->save_rows = false;
4,880✔
1616

1617
  init_int_heap(&solver->infeasible_vars, 0, 0);
4,880✔
1618
  init_arith_bstack(&solver->bstack, DEF_ARITH_BSTACK_SIZE);
4,880✔
1619
  init_arith_astack(&solver->assertion_queue, DEF_ARITH_ASTACK_SIZE);
4,880✔
1620
  init_eassertion_queue(&solver->egraph_queue);
4,880✔
1621
  init_arith_undo_stack(&solver->stack, DEF_ARITH_UNDO_STACK_SIZE);
4,880✔
1622

1623
  init_arith_trail(&solver->trail_stack);
4,880✔
1624
  init_pvector(&solver->saved_rows, 0);
4,880✔
1625

1626
  init_elim_matrix(&solver->elim);
4,880✔
1627
  init_fvar_vector(&solver->fvars);
4,880✔
1628

1629
  init_poly_buffer(&solver->buffer);
4,880✔
1630
  q_init(&solver->constant);
4,880✔
1631
  q_init(&solver->aux);
4,880✔
1632
  q_init(&solver->gcd);
4,880✔
1633
  xq_init(&solver->bound);
4,880✔
1634
  xq_init(&solver->delta);
4,880✔
1635
  xq_init(&solver->xq0);
4,880✔
1636

1637
  init_ivector(&solver->expl_vector, DEF_ARITH_EXPL_VECTOR_SIZE);
4,880✔
1638
  init_ivector(&solver->expl_queue, DEF_ARITH_EXPL_VECTOR_SIZE);
4,880✔
1639
  init_ivector(&solver->expl_aux, DEF_ARITH_EXPL_VECTOR_SIZE);
4,880✔
1640
  init_ivector(&solver->aux_vector, 10);
4,880✔
1641
  init_ivector(&solver->aux_vector2, 10);
4,880✔
1642
  init_ivector(&solver->rows_to_process, DEF_PROCESS_ROW_VECTOR_SIZE);
4,880✔
1643

1644
  init_arena(&solver->arena);
4,880✔
1645

1646
  // Model
1647
  solver->value = NULL;     // allocated when needed
4,880✔
1648
  q_init(&solver->epsilon);
4,880✔
1649
  q_init(&solver->factor);
4,880✔
1650
  solver->dprng = DPRNG_DEFAULT_SEED;
4,880✔
1651

1652
  solver->env = NULL;
4,880✔
1653

1654
  // add the constant
1655
  simplex_create_constant(solver);
4,880✔
1656

1657
  // push undo record for level 0
1658
  arith_push_undo_record(&solver->stack, 0, 0);
4,880✔
1659
}
4,880✔
1660

1661

1662
/*
1663
 * Set buffer as jump buffer for exceptions during internalization
1664
 */
1665
void simplex_solver_init_jmpbuf(simplex_solver_t *solver, jmp_buf *buffer) {
4,880✔
1666
  solver->env = buffer;
4,880✔
1667
}
4,880✔
1668

1669

1670

1671
/*
1672
 * Return the diophantine system subsolver
1673
 * - allocate and initialize it if needed
1674
 */
1675
static dsolver_t *simplex_get_dsolver(simplex_solver_t *solver) {
×
1676
  dsolver_t *s;
1677

1678
  s = solver->dsolver;
×
1679
  if (s == NULL) {
×
1680
    s = (dsolver_t *) safe_malloc(sizeof(dsolver_t));
×
1681
    init_dsolver(s, 0, 0, 0);
×
1682
    solver->dsolver = s;
×
1683
  }
1684
  return s;
×
1685
}
1686

1687

1688
/*
1689
 * Return the cache
1690
 * - allocate and initialize it if needed
1691
 */
1692
static cache_t *simplex_get_cache(simplex_solver_t *solver) {
26✔
1693
  cache_t *c;
1694

1695
  c = solver->cache;
26✔
1696
  if (c == NULL) {
26✔
1697
    c = (cache_t *) safe_malloc(sizeof(cache_t));
2✔
1698
    // initialize then synchronize the push/pop level
1699
    init_cache(c);
2✔
1700
    cache_set_level(c, solver->base_level);
2✔
1701
    solver->cache = c;
2✔
1702
  }
1703

1704
  return c;
26✔
1705
}
1706

1707

1708

1709

1710

1711

1712
/*******************
1713
 *  BINARY LEMMAS  *
1714
 ******************/
1715

1716
/*
1717
 * Add binary lemma for two atoms atom1 and atom2
1718
 * - the atoms must be on the same variable x
1719
 * - they must be distinct
1720
 */
1721
static void create_binary_lemma(simplex_solver_t *solver, arith_atom_t *atom1, arith_atom_t *atom2) {
35,512✔
1722
  arith_atom_t *aux;
1723
  rational_t *a, *b;
1724
  literal_t l1, l2;
1725

1726
  assert(var_of_atom(atom1) == var_of_atom(atom2) && atom1 != atom2);
1727
  assert(tag_of_atom(atom1) != tag_of_atom(atom2) || q_neq(bound_of_atom(atom1), bound_of_atom(atom2)));
1728

1729
#if TRACE
1730
  printf("---> create_binary_lemma:\n");
1731
  printf("     ");
1732
  print_simplex_atomdef(stdout, solver, boolvar_of_atom(atom1));
1733
  printf("     ");
1734
  print_simplex_atomdef(stdout, solver, boolvar_of_atom(atom2));
1735
#endif
1736

1737
  /*
1738
   * - make sure atom1 has a higher tag than atom2 to
1739
   *   cut the number of cases
1740
   * - after this, the possible combinations are
1741
   *     atom1      atom2
1742
   *   (x >= a)    (x >= b)
1743
   *   (x <= a)    (x >= b)
1744
   *   (x <= a)    (x <= b)
1745
   *   (x == a)    (x >= b)
1746
   *   (x == a)    (x <= b)
1747
   *   (x == a)    (x == b)
1748
   */
1749
  if (tag_of_atom(atom1) < tag_of_atom(atom2)) {
35,512✔
1750
    aux = atom1;
1,237✔
1751
    atom1 = atom2;
1,237✔
1752
    atom2 = aux;
1,237✔
1753
  }
1754

1755
  a = bound_of_atom(atom1);
35,512✔
1756
  b = bound_of_atom(atom2);
35,512✔
1757
  l1 = pos_lit(boolvar_of_atom(atom1));
35,512✔
1758
  l2 = pos_lit(boolvar_of_atom(atom2));
35,512✔
1759

1760
  switch (tag_of_atom(atom1)) {
35,512✔
1761
  case GE_ATM:
30,261✔
1762
    assert(tag_of_atom(atom2) == GE_ATM);
1763
    if (q_ge(a, b)) {
30,261✔
1764
      add_binary_clause(solver->core, not(l1), l2);  // (x >= a) ==> (x >= b)
22,019✔
1765
    } else {
1766
      add_binary_clause(solver->core, l1, not(l2));  // (x < a) ==> (x < b)
8,242✔
1767
    }
1768
    break;
30,261✔
1769

1770
  case LE_ATM:
5,251✔
1771
    if (tag_of_atom(atom2) == GE_ATM) {
5,251✔
1772
      if (q_lt(a, b)) {
4,970✔
1773
        add_binary_clause(solver->core, not(l1), not(l2));  // (x > a) or (x > b)
608✔
1774
      } else {
1775
        add_binary_clause(solver->core, l1, l2);   // (x <= a) or (x >= b)
4,362✔
1776
      }
1777
    } else {
1778
      assert(tag_of_atom(atom2) == LE_ATM);
1779
      if (q_le(a, b)) {
281✔
1780
        add_binary_clause(solver->core, not(l1), l2);  // (x <= a) ==> (x <= b)
153✔
1781
      } else {
1782
        add_binary_clause(solver->core, l1, not(l2));  // (x > a) ==> (x > b))
128✔
1783
      }
1784
    }
1785
    break;
5,251✔
1786

1787
  case EQ_ATM:
×
1788
    switch (tag_of_atom(atom2)) {
×
1789
    case GE_ATM:
×
1790
      if (q_ge(a, b)) {
×
1791
        add_binary_clause(solver->core, not(l1), l2); // (x == a) ==> (x >= b))
×
1792
      } else {
1793
        add_binary_clause(solver->core, not(l1), not(l2));  // (x == a) ==> (x < b)
×
1794
      }
1795
      break;
×
1796
    case LE_ATM:
×
1797
      if (q_le(a, b)) {
×
1798
        add_binary_clause(solver->core, not(l1), l2);   // (x == a) ==> (x <= b)
×
1799
      } else {
1800
        add_binary_clause(solver->core, not(l1), not(l2)); // (x == a) ==> (x > b);
×
1801
      }
1802
      break;
×
1803
    case EQ_ATM:
×
1804
      add_binary_clause(solver->core, not(l1), not(l2)); // (not (x == a)) or (not (x == b))
×
1805
      break;
×
1806
    }
1807
  }
1808

1809
  solver->stats.num_binary_lemmas ++;
35,512✔
1810
}
35,512✔
1811

1812

1813
/*
1814
 * Build all the binary lemmas involving atom id on variable x
1815
 * - id must not be in the atom_vector of x
1816
 *
1817
 * Let a be the bound for atom id: the atom is then either (x >= a) or (x <= a)
1818
 * - we search for two atoms atom1 and atom2 such that
1819
 *   bound_of(atom1) <= a and a <= bound_of(atom2)
1820
 *   and such that bound_of(atom1) and bound_of(atom2) are
1821
 *   as close to a as possible.
1822
 * - then we generate two lemmas
1823
 */
1824
static void build_binary_lemmas_for_atom(simplex_solver_t *solver, thvar_t x, int32_t id) {
51,540✔
1825
  arith_atomtable_t *atbl;
1826
  int32_t *atom_vector;
1827
  arith_atom_t *atom, *atom1, *atom2, *aux;
1828
  rational_t *a;
1829
  uint32_t i, n;
1830
  int32_t id2;
1831

1832
  if (simplex_option_enabled(solver, SIMPLEX_EAGER_LEMMAS)) {
51,540✔
1833
    atom_vector = arith_var_atom_vector(&solver->vtbl, x);
50,833✔
1834
    /*
1835
     * If we have N atoms on variable x, then this code is O(N^2).
1836
     * To limit the cost, we stop generating lemmas when N gets too large
1837
     * (i.e., more than 50).
1838
     */
1839
    if (atom_vector != NULL && iv_size(atom_vector) <= 50) {
50,833✔
1840
      atbl = &solver->atbl;
29,459✔
1841
      atom = arith_atom(atbl, id);
29,459✔
1842
      assert(var_of_atom(atom) == x);
1843
      a = bound_of_atom(atom);
29,459✔
1844
      atom1 = NULL;
29,459✔
1845
      atom2 = NULL;
29,459✔
1846
      n = iv_size(atom_vector);
29,459✔
1847
      for (i=0; i<n; i++) {
161,299✔
1848
        id2 = atom_vector[i];
136,092✔
1849
        assert(id != id2);
1850
        aux = arith_atom(atbl, id2);
136,092✔
1851
        if (q_eq(bound_of_atom(aux), a)) {
136,092✔
1852
          atom1 = aux;
4,252✔
1853
          atom2 = NULL;
4,252✔
1854
          break;
4,252✔
1855
        }
1856
        if (q_lt(bound_of_atom(aux), a)) {
131,840✔
1857
          // bound on aux < a
1858
          if (atom1 == NULL || q_gt(bound_of_atom(aux), bound_of_atom(atom1))) {
75,910✔
1859
            atom1 = aux;
48,545✔
1860
          }
1861
        } else {
1862
          // bound on aux > a
1863
          if (atom2 == NULL || q_lt(bound_of_atom(aux), bound_of_atom(atom2))) {
55,930✔
1864
            atom2 = aux;
15,555✔
1865
          }
1866
        }
1867
      }
1868
      if (atom1 != NULL) {
29,459✔
1869
        create_binary_lemma(solver, atom, atom1);
26,784✔
1870
      }
1871
      if (atom2 != NULL) {
29,459✔
1872
        create_binary_lemma(solver, atom, atom2);
8,728✔
1873
      }
1874
    }
1875
  }
1876
}
51,540✔
1877

1878

1879

1880

1881

1882
/*****************************
1883
 *  POLYNOMIAL CONSTRUCTION  *
1884
 ****************************/
1885

1886
/*
1887
 * Check whether p is a simple polynomial (cheap to substitute for variable x)
1888
 * - return true if p is either (c + b.y) or c or b.y or 0
1889
 */
1890
static bool simple_poly(polynomial_t *p) {
301,817✔
1891
  uint32_t n;
1892

1893
  n = p->nterms;
301,817✔
1894
  return (n <= 1) || (n <= 2 && p->mono[0].var == const_idx);
301,817✔
1895
}
1896

1897

1898
/*
1899
 * Check whether we should substitute x by its definition in polynomials or atoms
1900
 * - x must be different form const_idx
1901
 * - the substitution x := p is applied if it's cheap enough
1902
 */
1903
static bool trivial_variable(arith_vartable_t *tbl, thvar_t x) {
516,848✔
1904
  polynomial_t *q;
1905

1906
  assert(arith_var_kind(tbl, x) == AVAR_FREE ||
1907
         arith_var_kind(tbl, x) == AVAR_POLY);
1908

1909
  /*
1910
   * arith_var_def returns a void* pointer
1911
   * - if x is a free variable, the definition is NULL
1912
   * - otherwise, the definition is a pointer to a polynomial
1913
   */
1914
  q = arith_var_def(tbl, x);
516,848✔
1915
  return q != NULL && simple_poly(q);
516,848✔
1916
}
1917

1918

1919
/*
1920
 * Add monomial a.x to buffer b
1921
 * - if x has a simple definition p, then replace x by p, that is, add a.p to b
1922
 * - a must not be equal to solver->aux
1923
 */
1924
static void add_mono_or_subst(simplex_solver_t *solver, poly_buffer_t *b, thvar_t x, rational_t *a) {
37,554✔
1925
  polynomial_t *p;
1926

1927
  if (x != const_idx && trivial_variable(&solver->vtbl, x)) {
37,554✔
1928
    // replace x by its definition
1929
    p = arith_var_poly_def(&solver->vtbl, x);
1,187✔
1930
    assert(p->nterms <= 2);
1931
    poly_buffer_addmul_poly(b, p, a);
1,187✔
1932
  } else {
1933
    poly_buffer_add_monomial(b, x, a);
36,367✔
1934
  }
1935
}
37,554✔
1936

1937

1938
/*
1939
 * Add variable x to buffer b if x is not trivial
1940
 * otherwise add p to b, where (x := p) is the definition of x
1941
 */
1942
static void add_var_or_subst(simplex_solver_t *solver, poly_buffer_t *b, thvar_t x) {
192,049✔
1943
  polynomial_t *p;
1944

1945
  if (x != const_idx && trivial_variable(&solver->vtbl, x)) {
192,049✔
1946
    p = arith_var_poly_def(&solver->vtbl, x);
49,167✔
1947
    poly_buffer_add_poly(b, p);
49,167✔
1948
  } else {
1949
    poly_buffer_add_var(b, x);
142,882✔
1950
  }
1951
}
192,049✔
1952

1953

1954
/*
1955
 * Subtract x from buffer b if x is not trivial
1956
 * otherwise subtract p from b, where (x := p) is the definition of x
1957
 */
1958
static void sub_var_or_subst(simplex_solver_t *solver, poly_buffer_t *b, thvar_t x) {
188,722✔
1959
  polynomial_t *p;
1960

1961
  if (x != const_idx && trivial_variable(&solver->vtbl, x)) {
188,722✔
1962
    p = arith_var_poly_def(&solver->vtbl, x);
17,640✔
1963
    poly_buffer_sub_poly(b, p);
17,640✔
1964
  } else {
1965
    poly_buffer_sub_var(b, x);
171,082✔
1966
  }
1967
}
188,722✔
1968

1969

1970
/*
1971
 * Store p into solver->buffer and apply the renaming defined by map
1972
 * - p is of the form a_0 t_0 + ... + a_n t_n
1973
 *   map[i] is the simplex variable that represents t_i
1974
 *   with the possible exception that map[0] = null_thvar if t_0 = const_idx
1975
 */
1976
static void rename_poly_aux(simplex_solver_t *solver, polynomial_t *p, thvar_t *map) {
17,835✔
1977
  poly_buffer_t *b;
1978
  uint32_t i, n;
1979
  monomial_t *a;
1980

1981
  b = &solver->buffer;
17,835✔
1982
  assert(poly_buffer_nterms(b) == 0);
1983
  n = p->nterms;
17,835✔
1984

1985
  // if n is zero, there's nothing more to do
1986
  if (n > 0) {
17,835✔
1987
    a = p->mono;
17,835✔
1988

1989
    // deal with the constant first
1990
    if (a[0].var == const_idx) {
17,835✔
1991
      assert(map[0] == null_thvar);
1992

1993
      poly_buffer_add_const(b, &a[0].coeff);
8,564✔
1994
      a ++;
8,564✔
1995
      map ++;
8,564✔
1996
      n --;
8,564✔
1997
    }
1998

1999
    // non-constant monomials
2000
    for (i=0; i<n; i++) {
55,389✔
2001
      add_mono_or_subst(solver, b, map[i], &a[i].coeff);
37,554✔
2002
    }
2003
  }
2004
}
17,835✔
2005

2006

2007
/*
2008
 * Rename variables of p as defined by map
2009
 * - store the result in the internal poly_buffer and normalize the buffer
2010
 */
2011
static void rename_poly(simplex_solver_t *solver, polynomial_t *p, thvar_t *map) {
17,835✔
2012
  rename_poly_aux(solver, p, map);
17,835✔
2013
  normalize_poly_buffer(&solver->buffer);
17,835✔
2014
}
17,835✔
2015

2016

2017

2018
/*
2019
 * Check whether all variables of buffer are integers
2020
 */
2021
static bool all_integer_vars(simplex_solver_t *solver) {
187,811✔
2022
  arith_vartable_t *tbl;
2023
  poly_buffer_t *b;
2024
  monomial_t *a;
2025
  uint32_t i, n;
2026

2027
  b = &solver->buffer;
187,811✔
2028
  tbl = &solver->vtbl;
187,811✔
2029
  n = poly_buffer_nterms(b);
187,811✔
2030
  a = poly_buffer_mono(b);
187,811✔
2031
  for (i=0; i<n; i++) {
537,000✔
2032
    if (! arith_var_is_int(tbl, a[i].var)) return false;
365,122✔
2033
  }
2034
  return true;
171,878✔
2035
}
2036

2037

2038

2039
/*
2040
 * Activate variable x:
2041
 * - add the row x - p == 0 to the matrix provided x is not trivial
2042
 */
2043
static void activate_variable(simplex_solver_t *solver, thvar_t x) {
20,196✔
2044
  polynomial_t *p;
2045

2046
  p = arith_var_def(&solver->vtbl, x);
20,196✔
2047
  if (p != NULL && ! simple_poly(p)) {
20,196✔
2048
    matrix_add_eq(&solver->matrix, x, p->mono, p->nterms);
19,516✔
2049
  }
2050
}
20,196✔
2051

2052

2053

2054
/****************************************
2055
 *  SUPPORT FOR TERM/ATOM CONSTRUCTION  *
2056
 ***************************************/
2057

2058
/*
2059
 * Get a variable x whose definition is equal to the buffer then reset the buffer
2060
 * - if x is a new variable, add a column to the matrix and add a of the form
2061
 *   x - buffer = 0
2062
 */
2063
static thvar_t get_var_from_buffer(simplex_solver_t *solver) {
1,673✔
2064
  poly_buffer_t *b;
2065
  thvar_t x;
2066
  bool new_var;
2067

2068
  b = &solver->buffer;
1,673✔
2069

2070
  // check whether b is reduced to a single variable x
2071
  x = poly_buffer_convert_to_var(b);
1,673✔
2072

2073
  /*
2074
   * HACK: the result of poly_buffer_convert_to_var can be
2075
   *    -1 (null_idx) if b is not of the form 1.x
2076
   *     0 (const_idx) if b is 1
2077
   *     a good variable x if b is 1.x (with x>0)
2078
   *
2079
   * We must build a poly for x in the first two cases.
2080
   */
2081
  if (x <= 0) {
1,673✔
2082
    assert(x == const_idx || x == null_idx);
2083
    x = get_var_for_poly(&solver->vtbl, poly_buffer_mono(b), poly_buffer_nterms(b), &new_var);
1,673✔
2084
    if (new_var) {
1,673✔
2085
      matrix_add_column(&solver->matrix);
1,643✔
2086
      activate_variable(solver, x);
1,643✔
2087
      // set relevance mark in solver->eqprop
2088
      if (solver->eqprop != NULL) {
1,643✔
2089
        eqprop_set_relevance(solver, x);
722✔
2090
      }
2091
    }
2092
  }
2093
  reset_poly_buffer(b);
1,673✔
2094

2095
  return x;
1,673✔
2096
}
2097

2098

2099
/*
2100
 * Create the atom (x >= c) or (x <= c)
2101
 * - is_int indicates whether x is an integer variable or not
2102
 */
2103
static literal_t get_ge_atom(simplex_solver_t *solver, thvar_t x, bool is_int, rational_t *c) {
34,349✔
2104
  literal_t l;
2105
  int32_t new_idx, k;
2106

2107
  assert(solver->decision_level == solver->base_level);
2108

2109
  k = arith_var_upper_index(&solver->vtbl, x);
34,349✔
2110
  if (k >= 0 && xq_lt_q(solver->bstack.bound + k, c)) {
34,349✔
2111
    // axiom: x <= bound[k] and bound[k] < c so (x >= c) is false
2112
    return false_literal;
71✔
2113
  }
2114

2115
  k = arith_var_lower_index(&solver->vtbl, x);
34,278✔
2116
  if (k >= 0 && xq_ge_q(solver->bstack.bound + k, c)) {
34,278✔
2117
    // axiom: x >= bound[k] and bound[k] >= c so (x >= c) is true
2118
    return true_literal;
549✔
2119
  }
2120

2121
  l = get_literal_for_ge_atom(&solver->atbl, x, is_int, c, &new_idx);
33,729✔
2122
  if (new_idx >= 0) {
33,729✔
2123
    build_binary_lemmas_for_atom(solver, x, new_idx);
24,821✔
2124
    attach_atom_to_arith_var(&solver->vtbl, x, new_idx);
24,821✔
2125
  }
2126
  return l;
33,729✔
2127
}
2128

2129
static literal_t get_le_atom(simplex_solver_t *solver, thvar_t x, bool is_int, rational_t *c) {
34,518✔
2130
  literal_t l;
2131
  int32_t new_idx, k;
2132

2133
  assert(solver->decision_level == solver->base_level);
2134

2135
  k = arith_var_lower_index(&solver->vtbl, x);
34,518✔
2136
  if (k >= 0 && xq_gt_q(solver->bstack.bound + k, c)) {
34,518✔
2137
    // axiom: x >= bound[k] and bound[k] > c so (x <= c) is false
2138
    return false_literal;
54✔
2139
  }
2140

2141
  k = arith_var_upper_index(&solver->vtbl, x);
34,464✔
2142
  if (k >= 0 && xq_le_q(solver->bstack.bound + k, c)) {
34,464✔
2143
    // axiom: x <= bound[k] and bound[k] <= c so (x <= c) is true
2144
    return true_literal;
491✔
2145
  }
2146

2147
  l = get_literal_for_le_atom(&solver->atbl, x, is_int, c, &new_idx);
33,973✔
2148
  if (new_idx >= 0) {
33,973✔
2149
    build_binary_lemmas_for_atom(solver, x, new_idx);
25,246✔
2150
    attach_atom_to_arith_var(&solver->vtbl, x, new_idx);
25,246✔
2151
  }
2152
  return l;
33,973✔
2153
}
2154

2155

2156

2157
/*
2158
 * Decompose the buffer into (p + a) where a is the constant term
2159
 * - store the opposite of a into solver->constant
2160
 * - return a variable x equal to the non-constant part (i.e., p)
2161
 * - if x is a new variable, add a column to the matrix
2162
 */
2163
static thvar_t decompose_and_get_var(simplex_solver_t *solver) {
46,261✔
2164
  poly_buffer_t *b;
2165
  thvar_t x;
2166
  bool new_var;
2167

2168
  b = &solver->buffer;
46,261✔
2169
  poly_buffer_get_neg_constant(b, &solver->constant);
46,261✔
2170
  x = poly_buffer_nonconstant_convert_to_var(b);
46,261✔
2171
  if (x < 0) {
46,261✔
2172
    x = get_var_for_poly_offset(&solver->vtbl, poly_buffer_mono(b), poly_buffer_nterms(b), &new_var);
22,849✔
2173
    if (new_var) {
22,849✔
2174
      matrix_add_column(&solver->matrix);
18,553✔
2175
      activate_variable(solver, x);
18,553✔
2176
      // set relevance mark in solver->eqprop
2177
      if (solver->eqprop != NULL) {
18,553✔
2178
        eqprop_set_relevance(solver, x);
2,380✔
2179
      }
2180
    }
2181
  }
2182
  reset_poly_buffer(b);
46,261✔
2183
  return x;
46,261✔
2184
}
2185

2186

2187
/*
2188
 * Create the atom p >= 0 where p is stored in the solver's buffer
2189
 * - the buffer must be normalized
2190
 */
2191
static literal_t make_ge_atom(simplex_solver_t *solver) {
9,956✔
2192
  poly_buffer_t *b;
2193
  bool negated, is_int;
2194
  thvar_t x;
2195

2196
  b = &solver->buffer;
9,956✔
2197

2198
  /*
2199
   * Check whether the atom is trivially true or false
2200
   */
2201
  if (poly_buffer_is_zero(b) || poly_buffer_is_pos_constant(b)) {
9,956✔
2202
#if TRACE
2203
    printf("---> true\n");
2204
#endif
2205
    reset_poly_buffer(b);
53✔
2206
    return true_literal;
53✔
2207
  }
2208

2209
  if (poly_buffer_is_neg_constant(b)) {
9,903✔
2210
#if TRACE
2211
    printf("---> false\n");
2212
#endif
2213
    reset_poly_buffer(b);
34✔
2214
    return false_literal;
34✔
2215
  }
2216

2217
  /*
2218
   * Normalize to x <= b or x >= b
2219
   */
2220
  is_int = all_integer_vars(solver);
9,869✔
2221
  if (is_int) {
9,869✔
2222
    // make coefficients integers
2223
    negated = poly_buffer_make_nonconstant_integral(b);
3,886✔
2224
#if TRACE
2225
    printf("---> int scaling: ");
2226
    print_simplex_buffer(stdout, solver);
2227
    printf("\n");
2228
#endif
2229
    x = decompose_and_get_var(solver);
3,886✔
2230
    assert(arith_var_is_int(&solver->vtbl, x));
2231
    // strengthen the bound
2232
    // TODO: if x is a polynomial, we could strengthen more, i.e.,
2233
    //       divide by the GCD of x's coefficients?
2234
    if (negated) {
3,886✔
2235
      q_floor(&solver->constant);
2,047✔
2236
    } else {
2237
      q_ceil(&solver->constant);
1,839✔
2238
    }
2239

2240
  } else {
2241
    // make lead coefficient = 1
2242
    negated = poly_buffer_make_monic(b);
5,983✔
2243
#if TRACE
2244
    printf("---> monic: ");
2245
    print_simplex_buffer(stdout, solver);
2246
    printf("\n");
2247
#endif
2248
    x = decompose_and_get_var(solver);
5,983✔
2249
    assert(! arith_var_is_int(&solver->vtbl, x));
2250
  }
2251

2252

2253
  /*
2254
   * If negated is true, the atom is (x <= constant) otherwise
2255
   * it's (x >= constant)
2256
   */
2257
  if (negated) {
9,869✔
2258
#if TRACE
2259
    printf("---> atom ");
2260
    print_simplex_var(stdout, solver, x);
2261
    printf(" <= ");
2262
    q_print(stdout, &solver->constant);
2263
    printf("\n");
2264
    if (! arith_var_is_free(&solver->vtbl, x)) {
2265
      printf("     ");
2266
      print_simplex_vardef(stdout, solver, x);
2267
    }
2268
#endif
2269

2270
    return get_le_atom(solver, x, is_int, &solver->constant);
5,019✔
2271

2272
  } else {
2273
#if TRACE
2274
    printf("---> atom ");
2275
    print_simplex_var(stdout, solver, x);
2276
    printf(" >= ");
2277
    q_print(stdout, &solver->constant);
2278
    printf("\n");
2279
    if (! arith_var_is_free(&solver->vtbl, x)) {
2280
      printf("     ");
2281
      print_simplex_vardef(stdout, solver, x);
2282
    }
2283
#endif
2284

2285
    return get_ge_atom(solver, x, is_int, &solver->constant);
4,850✔
2286
  }
2287
}
2288

2289

2290
/*
2291
 * Auxiliary function: simplify the atom p == 0 where p is stored in the buffer
2292
 * - check whether p == 0 simplifies to true or false
2293
 * - if not, create the two atoms (p >= 0) and (p <= 0)
2294
 * Results:
2295
 * - if the atom simplifies, the returned value is either true_literal or false_literal
2296
 * - otherwise the returned value is null_literal, and literals for (p >= 0) and (p <= 0)
2297
 *   are returned in *l1 and *l2
2298
 */
2299
static literal_t simplify_eq_atom(simplex_solver_t *solver, literal_t *l1, literal_t *l2) {
37,642✔
2300
  poly_buffer_t *b;
2301
  thvar_t x;
2302
  bool is_int;
2303

2304
  b = &solver->buffer;
37,642✔
2305

2306
  if (poly_buffer_is_zero(b)) {
37,642✔
2307
#if TRACE
2308
    printf("---> true\n");
2309
#endif
2310
    reset_poly_buffer(b);
4,490✔
2311
    return true_literal;
4,490✔
2312
  }
2313

2314
  if (poly_buffer_is_nzconstant(b)) {
33,152✔
2315
#if TRACE
2316
    printf("---> false\n");
2317
#endif
2318
    reset_poly_buffer(b);
3,651✔
2319
    return false_literal;
3,651✔
2320
  }
2321

2322
  is_int = all_integer_vars(solver);
29,501✔
2323
  if (is_int) {
29,501✔
2324
    poly_buffer_make_integral(b);
25,930✔
2325
#if TRACE
2326
    printf("---> int scaling: ");
2327
    print_simplex_buffer(stdout, solver);
2328
    printf("\n");
2329
#endif
2330
    if (! poly_buffer_gcd_test(b)) {
25,930✔
2331
#if TRACE
2332
      printf("---> false by GCD test\n");
2333
#endif
2334
      reset_poly_buffer(b);
2✔
2335
      return false_literal;
2✔
2336
    }
2337
  } else {
2338
    poly_buffer_make_monic(b); // make lead coefficient = 1
3,571✔
2339

2340
#if TRACE
2341
    printf("---> monic: ");
2342
    print_simplex_buffer(stdout, solver);
2343
    printf("\n");
2344
#endif
2345
  }
2346

2347
  x = decompose_and_get_var(solver);  // buffer is now equal to x - c where c = &solver->constant
29,499✔
2348

2349
#if TRACE
2350
  printf("---> atom ");
2351
  print_simplex_var(stdout, solver, x);
2352
  printf(" == ");
2353
  q_print(stdout, &solver->constant);
2354
  printf("\n");
2355
  if (! arith_var_is_free(&solver->vtbl, x)) {
2356
    printf("     ");
2357
    print_simplex_vardef(stdout, solver, x);
2358
  }
2359
#endif
2360

2361
  *l1 = get_ge_atom(solver, x, is_int, &solver->constant);
29,499✔
2362
  *l2 = get_le_atom(solver, x, is_int, &solver->constant);
29,499✔
2363

2364
  return null_literal;
29,499✔
2365
}
2366

2367

2368
/*
2369
 * Create the atom p == 0 where p is stored in the buffer
2370
 * - check for simplification first
2371
 * - create (and (p >= 0) (p <= 0)) otherwise
2372
 */
2373
static literal_t make_eq_atom(simplex_solver_t *solver) {
30,973✔
2374
  literal_t l1, l2, l;
2375

2376
  l = simplify_eq_atom(solver, &l1, &l2);
30,973✔
2377
  if (l == null_literal) {
30,973✔
2378
    l = mk_and_gate2(solver->gate_manager, l1, l2);
22,860✔
2379
  }
2380
  return l;
30,973✔
2381
}
2382

2383

2384

2385
/*
2386
 * Assert c as lower bound for x
2387
 * - strict indicates whether the bound is strict or not
2388
 */
2389
static void add_lb_axiom(simplex_solver_t *solver, thvar_t x, rational_t *c, bool strict) {
5,266✔
2390
  xrational_t *b;
2391
  int32_t k;
2392

2393
  assert(solver->base_level == solver->decision_level);
2394

2395
#if TRACE
2396
  printf("---> add_lb_axiom: ");
2397
  print_simplex_var(stdout, solver, x);
2398
  if (strict) {
2399
    printf(" > ");
2400
  } else {
2401
    printf(" >= ");
2402
  }
2403
  q_print(stdout, c);
2404
  printf("\n");
2405
  if (! arith_var_is_free(&solver->vtbl, x)) {
2406
    printf("     ");
2407
    print_simplex_vardef(stdout, solver, x);
2408
  }
2409
#endif
2410

2411
  // store the bound as an extended rational
2412
  b = &solver->bound;
5,266✔
2413
  if (strict) {
5,266✔
2414
    xq_set_q_plus_delta(b, c);
136✔
2415
  } else {
2416
    xq_set_q(b, c);
5,130✔
2417
  }
2418

2419
  k = arith_var_upper_index(&solver->vtbl, x);
5,266✔
2420
  if (k >= 0 && xq_lt(solver->bstack.bound + k, b)) {
5,266✔
2421
    // Unsat: the existing upper bound on x is < b
2422
    solver->unsat_before_search = true;
41✔
2423
#if TRACE
2424
    printf("---> Conflict\n\n");
2425
#endif
2426
    return;
41✔
2427
  }
2428

2429
  k = arith_var_lower_index(&solver->vtbl, x);
5,225✔
2430
  if (k >= 0 && xq_ge(solver->bstack.bound + k, b)) {
5,225✔
2431
    // Redundant: the existing lower bound is >= b
2432
#if TRACE
2433
    printf("---> Redundant\n\n");
2434
#endif
2435
    return;
339✔
2436
  }
2437

2438
  push_lb_axiom(solver, x, b);
4,886✔
2439
}
2440

2441

2442
/*
2443
 * Assert c as upper bound for x
2444
 * - strict indicates whether the bound is strict or not
2445
 */
2446
static void add_ub_axiom(simplex_solver_t *solver, thvar_t x, rational_t *c, bool strict) {
4,463✔
2447
  xrational_t *b;
2448
  int32_t k;
2449

2450
  assert(solver->base_level == solver->decision_level);
2451

2452
#if TRACE
2453
  printf("---> add_ub_axiom: ");
2454
  print_simplex_var(stdout, solver, x);
2455
  if (strict) {
2456
    printf(" < ");
2457
  } else {
2458
    printf(" <= ");
2459
  }
2460
  q_print(stdout, c);
2461
  printf("\n");
2462
  if (! arith_var_is_free(&solver->vtbl, x)) {
2463
    printf("     ");
2464
    print_simplex_vardef(stdout, solver, x);
2465
  }
2466
#endif
2467

2468

2469
  // store the bound as an extended rational
2470
  b = &solver->bound;
4,463✔
2471
  if (strict) {
4,463✔
2472
    xq_set_q_minus_delta(b, c);
153✔
2473
  } else {
2474
    xq_set_q(b, c);
4,310✔
2475
  }
2476

2477
  k = arith_var_lower_index(&solver->vtbl, x);
4,463✔
2478
  if (k >= 0 && xq_gt(solver->bstack.bound + k, b)) {
4,463✔
2479
    // Unsat: existing lower bound on x is > b
2480
    solver->unsat_before_search = true;
18✔
2481
#if TRACE
2482
    printf("---> Conflict\n\n");
2483
#endif
2484
    return;
18✔
2485
  }
2486

2487
  k = arith_var_upper_index(&solver->vtbl, x);
4,445✔
2488
  if (k >= 0 && xq_le(solver->bstack.bound + k, b)) {
4,445✔
2489
    // redundant: existing upper bound <= b
2490
#if TRACE
2491
    printf("---> Redundant\n\n");
2492
#endif
2493
    return;
222✔
2494
  }
2495

2496
  push_ub_axiom(solver, x, b);
4,223✔
2497
}
2498

2499

2500

2501
/*
2502
 * Add the axiom p == 0 where p is stored in the solver's buffer
2503
 * - if p == 0 simplifies to false, set the 'unsat_before_search' flag
2504
 * - if p == 0 simplifies to true, do nothing
2505
 * - if p == 0 is equivalent to x == c for a variable x and constant c
2506
 *   then add the bounds (x <= c) and (x >= c)
2507
 * - otherwise, add the row p == 0 to the matrix
2508
 */
2509
static void add_eq_axiom(simplex_solver_t *solver) {
1,977✔
2510
  poly_buffer_t *b;
2511
  thvar_t x;
2512

2513
#if TRACE
2514
  printf("---> simplex_add_eq_axiom: ");
2515
  print_simplex_buffer(stdout, solver);
2516
  printf(" == 0\n");
2517
#endif
2518

2519
  b = &solver->buffer;
1,977✔
2520
  if (poly_buffer_is_zero(b)) {
1,977✔
2521
#if TRACE
2522
    printf("---> true\n");
2523
#endif
2524
    goto done;
6✔
2525
  }
2526

2527
  if (poly_buffer_is_nzconstant(b)) {
1,971✔
2528
#if TRACE
2529
    printf("---> false\n");
2530
#endif
2531
    solver->unsat_before_search = true;
2✔
2532
    goto done;
2✔
2533
  }
2534

2535
  if (all_integer_vars(solver)) {
1,969✔
2536
    poly_buffer_make_integral(b);
1,049✔
2537
#if TRACE
2538
    printf("---> int scaling: ");
2539
    print_simplex_buffer(stdout, solver);
2540
    printf("\n");
2541
#endif
2542
    if (! poly_buffer_gcd_test(b)) {
1,049✔
2543
#if TRACE
2544
      printf("---> false by GCD test\n");
2545
#endif
2546
      solver->unsat_before_search = true;
1✔
2547
      goto done;
1✔
2548
    }
2549
  }
2550

2551

2552
  // Check whether p == 0 can be rewritten to (x == constant)
2553
  x = poly_buffer_convert_to_vareq(b, &solver->constant);
1,968✔
2554
  if (x >= 0) {
1,968✔
2555
#if TRACE
2556
    printf("---> simplified to ");
2557
    print_simplex_var(stdout, solver, x);
2558
    printf(" == ");
2559
    q_print(stdout, &solver->constant);
2560
    printf("\n");
2561
#endif
2562
    // assert bounds (x <= constant) and (x >= constant)
2563
    add_ub_axiom(solver, x, &solver->constant, false);
883✔
2564
    add_lb_axiom(solver, x, &solver->constant, false);
883✔
2565
    goto done;
883✔
2566
  }
2567

2568

2569
#if TRACE
2570
  printf("---> new row\n");
2571
#endif
2572
  if (solver->save_rows) {
1,085✔
2573
    // make a copy so that the matrix can be restored if needed
2574
    pvector_push(&solver->saved_rows, monarray_copy_to_poly(poly_buffer_mono(b), poly_buffer_nterms(b)));
775✔
2575
  }
2576
  matrix_add_row(&solver->matrix, poly_buffer_mono(b), poly_buffer_nterms(b));
1,085✔
2577

2578
 done:
1,977✔
2579
  reset_poly_buffer(b);
1,977✔
2580
}
1,977✔
2581

2582

2583
/*
2584
 * Assert the axiom (p == 0) or (p != 0), where p is stored in the solver's buffer
2585
 * - if tt is true  --> assert (p == 0)
2586
 * - if tt is false --> assert (p != 0)
2587
 */
2588
static void add_eq_or_diseq_axiom(simplex_solver_t *solver, bool tt) {
2,230✔
2589
  literal_t l, l1, l2;
2590

2591
  if (tt) {
2,230✔
2592
    add_eq_axiom(solver);
1,977✔
2593
  } else {
2594
    // Add the clause (or (not (p >= 0)) (not (p <= 0)))
2595
    l = simplify_eq_atom(solver, &l1, &l2);
253✔
2596
    if (l == null_literal) {
253✔
2597
      // l1 is (p >= 0), l2 is (p <= 0): assert (or (not l1) (not l2))
2598
      add_binary_clause(solver->core, not(l1), not(l2));
223✔
2599

2600
#if TRACE
2601
      printf("---> adding clause: ");
2602
      print_binary_clause(stdout, not(l1), not(l2));
2603
      printf("\n");
2604
      if (var_of(l1) != const_bvar) {
2605
        print_simplex_atomdef(stdout, solver, var_of(l1));
2606
      }
2607
      if (var_of(l2) != const_bvar) {
2608
        print_simplex_atomdef(stdout, solver, var_of(l2));
2609
      }
2610
#endif
2611

2612
    } else if (l == true_literal) {
30✔
2613
      // p == 0 is true: mark the whole thing as unsat
2614
      solver->unsat_before_search = true;
18✔
2615
    } // otherwise l == false_literal: nothing to do
2616
  }
2617
}
2,230✔
2618

2619

2620
/*
2621
 * Assert the axiom (p >= 0) or (p < 0), where p is stored in the solver's buffer
2622
 * - if tt is true --> assert (p >= 0)
2623
 * - if tt is false --> assert (p < 0)
2624
 * - check whether the assertion simplifies to true or false first
2625
 * - if it's false, set the flag unsat_before_search
2626
 */
2627
static void add_ge_axiom(simplex_solver_t *solver, bool tt) {
7,466✔
2628
  poly_buffer_t *b;
2629
  bool negated;
2630
  thvar_t x;
2631

2632
#if TRACE
2633
  printf("---> simplex_add_ge_axiom: ");
2634
  print_simplex_buffer(stdout, solver);
2635
  if (tt) {
2636
    printf(" >= 0\n");
2637
  } else {
2638
    printf(" < 0\n");
2639
  }
2640
#endif
2641

2642
  b = &solver->buffer;
7,466✔
2643
  if (poly_buffer_is_zero(b) || poly_buffer_is_pos_constant(b)) {
7,466✔
2644
    // p >= 0 is trivially true
2645
    if (! tt) solver->unsat_before_search = true;
569✔
2646
#if TRACE
2647
    if (!tt) {
2648
      printf("---> unsat\n");
2649
    } else {
2650
      printf("---> redundant\n");
2651
    }
2652
#endif
2653
    goto done;
569✔
2654
  }
2655

2656
  if (poly_buffer_is_neg_constant(b)) {
6,897✔
2657
    // p >= 0 is trivially false
2658
    if (tt) solver->unsat_before_search = true;
4✔
2659
#if TRACE
2660
    if (!tt) {
2661
      printf("---> unsat\n");
2662
    } else {
2663
      printf("---> redundant\n");
2664
    }
2665
#endif
2666
    goto done;
4✔
2667
  }
2668

2669

2670
  /*
2671
   * Normalize then assert the bound
2672
   */
2673
  if (all_integer_vars(solver)) {
6,893✔
2674
    negated = poly_buffer_make_nonconstant_integral(b);
4,749✔
2675
#if TRACE
2676
    printf("---> int scaling: ");
2677
    print_simplex_buffer(stdout, solver);
2678
    printf("\n");
2679
#endif
2680
    x = decompose_and_get_var(solver);
4,749✔
2681
    assert(arith_var_is_int(&solver->vtbl, x));
2682
    if (negated) {
4,749✔
2683
      // TODO: strengthen more if x is a polynomial (divide by GCD of x's coefficients)
2684
      q_floor(&solver->constant);
1,662✔
2685
      if (tt) {
1,662✔
2686
        // (p >= 0) is equivalent to (x <= constant)
2687
        add_ub_axiom(solver, x, &solver->constant, false);
1,500✔
2688
#if TRACE
2689
        printf("---> ");
2690
        print_simplex_vardef(stdout, solver, x);
2691
        printf("---> bound: ");
2692
        print_simplex_var_bounds(stdout, solver, x);
2693
        printf("\n");
2694
#endif
2695
      } else {
2696
        // not (p >= 0) is equivalent to (x >= constant + 1)
2697
        q_add_one(&solver->constant);
162✔
2698
        add_lb_axiom(solver, x, &solver->constant, false);
162✔
2699
#if TRACE
2700
        printf("---> ");
2701
        print_simplex_vardef(stdout, solver, x);
2702
        printf("---> bound: ");
2703
        print_simplex_var_bounds(stdout, solver, x);
2704
        printf("\n");
2705
#endif
2706
      }
2707
    } else {
2708
      // TODO: strengthen more if x is a polynomial (divide by GCD of x's coefficients)
2709
      q_ceil(&solver->constant);
3,087✔
2710
      if (tt) {
3,087✔
2711
        // (p >= 0) is equivalent to (x >= constant)
2712
        add_lb_axiom(solver, x, &solver->constant, false);
2,335✔
2713
#if TRACE
2714
        printf("---> ");
2715
        print_simplex_vardef(stdout, solver, x);
2716
        printf("---> bound: ");
2717
        print_simplex_var_bounds(stdout, solver, x);
2718
        printf("\n");
2719
#endif
2720
      } else {
2721
        // not (p >= 0) is equivalent to (x <= constant - 1)
2722
        q_sub_one(&solver->constant);
752✔
2723
        add_ub_axiom(solver, x, &solver->constant, false);
752✔
2724
#if TRACE
2725
        printf("---> ");
2726
        print_simplex_vardef(stdout, solver, x);
2727
        printf("---> bound: ");
2728
        print_simplex_var_bounds(stdout, solver, x);
2729
        printf("\n");
2730
#endif
2731
      }
2732
    }
2733

2734
  } else {
2735
    negated = poly_buffer_make_monic(b);
2,144✔
2736
#if TRACE
2737
    printf("---> monic: ");
2738
    print_simplex_buffer(stdout, solver);
2739
    printf("\n");
2740
#endif
2741
    x = decompose_and_get_var(solver);
2,144✔
2742
    assert(! arith_var_is_int(&solver->vtbl, x));
2743
    if (negated == tt) {
2,144✔
2744
      // assert (p >= 0) <=> (x <= b) if tt
2745
      // assert (p < 0)  <=> (x < b)  if !tt
2746
      add_ub_axiom(solver, x, &solver->constant, !tt);
793✔
2747
    } else {
2748
      // assert (p >= 0) <=> (x >= b) if tt
2749
      // assert (p < 0)  <=> (x > b) if !tt
2750
      add_lb_axiom(solver, x, &solver->constant, !tt);
1,351✔
2751
    }
2752
  }
2753
  return;
6,893✔
2754

2755
 done:
573✔
2756
  reset_poly_buffer(b);
573✔
2757
}
2758

2759

2760

2761

2762
/**********************
2763
 *  INTERNALIZATION   *
2764
 *********************/
2765

2766
/*
2767
 * TERM CONSTRUCTION
2768
 */
2769

2770
/*
2771
 * Create a new theory variable
2772
 * - is_int indicates whether the variable should be an integer
2773
 * - also add a matrix column
2774
 */
2775
thvar_t simplex_create_var(simplex_solver_t *solver, bool is_int) {
11,090✔
2776
  thvar_t x;
2777

2778
  matrix_add_column(&solver->matrix);
11,090✔
2779
  x = create_arith_var(&solver->vtbl, is_int);
11,090✔
2780
  if (solver->eqprop != NULL) {
11,090✔
2781
    eqprop_set_relevance(solver, x);
5,123✔
2782
  }
2783
  return x;
11,090✔
2784
}
2785

2786

2787
/*
2788
 * Create a new variable that represents constant q
2789
 * - add a matrix column if that's a new variable
2790
 */
2791
thvar_t simplex_create_const(simplex_solver_t *solver, rational_t *q) {
1,569✔
2792
  poly_buffer_t *b;
2793
  thvar_t x;
2794
  bool new_var;
2795

2796
  b = &solver->buffer;
1,569✔
2797
  assert(poly_buffer_nterms(b) == 0);
2798
  poly_buffer_add_const(b, q);
1,569✔
2799
  normalize_poly_buffer(b);
1,569✔
2800
  x = get_var_for_poly(&solver->vtbl, poly_buffer_mono(b), poly_buffer_nterms(b), &new_var);
1,569✔
2801
  if (new_var) {
1,569✔
2802
    matrix_add_column(&solver->matrix);
1,567✔
2803
    // set relevance mark in solver->eqprop
2804
    if (solver->eqprop != NULL) {
1,567✔
2805
      eqprop_set_relevance(solver, x);
345✔
2806
    }
2807
  }
2808
  reset_poly_buffer(b);
1,569✔
2809

2810
  assert(trivial_variable(&solver->vtbl, x));
2811

2812
  return x;
1,569✔
2813
}
2814

2815

2816
/*
2817
 * Create a theory variable equal to p
2818
 * - arith_map maps variables of p to corresponding theory variables
2819
 *   in the solver
2820
 */
2821
thvar_t simplex_create_poly(simplex_solver_t *solver, polynomial_t *p, thvar_t *map) {
1,673✔
2822
#if TRACE
2823
  thvar_t x;
2824

2825
  printf("\n---> simplex_create_poly: ");
2826
  print_polynomial(stdout, p);
2827
  printf("\n");
2828
  rename_poly(solver, p, map);
2829
  printf("---> renaming: ");
2830
  print_simplex_buffer(stdout, solver);
2831
  printf("\n");
2832
  x = get_var_from_buffer(solver);
2833
  printf("---> var: ");
2834
  print_simplex_vardef(stdout, solver, x);
2835
  printf("\n");
2836

2837
  return x;
2838
#else
2839
  rename_poly(solver, p, map);
1,673✔
2840
  return get_var_from_buffer(solver);
1,673✔
2841
#endif
2842
}
2843

2844

2845

2846

2847
/*
2848
 * Placeholder for a power product p: raise an exception
2849
 */
2850
thvar_t simplex_create_pprod(simplex_solver_t *solver, pprod_t *p, thvar_t *map) {
×
2851
  if (solver->env != NULL) {
×
2852
    longjmp(*solver->env, FORMULA_NOT_LINEAR);
×
2853
  }
2854
  abort();
×
2855
}
2856

2857

2858
/*
2859
 * Attach egraph term t to a variable v
2860
 * - v must not have an eterm attached already
2861
 */
2862
void simplex_attach_eterm(simplex_solver_t *solver, thvar_t v, eterm_t t) {
5,649✔
2863
  attach_eterm_to_arith_var(&solver->vtbl, v, t);
5,649✔
2864
  // propagate to the eq_propagator if it exists
2865
  if (solver->eqprop != NULL) {
5,649✔
2866
    eqprop_record_eterm(solver, v, t);
5,427✔
2867
  }
2868
}
5,649✔
2869

2870

2871
/*
2872
 * Get the egraph term t attached to v
2873
 * - return null_eterm if v has no eterm attached
2874
 */
2875
eterm_t simplex_eterm_of_var(simplex_solver_t *solver, thvar_t v) {
5,217✔
2876
  return arith_var_get_eterm(&solver->vtbl, v);
5,217✔
2877
}
2878

2879

2880
/*
2881
 * ATOM CONSTRUCTION
2882
 */
2883

2884
/*
2885
 * Create the atom x >= 0
2886
 * - this attach the atom to the smt_core
2887
 */
2888
literal_t simplex_create_ge_atom(simplex_solver_t *solver, thvar_t x) {
346✔
2889
  poly_buffer_t *b;
2890

2891
  assert(valid_arith_var(&solver->vtbl, x));
2892

2893
  // replace x by its definition if it's a trivial variable
2894
  b = &solver->buffer;
346✔
2895
  add_var_or_subst(solver, b, x);
346✔
2896
  normalize_poly_buffer(b);
346✔
2897

2898
#if TRACE
2899
  printf("\n---> simplex_create_ge_atom: ");
2900
  print_simplex_var(stdout, solver, x);
2901
  printf(" >= 0\n");
2902
  printf("---> renaming: ");
2903
  print_simplex_buffer(stdout, solver);
2904
  printf("\n");
2905
#endif
2906

2907
  return make_ge_atom(solver);
346✔
2908
}
2909

2910

2911
/*
2912
 * Create the atom p >= 0 and return the corresponding literal
2913
 * - replace the variables of p as defined by map
2914
 */
2915
literal_t simplex_create_poly_ge_atom(simplex_solver_t *solver, polynomial_t *p, thvar_t *map) {
9,610✔
2916
  rename_poly(solver, p, map);
9,610✔
2917

2918
#if TRACE
2919
  printf("\n---> simplex_create_poly_ge_atom: ");
2920
  print_polynomial(stdout, p);
2921
  printf(" >= 0\n");
2922
  printf("---> renaming: ");
2923
  print_simplex_buffer(stdout, solver);
2924
  printf("\n");
2925
#endif
2926

2927
  return make_ge_atom(solver);
9,610✔
2928
}
2929

2930

2931

2932
/*
2933
 * Create the atom x == 0
2934
 * - this attach the atom to the smt_core
2935
 */
2936
literal_t simplex_create_eq_atom(simplex_solver_t *solver, thvar_t x) {
591✔
2937
  poly_buffer_t *b;
2938

2939
  // replace x by its definition if it's a trivial variable
2940
  b = &solver->buffer;
591✔
2941
  add_var_or_subst(solver, b, x);
591✔
2942
  normalize_poly_buffer(b);
591✔
2943

2944
#if TRACE
2945
  printf("\n---> simplex_create_eq_atom: ");
2946
  print_simplex_var(stdout, solver, x);
2947
  printf(" == 0\n");
2948
  printf("---> renaming: ");
2949
  print_simplex_buffer(stdout, solver);
2950
  printf("\n");
2951
#endif
2952

2953
  return make_eq_atom(solver);
591✔
2954
}
2955

2956

2957
/*
2958
 * Create the atom p == 0
2959
 * - apply the renaming defined by map
2960
 */
2961
literal_t simplex_create_poly_eq_atom(simplex_solver_t *solver, polynomial_t *p, thvar_t *map) {
871✔
2962
  rename_poly(solver, p, map);
871✔
2963

2964
#if TRACE
2965
  printf("\n---> simplex_create_poly_eq_atom: ");
2966
  print_polynomial(stdout, p);
2967
  printf(" == 0\n");
2968
  printf("---> renaming: ");
2969
  print_simplex_buffer(stdout, solver);
2970
  printf("\n");
2971
#endif
2972

2973
  return make_eq_atom(solver);
871✔
2974
}
2975

2976
/*
2977
 * Create the atom x - y == 0
2978
 * - x and y are two theory variables
2979
 */
2980
literal_t simplex_create_vareq_atom(simplex_solver_t *solver, thvar_t x, thvar_t y) {
29,511✔
2981
  poly_buffer_t *b;
2982

2983
  assert(valid_arith_var(&solver->vtbl, x) && valid_arith_var(&solver->vtbl, y));
2984

2985
  b = &solver->buffer;
29,511✔
2986
  assert(poly_buffer_nterms(b) == 0);
2987
  add_var_or_subst(solver, b, x);
29,511✔
2988
  sub_var_or_subst(solver, b, y);
29,511✔
2989
  normalize_poly_buffer(b);
29,511✔
2990

2991
#if TRACE
2992
  printf("\n---> simplex_create_vareq_atom: ");
2993
  print_simplex_var(stdout, solver, x);
2994
  printf(" == ");
2995
  print_simplex_var(stdout, solver, y);
2996
  printf("\n");
2997
  printf("---> after subst: ");
2998
  print_simplex_buffer(stdout, solver);
2999
  printf("\n");
3000
#endif
3001

3002
  return make_eq_atom(solver);
29,511✔
3003
}
3004

3005

3006
/*
3007
 * AXIOMS (BASE-LEVEL ASSERTIONS)
3008
 */
3009

3010
/*
3011
 * Assert a top-level inequality (either x >= 0 or x < 0)
3012
 * - tt indicates whether the constraint or its negation must be asserted
3013
 *   tt == true  --> assert x >= 0
3014
 *   tt == false --> assert x < 0
3015
 */
3016
void simplex_assert_ge_axiom(simplex_solver_t *solver, thvar_t x, bool tt){
1,878✔
3017
  poly_buffer_t *b;
3018

3019
  assert(valid_arith_var(&solver->vtbl, x));
3020

3021
  // replace x by its definition if it's a trivial variable
3022
  b = &solver->buffer;
1,878✔
3023
  add_var_or_subst(solver, b, x);
1,878✔
3024
  normalize_poly_buffer(b);
1,878✔
3025

3026
#if TRACE
3027
  printf("\n---> simplex_assert_ge_axiom: ");
3028
  print_simplex_var(stdout, solver, x);
3029
  if (tt) {
3030
    printf(" >= 0\n");
3031
  } else {
3032
    printf(" < 0\n");
3033
  }
3034
  printf("---> renaming: ");
3035
  print_simplex_buffer(stdout, solver);
3036
  printf("\n");
3037
#endif
3038

3039
  add_ge_axiom(solver, tt);
1,878✔
3040
}
1,878✔
3041

3042

3043
/*
3044
 * Assert a top-level inequality (either p >= 0 or p < 0)
3045
 * - map: convert p's variables to simplex variables
3046
 * - tt indicates which of the two inequalities to assert
3047
 */
3048
void simplex_assert_poly_ge_axiom(simplex_solver_t *solver, polynomial_t *p, thvar_t *map, bool tt) {
5,588✔
3049
  rename_poly(solver, p, map);
5,588✔
3050

3051
#if TRACE
3052
  printf("\n---> simplex_assert_poly_ge_axiom: ");
3053
  //  print_polynomial(stdout, p);
3054
  print_simplex_buffer(stdout, solver);
3055
  if (tt) {
3056
    printf(" >= 0\n");
3057
  } else {
3058
    printf(" < 0\n");
3059
  }
3060
#endif
3061

3062
  add_ge_axiom(solver, tt);
5,588✔
3063
}
5,588✔
3064

3065

3066
/*
3067
 * Assert a top-level equality constraint (either x == 0 or x != 0)
3068
 * - tt indicates whether the constraint or its negation must be asserted
3069
 *   tt == true  --> assert x == 0
3070
 *   tt == false --> assert x != 0
3071
 */
3072
void simplex_assert_eq_axiom(simplex_solver_t *solver, thvar_t x, bool tt) {
512✔
3073
  poly_buffer_t *b;
3074

3075
  assert(valid_arith_var(&solver->vtbl, x));
3076

3077
  // replace x by its definition if it's a trivial variable
3078
  b = &solver->buffer;
512✔
3079
  add_var_or_subst(solver, b, x);
512✔
3080
  normalize_poly_buffer(b);
512✔
3081

3082
#if TRACE
3083
  printf("\n---> simplex_assert_eq_axiom: ");
3084
  print_simplex_var(stdout, solver, x);
3085
  if (tt) {
3086
    printf(" == 0\n");
3087
  } else {
3088
    printf(" != 0\n");
3089
  }
3090
  printf("---> renaming: ");
3091
  print_simplex_buffer(stdout, solver);
3092
  printf("\n");
3093
#endif
3094

3095
  add_eq_or_diseq_axiom(solver, tt);
512✔
3096
}
512✔
3097

3098

3099
/*
3100
 * Assert top-level equality or disequality (either p == 0 or p != 0)
3101
 * - map: convert p's variables to simplex variables
3102
 * - if tt is true  ---> assert p == 0
3103
 * - if tt is false ---> assert p != 0
3104
 */
3105
void simplex_assert_poly_eq_axiom(simplex_solver_t *solver, polynomial_t *p, thvar_t *map, bool tt) {
93✔
3106
  rename_poly(solver, p, map);
93✔
3107

3108
#if TRACE
3109
  printf("\n---> simplex_assert_poly_eq_axiom: ");
3110
  print_polynomial(stdout, p);
3111
  if (tt) {
3112
    printf(" == 0\n");
3113
  } else {
3114
    printf(" != 0\n");
3115
  }
3116
  printf("---> renaming: ");
3117
  print_simplex_buffer(stdout, solver);
3118
  printf("\n");
3119
#endif
3120

3121
  add_eq_or_diseq_axiom(solver, tt);
93✔
3122
}
93✔
3123

3124

3125
/*
3126
 * If tt == true --> assert (x - y == 0)
3127
 * If tt == false --> assert (x - y != 0)
3128
 */
3129
void simplex_assert_vareq_axiom(simplex_solver_t *solver, thvar_t x, thvar_t y, bool tt) {
1,625✔
3130
  poly_buffer_t *b;
3131

3132
  assert(valid_arith_var(&solver->vtbl, x) && valid_arith_var(&solver->vtbl, y));
3133

3134
  b = &solver->buffer;
1,625✔
3135
  assert(poly_buffer_nterms(b) == 0);
3136
  add_var_or_subst(solver, b, x);
1,625✔
3137
  sub_var_or_subst(solver, b, y);
1,625✔
3138
  normalize_poly_buffer(b);
1,625✔
3139

3140
#if TRACE
3141
  printf("\n---> simplex_assert_vareq_axiom: ");
3142
  print_simplex_buffer(stdout, solver);
3143
  if (tt) {
3144
    printf(" == 0\n");
3145
  } else {
3146
    printf(" != 0\n");
3147
  }
3148
#endif
3149

3150
  add_eq_or_diseq_axiom(solver, tt);
1,625✔
3151
}
1,625✔
3152

3153

3154
/*
3155
 * Assert (c ==> x == y)
3156
 */
3157
void simplex_assert_cond_vareq_axiom(simplex_solver_t *solver, literal_t c, thvar_t x, thvar_t y) {
540✔
3158
  poly_buffer_t *b;
3159
  literal_t l, l1, l2;
3160

3161
  assert(valid_arith_var(&solver->vtbl, x) && valid_arith_var(&solver->vtbl, y));
3162

3163
  // compute polynomial p = (x - y)
3164
  b = &solver->buffer;
540✔
3165
  assert(poly_buffer_nterms(b) == 0);
3166
  add_var_or_subst(solver, b, x);
540✔
3167
  sub_var_or_subst(solver, b, y);
540✔
3168
  normalize_poly_buffer(b);
540✔
3169

3170
#if TRACE
3171
  printf("\n---> simplex_assert_cond_vareq_axiom: ");
3172
  print_literal(stdout, c);
3173
  printf(" implies ");
3174
  print_simplex_var(stdout, solver, x);
3175
  printf(" == ");
3176
  print_simplex_var(stdout, solver, y);
3177
  printf("\n");
3178
  printf("rewritten to: ");
3179
  print_literal(stdout, c);
3180
  printf(" implies ");
3181
  print_simplex_buffer(stdout, solver);
3182
  printf(" == 0\n");
3183
#endif
3184

3185
  l = simplify_eq_atom(solver, &l1, &l2);
540✔
3186
  if (l == null_literal) {
540✔
3187
    // l1 is (p >= 0) and l2 is (p <= 0)
3188
    // assert (c ==> l1) and (c ==> l2)
3189
    add_binary_clause(solver->core, not(c), l1);
540✔
3190
    add_binary_clause(solver->core, not(c), l2);
540✔
3191
  } else {
3192
    assert(l == false_literal || l == true_literal);
3193
    // if p == 0 is true, nothing to do
3194
    // if p == 0 is false, assert (not c)
3195
    if (l == false_literal) {
×
3196
      add_unit_clause(solver->core, not(c));
×
3197
    }
3198
  }
3199
}
540✔
3200

3201

3202

3203
/*
3204
 * Assert (c[0] \/ ... \/ c[n-1] \/ x == y)
3205
 */
3206
void simplex_assert_clause_vareq_axiom(simplex_solver_t *solver, uint32_t n, literal_t *c, thvar_t x, thvar_t y) {
5,876✔
3207
  poly_buffer_t *b;
3208
  ivector_t *v;
3209
  literal_t l, l1, l2;
3210

3211
  assert(valid_arith_var(&solver->vtbl, x) && valid_arith_var(&solver->vtbl, y));
3212

3213
  // compute polynomial p = (x - y)
3214
  b = &solver->buffer;
5,876✔
3215
  assert(poly_buffer_nterms(b) == 0);
3216
  add_var_or_subst(solver, b, x);
5,876✔
3217
  sub_var_or_subst(solver, b, y);
5,876✔
3218
  normalize_poly_buffer(b);
5,876✔
3219

3220
  l = simplify_eq_atom(solver, &l1, &l2);
5,876✔
3221
  if (l == null_literal) {
5,876✔
3222
    // l1 is (p >= 0) and l2 is (p <= 0)
3223
    // assert (c[0] \/ ... \/ c[n-1] \/ l1)
3224
    //    and (c[0] \/ ... \/ c[n-1] \/ l2)
3225

3226
    v = &solver->aux_vector;
5,876✔
3227
    assert(v->size == 0);
3228
    ivector_copy(v, c, n);
5,876✔
3229

3230
    assert(v->size == n);
3231
    ivector_push(v, l1);
5,876✔
3232
    add_clause(solver->core, n+1, v->data);
5,876✔
3233

3234
    v->data[n] = l2;
5,876✔
3235
    add_clause(solver->core, n+1, v->data);
5,876✔
3236

3237
    ivector_reset(v);
5,876✔
3238

3239
  } else {
3240
    assert(l == false_literal || l == true_literal);
3241
    // if p == 0 is true, nothing to do
3242
    // if p == 0 is false, assert (c[0] \/ ... \/ c[n-1])
3243
    if (l == false_literal) {
×
3244
      add_clause(solver->core, n, c);
×
3245
    }
3246
  }
3247
}
5,876✔
3248

3249

3250

3251
/*****************************************
3252
 *  SIMPLIFICATION/TABLEAU CONSTRUCTION  *
3253
 ****************************************/
3254

3255
/*
3256
 * Record the initial statistics
3257
 */
3258
static void simplex_set_initial_stats(simplex_solver_t *solver) {
13,178✔
3259
  solver->stats.num_init_vars = solver->vtbl.nvars;
13,178✔
3260
  solver->stats.num_init_rows = solver->matrix.nrows;
13,178✔
3261
  solver->stats.num_atoms = solver->atbl.natoms;
13,178✔
3262
}
13,178✔
3263

3264

3265
#if 0
3266
/*
3267
 * keep is a bitvector: mark all variables of p
3268
 */
3269
static void mark_vars_of_poly(byte_t *keep, polynomial_t *p) {
3270
  uint32_t i, n;
3271
  thvar_t x;
3272

3273
  n = p->nterms;
3274
  for (i=0; i<n; i++) {
3275
    x = p->mono[i].var;
3276
    if (x != const_idx) {
3277
      set_bit(keep, x);
3278
    }
3279
  }
3280
}
3281
#endif
3282

3283
/*
3284
 * Simplify the matrix
3285
 */
3286
static void simplex_simplify_matrix(simplex_solver_t *solver) {
13,178✔
3287
  uint32_t i, n;
3288
  arith_vartable_t *vtbl;
3289
  ivector_t *aux;
3290
  byte_t *keep;
3291
  byte_t *ivars;
3292

3293
#if TRACE_INIT
3294
  printf("\n**** SIMPLIFYING THE MATRIX ****\n\n");
3295
  print_simplex_matrix(stdout, solver);
3296
  printf("==== Simplex variables ====\n");
3297
  print_simplex_vars(stdout, solver);
3298
  printf("\n\n");
3299
#endif
3300

3301
  /*
3302
   * Mark the variables to keep
3303
   */
3304
  vtbl = &solver->vtbl;
13,178✔
3305
  n = solver->vtbl.nvars;
13,178✔
3306
  keep = allocate_bitvector0(n);  // default: all bits are 0
13,178✔
3307

3308
  if (solver->egraph != NULL && arith_vartable_has_eterms(vtbl)) {
13,178✔
3309
    /*
3310
     * We must keep at least any variable whose definition is the
3311
     * difference of two e-terms. More generally, we assume the egraph
3312
     * can dynamically create arbitrary linear combination of eterms.
3313
     *
3314
     * We could try to compute the set of variables whose definition
3315
     * is a linear combination of eterms. Instead we keep everything.
3316
     */
3317
    for (i=1; i<n; i++) {
13,381✔
3318
      set_bit(keep, i);
13,188✔
3319
    }
3320
  } else {
3321
    for (i=1; i<n; i++) { // skip the constant
36,905✔
3322
      if (!simplex_free_variable(solver, i) || arith_var_num_atoms(vtbl, i) > 0) {
23,920✔
3323
        // i is constrained or has atoms attached: keep it
3324
        set_bit(keep, i);
19,991✔
3325
      }
3326
    }
3327
  }
3328

3329
  /*
3330
   * Remove variables that have equal lower and upper bounds
3331
   * Collect the unconstrained variables in aux
3332
   */
3333
  aux = &solver->aux_vector;
13,178✔
3334
  assert(aux->size == 0);
3335
  matrix_collect_constants(&solver->matrix);
13,178✔
3336
  for (i=1; i<n; i++) { // skip const_idx == 0
50,286✔
3337
    if (simplex_fixed_variable(solver, i)) {
37,108✔
3338
#if TRACE_INIT
3339
      printf("---> eliminate fixed variable ");
3340
      print_simplex_var(stdout, solver, i);
3341
      printf("\n");
3342
#endif
3343
      matrix_eliminate_fixed_variable(&solver->matrix, i, fixed_variable_value(solver, i));
1,192✔
3344
    } else if (! tst_bit(keep, i)) {
35,916✔
3345
      // i may be eliminated
3346
      assert(simplex_eliminable_variable(solver, i));
3347
      ivector_push(aux, i);
3,929✔
3348
    }
3349
  }
3350
  matrix_cleanup_constants(&solver->matrix);
13,178✔
3351

3352
#if TRACE_INIT
3353
  printf("---> %"PRIu32" rows after elim fixed vars.\n", solver->matrix.nrows);
3354
  print_simplex_matrix(stdout, solver);
3355
#endif
3356

3357
  /*
3358
   * Eliminate unconstrained variables
3359
   * - eliminated rows of the form x := constant are stored in solver->fvars
3360
   * - other eliminated rows are stored in solver->elim
3361
   */
3362
  solver->stats.num_elim_candidates = aux->size;
13,178✔
3363
  ivars = get_integer_vars_vector(&solver->vtbl); // set of integer variables
13,178✔
3364
  simplify_matrix(&solver->matrix, aux->data, aux->size, ivars, &solver->elim, &solver->fvars);
13,178✔
3365

3366
  solver->stats.num_elim_rows = solver->elim.nrows;
13,178✔
3367
  solver->stats.num_simpl_fvars = solver->fvars.nvars;
13,178✔
3368
  solver->stats.num_simpl_rows = solver->matrix.nrows;
13,178✔
3369

3370
#if TRACE_INIT
3371
  printf("---> %"PRIu32" rows after gauss. elim.\n", solver->matrix.nrows);
3372
  printf("---> %"PRIu32" fixed variables detected\n\n", solver->fvars.nvars);
3373
  print_simplex_matrix(stdout, solver);
3374
  print_elim_matrix(stdout, &solver->vtbl, &solver->elim);
3375
  print_simplex_vars(stdout, solver);
3376
  printf("\n");
3377
  print_simplex_bounds(stdout, solver);
3378
  printf("\n");
3379
  fflush(stdout);
3380
#endif
3381

3382
  ivector_reset(aux);
13,178✔
3383

3384
  delete_bitvector(keep);
13,178✔
3385
  delete_bitvector(ivars);
13,178✔
3386
}
13,178✔
3387

3388

3389

3390
/*
3391
 * Compute the initial tableau
3392
 */
3393
static void simplex_init_tableau(simplex_solver_t *solver) {
13,178✔
3394
  assert(solver->matrix_ready);
3395

3396
  markowitz_tableau_construction(&solver->matrix, &solver->fvars);
13,178✔
3397
  solver->stats.num_rows = solver->matrix.nrows;
13,178✔
3398
  solver->stats.num_fixed_vars = solver->fvars.nvars;
13,178✔
3399

3400
#if TRACE_INIT
3401
  printf("---> %"PRIu32" rows in initial tableau\n", solver->matrix.nrows);
3402
  printf("---> %"PRIu32" fixed variables detected:\n\n", solver->fvars.nvars);
3403
  print_fixed_var_vector(stdout, &solver->vtbl, &solver->fvars);
3404
#endif
3405

3406
  // mark that the tableau is ready
3407
  solver->tableau_ready = true;
13,178✔
3408
  solver->matrix_ready = false;
13,178✔
3409

3410
  trace_printf(solver->core->trace, 12, "(initial tableau: %"PRIu32" rows, %"PRIu32" variables, %"PRIu32" atoms)\n",
13,178✔
3411
               solver->stats.num_rows, solver->vtbl.nvars, solver->atbl.natoms);
3412

3413
#if TRACE
3414
  printf("\n==== Variables ====\n");
3415
  print_simplex_vars(stdout, solver);
3416
  printf("\n==== Tableau ====\n");
3417
  print_simplex_matrix(stdout, solver);
3418
  printf("\n==== Bounds  ====\n");
3419
  print_simplex_bounds(stdout, solver);
3420
  printf("\n");
3421
  fflush(stdout);
3422
#endif
3423
}
13,178✔
3424

3425

3426
/*
3427
 * Check the fixed variable vector and set the bounds on fixed variables
3428
 * - also set the value of all fixed variables
3429
 * - set unsat_before_search true if there's a conflict
3430
 */
3431
static void simplex_check_fixed_vars(simplex_solver_t *solver) {
13,178✔
3432
  fvar_vector_t *v;
3433
  rational_t *a;
3434
  uint32_t i, n;
3435
  int32_t x;
3436

3437
  v = &solver->fvars;
13,178✔
3438
  n = v->nvars;
13,178✔
3439

3440
#if TRACE_INIT
3441
  if (n > 0) {
3442
    printf("\n---> CHECKING FIXED VARIABLES\n");
3443
  }
3444
#endif
3445

3446
  for (i=0; i<n; i++) {
13,713✔
3447
    x = v->fvar[i].var;
538✔
3448
    a = &v->fvar[i].value;
538✔
3449

3450
#if TRACE_INIT
3451
    printf("\n---> checking ");
3452
    print_simplex_var(stdout, solver, x);
3453
    printf(" == ");
3454
    q_print(stdout, a);
3455
    printf("\n");
3456
#endif
3457

3458
    assert(x >= 0);
3459

3460
    if (x == const_idx) {
538✔
3461
      assert(q_is_zero(a));
3462
      solver->unsat_before_search = true;
1✔
3463
      return;
1✔
3464
    }
3465

3466
    if (arith_var_is_int(&solver->vtbl, x) && ! q_is_integer(a)) {
537✔
3467
      solver->unsat_before_search = true;
2✔
3468
      return;
2✔
3469
    }
3470

3471
    add_lb_axiom(solver, x, a, false);
535✔
3472
    add_ub_axiom(solver, x, a, false);
535✔
3473
    xq_set_q(arith_var_value(&solver->vtbl, x), a);
535✔
3474
  }
3475
}
3476

3477

3478

3479

3480

3481

3482

3483

3484
/*************************
3485
 *  VARIABLE ASSIGNMENT  *
3486
 ************************/
3487

3488
/*
3489
 * Invariant we want to maintain:
3490
 * - for every non-basic variable x, val[x] is between the bounds on x
3491
 * - for every non-basic variable x, the lb and ub flags for x are correct
3492
 *   (lb_flag[x] = 1 iff val[x] = lower bound on x and
3493
 *    ub_flag[x] = 1 iff val[x] = upper bound on x)
3494
 * - the full assignment satisfies all the equations
3495
 * - the heap infeasible_vars contains every basic variable x whose
3496
 *   value is not within bounds.
3497
 *
3498
 * This invariant must hold before check_feasibility is called.
3499
 */
3500

3501
/*
3502
 * Set the ub/lb flags for a variable x
3503
 */
3504
static void simplex_set_bound_flags(simplex_solver_t *solver, thvar_t x) {
10,587✔
3505
  uint8_t t;
3506

3507
  t = arith_var_tag(&solver->vtbl, x);
10,587✔
3508
  t &= ~(AVARTAG_ATLB_MASK | AVARTAG_ATUB_MASK); // clear both bits
10,587✔
3509
  if (variable_at_lower_bound(solver, x)) {
10,587✔
3510
    t |= AVARTAG_ATLB_MASK;
2,910✔
3511
  }
3512
  if (variable_at_upper_bound(solver, x)) {
10,587✔
3513
    t |= AVARTAG_ATUB_MASK;
3,041✔
3514
  }
3515
  set_arith_var_tag(&solver->vtbl, x, t);
10,587✔
3516
}
10,587✔
3517

3518

3519
/*
3520
 * Clear both flags
3521
 */
3522
static void simplex_clear_bound_flags(simplex_solver_t *solver, thvar_t x) {
12,427✔
3523
  uint8_t t;
3524

3525
  assert(!variable_at_lower_bound(solver, x) && !variable_at_upper_bound(solver, x));
3526

3527
  t = arith_var_tag(&solver->vtbl, x);
12,427✔
3528
  t &= ~(AVARTAG_ATLB_MASK | AVARTAG_ATUB_MASK); // clear both bits
12,427✔
3529
  set_arith_var_tag(&solver->vtbl, x, t);
12,427✔
3530
}
12,427✔
3531

3532

3533
/*
3534
 * Compute the value of a basic variable x given a row
3535
 * - it's computed so as to satisfy the equation row == 0
3536
 * - store x in the heap if the bounds on x are not satisfied
3537
 */
3538
static void simplex_set_basic_var_value(simplex_solver_t *solver, thvar_t x, row_t *row) {
25,559✔
3539
  arith_vartable_t *vtbl;
3540
  xrational_t *v;
3541
  uint32_t i, n;
3542
  thvar_t y;
3543

3544
  vtbl = &solver->vtbl;
25,559✔
3545
  v = arith_var_value(vtbl, x);
25,559✔
3546
  xq_clear(v);
25,559✔
3547
  n = row->size;
25,559✔
3548
  for (i=0; i<n; i++) {
134,556✔
3549
    y = row->data[i].c_idx;
108,997✔
3550
    if (y >= 0 && y != x) {
108,997✔
3551
      /// monomial is a.y where a = data[i].coeff
3552
      xq_submul(v, arith_var_value(vtbl, y), &row->data[i].coeff);
77,031✔
3553
    }
3554
  }
3555

3556
  if (! value_satisfies_bounds(solver, x)) {
25,559✔
3557
#if TRACE_INIT
3558
    printf("---> infeasible var: ");
3559
    print_simplex_var(stdout, solver, x);
3560
    printf("\n");
3561
#endif
3562
    int_heap_add(&solver->infeasible_vars, x);
386✔
3563
  }
3564
}
25,559✔
3565

3566

3567
/*
3568
 * Initial variable assignment:
3569
 * - for every non-basic variable x:
3570
 *   val[x] = lower bound on x if it exists
3571
 *          or upper bound on x if it exists
3572
 *          or 0
3573
 * - for every basic variable, val[x] is computed from the matrix
3574
 */
3575
static void simplex_init_assignment(simplex_solver_t *solver) {
13,172✔
3576
  matrix_t *matrix;
3577
  arith_vartable_t *vtbl;
3578
  xrational_t *bound, *v;
3579
  uint32_t n;
3580
  int32_t i;
3581
  thvar_t x;
3582

3583
  assert(int_heap_is_empty(&solver->infeasible_vars));
3584

3585
  vtbl = &solver->vtbl;
13,172✔
3586
  matrix = &solver->matrix;
13,172✔
3587
  bound = solver->bstack.bound;
13,172✔
3588

3589
  // the constant should always have value = 1
3590
  assert(xq_is_one(arith_var_value(vtbl, const_idx)));
3591

3592
  // assign all non-basic/non-constant variables
3593
  n = vtbl->nvars;
13,172✔
3594
  for (x=1; x<n; x++) {
49,007✔
3595
    if (matrix_is_nonbasic_var(matrix, x)) {
35,835✔
3596
#if 0
3597
      i = arith_var_lower_index(vtbl, x);
3598
      if (i < 0) {
3599
        i = arith_var_upper_index(vtbl, x);
3600
      }
3601
#else
3602
      // test: give priority to upper bound
3603
      i = arith_var_upper_index(vtbl, x);
17,295✔
3604
      if (i < 0) {
17,295✔
3605
        i = arith_var_lower_index(vtbl, x);
14,255✔
3606
      }
3607
#endif
3608

3609
      v = arith_var_value(vtbl, x);
17,295✔
3610
      if (i >= 0) {
17,295✔
3611
        xq_set(v, bound + i);
4,868✔
3612
        simplex_set_bound_flags(solver, x);
4,868✔
3613
      } else {
3614
        // we must clear the tags here (because they could be wrong after pop)
3615
        xq_clear(v);
12,427✔
3616
        simplex_clear_bound_flags(solver, x);
12,427✔
3617
      }
3618
    }
3619
  }
3620

3621
  // propagate to the basic variables
3622
  n = matrix->nrows;
13,172✔
3623
  for (i=0; i<n; i++) {
31,712✔
3624
    x = matrix_basic_var(matrix, i);
18,540✔
3625
    simplex_set_basic_var_value(solver, x, matrix_row(matrix, i));
18,540✔
3626
  }
3627

3628
  // set the fix_ptr
3629
  solver->bstack.fix_ptr = solver->bstack.top;
13,172✔
3630
}
13,172✔
3631

3632

3633

3634
/*
3635
 * Update the value of a non-basic variable x and propagate
3636
 * to all basic variables that depend on x
3637
 * - q = new value of x
3638
 * - if a basic variable becomes infeasible, it's added to the heap
3639
 */
3640
static void update_non_basic_var_value(simplex_solver_t *solver, thvar_t x, xrational_t *q) {
334,809✔
3641
  arith_vartable_t *vtbl;
3642
  matrix_t *matrix;
3643
  xrational_t *v, *delta;
3644
  column_t *col;
3645
  uint32_t i, n;
3646
  int32_t r, k;
3647
  thvar_t y;
3648

3649
  vtbl = &solver->vtbl;
334,809✔
3650
  delta = &solver->delta;
334,809✔
3651
  v = arith_var_value(vtbl, x);  // current value of x
334,809✔
3652

3653
  assert(delta != q);
3654

3655
  xq_set(delta, q);
334,809✔
3656
  xq_sub(delta, v);   // delta = new value - old value
334,809✔
3657
  xq_set(v, q);       // value[x] := q
334,809✔
3658

3659
  matrix = &solver->matrix;
334,809✔
3660
  col = matrix->column[x];
334,809✔
3661

3662
  if (col != NULL) {
334,809✔
3663
    n = col->size;
329,474✔
3664
    for (i=0; i<n; i++) {
12,549,610✔
3665
      r = col->data[i].r_idx;
12,220,136✔
3666
      if (r >= 0) {
12,220,136✔
3667
        y = matrix_basic_var(matrix, r);
10,660,920✔
3668
        v = arith_var_value(vtbl, y);
10,660,920✔
3669
        k = col->data[i].r_ptr;
10,660,920✔
3670
        xq_submul(v, delta, matrix_coeff(matrix, r, k));
10,660,920✔
3671

3672
        // add y to the heap if the new value is not within its bounds
3673
        if (! value_within_bounds(solver, y, v)) {
10,660,920✔
3674
          int_heap_add(&solver->infeasible_vars, y);
499,470✔
3675
        }
3676
      }
3677
    }
3678
  }
3679
}
334,809✔
3680

3681

3682

3683
/*
3684
 * Update the value of non-basic var x to its lower or upper bound
3685
 */
3686
static void update_to_lower_bound(simplex_solver_t *solver, thvar_t x) {
244,990✔
3687
  int32_t k;
3688

3689
  assert(matrix_is_nonbasic_var(&solver->matrix, x));
3690
  k = arith_var_lower_index(&solver->vtbl, x);
244,990✔
3691
  assert(k >= 0);
3692
  update_non_basic_var_value(solver, x, solver->bstack.bound + k);
244,990✔
3693
  set_arith_var_lb(&solver->vtbl, x);
244,990✔
3694
  if (variable_at_upper_bound(solver, x)) {
244,990✔
3695
    set_arith_var_ub(&solver->vtbl, x);
38,731✔
3696
  } else {
3697
    clear_arith_var_ub(&solver->vtbl, x);
206,259✔
3698
  }
3699
}
244,990✔
3700

3701
static void update_to_upper_bound(simplex_solver_t *solver, thvar_t x) {
89,703✔
3702
  int32_t k;
3703

3704
  assert(matrix_is_nonbasic_var(&solver->matrix, x));
3705
  k = arith_var_upper_index(&solver->vtbl, x);
89,703✔
3706
  assert(k >= 0);
3707
  update_non_basic_var_value(solver, x, solver->bstack.bound + k);
89,703✔
3708
  set_arith_var_ub(&solver->vtbl, x);
89,703✔
3709
  if (variable_at_lower_bound(solver, x)) {
89,703✔
3710
    set_arith_var_lb(&solver->vtbl, x);
42,199✔
3711
  } else {
3712
    clear_arith_var_lb(&solver->vtbl, x);
47,504✔
3713
  }
3714
}
89,703✔
3715

3716

3717

3718
/*
3719
 * Update the variable assignment after new bounds have been added
3720
 * - the new bounds are in bstack queue (in bstack->bound[fix_ptr to top-1])
3721
 * - the assignment is updated to make sure that the value of all
3722
 *   non-basic variables is between their bounds
3723
 * - also add all basic variables that are not within their bounds to the
3724
 *   infeasible_vars heap
3725
 */
3726
static void simplex_fix_nonbasic_assignment(simplex_solver_t *solver) {
554,496✔
3727
  arith_bstack_t *bstack;
3728
  arith_vartable_t *vtbl;
3729
  matrix_t *matrix;
3730
  uint32_t i, n;
3731
  int32_t cmp;
3732
  thvar_t x;
3733

3734
#if TRACE
3735
  printf("---> Simplex: update non-basic assignment\n");
3736
#endif
3737

3738

3739
  bstack = &solver->bstack;
554,496✔
3740
  vtbl = &solver->vtbl;
554,496✔
3741
  matrix = &solver->matrix;
554,496✔
3742

3743
  n = bstack->top;
554,496✔
3744
  for (i = bstack->fix_ptr; i<n; i++) {
2,373,598✔
3745
    x = bstack->var[i];
1,819,102✔
3746
    if (constraint_is_lower_bound(bstack, i) && arith_var_lower_index(vtbl, x) == i) {
1,819,102✔
3747
      /*
3748
       * i is the current lower bound on x
3749
       */
3750
      cmp = xq_cmp(arith_var_value(vtbl, x), bstack->bound + i);
817,498✔
3751
      if (cmp < 0) {
817,498✔
3752
        // value < lower-bound
3753
        if (matrix_is_nonbasic_var(matrix, x)) {
84,869✔
3754
          // x is non-basic: correct its value
3755
          update_to_lower_bound(solver, x);
25,546✔
3756
#if TRACE
3757
          printf("     val[");
3758
          print_simplex_var(stdout, solver, x);
3759
          printf("] := ");
3760
          xq_print(stdout, arith_var_value(vtbl, x));
3761
          printf("\n");
3762
#endif
3763
        } else {
3764
          // x is basic: add it to the heap
3765
          int_heap_add(&solver->infeasible_vars, x);
59,323✔
3766
        }
3767

3768
      } else if (cmp == 0) {
732,629✔
3769
        // value == lower-bound: set the lower-bound flag on x
3770
        // this is required for non-basic vars and irrelevant for basic vars
3771
        set_arith_var_lb(vtbl, x);
486,374✔
3772
      }
3773

3774
    } else if (constraint_is_upper_bound(bstack, i) && arith_var_upper_index(vtbl, x) == i) {
1,001,604✔
3775
      /*
3776
       * i is the current upper bound on x
3777
       */
3778
      cmp = xq_cmp(arith_var_value(vtbl, x), bstack->bound + i);
834,589✔
3779
      if (cmp > 0) {
834,589✔
3780
        // value > upper bound
3781
        if (matrix_is_nonbasic_var(matrix, x)) {
96,388✔
3782
          // correct x's value
3783
          update_to_upper_bound(solver, x);
23,858✔
3784
#if TRACE
3785
          printf("     val[");
3786
          print_simplex_var(stdout, solver, x);
3787
          printf("] := ");
3788
          xq_print(stdout, arith_var_value(vtbl, x));
3789
          printf("\n");
3790
#endif
3791
        } else {
3792
          // x is basic: add it to the heap
3793
          int_heap_add(&solver->infeasible_vars, x);
72,530✔
3794
        }
3795
      } else if (cmp == 0) {
738,201✔
3796
        // value == upper bound: set the upper-bound flag on x
3797
        set_arith_var_ub(vtbl, x);
508,881✔
3798
      }
3799
    }
3800
  }
3801

3802
  // update fix_ptr
3803
  bstack->fix_ptr = n;
554,496✔
3804
  assert(bstack->fix_ptr == bstack->top);
3805
}
554,496✔
3806

3807

3808

3809

3810
/***************************************
3811
 *  CONFLICTS: SETS OF BOUND INDICES   *
3812
 **************************************/
3813

3814
/*
3815
 * A conflict is a set of bounds that are mutually inconsistent.
3816
 * The following functions builds a set of bounds in a vector.
3817
 * In addition, every bound is marked by setting a bit in  the bound stack
3818
 * for index k.
3819
 */
3820

3821
/*
3822
 * Check whether constraint k is marked
3823
 */
3824
static inline bool arith_cnstr_is_marked(arith_bstack_t *stack, int32_t k) {
813,941✔
3825
  assert(0 <= k && k < stack->top);
3826
  return arith_tag_mark(stack->tag[k]);
813,941✔
3827
}
3828

3829
/*
3830
 * Set the mark on constraint k
3831
 */
3832
static inline void arith_cnstr_set_mark(arith_bstack_t *stack, int32_t k) {
749,779✔
3833
  assert(0 <= k && k < stack->top);
3834
  stack->tag[k] |= ARITH_CNSTR_MARK_MASK;
749,779✔
3835
}
749,779✔
3836

3837
/*
3838
 * Clear the mark on constraint k
3839
 */
3840
static inline void arith_cnstr_clr_mark(arith_bstack_t *stack, int32_t k) {
749,779✔
3841
  assert(0 <= k && k < stack->top);
3842
  stack->tag[k] &= ~ARITH_CNSTR_MARK_MASK;
749,779✔
3843
}
749,779✔
3844

3845

3846
/*
3847
 * Add index k into the explanation queue q if it's not there already
3848
 * - all indices in the queue have a mark in stack
3849
 */
3850
static void enqueue_cnstr_index(ivector_t *q, int32_t k, arith_bstack_t *stack) {
813,941✔
3851
  if (! arith_cnstr_is_marked(stack, k)) {
813,941✔
3852
    ivector_push(q, k);
749,779✔
3853
    arith_cnstr_set_mark(stack, k);
749,779✔
3854
  }
3855
}
813,941✔
3856

3857

3858
/*
3859
 * Enqueue all the elements of array a into q
3860
 * - a must be an array of bound indices, terminated by -1
3861
 */
3862
static void enqueue_cnstr_array_indices(ivector_t *q, int32_t *a, arith_bstack_t *stack) {
119,361✔
3863
  int32_t i;
3864

3865
  for (;;) {
3866
    i = *a ++;
119,361✔
3867
    if (i < 0) break;
119,361✔
3868
    enqueue_cnstr_index(q, i, stack);
108,726✔
3869
  }
3870
}
10,635✔
3871

3872

3873

3874

3875
/***********************
3876
 *  FEASIBILITY CHECK  *
3877
 **********************/
3878

3879
/*
3880
 * Heuristic for selecting the entering variable:
3881
 * - score of x = number of non-free basic variables that depend on x
3882
 *    +  1 if x is not free
3883
 *   (a variable is free if it has no upper or lower bound)
3884
 * - the variable with smallest score is selected, ties are broken randomly
3885
 *
3886
 * The following function returns the score of x if it's smaller than best_score
3887
 * or best_score + 1 otherwise.
3888
 */
3889
static uint32_t entering_var_score(simplex_solver_t *solver, thvar_t x, uint32_t best_score) {
1,409,786✔
3890
  matrix_t *matrix;
3891
  column_t *col;
3892
  uint32_t i, n, score;
3893
  int32_t r;
3894
  thvar_t y;
3895

3896
  assert(0 <= x && x < solver->matrix.ncolumns &&
3897
         x != const_idx && matrix_is_nonbasic_var(&solver->matrix, x));
3898

3899
  score = 0;
1,409,786✔
3900
  if (! simplex_free_variable(solver, x)) {
1,409,786✔
3901
    score ++;
832,160✔
3902
    if (best_score == 0) goto done;
832,160✔
3903
  }
3904

3905
  matrix = &solver->matrix;
1,409,786✔
3906
  col = matrix->column[x];
1,409,786✔
3907
  n = col->size;
1,409,786✔
3908
  for (i=0; i<n; i++) {
59,907,852✔
3909
    r = col->data[i].r_idx;
59,514,519✔
3910
    if (r >= 0) {
59,514,519✔
3911
      y = matrix_basic_var(matrix, r);
34,763,531✔
3912
      assert(y >= 0);
3913
      if (! simplex_free_variable(solver, y)) {
34,763,531✔
3914
        score ++;
10,112,566✔
3915
        if (score > best_score) goto done;
10,112,566✔
3916
      }
3917
    }
3918
  }
3919

3920
 done:
393,333✔
3921
  return score;
1,409,786✔
3922
}
3923

3924

3925

3926
/*
3927
 * Search for entering variable in a given row:
3928
 * - x = basic variable in that row
3929
 * - return the index of the chosen variable in the row
3930
 *   or -1 if no variable was found
3931
 *
3932
 * There are two cases depending on whether the value of the
3933
 * basic variable x must increase or decrease:
3934
 * - if x must increase, the entering variable x_i must satisfy
3935
 *    (a_i > 0 and value[x_i] > l_i) or (a_i < 0 and value[x_i] < u_i)
3936
 * - if x must decrease, the entering variable x_i must satisfy
3937
 *    (a_i < 0 and value[x_i] > l_i) or (a_i > 0 and value[x_i] > u_i)
3938
 * where a_i = coefficient of x_i in the row
3939
 *
3940
 * If blands_rule is active, the entering variable is the one with smallest index,
3941
 * otherwise, it's the one with smallest score.
3942
 */
3943

3944

3945
/*
3946
 * Check whether y can be selected as entering variable when x must increase
3947
 * - a = coefficient of y
3948
 */
3949
static bool possible_entering_var_for_increase(arith_vartable_t *vtbl, thvar_t y, rational_t *a) {
8,246,533✔
3950
  uint8_t tag;
3951

3952
  assert(q_is_nonzero(a));
3953

3954
  tag = arith_var_tag(vtbl, y);
8,246,533✔
3955
  if (q_is_pos(a)) {
8,246,533✔
3956
    // a>0 and value[y] > lower bound on y
3957
    return (tag & AVARTAG_ATLB_MASK) == 0;
4,169,327✔
3958
  } else {
3959
    // a<0 and value[y] < upper bound on y
3960
    return (tag & AVARTAG_ATUB_MASK) == 0;
4,077,206✔
3961
  }
3962
}
3963

3964

3965
/*
3966
 * Search for an entering variable to increase x
3967
 */
3968
static int32_t find_entering_var_for_increase(simplex_solver_t *solver, row_t *row, thvar_t x) {
232,326✔
3969
  arith_vartable_t *vtbl;
3970
  uint32_t i, n;
3971
  thvar_t y;
3972
  uint32_t score, best_score, k;
3973
  int32_t best_i;
3974

3975
  vtbl = &solver->vtbl;
232,326✔
3976

3977
  n = row->size;
232,326✔
3978

3979
  best_i = -1;
232,326✔
3980
  best_score = UINT32_MAX;
232,326✔
3981

3982
  if (solver->use_blands_rule) {
232,326✔
3983

3984
    // Bland's rule: score for y = y
3985
    for (i=0; i<n; i++) {
822✔
3986
      y = row->data[i].c_idx;
792✔
3987
      if (y >= 0 && y != x && y < best_score &&
1,120✔
3988
          possible_entering_var_for_increase(vtbl, y, &row->data[i].coeff)) {
328✔
3989
        best_score = y;
57✔
3990
        best_i = i;
57✔
3991
      }
3992
    }
3993

3994
  } else {
3995

3996
    k = 0; // stop GCC warning
232,296✔
3997

3998
    // Leonardo's heuristic
3999
    for (i=0; i<n; i++) {
10,281,574✔
4000
      y = row->data[i].c_idx;
10,049,278✔
4001
      if (y >= 0 && y != x &&
18,295,483✔
4002
          possible_entering_var_for_increase(vtbl, y, &row->data[i].coeff)) {
8,246,205✔
4003
        score = entering_var_score(solver, y, best_score);
1,203,646✔
4004

4005
        if (score < best_score) {
1,203,646✔
4006
          // better variable
4007
          best_score = score;
249,375✔
4008
          best_i = i;
249,375✔
4009
          k = 1;
249,375✔
4010
        } else if (score == best_score) {
954,271✔
4011
          // pick uniformly among all variables with the same score
4012
          k ++;
29,212✔
4013
          if (random_uint(solver, k) == 0) {
29,212✔
4014
            best_i = i;
10,115✔
4015
          }
4016
        }
4017

4018
      }
4019
    }
4020
  }
4021

4022
  assert(best_score < UINT32_MAX || best_i < 0);
4023

4024
  return best_i;
232,326✔
4025
}
4026

4027

4028
/*
4029
 * Check whether y can be selected as entering variable when x must decrease
4030
 * - a = coefficient of y
4031
 */
4032
static bool possible_entering_var_for_decrease(arith_vartable_t *vtbl, thvar_t y, rational_t *a) {
1,763,305✔
4033
  uint8_t tag;
4034

4035
  assert(q_is_nonzero(a));
4036

4037
  tag = arith_var_tag(vtbl, y);
1,763,305✔
4038
  if (q_is_neg(a)) {
1,763,305✔
4039
    // a<0 and value[y] > lower bound on y
4040
    return (tag & AVARTAG_ATLB_MASK) == 0;
915,462✔
4041
  } else {
4042
    // a>0 and value[y] < upper bound on y
4043
    return (tag & AVARTAG_ATUB_MASK) == 0;
847,843✔
4044
  }
4045
}
4046

4047

4048
/*
4049
 * Search for an entering variable to decrease x
4050
 */
4051
static int32_t find_entering_var_for_decrease(simplex_solver_t *solver, row_t *row, thvar_t x) {
80,343✔
4052
  arith_vartable_t *vtbl;
4053
  uint32_t i, n;
4054
  thvar_t y;
4055
  uint32_t score, best_score, k;
4056
  int32_t best_i;
4057

4058
  vtbl = &solver->vtbl;
80,343✔
4059

4060
  n = row->size;
80,343✔
4061

4062
  best_i = -1;
80,343✔
4063
  best_score = UINT32_MAX;
80,343✔
4064

4065
  if (solver->use_blands_rule) {
80,343✔
4066

4067
    // Bland's rule: score for y = y
4068
    for (i=0; i<n; i++) {
2,032✔
4069
      y = row->data[i].c_idx;
1,958✔
4070
      if (y >= 0 && y != x && y < best_score &&
2,771✔
4071
          possible_entering_var_for_decrease(vtbl, y, &row->data[i].coeff)) {
813✔
4072
        best_score = y;
171✔
4073
        best_i = i;
171✔
4074
      }
4075
    }
4076

4077
  } else {
4078

4079
    k = 0; // stop GCC warning
80,269✔
4080

4081
    // Leonardo's heuristic
4082
    for (i=0; i<n; i++) {
2,274,347✔
4083
      y = row->data[i].c_idx;
2,194,078✔
4084
      if (y >= 0 && y != x &&
3,956,570✔
4085
          possible_entering_var_for_decrease(vtbl, y, &row->data[i].coeff)) {
1,762,492✔
4086
        score = entering_var_score(solver, y, best_score);
206,140✔
4087

4088
        if (score < best_score) {
206,140✔
4089
          // better variable
4090
          best_score = score;
91,715✔
4091
          best_i = i;
91,715✔
4092
          k = 1;
91,715✔
4093
        } else if (score == best_score) {
114,425✔
4094
          // pick uniformly among all variables with the same score
4095
          k ++;
23,031✔
4096
          if (random_uint(solver, k) == 0) {
23,031✔
4097
            best_i = i;
7,645✔
4098
          }
4099
        }
4100

4101
      }
4102
    }
4103
  }
4104

4105
  assert(best_score < UINT32_MAX || best_i < 0);
4106

4107
  return best_i;
80,343✔
4108
}
4109

4110

4111
/*
4112
 * Generate a conflict set for an infeasible row:
4113
 * - x is the base variable in that row.
4114
 * - x's value is smaller than x's lower bound.
4115
 * - there are no entering variable in the row.
4116
 *
4117
 * Collect the bound indices from this row into solver->expl_queue + set marks.
4118
 */
4119
static void conflict_set_for_increase(simplex_solver_t *solver, row_t *row, thvar_t x) {
12,882✔
4120
  arith_vartable_t *vtbl;
4121
  ivector_t *v;
4122
  thvar_t y;
4123
  uint32_t i, n;
4124
  int32_t k;
4125

4126
  vtbl = &solver->vtbl;
12,882✔
4127

4128
  // add bound indices to the explanation queue
4129
  v = &solver->expl_queue;
12,882✔
4130
  assert(v->size == 0);
4131

4132
  n = row->size;
12,882✔
4133
  for (i=0; i<n; i++) {
370,490✔
4134
    y = row->data[i].c_idx;
357,608✔
4135
    if (y >= 0 && y != x) {
357,608✔
4136
      if (q_is_pos(&row->data[i].coeff)) {
292,530✔
4137
        // a>0: we need the explanation for the lower bound on y
4138
        k = arith_var_lower_index(vtbl, y);
153,610✔
4139
      } else {
4140
        // a<0: we need the explanation for the upper bound on y
4141
        k = arith_var_upper_index(vtbl, y);
138,920✔
4142
      }
4143
      enqueue_cnstr_index(v, k, &solver->bstack);
292,530✔
4144
    }
4145
  }
4146

4147
  // add index for (x >= l)
4148
  enqueue_cnstr_index(v, arith_var_lower_index(vtbl, x), &solver->bstack);
12,882✔
4149
}
12,882✔
4150

4151

4152
/*
4153
 * Same thing for the other case (can't decrease the value of x)
4154
 * - x is the base variable in that row.
4155
 * - x's value is smaller than x's lower bound.
4156
 * - there are no entering variable in the row.
4157
 *
4158
 * Collect the bound indices from this row into solver->expl_queue + set marks.
4159
 */
4160
static void conflict_set_for_decrease(simplex_solver_t *solver, row_t *row, thvar_t x) {
14,498✔
4161
  arith_vartable_t *vtbl;
4162
  ivector_t *v;
4163
  thvar_t y;
4164
  uint32_t i, n;
4165
  int32_t k;
4166

4167
  vtbl = &solver->vtbl;
14,498✔
4168

4169
  // add bound indices to expl_queue
4170
  v = &solver->expl_queue;
14,498✔
4171
  assert(v->size == 0);
4172

4173
  n = row->size;
14,498✔
4174
  for (i=0; i<n; i++) {
436,631✔
4175
    y = row->data[i].c_idx;
422,133✔
4176
    if (y >= 0 && y != x) {
422,133✔
4177
      if (q_is_pos(&row->data[i].coeff)) {
343,804✔
4178
        // a>0: we need the explanation for the upper bound on y
4179
        k = arith_var_upper_index(vtbl, y);
165,728✔
4180
      } else {
4181
        // a<0: we need the explanation for the lower bound on y
4182
        k = arith_var_lower_index(vtbl, y);
178,076✔
4183
      }
4184
      enqueue_cnstr_index(v, k, &solver->bstack);
343,804✔
4185
    }
4186
  }
4187

4188
  // bounds contradict (x <= u)
4189
  enqueue_cnstr_index(v, arith_var_upper_index(vtbl, x), &solver->bstack);
14,498✔
4190
}
14,498✔
4191

4192

4193
/*
4194
 * Check for feasibility:
4195
 * - search for an assignment that satisfies all the bounds
4196
 * - return true if such an assignment is found
4197
 * - return false if a conflict is detected
4198
 *
4199
 * Preconditions/invariant:
4200
 * - the infeasible basic variables are stored in solver->infeasible_vars
4201
 * - for every non-basic variable x, val[x] is between the bounds on x
4202
 * - for every non-basic variable x, the lb and ub flags for x are correct
4203
 *   (lb_flag[x] = 1 iff val[x] = lower bound on x and
4204
 *    ub_flag[x] = 1 iff val[x] = upper bound on x)
4205
 *
4206
 * This invariant is maintained by this function.
4207
 *
4208
 * Result:
4209
 * - if the function returns true, then the array val contains an assignment
4210
 *   that satisfies all constraints. The heap solver->infeasible_vars is empty.
4211
 * - if the function returns false, then invariant above is still satisfied
4212
 *   in addition, a conflict set is stored in solver->expl_queue and every
4213
 *   bound index is solver->expl_queue is marked.
4214
 */
4215
static bool simplex_check_feasibility(simplex_solver_t *solver) {
569,056✔
4216
  matrix_t *matrix;
4217
  arith_vartable_t *vtbl;
4218
  ivector_t *leaving_vars;
4219
  row_t *row;
4220
  thvar_t x;
4221
  int32_t r, k;
4222
  uint32_t repeats, loops, bthreshold;
4223
  bool feasible;
4224

4225
#if TRACE
4226
  printf("---> SIMPLEX: CHECK FEASIBILITY\n");
4227
#endif
4228

4229
  matrix = &solver->matrix;
569,056✔
4230
  vtbl = &solver->vtbl;
569,056✔
4231

4232
  /*
4233
   * leaving variables are stored in aux_vector
4234
   * and marked in vtbl
4235
   */
4236
  leaving_vars = &solver->aux_vector;
569,056✔
4237
  assert(leaving_vars->size == 0);
4238
  repeats = 0;
569,056✔
4239
  solver->use_blands_rule = false;
569,056✔
4240
  loops = 0;
569,056✔
4241

4242
  /*
4243
   * Bland threshold: adjust it based on the number of variables
4244
   */
4245
  bthreshold = solver->bland_threshold;
569,056✔
4246
  if (solver->vtbl.nvars > 10000) {
569,056✔
4247
    bthreshold *= 1000;
×
4248
  } else if (solver->vtbl.nvars > 1000) {
569,056✔
4249
    bthreshold *= 100;
185,819✔
4250
  }
4251

4252
  for (;;) {
4253
    // check interrupt at every iteration
4254
    if (solver->interrupted) {
1,017,574✔
4255
      feasible = false;
×
4256
      break;
×
4257
    }
4258

4259
    if (tracing(solver->core->trace, 15)) {
1,017,574✔
4260
      loops ++;
×
4261
      if ((loops & 0xFFF) == 0) {
×
4262
        trace_puts(solver->core->trace, 15, ".");
×
4263
      }
4264
    }
4265

4266
    x = int_heap_get_min(&solver->infeasible_vars);
1,017,574✔
4267
    if (x < 0) {
1,017,574✔
4268
      feasible = true;
541,676✔
4269
      break;
541,676✔
4270
    }
4271

4272
#if TRACE
4273
    show_heap(stdout, solver);
4274
#endif
4275

4276
    r = matrix_basic_row(matrix, x);
475,898✔
4277
    row = matrix_row(matrix, r);
475,898✔
4278
    k = -1;
475,898✔
4279

4280
    if (variable_below_lower_bound(solver, x)) {
475,898✔
4281
      // find an entering variable that allows x to increase
4282
      k = find_entering_var_for_increase(solver, row, x);
232,326✔
4283
      if (k < 0) {
232,326✔
4284
        // no entering variable ==> conflict
4285
        conflict_set_for_increase(solver, row, x);
12,882✔
4286
        int_heap_add(&solver->infeasible_vars, x); // x is still infeasible
12,882✔
4287
        feasible = false;
12,882✔
4288
        solver->last_conflict_row = r;
12,882✔
4289
        break;
12,882✔
4290
      } else {
4291
        // pivot: make the entering variable basic
4292
        matrix_pivot(matrix, r, k);
219,444✔
4293
        update_to_lower_bound(solver, x);
219,444✔
4294
        solver->stats.num_pivots ++;
219,444✔
4295
      }
4296

4297
    } else if (variable_above_upper_bound(solver, x)) {
243,572✔
4298
      // find an entering variable that allows x to decrease
4299
      k = find_entering_var_for_decrease(solver, row, x);
80,343✔
4300
      if (k < 0) {
80,343✔
4301
        // no entering variable ==> conflict
4302
        conflict_set_for_decrease(solver, row, x);
14,498✔
4303
        int_heap_add(&solver->infeasible_vars, x); // x is still infeasible
14,498✔
4304
        feasible = false;
14,498✔
4305
        solver->last_conflict_row = r;
14,498✔
4306
        break;
14,498✔
4307
      } else {
4308
        // pivot: make the entering variable basic
4309
        matrix_pivot(matrix, r, k);
65,845✔
4310
        update_to_upper_bound(solver, x);
65,845✔
4311
        solver->stats.num_pivots ++;
65,845✔
4312
      }
4313
    }
4314

4315
    if (k >= 0 && !solver->use_blands_rule) {
448,518✔
4316
      /*
4317
       * Switch to Bland's rule after too many repeats
4318
       * - repeat is incremented if x has left the basis in a previous
4319
       *   pivoting round
4320
       */
4321
      if (! arith_var_is_marked(vtbl, x)) {
285,187✔
4322
        set_arith_var_mark(vtbl, x);
278,331✔
4323
        ivector_push(leaving_vars, x);
278,331✔
4324
      } else {
4325
        repeats ++;
6,856✔
4326
        if (repeats > bthreshold) {
6,856✔
4327
          solver->use_blands_rule = true;
3✔
4328
          solver->stats.num_blands ++;
3✔
4329
          trace_printf(solver->core->trace, 15, "(activating bland's rule: %"PRIu32")\n", solver->stats.num_blands);
3✔
4330
        }
4331
      }
4332
    }
4333
  }
4334

4335
  // cleanup the marks
4336
  r = leaving_vars->size;
569,056✔
4337
  for (k=0; k<r; k++) {
847,387✔
4338
    x = leaving_vars->data[k];
278,331✔
4339
    clear_arith_var_mark(vtbl, x);
278,331✔
4340
  }
4341
  ivector_reset(leaving_vars);
569,056✔
4342

4343
  if (tracing(solver->core->trace, 15)) {
569,056✔
4344
    if (loops > 0xFFF || solver->use_blands_rule) {
×
4345
      trace_newline(solver->core->trace, 15);
×
4346
    }
4347
  }
4348

4349
#if TRACE
4350
  if (feasible) {
4351
    printf("---> Simplex: make feasible succeeded\n");
4352
  } else {
4353
    printf("---> Simplex: arithmetic conflict\n");
4354
  }
4355
#endif
4356

4357
  return feasible;
569,056✔
4358
}
4359

4360

4361

4362

4363

4364
/******************
4365
 *  EXPLANATIONS  *
4366
 *****************/
4367

4368
/*
4369
 * Add the explanation for (x1 == x2) to vector v
4370
 * then remove duplicate literals from v.
4371
 * - triple->var[0] = x1
4372
 * - triple->var[1] = x2
4373
 * - triple->id = egraph edge to explain the equality
4374
 */
4375
static void collect_egraph_eq_expl(simplex_solver_t *solver, egraph_expl_triple_t *triple, ivector_t *v) {
13,378✔
4376
  eterm_t t1, t2;
4377
  uint32_t n;
4378

4379
  t1 = arith_var_eterm(&solver->vtbl, triple->var[0]);
13,378✔
4380
  t2 = arith_var_eterm(&solver->vtbl, triple->var[1]);
13,378✔
4381
  n = v->size;
13,378✔
4382
  egraph_explain_term_eq(solver->egraph, t1, t2, triple->id, v);
13,378✔
4383
  if (n > 0) {
13,378✔
4384
    ivector_remove_duplicates(v);
8,557✔
4385
  }
4386
}
13,378✔
4387

4388

4389
/*
4390
 * Expand the explanation queue: convert it to a conjunction of literals
4391
 * - solver->expl_queue must contain a set of constraint indices
4392
 * - a list of literals that explain all these constraints is added to v
4393
 * - the conflict set is emptied: expl_queue is reset and all bound marks are removed.
4394
 *
4395
 * NOTE: We assume that egraph explanations and simplex explanations
4396
 * never have common literals. This is true as long as the simplex
4397
 * does not propagate equalities to the egraph.
4398
 */
4399
static void simplex_build_explanation(simplex_solver_t *solver, ivector_t *v) {
31,778✔
4400
  arith_bstack_t *bstack;
4401
  ivector_t *queue, *aux;
4402
  uint8_t *tag;
4403
  uint32_t k;
4404
  int32_t i;
4405

4406
  queue = &solver->expl_queue;
31,778✔
4407
  aux = &solver->expl_aux;  // to store literals from egraph explanations
31,778✔
4408
  bstack = &solver->bstack;
31,778✔
4409
  tag = bstack->tag;
31,778✔
4410

4411
  assert(queue != v && aux->size == 0);
4412

4413
  for (k=0; k<queue->size; k++) {
756,108✔
4414
    i = queue->data[k];
724,330✔
4415
    assert(arith_cnstr_is_marked(bstack, i));
4416
    switch (arith_tag(tag[i])) {
724,330✔
4417
    case ARITH_AXIOM_LB:
78,212✔
4418
    case ARITH_AXIOM_UB:
4419
      // nothing to do
4420
      break;
78,212✔
4421

4422
    case ARITH_ASSERTED_LB:
623,546✔
4423
    case ARITH_ASSERTED_UB:
4424
      // add literal explanation to v
4425
      ivector_push(v, bstack->expl[i].lit);
623,546✔
4426
      break;
623,546✔
4427

4428
    case ARITH_DERIVED_LB:
9,194✔
4429
    case ARITH_DERIVED_UB:
4430
      // add antecedents to the queue
4431
      enqueue_cnstr_array_indices(queue, bstack->expl[i].ptr, bstack);
9,194✔
4432
      solver->stats.num_prop_expl ++;
9,194✔
4433
      break;
9,194✔
4434

4435
    case ARITH_EGRAPHEQ_LB:
13,378✔
4436
    case ARITH_EGRAPHEQ_UB:
4437
      // add explanation from the egraph into aux
4438
      collect_egraph_eq_expl(solver, bstack->expl[i].ptr, aux);
13,378✔
4439
      break;
13,378✔
4440

4441
    default:
×
4442
      abort();
×
4443
      break;
4444
    }
4445
  }
4446

4447

4448
  // add literals of aux into v
4449
  ivector_add(v, aux->data, aux->size);
31,778✔
4450
  ivector_reset(aux);
31,778✔
4451

4452
  ivector_remove_duplicates(v);  // TEST
31,778✔
4453

4454
  // cleanup the marks and empty the queue
4455
  for (k=0; k<queue->size; k++) {
756,108✔
4456
    i = queue->data[k];
724,330✔
4457
    arith_cnstr_clr_mark(bstack, i);
724,330✔
4458
  }
4459
  ivector_reset(queue);
31,778✔
4460
}
31,778✔
4461

4462

4463

4464

4465
/*
4466
 * Add explanation for bound k into vector v
4467
 * - the explanation is a conjunction of literals
4468
 */
4469
static void simplex_explain_bound(simplex_solver_t *solver, int32_t k, ivector_t *v) {
3,905✔
4470
  ivector_t *queue;
4471

4472
  queue = &solver->expl_queue;
3,905✔
4473
  assert(queue->size == 0);
4474
  enqueue_cnstr_index(queue, k, &solver->bstack);
3,905✔
4475
  simplex_build_explanation(solver, v);
3,905✔
4476
}
3,905✔
4477

4478

4479

4480
/*
4481
 * Negate all literals in v
4482
 * - this turns a conflict explanation (l_1 and .... and l_n) ==> false
4483
 *   into the clause (\not l1) or ... or (not l_n)
4484
 */
4485
static void convert_expl_to_clause(ivector_t *v) {
28,111✔
4486
  uint32_t i, n;
4487
  literal_t *a;
4488

4489
  n = v->size;
28,111✔
4490
  a = v->data;
28,111✔
4491
  for (i=0; i<n; i++) {
660,493✔
4492
    a[i] = not(a[i]);
632,382✔
4493
  }
4494
}
28,111✔
4495

4496

4497
/*
4498
 * Build a conflict clause from the content of the explanation queue
4499
 * and store it in v.
4500
 * - queue must contain a set of bound indices (that is inconsistent)
4501
 * - this is expanded first into a conjunction of literals (inconsistent)
4502
 * - then this is turned into a clause
4503
 */
4504
static void simplex_build_conflict_clause(simplex_solver_t *solver, ivector_t *v) {
27,380✔
4505
#if TRACE
4506
  uint32_t i, j, n;
4507
  literal_t l;
4508
  bool show;
4509
  void *atom;
4510
#endif
4511

4512
  assert(v->size == 0);
4513
  simplex_build_explanation(solver, v);
27,380✔
4514
  convert_expl_to_clause(v);
27,380✔
4515
#if TRACE
4516
  show = true;
4517
  n = v->size;
4518
  if (show) {
4519
    printf("---> Simplex: conflict clause (size = %"PRIu32")\n", n);
4520
    show = false;
4521
  }
4522
  for (i=0; i<n; i++) {
4523
    printf(" ");
4524
    print_literal(stdout, v->data[i]);
4525
  }
4526
  printf("\n");
4527
  for (i=0; i<n; i++) {
4528
    l = v->data[i];
4529
    atom = bvar_atom(solver->core, var_of(l));
4530
    if (atom != NULL) {
4531
      printf("    ");
4532
      print_literal(stdout, l);
4533
      printf(" := ");
4534
      if (atom_tag(atom) == ARITH_ATM_TAG) {
4535
        print_simplex_atom_of_literal(stdout, solver, l);
4536
      } else {
4537
        print_egraph_atom_of_literal(stdout, solver->egraph, l);
4538
      }
4539
      printf("\n");
4540
    }
4541
  }
4542
  printf("\n");
4543
  for (j=i+1; j<n; j++) {
4544
    if (v->data[i] == v->data[j]) {
4545
      printf("     duplicate literal: %"PRId32" (at index %"PRIu32" and %"PRIu32")\n", v->data[i], i, j);
4546
    }
4547
  }
4548
#endif
4549
}
27,380✔
4550

4551

4552
/*
4553
 * Convert a conflict set to a clause and report the conflict to the core
4554
 * - the conflict set is in solver->expl_queue.
4555
 * - the conflict clause is stored in solver->expl_vector
4556
 */
4557
static void simplex_report_conflict(simplex_solver_t *solver) {
27,380✔
4558
  ivector_t *v;
4559

4560
  // translate the queue into a conjunction of literals (stored in expl_vector);
4561
  v = &solver->expl_vector;
27,380✔
4562
  ivector_reset(v);
27,380✔
4563
  simplex_build_conflict_clause(solver, v);
27,380✔
4564

4565
#if 0
4566
  printf("\n---> SIMPLEX CONFLICT: not feasible\n");
4567
#endif
4568
  // record expl_vector as a conflict (first add the null-literal terminator)
4569
  ivector_push(v, null_literal);
27,380✔
4570
  record_theory_conflict(solver->core, v->data);
27,380✔
4571

4572
  solver->stats.num_conflicts ++;
27,380✔
4573
}
27,380✔
4574

4575

4576

4577

4578
/*
4579
 * EXPLANATIONS FOR EQUALITIES SENT TO THE EGRAPH
4580
 */
4581

4582
/*
4583
 * Add the two bounds for x to q (unless they are marked)
4584
 */
4585
static void enqueue_frozen_var_constraints(simplex_solver_t *solver, ivector_t *q, thvar_t x) {
10,814✔
4586
  int32_t l, u;
4587

4588
  assert(simplex_fixed_variable(solver, x));
4589

4590
  l = arith_var_lower_index(&solver->vtbl, x);
10,814✔
4591
  u = arith_var_upper_index(&solver->vtbl, x);
10,814✔
4592
  enqueue_cnstr_index(q, l, &solver->bstack);
10,814✔
4593
  enqueue_cnstr_index(q, u, &solver->bstack);
10,814✔
4594
}
10,814✔
4595

4596

4597
/*
4598
 * For an equality (x1 == x2) received from the egraph, add the corresponding egraph equality
4599
 * (t1 == t2) to result.
4600
 * - triple->var[0] = x1
4601
 * - triple->var[1] = x2
4602
 * - triple->id = egraph edge that caused (x1 == x2)
4603
 */
4604
static void explain_vareq_from_egraph(simplex_solver_t *solver, egraph_expl_triple_t *triple, th_explanation_t *result) {
7,087✔
4605
  eterm_t t1, t2;
4606

4607
  t1 = arith_var_eterm(&solver->vtbl, triple->var[0]);
7,087✔
4608
  t2 = arith_var_eterm(&solver->vtbl, triple->var[1]);
7,087✔
4609
  th_explanation_add_eq(result, t1, t2);
7,087✔
4610
}
7,087✔
4611

4612

4613
/*
4614
 * Expand the explanation queue and build a theory explanation object for the egraph
4615
 * - queue must contain a set of constraint indices that imply an equality (x1 == x2)
4616
 *   that was propagated to the egraph.
4617
 * - the queue is emptied and all constraint marks are cleared
4618
 */
4619
static void simplex_build_theory_explanation(simplex_solver_t *solver, ivector_t *queue, th_explanation_t *result) {
4,243✔
4620
  arith_bstack_t *bstack;
4621
  uint8_t *tag;
4622
  uint32_t k;
4623
  int32_t i;
4624

4625
  bstack = &solver->bstack;
4,243✔
4626
  tag = bstack->tag;
4,243✔
4627

4628
  for (k=0; k<queue->size; k++) {
29,692✔
4629
    i = queue->data[k];
25,449✔
4630
    assert(arith_cnstr_is_marked(bstack, i));
4631
    switch (arith_tag(tag[i])) {
25,449✔
4632
    case ARITH_AXIOM_LB:
1,030✔
4633
    case ARITH_AXIOM_UB:
4634
      // nothing to do
4635
      break;
1,030✔
4636

4637
    case ARITH_ASSERTED_LB:
15,891✔
4638
    case ARITH_ASSERTED_UB:
4639
      // add literal explanation to result
4640
      th_explanation_add_atom(result, bstack->expl[i].lit);
15,891✔
4641
      break;
15,891✔
4642

4643
    case ARITH_DERIVED_LB:
1,441✔
4644
    case ARITH_DERIVED_UB:
4645
      // add antecedents to the queue
4646
      enqueue_cnstr_array_indices(queue, bstack->expl[i].ptr, bstack);
1,441✔
4647
      solver->stats.num_prop_expl ++;
1,441✔
4648
      break;
1,441✔
4649

4650
    case ARITH_EGRAPHEQ_LB:
7,087✔
4651
    case ARITH_EGRAPHEQ_UB:
4652
      // add eq to the result
4653
      explain_vareq_from_egraph(solver, bstack->expl[i].ptr, result);
7,087✔
4654
      break;
7,087✔
4655

4656
    default:
×
4657
      abort();
×
4658
      break;
4659
    }
4660
  }
4661

4662
  // remove duplicates in result
4663
  cleanup_th_explanation(result);
4,243✔
4664

4665
  // cleanup the marks and empty the queue
4666
  for (k=0; k<queue->size; k++) {
29,692✔
4667
    i = queue->data[k];
25,449✔
4668
    arith_cnstr_clr_mark(bstack, i);
25,449✔
4669
  }
4670
  ivector_reset(queue);
4,243✔
4671
}
4,243✔
4672

4673

4674
/*
4675
 * Build an explanation for the egraph
4676
 * - this function is called by the egraph when it needs the explanation for (x1 == x2)
4677
 * - expl is NULL (we ignore it)
4678
 * - the explanation must be stored in result
4679
 * - when this function is called, result is empty
4680
 */
4681
static void simplex_expand_th_explanation(simplex_solver_t *solver, thvar_t x1, thvar_t x2, void *expl, th_explanation_t *result) {
4,243✔
4682
  eq_propagator_t *eqprop;
4683
  ivector_t *queue, *v;
4684
  uint32_t i, n;
4685

4686
  eqprop = solver->eqprop;
4,243✔
4687
  assert(eqprop != NULL);
4688

4689
  /*
4690
   * collect the relevant frozen variables in aux
4691
   */
4692
  v = &eqprop->aux;
4,243✔
4693
  ivector_reset(v);
4,243✔
4694
  offset_manager_explain_equality(&eqprop->mngr, x1, x2, v);
4,243✔
4695

4696
  /*
4697
   * All variables in eqprop->aux are frozen: add explanation for them
4698
   * to eqprop->expl_queue
4699
   */
4700
  queue = &eqprop->expl_queue;
4,243✔
4701
  assert(queue->size == 0);
4702
  n = v->size;
4,243✔
4703
  for (i=0; i<n; i++) {
15,057✔
4704
    enqueue_frozen_var_constraints(solver, queue, v->data[i]);
10,814✔
4705
  }
4706

4707
  // build the explanation from the queue then reset the queue
4708
  simplex_build_theory_explanation(solver, queue, result);
4,243✔
4709

4710
#if 0
4711
  printf("---> simplex provides explanation for g!%"PRId32" == g!%"PRId32"\n",
4712
         arith_var_eterm(&solver->vtbl, x1), arith_var_eterm(&solver->vtbl, x2));
4713
  printf("     antecedents: ");
4714
  print_theory_explanation(stdout, result);
4715
  printf("\n");
4716
  fflush(stdout);
4717
#endif
4718
}
4,243✔
4719

4720

4721

4722

4723
/*********************************
4724
 *  TOP-LEVEL FEASIBILITY CHECK  *
4725
 ********************************/
4726

4727
/*
4728
 * This function checks whether the bounds are consistent.  It
4729
 * constructs a feasible solution if they are and return true.
4730
 * Otherwsie, it builds a conflict clause and add it to the core
4731
 * otherwise, and it returns false.
4732
 *
4733
 * Preconditions: same as simplex_check_feasibility.
4734
 */
4735
static bool simplex_make_feasible(simplex_solver_t *solver) {
569,056✔
4736
  bool feasible;
4737

4738
#if DEBUG
4739
  check_nonbasic_assignment(solver);
4740
  check_vartags(solver);
4741
  check_infeasible_vars(solver);
4742
  check_integer_bounds(solver);
4743
  check_bound_marks(solver);
4744
#endif
4745

4746
  solver->stats.num_make_feasible ++;
569,056✔
4747
  feasible = simplex_check_feasibility(solver);
569,056✔
4748
  if (!feasible) {
569,056✔
4749
    simplex_report_conflict(solver);
27,380✔
4750
  }
4751

4752
#if DEBUG
4753
  check_bound_marks(solver);
4754
  check_vartags(solver);
4755
  if (feasible) {
4756
    check_assignment(solver);
4757
  } else {
4758
    check_nonbasic_assignment(solver);
4759
  }
4760

4761
#endif
4762

4763
  return feasible;
569,056✔
4764
}
4765

4766

4767

4768

4769

4770
/********************************
4771
 *  ADD LOWER AND UPPER BOUNDS  *
4772
 *******************************/
4773

4774
/*
4775
 * Construct a simple conflict when we have bound k ==> (not l)
4776
 * - the conflict clause is stored in solver->expl_vector
4777
 */
4778
static void record_simple_conflict(simplex_solver_t *solver, int32_t k, literal_t l) {
65✔
4779
  ivector_t *v;
4780

4781
  v = &solver->expl_vector;
65✔
4782
  ivector_reset(v);
65✔
4783
  simplex_explain_bound(solver, k, v);
65✔
4784

4785
  /*
4786
   * negate literals in v to turn (l1 and ... and l_m ==> (not l))
4787
   * into the clause (or (not l1) ... (not l_m) (not l))
4788
   */
4789
  convert_expl_to_clause(v);
65✔
4790
  ivector_push(v, not(l));
65✔
4791

4792
#if 0
4793
  if (is_pos(l)) {
4794
    printf("\n---> SIMPLEX CONFLICT: bound %"PRId32" => ~p!%"PRId32"\n", k, var_of(l));
4795
  } else {
4796
    printf("\n---> SIMPLEX CONFLICT: bound %"PRId32" => p!%"PRId32"\n", k, var_of(l));
4797
  }
4798
#endif
4799
  // add the end marker
4800
  ivector_push(v, null_literal);
65✔
4801
  record_theory_conflict(solver->core, v->data);
65✔
4802

4803
  solver->stats.num_conflicts ++;
65✔
4804
}
65✔
4805

4806

4807
/*
4808
 * Add a lower bound: x >= c or x > c
4809
 * - x = variable
4810
 * - c = rational bound
4811
 * - strict indicates whether the bound is strict or not
4812
 * - l = explanation (literal)
4813
 *
4814
 * return true if the bound is consistent
4815
 * return false if the  bound is inconsistent with the existing
4816
 * upper bound on x.
4817
 */
4818
static bool add_lower_bound(simplex_solver_t *solver, thvar_t x, rational_t *c, bool strict, literal_t l) {
912,750✔
4819
  arith_vartable_t *vtbl;
4820
  xrational_t *b;
4821
  int32_t k;
4822

4823
  vtbl = &solver->vtbl;
912,750✔
4824

4825
  // store the bound as an extended rational
4826
  b = &solver->bound;
912,750✔
4827
  xq_set_q(b, c);
912,750✔
4828
  if (strict) {
912,750✔
4829
    if (arith_var_is_int(vtbl, x)) {
191,515✔
4830
      // bound is c+1
4831
      assert(q_is_integer(c));
4832
      xq_add_one(b);
×
4833
    } else {
4834
      // bound is c+delta
4835
      xq_add_delta(b);
191,515✔
4836
    }
4837
  }
4838

4839
#if TRACE
4840
  printf("---> checking bound: ");
4841
  print_simplex_var(stdout, solver, x);
4842
  printf(" >= ");
4843
  xq_print(stdout, b);
4844
  printf("\n");
4845
#endif
4846

4847

4848
  k = arith_var_upper_index(vtbl, x);
912,750✔
4849
  if (k >= 0 && xq_lt(solver->bstack.bound + k, b)) {
912,750✔
4850
    // conflict: current upper bound on x is less than b
4851
    record_simple_conflict(solver, k, l);
16✔
4852

4853
#if TRACE
4854
    printf("---> conflict with bound ");
4855
    print_simplex_bound(stdout, solver, k);
4856
    printf("\n");
4857
#endif
4858

4859
    return false;
16✔
4860
  }
4861

4862
  k = arith_var_lower_index(vtbl, x);
912,734✔
4863
  if (k < 0 || xq_lt(solver->bstack.bound + k, b)) {
912,734✔
4864
    // the new bound is not redundant
4865
    push_lb_assertion(solver, x, b, l);
670,630✔
4866

4867
#if TRACE
4868
    printf("---> added ");
4869
    print_simplex_bound(stdout, solver, solver->bstack.top - 1);
4870
    printf("\n");
4871
  } else {
4872
    printf("---> redundant\n");
4873
#endif
4874

4875
  }
4876

4877
  return true;
912,734✔
4878
}
4879

4880

4881
/*
4882
 * Add a upper bound: x <= c or x < c
4883
 * - x = variable
4884
 * - c = rational bound
4885
 * - strict indicates whether the bound is strict or not
4886
 * - l = explanation (literal)
4887
 *
4888
 * return true if the bound is consistent
4889
 * return false if the  bound is inconsistent with the existing
4890
 * lower bound on x.
4891
 */
4892
static bool add_upper_bound(simplex_solver_t *solver, thvar_t x, rational_t *c, bool strict, literal_t l) {
898,230✔
4893
  arith_vartable_t *vtbl;
4894
  xrational_t *b;
4895
  int32_t k;
4896

4897
  vtbl = &solver->vtbl;
898,230✔
4898

4899
  // store the bound as an extended rational
4900
  b = &solver->bound;
898,230✔
4901
  xq_set_q(b, c);
898,230✔
4902
  if (strict) {
898,230✔
4903
    if (arith_var_is_int(vtbl, x)) {
444,707✔
4904
      // bound is c-1
4905
      assert(q_is_integer(c));
4906
      xq_sub_one(b);
268,120✔
4907
    } else {
4908
      // bound is c-delta
4909
      xq_sub_delta(b);
176,587✔
4910
    }
4911
  }
4912

4913

4914
#if TRACE
4915
  printf("---> checking bound: ");
4916
  print_simplex_var(stdout, solver, x);
4917
  printf(" <= ");
4918
  xq_print(stdout, b);
4919
  printf("\n");
4920
#endif
4921

4922
  k = arith_var_lower_index(vtbl, x);
898,230✔
4923
  if (k >= 0 && xq_gt(solver->bstack.bound + k, b)) {
898,230✔
4924
    // conflict: current lower bound on x is more than b
4925
    record_simple_conflict(solver, k, l);
49✔
4926

4927
#if TRACE
4928
    printf("---> conflict with bound ");
4929
    print_simplex_bound(stdout, solver, k);
4930
    printf("\n");
4931
#endif
4932

4933
    return false;
49✔
4934
  }
4935

4936
  k = arith_var_upper_index(vtbl, x);
898,181✔
4937
  if (k < 0 || xq_gt(solver->bstack.bound + k, b)) {
898,181✔
4938
    // the new bound is not redundant
4939
    push_ub_assertion(solver, x, b, l);
684,129✔
4940

4941
#if TRACE
4942
    printf("---> added ");
4943
    print_simplex_bound(stdout, solver, solver->bstack.top - 1);
4944
    printf("\n");
4945
  } else {
4946
    printf("---> redundant\n");
4947
#endif
4948

4949
  }
4950

4951
  return true;
898,181✔
4952
}
4953

4954

4955

4956

4957

4958
/***********************************
4959
 *   PROCESS THE ASSERTION QUEUE   *
4960
 **********************************/
4961

4962
/*
4963
 * Code for switch label when processing an asserted atom
4964
 * - the code is 2 bits for the atom type (GE, LE, EQ)
4965
 *   + 1 bit to indicate whether the atom is asserted true or false
4966
 * - the codes depend on the encoding used by arithatm_tag_t:
4967
 *   GE_ATM = 00, LE_ATM = 01, EQ_ATM = 10
4968
 */
4969
typedef enum atom_process_code {
4970
  GE_TRUE,   // 000
4971
  GE_FALSE,  // 001
4972
  LE_TRUE,   // 010
4973
  LE_FALSE,  // 011
4974
  EQ_TRUE,   // 100
4975
  EQ_FALSE,  // 101
4976
} atom_process_code_t;
4977

4978
static inline atom_process_code_t procode(arithatm_tag_t tag, uint32_t sgn_bit) {
1,810,980✔
4979
  assert(sgn_bit == 0 || sgn_bit == 1);
4980
  return (atom_process_code_t) ((tag << 1)|sgn_bit);
1,810,980✔
4981
}
4982

4983

4984
/*
4985
 * Process assertion a = atom index + sign bit
4986
 * - return true if no conflict is found
4987
 * - return false if a conflict is found (i.e., if the assertion is
4988
 *   incompatible with an existing bound)
4989
 */
4990
static bool simplex_process_assertion(simplex_solver_t *solver, int32_t a) {
1,810,980✔
4991
  arith_atom_t *atom;
4992
  int32_t id;
4993
  thvar_t x;
4994
  bvar_t z;
4995
  bool ok;
4996

4997
  id = atom_of_assertion(a);
1,810,980✔
4998
  atom = arith_atom(&solver->atbl, id);
1,810,980✔
4999
  x = var_of_atom(atom);
1,810,980✔
5000
  z = boolvar_of_atom(atom);
1,810,980✔
5001

5002

5003
#if TRACE
5004
  printf("---> processing assertion: ");
5005
  print_simplex_atom(stdout, solver, id);
5006
  if (assertion_is_true(a)) {
5007
    printf("  (true)\n");
5008
  } else {
5009
    printf("  (false)\n");
5010
  }
5011
#endif
5012

5013

5014
  switch (procode(tag_of_atom(atom), sign_of_assertion(a))) {
1,810,980✔
5015
  case GE_TRUE:  // x>=b
721,235✔
5016
    ok = add_lower_bound(solver, x, bound_of_atom(atom), false, pos_lit(z));
721,235✔
5017
    break;
721,235✔
5018
  case GE_FALSE: // x<b
444,707✔
5019
    ok = add_upper_bound(solver, x, bound_of_atom(atom), true, neg_lit(z));
444,707✔
5020
    break;
444,707✔
5021
  case LE_TRUE:  // x<=b
453,523✔
5022
    ok = add_upper_bound(solver, x, bound_of_atom(atom), false, pos_lit(z));
453,523✔
5023
    break;
453,523✔
5024
  case LE_FALSE: // x>b
191,515✔
5025
    ok = add_lower_bound(solver, x, bound_of_atom(atom), true, neg_lit(z));
191,515✔
5026
    break;
191,515✔
5027
  case EQ_TRUE:  // x == b: should never occur
×
5028
  case EQ_FALSE:
5029
  default:
5030
    abort();
×
5031
    break;
5032
  }
5033

5034
  return ok;
1,810,980✔
5035
}
5036

5037

5038
/*
5039
 * Process all assertions in the queue
5040
 * - add the asserted bound and update the assignment
5041
 * - return true if no conflict is found
5042
 * - return false if a conflict is found. If so, a conflict clause
5043
 *   is added to the core.
5044
 */
5045
static bool simplex_process_assertions(simplex_solver_t *solver) {
555,754✔
5046
  arith_astack_t *astack;
5047
  uint32_t p;
5048

5049
  astack = &solver->assertion_queue;
555,754✔
5050
  for (p=astack->prop_ptr; p<astack->top; p++) {
2,366,669✔
5051
    if (! simplex_process_assertion(solver, astack->data[p])) {
1,810,980✔
5052
      return false;
65✔
5053
    }
5054
  }
5055

5056
  assert(p == astack->top);
5057
  astack->prop_ptr = p;
555,689✔
5058

5059
  return true;
555,689✔
5060
}
5061

5062

5063

5064

5065

5066
/**************************************************
5067
 *  LITERALS IMPLIED BY AXIOMS OR DERIVED BOUNDS  *
5068
 *************************************************/
5069

5070
/*
5071
 * Record that atom atm or its negation is implied by bound i
5072
 * - l = implied literal = either pos_lit(x) or neg_lit(x) where x = boolean variable of atm
5073
 */
5074
static void simplex_implied_literal(simplex_solver_t *solver, int32_t atm, int32_t i, literal_t l) {
453,781✔
5075
  aprop_t *expl;
5076

5077
  assert(var_of(l) == boolvar_of_atom(arith_atom(&solver->atbl, atm)));
5078

5079
  /*
5080
   * If we're at the base level, just assert l
5081
   * Otherwise, propagate l with i as antecedent
5082
   */
5083
  if (solver->base_level == solver->decision_level) {
453,781✔
5084
    add_unit_clause(solver->core, l);
2,661✔
5085
  } else {
5086
    expl = make_simplex_prop_object(solver, i);
451,120✔
5087
    propagate_literal(solver->core, l, expl);
451,120✔
5088
    solver->stats.num_props ++;
451,120✔
5089
  }
5090

5091
  // mark that atm is assigned and push the assertion into the assertion stack
5092
  push_assertion(&solver->assertion_queue, mk_assertion(atm, sign_of(l)));
453,781✔
5093
  mark_arith_atom(&solver->atbl, atm);
453,781✔
5094

5095
}
453,781✔
5096

5097

5098

5099
/*
5100
 * Scan all atoms in atom vector v (all are atoms on a variable x)
5101
 * - if any of them is implied by the constraint (x >= a) then propagate it to the core
5102
 * - i = index of the bound (x >= a)
5103
 */
5104
static void check_lower_bound_implications(simplex_solver_t *solver, uint32_t i, xrational_t *a, int32_t *v) {
626,025✔
5105
  arith_atomtable_t *atbl;
5106
  arith_atom_t *p;
5107
  uint32_t n, j;
5108
  int32_t atm;
5109

5110
  atbl = &solver->atbl;
626,025✔
5111
  n = iv_size(v);
626,025✔
5112
  for (j=0; j<n; j++) {
3,447,883✔
5113
    atm = v[j];
2,821,858✔
5114
    if (arith_atom_is_unmarked(atbl, atm)) {
2,821,858✔
5115
      p = arith_atom(atbl, atm);
839,008✔
5116
      assert(var_of_atom(p) == solver->bstack.var[i]);
5117
      switch (tag_of_atom(p)) {
839,008✔
5118
      case GE_ATM:
683,242✔
5119
        /*
5120
         * x >= a implies x >= b  if a >= b
5121
         */
5122
        if (xq_ge_q(a, bound_of_atom(p))) {
683,242✔
5123

5124
#if TRACE
5125
          printf("---> atom[%"PRId32"]:\t", atm);
5126
          print_simplex_atom(stdout, solver, atm);
5127
          printf("\t\tis true by ");
5128
          print_simplex_bound(stdout, solver, i);
5129
          printf("\n");
5130
#endif
5131
          simplex_implied_literal(solver, atm, i, pos_lit(boolvar_of_atom(p)));
195,246✔
5132

5133
        }
5134
        break;
683,242✔
5135
      case LE_ATM:
155,766✔
5136
      case EQ_ATM:
5137
        /*
5138
         * x >= a implies (not x <= b) if a > b
5139
         * x >= a implies (not x == b) if a > b
5140
         */
5141
        if (xq_gt_q(a, bound_of_atom(p))) {
155,766✔
5142

5143
#if TRACE
5144
          printf("---> atom[%"PRId32"]:\t", atm);
5145
          print_simplex_atom(stdout, solver, atm);
5146
          printf("\t\tis false by ");
5147
          print_simplex_bound(stdout, solver, i);
5148
          printf("\n");
5149
#endif
5150
          simplex_implied_literal(solver, atm, i, neg_lit(boolvar_of_atom(p)));
23,720✔
5151
        }
5152
        break;
155,766✔
5153
      }
5154
    }
5155
  }
5156
}
626,025✔
5157

5158

5159
/*
5160
 * Same thing for the constraint (x <= a)
5161
 */
5162
static void check_upper_bound_implications(simplex_solver_t *solver, uint32_t i, xrational_t *a, int32_t *v) {
656,617✔
5163
  arith_atomtable_t *atbl;
5164
  arith_atom_t *p;
5165
  uint32_t n, j;
5166
  int32_t atm;
5167

5168
  atbl = &solver->atbl;
656,617✔
5169
  n = iv_size(v);
656,617✔
5170
  for (j=0; j<n; j++) {
3,608,295✔
5171
    atm = v[j];
2,951,678✔
5172
    if (arith_atom_is_unmarked(atbl, atm)) {
2,951,678✔
5173
      p = arith_atom(atbl, atm);
871,714✔
5174
      assert(var_of_atom(p) == solver->bstack.var[i]);
5175
      switch (tag_of_atom(p)) {
871,714✔
5176
      case LE_ATM:
89,410✔
5177
        /*
5178
         * x <= a implies x <= b  if a <= b
5179
         */
5180
        if (xq_le_q(a, bound_of_atom(p))) {
89,410✔
5181

5182
#if TRACE
5183
          printf("---> atom[%"PRId32"]:\t", atm);
5184
          print_simplex_atom(stdout, solver, atm);
5185
          printf("\t\tis true by ");
5186
          print_simplex_bound(stdout, solver, i);
5187
          printf("\n");
5188
#endif
5189

5190
          simplex_implied_literal(solver, atm, i, pos_lit(boolvar_of_atom(p)));
8,583✔
5191
        }
5192
        break;
89,410✔
5193
      case GE_ATM:
782,304✔
5194
      case EQ_ATM:
5195
        /*
5196
         * x <= a implies (not x >= b) if a < b
5197
         * x <= a implies (not x == b) if a < b
5198
         */
5199
        if (xq_lt_q(a, bound_of_atom(p))) {
782,304✔
5200

5201
#if TRACE
5202
          printf("---> atom[%"PRId32"]:\t", atm);
5203
          print_simplex_atom(stdout, solver, atm);
5204
          printf("\t\tis false by ");
5205
          print_simplex_bound(stdout, solver, i);
5206
          printf("\n");
5207
#endif
5208

5209
          simplex_implied_literal(solver, atm, i, neg_lit(boolvar_of_atom(p)));
226,232✔
5210
        }
5211
        break;
782,304✔
5212
      }
5213
    }
5214
  }
5215
}
656,617✔
5216

5217

5218

5219

5220
/*
5221
 * Propagation: find all literals implied by new bounds
5222
 * - scan the bound queue from bstack->prop_ptr to bstack->top-1
5223
 */
5224
static void simplex_literal_propagation(simplex_solver_t *solver) {
505,105✔
5225
  arith_bstack_t *bstack;
5226
  arith_vartable_t *vtbl;
5227
  int32_t *atom_vector;
5228
  uint32_t i;
5229
  thvar_t x;
5230

5231
  assert(solver->assertion_queue.prop_ptr == solver->assertion_queue.top &&
5232
         solver->bstack.fix_ptr == solver->bstack.top);
5233

5234
  bstack = &solver->bstack;
505,105✔
5235
  vtbl = &solver->vtbl;
505,105✔
5236

5237
  for (i = bstack->prop_ptr; i<bstack->top; i++) {
2,020,793✔
5238
    x = bstack->var[i];
1,515,688✔
5239
    atom_vector = arith_var_atom_vector(vtbl, x);
1,515,688✔
5240
    if (atom_vector != NULL) {
1,515,688✔
5241
      /*
5242
       * bound[i] is a constraint on x
5243
       */
5244
      if (constraint_is_lower_bound(bstack, i)) {
1,282,642✔
5245
        check_lower_bound_implications(solver, i, bstack->bound + i, atom_vector);
626,025✔
5246
      } else {
5247
        assert(constraint_is_upper_bound(bstack, i));
5248
        check_upper_bound_implications(solver, i, bstack->bound + i, atom_vector);
656,617✔
5249
      }
5250
    }
5251
  }
5252

5253
  assert(i == bstack->top);
5254
  bstack->prop_ptr = i;
505,105✔
5255

5256
  // update prop_ptr in the assertion queue to skip the implied atoms
5257
  solver->assertion_queue.prop_ptr = solver->assertion_queue.top;
505,105✔
5258
}
505,105✔
5259

5260

5261

5262

5263

5264

5265
/*********************************************
5266
 *  HELPER FUNCTIONS FOR THEORY PROPAGATION  *
5267
 ********************************************/
5268

5269
/*
5270
 * Record a conflict between an existing bound j and an implied bound
5271
 * - v = explanation for the implied bound = a set of bound indices
5272
 * - j = bound index
5273
 * There are two cases of conflict:
5274
 * 1) v implies (x >= b) and (u < b) where u = current upper bound on x
5275
 *    then j = index of the constraint (x <= u) in the bstack
5276
 * 2) v implies (x <= b) and (l > b) where l = current lower bound on x
5277
 *    then j = index of the constraint (x >= l) in the bstack
5278
 */
5279
static void record_derived_conflict(simplex_solver_t *solver, int32_t j, ivector_t *v) {
373✔
5280
  uint32_t i, n;
5281
  ivector_t *q;
5282

5283
  // add j and all elements of v into the queue
5284
  q = &solver->expl_queue;
373✔
5285
  assert(q->size == 0 && q != v);
5286
  enqueue_cnstr_index(q, j, &solver->bstack);
373✔
5287
  n = v->size;
373✔
5288
  for (i=0; i<n; i++) {
12,462✔
5289
    enqueue_cnstr_index(q, v->data[i], &solver->bstack);
12,089✔
5290
  }
5291

5292
  // expand into a conjunction of literals
5293
  v = &solver->expl_vector;
373✔
5294
  ivector_reset(v);
373✔
5295
  simplex_build_explanation(solver, v);
373✔
5296

5297
  convert_expl_to_clause(v);
373✔
5298
  ivector_push(v, null_literal);
373✔
5299
  record_theory_conflict(solver->core, v->data);
373✔
5300

5301
  solver->stats.num_conflicts ++;
373✔
5302
}
373✔
5303

5304

5305

5306
/*
5307
 * Check whether b is larger than the current lower bound on x
5308
 */
5309
static bool improved_lower_bound(simplex_solver_t *solver, thvar_t x, xrational_t *b) {
859,797✔
5310
  arith_bstack_t *bstack;
5311
  int32_t k;
5312

5313
  bstack = &solver->bstack;
859,797✔
5314
  k = arith_var_lower_index(&solver->vtbl, x);
859,797✔
5315
  return  k < 0 || xq_lt(bstack->bound + k, b);
859,797✔
5316
}
5317

5318

5319
/*
5320
 * Check whether b is smaller than the current upper bound on x
5321
 */
5322
static bool improved_upper_bound(simplex_solver_t *solver, thvar_t x, xrational_t *b) {
875,602✔
5323
  arith_bstack_t *bstack;
5324
  int32_t k;
5325

5326
  bstack = &solver->bstack;
875,602✔
5327
  k = arith_var_upper_index(&solver->vtbl, x);
875,602✔
5328
  return k < 0 || xq_gt(bstack->bound + k, b);
875,602✔
5329
}
5330

5331

5332
/*
5333
 * Add a derived bound (x >= b) with explanation stored in *v
5334
 * - v must be a set of bound indices that imply (x >= b)
5335
 * - b must be better than the current lower bound on x
5336
 * Return true if the new bound does not cause a conflict;
5337
 * return false and record a theory conflict otherwise.
5338
 *
5339
 * The new bound may cause val[x] to no longer be between the
5340
 * lower and upper bounds on x. If that's the case, the function
5341
 * set the global flag solver->recheck to true.
5342
 */
5343
static bool simplex_add_derived_lower_bound(simplex_solver_t *solver, thvar_t x, xrational_t *b, ivector_t *v) {
112,164✔
5344
  int32_t *a, k;
5345
  uint32_t i, n;
5346

5347
  assert(improved_lower_bound(solver, x, b));
5348

5349
  // Strengthen the bound to ceil(b) if x is an integer
5350
  if (arith_var_is_int(&solver->vtbl, x)) {
112,164✔
5351
    xq_ceil(b);
111,814✔
5352
  }
5353

5354
  // Check for conflict
5355
  k = arith_var_upper_index(&solver->vtbl, x);
112,164✔
5356
  if (k >= 0 && xq_lt(solver->bstack.bound + k, b)) {
112,164✔
5357
    // conflict: ub[x] = bound[k] < b
5358
    record_derived_conflict(solver, k, v);
308✔
5359
    return false;
308✔
5360
  }
5361

5362
  // Make a copy of v in the arena (add -1 as a terminator)
5363
  n = v->size;
111,856✔
5364
  a = (int32_t *) arena_alloc(&solver->arena, (n+1) * sizeof(literal_t));
111,856✔
5365
  for (i=0; i<n; i++) {
625,109✔
5366
    a[i] = v->data[i];
513,253✔
5367
  }
5368
  a[i] = -1;
111,856✔
5369

5370
  // Add the bound
5371
  push_lb_derived(solver, x, b, a);
111,856✔
5372

5373
#if TRACE_INTFEAS
5374
  printf("---> Derived bound\n");
5375
  print_simplex_bound(stdout, solver, arith_var_lower_index(&solver->vtbl, x));
5376
  printf("\n");
5377
  fflush(stdout);
5378
#endif
5379

5380
  /*
5381
   * Check whether val[x] is still within bounds (i.e., val[x] >= b holds)
5382
   */
5383
  if (xq_ge(b, arith_var_value(&solver->vtbl, x))) {
111,856✔
5384
    // b >= val[x]: set the recheck flag
5385
    solver->recheck = true;
64,736✔
5386
  }
5387

5388
  solver->stats.num_bound_props ++;
111,856✔
5389

5390
  return true;
111,856✔
5391
}
5392

5393

5394
/*
5395
 * Add a derived bound (x <= b) with explanation stored in *v
5396
 * - v must be a set of bound indices that imply (x <= b)
5397
 * - b must be better than the current upper bound on x
5398
 * Return true if the new bound does not cause a conflict.
5399
 * Return false if the new bound causes a conflict.
5400
 *
5401
 * Set solver->recheck to true if val[x] is no longer within bounds
5402
 */
5403
static bool simplex_add_derived_upper_bound(simplex_solver_t *solver, thvar_t x, xrational_t *b, ivector_t *v) {
127,358✔
5404
  int32_t *a, k;
5405
  uint32_t i, n;
5406

5407
  assert(improved_upper_bound(solver, x, b));
5408

5409
  // Strengthen the bound to floor(b) if x is an integer
5410
  if (arith_var_is_int(&solver->vtbl, x)) {
127,358✔
5411
    xq_floor(b);
127,063✔
5412
  }
5413

5414
  // Check for conflict
5415
  k = arith_var_lower_index(&solver->vtbl, x);
127,358✔
5416
  if (k >= 0 && xq_gt(solver->bstack.bound + k, b)) {
127,358✔
5417
    // conflict: lb[x] = bound[k] > b
5418
    record_derived_conflict(solver, k, v);
65✔
5419
    return false;
65✔
5420
  }
5421

5422
  // make a copy of v in the arena (add -1 as a terminator)
5423
  n = v->size;
127,293✔
5424
  a = (int32_t *) arena_alloc(&solver->arena, (n+1) * sizeof(literal_t));
127,293✔
5425
  for (i=0; i<n; i++) {
676,885✔
5426
    a[i] = v->data[i];
549,592✔
5427
  }
5428
  a[i] = -1;
127,293✔
5429

5430
  // Add the bound
5431
  push_ub_derived(solver, x, b, a);
127,293✔
5432

5433
#if TRACE_INTFEAS
5434
  printf("---> Derived bound\n");
5435
  print_simplex_bound(stdout, solver, arith_var_upper_index(&solver->vtbl, x));
5436
  printf("\n");
5437
  fflush(stdout);
5438
#endif
5439

5440
  /*
5441
   * Check whether val[x] is still within bounds (i.e., val[x] <= b holds)
5442
   */
5443
  if (xq_le(b, arith_var_value(&solver->vtbl, x))) {
127,293✔
5444
    // b <= val[x]: set the recheck flag
5445
    solver->recheck = true;
78,767✔
5446
  }
5447

5448
  solver->stats.num_bound_props ++;
127,293✔
5449

5450
  return true;
127,293✔
5451
}
5452

5453

5454

5455
/*********************
5456
 *  DERIVED BOUNDS   *
5457
 ********************/
5458

5459
/*
5460
 * Check whether we can derive a lower or upper bound on x from the row where x is basic
5461
 * - x must be a basic variable
5462
 * - if lower is true, this checks for a lower bound. Otherwise the function checks
5463
 *   for an upper bound.
5464
 *
5465
 * The row is of the form  x + sum of monomials == 0
5466
 * - we can derive a lower bound on x if all the monomials have an upper bound
5467
 *   (namely x >= - sum of monomials' upper bounds)
5468
 * - we can derive an upper bound on x if all the monomials have a lower bound
5469
 *   (namely x <= - sum of monomials' lower bounds)
5470
 */
5471
static bool simplex_basic_var_has_derived_bound(simplex_solver_t *solver, thvar_t x, bool lower) {
14,954✔
5472
  arith_vartable_t *vtbl;
5473
  row_t *row;
5474
  int32_t k;
5475
  uint32_t i, n;
5476
  thvar_t y;
5477

5478
  vtbl = &solver->vtbl;
14,954✔
5479

5480
  k = matrix_basic_row(&solver->matrix, x);
14,954✔
5481
  assert(k >= 0); // i.e., x is a basic variable
5482
  row = matrix_row(&solver->matrix, k);
14,954✔
5483

5484
  n = row->size;
14,954✔
5485
  for (i=0; i<n; i++) {
195,106✔
5486
    y = row->data[i].c_idx;
187,051✔
5487
    if (y >= 0 && y != x) {
187,051✔
5488
      /*
5489
       * monomial a * y where a = row->data[i].coeff
5490
       * - if lower is true, we check whether a * y has an upper bound
5491
       *   (i.e., a>0 and y has an upper bound or a<0 and y has a lower bound)
5492
       * - if lower is false, we check whether a * y has a lower bound
5493
       *   (i.e., a>0 and y has a lower bound or a>0 and y has an upper bound)
5494
       */
5495
      if (q_is_pos(&row->data[i].coeff) == lower) {
159,303✔
5496
        k = arith_var_upper_index(vtbl, y);
81,616✔
5497
      } else {
5498
        k = arith_var_lower_index(vtbl, y);
77,687✔
5499
      }
5500
      if (k < 0) return false;
159,303✔
5501
    }
5502
  }
5503

5504
  return true;
8,055✔
5505
}
5506

5507

5508
/*
5509
 * Compute the derived lower or upper bound on x
5510
 * - x must be a basic variable
5511
 * - if lower is true, the function computes the lower bound,
5512
 *   otherwise it computes the upper bound.
5513
 * - the bound is returned in b
5514
 *
5515
 * - If v is non-null, the antecedents (bounds that imply x <= b or x >= b) are added to vector v
5516
 */
5517
static void simplex_derived_bound_on_basic_var(simplex_solver_t *solver, thvar_t x, bool lower, xrational_t *b, ivector_t *v) {
8,055✔
5518
  arith_vartable_t *vtbl;
5519
  row_t *row;
5520
  int32_t k;
5521
  uint32_t i, n;
5522
  thvar_t y;
5523

5524
  vtbl = &solver->vtbl;
8,055✔
5525

5526
  k = matrix_basic_row(&solver->matrix, x);
8,055✔
5527
  assert(k >= 0); // i.e., x is a basic variable
5528
  row = matrix_row(&solver->matrix, k);
8,055✔
5529

5530
  xq_clear(b);
8,055✔
5531

5532
  n = row->size;
8,055✔
5533
  for (i=0; i<n; i++) {
132,649✔
5534
    y = row->data[i].c_idx;
124,594✔
5535
    if (y >= 0 && y != x) {
124,594✔
5536
      // monomial a * y where a = row->data[i].coeff
5537
      if (q_is_pos(&row->data[i].coeff) == lower) {
103,411✔
5538
        k = arith_var_upper_index(vtbl, y);
51,205✔
5539
      } else {
5540
        k = arith_var_lower_index(vtbl, y);
52,206✔
5541
      }
5542
      assert(k >= 0);
5543
      xq_addmul(b, solver->bstack.bound + k, &row->data[i].coeff);
103,411✔
5544
      if (v != NULL) ivector_push(v, k);
103,411✔
5545
    }
5546
  }
5547

5548
  xq_neg(b);
8,055✔
5549
}
8,055✔
5550

5551

5552
/*
5553
 * Wrapper: don't get antecedents
5554
 */
5555
static inline void simplex_get_derived_bound_on_basic_var(simplex_solver_t *solver, thvar_t x, bool lower, xrational_t *b) {
8,055✔
5556
  simplex_derived_bound_on_basic_var(solver, x, lower, b, NULL);
8,055✔
5557
}
8,055✔
5558

5559

5560

5561

5562

5563
/*
5564
 * DERIVED BOUNDS ON NON-BASIC VARIABLES
5565
 */
5566

5567
/*
5568
 * Check whether row r implies a bound on variable x
5569
 * - index ptr = where variable x occurs in the row
5570
 * - we must have row->data[ptr].c_idx == x
5571
 * - if lower is true, this checks for a lower bound on x, otherwise
5572
 *   this checks for an upper bound.
5573
 *
5574
 * The row has the form (a.x + sum of monomials == 0) so
5575
 * we have a.x = - (sum of monomials).
5576
 *
5577
 * If a<0 then
5578
 * - implied lower bound for x = - (lower bound on sum)/a
5579
 * - implied upper bound for x = - (upper bound on sum)/a
5580
 *
5581
 * If a>0 then
5582
 * - implied lower bound for x = - (upper bound on sum)/a
5583
 * - implied upper bound for x = - (lower bound on sum)/a
5584
 */
5585
static bool simplex_row_implies_bound_on_var(simplex_solver_t *solver, row_t *row, thvar_t x, int32_t ptr, bool lower) {
×
5586
  arith_vartable_t *vtbl;
5587
  uint32_t i, n;
5588
  int32_t k;
5589
  thvar_t y;
5590

5591
  assert(row->data[ptr].c_idx == x);
5592

5593
  vtbl = &solver->vtbl;
×
5594

5595
  if (q_is_neg(&row->data[ptr].coeff)) {
×
5596
    // x has a negative coefficient, we flip the flag lower.
5597
    lower = !lower;
×
5598
  }
5599

5600
  /*
5601
   * If lower is true, this loop checks whether all monomials other than a.x
5602
   * have an un upper bound. If lower is false, it checks whether all monomials
5603
   * other than a.x have a lower bound.
5604
   */
5605
  n = row->size;
×
5606
  for (i=0; i<n; i++) {
×
5607
    y = row->data[i].c_idx;
×
5608
    if (y >= 0 && y != x) {
×
5609
      if (q_is_pos(&row->data[i].coeff) == lower) {
×
5610
        k = arith_var_upper_index(vtbl, y);
×
5611
      } else {
5612
        k = arith_var_lower_index(vtbl, y);
×
5613
      }
5614
      if (k < 0) return false;
×
5615
    }
5616
  }
5617

5618
  return true;
×
5619
}
5620

5621

5622
/*
5623
 * Compute a derived bound on x implied by row
5624
 * - x must occur in the row at index ptr
5625
 * - the row must imply a bound (as checked by the previous function)
5626
 * - if lower is true, the function computes a lower bound on x, otherwise it computes an upper bound.
5627
 * - the resulting bound is stored in *b
5628
 */
5629
static void simplex_bound_on_var_implied_by_row(simplex_solver_t *solver, row_t *row, thvar_t x, int32_t ptr, bool lower, xrational_t *b) {
×
5630
  arith_vartable_t *vtbl;
5631
  int32_t k;
5632
  uint32_t i, n;
5633
  thvar_t y;
5634

5635
  assert(row->data[ptr].c_idx == x);
5636

5637
  vtbl = &solver->vtbl;
×
5638

5639
  if (q_is_neg(&row->data[ptr].coeff)) {
×
5640
    // x has a negative coefficient, we flip the flag lower.
5641
    lower = !lower;
×
5642
  }
5643

5644
  xq_clear(b);
×
5645

5646
  /*
5647
   * The row is (a.x) + sum = 0.
5648
   *
5649
   * If lower is true, this loop computes an upper bound on sum
5650
   * If lower is false, this loop computes a lower bound on sum
5651
   */
5652
  n = row->size;
×
5653
  for (i=0; i<n; i++) {
×
5654
    y = row->data[i].c_idx;
×
5655
    if (y >= 0 && y != x) {
×
5656
      // monomial a * y where a = row->data[i].coeff
5657
      if (q_is_pos(&row->data[i].coeff) == lower) {
×
5658
        k = arith_var_upper_index(vtbl, y);
×
5659
      } else {
5660
        k = arith_var_lower_index(vtbl, y);
×
5661
      }
5662
      assert(k >= 0);
5663
      xq_addmul(b, solver->bstack.bound + k, &row->data[i].coeff);
×
5664
    }
5665
  }
5666

5667
  // bound on x is - (bound on sum)/a
5668
  xq_neg(b);
×
5669
  xq_div(b, &row->data[ptr].coeff);
×
5670
}
×
5671

5672

5673
/*
5674
 * Collect antecedents for an implied bound on x
5675
 * - same parameters as the previous function.
5676
 * - the antecedents are added to vector v
5677
 */
5678
static void simplex_explain_bound_implied_by_row(simplex_solver_t *solver, row_t *row, thvar_t x, int32_t ptr, bool lower, ivector_t *v) {
×
5679
  arith_vartable_t *vtbl;
5680
  int32_t k;
5681
  uint32_t i, n;
5682
  thvar_t y;
5683

5684
  assert(row->data[ptr].c_idx == x);
5685

5686
  vtbl = &solver->vtbl;
×
5687

5688
  if (q_is_neg(&row->data[ptr].coeff)) {
×
5689
    // x has a negative coefficient, we flip the flag lower.
5690
    lower = !lower;
×
5691
  }
5692

5693
  /*
5694
   * The row is (a.x) + sum = 0.
5695
   *
5696
   * If lower is true, this loop collects upper bound on monomials of sum
5697
   * If lower is fales, this loop collects lower bound on monomials of sum
5698
   */
5699
  n = row->size;
×
5700
  for (i=0; i<n; i++) {
×
5701
    y = row->data[i].c_idx;
×
5702
    if (y >= 0 && y != x) {
×
5703
      // monomial a * y where a = row->data[i].coeff
5704
      if (q_is_pos(&row->data[i].coeff) == lower) {
×
5705
        k = arith_var_upper_index(vtbl, y);
×
5706
      } else {
5707
        k = arith_var_lower_index(vtbl, y);
×
5708
      }
5709
      assert(k >= 0);
5710
      ivector_push(v, k);
×
5711
    }
5712
  }
5713
}
×
5714

5715

5716
/*
5717
 * Check whether bound b1 is stronger than b2.
5718
 * - if lower is true --> b1 > b2
5719
 * - otherwise b1 < b2
5720
 */
5721
static bool better_bound(xrational_t *b1, xrational_t *b2, bool lower) {
×
5722
  int c;
5723
  c = xq_cmp(b1, b2);
×
5724
  return lower ? c>0 : c<0;
×
5725
}
5726

5727

5728
/*
5729
 * Test whether the basic variable in row r has a bound (lower or upper)
5730
 */
5731
static bool base_var_has_bound(simplex_solver_t *solver, int32_t r) {
×
5732
  thvar_t x;
5733

5734
  x = matrix_basic_var(&solver->matrix, r);
×
5735
  return arith_var_upper_index(&solver->vtbl, x) >= 0 || arith_var_lower_index(&solver->vtbl, x) >= 0;
×
5736
}
5737

5738

5739
/*
5740
 * Computes a derived bound on variable x and asserts it if it's better than the current bound on x
5741
 * - if lower is true, this attempts to add a lower bound
5742
 * - if lower is false, this attempts to add an upper bound.
5743
 * - returns false if the new bound causes a conflict (and adds a theory conflict in the core)
5744
 * - returns true otherwise.
5745
 * - the flag solver->recheck is set to true if val[x] is no-longer within the bounds on x
5746
 */
5747
static bool simplex_strengthen_bound_on_var(simplex_solver_t *solver, thvar_t x, bool lower) {
×
5748
  xrational_t *bound;
5749
  xrational_t *aux;
5750
  column_t *col;
5751
  row_t *row;
5752
  ivector_t *v;
5753
  uint32_t i, n;
5754
  int32_t best_r, r;
5755
  int32_t best_ptr, ptr;
5756
  bool ok;
5757

5758
  best_r = -1;
×
5759
  best_ptr = -1;
×
5760
  bound = &solver->bound;
×
5761
  aux = &solver->xq0;
×
5762

5763
  ok = true;
×
5764
  col = matrix_column(&solver->matrix, x);
×
5765
  if (col != NULL) {
×
5766
    /*
5767
     * Get the strongest derived bound on x
5768
     */
5769
    n = col->size;
×
5770
    for (i=0; i<n; i++) {
×
5771
      r = col->data[i].r_idx;
×
5772
      if (r >= 0 && base_var_has_bound(solver, r)) {
×
5773
        row = matrix_row(&solver->matrix, r);
×
5774
        ptr = col->data[i].r_ptr;
×
5775
        // x occurs in row r at index ptr
5776
        if (simplex_row_implies_bound_on_var(solver, row, x, ptr, lower)) {
×
5777
          simplex_bound_on_var_implied_by_row(solver, row, x, ptr, lower, aux);
×
5778
          if (best_r < 0 || better_bound(aux, bound, lower)) {
×
5779
            // aux is stronger than the current best bound
5780
            best_r = r;
×
5781
            best_ptr = ptr;
×
5782
            xq_set(bound, aux);
×
5783
          }
5784
        }
5785
      }
5786
    }
5787

5788
    /*
5789
     * assert the bound if it's better than the existing upper/lower bound on x
5790
     */
5791
    if (best_r >= 0) {
×
5792
      v = &solver->aux_vector;
×
5793
      assert(v->size == 0);
5794

5795
      if (lower) {
×
5796
        if (improved_lower_bound(solver, x, bound)) {
×
5797
          row = matrix_row(&solver->matrix, best_r);
×
5798
          simplex_explain_bound_implied_by_row(solver, row, x, best_ptr, lower, v);
×
5799
          ok = simplex_add_derived_lower_bound(solver, x, bound, v);
×
5800
        }
5801
      } else {
5802
        if (improved_upper_bound(solver, x, bound)) {
×
5803
          row = matrix_row(&solver->matrix, best_r);
×
5804
          simplex_explain_bound_implied_by_row(solver, row, x, best_ptr, lower, v);
×
5805
          ok = simplex_add_derived_upper_bound(solver, x, bound, v);
×
5806
        }
5807
      }
5808

5809
      ivector_reset(v); // must ensure that aux_vector is empty
×
5810
    }
5811

5812
  }
5813

5814
  return ok;
×
5815
}
5816

5817

5818
/*
5819
 * Attempt to strengthen the bounds on all non-basic variables.
5820
 * - return false if that causes a conflict (and add a theory conflict)
5821
 * - return true otherwise
5822
 * - sets solver->recheck to true if some variables are no-longer within their bounds
5823
 */
5824
static bool simplex_strengthen_bounds_on_non_basic_vars(simplex_solver_t *solver) {
×
5825
  arith_vartable_t *vtbl;
5826
  uint32_t i, n;
5827
  bool ok;
5828

5829
  ok = true;
×
5830
  vtbl = &solver->vtbl;
×
5831
  n = vtbl->nvars;
×
5832

5833
  // nothing to do for variable 0 (constant index)
5834
  for (i=1; i<n; i++) {
×
5835
    if (matrix_is_nonbasic_var(&solver->matrix, i)) {
×
5836
      ok = simplex_strengthen_bound_on_var(solver, i, true)
×
5837
        && simplex_strengthen_bound_on_var(solver, i, false);
×
5838
      if (!ok) {
×
5839
        // conflict detected
5840
        break;
×
5841
      }
5842
    }
5843
  }
5844

5845
  return ok;
×
5846
}
5847

5848

5849
/*
5850
 * Computes a derived bound on basic variable x and asserts it if it's better than x's current bound.
5851
 * - if lower is true: this tries to strengthen the lower bound
5852
 * - if lower is false: tries to strengthen the upper bound
5853
 * - returns false if the new bound causes a conflict (and add a theory conflict in the core)
5854
 * - returns true otherwise
5855
 */
5856
static bool simplex_strengthen_bound_on_basic_var(simplex_solver_t *solver, thvar_t x, bool lower) {
×
5857
  xrational_t *bound;
5858
  ivector_t *v;
5859
  bool ok;
5860

5861
  ok = true;
×
5862
  bound = &solver->bound;
×
5863
  v = &solver->aux_vector;
×
5864
  assert(v->size == 0);
5865

5866
  if (simplex_basic_var_has_derived_bound(solver, x, lower)) {
×
5867
    simplex_derived_bound_on_basic_var(solver, x, lower, bound, v);
×
5868

5869
    if (lower) {
×
5870
      if (improved_lower_bound(solver, x, bound)) {
×
5871
        ok = simplex_add_derived_lower_bound(solver, x, bound, v);
×
5872
      }
5873
    } else {
5874
      if (improved_upper_bound(solver, x, bound)) {
×
5875
        ok = simplex_add_derived_upper_bound(solver, x, bound, v);
×
5876
      }
5877
    }
5878

5879
    ivector_reset(v);
×
5880
  }
5881

5882
  return ok;
×
5883
}
5884

5885

5886
/*
5887
 * Attempt to strengthen the bounds on all basic variables.
5888
 * - return false if that causes a conflict (adds a theory conflict in the core)
5889
 * - return true otherwise
5890
 */
5891
static bool simplex_strengthen_bounds_on_basic_vars(simplex_solver_t *solver) {
×
5892
  arith_vartable_t *vtbl;
5893
  uint32_t i, n;
5894
  bool ok;
5895

5896
  ok = true;
×
5897
  vtbl = &solver->vtbl;
×
5898
  n = vtbl->nvars;
×
5899

5900
  // nothing to do for variable 0 (constant index)
5901
  for (i=1; i<n; i++) {
×
5902
    if (matrix_is_basic_var(&solver->matrix, i)) {
×
5903
      ok = simplex_strengthen_bound_on_basic_var(solver, i, true)
×
5904
        && simplex_strengthen_bound_on_basic_var(solver, i, false);
×
5905
      if (!ok) {
×
5906
        // conflict detected
5907
        break;
×
5908
      }
5909
    }
5910
  }
5911

5912
  return ok;
×
5913
}
5914

5915

5916

5917
/*
5918
 * Attempt to strengthen all the bounds
5919
 * - one pass for the non-basic variables + one pass for the basic variables
5920
 */
5921
static bool simplex_strengthen_bounds(simplex_solver_t *solver) {
×
5922
  return simplex_strengthen_bounds_on_non_basic_vars(solver) && simplex_strengthen_bounds_on_basic_vars(solver);
×
5923
}
5924

5925

5926
#if 0
5927

5928
// NOT USED
5929
/*
5930
 * Several rounds of strengthening
5931
 * - MAX_STRENGTHEN_ITERS  = maximal number of rounds
5932
 * - the function returns false if bound strengthening caused a conflict
5933
 */
5934
#define MAX_STRENGTHEN_ITERS 2
5935

5936
static bool simplex_strengthen_bounds_iter(simplex_solver_t *solver) {
5937
  uint32_t nb, i;
5938

5939
  for (i=0; i<MAX_STRENGTHEN_ITERS; i++) {
5940
    nb = solver->bstack.top;
5941
    if (!simplex_strengthen_bounds(solver)) return false;
5942
    // quit if the last round didn't find any new bound
5943
    if (nb == solver->bstack.top) break;
5944
  }
5945

5946
  return true;
5947
}
5948

5949
#endif
5950

5951

5952
/******************************
5953
 *  PROPAGATOR INCLUDED HERE  *
5954
 *****************************/
5955

5956
#include "solvers/simplex/simplex_propagator1.h"
5957

5958

5959

5960

5961

5962

5963
/***********************************
5964
 *  REBUILD THE CONSTRAINT MATRIX  *
5965
 **********************************/
5966

5967
/*
5968
 * Delete the tableau + elimination matrices etc.
5969
 */
5970
static void simplex_reset_tableau(simplex_solver_t *solver) {
42,081✔
5971
  if (solver->tableau_ready) {
42,081✔
5972
    assert(solver->save_rows);
5973

5974
    reset_elim_matrix(&solver->elim);
12,812✔
5975
    reset_fvar_vector(&solver->fvars);
12,812✔
5976
    reset_matrix(&solver->matrix);
12,812✔
5977

5978
    // clear statistics
5979
    solver->stats.num_elim_rows = 0;
12,812✔
5980
    solver->stats.num_simpl_fvars = 0;
12,812✔
5981
    solver->stats.num_simpl_rows = 0;
12,812✔
5982

5983
    // reset the propagator if any
5984
    if (solver->propagator != NULL) {
12,812✔
5985
      simplex_reset_propagator(solver);
×
5986
    }
5987

5988
    // reset the diophantine subsolver if any
5989
    if (solver->dsolver != NULL) {
12,812✔
5990
      reset_dsolver(solver->dsolver);
×
5991
    }
5992

5993
    solver->tableau_ready = false;
12,812✔
5994
  }
5995
}
42,081✔
5996

5997

5998
/*
5999
 * Prepare for new assertions:
6000
 * - rebuild the constraint matrix as it was before the previous call to
6001
 *   start_search (modulo reordering; the rows may be permuted)
6002
 * - we must make sure the rows are added in chronological order:
6003
 *   all rows created at base_level 0 must come first,
6004
 *   then all rows created at base_level 1 and so forth.
6005
 */
6006
static void simplex_restore_matrix(simplex_solver_t *solver) {
41,950✔
6007
  arith_trail_t *trail;
6008
  pvector_t *v;
6009
  polynomial_t *p;
6010
  uint32_t i, n, ns, nv;
6011

6012
  if (! solver->matrix_ready) {
41,950✔
6013
    assert(solver->save_rows && solver->matrix.nrows == 0 &&
6014
           solver->matrix.ncolumns == 0);
6015

6016
    // rebuild n empty columns in the matrix
6017
    matrix_add_columns(&solver->matrix, solver->vtbl.nvars);
12,802✔
6018

6019
    /*
6020
     * Restore rows from the trail stack:
6021
     * - for each base_level i,
6022
     *   tail->nvars = number of variables
6023
     *   tail->nsaved_rows = number of polynomials in solver->saved_rows
6024
     * (these counters are saved when we leave base_level i and enter i+1)
6025
     */
6026

6027
    v = &solver->saved_rows;
12,802✔
6028

6029
    ns = 0; // number of saved rows added so far
12,802✔
6030
    nv = 1; // number of variables visited so far (we start with 1 to skip const_idx)
12,802✔
6031

6032
    n = solver->trail_stack.top;
12,802✔
6033
    trail = solver->trail_stack.data;
12,802✔
6034
    assert(n == solver->base_level);
6035

6036
    for (i=0; i<n; i++) {
21,459✔
6037
      // saved rows for level i
6038
      while (ns < trail->nsaved_rows) {
8,822✔
6039
        assert(ns < v->size);
6040
        p = v->data[ns];
165✔
6041
        matrix_add_row(&solver->matrix, p->mono, p->nterms);
165✔
6042
        ns ++;
165✔
6043
      }
6044

6045
      // definition rows for level i
6046
      while (nv < trail->nvars) {
11,652✔
6047
        p = arith_var_def(&solver->vtbl, nv);
2,995✔
6048
        if (p != NULL && !simple_poly(p)) {
2,995✔
6049
          matrix_add_eq(&solver->matrix, nv, p->mono, p->nterms);
494✔
6050
        }
6051
        nv ++;
2,995✔
6052
      }
6053

6054
      trail ++;
8,657✔
6055
    }
6056

6057
    /*
6058
     * Restore rows added at the current base level
6059
     */
6060
    while (ns < v->size) {
12,813✔
6061
      p = v->data[ns];
11✔
6062
      matrix_add_row(&solver->matrix, p->mono, p->nterms);
11✔
6063
      ns ++;
11✔
6064
    }
6065

6066
    n = solver->vtbl.nvars;
12,802✔
6067
    while (nv < n) {
15,400✔
6068
      p = arith_var_def(&solver->vtbl, nv);
2,598✔
6069
      if (p != NULL && !simple_poly(p)) {
2,598✔
6070
        matrix_add_eq(&solver->matrix, nv, p->mono, p->nterms);
387✔
6071
      }
6072
      nv ++;
2,598✔
6073
    }
6074

6075
    // mark that the matrix is ready
6076
    solver->matrix_ready = true;
12,802✔
6077
  }
6078

6079
}
41,950✔
6080

6081

6082

6083

6084

6085

6086
/**************************************
6087
 *  ADDITION OF VARIABLES ON THE FLY  *
6088
 *************************************/
6089

6090
/*
6091
 * Decompose the buffer into (p + a) where a is the constant term
6092
 * - store the opposite of a into solver->constant
6093
 * - return a variable x equal to p
6094
 * - reset the buffer
6095
 *
6096
 * If a new variable x is created, add a row to the tableau and make x basic
6097
 * and also compute the value of x in the simplex assignment.
6098
 */
6099
static thvar_t decompose_and_get_dynamic_var(simplex_solver_t *solver) {
139,658✔
6100
  poly_buffer_t *b;
6101
  matrix_t *matrix;
6102
  thvar_t x;
6103
  int32_t r;
6104
  bool new_var;
6105

6106
  assert(solver->tableau_ready);
6107

6108
  b = &solver->buffer;
139,658✔
6109

6110
  poly_buffer_get_neg_constant(b, &solver->constant); // store -a, b is (p + a)
139,658✔
6111
  x = poly_buffer_nonconstant_convert_to_var(b);      // check whether p is a variable
139,658✔
6112
  if (x < 0) {
139,658✔
6113
    x = get_var_for_poly_offset(&solver->vtbl, poly_buffer_mono(b), poly_buffer_nterms(b), &new_var);
107,998✔
6114
    if (new_var) {
107,998✔
6115
      matrix = &solver->matrix;
7,019✔
6116
      // add a new column to the matrix`
6117
      assert(x == matrix->ncolumns);
6118
      matrix_add_column(matrix);
7,019✔
6119

6120
      // add a row and make x basic
6121
      poly_buffer_clear_const(b); // now b is equal to p
7,019✔
6122
      poly_buffer_substitution(b, matrix); // substitute basic variables of b
7,019✔
6123
      normalize_poly_buffer(b);
7,019✔
6124
      matrix_add_tableau_eq(matrix, x, poly_buffer_mono(b), poly_buffer_nterms(b));
7,019✔
6125

6126
      // compute the value of x
6127
      r = matrix_basic_row(matrix, x);
7,019✔
6128
      assert(0 <= r && r < matrix->nrows);
6129
      simplex_set_basic_var_value(solver, x, matrix_row(matrix, r));
7,019✔
6130

6131
      // set the relevance bit in eqprop if present
6132
      if (solver->eqprop != NULL) {
7,019✔
6133
        eqprop_set_relevance(solver, x);
6,088✔
6134
      }
6135

6136
#if TRACE
6137
      printf("     new simplex variable: ");
6138
      print_simplex_vardef(stdout, solver, x);
6139
#endif
6140
    }
6141
  }
6142
  reset_poly_buffer(b);
139,658✔
6143

6144
  return x;
139,658✔
6145
}
6146

6147

6148

6149
/*
6150
 * Build a polynomial p such that (x1 == x2) is equivalent to p == 0
6151
 * then check whether p == 0 simplifies to true or false.
6152
 * - normalize p as much as possible
6153
 * Results:
6154
 * - p is stored (normalized) in solver->buffer
6155
 * - if p == 0 simplifies, the result is true_literal or false_literal
6156
 * - otherwise, the returned value is null_literal
6157
 */
6158
static literal_t simplify_dynamic_vareq(simplex_solver_t *solver, thvar_t x1, thvar_t x2) {
139,582✔
6159
  poly_buffer_t *b;
6160
  bool is_int;
6161

6162
#if TRACE
6163
  printf("---> Simplex: simplify dynamic vareq: ");
6164
  print_simplex_var(stdout, solver, x1);
6165
  printf(" == ");
6166
  print_simplex_var(stdout, solver, x2);
6167
  printf("\n---> ");
6168
  print_simplex_vardef(stdout, solver, x1);
6169
  printf("---> ");
6170
  print_simplex_vardef(stdout, solver, x2);
6171
#endif
6172

6173
  b = &solver->buffer;
139,582✔
6174
  assert(poly_buffer_nterms(b) == 0);
6175

6176
  add_var_or_subst(solver, b, x1);
139,582✔
6177
  sub_var_or_subst(solver, b, x2);
139,582✔
6178
  normalize_poly_buffer(b);
139,582✔
6179

6180
#if TRACE
6181
  printf("---> buffer: ");
6182
  print_simplex_buffer(stdout, solver);
6183
  printf("\n");
6184
#endif
6185

6186
  if (poly_buffer_is_zero(b)) {
139,582✔
6187
#if TRACE
6188
    printf("---> vareq is true\n");
6189
#endif
6190
    return true_literal;
×
6191
  }
6192

6193
  if (poly_buffer_is_nzconstant(b)) {
139,582✔
6194
#if TRACE
6195
    printf("---> vareq is false\n");
6196
#endif
6197
    return false_literal;
3✔
6198
  }
6199

6200
  is_int = all_integer_vars(solver);
139,579✔
6201
  if (is_int) {
139,579✔
6202
    poly_buffer_make_integral(b);
136,264✔
6203
#if TRACE
6204
    printf("---> int scaling: ");
6205
    print_simplex_buffer(stdout, solver);
6206
    printf("\n");
6207
#endif
6208
    if (! poly_buffer_gcd_test(b)) {
136,264✔
6209
#if TRACE
6210
      printf("---> vareq is false by GCD test\n");
6211
#endif
6212
      return false_literal;
×
6213
    }
6214
  } else {
6215
    poly_buffer_make_monic(b); // make lead coefficient = 1
3,315✔
6216
#if TRACE
6217
    printf("---> monic: ");
6218
    print_simplex_buffer(stdout, solver);
6219
    printf("\n");
6220
#endif
6221
  }
6222

6223
  return null_literal;
139,579✔
6224
}
6225

6226

6227

6228

6229

6230
/**************************
6231
 *  INTEGER FEASIBILITY   *
6232
 *************************/
6233

6234
/*
6235
 * Check whether all integer variables have an integer value
6236
 */
6237
static bool simplex_assignment_integer_valid(simplex_solver_t *solver) {
15,198✔
6238
  arith_vartable_t *vtbl;
6239
  uint32_t i, n;
6240

6241
  vtbl = &solver->vtbl;
15,198✔
6242
  n = vtbl->nvars;
15,198✔
6243
  for (i=0; i<n; i++) {
361,090✔
6244
    if (arith_var_is_int(vtbl, i) && ! arith_var_value_is_int(vtbl, i)) {
347,155✔
6245
      return false;
1,263✔
6246
    }
6247
  }
6248

6249
  return true;
13,935✔
6250
}
6251

6252

6253
#if TRACE_BB
6254
/*
6255
 * Number of integer variables with a non-integer value
6256
 */
6257
static uint32_t simplex_num_integer_invalid_vars(simplex_solver_t *solver) {
6258
  arith_vartable_t *vtbl;
6259
  uint32_t i, n, c;
6260

6261
  c = 0;
6262
  vtbl = &solver->vtbl;
6263
  n = vtbl->nvars;
6264
  for (i=0; i<n; i++) {
6265
    if (arith_var_is_int(vtbl, i) && ! arith_var_value_is_int(vtbl, i)) {
6266
      c ++;
6267
    }
6268
  }
6269

6270
  return c;
6271
}
6272
#endif
6273

6274

6275
/*
6276
 * Check whether the system has integer variables other than the constant
6277
 * (const_idx ==0)
6278
 */
6279
static bool simplex_has_integer_vars(simplex_solver_t *solver) {
27,969✔
6280
  return num_integer_vars(&solver->vtbl) > 1;
27,969✔
6281
}
6282

6283

6284
/*
6285
 * Check whether the system mixes integer and non-integer variables
6286
 */
6287
static bool simplex_is_mixed_system(simplex_solver_t *solver) {
2,627✔
6288
  uint32_t k;
6289
  k = num_integer_vars(&solver->vtbl);
2,627✔
6290
  return 1 < k && k < num_arith_vars(&solver->vtbl);
2,627✔
6291
}
6292

6293

6294
/*
6295
 * Search for a variable in row that is non-integer and not fixed
6296
 * - return its index k in the row (i.e., row->data[k].c_idx is a non-integer variable)
6297
 *   or -1 if all variables are integer
6298
 * Note: We can substitute any fixed variable by its value, since the value of
6299
 * a fixed variable is always a rational (never an extended rational).
6300
 */
6301
static int32_t find_real_var_in_row(simplex_solver_t *solver, row_t *row) {
13,069✔
6302
  arith_vartable_t *vtbl;
6303
  uint32_t i, n;
6304
  thvar_t x;
6305

6306
  vtbl = &solver->vtbl;
13,069✔
6307
  n = row->size;
13,069✔
6308
  for (i=0; i<n; i++) {
285,549✔
6309
    x = row->data[i].c_idx;
272,897✔
6310
    if (x >= 0 && ! arith_var_is_int(vtbl, x) && ! simplex_fixed_variable(solver, x)) {
272,897✔
6311
      return i;
417✔
6312
    }
6313
  }
6314
  return -1;
12,652✔
6315
}
6316

6317

6318
/*
6319
 * Make integer variables non-basic (as much as possible)
6320
 * - this preserves feasibility
6321
 * - after this, if x is a basic integer variable in a row i then all variables
6322
 *   of row i are integer.
6323
 */
6324
static void make_integer_vars_nonbasic(simplex_solver_t *solver) {
562✔
6325
  matrix_t *matrix;
6326
  arith_vartable_t *vtbl;
6327
  row_t *row;
6328
  thvar_t x;
6329
  uint32_t i, n;
6330
  int32_t k;
6331

6332
  matrix = &solver->matrix;
562✔
6333
  vtbl = &solver->vtbl;
562✔
6334

6335
  n = matrix->nrows;
562✔
6336
  for (i=0; i<n; i++) {
20,197✔
6337
    x = matrix_basic_var(matrix, i);
19,635✔
6338
    assert(x >= 0);
6339
    if (arith_var_is_int(vtbl, x)) {
19,635✔
6340
      // check whether row i contains a non-integer variable y
6341
      // if so make y basic
6342
      row = matrix_row(matrix, i);
8,325✔
6343
      k = find_real_var_in_row(solver, row);
8,325✔
6344
      if (k >= 0) {
8,325✔
6345
        matrix_pivot(matrix, i, k);
80✔
6346
        solver->stats.num_pivots ++;
80✔
6347

6348
        // make sure the ub/lb flags for x are correct
6349
        simplex_set_bound_flags(solver, x);
80✔
6350
      }
6351
    }
6352
  }
6353
}
562✔
6354

6355

6356
/*
6357
 * Search for a feasible assignment where all non-basic integer variables
6358
 * have an integer value. Return true if such an assignment is found,
6359
 * false otherwise.
6360
 *
6361
 * We do this in two steps:
6362
 * 1) assign an integer value to the non-basic, integer variables
6363
 * 2) call make_feasible
6364
 *
6365
 * Step 2 may change the set of non-basic variables, but it maintains
6366
 * the property that all non-basic integer variables are assigned an
6367
 * integer value (because any variable that leaves the basis is assigned
6368
 * a value equal to its lower or upper bound).
6369
 *
6370
 * If the tableau is feasible when this function is called, then step 1
6371
 * may construct an infeasible solution but step 2 restores feasibility.
6372
 * So the function returns true in such a case.
6373
 */
6374
static bool assign_integers_to_nonbasic_vars(simplex_solver_t *solver) {
1,388✔
6375
  arith_vartable_t *vtbl;
6376
  xrational_t *aux;
6377
  uint32_t i, n;
6378

6379
  // we can use solver->bound here
6380
  aux = &solver->bound;
1,388✔
6381

6382
  vtbl = &solver->vtbl;
1,388✔
6383
  n = vtbl->nvars;
1,388✔
6384
  for (i=0; i<n; i++) {
244,716✔
6385
    if (arith_var_is_int(vtbl, i) && matrix_is_nonbasic_var(&solver->matrix, i) &&
243,328✔
6386
        ! arith_var_value_is_int(vtbl, i)) {
151,237✔
6387
      /*
6388
       * update value[i] to the ceil and set ub tag if needed
6389
       * (since value[i] is not an integer and upper the bound on i is an integer,
6390
       * ceil[value[i]] is within bounds).
6391
       */
6392
      xq_set(aux, arith_var_value(vtbl, i));
74✔
6393
      xq_ceil(aux);
74✔
6394
      update_non_basic_var_value(solver, i, aux);
74✔
6395
      if (variable_at_upper_bound(solver, i)) {
74✔
6396
        set_arith_var_ub(vtbl, i);
1✔
6397
      }
6398
      assert(value_satisfies_bounds(solver, i));
6399
    }
6400
  }
6401

6402
  return simplex_make_feasible(solver);
1,388✔
6403
}
6404

6405

6406

6407

6408
#ifndef NDEBUG
6409
/*
6410
 * For debugging: check that all the integer variables that don't have an integer value
6411
 * are basic.
6412
 */
6413
static bool non_integer_vars_are_basic(simplex_solver_t *solver) {
6414
  arith_vartable_t *vtbl;
6415
  uint32_t i, n;
6416

6417
  vtbl = &solver->vtbl;
6418
  n = vtbl->nvars;
6419
  for (i=0; i<n; i++) {
6420
    if (arith_var_is_int(vtbl, i) && ! arith_var_value_is_int(vtbl, i) &&
6421
        matrix_is_nonbasic_var(&solver->matrix, i)) {
6422
      return false;
6423
    }
6424
  }
6425

6426
  return true;
6427
}
6428

6429
#endif
6430

6431

6432
/*
6433
 * Prepare for integer solving:
6434
 * - make sure all non-basic integer variables have an integer value
6435
 * - so all the integer-infeasible variables are in the basis
6436
 */
6437
static void prepare_for_integer_solving(simplex_solver_t *solver) {
1,388✔
6438
  // move non-integer variables to the basis
6439
  if (simplex_is_mixed_system(solver)) {
1,388✔
6440
    make_integer_vars_nonbasic(solver);
562✔
6441
  }
6442

6443
#if TRACE_INTFEAS
6444
  printf("\nMOVED NON-INTEGER VARIABLES TO THE BASIS\n\n");
6445
  print_simplex_matrix(stdout, solver);
6446
  print_simplex_bounds(stdout, solver);
6447
  printf("\n");
6448
  print_simplex_assignment(stdout, solver);
6449
  printf("\n\n");
6450
  fflush(stdout);
6451
#endif
6452

6453
  // assign an integer value to all non-basic variables
6454
  if (! assign_integers_to_nonbasic_vars(solver)) {
1,388✔
6455
    abort();
×
6456
  }
6457

6458
#if TRACE_INTFEAS
6459
  printf("\nASSIGNED INTEGER VALUES TO NON_BASIC INTEGER VARIABLES\n\n");
6460
  print_simplex_matrix(stdout, solver);
6461
  print_simplex_bounds(stdout, solver);
6462
  printf("\n");
6463
  print_simplex_assignment(stdout, solver);
6464
  printf("\n\n");
6465
  fflush(stdout);
6466
#endif
6467

6468
  assert(non_integer_vars_are_basic(solver));
6469

6470
#if DEBUG
6471
  check_assignment(solver);
6472
  check_vartags(solver);
6473
#endif
6474
}
1,388✔
6475

6476

6477

6478

6479
#if 0
6480

6481
// NOT USED FOR NOW
6482

6483
/*
6484
 * Search for a feasible assignment that maps all non-basic variables
6485
 * to their upper or lower bound (except the variables that don't have bounds).
6486
 * Return true if such an assignment is found, false otherwise.
6487
 *
6488
 * This is done in two steps, as in the previous function.
6489
 */
6490
static bool move_nonbasic_vars_to_bounds(simplex_solver_t *solver) {
6491
  arith_vartable_t *vtbl;
6492
  uint32_t i, n;
6493

6494
  vtbl = &solver->vtbl;
6495
  n = vtbl->nvars;
6496
  for (i=0; i<n; i++) {
6497
    if (matrix_is_nonbasic_var(&solver->matrix, i) && ! arith_var_at_bound(vtbl, i)) {
6498
      if (arith_var_lower_index(vtbl, i) >= 0) {
6499
        update_to_lower_bound(solver, i);
6500
      } else if (arith_var_upper_index(vtbl, i) >= 0) {
6501
        update_to_upper_bound(solver, i);
6502
      }
6503
    }
6504
  }
6505

6506
  return simplex_make_feasible(solver);
6507
}
6508

6509
#endif
6510

6511

6512

6513
/*
6514
 * NAIVE GREEDY SEARCH
6515
 */
6516

6517
/*
6518
 * Naive search: attempt to make all the columns in the tableau integral
6519
 * by adjusting the values of the non-basic variables.
6520
 */
6521

6522
/*
6523
 * Heuristic: check whether the problem looks underconstrained
6524
 * - we count the number of variables with no upper or no lower bound
6525
 */
6526
static uint32_t num_unconstrained_vars(simplex_solver_t *solver) {
664✔
6527
  arith_vartable_t *vtbl;
6528
  uint32_t i, n, count;
6529

6530
  count = 0;
664✔
6531
  vtbl = &solver->vtbl;
664✔
6532
  n = vtbl->nvars;
664✔
6533
  for (i=1; i<n; i++) {
174,533✔
6534
    if (arith_var_lower_index(vtbl, i) < 0 ||
333,241✔
6535
        arith_var_upper_index(vtbl, i) < 0) {
159,372✔
6536
      count ++;
23,596✔
6537
    }
6538
  }
6539

6540
  return count;
664✔
6541
}
6542

6543
static bool underconstrained(simplex_solver_t *solver) {
664✔
6544
  uint32_t n, p;
6545

6546
  p = num_unconstrained_vars(solver);
664✔
6547
  n = solver->vtbl.nvars;
664✔
6548
  if (n > 20) {
664✔
6549
    return p >= n - (n/20);
654✔
6550
  } else {
6551
    return p >= n - 1;
10✔
6552
  }
6553
}
6554

6555

6556
/*
6557
 * Check whether the basic variable in row r is an integer variable
6558
 */
6559
static inline bool row_has_integer_basic_var(matrix_t *matrix, arith_vartable_t *vtbl, int32_t r) {
4,401✔
6560
  thvar_t x;
6561

6562
  assert(0 <= r && r < matrix->nrows);
6563
  x = matrix_basic_var(matrix, r);
4,401✔
6564
  assert(x >= 0);
6565
  return arith_var_is_int(vtbl, x);
4,401✔
6566
}
6567

6568
#ifndef NDEBUG
6569
/*
6570
 * For debugging: go through the column of variable x
6571
 * check that all elements a_i.x in this column are integer
6572
 */
6573
static bool column_is_integral(simplex_solver_t *solver, thvar_t x) {
6574
  xrational_t prod;
6575
  arith_vartable_t *vtbl;
6576
  matrix_t *matrix;
6577
  column_t *col;
6578
  uint32_t i, n;
6579
  int32_t r, j;
6580
  bool all_int;
6581

6582
  vtbl = &solver->vtbl;
6583
  matrix = &solver->matrix;
6584

6585
  assert(matrix_is_nonbasic_var(matrix, x));
6586

6587
  all_int = true;
6588

6589
  xq_init(&prod);
6590
  col = matrix_column(matrix, x);
6591
  if (col != NULL) {
6592
    n = col->size;
6593
    for (i=0; i<n; i++) {
6594
      r = col->data[i].r_idx;
6595
      if (r >= 0 && row_has_integer_basic_var(matrix, vtbl, r)) {
6596
        j = col->data[i].r_ptr;
6597
        xq_set(&prod, arith_var_value(vtbl, x));
6598
        xq_mul(&prod, matrix_coeff(matrix, r, j));
6599
        // prod is val[x] * coeff of x in row r
6600
        if (! xq_is_integer(&prod)) {
6601
          all_int = false;
6602
          break;
6603
        }
6604
      }
6605
    }
6606

6607
  }
6608

6609
  xq_clear(&prod);
6610

6611
  return all_int;
6612
}
6613
#endif
6614

6615

6616
/*
6617
 * Compute a period for x
6618
 * - the column of x contains coefficients { a_1, ...., a_n }.
6619
 * - we want to ensure a_1 * x .... a_n * x are all integers
6620
 * - so x must be a multiple of 1/a_1, ...., 1/a_n
6621
 *
6622
 * If x is an integer variable, this function computes the
6623
 *  lcm of { 1, 1/a_1, ..., 1/a_n }
6624
 * If x is not an integer variable, it computes the
6625
 *  lcm of { 1/a_1, ..., 1/a_n }
6626
 */
6627
static void lcm_in_column(simplex_solver_t *solver, rational_t *lcm, thvar_t x) {
340✔
6628
  rational_t inv_a;
6629
  arith_vartable_t *vtbl;
6630
  matrix_t *matrix;
6631
  column_t *col;
6632
  uint32_t i, n;
6633
  int32_t r, j;
6634

6635
  vtbl = &solver->vtbl;
340✔
6636
  matrix = &solver->matrix;
340✔
6637

6638
  assert(matrix_is_nonbasic_var(matrix, x));
6639

6640
  q_clear(lcm);
340✔
6641
  if (arith_var_is_int(vtbl, x)) {
340✔
6642
    q_set_one(lcm);
340✔
6643
  }
6644

6645
  col = matrix_column(matrix, x);
340✔
6646
  assert(col != NULL);
6647

6648
  q_init(&inv_a);
340✔
6649

6650
  n = col->size;
340✔
6651
  for (i=0; i<n; i++) {
4,942✔
6652
    r = col->data[i].r_idx;
4,602✔
6653
    if (r >= 0 && row_has_integer_basic_var(matrix, vtbl, r)) {
4,602✔
6654
      // x occurs in row r with coefficient a
6655
      j = col->data[i].r_ptr;
4,401✔
6656
      q_set(&inv_a, matrix_coeff(matrix, r, j));
4,401✔
6657
      assert(q_is_nonzero(&inv_a));
6658
      q_inv(&inv_a);
4,401✔
6659
      if (q_is_zero(lcm)) {
4,401✔
6660
        // lcm must be positive
6661
        q_set_abs(lcm, &inv_a);
×
6662
      } else {
6663
        q_generalized_lcm(lcm, &inv_a);
4,401✔
6664
      }
6665
    }
6666
  }
6667

6668
  q_clear(&inv_a);
340✔
6669
}
340✔
6670

6671

6672
/*
6673
 * Compute a safe delta interval for x
6674
 * - the interval stores: a lower bound L, an upper bound U
6675
 * - this defines a set of deltas for x: { d | L <= d && d <= U }
6676
 * - for any delta in this interval, updating
6677
 *      val[x] to val[x] + delta
6678
 *   maintains feasibility.
6679
 */
6680
static void safe_adjust_interval(simplex_solver_t *solver, interval_t *s, thvar_t x) {
340✔
6681
  xrational_t aux;
6682
  arith_vartable_t *vtbl;
6683
  matrix_t *matrix;
6684
  column_t *col;
6685
  rational_t *a;
6686
  uint32_t i, n;
6687
  int32_t r, j;
6688
  thvar_t y;
6689

6690
  vtbl = &solver->vtbl;
340✔
6691
  matrix = &solver->matrix;
340✔
6692

6693
  xq_init(&aux);
340✔
6694

6695
  assert(matrix_is_nonbasic_var(matrix, x));
6696

6697
  /*
6698
   * Initialize the interval:
6699
   * - period = not used
6700
   * - lower bound on delta = lower bound on x - value of x
6701
   * - upper bound on delta = upper bound on x - value of x
6702
   */
6703
  j = arith_var_lower_index(vtbl, x);
340✔
6704
  if (j >= 0) {
340✔
6705
    xq_set(&aux, &solver->bstack.bound[j]); // lower bound on x
219✔
6706
    xq_sub(&aux, arith_var_value(vtbl, x));
219✔
6707
    interval_update_lb(s, &aux);
219✔
6708
  }
6709
  j = arith_var_upper_index(vtbl, x);
340✔
6710
  if (j >= 0) {
340✔
6711
    xq_set(&aux, &solver->bstack.bound[j]); // upper bound on x
105✔
6712
    xq_sub(&aux, arith_var_value(vtbl, x));
105✔
6713
    interval_update_ub(s, &aux);
105✔
6714
  }
6715

6716
  assert(! empty_interval(s));
6717

6718
  // refine the bounds based on x's column
6719
  col = matrix_column(matrix, x);
340✔
6720
  assert(col != NULL);
6721
  n = col->size;
340✔
6722
  for (i=0; i<n; i++) {
4,942✔
6723
    r = col->data[i].r_idx;
4,602✔
6724
    if (r >= 0) {
4,602✔
6725
      j = col->data[i].r_ptr;
4,401✔
6726
      a = matrix_coeff(matrix, r, j);
4,401✔
6727
      y = matrix_basic_var(matrix, r);
4,401✔
6728
      assert(y >= 0 && q_is_nonzero(a));
6729

6730
      /*
6731
       * Update the interval using the bounds on y,
6732
       *
6733
       * We have y + ... + a x + ... = 0, so moving val[x]
6734
       * to val[x] + delta changes val[y] to val[y] - a * delta.
6735
       */
6736
      j = arith_var_lower_index(vtbl, y);
4,401✔
6737
      if (j >= 0) {
4,401✔
6738
        /*
6739
         * L := lower bound on y:
6740
         * if a > 0, we want delta <= (val[y] - L)/a
6741
         * if a < 0, we want delta >= (val[y] - L)/a
6742
         */
6743
        xq_set(&aux, arith_var_value(vtbl, y));
666✔
6744
        xq_sub(&aux, &solver->bstack.bound[j]);
666✔
6745
        xq_div(&aux, a);   // aux is (val[y] - L)/a
666✔
6746
        if (q_is_pos(a)) {
666✔
6747
          interval_update_ub(s, &aux);
303✔
6748
        } else {
6749
          interval_update_lb(s, &aux);
363✔
6750
        }
6751
      }
6752

6753
      j = arith_var_upper_index(vtbl, y);
4,401✔
6754
      if (j >= 0) {
4,401✔
6755
        /*
6756
         * U := upper bound on y:
6757
         * if a > 0, we want delta >= (val[y] - U)/a
6758
         * if a < 0, we want delta <= (val[y] - U)/a
6759
         */
6760
        xq_set(&aux, arith_var_value(vtbl, y));
1,091✔
6761
        xq_sub(&aux, &solver->bstack.bound[j]);
1,091✔
6762
        xq_div(&aux, a);  // aux is (val[y] - U)/a
1,091✔
6763
        if (q_is_pos(a)) {
1,091✔
6764
          interval_update_lb(s, &aux);
551✔
6765
        } else {
6766
          interval_update_ub(s, &aux);
540✔
6767
        }
6768
      }
6769

6770
      assert(! empty_interval(s));
6771
    }
6772
  }
6773

6774
  xq_clear(&aux);
340✔
6775
}
340✔
6776

6777

6778
#if 0
6779
/*
6780
 * For testing: display data about column x
6781
 */
6782
static void show_column_data(simplex_solver_t *solver, thvar_t x) {
6783
  interval_t interval;
6784
  xrational_t newval;
6785
  arith_vartable_t *vtbl;
6786
  bool x_is_int;
6787

6788
  vtbl = &solver->vtbl;
6789
  x_is_int = arith_var_is_int(vtbl, x);
6790

6791
  init_interval(&interval);
6792
  xq_init(&newval);
6793

6794
  // Get period
6795
  lcm_in_column(solver, &interval.period, x);
6796
  if (q_is_zero(&interval.period)) {
6797
    /*
6798
     * x is a non-integer variable
6799
     * and no integer basic variable depend on x
6800
     * no need to touch x.
6801
     */
6802
    assert(!x_is_int);
6803
    assert(column_is_integral(solver, x));
6804
    goto done;
6805
  }
6806

6807
  // Get bounds
6808
  safe_adjust_interval(solver, &interval, x);
6809
  if (interval.has_lb) {
6810
    xq_add(&interval.lb, arith_var_value(vtbl, x));
6811
    if (x_is_int) {
6812
      xq_ceil(&interval.lb);
6813
    }
6814
  }
6815
  if (interval.has_ub) {
6816
    xq_add(&interval.ub, arith_var_value(vtbl, x));
6817
    if (x_is_int) {
6818
      xq_floor(&interval.ub);
6819
    }
6820
  }
6821

6822
#if 0
6823
  printf("---> column of var = i!%"PRId32"\n", x);
6824
  if (interval.has_lb) {
6825
    printf("     lower bound: ");
6826
    xq_print(stdout, &interval.lb);
6827
    printf("\n");
6828
  } else {
6829
    printf("     no lower bound\n");
6830
  }
6831
  if (interval.has_ub) {
6832
    printf("     upper bound: ");
6833
    xq_print(stdout, &interval.ub);
6834
    printf("\n");
6835
  } else {
6836
    printf("     no upper bound\n");
6837
  }
6838
  printf("     period: ");
6839
  q_print(stdout, &interval.period);
6840
  printf("\n");
6841
  fflush(stdout);
6842
#endif
6843

6844
  if (empty_interval(&interval)) {
6845
    // no multiple of period between the two bounds
6846
#if 0
6847
    printf("     empty interval: can't fix\n");
6848
    fflush(stdout);
6849
#endif
6850
    goto done;
6851
  }
6852

6853

6854
  xq_set(&newval, arith_var_value(vtbl, x));
6855
  xq_div(&newval, &interval.period);
6856
  xq_floor(&newval);
6857
  xq_mul(&newval, &interval.period);
6858

6859
  assert(xq_le(&newval, arith_var_value(vtbl, x)));
6860

6861
  /*
6862
   * newval is a multiple of period and we have
6863
   *   newval <= val[x] < newval + period
6864
   */
6865
  if (xq_eq(&newval, arith_var_value(vtbl, x))) {
6866
    // no change needed
6867
    assert(column_is_integral(solver, x));
6868
#if 0
6869
    printf("     column already integral\n");
6870
    fflush(stdout);
6871
#endif
6872
  }
6873

6874
 done:
6875
  delete_interval(&interval);
6876
  xq_clear(&newval);
6877
}
6878

6879
#endif
6880

6881
/*
6882
 * Try to adjust the value of non-basic variable x to make x's column integral,
6883
 * while preserving all the bounds
6884
 * - x must be a non-basic, integer variable
6885
 * - x must have an integer value in the assignment
6886
 * - returns false if that's not possible
6887
 * - returns true and update the variable assignment otherwise
6888
 */
6889
static bool make_column_integral(simplex_solver_t *solver, thvar_t x) {
340✔
6890
  interval_t interval;
6891
  xrational_t newval;
6892
  arith_vartable_t *vtbl;
6893
  bool x_is_int, ok;
6894

6895
  vtbl = &solver->vtbl;
340✔
6896
  x_is_int = arith_var_is_int(vtbl, x);
340✔
6897
  ok = false;
340✔
6898

6899
  init_interval(&interval);
340✔
6900
  xq_init(&newval);
340✔
6901

6902
  // Get period
6903
  lcm_in_column(solver, &interval.period, x);
340✔
6904
  if (q_is_zero(&interval.period)) {
340✔
6905
    /*
6906
     * x is a non-integer variable
6907
     * and no integer basic variable depend on x
6908
     * no need to touch x.
6909
     */
6910
    assert(!x_is_int);
6911
    assert(column_is_integral(solver, x));
6912

6913
    ok = true;
×
6914
    goto done;
×
6915
  }
6916

6917
  // Get bounds
6918
  safe_adjust_interval(solver, &interval, x);
340✔
6919
  if (interval.has_lb) {
340✔
6920
    xq_add(&interval.lb, arith_var_value(vtbl, x));
331✔
6921
    if (x_is_int) {
331✔
6922
      xq_ceil(&interval.lb);
331✔
6923
    }
6924
  }
6925
  if (interval.has_ub) {
340✔
6926
    xq_add(&interval.ub, arith_var_value(vtbl, x));
320✔
6927
    if (x_is_int) {
320✔
6928
      xq_floor(&interval.ub);
320✔
6929
    }
6930
  }
6931

6932
#if 0
6933
  printf("---> make column integral: var = i!%"PRId32"\n", x);
6934
  if (interval.has_lb) {
6935
    printf("     lower bound: ");
6936
    xq_print(stdout, &interval.lb);
6937
    printf("\n");
6938
  } else {
6939
    printf("     no lower bound\n");
6940
  }
6941
  if (interval.has_ub) {
6942
    printf("     upper bound: ");
6943
    xq_print(stdout, &interval.ub);
6944
    printf("\n");
6945
  } else {
6946
    printf("     no upper bound\n");
6947
  }
6948
  printf("     period: ");
6949
  q_print(stdout, &interval.period);
6950
  printf("\n");
6951
  fflush(stdout);
6952
#endif
6953

6954
  if (empty_interval(&interval)) {
340✔
6955
    // no multiple of period between the two bounds
6956
#if 0
6957
    printf("     empty interval: can't fix\n");
6958
    fflush(stdout);
6959
#endif
6960

6961
    goto done;
×
6962
  }
6963

6964

6965
  xq_set(&newval, arith_var_value(vtbl, x));
340✔
6966
  xq_div(&newval, &interval.period);
340✔
6967
  xq_floor(&newval);
340✔
6968
  xq_mul(&newval, &interval.period);
340✔
6969

6970
  assert(xq_le(&newval, arith_var_value(vtbl, x)));
6971

6972
  /*
6973
   * newval is a multiple of period and we have
6974
   *   newval <= val[x] < newval + period
6975
   */
6976
  if (xq_eq(&newval, arith_var_value(vtbl, x))) {
340✔
6977
    // no change needed
6978
    assert(column_is_integral(solver, x));
6979

6980
#if 0
6981
    printf("     column already integral\n");
6982
    fflush(stdout);
6983
#endif
6984

6985
    ok = true;
211✔
6986
    goto done;
211✔
6987
  }
6988

6989
  // check whether newval works
6990
  if (!interval.has_lb || xq_le(&interval.lb, &newval)) {
129✔
6991
    // we can update x to newval
6992
    update_non_basic_var_value(solver, x, &newval);
14✔
6993
    simplex_set_bound_flags(solver, x);
14✔
6994

6995
    assert(column_is_integral(solver, x));
6996
    assert(int_heap_is_empty(&solver->infeasible_vars));
6997
    assert(value_satisfies_bounds(solver, x));
6998

6999
#if 0
7000
    printf("     update value to ");
7001
    xq_print(stdout, &newval);
7002
    printf("\n");
7003
    fflush(stdout);
7004
#endif
7005

7006
    ok = true;
14✔
7007
    goto done;
14✔
7008
  }
7009

7010
  // check whether newval + period works
7011
  xq_add_q(&newval, &interval.period);
115✔
7012
  if (!interval.has_ub || xq_ge(&interval.ub, &newval)) {
115✔
7013
    update_non_basic_var_value(solver, x, &newval);
28✔
7014
    simplex_set_bound_flags(solver, x);
28✔
7015

7016
    assert(column_is_integral(solver, x));
7017
    assert(int_heap_is_empty(&solver->infeasible_vars));
7018
    assert(value_satisfies_bounds(solver, x));
7019

7020
#if 0
7021
    printf("     update value to ");
7022
    xq_print(stdout, &newval);
7023
    printf("\n");
7024
    fflush(stdout);
7025
#endif
7026

7027
    ok = true;
28✔
7028
    goto done;
28✔
7029
  }
7030

7031
#if 0
7032
  printf("     can't fix\n");
7033
  fflush(stdout);
7034
#endif
7035

7036
 done:
87✔
7037
  delete_interval(&interval);
340✔
7038
  xq_clear(&newval);
340✔
7039

7040
  return ok;
340✔
7041
}
7042

7043

7044
/*
7045
 * Naive search
7046
 */
7047
static bool simplex_try_naive_integer_search(simplex_solver_t *solver) {
14✔
7048
  ivector_t aux;
7049
  arith_vartable_t *vtbl;
7050
  matrix_t *matrix;
7051
  uint32_t i, j, n;
7052
  thvar_t x;
7053
  bool ok;
7054

7055
#if 0
7056
  printf("\nNAIVE INTEGER SEARCH %"PRIu32" [dlevel = %"PRIu32", decisions = %"PRIu64"]\n\n",
7057
         solver->stats.num_make_intfeasible, solver->core->decision_level, solver->core->stats.decisions);
7058
  print_simplex_matrix(stdout, solver);
7059
  print_simplex_bounds(stdout, solver);
7060
  printf("\n");
7061
  print_simplex_assignment(stdout, solver);
7062
  printf("\n\n");
7063
  fflush(stdout);
7064
#endif
7065

7066
  vtbl = &solver->vtbl;
14✔
7067
  matrix = &solver->matrix;
14✔
7068

7069
  init_ivector(&aux, 20);
14✔
7070

7071
  n = vtbl->nvars;
14✔
7072
  ok = true;
14✔
7073

7074
  i = n;
14✔
7075
  while (i > 0) {
633✔
7076
    i --;
619✔
7077
    if (matrix_is_nonbasic_var(matrix, i) && matrix_column(matrix, i) != NULL) {
619✔
7078
      if (! make_column_integral(solver, i)) {
294✔
7079
        ivector_push(&aux, i);
44✔
7080
      }
7081
    }
7082
  }
7083

7084
  while (aux.size > 0 && ok) {
27✔
7085
    j = 0;
13✔
7086
    n = aux.size;
13✔
7087
    for (i=0; i<n; i++) {
59✔
7088
      x = aux.data[i];
46✔
7089
      if (!make_column_integral(solver, x)) {
46✔
7090
        aux.data[j] = x;
43✔
7091
        j ++;
43✔
7092
      }
7093
    }
7094
    ivector_shrink(&aux, j);
13✔
7095
    ok = (j < n);
13✔
7096
  }
7097

7098
  delete_ivector(&aux);
14✔
7099

7100
#if DEBUG
7101
  check_assignment(solver);
7102
  check_vartags(solver);
7103
#endif
7104

7105
  assert(!ok || simplex_assignment_integer_valid(solver));
7106

7107
#if 0
7108
  if (ok) {
7109
    printf("\nNAIVE INTEGER SEARCH WORKED\n\n");
7110
    print_simplex_matrix(stdout, solver);
7111
    print_simplex_bounds(stdout, solver);
7112
    printf("\n");
7113
    print_simplex_assignment(stdout, solver);
7114
    printf("\n\n");
7115
    fflush(stdout);
7116
  }
7117
#endif
7118

7119
  return ok;
14✔
7120
}
7121

7122

7123

7124
/*
7125
 * BRANCHING
7126
 */
7127

7128
#if TRACE_INTFEAS
7129
static void print_branch_candidates(FILE *f, simplex_solver_t *solver, ivector_t *v) {
7130
  uint32_t i, n;
7131

7132
  n = v->size;
7133
  for (i=0; i<n; i++) {
7134
    print_simplex_var_bounds(f, solver, v->data[i]);
7135
  }
7136
  fprintf(f, "\n");
7137
  fflush(f);
7138
}
7139

7140
#endif
7141

7142

7143
/*
7144
 * Collect all basic, integer variables that don't have an integer value
7145
 * in the current assignment
7146
 * - the result is stored in vector v (added to v)
7147
 */
7148
static void collect_non_integer_basic_vars(simplex_solver_t *solver, ivector_t *v) {
661✔
7149
  arith_vartable_t *vtbl;
7150
  uint32_t i, n;
7151

7152
  vtbl = &solver->vtbl;
661✔
7153
  n = vtbl->nvars;
661✔
7154
  for (i=0; i<n; i++) {
175,051✔
7155
    if (arith_var_is_int(vtbl, i) &&
343,318✔
7156
        matrix_is_basic_var(&solver->matrix, i) &&
168,928✔
7157
        ! arith_var_value_is_int(vtbl, i)) {
62,314✔
7158
      ivector_push(v, i);
7,477✔
7159
    }
7160
  }
7161
}
661✔
7162

7163

7164
/*
7165
 * Create branch & bound atom for a variable x.
7166
 * - if x has a lower and an upper bound: l <= x <= u,
7167
 *   we use the midpoint. The branch atom is (x >= ceil((l+u)/2)).
7168
 * - otherwise, we use (x >= ceil(value[x])).
7169
 */
7170
static void create_branch_atom(simplex_solver_t *solver, thvar_t x) {
577✔
7171
  xrational_t *bound;
7172
  int32_t new_idx, lb, ub;
7173
  literal_t l;
7174

7175
  assert(arith_var_is_int(&solver->vtbl, x) & ! arith_var_value_is_int(&solver->vtbl, x));
7176

7177
  bound = &solver->bound;
577✔
7178
  lb = arith_var_lower_index(&solver->vtbl, x);
577✔
7179
  ub = arith_var_upper_index(&solver->vtbl, x);
577✔
7180
  if (lb >= 0 && ub >= 0) {
577✔
7181
    xq_set(bound, solver->bstack.bound + lb);
372✔
7182
    xq_add(bound, solver->bstack.bound + ub);
372✔
7183
    q_set32(&solver->aux, 2);
372✔
7184
    xq_div(bound, &solver->aux);
372✔
7185
  } else {
7186
    xq_set(bound, arith_var_value(&solver->vtbl, x));
205✔
7187
  }
7188
  xq_ceil(bound);
577✔
7189
  assert(xq_is_integer(bound));
7190

7191
#if 0
7192
  printf("\n---> Branch & bound\n\n");
7193
  print_simplex_matrix(stdout, solver);
7194
  print_simplex_bounds(stdout, solver);
7195
  printf("\n");
7196
  print_simplex_assignment(stdout, solver);
7197
#endif
7198

7199
  l = get_literal_for_ge_atom(&solver->atbl, x, true, &bound->main, &new_idx);
577✔
7200
  solver->last_branch_atom = var_of(l);
577✔
7201

7202
  /*
7203
   * If support periodic calls to make_integer_feasible is enabled,
7204
   * then the branch atom may not be new.
7205
   */
7206
  // assert(new_idx >= 0);
7207
  if (new_idx >= 0) {
577✔
7208
    build_binary_lemmas_for_atom(solver, x, new_idx);
577✔
7209
    attach_atom_to_arith_var(&solver->vtbl, x, new_idx);
577✔
7210

7211
#if TRACE_BB || TRACE_INTFEAS
7212
    printf("---> Branch & bound: create ");
7213
    print_simplex_atomdef(stdout, solver, var_of(l));
7214
#endif
7215

7216
    solver->stats.num_branch_atoms ++;
577✔
7217
  }
7218
}
577✔
7219

7220

7221
/*
7222
 * Heuristic for selecting branching variable
7223
 * - try to select the most constrained variable
7224
 * - the score for x is (upper bound - lower bound) if that's small enough
7225
 * - return MAX_BRANCH_SCORE if x has zero or one bounds
7226
 */
7227
#define MAX_BRANCH_SCORE UINT32_MAX
7228
#define HALF_MAX_BRANCH_SCORE (UINT32_MAX/2)
7229

7230
#if 0
7231

7232
/*
7233
 * Simple version: use current bounds on x
7234
 */
7235
static uint32_t simplex_branch_score(simplex_solver_t *solver, thvar_t x) {
7236
  rational_t *diff;
7237
  int32_t l, u;
7238
  uint32_t s;
7239

7240
  diff = &solver->aux;
7241
  l = arith_var_lower_index(&solver->vtbl, x);
7242
  u = arith_var_upper_index(&solver->vtbl, x);
7243
  if (l < 0 && u < 0) {
7244
    return MAX_BRANCH_SCORE;
7245
  } else if (l < 0 || u < 0) {
7246
    return HALF_MAX_BRANCH_SCORE + 1;
7247
  }
7248
  q_set(diff, &solver->bstack.bound[u].main);
7249
  q_sub(diff, &solver->bstack.bound[l].main);
7250
  q_normalize(diff);
7251
  // diff = upper bound - lower bound
7252
  if (q_is_smallint(diff)) {
7253
    s = q_get_smallint(diff);
7254
    if (s < HALF_MAX_BRANCH_SCORE) {
7255
      return s;
7256
    }
7257
  }
7258

7259
  return HALF_MAX_BRANCH_SCORE;
7260
}
7261

7262
#else
7263

7264
/*
7265
 * New version: try to learn new bounds on x first (by bound strengthening)
7266
 */
7267

7268
/*
7269
 * Check whether x has an upper bound
7270
 * - if so, add the bound to diff
7271
 * - x must be an integer basic variable..
7272
 */
7273
static bool simplex_branch_var_add_ub(simplex_solver_t *solver, thvar_t x, rational_t *diff) {
7,477✔
7274
  xrational_t *bound;
7275
  xrational_t *ub;
7276
  bool derived, has_ub;
7277
  int32_t u;
7278

7279
  assert(arith_var_is_int(&solver->vtbl, x) && matrix_is_basic_var(&solver->matrix, x));
7280

7281
  ub = NULL; // Some versions of GCC give a warning otherwise
7,477✔
7282

7283
  bound = &solver->bound;
7,477✔
7284

7285
  derived = simplex_basic_var_has_derived_bound(solver, x, false);
7,477✔
7286
  if (derived) {
7,477✔
7287
    simplex_get_derived_bound_on_basic_var(solver, x, false, bound);
3,782✔
7288
    xq_floor(bound); // since x is an integer
3,782✔
7289
  }
7290

7291
  u = arith_var_upper_index(&solver->vtbl, x);
7,477✔
7292
  if (u >= 0) {
7,477✔
7293
    ub = solver->bstack.bound + u; // upper bound on x in the bound stack
3,723✔
7294
  }
7295

7296
  has_ub = false;
7,477✔
7297
  if (derived && (u < 0 || q_lt(&bound->main, &ub->main))) {
7,477✔
7298
    q_add(diff, &bound->main);
2,490✔
7299
    has_ub = true;
2,490✔
7300
  } else if (u >= 0) {
4,987✔
7301
    q_add(diff, &ub->main);
1,987✔
7302
    has_ub = true;
1,987✔
7303
  }
7304

7305
  return has_ub;
7,477✔
7306
}
7307

7308
/*
7309
 * Check whether x has a lower bound
7310
 * - if so, subtract the bound from diff
7311
 * - x must be an integer basic variable..
7312
 */
7313
static bool simplex_branch_var_sub_lb(simplex_solver_t *solver, thvar_t x, rational_t *diff) {
7,477✔
7314
  xrational_t *bound;
7315
  xrational_t *lb;
7316
  bool derived, has_lb;
7317
  int32_t l;
7318

7319
  assert(arith_var_is_int(&solver->vtbl, x) && matrix_is_basic_var(&solver->matrix, x));
7320

7321
  lb = NULL; // Some versions of GCC give a warning otherwise
7,477✔
7322

7323
  bound = &solver->bound;
7,477✔
7324

7325
  derived = simplex_basic_var_has_derived_bound(solver, x, true);
7,477✔
7326
  if (derived) {
7,477✔
7327
    simplex_get_derived_bound_on_basic_var(solver, x, true, bound);
4,273✔
7328
    xq_ceil(bound); // since x is an integer
4,273✔
7329
  }
7330

7331
  l = arith_var_lower_index(&solver->vtbl, x);
7,477✔
7332
  if (l >= 0) {
7,477✔
7333
    lb = solver->bstack.bound + l; // lower bound on x in the bound stack
4,700✔
7334
  }
7335

7336
  has_lb = false;
7,477✔
7337
  if (derived && (l < 0 || q_gt(&bound->main, &lb->main))) {
7,477✔
7338
    q_sub(diff, &bound->main);
2,648✔
7339
    has_lb = true;
2,648✔
7340
  } else if (l >= 0) {
4,829✔
7341
    q_sub(diff, &lb->main);
2,725✔
7342
    has_lb = true;
2,725✔
7343
  }
7344

7345
  return has_lb;
7,477✔
7346
}
7347

7348

7349
// new version: use derived bounds on x if available
7350
static uint32_t simplex_branch_score(simplex_solver_t *solver, thvar_t x) {
7,477✔
7351
  rational_t *diff;
7352
  bool has_lb, has_ub;
7353
  uint32_t s;
7354

7355
  diff = &solver->aux;
7,477✔
7356
  q_clear(diff);
7,477✔
7357
  has_ub = simplex_branch_var_add_ub(solver, x, diff);
7,477✔
7358
  assert(q_is_integer(diff));
7359
  has_lb = simplex_branch_var_sub_lb(solver, x, diff);
7,477✔
7360
  assert(q_is_integer(diff));
7361

7362
  if (has_ub && has_lb) {
7,477✔
7363
    q_normalize(diff);
3,111✔
7364
    /*
7365
     * The derived bounds could be in conflict (because we don't do
7366
     * exhaustive bound strengthening in strengthen bounds). In
7367
     * such a case, we have diff < 0. We give x a score of 0.
7368
     */
7369
    if (q_is_neg(diff)) {
3,111✔
7370
      s = 0;
4✔
7371
    } else if (q_is_smallint(diff)) {
3,107✔
7372
      s = q_get_smallint(diff);
2,916✔
7373
      if (s > HALF_MAX_BRANCH_SCORE) {
2,916✔
7374
        s = HALF_MAX_BRANCH_SCORE;
×
7375
      }
7376
    } else {
7377
      s = HALF_MAX_BRANCH_SCORE;
191✔
7378
    }
7379
  } else if (has_ub || has_lb) {
4,366✔
7380
    // at least one bound
7381
    s = HALF_MAX_BRANCH_SCORE + 1;
3,628✔
7382
  } else {
7383
    // no bounds
7384
    s = MAX_BRANCH_SCORE;
738✔
7385
  }
7386

7387
  return s;
7,477✔
7388
}
7389

7390
#endif
7391

7392

7393
/*
7394
 * Select a branch variable of v: pick the one with smallest score.
7395
 * Break ties randomly.
7396
 * - return the selected variable
7397
 * - score its score in *var_score
7398
 */
7399
static thvar_t select_branch_variable(simplex_solver_t *solver, ivector_t *v, uint32_t *var_score) {
656✔
7400
  uint32_t i, n, best_score, score, k;
7401
  thvar_t x, best_var;
7402

7403
#if TRACE_INTFEAS
7404
  printf("\nSELECT BRANCH VARIABLE\n\n");
7405
  print_simplex_matrix(stdout, solver);
7406
  print_simplex_bounds(stdout, solver);
7407
  printf("\n");
7408
  print_simplex_assignment(stdout, solver);
7409
  printf("\n\n");
7410
  fflush(stdout);
7411
#endif
7412

7413

7414
  n = v->size;
656✔
7415
  assert(n > 0);
7416

7417
  best_var = v->data[0];
656✔
7418
  best_score = simplex_branch_score(solver, best_var);
656✔
7419
  k = 1;
656✔
7420

7421
  for (i=1; i<n; i++) {
7,477✔
7422
    x = v->data[i];
6,821✔
7423
    score = simplex_branch_score(solver, x);
6,821✔
7424
    if (score < best_score) {
6,821✔
7425
      best_score = score;
892✔
7426
      best_var = x;
892✔
7427
      k = 1;
892✔
7428
    } else if (score == best_score) {
5,929✔
7429
      // break ties randomly
7430
      k ++;
3,447✔
7431
      if (random_uint(solver, k) == 0) {
3,447✔
7432
        best_var = x;
679✔
7433
      }
7434
    }
7435
  }
7436

7437
  *var_score = best_score;
656✔
7438
  return best_var;
656✔
7439
}
7440

7441

7442

7443

7444

7445
/*
7446
 * EXPLANATIONS FOR INTEGER UNSATISFIABILITY
7447
 */
7448

7449
/*
7450
 * Prepare to explain why variable x is fixed
7451
 * - add the constraint indices for x's lower and upper bound to vector q
7452
 */
7453
static void explain_fixed_variable(simplex_solver_t *solver, thvar_t x, ivector_t *q) {
1,753✔
7454
  int32_t k;
7455

7456
  assert(simplex_fixed_variable(solver, x));
7457

7458
  k = arith_var_lower_index(&solver->vtbl, x);
1,753✔
7459
  assert(k >= 0);
7460
  enqueue_cnstr_index(q, k, &solver->bstack);
1,753✔
7461

7462
  k = arith_var_upper_index(&solver->vtbl, x);
1,753✔
7463
  assert(k >= 0);
7464
  enqueue_cnstr_index(q, k, &solver->bstack);
1,753✔
7465
}
1,753✔
7466

7467

7468
/*
7469
 * Explain all fixed variables of a row
7470
 * - for each fixed var x, the lower index and upper index are pushed into q
7471
 *   (unless they are in q already)
7472
 */
7473
static void explain_fixed_variables_of_row(simplex_solver_t *solver, row_t *row, ivector_t *q) {
×
7474
  uint32_t i, n;
7475
  thvar_t x;
7476

7477
  n = row->size;
×
7478
  for (i=0; i<n; i++) {
×
7479
    x = row->data[i].c_idx;
×
7480
    if (x >= 0 && simplex_fixed_variable(solver, x)) {
×
7481
      explain_fixed_variable(solver, x, q);
×
7482
    }
7483
  }
7484
}
×
7485

7486

7487
/*
7488
 * Collect all the fixed variables that occur in a row of v
7489
 * - for each fixed variable x, its lower and upper index are pushed into q
7490
 */
7491
static void explain_fixed_variables_of_row_vector(simplex_solver_t *solver, ivector_t *v, ivector_t *q) {
×
7492
  matrix_t *matrix;
7493
  uint32_t i, n;
7494
  int32_t r;
7495

7496
  assert(v != q);
7497
  matrix = &solver->matrix;
×
7498
  n = v->size;
×
7499
  for (i=0; i<n; i++) {
×
7500
    r = v->data[i];
×
7501
    explain_fixed_variables_of_row(solver, matrix->row[r], q);
×
7502
  }
7503
}
×
7504

7505

7506

7507
/*
7508
 * Generate a conflict when the GCD test fails for a row
7509
 * - the explanation is stored in expl_vector
7510
 * - it's a set of literals that explain the fixed variables in the row
7511
 */
7512
static void build_gcd_conflict(simplex_solver_t *solver, row_t *row) {
×
7513
  ivector_t *v;
7514

7515
  // Collect bound indices in solver->expl_queue
7516
  v = &solver->expl_queue;
×
7517
  assert(v->size == 0);
7518
  explain_fixed_variables_of_row(solver, row, v);
×
7519

7520
  // Build the explanation into solver->expl_vector
7521
  v = &solver->expl_vector;
×
7522
  ivector_reset(v);
×
7523
  simplex_build_explanation(solver, v);
×
7524

7525
  // turn v into a clause and add null-literal as terminator
7526
  convert_expl_to_clause(v);
×
7527
  ivector_push(v, null_literal);
×
7528

7529
  // record v as a conflict
7530
  record_theory_conflict(solver->core, v->data);
×
7531

7532
  solver->stats.num_dioph_gcd_conflicts ++;
×
7533
}
×
7534

7535

7536

7537
/*
7538
 * Build a conflict from an integer-infeasible set of rows
7539
 * (returned by the diophantine solver)
7540
 * - v = vector of row indices
7541
 * - the conflict is a set of literals that explain the constant
7542
 *   in each of v (i.e., the fixed variables).
7543
 */
7544
static void build_dsolver_conflict(simplex_solver_t *solver, ivector_t *v) {
×
7545
  ivector_t *w;
7546

7547
  // Collect bound indices in solver->expl_queue
7548
  w = &solver->expl_queue;
×
7549
  assert(w->size == 0 && v != w);
7550
  explain_fixed_variables_of_row_vector(solver, v, w);
×
7551

7552
  // Build the explanation into solver->expl_vector
7553
  w = &solver->expl_vector;
×
7554
  ivector_reset(w);
×
7555
  simplex_build_explanation(solver, w);
×
7556

7557
  // turn expl into a clause then record the conflict
7558
  convert_expl_to_clause(w);
×
7559
  ivector_push(w, null_literal);
×
7560

7561
  record_theory_conflict(solver->core, w->data);
×
7562

7563
  solver->stats.num_dioph_conflicts ++;
×
7564
}
×
7565

7566

7567

7568

7569
/*
7570
 * BOUND STRENGTHENING
7571
 */
7572

7573
#ifndef NDEBUG
7574

7575
/*
7576
 * Check whether k is an element of q
7577
 */
7578
static bool in_vector(ivector_t *q, int32_t k) {
7579
  uint32_t i, n;
7580

7581
  n = q->size;
7582
  for (i=0; i<n; i++) {
7583
    if (q->data[i] == k) return true;
7584
  }
7585

7586
  return false;
7587
}
7588

7589
static bool not_in_vector(ivector_t *q, int32_t k) {
7590
  return ! in_vector(q, k);
7591
}
7592

7593
#endif
7594

7595
/*
7596
 * Clear the mark on all elements of q
7597
 */
7598
static void clear_antecedent_marks(simplex_solver_t *solver, ivector_t *q) {
×
7599
  arith_bstack_t *bstack;
7600
  uint32_t i, n;
7601
  int32_t k;
7602

7603
  bstack = &solver->bstack;
×
7604
  n = q->size;
×
7605
  for (i=0; i<n; i++) {
×
7606
    k = q->data[i];
×
7607
    arith_cnstr_clr_mark(bstack, k);
×
7608
  }
7609
}
×
7610

7611
/*
7612
 * Collect a set of bound indices that explain the general solution for
7613
 * variable x.
7614
 * - the diophantine solver returns a set of row indices as explanation for x
7615
 * - this function converts the set of rows to a set of bound indices (i.e.,
7616
 *   the lower/upper bound constraints on all the fixed variables in the
7617
 *   set of rows
7618
 * - the set of indices is added to vector q
7619
 */
7620
static void build_integer_solution_antecedent(simplex_solver_t *solver, thvar_t x, ivector_t *q) {
×
7621
  dsolver_t *dioph;
7622
  ivector_t *v;
7623

7624
  v = &solver->aux_vector;
×
7625
  dioph = solver->dsolver;
×
7626
  assert(v->size == 0 && v != q && dioph != NULL);
7627

7628
  // get the set of rows from the diophantine solver
7629
  dsolver_explain_solution(dioph, x, v);
×
7630

7631
  // collect the fixed variables of v into q
7632
  explain_fixed_variables_of_row_vector(solver, v, q);
×
7633

7634
  ivector_reset(v);
×
7635

7636
  /*
7637
   * HACK: the bstack marks are used to avoid adding the same
7638
   * bound index twice to q. They must be cleared here to avoid
7639
   * interference with conflict explanation if a conflict occurs.
7640
   */
7641
  clear_antecedent_marks(solver, q);
×
7642
}
×
7643

7644

7645

7646

7647
/*
7648
 * Attempt to strengthen the lower or upper bound on x
7649
 * using the general solution for x found by the diophantine solver
7650
 * - p must be the solution found for x
7651
 * - dioph must be non-null
7652
 * - return true if the strengthened bounds do not cause a conflict
7653
 * - return false otherwise
7654
 * Set the recheck flag if make_feasible is required after this
7655
 */
7656
static bool strengthen_bounds_on_integer_variable(simplex_solver_t *solver, dsolver_t *dioph, thvar_t x, polynomial_t *p) {
×
7657
  ivector_t *q;
7658
  rational_t *gcd, *aux, *constant;
7659
  xrational_t *bound;
7660
  int32_t k;
7661
  bool ok;
7662

7663
  gcd = &solver->gcd;
×
7664
  aux = &solver->aux;
×
7665
  constant = &solver->constant;
×
7666
  bound = &solver->bound;
×
7667

7668
  q = NULL;
×
7669
  ok = true;
×
7670

7671
  /*
7672
   * compute the gcd of all non-constant coefficients of p
7673
   * if gcd == 0, then p is a constant polynomial, which can happen only
7674
   * if x is a fixed variable in solver.
7675
   * if gcd == 1, we can't strengthen the bounds on x
7676
   */
7677
  monarray_gcd(p->mono, gcd);
×
7678
  assert(q_is_nonneg(gcd));
7679

7680
  if (q_cmp_int32(gcd, 1, 1) > 0) {
×
7681
    // get the constant of p
7682
    monarray_constant(p->mono, constant);
×
7683

7684
    //try to strengthen the lower bound on x
7685
    k = arith_var_lower_index(&solver->vtbl, x);
×
7686
    if (k >= 0) {
×
7687
      /*
7688
       * Let b = constant of p and l = current lower bound on x
7689
       * the strengthened bound is l' = b + d * ceil((l - b)/d)
7690
       * Let r = remainder of (l-b) divided by d
7691
       * if r = 0, then l' = l else l' = l + d - r (and l' > l)
7692
       */
7693
      assert(xq_is_integer(solver->bstack.bound + k));
7694
      q_set(aux, &solver->bstack.bound[k].main);
×
7695
      q_sub(aux, constant);
×
7696

7697
      q_integer_rem(aux, gcd);  // remainder of (l - b) divided by d
×
7698
      if (q_is_pos(aux)) {
×
7699

7700
        // the bound can be strengthened
7701
        xq_set(bound, solver->bstack.bound + k);
×
7702
        q_add(&bound->main, gcd);
×
7703
        q_sub(&bound->main, aux);
×
7704
        assert(xq_is_integer(bound));
7705

7706

7707
        // build the antecedent for x == p into aux_vector2
7708
        q = &solver->aux_vector2; // WARNING: we can't use expl_queue here
×
7709
        assert(q->size == 0);
7710
        build_integer_solution_antecedent(solver, x, q);
×
7711

7712
        // add bound index k at the end of q
7713
        assert(not_in_vector(q, k));
7714
        ivector_push(q, k);
×
7715

7716
        // add the new bound as a derived bound with antecedent q
7717
        ok = simplex_add_derived_lower_bound(solver, x, bound, q);
×
7718

7719
        ivector_pop(q); // remove k from q but keep the rest
×
7720

7721
        if (! ok) goto done;
×
7722
      }
7723
    }
7724

7725
    // try to strengthen the upper bound on x
7726
    k = arith_var_upper_index(&solver->vtbl, x);
×
7727
    if (k >= 0) {
×
7728
      /*
7729
       * The strengthened bound is u' = b + d * floor((u - b)/d)
7730
       * Let r = remainder of (u - b) divided by d
7731
       * If r = 0 then u' = u else u' = u - r
7732
       */
7733
      assert(xq_is_integer(solver->bstack.bound + k));
7734
      q_set(aux, &solver->bstack.bound[k].main);
×
7735
      q_sub(aux, constant);
×
7736
      q_integer_rem(aux, gcd);   // remainder of (u - b) divided by d
×
7737
      if (q_is_pos(aux)) {
×
7738
        // the bound can be strengthened
7739
        xq_set(bound, solver->bstack.bound + k);
×
7740
        q_sub(&bound->main, aux);
×
7741
        assert(xq_is_integer(bound));
7742

7743
        if (q == NULL) {
×
7744
          // explain x == p: build antecedent in q
7745
          q = &solver->aux_vector2; // can't use expl_queue or aux_vector
×
7746
          assert(q->size == 0);
7747
          build_integer_solution_antecedent(solver, x, q);
×
7748
        }
7749

7750
        // add bound index k at the end of q
7751
        assert(not_in_vector(q, k));
7752
        ivector_push(q, k);
×
7753

7754
        // add the new bound with antecedent q
7755
        ok = simplex_add_derived_upper_bound(solver, x, bound, q);
×
7756

7757
        ivector_pop(q); // remove k for cleanup
×
7758
      }
7759
    }
7760
  }
7761

7762
 done:
×
7763
  if (q != NULL) {
×
7764
    ivector_reset(q);
×
7765
  }
7766

7767
  return ok;
×
7768
}
7769

7770

7771

7772
/*
7773
 * Strengthen the bounds on all integer variables
7774
 * - dsolver = diophantine solver where the general solution was computed
7775
 * - return false if a conflict is detected (and record the conflict in the core)
7776
 * - return true otherwise
7777
 * - set solver->recheck to true if make_feasible is needed
7778
 */
7779
static bool strengthen_integer_bounds(simplex_solver_t *solver, dsolver_t *dioph) {
×
7780
  polynomial_t *p;
7781
  uint32_t i, n;
7782

7783
  assert(dioph->status == DSOLVER_SOLVED_SAT);
7784

7785
  n = dioph->nvars;
×
7786
  for (i=1; i<n; i++) {  //skip 0 == const_idx
×
7787
    p = dsolver_gen_sol(dioph, i);
×
7788
    if (p != NULL) {
×
7789
      if (! strengthen_bounds_on_integer_variable(solver, dioph, i, p)) {
×
7790
        // conflict detected: exit
7791
        solver->stats.num_dioph_bound_conflicts ++;
×
7792
        return false;
×
7793
      }
7794
    }
7795
  }
7796

7797
  return true;
×
7798
}
7799

7800

7801

7802

7803
/*
7804
 * TEST INTEGER FEASIBILITY USING THE DIOPHANTINE SUBSOLVER
7805
 */
7806

7807
/*
7808
 * Check whether row contains only integer (or non-integer but fixed variables)
7809
 */
7810
static bool matrix_row_is_integral(simplex_solver_t *solver, row_t *row) {
4,744✔
7811
  return find_real_var_in_row(solver, row) < 0;
4,744✔
7812
}
7813

7814
/*
7815
 * Add a row of the tableau to the subsolver
7816
 * - r = the row index in tableau
7817
 * - dioph = the subsolver
7818
 * - all variables of row must be fixed or integer variables
7819
 * - return true if the row is consistent, false otherwise
7820
 */
7821
static bool simplex_dsolver_add_row(simplex_solver_t *solver, dsolver_t *dioph, int32_t r, row_t *row) {
×
7822
  uint32_t i, n;
7823
  int32_t x;
7824

7825
  assert(matrix_row_is_integral(solver, row));
7826

7827
  (void) dsolver_row_open(dioph, r);
×
7828

7829
  n = row->size;
×
7830
  for (i=0; i<n; i++) {
×
7831
    x = row->data[i].c_idx;
×
7832
    if (x >= 0) {
×
7833
      if (simplex_fixed_variable(solver, x)) {
×
7834
        dsolver_row_addmul_constant(dioph, &row->data[i].coeff, fixed_variable_value(solver, x));
×
7835
      } else {
7836
        dsolver_row_add_mono(dioph, &row->data[i].coeff, x);
×
7837
      }
7838
    }
7839
  }
7840
  return dsolver_row_close(dioph);
×
7841
}
7842

7843

7844

7845

7846
/*
7847
 * Run the diophantine system solver on the current tableau
7848
 * - return false if a conflict is found
7849
 * - return true otherwise
7850
 * - set solver->recheck to true if bound-strengthening requires a call to make_feasible
7851
 *
7852
 * Heuristics:
7853
 * - dsolver_is_feasible can be very slow and expensive.
7854
 * - we call it only if solver->enable_dfeas is true
7855
 * - if dsolver_is_feasible is interrupted or gives up, we set enable_dfeas to false
7856
 *   (so dsolver_is_feasible will be skipped on the next call).
7857
 */
7858
static bool simplex_dsolver_check(simplex_solver_t *solver) {
×
7859
  dsolver_t *dioph;
7860
  matrix_t *matrix;
7861
  row_t *row;
7862
  ivector_t *v;
7863
  uint32_t i, n;
7864
  bool pure_integer;
7865

7866
  dioph = simplex_get_dsolver(solver);
×
7867
  reset_dsolver(dioph);
×
7868

7869
  pure_integer = ! simplex_is_mixed_system(solver);
×
7870

7871
  matrix = &solver->matrix;
×
7872
  n = matrix->nrows;
×
7873
  for (i=0; i<n; i++) {
×
7874
    row = matrix->row[i];
×
7875
    if (pure_integer || matrix_row_is_integral(solver, row)) {
×
7876
      if (! simplex_dsolver_add_row(solver, dioph, i, row)) {
×
7877
        // row i is not integer feasible (GCD test failed)
7878
        build_gcd_conflict(solver, row);
×
7879
        return false;
×
7880
      }
7881
    }
7882
  }
7883

7884
  /*
7885
   * Don't call dsolver_is_feasible if enable_dfeas is false.
7886
   */
7887
  if (! solver->enable_dfeas) return true;
×
7888
  //  if (dioph->nvars > 2000) return true;
7889

7890
  solver->stats.num_dioph_checks ++;
×
7891

7892
  // run the diophantine solver
7893
  dsolver_simplify(dioph);
×
7894
  switch (dsolver_is_feasible(dioph)) {
×
7895
  case DSOLVER_SOLVED_UNSAT:
×
7896
    /*
7897
     * get the set of unsat rows in aux_vector
7898
     * then build a conflict for these rows
7899
     */
7900
    v = &solver->aux_vector;
×
7901
    assert(v->size == 0);
7902
    dsolver_unsat_rows(dioph, v);
×
7903
    build_dsolver_conflict(solver, v);
×
7904
    ivector_reset(v);
×
7905

7906
    return false;
×
7907

7908
  case DSOLVER_SOLVED_SAT:
×
7909
    // Try to strengthen the bounds
7910
    dsolver_build_general_solution(dioph);
×
7911
    //  dsolver_print_gen_solution(stdout, dioph);
7912
    //  fflush(stdout);
7913
    return strengthen_integer_bounds(solver, dioph);
×
7914

7915
  case DSOLVER_INTERRUPTED:
×
7916
  case DSOLVER_UNSOLVED:
7917
    solver->enable_dfeas = false;
×
7918
    return true;
×
7919

7920
  default:
×
7921
    assert(false);
7922
    return true;
×
7923
  }
7924
}
7925

7926

7927
/*
7928
 * CHEAPER INTEGRALITY CONSTRAINTS
7929
 */
7930

7931
#if 0
7932
/*
7933
 * Print a list of variables
7934
 */
7935
static void show_vars(simplex_solver_t *solver, thvar_t *a, uint32_t n) {
7936
  uint32_t i;
7937
  thvar_t x;
7938

7939
  if (n == 0) {
7940
    printf("[]");
7941
  } else {
7942
    x = a[0];
7943
    printf("[");
7944
    print_simplex_var(stdout, solver, x);
7945
    for (i=1; i<n; i++) {
7946
      x = a[i];
7947
      printf(" ");
7948
      print_simplex_var(stdout, solver, x);
7949
    }
7950
    printf("]");
7951
  }
7952
}
7953

7954
static void show_array_of_bound_ids(ivector_t *a) {
7955
  uint32_t i, n;
7956

7957
  n = a->size;
7958
  if (n == 0) {
7959
    printf("[]");
7960
  } else {
7961
    printf("[%"PRId32, a->data[0]);
7962
    for (i=1; i<n; i++) {
7963
      printf(" %"PRId32, a->data[i]);
7964
    }
7965
    printf("]");
7966
  }
7967

7968
}
7969

7970
#endif
7971

7972
/*
7973
 * Conflict explanation when an integrality constraint is not feasible.
7974
 * - the explanation is a list of fixed variables stored in array a
7975
 * - n = number of elements of this array.
7976
 */
7977
static void build_integrality_conflict(simplex_solver_t *solver, thvar_t *a, uint32_t n) {
120✔
7978
  ivector_t *v;
7979
  uint32_t i;
7980

7981
  // Collect bound indices in solver->expl_queue
7982
  v = &solver->expl_queue;
120✔
7983
  assert(v->size == 0);
7984

7985
  for (i=0; i<n; i++) {
1,873✔
7986
    explain_fixed_variable(solver, a[i], v);
1,753✔
7987
  }
7988

7989
  // Build the explanation into solver->expl_vector
7990
  v = &solver->expl_vector;
120✔
7991
  ivector_reset(v);
120✔
7992
  simplex_build_explanation(solver, v);
120✔
7993

7994
  // turn v into a clause and add null-literal as terminator
7995
  convert_expl_to_clause(v);
120✔
7996
  ivector_push(v, null_literal);
120✔
7997

7998
  // record v as a conflict
7999
  record_theory_conflict(solver->core, v->data);
120✔
8000
}
120✔
8001

8002

8003
/*
8004
 * Build the antecedent for a bound derived from an integer constraint.
8005
 * An integer constraint may imply a bound on x when we know that
8006
 *  (x - T) is a multiple of Q.
8007
 * The integrality constraint code computes the relevant Q and T for x.
8008
 * The constraint "Q divides (x - T)" has an explanation given as
8009
 * a set of fixed variables.
8010
 *
8011
 * This function collects the bound indices that explain why these
8012
 * variables are fixed.
8013
 *
8014
 * Input:
8015
 * - a = array of n fixed variables
8016
 * - v = vector in which the bounds are added.
8017
 */
8018
static void collect_fixed_vars_antecedents(simplex_solver_t *solver, thvar_t *a, uint32_t n, ivector_t *v) {
2,517✔
8019
  uint32_t i;
8020
  thvar_t x;
8021
  int32_t l, u;
8022

8023
  assert(a != v->data);
8024

8025
  for (i=0; i<n; i++) {
42,029✔
8026
    x = a[i];
39,512✔
8027
    assert(simplex_fixed_variable(solver, x));
8028

8029
    l = arith_var_lower_index(&solver->vtbl, x);
39,512✔
8030
    u = arith_var_upper_index(&solver->vtbl, x);
39,512✔
8031
    assert(l >= 0 && u >= 0);
8032

8033
    ivector_push(v, l);
39,512✔
8034
    ivector_push(v, u);
39,512✔
8035
  }
8036
}
2,517✔
8037

8038

8039
/*
8040
 * Attempt to strengthen the bounds on x, when we know
8041
 * x = period * n + phase for some integer n.
8042
 * - v = explanation for this constraint (as an array of fixed variables)
8043
 * - returns false if the new bound causes a conflict
8044
 * - returns true otherwise (may also set the global flag solver->recheck to true)
8045
 */
8046
static bool simplex_integer_derived_bounds(simplex_solver_t *solver, thvar_t x,
45,448✔
8047
                                           rational_t *period, rational_t *phase, ivector_t *v) {
8048
  ivector_t *antecedents;
8049
  xrational_t *bound;
8050
  rational_t *aux;
8051
  int32_t k;
8052
  bool ok, antecedents_ready;
8053

8054
  assert(q_is_pos(period));
8055
  assert(arith_var_is_int(&solver->vtbl, x));
8056

8057
  antecedents = &solver->aux_vector;
45,448✔
8058
  assert(antecedents->size == 0 && antecedents != v);
8059
  antecedents_ready = false;
45,448✔
8060

8061
  bound = &solver->bound;
45,448✔
8062
  aux = &solver->aux;
45,448✔
8063
  ok = true;
45,448✔
8064

8065
  k = arith_var_lower_index(&solver->vtbl, x);
45,448✔
8066
  if (k >= 0) {
45,448✔
8067
    /*
8068
     * Let L = current lower bound on x, P = period, and B = phase.
8069
     * We have:
8070
     *  1) x >= L
8071
     *  2) there's an integer k such that (x = B + P k).
8072
     * This implies
8073
     *    (B + P k >= L) so k >= (L - B)/P and then k >= ceil((L - B)/P)
8074
     * This gives the derived bound
8075
     *   x >= B + P * ceil((L - B)/P).
8076
     *
8077
     * If (L - B)/P is not an integer, then B + P * ceil((L - B)/P) > L,
8078
     * so the derived bound is stronger than L.
8079
     *
8080
     */
8081
    assert(xq_is_integer(solver->bstack.bound + k)); // because x is an integer
8082
    q_set(aux, &solver->bstack.bound[k].main);  // L
32,569✔
8083
    q_sub(aux, phase);
32,569✔
8084
    q_div(aux, period);  // aux is (L - B)/P
32,569✔
8085
    q_normalize(aux);
32,569✔
8086
    if (! q_is_integer(aux)) {
32,569✔
8087
      /*
8088
       * strengthen the lower bound on x
8089
       */
8090
      q_ceil(aux);
1,898✔
8091
      q_mul(aux, period);
1,898✔
8092
      q_add(aux, phase);   // aux is B + P * ceil((L - B)/P)
1,898✔
8093
      q_normalize(aux);
1,898✔
8094
      assert(q_gt(aux, &solver->bstack.bound[k].main));
8095

8096
#if 0
8097
      printf("---> Strengthening lower bound on ");
8098
      print_simplex_var(stdout, solver, x);
8099
      printf("\n");
8100
      printf("  current value: ");
8101
      print_simplex_var_value(stdout, solver, x);
8102
      printf("\n");
8103
      printf("  current bounds: ");
8104
      print_simplex_var_bounds(stdout, solver, x);
8105
      printf("  period: ");
8106
      q_print(stdout, period);
8107
      printf("\n");
8108
      printf("  phase: ");
8109
      q_print(stdout, phase);
8110
      printf("\n");
8111
      printf("  derived lower bound: ");
8112
      q_print(stdout, aux);
8113
      printf("\n");
8114
#endif
8115
      /*
8116
       * Antecedents for the new bound:
8117
       * - we have (x >= Current bound) AND (x = B + P * some integer) => (x >= New bound)
8118
       * - and fixed vars => (x = B + P * some integer)
8119
       * So the antecendents for the new bounds are
8120
       * - the antecedents for the fixed vars + the current bound
8121
       */
8122
      collect_fixed_vars_antecedents(solver, v->data, v->size, antecedents);
1,898✔
8123
      antecedents_ready = true;
1,898✔
8124
      ivector_push(antecedents, k); // index for (x >= current bound)
1,898✔
8125
      xq_set_q(bound, aux);
1,898✔
8126
      ok = simplex_add_derived_lower_bound(solver, x, bound, antecedents);
1,898✔
8127

8128
#if 0
8129
      printf("  new bounds: ");
8130
      print_simplex_var_bounds(stdout, solver, x);
8131
      printf("  antecedents: ");
8132
      show_array_of_bound_ids(antecedents);
8133
      printf("\n\n");
8134
      fflush(stdout);
8135

8136
#endif
8137
      /*
8138
       * cleanup the antecedents vector: we want to remove the index k
8139
       * since the vector may be used again if we can strengthen the
8140
       * upper bound on x
8141
       */
8142
      ivector_pop(antecedents);
1,898✔
8143
      if (! ok) goto done;
1,898✔
8144

8145
    }
8146
  }
8147

8148
  k = arith_var_upper_index(&solver->vtbl, x);
45,142✔
8149
  if (k >= 0) {
45,142✔
8150
    /*
8151
     * Let U = current upper bound x. We have
8152
     *  1) x <= U
8153
     *  2) x = B + P k
8154
     * So  k <= floor((U - B)/P).
8155
     *
8156
     * The derived bound is then x <= B + P * floor((U - B)/P).
8157
     * If that's less than U, we add it as upper bound on x.
8158
     */
8159
    assert(xq_is_integer(solver->bstack.bound + k));
8160
    q_set(aux, &solver->bstack.bound[k].main); // U
30,692✔
8161
    q_sub(aux, phase);
30,692✔
8162
    q_div(aux, period); // aux is (U - B)/P
30,692✔
8163
    q_normalize(aux);
30,692✔
8164
    if (!q_is_integer(aux)) {
30,692✔
8165
      /*
8166
       * Derived bound smaller than U
8167
       */
8168
      q_floor(aux);
1,005✔
8169
      q_mul(aux, period);
1,005✔
8170
      q_add(aux, phase);
1,005✔
8171
      q_normalize(aux);
1,005✔
8172
      assert(q_lt(aux, &solver->bstack.bound[k].main));
8173

8174
#if 0
8175
      printf("---> Strengthening upper bound on ");
8176
      print_simplex_var(stdout, solver, x);
8177
      printf("\n");
8178
      printf("  current value: ");
8179
      print_simplex_var_value(stdout, solver, x);
8180
      printf("\n");
8181
      printf("  current_bounds: ");
8182
      print_simplex_var_bounds(stdout, solver, x);
8183
      printf("  period: ");
8184
      q_print(stdout, period);
8185
      printf("\n");
8186
      printf("  phase: ");
8187
      q_print(stdout, phase);
8188
      printf("\n");
8189
      printf("  derived upper bound: ");
8190
      q_print(stdout, aux);
8191
      printf("\n");
8192
#endif
8193

8194
      /*
8195
       * As above: antecedents for the derived bounds = current bound +
8196
       * antecedents for the fixed variables.
8197
       */
8198
      if (!antecedents_ready) {
1,005✔
8199
        collect_fixed_vars_antecedents(solver, v->data, v->size, antecedents);
619✔
8200
      }
8201
      ivector_push(antecedents, k);
1,005✔
8202

8203
      xq_set_q(bound, aux);
1,005✔
8204
      ok = simplex_add_derived_upper_bound(solver, x, bound, antecedents);
1,005✔
8205

8206
#if 0
8207
      printf("  new bounds: ");
8208
      print_simplex_var_bounds(stdout, solver, x);
8209
      printf("  antecedents: ");
8210
      show_array_of_bound_ids(antecedents);
8211
      printf("\n\n");
8212
      fflush(stdout);
8213

8214
#endif
8215
    }
8216
  }
8217

8218
 done:
44,137✔
8219
  // Must always clean up the aux_vector
8220
  ivector_reset(antecedents);
45,448✔
8221

8222
#if 0
8223
  if (!ok) {
8224
    printf("---> Bound conflict\n\n");
8225
    fflush(stdout);
8226
  }
8227
#endif
8228

8229
  return ok;
45,448✔
8230
}
8231

8232

8233

8234
#ifndef NDEBUG
8235
/*
8236
 * Some checks on period/phase computations for variable k
8237
 */
8238

8239
/*
8240
 * Sum of all fixed terms
8241
 */
8242
static void sum_of_fixed_terms(int_constraint_t *cnstr, rational_t *sum) {
8243
  uint32_t i, n;
8244

8245
  q_clear(sum);
8246
  n = cnstr->fixed_nterms;
8247
  for (i=0; i<n; i++) {
8248
    q_addmul(sum, cnstr->fixed_val + i, &cnstr->fixed_sum[i].coeff);
8249
  }
8250
}
8251

8252
/*
8253
 * Get a value of of variable k that satisfies the constraints.
8254
 * - the constraint is (a * var[k] + other vars + fixed sum) is an integer
8255
 * - so a possible solution is to set all other vars to zero
8256
 * - and var[k] is (z - fixed_sum)/a
8257
 */
8258
static void get_solution_for_var(int_constraint_t *cnstr, uint32_t k, rational_t *val, int32_t z) {
8259
  rational_t qz;
8260

8261
  assert(k < cnstr->sum_nterms);
8262

8263
  q_init(&qz);
8264

8265
  q_set32(&qz, z);
8266
  sum_of_fixed_terms(cnstr, val);
8267
  q_neg(val);
8268
  q_add(val, &qz);
8269
  q_div(val, &cnstr->sum[k].coeff);
8270

8271
  q_clear(&qz);
8272
}
8273

8274

8275
/*
8276
 * Check whether cnstr => var[k] = period * integer + phase holds
8277
 */
8278
static bool plausible_period_and_phase(int_constraint_t *cnstr, uint32_t k, rational_t *period, rational_t *phase) {
8279
  rational_t test_val;
8280
  int32_t z;
8281

8282
  q_init(&test_val);
8283

8284
  for (z = -20; z <= 20; z++) {
8285
    get_solution_for_var(cnstr, k, &test_val, z);
8286
    q_sub(&test_val, phase);  // value - phase
8287
    if (! q_divides(period, &test_val)) {
8288

8289
#if 0
8290
      printf("--- plausible_period_and_phase failed ---\n");
8291
      printf("period = ");
8292
      q_print(stdout, period);
8293
      printf("\n");
8294
      printf("phase = ");
8295
      q_print(stdout, phase);
8296
      printf("\n");
8297
      printf("test z = %"PRId32"\n", z);
8298
      printf("test_val = ");
8299
      q_print(stdout, &test_val);
8300
      printf("\n\n");
8301
      fflush(stdout);
8302

8303
      assert(false);
8304
#endif
8305

8306
      return false;
8307
    }
8308
  }
8309

8310
  q_clear(&test_val);
8311

8312
  return true;
8313
}
8314

8315
#endif
8316

8317

8318
/*
8319
 * Process a constraint stored in checker
8320
 * - first check feasibility
8321
 * - it this succeeds, try bound strengthening on all integer variables
8322
 *   in checker that are not fixed.
8323
 */
8324
static bool process_integrality_constraint(simplex_solver_t *solver, int_constraint_t *checker) {
9,662✔
8325
  ivector_t v;
8326
  rational_t *p, *q;
8327
  uint32_t i, n;
8328
  thvar_t x;
8329
  bool feasible;
8330

8331
#if 0
8332
  printf("==== Integrality constraint ====\n");
8333
  print_int_constraint(stdout, solver, checker);
8334
  fflush(stdout);
8335

8336
  init_ivector(&v, 10);
8337
  feasible = int_constraint_is_feasible(checker, &v);
8338
  if (feasible) {
8339
    printf("Feasible\n");
8340
  } else {
8341
    printf("Not feasible\n");
8342
    printf("Conflict vars: ");
8343
    show_vars(solver, v.data, v.size);
8344
    printf("\n");
8345
    fflush(stdout);
8346
  }
8347

8348
  if (feasible) {
8349
    n = int_constraint_num_terms(checker);
8350
    for (i=0; i<n; i++) {
8351
      ivector_reset(&v);
8352
      int_constraint_period_of_var(checker, i, &v);
8353
      x = int_constraint_get_var(checker, i);
8354
      p = int_constraint_period(checker);
8355
      q = int_constraint_phase(checker);
8356
      printf("Variable ");
8357
      print_simplex_var(stdout, solver, x);
8358
      printf(": period = ");
8359
      q_print(stdout, p);
8360
      printf(", phase = ");
8361
      q_print(stdout, q);
8362
      printf("\n");
8363
      printf("  antecedents: ");
8364
      show_vars(solver, v.data, v.size);
8365
      printf("\n");
8366
    }
8367
  }
8368

8369
  delete_ivector(&v);
8370

8371
  printf("=====\n\n");
8372
  fflush(stdout);
8373
#endif
8374

8375
  init_ivector(&v, 10);
9,662✔
8376
  feasible = int_constraint_is_feasible(checker, &v);
9,662✔
8377
  if (!feasible) {
9,662✔
8378
    build_integrality_conflict(solver, v.data, v.size);
120✔
8379
    trace_printf(solver->core->trace, 10, "(unsat by integrality test)\n");
120✔
8380
    solver->stats.num_itest_conflicts ++;
120✔
8381

8382
  } else {
8383

8384
    // Try bound strengthening
8385
    n = int_constraint_num_terms(checker);
9,542✔
8386
    for (i=0; i<n; i++) {
54,822✔
8387
      x = int_constraint_get_var(checker, i);
45,651✔
8388
      // if x is free, there's no bound to improve
8389
      if (! simplex_free_variable(solver, x)) {
45,651✔
8390
        ivector_reset(&v);
45,448✔
8391
        int_constraint_period_of_var(checker, i, &v);
45,448✔
8392
        p = int_constraint_period(checker);
45,448✔
8393
        q = int_constraint_phase(checker);
45,448✔
8394
        assert(plausible_period_and_phase(checker, i, p, q));
8395

8396
        feasible = simplex_integer_derived_bounds(solver, x, p, q, &v);
45,448✔
8397
        if (!feasible) {
45,448✔
8398
          solver->stats.num_itest_bound_conflicts ++;
371✔
8399
          trace_printf(solver->core->trace, 10, "(unsat by integer bound strengthening)\n");
371✔
8400
          goto done;
371✔
8401
        }
8402
      }
8403
    }
8404

8405
  }
8406

8407
 done:
9,171✔
8408
  delete_ivector(&v);
9,662✔
8409

8410
  return feasible;
9,662✔
8411
}
8412

8413

8414
/*
8415
 * Go through a row and extract an integrality constraint from it.
8416
 * - all variables in the row must be integer or fixed
8417
 */
8418
static bool test_integrality_in_row(simplex_solver_t *solver, int_constraint_t *checker, row_t *row) {
9,662✔
8419
  arith_vartable_t *vtbl;
8420
  uint32_t i, n;
8421
  thvar_t x;
8422
  rational_t *q;
8423

8424
  vtbl = &solver->vtbl;
9,662✔
8425
  n = row->size;
9,662✔
8426
  for (i=0; i<n; i++) {
183,205✔
8427
    x = row->data[i].c_idx;
173,543✔
8428
    if (x >= 0) {
173,543✔
8429
      q = &row->data[i].coeff;
158,239✔
8430
      if (arith_var_is_int(vtbl, x)) {
158,239✔
8431
        /*
8432
         * Integer variable: we skip it if it has an integer coefficient.
8433
         */
8434
        if (!q_is_integer(q)) {
158,239✔
8435
          if (simplex_fixed_variable(solver, x)) {
138,232✔
8436
            // x is fixed
8437
            int_constraint_add_fixed_mono(checker, q, x, true, fixed_variable_value(solver, x));
92,478✔
8438
          } else {
8439
            // x is not fixed
8440
            int_constraint_add_mono(checker, q, x);
45,754✔
8441
          }
8442
        }
8443
      } else {
8444
        /*
8445
         * Not an integer variable: it must be fixed
8446
         */
8447
        assert(simplex_fixed_variable(solver, x));
8448
        int_constraint_add_fixed_mono(checker, q, x, false, fixed_variable_value(solver, x));
×
8449
      }
8450
    }
8451
  }
8452

8453
  return process_integrality_constraint(solver, checker);
9,662✔
8454
}
8455

8456
static bool simplex_integrality_check(simplex_solver_t *solver) {
1,239✔
8457
  int_constraint_t checker;
8458
  matrix_t *matrix;
8459
  arith_vartable_t *vtbl;
8460
  row_t *row;
8461
  thvar_t x;
8462
  uint32_t i, n;
8463
  bool feasible;
8464
  bool pure_integer;
8465

8466
  feasible = true;
1,239✔
8467

8468
  pure_integer = ! simplex_is_mixed_system(solver);
1,239✔
8469

8470
  init_int_constraint(&checker);
1,239✔
8471
  vtbl = &solver->vtbl;
1,239✔
8472
  matrix = &solver->matrix;
1,239✔
8473
  n = matrix->nrows;
1,239✔
8474
  for (i=0; i<n; i++) {
76,189✔
8475
    x = matrix_basic_var(matrix, i);
75,441✔
8476
    if (arith_var_is_int(vtbl, x) && !arith_var_value_is_int(vtbl, x)) {
75,441✔
8477
      row = matrix->row[i];
9,999✔
8478
      if (pure_integer || matrix_row_is_integral(solver, row)) {
9,999✔
8479
        feasible = test_integrality_in_row(solver, &checker, row);
9,662✔
8480
        if (! feasible) {
9,662✔
8481
          break;
491✔
8482
        }
8483
        reset_int_constraint(&checker);
9,171✔
8484
      }
8485
    }
8486
  }
8487

8488
  delete_int_constraint(&checker);
1,239✔
8489

8490
  return feasible;
1,239✔
8491
}
8492

8493

8494

8495
#if 1
8496

8497
// NOT READY FOR PRIME TIME.
8498

8499
#include "solvers/simplex/gomory_cuts.h"
8500

8501
/*
8502
 * MIXED-INTEGER GOMORY CUTS
8503
 */
8504

8505
/*
8506
 * When we create atoms on the fly for an existing variable,
8507
 * we reset the prop_ptr so that we can propagate the new atom if necessary.
8508
 * - we reset the pointer to what's saved for the current decision level in the undo stack
8509
 */
8510
static void reset_prop_ptr(simplex_solver_t *solver) {
40✔
8511
  assert(solver->stack.top == solver->decision_level + 1);
8512
  solver->bstack.prop_ptr = solver->stack.data[solver->decision_level].n_bounds;
40✔
8513
  /* if (solver->base_level == 0) { */
8514
  /*   assert(solver->trail_stack.top == 0); */
8515
  /*   solver->bstack.prop_ptr = 0; */
8516
  /* } else { */
8517
  /*   assert(solver->trail_stack.top > 0); */
8518
  /*   solver->bstack.prop_ptr = arith_trail_top(&solver->trail_stack)->bound_ptr; */
8519
  /* } */
8520
}
40✔
8521

8522
/*
8523
 * Build atom (x >= c) or (x <= c) on the fly
8524
 * - flag is_int indicates whether x is an integer variable
8525
 */
8526
static literal_t mk_dynamic_ge_atom(simplex_solver_t *solver, thvar_t x, bool is_int, rational_t *c) {
97✔
8527
  int32_t new_idx;
8528
  literal_t l;
8529

8530
  assert(x != const_idx);
8531

8532
  l = get_literal_for_ge_atom(&solver->atbl, x, is_int, c, &new_idx);
97✔
8533
  if (new_idx >= 0) {
97✔
8534
    build_binary_lemmas_for_atom(solver, x, new_idx);
95✔
8535
    attach_atom_to_arith_var(&solver->vtbl, x, new_idx);
95✔
8536
  }
8537
  return l;
97✔
8538
}
8539

8540
static literal_t mk_dynamic_le_atom(simplex_solver_t *solver, thvar_t x, bool is_int, rational_t *c) {
22✔
8541
  int32_t new_idx;
8542
  literal_t l;
8543

8544
  assert(x != const_idx);
8545

8546
  l = get_literal_for_le_atom(&solver->atbl, x, is_int, c, &new_idx);
22✔
8547
  if (new_idx >= 0) {
22✔
8548
    build_binary_lemmas_for_atom(solver, x, new_idx);
20✔
8549
    attach_atom_to_arith_var(&solver->vtbl, x, new_idx);
20✔
8550
  }
8551
  return l;
22✔
8552
}
8553

8554

8555
/*
8556
 * Build an atom equivalent to p >= 0.
8557
 */
8558
static literal_t mk_gomory_atom(simplex_solver_t *solver) {
79✔
8559
  poly_buffer_t *b;
8560
  bool negated, is_int;
8561
  thvar_t x;
8562

8563
  b = &solver->buffer;
79✔
8564

8565
  if (poly_buffer_is_zero(b) || poly_buffer_is_pos_constant(b)) {
79✔
8566
    reset_poly_buffer(b);
×
8567
    return true_literal;
×
8568
  }
8569

8570
  if (poly_buffer_is_neg_constant(b)) {
79✔
8571
    reset_poly_buffer(b);
×
8572
    return false_literal;
×
8573
  }
8574

8575
#if 0
8576
  is_int = all_integer_vars(solver);
8577
  if (is_int) {
8578
    negated = poly_buffer_make_nonconstant_integral(b);
8579
    x = decompose_and_get_dynamic_var(solver);
8580
    assert(arith_var_is_int(&solver->vtbl, x));
8581
    if (negated) {
8582
      q_floor(&solver->constant);
8583
    } else {
8584
      q_ceil(&solver->constant);
8585
    }
8586
  } else {
8587
    negated = poly_buffer_make_monic(b);
8588
    x = decompose_and_get_dynamic_var(solver);
8589
    assert(! arith_var_is_int(&solver->vtbl, x));
8590
  }
8591
#else
8592
  // This seems to work better
8593
  negated = poly_buffer_make_monic(b);
79✔
8594
  x = decompose_and_get_dynamic_var(solver);
79✔
8595
  is_int = arith_var_is_int(&solver->vtbl, x);
79✔
8596
  if (is_int) {
79✔
8597
    if (negated) {
4✔
8598
      q_floor(&solver->constant);
×
8599
    } else {
8600
      q_ceil(&solver->constant);
4✔
8601
    }
8602
  }
8603
#endif
8604

8605

8606

8607
#if TRACE
8608
  printf("---> New var:\n");
8609
  print_simplex_vardef(stdout, solver, x);
8610
  printf("\n");
8611
  fflush(stdout);
8612
#endif
8613

8614
  // if negated is true, the atom is (x <= constant)
8615
  // otherwise, it's (x >= constant)
8616
  if (negated) {
79✔
8617
    return mk_dynamic_le_atom(solver, x, is_int, &solver->constant);
8✔
8618
  } else {
8619
    return mk_dynamic_ge_atom(solver, x, is_int, &solver->constant);
71✔
8620
  }
8621
}
8622

8623

8624
/*
8625
 * Literal for an assumption: x >= a
8626
 * - x is an existing variable
8627
 * - is_int indicates whether x is an integer
8628
 */
8629
static literal_t assumed_lb(simplex_solver_t *solver, thvar_t x, bool is_int, rational_t *a) {
1,217✔
8630
  int32_t k;
8631
  literal_t l;
8632

8633
  k = arith_var_lower_index(&solver->vtbl, x);
1,217✔
8634
  if (k >= 0 && xq_eq_q(solver->bstack.bound + k, a)) {
1,217✔
8635
    // this is the current bound on x
8636
    if (solver->decision_level == solver->base_level) {
1,217✔
8637
      return true_literal;
×
8638
    }
8639
    if (solver->bstack.tag[k] == ARITH_AXIOM_LB) {
1,217✔
8640
      return true_literal;
247✔
8641
    }
8642
    if (solver->bstack.tag[k] == ARITH_ASSERTED_LB) {
970✔
8643
      return solver->bstack.expl[k].lit;
944✔
8644
    }
8645
  }
8646

8647
  // in all other cases, create a new atom
8648
  l = mk_dynamic_ge_atom(solver, x, is_int, a);
26✔
8649
  reset_prop_ptr(solver);
26✔
8650

8651
  return l;
26✔
8652
}
8653

8654

8655
/*
8656
 * Same thing for an assumption x <= a
8657
 */
8658
static literal_t assumed_ub(simplex_solver_t *solver, thvar_t x, bool is_int, rational_t *a) {
116✔
8659
  int32_t k;
8660
  literal_t l;
8661

8662
  k = arith_var_upper_index(&solver->vtbl, x);
116✔
8663
  if (k >= 0 && xq_eq_q(solver->bstack.bound + k, a)) {
116✔
8664
    // this is the current bound on x
8665
    if (solver->decision_level == solver->base_level) {
116✔
8666
      return true_literal;
×
8667
    }
8668
    if (solver->bstack.tag[k] == ARITH_AXIOM_UB) {
116✔
8669
      return true_literal;
40✔
8670
    }
8671
    if (solver->bstack.tag[k] == ARITH_ASSERTED_UB) {
76✔
8672
      return solver->bstack.expl[k].lit;
62✔
8673
    }
8674
  }
8675

8676
  // in all other case, create a new atom
8677
  l = mk_dynamic_le_atom(solver, x, is_int, a);
14✔
8678
  reset_prop_ptr(solver);
14✔
8679

8680
  return l;
14✔
8681
}
8682

8683

8684

8685
/*
8686
 * Add a Gomory cut
8687
 * - simplex->buffer contains a polynomial p
8688
 * - the cut is (p >= 0)
8689
 * - this cut is implied by bounds on the variables stored in *g
8690
 *
8691
 * In general, we add a clause of the form
8692
 *   (x_1 >= l_1) /\ ... /\ (x_k >= l_k) /\ ... (x_n <= u_n) => (p >= 0).
8693
 *
8694
 */
8695
static void add_gomory_cut(simplex_solver_t *solver, gomory_vector_t *g) {
79✔
8696
  ivector_t *v;
8697
  uint32_t i, n, x;
8698
  bool is_int;
8699
  literal_t l, cut;
8700

8701
  cut = mk_gomory_atom(solver);
79✔
8702

8703
#if TRACE
8704
  printf("---> cut atom:\n");
8705
  printf("     ");
8706
  print_simplex_atomdef(stdout, solver, var_of(cut));
8707
  printf("\n");
8708
#endif
8709

8710
  v = &solver->expl_vector;
79✔
8711
  ivector_reset(v);
79✔
8712

8713
  if (solver->decision_level > solver->base_level) {
79✔
8714
    n = g->nelems;
79✔
8715
    for (i=0; i<n; i++) {
1,412✔
8716
      x = g->var[i];
1,333✔
8717
      is_int = gomory_var_is_int(g, i);
1,333✔
8718
      assert(is_int == arith_var_is_int(&solver->vtbl, x));
8719
      if (gomory_bound_is_lb(g, i)) {
1,333✔
8720
        l = assumed_lb(solver, x, is_int, g->bound + i);
1,217✔
8721
      } else {
8722
        l = assumed_ub(solver, x, is_int, g->bound + i);
116✔
8723
      }
8724
      if (l != true_literal) {
1,333✔
8725
        ivector_push(v, not(l));
1,046✔
8726
      }
8727
    }
8728
  }
8729

8730
  ivector_push(v, cut);
79✔
8731

8732
  add_clause(solver->core, v->size, v->data);
79✔
8733

8734
#if TRACE
8735
  printf("---> cut atom:\n");
8736
  printf("     ");
8737
  print_simplex_atomdef(stdout, solver, var_of(cut));
8738
  printf("\n");
8739
  printf("---> New clause:\n");
8740
  printf("     ");
8741
  print_litarray(stdout, v->size, v->data);
8742
  printf("\n");
8743
  n = v->size - 1;
8744
  if (n > 0) {
8745
    for (i=0; i<n; i++) {
8746
      printf("     ");
8747
      print_simplex_atomdef(stdout, solver, var_of(v->data[i]));
8748
    }
8749
  }
8750
  fflush(stdout);
8751
#endif
8752

8753
}
79✔
8754

8755

8756
/*
8757
 * Try a Gomory cut based on basic variable x
8758
 * - x must be an integer variable with a non-integer value
8759
 */
8760
static bool try_gomory_cut_for_var(simplex_solver_t *solver, gomory_vector_t *g, thvar_t x) {
133✔
8761
  arith_vartable_t *vtbl;
8762
  row_t *row;
8763
  rational_t *a;
8764
  xrational_t *val;
8765
  uint32_t i, n;
8766
  int32_t r;
8767
  thvar_t y;
8768
  bool is_int;
8769
  bool is_lb, is_ub;
8770

8771
  assert(arith_var_is_int(&solver->vtbl, x) &&
8772
         !arith_var_value_is_int(&solver->vtbl, x));
8773

8774
  vtbl = &solver->vtbl;
133✔
8775

8776
  r = matrix_basic_row(&solver->matrix, x);
133✔
8777
  assert(r >= 0);
8778
  row = matrix_row(&solver->matrix, r);
133✔
8779

8780
#if TRACE
8781
  printf("\n--- Try Gomory cut for ");
8782
  print_simplex_var(stdout, solver, x);
8783
  printf(" ---\n");
8784
  print_simplex_row(stdout, solver, row);
8785
  printf("\n\n");
8786
  print_simplex_var(stdout, solver, x);
8787
  printf(" = ");
8788
  print_simplex_var_value(stdout, solver, x);
8789
  printf("; ");
8790
  print_simplex_var_bounds(stdout, solver, x);
8791
  printf("\n");
8792
  fflush(stdout);
8793
#endif
8794

8795
  n = row->size;
133✔
8796
  for (i=0; i<n; i++) {
2,352✔
8797
    y = row->data[i].c_idx;
2,273✔
8798
    if (y >= 0) {
2,273✔
8799
      a = &row->data[i].coeff;
2,147✔
8800
      is_int = arith_var_is_int(vtbl, y);
2,147✔
8801
      if (! (is_int && q_is_integer(a))) {
2,147✔
8802
        /*
8803
         * Process term a * y where either y is not an integer variable
8804
         * or a is not an integer constant.
8805
         */
8806
        assert(y != x);
8807

8808
        /*
8809
         * Check whether y's value is equal to its lower or upper bound.
8810
         * If not, we could still generate a Gomory cut with y >= val as
8811
         * antecedent.
8812
         */
8813
        val = arith_var_value(vtbl, y);
2,027✔
8814
        is_lb = variable_at_lower_bound(solver, y);
2,027✔
8815
        is_ub = variable_at_upper_bound(solver, y);
2,027✔
8816
        if (! xq_is_rational(val) ||
2,027✔
8817
            ! (is_lb || is_ub)) {
2,027✔
8818
          // can't handle non-rational bounds
8819
          // also skip the case where y is not at one of its bound
8820
          return false;
54✔
8821
        }
8822
        assert(is_lb || is_ub);
8823
        gomory_vector_add_elem(g, y, a, &val->main, is_int, is_lb);
1,973✔
8824

8825
#if TRACE
8826
        print_simplex_var(stdout, solver, y);
8827
        printf(" = ");
8828
        print_simplex_var_value(stdout, solver, y);
8829
        printf("; ");
8830
        print_simplex_var_bounds(stdout, solver, y);
8831
        fflush(stdout);
8832
#endif
8833
      }
8834
    }
8835
  }
8836

8837
  /*
8838
   * Build the cut: terms >= bound
8839
   * - terms are stored in solver->buffer
8840
   * - the bound is stored in solver->aux
8841
   */
8842
  if (make_gomory_cut(g, &solver->buffer)) {
79✔
8843
#if TRACE
8844
    printf("\n---> Gomory cut:\n");
8845
    print_simplex_buffer(stdout, solver);
8846
    printf(" >= 0\n\n");
8847
    fflush(stdout);
8848
#endif
8849
    // deal with it
8850
    add_gomory_cut(solver, g);
79✔
8851
  }
8852

8853
  // cleanup
8854
  reset_poly_buffer(&solver->buffer);
79✔
8855

8856
  return true;
79✔
8857
}
8858

8859
/*
8860
 * Scan variables of v and try a Gomory cut for them
8861
 * - each element of v must be a basic integer variable
8862
 *   with a non-integer value.
8863
 * - max_cuts = bound on the total number of cuts
8864
 * - return the number of cuts added
8865
 */
8866
static uint32_t try_gomory_cuts(simplex_solver_t *solver, ivector_t *v, uint32_t max_cuts) {
×
8867
  gomory_vector_t cut;
8868
  uint32_t i, n, num_cuts;
8869

8870
#if TRACE
8871
  printf("\nTRY GOMORY CUTS: dlevel = %"PRIu32", base_level = %"PRIu32"\n", solver->decision_level, solver->base_level);
8872
  fflush(stdout);
8873
#endif
8874

8875
  init_gomory_vector(&cut);
×
8876
  num_cuts = 0;
×
8877
  n = v->size;
×
8878
  for (i=0; i<n; i++) {
×
8879
    num_cuts += try_gomory_cut_for_var(solver, &cut, v->data[i]);
×
8880
    if (num_cuts >= max_cuts) break;
×
8881
  }
8882
  delete_gomory_vector(&cut);
×
8883

8884
  return num_cuts;
×
8885
}
8886

8887

8888
/*
8889
 * Variant: focus on variable x
8890
 */
8891
static bool gomory_cut_for_var(simplex_solver_t *solver, thvar_t x) {
133✔
8892
  gomory_vector_t cut;
8893
  bool result;
8894

8895
  init_gomory_vector(&cut);
133✔
8896
  result = try_gomory_cut_for_var(solver, &cut, x);
133✔
8897
  delete_gomory_vector(&cut);
133✔
8898

8899
  return result;
133✔
8900
}
8901

8902
#endif
8903

8904

8905

8906

8907
/*
8908
 * FINAL CHECK
8909
 */
8910

8911
/*
8912
 * Each step (implemented by the wrapper functions) starts from
8913
 * a feasible tableau. It then tests for integer infeasibility using
8914
 * one of the techniques above, possibly generates new bounds,
8915
 * then attempt to restore the tableau to be feasible.
8916
 */
8917

8918
/*
8919
 * Generic wrapper:
8920
 * - f is a check function
8921
 * - name is the proceduce name
8922
 *
8923
 * Assumptions on f:
8924
 * - f(solver) returns false if there's a conflict and generates
8925
 *   a conflict explanation.
8926
 * - f may also generate new bounds and set solver->recheck to true
8927
 * - in such a case, the wrapper attempts to restore a feasible tableau.
8928
 */
8929
static bool intfeas_wrapper(simplex_solver_t *solver, const char *name, bool (*f)(simplex_solver_t *)) {
1,239✔
8930
  uint32_t nbounds;
8931

8932
  nbounds = solver->bstack.top;
1,239✔
8933
  solver->recheck = false;
1,239✔
8934
  if (! f(solver)) {
1,239✔
8935
    trace_printf(solver->core->trace, 10, "(unsat by %s)\n", name);
491✔
8936
    solver->stats.num_bound_conflicts ++;
491✔
8937
    return false;
491✔
8938
  } else {
8939
    trace_printf(solver->core->trace, 10, "(%s: %"PRIu32" new bounds)\n", name, solver->bstack.top - nbounds);
748✔
8940
    if (solver->recheck) {
748✔
8941
      /*
8942
       * Strengthened bounds require rechecking feasibility
8943
       */
8944
      simplex_fix_nonbasic_assignment(solver);
233✔
8945
      if (! simplex_make_feasible(solver) ) {
233✔
8946
        trace_printf(solver->core->trace, 10, "(infeasible after bound strengthening)\n");
84✔
8947
        solver->stats.num_bound_recheck_conflicts ++;
84✔
8948
        return false;
84✔
8949
      }
8950

8951
      // Since pivoting may have occurred we need to prepare for the next step
8952
      prepare_for_integer_solving(solver);
149✔
8953
    } else {
8954
      /*
8955
       * There may be strengthened bounds but everything is still feasible
8956
       * - we force fix_ptr to bstack.top (otherwise, things may break
8957
       *   because the invariant fix_ptr == top is expected to hold)
8958
       */
8959
      solver->bstack.fix_ptr = solver->bstack.top;
515✔
8960
    }
8961
  }
8962

8963
  return true;
664✔
8964
}
8965

8966

8967
/*
8968
 * Bound strengthening
8969
 */
8970
static bool simplex_intfeas_strengthening(simplex_solver_t *solver) {
×
8971
  return intfeas_wrapper(solver, "strengthening", simplex_strengthen_bounds);
×
8972
}
8973

8974
/*
8975
 * Cheap integrality test
8976
 */
8977
static bool simplex_intfeas_integrality_constraints(simplex_solver_t *solver) {
1,239✔
8978
  return intfeas_wrapper(solver, "integrality check", simplex_integrality_check);
1,239✔
8979
}
8980

8981
/*
8982
 * Dioophantine solver
8983
 */
8984
static bool simplex_intfeas_diophantine_check(simplex_solver_t *solver) {
×
8985
  return intfeas_wrapper(solver, "diophantine solver", simplex_dsolver_check);
×
8986
}
8987

8988
#if 0
8989
// NOT USED
8990
/*
8991
 * Iterated bound strengthening
8992
 */
8993
static bool simplex_intfeas_iter_strengthening(simplex_solver_t *solver) {
8994
  return intfeas_wrapper(solver, "strengthening", simplex_strengthen_bounds_iter);
8995
}
8996
#endif
8997

8998
/*
8999
 * Check whether the current set of constraints is integer feasible
9000
 * - return true if it is
9001
 * - if it is not, do something about it and return false.
9002
 * - the system must be feasible (in the reals)
9003
 */
9004
static bool simplex_make_integer_feasible(simplex_solver_t *solver) {
2,075✔
9005
  ivector_t *v;
9006
  thvar_t x;
9007
  uint32_t nbounds, bb_score, n;
9008

9009
#if TRACE_BB
9010
  printf("\n--- make integer feasible [dlevel = %"PRIu32", decisions = %"PRIu64"]: %"PRId32
9011
         " integer-invalid vars\n", solver->core->decision_level, solver->core->stats.decisions,
9012
         simplex_num_integer_invalid_vars(solver));
9013
#endif
9014

9015
#if DEBUG
9016
  check_assignment(solver);
9017
  check_vartags(solver);
9018
#endif
9019

9020
  if (simplex_assignment_integer_valid(solver)) {
2,075✔
9021
    return true;
836✔
9022
  }
9023

9024
  solver->stats.num_make_intfeasible ++;
1,239✔
9025

9026
  trace_printf(solver->core->trace, 10, "(testing integer feasibility)\n");
1,239✔
9027

9028
#if TRACE_INTFEAS
9029
  printf("\nMAKE INTEGER FEASIBLE %"PRIu32" [dlevel = %"PRIu32", decisions = %"PRIu64"]\n\n",
9030
         solver->stats.num_make_intfeasible, solver->core->decision_level, solver->core->stats.decisions);
9031
  print_simplex_vars(stdout, solver);
9032
  printf("\n");
9033
  print_simplex_matrix(stdout, solver);
9034
  print_simplex_bounds(stdout, solver);
9035
  printf("\n");
9036
  print_simplex_assignment(stdout, solver);
9037
  printf("\n\n");
9038
  fflush(stdout);
9039
#endif
9040

9041
  prepare_for_integer_solving(solver);
1,239✔
9042

9043
  /*
9044
   * Try bound strengthening + integrality test + diophantine check
9045
   */
9046
  nbounds = solver->bstack.top;
1,239✔
9047
  if (false && !simplex_intfeas_strengthening(solver)) return false;
9048
  if (!simplex_intfeas_integrality_constraints(solver)) return false;
1,239✔
9049
  if (false && !simplex_intfeas_diophantine_check(solver)) return false;
9050
  if (false && !simplex_intfeas_strengthening(solver)) return false;
9051

9052
  /*
9053
   * TRY OUR LUCK
9054
   */
9055
  if (underconstrained(solver)) {
664✔
9056
    if (simplex_try_naive_integer_search(solver)) {
14✔
9057
      trace_printf(solver->core->trace, 10, "(feasible by naive search)\n");
3✔
9058
      solver->bstack.prop_ptr = solver->bstack.fix_ptr;
3✔
9059
      return true;
3✔
9060
    }
9061
  }
9062

9063
  /*
9064
   * If we've learned new bounds in the previous phases,
9065
   * try more rounds of bound strengthening.
9066
   */
9067
  if (false && solver->bstack.top > nbounds && !simplex_intfeas_strengthening(solver)) {
9068
    return false;
9069
  }
9070

9071

9072
  /*
9073
   * BRANCH
9074
   */
9075

9076
  /*
9077
   * At this point: no unsat detected. But bounds may have been strengthened
9078
   * All integer basic variables have an integer value.
9079
   */
9080

9081
  // collect the integer basic variables that have a non-integer value
9082
  v = &solver->aux_vector;
661✔
9083
  assert(v->size == 0);
9084
  collect_non_integer_basic_vars(solver, v);
661✔
9085
  if (v->size == 0) {
661✔
9086
    if (! simplex_assignment_integer_valid(solver)){
5✔
9087
      abort();
×
9088
    }
9089
    solver->bstack.prop_ptr = solver->bstack.fix_ptr;
5✔
9090
    return true;
5✔
9091
  }
9092

9093
#if TRACE_INTFEAS
9094
  printf("\nMAKE INTEGER FEASIBLE %"PRIu32" [dlevel = %"PRIu32", decisions = %"PRIu64"]\n\n",
9095
         solver->stats.num_make_intfeasible, solver->core->decision_level, solver->core->stats.decisions);
9096
  printf("BRANCHING REQUIRED\n");
9097
  print_simplex_vars(stdout, solver);
9098
  printf("\n");
9099
  print_simplex_matrix(stdout, solver);
9100
  print_simplex_bounds(stdout, solver);
9101
  printf("\n");
9102
  print_simplex_assignment(stdout, solver);
9103
  printf("\n\n");
9104
  fflush(stdout);
9105
#endif
9106

9107
  /*
9108
   * Create a branch atom or create Gomory cuts
9109
   */
9110
  x = select_branch_variable(solver, v, &bb_score);
656✔
9111
  trace_printf(solver->core->trace, 3,
656✔
9112
               "(branch & bound: %"PRIu32" candidates, branch variable = i!%"PRId32", score = %"PRIu32")\n",
9113
               v->size, x, bb_score);
9114

9115
  if (solver->stats.num_branch_atoms >= 20) {
656✔
9116
    if (false && v->size > 1 && bb_score > 200000000 && solver->stats.num_gomory_cuts < 100) {
9117
      n = try_gomory_cuts(solver, v, 100);
9118
      solver->stats.num_gomory_cuts += n;
9119
      trace_printf(solver->core->trace, 3, "(Gomory cuts: %"PRIu32" cuts created)\n", n);
9120
      if (n > 0) goto done;
9121
      solver->core->stats.conflicts += 1000;
9122
    } else if (bb_score > 100000000) {
501✔
9123
      n = gomory_cut_for_var(solver, x);
133✔
9124
      solver->stats.num_gomory_cuts ++;
133✔
9125
      if (n > 0) {
133✔
9126
        trace_printf(solver->core->trace, 3, "(Created Gomory cut on var i!%"PRId32")\n", x);
79✔
9127
      } else {
9128
        trace_printf(solver->core->trace, 3, "(Failed to create Gomory cut on var i!%"PRId32")\n", x);
54✔
9129
      }
9130
      if (n > 0) goto done;
133✔
9131
      //      solver->core->stats.conflicts += 1000;
9132
    }
9133
  }
9134

9135
  create_branch_atom(solver, x);
577✔
9136
  solver->core->stats.conflicts += 40;
577✔
9137

9138
#if TRACE_INTFEAS
9139
  print_branch_candidates(stdout, solver, v);
9140
  printf("\n\nDONE\n");
9141
  fflush(stdout);
9142
#endif
9143

9144
 done:
656✔
9145
  ivector_reset(v);
656✔
9146

9147
  assert(x != null_thvar);
9148

9149
  return false;
656✔
9150
}
9151

9152

9153

9154

9155

9156

9157
/*********************************
9158
 *   PROCESS EGRAPH ASSERTIONS   *
9159
 ********************************/
9160

9161
/*
9162
 * When assertions in egraph_queue are processed, we know that the egraph
9163
 * has not found a conflict.
9164
 */
9165

9166
/*
9167
 * Construct a conflict when we have bound k ==> (x1 != x2)
9168
 * after the egraph propagated that (x1 == x2)
9169
 * - id = egraph edge that triggered (x1 == x2)
9170
 */
9171
static void record_egraph_eq_conflict(simplex_solver_t *solver, int32_t k, thvar_t x1, thvar_t x2, int32_t id) {
173✔
9172
  ivector_t *v;
9173
  eterm_t t1, t2;
9174

9175
  v = &solver->expl_vector;
173✔
9176
  ivector_reset(v);
173✔
9177
  simplex_explain_bound(solver, k, v); // conjunction of literals that imply k
173✔
9178

9179
  t1 = arith_var_eterm(&solver->vtbl, x1);
173✔
9180
  t2 = arith_var_eterm(&solver->vtbl, x2);
173✔
9181
  egraph_explain_term_eq(solver->egraph, t1, t2, id, v); // add literals that imply (x1 == x2)
173✔
9182

9183
  // turn v into a conflict clause
9184
  convert_expl_to_clause(v);
173✔
9185
  ivector_push(v, null_literal); // end-marker
173✔
9186

9187
#if 0
9188
  printf("\n---> SIMPLEX CONFLICT on g!%"PRId32" == g!%"PRId32" (conflict with bound)\n",
9189
         arith_var_eterm(&solver->vtbl, x1), arith_var_eterm(&solver->vtbl, x2));
9190
#endif
9191
  record_theory_conflict(solver->core, v->data);
173✔
9192

9193
  solver->stats.num_conflicts ++;
173✔
9194
}
173✔
9195

9196

9197
/*
9198
 * Process (x1 == x2)
9199
 * - x1 and x2 are two variables attached to two egraph terms t1 and t2
9200
 * - this function is called when t1 and t2 become equal in the egraph
9201
 * - id = egraph edge that triggered merge of x1 and x2's classes
9202
 * - return false if there's a conflict, true otherwise
9203
 */
9204
static bool simplex_process_var_eq(simplex_solver_t *solver, thvar_t x1, thvar_t x2, int32_t id) {
139,153✔
9205
  rational_t *c;
9206
  egraph_expl_triple_t *triple;
9207
  literal_t l;
9208
  thvar_t y;
9209
  int32_t k, cmp_lb, cmp_ub;
9210

9211
  assert(arith_var_has_eterm(&solver->vtbl, x1) && arith_var_has_eterm(&solver->vtbl, x2) && x1 != x2);
9212

9213
#if TRACE
9214
  printf("---> Simplex: process egraph equality: ");
9215
  print_simplex_var(stdout, solver, x1);
9216
  printf(" = ");
9217
  print_simplex_var(stdout, solver, x2);
9218
  printf(" [dlevel = %"PRIu32"]\n", solver->core->decision_level);
9219
  if (!arith_var_is_free(&solver->vtbl, x1)) {
9220
    printf("     ");
9221
    print_simplex_vardef(stdout, solver, x1);
9222
  }
9223
  if (!arith_var_is_free(&solver->vtbl, x2)) {
9224
    printf("     ");
9225
    print_simplex_vardef(stdout, solver, x2);
9226
  }
9227
  fflush(stdout);
9228
#endif
9229

9230
  /*
9231
   * build p such that p = 0 is equivalent to x1 = x2
9232
   * p is in solver->buffer
9233
   * l is a simplification code:
9234
   * can be false_literal if x1 = x2 is unsat
9235
   * l should never be true_literal
9236
   */
9237
  l = simplify_dynamic_vareq(solver, x1, x2);
139,153✔
9238
  if (l == false_literal) {
139,153✔
9239
    // p = 0 is false, we force a conflict by turning this into 1 = 0
9240
    y = const_idx;
3✔
9241
    q_clear(&solver->constant);
3✔
9242
    c = &solver->constant;
3✔
9243
    reset_poly_buffer(&solver->buffer);
3✔
9244
  } else {
9245
    assert(l != true_literal);
9246
    // get y and c such that y = c is equivalent to p = 0
9247
    y = decompose_and_get_dynamic_var(solver); // store c in solver-constant and reset buffer
139,150✔
9248
    c = &solver->constant;
139,150✔
9249
  }
9250

9251
#if TRACE
9252
  printf("     asserting ");
9253
  print_simplex_var(stdout, solver, y);
9254
  printf(" == ");
9255
  q_print(stdout, c);
9256
  printf("\n");
9257
  if (! arith_var_is_free(&solver->vtbl, y)) {
9258
    printf("     ");
9259
    print_simplex_vardef(stdout, solver, y);
9260
  }
9261
#endif
9262

9263

9264
  /*
9265
   * assert (y >= c) and (y <= c) but check for conflicts first
9266
   * we use cmp_lb and cmp_ub as indicators:
9267
   *
9268
   *   cmp_lb < 0  if lower bound on y < c (y >= c is asserted)
9269
   *   cmp_lb = 0  if lower bound on y = c (y >= c is redundant)
9270
   *   cmp_lb > 0  if lower bound on y > c (conflict)
9271
   *
9272
   *   cmp_ub < 0  if upper bound on y < c (conflict)
9273
   *   cmp_ub = 0  if upper bound on y = c (y <= c is redundant)
9274
   *   cmp_ub > 0  if upper bound on y > c (y <= c is asserted)
9275
   */
9276
  cmp_lb = -1;
139,153✔
9277
  cmp_ub = +1;
139,153✔
9278

9279
  k = arith_var_lower_index(&solver->vtbl, y);
139,153✔
9280
  if (k >= 0) {
139,153✔
9281
    cmp_lb = xq_cmp_q(solver->bstack.bound + k, c);
7,763✔
9282
    if (cmp_lb > 0) {
7,763✔
9283
      record_egraph_eq_conflict(solver, k, x1, x2, id);
84✔
9284

9285
#if TRACE
9286
      printf("     conflict with bound ");
9287
      print_simplex_bound(stdout, solver, k);
9288
      printf("\n");
9289
#endif
9290
      return false;
84✔
9291
    }
9292
  }
9293

9294
  k = arith_var_upper_index(&solver->vtbl, y);
139,069✔
9295
  if (k >= 0) {
139,069✔
9296
    cmp_ub = xq_cmp_q(solver->bstack.bound + k, c);
3,017✔
9297
    if (cmp_ub < 0) {
3,017✔
9298
      record_egraph_eq_conflict(solver, k, x1, x2, id);
89✔
9299

9300
#if TRACE
9301
      printf("     conflict with bound ");
9302
      print_simplex_bound(stdout, solver, k);
9303
      printf("\n");
9304
#endif
9305

9306
      return false;
89✔
9307
    }
9308
  }
9309

9310
  triple = NULL; // otherwise GCC gives a warning
138,980✔
9311
  if (cmp_lb < 0 || cmp_ub > 0) {
138,980✔
9312
    triple = (egraph_expl_triple_t *) arena_alloc(&solver->arena, sizeof(egraph_expl_triple_t));
136,500✔
9313
    triple->var[0] = x1;
136,500✔
9314
    triple->var[1] = x2;
136,500✔
9315
    triple->id = id;
136,500✔
9316
  }
9317
  if (cmp_lb < 0) {
138,980✔
9318
    push_lb_egraph(solver, y, c, triple);
132,628✔
9319
  }
9320
  if (cmp_ub > 0) {
138,980✔
9321
    push_ub_egraph(solver, y, c, triple);
136,164✔
9322
  }
9323

9324
  assert(simplex_fixed_variable(solver, y) && q_eq(fixed_variable_value(solver, y), c));
9325

9326
  return true;
138,980✔
9327
}
9328

9329

9330

9331
/*
9332
 * Return a literal and atom equivalent to (y > c)
9333
 */
9334
static literal_t create_pos_atom(simplex_solver_t *solver, thvar_t y, rational_t *c) {
429✔
9335
  int32_t new_idx;
9336
  literal_t l;
9337

9338
  assert(y != const_idx);
9339

9340
  // get the atom (y <= c)
9341
  l = get_literal_for_le_atom(&solver->atbl, y, arith_var_is_int(&solver->vtbl, y), c, &new_idx);
429✔
9342
  if (new_idx >= 0) {
429✔
9343
    build_binary_lemmas_for_atom(solver, y, new_idx);
385✔
9344
    attach_atom_to_arith_var(&solver->vtbl, y, new_idx);
385✔
9345
  }
9346
  return not(l);
429✔
9347
}
9348

9349
/*
9350
 * Return literal/atom equivalent to (y < c)
9351
 */
9352
static literal_t create_neg_atom(simplex_solver_t *solver, thvar_t y, rational_t *c) {
429✔
9353
  int32_t new_idx;
9354
  literal_t l;
9355

9356
  assert(y != const_idx);
9357

9358
  // get atom (y >= c)
9359
  l = get_literal_for_ge_atom(&solver->atbl, y, arith_var_is_int(&solver->vtbl, y), c, &new_idx);
429✔
9360
  if (new_idx >= 0) {
429✔
9361
    build_binary_lemmas_for_atom(solver, y, new_idx);
396✔
9362
    attach_atom_to_arith_var(&solver->vtbl, y, new_idx);
396✔
9363
  }
9364
  return not(l);
429✔
9365
}
9366

9367

9368
/*
9369
 * Create the lemma (eq t1 t2) or (x1 - x2 > 0) or (x1 - x2 < 0)
9370
 * - x1 and x2 must be two distinct variables, attached to the eterms t1 and t2
9371
 * - return the number of lemmas created (which is either 1 or
9372
 * - if the lemma already exist (i.e. no need to generate it again), return 0
9373
 * - otherwise create the lemma and return 1
9374
 */
9375
static uint32_t simplex_trichotomy_lemma(simplex_solver_t *solver, thvar_t x1, thvar_t x2) {
26✔
9376
  cache_t *cache;
9377
  cache_elem_t *e;
9378
  rational_t *c;
9379
  thvar_t y;
9380
  eterm_t t1, t2;
9381
  literal_t l, l0, l1, l2;
9382

9383
  assert(x1 != x2);
9384

9385
  // normalize: we want x1 < x2
9386
  if (x2 < x1) {
26✔
9387
    y = x1; x1 = x2; x2 = y;
×
9388
  }
9389

9390
#if TRACE
9391
  t1 = arith_var_eterm(&solver->vtbl, x1);
9392
  t2 = arith_var_eterm(&solver->vtbl, x2);
9393
  printf("---> Simplex: trichotomy lemma:\n");
9394
  printf("     x1 = ");
9395
  print_simplex_var(stdout, solver, x1);
9396
  printf(", t1 = ");
9397
  print_eterm_id(stdout, t1);
9398
  printf("\n");
9399
  printf("     x2 = ");
9400
  print_simplex_var(stdout, solver, x2);
9401
  printf(", t2 = ");
9402
  print_eterm_id(stdout, t2);
9403
  printf("\n");
9404
  if (!arith_var_is_free(&solver->vtbl, x1)) {
9405
    printf("     ");
9406
    print_simplex_vardef(stdout, solver, x1);
9407
  }
9408
  if (!arith_var_is_free(&solver->vtbl, x2)) {
9409
    printf("     ");
9410
    print_simplex_vardef(stdout, solver, x2);
9411
  }
9412
#endif
9413

9414
  cache = simplex_get_cache(solver);
26✔
9415
  e = cache_get(cache, TRICHOTOMY_LEMMA, x1, x2);
26✔
9416
  if (e->flag != NEW_CACHE_ELEM) {
26✔
9417
    // trichotomy instance already exists for x1 and x2
9418
#if TRACE
9419
    printf("     redundant\n");
9420
#endif
9421
    return 0;
×
9422
  }
9423

9424
  e->flag = ACTIVE_ARITH_LEMMA;
26✔
9425

9426
  /*
9427
   * create the egraph equality l := (eq t1 t2)
9428
   */
9429
  t1 = arith_var_eterm(&solver->vtbl, x1);
26✔
9430
  t2 = arith_var_eterm(&solver->vtbl, x2);
26✔
9431
  assert(t1 != null_eterm && t2 != null_eterm);
9432
  l = egraph_make_simple_eq(solver->egraph, pos_occ(t1), pos_occ(t2));
26✔
9433

9434
#if TRACE
9435
  printf("     trichotomy lemma: egraph atom: ");
9436
  print_literal(stdout, l);
9437
  printf(" := ");
9438
  print_egraph_atom_of_literal(stdout, solver->egraph, l);
9439
  printf("\n");
9440
#endif
9441

9442
  /*
9443
   * build p such that p=0 is equivalent to (x1 = x2)
9444
   * p is stored in solver->buffer
9445
   * l0 = simplification code
9446
   */
9447
  l0 = simplify_dynamic_vareq(solver, x1, x2);
26✔
9448
  if (l0 == false_literal) {
26✔
9449
    /*
9450
     * x1 = x2 is false: add (not (eq t1 t2)))) as an axiom for the egraph
9451
     */
9452
#if TRACE
9453
    printf("     reduced to 1 != 0\n");
9454
    printf("     add unit clause: ");
9455
    print_egraph_atom_of_literal(stdout, solver->egraph, not(l));
9456
    printf("\n");
9457
#endif
9458
    add_unit_clause(solver->core, not(l));
×
9459
    reset_poly_buffer(&solver->buffer);
×
9460

9461
#if 0
9462
    printf("---> SIMPLEX: trichotomy lemma for ");
9463
    print_simplex_var(stdout, solver, x1);
9464
    printf(" ");
9465
    print_simplex_var(stdout, solver, x2);
9466
    printf(" (axiom)\n");
9467
#endif
9468
    solver->stats.num_reduced_tricho ++;
×
9469

9470
  } else {
9471
    assert(l0 != true_literal); // since x1 != x2
9472

9473
    /*
9474
     * get y and c such that y = c is equivalent to x1 = x2
9475
     */
9476
    y = decompose_and_get_dynamic_var(solver); // store c in solver->constant and reset buffer
26✔
9477
    c = &solver->constant;
26✔
9478

9479
    l1 = create_pos_atom(solver, y, c);   // l1 := y > c
26✔
9480
    l2 = create_neg_atom(solver, y, c);   // l2 := y < c
26✔
9481

9482
#if TRACE
9483
    printf("     reduced to: ");
9484
    print_simplex_var(stdout, solver, y);
9485
    printf(" != ");
9486
    q_print(stdout, c);
9487
    printf("\n");
9488
    if (! arith_var_is_free(&solver->vtbl, y)) {
9489
      printf("     ");
9490
      print_simplex_vardef(stdout, solver, y);
9491
    }
9492
    printf("     simplex atom:\n      ");
9493
    print_literal(stdout, l1);
9494
    printf(" := ");
9495
    print_simplex_atom_of_literal(stdout, solver, l1);
9496
    printf("\n      ");
9497
    print_literal(stdout, l2);
9498
    printf(" := ");
9499
    print_simplex_atom_of_literal(stdout, solver, l2);
9500
    printf("\n");
9501

9502
    printf("     trichotomy clauses:\n");
9503
    printf("     (OR ");
9504
    print_egraph_atom_of_literal(stdout, solver->egraph, l);
9505
    printf(" ");
9506
    print_simplex_atom_of_literal(stdout, solver, l1);
9507
    printf(" ");
9508
    print_simplex_atom_of_literal(stdout, solver, l2);
9509
    printf(")\n");
9510
    printf("     (OR ");
9511
    print_simplex_atom_of_literal(stdout, solver, not(l1));
9512
    printf(" ");
9513
    print_egraph_atom_of_literal(stdout, solver->egraph, not(l));
9514
    printf(")\n");
9515
    printf("     (OR ");
9516
    print_simplex_atom_of_literal(stdout, solver, not(l2));
9517
    printf(" ");
9518
    print_egraph_atom_of_literal(stdout, solver->egraph, not(l));
9519
    printf(")\n");
9520
#endif
9521

9522
    add_ternary_clause(solver->core, l, l1, l2);
26✔
9523

9524
    /*
9525
     * The following two clauses encode
9526
     *   (t1 = t2) => (x1 - x2) <= 0
9527
     *   (t1 = t2) => (x1 - x2) >= 0
9528
     * They are redundant but adding them improves performance.
9529
     */
9530
    add_binary_clause(solver->core, not(l), not(l1));
26✔
9531
    add_binary_clause(solver->core, not(l), not(l2));
26✔
9532

9533
    solver->stats.num_tricho_lemmas ++;
26✔
9534
#if 0
9535
    printf("---> SIMPLEX: trichotomy lemma for ");
9536
    print_simplex_var(stdout, solver, x1);
9537
    printf(" ");
9538
    print_simplex_var(stdout, solver, x2);
9539
    printf(" (trichotomy)\n");
9540
#endif
9541
  }
9542

9543
  return 1;
26✔
9544
}
9545

9546

9547

9548
/*
9549
 * Process (x1 != x2)
9550
 * - x1 and x2 are two variables attached to two egraph terms t1 and t2
9551
 * - this does nothing: all disequalities are handled lazily in reconcile_model
9552
 */
9553
static void simplex_process_var_diseq(simplex_solver_t *solver, thvar_t x1, thvar_t x2) {
191,619✔
9554
  assert(arith_var_has_eterm(&solver->vtbl, x1) && arith_var_has_eterm(&solver->vtbl, x2) && x1 != x2);
9555

9556
#if TRACE
9557
  printf("---> Simplex: egraph disequality: ");
9558
  print_simplex_var(stdout, solver, x1);
9559
  printf(" != ");
9560
  print_simplex_var(stdout, solver, x2);
9561
  printf(" [dlevel = %"PRIu32", decisions = %"PRIu64"]\n", solver->core->decision_level, solver->core->stats.decisions);
9562
  if (! arith_var_is_free(&solver->vtbl, x1)) {
9563
    printf("     ");
9564
    print_simplex_vardef(stdout, solver, x1);
9565
  }
9566
  print_simplex_var_bounds(stdout, solver, x1);
9567
  if (! arith_var_is_free(&solver->vtbl, x2)) {
9568
    printf("     ");
9569
    print_simplex_vardef(stdout, solver, x2);
9570
  }
9571
  print_simplex_var_bounds(stdout, solver, x2);
9572
#endif
9573
}
191,619✔
9574

9575

9576
/*
9577
 * Assert that all variables a[0] ... a[n-1] are pairwise distinct
9578
 * - they are attached to egraph terms t[0] ... t[n-1]
9579
 * - the function is called when (distinct t[0] ... t[n-1]) is asserted in the egraph
9580
 * - this does nothing: just print trace if TRACE is enabled
9581
 */
9582
static void simplex_process_var_distinct(simplex_solver_t *solver, uint32_t n, thvar_t *a, composite_t *hint) {
2✔
9583
#if TRACE
9584
  uint32_t i, j;
9585

9586
  for (i=0; i<n-1; i++) {
9587
    for (j=i+1; j<n; j++) {
9588
      simplex_process_var_diseq(solver, a[i], a[j]);
9589
    }
9590
  }
9591
#endif
9592
}
2✔
9593

9594

9595
/*
9596
 * Process all assertions in the egraph queue
9597
 * - return true if no conflict is found
9598
 * - return false and add a conflict clause to the core otherwise.
9599
 */
9600
static bool simplex_process_egraph_assertions(simplex_solver_t *solver) {
519,151✔
9601
  eassertion_t *a, *end;
9602
  thvar_t x, y, z;
9603
  thvar_t pre_x, pre_y;
9604

9605
  if (eassertion_queue_is_nonempty(&solver->egraph_queue)) {
519,151✔
9606
    /*
9607
     * If the queue is empty, the call to eassertion_queue_end computes NULL + 0,
9608
     * which is undefined behavior (reported when compiled with MODE=sanitize).
9609
     */
9610
    a = eassertion_queue_start(&solver->egraph_queue);
137,615✔
9611
    end = eassertion_queue_end(&solver->egraph_queue);
137,615✔
9612

9613
    pre_x = null_thvar;
137,615✔
9614
    pre_y = null_thvar;
137,615✔
9615

9616
    while (a < end) {
577,376✔
9617
      switch (eassertion_get_kind(a)) {
439,934✔
9618
      case EGRAPH_VAR_EQ:
139,153✔
9619
        if (! simplex_process_var_eq(solver, a->var[0], a->var[1], a->id)) {
139,153✔
9620
#if 0
9621
          printf("---> SIMPLEX CONFLICT on g!%"PRId32" == g!%"PRId32"\n",
9622
                 arith_var_eterm(&solver->vtbl, a->var[0]),
9623
                 arith_var_eterm(&solver->vtbl, a->var[1]));
9624
#endif
9625
          reset_eassertion_queue(&solver->egraph_queue);
173✔
9626
          return false;
173✔
9627
        }
9628
        break;
138,980✔
9629

9630
      case EGRAPH_VAR_DISEQ:
300,780✔
9631
        x = a->var[0];
300,780✔
9632
        y = a->var[1];
300,780✔
9633
        if (x > y) {
300,780✔
9634
          z = x; x = y; y = z;
90,392✔
9635
        }
9636
        if (pre_x != x || pre_y != y) {
300,780✔
9637
          /*
9638
           * We use pre_x and pre_y as a cache to filter out duplicate
9639
           * disequalities.  That's imperfect but that filters out a lot
9640
           * of redundant disequalities, since the egraph tends to send
9641
           * several times the same disequality in a sequence.
9642
           */
9643
          simplex_process_var_diseq(solver, x, y);
189,846✔
9644
          pre_x = x;
189,846✔
9645
          pre_y = y;
189,846✔
9646
        }
9647
        break;
300,780✔
9648

9649
      case EGRAPH_VAR_DISTINCT:
1✔
9650
        simplex_process_var_distinct(solver, eassertion_get_arity(a), a->var, a->hint);
1✔
9651
        break;
1✔
9652

9653
      default:
×
9654
        assert(false);
9655
        break;
×
9656
      }
9657
      a = eassertion_next(a);
439,761✔
9658
    }
9659

9660
    reset_eassertion_queue(&solver->egraph_queue);
137,442✔
9661
  }
9662

9663
  return true;
518,978✔
9664
}
9665

9666

9667

9668

9669
/*
9670
 * EGRAPH ASSERTIONS RECEIVED BEFORE START SEARCH
9671
 */
9672

9673
/*
9674
 * Process all assertions in the egraph queue within 'base_propagate'
9675
 * - the tableau is not ready when this function is called
9676
 * - we deal only with equalities here. The reconcile_model function
9677
 *   will generate trichotomy axioms lazily if they're needed later on.
9678
 * - return true if no conflict is found
9679
 * - return false otherwise
9680
 */
9681
static bool simplex_process_egraph_base_assertions(simplex_solver_t *solver) {
23,360✔
9682
  eassertion_t *a, *end;
9683

9684
  assert(! solver->tableau_ready &&
9685
         ! solver->unsat_before_search &&
9686
         solver->base_level == solver->decision_level);
9687

9688
  if (eassertion_queue_is_nonempty(&solver->egraph_queue)) {
23,360✔
9689
    a = eassertion_queue_start(&solver->egraph_queue);
315✔
9690
    end = eassertion_queue_end(&solver->egraph_queue);
315✔
9691

9692
    while (a < end) {
3,023✔
9693
      switch (eassertion_get_kind(a)) {
2,708✔
9694
      case EGRAPH_VAR_EQ:
934✔
9695
        /*
9696
         * Since we're at the base level, we can treat the equality
9697
         * as an axiom.
9698
         */
9699
        simplex_assert_vareq_axiom(solver, a->var[0], a->var[1], true);
934✔
9700
        if (solver->unsat_before_search) {
934✔
9701
          // record the conflict in core
9702
          record_empty_theory_conflict(solver->core);
×
9703
          reset_eassertion_queue(&solver->egraph_queue);
×
9704
          return false;
×
9705
        }
9706
        break;
934✔
9707

9708
      case EGRAPH_VAR_DISEQ:
1,773✔
9709
        simplex_process_var_diseq(solver, a->var[0], a->var[1]);
1,773✔
9710
        break;
1,773✔
9711

9712
      case EGRAPH_VAR_DISTINCT:
1✔
9713
        simplex_process_var_distinct(solver, eassertion_get_arity(a), a->var, a->hint);
1✔
9714
        break;
1✔
9715

9716
      default:
×
9717
        assert(false);
9718
        break;
×
9719
      }
9720
      a = eassertion_next(a);
2,708✔
9721
    }
9722

9723
    reset_eassertion_queue(&solver->egraph_queue);
315✔
9724
  }
9725

9726
  return true;
23,360✔
9727
}
9728

9729

9730

9731
/***************************
9732
 *  INTERNALISATION START  *
9733
 **************************/
9734

9735
/*
9736
 * This is called before any new atom/variable is created
9737
 * (before start_search).
9738
 * - we reset the tableau and restore the matrix if needed
9739
 */
9740
void simplex_start_internalization(simplex_solver_t *solver) {
28,772✔
9741
  simplex_reset_tableau(solver);
28,772✔
9742
  simplex_restore_matrix(solver);
28,772✔
9743

9744
  assert(solver->matrix_ready && ! solver->tableau_ready);
9745
}
28,772✔
9746

9747

9748

9749
/******************
9750
 *  START SEARCH  *
9751
 *****************/
9752

9753
/*
9754
 * Start search:
9755
 * - simplify the matrix
9756
 * - initialize the tableau
9757
 * - compute the initial assignment
9758
 */
9759
void simplex_start_search(simplex_solver_t *solver) {
13,178✔
9760
  bool feasible;
9761

9762
#if TRACE
9763
  uint32_t i, n;
9764

9765
  printf("---> SIMPLEX START SEARCH\n");
9766
  printf("---> %"PRIu32" initial bounds\n", solver->bstack.top);
9767
  n = solver->bstack.top;
9768
  for (i=0; i<n; i++) {
9769
    printf("     ");
9770
    print_simplex_bound(stdout, solver, i);
9771
    printf("\n");
9772
  }
9773
  printf("\n");
9774
#endif
9775

9776
  // clear the interrupt flag
9777
  solver->interrupted = false;
13,178✔
9778

9779
  /*
9780
   * If start_search is called after pop and without an intervening
9781
   * start_internalization, then matrix_ready and tableau_ready are both false.
9782
   *
9783
   * If start_search is called after push and without an intervening
9784
   * start_internalization, then tableau_ready may be true and matrix_ready
9785
   * false.
9786
   *
9787
   * We force restore reset_tableau and restore_matrix here.
9788
   * This does nothing if the tableau is already reset and the matrix is ready.
9789
   */
9790
  simplex_reset_tableau(solver);
13,178✔
9791
  simplex_restore_matrix(solver);
13,178✔
9792

9793
  assert(solver->matrix_ready && !solver->tableau_ready);
9794

9795
  // reset the search statistics
9796
  simplex_set_initial_stats(solver);
13,178✔
9797

9798
  if (solver->unsat_before_search) {
13,178✔
9799
    record_empty_theory_conflict(solver->core);
×
9800
    solver->stats.num_conflicts ++;
×
9801
    goto done;
×
9802
  }
9803

9804
  // process all level 0 assertions: turn them into bounds
9805
  feasible = simplex_process_assertions(solver);
13,178✔
9806
  if (! feasible) goto done;
13,178✔
9807

9808
  // simplify
9809
  simplex_simplify_matrix(solver);
13,178✔
9810
  assert(good_matrix(&solver->matrix));
9811

9812
  // initialize the propagator here if propagation is enabled
9813
  if (simplex_option_enabled(solver, SIMPLEX_PROPAGATION)) {
13,178✔
9814
    simplex_init_propagator(solver);
12,842✔
9815
  }
9816

9817
  // compute the tableau
9818
  simplex_init_tableau(solver);
13,178✔
9819
  assert(good_matrix(&solver->matrix));
9820

9821
  // set bounds for all fixed variables
9822
  simplex_check_fixed_vars(solver);
13,178✔
9823
  if (solver->unsat_before_search) {
13,178✔
9824
    record_empty_theory_conflict(solver->core);
6✔
9825
    solver->stats.num_conflicts ++;
6✔
9826
    goto done;
6✔
9827
  }
9828

9829
  // compute the initial variable assignment
9830
  reset_int_heap(&solver->infeasible_vars);
13,172✔
9831
  simplex_init_assignment(solver);
13,172✔
9832
  feasible = simplex_make_feasible(solver);
13,172✔
9833
  if (! feasible) goto done;
13,172✔
9834

9835
  solver->last_conflict_row = -1;
13,118✔
9836

9837
  // reset heuristics counters for integer feasibility
9838
  solver->stats.num_branch_atoms = 0;
13,118✔
9839
  solver->stats.num_gomory_cuts = 0;
13,118✔
9840

9841
  // integer solving flags
9842
  // enable_dfeas is used in simplex_dsolver_check
9843
  solver->integer_solving = false;
13,118✔
9844
  solver->enable_dfeas = true;
13,118✔
9845
  if (simplex_has_integer_vars(solver) && simplex_option_enabled(solver, SIMPLEX_ICHECK)) {
13,118✔
9846
#if TRACE
9847
    printf("---> icheck active\n");
9848
    fflush(stdout);
9849
#endif
9850
    solver->check_counter = 0;
156✔
9851
  } else {
9852
    solver->check_counter = INT32_MAX;
12,962✔
9853
  }
9854

9855
  // check initial integer feasibility
9856
  if (! simplex_assignment_integer_valid(solver)) {
13,118✔
9857
#if TRACE
9858
    printf("---> initial assignment not integer feasible\n");
9859
    fflush(stdout);
9860
#endif
9861
  }
9862

9863
  // literals implied by toplevel atoms
9864
  simplex_literal_propagation(solver);
13,118✔
9865

9866
  // theory propagation based on all initial bounds
9867
  if (simplex_option_enabled(solver, SIMPLEX_PROPAGATION)) {
13,118✔
9868
    simplex_start_propagator(solver);
12,799✔
9869
  }
9870

9871
 done:
319✔
9872
#if DUMP
9873
  dump_state(solver);
9874
#endif
9875

9876
#if 0
9877
  printf("\n\n*** SIMPLEX START ***\n");
9878
  // print_simplex_vars_summary(stdout, solver);
9879
  printf("==== Simplex variables ====\n");
9880
  print_simplex_vars(stdout, solver);
9881
  printf("\n==== Tableau ====\n");
9882
  print_simplex_matrix(stdout, solver);
9883
  printf("\n==== Assignment ====\n");
9884
  print_simplex_assignment(stdout, solver);
9885
  printf("\n==== Bounds  ====\n");
9886
  print_simplex_bounds(stdout, solver);
9887
  printf("\n==== Atoms ====\n");
9888
  print_simplex_atoms(stdout, solver);
9889
  printf("\n");
9890
#endif
9891

9892
  return;
13,178✔
9893
}
9894

9895

9896
/*
9897
 * Stop the search: sets flag solver->interrupted to true and
9898
 * stops the diophantine solver if it's active.
9899
 * - the solver->interrupted flag is set to false by start_search
9900
 * - currently, the interrupted flag is checked in every iteration
9901
 *   of the make feasible procedure
9902
 */
9903
void simplex_stop_search(simplex_solver_t *solver) {
1✔
9904
  solver->interrupted = true;
1✔
9905
  if (solver->dsolver != NULL) {
1✔
9906
    dsolver_stop_search(solver->dsolver);
×
9907
  }
9908
}
1✔
9909

9910

9911

9912
/***************
9913
 *  PROPAGATE  *
9914
 **************/
9915

9916
/*
9917
 * Process all assertions
9918
 * - this function may be called before start_search
9919
 * - if it's called before start_search, the tableau is not ready
9920
 */
9921
bool simplex_propagate(simplex_solver_t *solver) {
836,720✔
9922
  bool feasible;
9923

9924
#if TRACE
9925
  printf("---> SIMPLEX PROPAGATE\n");
9926
#endif
9927

9928
  feasible = true;
836,720✔
9929

9930
  if (! solver->tableau_ready) {
836,720✔
9931
    // start search has not been called yet
9932
    assert(solver->decision_level == solver->base_level);
9933
    if (solver->unsat_before_search) {
23,437✔
9934
      record_empty_theory_conflict(solver->core);
76✔
9935
      feasible = false;
76✔
9936
      goto done;
76✔
9937
    }
9938

9939
    feasible = simplex_process_assertions(solver);
23,361✔
9940
    if (! feasible) goto done;
23,361✔
9941

9942
    feasible = simplex_process_egraph_base_assertions(solver);
23,360✔
9943
    goto done;
23,360✔
9944
  }
9945

9946
  assert(! solver->unsat_before_search);
9947

9948
  /*
9949
   * NOTE: we must check whether there are infeasible_vars here.
9950
   *
9951
   * If we get a conflict, we generate a clause that causes backtracking.
9952
   * But it may happen that nothing is propagated to the simplex after this
9953
   * backtracking (i.e., the assertion_queue does not change and the
9954
   * eassertion_queue is empty). In that case, we could end up with
9955
   * an invalid tableau and variable assignment because nothing will
9956
   * force us to restore feasibility. See issues 251 and 253.
9957
   */
9958
  if (solver->assertion_queue.prop_ptr < solver->assertion_queue.top ||
1,227,694✔
9959
      eassertion_queue_is_nonempty(&solver->egraph_queue) ||
414,411✔
9960
      !int_heap_is_empty(&solver->infeasible_vars)) {
297,012✔
9961

9962
    // process all assertions
9963
    feasible = simplex_process_assertions(solver);
519,215✔
9964
    if (! feasible) goto done;
519,215✔
9965

9966
    // assertions from the egraph
9967
    feasible = simplex_process_egraph_assertions(solver);
519,151✔
9968
    if (! feasible) goto done;
519,151✔
9969

9970
    // update the assignment for the non-basic variables
9971
    simplex_fix_nonbasic_assignment(solver);
518,978✔
9972

9973
    // check for feasibility
9974
    feasible = simplex_make_feasible(solver);
518,978✔
9975
    if (! feasible) goto done;
518,978✔
9976

9977
    // propagate egraph equalities
9978
    if (solver->eqprop != NULL) {
491,804✔
9979
      simplex_propagate_equalities(solver);
161,266✔
9980
    }
9981

9982
    /*
9983
     * Theory propagation
9984
     * - propagation may strengthen bounds on integer variables,
9985
     *   which may cause a conflict or require a new call to
9986
     *   make_feasible.
9987
     */
9988
    if (simplex_option_enabled(solver, SIMPLEX_PROPAGATION)) {
491,804✔
9989
      solver->recheck = false;
248,859✔
9990

9991
      if (true) {
9992
        feasible = simplex_do_propagation(solver);
248,859✔
9993
      } else {
9994
        feasible = simplex_strengthen_bounds(solver);
9995
      }
9996

9997
      if (! feasible) goto done;
248,859✔
9998

9999
      if (solver->recheck) {
248,857✔
10000
        simplex_fix_nonbasic_assignment(solver);
35,285✔
10001
        feasible = simplex_make_feasible(solver);
35,285✔
10002
        if (! feasible) goto done;
35,285✔
10003
      } else {
10004
        // there may be implied bounds but they don't require fixing the assignment
10005
        solver->bstack.fix_ptr = solver->bstack.top;
213,572✔
10006
      }
10007

10008
#if DEBUG
10009
      check_vartags(solver);
10010
      check_assignment(solver);
10011
      check_integer_bounds(solver);
10012
#endif
10013
    }
10014

10015
    // propagate literals
10016
    simplex_literal_propagation(solver);
491,734✔
10017

10018
  } else if (solver->bstack.prop_ptr < solver->bstack.top) {
294,068✔
10019
    /*
10020
     * We may end up here on the first call to propagate after
10021
     * simplex_final_check if the diophantine solver has strengthened
10022
     * some bounds without causing a conflict.  In such a case, a new
10023
     * branch &bound atom is created but there are no new assertion yet.
10024
     *
10025
     * We must call simplex_literal_propagation to at least force
10026
     * solver->bstack.prop_ptr to be equal to solver->bstack.top.
10027
     * This is required before the next call to increase decision level.
10028
     */
10029
    simplex_literal_propagation(solver);
253✔
10030
  }
10031

10032
  /*
10033
   * EXPERIMENTAL: periodically test for integer feasibility
10034
   */
10035
  if (false && solver->check_counter -- <= 0) {
10036
    if (simplex_has_integer_vars(solver)) {
10037
      solver->check_counter = solver->check_period;
10038

10039
      feasible = simplex_assignment_integer_valid(solver);
10040
      if (feasible) goto done;
10041

10042
      solver->recheck = false;
10043
      feasible = simplex_dsolver_check(solver);
10044
      if (! feasible) goto done;
10045

10046
#if TRACE_INTFEAS
10047
      assert(solver->dsolver != NULL);
10048
      printf("--- general solution from dsolver ---\n");
10049
      dsolver_print_gen_solution(stdout, solver->dsolver);
10050
      printf("\n\n");
10051
      fflush(stdout);
10052
#endif
10053

10054
      if (solver->recheck) {
10055
        simplex_fix_nonbasic_assignment(solver);
10056
        feasible = simplex_make_feasible(solver);
10057
        if (! feasible) goto done;
10058
      } else {
10059
        // bounds may have been strengthened
10060
        // but don't require fixing the assignment
10061
        solver->bstack.fix_ptr = solver->bstack.top;
10062
      }
10063

10064
#if DEBUG
10065
      check_vartags(solver);
10066
      check_assignment(solver);
10067
      check_integer_bounds(solver);
10068
#endif
10069

10070
      // the dsolver may have added new bounds
10071
      // check whether we can propagate literals
10072
      simplex_literal_propagation(solver);
10073

10074
    } else {
10075
      solver->check_counter = INT32_MAX; // i.e., infinity
10076
    }
10077
  }
10078

10079
 done:
785,802✔
10080
#if DEBUG
10081
  check_bound_marks(solver);
10082
#endif
10083

10084
  return feasible;
836,720✔
10085
}
10086

10087

10088

10089

10090
/*******************
10091
 *   FINAL CHECK   *
10092
 ******************/
10093

10094
/*
10095
 * Check for integer feasibility
10096
 */
10097
fcheck_code_t simplex_final_check(simplex_solver_t *solver) {
14,851✔
10098
#if DEBUG
10099
  check_assignment(solver);
10100
  check_integer_bounds(solver);
10101
  check_vartags(solver);
10102
  check_bound_marks(solver);
10103
#endif
10104

10105
#if TRACE
10106
  printf("---> SIMPLEX FINAL CHECK [dlevel = %"PRIu32", decisions = %"PRIu64"]\n",
10107
         solver->decision_level, solver->core->stats.decisions);
10108
  fflush(stdout);
10109
#endif
10110

10111
  if (simplex_has_integer_vars(solver)) {
14,851✔
10112
    if (simplex_make_integer_feasible(solver)) {
2,075✔
10113
      return FCHECK_SAT;
844✔
10114
    } else {
10115
      return FCHECK_CONTINUE;
1,231✔
10116
    }
10117
  } else {
10118
    assert(simplex_assignment_integer_valid(solver));
10119
    return FCHECK_SAT;
12,776✔
10120
  }
10121
}
10122

10123

10124
/*
10125
 * Clear: nothing to to
10126
 */
10127
void simplex_clear(simplex_solver_t *solver) {
12,764✔
10128
}
12,764✔
10129

10130

10131
/*****************************
10132
 *  INCREASE DECISION LEVEL  *
10133
 ***************************/
10134

10135
/*
10136
 * Increase simplex level but don't do it in eqprop
10137
 * - this is needed in simplex_push
10138
 */
10139
static void simplex_increase_dlevel(simplex_solver_t *solver) {
649,528✔
10140
  uint32_t nb, na;
10141

10142
  nb = solver->bstack.top;
649,528✔
10143
  na = solver->assertion_queue.top;
649,528✔
10144
  arith_push_undo_record(&solver->stack, nb, na);
649,528✔
10145
  solver->decision_level ++;
649,528✔
10146

10147
  // new scope in arena
10148
  arena_push(&solver->arena);
649,528✔
10149
}
649,528✔
10150

10151
/*
10152
 * Increase dlevel in simplex and eqprop
10153
 */
10154
void simplex_increase_decision_level(simplex_solver_t *solver) {
645,128✔
10155
  simplex_increase_dlevel(solver);
645,128✔
10156
  if (solver->eqprop != NULL) {
645,128✔
10157
#if 0
10158
    printf("---> eq prop: increase decision level to %"PRIu32"\n", solver->decision_level);
10159
#endif
10160
    offset_manager_increase_decision_level(&solver->eqprop->mngr);
177,434✔
10161
  }
10162
#if TRACE
10163
  printf("\n---> Simplex: increase decision level to %"PRIu32"\n", solver->decision_level);
10164
#endif
10165
}
645,128✔
10166

10167

10168

10169
/******************
10170
 *  BACKTRACKING  *
10171
 *****************/
10172

10173
/*
10174
 * Backtrack to back_level:
10175
 * - remove all bounds and assertions added at levels > back_level
10176
 * - don't propagate the backtrack to eqprop (this is needed for simplex_pop)
10177
 */
10178
static void simplex_go_back(simplex_solver_t *solver, uint32_t back_level) {
88,472✔
10179
  arith_bstack_t *bstack;
10180
  arith_vartable_t *vtbl;
10181
  arith_undo_record_t *undo;
10182
  int32_t *a;
10183
  uint32_t i, n;
10184
  thvar_t x;
10185
  int32_t k;
10186

10187
  assert(solver->base_level <= back_level && back_level < solver->decision_level);
10188

10189
  /*
10190
   * stack->data[back_level + 1] = record created on entry to back_level + 1
10191
   * so undo->n_bounds = number of bounds processed at back_level
10192
   *    undo->n_assertions = number of assertions processed at back_level
10193
   *
10194
   * When back_level + 1 was entered, simplex_propagate had completed without conflict
10195
   * so bstack->fix_ptr and bstack->prop_ptr were both equal to bstack->top,
10196
   * and assertion_queue->prop_ptr was equal to assertion_queue->top.
10197
   */
10198
  assert(back_level + 1 < solver->stack.top);
10199
  undo = solver->stack.data + back_level + 1;
88,472✔
10200

10201
  vtbl = &solver->vtbl;
88,472✔
10202
  bstack = &solver->bstack;
88,472✔
10203

10204

10205
  /*
10206
   * Remove the bounds and fix the lb/ub tags
10207
   */
10208
  assert(undo->n_bounds <= bstack->prop_ptr && bstack->prop_ptr <= bstack->fix_ptr &&
10209
         bstack->fix_ptr <= bstack->top);
10210

10211
  i = bstack->top;
88,472✔
10212

10213
  /*
10214
   * Bounds in bstack[fix_ptr ... top-1] have not been visited by fix_nonbasic_assignment
10215
   * - so variable assignment and tags are what they were before
10216
   *   all bounds i for bstack->fix_ptr <= i < bstack->top have
10217
   *   been processed
10218
   * ==> we must not touch the lb or ub tags for these bounds
10219
   */
10220
  n = bstack->fix_ptr;
88,472✔
10221
  while (i > n) {
90,403✔
10222
    i --;
1,931✔
10223
    x = bstack->var[i];
1,931✔
10224
    k = bstack->pre[i]; // previous bound of the same kind
1,931✔
10225
    if (constraint_is_lower_bound(bstack, i)) {
1,931✔
10226
      // restore k as lower index
10227
      set_arith_var_lower_index(vtbl, x, k);
1,046✔
10228
    } else {
10229
      // restore k as upper index
10230
      assert(constraint_is_upper_bound(bstack, i));
10231
      set_arith_var_upper_index(vtbl, x, k);
885✔
10232
    }
10233
  }
10234

10235

10236
  /*
10237
   * Rest of the bounds: restore previous bound and clear the tags
10238
   */
10239
  n = undo->n_bounds;
88,472✔
10240
  while (i > n) {
1,928,532✔
10241
    i --;
1,840,060✔
10242
    x = bstack->var[i];
1,840,060✔
10243
    k = bstack->pre[i]; // previous bound of the same kind
1,840,060✔
10244
    if (constraint_is_lower_bound(bstack, i)) {
1,840,060✔
10245
      clear_arith_var_lb(vtbl, x);
903,503✔
10246
      set_arith_var_lower_index(vtbl, x, k);
903,503✔
10247
    } else {
10248
      assert(constraint_is_upper_bound(bstack, i));
10249
      clear_arith_var_ub(vtbl, x);
936,557✔
10250
      set_arith_var_upper_index(vtbl, x, k);
936,557✔
10251
    }
10252
  }
10253

10254
  bstack->top = n;
88,472✔
10255
  bstack->prop_ptr = n;
88,472✔
10256
  bstack->fix_ptr = n;
88,472✔
10257

10258
  /*
10259
   * Remove the assertions
10260
   */
10261
  assert(undo->n_assertions <= solver->assertion_queue.prop_ptr &&
10262
         solver->assertion_queue.prop_ptr <= solver->assertion_queue.top);
10263

10264
  n = undo->n_assertions;
88,472✔
10265
  a = solver->assertion_queue.data;
88,472✔
10266
  i = solver->assertion_queue.top;
88,472✔
10267
  while (i > n) {
2,337,569✔
10268
    i --;
2,249,097✔
10269
    k = atom_of_assertion(a[i]);
2,249,097✔
10270
    unmark_arith_atom(&solver->atbl, k);
2,249,097✔
10271
  }
10272
  solver->assertion_queue.top = n;
88,472✔
10273
  solver->assertion_queue.prop_ptr = n;
88,472✔
10274

10275
  /*
10276
   * Backtrack arena
10277
   */
10278
  n = solver->decision_level;
88,472✔
10279
  do {
10280
    arena_pop(&solver->arena);
637,693✔
10281
    n --;
637,693✔
10282
  } while (n > back_level);
637,693✔
10283

10284

10285
  /*
10286
   * Empty the egraph queue
10287
   */
10288
  reset_eassertion_queue(&solver->egraph_queue);
88,472✔
10289

10290
  /*
10291
   * Restore the undo stack and the decision level
10292
   */
10293
  solver->stack.top = back_level + 1;
88,472✔
10294
  solver->decision_level = back_level;
88,472✔
10295
}
88,472✔
10296

10297

10298
/*
10299
 * Full backtrack
10300
 */
10301
void simplex_backtrack(simplex_solver_t *solver, uint32_t back_level) {
88,300✔
10302
#if TRACE
10303
  printf("---> Simplex: backtracking to level %"PRIu32"\n", back_level);
10304
#endif
10305

10306
  simplex_go_back(solver, back_level);
88,300✔
10307
  if (solver->eqprop != NULL) {
88,300✔
10308
#if 0
10309
    printf("---> eq prop: backtrack to level %"PRIu32"\n", back_level);
10310
#endif
10311
    offset_manager_backtrack(&solver->eqprop->mngr, back_level);
12,020✔
10312
  }
10313

10314

10315
#if DEBUG
10316
  if (solver->tableau_ready) {
10317
    /*
10318
     * NOTE: this may give false alarms if backtrack is called
10319
     * within simplex_pop because the context may be known to
10320
     * be UNSAT before make_feasible or init_assignment have
10321
     * been called.
10322
     *
10323
     * TODO: Fix this.
10324
     */
10325
    check_vartags(solver);
10326
    check_nonbasic_assignment(solver);
10327
  }
10328
#endif
10329

10330
#if TRACE
10331
  printf("---> Simplex: end backtracking\n\n");
10332
#endif
10333

10334

10335
}
88,300✔
10336

10337

10338

10339
/********************
10340
 *  PUSH/POP/RESET  *
10341
 *******************/
10342

10343
/*
10344
 * Start a new base level
10345
 */
10346
void simplex_push(simplex_solver_t *solver) {
4,400✔
10347
  uint32_t nv, na, nr, pa, pb;
10348

10349
  assert(solver->decision_level == solver->base_level &&
10350
         solver->bstack.prop_ptr == solver->bstack.fix_ptr &&
10351
         solver->save_rows &&
10352
         eassertion_queue_is_empty(&solver->egraph_queue));
10353

10354
  nv = solver->vtbl.nvars;
4,400✔
10355
  na = solver->atbl.natoms;
4,400✔
10356
  nr = solver->saved_rows.size;
4,400✔
10357
  pa = solver->assertion_queue.prop_ptr;
4,400✔
10358
  pb = solver->bstack.prop_ptr;
4,400✔
10359
  arith_trail_save(&solver->trail_stack, nv, na, nr, pa, pb);
4,400✔
10360

10361
  if (solver->cache != NULL) {
4,400✔
10362
    cache_push(solver->cache);
×
10363
  }
10364

10365
  solver->base_level ++;
4,400✔
10366

10367
  /*
10368
   * we don't want increase_decision_level here (otherwise,
10369
   * eqprop's decision level would be incremented twice).
10370
   */
10371
  simplex_increase_dlevel(solver);
4,400✔
10372

10373
  // propagate to eqprop if present
10374
  if (solver->eqprop != NULL) {
4,400✔
10375
    simplex_push_eqprop(solver);
153✔
10376
  }
10377
}
4,400✔
10378

10379

10380
/*
10381
 * Remove all atoms whose id is >= na from the variable indices
10382
 * - this is called before the atoms are actually removed from
10383
 *   the atom table
10384
 */
10385
static void simplex_detach_dead_atoms(simplex_solver_t *solver, uint32_t na) {
172✔
10386
  arith_vartable_t *vtbl;
10387
  arith_atomtable_t *atbl;
10388
  arith_atom_t *atm;
10389
  uint32_t i, n, nv;
10390
  thvar_t x;
10391

10392
  assert(na <= solver->atbl.natoms);
10393

10394
  atbl = &solver->atbl;
172✔
10395
  vtbl = &solver->vtbl;
172✔
10396

10397
  nv = vtbl->nvars;
172✔
10398
  n = atbl->natoms;
172✔
10399
  for (i=na; i<n; i++) {
943✔
10400
    atm = arith_atom(atbl, i);
771✔
10401
    x = var_of_atom(atm);
771✔
10402
    if (x < nv) {
771✔
10403
      // x is still a good variable
10404
      detach_atom_from_arith_var(vtbl, x, i);
75✔
10405
    }
10406
  }
10407
}
172✔
10408

10409

10410
/*
10411
 * Remove all eterms whose id is >= nt from the term table
10412
 * - this is required to synchronize the egraph and simplex solver after pop.
10413
 * - the egraph removes the dead eterms first then invoke the pop function
10414
 *   of all satellite solvers.
10415
 * - if arithmetic variable x is kept after pop but the egraph term
10416
 *   eterm[x] is not kept, then we must clear eterm[x]
10417
 *
10418
 * NOTE: this work because the 'pop' function in the egraph removes
10419
 * its own dead terms before calling the 'pop' function of all
10420
 * satellite solvers.
10421
 */
10422
static void simplex_remove_dead_eterms(simplex_solver_t *solver) {
172✔
10423
  uint32_t nterms;
10424

10425
  if (solver->egraph != NULL) {
172✔
10426
    nterms = egraph_num_terms(solver->egraph);
169✔
10427
    arith_vartable_remove_eterms(&solver->vtbl, nterms);
169✔
10428
  }
10429
}
172✔
10430

10431

10432
/*
10433
 * Number of active variables = all variables x whose
10434
 * definition p is not a simple polynomial.
10435
 * For all these variables, the matrix contains a row of
10436
 * the form x - p = 0.  If x is alive, this row must be kept
10437
 * when we backtrack.
10438
 */
10439
static uint32_t num_active_vars(arith_vartable_t *vtbl) {
38✔
10440
  polynomial_t *p;
10441
  uint32_t a, i, n;
10442

10443
  a = 0;
38✔
10444
  n = vtbl->nvars;
38✔
10445
  // skip var 0 since it's not a polynomial
10446
  for (i=1; i<n; i++) {
742✔
10447
    p = arith_var_def(vtbl, i);
704✔
10448
    if (p != NULL && !simple_poly(p)) {
704✔
10449
      a++;
30✔
10450
    }
10451
  }
10452

10453
  return a;
38✔
10454
}
10455

10456

10457
/*
10458
 * Scan the bound stack backward from top to fix_ptr
10459
 * and clear the ub/lb tags of all variables.
10460
 */
10461
static void roll_back_fix_ptr(simplex_solver_t *solver) {
172✔
10462
  arith_bstack_t *bstack;
10463
  arith_vartable_t *vtbl;
10464
  uint32_t i, n;
10465
  thvar_t x;
10466

10467
  vtbl = &solver->vtbl;
172✔
10468
  bstack = &solver->bstack;
172✔
10469

10470
  i = bstack->top;
172✔
10471
  n = bstack->fix_ptr;
172✔
10472
  while (i > n) {
456✔
10473
    i --;
284✔
10474
    x = bstack->var[i];
284✔
10475
    if (xq_eq(bstack->bound + i, arith_var_value(vtbl, x))) {
284✔
10476
      // value[x] = bound[k]
10477
      if (constraint_is_lower_bound(bstack, i)) {
134✔
10478
        clear_arith_var_lb(vtbl, x);
81✔
10479
      } else {
10480
        assert(constraint_is_upper_bound(bstack, i));
10481
        clear_arith_var_ub(vtbl, x);
53✔
10482
      }
10483
    }
10484
  }
10485
}
172✔
10486

10487

10488
/*
10489
 * Return to the previous base level
10490
 */
10491
void simplex_pop(simplex_solver_t *solver) {
172✔
10492
  arith_trail_t *top;
10493
  arith_undo_record_t *undo;
10494
  uint32_t nrows, ncolumns;
10495

10496
  assert(solver->base_level > 0 &&
10497
         solver->base_level == solver->decision_level &&
10498
         solver->save_rows);
10499

10500
  solver->unsat_before_search = false;
172✔
10501

10502

10503
  /*
10504
   * HACKISH: Backtrack to the previous base_level
10505
   *
10506
   * undo = trail object saved on entry to the current base_level
10507
   * undo->n_bounds = number of bounds in bstack on entry to base_level
10508
   * undo->n_assertions = number of assertions in assertion_queue on
10509
   *                  entry to current base_level
10510
   *
10511
   * If simplex_pop is called without a simplex_check then the
10512
   * preconditions of simplex_backtrack may not hold. We may have
10513
   *     bstack->fix_ptr  < undo->n_bounds
10514
   *     bstack->prop_ptr < undo->n_bounds
10515
   *     assertion_queue->prop_ptr < assertion_queue->n_assertions.
10516
   *
10517
   * In such a case, we fix the fix/prop_ptr before calling
10518
   * backtrack. This does not cause problems since we'll restore
10519
   * fix_ptr/prop_ptr after simplex_backtrack anyway.
10520
   */
10521
  undo = solver->stack.data + solver->base_level;
172✔
10522
  solver->base_level --;
172✔
10523

10524
  if (solver->bstack.fix_ptr < undo->n_bounds) {
172✔
10525
    solver->bstack.fix_ptr = undo->n_bounds;
2✔
10526
  }
10527
  if (solver->bstack.prop_ptr < undo->n_bounds) {
172✔
10528
    solver->bstack.prop_ptr = undo->n_bounds;
2✔
10529
  }
10530
  if (solver->assertion_queue.prop_ptr < undo->n_assertions) {
172✔
10531
    solver->assertion_queue.prop_ptr = undo->n_assertions;
×
10532
  }
10533
  // can't use simplex_backtrack here
10534
  simplex_go_back(solver, solver->base_level);
172✔
10535

10536

10537
  /*
10538
   * Remove variables in eqprop. This must be done before we delete
10539
   * variables in solver->vtbl, because polynomials in vtbl->def[x]
10540
   * may occur in the eqprop's data structures.
10541
   */
10542
  if (solver->eqprop != NULL) {
172✔
10543
    simplex_pop_eqprop(solver);
141✔
10544
  }
10545

10546
  /*
10547
   * Remove saved_rows, variables, and atoms that were
10548
   * created at the current base_level.
10549
   */
10550
  top = arith_trail_top(&solver->trail_stack);
172✔
10551
  delete_saved_rows(&solver->saved_rows, top->nsaved_rows);
172✔
10552
  arith_vartable_remove_vars(&solver->vtbl, top->nvars);
172✔
10553
  simplex_detach_dead_atoms(solver, top->natoms);
172✔
10554
  arith_atomtable_remove_atoms(&solver->atbl, top->natoms);
172✔
10555
  simplex_remove_dead_eterms(solver);
172✔
10556

10557
  if (solver->cache != NULL) {
172✔
10558
    cache_pop(solver->cache);
×
10559
  }
10560

10561
  // restore the propagation pointers
10562
  solver->bstack.prop_ptr = top->bound_ptr;
172✔
10563
  solver->bstack.fix_ptr = top->bound_ptr;
172✔
10564
  solver->assertion_queue.prop_ptr = top->assertion_ptr;
172✔
10565

10566
  /*
10567
   * If bstack->fix_ptr < bstack->top, we must now revisit
10568
   * all bounds in bstack[fix_ptr ... top-1] and clear the
10569
   * lb/ub tags of variables.
10570
   */
10571
  roll_back_fix_ptr(solver);
172✔
10572

10573
  // remove trail object
10574
  arith_trail_pop(&solver->trail_stack);
172✔
10575

10576
  if (solver->tableau_ready) {
172✔
10577
    // delete the tableau
10578
    simplex_reset_tableau(solver);
131✔
10579
  } else if (solver->matrix_ready) {
41✔
10580
    // push/pop called without check
10581
    // remove dead rows and columns
10582
    nrows = solver->saved_rows.size + num_active_vars(&solver->vtbl);
38✔
10583
    ncolumns = num_arith_vars(&solver->vtbl);
38✔
10584
    matrix_shrink(&solver->matrix, nrows, ncolumns);
38✔
10585
  }
10586

10587
  // cleanup the relevant marks of deleted variables
10588
  // reset propagation pointer in eqprop
10589
  if (solver->eqprop != NULL) {
172✔
10590
    simplex_eqprop_cleanup(solver);
141✔
10591
  }
10592
}
172✔
10593

10594

10595
/*
10596
 * Reset to the empty solver
10597
 */
10598
void simplex_reset(simplex_solver_t *solver) {
1✔
10599
  uint32_t n;
10600

10601
  solver->base_level = 0;
1✔
10602
  solver->decision_level = 0;
1✔
10603
  solver->unsat_before_search = false;
1✔
10604
  solver->interrupted = false;
1✔
10605

10606
  solver->prng = SPLX_PRNG_SEED;
1✔
10607

10608
  reset_simplex_statistics(&solver->stats);
1✔
10609

10610
  n = solver->vtbl.nvars;
1✔
10611
  if (solver->value != NULL) {
1✔
10612
    free_rational_array(solver->value, n);
×
10613
    solver->value = NULL;
×
10614
  }
10615
  q_clear(&solver->epsilon);
1✔
10616
  q_clear(&solver->factor);
1✔
10617
  solver->dprng = DPRNG_DEFAULT_SEED;
1✔
10618

10619
  reset_arith_atomtable(&solver->atbl);
1✔
10620
  reset_arith_vartable(&solver->vtbl);
1✔
10621

10622
  reset_matrix(&solver->matrix);
1✔
10623
  solver->tableau_ready = false;
1✔
10624
  solver->matrix_ready = true;
1✔
10625

10626
  solver->last_conflict_row = -1;
1✔
10627
  solver->recheck = false;
1✔
10628
  solver->integer_solving = false;
1✔
10629
  solver->enable_dfeas = false;
1✔
10630

10631
  if (solver->dsolver != NULL) {
1✔
10632
    reset_dsolver(solver->dsolver);
×
10633
  }
10634

10635
  if (solver->cache != NULL) {
1✔
10636
    reset_cache(solver->cache);
×
10637
  }
10638

10639
  if (solver->eqprop != NULL) {
1✔
10640
    simplex_reset_eqprop(solver);
×
10641
  }
10642

10643
  if (solver->propagator != NULL) {
1✔
10644
    simplex_reset_propagator(solver);
×
10645
  }
10646

10647
  reset_int_heap(&solver->infeasible_vars);
1✔
10648
  reset_arith_bstack(&solver->bstack);
1✔
10649
  reset_arith_astack(&solver->assertion_queue);
1✔
10650
  reset_eassertion_queue(&solver->egraph_queue);
1✔
10651
  reset_arith_undo_stack(&solver->stack);
1✔
10652

10653
  reset_arith_trail(&solver->trail_stack);
1✔
10654
  delete_saved_rows(&solver->saved_rows, 0);
1✔
10655

10656
  reset_elim_matrix(&solver->elim);
1✔
10657
  reset_fvar_vector(&solver->fvars);
1✔
10658

10659
  reset_poly_buffer(&solver->buffer);
1✔
10660
  q_clear(&solver->constant);
1✔
10661
  q_clear(&solver->aux);
1✔
10662
  q_clear(&solver->gcd);
1✔
10663
  xq_clear(&solver->bound);
1✔
10664
  xq_clear(&solver->delta);
1✔
10665
  xq_clear(&solver->xq0);
1✔
10666

10667
  ivector_reset(&solver->expl_vector);
1✔
10668
  ivector_reset(&solver->expl_queue);
1✔
10669
  ivector_reset(&solver->expl_aux);
1✔
10670

10671
  ivector_reset(&solver->aux_vector);
1✔
10672
  ivector_reset(&solver->aux_vector2);
1✔
10673
  ivector_reset(&solver->rows_to_process);
1✔
10674

10675
  // empty arena
10676
  arena_reset(&solver->arena);
1✔
10677

10678
  // add the constant
10679
  simplex_create_constant(solver);
1✔
10680

10681
  // push undo record for level 0
10682
  arith_push_undo_record(&solver->stack, 0, 0);
1✔
10683
}
1✔
10684

10685

10686

10687

10688
/*****************
10689
 *  ASSERT ATOM  *
10690
 ****************/
10691

10692
/*
10693
 * Assertion from the core:
10694
 * - a = simplex atom index (packed into a void* pointer)
10695
 * - l = literal pos(x) or neg(x) where x = boolean variable for x
10696
 * - if l == pos(x) then a must be asserted true
10697
 * - if l == neg(x) then a must be asserted false
10698
 *
10699
 * We skip a if the solver already knows that a is assigned. Otherwise,
10700
 * we just add the corresponding assertion code to the assertion queue.
10701
 */
10702
bool simplex_assert_atom(simplex_solver_t *solver, void *a, literal_t l) {
2,260,259✔
10703
  int32_t id;
10704

10705
  id = arithatom_tagged_ptr2idx(a);
2,260,259✔
10706
  assert(boolvar_of_atom(arith_atom(&solver->atbl, id)) == var_of(l));
10707

10708
  if (arith_atom_is_unmarked(&solver->atbl, id)) {
2,260,259✔
10709
    push_assertion(&solver->assertion_queue, mk_assertion(id, sign_of(l)));
1,820,762✔
10710
    mark_arith_atom(&solver->atbl, id);
1,820,762✔
10711

10712
#if TRACE
10713
    printf("---> added atom[%"PRId32"]: ", id);
10714
    print_simplex_atom(stdout, solver, id);
10715
    if (is_pos(l)) {
10716
      printf("  (p!%"PRId32" is true)\n", var_of(l));
10717
    } else {
10718
      printf("  (p!%"PRId32" is false)\n", var_of(l));
10719
    }
10720
  } else {
10721
    printf("---> skipped atom[%"PRId32"]: ", id);
10722
    print_simplex_atom(stdout, solver, id);
10723
    if (is_pos(l)) {
10724
      printf("  (true)\n");
10725
    } else {
10726
      printf("  (false)\n");
10727
    }
10728
#endif
10729
  }
10730

10731
  return true;
2,260,259✔
10732
}
10733

10734

10735

10736

10737

10738
/*************************
10739
 *  THEORY EXPLANATIONS  *
10740
 ************************/
10741

10742
/*
10743
 * Expand a propagation object into a conjunction of literals
10744
 * - expl is a pointer to a propagation object in solver->arena
10745
 *
10746
 * NOTE: the old APROP_EGRAPH_DISEQ is not used anymore,
10747
 */
10748
void simplex_expand_explanation(simplex_solver_t *solver, literal_t l, aprop_header_t *expl, ivector_t *v) {
3,667✔
10749
  assert(expl->tag == APROP_BOUND);
10750
  simplex_explain_bound(solver, ((aprop_t *) expl)->bound, v);
3,667✔
10751
}
3,667✔
10752

10753

10754

10755

10756
/*************************
10757
 *  SPLITTING HEURISTIC  *
10758
 ************************/
10759

10760
/*
10761
 * Evaluate atom in the current assignment
10762
 */
10763
static bool simplex_eval_atom(simplex_solver_t *solver, arith_atom_t *atom) {
268,713✔
10764
  thvar_t x;
10765
  bool b;
10766

10767
  b = false;   // prevents a GCC warning
268,713✔
10768
  x = var_of_atom(atom);
268,713✔
10769
  switch (tag_of_atom(atom)) {
268,713✔
10770
  case GE_ATM:
167,012✔
10771
    b = xq_ge_q(arith_var_value(&solver->vtbl, x), bound_of_atom(atom));
167,012✔
10772
    break;
167,012✔
10773
  case LE_ATM:
101,701✔
10774
    b = xq_le_q(arith_var_value(&solver->vtbl, x), bound_of_atom(atom));
101,701✔
10775
    break;
101,701✔
10776
  case EQ_ATM:
×
10777
    b = xq_eq_q(arith_var_value(&solver->vtbl, x), bound_of_atom(atom));
×
10778
    break;
×
10779
  }
10780

10781
#if TRACE && ! DEBUG
10782
  printf("---> atom: ");
10783
  print_simplex_atom(stdout, solver, arith_atom_id(&solver->atbl, atom));
10784
  if (b) {
10785
    printf(" is true\n");
10786
  } else {
10787
    printf(" is false\n");
10788
  }
10789
#endif
10790

10791
  return b;
268,713✔
10792
}
10793

10794

10795
/*
10796
 * Return l or (not l)
10797
 * - a = atom attached to l = simplex atom index packed in a void* pointer
10798
 */
10799
literal_t simplex_select_polarity(simplex_solver_t *solver, void *a, literal_t l) {
268,713✔
10800
  arith_atom_t *atom;
10801
  int32_t id;
10802
  bvar_t v;
10803

10804
  id = arithatom_tagged_ptr2idx(a);
268,713✔
10805
  atom = arith_atom(&solver->atbl, id);
268,713✔
10806
  v = var_of(l);
268,713✔
10807

10808
  if (v == solver->last_branch_atom && drand(&solver->dprng) > 0.1) {
268,713✔
10809
    // for a branch & bound atom
10810
    // we branch the opposite of the model
10811
    solver->last_branch_atom = null_bvar;
492✔
10812
    if (simplex_eval_atom(solver, atom)) {
492✔
10813
      return neg_lit(v);
119✔
10814
    } else {
10815
      return pos_lit(v);
373✔
10816
    }
10817
  }
10818

10819
  if (simplex_eval_atom(solver, atom)) {
268,221✔
10820
    return pos_lit(v);
167,076✔
10821
  } else {
10822
    return neg_lit(v);
101,145✔
10823
  }
10824
}
10825

10826

10827

10828
/*
10829
 * Select polarity when branching on an egraph equality
10830
 * - l is attached to an egraph atom (eq u1 u2)
10831
 * - x1 and x2 are the theory variables for u1 and u2, respectively
10832
 * - return l if (x1 == x2) in the current assignment
10833
 *   return (not l) otherwise
10834
 */
10835
literal_t simplex_select_eq_polarity(simplex_solver_t *solver, thvar_t x1, thvar_t x2, literal_t l) {
333✔
10836
  if (xq_eq(arith_var_value(&solver->vtbl, x1), arith_var_value(&solver->vtbl, x2))) {
333✔
10837
    return l;
275✔
10838
  } else {
10839
    return not(l);
58✔
10840
  }
10841
}
10842

10843

10844

10845

10846
/**********************
10847
 * DELETE THE SOLVER  *
10848
 *********************/
10849

10850
void delete_simplex_solver(simplex_solver_t *solver) {
4,880✔
10851
  uint32_t n;
10852

10853
  n = solver->vtbl.nvars;
4,880✔
10854
  if (solver->value != NULL) {
4,880✔
10855
    free_rational_array(solver->value, n);
×
10856
    solver->value = NULL;
×
10857
  }
10858
  q_clear(&solver->epsilon);
4,880✔
10859
  q_clear(&solver->factor);
4,880✔
10860

10861
  delete_arith_atomtable(&solver->atbl);
4,880✔
10862
  delete_arith_vartable(&solver->vtbl);
4,880✔
10863

10864
  if (solver->eqprop != NULL) {
4,880✔
10865
    simplex_delete_eqprop(solver);
71✔
10866
  }
10867

10868
  if (solver->propagator != NULL) {
4,880✔
10869
    simplex_delete_propagator(solver);
×
10870
  }
10871

10872
  if (solver->dsolver != NULL) {
4,880✔
10873
    delete_dsolver(solver->dsolver);
×
10874
    safe_free(solver->dsolver);
×
10875
    solver->dsolver = NULL;
×
10876
  }
10877

10878
  if (solver->cache != NULL) {
4,880✔
10879
    delete_cache(solver->cache);
2✔
10880
    safe_free(solver->cache);
2✔
10881
    solver->cache = NULL;
2✔
10882
  }
10883

10884
  delete_matrix(&solver->matrix);
4,880✔
10885
  delete_int_heap(&solver->infeasible_vars);
4,880✔
10886
  delete_arith_bstack(&solver->bstack);
4,880✔
10887
  delete_arith_astack(&solver->assertion_queue);
4,880✔
10888
  delete_eassertion_queue(&solver->egraph_queue);
4,880✔
10889
  delete_arith_undo_stack(&solver->stack);
4,880✔
10890

10891
  delete_arith_trail(&solver->trail_stack);
4,880✔
10892
  delete_saved_rows(&solver->saved_rows, 0);
4,880✔
10893
  delete_pvector(&solver->saved_rows);
4,880✔
10894

10895
  delete_elim_matrix(&solver->elim);
4,880✔
10896
  delete_fvar_vector(&solver->fvars);
4,880✔
10897

10898
  delete_poly_buffer(&solver->buffer);
4,880✔
10899
  q_clear(&solver->constant);
4,880✔
10900
  q_clear(&solver->aux);
4,880✔
10901
  q_clear(&solver->gcd);
4,880✔
10902
  xq_clear(&solver->bound);
4,880✔
10903
  xq_clear(&solver->delta);
4,880✔
10904
  xq_clear(&solver->xq0);
4,880✔
10905

10906
  delete_ivector(&solver->expl_vector);
4,880✔
10907
  delete_ivector(&solver->expl_queue);
4,880✔
10908
  delete_ivector(&solver->expl_aux);
4,880✔
10909
  delete_ivector(&solver->aux_vector);
4,880✔
10910
  delete_ivector(&solver->aux_vector2);
4,880✔
10911
  delete_ivector(&solver->rows_to_process);
4,880✔
10912

10913
  delete_arena(&solver->arena);
4,880✔
10914
}
4,880✔
10915

10916

10917

10918

10919

10920

10921
/*********************************
10922
 *   INTERFACE WITH THE EGRAPH   *
10923
 ********************************/
10924

10925
/*
10926
 * Save egraph assertions in the assertion queue
10927
 * - x1 and x2: become equal after the egraph merge two classes c1 and c2
10928
 *   such that thvar[c1] = x1 and thvar[c2] = x2
10929
 * - id = index of the egraph edge that caused c1 and c2 to be merged
10930
 */
10931
void simplex_assert_var_eq(simplex_solver_t *solver, thvar_t x1, thvar_t x2, int32_t id) {
150,675✔
10932
  assert(arith_var_has_eterm(&solver->vtbl, x1) && arith_var_has_eterm(&solver->vtbl, x2));
10933
  eassertion_push_eq(&solver->egraph_queue, x1, x2, id);
150,675✔
10934

10935
#if TRACE
10936
  printf("\n---> Simplex: received egraph equality: ");
10937
  print_simplex_var(stdout, solver, x1);
10938
  printf(" = ");
10939
  print_simplex_var(stdout, solver, x2);
10940
  printf("\n---> ");
10941
  print_simplex_vardef(stdout, solver, x1);
10942
  printf("---> ");
10943
  print_simplex_vardef(stdout, solver, x2);
10944
  printf("---> eterm[");
10945
  print_simplex_var(stdout, solver, x1);
10946
  printf("] = g!%"PRId32"\n", arith_var_get_eterm(&solver->vtbl, x1));
10947
  printf("---> eterm[");
10948
  print_simplex_var(stdout, solver, x2);
10949
  printf("] = g!%"PRId32"\n", arith_var_get_eterm(&solver->vtbl, x2));
10950
#endif
10951
}
150,675✔
10952

10953
void simplex_assert_var_diseq(simplex_solver_t *solver, thvar_t x1, thvar_t x2, composite_t *hint) {
317,312✔
10954
  assert(arith_var_has_eterm(&solver->vtbl, x1) && arith_var_has_eterm(&solver->vtbl, x2));
10955
  eassertion_push_diseq(&solver->egraph_queue, x1, x2, hint);
317,312✔
10956

10957
#if TRACE
10958
  printf("---> Simplex: received egraph disequality: ");
10959
  print_simplex_var(stdout, solver, x1);
10960
  printf(" != ");
10961
  print_simplex_var(stdout, solver, x2);
10962
  printf("\n---> ");
10963
  print_simplex_vardef(stdout, solver, x1);
10964
  printf("---> ");
10965
  print_simplex_vardef(stdout, solver, x2);
10966
#endif
10967
}
317,312✔
10968

10969
void simplex_assert_var_distinct(simplex_solver_t *solver, uint32_t n, thvar_t *a, composite_t *hint) {
2✔
10970
#ifndef NDEBUG
10971
  uint32_t i;
10972
  for (i=0; i<n; i++) {
10973
    assert(arith_var_has_eterm(&solver->vtbl, a[i]));
10974
  }
10975
#endif
10976

10977
  eassertion_push_distinct(&solver->egraph_queue, n, a, hint);
2✔
10978
}
2✔
10979

10980

10981
/*
10982
 * Check whether x1 and x2 are distinct at the base level
10983
 */
10984
bool simplex_check_disequality(simplex_solver_t *solver, thvar_t x1, thvar_t x2) {
11,588✔
10985
  poly_buffer_t *b;
10986
  bool diseq;
10987

10988
  assert(valid_arith_var(&solver->vtbl, x1) && valid_arith_var(&solver->vtbl, x2));
10989

10990
  b = &solver->buffer;
11,588✔
10991
  assert(poly_buffer_nterms(b) == 0);
10992
  add_var_or_subst(solver, b, x1);
11,588✔
10993
  sub_var_or_subst(solver, b, x2);
11,588✔
10994
  normalize_poly_buffer(b);
11,588✔
10995

10996
  diseq = poly_buffer_is_nzconstant(b);
11,588✔
10997
  reset_poly_buffer(b);
11,588✔
10998

10999
  return diseq;
11,588✔
11000
}
11001

11002

11003
/*
11004
 * Check whether x is a constant
11005
 */
11006
bool simplex_var_is_constant(simplex_solver_t *solver, thvar_t x) {
61,323✔
11007
  polynomial_t *q;
11008

11009
  if (x == const_idx) {
61,323✔
11010
    return true;
×
11011
  }
11012
  q = arith_var_def(&solver->vtbl, x);
61,323✔
11013
  return q != NULL && polynomial_is_constant(q);
61,323✔
11014
}
11015

11016

11017

11018

11019
/*
11020
 * MODEL PREPARATION FOR RECONCILE MODEL
11021
 */
11022

11023
/*
11024
 * Support for build model: evaluate polynomial p in the current assignment.
11025
 * - store the result in q
11026
 */
11027
static void simplex_eval_poly(simplex_solver_t *solver, polynomial_t *p, xrational_t *q) {
5,860✔
11028
  uint32_t i, n;
11029
  thvar_t x;
11030

11031
  xq_clear(q);
5,860✔
11032
  n = p->nterms;
5,860✔
11033
  for (i=0; i<n; i++) {
14,879✔
11034
    x = p->mono[i].var;
9,019✔
11035
    if (x == const_idx) {
9,019✔
11036
      xq_add_q(q, &p->mono[i].coeff);
5,049✔
11037
    } else {
11038
      assert(! trivial_variable(&solver->vtbl, x));
11039
      xq_addmul(q, arith_var_value(&solver->vtbl, x), &p->mono[i].coeff);
3,970✔
11040
    }
11041
  }
11042
}
5,860✔
11043

11044

11045
/*
11046
 * Build model: compute the value of trivial variables
11047
 * - for a trivial variable x, we have x := p where p is a simple polynomial
11048
 * - p is either a constant k or (a.y) or (k + a.y) where y is not a trivial
11049
 *   variable so the value of y is known.
11050
 * - if x is a trivial variable and has an eterm attached, then its value is
11051
 *   important
11052
 */
11053
static void simplex_prepare_model(simplex_solver_t *solver) {
13,311✔
11054
  arith_vartable_t *vtbl;
11055
  polynomial_t *p;
11056
  uint32_t i, n;
11057

11058
  assert(simplex_assignment_integer_valid(solver));
11059
#if DEBUG
11060
  check_assignment(solver);
11061
  check_integer_bounds(solver);
11062
  check_vartags(solver);
11063
  check_bound_marks(solver);
11064
#endif
11065

11066
  vtbl = &solver->vtbl;
13,311✔
11067
  n = vtbl->nvars;
13,311✔
11068
  for (i=1; i<n; i++) { // skip const_idx
270,929✔
11069
    p = arith_var_def(vtbl, i);
257,618✔
11070
    if (p != NULL && simple_poly(p)) {
257,618✔
11071
      assert(trivial_variable(vtbl, i));
11072
      // i is a trivial variable: compute its value = evaluate p
11073
      simplex_eval_poly(solver, p, arith_var_value(vtbl, i));
5,860✔
11074
    }
11075
  }
11076
}
13,311✔
11077

11078

11079

11080
/*
11081
 * Check whether x1 and x2 are equal in the model
11082
 */
11083
static bool simplex_var_equal_in_model(simplex_solver_t *solver, thvar_t x1, thvar_t x2) {
6,334✔
11084
  xrational_t *v1, *v2;
11085

11086
  v1 = arith_var_value(&solver->vtbl, x1);
6,334✔
11087
  v2 = arith_var_value(&solver->vtbl, x2);
6,334✔
11088
  return xq_eq(v1, v2);
6,334✔
11089
}
11090

11091

11092

11093
/*
11094
 * Hash function used in the integer partition used below
11095
 * - x and y match if they have the same value in the model
11096
 */
11097
static uint32_t simplex_model_hash(simplex_solver_t *solver, thvar_t x) {
47,438✔
11098
  xrational_t *vx;
11099
  uint32_t a, b, c, d;
11100

11101
  vx = arith_var_value(&solver->vtbl, x);
47,438✔
11102
  q_hash_decompose(&vx->main, &a, &b);
47,438✔
11103
  q_hash_decompose(&vx->delta, &c, &d);
47,438✔
11104
  return jenkins_hash_quad(a, b, c, d, 0xab2eaf25);
47,438✔
11105
}
11106

11107

11108
/*
11109
 * Check whether x is a root variable:
11110
 * - x is root if it has an egraph term t and x is the theory
11111
 *   variable in the class of t.
11112
 */
11113
static bool is_root_var(simplex_solver_t *solver, thvar_t x) {
2,005,788✔
11114
  egraph_t *egraph;
11115
  eterm_t t;
11116

11117
  t = arith_var_get_eterm(&solver->vtbl, x);
2,005,788✔
11118
  egraph = solver->egraph;
2,005,788✔
11119
  return (t != null_eterm) &&
2,882,793✔
11120
    (egraph_class_thvar(egraph, egraph_term_class(egraph, t)) == x);
877,005✔
11121
}
11122

11123

11124

11125
/*
11126
 * MODEL ADJUSTMENT
11127
 */
11128

11129
/*
11130
 * Check whether x is a non-constant, trivial variable
11131
 * - i.e. x's definition is either x := b y or x := a + b y
11132
 */
11133
static bool simple_dependent_var(arith_vartable_t *tbl, thvar_t x) {
47,396✔
11134
  polynomial_t *q;
11135
  uint32_t n;
11136

11137
  assert(arith_var_kind(tbl, x) == AVAR_FREE ||
11138
         arith_var_kind(tbl, x) == AVAR_POLY);
11139

11140
  q = arith_var_def(tbl, x);
47,396✔
11141
  if (q != NULL) {
47,396✔
11142
    n = q->nterms;
3,376✔
11143
    return (n == 1 && q->mono[0].var != const_idx) // q is b.y
1,722✔
11144
      || (n == 2 && q->mono[0].var == const_idx);  // q is a + b.y
5,098✔
11145
  }
11146
  return false;
44,020✔
11147
}
11148

11149

11150
/*
11151
 * Get the monomial b.y in x's definition
11152
 * - x must be a simple dependent variable
11153
 */
11154
static monomial_t *simple_depvar_mono(arith_vartable_t *tbl, thvar_t x) {
6,612✔
11155
  polynomial_t *q;
11156

11157
  assert(simple_dependent_var(tbl, x));
11158

11159
  q = arith_var_poly_def(tbl, x);
6,612✔
11160
  return q->mono + (q->nterms - 1); // b.y is the last monomial of q
6,612✔
11161
}
11162

11163

11164
/*
11165
 * Get the variable y in the definition of x
11166
 * - x must be a simple dependent variable
11167
 */
11168
static thvar_t simple_depvar_source(arith_vartable_t *tbl, thvar_t x) {
853✔
11169
  return simple_depvar_mono(tbl, x)->var;
853✔
11170
}
11171

11172

11173
/*
11174
 * Get the coefficient b in x's definition
11175
 * - x must be a simple dependent variable
11176
 */
11177
static rational_t *simple_depvar_coeff(arith_vartable_t *tbl, thvar_t x) {
5,759✔
11178
  return &simple_depvar_mono(tbl, x)->coeff;
5,759✔
11179
}
11180

11181

11182
/*
11183
 * Given a trivial variable x := a + b y.
11184
 * record the dependency y --> x into dtbl
11185
 */
11186
static void record_simple_var_dep(arith_vartable_t *tbl, dep_table_t *dep, thvar_t x) {
853✔
11187
  thvar_t y;
11188

11189
  y = simple_depvar_source(tbl, x);
853✔
11190
  add_dependent(dep, y, x); // add x as a dependent of y
853✔
11191
}
853✔
11192

11193

11194
/*
11195
 * Update the value of x: add delta to it
11196
 * - x must be a root variable
11197
 * - record the effect in hmap
11198
 */
11199
static void model_adjust_var(xq_hmap_t *hmap, arith_vartable_t *tbl, thvar_t x, rational_t *delta) {
377,068✔
11200
  xq_hmap_shift_entry(hmap, arith_var_value(tbl, x), delta);
377,068✔
11201
}
377,068✔
11202

11203

11204
/*
11205
 * Update the value of x's dependents when x's value is shifted by delta
11206
 * - record the effect in hmap
11207
 */
11208
static void model_adjust_var_dependents(xq_hmap_t *hmap, arith_vartable_t *tbl, dep_table_t *deps,
450,845✔
11209
                                        thvar_t x, rational_t *delta) {
11210
  int32_t *v;
11211
  uint32_t i, n;
11212
  thvar_t y;
11213

11214
  v = get_dependents(deps, x);
450,845✔
11215
  if (v != NULL) {
450,845✔
11216
    n = iv_size(v);
3,233✔
11217
    for (i=0; i<n; i++) {
8,199✔
11218
      y = v[i]; // y depends on x
4,966✔
11219
      assert(simple_depvar_source(tbl, y) == x);
11220
      xq_hmap_addmul_entry(hmap, arith_var_value(tbl, y), simple_depvar_coeff(tbl, y), delta);
4,966✔
11221
    }
11222
  }
11223
}
450,845✔
11224

11225

11226
/*
11227
 * Update the value of all basic variables that depend on x when x's value is
11228
 * shifted by delta. This is done only for basic variables that are roots (e.g,.
11229
 * they have an attached egraph term and that term is root of its equivalence
11230
 * class in the egraph).
11231
 * - x must be a non-basic variable
11232
 * - record the effect in hmap
11233
 */
11234
static void model_adjust_var_base_dependents(simplex_solver_t *solver, xq_hmap_t *hmap, dep_table_t *deps,
168,493✔
11235
                                             thvar_t x, rational_t *delta) {
11236
  matrix_t *matrix;
11237
  arith_vartable_t *vtbl;
11238
  column_t *col;
11239
  rational_t a;
11240
  uint32_t i, n;
11241
  int32_t r, j;
11242
  thvar_t y;
11243

11244
  vtbl = &solver->vtbl;
168,493✔
11245
  matrix = &solver->matrix;
168,493✔
11246

11247
  assert(matrix_is_nonbasic_var(matrix, x));
11248

11249
  col = matrix_column(matrix, x);
168,493✔
11250

11251
  if (col != NULL) {
168,493✔
11252
    q_init(&a);
96,977✔
11253

11254
    n = col->size;
96,977✔
11255
    for (i=0; i<n; i++) {
3,024,879✔
11256
      r = col->data[i].r_idx;
2,927,902✔
11257
      if (r >= 0) {
2,927,902✔
11258
        // x occurs in row r
11259
        y = matrix_basic_var(matrix, r); // y = basic variable for row r
1,186,241✔
11260
        assert(y != null_thvar);
11261
        if (is_root_var(solver, y)) {
1,186,241✔
11262
          /*
11263
           * Adjust y:
11264
           * - let c be the coefficient of x in row r
11265
           * - the row is (y + .... + c.x + ... = 0)
11266
           * - so new_val[y] must be val[y] - c * delta
11267
           */
11268
          j = col->data[i].r_ptr;
282,352✔
11269
          q_set_neg(&a, matrix_coeff(matrix, r, j)); // - c
282,352✔
11270
          q_mul(&a, delta);  // -c * delta
282,352✔
11271

11272
          model_adjust_var(hmap, vtbl, y, &a); // Update y
282,352✔
11273
          model_adjust_var_dependents(hmap, vtbl, deps, y, &a); // Update y's dependents
282,352✔
11274
        }
11275
      }
11276
    }
11277

11278
    q_clear(&a);
96,977✔
11279
  }
11280
}
168,493✔
11281

11282

11283
/*
11284
 * Full adjustment for variable x:
11285
 * - adjust x itself if it's a root variable
11286
 * - adjust x's dependents
11287
 * - adjust all the basic variables that depend on x
11288
 *
11289
 * x must not be a basic variable
11290
 */
11291
static void simplex_full_adjust_var(simplex_solver_t *solver, xq_hmap_t *hmap, dep_table_t *deps,
168,493✔
11292
                                    thvar_t x, rational_t *delta) {
11293
  if (is_root_var(solver, x)) {
168,493✔
11294
    model_adjust_var(hmap, &solver->vtbl, x, delta);
94,716✔
11295
  }
11296
  model_adjust_var_dependents(hmap, &solver->vtbl, deps, x, delta);
168,493✔
11297
  model_adjust_var_base_dependents(solver, hmap, deps, x, delta);
168,493✔
11298
}
168,493✔
11299

11300

11301
/*
11302
 * Check whether adjusting x can make a difference:
11303
 * - i.e., x or one of its dependent variables is a root variable
11304
 */
11305
static bool simplex_useful_adjust_var(simplex_solver_t *solver, dep_table_t *deps, thvar_t x) {
42,636✔
11306
  matrix_t *matrix;
11307
  column_t *col;
11308
  uint32_t i, n;
11309
  int32_t r;
11310

11311
  if (is_root_var(solver, x) || get_dependents(deps, x) != NULL) {
42,636✔
11312
    return true;
20,021✔
11313
  }
11314

11315
  matrix = &solver->matrix;
22,615✔
11316
  col = matrix_column(matrix, x);
22,615✔
11317
  if (col != NULL) {
22,615✔
11318
    n = col->size;
22,598✔
11319
    for (i=0; i<n; i++) {
261,743✔
11320
      r  = col->data[i].r_idx;
254,957✔
11321
      if (r >= 0 && is_root_var(solver, matrix_basic_var(matrix, r))) {
254,957✔
11322
        // the basic variable in row r is root
11323
        return true;
15,812✔
11324
      }
11325
    }
11326
  }
11327

11328
  return false;
6,803✔
11329
}
11330

11331

11332
/*
11333
 * Compute the safe delta interval for x
11334
 * - x must be a non-basic variable
11335
 * - store the result in s
11336
 */
11337
static void simplex_safe_adjust_interval(simplex_solver_t *solver, interval_t *s, thvar_t x) {
35,833✔
11338
  xrational_t aux;
11339
  rational_t inv_a;
11340
  matrix_t *matrix;
11341
  arith_vartable_t *vtbl;
11342
  column_t *col;
11343
  uint32_t i, n;
11344
  int32_t r, j;
11345
  thvar_t y;
11346

11347
  vtbl = &solver->vtbl;
35,833✔
11348
  matrix = &solver->matrix;
35,833✔
11349

11350
  assert(matrix_is_nonbasic_var(matrix, x));
11351

11352
  xq_init(&aux);
35,833✔
11353

11354

11355
  /*
11356
   * Initialize s using the bounds on x
11357
   */
11358
  reset_interval(s);
35,833✔
11359
  j = arith_var_lower_index(vtbl, x);
35,833✔
11360
  if (j >= 0) {
35,833✔
11361
    /*
11362
     * x has a lower bound L:
11363
     * to ensure x + delta >= L, we want delta >= L - val[x]
11364
     */
11365
    xq_set(&aux, &solver->bstack.bound[j]);
1,540✔
11366
    xq_sub(&aux, arith_var_value(vtbl, x));
1,540✔
11367
    interval_update_lb(s, &aux);
1,540✔
11368
  }
11369

11370
  j = arith_var_upper_index(vtbl, x);
35,833✔
11371
  if (j >= 0) {
35,833✔
11372
    /*
11373
     * we want delta <= U - val[x]
11374
     */
11375
    xq_set(&aux, &solver->bstack.bound[j]);
5,288✔
11376
    xq_sub(&aux, arith_var_value(vtbl, x));
5,288✔
11377
    interval_update_ub(s, &aux);
5,288✔
11378
  }
11379

11380
  if (arith_var_is_int(vtbl, x)) {
35,833✔
11381
    // delta must be an integer
11382
    q_set_one(&s->period);
33,933✔
11383
  }
11384

11385

11386
  /*
11387
   * Check the bounds on all variables that depend on x
11388
   */
11389
  col = matrix_column(matrix, x);
35,833✔
11390
  if (col != NULL) {
35,833✔
11391
    q_init(&inv_a);
21,918✔
11392

11393
    n = col->size;
21,918✔
11394
    for (i=0; i<n; i++) {
709,156✔
11395
      r = col->data[i].r_idx;
687,238✔
11396
      if (r >= 0) {
687,238✔
11397
        /*
11398
         * x occurs in row r with coefficient a (a != 0)
11399
         * store 1/a in inv_a
11400
         */
11401
        j = col->data[i].r_ptr;
309,974✔
11402
        q_set(&inv_a, matrix_coeff(matrix, r, j)); // coefficient of x in row r
309,974✔
11403
        assert(q_is_nonzero(&inv_a));
11404
        q_inv(&inv_a);
309,974✔
11405

11406
        y = matrix_basic_var(matrix, r); // basic variable in row r
309,974✔
11407
        assert(y != x);
11408

11409
        /*
11410
         * Update the interval using the bounds on y + the type of y:
11411
         * when val[x] is moved to val[x] + delta
11412
         *      val[y] shifts to val[y] - a * delta
11413
         */
11414
        j = arith_var_lower_index(vtbl, y);
309,974✔
11415
        if (j >= 0) {
309,974✔
11416
          /*
11417
           * y has a lower bound L:
11418
           * if a > 0, we want delta <= (val[y] - L)/a
11419
           * if a < 0, we want delta >= (val[y] - L)/a
11420
           */
11421
          xq_set(&aux, arith_var_value(vtbl, y));
20,065✔
11422
          xq_sub(&aux, &solver->bstack.bound[j]);
20,065✔
11423
          xq_mul(&aux, &inv_a);   // aux := (val[y] - L)/a
20,065✔
11424
          if (q_is_pos(&inv_a)) {
20,065✔
11425
            interval_update_ub(s, &aux);
14,557✔
11426
          } else {
11427
            interval_update_lb(s, &aux);
5,508✔
11428
          }
11429
        }
11430

11431
        j = arith_var_upper_index(vtbl, y);
309,974✔
11432
        if (j >= 0) {
309,974✔
11433
          /*
11434
           * y has an upper bound U:
11435
           * if a > 0, we want delta >= (val[y] - U)/a
11436
           * if a < 0, we want delta <= (val[y] - U)/a
11437
           */
11438
          xq_set(&aux, arith_var_value(vtbl, y));
34,456✔
11439
          xq_sub(&aux, &solver->bstack.bound[j]);
34,456✔
11440
          xq_mul(&aux, &inv_a);   // aux := (val[y] - U)/a
34,456✔
11441
          if (q_is_pos(&inv_a)) {
34,456✔
11442
            interval_update_lb(s, &aux);
9,582✔
11443
          } else {
11444
            interval_update_ub(s, &aux);
24,874✔
11445
          }
11446
        }
11447

11448
        if (arith_var_is_int(vtbl, y)) {
309,974✔
11449
          /*
11450
           * We want a * delta to be an integer so
11451
           * delta must be a multiple of 1/a
11452
           */
11453
          interval_update_period(s, &inv_a);
303,329✔
11454
        }
11455
      }
11456
    }
11457

11458
    q_clear(&inv_a);
21,918✔
11459
  }
11460

11461
  xq_clear(&aux);
35,833✔
11462
}
35,833✔
11463

11464

11465

11466
/*
11467
 * Update the value of all trivial variables in deps[x]
11468
 * - delta = shift on x
11469
 */
11470
static void simplex_shift_var_dependents(arith_vartable_t *tbl, dep_table_t *deps, thvar_t x, rational_t *delta) {
80,051✔
11471
  int32_t *v;
11472
  uint32_t i, n;
11473
  thvar_t y;
11474

11475
  v = get_dependents(deps, x);
80,051✔
11476
  if (v != NULL) {
80,051✔
11477
    n = iv_size(v);
617✔
11478
    for (i=0; i<n; i++) {
1,410✔
11479
      y = v[i];
793✔
11480
      assert(simple_depvar_source(tbl, y) == x);
11481
      xq_addmul_q(arith_var_value(tbl, y), simple_depvar_coeff(tbl, y), delta);
793✔
11482
    }
11483
  }
11484
}
80,051✔
11485

11486

11487
/*
11488
 * Shift the value of x by delta and propagate to all dependent variables
11489
 * - this modifies the variable assignments in vartable
11490
 *
11491
 * NOTE: this does not update the values of trivial variables that
11492
 * depend on x but are not in x's dependent vectors.
11493
 */
11494
static void simplex_shift_var_value(simplex_solver_t *solver, dep_table_t *deps, thvar_t x, rational_t *delta) {
5,597✔
11495
  arith_vartable_t *vtbl;
11496
  matrix_t *matrix;
11497
  column_t *col;
11498
  rational_t a;
11499
  uint32_t i, n;
11500
  int32_t r, j;
11501
  thvar_t y;
11502

11503
  vtbl = &solver->vtbl;
5,597✔
11504

11505
  xq_add_q(arith_var_value(vtbl, x), delta); // value[x] := value[x] + delta
5,597✔
11506
  simplex_set_bound_flags(solver, x);
5,597✔
11507

11508
  assert(value_satisfies_bounds(solver, x));
11509

11510
  simplex_shift_var_dependents(vtbl, deps, x, delta); // simple dependents
5,597✔
11511

11512
  matrix = &solver->matrix;
5,597✔
11513
  col = matrix_column(matrix, x);
5,597✔
11514
  if (col != NULL) {
5,597✔
11515
    q_init(&a);
3,440✔
11516

11517
    n = col->size;
3,440✔
11518
    for (i=0; i<n; i++) {
148,167✔
11519
      r = col->data[i].r_idx;
144,727✔
11520
      if (r >= 0) {
144,727✔
11521
        y = matrix_basic_var(matrix, r);   // y = basic var in row r
74,454✔
11522
        assert(y != null_thvar);
11523

11524
        // delta on y = - delta * coeff of x in row r
11525
        j = col->data[i].r_ptr;
74,454✔
11526
        q_set_neg(&a, matrix_coeff(matrix, r, j));
74,454✔
11527
        q_mul(&a, delta);
74,454✔
11528

11529
        // value[y] := value[y] + delta on y
11530
        xq_add_q(arith_var_value(vtbl, y), &a);
74,454✔
11531
        assert(value_satisfies_bounds(solver, y));
11532

11533
#if DEBUG
11534
        check_equation_satisfied(solver, r);
11535
#endif
11536
        simplex_shift_var_dependents(vtbl, deps, y, &a); // shift y's dependents
74,454✔
11537
      }
11538
    }
11539
  }
11540
}
5,597✔
11541

11542

11543

11544
/*
11545
 * Parameter used by the candidate selection heuristics below:
11546
 * - max number of candidates to try
11547
 */
11548
#define MAX_SHIFT_CANDIDATES 5
11549

11550

11551
/*
11552
 * Select a possible delta in the specified interval
11553
 * - i = selection index (i.e., the function must return a sequence
11554
 *   of distinct delta_i with indices i=0, 1, 2, ...)
11555
 * - prng = state of a pseudo random number generator (cf. dprng.h)
11556
 * - return value = true if delta_i exists (then its value is stored in delta)
11557
 * - return false otherwise.
11558
 */
11559
static bool simplex_get_shift_candidate(rational_t *delta, double *prng, interval_t *interval, uint32_t i) {
163,214✔
11560
  int64_t w;
11561
  int32_t k;
11562

11563
  w = (int64_t) interval->k_max - (int64_t) interval->k_min;
163,214✔
11564
  if (w <= MAX_SHIFT_CANDIDATES + 1) {
163,214✔
11565
    k = i;
841✔
11566
    k += interval->k_min;
841✔
11567
    if (k > interval->k_max) return false;
841✔
11568
  } else if (w < 1000 * MAX_SHIFT_CANDIDATES) {
162,373✔
11569
    k = irand(prng, w);
3,026✔
11570
    k += interval->k_min;
3,026✔
11571
  } else {
11572
    k = irand(prng, 1000 * MAX_SHIFT_CANDIDATES);
159,347✔
11573
    if (interval->k_min > -500 * MAX_SHIFT_CANDIDATES) {
159,347✔
11574
      k += interval->k_min;
6,412✔
11575
    } else if (interval->k_max < 500 * MAX_SHIFT_CANDIDATES) {
152,935✔
11576
      k = interval->k_max - k;
16,752✔
11577
    } else {
11578
      k -= 500 * MAX_SHIFT_CANDIDATES;
136,183✔
11579
    }
11580
  }
11581

11582
  assert(interval->k_min <= k && k <= interval->k_max);
11583
  q_set32(delta, k);
163,109✔
11584
  q_mul(delta, &interval->period);
163,109✔
11585

11586
  return !interval->has_ub || xq_ge_q(&interval->ub, delta);
163,109✔
11587
}
11588

11589

11590

11591
/*
11592
 * Compute the best adjustment for variable x:
11593
 * - deps = dependency table
11594
 * - hmap = partition for the current variable assignment
11595
 * - aux = auxiliary hmap for computations
11596
 * - interval = adjustment interval for x
11597
 */
11598
static void simplex_adjust_var(simplex_solver_t *solver, dep_table_t *deps, xq_hmap_t *hmap, xq_hmap_t *aux,
32,797✔
11599
                               interval_t *interval, thvar_t x) {
11600
  rational_t delta;
11601
  rational_t best_delta;
11602
  uint32_t best_num_classes;
11603
  uint32_t i, n;
11604

11605
  q_init(&best_delta);
32,797✔
11606
  q_init(&delta);
32,797✔
11607
  best_num_classes = xq_hmap_num_classes(hmap);
32,797✔
11608

11609
  interval_prepare_for_sampling(interval, MAX_SHIFT_CANDIDATES);
32,797✔
11610

11611
  /*
11612
   * Search for delta := shift of x's value that maximizes
11613
   * the number of classes in xq_hmap
11614
   */
11615
  for (i=0; i<MAX_SHIFT_CANDIDATES; i++) { // try at most 5 candidates
195,750✔
11616
    if (! simplex_get_shift_candidate(&delta, &solver->dprng, interval, i)) break;
163,214✔
11617

11618
    assert(sample_in_interval(interval, &delta));
11619

11620
    if (! q_is_zero(&delta)) {
163,109✔
11621
      // aux := the new partition for this delta
11622
      copy_xq_hmap(aux, hmap);
162,896✔
11623
      simplex_full_adjust_var(solver, aux, deps, x, &delta);
162,896✔
11624
      n = xq_hmap_num_classes(aux);
162,896✔
11625

11626
#if TRACE
11627
      printf("    delta = ");
11628
      q_print(stdout, &delta);
11629
      printf(": %"PRIu32" classes\n", n);
11630
#endif
11631

11632
      assert(xq_hmap_num_entries(aux) == xq_hmap_num_entries(hmap));
11633

11634
      if (n > best_num_classes) {
162,896✔
11635
        q_set(&best_delta, &delta);
5,625✔
11636
        best_num_classes = n;
5,625✔
11637
        if (n == xq_hmap_num_entries(aux)) {
5,625✔
11638
          // n is optimal
11639
          break;
156✔
11640
        }
11641
      }
11642
    }
11643
  }
11644

11645
  /*
11646
   * Apply the best shift to the current model and
11647
   * to hmap.
11648
   */
11649
  if (! q_is_zero(&best_delta)) {
32,797✔
11650
#if TRACE
11651
    printf("    adjustment: delta = ");
11652
    q_print(stdout, &best_delta);
11653
    printf(": %"PRIu32" classes\n", best_num_classes);
11654
#endif
11655
    // We must adjust hmap first
11656
    simplex_full_adjust_var(solver, hmap, deps, x, &best_delta);
5,597✔
11657
    assert(xq_hmap_num_classes(hmap) == best_num_classes);
11658

11659
    // shift x and update its dependents
11660
    simplex_shift_var_value(solver, deps, x, &best_delta);
5,597✔
11661
  }
11662

11663
  q_clear(&delta);
32,797✔
11664
  q_clear(&best_delta);
32,797✔
11665
}
32,797✔
11666

11667

11668

11669
/*
11670
 * Attempt to modify the current assignment
11671
 * - deps = dependency table
11672
 * - hmap = current partition table
11673
 */
11674
static void simplex_adjust_assignment(simplex_solver_t *solver, dep_table_t *deps, xq_hmap_t *hmap) {
548✔
11675
  interval_t interval;
11676
  xq_hmap_t aux;
11677
  uint32_t i, n;
11678

11679
#if DEBUG
11680
  check_assignment(solver);
11681
  check_integer_bounds(solver);
11682
  check_vartags(solver);
11683
  check_bound_marks(solver);
11684
#endif
11685

11686
  init_xq_hmap(&aux, 0);
548✔
11687
  init_interval(&interval);
548✔
11688

11689
  n = solver->vtbl.nvars;
548✔
11690
  for (i=1; i<n; i++) {
235,718✔
11691
    /*
11692
     * Skip all the dependent variables (i.e.. basic variable
11693
     * and trivial variables) and all variables that have
11694
     * equal lower and upper bounds.
11695
     */
11696
    if (matrix_is_nonbasic_var(&solver->matrix, i) &&
235,326✔
11697
        !trivial_variable(&solver->vtbl, i) &&
88,441✔
11698
        !simplex_fixed_variable(solver, i) &&
125,529✔
11699
        simplex_useful_adjust_var(solver, deps, i)) {
42,636✔
11700

11701
      // compute the safe interval for i
11702
      simplex_safe_adjust_interval(solver, &interval, i);
35,833✔
11703
      if (! singleton_interval(&interval)) {
35,833✔
11704
        /*
11705
         * Modify the value of x to maximize the number of classes in hmap
11706
         */
11707
#if TRACE
11708
        printf("interval for ");
11709
        print_simplex_var(stdout, solver, i);
11710
        if (interval.has_lb) {
11711
          printf(": lower bound = ");
11712
          xq_print(stdout, &interval.lb);
11713
        } else {
11714
          printf(": no lower bound");
11715
        }
11716

11717
        if (interval.has_ub) {
11718
          printf(", upper bound = ");
11719
          xq_print(stdout, &interval.ub);
11720
        } else {
11721
          printf(", no upper bound");
11722
        }
11723

11724
        printf(", period = ");
11725
        q_print(stdout, &interval.period);
11726
        printf("\n");
11727
#endif
11728

11729
        simplex_adjust_var(solver, deps, hmap, &aux, &interval, i);
32,797✔
11730

11731
#if DEBUG
11732
        check_assignment(solver);
11733
        check_integer_bounds(solver);
11734
        check_vartags(solver);
11735
        check_bound_marks(solver);
11736
#endif
11737

11738
        if (xq_hmap_num_classes(hmap) == xq_hmap_num_entries(hmap)) {
32,797✔
11739
          // no improvement possible
11740
          break;
156✔
11741
        }
11742
      }
11743
    }
11744
  }
11745

11746
  delete_interval(&interval);
548✔
11747
  delete_xq_hmap(&aux);
548✔
11748
}
548✔
11749

11750

11751
/*
11752
 * Attempt to modify the current model to minimize the number of
11753
 * conflicts with the egraph classes.
11754
 */
11755
static void simplex_adjust_model(simplex_solver_t *solver) {
13,310✔
11756
  xq_hmap_t hmap;
11757
  dep_table_t deps;
11758
  arith_vartable_t *vtbl;
11759
  uint32_t i, n;
11760

11761
  init_xq_hmap(&hmap, 0);
13,310✔
11762
  init_dep_table(&deps, 0);
13,310✔
11763

11764
  vtbl = &solver->vtbl;
13,310✔
11765
  n = vtbl->nvars;
13,310✔
11766
  for (i=0; i<n; i++) {
284,235✔
11767
    if (is_root_var(solver, i)) {
270,925✔
11768
      xq_hmap_add_entry(&hmap, arith_var_value(vtbl, i));
47,396✔
11769
      if (simple_dependent_var(vtbl, i)) {
47,396✔
11770
        record_simple_var_dep(vtbl, &deps, i);
853✔
11771
      }
11772
    }
11773
  }
11774

11775
  if (xq_hmap_num_classes(&hmap) < xq_hmap_num_entries(&hmap)) {
13,310✔
11776
#if TRACE
11777
    printf("---> before adjustment: %"PRIu32" entries, %"PRIu32" classes\n",
11778
           xq_hmap_num_entries(&hmap), xq_hmap_num_classes(&hmap));
11779
#endif
11780
    simplex_adjust_assignment(solver, &deps, &hmap);
548✔
11781
#if TRACE
11782
    printf("---> after adjustment: %"PRIu32" entries, %"PRIu32" classes\n",
11783
           xq_hmap_num_entries(&hmap), xq_hmap_num_classes(&hmap));
11784
#endif
11785
  }
11786

11787

11788
  delete_dep_table(&deps);
13,310✔
11789
  delete_xq_hmap(&hmap);
13,310✔
11790
}
13,310✔
11791

11792

11793

11794
/*
11795
 * RECONCILE MODEL
11796
 */
11797

11798
/*
11799
 * Replacement for build_model, var_equal_in_model, and release_model
11800
 * - attempt to build a model that's consistent with the egraph
11801
 * - construct at most max_eq interface equalities if that's not possible
11802
 * - return the number of interface equalities generated
11803
 */
11804
uint32_t simplex_reconcile_model(simplex_solver_t *solver, uint32_t max_eq) {
18✔
11805
  int_hclass_t hclass;
11806
  int32_t i, x, n;
11807
  uint32_t neq;
11808

11809
  assert(max_eq > 0);
11810

11811
  simplex_prepare_model(solver);
18✔
11812

11813
  if (simplex_option_enabled(solver, SIMPLEX_ADJUST_MODEL)) {
18✔
11814
    simplex_adjust_model(solver);
18✔
11815
  }
11816

11817

11818
#if TRACE
11819
  printf("SIMPLEX: reconcile model\n");
11820
  print_simplex_vars(stdout, solver);
11821
  printf("\n");
11822
  print_simplex_assignment(stdout, solver);
11823
  printf("\n\n");
11824
  fflush(stdout);
11825
#endif
11826

11827
  init_int_hclass(&hclass, 0, solver, (iclass_hash_fun_t) simplex_model_hash,
18✔
11828
                  (iclass_match_fun_t) simplex_var_equal_in_model);
11829

11830
  neq = 0;
18✔
11831
  n = solver->vtbl.nvars;
18✔
11832
  for (i=0; i<n; i++) {
2,429✔
11833
    if (is_root_var(solver, i)) {
2,411✔
11834
      x = int_hclass_get_rep(&hclass, i);
287✔
11835
      if (x != i) {
287✔
11836
        // x and i have the same value in the model
11837
        // but are in different classes in the egraph
11838
        neq += simplex_trichotomy_lemma(solver, x, i);
26✔
11839
        if (neq == max_eq) break;
26✔
11840
      }
11841
    }
11842
  }
11843

11844
  delete_int_hclass(&hclass);
18✔
11845

11846
#if TRACE
11847
  printf("---> reconcile model: %"PRIu32" trichotomy lemmas\n\n", neq);
11848
#endif
11849

11850
  return neq;
18✔
11851
}
11852

11853

11854

11855
/*
11856
 * EXPERIMENTAL: MODEL RECONCILIATION INTERFACE
11857
 */
11858

11859
static void simplex_prep_model(simplex_solver_t *solver) {
13,293✔
11860
  simplex_prepare_model(solver);
13,293✔
11861
  if (simplex_option_enabled(solver, SIMPLEX_ADJUST_MODEL)) {
13,293✔
11862
    simplex_adjust_model(solver);
13,292✔
11863
  }
11864
#if TRACE
11865
  printf("SIMPLEX: prepare model\n");
11866
  print_simplex_vars(stdout, solver);
11867
  printf("\n");
11868
  print_simplex_assignment(stdout, solver);
11869
  printf("\n\n");
11870
  fflush(stdout);
11871
#endif
11872
}
13,293✔
11873

11874
static void simplex_release_model(simplex_solver_t *solver) {
13,293✔
11875
  // nothing to do
11876
}
13,293✔
11877

11878
// var equal in model is already defined
11879

11880
/*
11881
 * Add the lemma l => x1 != x2
11882
 * - if equiv is true, also generate the reverse implication
11883
 */
11884
static void simplex_gen_interface_lemma(simplex_solver_t *solver, literal_t l, thvar_t x1, thvar_t x2, bool equiv) {
403✔
11885
  rational_t *c;
11886
  thvar_t y;
11887
  literal_t l0, l1, l2;
11888

11889
  assert(x1 != x2);
11890

11891
  /*
11892
   * build p such that p=0 is equivalent to (x1 = x2)
11893
   * p is stored in solver->buffer
11894
   * l0 = simplification code
11895
   */
11896
  l0 = simplify_dynamic_vareq(solver, x1, x2);
403✔
11897
  if (l0 == false_literal) {
403✔
11898
    /*
11899
     * x1 = x2 is false: add (not l) as an axiom for the egraph
11900
     */
11901
    add_unit_clause(solver->core, not(l));
×
11902
    solver->stats.num_reduced_inter_lemmas ++;
×
11903

11904
#if 0
11905
    printf("---> SIMPLEX: interface lemma for ");
11906
    print_simplex_var(stdout, solver, x1);
11907
    printf(" ");
11908
    print_simplex_var(stdout, solver, x2);
11909
    printf(" (axiom)\n");
11910
#endif
11911

11912
#if TRACE
11913
    printf("---> Simplex: reconciliation lemma for ");
11914
    print_simplex_var(stdout, solver, x1);
11915
    printf(" /= ");
11916
    print_simplex_var(stdout, solver, x2);
11917
    printf(" ----\n");
11918
    if (!arith_var_is_free(&solver->vtbl, x1)) {
11919
      printf("     ");
11920
      print_simplex_vardef(stdout, solver, x1);
11921
    }
11922
    if (!arith_var_is_free(&solver->vtbl, x2)) {
11923
      printf("     ");
11924
      print_simplex_vardef(stdout, solver, x2);
11925
    }
11926
    printf("     Antecedent:\n");
11927
    printf("      ");
11928
    print_literal(stdout, l);
11929
    printf(" := ");
11930
    print_egraph_atom_of_literal(stdout, solver->egraph, l);
11931
    printf("\n");
11932
    printf("     equality is false\n");
11933
    printf("     add unit clause: ");
11934
    print_egraph_atom_of_literal(stdout, solver->egraph, not(l));
11935
    printf("\n");
11936
#endif
11937

11938
  } else {
11939
    assert(l0 != true_literal); // because x1 != x2
11940

11941
    /*
11942
     * get y and c such that (y = c) is equivalent to (x1 = x2)
11943
     */
11944
    y = decompose_and_get_dynamic_var(solver);
403✔
11945
    c = &solver->constant;
403✔
11946

11947
    l1 = create_pos_atom(solver, y, c); // l1 is (y > c)
403✔
11948
    l2 = create_neg_atom(solver, y, c); // l2 is (y < c)
403✔
11949

11950
    add_ternary_clause(solver->core, not(l), l1, l2); // clause: (not l) or (y > c) or (y < c))
403✔
11951
    if (equiv) {
403✔
11952
      add_binary_clause(solver->core, l, not(l1)); // y > c => t1 /= t2
403✔
11953
      add_binary_clause(solver->core, l, not(l2)); // y < c => t1 /= t2
403✔
11954
    }
11955

11956
    solver->stats.num_interface_lemmas ++;
403✔
11957

11958
#if 0
11959
    printf("---> SIMPLEX: interface lemma for ");
11960
    print_simplex_var(stdout, solver, x1);
11961
    printf(" ");
11962
    print_simplex_var(stdout, solver, x2);
11963
    printf(" (trichotomy)\n");
11964
#endif
11965

11966

11967
#if TRACE
11968
    printf("---> Simplex: reconciliation lemma for ");
11969
    print_simplex_var(stdout, solver, x1);
11970
    printf(" /= ");
11971
    print_simplex_var(stdout, solver, x2);
11972
    printf(" ----\n");
11973
    if (!arith_var_is_free(&solver->vtbl, x1)) {
11974
      printf("     ");
11975
      print_simplex_vardef(stdout, solver, x1);
11976
    }
11977
    if (!arith_var_is_free(&solver->vtbl, x2)) {
11978
      printf("     ");
11979
      print_simplex_vardef(stdout, solver, x2);
11980
    }
11981
    printf("     Antecedent:\n");
11982
    printf("      ");
11983
    print_literal(stdout, l);
11984
    printf(" := ");
11985
    print_egraph_atom_of_literal(stdout, solver->egraph, l);
11986
    printf("\n");
11987
    printf("     Equality is reduced to\n");
11988
    printf("       ");
11989
    print_simplex_var(stdout, solver, y);
11990
    printf(" != ");
11991
    q_print(stdout, c);
11992
    printf("\n");
11993
    if (! arith_var_is_free(&solver->vtbl, y)) {
11994
      printf("     ");
11995
      print_simplex_vardef(stdout, solver, y);
11996
    }
11997
    printf("     simplex atom:\n      ");
11998
    print_literal(stdout, l1);
11999
    printf(" := ");
12000
    print_simplex_atom_of_literal(stdout, solver, l1);
12001
    printf("\n      ");
12002
    print_literal(stdout, l2);
12003
    printf(" := ");
12004
    print_simplex_atom_of_literal(stdout, solver, l2);
12005
    printf("\n");
12006
    printf("     add clause: (OR ");
12007
    print_egraph_atom_of_literal(stdout, solver->egraph, not(l));
12008
    printf(" ");
12009
    print_simplex_atom_of_literal(stdout, solver, l1);
12010
    printf(" ");
12011
    print_simplex_atom_of_literal(stdout, solver, l2);
12012
    printf(")\n\n");
12013
#endif
12014

12015
  }
12016

12017
}
403✔
12018

12019

12020
/*
12021
 * Build the variable partition for the current model
12022
 */
12023
static ipart_t *simplex_build_model_partition(simplex_solver_t *solver) {
13,293✔
12024
  ipart_t *partition;
12025
  uint32_t i, n;
12026

12027
  partition = (ipart_t *) safe_malloc(sizeof(ipart_t));
13,293✔
12028
  init_int_partition(partition, 0, solver, (ipart_hash_fun_t) simplex_model_hash,
13,293✔
12029
                     (ipart_match_fun_t) simplex_var_equal_in_model);
12030

12031
  n = solver->vtbl.nvars;
13,293✔
12032
  for (i=1; i<n; i++) {
268,518✔
12033
    if (is_root_var(solver, i)) {
255,225✔
12034
      int_partition_add(partition, i);
47,112✔
12035
    }
12036
  }
12037

12038
  return partition;
13,293✔
12039
}
12040

12041

12042
/*
12043
 * Free the partition
12044
 */
12045
static void simplex_release_model_partition(simplex_solver_t *solver, ipart_t *p) {
13,293✔
12046
  delete_int_partition(p);
13,293✔
12047
  safe_free(p);
13,293✔
12048
}
13,293✔
12049

12050

12051

12052

12053

12054
/************************
12055
 *  MODEL CONSTRUCTION  *
12056
 ***********************/
12057

12058
/*
12059
 * If the egraph is present, then reconcile model ensures that
12060
 * for all variables x_i and x_j, if x_i is attached to egraph term t1,
12061
 * and x_j is attached to egraph term t2, and t1 != t2, then
12062
 * value[x_i] != value[x_j] where the values are extended rationals.
12063
 *
12064
 * We want to preserve this property after value[x_i] and value[x_j]
12065
 * are concretized to rational numbers.
12066
 *
12067
 * If value[x_i] = a_i + b_i \delta  and value[x_j] = a_j + b_j \delta
12068
 * and x_i and x_j are attached to distinct eterms, then we want
12069
 *  (a_i + b_i epsilon) != (a_j + b_j epsilon).
12070
 *
12071
 * It is enough to ensure epsilon < (a_j - a_i)/(b_i - b_j) whenever
12072
 * (a_j > a_i) and (b_i > b_j) and x_i and x_j are attached to egraph terms.
12073
 */
12074

12075
/*
12076
 * Adjust epsilon to ensure concretization of (a1 + b1 \delta) != concretization of (a2 + b2 \delta)
12077
 * - q1 = a1 + b1 \delta
12078
 * - q2 = a2 + b2 \delta
12079
 */
12080
static void epsilon_for_diseq(simplex_solver_t *solver, xrational_t *q1, xrational_t *q2) {
168,045✔
12081
  rational_t *aux, *factor;
12082
  int main_cmp, delta_cmp;
12083

12084
  main_cmp = q_cmp(&q1->main, &q2->main);
168,045✔
12085
  delta_cmp = q_cmp(&q1->delta, &q2->delta);
168,045✔
12086

12087
  if ((main_cmp < 0 && delta_cmp > 0) || (main_cmp > 0 && delta_cmp < 0)) {
168,045✔
12088
    // (a1 < a2) and (b1 > b2)  or  (a1 > a2) and (b1 < b2)
12089
    factor = &solver->factor;
1,807✔
12090
    q_set(factor, &q1->delta);
1,807✔
12091
    q_sub(factor, &q2->delta); // factor = b1 - b2
1,807✔
12092
    aux = &solver->aux;
1,807✔
12093
    q_set(aux, &q2->main);
1,807✔
12094
    q_sub(aux, &q1->main);     // aux = a2 - a1
1,807✔
12095
    q_div(aux, factor);        // aux = (a2 - a1)/(b1 - b2)
1,807✔
12096
    assert(q_is_pos(aux));
12097
    if (q_le(aux, &solver->epsilon)) {
1,807✔
12098
      // force 0 < epsilon < (a2 - a1)/(b1 - b2)
12099
      q_set_int32(factor, 1, 2);
2✔
12100
      q_set(&solver->epsilon, aux);
2✔
12101
      q_mul(&solver->epsilon, factor);
2✔
12102
      assert(q_is_pos(&solver->epsilon) && q_lt(&solver->epsilon, aux));
12103
    }
12104
  }
12105
}
168,045✔
12106

12107

12108
/*
12109
 * Force epsilon < (a_j - a_i)/(b_i - b_j) for all pairs of variables
12110
 * x_i, x_j attached to egraph terms.
12111
 */
12112
static void epsilon_for_egraph(simplex_solver_t *solver) {
12,602✔
12113
  arith_vartable_t *vtbl;
12114
  xrational_t *q1, *q2;
12115
  uint32_t i, j, n;
12116

12117
  vtbl = &solver->vtbl;
12,602✔
12118
  n = vtbl->nvars;
12,602✔
12119
  for (i=1; i<n; i++) {
18,453✔
12120
    if (arith_var_has_eterm(vtbl, i)) {
5,851✔
12121
      q1 = arith_var_value(vtbl, i);
1,980✔
12122
      for (j=i+1; j<n; j++) {
864,921✔
12123
        if (arith_var_has_eterm(vtbl, j)) {
862,941✔
12124
          q2 = arith_var_value(vtbl, j);
168,045✔
12125
          epsilon_for_diseq(solver, q1, q2);
168,045✔
12126
        }
12127
      }
12128
    }
12129
  }
12130
}
12,602✔
12131

12132

12133
/*
12134
 * Adjust epsilon to ensure concretization of q1 <= concretization of q2
12135
 * - q1 is a + b \delta  --> concrete rational value = a + b * epsilon
12136
 * - q2 is c + d \delta  --> concrete rational value = c + d * epsilon
12137
 * - epsilon must be positive
12138
 *
12139
 * We assume a + b \delta <= c + d \delta in the extended rationals,
12140
 * that is we have either (a < c) or (a = c and b <= d).
12141
 *
12142
 * To ensure a + b * epsilon <= c + d * epsilon, we need
12143
 *     epsilon <= (c - a)/(b - d) when  b > d.
12144
 * If b <= d, any positive epsilon works (since a <= c).
12145
 */
12146
static void epsilon_for_le(simplex_solver_t *solver, xrational_t *q1, xrational_t *q2) {
8,572✔
12147
  rational_t *aux, *factor;
12148

12149
  assert(xq_le(q1, q2));
12150

12151
  if (q_gt(&q1->delta, &q2->delta)) {
8,572✔
12152
    factor = &solver->factor;
193✔
12153
    q_set(factor, &q1->delta);
193✔
12154
    q_sub(factor, &q2->delta);  // factor = b - d
193✔
12155
    aux = &solver->aux;
193✔
12156
    q_set(aux, &q2->main);
193✔
12157
    q_sub(aux, &q1->main);      // aux = c - a
193✔
12158
    q_div(aux, factor);         // aux = (c - a)/(b - d)
193✔
12159
    assert(q_is_pos(aux));
12160
    if (q_lt(aux, &solver->epsilon)) {
193✔
12161
      q_set(&solver->epsilon, aux);
12✔
12162
    }
12163
  }
12164
}
8,572✔
12165

12166

12167
/*
12168
 * Adjust solver->epsilon to ensure that the rational value of x
12169
 * is between the lower and upper bounds on x
12170
 */
12171
static void simplex_adjust_epsilon(simplex_solver_t *solver, thvar_t x) {
9,030✔
12172
  xrational_t *vx;
12173
  int32_t k;
12174

12175
  vx = arith_var_value(&solver->vtbl, x);
9,030✔
12176
  k = arith_var_lower_index(&solver->vtbl, x);
9,030✔
12177
  if (k >= 0) {
9,030✔
12178
    // ensure lower bound on x <= value of x
12179
    epsilon_for_le(solver, solver->bstack.bound + k, vx);
4,123✔
12180
  }
12181
  k = arith_var_upper_index(&solver->vtbl, x);
9,030✔
12182
  if (k >= 0) {
9,030✔
12183
    // ensure value of x <= upper bound on x
12184
    epsilon_for_le(solver, vx, solver->bstack.bound + k);
4,449✔
12185
  }
12186
}
9,030✔
12187

12188

12189

12190
/*
12191
 * Mark the eliminated variables (i.e., base variables in the elimination matrix)
12192
 */
12193
static void simplex_mark_eliminated_vars(simplex_solver_t *solver, byte_t *mark) {
12,890✔
12194
  elim_matrix_t *elim;
12195
  uint32_t i, n;
12196
  int32_t x;
12197

12198
  elim = &solver->elim;
12,890✔
12199
  n = elim->nrows;
12,890✔
12200
  for (i=0; i<n; i++) {
13,531✔
12201
    x = elim->base_var[i];
641✔
12202
    assert(! tst_bit(mark, x) && 0 <= x && x < solver->vtbl.nvars);
12203
    set_bit(mark, x);
641✔
12204
  }
12205
}
12,890✔
12206

12207

12208
/*
12209
 * Mark the trivial variables (whose definition in arith table is a simple polynomial).
12210
 */
12211
static void simplex_mark_trivial_vars(simplex_solver_t *solver, byte_t *mark) {
12,890✔
12212
  arith_vartable_t *vtbl;
12213
  uint32_t i, n;
12214

12215
  vtbl = &solver->vtbl;
12,890✔
12216
  n = vtbl->nvars;
12,890✔
12217
  for (i=1; i<n; i++) {
22,972✔
12218
    if (trivial_variable(vtbl, i)) {
10,082✔
12219
      assert(! tst_bit(mark, i));
12220
      set_bit(mark, i);
403✔
12221
    }
12222
  }
12223
}
12,890✔
12224

12225

12226
/*
12227
 * Mark and set the value of all variables in the fvar vector
12228
 * also set the value of the constant (const_idx = 0 has value 1)
12229
 */
12230
static void simplex_model_for_fvars(simplex_solver_t *solver, byte_t *mark) {
12,890✔
12231
  fvar_vector_t *v;
12232
  uint32_t i, n;
12233
  int32_t x;
12234

12235
  assert(solver->value != NULL);
12236

12237
  v = &solver->fvars;
12,890✔
12238
  n = v->nvars;
12,890✔
12239
  for (i=0; i<n; i++) {
12,898✔
12240
    x = v->fvar[i].var;
8✔
12241
    assert(! tst_bit(mark, x) && 0 <= x && x < solver->vtbl.nvars);
12242
    set_bit(mark, x);
8✔
12243
    q_set(solver->value + x, &v->fvar[i].value);
8✔
12244
  }
12245

12246
  // deal with the constant
12247
  if (! tst_bit(mark, 0)) {
12,890✔
12248
    set_bit(mark, 0);
12,890✔
12249
    q_set_one(solver->value); // i.e., value[0]
12,890✔
12250
  }
12251
  assert(q_is_one(solver->value));
12252
}
12,890✔
12253

12254

12255
/*
12256
 * Compute a rational value for all unmarked variables.
12257
 * - the value for x is a + b * epsilon where (a + b \delta) is
12258
 *   the current simplex assignment for x
12259
 */
12260
static void simplex_model_for_unmarked_vars(simplex_solver_t *solver, byte_t *mark) {
12,890✔
12261
  arith_vartable_t *vtbl;
12262
  rational_t *epsilon, *v;
12263
  xrational_t *vx;
12264
  uint32_t i, n;
12265

12266
  epsilon = &solver->epsilon;
12,890✔
12267
  assert(q_is_pos(epsilon) && solver->value != NULL);
12268

12269
  vtbl = &solver->vtbl;
12,890✔
12270
  n = vtbl->nvars;
12,890✔
12271
  for (i=1; i<n; i++) { // skip the constant
22,972✔
12272
    if (! tst_bit(mark, i)) {
10,082✔
12273
      vx = arith_var_value(vtbl, i); // vx = a + b\delta
9,030✔
12274
      v = solver->value + i;
9,030✔
12275
      q_set(v, &vx->main);
9,030✔
12276
      q_addmul(v, &vx->delta, epsilon); // v = a  + b * epsilon
9,030✔
12277
    }
12278
  }
12279
}
12,890✔
12280

12281

12282
/*
12283
 * Auxiliary function: compute value of polynomial p
12284
 * - value is an array of rational (value[x] = value of variable x)
12285
 * - the value is stored in v
12286
 */
12287
static void simplex_eval_rational_poly(rational_t *value, polynomial_t *p, rational_t *v) {
1,044✔
12288
  uint32_t i, n;
12289
  thvar_t x;
12290

12291
  assert(value != NULL && p != NULL && q_is_one(&value[0]));
12292

12293
  q_clear(v);
1,044✔
12294
  n = p->nterms;
1,044✔
12295
  for (i=0; i<n; i++) {
3,723✔
12296
    x = p->mono[i].var;
2,679✔
12297
    q_addmul(v, &p->mono[i].coeff, value + x); // v := coeff * value[x]
2,679✔
12298
  }
12299
}
1,044✔
12300

12301

12302
/*
12303
 * Assign a rational value to all eliminated variables
12304
 * - process the elimination matrix in reverse order
12305
 */
12306
static void simplex_model_for_eliminated_vars(simplex_solver_t *solver) {
12,890✔
12307
  elim_matrix_t *elim;
12308
  rational_t *aux;
12309
  uint32_t n;
12310
  int32_t x;
12311

12312
  aux = &solver->aux;
12,890✔
12313
  elim = &solver->elim;
12,890✔
12314
  n = elim->nrows;
12,890✔
12315
  while (n > 0) {
13,531✔
12316
    n --;
641✔
12317
    x = elim->base_var[n];
641✔
12318
    assert(0 <= x && x < solver->vtbl.nvars);
12319
    /*
12320
     * row[n] is a polynomial p that contains x.
12321
     * x has coefficient 1 in p and we want val[x] to ensure p == 0
12322
     */
12323
    assert(q_is_zero(solver->value + x)); // x should not have been touched
12324
    simplex_eval_rational_poly(solver->value, elim->row[n], aux);
641✔
12325
    q_set_neg(solver->value + x, aux);
641✔
12326

12327
#ifndef NDEBUG
12328
    simplex_eval_rational_poly(solver->value, elim->row[n], aux);
12329
    assert(q_is_zero(aux));
12330
#endif
12331
  }
12332
}
12,890✔
12333

12334

12335
/*
12336
 * Assign a rational value to all trivial variables.
12337
 */
12338
static void simplex_model_for_trivial_vars(simplex_solver_t *solver) {
12,890✔
12339
  arith_vartable_t *vtbl;
12340
  polynomial_t *p;
12341
  rational_t *aux;
12342
  uint32_t i, n;
12343

12344
  aux = &solver->aux;
12,890✔
12345
  vtbl = &solver->vtbl;
12,890✔
12346
  n = vtbl->nvars;
12,890✔
12347
  for (i=1; i<n; i++) {
22,972✔
12348
    p = arith_var_def(vtbl, i);
10,082✔
12349
    if (p != NULL && simple_poly(p)) {
10,082✔
12350
      assert(trivial_variable(vtbl, i));
12351
      simplex_eval_rational_poly(solver->value, p, aux);
403✔
12352
      q_set(solver->value + i, aux);
403✔
12353
    }
12354
  }
12355
}
12,890✔
12356

12357

12358

12359
#ifndef NDEBUG
12360

12361
/*
12362
 * DEBUGGING OF MODEL CONSTRUCTION
12363
 */
12364

12365
/*
12366
 * Evaluate a row: store result in *v
12367
 */
12368
static void simplex_eval_rational_row(rational_t *value, row_t *row, rational_t *v) {
12369
  uint32_t i, n;
12370
  thvar_t x;
12371

12372
  q_clear(v);
12373
  n = row->size;
12374
  for (i=0; i<n; i++) {
12375
    x = row->data[i].c_idx;
12376
    if (x >= 0) {
12377
      q_addmul(v, value + x, &row->data[i].coeff);
12378
    }
12379
  }
12380
}
12381

12382

12383
/*
12384
 * Evaluate an atom: return true or false
12385
 */
12386
static bool simplex_eval_atom_in_model(rational_t *value, arith_atom_t *atom) {
12387
  thvar_t x;
12388
  bool b;
12389

12390
  b = false;   // prevents GCC warning
12391
  x = var_of_atom(atom);
12392
  switch (tag_of_atom(atom)) {
12393
  case GE_ATM:
12394
    b = q_ge(value + x, bound_of_atom(atom));
12395
    break;
12396
  case LE_ATM:
12397
    b = q_le(value + x, bound_of_atom(atom));
12398
    break;
12399
  case EQ_ATM:
12400
    b = q_eq(value + x, bound_of_atom(atom));
12401
    break;
12402
  }
12403
  return b;
12404
}
12405

12406

12407
/*
12408
 * Check whether the model satisfies all equations in the tableau
12409
 */
12410
static bool equations_hold_in_model(simplex_solver_t *solver) {
12411
  row_t *row;
12412
  rational_t check;
12413
  uint32_t i, n;
12414

12415
  q_init(&check);
12416
  n = solver->matrix.nrows;
12417
  for (i=0; i<n; i++) {
12418
    row = matrix_row(&solver->matrix, i);
12419
    simplex_eval_rational_row(solver->value, row, &check);
12420
    if (q_is_nonzero(&check)) {
12421
      printf("---> BUG: invalid Simplex model: equation not satisfied\n");
12422
      printf("   row[%"PRIu32"]: ", i);
12423
      print_simplex_row(stdout, solver, row);
12424
      printf("\n");
12425
      fflush(stdout);
12426
      return false;
12427
    }
12428
  }
12429

12430
  q_clear(&check);
12431

12432
  return true;
12433
}
12434

12435

12436
/*
12437
 * Check whether the model satisfies all the assertions
12438
 */
12439
static bool assertions_hold_in_model(simplex_solver_t *solver) {
12440
  arith_atomtable_t *atbl;
12441
  arith_atom_t *atom;
12442
  thvar_t x;
12443
  bvar_t v;
12444
  bool truth;
12445
  uint32_t i, n;
12446

12447
  atbl = &solver->atbl;
12448
  n = atbl->natoms;
12449
  for (i=0; i<n; i++) {
12450
    atom = arith_atom(atbl, i);
12451
    v = boolvar_of_atom(atom);
12452
    x = var_of_atom(atom);
12453
    truth = simplex_eval_atom_in_model(solver->value, atom);
12454

12455
    switch (bvar_value(solver->core, v)) {
12456
    case VAL_FALSE:
12457
      if (truth) {
12458
        printf("---> BUG: invalid Simplex model\n");
12459
        print_simplex_atomdef(stdout, solver, v);
12460
        printf("  value[");
12461
        print_bvar(stdout, v);
12462
        printf("] = false\n");
12463
        printf("  value[");
12464
        print_simplex_var(stdout, solver, x);
12465
        printf("] = ");
12466
        q_print(stdout, solver->value + x);
12467
        printf("\n");
12468
        fflush(stdout);
12469

12470
        return false;
12471
      }
12472
      break;
12473
    case VAL_UNDEF_FALSE:
12474
    case VAL_UNDEF_TRUE:
12475
      // should not happen??
12476
      break;
12477
    case VAL_TRUE:
12478
      if (! truth) {
12479
        printf("---> BUG: invalid Simplex model\n");
12480
        print_simplex_atomdef(stdout, solver, v);
12481
        printf("  value[");
12482
        print_bvar(stdout, v);
12483
        printf("] = true\n");
12484
        printf("  value[");
12485
        print_simplex_var(stdout, solver, x);
12486
        printf("] = ");
12487
        q_print(stdout, solver->value + x);
12488
        printf("\n");
12489
        fflush(stdout);
12490
      }
12491
      break;
12492
    }
12493
  }
12494

12495
  return true;
12496
}
12497

12498

12499
/*
12500
 * Check that all integer variables have an integer value
12501
 */
12502
static bool model_is_integer_feasible(simplex_solver_t *solver) {
12503
  arith_vartable_t *vtbl;
12504
  uint32_t i, n;
12505

12506
  vtbl = &solver->vtbl;
12507
  n = vtbl->nvars;
12508
  for (i=0; i<n; i++) {
12509
    if (arith_var_is_int(vtbl, i) && ! q_is_integer(solver->value + i)) {
12510
      printf("---> BUG: invalid Simplex model\n");
12511
      printf("  integer variable ");
12512
      print_simplex_var(stdout, solver, i);
12513
      printf(" does not have an integer value\n");
12514
      printf("  value[");
12515
      print_simplex_var(stdout, solver, i);
12516
      printf("] = ");
12517
      q_print(stdout, solver->value + i);
12518
      printf("\n");
12519
      return false;
12520
    }
12521
  }
12522

12523
  return true;
12524
}
12525

12526

12527
/*
12528
 * Check that the model is consistent with the egraph
12529
 */
12530
static bool model_is_consistent_with_egraph(simplex_solver_t *solver) {
12531
  egraph_t *egraph;
12532
  arith_vartable_t *vtbl;
12533
  uint32_t i, j, n;
12534
  eterm_t t, u;
12535

12536
  egraph = solver->egraph;
12537
  if (egraph != NULL) {
12538
    vtbl = &solver->vtbl;
12539
    n = vtbl->nvars;
12540
    for (i=0; i<n; i++) {
12541
      t = arith_var_get_eterm(vtbl, i);
12542
      if (t != null_eterm) {
12543
        for (j=i+1; j<n; j++) {
12544
          u = arith_var_get_eterm(vtbl, j);
12545
          if (u != null_eterm && !egraph_equal_terms(egraph, t, u)) {
12546
            // t != u in the egraph so we want value[i] != value[j]
12547
            if (q_eq(solver->value + i, solver->value + j)) {
12548
              printf("---> BUG: invalid Simplex model\n");
12549
              printf("The model is not consistent with the egraph\n");
12550
              printf(" ");
12551
              print_simplex_var(stdout, solver, i);
12552
              printf(" is attached to egraph term: ");
12553
              print_eterm_id(stdout, t);
12554
              printf("\n ");
12555
              print_simplex_var(stdout, solver, j);
12556
              printf(" is attached to egraph term: ");
12557
              print_eterm_id(stdout, u);
12558
              printf("\n");
12559

12560
              printf(" value[");
12561
              print_simplex_var(stdout, solver, i);
12562
              printf("] = ");
12563
              q_print(stdout, solver->value + i);
12564
              printf("\n");
12565
              printf(" value[");
12566
              print_simplex_var(stdout, solver, j);
12567
              printf("] = ");
12568
              q_print(stdout, solver->value + j);
12569
              printf("\n");
12570

12571
              printf(" but ");
12572
              print_eterm_id(stdout, t);
12573
              printf(" != ");
12574
              print_eterm_id(stdout, u);
12575
              printf(" in the egraph\n");
12576

12577
              return false;
12578
            }
12579
          }
12580
        }
12581
      }
12582
    }
12583
  }
12584

12585
  return true;
12586
}
12587

12588
/*
12589
 * Check that the model is valid
12590
 */
12591
static bool good_simplex_model(simplex_solver_t *solver) {
12592
  return equations_hold_in_model(solver) && assertions_hold_in_model(solver) &&
12593
    model_is_integer_feasible(solver) && model_is_consistent_with_egraph(solver);
12594
}
12595

12596

12597
#endif
12598

12599

12600

12601
/*
12602
 * Model construction
12603
 */
12604
void simplex_build_model(simplex_solver_t *solver) {
12,890✔
12605
  byte_t *mark;
12606
  uint32_t i, n;
12607

12608
#if DEBUG
12609
  check_assignment(solver);
12610
#endif
12611

12612
  n = solver->vtbl.nvars;
12,890✔
12613
  solver->value = new_rational_array(n);
12,890✔
12614

12615
  /*
12616
   * Deal with fixed, eliminated, trivial variables.
12617
   */
12618
  mark = allocate_bitvector0(n);         // all variables initially unmarked
12,890✔
12619
  simplex_model_for_fvars(solver, mark); // fixed vars have a value and are marked
12,890✔
12620
  simplex_mark_eliminated_vars(solver, mark);
12,890✔
12621
  simplex_mark_trivial_vars(solver, mark);
12,890✔
12622

12623
  /*
12624
   * Compute a safe value for epsilon
12625
   */
12626
  q_set_one(&solver->epsilon); // default positive value
12,890✔
12627
  if (solver->egraph != NULL) {
12,890✔
12628
    // remove epsilon values that would cause a conflict with the egraph model.
12629
    epsilon_for_egraph(solver);
12,602✔
12630
  }
12631
  for (i=1; i<n; i++) {
22,972✔
12632
    if (! tst_bit(mark, i)) {
10,082✔
12633
      simplex_adjust_epsilon(solver, i);
9,030✔
12634
    }
12635
  }
12636

12637
  /*
12638
   * Compute values: for unmarked, eliminated, then trivial variables
12639
   */
12640
  simplex_model_for_unmarked_vars(solver, mark);
12,890✔
12641
  simplex_model_for_eliminated_vars(solver);
12,890✔
12642
  simplex_model_for_trivial_vars(solver);
12,890✔
12643

12644
  delete_bitvector(mark);
12,890✔
12645

12646
  assert(good_simplex_model(solver));
12647
}
12,890✔
12648

12649

12650
/*
12651
 * Free the model
12652
 */
12653
void simplex_free_model(simplex_solver_t *solver) {
12,890✔
12654
  uint32_t n;
12655

12656
  assert(solver->value != NULL);
12657
  n = solver->vtbl.nvars;
12,890✔
12658
  free_rational_array(solver->value, n);
12,890✔
12659
  solver->value = NULL;
12,890✔
12660
  q_clear(&solver->epsilon);
12,890✔
12661
  q_clear(&solver->factor);
12,890✔
12662
}
12,890✔
12663

12664

12665
/*
12666
 * Value of variable x in the model
12667
 */
12668
bool simplex_value_in_model(simplex_solver_t *solver, int32_t x, rational_t *v) {
3,109✔
12669
  assert(solver->value != NULL && 0 <= x && x < solver->vtbl.nvars);
12670
  q_set(v, solver->value + x);
3,109✔
12671
  return true;
3,109✔
12672
}
12673

12674

12675

12676
/*
12677
 * Get the type of variable x
12678
 */
12679
bool simplex_var_is_integer(simplex_solver_t *solver, int32_t x) {
1,543✔
12680
  return arith_var_is_int(&solver->vtbl, x);
1,543✔
12681
}
12682

12683

12684

12685
/****************
12686
 *  STATISTICS  *
12687
 ***************/
12688

12689
/*
12690
 * To get end-of-search statistics: set end_rows, end_atoms
12691
 */
12692
void simplex_collect_statistics(simplex_solver_t *solver) {
30✔
12693
  solver->stats.num_end_rows = solver->matrix.nrows;
30✔
12694
  solver->stats.num_end_atoms = solver->atbl.natoms;
30✔
12695
}
30✔
12696

12697

12698

12699
/******************************
12700
 *  INTERFACE TO THE CONTEXT  *
12701
 *****************************/
12702

12703

12704
static arith_interface_t simplex_context = {
12705
  (create_arith_var_fun_t) simplex_create_var,
12706
  (create_arith_const_fun_t) simplex_create_const,
12707
  (create_arith_poly_fun_t) simplex_create_poly,
12708
  (create_arith_pprod_fun_t) simplex_create_pprod,
12709

12710
  (create_arith_atom_fun_t) simplex_create_eq_atom,
12711
  (create_arith_atom_fun_t) simplex_create_ge_atom,
12712
  (create_arith_patom_fun_t) simplex_create_poly_eq_atom,
12713
  (create_arith_patom_fun_t) simplex_create_poly_ge_atom,
12714
  (create_arith_vareq_atom_fun_t) simplex_create_vareq_atom,
12715

12716
  (assert_arith_axiom_fun_t) simplex_assert_eq_axiom,
12717
  (assert_arith_axiom_fun_t) simplex_assert_ge_axiom,
12718
  (assert_arith_paxiom_fun_t) simplex_assert_poly_eq_axiom,
12719
  (assert_arith_paxiom_fun_t) simplex_assert_poly_ge_axiom,
12720
  (assert_arith_vareq_axiom_fun_t) simplex_assert_vareq_axiom,
12721
  (assert_arith_cond_vareq_axiom_fun_t) simplex_assert_cond_vareq_axiom,
12722
  (assert_arith_clause_vareq_axiom_fun_t) simplex_assert_clause_vareq_axiom,
12723

12724
  (attach_eterm_fun_t) simplex_attach_eterm,
12725
  (eterm_of_var_fun_t) simplex_eterm_of_var,
12726

12727
  (build_model_fun_t) simplex_build_model,
12728
  (free_model_fun_t) simplex_free_model,
12729
  (arith_val_in_model_fun_t) simplex_value_in_model,
12730

12731
  (arith_var_is_int_fun_t) simplex_var_is_integer,
12732
};
12733

12734

12735
/*
12736
 * Return the interface descriptor
12737
 */
12738
arith_interface_t *simplex_arith_interface(simplex_solver_t *solver) {
4,880✔
12739
  return &simplex_context;
4,880✔
12740
}
12741

12742

12743

12744

12745
/********************************
12746
 *  SMT AND CONTROL INTERFACES  *
12747
 *******************************/
12748

12749
static th_ctrl_interface_t simplex_control = {
12750
  (start_intern_fun_t) simplex_start_internalization,
12751
  (start_fun_t) simplex_start_search,
12752
  (propagate_fun_t) simplex_propagate,
12753
  (final_check_fun_t) simplex_final_check,
12754
  (increase_level_fun_t) simplex_increase_decision_level,
12755
  (backtrack_fun_t) simplex_backtrack,
12756
  (push_fun_t) simplex_push,
12757
  (pop_fun_t) simplex_pop,
12758
  (reset_fun_t) simplex_reset,
12759
  (clear_fun_t) simplex_clear,
12760
};
12761

12762
static th_smt_interface_t simplex_smt = {
12763
  (assert_fun_t) simplex_assert_atom,
12764
  (expand_expl_fun_t) simplex_expand_explanation,
12765
  (select_pol_fun_t) simplex_select_polarity,
12766
  NULL,
12767
  NULL,
12768
};
12769

12770

12771
/*
12772
 * Get the control and smt interfaces
12773
 */
12774
th_ctrl_interface_t *simplex_ctrl_interface(simplex_solver_t *solver) {
4,880✔
12775
  return &simplex_control;
4,880✔
12776
}
12777

12778
th_smt_interface_t *simplex_smt_interface(simplex_solver_t *solver) {
4,880✔
12779
  return &simplex_smt;
4,880✔
12780
}
12781

12782

12783

12784

12785

12786
/*********************************************
12787
 *  SATELLITE SOLVER INTERFACE (FOR EGRAPH)  *
12788
 ********************************************/
12789

12790
static th_egraph_interface_t simplex_egraph = {
12791
  (assert_eq_fun_t) simplex_assert_var_eq,
12792
  (assert_diseq_fun_t) simplex_assert_var_diseq,
12793
  (assert_distinct_fun_t) simplex_assert_var_distinct,
12794
  (check_diseq_fun_t) simplex_check_disequality,
12795
  (is_constant_fun_t) simplex_var_is_constant,
12796
  (expand_eq_exp_fun_t) simplex_expand_th_explanation,
12797
  (reconcile_model_fun_t) simplex_reconcile_model,
12798
  (prepare_model_fun_t) simplex_prep_model,
12799
  (equal_in_model_fun_t) simplex_var_equal_in_model,
12800
  (gen_inter_lemma_fun_t) simplex_gen_interface_lemma,
12801
  (release_model_fun_t) simplex_release_model,
12802
  (build_partition_fun_t) simplex_build_model_partition,
12803
  (free_partition_fun_t) simplex_release_model_partition,
12804
  (attach_to_var_fun_t) simplex_attach_eterm,
12805
  (get_eterm_fun_t) simplex_eterm_of_var,
12806
  (select_eq_polarity_fun_t) simplex_select_eq_polarity,
12807
};
12808

12809

12810
static arith_egraph_interface_t simplex_arith_egraph = {
12811
  (make_arith_var_fun_t) simplex_create_var,
12812
  (arith_val_fun_t) simplex_value_in_model,
12813
};
12814

12815

12816
/*
12817
 * Get the egraph interfaces
12818
 */
12819
th_egraph_interface_t *simplex_egraph_interface(simplex_solver_t *solver) {
4,316✔
12820
  return &simplex_egraph;
4,316✔
12821
}
12822

12823
arith_egraph_interface_t *simplex_arith_egraph_interface(simplex_solver_t *solver) {
4,316✔
12824
  return &simplex_arith_egraph;
4,316✔
12825
}
12826

12827

12828

12829

12830

12831
/***************************
12832
 *   DEBUGGING FUNCTIONS   *
12833
 **************************/
12834

12835
#if DUMP
12836

12837
static void print_simplex(FILE *f, simplex_solver_t *solver) {
12838
  fprintf(f, "\n==== Variables ====\n");
12839
  print_simplex_vars(f, solver);
12840
  fprintf(f, "\n==== Tableau ====\n");
12841
  print_simplex_matrix(f, solver);
12842
  fprintf(f, "\n==== Fixed vars ====\n");
12843
  print_fixed_var_vector(f, &solver->vtbl, &solver->fvars);
12844
  fprintf(f, "\n==== Eliminated rows ====\n");
12845
  print_elim_matrix(f, &solver->vtbl, &solver->elim);
12846
  fprintf(f, "\n==== Bounds  ====\n");
12847
  print_simplex_bounds(f, solver);
12848
  fprintf(f, "\n==== Assignment ====\n");
12849
  print_simplex_assignment(f, solver);
12850
  fprintf(f, "\n==== Atoms ====\n");
12851
  print_simplex_atoms(f, solver);
12852
  fprintf(f, "\n==== Boolean gates ====\n");
12853
  print_gate_table(f, &solver->gate_manager->htbl);
12854
}
12855

12856
static void print_core(FILE *f, smt_core_t *core) {
12857
  fprintf(f, "\n==== Clauses ====\n");
12858
  print_clauses(f, core);
12859
  fprintf(f, "\n==== Boolean assignment ====\n");
12860
  print_boolean_assignment(f, core);
12861
}
12862

12863
static void dump_state(simplex_solver_t *solver) {
12864
  FILE *dump;
12865

12866
  dump = fopen("simplex.dmp", "w");
12867
  if (dump == NULL) return;
12868
  print_simplex(dump, solver);
12869
  print_core(dump, solver->core);
12870
  fclose(dump);
12871
}
12872

12873
#endif
12874

12875

12876

12877
#if DEBUG
12878

12879
/*
12880
 * Error messages about variable x
12881
 */
12882
static void print_var_value(simplex_solver_t *solver, thvar_t x) {
12883
  printf("     val[");
12884
  print_simplex_var(stdout, solver, x);
12885
  printf("] = ");
12886
  xq_print(stdout, arith_var_value(&solver->vtbl, x));
12887
  printf("\n");
12888
}
12889

12890
static void print_var_lower_bound(simplex_solver_t *solver, thvar_t x) {
12891
  int32_t j;
12892

12893
  printf("     lb[");
12894
  print_simplex_var(stdout, solver, x);
12895
  printf("] = ");
12896
  j = arith_var_lower_index(&solver->vtbl, x);
12897
  if (j < 0) {
12898
    printf(" - infinity\n");
12899
  } else {
12900
    xq_print(stdout, &solver->bstack.bound[j]);
12901
    printf("\n");
12902
  }
12903
}
12904

12905
static void print_var_upper_bound(simplex_solver_t *solver, thvar_t x) {
12906
  int32_t j;
12907

12908
  printf("     ub[");
12909
  print_simplex_var(stdout, solver, x);
12910
  printf("] = ");
12911
  j = arith_var_upper_index(&solver->vtbl, x);
12912
  if (j < 0) {
12913
    printf(" + infinity\n");
12914
  } else {
12915
    xq_print(stdout, &solver->bstack.bound[j]);
12916
    printf("\n");
12917
  }
12918
}
12919

12920
static void print_var_lower_tag(simplex_solver_t *solver, thvar_t x) {
12921
  printf("     lb_flag[");
12922
  print_simplex_var(stdout, solver, x);
12923
  if (arith_var_at_lower_bound(&solver->vtbl, x)) {
12924
    printf("] = true\n");
12925
  } else {
12926
    printf("] = false\n");
12927
  }
12928
}
12929

12930
static void print_var_upper_tag(simplex_solver_t *solver, thvar_t x) {
12931
  printf("     ub_flag[");
12932
  print_simplex_var(stdout, solver, x);
12933
  if (arith_var_at_upper_bound(&solver->vtbl, x)) {
12934
    printf("] = true\n");
12935
  } else {
12936
    printf("] = false\n");
12937
  }
12938
}
12939

12940
/*
12941
 * Check whether assertion a is satisfied
12942
 */
12943
static void check_assertion(simplex_solver_t *solver, int32_t a) {
12944
  arith_atom_t *atom;
12945
  uint32_t i;
12946
  bool b;
12947

12948
  i = atom_of_assertion(a);
12949
  atom = arith_atom(&solver->atbl, i);
12950
  b = simplex_eval_atom(solver, atom);
12951
  if (b != assertion_is_true(a)) {
12952
    printf("---> ERROR: assertion not satisfied\n");
12953
    printf("     Atom ");
12954
    print_simplex_atom(stdout, solver, i);
12955
    if (assertion_is_true(a)) {
12956
      printf(" asserted true\n");
12957
    } else {
12958
      printf(" asserted false\n");
12959
    }
12960
    print_var_value(solver, var_of_atom(atom));
12961
  }
12962

12963
  switch (bvar_value(solver->core, boolvar_of_atom(atom))) {
12964
  case VAL_FALSE:
12965
    if (assertion_is_true(a)) {
12966
      printf("---> ERROR: truth assignment mismatch\n");
12967
      printf("     atom %"PRId32" asserted true\n", i);
12968
      printf("     var ");
12969
      print_bvar(stdout, boolvar_of_atom(atom));
12970
      printf(" is false\n");
12971
    }
12972
    break;
12973
  case VAL_UNDEF_TRUE:
12974
  case VAL_UNDEF_FALSE:
12975
    printf("---> ERROR: truth assignment mismatch\n");
12976
    printf("     atom %"PRId32" asserted\n", i);
12977
    printf("     atom %"PRId32" is ", i);
12978
    print_simplex_atom(stdout, solver, i);
12979
    printf("\n");
12980
    printf("     var ");
12981
    print_bvar(stdout, boolvar_of_atom(atom));
12982
    printf(" not assigned\n");
12983
    break;
12984
  case VAL_TRUE:
12985
    if (assertion_is_false(a)) {
12986
      printf("---> ERROR: truth assignment mismatch\n");
12987
      printf("     atom %"PRId32" asserted false\n", i);
12988
      printf("     var ");
12989
      print_bvar(stdout, boolvar_of_atom(atom));
12990
      printf(" is true\n");
12991
    }
12992
    break;
12993
  }
12994
}
12995

12996

12997
/*
12998
 * Check whether all assertions are satisfied by the current assignment
12999
 */
13000
static void check_all_assertions_satisfied(simplex_solver_t *solver) {
13001
  arith_astack_t *stack;
13002
  uint32_t i, n;
13003

13004
  stack = &solver->assertion_queue;
13005
  n = stack->top;
13006
  for (i=0; i<n; i++) {
13007
    check_assertion(solver, stack->data[i]);
13008
  }
13009
}
13010

13011

13012

13013
/*
13014
 * Check whether the current assignment satisfies all the bounds
13015
 */
13016
static void check_all_bounds_satisfied(simplex_solver_t *solver) {
13017
  uint32_t i, n;
13018

13019
  n = solver->vtbl.nvars;
13020
  for (i=0; i<n; i++) {
13021
    if (! value_satisfies_bounds(solver, i)) {
13022
      printf("---> ERROR: val[");
13023
      print_simplex_var(stdout, solver, i);
13024
      printf("] not within bounds\n");
13025
      print_var_value(solver, i);
13026
      print_var_lower_bound(solver, i);
13027
      print_var_upper_bound(solver, i);
13028
      fflush(stdout);
13029
    }
13030
  }
13031
}
13032

13033

13034
/*
13035
 * Check whether the current assignment satisfies all bounds on non-basic
13036
 * variables.
13037
 */
13038
static void check_all_nonbasic_bounds_satisfied(simplex_solver_t *solver) {
13039
  uint32_t i, n;
13040

13041
  n = solver->vtbl.nvars;
13042
  for (i=0; i<n; i++) {
13043
    if (matrix_is_nonbasic_var(&solver->matrix, i) &&
13044
        ! value_satisfies_bounds(solver, i)) {
13045
      printf("---> ERROR: non-basic val[");
13046
      print_simplex_var(stdout, solver, i);
13047
      printf("] not within bounds\n");
13048
      print_var_value(solver, i);
13049
      print_var_lower_bound(solver, i);
13050
      print_var_upper_bound(solver, i);
13051
      fflush(stdout);
13052
    }
13053
  }
13054
}
13055

13056
/*
13057
 * Check whether equation in row r is satisfied
13058
 */
13059
static void check_equation_satisfied(simplex_solver_t *solver, uint32_t r) {
13060
  row_t *row;
13061
  xrational_t check;
13062
  uint32_t i, n;
13063
  thvar_t x;
13064

13065
  xq_init(&check);
13066
  row = matrix_row(&solver->matrix, r);
13067
  n = row->size;
13068
  for (i=0; i<n; i++) {
13069
    x = row->data[i].c_idx;
13070
    if (x >= 0) {
13071
      xq_addmul(&check, arith_var_value(&solver->vtbl, x), &row->data[i].coeff);
13072
    }
13073
  }
13074

13075
  if (! xq_is_zero(&check)) {
13076
    printf("---> ERROR: row[%"PRIu32"] not satisfied\n", r);
13077
    fflush(stdout);
13078
  }
13079
  xq_clear(&check);
13080
}
13081

13082

13083
/*
13084
 * Check whether all equations in matrix are satisfied
13085
 */
13086
static void check_all_equations_satisfied(simplex_solver_t *solver) {
13087
  uint32_t i, n;
13088

13089
  n = solver->matrix.nrows;
13090
  for (i=0; i<n; i++) {
13091
    check_equation_satisfied(solver, i);
13092
  }
13093
}
13094

13095

13096
/*
13097
 * Check whether the current assignment satisfies all the constraints
13098
 */
13099
static void check_assignment(simplex_solver_t *solver) {
13100
  check_all_bounds_satisfied(solver);
13101
  check_all_equations_satisfied(solver);
13102
  check_all_assertions_satisfied(solver);
13103
}
13104

13105

13106
/*
13107
 * Check whether the current assignment satisfies all equality constraints
13108
 * and all bounds on non-basic variables.
13109
 */
13110
static void check_nonbasic_assignment(simplex_solver_t *solver) {
13111
  check_all_nonbasic_bounds_satisfied(solver);
13112
  check_all_equations_satisfied(solver);
13113
}
13114

13115

13116
/*
13117
 * Check whether the ub/lb tags on non-basic variables are correct
13118
 */
13119
static void check_vartags(simplex_solver_t *solver) {
13120
  uint32_t i, n;
13121
  bool at_bound, tag;
13122

13123
  n = solver->vtbl.nvars;
13124
  for (i=0; i<n; i++) {
13125
    if (matrix_is_nonbasic_var(&solver->matrix, i)) {
13126
      at_bound = variable_at_lower_bound(solver, i);
13127
      tag = arith_var_at_lower_bound(&solver->vtbl, i);
13128
      if (at_bound != tag) {
13129
        printf("---> ERROR: wrong tag for variable ");
13130
        print_simplex_var(stdout, solver, i);
13131
        printf("\n");
13132
        print_var_value(solver, i);
13133
        print_var_lower_bound(solver, i);
13134
        print_var_lower_tag(solver, i);
13135
        fflush(stdout);
13136
      }
13137

13138
      at_bound = variable_at_upper_bound(solver, i);
13139
      tag = arith_var_at_upper_bound(&solver->vtbl, i);
13140
      if (at_bound != tag) {
13141
        printf("---> ERROR: wrong tag for variable ");
13142
        print_simplex_var(stdout, solver, i);
13143
        printf("\n");
13144
        print_var_value(solver, i);
13145
        print_var_upper_bound(solver, i);
13146
        print_var_upper_tag(solver, i);
13147
        fflush(stdout);
13148
      }
13149
    }
13150
  }
13151
}
13152

13153

13154
/*
13155
 * Check that all infeasible basic variables are in the heap
13156
 */
13157
static void check_infeasible_vars(simplex_solver_t *solver) {
13158
  uint32_t i, n;
13159
  thvar_t x;
13160

13161
  n = solver->matrix.nrows;
13162
  for (i=0; i<n; i++) {
13163
    x = matrix_basic_var(&solver->matrix, i);
13164
    if (! (value_satisfies_bounds(solver, x) || int_heap_member(&solver->infeasible_vars, x))) {
13165
      printf("---> ERROR: infeasible variable ");
13166
      print_simplex_var(stdout, solver, x);
13167
      printf(" not in the heap\n");
13168
      fflush(stdout);
13169
    }
13170
  }
13171
}
13172

13173

13174

13175
/*
13176
 * Check that all bounds on integer variables are integer constants
13177
 */
13178
static void check_integer_bounds(simplex_solver_t *solver) {
13179
  uint32_t i, n;
13180
  int32_t k;
13181

13182
  n = solver->vtbl.nvars;
13183
  for (i=0; i<n; i++) {
13184
    if (arith_var_is_int(&solver->vtbl, i)) {
13185
      k = arith_var_upper_index(&solver->vtbl, i);
13186
      if (k >= 0 && ! xq_is_integer(solver->bstack.bound + k)) {
13187
        printf("---> ERROR: non-integer bound on an integer variable ");
13188
        print_simplex_var(stdout, solver, i);
13189
        printf("\n");
13190
        print_var_upper_bound(solver, i);
13191
        fflush(stdout);
13192
      }
13193

13194
      k = arith_var_lower_index(&solver->vtbl, i);
13195
      if (k >= 0 && ! xq_is_integer(solver->bstack.bound + k)) {
13196
        printf("---> ERROR: non-integer bound on an integer variable ");
13197
        print_simplex_var(stdout, solver, i);
13198
        printf("\n");
13199
        print_var_lower_bound(solver, i);
13200
        fflush(stdout);
13201
      }
13202
    }
13203
  }
13204
}
13205

13206

13207
/*
13208
 * All indices should be unmarked, except within theory/conflict explanation
13209
 */
13210
static void check_bound_marks(simplex_solver_t *solver) {
13211
  arith_bstack_t *bstack;
13212
  uint32_t i, n;
13213

13214
  bstack = &solver->bstack;
13215
  n = bstack->top;
13216
  for (i=0; i<n; i++) {
13217
    if (arith_cnstr_is_marked(bstack, i)) {
13218
      printf("---> ERROR: mark on bound %"PRIu32" is not cleared\n", i);
13219
      fflush(stdout);
13220
    }
13221
  }
13222
}
13223

13224

13225
#endif
13226

13227

13228

13229
#if TRACE
13230

13231
/*
13232
 * Show the list of infeasible variables (bounds not satisfied)
13233
 * - these variables are stored in the heap after a call to
13234
 *   simplex_fix_nonbasic_assingment
13235
 */
13236
static void show_heap(FILE *f, simplex_solver_t *solver) {
13237
  uint32_t i, n;
13238

13239
  n = solver->matrix.nrows;
13240
  fprintf(f, "Infeasible vars:");
13241
  for (i=0; i<n; i++) {
13242
    if (int_heap_member(&solver->infeasible_vars, i)) {
13243
      fprintf(f, " x_%"PRIu32, i);
13244
    }
13245
  }
13246
  fprintf(f, "\n");
13247
}
13248

13249
#endif
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