GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/theory/quantifiers/fmf/model_builder.cpp Lines: 38 71 53.5 %
Date: 2021-05-22 Branches: 45 234 19.2 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Aina Niemetz, Mathias Preiner
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
 * Implementation of model builder class.
14
 */
15
16
#include "theory/quantifiers/fmf/model_builder.h"
17
18
#include "options/quantifiers_options.h"
19
#include "theory/quantifiers/first_order_model.h"
20
#include "theory/quantifiers/fmf/model_engine.h"
21
#include "theory/quantifiers/instantiate.h"
22
#include "theory/quantifiers/quant_rep_bound_ext.h"
23
#include "theory/quantifiers/quantifiers_state.h"
24
25
using namespace std;
26
using namespace cvc5;
27
using namespace cvc5::kind;
28
using namespace cvc5::context;
29
using namespace cvc5::theory;
30
using namespace cvc5::theory::quantifiers;
31
32
9460
QModelBuilder::QModelBuilder(QuantifiersState& qs,
33
                             QuantifiersInferenceManager& qim,
34
                             QuantifiersRegistry& qr,
35
9460
                             TermRegistry& tr)
36
    : TheoryEngineModelBuilder(),
37
      d_addedLemmas(0),
38
      d_triedLemmas(0),
39
      d_qstate(qs),
40
      d_qim(qim),
41
      d_qreg(qr),
42
      d_treg(tr),
43
9460
      d_model(nullptr)
44
{
45
9460
}
46
47
8119
void QModelBuilder::finishInit()
48
{
49
  // allocate the default model
50
8119
  d_modelAloc.reset(new FirstOrderModel(d_qstate, d_qreg, d_treg));
51
8119
  d_model = d_modelAloc.get();
52
8119
}
53
54
11989
bool QModelBuilder::optUseModel() {
55
11989
  return options::mbqiMode() != options::MbqiMode::NONE || options::fmfBound();
56
}
57
58
9987
bool QModelBuilder::preProcessBuildModel(TheoryModel* m) {
59
9987
  return preProcessBuildModelStd( m );
60
}
61
62
11932
bool QModelBuilder::preProcessBuildModelStd(TheoryModel* m) {
63
11932
  d_addedLemmas = 0;
64
11932
  d_triedLemmas = 0;
65
11932
  if (options::fmfFunWellDefinedRelevant())
66
  {
67
    //traverse equality engine
68
124
    std::map< TypeNode, bool > eqc_usort;
69
    eq::EqClassesIterator eqcs_i =
70
62
        eq::EqClassesIterator(m->getEqualityEngine());
71
3374
    while( !eqcs_i.isFinished() ){
72
3312
      TypeNode tr = (*eqcs_i).getType();
73
1656
      eqc_usort[tr] = true;
74
1656
      ++eqcs_i;
75
    }
76
    //look at quantified formulas
77
394
    for (size_t i = 0, nquant = d_model->getNumAssertedQuantifiers();
78
394
         i < nquant;
79
         i++)
80
    {
81
664
      Node q = d_model->getAssertedQuantifier(i, true);
82
332
      if (d_model->isQuantifierActive(q))
83
      {
84
        //check if any of these quantified formulas can be set inactive
85
332
        if (q[0].getNumChildren() == 1)
86
        {
87
664
          TypeNode tn = q[0][0].getType();
88
332
          if (tn.getAttribute(AbsTypeFunDefAttribute()))
89
          {
90
            // we are allowed to assume the introduced type is empty
91
314
            if (eqc_usort.find(tn) == eqc_usort.end())
92
            {
93
72
              Trace("model-engine-debug")
94
36
                  << "Irrelevant function definition : " << q << std::endl;
95
36
              d_model->setQuantifierActive(q, false);
96
            }
97
          }
98
        }
99
      }
100
    }
101
  }
102
11932
  return true;
103
}
104
105
208
void QModelBuilder::debugModel( TheoryModel* m ){
106
  //debug the model: cycle through all instantiations for all quantifiers, report ones that are not true
107
208
  if( Trace.isOn("quant-check-model") ){
108
    FirstOrderModel* fm = d_model;
109
    Trace("quant-check-model") << "Testing quantifier instantiations..." << std::endl;
110
    int tests = 0;
111
    int bad = 0;
112
    QuantifiersBoundInference& qbi = d_qreg.getQuantifiersBoundInference();
113
    Instantiate* inst = d_qim.getInstantiate();
114
    for( unsigned i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
115
      Node f = fm->getAssertedQuantifier( i );
116
      std::vector< Node > vars;
117
      for( unsigned j=0; j<f[0].getNumChildren(); j++ ){
118
        vars.push_back( f[0][j] );
119
      }
120
      QRepBoundExt qrbe(qbi, fm);
121
      RepSetIterator riter(m->getRepSet(), &qrbe);
122
      if( riter.setQuantifier( f ) ){
123
        while( !riter.isFinished() ){
124
          tests++;
125
          std::vector< Node > terms;
126
          for (unsigned k = 0; k < riter.getNumTerms(); k++)
127
          {
128
            terms.push_back( riter.getCurrentTerm( k ) );
129
          }
130
          Node n = inst->getInstantiation(f, vars, terms);
131
          Node val = m->getValue(n);
132
          if (!val.isConst() || !val.getConst<bool>())
133
          {
134
            Trace("quant-check-model") << "*******  Instantiation " << n << " for " << std::endl;
135
            Trace("quant-check-model") << "         " << f << std::endl;
136
            Trace("quant-check-model") << "         Evaluates to " << val << std::endl;
137
            bad++;
138
          }
139
          riter.increment();
140
        }
141
        Trace("quant-check-model") << "Tested " << tests << " instantiations";
142
        if( bad>0 ){
143
          Trace("quant-check-model") << ", " << bad << " failed" << std::endl;
144
        }
145
        Trace("quant-check-model") << "." << std::endl;
146
      }else{
147
        if( riter.isIncomplete() ){
148
          Trace("quant-check-model") << "Warning: Could not test quantifier " << f << std::endl;
149
        }
150
      }
151
    }
152
  }
153
208
}
154
37654
FirstOrderModel* QModelBuilder::getModel() { return d_model; }