LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/arith/nl - pow2_solver.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 88 92 95.7 %
Date: 2024-12-30 14:24:00 Functions: 8 9 88.9 %
Branches: 29 46 63.0 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Yoni Zohar, Aina Niemetz, Andrew Reynolds
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2024 by the authors listed in the file AUTHORS
       8                 :            :  * in the top-level source directory and their institutional affiliations.
       9                 :            :  * All rights reserved.  See the file COPYING in the top-level source
      10                 :            :  * directory for licensing information.
      11                 :            :  * ****************************************************************************
      12                 :            :  *
      13                 :            :  * Implementation of pow2 solver.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "theory/arith/nl/pow2_solver.h"
      17                 :            : 
      18                 :            : #include "options/arith_options.h"
      19                 :            : #include "options/smt_options.h"
      20                 :            : #include "preprocessing/passes/bv_to_int.h"
      21                 :            : #include "theory/arith/arith_msum.h"
      22                 :            : #include "theory/arith/arith_utilities.h"
      23                 :            : #include "theory/arith/inference_manager.h"
      24                 :            : #include "theory/arith/nl/nl_model.h"
      25                 :            : #include "theory/rewriter.h"
      26                 :            : #include "util/bitvector.h"
      27                 :            : 
      28                 :            : using namespace cvc5::internal::kind;
      29                 :            : 
      30                 :            : namespace cvc5::internal {
      31                 :            : namespace theory {
      32                 :            : namespace arith {
      33                 :            : namespace nl {
      34                 :            : 
      35                 :      32376 : Pow2Solver::Pow2Solver(Env& env,
      36                 :            :                        InferenceManager& im,
      37                 :      32376 :                        NlModel& model)
      38                 :      32376 :     : EnvObj(env), d_im(im), d_model(model), d_initRefine(userContext())
      39                 :            : {
      40                 :      32376 :   NodeManager* nm = nodeManager();
      41                 :      32376 :   d_false = nm->mkConst(false);
      42                 :      32376 :   d_true = nm->mkConst(true);
      43                 :      32376 :   d_zero = nm->mkConstInt(Rational(0));
      44                 :      32376 :   d_one = nm->mkConstInt(Rational(1));
      45                 :      32376 :   d_two = nm->mkConstInt(Rational(2));
      46                 :      32376 : }
      47                 :            : 
      48                 :      32167 : Pow2Solver::~Pow2Solver() {}
      49                 :            : 
      50                 :       9256 : void Pow2Solver::initLastCall(const std::vector<Node>& assertions,
      51                 :            :                               const std::vector<Node>& false_asserts,
      52                 :            :                               const std::vector<Node>& xts)
      53                 :            : {
      54                 :       9256 :   d_pow2s.clear();
      55         [ +  - ]:       9256 :   Trace("pow2-mv") << "POW2 terms : " << std::endl;
      56         [ +  + ]:      50364 :   for (const Node& a : xts)
      57                 :            :   {
      58                 :      41108 :     Kind ak = a.getKind();
      59         [ +  + ]:      41108 :     if (ak != Kind::POW2)
      60                 :            :     {
      61                 :            :       // don't care about other terms
      62                 :      40136 :       continue;
      63                 :            :     }
      64                 :        972 :     d_pow2s.push_back(a);
      65                 :            :   }
      66         [ +  - ]:       9256 :   Trace("pow2") << "We have " << d_pow2s.size() << " pow2 terms." << std::endl;
      67                 :       9256 : }
      68                 :            : 
      69                 :       9256 : void Pow2Solver::checkInitialRefine()
      70                 :            : {
      71         [ +  - ]:       9256 :   Trace("pow2-check") << "Pow2Solver::checkInitialRefine" << std::endl;
      72                 :       9256 :   NodeManager* nm = nodeManager();
      73         [ +  + ]:      10228 :   for (const Node& i : d_pow2s)
      74                 :            :   {
      75         [ +  + ]:        972 :     if (d_initRefine.find(i) != d_initRefine.end())
      76                 :            :     {
      77                 :            :       // already sent initial axioms for i in this user context
      78                 :        876 :       continue;
      79                 :            :     }
      80                 :         96 :     d_initRefine.insert(i);
      81                 :            :     // initial refinement lemmas
      82                 :        192 :     std::vector<Node> conj;
      83                 :            :     // x>=0 -> x < pow2(x)
      84                 :        288 :     Node xgeq0 = nm->mkNode(Kind::LEQ, d_zero, i[0]);
      85                 :        288 :     Node xltpow2x = nm->mkNode(Kind::LT, i[0], i);
      86                 :         96 :     conj.push_back(nm->mkNode(Kind::IMPLIES, xgeq0, xltpow2x));
      87                 :        192 :     Node lem = nm->mkAnd(conj);
      88         [ +  - ]:        192 :     Trace("pow2-lemma") << "Pow2Solver::Lemma: " << lem << " ; INIT_REFINE"
      89                 :         96 :                         << std::endl;
      90                 :         96 :     d_im.addPendingLemma(lem, InferenceId::ARITH_NL_POW2_INIT_REFINE);
      91                 :            :   }
      92                 :       9256 : }
      93                 :            : 
      94                 :       1710 : void Pow2Solver::sortPow2sBasedOnModel()
      95                 :            : {
      96                 :            :   struct
      97                 :            :   {
      98                 :         26 :     bool operator()(Node a, Node b, NlModel& model) const
      99                 :            :     {
     100                 :         52 :       return model.computeConcreteModelValue(a[0])
     101                 :         78 :              < model.computeConcreteModelValue(b[0]);
     102                 :            :     }
     103                 :            :   } modelSort;
     104                 :            :   using namespace std::placeholders;
     105                 :       1710 :   std::sort(
     106                 :       3420 :       d_pow2s.begin(), d_pow2s.end(), std::bind(modelSort, _1, _2, d_model));
     107                 :       1710 : }
     108                 :            : 
     109                 :       1710 : void Pow2Solver::checkFullRefine()
     110                 :            : {
     111         [ +  - ]:       1710 :   Trace("pow2-check") << "Pow2Solver::checkFullRefine" << std::endl;
     112                 :       1710 :   NodeManager* nm = nodeManager();
     113                 :       1710 :   sortPow2sBasedOnModel();
     114                 :            :   // add lemmas for each pow2 term
     115         [ +  + ]:       1798 :   for (uint64_t i = 0, size = d_pow2s.size(); i < size; i++)
     116                 :            :   {
     117                 :         88 :     Node n = d_pow2s[i];
     118                 :         88 :     Node valPow2xAbstract = d_model.computeAbstractModelValue(n);
     119                 :         88 :     Node valPow2xConcrete = d_model.computeConcreteModelValue(n);
     120                 :        176 :     Node valXConcrete = d_model.computeConcreteModelValue(n[0]);
     121         [ -  + ]:         88 :     if (TraceIsOn("pow2-check"))
     122                 :            :     {
     123         [ -  - ]:          0 :       Trace("pow2-check") << "* " << i << ", value = " << valPow2xAbstract
     124                 :          0 :                           << std::endl;
     125         [ -  - ]:          0 :       Trace("pow2-check") << "  actual " << valXConcrete << " = "
     126                 :          0 :                           << valPow2xConcrete << std::endl;
     127                 :            :     }
     128         [ +  + ]:         88 :     if (valPow2xAbstract == valPow2xConcrete)
     129                 :            :     {
     130         [ +  - ]:         18 :       Trace("pow2-check") << "...already correct" << std::endl;
     131                 :         18 :       continue;
     132                 :            :     }
     133                 :            : 
     134                 :        140 :     Integer x = valXConcrete.getConst<Rational>().getNumerator();
     135                 :        140 :     Integer pow2x = valPow2xAbstract.getConst<Rational>().getNumerator();
     136                 :            :     // add monotinicity lemmas
     137         [ +  + ]:         81 :     for (uint64_t j = i + 1; j < size; j++)
     138                 :            :     {
     139                 :         22 :       Node m = d_pow2s[j];
     140                 :         22 :       Node valPow2yAbstract = d_model.computeAbstractModelValue(m);
     141                 :         33 :       Node valYConcrete = d_model.computeConcreteModelValue(m[0]);
     142                 :            : 
     143                 :         22 :       Integer y = valYConcrete.getConst<Rational>().getNumerator();
     144                 :         22 :       Integer pow2y = valPow2yAbstract.getConst<Rational>().getNumerator();
     145                 :            : 
     146 [ +  + ][ +  - ]:         11 :       if (x < y && pow2x >= pow2y)
                 [ +  + ]
     147                 :            :       {
     148                 :         24 :         Node assumption = nm->mkNode(Kind::LEQ, n[0], m[0]);
     149                 :         24 :         Node conclusion = nm->mkNode(Kind::LEQ, n, m);
     150                 :         24 :         Node lem = nm->mkNode(Kind::IMPLIES, assumption, conclusion);
     151                 :          8 :         d_im.addPendingLemma(
     152                 :            :             lem, InferenceId::ARITH_NL_POW2_MONOTONE_REFINE, nullptr, true);
     153                 :            :         }
     154                 :            :     }
     155                 :            : 
     156                 :            :     // triviality lemmas: pow2(x) = 0 whenever x < 0
     157                 :         70 :     if (x < 0 && pow2x != 0)
     158                 :            :     {
     159                 :         72 :       Node assumption = nm->mkNode(Kind::LT, n[0], d_zero);
     160                 :         72 :       Node conclusion = nm->mkNode(Kind::EQUAL, n, mkZero(n.getType()));
     161                 :         72 :       Node lem = nm->mkNode(Kind::IMPLIES, assumption, conclusion);
     162                 :         24 :       d_im.addPendingLemma(
     163                 :            :           lem, InferenceId::ARITH_NL_POW2_TRIVIAL_CASE_REFINE, nullptr, true);
     164                 :            :     }
     165                 :            : 
     166                 :            :     // Place holder for additional lemma schemas
     167                 :            : 
     168                 :            :     // End of additional lemma schemas
     169                 :            : 
     170                 :            :     // this is the most naive model-based schema based on model values
     171                 :        140 :     Node lem = valueBasedLemma(n);
     172         [ +  - ]:        140 :     Trace("pow2-lemma") << "Pow2Solver::Lemma: " << lem << " ; VALUE_REFINE"
     173                 :         70 :                         << std::endl;
     174                 :            :     // send the value lemma
     175                 :         70 :     d_im.addPendingLemma(
     176                 :            :         lem, InferenceId::ARITH_NL_POW2_VALUE_REFINE, nullptr, true);
     177                 :            :   }
     178                 :       1710 : }
     179                 :            : 
     180                 :         70 : Node Pow2Solver::valueBasedLemma(Node i)
     181                 :            : {
     182 [ -  + ][ -  + ]:         70 :   Assert(i.getKind() == Kind::POW2);
                 [ -  - ]
     183                 :        140 :   Node x = i[0];
     184                 :            : 
     185                 :        140 :   Node valX = d_model.computeConcreteModelValue(x);
     186                 :            : 
     187                 :         70 :   NodeManager* nm = nodeManager();
     188                 :         70 :   Node valC = nm->mkNode(Kind::POW2, valX);
     189                 :         70 :   valC = rewrite(valC);
     190                 :            : 
     191                 :        140 :   return nm->mkNode(Kind::IMPLIES, x.eqNode(valX), i.eqNode(valC));
     192                 :            : }
     193                 :            : 
     194                 :            : }  // namespace nl
     195                 :            : }  // namespace arith
     196                 :            : }  // namespace theory
     197                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14