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