return false;
}
+
+void TheoryEngineModelBuilder::addToTypeList( TypeNode tn, std::vector< TypeNode >& type_list,
+ std::map< TypeNode, bool >& visiting ){
+ if( std::find( type_list.begin(), type_list.end(), tn )==type_list.end() ){
+ if( visiting.find( tn )==visiting.end() ){
+ visiting[tn] = true;
+ /* This must make a recursive call on all types that are subterms of
+ * values of the current type.
+ * Note that recursive traversal here is over enumerated expressions
+ * (very low expression depth). */
+ if( tn.isArray() ){
+ addToTypeList( tn.getArrayIndexType(), type_list, visiting );
+ addToTypeList( tn.getArrayConstituentType(), type_list, visiting );
+ }else if( tn.isSet() ){
+ addToTypeList( tn.getSetElementType(), type_list, visiting );
+ }else if( tn.isDatatype() ){
+ const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype();
+ for( unsigned i=0; i<dt.getNumConstructors(); i++ ){
+ for( unsigned j=0; j<dt[i].getNumArgs(); j++ ){
+ TypeNode ctn = TypeNode::fromType( dt[i][j].getRangeType() );
+ addToTypeList( ctn, type_list, visiting );
+ }
+ }
+ }
+ Assert( std::find( type_list.begin(), type_list.end(), tn )==type_list.end() );
+ type_list.push_back( tn );
+ }
+ }
+}
+
bool TheoryEngineModelBuilder::buildModel(Model* m)
{
Trace("model-builder") << "TheoryEngineModelBuilder: buildModel" << std::endl;
}
typeConstSet.setTypeEnumeratorProperties( &tep );
}
- std::set< TypeNode > allTypes;
+ // AJR: build ordered list of types that ensures that base types are enumerated first.
+ // (I think) this is only strictly necessary for finite model finding + parametric types
+ // instantiated with uninterpreted sorts, but is probably a good idea to do in general
+ // since it leads to models with smaller term sizes.
+ std::vector< TypeNode > type_list;
eqcs_i = eq::EqClassesIterator(tm->d_equalityEngine);
for ( ; !eqcs_i.isFinished(); ++eqcs_i) {
else if (!rep.isNull()) {
assertedReps[eqc] = rep;
typeRepSet.add(eqct.getBaseType(), eqc);
- allTypes.insert(eqct.getBaseType());
+ std::map< TypeNode, bool > visiting;
+ addToTypeList(eqct.getBaseType(), type_list, visiting);
}
else {
typeNoRepSet.add(eqct, eqc);
- allTypes.insert(eqct);
+ std::map< TypeNode, bool > visiting;
+ addToTypeList(eqct, type_list, visiting);
}
}
Trace("model-builder") << "Processing EC's..." << std::endl;
TypeSet::iterator it;
- set<TypeNode>::iterator type_it;
+ vector<TypeNode>::iterator type_it;
set<Node>::iterator i, i2;
bool changed, unassignedAssignable, assignOne = false;
set<TypeNode> evaluableSet;
evaluableSet.clear();
// Iterate over all types we've seen
- for (type_it = allTypes.begin(); type_it != allTypes.end(); ++type_it) {
+ for (type_it = type_list.begin(); type_it != type_list.end(); ++type_it) {
TypeNode t = *type_it;
TypeNode tb = t.getBaseType();
set<Node>* noRepSet = typeNoRepSet.getSet(t);
// 2. there are no terms that share teh same base type that are unevaluated evaluable terms
// Alternatively, if 2 or 3 don't hold but we are in a special deadlock-breaking mode where assignOne is true, go ahead and make one assignment
changed = false;
- for (it = typeNoRepSet.begin(); it != typeNoRepSet.end(); ++it) {
- set<Node>& noRepSet = TypeSet::getSet(it);
+ //must iterate over the ordered type list to ensure that we do not enumerate values with subterms
+ // having types that we are currently enumerating (when possible)
+ // for example, this ensures we enumerate uninterpreted sort U before (List of U) and (Array U U)
+ // however, it does not break cyclic type dependencies for mutually recursive datatypes, but this is handled
+ // by recording all subterms of enumerated values in TypeSet::addSubTerms.
+ for (type_it = type_list.begin(); type_it != type_list.end(); ++type_it) {
+ TypeNode t = *type_it;
+ // continue if there are no more equivalence classes of this type to assign
+ std::set<Node>* noRepSetPtr = typeNoRepSet.getSet( t );
+ if( noRepSetPtr==NULL ){
+ continue;
+ }
+ set<Node>& noRepSet = *noRepSetPtr;
if (noRepSet.empty()) {
continue;
}
- TypeNode t = TypeSet::getType(it);
-
+
//get properties of this type
bool isCorecursive = false;
if( t.isDatatype() ){
TypeToTypeEnumMap d_teMap;
TypeEnumeratorProperties * d_tep;
- public:
+ /* Note that recursive traversal here is over enumerated expressions
+ * (very low expression depth). */
+ void addSubTerms(TNode n, std::map< TNode, bool >& visited, bool topLevel=true){
+ if( visited.find( n )==visited.end() ){
+ visited[n] = true;
+ if( !topLevel ){
+ add(n.getType(), n);
+ }
+ for( unsigned i=0; i<n.getNumChildren(); i++ ){
+ addSubTerms( n[i], visited, false );
+ }
+ }
+ }
+public:
TypeSet() : d_tep(NULL) {}
~TypeSet() {
iterator it;
n = **te;
}
s->insert(n);
+ // add all subterms of n to this set as well
+ // this is necessary for parametric types whose values are constructed from other types
+ // to ensure that we do not enumerate subterms of other previous enumerated values
+ std::map< TNode, bool > visited;
+ addSubTerms(n, visited);
++(*te);
return n;
}
bool isAssignable(TNode n);
void checkTerms(TNode n, TheoryModel* tm, NodeSet& cache);
void assignConstantRep( TheoryModel* tm, Node eqc, Node const_rep );
+ void addToTypeList( TypeNode tn, std::vector< TypeNode >& type_list, std::map< TypeNode, bool >& visiting );
/** is v an excluded codatatype value */
bool isExcludedCdtValue( Node v, std::set<Node>* repSet, std::map< Node, Node >& assertedReps, Node eqc );
bool isCdtValueMatch( Node v, Node r, Node eqc, Node& eqc_m );