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;
}
Exemple #9
0
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;
}
Exemple #10
0
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;
}
Exemple #16
0
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();
	}
}
Exemple #17
0
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;
}
Exemple #18
0
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;
}