Example #1
0
int main(int argc, char *argv[])
{
	Graph world;           // graph of world/distances
	FILE *data;            // file handle
	char  name[MAXNAME+2]; // input buffer to hold city name lines
	int   ncities;         // how many cities
	char *city[MAXCITIES]; // array of up to MAXCITIES city names
	int   maxflt;          // max length of flights

	// check command-line params
	if (argc != 1 && argc != 3 && argc != 4) usage();

	// get array of city names (assumes < MAXCITIES names)
	if ((data = fopen("ha30_name.txt","r")) == NULL) {
		fatal("Couldn't open file: ha30_name.txt");
	}
	ncities = 0;
	while (fgets(name,MAXNAME,data) != NULL) {
		name[strlen(name)-1] = '\0';
		city[ncities] = strdup(name);
		ncities++;
	}
	fclose(data);

	// make empty Graph
	world = newGraph(ncities);

	// get distances and populate Graph edges
	if ((data = fopen("ha30_dist.txt","r")) == NULL) {
		fatal("Couldn't open file: ha30_dist.txt");
	}
	int n=0, fromCity, toCity, distance;
	while (fscanf(data,"%d",&distance) == 1) {
		fromCity = n / ncities;
		toCity = n % ncities;
		// convert miles to km
		distance = distance * 100 * 1.609344;
		insertEdge(world, toCity, fromCity, distance);
		n++;
	}
	fclose(data);

	// get a new maximum flight distance
	maxflt = (argc == 4) ? atoi(argv[3]) : 10000;
	if (maxflt == 0) maxflt = 10000;

	// do what the user asks for
	if (argc == 1) {
		// only arg is data file => just show graph
		showGraph(world,city);
	}
	else {
		// find path from src -> dest
		int src = cityID(argv[1],city,ncities);
		if (src == -1)
			fatal("Source city name invalid");
		int dest = cityID(argv[2],city,ncities);
		if (dest == -1)
			fatal("Destination city name invalid");

		// use graph algorithm to find path
		int *path = malloc(ncities*sizeof(int));
		if (path == NULL)
			fatal("Can't allocate path array\n");
		int len = findPath(world,src,dest,maxflt,path);

		// display resulting path
		if (len < 0)
			printf("No route from %s to %s\n",argv[1],argv[2]);
		else {
			printf("Least-hops route:\n%s\n",city[path[0]]);
			int i;
			for (i = 1; i < len; i++)
				printf("->%s\n",city[path[i]]);
		}
	}
	return 0;
}
Example #2
0
static void
checkCompound(edge_t * e, graph_t * clg, agxbuf * xb, Dt_t * map, Dt_t* cmap)
{
    graph_t *tg;
    graph_t *hg;
    node_t *cn;
    node_t *cn1;
    node_t *t = agtail(e);
    node_t *h = aghead(e);
    edge_t *ce;
    item *ip;

    if (IS_CLUST_NODE(h)) return;
    tg = MAPC(t);
    hg = MAPC(h);
    if (!tg && !hg)
	return;
    if (tg == hg) {
	agerr(AGWARN, "cluster cycle %s -- %s not supported\n", agnameof(t),
	      agnameof(t));
	return;
    }
    ip = mapEdge(map, e);
    if (ip) {
	cloneEdge(e, ip->t, ip->h);
	return;
    }

    if (hg) {
	if (tg) {
	    if (agcontains(hg, tg)) {
		agerr(AGWARN, "tail cluster %s inside head cluster %s\n",
		      agnameof(tg), agnameof(hg));
		return;
	    }
	    if (agcontains(tg, hg)) {
		agerr(AGWARN, "head cluster %s inside tail cluster %s\n",
		      agnameof(hg),agnameof(tg));
		return;
	    }
	    cn = clustNode(t, tg, xb, clg);
	    cn1 = clustNode(h, hg, xb, clg);
	    ce = cloneEdge(e, cn, cn1);
	    insertEdge(map, t, h, ce);
	} else {
	    if (agcontains(hg, t)) {
		agerr(AGWARN, "tail node %s inside head cluster %s\n",
		      agnameof(t), agnameof(hg));
		return;
	    }
	    cn = clustNode(h, hg, xb, clg);
	    ce = cloneEdge(e, t, cn);
	    insertEdge(map, t, h, ce);
	}
    } else {
	if (agcontains(tg, h)) {
	    agerr(AGWARN, "head node %s inside tail cluster %s\n", agnameof(h),
		  agnameof(tg));
	    return;
	}
	cn = clustNode(t, tg, xb, clg);
	ce = cloneEdge(e, cn, h);
	insertEdge(map, t, h, ce);
    }
}
Example #3
0
 /**
  * \brief - Returns a Diamond graph
  * 
  * The diamond graph is a planar undirected graph with 4 vertices and 5 edges. It has 
  * radius 1, diameter 2, girth 3, chromatic number 3 and chromatic index 3. It is also 
  * a 2-vertex-connected and a 2-edge-connected Hamiltonian graph.
  * Reference Link - <a href="http://en.wikipedia.org/wiki/Franklin_graph">Nauru Graph</a>
  * 
  * @param std::vector<int> args - First parameter, a vector of integers, not used here,
  * included for consistency
  * 
  * @param int start- Second parameter, the starting position from which the vertices are 
  * to be added, default value 1
  * 
  * @returns Graph<int,int> - a Diamond graph
  * **/
 Graph<int,int> diamond(std::vector<int>, int start=1)
 {
     auto result = cycle({4},start);
     result.insertEdge(start+1,start+3,1);
     return result;
 }
