void FacilityLocation::builSolutionGraph() { if (s == NULL) s = new Graph(); activeRouters = 0; activeArcs = 0; s->nVertices = g->nVertices; s->nTerminals = g->nTerminals; s->nArcs = g->nArcs; s->reserve(g->nVertices + 1); for (int i = 0; i < g->nTerminals; ++i) { Vertex terminal = g->terminals[i]; s->addTerminal(terminal); s->addVertex(terminal); } for (auto& vit : vHash[Variable::V_Y]) { int col = vit.second; Variable var = vit.first; Vertex v = var.getVertex1(); int code = v.getCode(); if (!v.isTerminal() && fabs(xSol[col] - 1.0) < SOLVER_EPS) { ++activeRouters; v.setColor("red"); s->vertices[code] = v; } } printf(""); for (auto & vit : vHash[Variable::V_X]) { Arc arc = vit.first.getArc(); int col = vit.second; if (fabs(xSol[col] - 1.0) < SOLVER_EPS) { Vertex router = arc.getHead(); Vertex terminal = arc.getTail(); auto & element = g->arcSet[router.getCode()].find(arc); if (element != g->arcSet[router.getCode()].end()) { arc.setColor("red"); arc.setPenwidht(3.5); s->addArc(arc); } else { std::vector<Arc> path; findShortestPath(router, terminal, g, path); for (int i = 0; i < path.size(); ++i) { Arc aux = path[i]; aux.setColor("red"); aux.setPenwidht(1.5); s->addArc(aux); s->vertices[aux.getHead().getCode()].setColor("red"); } activeArcs += path.size(); printf(""); } } } printf(""); for (auto& vit : vHash[Variable::V_Z]) { Variable v = vit.first; int col = vit.second; Arc arc = v.getArc(); if (fabs(xSol[col] - 1.0) < SOLVER_EPS) { ++activeArcs; arc.setColor("red"); arc.setPenwidht(3.5); } else { arc.setColor("black"); arc.setStyle("dotted"); arc.setPenwidht(1.0); } s->addArc(arc); } printf(""); #ifdef DEBUG s->toDot(); #endif return; }
SolverMIP::SOLVERSTAT FacilityLocation::solveLRExtentedFormulations(MulltipleCutSetSeparation _cutSetSepFunc, double _tol) { int pos = 0; int nbCuts = 0; int sentinel = 0; int MAX_ITER = 100; int tailOffCounter = 0; int tailOffTol = 3; int printInterval = 5; double currentLp = 0., lastLp = 0.; bool noViolatedCutFound = true; std::set<long> hashTable; TypeVariableHashPtr vHashPtr = &(vHash); std::vector<std::set<int>*> cutSets; SolverMIP::SOLVERSTAT ret = SolverMIP::SOLVERSTAT::SOLVERSTAT_UNKNOWN; if (xSol != NULL) delete[] xSol; xSol = new double[getNCols()]; clock_t start = clock(); do { lastLp = currentLp; status = SolverMIP::solve(SolverMIP::METHOD::METHOD_DUAL); if (status == SolverMIP::SOLVERSTAT::SOLVERSTAT_MIPOPTIMAL || status == SolverMIP::SOLVERSTAT::SOLVERSTAT_LPOPTIMAL || status == SolverMIP::SOLVERSTAT::SOLVERSTAT_FEASIBLE) { ret = SolverMIP::SOLVERSTAT::SOLVERSTAT_FEASIBLE; currentLp = getObjVal(); // Getting fractional node solution getX(); if (sentinel % printInterval == 0) { printf("\n---- iter: %d\n", sentinel + 1); printf("OBJ_VAL = %lf\n", currentLp); } #ifndef DEBUG //Printing xNode solution printf("\n\n---- iter: %d\n", sentinel + 1); for (int varType = Variable::V_X; varType != Variable::V_UNKNOWN; varType += 10) { VariableHash::iterator vit = vHashPtr->at((Variable::VARTYPE)varType).begin(); for (; vit != vHashPtr->at((Variable::VARTYPE)varType).end(); ++vit) { int idx = vit->second; if (xSol[idx] > SOLVER_EPS) std::cout << (vit->first).toString() << "(" << idx << "); " << xSol[idx] << std::endl; printf(""); } printf(""); } #endif // Verifying optimality conditions if (fabs(currentLp - lastLp) < _tol) { ++tailOffCounter; if (tailOffCounter > tailOffTol) { ret = SolverMIP::SOLVERSTAT::SOLVERSTAT_LPOPTIMAL; break; } } else tailOffCounter = 0; // Calling the separation routine pos = cutSets.size(); int cutSize = _cutSetSepFunc(g, vHashPtr, xSol, cutSets, true); // If a fractional cycle is found... if (cutSets.size() - pos > 0) { noViolatedCutFound = false; for (int i = pos; i < cutSets.size(); ++i) { std::set<int>* sPtr = cutSets[i]; // Check whether the cut has already been generated unsigned long hashVal = hashFunc(*sPtr); std::set<long>::iterator it = hashTable.find(hashVal); if (it != hashTable.end()) { #ifdef DEBUG int warnCode = 990; std::string aux = convertSetToString(s); std::string msg = "The identified cut set was already separated " + convertSetToString(s); warningMsg(NULL, __func__, msg.data(), warnCode); #endif } else hashTable.insert(hashVal); // ... we must find the cut set ... std::vector<Variable> cutSet; for (VariableHash::iterator vit = vHashPtr->at(Variable::V_Z).begin(); vit != vHashPtr->at(Variable::V_Z).end(); ++vit) { Variable z = vit->first; int head = z.getArc().getHead().getCode(); int tail = z.getArc().getTail().getCode(); std::set<int>::iterator hIt = sPtr->find(head); std::set<int>::iterator tIt = sPtr->find(tail); // ... which is composed by those arcs with one endpoint in S bool isHeadInS = hIt != sPtr->end(); bool isTailInS = tIt != sPtr->end(); if (!(isHeadInS && isTailInS) && (isHeadInS || isTailInS)) { cutSet.push_back(z); } } // Identifying the y-variables involved in cut set constraints // And split them into two sets std::vector<Variable> sVec; std::vector<Variable> sCompVec; for (VariableHash::iterator vit = vHashPtr->at(Variable::V_Y).begin(); vit != vHashPtr->at(Variable::V_Y).end(); ++vit) { Variable v = vit->first; int nodeIdx = v.getVertex1().getCode(); if (sPtr->find(nodeIdx) != sPtr->end()) { sVec.push_back(v); } else { sCompVec.push_back(v); } } // Translating valid inequalities found into cplex/matrix representation int nzcnt = cutSet.size() + 2; std::vector<int> idx(nzcnt); std::vector<double> val(nzcnt); for (int i = 0; i < sVec.size(); ++i) { idx[0] = sVec[i].getColIdx(); val[0] = -1.0; for (int j = 0; j < sCompVec.size(); ++j) { idx[1] = sCompVec[j].getColIdx(); val[1] = -1.0; for (int k = 0; k < cutSet.size(); ++k) { idx[k + 2] = cutSet[k].getColIdx(); val[k + 2] = 1.0; } // Adding user generated cut int nRows = 1; double rhs = -1; char sense = 'G'; int rmatbeg = 0; int newColsAdded = 0; status = CPXaddrows(env, lp, newColsAdded, nRows, nzcnt, &rhs, &sense, &rmatbeg, &idx[0], &val[0], NULL, NULL); //status = CPXcutcallbackadd(_env, _cbdata, _wherefrom, nzcnt, -1, 'G', &idx[0], &val[0], CPX_USECUT_FORCE); if (status) { int warnCode = 999; std::string msg = "Failed to add integer cut."; warningMsg(NULL, __func__, msg.data(), warnCode); } else nbCuts++; printf(""); } } } #ifdef DEBUG // salva um arquivo .lp com o LP atual writeProbLP(".\\lpRelax"); #endif } else { // No violated cut was found noViolatedCutFound = true; } // If no violated cut was found if (noViolatedCutFound) { ret = SolverMIP::SOLVERSTAT::SOLVERSTAT_LPOPTIMAL; break; } } else { int warnCode = 201; std::string msg = "Model is infeasible"; warningMsg(typeid(*this).name(), __func__, msg.data(), warnCode); // salva um arquivo .lp com o LP atual writeProbLP(".\\infeasible"); ret = SolverMIP::SOLVERSTAT::SOLVERSTAT_INFEASIBLE; break; } } while (++sentinel < MAX_ITER); // Deallocating memory for (int i = 0; i < cutSets.size(); ++i) { if (cutSets[i] != NULL) { delete cutSets[i]; cutSets[i] = NULL; } } clock_t end = clock(); printf("\n-----"); printf("\n----- iter: %d", sentinel + 1); printf("\n----- OBJ_VAL = %lf", currentLp); printf("\n----- Exectution time: %.4f", (end - start) / (double)CLOCKS_PER_SEC); return ret; }
void Flow::builSolutionGraph() { if (s == NULL) s = new Graph(); int activeRouters = 0; int activeArcs = 0; s->nVertices = g->nVertices; s->nTerminals = g->nTerminals; s->nArcs = g->nArcs; s->reserve(g->nVertices + 1); for (int i = 0; i < g->nTerminals; ++i) { Vertex terminal = g->terminals[i]; s->addTerminal(terminal); s->addVertex(terminal); } for (auto & vit : vHash[Variable::V_X]) { int col = vit.second; Variable var = vit.first; Arc arc = var.getArc(); Vertex h = var.getArc().getHead(); Vertex t = var.getArc().getTail(); if (!h.isTerminal() && xSol[col] > SOLVER_EPS) { ++activeRouters; h.setColor("red"); s->vertices[h.getCode()] = h; } if (!t.isTerminal() && xSol[col] > SOLVER_EPS) { ++activeRouters; t.setColor("red"); s->vertices[t.getCode()] = t; } if (xSol[col] > SOLVER_EPS) { ++activeArcs; arc.setColor("red"); arc.setPenwidht(3.5); } else { arc.setColor("black"); arc.setStyle("dotted"); arc.setPenwidht(1.0); } s->addArc(arc); } #ifdef DEBUG s->toDot(); #endif return; }