From b5de7f35d208317c8724bb5a521e958393c88ded Mon Sep 17 00:00:00 2001 From: Sebastian Maio Date: Sun, 8 Jul 2018 19:30:32 -0300 Subject: [PATCH 1/5] Fixes undirected weighted/nonweighted graphs betweenness calculaction. --- src/gui/src/mainwindow.cpp | 84 ++++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 26 deletions(-) diff --git a/src/gui/src/mainwindow.cpp b/src/gui/src/mainwindow.cpp index 65a4769..566f564 100644 --- a/src/gui/src/mainwindow.cpp +++ b/src/gui/src/mainwindow.cpp @@ -318,6 +318,7 @@ void MainWindow::onNetworkLoad(const bool weightedgraph, const bool digraph, con if (digraph) { + ui->actionBetweenness->setEnabled(true); ui->actionClustering_coefficient->setEnabled(true); ui->actionNearest_neighbors_degree->setEnabled(true); ui->actionConfigure_Directed_Degree_sign->setEnabled(true); @@ -776,23 +777,35 @@ void MainWindow::computeBetweenness() while (!it.end()) { propertyMap.addProperty( - "betweenness", to_string(it->first), it->second); + "betweenness", to_string(it->first), it->second); ++it; } delete betweenness; } else { - auto betweenness = factory->createBetweenness(graph); - auto it = betweenness->iterator(); - - while (!it.end()) - { - propertyMap.addProperty( - "betweenness", to_string(it->first), it->second); - ++it; + if(digraph) { + auto betweenness = directedFactory->createBetweenness(directedGraph); + auto it = betweenness->iterator(); + while (!it.end()) + { + propertyMap.addProperty( + "betweenness", to_string(it->first), (it->second)); + ++it; + } + delete betweenness; + } + else { + auto betweenness = factory->createBetweenness(graph); + auto it = betweenness->iterator(); + while (!it.end()) + { + propertyMap.addProperty( + "betweenness", to_string(it->first), (it->second) / 2); + ++it; + } + delete betweenness; } - delete betweenness; } } @@ -2390,27 +2403,46 @@ graphpp::Boxplotentry MainWindow::computeTotalBpEntriesKnn() graphpp::Boxplotentry MainWindow::computeTotalBpEntriesBetweenness() { - Graph& g = graph; - auto vit = g.verticesIterator(); std::vector bCoefs; - - auto betweenness = factory->createBetweenness(g); - // TODO: replace with smart pointer - delete betweenness; - double coefSums = 0.0; unsigned int count = 0; - while (!vit.end()) - { - Vertex* v = *vit; - double c = propertyMap.getProperty( - "betweenness", to_string(v->getVertexId())); - bCoefs.push_back(c); - coefSums += c; - ++vit; - count++; + if(weightedgraph) { + WeightedGraph& wg = weightedGraph; + auto vit = weightedGraph.verticesIterator(); + if (! propertyMap.containsPropertySet("betweenness")) { + auto betweenness = weightedFactory->createBetweenness(wg); + delete betweenness; + } + while (!vit.end()) + { + Vertex* v = *vit; + double c = propertyMap.getProperty( + "betweenness", to_string(v->getVertexId())); + bCoefs.push_back(c); + coefSums += c; + ++vit; + count++; + } + } else { + Graph& g = graph; + auto vit = graph.verticesIterator(); + if (! propertyMap.containsPropertySet("betweenness")) { + auto betweenness = factory->createBetweenness(g); + delete betweenness; + } + while (!vit.end()) + { + Vertex* v = *vit; + double c = propertyMap.getProperty( + "betweenness", to_string(v->getVertexId())); + bCoefs.push_back(c); + coefSums += c; + ++vit; + count++; + } } + std::sort(bCoefs.begin(), bCoefs.end()); graphpp::Boxplotentry entry; if (bCoefs.size() > 0) From b380617c192bc2d684ba580983fef04d02c099a6 Mon Sep 17 00:00:00 2001 From: Sebastian Maio Date: Sun, 8 Jul 2018 23:59:18 -0300 Subject: [PATCH 2/5] Directed betweenneess working --- CMakeLists.txt | 2 +- src/core/inc/DirectedBetweenness.h | 131 ++++++++++++++++++++++++++++ src/core/inc/DirectedGraphFactory.h | 7 +- src/core/inc/IGraphFactory.h | 1 + src/gui/src/mainwindow.cpp | 18 ++++ 5 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 src/core/inc/DirectedBetweenness.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2061034..3fc30b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,8 +60,8 @@ set(CORE_HEADERS src/core/inc/NearestNeighborsDegree.h src/core/inc/WeightedNearestNeighborsDegree.h src/core/inc/GraphGenerator.h + src/core/inc/DirectedBetweenness.h src/core/inc/Betweenness.h - src/core/inc/IBetweenness.h src/core/inc/Boxplotentry.h src/core/inc/WeightedGraphFactory.h src/core/inc/WeightedClusteringCoefficient.h diff --git a/src/core/inc/DirectedBetweenness.h b/src/core/inc/DirectedBetweenness.h new file mode 100644 index 0000000..00b3f8f --- /dev/null +++ b/src/core/inc/DirectedBetweenness.h @@ -0,0 +1,131 @@ +#pragma once + +#include +#include +#include +#include + + +#include "IBetweenness.h" +#include "mili/mili.h" +#include "typedefs.h" + +namespace graphpp +{ +template +class DirectedBetweenness : public IBetweenness +{ +public: + typedef typename IBetweenness::BetweennessContainer BetweennessContainer; + typedef typename IBetweenness::BetweennessIterator BetweennessIterator; + + DirectedBetweenness(DirectedGraph& g) + { + initMap(g, 1, betweenness, 0.0, 0.0); + calculateBetweenness(g); + } + + virtual BetweennessIterator iterator() + { + return BetweennessIterator(betweenness); + } + +private: + void calculateBetweenness(DirectedGraph& g) + { + auto iter = g.verticesIterator(); + + while (!iter.end()) + { + DirectedVertex* s = *iter; + std::stack stack; + std::queue queue; + std::map> p; + std::map sigma; + std::map d; + std::map delta; + + initMap(g, s->getVertexId(), sigma, 0.0, 1.0); + initMap(g, s->getVertexId(), d, -1.0, 0.0); + initMap(g, s->getVertexId(), delta, 0.0, 0.0); + + queue.push(s); + + while (!queue.empty()) + { + DirectedVertex* v = queue.front(); + queue.pop(); + stack.push(v); + + // iterate through v's neighbors + auto neighbourIter = v->outNeighborsIterator(); + + while (!neighbourIter.end()) + { + Vertex* w = (Vertex*)*neighbourIter; + // w found for the first time? + double wValue = d[w->getVertexId()]; + // double vValue = d[v->getVertexId()]; + if (wValue < 0) + { + queue.push(w); + d[w->getVertexId()] = d[v->getVertexId()] + 1; + } + // shortest path to w via v? + if (d[w->getVertexId()] == (d[v->getVertexId()] + 1)) + { + sigma[w->getVertexId()] = sigma[w->getVertexId()] + sigma[v->getVertexId()]; + p[w->getVertexId()].push_back(v->getVertexId()); + } + + ++neighbourIter; + } + } + + // S returns vertices in order of non-increasing distance from s + while (!stack.empty()) + { + Vertex* w = stack.top(); + stack.pop(); + + std::list vertices = p[w->getVertexId()]; + + for (const auto& v : vertices) + { + delta[v] = delta[v] + ((1 + delta[w->getVertexId()]) * + (sigma[v] / sigma[w->getVertexId()])); + } + + if (w->getVertexId() != s->getVertexId()) + { + betweenness[w->getVertexId()] += delta[w->getVertexId()]; + } + } + + ++iter; + } + } + + void initMap( + DirectedGraph& g, + unsigned int vertexId, + std::map& m, + double commonValue, + double distinguishedValue) + { + auto it = g.verticesIterator(); + + // initialize all elements in zero, except for the current vertex + while (!it.end()) + { + Vertex* v = *it; + m.insert(std::pair(v->getVertexId(), commonValue)); + ++it; + } + // modify the value associated to key 'vertexId' + m[vertexId] = distinguishedValue; + } + + BetweennessContainer betweenness; +}; +} // namespace graphpp diff --git a/src/core/inc/DirectedGraphFactory.h b/src/core/inc/DirectedGraphFactory.h index 8bac470..dadb471 100644 --- a/src/core/inc/DirectedGraphFactory.h +++ b/src/core/inc/DirectedGraphFactory.h @@ -5,6 +5,7 @@ #include "DirectedNearestNeighborsDegree.h" #include "GraphReader.h" #include "IGraphFactory.h" +#include "DirectedBetweenness.h" namespace graphpp { @@ -16,11 +17,9 @@ class DirectedGraphFactory : public IGraphFactory { return new GraphReader(); } - virtual IBetweenness* createBetweenness(Graph&) + virtual IBetweenness* createBetweenness(DirectedGraph& g) { - // TODO Implement this - // return new DirectedBetweenness(); - return nullptr; + return new DirectedBetweenness(g); } virtual IClusteringCoefficient* createClusteringCoefficient() { diff --git a/src/core/inc/IGraphFactory.h b/src/core/inc/IGraphFactory.h index 33fe24b..da01452 100644 --- a/src/core/inc/IGraphFactory.h +++ b/src/core/inc/IGraphFactory.h @@ -8,6 +8,7 @@ #include "IShellIndex.h" #include "MaxClique.h" #include "StrengthDistribution.h" +#include "typedefs.h" namespace graphpp { diff --git a/src/gui/src/mainwindow.cpp b/src/gui/src/mainwindow.cpp index 566f564..cf6875f 100644 --- a/src/gui/src/mainwindow.cpp +++ b/src/gui/src/mainwindow.cpp @@ -2424,6 +2424,24 @@ graphpp::Boxplotentry MainWindow::computeTotalBpEntriesBetweenness() ++vit; count++; } + } + else if(digraph) { + DirectedGraph& dg = directedGraph; + auto vit = directedGraph.verticesIterator(); + if (! propertyMap.containsPropertySet("betweenness")) { + auto betweenness = directedFactory->createBetweenness(dg); + delete betweenness; + } + while (!vit.end()) + { + Vertex* v = *vit; + double c = propertyMap.getProperty( + "betweenness", to_string(v->getVertexId())); + bCoefs.push_back(c); + coefSums += c; + ++vit; + count++; + } } else { Graph& g = graph; auto vit = graph.verticesIterator(); From 40313e209fa64ffb2552a9682c406e6a65293758 Mon Sep 17 00:00:00 2001 From: Sebastian Maio Date: Mon, 9 Jul 2018 00:01:21 -0300 Subject: [PATCH 3/5] Fixes double count of paths for weighted non directed. --- src/gui/src/mainwindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/src/mainwindow.cpp b/src/gui/src/mainwindow.cpp index cf6875f..28b7328 100644 --- a/src/gui/src/mainwindow.cpp +++ b/src/gui/src/mainwindow.cpp @@ -771,13 +771,14 @@ void MainWindow::computeBetweenness() if (this->weightedgraph) { + // TODO Asumes there are no directed wieghted graphs auto betweenness = weightedFactory->createBetweenness(weightedGraph); auto it = betweenness->iterator(); while (!it.end()) { propertyMap.addProperty( - "betweenness", to_string(it->first), it->second); + "betweenness", to_string(it->first), (it->second)/2); ++it; } delete betweenness; From db931563a5151a26edc1549bea02ad0bdb74e393 Mon Sep 17 00:00:00 2001 From: Sebastian Maio Date: Mon, 9 Jul 2018 19:16:08 -0300 Subject: [PATCH 4/5] Deletes old properties when a new graph is created. --- src/gui/src/mainwindow.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gui/src/mainwindow.cpp b/src/gui/src/mainwindow.cpp index 28b7328..de19e56 100644 --- a/src/gui/src/mainwindow.cpp +++ b/src/gui/src/mainwindow.cpp @@ -1849,7 +1849,7 @@ void MainWindow::on_actionNewErdosRenyi_triggered() { this->onNetworkLoad(false, false, false); buildGraphFactory(false, false); - + propertyMap.clear(); graph = *(GraphGenerator::getInstance()->generateErdosRenyiGraph(n, p)); QString text("Network created using Erdos-Renyi algorithm"); @@ -1887,6 +1887,7 @@ void MainWindow::on_actionNewHiperbolic_triggered() { this->onNetworkLoad(false, false, false); buildGraphFactory(false, false); + propertyMap.clear(); QString text("Creating a network using a Papadopoulos hyperbolic graph algorithm..."); text.append("\nexpected avg node deg: "); @@ -1932,6 +1933,7 @@ void MainWindow::on_actionNewBarabasiAlbert_triggered() try { + propertyMap.clear(); this->onNetworkLoad(false, false, false); buildGraphFactory(false, false); @@ -1984,7 +1986,7 @@ void MainWindow::on_actionNewExtendedHOT_triggered() // The default parameters are taken from the paper // (http://cnet.fi.uba.ar/ignacio.alvarez-hamelin/pdf/model_internet_jiah_ns.pdf) - + propertyMap.clear(); unsigned int m = 1; unsigned int n = 50; unsigned int q = 1; @@ -2057,6 +2059,7 @@ void MainWindow::on_actionNewMolloyReed_triggered() { try { + propertyMap.clear(); this->onNetworkLoad(false, false, false); buildGraphFactory(false, false); From 0f6e0278293ee8a2d2a1574a61507d3bfffecb06 Mon Sep 17 00:00:00 2001 From: Sebastian Maio Date: Fri, 13 Jul 2018 00:07:55 -0300 Subject: [PATCH 5/5] Fixes weighted and unweighted plots --- src/core/inc/Betweenness.h | 2 +- src/core/inc/DirectedBetweenness.h | 2 +- src/core/inc/WeightedBetweenness.h | 2 +- src/gui/src/mainwindow.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/inc/Betweenness.h b/src/core/inc/Betweenness.h index 29a42b3..b52be11 100644 --- a/src/core/inc/Betweenness.h +++ b/src/core/inc/Betweenness.h @@ -19,7 +19,7 @@ class Betweenness : public IBetweenness Betweenness(Graph& g) { - initMap(g, 1, betweenness, 0.0, 0.0); + initMap(g, (*g.verticesIterator())->getVertexId(), betweenness, 0.0, 0.0); calculateBetweenness(g); } diff --git a/src/core/inc/DirectedBetweenness.h b/src/core/inc/DirectedBetweenness.h index 00b3f8f..99e0aba 100644 --- a/src/core/inc/DirectedBetweenness.h +++ b/src/core/inc/DirectedBetweenness.h @@ -21,7 +21,7 @@ class DirectedBetweenness : public IBetweenness DirectedBetweenness(DirectedGraph& g) { - initMap(g, 1, betweenness, 0.0, 0.0); + initMap(g, (*g.verticesIterator())->getVertexId(), betweenness, 0.0, 0.0); calculateBetweenness(g); } diff --git a/src/core/inc/WeightedBetweenness.h b/src/core/inc/WeightedBetweenness.h index b7bedfb..2fdf22c 100644 --- a/src/core/inc/WeightedBetweenness.h +++ b/src/core/inc/WeightedBetweenness.h @@ -41,7 +41,7 @@ class WeightedBetweenness : public IBetweenness WeightedBetweenness(Graph& g) { - initMap(g, 1, betweenness, 0.0, 0.0); + initMap(g, (*g.verticesIterator())->getVertexId(), betweenness, 0.0, 0.0); calculateBetweenness(g); } diff --git a/src/gui/src/mainwindow.cpp b/src/gui/src/mainwindow.cpp index de19e56..0755f95 100644 --- a/src/gui/src/mainwindow.cpp +++ b/src/gui/src/mainwindow.cpp @@ -817,7 +817,7 @@ void MainWindow::computeDegreeDistribution() if (this->weightedgraph) { - auto degreeDistribution = weightedFactory->createStrengthDistribution(weightedGraph); + auto degreeDistribution = weightedFactory->createDegreeDistribution(weightedGraph); auto it = degreeDistribution->iterator(); while (!it.end())