GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/prop/bvminisat/simp/SimpSolver.cc Lines: 300 406 73.9 %
Date: 2021-05-22 Branches: 370 974 38.0 %

Line Exec Source
1
/***********************************************************************************[SimpSolver.cc]
2
Copyright (c) 2006,      Niklas Een, Niklas Sorensson
3
Copyright (c) 2007-2010, Niklas Sorensson
4
5
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
associated documentation files (the "Software"), to deal in the Software without restriction,
7
including without limitation the rights to use, copy, modify, merge, publish, distribute,
8
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
9
furnished to do so, subject to the following conditions:
10
11
The above copyright notice and this permission notice shall be included in all copies or
12
substantial portions of the Software.
13
14
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
18
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
**************************************************************************************************/
20
21
#include "prop/bvminisat/simp/SimpSolver.h"
22
23
#include "base/check.h"
24
#include "options/bv_options.h"
25
#include "options/smt_options.h"
26
#include "proof/clause_id.h"
27
#include "prop/bvminisat/mtl/Sort.h"
28
#include "prop/bvminisat/utils/System.h"
29
30
namespace cvc5 {
31
namespace BVMinisat {
32
33
//=================================================================================================
34
// Options:
35
36
37
static const char* _cat = "SIMP";
38
39
9397
static BoolOption   opt_use_asymm        (_cat, "asymm",        "Shrink clauses by asymmetric branching.", false);
40
9397
static BoolOption   opt_use_rcheck       (_cat, "rcheck",       "Check if a clause is already implied. (costly)", false);
41
9397
static BoolOption   opt_use_elim         (_cat, "elim",         "Perform variable elimination.", true);
42
9397
static IntOption    opt_grow             (_cat, "grow",         "Allow a variable elimination step to grow by a number of clauses.", 0);
43
9397
static IntOption    opt_clause_lim       (_cat, "cl-lim",       "Variables are not eliminated if it produces a resolvent with a length above this limit. -1 means no limit", 20,   IntRange(-1, INT32_MAX));
44
9397
static IntOption    opt_subsumption_lim  (_cat, "sub-lim",      "Do not check if subsumption against a clause larger than this. -1 means no limit.", 1000, IntRange(-1, INT32_MAX));
45
9397
static DoubleOption opt_simp_garbage_frac(_cat, "simp-gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered during simplification.",  0.5, DoubleRange(0, false, HUGE_VAL, false));
46
47
48
//=================================================================================================
49
// Constructor/Destructor:
50
51
9422
SimpSolver::SimpSolver(cvc5::context::Context* context)
52
    : Solver(context),
53
      grow(opt_grow),
54
      clause_lim(opt_clause_lim),
55
      subsumption_lim(opt_subsumption_lim),
56
      simp_garbage_frac(opt_simp_garbage_frac),
57
      use_asymm(opt_use_asymm),
58
      use_rcheck(opt_use_rcheck),
59
      use_elim(opt_use_elim
60
1669164
               && cvc5::options::bitblastMode()
61
9422
                      == cvc5::options::BitblastMode::EAGER
62
9439
               && !cvc5::options::produceModels()),
63
      merges(0),
64
      asymm_lits(0),
65
      eliminated_vars(0),
66
      elimorder(1),
67
      use_simplification(true),
68
18844
      occurs(ClauseDeleted(ca)),
69
18844
      elim_heap(ElimLt(n_occ)),
70
      bwdsub_assigns(0),
71
56532
      n_touched(0)
72
{
73
74
18844
    vec<Lit> dummy(1,lit_Undef);
75
9422
    ca.extra_clause_field = true; // NOTE: must happen before allocating the dummy clause below.
76
9422
    bwdsub_tmpunit        = ca.alloc(dummy);
77
9422
    remove_satisfied      = false;
78
79
    // add the initialization for all the internal variables
80
28266
    for (int i = frozen.size(); i < vardata.size(); ++ i) {
81
18844
      frozen    .push(1);
82
18844
      eliminated.push(0);
83
18844
      if (use_simplification){
84
18844
          n_occ     .push(0);
85
18844
          n_occ     .push(0);
86
18844
          occurs    .init(i);
87
18844
          touched   .push(0);
88
18844
          elim_heap .insert(i);
89
      }
90
    }
91
92
9422
}
93
94
95
18844
SimpSolver::~SimpSolver()
96
{
97
  //  cvc5::StatisticsRegistry::unregisterStat(&total_eliminate_time);
98
18844
}
99
100
101
2099529
Var SimpSolver::newVar(bool sign, bool dvar, bool freeze) {
102
2099529
    Var v = Solver::newVar(sign, dvar);
103
104
2099529
    frozen    .push((char)false);
105
2099529
    eliminated.push((char)false);
106
107
2099529
    if (use_simplification){
108
2099529
        n_occ     .push(0);
109
2099529
        n_occ     .push(0);
110
2099529
        occurs    .init(v);
111
2099529
        touched   .push(0);
112
2099529
        elim_heap .insert(v);
113
2099529
        if (freeze) {
114
278418
          setFrozen(v, true);
115
        }
116
    }
117
2099529
    return v;
118
}
119
120
121
122
10079
lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp)
123
{
124
10079
    only_bcp = false;
125
126
20158
    vec<Var> extra_frozen;
127
10079
    lbool    result = l_True;
128
129
10079
    do_simp &= use_simplification;
130
131
10079
    if (do_simp) {
132
        // Assumptions must be temporarily frozen to run variable elimination:
133
788755
        for (int i = 0; i < assumptions.size(); i++){
134
778676
            Var v = var(assumptions[i]);
135
136
            // If an assumption has been eliminated, remember it.
137
778676
            Assert(!isEliminated(v));
138
139
778676
            if (!frozen[v]){
140
                // Freeze and store.
141
                setFrozen(v, true);
142
                extra_frozen.push(v);
143
            } }
144
145
10079
        if (do_simp && clause_added) {
146
5968
          cancelUntil(0);
147
5968
          result = lbool(eliminate(turn_off_simp));
148
5968
          clause_added = false;
149
        }
150
    }
151
152
10079
    if (result == l_True)
153
10077
        result = Solver::solve_();
154
2
    else if (verbosity >= 1)
155
        printf("===============================================================================\n");
156
157
10079
    if (do_simp)
158
        // Unfreeze the assumptions that were frozen:
159
10079
        for (int i = 0; i < extra_frozen.size(); i++)
160
            setFrozen(extra_frozen[i], false);
161
162
20158
    return result;
163
}
164
165
166
167
8013349
bool SimpSolver::addClause_(vec<Lit>& ps, ClauseId& id)
168
{
169
#ifdef CVC5_ASSERTIONS
170
8013349
  for (int i = 0; i < ps.size(); i++) Assert(!isEliminated(var(ps[i])));
171
#endif
172
173
8013349
    int nclauses = clauses.size();
174
175
8013349
    if (use_rcheck && implied(ps))
176
        return true;
177
178
8013349
    if (!Solver::addClause_(ps, id))
179
12
        return false;
180
181
8013337
    if (use_simplification && clauses.size() == nclauses + 1){
182
8001908
        CRef          cr = clauses.last();
183
8001908
        const Clause& clause = ca[cr];
184
185
        // NOTE: the clause is added to the queue immediately and then
186
        // again during 'gatherTouchedClauses()'. If nothing happens
187
        // in between, it will only be checked once. Otherwise, it may
188
        // be checked twice unnecessarily. This is an unfortunate
189
        // consequence of how backward subsumption is used to mimic
190
        // forward subsumption.
191
8001908
        subsumption_queue.insert(cr);
192
29747201
        for (int i = 0; i < clause.size(); i++)
193
        {
194
21745293
          occurs[var(clause[i])].push(cr);
195
21745293
          n_occ[toInt(clause[i])]++;
196
21745293
          touched[var(clause[i])] = 1;
197
21745293
          n_touched++;
198
21745293
          if (elim_heap.inHeap(var(clause[i])))
199
20514166
            elim_heap.increase(var(clause[i]));
200
        }
201
    }
202
203
8013337
    return true;
204
}
205
206
207
53346
void SimpSolver::removeClause(CRef cr)
208
{
209
53346
  const Clause& clause = ca[cr];
210
211
53346
  if (use_simplification)
212
  {
213
218556
    for (int i = 0; i < clause.size(); i++)
214
    {
215
165210
      n_occ[toInt(clause[i])]--;
216
165210
      updateElimHeap(var(clause[i]));
217
165210
      occurs.smudge(var(clause[i]));
218
    }
219
  }
220
53346
  Solver::removeClause(cr);
221
53346
}
222
223
224
44137
bool SimpSolver::strengthenClause(CRef cr, Lit l)
225
{
226
44137
  Clause& clause = ca[cr];
227
44137
  Assert(decisionLevel() == 0);
228
44137
  Assert(use_simplification);
229
230
  // FIX: this is too inefficient but would be nice to have (properly
231
  // implemented) if (!find(subsumption_queue, &clause))
232
44137
  subsumption_queue.insert(cr);
233
234
44137
  if (clause.size() == 2)
235
  {
236
3481
    removeClause(cr);
237
3481
    clause.strengthen(l);
238
  }
239
  else
240
  {
241
40656
    detachClause(cr, true);
242
40656
    clause.strengthen(l);
243
40656
    attachClause(cr);
244
40656
    remove(occurs[var(l)], cr);
245
40656
    n_occ[toInt(l)]--;
246
40656
    updateElimHeap(var(l));
247
  }
248
249
44137
  return clause.size() == 1 ? enqueue(clause[0]) && propagate() == CRef_Undef
250
44137
                            : true;
251
}
252
253
254
// Returns FALSE if clause is always satisfied ('out_clause' should not be used).
255
28059
bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause)
256
{
257
28059
    merges++;
258
28059
    out_clause.clear();
259
260
28059
    bool  ps_smallest = _ps.size() < _qs.size();
261
28059
    const Clause& ps  =  ps_smallest ? _qs : _ps;
262
28059
    const Clause& qs  =  ps_smallest ? _ps : _qs;
263
264
58929
    for (int i = 0; i < qs.size(); i++)
265
    {
266
47675
      if (var(qs[i]) != v)
267
      {
268
139521
        for (int j = 0; j < ps.size(); j++)
269
        {
270
125484
          if (var(ps[j]) == var(qs[i]))
271
          {
272
20470
            if (ps[j] == ~qs[i])
273
16805
              return false;
274
            else
275
3665
              goto next;
276
          }
277
        }
278
14037
        out_clause.push(qs[i]);
279
      }
280
44038
    next:;
281
    }
282
283
57606
    for (int i = 0; i < ps.size(); i++)
284
46352
        if (var(ps[i]) != v)
285
35098
            out_clause.push(ps[i]);
286
287
11254
    return true;
288
}
289
290
291
// Returns FALSE if clause is always satisfied.
292
57407
bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, int& size)
293
{
294
57407
    merges++;
295
296
57407
    bool  ps_smallest = _ps.size() < _qs.size();
297
57407
    const Clause& ps  =  ps_smallest ? _qs : _ps;
298
57407
    const Clause& qs  =  ps_smallest ? _ps : _qs;
299
57407
    const Lit*  __ps  = (const Lit*)ps;
300
57407
    const Lit*  __qs  = (const Lit*)qs;
301
302
57407
    size = ps.size()-1;
303
304
148391
    for (int i = 0; i < qs.size(); i++)
305
    {
306
116469
      if (var(__qs[i]) != v)
307
      {
308
395641
        for (int j = 0; j < ps.size(); j++)
309
        {
310
347652
          if (var(__ps[j]) == var(__qs[i]))
311
          {
312
33100
            if (__ps[j] == ~__qs[i])
313
25485
              return false;
314
            else
315
7615
              goto next;
316
          }
317
        }
318
47989
        size++;
319
      }
320
126364
    next:;
321
    }
322
323
31922
    return true;
324
}
325
326
327
5977
void SimpSolver::gatherTouchedClauses()
328
{
329
5977
    if (n_touched == 0) return;
330
331
    int i,j;
332
6601858
    for (i = j = 0; i < subsumption_queue.size(); i++)
333
6595883
        if (ca[subsumption_queue[i]].mark() == 0)
334
6595883
            ca[subsumption_queue[i]].mark(2);
335
336
19469825
    for (i = 0; i < touched.size(); i++)
337
19463850
        if (touched[i]){
338
1884228
            const vec<CRef>& cs = occurs.lookup(i);
339
30648473
            for (j = 0; j < cs.size(); j++)
340
28764245
                if (ca[cs[j]].mark() == 0){
341
8221335
                    subsumption_queue.insert(cs[j]);
342
8221335
                    ca[cs[j]].mark(2);
343
                }
344
1884228
            touched[i] = 0;
345
        }
346
347
14823193
    for (i = 0; i < subsumption_queue.size(); i++)
348
14817218
        if (ca[subsumption_queue[i]].mark() == 2)
349
14817218
            ca[subsumption_queue[i]].mark(0);
350
351
5975
    n_touched = 0;
352
}
353
354
bool SimpSolver::implied(const vec<Lit>& clause)
355
{
356
  Assert(decisionLevel() == 0);
357
358
  trail_lim.push(trail.size());
359
  for (int i = 0; i < clause.size(); i++)
360
  {
361
    if (value(clause[i]) == l_True)
362
    {
363
      cancelUntil(0);
364
      return false;
365
    }
366
    else if (value(clause[i]) != l_False)
367
    {
368
      Assert(value(clause[i]) == l_Undef);
369
      uncheckedEnqueue(~clause[i]);
370
    }
371
  }
372
373
  bool result = propagate() != CRef_Undef;
374
  cancelUntil(0);
375
  return result;
376
}
377
378
379
// Backward subsumption + backward subsumption resolution
380
8497
bool SimpSolver::backwardSubsumptionCheck(bool verbose)
381
{
382
8497
    int cnt = 0;
383
8497
    int subsumed = 0;
384
8497
    int deleted_literals = 0;
385
8497
    Assert(decisionLevel() == 0);
386
387
29766705
    while (subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()){
388
389
        // Empty subsumption queue and return immediately on user-interrupt:
390
14879104
        if (asynch_interrupt){
391
            subsumption_queue.clear();
392
            bwdsub_assigns = trail.size();
393
            break; }
394
395
        // Check top-level assignments by creating a dummy clause and placing it in the queue:
396
14879104
        if (subsumption_queue.size() == 0 && bwdsub_assigns < trail.size()){
397
6495
            Lit l = trail[bwdsub_assigns++];
398
6495
            ca[bwdsub_tmpunit][0] = l;
399
6495
            ca[bwdsub_tmpunit].calcAbstraction();
400
6495
            subsumption_queue.insert(bwdsub_tmpunit); }
401
402
14879104
        CRef    cr = subsumption_queue.peek(); subsumption_queue.pop();
403
14879104
        Clause& clause = ca[cr];
404
405
14879104
        if (clause.mark()) continue;
406
407
14853979
        if (verbose && verbosity >= 2 && cnt++ % 1000 == 0)
408
            printf("subsumption left: %10d (%10d subsumed, %10d deleted literals)\r", subsumption_queue.size(), subsumed, deleted_literals);
409
410
14853979
        Assert(clause.size() > 1
411
               || value(clause[0]) == l_True);  // Unit-clauses should have been
412
                                                // propagated before this point.
413
414
        // Find best variable to scan:
415
14853979
        Var best = var(clause[0]);
416
43047550
        for (int i = 1; i < clause.size(); i++)
417
28193571
          if (occurs[var(clause[i])].size() < occurs[best].size())
418
13120431
            best = var(clause[i]);
419
420
        // Search all candidates:
421
14853979
        vec<CRef>& _cs = occurs.lookup(best);
422
14853979
        CRef*       cs = (CRef*)_cs;
423
424
165299931
        for (int j = 0; j < _cs.size(); j++)
425
150445952
          if (clause.mark())
426
            break;
427
451336642
          else if (!ca[cs[j]].mark() && cs[j] != cr
428
421640460
                   && (subsumption_lim == -1
429
135597254
                       || ca[cs[j]].size() < subsumption_lim))
430
          {
431
135597254
            Lit l = clause.subsumes(ca[cs[j]]);
432
433
135597254
            if (l == lit_Undef)
434
33577
              subsumed++, removeClause(cs[j]);
435
135563677
            else if (l != lit_Error)
436
            {
437
44137
              deleted_literals++;
438
439
44137
              if (!strengthenClause(cs[j], ~l)) return false;
440
441
              // Did current candidate get deleted from cs? Then check candidate
442
              // at index j again:
443
44137
              if (var(l) == best) j--;
444
            }
445
          }
446
    }
447
448
8497
    return true;
449
}
450
451
452
bool SimpSolver::asymm(Var v, CRef cr)
453
{
454
  Clause& clause = ca[cr];
455
  Assert(decisionLevel() == 0);
456
457
  if (clause.mark() || satisfied(clause)) return true;
458
459
  trail_lim.push(trail.size());
460
  Lit l = lit_Undef;
461
  for (int i = 0; i < clause.size(); i++)
462
    if (var(clause[i]) != v && value(clause[i]) != l_False)
463
      uncheckedEnqueue(~clause[i]);
464
    else
465
      l = clause[i];
466
467
  if (propagate() != CRef_Undef)
468
  {
469
    cancelUntil(0);
470
    asymm_lits++;
471
    if (!strengthenClause(cr, l)) return false;
472
  }
473
  else
474
    cancelUntil(0);
475
476
  return true;
477
}
478
479
480
bool SimpSolver::asymmVar(Var v)
481
{
482
  Assert(use_simplification);
483
484
  const vec<CRef>& cls = occurs.lookup(v);
485
486
  if (value(v) != l_Undef || cls.size() == 0) return true;
487
488
  for (int i = 0; i < cls.size(); i++)
489
    if (!asymm(v, cls[i])) return false;
490
491
  return backwardSubsumptionCheck();
492
}
493
494
495
2520
static void mkElimClause(vec<uint32_t>& elimclauses, Lit x)
496
{
497
2520
    elimclauses.push(toInt(x));
498
2520
    elimclauses.push(1);
499
2520
}
500
501
6220
static void mkElimClause(vec<uint32_t>& elimclauses, Var v, Clause& clause)
502
{
503
6220
    int first = elimclauses.size();
504
6220
    int v_pos = -1;
505
506
    // Copy clause to elimclauses-vector. Remember position where the
507
    // variable 'v' occurs:
508
29061
    for (int i = 0; i < clause.size(); i++)
509
    {
510
22841
      elimclauses.push(toInt(clause[i]));
511
22841
      if (var(clause[i]) == v) v_pos = i + first;
512
    }
513
6220
    Assert(v_pos != -1);
514
515
    // Swap the first literal with the 'v' literal, so that the literal
516
    // containing 'v' will occur first in the clause:
517
6220
    uint32_t tmp = elimclauses[v_pos];
518
6220
    elimclauses[v_pos] = elimclauses[first];
519
6220
    elimclauses[first] = tmp;
520
521
    // Store the length of the clause last:
522
6220
    elimclauses.push(clause.size());
523
6220
}
524
525
526
527
4028
bool SimpSolver::eliminateVar(Var v)
528
{
529
4028
  Assert(!frozen[v]);
530
4028
  Assert(!isEliminated(v));
531
4028
  Assert(value(v) == l_Undef);
532
533
  // Split the occurrences into positive and negative:
534
  //
535
4028
  const vec<CRef>& cls = occurs.lookup(v);
536
8056
  vec<CRef> pos, neg;
537
39476
  for (int i = 0; i < cls.size(); i++)
538
35448
    (find(ca[cls[i]], mkLit(v)) ? pos : neg).push(cls[i]);
539
540
  // Check whether the increase in number of clauses stays within the allowed
541
  // ('grow'). Moreover, no clause must exceed the limit on the maximal clause
542
  // size (if it is set):
543
  //
544
4028
  int cnt = 0;
545
4028
  int clause_size = 0;
546
547
14005
  for (int i = 0; i < pos.size(); i++)
548
67384
    for (int j = 0; j < neg.size(); j++)
549
114814
      if (merge(ca[pos[i]], ca[neg[j]], v, clause_size)
550
58915
          && (++cnt > cls.size() + grow
551
30414
              || (clause_lim != -1 && clause_size > clause_lim)))
552
1508
        return true;
553
554
  // Delete and store old clauses:
555
2520
  eliminated[v] = true;
556
2520
  setDecisionVar(v, false);
557
2520
  eliminated_vars++;
558
559
2520
  if (pos.size() > neg.size())
560
  {
561
734
    for (int i = 0; i < neg.size(); i++)
562
496
      mkElimClause(elimclauses, v, ca[neg[i]]);
563
238
    mkElimClause(elimclauses, mkLit(v));
564
  }
565
  else
566
  {
567
8006
    for (int i = 0; i < pos.size(); i++)
568
5724
      mkElimClause(elimclauses, v, ca[pos[i]]);
569
2282
    mkElimClause(elimclauses, ~mkLit(v));
570
  }
571
572
2520
    for (int i = 0; i < cls.size(); i++) removeClause(cls[i]);
573
574
    // Produce clauses in cross product:
575
2520
    vec<Lit>& resolvent = add_tmp;
576
8987
    for (int i = 0; i < pos.size(); i++)
577
34526
      for (int j = 0; j < neg.size(); j++) {
578
28059
        ClauseId id = -1;
579
39313
        if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) &&
580
11254
            !addClause_(resolvent, id))
