LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/quantifiers/sygus - sygus_invariance.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 118 137 86.1 %
Date: 2026-04-26 10:45:53 Functions: 7 7 100.0 %
Branches: 80 138 58.0 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * Implementation of techniques for sygus invariance tests.
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "theory/quantifiers/sygus/sygus_invariance.h"
      14                 :            : 
      15                 :            : #include "theory/quantifiers/sygus/sygus_pbe.h"
      16                 :            : #include "theory/quantifiers/sygus/synth_conjecture.h"
      17                 :            : #include "theory/quantifiers/sygus/term_database_sygus.h"
      18                 :            : #include "theory/rewriter.h"
      19                 :            : 
      20                 :            : using namespace cvc5::internal::kind;
      21                 :            : using namespace std;
      22                 :            : 
      23                 :            : namespace cvc5::internal {
      24                 :            : namespace theory {
      25                 :            : namespace quantifiers {
      26                 :            : 
      27                 :      58199 : void EvalSygusInvarianceTest::init(Node conj, Node var, Node res)
      28                 :            : {
      29                 :      58199 :   d_terms.clear();
      30                 :            :   // simple miniscope
      31         [ +  + ]:     116398 :   if ((conj.getKind() == Kind::AND || conj.getKind() == Kind::OR)
      32 [ +  - ][ +  - ]:     116398 :       && res.isConst())
                 [ +  + ]
      33                 :            :   {
      34         [ +  + ]:      36306 :     for (const Node& c : conj)
      35                 :            :     {
      36                 :      24204 :       d_terms.push_back(c);
      37                 :      24204 :     }
      38                 :      12102 :     d_kind = conj.getKind();
      39                 :      12102 :     d_is_conjunctive = res.getConst<bool>() == (d_kind == Kind::AND);
      40                 :            :   }
      41                 :            :   else
      42                 :            :   {
      43                 :      46097 :     d_terms.push_back(conj);
      44                 :      46097 :     d_is_conjunctive = true;
      45                 :            :   }
      46                 :      58199 :   d_var = var;
      47                 :      58199 :   d_result = res;
      48                 :      58199 : }
      49                 :            : 
      50                 :     107943 : bool EvalSygusInvarianceTest::invariant(TermDbSygus* tds, Node nvn, Node x)
      51                 :            : {
      52                 :     107943 :   TNode tnvn = nvn;
      53                 :     107943 :   std::unordered_map<TNode, TNode> cache;
      54                 :     107943 :   std::vector<Node> keep;
      55         [ +  + ]:     154816 :   for (const Node& c : d_terms)
      56                 :            :   {
      57                 :     240038 :     Node conj_subs = c.substitute(d_var, tnvn, cache);
      58                 :            :     // Ensure ref counted for now since we are reusing the cache for substitute
      59                 :            :     // in this loop
      60                 :     120019 :     keep.push_back(conj_subs);
      61                 :     120019 :     Node conj_subs_unfold = tds->rewriteNode(conj_subs);
      62         [ +  - ]:     240038 :     Trace("sygus-cref-eval2-debug")
      63                 :     120019 :         << "  ...check unfolding : " << conj_subs_unfold << std::endl;
      64         [ +  - ]:     240038 :     Trace("sygus-cref-eval2-debug")
      65                 :     120019 :         << "  ......from : " << conj_subs << std::endl;
      66         [ +  + ]:     120019 :     if (conj_subs_unfold != d_result)
      67                 :            :     {
      68         [ +  - ]:      73146 :       if (d_is_conjunctive)
      69                 :            :       {
      70                 :            :         // ti /--> true  implies and( t1, ..., tn ) /--> true, where "/-->" is
      71                 :            :         // "does not evaluate to".
      72                 :      73146 :         return false;
      73                 :            :       }
      74                 :            :     }
      75         [ -  + ]:      46873 :     else if (!d_is_conjunctive)
      76                 :            :     {
      77                 :            :       // ti --> true  implies or( t1, ..., tn ) --> true
      78                 :          0 :       return true;
      79                 :            :     }
      80         [ +  - ]:      93746 :     Trace("sygus-cref-eval2")
      81                 :          0 :         << "Evaluation min explain : " << conj_subs << " still evaluates to "
      82                 :      46873 :         << d_result << " regardless of ";
      83         [ +  - ]:      46873 :     Trace("sygus-cref-eval2") << x << std::endl;
      84 [ +  + ][ +  + ]:     193165 :   }
      85                 :      34797 :   return d_is_conjunctive;
      86                 :     107943 : }
      87                 :            : 
      88                 :       2240 : void EquivSygusInvarianceTest::init(CVC5_UNUSED TermDbSygus* tds,
      89                 :            :                                     SynthConjecture* aconj,
      90                 :            :                                     Node e,
      91                 :            :                                     Node bvr)
      92                 :            : {
      93                 :            :   // compute the current examples
      94                 :       2240 :   d_bvr = bvr;
      95 [ -  + ][ -  + ]:       2240 :   Assert(tds != nullptr);
                 [ -  - ]
      96         [ +  - ]:       2240 :   if (aconj != nullptr)
      97                 :            :   {
      98                 :       2240 :     ExampleEvalCache* eec = aconj->getExampleEvalCache(e);
      99         [ +  + ]:       2240 :     if (eec != nullptr)
     100                 :            :     {
     101                 :            :       // get the result of evaluating bvr on the examples of enumerator e.
     102                 :        516 :       eec->evaluateVec(bvr, d_exo, false);
     103                 :        516 :       d_conj = aconj;
     104                 :        516 :       d_enum = e;
     105                 :            :     }
     106                 :            :   }
     107                 :       2240 : }
     108                 :            : 
     109                 :       8950 : bool EquivSygusInvarianceTest::invariant(TermDbSygus* tds, Node nvn, Node x)
     110                 :            : {
     111                 :       8950 :   TypeNode tn = nvn.getType();
     112                 :      17900 :   Node nbv = tds->sygusToBuiltin(nvn, tn);
     113                 :       8950 :   Node nbvr = d_rewriter->extendedRewrite(nbv);
     114         [ +  - ]:      17900 :   Trace("sygus-sb-mexp-debug")
     115                 :       8950 :       << "  min-exp check : " << nbv << " -> " << nbvr << std::endl;
     116                 :       8950 :   bool exc_arg = false;
     117                 :            :   // equivalent / singular up to normalization
     118         [ +  + ]:       8950 :   if (nbvr == d_bvr)
     119                 :            :   {
     120                 :            :     // gives the same result : then the explanation for the child is irrelevant
     121                 :         74 :     exc_arg = true;
     122                 :        148 :     Trace("sygus-sb-mexp") << "sb-min-exp : " << tds->sygusToBuiltin(nvn)
     123                 :         74 :                            << " is rewritten to " << nbvr;
     124         [ +  - ]:        148 :     Trace("sygus-sb-mexp") << " regardless of the content of "
     125                 :         74 :                            << tds->sygusToBuiltin(x) << std::endl;
     126                 :            :   }
     127                 :            :   else
     128                 :            :   {
     129         [ +  + ]:       8876 :     if (nbvr.isVar())
     130                 :            :     {
     131                 :        220 :       TypeNode xtn = x.getType();
     132         [ +  + ]:        220 :       if (xtn == tn)
     133                 :            :       {
     134                 :        420 :         Node bx = tds->sygusToBuiltin(x, xtn);
     135 [ -  + ][ -  + ]:        630 :         AssertEqual(bx.getType(), nbvr.getType());
                 [ -  - ]
     136         [ +  - ]:        210 :         if (nbvr == bx)
     137                 :            :         {
     138         [ +  - ]:        420 :           Trace("sygus-sb-mexp")
     139                 :        210 :               << "sb-min-exp : " << tds->sygusToBuiltin(nvn)
     140                 :        210 :               << " always rewrites to argument " << nbvr << std::endl;
     141                 :            :           // rewrites to the variable : then the explanation of this is
     142                 :            :           // irrelevant as well
     143                 :        210 :           exc_arg = true;
     144                 :        210 :           d_bvr = nbvr;
     145                 :            :         }
     146                 :        210 :       }
     147                 :        220 :     }
     148                 :            :   }
     149                 :            :   // equivalent under examples
     150         [ +  + ]:       8950 :   if (!exc_arg)
     151                 :            :   {
     152         [ +  + ]:       8666 :     if (!d_enum.isNull())
     153                 :            :     {
     154                 :       1902 :       bool ex_equiv = true;
     155                 :       1902 :       ExampleEvalCache* eec = d_conj->getExampleEvalCache(d_enum);
     156 [ -  + ][ -  + ]:       1902 :       Assert(eec != nullptr);
                 [ -  - ]
     157         [ +  + ]:       1988 :       for (unsigned j = 0, esize = d_exo.size(); j < esize; j++)
     158                 :            :       {
     159                 :       1978 :         Node nbvr_ex = eec->evaluate(nbvr, j);
     160         [ +  + ]:       1978 :         if (nbvr_ex != d_exo[j])
     161                 :            :         {
     162                 :       1892 :           ex_equiv = false;
     163                 :       1892 :           break;
     164                 :            :         }
     165         [ +  + ]:       1978 :       }
     166         [ +  + ]:       1902 :       if (ex_equiv)
     167                 :            :       {
     168                 :         10 :         Trace("sygus-sb-mexp") << "sb-min-exp : " << tds->sygusToBuiltin(nvn);
     169         [ +  - ]:         20 :         Trace("sygus-sb-mexp")
     170                 :          0 :             << " is the same w.r.t. examples regardless of the content of "
     171                 :         10 :             << tds->sygusToBuiltin(x) << std::endl;
     172                 :         10 :         exc_arg = true;
     173                 :            :       }
     174                 :            :     }
     175                 :            :   }
     176                 :       8950 :   return exc_arg;
     177                 :       8950 : }
     178                 :            : 
     179                 :         92 : void NegContainsSygusInvarianceTest::init(Node e,
     180                 :            :                                           std::vector<std::vector<Node> >& ex,
     181                 :            :                                           std::vector<Node>& exo,
     182                 :            :                                           std::vector<unsigned>& ncind)
     183                 :            : {
     184 [ -  + ][ -  + ]:         92 :   Assert(ex.size() == exo.size());
                 [ -  - ]
     185                 :         92 :   d_enum = e;
     186                 :         92 :   d_ex.insert(d_ex.end(), ex.begin(), ex.end());
     187                 :         92 :   d_exo.insert(d_exo.end(), exo.begin(), exo.end());
     188                 :         92 :   d_neg_con_indices.insert(d_neg_con_indices.end(), ncind.begin(), ncind.end());
     189                 :         92 : }
     190                 :            : 
     191                 :        130 : bool NegContainsSygusInvarianceTest::invariant(TermDbSygus* tds,
     192                 :            :                                                Node nvn,
     193                 :            :                                                Node x)
     194                 :            : {
     195         [ +  - ]:        130 :   if (!d_enum.isNull())
     196                 :            :   {
     197                 :        130 :     TypeNode tn = nvn.getType();
     198                 :        260 :     Node nbv = tds->sygusToBuiltin(nvn, tn);
     199                 :        130 :     Node nbvr = d_rewriter->extendedRewrite(nbv);
     200                 :            :     // if for any of the examples, it is not contained, then we can exclude
     201         [ +  + ]:      11934 :     for (unsigned i = 0; i < d_neg_con_indices.size(); i++)
     202                 :            :     {
     203                 :      11810 :       unsigned ii = d_neg_con_indices[i];
     204 [ -  + ][ -  + ]:      11810 :       Assert(ii < d_exo.size());
                 [ -  - ]
     205                 :      23620 :       Node nbvre = tds->evaluateBuiltin(tn, nbvr, d_ex[ii]);
     206                 :      11810 :       Node out = d_exo[ii];
     207                 :      23620 :       Node cont = NodeManager::mkNode(Kind::STRING_CONTAINS, out, nbvre);
     208         [ +  - ]:      11810 :       Trace("sygus-pbe-cterm-debug") << "Check: " << cont << std::endl;
     209                 :      11810 :       Node contr = d_rewriter->extendedRewrite(cont);
     210         [ +  - ]:      11810 :       if (!contr.isConst())
     211                 :            :       {
     212         [ +  + ]:      11810 :         if (d_isUniversal)
     213                 :            :         {
     214                 :          6 :           return false;
     215                 :            :         }
     216                 :            :       }
     217         [ -  - ]:          0 :       else if (contr.getConst<bool>() == d_isUniversal)
     218                 :            :       {
     219         [ -  - ]:          0 :         if (TraceIsOn("sygus-pbe-cterm"))
     220                 :            :         {
     221         [ -  - ]:          0 :           Trace("sygus-pbe-cterm")
     222                 :          0 :               << "PBE-cterm : enumerator : do not consider ";
     223         [ -  - ]:          0 :           Trace("sygus-pbe-cterm")
     224                 :          0 :               << nbv << " for any " << tds->sygusToBuiltin(x) << " since "
     225                 :          0 :               << std::endl;
     226         [ -  - ]:          0 :           Trace("sygus-pbe-cterm") << "   PBE-cterm :    for input example : ";
     227         [ -  - ]:          0 :           for (unsigned j = 0, size = d_ex[ii].size(); j < size; j++)
     228                 :            :           {
     229         [ -  - ]:          0 :             Trace("sygus-pbe-cterm") << d_ex[ii][j] << " ";
     230                 :            :           }
     231         [ -  - ]:          0 :           Trace("sygus-pbe-cterm") << std::endl;
     232         [ -  - ]:          0 :           Trace("sygus-pbe-cterm")
     233                 :          0 :               << "   PBE-cterm :     this rewrites to : " << nbvre << std::endl;
     234         [ -  - ]:          0 :           Trace("sygus-pbe-cterm")
     235                 :          0 :               << "   PBE-cterm : and is not in output : " << out << std::endl;
     236                 :            :         }
     237                 :          0 :         return !d_isUniversal;
     238                 :            :       }
     239         [ +  - ]:      23608 :       Trace("sygus-pbe-cterm-debug2")
     240                 :      11804 :           << "...check failed, rewrites to : " << contr << std::endl;
     241 [ +  + ][ +  + ]:      11828 :     }
         [ +  + ][ +  + ]
     242 [ +  + ][ +  + ]:        142 :   }
                 [ +  + ]
     243                 :        124 :   return d_isUniversal;
     244                 :            : }
     245                 :            : 
     246                 :            : }  // namespace quantifiers
     247                 :            : }  // namespace theory
     248                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14