Files
secondo/Algebras/MainMemory2/graph.h
2026-01-23 17:03:45 +08:00

862 lines
17 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2016,
University in Hagen,
Faculty of Mathematics and 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
----
*/
#ifndef GRAPH_H
#define GRAPH_H
#include <iostream>
#include <vector>
#include <set>
#include <limits>
#include <queue>
#include <stack>
#include <algorithm>
#include "Algebra.h"
#include "NestedList.h"
#include "QueryProcessor.h"
#include "Algebras/Relation-C++/RelationAlgebra.h"
#include "PointerWrapper.h"
namespace graph {
class Edge;
class Vertex;
class Graph;
/*
class Edge
This class represents an edge in a graph.
*/
class Edge {
public:
Edge(Tuple* _tuple, int _posSource, int _posDest,
double _cost, double _dist)
: tuple(_tuple),posSource(_posSource), posDest(_posDest),
cost(_cost), dist(_dist), noRefs(1) {
tuple->IncReference();
}
Edge(const Edge& e): tuple(e.tuple), posSource(e.posSource),
posDest(e.posDest), cost(e.cost),
dist(e.dist), noRefs(1){
tuple->IncReference();
}
Edge& operator=(const Edge& e){
this->tuple->DeleteIfAllowed();
this->tuple = e.tuple;
this->tuple->IncReference();
this->posSource = e.posSource;
this->posDest = e.posDest;
this->cost = e.cost;
this->dist = e.dist;
// noRefs remains unchanged
return *this;
}
~Edge() {
assert(noRefs == 0);
tuple->DeleteIfAllowed();
tuple = 0;
}
Tuple* getTuple() {
return tuple;
}
void IncReference(){
noRefs++;
}
void DeleteIfAllowed(){
assert(noRefs>0);
noRefs--;
if(noRefs==0){
delete this;
}
}
int getSource(){
return ((CcInt*) tuple->GetAttribute(posSource))->GetValue();
}
int getDest(){
return ((CcInt*) tuple->GetAttribute(posDest))->GetValue();
}
inline double getCost() const{
return cost;
}
inline double getDist() const{
return dist;
}
/*
~memSize~
Returns the memory size of this edge.
*/
size_t memSize() const {
size_t res = sizeof(*this);
return res;
}
Edge* clone(){
return new Edge(tuple->Clone(), posSource, posDest, cost, dist);
}
private:
Tuple* tuple;
int posSource;
int posDest;
double cost;
double dist;
size_t noRefs;
};
typedef PointerWrap<Edge> EdgeWrap;
/*
class Vertex
This class represents a vertex in a graph.
*/
class Vertex {
friend class Graph;
friend class Queue;
friend class Comp;
public:
/*
struct EqualVertex
This stuct is used to compare to vertices.
*/
struct EqualVertex {
/*
The operator() returns true if the node number of the first
vertex is smaller than the node number of the second vertex.
*/
bool operator()(const Vertex* v1, const Vertex* v2) const {
return v1->nr < v2->nr;
}
};
Vertex(int _nr):
nr(_nr), seen(false),
cost(std::numeric_limits<double>::max()),
dist(std::numeric_limits<double>::max()), prev(0),
index(0), lowlink(0), inStack(false), compNo(0) {
edges = new std::vector<EdgeWrap>();
}
~Vertex() {
delete edges;
}
std::size_t operator()(const Vertex &v) const {
return v.nr;
}
int getNr() {
return nr;
}
void setPrev(Vertex* v) {
prev = v;
}
void setCost(double i) {
cost = i;
}
void setDist(double i) {
dist = i;
}
double getCost() {
return cost;
}
double getDist() {
return dist;
}
void isSeen(bool b) {
seen = b;
}
bool wasSeen() {
return seen;
}
std::vector<EdgeWrap>* getEdges() {
return edges;
}
int getCompNo() {
return compNo;
}
/*
~getPath~
Adds all node numbers of the predecessors of this node to the
std::vector result.
*/
std::vector<int>* getPath(std::vector<int>* result) {
if(prev) {
prev->getPath(result);
}
result->push_back(nr);
return result;
}
/*
~print~
Prints this node including its adjacent nodes to the console.
*/
void print(std::ostream& out) const {
out << "vertex: " << nr << std::endl;
out << "adjacency list: ";
for(size_t i=0; i<edges->size(); i++) {
Edge* e = edges->at(i).getPointer();
out << "-> "
<< e->getDest()
<< ", " << e->getCost() << " "
<< ", " << e->getDist() << " ";
}
if(prev != 0)
out << std::endl << "prev: " << prev->nr;
out << std::endl << "seen: " << seen;
out << std::endl << "CompNo: " << compNo << std::endl << std::endl;
}
void printPath() {
if(prev) {
prev->printPath();
std::cout << " -> ";
}
std::cout << nr;
}
/*
~memSize~
Returns the memory size of this vertex.
*/
size_t memSize() const {
size_t res = sizeof(*this) + (sizeof(void*) * edges->size());
return res;
}
const std::vector<EdgeWrap>* getEdges() const{
return edges;
}
Vertex* clone(){
Vertex* res = new Vertex(nr);
res->seen = seen;
res->cost = cost;
res->dist = dist;
res->prev = 0; // only during dijkstra used
res->index = index;
res->lowlink = lowlink;
res->inStack = inStack;
res->compNo = compNo;
std::vector<EdgeWrap>* e = new std::vector<EdgeWrap>();
for(size_t i=0;i<edges->size();i++){
EdgeWrap w = edges->at(i);
Edge* ed = w()->clone();
e->push_back(EdgeWrap(ed));
}
res->edges = e;
return res;
}
private:
int nr;
bool seen;
double cost;
double dist;
Vertex* prev;
int index;
int lowlink;
bool inStack;
int compNo;
std::vector<EdgeWrap>* edges;
};
/*
class Comp
This class is used to compare entries in a priority queue ~Queue~.
*/
class Comp {
public:
bool operator() (const Vertex* lhs, const Vertex* rhs) const {
if(lhs->dist > rhs->dist) {
return true;
}
return false;
}
};
/*
class Queue
The class implements a priority queue in which the Vertex v with
the smallest ~dist~ value is at the front of the queue.
*/
class Queue {
public:
Queue() {
queue = new std::vector<Vertex*>();
std::make_heap(queue->begin(),queue->end(),Comp());
}
~Queue() {
clear();
delete queue;
}
/*
~clear~
Deletes all elements in the queue.
*/
void clear() {
queue->clear();
}
/*
~empty~
*/
bool empty() {
return queue->empty();
}
/*
~size~
Returns the size of this queue.
*/
size_t size() {
return queue->size();
}
/*
~top~
Returns the top element of this queue.
*/
Vertex* top() {
return queue->front();
}
/*
~push~
Adds a new element to the queue.
*/
void push(Vertex* entry) {
queue->push_back(entry);
std::push_heap(queue->begin(),queue->end(),Comp());
}
/*
~pop~
Removes the top element from the queue.
*/
void pop() {
std::pop_heap(queue->begin(),queue->end(),Comp());
queue->pop_back();
}
/*
~print~
Prints all elements of the queue to the console.
*/
void print(std::ostream& out) {
out << std::endl << "QUEUE:" << std::endl;
for(size_t i=0; i<queue->size(); i++) {
out << "NodeNumber: " << queue->at(i)->nr;
if(queue->at(i)->prev != 0)
out << " previous: " << queue->at(i)->prev->nr;
out << " Cost: " << queue->at(i)->cost;
out << " Distanz: " << queue->at(i)->dist << std::endl;
}
}
private:
std::vector<Vertex*>* queue;
};
/*
class Graph
This class represents a graph as adjacency lists.
*/
class Graph {
friend class Edge;
public:
Graph() {
graph = new std::set<Vertex*, Vertex::EqualVertex>();
result = new std::vector<int>();
}
~Graph() {
std::set<Vertex*,Vertex::EqualVertex>::iterator it = graph->begin();
while(it!=graph->end()) {
Vertex* v = *it;
delete v;
it++;
}
delete graph;
result->clear();
delete result;
}
/*
~reset~
*/
void reset() {
result->clear();
}
void clearScc() {
std::set<Vertex*,Vertex::EqualVertex>::iterator it = graph->begin();
while(it!=graph->end()) {
Vertex* v = *it;
v->index = 0;
v->lowlink = 0;
v->compNo = 0;
v->inStack = false;
v->seen = false;
it++;
}
}
/*
~isEmpty~
Returns true if this graph is empty.
*/
bool isEmpty() {
return graph->empty();
}
/*
~size~
Returns the number of nodes in this graph.
*/
int size() {
return graph->size();
}
/*
~getGraph~
*/
std::set<Vertex*,Vertex::EqualVertex>* getGraph() {
return graph;
}
/*
~getVertex~
If the nodenumber is already known in the graph, the node is returned,
otherwise a new node with that number is created and returned.
*/
Vertex* getVertex(int nr) {
Vertex* v = new Vertex(nr);
std::set<Vertex*,Vertex::EqualVertex>::iterator it;
it = graph->find(v);
if(it == graph->end()) {
graph->insert(v);
return v;
}
delete v;
return *it;
}
/*
~addEdge~
Adds a new edge to the graph.
*/
void addEdge(Tuple* edge, int posSource,
int posDest, double cost, double dist) {
Vertex* v = getVertex(((CcInt*)edge->
GetAttribute(posSource))->GetIntval());
getVertex(((CcInt*)edge->GetAttribute(posDest))->GetIntval());
Edge* e = new Edge(edge,posSource,posDest,cost,dist);
EdgeWrap ew(e);
v->edges->push_back(ew);
e->DeleteIfAllowed();
}
/*
~clear~
Deletes all nodes from this graph.
*/
void clear() {
std::set<Vertex*,Vertex::EqualVertex>::iterator it = graph->begin();
while(it!=graph->end()) {
Vertex* v = *it;
delete v;
it++;
}
}
/*
~getPath~
Recursively adds all predecessors of a given node to the std::vector result.
*/
void getPath(Vertex* dest) {
if(dest->cost==std::numeric_limits<double>::max())
std::cout << "Error, " << dest->nr << " not reachable\n";
else
dest->getPath(result);
}
/*
~getResult~
Returns a pointer to the std::vector result.
*/
std::vector<int>* getResult() {
return result;
}
void tarjan() {
int index = 0;
int compNo = 1;
std::stack<Vertex*>* stack = new std::stack<Vertex*>();
std::set<Vertex*,Vertex::EqualVertex>::iterator it = graph->begin();
while(it!=graph->end()) {
tarjan(*it,index,stack,compNo);
it++;
}
delete stack;
}
/*
~tarjan~
Calculates the scc for a given vertex.
*/
void tarjan(Vertex* v, int& index,
std::stack<Vertex*>* stack, int& compNo) {
if(v->wasSeen())
return;
v->index = index;
v->lowlink = index;
index++;
v->inStack = true;
v->seen = true;
stack->push(v);
Vertex* w;
// visit all adjacent nodes of v
for(size_t i=0; i<v->edges->size(); i++) {
w = getVertex(v->edges->at(i).getPointer()->getDest());
if(!w->seen) {
tarjan(w,index,stack,compNo); // recursive call
v->lowlink = std::min(v->lowlink,w->lowlink);
} else if(w->inStack) {
v->lowlink = std::min(v->lowlink,w->index);
}
}
// root of scc found
if (v->lowlink == v->index) {
v->compNo = compNo;
while(true) {
w = stack->top();
stack->pop();
w->inStack = false;
if(v->nr == w->nr)
break;
w->compNo = compNo;
}
compNo++;
}
}
/*
Iterative variant of tarjan.
*/
void tarjan2() {
int index = 0;
int compNo = 1;
std::stack<Vertex*> stack; // stack of tarjan
std::set<Vertex*,Vertex::EqualVertex>::iterator it;
for(it = graph->begin(); it!=graph->end();it++){
Vertex* v = *it;
if(!v->seen){
tarjan2(v,index,stack,compNo);
}
}
}
void tarjan2(Vertex* v, int& index,
std::stack<Vertex*>& stack, int& compNo){
typedef std::pair<Vertex*, size_t> stackentry;
std::stack<stackentry> rstack; // simulating recursion
rstack.push(stackentry(v,v->edges->size()));
for(size_t i=0;i<v->edges->size();i++){
stackentry e(v,v->edges->size()-(i+1));
rstack.push(e);
}
while(!rstack.empty()){
stackentry e = rstack.top();
rstack.pop();
v = e.first;
size_t pos = e.second;
if(!v->seen || pos>0){
if(pos==0){
v->index = index;
v->lowlink = index;
index++;
v->inStack = true;
v->seen = true;
stack.push(v);
} else {
}
if(pos<v->edges->size()){
Vertex* w = getVertex(v->edges->at(pos).getPointer()->getDest());
if(!w->seen){
rstack.push(stackentry(w,w->edges->size()));
for(size_t i=0;i<w->edges->size();i++){
stackentry e(w,w->edges->size()-(i+1));
rstack.push(e);
}
} else if(w->inStack){
v->lowlink = std::min(v->lowlink, w->index);
}
} else {
for(size_t i=0;i<v->edges->size();i++){
Vertex* w =getVertex(v->edges->at(i).getPointer()->getDest());
if(w->compNo<0){
v->lowlink = std::min(v->lowlink,w->lowlink);
}
}
if(v->lowlink == v->index){
assert(v->compNo < 0);
v->compNo = compNo;
while(true){
Vertex* w = stack.top();
stack.pop();
w->inStack=false;
if(v->nr == w->nr)
break;
assert(w->compNo < 0);
w->compNo = compNo;
}
compNo++;
}
}
} // vertex not seen before
} // while recursion stack not empty
}
/*
~getEdge~
Returns the tuple with start node ~source~ and end node ~dest~.
*/
Tuple* getEdge(int source, int dest) {
std::set<Vertex*,Vertex::EqualVertex>::iterator it;
Vertex* w = new Vertex(source);
it = graph->find(w);
Vertex* v = *it;
delete w;
for(size_t j=0; j<v->edges->size(); j++) {
Edge* e = v->edges->at(j).getPointer();
if(e->getDest() == dest) {
return e->getTuple();
}
}
return 0;
}
/*
~print~
Prints this graph to the console.
*/
void print(std::ostream& out) {
out << "------> GRAPH: " << std::endl;
out << "GRAPH size: " << this->memSize() << endl;
std::set<Vertex*,Vertex::EqualVertex>::iterator it = graph->begin();
while(it!=graph->end()) {
Vertex* v = *it;
v->print(out);
it++;
}
}
/*
~memSize~
Returns the memory size of this graph.
*/
size_t memSize() const {
size_t res = sizeof(*this) + (sizeof(void*) * graph->size());
return res;
}
void resetComp(){
std::set<Vertex*, Vertex::EqualVertex>::iterator it;
for(it=graph->begin();it!=graph->end();it++){
Vertex* v = *it;
v->seen=false;
v->index=-1;
v->lowlink=-1;
v->inStack=false;
v->compNo = -1;
}
}
Graph* clone(){
Graph* res = new Graph();
std::set<Vertex*, Vertex::EqualVertex>::iterator it;
for(it = graph->begin(); it!=graph->end();it++){
res->graph->insert( (*it)->clone());
}
for(size_t i=0;i<result->size();i++){
res->result->push_back(result->at(i));
}
return res;
}
private:
std::set<Vertex*, Vertex::EqualVertex>* graph;
std::vector<int>* result;
};
} // end namespace
#endif