diff --git a/alib2graph_data/src/graph/GraphBase.hpp b/alib2graph_data/src/graph/GraphBase.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ef3e66e71e44d2c8ea0551124631c9a9b5b36430 --- /dev/null +++ b/alib2graph_data/src/graph/GraphBase.hpp @@ -0,0 +1,32 @@ +// GraphBase.hpp +// +// Created on: 28. 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_GRAPHBASE_HPP +#define ALIB2_GRAPHBASE_HPP + +#include <object/ObjectBase.h> + +namespace graph { + +/** + * Represents graph. + */ +class GraphBase : public object::ObjectBase { +// --------------------------------------------------------------------------------------------------------------------- + + public: + virtual GraphBase *clone() const = 0; + virtual GraphBase *plunder() &&= 0; + +// --------------------------------------------------------------------------------------------------------------------- +}; + +} // namespace graph + +#endif //ALIB2_GRAPHBASE_HPP diff --git a/alib2graph_data/src/graph/GraphFeatures.hpp b/alib2graph_data/src/graph/GraphFeatures.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0e3f7c3ab9603d724efcbd0344400466563157bd --- /dev/null +++ b/alib2graph_data/src/graph/GraphFeatures.hpp @@ -0,0 +1,42 @@ +// GraphFeatures.hpp +// +// Created on: 01. 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 + +#ifndef ALIB2_GRAPHFEATURES_HPP +#define ALIB2_GRAPHFEATURES_HPP + +#include <common/DefaultTypes.hpp> + +namespace graph { + +class GraphBase; + +template<typename TNode = DefaultNodeType, typename = DefaultEdgeType> +class GraphInterface; + +template<typename TNode = DefaultNodeType, typename = DefaultEdgeType> +class UndirectedGraph; + +template<typename TNode = DefaultNodeType, typename = DefaultEdgeType> +class UndirectedMultiGraph; + +template<typename TNode = DefaultNodeType, typename = DefaultEdgeType> +class DirectedGraph; + +template<typename TNode = DefaultNodeType, typename = DefaultEdgeType> +class DirectedMultiGraph; + +template<typename TNode = DefaultNodeType, typename = DefaultEdgeType> +class MixedGraph; + +template<typename TNode = DefaultNodeType, typename = DefaultEdgeType> +class MixedMultiGraph; + +} // namespace graph + +#endif //ALIB2_GRAPHFEATURES_HPP diff --git a/alib2graph_data/src/graph/GraphInterface.hpp b/alib2graph_data/src/graph/GraphInterface.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d9c6b39d00f792b853e7b1af8bdeb695cc4bd653 --- /dev/null +++ b/alib2graph_data/src/graph/GraphInterface.hpp @@ -0,0 +1,56 @@ +// GraphInterface.hpp +// +// Created on: 29. 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_GENERALGRAPH_HPP +#define ALIB2_GENERALGRAPH_HPP + +#include <alib/set> +#include <alib/vector> +#include <functional> + +#include "GraphBase.hpp" + +namespace graph { + +template<typename TNode, typename TEdge> +class GraphInterface : public GraphBase { +// --------------------------------------------------------------------------------------------------------------------- + public: + using node_type = TNode; + using edge_type = TEdge; + +// --------------------------------------------------------------------------------------------------------------------- + + virtual size_t nodeCount() const = 0; + virtual size_t edgeCount() const = 0; + +// --------------------------------------------------------------------------------------------------------------------- + + virtual ext::set<TNode> getNodes() const = 0; + virtual ext::vector<TEdge> getEdges() const = 0; + +// --------------------------------------------------------------------------------------------------------------------- + + virtual ext::set<TNode> successors(const TNode &n) const = 0; + virtual ext::vector<TEdge> successorEdges(const TNode &n) const = 0; + virtual ext::set<TNode> predecessors(const TNode &n) const = 0; + virtual ext::vector<TEdge> predecessorEdges(const TNode &n) const = 0; + +// --------------------------------------------------------------------------------------------------------------------- + + virtual std::string name() const = 0; + +// --------------------------------------------------------------------------------------------------------------------- +}; + +// ===================================================================================================================== + +} + +#endif //ALIB2_GENERALGRAPH_HPP diff --git a/alib2graph_data/src/graph/undirected/UndirectedGraph.cpp b/alib2graph_data/src/graph/undirected/UndirectedGraph.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc233709ddd423dec341274082dc11f00aeb83f3 --- /dev/null +++ b/alib2graph_data/src/graph/undirected/UndirectedGraph.cpp @@ -0,0 +1,17 @@ +// UndirectedGraph.cpp +// +// Created on: 28. 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 + +#include "UndirectedGraph.hpp" +#include <registration/ValuePrinterRegistration.hpp> + +namespace { + +static auto valuePrinter = registration::ValuePrinterRegister<graph::UndirectedGraph<> >(); + +} diff --git a/alib2graph_data/src/graph/undirected/UndirectedGraph.hpp b/alib2graph_data/src/graph/undirected/UndirectedGraph.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a082437d4b6e72f45f79deabe0a78fb1ba7f6173 --- /dev/null +++ b/alib2graph_data/src/graph/undirected/UndirectedGraph.hpp @@ -0,0 +1,385 @@ +// UndirectedGraph.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_UNDIRECTEDGRAPH_HPP +#define ALIB2_UNDIRECTEDGRAPH_HPP + +#include <alib/map> +#include <alib/pair> +#include <alib/set> +#include <alib/vector> +#include <functional> +#include <object/Object.h> +#include <object/UniqueObject.h> +#include <core/normalize.hpp> +#include <alib/tuple> + +#include <common/Normalize.hpp> +#include <graph/GraphInterface.hpp> +#include <graph/GraphFeatures.hpp> + +namespace graph { + +template<typename TNode, typename TEdge> +class UndirectedGraph : public GraphInterface<TNode, TEdge> { +// --------------------------------------------------------------------------------------------------------------------- + + public: + using node_type = TNode; + using edge_type = TEdge; + using normalized_type = UndirectedGraph<>; + +// --------------------------------------------------------------------------------------------------------------------- + + protected: + ext::map<TNode, ext::map<TNode, TEdge>> m_adjacency_list; + +// ===================================================================================================================== +// Constructor, Destructor, Operators + public: + +// --------------------------------------------------------------------------------------------------------------------- + + const ext::map<TNode, ext::map<TNode, TEdge>> &getAdjacencyList() const &; + + ext::map<TNode, ext::map<TNode, TEdge>> &&getAdjacencyList() &&; + +// --------------------------------------------------------------------------------------------------------------------- + +// ===================================================================================================================== +// ObjectBase interface + public: + GraphBase *clone() const override; + + GraphBase *plunder() &&override; + + int compare(const object::ObjectBase &other) const override; + + virtual int compare(const UndirectedGraph &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 + public: + + 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>> &UndirectedGraph<TNode, + TEdge>::getAdjacencyList() const &{ + return m_adjacency_list; +} + +template<typename TNode, typename TEdge> +ext::map<TNode, ext::map<TNode, TEdge>> &&UndirectedGraph<TNode, TEdge>::getAdjacencyList() &&{ + return std::move(m_adjacency_list); +} + + +// --------------------------------------------------------------------------------------------------------------------- + +template<typename TNode, typename TEdge> +void UndirectedGraph<TNode, TEdge>::addNode(const TNode &n) { + m_adjacency_list[n]; +} + +template<typename TNode, typename TEdge> +void UndirectedGraph<TNode, TEdge>::addNode(TNode &&n) { + m_adjacency_list[std::forward<TNode>(n)]; +} + +template<typename TNode, typename TEdge> +template<typename... Params> +void UndirectedGraph<TNode, TEdge>::addNode(Params &&... params) { + addNode(TNode(std::forward<Params>(params) ...)); +} + +// --------------------------------------------------------------------------------------------------------------------- + +template<typename TNode, typename TEdge> +bool UndirectedGraph<TNode, TEdge>::addEdge(const TEdge &e) { + if (e.first == e.second) { + return false; + } + + if (m_adjacency_list.find(e.first) != m_adjacency_list.end() + && m_adjacency_list[e.first].find(e.second) != m_adjacency_list[e.first].end()) { + return false; + } + + m_adjacency_list[e.first].insert(ext::make_pair(e.second, e)); + m_adjacency_list[e.second].insert(ext::make_pair(e.first, e)); + + return true; +} + +template<typename TNode, typename TEdge> +bool UndirectedGraph<TNode, TEdge>::addEdge(TEdge &&e) { + if (e.first == e.second) { + return false; + } + + if (m_adjacency_list.find(e.first) != m_adjacency_list.end() + && m_adjacency_list[e.first].find(e.second) != m_adjacency_list[e.first].end()) { + return false; + } + + m_adjacency_list[e.first].insert(ext::make_pair(e.second, e)); + m_adjacency_list[e.second].insert(ext::make_pair(e.first, std::forward<TEdge>(e))); + + return true; +} + +template<typename TNode, typename TEdge> +template<typename... Params> +bool UndirectedGraph<TNode, TEdge>::addEdge(Params &&... params) { + return addEdge(TEdge(std::forward<Params>(params) ...)); +} + +// --------------------------------------------------------------------------------------------------------------------- + +template<typename TNode, typename TEdge> +size_t UndirectedGraph<TNode, TEdge>::nodeCount() const { + return m_adjacency_list.size(); +} + +template<typename TNode, typename TEdge> +size_t UndirectedGraph<TNode, TEdge>::edgeCount() const { + size_t cnt = 0; + + for (const auto &i: m_adjacency_list) { + cnt += i.second.size(); + } + + return cnt / 2; +} + +// --------------------------------------------------------------------------------------------------------------------- + +template<typename TNode, typename TEdge> +ext::set<TNode> UndirectedGraph<TNode, TEdge>::getNodes() const { + ext::set<TNode> set; + + for (const auto &i: m_adjacency_list) { + set.insert(i.first); + } + + return set; +} + +template<typename TNode, typename TEdge> +ext::vector<TEdge> UndirectedGraph<TNode, TEdge>::getEdges() const { + ext::vector<TEdge> vec; + + for (const auto &i:m_adjacency_list) { + for (const auto &j : i.second) { + vec.push_back(j.second); + } + } + + return vec; +} + +// --------------------------------------------------------------------------------------------------------------------- + +template<typename TNode, typename TEdge> +ext::set<TNode> UndirectedGraph<TNode, TEdge>::successors(const TNode &n) const { + ext::set<TNode> set; + + if (m_adjacency_list.count(n) == 0) { + return set; + } + + for (const auto &i: m_adjacency_list.at(n)) { + set.insert(i.first); + } + + return set; +} + +template<typename TNode, typename TEdge> +ext::vector<TEdge> UndirectedGraph<TNode, TEdge>::successorEdges(const TNode &n) const { + ext::vector<TEdge> vec; + + if (m_adjacency_list.count(n) == 0) { + return vec; + } + + for (const auto &i: m_adjacency_list.at(n)) { + vec.push_back(i.second); + } + + return vec; +} + +template<typename TNode, typename TEdge> +ext::set<TNode> UndirectedGraph<TNode, TEdge>::predecessors(const TNode &n) const { + return successors(n); +} + +template<typename TNode, typename TEdge> +ext::vector<TEdge> UndirectedGraph<TNode, TEdge>::predecessorEdges(const TNode &n) const { + return successorEdges(n); +} + +// --------------------------------------------------------------------------------------------------------------------- + +template<typename TNode, typename TEdge> +std::string UndirectedGraph<TNode, TEdge>::name() const { + return "UndirectedGraph"; +} + +// --------------------------------------------------------------------------------------------------------------------- + +template<typename TNode, typename TEdge> +GraphBase *UndirectedGraph<TNode, TEdge>::clone() const { + return new UndirectedGraph(*this); +} + +template<typename TNode, typename TEdge> +GraphBase *UndirectedGraph<TNode, TEdge>::plunder() &&{ + return new UndirectedGraph(std::move(*this)); +} + +template<typename TNode, typename TEdge> +int UndirectedGraph<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 UndirectedGraph<TNode, TEdge>::compare(const UndirectedGraph &other) const { + auto first = ext::tie(m_adjacency_list); + auto second = ext::tie(other.getAdjacencyList()); + + static ext::compare<decltype(first)> comp; + + return comp(first, second); +} + +template<typename TNode, typename TEdge> +object::ObjectBase *UndirectedGraph<TNode, TEdge>::inc() &&{ + return new object::UniqueObject(object::Object(std::move(*this)), primitive::Integer(0)); +} + +template<typename TNode, typename TEdge> +void UndirectedGraph<TNode, TEdge>::operator>>(std::ostream &ostream) const { + ostream << "(" << name() << " "; + for (const auto &i : m_adjacency_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> +UndirectedGraph<TNode, TEdge>::operator std::string() const { + std::stringstream ss; + ss << "<"; + for (const auto &i : m_adjacency_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::UndirectedGraph<TNode, TEdge>, typename std::enable_if<!std::is_same< + graph::UndirectedGraph<TNode, TEdge>, graph::UndirectedGraph<> >::value>::type> { + static graph::UndirectedGraph<> eval(graph::UndirectedGraph<TNode, TEdge> &&value) { + graph::UndirectedGraph<> graph; + + for (auto &&i: ext::make_moveable_map(std::move(value).getAdjacencyList())) { + 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_UNDIRECTEDGRAPH_HPP diff --git a/alib2graph_data/src/graph/undirected/UndirectedMultiGraph.cpp b/alib2graph_data/src/graph/undirected/UndirectedMultiGraph.cpp new file mode 100644 index 0000000000000000000000000000000000000000..07460c1f170d07a0f27fb68c01e2c0b8d28fe3ac --- /dev/null +++ b/alib2graph_data/src/graph/undirected/UndirectedMultiGraph.cpp @@ -0,0 +1,17 @@ +// UndirectedMultiGraph.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 "UndirectedMultiGraph.hpp" +#include <registration/ValuePrinterRegistration.hpp> + +namespace { + +static auto valuePrinter = registration::ValuePrinterRegister<graph::UndirectedMultiGraph<> >(); + +} diff --git a/alib2graph_data/src/graph/undirected/UndirectedMultiGraph.hpp b/alib2graph_data/src/graph/undirected/UndirectedMultiGraph.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cb87d22b5e8f9b6bfbf48aa163e7dcfd1343683a --- /dev/null +++ b/alib2graph_data/src/graph/undirected/UndirectedMultiGraph.hpp @@ -0,0 +1,362 @@ +// UndirectedMultiGraph.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_UNDIRECTEDMULTIGRAPH_HPP +#define ALIB2_UNDIRECTEDMULTIGRAPH_HPP + +#include <alib/map> +#include <alib/pair> +#include <alib/set> +#include <alib/vector> +#include <alib/tuple> +#include <functional> +#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 UndirectedMultiGraph : public GraphInterface<TNode, TEdge> { +// --------------------------------------------------------------------------------------------------------------------- + + public: + using node_type = TNode; + using edge_type = TEdge; + using normalized_type = UndirectedMultiGraph<>; + +// --------------------------------------------------------------------------------------------------------------------- + + protected: + ext::map<TNode, std::multimap<TNode, TEdge>> m_adjacency_list; + +// ===================================================================================================================== +// Constructor, Destructor, Operators + public: + +// --------------------------------------------------------------------------------------------------------------------- + + const ext::map<TNode, std::multimap<TNode, TEdge>> &getAdjacencyList() const &; + + ext::map<TNode, std::multimap<TNode, TEdge>> &&getAdjacencyList() &&; + +// --------------------------------------------------------------------------------------------------------------------- + +// ===================================================================================================================== +// ObjectBase interface + public: + GraphBase *clone() const override; + + GraphBase *plunder() &&override; + + int compare(const object::ObjectBase &other) const override; + + virtual int compare(const UndirectedMultiGraph &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, std::multimap<TNode, TEdge>> &UndirectedMultiGraph<TNode, TEdge>::getAdjacencyList() const &{ + return m_adjacency_list; +} + +template<typename TNode, typename TEdge> +ext::map<TNode, std::multimap<TNode, TEdge>> &&UndirectedMultiGraph<TNode, TEdge>::getAdjacencyList() &&{ + return std::move(m_adjacency_list); +} + +// --------------------------------------------------------------------------------------------------------------------- + +template<typename TNode, typename TEdge> +void UndirectedMultiGraph<TNode, TEdge>::addNode(const TNode &n) { + m_adjacency_list[n]; +} + +template<typename TNode, typename TEdge> +void UndirectedMultiGraph<TNode, TEdge>::addNode(TNode &&n) { + m_adjacency_list[std::forward<TNode>(n)]; +} + +template<typename TNode, typename TEdge> +template<typename... Params> +void UndirectedMultiGraph<TNode, TEdge>::addNode(Params &&... params) { + addNode(TNode(std::forward<Params>(params) ...)); +} + +// --------------------------------------------------------------------------------------------------------------------- + +template<typename TNode, typename TEdge> +bool UndirectedMultiGraph<TNode, TEdge>::addEdge(const TEdge &e) { + m_adjacency_list[e.first].insert(ext::make_pair(e.second, e)); + m_adjacency_list[e.second].insert(ext::make_pair(e.first, e)); + return true; +} + +template<typename TNode, typename TEdge> +bool UndirectedMultiGraph<TNode, TEdge>::addEdge(TEdge &&e) { + m_adjacency_list[e.first].insert(ext::make_pair(e.second, e)); + m_adjacency_list[e.second].insert(ext::make_pair(e.first, std::forward<TEdge>(e))); + return true; +} + +template<typename TNode, typename TEdge> +template<typename... Params> +bool UndirectedMultiGraph<TNode, TEdge>::addEdge(Params &&... params) { + return addEdge(TEdge(std::forward<Params>(params) ...)); +} + +// --------------------------------------------------------------------------------------------------------------------- + +template<typename TNode, typename TEdge> +size_t UndirectedMultiGraph<TNode, TEdge>::nodeCount() const { + return m_adjacency_list.size(); +} + +template<typename TNode, typename TEdge> +size_t UndirectedMultiGraph<TNode, TEdge>::edgeCount() const { + size_t cnt = 0; + + for (const auto &i: m_adjacency_list) { + cnt += i.second.size(); + } + + return cnt / 2; +} + +// --------------------------------------------------------------------------------------------------------------------- + +template<typename TNode, typename TEdge> +ext::set<TNode> UndirectedMultiGraph<TNode, TEdge>::getNodes() const { + ext::set<TNode> set; + + for (const auto &i: m_adjacency_list) { + set.insert(i.first); + } + + return set; +} + +template<typename TNode, typename TEdge> +ext::vector<TEdge> UndirectedMultiGraph<TNode, TEdge>::getEdges() const { + ext::vector<TEdge> vec; + + for (const auto &i:m_adjacency_list) { + for (const auto &j : i.second) { + vec.push_back(j.second); + } + } + + return vec; +} + +// --------------------------------------------------------------------------------------------------------------------- + +template<typename TNode, typename TEdge> +ext::set<TNode> UndirectedMultiGraph<TNode, TEdge>::successors(const TNode &n) const { + ext::set<TNode> set; + + if (m_adjacency_list.count(n) == 0) { + return set; + } + + for (const auto &i: m_adjacency_list.at(n)) { + set.insert(i.first); + } + + return set; +} + +template<typename TNode, typename TEdge> +ext::vector<TEdge> UndirectedMultiGraph<TNode, TEdge>::successorEdges(const TNode &n) const { + ext::vector<TEdge> vec; + + if (m_adjacency_list.count(n) == 0) { + return vec; + } + + for (const auto &i: m_adjacency_list.at(n)) { + vec.push_back(i.second); + } + + return vec; +} + +template<typename TNode, typename TEdge> +ext::set<TNode> UndirectedMultiGraph<TNode, TEdge>::predecessors(const TNode &n) const { + return successors(n); +} + +template<typename TNode, typename TEdge> +ext::vector<TEdge> UndirectedMultiGraph<TNode, TEdge>::predecessorEdges(const TNode &n) const { + return successorEdges(n); +} + +// --------------------------------------------------------------------------------------------------------------------- + +template<typename TNode, typename TEdge> +std::string UndirectedMultiGraph<TNode, TEdge>::name() const { + return "UndirectedMultiGraph"; +} + +// --------------------------------------------------------------------------------------------------------------------- + +template<typename TNode, typename TEdge> +GraphBase *UndirectedMultiGraph<TNode, TEdge>::clone() const { + return new UndirectedMultiGraph(*this); +} + +template<typename TNode, typename TEdge> +GraphBase *UndirectedMultiGraph<TNode, TEdge>::plunder() &&{ + return new UndirectedMultiGraph(std::move(*this)); +} + +template<typename TNode, typename TEdge> +int UndirectedMultiGraph<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 UndirectedMultiGraph<TNode, TEdge>::compare(const UndirectedMultiGraph &other) const { + auto first = ext::tie(m_adjacency_list); + auto second = ext::tie(other.getAdjacencyList()); + + static ext::compare<decltype(first)> comp; + + return comp(first, second); +} + +template<typename TNode, typename TEdge> +object::ObjectBase *UndirectedMultiGraph<TNode, TEdge>::inc() &&{ + return new object::UniqueObject(object::Object(std::move(*this)), primitive::Integer(0)); +} + +template<typename TNode, typename TEdge> +void UndirectedMultiGraph<TNode, TEdge>::operator>>(std::ostream &ostream) const { + ostream << "(" << name() << " "; + for (const auto &i : m_adjacency_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> +UndirectedMultiGraph<TNode, TEdge>::operator std::string() const { + std::stringstream ss; + ss << "<"; + for (const auto &i : m_adjacency_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::UndirectedMultiGraph<TNode, TEdge>, typename std::enable_if<!std::is_same< + graph::UndirectedMultiGraph<TNode, TEdge>, graph::UndirectedMultiGraph<> >::value>::type> { + static graph::UndirectedMultiGraph<> eval(graph::UndirectedMultiGraph<TNode, TEdge> &&value) { + graph::UndirectedMultiGraph<> graph; + + for (auto &&i: ext::make_moveable_map(std::move(value).getAdjacencyList())) { + 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_UNDIRECTEDMULTIGRAPH_HPP