//NOTE: very stupid and not very efficient; better use a graph for this problem vector<VariableIndex> Recurrence::dependencyOrder(UpdateMap &update) { vector<VariableIndex> ordering; set<VariableIndex> orderedVars; while (ordering.size() < update.size()) { bool changed = false; for (auto up : update) { if (orderedVars.count(up.first) > 0) continue; //check if all variables on update rhs are already processed for (const string &varname : up.second.getVariableNames()) { VariableIndex vi = itrs.getVarindex(varname); if (vi != up.first && update.count(vi) > 0 && orderedVars.count(vi) == 0) goto skipUpdate; } orderedVars.insert(up.first); ordering.push_back(up.first); changed = true; skipUpdate: ; } if (changed) continue; //if not all dependencies could be resolved, try to add constraints to the guard to make things easier GiNaC::exmap subs; ExprSymbol target; bool has_target = false; for (auto up : update) { if (orderedVars.count(up.first) > 0) continue; if (!has_target) { target = itrs.getGinacSymbol(up.first); has_target = true; } else { addGuard.push_back(target == itrs.getGinacSymbol(up.first)); subs[itrs.getGinacSymbol(up.first)] = target; } } //assume all remaining variables are equal for (auto &up : update) { up.second = up.second.subs(subs); } } return ordering; }
void Union::updateModel(const UpdateMap &mapIn) { setFailure(); //assume failure until success. try { if ( mapIn.count(InputTypes::target) != 1 || mapIn.count(InputTypes::tool) < 1 ) { //we should have a status message in the base class. std::ostringstream stream; stream << "wrong number of arguments. " << "target count is: " << mapIn.count(InputTypes::target) << " " << "tool count is: " << mapIn.count(InputTypes::tool); throw std::runtime_error(stream.str()); } //target const SeerShape &targetSeerShape = mapIn.equal_range(InputTypes::target).first->second->getSeerShape(); assert(!targetSeerShape.isNull()); //tools gu::ShapeVector toolOCCTShapes; for (auto pairIt = mapIn.equal_range(InputTypes::tool); pairIt.first != pairIt.second; ++pairIt.first) { const SeerShape &toolSeerShape = pairIt.first->second->getSeerShape(); assert(!toolSeerShape.isNull()); toolOCCTShapes.push_back(toolSeerShape.getRootOCCTShape()); } //set default on failure to parent target. seerShape->partialAssign(targetSeerShape); BooleanOperation fuser(targetSeerShape.getRootOCCTShape(), toolOCCTShapes, BOPAlgo_FUSE); fuser.Build(); if (!fuser.IsDone()) throw std::runtime_error("OCC fuse failed"); ShapeCheck check(fuser.Shape()); if (!check.isValid()) throw std::runtime_error("shapeCheck failed"); seerShape->setOCCTShape(fuser.Shape()); seerShape->shapeMatch(targetSeerShape); for (auto pairIt = mapIn.equal_range(InputTypes::tool); pairIt.first != pairIt.second; ++pairIt.first) seerShape->shapeMatch(pairIt.first->second->getSeerShape()); seerShape->uniqueTypeMatch(targetSeerShape); BooleanIdMapper idMapper(mapIn, fuser.getBuilder(), iMapWrapper, seerShape.get()); idMapper.go(); seerShape->outerWireMatch(targetSeerShape); for (auto pairIt = mapIn.equal_range(InputTypes::tool); pairIt.first != pairIt.second; ++pairIt.first) seerShape->outerWireMatch(pairIt.first->second->getSeerShape()); seerShape->derivedMatch(); seerShape->dumpNils(getTypeString()); //only if there are shapes with nil ids. seerShape->dumpDuplicates(getTypeString()); seerShape->ensureNoNils(); seerShape->ensureNoDuplicates(); setSuccess(); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); std::cout << std::endl << "Error in union update. " << e->GetMessageString() << std::endl; } catch (std::exception &e) { std::cout << std::endl << "Error in union update. " << e.what() << std::endl; } setModelClean(); }