GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/sygus/synth_verify.cpp Lines: 45 49 91.8 %
Date: 2021-09-15 Branches: 84 190 44.2 %

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/arith_options.h"
20
#include "options/base_options.h"
21
#include "options/quantifiers_options.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
1233
SynthVerify::SynthVerify(const Options& opts,
36
                         const LogicInfo& logicInfo,
37
1233
                         TermDbSygus* tds)
38
1233
    : d_tds(tds), d_subLogicInfo(logicInfo)
39
{
40
  // determine the options to use for the verification subsolvers we spawn
41
  // we start with the provided options
42
1233
  d_subOptions.copyValues(opts);
43
  // limit the number of instantiation rounds on subcalls
44
2466
  d_subOptions.quantifiers.instMaxRounds =
45
2466
      d_subOptions.quantifiers.sygusVerifyInstMaxRounds;
46
  // Disable sygus on the subsolver. This is particularly important since it
47
  // ensures that recursive function definitions have the standard ownership
48
  // instead of being claimed by sygus in the subsolver.
49
1233
  d_subOptions.base.inputLanguage = Language::LANG_SMTLIB_V2_6;
50
1233
  d_subOptions.quantifiers.sygus = false;
51
  // use tangent planes by default, since we want to put effort into
52
  // the verification step for sygus queries with non-linear arithmetic
53
1233
  if (!d_subOptions.arith.nlExtTangentPlanesWasSetByUser)
54
  {
55
1228
    d_subOptions.arith.nlExtTangentPlanes = true;
56
  }
57
1233
}
58
59
1231
SynthVerify::~SynthVerify() {}
60
61
1696
Result SynthVerify::verify(Node query,
62
                           const std::vector<Node>& vars,
63
                           std::vector<Node>& mvs)
64
{
65
1696
  NodeManager* nm = NodeManager::currentNM();
66
  // simplify the lemma based on the term database sygus utility
67
1696
  query = d_tds->rewriteNode(query);
68
  // eagerly unfold applications of evaluation function
69
1696
  Trace("cegqi-debug") << "pre-unfold counterexample : " << query << std::endl;
70
71
1696
  if (query.isConst())
72
  {
73
1320
    if (!query.getConst<bool>())
74
    {
75
1164
      return Result(Result::UNSAT);
76
    }
77
    // sat, but we need to get arbtirary model values below
78
  }
79
  else
80
  {
81
    // if non-constant, we may need to add recursive function definitions
82
376
    FunDefEvaluator* feval = d_tds->getFunDefEvaluator();
83
376
    const std::vector<Node>& fdefs = feval->getDefinitions();
84
376
    if (!fdefs.empty())
85
    {
86
      // Get the relevant definitions based on the symbols in the query.
87
      // Notice in some cases, this may have the effect of making the subcall
88
      // involve no recursive function definitions at all, in which case the
89
      // subcall to verification may be decidable, in which case the call
90
      // below is guaranteed to generate a new counterexample point.
91
66
      std::unordered_set<Node> syms;
92
33
      expr::getSymbols(query, syms);
93
66
      std::vector<Node> qconj;
94
33
      qconj.push_back(query);
95
211
      for (const Node& f : syms)
96
      {
97
356
        Node q = feval->getDefinitionFor(f);
98
178
        if (!q.isNull())
99
        {
100
35
          qconj.push_back(q);
101
        }
102
      }
103
33
      query = nm->mkAnd(qconj);
104
33
      Trace("cegqi-debug") << "query is " << query << std::endl;
105
    }
106
  }
107
532
  Trace("sygus-engine") << "  *** Verify with subcall..." << std::endl;
108
1064
  Result r = checkWithSubsolver(query, vars, mvs, d_subOptions, d_subLogicInfo);
109
532
  Trace("sygus-engine") << "  ...got " << r << std::endl;
110
532
  if (r.asSatisfiabilityResult().isSat() == Result::SAT)
111
  {
112
402
    if (Trace.isOn("sygus-engine"))
113
    {
114
      Trace("sygus-engine") << "  * Verification lemma failed for:\n   ";
115
      for (unsigned i = 0, size = vars.size(); i < size; i++)
116
      {
117
        Trace("sygus-engine") << vars[i] << " -> " << mvs[i] << " ";
118
      }
119
      Trace("sygus-engine") << std::endl;
120
    }
121
402
    if (Configuration::isAssertionBuild())
122
    {
123
      // the values for the query should be a complete model
124
      Node squery =
125
804
          query.substitute(vars.begin(), vars.end(), mvs.begin(), mvs.end());
126
402
      Trace("cegqi-debug") << "...squery : " << squery << std::endl;
127
402
      squery = Rewriter::rewrite(squery);
128
402
      Trace("cegqi-debug") << "...rewrites to : " << squery << std::endl;
129
402
      Assert(options::sygusRecFun()
130
             || (squery.isConst() && squery.getConst<bool>()));
131
    }
132
  }
133
532
  return r;
134
}
135
136
}  // namespace quantifiers
137
}  // namespace theory
138
29577
}  // namespace cvc5