void StatisicsPropertyintegration::setup() { m_char_type = new TypeNode("char_type"); m_char_property = new StatisticsProperty; m_char_property->setFlags(flag_class); m_char_type->addProperty("char_prop", m_char_property); m_char1 = new Entity("1", 1); m_char1->setType(m_char_type); m_char_property->install(m_char1, "char_prop"); m_char_property->apply(m_char1); m_char2 = new Entity("2", 2); m_char2->setType(m_char_type); m_char_property->install(m_char2, "char_prop"); m_char_property->apply(m_char2); }
bool TermEnumeration::isClosedEnumerableType(TypeNode tn) { std::unordered_map<TypeNode, bool, TypeNodeHashFunction>::iterator it = d_typ_closed_enum.find(tn); if (it == d_typ_closed_enum.end()) { d_typ_closed_enum[tn] = true; bool ret = true; if (tn.isArray() || tn.isSort() || tn.isCodatatype() || tn.isFunction()) { ret = false; } else if (tn.isSet()) { ret = isClosedEnumerableType(tn.getSetElementType()); } 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()); if (tn != ctn && !isClosedEnumerableType(ctn)) { ret = false; break; } } if (!ret) { break; } } } // other parametric sorts go here d_typ_closed_enum[tn] = ret; return ret; } else { return it->second; } }
void Entitytest::test_setAttr_type() { TestProperty * type_property = new TestProperty; type_property->data() = 17; type_property->flags() &= flag_class; m_type->addProperty("test_int_property", type_property); PropertyBase * pb = m_entity->setAttr("test_int_property", 24); ASSERT_NOT_NULL(pb); ASSERT_NOT_EQUAL(type_property, pb); ASSERT_TRUE((pb->flags() & flag_class) == 0); auto * int_property = dynamic_cast<TestProperty *>(pb); ASSERT_NOT_NULL(int_property); ASSERT_EQUAL(int_property->data(), 24); ASSERT_TRUE(!m_TestProperty_install_called); ASSERT_TRUE(m_TestProperty_apply_called); }
Node DatatypesEnumerator::getTermEnum( TypeNode tn, unsigned i ){ Node ret; if( i<d_terms[tn].size() ){ ret = d_terms[tn][i]; }else{ Debug("dt-enum-debug") << "get term enum " << tn << " " << i << std::endl; std::map< TypeNode, unsigned >::iterator it = d_te_index.find( tn ); unsigned tei; if( it==d_te_index.end() ){ //initialize child enumerator for type tei = d_children.size(); d_te_index[tn] = tei; if( tn.isDatatype() && d_has_debruijn ){ //must indicate that this is a child enumerator (do not normalize constants for it) DatatypesEnumerator * dte = new DatatypesEnumerator( tn, true ); d_children.push_back( TypeEnumerator( dte ) ); }else{ d_children.push_back( TypeEnumerator( tn ) ); } d_terms[tn].push_back( *d_children[tei] ); }else{ tei = it->second; } //enumerate terms until index is reached while( i>=d_terms[tn].size() ){ ++d_children[tei]; if( d_children[tei].isFinished() ){ Debug("dt-enum-debug") << "...fail term enum " << tn << " " << i << std::endl; return Node::null(); } d_terms[tn].push_back( *d_children[tei] ); } Debug("dt-enum-debug") << "...return term enum " << tn << " " << i << " : " << d_terms[tn][i] << std::endl; ret = d_terms[tn][i]; } return ret; }
TypeNode* TypeNameNode::getTypeNode(TemplateArguments* templateArguments) { //assert(0 == templateArguments || templateArguments->m_classTypeNode->isTemplateClassInstance()); assert(0 != m_startTypeNode); TypeNode* result = 0; if (0 == m_typeNode)// under template parameter { assert(templateArguments && m_startTypeNode && (m_startTypeNode->isTemplateParameter() || m_startTypeNode->isTypedef()) ); if (templateArguments->m_classTypeNode->isClass()) { return 0; } TypeNode* actualStartTypeNode = m_startTypeNode->getActualTypeNode(templateArguments); assert(actualStartTypeNode); std::vector<ScopeNameNode*> scopeNameNodes; m_scopeNameList->collectIdentifyNodes(scopeNameNodes); if (scopeNameNodes.size() == 1) { result = actualStartTypeNode; } else { scopeNameNodes.erase(scopeNameNodes.begin()); TypeNode* initialTypeTreeNode = 0; TypeNode* finalTypeTreeNode = 0; if (g_typeTree.findNodeByScopeNames(initialTypeTreeNode, finalTypeTreeNode, scopeNameNodes, actualStartTypeNode, templateArguments)) { assert(finalTypeTreeNode); result = finalTypeTreeNode; } } } else if (m_typeNode->isTemplateParameter()) { assert(templateArguments); result = templateArguments->findTypeNode(m_scopeNameList->m_scopeName->m_name->m_str); } else if (m_typeNode->isTemplateClass()) { assert(templateArguments); if (m_scopeNameList->m_scopeName->isTemplateForm()) { result = g_typeTree.findNodeByScopeName(m_scopeNameList->m_scopeName, m_typeNode->m_enclosing, templateArguments); } else { assert(m_scopeNameList->m_scopeName->m_name->m_str == templateArguments->m_className); result = templateArguments->m_classTypeNode; } } else if (m_typeNode->isUnderTemplateClass()) { assert(templateArguments); if (m_startTypeNode->isUnderTemplateClass()) { std::vector<TypeNode*> typeNodes; TypeNode* typeNode = m_typeNode; while (typeNode) { if (typeNode->isTemplateClass()) { break; } typeNodes.push_back(typeNode); typeNode = typeNode->m_enclosing; } assert(typeNode->isTemplateClass() && typeNode->m_name == templateArguments->m_className); typeNode = templateArguments->m_classTypeNode; auto it = typeNodes.rbegin(); auto end = typeNodes.rend(); for (; it != end; ++it) { TypeNode* tempTypeNode = *it; typeNode = typeNode->getChildNode(tempTypeNode->m_name); assert(typeNode); } if (typeNode->isTypedef()) { TypeNode* actualTypeNode = typeNode->getActualTypeNode(templateArguments); if (actualTypeNode->isTemplateParameter()) { typeNode = templateArguments->findTypeNode(actualTypeNode->m_name); assert(0 != typeNode); } } result = typeNode; } else { std::vector<ScopeNameNode*> scopeNameNodes; m_scopeNameList->collectIdentifyNodes(scopeNameNodes); TypeNode* initialTypeTreeNode = 0; TypeNode* finalTypeTreeNode = 0; if (m_startTypeNode->isTemplateClass() && !scopeNameNodes[0]->isTemplateForm()) { assert(m_startTypeNode->m_name == templateArguments->m_className); scopeNameNodes.erase(scopeNameNodes.begin()); if (g_typeTree.findNodeByScopeNames(initialTypeTreeNode, finalTypeTreeNode, scopeNameNodes, templateArguments->m_classTypeNode, templateArguments)) { result = finalTypeTreeNode; } } else { if (g_typeTree.findNodeByScopeNames(initialTypeTreeNode, finalTypeTreeNode, scopeNameNodes, m_startTypeNode->m_enclosing, templateArguments)) { result = finalTypeTreeNode; } } } } else { assert(m_typeNode->isPredefinedType() || m_typeNode->isEnum() || m_typeNode->isClass() || m_typeNode->isTemplateClassInstance() || m_typeNode->isTypedef() || m_typeNode->isTypeDeclaration()); result = m_typeNode; } if(0 == result) { RaiseError_InvalidTypeName(m_scopeNameList); } return result; }
void TypeNameNode::getRelativeName(std::string& typeName, ScopeNode* scopeNode) { assert(m_startTypeNode && scopeNode); if (0 == m_scopeNameList)// predefined type { m_typeNode->getFullName(typeName); } else { if (m_typeNode) { MemberNode* memberNode = m_typeNode->getSyntaxNode(); if (memberNode && memberNode->m_nativeName) { memberNode->getNativeName(typeName, 0); return; } } if (m_scopeNameList->isGlobal()) { m_scopeNameList->getString(typeName); } else { TypeNode* scopeTypeNode = scopeNode->getTypeNode(); std::vector<TypeNode*> enclosings; m_startTypeNode->getEnclosings(enclosings); std::vector<TypeNode*> scopeEnclosings; scopeTypeNode->getEnclosings(scopeEnclosings); scopeEnclosings.push_back(scopeTypeNode); auto it = enclosings.begin(); auto end = enclosings.end(); auto it2 = scopeEnclosings.begin(); auto end2 = scopeEnclosings.end(); for (; it2 != end2; ++it2) { if (it == end) { break; } if (*it != *it2) { break; } ++it; } typeName.clear(); for (; it != end; ++it) { TypeNode* typeNode = *it; std::string localName; typeNode->getLocalName(localName); typeName += localName + "::"; } std::string str; m_scopeNameList->getString(str); typeName += str; } } }
TypeCategory TemplateParameterTypeNode::getTypeCategory(TemplateArguments* templateArguments) { TypeNode* actualTypeNode = templateArguments->findTypeNode(m_name); return actualTypeNode->getTypeCategory(templateArguments); }
void TypeNodeProvider::value(Atlas::Message::Element& value, const TypeNode& type) const { if (m_attribute_name == "name") { value = type.name(); } }
Node DtInstantiator::solve_dt(Node v, Node a, Node b, Node sa, Node sb) { Trace("cegqi-arith-debug2") << "Solve dt : " << v << " " << a << " " << b << " " << sa << " " << sb << std::endl; Node ret; if (!a.isNull() && a == v) { ret = sb; } else if (!b.isNull() && b == v) { ret = sa; } else if (!a.isNull() && a.getKind() == APPLY_CONSTRUCTOR) { if (!b.isNull() && b.getKind() == APPLY_CONSTRUCTOR) { if (a.getOperator() == b.getOperator()) { for (unsigned i = 0, nchild = a.getNumChildren(); i < nchild; i++) { Node s = solve_dt(v, a[i], b[i], sa[i], sb[i]); if (!s.isNull()) { return s; } } } } else { NodeManager* nm = NodeManager::currentNM(); unsigned cindex = Datatype::indexOf(a.getOperator().toExpr()); TypeNode tn = a.getType(); const Datatype& dt = static_cast<DatatypeType>(tn.toType()).getDatatype(); for (unsigned i = 0, nchild = a.getNumChildren(); i < nchild; i++) { Node nn = nm->mkNode( APPLY_SELECTOR_TOTAL, Node::fromExpr(dt[cindex].getSelectorInternal(tn.toType(), i)), sb); Node s = solve_dt(v, a[i], Node::null(), sa[i], nn); if (!s.isNull()) { return s; } } } } else if (!b.isNull() && b.getKind() == APPLY_CONSTRUCTOR) { // flip sides return solve_dt(v, b, a, sb, sa); } if (!ret.isNull()) { // ensure does not contain v if (expr::hasSubterm(ret, v)) { ret = Node::null(); } } return ret; }
void setup() { m_inheritance = new Inheritance(); //Set up testing environment for Type/Soft properties m_b1 = new TestEntity("1", 1); add_entity(m_b1); m_thingType = new TypeNode("thing"); types["thing"] = m_thingType; m_barrelType = new TypeNode("barrel"); m_barrelType->setParent(m_thingType); types["barrel"] = m_barrelType; m_b1->setType(m_barrelType); m_b1->setProperty("mass", new SoftProperty(Element(30))); m_b1->setProperty("burn_speed", new SoftProperty(Element(0.3))); m_b1->setProperty("isVisible", new SoftProperty(Element(true))); m_b2 = new Entity("2", 2); add_entity(m_b2); m_b2->setProperty("mass", new SoftProperty(Element(20))); m_b2->setProperty("burn_speed", new SoftProperty(0.25)); m_b2->setType(m_barrelType); m_b2->setProperty("isVisible", new SoftProperty(Element(false))); m_b3 = new Entity("3", 3); add_entity(m_b3); m_b3->setProperty("mass", new SoftProperty(Element(25))); m_b3->setProperty("burn_speed", new SoftProperty(Element(0.25))); m_b3->setType(m_barrelType); m_boulderType = new TypeNode("boulder"); types["boulder"] = m_boulderType; m_bl1 = new Entity("4", 4); add_entity(m_bl1); m_bl1->setProperty("mass", new SoftProperty(Element(25))); m_bl1->setType(m_boulderType); SoftProperty* prop1 = new SoftProperty(); prop1->set(std::vector<Element>{25.0, 20.0}); m_bl1->setProperty("float_list", prop1); SoftProperty* list_prop2 = new SoftProperty(); list_prop2->set(std::vector<Element>{"foo", "bar"}); m_bl1->setProperty("string_list", list_prop2); // Create an entity-related memory map Atlas::Message::MapType entity_memory_map{{"disposition", 25}}; m_memory.emplace("1", entity_memory_map); //b1 contains bl1 which contains b3 m_b1_container = new LocatedEntitySet; m_b1_container->insert(m_bl1); m_bl1->m_location.m_parent = m_b1; m_b1->m_contains = m_b1_container; m_b1->test_setDomain(new TestDomain(*m_b1)); m_bl1_container = new LocatedEntitySet; m_bl1_container->insert(m_b3); m_b3->m_location.m_parent = m_bl1; m_bl1->m_contains = m_bl1_container; //Set up testing environment for Outfit property m_glovesType = new TypeNode("gloves"); types["gloves"] = m_glovesType; m_bootsType = new TypeNode("boots"); m_characterType = new TypeNode("character"); types["character"] = m_characterType; TypeNode* m_clothType = new TypeNode("cloth"); types["cloth"] = m_clothType; TypeNode* m_leatherType = new TypeNode("leather"); m_glovesEntity = new Entity("5", 5); add_entity(m_glovesEntity); m_glovesEntity->setType(m_glovesType); m_glovesEntity->setProperty("color", new SoftProperty("brown")); m_glovesEntity->setProperty("mass", new SoftProperty(5)); //Mark it with a "reach" so we can use it in the "can_reach ... with" tests auto reachProp = new Property<double>(); reachProp->data() = 10.0f; m_glovesEntity->setProperty("reach", reachProp); m_bootsEntity = new Entity("6", 6); add_entity(m_bootsEntity); m_bootsEntity->setType(m_bootsType); m_bootsEntity->setProperty("color", new SoftProperty("black")); m_bootsEntity->setProperty("mass", new SoftProperty(10)); m_cloth = new Entity("8", 8); add_entity(m_cloth); m_cloth->setType(m_clothType); m_cloth->setProperty("color", new SoftProperty("green")); m_leather = new Entity("9", 9); add_entity(m_leather); m_leather->setType(m_leatherType); m_leather->setProperty("color", new SoftProperty("pink")); //The m_cloth entity is attached to the gloves by the "thumb" attachment { auto attachedProp = new SoftProperty(); attachedProp->data() = Atlas::Message::MapType{{"$eid", m_cloth->getId()}}; m_glovesEntity->setProperty("attached_thumb", attachedProp); auto plantedOnProp = new PlantedOnProperty(); plantedOnProp->data().entity = WeakEntityRef(m_glovesEntity.get()); m_cloth->setProperty("planted_on", plantedOnProp); } m_ch1 = new Entity("7", 7); add_entity(m_ch1); m_ch1->setType(m_characterType); //The m_glovesEntity entity is attached to the m_ch1 by the "hand_primary" attachment { auto attachedHandPrimaryProp = new SoftProperty(); attachedHandPrimaryProp->data() = Atlas::Message::MapType{{"$eid", m_glovesEntity->getId()}}; m_ch1->setProperty("attached_hand_primary", attachedHandPrimaryProp); } { auto plantedOnProp = new PlantedOnProperty(); plantedOnProp->data().entity = WeakEntityRef(m_ch1.get()); m_glovesEntity->setProperty("planted_on", plantedOnProp); } BBoxProperty* bbox1 = new BBoxProperty; bbox1->set((std::vector<Element>{-1, -3, -2, 1, 3, 2})); m_b1->setProperty("bbox", bbox1); BBoxProperty* bbox2 = new BBoxProperty; bbox2->set(std::vector<Element>{-3, -2, -1, 1, 3, 2}); m_bl1->setProperty("bbox", bbox2); m_cloth->setProperty("bbox", bbox1->copy()); }
PreprocessingPassResult SygusAbduct::applyInternal( AssertionPipeline* assertionsToPreprocess) { NodeManager* nm = NodeManager::currentNM(); Trace("sygus-abduct") << "Run sygus abduct..." << std::endl; Trace("sygus-abduct-debug") << "Collect symbols..." << std::endl; std::unordered_set<Node, NodeHashFunction> symset; std::vector<Node>& asserts = assertionsToPreprocess->ref(); // do we have any assumptions, e.g. via check-sat-assuming? bool usingAssumptions = (assertionsToPreprocess->getNumAssumptions() > 0); // The following is our set of "axioms". We construct this set only when the // usingAssumptions (above) is true. In this case, our input formula is // partitioned into Fa ^ Fc as described in the header of this class, where: // - The conjunction of assertions marked as assumptions are the negated // conjecture Fc, and // - The conjunction of all other assertions are the axioms Fa. std::vector<Node> axioms; for (size_t i = 0, size = asserts.size(); i < size; i++) { expr::getSymbols(asserts[i], symset); // if we are not an assumption, add it to the set of axioms if (usingAssumptions && i < assertionsToPreprocess->getAssumptionsStart()) { axioms.push_back(asserts[i]); } } Trace("sygus-abduct-debug") << "...finish, got " << symset.size() << " symbols." << std::endl; Trace("sygus-abduct-debug") << "Setup symbols..." << std::endl; std::vector<Node> syms; std::vector<Node> vars; std::vector<Node> varlist; std::vector<TypeNode> varlistTypes; for (const Node& s : symset) { TypeNode tn = s.getType(); if (tn.isFirstClass()) { std::stringstream ss; ss << s; Node var = nm->mkBoundVar(tn); syms.push_back(s); vars.push_back(var); Node vlv = nm->mkBoundVar(ss.str(), tn); varlist.push_back(vlv); varlistTypes.push_back(tn); } } Trace("sygus-abduct-debug") << "...finish" << std::endl; Trace("sygus-abduct-debug") << "Make abduction predicate..." << std::endl; // make the abduction predicate to synthesize TypeNode abdType = varlistTypes.empty() ? nm->booleanType() : nm->mkPredicateType(varlistTypes); Node abd = nm->mkBoundVar("A", abdType); Trace("sygus-abduct-debug") << "...finish" << std::endl; Trace("sygus-abduct-debug") << "Make abduction predicate app..." << std::endl; std::vector<Node> achildren; achildren.push_back(abd); achildren.insert(achildren.end(), vars.begin(), vars.end()); Node abdApp = vars.empty() ? abd : nm->mkNode(APPLY_UF, achildren); Trace("sygus-abduct-debug") << "...finish" << std::endl; Trace("sygus-abduct-debug") << "Set attributes..." << std::endl; // set the sygus bound variable list Node abvl = nm->mkNode(BOUND_VAR_LIST, varlist); abd.setAttribute(theory::SygusSynthFunVarListAttribute(), abvl); Trace("sygus-abduct-debug") << "...finish" << std::endl; Trace("sygus-abduct-debug") << "Make conjecture body..." << std::endl; Node input = asserts.size() == 1 ? asserts[0] : nm->mkNode(AND, asserts); input = input.substitute(syms.begin(), syms.end(), vars.begin(), vars.end()); // A(x) => ~input( x ) input = nm->mkNode(OR, abdApp.negate(), input.negate()); Trace("sygus-abduct-debug") << "...finish" << std::endl; Trace("sygus-abduct-debug") << "Make conjecture..." << std::endl; Node res = input.negate(); if (!vars.empty()) { Node bvl = nm->mkNode(BOUND_VAR_LIST, vars); // exists x. ~( A( x ) => ~input( x ) ) res = nm->mkNode(EXISTS, bvl, res); } // sygus attribute Node sygusVar = nm->mkSkolem("sygus", nm->booleanType()); theory::SygusAttribute ca; sygusVar.setAttribute(ca, true); Node instAttr = nm->mkNode(INST_ATTRIBUTE, sygusVar); std::vector<Node> iplc; iplc.push_back(instAttr); if (!axioms.empty()) { Node aconj = axioms.size() == 1 ? axioms[0] : nm->mkNode(AND, axioms); aconj = aconj.substitute(syms.begin(), syms.end(), vars.begin(), vars.end()); Trace("sygus-abduct") << "---> Assumptions: " << aconj << std::endl; Node sc = nm->mkNode(AND, aconj, abdApp); Node vbvl = nm->mkNode(BOUND_VAR_LIST, vars); sc = nm->mkNode(EXISTS, vbvl, sc); Node sygusScVar = nm->mkSkolem("sygus_sc", nm->booleanType()); sygusScVar.setAttribute(theory::SygusSideConditionAttribute(), sc); instAttr = nm->mkNode(INST_ATTRIBUTE, sygusScVar); // build in the side condition // exists x. A( x ) ^ input_axioms( x ) // as an additional annotation on the sygus conjecture. In other words, // the abducts A we procedure must be consistent with our axioms. iplc.push_back(instAttr); } Node instAttrList = nm->mkNode(INST_PATTERN_LIST, iplc); Node fbvl = nm->mkNode(BOUND_VAR_LIST, abd); // forall A. exists x. ~( A( x ) => ~input( x ) ) res = nm->mkNode(FORALL, fbvl, res, instAttrList); Trace("sygus-abduct-debug") << "...finish" << std::endl; res = theory::Rewriter::rewrite(res); Trace("sygus-abduct") << "Generate: " << res << std::endl; Node trueNode = nm->mkConst(true); assertionsToPreprocess->replace(0, res); for (size_t i = 1, size = assertionsToPreprocess->size(); i < size; ++i) { assertionsToPreprocess->replace(i, trueNode); } return PreprocessingPassResult::NO_CONFLICT; }
void PrintASTVisitor::visit(TypeNode& node) { std::cout << indent() << "TypeNode: " << SymbolTable::equelleString(node.type()) << '\n'; }
bool TypeTree::checkTypeNameNode(TypeNode*& initialTypeTreeNode, TypeNode*& finalTypeTreeNode, ScopeNameListNode* scopeNameListNode, TypeNode* enclosingTypeTreeNode, TemplateArguments* templateArguments) { assert(0 == templateArguments || templateArguments->m_classTypeNode->isTemplateClass()); initialTypeTreeNode = 0; finalTypeTreeNode = 0; std::vector<ScopeNameNode*> scopeNameNodes; scopeNameListNode->collectIdentifyNodes(scopeNameNodes); assert(!scopeNameNodes.empty()); if (0 != templateArguments && !scopeNameListNode->isGlobal()) { ScopeNameNode* scopeNameNode = scopeNameNodes.front(); if (!scopeNameNode->isTemplateForm()) { if (scopeNameNode->m_name->m_str == templateArguments->m_className) { initialTypeTreeNode = templateArguments->m_classTypeNode; if (1 == scopeNameNodes.size()) { //finalTypeTreeNode->isTemplateClass() finalTypeTreeNode = initialTypeTreeNode; return true; } else { //0 == finalTypeTreeNode || finalTypeTreeNode->isUnderTemplateClass() scopeNameNodes.erase(scopeNameNodes.begin()); TypeNode* tmpTypeNode = 0; return findNodeByScopeNames(tmpTypeNode, finalTypeTreeNode, scopeNameNodes, initialTypeTreeNode, 0); } } initialTypeTreeNode = templateArguments->findTypeNode(scopeNameNode->m_name->m_str); if(initialTypeTreeNode) { if (1 == scopeNameNodes.size()) { //finalTypeTreeNode->isTemplateParameter() finalTypeTreeNode = initialTypeTreeNode; } else { finalTypeTreeNode = 0; } return true; } } } if (scopeNameListNode->isGlobal()) { return findNodeByScopeNames(initialTypeTreeNode, finalTypeTreeNode, scopeNameNodes, getRootNamespaceTypeNode(), templateArguments); } TypeNode* enclosing = enclosingTypeTreeNode; while (enclosing) { if(findNodeByScopeNames(initialTypeTreeNode, finalTypeTreeNode, scopeNameNodes, enclosing, templateArguments)) { return true; } enclosing = enclosing->getEnclosing(); } initialTypeTreeNode = 0; finalTypeTreeNode = 0; bool result = false; auto it = m_allNamespaces.begin(); auto end = m_allNamespaces.end(); for (; it != end; ++it) { TypeNode* tempInitialTypeTreeNode = 0; TypeNode* tempFinalTypeTreeNode = 0; if(findNodeByScopeNames(tempInitialTypeTreeNode, tempFinalTypeTreeNode, scopeNameNodes, *it, templateArguments)) { if (result) { char buf[512]; std::string str; scopeNameListNode->getString(str); sprintf_s(buf, "\'%s\' : ambiguous type name could be %s(%d, %d) or %s(%d, %d)", str.c_str(), finalTypeTreeNode->m_sourceFile->m_fileName.c_str(), finalTypeTreeNode->m_identifyNode->m_lineNo, finalTypeTreeNode->m_identifyNode->m_columnNo, tempFinalTypeTreeNode->m_sourceFile->m_fileName.c_str(), tempFinalTypeTreeNode->m_identifyNode->m_lineNo, tempFinalTypeTreeNode->m_identifyNode->m_columnNo); ErrorList_AddItem_CurrentFile(scopeNameNodes.back()->m_name->m_lineNo, scopeNameNodes.back()->m_name->m_columnNo, semantic_error_ambiguous_type_name, buf); return false; } else { initialTypeTreeNode = tempInitialTypeTreeNode; finalTypeTreeNode = tempFinalTypeTreeNode; result = true; } } } if (!result) { RaiseError_InvalidTypeName(scopeNameListNode); } return result; }
void SortInference::simplify( std::vector< Node >& assertions, bool doSortInference, bool doMonotonicyInference ){ if( doSortInference ){ Trace("sort-inference-proc") << "Calculating sort inference..." << std::endl; NodeManager* nm = NodeManager::currentNM(); //process all assertions std::map< Node, int > visited; for( unsigned i=0; i<assertions.size(); i++ ){ Trace("sort-inference-debug") << "Process " << assertions[i] << std::endl; std::map< Node, Node > var_bound; process( assertions[i], var_bound, visited ); } Trace("sort-inference-proc") << "...done" << std::endl; for( std::map< Node, int >::iterator it = d_op_return_types.begin(); it != d_op_return_types.end(); ++it ){ Trace("sort-inference") << it->first << " : "; TypeNode retTn = it->first.getType(); if( !d_op_arg_types[ it->first ].empty() ){ Trace("sort-inference") << "( "; for( size_t i=0; i<d_op_arg_types[ it->first ].size(); i++ ){ recordSubsort( retTn[i], d_op_arg_types[ it->first ][i] ); printSort( "sort-inference", d_op_arg_types[ it->first ][i] ); Trace("sort-inference") << " "; } Trace("sort-inference") << ") -> "; retTn = retTn[(int)retTn.getNumChildren()-1]; } recordSubsort( retTn, it->second ); printSort( "sort-inference", it->second ); Trace("sort-inference") << std::endl; } for( std::map< Node, std::map< Node, int > >::iterator it = d_var_types.begin(); it != d_var_types.end(); ++it ){ Trace("sort-inference") << "Quantified formula : " << it->first << " : " << std::endl; for( unsigned i=0; i<it->first[0].getNumChildren(); i++ ){ recordSubsort( it->first[0][i].getType(), it->second[it->first[0][i]] ); printSort( "sort-inference", it->second[it->first[0][i]] ); Trace("sort-inference") << std::endl; } Trace("sort-inference") << std::endl; } bool rewritten = false; // determine monotonicity of sorts Trace("sort-inference-proc") << "Calculating monotonicty for subsorts..." << std::endl; std::map<Node, std::map<int, bool> > visitedm; for (const Node& a : assertions) { Trace("sort-inference-debug") << "Process monotonicity for " << a << std::endl; std::map<Node, Node> var_bound; processMonotonic(a, true, true, var_bound, visitedm); } Trace("sort-inference-proc") << "...done" << std::endl; Trace("sort-inference") << "We have " << d_sub_sorts.size() << " sub-sorts : " << std::endl; for (unsigned i = 0, size = d_sub_sorts.size(); i < size; i++) { printSort("sort-inference", d_sub_sorts[i]); if (d_type_types.find(d_sub_sorts[i]) != d_type_types.end()) { Trace("sort-inference") << " is interpreted." << std::endl; } else if (d_non_monotonic_sorts.find(d_sub_sorts[i]) == d_non_monotonic_sorts.end()) { Trace("sort-inference") << " is monotonic." << std::endl; } else { Trace("sort-inference") << " is not monotonic." << std::endl; } } // simplify all assertions by introducing new symbols wherever necessary Trace("sort-inference-proc") << "Perform simplification..." << std::endl; std::map<Node, std::map<TypeNode, Node> > visited2; for (unsigned i = 0, size = assertions.size(); i < size; i++) { Node prev = assertions[i]; std::map<Node, Node> var_bound; Trace("sort-inference-debug") << "Simplify " << prev << std::endl; TypeNode tnn; Node curr = simplifyNode(assertions[i], var_bound, tnn, visited2); Trace("sort-inference-debug") << "Done." << std::endl; if (curr != assertions[i]) { Trace("sort-inference-debug") << "Rewrite " << curr << std::endl; curr = theory::Rewriter::rewrite(curr); rewritten = true; Trace("sort-inference-rewrite") << assertions << std::endl; Trace("sort-inference-rewrite") << " --> " << curr << std::endl; PROOF(ProofManager::currentPM()->addDependence(curr, assertions[i]);); assertions[i] = curr; } }
void SharedTermsVisitor::visit(TNode current, TNode parent) { Debug("register") << "SharedTermsVisitor::visit(" << current << "," << parent << ")" << std::endl; if (Debug.isOn("register::internal")) { Debug("register::internal") << toString() << std::endl; } // Get the theories of the terms TheoryId currentTheoryId = Theory::theoryOf(current); TheoryId parentTheoryId = Theory::theoryOf(parent); #if 0 bool useType = current != parent && currentTheoryId != parentTheoryId; #else // Should we use the theory of the type bool useType = false; TheoryId typeTheoryId = THEORY_LAST; if (current != parent) { if (currentTheoryId != parentTheoryId) { // If enclosed by different theories it's shared -- in read(a, f(a)) f(a) should be shared with integers TypeNode type = current.getType(); useType = true; typeTheoryId = Theory::theoryOf(type); } else { TypeNode type = current.getType(); typeTheoryId = Theory::theoryOf(type); if (typeTheoryId != currentTheoryId) { if (options::finiteModelFind() && type.isSort()) { // We're looking for finite models useType = true; } else { Cardinality card = type.getCardinality(); if (card.isFinite()) { useType = true; } } } } } #endif Theory::Set visitedTheories = d_visited[current]; Debug("register::internal") << "SharedTermsVisitor::visit(" << current << "," << parent << "): previously registered with " << Theory::setToString(visitedTheories) << std::endl; if (!Theory::setContains(currentTheoryId, visitedTheories)) { visitedTheories = Theory::setInsert(currentTheoryId, visitedTheories); Debug("register::internal") << "SharedTermsVisitor::visit(" << current << "," << parent << "): adding " << currentTheoryId << std::endl; } if (!Theory::setContains(parentTheoryId, visitedTheories)) { visitedTheories = Theory::setInsert(parentTheoryId, visitedTheories); Debug("register::internal") << "SharedTermsVisitor::visit(" << current << "," << parent << "): adding " << parentTheoryId << std::endl; } if (useType) { //////TheoryId typeTheoryId = Theory::theoryOf(current.getType()); if (!Theory::setContains(typeTheoryId, visitedTheories)) { visitedTheories = Theory::setInsert(typeTheoryId, visitedTheories); Debug("register::internal") << "SharedTermsVisitor::visit(" << current << "," << parent << "): adding " << typeTheoryId << std::endl; } } Debug("register::internal") << "SharedTermsVisitor::visit(" << current << "," << parent << "): now registered with " << Theory::setToString(visitedTheories) << std::endl; // Record the new theories that we visited d_visited[current] = visitedTheories; // If there is more than two theories and a new one has been added notify the shared terms database if (Theory::setDifference(visitedTheories, Theory::setInsert(currentTheoryId))) { d_sharedTerms.addSharedTerm(d_atom, current, visitedTheories); } Assert(d_visited.find(current) != d_visited.end()); Assert(alreadyVisited(current, parent)); }
bool SharedTermsVisitor::alreadyVisited(TNode current, TNode parent) const { Debug("register::internal") << "SharedTermsVisitor::alreadyVisited(" << current << "," << parent << ")" << std::endl; if( ( parent.getKind() == kind::FORALL || parent.getKind() == kind::EXISTS || parent.getKind() == kind::REWRITE_RULE /*|| parent.getKind() == kind::CARDINALITY_CONSTRAINT*/ ) && current != parent ) { Debug("register::internal") << "quantifier:true" << std::endl; return true; } TNodeVisitedMap::const_iterator find = d_visited.find(current); // If node is not visited at all, just return false if (find == d_visited.end()) { Debug("register::internal") << "1:false" << std::endl; return false; } Theory::Set theories = (*find).second; TheoryId currentTheoryId = Theory::theoryOf(current); TheoryId parentTheoryId = Theory::theoryOf(parent); // Should we use the theory of the type #if 0 bool useType = current != parent && currentTheoryId != parentTheoryId; #else bool useType = false; TheoryId typeTheoryId = THEORY_LAST; if (current != parent) { if (currentTheoryId != parentTheoryId) { // If enclosed by different theories it's shared -- in read(a, f(a)) f(a) should be shared with integers TypeNode type = current.getType(); useType = true; typeTheoryId = Theory::theoryOf(type); } else { TypeNode type = current.getType(); typeTheoryId = Theory::theoryOf(type); if (typeTheoryId != currentTheoryId) { if (options::finiteModelFind() && type.isSort()) { // We're looking for finite models useType = true; } else { Cardinality card = type.getCardinality(); if (card.isFinite()) { useType = true; } } } } } #endif if (Theory::setContains(currentTheoryId, theories)) { if (Theory::setContains(parentTheoryId, theories)) { if (useType) { ////TheoryId typeTheoryId = Theory::theoryOf(current.getType()); return Theory::setContains(typeTheoryId, theories); } else { return true; } } else { return false; } } else { return false; } }
void TheoryEngineModelBuilder::buildModel(Model* m, bool fullModel) { TheoryModel* tm = (TheoryModel*)m; // buildModel with fullModel = true should only be called once in any context Assert(!tm->d_modelBuilt); tm->d_modelBuilt = fullModel; // Reset model tm->reset(); // Collect model info from the theories Trace("model-builder") << "TheoryEngineModelBuilder: Collect model info..." << std::endl; d_te->collectModelInfo(tm, fullModel); // Loop through all terms and make sure that assignable sub-terms are in the equality engine eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( &tm->d_equalityEngine ); { NodeSet cache; for ( ; !eqcs_i.isFinished(); ++eqcs_i) { eq::EqClassIterator eqc_i = eq::EqClassIterator((*eqcs_i), &tm->d_equalityEngine); for ( ; !eqc_i.isFinished(); ++eqc_i) { checkTerms(*eqc_i, tm, cache); } } } Trace("model-builder") << "Collect representatives..." << std::endl; // Process all terms in the equality engine, store representatives for each EC std::map< Node, Node > assertedReps, constantReps; TypeSet typeConstSet, typeRepSet, typeNoRepSet; std::set< TypeNode > allTypes; eqcs_i = eq::EqClassesIterator(&tm->d_equalityEngine); for ( ; !eqcs_i.isFinished(); ++eqcs_i) { // eqc is the equivalence class representative Node eqc = (*eqcs_i); Trace("model-builder") << "Processing EC: " << eqc << endl; Assert(tm->d_equalityEngine.getRepresentative(eqc) == eqc); TypeNode eqct = eqc.getType(); Assert(assertedReps.find(eqc) == assertedReps.end()); Assert(constantReps.find(eqc) == constantReps.end()); // Loop through terms in this EC Node rep, const_rep; eq::EqClassIterator eqc_i = eq::EqClassIterator(eqc, &tm->d_equalityEngine); for ( ; !eqc_i.isFinished(); ++eqc_i) { Node n = *eqc_i; Trace("model-builder") << " Processing Term: " << n << endl; // Record as rep if this node was specified as a representative if (tm->d_reps.find(n) != tm->d_reps.end()){ Assert(rep.isNull()); rep = tm->d_reps[n]; Assert(!rep.isNull() ); Trace("model-builder") << " Rep( " << eqc << " ) = " << rep << std::endl; } // Record as const_rep if this node is constant if (n.isConst()) { Assert(const_rep.isNull()); const_rep = n; Trace("model-builder") << " ConstRep( " << eqc << " ) = " << const_rep << std::endl; } //model-specific processing of the term tm->addTerm(n); } // Assign representative for this EC if (!const_rep.isNull()) { // Theories should not specify a rep if there is already a constant in the EC Assert(rep.isNull() || rep == const_rep); constantReps[eqc] = const_rep; typeConstSet.add(eqct.getBaseType(), const_rep); } else if (!rep.isNull()) { assertedReps[eqc] = rep; typeRepSet.add(eqct.getBaseType(), eqc); allTypes.insert(eqct); } else { typeNoRepSet.add(eqct, eqc); allTypes.insert(eqct); } } // Need to ensure that each EC has a constant representative. Trace("model-builder") << "Processing EC's..." << std::endl; TypeSet::iterator it; set<TypeNode>::iterator type_it; set<Node>::iterator i, i2; bool changed, unassignedAssignable, assignOne = false; set<TypeNode> evaluableSet; // Double-fixed-point loop // Outer loop handles a special corner case (see code at end of loop for details) for (;;) { // Inner fixed-point loop: we are trying to learn constant values for every EC. Each time through this loop, we process all of the // types by type and may learn some new EC values. EC's in one type may depend on EC's in another type, so we need a fixed-point loop // to ensure that we learn as many EC values as possible do { changed = false; unassignedAssignable = false; evaluableSet.clear(); // Iterate over all types we've seen for (type_it = allTypes.begin(); type_it != allTypes.end(); ++type_it) { TypeNode t = *type_it; TypeNode tb = t.getBaseType(); set<Node>* noRepSet = typeNoRepSet.getSet(t); // 1. Try to evaluate the EC's in this type if (noRepSet != NULL && !noRepSet->empty()) { Trace("model-builder") << " Eval phase, working on type: " << t << endl; bool assignable, evaluable, evaluated; d_normalizedCache.clear(); for (i = noRepSet->begin(); i != noRepSet->end(); ) { i2 = i; ++i; assignable = false; evaluable = false; evaluated = false; eq::EqClassIterator eqc_i = eq::EqClassIterator(*i2, &tm->d_equalityEngine); for ( ; !eqc_i.isFinished(); ++eqc_i) { Node n = *eqc_i; if (isAssignable(n)) { assignable = true; } else { evaluable = true; Node normalized = normalize(tm, n, constantReps, true); if (normalized.isConst()) { typeConstSet.add(tb, normalized); constantReps[*i2] = normalized; Trace("model-builder") << " Eval: Setting constant rep of " << (*i2) << " to " << normalized << endl; changed = true; evaluated = true; noRepSet->erase(i2); break; } } } if (!evaluated) { if (evaluable) { evaluableSet.insert(tb); } if (assignable) { unassignedAssignable = true; } } } } // 2. Normalize any non-const representative terms for this type set<Node>* repSet = typeRepSet.getSet(t); if (repSet != NULL && !repSet->empty()) { Trace("model-builder") << " Normalization phase, working on type: " << t << endl; d_normalizedCache.clear(); for (i = repSet->begin(); i != repSet->end(); ) { Assert(assertedReps.find(*i) != assertedReps.end()); Node rep = assertedReps[*i]; Node normalized = normalize(tm, rep, constantReps, false); Trace("model-builder") << " Normalizing rep (" << rep << "), normalized to (" << normalized << ")" << endl; if (normalized.isConst()) { changed = true; typeConstSet.add(t.getBaseType(), normalized); constantReps[*i] = normalized; assertedReps.erase(*i); i2 = i; ++i; repSet->erase(i2); } else { if (normalized != rep) { assertedReps[*i] = normalized; changed = true; } ++i; } } } } } while (changed); if (!fullModel || !unassignedAssignable) { break; } // 3. Assign unassigned assignable EC's using type enumeration - assign a value *different* from all other EC's if the type is infinite // Assign first value from type enumerator otherwise - for finite types, we rely on polite framework to ensure that EC's that have to be // different are different. // Only make assignments on a type if: // 1. fullModel is true // 2. there are no terms that share the same base type with un-normalized representatives // 3. 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); if (noRepSet.empty()) { continue; } TypeNode t = TypeSet::getType(it); TypeNode tb = t.getBaseType(); if (!assignOne) { set<Node>* repSet = typeRepSet.getSet(tb); if (repSet != NULL && !repSet->empty()) { continue; } if (evaluableSet.find(tb) != evaluableSet.end()) { continue; } } Trace("model-builder") << " Assign phase, working on type: " << t << endl; bool assignable, evaluable CVC4_UNUSED; for (i = noRepSet.begin(); i != noRepSet.end(); ) { i2 = i; ++i; eq::EqClassIterator eqc_i = eq::EqClassIterator(*i2, &tm->d_equalityEngine); assignable = false; evaluable = false; for ( ; !eqc_i.isFinished(); ++eqc_i) { Node n = *eqc_i; if (isAssignable(n)) { assignable = true; } else { evaluable = true; } } if (assignable) { Assert(!evaluable || assignOne); Assert(!t.isBoolean() || (*i2).getKind() == kind::APPLY_UF); Node n; if (t.getCardinality().isInfinite()) { n = typeConstSet.nextTypeEnum(t, true); } else { TypeEnumerator te(t); n = *te; } Assert(!n.isNull()); constantReps[*i2] = n; Trace("model-builder") << " Assign: Setting constant rep of " << (*i2) << " to " << n << endl; changed = true; noRepSet.erase(i2); if (assignOne) { assignOne = false; break; } } } } // Corner case - I'm not sure this can even happen - but it's theoretically possible to have a cyclical dependency // in EC assignment/evaluation, e.g. EC1 = {a, b + 1}; EC2 = {b, a - 1}. In this case, neither one will get assigned because we are waiting // to be able to evaluate. But we will never be able to evaluate because the variables that need to be assigned are in // these same EC's. In this case, repeat the whole fixed-point computation with the difference that the first EC // that has both assignable and evaluable expressions will get assigned. if (!changed) { Assert(!assignOne); // check for infinite loop! assignOne = true; } } #ifdef CVC4_ASSERTIONS if (fullModel) { // Assert that all representatives have been converted to constants for (it = typeRepSet.begin(); it != typeRepSet.end(); ++it) { set<Node>& repSet = TypeSet::getSet(it); if (!repSet.empty()) { Trace("model-builder") << "***Non-empty repSet, size = " << repSet.size() << ", first = " << *(repSet.begin()) << endl; Assert(false); } } } #endif /* CVC4_ASSERTIONS */ Trace("model-builder") << "Copy representatives to model..." << std::endl; tm->d_reps.clear(); std::map< Node, Node >::iterator itMap; for (itMap = constantReps.begin(); itMap != constantReps.end(); ++itMap) { tm->d_reps[itMap->first] = itMap->second; tm->d_rep_set.add(itMap->second); } if (!fullModel) { // Make sure every EC has a rep for (itMap = assertedReps.begin(); itMap != assertedReps.end(); ++itMap ) { tm->d_reps[itMap->first] = itMap->second; tm->d_rep_set.add(itMap->second); } for (it = typeNoRepSet.begin(); it != typeNoRepSet.end(); ++it) { set<Node>& noRepSet = TypeSet::getSet(it); set<Node>::iterator i; for (i = noRepSet.begin(); i != noRepSet.end(); ++i) { tm->d_reps[*i] = *i; tm->d_rep_set.add(*i); } } } //modelBuilder-specific initialization processBuildModel( tm, fullModel ); #ifdef CVC4_ASSERTIONS if (fullModel) { // Check that every term evaluates to its representative in the model for (eqcs_i = eq::EqClassesIterator(&tm->d_equalityEngine); !eqcs_i.isFinished(); ++eqcs_i) { // eqc is the equivalence class representative Node eqc = (*eqcs_i); Node rep; itMap = constantReps.find(eqc); if (itMap == constantReps.end() && eqc.getType().isBoolean()) { rep = tm->getValue(eqc); Assert(rep.isConst()); } else { Assert(itMap != constantReps.end()); rep = itMap->second; } eq::EqClassIterator eqc_i = eq::EqClassIterator(eqc, &tm->d_equalityEngine); for ( ; !eqc_i.isFinished(); ++eqc_i) { Node n = *eqc_i; static int repCheckInstance = 0; ++repCheckInstance; Debug("check-model::rep-checking") << "( " << repCheckInstance <<") " << "n: " << n << endl << "getValue(n): " << tm->getValue(n) << endl << "rep: " << rep << endl; Assert(tm->getValue(*eqc_i) == rep); } } } #endif /* CVC4_ASSERTIONS */ }
void PrintEquelleASTVisitor::visit(TypeNode& node) { std::cout << SymbolTable::equelleString(node.type()); }
Node TheoryModel::getModelValue(TNode n, bool hasBoundVars) const { Assert(n.getKind() != kind::FORALL && n.getKind() != kind::EXISTS); if(n.getKind() == kind::LAMBDA) { NodeManager* nm = NodeManager::currentNM(); Node body = getModelValue(n[1], true); // This is a bit ugly, but cache inside simplifier can change, so can't be const // The ite simplifier is needed to get rid of artifacts created by Boolean terms body = const_cast<ITESimplifier*>(&d_iteSimp)->simpITE(body); body = Rewriter::rewrite(body); return nm->mkNode(kind::LAMBDA, n[0], body); } if(n.isConst() || (hasBoundVars && n.getKind() == kind::BOUND_VARIABLE)) { return n; } TypeNode t = n.getType(); if (t.isFunction() || t.isPredicate()) { if (d_enableFuncModels) { std::map< Node, Node >::const_iterator it = d_uf_models.find(n); if (it != d_uf_models.end()) { // Existing function return it->second; } // Unknown function symbol: return LAMBDA x. c, where c is the first constant in the enumeration of the range type vector<TypeNode> argTypes = t.getArgTypes(); vector<Node> args; NodeManager* nm = NodeManager::currentNM(); for (unsigned i = 0; i < argTypes.size(); ++i) { args.push_back(nm->mkBoundVar(argTypes[i])); } Node boundVarList = nm->mkNode(kind::BOUND_VAR_LIST, args); TypeEnumerator te(t.getRangeType()); return nm->mkNode(kind::LAMBDA, boundVarList, *te); } // TODO: if func models not enabled, throw an error? Unreachable(); } if (n.getNumChildren() > 0) { std::vector<Node> children; if (n.getKind() == APPLY_UF) { Node op = getModelValue(n.getOperator(), hasBoundVars); children.push_back(op); } else if (n.getMetaKind() == kind::metakind::PARAMETERIZED) { children.push_back(n.getOperator()); } //evaluate the children for (unsigned i = 0; i < n.getNumChildren(); ++i) { Node val = getModelValue(n[i], hasBoundVars); children.push_back(val); } Node val = Rewriter::rewrite(NodeManager::currentNM()->mkNode(n.getKind(), children)); Assert(hasBoundVars || val.isConst()); return val; } if (!d_equalityEngine.hasTerm(n)) { // Unknown term - return first enumerated value for this type TypeEnumerator te(n.getType()); return *te; } Node val = d_equalityEngine.getRepresentative(n); Assert(d_reps.find(val) != d_reps.end()); std::map< Node, Node >::const_iterator it = d_reps.find( val ); if( it!=d_reps.end() ){ return it->second; }else{ return Node::null(); } }
Node RemoveITE::run(TNode node, std::vector<Node>& output, IteSkolemMap& iteSkolemMap) { // Current node Debug("ite") << "removeITEs(" << node << ")" << endl; // The result may be cached already NodeManager *nodeManager = NodeManager::currentNM(); ITECache::iterator i = d_iteCache.find(node); if(i != d_iteCache.end()) { Node cachedRewrite = (*i).second; Debug("ite") << "removeITEs: in-cache: " << cachedRewrite << endl; return cachedRewrite.isNull() ? Node(node) : cachedRewrite; } // If an ITE replace it if(node.getKind() == kind::ITE) { TypeNode nodeType = node.getType(); if(!nodeType.isBoolean()) { // Make the skolem to represent the ITE Node skolem = nodeManager->mkSkolem("termITE_$$", nodeType, "a variable introduced due to term-level ITE removal"); // The new assertion Node newAssertion = nodeManager->mkNode(kind::ITE, node[0], skolem.eqNode(node[1]), skolem.eqNode(node[2])); Debug("ite") << "removeITEs(" << node << ") => " << newAssertion << endl; // Attach the skolem d_iteCache[node] = skolem; // Remove ITEs from the new assertion, rewrite it and push it to the output newAssertion = run(newAssertion, output, iteSkolemMap); iteSkolemMap[skolem] = output.size(); output.push_back(newAssertion); // The representation is now the skolem return skolem; } } // If not an ITE, go deep if( node.getKind() != kind::FORALL && node.getKind() != kind::EXISTS && node.getKind() != kind::REWRITE_RULE ) { vector<Node> newChildren; bool somethingChanged = false; if(node.getMetaKind() == kind::metakind::PARAMETERIZED) { newChildren.push_back(node.getOperator()); } // Remove the ITEs from the children for(TNode::const_iterator it = node.begin(), end = node.end(); it != end; ++it) { Node newChild = run(*it, output, iteSkolemMap); somethingChanged |= (newChild != *it); newChildren.push_back(newChild); } // If changes, we rewrite if(somethingChanged) { Node cachedRewrite = nodeManager->mkNode(node.getKind(), newChildren); d_iteCache[node] = cachedRewrite; return cachedRewrite; } else { d_iteCache[node] = Node::null(); return node; } } else { d_iteCache[node] = Node::null(); return node; } }
virtual void deleteAll() { type->deleteAll(); }
TypeNode* TypeTree::findNodeByScopeName(ScopeNameNode* scopeNameNode, TypeNode* enclosingTypeTreeNode, TemplateArguments* templateArguments) { if (templateArguments && templateArguments->m_classTypeNode->isTemplateClass())//must be TypeNameNode::calcTypeNodes { if (scopeNameNode->isTemplateForm()) { TypeNode* result = enclosingTypeTreeNode->getChildNode(scopeNameNode->m_name->m_str); if (0 == result || !result->isTemplateClass()) { return 0; } std::vector<TypeNameNode*> paramTypeNameNodes; scopeNameNode->m_parameterList->collectTypeNameNodes(paramTypeNameNodes); assert(!paramTypeNameNodes.empty()); if (paramTypeNameNodes.size() != static_cast<ClassTypeNode*>(result)->m_parameterNodes.size()) { return 0; } bool hasUndeteminedType = false; std::string name = scopeNameNode->m_name->m_str; name += "<"; auto begin = paramTypeNameNodes.begin(); auto end = paramTypeNameNodes.end(); for (auto it = begin; it != end; ++it) { if (it != begin) { name += ", "; } TypeNameNode* paramTypeNameNode = *it; assert(paramTypeNameNode->m_startTypeNode); if (0 == paramTypeNameNode->m_typeNode || paramTypeNameNode->m_typeNode->isTemplateParameter() || paramTypeNameNode->m_typeNode->isTemplateClass() || paramTypeNameNode->m_typeNode->isUnderTemplateClass()) { hasUndeteminedType = true; break; } else { assert(paramTypeNameNode->m_typeNode->isPredefinedType() || paramTypeNameNode->m_typeNode->isEnum() || paramTypeNameNode->m_typeNode->isClass() || paramTypeNameNode->m_typeNode->isTemplateClassInstance() || paramTypeNameNode->m_typeNode->isTypedef() || paramTypeNameNode->m_typeNode->isTypeDeclaration()); std::string paramName; paramTypeNameNode->m_typeNode->getActualTypeFullName(paramName); name += paramName; } } name += ">"; if (!hasUndeteminedType) { result = enclosingTypeTreeNode->getChildNode(name); } return result; } else { TypeNode* result = enclosingTypeTreeNode->getChildNode(scopeNameNode->m_name->m_str); if (0 == result || result->isTemplateClass()) { return 0; } return result; } } else { if (scopeNameNode->isTemplateForm()) { TypeNode* result = enclosingTypeTreeNode->getChildNode(scopeNameNode->m_name->m_str); if (0 == result || !result->isTemplateClass()) { return 0; } std::vector<TypeNameNode*> paramTypeNameNodes; scopeNameNode->m_parameterList->collectTypeNameNodes(paramTypeNameNodes); assert(!paramTypeNameNodes.empty()); if (paramTypeNameNodes.size() != static_cast<ClassTypeNode*>(result)->m_parameterNodes.size()) { return 0; } bool hasUndeteminedType = false; std::string name = scopeNameNode->m_name->m_str; name += "<"; auto begin = paramTypeNameNodes.begin(); auto end = paramTypeNameNodes.end(); for (auto it = begin; it != end; ++it) { if (it != begin) { name += ", "; } TypeNameNode* paramTypeNameNode = *it; TypeNode* paramTypeNode = paramTypeNameNode->getTypeNode(templateArguments); if(0 == paramTypeNode) { return 0; } else { std::string paramName; paramTypeNode->getActualTypeFullName(paramName); name += paramName; } } name += ">"; if (!hasUndeteminedType) { result = enclosingTypeTreeNode->getChildNode(name); } return result; } else { TypeNode* result = enclosingTypeTreeNode->getChildNode(scopeNameNode->m_name->m_str); if (0 == result || result->isTemplateClass()) { return 0; } return result; } } }
//this isolates the atom into solved form // veq_c * pv <> val + vts_coeff_delta * delta + vts_coeff_inf * inf // ensures val is Int if pv is Int, and val does not contain vts symbols int ArithInstantiator::solve_arith( CegInstantiator * ci, Node pv, Node atom, Node& veq_c, Node& val, Node& vts_coeff_inf, Node& vts_coeff_delta ) { int ires = 0; Trace("cbqi-inst-debug") << "isolate for " << pv << " in " << atom << std::endl; std::map< Node, Node > msum; if( QuantArith::getMonomialSumLit( atom, msum ) ){ Trace("cbqi-inst-debug") << "got monomial sum: " << std::endl; if( Trace.isOn("cbqi-inst-debug") ){ QuantArith::debugPrintMonomialSum( msum, "cbqi-inst-debug" ); } TypeNode pvtn = pv.getType(); //remove vts symbols from polynomial Node vts_coeff[2]; for( unsigned t=0; t<2; t++ ){ if( !d_vts_sym[t].isNull() ){ std::map< Node, Node >::iterator itminf = msum.find( d_vts_sym[t] ); if( itminf!=msum.end() ){ vts_coeff[t] = itminf->second; if( vts_coeff[t].isNull() ){ vts_coeff[t] = NodeManager::currentNM()->mkConst( Rational( 1 ) ); } //negate if coefficient on variable is positive std::map< Node, Node >::iterator itv = msum.find( pv ); if( itv!=msum.end() ){ //multiply by the coefficient we will isolate for if( itv->second.isNull() ){ vts_coeff[t] = QuantArith::negate(vts_coeff[t]); }else{ if( !pvtn.isInteger() ){ vts_coeff[t] = NodeManager::currentNM()->mkNode( MULT, NodeManager::currentNM()->mkConst( Rational(-1) / itv->second.getConst<Rational>() ), vts_coeff[t] ); vts_coeff[t] = Rewriter::rewrite( vts_coeff[t] ); }else if( itv->second.getConst<Rational>().sgn()==1 ){ vts_coeff[t] = QuantArith::negate(vts_coeff[t]); } } } Trace("cbqi-inst-debug") << "vts[" << t << "] coefficient is " << vts_coeff[t] << std::endl; msum.erase( d_vts_sym[t] ); } } } ires = QuantArith::isolate( pv, msum, veq_c, val, atom.getKind() ); if( ires!=0 ){ Node realPart; if( Trace.isOn("cbqi-inst-debug") ){ Trace("cbqi-inst-debug") << "Isolate : "; if( !veq_c.isNull() ){ Trace("cbqi-inst-debug") << veq_c << " * "; } Trace("cbqi-inst-debug") << pv << " " << atom.getKind() << " " << val << std::endl; } if( options::cbqiAll() ){ // when not pure LIA/LRA, we must check whether the lhs contains pv if( TermDb::containsTerm( val, pv ) ){ Trace("cbqi-inst-debug") << "fail : contains bad term" << std::endl; return 0; } } if( pvtn.isInteger() && ( ( !veq_c.isNull() && !veq_c.getType().isInteger() ) || !val.getType().isInteger() ) ){ //redo, split integer/non-integer parts bool useCoeff = false; Integer coeff = ci->getQuantifiersEngine()->getTermDatabase()->d_one.getConst<Rational>().getNumerator(); for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){ if( it->first.isNull() || it->first.getType().isInteger() ){ if( !it->second.isNull() ){ coeff = coeff.lcm( it->second.getConst<Rational>().getDenominator() ); useCoeff = true; } } } //multiply everything by this coefficient Node rcoeff = NodeManager::currentNM()->mkConst( Rational( coeff ) ); std::vector< Node > real_part; for( std::map< Node, Node >::iterator it = msum.begin(); it != msum.end(); ++it ){ if( useCoeff ){ if( it->second.isNull() ){ msum[it->first] = rcoeff; }else{ msum[it->first] = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, it->second, rcoeff ) ); } } if( !it->first.isNull() && !it->first.getType().isInteger() ){ real_part.push_back( msum[it->first].isNull() ? it->first : NodeManager::currentNM()->mkNode( MULT, msum[it->first], it->first ) ); } } //remove delta TODO: check this vts_coeff[1] = Node::null(); //multiply inf if( !vts_coeff[0].isNull() ){ vts_coeff[0] = Rewriter::rewrite( NodeManager::currentNM()->mkNode( MULT, rcoeff, vts_coeff[0] ) ); } realPart = real_part.empty() ? ci->getQuantifiersEngine()->getTermDatabase()->d_zero : ( real_part.size()==1 ? real_part[0] : NodeManager::currentNM()->mkNode( PLUS, real_part ) ); Assert( ci->getOutput()->isEligibleForInstantiation( realPart ) ); //re-isolate Trace("cbqi-inst-debug") << "Re-isolate..." << std::endl; ires = QuantArith::isolate( pv, msum, veq_c, val, atom.getKind() ); Trace("cbqi-inst-debug") << "Isolate for mixed Int/Real : " << veq_c << " * " << pv << " " << atom.getKind() << " " << val << std::endl; Trace("cbqi-inst-debug") << " real part : " << realPart << std::endl; if( ires!=0 ){ int ires_use = ( msum[pv].isNull() || msum[pv].getConst<Rational>().sgn()==1 ) ? 1 : -1; val = Rewriter::rewrite( NodeManager::currentNM()->mkNode( ires_use==-1 ? PLUS : MINUS, NodeManager::currentNM()->mkNode( ires_use==-1 ? MINUS : PLUS, val, realPart ), NodeManager::currentNM()->mkNode( TO_INTEGER, realPart ) ) ); //TODO: round up for upper bounds? Trace("cbqi-inst-debug") << "result : " << val << std::endl; Assert( val.getType().isInteger() ); } } } vts_coeff_inf = vts_coeff[0]; vts_coeff_delta = vts_coeff[1]; Trace("cbqi-inst-debug") << "Return " << veq_c << " * " << pv << " " << atom.getKind() << " " << val << ", vts = (" << vts_coeff_inf << ", " << vts_coeff_delta << ")" << std::endl; }else{ Trace("cbqi-inst-debug") << "fail : could not get monomial sum" << std::endl; } return ires; }
TypeNode exportTypeInternal(TypeNode n, NodeManager* from, NodeManager* to, ExprManagerMapCollection& vmap) { Debug("export") << "type: " << n << " " << n.getId() << std::endl; if(theory::kindToTheoryId(n.getKind()) == theory::THEORY_DATATYPES) { throw ExportUnsupportedException ("export of types belonging to theory of DATATYPES kinds unsupported"); } if(n.getMetaKind() == kind::metakind::PARAMETERIZED && n.getKind() != kind::SORT_TYPE) { throw ExportUnsupportedException ("export of PARAMETERIZED-kinded types (other than SORT_KIND) not supported"); } if(n.getKind() == kind::TYPE_CONSTANT) { return to->mkTypeConst(n.getConst<TypeConstant>()); } else if(n.getKind() == kind::BITVECTOR_TYPE) { return to->mkBitVectorType(n.getConst<BitVectorSize>()); } else if(n.getKind() == kind::SUBRANGE_TYPE) { return to->mkSubrangeType(n.getSubrangeBounds()); } Type from_t = from->toType(n); Type& to_t = vmap.d_typeMap[from_t]; if(! to_t.isNull()) { Debug("export") << "+ mapped `" << from_t << "' to `" << to_t << "'" << std::endl; return *Type::getTypeNode(to_t); } NodeBuilder<> children(to, n.getKind()); if(n.getKind() == kind::SORT_TYPE) { Debug("export") << "type: operator: " << n.getOperator() << std::endl; // make a new sort tag in target node manager Node sortTag = NodeBuilder<0>(to, kind::SORT_TAG); children << sortTag; } for(TypeNode::iterator i = n.begin(), i_end = n.end(); i != i_end; ++i) { Debug("export") << "type: child: " << *i << std::endl; children << exportTypeInternal(*i, from, to, vmap); } TypeNode out = children.constructTypeNode();// FIXME thread safety to_t = to->toType(out); return out; }/* exportTypeInternal() */
void CoreSolver::buildModel() { Debug("bv-core") << "CoreSolver::buildModel() \n"; d_modelValues.clear(); TNodeSet constants; TNodeSet constants_in_eq_engine; // collect constants in equality engine eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(&d_equalityEngine); while (!eqcs_i.isFinished()) { TNode repr = *eqcs_i; if (repr.getKind() == kind::CONST_BITVECTOR) { // must check if it's just the constant eq::EqClassIterator it(repr, &d_equalityEngine); if (!(++it).isFinished() || true) { constants.insert(repr); constants_in_eq_engine.insert(repr); } } ++eqcs_i; } // build repr to value map eqcs_i = eq::EqClassesIterator(&d_equalityEngine); while (!eqcs_i.isFinished()) { TNode repr = *eqcs_i; ++eqcs_i; if (repr.getKind() != kind::VARIABLE && repr.getKind() != kind::SKOLEM && repr.getKind() != kind::CONST_BITVECTOR && !d_bv->isSharedTerm(repr)) { continue; } TypeNode type = repr.getType(); if (type.isBitVector() && repr.getKind()!= kind::CONST_BITVECTOR) { Debug("bv-core-model") << " processing " << repr <<"\n"; // we need to assign a value for it TypeEnumerator te(type); Node val; do { val = *te; ++te; // Debug("bv-core-model") << " trying value " << val << "\n"; // Debug("bv-core-model") << " is in set? " << constants.count(val) << "\n"; // Debug("bv-core-model") << " enumerator done? " << te.isFinished() << "\n"; } while (constants.count(val) != 0 && !(te.isFinished())); if (te.isFinished() && constants.count(val) != 0) { // if we cannot enumerate anymore values we just return the lemma stating that // at least two of the representatives are equal. std::vector<TNode> representatives; representatives.push_back(repr); for (TNodeSet::const_iterator it = constants_in_eq_engine.begin(); it != constants_in_eq_engine.end(); ++it) { TNode constant = *it; if (utils::getSize(constant) == utils::getSize(repr)) { representatives.push_back(constant); } } for (ModelValue::const_iterator it = d_modelValues.begin(); it != d_modelValues.end(); ++it) { representatives.push_back(it->first); } std::vector<Node> equalities; for (unsigned i = 0; i < representatives.size(); ++i) { for (unsigned j = i + 1; j < representatives.size(); ++j) { TNode a = representatives[i]; TNode b = representatives[j]; if (a.getKind() == kind::CONST_BITVECTOR && b.getKind() == kind::CONST_BITVECTOR) { Assert (a != b); continue; } if (utils::getSize(a) == utils::getSize(b)) { equalities.push_back(utils::mkNode(kind::EQUAL, a, b)); } } } // better off letting the SAT solver split on values if (equalities.size() > d_lemmaThreshold) { d_isComplete = false; return; } Node lemma = utils::mkOr(equalities); d_bv->lemma(lemma); Debug("bv-core") << " lemma: " << lemma << "\n"; return; } Debug("bv-core-model") << " " << repr << " => " << val <<"\n" ; constants.insert(val); d_modelValues[repr] = val; } } }
TypeNode NodeManager::getDatatypeForTupleRecord(TypeNode t) { Assert(t.isTuple() || t.isRecord()); //AJR: not sure why .getBaseType() was used in two cases below, // disabling this, which is necessary to fix bug 605/667, // which involves records of INT which were mapped to records of REAL below. TypeNode tOrig = t; if(t.isTuple()) { vector<TypeNode> v; bool changed = false; for(size_t i = 0; i < t.getNumChildren(); ++i) { TypeNode tn = t[i]; TypeNode base; if(tn.isTuple() || tn.isRecord()) { base = getDatatypeForTupleRecord(tn); } else { base = tn;//.getBaseType(); } changed = changed || (tn != base); v.push_back(base); } if(changed) { t = mkTupleType(v); } } else { const Record& r = t.getRecord(); std::vector< std::pair<std::string, Type> > v; bool changed = false; const Record::FieldVector& fields = r.getFields(); for(Record::FieldVector::const_iterator i = fields.begin(); i != fields.end(); ++i) { Type tn = (*i).second; Type base; if(tn.isTuple() || tn.isRecord()) { base = getDatatypeForTupleRecord(TypeNode::fromType(tn)).toType(); } else { base = tn;//.getBaseType(); } changed = changed || (tn != base); v.push_back(std::make_pair((*i).first, base)); } if(changed) { t = mkRecordType(Record(v)); } } // if the type doesn't have an associated datatype, then make one for it TypeNode& dtt = d_tupleAndRecordTypes[t]; if(dtt.isNull()) { if(t.isTuple()) { Datatype dt("__cvc4_tuple"); DatatypeConstructor c("__cvc4_tuple_ctor"); for(TypeNode::const_iterator i = t.begin(); i != t.end(); ++i) { c.addArg("__cvc4_tuple_stor", (*i).toType()); } dt.addConstructor(c); dtt = TypeNode::fromType(toExprManager()->mkDatatypeType(dt)); Debug("tuprec") << "REWROTE " << t << " to " << dtt << std::endl; dtt.setAttribute(DatatypeTupleAttr(), tOrig); } else { const Record& rec = t.getRecord(); const Record::FieldVector& fields = rec.getFields(); Datatype dt("__cvc4_record"); DatatypeConstructor c("__cvc4_record_ctor"); for(Record::FieldVector::const_iterator i = fields.begin(); i != fields.end(); ++i) { c.addArg((*i).first, (*i).second); } dt.addConstructor(c); dtt = TypeNode::fromType(toExprManager()->mkDatatypeType(dt)); Debug("tuprec") << "REWROTE " << t << " to " << dtt << std::endl; dtt.setAttribute(DatatypeRecordAttr(), tOrig); } } else { Debug("tuprec") << "REUSING cached " << t << ": " << dtt << std::endl; } Assert(!dtt.isNull()); return dtt; }
void BoundedIntegers::registerQuantifier( Node f ) { Trace("bound-int") << "Register quantifier " << f << std::endl; bool success; do{ std::map< Node, unsigned > bound_lit_type_map; std::map< int, std::map< Node, Node > > bound_lit_map; std::map< int, std::map< Node, bool > > bound_lit_pol_map; std::map< int, std::map< Node, Node > > bound_int_range_term; success = false; process( f, f[1], true, bound_lit_type_map, bound_lit_map, bound_lit_pol_map, bound_int_range_term ); //for( std::map< Node, Node >::iterator it = d_bounds[0][f].begin(); it != d_bounds[0][f].end(); ++it ){ for( std::map< Node, unsigned >::iterator it = bound_lit_type_map.begin(); it != bound_lit_type_map.end(); ++it ){ Node v = it->first; if( !isBound( f, v ) ){ bool setBoundVar = false; if( it->second==BOUND_INT_RANGE ){ //must have both if( bound_lit_map[0].find( v )!=bound_lit_map[0].end() && bound_lit_map[1].find( v )!=bound_lit_map[1].end() ){ setBoundedVar( f, v, BOUND_INT_RANGE ); setBoundVar = true; success = true; for( unsigned b=0; b<2; b++ ){ //set the bounds Assert( bound_int_range_term[b].find( v )!=bound_int_range_term[b].end() ); d_bounds[b][f][v] = bound_int_range_term[b][v]; } Node r = NodeManager::currentNM()->mkNode( MINUS, d_bounds[1][f][v], d_bounds[0][f][v] ); d_range[f][v] = Rewriter::rewrite( r ); Trace("bound-int") << "Variable " << v << " is bound because of int range literals " << bound_lit_map[0][v] << " and " << bound_lit_map[1][v] << std::endl; } }else if( it->second==BOUND_SET_MEMBER ){ setBoundedVar( f, v, BOUND_SET_MEMBER ); setBoundVar = true; d_setm_range[f][v] = bound_lit_map[0][v][1]; Trace("bound-int") << "Variable " << v << " is bound because of set membership literal " << bound_lit_map[0][v] << std::endl; } if( setBoundVar ){ //set Attributes on literals for( unsigned b=0; b<2; b++ ){ if( bound_lit_map[b].find( v )!=bound_lit_map[b].end() ){ Assert( bound_lit_pol_map[b].find( v )!=bound_lit_pol_map[b].end() ); BoundIntLitAttribute bila; bound_lit_map[b][v].setAttribute( bila, bound_lit_pol_map[b][v] ? 1 : 0 ); }else{ Assert( it->second!=BOUND_INT_RANGE ); } } } } } }while( success ); Trace("bound-int") << "Bounds are : " << std::endl; for( unsigned i=0; i<d_set[f].size(); i++) { Node v = d_set[f][i]; if( d_bound_type[f][v]==BOUND_INT_RANGE ){ Trace("bound-int") << " " << d_bounds[0][f][v] << " <= " << v << " <= " << d_bounds[1][f][v] << " (range is " << d_range[f][v] << ")" << std::endl; }else if( d_bound_type[f][v]==BOUND_SET_MEMBER ){ Trace("bound-int") << " " << v << " in " << d_setm_range[f][v] << std::endl; } } bool bound_success = true; for( unsigned i=0; i<f[0].getNumChildren(); i++) { if( d_bound_type[f].find( f[0][i] )==d_bound_type[f].end() ){ TypeNode tn = f[0][i].getType(); if( !tn.isSort() && !getTermDatabase()->mayComplete( tn ) ){ Trace("bound-int-warn") << "Warning : Bounded Integers : Due to quantification on " << f[0][i] << ", could not find bounds for " << f << std::endl; bound_success = false; break; } } } if( bound_success ){ d_bound_quants.push_back( f ); for( unsigned i=0; i<d_set[f].size(); i++) { Node v = d_set[f][i]; if( d_bound_type[f][v]==BOUND_INT_RANGE || d_bound_type[f][v]==BOUND_SET_MEMBER ){ Node r; if( d_bound_type[f][v]==BOUND_INT_RANGE ){ r = d_range[f][v]; }else if( d_bound_type[f][v]==BOUND_SET_MEMBER ){ r = NodeManager::currentNM()->mkNode( CARD, d_setm_range[f][v] ); } bool isProxy = false; if( r.hasBoundVar() ){ //introduce a new bound Node new_range = NodeManager::currentNM()->mkSkolem( "bir", r.getType(), "bound for term" ); d_nground_range[f][v] = d_range[f][v]; d_range[f][v] = new_range; r = new_range; isProxy = true; } if( !r.isConst() ){ if( std::find(d_ranges.begin(), d_ranges.end(), r)==d_ranges.end() ){ Trace("bound-int") << "For " << v << ", bounded Integer Module will try to minimize : " << r << std::endl; d_ranges.push_back( r ); d_rms[r] = new IntRangeModel( this, r, d_quantEngine->getSatContext(), d_quantEngine->getUserContext(), isProxy ); d_rms[r]->initialize(); } } } } } }
bool RepSetIterator::initialize(){ for( size_t i=0; i<d_types.size(); i++ ){ d_index.push_back( 0 ); //store default index order d_index_order.push_back( i ); d_var_order[i] = i; //store default domain d_domain.push_back( RepDomain() ); TypeNode tn = d_types[i]; if( tn.isSort() ){ if( !d_rep_set->hasType( tn ) ){ Node var = NodeManager::currentNM()->mkSkolem( "repSet", tn, "is a variable created by the RepSetIterator" ); Trace("mkVar") << "RepSetIterator:: Make variable " << var << " : " << tn << std::endl; d_rep_set->add( tn, var ); } }else if( tn.isInteger() ){ bool inc = false; //check if it is bound if( d_owner.getKind()==FORALL && d_qe && d_qe->getBoundedIntegers() ){ if( d_qe->getBoundedIntegers()->isBoundVar( d_owner, d_owner[0][i] ) ){ Trace("bound-int-rsi") << "Rep set iterator: variable #" << i << " is bounded integer." << std::endl; d_enum_type.push_back( ENUM_RANGE ); }else{ inc = true; } }else{ inc = true; } if( inc ){ //check if it is otherwise bound if( d_bounds[0].find(i)!=d_bounds[0].end() && d_bounds[1].find(i)!=d_bounds[1].end() ){ Trace("bound-int-rsi") << "Rep set iterator: variable #" << i << " is bounded." << std::endl; d_enum_type.push_back( ENUM_RANGE ); }else{ Trace("fmf-incomplete") << "Incomplete because of integer quantification of " << d_owner[0][i] << "." << std::endl; d_incomplete = true; } } //enumerate if the sort is reasonably small, the upper bound of 1000 is chosen arbitrarily for now }else if( tn.getCardinality().isFinite() && !tn.getCardinality().isLargeFinite() && tn.getCardinality().getFiniteCardinality().toUnsignedInt()<=1000 ){ d_rep_set->complete( tn ); }else{ Trace("fmf-incomplete") << "Incomplete because of quantification of type " << tn << std::endl; d_incomplete = true; } if( d_enum_type.size()<=i ){ d_enum_type.push_back( ENUM_DOMAIN_ELEMENTS ); if( d_rep_set->hasType( tn ) ){ for( size_t j=0; j<d_rep_set->d_type_reps[tn].size(); j++ ){ d_domain[i].push_back( j ); } }else{ return false; } } } //must set a variable index order based on bounded integers if (d_owner.getKind()==FORALL && d_qe && d_qe->getBoundedIntegers()) { Trace("bound-int-rsi") << "Calculating variable order..." << std::endl; std::vector< int > varOrder; for( unsigned i=0; i<d_qe->getBoundedIntegers()->getNumBoundVars(d_owner); i++ ){ varOrder.push_back(d_qe->getBoundedIntegers()->getBoundVarNum(d_owner,i)); } for( unsigned i=0; i<d_owner[0].getNumChildren(); i++) { if( !d_qe->getBoundedIntegers()->isBoundVar(d_owner, d_owner[0][i])) { varOrder.push_back(i); } } Trace("bound-int-rsi") << "Variable order : "; for( unsigned i=0; i<varOrder.size(); i++) { Trace("bound-int-rsi") << varOrder[i] << " "; } Trace("bound-int-rsi") << std::endl; std::vector< int > indexOrder; indexOrder.resize(varOrder.size()); for( unsigned i=0; i<varOrder.size(); i++){ indexOrder[varOrder[i]] = i; } Trace("bound-int-rsi") << "Will use index order : "; for( unsigned i=0; i<indexOrder.size(); i++) { Trace("bound-int-rsi") << indexOrder[i] << " "; } Trace("bound-int-rsi") << std::endl; setIndexOrder(indexOrder); } //now reset the indices for (unsigned i=0; i<d_index.size(); i++) { if (!resetIndex(i, true)){ break; } } return true; }
bool RepSetIterator::initialize( RepBoundExt* rext ){ Trace("rsi") << "Initialize rep set iterator..." << std::endl; for( unsigned v=0; v<d_types.size(); v++ ){ d_index.push_back( 0 ); //store default index order d_index_order.push_back( v ); d_var_order[v] = v; //store default domain //d_domain.push_back( RepDomain() ); d_domain_elements.push_back( std::vector< Node >() ); TypeNode tn = d_types[v]; Trace("rsi") << "Var #" << v << " is type " << tn << "..." << std::endl; if( tn.isSort() ){ //must ensure uninterpreted type is non-empty. if( !d_rep_set->hasType( tn ) ){ //FIXME: // terms in rep_set are now constants which mapped to terms through TheoryModel // thus, should introduce a constant and a term. for now, just a term. //Node c = d_qe->getTermDatabase()->getEnumerateTerm( tn, 0 ); Node var = d_qe->getModel()->getSomeDomainElement( tn ); Trace("mkVar") << "RepSetIterator:: Make variable " << var << " : " << tn << std::endl; d_rep_set->add( tn, var ); } } bool inc = true; //check if it is externally bound if( rext && rext->setBound( d_owner, v, tn, d_domain_elements[v] ) ){ d_enum_type.push_back( ENUM_DEFAULT ); inc = false; //builtin: check if it is bound by bounded integer module }else if( d_owner.getKind()==FORALL && d_qe && d_qe->getBoundedIntegers() ){ if( d_qe->getBoundedIntegers()->isBoundVar( d_owner, d_owner[0][v] ) ){ unsigned bvt = d_qe->getBoundedIntegers()->getBoundVarType( d_owner, d_owner[0][v] ); if( bvt!=quantifiers::BoundedIntegers::BOUND_FINITE ){ d_enum_type.push_back( ENUM_BOUND_INT ); inc = false; }else{ //will treat in default way } } } if( !tn.isSort() ){ if( inc ){ if( d_qe->getTermDatabase()->mayComplete( tn ) ){ Trace("rsi") << " do complete, since cardinality is small (" << tn.getCardinality() << ")..." << std::endl; d_rep_set->complete( tn ); //must have succeeded Assert( d_rep_set->hasType( tn ) ); }else{ Trace("rsi") << " variable cannot be bounded." << std::endl; Trace("fmf-incomplete") << "Incomplete because of quantification of type " << tn << std::endl; d_incomplete = true; } } } //if we have yet to determine the type of enumeration if( d_enum_type.size()<=v ){ if( d_rep_set->hasType( tn ) ){ d_enum_type.push_back( ENUM_DEFAULT ); for( unsigned j=0; j<d_rep_set->d_type_reps[tn].size(); j++ ){ //d_domain[v].push_back( j ); d_domain_elements[v].push_back( d_rep_set->d_type_reps[tn][j] ); } }else{ Assert( d_incomplete ); return false; } } } //must set a variable index order based on bounded integers if( d_owner.getKind()==FORALL && d_qe && d_qe->getBoundedIntegers() ){ Trace("bound-int-rsi") << "Calculating variable order..." << std::endl; std::vector< int > varOrder; for( unsigned i=0; i<d_qe->getBoundedIntegers()->getNumBoundVars( d_owner ); i++ ){ Node v = d_qe->getBoundedIntegers()->getBoundVar( d_owner, i ); Trace("bound-int-rsi") << " bound var #" << i << " is " << v << std::endl; varOrder.push_back( d_qe->getTermDatabase()->getVariableNum( d_owner, v ) ); } for( unsigned i=0; i<d_owner[0].getNumChildren(); i++) { if( !d_qe->getBoundedIntegers()->isBoundVar(d_owner, d_owner[0][i])) { varOrder.push_back(i); } } Trace("bound-int-rsi") << "Variable order : "; for( unsigned i=0; i<varOrder.size(); i++) { Trace("bound-int-rsi") << varOrder[i] << " "; } Trace("bound-int-rsi") << std::endl; std::vector< int > indexOrder; indexOrder.resize(varOrder.size()); for( unsigned i=0; i<varOrder.size(); i++){ indexOrder[varOrder[i]] = i; } Trace("bound-int-rsi") << "Will use index order : "; for( unsigned i=0; i<indexOrder.size(); i++) { Trace("bound-int-rsi") << indexOrder[i] << " "; } Trace("bound-int-rsi") << std::endl; setIndexOrder( indexOrder ); } //now reset the indices do_reset_increment( -1, true ); return true; }
void UnconstrainedSimplifier::processUnconstrained() { TNodeSet::iterator it = d_unconstrained.begin(), iend = d_unconstrained.end(); vector<TNode> workList; for ( ; it != iend; ++it) { workList.push_back(*it); } Node currentSub; TNode parent; bool swap; bool isSigned; bool strict; vector<TNode> delayQueueLeft; vector<Node> delayQueueRight; TNode current = workList.back(); workList.pop_back(); for (;;) { Assert(d_visitedOnce.find(current) != d_visitedOnce.end()); parent = d_visitedOnce[current]; if (!parent.isNull()) { swap = isSigned = strict = false; switch (parent.getKind()) { // If-then-else operator - any two unconstrained children makes the parent unconstrained case kind::ITE: { Assert(parent[0] == current || parent[1] == current || parent[2] == current); bool uCond = parent[0] == current || d_unconstrained.find(parent[0]) != d_unconstrained.end(); bool uThen = parent[1] == current || d_unconstrained.find(parent[1]) != d_unconstrained.end(); bool uElse = parent[2] == current || d_unconstrained.find(parent[2]) != d_unconstrained.end(); if ((uCond && uThen) || (uCond && uElse) || (uThen && uElse)) { if (d_unconstrained.find(parent) == d_unconstrained.end() && !d_substitutions.hasSubstitution(parent)) { ++d_numUnconstrainedElim; if (uThen) { if (parent[1] != current) { if (parent[1].isVar()) { currentSub = parent[1]; } else { Assert(d_substitutions.hasSubstitution(parent[1])); currentSub = d_substitutions.apply(parent[1]); } } else if (currentSub.isNull()) { currentSub = current; } } else if (parent[2] != current) { if (parent[2].isVar()) { currentSub = parent[2]; } else { Assert(d_substitutions.hasSubstitution(parent[2])); currentSub = d_substitutions.apply(parent[2]); } } else if (currentSub.isNull()) { currentSub = current; } current = parent; } else { currentSub = Node(); } } else if (uCond) { Cardinality card = parent.getType().getCardinality(); if (card.isFinite() && !card.isLargeFinite() && card.getFiniteCardinality() == 2) { // Special case: condition is unconstrained, then and else are different, and total cardinality of the type is 2, then the result // is unconstrained Node test; if (parent.getType().isBoolean()) { test = Rewriter::rewrite(parent[1].iffNode(parent[2])); } else { test = Rewriter::rewrite(parent[1].eqNode(parent[2])); } if (test == NodeManager::currentNM()->mkConst<bool>(false)) { ++d_numUnconstrainedElim; if (currentSub.isNull()) { currentSub = current; } currentSub = newUnconstrainedVar(parent.getType(), currentSub); current = parent; } } } break; } // Comparisons that return a different type - assuming domains are larger than 1, any // unconstrained child makes parent unconstrained as well case kind::EQUAL: if (parent[0].getType() != parent[1].getType()) { TNode other = (parent[0] == current) ? parent[1] : parent[0]; if (current.getType().isSubtypeOf(other.getType())) { break; } } if( parent[0].getType().isDatatype() ){ TypeNode tn = parent[0].getType(); const Datatype& dt = ((DatatypeType)(tn).toType()).getDatatype(); if( dt.isRecursiveSingleton( tn.toType() ) ){ //domain size may be 1 break; } } case kind::BITVECTOR_COMP: case kind::LT: case kind::LEQ: case kind::GT: case kind::GEQ: { if (d_unconstrained.find(parent) == d_unconstrained.end() && !d_substitutions.hasSubstitution(parent)) { ++d_numUnconstrainedElim; Assert(parent[0] != parent[1] && (parent[0] == current || parent[1] == current)); if (currentSub.isNull()) { currentSub = current; } currentSub = newUnconstrainedVar(parent.getType(), currentSub); current = parent; } else { currentSub = Node(); } break; } // Unary operators that propagate unconstrainedness case kind::NOT: case kind::BITVECTOR_NOT: case kind::BITVECTOR_NEG: case kind::UMINUS: ++d_numUnconstrainedElim; Assert(parent[0] == current); if (currentSub.isNull()) { currentSub = current; } current = parent; break; // Unary operators that propagate unconstrainedness and return a different type case kind::BITVECTOR_EXTRACT: ++d_numUnconstrainedElim; Assert(parent[0] == current); if (currentSub.isNull()) { currentSub = current; } currentSub = newUnconstrainedVar(parent.getType(), currentSub); current = parent; break; // Operators returning same type requiring all children to be unconstrained case kind::AND: case kind::OR: case kind::IMPLIES: case kind::BITVECTOR_AND: case kind::BITVECTOR_OR: case kind::BITVECTOR_NAND: case kind::BITVECTOR_NOR: { bool allUnconstrained = true; for(TNode::iterator child_it = parent.begin(); child_it != parent.end(); ++child_it) { if (d_unconstrained.find(*child_it) == d_unconstrained.end()) { allUnconstrained = false; break; } } if (allUnconstrained) { if (d_unconstrained.find(parent) == d_unconstrained.end() && !d_substitutions.hasSubstitution(parent)) { ++d_numUnconstrainedElim; if (currentSub.isNull()) { currentSub = current; } current = parent; } else { currentSub = Node(); } } } break; // Require all children to be unconstrained and different case kind::BITVECTOR_SHL: case kind::BITVECTOR_LSHR: case kind::BITVECTOR_ASHR: case kind::BITVECTOR_UDIV_TOTAL: case kind::BITVECTOR_UREM_TOTAL: case kind::BITVECTOR_SDIV: case kind::BITVECTOR_SREM: case kind::BITVECTOR_SMOD: { bool allUnconstrained = true; bool allDifferent = true; for(TNode::iterator child_it = parent.begin(); child_it != parent.end(); ++child_it) { if (d_unconstrained.find(*child_it) == d_unconstrained.end()) { allUnconstrained = false; break; } for(TNode::iterator child_it2 = child_it + 1; child_it2 != parent.end(); ++child_it2) { if (*child_it == *child_it2) { allDifferent = false; break; } } } if (allUnconstrained && allDifferent) { if (d_unconstrained.find(parent) == d_unconstrained.end() && !d_substitutions.hasSubstitution(parent)) { ++d_numUnconstrainedElim; if (currentSub.isNull()) { currentSub = current; } current = parent; } else { currentSub = Node(); } } break; } // Requires all children to be unconstrained and different, and returns a different type case kind::BITVECTOR_CONCAT: { bool allUnconstrained = true; bool allDifferent = true; for(TNode::iterator child_it = parent.begin(); child_it != parent.end(); ++child_it) { if (d_unconstrained.find(*child_it) == d_unconstrained.end()) { allUnconstrained = false; break; } for(TNode::iterator child_it2 = child_it + 1; child_it2 != parent.end(); ++child_it2) { if (*child_it == *child_it2) { allDifferent = false; break; } } } if (allUnconstrained && allDifferent) { if (d_unconstrained.find(parent) == d_unconstrained.end() && !d_substitutions.hasSubstitution(parent)) { ++d_numUnconstrainedElim; if (currentSub.isNull()) { currentSub = current; } currentSub = newUnconstrainedVar(parent.getType(), currentSub); current = parent; } else { currentSub = Node(); } } } break; // N-ary operators returning same type requiring at least one child to be unconstrained case kind::PLUS: case kind::MINUS: if (current.getType().isInteger() && !parent.getType().isInteger()) { break; } case kind::IFF: case kind::XOR: case kind::BITVECTOR_XOR: case kind::BITVECTOR_XNOR: case kind::BITVECTOR_PLUS: case kind::BITVECTOR_SUB: if (d_unconstrained.find(parent) == d_unconstrained.end() && !d_substitutions.hasSubstitution(parent)) { ++d_numUnconstrainedElim; if (currentSub.isNull()) { currentSub = current; } current = parent; } else { currentSub = Node(); } break; // Multiplication/division: must be non-integer and other operand must be non-zero case kind::MULT: { case kind::DIVISION: Assert(parent.getNumChildren() == 2); TNode other; if (parent[0] == current) { other = parent[1]; } else { Assert(parent[1] == current); other = parent[0]; } if (d_unconstrained.find(other) != d_unconstrained.end()) { if (d_unconstrained.find(parent) == d_unconstrained.end() && !d_substitutions.hasSubstitution(parent)) { if (current.getType().isInteger() && other.getType().isInteger()) { Assert(parent.getKind() == kind::DIVISION || parent.getType().isInteger()); if (parent.getKind() == kind::DIVISION) { break; } } ++d_numUnconstrainedElim; if (currentSub.isNull()) { currentSub = current; } current = parent; } else { currentSub = Node(); } } else { // if only the denominator of a division is unconstrained, can't set it to 0 so the result is not unconstrained if (parent.getKind() == kind::DIVISION && current == parent[1]) { break; } NodeManager* nm = NodeManager::currentNM(); // if we are an integer, the only way we are unconstrained is if we are a MULT by -1 if (current.getType().isInteger()) { // div/mult by 1 should have been simplified Assert(other != nm->mkConst<Rational>(1)); if (other == nm->mkConst<Rational>(-1)) { // div by -1 should have been simplified Assert(parent.getKind() == kind::MULT); Assert(parent.getType().isInteger()); } else { break; } } else { // TODO: could build ITE here Node test = other.eqNode(nm->mkConst<Rational>(0)); if (Rewriter::rewrite(test) != nm->mkConst<bool>(false)) { break; } } ++d_numUnconstrainedElim; if (currentSub.isNull()) { currentSub = current; } current = parent; } break; } // Bitvector MULT - current must only appear once in the children: // all other children must be unconstrained or odd case kind::BITVECTOR_MULT: { bool found = false; bool done = false; for(TNode::iterator child_it = parent.begin(); child_it != parent.end(); ++child_it) { if ((*child_it) == current) { if (found) { done = true; break; } found = true; continue; } else if (d_unconstrained.find(*child_it) != d_unconstrained.end()) { continue; } else { NodeManager* nm = NodeManager::currentNM(); Node extractOp = nm->mkConst<BitVectorExtract>(BitVectorExtract(0,0)); vector<Node> children; children.push_back(*child_it); Node test = nm->mkNode(extractOp, children); BitVector one(1,unsigned(1)); test = test.eqNode(nm->mkConst<BitVector>(one)); if (Rewriter::rewrite(test) != nm->mkConst<bool>(true)) { done = true; break; } } } if (done) { break; } if (d_unconstrained.find(parent) == d_unconstrained.end() && !d_substitutions.hasSubstitution(parent)) { ++d_numUnconstrainedElim; if (currentSub.isNull()) { currentSub = current; } current = parent; } else { currentSub = Node(); } break; } // Uninterpreted function - if domain is infinite, no quantifiers are used, and any child is unconstrained, result is unconstrained case kind::APPLY_UF: if (d_logicInfo.isQuantified() || !current.getType().getCardinality().isInfinite()) { break; } if (d_unconstrained.find(parent) == d_unconstrained.end() && !d_substitutions.hasSubstitution(parent)) { ++d_numUnconstrainedElim; if (currentSub.isNull()) { currentSub = current; } if (parent.getType() != current.getType()) { currentSub = newUnconstrainedVar(parent.getType(), currentSub); } current = parent; } else { currentSub = Node(); } break; // Array select - if array is unconstrained, so is result case kind::SELECT: if (parent[0] == current) { ++d_numUnconstrainedElim; Assert(current.getType().isArray()); if (currentSub.isNull()) { currentSub = current; } currentSub = newUnconstrainedVar(current.getType().getArrayConstituentType(), currentSub); current = parent; } break; // Array store - if both store and value are unconstrained, so is resulting store case kind::STORE: if (((parent[0] == current && d_unconstrained.find(parent[2]) != d_unconstrained.end()) || (parent[2] == current && d_unconstrained.find(parent[0]) != d_unconstrained.end()))) { if (d_unconstrained.find(parent) == d_unconstrained.end() && !d_substitutions.hasSubstitution(parent)) { ++d_numUnconstrainedElim; if (parent[0] != current) { if (parent[0].isVar()) { currentSub = parent[0]; } else { Assert(d_substitutions.hasSubstitution(parent[0])); currentSub = d_substitutions.apply(parent[0]); } } else if (currentSub.isNull()) { currentSub = current; } current = parent; } else { currentSub = Node(); } } break; // Bit-vector comparisons: replace with new Boolean variable, but have // to also conjoin with a side condition as there is always one case // when the comparison is forced to be false case kind::BITVECTOR_ULT: case kind::BITVECTOR_UGE: case kind::BITVECTOR_UGT: case kind::BITVECTOR_ULE: case kind::BITVECTOR_SLT: case kind::BITVECTOR_SGE: case kind::BITVECTOR_SGT: case kind::BITVECTOR_SLE: { // Tuples over (signed, swap, strict). switch (parent.getKind()) { case kind::BITVECTOR_UGE: break; case kind::BITVECTOR_ULT: strict = true; break; case kind::BITVECTOR_ULE: swap = true; break; case kind::BITVECTOR_UGT: swap = true; strict = true; break; case kind::BITVECTOR_SGE: isSigned = true; break; case kind::BITVECTOR_SLT: isSigned = true; strict = true; break; case kind::BITVECTOR_SLE: isSigned = true; swap = true; break; case kind::BITVECTOR_SGT: isSigned = true; swap = true; strict = true; break; default: Unreachable(); } TNode other; bool left = false; if (parent[0] == current) { other = parent[1]; left = true; } else { Assert(parent[1] == current); other = parent[0]; } if (d_unconstrained.find(other) != d_unconstrained.end()) { if (d_unconstrained.find(parent) == d_unconstrained.end() && !d_substitutions.hasSubstitution(parent)) { ++d_numUnconstrainedElim; if (currentSub.isNull()) { currentSub = current; } currentSub = newUnconstrainedVar(parent.getType(), currentSub); current = parent; } else { currentSub = Node(); } } else { unsigned size = current.getType().getBitVectorSize(); BitVector bv = isSigned ? BitVector(size, Integer(1).multiplyByPow2(size - 1)) : BitVector(size, unsigned(0)); if (swap == left) { bv = ~bv; } if (currentSub.isNull()) { currentSub = current; } currentSub = newUnconstrainedVar(parent.getType(), currentSub); current = parent; NodeManager* nm = NodeManager::currentNM(); Node test = Rewriter::rewrite(other.eqNode(nm->mkConst<BitVector>(bv))); if (test == nm->mkConst<bool>(false)) { break; } if (strict) { currentSub = currentSub.andNode(test.notNode()); } else { currentSub = currentSub.orNode(test); } // Delay adding this substitution - see comment at end of function delayQueueLeft.push_back(current); delayQueueRight.push_back(currentSub); currentSub = Node(); parent = TNode(); } break; } // Do nothing case kind::BITVECTOR_SIGN_EXTEND: case kind::BITVECTOR_ZERO_EXTEND: case kind::BITVECTOR_REPEAT: case kind::BITVECTOR_ROTATE_LEFT: case kind::BITVECTOR_ROTATE_RIGHT: default: break; } if (current == parent && d_visited[parent] == 1) { d_unconstrained.insert(parent); continue; } } if (!currentSub.isNull()) { Assert(currentSub.isVar()); d_substitutions.addSubstitution(current, currentSub, false); } if (workList.empty()) { break; } current = workList.back(); currentSub = Node(); workList.pop_back(); } TNode left; Node right; // All substitutions except those arising from bitvector comparisons are // substitutions t -> x where x is a variable. This allows us to build the // substitution very quickly (never invalidating the substitution cache). // Bitvector comparisons are more complicated and may require // back-substitution and cache-invalidation. So we do these last. while (!delayQueueLeft.empty()) { left = delayQueueLeft.back(); if (!d_substitutions.hasSubstitution(left)) { right = d_substitutions.apply(delayQueueRight.back()); d_substitutions.addSubstitution(delayQueueLeft.back(), right); } delayQueueLeft.pop_back(); delayQueueRight.pop_back(); } }