void FastPlanarSubgraph::computeDelEdges(const Graph &G, const EdgeArray<int> *pCost, const EdgeArray<edge> *backTableEdges, List<edge> &delEdges) { if (m_nRuns <= 0) { // Compute st-numbering NodeArray<int> numbering(G,0); int n = stNumber(G,numbering); OGDF_ASSERT_IF(dlConsistencyChecks,testSTnumber(G,numbering,n)) planarize(G,numbering,delEdges); } else { int bestSolution = INT_MAX; for(int i = 1; i <= m_nRuns && bestSolution > 1; ++i) { List<edge> currentDelEdges; // Compute (randomized) st-numbering NodeArray<int> numbering(G,0); int n = stNumber(G,numbering,0,0,true); OGDF_ASSERT_IF(dlConsistencyChecks,testSTnumber(G,numbering,n)) planarize(G,numbering,currentDelEdges); if(pCost == 0) { int currentSolution = currentDelEdges.size(); if(currentSolution < bestSolution) { bestSolution = currentSolution; delEdges.clear(); delEdges.conc(currentDelEdges); } } else { int currentSolution = 0; ListConstIterator<edge> it; for(it = currentDelEdges.begin(); it.valid(); ++it) if(backTableEdges != 0) currentSolution += (*pCost)[(*backTableEdges)[*it]]; else currentSolution += (*pCost)[*it]; if(currentSolution < bestSolution) { bestSolution = currentSolution; delEdges.clear(); delEdges.conc(currentDelEdges); } } } } }
void CombinatorialEmbedding::moveBridge(adjEntry adjBridge, adjEntry adjBefore) { OGDF_ASSERT(m_rightFace[adjBridge] == m_rightFace[adjBridge->twin()]); OGDF_ASSERT(m_rightFace[adjBridge] != m_rightFace[adjBefore]); face fOld = m_rightFace[adjBridge]; face fNew = m_rightFace[adjBefore]; adjEntry adjCand = adjBridge->faceCycleSucc(); int sz = 0; adjEntry adj; for(adj = adjBridge->twin(); adj != adjCand; adj = adj->faceCycleSucc()) { if (fOld->entries.m_adjFirst == adj) fOld->entries.m_adjFirst = adjCand; m_rightFace[adj] = fNew; ++sz; } fOld->m_size -= sz; fNew->m_size += sz; edge e = adjBridge->theEdge(); if(e->source() == adjBridge->twinNode()) m_pGraph->moveSource(e, adjBefore, after); else m_pGraph->moveTarget(e, adjBefore, after); OGDF_ASSERT_IF(dlConsistencyChecks, consistencyCheck()); }
void CombinatorialEmbedding::reverseEdge(edge e) { // reverse edge in graph m_pGraph->reverseEdge(e); OGDF_ASSERT_IF(dlConsistencyChecks, consistencyCheck()); }
edge CombinatorialEmbedding::splitFace(adjEntry adjSrc, adjEntry adjTgt) { OGDF_ASSERT(m_rightFace[adjSrc] == m_rightFace[adjTgt]) OGDF_ASSERT(adjSrc != adjTgt) edge e = m_pGraph->newEdge(adjSrc,adjTgt); face f1 = m_rightFace[adjTgt]; face f2 = createFaceElement(adjSrc); adjEntry adj = adjSrc; do { m_rightFace[adj] = f2; f2->m_size++; adj = adj->faceCycleSucc(); } while (adj != adjSrc); f1->entries.m_adjFirst = adjTgt; f1->m_size += (2 - f2->m_size); m_rightFace[e->adjSource()] = f1; OGDF_ASSERT_IF(dlConsistencyChecks, consistencyCheck()); return e; }
node CombinatorialEmbedding::contract(edge e) { // Since we remove face e, we also remove adjSrc and adjTgt. // We make sure that node of them is stored as first adjacency // entry of a face. adjEntry adjSrc = e->adjSource(); adjEntry adjTgt = e->adjTarget(); face fSrc = m_rightFace[adjSrc]; face fTgt = m_rightFace[adjTgt]; if (fSrc->entries.m_adjFirst == adjSrc) { adjEntry adj = adjSrc->faceCycleSucc(); fSrc->entries.m_adjFirst = (adj != adjTgt) ? adj : adj->faceCycleSucc(); } if (fTgt->entries.m_adjFirst == adjTgt) { adjEntry adj = adjTgt->faceCycleSucc(); fTgt->entries.m_adjFirst = (adj != adjSrc) ? adj : adj->faceCycleSucc(); } node v = m_pGraph->contract(e); --fSrc->m_size; --fTgt->m_size; OGDF_ASSERT_IF(dlConsistencyChecks, consistencyCheck()); return v; }
void ConstCombinatorialEmbedding::computeFaces() { m_externalFace = nullptr; // no longer valid! m_faceIdCount = 0; faces.clear(); m_rightFace.fill(nullptr); for(node v : m_cpGraph->nodes) { for(adjEntry adj : v->adjEdges) { if (m_rightFace[adj]) continue; #ifdef OGDF_DEBUG face f = OGDF_NEW FaceElement(this,adj,m_faceIdCount++); #else face f = OGDF_NEW FaceElement(adj,m_faceIdCount++); #endif faces.pushBack(f); adjEntry adj2 = adj; do { m_rightFace[adj2] = f; f->m_size++; adj2 = adj2->faceCycleSucc(); } while (adj2 != adj); } } m_faceArrayTableSize = Graph::nextPower2(MIN_FACE_TABLE_SIZE,m_faceIdCount); reinitArrays(); OGDF_ASSERT_IF(dlConsistencyChecks, consistencyCheck()); }
face CombinatorialEmbedding::joinFaces(edge e) { face f = joinFacesPure(e); m_pGraph->delEdge(e); OGDF_ASSERT_IF(dlConsistencyChecks, consistencyCheck()); return f; }
ClusterGraph &ClusterGraph::operator=(const ClusterGraph &C) { clear(); shallowCopy(C); m_clusterArrayTableSize = C.m_clusterArrayTableSize; reinitArrays(); OGDF_ASSERT_IF(dlConsistencyChecks, consistencyCheck()); return *this; }
Graph &Graph::operator=(const Graph &G) { clear(); copy(G); m_nodeArrayTableSize = nextPower2(MIN_NODE_TABLE_SIZE,m_nodeIdCount); m_edgeArrayTableSize = nextPower2(MIN_EDGE_TABLE_SIZE,m_edgeIdCount); reinitArrays(); OGDF_ASSERT_IF(dlConsistencyChecks, consistencyCheck()); return *this; }
TricComp::TricComp (const Graph& G) : m_ESTACK(G.numberOfEdges()) { m_pGC = new GraphCopySimple(G); GraphCopySimple &GC = *m_pGC; const int n = GC.numberOfNodes(); const int m = GC.numberOfEdges(); #ifdef TRIC_COMP_OUTPUT cout << "Dividing G into triconnected components.\n" << endl; cout << "n = " << n << ", m = " << m << endl << endl; #endif m_component = Array<CompStruct>(3*m-6); m_numComp = 0; // special cases OGDF_ASSERT(n >= 2); OGDF_ASSERT_IF(dlExtendedChecking, isBiconnected(G)); if (n <= 2) { OGDF_ASSERT(m >= 3); CompStruct &C = newComp(); edge e; forall_edges(e,GC) C << e; C.m_type = bond; return; } m_TYPE.init(GC,unseen); splitMultiEdges(); // initialize arrays m_NUMBER.init(GC,0); m_LOWPT1.init(GC); m_LOWPT2.init(GC); m_FATHER.init(GC,0); m_ND .init(GC); m_DEGREE.init(GC); m_TREE_ARC.init(GC,0); m_NODEAT = Array<node>(1,n); m_numCount = 0; m_start = GC.firstNode(); DFS1(GC,m_start,0); edge e; forall_edges(e,GC) { bool up = (m_NUMBER[e->target()] - m_NUMBER[e->source()] > 0); if ((up && m_TYPE[e] == frond) || (!up && m_TYPE[e] == tree)) GC.reverseEdge(e); }
void CombinatorialEmbedding::clear() { m_pGraph->clear(); faces.clear(); m_faceIdCount = 0; m_faceArrayTableSize = MIN_FACE_TABLE_SIZE; m_externalFace = nullptr; reinitArrays(); OGDF_ASSERT_IF(dlConsistencyChecks, consistencyCheck()); }
void CombinatorialEmbedding::removeDeg1(node v) { OGDF_ASSERT(v->degree() == 1); adjEntry adj = v->firstAdj(); face f = m_rightFace[adj]; if (f->entries.m_adjFirst == adj || f->entries.m_adjFirst == adj->twin()) f->entries.m_adjFirst = adj->faceCycleSucc(); f->m_size -= 2; m_pGraph->delNode(v); OGDF_ASSERT_IF(dlConsistencyChecks, consistencyCheck()); }
edge CombinatorialEmbedding::split(edge e) { face f1 = m_rightFace[e->adjSource()]; face f2 = m_rightFace[e->adjTarget()]; edge e2 = m_pGraph->split(e); m_rightFace[e->adjSource()] = m_rightFace[e2->adjSource()] = f1; f1->m_size++; m_rightFace[e->adjTarget()] = m_rightFace[e2->adjTarget()] = f2; f2->m_size++; OGDF_ASSERT_IF(dlConsistencyChecks, consistencyCheck()); return e2; }
//-- //----------------- //incremental stuff //special version of the above function doing a pushback of the new edge //on the adjacency list of v making it possible to insert new degree 0 //nodes into a face, end node v edge CombinatorialEmbedding::splitFace(adjEntry adjSrc, node v) { adjEntry adjTgt = v->lastAdj(); edge e = nullptr; bool degZ = v->degree() == 0; if (degZ) { e = m_pGraph->newEdge(adjSrc, v); } else { OGDF_ASSERT(m_rightFace[adjSrc] == m_rightFace[adjTgt]) OGDF_ASSERT(adjSrc != adjTgt) e = m_pGraph->newEdge(adjSrc, adjTgt); //could use ne(v,ad) here, too } face f1 = m_rightFace[adjSrc]; //if v already had an adjacent edge, we split the face in two faces int subSize = 0; if (!degZ) { face f2 = createFaceElement(adjTgt); adjEntry adj = adjTgt; do { m_rightFace[adj] = f2; f2->m_size++; adj = adj->faceCycleSucc(); } while (adj != adjTgt); subSize = f2->m_size; }//if not zero degree else { m_rightFace[e->adjSource()] = f1; } f1->entries.m_adjFirst = adjSrc; f1->m_size += (2 - subSize); m_rightFace[e->adjTarget()] = f1; OGDF_ASSERT_IF(dlConsistencyChecks, consistencyCheck()); return e; }//splitface
node CombinatorialEmbedding::splitNode(adjEntry adjStartLeft, adjEntry adjStartRight) { face fL = leftFace(adjStartLeft); face fR = leftFace(adjStartRight); node u = m_pGraph->splitNode(adjStartLeft,adjStartRight); adjEntry adj = adjStartLeft->cyclicPred(); m_rightFace[adj] = fL; ++fL->m_size; m_rightFace[adj->twin()] = fR; ++fR->m_size; OGDF_ASSERT_IF(dlConsistencyChecks, consistencyCheck()); return u; }
void PlanarSPQRTree::adoptEmbedding() { OGDF_ASSERT_IF(dlExtendedChecking, originalGraph().representsCombEmbedding()); // ordered list of adjacency entries (for one original node) in all // skeletons (where this node occurs) NodeArray<SListPure<adjEntry> > adjEdges(tree()); // copy in skeleton of current original node NodeArray<node> currentCopy(tree(),nullptr); NodeArray<adjEntry> lastAdj(tree(),nullptr); SListPure<node> current; // currently processed nodes for (node vOrig : originalGraph().nodes) { for(adjEntry adjOrig : vOrig->adjEdges) { edge eOrig = adjOrig->theEdge(); const Skeleton &S = skeletonOfReal(eOrig); edge eCopy = copyOfReal(eOrig); adjEntry adjCopy = (S.original(eCopy->source()) == vOrig) ? eCopy->adjSource() : eCopy->adjTarget(); setPosInEmbedding(adjEdges,currentCopy,lastAdj,current,S,adjCopy); } for(node vT : current) { skeleton(vT).getGraph().sort(currentCopy[vT],adjEdges[vT]); adjEdges[vT].clear(); currentCopy[vT] = nullptr; } current.clear(); } }
LPSolver::Status LPSolver::optimize( OptimizationGoal goal, // goal of optimization (minimize or maximize) Array<double> &obj, // objective function vector Array<int> &matrixBegin, // matrixBegin[i] = begin of column i Array<int> &matrixCount, // matrixCount[i] = number of nonzeroes in column i Array<int> &matrixIndex, // matrixIndex[n] = index of matrixValue[n] in its column Array<double> &matrixValue, // matrixValue[n] = non-zero value in matrix Array<double> &rightHandSide, // right-hand side of LP constraints Array<char> &equationSense, // 'E' == 'G' >= 'L' <= Array<double> &lowerBound, // lower bound of x[i] Array<double> &upperBound, // upper bound of x[i] double &optimum, // optimum value of objective function (if result is lpOptimal) Array<double> &x // x-vector of optimal solution (if result is lpOptimal) ) { if(osi->getNumCols()>0) { // get a fresh one if necessary delete osi; osi = CoinManager::createCorrectOsiSolverInterface(); } const int numRows = rightHandSide.size(); const int numCols = obj.size(); #ifdef OGDF_DEBUG const int numNonzeroes = matrixIndex.size(); #endif // assert correctness of array boundaries OGDF_ASSERT(obj .low() == 0 && obj .size() == numCols); OGDF_ASSERT(matrixBegin .low() == 0 && matrixBegin .size() == numCols); OGDF_ASSERT(matrixCount .low() == 0 && matrixCount .size() == numCols); OGDF_ASSERT(matrixIndex .low() == 0 && matrixIndex .size() == numNonzeroes); OGDF_ASSERT(matrixValue .low() == 0 && matrixValue .size() == numNonzeroes); OGDF_ASSERT(rightHandSide.low() == 0 && rightHandSide.size() == numRows); OGDF_ASSERT(equationSense.low() == 0 && equationSense.size() == numRows); OGDF_ASSERT(lowerBound .low() == 0 && lowerBound .size() == numCols); OGDF_ASSERT(upperBound .low() == 0 && upperBound .size() == numCols); OGDF_ASSERT(x .low() == 0 && x .size() == numCols); osi->setObjSense(goal==lpMinimize ? 1 : -1); int i; CoinPackedVector zero; for(i = 0; i < numRows; ++i) { osi->addRow(zero,equationSense[i],rightHandSide[i],0); } for(int colNo = 0; colNo < numCols; ++colNo) { CoinPackedVector cpv; for(i = matrixBegin[colNo]; i<matrixBegin[colNo]+matrixCount[colNo]; ++i) { cpv.insert(matrixIndex[i],matrixValue[i]); } osi->addCol(cpv,lowerBound[colNo],upperBound[colNo],obj[colNo]); } osi->initialSolve(); Status status; if(osi->isProvenOptimal()) { optimum = osi->getObjValue(); const double* sol = osi->getColSolution(); for(i = numCols; i-->0;) x[i]=sol[i]; status = lpOptimal; OGDF_ASSERT_IF(dlExtendedChecking, checkFeasibility(matrixBegin,matrixCount,matrixIndex,matrixValue, rightHandSide,equationSense,lowerBound,upperBound,x)); } else if(osi->isProvenPrimalInfeasible()) status = lpInfeasible; else if(osi->isProvenDualInfeasible()) status = lpUnbounded; else OGDF_THROW_PARAM(AlgorithmFailureException,afcNoSolutionFound); return status; }
void TileToRowsCCPacker::callGeneric(Array<POINT> &box, Array<POINT> &offset, double pageRatio) { OGDF_ASSERT(box.size() == offset.size()); // negative pageRatio makes no sense, // pageRatio = 0 will cause division by zero OGDF_ASSERT(pageRatio > 0); const int n = box.size(); int nRows = 0; Array<RowInfo<POINT> > row(n); // sort the box indices according to decreasing height of the // corresponding boxes Array<int> sortedIndices(n); int i; for(i = 0; i < n; ++i) sortedIndices[i] = i; DecrIndexComparer<POINT> comp(box); sortedIndices.quicksort(comp); // i iterates over all box indices according to decreasing height of // the boxes for(int iSI = 0; iSI < n; ++iSI) { int i = sortedIndices[iSI]; // Find the row which increases the covered area as few as possible. // The area measured is the area of the smallest rectangle that covers // all boxes and whose width / height ratio is pageRatio int bestRow = findBestRow(row,nRows,pageRatio,box[i]); // bestRow = -1 indictes that a new row is added if (bestRow < 0) { struct RowInfo<POINT> &r = row[nRows++]; r.m_boxes.pushBack(i); r.m_maxHeight = box[i].m_y; r.m_width = box[i].m_x; } else { struct RowInfo<POINT> &r = row[bestRow]; r.m_boxes.pushBack(i); r.m_maxHeight = max(r.m_maxHeight,box[i].m_y); r.m_width += box[i].m_x; } } // At this moment, we know which box is contained in which row. // The following loop sets the required offset of each box typename POINT::numberType y = 0; // sum of the heights of boxes 0,...,i-1 for(i = 0; i < nRows; ++i) { const RowInfo<POINT> &r = row[i]; typename POINT::numberType x = 0; // sum of the widths of the boxes to the left of box *it for(int j : r.m_boxes) { offset[j] = POINT(x,y); x += box[j].m_x; } y += r.m_maxHeight; } OGDF_ASSERT_IF(dlConsistencyChecks, checkOffsets(box,offset)); }
// // Prepare planarity test for one cluster // bool CconnectClusterPlanar::preparation( Graph &G, cluster &cl, node superSink) { int bcIdSuperSink = -1; // ID of biconnected component that contains superSink // Initialization with -1 necessary for assertion bool cPlanar = true; NodeArray<node> tableNodes(G, nullptr); EdgeArray<edge> tableEdges(G, nullptr); NodeArray<bool> mark(G, 0); EdgeArray<int> componentID(G); // Determine Biconnected Components int bcCount = biconnectedComponents(G, componentID); // Determine edges per biconnected component Array<SList<edge> > blockEdges(0, bcCount - 1); for (edge e : G.edges) { blockEdges[componentID[e]].pushFront(e); } // Determine nodes per biconnected component. Array<SList<node> > blockNodes(0, bcCount - 1); for (int i = 0; i < bcCount; i++) { for (edge e : blockEdges[i]) { if (!mark[e->source()]) { blockNodes[i].pushBack(e->source()); mark[e->source()] = true; } if (!mark[e->target()]) { blockNodes[i].pushBack(e->target()); mark[e->target()] = true; } } if (superSink && mark[superSink]) { OGDF_ASSERT(bcIdSuperSink == -1); bcIdSuperSink = i; } for (node v : blockNodes[i]) { if (mark[v]) mark[v] = false; else { OGDF_ASSERT(mark[v]); // v has been placed two times on the list. } } } // Perform planarity test for every biconnected component if (bcCount == 1) { // Compute st-numbering NodeArray<int> numbering(G,0); #ifdef OGDF_DEBUG int n = #endif (superSink) ? stNumber(G,numbering,nullptr,superSink) : stNumber(G,numbering); OGDF_ASSERT_IF(dlConsistencyChecks,testSTnumber(G,numbering,n)) EdgeArray<edge> backTableEdges(G,nullptr); for(edge e : G.edges) backTableEdges[e] = e; cPlanar = doTest(G,numbering,cl,superSink,backTableEdges); } else { for (int i = 0; i < bcCount; i++) { #ifdef OGDF_DEBUG if(int(ogdf::debugLevel)>=int(dlHeavyChecks)){ cout<<endl<<endl<<"-----------------------------------"; cout<<endl<<endl<<"Component "<<i<<endl;} #endif Graph C; for (node v : blockNodes[i]) { node w = C.newNode(); tableNodes[v] = w; #ifdef OGDF_DEBUG if (int(ogdf::debugLevel) >= int(dlHeavyChecks)){ cout << "Original: " << v << " New: " << w << endl; } #endif } NodeArray<node> backTableNodes(C,nullptr); for (edge e : blockEdges[i]) { edge f = C.newEdge(tableNodes[e->source()],tableNodes[e->target()]); tableEdges[e] = f; } EdgeArray<edge> backTableEdges(C,nullptr); for (edge e : blockEdges[i]) backTableEdges[tableEdges[e]] = e; // Compute st-numbering NodeArray<int> numbering(C,0); if (bcIdSuperSink == i) { #ifdef OGDF_DEBUG int n = #endif stNumber(C,numbering,nullptr,tableNodes[superSink]); OGDF_ASSERT_IF(dlConsistencyChecks,testSTnumber(C,numbering,n)) cPlanar = doTest(C,numbering,cl,tableNodes[superSink],backTableEdges); } else { #ifdef OGDF_DEBUG int n = #endif stNumber(C,numbering); OGDF_ASSERT_IF(dlConsistencyChecks,testSTnumber(C,numbering,n)) cPlanar = doTest(C,numbering,cl,nullptr,backTableEdges); } if (!cPlanar) break; } } return cPlanar; }