/****************************************************************************** * Top contributors (to current version): * Andrew Reynolds, Mathias Preiner, Aina Niemetz * * 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. * **************************************************************************** * * Utilities used for querying about equality information. */ #include "theory/quantifiers/equality_query.h" #include "options/quantifiers_options.h" #include "theory/quantifiers/first_order_model.h" #include "theory/quantifiers/quantifiers_attributes.h" #include "theory/quantifiers/quantifiers_state.h" #include "theory/quantifiers/term_util.h" using namespace std; using namespace cvc5::kind; using namespace cvc5::context; namespace cvc5 { namespace theory { namespace quantifiers { EqualityQuery::EqualityQuery(QuantifiersState& qs, FirstOrderModel* m) : d_qstate(qs), d_model(m), d_eqi_counter(qs.getSatContext()), d_reset_count(0) { } EqualityQuery::~EqualityQuery() {} bool EqualityQuery::reset(Theory::Effort e) { d_int_rep.clear(); d_reset_count++; return true; } Node EqualityQuery::getInternalRepresentative(Node a, Node q, size_t index) { Assert(q.isNull() || q.getKind() == FORALL); Node r = d_qstate.getRepresentative(a); if( options::finiteModelFind() ){ if( r.isConst() && quantifiers::TermUtil::containsUninterpretedConstant( r ) ){ //map back from values assigned by model, if any if (d_model != nullptr) { Node tr = d_model->getRepSet()->getTermForRepresentative(r); if (!tr.isNull()) { r = tr; r = d_qstate.getRepresentative(r); }else{ if( r.getType().isSort() ){ Trace("internal-rep-warn") << "No representative for UF constant." << std::endl; //should never happen : UF constants should never escape model Assert(false); } } } } } TypeNode v_tn = q.isNull() ? a.getType() : q[0][index].getType(); if (options::quantRepMode() == options::QuantRepMode::EE) { int32_t score = getRepScore(r, q, index, v_tn); if (score >= 0) { return r; } // if we are not a valid representative, try to select one below } std::map& v_int_rep = d_int_rep[v_tn]; std::map::const_iterator itir = v_int_rep.find(r); if (itir != v_int_rep.end()) { return itir->second; } // find best selection for representative Node r_best; std::vector eqc; d_qstate.getEquivalenceClass(r, eqc); Trace("internal-rep-select") << "Choose representative for equivalence class : " << eqc << ", type = " << v_tn << std::endl; int32_t r_best_score = -1; for (const Node& n : eqc) { int32_t score = getRepScore(n, q, index, v_tn); if (score != -2) { if (r_best.isNull() || (score >= 0 && (r_best_score < 0 || score < r_best_score))) { r_best = n; r_best_score = score; } } } if (r_best.isNull()) { Trace("internal-rep-warn") << "No valid choice for representative in eqc class " << eqc << std::endl; return Node::null(); } // now, make sure that no other member of the class is an instance std::unordered_map cache; r_best = getInstance(r_best, eqc, cache); // store that this representative was chosen at this point if (d_rep_score.find(r_best) == d_rep_score.end()) { d_rep_score[r_best] = d_reset_count; } Trace("internal-rep-select") << "...Choose " << r_best << " with score " << r_best_score << " and type " << r_best.getType() << std::endl; Assert(r_best.getType().isSubtypeOf(v_tn)); v_int_rep[r] = r_best; if (Trace.isOn("internal-rep-debug")) { if (r_best != a) { Trace("internal-rep-debug") << "rep( " << a << " ) = " << r << ", " << std::endl; Trace("internal-rep-debug") << "int_rep( " << a << " ) = " << r_best << ", " << std::endl; } } return r_best; } //helper functions Node EqualityQuery::getInstance( Node n, const std::vector& eqc, std::unordered_map& cache) { if(cache.find(n) != cache.end()) { return cache[n]; } for( size_t i=0; i