Example #4
0
void DDGNode::addAntiDependency(DDGNode *dependent, int myIteration, int dependentIteration)
{
	insertEdge(dependent, 0, myIteration, dependentIteration, ANTI_DEP);
	printEdges();
}
Example #5
0
void DDGNode::addOutputDependency(DDGNode *dependent, int myIteration, int dependentIteration)
{
	insertEdge(dependent, latency, myIteration, dependentIteration, OUT_DEP);
	printEdges();
}
Example #6
0
int main(int argc, char **argv) {
    FILE *inFile;
    char str[20000];
    char *token;
    int nVerts;
    int nReqs;
    Graph pathGraph;

    /*
     * Validate input file
     *
     */

    if (argc < 2) {
        perror("Please specify an input file\n");
        return (-1);
    }

    inFile = fopen(argv[1], "r");
    if (inFile == NULL) {
        perror("Could not open input file");
        return (-1);
    }

    /*
     * Read Input file
     *
     */

    fgets(str, 60, inFile);
    strtok(str, "\n");
    token = strtok(str, " ");
    nVerts = atoi( token );
    token = strtok(NULL, " ");
    nReqs = atoi( token );


    /*
     * Build Graph & Insert Edges
     *
     */

    pathGraph = newGraph( nVerts );

    for (int from = 0; from < nVerts; ++from ) {
        fgets (str, 20000, inFile);
        strtok(str, "\n");

        token = strtok(str, " ");
        token = strtok (NULL, " ");

        while( token != NULL) {
            int to = atoi( token );

            insertEdge( pathGraph, from, to);
            token = strtok (NULL, " ");
        }
    }

    /*
     * Process requests and find paths
     *
     */

    for (int from = 0; from < nReqs; ++from ) {
        int source;
        int dest;
        fgets (str, 20000, inFile);
        strtok(str, "\n");

        token = strtok(str, " ");
        source = atoi( token );
        token = strtok(NULL, " ");
        dest = atoi( token );

        doBFS(pathGraph, source);
        int dist = getDistance( pathGraph, dest);
        if ( dist > -1) {
            printf("The shortest path from %d to %d requires %d edge(s):\n", source, dest, dist);
            ListHndl path = getPathTo( pathGraph, dest);
            moveFirst( path );
            while( !offEnd( path )) {
                printf("%d ", getCurrent( path));
                if ( !atLast( path )) { printf( "-> "); }
                else { printf("\n\n"); }
                moveNext( path );
            }

            freeList( path );

        } else {
            printf("No path from %d to %d exists\n\n", source, dest);
        }
    }

    fclose (inFile);

    freeGraph(pathGraph);

    return 0;
}
Example #7
0
void DDGNode::addFlowDependency(DDGNode *dependent, int myIteration, int dependentIteration)
{
	insertEdge(dependent, latency, myIteration, dependentIteration, TRUE_DEP);
	printEdges();
}
void
NIImporter_OpenStreetMap::_loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) {
    // check whether the option is set (properly)
    if (!oc.isSet("osm-files")) {
        return;
    }
    // preset types
    //  for highways
    NBTypeCont& tc = nb.getTypeCont();
    SUMOReal const WIDTH = NBEdge::UNSPECIFIED_WIDTH;
    tc.insert("highway.motorway",      3, (SUMOReal)(160./ 3.6), 13, WIDTH, SVC_UNKNOWN, true);
    tc.insert("highway.motorway_link", 1, (SUMOReal)(80. / 3.6), 12, WIDTH, SVC_UNKNOWN, true);
    tc.insert("highway.trunk",         2, (SUMOReal)(100./ 3.6), 11, WIDTH); // !!! 130km/h?
    tc.insert("highway.trunk_link",    1, (SUMOReal)(80. / 3.6), 10, WIDTH);
    tc.insert("highway.primary",       2, (SUMOReal)(100./ 3.6),  9, WIDTH);
    tc.insert("highway.primary_link",  1, (SUMOReal)(80. / 3.6),  8, WIDTH);
    tc.insert("highway.secondary",     2, (SUMOReal)(100./ 3.6),  7, WIDTH);
    tc.insert("highway.secondary_link",1, (SUMOReal)(80. / 3.6),  6, WIDTH);
    tc.insert("highway.tertiary",      1, (SUMOReal)(80. / 3.6),  6, WIDTH);
    tc.insert("highway.tertiary_link", 1, (SUMOReal)(80. / 3.6),  5, WIDTH);
    tc.insert("highway.unclassified",  1, (SUMOReal)(80. / 3.6),  5, WIDTH);
    tc.insert("highway.residential",   1, (SUMOReal)(50. / 3.6),  4, WIDTH); // actually, maybe one lane for parking would be nice...
    tc.insert("highway.living_street", 1, (SUMOReal)(10. / 3.6),  3, WIDTH);
    tc.insert("highway.service",       1, (SUMOReal)(20. / 3.6),  2, WIDTH, SVC_DELIVERY);
    tc.insert("highway.track",         1, (SUMOReal)(20. / 3.6),  1, WIDTH);
    tc.insert("highway.services",      1, (SUMOReal)(30. / 3.6),  1, WIDTH);
    tc.insert("highway.unsurfaced",    1, (SUMOReal)(30. / 3.6),  1, WIDTH); // unofficial value, used outside germany
    tc.insert("highway.footway",       1, (SUMOReal)(30. / 3.6),  1, WIDTH, SVC_PEDESTRIAN); 
    tc.insert("highway.pedestrian",    1, (SUMOReal)(30. / 3.6),  1, WIDTH, SVC_PEDESTRIAN);

    tc.insert("highway.path",          1, (SUMOReal)(10. / 3.6),  1, WIDTH, SVC_PEDESTRIAN);
    tc.insert("highway.bridleway",     1, (SUMOReal)(10. / 3.6),  1, WIDTH, SVC_BICYCLE); // no horse stuff
    tc.insert("highway.cycleway",      1, (SUMOReal)(20. / 3.6),  1, WIDTH, SVC_BICYCLE);
    tc.insert("highway.footway",       1, (SUMOReal)(10. / 3.6),  1, WIDTH, SVC_PEDESTRIAN);
    tc.insert("highway.step",          1, (SUMOReal)(5.  / 3.6),  1, WIDTH, SVC_PEDESTRIAN); // additional
    tc.insert("highway.steps",         1, (SUMOReal)(5.  / 3.6),  1, WIDTH, SVC_PEDESTRIAN); // :-) do not run too fast
    tc.insert("highway.stairs",        1, (SUMOReal)(5.  / 3.6),  1, WIDTH, SVC_PEDESTRIAN); // additional
    tc.insert("highway.bus_guideway",  1, (SUMOReal)(30. / 3.6),  1, WIDTH, SVC_BUS);
    tc.insert("highway.raceway",       2, (SUMOReal)(300./ 3.6), 14, WIDTH, SVC_VIP);
    tc.insert("highway.ford",          1, (SUMOReal)(10. / 3.6),  1, WIDTH, SVC_PUBLIC_ARMY);

    //  for railways
    tc.insert("railway.rail",          1, (SUMOReal)(30. / 3.6),  1, WIDTH, SVC_RAIL_FAST);
    tc.insert("railway.tram",          1, (SUMOReal)(30. / 3.6),  1, WIDTH, SVC_CITYRAIL);
    tc.insert("railway.light_rail",    1, (SUMOReal)(30. / 3.6),  1, WIDTH, SVC_LIGHTRAIL);
    tc.insert("railway.subway",        1, (SUMOReal)(30. / 3.6),  1, WIDTH, SVC_CITYRAIL);
    tc.insert("railway.preserved",     1, (SUMOReal)(30. / 3.6),  1, WIDTH, SVC_LIGHTRAIL);
    tc.insert("railway.monorail",      1, (SUMOReal)(30. / 3.6),  1, WIDTH, SVC_LIGHTRAIL); // rail stuff has to be discussed


    /* Parse file(s)
     * Each file is parsed twice: first for nodes, second for edges. */
    std::vector<std::string> files = oc.getStringVector("osm-files");
    // load nodes, first
    NodesHandler nodesHandler(myOSMNodes, myUniqueNodes);
    for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
        // nodes
        if (!FileHelpers::exists(*file)) {
            WRITE_ERROR("Could not open osm-file '" + *file + "'.");
            return;
        }
        nodesHandler.setFileName(*file);
        PROGRESS_BEGIN_MESSAGE("Parsing nodes from osm-file '" + *file + "'");
        if (!XMLSubSys::runParser(nodesHandler, *file)) {
            return;
        }
        PROGRESS_DONE_MESSAGE();
    }
    // load edges, then
    EdgesHandler edgesHandler(myOSMNodes, myEdges);
    for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
        // edges
        edgesHandler.setFileName(*file);
        PROGRESS_BEGIN_MESSAGE("Parsing edges from osm-file '" + *file + "'");
        XMLSubSys::runParser(edgesHandler, *file);
        PROGRESS_DONE_MESSAGE();
    }

    /* Remove duplicate edges with the same shape and attributes */
    if (!OptionsCont::getOptions().getBool("osm.skip-duplicates-check")) {
        PROGRESS_BEGIN_MESSAGE("Removing duplicate edges");
        if (myEdges.size() > 1) {
            std::set<const Edge*, CompareEdges> dupsFinder;
            for (std::map<std::string, Edge*>::iterator it = myEdges.begin(); it != myEdges.end();) {
                if (dupsFinder.count(it->second) > 0) {
                    WRITE_MESSAGE("Found duplicate edges. Removing " + it->first);
                    delete it->second;
                    myEdges.erase(it++);
                } else {
                    dupsFinder.insert(it->second);
                    it++;
                }
            }
        }
        PROGRESS_DONE_MESSAGE();
    }

    /* Mark which nodes are used (by edges or traffic lights).
     * This is necessary to detect which OpenStreetMap nodes are for
     * geometry only */
    std::map<int, int> nodeUsage;
    // Mark which nodes are used by edges (begin and end)
    for (std::map<std::string, Edge*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
        Edge* e = (*i).second;
        assert(e->myCurrentIsRoad);
        for (std::vector<int>::const_iterator j = e->myCurrentNodes.begin(); j != e->myCurrentNodes.end(); ++j) {
            if (nodeUsage.find(*j) == nodeUsage.end()) {
                nodeUsage[*j] = 0;
            }
            nodeUsage[*j] = nodeUsage[*j] + 1;
        }
    }
    // Mark which nodes are used by traffic lights
    for (std::map<int, NIOSMNode*>::const_iterator nodesIt = myOSMNodes.begin(); nodesIt != myOSMNodes.end(); ++nodesIt) {
        if (nodesIt->second->tlsControlled) {
            // If the key is not found in the map, the value is automatically
            // initialized with 0.
            nodeUsage[nodesIt->first] += 1;
        }
    }
    /* Instantiate edges
     * Only those nodes in the middle of an edge which are used by more than
     * one edge are instantiated. Other nodes are considered as geometry nodes. */
    NBNodeCont& nc = nb.getNodeCont();
    NBEdgeCont& ec = nb.getEdgeCont();
    NBTrafficLightLogicCont& tlsc = nb.getTLLogicCont();
    for (std::map<std::string, Edge*>::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
        Edge* e = (*i).second;
        assert(e->myCurrentIsRoad);
        // build nodes;
        //  the from- and to-nodes must be built in any case
        //  the geometry nodes are only built if more than one edge references them
        NBNode* currentFrom = insertNodeChecking(*e->myCurrentNodes.begin(), nc, tlsc);
        NBNode* last = insertNodeChecking(*(e->myCurrentNodes.end() - 1), nc, tlsc);
        int running = 0;
        std::vector<int> passed;
        for (std::vector<int>::iterator j = e->myCurrentNodes.begin(); j != e->myCurrentNodes.end(); ++j) {
            passed.push_back(*j);
            if (nodeUsage[*j] > 1 && j != e->myCurrentNodes.end() - 1 && j != e->myCurrentNodes.begin()) {
                NBNode* currentTo = insertNodeChecking(*j, nc, tlsc);
                insertEdge(e, running, currentFrom, currentTo, passed, ec, tc);
                currentFrom = currentTo;
                running++;
                passed.clear();
            }
        }
        if (running == 0) {
            running = -1;
        }
        insertEdge(e, running, currentFrom, last, passed, ec, tc);
    }
}
Example #9
0
void ConnectivityGraph::init( const OptimizableFunction & func,
		const VariablePtrVec & vars, const FactorPtrVec & factors ) {

	assert( (VariableCount) vars.size() == numvariables );

	numfactors = factors.size();
	numvertices = numvariables + numfactors;

	numlevels = (VariableCount) ( std::log( (double) numvertices ) /
				std::log( 2.0 ) );

	const Clock::time_point starttime = Clock::now();

	std::cout << "connectivity graph init: " << numvariables << " vars, " <<
			numfactors << " factors, " << numvertices << " vertices, " <<
			numlevels << " levels" << std::endl;

	vertices.reserve( numvertices );

	// create all the forests (empty)
	forests.resize( numlevels );

//	edgepool.setMaxSize( numfactors * numvertices * numvertices );

#ifdef DEBUG
	assignedVars.clear();
	assignedFactors.clear();
	assignedVars.resize( numvertices );
	assignedFactors.resize( numfactors );

//	existingEdges.clear();
//	existingEdges.resize( numvertices,
//			std::vector< BOOSTNS::dynamic_bitset<> >( numvertices,
//					BOOSTNS::dynamic_bitset<>( numfactors )  ) );
#endif // DEBUG

	// create a vertex for each variable and put all the loop nodes in forests
	for ( Variable * vp : vars ) {
		vertices.emplace_back( vp, 0, numlevels );
		Vertex & vx = vertices.back();

		for ( ETForestLevel l = 0; l < numlevels; ++l ) {
			forests[l].emplace( vx.getETVertexID(), vx.ETvertices[l].loopNode );
		}
	}

	// create a vertex for each factor and put all the loop nodes in forests
	for ( Factor * fp : factors ) {
		vertices.emplace_back( fp, numvariables, numlevels );
		Vertex & vx = vertices.back();

		for ( ETForestLevel l = 0; l < numlevels; ++l ) {
			forests[l].emplace( vx.getETVertexID(), vx.ETvertices[l].loopNode );
		}
	}

	size_t nedges = 0;

	// add all of the edges -- this is a factor graph, so connect all factor
	// vertices to all variables contained in that factor
	for ( const Factor * f : factors ) {
		if ( f->isAssigned() ) continue;
		const VariablePtrVec & fvars( f->getVariables() );
		for ( const Variable * v : fvars ) {
			if ( v->isAssigned() ) continue;
			if ( f->containsVar( v->getID() ) ) {
//				std::cout << "inserting edge from vid: " << v->getID() <<
//						" to fid " << f->getID() << std::endl;
				insertEdge( vidToVertexID( v->getID() ),
						fidToVertexID( f->getID() ) );
				++nedges;
			}
		}
	}

	BOOSTNS::dynamic_bitset<> addedBlockEdges( func.getNumBlocks(), false );
	VariableID vidl, vidu;
	VariableCount bid;

	// add edges between all the variables in each block (so they never get
	// separated)
	for ( const Variable * vp : vars ) {
		if ( vp->isAssigned() ) continue;
		bid = func.getBlockID( vp->getID() );
		if ( addedBlockEdges[bid] ) continue;

		func.getBlockRangeByBlkId( bid, vidl, vidu );

		for ( VariableID vid1 = vidl; vid1 < vidu; ++vid1 ) {
			for ( VariableID vid2 = vid1+1; vid2 <= vidu; ++vid2 ) {
//				std::cout << "inserting edge from vid: " << vid1 <<
//						" to vid " << vid2 << " (block " << bid << ")"  << std::endl;
				insertEdge( vidToVertexID( vid1 ), vidToVertexID( vid2 ) );
				++nedges;
			}
		}

		addedBlockEdges[bid] = true;
	}

//	drawgraph();

	std::cout << "connectivity graph initialization completed in " <<
			( (Duration) ( Clock::now() - starttime ) ).count() <<
			" seconds (" << nedges << " edges)" << std::endl;
}
Example #10
0
//main/////////////////////////////////////////////////////////////////////////////////////////////////////////
int main(){
    mapa m;
    grafo g = inicializaGrafo(&g, &m);
    int i, i1, i2, i3;

    char esc[20];       //comando a ser digitado

    int FM = 1;
    while (FM == 1){

        scanf("%s", esc);  //lerá o comando até o primeiro espaço, para depois ler até o proximo espaço, e assim por diante
        int escI = identificaComando(esc);  //identifica o comando digitado
        switch(escI){
            case _CV:   //cria vértice
                scanf("%d", &i1);
                insertVertex(&g, &m, i1);
                break;

            case _DV:   //destrói vértice
                scanf("%d", &i1);
                removeVertex(&g, i1, &m);
                break;

            case _CA:   //cria aresta
                scanf("%d %d %d", &i1, &i2, &i3);
                insertEdge(&g, i1, i2, &m, i3);
                break;

            case _DA:   //destrói aresta
                scanf("%d", &i1);
                removeEdge(&g, i1, &m);
                break;

            case _TV:   //troca vértice
                scanf("%d %d", &i1, &i2);
                replaceVertex(i1, i2, m);
                break;

            case _TA:   //troca aresta
                scanf("%d %d", &i1, &i2);
                replaceEdge(i1, i2, m);
                break;

            case _IG:   //imprime grafo
                printf("%d\n", g.nvertices);
                for (i = 0; i < m.indiceVert; i++){
                    vertice *v = pegaVertRef(m, i+1);
                    if (v != NULL){
                        printf("%d ", i+1);
                        printf("%d\n", v->conteudo);
                    }
                }

                printf("%d\n", g.narestas);
                for (i = 0; i < m.indiceAres; i++){
                    aresta *a = pegaAresRef(m, i+1);
                    if (a != NULL){
                        printf("%d ", i+1);
                        vertice *vT = a->dir;
                        printf("%d ", pegaVertInd(m, vT));
                        vT = a->esq;
                        printf("%d ", pegaVertInd(m, vT));
                        printf("%d\n", a->conteudo);
                    }
                }
                break;

            case _CM:   //caminho mínimo
                scanf("%d %d", &i1, &i2);
                dijkstra(&g, m, i1, i2);
                break;

            case _FM:   //fim
                FM = 0;
                break;

        }
    }
    return 0;
}
Example #11
0
//---------------------------------------------------------
// actual call (called by all variations of call)
//   crossing of generalizations is forbidden if forbidCrossingGens = true
//   edge costs are obeyed if costOrig != 0
//
Module::ReturnType FixedEmbeddingInserter::doCall(
	PlanRep &PG,
	const List<edge> &origEdges,
	bool forbidCrossingGens,
	const EdgeArray<int>  *costOrig,
	const EdgeArray<bool> *forbiddenEdgeOrig,
	const EdgeArray<unsigned int> *edgeSubGraph)
{
  
	double T;
	usedTime(T);
	
	ReturnType retValue = retFeasible;
	m_runsPostprocessing = 0;

	PG.embed(); 
	OGDF_ASSERT(PG.representsCombEmbedding() == true);

	if (origEdges.size() == 0)
		return retOptimal;  // nothing to do

	// initialization
	CombinatorialEmbedding E(PG);  // embedding of PG

	m_dual.clear();
	m_primalAdj.init(m_dual);
	m_nodeOf.init(E);

	// construct dual graph
	m_primalIsGen.init(m_dual,false);

	OGDF_ASSERT(forbidCrossingGens == false || forbiddenEdgeOrig == 0);

	if(forbidCrossingGens)
		constructDualForbidCrossingGens((const PlanRepUML&)PG,E);
	else
		constructDual(PG,E,forbiddenEdgeOrig);

	// m_delFaces and m_newFaces are used by removeEdge()
	// if we can't allocate memory for them, we throw an exception
	if (removeReinsert() != rrNone) {
		m_delFaces = new FaceSetSimple(E);
		if (m_delFaces == 0)
			OGDF_THROW(InsufficientMemoryException);

		m_newFaces = new FaceSetPure(E);
		if (m_newFaces == 0) {
			delete m_delFaces;
			OGDF_THROW(InsufficientMemoryException);
		}

	// no postprocessing -> no removeEdge()
	} else {
		m_delFaces = 0;
		m_newFaces = 0;
	}

	SListPure<edge> currentOrigEdges;
	if(removeReinsert() == rrIncremental) {
		edge e;
		forall_edges(e,PG)
			currentOrigEdges.pushBack(PG.original(e));
	}

	// insertion of edges
	ListConstIterator<edge> it;
	for(it = origEdges.begin(); it.valid(); ++it)
	{
		edge eOrig = *it;

		int eSubGraph = 0;  // edgeSubGraph-data of eOrig
		if(edgeSubGraph!=0) eSubGraph = (*edgeSubGraph)[eOrig];

		SList<adjEntry> crossed;
		if(costOrig != 0) {
			findShortestPath(PG, E, *costOrig,
				PG.copy(eOrig->source()),PG.copy(eOrig->target()),
				forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrig) : Graph::association,
				crossed, edgeSubGraph, eSubGraph);
		} else {
			findShortestPath(E,
				PG.copy(eOrig->source()),PG.copy(eOrig->target()),
				forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrig) : Graph::association,
				crossed);
		}

		insertEdge(PG,E,eOrig,crossed,forbidCrossingGens,forbiddenEdgeOrig);
		
		if(removeReinsert() == rrIncremental) {
			currentOrigEdges.pushBack(eOrig);

			bool improved;
			do {
				++m_runsPostprocessing;
				improved = false;
				
				SListConstIterator<edge> itRR;
				for(itRR = currentOrigEdges.begin(); itRR.valid(); ++itRR)
				{
					edge eOrigRR = *itRR;
		
					int pathLength;
					if(costOrig != 0)
						pathLength = costCrossed(eOrigRR,PG,*costOrig,edgeSubGraph);
					else
						pathLength = PG.chain(eOrigRR).size() - 1;
					if (pathLength == 0) continue; // cannot improve
		
					removeEdge(PG,E,eOrigRR,forbidCrossingGens,forbiddenEdgeOrig);
		
					// try to find a better insertion path
					SList<adjEntry> crossed;
					if(costOrig != 0) {
						int eSubGraph = 0;  // edgeSubGraph-data of eOrig
						if(edgeSubGraph!=0) eSubGraph = (*edgeSubGraph)[eOrigRR];

						findShortestPath(PG, E, *costOrig,
							PG.copy(eOrigRR->source()),PG.copy(eOrigRR->target()),
							forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrigRR) : Graph::association,
							crossed, edgeSubGraph, eSubGraph);
					} else {
						findShortestPath(E,
							PG.copy(eOrigRR->source()),PG.copy(eOrigRR->target()),
							forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrigRR) : Graph::association,
							crossed);
					}
					
					// re-insert edge (insertion path cannot be longer)
					insertEdge(PG,E,eOrigRR,crossed,forbidCrossingGens,forbiddenEdgeOrig);
		
					int newPathLength = (costOrig != 0) ? costCrossed(eOrigRR,PG,*costOrig,edgeSubGraph) : (PG.chain(eOrigRR).size() - 1);
					OGDF_ASSERT(newPathLength <= pathLength);
					
					if(newPathLength < pathLength)
						improved = true;
				}
			} while (improved);
		}
	}

	const Graph &G = PG.original();
	if(removeReinsert() != rrIncremental) {
		// postprocessing (remove-reinsert heuristc)
		SListPure<edge> rrEdges;
	
		switch(removeReinsert())
		{
		case rrAll:
		case rrMostCrossed: {
				const List<node> &origInCC = PG.nodesInCC();
				ListConstIterator<node> itV;
	
				for(itV = origInCC.begin(); itV.valid(); ++itV) {
					node vG = *itV;
					adjEntry adj;
					forall_adj(adj,vG) {
						if ((adj->index() & 1) == 0) continue;
						edge eG = adj->theEdge();
						rrEdges.pushBack(eG);
					}
				}
			}
			break;
	
		case rrInserted:
			for(ListConstIterator<edge> it = origEdges.begin(); it.valid(); ++it)
				rrEdges.pushBack(*it);
			break;

		case rrNone:
		case rrIncremental:
			break;
		}
	
		// marks the end of the interval of rrEdges over which we iterate
		// initially set to invalid iterator which means all edges
		SListConstIterator<edge> itStop;
	
		bool improved;
		do {
			// abort postprocessing if time limit reached
			if (m_timeLimit >= 0 && m_timeLimit <= usedTime(T)) {
				retValue = retTimeoutFeasible;
				break;
			}
				
			++m_runsPostprocessing;
			improved = false;
	
			if(removeReinsert() == rrMostCrossed)
			{
				FEICrossingsBucket bucket(&PG);
				rrEdges.bucketSort(bucket);
	
				const int num = int(0.01 * percentMostCrossed() * G.numberOfEdges());
				itStop = rrEdges.get(num);
			}
	
			SListConstIterator<edge> it;
			for(it = rrEdges.begin(); it != itStop; ++it)
			{
				edge eOrig = *it;
							
				// remove only if crossings on edge;
				// in especially: forbidden edges are never handled by postprocessing
				//   since there are no crossings on such edges
				int pathLength;
				if(costOrig != 0)
					pathLength = costCrossed(eOrig,PG,*costOrig,edgeSubGraph);
				else
					pathLength = PG.chain(eOrig).size() - 1;
				if (pathLength == 0) continue; // cannot improve
	
				removeEdge(PG,E,eOrig,forbidCrossingGens,forbiddenEdgeOrig);
	
				// try to find a better insertion path
				SList<adjEntry> crossed;
				if(costOrig != 0) {
					int eSubGraph = 0;  // edgeSubGraph-data of eOrig
					if(edgeSubGraph!=0) eSubGraph = (*edgeSubGraph)[eOrig];

					findShortestPath(PG, E, *costOrig,
						PG.copy(eOrig->source()),PG.copy(eOrig->target()),
						forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrig) : Graph::association,
						crossed, edgeSubGraph, eSubGraph);
				} else {
					findShortestPath(E,
						PG.copy(eOrig->source()),PG.copy(eOrig->target()),
						forbidCrossingGens ? ((const PlanRepUML&)PG).typeOrig(eOrig) : Graph::association,
						crossed);
				}
	
				// re-insert edge (insertion path cannot be longer)
				insertEdge(PG,E,eOrig,crossed,forbidCrossingGens,forbiddenEdgeOrig);
	
				int newPathLength = (costOrig != 0) ? costCrossed(eOrig,PG,*costOrig,edgeSubGraph) : (PG.chain(eOrig).size() - 1);
				OGDF_ASSERT(newPathLength <= pathLength);
				
				if(newPathLength < pathLength)
					improved = true;
			}
		} while(improved); // iterate as long as we improve
	}
