LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/theory/quantifiers/sygus - transition_inference.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 282 297 94.9 %
Date: 2026-01-25 11:16:35 Functions: 20 20 100.0 %
Branches: 205 310 66.1 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andrew Reynolds, Aina Niemetz, Daniel Larraz
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2025 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 utility for inferring whether a synthesis conjecture
      14                 :            :  * encodes a transition system.
      15                 :            :  */
      16                 :            : #include "theory/quantifiers/sygus/transition_inference.h"
      17                 :            : 
      18                 :            : #include "expr/node_algorithm.h"
      19                 :            : #include "expr/skolem_manager.h"
      20                 :            : #include "theory/arith/arith_msum.h"
      21                 :            : #include "theory/quantifiers/term_util.h"
      22                 :            : #include "theory/rewriter.h"
      23                 :            : 
      24                 :            : using namespace cvc5::internal::kind;
      25                 :            : 
      26                 :            : namespace cvc5::internal {
      27                 :            : namespace theory {
      28                 :            : namespace quantifiers {
      29                 :            : 
      30                 :        630 : bool DetTrace::DetTraceTrie::add(Node loc, const std::vector<Node>& val)
      31                 :            : {
      32                 :        630 :   DetTraceTrie* curr = this;
      33         [ +  + ]:       1876 :   for (const Node& v : val)
      34                 :            :   {
      35                 :       1246 :     curr = &(curr->d_children[v]);
      36                 :            :   }
      37         [ +  - ]:        630 :   if (curr->d_children.empty())
      38                 :            :   {
      39                 :        630 :     curr->d_children[loc].clear();
      40                 :        630 :     return true;
      41                 :            :   }
      42                 :          0 :   return false;
      43                 :            : }
      44                 :            : 
      45                 :         14 : Node DetTrace::DetTraceTrie::constructFormula(NodeManager* nm,
      46                 :            :                                               const std::vector<Node>& vars,
      47                 :            :                                               unsigned index)
      48                 :            : {
      49         [ -  + ]:         14 :   if (index == vars.size())
      50                 :            :   {
      51                 :          0 :     return nm->mkConst(true);
      52                 :            :   }
      53                 :         28 :   std::vector<Node> disj;
      54         [ +  + ]:         48 :   for (std::pair<const Node, DetTraceTrie>& p : d_children)
      55                 :            :   {
      56                 :         68 :     Node eq = vars[index].eqNode(p.first);
      57         [ +  + ]:         34 :     if (index < vars.size() - 1)
      58                 :            :     {
      59                 :         10 :       Node conc = p.second.constructFormula(nm, vars, index + 1);
      60                 :         10 :       disj.push_back(nm->mkNode(Kind::AND, eq, conc));
      61                 :            :     }
      62                 :            :     else
      63                 :            :     {
      64                 :         24 :       disj.push_back(eq);
      65                 :            :     }
      66                 :            :   }
      67 [ -  + ][ -  + ]:         14 :   Assert(!disj.empty());
                 [ -  - ]
      68         [ +  + ]:         14 :   return disj.size() == 1 ? disj[0] : nm->mkNode(Kind::OR, disj);
      69                 :            : }
      70                 :            : 
      71                 :        630 : bool DetTrace::increment(Node loc, std::vector<Node>& vals)
      72                 :            : {
      73         [ +  - ]:        630 :   if (d_trie.add(loc, vals))
      74                 :            :   {
      75         [ +  + ]:       1876 :     for (unsigned i = 0, vsize = vals.size(); i < vsize; i++)
      76                 :            :     {
      77                 :       1246 :       d_curr[i] = vals[i];
      78                 :            :     }
      79                 :        630 :     return true;
      80                 :            :   }
      81                 :          0 :   return false;
      82                 :            : }
      83                 :            : 
      84                 :          4 : Node DetTrace::constructFormula(NodeManager* nm, const std::vector<Node>& vars)
      85                 :            : {
      86                 :          4 :   return d_trie.constructFormula(nm, vars);
      87                 :            : }
      88                 :            : 
      89                 :        634 : void DetTrace::print(const char* c) const
      90                 :            : {
      91         [ +  + ]:       1886 :   for (const Node& n : d_curr)
      92                 :            :   {
      93         [ +  - ]:       1252 :     Trace(c) << n << " ";
      94                 :            :   }
      95                 :        634 : }
      96                 :            : 
      97                 :        495 : Node TransitionInference::getFunction() const { return d_func; }
      98                 :            : 
      99                 :        602 : void TransitionInference::getVariables(std::vector<Node>& vars) const
     100                 :            : {
     101                 :        602 :   vars.insert(vars.end(), d_vars.begin(), d_vars.end());
     102                 :        602 : }
     103                 :            : 
     104                 :        602 : Node TransitionInference::getPreCondition() const { return d_pre.d_this; }
     105                 :       1226 : Node TransitionInference::getPostCondition() const { return d_post.d_this; }
     106                 :       1210 : Node TransitionInference::getTransitionRelation() const
     107                 :            : {
     108                 :       1210 :   return d_trans.d_this;
     109                 :            : }
     110                 :            : 
     111                 :       1421 : void TransitionInference::getConstantSubstitution(
     112                 :            :     const std::vector<Node>& vars,
     113                 :            :     const std::vector<Node>& disjuncts,
     114                 :            :     std::vector<Node>& const_var,
     115                 :            :     std::vector<Node>& const_subs,
     116                 :            :     bool reqPol)
     117                 :            : {
     118         [ +  + ]:       4547 :   for (const Node& d : disjuncts)
     119                 :            :   {
     120                 :       6252 :     Node sn;
     121         [ +  + ]:       3126 :     if (!const_var.empty())
     122                 :            :     {
     123                 :        944 :       sn = d.substitute(const_var.begin(),
     124                 :            :                         const_var.end(),
     125                 :            :                         const_subs.begin(),
     126                 :        472 :                         const_subs.end());
     127                 :        472 :       sn = rewrite(sn);
     128                 :            :     }
     129                 :            :     else
     130                 :            :     {
     131                 :       2654 :       sn = d;
     132                 :            :     }
     133                 :       3126 :     bool slit_pol = sn.getKind() != Kind::NOT;
     134         [ +  + ]:       6252 :     Node slit = sn.getKind() == Kind::NOT ? sn[0] : sn;
     135 [ +  + ][ +  + ]:       3126 :     if (slit.getKind() == Kind::EQUAL && slit_pol == reqPol)
                 [ +  + ]
     136                 :            :     {
     137                 :            :       // check if it is a variable equality
     138                 :        844 :       TNode v;
     139                 :        844 :       Node s;
     140         [ +  + ]:        847 :       for (unsigned r = 0; r < 2; r++)
     141                 :            :       {
     142         [ +  + ]:        663 :         if (std::find(vars.begin(), vars.end(), slit[r]) != vars.end())
     143                 :            :         {
     144         [ +  + ]:        239 :           if (!expr::hasSubterm(slit[1 - r], slit[r]))
     145                 :            :           {
     146                 :        238 :             v = slit[r];
     147                 :        238 :             s = slit[1 - r];
     148                 :        238 :             break;
     149                 :            :           }
     150                 :            :         }
     151                 :            :       }
     152         [ +  + ]:        422 :       if (v.isNull())
     153                 :            :       {
     154                 :            :         // solve for var
     155                 :        368 :         std::map<Node, Node> msum;
     156         [ +  + ]:        184 :         if (ArithMSum::getMonomialSumLit(slit, msum))
     157                 :            :         {
     158         [ +  + ]:        233 :           for (std::pair<const Node, Node>& m : msum)
     159                 :            :           {
     160         [ +  + ]:        172 :             if (std::find(vars.begin(), vars.end(), m.first) != vars.end())
     161                 :            :             {
     162                 :        108 :               Node veq_c;
     163                 :        108 :               Node val;
     164                 :            :               int ires =
     165                 :         54 :                   ArithMSum::isolate(m.first, msum, veq_c, val, Kind::EQUAL);
     166         [ +  - ]:         54 :               if (ires != 0 && veq_c.isNull()
     167                 :        108 :                   && !expr::hasSubterm(val, m.first))
     168                 :            :               {
     169                 :         54 :                 v = m.first;
     170                 :         54 :                 s = val;
     171                 :            :               }
     172                 :            :             }
     173                 :            :           }
     174                 :            :         }
     175                 :            :       }
     176         [ +  + ]:        422 :       if (!v.isNull())
     177                 :            :       {
     178                 :        584 :         TNode ts = s;
     179         [ +  + ]:        486 :         for (unsigned k = 0, csize = const_subs.size(); k < csize; k++)
     180                 :            :         {
     181                 :        194 :           const_subs[k] = rewrite(const_subs[k].substitute(v, ts));
     182                 :            :         }
     183         [ +  - ]:        584 :         Trace("cegqi-inv-debug2")
     184                 :        292 :             << "...substitution : " << v << " -> " << s << std::endl;
     185                 :        292 :         const_var.push_back(v);
     186                 :        292 :         const_subs.push_back(s);
     187                 :            :       }
     188                 :            :     }
     189                 :            :   }
     190                 :       1421 : }
     191                 :            : 
     192                 :       1456 : void TransitionInference::process(Node n, Node f)
     193                 :            : {
     194                 :            :   // set the function
     195                 :       1456 :   d_func = f;
     196                 :       1456 :   process(n);
     197                 :       1456 : }
     198                 :            : 
     199                 :       1456 : void TransitionInference::process(Node n)
     200                 :            : {
     201                 :       1456 :   NodeManager* nm = nodeManager();
     202                 :       1456 :   d_complete = true;
     203                 :       1456 :   d_trivial = true;
     204                 :       2912 :   std::vector<Node> n_check;
     205         [ +  + ]:       1456 :   if (n.getKind() == Kind::AND)
     206                 :            :   {
     207         [ +  + ]:       1559 :     for (const Node& nc : n)
     208                 :            :     {
     209                 :       1090 :       n_check.push_back(nc);
     210                 :            :     }
     211                 :            :   }
     212                 :            :   else
     213                 :            :   {
     214                 :        987 :     n_check.push_back(n);
     215                 :            :   }
     216         [ +  + ]:       3533 :   for (const Node& nn : n_check)
     217                 :            :   {
     218                 :       2077 :     std::map<bool, std::map<Node, bool> > visited;
     219                 :       2077 :     std::map<bool, Node> terms;
     220                 :       2077 :     std::vector<Node> disjuncts;
     221         [ +  - ]:       4154 :     Trace("cegqi-inv") << "TransitionInference : Process disjunct : " << nn
     222                 :       2077 :                        << std::endl;
     223         [ +  + ]:       2077 :     if (!processDisjunct(nn, terms, disjuncts, visited, true))
     224                 :            :     {
     225                 :        283 :       d_complete = false;
     226                 :        283 :       continue;
     227                 :            :     }
     228         [ +  + ]:       1794 :     if (terms.empty())
     229                 :            :     {
     230                 :        373 :       continue;
     231                 :            :     }
     232                 :       1421 :     Node curr;
     233                 :            :     // The component that this disjunct contributes to, where
     234                 :            :     // 1 : pre-condition, -1 : post-condition, 0 : transition relation
     235                 :            :     int comp_num;
     236                 :       1421 :     std::map<bool, Node>::iterator itt = terms.find(false);
     237         [ +  + ]:       1421 :     if (itt != terms.end())
     238                 :            :     {
     239                 :        909 :       curr = itt->second;
     240         [ +  + ]:        909 :       if (terms.find(true) != terms.end())
     241                 :            :       {
     242                 :         66 :         comp_num = 0;
     243                 :            :       }
     244                 :            :       else
     245                 :            :       {
     246                 :        843 :         comp_num = -1;
     247                 :            :       }
     248                 :            :     }
     249                 :            :     else
     250                 :            :     {
     251                 :        512 :       curr = terms[true];
     252                 :        512 :       comp_num = 1;
     253                 :            :     }
     254         [ +  - ]:       1421 :     Trace("cegqi-inv-debug2") << "  normalize based on " << curr << std::endl;
     255                 :       1421 :     std::vector<Node> vars;
     256                 :       1421 :     std::vector<Node> svars;
     257                 :       1421 :     getNormalizedSubstitution(curr, d_vars, vars, svars, disjuncts);
     258         [ +  + ]:       4531 :     for (unsigned j = 0, dsize = disjuncts.size(); j < dsize; j++)
     259                 :            :     {
     260         [ +  - ]:       3110 :       Trace("cegqi-inv-debug2") << "  apply " << disjuncts[j] << std::endl;
     261                 :       6220 :       disjuncts[j] = rewrite(disjuncts[j].substitute(
     262                 :       3110 :           vars.begin(), vars.end(), svars.begin(), svars.end()));
     263         [ +  - ]:       3110 :       Trace("cegqi-inv-debug2") << "  ..." << disjuncts[j] << std::endl;
     264                 :            :     }
     265                 :       1421 :     std::vector<Node> const_var;
     266                 :       1421 :     std::vector<Node> const_subs;
     267         [ +  + ]:       1421 :     if (comp_num == 0)
     268                 :            :     {
     269                 :            :       // transition
     270 [ -  + ][ -  + ]:         66 :       Assert(terms.find(true) != terms.end());
                 [ -  - ]
     271                 :        132 :       Node next = terms[true];
     272                 :        132 :       next = rewrite(next.substitute(
     273                 :         66 :           vars.begin(), vars.end(), svars.begin(), svars.end()));
     274         [ +  - ]:        132 :       Trace("cegqi-inv-debug")
     275                 :         66 :           << "transition next predicate : " << next << std::endl;
     276                 :            :       // make the primed variables if we have not already
     277         [ +  - ]:         66 :       if (d_prime_vars.empty())
     278                 :            :       {
     279         [ +  + ]:        374 :         for (unsigned j = 0, nchild = next.getNumChildren(); j < nchild; j++)
     280                 :            :         {
     281                 :            :           Node v = NodeManager::mkDummySkolem(
     282                 :        924 :               "ir", next[j].getType(), "template inference rev argument");
     283                 :        308 :           d_prime_vars.push_back(v);
     284                 :            :         }
     285                 :            :       }
     286                 :            :       // normalize the other direction
     287         [ +  - ]:         66 :       Trace("cegqi-inv-debug2") << "  normalize based on " << next << std::endl;
     288                 :        132 :       std::vector<Node> rvars;
     289                 :        132 :       std::vector<Node> rsvars;
     290                 :         66 :       getNormalizedSubstitution(next, d_prime_vars, rvars, rsvars, disjuncts);
     291 [ -  + ][ -  + ]:         66 :       Assert(rvars.size() == rsvars.size());
                 [ -  - ]
     292         [ +  + ]:        368 :       for (unsigned j = 0, dsize = disjuncts.size(); j < dsize; j++)
     293                 :            :       {
     294         [ +  - ]:        302 :         Trace("cegqi-inv-debug2") << "  apply " << disjuncts[j] << std::endl;
     295                 :        604 :         disjuncts[j] = rewrite(disjuncts[j].substitute(
     296                 :        302 :             rvars.begin(), rvars.end(), rsvars.begin(), rsvars.end()));
     297         [ +  - ]:        302 :         Trace("cegqi-inv-debug2") << "  ..." << disjuncts[j] << std::endl;
     298                 :            :       }
     299                 :         66 :       getConstantSubstitution(
     300                 :         66 :           d_prime_vars, disjuncts, const_var, const_subs, false);
     301                 :            :     }
     302                 :            :     else
     303                 :            :     {
     304                 :       1355 :       getConstantSubstitution(d_vars, disjuncts, const_var, const_subs, false);
     305                 :            :     }
     306                 :       1421 :     Node res;
     307         [ +  + ]:       1421 :     if (disjuncts.empty())
     308                 :            :     {
     309                 :         12 :       res = nm->mkConst(false);
     310                 :            :     }
     311         [ +  + ]:       1409 :     else if (disjuncts.size() == 1)
     312                 :            :     {
     313                 :        309 :       res = disjuncts[0];
     314                 :            :     }
     315                 :            :     else
     316                 :            :     {
     317                 :       1100 :       res = nm->mkNode(Kind::OR, disjuncts);
     318                 :            :     }
     319         [ +  + ]:       1421 :     if (expr::hasBoundVar(res))
     320                 :            :     {
     321         [ +  - ]:        626 :       Trace("cegqi-inv-debug2") << "...failed, free variable." << std::endl;
     322                 :        626 :       d_complete = false;
     323                 :        626 :       continue;
     324                 :            :     }
     325         [ +  - ]:       1590 :     Trace("cegqi-inv") << "*** inferred "
     326         [ -  - ]:        795 :                        << (comp_num == 1 ? "pre"
     327         [ -  - ]:          0 :                                          : (comp_num == -1 ? "post" : "trans"))
     328                 :        795 :                        << "-condition : " << res << std::endl;
     329 [ +  + ][ +  + ]:        795 :     Component& c =
     330                 :            :         (comp_num == 1 ? d_pre : (comp_num == -1 ? d_post : d_trans));
     331                 :        795 :     c.d_conjuncts.push_back(res);
     332         [ +  + ]:        795 :     if (!const_var.empty())
     333                 :            :     {
     334                 :        133 :       bool has_const_eq = const_var.size() == d_vars.size();
     335         [ +  - ]:        266 :       Trace("cegqi-inv") << "    with constant substitution, complete = "
     336                 :        133 :                          << has_const_eq << " : " << std::endl;
     337         [ +  + ]:        390 :       for (unsigned i = 0, csize = const_var.size(); i < csize; i++)
     338                 :            :       {
     339         [ +  - ]:        514 :         Trace("cegqi-inv") << "      " << const_var[i] << " -> "
     340                 :        257 :                            << const_subs[i] << std::endl;
     341         [ +  + ]:        257 :         if (has_const_eq)
     342                 :            :         {
     343                 :        144 :           c.d_const_eq[res][const_var[i]] = const_subs[i];
     344                 :            :         }
     345                 :            :       }
     346         [ +  - ]:        266 :       Trace("cegqi-inv") << "...size = " << const_var.size()
     347                 :        133 :                          << ", #vars = " << d_vars.size() << std::endl;
     348                 :            :     }
     349                 :            :   }
     350                 :            : 
     351                 :            :   // finalize the components
     352         [ +  + ]:       5824 :   for (int i = -1; i <= 1; i++)
     353                 :            :   {
     354 [ +  + ][ +  + ]:       4368 :     Component& c = (i == 1 ? d_pre : (i == -1 ? d_post : d_trans));
     355                 :       8736 :     Node ret;
     356         [ +  + ]:       4368 :     if (c.d_conjuncts.empty())
     357                 :            :     {
     358                 :       3581 :       ret = nm->mkConst(true);
     359                 :            :     }
     360         [ +  + ]:        787 :     else if (c.d_conjuncts.size() == 1)
     361                 :            :     {
     362                 :        781 :       ret = c.d_conjuncts[0];
     363                 :            :     }
     364                 :            :     else
     365                 :            :     {
     366                 :          6 :       ret = nm->mkNode(Kind::AND, c.d_conjuncts);
     367                 :            :     }
     368 [ +  + ][ +  + ]:       4368 :     if (i == 0 || i == 1)
     369                 :            :     {
     370                 :            :       // pre-condition and transition are negated
     371                 :       2912 :       ret = TermUtil::simpleNegate(ret);
     372                 :            :     }
     373                 :       4368 :     c.d_this = ret;
     374                 :            :   }
     375                 :       1456 : }
     376                 :       1487 : void TransitionInference::getNormalizedSubstitution(
     377                 :            :     Node curr,
     378                 :            :     const std::vector<Node>& pvars,
     379                 :            :     std::vector<Node>& vars,
     380                 :            :     std::vector<Node>& subs,
     381                 :            :     std::vector<Node>& disjuncts)
     382                 :            : {
     383         [ +  + ]:       4597 :   for (unsigned j = 0, nchild = curr.getNumChildren(); j < nchild; j++)
     384                 :            :   {
     385         [ +  + ]:       3110 :     if (curr[j].getKind() == Kind::BOUND_VARIABLE)
     386                 :            :     {
     387                 :            :       // if the argument is a bound variable, add to the renaming
     388                 :       3009 :       vars.push_back(curr[j]);
     389                 :       3009 :       subs.push_back(pvars[j]);
     390                 :            :     }
     391                 :            :     else
     392                 :            :     {
     393                 :            :       // otherwise, treat as a constraint on the variable
     394                 :            :       // For example, this transforms e.g. a precondition clause
     395                 :            :       // I( 0, 1 ) to x1 != 0 OR x2 != 1 OR I( x1, x2 ).
     396                 :        101 :       Node eq = curr[j].eqNode(pvars[j]);
     397                 :        101 :       disjuncts.push_back(eq.negate());
     398                 :            :     }
     399                 :            :   }
     400                 :       1487 : }
     401                 :            : 
     402                 :      22837 : bool TransitionInference::processDisjunct(
     403                 :            :     Node n,
     404                 :            :     std::map<bool, Node>& terms,
     405                 :            :     std::vector<Node>& disjuncts,
     406                 :            :     std::map<bool, std::map<Node, bool> >& visited,
     407                 :            :     bool topLevel)
     408                 :            : {
     409         [ +  + ]:      22837 :   if (visited[topLevel].find(n) != visited[topLevel].end())
     410                 :            :   {
     411                 :       4958 :     return true;
     412                 :            :   }
     413                 :      17879 :   visited[topLevel][n] = true;
     414 [ +  + ][ +  + ]:      17879 :   bool childTopLevel = n.getKind() == Kind::OR && topLevel;
     415                 :            :   // if another part mentions UF or a free variable, then fail
     416                 :      17879 :   bool lit_pol = n.getKind() != Kind::NOT;
     417         [ +  + ]:      35758 :   Node lit = n.getKind() == Kind::NOT ? n[0] : n;
     418                 :            :   // is it an application of the function-to-synthesize? Yes if we haven't
     419                 :            :   // encountered a function or if it matches the existing d_func.
     420                 :      53637 :   if (lit.getKind() == Kind::APPLY_UF
     421 [ +  + ][ +  - ]:      17879 :       && (d_func.isNull() || lit.getOperator() == d_func))
         [ +  + ][ +  + ]
         [ +  + ][ -  - ]
     422                 :            :   {
     423                 :       3540 :     Node op = lit.getOperator();
     424                 :            :     // initialize the variables
     425         [ +  + ]:       1770 :     if (d_trivial)
     426                 :            :     {
     427                 :       1093 :       d_trivial = false;
     428                 :       1093 :       d_func = op;
     429         [ +  - ]:       1093 :       Trace("cegqi-inv-debug") << "Use " << op << " with args ";
     430         [ +  + ]:       3235 :       for (const Node& l : lit)
     431                 :            :       {
     432                 :            :         Node v = NodeManager::mkDummySkolem(
     433                 :       4284 :             "i", l.getType(), "template inference argument");
     434                 :       2142 :         d_vars.push_back(v);
     435         [ +  - ]:       2142 :         Trace("cegqi-inv-debug") << v << " ";
     436                 :            :       }
     437         [ +  - ]:       1093 :       Trace("cegqi-inv-debug") << std::endl;
     438                 :            :     }
     439 [ -  + ][ -  + ]:       1770 :     Assert(!d_func.isNull());
                 [ -  - ]
     440         [ +  + ]:       1770 :     if (topLevel)
     441                 :            :     {
     442         [ +  - ]:       1487 :       if (terms.find(lit_pol) == terms.end())
     443                 :            :       {
     444                 :       1487 :         terms[lit_pol] = lit;
     445                 :       1487 :         return true;
     446                 :            :       }
     447                 :            :       else
     448                 :            :       {
     449         [ -  - ]:          0 :         Trace("cegqi-inv-debug")
     450                 :          0 :             << "...failed, repeated inv-app : " << lit << std::endl;
     451                 :          0 :         return false;
     452                 :            :       }
     453                 :            :     }
     454         [ +  - ]:        566 :     Trace("cegqi-inv-debug")
     455                 :        283 :         << "...failed, non-entailed inv-app : " << lit << std::endl;
     456                 :        283 :     return false;
     457                 :            :   }
     458 [ +  + ][ +  + ]:      16109 :   else if (topLevel && !childTopLevel)
     459                 :            :   {
     460                 :       3717 :     disjuncts.push_back(n);
     461                 :            :   }
     462         [ +  + ]:      36404 :   for (const Node& nc : n)
     463                 :            :   {
     464         [ +  + ]:      20760 :     if (!processDisjunct(nc, terms, disjuncts, visited, childTopLevel))
     465                 :            :     {
     466                 :        465 :       return false;
     467                 :            :     }
     468                 :            :   }
     469                 :      15644 :   return true;
     470                 :            : }
     471                 :            : 
     472                 :         43 : TraceIncStatus TransitionInference::initializeTrace(DetTrace& dt,
     473                 :            :                                                     Node loc,
     474                 :            :                                                     bool fwd)
     475                 :            : {
     476         [ +  - ]:         43 :   Component& c = fwd ? d_pre : d_post;
     477 [ -  + ][ -  + ]:         43 :   Assert(c.has(loc));
                 [ -  - ]
     478                 :         43 :   std::map<Node, std::map<Node, Node> >::iterator it = c.d_const_eq.find(loc);
     479         [ +  + ]:         43 :   if (it != c.d_const_eq.end())
     480                 :            :   {
     481                 :         10 :     std::vector<Node> next;
     482         [ +  + ]:         28 :     for (const Node& v : d_vars)
     483                 :            :     {
     484 [ -  + ][ -  + ]:         18 :       Assert(it->second.find(v) != it->second.end());
                 [ -  - ]
     485                 :         18 :       next.push_back(it->second[v]);
     486                 :         18 :       dt.d_curr.push_back(it->second[v]);
     487                 :            :     }
     488         [ +  - ]:         10 :     Trace("cegqi-inv-debug2") << "dtrace : initial increment" << std::endl;
     489                 :         10 :     bool ret = dt.increment(loc, next);
     490 [ -  + ][ -  + ]:         10 :     AlwaysAssert(ret);
                 [ -  - ]
     491                 :         10 :     return TRACE_INC_SUCCESS;
     492                 :            :   }
     493                 :         33 :   return TRACE_INC_INVALID;
     494                 :            : }
     495                 :            : 
     496                 :        624 : TraceIncStatus TransitionInference::incrementTrace(DetTrace& dt,
     497                 :            :                                                    Node loc,
     498                 :            :                                                    bool fwd)
     499                 :            : {
     500 [ -  + ][ -  + ]:        624 :   Assert(d_trans.has(loc));
                 [ -  - ]
     501                 :            :   // check if it satisfies the pre/post condition
     502         [ +  - ]:       1248 :   Node cc = fwd ? getPostCondition() : getPreCondition();
     503 [ -  + ][ -  + ]:        624 :   Assert(!cc.isNull());
                 [ -  - ]
     504                 :        624 :   Node ccr = rewrite(cc.substitute(
     505                 :       2496 :       d_vars.begin(), d_vars.end(), dt.d_curr.begin(), dt.d_curr.end()));
     506         [ +  - ]:        624 :   if (ccr.isConst())
     507                 :            :   {
     508 [ +  - ][ -  + ]:        624 :     if (ccr.getConst<bool>() == (fwd ? false : true))
     509                 :            :     {
     510         [ -  - ]:          0 :       Trace("cegqi-inv-debug2") << "dtrace : counterexample" << std::endl;
     511                 :          0 :       return TRACE_INC_CEX;
     512                 :            :     }
     513                 :            :   }
     514                 :            : 
     515                 :            :   // terminates?
     516                 :       1248 :   Node c = getTransitionRelation();
     517 [ -  + ][ -  + ]:        624 :   Assert(!c.isNull());
                 [ -  - ]
     518                 :            : 
     519 [ -  + ][ -  + ]:        624 :   Assert(d_vars.size() == dt.d_curr.size());
                 [ -  - ]
     520                 :        624 :   Node cr = rewrite(c.substitute(
     521                 :       2496 :       d_vars.begin(), d_vars.end(), dt.d_curr.begin(), dt.d_curr.end()));
     522         [ +  + ]:        624 :   if (cr.isConst())
     523                 :            :   {
     524         [ +  - ]:          4 :     if (!cr.getConst<bool>())
     525                 :            :     {
     526         [ +  - ]:          4 :       Trace("cegqi-inv-debug2") << "dtrace : terminated" << std::endl;
     527                 :          4 :       return TRACE_INC_TERMINATE;
     528                 :            :     }
     529                 :          0 :     return TRACE_INC_INVALID;
     530                 :            :   }
     531         [ -  + ]:        620 :   if (!fwd)
     532                 :            :   {
     533                 :            :     // only implemented in forward direction
     534                 :          0 :     Assert(false);
     535                 :            :     return TRACE_INC_INVALID;
     536                 :            :   }
     537                 :        620 :   Component& cm = d_trans;
     538                 :        620 :   std::map<Node, std::map<Node, Node> >::iterator it = cm.d_const_eq.find(loc);
     539         [ -  + ]:        620 :   if (it == cm.d_const_eq.end())
     540                 :            :   {
     541                 :          0 :     return TRACE_INC_INVALID;
     542                 :            :   }
     543                 :       1240 :   std::vector<Node> next;
     544         [ +  + ]:       1848 :   for (const Node& pv : d_prime_vars)
     545                 :            :   {
     546 [ -  + ][ -  + ]:       1228 :     Assert(it->second.find(pv) != it->second.end());
                 [ -  - ]
     547                 :       2456 :     Node pvs = it->second[pv];
     548 [ -  + ][ -  + ]:       1228 :     Assert(d_vars.size() == dt.d_curr.size());
                 [ -  - ]
     549                 :       1228 :     Node pvsr = rewrite(pvs.substitute(
     550                 :       4912 :         d_vars.begin(), d_vars.end(), dt.d_curr.begin(), dt.d_curr.end()));
     551                 :       1228 :     next.push_back(pvsr);
     552                 :            :   }
     553         [ +  - ]:        620 :   if (dt.increment(loc, next))
     554                 :            :   {
     555         [ +  - ]:        620 :     Trace("cegqi-inv-debug2") << "dtrace : success increment" << std::endl;
     556                 :        620 :     return TRACE_INC_SUCCESS;
     557                 :            :   }
     558                 :            :   // looped
     559         [ -  - ]:          0 :   Trace("cegqi-inv-debug2") << "dtrace : looped" << std::endl;
     560                 :          0 :   return TRACE_INC_TERMINATE;
     561                 :            : }
     562                 :            : 
     563                 :         45 : TraceIncStatus TransitionInference::initializeTrace(DetTrace& dt, bool fwd)
     564                 :            : {
     565         [ +  - ]:         45 :   Trace("cegqi-inv-debug2") << "Initialize trace" << std::endl;
     566         [ +  - ]:         45 :   Component& c = fwd ? d_pre : d_post;
     567         [ +  + ]:         45 :   if (c.d_conjuncts.size() == 1)
     568                 :            :   {
     569                 :         43 :     return initializeTrace(dt, c.d_conjuncts[0], fwd);
     570                 :            :   }
     571                 :          2 :   return TRACE_INC_INVALID;
     572                 :            : }
     573                 :            : 
     574                 :        624 : TraceIncStatus TransitionInference::incrementTrace(DetTrace& dt, bool fwd)
     575                 :            : {
     576         [ +  - ]:        624 :   if (d_trans.d_conjuncts.size() == 1)
     577                 :            :   {
     578                 :        624 :     return incrementTrace(dt, d_trans.d_conjuncts[0], fwd);
     579                 :            :   }
     580                 :          0 :   return TRACE_INC_INVALID;
     581                 :            : }
     582                 :            : 
     583                 :          4 : Node TransitionInference::constructFormulaTrace(DetTrace& dt) const
     584                 :            : {
     585                 :          4 :   return dt.constructFormula(nodeManager(), d_vars);
     586                 :            : }
     587                 :            : 
     588                 :            : }  // namespace quantifiers
     589                 :            : }  // namespace theory
     590                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14