void 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_thss->getSatContext() );
+ d_nodes[n] = new RegionNodeInfo(d_cf->d_state.getSatContext());
}
d_nodes[n]->setValid(valid);
d_reps_size = d_reps_size + ( valid ? 1 : -1 );
}
SortModel::SortModel(Node n,
- context::Context* c,
- context::UserContext* u,
+ TheoryState& state,
+ TheoryInferenceManager& im,
CardinalityExtension* thss)
: d_type(n.getType()),
+ d_state(state),
+ d_im(im),
d_thss(thss),
- d_regions_index(c, 0),
- d_regions_map(c),
- d_split_score(c),
- d_disequalities_index(c, 0),
- d_reps(c, 0),
- d_conflict(c, false),
- d_cardinality(c, 1),
- d_hasCard(c, false),
- d_maxNegCard(c, 0),
- d_initialized(u, false),
- d_lemma_cache(u),
+ d_regions_index(d_state.getSatContext(), 0),
+ d_regions_map(d_state.getSatContext()),
+ d_split_score(d_state.getSatContext()),
+ d_disequalities_index(d_state.getSatContext(), 0),
+ d_reps(d_state.getSatContext(), 0),
+ d_cardinality(d_state.getSatContext(), 1),
+ d_hasCard(d_state.getSatContext(), false),
+ d_maxNegCard(d_state.getSatContext(), 0),
+ d_initialized(d_state.getUserContext(), false),
d_c_dec_strat(nullptr)
{
d_cardinality_term = n;
// We are guaranteed that the decision manager is ready since we
// construct this module during TheoryUF::finishInit.
d_c_dec_strat.reset(new CardinalityDecisionStrategy(
- n, c, thss->getTheory()->getValuation()));
+ n, d_state.getSatContext(), thss->getTheory()->getValuation()));
}
}
}
/** initialize */
-void SortModel::initialize( OutputChannel* out ){
+void SortModel::initialize()
+{
if (d_c_dec_strat.get() != nullptr && !d_initialized)
{
d_initialized = true;
/** new node */
void SortModel::newEqClass( Node n ){
- if( !d_conflict ){
+ if (!d_state.isInConflict())
+ {
if( d_regions_map.find( n )==d_regions_map.end() ){
// Must generate totality axioms for every cardinality we have
// allocated thus far.
for( std::map< int, Node >::iterator it = d_cardinality_literal.begin();
it != d_cardinality_literal.end(); ++it ){
if( applyTotality( it->first ) ){
- addTotalityAxiom( n, it->first, &d_thss->getOutputChannel() );
+ addTotalityAxiom(n, it->first);
}
}
if( options::ufssTotality() ){
d_regions[ d_regions_index ]->setValid(true);
Assert(d_regions[d_regions_index]->getNumReps() == 0);
}else{
- d_regions.push_back( new Region( this, d_thss->getSatContext() ) );
+ d_regions.push_back(new Region(this, d_state.getSatContext()));
}
d_regions[ d_regions_index ]->addRep( n );
d_regions_index = d_regions_index + 1;
/** merge */
void SortModel::merge( Node a, Node b ){
- if( !d_conflict ){
+ if (!d_state.isInConflict())
+ {
if( options::ufssTotality() ){
if( d_regions_map[b]==-1 ){
d_regions_map[a] = -1;
/** assert terms are disequal */
void SortModel::assertDisequal( Node a, Node b, Node reason ){
- if( !d_conflict ){
+ if (!d_state.isInConflict())
+ {
if( options::ufssTotality() ){
//do nothing
}else{
}
/** check */
-void SortModel::check( Theory::Effort level, OutputChannel* out ){
+void SortModel::check(Theory::Effort level)
+{
Assert(options::ufssMode() == options::UfssMode::FULL);
- if( level>=Theory::EFFORT_STANDARD && d_hasCard && !d_conflict ){
+ if (level >= Theory::EFFORT_STANDARD && d_hasCard && !d_state.isInConflict())
+ {
Debug("uf-ss") << "CardinalityExtension: Check " << level << " " << d_type
<< std::endl;
if( level==Theory::EFFORT_FULL ){
std::vector< Node > clique;
if( d_regions[i]->check( level, d_cardinality, clique ) ){
//add clique lemma
- addCliqueLemma( clique, out );
+ addCliqueLemma(clique);
return;
}else{
Trace("uf-ss-debug") << "No clique in Region #" << i << std::endl;
//see if we have any recommended splits from large regions
for( int i=0; i<(int)d_regions_index; i++ ){
if( d_regions[i]->valid() && d_regions[i]->getNumReps()>d_cardinality ){
-
- int sp = addSplit( d_regions[i], out );
+ int sp = addSplit(d_regions[i]);
if( sp==1 ){
addedLemma = true;
#ifdef ONE_SPLIT_REGION
break;
#endif
}else if( sp==-1 ){
- check( level, out );
+ check(level);
return;
}
}
}
if( recheck ){
Trace("uf-ss-debug") << "Must recheck." << std::endl;
- check( level, out );
+ check(level);
}
}
}
d_initialized = false;
}
-void SortModel::propagate( Theory::Effort level, OutputChannel* out ){
-
-}
-
int SortModel::getNumDisequalitiesToRegion( Node n, int ri ){
int ni = d_regions_map[n];
int counter = 0;
}
}
-void SortModel::assertCardinality( OutputChannel* out, int c, bool val ){
- if( !d_conflict ){
+void SortModel::assertCardinality(int c, bool val)
+{
+ if (!d_state.isInConflict())
+ {
Trace("uf-ss-assert")
<< "Assert cardinality " << d_type << " " << c << " " << val
<< " level = "
if( !prevHasCard || c<d_cardinality ){
d_cardinality = c;
simpleCheckCardinality();
- if( d_thss->d_conflict.get() ){
+ if (d_state.isInConflict())
+ {
return;
}
}
for( int i=0; i<(int)d_regions_index; i++ ){
if( d_regions[i]->valid() ){
checkRegion( i );
- if( d_conflict ){
+ if (d_state.isInConflict())
+ {
return;
}
}
std::vector< Node > clique;
if( d_regions[ri]->check( Theory::EFFORT_STANDARD, d_cardinality, clique ) ){
//explain clique
- addCliqueLemma( clique, &d_thss->getOutputChannel() );
+ addCliqueLemma(clique);
}
}
}
d_regions_map[n] = ri;
}
-int SortModel::addSplit( Region* r, OutputChannel* out ){
+int SortModel::addSplit(Region* r)
+{
Node s;
if( r->hasSplits() ){
//take the first split you find
//Notice() << "*** Split on " << s << std::endl;
//split on the equality s
Node lem = NodeManager::currentNM()->mkNode( kind::OR, ss, ss.negate() );
- if( doSendLemma( lem ) ){
+ // send lemma, with caching
+ if (d_im.lemma(lem))
+ {
Trace("uf-ss-lemma") << "*** Split on " << s << std::endl;
//tell the sat solver to explore the equals branch first
- out->requirePhase( ss, true );
+ d_im.requirePhase(ss, true);
++( d_thss->d_statistics.d_split_lemmas );
}
return 1;
}
}
-
-void SortModel::addCliqueLemma( std::vector< Node >& clique, OutputChannel* out ){
+void SortModel::addCliqueLemma(std::vector<Node>& clique)
+{
Assert(d_hasCard);
Assert(d_cardinality > 0);
while( clique.size()>size_t(d_cardinality+1) ){
}
eqs.push_back(d_cardinality_literal[d_cardinality].notNode());
Node lem = NodeManager::currentNM()->mkNode(OR, eqs);
- if (doSendLemma(lem))
+ // send lemma, with caching
+ if (d_im.lemma(lem))
{
Trace("uf-ss-lemma") << "*** Add clique lemma " << lem << std::endl;
++(d_thss->d_statistics.d_clique_lemmas);
}
}
-void SortModel::addTotalityAxiom( Node n, int cardinality, OutputChannel* out ){
+void SortModel::addTotalityAxiom(Node n, int cardinality)
+{
if( std::find( d_totality_terms[0].begin(), d_totality_terms[0].end(), n )==d_totality_terms[0].end() ){
if( std::find( d_totality_lems[n].begin(), d_totality_lems[n].end(), cardinality ) == d_totality_lems[n].end() ){
NodeManager* nm = NodeManager::currentNM();
Node ax = eqs.size()==1 ? eqs[0] : NodeManager::currentNM()->mkNode( OR, eqs );
Node lem = NodeManager::currentNM()->mkNode( IMPLIES, eq, ax );
Trace("uf-ss-lemma") << "*** Add (canonicity) totality axiom " << lem << std::endl;
- d_thss->getOutputChannel().lemma( lem );
+ d_im.lemma(lem, LemmaProperty::NONE, false);
}
}
}
Node lem = NodeManager::currentNM()->mkNode( IMPLIES, cardLit, ax );
Trace("uf-ss-lemma") << "*** Add totality axiom " << lem << std::endl;
//send as lemma to the output channel
- d_thss->getOutputChannel().lemma( lem );
+ d_im.lemma(lem, LemmaProperty::NONE, false);
++( d_thss->d_statistics.d_totality_lemmas );
}
}
Node lem = NodeManager::currentNM()->mkNode( AND, getCardinalityLiteral( d_cardinality.get() ),
getCardinalityLiteral( d_maxNegCard.get() ).negate() );
Trace("uf-ss-lemma") << "*** Simple cardinality conflict : " << lem << std::endl;
- d_thss->getOutputChannel().conflict( lem );
- d_thss->d_conflict.set( true );
- }
-}
-
-bool SortModel::doSendLemma( Node lem ) {
- if( d_lemma_cache.find( lem )==d_lemma_cache.end() ){
- d_lemma_cache[lem] = true;
- d_thss->getOutputChannel().lemma( lem );
- return true;
- }else{
- return false;
+ d_im.conflict(lem);
}
}
Node cl = getCardinalityLiteral( d_maxNegCard );
Node lem = NodeManager::currentNM()->mkNode( OR, cl, NodeManager::currentNM()->mkNode( AND, force_cl ) );
Trace("uf-ss-lemma") << "*** Enforce negative cardinality constraint lemma : " << lem << std::endl;
- d_thss->getOutputChannel().lemma( lem );
+ d_im.lemma(lem, LemmaProperty::NONE, false);
return false;
}
}
Node lem = var.eqNode(d_totality_terms[0][i - 1]).notNode();
Trace("uf-ss-lemma") << "Totality distinctness lemma : " << lem
<< std::endl;
- d_thss->getOutputChannel().lemma(lem);
+ d_im.lemma(lem, LemmaProperty::NONE, false);
}
// must send totality axioms for each existing term
for (NodeIntMap::iterator it = d_regions_map.begin();
it != d_regions_map.end();
++it)
{
- addTotalityAxiom((*it).first, c, &d_thss->getOutputChannel());
+ addTotalityAxiom((*it).first, c);
}
return lit;
}
-CardinalityExtension::CardinalityExtension(context::Context* c,
- context::UserContext* u,
- OutputChannel& out,
+CardinalityExtension::CardinalityExtension(TheoryState& state,
+ TheoryInferenceManager& im,
TheoryUF* th)
- : d_out(&out),
+ : d_state(state),
+ d_im(im),
d_th(th),
- d_conflict(c, false),
d_rep_model(),
- d_min_pos_com_card(c, -1),
+ d_min_pos_com_card(state.getSatContext(), -1),
d_cc_dec_strat(nullptr),
- d_initializedCombinedCardinality(u, false),
- d_card_assertions_eqv_lemma(u),
- d_min_pos_tn_master_card(c, -1),
- d_rel_eqc(c)
+ d_initializedCombinedCardinality(state.getUserContext(), false),
+ d_card_assertions_eqv_lemma(state.getUserContext()),
+ d_min_pos_tn_master_card(state.getSatContext(), -1),
+ d_rel_eqc(state.getSatContext())
{
if (options::ufssMode() == options::UfssMode::FULL && options::ufssFairness())
{
// Register the strategy with the decision manager of the theory.
// We are guaranteed that the decision manager is ready since we
// construct this module during TheoryUF::finishInit.
- d_cc_dec_strat.reset(
- new CombinedCardinalityDecisionStrategy(c, th->getValuation()));
+ d_cc_dec_strat.reset(new CombinedCardinalityDecisionStrategy(
+ state.getSatContext(), th->getValuation()));
}
}
return nullptr;
}
-/** get default sat context */
-context::Context* CardinalityExtension::getSatContext()
-{
- return d_th->getSatContext();
-}
-
-/** get default output channel */
-OutputChannel& CardinalityExtension::getOutputChannel()
-{
- return d_th->getOutputChannel();
-}
-
/** ensure eqc */
void CardinalityExtension::ensureEqc(SortModel* c, Node a)
{
}
}
Trace("uf-ss-com-card-debug") << "...assert cardinality" << std::endl;
- d_rep_model[tn]->assertCardinality( d_out, nCard, polarity );
+ d_rep_model[tn]->assertCardinality(nCard, polarity);
//check if combined cardinality is violated
checkCombinedCardinality();
}else{
Node eqv_lit = NodeManager::currentNM()->mkNode( CARDINALITY_CONSTRAINT, ct, lit[1] );
eqv_lit = lit.eqNode( eqv_lit );
Trace("uf-ss-lemma") << "*** Cardinality equiv lemma : " << eqv_lit << std::endl;
- getOutputChannel().lemma( eqv_lit );
+ d_im.lemma(eqv_lit, LemmaProperty::NONE, false);
d_card_assertions_eqv_lemma[lit] = true;
}
}
if( lit.getKind()==CARDINALITY_CONSTRAINT || lit.getKind()==COMBINED_CARDINALITY_CONSTRAINT ){
// cardinality constraint from user input, set incomplete
Trace("uf-ss") << "Literal " << lit << " not handled when uf ss mode is not FULL, set incomplete." << std::endl;
- d_out->setIncomplete();
+ d_im.setIncomplete();
}
}
Trace("uf-ss") << "Assert: done " << n << " " << isDecision << std::endl;
/** check */
void CardinalityExtension::check(Theory::Effort level)
{
- if( !d_conflict ){
+ if (!d_state.isInConflict())
+ {
if (options::ufssMode() == options::UfssMode::FULL)
{
Trace("uf-ss-solver")
}
}
for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
- it->second->check( level, d_out );
- if( it->second->isConflict() ){
- d_conflict = true;
+ it->second->check(level);
+ if (d_state.isInConflict())
+ {
break;
}
}
Node eq = Rewriter::rewrite( a.eqNode( b ) );
Node lem = NodeManager::currentNM()->mkNode( kind::OR, eq, eq.negate() );
Trace("uf-ss-lemma") << "*** Split (no-minimal) : " << lem << std::endl;
- d_out->lemma( lem );
- d_out->requirePhase( eq, true );
+ d_im.lemma(lem, LemmaProperty::NONE, false);
+ d_im.requirePhase(eq, true);
type_proc[tn] = true;
break;
}
d_initializedCombinedCardinality = false;
for( std::map< TypeNode, SortModel* >::iterator it = d_rep_model.begin(); it != d_rep_model.end(); ++it ){
it->second->presolve();
- it->second->initialize( d_out );
+ it->second->initialize();
}
}
SortModel* rm = NULL;
if( tn.isSort() ){
Trace("uf-ss-register") << "Create sort model " << tn << "." << std::endl;
- rm = new SortModel( n, d_th->getSatContext(), d_th->getUserContext(), this );
- //getOutputChannel().lemma( n.eqNode( rm->getCardinalityTerm() ) );
- }else{
- /*
- if( tn==NodeManager::currentNM()->integerType() || tn==NodeManager::currentNM()->realType() ){
- Debug("uf-ss-na") << "Error: Cannot perform finite model finding on arithmetic quantifier";
- Debug("uf-ss-na") << " (" << f << ")";
- Debug("uf-ss-na") << std::endl;
- Unimplemented() << "Cannot perform finite model finding on arithmetic quantifier";
- }else if( tn.isDatatype() ){
- Debug("uf-ss-na") << "Error: Cannot perform finite model finding on datatype quantifier";
- Debug("uf-ss-na") << " (" << f << ")";
- Debug("uf-ss-na") << std::endl;
- Unimplemented() << "Cannot perform finite model finding on datatype quantifier";
- }
- */
+ rm = new SortModel(n, d_state, d_im, this);
}
if( rm ){
- rm->initialize( d_out );
+ rm->initialize();
d_rep_model[tn] = rm;
//d_rep_model_init[tn] = true;
}
}else{
//ensure sort model is initialized
- it->second->initialize( d_out );
+ it->second->initialize();
}
}
}
<< " : " << cf << std::endl;
Trace("uf-ss-com-card") << "*** Combined monotone cardinality conflict"
<< " : " << cf << std::endl;
- getOutputChannel().conflict( cf );
- d_conflict.set( true );
+ d_im.conflict(cf);
return;
}
}
<< std::endl;
Trace("uf-ss-com-card") << "*** Combined cardinality conflict : " << cf
<< std::endl;
- getOutputChannel().conflict( cf );
- d_conflict.set( true );
+ d_im.conflict(cf);
}
}
}
private:
/** the type this model is for */
TypeNode d_type;
+ /** Reference to the state object */
+ TheoryState& d_state;
+ /** Reference to the inference manager */
+ TheoryInferenceManager& d_im;
/** Pointer to the cardinality extension that owns this. */
CardinalityExtension* d_thss;
/** regions used to d_region_index */
/** move node n to region ri */
void moveNode( Node n, int ri );
/** allocate cardinality */
- void allocateCardinality( OutputChannel* out );
+ void allocateCardinality();
/**
* Add splits. Returns
* 0 = no split,
* -1 = entailed disequality added, or
* 1 = split added.
*/
- int addSplit( Region* r, OutputChannel* out );
+ int addSplit(Region* r);
/** add clique lemma */
- void addCliqueLemma( std::vector< Node >& clique, OutputChannel* out );
+ void addCliqueLemma(std::vector<Node>& clique);
/** add totality axiom */
- void addTotalityAxiom( Node n, int cardinality, OutputChannel* out );
- /** Are we in conflict */
- context::CDO<bool> d_conflict;
+ void addTotalityAxiom(Node n, int cardinality);
/** cardinality */
context::CDO< int > d_cardinality;
/** cardinality lemma term */
std::vector< Node > d_fresh_aloc_reps;
/** whether we are initialized */
context::CDO< bool > d_initialized;
- /** cache for lemmas */
- NodeBoolMap d_lemma_cache;
/** apply totality */
bool applyTotality( int cardinality );
/** simple check cardinality */
void simpleCheckCardinality();
- bool doSendLemma( Node lem );
-
public:
SortModel(Node n,
- context::Context* c,
- context::UserContext* u,
+ TheoryState& state,
+ TheoryInferenceManager& im,
CardinalityExtension* thss);
virtual ~SortModel();
/** initialize */
- void initialize( OutputChannel* out );
+ void initialize();
/** new node */
void newEqClass( Node n );
/** merge */
/** are disequal */
bool areDisequal( Node a, Node b );
/** check */
- void check( Theory::Effort level, OutputChannel* out );
+ void check(Theory::Effort level);
/** presolve */
void presolve();
- /** propagate */
- void propagate( Theory::Effort level, OutputChannel* out );
/** assert cardinality */
- void assertCardinality( OutputChannel* out, int c, bool val );
- /** is in conflict */
- bool isConflict() { return d_conflict; }
+ void assertCardinality(int c, bool val);
/** get cardinality */
int getCardinality() { return d_cardinality; }
/** has cardinality */
}; /** class SortModel */
public:
- CardinalityExtension(context::Context* c,
- context::UserContext* u,
- OutputChannel& out,
+ CardinalityExtension(TheoryState& state,
+ TheoryInferenceManager& im,
TheoryUF* th);
~CardinalityExtension();
/** get theory */
TheoryUF* getTheory() { return d_th; }
/** get sort inference module */
SortInference* getSortInference();
- /** get default sat context */
- context::Context* getSatContext();
- /** get default output channel */
- OutputChannel& getOutputChannel();
/** new node */
void newEqClass( Node n );
/** merge */
void debugPrint( const char* c );
/** debug a model */
bool debugModel( TheoryModel* m );
- /** get is in conflict */
- bool isConflict() { return d_conflict; }
/** get cardinality for node */
int getCardinality( Node n );
/** get cardinality for type */
/** ensure eqc for all subterms of n */
void ensureEqcRec(Node n);
- /** The output channel used by this class. */
- OutputChannel* d_out;
+ /** Reference to the state object */
+ TheoryState& d_state;
+ /** Reference to the inference manager */
+ TheoryInferenceManager& d_im;
/** theory uf pointer */
TheoryUF* d_th;
- /** Are we in conflict */
- context::CDO<bool> d_conflict;
/** rep model structure, one for each type */
std::map<TypeNode, SortModel*> d_rep_model;