GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/sygus/synth_verify.cpp Lines: 44 48 91.7 %
Date: 2021-11-07 Branches: 87 196 44.4 %

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