#include "theory/sets/theory_sets.h"
using namespace std;
+using namespace CVC4::kind;
namespace CVC4 {
namespace theory {
typedef std::map< Node, std::map< kind::Kind_t, std::vector< Node > > >::iterator TERM_IT;
typedef std::map< Node, std::map< Node, std::unordered_set< Node, NodeHashFunction > > >::iterator TC_IT;
- void TheorySetsRels::check(Theory::Effort level) {
- Trace("rels") << "\n[sets-rels] ******************************* Start the relational solver, effort = " << level << " *******************************\n" << std::endl;
- if(Theory::fullEffort(level)) {
- collectRelsInfo();
- check();
- doPendingLemmas();
- Assert( d_lemmas_out.empty() );
- Assert( d_pending_facts.empty() );
- } else {
- doPendingMerge();
- }
- Trace("rels") << "\n[sets-rels] ******************************* Done with the relational solver *******************************\n" << std::endl;
+TheorySetsRels::TheorySetsRels(context::Context* c,
+ context::UserContext* u,
+ eq::EqualityEngine* eq,
+ TheorySetsPrivate& set)
+ : d_eqEngine(eq),
+ d_sets_theory(set),
+ d_trueNode(NodeManager::currentNM()->mkConst<bool>(true)),
+ d_falseNode(NodeManager::currentNM()->mkConst<bool>(false)),
+ d_shared_terms(u),
+ d_satContext(c)
+{
+ d_eqEngine->addFunctionKind(PRODUCT);
+ d_eqEngine->addFunctionKind(JOIN);
+ d_eqEngine->addFunctionKind(TRANSPOSE);
+ d_eqEngine->addFunctionKind(TCLOSURE);
+ d_eqEngine->addFunctionKind(JOIN_IMAGE);
+ d_eqEngine->addFunctionKind(IDEN);
+ d_eqEngine->addFunctionKind(APPLY_CONSTRUCTOR);
+}
+
+TheorySetsRels::~TheorySetsRels() {}
+
+void TheorySetsRels::check(Theory::Effort level)
+{
+ Trace("rels") << "\n[sets-rels] ******************************* Start the "
+ "relational solver, effort = "
+ << level << " *******************************\n"
+ << std::endl;
+ if (Theory::fullEffort(level))
+ {
+ collectRelsInfo();
+ check();
+ doPendingInfers();
}
+ Assert(d_pending.empty());
+ Trace("rels") << "\n[sets-rels] ******************************* Done with "
+ "the relational solver *******************************\n"
+ << std::endl;
+}
void TheorySetsRels::check() {
MEM_IT m_it = d_rReps_memberReps_cache.begin();
for(unsigned int i = 0; i < m_it->second.size(); i++) {
Node mem = d_rReps_memberReps_cache[rel_rep][i];
Node exp = d_rReps_memberReps_exp_cache[rel_rep][i];
- std::map<kind::Kind_t, std::vector<Node> > kind_terms = d_terms_cache[rel_rep];
+ std::map<kind::Kind_t, std::vector<Node> >& kind_terms =
+ d_terms_cache[rel_rep];
if( kind_terms.find(kind::TRANSPOSE) != kind_terms.end() ) {
- std::vector<Node> tp_terms = kind_terms[kind::TRANSPOSE];
+ std::vector<Node>& tp_terms = kind_terms[TRANSPOSE];
if( tp_terms.size() > 0 ) {
applyTransposeRule( tp_terms );
applyTransposeRule( tp_terms[0], rel_rep, exp );
}
}
if( kind_terms.find(kind::JOIN) != kind_terms.end() ) {
- std::vector<Node> join_terms = kind_terms[kind::JOIN];
+ std::vector<Node>& join_terms = kind_terms[JOIN];
for( unsigned int j = 0; j < join_terms.size(); j++ ) {
applyJoinRule( join_terms[j], rel_rep, exp );
}
}
if( kind_terms.find(kind::PRODUCT) != kind_terms.end() ) {
- std::vector<Node> product_terms = kind_terms[kind::PRODUCT];
+ std::vector<Node>& product_terms = kind_terms[PRODUCT];
for( unsigned int j = 0; j < product_terms.size(); j++ ) {
applyProductRule( product_terms[j], rel_rep, exp );
}
}
if( kind_terms.find(kind::TCLOSURE) != kind_terms.end() ) {
- std::vector<Node> tc_terms = kind_terms[kind::TCLOSURE];
+ std::vector<Node>& tc_terms = kind_terms[TCLOSURE];
for( unsigned int j = 0; j < tc_terms.size(); j++ ) {
applyTCRule( mem, tc_terms[j], rel_rep, exp );
}
}
if( kind_terms.find(kind::JOIN_IMAGE) != kind_terms.end() ) {
- std::vector<Node> join_image_terms = kind_terms[kind::JOIN_IMAGE];
+ std::vector<Node>& join_image_terms = kind_terms[JOIN_IMAGE];
for( unsigned int j = 0; j < join_image_terms.size(); j++ ) {
applyJoinImageRule( mem, join_image_terms[j], exp );
}
}
if( kind_terms.find(kind::IDEN) != kind_terms.end() ) {
- std::vector<Node> iden_terms = kind_terms[kind::IDEN];
+ std::vector<Node>& iden_terms = kind_terms[IDEN];
for( unsigned int j = 0; j < iden_terms.size(); j++ ) {
applyIdenRule( mem, iden_terms[j], exp );
}
t_it++;
}
doTCInference();
+
+ // clean up
+ d_tuple_reps.clear();
+ d_rReps_memberReps_exp_cache.clear();
+ d_terms_cache.clear();
+ d_membership_trie.clear();
+ d_rel_nodes.clear();
+ d_rReps_memberReps_cache.clear();
+ d_rRep_tcGraph.clear();
+ d_tcr_tcGraph_exps.clear();
+ d_tcr_tcGraph.clear();
}
/*
Node eqc_rep = (*eqcs_i);
eq::EqClassIterator eqc_i = eq::EqClassIterator( eqc_rep, d_eqEngine );
+ TypeNode erType = eqc_rep.getType();
Trace("rels-ee") << "[sets-rels-ee] Eqc term representative: " << eqc_rep << " with type " << eqc_rep.getType() << std::endl;
while( !eqc_i.isFinished() ){
Trace("rels-ee") << " term : " << eqc_node << std::endl;
- if( getRepresentative(eqc_rep) == getRepresentative(d_trueNode) ||
- getRepresentative(eqc_rep) == getRepresentative(d_falseNode) ) {
-
+ if (erType.isBoolean() && eqc_rep.isConst())
+ {
// collect membership info
if( eqc_node.getKind() == kind::MEMBER && eqc_node[1].getType().getSetElementType().isTuple()) {
Node tup_rep = getRepresentative( eqc_node[0] );
reduceTupleVar( eqc_node );
}
- bool is_true_eq = areEqual( eqc_rep, d_trueNode );
+ bool is_true_eq = eqc_rep.getConst<bool>();
Node reason = is_true_eq ? eqc_node : eqc_node.negate();
if( is_true_eq ) {
if( safelyAddToMap(d_rReps_memberReps_cache, rel_rep, tup_rep) ) {
- addToMap(d_rReps_memberReps_exp_cache, rel_rep, reason);
+ d_rReps_memberReps_exp_cache[rel_rep].push_back(reason);
computeTupleReps(tup_rep);
d_membership_trie[rel_rep].addTerm(tup_rep, d_tuple_reps[tup_rep]);
}
}
}
// collect relational terms info
- } else if( eqc_rep.getType().isSet() && eqc_rep.getType().getSetElementType().isTuple() ) {
+ }
+ else if (erType.isSet() && erType.getSetElementType().isTuple())
+ {
if( eqc_node.getKind() == kind::TRANSPOSE || eqc_node.getKind() == kind::JOIN ||
eqc_node.getKind() == kind::PRODUCT || eqc_node.getKind() == kind::TCLOSURE ||
eqc_node.getKind() == kind::JOIN_IMAGE || eqc_node.getKind() == kind::IDEN ) {
}
}
// need to add all tuple elements as shared terms
- } else if( eqc_node.getType().isTuple() && !eqc_node.isConst() && !eqc_node.isVar() ) {
- for( unsigned int i = 0; i < eqc_node.getType().getTupleLength(); i++ ) {
+ }
+ else if (erType.isTuple() && !eqc_node.isConst() && !eqc_node.isVar())
+ {
+ for (unsigned i = 0, tlen = erType.getTupleLength(); i < tlen; i++)
+ {
Node element = RelsUtils::nthElementOfTuple( eqc_node, i );
if( !element.isConst() ) {
if( rel_mem_it == d_rReps_memberReps_cache.end() ) {
return;
}
+ NodeManager* nm = NodeManager::currentNM();
Node join_image_rel = join_image_term[0];
std::unordered_set< Node, NodeHashFunction > hasChecked;
NodeManager::currentNM()->mkNode( kind::APPLY_CONSTRUCTOR,
Node::fromExpr(dt[0].getConstructor()), fst_mem_rep ),
join_image_term);
- if( holds( new_membership ) ) {
+ if (d_sets_theory.isEntailed(new_membership, true))
+ {
++mem_rep_it;
++mem_rep_exp_it;
continue;
new_membership = NodeManager::currentNM()->mkNode( kind::OR, new_membership, NodeManager::currentNM()->mkNode( kind::NOT, NodeManager::currentNM()->mkNode( kind::DISTINCT, existing_members ) ));
}
Assert(reasons.size() >= 1);
- sendInfer( new_membership, reasons.size() > 1 ? NodeManager::currentNM()->mkNode( kind::AND, reasons) : reasons[0], "JOIN-IMAGE UP" );
+ sendInfer(
+ new_membership,
+ reasons.size() > 1 ? nm->mkNode(AND, reasons) : reasons[0],
+ "JOIN-IMAGE UP");
break;
}
}
if( distinct_skolems.size() >= 2 ) {
conclusion = NodeManager::currentNM()->mkNode( kind::AND, conclusion, NodeManager::currentNM()->mkNode( kind::DISTINCT, distinct_skolems ) );
}
- sendInfer( conclusion, reason, "JOIN-IMAGE DOWN" );
+ sendInfer(conclusion, reason, "JOIN-IMAGE DOWN");
Trace("rels-debug") << "\n[Theory::Rels] *********** Done with applyJoinImageRule ***********" << std::endl;
}
void TheorySetsRels::applyIdenRule( Node mem_rep, Node iden_term, Node exp) {
Trace("rels-debug") << "\n[Theory::Rels] *********** applyIdenRule on " << iden_term
<< " with mem_rep = " << mem_rep << " and exp = " << exp << std::endl;
+ NodeManager* nm = NodeManager::currentNM();
if( d_rel_nodes.find( iden_term ) == d_rel_nodes.end() ) {
computeMembersForIdenTerm( iden_term );
d_rel_nodes.insert( iden_term );
if( exp[1] != iden_term ) {
reason = NodeManager::currentNM()->mkNode( kind::AND, reason, NodeManager::currentNM()->mkNode( kind::EQUAL, exp[1], iden_term ) );
}
- sendInfer( NodeManager::currentNM()->mkNode( kind::AND, fact, NodeManager::currentNM()->mkNode( kind::EQUAL, fst_mem, snd_mem ) ), reason, "IDENTITY-DOWN" );
+ sendInfer(nm->mkNode(AND, fact, nm->mkNode(EQUAL, fst_mem, snd_mem)),
+ reason,
+ "IDENTITY-DOWN");
Trace("rels-debug") << "\n[Theory::Rels] *********** Done with applyIdenRule on " << iden_term << std::endl;
}
if( d_rReps_memberReps_cache.find( iden_term_rel_rep ) == d_rReps_memberReps_cache.end() ) {
return;
}
+ NodeManager* nm = NodeManager::currentNM();
MEM_IT rel_mem_exp_it = d_rReps_memberReps_exp_cache.find( iden_term_rel_rep );
std::vector< Node >::iterator mem_rep_exp_it = (*rel_mem_exp_it).second.begin();
if( (*mem_rep_exp_it)[1] != iden_term_rel ) {
reason = NodeManager::currentNM()->mkNode( kind::AND, reason, NodeManager::currentNM()->mkNode( kind::EQUAL, (*mem_rep_exp_it)[1], iden_term_rel ) );
}
- sendInfer( NodeManager::currentNM()->mkNode( kind::MEMBER, new_mem, iden_term ), reason, "IDENTITY-UP" );
+ sendInfer(nm->mkNode(MEMBER, new_mem, iden_term), reason, "IDENTITY-UP");
++mem_rep_exp_it;
}
Trace("rels-debug") << "\n[Theory::Rels] *********** Done with computing members for Iden Term = " << iden_term << std::endl;
(NodeManager::currentNM()->mkNode(kind::OR, sk_eq, NodeManager::currentNM()->mkNode(kind::MEMBER, RelsUtils::constructPair(tc_rel, sk_1, sk_2), tc_rel))))))));
Node tc_lemma = NodeManager::currentNM()->mkNode(kind::IMPLIES, reason, conclusion );
- std::vector< Node > require_phase;
- require_phase.push_back(Rewriter::rewrite(mem_of_r));
- require_phase.push_back(Rewriter::rewrite(sk_eq));
- d_tc_lemmas_last[tc_lemma] = require_phase;
+ d_pending.push_back(tc_lemma);
}
bool TheorySetsRels::isTCReachable( Node mem_rep, Node tc_rel ) {
void TheorySetsRels::doTCInference(Node tc_rel, std::vector< Node > reasons, std::map< Node, std::unordered_set< Node, NodeHashFunction > >& tc_graph,
std::map< Node, Node >& rel_tc_graph_exps, Node start_node_rep, Node cur_node_rep, std::unordered_set< Node, NodeHashFunction >& seen ) {
+ NodeManager* nm = NodeManager::currentNM();
Node tc_mem = RelsUtils::constructPair( tc_rel, RelsUtils::nthElementOfTuple((reasons.front())[0], 0), RelsUtils::nthElementOfTuple((reasons.back())[0], 1) );
std::vector< Node > all_reasons( reasons );
all_reasons.push_back( NodeManager::currentNM()->mkNode(kind::EQUAL, tc_rel[0], reasons.back()[1]) );
}
if( all_reasons.size() > 1) {
- sendInfer( NodeManager::currentNM()->mkNode(kind::MEMBER, tc_mem, tc_rel), NodeManager::currentNM()->mkNode(kind::AND, all_reasons), "TCLOSURE-Forward");
+ sendInfer(nm->mkNode(MEMBER, tc_mem, tc_rel),
+ nm->mkNode(AND, all_reasons),
+ "TCLOSURE-Forward");
} else {
- sendInfer( NodeManager::currentNM()->mkNode(kind::MEMBER, tc_mem, tc_rel), all_reasons.front(), "TCLOSURE-Forward");
+ sendInfer(nm->mkNode(MEMBER, tc_mem, tc_rel),
+ all_reasons.front(),
+ "TCLOSURE-Forward");
}
// check if cur_node has been traversed or not
if( pt_rel != exp[1] ) {
reason = NodeManager::currentNM()->mkNode(kind::AND, exp, NodeManager::currentNM()->mkNode(kind::EQUAL, pt_rel, exp[1]));
}
- sendInfer( fact_1, reason, "product-split" );
- sendInfer( fact_2, reason, "product-split" );
+ sendInfer(fact_1, reason, "product-split");
+ sendInfer(fact_2, reason, "product-split");
}
/* join-split rule: (a, b) IS_IN (X JOIN Y)
Node r1_rep = getRepresentative(join_rel[0]);
Node r2_rep = getRepresentative(join_rel[1]);
TypeNode shared_type = r2_rep.getType().getSetElementType().getTupleTypes()[0];
- Node shared_x = NodeManager::currentNM()->mkSkolem("srj_", shared_type);
+ Node shared_x = d_sets_theory.getSkolemCache().mkTypedSkolemCached(
+ shared_type, mem, join_rel, SkolemCache::SK_JOIN, "srj");
Datatype dt = join_rel[0].getType().getSetElementType().getDatatype();
unsigned int s1_len = join_rel[0].getType().getSetElementType().getTupleLength();
unsigned int tup_len = join_rel.getType().getSetElementType().getTupleLength();
reason = NodeManager::currentNM()->mkNode(kind::AND, reason, NodeManager::currentNM()->mkNode(kind::EQUAL, join_rel, exp[1]));
}
Node fact = NodeManager::currentNM()->mkNode(kind::MEMBER, mem1, join_rel[0]);
- sendInfer( fact, reason, "JOIN-Split" );
+ sendInfer(fact, reason, "JOIN-Split-1");
fact = NodeManager::currentNM()->mkNode(kind::MEMBER, mem2, join_rel[1]);
- sendInfer( fact, reason, "JOIN-Split" );
+ sendInfer(fact, reason, "JOIN-Split-2");
makeSharedTerm( shared_x );
}
if( tp_terms.size() < 1) {
return;
}
+ NodeManager* nm = NodeManager::currentNM();
for( unsigned int i = 1; i < tp_terms.size(); i++ ) {
Trace("rels-debug") << "\n[Theory::Rels] *********** Applying TRANSPOSE-Equal rule on transposed term = " << tp_terms[0] << " and " << tp_terms[i] << std::endl;
- sendInfer(NodeManager::currentNM()->mkNode(kind::EQUAL, tp_terms[0][0], tp_terms[i][0]), NodeManager::currentNM()->mkNode(kind::EQUAL, tp_terms[0], tp_terms[i]), "TRANSPOSE-Equal");
+ sendInfer(nm->mkNode(EQUAL, tp_terms[0][0], tp_terms[i][0]),
+ nm->mkNode(EQUAL, tp_terms[0], tp_terms[i]),
+ "TRANSPOSE-Equal");
}
}
Trace("rels-debug") << "\n[Theory::Rels] *********** Applying TRANSPOSE rule on transposed term = " << tp_rel
<< ", its representative = " << tp_rel_rep
<< " with explanation = " << exp << std::endl;
+ NodeManager* nm = NodeManager::currentNM();
if(d_rel_nodes.find( tp_rel ) == d_rel_nodes.end()) {
Trace("rels-debug") << "\n[Theory::Rels] Apply TRANSPOSE-Compose rule on term: " << tp_rel
if( tp_rel != exp[1] ) {
reason = NodeManager::currentNM()->mkNode(kind::AND, reason, NodeManager::currentNM()->mkNode(kind::EQUAL, tp_rel, exp[1]));
}
- sendInfer( NodeManager::currentNM()->mkNode(kind::MEMBER, reversed_mem, tp_rel[0]), reason, "TRANSPOSE-Reverse" );
+ sendInfer(nm->mkNode(MEMBER, reversed_mem, tp_rel[0]),
+ reason,
+ "TRANSPOSE-Reverse");
}
void TheorySetsRels::doTCInference() {
}
Node rel0_rep = getRepresentative(rel[0]);
- if(d_rReps_memberReps_cache.find( rel0_rep ) == d_rReps_memberReps_cache.end())
+ if (d_rReps_memberReps_cache.find(rel0_rep)
+ == d_rReps_memberReps_cache.end())
+ {
return;
+ }
+ NodeManager* nm = NodeManager::currentNM();
std::vector<Node> members = d_rReps_memberReps_cache[rel0_rep];
std::vector<Node> exps = d_rReps_memberReps_exp_cache[rel0_rep];
if( rel[0] != exps[i][1] ) {
reason = NodeManager::currentNM()->mkNode(kind::AND, reason, NodeManager::currentNM()->mkNode(kind::EQUAL, rel[0], exps[i][1]));
}
- sendInfer(NodeManager::currentNM()->mkNode(kind::MEMBER, RelsUtils::reverseTuple(exps[i][0]), rel), reason, "TRANSPOSE-reverse");
+ sendInfer(nm->mkNode(MEMBER, RelsUtils::reverseTuple(exps[i][0]), rel),
+ reason,
+ "TRANSPOSE-reverse");
}
}
}
d_rReps_memberReps_cache.find( r2_rep ) == d_rReps_memberReps_cache.end() ) {
return;
}
+ NodeManager* nm = NodeManager::currentNM();
std::vector<Node> r1_rep_exps = d_rReps_memberReps_exp_cache[r1_rep];
std::vector<Node> r2_rep_exps = d_rReps_memberReps_exp_cache[r2_rep];
reasons.push_back( NodeManager::currentNM()->mkNode(kind::EQUAL, r2, r2_rep_exps[j][1]) );
}
if( isProduct ) {
- sendInfer( fact, NodeManager::currentNM()->mkNode(kind::AND, reasons), "PRODUCT-Compose" );
+ sendInfer(fact,
+ nm->mkNode(kind::AND, reasons),
+ "PRODUCT-Compose");
} else {
if( r1_rmost != r2_lmost ) {
reasons.push_back( NodeManager::currentNM()->mkNode(kind::EQUAL, r1_rmost, r2_lmost) );
}
- sendInfer( fact, NodeManager::currentNM()->mkNode(kind::AND, reasons), "JOIN-Compose" );
+ sendInfer(fact, nm->mkNode(kind::AND, reasons), "JOIN-Compose");
}
}
}
}
- void TheorySetsRels::doPendingLemmas() {
- Trace("rels-debug") << "[Theory::Rels] **************** Start doPendingLemmas !" << std::endl;
- if( !(*d_conflict) ){
- if ( (!d_lemmas_out.empty() || !d_pending_facts.empty()) ) {
- for( unsigned i=0; i < d_lemmas_out.size(); i++ ){
- Assert(d_lemmas_out[i].getKind() == kind::IMPLIES);
- if(holds( d_lemmas_out[i][1] )) {
- Trace("rels-lemma-skip") << "[sets-rels-lemma-skip] Skip an already held lemma: "
- << d_lemmas_out[i]<< std::endl;
- continue;
- }
- d_sets_theory.d_out->lemma( d_lemmas_out[i] );
- Trace("rels-lemma") << "[sets-rels-lemma] Send out a lemma : "
- << d_lemmas_out[i] << std::endl;
- }
- for( std::map<Node, Node>::iterator pending_it = d_pending_facts.begin();
- pending_it != d_pending_facts.end(); pending_it++ ) {
- if( holds( pending_it->first ) ) {
- Trace("rels-lemma-skip") << "[sets-rels-fact-lemma-skip] Skip an already held fact,: "
- << pending_it->first << std::endl;
- continue;
- }
- Node lemma = NodeManager::currentNM()->mkNode(kind::IMPLIES, pending_it->second, pending_it->first);
- if( d_lemmas_produced.find( lemma ) == d_lemmas_produced.end() ) {
- d_sets_theory.d_out->lemma(NodeManager::currentNM()->mkNode(kind::IMPLIES, pending_it->second, pending_it->first));
- Trace("rels-lemma") << "[sets-rels-fact-lemma] Send out a fact as lemma : "
- << pending_it->first << " with reason " << pending_it->second << std::endl;
- d_lemmas_produced.insert( lemma );
- }
+ void TheorySetsRels::doPendingInfers()
+ {
+ // process the inferences in d_pending
+ if (!d_sets_theory.isInConflict())
+ {
+ std::vector<Node> lemmas;
+ for (const Node& p : d_pending)
+ {
+ d_sets_theory.processInference(p, "rels", lemmas);
+ if (d_sets_theory.isInConflict())
+ {
+ break;
}
}
+ // if we are still not in conflict, send lemmas
+ if (!d_sets_theory.isInConflict())
+ {
+ d_sets_theory.flushLemmas(lemmas);
+ }
}
- doTCLemmas();
- Trace("rels-debug") << "[Theory::Rels] **************** Done with doPendingLemmas !" << std::endl;
- d_tuple_reps.clear();
- d_rReps_memberReps_exp_cache.clear();
- d_terms_cache.clear();
- d_lemmas_out.clear();
- d_membership_trie.clear();
- d_rel_nodes.clear();
- d_pending_facts.clear();
- d_rReps_memberReps_cache.clear();
- d_rRep_tcGraph.clear();
- d_tcr_tcGraph_exps.clear();
- d_tcr_tcGraph.clear();
- d_tc_lemmas_last.clear();
+ d_pending.clear();
}
-
bool TheorySetsRels::isRelationKind( Kind k ) {
return k == kind::TRANSPOSE || k == kind::PRODUCT || k == kind::JOIN || k == kind::TCLOSURE;
}
- void TheorySetsRels::doTCLemmas() {
- Trace("rels-debug") << "[Theory::Rels] **************** Start doTCLemmas !" << std::endl;
- std::map< Node, std::vector< Node > >::iterator tc_lemma_it = d_tc_lemmas_last.begin();
- while( tc_lemma_it != d_tc_lemmas_last.end() ) {
- if( !holds( tc_lemma_it->first[1] ) ) {
- if( d_lemmas_produced.find( tc_lemma_it->first ) == d_lemmas_produced.end() ) {
- d_sets_theory.d_out->lemma( tc_lemma_it->first );
- d_lemmas_produced.insert( tc_lemma_it->first );
-
- for( unsigned int i = 0; i < (tc_lemma_it->second).size(); i++ ) {
- if( (tc_lemma_it->second)[i] == d_falseNode ) {
- d_sets_theory.d_out->requirePhase((tc_lemma_it->second)[i], true);
- }
- }
- Trace("rels-lemma") << "[Theory::Rels] **** Send out a TC lemma = " << tc_lemma_it->first << " by " << "TCLOSURE-Forward"<< std::endl;
- }
- }
- ++tc_lemma_it;
- }
- Trace("rels-debug") << "[Theory::Rels] **************** Done with doTCLemmas !" << std::endl;
- }
-
- void TheorySetsRels::sendLemma(Node conc, Node ant, const char * c) {
- if( !holds( conc ) ) {
- Node lemma = NodeManager::currentNM()->mkNode(kind::IMPLIES, ant, conc);
- if( d_lemmas_produced.find( lemma ) == d_lemmas_produced.end() ) {
- d_lemmas_out.push_back( lemma );
- d_lemmas_produced.insert( lemma );
- Trace("rels-send-lemma") << "[Theory::Rels] **** Generate a lemma conclusion = " << conc << " with reason = " << ant << " by " << c << std::endl;
- }
- }
- }
-
- void TheorySetsRels::sendInfer( Node fact, Node exp, const char * c ) {
- if( !holds( fact ) ) {
- Trace("rels-send-lemma") << "[Theory::Rels] **** Generate an infered fact "
- << fact << " with reason " << exp << " by "<< c << std::endl;
- d_pending_facts[fact] = exp;
- } else {
- Trace("rels-send-lemma-debug") << "[Theory::Rels] **** Generate an infered fact "
- << fact << " with reason " << exp << " by "<< c
- << ", but it holds already, thus skip it!" << std::endl;
- }
- }
-
Node TheorySetsRels::getRepresentative( Node t ) {
if( d_eqEngine->hasTerm( t ) ){
return d_eqEngine->getRepresentative( t );
return false;
}
- void TheorySetsRels::addToMap(std::map< Node, std::vector<Node> >& map, Node rel_rep, Node member) {
- if(map.find(rel_rep) == map.end()) {
- std::vector<Node> members;
- members.push_back(member);
- map[rel_rep] = members;
- } else {
- map[rel_rep].push_back(member);
- }
- }
-
- void TheorySetsRels::addSharedTerm( TNode n ) {
- Trace("rels-debug") << "[sets-rels] Add a shared term: " << n << std::endl;
- d_sets_theory.addSharedTerm(n);
- d_eqEngine->addTriggerTerm(n, THEORY_SETS);
- }
-
void TheorySetsRels::makeSharedTerm( Node n ) {
- Trace("rels-share") << " [sets-rels] making shared term " << n << std::endl;
if(d_shared_terms.find(n) == d_shared_terms.end()) {
+ Trace("rels-share") << " [sets-rels] making shared term " << n
+ << std::endl;
Node skolem = NodeManager::currentNM()->mkSkolem( "sts", NodeManager::currentNM()->mkSetType( n.getType() ) );
- sendLemma(skolem.eqNode(NodeManager::currentNM()->mkNode(kind::SINGLETON,n)), d_trueNode, "share-term");
+ Node skEq =
+ skolem.eqNode(NodeManager::currentNM()->mkNode(kind::SINGLETON, n));
+ // force lemma to be sent immediately
+ d_sets_theory.getOutputChannel()->lemma(skEq);
d_shared_terms.insert(n);
}
}
- bool TheorySetsRels::holds(Node node) {
- bool polarity = node.getKind() != kind::NOT;
- Node atom = polarity ? node : node[0];
- return d_sets_theory.isEntailed( atom, polarity );
- }
-
/*
* For each tuple n, we store a mapping between n and a list of its elements representatives
* in d_tuple_reps. This would later be used for applying JOIN operator.
Node tuple_reduct = NodeManager::currentNM()->mkNode(kind::APPLY_CONSTRUCTOR, tuple_elements);
tuple_reduct = NodeManager::currentNM()->mkNode(kind::MEMBER,tuple_reduct, n[1]);
Node tuple_reduction_lemma = NodeManager::currentNM()->mkNode(kind::EQUAL, n, tuple_reduct);
- sendLemma(tuple_reduction_lemma, d_trueNode, "tuple-reduction");
+ sendInfer(tuple_reduction_lemma, d_trueNode, "tuple-reduction");
d_symbolic_tuples.insert(n);
}
}
- TheorySetsRels::TheorySetsRels( context::Context* c,
- context::UserContext* u,
- eq::EqualityEngine* eq,
- context::CDO<bool>* conflict,
- TheorySets& d_set ):
- d_eqEngine(eq),
- d_conflict(conflict),
- d_sets_theory(d_set),
- d_trueNode(NodeManager::currentNM()->mkConst<bool>(true)),
- d_falseNode(NodeManager::currentNM()->mkConst<bool>(false)),
- d_pending_merge(c),
- d_lemmas_produced(u),
- d_shared_terms(u)
- {
- d_eqEngine->addFunctionKind(kind::PRODUCT);
- d_eqEngine->addFunctionKind(kind::JOIN);
- d_eqEngine->addFunctionKind(kind::TRANSPOSE);
- d_eqEngine->addFunctionKind(kind::TCLOSURE);
- d_eqEngine->addFunctionKind(kind::JOIN_IMAGE);
- d_eqEngine->addFunctionKind(kind::IDEN);
- }
-
- TheorySetsRels::~TheorySetsRels() {
- for(std::map< Node, EqcInfo* >::iterator i = d_eqc_info.begin(), iend = d_eqc_info.end();
- i != iend; ++i){
- EqcInfo* current = (*i).second;
- Assert(current != NULL);
- delete current;
- }
- }
-
std::vector<Node> TupleTrie::findTerms( std::vector< Node >& reps, int argIndex ) {
std::vector<Node> nodes;
std::map< Node, TupleTrie >::iterator it;
}
}
- TheorySetsRels::EqcInfo::EqcInfo( context::Context* c ) :
- d_mem(c), d_mem_exp(c), d_tp(c), d_pt(c), d_tc(c), d_rel_tc(c) {}
-
- void TheorySetsRels::eqNotifyNewClass( Node n ) {
- Trace("rels-std") << "[sets-rels] eqNotifyNewClass:" << " t = " << n << std::endl;
- if(n.getKind() == kind::TRANSPOSE || n.getKind() == kind::PRODUCT || n.getKind() == kind::TCLOSURE) {
- getOrMakeEqcInfo( n, true );
- if( n.getKind() == kind::TCLOSURE ) {
- Node relRep_of_tc = getRepresentative( n[0] );
- EqcInfo* rel_ei = getOrMakeEqcInfo( relRep_of_tc, true );
-
- if( rel_ei->d_rel_tc.get().isNull() ) {
- rel_ei->d_rel_tc = n;
- Node exp = relRep_of_tc == n[0] ? d_trueNode : NodeManager::currentNM()->mkNode( kind::EQUAL, relRep_of_tc, n[0] );
- for( NodeSet::const_iterator mem_it = rel_ei->d_mem.begin(); mem_it != rel_ei->d_mem.end(); mem_it++ ) {
- Node mem_exp = (*rel_ei->d_mem_exp.find(*mem_it)).second;
- exp = NodeManager::currentNM()->mkNode( kind::AND, exp, mem_exp);
- if( mem_exp[1] != relRep_of_tc ) {
- exp = NodeManager::currentNM()->mkNode( kind::AND, exp, NodeManager::currentNM()->mkNode(kind::EQUAL, relRep_of_tc, mem_exp[1] ) );
- }
- sendMergeInfer( NodeManager::currentNM()->mkNode(kind::MEMBER, mem_exp[0], n), exp, "TCLOSURE-UP I" );
- }
- }
- }
- }
- }
-
- // Merge t2 into t1, t1 will be the rep of the new eqc
- void TheorySetsRels::eqNotifyPostMerge( Node t1, Node t2 ) {
- Trace("rels-std") << "[sets-rels-std] eqNotifyPostMerge:" << " t1 = " << t1 << " t2 = " << t2 << std::endl;
-
- // Merge membership constraint with "true" eqc
- if( t1 == d_trueNode && t2.getKind() == kind::MEMBER && t2[0].getType().isTuple() ) {
- Node mem_rep = getRepresentative( t2[0] );
- Node t2_1rep = getRepresentative( t2[1] );
- EqcInfo* ei = getOrMakeEqcInfo( t2_1rep, true );
- if(ei->d_mem.contains(mem_rep)) {
- return;
- }
- Node exp = t2;
-
- ei->d_mem.insert( mem_rep );
- ei->d_mem_exp.insert( mem_rep, exp );
-
- // Process a membership constraint that a tuple is a member of transpose of rel
- if( !ei->d_tp.get().isNull() ) {
- if( ei->d_tp.get() != t2[1] ) {
- exp = NodeManager::currentNM()->mkNode(kind::AND, NodeManager::currentNM()->mkNode(kind::EQUAL, ei->d_tp.get(), t2[1]), t2 );
- }
- sendInferTranspose( t2[0], ei->d_tp.get(), exp );
- }
- // Process a membership constraint that a tuple is a member of product of rel
- if( !ei->d_pt.get().isNull() ) {
- if( ei->d_pt.get() != t2[1] ) {
- exp = NodeManager::currentNM()->mkNode(kind::AND, NodeManager::currentNM()->mkNode(kind::EQUAL, ei->d_pt.get(), t2[1]), t2 );
- }
- sendInferProduct( t2[0], ei->d_pt.get(), exp );
- }
-
- if( !ei->d_rel_tc.get().isNull() ) {
- if( ei->d_rel_tc.get()[0] != t2[1] ) {
- exp = NodeManager::currentNM()->mkNode(kind::AND, NodeManager::currentNM()->mkNode(kind::EQUAL, ei->d_rel_tc.get()[0], t2[1]), t2 );
- }
- sendMergeInfer(NodeManager::currentNM()->mkNode(kind::MEMBER, t2[0], ei->d_rel_tc.get()), exp, "TCLOSURE-UP I");
- }
- // Process a membership constraint that a tuple is a member of transitive closure of rel
- if( !ei->d_tc.get().isNull() ) {
- sendInferTClosure( t2, ei );
- }
-
- // Merge two relation eqcs
- } else if( t1.getType().isSet() && t2.getType().isSet() && t1.getType().getSetElementType().isTuple() ) {
- EqcInfo* t1_ei = getOrMakeEqcInfo( t1 );
- EqcInfo* t2_ei = getOrMakeEqcInfo( t2 );
-
- if( t1_ei != NULL && t2_ei != NULL ) {
- if( !t1_ei->d_tp.get().isNull() && !t2_ei->d_tp.get().isNull() ) {
- sendInferTranspose(t1_ei->d_tp.get(), t2_ei->d_tp.get(), NodeManager::currentNM()->mkNode(kind::EQUAL, t1_ei->d_tp.get(), t2_ei->d_tp.get() ) );
- }
- std::vector< Node > t2_new_mems;
- std::vector< Node > t2_new_exps;
- NodeSet::const_iterator t2_mem_it = t2_ei->d_mem.begin();
- NodeSet::const_iterator t1_mem_it = t1_ei->d_mem.begin();
-
- for( ; t2_mem_it != t2_ei->d_mem.end(); t2_mem_it++ ) {
- if( !t1_ei->d_mem.contains( *t2_mem_it ) ) {
- Node t2_mem_exp = (*t2_ei->d_mem_exp.find(*t2_mem_it)).second;
-
- if( t2_ei->d_tp.get().isNull() && !t1_ei->d_tp.get().isNull() ) {
- Node reason = t1_ei->d_tp.get() == (t2_mem_exp)[1]
- ? (t2_mem_exp) : NodeManager::currentNM()->mkNode(kind::AND, t2_mem_exp, NodeManager::currentNM()->mkNode(kind::EQUAL, (t2_mem_exp)[1], t1_ei->d_tp.get()));
- sendInferTranspose( t2_mem_exp[0], t1_ei->d_tp.get(), reason );
- }
- if( t2_ei->d_pt.get().isNull() && !t1_ei->d_pt.get().isNull() ) {
- Node reason = t1_ei->d_pt.get() == (t2_mem_exp)[1]
- ? (t2_mem_exp) : NodeManager::currentNM()->mkNode(kind::AND, t2_mem_exp, NodeManager::currentNM()->mkNode(kind::EQUAL, (t2_mem_exp)[1], t1_ei->d_pt.get()));
- sendInferProduct( t2_mem_exp[0], t1_ei->d_pt.get(), reason );
- }
- if( t2_ei->d_tc.get().isNull() && !t1_ei->d_tc.get().isNull() ) {
- sendInferTClosure( t2_mem_exp, t1_ei );
- }
- if( t2_ei->d_rel_tc.get().isNull() && !t1_ei->d_rel_tc.get().isNull() ) {
- Node reason = t1_ei->d_rel_tc.get()[0] == t2_mem_exp[1] ?
- t2_mem_exp : NodeManager::currentNM()->mkNode(kind::AND, NodeManager::currentNM()->mkNode(kind::EQUAL, t1_ei->d_rel_tc.get()[0], t2_mem_exp[1]), t2_mem_exp );
- sendMergeInfer(NodeManager::currentNM()->mkNode(kind::MEMBER, t2_mem_exp[0], t1_ei->d_rel_tc.get()), reason, "TCLOSURE-UP I");
- }
- t2_new_mems.push_back( *t2_mem_it );
- t2_new_exps.push_back( t2_mem_exp );
- }
- }
- for( ; t1_mem_it != t1_ei->d_mem.end(); t1_mem_it++ ) {
- if( !t2_ei->d_mem.contains( *t1_mem_it ) ) {
- Node t1_mem_exp = (*t1_ei->d_mem_exp.find(*t1_mem_it)).second;
- if( t1_ei->d_tp.get().isNull() && !t2_ei->d_tp.get().isNull() ) {
- Node reason = t2_ei->d_tp.get() == (t1_mem_exp)[1]
- ? (t1_mem_exp) : NodeManager::currentNM()->mkNode(kind::AND, t1_mem_exp, NodeManager::currentNM()->mkNode(kind::EQUAL, (t1_mem_exp)[1], t2_ei->d_tp.get()));
- sendInferTranspose( (t1_mem_exp)[0], t2_ei->d_tp.get(), reason );
- }
- if( t1_ei->d_pt.get().isNull() && !t2_ei->d_pt.get().isNull() ) {
- Node reason = t2_ei->d_pt.get() == (t1_mem_exp)[1]
- ? (t1_mem_exp) : NodeManager::currentNM()->mkNode(kind::AND, t1_mem_exp, NodeManager::currentNM()->mkNode(kind::EQUAL, (t1_mem_exp)[1], t2_ei->d_pt.get()));
- sendInferProduct( (t1_mem_exp)[0], t2_ei->d_pt.get(), reason );
- }
- if( t1_ei->d_tc.get().isNull() && !t2_ei->d_tc.get().isNull() ) {
- sendInferTClosure(t1_mem_exp, t2_ei );
- }
- if( t1_ei->d_rel_tc.get().isNull() && !t2_ei->d_rel_tc.get().isNull() ) {
- Node reason = t2_ei->d_rel_tc.get()[0] == t1_mem_exp[1] ?
- t1_mem_exp : NodeManager::currentNM()->mkNode(kind::AND, NodeManager::currentNM()->mkNode(kind::EQUAL, t2_ei->d_rel_tc.get()[0], t1_mem_exp[1]), t1_mem_exp );
- sendMergeInfer(NodeManager::currentNM()->mkNode(kind::MEMBER, t1_mem_exp[0], t2_ei->d_rel_tc.get()), reason, "TCLOSURE-UP I");
- }
- }
- }
- std::vector< Node >::iterator t2_new_mem_it = t2_new_mems.begin();
- std::vector< Node >::iterator t2_new_exp_it = t2_new_exps.begin();
- for( ; t2_new_mem_it != t2_new_mems.end(); t2_new_mem_it++, t2_new_exp_it++ ) {
- t1_ei->d_mem.insert( *t2_new_mem_it );
- t1_ei->d_mem_exp.insert( *t2_new_mem_it, *t2_new_exp_it );
- }
- if( t1_ei->d_tp.get().isNull() && !t2_ei->d_tp.get().isNull() ) {
- t1_ei->d_tp.set(t2_ei->d_tp.get());
- }
- if( t1_ei->d_pt.get().isNull() && !t2_ei->d_pt.get().isNull() ) {
- t1_ei->d_pt.set(t2_ei->d_pt.get());
- }
- if( t1_ei->d_tc.get().isNull() && !t2_ei->d_tc.get().isNull() ) {
- t1_ei->d_tc.set(t2_ei->d_tc.get());
- }
- if( t1_ei->d_rel_tc.get().isNull() && !t2_ei->d_rel_tc.get().isNull() ) {
- t1_ei->d_rel_tc.set(t2_ei->d_rel_tc.get());
- }
- } else if( t1_ei != NULL ) {
- if( (t2.getKind() == kind::TRANSPOSE && t1_ei->d_tp.get().isNull()) ||
- (t2.getKind() == kind::PRODUCT && t1_ei->d_pt.get().isNull()) ||
- (t2.getKind() == kind::TCLOSURE && t1_ei->d_tc.get().isNull()) ) {
- NodeSet::const_iterator t1_mem_it = t1_ei->d_mem.begin();
-
- if( t2.getKind() == kind::TRANSPOSE ) {
- t1_ei->d_tp = t2;
- } else if( t2.getKind() == kind::PRODUCT ) {
- t1_ei->d_pt = t2;
- } else if( t2.getKind() == kind::TCLOSURE ) {
- t1_ei->d_tc = t2;
- }
- for( ; t1_mem_it != t1_ei->d_mem.end(); t1_mem_it++ ) {
- Node t1_exp = (*t1_ei->d_mem_exp.find(*t1_mem_it)).second;
- if( t2.getKind() == kind::TRANSPOSE ) {
- Node reason = t2 == t1_exp[1]
- ? (t1_exp) : NodeManager::currentNM()->mkNode(kind::AND, (t1_exp), NodeManager::currentNM()->mkNode(kind::EQUAL, (t1_exp)[1], t2));
- sendInferTranspose( (t1_exp)[0], t2, reason );
- } else if( t2.getKind() == kind::PRODUCT ) {
- Node reason = t2 == (t1_exp)[1]
- ? (t1_exp) : NodeManager::currentNM()->mkNode(kind::AND, (t1_exp), NodeManager::currentNM()->mkNode(kind::EQUAL, (t1_exp)[1], t2));
- sendInferProduct( (t1_exp)[0], t2, reason );
- } else if( t2.getKind() == kind::TCLOSURE ) {
- sendInferTClosure( t1_exp, t1_ei );
- }
- }
- }
- } else if( t2_ei != NULL ) {
- EqcInfo* new_t1_ei = getOrMakeEqcInfo( t1, true );
- if( new_t1_ei->d_tp.get().isNull() && !t2_ei->d_tp.get().isNull() ) {
- new_t1_ei->d_tp.set(t2_ei->d_tp.get());
- }
- if( new_t1_ei->d_pt.get().isNull() && !t2_ei->d_pt.get().isNull() ) {
- new_t1_ei->d_pt.set(t2_ei->d_pt.get());
- }
- if( new_t1_ei->d_tc.get().isNull() && !t2_ei->d_tc.get().isNull() ) {
- new_t1_ei->d_tc.set(t2_ei->d_tc.get());
- }
- if( new_t1_ei->d_rel_tc.get().isNull() && !t2_ei->d_rel_tc.get().isNull() ) {
- new_t1_ei->d_rel_tc.set(t2_ei->d_rel_tc.get());
- }
- if( (t1.getKind() == kind::TRANSPOSE && t2_ei->d_tp.get().isNull()) ||
- (t1.getKind() == kind::PRODUCT && t2_ei->d_pt.get().isNull()) ||
- (t1.getKind() == kind::TCLOSURE && t2_ei->d_tc.get().isNull()) ) {
- NodeSet::const_iterator t2_mem_it = t2_ei->d_mem.begin();
-
- for( ; t2_mem_it != t2_ei->d_mem.end(); t2_mem_it++ ) {
- Node t2_exp = (*t1_ei->d_mem_exp.find(*t2_mem_it)).second;
-
- if( t1.getKind() == kind::TRANSPOSE ) {
- Node reason = t1 == (t2_exp)[1]
- ? (t2_exp) : NodeManager::currentNM()->mkNode(kind::AND, (t2_exp), NodeManager::currentNM()->mkNode(kind::EQUAL, (t2_exp)[1], t1));
- sendInferTranspose( (t2_exp)[0], t1, reason );
- } else if( t1.getKind() == kind::PRODUCT ) {
- Node reason = t1 == (t2_exp)[1]
- ? (t2_exp) : NodeManager::currentNM()->mkNode(kind::AND, (t2_exp), NodeManager::currentNM()->mkNode(kind::EQUAL, (t2_exp)[1], t1));
- sendInferProduct( (t2_exp)[0], t1, reason );
- } else if( t1.getKind() == kind::TCLOSURE ) {
- sendInferTClosure( t2_exp, new_t1_ei );
- }
- }
- }
- }
- }
-
- Trace("rels-std") << "[sets-rels] done with eqNotifyPostMerge:" << " t1 = " << t1 << " t2 = " << t2 << std::endl;
- }
-
- void TheorySetsRels::sendInferTClosure( Node new_mem_exp, EqcInfo* ei ) {
- NodeSet::const_iterator mem_it = ei->d_mem.begin();
- Node mem_rep = getRepresentative( new_mem_exp[0] );
- Node new_mem_rel = new_mem_exp[1];
- Node new_mem_fst = RelsUtils::nthElementOfTuple( new_mem_exp[0], 0 );
- Node new_mem_snd = RelsUtils::nthElementOfTuple( new_mem_exp[0], 1 );
- for( ; mem_it != ei->d_mem.end(); mem_it++ ) {
- if( *mem_it == mem_rep ) {
- continue;
- }
- Node d_mem_exp = (*ei->d_mem_exp.find(*mem_it)).second;
- Node d_mem_fst = RelsUtils::nthElementOfTuple( d_mem_exp[0], 0 );
- Node d_mem_snd = RelsUtils::nthElementOfTuple( d_mem_exp[0], 1 );
- Node d_mem_rel = d_mem_exp[1];
- if( areEqual( new_mem_fst, d_mem_snd) ) {
- Node reason = NodeManager::currentNM()->mkNode( kind::AND, new_mem_exp, d_mem_exp );
- reason = NodeManager::currentNM()->mkNode( kind::AND, reason, NodeManager::currentNM()->mkNode(kind::EQUAL, new_mem_fst, d_mem_snd ) );
- if( new_mem_rel != ei->d_tc.get() ) {
- reason = NodeManager::currentNM()->mkNode( kind::AND, reason, NodeManager::currentNM()->mkNode(kind::EQUAL, new_mem_rel, ei->d_tc.get() ) );
- }
- if( d_mem_rel != ei->d_tc.get() ) {
- reason = NodeManager::currentNM()->mkNode( kind::AND, reason, NodeManager::currentNM()->mkNode(kind::EQUAL, d_mem_rel, ei->d_tc.get() ) );
- }
- Node new_membership = NodeManager::currentNM()->mkNode( kind::MEMBER, RelsUtils::constructPair( d_mem_rel, d_mem_fst, new_mem_snd ), ei->d_tc.get() );
- sendMergeInfer( new_membership, reason, "TCLOSURE-UP II" );
- }
- if( areEqual( new_mem_snd, d_mem_fst ) ) {
- Node reason = NodeManager::currentNM()->mkNode( kind::AND, new_mem_exp, d_mem_exp );
- reason = NodeManager::currentNM()->mkNode( kind::AND, reason, NodeManager::currentNM()->mkNode(kind::EQUAL, new_mem_snd, d_mem_fst ) );
- if( new_mem_rel != ei->d_tc.get() ) {
- reason = NodeManager::currentNM()->mkNode( kind::AND, reason, NodeManager::currentNM()->mkNode(kind::EQUAL, new_mem_rel, ei->d_tc.get() ) );
- }
- if( d_mem_rel != ei->d_tc.get() ) {
- reason = NodeManager::currentNM()->mkNode( kind::AND, reason, NodeManager::currentNM()->mkNode(kind::EQUAL, d_mem_rel, ei->d_tc.get() ) );
- }
- Node new_membership = NodeManager::currentNM()->mkNode( kind::MEMBER, RelsUtils::constructPair( d_mem_rel, new_mem_fst, d_mem_snd ), ei->d_tc.get() );
- sendMergeInfer( new_membership, reason, "TCLOSURE-UP II" );
- }
- }
- }
-
-
- void TheorySetsRels::doPendingMerge() {
- for( NodeList::const_iterator itr = d_pending_merge.begin(); itr != d_pending_merge.end(); itr++ ) {
- if( !holds(*itr) ) {
- if( d_lemmas_produced.find(*itr)==d_lemmas_produced.end() ) {
- Trace("rels-std-lemma") << "[std-sets-rels-lemma] Send out a merge fact as lemma: "
- << *itr << std::endl;
- d_sets_theory.d_out->lemma( *itr );
- d_lemmas_produced.insert(*itr);
- }
- }
- }
- }
-
- // t1 and t2 can be both relations
- // or t1 is a tuple, t2 is a transposed relation
- void TheorySetsRels::sendInferTranspose( Node t1, Node t2, Node exp ) {
- Assert( t2.getKind() == kind::TRANSPOSE );
-
- if( isRel(t1) && isRel(t2) ) {
- Assert(t1.getKind() == kind::TRANSPOSE);
- sendMergeInfer(NodeManager::currentNM()->mkNode(kind::EQUAL, t1[0], t2[0]), exp, "Transpose-Equal");
- return;
- }
- sendMergeInfer(NodeManager::currentNM()->mkNode(kind::MEMBER, RelsUtils::reverseTuple(t1), t2[0]), exp, "Transpose-Rule");
- }
-
- void TheorySetsRels::sendMergeInfer( Node fact, Node reason, const char * c ) {
- if( !holds( fact ) ) {
- Node lemma = NodeManager::currentNM()->mkNode( kind::IMPLIES, reason, fact);
- d_pending_merge.push_back(lemma);
- Trace("rels-std") << "[std-rels-lemma] Generate a lemma by applying " << c
- << ": " << lemma << std::endl;
- }
- }
-
- void TheorySetsRels::sendInferProduct( Node member, Node pt_rel, Node exp ) {
- Assert( pt_rel.getKind() == kind::PRODUCT );
-
- std::vector<Node> r1_element;
- std::vector<Node> r2_element;
- Node r1 = pt_rel[0];
- Node r2 = pt_rel[1];
- Datatype dt = r1.getType().getSetElementType().getDatatype();
- unsigned int i = 0;
- unsigned int s1_len = r1.getType().getSetElementType().getTupleLength();
- unsigned int tup_len = pt_rel.getType().getSetElementType().getTupleLength();
-
- r1_element.push_back(Node::fromExpr(dt[0].getConstructor()));
- for( ; i < s1_len; ++i ) {
- r1_element.push_back( RelsUtils::nthElementOfTuple( member, i ) );
- }
-
- dt = r2.getType().getSetElementType().getDatatype();
- r2_element.push_back( Node::fromExpr( dt[0].getConstructor() ) );
- for( ; i < tup_len; ++i ) {
- r2_element.push_back( RelsUtils::nthElementOfTuple(member, i) );
- }
-
- Node tuple_1 = NodeManager::currentNM()->mkNode( kind::APPLY_CONSTRUCTOR, r1_element );
- Node tuple_2 = NodeManager::currentNM()->mkNode( kind::APPLY_CONSTRUCTOR, r2_element );
- sendMergeInfer( NodeManager::currentNM()->mkNode(kind::MEMBER, tuple_1, r1), exp, "Product-Split" );
- sendMergeInfer( NodeManager::currentNM()->mkNode(kind::MEMBER, tuple_2, r2), exp, "Product-Split" );
- }
-
- TheorySetsRels::EqcInfo* TheorySetsRels::getOrMakeEqcInfo( Node n, bool doMake ){
- std::map< Node, EqcInfo* >::iterator eqc_i = d_eqc_info.find( n );
- if( eqc_i == d_eqc_info.end() ){
- if( doMake ){
- EqcInfo* ei;
- if( eqc_i!=d_eqc_info.end() ){
- ei = eqc_i->second;
- }else{
- ei = new EqcInfo(d_sets_theory.getSatContext());
- d_eqc_info[n] = ei;
- }
- if( n.getKind() == kind::TRANSPOSE ){
- ei->d_tp = n;
- } else if( n.getKind() == kind::PRODUCT ) {
- ei->d_pt = n;
- } else if( n.getKind() == kind::TCLOSURE ) {
- ei->d_tc = n;
- }
- return ei;
- }else{
- return NULL;
- }
- }else{
- return (*eqc_i).second;
- }
- }
-
- void TheorySetsRels::printNodeMap(const char* fst,
- const char* snd,
- const NodeMap& map)
+ void TheorySetsRels::sendInfer(Node fact, Node reason, const char* c)
{
- for (const auto& key_data : map)
- {
- Trace("rels-debug") << fst << " " << key_data.first << " " << snd << " "
- << key_data.second << std::endl;
- }
+ Trace("rels-lemma") << "Rels::lemma " << fact << " from " << reason
+ << " by " << c << std::endl;
+ Node lemma = NodeManager::currentNM()->mkNode(IMPLIES, reason, fact);
+ d_pending.push_back(lemma);
}
}
}