void decodePlanarCode(unsigned short* code) { /* complexity of method to determine inverse isn't that good, but will have to satisfy for now */ int i, j, codePosition; int edgeCounter = 0; EDGE *inverse; nv = code[0]; codePosition = 1; for (i = 0; i < nv; i++) { degree[i] = 0; neighbourhood[i] = SINGLETON(code[codePosition] - 1); firstedge[i] = edges + edgeCounter; edges[edgeCounter].start = i; edges[edgeCounter].end = code[codePosition] - 1; edges[edgeCounter].vertices = UNION(SINGLETON(i), SINGLETON(code[codePosition] - 1)); edges[edgeCounter].next = edges + edgeCounter + 1; if (code[codePosition] - 1 < i) { inverse = edgeMatrix[code[codePosition] - 1][i]; edges[edgeCounter].inverse = inverse; inverse->inverse = edges + edgeCounter; } else { edgeMatrix[i][code[codePosition] - 1] = edges + edgeCounter; edges[edgeCounter].inverse = NULL; } edgeCounter++; codePosition++; for (j = 1; code[codePosition]; j++, codePosition++) { if (j == MAXVAL) { fprintf(stderr, "MAXVAL too small: %d\n", MAXVAL); exit(0); } ADD(neighbourhood[i], code[codePosition] - 1); edges[edgeCounter].start = i; edges[edgeCounter].end = code[codePosition] - 1; edges[edgeCounter].vertices = UNION(SINGLETON(i), SINGLETON(code[codePosition] - 1)); edges[edgeCounter].prev = edges + edgeCounter - 1; edges[edgeCounter].next = edges + edgeCounter + 1; if (code[codePosition] - 1 < i) { inverse = edgeMatrix[code[codePosition] - 1][i]; edges[edgeCounter].inverse = inverse; inverse->inverse = edges + edgeCounter; } else { edgeMatrix[i][code[codePosition] - 1] = edges + edgeCounter; edges[edgeCounter].inverse = NULL; } edgeCounter++; } firstedge[i]->prev = edges + edgeCounter - 1; edges[edgeCounter - 1].next = firstedge[i]; degree[i] = j; codePosition++; /* read the closing 0 */ } ne = edgeCounter; makeDual(); // nv - ne/2 + nf = 2 }
PLANE_GRAPH *decodePlanarCode(unsigned short* code, PG_INPUT_OPTIONS *options) { int i, j, codePosition, nv, maxn; int edgeCounter = 0; PG_EDGE *inverse; nv = code[0]; codePosition = 1; if(options->maxn <= 0){ maxn = nv*options->maxnFactor; } else { maxn = options->maxn; } PLANE_GRAPH *pg = newPlaneGraph(maxn, options->maxe); pg->nv = nv; for (i = 0; i < nv; i++) { pg->degree[i] = 0; pg->firstedge[i] = pg->edges + edgeCounter; pg->edges[edgeCounter].start = i; pg->edges[edgeCounter].end = code[codePosition] - 1; pg->edges[edgeCounter].next = pg->edges + edgeCounter + 1; if (code[codePosition] - 1 < i) { inverse = findEdge(pg, code[codePosition] - 1, i); pg->edges[edgeCounter].inverse = inverse; inverse->inverse = pg->edges + edgeCounter; } else { pg->edges[edgeCounter].inverse = NULL; } edgeCounter++; codePosition++; for (j = 1; code[codePosition]; j++, codePosition++) { pg->edges[edgeCounter].start = i; pg->edges[edgeCounter].end = code[codePosition] - 1; pg->edges[edgeCounter].prev = pg->edges + edgeCounter - 1; pg->edges[edgeCounter].next = pg->edges + edgeCounter + 1; if (code[codePosition] - 1 < i) { inverse = findEdge(pg, code[codePosition] - 1, i); pg->edges[edgeCounter].inverse = inverse; inverse->inverse = pg->edges + edgeCounter; } else { pg->edges[edgeCounter].inverse = NULL; } edgeCounter++; } pg->firstedge[i]->prev = pg->edges + edgeCounter - 1; pg->edges[edgeCounter - 1].next = pg->firstedge[i]; pg->degree[i] = j; codePosition++; /* read the closing 0 */ } pg->ne = edgeCounter; if(options->computeDual){ makeDual(pg); } return pg; }
/** Extract sub block number <code>n</code> from <code>problem</code>. * The constructor creates a representation of block number <code>n</code> * as described in <code>problem</code>. * The constructor will also connect the newly created block to a remote * object solver instance. * @param problem The problem from which the block is to be extracted. * @param n Index of the block to be extracted. * @param argc Argument for IloCplex constructor. * @param argv Argument for IloCplex constructor. * @param machines List of machines to which to connect. If the code is * compiled for the TCP/IP transport then the block will * be connected to <code>machines[n]</code>. */ BendersOpt::Block::Block(Problem const *problem, IloInt n, int argc, char const *const *argv, std::vector<char const *> const &machines) : env(), number(n), vars(0), rows(0), cplex(0), cb(0) { IloNumVarArray problemVars = problem->getVariables(); IloRangeArray problemRanges = problem->getRows(); // Create a map that maps variables in the original model to their // respective index in problemVars. std::map<IloNumVar,IloInt,ExtractableLess<IloNumVar> > origIdxMap; for (IloInt j = 0; j < problemVars.getSize(); ++j) origIdxMap.insert(std::map<IloNumVar,IloInt,ExtractableLess<IloNumVar> >::value_type(problemVars[j], j)); // Copy non-fixed variables from original problem into primal problem. IloExpr primalObj(env); IloNumVarArray primalVars(env); IloRangeArray primalRows(env); IdxMap idxMap; // Index of original variable in block's primal model RowSet rowSet; for (IloInt j = 0; j < problemVars.getSize(); ++j) { IloNumVar x = problemVars[j]; if ( problem->getBlock(x) == number ) { // Create column in block LP with exactly the same data. if ( x.getType() != IloNumVar::Float ) { std::stringstream s; s << "Cannot create non-continuous block variable " << x; std::cerr << s.str() << std::endl; throw s.str(); } IloNumVar v(env, x.getLB(), x.getUB(), x.getType(), x.getName()); // Normalize objective function to 'minimize' double coef = problem->getObjCoef(x); if ( problem->getObjSense() != IloObjective::Minimize ) coef *= -1.0; primalObj += coef * v; // Record the index that the copied variable has in the // block model. idxMap.insert(IdxMap::value_type(x, primalVars.getSize())); primalVars.add(v); // Mark the rows that are intersected by this column // so that we can collect them later. RowSet const &intersected = problem->getIntersectedRows(x); for (RowSet::const_iterator it = intersected.begin(); it != intersected.end(); ++it) rowSet.insert(*it); } else idxMap.insert(IdxMap::value_type(x, -1)); } // Now copy all rows that intersect block variables. for (IloInt i = 0; i < problemRanges.getSize(); ++i) { IloRange r = problemRanges[i]; if ( rowSet.find(r) == rowSet.end() ) continue; // Create a copy of the row, normalizing it to '<=' double factor = 1.0; if ( r.getLB() > -IloInfinity ) factor = -1.0; IloRange primalR(env, factor < 0 ? -r.getUB() : r.getLB(), factor < 0 ? -r.getLB() : r.getUB(), r.getName()); IloExpr lhs(env); for (IloExpr::LinearIterator it = r.getLinearIterator(); it.ok(); ++it) { IloNumVar v = it.getVar(); double const val = factor * it.getCoef(); if ( problem->getBlock(v) != number ) { // This column is not explicitly in this block. This means // that it is a column that will be fixed by the master. // We collect all such columns so that we can adjust the // dual objective function according to concrete fixings. // Store information about variables in this block that // will be fixed by master solves. fixed.push_back(FixData(primalRows.getSize(), origIdxMap[v], -val)); } else { // The column is an ordinary in this block. Just copy it. lhs += primalVars[idxMap[v]] * val; } } primalR.setExpr(lhs); primalRows.add(primalR); lhs.end(); } // Create the dual of the primal model we just created. // Note that makeDual _always_ returns a 'maximize' objective. IloObjective objective(env, primalObj, IloObjective::Minimize); makeDual(objective, primalVars, primalRows, &obj, &vars, &rows); objective.end(); primalRows.endElements(); primalRows.end(); primalVars.endElements(); primalVars.end(); primalObj.end(); // Create a model. IloModel model(env); model.add(obj); model.add(vars); model.add(rows); for (IloExpr::LinearIterator it = obj.getLinearIterator(); it.ok(); ++it) objMap.insert(ObjMap::value_type(it.getVar(), it.getCoef())); // Finally create the IloCplex instance that will solve // the problems associated with this block. char const **transargv = new char const *[argc + 3]; for (int i = 0; i < argc; ++i) transargv[i] = argv[i]; #if defined(USE_MPI) char extra[128]; sprintf (extra, "-remoterank=%d", static_cast<int>(number + 1)); transargv[argc++] = extra; (void)machines; #elif defined(USE_PROCESS) char extra[128]; sprintf (extra, "-logfile=block%04d.log", static_cast<int>(number)); transargv[argc++] = extra; (void)machines; #elif defined(USE_TCPIP) transargv[argc++] = machines[number]; #endif cplex = IloCplex(model, TRANSPORT, argc, transargv); delete[] transargv; // Suppress output from this block's solver. cplex.setOut(env.getNullStream()); cplex.setWarning(env.getNullStream()); }
PLANE_GRAPH *getDualGraph(PLANE_GRAPH *pg){ int i; if(!pg->dualComputed){ makeDual(pg); } PLANE_GRAPH *dual = newPlaneGraph(pg->nf, pg->ne); if(dual==NULL){ fprintf(stderr, "Insufficient memory to create dual.\n"); return NULL; } for(i = 0; i < pg->ne; i++){ pg->edges[i].index = i; } dual->nv = pg->nf; dual->ne = pg->ne; dual->nf = pg->nv; for(i = 0; i < pg->ne; i++){ dual->edges[i].start = pg->edges[i].rightface; dual->edges[i].end = pg->edges[i].inverse->rightface; dual->edges[i].rightface = pg->edges[i].end; dual->edges[i].inverse = dual->edges + pg->edges[i].inverse->index; dual->edges[i].next = dual->edges + pg->edges[i].inverse->prev->index; dual->edges[i].prev = dual->edges + pg->edges[i].next->inverse->index; } for(i = 0; i < pg->nf; i++){ dual->degree[i] = pg->faceSize[i]; dual->firstedge[i] = dual->edges + pg->facestart[i]->index; } dual->maxf = pg->nv; dual->facestart = (PG_EDGE **)malloc(sizeof(PG_EDGE *)*(dual->maxf)); if(dual->facestart == NULL){ dual->maxf = 0; return dual; } dual->faceSize = (int *)malloc(sizeof(int)*(dual->maxf)); if(dual->faceSize == NULL){ dual->maxf = 0; free(dual->facestart); return dual; } for(i = 0; i < pg->nv; i++){ dual->faceSize[i] = pg->degree[i]; dual->facestart[i] = dual->edges + pg->firstedge[i]->inverse->index; } dual->dualComputed = TRUE; return dual; }