GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/sygus/synth_verify.cpp Lines: 42 46 91.3 %
Date: 2021-08-16 Branches: 84 192 43.8 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 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
 * Class for verifying queries for synthesis solutions
14
 */
15
16
#include "theory/quantifiers/sygus/synth_verify.h"
17
18
#include "expr/node_algorithm.h"
19
#include "options/base_options.h"
20
#include "options/quantifiers_options.h"
21
#include "smt/smt_engine_scope.h"
22
#include "smt/smt_statistics_registry.h"
23
#include "theory/quantifiers/first_order_model.h"
24
#include "theory/quantifiers/sygus/term_database_sygus.h"
25
#include "theory/rewriter.h"
26
#include "theory/smt_engine_subsolver.h"
27
28
using namespace cvc5::kind;
29
using namespace std;
30
31
namespace cvc5 {
32
namespace theory {
33
namespace quantifiers {
34
35
1151
SynthVerify::SynthVerify(TermDbSygus* tds) : d_tds(tds)
36
{
37
  // determine the options to use for the verification subsolvers we spawn
38
  // we start with the options of the current SmtEngine
39
1151
  SmtEngine* smtCurr = smt::currentSmtEngine();
40
1151
  d_subOptions.copyValues(smtCurr->getOptions());
41
  // limit the number of instantiation rounds on subcalls
42
2302
  d_subOptions.quantifiers.instMaxRounds =
43
2302
      d_subOptions.quantifiers.sygusVerifyInstMaxRounds;
44
  // Disable sygus on the subsolver. This is particularly important since it
45
  // ensures that recursive function definitions have the standard ownership
46
  // instead of being claimed by sygus in the subsolver.
47
1151
  d_subOptions.base.inputLanguage = language::input::LANG_SMTLIB_V2_6;
48
1151
  d_subOptions.quantifiers.sygus = false;
49
1151
}
50
51
1151
SynthVerify::~SynthVerify() {}
52
53
1714
Result SynthVerify::verify(Node query,
54
                           const std::vector<Node>& vars,
55
                           std::vector<Node>& mvs)
56
{
57
1714
  NodeManager* nm = NodeManager::currentNM();
58
  // simplify the lemma based on the term database sygus utility
59
1714
  query = d_tds->rewriteNode(query);
60
  // eagerly unfold applications of evaluation function
61
1714
  Trace("cegqi-debug") << "pre-unfold counterexample : " << query << std::endl;
62
63
1714
  if (query.isConst())
64
  {
65
1295
    if (!query.getConst<bool>())
66
    {
67
1141
      return Result(Result::UNSAT);
68
    }
69
    // sat, but we need to get arbtirary model values below
70
  }
71
  else
72
  {
73
    // if non-constant, we may need to add recursive function definitions
74
419
    FunDefEvaluator* feval = d_tds->getFunDefEvaluator();
75
419
    const std::vector<Node>& fdefs = feval->getDefinitions();
76
419
    if (!fdefs.empty())
77
    {
78
      // Get the relevant definitions based on the symbols in the query.
79
      // Notice in some cases, this may have the effect of making the subcall
80
      // involve no recursive function definitions at all, in which case the
81
      // subcall to verification may be decidable, in which case the call
82
      // below is guaranteed to generate a new counterexample point.
83
66
      std::unordered_set<Node> syms;
84
33
      expr::getSymbols(query, syms);
85
66
      std::vector<Node> qconj;
86
33
      qconj.push_back(query);
87
211
      for (const Node& f : syms)
88
      {
89
356
        Node q = feval->getDefinitionFor(f);
90
178
        if (!q.isNull())
91
        {
92
35
          qconj.push_back(q);
93
        }
94
      }
95
33
      query = nm->mkAnd(qconj);
96
33
      Trace("cegqi-debug") << "query is " << query << std::endl;
97
    }
98
  }
99
573
  Trace("sygus-engine") << "  *** Verify with subcall..." << std::endl;
100
1146
  Result r = checkWithSubsolver(query, vars, mvs, &d_subOptions);
101
573
  Trace("sygus-engine") << "  ...got " << r << std::endl;
102
573
  if (r.asSatisfiabilityResult().isSat() == Result::SAT)
103
  {
104
423
    if (Trace.isOn("sygus-engine"))
105
    {
106
      Trace("sygus-engine") << "  * Verification lemma failed for:\n   ";
107
      for (unsigned i = 0, size = vars.size(); i < size; i++)
108
      {
109
        Trace("sygus-engine") << vars[i] << " -> " << mvs[i] << " ";
110
      }
111
      Trace("sygus-engine") << std::endl;
112
    }
113
423
    if (Configuration::isAssertionBuild())
114
    {
115
      // the values for the query should be a complete model
116
      Node squery =
117
846
          query.substitute(vars.begin(), vars.end(), mvs.begin(), mvs.end());
118
423
      Trace("cegqi-debug") << "...squery : " << squery << std::endl;
119
423
      squery = Rewriter::rewrite(squery);
120
423
      Trace("cegqi-debug") << "...rewrites to : " << squery << std::endl;
121
423
      Assert(options::sygusRecFun()
122
             || (squery.isConst() && squery.getConst<bool>()));
123
    }
124
  }
125
573
  return r;
126
}
127
128
}  // namespace quantifiers
129
}  // namespace theory
130
29340
}  // namespace cvc5