From dbdd9e3cdcbc75a33b4d1d765d0bec5fe56e3385 Mon Sep 17 00:00:00 2001
From: David Rosca <roscadav@fit.cvut.cz>
Date: Thu, 26 Feb 2015 16:23:04 +0100
Subject: [PATCH] Graphs - Initial commit

---
 alib2data/src/StringApi.cpp                   |  10 +
 alib2data/src/StringApi.hpp                   |  10 +
 alib2data/src/XmlApi.cpp                      |  32 ++++
 alib2data/src/XmlApi.hpp                      |  22 +++
 alib2data/src/graph/Graph.h                   |  29 +++
 alib2data/src/graph/GraphBase.h               |  29 +++
 alib2data/src/graph/GraphFeatures.h           |  13 ++
 alib2data/src/graph/GraphFromStringLexer.cpp  |  76 ++++++++
 alib2data/src/graph/GraphFromStringLexer.h    |  35 ++++
 alib2data/src/graph/GraphFromStringParser.cpp | 160 ++++++++++++++++
 alib2data/src/graph/GraphFromStringParser.h   |  47 +++++
 alib2data/src/graph/GraphFromXMLParser.cpp    | 141 ++++++++++++++
 alib2data/src/graph/GraphFromXMLParser.h      |  47 +++++
 alib2data/src/graph/GraphRepresentation.cpp   |  31 ++++
 alib2data/src/graph/GraphRepresentation.h     |  19 ++
 alib2data/src/graph/GraphToStringComposer.cpp | 112 ++++++++++++
 alib2data/src/graph/GraphToStringComposer.h   |  38 ++++
 alib2data/src/graph/GraphToXMLComposer.cpp    | 101 ++++++++++
 alib2data/src/graph/GraphToXMLComposer.h      |  43 +++++
 alib2data/src/graph/common/GraphElement.cpp   |   9 +
 alib2data/src/graph/common/GraphElement.h     |  30 +++
 alib2data/src/graph/common/Macros.h           |  28 +++
 alib2data/src/graph/common/Node.cpp           | 103 +++++++++++
 alib2data/src/graph/common/Node.h             |  58 ++++++
 .../directed/AdjacencyListDirectedGraph.cpp   | 121 ++++++++++++
 .../directed/AdjacencyListDirectedGraph.h     |  37 ++++
 alib2data/src/graph/directed/DirectedEdge.cpp | 170 +++++++++++++++++
 alib2data/src/graph/directed/DirectedEdge.h   |  67 +++++++
 .../src/graph/directed/DirectedGraph.cpp      | 154 ++++++++++++++++
 alib2data/src/graph/directed/DirectedGraph.h  |  72 ++++++++
 .../src/graph/directed/IDirectedGraph.cpp     |  23 +++
 alib2data/src/graph/directed/IDirectedGraph.h |  38 ++++
 .../src/graph/undirected/UndirectedEdge.cpp   | 173 ++++++++++++++++++
 .../src/graph/undirected/UndirectedEdge.h     |  67 +++++++
 .../src/graph/undirected/UndirectedGraph.h    |  14 ++
 alib2data/src/object/ObjectBase.h             |   9 +
 alib2data/src/std/compare.hpp                 |  16 ++
 37 files changed, 2184 insertions(+)
 create mode 100644 alib2data/src/graph/Graph.h
 create mode 100644 alib2data/src/graph/GraphBase.h
 create mode 100644 alib2data/src/graph/GraphFeatures.h
 create mode 100644 alib2data/src/graph/GraphFromStringLexer.cpp
 create mode 100644 alib2data/src/graph/GraphFromStringLexer.h
 create mode 100644 alib2data/src/graph/GraphFromStringParser.cpp
 create mode 100644 alib2data/src/graph/GraphFromStringParser.h
 create mode 100644 alib2data/src/graph/GraphFromXMLParser.cpp
 create mode 100644 alib2data/src/graph/GraphFromXMLParser.h
 create mode 100644 alib2data/src/graph/GraphRepresentation.cpp
 create mode 100644 alib2data/src/graph/GraphRepresentation.h
 create mode 100644 alib2data/src/graph/GraphToStringComposer.cpp
 create mode 100644 alib2data/src/graph/GraphToStringComposer.h
 create mode 100644 alib2data/src/graph/GraphToXMLComposer.cpp
 create mode 100644 alib2data/src/graph/GraphToXMLComposer.h
 create mode 100644 alib2data/src/graph/common/GraphElement.cpp
 create mode 100644 alib2data/src/graph/common/GraphElement.h
 create mode 100644 alib2data/src/graph/common/Macros.h
 create mode 100644 alib2data/src/graph/common/Node.cpp
 create mode 100644 alib2data/src/graph/common/Node.h
 create mode 100644 alib2data/src/graph/directed/AdjacencyListDirectedGraph.cpp
 create mode 100644 alib2data/src/graph/directed/AdjacencyListDirectedGraph.h
 create mode 100644 alib2data/src/graph/directed/DirectedEdge.cpp
 create mode 100644 alib2data/src/graph/directed/DirectedEdge.h
 create mode 100644 alib2data/src/graph/directed/DirectedGraph.cpp
 create mode 100644 alib2data/src/graph/directed/DirectedGraph.h
 create mode 100644 alib2data/src/graph/directed/IDirectedGraph.cpp
 create mode 100644 alib2data/src/graph/directed/IDirectedGraph.h
 create mode 100644 alib2data/src/graph/undirected/UndirectedEdge.cpp
 create mode 100644 alib2data/src/graph/undirected/UndirectedEdge.h
 create mode 100644 alib2data/src/graph/undirected/UndirectedGraph.h

diff --git a/alib2data/src/StringApi.cpp b/alib2data/src/StringApi.cpp
index b1ed53c2f6..48e958afd0 100644
--- a/alib2data/src/StringApi.cpp
+++ b/alib2data/src/StringApi.cpp
@@ -17,6 +17,7 @@ const regexp::RegExpFromStringParser FromStringParsers::regexpParser;
 const string::StringFromStringParser FromStringParsers::stringParser;
 const automaton::AutomatonFromStringParser FromStringParsers::automatonParser;
 const grammar::GrammarFromStringParser FromStringParsers::grammarParser;
+const graph::GraphFromStringParser FromStringParsers::graphParser;
 const primitive::PrimitiveFromStringParser FromStringParsers::primitiveParser;
 
 const label::LabelToStringComposer ToStringComposers::labelComposer;
@@ -25,6 +26,7 @@ const regexp::RegExpToStringComposer ToStringComposers::regexpComposer;
 const string::StringToStringComposer ToStringComposers::stringComposer;
 const automaton::AutomatonToStringComposer ToStringComposers::automatonComposer;
 const grammar::GrammarToStringComposer ToStringComposers::grammarComposer;
+const graph::GraphToStringComposer ToStringComposers::graphComposer;
 const primitive::PrimitiveToStringComposer ToStringComposers::primitiveComposer;
 
 alphabet::Symbol stringApi<alphabet::Symbol>::parse(std::istream& input) {
@@ -52,6 +54,14 @@ void stringApi<grammar::Grammar>::compose(std::ostream& output, const grammar::G
 	return ToStringComposers::grammarComposer.compose(output, data);
 }
 
+graph::Graph stringApi<graph::Graph>::parse(std::istream& input) {
+	return FromStringParsers::graphParser.parseGraph(input);
+}
+
+void stringApi<graph::Graph>::compose(std::ostream& output, const graph::Graph& data) {
+	return ToStringComposers::graphComposer.compose(output, data);
+}
+
 label::Label stringApi<label::Label>::parse(std::istream& input) {
 	return FromStringParsers::labelParser.parseLabel(input);
 }
diff --git a/alib2data/src/StringApi.hpp b/alib2data/src/StringApi.hpp
index cc9044f776..752e3f1224 100644
--- a/alib2data/src/StringApi.hpp
+++ b/alib2data/src/StringApi.hpp
@@ -14,6 +14,7 @@
 #include "string/StringFromStringParser.h"
 #include "automaton/AutomatonFromStringParser.h"
 #include "grammar/GrammarFromStringParser.h"
+#include "graph/GraphFromStringParser.h"
 #include "primitive/PrimitiveFromStringParser.h"
 
 #include "label/LabelToStringComposer.h"
@@ -22,6 +23,7 @@
 #include "string/StringToStringComposer.h"
 #include "automaton/AutomatonToStringComposer.h"
 #include "grammar/GrammarToStringComposer.h"
+#include "graph/GraphToStringComposer.h"
 #include "primitive/PrimitiveToStringComposer.h"
 
 #include "object/ObjectBase.h"
@@ -53,6 +55,12 @@ struct stringApi<grammar::Grammar> {
 	static void compose(std::ostream& output, const grammar::Grammar& data);
 };
 
+template<>
+struct stringApi<graph::Graph> {
+	static graph::Graph parse(std::istream& input);
+	static void compose(std::ostream& output, const graph::Graph& data);
+};
+
 template<>
 struct stringApi<label::Label> {
 	static label::Label parse(std::istream& input);
@@ -85,6 +93,7 @@ public:
 	static const string::StringFromStringParser stringParser;
 	static const automaton::AutomatonFromStringParser automatonParser;
 	static const grammar::GrammarFromStringParser grammarParser;
+	static const graph::GraphFromStringParser graphParser;
 	static const primitive::PrimitiveFromStringParser primitiveParser;
 
 };
@@ -97,6 +106,7 @@ public:
 	static const string::StringToStringComposer stringComposer;
 	static const automaton::AutomatonToStringComposer automatonComposer;
 	static const grammar::GrammarToStringComposer grammarComposer;
+	static const graph::GraphToStringComposer graphComposer;
 	static const primitive::PrimitiveToStringComposer primitiveComposer;
 };
 
diff --git a/alib2data/src/XmlApi.cpp b/alib2data/src/XmlApi.cpp
index 30ee8856de..824409f9e6 100644
--- a/alib2data/src/XmlApi.cpp
+++ b/alib2data/src/XmlApi.cpp
@@ -15,6 +15,7 @@ const regexp::RegExpFromXMLParser FromXMLParsers::regexpParser;
 const string::StringFromXMLParser FromXMLParsers::stringParser;
 const automaton::AutomatonFromXMLParser FromXMLParsers::automatonParser;
 const grammar::GrammarFromXMLParser FromXMLParsers::grammarParser;
+const graph::GraphFromXMLParser FromXMLParsers::graphParser;
 const exception::ExceptionFromXMLParser FromXMLParsers::exceptionParser;
 const alib::ObjectFromXMLParser FromXMLParsers::objectParser;
 const container::ContainerFromXMLParser FromXMLParsers::containerParser;
@@ -26,6 +27,7 @@ const regexp::RegExpToXMLComposer ToXMLComposers::regexpComposer;
 const string::StringToXMLComposer ToXMLComposers::stringComposer;
 const automaton::AutomatonToXMLComposer ToXMLComposers::automatonComposer;
 const grammar::GrammarToXMLComposer ToXMLComposers::grammarComposer;
+const graph::GraphToXMLComposer ToXMLComposers::graphComposer;
 const alib::ObjectToXMLComposer ToXMLComposers::objectComposer;
 const exception::ExceptionToXMLComposer ToXMLComposers::exceptionComposer;
 const container::ContainerToXMLComposer ToXMLComposers::containerComposer;
@@ -82,6 +84,7 @@ const std::string Names::GRAMMAR_CSG = "CSG";
 const std::string Names::GRAMMAR_NON_CONTRACTING_GRAMMAR = "NonContractingGrammar";
 const std::string Names::GRAMMAR_CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR = "ContextPpreservingUnrestrictedGrammar";
 const std::string Names::GRAMMAR_UNRESTRICTED_GRAMMAR = "UnrestrictedGrammar";
