Esempio n. 1
0
Module::ReturnType SubgraphPlanarizer::doCall(
	PlanRep &pr,
	int      cc,
	const EdgeArray<int>      *pCostOrig,
	const EdgeArray<bool>     *pForbiddenOrig,
	const EdgeArray<__uint32> *pEdgeSubGraphs,
	int                       &crossingNumber)
{
	OGDF_ASSERT(m_permutations >= 1);

	PlanarSubgraphModule &subgraph = m_subgraph.get();
	EdgeInsertionModule  &inserter = m_inserter.get();

	int nThreads = min(m_maxThreads, m_permutations);

	__int64 startTime;
	System::usedRealTime(startTime);
	__int64 stopTime = (m_timeLimit >= 0) ? (startTime + __int64(1000.0*m_timeLimit)) : -1;

	//
	// Compute subgraph
	//
	if(m_setTimeout)
		subgraph.timeLimit(m_timeLimit);

	pr.initCC(cc);

	List<edge> delEdges;
	ReturnType retValue;

	if(pCostOrig) {
		EdgeArray<int> costPG(pr);
		edge e;
		forall_edges(e,pr)
			costPG[e] = (*pCostOrig)[pr.original(e)];

		retValue = subgraph.call(pr, costPG, delEdges);
	} else
		retValue = subgraph.call(pr, delEdges);

	if(isSolution(retValue) == false)
		return retValue;

	const int m = delEdges.size();
	if(m == 0)
		return retOptimal;  // graph is planar

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

	//
	// Permutation phase
	//

	int seed = rand();
#ifdef OGDF_HAVE_CPP11
	minstd_rand rng(seed);
#endif

	if(nThreads > 1) {
		//
		// Parallel implementation
		//
		ThreadMaster master(
			pr, cc,
			pCostOrig, pForbiddenOrig, pEdgeSubGraphs,
			delEdges,
			seed,
			m_permutations - nThreads,
			stopTime);

		Array<Worker *> thread(nThreads-1);
		for(int i = 0; i < nThreads-1; ++i) {
			thread[i] = new Worker(&master, inserter.clone());
			thread[i]->start();
		}

#ifdef OGDF_HAVE_CPP11
		doWorkHelper(master, inserter, rng);
#else
		doWorkHelper(master, inserter);
#endif

		for(int i = 0; i < nThreads-1; ++i) {
			thread[i]->join();
			delete thread[i];
		}

		master.restore(pr, crossingNumber);

	} else {
		//
		// Sequential implementation
		//
		PlanRepLight prl(pr);

		Array<edge> deletedEdges(m);
		int j = 0;
		for(ListIterator<edge> it = delEdges.begin(); it.valid(); ++it)
			deletedEdges[j++] = *it;

		bool foundSolution = false;
		CrossingStructure cs;
		for(int i = 1; i <= m_permutations; ++i)
		{
			int cr;
			bool ok = doSinglePermutation(prl, cc, pCostOrig, pForbiddenOrig, pEdgeSubGraphs, deletedEdges, inserter,
#ifdef OGDF_HAVE_CPP11
				rng,
#endif
				cr);

			if(ok && (foundSolution == false || cr < cs.weightedCrossingNumber())) {
				foundSolution = true;
				cs.init(prl, cr);
			}

			if(stopTime >= 0 && System::realTime() >= stopTime) {
				if(foundSolution == false)
					return retTimeoutInfeasible; // not able to find a solution...
				break;
			}
		}

		cs.restore(pr,cc); // restore best solution in pr
		crossingNumber = cs.weightedCrossingNumber();

		OGDF_ASSERT(isPlanar(pr) == true);
	}

	return retFeasible;
}
Esempio n. 2
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;
}