581
          return false;
582
      }
583
584
    // Free occurs list for this variable:
585
2520
    occurs[v].clear(true);
586
587
    // Free watchers lists for this variable, if possible:
588
2520
    if (watches[ mkLit(v)].size() == 0) watches[ mkLit(v)].clear(true);
589
2520
    if (watches[~mkLit(v)].size() == 0) watches[~mkLit(v)].clear(true);
590
591
2520
    return backwardSubsumptionCheck();
592
}
593
594
595
bool SimpSolver::substitute(Var v, Lit x)
596
{
597
  Assert(!frozen[v]);
598
  Assert(!isEliminated(v));
599
  Assert(value(v) == l_Undef);
600
601
  if (!ok) return false;
602
603
  eliminated[v] = true;
604
  setDecisionVar(v, false);
605
  const vec<CRef>& cls = occurs.lookup(v);
606
607
  vec<Lit>& subst_clause = add_tmp;
608
  for (int i = 0; i < cls.size(); i++)
609
  {
610
    Clause& clause = ca[cls[i]];
611
612
    subst_clause.clear();
613
    for (int j = 0; j < clause.size(); j++)
614
    {
615
      Lit p = clause[j];
616
      subst_clause.push(var(p) == v ? x ^ sign(p) : p);
617
    }
618
619
    removeClause(cls[i]);
620
    ClauseId id;
621
    if (!addClause_(subst_clause, id)) return ok = false;
622
  }
623
624
    return true;
625
}
626
627
628
void SimpSolver::extendModel()
629
{
630
    int i, j;
631
    Lit x;
632
633
    for (i = elimclauses.size()-1; i > 0; i -= j){
634
        for (j = elimclauses[i--]; j > 1; j--, i--)
635
            if (modelValue(toLit(elimclauses[i])) != l_False)
636
                goto next;
637
638
        x = toLit(elimclauses[i]);
639
        model[var(x)] = lbool(!sign(x));
640
    next:;
641
    }
642
}
643
644
645
5968
bool SimpSolver::eliminate(bool turn_off_elim)
646
{
647
  //  cvc5::TimerStat::CodeTimer codeTimer(total_eliminate_time);
648
649
5968
  if (!simplify())
650
2
    return false;
651
5966
  else if (!use_simplification)
652
    return true;
653
654
  // Main simplification loop:
655
  //
656
17920
  while (n_touched > 0 || bwdsub_assigns < trail.size() || elim_heap.size() > 0)
657
  {
658
5977
    gatherTouchedClauses();
659
    // printf("  ## (time = %6.2f s) BWD-SUB: queue = %d, trail = %d\n",
660
    // cpuTime(), subsumption_queue.size(), trail.size() - bwdsub_assigns);
661
11956
    if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size())
662
11954
        && !backwardSubsumptionCheck(true))
