--- /dev/null
+This branch is used for development of the finite model finding mode of CVC4.
/* class DeclareFunctionCommand */
-DeclareFunctionCommand::DeclareFunctionCommand(const std::string& id, Type t) throw() :
+DeclareFunctionCommand::DeclareFunctionCommand(const std::string& id, Expr func, Type t) throw() :
DeclarationDefinitionCommand(id),
+ d_func(func),
d_type(t) {
}
void DeclareFunctionCommand::invoke(SmtEngine* smtEngine) throw() {
Dump("declarations") << *this;
+ smtEngine->addToModelFunction( d_func );
d_commandStatus = CommandSuccess::instance();
}
Command* DeclareFunctionCommand::exportTo(ExprManager* exprManager,
ExprManagerMapCollection& variableMap) {
- return new DeclareFunctionCommand(d_symbol,
+ return new DeclareFunctionCommand(d_symbol, d_func.exportTo(exprManager, variableMap),
d_type.exportTo(exprManager, variableMap));
}
Command* DeclareFunctionCommand::clone() const {
- return new DeclareFunctionCommand(d_symbol, d_type);
+ return new DeclareFunctionCommand(d_symbol, d_func, d_type);
}
/* class DeclareTypeCommand */
void DeclareTypeCommand::invoke(SmtEngine* smtEngine) throw() {
Dump("declarations") << *this;
+ smtEngine->addToModelType( d_type );
d_commandStatus = CommandSuccess::instance();
}
return c;
}
+/* class GetModelCommand */
+
+GetModelCommand::GetModelCommand() throw() {
+}
+
+void GetModelCommand::invoke(SmtEngine* smtEngine) throw() {
+ try {
+ d_result = smtEngine->getModel();
+ d_smtEngine = smtEngine;
+ d_commandStatus = CommandSuccess::instance();
+ } catch(exception& e) {
+ d_commandStatus = new CommandFailure(e.what());
+ }
+}
+
+Model* GetModelCommand::getResult() const throw() {
+ return d_result;
+}
+
+void GetModelCommand::printResult(std::ostream& out) const throw() {
+ if(! ok()) {
+ this->Command::printResult(out);
+ } else {
+ d_smtEngine->printModel( out, d_result );
+ }
+}
+
+Command* GetModelCommand::exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap) {
+ GetModelCommand* c = new GetModelCommand();
+ c->d_result = d_result;
+ c->d_smtEngine = d_smtEngine;
+ return c;
+}
+
+Command* GetModelCommand::clone() const {
+ GetModelCommand* c = new GetModelCommand();
+ c->d_result = d_result;
+ c->d_smtEngine = d_smtEngine;
+ return c;
+}
+
/* class GetProofCommand */
GetProofCommand::GetProofCommand() throw() {
#include "util/sexpr.h"
#include "util/datatype.h"
#include "util/proof.h"
+#include "util/model.h"
namespace CVC4 {
class CVC4_PUBLIC DeclareFunctionCommand : public DeclarationDefinitionCommand {
protected:
+ Expr d_func;
Type d_type;
public:
- DeclareFunctionCommand(const std::string& id, Type type) throw();
+ DeclareFunctionCommand(const std::string& id, Expr func, Type type) throw();
~DeclareFunctionCommand() throw() {}
Type getType() const throw();
void invoke(SmtEngine* smtEngine) throw();
Command* clone() const;
};/* class GetAssignmentCommand */
+class CVC4_PUBLIC GetModelCommand : public Command {
+protected:
+ Model* d_result;
+ SmtEngine* d_smtEngine;
+public:
+ GetModelCommand() throw();
+ ~GetModelCommand() throw() {}
+ void invoke(SmtEngine* smtEngine) throw();
+ Model* getResult() const throw();
+ void printResult(std::ostream& out) const throw();
+ Command* exportTo(ExprManager* exprManager, ExprManagerMapCollection& variableMap);
+ Command* clone() const;
+};/* class GetModelCommand */
+
class CVC4_PUBLIC GetProofCommand : public Command {
protected:
Proof* d_result;
}
} else {
Debug("parser") << " " << *i << " not declared" << std::endl;
- PARSER_STATE->mkVar(*i, t);
+ Expr func = PARSER_STATE->mkVar(*i, t);
if(topLevel) {
- Command* decl = new DeclareFunctionCommand(*i, t);
+ Command* decl = new DeclareFunctionCommand(*i, func, t);
seq->addCommand(decl);
}
}
} else {
t = EXPR_MANAGER->mkFunctionType(sorts);
}
- PARSER_STATE->mkVar(name, t);
- smt_command = new DeclareFunctionCommand(name, t);
+ Expr func = PARSER_STATE->mkVar(name, t);
+ smt_command = new DeclareFunctionCommand(name, func, t);
}
;
} else {
t = EXPR_MANAGER->mkPredicateType(p_sorts);
}
- PARSER_STATE->mkVar(name, t);
- smt_command = new DeclareFunctionCommand(name, t);
+ Expr func = PARSER_STATE->mkVar(name, t);
+ smt_command = new DeclareFunctionCommand(name, func, t);
}
;
if( sorts.size() > 0 ) {
t = EXPR_MANAGER->mkFunctionType(sorts, t);
}
- PARSER_STATE->mkVar(name, t);
- $cmd = new DeclareFunctionCommand(name, t); }
+ Expr func = PARSER_STATE->mkVar(name, t);
+ $cmd = new DeclareFunctionCommand(name, func, t); }
| /* function definition */
DEFINE_FUN_TOK { PARSER_STATE->checkThatLogicIsSet(); }
symbol[name,CHECK_UNDECLARED,SYM_VARIABLE]
LPAREN_TOK ( LPAREN_TOK datatypeDef[dts] RPAREN_TOK )+ RPAREN_TOK
{ PARSER_STATE->popScope();
cmd = new DatatypeDeclarationCommand(PARSER_STATE->mkMutualDatatypeTypes(dts)); }
+ | /* get model */
+ GET_MODEL_TOK { PARSER_STATE->checkThatLogicIsSet(); }
+ { cmd = new GetModelCommand; }
| ECHO_TOK
( simpleSymbolicExpr[sexpr]
{ std::stringstream ss;
// extended commands
DECLARE_DATATYPES_TOK : 'declare-datatypes';
+GET_MODEL_TOK : 'get-model';
ECHO_TOK : 'echo';
// attributes
//Conversion from rational to unsorted
t = em->mkFunctionType(em->realType(), d_unsorted);
d_rtu_op = em->mkVar("$$rtu",t);
- preemptCommand(new DeclareFunctionCommand("$$rtu", t));
+ preemptCommand(new DeclareFunctionCommand("$$rtu", d_rtu_op, t));
//Conversion from unsorted to rational
t = em->mkFunctionType(d_unsorted, em->realType());
d_utr_op = em->mkVar("$$utr",t);
- preemptCommand(new DeclareFunctionCommand("$$utur", t));
+ preemptCommand(new DeclareFunctionCommand("$$utur", d_utr_op, t));
}
// Add the inverse in order to show that over the elements that
// appear in the problem there is a bijection between unsorted and
//Conversion from string to unsorted
t = em->mkFunctionType(em->stringType(), d_unsorted);
d_stu_op = em->mkVar("$$stu",t);
- preemptCommand(new DeclareFunctionCommand("$$stu", t));
+ preemptCommand(new DeclareFunctionCommand("$$stu", d_stu_op, t));
//Conversion from unsorted to string
t = em->mkFunctionType(d_unsorted, em->stringType());
d_uts_op = em->mkVar("$$uts",t);
- preemptCommand(new DeclareFunctionCommand("$$uts", t));
+ preemptCommand(new DeclareFunctionCommand("$$uts", d_uts_op, t));
}
// Add the inverse in order to show that over the elements that
// appear in the problem there is a bijection between unsorted and
} else {
Type t = term ? d_unsorted : getExprManager()->booleanType();
expr = mkVar(name,t,true); //levelZero
- preemptCommand(new DeclareFunctionCommand(name, t));
+ preemptCommand(new DeclareFunctionCommand(name, expr, t));
}
} else { // Its an application
if(isDeclared(name)){ //already appeared
Type t = term ? d_unsorted : getExprManager()->booleanType();
t = getExprManager()->mkFunctionType(sorts, t);
expr = mkVar(name,t,true); //levelZero
- preemptCommand(new DeclareFunctionCommand(name, t));
+ preemptCommand(new DeclareFunctionCommand(name, expr, t));
}
expr = getExprManager()->mkExpr(kind::APPLY_UF, expr, args);
}
const Integer& x = bv.getValue();
unsigned n = bv.getSize();
out << "(_ ";
- out << "bv" << x <<" " << n;
- out << ")";
+ out << "bv" << x <<" " << n;
+ out << ")";
// //out << "#b";
// while(n-- > 0) {
// TODO user patterns
break;
+ //function models
+ case kind::FUNCTION_MODEL:
+ break;
+ case kind::FUNCTION_CASE_SPLIT:
+ break;
+ case kind::FUNCTION_CASE:
+ out << "if ";
+ break;
default:
// fall back on however the kind prints itself; this probably
// won't be SMT-LIB v2 compliant, but it will be clear from the
#include "theory/theory_traits.h"
#include "theory/logic_info.h"
#include "util/ite_removal.h"
+#include "theory/model.h"
using namespace std;
using namespace CVC4;
} else if(key == ":produce-unsat-cores") {
throw BadOptionException();
} else if(key == ":produce-models") {
- throw BadOptionException();
+ //throw BadOptionException();
+ const_cast<Options*>( Options::s_current )->produceModels = true;
} else if(key == ":produce-assignments") {
throw BadOptionException();
} else {
for (unsigned i = 0; i < d_assertionsToCheck.size(); ++ i) {
d_assertionsToCheck[i] = Rewriter::rewrite(d_assertionsToCheck[i]);
}
-
+
}
void SmtEnginePrivate::staticLearning() {
expandDefinitions(d_assertionsToPreprocess[i], cache);
}
}
-
+
// Apply the substitutions we already have, and normalize
Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
<< "applying substitutions" << endl;
throw ModalException(msg);
}
if(d_status.isNull() ||
- d_status.asSatisfiabilityResult() != Result::SAT ||
+ d_status.asSatisfiabilityResult() == Result::UNSAT ||
d_problemExtended) {
const char* msg =
- "Cannot get value unless immediately preceded by SAT/INVALID response.";
+ "Cannot get value unless immediately preceded by SAT/INVALID or UNKNOWN response.";
throw ModalException(msg);
}
- if(type.isFunction() || type.isPredicate() ||
- type.isKind() || type.isSortConstructor()) {
+ if(type.isKind() || type.isSortConstructor()) {
const char* msg =
- "Cannot get value of a function, predicate, or sort.";
+ "Cannot get value of a sort.";
throw ModalException(msg);
}
n = Rewriter::rewrite(n);
Trace("smt") << "--- getting value of " << n << endl;
- Node resultNode = d_theoryEngine->getValue(n);
-
+ theory::TheoryModel* m = d_theoryEngine->getModel();
+ Node resultNode;
+ if( m ){
+ resultNode = m->getValue( n );
+ }
+ Trace("smt") << "--- got value " << n << " = " << resultNode << endl;
// type-check the result we got
- Assert(resultNode.isNull() || resultNode.getType() == n.getType());
+ Assert(resultNode.isNull() || resultNode.getType().isSubtypeOf( n.getType() ));
return Expr(d_exprManager, new Node(resultNode));
}
throw ModalException(msg);
}
if(d_status.isNull() ||
- d_status.asSatisfiabilityResult() != Result::SAT ||
+ d_status.asSatisfiabilityResult() == Result::UNSAT ||
d_problemExtended) {
const char* msg =
"Cannot get the current assignment unless immediately "
- "preceded by SAT/INVALID response.";
+ "preceded by SAT/INVALID or UNKNOWN response.";
throw ModalException(msg);
}
Node n = Rewriter::rewrite(*i);
Trace("smt") << "--- getting value of " << n << endl;
- Node resultNode = d_theoryEngine->getValue(n);
+ theory::TheoryModel* m = d_theoryEngine->getModel();
+ Node resultNode;
+ if( m ){
+ resultNode = m->getValue( n );
+ }
// type-check the result we got
Assert(resultNode.isNull() || resultNode.getType() == boolType);
return SExpr(sexprs);
}
+
+void SmtEngine::addToModelType( Type& t ){
+ Trace("smt") << "SMT addToModelType(" << t << ")" << endl;
+ NodeManagerScope nms(d_nodeManager);
+ if( Options::current()->produceModels ) {
+ d_theoryEngine->getModel()->addDefineType( TypeNode::fromType( t ) );
+ }
+}
+
+void SmtEngine::addToModelFunction( Expr& e ){
+ Trace("smt") << "SMT addToModelFunction(" << e << ")" << endl;
+ NodeManagerScope nms(d_nodeManager);
+ if( Options::current()->produceModels ) {
+ d_theoryEngine->getModel()->addDefineFunction( e.getNode() );
+ }
+}
+
+
+Model* SmtEngine::getModel() throw(ModalException, AssertionException){
+ Trace("smt") << "SMT getModel()" << endl;
+ NodeManagerScope nms(d_nodeManager);
+
+ if(!Options::current()->produceModels) {
+ const char* msg =
+ "Cannot get value when produce-models options is off.";
+ throw ModalException(msg);
+ }
+ if(d_status.isNull() ||
+ d_status.asSatisfiabilityResult() == Result::UNSAT ||
+ d_problemExtended) {
+ const char* msg =
+ "Cannot get the current model unless immediately "
+ "preceded by SAT/INVALID or UNKNOWN response.";
+ throw ModalException(msg);
+ }
+
+ return d_theoryEngine->getModel();
+}
+
Proof* SmtEngine::getProof() throw(ModalException, AssertionException) {
Trace("smt") << "SMT getProof()" << endl;
NodeManagerScope nms(d_nodeManager);
return d_exprManager->d_nodeManager->getStatisticsRegistry();
}
+void SmtEngine::printModel( std::ostream& out, Model* m ){
+ NodeManagerScope nms(d_nodeManager);
+ m->toStream(out);
+}
+
}/* CVC4 namespace */
#include "expr/expr.h"
#include "expr/expr_manager.h"
#include "util/proof.h"
+#include "util/model.h"
#include "smt/bad_option_exception.h"
#include "smt/modal_exception.h"
#include "smt/no_such_function_exception.h"
*/
SExpr getAssignment() throw(ModalException, AssertionException);
+ /**
+ * Add to Model Type. This is used for recording which types should be reported
+ * during a get-model call.
+ */
+ void addToModelType( Type& t );
+
+ /**
+ * Add to Model Function. This is used for recording which functions should be reported
+ * during a get-model call.
+ */
+ void addToModelFunction( Expr& e );
+
+ /**
+ * Get the model (only if immediately preceded by a SAT
+ * or INVALID query). Only permitted if CVC4 was built with model
+ * support and produce-models is on.
+ */
+ Model* getModel() throw(ModalException, AssertionException);
+
/**
* Get the last proof (only if immediately preceded by an UNSAT
* or VALID query). Only permitted if CVC4 was built with proof
return d_status;
}
+ /**
+ * print model function (need this?)
+ */
+ void printModel( std::ostream& out, Model* m );
+
};/* class SmtEngine */
}/* CVC4 namespace */
inst_match_impl.h \
inst_match.cpp \
trigger.h \
- trigger.cpp
+ trigger.cpp \
+ model.h \
+ model.cpp
nodist_libtheory_la_SOURCES = \
rewriter_tables.h \
#include "theory/arith/constraint.h"
#include "theory/arith/theory_arith.h"
#include "theory/arith/normal_form.h"
+#include "theory/model.h"
#include <stdint.h>
d_qflraStatus = Result::UNSAT;
if(previous == Result::SAT){
++d_statistics.d_revertsOnConflicts;
- Debug("arith::bt") << "clearing here " << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
+ Debug("arith::bt") << "clearing here " << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
revertOutOfConflict();
d_simplex.clearQueue();
}else{
++d_statistics.d_commitsOnConflicts;
- Debug("arith::bt") << "committing here " << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
+ Debug("arith::bt") << "committing here " << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
d_partialModel.commitAssignmentChanges();
revertOutOfConflict();
}
++d_statistics.d_nontrivialSatChecks;
}
- Debug("arith::bt") << "committing sap inConflit" << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
+ Debug("arith::bt") << "committing sap inConflit" << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
d_partialModel.commitAssignmentChanges();
d_unknownsInARow = 0;
if(Debug.isOn("arith::consistency")){
++d_unknownsInARow;
++(d_statistics.d_unknownChecks);
Assert(!fullEffort(effortLevel));
- Debug("arith::bt") << "committing unknown" << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
+ Debug("arith::bt") << "committing unknown" << " " << newFacts << " " << previous << " " << d_qflraStatus << endl;
d_partialModel.commitAssignmentChanges();
d_statistics.d_maxUnknownsInARow.maxAssign(d_unknownsInARow);
break;
}
}
-Node TheoryArith::getValue(TNode n) {
- NodeManager* nodeManager = NodeManager::currentNM();
+void TheoryArith::collectModelInfo( TheoryModel* m ){
- Assert(d_qflraStatus == Result::SAT);
-
- switch(n.getKind()) {
- case kind::VARIABLE: {
- ArithVar var = d_arithvarNodeMap.asArithVar(n);
-
- DeltaRational drat = d_partialModel.getAssignment(var);
- const Rational& delta = d_partialModel.getDelta();
- Debug("getValue") << n << " " << drat << " " << delta << endl;
- return nodeManager->
- mkConst( drat.getNoninfinitesimalPart() +
- drat.getInfinitesimalPart() * delta );
- }
-
- case kind::EQUAL: // 2 args
- return nodeManager->
- mkConst( d_valuation.getValue(n[0]) == d_valuation.getValue(n[1]) );
-
- case kind::PLUS: { // 2+ args
- Rational value(0);
- for(TNode::iterator i = n.begin(),
- iend = n.end();
- i != iend;
- ++i) {
- value += d_valuation.getValue(*i).getConst<Rational>();
- }
- return nodeManager->mkConst(value);
- }
-
- case kind::MULT: { // 2+ args
- Rational value(1);
- for(TNode::iterator i = n.begin(),
- iend = n.end();
- i != iend;
- ++i) {
- value *= d_valuation.getValue(*i).getConst<Rational>();
- }
- return nodeManager->mkConst(value);
- }
-
- case kind::MINUS: // 2 args
- // should have been rewritten
- Unreachable();
-
- case kind::UMINUS: // 1 arg
- // should have been rewritten
- Unreachable();
-
- case kind::DIVISION: // 2 args
- return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() /
- d_valuation.getValue(n[1]).getConst<Rational>() );
-
- case kind::LT: // 2 args
- return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() <
- d_valuation.getValue(n[1]).getConst<Rational>() );
-
- case kind::LEQ: // 2 args
- return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() <=
- d_valuation.getValue(n[1]).getConst<Rational>() );
-
- case kind::GT: // 2 args
- return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() >
- d_valuation.getValue(n[1]).getConst<Rational>() );
-
- case kind::GEQ: // 2 args
- return nodeManager->mkConst( d_valuation.getValue(n[0]).getConst<Rational>() >=
- d_valuation.getValue(n[1]).getConst<Rational>() );
-
- default:
- Unhandled(n.getKind());
- }
}
bool TheoryArith::safeToReset() const {
void propagate(Effort e);
Node explain(TNode n);
- Node getValue(TNode n);
+ void collectModelInfo( TheoryModel* m );
void shutdown(){ }
#include "theory/arith/theory_arith_instantiator.h"
#include "theory/arith/theory_arith.h"
#include "theory/theory_engine.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
d_counter++;
}
-int InstStrategySimplex::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategySimplex::process( Node f, Theory::Effort effort, int e ){
if( e<2 ){
return STATUS_UNFINISHED;
}else if( e==2 ){
//
//}
//
-//int InstStrategySimplexUfMatch::process( Node f, int effort, int instLimit ){
+//int InstStrategySimplexUfMatch::process( Node f, int effort ){
// if( effort<2 ){
// return STATUS_UNFINISHED;
// }else if( effort==2 ){
// while( d_tableaux_ce_term_trigger[x]->getNextMatch() && !addedLemma ){
// InstMatch* m = d_tableaux_ce_term_trigger[x]->getCurrent();
// if( m->isComplete( f ) ){
-// if( d_quantEngine->addInstantiation( f, m, true ) ){
+// if( d_quantEngine->addInstantiation( f, m ) ){
// ++(d_th->d_statistics.d_instantiations_match_pure);
// ++(d_th->d_statistics.d_instantiations);
// addedLemma = true;
// //Debug("quant-arith") << std::endl;
// std::vector< Node > vars;
// std::vector< Node > matches;
-// for( int i=0; i<d_quantEngine->getNumInstantiationConstants( f ); i++ ){
-// Node ic = d_quantEngine->getInstantiationConstant( f, i );
+// for( int i=0; i<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
+// Node ic = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
// if( m->d_map[ ic ]!=Node::null() ){
// vars.push_back( ic );
// matches.push_back( m->d_map[ ic ] );
// ++(d_th->d_statistics.d_instantiations_match_var);
// }
// }else{
-// if( d_quantEngine->addInstantiation( f, m, true ) ){
+// if( d_quantEngine->addInstantiation( f, m ) ){
// addedLemma = true;
// ++(d_th->d_statistics.d_instantiations_match_no_var);
// ++(d_th->d_statistics.d_instantiations);
}
}
-int InstantiatorTheoryArith::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstantiatorTheoryArith::process( Node f, Theory::Effort effort, int e ){
Debug("quant-arith") << "Arith: Try to solve (" << effort << ") for " << f << "... " << std::endl;
return InstStrategy::STATUS_UNKNOWN;
}
Node f = d_quantEngine->getQuantifier( q );
Debug(c) << f << std::endl;
Debug(c) << " Inst constants: ";
- for( int i=0; i<(int)d_quantEngine->getNumInstantiationConstants( f ); i++ ){
+ for( int i=0; i<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); i++ ){
if( i>0 ){
Debug( c ) << ", ";
}
- Debug( c ) << d_quantEngine->getInstantiationConstant( f, i );
+ Debug( c ) << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i );
}
Debug(c) << std::endl;
Debug(c) << " Instantiation rows: ";
//use as instantiation value for var
m.d_map[ var ] = instVal;
Debug("quant-arith") << "Add instantiation " << m << std::endl;
- return d_quantEngine->addInstantiation( f, m, true );
+ return d_quantEngine->addInstantiation( f, m );
}
Node InstantiatorTheoryArith::getTableauxValue( Node n, bool minus_delta ){
Node d_negOne;
/** process functions */
void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
public:
InstStrategySimplex( InstantiatorTheoryArith* th, QuantifiersEngine* ie );
~InstStrategySimplex(){}
// /** trigger for instantiation rows */
// std::map< ArithVar, Trigger* > d_tableaux_ce_term_trigger;
//public:
-// InstStrategySimplexUfMatch( InstantiatorTheoryArith* th, QuantifiersEngine* ie ) :
+// InstStrategySimplexUfMatch( InstantiatorTheoryArith* th, QuantifiersEngine* ie ) :
// InstStrategy( ie ), d_th( th ){}
// ~InstStrategySimplexUfMatch(){}
// void resetInstantiationRound();
/** reset instantiation */
void processResetInstantiationRound( Theory::Effort effort );
/** process at effort */
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
/** add term to row */
void addTermToRow( ArithVar x, Node n, Node& f, NodeBuilder<>& t );
/** get delta for node */
#include "theory/rewriter.h"
#include "expr/command.h"
#include "theory/arrays/theory_arrays_instantiator.h"
+#include "theory/model.h"
using namespace std;
d_checkTimer("theory::arrays::checkTime"),
d_ppEqualityEngine(u, "theory::arrays::TheoryArraysPP"),
d_ppFacts(u),
- // d_ppCache(u),
+ // d_ppCache(u),
d_literalsToPropagate(c),
d_literalsToPropagateIndex(c, 0),
d_isPreRegistered(c),
for (j = leftWrites - 1; j > i; --j) {
index_j = write_j[1];
if (!ppDisequal(index_i, index_j)) {
- Node hyp2(index_i.getType() == nm->booleanType()?
+ Node hyp2(index_i.getType() == nm->booleanType()?
index_i.iffNode(index_j) : index_i.eqNode(index_j));
hyp << hyp2.notNode();
}
// MODEL GENERATION
/////////////////////////////////////////////////////////////////////////////
-
-Node TheoryArrays::getValue(TNode n)
-{
- // TODO: Implement this
- NodeManager* nodeManager = NodeManager::currentNM();
-
- switch(n.getKind()) {
-
- case kind::VARIABLE:
- Unhandled(kind::VARIABLE);
-
- case kind::EQUAL: // 2 args
- return nodeManager->
- mkConst( d_valuation.getValue(n[0]) == d_valuation.getValue(n[1]) );
-
- default:
- Unhandled(n.getKind());
- }
+void TheoryArrays::collectModelInfo( TheoryModel* m ){
+ m->assertEqualityEngine( &d_equalityEngine );
}
-
/////////////////////////////////////////////////////////////////////////////
// NOTIFICATIONS
/////////////////////////////////////////////////////////////////////////////
void TheoryArrays::check(Effort e) {
TimerStat::CodeTimer codeTimer(d_checkTimer);
- while (!done() && !d_conflict)
+ while (!done() && !d_conflict)
{
// Get all the assertions
Assertion assertion = get();
d_equalityEngine.assertEquality(eq2, true, d_true);
continue;
}
-
+
Node lem = nm->mkNode(kind::OR, eq2_r, eq1_r);
Trace("arrays-lem")<<"Arrays::addRowLemma adding "<<lem<<"\n";
private:
public:
- Node getValue(TNode n);
+ void collectModelInfo( TheoryModel* m );
/////////////////////////////////////////////////////////////////////////////
// NOTIFICATIONS
void queueRowLemma(RowLemmaType lem);
void dischargeLemmas();
+ public:
+
+ eq::EqualityEngine* getEqualityEngine() {
+ return &d_equalityEngine;
+ }
+
};/* class TheoryArrays */
}/* CVC4::theory::arrays namespace */
}
-int InstantiatorTheoryArrays::process( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstantiatorTheoryArrays::process( Node f, Theory::Effort effort, int e ){
return InstStrategy::STATUS_SAT;
}
+
+bool InstantiatorTheoryArrays::hasTerm( Node a ){
+ return ((TheoryArrays*)d_th)->getEqualityEngine()->hasTerm( a );
+}
+
+bool InstantiatorTheoryArrays::areEqual( Node a, Node b ){
+ if( hasTerm( a ) && hasTerm( b ) ){
+ return ((TheoryArrays*)d_th)->getEqualityEngine()->areEqual( a, b );
+ }else{
+ return a==b;
+ }
+}
+
+bool InstantiatorTheoryArrays::areDisequal( Node a, Node b ){
+ if( hasTerm( a ) && hasTerm( b ) ){
+ return ((TheoryArrays*)d_th)->getEqualityEngine()->areDisequal( a, b, false );
+ }else{
+ return false;
+ }
+}
+
+Node InstantiatorTheoryArrays::getRepresentative( Node a ){
+ if( hasTerm( a ) ){
+ return ((TheoryArrays*)d_th)->getEqualityEngine()->getRepresentative( a );
+ }else{
+ return a;
+ }
+}
+
/** reset instantiation round */
void processResetInstantiationRound( Theory::Effort effort );
/** process quantifier */
- int process( Node f, Theory::Effort effort, int e, int limitInst = 0 );
+ int process( Node f, Theory::Effort effort, int e );
public:
InstantiatorTheoryArrays(context::Context* c, QuantifiersEngine* ie, Theory* th);
~InstantiatorTheoryArrays() {}
void assertNode( Node assertion );
/** identify */
std::string identify() const { return std::string("InstantiatorTheoryArrays"); }
+public:
+ /** general queries about equality */
+ bool hasTerm( Node a );
+ bool areEqual( Node a, Node b );
+ bool areDisequal( Node a, Node b );
+ Node getRepresentative( Node a );
};/* class Instantiatior */
}
namespace theory {
namespace booleans {
-Node TheoryBool::getValue(TNode n) {
- NodeManager* nodeManager = NodeManager::currentNM();
+void TheoryBool::collectModelInfo( TheoryModel* m ){
- switch(n.getKind()) {
- case kind::VARIABLE:
- // case for Boolean vars is implemented in TheoryEngine (since it
- // appeals to the PropEngine to get the value)
- Unreachable();
-
- case kind::EQUAL: // 2 args
- // should be handled by IFF
- Unreachable();
-
- case kind::NOT: { // 1 arg
- Node v = d_valuation.getValue(n[0]);
- return v.isNull() ? Node::null() : nodeManager->mkConst(! v.getConst<bool>());
- }
-
- case kind::AND: { // 2+ args
- bool foundNull = false;
- for(TNode::iterator i = n.begin(),
- iend = n.end();
- i != iend;
- ++i) {
- Node v = d_valuation.getValue(*i);
- if(v.isNull()) {
- foundNull = true;
- } else if(! v.getConst<bool>()) {
- return nodeManager->mkConst(false);
- }
- }
- return foundNull ? Node::null() : nodeManager->mkConst(true);
- }
-
- case kind::IFF: { // 2 args
- Node v0 = d_valuation.getValue(n[0]);
- Node v1 = d_valuation.getValue(n[1]);
- if(v0.isNull() || v1.isNull()) {
- return Node::null();
- }
- return nodeManager->mkConst( v0.getConst<bool>() == v1.getConst<bool>() );
- }
-
- case kind::IMPLIES: { // 2 args
- Node v0 = d_valuation.getValue(n[0]);
- Node v1 = d_valuation.getValue(n[1]);
- if(v0.isNull() && v1.isNull()) {
- return Node::null();
- }
- bool value = false;
- if(! v0.isNull()) {
- value = value || (! v0.getConst<bool>());
- }
- if(! v1.isNull()) {
- value = value || v1.getConst<bool>();
- }
- return nodeManager->mkConst(value);
- }
-
- case kind::OR: { // 2+ args
- bool foundNull = false;
- for(TNode::iterator i = n.begin(),
- iend = n.end();
- i != iend;
- ++i) {
- Node v = d_valuation.getValue(*i);
- if(v.isNull()) {
- foundNull = true;
- } else if(v.getConst<bool>()) {
- return nodeManager->mkConst(true);
- }
- }
- return foundNull ? Node::null() : nodeManager->mkConst(false);
- }
-
- case kind::XOR: { // 2 args
- Node v0 = d_valuation.getValue(n[0]);
- Node v1 = d_valuation.getValue(n[1]);
- if(v0.isNull() || v1.isNull()) {
- return Node::null();
- }
- return nodeManager->mkConst( v0.getConst<bool>() != v1.getConst<bool>() );
- }
-
- case kind::ITE: { // 3 args
- // all ITEs should be gone except (bool,bool,bool) ones
- Assert( n[1].getType() == nodeManager->booleanType() &&
- n[2].getType() == nodeManager->booleanType() );
- Node v0 = d_valuation.getValue(n[0]);
- Node v1 = d_valuation.getValue(n[1]);
- Node v2 = d_valuation.getValue(n[2]);
- if(v0.isNull()) {
- return v1 == v2 ? v1 : Node::null();
- }
- return nodeManager->mkConst( v0.getConst<bool>() ? v1.getConst<bool>() : v2.getConst<bool>() );
- }
-
- default:
- Unhandled(n.getKind());
- }
}
Theory::PPAssertStatus TheoryBool::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
#include "theory/theory.h"
#include "context/context.h"
+#include "theory/model.h"
namespace CVC4 {
namespace theory {
Theory(THEORY_BOOL, c, u, out, valuation, logicInfo, qe) {
}
- Node getValue(TNode n);
+ void collectModelInfo( TheoryModel* m );
PPAssertStatus ppAssert(TNode in, SubstitutionMap& outSubstitutions);
#include "theory/builtin/theory_builtin.h"
#include "theory/valuation.h"
#include "expr/kind.h"
+#include "theory/model.h"
using namespace std;
namespace theory {
namespace builtin {
-Node TheoryBuiltin::getValue(TNode n) {
- switch(n.getKind()) {
+void TheoryBuiltin::collectModelInfo( TheoryModel* m ){
- case kind::VARIABLE:
- // no variables that the builtin theory is responsible for
- Unreachable();
-
- case kind::EQUAL: { // 2 args
- // has to be an EQUAL over tuples, since all others should be
- // handled elsewhere
- Assert(n[0].getKind() == kind::TUPLE &&
- n[1].getKind() == kind::TUPLE);
- return NodeManager::currentNM()->
- mkConst( getValue(n[0]) == getValue(n[1]) );
- }
-
- case kind::TUPLE: { // 2+ args
- NodeBuilder<> nb(kind::TUPLE);
- for(TNode::iterator i = n.begin(),
- iend = n.end();
- i != iend;
- ++i) {
- nb << d_valuation.getValue(*i);
- }
- return Node(nb);
- }
-
- default:
- // all other "builtins" should have been rewritten away or handled
- // by the valuation, or handled elsewhere.
- Unhandled(n.getKind());
- }
}
}/* CVC4::theory::builtin namespace */
public:
TheoryBuiltin(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo, QuantifiersEngine* qe) :
Theory(THEORY_BUILTIN, c, u, out, valuation, logicInfo, qe) {}
- Node getValue(TNode n);
+ void collectModelInfo( TheoryModel* m );
std::string identify() const { return std::string("TheoryBuiltin"); }
};/* class TheoryBuiltin */
{
StatisticsRegistry::registerStat(&d_avgConflictSize);
StatisticsRegistry::registerStat(&d_solveSubstitutions);
- StatisticsRegistry::registerStat(&d_solveTimer);
+ StatisticsRegistry::registerStat(&d_solveTimer);
}
TheoryBV::Statistics::~Statistics() {
StatisticsRegistry::unregisterStat(&d_avgConflictSize);
StatisticsRegistry::unregisterStat(&d_solveSubstitutions);
- StatisticsRegistry::unregisterStat(&d_solveTimer);
+ StatisticsRegistry::unregisterStat(&d_solveTimer);
}
void TheoryBV::preRegisterTerm(TNode node) {
}
d_bitblastSolver.preRegister(node);
- d_equalitySolver.preRegister(node);
+ d_equalitySolver.preRegister(node);
}
void TheoryBV::sendConflict() {
{
BVDebug("bitvector") << "TheoryBV::check(" << e << ")" << std::endl;
- // if we are already in conflict just return the conflict
+ // if we are already in conflict just return the conflict
if (inConflict()) {
sendConflict();
return;
}
-
+
// getting the new assertions
- std::vector<TNode> new_assertions;
+ std::vector<TNode> new_assertions;
while (!done()) {
Assertion assertion = get();
TNode fact = assertion.assertion;
new_assertions.push_back(fact);
- BVDebug("bitvector-assertions") << "TheoryBV::check assertion " << fact << "\n";
+ BVDebug("bitvector-assertions") << "TheoryBV::check assertion " << fact << "\n";
}
if (!inConflict()) {
// sending assertions to the equality solver first
d_equalitySolver.addAssertions(new_assertions, e);
}
-
+
if (!inConflict()) {
// sending assertions to the bitblast solver
d_bitblastSolver.addAssertions(new_assertions, e);
}
-
+
if (inConflict()) {
sendConflict();
}
}
+void TheoryBV::collectModelInfo( TheoryModel* m ){
-Node TheoryBV::getValue(TNode n) {
- //NodeManager* nodeManager = NodeManager::currentNM();
-
- switch(n.getKind()) {
-
- case kind::VARIABLE:
- Unhandled(kind::VARIABLE);
-
- case kind::EQUAL: // 2 args
- Unhandled(kind::VARIABLE);
-
- default:
- Unhandled(n.getKind());
- }
}
-
void TheoryBV::propagate(Effort e) {
BVDebug("bitvector") << indent() << "TheoryBV::propagate()" << std::endl;
Theory::PPAssertStatus TheoryBV::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
switch(in.getKind()) {
case kind::EQUAL:
-
+
if (in[0].getMetaKind() == kind::metakind::VARIABLE && !in[1].hasSubterm(in[0])) {
- ++(d_statistics.d_solveSubstitutions);
+ ++(d_statistics.d_solveSubstitutions);
outSubstitutions.addSubstitution(in[0], in[1]);
return PP_ASSERT_STATUS_SOLVED;
}
if (in[1].getMetaKind() == kind::metakind::VARIABLE && !in[0].hasSubterm(in[1])) {
- ++(d_statistics.d_solveSubstitutions);
+ ++(d_statistics.d_solveSubstitutions);
outSubstitutions.addSubstitution(in[1], in[0]);
return PP_ASSERT_STATUS_SOLVED;
}
void TheoryBV::explain(TNode literal, std::vector<TNode>& assumptions) {
- // Ask the appropriate subtheory for the explanation
+ // Ask the appropriate subtheory for the explanation
if (propagatedBy(literal, SUB_EQUALITY)) {
BVDebug("bitvector::explain") << "TheoryBV::explain(" << literal << "): EQUALITY" << std::endl;
- d_equalitySolver.explain(literal, assumptions);
+ d_equalitySolver.explain(literal, assumptions);
} else {
Assert(propagatedBy(literal, SUB_BITBLAST));
- BVDebug("bitvector::explain") << "TheoryBV::explain(" << literal << ") : BITBLASTER" << std::endl;
- d_bitblastSolver.explain(literal, assumptions);
+ BVDebug("bitvector::explain") << "TheoryBV::explain(" << literal << ") : BITBLASTER" << std::endl;
+ d_bitblastSolver.explain(literal, assumptions);
}
}
explain(node, assumptions);
// this means that it is something true at level 0
if (assumptions.size() == 0) {
- return utils::mkTrue();
+ return utils::mkTrue();
}
// return the explanation
Node explanation = mkAnd(assumptions);
void TheoryBV::addSharedTerm(TNode t) {
Debug("bitvector::sharing") << indent() << "TheoryBV::addSharedTerm(" << t << ")" << std::endl;
- d_sharedTermsSet.insert(t);
+ d_sharedTermsSet.insert(t);
if (!Options::current()->bitvectorEagerBitblast && d_useEqualityEngine) {
- d_equalitySolver.addSharedTerm(t);
+ d_equalitySolver.addSharedTerm(t);
}
}
void check(Effort e);
void propagate(Effort e);
-
+
Node explain(TNode n);
- Node getValue(TNode n);
+ void collectModelInfo( TheoryModel* m );
std::string identify() const { return std::string("TheoryBV"); }
}
void setConflict(Node conflict = Node::null()) {
- d_conflict = true;
+ d_conflict = true;
d_conflictNode = conflict;
}
friend class Bitblaster;
friend class BitblastSolver;
- friend class EqualitySolver;
-
+ friend class EqualitySolver;
+
};/* class TheoryBV */
}/* CVC4::theory::bv namespace */
#include "util/datatype.h"
#include "util/Assert.h"
#include "theory/datatypes/theory_datatypes_instantiator.h"
+#include "theory/model.h"
#include <map>
void TheoryDatatypes::preRegisterTerm(TNode n) {
Debug("datatypes-prereg") << "TheoryDatatypes::preRegisterTerm() " << n << endl;
+ if( n.getType().isDatatype() ){
+ d_preRegTerms.push_back( n );
+ }
}
}
}
-Node TheoryDatatypes::getValue(TNode n) {
- NodeManager* nodeManager = NodeManager::currentNM();
- switch(n.getKind()) {
- case kind::VARIABLE:
- Unhandled(kind::VARIABLE);
- case kind::EQUAL: // 2 args
- return nodeManager->
- mkConst( d_valuation.getValue(n[0]) == d_valuation.getValue(n[1]) );
- default:
- Unhandled(n.getKind());
+void TheoryDatatypes::collectModelInfo( TheoryModel* m ){
+ //temporary
+ for( int i=0; i<(int)d_preRegTerms.size(); i++ ){
+ Node n = find( d_preRegTerms[i] );
+ m->assertEquality( n, d_preRegTerms[i], true );
}
}
}
return false;
}
+
+bool TheoryDatatypes::hasTerm( Node a ){
+ return false;
+}
+
+bool TheoryDatatypes::areEqual( Node a, Node b ){
+ Node ar = find( a );
+ Node br = find( b );
+ if( ar==br ){
+ return true;
+ }else if( ar.getKind()==APPLY_CONSTRUCTOR && br.getKind()==APPLY_CONSTRUCTOR &&
+ ar.getOperator()==br.getOperator() ){
+ //for( int i=0; i<(int)ar.getNumChildren(); i++ ){
+ // if( !areEqual( ar[0], br[0] ) ){
+ // return false;
+ // }
+ //}
+ //return true;
+ return false;
+ }else{
+ return false;
+ }
+}
+
+bool TheoryDatatypes::areDisequal( Node a, Node b ){
+ Node ar = find( a );
+ Node br = find( b );
+ if( ar==br ){
+ return false;
+ }else if( ar.getKind()==APPLY_CONSTRUCTOR && br.getKind()==APPLY_CONSTRUCTOR &&
+ ar.getOperator()!=br.getOperator() ){
+ return true;
+ }else{
+ EqLists::iterator deq_ia = d_disequalities.find( ar );
+ EqLists::iterator deq_ib = d_disequalities.find( br );
+ if( deq_ia!=d_disequalities.end() && deq_ib!=d_disequalities.end() ){
+ EqList* deq;
+ if( (*deq_ib).second->size()<(*deq_ia).second->size() ){
+ deq = (*deq_ib).second;
+ }else{
+ deq = (*deq_ia).second;
+ }
+ for(EqList::const_iterator i = deq->begin(); i != deq->end(); i++) {
+ TNode deqn = (*i);
+ TNode sp = find(deqn[0]);
+ TNode tp = find(deqn[1]);
+ if( sp==a && tp==b ){
+ return true;
+ }else if( sp==b && tp==a ){
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
+
+Node TheoryDatatypes::getRepresentative( Node a ){
+ return find( a );
+}
+
*/
CongruenceClosureExplainer<CongruenceChannel, CONGRUENCE_OPERATORS_2 (kind::APPLY_CONSTRUCTOR, kind::APPLY_SELECTOR)> d_cce;
+ //temporary
+ std::vector< Node > d_preRegTerms;
public:
TheoryDatatypes(context::Context* c, context::UserContext* u, OutputChannel& out, Valuation valuation, const LogicInfo& logicInfo, QuantifiersEngine* qe);
~TheoryDatatypes();
void addSharedTerm(TNode t);
void check(Effort e);
- Node getValue(TNode n);
+ void collectModelInfo( TheoryModel* m );
void shutdown() { }
std::string identify() const { return std::string("TheoryDatatypes"); }
bool searchForCycle( Node n, Node on,
std::map< Node, bool >& visited,
NodeBuilder<>& explanation );
+public:
+ //equality queries
+ bool hasTerm( Node a );
+ bool areEqual( Node a, Node b );
+ bool areDisequal( Node a, Node b );
+ Node getRepresentative( Node a );
};/* class TheoryDatatypes */
inline bool TheoryDatatypes::hasConflict() {
#include "theory/datatypes/theory_datatypes_instantiator.h"
#include "theory/datatypes/theory_datatypes.h"
#include "theory/theory_engine.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
}
-int InstantiatorTheoryDatatypes::process( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstantiatorTheoryDatatypes::process( Node f, Theory::Effort effort, int e ){
Debug("quant-datatypes") << "Datatypes: Try to solve (" << e << ") for " << f << "... " << std::endl;
if( Options::current()->cbqi ){
if( e<2 ){
return InstStrategy::STATUS_UNFINISHED;
}else if( e==2 ){
InstMatch m;
- for( int j = 0; j<(int)d_quantEngine->getNumInstantiationConstants( f ); j++ ){
- Node i = d_quantEngine->getInstantiationConstant( f, j );
+ for( int j = 0; j<(int)d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); j++ ){
+ Node i = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
if( i.getType().isDatatype() ){
Node n = getValueFor( i );
Debug("quant-datatypes-debug") << "Value for " << i << " is " << n << std::endl;
}
}
-Node InstantiatorTheoryDatatypes::getRepresentative( Node n ){
- return ((TheoryDatatypes*)d_th)->find( n );
-}
-
InstantiatorTheoryDatatypes::Statistics::Statistics():
d_instantiations("InstantiatorTheoryDatatypes::Instantiations_Total", 0)
{
StatisticsRegistry::unregisterStat(&d_instantiations);
}
+bool InstantiatorTheoryDatatypes::hasTerm( Node a ){
+ return ((TheoryDatatypes*)d_th)->hasTerm( a );
+}
+
+bool InstantiatorTheoryDatatypes::areEqual( Node a, Node b ){
+ return ((TheoryDatatypes*)d_th)->areEqual( a, b );
+}
+
+bool InstantiatorTheoryDatatypes::areDisequal( Node a, Node b ){
+ return ((TheoryDatatypes*)d_th)->areDisequal( a, b );
+}
+
+Node InstantiatorTheoryDatatypes::getRepresentative( Node a ){
+ return ((TheoryDatatypes*)d_th)->getRepresentative( a );
+}
/** reset instantiation */
void processResetInstantiationRound( Theory::Effort effort );
/** process at effort */
- int process( Node f, Theory::Effort effort, int e, int limitInst );
+ int process( Node f, Theory::Effort effort, int e );
/** get value for */
Node getValueFor( Node n );
- /** get representative */
- Node getRepresentative( Node n );
class Statistics {
public:
~Statistics();
};
Statistics d_statistics;
+public:
+ /** general queries about equality */
+ bool hasTerm( Node a );
+ bool areEqual( Node a, Node b );
+ bool areDisequal( Node a, Node b );
+ Node getRepresentative( Node a );
};/* class InstantiatiorTheoryDatatypes */
}
void explain(TNode n) {}
/**
- * Get a theory value.
+ * Get model
*
- * Overloads Node getValue(TNode n); from theory.h.
* See theory/theory.h for more information about this method.
*/
- Node getValue(TNode n) {
+ void collectModelInfo( TheoryModel* m ){
Unimplemented("TheoryUFTim doesn't support model generation");
}
#include "theory/uf/theory_uf_instantiator.h"
#include "theory/uf/theory_uf_candidate_generator.h"
#include "theory/uf/equality_engine.h"
+#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
bool CandidateGenerator::isLegalCandidate( Node n ){
- return !n.getAttribute(NoMatchAttribute()) && ( !Options::current()->cbqi || !n.hasAttribute(InstConstantAttribute()) );
+ return ( !n.getAttribute(NoMatchAttribute()) && ( !Options::current()->cbqi || !n.hasAttribute(InstConstantAttribute()) ) ) ||
+ ( Options::current()->finiteModelFind && n.hasAttribute(ModelBasisArgAttribute()) && n.getAttribute(ModelBasisArgAttribute())==1 );
}
void CandidateGeneratorQueue::addCandidate( Node n ) {
}
void InstMatch::makeComplete( Node f, QuantifiersEngine* qe ){
- for( int i=0; i<(int)qe->d_inst_constants[f].size(); i++ ){
- if( d_map.find( qe->d_inst_constants[f][i] )==d_map.end() ){
- d_map[ qe->d_inst_constants[f][i] ] = qe->getFreeVariableForInstConstant( qe->d_inst_constants[f][i] );
+ for( int i=0; i<(int)qe->getTermDatabase()->d_inst_constants[f].size(); i++ ){
+ if( d_map.find( qe->getTermDatabase()->d_inst_constants[f][i] )==d_map.end() ){
+ d_map[ qe->getTermDatabase()->d_inst_constants[f][i] ] = qe->getTermDatabase()->getFreeVariableForInstConstant( qe->getTermDatabase()->d_inst_constants[f][i] );
}
}
}
if( Options::current()->cbqi && it->second.hasAttribute(InstConstantAttribute()) ){
d_map[ it->first ] = qe->getEqualityQuery()->getInternalRepresentative( it->second );
if( Options::current()->cbqi && it->second.hasAttribute(InstConstantAttribute()) ){
- d_map[ it->first ] = qe->getFreeVariableForInstConstant( it->first );
+ d_map[ it->first ] = qe->getTermDatabase()->getFreeVariableForInstConstant( it->first );
}
}
}
for( std::map< Node, Node >::iterator it = d_map.begin(); it != d_map.end(); ++it ){
d_map[ it->first ] = qe->getEqualityQuery()->getInternalRepresentative( it->second );
if( Options::current()->cbqi && it->second.hasAttribute(InstConstantAttribute()) ){
- d_map[ it->first ] = qe->getFreeVariableForInstConstant( it->first );
+ d_map[ it->first ] = qe->getTermDatabase()->getFreeVariableForInstConstant( it->first );
}
}
}
if( it!=d_map.end() && !it->second.isNull() ){
match.push_back( it->second );
}else{
- match.push_back( qe->getFreeVariableForInstConstant( vars[i] ) );
+ match.push_back( qe->getTermDatabase()->getFreeVariableForInstConstant( vars[i] ) );
}
}
}
void InstMatchTrie::addInstMatch2( QuantifiersEngine* qe, Node f, InstMatch& m, int index, ImtIndexOrder* imtio ){
if( long(index)<long(f[0].getNumChildren()) && ( !imtio || long(index)<long(imtio->d_order.size()) ) ){
int i_index = imtio ? imtio->d_order[index] : index;
- Node n = m.d_map[ qe->getInstantiationConstant( f, i_index ) ];
+ Node n = m.d_map[ qe->getTermDatabase()->getInstantiationConstant( f, i_index ) ];
d_data[n].addInstMatch2( qe, f, m, index+1, imtio );
}
}
return true;
}else{
int i_index = imtio ? imtio->d_order[index] : index;
- Node n = m.d_map[ qe->getInstantiationConstant( f, i_index ) ];
+ Node n = m.d_map[ qe->getTermDatabase()->getInstantiationConstant( f, i_index ) ];
std::map< Node, InstMatchTrie >::iterator it = d_data.find( n );
if( it!=d_data.end() ){
if( it->second.existsInstMatch( qe, f, m, modEq, index+1, imtio ) ){
if( modEq ){
//check modulo equality if any other instantiation match exists
if( ((uf::TheoryUF*)qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine()->hasTerm( n ) ){
- eq::EqClassIterator eqc( qe->getEqualityQuery()->getRepresentative( n ),
+ eq::EqClassIterator eqc( ((uf::TheoryUF*)qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine()->getRepresentative( n ),
((uf::TheoryUF*)qe->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine() );
while( !eqc.isFinished() ){
Node en = (*eqc);
Debug("matching") << "Matching " << t << " against pattern " << d_match_pattern << " ("
<< m.d_map.size() << ")" << ", " << d_children.size() << std::endl;
Assert( !d_match_pattern.isNull() );
- if( d_matchPolicy==MATCH_GEN_INTERNAL_ARITHMETIC ){
+ if( qe->d_optMatchIgnoreModelBasis && t.getAttribute(ModelBasisAttribute()) ){
+ return true;
+ }else if( d_matchPolicy==MATCH_GEN_INTERNAL_ARITHMETIC ){
return getMatchArithmetic( t, m, qe );
}else if( d_matchPolicy==MATCH_GEN_INTERNAL_ERROR ){
return false;
t = d_cg->getNextCandidate();
//if t not null, try to fit it into match m
if( !t.isNull() && t.getType()==d_match_pattern.getType() ){
- //Assert( t.getType()==d_match_pattern.getType() );
success = getMatch( t, m, qe );
}
}while( !success && !t.isNull() );
return false;
}
-int InstMatchGenerator::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit, bool addSplits ){
+int InstMatchGenerator::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
//now, try to add instantiation for each match produced
int addedLemmas = 0;
InstMatch m;
while( getNextMatch( m, qe ) ){
//m.makeInternal( d_quantEngine->getEqualityQuery() );
m.add( baseMatch );
- if( qe->addInstantiation( f, m, addSplits ) ){
+ if( qe->addInstantiation( f, m ) ){
addedLemmas++;
- if( instLimit>0 && addedLemmas==instLimit ){
+ if( qe->d_optInstLimitActive && qe->d_optInstLimit<=0 ){
return addedLemmas;
}
}
}
}
-void InstMatchGeneratorMulti::collectInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
- std::vector< IndexedTrie >& unique_var_tries,
- int trieIndex, int childIndex, int endChildIndex, bool modEq ){
+int InstMatchGeneratorMulti::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
+ int addedLemmas = 0;
+ Debug("smart-multi-trigger") << "Process smart multi trigger" << std::endl;
+ for( int i=0; i<(int)d_children.size(); i++ ){
+ Debug("smart-multi-trigger") << "Calculate matches " << i << std::endl;
+ std::vector< InstMatch > newMatches;
+ InstMatch m;
+ while( d_children[i]->getNextMatch( m, qe ) ){
+ m.makeRepresentative( qe );
+ newMatches.push_back( InstMatch( &m ) );
+ m.clear();
+ }
+ for( int j=0; j<(int)newMatches.size(); j++ ){
+ processNewMatch( qe, newMatches[j], i, addedLemmas );
+ }
+ }
+ return addedLemmas;
+}
+
+void InstMatchGeneratorMulti::processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas ){
+ //see if these produce new matches
+ d_children_trie[fromChildIndex].addInstMatch( qe, d_f, m, true );
+ //possibly only do the following if we know that new matches will be produced?
+ //the issue is that instantiations are filtered in quantifiers engine, and so there is no guarentee that
+ // we can safely skip the following lines, even when we have already produced this match.
+ Debug("smart-multi-trigger") << "Child " << fromChildIndex << " produced match " << m << std::endl;
+ //process new instantiations
+ int childIndex = (fromChildIndex+1)%(int)d_children.size();
+ std::vector< IndexedTrie > unique_var_tries;
+ processNewInstantiations( qe, m, addedLemmas, d_children_trie[childIndex].getTrie(),
+ unique_var_tries, 0, childIndex, fromChildIndex, true );
+}
+
+void InstMatchGeneratorMulti::processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int trieIndex, int childIndex, int endChildIndex, bool modEq ){
if( childIndex==endChildIndex ){
//now, process unique variables
- collectInstantiations2( qe, m, addedLemmas, unique_var_tries, 0 );
+ processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, 0 );
}else if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){
int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];
- Node curr_ic = qe->getInstantiationConstant( d_f, curr_index );
+ Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
if( m.d_map.find( curr_ic )==m.d_map.end() ){
//if( d_var_to_node[ curr_index ].size()==1 ){ //FIXME
// //unique variable(s), defer calculation
// unique_var_tries.push_back( IndexedTrie( std::pair< int, int >( childIndex, trieIndex ), tr ) );
// int newChildIndex = (childIndex+1)%(int)d_children.size();
- // collectInstantiations( qe, m, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
- // 0, newChildIndex, endChildIndex, modEq );
+ // processNewInstantiations( qe, m, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
+ // 0, newChildIndex, endChildIndex, modEq );
//}else{
//shared and non-set variable, add to InstMatch
for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){
InstMatch mn( &m );
mn.d_map[ curr_ic ] = it->first;
- collectInstantiations( qe, mn, addedLemmas, &(it->second), unique_var_tries,
- trieIndex+1, childIndex, endChildIndex, modEq );
+ processNewInstantiations( qe, mn, addedLemmas, &(it->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
}
//}
}else{
Node n = m.d_map[ curr_ic ];
std::map< Node, InstMatchTrie >::iterator it = tr->d_data.find( n );
if( it!=tr->d_data.end() ){
- collectInstantiations( qe, m, addedLemmas, &(it->second), unique_var_tries,
- trieIndex+1, childIndex, endChildIndex, modEq );
+ processNewInstantiations( qe, m, addedLemmas, &(it->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
}
if( modEq ){
//check modulo equality for other possible instantiations
if( en!=n ){
std::map< Node, InstMatchTrie >::iterator itc = tr->d_data.find( en );
if( itc!=tr->d_data.end() ){
- collectInstantiations( qe, m, addedLemmas, &(itc->second), unique_var_tries,
- trieIndex+1, childIndex, endChildIndex, modEq );
+ processNewInstantiations( qe, m, addedLemmas, &(itc->second), unique_var_tries,
+ trieIndex+1, childIndex, endChildIndex, modEq );
}
}
++eqc;
}
}else{
int newChildIndex = (childIndex+1)%(int)d_children.size();
- collectInstantiations( qe, m, addedLemmas, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
- 0, newChildIndex, endChildIndex, modEq );
+ processNewInstantiations( qe, m, addedLemmas, d_children_trie[newChildIndex].getTrie(), unique_var_tries,
+ 0, newChildIndex, endChildIndex, modEq );
}
}
-void InstMatchGeneratorMulti::collectInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
- std::vector< IndexedTrie >& unique_var_tries,
- int uvtIndex, InstMatchTrie* tr, int trieIndex ){
+void InstMatchGeneratorMulti::processNewInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int uvtIndex, InstMatchTrie* tr, int trieIndex ){
if( uvtIndex<(int)unique_var_tries.size() ){
int childIndex = unique_var_tries[uvtIndex].first.first;
if( !tr ){
}
if( trieIndex<(int)d_children_trie[childIndex].getOrdering()->d_order.size() ){
int curr_index = d_children_trie[childIndex].getOrdering()->d_order[trieIndex];
- Node curr_ic = qe->getInstantiationConstant( d_f, curr_index );
+ Node curr_ic = qe->getTermDatabase()->getInstantiationConstant( d_f, curr_index );
//unique non-set variable, add to InstMatch
for( std::map< Node, InstMatchTrie >::iterator it = tr->d_data.begin(); it != tr->d_data.end(); ++it ){
InstMatch mn( &m );
mn.d_map[ curr_ic ] = it->first;
- collectInstantiations2( qe, mn, addedLemmas, unique_var_tries, uvtIndex, &(it->second), trieIndex+1 );
+ processNewInstantiations2( qe, mn, addedLemmas, unique_var_tries, uvtIndex, &(it->second), trieIndex+1 );
}
}else{
- collectInstantiations2( qe, m, addedLemmas, unique_var_tries, uvtIndex+1 );
+ processNewInstantiations2( qe, m, addedLemmas, unique_var_tries, uvtIndex+1 );
}
}else{
//m is an instantiation
- if( qe->addInstantiation( d_f, m, true ) ){
+ if( qe->addInstantiation( d_f, m ) ){
addedLemmas++;
Debug("smart-multi-trigger") << "-> Produced instantiation " << m << std::endl;
}
}
}
-int InstMatchGeneratorMulti::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit, bool addSplits ){
- int addedLemmas = 0;
- Debug("smart-multi-trigger") << "Process smart multi trigger" << std::endl;
- for( int i=0; i<(int)d_children.size(); i++ ){
- Debug("smart-multi-trigger") << "Calculate matches " << i << std::endl;
- std::vector< InstMatch > newMatches;
- InstMatch m;
- while( d_children[i]->getNextMatch( m, qe ) ){
- m.makeRepresentative( qe );
- newMatches.push_back( InstMatch( &m ) );
- m.clear();
- }
- for( int j=0; j<(int)newMatches.size(); j++ ){
- processNewMatch( qe, newMatches[j], i, addedLemmas );
- }
- }
- return addedLemmas;
-}
-
-void InstMatchGeneratorMulti::processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas ){
- //see if these produce new matches
- d_children_trie[fromChildIndex].addInstMatch( qe, d_f, m, true );
- //possibly only do the following if we know that new matches will be produced?
- //the issue is that instantiations are filtered in quantifiers engine, and so there is no guarentee that
- // we can safely skip the following lines, even when we have already produced this match.
- Debug("smart-multi-trigger") << "Child " << fromChildIndex << " produced match " << m << std::endl;
- //collect new instantiations
- int childIndex = (fromChildIndex+1)%(int)d_children.size();
- std::vector< IndexedTrie > unique_var_tries;
- collectInstantiations( qe, m, addedLemmas,
- d_children_trie[childIndex].getTrie(), unique_var_tries, 0, childIndex, fromChildIndex, true );
-}
-
int InstMatchGeneratorMulti::addTerm( Node f, Node t, QuantifiersEngine* qe ){
Assert( Options::current()->eagerInstQuant );
int addedLemmas = 0;
return addedLemmas;
}
-int InstMatchGeneratorSimple::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit, bool addSplits ){
+int InstMatchGeneratorSimple::addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ){
InstMatch m;
m.add( baseMatch );
int addedLemmas = 0;
if( d_match_pattern.getType()==NodeManager::currentNM()->booleanType() ){
for( int i=0; i<2; i++ ){
- addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_pred_map_trie[i][ d_match_pattern.getOperator() ]),
- instLimit, addSplits );
+ addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_pred_map_trie[i][ d_match_pattern.getOperator() ]) );
}
}else{
- addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_func_map_trie[ d_match_pattern.getOperator() ]),
- instLimit, addSplits );
+ addInstantiations( m, qe, addedLemmas, 0, &(qe->getTermDatabase()->d_func_map_trie[ d_match_pattern.getOperator() ]) );
}
return addedLemmas;
}
-void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex,
- TermArgTrie* tat, int instLimit, bool addSplits ){
+void InstMatchGeneratorSimple::addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat ){
if( argIndex==(int)d_match_pattern.getNumChildren() ){
//m is an instantiation
- if( qe->addInstantiation( d_f, m, addSplits ) ){
+ if( qe->addInstantiation( d_f, m ) ){
addedLemmas++;
Debug("simple-multi-trigger") << "-> Produced instantiation " << m << std::endl;
}
}else{
if( d_match_pattern[argIndex].getKind()==INST_CONSTANT ){
Node ic = d_match_pattern[argIndex];
- for( std::map< Node, TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
+ for( std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.begin(); it != tat->d_data.end(); ++it ){
Node t = it->first;
if( m.d_map[ ic ].isNull() || m.d_map[ ic ]==t ){
Node prev = m.d_map[ ic ];
m.d_map[ ic ] = t;
- addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second), instLimit, addSplits );
+ addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
m.d_map[ ic ] = prev;
}
}
}else{
Node r = qe->getEqualityQuery()->getRepresentative( d_match_pattern[argIndex] );
- std::map< Node, TermArgTrie >::iterator it = tat->d_data.find( r );
+ std::map< Node, quantifiers::TermArgTrie >::iterator it = tat->d_data.find( r );
if( it!=tat->d_data.end() ){
- addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second), instLimit, addSplits );
+ addInstantiations( m, qe, addedLemmas, argIndex+1, &(it->second) );
}
}
}
given Node can't match the pattern */
virtual bool nonunifiable( TNode t, const std::vector<Node> & vars) = 0;
/** add instantiations directly */
- virtual int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit = 0, bool addSplits = false ) = 0;
+ virtual int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe ) = 0;
/** add ground term t, called when t is added to term db */
virtual int addTerm( Node f, Node t, QuantifiersEngine* qe ) = 0;
};/* class IMGenerator */
given Node can't match the pattern */
bool nonunifiable( TNode t, const std::vector<Node> & vars);
/** add instantiations */
- int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit = 0, bool addSplits = false );
+ int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
/** add ground term t */
int addTerm( Node f, Node t, QuantifiersEngine* qe );
};/* class InstMatchGenerator */
/** smart multi-trigger implementation */
class InstMatchGeneratorMulti : public IMGenerator {
-private:
- void processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas );
private:
/** indexed trie */
typedef std::pair< std::pair< int, int >, InstMatchTrie* > IndexedTrie;
- /** collect instantiations */
- void collectInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
- std::vector< IndexedTrie >& unique_var_tries,
- int trieIndex, int childIndex, int endChildIndex, bool modEq );
- /** collect instantiations 2 */
- void collectInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
- std::vector< IndexedTrie >& unique_var_tries,
- int uvtIndex, InstMatchTrie* tr = NULL, int trieIndex = 0 );
+ /** process new match */
+ void processNewMatch( QuantifiersEngine* qe, InstMatch& m, int fromChildIndex, int& addedLemmas );
+ /** process new instantiations */
+ void processNewInstantiations( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas, InstMatchTrie* tr,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int trieIndex, int childIndex, int endChildIndex, bool modEq );
+ /** process new instantiations 2 */
+ void processNewInstantiations2( QuantifiersEngine* qe, InstMatch& m, int& addedLemmas,
+ std::vector< IndexedTrie >& unique_var_tries,
+ int uvtIndex, InstMatchTrie* tr = NULL, int trieIndex = 0 );
private:
/** var contains (variable indices) for each pattern node */
std::map< Node, std::vector< int > > d_var_contains;
given Node can't match the pattern */
bool nonunifiable( TNode t, const std::vector<Node> & vars) { return true; }
/** add instantiations */
- int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit = 0, bool addSplits = false );
+ int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
/** add ground term t */
int addTerm( Node f, Node t, QuantifiersEngine* qe );
};/* class InstMatchGeneratorMulti */
-class TermArgTrie;
+namespace quantifiers{
+ class TermArgTrie;
+}
/** smart (single)-trigger implementation */
class InstMatchGeneratorSimple : public IMGenerator {
/** match term */
Node d_match_pattern;
/** add instantiations */
- void addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas,
- int argIndex, TermArgTrie* tat, int instLimit, bool addSplits );
+ void addInstantiations( InstMatch& m, QuantifiersEngine* qe, int& addedLemmas, int argIndex, quantifiers::TermArgTrie* tat );
public:
/** constructors */
InstMatchGeneratorSimple( Node f, Node pat ) : d_f( f ), d_match_pattern( pat ){}
given Node can't match the pattern */
bool nonunifiable( TNode t, const std::vector<Node> & vars) { return true; }
/** add instantiations */
- int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe, int instLimit = 0, bool addSplits = false );
+ int addInstantiations( Node f, InstMatch& baseMatch, QuantifiersEngine* qe );
/** add ground term t, possibly add instantiations */
int addTerm( Node f, Node t, QuantifiersEngine* qe );
};/* class InstMatchGeneratorSimple */
void InstantiatorDefault::processResetInstantiationRound( Theory::Effort effort ){
}
-int InstantiatorDefault::process( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstantiatorDefault::process( Node f, Theory::Effort effort, int e ){
+ /*
if( e < 4 ){
return InstStrategy::STATUS_UNFINISHED;
}else if( e == 4 ){
}
d_quantEngine->addInstantiation( f, m );
}
+ */
return InstStrategy::STATUS_UNKNOWN;
}
/** reset instantiation round */
void processResetInstantiationRound(Theory::Effort effort);
/** process quantifier */
- int process(Node f, Theory::Effort effort, int e, int limitInst = 0);
+ int process( Node f, Theory::Effort effort, int e );
public:
InstantiatorDefault(context::Context* c, QuantifiersEngine* ie, Theory* th);
~InstantiatorDefault() { }
--- /dev/null
+/********************* */\r
+/*! \file model.cpp\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Implementation of model class\r
+ **/\r
+\r
+#include "theory/model.h"\r
+#include "theory/quantifiers_engine.h"\r
+#include "theory/theory_engine.h"\r
+\r
+using namespace std;\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::context;\r
+using namespace CVC4::theory;\r
+\r
+void RepSet::clear(){\r
+ d_type_reps.clear();\r
+ d_tmap.clear();\r
+}\r
+\r
+void RepSet::add( Node n ){\r
+ TypeNode t = n.getType();\r
+ d_tmap[ n ] = (int)d_type_reps[t].size();\r
+ d_type_reps[t].push_back( n );\r
+}\r
+\r
+void RepSet::set( TypeNode t, std::vector< Node >& reps ){\r
+ for( size_t i=0; i<reps.size(); i++ ){\r
+ d_tmap[ reps[i] ] = i;\r
+ }\r
+ d_type_reps[t].insert( d_type_reps[t].begin(), reps.begin(), reps.end() );\r
+}\r
+\r
+void RepSet::toStream(std::ostream& out){\r
+#if 0\r
+ for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){\r
+ out << it->first << " : " << std::endl;\r
+ for( int i=0; i<(int)it->second.size(); i++ ){\r
+ out << " " << i << ": " << it->second[i] << std::endl;\r
+ }\r
+ }\r
+#else\r
+ for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){\r
+ if( !it->first.isFunction() && !it->first.isPredicate() ){\r
+ out << "(" << it->first << " " << it->second.size();\r
+ out << " (";\r
+ for( int i=0; i<(int)it->second.size(); i++ ){\r
+ if( i>0 ){ out << " "; }\r
+ out << it->second[i];\r
+ }\r
+ out << ")";\r
+ out << ")" << std::endl;\r
+ }\r
+ }\r
+#endif\r
+}\r
+\r
+TheoryModel::TheoryModel( context::Context* c, std::string name ) :\r
+d_equalityEngine( c, name ){\r
+ d_true = NodeManager::currentNM()->mkConst( true );\r
+ d_false = NodeManager::currentNM()->mkConst( false );\r
+}\r
+\r
+void TheoryModel::addDefineFunction( Node n ){\r
+ d_define_funcs.push_back( n );\r
+ d_defines.push_back( 0 );\r
+}\r
+\r
+void TheoryModel::addDefineType( TypeNode tn ){\r
+ d_define_types.push_back( tn );\r
+ d_defines.push_back( 1 );\r
+}\r
+\r
+void TheoryModel::toStreamFunction( Node n, std::ostream& out ){\r
+ out << "(" << n;\r
+ //out << " : " << n.getType();\r
+ out << " ";\r
+ Node value = getValue( n );\r
+ if( n.getType().isSort() ){\r
+ int index = d_ra.getIndexFor( value );\r
+ if( index!=-1 ){\r
+ out << value.getType() << "_" << index;\r
+ }else{\r
+ out << value;\r
+ }\r
+ }else{\r
+ out << value;\r
+ }\r
+ out << ")" << std::endl;\r
+}\r
+\r
+void TheoryModel::toStreamType( TypeNode tn, std::ostream& out ){\r
+ out << "(" << tn;\r
+ if( tn.isSort() ){\r
+ if( d_ra.d_type_reps.find( tn )!=d_ra.d_type_reps.end() ){\r
+ out << " " << d_ra.d_type_reps[tn].size();\r
+ //out << " (";\r
+ //for( size_t i=0; i<d_ra.d_type_reps[tn].size(); i++ ){\r
+ // if( i>0 ){ out << " "; }\r
+ // out << d_ra.d_type_reps[tn][i];\r
+ //}\r
+ //out << ")";\r
+ }\r
+ }\r
+ out << ")" << std::endl;\r
+}\r
+\r
+void TheoryModel::toStream( std::ostream& out ){\r
+ int funcIndex = 0;\r
+ int typeIndex = 0;\r
+ for( size_t i=0; i<d_defines.size(); i++ ){\r
+ if( d_defines[i]==0 ){\r
+ toStreamFunction( d_define_funcs[funcIndex], out );\r
+ funcIndex++;\r
+ }else if( d_defines[i]==1 ){\r
+ toStreamType( d_define_types[typeIndex], out );\r
+ typeIndex++;\r
+ }\r
+ }\r
+}\r
+\r
+Node TheoryModel::getValue( TNode n ){\r
+ Debug("model") << "TheoryModel::getValue " << n << std::endl;\r
+\r
+ kind::MetaKind metakind = n.getMetaKind();\r
+\r
+ //// special case: prop engine handles boolean vars\r
+ //if(metakind == kind::metakind::VARIABLE && n.getType().isBoolean()) {\r
+ // Debug("model") << "-> Propositional variable." << std::endl;\r
+ // return d_te->getPropEngine()->getValue( n );\r
+ //}\r
+\r
+ // special case: value of a constant == itself\r
+ if(metakind == kind::metakind::CONSTANT) {\r
+ Debug("model") << "-> Constant." << std::endl;\r
+ return n;\r
+ }\r
+\r
+ // see if the value is explicitly set in the model\r
+ if( d_equalityEngine.hasTerm( n ) ){\r
+ Debug("model") << "-> Defined term." << std::endl;\r
+ return getRepresentative( n );\r
+ }else{\r
+ Node nn;\r
+ if( n.getNumChildren()>0 ){\r
+ std::vector< Node > children;\r
+ if( metakind == kind::metakind::PARAMETERIZED ){\r
+ Debug("model-debug") << "get operator: " << n.getOperator() << std::endl;\r
+ children.push_back( n.getOperator() );\r
+ }\r
+ //evaluate the children\r
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+ Node val = getValue( n[i] );\r
+ Debug("model-debug") << i << " : " << n[i] << " -> " << val << std::endl;\r
+ Assert( !val.isNull() );\r
+ children.push_back( val );\r
+ }\r
+ Debug("model-debug") << "Done eval children" << std::endl;\r
+ nn = NodeManager::currentNM()->mkNode( n.getKind(), children );\r
+ }else{\r
+ nn = n;\r
+ }\r
+ //interpretation is the rewritten form\r
+ nn = Rewriter::rewrite( nn );\r
+\r
+ // special case: value of a constant == itself\r
+ if(metakind == kind::metakind::CONSTANT) {\r
+ Debug("model") << "-> Theory-interpreted term." << std::endl;\r
+ return nn;\r
+ }else if( d_equalityEngine.hasTerm( nn ) ){\r
+ Debug("model") << "-> Theory-interpreted (defined) term." << std::endl;\r
+ return getRepresentative( nn );\r
+ }else{\r
+ Debug("model") << "-> Model-interpreted term." << std::endl;\r
+ //otherwise, get the interpreted value in the model\r
+ return getInterpretedValue( nn );\r
+ }\r
+ }\r
+\r
+ ////case for equality\r
+ //if( n.getKind()==EQUAL ){\r
+ // Debug("model") << "-> Equality." << std::endl;\r
+ // Node n1 = getValue( n[0] );\r
+ // Node n2 = getValue( n[1] );\r
+ // return NodeManager::currentNM()->mkConst( n1==n2 );\r
+ //}\r
+}\r
+\r
+Node TheoryModel::getDomainValue( TypeNode tn, std::vector< Node >& exclude ){\r
+ if( d_ra.d_type_reps.find( tn )!=d_ra.d_type_reps.end() ){\r
+ //try to find a pre-existing arbitrary element\r
+ for( size_t i=0; i<d_ra.d_type_reps[tn].size(); i++ ){\r
+ if( std::find( exclude.begin(), exclude.end(), d_ra.d_type_reps[tn][i] )==exclude.end() ){\r
+ return d_ra.d_type_reps[tn][i];\r
+ }\r
+ }\r
+ }\r
+ return Node::null();\r
+}\r
+\r
+//FIXME: use the theory enumerator to generate constants here\r
+Node TheoryModel::getNewDomainValue( TypeNode tn, bool mkConst ){\r
+ if( tn==NodeManager::currentNM()->booleanType() ){\r
+ if( d_ra.d_type_reps[tn].empty() ){\r
+ return d_false;\r
+ }else if( d_ra.d_type_reps[tn].size()==1 ){\r
+ return NodeManager::currentNM()->mkConst( areEqual( d_ra.d_type_reps[tn][0], d_false ) );\r
+ }else{\r
+ return Node::null();\r
+ }\r
+ }else if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){\r
+ int val = 0;\r
+ do{\r
+ Node r = NodeManager::currentNM()->mkConst( Rational(val) );\r
+ if( std::find( d_ra.d_type_reps[tn].begin(), d_ra.d_type_reps[tn].end(), r )==d_ra.d_type_reps[tn].end() &&\r
+ !d_equalityEngine.hasTerm( r ) ){\r
+ return r;\r
+ }\r
+ val++;\r
+ }while( true );\r
+ }else{\r
+ //otherwise must make a variable FIXME: how to make constants for other sorts?\r
+ //return NodeManager::currentNM()->mkVar( tn );\r
+ return Node::null();\r
+ }\r
+}\r
+\r
+/** assert equality */\r
+void TheoryModel::assertEquality( Node a, Node b, bool polarity ){\r
+ d_equalityEngine.assertEquality( a.eqNode(b), polarity, Node::null() );\r
+}\r
+\r
+/** assert predicate */\r
+void TheoryModel::assertPredicate( Node a, bool polarity ){\r
+ if( a.getKind()==EQUAL ){\r
+ d_equalityEngine.assertEquality( a, polarity, Node::null() );\r
+ }else{\r
+ d_equalityEngine.assertPredicate( a, polarity, Node::null() );\r
+ }\r
+}\r
+\r
+/** assert equality engine */\r
+void TheoryModel::assertEqualityEngine( eq::EqualityEngine* ee ){\r
+ eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee );\r
+ while( !eqcs_i.isFinished() ){\r
+ Node eqc = (*eqcs_i);\r
+ bool predicate = false;\r
+ bool predPolarity = false;\r
+ if( eqc.getType()==NodeManager::currentNM()->booleanType() ){\r
+ predicate = true;\r
+ predPolarity = ee->areEqual( eqc, d_true );\r
+ //FIXME: do we guarentee that all boolean equivalence classes contain either d_true or d_false?\r
+ }\r
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, ee );\r
+ while( !eqc_i.isFinished() ){\r
+ if( predicate ){\r
+ assertPredicate( *eqc_i, predPolarity );\r
+ }else{\r
+ assertEquality( *eqc_i, eqc, true );\r
+ }\r
+ ++eqc_i;\r
+ }\r
+ ++eqcs_i;\r
+ }\r
+}\r
+\r
+bool TheoryModel::hasTerm( Node a ){\r
+ return d_equalityEngine.hasTerm( a );\r
+}\r
+\r
+Node TheoryModel::getRepresentative( Node a ){\r
+ if( d_equalityEngine.hasTerm( a ) ){\r
+ return d_reps[ d_equalityEngine.getRepresentative( a ) ];\r
+ }else{\r
+ return a;\r
+ }\r
+}\r
+\r
+bool TheoryModel::areEqual( Node a, Node b ){\r
+ if( a==b ){\r
+ return true;\r
+ }else if( d_equalityEngine.hasTerm( a ) && d_equalityEngine.hasTerm( b ) ){\r
+ return d_equalityEngine.areEqual( a, b );\r
+ }else{\r
+ return false;\r
+ }\r
+}\r
+\r
+bool TheoryModel::areDisequal( Node a, Node b ){\r
+ if( d_equalityEngine.hasTerm( a ) && d_equalityEngine.hasTerm( b ) ){\r
+ return d_equalityEngine.areDisequal( a, b, false );\r
+ }else{\r
+ return false;\r
+ }\r
+}\r
+\r
+//for debugging\r
+void TheoryModel::printRepresentativeDebug( const char* c, Node r ){\r
+ if( r.isNull() ){\r
+ Debug( c ) << "null";\r
+ }else if( r.getType()==NodeManager::currentNM()->booleanType() ){\r
+ if( areEqual( r, d_true ) ){\r
+ Debug( c ) << "true";\r
+ }else{\r
+ Debug( c ) << "false";\r
+ }\r
+ }else{\r
+ Debug( c ) << getRepresentative( r );\r
+ }\r
+}\r
+\r
+void TheoryModel::printRepresentative( std::ostream& out, Node r ){\r
+ Assert( !r.isNull() );\r
+ if( r.isNull() ){\r
+ out << "null";\r
+ }else if( r.getType()==NodeManager::currentNM()->booleanType() ){\r
+ if( areEqual( r, d_true ) ){\r
+ out << "true";\r
+ }else{\r
+ out << "false";\r
+ }\r
+ }else{\r
+ out << getRepresentative( r );\r
+ }\r
+}\r
+\r
+DefaultModel::DefaultModel( context::Context* c, std::string name ) : TheoryModel( c, name ){\r
+\r
+}\r
+\r
+Node DefaultModel::getInterpretedValue( TNode n ){\r
+ Assert( !d_equalityEngine.hasTerm( n ) );\r
+ TypeNode type = n.getType();\r
+ if( type.isFunction() || type.isPredicate() ){\r
+ //DO_THIS?\r
+ return n;\r
+ }else{\r
+ //first, try to choose an existing term as value\r
+ std::vector< Node > v_emp;\r
+ Node n2 = getDomainValue( type, v_emp );\r
+ if( !n2.isNull() ){\r
+ return n2;\r
+ }else{\r
+ //otherwise, choose new valuse\r
+ n2 = getNewDomainValue( type, true );\r
+ if( !n2.isNull() ){\r
+ return n2;\r
+ }else{\r
+ return n;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+TheoryEngineModelBuilder::TheoryEngineModelBuilder( TheoryEngine* te ) : d_te( te ){\r
+\r
+}\r
+\r
+void TheoryEngineModelBuilder::buildModel( Model* m ){\r
+ TheoryModel* tm = (TheoryModel*)m;\r
+ //reset representative information\r
+ tm->d_reps.clear();\r
+ tm->d_ra.clear();\r
+ Debug( "model-builder" ) << "TheoryEngineModelBuilder: Collect model info..." << std::endl;\r
+ //collect model info from the theory engine\r
+ d_te->collectModelInfo( tm );\r
+ Debug( "model-builder" ) << "TheoryEngineModelBuilder: Build representatives..." << std::endl;\r
+ //populate term database, store representatives\r
+ eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &tm->d_equalityEngine );\r
+ while( !eqcs_i.isFinished() ){\r
+ Node eqc = (*eqcs_i);\r
+ //add terms to model\r
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &tm->d_equalityEngine );\r
+ while( !eqc_i.isFinished() ){\r
+ tm->addTerm( *eqc_i );\r
+ ++eqc_i;\r
+ }\r
+ //choose representative for this equivalence class\r
+ Node rep = chooseRepresentative( tm, eqc );\r
+ //store representative in representative set\r
+ if( !rep.isNull() ){\r
+ tm->d_reps[ eqc ] = rep;\r
+ tm->d_ra.add( rep );\r
+ }\r
+ ++eqcs_i;\r
+ }\r
+ //do model-builder specific initialization\r
+ // this should include choosing representatives for equivalence classes that have not yet been\r
+ // assigned representatives\r
+ processBuildModel( tm );\r
+}\r
+\r
+Node TheoryEngineModelBuilder::chooseRepresentative( TheoryModel* tm, Node eqc ){\r
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &tm->d_equalityEngine );\r
+ while( !eqc_i.isFinished() ){\r
+ //if constant, use this as representative\r
+ if( (*eqc_i).getMetaKind()==kind::metakind::CONSTANT ){\r
+ return *eqc_i;\r
+ }\r
+ ++eqc_i;\r
+ }\r
+ return Node::null();\r
+}\r
+\r
+void TheoryEngineModelBuilder::processBuildModel( TheoryModel* tm ){\r
+ Debug( "model-builder" ) << "TheoryEngineModelBuilder: Complete model..." << std::endl;\r
+ //create constants for all unresolved equivalence classes\r
+ eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &tm->d_equalityEngine );\r
+ while( !eqcs_i.isFinished() ){\r
+ Node n = *eqcs_i;\r
+ if( tm->d_reps.find( n )!=tm->d_reps.end() ){\r
+ TypeNode tn = n.getType();\r
+ //add new constant to equivalence class\r
+ Node rep = tm->getNewDomainValue( tn, true );\r
+ if( !rep.isNull() ){\r
+ tm->assertEquality( n, rep, true );\r
+ }else{\r
+ rep = n;\r
+ }\r
+ tm->d_reps[ n ] = rep;\r
+ tm->d_ra.add( rep );\r
+ }\r
+ ++eqcs_i;\r
+ }\r
+}\r
--- /dev/null
+/********************* */\r
+/*! \file model.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Model class\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__THEORY_MODEL_H\r
+#define __CVC4__THEORY_MODEL_H\r
+\r
+#include "util/model.h"\r
+#include "theory/uf/equality_engine.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+\r
+class QuantifiersEngine;\r
+\r
+/** this class stores a representative set */\r
+class RepSet {\r
+public:\r
+ RepSet(){}\r
+ ~RepSet(){}\r
+ std::map< TypeNode, std::vector< Node > > d_type_reps;\r
+ std::map< Node, int > d_tmap;\r
+ /** clear the set */\r
+ void clear();\r
+ /** has type */\r
+ bool hasType( TypeNode tn ) { return d_type_reps.find( tn )!=d_type_reps.end(); }\r
+ /** add representative for type */\r
+ void add( Node n );\r
+ /** set the representatives for type */\r
+ void set( TypeNode t, std::vector< Node >& reps );\r
+ /** returns index in d_type_reps for node n */\r
+ int getIndexFor( Node n ) { return d_tmap.find( n )!=d_tmap.end() ? d_tmap[n] : -1; }\r
+ /** debug print */\r
+ void toStream(std::ostream& out);\r
+};\r
+\r
+//representative domain\r
+typedef std::vector< int > RepDomain;\r
+\r
+class TheoryEngineModelBuilder;\r
+\r
+/** Theory Model class\r
+ * For Model m, should call m.initialize() before using\r
+ */\r
+class TheoryModel : public Model\r
+{\r
+ friend class TheoryEngineModelBuilder;\r
+protected:\r
+ /** add term */\r
+ virtual void addTerm( Node n ) {}\r
+private:\r
+ /** definitions */\r
+ std::vector< Node > d_define_funcs;\r
+ std::vector< TypeNode > d_define_types;\r
+ std::vector< int > d_defines;\r
+protected:\r
+ /** to stream functions */\r
+ virtual void toStreamFunction( Node n, std::ostream& out );\r
+ virtual void toStreamType( TypeNode tn, std::ostream& out );\r
+public:\r
+ TheoryModel( context::Context* c, std::string name );\r
+ virtual ~TheoryModel(){}\r
+ /** equality engine containing all known equalities/disequalities */\r
+ eq::EqualityEngine d_equalityEngine;\r
+ /** map of representatives of equality engine to used representatives in representative set */\r
+ std::map< Node, Node > d_reps;\r
+ /** representative alphabet */\r
+ RepSet d_ra;\r
+ //true/false nodes\r
+ Node d_true;\r
+ Node d_false;\r
+public:\r
+ /** add defined function */\r
+ void addDefineFunction( Node n );\r
+ /** add defined type */\r
+ void addDefineType( TypeNode tn );\r
+ /**\r
+ * Get value function. This should be called only after a ModelBuilder has called buildModel(...)\r
+ * on this model.\r
+ */\r
+ Node getValue( TNode n );\r
+ /** get interpreted value, should be a representative in d_reps */\r
+ virtual Node getInterpretedValue( TNode n ) = 0;\r
+ /** get existing domain value, with possible exclusions */\r
+ Node getDomainValue( TypeNode tn, std::vector< Node >& exclude );\r
+ /** get new domain value */\r
+ Node getNewDomainValue( TypeNode tn, bool mkConst = false );\r
+public:\r
+ /** assert equality */\r
+ void assertEquality( Node a, Node b, bool polarity );\r
+ /** assert predicate */\r
+ void assertPredicate( Node a, bool polarity );\r
+ /** assert equality engine */\r
+ void assertEqualityEngine( eq::EqualityEngine* ee );\r
+public:\r
+ //queries about equality\r
+ bool hasTerm( Node a );\r
+ Node getRepresentative( Node a );\r
+ bool areEqual( Node a, Node b );\r
+ bool areDisequal( Node a, Node b );\r
+public:\r
+ /** print representative function */\r
+ void printRepresentativeDebug( const char* c, Node r );\r
+ void printRepresentative( std::ostream& out, Node r );\r
+ /** to stream function */\r
+ void toStream( std::ostream& out );\r
+};\r
+\r
+//default model class: extends model arbitrarily\r
+class DefaultModel : public TheoryModel\r
+{\r
+public:\r
+ DefaultModel( context::Context* c, std::string name );\r
+ virtual ~DefaultModel(){}\r
+public:\r
+ Node getInterpretedValue( TNode n );\r
+};\r
+\r
+//incomplete model class: does not extend model\r
+class IncompleteModel : public TheoryModel\r
+{\r
+public:\r
+ IncompleteModel( context::Context* c, std::string name ) : TheoryModel( c, name ){}\r
+ virtual ~IncompleteModel(){}\r
+public:\r
+ Node getInterpretedValue( TNode n ) { return Node::null(); }\r
+};\r
+\r
+\r
+class TheoryEngineModelBuilder : public ModelBuilder\r
+{\r
+protected:\r
+ /** pointer to theory engine */\r
+ TheoryEngine* d_te;\r
+ /** choose representative */\r
+ virtual Node chooseRepresentative( TheoryModel* tm, Node eqc );\r
+ /** representatives that are current not set */\r
+ virtual void processBuildModel( TheoryModel* tm );\r
+public:\r
+ TheoryEngineModelBuilder( TheoryEngine* te );\r
+ virtual ~TheoryEngineModelBuilder(){}\r
+ /**\r
+ * Build model function.\r
+ */\r
+ void buildModel( Model* m );\r
+};\r
+\r
+}\r
+}\r
+\r
+#endif
\ No newline at end of file
instantiation_engine.h \
instantiation_engine.cpp \
model_engine.h \
- model_engine.cpp
+ model_engine.cpp \
+ relevant_domain.h \
+ relevant_domain.cpp \
+ rep_set_iterator.h \
+ rep_set_iterator.cpp \
+ term_database.h \
+ term_database.cpp \
+ first_order_model.h \
+ first_order_model.cpp
EXTRA_DIST = kinds
\ No newline at end of file
--- /dev/null
+/********************* */\r
+/*! \file first_order_model.cpp\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Implementation of model engine model class\r
+ **/\r
+\r
+#include "theory/quantifiers/first_order_model.h"\r
+#include "theory/quantifiers/rep_set_iterator.h"\r
+#include "theory/quantifiers/model_engine.h"\r
+#include "theory/uf/theory_uf_strong_solver.h"\r
+\r
+using namespace std;\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::context;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::quantifiers;\r
+\r
+FirstOrderModel::FirstOrderModel( QuantifiersEngine* qe, context::Context* c, std::string name ) : DefaultModel( c, name ),\r
+d_term_db( qe->getTermDatabase() ), d_forall_asserts( c ){\r
+\r
+}\r
+\r
+void FirstOrderModel::initialize(){\r
+ //rebuild models\r
+ d_uf_model.clear();\r
+ d_array_model.clear();\r
+ //for each quantifier, collect all operators we care about\r
+ for( int i=0; i<getNumAssertedQuantifiers(); i++ ){\r
+ Node f = getAssertedQuantifier( i );\r
+ //initialize model for term\r
+ initializeModelForTerm( f[1] );\r
+ }\r
+\r
+ if( Options::current()->printModelEngine ){\r
+ for( std::map< TypeNode, std::vector< Node > >::iterator it = d_ra.d_type_reps.begin(); it != d_ra.d_type_reps.end(); ++it ){\r
+ if( uf::StrongSolverTheoryUf::isRelevantType( it->first ) ){\r
+ Message() << "Cardinality( " << it->first << " )" << " = " << it->second.size() << std::endl;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+void FirstOrderModel::initializeModelForTerm( Node n ){\r
+ if( n.getKind()==APPLY_UF ){\r
+ Node op = n.getOperator();\r
+ if( d_uf_model.find( op )==d_uf_model.end() ){\r
+ TypeNode tn = op.getType();\r
+ tn = tn[ (int)tn.getNumChildren()-1 ];\r
+ if( tn==NodeManager::currentNM()->booleanType() || uf::StrongSolverTheoryUf::isRelevantType( tn ) ){\r
+ d_uf_model[ op ] = uf::UfModel( op, this );\r
+ }\r
+ }\r
+ }\r
+ if( n.getKind()!=STORE && n.getType().isArray() ){\r
+ d_array_model[n] = Node::null();\r
+ }\r
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+ initializeModelForTerm( n[i] );\r
+ }\r
+}\r
+\r
+void FirstOrderModel::toStreamFunction( Node n, std::ostream& out ){\r
+ if( d_uf_model.find( n )!=d_uf_model.end() ){\r
+ //d_uf_model[n].toStream( out );\r
+ Node value = d_uf_model[n].getFunctionValue();\r
+ out << "(" << n << " " << value << ")";\r
+ //}else if( d_array_model.find( n )!=d_array_model.end() ){\r
+ //out << "(" << n << " " << d_array_model[n] << ")" << std::endl;\r
+ // out << "(" << n << " Array)" << std::endl;\r
+ }else{\r
+ DefaultModel::toStreamFunction( n, out );\r
+ }\r
+}\r
+\r
+void FirstOrderModel::toStreamType( TypeNode tn, std::ostream& out ){\r
+ DefaultModel::toStreamType( tn, out );\r
+}\r
+\r
+Node FirstOrderModel::getInterpretedValue( TNode n ){\r
+ Debug("fo-model") << "get interpreted value " << n << std::endl;\r
+ TypeNode type = n.getType();\r
+ if( type.isFunction() || type.isPredicate() ){\r
+ if( d_uf_model.find( n )!=d_uf_model.end() ){\r
+ return d_uf_model[n].getFunctionValue();\r
+ }else{\r
+ return n;\r
+ }\r
+ }else if( n.getKind()==APPLY_UF ){\r
+ int depIndex;\r
+ return d_uf_model[ n.getOperator() ].getValue( n, depIndex );\r
+ }\r
+ return DefaultModel::getInterpretedValue( n );\r
+}\r
+\r
+TermDb* FirstOrderModel::getTermDatabase(){\r
+ return d_term_db;\r
+}\r
+\r
+\r
+void FirstOrderModel::toStream(std::ostream& out){\r
+ DefaultModel::toStream( out );\r
+#if 0\r
+ out << "---Current Model---" << std::endl;\r
+ out << "Representatives: " << std::endl;\r
+ d_ra.toStream( out );\r
+ out << "Functions: " << std::endl;\r
+ for( std::map< Node, uf::UfModel >::iterator it = d_uf_model.begin(); it != d_uf_model.end(); ++it ){\r
+ it->second.toStream( out );\r
+ out << std::endl;\r
+ }\r
+#elif 0\r
+ d_ra.toStream( out );\r
+ //print everything not related to UF in equality engine\r
+ eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );\r
+ while( !eqcs_i.isFinished() ){\r
+ Node eqc = (*eqcs_i);\r
+ Node rep = getRepresentative( eqc );\r
+ TypeNode type = rep.getType();\r
+ eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc, &d_equalityEngine );\r
+ while( !eqc_i.isFinished() ){\r
+ //do not print things that have interpretations in model\r
+ if( (*eqc_i).getMetaKind()!=kind::metakind::CONSTANT && !hasInterpretedValue( *eqc_i ) ){\r
+ out << "(" << (*eqc_i) << " " << rep << ")" << std::endl;\r
+ }\r
+ ++eqc_i;\r
+ }\r
+ ++eqcs_i;\r
+ }\r
+ //print functions\r
+ for( std::map< Node, uf::UfModel >::iterator it = d_uf_model.begin(); it != d_uf_model.end(); ++it ){\r
+ it->second.toStream( out );\r
+ out << std::endl;\r
+ }\r
+#endif\r
+}
\ No newline at end of file
--- /dev/null
+/********************* */\r
+/*! \file first_order_model.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Model extended classes\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__FIRST_ORDER_MODEL_H\r
+#define __CVC4__FIRST_ORDER_MODEL_H\r
+\r
+#include "theory/model.h"\r
+#include "theory/uf/theory_uf_model.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+\r
+struct ModelBasisAttributeId {};\r
+typedef expr::Attribute<ModelBasisAttributeId, bool> ModelBasisAttribute;\r
+//for APPLY_UF terms, 1 : term has direct child with model basis attribute,\r
+// 0 : term has no direct child with model basis attribute.\r
+struct ModelBasisArgAttributeId {};\r
+typedef expr::Attribute<ModelBasisArgAttributeId, uint64_t> ModelBasisArgAttribute;\r
+\r
+class QuantifiersEngine;\r
+\r
+namespace quantifiers{\r
+\r
+class TermDb;\r
+\r
+class FirstOrderModel : public DefaultModel\r
+{\r
+private:\r
+ //pointer to term database\r
+ TermDb* d_term_db;\r
+ //for initialize model\r
+ void initializeModelForTerm( Node n );\r
+ /** to stream functions */\r
+ void toStreamFunction( Node n, std::ostream& out );\r
+ void toStreamType( TypeNode tn, std::ostream& out );\r
+public: //for Theory UF:\r
+ //models for each UF operator\r
+ std::map< Node, uf::UfModel > d_uf_model;\r
+public: //for Theory Arrays:\r
+ //default value for each non-store array\r
+ std::map< Node, Node > d_array_model;\r
+public: //for Theory Quantifiers:\r
+ /** list of quantifiers asserted in the current context */\r
+ context::CDList<Node> d_forall_asserts;\r
+ /** get number of asserted quantifiers */\r
+ int getNumAssertedQuantifiers() { return (int)d_forall_asserts.size(); }\r
+ /** get asserted quantifier */\r
+ Node getAssertedQuantifier( int i ) { return d_forall_asserts[i]; }\r
+public:\r
+ FirstOrderModel( QuantifiersEngine* qe, context::Context* c, std::string name );\r
+ virtual ~FirstOrderModel(){}\r
+ // initialize the model\r
+ void initialize();\r
+ /** get interpreted value */\r
+ Node getInterpretedValue( TNode n );\r
+public:\r
+ /** get term database */\r
+ TermDb* getTermDatabase();\r
+ /** to stream function */\r
+ void toStream( std::ostream& out );\r
+};\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif\r
#include "theory/theory_engine.h"
#include "theory/uf/theory_uf_instantiator.h"
+#include "theory/quantifiers/term_database.h"
+#include "theory/quantifiers/first_order_model.h"
using namespace std;
using namespace CVC4;
using namespace CVC4::theory;
using namespace CVC4::theory::quantifiers;
-//#define IE_PRINT_PROCESS_TIMES
+InstantiationEngine::InstantiationEngine( QuantifiersEngine* qe, bool setIncomplete ) :
+QuantifiersModule( qe ), d_setIncomplete( setIncomplete ){
-InstantiationEngine::InstantiationEngine( TheoryQuantifiers* th ) :
-d_th( th ){
-
-}
-
-QuantifiersEngine* InstantiationEngine::getQuantifiersEngine(){
- return d_th->getQuantifiersEngine();
}
bool InstantiationEngine::hasAddedCbqiLemma( Node f ) {
//code for counterexample-based quantifier instantiation
Debug("cbqi") << "Do cbqi for " << f << std::endl;
//make the counterexample body
- //Node ceBody = f[1].substitute( getQuantifiersEngine()->d_vars[f].begin(), getQuantifiersEngine()->d_vars[f].end(),
- // getQuantifiersEngine()->d_inst_constants[f].begin(),
- // getQuantifiersEngine()->d_inst_constants[f].end() );
+ //Node ceBody = f[1].substitute( d_quantEngine->d_vars[f].begin(), d_quantEngine->d_vars[f].end(),
+ // d_quantEngine->d_inst_constants[f].begin(),
+ // d_quantEngine->d_inst_constants[f].end() );
//get the counterexample literal
- Node ceBody = getQuantifiersEngine()->getCounterexampleBody( f );
- Node ceLit = d_th->getValuation().ensureLiteral( ceBody.notNode() );
+ Node ceBody = d_quantEngine->getTermDatabase()->getCounterexampleBody( f );
+ Node ceLit = d_quantEngine->getValuation().ensureLiteral( ceBody.notNode() );
d_ce_lit[ f ] = ceLit;
- getQuantifiersEngine()->setInstantiationConstantAttr( ceLit, f );
+ d_quantEngine->getTermDatabase()->setInstantiationConstantAttr( ceLit, f );
// set attributes, mark all literals in the body of n as dependent on cel
//registerLiterals( ceLit, f );
//require any decision on cel to be phase=true
- d_th->getOutputChannel().requirePhase( ceLit, true );
+ d_quantEngine->getOutputChannel().requirePhase( ceLit, true );
Debug("cbqi-debug") << "Require phase " << ceLit << " = true." << std::endl;
//add counterexample lemma
NodeBuilder<> nb(kind::OR);
nb << f << ceLit;
Node lem = nb;
Debug("cbqi-debug") << "Counterexample lemma : " << lem << std::endl;
- d_th->getOutputChannel().lemma( lem );
+ d_quantEngine->getOutputChannel().lemma( lem );
}
bool InstantiationEngine::doInstantiationRound( Theory::Effort effort ){
if( Options::current()->cbqi ){
//check if any cbqi lemma has not been added yet
bool addedLemma = false;
- for( int i=0; i<(int)getQuantifiersEngine()->getNumAssertedQuantifiers(); i++ ){
- Node f = getQuantifiersEngine()->getAssertedQuantifier( i );
+ for( int i=0; i<(int)d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
if( doCbqi( f ) && !hasAddedCbqiLemma( f ) ){
//add cbqi lemma
addCbqiLemma( f );
//if not, proceed to instantiation round
Debug("inst-engine") << "IE: Instantiation Round." << std::endl;
Debug("inst-engine-ctrl") << "IE: Instantiation Round." << std::endl;
- //reset instantiators
+ //reset the quantifiers engine
Debug("inst-engine-ctrl") << "Reset IE" << std::endl;
- for( int i=0; i<theory::THEORY_LAST; i++ ){
- if( getQuantifiersEngine()->getInstantiator( i ) ){
- getQuantifiersEngine()->getInstantiator( i )->resetInstantiationRound( effort );
- }
- }
- getQuantifiersEngine()->getTermDatabase()->reset( effort );
+ d_quantEngine->resetInstantiationRound( effort );
//iterate over an internal effort level e
int e = 0;
int eLimit = effort==Theory::EFFORT_LAST_CALL ? 10 : 2;
Debug("inst-engine") << "IE: Prepare instantiation (" << e << ")." << std::endl;
d_inst_round_status = InstStrategy::STATUS_SAT;
//instantiate each quantifier
- for( int q=0; q<getQuantifiersEngine()->getNumAssertedQuantifiers(); q++ ){
- Node f = getQuantifiersEngine()->getAssertedQuantifier( q );
+ for( int q=0; q<d_quantEngine->getModel()->getNumAssertedQuantifiers(); q++ ){
+ Node f = d_quantEngine->getModel()->getAssertedQuantifier( q );
Debug("inst-engine-debug") << "IE: Instantiate " << f << "..." << std::endl;
//if this quantifier is active
- if( getQuantifiersEngine()->getActive( f ) ){
- //int e_use = getQuantifiersEngine()->getRelevance( f )==-1 ? e - 1 : e;
+ if( d_quantEngine->getActive( f ) ){
+ //int e_use = d_quantEngine->getRelevance( f )==-1 ? e - 1 : e;
int e_use = e;
if( e_use>=0 ){
//use each theory instantiator to instantiate f
for( int i=0; i<theory::THEORY_LAST; i++ ){
- if( getQuantifiersEngine()->getInstantiator( i ) ){
- Debug("inst-engine-debug") << "Do " << getQuantifiersEngine()->getInstantiator( i )->identify() << " " << e_use << std::endl;
- int limitInst = 0;
- int quantStatus = getQuantifiersEngine()->getInstantiator( i )->doInstantiation( f, effort, e_use, limitInst );
+ if( d_quantEngine->getInstantiator( i ) ){
+ Debug("inst-engine-debug") << "Do " << d_quantEngine->getInstantiator( i )->identify() << " " << e_use << std::endl;
+ int quantStatus = d_quantEngine->getInstantiator( i )->doInstantiation( f, effort, e_use );
Debug("inst-engine-debug") << " -> status is " << quantStatus << std::endl;
InstStrategy::updateStatus( d_inst_round_status, quantStatus );
}
}
}
//do not consider another level if already added lemma at this level
- if( getQuantifiersEngine()->hasAddedLemma() ){
+ if( d_quantEngine->hasAddedLemma() ){
d_inst_round_status = InstStrategy::STATUS_UNKNOWN;
}
e++;
}
Debug("inst-engine") << "All instantiators finished, # added lemmas = ";
- Debug("inst-engine") << (int)getQuantifiersEngine()->d_lemmas_waiting.size() << std::endl;
+ Debug("inst-engine") << (int)d_quantEngine->d_lemmas_waiting.size() << std::endl;
//Notice() << "All instantiators finished, # added lemmas = " << (int)d_lemmas_waiting.size() << std::endl;
- if( !getQuantifiersEngine()->hasAddedLemma() ){
+ if( !d_quantEngine->hasAddedLemma() ){
Debug("inst-engine-stuck") << "No instantiations produced at this state: " << std::endl;
for( int i=0; i<theory::THEORY_LAST; i++ ){
- if( getQuantifiersEngine()->getInstantiator( i ) ){
- getQuantifiersEngine()->getInstantiator( i )->debugPrint("inst-engine-stuck");
+ if( d_quantEngine->getInstantiator( i ) ){
+ d_quantEngine->getInstantiator( i )->debugPrint("inst-engine-stuck");
Debug("inst-engine-stuck") << std::endl;
}
}
Debug("inst-engine-ctrl") << "---Fail." << std::endl;
return false;
}else{
- Debug("inst-engine-ctrl") << "---Done. " << (int)getQuantifiersEngine()->d_lemmas_waiting.size() << std::endl;
-#ifdef IE_PRINT_PROCESS_TIMES
- Notice() << "lemmas = " << (int)getQuantifiersEngine()->d_lemmas_waiting.size() << std::endl;
-#endif
+ Debug("inst-engine-ctrl") << "---Done. " << (int)d_quantEngine->d_lemmas_waiting.size() << std::endl;
+ if( Options::current()->printInstEngine ){
+ Message() << "Added lemmas = " << (int)d_quantEngine->d_lemmas_waiting.size() << std::endl;
+ }
//flush lemmas to output channel
- getQuantifiersEngine()->flushLemmas( &d_th->getOutputChannel() );
+ d_quantEngine->flushLemmas( &d_quantEngine->getOutputChannel() );
return true;
}
}
}
if( performCheck ){
Debug("inst-engine") << "IE: Check " << e << " " << ierCounter << std::endl;
-#ifdef IE_PRINT_PROCESS_TIMES
- double clSet = double(clock())/double(CLOCKS_PER_SEC);
- Notice() << "Run instantiation round " << e << " " << ierCounter << std::endl;
-#endif
+ double clSet = 0;
+ if( Options::current()->printInstEngine ){
+ clSet = double(clock())/double(CLOCKS_PER_SEC);
+ Message() << "---Instantiation Engine Round, effort = " << e << "---" << std::endl;
+ }
bool quantActive = false;
//for each quantifier currently asserted,
// such that the counterexample literal is not in positive in d_counterexample_asserts
// for( BoolMap::iterator i = d_forall_asserts.begin(); i != d_forall_asserts.end(); i++ ) {
// if( (*i).second ) {
- Debug("quantifiers") << "quantifiers: check: asserted quantifiers size"
- << getQuantifiersEngine()->getNumAssertedQuantifiers() << std::endl;
- for( int i=0; i<(int)getQuantifiersEngine()->getNumAssertedQuantifiers(); i++ ){
- Node n = getQuantifiersEngine()->getAssertedQuantifier( i );
+ Debug("quantifiers") << "quantifiers: check: asserted quantifiers size"
+ << d_quantEngine->getModel()->getNumAssertedQuantifiers() << std::endl;
+ for( int i=0; i<(int)d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node n = d_quantEngine->getModel()->getAssertedQuantifier( i );
if( Options::current()->cbqi && hasAddedCbqiLemma( n ) ){
Node cel = d_ce_lit[ n ];
bool active, value;
bool ceValue = false;
- if( d_th->getValuation().hasSatValue( cel, value ) ){
+ if( d_quantEngine->getValuation().hasSatValue( cel, value ) ){
active = value;
ceValue = true;
}else{
active = true;
}
- getQuantifiersEngine()->setActive( n, active );
+ d_quantEngine->setActive( n, active );
if( active ){
Debug("quantifiers") << " Active : " << n;
quantActive = true;
}else{
Debug("quantifiers") << " NOT active : " << n;
- if( d_th->getValuation().isDecision( cel ) ){
+ if( d_quantEngine->getValuation().isDecision( cel ) ){
Debug("quant-req-phase") << "Bad decision : " << cel << std::endl;
}
//note that the counterexample literal must not be a decision
- Assert( !d_th->getValuation().isDecision( cel ) );
+ Assert( !d_quantEngine->getValuation().isDecision( cel ) );
}
- if( d_th->getValuation().hasSatValue( n, value ) ){
+ if( d_quantEngine->getValuation().hasSatValue( n, value ) ){
Debug("quantifiers") << ", value = " << value;
}
if( ceValue ){
}
Debug("quantifiers") << std::endl;
}else{
- getQuantifiersEngine()->setActive( n, true );
+ d_quantEngine->setActive( n, true );
quantActive = true;
Debug("quantifiers") << " Active : " << n << ", no ce assigned." << std::endl;
}
Debug("quantifiers-relevance") << "Quantifier : " << n << std::endl;
- Debug("quantifiers-relevance") << " Relevance : " << getQuantifiersEngine()->getRelevance( n ) << std::endl;
- Debug("quantifiers") << " Relevance : " << getQuantifiersEngine()->getRelevance( n ) << std::endl;
+ Debug("quantifiers-relevance") << " Relevance : " << d_quantEngine->getRelevance( n ) << std::endl;
+ Debug("quantifiers") << " Relevance : " << d_quantEngine->getRelevance( n ) << std::endl;
}
//}
if( quantActive ){
bool addedLemmas = doInstantiationRound( e );
- //Debug("quantifiers-dec") << "Do instantiation, level = " << d_th->getValuation().getDecisionLevel() << std::endl;
+ //Debug("quantifiers-dec") << "Do instantiation, level = " << d_quantEngine->getValuation().getDecisionLevel() << std::endl;
//for( int i=1; i<=(int)d_valuation.getDecisionLevel(); i++ ){
// Debug("quantifiers-dec") << " " << d_valuation.getDecision( i ) << std::endl;
//}
if( d_inst_round_status==InstStrategy::STATUS_SAT ){
Debug("inst-engine") << "No instantiation given, returning SAT..." << std::endl;
debugSat( SAT_INST_STRATEGY );
- }else{
+ }else if( d_setIncomplete ){
Debug("inst-engine") << "No instantiation given, returning unknown..." << std::endl;
- d_th->getOutputChannel().setIncomplete();
+ d_quantEngine->getOutputChannel().setIncomplete();
+ }else{
+ Assert( Options::current()->finiteModelFind );
+ Debug("inst-engine") << "No instantiation given, defer to another engine..." << std::endl;
}
}
}
}
}
}
-#ifdef IE_PRINT_PROCESS_TIMES
- double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
- Notice() << "Done Run instantiation round " << (clSet2-clSet) << std::endl;
-#endif
+ if( Options::current()->printInstEngine ){
+ double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
+ Message() << "Finished instantiation engine, time = " << (clSet2-clSet) << std::endl;
+ }
}
}
void InstantiationEngine::registerQuantifier( Node f ){
//Notice() << "do cbqi " << f << " ? " << std::endl;
- Node ceBody = getQuantifiersEngine()->getCounterexampleBody( f );
+ Node ceBody = d_quantEngine->getTermDatabase()->getCounterexampleBody( f );
if( !doCbqi( f ) ){
- getQuantifiersEngine()->addTermToDatabase( ceBody, true );
+ d_quantEngine->addTermToDatabase( ceBody, true );
//need to tell which instantiators will be responsible
//by default, just chose the UF instantiator
- getQuantifiersEngine()->getInstantiator( theory::THEORY_UF )->setHasConstraintsFrom( f );
+ d_quantEngine->getInstantiator( theory::THEORY_UF )->setHasConstraintsFrom( f );
}
//take into account user patterns
if( f.getNumChildren()==3 ){
- Node subsPat = getQuantifiersEngine()->getSubstitutedNode( f[2], f );
+ Node subsPat = d_quantEngine->getTermDatabase()->getSubstitutedNode( f[2], f );
//add patterns
for( int i=0; i<(int)subsPat.getNumChildren(); i++ ){
//Notice() << "Add pattern " << subsPat[i] << " for " << f << std::endl;
- ((uf::InstantiatorTheoryUf*)getQuantifiersEngine()->getInstantiator( theory::THEORY_UF ))->addUserPattern( f, subsPat[i] );
+ ((uf::InstantiatorTheoryUf*)d_quantEngine->getInstantiator( theory::THEORY_UF ))->addUserPattern( f, subsPat[i] );
}
}
}
// registerLiterals( n[i], f );
// }
// if( !d_ce_lit[ f ].isNull() ){
-// if( getQuantifiersEngine()->d_te->getPropEngine()->isSatLiteral( n ) && n.getKind()!=NOT ){
+// if( d_quantEngine->d_te->getPropEngine()->isSatLiteral( n ) && n.getKind()!=NOT ){
// if( n!=d_ce_lit[ f ] && n.notNode()!=d_ce_lit[ f ] ){
// Debug("quant-dep-dec") << "Make " << n << " dependent on ";
// Debug("quant-dep-dec") << d_ce_lit[ f ] << std::endl;
-// d_th->getOutputChannel().dependentDecision( d_ce_lit[ f ], n );
+// d_quantEngine->getOutputChannel().dependentDecision( d_ce_lit[ f ], n );
// }
// }
// }
void InstantiationEngine::debugSat( int reason ){
if( reason==SAT_CBQI ){
//Debug("quantifiers-sat") << "Decisions:" << std::endl;
- //for( int i=1; i<=(int)d_th->getValuation().getDecisionLevel(); i++ ){
- // Debug("quantifiers-sat") << " " << i << ": " << d_th->getValuation().getDecision( i ) << std::endl;
+ //for( int i=1; i<=(int)d_quantEngine->getValuation().getDecisionLevel(); i++ ){
+ // Debug("quantifiers-sat") << " " << i << ": " << d_quantEngine->getValuation().getDecision( i ) << std::endl;
//}
//for( BoolMap::iterator i = d_forall_asserts.begin(); i != d_forall_asserts.end(); i++ ) {
// if( (*i).second ) {
- for( int i=0; i<(int)getQuantifiersEngine()->getNumAssertedQuantifiers(); i++ ){
- Node f = getQuantifiersEngine()->getAssertedQuantifier( i );
+ for( int i=0; i<(int)d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
Node cel = d_ce_lit[ f ];
Assert( !cel.isNull() );
bool value;
- if( d_th->getValuation().hasSatValue( cel, value ) ){
+ if( d_quantEngine->getValuation().hasSatValue( cel, value ) ){
if( !value ){
- AlwaysAssert(! d_th->getValuation().isDecision( cel ),
+ AlwaysAssert(! d_quantEngine->getValuation().isDecision( cel ),
"bad decision on counterexample literal");
}
}
//propagate as decision all counterexample literals that are not asserted
for( std::map< Node, Node >::iterator it = d_ce_lit.begin(); it != d_ce_lit.end(); ++it ){
bool value;
- if( !d_th->getValuation().hasSatValue( it->second, value ) ){
+ if( !d_quantEngine->getValuation().hasSatValue( it->second, value ) ){
//if not already set, propagate as decision
- d_th->getOutputChannel().propagateAsDecision( it->second );
+ d_quantEngine->getOutputChannel().propagateAsDecision( it->second );
Debug("cbqi-prop-as-dec") << "CBQI: propagate as decision " << it->second << std::endl;
}
}
class InstantiationEngine : public QuantifiersModule
{
-private:
- TheoryQuantifiers* d_th;
- QuantifiersEngine* getQuantifiersEngine();
private:
typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;
/** status of instantiation round (one of InstStrategy::STATUS_*) */
int d_inst_round_status;
/** map from universal quantifiers to their counterexample literals */
std::map< Node, Node > d_ce_lit;
+ /** whether the instantiation engine should set incomplete if it cannot answer SAT */
+ bool d_setIncomplete;
private:
bool hasAddedCbqiLemma( Node f );
void addCbqiLemma( Node f );
/** debug sat */
void debugSat( int reason );
public:
- InstantiationEngine( TheoryQuantifiers* th );
+ InstantiationEngine( QuantifiersEngine* qe, bool setIncomplete = true );
~InstantiationEngine(){}
void check( Theory::Effort e );
**/
#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/rep_set_iterator.h"
#include "theory/theory_engine.h"
#include "theory/uf/equality_engine.h"
#include "theory/uf/theory_uf.h"
#include "theory/uf/theory_uf_strong_solver.h"
#include "theory/uf/theory_uf_instantiator.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "theory/quantifiers/term_database.h"
-//#define ME_PRINT_PROCESS_TIMES
+//#define ME_PRINT_WARNINGS
//#define DISABLE_EVAL_SKIP_MULTIPLE
-#define RECONSIDER_FUNC_DEFAULT_VALUE
+
#define RECONSIDER_FUNC_CONSTANT
-#define USE_INDEX_ORDERING
-//#define ONE_INST_PER_QUANT_PER_ROUND
+#define EVAL_FAIL_SKIP_MULTIPLE
+//#define ONE_QUANT_PER_ROUND_INST_GEN
+//#define ONE_QUANT_PER_ROUND
using namespace std;
using namespace CVC4;
using namespace CVC4::theory;
using namespace CVC4::theory::quantifiers;
-void printRepresentative( const char* c, QuantifiersEngine* qe, Node r ){
- if( r.getType()==NodeManager::currentNM()->booleanType() ){
- if( qe->getEqualityQuery()->areEqual( r, NodeManager::currentNM()->mkConst( true ) ) ){
- Debug( c ) << "true";
- }else{
- Debug( c ) << "false";
- }
- }else{
- Debug( c ) << qe->getEqualityQuery()->getRepresentative( r );
- }
-}
-
-RepAlphabet::RepAlphabet( RepAlphabet& ra, QuantifiersEngine* qe ){
- //translate to current representatives
- for( std::map< TypeNode, std::vector< Node > >::iterator it = ra.d_type_reps.begin(); it != ra.d_type_reps.end(); ++it ){
- std::vector< Node > reps;
- for( int i=0; i<(int)it->second.size(); i++ ){
- //reps.push_back( ie->getEqualityQuery()->getRepresentative( it->second[i] ) );
- reps.push_back( it->second[i] );
- }
- set( it->first, reps );
- }
-}
-
-void RepAlphabet::set( TypeNode t, std::vector< Node >& reps ){
- d_type_reps[t].insert( d_type_reps[t].begin(), reps.begin(), reps.end() );
- for( int i=0; i<(int)reps.size(); i++ ){
- d_tmap[ reps[i] ] = i;
- }
-}
-
-void RepAlphabet::debugPrint( const char* c, QuantifiersEngine* qe ){
- for( std::map< TypeNode, std::vector< Node > >::iterator it = d_type_reps.begin(); it != d_type_reps.end(); ++it ){
- Debug( c ) << it->first << " : " << std::endl;
- for( int i=0; i<(int)it->second.size(); i++ ){
- Debug( c ) << " " << i << ": " << it->second[i] << std::endl;
- Debug( c ) << " eq_class( " << it->second[i] << " ) : ";
- ((uf::InstantiatorTheoryUf*)qe->getInstantiator( THEORY_UF ))->outputEqClass( c, it->second[i] );
- Debug( c ) << std::endl;
- }
- }
-}
-
-RepAlphabetIterator::RepAlphabetIterator( QuantifiersEngine* qe, Node f, ModelEngine* model ){
- for( size_t i=0; i<f[0].getNumChildren(); i++ ){
- d_index_order.push_back( i );
- }
- initialize( qe, f, model );
-}
-
-RepAlphabetIterator::RepAlphabetIterator( QuantifiersEngine* qe, Node f, ModelEngine* model, std::vector< int >& indexOrder ){
- d_index_order.insert( d_index_order.begin(), indexOrder.begin(), indexOrder.end() );
- initialize( qe, f, model );
-}
-
-void RepAlphabetIterator::initialize( QuantifiersEngine* qe, Node f, ModelEngine* model ){
- d_f = f;
- d_model = model;
- //store instantiation constants
- for( size_t i=0; i<f[0].getNumChildren(); i++ ){
- d_ic.push_back( qe->getInstantiationConstant( d_f, i ) );
- d_index.push_back( 0 );
- }
- //make the d_var_order mapping
- for( size_t i=0; i<d_index_order.size(); i++ ){
- d_var_order[d_index_order[i]] = i;
- }
- //for testing
- d_inst_tried = 0;
- d_inst_tests = 0;
-}
-
-void RepAlphabetIterator::increment2( QuantifiersEngine* qe, int counter ){
- Assert( !isFinished() );
- //increment d_index
- while( counter>=0 && d_index[counter]==(int)(d_model->getReps()->d_type_reps[d_f[0][d_index_order[counter]].getType()].size()-1) ){
- counter--;
- }
- if( counter==-1 ){
- d_index.clear();
- }else{
- for( int i=(int)d_index.size()-1; i>counter; i-- ){
- d_index[i] = 0;
- d_model->clearEvalFailed( i );
- }
- d_index[counter]++;
- d_model->clearEvalFailed( counter );
- }
-}
-
-void RepAlphabetIterator::increment( QuantifiersEngine* qe ){
- if( !isFinished() ){
- increment2( qe, (int)d_index.size()-1 );
- }
-}
+ModelEngineBuilder::ModelEngineBuilder( QuantifiersEngine* qe ) :
+TheoryEngineModelBuilder( qe->getTheoryEngine() ),
+d_qe( qe ){
-bool RepAlphabetIterator::isFinished(){
- return d_index.empty();
}
-void RepAlphabetIterator::getMatch( QuantifiersEngine* ie, InstMatch& m ){
- for( int i=0; i<(int)d_index.size(); i++ ){
- m.d_map[ ie->getInstantiationConstant( d_f, i ) ] = getTerm( i );
- }
+Node ModelEngineBuilder::chooseRepresentative( TheoryModel* tm, Node eqc ){
+ return eqc;
}
-Node RepAlphabetIterator::getTerm( int i ){
- TypeNode tn = d_f[0][d_index_order[i]].getType();
- Assert( d_model->getReps()->d_type_reps.find( tn )!=d_model->getReps()->d_type_reps.end() );
- return d_model->getReps()->d_type_reps[tn][d_index[d_index_order[i]]];
-}
-
-void RepAlphabetIterator::calculateTerms( QuantifiersEngine* qe ){
- d_terms.clear();
- for( int i=0; i<qe->getNumInstantiationConstants( d_f ); i++ ){
- d_terms.push_back( getTerm( i ) );
- }
-}
-
-void RepAlphabetIterator::debugPrint( const char* c ){
- for( int i=0; i<(int)d_index.size(); i++ ){
- Debug( c ) << i << ": " << d_index[i] << ", (" << getTerm( i ) << " / " << d_ic[ i ] << std::endl;
- }
-}
-
-void RepAlphabetIterator::debugPrintSmall( const char* c ){
- Debug( c ) << "RI: ";
- for( int i=0; i<(int)d_index.size(); i++ ){
- Debug( c ) << d_index[i] << ": " << getTerm( i ) << " ";
- }
- Debug( c ) << std::endl;
-}
-
-//set value function
-void UfModelTree::setValue( QuantifiersEngine* qe, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex ){
- if( d_data.empty() ){
- d_value = v;
- }else if( !d_value.isNull() && d_value!=v ){
- d_value = Node::null();
- }
- if( argIndex<(int)n.getNumChildren() ){
- //take r = null when argument is the model basis
- Node r;
- if( ground || !n[ indexOrder[argIndex] ].getAttribute(ModelBasisAttribute()) ){
- r = qe->getEqualityQuery()->getRepresentative( n[ indexOrder[argIndex] ] );
- }
- d_data[ r ].setValue( qe, n, v, indexOrder, ground, argIndex+1 );
- }
-}
-
-//get value function
-Node UfModelTree::getValue( QuantifiersEngine* qe, Node n, std::vector< int >& indexOrder, int& depIndex, int argIndex ){
- if( !d_value.isNull() && isTotal( n.getOperator(), argIndex ) ){
- //Notice() << "Constant, return " << d_value << ", depIndex = " << argIndex << std::endl;
- depIndex = argIndex;
- return d_value;
- }else{
- Node val;
- int childDepIndex[2] = { argIndex, argIndex };
- for( int i=0; i<2; i++ ){
- //first check the argument, then check default
- Node r;
- if( i==0 ){
- r = qe->getEqualityQuery()->getRepresentative( n[ indexOrder[argIndex] ] );
+void ModelEngineBuilder::processBuildModel( TheoryModel* m ) {
+ d_addedLemmas = 0;
+ //only construct first order model if optUseModel() is true
+ if( optUseModel() ){
+ FirstOrderModel* fm = (FirstOrderModel*)m;
+ //initialize model
+ fm->initialize();
+ //analyze the quantifiers
+ Debug("fmf-model-debug") << "Analyzing quantifiers..." << std::endl;
+ analyzeQuantifiers( fm );
+ //if applicable, find exceptions
+ if( optInstGen() ){
+ //now, see if we know that any exceptions via InstGen exist
+ Debug("fmf-model-debug") << "Perform InstGen techniques for quantifiers..." << std::endl;
+ for( int i=0; i<fm->getNumAssertedQuantifiers(); i++ ){
+ Node f = fm->getAssertedQuantifier( i );
+ if( d_quant_sat.find( f )==d_quant_sat.end() ){
+ d_addedLemmas += doInstGen( fm, f );
+ if( optOneQuantPerRoundInstGen() && d_addedLemmas>0 ){
+ break;
+ }
+ }
}
- std::map< Node, UfModelTree >::iterator it = d_data.find( r );
- if( it!=d_data.end() ){
- val = it->second.getValue( qe, n, indexOrder, childDepIndex[i], argIndex+1 );
- if( !val.isNull() ){
- break;
+ if( Options::current()->printModelEngine ){
+ if( d_addedLemmas>0 ){
+ Message() << "InstGen, added lemmas = " << d_addedLemmas << std::endl;
+ }else{
+ Message() << "No InstGen lemmas..." << std::endl;
}
- }else{
- //argument is not a defined argument: thus, it depends on this argument
- childDepIndex[i] = argIndex+1;
}
+ Debug("fmf-model-debug") << "---> Added lemmas = " << d_addedLemmas << std::endl;
+ }
+ if( d_addedLemmas==0 ){
+ //if no immediate exceptions, build the model
+ // this model will be an approximation that will need to be tested via exhaustive instantiation
+ Debug("fmf-model-debug") << "Building model..." << std::endl;
+ finishBuildModel( fm );
}
- //update depIndex
- depIndex = childDepIndex[0]>childDepIndex[1] ? childDepIndex[0] : childDepIndex[1];
- //Notice() << "Return " << val << ", depIndex = " << depIndex;
- //Notice() << " ( " << childDepIndex[0] << ", " << childDepIndex[1] << " )" << std::endl;
- return val;
}
}
-//simplify function
-void UfModelTree::simplify( Node op, Node defaultVal, int argIndex ){
- if( argIndex<(int)op.getType().getNumChildren()-1 ){
- std::vector< Node > eraseData;
- //first process the default argument
- Node r;
- std::map< Node, UfModelTree >::iterator it = d_data.find( r );
- if( it!=d_data.end() ){
- if( !defaultVal.isNull() && it->second.d_value==defaultVal ){
- eraseData.push_back( r );
- }else{
- it->second.simplify( op, defaultVal, argIndex+1 );
- if( !it->second.d_value.isNull() && it->second.isTotal( op, argIndex+1 ) ){
- defaultVal = it->second.d_value;
+void ModelEngineBuilder::analyzeQuantifiers( FirstOrderModel* fm ){
+ d_quant_selection_lits.clear();
+ d_quant_sat.clear();
+ d_uf_prefs.clear();
+ int quantSatInit = 0;
+ int nquantSatInit = 0;
+ //analyze the preferences of each quantifier
+ for( int i=0; i<(int)fm->getNumAssertedQuantifiers(); i++ ){
+ Node f = fm->getAssertedQuantifier( i );
+ Debug("fmf-model-prefs") << "Analyze quantifier " << f << std::endl;
+ std::vector< Node > pro_con[2];
+ std::vector< Node > constantSatOps;
+ bool constantSatReconsider;
+ //for each asserted quantifier f,
+ // - determine which literals form model basis for each quantifier
+ // - check which function/predicates have good and bad definitions according to f
+ for( std::map< Node, bool >::iterator it = d_qe->d_phase_reqs[f].begin();
+ it != d_qe->d_phase_reqs[f].end(); ++it ){
+ Node n = it->first;
+ Node gn = d_qe->getTermDatabase()->getModelBasis( n );
+ Debug("fmf-model-req") << " Req: " << n << " -> " << it->second << std::endl;
+ //calculate preference
+ int pref = 0;
+ bool value;
+ if( d_qe->getValuation().hasSatValue( gn, value ) ){
+ if( value!=it->second ){
+ //store this literal as a model basis literal
+ // this literal will force a default values in model that (modulo exceptions) shows
+ // that f is satisfied by the model
+ d_quant_selection_lits[f].push_back( value ? n : n.notNode() );
+ pref = 1;
}else{
- defaultVal = Node::null();
+ pref = -1;
}
}
- }
- //now see if any children can be removed, and simplify the ones that cannot
- for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
- if( !it->first.isNull() ){
- if( !defaultVal.isNull() && it->second.d_value==defaultVal ){
- eraseData.push_back( it->first );
+ if( pref!=0 ){
+ //Store preferences for UF
+ bool isConst = !n.hasAttribute(InstConstantAttribute());
+ std::vector< Node > uf_terms;
+ if( gn.getKind()==APPLY_UF ){
+ uf_terms.push_back( gn );
+ isConst = fm->d_uf_model[gn.getOperator()].isConstant();
+ }else if( gn.getKind()==EQUAL ){
+ isConst = true;
+ for( int j=0; j<2; j++ ){
+ if( n[j].hasAttribute(InstConstantAttribute()) ){
+ if( n[j].getKind()==APPLY_UF ){
+ Node op = gn[j].getOperator();
+ if( fm->d_uf_model.find( op )!=fm->d_uf_model.end() ){
+ uf_terms.push_back( gn[j] );
+ isConst = isConst && fm->d_uf_model[op].isConstant();
+ }else{
+ isConst = false;
+ }
+ }else{
+ isConst = false;
+ }
+ }
+ }
+ }
+ Debug("fmf-model-prefs") << " It is " << ( pref==1 ? "pro" : "con" );
+ Debug("fmf-model-prefs") << " the definition of " << n << std::endl;
+ if( pref==1 && isConst ){
+ d_quant_sat[f] = true;
+ //instead, just note to the model for each uf term that f is pro its definition
+ constantSatReconsider = false;
+ constantSatOps.clear();
+ for( int j=0; j<(int)uf_terms.size(); j++ ){
+ Node op = uf_terms[j].getOperator();
+ constantSatOps.push_back( op );
+ if( d_uf_prefs[op].d_reconsiderModel ){
+ constantSatReconsider = true;
+ }
+ }
+ if( !constantSatReconsider ){
+ break;
+ }
}else{
- it->second.simplify( op, defaultVal, argIndex+1 );
+ int pcIndex = pref==1 ? 0 : 1;
+ for( int j=0; j<(int)uf_terms.size(); j++ ){
+ pro_con[pcIndex].push_back( uf_terms[j] );
+ }
}
}
}
- for( int i=0; i<(int)eraseData.size(); i++ ){
- d_data.erase( eraseData[i] );
- }
- }
-}
-
-//is total function
-bool UfModelTree::isTotal( Node op, int argIndex ){
- if( argIndex==(int)(op.getType().getNumChildren()-1) ){
- return !d_value.isNull();
- }else{
- Node r;
- std::map< Node, UfModelTree >::iterator it = d_data.find( r );
- if( it!=d_data.end() ){
- return it->second.isTotal( op, argIndex+1 );
+ if( d_quant_sat.find( f )!=d_quant_sat.end() ){
+ Debug("fmf-model-prefs") << " * Constant SAT due to definition of ops: ";
+ for( int i=0; i<(int)constantSatOps.size(); i++ ){
+ Debug("fmf-model-prefs") << constantSatOps[i] << " ";
+ d_uf_prefs[constantSatOps[i]].d_reconsiderModel = false;
+ }
+ Debug("fmf-model-prefs") << std::endl;
+ quantSatInit++;
+ d_statistics.d_pre_sat_quant += quantSatInit;
}else{
- return false;
- }
- }
-}
-
-Node UfModelTree::getConstantValue( QuantifiersEngine* qe, Node n, std::vector< int >& indexOrder, int argIndex ){
- return d_value;
-}
-
-void indent( const char* c, int ind ){
- for( int i=0; i<ind; i++ ){
- Debug( c ) << " ";
- }
-}
-
-void UfModelTree::debugPrint( const char* c, QuantifiersEngine* qe, std::vector< int >& indexOrder, int ind, int arg ){
- if( !d_data.empty() ){
- for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){
- if( !it->first.isNull() ){
- indent( c, ind );
- Debug( c ) << "if x_" << indexOrder[arg] << " == " << it->first << std::endl;
- it->second.debugPrint( c, qe, indexOrder, ind+2, arg+1 );
+ nquantSatInit++;
+ d_statistics.d_pre_nsat_quant += quantSatInit;
+ //note quantifier's value preferences to models
+ for( int k=0; k<2; k++ ){
+ for( int j=0; j<(int)pro_con[k].size(); j++ ){
+ Node op = pro_con[k][j].getOperator();
+ Node r = fm->getRepresentative( pro_con[k][j] );
+ d_uf_prefs[op].setValuePreference( f, pro_con[k][j], r, k==0 );
+ }
}
}
- if( d_data.find( Node::null() )!=d_data.end() ){
- d_data[ Node::null() ].debugPrint( c, qe, indexOrder, ind, arg+1 );
- }
- }else{
- indent( c, ind );
- Debug( c ) << "return ";
- printRepresentative( c, qe, d_value );
- //Debug( c ) << " { ";
- //for( int i=0; i<(int)d_explicit.size(); i++ ){
- // Debug( c ) << d_explicit[i] << " ";
- //}
- //Debug( c ) << "}";
- Debug( c ) << std::endl;
}
+ Debug("fmf-model-prefs") << "Pre-Model Completion: Quantifiers SAT: " << quantSatInit << " / " << (quantSatInit+nquantSatInit) << std::endl;
}
-UfModel::UfModel( Node op, ModelEngine* me ) : d_op( op ), d_me( me ),
- d_model_constructed( false ), d_reconsider_model( false ){
-
- d_tree = UfModelTreeOrdered( op ); TypeNode tn = d_op.getType(); tn = tn[(int)tn.getNumChildren()-1]; Assert( tn==NodeManager::currentNM()->booleanType() || uf::StrongSolverTheoryUf::isRelevantType( tn ) ); //look at ground assertions
- for( int i=0; i<(int)d_me->getQuantifiersEngine()->getTermDatabase()->d_op_map[ d_op ].size(); i++ ){
- Node n = d_me->getQuantifiersEngine()->getTermDatabase()->d_op_map[ d_op ][i];
- bool add = true;
- if( n.getAttribute(NoMatchAttribute()) ){
- add = false;
- //determine if it has model basis attribute
- for( int j=0; j<(int)n.getNumChildren(); j++ ){
- if( n[j].getAttribute(ModelBasisAttribute()) ){
- add = true;
- break;
+int ModelEngineBuilder::doInstGen( FirstOrderModel* fm, Node f ){
+ //we wish to add all known exceptions to our model basis literal(s)
+ // this will help to refine our current model.
+ //This step is advantageous over exhaustive instantiation, since we are adding instantiations that involve model basis terms,
+ // effectively acting as partial instantiations instead of pointwise instantiations.
+ int addedLemmas = 0;
+ for( int i=0; i<(int)d_quant_selection_lits[f].size(); i++ ){
+ bool phase = d_quant_selection_lits[f][i].getKind()!=NOT;
+ Node lit = d_quant_selection_lits[f][i].getKind()==NOT ? d_quant_selection_lits[f][i][0] : d_quant_selection_lits[f][i];
+ Assert( lit.hasAttribute(InstConstantAttribute()) );
+ std::vector< Node > tr_terms;
+ if( lit.getKind()==APPLY_UF ){
+ //only match predicates that are contrary to this one, use literal matching
+ Node eq = NodeManager::currentNM()->mkNode( IFF, lit, !phase ? fm->d_true : fm->d_false );
+ fm->getTermDatabase()->setInstantiationConstantAttr( eq, f );
+ tr_terms.push_back( eq );
+ }else if( lit.getKind()==EQUAL ){
+ //collect trigger terms
+ for( int j=0; j<2; j++ ){
+ if( lit[j].hasAttribute(InstConstantAttribute()) ){
+ if( lit[j].getKind()==APPLY_UF ){
+ tr_terms.push_back( lit[j] );
+ }else{
+ tr_terms.clear();
+ break;
+ }
}
}
- }
- if( add ){
- d_ground_asserts.push_back( n );
- Node r = d_me->getQuantifiersEngine()->getEqualityQuery()->getRepresentative( n );
- d_ground_asserts_reps.push_back( r );
- }
- }
- //determine if it is constant
- if( !d_ground_asserts.empty() ){
- bool isConstant = true;
- for( int i=1; i<(int)d_ground_asserts.size(); i++ ){
- if( d_ground_asserts_reps[0]!=d_ground_asserts_reps[i] ){
- isConstant = false;
- break;
+ if( tr_terms.size()==1 && !phase ){
+ //equality between a function and a ground term, use literal matching
+ tr_terms.clear();
+ tr_terms.push_back( lit );
}
}
- if( isConstant ){
- //set constant value
- Node t = d_me->getModelBasisApplyUfTerm( d_op );
- Node r = d_ground_asserts_reps[0];
- setValue( t, r, false );
- setModel();
- d_reconsider_model = true;
- Debug("fmf-model-cons") << "Function " << d_op << " is the constant function ";
- printRepresentative( "fmf-model-cons", d_me->getQuantifiersEngine(), r );
- Debug("fmf-model-cons") << std::endl;
+ //if applicable, try to add exceptions here
+ if( !tr_terms.empty() ){
+ //make a trigger for these terms, add instantiations
+ Trigger* tr = Trigger::mkTrigger( d_qe, f, tr_terms );
+ //Notice() << "Trigger = " << (*tr) << std::endl;
+ tr->resetInstantiationRound();
+ tr->reset( Node::null() );
+ //d_qe->d_optInstMakeRepresentative = false;
+ //d_qe->d_optMatchIgnoreModelBasis = true;
+ addedLemmas += tr->addInstantiations( d_quant_basis_match[f] );
}
}
+ return addedLemmas;
}
-void UfModel::setValue( Node n, Node v, bool ground ){
- d_set_values[ ground ? 1 : 0 ][n] = v;
-}
-
-void UfModel::setModel(){
- makeModel( d_me->getQuantifiersEngine(), d_tree );
- d_model_constructed = true;
-}
-
-void UfModel::clearModel(){
- for( int k=0; k<2; k++ ){
- d_set_values[k].clear();
+void ModelEngineBuilder::finishBuildModel( FirstOrderModel* fm ){
+ //build model for UF
+ for( std::map< Node, uf::UfModel >::iterator it = fm->d_uf_model.begin(); it != fm->d_uf_model.end(); ++it ){
+ finishBuildModelUf( fm, it->second );
}
- d_tree.clear();
- d_model_constructed = false;
-}
-
-Node UfModel::getConstantValue( QuantifiersEngine* qe, Node n ){
- if( d_model_constructed ){
- return d_tree.getConstantValue( qe, n );
- }else{
- return Node::null();
+ //build model for arrays
+ for( std::map< Node, Node >::iterator it = fm->d_array_model.begin(); it != fm->d_array_model.end(); ++it ){
+ //consult the model basis select term
+ // i.e. the default value for array A is the value of select( A, e ), where e is the model basis term
+ TypeNode tn = it->first.getType();
+ Node selModelBasis = NodeManager::currentNM()->mkNode( SELECT, it->first, fm->getTermDatabase()->getModelBasisTerm( tn[0] ) );
+ it->second = fm->getRepresentative( selModelBasis );
}
+ Debug("fmf-model-debug") << "Done building models." << std::endl;
}
-bool UfModel::isConstant(){
- Node gn = d_me->getModelBasisApplyUfTerm( d_op );
- Node n = getConstantValue( d_me->getQuantifiersEngine(), gn );
- return !n.isNull();
-}
-
-void UfModel::buildModel(){
+void ModelEngineBuilder::finishBuildModelUf( FirstOrderModel* fm, uf::UfModel& model ){
+ Node op = model.getOperator();
#ifdef RECONSIDER_FUNC_CONSTANT
- if( d_model_constructed ){
- if( d_reconsider_model ){
+ if( model.isModelConstructed() && model.isConstant() ){
+ if( d_uf_prefs[op].d_reconsiderModel ){
//if we are allowed to reconsider default value, then see if the default value can be improved
- Node t = d_me->getModelBasisApplyUfTerm( d_op );
- Node v = d_set_values[0][t];
- if( d_value_pro_con[1][v].size()>d_value_pro_con[0][v].size() ){
- Debug("fmf-model-cons-debug") << "Consider changing the default value for " << d_op << std::endl;
- clearModel();
+ Node t = d_qe->getTermDatabase()->getModelBasisOpTerm( op );
+ Node v = model.getConstantValue( t );
+ if( d_uf_prefs[op].d_value_pro_con[0][v].empty() ){
+ Debug("fmf-model-cons-debug") << "Consider changing the default value for " << op << std::endl;
+ model.clearModel();
}
}
}
#endif
- //now, construct models for each uninterpretted function/predicate
- if( !d_model_constructed ){
- Debug("fmf-model-cons") << "Construct model for " << d_op << "..." << std::endl;
- //now, set the values in the model
- for( int i=0; i<(int)d_ground_asserts.size(); i++ ){
- Node n = d_ground_asserts[i];
- Node v = d_ground_asserts_reps[i];
+ if( !model.isModelConstructed() ){
+ //construct the model for the uninterpretted function/predicate
+ bool setDefaultVal = true;
+ Node defaultTerm = d_qe->getTermDatabase()->getModelBasisOpTerm( op );
+ Debug("fmf-model-cons") << "Construct model for " << op << "..." << std::endl;
+ //set the values in the model
+ for( size_t i=0; i<model.d_ground_asserts.size(); i++ ){
+ Node n = model.d_ground_asserts[i];
+ Node v = model.d_ground_asserts_reps[i];
//if this assertion did not help the model, just consider it ground
//set n = v in the model tree
Debug("fmf-model-cons") << " Set " << n << " = ";
- printRepresentative( "fmf-model-cons", d_me->getQuantifiersEngine(), v );
+ fm->printRepresentativeDebug( "fmf-model-cons", v );
Debug("fmf-model-cons") << std::endl;
//set it as ground value
- setValue( n, v );
- }
- //set the default value
- //chose defaultVal based on heuristic (the best proportion of "pro" responses)
- Node defaultVal;
- double maxScore = -1;
- for( int i=0; i<(int)d_values.size(); i++ ){
- Node v = d_values[i];
- double score = ( 1.0 + (double)d_value_pro_con[0][v].size() )/( 1.0 + (double)d_value_pro_con[1][v].size() );
- Debug("fmf-model-cons") << " - score( ";
- printRepresentative( "fmf-model-cons", d_me->getQuantifiersEngine(), v );
- Debug("fmf-model-cons") << " ) = " << score << std::endl;
- if( score>maxScore ){
- defaultVal = v;
- maxScore = score;
- }
- }
-#ifdef RECONSIDER_FUNC_DEFAULT_VALUE
- if( maxScore<1.0 ){
- //consider finding another value, if possible
- Debug("fmf-model-cons-debug") << "Poor choice for default value, score = " << maxScore << std::endl;
- TypeNode tn = d_op.getType();
- Node newDefaultVal = d_me->getArbitraryElement( tn[(int)tn.getNumChildren()-1], d_values );
- if( !newDefaultVal.isNull() ){
- defaultVal = newDefaultVal;
- Debug("fmf-model-cons-debug") << "-> Change default value to ";
- printRepresentative( "fmf-model-cons-debug", d_me->getQuantifiersEngine(), defaultVal );
- Debug("fmf-model-cons-debug") << std::endl;
+ model.setValue( n, v );
+ if( model.optUsePartialDefaults() ){
+ //also set as default value if necessary
+ //if( n.getAttribute(ModelBasisArgAttribute())==1 && !d_term_pro_con[0][n].empty() ){
+ if( n.hasAttribute(ModelBasisArgAttribute()) && n.getAttribute(ModelBasisArgAttribute())==1 ){
+ model.setValue( n, v, false );
+ if( n==defaultTerm ){
+ //incidentally already set, we will not need to find a default value
+ setDefaultVal = false;
+ }
+ }
}else{
- Debug("fmf-model-cons-debug") << "-> Could not find arbitrary element of type " << tn[(int)tn.getNumChildren()-1] << std::endl;
- Debug("fmf-model-cons-debug") << " Excluding: ";
- for( int i=0; i<(int)d_values.size(); i++ ){
- Debug("fmf-model-cons-debug") << d_values[i] << " ";
+ if( n==defaultTerm ){
+ model.setValue( n, v, false );
+ //incidentally already set, we will not need to find a default value
+ setDefaultVal = false;
}
- Debug("fmf-model-cons-debug") << std::endl;
}
}
-#endif
- Assert( !defaultVal.isNull() );
- //get the default term (this term must be defined non-ground in model)
- Node defaultTerm = d_me->getModelBasisApplyUfTerm( d_op );
- Debug("fmf-model-cons") << " Choose ";
- printRepresentative("fmf-model-cons", d_me->getQuantifiersEngine(), defaultVal );
- Debug("fmf-model-cons") << " as default value (" << defaultTerm << ")" << std::endl;
- Debug("fmf-model-cons") << " # quantifiers pro = " << d_value_pro_con[0][defaultVal].size() << std::endl;
- Debug("fmf-model-cons") << " # quantifiers con = " << d_value_pro_con[1][defaultVal].size() << std::endl;
- setValue( defaultTerm, defaultVal, false );
+ //set the overall default value if not set already (is this necessary??)
+ if( setDefaultVal ){
+ Debug("fmf-model-cons") << " Choose default value..." << std::endl;
+ //chose defaultVal based on heuristic, currently the best ratio of "pro" responses
+ Node defaultVal = d_uf_prefs[op].getBestDefaultValue( defaultTerm, fm );
+ Assert( !defaultVal.isNull() );
+ model.setValue( defaultTerm, defaultVal, false );
+ }
Debug("fmf-model-cons") << " Making model...";
- setModel();
- Debug("fmf-model-cons") << " Finished constructing model for " << d_op << "." << std::endl;
+ model.setModel();
+ Debug("fmf-model-cons") << " Finished constructing model for " << op << "." << std::endl;
}
}
-void UfModel::setValuePreference( Node f, Node n, bool isPro ){
- Node v = d_me->getQuantifiersEngine()->getEqualityQuery()->getRepresentative( n );
- //Notice() << "Set value preference " << n << " = " << v << " " << isPro << std::endl;
- if( std::find( d_values.begin(), d_values.end(), v )==d_values.end() ){
- d_values.push_back( v );
- }
- int index = isPro ? 0 : 1;
- if( std::find( d_value_pro_con[index][v].begin(), d_value_pro_con[index][v].end(), f )==d_value_pro_con[index][v].end() ){
- d_value_pro_con[index][v].push_back( f );
- }
+bool ModelEngineBuilder::optUseModel() {
+ return Options::current()->fmfModelBasedInst;
}
-void UfModel::makeModel( QuantifiersEngine* qe, UfModelTreeOrdered& tree ){
- for( int k=0; k<2; k++ ){
- for( std::map< Node, Node >::iterator it = d_set_values[k].begin(); it != d_set_values[k].end(); ++it ){
- tree.setValue( qe, it->first, it->second, k==1 );
- }
- }
- tree.simplify();
+bool ModelEngineBuilder::optInstGen(){
+ return Options::current()->fmfInstGen;
+}
+
+bool ModelEngineBuilder::optOneQuantPerRoundInstGen(){
+#ifdef ONE_QUANT_PER_ROUND_INST_GEN
+ return true;
+#else
+ return false;
+#endif
}
-void UfModel::debugPrint( const char* c ){
- //Debug( c ) << "Function " << d_op << std::endl;
- //Debug( c ) << " Type: " << d_op.getType() << std::endl;
- //Debug( c ) << " Ground asserts:" << std::endl;
- //for( int i=0; i<(int)d_ground_asserts.size(); i++ ){
- // Debug( c ) << " " << d_ground_asserts[i] << " = ";
- // printRepresentative( c, d_me->getQuantifiersEngine(), d_ground_asserts[i] );
- // Debug( c ) << std::endl;
- //}
- //Debug( c ) << " Model:" << std::endl;
+ModelEngineBuilder::Statistics::Statistics():
+ d_pre_sat_quant("ModelEngineBuilder::Status_quant_pre_sat", 0),
+ d_pre_nsat_quant("ModelEngineBuilder::Status_quant_pre_non_sat", 0)
+{
+ StatisticsRegistry::registerStat(&d_pre_sat_quant);
+ StatisticsRegistry::registerStat(&d_pre_nsat_quant);
+}
- TypeNode t = d_op.getType();
- Debug( c ) << d_op << "( ";
- for( int i=0; i<(int)(t.getNumChildren()-1); i++ ){
- Debug( c ) << "x_" << i << " : " << t[i];
- if( i<(int)(t.getNumChildren()-2) ){
- Debug( c ) << ", ";
- }
- }
- Debug( c ) << " ) : " << t[(int)t.getNumChildren()-1] << std::endl;
- if( d_tree.isEmpty() ){
- Debug( c ) << " [undefined]" << std::endl;
- }else{
- d_tree.debugPrint( c, d_me->getQuantifiersEngine(), 3 );
- Debug( c ) << std::endl;
- }
- //Debug( c ) << " Phase reqs:" << std::endl; //for( int i=0; i<2; i++ ){
- // for( std::map< Node, std::vector< Node > >::iterator it = d_reqs[i].begin(); it != d_reqs[i].end(); ++it ){
- // Debug( c ) << " " << it->first << std::endl;
- // for( int j=0; j<(int)it->second.size(); j++ ){
- // Debug( c ) << " " << it->second[j] << " -> " << (i==1) << std::endl;
- // }
- // }
- //}
- //Debug( c ) << std::endl;
- //for( int i=0; i<2; i++ ){
- // for( std::map< Node, std::map< Node, std::vector< Node > > >::iterator it = d_eq_reqs[i].begin(); it != d_eq_reqs[i].end(); ++it ){
- // Debug( c ) << " " << "For " << it->first << ":" << std::endl;
- // for( std::map< Node, std::vector< Node > >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
- // for( int j=0; j<(int)it2->second.size(); j++ ){
- // Debug( c ) << " " << it2->first << ( i==1 ? "==" : "!=" ) << it2->second[j] << std::endl;
- // }
- // }
- // }
- //}
+ModelEngineBuilder::Statistics::~Statistics(){
+ StatisticsRegistry::unregisterStat(&d_pre_sat_quant);
+ StatisticsRegistry::unregisterStat(&d_pre_nsat_quant);
}
//Model Engine constructor
-ModelEngine::ModelEngine( TheoryQuantifiers* th ){
- d_th = th;
- d_quantEngine = th->getQuantifiersEngine();
- d_ss = ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->getTheory( THEORY_UF ))->getStrongSolver();
+ModelEngine::ModelEngine( QuantifiersEngine* qe ) :
+QuantifiersModule( qe ),
+d_builder( qe ),
+d_rel_domain( qe->getModel() ){
+
}
void ModelEngine::check( Theory::Effort e ){
- if( e==Theory::EFFORT_LAST_CALL ){
- bool quantsInit = true;
+ if( e==Theory::EFFORT_LAST_CALL && !d_quantEngine->hasAddedLemma() ){
//first, check if we can minimize the model further
- if( !d_ss->minimize() ){
+ if( !((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->getTheory( THEORY_UF ))->getStrongSolver()->minimize() ){
return;
}
- if( useModel() ){
- //now, check if any quantifiers are un-initialized
- for( int i=0; i<d_quantEngine->getNumAssertedQuantifiers(); i++ ){
- Node f = d_quantEngine->getAssertedQuantifier( i );
- if( !initializeQuantifier( f ) ){
- quantsInit = false;
- }
+ //the following will attempt to build a model and test that it satisfies all asserted universal quantifiers
+ int addedLemmas = 0;
+ if( d_builder.optUseModel() ){
+ //check if any quantifiers are un-initialized
+ for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
+ addedLemmas += initializeQuantifier( f );
}
}
- if( quantsInit ){
-#ifdef ME_PRINT_PROCESS_TIMES
- Notice() << "---Instantiation Round---" << std::endl;
-#endif
+ if( addedLemmas==0 ){
+ //quantifiers are initialized, we begin an instantiation round
+ double clSet = 0;
+ if( Options::current()->printModelEngine ){
+ clSet = double(clock())/double(CLOCKS_PER_SEC);
+ Message() << "---Model Engine Round---" << std::endl;
+ }
Debug("fmf-model-debug") << "---Begin Instantiation Round---" << std::endl;
++(d_statistics.d_inst_rounds);
- d_quantEngine->getTermDatabase()->reset( e );
- //build the representatives
- Debug("fmf-model-debug") << "Building representatives..." << std::endl;
- buildRepresentatives();
- if( useModel() ){
- //initialize the model
- Debug("fmf-model-debug") << "Initializing model..." << std::endl;
- initializeModel();
- //analyze the quantifiers
- Debug("fmf-model-debug") << "Analyzing quantifiers..." << std::endl;
- analyzeQuantifiers();
- //build the model
- Debug("fmf-model-debug") << "Building model..." << std::endl;
- for( std::map< Node, UfModel >::iterator it = d_uf_model.begin(); it != d_uf_model.end(); ++it ){
- it->second.buildModel();
+ //reset the quantifiers engine
+ d_quantEngine->resetInstantiationRound( e );
+ //initialize the model
+ Debug("fmf-model-debug") << "Build model..." << std::endl;
+ d_builder.buildModel( d_quantEngine->getModel() );
+ d_quantEngine->d_model_set = true;
+ //if builder has lemmas, add and return
+ if( d_builder.d_addedLemmas>0 ){
+ addedLemmas += (int)d_builder.d_addedLemmas;
+ }else{
+ //print debug
+ Debug("fmf-model-complete") << std::endl;
+ debugPrint("fmf-model-complete");
+ //verify we are SAT by trying exhaustive instantiation
+ if( optUseRelevantDomain() ){
+ d_rel_domain.compute();
}
- }
- //print debug
- debugPrint("fmf-model-complete");
- //try exhaustive instantiation
- Debug("fmf-model-debug") << "Do exhaustive instantiation..." << std::endl;
- int addedLemmas = 0;
- for( int i=0; i<d_quantEngine->getNumAssertedQuantifiers(); i++ ){
- Node f = d_quantEngine->getAssertedQuantifier( i );
- if( d_quant_sat.find( f )==d_quant_sat.end() ){
- addedLemmas += instantiateQuantifier( f );
+ d_triedLemmas = 0;
+ d_testLemmas = 0;
+ d_relevantLemmas = 0;
+ d_totalLemmas = 0;
+ Debug("fmf-model-debug") << "Do exhaustive instantiation..." << std::endl;
+ for( int i=0; i<d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
+ if( d_builder.d_quant_sat.find( f )==d_builder.d_quant_sat.end() ){
+ addedLemmas += exhaustiveInstantiate( f, optUseRelevantDomain() );
+ if( optOneQuantPerRound() && addedLemmas>0 ){
+ break;
+ }
+ }
+#ifdef ME_PRINT_WARNINGS
+ if( addedLemmas>10000 ){
+ break;
+ }
+#endif
+ }
+ Debug("fmf-model-debug") << "---> Added lemmas = " << addedLemmas << " / " << d_triedLemmas << " / ";
+ Debug("fmf-model-debug") << d_testLemmas << " / " << d_relevantLemmas << " / " << d_totalLemmas << std::endl;
+ if( Options::current()->printModelEngine ){
+ Message() << "Added Lemmas = " << addedLemmas << " / " << d_triedLemmas << " / ";
+ Message() << d_testLemmas << " / " << d_relevantLemmas << " / " << d_totalLemmas << std::endl;
+ double clSet2 = double(clock())/double(CLOCKS_PER_SEC);
+ Message() << "Finished model engine, time = " << (clSet2-clSet) << std::endl;
+ }
+#ifdef ME_PRINT_WARNINGS
+ if( addedLemmas>10000 ){
+ Debug("fmf-exit") << std::endl;
+ debugPrint("fmf-exit");
+ exit( 0 );
}
- }
-#ifdef ME_PRINT_PROCESS_TIMES
- Notice() << "Added Lemmas = " << addedLemmas << std::endl;
#endif
- if( addedLemmas==0 ){
- //debugPrint("fmf-consistent");
- //for( std::map< Node, UfModel >::iterator it = d_uf_model.begin(); it != d_uf_model.end(); ++it ){
- // it->second.simplify();
- //}
- Debug("fmf-consistent") << std::endl;
- debugPrint("fmf-consistent");
}
}
- d_quantEngine->flushLemmas( &d_th->getOutputChannel() );
+ if( addedLemmas==0 ){
+ //CVC4 will answer SAT
+ Debug("fmf-consistent") << std::endl;
+ debugPrint("fmf-consistent");
+ }else{
+ //otherwise, the search will continue
+ d_quantEngine->flushLemmas( &d_quantEngine->getOutputChannel() );
+ }
}
}
}
-bool ModelEngine::useModel() {
- return Options::current()->fmfModelBasedInst;
+bool ModelEngine::optOneInstPerQuantRound(){
+ return Options::current()->fmfOneInstPerRound;
+}
+
+bool ModelEngine::optUseRelevantDomain(){
+ return Options::current()->fmfRelevantDomain;
+}
+
+bool ModelEngine::optOneQuantPerRound(){
+#ifdef ONE_QUANT_PER_ROUND
+ return true;
+#else
+ return false;
+#endif
}
-bool ModelEngine::initializeQuantifier( Node f ){
+int ModelEngine::initializeQuantifier( Node f ){
if( d_quant_init.find( f )==d_quant_init.end() ){
d_quant_init[f] = true;
Debug("inst-fmf-init") << "Initialize " << f << std::endl;
//add the model basis instantiation
// This will help produce the necessary information for model completion.
- // We do this by extending distinguish ground assertions (those
+ // We do this by extending distinguish ground assertions (those
// containing terms with "model basis" attribute) to hold for all cases.
-
+
////first, check if any variables are required to be equal
//for( std::map< Node, bool >::iterator it = d_quantEngine->d_phase_reqs[f].begin();
// it != d_quantEngine->d_phase_reqs[f].end(); ++it ){
// Notice() << "Unhandled phase req: " << n << std::endl;
// }
//}
-
+ std::vector< Node > ics;
std::vector< Node > terms;
for( int j=0; j<(int)f[0].getNumChildren(); j++ ){
- terms.push_back( getModelBasisTerm( f[0][j].getType() ) );
+ Node ic = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
+ Node t = d_quantEngine->getTermDatabase()->getModelBasisTerm( ic.getType() );
+ ics.push_back( ic );
+ terms.push_back( t );
+ //calculate the basis match for f
+ d_builder.d_quant_basis_match[f].d_map[ ic ] = t;
}
++(d_statistics.d_num_quants_init);
+ //register model basis body
+ Node n = d_quantEngine->getTermDatabase()->getCounterexampleBody( f );
+ Node gn = n.substitute( ics.begin(), ics.end(), terms.begin(), terms.end() );
+ d_quantEngine->getTermDatabase()->registerModelBasis( n, gn );
+ //add model basis instantiation
if( d_quantEngine->addInstantiation( f, terms ) ){
- return false;
+ return 1;
}else{
- //usually shouldn't happen
+ //shouldn't happen usually, but will occur if x != y is a required literal for f.
//Notice() << "No model basis for " << f << std::endl;
++(d_statistics.d_num_quants_init_fail);
}
}
- return true;
-}
-
-void ModelEngine::buildRepresentatives(){
- d_ra.clear();
- //collect all representatives for all types and store as representative alphabet
- for( int i=0; i<d_ss->getNumCardinalityTypes(); i++ ){
- TypeNode tn = d_ss->getCardinalityType( i );
- std::vector< Node > reps;
- d_ss->getRepresentatives( tn, reps );
- Assert( !reps.empty() );
- //if( (int)reps.size()!=d_ss->getCardinality( tn ) ){
- // Notice() << "InstStrategyFinteModelFind::processResetInstantiationRound: Bad representatives for type." << std::endl;
- // Notice() << " " << tn << " has cardinality " << d_ss->getCardinality( tn );
- // Notice() << " but only " << (int)reps.size() << " were given." << std::endl;
- // Unimplemented( 27 );
- //}
- Debug("fmf-model-debug") << " " << tn << " -> " << reps.size() << std::endl;
- Debug("fmf-model-debug") << " ";
- for( int i=0; i<(int)reps.size(); i++ ){
- Debug("fmf-model-debug") << reps[i] << " ";
- }
- Debug("fmf-model-debug") << std::endl;
- //set them in the alphabet
- d_ra.set( tn, reps );
-#ifdef ME_PRINT_PROCESS_TIMES
- Notice() << tn << " has " << reps.size() << " representatives. " << std::endl;
-#endif
- }
+ return 0;
}
-void ModelEngine::initializeModel(){
- d_uf_model.clear();
- d_quant_sat.clear();
- for( int k=0; k<2; k++ ){
- d_pro_con_quant[k].clear();
- }
-
- ////now analyze quantifiers (temporary)
- //for( int i=0; i<(int)d_quantEngine->getNumAssertedQuantifiers(); i++ ){
- // Node f = d_quantEngine->getAssertedQuantifier( i );
- // Debug("fmf-model-req") << "Phase requirements for " << f << ": " << std::endl;
- // for( std::map< Node, bool >::iterator it = d_quantEngine->d_phase_reqs[f].begin();
- // it != d_quantEngine->d_phase_reqs[f].end(); ++it ){
- // Node n = it->first;
- // Debug("fmf-model-req") << " " << n << " -> " << it->second << std::endl;
- // if( n.getKind()==APPLY_UF ){
- // processPredicate( f, n, it->second );
- // }else if( n.getKind()==EQUAL ){
- // processEquality( f, n, it->second );
- // }
- // }
- //}
- for( int i=0; i<(int)d_quantEngine->getNumAssertedQuantifiers(); i++ ){
- Node f = d_quantEngine->getAssertedQuantifier( i );
- initializeUf( f[1] );
- //register model basis terms
- std::vector< Node > vars;
- std::vector< Node > subs;
- for( int j=0; j<(int)f[0].getNumChildren(); j++ ){
- vars.push_back( d_quantEngine->getInstantiationConstant( f, j ) );
- subs.push_back( getModelBasisTerm( f[0][j].getType() ) );
- }
- Node n = d_quantEngine->getCounterexampleBody( f );
- Node gn = n.substitute( vars.begin(), vars.end(), subs.begin(), subs.end() );
- registerModelBasis( n, gn );
- }
-}
-
-void ModelEngine::analyzeQuantifiers(){
- int quantSatInit = 0;
- int nquantSatInit = 0;
- //analyze the preferences of each quantifier
- for( int i=0; i<(int)d_quantEngine->getNumAssertedQuantifiers(); i++ ){
- Node f = d_quantEngine->getAssertedQuantifier( i );
- Debug("fmf-model-prefs") << "Analyze quantifier " << f << std::endl;
- std::vector< Node > pro_con[2];
- std::vector< Node > pro_con_patterns[2];
- //check which model basis terms have good and bad definitions according to f
- for( std::map< Node, bool >::iterator it = d_quantEngine->d_phase_reqs[f].begin();
- it != d_quantEngine->d_phase_reqs[f].end(); ++it ){
- Node n = it->first;
- Node gn = d_model_basis[n];
- Debug("fmf-model-req") << " Req: " << n << " -> " << it->second << std::endl;
- int pref = 0;
- bool isConst = true;
- std::vector< Node > uf_terms;
- std::vector< Node > uf_term_patterns;
- if( gn.getKind()==APPLY_UF ){
- if( d_quantEngine->getEqualityQuery()->hasTerm( gn ) ){
- uf_terms.push_back( gn );
- uf_term_patterns.push_back( n );
- bool phase = areEqual( gn, NodeManager::currentNM()->mkConst( true ) );
- pref = phase!=it->second ? 1 : -1;
- }
- }else if( gn.getKind()==EQUAL ){
- bool success = true;
- for( int j=0; j<2; j++ ){
- if( n[j].getKind()==APPLY_UF ){
- Node op = gn[j].getOperator();
- if( d_uf_model.find( op )!=d_uf_model.end() ){
- Assert( gn[j].getKind()==APPLY_UF );
- uf_terms.push_back( gn[j] );
- uf_term_patterns.push_back( n[j] );
- }else{
- //found undefined uf operator
- success = false;
- }
- }else if( n[j].hasAttribute(InstConstantAttribute()) ){
- isConst = false;
- }
- }
- if( success && !uf_terms.empty() ){
- if( (!it->second && areEqual( gn[0], gn[1] )) || (it->second && areDisequal( gn[0], gn[1] )) ){
- pref = 1;
- }else if( (it->second && areEqual( gn[0], gn[1] )) || (!it->second && areDisequal( gn[0], gn[1] )) ){
- pref = -1;
- }
- }
- }
- if( pref!=0 ){
- Debug("fmf-model-prefs") << " It is " << ( pref==1 ? "pro" : "con" );
- Debug("fmf-model-prefs") << " the definition of " << n << std::endl;
- if( pref==1 ){
- if( isConst ){
- for( int j=0; j<(int)uf_terms.size(); j++ ){
- //the only uf that is initialized are those that are constant
- Node op = uf_terms[j].getOperator();
- Assert( d_uf_model.find( op )!=d_uf_model.end() );
- if( !d_uf_model[op].isConstant() ){
- isConst = false;
- break;
- }
- }
- if( isConst ){
- d_quant_sat[f] = true;
- //we only need to consider current term definition(s) for this quantifier to be satisified, ignore the others
- for( int k=0; k<2; k++ ){
- pro_con[k].clear();
- pro_con_patterns[k].clear();
- }
- //instead, just note to the model for each uf term that f is pro its definition
- for( int j=0; j<(int)uf_terms.size(); j++ ){
- Node op = uf_terms[j].getOperator();
- d_uf_model[op].d_reconsider_model = false;
- }
- }
- }
- }
- if( d_quant_sat.find( f )!=d_quant_sat.end() ){
- Debug("fmf-model-prefs") << " * Constant SAT due to definition of " << n << std::endl;
- break;
- }else{
- int pcIndex = pref==1 ? 0 : 1;
- for( int j=0; j<(int)uf_terms.size(); j++ ){
- pro_con[pcIndex].push_back( uf_terms[j] );
- pro_con_patterns[pcIndex].push_back( uf_term_patterns[j] );
- }
- }
- }
- }
- if( d_quant_sat.find( f )!=d_quant_sat.end() ){
- quantSatInit++;
- d_statistics.d_pre_sat_quant += quantSatInit;
- }else{
- nquantSatInit++;
- d_statistics.d_pre_nsat_quant += quantSatInit;
- }
- //add quantifier's preferences to vector
- for( int k=0; k<2; k++ ){
- for( int j=0; j<(int)pro_con[k].size(); j++ ){
- Node op = pro_con[k][j].getOperator();
- d_uf_model[op].setValuePreference( f, pro_con[k][j], k==0 );
- d_pro_con_quant[k][ f ].push_back( pro_con_patterns[k][j] );
- }
- }
- }
- Debug("fmf-model-prefs") << "Pre-Model Completion: Quantifiers SAT: " << quantSatInit << " / " << (quantSatInit+nquantSatInit) << std::endl;
-}
-
-int ModelEngine::instantiateQuantifier( Node f ){
+int ModelEngine::exhaustiveInstantiate( Node f, bool useRelInstDomain ){
+ int tests = 0;
int addedLemmas = 0;
+ int triedLemmas = 0;
Debug("inst-fmf-ei") << "Add matches for " << f << "..." << std::endl;
Debug("inst-fmf-ei") << " Instantiation Constants: ";
for( size_t i=0; i<f[0].getNumChildren(); i++ ){
- Debug("inst-fmf-ei") << d_quantEngine->getInstantiationConstant( f, i ) << " ";
+ Debug("inst-fmf-ei") << d_quantEngine->getTermDatabase()->getInstantiationConstant( f, i ) << " ";
}
Debug("inst-fmf-ei") << std::endl;
- for( int k=0; k<2; k++ ){
- Debug("inst-fmf-ei") << " " << ( k==0 ? "Pro" : "Con" ) << " definitions:" << std::endl;
- for( int i=0; i<(int)d_pro_con_quant[k][f].size(); i++ ){
- Debug("inst-fmf-ei") << " " << d_pro_con_quant[k][f][i] << std::endl;
- }
- }
- if( d_pro_con_quant[0][f].empty() ){
- Debug("inst-fmf-ei") << "WARNING: " << f << " has no pros for default literal definitions" << std::endl;
- }
- d_eval_failed_lits.clear();
- d_eval_failed.clear();
- d_eval_term_model.clear();
- //d_eval_term_vals.clear();
- //d_eval_term_fv_deps.clear();
- RepAlphabetIterator riter( d_quantEngine, f, this );
- increment( &riter );
-#ifdef ONE_INST_PER_QUANT_PER_ROUND
- while( !riter.isFinished() && addedLemmas==0 ){
-#else
- while( !riter.isFinished() ){
+ if( d_builder.d_quant_selection_lits[f].empty() ){
+ Debug("inst-fmf-ei") << "WARNING: " << f << " has no model literal definitions (is f clausified?)" << std::endl;
+#ifdef ME_PRINT_WARNINGS
+ Message() << "WARNING: " << f << " has no model literal definitions (is f clausified?)" << std::endl;
#endif
- InstMatch m;
- riter.getMatch( d_quantEngine, m );
- Debug("fmf-model-eval") << "* Add instantiation " << std::endl;
- riter.d_inst_tried++;
- if( d_quantEngine->addInstantiation( f, m ) ){
- addedLemmas++;
- }
- riter.increment( d_quantEngine );
- increment( &riter );
- }
- if( Debug.isOn("inst-fmf-ei") ){
- int totalInst = 1;
- for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
- totalInst = totalInst * (int)getReps()->d_type_reps[ f[0][i].getType() ].size();
- }
- Debug("inst-fmf-ei") << "Finished: " << std::endl;
- Debug("inst-fmf-ei") << " Inst Skipped: " << (totalInst-riter.d_inst_tried) << std::endl;
- Debug("inst-fmf-ei") << " Inst Tried: " << riter.d_inst_tried << std::endl;
- Debug("inst-fmf-ei") << " Inst Added: " << addedLemmas << std::endl;
- Debug("inst-fmf-ei") << " # Tests: " << riter.d_inst_tests << std::endl;
- }
- return addedLemmas;
-}
-
-void ModelEngine::registerModelBasis( Node n, Node gn ){
- if( d_model_basis.find( n )==d_model_basis.end() ){
- d_model_basis[n] = gn;
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- registerModelBasis( n[i], gn[i] );
- }
- }
-}
-
-Node ModelEngine::getArbitraryElement( TypeNode tn, std::vector< Node >& exclude ){
- Node retVal;
- if( tn==NodeManager::currentNM()->booleanType() ){
- if( exclude.empty() ){
- retVal = NodeManager::currentNM()->mkConst( false );
- }else if( exclude.size()==1 ){
- retVal = NodeManager::currentNM()->mkConst( areEqual( exclude[0], NodeManager::currentNM()->mkConst( false ) ) );
- }
- }else if( d_ra.d_type_reps.find( tn )!=d_ra.d_type_reps.end() ){
- for( int i=0; i<(int)d_ra.d_type_reps[tn].size(); i++ ){
- if( std::find( exclude.begin(), exclude.end(), d_ra.d_type_reps[tn][i] )==exclude.end() ){
- retVal = d_ra.d_type_reps[tn][i];
- break;
- }
- }
- }
- if( !retVal.isNull() ){
- return d_quantEngine->getEqualityQuery()->getRepresentative( retVal );
}else{
- return Node::null();
- }
-}
-
-Node ModelEngine::getModelBasisTerm( TypeNode tn, int i ){
- return d_ss->getCardinalityTerm( tn );
-}
-
-Node ModelEngine::getModelBasisApplyUfTerm( Node op ){
- if( d_model_basis_term.find( op )==d_model_basis_term.end() ){
- TypeNode t = op.getType();
- std::vector< Node > children;
- children.push_back( op );
- for( int i=0; i<(int)t.getNumChildren()-1; i++ ){
- children.push_back( getModelBasisTerm( t[i] ) );
- }
- d_model_basis_term[op] = NodeManager::currentNM()->mkNode( APPLY_UF, children );
- }
- return d_model_basis_term[op];
-}
-
-bool ModelEngine::isModelBasisTerm( Node op, Node n ){
- if( n.getOperator()==op ){
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( !n[i].getAttribute(ModelBasisAttribute()) ){
- return false;
- }
- }
- return true;
- }else{
- return false;
- }
-}
-
-void ModelEngine::initializeUf( Node n ){
- std::vector< Node > terms;
- collectUfTerms( n, terms );
- for( int i=0; i<(int)terms.size(); i++ ){
- initializeUfModel( terms[i].getOperator() );
- }
-}
-
-void ModelEngine::collectUfTerms( Node n, std::vector< Node >& terms ){
- if( n.getKind()==APPLY_UF ){
- terms.push_back( n );
- }
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- collectUfTerms( n[i], terms );
- }
-}
-
-void ModelEngine::initializeUfModel( Node op ){
- if( d_uf_model.find( op )==d_uf_model.end() ){
- TypeNode tn = op.getType();
- tn = tn[ (int)tn.getNumChildren()-1 ];
- if( tn==NodeManager::currentNM()->booleanType() || uf::StrongSolverTheoryUf::isRelevantType( tn ) ){
- d_uf_model[ op ] = UfModel( op, this );
- }
- }
-}
-
-void ModelEngine::makeEvalTermModel( Node n ){
- if( d_eval_term_model.find( n )==d_eval_term_model.end() ){
- makeEvalTermIndexOrder( n );
- if( !d_eval_term_use_default_model[n] ){
- Node op = n.getOperator();
- d_eval_term_model[n] = UfModelTreeOrdered( op, d_eval_term_index_order[n] );
- d_uf_model[op].makeModel( d_quantEngine, d_eval_term_model[n] );
- Debug("fmf-model-index-order") << "Make model for " << n << " : " << std::endl;
- d_eval_term_model[n].debugPrint( "fmf-model-index-order", d_quantEngine, 2 );
- }
- }
-}
-
-struct sortGetMaxVariableNum {
- std::map< Node, int > d_max_var_num;
- int computeMaxVariableNum( Node n ){
- if( n.getKind()==INST_CONSTANT ){
- return n.getAttribute(InstVarNumAttribute());
- }else if( n.hasAttribute(InstConstantAttribute()) ){
- int maxVal = -1;
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- int val = getMaxVariableNum( n[i] );
- if( val>maxVal ){
- maxVal = val;
- }
- }
- return maxVal;
- }else{
- return -1;
- }
- }
- int getMaxVariableNum( Node n ){
- std::map< Node, int >::iterator it = d_max_var_num.find( n );
- if( it==d_max_var_num.end() ){
- int num = computeMaxVariableNum( n );
- d_max_var_num[n] = num;
- return num;
- }else{
- return it->second;
- }
- }
- bool operator() (Node i,Node j) { return (getMaxVariableNum(i)<getMaxVariableNum(j));}
-};
-
-void ModelEngine::makeEvalTermIndexOrder( Node n ){
- if( d_eval_term_index_order.find( n )==d_eval_term_index_order.end() ){
- //sort arguments in order of least significant vs. most significant variable in default ordering
- std::map< Node, std::vector< int > > argIndex;
- std::vector< Node > args;
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- if( argIndex.find( n[i] )==argIndex.end() ){
- args.push_back( n[i] );
- }
- argIndex[n[i]].push_back( i );
- }
- sortGetMaxVariableNum sgmvn;
- std::sort( args.begin(), args.end(), sgmvn );
- for( int i=0; i<(int)args.size(); i++ ){
- for( int j=0; j<(int)argIndex[ args[i] ].size(); j++ ){
- d_eval_term_index_order[n].push_back( argIndex[ args[i] ][j] );
- }
- }
- bool useDefault = true;
- for( int i=0; i<(int)d_eval_term_index_order[n].size(); i++ ){
- if( i!=d_eval_term_index_order[n][i] ){
- useDefault = false;
- break;
- }
- }
- d_eval_term_use_default_model[n] = useDefault;
- Debug("fmf-model-index-order") << "Will consider the following index ordering for " << n << " : ";
- for( int i=0; i<(int)d_eval_term_index_order[n].size(); i++ ){
- Debug("fmf-model-index-order") << d_eval_term_index_order[n][i] << " ";
- }
- Debug("fmf-model-index-order") << std::endl;
- }
-}
-
-//void ModelEngine::processPredicate( Node f, Node p, bool phase ){
-// Node op = p.getOperator();
-// initializeUfModel( op );
-// d_uf_model[ op ].addRequirement( f, p, phase );
-//}
-//
-//void ModelEngine::processEquality( Node f, Node eq, bool phase ){
-// for( int i=0; i<2; i++ ){
-// int j = i==0 ? 1 : 0;
-// if( eq[i].getKind()==APPLY_UF && eq[i].hasAttribute(InstConstantAttribute()) ){
-// Node op = eq[i].getOperator();
-// initializeUfModel( op );
-// d_uf_model[ op ].addEqRequirement( f, eq[i], eq[j], phase );
-// }
-// }
-//}
-
-void ModelEngine::increment( RepAlphabetIterator* rai ){
- if( useModel() ){
- bool success;
- do{
- success = true;
- if( !rai->isFinished() ){
- //see if instantiation is already true in current model
- Debug("fmf-model-eval") << "Evaulating ";
- rai->debugPrintSmall("fmf-model-eval");
- //calculate represenative terms we are currently considering
- rai->calculateTerms( d_quantEngine );
- rai->d_inst_tests++;
- //if eVal is not (int)rai->d_index.size(), then the instantiation is already true in the model,
- // and eVal is the highest index in rai which we can safely iterate
- int depIndex;
- if( evaluate( rai, d_quantEngine->getCounterexampleBody( rai->d_f ), depIndex )==1 ){
- Debug("fmf-model-eval") << " Returned success with depIndex = " << depIndex << std::endl;
- //Notice() << "Returned eVal = " << eVal << "/" << rai->d_index.size() << std::endl;
- if( depIndex<(int)rai->d_index.size() ){
-#ifdef DISABLE_EVAL_SKIP_MULTIPLE
- depIndex = (int)rai->d_index.size()-1;
-#endif
- rai->increment2( d_quantEngine, depIndex );
- success = false;
+ Debug("inst-fmf-ei") << " Model literal definitions:" << std::endl;
+ for( size_t i=0; i<d_builder.d_quant_selection_lits[f].size(); i++ ){
+ Debug("inst-fmf-ei") << " " << d_builder.d_quant_selection_lits[f][i] << std::endl;
+ }
+ }
+ RepSetIterator riter( f, d_quantEngine->getModel() );
+ //set the domain for the iterator (the sufficient set of instantiations to try)
+ if( useRelInstDomain ){
+ riter.setDomain( d_rel_domain.d_quant_inst_domain[f] );
+ }
+ RepSetEvaluator reval( d_quantEngine->getModel(), &riter );
+ while( !riter.isFinished() && ( addedLemmas==0 || !optOneInstPerQuantRound() ) ){
+ d_testLemmas++;
+ if( d_builder.optUseModel() ){
+ //see if instantiation is already true in current model
+ Debug("fmf-model-eval") << "Evaluating ";
+ riter.debugPrintSmall("fmf-model-eval");
+ Debug("fmf-model-eval") << "Done calculating terms." << std::endl;
+ tests++;
+ //if evaluate(...)==1, then the instantiation is already true in the model
+ // depIndex is the index of the least significant variable that this evaluation relies upon
+ int depIndex = riter.getNumTerms()-1;
+ int eval = reval.evaluate( d_quantEngine->getTermDatabase()->getCounterexampleBody( f ), depIndex );
+ if( eval==1 ){
+ Debug("fmf-model-eval") << " Returned success with depIndex = " << depIndex << std::endl;
+ riter.increment2( depIndex );
+ }else{
+ Debug("fmf-model-eval") << " Returned " << (eval==-1 ? "failure" : "unknown") << ", depIndex = " << depIndex << std::endl;
+ InstMatch m;
+ riter.getMatch( d_quantEngine, m );
+ Debug("fmf-model-eval") << "* Add instantiation " << m << std::endl;
+ triedLemmas++;
+ d_triedLemmas++;
+ if( d_quantEngine->addInstantiation( f, m ) ){
+ addedLemmas++;
+#ifdef EVAL_FAIL_SKIP_MULTIPLE
+ if( eval==-1 ){
+ riter.increment2( depIndex );
+ }else{
+ riter.increment();
}
+#else
+ riter.increment();
+#endif
}else{
- Debug("fmf-model-eval") << " Returned failure." << std::endl;
- }
- }
- }while( !success );
- }
-}
-
-//if evaluate( rai, n, phaseReq ) = eVal,
-// if eVal = rai->d_index.size()
-// then the formula n instantiated with rai cannot be proven to be equal to phaseReq
-// otherwise,
-// each n{rai->d_index[0]/x_0...rai->d_index[eVal]/x_eVal, */x_(eVal+1) ... */x_n } is equal to phaseReq in the current model
-int ModelEngine::evaluate( RepAlphabetIterator* rai, Node n, int& depIndex ){
- ++(d_statistics.d_eval_formulas);
- //Debug("fmf-model-eval-debug") << "Evaluate " << n << " " << phaseReq << std::endl;
- if( n.getKind()==NOT ){
- int val = evaluate( rai, n[0], depIndex );
- return val==1 ? -1 : ( val==-1 ? 1 : 0 );
- }else if( n.getKind()==OR || n.getKind()==AND || n.getKind()==IMPLIES ){
- int baseVal = n.getKind()==AND ? 1 : -1;
- int eVal = baseVal;
- int posDepIndex = (int)rai->d_index.size();
- int negDepIndex = -1;
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- //evaluate subterm
- int childDepIndex;
- Node nn = ( i==0 && n.getKind()==IMPLIES ) ? n[i].notNode() : n[i];
- int eValT = evaluate( rai, nn, childDepIndex );
- if( eValT==baseVal ){
- if( eVal==baseVal ){
- if( childDepIndex>negDepIndex ){
- negDepIndex = childDepIndex;
- }
- }
- }else if( eValT==-baseVal ){
- eVal = -baseVal;
- if( childDepIndex<posDepIndex ){
- posDepIndex = childDepIndex;
- if( posDepIndex==-1 ){
- break;
- }
- }
- }else if( eValT==0 ){
- if( eVal==baseVal ){
- eVal = 0;
+ Debug("ajr-temp") << "* Failed Add instantiation " << m << std::endl;
+ riter.increment();
}
}
- }
- if( eVal!=0 ){
- depIndex = eVal==-baseVal ? posDepIndex : negDepIndex;
- return eVal;
- }else{
- return 0;
- }
- }else if( n.getKind()==IFF || n.getKind()==XOR ){
- int depIndex1;
- int eVal = evaluate( rai, n[0], depIndex1 );
- if( eVal!=0 ){
- int depIndex2;
- int eVal2 = evaluate( rai, n.getKind()==XOR ? n[1].notNode() : n[1], depIndex2 );
- if( eVal2!=0 ){
- depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
- return eVal==eVal2 ? 1 : -1;
- }
- }
- return 0;
- }else if( n.getKind()==ITE ){
- int depIndex1;
- int eVal = evaluate( rai, n[0], depIndex1 );
- if( eVal==0 ){
- //DO_THIS: evaluate children to see if they are the same value?
- return 0;
}else{
- int depIndex2;
- int eValT = evaluate( rai, n[eVal==1 ? 1 : 2], depIndex2 );
- depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;
- return eValT;
- }
- }else if( n.getKind()==FORALL ){
- return 0;
- }else{
- ////if we know we will fail again, immediately return
- //if( d_eval_failed.find( n )!=d_eval_failed.end() ){
- // if( d_eval_failed[n] ){
- // return -1;
- // }
- //}
- //Debug("fmf-model-eval-debug") << "Evaluate literal " << n << std::endl;
- //this should be a literal
- Node gn = n.substitute( rai->d_ic.begin(), rai->d_ic.end(), rai->d_terms.begin(), rai->d_terms.end() );
- //Debug("fmf-model-eval-debug") << " Ground version = " << gn << std::endl;
- int retVal = 0;
- std::vector< Node > fv_deps;
- if( n.getKind()==APPLY_UF ){
- //case for boolean predicates
- Node val = evaluateTerm( n, gn, fv_deps );
- if( d_quantEngine->getEqualityQuery()->hasTerm( val ) ){
- if( areEqual( val, NodeManager::currentNM()->mkConst( true ) ) ){
- retVal = 1;
- }else{
- retVal = -1;
- }
- }
- }else if( n.getKind()==EQUAL ){
- //case for equality
- retVal = evaluateEquality( n[0], n[1], gn[0], gn[1], fv_deps );
- }
- if( retVal!=0 ){
- int maxIndex = -1;
- for( int i=0; i<(int)fv_deps.size(); i++ ){
- int index = rai->d_var_order[ fv_deps[i].getAttribute(InstVarNumAttribute()) ];
- if( index>maxIndex ){
- maxIndex = index;
- if( index==(int)rai->d_index.size()-1 ){
- break;
- }
- }
+ InstMatch m;
+ riter.getMatch( d_quantEngine, m );
+ Debug("fmf-model-eval") << "* Add instantiation " << std::endl;
+ triedLemmas++;
+ d_triedLemmas++;
+ if( d_quantEngine->addInstantiation( f, m ) ){
+ addedLemmas++;
}
- Debug("fmf-model-eval-debug") << "Evaluate literal: return " << retVal << ", depends = " << maxIndex << std::endl;
- depIndex = maxIndex;
+ riter.increment();
}
- return retVal;
- }
-}
-
-int ModelEngine::evaluateEquality( Node n1, Node n2, Node gn1, Node gn2, std::vector< Node >& fv_deps ){
- ++(d_statistics.d_eval_eqs);
- Debug("fmf-model-eval-debug") << "Evaluate equality: " << std::endl;
- Debug("fmf-model-eval-debug") << " " << n1 << " = " << n2 << std::endl;
- Debug("fmf-model-eval-debug") << " " << gn1 << " = " << gn2 << std::endl;
- Node val1 = evaluateTerm( n1, gn1, fv_deps );
- Node val2 = evaluateTerm( n2, gn2, fv_deps );
- Debug("fmf-model-eval-debug") << " Values : ";
- printRepresentative( "fmf-model-eval-debug", d_quantEngine, val1 );
- Debug("fmf-model-eval-debug") << " = ";
- printRepresentative( "fmf-model-eval-debug", d_quantEngine, val2 );
- Debug("fmf-model-eval-debug") << std::endl;
- int retVal = 0;
- if( areEqual( val1, val2 ) ){
- retVal = 1;
- }else if( areDisequal( val1, val2 ) ){
- retVal = -1;
- }
- if( retVal!=0 ){
- Debug("fmf-model-eval-debug") << " ---> Success, value = " << (retVal==1) << std::endl;
- }else{
- Debug("fmf-model-eval-debug") << " ---> Failed" << std::endl;
- }
- Debug("fmf-model-eval-debug") << " Value depends on variables: ";
- for( int i=0; i<(int)fv_deps.size(); i++ ){
- Debug("fmf-model-eval-debug") << fv_deps[i] << " ";
}
- Debug("fmf-model-eval-debug") << std::endl;
- return retVal;
-}
-
-Node ModelEngine::evaluateTerm( Node n, Node gn, std::vector< Node >& fv_deps ){
- if( n.hasAttribute(InstConstantAttribute()) ){
- if( n.getKind()==INST_CONSTANT ){
- fv_deps.push_back( n );
- return gn;
- //}else if( d_eval_term_fv_deps.find( n )!=d_eval_term_fv_deps.end() &&
- // d_eval_term_fv_deps[n].find( gn )!=d_eval_term_fv_deps[n].end() ){
- // fv_deps.insert( fv_deps.end(), d_eval_term_fv_deps[n][gn].begin(), d_eval_term_fv_deps[n][gn].end() );
- // return d_eval_term_vals[gn];
- }else{
- //Debug("fmf-model-eval-debug") << "Evaluate term " << n << " (" << gn << ")" << std::endl;
- //first we must evaluate the arguments
- Node val = gn;
- if( n.getKind()==APPLY_UF ){
- Node op = gn.getOperator();
- //if it is a defined UF, then consult the interpretation
- Node gnn = gn;
- ++(d_statistics.d_eval_uf_terms);
- int depIndex = 0;
- //first we must evaluate the arguments
- bool childrenChanged = false;
- std::vector< Node > children;
- children.push_back( op );
- std::map< int, std::vector< Node > > children_var_deps;
- //for each argument, calculate its value, and the variables its value depends upon
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- Node nn = evaluateTerm( n[i], gn[i], children_var_deps[i] );
- children.push_back( nn );
- childrenChanged = childrenChanged || nn!=gn[i];
- }
- //remake gn if changed
- if( childrenChanged ){
- gnn = NodeManager::currentNM()->mkNode( APPLY_UF, children );
- }
- if( d_uf_model.find( op )!=d_uf_model.end() ){
-#ifdef USE_INDEX_ORDERING
- //make the term model specifically for n
- makeEvalTermModel( n );
- //now, consult the model
- if( d_eval_term_use_default_model[n] ){
- val = d_uf_model[op].d_tree.getValue( d_quantEngine, gnn, depIndex );
- }else{
- val = d_eval_term_model[ n ].getValue( d_quantEngine, gnn, depIndex );
- }
- //Debug("fmf-model-eval-debug") << "Evaluate term " << n << " (" << gn << ", " << gnn << ")" << std::endl;
- //d_eval_term_model[ n ].debugPrint("fmf-model-eval-debug", d_quantEngine );
- Assert( !val.isNull() );
-#else
- //now, consult the model
- val = d_uf_model[op].d_tree.getValue( d_quantEngine, gnn, depIndex );
-#endif
- }else{
- d_eval_term_use_default_model[n] = true;
- val = gnn;
- depIndex = (int)n.getNumChildren();
- }
- Debug("fmf-model-eval-debug") << "Evaluate term " << n << " = " << gn << " = " << gnn << " = ";
- printRepresentative( "fmf-model-eval-debug", d_quantEngine, val );
- Debug("fmf-model-eval-debug") << ", depIndex = " << depIndex << std::endl;
- if( !val.isNull() ){
-#ifdef USE_INDEX_ORDERING
- for( int i=0; i<depIndex; i++ ){
- int index = d_eval_term_use_default_model[n] ? i : d_eval_term_index_order[n][i];
- Debug("fmf-model-eval-debug") << "Add variables from " << index << "..." << std::endl;
- fv_deps.insert( fv_deps.end(), children_var_deps[index].begin(),
- children_var_deps[index].end() );
- }
-#else
- //calculate the free variables that the value depends on : take those in children_var_deps[0...depIndex-1]
- for( std::map< int, std::vector< Node > >::iterator it = children_var_deps.begin(); it != children_var_deps.end(); ++it ){
- if( it->first<depIndex ){
- fv_deps.insert( fv_deps.end(), it->second.begin(), it->second.end() );
- }
- }
-#endif
- }
- ////cache the result
- //d_eval_term_vals[gn] = val;
- //d_eval_term_fv_deps[n][gn].insert( d_eval_term_fv_deps[n][gn].end(), fv_deps.begin(), fv_deps.end() );
+ d_statistics.d_eval_formulas += reval.d_eval_formulas;
+ d_statistics.d_eval_eqs += reval.d_eval_eqs;
+ d_statistics.d_eval_uf_terms += reval.d_eval_uf_terms;
+ int totalInst = 1;
+ int relevantInst = 1;
+ for( size_t i=0; i<f[0].getNumChildren(); i++ ){
+ totalInst = totalInst * (int)d_quantEngine->getModel()->d_ra.d_type_reps[ f[0][i].getType() ].size();
+ relevantInst = relevantInst * (int)riter.d_domain[i].size();
+ }
+ d_totalLemmas += totalInst;
+ d_relevantLemmas += relevantInst;
+ Debug("inst-fmf-ei") << "Finished: " << std::endl;
+ Debug("inst-fmf-ei") << " Inst Total: " << totalInst << std::endl;
+ Debug("inst-fmf-ei") << " Inst Relevant: " << relevantInst << std::endl;
+ Debug("inst-fmf-ei") << " Inst Tried: " << triedLemmas << std::endl;
+ Debug("inst-fmf-ei") << " Inst Added: " << addedLemmas << std::endl;
+ Debug("inst-fmf-ei") << " # Tests: " << tests << std::endl;
+///-----------
+#ifdef ME_PRINT_WARNINGS
+ if( addedLemmas>1000 ){
+ Notice() << "WARNING: many instantiations produced for " << f << ": " << std::endl;
+ Notice() << " Inst Total: " << totalInst << std::endl;
+ Notice() << " Inst Relevant: " << totalRelevant << std::endl;
+ Notice() << " Inst Tried: " << triedLemmas << std::endl;
+ Notice() << " Inst Added: " << addedLemmas << std::endl;
+ Notice() << " # Tests: " << tests << std::endl;
+ Notice() << std::endl;
+ if( !d_builder.d_quant_selection_lits[f].empty() ){
+ Notice() << " Model literal definitions:" << std::endl;
+ for( size_t i=0; i<d_builder.d_quant_selection_lits[f].size(); i++ ){
+ Notice() << " " << d_builder.d_quant_selection_lits[f][i] << std::endl;
}
- return val;
+ Notice() << std::endl;
}
- }else{
- return n;
- }
-}
-
-void ModelEngine::clearEvalFailed( int index ){
- for( int i=0; i<(int)d_eval_failed_lits[index].size(); i++ ){
- d_eval_failed[ d_eval_failed_lits[index][i] ] = false;
}
- d_eval_failed_lits[index].clear();
-}
-
-bool ModelEngine::areEqual( Node a, Node b ){
- return d_quantEngine->getEqualityQuery()->areEqual( a, b );
-}
-
-bool ModelEngine::areDisequal( Node a, Node b ){
- return d_quantEngine->getEqualityQuery()->areDisequal( a, b );
+#endif
+///-----------
+ return addedLemmas;
}
void ModelEngine::debugPrint( const char* c ){
- Debug( c ) << "---Current Model---" << std::endl;
- Debug( c ) << "Representatives: " << std::endl;
- d_ra.debugPrint( c, d_quantEngine );
Debug( c ) << "Quantifiers: " << std::endl;
- for( int i=0; i<(int)d_quantEngine->getNumAssertedQuantifiers(); i++ ){
- Node f = d_quantEngine->getAssertedQuantifier( i );
+ for( int i=0; i<(int)d_quantEngine->getModel()->getNumAssertedQuantifiers(); i++ ){
+ Node f = d_quantEngine->getModel()->getAssertedQuantifier( i );
Debug( c ) << " ";
- if( d_quant_sat.find( f )!=d_quant_sat.end() ){
+ if( d_builder.d_quant_sat.find( f )!=d_builder.d_quant_sat.end() ){
Debug( c ) << "*SAT* ";
}else{
Debug( c ) << " ";
}
Debug( c ) << f << std::endl;
}
- Debug( c ) << "Functions: " << std::endl;
- for( std::map< Node, UfModel >::iterator it = d_uf_model.begin(); it != d_uf_model.end(); ++it ){
- it->second.debugPrint( c );
- Debug( c ) << std::endl;
- }
+ //d_quantEngine->getModel()->debugPrint( c );
}
ModelEngine::Statistics::Statistics():
d_inst_rounds("ModelEngine::Inst_Rounds", 0),
- d_pre_sat_quant("ModelEngine::Status_quant_pre_sat", 0),
- d_pre_nsat_quant("ModelEngine::Status_quant_pre_non_sat", 0),
d_eval_formulas("ModelEngine::Eval_Formulas", 0 ),
d_eval_eqs("ModelEngine::Eval_Equalities", 0 ),
d_eval_uf_terms("ModelEngine::Eval_Uf_Terms", 0 ),
d_num_quants_init_fail("ModelEngine::Num_Quants_No_Basis", 0 )
{
StatisticsRegistry::registerStat(&d_inst_rounds);
- StatisticsRegistry::registerStat(&d_pre_sat_quant);
- StatisticsRegistry::registerStat(&d_pre_nsat_quant);
StatisticsRegistry::registerStat(&d_eval_formulas);
StatisticsRegistry::registerStat(&d_eval_eqs);
StatisticsRegistry::registerStat(&d_eval_uf_terms);
ModelEngine::Statistics::~Statistics(){
StatisticsRegistry::unregisterStat(&d_inst_rounds);
- StatisticsRegistry::unregisterStat(&d_pre_sat_quant);
- StatisticsRegistry::unregisterStat(&d_pre_nsat_quant);
StatisticsRegistry::unregisterStat(&d_eval_formulas);
StatisticsRegistry::unregisterStat(&d_eval_eqs);
StatisticsRegistry::unregisterStat(&d_eval_uf_terms);
StatisticsRegistry::unregisterStat(&d_num_quants_init);
StatisticsRegistry::unregisterStat(&d_num_quants_init_fail);
}
+
+
** See the file COPYING in the top-level source directory for licensing
** information.\endverbatim
**
- ** \brief Instantiation Engine classes
+ ** \brief Model Engine classes
**/
#include "cvc4_private.h"
#include "theory/quantifiers_engine.h"
#include "theory/quantifiers/theory_quantifiers.h"
+#include "theory/model.h"
+#include "theory/uf/theory_uf_model.h"
+#include "theory/quantifiers/relevant_domain.h"
namespace CVC4 {
namespace theory {
namespace quantifiers {
-/** this class stores a representative alphabet */
-class RepAlphabet {
-public:
- RepAlphabet(){}
- RepAlphabet( RepAlphabet& ra, QuantifiersEngine* qe );
- ~RepAlphabet(){}
- std::map< TypeNode, std::vector< Node > > d_type_reps;
- std::map< Node, int > d_tmap;
- /** clear the alphabet */
- void clear(){
- d_type_reps.clear();
- d_tmap.clear();
- }
- /** set the representatives for type */
- void set( TypeNode t, std::vector< Node >& reps );
- /** returns index in d_type_reps for node n */
- int getIndexFor( Node n ) { return d_tmap.find( n )!=d_tmap.end() ? d_tmap[n] : -1; }
- /** debug print */
- void debugPrint( const char* c, QuantifiersEngine* qe );
-};
-
-class ModelEngine;
-
-/** this class iterates over a RepAlphabet */
-class RepAlphabetIterator {
-private:
- void initialize( QuantifiersEngine* qe, Node f, ModelEngine* model );
-public:
- RepAlphabetIterator( QuantifiersEngine* qe, Node f, ModelEngine* model );
- RepAlphabetIterator( QuantifiersEngine* qe, Node f, ModelEngine* model, std::vector< int >& indexOrder );
- ~RepAlphabetIterator(){}
- //pointer to quantifier
- Node d_f;
- //pointer to model
- ModelEngine* d_model;
- //index we are considering
- std::vector< int > d_index;
- //ordering for variables we are indexing over
- // for example, given reps = { a, b } and quantifier forall( x, y, z ) P( x, y, z ) with d_index_order = { 2, 0, 1 },
- // then we consider instantiations in this order:
- // a/x a/y a/z
- // a/x b/y a/z
- // b/x a/y a/z
- // b/x b/y a/z
- // ...
- std::vector< int > d_index_order;
- //variables to index they are considered at
- // for example, if d_index_order = { 2, 0, 1 }
- // then d_var_order = { 0 -> 1, 1 -> 2, 2 -> 0 }
- std::map< int, int > d_var_order;
- //the instantiation constants of d_f
- std::vector< Node > d_ic;
- //the current terms we are considering
- std::vector< Node > d_terms;
-public:
- /** increment the iterator */
- void increment2( QuantifiersEngine* qe, int counter );
- void increment( QuantifiersEngine* qe );
- /** is the iterator finished? */
- bool isFinished();
- /** produce the match that this iterator represents */
- void getMatch( QuantifiersEngine* qe, InstMatch& m );
- /** get the i_th term we are considering */
- Node getTerm( int i );
- /** get the number of terms we are considering */
- int getNumTerms() { return d_f[0].getNumChildren(); }
- /** refresh d_term to be current with d_index */
- void calculateTerms( QuantifiersEngine* qe );
- /** debug print */
- void debugPrint( const char* c );
- void debugPrintSmall( const char* c );
- //for debugging
- int d_inst_tried;
- int d_inst_tests;
-};
-
-
-class UfModelTree
-{
-public:
- UfModelTree(){}
- /** the data */
- std::map< Node, UfModelTree > d_data;
- /** the value of this tree node (if all paths lead to same value) */
- Node d_value;
-public:
- //is this model tree empty?
- bool isEmpty() { return d_data.empty(); }
- //clear
- void clear(){
- d_data.clear();
- d_value = Node::null();
- }
- /** setValue function
- *
- * For each argument of n with ModelBasisAttribute() set to true will be considered default arguments if ground=false
- *
- */
- void setValue( QuantifiersEngine* qe, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex );
- /** getValue function
- *
- * returns $val, the value of ground term n
- * Say n is f( t_0...t_n )
- * depIndex is the index for which every term of the form f( t_0 ... t_depIndex, *,... * ) is equal to $val
- * for example, if g( x_0, x_1, x_2 ) := lambda x_0 x_1 x_2. if( x_1==a ) b else c,
- * then g( a, a, a ) would return b with depIndex = 1
- * If ground = true, we are asking whether the term n is constant (assumes that all non-model basis arguments are ground)
- *
- */
- Node getValue( QuantifiersEngine* qe, Node n, std::vector< int >& indexOrder, int& depIndex, int argIndex );
- ///** getConstant Value function
- // *
- // * given term n, where n may contain model basis arguments
- // * if n is constant for its entire domain, then this function returns the value of its domain
- // * otherwise, it returns null
- // * for example, if f( x_0, x_1 ) := if( x_0 = a ) b else if( x_1 = a ) a else b,
- // * then f( a, e ) would return b, while f( e, a ) would return null
- // *
- // */
- Node getConstantValue( QuantifiersEngine* qe, Node n, std::vector< int >& indexOrder, int argIndex );
- /** simplify function */
- void simplify( Node op, Node defaultVal, int argIndex );
- // is total ?
- bool isTotal( Node op, int argIndex );
-public:
- void debugPrint( const char* c, QuantifiersEngine* qe, std::vector< int >& indexOrder, int ind = 0, int arg = 0 );
-};
-class UfModelTreeOrdered
+//the model builder
+class ModelEngineBuilder : public TheoryEngineModelBuilder
{
-private:
- Node d_op;
- std::vector< int > d_index_order;
- UfModelTree d_tree;
-public:
- UfModelTreeOrdered(){}
- UfModelTreeOrdered( Node op ) : d_op( op ){
- TypeNode tn = d_op.getType();
- for( int i=0; i<(int)(tn.getNumChildren()-1); i++ ){
- d_index_order.push_back( i );
- }
- }
- UfModelTreeOrdered( Node op, std::vector< int >& indexOrder ) : d_op( op ){
- d_index_order.insert( d_index_order.end(), indexOrder.begin(), indexOrder.end() );
- }
- bool isEmpty() { return d_tree.isEmpty(); }
- void clear() { d_tree.clear(); }
- void setValue( QuantifiersEngine* qe, Node n, Node v, bool ground = true ){
- d_tree.setValue( qe, n, v, d_index_order, ground, 0 );
- }
- Node getValue( QuantifiersEngine* qe, Node n, int& depIndex ){
- return d_tree.getValue( qe, n, d_index_order, depIndex, 0 );
- }
- Node getConstantValue( QuantifiersEngine* qe, Node n ) {
- return d_tree.getConstantValue( qe, n, d_index_order, 0 );
- }
- void simplify() { d_tree.simplify( d_op, Node::null(), 0 ); }
- bool isTotal() { return d_tree.isTotal( d_op, 0 ); }
-public:
- void debugPrint( const char* c, QuantifiersEngine* qe, int ind = 0 ){
- d_tree.debugPrint( c, qe, d_index_order, ind );
- }
-};
-
-class UfModel
-{
-//public:
- //std::map< Node, std::vector< Node > > d_reqs[2];
- //std::map< Node, std::map< Node, std::vector< Node > > > d_eq_reqs[2];
- ///** add requirement */
- //void addRequirement( Node f, Node p, bool phase ) { d_reqs[ phase ? 1 : 0 ][ f ].push_back( p ); }
- ///** add equality requirement */
- //void addEqRequirement( Node f, Node t, Node te, bool phase ) { d_eq_reqs[ phase ? 1 : 0 ][ f ][ t ].push_back( te ); }
-private:
- Node d_op;
- ModelEngine* d_me;
- std::vector< Node > d_ground_asserts;
- std::vector< Node > d_ground_asserts_reps;
- bool d_model_constructed;
- //store for set values
- std::map< Node, Node > d_set_values[2];
- // preferences for default values
- std::vector< Node > d_values;
- std::map< Node, std::vector< Node > > d_value_pro_con[2];
- /** set value */
- void setValue( Node n, Node v, bool ground = true );
- /** set model */
- void setModel();
- /** clear model */
- void clearModel();
-public:
- UfModel(){}
- UfModel( Node op, ModelEngine* qe );
- ~UfModel(){}
- //data structure that stores the model
- UfModelTreeOrdered d_tree;
- //quantifiers that are satisfied because of the constant definition of d_op
- bool d_reconsider_model;
-public:
- /** debug print */
- void debugPrint( const char* c );
- /** get constant value */
- Node getConstantValue( QuantifiersEngine* qe, Node n );
- /** is empty */
- bool isEmpty() { return d_ground_asserts.empty(); }
- /** is constant */
- bool isConstant();
-public:
- /** build model */
- void buildModel();
- /** make model */
- void makeModel( QuantifiersEngine* qe, UfModelTreeOrdered& tree );
-public:
- /** set value preference */
- void setValuePreference( Node f, Node n, bool isPro );
+protected:
+ //quantifiers engine
+ QuantifiersEngine* d_qe;
+ //map from operators to model preference data
+ std::map< Node, uf::UfModelPreferenceData > d_uf_prefs;
+ /** choose representative */
+ Node chooseRepresentative( TheoryModel* tm, Node eqc );
+ /** use constants for representatives */
+ void processBuildModel( TheoryModel* m );
+ //analyze quantifiers
+ void analyzeQuantifiers( FirstOrderModel* fm );
+ //build model
+ void finishBuildModel( FirstOrderModel* fm );
+ //theory-specific build models
+ void finishBuildModelUf( FirstOrderModel* fm, uf::UfModel& model );
+ //do InstGen techniques for quantifier, return number of lemmas produced
+ int doInstGen( FirstOrderModel* fm, Node f );
+public:
+ ModelEngineBuilder( QuantifiersEngine* qe );
+ virtual ~ModelEngineBuilder(){}
+public:
+ /** number of lemmas generated while building model */
+ int d_addedLemmas;
+ //map from quantifiers to if are constant SAT
+ std::map< Node, bool > d_quant_sat;
+ //map from quantifiers to the instantiation literals that their model is dependent upon
+ std::map< Node, std::vector< Node > > d_quant_selection_lits;
+public:
+ //map from quantifiers to model basis match
+ std::map< Node, InstMatch > d_quant_basis_match;
+ //options
+ bool optUseModel();
+ bool optInstGen();
+ bool optOneQuantPerRoundInstGen();
+ /** statistics class */
+ class Statistics {
+ public:
+ IntStat d_pre_sat_quant;
+ IntStat d_pre_nsat_quant;
+ Statistics();
+ ~Statistics();
+ };
+ Statistics d_statistics;
};
-
-
-
class ModelEngine : public QuantifiersModule
{
- friend class UfModel;
- friend class RepAlphabetIterator;
+ friend class uf::UfModel;
+ friend class RepSetIterator;
private:
- TheoryQuantifiers* d_th;
- QuantifiersEngine* d_quantEngine;
- uf::StrongSolverTheoryUf* d_ss;
+ /** builder class */
+ ModelEngineBuilder d_builder;
+private: //data maintained globally:
//which quantifiers have been initialized
std::map< Node, bool > d_quant_init;
- //map from ops to model basis terms
- std::map< Node, Node > d_model_basis_term;
- //map from instantiation terms to their model basis equivalent
- std::map< Node, Node > d_model_basis;
- //the model we are working with
- RepAlphabet d_ra;
- std::map< Node, UfModel > d_uf_model;
- ////map from model basis terms to quantifiers that are pro/con their definition
- //std::map< Node, std::vector< Node > > d_quant_pro_con[2];
- //map from quantifiers to model basis terms that are pro the definition of
- std::map< Node, std::vector< Node > > d_pro_con_quant[2];
- //map from quantifiers to if are constant SAT
- std::map< Node, bool > d_quant_sat;
+private: //analysis of current model:
+ //relevant domain
+ RelevantDomain d_rel_domain;
private:
- int evaluate( RepAlphabetIterator* rai, Node n, int& depIndex );
- int evaluateEquality( Node n1, Node n2, Node gn1, Node gn2, std::vector< Node >& fv_deps );
- Node evaluateTerm( Node n, Node gn, std::vector< Node >& fv_deps );
- //temporary storing which literals have failed
- void clearEvalFailed( int index );
- std::map< Node, bool > d_eval_failed;
- std::map< int, std::vector< Node > > d_eval_failed_lits;
- ////temporary storing for values/free variable dependencies
- //std::map< Node, Node > d_eval_term_vals;
- //std::map< Node, std::map< Node, std::vector< Node > > > d_eval_term_fv_deps;
+ //options
+ bool optOneInstPerQuantRound();
+ bool optUseRelevantDomain();
+ bool optOneQuantPerRound();
private:
- //map from terms to the models used to calculate their value
- std::map< Node, UfModelTreeOrdered > d_eval_term_model;
- std::map< Node, bool > d_eval_term_use_default_model;
- void makeEvalTermModel( Node n );
- //index ordering to use for each term
- std::map< Node, std::vector< int > > d_eval_term_index_order;
- int getMaxVariableNum( int n );
- void makeEvalTermIndexOrder( Node n );
-public:
- void increment( RepAlphabetIterator* rai );
+ //initialize quantifiers, return number of lemmas produced
+ int initializeQuantifier( Node f );
+ //exhaustively instantiate quantifier (possibly using mbqi), return number of lemmas produced
+ int exhaustiveInstantiate( Node f, bool useRelInstDomain = false );
private:
- //queries about equality
- bool areEqual( Node a, Node b );
- bool areDisequal( Node a, Node b );
-private:
- bool useModel();
-private:
- //initialize quantifiers, return false if lemma needed to be added
- bool initializeQuantifier( Node f );
- //build representatives
- void buildRepresentatives();
- //initialize model
- void initializeModel();
- //analyze quantifiers
- void analyzeQuantifiers();
- //instantiate quantifier, return number of lemmas produced
- int instantiateQuantifier( Node f );
-private:
- //register instantiation terms with their corresponding model basis terms
- void registerModelBasis( Node n, Node gn );
- //for building UF model
- void initializeUf( Node n );
- void collectUfTerms( Node n, std::vector< Node >& terms );
- void initializeUfModel( Node op );
- //void processPredicate( Node f, Node p, bool phase );
- //void processEquality( Node f, Node eq, bool phase );
+ //temporary statistics
+ int d_triedLemmas;
+ int d_testLemmas;
+ int d_totalLemmas;
+ int d_relevantLemmas;
public:
- ModelEngine( TheoryQuantifiers* th );
+ ModelEngine( QuantifiersEngine* qe );
~ModelEngine(){}
- //get quantifiers engine
- QuantifiersEngine* getQuantifiersEngine() { return d_quantEngine; }
- //get representatives
- RepAlphabet* getReps() { return &d_ra; }
- //get arbitrary element
- Node getArbitraryElement( TypeNode tn, std::vector< Node >& exclude );
- //get model basis term
- Node getModelBasisTerm( TypeNode tn, int i = 0 );
- //get model basis term for op
- Node getModelBasisApplyUfTerm( Node op );
- //is model basis term for op
- bool isModelBasisTerm( Node op, Node n );
public:
void check( Theory::Effort e );
void registerQuantifier( Node f );
class Statistics {
public:
IntStat d_inst_rounds;
- IntStat d_pre_sat_quant;
- IntStat d_pre_nsat_quant;
IntStat d_eval_formulas;
IntStat d_eval_eqs;
IntStat d_eval_uf_terms;
--- /dev/null
+/********************* */\r
+/*! \file relevant_domain.cpp\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Implementation of relevant domain class\r
+ **/\r
+\r
+#include "theory/quantifiers_engine.h"\r
+#include "theory/quantifiers/relevant_domain.h"\r
+#include "theory/quantifiers/term_database.h"\r
+#include "theory/quantifiers/first_order_model.h"\r
+\r
+using namespace std;\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::context;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::quantifiers;\r
+\r
+RelevantDomain::RelevantDomain( FirstOrderModel* m ) : d_model( m ){\r
+\r
+}\r
+\r
+void RelevantDomain::compute(){\r
+ d_quant_inst_domain.clear();\r
+ for( int i=0; i<(int)d_model->getNumAssertedQuantifiers(); i++ ){\r
+ Node f = d_model->getAssertedQuantifier( i );\r
+ d_quant_inst_domain[f].resize( f[0].getNumChildren() );\r
+ }\r
+ //add ground terms to domain (rule 1 of complete instantiation essentially uf fragment)\r
+ for( std::map< Node, uf::UfModel >::iterator it = d_model->d_uf_model.begin();\r
+ it != d_model->d_uf_model.end(); ++it ){\r
+ Node op = it->first;\r
+ for( int i=0; i<(int)it->second.d_ground_asserts.size(); i++ ){\r
+ Node n = it->second.d_ground_asserts[i];\r
+ //add arguments to domain\r
+ for( int j=0; j<(int)n.getNumChildren(); j++ ){\r
+ if( d_model->d_ra.hasType( n[j].getType() ) ){\r
+ Node ra = d_model->getRepresentative( n[j] );\r
+ int raIndex = d_model->d_ra.getIndexFor( ra );\r
+ Assert( raIndex!=-1 );\r
+ if( std::find( d_active_domain[op][j].begin(), d_active_domain[op][j].end(), raIndex )==d_active_domain[op][j].end() ){\r
+ d_active_domain[op][j].push_back( raIndex );\r
+ }\r
+ }\r
+ }\r
+ //add to range\r
+ Node r = it->second.d_ground_asserts_reps[i];\r
+ int raIndex = d_model->d_ra.getIndexFor( r );\r
+ Assert( raIndex!=-1 );\r
+ if( std::find( d_active_range[op].begin(), d_active_range[op].end(), raIndex )==d_active_range[op].end() ){\r
+ d_active_range[op].push_back( raIndex );\r
+ }\r
+ }\r
+ }\r
+ //find fixed point for relevant domain computation\r
+ bool success;\r
+ do{\r
+ success = true;\r
+ for( int i=0; i<(int)d_model->getNumAssertedQuantifiers(); i++ ){\r
+ Node f = d_model->getAssertedQuantifier( i );\r
+ //compute the domain of relevant instantiations (rule 3 of complete instantiation, essentially uf fragment)\r
+ if( computeRelevantInstantiationDomain( d_model->getTermDatabase()->getCounterexampleBody( f ), Node::null(), -1, d_quant_inst_domain[f] ) ){\r
+ success = false;\r
+ }\r
+ //extend the possible domain for functions (rule 2 of complete instantiation, essentially uf fragment)\r
+ RepDomain range;\r
+ if( extendFunctionDomains( d_model->getTermDatabase()->getCounterexampleBody( f ), range ) ){\r
+ success = false;\r
+ }\r
+ }\r
+ }while( !success );\r
+}\r
+\r
+bool RelevantDomain::computeRelevantInstantiationDomain( Node n, Node parent, int arg, std::vector< RepDomain >& rd ){\r
+ bool domainChanged = false;\r
+ if( n.getKind()==INST_CONSTANT ){\r
+ bool domainSet = false;\r
+ int vi = n.getAttribute(InstVarNumAttribute());\r
+ Assert( !parent.isNull() );\r
+ if( parent.getKind()==APPLY_UF ){\r
+ //if the child of APPLY_UF term f( ... ), only consider the active domain of f at given argument\r
+ Node op = parent.getOperator();\r
+ if( d_active_domain.find( op )!=d_active_domain.end() ){\r
+ for( size_t i=0; i<d_active_domain[op][arg].size(); i++ ){\r
+ int d = d_active_domain[op][arg][i];\r
+ if( std::find( rd[vi].begin(), rd[vi].end(), d )==rd[vi].end() ){\r
+ rd[vi].push_back( d );\r
+ domainChanged = true;\r
+ }\r
+ }\r
+ domainSet = true;\r
+ }\r
+ }\r
+ if( !domainSet ){\r
+ //otherwise, we must consider the entire domain\r
+ TypeNode tn = n.getType();\r
+ if( d_model->d_ra.hasType( tn ) ){\r
+ if( rd[vi].size()!=d_model->d_ra.d_type_reps[tn].size() ){\r
+ rd[vi].clear();\r
+ for( size_t i=0; i<d_model->d_ra.d_type_reps[tn].size(); i++ ){\r
+ rd[vi].push_back( i );\r
+ domainChanged = true;\r
+ }\r
+ }\r
+ }else{\r
+ //infinite domain?\r
+ }\r
+ }\r
+ }else{\r
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+ if( computeRelevantInstantiationDomain( n[i], n, i, rd ) ){\r
+ domainChanged = true;\r
+ }\r
+ }\r
+ }\r
+ return domainChanged;\r
+}\r
+\r
+bool RelevantDomain::extendFunctionDomains( Node n, RepDomain& range ){\r
+ if( n.getKind()==INST_CONSTANT ){\r
+ Node f = n.getAttribute(InstConstantAttribute());\r
+ int var = n.getAttribute(InstVarNumAttribute());\r
+ range.insert( range.begin(), d_quant_inst_domain[f][var].begin(), d_quant_inst_domain[f][var].end() );\r
+ return false;\r
+ }else{\r
+ Node op;\r
+ if( n.getKind()==APPLY_UF ){\r
+ op = n.getOperator();\r
+ }\r
+ bool domainChanged = false;\r
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+ RepDomain childRange;\r
+ if( extendFunctionDomains( n[i], childRange ) ){\r
+ domainChanged = true;\r
+ }\r
+ if( n.getKind()==APPLY_UF ){\r
+ if( d_active_domain.find( op )!=d_active_domain.end() ){\r
+ for( int j=0; j<(int)childRange.size(); j++ ){\r
+ int v = childRange[j];\r
+ if( std::find( d_active_domain[op][i].begin(), d_active_domain[op][i].end(), v )==d_active_domain[op][i].end() ){\r
+ d_active_domain[op][i].push_back( v );\r
+ domainChanged = true;\r
+ }\r
+ }\r
+ }else{\r
+ //do this?\r
+ }\r
+ }\r
+ }\r
+ //get the range\r
+ if( n.hasAttribute(InstConstantAttribute()) ){\r
+ if( n.getKind()==APPLY_UF && d_active_range.find( op )!=d_active_range.end() ){\r
+ range.insert( range.end(), d_active_range[op].begin(), d_active_range[op].end() );\r
+ }else{\r
+ //infinite range?\r
+ }\r
+ }else{\r
+ Node r = d_model->getRepresentative( n );\r
+ range.push_back( d_model->d_ra.getIndexFor( r ) );\r
+ }\r
+ return domainChanged;\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+/********************* */\r
+/*! \file relevant_domain.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief relevant domain class\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__RELEVANT_DOMAIN_H\r
+#define __CVC4__RELEVANT_DOMAIN_H\r
+\r
+#include "theory/quantifiers/first_order_model.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+namespace quantifiers {\r
+\r
+class RelevantDomain\r
+{\r
+private:\r
+ FirstOrderModel* d_model;\r
+\r
+ //the domain of the arguments for each operator\r
+ std::map< Node, std::map< int, RepDomain > > d_active_domain;\r
+ //the range for each operator\r
+ std::map< Node, RepDomain > d_active_range;\r
+ //for computing relevant instantiation domain, return true if changed\r
+ bool computeRelevantInstantiationDomain( Node n, Node parent, int arg, std::vector< RepDomain >& rd );\r
+ //for computing extended\r
+ bool extendFunctionDomains( Node n, RepDomain& range );\r
+public:\r
+ RelevantDomain( FirstOrderModel* m );\r
+ virtual ~RelevantDomain(){}\r
+ //compute the relevant domain\r
+ void compute();\r
+ //relevant instantiation domain for each quantifier\r
+ std::map< Node, std::vector< RepDomain > > d_quant_inst_domain;\r
+};\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif\r
--- /dev/null
+/********************* */\r
+/*! \file rep_set_iterator.cpp\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Implementation of relevant domain class\r
+ **/\r
+\r
+#include "theory/quantifiers/rep_set_iterator.h"\r
+#include "theory/quantifiers/model_engine.h"\r
+#include "theory/quantifiers/term_database.h"\r
+\r
+#define USE_INDEX_ORDERING\r
+\r
+using namespace std;\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::context;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::quantifiers;\r
+\r
+RepSetIterator::RepSetIterator( Node f, FirstOrderModel* model ) : d_f( f ), d_model( model ){\r
+ //store instantiation constants\r
+ for( size_t i=0; i<f[0].getNumChildren(); i++ ){\r
+ d_index.push_back( 0 );\r
+ }\r
+ for( size_t i=0; i<f[0].getNumChildren(); i++ ){\r
+ //store default index order\r
+ d_index_order.push_back( i );\r
+ d_var_order[i] = i;\r
+ //store default domain\r
+ d_domain.push_back( RepDomain() );\r
+ for( int j=0; j<(int)d_model->d_ra.d_type_reps[d_f[0][i].getType()].size(); j++ ){\r
+ d_domain[i].push_back( j );\r
+ }\r
+ }\r
+}\r
+\r
+void RepSetIterator::setIndexOrder( std::vector< int >& indexOrder ){\r
+ d_index_order.clear();\r
+ d_index_order.insert( d_index_order.begin(), indexOrder.begin(), indexOrder.end() );\r
+ //make the d_var_order mapping\r
+ for( int i=0; i<(int)d_index_order.size(); i++ ){\r
+ d_var_order[d_index_order[i]] = i;\r
+ }\r
+}\r
+\r
+void RepSetIterator::setDomain( std::vector< RepDomain >& domain ){\r
+ d_domain.clear();\r
+ d_domain.insert( d_domain.begin(), domain.begin(), domain.end() );\r
+ //we are done if a domain is empty\r
+ for( int i=0; i<(int)d_domain.size(); i++ ){\r
+ if( d_domain[i].empty() ){\r
+ d_index.clear();\r
+ }\r
+ }\r
+}\r
+\r
+void RepSetIterator::increment2( int counter ){\r
+ Assert( !isFinished() );\r
+#ifdef DISABLE_EVAL_SKIP_MULTIPLE\r
+ counter = (int)d_index.size()-1;\r
+#endif\r
+ //increment d_index\r
+ while( counter>=0 && d_index[counter]==(int)(d_domain[counter].size()-1) ){\r
+ counter--;\r
+ }\r
+ if( counter==-1 ){\r
+ d_index.clear();\r
+ }else{\r
+ for( int i=(int)d_index.size()-1; i>counter; i-- ){\r
+ d_index[i] = 0;\r
+ //d_model->clearEvalFailed( i );\r
+ }\r
+ d_index[counter]++;\r
+ //d_model->clearEvalFailed( counter );\r
+ }\r
+}\r
+\r
+void RepSetIterator::increment(){\r
+ if( !isFinished() ){\r
+ increment2( (int)d_index.size()-1 );\r
+ }\r
+}\r
+\r
+bool RepSetIterator::isFinished(){\r
+ return d_index.empty();\r
+}\r
+\r
+void RepSetIterator::getMatch( QuantifiersEngine* qe, InstMatch& m ){\r
+ for( int i=0; i<(int)d_index.size(); i++ ){\r
+ m.d_map[ qe->getTermDatabase()->getInstantiationConstant( d_f, d_index_order[i] ) ] = getTerm( i );\r
+ }\r
+}\r
+\r
+Node RepSetIterator::getTerm( int i ){\r
+ TypeNode tn = d_f[0][d_index_order[i]].getType();\r
+ Assert( d_model->d_ra.d_type_reps.find( tn )!=d_model->d_ra.d_type_reps.end() );\r
+ int index = d_index_order[i];\r
+ return d_model->d_ra.d_type_reps[tn][d_domain[index][d_index[index]]];\r
+}\r
+\r
+void RepSetIterator::debugPrint( const char* c ){\r
+ for( int i=0; i<(int)d_index.size(); i++ ){\r
+ Debug( c ) << i << " : " << d_index[i] << " : " << getTerm( i ) << std::endl;\r
+ }\r
+}\r
+\r
+void RepSetIterator::debugPrintSmall( const char* c ){\r
+ Debug( c ) << "RI: ";\r
+ for( int i=0; i<(int)d_index.size(); i++ ){\r
+ Debug( c ) << d_index[i] << ": " << getTerm( i ) << " ";\r
+ }\r
+ Debug( c ) << std::endl;\r
+}\r
+\r
+RepSetEvaluator::RepSetEvaluator( FirstOrderModel* m, RepSetIterator* ri ) : d_model( m ), d_riter( ri ){\r
+\r
+}\r
+\r
+//if evaluate( n, phaseReq ) = eVal,\r
+// if eVal = d_riter->d_index.size()\r
+// then the formula n instantiated with d_riter cannot be proven to be equal to phaseReq\r
+// otherwise,\r
+// each n{d_riter->d_index[0]/x_0...d_riter->d_index[eVal]/x_eVal, */x_(eVal+1) ... */x_n } is equal to phaseReq in the current model\r
+int RepSetEvaluator::evaluate( Node n, int& depIndex ){\r
+ ++d_eval_formulas;\r
+ //Debug("fmf-eval-debug") << "Evaluate " << n << " " << phaseReq << std::endl;\r
+ //Notice() << "Eval " << n << std::endl;\r
+ if( n.getKind()==NOT ){\r
+ int val = evaluate( n[0], depIndex );\r
+ return val==1 ? -1 : ( val==-1 ? 1 : 0 );\r
+ }else if( n.getKind()==OR || n.getKind()==AND || n.getKind()==IMPLIES ){\r
+ int baseVal = n.getKind()==AND ? 1 : -1;\r
+ int eVal = baseVal;\r
+ int posDepIndex = d_riter->getNumTerms();\r
+ int negDepIndex = -1;\r
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+ //evaluate subterm\r
+ int childDepIndex;\r
+ Node nn = ( i==0 && n.getKind()==IMPLIES ) ? n[i].notNode() : n[i];\r
+ int eValT = evaluate( nn, childDepIndex );\r
+ if( eValT==baseVal ){\r
+ if( eVal==baseVal ){\r
+ if( childDepIndex>negDepIndex ){\r
+ negDepIndex = childDepIndex;\r
+ }\r
+ }\r
+ }else if( eValT==-baseVal ){\r
+ eVal = -baseVal;\r
+ if( childDepIndex<posDepIndex ){\r
+ posDepIndex = childDepIndex;\r
+ if( posDepIndex==-1 ){\r
+ break;\r
+ }\r
+ }\r
+ }else if( eValT==0 ){\r
+ if( eVal==baseVal ){\r
+ eVal = 0;\r
+ }\r
+ }\r
+ }\r
+ if( eVal!=0 ){\r
+ depIndex = eVal==-baseVal ? posDepIndex : negDepIndex;\r
+ return eVal;\r
+ }else{\r
+ return 0;\r
+ }\r
+ }else if( n.getKind()==IFF || n.getKind()==XOR ){\r
+ int depIndex1;\r
+ int eVal = evaluate( n[0], depIndex1 );\r
+ if( eVal!=0 ){\r
+ int depIndex2;\r
+ int eVal2 = evaluate( n.getKind()==XOR ? n[1].notNode() : n[1], depIndex2 );\r
+ if( eVal2!=0 ){\r
+ depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;\r
+ return eVal==eVal2 ? 1 : -1;\r
+ }\r
+ }\r
+ return 0;\r
+ }else if( n.getKind()==ITE ){\r
+ int depIndex1, depIndex2;\r
+ int eVal = evaluate( n[0], depIndex1 );\r
+ if( eVal==0 ){\r
+ //evaluate children to see if they are the same value\r
+ int eval1 = evaluate( n[1], depIndex1 );\r
+ if( eval1!=0 ){\r
+ int eval2 = evaluate( n[1], depIndex2 );\r
+ if( eval1==eval2 ){\r
+ depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;\r
+ return eval1;\r
+ }\r
+ }\r
+ }else{\r
+ int eValT = evaluate( n[eVal==1 ? 1 : 2], depIndex2 );\r
+ depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;\r
+ return eValT;\r
+ }\r
+ return 0;\r
+ }else if( n.getKind()==FORALL ){\r
+ return 0;\r
+ }else{\r
+ ////if we know we will fail again, immediately return\r
+ //if( d_eval_failed.find( n )!=d_eval_failed.end() ){\r
+ // if( d_eval_failed[n] ){\r
+ // return -1;\r
+ // }\r
+ //}\r
+ //Debug("fmf-eval-debug") << "Evaluate literal " << n << std::endl;\r
+ //this should be a literal\r
+ //Node gn = n.substitute( d_riter->d_ic.begin(), d_riter->d_ic.end(), d_riter->d_terms.begin(), d_riter->d_terms.end() );\r
+ //Debug("fmf-eval-debug") << " Ground version = " << gn << std::endl;\r
+ int retVal = 0;\r
+ depIndex = d_riter->getNumTerms()-1;\r
+ if( n.getKind()==APPLY_UF ){\r
+ //case for boolean predicates\r
+ Node val = evaluateTerm( n, depIndex );\r
+ if( d_model->hasTerm( val ) ){\r
+ if( d_model->areEqual( val, d_model->d_true ) ){\r
+ retVal = 1;\r
+ }else{\r
+ retVal = -1;\r
+ }\r
+ }\r
+ }else if( n.getKind()==EQUAL ){\r
+ //case for equality\r
+ retVal = evaluateEquality( n[0], n[1], depIndex );\r
+ }else{\r
+ std::vector< int > cdi;\r
+ Node val = evaluateTermDefault( n, depIndex, cdi );\r
+ if( !val.isNull() ){\r
+ val = Rewriter::rewrite( val );\r
+ if( val==d_model->d_true ){\r
+ retVal = 1;\r
+ }else if( val==d_model->d_false ){\r
+ retVal = -1;\r
+ }\r
+ }\r
+ }\r
+ if( retVal!=0 ){\r
+ Debug("fmf-eval-debug") << "Evaluate literal: return " << retVal << ", depends = " << depIndex << std::endl;\r
+ }else{\r
+ Debug("fmf-eval-amb") << "Neither true nor false : " << n << std::endl;\r
+ //std::cout << "Neither true nor false : " << n << std::endl;\r
+ }\r
+ return retVal;\r
+ }\r
+}\r
+\r
+int RepSetEvaluator::evaluateEquality( Node n1, Node n2, int& depIndex ){\r
+ ++d_eval_eqs;\r
+ //Notice() << "Eval eq " << n1 << " " << n2 << std::endl;\r
+ Debug("fmf-eval-debug") << "Evaluate equality: " << std::endl;\r
+ Debug("fmf-eval-debug") << " " << n1 << " = " << n2 << std::endl;\r
+ int depIndex1, depIndex2;\r
+ Node val1 = evaluateTerm( n1, depIndex1 );\r
+ Node val2 = evaluateTerm( n2, depIndex2 );\r
+ Debug("fmf-eval-debug") << " Values : ";\r
+ d_model->printRepresentativeDebug( "fmf-eval-debug", val1 );\r
+ Debug("fmf-eval-debug") << " = ";\r
+ d_model->printRepresentativeDebug( "fmf-eval-debug", val2 );\r
+ Debug("fmf-eval-debug") << std::endl;\r
+ int retVal = 0;\r
+ if( !val1.isNull() && !val2.isNull() ){\r
+ if( d_model->areEqual( val1, val2 ) ){\r
+ retVal = 1;\r
+ }else if( d_model->areDisequal( val1, val2 ) ){\r
+ retVal = -1;\r
+ }else{\r
+ Node eq = val1.eqNode( val2 );\r
+ eq = Rewriter::rewrite( eq );\r
+ if( eq==d_model->d_true ){\r
+ retVal = 1;\r
+ }else if( eq==d_model->d_false ){\r
+ retVal = -1;\r
+ }\r
+ }\r
+ }\r
+ if( retVal!=0 ){\r
+ depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;\r
+ Debug("fmf-eval-debug") << " value = " << (retVal==1) << ", depIndex = " << depIndex << std::endl;\r
+ }else{\r
+ depIndex = d_riter->getNumTerms()-1;\r
+ Debug("fmf-eval-amb") << "Neither equal nor disequal : " << n1 << " , " << n2 << std::endl;\r
+ //std::cout << "Neither equal nor disequal : " << n1 << " , " << n2 << std::endl;\r
+ }\r
+ return retVal;\r
+}\r
+\r
+Node RepSetEvaluator::evaluateTerm( Node n, int& depIndex ){\r
+ //Notice() << "Eval term " << n << std::endl;\r
+ if( n.hasAttribute(InstConstantAttribute()) ){\r
+ Node val;\r
+ depIndex = d_riter->getNumTerms()-1;\r
+ //check the type of n\r
+ if( n.getKind()==INST_CONSTANT ){\r
+ int v = n.getAttribute(InstVarNumAttribute());\r
+ depIndex = d_riter->d_var_order[ v ];\r
+ val = d_riter->getTerm( v );\r
+ }else if( n.getKind()==ITE ){\r
+ int depIndex1, depIndex2;\r
+ int eval = evaluate( n[0], depIndex1 );\r
+ if( eval==0 ){\r
+ //evaluate children to see if they are the same\r
+ Node val1 = evaluateTerm( n[ 1 ], depIndex1 );\r
+ Node val2 = evaluateTerm( n[ 1 ], depIndex1 );\r
+ if( val1==val2 ){\r
+ val = val1;\r
+ depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;\r
+ }else{\r
+ return Node::null();\r
+ }\r
+ }else{\r
+ val = evaluateTerm( n[ eval==1 ? 1 : 2 ], depIndex2 );\r
+ depIndex = depIndex1>depIndex2 ? depIndex1 : depIndex2;\r
+ }\r
+ }else{\r
+#if 0\r
+ //for select, pre-process read over writes\r
+ if( n.getKind()==SELECT ){\r
+ Node selIndex = evaluateTerm( n[1], depIndex );\r
+ if( selIndex.isNull() ){\r
+ depIndex = d_riter->getNumTerms()-1;\r
+ return Node::null();\r
+ }\r
+ Node arr = n[0];\r
+ int eval = 1;\r
+ while( arr.getKind()==STORE && eval!=0 ){\r
+ int tempIndex;\r
+ eval = evaluateEquality( selIndex, arr[1], tempIndex );\r
+ depIndex = tempIndex > depIndex ? tempIndex : depIndex;\r
+ if( eval==1 ){\r
+ val = evaluateTerm( arr[2], tempIndex );\r
+ depIndex = tempIndex > depIndex ? tempIndex : depIndex;\r
+ return val;\r
+ }else if( eval==-1 ){\r
+ arr = arr[0];\r
+ }\r
+ }\r
+ n = NodeManager::currentNM()->mkNode( SELECT, arr, selIndex );\r
+ }\r
+#endif\r
+ //default term evaluate : evaluate all children, recreate the value\r
+ std::vector< int > children_depIndex;\r
+ val = evaluateTermDefault( n, depIndex, children_depIndex );\r
+ //case split on the type of term\r
+ if( n.getKind()==APPLY_UF ){\r
+ Node op = n.getOperator();\r
+ //Debug("fmf-eval-debug") << "Evaluate term " << n << " (" << gn << ")" << std::endl;\r
+ //if it is a defined UF, then consult the interpretation\r
+ ++d_eval_uf_terms;\r
+ int argDepIndex = 0;\r
+ if( d_model->d_uf_model.find( op )!=d_model->d_uf_model.end() ){\r
+ //make the term model specifically for n\r
+ makeEvalUfModel( n );\r
+ //now, consult the model\r
+ if( d_eval_uf_use_default[n] ){\r
+ val = d_model->d_uf_model[op].d_tree.getValue( d_model, val, argDepIndex );\r
+ }else{\r
+ val = d_eval_uf_model[ n ].getValue( d_model, val, argDepIndex );\r
+ }\r
+ //Debug("fmf-eval-debug") << "Evaluate term " << n << " (" << gn << ")" << std::endl;\r
+ //d_eval_uf_model[ n ].debugPrint("fmf-eval-debug", d_qe );\r
+ Assert( !val.isNull() );\r
+ }else{\r
+ d_eval_uf_use_default[n] = true;\r
+ argDepIndex = (int)n.getNumChildren();\r
+ }\r
+ //recalculate the depIndex\r
+ depIndex = -1;\r
+ for( int i=0; i<argDepIndex; i++ ){\r
+ int index = d_eval_uf_use_default[n] ? i : d_eval_term_index_order[n][i];\r
+ Debug("fmf-eval-debug") << "Add variables from " << index << "..." << std::endl;\r
+ if( children_depIndex[index]>depIndex ){\r
+ depIndex = children_depIndex[index];\r
+ }\r
+ }\r
+ Debug("fmf-eval-debug") << "Evaluate term " << n << " = ";\r
+ d_model->printRepresentativeDebug( "fmf-eval-debug", val );\r
+ Debug("fmf-eval-debug") << ", depIndex = " << depIndex << std::endl;\r
+ }else if( n.getKind()==SELECT ){\r
+ if( d_model->d_array_model.find( n[0] )!=d_model->d_array_model.end() ){\r
+ //consult the default value for the array DO_THIS\r
+ //val = Rewriter::rewrite( val );\r
+ //val = d_model->d_array_model[ n[0] ];\r
+ val = Rewriter::rewrite( val );\r
+ }else{\r
+ val = Rewriter::rewrite( val );\r
+ }\r
+ }else{\r
+ val = Rewriter::rewrite( val );\r
+ }\r
+ }\r
+ return val;\r
+ }else{\r
+ depIndex = -1;\r
+ return n;\r
+ }\r
+}\r
+\r
+Node RepSetEvaluator::evaluateTermDefault( Node n, int& depIndex, std::vector< int >& childDepIndex ){\r
+ //first we must evaluate the arguments\r
+ std::vector< Node > children;\r
+ if( n.getMetaKind()==kind::metakind::PARAMETERIZED ){\r
+ children.push_back( n.getOperator() );\r
+ }\r
+ depIndex = -1;\r
+ //for each argument, calculate its value, and the variables its value depends upon\r
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+ childDepIndex.push_back( -1 );\r
+ Node nn = evaluateTerm( n[i], childDepIndex[i] );\r
+ if( nn.isNull() ){\r
+ depIndex = d_riter->getNumTerms()-1;\r
+ return nn;\r
+ }else{\r
+ children.push_back( nn );\r
+ if( childDepIndex[i]>depIndex ){\r
+ depIndex = childDepIndex[i];\r
+ }\r
+ }\r
+ }\r
+ //recreate the value\r
+ return NodeManager::currentNM()->mkNode( n.getKind(), children );\r
+}\r
+\r
+void RepSetEvaluator::clearEvalFailed( int index ){\r
+ for( int i=0; i<(int)d_eval_failed_lits[index].size(); i++ ){\r
+ d_eval_failed[ d_eval_failed_lits[index][i] ] = false;\r
+ }\r
+ d_eval_failed_lits[index].clear();\r
+}\r
+\r
+void RepSetEvaluator::makeEvalUfModel( Node n ){\r
+ if( d_eval_uf_model.find( n )==d_eval_uf_model.end() ){\r
+ makeEvalUfIndexOrder( n );\r
+ if( !d_eval_uf_use_default[n] ){\r
+ Node op = n.getOperator();\r
+ d_eval_uf_model[n] = uf::UfModelTreeOrdered( op, d_eval_term_index_order[n] );\r
+ d_model->d_uf_model[op].makeModel( d_eval_uf_model[n] );\r
+ //Debug("fmf-index-order") << "Make model for " << n << " : " << std::endl;\r
+ //d_eval_uf_model[n].debugPrint( "fmf-index-order", d_qe, 2 );\r
+ }\r
+ }\r
+}\r
+\r
+struct sortGetMaxVariableNum {\r
+ std::map< Node, int > d_max_var_num;\r
+ int computeMaxVariableNum( Node n ){\r
+ if( n.getKind()==INST_CONSTANT ){\r
+ return n.getAttribute(InstVarNumAttribute());\r
+ }else if( n.hasAttribute(InstConstantAttribute()) ){\r
+ int maxVal = -1;\r
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+ int val = getMaxVariableNum( n[i] );\r
+ if( val>maxVal ){\r
+ maxVal = val;\r
+ }\r
+ }\r
+ return maxVal;\r
+ }else{\r
+ return -1;\r
+ }\r
+ }\r
+ int getMaxVariableNum( Node n ){\r
+ std::map< Node, int >::iterator it = d_max_var_num.find( n );\r
+ if( it==d_max_var_num.end() ){\r
+ int num = computeMaxVariableNum( n );\r
+ d_max_var_num[n] = num;\r
+ return num;\r
+ }else{\r
+ return it->second;\r
+ }\r
+ }\r
+ bool operator() (Node i,Node j) { return (getMaxVariableNum(i)<getMaxVariableNum(j));}\r
+};\r
+\r
+void RepSetEvaluator::makeEvalUfIndexOrder( Node n ){\r
+ if( d_eval_term_index_order.find( n )==d_eval_term_index_order.end() ){\r
+#ifdef USE_INDEX_ORDERING\r
+ //sort arguments in order of least significant vs. most significant variable in default ordering\r
+ std::map< Node, std::vector< int > > argIndex;\r
+ std::vector< Node > args;\r
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+ if( argIndex.find( n[i] )==argIndex.end() ){\r
+ args.push_back( n[i] );\r
+ }\r
+ argIndex[n[i]].push_back( i );\r
+ }\r
+ sortGetMaxVariableNum sgmvn;\r
+ std::sort( args.begin(), args.end(), sgmvn );\r
+ for( int i=0; i<(int)args.size(); i++ ){\r
+ for( int j=0; j<(int)argIndex[ args[i] ].size(); j++ ){\r
+ d_eval_term_index_order[n].push_back( argIndex[ args[i] ][j] );\r
+ }\r
+ }\r
+ bool useDefault = true;\r
+ for( int i=0; i<(int)d_eval_term_index_order[n].size(); i++ ){\r
+ if( i!=d_eval_term_index_order[n][i] ){\r
+ useDefault = false;\r
+ break;\r
+ }\r
+ }\r
+ d_eval_uf_use_default[n] = useDefault;\r
+ Debug("fmf-index-order") << "Will consider the following index ordering for " << n << " : ";\r
+ for( int i=0; i<(int)d_eval_term_index_order[n].size(); i++ ){\r
+ Debug("fmf-index-order") << d_eval_term_index_order[n][i] << " ";\r
+ }\r
+ Debug("fmf-index-order") << std::endl;\r
+#else\r
+ d_eval_uf_use_default[n] = true;\r
+#endif\r
+ }\r
+}\r
+\r
+\r
--- /dev/null
+/********************* */\r
+/*! \file rep_set_iterator.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief rep_set_iterator class\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__REP_SET_ITERATOR_H\r
+#define __CVC4__REP_SET_ITERATOR_H\r
+\r
+#include "theory/quantifiers_engine.h"\r
+#include "theory/quantifiers/first_order_model.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+namespace quantifiers {\r
+\r
+/** this class iterates over a RepSet */\r
+class RepSetIterator {\r
+public:\r
+ RepSetIterator( Node f, FirstOrderModel* model );\r
+ ~RepSetIterator(){}\r
+ //pointer to quantifier\r
+ Node d_f;\r
+ //pointer to model\r
+ FirstOrderModel* d_model;\r
+ //index we are considering\r
+ std::vector< int > d_index;\r
+ //domain we are considering\r
+ std::vector< RepDomain > d_domain;\r
+ //ordering for variables we are indexing over\r
+ // for example, given reps = { a, b } and quantifier forall( x, y, z ) P( x, y, z ) with d_index_order = { 2, 0, 1 },\r
+ // then we consider instantiations in this order:\r
+ // a/x a/y a/z\r
+ // a/x b/y a/z\r
+ // b/x a/y a/z\r
+ // b/x b/y a/z\r
+ // ...\r
+ std::vector< int > d_index_order;\r
+ //variables to index they are considered at\r
+ // for example, if d_index_order = { 2, 0, 1 }\r
+ // then d_var_order = { 0 -> 1, 1 -> 2, 2 -> 0 }\r
+ std::map< int, int > d_var_order;\r
+ //the instantiation constants of d_f\r
+ std::vector< Node > d_ic;\r
+ //the current terms we are considering\r
+ std::vector< Node > d_terms;\r
+public:\r
+ /** set index order */\r
+ void setIndexOrder( std::vector< int >& indexOrder );\r
+ /** set domain */\r
+ void setDomain( std::vector< RepDomain >& domain );\r
+ /** increment the iterator */\r
+ void increment2( int counter );\r
+ void increment();\r
+ /** is the iterator finished? */\r
+ bool isFinished();\r
+ /** produce the match that this iterator represents */\r
+ void getMatch( QuantifiersEngine* qe, InstMatch& m );\r
+ /** get the i_th term we are considering */\r
+ Node getTerm( int i );\r
+ /** get the number of terms we are considering */\r
+ int getNumTerms() { return d_f[0].getNumChildren(); }\r
+ /** debug print */\r
+ void debugPrint( const char* c );\r
+ void debugPrintSmall( const char* c );\r
+};\r
+\r
+class RepSetEvaluator\r
+{\r
+private:\r
+ FirstOrderModel* d_model;\r
+ RepSetIterator* d_riter;\r
+private: //for Theory UF:\r
+ //map from terms to the models used to calculate their value\r
+ std::map< Node, bool > d_eval_uf_use_default;\r
+ std::map< Node, uf::UfModelTreeOrdered > d_eval_uf_model;\r
+ void makeEvalUfModel( Node n );\r
+ //index ordering to use for each term\r
+ std::map< Node, std::vector< int > > d_eval_term_index_order;\r
+ int getMaxVariableNum( int n );\r
+ void makeEvalUfIndexOrder( Node n );\r
+private:\r
+ //default evaluate term function\r
+ Node evaluateTermDefault( Node n, int& depIndex, std::vector< int >& childDepIndex );\r
+ //temporary storing which literals have failed\r
+ void clearEvalFailed( int index );\r
+ std::map< Node, bool > d_eval_failed;\r
+ std::map< int, std::vector< Node > > d_eval_failed_lits;\r
+public:\r
+ RepSetEvaluator( FirstOrderModel* m, RepSetIterator* ri );\r
+ virtual ~RepSetEvaluator(){}\r
+ /** evaluate functions */\r
+ int evaluate( Node n, int& depIndex );\r
+ int evaluateEquality( Node n1, Node n2, int& depIndex );\r
+ Node evaluateTerm( Node n, int& depIndex );\r
+public:\r
+ //statistics\r
+ int d_eval_formulas;\r
+ int d_eval_eqs;\r
+ int d_eval_uf_terms;\r
+};\r
+\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif\r
--- /dev/null
+/********************* */\r
+/*! \file term_database.cpp\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Implementation of term databse class\r
+ **/\r
+\r
+ #include "theory/quantifiers/term_database.h"\r
+ #include "theory/quantifiers_engine.h"\r
+ #include "theory/uf/theory_uf_instantiator.h"\r
+ #include "theory/theory_engine.h"\r
+ #include "theory/quantifiers/first_order_model.h"\r
+\r
+using namespace std;\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::context;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::quantifiers;\r
+\r
+ bool TermArgTrie::addTerm2( QuantifiersEngine* qe, Node n, int argIndex ){\r
+ if( argIndex<(int)n.getNumChildren() ){\r
+ Node r = qe->getEqualityQuery()->getRepresentative( n[ argIndex ] );\r
+ std::map< Node, TermArgTrie >::iterator it = d_data.find( r );\r
+ if( it==d_data.end() ){\r
+ d_data[r].addTerm2( qe, n, argIndex+1 );\r
+ return true;\r
+ }else{\r
+ return it->second.addTerm2( qe, n, argIndex+1 );\r
+ }\r
+ }else{\r
+ //store n in d_data (this should be interpretted as the "data" and not as a reference to a child)\r
+ d_data[n].d_data.clear();\r
+ return false;\r
+ }\r
+ }\r
+\r
+ void TermDb::addTerm( Node n, std::vector< Node >& added, bool withinQuant ){\r
+ //don't add terms in quantifier bodies\r
+ if( !withinQuant || Options::current()->registerQuantBodyTerms ){\r
+ if( d_processed.find( n )==d_processed.end() ){\r
+ d_processed[n] = true;\r
+ //if this is an atomic trigger, consider adding it\r
+ if( Trigger::isAtomicTrigger( n ) ){\r
+ if( !n.hasAttribute(InstConstantAttribute()) ){\r
+ Debug("term-db") << "register trigger term " << n << std::endl;\r
+ //Notice() << "register trigger term " << n << std::endl;\r
+ Node op = n.getOperator();\r
+ d_op_map[op].push_back( n );\r
+ d_type_map[ n.getType() ].push_back( n );\r
+ added.push_back( n );\r
+\r
+ uf::InstantiatorTheoryUf* d_ith = (uf::InstantiatorTheoryUf*)d_quantEngine->getInstantiator( THEORY_UF );\r
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+ addTerm( n[i], added, withinQuant );\r
+ if( Options::current()->efficientEMatching ){\r
+ if( d_parents[n[i]][op].empty() ){\r
+ //must add parent to equivalence class info\r
+ Node nir = d_ith->getRepresentative( n[i] );\r
+ uf::EqClassInfo* eci_nir = d_ith->getEquivalenceClassInfo( nir );\r
+ if( eci_nir ){\r
+ eci_nir->d_pfuns[ op ] = true;\r
+ }\r
+ }\r
+ //add to parent structure\r
+ if( std::find( d_parents[n[i]][op][i].begin(), d_parents[n[i]][op][i].end(), n )==d_parents[n[i]][op][i].end() ){\r
+ d_parents[n[i]][op][i].push_back( n );\r
+ }\r
+ }\r
+ }\r
+ if( Options::current()->efficientEMatching ){\r
+ //new term, add n to candidate generators\r
+ for( int i=0; i<(int)d_ith->d_cand_gens[op].size(); i++ ){\r
+ d_ith->d_cand_gens[op][i]->addCandidate( n );\r
+ }\r
+ }\r
+ if( Options::current()->eagerInstQuant ){\r
+ if( !n.hasAttribute(InstLevelAttribute()) && n.getAttribute(InstLevelAttribute())==0 ){\r
+ int addedLemmas = 0;\r
+ for( int i=0; i<(int)d_ith->d_op_triggers[op].size(); i++ ){\r
+ addedLemmas += d_ith->d_op_triggers[op][i]->addTerm( n );\r
+ }\r
+ //Message() << "Terms, added lemmas: " << addedLemmas << std::endl;\r
+ d_quantEngine->flushLemmas( &d_quantEngine->getTheoryEngine()->getTheory( THEORY_QUANTIFIERS )->getOutputChannel() );\r
+ }\r
+ }\r
+ }\r
+ }\r
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+ addTerm( n[i], added, withinQuant );\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ void TermDb::reset( Theory::Effort effort ){\r
+ int nonCongruentCount = 0;\r
+ int congruentCount = 0;\r
+ int alreadyCongruentCount = 0;\r
+ //rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms\r
+ for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){\r
+ if( !it->second.empty() ){\r
+ if( it->second[0].getType()==NodeManager::currentNM()->booleanType() ){\r
+ d_pred_map_trie[ 0 ][ it->first ].d_data.clear();\r
+ d_pred_map_trie[ 1 ][ it->first ].d_data.clear();\r
+ }else{\r
+ d_func_map_trie[ it->first ].d_data.clear();\r
+ for( int i=0; i<(int)it->second.size(); i++ ){\r
+ Node n = it->second[i];\r
+ if( !n.getAttribute(NoMatchAttribute()) ){\r
+ if( !d_func_map_trie[ it->first ].addTerm( d_quantEngine, n ) ){\r
+ NoMatchAttribute nma;\r
+ n.setAttribute(nma,true);\r
+ congruentCount++;\r
+ }else{\r
+ nonCongruentCount++;\r
+ }\r
+ }else{\r
+ congruentCount++;\r
+ alreadyCongruentCount++;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ for( int i=0; i<2; i++ ){\r
+ Node n = NodeManager::currentNM()->mkConst( i==1 );\r
+ eq::EqClassIterator eqc( d_quantEngine->getEqualityQuery()->getRepresentative( n ),\r
+ ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine() );\r
+ while( !eqc.isFinished() ){\r
+ Node en = (*eqc);\r
+ if( en.getKind()==APPLY_UF && !en.hasAttribute(InstConstantAttribute()) ){\r
+ if( !en.getAttribute(NoMatchAttribute()) ){\r
+ Node op = en.getOperator();\r
+ if( !d_pred_map_trie[i][op].addTerm( d_quantEngine, en ) ){\r
+ NoMatchAttribute nma;\r
+ en.setAttribute(nma,true);\r
+ congruentCount++;\r
+ }else{\r
+ nonCongruentCount++;\r
+ }\r
+ }else{\r
+ alreadyCongruentCount++;\r
+ }\r
+ }\r
+ ++eqc;\r
+ }\r
+ }\r
+ Debug("term-db-cong") << "TermDb: Reset" << std::endl;\r
+ Debug("term-db-cong") << "Congruent/Non-Congruent = ";\r
+ Debug("term-db-cong") << congruentCount << "(" << alreadyCongruentCount << ") / " << nonCongruentCount << std::endl;\r
+}\r
+\r
+void TermDb::registerModelBasis( Node n, Node gn ){\r
+ if( d_model_basis.find( n )==d_model_basis.end() ){\r
+ d_model_basis[n] = gn;\r
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+ registerModelBasis( n[i], gn[i] );\r
+ }\r
+ }\r
+}\r
+\r
+Node TermDb::getModelBasisTerm( TypeNode tn, int i ){\r
+ if( d_model_basis_term.find( tn )==d_model_basis_term.end() ){\r
+ std::stringstream ss;\r
+ ss << Expr::setlanguage(Options::current()->outputLanguage);\r
+ ss << "e_" << tn;\r
+ d_model_basis_term[tn] = NodeManager::currentNM()->mkVar( ss.str(), tn );\r
+ ModelBasisAttribute mba;\r
+ d_model_basis_term[tn].setAttribute(mba,true);\r
+ }\r
+ return d_model_basis_term[tn];\r
+}\r
+\r
+Node TermDb::getModelBasisOpTerm( Node op ){\r
+ if( d_model_basis_op_term.find( op )==d_model_basis_op_term.end() ){\r
+ TypeNode t = op.getType();\r
+ std::vector< Node > children;\r
+ children.push_back( op );\r
+ for( size_t i=0; i<t.getNumChildren()-1; i++ ){\r
+ children.push_back( getModelBasisTerm( t[i] ) );\r
+ }\r
+ d_model_basis_op_term[op] = NodeManager::currentNM()->mkNode( APPLY_UF, children );\r
+ }\r
+ return d_model_basis_op_term[op];\r
+}\r
+\r
+void TermDb::computeModelBasisArgAttribute( Node n ){\r
+ if( !n.hasAttribute(ModelBasisArgAttribute()) ){\r
+ uint64_t val = 0;\r
+ //determine if it has model basis attribute\r
+ for( int j=0; j<(int)n.getNumChildren(); j++ ){\r
+ if( n[j].getAttribute(ModelBasisAttribute()) ){\r
+ val = 1;\r
+ break;\r
+ }\r
+ }\r
+ ModelBasisArgAttribute mbaa;\r
+ n.setAttribute( mbaa, val );\r
+ }\r
+}\r
+\r
+void TermDb::makeInstantiationConstantsFor( Node f ){\r
+ if( d_inst_constants.find( f )==d_inst_constants.end() ){\r
+ Debug("quantifiers-engine") << "Instantiation constants for " << f << " : " << std::endl;\r
+ for( int i=0; i<(int)f[0].getNumChildren(); i++ ){\r
+ d_vars[f].push_back( f[0][i] );\r
+ //make instantiation constants\r
+ Node ic = NodeManager::currentNM()->mkInstConstant( f[0][i].getType() );\r
+ d_inst_constants_map[ic] = f;\r
+ d_inst_constants[ f ].push_back( ic );\r
+ Debug("quantifiers-engine") << " " << ic << std::endl;\r
+ //set the var number attribute\r
+ InstVarNumAttribute ivna;\r
+ ic.setAttribute(ivna,i);\r
+ }\r
+ }\r
+}\r
+\r
+void TermDb::setInstantiationLevelAttr( Node n, uint64_t level ){\r
+ if( !n.hasAttribute(InstLevelAttribute()) ){\r
+ InstLevelAttribute ila;\r
+ n.setAttribute(ila,level);\r
+ }\r
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+ setInstantiationLevelAttr( n[i], level );\r
+ }\r
+}\r
+\r
+\r
+void TermDb::setInstantiationConstantAttr( Node n, Node f ){\r
+ if( !n.hasAttribute(InstConstantAttribute()) ){\r
+ bool setAttr = false;\r
+ if( n.getKind()==INST_CONSTANT ){\r
+ setAttr = true;\r
+ }else{\r
+ for( int i=0; i<(int)n.getNumChildren(); i++ ){\r
+ setInstantiationConstantAttr( n[i], f );\r
+ if( n[i].hasAttribute(InstConstantAttribute()) ){\r
+ setAttr = true;\r
+ }\r
+ }\r
+ }\r
+ if( setAttr ){\r
+ InstConstantAttribute ica;\r
+ n.setAttribute(ica,f);\r
+ //also set the no-match attribute\r
+ NoMatchAttribute nma;\r
+ n.setAttribute(nma,true);\r
+ }\r
+ }\r
+}\r
+\r
+\r
+Node TermDb::getCounterexampleBody( Node f ){\r
+ std::map< Node, Node >::iterator it = d_counterexample_body.find( f );\r
+ if( it==d_counterexample_body.end() ){\r
+ makeInstantiationConstantsFor( f );\r
+ Node n = getSubstitutedNode( f[1], f );\r
+ d_counterexample_body[ f ] = n;\r
+ return n;\r
+ }else{\r
+ return it->second;\r
+ }\r
+}\r
+\r
+Node TermDb::getSkolemizedBody( Node f ){\r
+ Assert( f.getKind()==FORALL );\r
+ if( d_skolem_body.find( f )==d_skolem_body.end() ){\r
+ std::vector< Node > vars;\r
+ for( int i=0; i<(int)f[0].getNumChildren(); i++ ){\r
+ Node skv = NodeManager::currentNM()->mkSkolem( f[0][i].getType() );\r
+ d_skolem_constants[ f ].push_back( skv );\r
+ vars.push_back( f[0][i] );\r
+ }\r
+ d_skolem_body[ f ] = f[ 1 ].substitute( vars.begin(), vars.end(),\r
+ d_skolem_constants[ f ].begin(), d_skolem_constants[ f ].end() );\r
+ if( f.hasAttribute(InstLevelAttribute()) ){\r
+ setInstantiationLevelAttr( d_skolem_body[ f ], f.getAttribute(InstLevelAttribute()) );\r
+ }\r
+ }\r
+ return d_skolem_body[ f ];\r
+}\r
+\r
+\r
+Node TermDb::getSubstitutedNode( Node n, Node f ){\r
+ return convertNodeToPattern(n,f,d_vars[f],d_inst_constants[ f ]);\r
+}\r
+\r
+Node TermDb::convertNodeToPattern( Node n, Node f, const std::vector<Node> & vars,\r
+ const std::vector<Node> & inst_constants){\r
+ Node n2 = n.substitute( vars.begin(), vars.end(),\r
+ inst_constants.begin(),\r
+ inst_constants.end() );\r
+ setInstantiationConstantAttr( n2, f );\r
+ return n2;\r
+}\r
+\r
+Node TermDb::getFreeVariableForInstConstant( Node n ){\r
+ TypeNode tn = n.getType();\r
+ if( d_free_vars.find( tn )==d_free_vars.end() ){\r
+ //if integer or real, make zero\r
+ if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){\r
+ Rational z(0);\r
+ d_free_vars[tn] = NodeManager::currentNM()->mkConst( z );\r
+ }else{\r
+ if( d_type_map[ tn ].empty() ){\r
+ d_free_vars[tn] = NodeManager::currentNM()->mkVar( tn );\r
+ }else{\r
+ d_free_vars[tn] = d_type_map[ tn ][ 0 ];\r
+ }\r
+ }\r
+ }\r
+ return d_free_vars[tn];\r
+}
\ No newline at end of file
--- /dev/null
+/**********************/\r
+/*! \file term_database.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief term database class\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__QUANTIFIERS_TERM_DATABASE_H\r
+#define __CVC4__QUANTIFIERS_TERM_DATABASE_H\r
+\r
+#include "theory/theory.h"\r
+\r
+#include <map>\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+\r
+class QuantifiersEngine;\r
+\r
+namespace quantifiers {\r
+\r
+class TermArgTrie {\r
+private:\r
+ bool addTerm2( QuantifiersEngine* qe, Node n, int argIndex );\r
+public:\r
+ /** the data */\r
+ std::map< Node, TermArgTrie > d_data;\r
+public:\r
+ bool addTerm( QuantifiersEngine* qe, Node n ) { return addTerm2( qe, n, 0 ); }\r
+};/* class TermArgTrie */\r
+\r
+class TermDb {\r
+ friend class ::CVC4::theory::QuantifiersEngine;\r
+private:\r
+ /** reference to the quantifiers engine */\r
+ QuantifiersEngine* d_quantEngine;\r
+ /** calculated no match terms */\r
+ bool d_matching_active;\r
+ /** terms processed */\r
+ std::map< Node, bool > d_processed;\r
+public:\r
+ TermDb( QuantifiersEngine* qe ) : d_quantEngine( qe ), d_matching_active( true ){}\r
+ ~TermDb(){}\r
+ /** map from APPLY_UF operators to ground terms for that operator */\r
+ std::map< Node, std::vector< Node > > d_op_map;\r
+ /** map from APPLY_UF functions to trie */\r
+ std::map< Node, TermArgTrie > d_func_map_trie;\r
+ /** map from APPLY_UF predicates to trie */\r
+ std::map< Node, TermArgTrie > d_pred_map_trie[2];\r
+ /** map from type nodes to terms of that type */\r
+ std::map< TypeNode, std::vector< Node > > d_type_map;\r
+ /** add a term to the database */\r
+ void addTerm( Node n, std::vector< Node >& added, bool withinQuant = false );\r
+ /** reset (calculate which terms are active) */\r
+ void reset( Theory::Effort effort );\r
+ /** set active */\r
+ void setMatchingActive( bool a ) { d_matching_active = a; }\r
+ /** get active */\r
+ bool getMatchingActive() { return d_matching_active; }\r
+public:\r
+ /** parent structure (for efficient E-matching):\r
+ n -> op -> index -> L\r
+ map from node "n" to a list of nodes "L", where each node n' in L\r
+ has operator "op", and n'["index"] = n.\r
+ for example, d_parents[n][f][1] = { f( t1, n ), f( t2, n ), ... }\r
+ */\r
+ std::map< Node, std::map< Node, std::map< int, std::vector< Node > > > > d_parents;\r
+private:\r
+ //map from types to model basis terms\r
+ std::map< TypeNode, Node > d_model_basis_term;\r
+ //map from ops to model basis terms\r
+ std::map< Node, Node > d_model_basis_op_term;\r
+ //map from instantiation terms to their model basis equivalent\r
+ std::map< Node, Node > d_model_basis;\r
+public:\r
+ //get model basis term\r
+ Node getModelBasisTerm( TypeNode tn, int i = 0 );\r
+ //get model basis term for op\r
+ Node getModelBasisOpTerm( Node op );\r
+ // compute model basis arg\r
+ void computeModelBasisArgAttribute( Node n );\r
+ //register instantiation terms with their corresponding model basis terms\r
+ void registerModelBasis( Node n, Node gn );\r
+ //get model basis\r
+ Node getModelBasis( Node n ) { return d_model_basis[n]; }\r
+private:\r
+ /** map from universal quantifiers to the list of variables */\r
+ std::map< Node, std::vector< Node > > d_vars;\r
+ /** map from universal quantifiers to the list of skolem constants */\r
+ std::map< Node, std::vector< Node > > d_skolem_constants;\r
+ /** map from universal quantifiers to their skolemized body */\r
+ std::map< Node, Node > d_skolem_body;\r
+ /** instantiation constants to universal quantifiers */\r
+ std::map< Node, Node > d_inst_constants_map;\r
+ /** map from universal quantifiers to their counterexample body */\r
+ std::map< Node, Node > d_counterexample_body;\r
+ /** free variable for instantiation constant type */\r
+ std::map< TypeNode, Node > d_free_vars;\r
+private:\r
+ /** make instantiation constants for */\r
+ void makeInstantiationConstantsFor( Node f );\r
+public:\r
+ /** map from universal quantifiers to the list of instantiation constants */\r
+ std::map< Node, std::vector< Node > > d_inst_constants;\r
+ /** set instantiation level attr */\r
+ void setInstantiationLevelAttr( Node n, uint64_t level );\r
+ /** set instantiation constant attr */\r
+ void setInstantiationConstantAttr( Node n, Node f );\r
+ /** get the i^th instantiation constant of f */\r
+ Node getInstantiationConstant( Node f, int i ) { return d_inst_constants[f][i]; }\r
+ /** get number of instantiation constants for f */\r
+ int getNumInstantiationConstants( Node f ) { return (int)d_inst_constants[f].size(); }\r
+ /** get the ce body f[e/x] */\r
+ Node getCounterexampleBody( Node f );\r
+ /** get the skolemized body f[e/x] */\r
+ Node getSkolemizedBody( Node f );\r
+ /** returns node n with bound vars of f replaced by instantiation constants of f\r
+ node n : is the futur pattern\r
+ node f : is the quantifier containing which bind the variable\r
+ return a pattern where the variable are replaced by variable for\r
+ instantiation.\r
+ */\r
+ Node getSubstitutedNode( Node n, Node f );\r
+ /** same as before but node f is just linked to the new pattern by the\r
+ applied attribute\r
+ vars the bind variable\r
+ nvars the same variable but with an attribute\r
+ */\r
+ Node convertNodeToPattern( Node n, Node f,\r
+ const std::vector<Node> & vars,\r
+ const std::vector<Node> & nvars);\r
+ /** get free variable for instantiation constant */\r
+ Node getFreeVariableForInstConstant( Node n );\r
+};/* class TermDb */\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif\r
#include <map>
#include <time.h>
#include "theory/quantifiers/theory_quantifiers_instantiator.h"
-
-#define USE_FLIP_DECISION
-
-//static bool clockSet = false;
-//double initClock;
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
d_numRestarts(0){
d_numInstantiations = 0;
d_baseDecLevel = -1;
- if( Options::current()->finiteModelFind ){
- qe->addModule( new ModelEngine( this ) );
- }else{
- qe->addModule( new InstantiationEngine( this ) );
- }
}
void TheoryQuantifiers::notifyEq(TNode lhs, TNode rhs) {
Debug("quantifiers-other") << "TheoryQuantifiers::notifyEq(): "
<< lhs << " = " << rhs << endl;
-
+
}
-void TheoryQuantifiers::preRegisterTerm(TNode n) {
+void TheoryQuantifiers::preRegisterTerm(TNode n) {
Debug("quantifiers-prereg") << "TheoryQuantifiers::preRegisterTerm() " << n << endl;
if( n.getKind()==FORALL && !n.hasAttribute(InstConstantAttribute()) ){
getQuantifiersEngine()->registerQuantifier( n );
}
}
+void TheoryQuantifiers::collectModelInfo( TheoryModel* m ){
+
+}
+
void TheoryQuantifiers::check(Effort e) {
CodeTimer codeTimer(d_theoryTime);
break;
}
}
- break;
+ break;
default:
Unhandled(assertion.getKind());
break;
Assert( n.getKind()== NOT && n[0].getKind()==FORALL );
if( !n[0].hasAttribute(InstConstantAttribute()) ){
if( d_skolemized.find( n )==d_skolemized.end() ){
- Node body = getQuantifiersEngine()->getSkolemizedBody( n[0] );
+ Node body = getQuantifiersEngine()->getTermDatabase()->getSkolemizedBody( n[0] );
NodeBuilder<> nb(kind::OR);
nb << n[0] << body.notNode();
Node lem = nb;
}
bool TheoryQuantifiers::flipDecision(){
-#ifndef USE_FLIP_DECISION
- return false;
-#else
//Debug("quantifiers-flip") << "No instantiation given, flip decision, level = " << d_valuation.getDecisionLevel() << std::endl;
//for( int i=1; i<=(int)d_valuation.getDecisionLevel(); i++ ){
// Debug("quantifiers-flip") << " " << d_valuation.getDecision( i ) << std::endl;
return restart();
}
return true;
-#endif
}
bool TheoryQuantifiers::restart(){
namespace quantifiers {
class TheoryEngine;
+class ModelEngine;
+class InstantiationEngine;
class TheoryQuantifiers : public Theory {
private:
void check(Effort e);
void propagate(Effort level);
Node getValue(TNode n);
+ void collectModelInfo( TheoryModel* m );
void shutdown() { }
std::string identify() const { return std::string("TheoryQuantifiers"); }
bool flipDecision();
}
-int InstantiatorTheoryQuantifiers::process( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstantiatorTheoryQuantifiers::process( Node f, Theory::Effort effort, int e ){
Debug("quant-quant") << "Quant: Try to solve (" << e << ") for " << f << "... " << std::endl;
if( e<5 ){
return InstStrategy::STATUS_UNFINISHED;
/** reset instantiation */
void processResetInstantiationRound( Theory::Effort effort );
/** process at effort */
- int process( Node f, Theory::Effort effort, int e, int limitInst );
+ int process( Node f, Theory::Effort effort, int e );
class Statistics {
public:
#include "theory/uf/theory_uf_instantiator.h"
#include "theory/uf/theory_uf_strong_solver.h"
#include "theory/uf/equality_engine.h"
+#include "theory/arrays/theory_arrays.h"
+#include "theory/datatypes/theory_datatypes.h"
#include "theory/quantifiers/quantifiers_rewriter.h"
+#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/instantiation_engine.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
d_no_instantiate_temp.insert( d_no_instantiate_temp.begin(), d_no_instantiate.begin(), d_no_instantiate.end() );
processResetInstantiationRound( effort );
}
+
/** do instantiation round method */
-int InstStrategy::doInstantiation( Node f, Theory::Effort effort, int e, int limitInst ){
+int InstStrategy::doInstantiation( Node f, Theory::Effort effort, int e ){
if( shouldInstantiate( f ) ){
int origLemmas = d_quantEngine->getNumLemmasWaiting();
- int retVal = process( f, effort, e, limitInst );
+ int retVal = process( f, effort, e );
if( d_quantEngine->getNumLemmasWaiting()!=origLemmas ){
for( int i=0; i<(int)d_priority_over.size(); i++ ){
d_priority_over[i]->d_no_instantiate_temp.push_back( f );
}
}
-bool TermArgTrie::addTerm2( QuantifiersEngine* qe, Node n, int argIndex ){
- if( argIndex<(int)n.getNumChildren() ){
- Node r = qe->getEqualityQuery()->getRepresentative( n[ argIndex ] );
- std::map< Node, TermArgTrie >::iterator it = d_data.find( r );
- if( it==d_data.end() ){
- d_data[r].addTerm2( qe, n, argIndex+1 );
- return true;
- }else{
- return it->second.addTerm2( qe, n, argIndex+1 );
- }
+QuantifiersEngine::QuantifiersEngine(context::Context* c, TheoryEngine* te):
+d_te( te ),
+d_active( c ){
+ d_eq_query = new EqualityQueryQuantifiersEngine( this );
+ d_term_db = new quantifiers::TermDb( this );
+ d_hasAddedLemma = false;
+
+ //the model object
+ d_model = new quantifiers::FirstOrderModel( this, c, "FirstOrderModel" );
+
+ //add quantifiers modules
+ if( !Options::current()->finiteModelFind || Options::current()->fmfInstEngine ){
+ //the instantiation must set incomplete flag unless finite model finding is turned on
+ d_inst_engine = new quantifiers::InstantiationEngine( this, !Options::current()->finiteModelFind );
+ d_modules.push_back( d_inst_engine );
}else{
- //store n in d_data (this should be interpretted as the "data" and not as a reference to a child)
- d_data[n].d_data.clear();
- return false;
+ d_inst_engine = NULL;
}
-}
-
-void TermDb::addTerm( Node n, std::vector< Node >& added, bool withinQuant ){
- //don't add terms in quantifier bodies
- if( !withinQuant || Options::current()->registerQuantBodyTerms ){
- if( d_processed.find( n )==d_processed.end() ){
- d_processed[n] = true;
- //if this is an atomic trigger, consider adding it
- if( Trigger::isAtomicTrigger( n ) ){
- if( !n.hasAttribute(InstConstantAttribute()) ){
- Debug("term-db") << "register trigger term " << n << std::endl;
- //Notice() << "register trigger term " << n << std::endl;
- Node op = n.getOperator();
- d_op_map[op].push_back( n );
- d_type_map[ n.getType() ].push_back( n );
- added.push_back( n );
-
- uf::InstantiatorTheoryUf* d_ith = (uf::InstantiatorTheoryUf*)d_quantEngine->getInstantiator( THEORY_UF );
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- addTerm( n[i], added, withinQuant );
- if( Options::current()->efficientEMatching ){
- if( d_parents[n[i]][op].empty() ){
- //must add parent to equivalence class info
- Node nir = d_ith->getRepresentative( n[i] );
- uf::EqClassInfo* eci_nir = d_ith->getEquivalenceClassInfo( nir );
- if( eci_nir ){
- eci_nir->d_pfuns[ op ] = true;
- }
- }
- //add to parent structure
- if( std::find( d_parents[n[i]][op][i].begin(), d_parents[n[i]][op][i].end(), n )==d_parents[n[i]][op][i].end() ){
- d_parents[n[i]][op][i].push_back( n );
- }
- }
- }
- if( Options::current()->efficientEMatching ){
- //new term, add n to candidate generators
- for( int i=0; i<(int)d_ith->d_cand_gens[op].size(); i++ ){
- d_ith->d_cand_gens[op][i]->addCandidate( n );
- }
- }
- if( Options::current()->eagerInstQuant ){
- if( !n.hasAttribute(InstLevelAttribute()) && n.getAttribute(InstLevelAttribute())==0 ){
- int addedLemmas = 0;
- for( int i=0; i<(int)d_ith->d_op_triggers[op].size(); i++ ){
- addedLemmas += d_ith->d_op_triggers[op][i]->addTerm( n );
- }
- //Message() << "Terms, added lemmas: " << addedLemmas << std::endl;
- d_quantEngine->flushLemmas( &d_quantEngine->getTheoryEngine()->getTheory( THEORY_QUANTIFIERS )->getOutputChannel() );
- }
- }
- }
- }
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- addTerm( n[i], added, withinQuant );
- }
- }
+ if( Options::current()->finiteModelFind ){
+ d_model_engine = new quantifiers::ModelEngine( this );
+ d_modules.push_back( d_model_engine );
+ }else{
+ d_model_engine = NULL;
}
-}
-void TermDb::reset( Theory::Effort effort ){
- int nonCongruentCount = 0;
- int congruentCount = 0;
- int alreadyCongruentCount = 0;
- //rebuild d_func/pred_map_trie for each operation, this will calculate all congruent terms
- for( std::map< Node, std::vector< Node > >::iterator it = d_op_map.begin(); it != d_op_map.end(); ++it ){
- if( !it->second.empty() ){
- if( it->second[0].getType()==NodeManager::currentNM()->booleanType() ){
- d_pred_map_trie[ 0 ][ it->first ].d_data.clear();
- d_pred_map_trie[ 1 ][ it->first ].d_data.clear();
- }else{
- d_func_map_trie[ it->first ].d_data.clear();
- for( int i=0; i<(int)it->second.size(); i++ ){
- Node n = it->second[i];
- if( !n.getAttribute(NoMatchAttribute()) ){
- if( !d_func_map_trie[ it->first ].addTerm( d_quantEngine, n ) ){
- NoMatchAttribute nma;
- n.setAttribute(nma,true);
- congruentCount++;
- }else{
- nonCongruentCount++;
- }
- }else{
- congruentCount++;
- alreadyCongruentCount++;
- }
- }
- }
- }
- }
- for( int i=0; i<2; i++ ){
- Node n = NodeManager::currentNM()->mkConst( i==1 );
- eq::EqClassIterator eqc( d_quantEngine->getEqualityQuery()->getRepresentative( n ),
- ((uf::TheoryUF*)d_quantEngine->getTheoryEngine()->getTheory( THEORY_UF ))->getEqualityEngine() );
- while( !eqc.isFinished() ){
- Node en = (*eqc);
- if( en.getKind()==APPLY_UF && !en.hasAttribute(InstConstantAttribute()) ){
- if( !en.getAttribute(NoMatchAttribute()) ){
- Node op = en.getOperator();
- if( !d_pred_map_trie[i][op].addTerm( d_quantEngine, en ) ){
- NoMatchAttribute nma;
- en.setAttribute(nma,true);
- congruentCount++;
- }else{
- nonCongruentCount++;
- }
- }else{
- alreadyCongruentCount++;
- }
- }
- ++eqc;
- }
- }
- Debug("term-db-cong") << "TermDb: Reset" << std::endl;
- Debug("term-db-cong") << "Congruent/Non-Congruent = ";
- Debug("term-db-cong") << congruentCount << "(" << alreadyCongruentCount << ") / " << nonCongruentCount << std::endl;
+ //options
+ d_optInstCheckDuplicate = true;
+ d_optInstMakeRepresentative = true;
+ d_optInstAddSplits = false;
+ d_optMatchIgnoreModelBasis = false;
+ d_optInstLimitActive = false;
+ d_optInstLimit = 0;
}
+Instantiator* QuantifiersEngine::getInstantiator( int id ){
+ return d_te->getTheory( id )->getInstantiator();
+}
-
-QuantifiersEngine::QuantifiersEngine(context::Context* c, TheoryEngine* te):
-d_te( te ),
-d_forall_asserts( c ),
-d_active( c ){
- d_eq_query = NULL;
- d_term_db = new TermDb( this );
+context::Context* QuantifiersEngine::getSatContext(){
+ return d_te->getTheory( THEORY_QUANTIFIERS )->getSatContext();
}
-Instantiator* QuantifiersEngine::getInstantiator( int id ){
- return d_te->getTheory( id )->getInstantiator();
+OutputChannel& QuantifiersEngine::getOutputChannel(){
+ return d_te->getTheory( THEORY_QUANTIFIERS )->getOutputChannel();
+}
+/** get default valuation for the quantifiers engine */
+Valuation& QuantifiersEngine::getValuation(){
+ return d_te->getTheory( THEORY_QUANTIFIERS )->getValuation();
}
void QuantifiersEngine::check( Theory::Effort e ){
CodeTimer codeTimer(d_time);
+ d_hasAddedLemma = false;
+ d_model_set = false;
if( e==Theory::EFFORT_LAST_CALL ){
++(d_statistics.d_instantiation_rounds_lc);
}else if( e==Theory::EFFORT_FULL ){
for( int i=0; i<(int)d_modules.size(); i++ ){
d_modules[i]->check( e );
}
- //if( e==Theory::EFFORT_FULL ){
- // Notice() << "Done instantiation Round" << std::endl;
- //}
+ //build the model if not done so already
+ // this happens if no quantifiers are currently asserted and no model-building module is enabled
+ if( Options::current()->produceModels && e==Theory::EFFORT_LAST_CALL && !d_hasAddedLemma && !d_model_set ){
+ d_te->getModelBuilder()->buildModel( d_model );
+ }
}
std::vector<Node> QuantifiersEngine::createInstVariable( std::vector<Node> & vars ){
return inst_constant;
}
-void QuantifiersEngine::makeInstantiationConstantsFor( Node f ){
- if( d_inst_constants.find( f )==d_inst_constants.end() ){
- Debug("quantifiers-engine") << "Instantiation constants for " << f << " : " << std::endl;
- for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
- d_vars[f].push_back( f[0][i] );
- //make instantiation constants
- Node ic = NodeManager::currentNM()->mkInstConstant( f[0][i].getType() );
- d_inst_constants_map[ic] = f;
- d_inst_constants[ f ].push_back( ic );
- Debug("quantifiers-engine") << " " << ic << std::endl;
- //set the var number attribute
- InstVarNumAttribute ivna;
- ic.setAttribute(ivna,i);
- }
- }
-}
-
void QuantifiersEngine::registerQuantifier( Node f ){
if( std::find( d_quants.begin(), d_quants.end(), f )==d_quants.end() ){
+ d_quants.push_back( f );
std::vector< Node > quants;
#ifdef REWRITE_ASSERTED_QUANTIFIERS
//do assertion-time rewriting of quantifier
++(d_statistics.d_num_quant);
Assert( quants[q].getKind()==FORALL );
//register quantifier
- d_quants.push_back( quants[q] );
+ d_r_quants.push_back( quants[q] );
//make instantiation constants for quants[q]
- makeInstantiationConstantsFor( quants[q] );
+ d_term_db->makeInstantiationConstantsFor( quants[q] );
//compute symbols in quants[q]
std::vector< Node > syms;
computeSymbols( quants[q][1], syms );
for( int i=0; i<(int)d_modules.size(); i++ ){
d_modules[i]->registerQuantifier( quants[q] );
}
- Node ceBody = getCounterexampleBody( quants[q] );
+ Node ceBody = d_term_db->getCounterexampleBody( quants[q] );
generatePhaseReqs( quants[q], ceBody );
//also register it with the strong solver
if( Options::current()->finiteModelFind ){
void QuantifiersEngine::registerPattern( std::vector<Node> & pattern) {
for(std::vector<Node>::iterator p = pattern.begin(); p != pattern.end(); ++p){
std::vector< Node > added;
- d_term_db->addTerm(*p,added);
+ getTermDatabase()->addTerm(*p,added);
}
}
void QuantifiersEngine::assertNode( Node f ){
Assert( f.getKind()==FORALL );
for( int j=0; j<(int)d_quant_rewritten[f].size(); j++ ){
- d_forall_asserts.push_back( d_quant_rewritten[f][j] );
+ d_model->d_forall_asserts.push_back( d_quant_rewritten[f][j] );
for( int i=0; i<(int)d_modules.size(); i++ ){
d_modules[i]->assertNode( d_quant_rewritten[f][j] );
}
}
}
+void QuantifiersEngine::resetInstantiationRound( Theory::Effort level ){
+ for( int i=0; i<theory::THEORY_LAST; i++ ){
+ if( getInstantiator( i ) ){
+ getInstantiator( i )->resetInstantiationRound( level );
+ }
+ }
+ getTermDatabase()->reset( level );
+}
+
void QuantifiersEngine::addTermToDatabase( Node n, bool withinQuant ){
- if( d_term_db ){
- std::vector< Node > added;
- d_term_db->addTerm( n, added, withinQuant );
+ std::vector< Node > added;
+ getTermDatabase()->addTerm( n, added, withinQuant );
#ifdef COMPUTE_RELEVANCE
- for( int i=0; i<(int)added.size(); i++ ){
- if( !withinQuant ){
- setRelevance( added[i].getOperator(), 0 );
- }
+ for( int i=0; i<(int)added.size(); i++ ){
+ if( !withinQuant ){
+ setRelevance( added[i].getOperator(), 0 );
}
-#endif
- }else{
- Notice() << "Warning: no term database for quantifier engine." << std::endl;
}
+#endif
+
}
bool QuantifiersEngine::addLemma( Node lem ){
//}
Assert( f.getKind()==FORALL );
Assert( !f.hasAttribute(InstConstantAttribute()) );
- Assert( d_vars[f].size()==terms.size() && d_vars[f].size()==f[0].getNumChildren() );
- Node body = f[ 1 ].substitute( d_vars[f].begin(), d_vars[f].end(),
+ Assert( d_term_db->d_vars[f].size()==terms.size() && d_term_db->d_vars[f].size()==f[0].getNumChildren() );
+ Node body = f[ 1 ].substitute( d_term_db->d_vars[f].begin(), d_term_db->d_vars[f].end(),
terms.begin(), terms.end() );
NodeBuilder<> nb(kind::OR);
nb << d_rewritten_quant[f].notNode() << body;
maxInstLevel = terms[i].getAttribute(InstLevelAttribute());
}
}else{
- setInstantiationLevelAttr( terms[i], 0 );
+ d_term_db->setInstantiationLevelAttr( terms[i], 0 );
}
}
}
- setInstantiationLevelAttr( body, maxInstLevel+1 );
+ d_term_db->setInstantiationLevelAttr( body, maxInstLevel+1 );
++(d_statistics.d_instantiations);
d_statistics.d_total_inst_var += (int)terms.size();
d_statistics.d_max_instantiation_level.maxAssign( maxInstLevel+1 );
}
}
-bool QuantifiersEngine::addInstantiation( Node f, InstMatch& m, bool addSplits ){
+bool QuantifiersEngine::addInstantiation( Node f, InstMatch& m ){
m.makeComplete( f, this );
m.makeRepresentative( this );
Debug("quant-duplicate") << "After make rep: " << m << std::endl;
}
Debug("quant-duplicate") << " -> Does not exist." << std::endl;
std::vector< Node > match;
- m.computeTermVec( d_inst_constants[f], match );
+ m.computeTermVec( d_term_db->d_inst_constants[f], match );
//old....
//m.makeRepresentative( d_eq_query );
}
void QuantifiersEngine::flushLemmas( OutputChannel* out ){
- for( int i=0; i<(int)d_lemmas_waiting.size(); i++ ){
- out->lemma( d_lemmas_waiting[i] );
- }
- d_lemmas_waiting.clear();
-}
-
-Node QuantifiersEngine::getCounterexampleBody( Node f ){
- std::map< Node, Node >::iterator it = d_counterexample_body.find( f );
- if( it==d_counterexample_body.end() ){
- makeInstantiationConstantsFor( f );
- Node n = getSubstitutedNode( f[1], f );
- d_counterexample_body[ f ] = n;
- return n;
- }else{
- return it->second;
- }
-}
-
-Node QuantifiersEngine::getSkolemizedBody( Node f ){
- Assert( f.getKind()==FORALL );
- if( d_skolem_body.find( f )==d_skolem_body.end() ){
- std::vector< Node > vars;
- for( int i=0; i<(int)f[0].getNumChildren(); i++ ){
- Node skv = NodeManager::currentNM()->mkSkolem( f[0][i].getType() );
- d_skolem_constants[ f ].push_back( skv );
- vars.push_back( f[0][i] );
- }
- d_skolem_body[ f ] = f[ 1 ].substitute( vars.begin(), vars.end(),
- d_skolem_constants[ f ].begin(), d_skolem_constants[ f ].end() );
- if( f.hasAttribute(InstLevelAttribute()) ){
- setInstantiationLevelAttr( d_skolem_body[ f ], f.getAttribute(InstLevelAttribute()) );
+ if( !d_lemmas_waiting.empty() ){
+ //take default output channel if none is provided
+ d_hasAddedLemma = true;
+ for( int i=0; i<(int)d_lemmas_waiting.size(); i++ ){
+ if( out ){
+ out->lemma( d_lemmas_waiting[i] );
+ }
}
+ d_lemmas_waiting.clear();
}
- return d_skolem_body[ f ];
}
void QuantifiersEngine::getPhaseReqTerms( Node f, std::vector< Node >& nodes ){
}
Debug("literal-matching") << " Make " << prev << " -> " << nodes[i] << std::endl;
Assert( prev.hasAttribute(InstConstantAttribute()) );
- setInstantiationConstantAttr( nodes[i], prev.getAttribute(InstConstantAttribute()) );
+ d_term_db->setInstantiationConstantAttr( nodes[i], prev.getAttribute(InstConstantAttribute()) );
++(d_statistics.d_lit_phase_req);
}else{
++(d_statistics.d_lit_phase_nreq);
}
-Node QuantifiersEngine::getSubstitutedNode( Node n, Node f ){
- return convertNodeToPattern(n,f,d_vars[f],d_inst_constants[ f ]);
-}
-
-Node QuantifiersEngine::convertNodeToPattern( Node n, Node f, const std::vector<Node> & vars,
- const std::vector<Node> & inst_constants){
- Node n2 = n.substitute( vars.begin(), vars.end(),
- inst_constants.begin(),
- inst_constants.end() );
- setInstantiationConstantAttr( n2, f );
- return n2;
-}
-
-
-void QuantifiersEngine::setInstantiationLevelAttr( Node n, uint64_t level ){
- if( !n.hasAttribute(InstLevelAttribute()) ){
- InstLevelAttribute ila;
- n.setAttribute(ila,level);
- }
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- setInstantiationLevelAttr( n[i], level );
- }
-}
-
-
-void QuantifiersEngine::setInstantiationConstantAttr( Node n, Node f ){
- if( !n.hasAttribute(InstConstantAttribute()) ){
- bool setAttr = false;
- if( n.getKind()==INST_CONSTANT ){
- setAttr = true;
- }else{
- for( int i=0; i<(int)n.getNumChildren(); i++ ){
- setInstantiationConstantAttr( n[i], f );
- if( n[i].hasAttribute(InstConstantAttribute()) ){
- setAttr = true;
- }
- }
- }
- if( setAttr ){
- InstConstantAttribute ica;
- n.setAttribute(ica,f);
- //also set the no-match attribute
- NoMatchAttribute nma;
- n.setAttribute(nma,true);
- }
- }
-}
-
QuantifiersEngine::Statistics::Statistics():
d_num_quant("QuantifiersEngine::Num_Quantifiers", 0),
d_instantiation_rounds("QuantifiersEngine::Rounds_Instantiation_Full", 0),
StatisticsRegistry::unregisterStat(&d_multi_trigger_instantiations);
}
-Node QuantifiersEngine::getFreeVariableForInstConstant( Node n ){
- TypeNode tn = n.getType();
- if( d_free_vars.find( tn )==d_free_vars.end() ){
- //if integer or real, make zero
- if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){
- Rational z(0);
- d_free_vars[tn] = NodeManager::currentNM()->mkConst( z );
- }else{
- if( d_term_db->d_type_map[ tn ].empty() ){
- d_free_vars[tn] = NodeManager::currentNM()->mkVar( tn );
- }else{
- d_free_vars[tn] =d_term_db->d_type_map[ tn ][ 0 ];
- }
- }
- }
- return d_free_vars[tn];
-}
-
/** compute symbols */
void QuantifiersEngine::computeSymbols( Node n, std::vector< Node >& syms ){
if( n.getKind()==APPLY_UF ){
}
}
}
+
+
+
+bool EqualityQueryQuantifiersEngine::hasTerm( Node a ){
+ eq::EqualityEngine* ee = d_qe->getTheoryEngine()->getSharedTermsDatabase()->getEqualityEngine();
+ if( ee->hasTerm( a ) ){
+ return true;
+ }
+ for( int i=0; i<theory::THEORY_LAST; i++ ){
+ if( d_qe->getInstantiator( i ) ){
+ if( d_qe->getInstantiator( i )->hasTerm( a ) ){
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+Node EqualityQueryQuantifiersEngine::getRepresentative( Node a ){
+ eq::EqualityEngine* ee = d_qe->getTheoryEngine()->getSharedTermsDatabase()->getEqualityEngine();
+ if( ee->hasTerm( a ) ){
+ return ee->getRepresentative( a );
+ }
+ for( int i=0; i<theory::THEORY_LAST; i++ ){
+ if( d_qe->getInstantiator( i ) ){
+ if( d_qe->getInstantiator( i )->hasTerm( a ) ){
+ return d_qe->getInstantiator( i )->getRepresentative( a );
+ }
+ }
+ }
+ return a;
+}
+
+bool EqualityQueryQuantifiersEngine::areEqual( Node a, Node b ){
+ if( a==b ){
+ return true;
+ }else{
+ eq::EqualityEngine* ee = d_qe->getTheoryEngine()->getSharedTermsDatabase()->getEqualityEngine();
+ if( ee->hasTerm( a ) && ee->hasTerm( b ) ){
+ if( ee->areEqual( a, b ) ){
+ return true;
+ }
+ }
+ for( int i=0; i<theory::THEORY_LAST; i++ ){
+ if( d_qe->getInstantiator( i ) ){
+ if( d_qe->getInstantiator( i )->areEqual( a, b ) ){
+ return true;
+ }
+ }
+ }
+ //std::cout << "Equal = " << eq_sh << " " << eq_uf << " " << eq_a << " " << eq_dt << std::endl;
+ return false;
+ }
+}
+
+bool EqualityQueryQuantifiersEngine::areDisequal( Node a, Node b ){
+ eq::EqualityEngine* ee = d_qe->getTheoryEngine()->getSharedTermsDatabase()->getEqualityEngine();
+ if( ee->hasTerm( a ) && ee->hasTerm( b ) ){
+ if( ee->areDisequal( a, b, false ) ){
+ return true;
+ }
+ }
+ for( int i=0; i<theory::THEORY_LAST; i++ ){
+ if( d_qe->getInstantiator( i ) ){
+ if( d_qe->getInstantiator( i )->areDisequal( a, b ) ){
+ return true;
+ }
+ }
+ }
+ return false;
+ //std::cout << "Disequal = " << deq_sh << " " << deq_uf << " " << deq_a << " " << deq_dt << std::endl;
+}
+
+Node EqualityQueryQuantifiersEngine::getInternalRepresentative( Node a ){
+ //for( int i=0; i<theory::THEORY_LAST; i++ ){
+ // if( d_qe->getInstantiator( i ) ){
+ // if( d_qe->getInstantiator( i )->hasTerm( a ) ){
+ // return d_qe->getInstantiator( i )->getInternalRepresentative( a );
+ // }
+ // }
+ //}
+ //return a;
+ return d_qe->getInstantiator( THEORY_UF )->getInternalRepresentative( a );
+}
/** reset instantiation */
virtual void processResetInstantiationRound( Theory::Effort effort ) = 0;
/** process method */
- virtual int process( Node f, Theory::Effort effort, int e, int limitInst = 0 ) = 0;
+ virtual int process( Node f, Theory::Effort effort, int e ) = 0;
public:
InstStrategy( QuantifiersEngine* ie ) : d_quantEngine( ie ){}
virtual ~InstStrategy(){}
/** reset instantiation */
void resetInstantiationRound( Theory::Effort effort );
/** do instantiation round method */
- int doInstantiation( Node f, Theory::Effort effort, int e, int limitInst = 0 );
+ int doInstantiation( Node f, Theory::Effort effort, int e );
/** update status */
static void updateStatus( int& currStatus, int addStatus ){
if( addStatus==STATUS_UNFINISHED ){
};/* class InstStrategy */
class QuantifiersModule {
+protected:
+ QuantifiersEngine* d_quantEngine;
public:
- QuantifiersModule(){}
+ QuantifiersModule( QuantifiersEngine* qe ) : d_quantEngine( qe ){}
~QuantifiersModule(){}
+ //get quantifiers engine
+ QuantifiersEngine* getQuantifiersEngine() { return d_quantEngine; }
/* Call during check registerQuantifier has already been called */
virtual void check( Theory::Effort e ) = 0;
/* Called for new quantifiers */
virtual Node explain(TNode n) = 0;
};/* class QuantifiersModule */
-class TermArgTrie {
-private:
- bool addTerm2( QuantifiersEngine* qe, Node n, int argIndex );
-public:
- /** the data */
- std::map< Node, TermArgTrie > d_data;
-public:
- bool addTerm( QuantifiersEngine* qe, Node n ) { return addTerm2( qe, n, 0 ); }
-};/* class TermArgTrie */
-
-class TermDb {
-private:
- /** reference to the quantifiers engine */
- QuantifiersEngine* d_quantEngine;
- /** calculated no match terms */
- bool d_matching_active;
- /** terms processed */
- std::map< Node, bool > d_processed;
-public:
- TermDb( QuantifiersEngine* qe ) : d_quantEngine( qe ), d_matching_active( true ){}
- ~TermDb(){}
- /** map from APPLY_UF operators to ground terms for that operator */
- std::map< Node, std::vector< Node > > d_op_map;
- /** map from APPLY_UF functions to trie */
- std::map< Node, TermArgTrie > d_func_map_trie;
- /** map from APPLY_UF predicates to trie */
- std::map< Node, TermArgTrie > d_pred_map_trie[2];
- /** map from type nodes to terms of that type */
- std::map< TypeNode, std::vector< Node > > d_type_map;
- /** add a term to the database */
- void addTerm( Node n, std::vector< Node >& added, bool withinQuant = false );
- /** reset (calculate which terms are active) */
- void reset( Theory::Effort effort );
- /** set active */
- void setMatchingActive( bool a ) { d_matching_active = a; }
- /** get active */
- bool getMatchingActive() { return d_matching_active; }
-public:
- /** parent structure (for efficient E-matching):
- n -> op -> index -> L
- map from node "n" to a list of nodes "L", where each node n' in L
- has operator "op", and n'["index"] = n.
- for example, d_parents[n][f][1] = { f( t1, n ), f( t2, n ), ... }
- */
- std::map< Node, std::map< Node, std::map< int, std::vector< Node > > > > d_parents;
-};/* class TermDb */
-
namespace quantifiers {
class InstantiationEngine;
+ class ModelEngine;
+ class TermDb;
+ class FirstOrderModel;
}/* CVC4::theory::quantifiers */
+
class QuantifiersEngine {
friend class quantifiers::InstantiationEngine;
+ friend class quantifiers::ModelEngine;
friend class InstMatch;
private:
typedef context::CDHashMap< Node, bool, NodeHashFunction > BoolMap;
TheoryEngine* d_te;
/** vector of modules for quantifiers */
std::vector< QuantifiersModule* > d_modules;
+ /** instantiation engine */
+ quantifiers::InstantiationEngine* d_inst_engine;
+ /** model engine */
+ quantifiers::ModelEngine* d_model_engine;
/** equality query class */
EqualityQuery* d_eq_query;
- /** list of all quantifiers */
+ /** list of all quantifiers (pre-rewrite) */
std::vector< Node > d_quants;
- /** list of quantifiers asserted in the current context */
- context::CDList<Node> d_forall_asserts;
- /** map from universal quantifiers to the list of variables */
- std::map< Node, std::vector< Node > > d_vars;
- /** map from universal quantifiers to the list of skolem constants */
- std::map< Node, std::vector< Node > > d_skolem_constants;
- /** map from universal quantifiers to their skolemized body */
- std::map< Node, Node > d_skolem_body;
- /** map from universal quantifiers to their bound body */
- std::map< Node, Node > d_bound_body;
- /** instantiation constants to universal quantifiers */
- std::map< Node, Node > d_inst_constants_map;
- /** map from universal quantifiers to their counterexample body */
- std::map< Node, Node > d_counterexample_body;
- /** map from universal quantifiers to the list of instantiation constants */
- std::map< Node, std::vector< Node > > d_inst_constants;
+ /** list of all quantifiers (post-rewrite) */
+ std::vector< Node > d_r_quants;
/** map from quantifiers to whether they are active */
BoolMap d_active;
/** lemmas produced */
std::map< Node, bool > d_lemmas_produced;
/** lemmas waiting */
std::vector< Node > d_lemmas_waiting;
+ /** has added lemma this round */
+ bool d_hasAddedLemma;
/** inst matches produced for each quantifier */
std::map< Node, InstMatchTrie > d_inst_match_trie;
- /** free variable for instantiation constant type */
- std::map< TypeNode, Node > d_free_vars;
/** owner of quantifiers */
std::map< Node, Theory* > d_owner;
/** term database */
- TermDb* d_term_db;
+ quantifiers::TermDb* d_term_db;
+ /** extended model object */
+ quantifiers::FirstOrderModel* d_model;
+ /** has the model been set? */
+ bool d_model_set;
/** universal quantifiers that have been rewritten */
std::map< Node, std::vector< Node > > d_quant_rewritten;
/** map from rewritten universal quantifiers to the quantifier they are the consequence of */
private:
/** helper functions compute phase requirements */
static void computePhaseReqs2( Node n, bool polarity, std::map< Node, int >& phaseReqs );
- /** set instantiation level attr */
- void setInstantiationLevelAttr( Node n, uint64_t level );
- /** set instantiation constant attr */
- void setInstantiationConstantAttr( Node n, Node f );
- /** make instantiation constants for */
- void makeInstantiationConstantsFor( Node f );
KEEP_STATISTIC(TimerStat, d_time, "theory::QuantifiersEngine::time");
TheoryEngine* getTheoryEngine() { return d_te; }
/** get equality query object */
EqualityQuery* getEqualityQuery() { return d_eq_query; }
- /** set equality query object */
- void setEqualityQuery( EqualityQuery* eq ) { d_eq_query = eq; }
+ /** get instantiation engine */
+ quantifiers::InstantiationEngine* getInstantiationEngine() { return d_inst_engine; }
+ /** get model engine */
+ quantifiers::ModelEngine* getModelEngine() { return d_model_engine; }
+ /** get default sat context for quantifiers engine */
+ context::Context* getSatContext();
+ /** get default output channel for the quantifiers engine */
+ OutputChannel& getOutputChannel();
+ /** get default valuation for the quantifiers engine */
+ Valuation& getValuation();
public:
- /** add module */
- void addModule( QuantifiersModule* qm ) { d_modules.push_back( qm ); }
/** check at level */
void check( Theory::Effort e );
/** register (non-rewritten) quantifier */
void assertNode( Node f );
/** propagate */
void propagate( Theory::Effort level );
+ /** reset instantiation round */
+ void resetInstantiationRound( Theory::Effort level );
+
+ //create inst variable
+ std::vector<Node> createInstVariable( std::vector<Node> & vars );
public:
/** add lemma lem */
bool addLemma( Node lem );
/** instantiate f with arguments terms */
bool addInstantiation( Node f, std::vector< Node >& terms );
/** do instantiation specified by m */
- bool addInstantiation( Node f, InstMatch& m, bool addSplits = false );
+ bool addInstantiation( Node f, InstMatch& m );
/** split on node n */
bool addSplit( Node n, bool reqPhase = false, bool reqPhasePol = true );
/** add split equality */
bool addSplitEquality( Node n1, Node n2, bool reqPhase = false, bool reqPhasePol = true );
/** has added lemma */
- bool hasAddedLemma() { return !d_lemmas_waiting.empty(); }
+ bool hasAddedLemma() { return !d_lemmas_waiting.empty() || d_hasAddedLemma; }
/** flush lemmas */
void flushLemmas( OutputChannel* out );
/** get number of waiting lemmas */
int getNumQuantifiers() { return (int)d_quants.size(); }
/** get quantifier */
Node getQuantifier( int i ) { return d_quants[i]; }
- /** get number of asserted quantifiers */
- int getNumAssertedQuantifiers() { return (int)d_forall_asserts.size(); }
- /** get asserted quantifier */
- Node getAssertedQuantifier( int i ) { return d_forall_asserts[i]; }
- /** get instantiation constants */
- void getInstantiationConstantsFor( Node f, std::vector< Node >& ics ) {
- ics.insert( ics.begin(), d_inst_constants[f].begin(), d_inst_constants[f].end() );
- }
- /** get the i^th instantiation constant of f */
- Node getInstantiationConstant( Node f, int i ) { return d_inst_constants[f][i]; }
- /** get number of instantiation constants for f */
- int getNumInstantiationConstants( Node f ) { return (int)d_inst_constants[f].size(); }
- std::vector<Node> createInstVariable( std::vector<Node> & vars );
-public:
- /** get the ce body f[e/x] */
- Node getCounterexampleBody( Node f );
- /** get the skolemized body f[e/x] */
- Node getSkolemizedBody( Node f );
/** set active */
void setActive( Node n, bool val ) { d_active[n] = val; }
/** get active */
static void computePhaseReqs( Node n, bool polarity, std::map< Node, bool >& phaseReqs );
/** compute phase requirements */
void generatePhaseReqs( Node f, Node n );
-public:
- /** returns node n with bound vars of f replaced by instantiation constants of f
- node n : is the futur pattern
- node f : is the quantifier containing which bind the variable
- return a pattern where the variable are replaced by variable for
- instantiation.
- */
- Node getSubstitutedNode( Node n, Node f );
- /** same as before but node f is just linked to the new pattern by the
- applied attribute
- vars the bind variable
- nvars the same variable but with an attribute
- */
- Node convertNodeToPattern( Node n, Node f,
- const std::vector<Node> & vars,
- const std::vector<Node> & nvars);
- /** get free variable for instantiation constant */
- Node getFreeVariableForInstConstant( Node n );
- /** get bound variable for variable */
- Node getBoundVariableForVariable( Node n );
public:
/** has owner */
bool hasOwner( Node f ) { return d_owner.find( f )!=d_owner.end(); }
/** set owner */
void setOwner( Node f, Theory* t ) { d_owner[f] = t; }
public:
+ /** get model */
+ quantifiers::FirstOrderModel* getModel() { return d_model; }
/** get term database */
- TermDb* getTermDatabase() { return d_term_db; }
+ quantifiers::TermDb* getTermDatabase() { return d_term_db; }
/** add term to database */
void addTermToDatabase( Node n, bool withinQuant = false );
private:
~Statistics();
};/* class QuantifiersEngine::Statistics */
Statistics d_statistics;
+public:
+ /** options */
+ bool d_optInstCheckDuplicate;
+ bool d_optInstMakeRepresentative;
+ bool d_optInstAddSplits;
+ bool d_optMatchIgnoreModelBasis;
+ bool d_optInstLimitActive;
+ int d_optInstLimit;
};/* class QuantifiersEngine */
+
+
+/** equality query object using theory engine */
+class EqualityQueryQuantifiersEngine : public EqualityQuery
+{
+private:
+ /** pointer to theory engine */
+ QuantifiersEngine* d_qe;
+public:
+ EqualityQueryQuantifiersEngine( QuantifiersEngine* qe ) : d_qe( qe ){}
+ ~EqualityQueryQuantifiersEngine(){}
+ /** general queries about equality */
+ bool hasTerm( Node a );
+ Node getRepresentative( Node a );
+ bool areEqual( Node a, Node b );
+ bool areDisequal( Node a, Node b );
+ Node getInternalRepresentative( Node a );
+}; /* EqualityQueryQuantifiersEngine */
+
}/* CVC4::theory namespace */
}/* CVC4 namespace */
const size_t gid){
/** TODO: Should use the representative of g, but should I keep the
mapping for myself? */
- /* If it false in one model (current valuation) it's false for all */
- if (useCurrentModel){
- Node val = getValuation().getValue(g0);
- Debug("rewriterules") << "getValue:" << g0 << " = "
- << val << " is " << (val == d_false) << std::endl;
- if (val == d_false) return AFALSE;
- };
+ //AJR: removed this code after talking with Francois
+ ///* If it false in one model (current valuation) it's false for all */
+ //if (useCurrentModel){
+ // Node val = getValuation().getValue(g0);
+ // Debug("rewriterules") << "getValue:" << g0 << " = "
+ // << val << " is " << (val == d_false) << std::endl;
+ // if (val == d_false) return AFALSE;
+ //};
/** Currently create a node with a literal */
Node g = getValuation().ensureLiteral(g0);
GuardedMap::iterator l_i = d_guardeds.find(g);
return substGuards(&i, TCache ());
}
+void TheoryRewriteRules::collectModelInfo( TheoryModel* m ){
+
+}
+
Theory::PPAssertStatus TheoryRewriteRules::ppAssert(TNode in, SubstitutionMap& outSubstitutions) {
addRewriteRule(in);
return PP_ASSERT_STATUS_UNSOLVED;
#include "theory/inst_match_impl.h"
#include "util/stats.h"
#include "theory/rewriterules/theory_rewriterules_preprocess.h"
+#include "theory/model.h"
namespace CVC4 {
namespace theory {
inside check */
typedef std::vector< RuleInst* > QRuleInsts;
QRuleInsts d_ruleinsts_to_add;
+
public:
/** true and false for predicate */
Node d_true;
/** Usual function for theories */
void check(Theory::Effort e);
Node explain(TNode n);
+ void collectModelInfo( TheoryModel* m );
void notifyEq(TNode lhs, TNode rhs);
std::string identify() const {
return "THEORY_REWRITERULES";
#include "theory/rewriterules/theory_rewriterules_preprocess.h"
#include "theory/rewriterules/theory_rewriterules.h"
+#include "theory/quantifiers/term_database.h"
+
using namespace std;
using namespace CVC4;
using namespace CVC4::kind;
TNode r){
if (tri.getKind() == kind::NOT && tri[0].getKind() == kind::APPLY_UF)
tri = tri[0];
- pattern.push_back(re.getQuantifiersEngine()->
+ pattern.push_back(re.getQuantifiersEngine()->getTermDatabase()->
convertNodeToPattern(tri,r,vars,inst_constants));
}
bool propagateEquality(TNode equality, bool polarity);
/** Theory engine */
- TheoryEngine* d_theoryEngine;
+ TheoryEngine* d_theoryEngine;
/** Are we in conflict */
context::CDO<bool> d_inConflict;
-
+
/** Conflicting terms, if any */
Node d_conflictLHS, d_conflictRHS;
-
+
/** Polarity of the conflict */
bool d_conflictPolarity;
*/
bool isKnown(TNode literal) const;
- /**
+ /**
* Returns an explanation of the propagation that came from the database.
*/
Node explain(TNode literal) const;
* Add an equality to propagate.
*/
void addEqualityToPropagate(TNode equality);
-
+
/**
- * Add a shared term to the database. The shared term is a subterm of the atom and
- * should be associated with the given theory.
+ * Add a shared term to the database. The shared term is a subterm of the atom and
+ * should be associated with the given theory.
*/
void addSharedTerm(TNode atom, TNode term, theory::Theory::Set theories);
* Get the theories that share the term and have been notified already.
*/
theory::Theory::Set getNotifiedTheories(TNode term) const;
-
+
/**
* Returns true if the term is currently registered as shared with some theory.
*/
*/
bool areDisequal(TNode a, TNode b) const;
+ /**
+ * get equality engine
+ */
+ theory::eq::EqualityEngine* getEqualityEngine() { return &d_equalityEngine; }
protected:
/**
break;
case THEORY_OF_TERM_BASED:
// Variables
- if (node.getMetaKind() == kind::metakind::VARIABLE) {
- if (theoryOf(node.getType()) != theory::THEORY_BOOL) {
+ if (node.getMetaKind() == kind::metakind::VARIABLE) {
+ if (theoryOf(node.getType()) != theory::THEORY_BOOL) {
// We treat the varibables as uninterpreted
return s_uninterpretedSortOwner;
} else {
// Except for the Boolean ones, which we just ignore anyhow
return theory::THEORY_BOOL;
}
- }
+ }
// Constants
if (node.getMetaKind() == kind::metakind::CONSTANT) {
- // Constants go to the theory of the type
+ // Constants go to the theory of the type
return theoryOf(node.getType());
- }
- // Equality
+ }
+ // Equality
if (node.getKind() == kind::EQUAL) {
// If one of them is an ITE, it's irelevant, since they will get replaced out anyhow
if (node[0].getKind() == kind::ITE) {
}
if (node[1].getKind() == kind::ITE) {
return theoryOf(node[1].getType());
- }
+ }
// If both sides belong to the same theory the choice is easy
TheoryId T1 = theoryOf(node[0]);
TheoryId T2 = theoryOf(node[1]);
return T1;
}
TheoryId T3 = theoryOf(node[0].getType());
- // This is a case of
+ // This is a case of
// * x*y = f(z) -> UF
// * x = c -> UF
// * f(x) = read(a, y) -> either UF or ARRAY
// at least one of the theories has to be parametric, i.e. theory of the type is different
- // from the theory of the term
+ // from the theory of the term
if (T1 == T3) {
return T2;
}
}
// If both are parametric, we take the smaller one (arbitraty)
return T1 < T2 ? T1 : T2;
- }
+ }
// Regular nodes are owned by the kind
- return kindToTheoryId(node.getKind());
- break;
+ return kindToTheoryId(node.getKind());
+ break;
default:
Unreachable();
- }
+ }
}
void Theory::addSharedTermInternal(TNode n) {
processResetInstantiationRound(effort);
}
-int Instantiator::doInstantiation(Node f, Theory::Effort effort, int e, int limitInst) {
+int Instantiator::doInstantiation(Node f, Theory::Effort effort, int e ) {
if(hasConstraintsFrom(f)) {
- int origLemmas = d_quantEngine->getNumLemmasWaiting();
- int status = process(f, effort, e, limitInst);
- if(limitInst <= 0 || (d_quantEngine->getNumLemmasWaiting()-origLemmas) < limitInst) {
- if(d_instStrategies.empty()) {
- Debug("inst-engine-inst") << "There are no instantiation strategies allocated." << endl;
- } else {
- for(int i = 0; i < (int) d_instStrategies.size(); ++i) {
- if(isActiveStrategy(d_instStrategies[i])) {
- Debug("inst-engine-inst") << d_instStrategies[i]->identify() << " process " << effort << endl;
- //call the instantiation strategy's process method
- int s_limitInst = limitInst > 0 ? limitInst - (d_quantEngine->getNumLemmasWaiting() - origLemmas) : 0;
- int s_status = d_instStrategies[i]->doInstantiation(f, effort, e, s_limitInst);
- Debug("inst-engine-inst") << " -> status is " << s_status << endl;
- if(limitInst > 0 && (d_quantEngine->getNumLemmasWaiting() - origLemmas) >= limitInst) {
- Assert( (d_quantEngine->getNumLemmasWaiting() - origLemmas) == limitInst );
- i = (int) d_instStrategies.size();
- status = InstStrategy::STATUS_UNKNOWN;
- } else {
- InstStrategy::updateStatus(status, s_status);
- }
- } else {
- Debug("inst-engine-inst") << d_instStrategies[i]->identify() << " is not active." << endl;
- }
+ int status = process(f, effort, e );
+ if(d_instStrategies.empty()) {
+ Debug("inst-engine-inst") << "There are no instantiation strategies allocated." << endl;
+ } else {
+ for(int i = 0; i < (int) d_instStrategies.size(); ++i) {
+ if(isActiveStrategy(d_instStrategies[i])) {
+ Debug("inst-engine-inst") << d_instStrategies[i]->identify() << " process " << effort << endl;
+ //call the instantiation strategy's process method
+ int s_status = d_instStrategies[i]->doInstantiation( f, effort, e );
+ Debug("inst-engine-inst") << " -> status is " << s_status << endl;
+ InstStrategy::updateStatus(status, s_status);
+ } else {
+ Debug("inst-engine-inst") << d_instStrategies[i]->identify() << " is not active." << endl;
}
}
}
class Instantiator;
class InstStrategy;
class QuantifiersEngine;
+class TheoryModel;
/**
* Information about an assertion for the theories.
static inline TheoryId theoryOf(TNode node) {
return theoryOf(s_theoryOfMode, node);
}
-
+
/** Set the theoryOf mode */
static void setTheoryOfMode(TheoryOfMode mode) {
s_theoryOfMode = mode;
}
-
+
/**
* Set the owner of the uninterpreted sort.
*/
}
/**
- * Return the value of a node (typically used after a ). If the
- * theory supports model generation but has no value for this node,
- * it should return Node::null(). If the theory doesn't support
- * model generation at all, or usually would but doesn't in its
- * current state, it should throw an exception saying so.
- *
- * The TheoryEngine is passed in so that you can recursively request
- * values for the Node's children. This is important because the
- * TheoryEngine takes care of simple cases (metakind CONSTANT,
- * Boolean-valued VARIABLES, ...) and can dispatch to other theories
- * if that's necessary. Only call your own getValue() recursively
- * if you *know* that you are responsible handle the Node you're
- * asking for; other theories can use your types, so be careful
- * here! To be safe, it's best to delegate back to the
- * TheoryEngine (by way of the Valuation proxy object, which avoids
- * direct dependence on TheoryEngine).
- *
- * Usually, you need to handle at least the two cases of EQUAL and
- * VARIABLE---EQUAL in case a value of yours is on the LHS of an
- * EQUAL, and VARIABLE for variables of your types. You also need
- * to support any operators that can survive your rewriter. You
- * don't need to handle constants, as they are handled by the
- * TheoryEngine.
- *
- * There are some gotchas here. The user may be requesting the
- * value of an expression that wasn't part of the satisfiable
- * assertion, or has been declared since. If you don't have a value
- * and suspect this situation is the case, return Node::null()
- * rather than throwing an exception.
- */
- virtual Node getValue(TNode n) {
- Unimplemented("Theory %s doesn't support Theory::getValue interface",
+ * Get all relevant information in this theory regarding the current
+ * model. This should be called after a call to check( FULL_EFFORT )
+ * for all theories with no conflicts and no lemmas added.
+ */
+ virtual void collectModelInfo( TheoryModel* m ){
+ Unimplemented("Theory %s doesn't support Theory::getModel interface",
identify().c_str());
- return Node::null();
}
/**
/** reset instantiation round */
virtual void processResetInstantiationRound( Theory::Effort effort ) = 0;
/** process quantifier */
- virtual int process( Node f, Theory::Effort effort, int e, int limitInst = 0 ) = 0;
+ virtual int process( Node f, Theory::Effort effort, int e ) = 0;
public:
/** set has constraints from quantifier f */
void setHasConstraintsFrom( Node f );
virtual void preRegisterTerm( Node t ) { }
/** assertNode function, assertion was asserted to theory */
virtual void assertNode( Node assertion ){}
- /** reset instantiation round */
- void resetInstantiationRound( Theory::Effort effort );
- /** do instantiation method*/
- int doInstantiation( Node f, Theory::Effort effort, int e, int limitInst = 0 );
/** identify */
virtual std::string identify() const { return std::string("Unknown"); }
/** print debug information */
virtual void debugPrint( const char* c ) {}
- /** get status */
- //int getStatus() { return d_status; }
+public:
+ /** reset instantiation round */
+ void resetInstantiationRound( Theory::Effort effort );
+ /** do instantiation method*/
+ int doInstantiation( Node f, Theory::Effort effort, int e );
+public:
+ /** general queries about equality */
+ virtual bool hasTerm( Node a ) { return false; }
+ virtual bool areEqual( Node a, Node b ) { return false; }
+ virtual bool areDisequal( Node a, Node b ) { return false; }
+ virtual Node getRepresentative( Node a ) { return a; }
+ virtual Node getInternalRepresentative( Node a ) { return getRepresentative( a ); }
};/* class Instantiator */
inline Assertion Theory::get() {
#include "util/node_visitor.h"
#include "util/ite_removal.h"
+#include "theory/model.h"
#include "theory/quantifiers_engine.h"
#include "theory/quantifiers/theory_quantifiers.h"
+#include "theory/quantifiers/model_engine.h"
+#include "theory/quantifiers/first_order_model.h"
using namespace std;
d_logicInfo(logicInfo),
d_sharedTerms(this, context),
d_quantEngine(NULL),
+ d_curr_model(NULL),
+ d_curr_model_builder(NULL),
d_ppCache(),
d_possiblePropagations(context),
d_hasPropagated(context),
// initialize the quantifiers engine
d_quantEngine = new QuantifiersEngine(context, this);
+ //build model information if applicable
+ d_curr_model = new theory::DefaultModel( context, "DefaultModel" );
+ d_curr_model_builder = new theory::TheoryEngineModelBuilder( this );
+
Rewriter::init();
StatisticsRegistry::registerStat(&d_combineTheoriesTime);
d_true = NodeManager::currentNM()->mkConst<bool>(true);
Dump(tag) << CommentCommand("Completeness check");
Dump(tag) << PushCommand();
- // Dump the shared terms
+ // Dump the shared terms
if (d_logicInfo.isSharingEnabled()) {
Dump(tag) << CommentCommand("Shared terms");
context::CDList<TNode>::const_iterator it = theory->shared_terms_begin(), it_end = theory->shared_terms_end();
}
}
- // Dump the assertions
+ // Dump the assertions
Dump(tag) << CommentCommand("Assertions");
context::CDList<Assertion>::const_iterator it = theory->facts_begin(), it_end = theory->facts_end();
for (; it != it_end; ++ it) {
// Get the assertion
Node assertionNode = (*it).assertion;
// Purify all the terms
-
+
BoolExpr assertionExpr(assertionNode.toExpr());
if ((*it).isPreregistered) {
Dump(tag) << CommentCommand("Preregistered");
continue;
}
- // Check equality
+ // Check equality
Dump(tag) << PushCommand();
BoolExpr eqExpr(equality.toExpr());
Dump(tag) << AssertCommand(eqExpr);
- Dump(tag) << CheckSatCommand();
+ Dump(tag) << CheckSatCommand();
Dump(tag) << PopCommand();
- // Check disequality
+ // Check disequality
Dump(tag) << PushCommand();
BoolExpr diseqExpr(disequality.toExpr());
Dump(tag) << AssertCommand(diseqExpr);
- Dump(tag) << CheckSatCommand();
- Dump(tag) << PopCommand();
+ Dump(tag) << CheckSatCommand();
+ Dump(tag) << PopCommand();
}
}
}
}
-
+
Dump(tag) << PopCommand();
}
}
// If in full effort, we have a fake new assertion just to jumpstart the checking
if (Theory::fullEffort(effort)) {
d_factsAsserted = true;
- }
-
+ }
+
// Check until done
while (d_factsAsserted && !d_inConflict && !d_lemmasAdded) {
// Must consult quantifiers theory for last call to ensure sat, or otherwise add a lemma
if( effort == Theory::EFFORT_FULL &&
- d_logicInfo.isQuantified() &&
! d_inConflict &&
! d_lemmasAdded ) {
- ((theory::quantifiers::TheoryQuantifiers*) d_theoryTable[THEORY_QUANTIFIERS])->performCheck(Theory::EFFORT_LAST_CALL);
- // if we have given up, then possibly flip decision
- if(Options::current()->flipDecision) {
- if(d_incomplete && !d_inConflict && !d_lemmasAdded) {
- if( ((theory::quantifiers::TheoryQuantifiers*) d_theoryTable[THEORY_QUANTIFIERS])->flipDecision() ) {
- d_incomplete = false;
+ if( d_logicInfo.isQuantified() ){
+ ((theory::quantifiers::TheoryQuantifiers*) d_theoryTable[THEORY_QUANTIFIERS])->performCheck(Theory::EFFORT_LAST_CALL);
+ // if we have given up, then possibly flip decision
+ if(Options::current()->flipDecision) {
+ if(d_incomplete && !d_inConflict && !d_lemmasAdded) {
+ if( ((theory::quantifiers::TheoryQuantifiers*) d_theoryTable[THEORY_QUANTIFIERS])->flipDecision() ) {
+ d_incomplete = false;
+ }
}
}
+ //if returning incomplete or SAT, we have ensured that the model in the quantifiers engine has been built
+ }else if( Options::current()->produceModels ){
+ //must build model at this point
+ d_curr_model_builder->buildModel( d_curr_model );
}
}
} catch(const theory::Interrupted&) {
Trace("theory") << "TheoryEngine::check() => conflict" << endl;
}
-
- // If fulleffort, check all theories
+
+ // If fulleffort, check all theories
if(Dump.isOn("theory::fullcheck") && Theory::fullEffort(effort)) {
if (!d_inConflict && !d_lemmasAdded) {
dumpAssertions("theory::fullcheck");
Node literal = value ? equality : equality.notNode();
Node normalizedLiteral = value ? normalizedEquality : normalizedEquality.notNode();
// We're sending the original literal back, backed by the normalized one
- if (markPropagation(literal, normalizedLiteral, /* to */ carePair.theory, /* from */ THEORY_SAT_SOLVER)) {
+ if (markPropagation(literal, normalizedLiteral, /* to */ carePair.theory, /* from */ THEORY_SAT_SOLVER)) {
// We assert it, and we know it's preregistereed if it's the same theory
bool preregistered = Theory::theoryOf(literal) == carePair.theory;
theoryOf(carePair.theory)->assertFact(literal, preregistered);
}
}
}
-
+
// We need to split on it
Debug("sharing") << "TheoryEngine::combineTheories(): requesting a split " << std::endl;
lemma(equality.orNode(equality.notNode()), false, false);
return true;
}
-Node TheoryEngine::getValue(TNode node) {
- kind::MetaKind metakind = node.getMetaKind();
-
- // special case: prop engine handles boolean vars
- if(metakind == kind::metakind::VARIABLE && node.getType().isBoolean()) {
- return d_propEngine->getValue(node);
+void TheoryEngine::collectModelInfo( theory::TheoryModel* m ){
+ //consult each theory to get all relevant information concerning the model
+ for( int i=0; i<theory::THEORY_LAST; i++ ){
+ if( d_theoryTable[i] ){
+ d_theoryTable[i]->collectModelInfo( m );
+ }
}
+}
- // special case: value of a constant == itself
- if(metakind == kind::metakind::CONSTANT) {
- return node;
+/* get model */
+TheoryModel* TheoryEngine::getModel(){
+ Debug("model") << "TheoryEngine::getModel()" << std::endl;
+ if( d_logicInfo.isQuantified() ){
+ Debug("model") << "Get model from quantifiers engine." << std::endl;
+ return d_quantEngine->getModel();
+ }else{
+ Debug("model") << "Get default model." << std::endl;
+ return d_curr_model;
}
-
- // otherwise ask the theory-in-charge
- return theoryOf(node)->getValue(node);
-
-}/* TheoryEngine::getValue(TNode node) */
+}
bool TheoryEngine::presolve() {
// What and where it came from
NodeTheoryPair toExplain(originalAssertion, fromTheoryId, d_propagationMapTimestamp);
- // See if the theory already got this literal
+ // See if the theory already got this literal
PropagationMap::const_iterator find = d_propagationMap.find(toAssert);
if (find != d_propagationMap.end()) {
// The theory already knows this
void TheoryEngine::assertToTheory(TNode assertion, theory::TheoryId toTheoryId, theory::TheoryId fromTheoryId) {
-
+
Trace("theory::assertToTheory") << "TheoryEngine::assertToTheory(" << assertion << ", " << toTheoryId << ", " << fromTheoryId << ")" << std::endl;
-
+
Assert(toTheoryId != fromTheoryId);
-
+
if (d_inConflict) {
return;
}
// We assert it, and we know it's preregistereed
toTheory->assertFact(assertion, true);
// Mark that we have more information
- d_factsAsserted = true;
+ d_factsAsserted = true;
} else {
Assert(toTheoryId == THEORY_SAT_SOLVER);
// Check for propositional conflict
} else {
return;
}
- }
+ }
d_propagatedLiterals.push_back(assertion);
}
return;
}
-
+
// Polarity of the assertion
bool polarity = assertion.getKind() != kind::NOT;
-
+
// Atom of the assertion
TNode atom = polarity ? assertion : assertion[0];
-
+
// If sending to the shared terms database, it's also simple
if (toTheoryId == THEORY_BUILTIN) {
Assert(atom.getKind() == kind::EQUAL);
}
return;
}
-
- // Things from the SAT solver are already normalized, so they go
+
+ // Things from the SAT solver are already normalized, so they go
// directly to the apropriate theory
if (fromTheoryId == THEORY_SAT_SOLVER) {
- // We know that this is normalized, so just send it off to the theory
+ // We know that this is normalized, so just send it off to the theory
if (markPropagation(assertion, assertion, toTheoryId, fromTheoryId)) {
// We assert it, and we know it's preregistereed coming from the SAT solver directly
theoryOf(toTheoryId)->assertFact(assertion, true);
}
return;
}
-
+
// Propagations to the SAT solver are just enqueued for pickup by
// the SAT solver later
if (toTheoryId == THEORY_SAT_SOLVER) {
// Normalize to lhs < rhs if not a sat literal
Assert(atom.getKind() == kind::EQUAL);
Assert(atom[0] != atom[1]);
-
+
Node normalizedAtom = atom;
if (!d_propEngine->isSatLiteral(normalizedAtom)) {
Node reverse = atom[1].eqNode(atom[0]);
if (d_propEngine->isSatLiteral(reverse) || atom[0] > atom[1]) {
normalizedAtom = reverse;
- }
- }
+ }
+ }
Node normalizedAssertion = polarity ? normalizedAtom : normalizedAtom.notNode();
// Try and assert (note that we assert the non-normalized one)
// Assert away
theoryOf(toTheoryId)->assertFact(normalizedAssertion, preregistered);
d_factsAsserted = true;
- }
+ }
return;
}
void TheoryEngine::assertFact(TNode literal)
{
Trace("theory") << "TheoryEngine::assertFact(" << literal << ")" << std::endl;
-
+
d_propEngine->checkTime();
// If we're in conflict, nothing to do
}
if (theory != THEORY_BUILTIN) {
// Assert to the shared terms database
- assertToTheory(literal, /* to */ THEORY_BUILTIN, /* from */ theory);
+ assertToTheory(literal, /* to */ THEORY_BUILTIN, /* from */ theory);
}
} else {
// Just send off to the SAT solver
return explanation;
}
- // Initial thing to explain
+ // Initial thing to explain
NodeTheoryPair toExplain(node, THEORY_SAT_SOLVER, d_propagationMapTimestamp);
Assert(d_propagationMap.find(toExplain) != d_propagationMap.end());
// Create the workplace for explanations
// Process the explanation
getExplanation(explanationVector);
Node explanation = mkExplanation(explanationVector);
-
+
Debug("theory::explain") << "TheoryEngine::getExplanation(" << node << ") => " << explanation << std::endl;
-
+
return explanation;
}
if(!removable) {
d_decisionEngine->addAssertions(additionalLemmas, 1, iteSkolemMap);
}
-
+
// Mark that we added some lemmas
d_lemmasAdded = true;
Dump("t-conflicts") << CommentCommand("theory conflict: expect unsat")
<< CheckSatCommand(conflict.toExpr());
}
-
+
// In the multiple-theories case, we need to reconstruct the conflict
if (d_logicInfo.isSharingEnabled()) {
// Create the workplace for explanations
unsigned i = 0; // Index of the current literal we are processing
unsigned j = 0; // Index of the last literal we are keeping
-
+
while (i < explanationVector.size()) {
-
+
// Get the current literal to explain
NodeTheoryPair toExplain = explanationVector[i];
if (toExplain.node.isConst() && toExplain.node.getConst<bool>()) {
++ i;
continue;
- }
+ }
if (toExplain.node.getKind() == kind::NOT && toExplain.node[0].isConst() && !toExplain.node[0].getConst<bool>()) {
++ i;
continue;
continue;
}
- // See if it was sent to the theory by another theory
+ // See if it was sent to the theory by another theory
PropagationMap::const_iterator find = d_propagationMap.find(toExplain);
if (find != d_propagationMap.end()) {
// There is some propagation, check if its a timely one
explanationVector.push_back(newExplain);
++ i;
}
-
+
// Keep only the relevant literals
explanationVector.resize(j);
-}
+}
void TheoryEngine::ppUnconstrainedSimp(vector<Node>& assertions)
#include "util/cache.h"
#include "theory/ite_simplifier.h"
#include "theory/unconstrained_simplifier.h"
+#include "theory/model.h"
namespace CVC4 {
/**
- * A pair of a theory and a node. This is used to mark the flow of
+ * A pair of a theory and a node. This is used to mark the flow of
* propagations between theories.
- */
+ */
struct NodeTheoryPair {
Node node;
theory::TheoryId theory;
: node(node), theory(theory), timestamp(timestamp) {}
NodeTheoryPair()
: theory(theory::THEORY_LAST) {}
- // Comparison doesn't take into account the timestamp
+ // Comparison doesn't take into account the timestamp
bool operator == (const NodeTheoryPair& pair) const {
return node == pair.node && theory == pair.theory;
}
* CVC4.
*/
class TheoryEngine {
-
+
/** Shared terms database can use the internals notify the theories */
friend class SharedTermsDatabase;
*/
theory::QuantifiersEngine* d_quantEngine;
+ /**
+ * Default model object
+ */
+ theory::DefaultModel* d_curr_model;
+ /**
+ * Model builder object
+ */
+ theory::TheoryEngineModelBuilder* d_curr_model_builder;
+
typedef std::hash_map<Node, Node, NodeHashFunction> NodeMap;
typedef std::hash_map<TNode, Node, TNodeHashFunction> TNodeMap;
* Adds a new lemma, returning its status.
*/
theory::LemmaStatus lemma(TNode node, bool negated, bool removable);
-
+
/** Time spent in theory combination */
TimerStat d_combineTheoriesTime;
return d_propEngine;
}
+ /**
+ * Get a pointer to the underlying sat context.
+ */
+ inline context::Context* getSatContext() const {
+ return d_context;
+ }
+
/**
* Get a pointer to the underlying quantifiers engine.
*/
void assertToTheory(TNode assertion, theory::TheoryId toTheoryId, theory::TheoryId fromTheoryId);
/**
- * Marks a theory propagation from a theory to a theory where a
+ * Marks a theory propagation from a theory to a theory where a
* theory could be the THEORY_SAT_SOLVER for literals coming from
* or being propagated to the SAT solver. If the receiving theory
* already recieved the literal, the method returns false, otherwise
* it returns true.
- *
+ *
* @param assertion the normalized assertion being sent
* @param originalAssertion the actual assertion that was sent
* @param toTheoryId the theory that is on the receiving end
/**
* Computes the explanation by travarsing the propagation graph and
- * asking relevant theories to explain the propagations. Initially
+ * asking relevant theories to explain the propagations. Initially
* the explanation vector should contain only the element (node, theory)
* where the node is the one to be explained, and the theory is the
* theory that sent the literal.
Node getExplanation(TNode node);
/**
- * Returns the value of the given node.
+ * collect model info
+ */
+ void collectModelInfo( theory::TheoryModel* m );
+
+ /**
+ * Get the current model
*/
- Node getValue(TNode node);
+ theory::TheoryModel* getModel();
+
+ /**
+ * Get the model builder
+ */
+ theory::TheoryEngineModelBuilder* getModelBuilder() { return d_curr_model_builder; }
/**
* Get the theory associated to a given Node.
Node ppSimpITE(TNode assertion);
void ppUnconstrainedSimp(std::vector<Node>& assertions);
+ SharedTermsDatabase* getSharedTermsDatabase() { return &d_sharedTerms; }
+
};/* class TheoryEngine */
}/* CVC4 namespace */
return d_mg->addTerm( d_f, t, d_quantEngine );
}
-int Trigger::addInstantiations( InstMatch& baseMatch, int instLimit, bool addSplits ){
- int addedLemmas = d_mg->addInstantiations( d_f, baseMatch, d_quantEngine, instLimit, addSplits );
+int Trigger::addInstantiations( InstMatch& baseMatch ){
+ int addedLemmas = d_mg->addInstantiations( d_f, baseMatch, d_quantEngine );
if( addedLemmas>0 ){
Debug("inst-trigger") << "Added " << addedLemmas << " lemmas, trigger was ";
for( int i=0; i<(int)d_nodes.size(); i++ ){
public:
/** add all available instantiations exhaustively, in any equivalence class
if limitInst>0, limitInst is the max # of instantiations to try */
- int addInstantiations( InstMatch& baseMatch, int instLimit = 0, bool addSplits = false );
+ int addInstantiations( InstMatch& baseMatch );
/** mkTrigger method
ie : quantifier engine;
f : forall something ....
theory_uf_candidate_generator.h \
theory_uf_candidate_generator.cpp \
inst_strategy.h \
- inst_strategy.cpp
+ inst_strategy.cpp \
+ theory_uf_model.h \
+ theory_uf_model.cpp
EXTRA_DIST = kinds
#include "theory/theory_engine.h"
#include "theory/uf/theory_uf.h"
#include "theory/uf/equality_engine.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
struct sortQuantifiersForSymbol {
QuantifiersEngine* d_qe;
- bool operator() (Node i, Node j) {
+ bool operator() (Node i, Node j) {
int nqfsi = d_qe->getNumQuantifiersForSymbol( i.getOperator() );
int nqfsj = d_qe->getNumQuantifiersForSymbol( j.getOperator() );
if( nqfsi<nqfsj ){
}
}
-int InstStrategyCheckCESolved::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyCheckCESolved::process( Node f, Theory::Effort effort, int e ){
if( e==0 ){
//calc solved if not done so already
if( d_solved.find( f )==d_solved.end() ){
//d_quantEngine->d_hasInstantiated[f] = true;
}
d_solved[f] = false;
- }
+ }
Debug("quant-uf-strategy") << "done." << std::endl;
}
return STATUS_UNKNOWN;
d_th->d_baseMatch[f].clear();
d_solved[ f ]= true;
//check if instantiation constants are solved for
- for( int j = 0; j<(int)d_quantEngine->getNumInstantiationConstants( f ); j++ ){
- Node i = d_quantEngine->getInstantiationConstant( f, j );
+ for( int j = 0; j<d_quantEngine->getTermDatabase()->getNumInstantiationConstants( f ); j++ ){
+ Node i = d_quantEngine->getTermDatabase()->getInstantiationConstant( f, j );
Node rep = d_th->getInternalRepresentative( i );
if( !rep.hasAttribute(InstConstantAttribute()) ){
d_th->d_baseMatch[f].d_map[ i ] = rep;
}
}
-int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyUserPatterns::process( Node f, Theory::Effort effort, int e ){
if( e==0 ){
return STATUS_UNFINISHED;
}else if( e==1 ){
//#endif
}
if( processTrigger ){
- //if( d_user_gen[f][i]->isMultiTrigger() )
+ //if( d_user_gen[f][i]->isMultiTrigger() )
//Notice() << " Process (user) " << (*d_user_gen[f][i]) << " for " << f << "..." << std::endl;
- int numInst = d_user_gen[f][i]->addInstantiations( d_th->d_baseMatch[f], instLimit );
- //if( d_user_gen[f][i]->isMultiTrigger() )
+ int numInst = d_user_gen[f][i]->addInstantiations( d_th->d_baseMatch[f] );
+ //if( d_user_gen[f][i]->isMultiTrigger() )
//Notice() << " Done, numInst = " << numInst << "." << std::endl;
d_th->d_statistics.d_instantiations_user_pattern += numInst;
if( d_user_gen[f][i]->isMultiTrigger() ){
}
return STATUS_UNKNOWN;
}
-
+
void InstStrategyUserPatterns::addUserPattern( Node f, Node pat ){
//add to generators
std::vector< Node > nodes;
d_quantEngine->getPhaseReqTerms( f, nodes );
//check match option
int matchOption = Options::current()->efficientEMatching ? InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH : 0;
- d_user_gen[f].push_back( Trigger::mkTrigger( d_quantEngine, f, nodes, matchOption, true, Trigger::TR_MAKE_NEW,
+ d_user_gen[f].push_back( Trigger::mkTrigger( d_quantEngine, f, nodes, matchOption, true, Trigger::TR_MAKE_NEW,
Options::current()->smartTriggers ) );
}
}
-
+
void InstStrategyAutoGenTriggers::processResetInstantiationRound( Theory::Effort effort ){
//reset triggers
for( std::map< Node, std::map< Trigger*, bool > >::iterator it = d_auto_gen_trigger.begin(); it != d_auto_gen_trigger.end(); ++it ){
}
}
-int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyAutoGenTriggers::process( Node f, Theory::Effort effort, int e ){
int peffort = f.getNumChildren()==3 ? 2 : 1;
//int peffort = f.getNumChildren()==3 ? 2 : 1;
//int peffort = 1;
#endif
}
if( processTrigger ){
- //if( tr->isMultiTrigger() )
+ //if( tr->isMultiTrigger() )
Debug("quant-uf-strategy-auto-gen-triggers") << " Process " << (*tr) << "..." << std::endl;
- int numInst = tr->addInstantiations( d_th->d_baseMatch[f], instLimit );
- //if( tr->isMultiTrigger() )
+ int numInst = tr->addInstantiations( d_th->d_baseMatch[f] );
+ //if( tr->isMultiTrigger() )
Debug("quant-uf-strategy-auto-gen-triggers") << " Done, numInst = " << numInst << "." << std::endl;
if( d_tr_strategy==Trigger::TS_MIN_TRIGGER ){
d_th->d_statistics.d_instantiations_auto_gen_min += numInst;
d_patTerms[0][f].clear();
d_patTerms[1][f].clear();
std::vector< Node > patTermsF;
- Trigger::collectPatTerms( d_quantEngine, f, d_quantEngine->getCounterexampleBody( f ), patTermsF, d_tr_strategy, true );
- Debug("auto-gen-trigger") << "Collected pat terms for " << d_quantEngine->getCounterexampleBody( f ) << std::endl;
+ Trigger::collectPatTerms( d_quantEngine, f, d_quantEngine->getTermDatabase()->getCounterexampleBody( f ), patTermsF, d_tr_strategy, true );
+ Debug("auto-gen-trigger") << "Collected pat terms for " << d_quantEngine->getTermDatabase()->getCounterexampleBody( f ) << std::endl;
Debug("auto-gen-trigger") << " ";
for( int i=0; i<(int)patTermsF.size(); i++ ){
Debug("auto-gen-trigger") << patTermsF[i] << " ";
int matchOption = Options::current()->efficientEMatching ? InstMatchGenerator::MATCH_GEN_EFFICIENT_E_MATCH : 0;
Trigger* tr = NULL;
if( d_is_single_trigger[ patTerms[0] ] ){
- tr = Trigger::mkTrigger( d_quantEngine, f, patTerms[0], matchOption, false, Trigger::TR_RETURN_NULL,
+ tr = Trigger::mkTrigger( d_quantEngine, f, patTerms[0], matchOption, false, Trigger::TR_RETURN_NULL,
Options::current()->smartTriggers );
d_single_trigger_gen[ patTerms[0] ] = true;
}else{
d_made_multi_trigger[f] = true;
}
//will possibly want to get an old trigger
- tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD,
+ tr = Trigger::mkTrigger( d_quantEngine, f, patTerms, matchOption, false, Trigger::TR_GET_OLD,
Options::current()->smartTriggers );
}
if( tr ){
if( tr->isMultiTrigger() ){
- //disable all other multi triggers
+ //disable all other multi triggers
for( std::map< Trigger*, bool >::iterator it = d_auto_gen_trigger[f].begin(); it != d_auto_gen_trigger[f].end(); ++it ){
if( it->first->isMultiTrigger() ){
d_auto_gen_trigger[f][ it->first ] = false;
success = false;
if( d_quantEngine->getNumQuantifiersForSymbol( patTerms[index].getOperator() )<=nqfs_curr ){
d_single_trigger_gen[ patTerms[index] ] = true;
- Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL,
+ Trigger* tr2 = Trigger::mkTrigger( d_quantEngine, f, patTerms[index], matchOption, false, Trigger::TR_RETURN_NULL,
Options::current()->smartTriggers );
if( tr2 ){
//Notice() << "Add additional trigger " << patTerms[index] << std::endl;
void InstStrategyAddFailSplits::processResetInstantiationRound( Theory::Effort effort ){
}
-int InstStrategyAddFailSplits::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyAddFailSplits::process( Node f, Theory::Effort effort, int e ){
if( e<4 ){
return STATUS_UNFINISHED;
}else{
- for( std::map< Node, std::map< Node, std::vector< InstMatchGenerator* > > >::iterator it = InstMatchGenerator::d_match_fails.begin();
+ for( std::map< Node, std::map< Node, std::vector< InstMatchGenerator* > > >::iterator it = InstMatchGenerator::d_match_fails.begin();
it != InstMatchGenerator::d_match_fails.end(); ++it ){
for( std::map< Node, std::vector< InstMatchGenerator* > >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
if( !it2->second.empty() ){
void InstStrategyFreeVariable::processResetInstantiationRound( Theory::Effort effort ){
}
-int InstStrategyFreeVariable::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstStrategyFreeVariable::process( Node f, Theory::Effort effort, int e ){
if( e<5 ){
return STATUS_UNFINISHED;
}else{
void calcSolved( Node f );
/** process functions */
void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
public:
- InstStrategyCheckCESolved( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
+ InstStrategyCheckCESolved( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
InstStrategy( ie ), d_th( th ){}
~InstStrategyCheckCESolved(){}
/** identify */
std::map< Node, int > d_counter;
/** process functions */
void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
public:
- InstStrategyUserPatterns( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
+ InstStrategyUserPatterns( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
InstStrategy( ie ), d_th( th ){}
~InstStrategyUserPatterns(){}
public:
private:
/** process functions */
void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
/** generate triggers */
void generateTriggers( Node f );
public:
- InstStrategyAutoGenTriggers( InstantiatorTheoryUf* th, QuantifiersEngine* ie, int tstrt, int rstrt, int rgfr = -1 ) :
+ InstStrategyAutoGenTriggers( InstantiatorTheoryUf* th, QuantifiersEngine* ie, int tstrt, int rstrt, int rgfr = -1 ) :
InstStrategy( ie ), d_th( th ), d_tr_strategy( tstrt ), d_rlv_strategy( rstrt ), d_generate_additional( false ){
setRegenerateFrequency( rgfr );
}
InstantiatorTheoryUf* d_th;
/** process functions */
void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
public:
- InstStrategyAddFailSplits( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
+ InstStrategyAddFailSplits( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
InstStrategy( ie ), d_th( th ){}
~InstStrategyAddFailSplits(){}
/** identify */
std::map< Node, bool > d_guessed;
/** process functions */
void processResetInstantiationRound( Theory::Effort effort );
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
public:
- InstStrategyFreeVariable( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
+ InstStrategyFreeVariable( InstantiatorTheoryUf* th, QuantifiersEngine* ie ) :
InstStrategy( ie ), d_th( th ){}
~InstStrategyFreeVariable(){}
/** identify */
typerule APPLY_UF ::CVC4::theory::uf::UfTypeRule
operator CARDINALITY_CONSTRAINT 2 "cardinality constraint"
-
typerule CARDINALITY_CONSTRAINT ::CVC4::theory::uf::CardinalityConstraintTypeRule
+#
+# For compact function models
+# There are three cases for FUNCTION_MODEL nodes:
+# (1) The node has two children, the first being of kind FUNCTION_CASE_SPLIT. The second child specifies a default value.
+# (2) The node has one child of kind FUNCTION_CASE_SPLIT.
+# (3) The node has one child, it's default value.
+#
+# Semantics of FUNCTION_MODEL kind-ed nodes. The value of n applied to arguments args is
+#
+# getValueFM( n, args, 0 ), where:
+#
+# Node getValueFM( n, args, argIndex )
+# if n.getKind()!=FUNCTION_MODEL
+# return n;
+# else if (1)
+# val = getValueFCS( n[0], args, argIndex );
+# if !val.isNull()
+# return val;
+# else
+# return getValueFM( n[1], args, argIndex+1 );
+# else if (2)
+# return getValueFCS( n[0], args, argIndex );
+# else if (3)
+# return getValueFM( n[0], args, argIndex+1 );
+#
+# Node getValueFCS( n, args, argIndex ) :
+# //n.getKind()==FUNCTION_CASE_SPLIT
+# //n[j].getKind()==FUNCTION_CASE for all 0<=j<n.getNumChildren()
+# if( args[argIndex]=n[i][0] for some i)
+# return getValueFM( n[i][1], args, argIndex+1 );
+# else
+# return null;
+#
+
+operator FUNCTION_MODEL 1:2 "function model"
+typerule FUNCTION_MODEL ::CVC4::theory::uf::FunctionModelTypeRule
+
+operator FUNCTION_CASE_SPLIT 1: "function case split"
+typerule FUNCTION_CASE_SPLIT ::CVC4::theory::uf::FunctionCaseSplitTypeRule
+
+operator FUNCTION_CASE 2 "function case"
+typerule FUNCTION_CASE ::CVC4::theory::uf::FunctionCaseTypeRule
+
endtheory
#include "theory/uf/theory_uf.h"
#include "theory/uf/theory_uf_instantiator.h"
#include "theory/uf/theory_uf_strong_solver.h"
+#include "theory/model.h"
using namespace std;
using namespace CVC4;
return mkAnd(assumptions);
}
+void TheoryUF::collectModelInfo( TheoryModel* m ){
+ m->assertEqualityEngine( &d_equalityEngine );
+}
+
void TheoryUF::presolve() {
// TimerStat::CodeTimer codeTimer(d_presolveTimer);
Node d_conflictNode;
/**
- * Should be called to propagate the literal. We use a node here
- * since some of the propagated literals are not kept anywhere.
+ * Should be called to propagate the literal. We use a node here
+ * since some of the propagated literals are not kept anywhere.
*/
bool propagate(TNode literal);
void preRegisterTerm(TNode term);
Node explain(TNode n);
+ void collectModelInfo( TheoryModel* m );
+
void ppStaticLearn(TNode in, NodeBuilder<>& learned);
void presolve();
#include "theory/uf/theory_uf_candidate_generator.h"
#include "theory/theory_engine.h"
#include "theory/uf/theory_uf.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
using namespace CVC4::theory;
using namespace CVC4::theory::uf;
-CandidateGeneratorTheoryUf::CandidateGeneratorTheoryUf( InstantiatorTheoryUf* ith, Node op ) :
+CandidateGeneratorTheoryUf::CandidateGeneratorTheoryUf( InstantiatorTheoryUf* ith, Node op ) :
d_op( op ), d_ith( ith ), d_term_iter( -2 ){
Assert( !d_op.isNull() );
}
}
-//CandidateGeneratorTheoryUfDisequal::CandidateGeneratorTheoryUfDisequal( InstantiatorTheoryUf* ith, Node eqc ) :
+//CandidateGeneratorTheoryUfDisequal::CandidateGeneratorTheoryUfDisequal( InstantiatorTheoryUf* ith, Node eqc ) :
// d_ith( ith ), d_eq_class( eqc ){
// d_eci = NULL;
//}
//void CandidateGeneratorTheoryUfDisequal::resetInstantiationRound(){
-//
+//
//}
////we will iterate over all terms that are disequal from eqc
//void CandidateGeneratorTheoryUfDisequal::reset( Node eqc ){
//}
-CandidateGeneratorTheoryUfLitEq::CandidateGeneratorTheoryUfLitEq( InstantiatorTheoryUf* ith, Node mpat ) :
+CandidateGeneratorTheoryUfLitEq::CandidateGeneratorTheoryUfLitEq( InstantiatorTheoryUf* ith, Node mpat ) :
d_match_pattern( mpat ), d_ith( ith ){
-
+
}
void CandidateGeneratorTheoryUfLitEq::resetInstantiationRound(){
-
+
}
void CandidateGeneratorTheoryUfLitEq::reset( Node eqc ){
d_eq = eq::EqClassesIterator( ((TheoryUF*)d_ith->getTheory())->getEqualityEngine() );
}
-CandidateGeneratorTheoryUfLitDeq::CandidateGeneratorTheoryUfLitDeq( InstantiatorTheoryUf* ith, Node mpat ) :
+CandidateGeneratorTheoryUfLitDeq::CandidateGeneratorTheoryUfLitDeq( InstantiatorTheoryUf* ith, Node mpat ) :
d_match_pattern( mpat ), d_ith( ith ){
-
+
}
void CandidateGeneratorTheoryUfLitDeq::resetInstantiationRound(){
-
+
}
void CandidateGeneratorTheoryUfLitDeq::reset( Node eqc ){
- Node false_term = ((TheoryUF*)d_ith->getTheory())->getEqualityEngine()->getRepresentative(
+ Node false_term = ((TheoryUF*)d_ith->getTheory())->getEqualityEngine()->getRepresentative(
NodeManager::currentNM()->mkConst<bool>(false) );
d_eqc_false = eq::EqClassIterator( false_term, ((TheoryUF*)d_ith->getTheory())->getEqualityEngine() );
}
#include "theory/theory_engine.h"
#include "theory/uf/theory_uf.h"
#include "theory/uf/equality_engine.h"
-//#include "theory/uf/inst_strategy_model_find.h"
+#include "theory/quantifiers/term_database.h"
using namespace std;
using namespace CVC4;
}
//set member
-void EqClassInfo::setMember( Node n, TermDb* db ){
+void EqClassInfo::setMember( Node n, quantifiers::TermDb* db ){
if( n.getKind()==APPLY_UF ){
d_funs[n.getOperator()] = true;
}
InstantiatorTheoryUf::InstantiatorTheoryUf(context::Context* c, CVC4::theory::QuantifiersEngine* qe, Theory* th) :
Instantiator( c, qe, th )
{
- qe->setEqualityQuery( new EqualityQueryInstantiatorTheoryUf( this ) );
-
- if( Options::current()->finiteModelFind ){
- //if( Options::current()->cbqi ){
- // addInstStrategy( new InstStrategyCheckCESolved( this, qe ) );
- //}
- //addInstStrategy( new InstStrategyFiniteModelFind( c, this, ((TheoryUF*)th)->getStrongSolver(), qe ) );
- qe->getTermDatabase()->setMatchingActive( false );
- }else{
+ if( !Options::current()->finiteModelFind || Options::current()->fmfInstEngine ){
if( Options::current()->cbqi ){
addInstStrategy( new InstStrategyCheckCESolved( this, qe ) );
}
i_ag->setGenerateAdditional( true );
addInstStrategy( i_ag );
//addInstStrategy( new InstStrategyAddFailSplits( this, ie ) );
- addInstStrategy( new InstStrategyFreeVariable( this, qe ) );
+ if( !Options::current()->finiteModelFind ){
+ addInstStrategy( new InstStrategyFreeVariable( this, qe ) );
+ }
//d_isup->setPriorityOver( i_ag );
//d_isup->setPriorityOver( i_agm );
//i_ag->setPriorityOver( i_agm );
d_ground_reps.clear();
}
-int InstantiatorTheoryUf::process( Node f, Theory::Effort effort, int e, int instLimit ){
+int InstantiatorTheoryUf::process( Node f, Theory::Effort effort, int e ){
Debug("quant-uf") << "UF: Try to solve (" << e << ") for " << f << "... " << std::endl;
return InstStrategy::STATUS_SAT;
}
eqc_iter++;
}
}else{
- TermDb* db = d_quantEngine->getTermDatabase();
+ quantifiers::TermDb* db = d_quantEngine->getTermDatabase();
//see if parent f exists from argument arg
if( db->d_parents.find( n )!=db->d_parents.end() ){
if( db->d_parents[n].find( f )!=db->d_parents[n].end() ){
//take all terms from the uf term db and add to candidate generator
Node op = pat.getOperator();
- TermDb* db = d_quantEngine->getTermDatabase();
+ quantifiers::TermDb* db = d_quantEngine->getTermDatabase();
for( int i=0; i<(int)db->d_op_map[op].size(); i++ ){
cg->addCandidate( db->d_op_map[op][i] );
}
namespace CVC4 {
namespace theory {
-class TermDb;
+namespace quantifiers{
+ class TermDb;
+}
namespace uf {
EqClassInfo( context::Context* c );
~EqClassInfo(){}
//set member
- void setMember( Node n, TermDb* db );
+ void setMember( Node n, quantifiers::TermDb* db );
//has function "funs"
bool hasFunction( Node op );
//has parent "pfuns"
class InstantiatorTheoryUf : public Instantiator{
friend class ::CVC4::theory::InstMatchGenerator;
- friend class ::CVC4::theory::TermDb;
+ friend class ::CVC4::theory::quantifiers::TermDb;
protected:
typedef context::CDHashMap<Node, bool, NodeHashFunction> BoolMap;
typedef context::CDHashMap<Node, int, NodeHashFunction> IntMap;
/** reset instantiation */
void processResetInstantiationRound( Theory::Effort effort );
/** calculate matches for quantifier f at effort */
- int process( Node f, Theory::Effort effort, int e, int instLimit );
+ int process( Node f, Theory::Effort effort, int e );
public:
/** statistics class */
class Statistics {
--- /dev/null
+/********************* */\r
+/*! \file theory_uf_model.cpp\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Implementation of Theory UF Model\r
+ **/\r
+\r
+#include "theory/quantifiers/model_engine.h"\r
+#include "theory/theory_engine.h"\r
+#include "theory/uf/equality_engine.h"\r
+#include "theory/uf/theory_uf.h"\r
+#include "theory/uf/theory_uf_strong_solver.h"\r
+#include "theory/uf/theory_uf_instantiator.h"\r
+#include "theory/quantifiers/first_order_model.h"\r
+#include "theory/quantifiers/term_database.h"\r
+\r
+#define RECONSIDER_FUNC_DEFAULT_VALUE\r
+#define USE_PARTIAL_DEFAULT_VALUES\r
+\r
+using namespace std;\r
+using namespace CVC4;\r
+using namespace CVC4::kind;\r
+using namespace CVC4::context;\r
+using namespace CVC4::theory;\r
+using namespace CVC4::theory::uf;\r
+\r
+//clear\r
+void UfModelTree::clear(){\r
+ d_data.clear();\r
+ d_value = Node::null();\r
+}\r
+\r
+bool UfModelTree::hasConcreteArgumentDefinition(){\r
+ if( d_data.size()>1 ){\r
+ return true;\r
+ }else if( d_data.empty() ){\r
+ return false;\r
+ }else{\r
+ Node r;\r
+ return d_data.find( r )==d_data.end();\r
+ }\r
+}\r
+\r
+//set value function\r
+void UfModelTree::setValue( TheoryModel* m, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex ){\r
+ if( d_data.empty() ){\r
+ d_value = v;\r
+ }else if( !d_value.isNull() && d_value!=v ){\r
+ d_value = Node::null();\r
+ }\r
+ if( argIndex<(int)n.getNumChildren() ){\r
+ //take r = null when argument is the model basis\r
+ Node r;\r
+ if( ground || !n[ indexOrder[argIndex] ].getAttribute(ModelBasisAttribute()) ){\r
+ r = m->getRepresentative( n[ indexOrder[argIndex] ] );\r
+ }\r
+ d_data[ r ].setValue( m, n, v, indexOrder, ground, argIndex+1 );\r
+ }\r
+}\r
+\r
+//get value function\r
+Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int& depIndex, int argIndex ){\r
+ if( !d_value.isNull() && isTotal( n.getOperator(), argIndex ) ){\r
+ //Notice() << "Constant, return " << d_value << ", depIndex = " << argIndex << std::endl;\r
+ depIndex = argIndex;\r
+ return d_value;\r
+ }else{\r
+ Node val;\r
+ int childDepIndex[2] = { argIndex, argIndex };\r
+ for( int i=0; i<2; i++ ){\r
+ //first check the argument, then check default\r
+ Node r;\r
+ if( i==0 ){\r
+ r = m->getRepresentative( n[ indexOrder[argIndex] ] );\r
+ }\r
+ std::map< Node, UfModelTree >::iterator it = d_data.find( r );\r
+ if( it!=d_data.end() ){\r
+ val = it->second.getValue( m, n, indexOrder, childDepIndex[i], argIndex+1 );\r
+ if( !val.isNull() ){\r
+ break;\r
+ }\r
+ }else{\r
+ //argument is not a defined argument: thus, it depends on this argument\r
+ childDepIndex[i] = argIndex+1;\r
+ }\r
+ }\r
+ //update depIndex\r
+ depIndex = childDepIndex[0]>childDepIndex[1] ? childDepIndex[0] : childDepIndex[1];\r
+ //Notice() << "Return " << val << ", depIndex = " << depIndex;\r
+ //Notice() << " ( " << childDepIndex[0] << ", " << childDepIndex[1] << " )" << std::endl;\r
+ return val;\r
+ }\r
+}\r
+\r
+Node UfModelTree::getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, std::vector< int >& depIndex, int argIndex ){\r
+ if( argIndex==(int)indexOrder.size() ){\r
+ return d_value;\r
+ }else{\r
+ Node val;\r
+ bool depArg = false;\r
+ //will try concrete value first, then default\r
+ for( int i=0; i<2; i++ ){\r
+ Node r;\r
+ if( i==0 ){\r
+ r = m->getRepresentative( n[ indexOrder[argIndex] ] );\r
+ }\r
+ std::map< Node, UfModelTree >::iterator it = d_data.find( r );\r
+ if( it!=d_data.end() ){\r
+ val = it->second.getValue( m, n, indexOrder, depIndex, argIndex+1 );\r
+ //we have found a value\r
+ if( !val.isNull() ){\r
+ if( i==0 ){\r
+ depArg = true;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ //it depends on this argument if we found it via concrete argument value,\r
+ // or if found by default/disequal from some concrete argument value(s).\r
+ if( depArg || hasConcreteArgumentDefinition() ){\r
+ if( std::find( depIndex.begin(), depIndex.end(), indexOrder[argIndex] )==depIndex.end() ){\r
+ depIndex.push_back( indexOrder[argIndex] );\r
+ }\r
+ }\r
+ return val;\r
+ }\r
+}\r
+\r
+Node UfModelTree::getFunctionValue(){\r
+ if( !d_data.empty() ){\r
+ Node defaultValue;\r
+ std::vector< Node > caseValues;\r
+ for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){\r
+ if( it->first.isNull() ){\r
+ defaultValue = it->second.getFunctionValue();\r
+ }else{\r
+ caseValues.push_back( NodeManager::currentNM()->mkNode( FUNCTION_CASE, it->first, it->second.getFunctionValue() ) );\r
+ }\r
+ }\r
+ if( caseValues.empty() && defaultValue.getKind()!=FUNCTION_CASE_SPLIT && defaultValue.getKind()!=FUNCTION_MODEL ){\r
+ return defaultValue;\r
+ }else{\r
+ std::vector< Node > children;\r
+ if( !caseValues.empty() ){\r
+ children.push_back( NodeManager::currentNM()->mkNode( FUNCTION_CASE_SPLIT, caseValues ) );\r
+ }\r
+ if( !defaultValue.isNull() ){\r
+ children.push_back( defaultValue );\r
+ }\r
+ return NodeManager::currentNM()->mkNode( FUNCTION_MODEL, children );\r
+ }\r
+ }else{\r
+ Assert( !d_value.isNull() );\r
+ return d_value;\r
+ }\r
+}\r
+\r
+//simplify function\r
+void UfModelTree::simplify( Node op, Node defaultVal, int argIndex ){\r
+ if( argIndex<(int)op.getType().getNumChildren()-1 ){\r
+ std::vector< Node > eraseData;\r
+ //first process the default argument\r
+ Node r;\r
+ std::map< Node, UfModelTree >::iterator it = d_data.find( r );\r
+ if( it!=d_data.end() ){\r
+ if( !defaultVal.isNull() && it->second.d_value==defaultVal ){\r
+ eraseData.push_back( r );\r
+ }else{\r
+ it->second.simplify( op, defaultVal, argIndex+1 );\r
+ if( !it->second.d_value.isNull() && it->second.isTotal( op, argIndex+1 ) ){\r
+ defaultVal = it->second.d_value;\r
+ }else{\r
+ defaultVal = Node::null();\r
+ if( it->second.isEmpty() ){\r
+ eraseData.push_back( r );\r
+ }\r
+ }\r
+ }\r
+ }\r
+ //now see if any children can be removed, and simplify the ones that cannot\r
+ for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){\r
+ if( !it->first.isNull() ){\r
+ if( !defaultVal.isNull() && it->second.d_value==defaultVal ){\r
+ eraseData.push_back( it->first );\r
+ }else{\r
+ it->second.simplify( op, defaultVal, argIndex+1 );\r
+ if( it->second.isEmpty() ){\r
+ eraseData.push_back( it->first );\r
+ }\r
+ }\r
+ }\r
+ }\r
+ for( int i=0; i<(int)eraseData.size(); i++ ){\r
+ d_data.erase( eraseData[i] );\r
+ }\r
+ }\r
+}\r
+\r
+//is total function\r
+bool UfModelTree::isTotal( Node op, int argIndex ){\r
+ if( argIndex==(int)(op.getType().getNumChildren()-1) ){\r
+ return !d_value.isNull();\r
+ }else{\r
+ Node r;\r
+ std::map< Node, UfModelTree >::iterator it = d_data.find( r );\r
+ if( it!=d_data.end() ){\r
+ return it->second.isTotal( op, argIndex+1 );\r
+ }else{\r
+ return false;\r
+ }\r
+ }\r
+}\r
+\r
+Node UfModelTree::getConstantValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int argIndex ){\r
+ return d_value;\r
+}\r
+\r
+void indent( std::ostream& out, int ind ){\r
+ for( int i=0; i<ind; i++ ){\r
+ out << " ";\r
+ }\r
+}\r
+\r
+void UfModelTree::debugPrint( std::ostream& out, TheoryModel* m, std::vector< int >& indexOrder, int ind, int arg ){\r
+ if( !d_data.empty() ){\r
+ for( std::map< Node, UfModelTree >::iterator it = d_data.begin(); it != d_data.end(); ++it ){\r
+ if( !it->first.isNull() ){\r
+ indent( out, ind );\r
+ out << "if x_" << indexOrder[arg] << " == " << it->first << std::endl;\r
+ it->second.debugPrint( out, m, indexOrder, ind+2, arg+1 );\r
+ }\r
+ }\r
+ if( d_data.find( Node::null() )!=d_data.end() ){\r
+ d_data[ Node::null() ].debugPrint( out, m, indexOrder, ind, arg+1 );\r
+ }\r
+ }else{\r
+ indent( out, ind );\r
+ out << "return ";\r
+ m->printRepresentative( out, d_value );\r
+ //out << " { ";\r
+ //for( int i=0; i<(int)d_explicit.size(); i++ ){\r
+ // out << d_explicit[i] << " ";\r
+ //}\r
+ //out << "}";\r
+ out << std::endl;\r
+ }\r
+}\r
+\r
+UfModel::UfModel( Node op, quantifiers::FirstOrderModel* m ) : d_model( m ), d_op( op ),\r
+d_model_constructed( false ){\r
+ d_tree = UfModelTreeOrdered( op );\r
+ TypeNode tn = d_op.getType();\r
+ tn = tn[(int)tn.getNumChildren()-1];\r
+ Assert( tn==NodeManager::currentNM()->booleanType() || tn.isDatatype() || uf::StrongSolverTheoryUf::isRelevantType( tn ) );\r
+ //look at ground assertions\r
+ for( size_t i=0; i<d_model->getTermDatabase()->d_op_map[ d_op ].size(); i++ ){\r
+ Node n = d_model->getTermDatabase()->d_op_map[ d_op ][i];\r
+ d_model->getTermDatabase()->computeModelBasisArgAttribute( n );\r
+ if( !n.getAttribute(NoMatchAttribute()) || n.getAttribute(ModelBasisArgAttribute())==1 ){\r
+ Node r = d_model->getRepresentative( n );\r
+ d_ground_asserts_reps.push_back( r );\r
+ d_ground_asserts.push_back( n );\r
+ }\r
+ }\r
+ //determine if it is constant\r
+ if( !d_ground_asserts.empty() ){\r
+ bool isConstant = true;\r
+ for( int i=1; i<(int)d_ground_asserts.size(); i++ ){\r
+ if( d_ground_asserts_reps[0]!=d_ground_asserts_reps[i] ){\r
+ isConstant = false;\r
+ break;\r
+ }\r
+ }\r
+ if( isConstant ){\r
+ //set constant value\r
+ Node t = d_model->getTermDatabase()->getModelBasisOpTerm( d_op );\r
+ Node r = d_ground_asserts_reps[0];\r
+ setValue( t, r, false );\r
+ setModel();\r
+ Debug("fmf-model-cons") << "Function " << d_op << " is the constant function ";\r
+ d_model->printRepresentativeDebug( "fmf-model-cons", r );\r
+ Debug("fmf-model-cons") << std::endl;\r
+ }\r
+ }\r
+}\r
+\r
+Node UfModel::getIntersection( Node n1, Node n2, bool& isGround ){\r
+ //Notice() << "Get intersection " << n1 << " " << n2 << std::endl;\r
+ isGround = true;\r
+ std::vector< Node > children;\r
+ children.push_back( n1.getOperator() );\r
+ for( int i=0; i<(int)n1.getNumChildren(); i++ ){\r
+ if( n1[i]==n2[i] ){\r
+ if( n1[i].getAttribute(ModelBasisAttribute()) ){\r
+ isGround = false;\r
+ }\r
+ children.push_back( n1[i] );\r
+ }else if( n1[i].getAttribute(ModelBasisAttribute()) ){\r
+ children.push_back( n2[i] );\r
+ }else if( n2[i].getAttribute(ModelBasisAttribute()) ){\r
+ children.push_back( n1[i] );\r
+ }else if( d_model->areEqual( n1[i], n2[i] ) ){\r
+ children.push_back( n1[i] );\r
+ }else{\r
+ return Node::null();\r
+ }\r
+ }\r
+ return NodeManager::currentNM()->mkNode( APPLY_UF, children );\r
+}\r
+\r
+void UfModel::setValue( Node n, Node v, bool ground, bool isReq ){\r
+ Assert( !n.isNull() );\r
+ Assert( !v.isNull() );\r
+ d_set_values[ isReq ? 1 : 0 ][ ground ? 1 : 0 ][n] = v;\r
+ if( optUsePartialDefaults() ){\r
+ if( !ground ){\r
+ int defSize = (int)d_defaults.size();\r
+ for( int i=0; i<defSize; i++ ){\r
+ bool isGround;\r
+ //for soundness, to allow variable order-independent function interpretations,\r
+ // we must ensure that the intersection of all default terms\r
+ // is also defined.\r
+ //for example, if we have that f( e, a ) = ..., and f( b, e ) = ...,\r
+ // then we must define f( b, a ).\r
+ Node ni = getIntersection( n, d_defaults[i], isGround );\r
+ if( !ni.isNull() ){\r
+ //if the intersection exists, and is not already defined\r
+ if( d_set_values[0][ isGround ? 1 : 0 ].find( ni )==d_set_values[0][ isGround ? 1 : 0 ].end() &&\r
+ d_set_values[1][ isGround ? 1 : 0 ].find( ni )==d_set_values[1][ isGround ? 1 : 0 ].end() ){\r
+ //use the current value\r
+ setValue( ni, v, isGround, false );\r
+ }\r
+ }\r
+ }\r
+ d_defaults.push_back( n );\r
+ }\r
+ if( isReq && d_set_values[0][ ground ? 1 : 0 ].find( n )!=d_set_values[0][ ground ? 1 : 0 ].end()){\r
+ d_set_values[0][ ground ? 1 : 0 ].erase( n );\r
+ }\r
+ }\r
+}\r
+\r
+Node UfModel::getValue( Node n, int& depIndex ){\r
+ return d_tree.getValue( d_model, n, depIndex );\r
+}\r
+\r
+Node UfModel::getValue( Node n, std::vector< int >& depIndex ){\r
+ return d_tree.getValue( d_model, n, depIndex );\r
+}\r
+\r
+Node UfModel::getConstantValue( Node n ){\r
+ if( d_model_constructed ){\r
+ return d_tree.getConstantValue( d_model, n );\r
+ }else{\r
+ return Node::null();\r
+ }\r
+}\r
+\r
+Node UfModel::getFunctionValue(){\r
+ if( d_func_value.isNull() && d_model_constructed ){\r
+ d_func_value = d_tree.getFunctionValue();\r
+ }\r
+ return d_func_value;\r
+}\r
+\r
+bool UfModel::isConstant(){\r
+ Node gn = d_model->getTermDatabase()->getModelBasisOpTerm( d_op );\r
+ Node n = getConstantValue( gn );\r
+ return !n.isNull();\r
+}\r
+\r
+bool UfModel::optUsePartialDefaults(){\r
+#ifdef USE_PARTIAL_DEFAULT_VALUES\r
+ return true;\r
+#else\r
+ return false;\r
+#endif\r
+}\r
+\r
+void UfModel::setModel(){\r
+ makeModel( d_tree );\r
+ d_model_constructed = true;\r
+ d_func_value = Node::null();\r
+\r
+ //for debugging, make sure model satisfies all ground assertions\r
+ for( size_t i=0; i<d_ground_asserts.size(); i++ ){\r
+ int depIndex;\r
+ Node n = d_tree.getValue( d_model, d_ground_asserts[i], depIndex );\r
+ if( n!=d_ground_asserts_reps[i] ){\r
+ Debug("fmf-bad") << "Bad model : " << d_ground_asserts[i] << " := ";\r
+ d_model->printRepresentativeDebug("fmf-bad", n );\r
+ Debug("fmf-bad") << " != ";\r
+ d_model->printRepresentativeDebug("fmf-bad", d_ground_asserts_reps[i] );\r
+ Debug("fmf-bad") << std::endl;\r
+ }\r
+ }\r
+}\r
+\r
+void UfModel::clearModel(){\r
+ for( int j=0; j<2; j++ ){\r
+ for( int k=0; k<2; k++ ){\r
+ d_set_values[j][k].clear();\r
+ }\r
+ }\r
+ d_tree.clear();\r
+ d_model_constructed = false;\r
+}\r
+\r
+void UfModel::makeModel( UfModelTreeOrdered& tree ){\r
+ for( int j=0; j<2; j++ ){\r
+ for( int k=0; k<2; k++ ){\r
+ for( std::map< Node, Node >::iterator it = d_set_values[j][k].begin(); it != d_set_values[j][k].end(); ++it ){\r
+ tree.setValue( d_model, it->first, it->second, k==1 );\r
+ }\r
+ }\r
+ }\r
+ tree.simplify();\r
+}\r
+\r
+void UfModel::toStream(std::ostream& out){\r
+ //out << "Function " << d_op << std::endl;\r
+ //out << " Type: " << d_op.getType() << std::endl;\r
+ //out << " Ground asserts:" << std::endl;\r
+ //for( int i=0; i<(int)d_ground_asserts.size(); i++ ){\r
+ // out << " " << d_ground_asserts[i] << " = ";\r
+ // d_model->printRepresentative( out, d_ground_asserts[i] );\r
+ // out << std::endl;\r
+ //}\r
+ //out << " Model:" << std::endl;\r
+\r
+ TypeNode t = d_op.getType();\r
+ out << d_op << "( ";\r
+ for( int i=0; i<(int)(t.getNumChildren()-1); i++ ){\r
+ out << "x_" << i << " : " << t[i];\r
+ if( i<(int)(t.getNumChildren()-2) ){\r
+ out << ", ";\r
+ }\r
+ }\r
+ out << " ) : " << t[(int)t.getNumChildren()-1] << std::endl;\r
+ if( d_tree.isEmpty() ){\r
+ out << " [undefined]" << std::endl;\r
+ }else{\r
+ d_tree.debugPrint( out, d_model, 3 );\r
+ out << std::endl;\r
+ }\r
+ //out << " Phase reqs:" << std::endl; //for( int i=0; i<2; i++ ){\r
+ // for( std::map< Node, std::vector< Node > >::iterator it = d_reqs[i].begin(); it != d_reqs[i].end(); ++it ){\r
+ // out << " " << it->first << std::endl;\r
+ // for( int j=0; j<(int)it->second.size(); j++ ){\r
+ // out << " " << it->second[j] << " -> " << (i==1) << std::endl;\r
+ // }\r
+ // }\r
+ //}\r
+ //out << std::endl;\r
+ //for( int i=0; i<2; i++ ){\r
+ // for( std::map< Node, std::map< Node, std::vector< Node > > >::iterator it = d_eq_reqs[i].begin(); it != d_eq_reqs[i].end(); ++it ){\r
+ // out << " " << "For " << it->first << ":" << std::endl;\r
+ // for( std::map< Node, std::vector< Node > >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){\r
+ // for( int j=0; j<(int)it2->second.size(); j++ ){\r
+ // out << " " << it2->first << ( i==1 ? "==" : "!=" ) << it2->second[j] << std::endl;\r
+ // }\r
+ // }\r
+ // }\r
+ //}\r
+}\r
+\r
+Node UfModel::toIte2( Node fm_node, std::vector< Node >& args, int index, Node defaultNode ){\r
+ if( fm_node.getKind()==FUNCTION_MODEL ){\r
+ if( fm_node[0].getKind()==FUNCTION_CASE_SPLIT ){\r
+ Node retNode;\r
+ Node childDefaultNode = defaultNode;\r
+ //get new default\r
+ if( fm_node.getNumChildren()==2 ){\r
+ childDefaultNode = toIte2( fm_node[1], args, index+1, defaultNode );\r
+ }\r
+ retNode = childDefaultNode;\r
+ for( int i=(int)fm_node[0].getNumChildren()-1; i>=0; i-- ){\r
+ Node childNode = toIte2( fm_node[0][1], args, index+1, childDefaultNode );\r
+ retNode = NodeManager::currentNM()->mkNode( ITE, args[index].eqNode( fm_node[0][0] ), childNode, retNode );\r
+ }\r
+ return retNode;\r
+ }else{\r
+ return toIte2( fm_node[0], args, index+1, defaultNode );\r
+ }\r
+ }else{\r
+ return fm_node;\r
+ }\r
+}\r
+\r
+\r
+void UfModelPreferenceData::setValuePreference( Node f, Node n, Node r, bool isPro ){\r
+ if( std::find( d_values.begin(), d_values.end(), r )==d_values.end() ){\r
+ d_values.push_back( r );\r
+ }\r
+ int index = isPro ? 0 : 1;\r
+ if( std::find( d_value_pro_con[index][r].begin(), d_value_pro_con[index][r].end(), f )==d_value_pro_con[index][r].end() ){\r
+ d_value_pro_con[index][r].push_back( f );\r
+ }\r
+ d_term_pro_con[index][n].push_back( f );\r
+}\r
+\r
+Node UfModelPreferenceData::getBestDefaultValue( Node defaultTerm, TheoryModel* m ){\r
+ Node defaultVal;\r
+ double maxScore = -1;\r
+ for( size_t i=0; i<d_values.size(); i++ ){\r
+ Node v = d_values[i];\r
+ double score = ( 1.0 + (double)d_value_pro_con[0][v].size() )/( 1.0 + (double)d_value_pro_con[1][v].size() );\r
+ Debug("fmf-model-cons") << " - score( ";\r
+ m->printRepresentativeDebug( "fmf-model-cons", v );\r
+ Debug("fmf-model-cons") << " ) = " << score << std::endl;\r
+ if( score>maxScore ){\r
+ defaultVal = v;\r
+ maxScore = score;\r
+ }\r
+ }\r
+#ifdef RECONSIDER_FUNC_DEFAULT_VALUE\r
+ if( maxScore<1.0 ){\r
+ //consider finding another value, if possible\r
+ Debug("fmf-model-cons-debug") << "Poor choice for default value, score = " << maxScore << std::endl;\r
+ TypeNode tn = defaultTerm.getType();\r
+ Node newDefaultVal = m->getDomainValue( tn, d_values );\r
+ if( !newDefaultVal.isNull() ){\r
+ defaultVal = newDefaultVal;\r
+ Debug("fmf-model-cons-debug") << "-> Change default value to ";\r
+ m->printRepresentativeDebug( "fmf-model-cons-debug", defaultVal );\r
+ Debug("fmf-model-cons-debug") << std::endl;\r
+ }else{\r
+ Debug("fmf-model-cons-debug") << "-> Could not find arbitrary element of type " << tn[(int)tn.getNumChildren()-1] << std::endl;\r
+ Debug("fmf-model-cons-debug") << " Excluding: ";\r
+ for( int i=0; i<(int)d_values.size(); i++ ){\r
+ Debug("fmf-model-cons-debug") << d_values[i] << " ";\r
+ }\r
+ Debug("fmf-model-cons-debug") << std::endl;\r
+ }\r
+ }\r
+#endif\r
+ //get the default term (this term must be defined non-ground in model)\r
+ Debug("fmf-model-cons") << " Choose ";\r
+ m->printRepresentativeDebug("fmf-model-cons", defaultVal );\r
+ Debug("fmf-model-cons") << " as default value (" << defaultTerm << ")" << std::endl;\r
+ Debug("fmf-model-cons") << " # quantifiers pro = " << d_value_pro_con[0][defaultVal].size() << std::endl;\r
+ Debug("fmf-model-cons") << " # quantifiers con = " << d_value_pro_con[1][defaultVal].size() << std::endl;\r
+ return defaultVal;\r
+}
\ No newline at end of file
--- /dev/null
+/********************* */\r
+/*! \file theory_uf_model.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Model for Theory UF\r
+ **/\r
+\r
+#include "cvc4_private.h"\r
+\r
+#ifndef __CVC4__THEORY_UF_MODEL_H\r
+#define __CVC4__THEORY_UF_MODEL_H\r
+\r
+#include "theory/model.h"\r
+\r
+namespace CVC4 {\r
+namespace theory {\r
+\r
+namespace quantifiers{\r
+ class FirstOrderModel;\r
+}\r
+\r
+namespace uf {\r
+\r
+class UfModelTree\r
+{\r
+public:\r
+ UfModelTree(){}\r
+ /** the data */\r
+ std::map< Node, UfModelTree > d_data;\r
+ /** the value of this tree node (if all paths lead to same value) */\r
+ Node d_value;\r
+ /** has concrete argument defintion */\r
+ bool hasConcreteArgumentDefinition();\r
+public:\r
+ //is this model tree empty?\r
+ bool isEmpty() { return d_data.empty() && d_value.isNull(); }\r
+ //clear\r
+ void clear();\r
+ /** setValue function\r
+ *\r
+ * For each argument of n with ModelBasisAttribute() set to true will be considered default arguments if ground=false\r
+ *\r
+ */\r
+ void setValue( TheoryModel* m, Node n, Node v, std::vector< int >& indexOrder, bool ground, int argIndex );\r
+ /** getValue function\r
+ *\r
+ * returns $val, the value of ground term n\r
+ * Say n is f( t_0...t_n )\r
+ * depIndex is the index for which every term of the form f( t_0 ... t_depIndex, *,... * ) is equal to $val\r
+ * for example, if g( x_0, x_1, x_2 ) := lambda x_0 x_1 x_2. if( x_1==a ) b else c,\r
+ * then g( a, a, a ) would return b with depIndex = 1\r
+ * If ground = true, we are asking whether the term n is constant (assumes that all non-model basis arguments are ground)\r
+ *\r
+ */\r
+ Node getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int& depIndex, int argIndex );\r
+ Node getValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, std::vector< int >& depIndex, int argIndex );\r
+ ///** getConstant Value function\r
+ // *\r
+ // * given term n, where n may contain model basis arguments\r
+ // * if n is constant for its entire domain, then this function returns the value of its domain\r
+ // * otherwise, it returns null\r
+ // * for example, if f( x_0, x_1 ) := if( x_0 = a ) b else if( x_1 = a ) a else b,\r
+ // * then f( a, e ) would return b, while f( e, a ) would return null\r
+ // *\r
+ // */\r
+ Node getConstantValue( TheoryModel* m, Node n, std::vector< int >& indexOrder, int argIndex );\r
+ /** getFunctionValue */\r
+ Node getFunctionValue();\r
+ /** simplify function */\r
+ void simplify( Node op, Node defaultVal, int argIndex );\r
+ // is total ?\r
+ bool isTotal( Node op, int argIndex );\r
+public:\r
+ void debugPrint( std::ostream& out, TheoryModel* m, std::vector< int >& indexOrder, int ind = 0, int arg = 0 );\r
+};\r
+\r
+class UfModelTreeOrdered\r
+{\r
+private:\r
+ Node d_op;\r
+ std::vector< int > d_index_order;\r
+ UfModelTree d_tree;\r
+public:\r
+ UfModelTreeOrdered(){}\r
+ UfModelTreeOrdered( Node op ) : d_op( op ){\r
+ TypeNode tn = d_op.getType();\r
+ for( int i=0; i<(int)(tn.getNumChildren()-1); i++ ){\r
+ d_index_order.push_back( i );\r
+ }\r
+ }\r
+ UfModelTreeOrdered( Node op, std::vector< int >& indexOrder ) : d_op( op ){\r
+ d_index_order.insert( d_index_order.end(), indexOrder.begin(), indexOrder.end() );\r
+ }\r
+ bool isEmpty() { return d_tree.isEmpty(); }\r
+ void clear() { d_tree.clear(); }\r
+ void setValue( TheoryModel* m, Node n, Node v, bool ground = true ){\r
+ d_tree.setValue( m, n, v, d_index_order, ground, 0 );\r
+ }\r
+ Node getValue( TheoryModel* m, Node n, int& depIndex ){\r
+ return d_tree.getValue( m, n, d_index_order, depIndex, 0 );\r
+ }\r
+ Node getValue( TheoryModel* m, Node n, std::vector< int >& depIndex ){\r
+ return d_tree.getValue( m, n, d_index_order, depIndex, 0 );\r
+ }\r
+ Node getConstantValue( TheoryModel* m, Node n ) {\r
+ return d_tree.getConstantValue( m, n, d_index_order, 0 );\r
+ }\r
+ Node getFunctionValue(){\r
+ return d_tree.getFunctionValue();\r
+ }\r
+ void simplify() { d_tree.simplify( d_op, Node::null(), 0 ); }\r
+ bool isTotal() { return d_tree.isTotal( d_op, 0 ); }\r
+public:\r
+ void debugPrint( std::ostream& out, TheoryModel* m, int ind = 0 ){\r
+ d_tree.debugPrint( out, m, d_index_order, ind );\r
+ }\r
+};\r
+\r
+class UfModel\r
+{\r
+private:\r
+ quantifiers::FirstOrderModel* d_model;\r
+ //the operator this model is for\r
+ Node d_op;\r
+ //is model constructed\r
+ bool d_model_constructed;\r
+ //store for set values\r
+ std::map< Node, Node > d_set_values[2][2];\r
+private:\r
+ // defaults\r
+ std::vector< Node > d_defaults;\r
+ Node getIntersection( Node n1, Node n2, bool& isGround );\r
+public:\r
+ UfModel(){}\r
+ UfModel( Node op, quantifiers::FirstOrderModel* m );\r
+ ~UfModel(){}\r
+ //ground terms for this operator\r
+ std::vector< Node > d_ground_asserts;\r
+ //the representatives they are equal to\r
+ std::vector< Node > d_ground_asserts_reps;\r
+ //data structure that stores the model\r
+ UfModelTreeOrdered d_tree;\r
+ //node equivalent of this model\r
+ Node d_func_value;\r
+public:\r
+ /** get operator */\r
+ Node getOperator() { return d_op; }\r
+ /** debug print */\r
+ void toStream( std::ostream& out );\r
+ /** set value */\r
+ void setValue( Node n, Node v, bool ground = true, bool isReq = true );\r
+ /** get value, return arguments that the value depends on */\r
+ Node getValue( Node n, int& depIndex );\r
+ Node getValue( Node n, std::vector< int >& depIndex );\r
+ /** get constant value */\r
+ Node getConstantValue( Node n );\r
+ /** get function value for this function */\r
+ Node getFunctionValue();\r
+ /** is model constructed */\r
+ bool isModelConstructed() { return d_model_constructed; }\r
+ /** is empty */\r
+ bool isEmpty() { return d_ground_asserts.empty(); }\r
+ /** is constant */\r
+ bool isConstant();\r
+ /** uses partial default values */\r
+ bool optUsePartialDefaults();\r
+public:\r
+ /** set model */\r
+ void setModel();\r
+ /** clear model */\r
+ void clearModel();\r
+ /** make model */\r
+ void makeModel( UfModelTreeOrdered& tree );\r
+public:\r
+ /** set value preference */\r
+ void setValuePreference( Node f, Node n, bool isPro );\r
+private:\r
+ //helper for to ITE function.\r
+ static Node toIte2( Node fm_node, std::vector< Node >& args, int index, Node defaultNode );\r
+public:\r
+ /** to ITE function for function model nodes */\r
+ static Node toIte( Node fm_node, std::vector< Node >& args ) { return toIte2( fm_node, args, 0, Node::null() ); }\r
+};\r
+\r
+//this class stores temporary information useful to model engine for constructing model\r
+class UfModelPreferenceData\r
+{\r
+public:\r
+ UfModelPreferenceData() : d_reconsiderModel( false ){}\r
+ virtual ~UfModelPreferenceData(){}\r
+ // preferences for default values\r
+ std::vector< Node > d_values;\r
+ std::map< Node, std::vector< Node > > d_value_pro_con[2];\r
+ std::map< Node, std::vector< Node > > d_term_pro_con[2];\r
+ bool d_reconsiderModel;\r
+ /** set value preference */\r
+ void setValuePreference( Node f, Node n, Node r, bool isPro );\r
+ /** get best default value */\r
+ Node getBestDefaultValue( Node defaultTerm, TheoryModel* m );\r
+};\r
+\r
+\r
+}\r
+}\r
+}\r
+\r
+#endif\r
#include "theory/uf/equality_engine.h"
#include "theory/uf/theory_uf_instantiator.h"
#include "theory/theory_engine.h"
+#include "theory/quantifiers/term_database.h"
-//#define USE_REGION_SAT
+//#define USE_SMART_SPLITS
+//#define ONE_SPLIT_REGION
+//#define DISABLE_QUICK_CLIQUE_CHECKS
+//#define COMBINE_REGIONS_SMALL_INTO_LARGE
using namespace std;
using namespace CVC4;
using namespace CVC4::theory;
using namespace CVC4::theory::uf;
+void StrongSolverTheoryUf::ConflictFind::Region::addRep( Node n ) {
+ setRep( n, true );
+}
+
void StrongSolverTheoryUf::ConflictFind::Region::takeNode( StrongSolverTheoryUf::ConflictFind::Region* r, Node n ){
//Debug("uf-ss") << "takeNode " << r << " " << n << std::endl;
//Debug("uf-ss") << "r : " << std::endl;
}
//remove representative
r->setRep( n, false );
- //Debug("uf-ss") << "done takeNode " << r << " " << n << std::endl;
}
void StrongSolverTheoryUf::ConflictFind::Region::combine( StrongSolverTheoryUf::ConflictFind::Region* r ){
r->d_valid = false;
}
-void StrongSolverTheoryUf::ConflictFind::Region::setRep( Node n, bool valid ){
- Assert( hasRep( n )!=valid );
- if( d_nodes.find( n )==d_nodes.end() && valid ){
- d_nodes[n] = new RegionNodeInfo( d_cf->d_th->getSatContext() );
- }
- d_nodes[n]->d_valid = valid;
- d_reps_size = d_reps_size + ( valid ? 1 : -1 );
- if( d_testClique.find( n )!=d_testClique.end() && d_testClique[n] ){
- Assert( !valid );
- d_testClique[n] = false;
- d_testCliqueSize = d_testCliqueSize - 1;
- //remove all splits involving n
- for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end(); ++it ){
- if( (*it).second ){
- if( (*it).first[0]==n || (*it).first[1]==n ){
- d_splits[ (*it).first ] = false;
- d_splitsSize = d_splitsSize - 1;
- }
- }
- }
- }
-}
-
/** setEqual */
void StrongSolverTheoryUf::ConflictFind::Region::setEqual( Node a, Node b ){
Assert( hasRep( a ) && hasRep( b ) );
}
}
+void StrongSolverTheoryUf::ConflictFind::Region::setRep( Node n, bool valid ){
+ Assert( hasRep( n )!=valid );
+ if( valid && d_nodes.find( n )==d_nodes.end() ){
+ d_nodes[n] = new RegionNodeInfo( d_cf->d_th->getSatContext() );
+ }
+ d_nodes[n]->d_valid = valid;
+ d_reps_size = d_reps_size + ( valid ? 1 : -1 );
+ //removing a member of the test clique from this region
+ if( d_testClique.find( n )!=d_testClique.end() && d_testClique[n] ){
+ Assert( !valid );
+ d_testClique[n] = false;
+ d_testCliqueSize = d_testCliqueSize - 1;
+ //remove all splits involving n
+ for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end(); ++it ){
+ if( (*it).second ){
+ if( (*it).first[0]==n || (*it).first[1]==n ){
+ d_splits[ (*it).first ] = false;
+ d_splitsSize = d_splitsSize - 1;
+ }
+ }
+ }
+ }
+}
+
bool StrongSolverTheoryUf::ConflictFind::Region::isDisequal( Node n1, Node n2, int type ){
RegionNodeInfo::DiseqList* del = d_nodes[ n1 ]->d_disequalities[type];
return del->d_disequalities.find( n2 )!=del->d_disequalities.end() && del->d_disequalities[n2];
}
+struct sortInternalDegree {
+ StrongSolverTheoryUf::ConflictFind::Region* r;
+ bool operator() (Node i,Node j) { return (r->d_nodes[i]->getNumInternalDisequalities()>r->d_nodes[j]->getNumInternalDisequalities());}
+};
+
+struct sortExternalDegree {
+ StrongSolverTheoryUf::ConflictFind::Region* r;
+ bool operator() (Node i,Node j) { return (r->d_nodes[i]->getNumExternalDisequalities()>r->d_nodes[j]->getNumExternalDisequalities());}
+};
+
bool StrongSolverTheoryUf::ConflictFind::Region::getMustCombine( int cardinality ){
- if( d_total_diseq_external>=long(cardinality) ){
+ if( Options::current()->ufssRegions && d_total_diseq_external>=long(cardinality) ){
//The number of external disequalities is greater than or equal to cardinality.
//Thus, a clique of size cardinality+1 may exist between nodes in d_regions[i] and other regions
//Check if this is actually the case: must have n nodes with outgoing degree (cardinality+1-n) for some n>0
if( outDeg>=cardinality ){
//we have 1 node of degree greater than (cardinality)
return true;
- }else if( outDeg>0 ){
+ }else if( outDeg>=1 ){
degrees.push_back( outDeg );
if( (int)degrees.size()>=cardinality ){
//we have (cardinality) nodes of degree 1
}
}
}
+ //static int gmcCount = 0;
+ //gmcCount++;
+ //if( gmcCount%100==0 ){
+ // std::cout << gmcCount << " " << cardinality << std::endl;
+ //}
+ //this should happen relatively infrequently....
std::sort( degrees.begin(), degrees.end() );
for( int i=0; i<(int)degrees.size(); i++ ){
if( degrees[i]>=cardinality+1-((int)degrees.size()-i) ){
return false;
}
-struct sortInternalDegree {
- StrongSolverTheoryUf::ConflictFind::Region* r;
- bool operator() (Node i,Node j) { return (r->d_nodes[i]->getNumInternalDisequalities()>r->d_nodes[j]->getNumInternalDisequalities());}
-};
-
-
bool StrongSolverTheoryUf::ConflictFind::Region::check( Theory::Effort level, int cardinality, std::vector< Node >& clique ){
if( d_reps_size>long(cardinality) ){
- if( d_reps_size>long(cardinality) && d_total_diseq_internal==d_reps_size*( d_reps_size - 1 ) ){
+ if( d_total_diseq_internal==d_reps_size*( d_reps_size - 1 ) ){
//quick clique check, all reps form a clique
for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
if( it->second->d_valid ){
}
}
return true;
- }else{
+ }else if( Options::current()->ufssRegions || Options::current()->ufssEagerSplits || level==Theory::EFFORT_FULL ){
//build test clique, up to size cardinality+1
if( d_testCliqueSize<=long(cardinality) ){
std::vector< Node > newClique;
for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
//if not in the test clique, add it to the set of new members
if( it->second->d_valid && ( d_testClique.find( it->first )==d_testClique.end() || !d_testClique[ it->first ] ) ){
+ //if( it->second->getNumInternalDisequalities()>cardinality || level==Theory::EFFORT_FULL ){
newClique.push_back( it->first );
+ //}
}
}
//choose remaining nodes with the highest degrees
d_testCliqueSize = d_testCliqueSize + 1;
}
}
- Assert( d_testCliqueSize==long(cardinality+1) );
- if( d_splitsSize==0 ){
+ //check if test clique has larger size than cardinality, and forms a clique
+ if( d_testCliqueSize>=long(cardinality+1) && d_splitsSize==0 ){
//test clique is a clique
for( NodeBoolMap::iterator it = d_testClique.begin(); it != d_testClique.end(); ++it ){
if( (*it).second ){
return false;
}
+void StrongSolverTheoryUf::ConflictFind::Region::getRepresentatives( std::vector< Node >& reps ){
+ for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
+ RegionNodeInfo* rni = it->second;
+ if( rni->d_valid ){
+ reps.push_back( it->first );
+ }
+ }
+}
+
+void StrongSolverTheoryUf::ConflictFind::Region::getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities ){
+ for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
+ RegionNodeInfo* rni = it->second;
+ if( rni->d_valid ){
+ RegionNodeInfo::DiseqList* del = rni->d_disequalities[0];
+ for( NodeBoolMap::iterator it2 = del->d_disequalities.begin(); it2 != del->d_disequalities.end(); ++it2 ){
+ if( (*it2).second ){
+ num_ext_disequalities[ (*it2).first ]++;
+ }
+ }
+ }
+ }
+}
+
Node StrongSolverTheoryUf::ConflictFind::Region::getBestSplit(){
+#ifndef USE_SMART_SPLITS
//take the first split you find
for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end(); ++it ){
if( (*it).second ){
}
}
return Node::null();
+#else
+ std::vector< Node > splits;
+ for( NodeBoolMap::iterator it = d_splits.begin(); it != d_splits.end(); ++it ){
+ if( (*it).second ){
+ splits.push_back( (*it).first );
+ }
+ }
+ if( splits.size()>1 ){
+ std::map< Node, std::map< Node, bool > > ops;
+ Debug("uf-ss-split") << "Choice for splits: " << std::endl;
+ double maxScore = -1;
+ int maxIndex;
+ for( int i=0; i<(int)splits.size(); i++ ){
+ Debug("uf-ss-split") << " " << splits[i] << std::endl;
+ for( int j=0; j<2; j++ ){
+ if( ops.find( splits[i][j] )==ops.end() ){
+ EqClassIterator eqc( splits[i][j], ((uf::TheoryUF*)d_cf->d_th)->getEqualityEngine() );
+ while( !eqc.isFinished() ){
+ Node n = (*eqc);
+ if( n.getKind()==APPLY_UF ){
+ ops[ splits[i][j] ][ n.getOperator() ] = true;
+ }
+ ++eqc;
+ }
+ }
+ }
+ //now, compute score
+ int common[2] = { 0, 0 };
+ for( int j=0; j<2; j++ ){
+ int j2 = j==0 ? 1 : 0;
+ for( std::map< Node, bool >::iterator it = ops[ splits[i][j] ].begin(); it != ops[ splits[i][j] ].end(); ++it ){
+ if( ops[ splits[i][j2] ].find( it->first )!=ops[ splits[i][j2] ].end() ){
+ common[0]++;
+ }else{
+ common[1]++;
+ }
+ }
+ }
+ double score = ( 1.0 + (double)common[0] )/( 1.0 + (double)common[1] );
+ if( score>maxScore ){
+ maxScore = score;
+ maxIndex = i;
+ }
+ }
+ //if( maxIndex!=0 ){
+ // std::cout << "Chose maxIndex = " << maxIndex << std::endl;
+ //}
+ return splits[maxIndex];
+ }else if( !splits.empty() ){
+ return splits[0];
+ }else{
+ return Node::null();
+ }
+#endif
}
void StrongSolverTheoryUf::ConflictFind::Region::addSplit( OutputChannel* out ){
out->requirePhase( s, true );
}
-void StrongSolverTheoryUf::ConflictFind::Region::getRepresentatives( std::vector< Node >& reps ){
- for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
- RegionNodeInfo* rni = it->second;
- if( rni->d_valid ){
- reps.push_back( it->first );
- }
- }
-}
-
bool StrongSolverTheoryUf::ConflictFind::Region::minimize( OutputChannel* out ){
if( hasSplits() ){
addSplit( out );
}
}
-void StrongSolverTheoryUf::ConflictFind::Region::getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities ){
- for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
- RegionNodeInfo* rni = it->second;
- if( rni->d_valid ){
- RegionNodeInfo::DiseqList* del = rni->d_disequalities[0];
- for( NodeBoolMap::iterator it2 = del->d_disequalities.begin(); it2 != del->d_disequalities.end(); ++it2 ){
- if( (*it2).second ){
- num_ext_disequalities[ (*it2).first ]++;
- }
- }
- }
- }
-}
-
void StrongSolverTheoryUf::ConflictFind::Region::debugPrint( const char* c, bool incClique ){
Debug( c ) << "Num reps: " << d_reps_size << std::endl;
for( std::map< Node, RegionNodeInfo* >::iterator it = d_nodes.begin(); it != d_nodes.end(); ++it ){
}
}
-void StrongSolverTheoryUf::ConflictFind::combineRegions( int ai, int bi ){
- Debug("uf-ss-region") << "uf-ss: Combine Region #" << bi << " with Region #" << ai << std::endl;
- Assert( isValid( ai ) && isValid( bi ) );
- for( std::map< Node, Region::RegionNodeInfo* >::iterator it = d_regions[bi]->d_nodes.begin(); it != d_regions[bi]->d_nodes.end(); ++it ){
- Region::RegionNodeInfo* rni = it->second;
- if( rni->d_valid ){
- d_regions_map[ it->first ] = ai;
- }
- }
- //update regions disequal DO_THIS?
- d_regions[ai]->combine( d_regions[bi] );
- d_regions[bi]->d_valid = false;
-}
-
-void StrongSolverTheoryUf::ConflictFind::moveNode( Node n, int ri ){
- Debug("uf-ss-region") << "uf-ss: Move node " << n << " to Region #" << ri << std::endl;
- Assert( isValid( d_regions_map[ n ] ) );
- Assert( isValid( ri ) );
- ////update regions disequal DO_THIS?
- //Region::RegionNodeInfo::DiseqList* del = d_regions[ d_regions_map[n] ]->d_nodes[n]->d_disequalities[0];
- //for( NodeBoolMap::iterator it = del->d_disequalities.begin(); it != del->d_disequalities.end(); ++it ){
- // if( (*it).second ){
- // }
- //}
- //move node to region ri
- d_regions[ri]->takeNode( d_regions[ d_regions_map[n] ], n );
- d_regions_map[n] = ri;
-}
-
int StrongSolverTheoryUf::ConflictFind::getNumDisequalitiesToRegion( Node n, int ri ){
int ni = d_regions_map[n];
int counter = 0;
Region::RegionNodeInfo::DiseqList* del = it->second->d_disequalities[0];
for( NodeBoolMap::iterator it2 = del->d_disequalities.begin(); it2 != del->d_disequalities.end(); ++it2 ){
if( (*it2).second ){
- //if( !isValid( d_regions_map[ (*it2).first ] ) ){
- // Debug( "uf-ss-temp" ) << "^^^" << ri << " " << d_regions_map[ (*it2).first ].get() << std::endl;
- // debugPrint( "uf-ss-temp" );
- //}
Assert( isValid( d_regions_map[ (*it2).first ] ) );
//Notice() << "Found disequality with " << (*it2).first << ", region = " << d_regions_map[ (*it2).first ] << std::endl;
regions_diseq[ d_regions_map[ (*it2).first ] ]++;
/** new node */
void StrongSolverTheoryUf::ConflictFind::newEqClass( Node n ){
if( d_regions_map.find( n )==d_regions_map.end() ){
+ if( !Options::current()->ufssRegions ){
+ //if not using regions, always add new equivalence classes to region index = 0
+ d_regions_index = 0;
+ }
d_regions_map[n] = d_regions_index;
Debug("uf-ss") << "StrongSolverTheoryUf: New Eq Class " << n << std::endl;
Debug("uf-ss-debug") << d_regions_index << " " << (int)d_regions.size() << std::endl;
if( d_regions_index<d_regions.size() ){
d_regions[ d_regions_index ]->debugPrint("uf-ss-debug",true);
d_regions[ d_regions_index ]->d_valid = true;
- //Assert( d_regions[ d_regions_index ]->d_valid );
- Assert( d_regions[ d_regions_index ]->getNumReps()==0 );
+ Assert( !Options::current()->ufssRegions || d_regions[ d_regions_index ]->getNumReps()==0 );
}else{
d_regions.push_back( new Region( this, d_th->getSatContext() ) );
}
- d_regions[ d_regions_index ]->setRep( n, true );
+ d_regions[ d_regions_index ]->addRep( n );
d_regions_index = d_regions_index + 1;
d_reps = d_reps + 1;
}
int bi = d_regions_map[b];
Debug("uf-ss") << " regions: " << ai << " " << bi << std::endl;
if( ai!=bi ){
- if( d_regions[ai]->getNumReps()==1 ){
- combineRegions( bi, ai );
- d_regions[bi]->setEqual( a, b );
- checkRegion( bi );
+ if( d_regions[ai]->getNumReps()==1 ){
+ int ri = combineRegions( bi, ai );
+ d_regions[ri]->setEqual( a, b );
+ checkRegion( ri );
}else if( d_regions[bi]->getNumReps()==1 ){
- combineRegions( ai, bi );
- d_regions[ai]->setEqual( a, b );
- checkRegion( ai );
+ int ri = combineRegions( ai, bi );
+ d_regions[ri]->setEqual( a, b );
+ checkRegion( ri );
}else{
// either move a to d_regions[bi], or b to d_regions[ai]
int aex = d_regions[ai]->d_nodes[a]->getNumInternalDisequalities() - getNumDisequalitiesToRegion( a, bi );
}
}
-bool StrongSolverTheoryUf::ConflictFind::checkRegion( int ri, bool rec ){
+void StrongSolverTheoryUf::ConflictFind::checkRegion( int ri, bool rec ){
if( isValid(ri) ){
Assert( d_cardinality>0 );
//first check if region is in conflict
if( d_regions[ri]->check( Theory::EFFORT_STANDARD, d_cardinality, clique ) ){
//explain clique
explainClique( clique, &d_th->getOutputChannel() );
- return false;
}else if( d_regions[ri]->getMustCombine( d_cardinality ) ){
- //this region must merge with another
- Debug("uf-ss-check-region") << "We must combine Region #" << ri << ". " << std::endl;
- d_regions[ri]->debugPrint("uf-ss-check-region");
////alternatively, check if we can reduce the number of external disequalities by moving single nodes
//for( std::map< Node, bool >::iterator it = d_regions[i]->d_reps.begin(); it != d_regions[i]->d_reps.end(); ++it ){
// if( it->second ){
// int inDeg = d_regions[i]->d_disequalities_size[1][ it-> first ];
- // int outDeg = d_regions[i]->d_disequalities_size[1][ it-> first ];
+ // int outDeg = d_regions[i]->d_disequalities_size[0][ it-> first ];
// if( inDeg<outDeg ){
// }
// }
//}
- //take region with maximum disequality density
- double maxScore = 0;
- int maxRegion = -1;
- std::map< int, int > regions_diseq;
- getDisequalitiesToRegions( ri, regions_diseq );
- for( std::map< int, int >::iterator it = regions_diseq.begin(); it != regions_diseq.end(); ++it ){
- Debug("uf-ss-check-region") << it->first << " : " << it->second << std::endl;
+ int riNew = forceCombineRegion( ri, true );
+ if( riNew>=0 && rec ){
+ checkRegion( riNew, rec );
}
- for( std::map< int, int >::iterator it = regions_diseq.begin(); it != regions_diseq.end(); ++it ){
- Assert( it->first!=ri );
- Assert( isValid( it->first ) );
- Assert( d_regions[ it->first ]->getNumReps()>0 );
- double tempScore = double(it->second)/double(d_regions[it->first]->getNumReps() );
- if( tempScore>maxScore ){
- maxRegion = it->first;
- maxScore = tempScore;
- }
+ }
+ }
+}
+
+int StrongSolverTheoryUf::ConflictFind::forceCombineRegion( int ri, bool useDensity ){
+ if( !useDensity ){
+ for( int i=0; i<(int)d_regions_index; i++ ){
+ if( ri!=i && d_regions[i]->d_valid ){
+ return combineRegions( ri, i );
}
- Assert( maxRegion!=-1 );
+ }
+ return -1;
+ }else{
+ //this region must merge with another
+ Debug("uf-ss-check-region") << "We must combine Region #" << ri << ". " << std::endl;
+ d_regions[ri]->debugPrint("uf-ss-check-region");
+ //take region with maximum disequality density
+ double maxScore = 0;
+ int maxRegion = -1;
+ std::map< int, int > regions_diseq;
+ getDisequalitiesToRegions( ri, regions_diseq );
+ for( std::map< int, int >::iterator it = regions_diseq.begin(); it != regions_diseq.end(); ++it ){
+ Debug("uf-ss-check-region") << it->first << " : " << it->second << std::endl;
+ }
+ for( std::map< int, int >::iterator it = regions_diseq.begin(); it != regions_diseq.end(); ++it ){
+ Assert( it->first!=ri );
+ Assert( isValid( it->first ) );
+ Assert( d_regions[ it->first ]->getNumReps()>0 );
+ double tempScore = double(it->second)/double(d_regions[it->first]->getNumReps() );
+ if( tempScore>maxScore ){
+ maxRegion = it->first;
+ maxScore = tempScore;
+ }
+ }
+ if( maxRegion!=-1 ){
Debug("uf-ss-check-region") << "Combine with region #" << maxRegion << ":" << std::endl;
d_regions[maxRegion]->debugPrint("uf-ss-check-region");
- combineRegions( ri, maxRegion );
- if( rec ){
- checkRegion( ri, rec );
- }
- //std::vector< Node > clique;
- //if( d_regions[ri]->check( Theory::EFFORT_STANDARD, cardinality, clique ) ){
- // //explain clique
- // Notice() << "found clique " << std::endl;
- //}
- return true;
+ return combineRegions( ri, maxRegion );
}
+ return -1;
}
- return false;
+}
+
+
+int StrongSolverTheoryUf::ConflictFind::combineRegions( int ai, int bi ){
+#ifdef COMBINE_REGIONS_SMALL_INTO_LARGE
+ if( d_regions[ai]->getNumReps()<d_regions[bi]->getNumReps() ){
+ return combineRegions( bi, ai );
+ }
+#endif
+ Debug("uf-ss-region") << "uf-ss: Combine Region #" << bi << " with Region #" << ai << std::endl;
+ Assert( isValid( ai ) && isValid( bi ) );
+ for( std::map< Node, Region::RegionNodeInfo* >::iterator it = d_regions[bi]->d_nodes.begin(); it != d_regions[bi]->d_nodes.end(); ++it ){
+ Region::RegionNodeInfo* rni = it->second;
+ if( rni->d_valid ){
+ d_regions_map[ it->first ] = ai;
+ }
+ }
+ //update regions disequal DO_THIS?
+ d_regions[ai]->combine( d_regions[bi] );
+ d_regions[bi]->d_valid = false;
+ return ai;
+}
+
+void StrongSolverTheoryUf::ConflictFind::moveNode( Node n, int ri ){
+ Debug("uf-ss-region") << "uf-ss: Move node " << n << " to Region #" << ri << std::endl;
+ Assert( isValid( d_regions_map[ n ] ) );
+ Assert( isValid( ri ) );
+ //move node to region ri
+ d_regions[ri]->takeNode( d_regions[ d_regions_map[n] ], n );
+ d_regions_map[n] = ri;
}
bool StrongSolverTheoryUf::ConflictFind::disambiguateTerms( OutputChannel* out ){
Debug("uf-ss-disamb") << "Disambiguate terms." << std::endl;
bool lemmaAdded = false;
//otherwise, determine ambiguous pairs of ground terms for relevant sorts
- TermDb* db = d_th->getQuantifiersEngine()->getTermDatabase();
+ quantifiers::TermDb* db = d_th->getQuantifiersEngine()->getTermDatabase();
for( std::map< Node, std::vector< Node > >::iterator it = db->d_op_map.begin(); it != db->d_op_map.end(); ++it ){
Debug("uf-ss-disamb") << "Check " << it->first << std::endl;
if( it->second.size()>1 ){
}
}
}
- if( level==Theory::EFFORT_FULL ){
+ bool addedLemma = false;
+ //do splitting on demand
+ if( level==Theory::EFFORT_FULL || Options::current()->ufssEagerSplits ){
Debug("uf-ss-debug") << "Add splits?" << std::endl;
- //see if we have any recommended splits
- bool addedLemma = false;
+ //see if we have any recommended splits from large regions
for( int i=0; i<(int)d_regions_index; i++ ){
- if( d_regions[i]->d_valid ){
+ if( d_regions[i]->d_valid && d_regions[i]->getNumReps()>d_cardinality ){
if( d_regions[i]->hasSplits() ){
d_regions[i]->addSplit( out );
addedLemma = true;
++( d_th->getStrongSolver()->d_statistics.d_split_lemmas );
+#ifdef ONE_SPLIT_REGION
+ break;
+#endif
}
}
}
+ }
+ //force continuation via term disambiguation or combination of regions
+ if( level==Theory::EFFORT_FULL ){
if( !addedLemma ){
Debug("uf-ss") << "No splits added." << std::endl;
- if( Options::current()->fmfRegionSat ){
+ if( Options::current()->ufssColoringSat ){
//otherwise, try to disambiguate individual terms
if( !disambiguateTerms( out ) ){
//no disequalities can be propagated
debugPrint("uf-ss-sat");
}
}else{
- //naive strategy. combine the first two valid regions
- int regIndex = -1;
+ bool recheck = false;
+ //naive strategy, force region combination involving the first valid region
for( int i=0; i<(int)d_regions_index; i++ ){
if( d_regions[i]->d_valid ){
- if( regIndex==-1 ){
- regIndex = i;
- }else{
- combineRegions( regIndex, i );
- check( level, out );
- }
+ forceCombineRegion( i, false );
+ recheck = true;
+ break;
}
}
+ if( recheck ){
+ check( level, out );
+ }
}
}
}
void StrongSolverTheoryUf::ConflictFind::propagate( Theory::Effort level, OutputChannel* out ){
Assert( d_cardinality>0 );
-
- //propagate the current cardinality as a decision literal
+ //propagate the current cardinality as a decision literal, if not already asserted
Node cn = d_cardinality_literal[ d_cardinality ];
Debug("uf-ss-prop-as-dec") << "Propagate as decision " << d_type << ", cardinality = " << d_cardinality << std::endl;
Assert( !cn.isNull() );
Debug("uf-ss-prop-as-dec") << "Propagate as decision " << d_cardinality_literal[ d_cardinality ];
Debug("uf-ss-prop-as-dec") << " " << d_cardinality_literal[ d_cardinality ][0].getType() << std::endl;
}
-
}
void StrongSolverTheoryUf::ConflictFind::debugPrint( const char* c ){
}
void StrongSolverTheoryUf::ConflictFind::getRepresentatives( std::vector< Node >& reps ){
- if( !Options::current()->fmfRegionSat ){
+ if( !Options::current()->ufssColoringSat ){
bool foundRegion = false;
for( int i=0; i<(int)d_regions_index; i++ ){
//should not have multiple regions at this point
}
bool StrongSolverTheoryUf::ConflictFind::minimize( OutputChannel* out ){
+ //ensure that model forms a clique:
+ // if two equivalence classes are neither equal nor disequal, add a split
int validRegionIndex = -1;
for( int i=0; i<(int)d_regions_index; i++ ){
if( d_regions[i]->d_valid ){
if( d_cardinality_lemma.find( d_cardinality )==d_cardinality_lemma.end() ){
if( d_cardinality_lemma_term.isNull() ){
std::stringstream ss;
- ss << "fmf_term_" << d_type;
+ ss << Expr::setlanguage(Options::current()->outputLanguage);
+ ss << "t_" << d_type;
d_cardinality_lemma_term = NodeManager::currentNM()->mkVar( ss.str(), d_type );
- ModelBasisAttribute mba;
- d_cardinality_lemma_term.setAttribute(mba,true);
}
Node lem = NodeManager::currentNM()->mkNode( CARDINALITY_CONSTRAINT, d_cardinality_lemma_term,
NodeManager::currentNM()->mkConst( Rational( d_cardinality ) ) );
Debug("uf-ss-solver") << "StrongSolverTheoryUf: Merge " << a << " " << b << " " << tn << std::endl;
c->merge( a, b );
}
- //else if( isRelevantType( tn ) ){
- //}
}
/** assert terms are disequal */
//Assert( d_th->d_equalityEngine.getRepresentative( b )==b );
c->assertDisequal( a, b, reason );
}
- //else if( isRelevantType( tn ) ){
- //}
}
/** assert a node */
}
}
-Node StrongSolverTheoryUf::getCardinalityTerm( TypeNode t ){
- ConflictFind* c = getConflictFind( t );
- if( c ){
- return c->getCardinalityTerm();
- }else{
- return Node::null();
- }
-}
+//Node StrongSolverTheoryUf::getCardinalityTerm( TypeNode t ){
+// ConflictFind* c = getConflictFind( t );
+// if( c ){
+// return c->getCardinalityTerm();
+// }else{
+// return Node::null();
+// }
+//}
bool StrongSolverTheoryUf::minimize(){
for( std::map< TypeNode, ConflictFind* >::iterator it = d_conf_find.begin(); it != d_conf_find.end(); ++it ){
t!=NodeManager::currentNM()->realType() &&
t!=NodeManager::currentNM()->builtinOperatorType() &&
!t.isFunction() &&
- !t.isDatatype();
+ !t.isDatatype() &&
+ !t.isArray();
}
bool StrongSolverTheoryUf::involvesRelevantType( Node n ){
namespace CVC4 {
namespace theory {
-
-struct ModelBasisAttributeId {};
-typedef expr::Attribute<ModelBasisAttributeId, bool> ModelBasisAttribute;
-
namespace uf {
class TheoryUF;
typedef context::CDHashMap<Node, int, NodeHashFunction> NodeIntMap;
typedef context::CDChunkList<Node> NodeList;
typedef context::CDList<bool> BoolList;
+ typedef context::CDList<bool> IntList;
typedef context::CDHashMap<TypeNode, bool, TypeNodeHashFunction> TypeNodeBoolMap;
public:
/** information for incremental conflict/clique finding for a particular sort */
DiseqList d_external;
public:
/** constructor */
- RegionNodeInfo( context::Context* c ) : d_internal( c ), d_external( c ), d_valid( c, true ){
+ RegionNodeInfo( context::Context* c ) :
+ d_internal( c ), d_external( c ), d_valid( c, true ){
d_disequalities[0] = &d_internal;
d_disequalities[1] = &d_external;
}
context::CDO< unsigned > d_total_diseq_external;
//total disequality size (internal)
context::CDO< unsigned > d_total_diseq_internal;
+ private:
+ /** set rep */
+ void setRep( Node n, bool valid );
public:
//constructor
Region( ConflictFind* cf, context::Context* c ) : d_cf( cf ), d_testClique( c ), d_testCliqueSize( c, 0 ),
//whether region is valid
context::CDO< bool > d_valid;
public:
- //get num reps
- int getNumReps() { return d_reps_size; }
- // has representative
- bool hasRep( Node n ) { return d_nodes.find( n )!=d_nodes.end() && d_nodes[n]->d_valid; }
+ /** add rep */
+ void addRep( Node n );
//take node from region
void takeNode( Region* r, Node n );
//merge with other region
void combine( Region* r );
- /** set rep */
- void setRep( Node n, bool valid );
/** merge */
void setEqual( Node a, Node b );
//set n1 != n2 to value 'valid', type is whether it is internal/external
void setDisequal( Node n1, Node n2, int type, bool valid );
+ public:
+ //get num reps
+ int getNumReps() { return d_reps_size; }
+ //get test clique size
+ int getTestCliqueSize() { return d_testCliqueSize; }
+ // has representative
+ bool hasRep( Node n ) { return d_nodes.find( n )!=d_nodes.end() && d_nodes[n]->d_valid; }
// is disequal
bool isDisequal( Node n1, Node n2, int type );
- public:
/** get must merge */
bool getMustCombine( int cardinality );
- /** check for cliques */
- bool check( Theory::Effort level, int cardinality, std::vector< Node >& clique );
/** has splits */
bool hasSplits() { return d_splitsSize>0; }
- /** add split */
- void addSplit( OutputChannel* out );
/** get representatives */
void getRepresentatives( std::vector< Node >& reps );
- /** minimize */
- bool minimize( OutputChannel* out );
/** get external disequalities */
void getNumExternalDisequalities( std::map< Node, int >& num_ext_disequalities );
+ public:
+ /** check for cliques */
+ bool check( Theory::Effort level, int cardinality, std::vector< Node >& clique );
+ /** add split */
+ void addSplit( OutputChannel* out );
+ /** minimize */
+ bool minimize( OutputChannel* out );
//print debug
void debugPrint( const char* c, bool incClique = false );
};
/** whether two terms are ambiguous (indexed by equalities) */
NodeBoolMap d_term_amb;
private:
- /** merge regions */
- void combineRegions( int ai, int bi );
- /** move node n to region ri */
- void moveNode( Node n, int ri );
/** get number of disequalities from node n to region ri */
int getNumDisequalitiesToRegion( Node n, int ri );
/** get number of disequalities from Region r to other regions */
void getDisequalitiesToRegions( int ri, std::map< int, int >& regions_diseq );
- /** check if we need to combine region ri */
- bool checkRegion( int ri, bool rec = true );
/** explain clique */
void explainClique( std::vector< Node >& clique, OutputChannel* out );
/** is valid */
bool isValid( int ri ) { return ri>=0 && ri<(int)d_regions_index && d_regions[ ri ]->d_valid; }
/** check ambiguous terms */
bool disambiguateTerms( OutputChannel* out );
+ private:
+ /** check if we need to combine region ri */
+ void checkRegion( int ri, bool rec = true );
+ /** force combine region */
+ int forceCombineRegion( int ri, bool useDensity = true );
+ /** merge regions */
+ int combineRegions( int ai, int bi );
+ /** move node n to region ri */
+ void moveNode( Node n, int ri );
private:
/** cardinality operating with */
context::CDO< int > d_cardinality;
/** get representatives */
void getRepresentatives( std::vector< Node >& reps );
/** get model basis term */
- Node getCardinalityTerm() { return d_cardinality_lemma_term; }
+ //Node getCardinalityTerm() { return d_cardinality_lemma_term; }
/** minimize */
bool minimize( OutputChannel* out );
/** get cardinality lemma */
/** get representatives */
void getRepresentatives( TypeNode t, std::vector< Node >& reps );
/** get cardinality term */
- Node getCardinalityTerm( TypeNode t );
+ //Node getCardinalityTerm( TypeNode t );
/** minimize */
bool minimize();
}
return nodeManager->booleanType();
}
-};/* class UfTypeRule */
+};/* class CardinalityConstraintTypeRule */
+
+class FunctionModelTypeRule {
+public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw(TypeCheckingExceptionPrivate) {
+ TypeNode tn = n[0].getType(check);
+ if( check ){
+ if( n.getNumChildren()==2 ){
+ if( n[0].getKind()!=kind::FUNCTION_CASE_SPLIT ){
+ throw TypeCheckingExceptionPrivate(n, "improper function model representation : first child must be case split");
+ }
+ TypeNode tn2 = n[1].getType(check);
+ if( tn!=tn2 ){
+ std::stringstream ss;
+ ss << "function model has inconsistent return types : " << tn << " " << tn2;
+ throw TypeCheckingExceptionPrivate(n, ss.str());
+ }
+ }
+ }
+ return tn;
+ }
+};/* class FunctionModelTypeRule */
+
+class FunctionCaseSplitTypeRule {
+public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw(TypeCheckingExceptionPrivate) {
+ TypeNode retType = n[0][1].getType(check);
+ if( check ){
+ TypeNode argType = n[0][0].getType(check);
+ for( size_t i=0; i<n.getNumChildren(); i++ ){
+ TypeNode argType2 = n[i][0].getType(check);
+ if( argType!=argType2 ){
+ std::stringstream ss;
+ ss << "function case split has inconsistent argument types : " << argType << " " << argType2;
+ throw TypeCheckingExceptionPrivate(n, ss.str());
+ }
+ TypeNode retType2 = n[i][1].getType(check);
+ if( retType!=retType2 ){
+ std::stringstream ss;
+ ss << "function case split has inconsistent return types : " << retType << " " << retType2;
+ throw TypeCheckingExceptionPrivate(n, ss.str());
+ }
+ }
+ }
+ return retType;
+ }
+};/* class FunctionCaseSplitTypeRule */
+
+
+class FunctionCaseTypeRule {
+public:
+ inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check)
+ throw(TypeCheckingExceptionPrivate) {
+ TypeNode retType = n[1].getType(check);
+ if( check ){
+ TypeNode argType = n[0].getType(check);
+ }
+ return retType;
+ }
+};/* class FunctionCaseTypeRule */
+
}/* CVC4::theory::uf namespace */
}/* CVC4::theory namespace */
}
}
-
-Node Valuation::getValue(TNode n) const {
- return d_engine->getValue(n);
-}
-
bool Valuation::isSatLiteral(TNode n) const {
return d_engine->getPropEngine()->isSatLiteral(n);
}
d_engine(engine) {
}
- Node getValue(TNode n) const;
-
/*
* Return true if n has an associated SAT literal
*/
ite_removal.h \
ite_removal.cpp \
node_visitor.h \
- index.h
+ index.h \
+ model.h \
+ model.cpp
libutil_la_LIBADD = \
@builddir@/libutilcudd.la
std::string s = ss.str();
CVC4dumpstream(getStream(), d_commands)
<< CommentCommand(s + " is " + comment)
- << DeclareFunctionCommand(s, e.getType());
+ << DeclareFunctionCommand(s, e, e.getType());
}
}
--- /dev/null
+/********************* */\r
+/*! \file model.cpp\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief implementation of Model class\r
+ **/
\ No newline at end of file
--- /dev/null
+/********************* */\r
+/*! \file model.h\r
+ ** \verbatim\r
+ ** Original author: ajreynol\r
+ ** Major contributors: none\r
+ ** Minor contributors (to current version): none\r
+ ** This file is part of the CVC4 prototype.\r
+ ** Copyright (c) 2009, 2010, 2011 The Analysis of Computer Systems Group (ACSys)\r
+ ** Courant Institute of Mathematical Sciences\r
+ ** New York University\r
+ ** See the file COPYING in the top-level source directory for licensing\r
+ ** information.\endverbatim\r
+ **\r
+ ** \brief Model class\r
+ **/\r
+\r
+#include "cvc4_public.h"\r
+\r
+#ifndef __CVC4__MODEL_H\r
+#define __CVC4__MODEL_H\r
+\r
+#include <iostream>\r
+\r
+namespace CVC4 {\r
+\r
+class Model\r
+{\r
+public:\r
+ virtual void toStream(std::ostream& out) = 0;\r
+};/* class Model */\r
+\r
+class ModelBuilder\r
+{\r
+public:\r
+ ModelBuilder(){}\r
+ virtual ~ModelBuilder(){}\r
+ virtual void buildModel( Model* m ) = 0;\r
+};/* class ModelBuilder */\r
+\r
+}/* CVC4 namespace */\r
+\r
+#endif /* __CVC4__MODEL_H */\r
instWhenMode(INST_WHEN_FULL_LAST_CALL),
eagerInstQuant(false),
finiteModelFind(false),
- fmfRegionSat(false),
+ ufssEagerSplits(false),
+ ufssRegions(true),
+ ufssColoringSat(false),
fmfModelBasedInst(true),
+ fmfInstGen(true),
+ fmfOneInstPerRound(false),
+ fmfInstEngine(false),
+ fmfRelevantDomain(false),
efficientEMatching(false),
literalMatchMode(LITERAL_MATCH_NONE),
cbqi(false),
cbqiSetByUser(false),
userPatternsQuant(true),
flipDecision(false),
+ printInstEngine(false),
+ printModelEngine(false),
lemmaOutputChannel(NULL),
lemmaInputChannel(NULL),
threads(2),// default should be 1 probably, but say 2 for now
--enable-symmetry-breaker turns on UF symmetry breaker (Deharbe et al.,\n\
CADE 2011) [on by default only for QF_UF]\n\
--disable-symmetry-breaker turns off UF symmetry breaker\n\
+ QUANTIFIERS:\n\
--disable-miniscope-quant disable miniscope quantifiers\n\
--disable-miniscope-quant-fv disable miniscope quantifiers for ground subformulas\n\
--disable-prenex-quant disable prenexing of quantified formulas\n\
--cnf-quant apply CNF conversion to quantified formulas\n\
--pre-skolem-quant apply skolemization eagerly to bodies of quantified formulas\n\
--disable-smart-triggers disable smart triggers\n\
- --register-quant-body-terms consider terms within bodies of quantified formulas for matching\n\
+ --register-quant-body-terms consider ground terms within bodies of quantified formulas for matching\n\
--inst-when=MODE when to apply instantiation\n\
--eager-inst-quant apply quantifier instantiation eagerly\n\
- --finite-model-find use finite model finding heuristic for quantifier instantiation\n\
- --use-fmf-region-sat use region-based SAT heuristic for finite model finding\n\
- --disable-fmf-model-inst disable model-based instantiation for finite model finding\n\
--efficient-e-matching use efficient E-matching\n\
--literal-matching=MODE choose literal matching mode\n\
--enable-cbqi turns on counterexample-based quantifier instantiation [off by default]\n\
--disable-cbqi turns off counterexample-based quantifier instantiation\n\
--ignore-user-patterns ignore user-provided patterns for quantifier instantiation\n\
--enable-flip-decision turns on flip decision heuristic\n\
+ FINITE_MODEL_FINDING:\n\
+ --finite-model-find use finite model finding heuristic for quantifier instantiation\n\
+ --disable-uf-ss-regions disable region-based method for discovering cliques and splits in uf strong solver\n\
+ --uf-ss-eager-split add splits eagerly for uf strong solver\n\
+ --uf-ss-coloring-sat use coloring-based SAT heuristic for uf strong solver\n\
+ --disable-fmf-mbqi disable model-based quantifier instantiation for finite model finding\n\
+ --disable-fmf-inst-gen disable Inst-Gen instantiation techniques for finite model finding\n\
+ --fmf-one-inst-per-round only add one instantiation per quantifier per round for fmf\n\
+ --fmf-inst-engine use instantiation engine in conjunction with finite model finding\n\
+ --fmf-relevant-domain use relevant domain computation, similar to complete instantiation (Ge, deMoura 09)\n\
+ OTHER:\n\
--disable-dio-solver turns off Linear Diophantine Equation solver (Griggio, JSAT 2012)\n\
--disable-arith-rewrite-equalities turns off the preprocessing rewrite turning equalities into a conjunction of inequalities.\n\
--threads=N sets the number of solver threads\n\
+ near leaves (don't expect it to work well) [Unimplemented]\n\
";
+static const string instWhenHelp = "\
+Modes currently supported by the --inst-when option:\n\
+\n\
+full\n\
++ Run instantiation round at full effort, before theory combination.\n\
+\n\
+full-last-call (default)\n\
++ Alternate running instantiation rounds at full effort and last\n\
+ call. In other words, interleave instantiation and theory combination.\n\
+\n\
+last-call\n\
++ Run instantiation at last call effort, after theory combination.\n\
+\n\
+";
+
+static const string literalMatchHelp = "\
+Literal match modes currently supported by the --literal-match option:\n\
+\n\
+none (default)\n\
++ Do not use literal matching.\n\
+\n\
+predicate\n\
++ Consider the phase requirements of predicate literals when applying heuristic\n\
+ quantifier instantiation. For example, the trigger P( x ) in the quantified \n\
+ formula forall( x ). ( P( x ) V ~Q( x ) ) will only be matched with ground\n\
+ terms P( t ) where P( t ) is in the equivalence class of false, and likewise\n\
+ Q( x ) with Q( s ) where Q( s ) is in the equivalence class of true.\n\
+\n\
+";
+
static const string dumpHelp = "\
Dump modes currently supported by the --dump option:\n\
\n\
INST_WHEN,
EAGER_INST_QUANT,
FINITE_MODEL_FIND,
- FMF_REGION_SAT,
+ DISABLE_UF_SS_REGIONS,
+ UF_SS_EAGER_SPLIT,
+ UF_SS_COLORING_SAT,
DISABLE_FMF_MODEL_BASED_INST,
+ DISABLE_FMF_INST_GEN,
+ FMF_ONE_INST_PER_ROUND,
+ FMF_INST_ENGINE,
+ FMF_RELEVANT_DOMAIN,
EFFICIENT_E_MATCHING,
LITERAL_MATCHING,
ENABLE_CBQI,
DISABLE_CBQI,
IGNORE_USER_PATTERNS,
ENABLE_FLIP_DECISION,
+ PRINT_MODEL_ENGINE,
+ PRINT_INST_ENGINE,
PARALLEL_THREADS,
PARALLEL_SEPARATE_OUTPUT,
PORTFOLIO_FILTER_LENGTH,
{ "inst-when", required_argument, NULL, INST_WHEN },
{ "eager-inst-quant", no_argument, NULL, EAGER_INST_QUANT },
{ "finite-model-find", no_argument, NULL, FINITE_MODEL_FIND },
- { "use-fmf-region-sat", no_argument, NULL, FMF_REGION_SAT },
- { "disable-fmf-model-inst", no_argument, NULL, DISABLE_FMF_MODEL_BASED_INST },
+ { "disable-uf-ss-regions", no_argument, NULL, DISABLE_UF_SS_REGIONS },
+ { "uf-ss-eager-split", no_argument, NULL, UF_SS_EAGER_SPLIT },
+ { "uf-ss-coloring-sat", no_argument, NULL, UF_SS_COLORING_SAT },
+ { "disable-fmf-mbqi", no_argument, NULL, DISABLE_FMF_MODEL_BASED_INST },
+ { "disable-fmf-inst-gen", no_argument, NULL, DISABLE_FMF_INST_GEN },
+ { "fmf-one-inst-per-round", no_argument, NULL, FMF_ONE_INST_PER_ROUND },
+ { "fmf-inst-engine", no_argument, NULL, FMF_INST_ENGINE },
+ { "fmf-relevant-domain", no_argument, NULL, FMF_RELEVANT_DOMAIN },
{ "efficient-e-matching", no_argument, NULL, EFFICIENT_E_MATCHING },
{ "literal-matching", required_argument, NULL, LITERAL_MATCHING },
{ "enable-cbqi", no_argument, NULL, ENABLE_CBQI },
{ "disable-cbqi", no_argument, NULL, DISABLE_CBQI },
{ "ignore-user-patterns", no_argument, NULL, IGNORE_USER_PATTERNS },
{ "enable-flip-decision", no_argument, NULL, ENABLE_FLIP_DECISION },
+ { "print-m-e", no_argument, NULL, PRINT_MODEL_ENGINE },
+ { "print-i-e", no_argument, NULL, PRINT_INST_ENGINE },
{ "threads", required_argument, NULL, PARALLEL_THREADS },
{ "separate-output", no_argument, NULL, PARALLEL_SEPARATE_OUTPUT },
{ "filter-lemma-length", required_argument, NULL, PORTFOLIO_FILTER_LENGTH },
if(i == 0) {
Warning() << "Decision budget is 0. Consider using internal decision heuristic and "
<< std::endl << " removing this option." << std::endl;
-
+
}
decisionOptions.maxRelTimeAsPermille = (unsigned short)i;
}
} else if(!strcmp(optarg, "last-call")) {
instWhenMode = INST_WHEN_LAST_CALL;
} else if(!strcmp(optarg, "help")) {
- //puts(instWhenHelp.c_str());
+ puts(instWhenHelp.c_str());
exit(1);
} else {
throw OptionException(string("unknown option for --inst-when: `") +
case FINITE_MODEL_FIND:
finiteModelFind = true;
break;
- case FMF_REGION_SAT:
- fmfRegionSat = true;
+ case DISABLE_UF_SS_REGIONS:
+ ufssRegions = false;
+ break;
+ case UF_SS_EAGER_SPLIT:
+ ufssEagerSplits = true;
+ break;
+ case UF_SS_COLORING_SAT:
+ ufssColoringSat = true;
break;
case DISABLE_FMF_MODEL_BASED_INST:
fmfModelBasedInst = false;
break;
+ case DISABLE_FMF_INST_GEN:
+ fmfInstGen = false;
+ break;
+ case FMF_ONE_INST_PER_ROUND:
+ fmfOneInstPerRound = true;
+ break;
+ case FMF_INST_ENGINE:
+ fmfInstEngine = true;
+ break;
+ case FMF_RELEVANT_DOMAIN:
+ fmfRelevantDomain = true;
+ break;
case EFFICIENT_E_MATCHING:
efficientEMatching = true;
break;
} else if(!strcmp(optarg, "equality")) {
literalMatchMode = LITERAL_MATCH_EQUALITY;
} else if(!strcmp(optarg, "help")) {
- //puts(literalMatchHelp.c_str());
+ puts(literalMatchHelp.c_str());
exit(1);
} else {
throw OptionException(string("unknown option for --literal-matching: `") +
case ENABLE_FLIP_DECISION:
flipDecision = true;
break;
+ case PRINT_MODEL_ENGINE:
+ printModelEngine = true;
+ break;
+ case PRINT_INST_ENGINE:
+ printInstEngine = true;
+ break;
case TIME_LIMIT:
{
int i = atoi(optarg);
DecisionMode decisionMode;
/** Whether the user set the decision strategy */
bool decisionModeSetByUser;
- /**
+ /**
* Extra settings for decision stuff, varies by strategy enabled
* - With DECISION_STRATEGY_RELEVANCY
* > Least significant bit: true if one should only decide on leaves
bool finiteModelFind;
/**
- * Whether to use region-based SAT for finite model finding
+ * Whether to use eager splitting on demand for finite model finding
+ */
+ bool ufssEagerSplits;
+
+ /**
+ * Whether to use region-based approach for finite model finding
+ */
+ bool ufssRegions;
+
+ /**
+ * Whether to use coloring-based methods for determining whether a model of
+ * currently cardinality exists.
*/
- bool fmfRegionSat;
+ bool ufssColoringSat;
/**
* Whether to use model-based exhaustive instantiation for finite model finding
*/
bool fmfModelBasedInst;
+ /**
+ * Whether to use Inst-Gen techniques for finite model finding
+ */
+ bool fmfInstGen;
+
+ /*
+ * Whether to only add only instantiation per quantifier per round for finite model finding
+ */
+ bool fmfOneInstPerRound;
+
+ /*
+ * Whether to use instantiation engine in conjunction with finite model finding
+ */
+ bool fmfInstEngine;
+
+ /*
+ * Whether to compute relevant domains, in the manner of Complete Instantiation for Quantified Formulas [Ge, deMoura 09]
+ */
+ bool fmfRelevantDomain;
+
/**
* Whether to use efficient E-matching
*/
*/
bool flipDecision;
+ /**
+ * print details for instantiation/model engine
+ */
+ bool printInstEngine;
+ bool printModelEngine;
+
/** The output channel to receive notfication events for new lemmas */
LemmaOutputChannel* lemmaOutputChannel;
LemmaInputChannel* lemmaInputChannel;