+const std::string Names::GRAPH_DIRECTED_GRAPH = "DirectedGraph";
 const std::string Names::LABEL_PRIMITIVE_LABEL = "PrimitiveLabel";
 const std::string Names::LABEL_HEXAVIGESIMAL_LABEL = "HexavigesimalLabel";
 const std::string Names::LABEL_OBJECT_LABEL = "ObjectLabel";
@@ -751,6 +754,31 @@ void xmlApi<grammar::UnrestrictedGrammar>::compose(std::list<sax::Token>& output
 }
 
 
+graph::Graph xmlApi<graph::Graph>::parse(std::list<sax::Token>& input) {
+	return FromXMLParsers::graphParser.parseGraph(input);
+}
+
+bool xmlApi<graph::Graph>::first(const std::list<sax::Token>& input) {
+	return FromXMLParsers::graphParser.first(input);
+}
+
+void xmlApi<graph::Graph>::compose(std::list<sax::Token>& output, const graph::Graph& data) {
+	ToXMLComposers::graphComposer.compose(output, data);
+}
+
+graph::DirectedGraph xmlApi<graph::DirectedGraph>::parse(std::list<sax::Token>& input) {
+	return FromXMLParsers::graphParser.parseDirectedGraph(input);
+}
+
+bool xmlApi<graph::DirectedGraph>::first(const std::list<sax::Token>& input) {
+	return sax::FromXMLParserHelper::isToken(input, sax::Token::TokenType::START_ELEMENT, Names::GRAPH_DIRECTED_GRAPH);
+}
+
+void xmlApi<graph::DirectedGraph>::compose(std::list<sax::Token>& output, const graph::DirectedGraph& data) {
+	ToXMLComposers::graphComposer.compose(output, data);
+}
+
+
 label::Label xmlApi<label::Label>::parse(std::list<sax::Token>& input) {
 	return FromXMLParsers::labelParser.parseLabel(input);
 }
@@ -1246,6 +1274,10 @@ void ToXMLComposers::Visit(void* data, const grammar::UnrestrictedGrammar& gramm
 	xmlApi<grammar::UnrestrictedGrammar>::compose(*((std::list<sax::Token>*) data), grammar);
 }
 
+void ToXMLComposers::Visit(void* data, const graph::DirectedGraph& graph) const {
+	xmlApi<graph::DirectedGraph>::compose(*((std::list<sax::Token>*) data), graph);
+}
+
 void ToXMLComposers::Visit(void* data, const label::PrimitiveLabel& label) const {
 	xmlApi<label::PrimitiveLabel>::compose(*((std::list<sax::Token>*) data), label);
 }
diff --git a/alib2data/src/XmlApi.hpp b/alib2data/src/XmlApi.hpp
index 65e8d82ab7..5278d7af1b 100644
--- a/alib2data/src/XmlApi.hpp
+++ b/alib2data/src/XmlApi.hpp
@@ -14,6 +14,7 @@
 #include "string/StringFromXMLParser.h"
 #include "automaton/AutomatonFromXMLParser.h"
 #include "grammar/GrammarFromXMLParser.h"
+#include "graph/GraphFromXMLParser.h"
 #include "object/ObjectFromXMLParser.h"
 #include "exception/ExceptionFromXMLParser.h"
 #include "primitive/PrimitiveFromXMLParser.h"
@@ -24,6 +25,7 @@
 #include "string/StringToXMLComposer.h"
 #include "automaton/AutomatonToXMLComposer.h"
 #include "grammar/GrammarToXMLComposer.h"
+#include "graph/GraphToXMLComposer.h"
 #include "object/ObjectToXMLComposer.h"
 #include "exception/ExceptionToXMLComposer.h"
 #include "primitive/PrimitiveToXMLComposer.h"
@@ -83,6 +85,7 @@ public:
 	const static std::string GRAMMAR_NON_CONTRACTING_GRAMMAR;
 	const static std::string GRAMMAR_CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR;
 	const static std::string GRAMMAR_UNRESTRICTED_GRAMMAR;
+	const static std::string GRAPH_DIRECTED_GRAPH;
 	const static std::string LABEL_PRIMITIVE_LABEL;
 	const static std::string LABEL_HEXAVIGESIMAL_LABEL;
 	const static std::string LABEL_OBJECT_LABEL;
@@ -526,6 +529,21 @@ struct xmlApi<grammar::UnrestrictedGrammar> {
 };
 
 
