initial commit
This commit is contained in:
commit
efcd3e1892
106 changed files with 27000 additions and 0 deletions
7
src/util/graph/Dijkstra.cpp
Normal file
7
src/util/graph/Dijkstra.cpp
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// Copyright 2017, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#include "util/graph/Dijkstra.h"
|
||||
|
||||
size_t util::graph::Dijkstra::ITERS = 0;
|
||||
113
src/util/graph/Dijkstra.h
Normal file
113
src/util/graph/Dijkstra.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
// Copyright 2017, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#ifndef UTIL_GRAPH_DIJKSTRA_H_
|
||||
#define UTIL_GRAPH_DIJKSTRA_H_
|
||||
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include "util/graph/Edge.h"
|
||||
#include "util/graph/Graph.h"
|
||||
#include "util/graph/Node.h"
|
||||
#include "util/graph/ShortestPath.h"
|
||||
|
||||
namespace util {
|
||||
namespace graph {
|
||||
|
||||
using util::graph::Graph;
|
||||
using util::graph::Node;
|
||||
using util::graph::Edge;
|
||||
|
||||
// dijkstras algorithm for util graph
|
||||
class Dijkstra : public ShortestPath<Dijkstra> {
|
||||
public:
|
||||
template <typename N, typename E, typename C>
|
||||
struct RouteNode {
|
||||
RouteNode() : n(0), parent(0), d(), h(), e(0) {}
|
||||
RouteNode(Node<N, E>* n) : n(n), parent(0), d(), h(), e(0) {}
|
||||
RouteNode(Node<N, E>* n, Node<N, E>* parent, C d, Edge<N, E>* e)
|
||||
: n(n), parent(parent), d(d), h(), e(e) {}
|
||||
RouteNode(Node<N, E>* n, Node<N, E>* parent, C d, C h, Edge<N, E>* e)
|
||||
: n(n), parent(parent), d(d), h(h), e(e) {}
|
||||
|
||||
Node<N, E>* n;
|
||||
Node<N, E>* parent;
|
||||
|
||||
C d;
|
||||
C h;
|
||||
|
||||
Edge<N, E>* e;
|
||||
|
||||
bool operator<(const RouteNode<N, E, C>& p) const {
|
||||
return h > p.h || (h == p.h && d > p.d);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
using Settled = std::unordered_map<Node<N, E>*, RouteNode<N, E, C> >;
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
using PQ = std::priority_queue<RouteNode<N, E, C> >;
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
struct CostFunc : public ShortestPath::CostFunc<N, E, C> {
|
||||
C operator()(const Edge<N, E>* from, const Node<N, E>* n,
|
||||
const Edge<N, E>* to) const {
|
||||
UNUSED(from);
|
||||
UNUSED(n);
|
||||
UNUSED(to);
|
||||
return C();
|
||||
};
|
||||
};
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
struct HeurFunc : public ShortestPath::HeurFunc<N, E, C> {
|
||||
C operator()(const Edge<N, E>* from,
|
||||
const std::set<Edge<N, E>*>& to) const {
|
||||
UNUSED(from);
|
||||
UNUSED(to);
|
||||
return C();
|
||||
};
|
||||
};
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Node<N, E>*, C> shortestPathImpl(
|
||||
Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc, const ShortestPath::HeurFunc<N, E, C>&,
|
||||
std::unordered_map<Node<N, E>*, EList<N, E>*> resEdges,
|
||||
std::unordered_map<Node<N, E>*, NList<N, E>*> resNode);
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPathImpl(const std::set<Node<N, E>*> from, const std::set<Node<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes);
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPathImpl(Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes);
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static void relax(RouteNode<N, E, C>& cur, const std::set<Node<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc, PQ<N, E, C>& pq);
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static void buildPath(Node<N, E>* curN, Settled<N, E, C>& settled,
|
||||
NList<N, E>* resNodes, EList<N, E>* resEdges);
|
||||
|
||||
static size_t ITERS;
|
||||
};
|
||||
|
||||
#include "util/graph/Dijkstra.tpp"
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UTIL_GRAPH_DIJKSTRA_H_
|
||||
175
src/util/graph/Dijkstra.tpp
Normal file
175
src/util/graph/Dijkstra.tpp
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
// Copyright 2017, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E, typename C>
|
||||
C Dijkstra::shortestPathImpl(Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes) {
|
||||
if (from->getOutDeg() == 0) return costFunc.inf();
|
||||
|
||||
Settled<N, E, C> settled;
|
||||
PQ<N, E, C> pq;
|
||||
bool found = false;
|
||||
|
||||
pq.emplace(from);
|
||||
RouteNode<N, E, C> cur;
|
||||
|
||||
while (!pq.empty()) {
|
||||
Dijkstra::ITERS++;
|
||||
|
||||
if (settled.find(pq.top().n) != settled.end()) {
|
||||
pq.pop();
|
||||
continue;
|
||||
}
|
||||
|
||||
cur = pq.top();
|
||||
pq.pop();
|
||||
|
||||
settled[cur.n] = cur;
|
||||
|
||||
if (to.find(cur.n) != to.end()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
relax(cur, to, costFunc, heurFunc, pq);
|
||||
}
|
||||
|
||||
if (!found) return costFunc.inf();
|
||||
|
||||
buildPath(cur.n, settled, resNodes, resEdges);
|
||||
|
||||
return cur.d;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E, typename C>
|
||||
C Dijkstra::shortestPathImpl(const std::set<Node<N, E>*> from,
|
||||
const std::set<Node<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes) {
|
||||
Settled<N, E, C> settled;
|
||||
PQ<N, E, C> pq;
|
||||
bool found = false;
|
||||
|
||||
// put all nodes in from onto PQ
|
||||
for (auto n : from) pq.emplace(n);
|
||||
RouteNode<N, E, C> cur;
|
||||
|
||||
while (!pq.empty()) {
|
||||
Dijkstra::ITERS++;
|
||||
|
||||
if (settled.find(pq.top().n) != settled.end()) {
|
||||
pq.pop();
|
||||
continue;
|
||||
}
|
||||
|
||||
cur = pq.top();
|
||||
pq.pop();
|
||||
|
||||
settled[cur.n] = cur;
|
||||
|
||||
if (to.find(cur.n) != to.end()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
relax(cur, to, costFunc, heurFunc, pq);
|
||||
}
|
||||
|
||||
if (!found) return costFunc.inf();
|
||||
|
||||
buildPath(cur.n, settled, resNodes, resEdges);
|
||||
|
||||
return cur.d;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E, typename C>
|
||||
std::unordered_map<Node<N, E>*, C> Dijkstra::shortestPathImpl(
|
||||
Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
std::unordered_map<Node<N, E>*, EList<N, E>*> resEdges,
|
||||
std::unordered_map<Node<N, E>*, NList<N, E>*> resNodes) {
|
||||
std::unordered_map<Node<N, E>*, C> costs;
|
||||
if (to.size() == 0) return costs;
|
||||
// init costs with inf
|
||||
for (auto n : to) costs[n] = costFunc.inf();
|
||||
|
||||
if (from->getOutDeg() == 0) return costs;
|
||||
|
||||
Settled<N, E, C> settled;
|
||||
PQ<N, E, C> pq;
|
||||
|
||||
size_t found = 0;
|
||||
|
||||
pq.emplace(from);
|
||||
RouteNode<N, E, C> cur;
|
||||
|
||||
while (!pq.empty()) {
|
||||
Dijkstra::ITERS++;
|
||||
|
||||
if (settled.find(pq.top().n) != settled.end()) {
|
||||
pq.pop();
|
||||
continue;
|
||||
}
|
||||
|
||||
cur = pq.top();
|
||||
pq.pop();
|
||||
|
||||
settled[cur.n] = cur;
|
||||
|
||||
if (to.find(cur.n) != to.end()) {
|
||||
found++;
|
||||
}
|
||||
|
||||
if (found == to.size()) break;
|
||||
|
||||
relax(cur, to, costFunc, heurFunc, pq);
|
||||
}
|
||||
|
||||
for (auto nto : to) {
|
||||
if (!settled.count(nto)) continue;
|
||||
Node<N, E>* curN = nto;
|
||||
costs[nto] = settled[curN].d;
|
||||
|
||||
buildPath(nto, settled, resNodes[nto], resEdges[nto]);
|
||||
}
|
||||
|
||||
return costs;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E, typename C>
|
||||
void Dijkstra::relax(RouteNode<N, E, C>& cur, const std::set<Node<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc, PQ<N, E, C>& pq) {
|
||||
for (auto edge : cur.n->getAdjListOut()) {
|
||||
C newC = costFunc(cur.n, edge, edge->getOtherNd(cur.n));
|
||||
newC = cur.d + newC;
|
||||
if (costFunc.inf() <= newC) continue;
|
||||
|
||||
const C& newH = newC + heurFunc(edge->getOtherNd(cur.n), to);
|
||||
|
||||
pq.emplace(edge->getOtherNd(cur.n), cur.n, newC, newH, &(*edge));
|
||||
}
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E, typename C>
|
||||
void Dijkstra::buildPath(Node<N, E>* curN,
|
||||
Settled<N, E, C>& settled, NList<N, E>* resNodes,
|
||||
EList<N, E>* resEdges) {
|
||||
while (true) {
|
||||
const RouteNode<N, E, C>& curNode = settled[curN];
|
||||
if (resNodes) resNodes->push_back(curNode.n);
|
||||
if (!curNode.parent) break;
|
||||
if (resEdges) resEdges->push_back(curNode.e);
|
||||
curN = curNode.parent;
|
||||
}
|
||||
}
|
||||
41
src/util/graph/DirGraph.h
Normal file
41
src/util/graph/DirGraph.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2016, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#ifndef UTIL_GRAPH_DIRGRAPH_H_
|
||||
#define UTIL_GRAPH_DIRGRAPH_H_
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "util/graph/Graph.h"
|
||||
#include "util/graph/Edge.h"
|
||||
#include "util/graph/DirNode.h"
|
||||
|
||||
namespace util {
|
||||
namespace graph {
|
||||
|
||||
template <typename N, typename E>
|
||||
using UndirEdge = Edge<N, E>;
|
||||
|
||||
template <typename N, typename E>
|
||||
class DirGraph : public Graph<N, E> {
|
||||
public:
|
||||
explicit DirGraph();
|
||||
|
||||
using Graph<N, E>::addEdg;
|
||||
|
||||
Node<N, E>* addNd();
|
||||
Node<N, E>* addNd(DirNode<N, E>* n);
|
||||
Node<N, E>* addNd(const N& pl);
|
||||
Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to, const E& p);
|
||||
|
||||
Node<N, E>* mergeNds(Node<N, E>* a, Node<N, E>* b);
|
||||
|
||||
};
|
||||
|
||||
#include "util/graph/DirGraph.tpp"
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UTIL_GRAPH_DIRGRAPH_H_
|
||||
59
src/util/graph/DirGraph.tpp
Normal file
59
src/util/graph/DirGraph.tpp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright 2016, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
DirGraph<N, E>::DirGraph() {}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Node<N, E>* DirGraph<N, E>::addNd(const N& pl) {
|
||||
return addNd(new DirNode<N, E>(pl));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Node<N, E>* DirGraph<N, E>::addNd() {
|
||||
return addNd(new DirNode<N, E>());
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Node<N, E>* DirGraph<N, E>::addNd(DirNode<N, E>* n) {
|
||||
auto ins = Graph<N, E>::getNds()->insert(n);
|
||||
return *ins.first;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Edge<N, E>* DirGraph<N, E>::addEdg(Node<N, E>* from, Node<N, E>* to,
|
||||
const E& p) {
|
||||
Edge<N, E>* e = Graph<N, E>::getEdg(from, to);
|
||||
if (!e) {
|
||||
e = new Edge<N, E>(from, to, p);
|
||||
from->addEdge(e);
|
||||
to->addEdge(e);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Node<N, E>* DirGraph<N, E>::mergeNds(Node<N, E>* a, Node<N, E>* b) {
|
||||
for (auto e : a->getAdjListOut()) {
|
||||
if (e->getTo() != b) {
|
||||
addEdg(b, e->getTo(), e->pl());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto e : a->getAdjListIn()) {
|
||||
if (e->getFrom() != b) {
|
||||
addEdg(e->getFrom(), b, e->pl());
|
||||
}
|
||||
}
|
||||
|
||||
DirGraph<N, E>::delNd(a);
|
||||
|
||||
return b;
|
||||
}
|
||||
57
src/util/graph/DirNode.h
Normal file
57
src/util/graph/DirNode.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2016, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#ifndef UTIL_GRAPH_DIRNODE_H_
|
||||
#define UTIL_GRAPH_DIRNODE_H_
|
||||
|
||||
#include <vector>
|
||||
#include "util/graph/Node.h"
|
||||
|
||||
namespace util {
|
||||
namespace graph {
|
||||
|
||||
// forward declaration of Edge
|
||||
|
||||
template <typename N, typename E>
|
||||
class DirNode : public Node<N, E> {
|
||||
public:
|
||||
DirNode();
|
||||
DirNode(const N& pl);
|
||||
~DirNode();
|
||||
|
||||
const std::vector<Edge<N, E>*>& getAdjList() const;
|
||||
const std::vector<Edge<N, E>*>& getAdjListIn() const;
|
||||
const std::vector<Edge<N, E>*>& getAdjListOut() const;
|
||||
|
||||
size_t getDeg() const;
|
||||
size_t getInDeg() const;
|
||||
size_t getOutDeg() const;
|
||||
|
||||
bool hasEdgeIn(const Edge<N, E>* e) const;
|
||||
bool hasEdgeOut(const Edge<N, E>* e) const;
|
||||
bool hasEdge(const Edge<N, E>* e) const;
|
||||
|
||||
// add edge to this node's adjacency lists
|
||||
void addEdge(Edge<N, E>* e);
|
||||
|
||||
// remove edge from this node's adjacency lists
|
||||
void removeEdge(Edge<N, E>* e);
|
||||
|
||||
N& pl();
|
||||
const N& pl() const;
|
||||
|
||||
private:
|
||||
std::vector<Edge<N, E>*> _adjListIn;
|
||||
std::vector<Edge<N, E>*> _adjListOut;
|
||||
N _pl;
|
||||
|
||||
bool adjInContains(const Edge<N, E>* e) const;
|
||||
bool adjOutContains(const Edge<N, E>* e) const;
|
||||
};
|
||||
|
||||
#include "util/graph/DirNode.tpp"
|
||||
|
||||
}}
|
||||
|
||||
#endif // UTIL_GRAPH_DIRNODE_H_
|
||||
153
src/util/graph/DirNode.tpp
Normal file
153
src/util/graph/DirNode.tpp
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
// Copyright 2016, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
DirNode<N, E>::DirNode() : _pl() {}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
DirNode<N, E>::DirNode(const N& pl) : _pl(pl) {}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
DirNode<N, E>::~DirNode() {
|
||||
// delete self edges
|
||||
for (auto e = _adjListOut.begin(); e != _adjListOut.end();) {
|
||||
Edge<N, E>* eP = *e;
|
||||
if (eP->getTo() == this) {
|
||||
_adjListIn.erase(std::find(_adjListIn.begin(), _adjListIn.end(), eP));
|
||||
e = _adjListOut.erase(e);
|
||||
delete eP;
|
||||
} else {
|
||||
e++;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto e = _adjListOut.begin(); e != _adjListOut.end(); e++) {
|
||||
Edge<N, E>* eP = *e;
|
||||
|
||||
if (eP->getTo() != this) {
|
||||
eP->getTo()->removeEdge(eP);
|
||||
delete eP;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto e = _adjListIn.begin(); e != _adjListIn.end(); e++) {
|
||||
Edge<N, E>* eP = *e;
|
||||
|
||||
if (eP->getFrom() != this) {
|
||||
eP->getFrom()->removeEdge(eP);
|
||||
delete eP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
void DirNode<N, E>::addEdge(Edge<N, E>* e) {
|
||||
if (e->getFrom() == this && !adjOutContains(e)) {
|
||||
_adjListOut.reserve(_adjListOut.size() + 1);
|
||||
_adjListOut.push_back(e);
|
||||
}
|
||||
if (e->getTo() == this && !adjInContains(e)) {
|
||||
_adjListIn.reserve(_adjListIn.size() + 1);
|
||||
_adjListIn.push_back(e);
|
||||
}
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
void DirNode<N, E>::removeEdge(Edge<N, E>* e) {
|
||||
if (e->getFrom() == this) {
|
||||
auto p = std::find(_adjListOut.begin(), _adjListOut.end(), e);
|
||||
if (p != _adjListOut.end()) _adjListOut.erase(p);
|
||||
}
|
||||
if (e->getTo() == this) {
|
||||
auto p = std::find(_adjListIn.begin(), _adjListIn.end(), e);
|
||||
if (p != _adjListIn.end()) _adjListIn.erase(p);
|
||||
}
|
||||
}
|
||||
//
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
bool DirNode<N, E>::hasEdgeIn(const Edge<N, E>* e) const {
|
||||
return e->getTo() == this;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
bool DirNode<N, E>::hasEdgeOut(const Edge<N, E>* e) const {
|
||||
return e->getFrom() == this;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
bool DirNode<N, E>::hasEdge(const Edge<N, E>* e) const {
|
||||
return hasEdgeOut(e) || hasEdgeIn(e);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
const std::vector<Edge<N, E>*>& DirNode<N, E>::getAdjList() const {
|
||||
return _adjListOut;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
const std::vector<Edge<N, E>*>& DirNode<N, E>::getAdjListOut() const {
|
||||
return _adjListOut;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
const std::vector<Edge<N, E>*>& DirNode<N, E>::getAdjListIn() const {
|
||||
return _adjListIn;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
size_t DirNode<N, E>::getDeg() const {
|
||||
return _adjListOut.size();
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
size_t DirNode<N, E>::getInDeg() const {
|
||||
return _adjListIn.size();
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
size_t DirNode<N, E>::getOutDeg() const {
|
||||
return _adjListOut.size();
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
N& DirNode<N, E>::pl() {
|
||||
return _pl;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
const N& DirNode<N, E>::pl() const {
|
||||
return _pl;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
bool DirNode<N, E>::adjInContains(const Edge<N, E>* e) const {
|
||||
for (size_t i = 0; i < _adjListIn.size(); i++)
|
||||
if (_adjListIn[i] == e) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
bool DirNode<N, E>::adjOutContains(const Edge<N, E>* e) const {
|
||||
for (size_t i = 0; i < _adjListOut.size(); i++)
|
||||
if (_adjListOut[i] == e) return true;
|
||||
return false;
|
||||
}
|
||||
7
src/util/graph/EDijkstra.cpp
Normal file
7
src/util/graph/EDijkstra.cpp
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// Copyright 2017, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#include "util/graph/EDijkstra.h"
|
||||
|
||||
size_t util::graph::EDijkstra::ITERS = 0;
|
||||
139
src/util/graph/EDijkstra.h
Normal file
139
src/util/graph/EDijkstra.h
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
// Copyright 2017, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#ifndef UTIL_GRAPH_EDIJKSTRA_H_
|
||||
#define UTIL_GRAPH_EDIJKSTRA_H_
|
||||
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include "util/graph/Edge.h"
|
||||
#include "util/graph/Graph.h"
|
||||
#include "util/graph/Node.h"
|
||||
#include "util/graph/ShortestPath.h"
|
||||
|
||||
namespace util {
|
||||
namespace graph {
|
||||
|
||||
using util::graph::Graph;
|
||||
using util::graph::Node;
|
||||
using util::graph::Edge;
|
||||
|
||||
// edge-based dijkstra - settles edges instead of nodes
|
||||
class EDijkstra : public ShortestPath<EDijkstra> {
|
||||
public:
|
||||
template <typename N, typename E, typename C>
|
||||
struct RouteEdge {
|
||||
RouteEdge() : e(0), parent(0), d(), h(), n(0) {}
|
||||
RouteEdge(Edge<N, E>* e) : e(e), parent(0), d(), h(), n(0) {}
|
||||
RouteEdge(Edge<N, E>* e, Edge<N, E>* parent, Node<N, E>* n, C d)
|
||||
: e(e), parent(parent), d(d), h(), n(n) {}
|
||||
RouteEdge(Edge<N, E>* e, Edge<N, E>* parent, Node<N, E>* n, C d, C h)
|
||||
: e(e), parent(parent), d(d), h(h), n(n) {}
|
||||
|
||||
Edge<N, E>* e;
|
||||
Edge<N, E>* parent;
|
||||
|
||||
C d;
|
||||
C h;
|
||||
|
||||
Node<N, E>* n;
|
||||
|
||||
bool operator<(const RouteEdge<N, E, C>& p) const {
|
||||
return h > p.h || (h == p.h && d > p.d);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
struct CostFunc : public ShortestPath::CostFunc<N, E, C> {
|
||||
C operator()(const Node<N, E>* from, const Edge<N, E>* e,
|
||||
const Node<N, E>* to) const {
|
||||
UNUSED(from);
|
||||
UNUSED(e);
|
||||
UNUSED(to);
|
||||
return C();
|
||||
};
|
||||
};
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
struct HeurFunc : public ShortestPath::HeurFunc<N, E, C> {
|
||||
C operator()(const Node<N, E>* from,
|
||||
const std::set<Node<N, E>*>& to) const {
|
||||
UNUSED(from);
|
||||
UNUSED(to);
|
||||
return C();
|
||||
};
|
||||
};
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
using Settled = std::unordered_map<Edge<N, E>*, RouteEdge<N, E, C> >;
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
using PQ = std::priority_queue<RouteEdge<N, E, C> >;
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPathImpl(const std::set<Edge<N, E>*> from,
|
||||
const std::set<Edge<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes);
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPathImpl(Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes);
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPathImpl(Edge<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes);
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPathImpl(const std::set<Edge<N, E>*>& from,
|
||||
const std::set<Node<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes);
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Edge<N, E>*, C> shortestPathImpl(
|
||||
const std::set<Edge<N, E>*>& from,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc, bool rev);
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Edge<N, E>*, C> shortestPathImpl(
|
||||
Edge<N, E>* from, const std::set<Edge<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
std::unordered_map<Edge<N, E>*, EList<N, E>*> resEdges,
|
||||
std::unordered_map<Edge<N, E>*, NList<N, E>*> resNodes);
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static void buildPath(Edge<N, E>* curE, const Settled<N, E, C>& settled,
|
||||
NList<N, E>* resNodes, EList<N, E>* resEdges);
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static inline void relax(RouteEdge<N, E, C>& cur,
|
||||
const std::set<Edge<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
PQ<N, E, C>& pq);
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static void relaxInv(RouteEdge<N, E, C>& cur,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
PQ<N, E, C>& pq);
|
||||
|
||||
static size_t ITERS;
|
||||
};
|
||||
|
||||
#include "util/graph/EDijkstra.tpp"
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UTIL_GRAPH_DIJKSTRA_H_
|
||||
258
src/util/graph/EDijkstra.tpp
Normal file
258
src/util/graph/EDijkstra.tpp
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
// Copyright 2017, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E, typename C>
|
||||
C EDijkstra::shortestPathImpl(Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes) {
|
||||
std::set<Edge<N, E>*> frEs;
|
||||
std::set<Edge<N, E>*> toEs;
|
||||
|
||||
frEs.insert(from->getAdjListOut().begin(), from->getAdjListOut().end());
|
||||
|
||||
for (auto n : to) {
|
||||
toEs.insert(n->getAdjListIn().begin(), n->getAdjListIn().end());
|
||||
}
|
||||
|
||||
C cost = shortestPathImpl(frEs, toEs, costFunc, heurFunc, resEdges, resNodes);
|
||||
|
||||
// the beginning node is not included in our edge based dijkstra
|
||||
if (resNodes) resNodes->push_back(from);
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E, typename C>
|
||||
C EDijkstra::shortestPathImpl(Edge<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes) {
|
||||
std::set<Edge<N, E>*> frEs;
|
||||
std::set<Edge<N, E>*> toEs;
|
||||
|
||||
frEs.insert(from);
|
||||
|
||||
for (auto n : to) {
|
||||
toEs.insert(n->getAdjListIn().begin(), n->getAdjListIn().end());
|
||||
}
|
||||
|
||||
C cost = shortestPathImpl(frEs, toEs, costFunc, heurFunc, resEdges, resNodes);
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E, typename C>
|
||||
C EDijkstra::shortestPathImpl(const std::set<Edge<N, E>*> from,
|
||||
const std::set<Edge<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes) {
|
||||
if (from.size() == 0 || to.size() == 0) return costFunc.inf();
|
||||
|
||||
Settled<N, E, C> settled;
|
||||
PQ<N, E, C> pq;
|
||||
bool found = false;
|
||||
|
||||
// at the beginning, put all edges on the priority queue,
|
||||
// init them with their own cost
|
||||
for (auto e : from) {
|
||||
C c = costFunc(0, 0, e);
|
||||
C h = heurFunc(e, to);
|
||||
pq.emplace(e, (Edge<N, E>*)0, (Node<N, E>*)0, c, c + h);
|
||||
}
|
||||
|
||||
RouteEdge<N, E, C> cur;
|
||||
|
||||
while (!pq.empty()) {
|
||||
EDijkstra::ITERS++;
|
||||
|
||||
if (settled.find(pq.top().e) != settled.end()) {
|
||||
pq.pop();
|
||||
continue;
|
||||
}
|
||||
|
||||
cur = pq.top();
|
||||
pq.pop();
|
||||
|
||||
settled[cur.e] = cur;
|
||||
|
||||
if (to.find(cur.e) != to.end()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
relax(cur, to, costFunc, heurFunc, pq);
|
||||
}
|
||||
|
||||
if (!found) return costFunc.inf();
|
||||
|
||||
buildPath(cur.e, settled, resNodes, resEdges);
|
||||
|
||||
return cur.d;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E, typename C>
|
||||
std::unordered_map<Edge<N, E>*, C> EDijkstra::shortestPathImpl(
|
||||
const std::set<Edge<N, E>*>& from, const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
bool rev) {
|
||||
std::unordered_map<Edge<N, E>*, C> costs;
|
||||
|
||||
Settled<N, E, C> settled;
|
||||
PQ<N, E, C> pq;
|
||||
|
||||
std::set<Edge<N, E>*> to;
|
||||
|
||||
for (auto e : from) {
|
||||
pq.emplace(e, (Edge<N, E>*)0, (Node<N, E>*)0, costFunc(0, 0, e), C());
|
||||
}
|
||||
|
||||
RouteEdge<N, E, C> cur;
|
||||
|
||||
while (!pq.empty()) {
|
||||
EDijkstra::ITERS++;
|
||||
|
||||
if (settled.find(pq.top().e) != settled.end()) {
|
||||
pq.pop();
|
||||
continue;
|
||||
}
|
||||
|
||||
cur = pq.top();
|
||||
pq.pop();
|
||||
|
||||
settled[cur.e] = cur;
|
||||
|
||||
costs[cur.e] = cur.d;
|
||||
buildPath(cur.e, settled, (NList<N, E>*)0, (EList<N, E>*)0);
|
||||
|
||||
if (rev)
|
||||
relaxInv(cur, costFunc, pq);
|
||||
else
|
||||
relax(cur, to, costFunc, ZeroHeurFunc<N, E, C>(), pq);
|
||||
}
|
||||
|
||||
return costs;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E, typename C>
|
||||
std::unordered_map<Edge<N, E>*, C> EDijkstra::shortestPathImpl(
|
||||
Edge<N, E>* from, const std::set<Edge<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
std::unordered_map<Edge<N, E>*, EList<N, E>*> resEdges,
|
||||
std::unordered_map<Edge<N, E>*, NList<N, E>*> resNodes) {
|
||||
std::unordered_map<Edge<N, E>*, C> costs;
|
||||
if (to.size() == 0) return costs;
|
||||
|
||||
// init costs with inf
|
||||
for (auto e : to) costs[e] = costFunc.inf();
|
||||
|
||||
Settled<N, E, C> settled;
|
||||
PQ<N, E, C> pq;
|
||||
|
||||
size_t found = 0;
|
||||
|
||||
C c = costFunc(0, 0, from);
|
||||
C h = heurFunc(from, to);
|
||||
pq.emplace(from, (Edge<N, E>*)0, (Node<N, E>*)0, c, c + h);
|
||||
|
||||
RouteEdge<N, E, C> cur;
|
||||
|
||||
while (!pq.empty()) {
|
||||
EDijkstra::ITERS++;
|
||||
|
||||
if (settled.find(pq.top().e) != settled.end()) {
|
||||
pq.pop();
|
||||
continue;
|
||||
}
|
||||
|
||||
cur = pq.top();
|
||||
pq.pop();
|
||||
|
||||
settled[cur.e] = cur;
|
||||
|
||||
if (to.find(cur.e) != to.end()) {
|
||||
found++;
|
||||
costs[cur.e] = cur.d;
|
||||
buildPath(cur.e, settled, resNodes[cur.e], resEdges[cur.e]);
|
||||
}
|
||||
|
||||
if (found == to.size()) return costs;
|
||||
|
||||
relax(cur, to, costFunc, heurFunc, pq);
|
||||
}
|
||||
|
||||
return costs;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E, typename C>
|
||||
void EDijkstra::relaxInv(RouteEdge<N, E, C>& cur,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
PQ<N, E, C>& pq) {
|
||||
|
||||
// handling undirected graph makes no sense here
|
||||
|
||||
for (const auto edge : cur.e->getFrom()->getAdjListIn()) {
|
||||
if (edge == cur.e) continue;
|
||||
C newC = costFunc(edge, cur.e->getFrom(), cur.e);
|
||||
newC = cur.d + newC;
|
||||
if (costFunc.inf() <= newC) continue;
|
||||
|
||||
pq.emplace(edge, cur.e, cur.e->getFrom(), newC, C());
|
||||
}
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E, typename C>
|
||||
void EDijkstra::relax(RouteEdge<N, E, C>& cur, const std::set<Edge<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const ShortestPath::HeurFunc<N, E, C>& heurFunc,
|
||||
PQ<N, E, C>& pq) {
|
||||
if (cur.e->getFrom()->hasEdgeIn(cur.e)) {
|
||||
// for undirected graphs
|
||||
for (const auto edge : cur.e->getFrom()->getAdjListOut()) {
|
||||
if (edge == cur.e) continue;
|
||||
C newC = costFunc(cur.e, cur.e->getFrom(), edge);
|
||||
newC = cur.d + newC;
|
||||
if (costFunc.inf() <= newC) continue;
|
||||
|
||||
const C& h = heurFunc(edge, to);
|
||||
const C& newH = newC + h;
|
||||
|
||||
pq.emplace(edge, cur.e, cur.e->getFrom(), newC, newH);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto edge : cur.e->getTo()->getAdjListOut()) {
|
||||
if (edge == cur.e) continue;
|
||||
C newC = costFunc(cur.e, cur.e->getTo(), edge);
|
||||
newC = cur.d + newC;
|
||||
if (costFunc.inf() <= newC) continue;
|
||||
|
||||
const C& h = heurFunc(edge, to);
|
||||
const C& newH = newC + h;
|
||||
|
||||
pq.emplace(edge, cur.e, cur.e->getTo(), newC, newH);
|
||||
}
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E, typename C>
|
||||
void EDijkstra::buildPath(Edge<N, E>* curE, const Settled<N, E, C>& settled,
|
||||
NList<N, E>* resNodes, EList<N, E>* resEdges) {
|
||||
const RouteEdge<N, E, C>* curEdge = &settled.find(curE)->second;
|
||||
if (resNodes) resNodes->push_back(curEdge->e->getOtherNd(curEdge->n));
|
||||
while (true) {
|
||||
if (resNodes && curEdge->n) resNodes->push_back(curEdge->n);
|
||||
if (resEdges) resEdges->push_back(curEdge->e);
|
||||
if (!curEdge->parent) break;
|
||||
curEdge = &settled.find(curEdge->parent)->second;
|
||||
}
|
||||
}
|
||||
41
src/util/graph/Edge.h
Normal file
41
src/util/graph/Edge.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2016, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#ifndef UTIL_GRAPH_EDGE_H_
|
||||
#define UTIL_GRAPH_EDGE_H_
|
||||
|
||||
#include <vector>
|
||||
#include "util/graph/Node.h"
|
||||
|
||||
namespace util {
|
||||
namespace graph {
|
||||
|
||||
template <typename N, typename E>
|
||||
class Edge {
|
||||
public:
|
||||
Edge(Node<N, E>* from, Node<N, E>* to, const E& pl);
|
||||
|
||||
Node<N, E>* getFrom() const;
|
||||
Node<N, E>* getTo() const;
|
||||
|
||||
Node<N, E>* getOtherNd(const Node<N, E>* notNode) const;
|
||||
|
||||
void setFrom(Node<N, E>* from);
|
||||
void setTo(Node<N, E>* to);
|
||||
|
||||
E& pl();
|
||||
const E& pl() const;
|
||||
|
||||
private:
|
||||
Node<N, E>* _from;
|
||||
Node<N, E>* _to;
|
||||
E _pl;
|
||||
};
|
||||
|
||||
#include "util/graph/Edge.tpp"
|
||||
|
||||
}}
|
||||
|
||||
#endif // UTIL_GRAPH_EDGE_H_
|
||||
|
||||
41
src/util/graph/Edge.tpp
Normal file
41
src/util/graph/Edge.tpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2016, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Edge<N, E>::Edge(Node<N, E>* from, Node<N, E>* to, const E& pl)
|
||||
: _from(from), _to(to), _pl(pl) {
|
||||
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Node<N, E>* Edge<N, E>::getFrom() const {
|
||||
return _from;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Node<N, E>* Edge<N, E>::getTo() const {
|
||||
return _to;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Node<N, E>* Edge<N, E>::getOtherNd(const Node<N, E>* notNode) const {
|
||||
if (_to == notNode) return _from;
|
||||
return _to;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
E& Edge<N, E>::pl() {
|
||||
return _pl;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
const E& Edge<N, E>::pl() const {
|
||||
return _pl;
|
||||
}
|
||||
47
src/util/graph/Graph.h
Normal file
47
src/util/graph/Graph.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2016, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#ifndef UTIL_GRAPH_GRAPH_H_
|
||||
#define UTIL_GRAPH_GRAPH_H_
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "util/graph/Edge.h"
|
||||
#include "util/graph/Node.h"
|
||||
|
||||
namespace util {
|
||||
namespace graph {
|
||||
|
||||
template <typename N, typename E>
|
||||
class Graph {
|
||||
public:
|
||||
~Graph();
|
||||
virtual Node<N, E>* addNd() = 0;
|
||||
virtual Node<N, E>* addNd(const N& pl) = 0;
|
||||
Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to);
|
||||
virtual Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to, const E& p) = 0;
|
||||
Edge<N, E>* getEdg(Node<N, E>* from, Node<N, E>* to);
|
||||
const Edge<N, E>* getEdg(Node<N, E>* from, Node<N, E>* to) const;
|
||||
|
||||
virtual Node<N, E>* mergeNds(Node<N, E>* a, Node<N, E>* b) = 0;
|
||||
|
||||
const std::set<Node<N, E>*>& getNds() const;
|
||||
std::set<Node<N, E>*>* getNds();
|
||||
|
||||
typename std::set<Node<N, E>*>::iterator delNd(Node<N, E>* n);
|
||||
typename std::set<Node<N, E>*>::iterator delNd(
|
||||
typename std::set<Node<N, E>*>::iterator i);
|
||||
void delEdg(Node<N, E>* from, Node<N, E>* to);
|
||||
|
||||
private:
|
||||
std::set<Node<N, E>*> _nodes;
|
||||
};
|
||||
|
||||
#include "util/graph/Graph.tpp"
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UTIL_GRAPH_GRAPH_H_
|
||||
76
src/util/graph/Graph.tpp
Normal file
76
src/util/graph/Graph.tpp
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright 2016, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Graph<N, E>::~Graph() {
|
||||
for (auto n : _nodes) delete n;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Edge<N, E>* Graph<N, E>::addEdg(Node<N, E>* from, Node<N, E>* to) {
|
||||
return addEdg(from, to, E());
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
const std::set<Node<N, E>*>& Graph<N, E>::getNds() const {
|
||||
return _nodes;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
std::set<Node<N, E>*>* Graph<N, E>::getNds() {
|
||||
return &_nodes;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
typename std::set<Node<N, E>*>::iterator Graph<N, E>::delNd(
|
||||
Node<N, E>* n) {
|
||||
return delNd(_nodes.find(n));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
typename std::set<Node<N, E>*>::iterator Graph<N, E>::delNd(
|
||||
typename std::set<Node<N, E>*>::iterator i) {
|
||||
delete *i;
|
||||
return _nodes.erase(i);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
void Graph<N, E>::delEdg(Node<N, E>* from, Node<N, E>* to) {
|
||||
Edge<N, E>* toDel = getEdg(from, to);
|
||||
if (!toDel) return;
|
||||
|
||||
from->removeEdge(toDel);
|
||||
to->removeEdge(toDel);
|
||||
|
||||
assert(!getEdg(from, to));
|
||||
|
||||
delete toDel;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Edge<N, E>* Graph<N, E>::getEdg(Node<N, E>* from, Node<N, E>* to) {
|
||||
for (auto e : from->getAdjList()) {
|
||||
if (e->getOtherNd(from) == to) return e;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
const Edge<N, E>* Graph<N, E>::getEdg(Node<N, E>* from, Node<N, E>* to) const {
|
||||
for (auto e : from->getAdjList()) {
|
||||
if (e->getOtherNd(from) == to) return e;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
44
src/util/graph/Node.h
Normal file
44
src/util/graph/Node.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2016, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#ifndef UTIL_GRAPH_NODE_H_
|
||||
#define UTIL_GRAPH_NODE_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace util {
|
||||
namespace graph {
|
||||
|
||||
// forward declaration of Edge
|
||||
template <typename N, typename E>
|
||||
class Edge;
|
||||
|
||||
template <typename N, typename E>
|
||||
class Node {
|
||||
public:
|
||||
virtual const std::vector<Edge<N, E>*>& getAdjList() const = 0;
|
||||
virtual const std::vector<Edge<N, E>*>& getAdjListOut() const = 0;
|
||||
virtual const std::vector<Edge<N, E>*>& getAdjListIn() const = 0;
|
||||
|
||||
virtual size_t getDeg() const = 0;
|
||||
virtual size_t getInDeg() const = 0;
|
||||
virtual size_t getOutDeg() const = 0;
|
||||
|
||||
virtual bool hasEdgeIn(const Edge<N, E>* e) const = 0;
|
||||
virtual bool hasEdgeOut(const Edge<N, E>* e) const = 0;
|
||||
virtual bool hasEdge(const Edge<N, E>* e) const = 0;
|
||||
|
||||
// add edge to this node's adjacency lists
|
||||
virtual void addEdge(Edge<N, E>* e) = 0;
|
||||
virtual void removeEdge(Edge<N, E>* e) = 0;
|
||||
|
||||
virtual ~Node() {};
|
||||
|
||||
virtual N& pl() = 0;
|
||||
virtual const N& pl() const = 0;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif // UTIL_GRAPH_NODE_H_
|
||||
401
src/util/graph/ShortestPath.h
Normal file
401
src/util/graph/ShortestPath.h
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
// Copyright 2017, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#ifndef UTIL_GRAPH_SHORTESTPATH_H_
|
||||
#define UTIL_GRAPH_SHORTESTPATH_H_
|
||||
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include "util/graph/Edge.h"
|
||||
#include "util/graph/Graph.h"
|
||||
#include "util/graph/Node.h"
|
||||
|
||||
namespace util {
|
||||
namespace graph {
|
||||
|
||||
using util::graph::Graph;
|
||||
using util::graph::Node;
|
||||
using util::graph::Edge;
|
||||
|
||||
// shortest path base class
|
||||
template <class D>
|
||||
class ShortestPath {
|
||||
public:
|
||||
template <typename N, typename E>
|
||||
using EList = std::vector<Edge<N, E>*>;
|
||||
|
||||
template <typename N, typename E>
|
||||
using NList = std::vector<Node<N, E>*>;
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
struct CostFunc {
|
||||
virtual C operator()(const Node<N, E>* from, const Edge<N, E>* e,
|
||||
const Node<N, E>* to) const = 0;
|
||||
virtual C operator()(const Edge<N, E>* from, const Node<N, E>* n,
|
||||
const Edge<N, E>* to) const = 0;
|
||||
virtual C inf() const = 0;
|
||||
};
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
struct HeurFunc {
|
||||
virtual C operator()(const Node<N, E>* a,
|
||||
const std::set<Node<N, E>*>& b) const = 0;
|
||||
virtual C operator()(const Edge<N, E>* a,
|
||||
const std::set<Edge<N, E>*>& b) const = 0;
|
||||
};
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
struct ZeroHeurFunc : public HeurFunc<N, E, C> {
|
||||
C operator()(const Node<N, E>* a, const std::set<Node<N, E>*>& b) const {
|
||||
UNUSED(a);
|
||||
UNUSED(b);
|
||||
return C();
|
||||
}
|
||||
C operator()(const Edge<N, E>* a, const std::set<Edge<N, E>*>& b) const {
|
||||
UNUSED(a);
|
||||
UNUSED(b);
|
||||
return C();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
const HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes) {
|
||||
return D::shortestPathImpl(from, to, costFunc, heurFunc, resEdges,
|
||||
resNodes);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(const std::set<Node<N, E>*> from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
const HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes) {
|
||||
return D::shortestPathImpl(from, to, costFunc, heurFunc, resEdges,
|
||||
resNodes);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes) {
|
||||
return D::shortestPathImpl(from, to, costFunc, ZeroHeurFunc<N, E, C>(),
|
||||
resEdges, resNodes);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Node<N, E>*, C> shortestPath(
|
||||
Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc, const HeurFunc<N, E, C>& heurFunc,
|
||||
std::unordered_map<Node<N, E>*, EList<N, E>*> resEdges,
|
||||
std::unordered_map<Node<N, E>*, NList<N, E>*> resNodes) {
|
||||
return D::shortestPathImpl(from, to, costFunc, heurFunc, resEdges,
|
||||
resNodes);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Node<N, E>*, C> shortestPath(
|
||||
Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
std::unordered_map<Node<N, E>*, EList<N, E>*> resEdges,
|
||||
std::unordered_map<Node<N, E>*, NList<N, E>*> resNodes) {
|
||||
return D::shortestPathImpl(from, to, costFunc, ZeroHeurFunc<N, E, C>(),
|
||||
resEdges, resNodes);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Node<N, E>*, C> shortestPath(
|
||||
Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc, const HeurFunc<N, E, C>& heurFunc,
|
||||
std::unordered_map<Node<N, E>*, EList<N, E>*> resEdges) {
|
||||
std::unordered_map<Node<N, E>*, NList<N, E>*> dummyRet;
|
||||
return D::shortestPathImpl(from, to, costFunc, heurFunc, resEdges,
|
||||
dummyRet);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Node<N, E>*, C> shortestPath(
|
||||
Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
std::unordered_map<Node<N, E>*, EList<N, E>*> resEdges) {
|
||||
std::unordered_map<Node<N, E>*, NList<N, E>*> dummyRet;
|
||||
return D::shortestPathImpl(from, to, costFunc, ZeroHeurFunc<N, E, C>(),
|
||||
resEdges, dummyRet);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Node<N, E>*, C> shortestPath(
|
||||
Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
std::unordered_map<Node<N, E>*, NList<N, E>*> resNodes) {
|
||||
std::unordered_map<Node<N, E>*, EList<N, E>*> dummyRet;
|
||||
return D::shortestPathImpl(from, to, costFunc, ZeroHeurFunc<N, E, C>(),
|
||||
dummyRet, resNodes);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Node<N, E>*, C> shortestPath(
|
||||
Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc, const HeurFunc<N, E, C>& heurFunc,
|
||||
std::unordered_map<Node<N, E>*, NList<N, E>*> resNodes) {
|
||||
std::unordered_map<Node<N, E>*, EList<N, E>*> dummyRet;
|
||||
return D::shortestPathImpl(from, to, costFunc, heurFunc, dummyRet,
|
||||
resNodes);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Node<N, E>* from, Node<N, E>* to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes) {
|
||||
if (to->getInDeg() == 0) return costFunc.inf();
|
||||
std::set<Node<N, E>*> tos;
|
||||
tos.insert(to);
|
||||
return shortestPath(from, tos, costFunc, resEdges, resNodes);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Node<N, E>* from, Node<N, E>* to,
|
||||
const CostFunc<N, E, C>& costFunc) {
|
||||
if (to->getInDeg() == 0) return costFunc.inf();
|
||||
std::set<Node<N, E>*> tos;
|
||||
tos.insert(to);
|
||||
EList<N, E>* el = 0;
|
||||
NList<N, E>* nl = 0;
|
||||
return shortestPath(from, tos, costFunc, el, nl);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Node<N, E>* from, Node<N, E>* to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
NList<N, E>* resNodes) {
|
||||
if (to->getInDeg() == 0) return costFunc.inf();
|
||||
std::set<Node<N, E>*> tos;
|
||||
tos.insert(to);
|
||||
EList<N, E>* el = 0;
|
||||
return shortestPath(from, tos, costFunc, el, resNodes);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Node<N, E>* from, Node<N, E>* to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
EList<N, E>* resEdges) {
|
||||
if (to->getInDeg() == 0) return costFunc.inf();
|
||||
std::set<Node<N, E>*> tos;
|
||||
tos.insert(to);
|
||||
NList<N, E>* nl = 0;
|
||||
return shortestPath(from, tos, costFunc, resEdges, nl);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
NList<N, E>* resNodes) {
|
||||
EList<N, E>* el = 0;
|
||||
return shortestPath(from, to, costFunc, el, resNodes);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
EList<N, E>* resEdges) {
|
||||
NList<N, E>* nl = 0;
|
||||
return shortestPath(from, to, costFunc, resEdges, nl);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Node<N, E>* from, Node<N, E>* to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
const HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges, NList<N, E>* resNodes) {
|
||||
if (to->getInDeg() == 0) return costFunc.inf();
|
||||
std::set<Node<N, E>*> tos;
|
||||
tos.insert(to);
|
||||
return D::shortestPathImpl(from, tos, costFunc, heurFunc, resEdges,
|
||||
resNodes);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Node<N, E>* from, Node<N, E>* to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
const HeurFunc<N, E, C>& heurFunc,
|
||||
NList<N, E>* resNodes) {
|
||||
if (to->getInDeg() == 0) return costFunc.inf();
|
||||
std::set<Node<N, E>*> tos;
|
||||
tos.insert(to);
|
||||
EList<N, E>* el = 0;
|
||||
return D::shortestPathImpl(from, tos, costFunc, heurFunc, el, resNodes);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Node<N, E>* from, Node<N, E>* to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
const HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges) {
|
||||
if (to->getInDeg() == 0) return costFunc.inf();
|
||||
std::set<Node<N, E>*> tos;
|
||||
tos.insert(to);
|
||||
NList<N, E>* nl = 0;
|
||||
return D::shortestPathImpl(from, tos, costFunc, heurFunc, resEdges, nl);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
const HeurFunc<N, E, C>& heurFunc,
|
||||
NList<N, E>* resNodes) {
|
||||
EList<N, E>* el = 0;
|
||||
return D::shortestPathImpl(from, to, costFunc, heurFunc, el, resNodes);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Node<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
const HeurFunc<N, E, C>& heurFunc,
|
||||
EList<N, E>* resEdges) {
|
||||
NList<N, E>* nl = 0;
|
||||
return D::shortestPathImpl(from, to, costFunc, heurFunc, resEdges, nl);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Edge<N, E>*, C> shortestPath(
|
||||
Edge<N, E>* from, const std::set<Edge<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const HeurFunc<N, E, C>& heurFunc,
|
||||
std::unordered_map<Edge<N, E>*, EList<N, E>*> resEdges,
|
||||
std::unordered_map<Edge<N, E>*, NList<N, E>*> resNodes) {
|
||||
return D::shortestPathImpl(from, to, costFunc, heurFunc, resEdges,
|
||||
resNodes);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Edge<N, E>*, C> shortestPath(
|
||||
Edge<N, E>* from, const std::set<Edge<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const HeurFunc<N, E, C>& heurFunc,
|
||||
std::unordered_map<Edge<N, E>*, EList<N, E>*> resEdges) {
|
||||
std::unordered_map<Edge<N, E>*, NList<N, E>*> dummyRet;
|
||||
return D::shortestPathImpl(from, to, costFunc, heurFunc, resEdges,
|
||||
dummyRet);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Edge<N, E>*, C> shortestPath(
|
||||
Edge<N, E>* from, const std::set<Edge<N, E>*>& to,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc,
|
||||
const HeurFunc<N, E, C>& heurFunc) {
|
||||
std::unordered_map<Edge<N, E>*, NList<N, E>*> dummyRet;
|
||||
std::unordered_map<Edge<N, E>*, EList<N, E>*> dummyRetE;
|
||||
return D::shortestPathImpl(from, to, costFunc, heurFunc, dummyRetE,
|
||||
dummyRet);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(const std::set<Edge<N, E>*>& from,
|
||||
const std::set<Edge<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
const HeurFunc<N, E, C>& heurFunc) {
|
||||
NList<N, E>* nl = 0;
|
||||
EList<N, E>* el = 0;
|
||||
return D::shortestPathImpl(from, to, costFunc, heurFunc, el, nl);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Edge<N, E>* from,
|
||||
Edge<N, E>* to,
|
||||
const CostFunc<N, E, C>& costFunc ) {
|
||||
NList<N, E>* nl = 0;
|
||||
EList<N, E>* el = 0;
|
||||
std::set<Edge<N, E>*> tos{to};
|
||||
std::set<Edge<N, E>*> froms{from};
|
||||
return D::shortestPathImpl(froms, tos, costFunc, ZeroHeurFunc<N, E, C>(), el, nl);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(const std::set<Edge<N, E>*>& from,
|
||||
const std::set<Edge<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
const HeurFunc<N, E, C>& heurFunc, EList<N, E>* el) {
|
||||
NList<N, E>* nl = 0;
|
||||
return D::shortestPathImpl(from, to, costFunc, heurFunc, el, nl);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Edge<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
const HeurFunc<N, E, C>& heurFunc, EList<N, E>* el,
|
||||
NList<N, E>* nl) {
|
||||
return D::shortestPathImpl(from, to, costFunc, heurFunc, el, nl);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Edge<N, E>* from, const std::set<Node<N, E>*>& to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
EList<N, E>* el,
|
||||
NList<N, E>* nl) {
|
||||
return D::shortestPathImpl(from, to, costFunc, ZeroHeurFunc<N, E, C>(), el,
|
||||
nl);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Edge<N, E>* from, Node<N, E>* to,
|
||||
const CostFunc<N, E, C>& costFunc,
|
||||
const HeurFunc<N, E, C>& heurFunc, EList<N, E>* el,
|
||||
NList<N, E>* nl) {
|
||||
std::set<Node<N, E>*> tos{to};
|
||||
return D::shortestPathImpl(from, tos, costFunc, heurFunc, el, nl);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static C shortestPath(Edge<N, E>* from, Node<N, E>* to,
|
||||
const CostFunc<N, E, C>& costFunc, EList<N, E>* el,
|
||||
NList<N, E>* nl) {
|
||||
std::set<Node<N, E>*> tos{to};
|
||||
return D::shortestPathImpl(from, tos, costFunc, ZeroHeurFunc<N, E, C>(), el,
|
||||
nl);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Edge<N, E>*, C> shortestPath(
|
||||
Edge<N, E>* from,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc) {
|
||||
std::set<Edge<N, E>*> froms { from };
|
||||
return D::shortestPathImpl(froms, costFunc, false);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Edge<N, E>*, C> shortestPathRev(
|
||||
Edge<N, E>* from,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc) {
|
||||
std::set<Edge<N, E>*> froms { from };
|
||||
return D::shortestPathImpl(froms, costFunc, true);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Edge<N, E>*, C> shortestPath(
|
||||
Node<N, E>* from,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc) {
|
||||
std::set<Edge<N, E>*> froms;
|
||||
froms.insert(from->getAdjListOut().begin(), from->getAdjListOut().end());
|
||||
return D::shortestPathImpl(froms, costFunc, false);
|
||||
}
|
||||
|
||||
template <typename N, typename E, typename C>
|
||||
static std::unordered_map<Edge<N, E>*, C> shortestPathRev(
|
||||
Node<N, E>* from,
|
||||
const ShortestPath::CostFunc<N, E, C>& costFunc) {
|
||||
std::set<Edge<N, E>*> froms;
|
||||
froms.insert(from->getAdjListOut().begin(), from->getAdjListOut().end());
|
||||
return D::shortestPathImpl(froms, costFunc, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UTIL_GRAPH_SHORTESTPATH_H_
|
||||
1
src/util/graph/ShortestPath.tpp
Normal file
1
src/util/graph/ShortestPath.tpp
Normal file
|
|
@ -0,0 +1 @@
|
|||
|
||||
41
src/util/graph/UndirGraph.h
Normal file
41
src/util/graph/UndirGraph.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2016, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#ifndef UTIL_GRAPH_UNDIRGRAPH_H_
|
||||
#define UTIL_GRAPH_UNDIRGRAPH_H_
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "util/graph/Graph.h"
|
||||
#include "util/graph/Edge.h"
|
||||
#include "util/graph/UndirNode.h"
|
||||
|
||||
namespace util {
|
||||
namespace graph {
|
||||
|
||||
template <typename N, typename E>
|
||||
using UndirEdge = Edge<N, E>;
|
||||
|
||||
template <typename N, typename E>
|
||||
class UndirGraph : public Graph<N, E> {
|
||||
public:
|
||||
explicit UndirGraph();
|
||||
|
||||
using Graph<N, E>::addEdg;
|
||||
|
||||
Node<N, E>* addNd();
|
||||
Node<N, E>* addNd(UndirNode<N, E>* n);
|
||||
Node<N, E>* addNd(const N& pl);
|
||||
Edge<N, E>* addEdg(Node<N, E>* from, Node<N, E>* to, const E& p);
|
||||
|
||||
Node<N, E>* mergeNds(Node<N, E>* a, Node<N, E>* b);
|
||||
|
||||
};
|
||||
|
||||
#include "util/graph/UndirGraph.tpp"
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UTIL_GRAPH_UNDIRGRAPH_H_
|
||||
59
src/util/graph/UndirGraph.tpp
Normal file
59
src/util/graph/UndirGraph.tpp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright 2016, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
UndirGraph<N, E>::UndirGraph() {}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Node<N, E>* UndirGraph<N, E>::addNd(const N& pl) {
|
||||
return addNd(new UndirNode<N, E>(pl));
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Node<N, E>* UndirGraph<N, E>::addNd() {
|
||||
return addNd(new UndirNode<N, E>());
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Node<N, E>* UndirGraph<N, E>::addNd(UndirNode<N, E>* n) {
|
||||
auto ins = Graph<N, E>::getNds()->insert(n);
|
||||
return *ins.first;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Edge<N, E>* UndirGraph<N, E>::addEdg(Node<N, E>* from, Node<N, E>* to,
|
||||
const E& p) {
|
||||
Edge<N, E>* e = Graph<N, E>::getEdg(from, to);
|
||||
if (!e) {
|
||||
e = new Edge<N, E>(from, to, p);
|
||||
from->addEdge(e);
|
||||
to->addEdge(e);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
Node<N, E>* UndirGraph<N, E>::mergeNds(Node<N, E>* a, Node<N, E>* b) {
|
||||
for (auto e : a->getAdjListOut()) {
|
||||
if (e->getTo() != b) {
|
||||
addEdg(b, e->getTo(), e->pl());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto e : a->getAdjListIn()) {
|
||||
if (e->getFrom() != b) {
|
||||
addEdg(e->getFrom(), b, e->pl());
|
||||
}
|
||||
}
|
||||
|
||||
UndirGraph<N, E>::delNd(a);
|
||||
|
||||
return b;
|
||||
}
|
||||
53
src/util/graph/UndirNode.h
Normal file
53
src/util/graph/UndirNode.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright 2016, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#ifndef UTIL_GRAPH_UNDIRNODE_H_
|
||||
#define UTIL_GRAPH_UNDIRNODE_H_
|
||||
|
||||
#include <vector>
|
||||
#include "util/graph/Node.h"
|
||||
|
||||
namespace util {
|
||||
namespace graph {
|
||||
|
||||
template <typename N, typename E>
|
||||
class UndirNode : public Node<N, E> {
|
||||
public:
|
||||
UndirNode();
|
||||
UndirNode(const N& pl);
|
||||
~UndirNode();
|
||||
|
||||
const std::vector<Edge<N, E>*>& getAdjList() const;
|
||||
const std::vector<Edge<N, E>*>& getAdjListIn() const;
|
||||
const std::vector<Edge<N, E>*>& getAdjListOut() const;
|
||||
|
||||
size_t getDeg() const;
|
||||
size_t getInDeg() const;
|
||||
size_t getOutDeg() const;
|
||||
|
||||
bool hasEdgeIn(const Edge<N, E>* e) const;
|
||||
bool hasEdgeOut(const Edge<N, E>* e) const;
|
||||
bool hasEdge(const Edge<N, E>* e) const;
|
||||
|
||||
// add edge to this node's adjacency lists
|
||||
void addEdge(Edge<N, E>* e);
|
||||
|
||||
// remove edge from this node's adjacency lists
|
||||
void removeEdge(Edge<N, E>* e);
|
||||
|
||||
N& pl();
|
||||
const N& pl() const;
|
||||
|
||||
private:
|
||||
std::vector<Edge<N, E>*> _adjList;
|
||||
N _pl;
|
||||
|
||||
bool adjContains(const Edge<N, E>* e) const;
|
||||
};
|
||||
|
||||
#include "util/graph/UndirNode.tpp"
|
||||
|
||||
}}
|
||||
|
||||
#endif // UTIL_GRAPH_UNDIRNODE_H_
|
||||
130
src/util/graph/UndirNode.tpp
Normal file
130
src/util/graph/UndirNode.tpp
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
// Copyright 2016, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
UndirNode<N, E>::UndirNode() : _pl() {
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
UndirNode<N, E>::UndirNode(const N& pl) : _pl(pl) {
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
UndirNode<N, E>::~UndirNode() {
|
||||
// delete self edges
|
||||
for (auto e = _adjList.begin(); e != _adjList.end();) {
|
||||
Edge<N, E>* eP = *e;
|
||||
if (eP->getTo() == this && eP->getFrom() == this) {
|
||||
e = _adjList.erase(e);
|
||||
delete eP;
|
||||
} else {
|
||||
e++;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto e = _adjList.begin(); e != _adjList.end(); e++) {
|
||||
Edge<N, E>* eP = *e;
|
||||
|
||||
if (eP->getTo() != this) {
|
||||
eP->getTo()->removeEdge(eP);
|
||||
}
|
||||
|
||||
if (eP->getFrom() != this) {
|
||||
eP->getFrom()->removeEdge(eP);
|
||||
}
|
||||
|
||||
delete eP;
|
||||
}
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
bool UndirNode<N, E>::hasEdgeIn(const Edge<N, E>* e) const {
|
||||
return hasEdge(e);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
bool UndirNode<N, E>::hasEdgeOut(const Edge<N, E>* e) const {
|
||||
return hasEdge(e);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
bool UndirNode<N, E>::hasEdge(const Edge<N, E>* e) const {
|
||||
return e->getFrom() == this || e->getTo() == this;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
bool UndirNode<N, E>::adjContains(const Edge<N, E>* e) const {
|
||||
for (size_t i = 0; i < _adjList.size(); i++) if (_adjList[i] == e) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
void UndirNode<N, E>::addEdge(Edge<N, E>* e) {
|
||||
if (adjContains(e)) return;
|
||||
_adjList.reserve(_adjList.size() + 1);
|
||||
_adjList.push_back(e);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
void UndirNode<N, E>::removeEdge(Edge<N, E>* e) {
|
||||
auto p = std::find(_adjList.begin(), _adjList.end(), e);
|
||||
if (p != _adjList.end()) _adjList.erase(p);
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
const std::vector<Edge<N, E>*>& UndirNode<N, E>::getAdjList() const {
|
||||
return _adjList;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
const std::vector<Edge<N, E>*>& UndirNode<N, E>::getAdjListOut() const {
|
||||
return _adjList;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
const std::vector<Edge<N, E>*>& UndirNode<N, E>::getAdjListIn() const {
|
||||
return _adjList;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
size_t UndirNode<N, E>::getDeg() const {
|
||||
return _adjList.size();
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
size_t UndirNode<N, E>::getInDeg() const {
|
||||
return getDeg();
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
size_t UndirNode<N, E>::getOutDeg() const {
|
||||
return getDeg();
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
N& UndirNode<N, E>::pl() {
|
||||
return _pl;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
template <typename N, typename E>
|
||||
const N& UndirNode<N, E>::pl() const {
|
||||
return _pl;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue