Пример #1
0
// sets the positions of the nodes in a largest face of G in the form
// of a regular k-gon. The corresponding nodes and their positions are
// stored in nodes and pos, respectively.
void TutteLayout::setFixedNodes(
	const Graph &G,
	List<node>& nodes,
	List<DPoint>& pos,
	double radius)
{
	// compute faces of a copy of G
	GraphCopy GC(G);
	PlanarModule pm;

	// compute a planar embedding if \a G is planar
	if(pm.planarityTest(G)) pm.planarEmbed(GC);

	CombinatorialEmbedding E(GC);
	E.computeFaces();

	// search for largest face
	face maxFace = E.maximalFace();

	// delete possible old entries in nodes and pos
	nodes.clear();
	pos.clear();

	// set nodes and pos
	NodeArray<bool> addMe(GC,true);
	adjEntry adj;

	List<node> maxNodes;
	forall_face_adj(adj,maxFace) {
		maxNodes.pushBack(adj->theNode());
	} 
Пример #2
0
bool CconnectClusterPlanar::preProcess(ClusterGraph &C,Graph &G)
{
	if (!isCConnected(C))
	{
		ogdf::sprintf(errorCode,124,"Graph is not C-connected \n"); 
		m_errorCode = nonCConnected;
		return false;
	}

	PlanarModule Pm;
	if (!Pm.planarityTest(C))
	{
		ogdf::sprintf(errorCode,124,"Graph is not planar\n"); 
		m_errorCode = nonPlanar;
		return false;
	}

	cluster c;

	SListPure<node> selfLoops;
	makeLoopFree(G,selfLoops);

	c = C.rootCluster();

	bool cPlanar = planarityTest(C,c,G);

	return cPlanar;
}
void ExpandedGraph2::expand(node v, node vPred, node vSucc)
{
    m_exp.clear();
    while (!m_nodesG.empty())
        m_GtoExp[m_nodesG.popBackRet()] = 0;

    edge eInS = 0;
    if (vPred != 0) {
        eInS = m_BC.dynamicSPQRForest().virtualEdge(vPred,v);
        m_eS = insertEdge(eInS->source(),eInS->target(),0);
    }
    edge eOutS = 0;
    if (vSucc != 0) {
        eOutS = m_BC.dynamicSPQRForest().virtualEdge(vSucc,v);
        m_eT = insertEdge(eOutS->source(),eOutS->target(),0);
    }

    expandSkeleton(v, eInS, eOutS);

    PlanarModule pm;
    pm.planarEmbed(m_exp);
    m_E.init(m_exp);
}
Пример #4
0
void PlanarDrawLayout::doCall(
	const Graph &G,
	adjEntry adjExternal,
	GridLayout &gridLayout,
	IPoint &boundingBox,
	bool fixEmbedding)
{
	// require to have a planar graph without multi-edges and self-loops;
	// planarity is checked below
	OGDF_ASSERT(isSimple(G) && isLoopFree(G));

	// handle special case of graphs with less than 3 nodes
	if(G.numberOfNodes() < 3)
	{
		node v1, v2;
		switch(G.numberOfNodes())
		{
		case 0:
			boundingBox = IPoint(0,0);
			return;

		case 1:
			v1 = G.firstNode();
			gridLayout.x(v1) = gridLayout.y(v1) = 0;
			boundingBox = IPoint(0,0);
			return;

		case 2:
			v1 = G.firstNode();
			v2 = G.lastNode ();
			gridLayout.x(v1) = gridLayout.y(v1) = gridLayout.y(v2) = 0;
			gridLayout.x(v2) = 1;
			boundingBox = IPoint(1,0);
			return;
		}
	}

	// we make a copy of G since we use planar biconnected augmentation
	GraphCopySimple GC(G);

	if(fixEmbedding) {
		PlanarAugmentationFix augmenter;
		augmenter.call(GC);

	} else {
		// augment graph planar biconnected
		m_augmenter.get().call(GC);

		// embed augmented graph
		PlanarModule pm;
		bool isPlanar = pm.planarEmbed(GC);
		if(isPlanar == false)
			OGDF_THROW_PARAM(PreconditionViolatedException, pvcPlanar);
	}

	// compute shelling order
	m_computeOrder.get().baseRatio(m_baseRatio);

	ShellingOrder order;
	m_computeOrder.get().call(GC,order,adjExternal);

	// compute grid coordinates for GC
	NodeArray<int> x(GC), y(GC);
	computeCoordinates(GC,order,x,y);

	boundingBox.m_x = x[order(1,order.len(1))];
	boundingBox.m_y = 0;
	node v;
	forall_nodes(v,GC)
		if(y[v] > boundingBox.m_y) boundingBox.m_y = y[v];

	// copy coordinates from GC to G
	forall_nodes(v,G) {
		node vCopy = GC.copy(v);
		gridLayout.x(v) = x[vCopy];
		gridLayout.y(v) = y[vCopy];
	}
Пример #5
0
Module::ReturnType SubgraphPlanarizer::doCall(PlanRep &PG,
	int cc,
	const EdgeArray<int>  &cost,
	const EdgeArray<bool> &forbid,
	const EdgeArray<unsigned int>  &subgraphs,
	int& crossingNumber)
{
	OGDF_ASSERT(m_permutations >= 1);
  
	OGDF_ASSERT(!(useSubgraphs()) || useCost()); // ersetze durch exception handling

	double startTime;
	usedTime(startTime);

	if(m_setTimeout)
		m_subgraph.get().timeLimit(m_timeLimit);

	List<edge> deletedEdges;
	PG.initCC(cc);
	EdgeArray<int> costPG(PG);
	edge e;
	forall_edges(e,PG)
		costPG[e] = cost[PG.original(e)];
	ReturnType retValue = m_subgraph.get().call(PG, costPG, deletedEdges);
	if(isSolution(retValue) == false)
		return retValue;

	for(ListIterator<edge> it = deletedEdges.begin(); it.valid(); ++it)
		*it = PG.original(*it);

	bool foundSolution = false;
	CrossingStructure cs;
	for(int i = 1; i <= m_permutations; ++i)
	{
		const int nG = PG.numberOfNodes();
		
		for(ListConstIterator<edge> it = deletedEdges.begin(); it.valid(); ++it)
			PG.delCopy(PG.copy(*it));

		deletedEdges.permute();
	
		if(m_setTimeout)
			m_inserter.get().timeLimit(
				(m_timeLimit >= 0) ? max(0.0,m_timeLimit - usedTime(startTime)) : -1);
		
		ReturnType ret;
		if(useForbid()) {
			if(useCost()) {
				if(useSubgraphs())
					ret = m_inserter.get().call(PG, cost, forbid, deletedEdges, subgraphs);
				else
					ret = m_inserter.get().call(PG, cost, forbid, deletedEdges);
			} else
				ret = m_inserter.get().call(PG, forbid, deletedEdges);
		} else {
			if(useCost()) {	
				if(useSubgraphs())
					ret = m_inserter.get().call(PG, cost, deletedEdges, subgraphs);
				else
					ret = m_inserter.get().call(PG, cost, deletedEdges);
			} else
				ret = m_inserter.get().call(PG, deletedEdges);
		}

		if(isSolution(ret) == false)
			continue; // no solution found, that's bad...
	
		if(!useCost())
			crossingNumber = PG.numberOfNodes() - nG;
		else {
			crossingNumber = 0;
			node n;
			forall_nodes(n, PG) {
				if(PG.original(n) == 0) { // dummy found -> calc cost
					edge e1 = PG.original(n->firstAdj()->theEdge());
					edge e2 = PG.original(n->lastAdj()->theEdge());
					if(useSubgraphs()) {
						int subgraphCounter = 0;
						for(int i=0; i<32; i++) {
							if(((subgraphs[e1] & (1<<i))!=0) && ((subgraphs[e2] & (1<<i)) != 0))
								subgraphCounter++;
						}
						crossingNumber += (subgraphCounter*cost[e1] * cost[e2]);
					} else
						crossingNumber += cost[e1] * cost[e2];
				}
			}
		}
		
		if(i == 1 || crossingNumber < cs.weightedCrossingNumber()) {
			foundSolution = true;
			cs.init(PG, crossingNumber);
		}
		
		if(localLogMode() == LM_STATISTIC) {
			if(m_permutations <= 200 ||
				i <= 10 || (i <= 30 && (i % 2) == 0) || (i > 30 && i <= 100 && (i % 5) == 0) || ((i % 10) == 0))
				sout() << "\t" << cs.weightedCrossingNumber();
		}
		
		PG.initCC(cc);

		if(m_timeLimit >= 0 && usedTime(startTime) >= m_timeLimit) {
			if(foundSolution == false)
				return retTimeoutInfeasible; // not able to find a solution...
			break;
		}
	}
	
	cs.restore(PG,cc); // restore best solution in PG
	crossingNumber = cs.weightedCrossingNumber();
	
	PlanarModule pm;
	OGDF_ASSERT(pm.planarityTest(PG) == true);
	
	return retFeasible;
}
Пример #6
0
void planarTriconnectedGraph(Graph &G, int n, int m)
{
	if (n < 4) n = 4;
	if(n % 2) ++n; // need an even number

	// start with K_4
	completeGraph(G,4);

	PlanarModule pm;
	pm.planarEmbed(G);

	// nodes[0],...,nodes[i-1] is array of all nodes
	Array<node> nodes(n);

	node v;
	int i = 0;
	forall_nodes(v,G)
		nodes[i++] = v;

	// create planar triconnected 3-graph
	for(; i < n; )
	{
		// pick a random node
		v = nodes[randomNumber(0,i-1)];

		adjEntry adj2 = v->firstAdj();
		int r = randomNumber(0,2);
		switch(r) {
			case 2: adj2 = adj2->succ(); // fall through to next case
			case 1: adj2 = adj2->succ();
		}
		adjEntry adj1 = adj2->cyclicSucc();

		nodes[i++] = G.splitNode(adj1,adj2);

		r = randomNumber(0,1);
		if(r == 0) {
			adjEntry adj = adj1->twin();
			G.newEdge(adj2,adj);
			nodes[i++] = G.splitNode(adj,adj->cyclicSucc()->cyclicSucc());

		} else {
			adjEntry adj = adj1->cyclicSucc()->twin();
			G.newEdge(adj2,adj,ogdf::before);
			nodes[i++] = G.splitNode(adj->cyclicPred(),adj->cyclicSucc());
		}
	}

	nodes.init();
	Array<edge> edges(m);

	CombinatorialEmbedding E(G);
	Array<face> faces(2*n);

	i = 0;
	face f;
	forall_faces(f,E) {
		if(f->size() >= 4)
			faces[i++] = f;
	}

	while(G.numberOfEdges() < m && i > 0)
	{
		int r = randomNumber(0,i-1);
		f = faces[r];
		faces[r] = faces[--i];

		int p = randomNumber(0,f->size()-1);
		int j = 0;
		adjEntry adj, adj2;
		for(adj = f->firstAdj(); j < p; adj = adj->faceCycleSucc(), ++j) ;

		p = randomNumber(2, f->size()-2);
		for(j = 0, adj2 = adj; j < p; adj2 = adj2->faceCycleSucc(), ++j) ;

		edge e = E.splitFace(adj,adj2);

		f = E.rightFace(e->adjSource());
		if(f->size() >= 4) faces[i++] = f;

		f = E.rightFace(e->adjTarget());
		if(f->size() >= 4) faces[i++] = f;
	}
}
Пример #7
0
void planarTriconnectedGraph(Graph &G, int n, double p1, double p2)
{
	if (n < 4) n = 4;

	// start with K_4
	completeGraph(G,4);

	PlanarModule pm;
	pm.planarEmbed(G);

	// nodes[0],...,nodes[i-1] is array of all nodes
	Array<node> nodes(n);

	node v;
	int i = 0;
	forall_nodes(v,G)
		nodes[i++] = v;

	for(; i < n; ++i)
	{
		// pick a random node
		v = nodes[randomNumber(0,i-1)];

		int m = v->degree();
		int a1 = randomNumber(0,m-1);
		int a2 = randomNumber(0,m-2);

		int j;
		adjEntry adj1, adj2;
		for(adj1 = v->firstAdj(), j = 0; j < a1; adj1 = adj1->succ(), ++j) ;
		for(adj2 = adj1->cyclicSucc(), j = 0; j < a2; adj2 = adj2->cyclicSucc(), ++j) ;

		adjEntry adj_b1 = adj2->cyclicPred();
		adjEntry adj_b2 = adj1->cyclicPred();

		nodes[i] = G.splitNode(adj1, adj2);

		if(adj1 == adj_b1)
			G.newEdge(adj_b1, adj2->twin());
		else if(adj2 == adj_b2)
			G.newEdge(adj2, adj_b1->twin(), ogdf::before);
		else {
			double r = randomDouble(0.0,1.0);
			if(r <= p1) {
				int s = randomNumber(0,1);
				if(s == 0)
					G.newEdge(adj_b1, adj2->twin());
				else
					G.newEdge(adj2, adj_b1->twin(), ogdf::before);
			}
		}

		double r = randomDouble(0.0,1.0);
		if(r <= p2) {
			int s = randomNumber(0,1);
			if(s == 0)
				G.newEdge(adj1, adj_b2->twin(), ogdf::before);
			else
				G.newEdge(adj_b2, adj1->twin());
		}
	}
}