summaryrefslogtreecommitdiff
path: root/src/theory/quantifiers/sygus/synth_verify.cpp
blob: 43131ac24b5b1aa7d529492ebe74611ff5bae748 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/******************************************************************************
 * Top contributors (to current version):
 *   Andrew Reynolds
 *
 * This file is part of the cvc5 project.
 *
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
 * in the top-level source directory and their institutional affiliations.
 * All rights reserved.  See the file COPYING in the top-level source
 * directory for licensing information.
 * ****************************************************************************
 *
 * Class for verifying queries for synthesis solutions
 */

#include "theory/quantifiers/sygus/synth_verify.h"

#include "expr/node_algorithm.h"
#include "options/base_options.h"
#include "options/quantifiers_options.h"
#include "smt/smt_engine_scope.h"
#include "smt/smt_statistics_registry.h"
#include "theory/quantifiers/first_order_model.h"
#include "theory/quantifiers/sygus/term_database_sygus.h"
#include "theory/rewriter.h"
#include "theory/smt_engine_subsolver.h"

using namespace cvc5::kind;
using namespace std;

namespace cvc5 {
namespace theory {
namespace quantifiers {

SynthVerify::SynthVerify(TermDbSygus* tds) : d_tds(tds)
{
  // determine the options to use for the verification subsolvers we spawn
  // we start with the options of the current SmtEngine
  SmtEngine* smtCurr = smt::currentSmtEngine();
  d_subOptions.copyValues(smtCurr->getOptions());
  // limit the number of instantiation rounds on subcalls
  d_subOptions.quantifiers.instMaxRounds =
      d_subOptions.quantifiers.sygusVerifyInstMaxRounds;
  // Disable sygus on the subsolver. This is particularly important since it
  // ensures that recursive function definitions have the standard ownership
  // instead of being claimed by sygus in the subsolver.
  d_subOptions.base.inputLanguage = language::input::LANG_SMTLIB_V2_6;
  d_subOptions.quantifiers.sygus = false;
}

SynthVerify::~SynthVerify() {}

Result SynthVerify::verify(Node query,
                           const std::vector<Node>& vars,
                           std::vector<Node>& mvs)
{
  NodeManager* nm = NodeManager::currentNM();
  // simplify the lemma based on the term database sygus utility
  query = d_tds->rewriteNode(query);
  // eagerly unfold applications of evaluation function
  Trace("cegqi-debug") << "pre-unfold counterexample : " << query << std::endl;

  if (query.isConst())
  {
    if (!query.getConst<bool>())
    {
      return Result(Result::UNSAT);
    }
    // sat, but we need to get arbtirary model values below
  }
  else
  {
    // if non-constant, we may need to add recursive function definitions
    FunDefEvaluator* feval = d_tds->getFunDefEvaluator();
    const std::vector<Node>& fdefs = feval->getDefinitions();
    if (!fdefs.empty())
    {
      // Get the relevant definitions based on the symbols in the query.
      // Notice in some cases, this may have the effect of making the subcall
      // involve no recursive function definitions at all, in which case the
      // subcall to verification may be decidable, in which case the call
      // below is guaranteed to generate a new counterexample point.
      std::unordered_set<Node> syms;
      expr::getSymbols(query, syms);
      std::vector<Node> qconj;
      qconj.push_back(query);
      for (const Node& f : syms)
      {
        Node q = feval->getDefinitionFor(f);
        if (!q.isNull())
        {
          qconj.push_back(q);
        }
      }
      query = nm->mkAnd(qconj);
      Trace("cegqi-debug") << "query is " << query << std::endl;
    }
  }
  Trace("sygus-engine") << "  *** Verify with subcall..." << std::endl;
  Result r = checkWithSubsolver(query, vars, mvs, &d_subOptions);
  Trace("sygus-engine") << "  ...got " << r << std::endl;
  if (r.asSatisfiabilityResult().isSat() == Result::SAT)
  {
    if (Trace.isOn("sygus-engine"))
    {
      Trace("sygus-engine") << "  * Verification lemma failed for:\n   ";
      for (unsigned i = 0, size = vars.size(); i < size; i++)
      {
        Trace("sygus-engine") << vars[i] << " -> " << mvs[i] << " ";
      }
      Trace("sygus-engine") << std::endl;
    }
    if (Configuration::isAssertionBuild())
    {
      // the values for the query should be a complete model
      Node squery =
          query.substitute(vars.begin(), vars.end(), mvs.begin(), mvs.end());
      Trace("cegqi-debug") << "...squery : " << squery << std::endl;
      squery = Rewriter::rewrite(squery);
      Trace("cegqi-debug") << "...rewrites to : " << squery << std::endl;
      Assert(options::sygusRecFun()
             || (squery.isConst() && squery.getConst<bool>()));
    }
  }
  return r;
}

}  // namespace quantifiers
}  // namespace theory
}  // namespace cvc5
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback