Skip to content
Snippets Groups Projects
Commit 59a2c48c authored by David Rosca's avatar David Rosca
Browse files

Graph: compare by node/edge values + output to xml/string

parent 03169212
No related branches found
Tags BP-roscadav
No related merge requests found
Showing
with 348 additions and 12 deletions
......@@ -39,12 +39,42 @@ L0:
token.value += character;
token.raw += character;
return token;
} else if (character == '=') {
token.type = TokenType::EQUAL;
token.value += character;
token.raw += character;
return token;
} else if (character >= '0' && character <= '9') {
token.type = TokenType::INTEGER;
token.value += character;
token.raw += character;
goto L1;
} else {
in.putback(character);
putback(in, std::move(token));
token.type = TokenType::ERROR;
return token;
}
L1:
character = in.get();
if (in.eof()) {
return token;
} else if (character >= '0' && character <= '9') {
token.value += character;
token.raw += character;
goto L1;
} else {
in.unget();
return token;
}
}
GraphFromStringLexer::Token GraphFromStringLexer::peek(std::istream &in) const
{
Token token = next(in);
putback(in, token);
return token;
}
 
void GraphFromStringLexer::putback(std::istream &input, GraphFromStringLexer::Token token) const
......
......@@ -14,6 +14,8 @@ public:
RPAR,
COLON,
COMMA,
EQUAL,
INTEGER,
TEOF,
ERROR
};
......@@ -25,6 +27,7 @@ public:
};
 
Token next(std::istream &input) const;
Token peek(std::istream &input) const;
void putback(std::istream &input, Token token) const;
 
std::string getString(std::istream &input) const;
......
......@@ -41,6 +41,10 @@ DirectedGraph GraphFromStringParser::parseDirectedGraph(std::istream &input) con
parseNodes(input, graph);
parseDelimiter(input); // :
parseDirectedEdges(input, graph);
parseDelimiter(input); // :
parseNodeValues(input, graph);
parseDelimiter(input); // :
parseDirectedEdgeValues(input, graph);
return graph;
}
 
......@@ -51,6 +55,10 @@ UndirectedGraph GraphFromStringParser::parseUndirectedGraph(std::istream &input)
parseNodes(input, graph);
parseDelimiter(input); // :
parseUndirectedEdges(input, graph);
parseDelimiter(input); // :
parseNodeValues(input, graph);
parseDelimiter(input); // :
parseUndirectedEdgeValues(input, graph);
return graph;
}
 
......@@ -116,7 +124,6 @@ void GraphFromStringParser::parseDirectedEdges(std::istream &input, DirectedGrap
}
lexer.putback(input, token);
 
while (true) {
graph.addEdge(parseDirectedEdge(input));
 
......@@ -157,4 +164,86 @@ void GraphFromStringParser::parseDelimiter(std::istream &input) const
}
}
 
int GraphFromStringParser::parseValue(std::istream &input) const
{
GraphFromStringLexer::Token token = lexer.next(input);
if (token.type != GraphFromStringLexer::TokenType::EQUAL) {
throw exception::AlibException("Invalid input. Expected EQUAL");
}
token = lexer.next(input);
if (token.type != GraphFromStringLexer::TokenType::INTEGER) {
throw exception::AlibException("Invalid input. Expected INTEGER");
}
return std::stoi(token.value);
}
template<typename T>
void GraphFromStringParser::parseNodeValues(std::istream &input, T &graph) const
{
GraphFromStringLexer::Token token = lexer.peek(input);
// Empty values?
if (token.type == GraphFromStringLexer::TokenType::COLON) {
return;
}
while (true) {
graph::Node node = parseNode(input);
int value = parseValue(input);
graph.setNodeValue(node, value);
token = lexer.next(input);
if (token.type != GraphFromStringLexer::TokenType::COMMA) {
lexer.putback(input, token);
return;
}
}
}
void GraphFromStringParser::parseDirectedEdgeValues(std::istream &input, DirectedGraph &graph) const
{
GraphFromStringLexer::Token token = lexer.peek(input);
// Empty values?
if (token.type == GraphFromStringLexer::TokenType::RPAR) {
return;
}
while (true) {
graph::DirectedEdge node = parseDirectedEdge(input);
int value = parseValue(input);
graph.setEdgeValue(node, value);
token = lexer.next(input);
if (token.type != GraphFromStringLexer::TokenType::COMMA) {
lexer.putback(input, token);
return;
}
}
}
void GraphFromStringParser::parseUndirectedEdgeValues(std::istream &input, UndirectedGraph &graph) const
{
GraphFromStringLexer::Token token = lexer.peek(input);
// Empty values?
if (token.type == GraphFromStringLexer::TokenType::RPAR) {
return;
}
while (true) {
graph::UndirectedEdge node = parseUndirectedEdge(input);
int value = parseValue(input);
graph.setEdgeValue(node, value);
token = lexer.next(input);
if (token.type != GraphFromStringLexer::TokenType::COMMA) {
lexer.putback(input, token);
return;
}
}
}
} // namespace graph
......@@ -36,6 +36,12 @@ private:
void parseDirectedEdges(std::istream &input, DirectedGraph &graph) const;
void parseUndirectedEdges(std::istream &input, UndirectedGraph &graph) const;
void parseDelimiter(std::istream &input) const;
int parseValue(std::istream &input) const;
template<typename T>
void parseNodeValues(std::istream &input, T &graph) const;
void parseDirectedEdgeValues(std::istream &input, DirectedGraph &graph) const;
void parseUndirectedEdgeValues(std::istream &input, UndirectedGraph &graph) const;
 
GraphFromStringLexer lexer;
 
......
......@@ -32,6 +32,8 @@ DirectedGraph GraphFromXMLParser::parseDirectedGraph(std::list<sax::Token> &inpu
DirectedGraph graph(parseRepresentation(input));
parseNodes(input, graph);
parseDirectedEdges(input, graph);
parseNodeValues(input, graph);
parseDirectedEdgeValues(input, graph);
 
popToken(input, sax::Token::TokenType::END_ELEMENT, alib::Names::GRAPH_DIRECTED_GRAPH);
return graph;
......@@ -44,6 +46,8 @@ UndirectedGraph GraphFromXMLParser::parseUndirectedGraph(std::list<sax::Token> &
UndirectedGraph graph(parseRepresentation(input));
parseNodes(input, graph);
parseUndirectedEdges(input, graph);
parseNodeValues(input, graph);
parseUndirectedEdgeValues(input, graph);
 
popToken(input, sax::Token::TokenType::END_ELEMENT, alib::Names::GRAPH_UNDIRECTED_GRAPH);
return graph;
......@@ -105,6 +109,16 @@ UndirectedEdge GraphFromXMLParser::parseUndirectedEdge(std::list<sax::Token> &in
return UndirectedEdge(first, second, name);
}
 
int GraphFromXMLParser::parseValue(std::list<sax::Token> &input) const
{
popToken(input, sax::Token::TokenType::START_ELEMENT, "value");
int value = std::stoi(popTokenData(input, sax::Token::TokenType::CHARACTER));
popToken(input, sax::Token::TokenType::END_ELEMENT, "value");
return value;
}
template<typename T>
void GraphFromXMLParser::parseNodes(std::list<sax::Token> &input, T &graph) const
{
......@@ -139,5 +153,48 @@ void GraphFromXMLParser::parseUndirectedEdges(std::list<sax::Token> &input, Undi
popToken(input, sax::Token::TokenType::END_ELEMENT, "edges");
}
 
template<typename T>
void GraphFromXMLParser::parseNodeValues(std::list<sax::Token> &input, T &graph) const
{
popToken(input, sax::Token::TokenType::START_ELEMENT, "nodevalues");
while (isTokenType(input, sax::Token::TokenType::START_ELEMENT)) {
graph::Node node = parseNode(input);
int value = parseValue(input);
graph.setNodeValue(node, value);
}
popToken(input, sax::Token::TokenType::END_ELEMENT, "nodevalues");
}
void GraphFromXMLParser::parseDirectedEdgeValues(std::list<sax::Token> &input, DirectedGraph &graph) const
{
popToken(input, sax::Token::TokenType::START_ELEMENT, "edgevalues");
while (isTokenType(input, sax::Token::TokenType::START_ELEMENT)) {
graph::DirectedEdge edge = parseDirectedEdge(input);
int value = parseValue(input);
graph.setEdgeValue(edge, value);
}
popToken(input, sax::Token::TokenType::END_ELEMENT, "edgevalues");
}
void GraphFromXMLParser::parseUndirectedEdgeValues(std::list<sax::Token> &input, UndirectedGraph &graph) const
{
popToken(input, sax::Token::TokenType::START_ELEMENT, "edgevalues");
while (isTokenType(input, sax::Token::TokenType::START_ELEMENT)) {
graph::UndirectedEdge edge = parseUndirectedEdge(input);
int value = parseValue(input);
graph.setEdgeValue(edge, value);
}
popToken(input, sax::Token::TokenType::END_ELEMENT, "edgevalues");
}
} // namespace graph
 
......@@ -33,12 +33,18 @@ private:
Node parseNode(std::list<sax::Token> &input) const;
DirectedEdge parseDirectedEdge(std::list<sax::Token> &input) const;
UndirectedEdge parseUndirectedEdge(std::list<sax::Token> &input) const;
int parseValue(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>
void parseNodeValues(std::list<sax::Token> &input, T &graph) const;
void parseDirectedEdgeValues(std::list<sax::Token> &input, DirectedGraph &graph) const;
void parseUndirectedEdgeValues(std::list<sax::Token> &input, UndirectedGraph &graph) const;
template<typename T> friend class alib::xmlApi;
};
 
......
......@@ -22,6 +22,10 @@ void GraphToStringComposer::Visit(void *data, const DirectedGraph &graph) const
composeNodes(out, graph.getNodes());
out << ":";
composeDirectedEdges(out, graph.getEdges());
out << ":";
composeNodeValues(out, graph);
out << ":";
composeEdgeValues(out, graph);
}
 
void GraphToStringComposer::Visit(void *data, const UndirectedGraph &graph) const
......@@ -34,6 +38,10 @@ void GraphToStringComposer::Visit(void *data, const UndirectedGraph &graph) cons
composeNodes(out, graph.getNodes());
out << ":";
composeUndirectedEdges(out, graph.getEdges());
out << ":";
composeNodeValues(out, graph);
out << ":";
composeEdgeValues(out, graph);
}
 
