From a913b920edb48ff1104ea849769432b7ef84d714 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Uhl=C3=ADk?= <jan@uhlik.me>
Date: Thu, 29 Mar 2018 20:14:38 +0200
Subject: [PATCH] Add Directed(Multi)Graph classes.

---
 .../src/graph/directed/DirectedGraph.cpp      |  17 +
 .../src/graph/directed/DirectedGraph.hpp      | 433 ++++++++++++++++++
 .../src/graph/directed/DirectedMultiGraph.cpp |  17 +
 .../src/graph/directed/DirectedMultiGraph.hpp | 410 +++++++++++++++++
 4 files changed, 877 insertions(+)
 create mode 100644 alib2graph_data/src/graph/directed/DirectedGraph.cpp
 create mode 100644 alib2graph_data/src/graph/directed/DirectedGraph.hpp
 create mode 100644 alib2graph_data/src/graph/directed/DirectedMultiGraph.cpp
 create mode 100644 alib2graph_data/src/graph/directed/DirectedMultiGraph.hpp

diff --git a/alib2graph_data/src/graph/directed/DirectedGraph.cpp b/alib2graph_data/src/graph/directed/DirectedGraph.cpp
new file mode 100644
index 0000000000..be40f8e81d
--- /dev/null
+++ b/alib2graph_data/src/graph/directed/DirectedGraph.cpp
@@ -0,0 +1,17 @@
+// DirectedGraph.cpp
+//
+//     Created on: 04. 03. 2018
+//         Author: Jan Uhlik
+//    Modified by:
+//
+// Copyright (c) 2017 Czech Technical University in Prague | Faculty of Information Technology. All rights reserved.
+// Git repository: https://gitlab.fit.cvut.cz/algorithms-library-toolkit/automata-library
+
+#include "DirectedGraph.hpp"
+#include <registration/ValuePrinterRegistration.hpp>
+
+namespace {
+
+static auto valuePrinter = registration::ValuePrinterRegister<graph::DirectedGraph<> >();
+
+}
diff --git a/alib2graph_data/src/graph/directed/DirectedGraph.hpp b/alib2graph_data/src/graph/directed/DirectedGraph.hpp
new file mode 100644
index 0000000000..3ecb372ed5
--- /dev/null
+++ b/alib2graph_data/src/graph/directed/DirectedGraph.hpp
@@ -0,0 +1,433 @@
+// DirectedGraph.hpp
+//
+//     Created on: 30. 01. 2018
+//         Author: Jan Uhlik
+//    Modified by:
+//
+// Copyright (c) 2017 Czech Technical University in Prague | Faculty of Information Technology. All rights reserved.
+// Git repository: https://gitlab.fit.cvut.cz/algorithms-library-toolkit/automata-library
+
+#ifndef ALIB2_DIRECTEDGRAPH_HPP
+#define ALIB2_DIRECTEDGRAPH_HPP
+
+#include <alib/map>
+#include <alib/set>
+#include <alib/tuple>
+#include <alib/vector>
+#include <functional>
+#include <alib/pair>
+#include <object/Object.h>
+#include <object/UniqueObject.h>
+#include <core/normalize.hpp>
+
+#include <common/Normalize.hpp>
+#include <graph/GraphInterface.hpp>
+#include <graph/GraphFeatures.hpp>
+
+namespace graph {
+
+template<typename TNode, typename TEdge>
+class DirectedGraph : public GraphInterface<TNode, TEdge> {
+// ---------------------------------------------------------------------------------------------------------------------
+
+ public:
+  using node_type = TNode;
+  using edge_type = TEdge;
+  using normalized_type = DirectedGraph<>;
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+ protected:
+  ext::map<TNode, ext::map<TNode, TEdge>> m_succ_list;
+  ext::map<TNode, ext::map<TNode, TEdge>> m_pred_list;
+
+// =====================================================================================================================
+// Constructor, Destructor, Operators
+ public:
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  const ext::map<TNode, ext::map<TNode, TEdge>> &getSuccessorList() const &;
+  ext::map<TNode, ext::map<TNode, TEdge>> &&getSuccessorList() &&;
+
+  const ext::map<TNode, ext::map<TNode, TEdge>> &getPredecessorList() const &;
+  ext::map<TNode, ext::map<TNode, TEdge>> &&getPredecessorList() &&;
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+// =====================================================================================================================
+// ObjectBase interface
+ public:
+  GraphBase *clone() const override;
+
+  GraphBase *plunder() &&override;
+
+  int compare(const object::ObjectBase &other) const override;
+
+  virtual int compare(const DirectedGraph &other) const;
+
+  object::ObjectBase *inc() &&override;
+
+  void operator>>(std::ostream &ostream) const override;
+
+  explicit operator std::string() const override;
+
+// =====================================================================================================================
+// Graph interface
+
+ public:
+  void addNode(const TNode &n);
+  void addNode(TNode &&n);
+  template<typename ... Params>
+  void addNode(Params &&... params);
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  bool addEdge(const TEdge &e);
+  bool addEdge(TEdge &&e);
+  template<typename ... Params>
+  bool addEdge(Params &&... params);
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+// =====================================================================================================================
+// GraphInterface interface
+
+  size_t nodeCount() const override;
+  size_t edgeCount() const override;
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  ext::set<TNode> getNodes() const override;
+  ext::vector<TEdge> getEdges() const override;
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  ext::set<TNode> successors(const TNode &n) const override;
+  ext::vector<TEdge> successorEdges(const TNode &n) const override;
+  ext::set<TNode> predecessors(const TNode &n) const override;
+  ext::vector<TEdge> predecessorEdges(const TNode &n) const override;
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  std::string name() const override;
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+};
+
+// =====================================================================================================================
+
+template<typename TNode, typename TEdge>
+const ext::map<TNode, ext::map<TNode, TEdge>> &DirectedGraph<TNode, TEdge>::getSuccessorList() const &{
+  return m_succ_list;
+}
+
+template<typename TNode, typename TEdge>
+ext::map<TNode, ext::map<TNode, TEdge>> &&DirectedGraph<TNode, TEdge>::getSuccessorList() &&{
+  return std::move(m_succ_list);
+}
+
+template<typename TNode, typename TEdge>
+const ext::map<TNode, ext::map<TNode, TEdge>> &DirectedGraph<TNode, TEdge>::getPredecessorList() const &{
+  return m_pred_list;
+}
+
+template<typename TNode, typename TEdge>
+ext::map<TNode, ext::map<TNode, TEdge>> &&DirectedGraph<TNode, TEdge>::getPredecessorList() &&{
+  return std::move(m_pred_list);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode, typename TEdge>
+void DirectedGraph<TNode, TEdge>::addNode(const TNode &n) {
+  m_succ_list[n];
+  m_pred_list[n];
+}
+
+template<typename TNode, typename TEdge>
+void DirectedGraph<TNode, TEdge>::addNode(TNode &&n) {
+  m_succ_list[n];
+  m_pred_list[std::forward<TNode>(n)];
+}
+
+template<typename TNode, typename TEdge>
+template<typename... Params>
+void DirectedGraph<TNode, TEdge>::addNode(Params &&... params) {
+  addNode(TNode(std::forward<Params>(params) ...));
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode, typename TEdge>
+bool DirectedGraph<TNode, TEdge>::addEdge(const TEdge &e) {
+  if (e.first == e.second) {
+    return false;
+  }
+
+  auto search_succ = m_succ_list.find(e.first);
+  if (search_succ != m_succ_list.end() && search_succ->second.find(e.second) != search_succ->second.end()) {
+    return false;
+  }
+
+  addNode(e.first);
+  addNode(e.second);
+  m_succ_list[e.first].insert(ext::make_pair(e.second, e));
+  m_pred_list[e.second].insert(ext::make_pair(e.first, e));
+
+  return true;
+}
+
+template<typename TNode, typename TEdge>
+bool DirectedGraph<TNode, TEdge>::addEdge(TEdge &&e) {
+  if (e.first == e.second) {
+    return false;
+  }
+
+  auto search_succ = m_succ_list.find(e.first);
+  if (search_succ != m_succ_list.end() && search_succ->second.find(e.second) != search_succ->second.end()) {
+    return false;
+  }
+
+  addNode(e.first);
+  addNode(e.second);
+  m_succ_list[e.first].insert(ext::make_pair(e.second, e));
+  m_pred_list[e.second].insert(ext::make_pair(e.first, std::forward<TEdge>(e)));
+
+  return true;
+}
+
+template<typename TNode, typename TEdge>
+template<typename... Params>
+bool DirectedGraph<TNode, TEdge>::addEdge(Params &&... params) {
+  return addEdge(TEdge(std::forward<Params>(params) ...));
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode, typename TEdge>
+size_t DirectedGraph<TNode, TEdge>::nodeCount() const {
+  return m_succ_list.size();
+}
+template<typename TNode, typename TEdge>
+size_t DirectedGraph<TNode, TEdge>::edgeCount() const {
+  size_t cnt = 0;
+
+  for (const auto &i: m_succ_list) {
+    cnt += i.second.size();
+  }
+
+  return cnt;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode, typename TEdge>
+ext::set<TNode> DirectedGraph<TNode, TEdge>::getNodes() const {
+  ext::set<TNode> set;
+
+  for (const auto &i: m_succ_list) {
+    set.insert(i.first);
+  }
+
+  return set;
+}
+
+template<typename TNode, typename TEdge>
+ext::vector<TEdge> DirectedGraph<TNode, TEdge>::getEdges() const {
+  ext::vector<TEdge> vec;
+
+  for (const auto &i: m_succ_list) {
+    for (const auto &j : i.second) {
+      vec.push_back(j.second);
+    }
+  }
+
+  return vec;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode, typename TEdge>
+ext::set<TNode> DirectedGraph<TNode, TEdge>::successors(const TNode &n) const {
+  ext::set<TNode> set;
+
+  if (m_succ_list.count(n) == 0) {
+    return set;
+  }
+
+  for (const auto &i: m_succ_list.at(n)) {
+    set.insert(i.first);
+  }
+
+  return set;
+}
+
+template<typename TNode, typename TEdge>
+ext::vector<TEdge> DirectedGraph<TNode, TEdge>::successorEdges(const TNode &n) const {
+  ext::vector<TEdge> vec;
+
+  if (m_succ_list.count(n) == 0) {
+    return vec;
+  }
+
+  for (const auto &i: m_succ_list.at(n)) {
+    vec.push_back(i.second);
+  }
+
+  return vec;
+}
+
+template<typename TNode, typename TEdge>
+ext::set<TNode> DirectedGraph<TNode, TEdge>::predecessors(const TNode &n) const {
+  ext::set<TNode> set;
+
+  if (m_pred_list.count(n) == 0) {
+    return set;
+  }
+
+  for (const auto &i: m_pred_list.at(n)) {
+    set.insert(i.first);
+  }
+
+  return set;
+}
+
+template<typename TNode, typename TEdge>
+ext::vector<TEdge> DirectedGraph<TNode, TEdge>::predecessorEdges(const TNode &n) const {
+  ext::vector<TEdge> vec;
+
+  if (m_pred_list.count(n) == 0) {
+    return vec;
+  }
+
+  for (const auto &i: m_pred_list.at(n)) {
+    vec.push_back(i.second);
+  }
+
+  return vec;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode, typename TEdge>
+std::string DirectedGraph<TNode, TEdge>::name() const {
+  return "DirectedGraph";
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode, typename TEdge>
+GraphBase *DirectedGraph<TNode, TEdge>::clone() const {
+  return new DirectedGraph(*this);
+}
+
+template<typename TNode, typename TEdge>
+GraphBase *DirectedGraph<TNode, TEdge>::plunder() &&{
+  return new DirectedGraph(std::move(*this));
+}
+
+template<typename TNode, typename TEdge>
+int DirectedGraph<TNode, TEdge>::compare(const object::ObjectBase &other) const {
+  if (ext::type_index(typeid(*this)) == ext::type_index(typeid(other))) return this->compare((decltype(*this)) other);
+  return ext::type_index(typeid(*this)) - ext::type_index(typeid(other));
+}
+
+template<typename TNode, typename TEdge>
+int DirectedGraph<TNode, TEdge>::compare(const DirectedGraph &other) const {
+  auto first = ext::tie(m_succ_list, m_pred_list);
+  auto second = ext::tie(other.getSuccessorList(), other.getPredecessorList());
+
+  static ext::compare<decltype(first)> comp;
+
+  return comp(first, second);
+}
+
+template<typename TNode, typename TEdge>
+object::ObjectBase *DirectedGraph<TNode, TEdge>::inc() &&{
+  return new object::UniqueObject(object::Object(std::move(*this)), primitive::Integer(0));
+}
+
+template<typename TNode, typename TEdge>
+void DirectedGraph<TNode, TEdge>::operator>>(std::ostream &ostream) const {
+  ostream << "(" << name() << " ";
+  for (const auto &i : m_succ_list) {
+    ostream << i.first << "  -->" << std::endl;
+
+    for (const auto &j : i.second) {
+      ostream << "\t\t" << j.first << " " << j.second << std::endl;
+    }
+  }
+  ostream << ")";
+}
+
+template<typename TNode, typename TEdge>
+DirectedGraph<TNode, TEdge>::operator std::string() const {
+  std::stringstream ss;
+  ss << "<";
+  for (const auto &i : m_succ_list) {
+    ss << i.first << "  -->" << std::endl;
+
+    for (const auto &j : i.second) {
+      ss << "\t\t" << j.first << " " << j.second << std::endl;
+    }
+  }
+  ss << ">";
+  return std::move(ss).str();
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+} // namespace graph
+
+// =====================================================================================================================
+
+namespace core {
+
+/**
+ * Helper for normalisation of types specified by templates used as internal datatypes of symbols and states.
+ *
+ * \returns new instance of the graph with default template parameters or unmodified instance if the template parameters were already the default ones
+ */
+
+template<typename TNode, typename TEdge>
+struct normalize<graph::DirectedGraph<TNode, TEdge>, typename std::enable_if<!std::is_same<
+    graph::DirectedGraph<TNode, TEdge>, graph::DirectedGraph<> >::value>::type> {
+  static graph::DirectedGraph<> eval(graph::DirectedGraph<TNode, TEdge> &&value) {
+    graph::DirectedGraph<> graph;
+
+    // Create successor
+    for (auto &&i: ext::make_moveable_map(std::move(value).getSuccessorList())) {
+      DefaultNodeType first = common::Normalize::normalizeNode(std::move(i.first));
+      for (auto &&j: i.second) {
+        DefaultNodeType second = common::Normalize::normalizeNode(std::move(j.first));
+        DefaultEdgeType edge = common::Normalize::normalizeEdge(std::move(j.second));
+
+        graph.addNode(first);
+        graph.addNode(second);
+        graph.addEdge(edge);
+      }
+    }
+
+    // Create predecessors
+    for (auto &&i: ext::make_moveable_map(std::move(value).getPredecessorList())) {
+      DefaultNodeType first = common::Normalize::normalizeNode(std::move(i.first));
+      for (auto &&j: i.second) {
+        DefaultNodeType second = common::Normalize::normalizeNode(std::move(j.first));
+        DefaultEdgeType edge = common::Normalize::normalizeEdge(std::move(j.second));
+
+        graph.addNode(first);
+        graph.addNode(second);
+        graph.addEdge(edge);
+      }
+    }
+
+    return graph;
+  }
+};
+
+}
+
+// =====================================================================================================================
+#endif //ALIB2_DIRECTEDGRAPH_HPP
diff --git a/alib2graph_data/src/graph/directed/DirectedMultiGraph.cpp b/alib2graph_data/src/graph/directed/DirectedMultiGraph.cpp
new file mode 100644
index 0000000000..3ca8e1b13f
--- /dev/null
+++ b/alib2graph_data/src/graph/directed/DirectedMultiGraph.cpp
@@ -0,0 +1,17 @@
+// DirectedMultiGraph.cpp
+//
+//     Created on: 04. 03. 2018
+//         Author: Jan Uhlik
+//    Modified by:
+//
+// Copyright (c) 2017 Czech Technical University in Prague | Faculty of Information Technology. All rights reserved.
+// Git repository: https://gitlab.fit.cvut.cz/algorithms-library-toolkit/automata-library
+
+#include "DirectedMultiGraph.hpp"
+#include <registration/ValuePrinterRegistration.hpp>
+
+namespace {
+
+static auto valuePrinter = registration::ValuePrinterRegister<graph::DirectedMultiGraph<> >();
+
+}
diff --git a/alib2graph_data/src/graph/directed/DirectedMultiGraph.hpp b/alib2graph_data/src/graph/directed/DirectedMultiGraph.hpp
new file mode 100644
index 0000000000..1898e1f349
--- /dev/null
+++ b/alib2graph_data/src/graph/directed/DirectedMultiGraph.hpp
@@ -0,0 +1,410 @@
+// DirectedMultiGraph.hpp
+//
+//     Created on: 05. 02. 2018
+//         Author: Jan Uhlik
+//    Modified by:
+//
+// Copyright (c) 2017 Czech Technical University in Prague | Faculty of Information Technology. All rights reserved.
+// Git repository: https://gitlab.fit.cvut.cz/algorithms-library-toolkit/automata-library
+
+#ifndef ALIB2_DIRECTEDMULTIGRAPH_HPP
+#define ALIB2_DIRECTEDMULTIGRAPH_HPP
+
+#include <alib/map>
+#include <alib/set>
+#include <alib/vector>
+#include <alib/tuple>
+#include <functional>
+#include <alib/pair>
+#include <object/Object.h>
+#include <object/UniqueObject.h>
+#include <core/normalize.hpp>
+
+#include <common/Normalize.hpp>
+#include <graph/GraphInterface.hpp>
+#include <graph/GraphFeatures.hpp>
+
+namespace graph {
+
+template<typename TNode, typename TEdge>
+class DirectedMultiGraph : public GraphInterface<TNode, TEdge> {
+// ---------------------------------------------------------------------------------------------------------------------
+
+ public:
+  using node_type = TNode;
+  using edge_type = TEdge;
+  using normalized_type = DirectedMultiGraph<>;
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+ protected:
+  ext::map<TNode, std::multimap<TNode, TEdge>> m_succ_list;
+  ext::map<TNode, std::multimap<TNode, TEdge>> m_pred_list;
+
+// =====================================================================================================================
+// Constructor, Destructor, Operators
+ public:
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  const ext::map<TNode, std::multimap<TNode, TEdge>> &getSuccessorList() const &;
+  ext::map<TNode, std::multimap<TNode, TEdge>> &&getSuccessorList() &&;
+
+  const ext::map<TNode, std::multimap<TNode, TEdge>> &getPredecessorList() const &;
+  ext::map<TNode, std::multimap<TNode, TEdge>> &&getPredecessorList() &&;
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+// =====================================================================================================================
+// ObjectBase interface
+ public:
+  GraphBase *clone() const override;
+
+  GraphBase *plunder() &&override;
+
+  int compare(const object::ObjectBase &other) const override;
+
+  virtual int compare(const DirectedMultiGraph &other) const;
+
+  object::ObjectBase *inc() &&override;
+
+  void operator>>(std::ostream &ostream) const override;
+
+  explicit operator std::string() const override;
+
+// =====================================================================================================================
+// Graph interface
+
+ public:
+  virtual void addNode(const TNode &n);
+  virtual void addNode(TNode &&n);
+  template<typename ... Params>
+  void addNode(Params &&... params);
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  virtual bool addEdge(const TEdge &e);
+  virtual bool addEdge(TEdge &&e);
+  template<typename ... Params>
+  bool addEdge(Params &&... params);
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+// =====================================================================================================================
+// GraphInterface interface
+
+  size_t nodeCount() const override;
+  size_t edgeCount() const override;
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  ext::set<TNode> getNodes() const override;
+  ext::vector<TEdge> getEdges() const override;
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  ext::set<TNode> successors(const TNode &n) const override;
+  ext::vector<TEdge> successorEdges(const TNode &n) const override;
+  ext::set<TNode> predecessors(const TNode &n) const override;
+  ext::vector<TEdge> predecessorEdges(const TNode &n) const override;
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+  std::string name() const override;
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+};
+
+// =====================================================================================================================
+
+template<typename TNode, typename TEdge>
+const ext::map<TNode, std::multimap<TNode, TEdge>> &DirectedMultiGraph<TNode, TEdge>::getSuccessorList() const &{
+  return m_succ_list;
+}
+
+template<typename TNode, typename TEdge>
+ext::map<TNode, std::multimap<TNode, TEdge>> &&DirectedMultiGraph<TNode, TEdge>::getSuccessorList() &&{
+  return std::move(m_succ_list);
+}
+
+template<typename TNode, typename TEdge>
+const ext::map<TNode, std::multimap<TNode, TEdge>> &DirectedMultiGraph<TNode, TEdge>::getPredecessorList() const &{
+  return m_pred_list;
+}
+
+template<typename TNode, typename TEdge>
+ext::map<TNode, std::multimap<TNode, TEdge>> &&DirectedMultiGraph<TNode, TEdge>::getPredecessorList() &&{
+  return std::move(m_pred_list);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode, typename TEdge>
+void DirectedMultiGraph<TNode, TEdge>::addNode(const TNode &n) {
+  m_succ_list[n];
+  m_pred_list[n];
+}
+
+template<typename TNode, typename TEdge>
+void DirectedMultiGraph<TNode, TEdge>::addNode(TNode &&n) {
+  m_succ_list[n];
+  m_pred_list[std::forward<TNode>(n)];
+}
+
+template<typename TNode, typename TEdge>
+template<typename... Params>
+void DirectedMultiGraph<TNode, TEdge>::addNode(Params &&... params) {
+  addNode(TNode(std::forward<Params>(params) ...));
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode, typename TEdge>
+bool DirectedMultiGraph<TNode, TEdge>::addEdge(const TEdge &e) {
+  m_succ_list[e.first].insert(ext::make_pair(e.second, e));
+  m_pred_list[e.second].insert(ext::make_pair(e.first, e));
+  return true;
+}
+
+template<typename TNode, typename TEdge>
+bool DirectedMultiGraph<TNode, TEdge>::addEdge(TEdge &&e) {
+  m_succ_list[e.first].insert(ext::make_pair(e.second, e));
+  m_pred_list[e.second].insert(ext::make_pair(e.first, std::forward<TEdge>(e)));
+  return true;
+}
+
+template<typename TNode, typename TEdge>
+template<typename... Params>
+bool DirectedMultiGraph<TNode, TEdge>::addEdge(Params &&... params) {
+  return addEdge(TEdge(std::forward<Params>(params) ...));
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode, typename TEdge>
+size_t DirectedMultiGraph<TNode, TEdge>::nodeCount() const {
+  return m_succ_list.size();
+}
+template<typename TNode, typename TEdge>
+size_t DirectedMultiGraph<TNode, TEdge>::edgeCount() const {
+  size_t cnt = 0;
+
+  for (const auto &i: m_succ_list) {
+    cnt += i.second.size();
+  }
+
+  return cnt;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode, typename TEdge>
+ext::set<TNode> DirectedMultiGraph<TNode, TEdge>::getNodes() const {
+  ext::set<TNode> set;
+
+  for (const auto &i: m_succ_list) {
+    set.insert(i.first);
+  }
+
+  return set;
+}
+
+template<typename TNode, typename TEdge>
+ext::vector<TEdge> DirectedMultiGraph<TNode, TEdge>::getEdges() const {
+  ext::vector<TEdge> vec;
+
+  for (const auto &i: m_succ_list) {
+    for (const auto &j : i.second) {
+      vec.push_back(j.second);
+    }
+  }
+
+  return vec;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode, typename TEdge>
+ext::set<TNode> DirectedMultiGraph<TNode, TEdge>::successors(const TNode &n) const {
+  ext::set<TNode> set;
+
+  if (m_succ_list.count(n) == 0) {
+    return set;
+  }
+
+  for (const auto &i: m_succ_list.at(n)) {
+    set.insert(i.first);
+  }
+
+  return set;
+}
+
+template<typename TNode, typename TEdge>
+ext::vector<TEdge> DirectedMultiGraph<TNode, TEdge>::successorEdges(const TNode &n) const {
+  ext::vector<TEdge> vec;
+
+  if (m_succ_list.count(n) == 0) {
+    return vec;
+  }
+
+  for (const auto &i: m_succ_list.at(n)) {
+    vec.push_back(i.second);
+  }
+
+  return vec;
+}
+
+template<typename TNode, typename TEdge>
+ext::set<TNode> DirectedMultiGraph<TNode, TEdge>::predecessors(const TNode &n) const {
+  ext::set<TNode> set;
+
+  if (m_pred_list.count(n) == 0) {
+    return set;
+  }
+
+  for (const auto &i: m_pred_list.at(n)) {
+    set.insert(i.first);
+  }
+
+  return set;
+}
+
+template<typename TNode, typename TEdge>
+ext::vector<TEdge> DirectedMultiGraph<TNode, TEdge>::predecessorEdges(const TNode &n) const {
+  ext::vector<TEdge> vec;
+
+  if (m_pred_list.count(n) == 0) {
+    return vec;
+  }
+
+  for (const auto &i: m_pred_list.at(n)) {
+    vec.push_back(i.second);
+  }
+
+  return vec;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode, typename TEdge>
+std::string DirectedMultiGraph<TNode, TEdge>::name() const {
+  return "DirectedMultiGraph";
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+template<typename TNode, typename TEdge>
+GraphBase *DirectedMultiGraph<TNode, TEdge>::clone() const {
+  return new DirectedMultiGraph(*this);
+}
+
+template<typename TNode, typename TEdge>
+GraphBase *DirectedMultiGraph<TNode, TEdge>::plunder() &&{
+  return new DirectedMultiGraph(std::move(*this));
+}
+
+template<typename TNode, typename TEdge>
+int DirectedMultiGraph<TNode, TEdge>::compare(const object::ObjectBase &other) const {
+  if (ext::type_index(typeid(*this)) == ext::type_index(typeid(other))) return this->compare((decltype(*this)) other);
+  return ext::type_index(typeid(*this)) - ext::type_index(typeid(other));
+}
+
+template<typename TNode, typename TEdge>
+int DirectedMultiGraph<TNode, TEdge>::compare(const DirectedMultiGraph &other) const {
+  auto first = ext::tie(m_succ_list, m_pred_list);
+  auto second = ext::tie(other.getSuccessorList(), other.getPredecessorList());
+
+  static ext::compare<decltype(first)> comp;
+
+  return comp(first, second);
+}
+
+template<typename TNode, typename TEdge>
+object::ObjectBase *DirectedMultiGraph<TNode, TEdge>::inc() &&{
+  return new object::UniqueObject(object::Object(std::move(*this)), primitive::Integer(0));
+}
+
+template<typename TNode, typename TEdge>
+void DirectedMultiGraph<TNode, TEdge>::operator>>(std::ostream &ostream) const {
+  ostream << "(" << name() << " ";
+  for (const auto &i : m_succ_list) {
+    ostream << i.first << "  -->" << std::endl;
+
+    for (const auto &j : i.second) {
+      ostream << "\t\t" << j.first << " " << j.second << std::endl;
+    }
+  }
+  ostream << ")";
+}
+
+template<typename TNode, typename TEdge>
+DirectedMultiGraph<TNode, TEdge>::operator std::string() const {
+  std::stringstream ss;
+  ss << "<";
+  for (const auto &i : m_succ_list) {
+    ss << i.first << "  -->" << std::endl;
+
+    for (const auto &j : i.second) {
+      ss << "\t\t" << j.first << " " << j.second << std::endl;
+    }
+  }
+  ss << ">";
+  return std::move(ss).str();
+}
+// ---------------------------------------------------------------------------------------------------------------------
+
+} // namespace graph
+
+// =====================================================================================================================
+
+namespace core {
+
+/**
+ * Helper for normalisation of types specified by templates used as internal datatypes of symbols and states.
+ *
+ * \returns new instance of the graph with default template parameters or unmodified instance if the template parameters were already the default ones
+ */
+
+template<typename TNode, typename TEdge>
+struct normalize<graph::DirectedMultiGraph<TNode, TEdge>, typename std::enable_if<!std::is_same<
+    graph::DirectedMultiGraph<TNode, TEdge>, graph::DirectedMultiGraph<> >::value>::type> {
+  static graph::DirectedMultiGraph<> eval(graph::DirectedMultiGraph<TNode, TEdge> &&value) {
+    graph::DirectedMultiGraph<> graph;
+
+    // Create successor
+    for (auto &&i: ext::make_moveable_map(std::move(value).getSuccessorList())) {
+      DefaultNodeType first = common::Normalize::normalizeNode(std::move(i.first));
+      for (auto &&j: i.second) {
+        DefaultNodeType second = common::Normalize::normalizeNode(std::move(j.first));
+        DefaultEdgeType edge = common::Normalize::normalizeEdge(std::move(j.second));
+
+        graph.addNode(first);
+        graph.addNode(second);
+        graph.addEdge(edge);
+      }
+    }
+
+    // Create predecessors
+    for (auto &&i: ext::make_moveable_map(std::move(value).getPredecessorList())) {
+      DefaultNodeType first = common::Normalize::normalizeNode(std::move(i.first));
+      for (auto &&j: i.second) {
+        DefaultNodeType second = common::Normalize::normalizeNode(std::move(j.first));
+        DefaultEdgeType edge = common::Normalize::normalizeEdge(std::move(j.second));
+
+        graph.addNode(first);
+        graph.addNode(second);
+        graph.addEdge(edge);
+      }
+    }
+
+    return graph;
+  }
+};
+
+// ---------------------------------------------------------------------------------------------------------------------
+
+}
+
+// =====================================================================================================================
+#endif //ALIB2_DIRECTEDMULTIGRAPH_HPP
-- 
GitLab