663
    {
664
      ok = false;
665
      goto cleanup;
666
    }
667
668
    // Empty elim_heap and return immediately on user-interrupt:
669
5977
    if (asynch_interrupt)
670
    {
671
      Assert(bwdsub_assigns == trail.size());
672
      Assert(subsumption_queue.size() == 0);
673
      Assert(n_touched == 0);
674
      elim_heap.clear();
675
      goto cleanup;
676
    }
677
678
    // printf("  ## (time = %6.2f s) ELIM: vars = %d\n", cpuTime(),
679
    // elim_heap.size());
680
1735614
    for (int cnt = 0; !elim_heap.empty(); cnt++)
681
    {
682
1729637
      Var elim = elim_heap.removeMin();
683
684
1729637
      if (asynch_interrupt) break;
685
686
1729637
      if (isEliminated(elim) || value(elim) != l_Undef) continue;
687
688
1723173
      if (verbosity >= 2 && cnt % 100 == 0)
689
        printf("elimination left: %10d\r", elim_heap.size());
690
691
1723173
      if (use_asymm)
692
      {
693
        // Temporarily freeze variable. Otherwise, it would immediately end up
694
        // on the queue again:
695
        bool was_frozen = frozen[elim];
696
        frozen[elim] = true;
697
        if (!asymmVar(elim))
698
        {
699
          ok = false;
700
          goto cleanup;
701
        }
702
        frozen[elim] = was_frozen;
703
      }
704
705
      // At this point, the variable may have been set by assymetric branching,
706
      // so check it again. Also, don't eliminate frozen variables:
707
3452313
      if (use_elim && value(elim) == l_Undef && !frozen[elim]
708
1727201
          && !eliminateVar(elim))
709
      {
710
        ok = false;
711
        goto cleanup;
712
      }
713
714
1723173
      checkGarbage(simp_garbage_frac);
715
    }
716
717
5977
    Assert(subsumption_queue.size() == 0);
718
    }
719
5966
 cleanup:
720
721
    // If no more simplification is needed, free all simplification-related data structures:
722
5966
    if (turn_off_elim){
723
        touched  .clear(true);
724
        occurs   .clear(true);
725
        n_occ    .clear(true);
726
        elim_heap.clear(true);
727
        subsumption_queue.clear(true);
728
729
        use_simplification    = false;
730
        remove_satisfied      = true;
731
        ca.extra_clause_field = false;
732
733
        // Force full cleanup (this is safe and desirable since it only happens once):
734
        rebuildOrderHeap();
735
        garbageCollect();
736
    }else{
737
        // Cheaper cleanup:
738
5966
        cleanUpClauses(); // TODO: can we make 'cleanUpClauses()' not be linear in the problem size somehow?
739
5966
        checkGarbage();
740
    }
741
742
5966
    if (verbosity >= 1 && elimclauses.size() > 0)
743
      printf(
744
          "|  Eliminated clauses:     %10.2f Mb                                "
745
          "      |\n",
746
          double(elimclauses.size() * sizeof(uint32_t)) / (1024 * 1024));
747
748
5966
    return ok;
749
750
751
752
}
753
754
755
6026
void SimpSolver::cleanUpClauses()
756
{
757
6026
    occurs.cleanAll();
758
    int i,j;
759
96014346
    for (i = j = 0; i < clauses.size(); i++)
760
96008320
        if (ca[clauses[i]].mark() == 0)
761
95954974
            clauses[j++] = clauses[i];
762
6026
    clauses.shrink(i - j);
763
6026
}
764
765
766
//=================================================================================================
767
// Garbage Collection methods:
768
769
770
60
void SimpSolver::relocAll(ClauseAllocator& to)
771
{
772
60
    if (!use_simplification) return;
773
774
    // All occurs lists:
775
    //
776
44543
    for (int i = 0; i < nVars(); i++){
777
44483
        vec<CRef>& cs = occurs[i];
778
434754
        for (int j = 0; j < cs.size(); j++)
779
390271
            ca.reloc(cs[j], to);
780
    }
781
782
    // Subsumption queue:
783
    //
784
300
    for (int i = 0; i < subsumption_queue.size(); i++)
785
240
        ca.reloc(subsumption_queue[i], to);
786
787
    // Temporary clause:
788
    //
789
60
    ca.reloc(bwdsub_tmpunit, to);
790
}
791
792
793
60
void SimpSolver::garbageCollect()
794
{
795
    // Initialize the next region to a size corresponding to the estimated utilization degree. This
796
    // is not precise but should avoid some unnecessary reallocations for the new region:
797
120
    ClauseAllocator to(ca.size() - ca.wasted());
798
799
60
    cleanUpClauses();
800
60
    to.extra_clause_field = ca.extra_clause_field; // NOTE: this is important to keep (or lose) the extra fields.
801
60
    relocAll(to);
802
60
    Solver::relocAll(to);
803
60
    if (verbosity >= 2)
804
      printf(
805
          "|  Garbage collection:   %12d bytes => %12d bytes             |\n",
806
          ca.size() * ClauseAllocator::Unit_Size,
807
          to.size() * ClauseAllocator::Unit_Size);
808
60
    to.moveTo(ca);
809
60
}
810
811
}  // namespace BVMinisat
812
1687933
}  // namespace cvc5