void GraphToStringComposer::Visit(void *data, const Node &node) const
......@@ -108,4 +116,36 @@ void GraphToStringComposer::composeUndirectedEdges(std::ostream &out, const std:
}
}
 
template<typename T>
void GraphToStringComposer::composeNodeValues(std::ostream &out, const T &graph) const
{
bool first = true;
for (auto i : graph.nodeValues) {
if (first) {
first = false;
} else {
out << ",";
}
i.first.Accept(static_cast<void*>(&out), *this);
out << "=" << i.second;
}
}
template<typename T>
void GraphToStringComposer::composeEdgeValues(std::ostream &out, const T &graph) const
{
bool first = true;
for (auto i : graph.edgeValues) {
if (first) {
first = false;
} else {
out << ",";
}
i.first.Accept(static_cast<void*>(&out), *this);
out << "=" << i.second;
}
}
} // namespace graph
......@@ -31,6 +31,12 @@ private:
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;
template<typename T>
void composeNodeValues(std::ostream &out, const T &graph) const;
template<typename T>
void composeEdgeValues(std::ostream &out, const T &graph) const;
};
 
} // namespace graph
......
......@@ -2,6 +2,7 @@
#include "GraphRepresentation.h"
 
#include "../XmlApi.hpp"
#include "../std/itos.h"
 