Example #12
0
void testTidalTrust(int bucketsNumber, int bucketSize) {
    //create small graph for testing tidal's trust algorithm result
    Graph* gtt = createGraph(bucketsNumber, bucketSize);

    TrustNode* n1tt = new TrustNode(1, NULL, NULL);
		Properties* tidalTrustProperties1 = new Properties(2);
		tidalTrustProperties1->setDoubleProperty(-1.0, 0); //trustValue
		tidalTrustProperties1->setIntegerProperty(INT_MAX, 1);	 //last updated depth
		n1tt->setTidalTrustProperties(tidalTrustProperties1);
	TrustNode* n2tt = new TrustNode(2, NULL, NULL);
    	Properties* tidalTrustProperties2 = new Properties(2);
		tidalTrustProperties2->setDoubleProperty(-1.0, 0); //trustValue
		tidalTrustProperties2->setIntegerProperty(INT_MAX, 1);	 //last updated depth
		n2tt->setTidalTrustProperties(tidalTrustProperties2);
	TrustNode* n3tt = new TrustNode(3, NULL, NULL);
		Properties* tidalTrustProperties3 = new Properties(2);
		tidalTrustProperties3->setDoubleProperty(-1.0, 0); //trustValue
		tidalTrustProperties3->setIntegerProperty(INT_MAX, 1);	 //last updated depth
		n3tt->setTidalTrustProperties(tidalTrustProperties3);
	TrustNode* n4tt = new TrustNode(4, NULL, NULL);
		Properties* tidalTrustProperties4 = new Properties(2);
		tidalTrustProperties4->setDoubleProperty(-1.0, 0); //trustValue
		tidalTrustProperties4->setIntegerProperty(INT_MAX, 1);	 //last updated depth
		n4tt->setTidalTrustProperties(tidalTrustProperties4);
    TrustNode* n5tt = new TrustNode(5, NULL, NULL);
		Properties* tidalTrustProperties5 = new Properties(2);
		tidalTrustProperties5->setDoubleProperty(-1.0, 0); //trustValue
		tidalTrustProperties5->setIntegerProperty(INT_MAX, 1);	 //last updated depth
		n5tt->setTidalTrustProperties(tidalTrustProperties5);
    TrustNode* n6tt = new TrustNode(6, NULL, NULL);
		Properties* tidalTrustProperties6 = new Properties(2);
		tidalTrustProperties6->setDoubleProperty(-1.0, 0); //trustValue
		tidalTrustProperties6->setIntegerProperty(INT_MAX, 1);	 //last updated depth
		n6tt->setTidalTrustProperties(tidalTrustProperties6);
    TrustNode* n7tt = new TrustNode(7, NULL, NULL);
		Properties* tidalTrustProperties7 = new Properties(2);
		tidalTrustProperties7->setDoubleProperty(-1.0, 0); //trustValue
		tidalTrustProperties7->setIntegerProperty(INT_MAX, 1);	 //last updated depth
		n7tt->setTidalTrustProperties(tidalTrustProperties7);
    TrustNode* n8tt = new TrustNode(8, NULL, NULL);
		Properties* tidalTrustProperties8 = new Properties(2);
		tidalTrustProperties8->setDoubleProperty(-1.0, 0); //trustValue
		tidalTrustProperties8->setIntegerProperty(INT_MAX, 1);	 //last updated depth
		n8tt->setTidalTrustProperties(tidalTrustProperties8);
    TrustNode* n9tt = new TrustNode(9, NULL, NULL);
		Properties* tidalTrustProperties9 = new Properties(2);
		tidalTrustProperties9->setDoubleProperty(-1.0, 0); //trustValue
		tidalTrustProperties9->setIntegerProperty(INT_MAX, 1);	 //last updated depth
		n9tt->setTidalTrustProperties(tidalTrustProperties9);
    TrustNode* n10tt = new TrustNode(10, NULL, NULL);
		Properties* tidalTrustProperties10 = new Properties(2);
		tidalTrustProperties10->setDoubleProperty(-1.0, 0); //trustValue
		tidalTrustProperties10->setIntegerProperty(INT_MAX, 1);	 //last updated depth
		n10tt->setTidalTrustProperties(tidalTrustProperties10);
    TrustNode* n11tt = new TrustNode(11, NULL, NULL);
		Properties* tidalTrustProperties11 = new Properties(2);
		tidalTrustProperties11->setDoubleProperty(-1.0, 0); //trustValue
		tidalTrustProperties11->setIntegerProperty(INT_MAX, 1);	 //last updated depth
		n11tt->setTidalTrustProperties(tidalTrustProperties11);

    insertNode(n1tt, gtt);
    insertNode(n2tt, gtt);
    insertNode(n3tt, gtt);
    insertNode(n4tt, gtt);
    insertNode(n5tt, gtt);
    insertNode(n6tt, gtt);
    insertNode(n7tt, gtt);
    insertNode(n8tt, gtt);
    insertNode(n9tt, gtt);
    insertNode(n10tt, gtt);
    insertNode(n11tt, gtt);


    Edge* e1tt = setEdgeTrustProperties(1, 2, 1.0);
    Edge* e2tt = setEdgeTrustProperties(1, 5, 1.0);
    Edge* e3tt = setEdgeTrustProperties(2, 3, 0.9);
    Edge* e4tt = setEdgeTrustProperties(2, 4, 0.9);
    Edge* e5tt = setEdgeTrustProperties(3, 6, 0.8);
    Edge* e6tt = setEdgeTrustProperties(4, 6, 0.3);
    Edge* e7tt = setEdgeTrustProperties(4, 7, 0.9);
    Edge* e8tt = setEdgeTrustProperties(5, 10, 0.9);
    Edge* e9tt = setEdgeTrustProperties(6, 9, 1.0);
    Edge* e10tt = setEdgeTrustProperties(7, 8, 1.0);
    Edge* e11tt = setEdgeTrustProperties(8, 9, 1.0);
    Edge* e12tt = setEdgeTrustProperties(9, 11, 1.0);
    Edge* e13tt = setEdgeTrustProperties(10, 11, 0.4);

    /* Insert edges in graph */
    insertEdge(1, e1tt, gtt);
    insertEdge(1, e2tt, gtt);
    insertEdge(2, e3tt, gtt);
    insertEdge(2, e4tt, gtt);
    insertEdge(3, e5tt, gtt);
    insertEdge(4, e6tt, gtt);
    insertEdge(4, e7tt, gtt);
    insertEdge(5, e8tt, gtt);
    insertEdge(6, e9tt, gtt);
    insertEdge(7, e10tt, gtt);
    insertEdge(8, e11tt, gtt);
    insertEdge(9, e12tt, gtt);
    insertEdge(10, e13tt, gtt);

    Node *att = lookupNode(1, gtt);

    Node *btt = lookupNode(11, gtt);

    //Estimate trust(1,11)
    double trust1_11 = estimateTrust(att, btt, gtt);
    CHECKDOUBLE("Graph estimate trust (1,11)", trust1_11, 0.36);

    //Estimate trust(1,9)
    Node *ctt = lookupNode(9, gtt);
    double trust1_9 = estimateTrust(att, ctt, gtt);
    CHECKDOUBLE("Graph estimate trust (1,9)", trust1_9, 0.72);
}
Example #13
0
void testClosenessCentrality(int bucketsNumber, int bucketSize) {
    //create small graph for testing betweenness Centrality
    Graph* gClos = createGraph(bucketsNumber, bucketSize);

    Node* n1Clos = createNode(1, NULL);
    Node* n2Clos = createNode(2, NULL);
    Node* n3Clos = createNode(3, NULL);
    Node* n4Clos = createNode(4, NULL);
    Node* n5Clos = createNode(5, NULL);
    Node* n6Clos = createNode(6, NULL);
    Node* n7Clos = createNode(7, NULL);

    insertNode(n1Clos, gClos);
    insertNode(n2Clos, gClos);
    insertNode(n3Clos, gClos);
    insertNode(n4Clos, gClos);
    insertNode(n5Clos, gClos);
    insertNode(n6Clos, gClos);
    insertNode(n7Clos, gClos);

    /* Create edges and set properties */
    Edge* e1Clos = createEdge(1, 2, NULL);
    Edge* e2Clos = createEdge(1, 3, NULL);
    Edge* e3Clos = createEdge(2, 1, NULL);
    Edge* e4Clos = createEdge(2, 3, NULL);
    Edge* e5Clos = createEdge(3, 1, NULL);
    Edge* e6Clos = createEdge(3, 2, NULL);
    Edge* e7Clos = createEdge(3, 4, NULL);
    Edge* e8Clos = createEdge(4, 3, NULL);
    Edge* e9Clos = createEdge(4, 5, NULL);
    Edge* e10Clos = createEdge(5, 4, NULL);
    Edge* e11Clos = createEdge(5, 6, NULL);
    Edge* e12Clos = createEdge(5, 7, NULL);
    Edge* e13Clos = createEdge(6, 5, NULL);
    Edge* e14Clos = createEdge(6, 7, NULL);
    Edge* e15Clos = createEdge(7, 5, NULL);
    Edge* e16Clos = createEdge(7, 6, NULL);


     /* Insert edges in graph */
    insertEdge(1, e1Clos, gClos);
    insertEdge(1, e2Clos, gClos);
    insertEdge(2, e3Clos, gClos);
    insertEdge(2, e4Clos, gClos);
    insertEdge(3, e5Clos, gClos);
    insertEdge(3, e6Clos, gClos);
    insertEdge(3, e7Clos, gClos);
    insertEdge(4, e8Clos, gClos);
    insertEdge(4, e9Clos, gClos);
    insertEdge(5, e10Clos, gClos);
    insertEdge(5, e11Clos, gClos);
    insertEdge(5, e12Clos, gClos);
    insertEdge(6, e13Clos, gClos);
    insertEdge(6, e14Clos, gClos);
    insertEdge(7, e15Clos, gClos);
    insertEdge(7, e16Clos, gClos);


    double closCentrty1 = closenessCentrality(n1Clos, gClos);
    CHECKDOUBLE("Small Graph closeness centrality node:1 ", closCentrty1, 3.33 / 6.0);

    double closCentrty2 = closenessCentrality(n2Clos, gClos);
    CHECKDOUBLE("Small Graph closeness centrality node:2 ", closCentrty2, 3.33 / 6.0);

    double closCentrty3 = closenessCentrality(n3Clos, gClos);
    CHECKDOUBLE("Small Graph closeness centrality node:3 ", closCentrty3, 4.16 / 6.0);

    double closCentrty4 = closenessCentrality(n4Clos, gClos);
    CHECKDOUBLE("Small Graph closeness centrality node:4 ", closCentrty4, 4.0 / 6.0);

    double closCentrty5 = closenessCentrality(n5Clos, gClos);
    CHECKDOUBLE("Small Graph closeness centrality node:5 ", closCentrty5, 4.16 / 6.0);

    double closCentrty6 = closenessCentrality(n6Clos, gClos);
    CHECKDOUBLE("Small Graph closeness centrality node:6 ", closCentrty6, 3.33 / 6.0);

    double closCentrty7 = closenessCentrality(n7Clos, gClos);
    CHECKDOUBLE("Small Graph closeness centrality node:7 ", closCentrty7, 3.33 / 6.0);

}
Example #14
0
	//--------------------------------------------------------------------
	// actual algorithm call
	//--------------------------------------------------------------------
	Module::ReturnType FixEdgeInserterCore::call(
		const Array<edge> &origEdges,
		bool keepEmbedding,
		RemoveReinsertType rrPost,
		double percentMostCrossed)
	{
		double T;
		usedTime(T);

		Module::ReturnType retValue = Module::retFeasible;
		m_runsPostprocessing = 0;

		if(!keepEmbedding) m_pr.embed();
		OGDF_ASSERT(m_pr.representsCombEmbedding() == true);

		if (origEdges.size() == 0)
			return Module::retOptimal;  // nothing to do

		// initialization
		CombinatorialEmbedding E(m_pr);  // embedding of PG

		init(E);
		constructDual(E);

		// m_delFaces and m_newFaces are used by removeEdge()
		// if we can't allocate memory for them, we throw an exception
		if (rrPost != rrNone) {
			m_delFaces = new FaceSetSimple(E);
			if (m_delFaces == nullptr)
				OGDF_THROW(InsufficientMemoryException);

			m_newFaces = new FaceSetPure(E);
			if (m_newFaces == nullptr) {
				delete m_delFaces;
				OGDF_THROW(InsufficientMemoryException);
			}

		// no postprocessing -> no removeEdge()
		} else {
			m_delFaces = nullptr;
			m_newFaces = nullptr;
		}

		SListPure<edge> currentOrigEdges;
		if(rrPost == rrIncremental) {
			for(edge e : m_pr.edges)
				currentOrigEdges.pushBack(m_pr.original(e));
		}

		// insertion of edges
		bool doIncrementalPostprocessing =
			( rrPost == rrIncremental || rrPost == rrIncInserted );
		for(int i = origEdges.low(); i <= origEdges.high(); ++i)
		{
			edge eOrig = origEdges[i];
			storeTypeOfCurrentEdge(eOrig);
			//int eSubGraph = 0;  // edgeSubGraphs-data of eOrig
			//if(edgeSubGraphs!=0) eSubGraph = (*edgeSubGraphs)[eOrig];

			SList<adjEntry> crossed;
			if(m_pCost != nullptr) {
				findWeightedShortestPath(E, eOrig, crossed);
			} else {
				findShortestPath(E, eOrig, crossed);
			}

			insertEdge(E, eOrig, crossed);

			if(doIncrementalPostprocessing) {
				currentOrigEdges.pushBack(eOrig);

				bool improved;
				do {
					++m_runsPostprocessing;
					improved = false;

					for (edge eOrigRR : currentOrigEdges)
					{
						int pathLength = (m_pCost != nullptr) ? costCrossed(eOrigRR) : (m_pr.chain(eOrigRR).size() - 1);
						if (pathLength == 0) continue; // cannot improve

						removeEdge(E, eOrigRR);

						storeTypeOfCurrentEdge(eOrigRR);

						// try to find a better insertion path
						SList<adjEntry> crossed;
						if(m_pCost != nullptr) {
							findWeightedShortestPath(E, eOrigRR, crossed);
						} else {
							findShortestPath(E, eOrigRR, crossed);
						}

						// re-insert edge (insertion path cannot be longer)
						insertEdge(E, eOrigRR, crossed);

						int newPathLength = (m_pCost != nullptr) ? costCrossed(eOrigRR) : (m_pr.chain(eOrigRR).size() - 1);
						OGDF_ASSERT(newPathLength <= pathLength);

						if(newPathLength < pathLength)
							improved = true;
					}
				} while (improved);
			}
		}

		if(!doIncrementalPostprocessing) {
			// postprocessing (remove-reinsert heuristc)
			const int m = m_pr.original().numberOfEdges();
			SListPure<edge> rrEdges;

			switch(rrPost)
			{
			case rrAll:
			case rrMostCrossed:
				for(int i = m_pr.startEdge(); i < m_pr.stopEdge(); ++i)
					rrEdges.pushBack(m_pr.e(i));
				break;

			case rrInserted:
				for(int i = origEdges.low(); i <= origEdges.high(); ++i)
					rrEdges.pushBack(origEdges[i]);
				break;

			case rrNone:
			case rrIncremental:
			case rrIncInserted:
				break;
			}

			// marks the end of the interval of rrEdges over which we iterate
			// initially set to invalid iterator which means all edges
			SListConstIterator<edge> itStop;

			bool improved;
			do {
				// abort postprocessing if time limit reached
				if (m_timeLimit >= 0 && m_timeLimit <= usedTime(T)) {
					retValue = Module::retTimeoutFeasible;
					break;
				}

				++m_runsPostprocessing;
				improved = false;

				if(rrPost == rrMostCrossed)
				{
					FEICrossingsBucket bucket(&m_pr);
					rrEdges.bucketSort(bucket);

					const int num = int(0.01 * percentMostCrossed * m);
					itStop = rrEdges.get(num);
				}

				SListConstIterator<edge> it;
				for(it = rrEdges.begin(); it != itStop; ++it)
				{
					edge eOrig = *it;

					int pathLength = (m_pCost != nullptr) ? costCrossed(eOrig) : (m_pr.chain(eOrig).size() - 1);
					if (pathLength == 0) continue; // cannot improve

					removeEdge(E, eOrig);

					storeTypeOfCurrentEdge(eOrig);

					// try to find a better insertion path
					SList<adjEntry> crossed;
					if(m_pCost != nullptr) {
						findWeightedShortestPath(E, eOrig, crossed);
					} else {
						findShortestPath(E, eOrig, crossed);
					}

					// re-insert edge (insertion path cannot be longer)
					insertEdge(E, eOrig, crossed);

					// we cannot find a shortest path that is longer than before!
					int newPathLength = (m_pCost != nullptr) ? costCrossed(eOrig) : (m_pr.chain(eOrig).size() - 1);
					OGDF_ASSERT(newPathLength <= pathLength);

					if(newPathLength < pathLength)
						improved = true;
				}
			} while (improved);
		}

		// verify computed planarization
		OGDF_ASSERT(m_pr.representsCombEmbedding());

		// free resources
		cleanup();

		return retValue;
	}