+template<>
+struct xmlApi<graph::Graph> {
+	static graph::Graph parse(std::list<sax::Token>& input);
+	static bool first(const std::list<sax::Token>& input);
+	static void compose(std::list<sax::Token>& output, const graph::Graph& data);
+};
+
+template<>
+struct xmlApi<graph::DirectedGraph> {
+	static graph::DirectedGraph parse(std::list<sax::Token>& input);
+	static bool first(const std::list<sax::Token>& input);
+	static void compose(std::list<sax::Token>& output, const graph::DirectedGraph& data);
+};
+
+
 template<>
 struct xmlApi<label::Label> {
 	static label::Label parse(std::list<sax::Token>& input);
@@ -731,6 +749,7 @@ public:
 	static const string::StringFromXMLParser stringParser;
 	static const automaton::AutomatonFromXMLParser automatonParser;
 	static const grammar::GrammarFromXMLParser grammarParser;
+	static const graph::GraphFromXMLParser graphParser;
 	static const exception::ExceptionFromXMLParser exceptionParser;
 	static const ObjectFromXMLParser objectParser;
 	static const container::ContainerFromXMLParser containerParser;
@@ -788,6 +807,8 @@ class ToXMLComposers : public VisitableObjectBase::const_visitor_type {
 	void Visit(void*, const grammar::ContextPreservingUnrestrictedGrammar& grammar) const;
 	void Visit(void*, const grammar::UnrestrictedGrammar& grammar) const;
 
+	void Visit(void*, const graph::DirectedGraph& graph) const;
+
 	void Visit(void*, const label::PrimitiveLabel& label) const;
 	void Visit(void*, const label::HexavigesimalLabel& label) const;
 	void Visit(void*, const label::ObjectLabel& label) const;
@@ -820,6 +841,7 @@ public:
 	static const string::StringToXMLComposer stringComposer;
 	static const automaton::AutomatonToXMLComposer automatonComposer;
 	static const grammar::GrammarToXMLComposer grammarComposer;
+	static const graph::GraphToXMLComposer graphComposer;
 	static const exception::ExceptionToXMLComposer exceptionComposer;
 	static const ObjectToXMLComposer objectComposer;
 	static const container::ContainerToXMLComposer containerComposer;
diff --git a/alib2data/src/graph/Graph.h b/alib2data/src/graph/Graph.h
new file mode 100644
index 0000000000..7d47b0c256
--- /dev/null
+++ b/alib2data/src/graph/Graph.h
@@ -0,0 +1,29 @@
+#ifndef GRAPH_H_
+#define GRAPH_H_
+
+#include "../std/visitor.hpp"
+#include "../std/compare.hpp"
+#include "../common/wrapper.hpp"
+#include "GraphBase.h"
+
+namespace graph {
+
+// Wrapper around graphs.
+typedef alib::wrapper<GraphBase> Graph;
+
+} // namespace graph
+
+namespace std {
+
+template<>
+struct compare<graph::Graph>
+{
+	int operator()(const graph::Graph &first, const graph::Graph &second) const
+	{
+		return first.getData().compare(second.getData());
+	}
+};
+
+} // namespace
+
+#endif // GRAPH_H_
diff --git a/alib2data/src/graph/GraphBase.h b/alib2data/src/graph/GraphBase.h
new file mode 100644
index 0000000000..e3539fef1a
--- /dev/null
+++ b/alib2data/src/graph/GraphBase.h
@@ -0,0 +1,29 @@
+#ifndef GRAPH_BASE_H_
+#define GRAPH_BASE_H_
+
+#include "common/Macros.h"
+#include "../common/base.hpp"
+#include "../object/ObjectBase.h"
+
+namespace graph {
+
+class GraphBase;
+
+typedef std::acceptor_base<GraphBase, DirectedGraph, UndirectedGraph> VisitableGraphBase;
+
+// Abstract base class for all graphs.
+class GraphBase : public alib::ObjectBase, public VisitableGraphBase
+{
+public:
+	using VisitableGraphBase::Accept;
+	using alib::VisitableObjectBase::Accept;
+
+	virtual GraphBase *clone() const = 0;
+	virtual GraphBase *plunder() && = 0;
+};
+
+} // namespace graph
+
+GRAPH_DEFINE_STD_COMPARE(GraphBase)
+
+#endif // GRAPH_BASE_H_
diff --git a/alib2data/src/graph/GraphFeatures.h b/alib2data/src/graph/GraphFeatures.h
new file mode 100644
index 0000000000..dba0c28394
--- /dev/null
+++ b/alib2data/src/graph/GraphFeatures.h
@@ -0,0 +1,13 @@
+#ifndef GRAPH_FEATURES_H_
+#define GRAPH_FEATURES_H_
+
+namespace graph {
+
+enum class FEATURES {
+	DIRECTED,
+	UNDIRECTED
+};
+
+} // namespace graph
+
+#endif // GRAPH_FEATURES_H_
diff --git a/alib2data/src/graph/GraphFromStringLexer.cpp b/alib2data/src/graph/GraphFromStringLexer.cpp
new file mode 100644
index 0000000000..422de85536
--- /dev/null
+++ b/alib2data/src/graph/GraphFromStringLexer.cpp
@@ -0,0 +1,76 @@
+#include "GraphFromStringLexer.h"
+
+#include <cctype>
+
+namespace graph {
+
+GraphFromStringLexer::Token GraphFromStringLexer::next(std::istream &in) const
+{
+	Token token;
+	token.type = TokenType::ERROR;
+	char character;
+
+L0:
+	character = in.get();
+
+	if (in.eof()) {
+		token.type = TokenType::TEOF;
+		return token;
+	} else if (isspace(character)) {
+		token.raw += character;
+		goto L0;
+	} else if (character == '(') {
+		token.type = TokenType::LPAR;
+		token.value += character;
+		token.raw += character;
+		return token;
+	} else if (character == ')') {
+		token.type = TokenType::RPAR;
+		token.value += character;
+		token.raw += character;
+		return token;
+	} else if (character == ':') {
+		token.type = TokenType::COLON;
+		token.value += character;
+		token.raw += character;
+		return token;
+	} else if (character == ',') {
+		token.type = TokenType::COMMA;
+		token.value += character;
+		token.raw += character;
+		return token;
+	} else {
+		in.putback(character);
+		putback(in, std::move(token));
+		token.type = TokenType::ERROR;
+		return token;
+	}
+}
+
+void GraphFromStringLexer::putback(std::istream &input, GraphFromStringLexer::Token token) const
+{
+	while (!token.raw.empty()) {
+		input.putback(token.raw.back());
+		token.raw.pop_back();
+	}
+	input.clear();
+}
+
+std::string GraphFromStringLexer::getString(std::istream &input) const
+{
+	std::string str;
+	char character;
+
+	while (input >> character) {
+		if (character == ':') {
+			input.putback(character);
+			return str;
+		}
+		str += character;
+	}
+
+	return std::string();
+}
+
+} // namespace graph
+
diff --git a/alib2data/src/graph/GraphFromStringLexer.h b/alib2data/src/graph/GraphFromStringLexer.h
new file mode 100644
index 0000000000..5246f9795d
--- /dev/null
+++ b/alib2data/src/graph/GraphFromStringLexer.h
@@ -0,0 +1,35 @@
+#ifndef GRAPH_FROM_STRING_LEXER_H_
+#define GRAPH_FROM_STRING_LEXER_H_
+
+#include <string>
+#include <sstream>
+
+namespace graph {
+
+class GraphFromStringLexer
+{
+public:
+	enum class TokenType {
+		LPAR,
+		RPAR,
+		COLON,
+		COMMA,
+		TEOF,
+		ERROR
+	};
+
+	struct Token {
+		TokenType type;
+		std::string value;
+		std::string raw;
+	};
+
+	Token next(std::istream &input) const;
+	void putback(std::istream &input, Token token) const;
+
+	std::string getString(std::istream &input) const;
+};
+
+} // namespace graph
+
+#endif // GRAPH_FROM_STRING_LEXER_H_
diff --git a/alib2data/src/graph/GraphFromStringParser.cpp b/alib2data/src/graph/GraphFromStringParser.cpp
new file mode 100644
index 0000000000..4b75e0bfa0
--- /dev/null
+++ b/alib2data/src/graph/GraphFromStringParser.cpp
@@ -0,0 +1,160 @@
+#include "GraphFromStringParser.h"
+#include "../exception/AlibException.h"
+
+#include "../StringApi.hpp"
+
+namespace graph {
+
+Graph GraphFromStringParser::parseGraph(std::istream &input) const
+{
+	GraphFromStringLexer::Token token = lexer.next(input);
+	if (token.type != GraphFromStringLexer::TokenType::LPAR) {
+		throw exception::AlibException("Invalid input. Expected LPAR");
+	}
+
+	const std::string &str = lexer.getString(input);
+	if (str == "DirectedGraph") {
+		parseDelimiter(input); // :
+		Graph graph{parseDirectedGraph(input)};
+
+		if (lexer.next(input).type != GraphFromStringLexer::TokenType::RPAR) {
+			throw exception::AlibException("Invalid input. Expected RPAR");
+		}
+		return graph;
+	} else if (str == "UndirectedGraph") {
+		parseDelimiter(input); // :
+		//Graph graph{parseUndirectedGraph(input)};
+
+		if (lexer.next(input).type != GraphFromStringLexer::TokenType::RPAR) {
+			throw exception::AlibException("Invalid input. Expected RPAR");
+		}
+		// return graph;
+	}
+
+	throw exception::AlibException("Invalid graph type");
+}
+
+DirectedGraph GraphFromStringParser::parseDirectedGraph(std::istream &input) const
+{
+	DirectedGraph graph(parseRepresentation(input));
+	parseDelimiter(input); // :
+	parseNodes(input, graph);
+	parseDelimiter(input); // :
+	parseDirectedEdges(input, graph);
+	return graph;
+}
+
+UndirectedGraph GraphFromStringParser::parseUndirectedGraph(std::istream &input) const
+{
+	//UndirectedGraph graph(parseRepresentation(input));
+	//parseDelimiter(input); // :
+	//parseNodes(input, graph);
+	//parseDelimiter(input); // :
+	//parseUndirectedEdges(input, graph);
+	//return graph;
+}
+
+REPRESENTATION GraphFromStringParser::parseRepresentation(std::istream &input) const
+{
+	std::string representation = lexer.getString(input);
+	if (representation.empty()) {
+		throw exception::AlibException("Invalid representation");
+	}
+	return representationFromString(representation);
+}
+
+Node GraphFromStringParser::parseNode(std::istream &input) const
+{
+	return Node(alib::stringApi<label::Label>::parse(input));
+}
+
+DirectedEdge GraphFromStringParser::parseDirectedEdge(std::istream &input) const
+{
+	Node from = parseNode(input);
+	label::Label name = alib::stringApi<label::Label>::parse(input);
+	Node to = parseNode(input);
+	return DirectedEdge(from, to, name);
+}
+
+UndirectedEdge GraphFromStringParser::parseUndirectedEdge(std::istream &input) const
+{
+	Node first = parseNode(input);
+	label::Label name = alib::stringApi<label::Label>::parse(input);
+	Node second = parseNode(input);
+	return UndirectedEdge(first, second, name);
+}
+
+template<typename T>
+void GraphFromStringParser::parseNodes(std::istream &input, T &graph) const
+{
+	GraphFromStringLexer::Token token = lexer.next(input);
+
+	// Empty nodes?
+	if (token.type == GraphFromStringLexer::TokenType::COLON) {
+		return;
+	}
+	lexer.putback(input, token);
+
+	while (true) {
+		graph.addNode(parseNode(input));
+
+		token = lexer.next(input);
+		if (token.type != GraphFromStringLexer::TokenType::COMMA) {
+			lexer.putback(input, token);
+			return;
+		}
+	}
+}
+
+void GraphFromStringParser::parseDirectedEdges(std::istream &input, DirectedGraph &graph) const
+{
+	GraphFromStringLexer::Token token = lexer.next(input);
+
+	// Empty edges?
+	if (token.type == GraphFromStringLexer::TokenType::COLON) {
+		return;
+	}
+	lexer.putback(input, token);
+
+
+	while (true) {
+		graph.addEdge(parseDirectedEdge(input));
+
+		token = lexer.next(input);
+		if (token.type != GraphFromStringLexer::TokenType::COMMA) {
+			lexer.putback(input, token);
+			return;
+		}
+	}
+}
+
+void GraphFromStringParser::parseUndirectedEdges(std::istream &input, UndirectedGraph &graph) const
+{
+	GraphFromStringLexer::Token token = lexer.next(input);
+
+	// Empty edges?
+	if (token.type == GraphFromStringLexer::TokenType::COLON) {
+		return;
+	}
+	lexer.putback(input, token);
+
+	while (true) {
+		//graph.addEdge(parseUndirectedEdge(input));
+
+		token = lexer.next(input);
+		if (token.type != GraphFromStringLexer::TokenType::COMMA) {
+			lexer.putback(input, token);
+			return;
+		}
+	}
+}
+
+void GraphFromStringParser::parseDelimiter(std::istream &input) const
+{
+	GraphFromStringLexer::Token token = lexer.next(input);
+	if (token.type != GraphFromStringLexer::TokenType::COLON) {
+		throw exception::AlibException("Invalid input. Expected COLON");
+	}
+}
+
+} // namespace graph
diff --git a/alib2data/src/graph/GraphFromStringParser.h b/alib2data/src/graph/GraphFromStringParser.h
new file mode 100644
index 0000000000..48e979b143
--- /dev/null
+++ b/alib2data/src/graph/GraphFromStringParser.h
@@ -0,0 +1,47 @@
+#ifndef GRAPH_FROM_STRING_PARSER_H_
+#define GRAPH_FROM_STRING_PARSER_H_
+
+#include "Graph.h"
+#include "GraphFeatures.h"
+#include "GraphRepresentation.h"
+#include "directed/DirectedGraph.h"
+#include "undirected/UndirectedGraph.h"
+
+#include "GraphFromStringLexer.h"
+#include "GraphFeatures.h"
+
+namespace alib {
+
+template<typename T>
+struct stringApi;
+
+} // namespace alib
+
+namespace graph {
+
+class GraphFromStringParser
+{
+private:
+	Graph parseGraph(std::istream &input) const;
+	DirectedGraph parseDirectedGraph(std::istream &input) const;
+	UndirectedGraph parseUndirectedGraph(std::istream &input) const;
+
+	REPRESENTATION parseRepresentation(std::istream &input) const;
+	Node parseNode(std::istream &input) const;
+	DirectedEdge parseDirectedEdge(std::istream &input) const;
+	UndirectedEdge parseUndirectedEdge(std::istream &input) const;
+
+	template<typename T>
+	void parseNodes(std::istream &input, T &graph) const;
+	void parseDirectedEdges(std::istream &input, DirectedGraph &graph) const;
+	void parseUndirectedEdges(std::istream &input, UndirectedGraph &graph) const;
+	void parseDelimiter(std::istream &input) const;
+
+	GraphFromStringLexer lexer;
+
+	template<typename T> friend class alib::stringApi;
+};
+
+} // namespace graph
+
+#endif // GRAPH_FROM_STRING_PARSER_H_
diff --git a/alib2data/src/graph/GraphFromXMLParser.cpp b/alib2data/src/graph/GraphFromXMLParser.cpp
new file mode 100644
index 0000000000..8858373146
--- /dev/null
+++ b/alib2data/src/graph/GraphFromXMLParser.cpp
@@ -0,0 +1,141 @@
+#include "GraphFromXMLParser.h"
+#include "../sax/ParserException.h"
+
+#include "../XmlApi.hpp"
+
+namespace graph {
+
+bool GraphFromXMLParser::first(const std::list<sax::Token> &input) const
+{
+	if (alib::xmlApi<DirectedGraph>::first(input)) {
+		return true;
+	}
+
+	return false;
+}
+
+Graph GraphFromXMLParser::parseGraph(std::list<sax::Token> &input) const
+{
+	if (alib::xmlApi<DirectedGraph>::first(input)) {
+		return Graph(parseDirectedGraph(input));
+	}
+
+	throw exception::AlibException();
+}
+
+DirectedGraph GraphFromXMLParser::parseDirectedGraph(std::list<sax::Token> &input) const
+{
+	popToken(input, sax::Token::TokenType::START_ELEMENT, alib::Names::GRAPH_DIRECTED_GRAPH);
+
+	DirectedGraph graph(parseRepresentation(input));
+	parseNodes(input, graph);
+	parseDirectedEdges(input, graph);
+
+	popToken(input, sax::Token::TokenType::END_ELEMENT, alib::Names::GRAPH_DIRECTED_GRAPH);
+	return graph;
+}
+
+UndirectedGraph GraphFromXMLParser::parseUndirectedGraph(std::list<sax::Token> &input) const
+{
+	//popToken(input, sax::Token::TokenType::START_ELEMENT, alib::Names::GRAPH_UNDIRECTED_GRAPH);
+
+	//UndirectedGraph graph(parseRepresentation(input));
+	//parseNodes(input, graph);
+	//parseUndirectedEdges(input, graph);
+
+	//popToken(input, sax::Token::TokenType::END_ELEMENT, alib::Names::GRAPH_UNDIRECTED_GRAPH);
+	//return graph;
+}
+
+REPRESENTATION GraphFromXMLParser::parseRepresentation(std::list<sax::Token> &input) const
+{
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "representation");
+
+	REPRESENTATION r = representationFromString(popTokenData(input, sax::Token::TokenType::CHARACTER));
+
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "representation");
+	return r;
+}
+
+Node GraphFromXMLParser::parseNode(std::list<sax::Token> &input) const
+{
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "node");
+
+	Node n = Node(alib::xmlApi<label::Label>::parse(input));
+
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "node");
+	return n;
+}
+
+DirectedEdge GraphFromXMLParser::parseDirectedEdge(std::list<sax::Token> &input) const
+{
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "edge");
+
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "from");
+	Node from = parseNode(input);
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "from");
+
+	label::Label name = alib::xmlApi<label::Label>::parse(input);
+
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "to");
+	Node to = parseNode(input);
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "to");
+
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "edge");
+	return DirectedEdge(from, to, name);
+}
+
+UndirectedEdge GraphFromXMLParser::parseUndirectedEdge(std::list<sax::Token> &input) const
+{
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "edge");
+
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "first");
+	Node first = parseNode(input);
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "first");
+
+	label::Label name = alib::xmlApi<label::Label>::parse(input);
+
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "second");
+	Node second = parseNode(input);
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "second");
+
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "edge");
+	return UndirectedEdge(first, second, name);
+}
+
+template<typename T>
+void GraphFromXMLParser::parseNodes(std::list<sax::Token> &input, T &graph) const
+{
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "nodes");
+
+	while (isTokenType(input, sax::Token::TokenType::START_ELEMENT)) {
+		graph.addNode(parseNode(input));
+	}
+
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "nodes");
+}
+
+void GraphFromXMLParser::parseDirectedEdges(std::list<sax::Token> &input, DirectedGraph &graph) const
+{
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "edges");
+
+	while (isTokenType(input, sax::Token::TokenType::START_ELEMENT)) {
+		graph.addEdge(parseDirectedEdge(input));
+	}
+
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "edges");
+}
+
+void GraphFromXMLParser::parseUndirectedEdges(std::list<sax::Token> &input, UndirectedGraph &graph) const
+{
+	//popToken(input, sax::Token::TokenType::START_ELEMENT, "edges");
+
+	//while (isTokenType(input, sax::Token::TokenType::START_ELEMENT)) {
+	//	graph.addEdge(parseUndirectedEdge(input));
+	//}
+
+	//popToken(input, sax::Token::TokenType::END_ELEMENT, "edges");
+}
+
+} // namespace graph
+
diff --git a/alib2data/src/graph/GraphFromXMLParser.h b/alib2data/src/graph/GraphFromXMLParser.h
new file mode 100644
index 0000000000..472dfc921c
--- /dev/null
+++ b/alib2data/src/graph/GraphFromXMLParser.h
@@ -0,0 +1,47 @@
+#ifndef GRAPH_FROM_XML_PARSER_H_
+#define GRAPH_FROM_XML_PARSER_H_
+
+#include "../sax/FromXMLParserHelper.h"
+#include "Graph.h"
+#include "GraphFeatures.h"
+#include "directed/DirectedGraph.h"
+#include "undirected/UndirectedGraph.h"
+#include "../sax/Token.h"
+#include "../alphabet/Symbol.h"
+
+namespace alib {
+
+template<typename T>
+struct xmlApi;
+
+} // namespace alib
+
+namespace graph {
+
+// Parser used to get Graph from XML parsed into list of tokens.
+class GraphFromXMLParser : public sax::FromXMLParserHelper
+{
+public:
+	bool first(const std::list<sax::Token> &input) const;
+
+private:
+	Graph parseGraph(std::list<sax::Token> &input) const;
+	DirectedGraph parseDirectedGraph(std::list<sax::Token> &input) const;
+	UndirectedGraph parseUndirectedGraph(std::list<sax::Token> &input) const;
+
+	REPRESENTATION parseRepresentation(std::list<sax::Token> &input) const;
+	Node parseNode(std::list<sax::Token> &input) const;
+	DirectedEdge parseDirectedEdge(std::list<sax::Token> &input) const;
+	UndirectedEdge parseUndirectedEdge(std::list<sax::Token> &input) const;
+
+	template<typename T>
+	void parseNodes(std::list<sax::Token> &input, T &graph) const;
+	void parseDirectedEdges(std::list<sax::Token> &input, DirectedGraph &graph) const;
+	void parseUndirectedEdges(std::list<sax::Token> &input, UndirectedGraph &graph) const;
+
+	template<typename T> friend class alib::xmlApi;
+};
+
+} // namespace graph
+
+#endif // GRAPH_FROM_XML_PARSER_H_
diff --git a/alib2data/src/graph/GraphRepresentation.cpp b/alib2data/src/graph/GraphRepresentation.cpp
new file mode 100644
index 0000000000..180569fa4a
--- /dev/null
+++ b/alib2data/src/graph/GraphRepresentation.cpp
@@ -0,0 +1,31 @@
+#include "GraphRepresentation.h"
+
+namespace graph {
+
+std::string representationToString(REPRESENTATION r)
+{
+	switch (r) {
+	case REPRESENTATION::ADJACENCY_LIST:
+		return "AdjacencyList";
+	case REPRESENTATION::ADJACENCY_MATRIX:
+		return "AdjacencyMatrix";
+	case REPRESENTATION::INCIDENCE_MATRIX:
+		return "IncidenceMatrix";
+	default:
+		return "AdjacencyList";
+	}
+}
+
+REPRESENTATION representationFromString(const std::string &str)
+{
+	if (str == "AdjacencyList") {
+		return REPRESENTATION::ADJACENCY_LIST;
+	} else if (str == "AdjacencyMatrix") {
+		return REPRESENTATION::ADJACENCY_MATRIX;
+	} else if (str == "IncidenceMatrix") {
+		return REPRESENTATION::INCIDENCE_MATRIX;
+	}
+	return REPRESENTATION::ADJACENCY_LIST;
+}
+
+} // namespace graph
diff --git a/alib2data/src/graph/GraphRepresentation.h b/alib2data/src/graph/GraphRepresentation.h
new file mode 100644
index 0000000000..e93115b7ff
--- /dev/null
+++ b/alib2data/src/graph/GraphRepresentation.h
@@ -0,0 +1,19 @@
+#ifndef GRAPH_REPRESENTATION_H_
+#define GRAPH_REPRESENTATION_H_
+
+#include <string>
+
+namespace graph {
+
+enum class REPRESENTATION {
+	ADJACENCY_LIST,
+	ADJACENCY_MATRIX,
+	INCIDENCE_MATRIX
+};
+
+std::string representationToString(REPRESENTATION r);
+REPRESENTATION representationFromString(const std::string &str);
+
+} // namespace graph
+
+#endif // GRAPH_REPRESENTATION_H_
diff --git a/alib2data/src/graph/GraphToStringComposer.cpp b/alib2data/src/graph/GraphToStringComposer.cpp
new file mode 100644
index 0000000000..8ec08c07c2
--- /dev/null
+++ b/alib2data/src/graph/GraphToStringComposer.cpp
@@ -0,0 +1,112 @@
+#include "GraphToStringComposer.h"
+#include "../StringApi.hpp"
+
+#include <algorithm>
+
+namespace graph {
+
+void GraphToStringComposer::compose(std::ostream &out, const Graph &graph) const
+{
+	out << "(";
+	graph.getData().Accept(static_cast<void*>(&out), *this);
+	out << ")";
+}
+
+void GraphToStringComposer::Visit(void *data, const DirectedGraph &graph) const
+{
+	std::ostream &out = *static_cast<std::ostream*>(data);
+
+	out << "DirectedGraph:";
+	composeRepresentation(out, graph.getRepresentation());
+	out << ":";
+	composeNodes(out, graph.getNodes());
+	out << ":";
+	composeDirectedEdges(out, graph.getEdges());
+}
+
+void GraphToStringComposer::Visit(void *data, const UndirectedGraph &graph) const
+{
+	std::ostream &out = *static_cast<std::ostream*>(data);
+
+	out << "UndirectedGraph:";
+	(void) graph;
+	//composeRepresentation(out, graph.getRepresentation());
+	//out << ":";
+	//composeNodes(out, graph.getNodes());
+	//out << ":";
+	//composeUndirectedEdges(out, graph.getEdges());
+}
+
+void GraphToStringComposer::Visit(void *data, const Node &node) const
+{
+	std::ostream &out = *static_cast<std::ostream*>(data);
+
+	alib::stringApi<label::Label>::compose(out, node.getName());
+}
+
+void GraphToStringComposer::Visit(void *data, const DirectedEdge &edge) const
+{
+	std::ostream &out = *static_cast<std::ostream*>(data);
+
+	edge.getFromNode().Accept(static_cast<void*>(&out), *this);
+	alib::stringApi<label::Label>::compose(out, edge.getName());
+	edge.getToNode().Accept(static_cast<void*>(&out), *this);
+}
+
+void GraphToStringComposer::Visit(void *data, const UndirectedEdge &edge) const
+{
+	std::ostream &out = *static_cast<std::ostream*>(data);
+
+	edge.getFirstNode().Accept(static_cast<void*>(&out), *this);
+	alib::stringApi<label::Label>::compose(out, edge.getName());
+	edge.getSecondNode().Accept(static_cast<void*>(&out), *this);
+}
+
+void GraphToStringComposer::composeRepresentation(std::ostream &out, REPRESENTATION representation) const
+{
+	out << representationToString(representation);
+}
+
+void GraphToStringComposer::composeNodes(std::ostream &out, const std::set<Node> &nodes) const
+{
+	bool first = true;
+
+	for (const Node &node : nodes) {
+		if (first) {
+			first = false;
+		} else {
+			out << ",";
+		}
+		node.Accept(static_cast<void*>(&out), *this);
+	}
+}
+
+void GraphToStringComposer::composeDirectedEdges(std::ostream &out, const std::set<DirectedEdge> &edges) const
+{
+	bool first = true;
+
+	for (const DirectedEdge &edge : edges) {
+		if (first) {
+			first = false;
+		} else {
+			out << ",";
+		}
+		edge.Accept(static_cast<void*>(&out), *this);
+	}
+}
+
+void GraphToStringComposer::composeUndirectedEdges(std::ostream &out, const std::set<UndirectedEdge> &edges) const
+{
+	bool first = true;
+
+	for (const UndirectedEdge &edge : edges) {
+		if (first) {
+			first = false;
+		} else {
+			out << ",";
+		}
+		edge.Accept(static_cast<void*>(&out), *this);
+	}
+}
+
+} // namespace graph
diff --git a/alib2data/src/graph/GraphToStringComposer.h b/alib2data/src/graph/GraphToStringComposer.h
new file mode 100644
index 0000000000..6a7c211b99
--- /dev/null
+++ b/alib2data/src/graph/GraphToStringComposer.h
@@ -0,0 +1,38 @@
+#ifndef GRAPH_TO_STRING_COMPOSER_H_
+#define GRAPH_TO_STRING_COMPOSER_H_
+
+#include <set>
+#include <string>
+
+#include "Graph.h"
+#include "GraphRepresentation.h"
+#include "common/GraphElement.h"
+#include "directed/DirectedGraph.h"
+#include "undirected/UndirectedGraph.h"
+#include "../std/visitor.hpp"
+#include "../sax/Token.h"
+
+namespace graph {
+
+class GraphToStringComposer : public VisitableGraphBase::const_visitor_type, GraphElement::const_visitor_type
+{
+public:
+	void compose(std::ostream &out, const Graph &graph) const;
+
+private:
+	void Visit(void *data, const DirectedGraph &graph) const;
+	void Visit(void *data, const UndirectedGraph &graph) const;
+
+	void Visit(void *data, const Node &node) const;
+	void Visit(void *data, const DirectedEdge &edge) const;
+	void Visit(void *data, const UndirectedEdge &edge) const;
+
+	void composeRepresentation(std::ostream &out, REPRESENTATION representation) const;
+	void composeNodes(std::ostream &out, const std::set<Node> &nodes) const;
+	void composeDirectedEdges(std::ostream &out, const std::set<DirectedEdge> &edges) const;
+	void composeUndirectedEdges(std::ostream &out, const std::set<UndirectedEdge> &edges) const;
+};
+
+} // namespace graph
+
+#endif // GRAPH_TO_STRING_COMPOSER_H_
diff --git a/alib2data/src/graph/GraphToXMLComposer.cpp b/alib2data/src/graph/GraphToXMLComposer.cpp
new file mode 100644
index 0000000000..1c909506bb
--- /dev/null
+++ b/alib2data/src/graph/GraphToXMLComposer.cpp
@@ -0,0 +1,101 @@
+#include "GraphToXMLComposer.h"
+#include "GraphRepresentation.h"
+
+#include "../XmlApi.hpp"
+
+namespace graph {
+
+void GraphToXMLComposer::Visit(void *data, const Node &node) const
+{
+	std::list<sax::Token> &out = *static_cast<std::list<sax::Token>*>(data);
+
+	out.push_back(sax::Token("node", sax::Token::TokenType::START_ELEMENT));
+	alib::xmlApi<label::Label>::compose(out, node.getName());
+	out.push_back(sax::Token("node", sax::Token::TokenType::END_ELEMENT));
+}
+
+void GraphToXMLComposer::Visit(void *data, const DirectedEdge &edge) const
+{
+	std::list<sax::Token> &out = *static_cast<std::list<sax::Token>*>(data);
+
+	out.push_back(sax::Token("edge", sax::Token::TokenType::START_ELEMENT));
+
+	out.push_back(sax::Token("from", sax::Token::TokenType::START_ELEMENT));
+	edge.getFromNode().Accept(static_cast<void*>(&out), *this);
+	out.push_back(sax::Token("from", sax::Token::TokenType::END_ELEMENT));
+
+	alib::xmlApi<label::Label>::compose(out, edge.getName());
+
+	out.push_back(sax::Token("to", sax::Token::TokenType::START_ELEMENT));
+	edge.getToNode().Accept(static_cast<void*>(&out), *this);
+	out.push_back(sax::Token("to", sax::Token::TokenType::END_ELEMENT));
+
+	out.push_back(sax::Token("edge", sax::Token::TokenType::END_ELEMENT));
+}
+
+void GraphToXMLComposer::Visit(void *data, const UndirectedEdge &edge) const
+{
+	std::list<sax::Token> &out = *static_cast<std::list<sax::Token>*>(data);
+
+	out.push_back(sax::Token("edge", sax::Token::TokenType::START_ELEMENT));
+
+	out.push_back(sax::Token("first", sax::Token::TokenType::START_ELEMENT));
+	edge.getFirstNode().Accept(static_cast<void*>(&out), *this);
+	out.push_back(sax::Token("first", sax::Token::TokenType::END_ELEMENT));
+
+	alib::xmlApi<label::Label>::compose(out, edge.getName());
+
+	out.push_back(sax::Token("second", sax::Token::TokenType::START_ELEMENT));
+	edge.getSecondNode().Accept(static_cast<void*>(&out), *this);
+	out.push_back(sax::Token("second", sax::Token::TokenType::END_ELEMENT));
+
+	out.push_back(sax::Token("edge", sax::Token::TokenType::END_ELEMENT));
+}
+
+void GraphToXMLComposer::compose(std::list<sax::Token> &out, const GraphBase &graph) const
+{
+	graph.Accept((void*) &out, alib::ToXMLComposers::toXMLComposers);
+}
+
+void GraphToXMLComposer::compose(std::list<sax::Token> &out, const Graph &graph) const
+{
+	graph.getData().Accept((void*) &out, alib::ToXMLComposers::toXMLComposers);
+}
+
+void GraphToXMLComposer::compose(std::list<sax::Token> &out, const DirectedGraph &graph) const
+{
+	out.push_back(sax::Token(alib::Names::GRAPH_DIRECTED_GRAPH, sax::Token::TokenType::START_ELEMENT));
+
+	composeRepresentation(out, representationToString(graph.getRepresentation()));
+	composeNodes(out, graph.getNodes());
+	composeDirectedEdges(out, graph.getEdges());
+
+	out.push_back(sax::Token(alib::Names::GRAPH_DIRECTED_GRAPH, sax::Token::TokenType::END_ELEMENT));
+}
+
+void GraphToXMLComposer::composeRepresentation(std::list<sax::Token> &out, const std::string &representation) const
+{
+	out.push_back(sax::Token("representation", sax::Token::TokenType::START_ELEMENT));
+	out.push_back(sax::Token(representation, sax::Token::TokenType::CHARACTER));
+	out.push_back(sax::Token("representation", sax::Token::TokenType::END_ELEMENT));
+}
+
+void GraphToXMLComposer::composeNodes(std::list<sax::Token> &out, const std::set<Node> &nodes) const
+{
+	out.push_back(sax::Token("nodes", sax::Token::TokenType::START_ELEMENT));
+	for (const Node &node : nodes) {
+		node.Accept(static_cast<void*>(&out), *this);
+	}
+	out.push_back(sax::Token("nodes", sax::Token::TokenType::END_ELEMENT));
+}
+
+void GraphToXMLComposer::composeDirectedEdges(std::list<sax::Token> &out, const std::set<DirectedEdge> &edges) const
+{
+	out.push_back(sax::Token("edges", sax::Token::TokenType::START_ELEMENT));
+	for (const DirectedEdge &edge : edges) {
+		edge.Accept(static_cast<void*>(&out), *this);
+	}
+	out.push_back(sax::Token("edges", sax::Token::TokenType::END_ELEMENT));
+}
+
+} // namespace graph
diff --git a/alib2data/src/graph/GraphToXMLComposer.h b/alib2data/src/graph/GraphToXMLComposer.h
new file mode 100644
index 0000000000..a53d9b1e88
--- /dev/null
+++ b/alib2data/src/graph/GraphToXMLComposer.h
@@ -0,0 +1,43 @@
+#ifndef GRAPH_TO_XML_COMPOSER_H_
+#define GRAPH_TO_XML_COMPOSER_H_
+
+#include <set>
+#include <list>
+
+#include "Graph.h"
+#include "common/GraphElement.h"
+#include "directed/DirectedGraph.h"
+#include "undirected/UndirectedGraph.h"
+#include "../std/visitor.hpp"
+#include "../sax/Token.h"
+
+namespace alib {
+
+template<typename T>
+struct xmlApi;
+
+} // namespace alib
+
+namespace graph {
+
+// This class contains methods to print XML representation of graph to the output stream.
+class GraphToXMLComposer : public GraphElement::const_visitor_type
+{
+private:
+	void Visit(void *data, const Node &node) const;
+	void Visit(void *data, const DirectedEdge &edge) const;
+	void Visit(void *data, const UndirectedEdge &edge) const;
+
+	void compose(std::list<sax::Token> &out, const GraphBase &graph) const;
+	void compose(std::list<sax::Token> &out, const Graph &graph) const;
+	void compose(std::list<sax::Token> &out, const DirectedGraph &graph) const;
+	void composeRepresentation(std::list<sax::Token> &out, const std::string &representation) const;
+	void composeNodes(std::list<sax::Token> &out, const std::set<Node> &nodes) const;
+	void composeDirectedEdges(std::list<sax::Token> &out, const std::set<DirectedEdge> &edges) const;
+
+	template<typename T> friend class alib::xmlApi;
+};
+
+} // namespace graph
+
+#endif // GRAPH_TO_XML_COMPOSER_H_
diff --git a/alib2data/src/graph/common/GraphElement.cpp b/alib2data/src/graph/common/GraphElement.cpp
new file mode 100644
index 0000000000..0687b8aab7
--- /dev/null
+++ b/alib2data/src/graph/common/GraphElement.cpp
@@ -0,0 +1,9 @@
+#include "GraphElement.h"
+
+namespace graph {
+
+GraphElement::GraphElement()
+{
+}
+
+} // namespace graph
diff --git a/alib2data/src/graph/common/GraphElement.h b/alib2data/src/graph/common/GraphElement.h
new file mode 100644
index 0000000000..ac6a1d8ff0
--- /dev/null
+++ b/alib2data/src/graph/common/GraphElement.h
@@ -0,0 +1,30 @@
+#ifndef GRAPH_ELEMENT_H_
+#define GRAPH_ELEMENT_H_
+
+// for std::hash
+#include <string>
+#include <functional>
+
+#include "../../std/visitor.hpp"
+#include "../../object/Object.h"
+
+namespace graph {
+
+class GraphElement;
+
+class Node;
+class DirectedEdge;
+class UndirectedEdge;
+
+// Abstract class representing element in the graph. Can be node or edge.
+typedef std::acceptor_base<GraphElement, Node, DirectedEdge, UndirectedEdge> VisitableGraphElement;
+
+class GraphElement : public alib::base<GraphElement, Node, DirectedEdge, UndirectedEdge>, public VisitableGraphElement
+{
+public:
+	explicit GraphElement();
+};
+
+} // namespace graph
+
+#endif // GRAPH_ELEMENT_H_
diff --git a/alib2data/src/graph/common/Macros.h b/alib2data/src/graph/common/Macros.h
new file mode 100644
index 0000000000..5e17259986
--- /dev/null
+++ b/alib2data/src/graph/common/Macros.h
@@ -0,0 +1,28 @@
+#ifndef GRAPH_MACROS_H_
+#define GRAPH_MACROS_H_
+
+#define GRAPH_DEFINE_STD_HASH(T) \
+	namespace std { \
+	template <> \
+	struct hash<graph::T> \
+	{ \
+		std::size_t operator()(const graph::T &t) const \
+		{ \
+			return std::hash<std::string>()(static_cast<std::string>(t)); \
+		} \
+	}; \
+	} \
+
+#define GRAPH_DEFINE_STD_COMPARE(T) \
+	namespace std { \
+	template<> \
+	struct compare<graph::T> \
+	{ \
+		int operator()(const graph::T &first, const graph::T &second) const \
+		{ \
+			return first.compare(second); \
+		} \
+	}; \
+	} \
+
+#endif // GRAPH_MACROS_H_
diff --git a/alib2data/src/graph/common/Node.cpp b/alib2data/src/graph/common/Node.cpp
new file mode 100644
index 0000000000..a2251e7b08
--- /dev/null
+++ b/alib2data/src/graph/common/Node.cpp
@@ -0,0 +1,103 @@
+#include "Node.h"
+#include "../../label/Label.h"
+
+#include <sstream>
+
+namespace graph {
+
+Node::Node(const label::Label &name)
+	: name(name)
+{
+}
+
+Node::Node(label::Label &&name)
+	: name(std::move(name))
+{
+}
+
+Node::Node(int number)
+	: name(label::labelFrom(number))
+{
+}
+
+Node::Node(char character)
+	: name(label::labelFrom(character))
+{
+}
+
+Node::Node(const std::string &name)
+	: name(label::labelFrom(name))
+{
+}
+
+Node::Node(const Node &other)
+	: name(other.name)
+{
+}
+
+Node::Node(Node &&other) noexcept
+	: name(std::move(other.name))
+{
+}
+
+Node &Node::operator=(const Node &other)
+{
+	if (this == &other) {
+		return *this;
+	}
+
+	*this = Node(other);
+	return *this;
+}
+
+Node &Node::operator=(Node &&other)
+{
+	std::swap(name, other.name);
+	return *this;
+}
+
+GraphElement *Node::clone() const
+{
+	return new Node(*this);
+}
+
+GraphElement *Node::plunder() &&
+{
+	return new Node(std::move(*this));
+}
+
+const label::Label &Node::getName() const
+{
+	return name;
+}
+
+int Node::compare(const Node &other) const
+{
+	return name.getData().compare(other.name.getData());
+}
+
+void Node::operator>>(std::ostream &out) const
+{
+	dump(out);
+}
+
+Node::operator std::string() const
+{
+	std::stringstream ss;
+	ss << *this;
+	return ss.str();
+}
+
+std::ostream &operator<<(std::ostream &out, const Node &node)
+{
+	node.dump(out);
+	return out;
+}
+
+void Node::dump(std::ostream &os) const
+{
+	os << "(Node " << name << ")";
+}
+
+} // namespace graph
+
diff --git a/alib2data/src/graph/common/Node.h b/alib2data/src/graph/common/Node.h
new file mode 100644
index 0000000000..ec5c004f26
--- /dev/null
+++ b/alib2data/src/graph/common/Node.h
@@ -0,0 +1,58 @@
+#ifndef NODE_H_
+#define NODE_H_
+
+#include "Macros.h"
+#include "GraphElement.h"
+#include "../../label/Label.h"
+
+namespace graph {
+
+class Node : public std::acceptor<Node, GraphElement, GraphElement>
+{
+public:
+	explicit Node(const label::Label &name);
+	explicit Node(label::Label &&name);
+	explicit Node(int number);
+	explicit Node(char character);
+	explicit Node(const std::string &name);
+
+	Node(const Node &other);
+	Node(Node &&other) noexcept;
+	Node &operator=(const Node &other);
+	Node &operator=(Node &&other);
+
+	GraphElement *clone() const;
+	GraphElement *plunder() &&;
+
+	const label::Label &getName() const;
+
+	int compare(const GraphElement &other) const override
+	{
+		return -other.compare(*this);
+	}
+
+	int compare(const Node &other) const;
+
+	void operator>>(std::ostream &out) const override;
+
+	operator std::string() const override;
+
+	int selfTypeId() const override
+	{
+		return typeId<Node>();
+	}
+
+	friend std::ostream &operator<<(std::ostream &out, const Node &node);
+
+private:
+	void dump(std::ostream &os) const;
+
+	label::Label name;
+};
+
+} // namespace graph
+
+GRAPH_DEFINE_STD_HASH(Node)
+GRAPH_DEFINE_STD_COMPARE(Node)
+
+#endif // NODE_H_
diff --git a/alib2data/src/graph/directed/AdjacencyListDirectedGraph.cpp b/alib2data/src/graph/directed/AdjacencyListDirectedGraph.cpp
new file mode 100644
index 0000000000..35528bafd9
--- /dev/null
+++ b/alib2data/src/graph/directed/AdjacencyListDirectedGraph.cpp
@@ -0,0 +1,121 @@
+#include "AdjacencyListDirectedGraph.h"
+#include "../../std/compare.hpp"
+
+namespace graph {
+
+std::set<Node> AdjacencyListDirectedGraph::allNodes() const
+{
+	std::set<Node> out;
+
+	for (auto i : adj) {
+		out.insert(i.first);
+	}
+
+	return out;
+}
+
+std::set<DirectedEdge> AdjacencyListDirectedGraph::allEdges() const
+{
+	return edges;
+}
+
+std::set<DirectedEdge> AdjacencyListDirectedGraph::findEdges(const Node &from, const Node &to) const
+{
+	std::set<DirectedEdge> out;
+
+	for (const DirectedEdge &e : edges) {
+		if (e.getFromNode() == from && e.getToNode() == to) {
+			out.insert(e);
+		}
+	}
+
+	return out;
+}
+
+std::set<Node> AdjacencyListDirectedGraph::neighbors(const Node &node) const
+{
+	auto search = adj.find(node);
+	if (search == adj.end()) {
+		return std::set<Node>();
+	}
+	return search->second;
+}
+
+std::set<DirectedEdge> AdjacencyListDirectedGraph::neighborEdges(const Node &node) const
+{
+	std::set<DirectedEdge> out;
+	const std::set<Node> &nghbrs = neighbors(node);
+
+	for (const DirectedEdge &e : edges) {
+		if (e.getFromNode() == node && nghbrs.find(e.getToNode()) != nghbrs.end()) {
+			out.insert(e);
+		}
+	}
+
+	return out;
+}
+
+void AdjacencyListDirectedGraph::addNode(const Node &node)
+{
+	if (adj.find(node) != adj.end()) {
+		return;
+	}
+
+	adj[node]; // insert key
+}
+
+void AdjacencyListDirectedGraph::removeNode(const Node &node)
+{
+	auto search = adj.find(node);
+	if (search == adj.end()) {
+		return;
+	}
+
+	adj.erase(search);
+
+	auto i = edges.begin();
+	while (i != edges.end()) {
+		if (i->getFromNode() == node || i->getToNode() == node) {
+			edges.erase(i++);
+		} else {
+			i++;
+		}
+	}
+}
+
+void AdjacencyListDirectedGraph::addEdge(const DirectedEdge &edge)
+{
+	if (edges.find(edge) != edges.end()) {
+		return;
+	}
+
+	edges.insert(edge);
+}
+
+void AdjacencyListDirectedGraph::removeEdge(const DirectedEdge &edge)
+{
+	auto search = edges.find(edge);
+	if (search == edges.end()) {
+		return;
+	}
+
+	edges.erase(search);
+
+	// Don't touch adj if there still is an edge, in case of multigraph,
+	if (!findEdges(edge.getFromNode(), edge.getToNode()).empty()) {
+		adj[edge.getFromNode()].erase(edge.getToNode());
+	}
+}
+
+int AdjacencyListDirectedGraph::compare(IDirectedGraph *other) const
+{
+	AdjacencyListDirectedGraph *o = dynamic_cast<AdjacencyListDirectedGraph*>(other);
+
+	auto first = std::tie(edges, adj);
+	auto second = std::tie(o->edges, o->adj);
+
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
+}
+
+} // namespace graph
diff --git a/alib2data/src/graph/directed/AdjacencyListDirectedGraph.h b/alib2data/src/graph/directed/AdjacencyListDirectedGraph.h
new file mode 100644
index 0000000000..5d22b85845
--- /dev/null
+++ b/alib2data/src/graph/directed/AdjacencyListDirectedGraph.h
@@ -0,0 +1,37 @@
+#ifndef ADJACENCY_LIST_DIRECTED_GRAPH_H_
+#define ADJACENCY_LIST_DIRECTED_GRAPH_H_
+
+#include <set>
+#include <unordered_map>
+
+#include "IDirectedGraph.h"
+
+namespace graph {
+
+class AdjacencyListDirectedGraph : public IDirectedGraph
+{
+public:
+	std::set<Node> allNodes() const override;
+	std::set<DirectedEdge> allEdges() const override;
+
+	std::set<DirectedEdge> findEdges(const Node &from, const Node &to) const override;
+
+	std::set<Node> neighbors(const Node &node) const override;
+	std::set<DirectedEdge> neighborEdges(const Node &node) const override;
+
+	void addNode(const Node &node) override;
+	void removeNode(const Node &node) override;
+
+	void addEdge(const DirectedEdge &edge) override;
+	void removeEdge(const DirectedEdge &edge) override;
+
+	int compare(IDirectedGraph *other) const override;
+
+private:
+	std::set<DirectedEdge> edges;
+	std::unordered_map<Node, std::set<Node>> adj;
+};
+
+} // namespace graph
+
+#endif // ADJACENCY_LIST_DIRECTED_GRAPH_H_
diff --git a/alib2data/src/graph/directed/DirectedEdge.cpp b/alib2data/src/graph/directed/DirectedEdge.cpp
new file mode 100644
index 0000000000..dedcefb852
--- /dev/null
+++ b/alib2data/src/graph/directed/DirectedEdge.cpp
@@ -0,0 +1,170 @@
+#include "DirectedEdge.h"
+
+#include <sstream>
+
+namespace graph {
+
+DirectedEdge::DirectedEdge(const Node &from, const Node &to)
+	: from(from)
+	, to(to)
+	, name(label::labelFrom('d'))
+{
+}
+
+DirectedEdge::DirectedEdge(Node &&from, Node &&to)
+	: from(std::move(from))
+	, to(std::move(to))
+	, name(label::labelFrom('d'))
+{
+}
+
+DirectedEdge::DirectedEdge(const Node &from, const Node &to, const label::Label &name)
+	: from(from)
+	, to(to)
+	, name(name)
+{
+}
+
+DirectedEdge::DirectedEdge(Node &&from, Node &&to, label::Label &&name)
+	: from(std::move(from))
+	, to(std::move(to))
+	, name(std::move(name))
+{
+}
+
+DirectedEdge::DirectedEdge(const Node &from, const Node &to, int number)
+	: from(from)
+	, to(to)
+	, name(label::labelFrom(number))
+{
+}
+
+DirectedEdge::DirectedEdge(Node &&from, Node &&to, int number)
+	: from(std::move(from))
+	, to(std::move(to))
+	, name(label::labelFrom(number))
+{
+}
+
+DirectedEdge::DirectedEdge(const Node &from, const Node &to, char character)
+	: from(from)
+	, to(to)
+	, name(label::labelFrom(character))
+{
+}
+
+DirectedEdge::DirectedEdge(Node &&from, Node &&to, char character)
+	: from(std::move(from))
+	, to(std::move(to))
+	, name(label::labelFrom(character))
+{
+}
+
+DirectedEdge::DirectedEdge(const Node &from, const Node &to, const std::string &name)
+	: from(from)
+	, to(to)
+	, name(label::labelFrom(name))
+{
+}
+
+DirectedEdge::DirectedEdge(Node &&from, Node &&to, const std::string &name)
+	: from(std::move(from))
+	, to(std::move(to))
+	, name(label::labelFrom(name))
+{
+}
+
+DirectedEdge::DirectedEdge(const DirectedEdge &other)
+	: from(other.from)
+	, to(other.to)
+	, name(other.name)
+{
+}
+
+DirectedEdge::DirectedEdge(DirectedEdge &&other) noexcept
+	: from(std::move(other.from))
+	, to(std::move(other.to))
+	, name(std::move(other.name))
+{
+}
+
+DirectedEdge &DirectedEdge::operator=(const DirectedEdge &other)
+{
+	if (this == &other) {
+		return *this;
+	}
+
+	*this = DirectedEdge(other);
+	return *this;
+}
+
+DirectedEdge &DirectedEdge::operator=(DirectedEdge &&other)
+{
+	std::swap(from, other.from);
+	std::swap(to, other.to);
+	std::swap(name, other.name);
+	return *this;
+}
+
+GraphElement *DirectedEdge::clone() const
+{
+	return new DirectedEdge(*this);
+}
+
+GraphElement *DirectedEdge::plunder() &&
+{
+	return new DirectedEdge(std::move(*this));
+}
+
+const Node &DirectedEdge::getFromNode() const
+{
+	return from;
+}
+
+const Node &DirectedEdge::getToNode() const
+{
+	return to;
+}
+
+const label::Label &DirectedEdge::getName() const
+{
+	return name;
+}
+
+int DirectedEdge::compare(const DirectedEdge &other) const
+{
+	int res = name.getData().compare(other.name.getData());
+	if (res == 0) {
+		res = from.compare(other.from);
+		if (res == 0) {
+			res = to.compare(other.to);
+		}
+	}
+	return res;
+}
+
+void DirectedEdge::operator>>(std::ostream &out) const
+{
+	dump(out);
+}
+
+DirectedEdge::operator std::string() const
+{
+	std::stringstream ss;
+	ss << *this;
+	return ss.str();
+}
+
+std::ostream &operator<<(std::ostream &out, const DirectedEdge &node)
+{
+	node.dump(out);
+	return out;
+}
+
+void DirectedEdge::dump(std::ostream &os) const
+{
+	os << "(DirectedEdge " << from << " -> " << to << ")";
+}
+
+} // namespace graph
+
diff --git a/alib2data/src/graph/directed/DirectedEdge.h b/alib2data/src/graph/directed/DirectedEdge.h
new file mode 100644
index 0000000000..53a901f662
--- /dev/null
+++ b/alib2data/src/graph/directed/DirectedEdge.h
@@ -0,0 +1,67 @@
+#ifndef DIRECTED_EDGE_H_
+#define DIRECTED_EDGE_H_
+
+#include "../common/GraphElement.h"
+#include "../common/Macros.h"
+#include "../common/Node.h"
+
+namespace graph {
+
+class DirectedEdge : public std::acceptor<DirectedEdge, GraphElement, GraphElement>
+{
+public:
+	explicit DirectedEdge(const Node &from, const Node &to);
+	explicit DirectedEdge(Node &&from, Node &&to);
+	explicit DirectedEdge(const Node &from, const Node &to, const label::Label &name);
+	explicit DirectedEdge(Node &&from, Node &&to, label::Label &&name);
+	explicit DirectedEdge(const Node &from, const Node &to, int number);
+	explicit DirectedEdge(Node &&from, Node &&to, int number);
+	explicit DirectedEdge(const Node &from, const Node &to, char character);
+	explicit DirectedEdge(Node &&from, Node &&to, char character);
+	explicit DirectedEdge(const Node &from, const Node &to, const std::string &name);
+	explicit DirectedEdge(Node &&from, Node &&to, const std::string &name);
+
+	DirectedEdge(const DirectedEdge &other);
+	DirectedEdge(DirectedEdge &&other) noexcept;
+	DirectedEdge &operator=(const DirectedEdge &other);
+	DirectedEdge &operator=(DirectedEdge &&other);
+
+	GraphElement *clone() const;
+	GraphElement *plunder() &&;
+
+	const Node &getFromNode() const;
+	const Node &getToNode() const;
+	const label::Label &getName() const;
+
+	int compare(const GraphElement &other) const override
+	{
+		return -other.compare(*this);
+	}
+
+	int compare(const DirectedEdge &other) const;
+
+	void operator>>(std::ostream &out) const override;
+
+	operator std::string() const override;
+
+	int selfTypeId() const override
+	{
+		return typeId<DirectedEdge>();
+	}
+
+	friend std::ostream &operator<<(std::ostream &out, const DirectedEdge &node);
+
+private:
+	void dump(std::ostream &os) const;
+
+	Node from;
+	Node to;
+	label::Label name;
+};
+
+} // namespace graph
+
+GRAPH_DEFINE_STD_HASH(DirectedEdge)
+GRAPH_DEFINE_STD_COMPARE(DirectedEdge)
+
+#endif // DIRECTED_EDGE_H_
diff --git a/alib2data/src/graph/directed/DirectedGraph.cpp b/alib2data/src/graph/directed/DirectedGraph.cpp
new file mode 100644
index 0000000000..874495de56
--- /dev/null
+++ b/alib2data/src/graph/directed/DirectedGraph.cpp
@@ -0,0 +1,154 @@
+#include "DirectedGraph.h"
+#include "IDirectedGraph.h"
+#include "AdjacencyListDirectedGraph.h"
+#include "../../std/set.hpp"
+
+#include <iostream>
+#include <algorithm>
+#include <sstream>
+
+namespace graph {
+
+DirectedGraph::DirectedGraph(REPRESENTATION representation)
+	: representation(representation)
+{
+	init();
+}
+
+DirectedGraph::~DirectedGraph() noexcept
+{
+	delete impl;
+}
+
+DirectedGraph::DirectedGraph(const DirectedGraph &other)
+	: representation(other.representation)
+{
+	init();
+}
+
+DirectedGraph::DirectedGraph(DirectedGraph &&other) noexcept
+	: representation(other.representation)
+	, impl(other.impl)
+{
+	other.impl = 0;
+}
+
+DirectedGraph &DirectedGraph::operator=(const DirectedGraph &other)
+{
+	if (this == &other) {
+		return *this;
+	}
+
+	*this = DirectedGraph(other);
+	return *this;
+}
+
+DirectedGraph &DirectedGraph::operator=(DirectedGraph &&other) noexcept
+{
+	this->representation = other.representation;
+	std::swap(this->impl, other.impl);
+	return *this;
+}
+
+GraphBase *DirectedGraph::clone() const
+{
+	return new DirectedGraph(*this);
+}
+
+GraphBase *DirectedGraph::plunder() &&
+{
+	return new DirectedGraph(std::move(*this));
+}
+
+REPRESENTATION DirectedGraph::getRepresentation() const
+{
+	return representation;
+}
+
+std::set<Node> DirectedGraph::getNodes() const
+{
+	return impl->allNodes();
+}
+
+std::set<DirectedEdge> DirectedGraph::getEdges() const
+{
+	return impl->allEdges();
+}
+
+bool DirectedGraph::hasEdge(const Node &from, const Node &to) const
+{
+	return !impl->findEdges(from, to).empty();
+}
+
+std::set<DirectedEdge> DirectedGraph::findEdges(const Node &from, const Node &to) const
+{
+	return impl->findEdges(from, to);
+}
+
+std::set<Node> DirectedGraph::neighbors(const Node &node) const
+{
+	return impl->neighbors(node);
+}
+
+std::set<DirectedEdge> DirectedGraph::neighborEdges(const Node &node) const
+{
+	return impl->neighborEdges(node);
+}
+
+void DirectedGraph::addNode(const Node &node)
+{
+	return impl->addNode(node);
+}
+
+void DirectedGraph::removeNode(const Node &node)
+{
+	return impl->removeNode(node);
+}
+
+void DirectedGraph::addEdge(const DirectedEdge &edge)
+{
+	return impl->addEdge(edge);
+}
+
+void DirectedGraph::removeEdge(const DirectedEdge &edge)
+{
+	return impl->removeEdge(edge);
+}
+
+void DirectedGraph::operator>>(std::ostream &out) const
+{
+	out << "(DirectedGraph " << static_cast<std::string>(*impl) << ")";
+}
+
+int DirectedGraph::compare(const DirectedGraph &other) const
+{
+	if (representation != other.representation) {
+		return static_cast<int>(representation) - static_cast<int>(other.representation);
+	}
+
+	return impl->compare(other.impl);
+}
+
+DirectedGraph::operator std::string() const
+{
+	std::stringstream ss;
+	ss << *this;
+	return ss.str();
+}
+
+void DirectedGraph::init()
+{
+	switch (representation) {
+	case REPRESENTATION::ADJACENCY_LIST:
+		impl = new AdjacencyListDirectedGraph();
+		break;
+
+	case REPRESENTATION::ADJACENCY_MATRIX:
+	case REPRESENTATION:::INCIDENCE_MATRIX:
+
+	default:
+		impl = 0;
+	}
+}
+
+} // namespace graph
diff --git a/alib2data/src/graph/directed/DirectedGraph.h b/alib2data/src/graph/directed/DirectedGraph.h
new file mode 100644
index 0000000000..c3693578b4
--- /dev/null
+++ b/alib2data/src/graph/directed/DirectedGraph.h
@@ -0,0 +1,72 @@
+#ifndef DIRECTED_GRAPH_H_
+#define DIRECTED_GRAPH_H_
+
+#include "../GraphBase.h"
+#include "../GraphRepresentation.h"
+#include "../common/Macros.h"
+#include "../common/Node.h"
+#include "DirectedEdge.h"
+
+namespace graph {
+
+class IDirectedGraph;
+
+class DirectedGraph : public std::acceptor<DirectedGraph, VisitableGraphBase, std::acceptor<DirectedGraph, alib::VisitableObjectBase, GraphBase>>
+{
+public:
+	explicit DirectedGraph(REPRESENTATION representation);
+	~DirectedGraph() noexcept;
+
+	DirectedGraph(const DirectedGraph &other);
+	DirectedGraph(DirectedGraph &&other) noexcept;
+	DirectedGraph &operator=(const DirectedGraph &other);
+	DirectedGraph &operator=(DirectedGraph &&other) noexcept;
+
+	GraphBase *clone() const override;
+	GraphBase *plunder() && override;
+
+	REPRESENTATION getRepresentation() const;
+
+	std::set<Node> getNodes() const;
+	std::set<DirectedEdge> getEdges() const;
+
+	bool hasEdge(const Node &from, const Node &to) const;
+	std::set<DirectedEdge> findEdges(const Node &from, const Node &to) const;
+
+	std::set<Node> neighbors(const Node &node) const;
+	std::set<DirectedEdge> neighborEdges(const Node &node) const;
+
+	void addNode(const Node &node);
+	void removeNode(const Node &node);
+
+	void addEdge(const DirectedEdge &edge);
+	void removeEdge(const DirectedEdge &edge);
+
+	int compare(const ObjectBase &other) const override
+	{
+		return -other.compare(*this);
+	}
+
+	int compare(const DirectedGraph &other) const;
+
+	void operator>>(std::ostream &out) const override;
+
+	operator std::string() const override;
+
+	int selfTypeId() const override
+	{
+		return typeId<DirectedGraph>();
+	}
+
+private:
+	void init();
+
+	REPRESENTATION representation;
+	IDirectedGraph *impl;
+};
+
+} // namespace graph
+
+GRAPH_DEFINE_STD_COMPARE(DirectedGraph)
+
+#endif // DIRECTED_GRAPH_H_
diff --git a/alib2data/src/graph/directed/IDirectedGraph.cpp b/alib2data/src/graph/directed/IDirectedGraph.cpp
new file mode 100644
index 0000000000..eba90153b8
--- /dev/null
+++ b/alib2data/src/graph/directed/IDirectedGraph.cpp
@@ -0,0 +1,23 @@
+#include "IDirectedGraph.h"
+
+#include <sstream>
+
+namespace graph {
+
+IDirectedGraph::~IDirectedGraph() noexcept
+{
+}
+
+IDirectedGraph::operator std::string() const
+{
+	std::stringstream ss;
+	for (const Node &node : allNodes()) {
+		ss << node;
+	}
+	for (const DirectedEdge &edge : allEdges()) {
+		ss << edge;
+	}
+	return ss.str();
+}
+
+} // namespace graph
diff --git a/alib2data/src/graph/directed/IDirectedGraph.h b/alib2data/src/graph/directed/IDirectedGraph.h
new file mode 100644
index 0000000000..5961c0817f
--- /dev/null
+++ b/alib2data/src/graph/directed/IDirectedGraph.h
@@ -0,0 +1,38 @@
+#ifndef I_DIRECTED_GRAPH_H_
+#define I_DIRECTED_GRAPH_H_
+
+#include <set>
+#include <map>
+
+#include "../common/Node.h"
+#include "DirectedEdge.h"
+
+namespace graph {
+
+class IDirectedGraph
+{
+public:
+	virtual ~IDirectedGraph() noexcept;
+
+	virtual std::set<Node> allNodes() const = 0;
+	virtual std::set<DirectedEdge> allEdges() const = 0;
+
+	virtual std::set<DirectedEdge> findEdges(const Node &from, const Node &to) const = 0;
+
+	virtual std::set<Node> neighbors(const Node &node) const = 0;
+	virtual std::set<DirectedEdge> neighborEdges(const Node &node) const = 0;
+
+	virtual void addNode(const Node &node) = 0;
+	virtual void removeNode(const Node &node) = 0;
+
+	virtual void addEdge(const DirectedEdge &edge) = 0;
+	virtual void removeEdge(const DirectedEdge &edge) = 0;
+
+	virtual int compare(IDirectedGraph *other) const = 0;
+
+	operator std::string() const;
+};
+
+} // namespace graph
+
+#endif // I_DIRECTED_GRAPH_H_
diff --git a/alib2data/src/graph/undirected/UndirectedEdge.cpp b/alib2data/src/graph/undirected/UndirectedEdge.cpp
new file mode 100644
index 0000000000..c259152f0b
--- /dev/null
+++ b/alib2data/src/graph/undirected/UndirectedEdge.cpp
@@ -0,0 +1,173 @@
+#include "UndirectedEdge.h"
+
+#include <sstream>
+
+namespace graph {
+
+UndirectedEdge::UndirectedEdge(const Node &first, const Node &second)
+	: first(first)
+	, second(second)
+	, name(label::labelFrom('u'))
+{
+}
+
+UndirectedEdge::UndirectedEdge(Node &&first, Node &&second)
+	: first(std::move(first))
+	, second(std::move(second))
+	, name(label::labelFrom('u'))
+{
+}
+
+UndirectedEdge::UndirectedEdge(const Node &first, const Node &second, const label::Label &name)
+	: first(first)
+	, second(second)
+	, name(name)
+{
+}
+
+UndirectedEdge::UndirectedEdge(Node &&first, Node &&second, label::Label &&name)
+	: first(std::move(first))
+	, second(std::move(second))
+	, name(std::move(name))
+{
+}
+
+UndirectedEdge::UndirectedEdge(const Node &first, const Node &second, int number)
+	: first(first)
+	, second(second)
+	, name(label::labelFrom(number))
+{
+}
+
+UndirectedEdge::UndirectedEdge(Node &&first, Node &&second, int number)
+	: first(std::move(first))
+	, second(std::move(second))
+	, name(label::labelFrom(number))
+{
+}
+
+UndirectedEdge::UndirectedEdge(const Node &first, const Node &second, char character)
+	: first(first)
+	, second(second)
+	, name(label::labelFrom(character))
+{
+}
+
+UndirectedEdge::UndirectedEdge(Node &&first, Node &&second, char character)
+	: first(std::move(first))
+	, second(std::move(second))
+	, name(label::labelFrom(character))
+{
+}
+
+UndirectedEdge::UndirectedEdge(const Node &first, const Node &second, const std::string &name)
+	: first(first)
+	, second(second)
+	, name(label::labelFrom(name))
+{
+}
+
+UndirectedEdge::UndirectedEdge(Node &&first, Node &&second, const std::string &name)
+	: first(std::move(first))
+	, second(std::move(second))
+	, name(label::labelFrom(name))
+{
+}
+
+UndirectedEdge::UndirectedEdge(const UndirectedEdge &other)
+	: first(other.first)
+	, second(other.second)
+	, name(other.name)
+{
+}
+
+UndirectedEdge::UndirectedEdge(UndirectedEdge &&other) noexcept
+	: first(std::move(other.first))
+	, second(std::move(other.second))
+	, name(std::move(other.name))
+{
+}
+
+UndirectedEdge &UndirectedEdge::operator=(const UndirectedEdge &other)
+{
+	if (this == &other) {
+		return *this;
+	}
+
+	*this = UndirectedEdge(other);
+	return *this;
+}
+
+UndirectedEdge &UndirectedEdge::operator=(UndirectedEdge &&other)
+{
+	std::swap(first, other.first);
+	std::swap(second, other.second);
+	std::swap(name, other.name);
+	return *this;
+}
+
+GraphElement *UndirectedEdge::clone() const
+{
+	return new UndirectedEdge(*this);
+}
+
+GraphElement *UndirectedEdge::plunder() &&
+{
+	return new UndirectedEdge(std::move(*this));
+}
+
+const Node &UndirectedEdge::getFirstNode() const
+{
+	return first;
+}
+
+const Node &UndirectedEdge::getSecondNode() const
+{
+	return second;
+}
+
+const label::Label &UndirectedEdge::getName() const
+{
+	return name;
+}
+
+int UndirectedEdge::compare(const UndirectedEdge &other) const
+{
+	int res = name.getData().compare(other.name.getData());
+	if (res == 0) {
+		if (first.compare(other.second) == 0 && second.compare(other.first) == 0) {
+			return 0;
+		}
+		res = first.compare(other.first);
+		if (res == 0) {
+			res = second.compare(other.second);
+		}
+	}
+	return res;
+}
+
+void UndirectedEdge::operator>>(std::ostream &out) const
+{
+	dump(out);
+}
+
+UndirectedEdge::operator std::string() const
+{
+	std::stringstream ss;
+	ss << *this;
+	return ss.str();
+}
+
+std::ostream &operator<<(std::ostream &out, const UndirectedEdge &node)
+{
+	node.dump(out);
+	return out;
+}
+
+void UndirectedEdge::dump(std::ostream &os) const
+{
+	os << "(UndirectedEdge " << first << " -> " << second << ")";
+}
+
+} // namespace graph
+
diff --git a/alib2data/src/graph/undirected/UndirectedEdge.h b/alib2data/src/graph/undirected/UndirectedEdge.h
new file mode 100644
index 0000000000..894cac3683
--- /dev/null
+++ b/alib2data/src/graph/undirected/UndirectedEdge.h
@@ -0,0 +1,67 @@
+#ifndef UNDIRECTED_EDGE_H_
+#define UNDIRECTED_EDGE_H_
+
+#include "../common/GraphElement.h"
+#include "../common/Macros.h"
+#include "../common/Node.h"
+
+namespace graph {
+
+class UndirectedEdge : public std::acceptor<UndirectedEdge, GraphElement, GraphElement>
+{
+public:
+	explicit UndirectedEdge(const Node &first, const Node &second);
+	explicit UndirectedEdge(Node &&first, Node &&second);
+	explicit UndirectedEdge(const Node &first, const Node &second, const label::Label &name);
+	explicit UndirectedEdge(Node &&first, Node &&second, label::Label &&name);
+	explicit UndirectedEdge(const Node &first, const Node &second, int number);
+	explicit UndirectedEdge(Node &&first, Node &&second, int number);
+	explicit UndirectedEdge(const Node &first, const Node &second, char character);
+	explicit UndirectedEdge(Node &&first, Node &&second, char character);
+	explicit UndirectedEdge(const Node &first, const Node &second, const std::string &name);
+	explicit UndirectedEdge(Node &&first, Node &&second, const std::string &name);
+
+	UndirectedEdge(const UndirectedEdge &other);
+	UndirectedEdge(UndirectedEdge &&other) noexcept;
+	UndirectedEdge &operator=(const UndirectedEdge &other);
+	UndirectedEdge &operator=(UndirectedEdge &&other);
+
+	GraphElement *clone() const;
+	GraphElement *plunder() &&;
+
+	const Node &getFirstNode() const;
+	const Node &getSecondNode() const;
+	const label::Label &getName() const;
+
+	int compare(const GraphElement &other) const override
+	{
+		return -other.compare(*this);
+	}
+
+	int compare(const UndirectedEdge &other) const;
+
+	void operator>>(std::ostream &out) const override;
+
+	operator std::string() const override;
+
+	int selfTypeId() const override
+	{
+		return typeId<UndirectedEdge>();
+	}
+
+	friend std::ostream &operator<<(std::ostream &out, const UndirectedEdge &node);
+
+private:
+	void dump(std::ostream &os) const;
+
+	Node first;
+	Node second;
+	label::Label name;
+};
+
+} // namespace graph
+
+GRAPH_DEFINE_STD_HASH(UndirectedEdge)
+GRAPH_DEFINE_STD_COMPARE(UndirectedEdge)
+
+#endif // UNDIRECTED_EDGE_H_
diff --git a/alib2data/src/graph/undirected/UndirectedGraph.h b/alib2data/src/graph/undirected/UndirectedGraph.h
new file mode 100644
index 0000000000..1c48850279
--- /dev/null
+++ b/alib2data/src/graph/undirected/UndirectedGraph.h
@@ -0,0 +1,14 @@
+#ifndef UNDIRECTED_GRAPH_H_
+#define UNDIRECTED_GRAPH_H_
+
+#include "UndirectedEdge.h"
+
+namespace graph {
+
+class UndirectedGraph
+{
+};
+
+} // namespace graph
+
+#endif // UNDIRECTED_GRAPH_H_
diff --git a/alib2data/src/object/ObjectBase.h b/alib2data/src/object/ObjectBase.h
index 04a619b2f0..5596022611 100644
--- a/alib2data/src/object/ObjectBase.h
+++ b/alib2data/src/object/ObjectBase.h
@@ -64,6 +64,13 @@ class UnrestrictedGrammar;
 
 }
 
