initial commit

This commit is contained in:
Patrick Brosi 2018-06-09 17:14:08 +02:00
commit efcd3e1892
106 changed files with 27000 additions and 0 deletions

View 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
View 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
View 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
View 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_

View 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
View 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
View 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;
}

View 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
View 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_

View 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
View 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
View 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
View 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
View 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
View 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_

View 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_

View file

@ -0,0 +1 @@

View 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_

View 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;
}

View 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_

View 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;
}