LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/prop/minisat/simp - SimpSolver.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 305 405 75.3 %
Date: 2024-11-09 12:39:55 Functions: 20 24 83.3 %
Branches: 271 388 69.8 %

           Branch data     Line data    Source code
       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/minisat/simp/SimpSolver.h"
      22                 :            : 
      23                 :            : #include "base/check.h"
      24                 :            : #include "options/prop_options.h"
      25                 :            : #include "options/smt_options.h"
      26                 :            : #include "proof/clause_id.h"
      27                 :            : #include "prop/minisat/mtl/Sort.h"
      28                 :            : #include "prop/minisat/utils/System.h"
      29                 :            : 
      30                 :            : using namespace cvc5::internal;
      31                 :            : using namespace cvc5::internal::Minisat;
      32                 :            : 
      33                 :            : //=================================================================================================
      34                 :            : // Options:
      35                 :            : 
      36                 :            : 
      37                 :            : static const char* _cat = "SIMP";
      38                 :            : 
      39                 :            : static BoolOption   opt_use_asymm        (_cat, "asymm",        "Shrink clauses by asymmetric branching.", false);
      40                 :            : static BoolOption   opt_use_rcheck       (_cat, "rcheck",       "Check if a clause is already implied. (costly)", false);
      41                 :            : static IntOption    opt_grow             (_cat, "grow",         "Allow a variable elimination step to grow by a number of clauses.", 0);
      42                 :            : 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));
      43                 :            : 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));
      44                 :            : 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));
      45                 :            : 
      46                 :            : 
      47                 :            : //=================================================================================================
      48                 :            : // Constructor/Destructor:
      49                 :            : 
      50                 :      50267 : SimpSolver::SimpSolver(Env& env,
      51                 :            :                        prop::TheoryProxy* proxy,
      52                 :            :                        context::Context* context,
      53                 :            :                        context::UserContext* userContext,
      54                 :            :                        prop::PropPfManager* ppm,
      55                 :      50267 :                        bool enableIncremental)
      56                 :            :     : Solver(env, proxy, context, userContext, ppm, enableIncremental),
      57                 :            :       grow(opt_grow),
      58                 :            :       clause_lim(opt_clause_lim),
      59                 :            :       subsumption_lim(opt_subsumption_lim),
      60                 :            :       simp_garbage_frac(opt_simp_garbage_frac),
      61                 :            :       use_asymm(opt_use_asymm),
      62                 :            :       // make sure this is not enabled if unsat cores or proofs are on
      63                 :      50267 :       use_rcheck(opt_use_rcheck && !options().smt.produceUnsatCores && !ppm),
      64                 :            :       merges(0),
      65                 :            :       asymm_lits(0),
      66                 :            :       eliminated_vars(0),
      67                 :            :       elimorder(1),
      68                 :            :       use_simplification(
      69                 :     100534 :           options().prop.minisatSimpMode != options::MinisatSimpMode::NONE
      70 [ +  - ][ +  + ]:      50267 :           && !enableIncremental && !options().smt.produceUnsatCores && !ppm),
         [ +  + ][ +  - ]
      71                 :          0 :       occurs(ClauseDeleted(ca)),
      72                 :     100534 :       elim_heap(ElimLt(n_occ)),
      73                 :            :       bwdsub_assigns(0),
      74                 :     150801 :       n_touched(0)
      75                 :            : {
      76                 :     100534 :     vec<Lit> dummy(1,lit_Undef);
      77                 :      50267 :     ca.extra_clause_field = true; // NOTE: must happen before allocating the dummy clause below.
      78                 :      50267 :     bwdsub_tmpunit        = ca.alloc(0, dummy);
      79                 :      50267 :     remove_satisfied      = false;
      80                 :            : 
      81                 :            :     // add the initialization for all the internal variables
      82         [ +  + ]:     150801 :     for (int i = frozen.size(); i < vardata.size(); ++ i) {
      83                 :     100534 :       frozen    .push(1);
      84                 :     100534 :       eliminated.push(0);
      85         [ +  + ]:     100534 :       if (use_simplification){
      86                 :      10524 :           n_occ     .push(0);
      87                 :      10524 :           n_occ     .push(0);
      88                 :      10524 :           occurs    .init(i);
      89                 :      10524 :           touched   .push(0);
      90                 :      10524 :           elim_heap .insert(i);
      91                 :            :       }
      92                 :            :     }
      93                 :      50267 : }
      94                 :            : 
      95                 :            : 
      96                 :     100022 : SimpSolver::~SimpSolver()
      97                 :            : {
      98                 :     100022 : }
      99                 :            : 
     100                 :    2212700 : Var SimpSolver::newVar(bool sign, bool dvar, bool isTheoryAtom, bool canErase)
     101                 :            : {
     102                 :    2212700 :   Var v = Solver::newVar(sign, dvar, isTheoryAtom, canErase);
     103                 :            : 
     104         [ +  + ]:    2212700 :   if (use_simplification)
     105                 :            :   {
     106                 :     173616 :     frozen.push((char)(!canErase));
     107                 :     173616 :     eliminated.push((char)false);
     108                 :     173616 :     n_occ.push(0);
     109                 :     173616 :     n_occ.push(0);
     110                 :     173616 :     occurs.init(v);
     111                 :     173616 :     touched.push(0);
     112                 :     173616 :     elim_heap.insert(v);
     113                 :            :   }
     114                 :    2212700 :   return v;
     115                 :            : }
     116                 :            : 
     117                 :      49677 : lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp)
     118                 :            : {
     119         [ -  + ]:      49677 :   if (options().prop.minisatDumpDimacs)
     120                 :            :   {
     121                 :          0 :     toDimacs();
     122                 :          0 :     return l_Undef;
     123                 :            :   }
     124 [ -  + ][ -  + ]:      49677 :     Assert(decisionLevel() == 0);
                 [ -  - ]
     125                 :            : 
     126                 :      49690 :     vec<Var> extra_frozen;
     127                 :      49677 :     lbool    result = l_True;
     128                 :            : 
     129                 :      49677 :     do_simp &= use_simplification;
     130                 :            : 
     131         [ +  + ]:      49677 :     if (do_simp){
     132                 :            :         // Assumptions must be temporarily frozen to run variable elimination:
     133         [ -  + ]:       4406 :         for (int i = 0; i < assumptions.size(); i++){
     134                 :          0 :             Var v = var(assumptions[i]);
     135                 :            : 
     136                 :            :             // If an assumption has been eliminated, remember it.
     137                 :          0 :             Assert(!isEliminated(v));
     138                 :            : 
     139         [ -  - ]:          0 :             if (!frozen[v]){
     140                 :            :                 // Freeze and store.
     141                 :          0 :                 setFrozen(v, true);
     142                 :          0 :                 extra_frozen.push(v);
     143                 :            :             } }
     144                 :            : 
     145                 :       4406 :         result = lbool(eliminate(turn_off_simp));
     146                 :            :     }
     147                 :            : 
     148         [ +  + ]:      49677 :     if (result == l_True)
     149                 :      48572 :         result = Solver::solve_();
     150         [ +  + ]:       1105 :     else if (verbosity >= 1)
     151                 :          1 :         printf("===============================================================================\n");
     152                 :            : 
     153         [ +  + ]:      49664 :     if (result == l_True)
     154                 :      24145 :         extendModel();
     155                 :            : 
     156         [ +  + ]:      49664 :     if (do_simp)
     157                 :            :         // Unfreeze the assumptions that were frozen:
     158         [ -  + ]:       4400 :         for (int i = 0; i < extra_frozen.size(); i++)
     159                 :          0 :             setFrozen(extra_frozen[i], false);
     160                 :            : 
     161                 :      49664 :     return result;
     162                 :            : }
     163                 :            : 
     164                 :            : 
     165                 :            : 
     166                 :    6278210 : bool SimpSolver::addClause_(vec<Lit>& ps, bool removable, ClauseId& id)
     167                 :            : {
     168                 :            : #ifdef CVC5_ASSERTIONS
     169         [ +  + ]:    6278210 :   if (use_simplification)
     170                 :            :   {
     171 [ +  + ][ -  + ]:    2238270 :     for (int i = 0; i < ps.size(); i++) Assert(!isEliminated(var(ps[i])));
         [ -  + ][ -  - ]
     172                 :            :   }
     173                 :            : #endif
     174                 :            : 
     175                 :    6278210 :     int nclauses = clauses_persistent.size();
     176                 :            : 
     177 [ -  + ][ -  - ]:    6278210 :     if (use_rcheck && implied(ps))
                 [ -  + ]
     178                 :          0 :         return true;
     179                 :            : 
     180         [ +  + ]:    6278210 :     if (!Solver::addClause_(ps, removable, id))
     181                 :       8505 :         return false;
     182                 :            : 
     183 [ +  + ][ +  + ]:    6269710 :     if (use_simplification && clauses_persistent.size() == nclauses + 1){
                 [ +  + ]
     184                 :     167948 :         CRef          cr = clauses_persistent.last();
     185                 :     167948 :         const Clause& c  = ca[cr];
     186                 :            : 
     187                 :            :         // NOTE: the clause is added to the queue immediately and then
     188                 :            :         // again during 'gatherTouchedClauses()'. If nothing happens
     189                 :            :         // in between, it will only be checked once. Otherwise, it may
     190                 :            :         // be checked twice unnecessarily. This is an unfortunate
     191                 :            :         // consequence of how backward subsumption is used to mimic
     192                 :            :         // forward subsumption.
     193                 :     167948 :         subsumption_queue.insert(cr);
     194         [ +  + ]:     645534 :         for (int i = 0; i < c.size(); i++){
     195                 :     477586 :             occurs[var(c[i])].push(cr);
     196                 :     477586 :             n_occ[toInt(c[i])]++;
     197                 :     477586 :             touched[var(c[i])] = 1;
     198                 :     477586 :             n_touched++;
     199         [ +  + ]:     477586 :             if (elim_heap.inHeap(var(c[i])))
     200                 :     459884 :                 elim_heap.increase(var(c[i]));
     201                 :            :         }
     202                 :            :     }
     203                 :            : 
     204                 :    6269710 :     return true;
     205                 :            : }
     206                 :            : 
     207                 :            : 
     208                 :      58909 : void SimpSolver::removeClause(CRef cr)
     209                 :            : {
     210                 :      58909 :     const Clause& c = ca[cr];
     211         [ +  - ]:      58909 :     Trace("minisat") << "SimpSolver::removeClause(" << c << ")" << std::endl;
     212                 :            : 
     213         [ +  - ]:      58909 :     if (use_simplification)
     214         [ +  + ]:     220639 :         for (int i = 0; i < c.size(); i++){
     215                 :     161730 :             n_occ[toInt(c[i])]--;
     216                 :     161730 :             updateElimHeap(var(c[i]));
     217                 :     161730 :             occurs.smudge(var(c[i]));
     218                 :            :         }
     219                 :            : 
     220                 :      58909 :     Solver::removeClause(cr);
     221                 :      58909 : }
     222                 :            : 
     223                 :            : 
     224                 :      18672 : bool SimpSolver::strengthenClause(CRef cr, Lit l)
     225                 :            : {
     226                 :      18672 :     Clause& c = ca[cr];
     227 [ -  + ][ -  + ]:      18672 :     Assert(decisionLevel() == 0);
                 [ -  - ]
     228 [ -  + ][ -  + ]:      18672 :     Assert(use_simplification);
                 [ -  - ]
     229                 :            : 
     230                 :            :     // FIX: this is too inefficient but would be nice to have (properly implemented)
     231                 :            :     // if (!find(subsumption_queue, &c))
     232                 :      18672 :     subsumption_queue.insert(cr);
     233                 :            : 
     234         [ +  + ]:      18672 :     if (c.size() == 2){
     235                 :       3047 :         removeClause(cr);
     236                 :       3047 :         c.strengthen(l);
     237                 :            :     }else{
     238                 :      15625 :         detachClause(cr, true);
     239                 :      15625 :         c.strengthen(l);
     240                 :      15625 :         attachClause(cr);
     241                 :      15625 :         remove(occurs[var(l)], cr);
     242                 :      15625 :         n_occ[toInt(l)]--;
     243                 :      15625 :         updateElimHeap(var(l));
     244                 :            :     }
     245                 :            : 
     246 [ +  + ][ +  - ]:      18672 :     return c.size() == 1 ? enqueue(c[0]) && propagate(CHECK_WITHOUT_THEORY) == CRef_Undef : true;
                 [ +  + ]
     247                 :            : }
     248                 :            : 
     249                 :            : 
     250                 :            : // Returns FALSE if clause is always satisfied ('out_clause' should not be used).
     251                 :      50010 : bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause)
     252                 :            : {
     253                 :      50010 :     merges++;
     254                 :      50010 :     out_clause.clear();
     255                 :            : 
     256                 :      50010 :     bool  ps_smallest = _ps.size() < _qs.size();
     257         [ +  + ]:      50010 :     const Clause& ps  =  ps_smallest ? _qs : _ps;
     258         [ +  + ]:      50010 :     const Clause& qs  =  ps_smallest ? _ps : _qs;
     259                 :            : 
     260         [ +  + ]:     114517 :     for (int i = 0; i < qs.size(); i++)
     261                 :            :     {
     262         [ +  + ]:      93032 :       if (var(qs[i]) != v)
     263                 :            :       {
     264         [ +  + ]:     250610 :         for (int j = 0; j < ps.size(); j++)
     265                 :            :         {
     266         [ +  + ]:     220031 :           if (var(ps[j]) == var(qs[i]))
     267                 :            :           {
     268         [ +  + ]:      33510 :             if (ps[j] == ~qs[i])
     269                 :      28525 :               return false;
     270                 :            :             else
     271                 :       4985 :               goto next;
     272                 :            :           }
     273                 :            :         }
     274                 :      30579 :         out_clause.push(qs[i]);
     275                 :            :       }
     276                 :      64507 :     next:;
     277                 :            :     }
     278                 :            : 
     279         [ +  + ]:     104834 :     for (int i = 0; i < ps.size(); i++)
     280         [ +  + ]:      83349 :         if (var(ps[i]) != v)
     281                 :      61864 :             out_clause.push(ps[i]);
     282                 :            : 
     283                 :      21485 :     return true;
     284                 :            : }
     285                 :            : 
     286                 :            : 
     287                 :            : // Returns FALSE if clause is always satisfied.
     288                 :     285027 : bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, int& size)
     289                 :            : {
     290                 :     285027 :     merges++;
     291                 :            : 
     292                 :     285027 :     bool  ps_smallest = _ps.size() < _qs.size();
     293         [ +  + ]:     285027 :     const Clause& ps  =  ps_smallest ? _qs : _ps;
     294         [ +  + ]:     285027 :     const Clause& qs  =  ps_smallest ? _ps : _qs;
     295                 :     285027 :     const Lit*  __ps  = (const Lit*)ps;
     296                 :     285027 :     const Lit*  __qs  = (const Lit*)qs;
     297                 :            : 
     298                 :     285027 :     size = ps.size()-1;
     299                 :            : 
     300         [ +  + ]:     780725 :     for (int i = 0; i < qs.size(); i++)
     301                 :            :     {
     302         [ +  + ]:     610409 :       if (var(__qs[i]) != v)
     303                 :            :       {
     304         [ +  + ]:    2252650 :         for (int j = 0; j < ps.size(); j++)
     305                 :            :         {
     306         [ +  + ]:    1986400 :           if (var(__ps[j]) == var(__qs[i]))
     307                 :            :           {
     308         [ +  + ]:     142886 :             if (__ps[j] == ~__qs[i])
     309                 :     114711 :               return false;
     310                 :            :             else
     311                 :      28175 :               goto next;
     312                 :            :           }
     313                 :            :         }
     314                 :     266254 :         size++;
     315                 :            :       }
     316                 :     495698 :     next:;
     317                 :            :     }
     318                 :            : 
     319                 :     170316 :     return true;
     320                 :            : }
     321                 :            : 
     322                 :            : 
     323                 :       3386 : void SimpSolver::gatherTouchedClauses()
     324                 :            : {
     325         [ +  + ]:       3386 :     if (n_touched == 0) return;
     326                 :            : 
     327                 :            :     int i,j;
     328         [ +  + ]:     148483 :     for (i = j = 0; i < subsumption_queue.size(); i++)
     329         [ +  - ]:     146248 :         if (ca[subsumption_queue[i]].mark() == 0)
     330                 :     146248 :             ca[subsumption_queue[i]].mark(2);
     331                 :            : 
     332         [ +  + ]:     129286 :     for (i = 0; i < touched.size(); i++)
     333         [ +  + ]:     127051 :         if (touched[i]){
     334                 :      73054 :             const vec<CRef>& cs = occurs.lookup(i);
     335         [ +  + ]:     565736 :             for (j = 0; j < cs.size(); j++)
     336         [ +  + ]:     492682 :                 if (ca[cs[j]].mark() == 0){
     337                 :      37952 :                     subsumption_queue.insert(cs[j]);
     338                 :      37952 :                     ca[cs[j]].mark(2);
     339                 :            :                 }
     340                 :      73054 :             touched[i] = 0;
     341                 :            :         }
     342                 :            : 
     343         [ +  + ]:     186435 :     for (i = 0; i < subsumption_queue.size(); i++)
     344         [ +  - ]:     184200 :         if (ca[subsumption_queue[i]].mark() == 2)
     345                 :     184200 :             ca[subsumption_queue[i]].mark(0);
     346                 :            : 
     347                 :       2235 :     n_touched = 0;
     348                 :            : }
     349                 :            : 
     350                 :            : 
     351                 :          0 : bool SimpSolver::implied(const vec<Lit>& c)
     352                 :            : {
     353                 :          0 :   Assert(decisionLevel() == 0);
     354                 :            : 
     355                 :          0 :   trail_lim.push(trail.size());
     356         [ -  - ]:          0 :   for (int i = 0; i < c.size(); i++)
     357                 :            :   {
     358         [ -  - ]:          0 :     if (value(c[i]) == l_True)
     359                 :            :     {
     360                 :          0 :       cancelUntil(0);
     361                 :          0 :       return false;
     362                 :            :     }
     363         [ -  - ]:          0 :     else if (value(c[i]) != l_False)
     364                 :            :     {
     365                 :          0 :       Assert(value(c[i]) == l_Undef);
     366                 :          0 :       uncheckedEnqueue(~c[i]);
     367                 :            :     }
     368                 :            :   }
     369                 :            : 
     370                 :          0 :   bool result = propagate(CHECK_WITHOUT_THEORY) != CRef_Undef;
     371                 :          0 :   cancelUntil(0);
     372                 :          0 :   return result;
     373                 :            : }
     374                 :            : 
     375                 :            : 
     376                 :            : // Backward subsumption + backward subsumption resolution
     377                 :       9809 : bool SimpSolver::backwardSubsumptionCheck(bool verbose)
     378                 :            : {
     379                 :       9809 :     int cnt = 0;
     380                 :       9809 :     int subsumed = 0;
     381                 :       9809 :     int deleted_literals = 0;
     382 [ -  + ][ -  + ]:       9809 :     Assert(decisionLevel() == 0);
                 [ -  - ]
     383                 :            : 
     384 [ +  + ][ +  + ]:     265389 :     while (subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()){
                 [ +  + ]
     385                 :            : 
     386                 :            :         // Empty subsumption queue and return immediately on user-interrupt:
     387         [ -  + ]:     255582 :         if (asynch_interrupt){
     388                 :          0 :             subsumption_queue.clear();
     389                 :          0 :             bwdsub_assigns = trail.size();
     390                 :          0 :             break; }
     391                 :            : 
     392                 :            :         // Check top-level assignments by creating a dummy clause and placing it in the queue:
     393 [ +  + ][ +  - ]:     255582 :         if (subsumption_queue.size() == 0 && bwdsub_assigns < trail.size()){
                 [ +  + ]
     394                 :      31233 :             Lit l = trail[bwdsub_assigns++];
     395                 :      31233 :             ca[bwdsub_tmpunit][0] = l;
     396                 :      31233 :             ca[bwdsub_tmpunit].calcAbstraction();
     397                 :      31233 :             subsumption_queue.insert(bwdsub_tmpunit); }
     398                 :            : 
     399                 :     255582 :         CRef    cr = subsumption_queue.peek(); subsumption_queue.pop();
     400                 :     255582 :         Clause& c  = ca[cr];
     401                 :            : 
     402         [ +  + ]:     255582 :         if (c.mark()) continue;
     403                 :            : 
     404 [ +  + ][ -  + ]:     250136 :         if (verbose && verbosity >= 2 && cnt++ % 1000 == 0)
         [ -  - ][ -  + ]
     405                 :          0 :             printf("subsumption left: %10d (%10d subsumed, %10d deleted literals)\r", subsumption_queue.size(), subsumed, deleted_literals);
     406                 :            : 
     407 [ +  + ][ -  + ]:     250136 :         Assert(c.size() > 1
         [ -  + ][ -  - ]
     408                 :            :                || value(c[0]) == l_True);  // Unit-clauses should have been
     409                 :            :                                            // propagated before this point.
     410                 :            : 
     411                 :            :         // Find best variable to scan:
     412                 :     250136 :         Var best = var(c[0]);
     413         [ +  + ]:    1705660 :         for (int i = 1; i < c.size(); i++)
     414         [ +  + ]:    1455520 :             if (occurs[var(c[i])].size() < occurs[best].size())
     415                 :     167474 :                 best = var(c[i]);
     416                 :            : 
     417                 :            :         // Search all candidates:
     418                 :     250136 :         vec<CRef>& _cs = occurs.lookup(best);
     419                 :     250136 :         CRef*       cs = (CRef*)_cs;
     420                 :            : 
     421         [ +  + ]:    2402620 :         for (int j = 0; j < _cs.size(); j++)
     422         [ -  + ]:    2152480 :             if (c.mark())
     423                 :          0 :                 break;
     424 [ +  + ][ +  + ]:    2152480 :             else if (!ca[cs[j]].mark() &&  cs[j] != cr && (subsumption_lim == -1 || ca[cs[j]].size() < subsumption_lim)){
         [ +  - ][ +  - ]
                 [ +  + ]
     425                 :    1930730 :                 Lit l = c.subsumes(ca[cs[j]]);
     426                 :            : 
     427         [ +  + ]:    1930730 :                 if (l == lit_Undef)
     428                 :      21249 :                     subsumed++, removeClause(cs[j]);
     429         [ +  + ]:    1909480 :                 else if (l != lit_Error){
     430                 :      18672 :                     deleted_literals++;
     431                 :            : 
     432         [ +  + ]:      18672 :                     if (!strengthenClause(cs[j], ~l))
     433                 :          2 :                         return false;
     434                 :            : 
     435                 :            :                     // Did current candidate get deleted from cs? Then check candidate at index j again:
     436         [ +  + ]:      18670 :                     if (var(l) == best)
     437                 :      15497 :                         j--;
     438                 :            :                 }
     439                 :            :             }
     440                 :            :     }
     441                 :            : 
     442                 :       9807 :     return true;
     443                 :            : }
     444                 :            : 
     445                 :            : 
     446                 :          0 : bool SimpSolver::asymm(Var v, CRef cr)
     447                 :            : {
     448                 :          0 :     Clause& c = ca[cr];
     449                 :          0 :     Assert(decisionLevel() == 0);
     450                 :            : 
     451                 :          0 :     if (c.mark() || satisfied(c)) return true;
     452                 :            : 
     453                 :          0 :     trail_lim.push(trail.size());
     454                 :          0 :     Lit l = lit_Undef;
     455         [ -  - ]:          0 :     for (int i = 0; i < c.size(); i++)
     456                 :          0 :         if (var(c[i]) != v && value(c[i]) != l_False)
     457                 :          0 :             uncheckedEnqueue(~c[i]);
     458                 :            :         else
     459                 :          0 :             l = c[i];
     460                 :            : 
     461         [ -  - ]:          0 :     if (propagate(CHECK_WITHOUT_THEORY) != CRef_Undef){
     462                 :          0 :         cancelUntil(0);
     463                 :          0 :         asymm_lits++;
     464         [ -  - ]:          0 :         if (!strengthenClause(cr, l))
     465                 :          0 :             return false;
     466                 :            :     }else
     467                 :          0 :         cancelUntil(0);
     468                 :            : 
     469                 :          0 :     return true;
     470                 :            : }
     471                 :            : 
     472                 :            : 
     473                 :          0 : bool SimpSolver::asymmVar(Var v)
     474                 :            : {
     475                 :          0 :   Assert(use_simplification);
     476                 :            : 
     477                 :          0 :   const vec<CRef>& cls = occurs.lookup(v);
     478                 :            : 
     479                 :          0 :   if (value(v) != l_Undef || cls.size() == 0) return true;
     480                 :            : 
     481         [ -  - ]:          0 :   for (int i = 0; i < cls.size(); i++)
     482         [ -  - ]:          0 :     if (!asymm(v, cls[i])) return false;
     483                 :            : 
     484                 :          0 :   return backwardSubsumptionCheck();
     485                 :            : }
     486                 :            : 
     487                 :            : 
     488                 :       6425 : static void mkElimClause(vec<uint32_t>& elimclauses, Lit x)
     489                 :            : {
     490                 :       6425 :     elimclauses.push(toInt(x));
     491                 :       6425 :     elimclauses.push(1);
     492                 :       6425 : }
     493                 :            : 
     494                 :            : 
     495                 :      13182 : static void mkElimClause(vec<uint32_t>& elimclauses, Var v, Clause& c)
     496                 :            : {
     497                 :      13182 :     int first = elimclauses.size();
     498                 :      13182 :     int v_pos = -1;
     499                 :            : 
     500                 :            :     // Copy clause to elimclauses-vector. Remember position where the
     501                 :            :     // variable 'v' occurs:
     502         [ +  + ]:      58292 :     for (int i = 0; i < c.size(); i++){
     503                 :      45110 :         elimclauses.push(toInt(c[i]));
     504         [ +  + ]:      45110 :         if (var(c[i]) == v)
     505                 :      13182 :             v_pos = i + first;
     506                 :            :     }
     507 [ -  + ][ -  + ]:      13182 :     Assert(v_pos != -1);
                 [ -  - ]
     508                 :            : 
     509                 :            :     // Swap the first literal with the 'v' literal, so that the literal
     510                 :            :     // containing 'v' will occur first in the clause:
     511                 :      13182 :     uint32_t tmp = elimclauses[v_pos];
     512                 :      13182 :     elimclauses[v_pos] = elimclauses[first];
     513                 :      13182 :     elimclauses[first] = tmp;
     514                 :            : 
     515                 :            :     // Store the length of the clause last:
     516                 :      13182 :     elimclauses.push(c.size());
     517                 :      13182 : }
     518                 :            : 
     519                 :            : 
     520                 :            : 
     521                 :      16044 : bool SimpSolver::eliminateVar(Var v)
     522                 :            : {
     523 [ -  + ][ -  + ]:      16044 :   Assert(!frozen[v]);
                 [ -  - ]
     524 [ -  + ][ -  + ]:      16044 :   Assert(!isEliminated(v));
                 [ -  - ]
     525 [ -  + ][ -  + ]:      16044 :   Assert(value(v) == l_Undef);
                 [ -  - ]
     526                 :            : 
     527                 :            :   // Split the occurrences into positive and negative:
     528                 :            :   //
     529                 :      16044 :   const vec<CRef>& cls = occurs.lookup(v);
     530                 :      32088 :   vec<CRef> pos, neg;
     531         [ +  + ]:     212622 :   for (int i = 0; i < cls.size(); i++)
     532         [ +  + ]:     196578 :     (find(ca[cls[i]], mkLit(v)) ? pos : neg).push(cls[i]);
     533                 :            : 
     534                 :            :   // Check whether the increase in number of clauses stays within the allowed
     535                 :            :   // ('grow'). Moreover, no clause must exceed the limit on the maximal clause
     536                 :            :   // size (if it is set):
     537                 :            :   //
     538                 :      16044 :   int cnt = 0;
     539                 :      16044 :   int clause_size = 0;
     540                 :            : 
     541         [ +  + ]:      57575 :   for (int i = 0; i < pos.size(); i++)
     542         [ +  + ]:     326558 :     for (int j = 0; j < neg.size(); j++)
     543                 :     285027 :       if (merge(ca[pos[i]], ca[neg[j]], v, clause_size)
     544 [ +  + ][ +  + ]:     447491 :           && (++cnt > cls.size() + grow
                 [ +  + ]
     545 [ +  - ][ +  + ]:     162464 :               || (clause_lim != -1 && clause_size > clause_lim)))
     546                 :       9619 :         return true;
     547                 :            : 
     548                 :            :   // Delete and store old clauses:
     549                 :       6425 :   eliminated[v] = true;
     550                 :       6425 :   setDecisionVar(v, false);
     551                 :       6425 :   eliminated_vars++;
     552                 :            : 
     553         [ +  + ]:       6425 :   if (pos.size() > neg.size())
     554                 :            :   {
     555         [ +  + ]:       4555 :     for (int i = 0; i < neg.size(); i++)
     556                 :       2890 :       mkElimClause(elimclauses, v, ca[neg[i]]);
     557                 :       1665 :     mkElimClause(elimclauses, mkLit(v));
     558                 :            :   }
     559                 :            :   else
     560                 :            :   {
     561         [ +  + ]:      15052 :     for (int i = 0; i < pos.size(); i++)
     562                 :      10292 :       mkElimClause(elimclauses, v, ca[pos[i]]);
     563                 :       4760 :     mkElimClause(elimclauses, ~mkLit(v));
     564                 :            :   }
     565                 :            : 
     566         [ +  + ]:      41038 :     for (int i = 0; i < cls.size(); i++) removeClause(cls[i]);
     567                 :            : 
     568                 :       6425 :     ClauseId id = ClauseIdUndef;
     569                 :            :     // Produce clauses in cross product:
     570                 :       6425 :     vec<Lit>& resolvent = add_tmp;
     571         [ +  + ]:      22811 :     for (int i = 0; i < pos.size(); i++)
     572         [ +  + ]:      66396 :         for (int j = 0; j < neg.size(); j++) {
     573 [ -  + ][ -  - ]:      50010 :             bool removable = ca[pos[i]].removable() && ca[pos[neg[j]]].removable();
     574 [ +  + ][ -  + ]:      71495 :             if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) &&
     575         [ -  + ]:      21485 :                 !addClause_(resolvent, removable, id)) {
     576                 :          0 :                 return false;
     577                 :            :             }
     578                 :            :         }
     579                 :            : 
     580                 :            :     // Free occurs list for this variable:
     581                 :       6425 :     occurs[v].clear(true);
     582                 :            : 
     583                 :            :     // Free watchers lists for this variable, if possible:
     584         [ +  + ]:       6425 :     if (watches[ mkLit(v)].size() == 0) watches[ mkLit(v)].clear(true);
     585         [ +  + ]:       6425 :     if (watches[~mkLit(v)].size() == 0) watches[~mkLit(v)].clear(true);
     586                 :            : 
     587                 :       6425 :     return backwardSubsumptionCheck();
     588                 :            : }
     589                 :            : 
     590                 :            : 
     591                 :          0 : bool SimpSolver::substitute(Var v, Lit x)
     592                 :            : {
     593                 :          0 :   Assert(!frozen[v]);
     594                 :          0 :   Assert(!isEliminated(v));
     595                 :          0 :   Assert(value(v) == l_Undef);
     596                 :            : 
     597         [ -  - ]:          0 :   if (!ok) return false;
     598                 :            : 
     599                 :          0 :   eliminated[v] = true;
     600                 :          0 :   setDecisionVar(v, false);
     601                 :          0 :   const vec<CRef>& cls = occurs.lookup(v);
     602                 :            : 
     603                 :          0 :   vec<Lit>& subst_clause = add_tmp;
     604         [ -  - ]:          0 :   for (int i = 0; i < cls.size(); i++)
     605                 :            :   {
     606                 :          0 :     Clause& c = ca[cls[i]];
     607                 :            : 
     608                 :          0 :     subst_clause.clear();
     609         [ -  - ]:          0 :     for (int j = 0; j < c.size(); j++)
     610                 :            :     {
     611                 :          0 :       Lit p = c[j];
     612         [ -  - ]:          0 :       subst_clause.push(var(p) == v ? x ^ sign(p) : p);
     613                 :            :     }
     614                 :            : 
     615                 :          0 :     removeClause(cls[i]);
     616                 :          0 :     ClauseId id = ClauseIdUndef;
     617         [ -  - ]:          0 :     if (!addClause_(subst_clause, c.removable(), id))
     618                 :            :     {
     619                 :          0 :       return ok = false;
     620                 :            :     }
     621                 :            :   }
     622                 :            : 
     623                 :          0 :     return true;
     624                 :            : }
     625                 :            : 
     626                 :            : 
     627                 :      24145 : void SimpSolver::extendModel()
     628                 :            : {
     629                 :            :     int i, j;
     630                 :            :     Lit x;
     631                 :            : 
     632         [ +  + ]:      33507 :     for (i = elimclauses.size()-1; i > 0; i -= j){
     633         [ +  + ]:      14156 :         for (j = elimclauses[i--]; j > 1; j--, i--)
     634         [ +  + ]:       9247 :             if (modelValue(toLit(elimclauses[i])) != l_False)
     635                 :       4453 :                 goto next;
     636                 :            : 
     637                 :       4909 :         x = toLit(elimclauses[i]);
     638                 :       4909 :         model[var(x)] = lbool(!sign(x));
     639                 :       9362 :     next:;
     640                 :            :     }
     641                 :      24145 : }
     642                 :            : 
     643                 :            : 
     644                 :       4406 : bool SimpSolver::eliminate(bool turn_off_elim)
     645                 :            : {
     646         [ +  + ]:       4406 :     if (!simplify())
     647                 :       1103 :         return false;
     648         [ -  + ]:       3303 :     else if (!use_simplification)
     649                 :          0 :         return true;
     650                 :            : 
     651                 :            :     // Main simplification loop:
     652                 :            :     //
     653 [ +  + ][ +  + ]:       6687 :     while (n_touched > 0 || bwdsub_assigns < trail.size() || elim_heap.size() > 0){
         [ -  + ][ +  + ]
     654                 :            : 
     655                 :       3386 :         gatherTouchedClauses();
     656                 :            :         // printf("  ## (time = %6.2f s) BWD-SUB: queue = %d, trail = %d\n", cpuTime(), subsumption_queue.size(), trail.size() - bwdsub_assigns);
     657         [ +  + ]:       4539 :         if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size())
     658 [ +  + ][ +  + ]:       4539 :             && !backwardSubsumptionCheck(true))
                 [ +  + ]
     659                 :            :         {
     660                 :          1 :           ok = false;
     661                 :          1 :           goto cleanup;
     662                 :            :         }
     663                 :            : 
     664                 :            :         // Empty elim_heap and return immediately on user-interrupt:
     665         [ -  + ]:       3385 :         if (asynch_interrupt){
     666                 :          0 :           Assert(bwdsub_assigns == trail.size());
     667                 :          0 :           Assert(subsumption_queue.size() == 0);
     668                 :          0 :           Assert(n_touched == 0);
     669                 :          0 :           elim_heap.clear();
     670                 :          0 :           goto cleanup;
     671                 :            :         }
     672                 :            : 
     673                 :            :         // printf("  ## (time = %6.2f s) ELIM: vars = %d\n", cpuTime(), elim_heap.size());
     674         [ +  + ]:      92795 :         for (int cnt = 0; !elim_heap.empty(); cnt++){
     675                 :      89411 :             Var elim = elim_heap.removeMin();
     676                 :            : 
     677         [ -  + ]:      89411 :             if (asynch_interrupt) break;
     678                 :            : 
     679 [ +  - ][ +  + ]:      89411 :             if (isEliminated(elim) || value(elim) != l_Undef) continue;
                 [ +  + ]
     680                 :            : 
     681 [ -  + ][ -  - ]:      58243 :             if (verbosity >= 2 && cnt % 100 == 0)
     682                 :          0 :                 printf("elimination left: %10d\r", elim_heap.size());
     683                 :            : 
     684         [ -  + ]:      58243 :             if (use_asymm){
     685                 :            :                 // Temporarily freeze variable. Otherwise, it would immediately end up on the queue again:
     686                 :          0 :                 bool was_frozen = frozen[elim];
     687                 :          0 :                 frozen[elim] = true;
     688         [ -  - ]:          0 :                 if (!asymmVar(elim)){
     689                 :          0 :                     ok = false; goto cleanup; }
     690                 :          0 :                 frozen[elim] = was_frozen; }
     691                 :            : 
     692                 :            :             // At this point, the variable may have been set by assymetric branching, so check it
     693                 :            :             // again. Also, don't eliminate frozen variables:
     694                 :      58243 :             if (options().prop.minisatSimpMode
     695                 :            :                     != options::MinisatSimpMode::CLAUSE_ELIM
     696 [ +  - ][ +  + ]:      29998 :                 && value(elim) == l_Undef && !frozen[elim]
     697 [ +  + ][ +  + ]:      88241 :                 && !eliminateVar(elim))
                 [ +  + ]
     698                 :            :             {
     699                 :          1 :               ok = false;
     700                 :          1 :               goto cleanup;
     701                 :            :             }
     702                 :            : 
     703                 :      58242 :             checkGarbage(simp_garbage_frac);
     704                 :            :         }
     705                 :            : 
     706 [ -  + ][ -  + ]:       3384 :         Assert(subsumption_queue.size() == 0);
                 [ -  - ]
     707                 :            :     }
     708                 :       3301 :  cleanup:
     709                 :            : 
     710                 :            :     // If no more simplification is needed, free all simplification-related data structures:
     711         [ -  + ]:       3303 :     if (turn_off_elim){
     712                 :          0 :         touched  .clear(true);
     713                 :          0 :         occurs   .clear(true);
     714                 :          0 :         n_occ    .clear(true);
     715                 :          0 :         elim_heap.clear(true);
     716                 :          0 :         subsumption_queue.clear(true);
     717                 :            : 
     718                 :          0 :         use_simplification    = false;
     719                 :          0 :         remove_satisfied      = true;
     720                 :          0 :         ca.extra_clause_field = false;
     721                 :            : 
     722                 :            :         // Force full cleanup (this is safe and desirable since it only happens once):
     723                 :          0 :         rebuildOrderHeap();
     724                 :          0 :         garbageCollect();
     725                 :            :     }else{
     726                 :            :         // Cheaper cleanup:
     727                 :       3303 :         cleanUpClauses(); // TODO: can we make 'cleanUpClauses()' not be linear in the problem size somehow?
     728                 :       3303 :         checkGarbage();
     729                 :            :     }
     730                 :            : 
     731 [ +  + ][ -  + ]:       3303 :     if (verbosity >= 1 && elimclauses.size() > 0)
                 [ -  + ]
     732                 :          0 :       printf(
     733                 :            :           "|  Eliminated clauses:     %10.2f Mb                                "
     734                 :            :           "      |\n",
     735                 :          0 :           double(elimclauses.size() * sizeof(uint32_t)) / (1024 * 1024));
     736                 :            : 
     737                 :       3303 :     return ok;
     738                 :            : }
     739                 :            : 
     740                 :            : 
     741                 :       6591 : void SimpSolver::cleanUpClauses()
     742                 :            : {
     743                 :       6591 :     occurs.cleanAll();
     744                 :            :     int i,j;
     745         [ +  + ]:     885953 :     for (i = j = 0; i < clauses_persistent.size(); i++)
     746         [ +  + ]:     879362 :         if (ca[clauses_persistent[i]].mark() == 0)
     747                 :     820453 :             clauses_persistent[j++] = clauses_persistent[i];
     748                 :       6591 :     clauses_persistent.shrink(i - j);
     749                 :       6591 : }
     750                 :            : 
     751                 :            : //=================================================================================================
     752                 :            : // Garbage Collection methods:
     753                 :            : 
     754                 :            : 
     755                 :       3288 : void SimpSolver::relocAll(ClauseAllocator& to)
     756                 :            : {
     757         [ +  + ]:       3288 :     if (!use_simplification) return;
     758                 :            : 
     759                 :            :     // All occurs lists:
     760                 :            :     //
     761         [ +  + ]:     295148 :     for (int i = 0; i < nVars(); i++){
     762                 :     293839 :         vec<CRef>& cs = occurs[i];
     763         [ +  + ]:     690051 :         for (int j = 0; j < cs.size(); j++)
     764                 :     396212 :             ca.reloc(cs[j], to);
     765                 :            :     }
     766                 :            : 
     767                 :            :     // Subsumption queue:
     768                 :            :     //
     769         [ +  + ]:       1317 :     for (int i = 0; i < subsumption_queue.size(); i++)
     770                 :          8 :         ca.reloc(subsumption_queue[i], to);
     771                 :            :     // TODO reloc now takes the proof form the core solver
     772                 :            :     // Temporary clause:
     773                 :            :     //
     774                 :       1309 :     ca.reloc(bwdsub_tmpunit, to);
     775                 :            :     // TODO reloc now takes the proof form the core solver
     776                 :            : }
     777                 :            : 
     778                 :            : 
     779                 :       3288 : void SimpSolver::garbageCollect()
     780                 :            : {
     781                 :            :     // Initialize the next region to a size corresponding to the estimated utilization degree. This
     782                 :            :     // is not precise but should avoid some unnecessary reallocations for the new region:
     783                 :       6576 :     ClauseAllocator to(ca.size() - ca.wasted());
     784                 :            : 
     785                 :       3288 :     cleanUpClauses();
     786                 :       3288 :     to.extra_clause_field = ca.extra_clause_field; // NOTE: this is important to keep (or lose) the extra fields.
     787                 :       3288 :     relocAll(to);
     788                 :       3288 :     Solver::relocAll(to);
     789         [ -  + ]:       3288 :     if (verbosity >= 2)
     790                 :          0 :       printf(
     791                 :            :           "|  Garbage collection:   %12d bytes => %12d bytes             |\n",
     792                 :          0 :           ca.size() * ClauseAllocator::Unit_Size,
     793                 :          0 :           to.size() * ClauseAllocator::Unit_Size);
     794                 :       3288 :     to.moveTo(ca);
     795                 :            :     // TODO: proof.finalizeUpdateId();
     796                 :       3288 : }

Generated by: LCOV version 1.14