+namespace graph {
+
+class DirectedGraph;
+class UndirectedGraph;
+
+}
+
 namespace label {
 
 class PrimitiveLabel;
@@ -135,6 +142,7 @@ typedef std::acceptor_base<ObjectBase,
 			exception::AlibException,
 			automaton::DFA, automaton::NFA, automaton::MultiInitialStateNFA, automaton::EpsilonNFA, automaton::CompactNFA, automaton::ExtendedNFA, automaton::DPDA, automaton::SinglePopDPDA, automaton::InputDrivenDPDA, automaton::VisiblyPushdownDPDA, automaton::RealTimeHeightDeterministicDPDA, automaton::NPDA, automaton::SinglePopNPDA, automaton::InputDrivenNPDA, automaton::VisiblyPushdownNPDA, automaton::RealTimeHeightDeterministicNPDA, automaton::OneTapeDTM,
 			grammar::LeftLG, grammar::LeftRG, grammar::RightLG, grammar::RightRG, grammar::LG, grammar::CFG, grammar::EpsilonFreeCFG, grammar::CNF, grammar::GNF, grammar::CSG, grammar::NonContractingGrammar, grammar::ContextPreservingUnrestrictedGrammar, grammar::UnrestrictedGrammar,
+			graph::DirectedGraph,
 			label::PrimitiveLabel, label::HexavigesimalLabel, label::ObjectLabel, label::LabelSetLabel, label::LabelPairLabel, label::UniqueLabel,
 			regexp::UnboundedRegExp, regexp::FormalRegExp,
 			string::Epsilon, string::LinearString, string::CyclicString,
@@ -150,6 +158,7 @@ class ObjectBase :
 			exception::AlibException,
 			automaton::DFA, automaton::NFA, automaton::MultiInitialStateNFA, automaton::EpsilonNFA, automaton::CompactNFA, automaton::ExtendedNFA, automaton::DPDA, automaton::SinglePopDPDA, automaton::InputDrivenDPDA, automaton::VisiblyPushdownDPDA, automaton::RealTimeHeightDeterministicDPDA, automaton::NPDA, automaton::SinglePopNPDA, automaton::InputDrivenNPDA, automaton::VisiblyPushdownNPDA, automaton::RealTimeHeightDeterministicNPDA, automaton::OneTapeDTM,
 			grammar::LeftLG, grammar::LeftRG, grammar::RightLG, grammar::RightRG, grammar::LG, grammar::CFG, grammar::EpsilonFreeCFG, grammar::CNF, grammar::GNF, grammar::CSG, grammar::NonContractingGrammar, grammar::ContextPreservingUnrestrictedGrammar, grammar::UnrestrictedGrammar,
+			graph::DirectedGraph,
 			label::PrimitiveLabel, label::HexavigesimalLabel, label::ObjectLabel, label::LabelSetLabel, label::LabelPairLabel, label::UniqueLabel,
 			regexp::UnboundedRegExp, regexp::FormalRegExp,
 			string::Epsilon, string::LinearString, string::CyclicString,
diff --git a/alib2data/src/std/compare.hpp b/alib2data/src/std/compare.hpp
index 4e1e780cb0..6f1e7e3559 100644
--- a/alib2data/src/std/compare.hpp
+++ b/alib2data/src/std/compare.hpp
@@ -12,6 +12,7 @@
 #include <vector>
 #include <string>
 #include <map>
+#include <unordered_map>
 #include <tuple>
 
 namespace std {
@@ -92,6 +93,21 @@ struct compare<map<T, R>> {
 	}
 };
 
+template<class T, class R>
+struct compare<unordered_map<T, R>> {
+	int operator()(const unordered_map<T, R>& first, const unordered_map<T, R>& second) const {
+		if(first.size() < second.size()) return -1;
+		if(first.size() > second.size()) return 1;
+
+		compare<std::pair<T, R>> comp;
+		for(auto iterF = first.begin(), iterS = second.begin(); iterF != first.end(); iterF++, iterS++) {
+			int res = comp(*iterF, *iterS);
+			if(res != 0) return res;
+		}
+		return 0;
+	}
+};
+
 template<int I, typename Tuple>
 struct compareTupleHelper;
 
-- 
GitLab