diff options
author | Andrew Reynolds <andrew.j.reynolds@gmail.com> | 2013-09-27 09:27:19 -0500 |
---|---|---|
committer | Andrew Reynolds <andrew.j.reynolds@gmail.com> | 2013-09-27 09:27:29 -0500 |
commit | e277b4d220a1d15ac32f6e4fc5f06e88f55b7f68 (patch) | |
tree | 2a56691dea81453e5f9ba42e859fdc6783fa1545 /src/theory/uf | |
parent | ccd1ca4c32e8a3eac8b18911a7b2d32b55203707 (diff) |
Add new symmetry breaking technique for finite model finding. Improvements to bounded integer quantifier instantiation.
Diffstat (limited to 'src/theory/uf')
-rw-r--r-- | src/theory/uf/options | 2 | ||||
-rw-r--r-- | src/theory/uf/theory_uf_strong_solver.cpp | 131 | ||||
-rw-r--r-- | src/theory/uf/theory_uf_strong_solver.h | 35 |
3 files changed, 132 insertions, 36 deletions
diff --git a/src/theory/uf/options b/src/theory/uf/options index 437e30e46..b9f60b83d 100644 --- a/src/theory/uf/options +++ b/src/theory/uf/options @@ -40,5 +40,7 @@ option ufssMinimalModel /--disable-uf-ss-min-model bool :default true option ufssCliqueSplits --uf-ss-clique-splits bool :default false use cliques instead of splitting on demand to shrink model +option ufssSymBreak --uf-ss-sym-break bool :default false + finite model finding symmetry breaking techniques endmodule diff --git a/src/theory/uf/theory_uf_strong_solver.cpp b/src/theory/uf/theory_uf_strong_solver.cpp index adcf78a86..82cd1f809 100644 --- a/src/theory/uf/theory_uf_strong_solver.cpp +++ b/src/theory/uf/theory_uf_strong_solver.cpp @@ -20,6 +20,8 @@ #include "theory/quantifiers/term_database.h" #include "theory/uf/options.h" #include "theory/model.h" +#include "theory/quantifiers/symmetry_breaking.h" + //#define ONE_SPLIT_REGION //#define DISABLE_QUICK_CLIQUE_CHECKS @@ -117,6 +119,10 @@ void StrongSolverTheoryUF::SortModel::Region::setEqual( Node a, Node b ){ if( options::ufssDiseqPropagation() ){ d_cf->d_thss->getDisequalityPropagator()->assertDisequal(a, n, Node::null()); } + if( options::ufssSymBreak() ){ + //d_cf->d_thss->getSymmetryBreaker()->assertDisequal( a, n ); + d_cf->d_thss->getSymmetryBreaker()->queueFact( a.eqNode( n ).negate() ); + } } setDisequal( b, n, t, false ); nr->setDisequal( n, b, t, false ); @@ -515,9 +521,15 @@ void StrongSolverTheoryUF::SortModel::merge( Node a, Node b ){ } d_reps = d_reps - 1; - if( options::ufssDiseqPropagation() && !d_conflict ){ - //notify the disequality propagator - d_thss->getDisequalityPropagator()->merge(a, b); + if( !d_conflict ){ + if( options::ufssDiseqPropagation() ){ + //notify the disequality propagator + d_thss->getDisequalityPropagator()->merge(a, b); + } + if( options::ufssSymBreak() ){ + //d_thss->getSymmetryBreaker()->merge(a, b); + d_thss->getSymmetryBreaker()->queueFact( a.eqNode( b ) ); + } } } } @@ -565,9 +577,15 @@ void StrongSolverTheoryUF::SortModel::assertDisequal( Node a, Node b, Node reaso checkRegion( bi ); } - if( options::ufssDiseqPropagation() && !d_conflict ){ - //notify the disequality propagator - d_thss->getDisequalityPropagator()->assertDisequal(a, b, Node::null()); + if( !d_conflict ){ + if( options::ufssDiseqPropagation() ){ + //notify the disequality propagator + d_thss->getDisequalityPropagator()->assertDisequal(a, b, Node::null()); + } + if( options::ufssSymBreak() ){ + //d_thss->getSymmetryBreaker()->assertDisequal(a, b); + d_thss->getSymmetryBreaker()->queueFact( a.eqNode( b ).negate() ); + } } } } @@ -670,7 +688,7 @@ void StrongSolverTheoryUF::SortModel::check( Theory::Effort level, OutputChannel for( int i=0; i<(int)d_regions_index; i++ ){ if( d_regions[i]->d_valid ){ Node op = d_regions[i]->d_nodes.begin()->first; - int sort_id = d_thss->getTheory()->getQuantifiersEngine()->getTheoryEngine()->getSortInference()->getSortId(op); + int sort_id = d_thss->getSortInference()->getSortId(op); if( sortsFound.find( sort_id )!=sortsFound.end() ){ combineRegions( sortsFound[sort_id], i ); recheck = true; @@ -979,17 +997,32 @@ void StrongSolverTheoryUF::SortModel::moveNode( Node n, int ri ){ void StrongSolverTheoryUF::SortModel::allocateCardinality( OutputChannel* out ){ if( d_aloc_cardinality>0 ){ Trace("uf-ss-fmf") << "No model of size " << d_aloc_cardinality << " exists for type " << d_type << " in this branch" << std::endl; - if( Trace.isOn("uf-ss-cliques") ){ - Trace("uf-ss-cliques") << "Cliques of size " << (d_aloc_cardinality+1) << " : " << std::endl; - for( size_t i=0; i<d_cliques[ d_aloc_cardinality ].size(); i++ ){ - Trace("uf-ss-cliques") << " "; - for( size_t j=0; j<d_cliques[ d_aloc_cardinality ][i].size(); j++ ){ - Trace("uf-ss-cliques") << d_cliques[ d_aloc_cardinality ][i][j] << " "; - } - Trace("uf-ss-cliques") << std::endl; + } + if( Trace.isOn("uf-ss-cliques") ){ + Trace("uf-ss-cliques") << "Cliques of size " << (d_aloc_cardinality+1) << " for " << d_type << " : " << std::endl; + for( size_t i=0; i<d_cliques[ d_aloc_cardinality ].size(); i++ ){ + Trace("uf-ss-cliques") << " "; + for( size_t j=0; j<d_cliques[ d_aloc_cardinality ][i].size(); j++ ){ + Trace("uf-ss-cliques") << d_cliques[ d_aloc_cardinality ][i][j] << " "; } + Trace("uf-ss-cliques") << std::endl; + } + } + /* + if( options::ufssSymBreak() ){ + std::vector< Node > reps; + getRepresentatives( reps ); + if( d_aloc_cardinality>0 ){ + d_thss->getSymmetryBreaker()->allocateCardinality( out, d_type, d_aloc_cardinality+1, d_cliques[ d_aloc_cardinality ], reps ); + }else{ + std::vector< Node > clique; + clique.push_back( d_cardinality_term ); + std::vector< std::vector< Node > > cliques; + cliques.push_back( clique ); + d_thss->getSymmetryBreaker()->allocateCardinality( out, d_type, 1, cliques, reps ); } } + */ d_aloc_cardinality = d_aloc_cardinality + 1; //check for abort case @@ -1094,7 +1127,7 @@ bool StrongSolverTheoryUF::SortModel::addSplit( Region* r, OutputChannel* out ){ Trace("uf-ss-lemma") << "*** Split on " << s << std::endl; if( options::sortInference()) { for( int i=0; i<2; i++ ){ - int si = d_thss->getTheory()->getQuantifiersEngine()->getTheoryEngine()->getSortInference()->getSortId( s[i] ); + int si = d_thss->getSortInference()->getSortId( s[i] ); Trace("uf-ss-split-si") << si << " "; } Trace("uf-ss-split-si") << std::endl; @@ -1122,10 +1155,10 @@ void StrongSolverTheoryUF::SortModel::addCliqueLemma( std::vector< Node >& cliqu clique.pop_back(); } //debugging information - if( Trace.isOn("uf-ss-cliques") ){ + if( options::ufssSymBreak() ){ std::vector< Node > clique_vec; clique_vec.insert( clique_vec.begin(), clique.begin(), clique.end() ); - d_cliques[ d_cardinality ].push_back( clique_vec ); + addClique( d_cardinality, clique_vec ); } if( options::ufssSimpleCliques() && !options::ufssExplainedCliques() ){ //add as lemma @@ -1273,7 +1306,7 @@ void StrongSolverTheoryUF::SortModel::addTotalityAxiom( Node n, int cardinality, Node cardLit = d_cardinality_literal[ cardinality ]; int sort_id = 0; if( options::sortInference() ){ - sort_id = d_thss->getTheory()->getQuantifiersEngine()->getTheoryEngine()->getSortInference()->getSortId(n); + sort_id = d_thss->getSortInference()->getSortId(n); } Trace("uf-ss-totality") << "Add totality lemma for " << n << " " << cardinality << ", sort id is " << sort_id << std::endl; int use_cardinality = cardinality; @@ -1302,6 +1335,14 @@ void StrongSolverTheoryUF::SortModel::addTotalityAxiom( Node n, int cardinality, } } +void StrongSolverTheoryUF::SortModel::addClique( int c, std::vector< Node >& clique ) { + + if( d_clique_trie[c].add( clique ) ){ + d_cliques[ c ].push_back( clique ); + } +} + + /** apply totality */ bool StrongSolverTheoryUF::SortModel::applyTotality( int cardinality ){ return options::ufssTotality() || cardinality<=options::ufssTotalityLimited(); @@ -1379,22 +1420,16 @@ int StrongSolverTheoryUF::SortModel::getNumRegions(){ } void StrongSolverTheoryUF::SortModel::getRepresentatives( std::vector< Node >& reps ){ - //if( !options::ufssColoringSat() ){ - bool foundRegion = false; - for( int i=0; i<(int)d_regions_index; i++ ){ - //should not have multiple regions at this point - if( foundRegion ){ - Assert( !d_regions[i]->d_valid ); - } - if( d_regions[i]->d_valid ){ - //this is the only valid region - d_regions[i]->getRepresentatives( reps ); - foundRegion = true; - } + for( int i=0; i<(int)d_regions_index; i++ ){ + //should not have multiple regions at this point + //if( foundRegion ){ + // Assert( !d_regions[i]->d_valid ); + //} + if( d_regions[i]->d_valid ){ + //this is the only valid region + d_regions[i]->getRepresentatives( reps ); } - //}else{ - // Unimplemented("Build representatives for fmf region sat is not implemented"); - //} + } } StrongSolverTheoryUF::StrongSolverTheoryUF(context::Context* c, context::UserContext* u, OutputChannel& out, TheoryUF* th) : @@ -1415,6 +1450,15 @@ d_rep_model_init( c ) }else{ d_deq_prop = NULL; } + if( options::ufssSymBreak() ){ + d_sym_break = new SubsortSymmetryBreaker( th->getQuantifiersEngine(), c ); + }else{ + d_sym_break = NULL; + } +} + +SortInference* StrongSolverTheoryUF::getSortInference() { + return d_th->getQuantifiersEngine()->getTheoryEngine()->getSortInference(); } /** get default sat context */ @@ -1433,6 +1477,10 @@ void StrongSolverTheoryUF::newEqClass( Node n ){ if( c ){ Trace("uf-ss-solver") << "StrongSolverTheoryUF: New eq class " << n << " : " << n.getType() << std::endl; c->newEqClass( n ); + if( options::ufssSymBreak() ){ + //d_sym_break->newEqClass( n ); + d_sym_break->queueFact( n ); + } } } @@ -1539,6 +1587,10 @@ void StrongSolverTheoryUF::check( Theory::Effort level ){ break; } } + //check symmetry breaker + if( !d_conflict && options::ufssSymBreak() ){ + d_sym_break->check( level ); + } //disambiguate terms if necessary //if( !d_conflict && level==Theory::EFFORT_FULL && options::ufssColoringSat() ){ // Assert( d_term_amb!=NULL ); @@ -1644,6 +1696,14 @@ int StrongSolverTheoryUF::getCardinality( Node n ) { } } +int StrongSolverTheoryUF::getCardinality( TypeNode tn ) { + std::map< TypeNode, SortModel* >::iterator it = d_rep_model.find( tn ); + if( it!=d_rep_model.end() && it->second ){ + return it->second->getCardinality(); + } + return -1; +} + void StrongSolverTheoryUF::getRepresentatives( Node n, std::vector< Node >& reps ){ SortModel* c = getSortModel( n ); if( c ){ @@ -1698,6 +1758,7 @@ StrongSolverTheoryUF::Statistics::Statistics(): d_clique_lemmas("StrongSolverTheoryUF::Clique_Lemmas", 0), d_split_lemmas("StrongSolverTheoryUF::Split_Lemmas", 0), d_disamb_term_lemmas("StrongSolverTheoryUF::Disambiguate_Term_Lemmas", 0), + d_sym_break_lemmas("StrongSolverTheoryUF::Symmetry_Breaking_Lemmas", 0), d_totality_lemmas("StrongSolverTheoryUF::Totality_Lemmas", 0), d_max_model_size("StrongSolverTheoryUF::Max_Model_Size", 1) { @@ -1705,6 +1766,7 @@ StrongSolverTheoryUF::Statistics::Statistics(): StatisticsRegistry::registerStat(&d_clique_lemmas); StatisticsRegistry::registerStat(&d_split_lemmas); StatisticsRegistry::registerStat(&d_disamb_term_lemmas); + StatisticsRegistry::registerStat(&d_sym_break_lemmas); StatisticsRegistry::registerStat(&d_totality_lemmas); StatisticsRegistry::registerStat(&d_max_model_size); } @@ -1714,6 +1776,7 @@ StrongSolverTheoryUF::Statistics::~Statistics(){ StatisticsRegistry::unregisterStat(&d_clique_lemmas); StatisticsRegistry::unregisterStat(&d_split_lemmas); StatisticsRegistry::unregisterStat(&d_disamb_term_lemmas); + StatisticsRegistry::unregisterStat(&d_sym_break_lemmas); StatisticsRegistry::unregisterStat(&d_totality_lemmas); StatisticsRegistry::unregisterStat(&d_max_model_size); } diff --git a/src/theory/uf/theory_uf_strong_solver.h b/src/theory/uf/theory_uf_strong_solver.h index fa8d60b49..8e568444b 100644 --- a/src/theory/uf/theory_uf_strong_solver.h +++ b/src/theory/uf/theory_uf_strong_solver.h @@ -26,7 +26,13 @@ #include "util/statistics_registry.h" namespace CVC4 { + +class SortInference; + namespace theory { + +class SubsortSymmetryBreaker; + namespace uf { class TheoryUF; @@ -40,7 +46,6 @@ protected: typedef context::CDHashMap<Node, Node, NodeHashFunction> NodeNodeMap; 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 */ @@ -202,6 +207,23 @@ public: /** add totality axiom */ void addTotalityAxiom( Node n, int cardinality, OutputChannel* out ); private: + class NodeTrie { + std::map< Node, NodeTrie > d_children; + public: + bool add( std::vector< Node >& n, unsigned i = 0 ){ + Assert( i<n.size() ); + if( i==(n.size()-1) ){ + bool ret = d_children.find( n[i] )==d_children.end(); + d_children[n[i]].d_children.clear(); + return ret; + }else{ + return d_children[n[i]].add( n, i+1 ); + } + } + }; + std::map< int, NodeTrie > d_clique_trie; + void addClique( int c, std::vector< Node >& clique ); + private: /** Are we in conflict */ context::CDO<bool> d_conflict; /** cardinality */ @@ -286,6 +308,8 @@ private: TermDisambiguator* d_term_amb; /** disequality propagator */ DisequalityPropagator* d_deq_prop; + /** symmetry breaking techniques */ + SubsortSymmetryBreaker* d_sym_break; public: StrongSolverTheoryUF(context::Context* c, context::UserContext* u, OutputChannel& out, TheoryUF* th); ~StrongSolverTheoryUF() {} @@ -295,6 +319,10 @@ public: TermDisambiguator* getTermDisambiguator() { return d_term_amb; } /** disequality propagator */ DisequalityPropagator* getDisequalityPropagator() { return d_deq_prop; } + /** symmetry breaker */ + SubsortSymmetryBreaker* getSymmetryBreaker() { return d_sym_break; } + /** get sort inference module */ + SortInference* getSortInference(); /** get default sat context */ context::Context* getSatContext(); /** get default output channel */ @@ -336,8 +364,10 @@ public: TypeNode getCardinalityType( int i ) { return d_conf_types[i]; } /** get is in conflict */ bool isConflict() { return d_conflict; } - /** get cardinality for sort */ + /** get cardinality for node */ int getCardinality( Node n ); + /** get cardinality for type */ + int getCardinality( TypeNode tn ); /** get representatives */ void getRepresentatives( Node n, std::vector< Node >& reps ); /** minimize */ @@ -349,6 +379,7 @@ public: IntStat d_clique_lemmas; IntStat d_split_lemmas; IntStat d_disamb_term_lemmas; + IntStat d_sym_break_lemmas; IntStat d_totality_lemmas; IntStat d_max_model_size; Statistics(); |