}
if( e == EFFORT_FULL ) {
+ //check for cycles
+ checkCycles();
+ if( d_conflict ){
+ return;
+ }
+ //check for splits
Debug("datatypes-split") << "Check for splits " << e << endl;
bool addedFact = false;
do {
}
}
}
+ /*
if( !needSplit && mustSpecifyAssignment() ){
- // &&
//for the sake of termination, we must choose the constructor of a ground term
//NEED GUARENTEE: groundTerm should not contain any subterms of the same type
- //** TODO: this is probably not good enough, actually need fair enumeration strategy
- /*
+ // TODO: this is probably not good enough, actually need fair enumeration strategy
Node groundTerm = n.getType().mkGroundTerm();
int index = Datatype::indexOf( groundTerm.getOperator().toExpr() );
if( pcons[index] ){
consIndex = index;
}
needSplit = true;
- */
}
+ */
if( needSplit && consIndex!=-1 ) {
Node test = NodeManager::currentNM()->mkNode( APPLY_TESTER, Node::fromExpr( dt[consIndex].getTester() ), n );
Trace("dt-split") << "*************Split for possible constructor " << dt[consIndex] << " for " << n << endl;
Debug("datatypes-explain") << "Explain " << literal << std::endl;
bool polarity = literal.getKind() != kind::NOT;
TNode atom = polarity ? literal : literal[0];
+ std::vector<TNode> tassumptions;
if (atom.getKind() == kind::EQUAL || atom.getKind() == kind::IFF) {
- d_equalityEngine.explainEquality(atom[0], atom[1], polarity, assumptions);
+ d_equalityEngine.explainEquality(atom[0], atom[1], polarity, tassumptions);
} else {
- d_equalityEngine.explainPredicate(atom, polarity, assumptions);
+ d_equalityEngine.explainPredicate(atom, polarity, tassumptions);
+ }
+ for( unsigned i=0; i<tassumptions.size(); i++ ){
+ if( std::find( assumptions.begin(), assumptions.end(), tassumptions[i] )==assumptions.end() ){
+ assumptions.push_back( tassumptions[i] );
+ }
}
}
} else {
d_conflictNode = explain( a.eqNode(b) );
}
- Debug("datatypes-conflict") << "CONFLICT: Eq engine conflict : " << d_conflictNode << std::endl;
+ Trace("dt-conflict") << "CONFLICT: Eq engine conflict : " << d_conflictNode << std::endl;
d_out->conflict( d_conflictNode );
d_conflict = true;
}
if( cons1.getOperator()!=cons2.getOperator() ){
//check for clash
d_conflictNode = explain( cons1.eqNode( cons2 ) );
- Debug("datatypes-conflict") << "CONFLICT: Clash conflict : " << d_conflictNode << std::endl;
+ Trace("dt-conflict") << "CONFLICT: Clash conflict : " << d_conflictNode << std::endl;
d_out->conflict( d_conflictNode );
d_conflict = true;
return;
explain( *i, assumptions );
explain( cons2.eqNode( (*i)[0][0] ), assumptions );
d_conflictNode = NodeManager::currentNM()->mkNode( AND, assumptions );
- Debug("datatypes-conflict") << "CONFLICT: Tester merge eq conflict : " << d_conflictNode << std::endl;
- Debug("datatypes-conflict-temp") << "CONFLICT: Tester merge eq conflict : " << d_conflictNode << std::endl;
+ Trace("dt-conflict") << "CONFLICT: Tester merge eq conflict : " << d_conflictNode << std::endl;
d_out->conflict( d_conflictNode );
d_conflict = true;
return;
newRep = trep2;
}
bool result = d_cycle_check.addEdgeNode( oldRep, newRep );
- d_hasSeenCycle.set( d_hasSeenCycle.get() || result );
- Debug("datatypes-cycles") << "DtCyc: Equal " << oldRep << " -> " << newRep << " " << d_hasSeenCycle.get() << endl;
- if( d_hasSeenCycle.get() ){
+ //d_hasSeenCycle.set( d_hasSeenCycle.get() || result );
+ Debug("datatypes-cycles") << "DtCyc: Equal " << oldRep << " -> " << newRep << " " << result << " " << d_hasSeenCycle.get() << endl;
+ if( result ){
checkCycles();
if( d_conflict ){
+ Debug("datatypes-cycles-find") << "Cycle found." << std::endl;
return;
+ }else{
+ Debug("datatypes-cycles-find") << "WARNING : no cycle found." << std::endl;
+ d_cycle_check.debugPrint();
}
}
}
explain( t, assumptions );
explain( eqc->d_constructor.get().eqNode( tt[0] ), assumptions );
d_conflictNode = NodeManager::currentNM()->mkNode( AND, assumptions );
- Debug("datatypes-conflict") << "CONFLICT: Tester eq conflict : " << d_conflictNode << std::endl;
+ Trace("dt-conflict") << "CONFLICT: Tester eq conflict : " << d_conflictNode << std::endl;
d_out->conflict( d_conflictNode );
return;
}else{
explain( t, assumptions );
explain( jt[0].eqNode( tt[0] ), assumptions );
d_conflictNode = NodeManager::currentNM()->mkNode( AND, assumptions );
- Debug("datatypes-conflict") << "CONFLICT: Tester conflict : " << d_conflictNode << std::endl;
+ Trace("dt-conflict") << "CONFLICT: Tester conflict : " << d_conflictNode << std::endl;
d_out->conflict( d_conflictNode );
}
}
if( n.getKind() == APPLY_CONSTRUCTOR ){
//we must take into account subterm relation when checking for cycles
for( int i=0; i<(int)n.getNumChildren(); i++ ) {
- Debug("datatypes-cycles") << "DtCyc: Subterm " << n << " -> " << n[i] << endl;
bool result = d_cycle_check.addEdgeNode( n, n[i] );
+ Debug("datatypes-cycles") << "DtCyc: Subterm " << n << " -> " << n[i] << " " << result << endl;
+ if( result && !d_hasSeenCycle.get() ){
+ Debug("datatypes-cycles") << "FOUND CYCLE" << std::endl;
+ }
d_hasSeenCycle.set( d_hasSeenCycle.get() || result );
}
}else if( n.getKind() == APPLY_SELECTOR ){
Trace("dt-terms") << "Created term : " << n << std::endl;
//see if it is rewritten to be something different
Node rn = Rewriter::rewrite( n );
- if( rn!=n ){
+ if( rn!=n && !areEqual( rn, n ) ){
Node eq = n.getType().isBoolean() ? rn.iffNode( n ) : rn.eqNode( n );
d_pending.push_back( eq );
d_pending_exp[ eq ] = NodeManager::currentNM()->mkConst( true );
int index = getLabelIndex( eqc, n );
const Datatype& dt = ((DatatypeType)(tt.getType()).toType()).getDatatype();
//must be finite or have a selector
- //if( eqc->d_selectors || dt[ index ].isFinite() || mustSpecifyAssignment() ){
- //instantiate this equivalence class
- eqc->d_inst = true;
- Node tt_cons = getInstantiateCons( tt, dt, index );
- Node eq;
- if( tt!=tt_cons ){
- eq = tt.eqNode( tt_cons );
- Debug("datatypes-inst") << "DtInstantiate : " << eqc << " " << eq << std::endl;
- d_pending.push_back( eq );
- d_pending_exp[ eq ] = exp;
- Trace("datatypes-infer") << "DtInfer : " << eq << " by " << exp << std::endl;
- //eqc->d_inst.set( eq );
- d_infer.push_back( eq );
- d_infer_exp.push_back( exp );
- }
+ //if( eqc->d_selectors || dt[ index ].isFinite() ){ // || mustSpecifyAssignment()
+ //instantiate this equivalence class
+ eqc->d_inst = true;
+ Node tt_cons = getInstantiateCons( tt, dt, index );
+ Node eq;
+ if( tt!=tt_cons ){
+ eq = tt.eqNode( tt_cons );
+ Debug("datatypes-inst") << "DtInstantiate : " << eqc << " " << eq << std::endl;
+ d_pending.push_back( eq );
+ d_pending_exp[ eq ] = exp;
+ Trace("datatypes-infer") << "DtInfer : " << eq << " by " << exp << std::endl;
+ //eqc->d_inst.set( eq );
+ d_infer.push_back( eq );
+ d_infer_exp.push_back( exp );
+ }
//}
//else{
// Debug("datatypes-inst") << "Do not instantiate" << std::endl;
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &d_equalityEngine );
while( !eqcs_i.isFinished() ){
Node eqc = (*eqcs_i);
- map< Node, bool > visited;
- std::vector< TNode > expl;
- if( searchForCycle( eqc, eqc, visited, expl ) ) {
- Assert( expl.size()>0 );
- if( expl.size() == 1 ){
- d_conflictNode = expl[ 0 ];
- }else{
- d_conflictNode = NodeManager::currentNM()->mkNode( AND, expl );
+ if( eqc.getType().isDatatype() ) {
+ map< Node, bool > visited;
+ std::vector< TNode > expl;
+ Node cn = searchForCycle( eqc, eqc, visited, expl );
+ //if we discovered a different cycle while searching this one
+ if( !cn.isNull() && cn!=eqc ){
+ visited.clear();
+ expl.clear();
+ Node prev = cn;
+ cn = searchForCycle( cn, cn, visited, expl );
+ Assert( prev==cn );
+ }
+
+ if( !cn.isNull() ) {
+ Assert( expl.size()>0 );
+ if( expl.size() == 1 ){
+ d_conflictNode = expl[ 0 ];
+ }else{
+ d_conflictNode = NodeManager::currentNM()->mkNode( AND, expl );
+ }
+ Trace("dt-conflict") << "CONFLICT: Cycle conflict : " << d_conflictNode << std::endl;
+ d_out->conflict( d_conflictNode );
+ d_conflict = true;
+ return;
}
- Debug("datatypes-conflict") << "CONFLICT: Cycle conflict : " << d_conflictNode << std::endl;
- d_out->conflict( d_conflictNode );
- d_conflict = true;
- return;
}
++eqcs_i;
}
}
//postcondition: if cycle detected, explanation is why n is a subterm of on
-bool TheoryDatatypes::searchForCycle( Node n, Node on,
+Node TheoryDatatypes::searchForCycle( Node n, Node on,
map< Node, bool >& visited,
std::vector< TNode >& explanation, bool firstTime ) {
Debug("datatypes-cycle-check") << "Search for cycle " << n << " " << on << endl;
if( nn==on ){
Node lit = NodeManager::currentNM()->mkNode( EQUAL, n, nn );
explain( lit, explanation );
- return true;
+ return on;
}
}else{
nn = n;
}
if( visited.find( nn ) == visited.end() ) {
visited[nn] = true;
- EqcInfo* eqc = getOrMakeEqcInfo( nn );
+ EqcInfo* eqc = getOrMakeEqcInfo( nn, false );
if( eqc ){
Node ncons = eqc->d_constructor.get();
if( !ncons.isNull() ) {
for( int i=0; i<(int)ncons.getNumChildren(); i++ ) {
- if( searchForCycle( ncons[i], on, visited, explanation, false ) ) {
+ Node cn = searchForCycle( ncons[i], on, visited, explanation, false );
+ if( cn==on ) {
if( Debug.isOn("datatypes-cycles") && !d_cycle_check.isConnectedNode( n, ncons[i] ) ){
Debug("datatypes-cycles") << "Cycle subterm: " << n << " is not -> " << ncons[i] << "!!!!" << std::endl;
}
Node lit = NodeManager::currentNM()->mkNode( EQUAL, n, ncons );
explain( lit, explanation );
}
- return true;
+ return on;
+ }else if( !cn.isNull() ){
+ return cn;
}
}
}
}
+ visited.erase( nn );
+ return Node::null();
+ }else{
+ return nn;
}
- return false;
}
bool TheoryDatatypes::mustSpecifyAssignment(){
bool TransitiveClosure::addEdge(unsigned i, unsigned j)
{
+ Debug("trans-closure") << "Add edge " << i << " -> " << j << std::endl;
// Check for loops
Assert(i != j, "Cannot add self-loop");
- if (adjMatrix.size() > j && adjMatrix[j] != NULL && adjMatrix[j]->read(i)) {
+ if (adjIndex.get() > j && adjMatrix[j] != NULL && adjMatrix[j]->read(i)) {
return true;
}
// Grow matrix if necessary
unsigned maxSize = ((i > j) ? i : j) + 1;
- while (maxSize > adjMatrix.size()) {
- adjMatrix.push_back(NULL);
+ while (maxSize > adjIndex.get()) {
+ if( maxSize > adjMatrix.size() ){
+ adjMatrix.push_back(NULL);
+ }else if( adjMatrix[adjIndex.get()]!=NULL ){
+ adjMatrix[adjIndex.get()]->clear();
+ }
+ adjIndex.set( adjIndex.get() + 1 );
}
// Add edge from i to j and everything j can reach
// Add edges from everything that can reach i to j and everything that j can reach
unsigned k;
- for (k = 0; k < adjMatrix.size(); ++k) {
+ for (k = 0; k < adjIndex.get(); ++k) {
if (adjMatrix[k] != NULL && adjMatrix[k]->read(i)) {
adjMatrix[k]->write(j);
if (adjMatrix[j] != NULL) {
bool TransitiveClosure::isConnected(unsigned i, unsigned j)
{
- if( i>=adjMatrix.size() || j>adjMatrix.size() ){
+ if( i>=adjIndex.get() || j>adjIndex.get() ){//adjMatrix.size() ){
return false;
}else{
return adjMatrix[i] != NULL && adjMatrix[i]->read(j);
void TransitiveClosure::debugPrintMatrix()
{
unsigned i,j;
- for (i = 0; i < adjMatrix.size(); ++i) {
- for (j = 0; j < adjMatrix.size(); ++j) {
+ for (i = 0; i < adjIndex.get(); ++i) {
+ for (j = 0; j < adjIndex.get(); ++j) {
if (adjMatrix[i] != NULL && adjMatrix[i]->read(j)) {
Debug("trans-closure") << "1 ";
}
else Debug("trans-closure") << "0 ";
}
Debug("trans-closure") << endl;
- }
+ }
}
unsigned TransitiveClosureNode::getId( Node i ){
void TransitiveClosureNode::debugPrint(){
for( int i=0; i<(int)currEdges.size(); i++ ){
- Debug("trans-closure") << "currEdges[ " << i << " ] = "
+ Debug("trans-closure") << "currEdges[ " << i << " ] = "
<< currEdges[i].first << " -> " << currEdges[i].second;
+ int id1 = getId( currEdges[i].first );
+ int id2 = getId( currEdges[i].second );
+ Debug("trans-closure") << " { " << id1 << " -> " << id2 << " } ";
Debug("trans-closure") << std::endl;
}
+ debugPrintMatrix();
}