namespace graph {
 
......@@ -68,7 +69,9 @@ void GraphToXMLComposer::compose(std::list<sax::Token> &out, const DirectedGraph
 
composeRepresentation(out, representationToString(graph.getRepresentation()));
composeNodes(out, graph.getNodes());
composeDirectedEdges(out, graph.getEdges());
composeEdges(out, graph.getEdges());
composeNodeValues(out, graph);
composeEdgeValues(out, graph);
 
out.push_back(sax::Token(alib::Names::GRAPH_DIRECTED_GRAPH, sax::Token::TokenType::END_ELEMENT));
}
......@@ -79,7 +82,9 @@ void GraphToXMLComposer::compose(std::list<sax::Token> &out, const UndirectedGra
 
composeRepresentation(out, representationToString(graph.getRepresentation()));
composeNodes(out, graph.getNodes());
composeUndirectedEdges(out, graph.getEdges());
composeEdges(out, graph.getEdges());
composeNodeValues(out, graph);
composeEdgeValues(out, graph);
 
out.push_back(sax::Token(alib::Names::GRAPH_UNDIRECTED_GRAPH, sax::Token::TokenType::END_ELEMENT));
}
......@@ -100,22 +105,40 @@ void GraphToXMLComposer::composeNodes(std::list<sax::Token> &out, const std::set
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
template<typename T>
void GraphToXMLComposer::composeEdges(std::list<sax::Token> &out, const std::set<T> &edges) const
{
out.push_back(sax::Token("edges", sax::Token::TokenType::START_ELEMENT));
for (const DirectedEdge &edge : edges) {
for (const auto &edge : edges) {
edge.Accept(static_cast<void*>(&out), *this);
}
out.push_back(sax::Token("edges", sax::Token::TokenType::END_ELEMENT));
}
 
void GraphToXMLComposer::composeUndirectedEdges(std::list<sax::Token> &out, const std::set<UndirectedEdge> &edges) const
template<typename T>
void GraphToXMLComposer::composeNodeValues(std::list<sax::Token> &out, const T &graph) const
{
out.push_back(sax::Token("edges", sax::Token::TokenType::START_ELEMENT));
for (const UndirectedEdge &edge : edges) {
edge.Accept(static_cast<void*>(&out), *this);
out.push_back(sax::Token("nodevalues", sax::Token::TokenType::START_ELEMENT));
for (auto i : graph.nodeValues) {
i.first.Accept(static_cast<void*>(&out), *this);
out.push_back(sax::Token("value", sax::Token::TokenType::START_ELEMENT));
out.push_back(sax::Token(std::itos(i.second), sax::Token::TokenType::CHARACTER));
out.push_back(sax::Token("value", sax::Token::TokenType::END_ELEMENT));
}
out.push_back(sax::Token("edges", sax::Token::TokenType::END_ELEMENT));
out.push_back(sax::Token("nodevalues", sax::Token::TokenType::END_ELEMENT));
}
template<typename T>
void GraphToXMLComposer::composeEdgeValues(std::list<sax::Token> &out, const T &graph) const
{
out.push_back(sax::Token("edgevalues", sax::Token::TokenType::START_ELEMENT));
for (auto &i : graph.edgeValues) {
i.first.Accept(static_cast<void*>(&out), *this);
out.push_back(sax::Token("value", sax::Token::TokenType::START_ELEMENT));
out.push_back(sax::Token(std::itos(i.second), sax::Token::TokenType::CHARACTER));
out.push_back(sax::Token("value", sax::Token::TokenType::END_ELEMENT));
}
out.push_back(sax::Token("edgevalues", sax::Token::TokenType::END_ELEMENT));
}
 
} // namespace graph
......@@ -35,8 +35,14 @@ private:
 
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;
void composeUndirectedEdges(std::list<sax::Token> &out, const std::set<UndirectedEdge> &edges) const;
template<typename T>
void composeEdges(std::list<sax::Token> &out, const std::set<T> &edges) const;
template<typename T>
void composeNodeValues(std::list<sax::Token> &out, const T &graph) const;
template<typename T>
void composeEdgeValues(std::list<sax::Token> &out, const T &graph) const;
 
template<typename T> friend class alib::xmlApi;
};
......
......@@ -23,6 +23,8 @@ DirectedGraph::~DirectedGraph() noexcept
 
DirectedGraph::DirectedGraph(const DirectedGraph &other)
: representation(other.representation)
, nodeValues(other.nodeValues)
, edgeValues(other.edgeValues)
{
init();
impl->copy(other.impl);
......@@ -31,6 +33,8 @@ DirectedGraph::DirectedGraph(const DirectedGraph &other)
DirectedGraph::DirectedGraph(DirectedGraph &&other) noexcept
: representation(other.representation)
, impl(other.impl)
, nodeValues(std::move(other.nodeValues))
, edgeValues(std::move(other.edgeValues))
{
other.impl = 0;
}
......@@ -49,6 +53,8 @@ DirectedGraph &DirectedGraph::operator=(DirectedGraph &&other) noexcept
{
this->representation = other.representation;
std::swap(this->impl, other.impl);
std::swap(this->nodeValues, other.nodeValues);
std::swap(this->edgeValues, other.edgeValues);
return *this;
}
 
......@@ -184,6 +190,16 @@ int DirectedGraph::compare(const DirectedGraph &other) const
return static_cast<int>(representation) - static_cast<int>(other.representation);
}
 
auto first = std::tie(nodeValues, edgeValues);
auto second = std::tie(other.nodeValues, other.edgeValues);
std::compare<decltype(first)> comp;
int res = comp(first, second);
if (res != 0) {
return res;
}
return impl->compare(other.impl);
}
 
......
......@@ -79,6 +79,9 @@ private:
 
std::unordered_map<Node, int> nodeValues;
std::unordered_map<DirectedEdge, int> edgeValues;
friend class GraphToXMLComposer;
friend class GraphToStringComposer;
};
 
} // namespace graph
......
......@@ -23,6 +23,8 @@ UndirectedGraph::~UndirectedGraph() noexcept
 
