1389 lines
33 KiB
C++
1389 lines
33 KiB
C++
/*
|
|
----
|
|
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 <vector>
|
|
|
|
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<Vertex>* otherVertices= other->GetVertices();
|
|
vector<Edge>* otherEdges=other->GetEdges();
|
|
for (int i=0; i<this->GetNumVertices()&&res;i++)
|
|
{
|
|
if(!(this->HasVertex(otherVertices->at(i).GetKey())))
|
|
{
|
|
res=false;
|
|
}
|
|
}
|
|
for (int i=0; i<this->GetNumEdges()&&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<Vertex>* v = g.GetVertices(true);
|
|
|
|
// vector returned?
|
|
if (v!=0) {
|
|
|
|
// add all vertices
|
|
for (unsigned int i=0;i<v->size();i++)
|
|
Add((*v)[i]);
|
|
|
|
delete v;
|
|
}
|
|
|
|
vector<Edge>* e = g.GetEdges(true);
|
|
|
|
// vector returned?
|
|
if (e!=0) {
|
|
|
|
// add all edges
|
|
for (unsigned int i=0;i<e->size();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<verticesStruct>::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<verticesStruct> node;
|
|
|
|
// sourceKey not found?
|
|
if (AVLTree<verticesStruct>::ReadNode(vertices,node,
|
|
sourceKey,verticesRoot)<0)
|
|
return false;
|
|
|
|
return AVLTree<adjStruct>::HasKey(adjlist,targetKey,node.elem.succ);
|
|
}
|
|
|
|
|
|
bool Graph::HasVertex(const int key) const {
|
|
|
|
assert(IsDefined());
|
|
|
|
return AVLTree<verticesStruct>::HasKey(vertices,key,verticesRoot);
|
|
}
|
|
|
|
|
|
vector<Vertex>* Graph::GetSuccFrom(const int key) const {
|
|
|
|
assert(IsDefined());
|
|
|
|
AVLNode<verticesStruct> n;
|
|
|
|
// key does not exist?
|
|
if (AVLTree<verticesStruct>::ReadNode(vertices,n,key,verticesRoot)<0)
|
|
return 0;
|
|
|
|
vector<AVLNode<adjStruct> > a(0);
|
|
AVLTree<adjStruct>::ReadNodes(adjlist,a,n.elem.succ);
|
|
|
|
vector<Vertex>* result = new vector<Vertex>(0);
|
|
AVLNode<verticesStruct> node;
|
|
|
|
// create vertices from keys
|
|
for (unsigned int i=0; i<a.size();i++) {
|
|
vertices.Get(a[i].elem.keyInt,node);
|
|
result->push_back(Vertex(node.key,node.elem.pos));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
vector<int>* Graph::GetSuccKeysFrom(const int key) const {
|
|
|
|
assert(IsDefined());
|
|
|
|
AVLNode<verticesStruct> node;
|
|
|
|
// key does not exist?
|
|
if (AVLTree<verticesStruct>::ReadNode(vertices,node,key,verticesRoot)<0)
|
|
return 0;
|
|
|
|
vector<int>* result = new vector<int>(0);
|
|
AVLTree<adjStruct>::ReadKeys(adjlist,result,node.elem.succ);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
vector<Edge>* Graph::GetSuccEdgesFrom(const int key) const {
|
|
|
|
assert(IsDefined());
|
|
|
|
AVLNode<verticesStruct> n;
|
|
|
|
// key does not exist?
|
|
if (AVLTree<verticesStruct>::ReadNode(vertices,n,key,verticesRoot)<0)
|
|
return 0;
|
|
|
|
vector<AVLNode<adjStruct> > a(0);
|
|
AVLTree<adjStruct>::ReadNodes(adjlist,a,n.elem.succ);
|
|
|
|
vector<Edge>* result = new vector<Edge>(0);
|
|
|
|
// create edges to successors
|
|
for (unsigned int i=0; i<a.size();i++)
|
|
result->push_back(Edge(key,a[i].key,a[i].elem.cost));
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
vector<Edge>* Graph::GetPredEdgesFrom(const int key) const {
|
|
|
|
assert(IsDefined());
|
|
|
|
// key does not exist?
|
|
if (!AVLTree<verticesStruct>::HasKey(vertices,key,verticesRoot))
|
|
return 0;
|
|
|
|
vector<Edge>* result = new vector<Edge>(0);
|
|
AVLNode<adjStruct> node;
|
|
vector<AVLNode<verticesStruct> > v(0);
|
|
AVLTree<verticesStruct>::ReadNodes(vertices,v,verticesRoot);
|
|
|
|
for (unsigned int i=0;i<v.size();i++)
|
|
|
|
// edge with key as target?
|
|
if (AVLTree<adjStruct>::ReadNode(adjlist,node,key,v[i].elem.succ)>=0)
|
|
result->push_back(Edge(v[i].key,node.key,node.elem.cost));
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
vector<Vertex>* Graph::GetPredFrom(const int key) const {
|
|
|
|
assert(IsDefined());
|
|
|
|
// key does not exist?
|
|
if (!AVLTree<verticesStruct>::HasKey(vertices,key,verticesRoot))
|
|
return 0;
|
|
|
|
vector<Vertex>* result = new vector<Vertex>(0);
|
|
vector<AVLNode<verticesStruct> > v(0);
|
|
AVLTree<verticesStruct>::ReadNodes(vertices,v,verticesRoot);
|
|
|
|
for (unsigned int i=0;i<v.size();i++)
|
|
|
|
// edge with key as target?
|
|
if (AVLTree<adjStruct>::HasKey(adjlist,key,v[i].elem.succ))
|
|
result->push_back(Vertex(v[i].key,v[i].elem.pos));
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
vector<int>* Graph::GetPredKeysFrom(const int key) const {
|
|
|
|
assert(IsDefined());
|
|
|
|
// key does not exist?
|
|
if (!AVLTree<verticesStruct>::HasKey(vertices,key,verticesRoot))
|
|
return 0;
|
|
|
|
vector<int>* result = new vector<int>(0);
|
|
vector<AVLNode<verticesStruct> > v(0);
|
|
AVLTree<verticesStruct>::ReadNodes(vertices,v,verticesRoot);
|
|
|
|
for (unsigned int i=0;i<v.size();i++)
|
|
|
|
// edge with key as target?
|
|
if (AVLTree<adjStruct>::HasKey(adjlist,key,v[i].elem.succ))
|
|
result->push_back(v[i].key);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
bool Graph::DeleteVertex (const int key) {
|
|
|
|
assert(IsDefined());
|
|
|
|
AVLNode<verticesStruct> node;
|
|
|
|
// key does not exist?
|
|
if (AVLTree<verticesStruct>::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<int>* v = GetPredKeysFrom(key);
|
|
|
|
for (unsigned int i=0;i<v->size();i++)
|
|
DeleteEdge((*v)[i],key);
|
|
|
|
delete v;
|
|
|
|
// delete all outgoing edges
|
|
v = GetSuccKeysFrom(key);
|
|
|
|
for (unsigned int i=0;i<v->size();i++)
|
|
DeleteEdge(key,(*v)[i]);
|
|
|
|
delete v;
|
|
|
|
}
|
|
|
|
int newRoot = AVLTree<verticesStruct>::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<Vertex>* Graph::GetVertices(const bool opt) const {
|
|
|
|
assert(IsDefined());
|
|
|
|
vector<Vertex>* v = new vector<Vertex>(0);
|
|
vector<AVLNode<verticesStruct> > n(0);
|
|
|
|
// return vertices in optimized order?
|
|
if (opt)
|
|
AVLTree<verticesStruct>::ReadOptNodes(vertices,n,verticesRoot);
|
|
else
|
|
AVLTree<verticesStruct>::ReadNodes(vertices,n,verticesRoot);
|
|
|
|
for (unsigned int i=0; i<n.size(); i++)
|
|
v->push_back(Vertex(n[i].key,n[i].elem.pos));
|
|
|
|
|
|
return v;
|
|
}
|
|
|
|
|
|
vector<Edge>* Graph::GetEdges(const bool opt) const {
|
|
|
|
assert(IsDefined());
|
|
|
|
vector<Edge>* v = new vector<Edge>(0);
|
|
vector<AVLNode<verticesStruct> > n(0);
|
|
vector<AVLNode<adjStruct> > adj(0);
|
|
|
|
AVLTree<verticesStruct>::ReadNodes(vertices,n,verticesRoot);
|
|
|
|
for (unsigned int i=0; i<n.size(); i++) {
|
|
|
|
// succ tree not empty?
|
|
if (n[i].elem.succ != -1) {
|
|
|
|
adj.clear();
|
|
|
|
// return edges in optimized order?
|
|
if (opt)
|
|
AVLTree<adjStruct>::ReadOptNodes(adjlist,adj,n[i].elem.succ);
|
|
else
|
|
AVLTree<adjStruct>::ReadNodes(adjlist,adj,n[i].elem.succ);
|
|
|
|
for (unsigned int j=0; j<adj.size(); j++)
|
|
v->push_back(Edge(n[i].key,adj[j].key,adj[j].elem.cost));
|
|
}
|
|
}
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
int Graph::GetInDegFrom(const int key) const {
|
|
|
|
assert(IsDefined());
|
|
|
|
AVLNode<verticesStruct> node;
|
|
|
|
// key not found?
|
|
if (AVLTree<verticesStruct>::ReadNode(vertices,node,key,verticesRoot)<0)
|
|
return -1;
|
|
|
|
return node.elem.inDeg;
|
|
}
|
|
|
|
|
|
int Graph::GetOutDegFrom(const int key) const {
|
|
|
|
assert(IsDefined());
|
|
|
|
AVLNode<verticesStruct> node;
|
|
|
|
// key not found?
|
|
if (AVLTree<verticesStruct>::ReadNode(vertices,node,key,verticesRoot)<0)
|
|
return -1;
|
|
|
|
return node.elem.outDeg;
|
|
}
|
|
|
|
|
|
int Graph::GetMaxDeg(const bool out) const {
|
|
|
|
assert(IsDefined());
|
|
|
|
vector<AVLNode<verticesStruct> > nodes;
|
|
int n = AVLTree<verticesStruct>::ReadNodes(vertices,nodes,verticesRoot);
|
|
int maxOut = 0;
|
|
int maxIn = 0;
|
|
|
|
for (int i=0;i<n;i++) {
|
|
maxOut = max(maxOut,nodes[i].elem.outDeg);
|
|
maxIn = max(maxIn,nodes[i].elem.inDeg);
|
|
}
|
|
|
|
return (out ? maxOut : maxIn);
|
|
}
|
|
|
|
|
|
int Graph::GetMinDeg(const bool out) const {
|
|
|
|
assert(IsDefined());
|
|
|
|
vector<AVLNode<verticesStruct> > nodes;
|
|
int n = AVLTree<verticesStruct>::ReadNodes(vertices,nodes,verticesRoot);
|
|
int minOut = n;
|
|
int minIn = n;
|
|
|
|
for (int i=0;i<n;i++) {
|
|
minOut = min(minOut,nodes[i].elem.outDeg);
|
|
minIn = min(minIn,nodes[i].elem.inDeg);
|
|
}
|
|
|
|
return (out ? minOut : minIn);
|
|
}
|
|
|
|
|
|
bool Graph::SetCost(const int sourceKey,
|
|
const int targetKey,
|
|
const float cost) {
|
|
|
|
assert(IsDefined());
|
|
|
|
AVLNode<verticesStruct> n;
|
|
|
|
// sourceKey not found?
|
|
if (AVLTree<verticesStruct>::ReadNode(vertices,n,sourceKey,verticesRoot)<0)
|
|
return false;
|
|
|
|
AVLNode<adjStruct> a;
|
|
|
|
int index = AVLTree<adjStruct>::ReadNode(adjlist,a,targetKey,n.elem.succ);
|
|
|
|
// targetKey not found?
|
|
if (index < 0)
|
|
return false;
|
|
|
|
a.elem.cost = cost;
|
|
AVLTree<adjStruct>::UpdateNode(adjlist,index,a.elem);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Graph::SetPos(const int key, const Point& pos) {
|
|
|
|
assert(IsDefined());
|
|
|
|
AVLNode<verticesStruct> node;
|
|
|
|
int index = AVLTree<verticesStruct>::ReadNode(vertices,node,
|
|
key,verticesRoot);
|
|
|
|
// key not found?
|
|
if (index<0)
|
|
return false;
|
|
|
|
node.elem.pos = pos;
|
|
AVLTree<verticesStruct>::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<verticesStruct> v;
|
|
|
|
// key not found?
|
|
if (AVLTree<verticesStruct>::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<verticesStruct> v;
|
|
|
|
// sourceKey not found?
|
|
if (AVLTree<verticesStruct>::ReadNode(vertices,v,sourceKey,verticesRoot)<0)
|
|
return Edge(false);
|
|
|
|
AVLNode<adjStruct> e;
|
|
|
|
// targetKey not found?
|
|
if (AVLTree<adjStruct>::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<verticesStruct> source;
|
|
int srcIndex = AVLTree<verticesStruct>::ReadNode(vertices,source,
|
|
sourceKey,verticesRoot);
|
|
|
|
// source key unknown?
|
|
if (srcIndex < 0)
|
|
return false;
|
|
|
|
AVLNode<verticesStruct> target;
|
|
int tgtIndex = AVLTree<verticesStruct>::ReadNode(vertices,target,
|
|
targetKey,verticesRoot);
|
|
|
|
// target key unknown?
|
|
if (tgtIndex < 0)
|
|
return false;
|
|
|
|
adjStruct a;
|
|
a.keyInt = tgtIndex;
|
|
a.cost = cost;
|
|
|
|
int newRoot = AVLTree<adjStruct>::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<verticesStruct>::UpdateNode(vertices,srcIndex,source.elem);
|
|
|
|
// edge is no loop?
|
|
if (sourceKey != targetKey) {
|
|
target.elem.inDeg++;
|
|
AVLTree<verticesStruct>::UpdateNode(vertices,tgtIndex,target.elem);
|
|
}
|
|
|
|
numEdges++;
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Graph::DeleteEdge (const int sourceKey, const int targetKey ) {
|
|
|
|
assert(IsDefined());
|
|
|
|
AVLNode<verticesStruct> source;
|
|
int srcIndex = AVLTree<verticesStruct>::ReadNode(vertices,source,
|
|
sourceKey,verticesRoot);
|
|
|
|
// source key unknown?
|
|
if (srcIndex < 0)
|
|
return false;
|
|
|
|
AVLNode<verticesStruct> target;
|
|
int tgtIndex = AVLTree<verticesStruct>::ReadNode(vertices,target,
|
|
targetKey,verticesRoot);
|
|
|
|
// target key unknown?
|
|
if (tgtIndex < 0)
|
|
return false;
|
|
|
|
int newRoot = AVLTree<adjStruct>::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<verticesStruct>::UpdateNode(vertices,srcIndex,source.elem);
|
|
|
|
// edge is no loop?
|
|
if (sourceKey != targetKey) {
|
|
target.elem.inDeg--;
|
|
AVLTree<verticesStruct>::UpdateNode(vertices,tgtIndex,target.elem);
|
|
}
|
|
|
|
numEdges--;
|
|
return true;
|
|
}
|
|
|
|
|
|
Graph* Graph::GetMappedGraph(vector<int>& map) const {
|
|
|
|
assert(IsDefined());
|
|
|
|
Graph* g = new Graph(true);
|
|
|
|
// copy vertices
|
|
AVLNode<verticesStruct> n;
|
|
int i;
|
|
|
|
for (i=0;i<vertices.Size();i++) {
|
|
|
|
vertices.Get(i,n);
|
|
g->vertices.Append(n);
|
|
}
|
|
g->verticesRoot = verticesRoot;
|
|
g->numVertices = numVertices;
|
|
g->numEdges = numEdges;
|
|
|
|
// map vertex keys to 0,..,n-1
|
|
int num = 0;
|
|
AVLTree<verticesStruct>::MapKeys(g->vertices,num,map,verticesRoot);
|
|
|
|
// map target keys to new keys
|
|
AVLNode<adjStruct> e;
|
|
|
|
for (i=0;i<adjlist.Size();i++) {
|
|
|
|
adjlist.Get(i,e);
|
|
g->vertices.Get(e.elem.keyInt,n);
|
|
AVLNode<adjStruct> a = AVLTree<adjStruct>::NewNode(&e);
|
|
a.key = n.key;
|
|
g->adjlist.Append(a);
|
|
}
|
|
|
|
return g;
|
|
}
|
|
|
|
|
|
struct circleEnv {
|
|
float maxDist;
|
|
int startKey;
|
|
Graph* graph;
|
|
vector<Vertex>* vertices;
|
|
vector<float> distance;
|
|
vector<int> 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<Edge>* succ = env.graph->GetSuccEdgesFrom(key);
|
|
|
|
// examine all outgoing edges of the vertex
|
|
for (unsigned int i=0;i<succ->size();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;i<env.graph->GetNumVertices();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<tarjanStruct> tVertices;
|
|
stack<int> tStack;
|
|
vector<int> map;
|
|
vector<Graph*> 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<int>* succ = env.graph->GetSuccKeysFrom(index);
|
|
|
|
// check all successors
|
|
for (unsigned int i=0;i<succ->size();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*> 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<Vertex>* vt = GetVertices();
|
|
|
|
for (unsigned int i=0;i<vt->size();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<env.tVertices.size();i++)
|
|
|
|
// vertex part of new connected component?
|
|
if (!env.tVertices[i].visited) {
|
|
|
|
Tarjan(i,env);
|
|
}
|
|
|
|
// add edges to the SCCs
|
|
|
|
vector<Edge>* ve = env.graph->GetEdges();
|
|
|
|
int src,tgt;
|
|
|
|
for (unsigned int i=0;i<ve->size();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<Edge>* 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<pathStruct> wayPoint;
|
|
vector<Edge>* graphEdges = GetEdges();
|
|
vector<Vertex>* 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<Vertex>* bigVertex = GetVertices();
|
|
vector<Vertex>* 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<Edge>* bigEdges = GetEdges();
|
|
vector<Edge>* 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();
|
|
}
|
|
|
|
|