/* ---- This file is part of SECONDO. Copyright (C) 2004, University in Hagen, Department of Computer Science, Database Systems for New Applications. SECONDO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SECONDO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with SECONDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---- //paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}] //[TOC] [\tableofcontents] [1] Implementation of Graph February 2007, G. Barz, M. Stein, A. Ruloffs, A. Martin [TOC] 1 Overview This file contains the implementation of the class ~Graph~ and all necesarry functions and classes for the registration of the ~graph~ type constructor. 2 Defines and includes */ #include "PlaceNodesHelper.h" #include "GraphAlgebra.h" #include "binTree.h" #include "minTree.h" #include using namespace std; /* 3 Implementation of the ~Graph~ class Read GraphAlgebra.h for more informations about the member functions. */ Graph::Graph() { } Graph::Graph(const bool Defined) : Attribute(Defined),vertices(0), adjlist(0){ if(IsDefined()){ Clear(); } } Graph::Graph(const Graph& g) : Attribute(g.IsDefined()),vertices(0), adjlist(0) { CopyFrom(&g); } Graph::~Graph() { } void Graph::Clear() { vertices.clean(); adjlist.clean(); verticesRoot = -1; numVertices = 0; numEdges = 0; } bool Graph::EqualsWith(const Graph* other) const { assert(IsDefined() && other->IsDefined()); if(this->GetNumEdges()!=other->GetNumEdges()) return false; if(this->GetNumVertices()!=other->GetNumVertices()) return false; bool res=true; vector* otherVertices= other->GetVertices(); vector* otherEdges=other->GetEdges(); for (int i=0; iGetNumVertices()&&res;i++) { if(!(this->HasVertex(otherVertices->at(i).GetKey()))) { res=false; } } for (int i=0; iGetNumEdges()&&res;i++) { if(!(this->HasEdge(otherEdges->at(i).GetSource(), otherEdges->at(i).GetTarget()))) { res=false; } else { Edge e =this->GetEdge(otherEdges->at(i).GetSource(), otherEdges->at(i).GetTarget()); if(e.GetCost()!=otherEdges->at(i).GetCost()) { res=false; } } } delete otherVertices; delete otherEdges; return res; } int Graph::GetNumVertices() const { assert(IsDefined()); return numVertices; } int Graph::GetNumEdges() const { assert(IsDefined()); return numEdges; } bool Graph::IsEmpty() const { assert(IsDefined()); return (numVertices == 0); } void Graph::Add(const Graph& g) { assert(IsDefined() && g.IsDefined()); vector* v = g.GetVertices(true); // vector returned? if (v!=0) { // add all vertices for (unsigned int i=0;isize();i++) Add((*v)[i]); delete v; } vector* e = g.GetEdges(true); // vector returned? if (e!=0) { // add all edges for (unsigned int i=0;isize();i++) Add((*e)[i]); delete e; } } bool Graph::AddVertex (const int key, const Point &pos) { assert(IsDefined()); // key already exists? if (HasVertex(key)) return false; verticesStruct v; v.pos = pos; v.succ = -1; v.inDeg = 0; v.outDeg = 0; int newRoot=AVLTree::InsertKey(vertices, key,v,verticesRoot); // could not insert key? if (newRoot == -1) return false; verticesRoot = newRoot; numVertices++; return true; } bool Graph::Add(const Vertex& v) { return AddVertex(v.GetKey(),v.GetPos()); } bool Graph::Add(const Edge& e) { return AddEdge(e.GetSource(),e.GetTarget(),e.GetCost()); } bool Graph::HasEdge(const int sourceKey, const int targetKey) const { assert(IsDefined()); AVLNode node; // sourceKey not found? if (AVLTree::ReadNode(vertices,node, sourceKey,verticesRoot)<0) return false; return AVLTree::HasKey(adjlist,targetKey,node.elem.succ); } bool Graph::HasVertex(const int key) const { assert(IsDefined()); return AVLTree::HasKey(vertices,key,verticesRoot); } vector* Graph::GetSuccFrom(const int key) const { assert(IsDefined()); AVLNode n; // key does not exist? if (AVLTree::ReadNode(vertices,n,key,verticesRoot)<0) return 0; vector > a(0); AVLTree::ReadNodes(adjlist,a,n.elem.succ); vector* result = new vector(0); AVLNode node; // create vertices from keys for (unsigned int i=0; ipush_back(Vertex(node.key,node.elem.pos)); } return result; } vector* Graph::GetSuccKeysFrom(const int key) const { assert(IsDefined()); AVLNode node; // key does not exist? if (AVLTree::ReadNode(vertices,node,key,verticesRoot)<0) return 0; vector* result = new vector(0); AVLTree::ReadKeys(adjlist,result,node.elem.succ); return result; } vector* Graph::GetSuccEdgesFrom(const int key) const { assert(IsDefined()); AVLNode n; // key does not exist? if (AVLTree::ReadNode(vertices,n,key,verticesRoot)<0) return 0; vector > a(0); AVLTree::ReadNodes(adjlist,a,n.elem.succ); vector* result = new vector(0); // create edges to successors for (unsigned int i=0; ipush_back(Edge(key,a[i].key,a[i].elem.cost)); return result; } vector* Graph::GetPredEdgesFrom(const int key) const { assert(IsDefined()); // key does not exist? if (!AVLTree::HasKey(vertices,key,verticesRoot)) return 0; vector* result = new vector(0); AVLNode node; vector > v(0); AVLTree::ReadNodes(vertices,v,verticesRoot); for (unsigned int i=0;i::ReadNode(adjlist,node,key,v[i].elem.succ)>=0) result->push_back(Edge(v[i].key,node.key,node.elem.cost)); return result; } vector* Graph::GetPredFrom(const int key) const { assert(IsDefined()); // key does not exist? if (!AVLTree::HasKey(vertices,key,verticesRoot)) return 0; vector* result = new vector(0); vector > v(0); AVLTree::ReadNodes(vertices,v,verticesRoot); for (unsigned int i=0;i::HasKey(adjlist,key,v[i].elem.succ)) result->push_back(Vertex(v[i].key,v[i].elem.pos)); return result; } vector* Graph::GetPredKeysFrom(const int key) const { assert(IsDefined()); // key does not exist? if (!AVLTree::HasKey(vertices,key,verticesRoot)) return 0; vector* result = new vector(0); vector > v(0); AVLTree::ReadNodes(vertices,v,verticesRoot); for (unsigned int i=0;i::HasKey(adjlist,key,v[i].elem.succ)) result->push_back(v[i].key); return result; } bool Graph::DeleteVertex (const int key) { assert(IsDefined()); AVLNode node; // key does not exist? if (AVLTree::ReadNode(vertices,node,key,verticesRoot)<0) return false; // any edges to delete? if ((node.elem.inDeg > 0) || (node.elem.outDeg > 0)) { // delete all ingoing edges vector* v = GetPredKeysFrom(key); for (unsigned int i=0;isize();i++) DeleteEdge((*v)[i],key); delete v; // delete all outgoing edges v = GetSuccKeysFrom(key); for (unsigned int i=0;isize();i++) DeleteEdge(key,(*v)[i]); delete v; } int newRoot = AVLTree::DeleteKey(vertices, key,verticesRoot); // delete failed? if (newRoot < -1) return false; verticesRoot = newRoot; numVertices--; return true; } bool Graph::Delete(const Vertex& v) { return DeleteVertex(v.GetKey()); } bool Graph::Delete(const Edge& e) { return DeleteEdge(e.GetSource(),e.GetTarget()); } vector* Graph::GetVertices(const bool opt) const { assert(IsDefined()); vector* v = new vector(0); vector > n(0); // return vertices in optimized order? if (opt) AVLTree::ReadOptNodes(vertices,n,verticesRoot); else AVLTree::ReadNodes(vertices,n,verticesRoot); for (unsigned int i=0; ipush_back(Vertex(n[i].key,n[i].elem.pos)); return v; } vector* Graph::GetEdges(const bool opt) const { assert(IsDefined()); vector* v = new vector(0); vector > n(0); vector > adj(0); AVLTree::ReadNodes(vertices,n,verticesRoot); for (unsigned int i=0; i::ReadOptNodes(adjlist,adj,n[i].elem.succ); else AVLTree::ReadNodes(adjlist,adj,n[i].elem.succ); for (unsigned int j=0; jpush_back(Edge(n[i].key,adj[j].key,adj[j].elem.cost)); } } return v; } int Graph::GetInDegFrom(const int key) const { assert(IsDefined()); AVLNode node; // key not found? if (AVLTree::ReadNode(vertices,node,key,verticesRoot)<0) return -1; return node.elem.inDeg; } int Graph::GetOutDegFrom(const int key) const { assert(IsDefined()); AVLNode node; // key not found? if (AVLTree::ReadNode(vertices,node,key,verticesRoot)<0) return -1; return node.elem.outDeg; } int Graph::GetMaxDeg(const bool out) const { assert(IsDefined()); vector > nodes; int n = AVLTree::ReadNodes(vertices,nodes,verticesRoot); int maxOut = 0; int maxIn = 0; for (int i=0;i > nodes; int n = AVLTree::ReadNodes(vertices,nodes,verticesRoot); int minOut = n; int minIn = n; for (int i=0;i n; // sourceKey not found? if (AVLTree::ReadNode(vertices,n,sourceKey,verticesRoot)<0) return false; AVLNode a; int index = AVLTree::ReadNode(adjlist,a,targetKey,n.elem.succ); // targetKey not found? if (index < 0) return false; a.elem.cost = cost; AVLTree::UpdateNode(adjlist,index,a.elem); return true; } bool Graph::SetPos(const int key, const Point& pos) { assert(IsDefined()); AVLNode node; int index = AVLTree::ReadNode(vertices,node, key,verticesRoot); // key not found? if (index<0) return false; node.elem.pos = pos; AVLTree::UpdateNode(vertices,index,node.elem); return true; } bool Graph::Update(const Vertex& v) { return SetPos(v.GetKey(),v.GetPos()); } bool Graph::Update(const Edge& e) { return SetCost(e.GetSource(),e.GetTarget(),e.GetCost()); } Vertex Graph::GetVertex(const int key) const { assert(IsDefined()); AVLNode v; // key not found? if (AVLTree::ReadNode(vertices,v,key,verticesRoot)<0) return Vertex(false); return Vertex(v.key,v.elem.pos); } Edge Graph::GetEdge(const int sourceKey, const int targetKey) const { assert(IsDefined()); AVLNode v; // sourceKey not found? if (AVLTree::ReadNode(vertices,v,sourceKey,verticesRoot)<0) return Edge(false); AVLNode e; // targetKey not found? if (AVLTree::ReadNode(adjlist,e,targetKey,v.elem.succ)<0) return Edge(false); return Edge(v.key,e.key,e.elem.cost); } bool Graph::AddEdge (const int sourceKey, const int targetKey, const float cost) { assert(IsDefined()); AVLNode source; int srcIndex = AVLTree::ReadNode(vertices,source, sourceKey,verticesRoot); // source key unknown? if (srcIndex < 0) return false; AVLNode target; int tgtIndex = AVLTree::ReadNode(vertices,target, targetKey,verticesRoot); // target key unknown? if (tgtIndex < 0) return false; adjStruct a; a.keyInt = tgtIndex; a.cost = cost; int newRoot = AVLTree::InsertKey(adjlist,targetKey, a,source.elem.succ); // insert failed? if (newRoot < 0) return false; // update source and target vertex source.elem.outDeg++; source.elem.succ = newRoot; // edge is a loop? if (sourceKey == targetKey) source.elem.inDeg++; AVLTree::UpdateNode(vertices,srcIndex,source.elem); // edge is no loop? if (sourceKey != targetKey) { target.elem.inDeg++; AVLTree::UpdateNode(vertices,tgtIndex,target.elem); } numEdges++; return true; } bool Graph::DeleteEdge (const int sourceKey, const int targetKey ) { assert(IsDefined()); AVLNode source; int srcIndex = AVLTree::ReadNode(vertices,source, sourceKey,verticesRoot); // source key unknown? if (srcIndex < 0) return false; AVLNode target; int tgtIndex = AVLTree::ReadNode(vertices,target, targetKey,verticesRoot); // target key unknown? if (tgtIndex < 0) return false; int newRoot = AVLTree::DeleteKey(adjlist,targetKey, source.elem.succ); // delete failed? if (newRoot < -1) return false; // update source and target vertex source.elem.outDeg--; source.elem.succ = newRoot; // edge is a loop? if (sourceKey == targetKey) source.elem.inDeg--; AVLTree::UpdateNode(vertices,srcIndex,source.elem); // edge is no loop? if (sourceKey != targetKey) { target.elem.inDeg--; AVLTree::UpdateNode(vertices,tgtIndex,target.elem); } numEdges--; return true; } Graph* Graph::GetMappedGraph(vector& map) const { assert(IsDefined()); Graph* g = new Graph(true); // copy vertices AVLNode n; int i; for (i=0;ivertices.Append(n); } g->verticesRoot = verticesRoot; g->numVertices = numVertices; g->numEdges = numEdges; // map vertex keys to 0,..,n-1 int num = 0; AVLTree::MapKeys(g->vertices,num,map,verticesRoot); // map target keys to new keys AVLNode e; for (i=0;ivertices.Get(e.elem.keyInt,n); AVLNode a = AVLTree::NewNode(&e); a.key = n.key; g->adjlist.Append(a); } return g; } struct circleEnv { float maxDist; int startKey; Graph* graph; vector* vertices; vector distance; vector map; Graph* circle; }; void GraphCircle(circleEnv& env, const int key, const float dist) { env.circle->AddVertex(env.map[key],(*env.vertices)[key].GetPos()); env.distance[key] = dist; Path* p; vector* succ = env.graph->GetSuccEdgesFrom(key); // examine all outgoing edges of the vertex for (unsigned int i=0;isize();i++) { Edge& e = (*succ)[i]; float& targetDist = env.distance[e.GetTarget()]; // distance from start vertex to target vertex unknown? if (targetDist<0.0f) { p = env.graph->GetShortestPath(env.startKey,e.GetTarget()); assert(p->IsDefined()); targetDist = p->GetCost(); delete p; // vertex outside circle? if (targetDist > env.maxDist) continue; // add vertex to circle and continue in target GraphCircle(env,e.GetTarget(),targetDist); } // edge part of circle? if ((dist+e.GetCost()) <= env.maxDist) env.circle->AddEdge(env.map[e.GetSource()], env.map[e.GetTarget()],e.GetCost()); } delete succ; } Graph* Graph::GetCircle(const int startKey, const float maxDist) const { assert(IsDefined() && (maxDist >= 0.0f)); circleEnv env; env.maxDist = maxDist; env.distance.clear(); env.map.clear(); env.circle = new Graph(true); env.graph = GetMappedGraph(env.map); env.vertices = env.graph->GetVertices(); env.startKey = -1; // initialize distances and check if startKey exists for(int i=0;iGetNumVertices();i++) { env.distance.push_back(-1.0f); // startKey found? if (env.map[i] == startKey) env.startKey = i; } // startKey exists? if (env.startKey != -1) GraphCircle(env,env.startKey,0); delete env.graph; delete env.vertices; return env.circle; } struct tarjanStruct { Point pos; int dfs; int lowlink; int sccIndex; bool inStack; bool visited; }; struct tarjanEnv { int maxDfs; Graph* graph; vector tVertices; stack tStack; vector map; vector SCC; }; void Tarjan(const int index, tarjanEnv& env ) { tarjanStruct& v = env.tVertices[index]; v.dfs = env.maxDfs; v.lowlink = env.maxDfs; env.maxDfs++; env.tStack.push(index); v.inStack = true; v.visited = true; vector* succ = env.graph->GetSuccKeysFrom(index); // check all successors for (unsigned int i=0;isize();i++) { tarjanStruct& vs = env.tVertices[(*succ)[i]]; // successor is new vertex? if (!vs.visited) { Tarjan((*succ)[i],env); v.lowlink = min(v.lowlink, vs.lowlink); } // stack contains successor? else if (vs.inStack) v.lowlink = min(v.lowlink, vs.dfs); } delete succ; // current vertex is the root of a SCC? if (v.lowlink == v.dfs) { Graph* scc = new Graph(true); int i; // build SCC from all vertices on stack above the root vertex do { i = env.tStack.top(); env.tStack.pop(); env.tVertices[i].inStack = false; env.tVertices[i].sccIndex = env.SCC.size(); scc->AddVertex(env.map[i],env.tVertices[i].pos); } while (i != index); env.SCC.push_back(scc); } } vector Graph::GetStronglyConnectedComponents() const { assert(IsDefined()); tarjanEnv env; env.SCC.clear(); env.map.clear(); // work on the mapped version env.graph = GetMappedGraph(env.map); // add additional informations to the vertices env.tVertices.clear(); vector* vt = GetVertices(); for (unsigned int i=0;isize();i++) { tarjanStruct t; t.pos = (*vt)[i].GetPos(); t.visited = false; t.dfs = 0; t.sccIndex = 0; t.lowlink = 0; t.inStack = false; env.tVertices.push_back(t); } delete vt; // execute the Tarjan algorithm on all connected components env.maxDfs = 0; for (unsigned int i=0;i* ve = env.graph->GetEdges(); int src,tgt; for (unsigned int i=0;isize();i++) { src = (*ve)[i].GetSource(); tgt = (*ve)[i].GetTarget(); // source and target of current edge in the same SCC? if (env.tVertices[src].sccIndex == env.tVertices[tgt].sccIndex) env.SCC[env.tVertices[src].sccIndex]->AddEdge(env.map[src], env.map[tgt],(*ve)[i].GetCost()); } // free memory delete ve; delete env.graph; return env.SCC; } int FirstSourceEdge(vector* graphEdges, int count, int key) { if (count == 0) return 0; int pos = count / 2; int diff = pos; while (diff > 0) { if ((*graphEdges) [pos].GetSource() == key) break; if ((*graphEdges) [pos].GetSource() > key) pos -= diff; else pos += diff; if (pos < 0) pos = 0; if (pos >= count) pos = count - 1; diff = (diff==1) ? 0 : (diff + 1) / 2; } while( pos > 0 && (*graphEdges) [pos - 1].GetSource() == key) pos--; return pos; } Path* Graph::GetShortestPath(int start, int target) const{ Path* res = new Path(true); GetShortestPath(start, target, res); return res; } void Graph::GetShortestPath(int start, int target, Path* solution) const { BinTree parts; MinTree edges; vector wayPoint; vector* graphEdges = GetEdges(); vector* graphVertex = GetVertices(); solution->Clear(); bool found = false; float foundWeight = -1.0f; Edge iEdge; Edge hitTarget; // if start and targetvertex are equal, ... if (start == target) { for (int i = 0; i < GetNumVertices(); i++) // return path of length 0 if start is an edge of the graph if ((*graphVertex) [i].GetKey() == start) { solution->SetDefined(true); pathStruct loneSome; loneSome.key = start; loneSome.pos = (*graphVertex) [i].GetPos(); loneSome.cost = 0.0f; solution->Append(loneSome); delete graphEdges; delete graphVertex; return; } // if not in graph return an undefined path solution->SetDefined(false); delete graphEdges; delete graphVertex; return; } else { // search for all edges beginning at the start key for(int i = 0; i < GetNumEdges(); i++) { // EdgeSize of Graph !!! if ((*graphEdges) [i].GetSource() == start) { // found a connected edge // Of Graph !!! if ((*graphEdges) [i].GetTarget() == start) // reflective edge continue; iEdge = (*graphEdges) [i]; if ((parts.getCostOfEdge(iEdge.GetTarget()) == -1.0f) || // to-point first time reached ... (parts.getCostOfEdge(iEdge.GetTarget()) > iEdge.GetCost())) { // or with less weight edges.put((Edge)iEdge); parts.insertElem(iEdge); if (iEdge.GetTarget() == target) { found = true; foundWeight = iEdge.GetCost(); hitTarget = iEdge; } } } } bool searchOn = true; Edge actual(false); while(searchOn) { // After have searched from the start vertex, // search from the further vertices on the way actual = (Edge) edges.pull(); if (actual.IsDefined() == false) { // no more further edges to examine searchOn = false; break; } if (found && actual.GetCost() >= foundWeight) { // No Path may avaiable with lower weight searchOn = false; break; } if (parts.getCostOfEdge(actual.GetTarget()) != -1.0f) // if to-point not first time reached ... if (parts.getCostOfEdge(actual.GetTarget()) < actual.GetCost()) { // ... with less weight continue; // then try next edge } int start = FirstSourceEdge(graphEdges, GetNumEdges(), actual.GetTarget()); for(int i = start; i < GetNumEdges(); i++) { if ((*graphEdges) [i].GetSource() != actual.GetTarget()) break; if ((*graphEdges) [i].GetSource() == (*graphEdges) [i].GetTarget()) // reflective edge continue; if ((parts.getCostOfEdge((*graphEdges)[i].GetTarget()) ==-1.0f)|| // to-point first time reached ... (parts.getCostOfEdge((*graphEdges) [i].GetTarget()) > actual.GetCost() + (*graphEdges) [i].GetCost())) { // or with less weight iEdge = (*graphEdges) [i]; iEdge.SetCost(actual.GetCost() + iEdge.GetCost()); edges.put(iEdge); parts.insertElem(iEdge); if (iEdge.GetTarget() == target) { found = true; if (foundWeight < 0 || (foundWeight >= 0 && foundWeight > iEdge.GetCost())) { foundWeight = iEdge.GetCost(); hitTarget = iEdge; } } } } } } if (found) { // After examine the graph // gather backwards the path to the start vertex solution->SetDefined(true); pathStruct pstmp; pstmp.key = hitTarget.GetTarget(); pstmp.pos = (GetVertex(hitTarget.GetTarget())).GetPos(); pstmp.cost = hitTarget.GetCost(); wayPoint.push_back(pstmp); // Push target vertex on vector iEdge = hitTarget; float costHelper = iEdge.GetCost(); while (iEdge.GetSource() != start) { iEdge = (Edge) parts.getElemAT(iEdge.GetSource()); pstmp.key = iEdge.GetTarget(); pstmp.pos = (GetVertex(iEdge.GetTarget())).GetPos(); pstmp.cost = costHelper; costHelper = iEdge.GetCost(); pstmp.cost -= costHelper; wayPoint.push_back(pstmp); // Push vertex of the way on the vector } pstmp.key = iEdge.GetSource(); pstmp.pos = (GetVertex(iEdge.GetSource())).GetPos(); pstmp.cost = costHelper; wayPoint.push_back(pstmp); // Push start-vertex on the vector while(!wayPoint.empty()) { solution->Append(wayPoint.back()); wayPoint.pop_back(); } } else { solution->SetDefined(false); } delete graphEdges; delete graphVertex; }; bool Graph::PartOf(const Graph* part) const { int debugLevel = 0; if (debugLevel >= 1) cout << " BigVertices " << GetNumVertices() << " PartVertices " << part->GetNumVertices() << endl; if (GetNumVertices() < part->GetNumVertices()) return false; if (debugLevel >= 1) cout << " BigEdges " << GetNumEdges() << " PartEdges " << part->GetNumEdges() << endl; if (GetNumEdges() < part->GetNumEdges()) return false; vector* bigVertex = GetVertices(); vector* partVertex = part->GetVertices(); if (debugLevel >= 1) cout << " Line 1120" << endl; // O(nlogn) Implementation of vertices comparison bool found = true; for (int i = 0; i < part->GetNumVertices(); i++) { if (debugLevel >=2) cout << " i " << i << " SearchKey " << (*partVertex) [i].GetKey() << endl; found = false; int searchPos = GetNumVertices() / 2; int delta = searchPos; bool goon = true; bool goon2 = true; while (goon2) { if (!goon) goon2 = false; if (delta == 1) goon = false; if (debugLevel >=2) cout << " searchpos " << searchPos << " TestKey " << (*bigVertex) [searchPos].GetKey() << endl; if (searchPos >= 0 && searchPos < GetNumVertices()) if ((*partVertex) [i].GetKey() == (*bigVertex)[searchPos].GetKey()) { found = true; break; } delta = (delta + 1) / 2; if ((*partVertex) [i].GetKey() < (*bigVertex)[searchPos].GetKey()) searchPos -= delta; else searchPos += delta; } } delete bigVertex; delete partVertex; if (!found) return false; vector* bigEdges = GetEdges(); vector* partEdges = part->GetEdges(); if (debugLevel >= 1) cout << " Line 1137" << endl; // O(nlogn) Implementation of edges comparison found = true; for (int i = 0; i < part->GetNumEdges(); i++) { found = false; if (debugLevel >= 2) cout << " Search edge from " << (*partEdges)[i].GetSource() << " to " << (*partEdges) [i].GetTarget() << endl; int searchPos = GetNumEdges() / 2; int delta = searchPos; bool goon = true; bool goon2 = true; while (goon2) { if (!goon) goon2 = false; if (delta == 1) goon = false; if (debugLevel >=2) cout << " searchpos " << searchPos << " TestKey " << (*bigEdges) [searchPos].GetSource() << endl; if (searchPos >= 0 && searchPos < GetNumEdges()) if ((*partEdges) [i].GetSource() == (*bigEdges)[searchPos].GetSource() && (*partEdges) [i].GetTarget() == (*bigEdges)[searchPos].GetTarget() && (*partEdges) [i].GetCost() == (*bigEdges)[searchPos].GetCost() ) { found = true; break; } delta = (delta + 1) / 2; if ((*partEdges) [i].GetSource() < (*bigEdges)[searchPos].GetSource() || ((*partEdges) [i].GetSource() == (*bigEdges)[searchPos].GetSource() && (*partEdges) [i].GetTarget() < (*bigEdges)[searchPos].GetTarget()) || ((*partEdges) [i].GetSource() == (*bigEdges)[searchPos].GetSource() && (*partEdges) [i].GetTarget()== (*bigEdges)[searchPos].GetTarget() && (*partEdges) [i].GetCost() < (*bigEdges)[searchPos].GetCost()) ) searchPos -= delta; else searchPos += delta; } } delete bigEdges; delete partEdges; if (!found) return false; return true; } void Graph::Minimize() { assert(IsDefined()); // empty space in DBArrays? if ((vertices.Size() > numVertices) || (adjlist.Size() > numEdges)) { Graph g(*this); Clear(); Add(g); } } Graph* Graph::Clone() const { return new Graph(*this); } size_t Graph::Sizeof() const { return sizeof(Graph); } int Graph::Compare(const Attribute*) const { return 0; } bool Graph::Adjacent(const Attribute*) const { return 0; } size_t Graph::HashValue() const { return 0; } void Graph::CopyFrom(const Attribute* arg) { const Graph* g = (const Graph*)arg; vertices.copyFrom(g->vertices); adjlist.copyFrom(g->adjlist); SetDefined(g->IsDefined()); numVertices = g->numVertices; numEdges = g->numEdges; verticesRoot = g->verticesRoot; } int Graph::NumOfFLOBs() const { return 2; } Flob* Graph::GetFLOB(const int i) { assert( i >= 0 && i < NumOfFLOBs() ); if (i==1) return &adjlist; return &vertices; } void Graph::Destroy() { vertices.Destroy(); adjlist.Destroy(); }