LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/smt - check_models.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 43 55 78.2 %
Date: 2025-01-14 12:45:38 Functions: 2 2 100.0 %
Branches: 15 22 68.2 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andrew Reynolds, Gereon Kremer, Morgan Deters
       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                 :            :  * Utility for constructing and maintaining abstract values.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "smt/check_models.h"
      17                 :            : 
      18                 :            : #include "base/modal_exception.h"
      19                 :            : #include "options/quantifiers_options.h"
      20                 :            : #include "options/smt_options.h"
      21                 :            : #include "smt/env.h"
      22                 :            : #include "smt/expand_definitions.h"
      23                 :            : #include "smt/preprocessor.h"
      24                 :            : #include "smt/smt_solver.h"
      25                 :            : #include "theory/rewriter.h"
      26                 :            : #include "theory/theory_model.h"
      27                 :            : #include "theory/trust_substitutions.h"
      28                 :            : 
      29                 :            : using namespace cvc5::internal::theory;
      30                 :            : 
      31                 :            : namespace cvc5::internal {
      32                 :            : namespace smt {
      33                 :            : 
      34                 :       2336 : CheckModels::CheckModels(Env& e) : EnvObj(e) {}
      35                 :            : 
      36                 :       2994 : void CheckModels::checkModel(TheoryModel* m,
      37                 :            :                              const context::CDList<Node>& al,
      38                 :            :                              bool hardFailure)
      39                 :            : {
      40                 :            :   // Throughout, we use verbose(1) to give diagnostic output.
      41                 :            :   //
      42                 :            :   // If this function is running, the user gave --check-model (or equivalent),
      43                 :            :   // and if verbose(1) is on, the user gave --verbose (or equivalent).
      44                 :            : 
      45                 :       2994 :   Node sepHeap, sepNeq;
      46         [ -  + ]:       2994 :   if (m->getHeapModel(sepHeap, sepNeq))
      47                 :            :   {
      48                 :            :     throw RecoverableModalException(
      49                 :          0 :         "Cannot run check-model on a model with a separation logic heap.");
      50                 :            :   }
      51         [ +  + ]:       2994 :   if (options().quantifiers.fmfFunWellDefined)
      52                 :            :   {
      53                 :          4 :     warning() << "Running check-model is not guaranteed to pass when fmf-fun "
      54                 :          4 :                  "is enabled."
      55                 :          4 :               << std::endl;
      56                 :            :     // only throw warning
      57                 :          4 :     hardFailure = false;
      58                 :            :   }
      59                 :            :   // expand definitions module and substitutions
      60                 :       2994 :   std::unordered_map<Node, Node> ecache;
      61                 :       2994 :   ExpandDefs expDef(d_env);
      62                 :            : 
      63                 :       2994 :   theory::SubstitutionMap& sm = d_env.getTopLevelSubstitutions().get();
      64         [ +  - ]:       2994 :   Trace("check-model") << "checkModel: Check assertions..." << std::endl;
      65                 :       2994 :   std::unordered_map<Node, Node> cache;
      66                 :            :   // the list of assertions that did not rewrite to true
      67                 :       2994 :   std::vector<Node> noCheckList;
      68                 :            :   // Now go through all our user assertions checking if they're satisfied.
      69         [ +  + ]:      26834 :   for (const Node& assertion : al)
      70                 :            :   {
      71                 :      47680 :     verbose(1) << "SolverEngine::checkModel(): checking assertion " << assertion
      72                 :      23840 :                << std::endl;
      73                 :            : 
      74                 :            :     // Apply any define-funs from the problem. We do not expand theory symbols
      75                 :            :     // like integer division here. Hence, the code below is not able to properly
      76                 :            :     // evaluate e.g. divide-by-zero. This is intentional since the evaluation
      77                 :            :     // is not trustworthy, since the UF introduced by expanding definitions may
      78                 :            :     // not be properly constrained.
      79                 :      23840 :     Node n = sm.apply(assertion);
      80                 :      47680 :     verbose(1) << "SolverEngine::checkModel(): -- substitutes to " << n
      81                 :      23840 :                << std::endl;
      82                 :            : 
      83                 :            :     // Expand definitions, which is required for being accurate for operators
      84                 :            :     // that expand involving skolems during preprocessing. Not doing this will
      85                 :            :     // increase the spurious warnings raised by this class.
      86                 :      23840 :     n = expDef.expandDefinitions(n, cache);
      87                 :      47680 :     verbose(1) << "SolverEngine::checkModel(): -- expands to " << n
      88                 :      23840 :                << std::endl;
      89                 :            : 
      90                 :      23840 :     n = rewrite(n);
      91                 :      47680 :     verbose(1) << "SolverEngine::checkModel(): -- rewrites to " << n
      92                 :      23840 :                << std::endl;
      93                 :            : 
      94                 :            :     // We look up the value before simplifying. If n contains quantifiers,
      95                 :            :     // this may increases the chance of finding its value before the node is
      96                 :            :     // altered by simplification below.
      97                 :      23840 :     n = m->getValue(n);
      98                 :      47680 :     verbose(1) << "SolverEngine::checkModel(): -- get value : " << n
      99                 :      23840 :                << std::endl;
     100                 :            : 
     101 [ +  + ][ +  - ]:      23840 :     if (n.isConst() && n.getConst<bool>())
                 [ +  + ]
     102                 :            :     {
     103                 :            :       // assertion is true, everything is fine
     104                 :      23753 :       continue;
     105                 :            :     }
     106                 :            : 
     107                 :            :     // Otherwise, we did not succeed in showing the current assertion to be
     108                 :            :     // true. This may either indicate that our model is wrong, or that we cannot
     109                 :            :     // check it. The latter may be the case for several reasons.
     110                 :            :     // One example is the occurrence of partial operators. Another example
     111                 :            :     // are quantified formulas, which are not checkable, although we assign
     112                 :            :     // them to true/false based on the satisfying assignment. However,
     113                 :            :     // quantified formulas can be modified during preprocess, so they may not
     114                 :            :     // correspond to those in the satisfying assignment. Hence we throw
     115                 :            :     // warnings for assertions that do not simplify to either true or false.
     116                 :            :     // Other theories such as non-linear arithmetic (in particular,
     117                 :            :     // transcendental functions) also have the property of not being able to
     118                 :            :     // be checked precisely here.
     119                 :            :     // Note that warnings like these can be avoided for quantified formulas
     120                 :            :     // by making preprocessing passes explicitly record how they
     121                 :            :     // rewrite quantified formulas (see cvc4-wishues#43).
     122         [ +  - ]:         87 :     if (!n.isConst())
     123                 :            :     {
     124                 :            :       // Not constant, print a less severe warning message here.
     125                 :         87 :       warning()
     126                 :            :           << "Warning : SolverEngine::checkModel(): cannot check simplified "
     127                 :         87 :              "assertion : "
     128                 :         87 :           << n << std::endl;
     129                 :         87 :       noCheckList.push_back(n);
     130                 :         87 :       continue;
     131                 :            :     }
     132                 :            :     // Assertions that simplify to false result in an InternalError or
     133                 :            :     // Warning being thrown below (when hardFailure is false).
     134                 :          0 :     verbose(1) << "SolverEngine::checkModel(): *** PROBLEM: EXPECTED `TRUE' ***"
     135                 :          0 :                << std::endl;
     136                 :          0 :     std::stringstream ss;
     137                 :            :     ss << "SolverEngine::checkModel(): "
     138                 :          0 :        << "ERRORS SATISFYING ASSERTIONS WITH MODEL:" << std::endl
     139                 :          0 :        << "assertion:     " << assertion << std::endl
     140                 :          0 :        << "simplifies to: " << n << std::endl
     141                 :          0 :        << "expected `true'." << std::endl
     142                 :          0 :        << "Run with `--check-models -v' for additional diagnostics.";
     143         [ -  - ]:          0 :     if (hardFailure)
     144                 :            :     {
     145                 :            :       // internal error if hardFailure is true
     146                 :          0 :       InternalError() << ss.str();
     147                 :            :     }
     148                 :            :     else
     149                 :            :     {
     150                 :          0 :       warning() << ss.str() << std::endl;
     151                 :            :     }
     152                 :            :   }
     153         [ +  + ]:       2994 :   if (noCheckList.empty())
     154                 :            :   {
     155                 :       2925 :     verbose(1) << "SolverEngine::checkModel(): all assertions checked out OK !"
     156                 :       2925 :                << std::endl;
     157                 :       2925 :     return;
     158                 :            :   }
     159                 :            :   // if the noCheckList is non-empty, we could expand definitions on this list
     160                 :            :   // and check satisfiability
     161                 :            : 
     162         [ +  - ]:         69 :   Trace("check-model") << "checkModel: Finish" << std::endl;
     163                 :            : }
     164                 :            : 
     165                 :            : }  // namespace smt
     166                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14