UndirectedGraph::UndirectedGraph(const UndirectedGraph &other)
: representation(other.representation)
, nodeValues(other.nodeValues)
, edgeValues(other.edgeValues)
{
init();
impl->copy(other.impl);
......@@ -31,6 +33,8 @@ UndirectedGraph::UndirectedGraph(const UndirectedGraph &other)
UndirectedGraph::UndirectedGraph(UndirectedGraph &&other) noexcept
: representation(other.representation)
, impl(other.impl)
, nodeValues(std::move(other.nodeValues))
, edgeValues(std::move(other.edgeValues))
{
other.impl = 0;
}
......@@ -49,6 +53,8 @@ UndirectedGraph &UndirectedGraph::operator=(UndirectedGraph &&other) noexcept
{
this->representation = other.representation;
std::swap(this->impl, other.impl);
std::swap(this->nodeValues, other.nodeValues);
std::swap(this->edgeValues, other.edgeValues);
return *this;
}
 
......@@ -184,6 +190,16 @@ int UndirectedGraph::compare(const UndirectedGraph &other) const
return static_cast<int>(representation) - static_cast<int>(other.representation);
}
 
auto first = std::tie(nodeValues, edgeValues);
auto second = std::tie(other.nodeValues, other.edgeValues);
std::compare<decltype(first)> comp;
int res = comp(first, second);
if (res != 0) {
return res;
}
return impl->compare(other.impl);
}
 
......
......@@ -79,6 +79,9 @@ private:
 
std::unordered_map<Node, int> nodeValues;
std::unordered_map<UndirectedEdge, int> edgeValues;
friend class GraphToXMLComposer;
friend class GraphToStringComposer;
};
 
} // namespace graph
......
......@@ -182,6 +182,14 @@ void GraphTest::testXMLParser_impl(graph::REPRESENTATION representation)
graph::Graph dg2 = alib::XmlDataFactory::fromString<graph::Graph>(tmp);
CPPUNIT_ASSERT(dg1 == dg2);
 
dg.setEdgeValue(graph::DirectedEdge(n1, n2), 1);
dg.setEdgeValue(graph::DirectedEdge(n1, n3), 2);
graph::Graph dg1_2(dg);
tmp = alib::XmlDataFactory::toString(dg1_2);
graph::Graph dg2_2 = alib::XmlDataFactory::fromString<graph::Graph>(tmp);
CPPUNIT_ASSERT(dg1_2 == dg2_2);
// Undirected
graph::UndirectedGraph ug(representation);
ug.addNode(n1);
......@@ -194,6 +202,14 @@ void GraphTest::testXMLParser_impl(graph::REPRESENTATION representation)
tmp = alib::XmlDataFactory::toString(ug1);
graph::Graph ug2 = alib::XmlDataFactory::fromString<graph::Graph>(tmp);
CPPUNIT_ASSERT(ug1 == ug2);
ug.setEdgeValue(graph::UndirectedEdge(n1, n2), 1);
ug.setEdgeValue(graph::UndirectedEdge(n1, n3), 2);
graph::Graph ug1_2(ug);
tmp = alib::XmlDataFactory::toString(ug1_2);
graph::Graph ug2_2 = alib::XmlDataFactory::fromString<graph::Graph>(tmp);
CPPUNIT_ASSERT(ug1_2 == ug2_2);
}
 
void GraphTest::testStringParser_impl(graph::REPRESENTATION representation)
......@@ -216,6 +232,14 @@ void GraphTest::testStringParser_impl(graph::REPRESENTATION representation)
graph::Graph dg2 = alib::StringDataFactory::fromString<graph::Graph>(tmp);
CPPUNIT_ASSERT(dg1 == dg2);
 
dg.setEdgeValue(graph::DirectedEdge(n1, n2), 1);
dg.setEdgeValue(graph::DirectedEdge(n1, n3), 2);
graph::Graph dg1_2(dg);
tmp = alib::StringDataFactory::toString(dg1_2);
graph::Graph dg2_2 = alib::StringDataFactory::fromString<graph::Graph>(tmp);
CPPUNIT_ASSERT(dg1_2 == dg2_2);
// Undirected
graph::UndirectedGraph ug(representation);
ug.addNode(n1);
......@@ -228,6 +252,14 @@ void GraphTest::testStringParser_impl(graph::REPRESENTATION representation)
tmp = alib::StringDataFactory::toString(ug1);
graph::Graph ug2 = alib::StringDataFactory::fromString<graph::Graph>(tmp);
CPPUNIT_ASSERT(ug1 == ug2);
ug.setEdgeValue(graph::UndirectedEdge(n1, n2), 1);
ug.setEdgeValue(graph::UndirectedEdge(n1, n3), 2);
graph::Graph ug1_2(ug);
tmp = alib::StringDataFactory::toString(ug1_2);
graph::Graph ug2_2 = alib::StringDataFactory::fromString<graph::Graph>(tmp);
CPPUNIT_ASSERT(ug1_2 == ug2_2);
}
 
void GraphTest::testAddEdge_impl(graph::REPRESENTATION representation)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment