Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@

### pgRouting 3.7.2 Release Notes

No Changes Yet
**Bug fixes**

* [#2706](https://github.com/pgRouting/pgrouting/pull/2706) winnie crashing
on pgr_betweennessCentrality

### pgRouting 3.7.1 Release Notes

Expand Down
5 changes: 4 additions & 1 deletion doc/src/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ pgRouting 3.7
pgRouting 3.7.2 Release Notes
-------------------------------------------------------------------------------

No Changes Yet
.. rubric:: Bug fixes

* `#2706 <https://github.com/pgRouting/pgrouting/pull/2706>`__ winnie crashing
on pgr_betweennessCentrality

pgRouting 3.7.1 Release Notes
-------------------------------------------------------------------------------
Expand Down
75 changes: 75 additions & 0 deletions include/cpp_common/to_postgres.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*PGR-GNU*****************************************************************
File: to_postgres.hpp

Copyright (c) 2015 pgRouting developers
Mail: project@pgrouting.org

------

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

********************************************************************PGR-GNU*/

#ifndef INCLUDE_CPP_COMMON_TO_POSTGRES_HPP_
#define INCLUDE_CPP_COMMON_TO_POSTGRES_HPP_
#pragma once

#include <vector>
#include <cstddef>

#include "c_types/iid_t_rt.h"

#include "cpp_common/base_graph.hpp"
#include "cpp_common/alloc.hpp"

namespace pgrouting {
namespace to_postgres {

/** @brief Stored results on a vector are saved on a C array
*
* @param[in] graph Created graph with the base Graph
* @param[in] results results[i] -> the ith element of the vector contains the results
* @param[out] result_count The size of the vector
* @param[out] result_tuples The C array of <bigint, bigint, float>
*
* <bigint, bigint, float> = < i , 0, results[i] >
*
* Currently works for pgr_betweennessCentrality
*/
template <class G>
void vector_to_tuple(
const G &graph,
const std::vector<double> results,
size_t &result_count,
IID_t_rt **result_tuples) {
result_count = results.size();
*result_tuples = pgrouting::pgr_alloc(result_count, (*result_tuples));

size_t seq = 0;
for (typename G::V v_i = 0; v_i < graph.num_vertices(); ++v_i) {
(*result_tuples)[seq].from_vid = graph[v_i].id;
/*
* These 2 lines are specifically for pgr_betweennessCentrality
*/
(*result_tuples)[seq].to_vid = 0;
(*result_tuples)[seq].cost = graph.is_directed()? results[v_i] / 2.0 : results[v_i];
seq++;
}
}

} // namespace to_postgres
} // namespace pgrouting

#endif // INCLUDE_CPP_COMMON_TO_POSTGRES_HPP_
122 changes: 30 additions & 92 deletions include/metrics/betweennessCentrality.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,115 +30,53 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#pragma once

#include <vector>
#include <map>
#include <type_traits>

#include <boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/graph/betweenness_centrality.hpp>
#include <boost/graph/graph_traits.hpp>

#include "c_types/iid_t_rt.h"
#include "cpp_common/basePath_SSEC.hpp"
#include "cpp_common/base_graph.hpp"
#include "cpp_common/interruption.hpp"
#include "cpp_common/alloc.hpp"

namespace pgrouting {
template <class G> class Pgr_metrics;
namespace metrics {

template <class G>
void
pgr_betweennesscentrality(
G &graph,
size_t &result_tuple_count,
IID_t_rt **postgres_rows) {
Pgr_metrics<G> fn_centrality;
fn_centrality.betweennessCentrality(graph, result_tuple_count, postgres_rows);
}

template <class G>
class Pgr_metrics {
public:
using Graph = typename G::B_G;
using V = typename G::V;
using E = typename G::E;
typedef typename boost::graph_traits<Graph>::directed_category directed_category;

void betweennessCentrality(
const G &graph,
size_t &result_tuple_count,
IID_t_rt **postgres_rows) {
// required parameters
std::vector<double> centrality(boost::num_vertices(graph.graph), 0.0);
auto centrality_map = boost::make_iterator_property_map(centrality.begin(),
boost::get(boost::vertex_index, graph.graph));
std::vector<double> distance(boost::num_vertices(graph.graph), 0.0);
auto distance_map = boost::make_iterator_property_map(distance.begin(),
boost::get(boost::vertex_index, graph.graph));
// dummy parameters
std::vector<double> edge_centrality(boost::num_edges(graph.graph), 0.0);
auto edge_centrality_map = boost::make_iterator_property_map(edge_centrality.begin(),
boost::get(&pgrouting::Basic_edge::cost,
graph.graph));
std::vector<std::vector<E>> incoming(boost::num_vertices(graph.graph));
auto incoming_map = boost::make_iterator_property_map(incoming.begin(),
boost::get(boost::vertex_index, graph.graph),
std::vector<E>());
std::vector<double> dependency(boost::num_vertices(graph.graph), 0.0);
auto dependency_map = boost::make_iterator_property_map(dependency.begin(),
boost::get(boost::vertex_index, graph.graph));
std::vector<std::size_t> path_count(boost::num_vertices(graph.graph), 0);
auto path_count_map = boost::make_iterator_property_map(path_count.begin(),
boost::get(boost::vertex_index, graph.graph));
auto vertex_index = boost::get(boost::vertex_index, graph.graph);

/* abort in case of an interruption occurs (e.g. the query is being cancelled) */
CHECK_FOR_INTERRUPTS();

boost::brandes_betweenness_centrality(
std::vector<double> betweennessCentrality(
const G &graph
) {
std::vector<double> centrality(boost::num_vertices(graph.graph), 0.0);
auto centrality_map = boost::make_iterator_property_map(centrality.begin(),
boost::get(boost::vertex_index, graph.graph));

CHECK_FOR_INTERRUPTS();

try {
boost::brandes_betweenness_centrality(
graph.graph,
centrality_map);

if (boost::num_vertices(graph.graph) > 2) {
boost::relative_betweenness_centrality(
graph.graph,
centrality_map,
edge_centrality_map,
incoming_map,
distance_map,
dependency_map,
path_count_map,
vertex_index,
get(&pgrouting::Basic_edge::cost, graph.graph));

if (boost::num_vertices(graph.graph) > 2) {
boost::relative_betweenness_centrality(
graph.graph,
centrality_map);
centrality_map);
}
} catch (boost::exception const& ex) {
(void)ex;
throw;
} catch (std::exception &e) {
(void)e;
throw;
} catch (...) {
throw;
}

generate_results(graph, centrality, result_tuple_count, postgres_rows);
}
return centrality;
}

private:
void generate_results(
const G &graph,
const std::vector<double> centrality_results,
size_t &result_tuple_count,
IID_t_rt **postgres_rows) const {
result_tuple_count = centrality_results.size();
*postgres_rows = pgr_alloc(result_tuple_count, (*postgres_rows));

size_t seq = 0;
for (typename G::V v_i = 0; v_i < graph.num_vertices(); ++v_i) {
(*postgres_rows)[seq].from_vid = graph[v_i].id;
(*postgres_rows)[seq].to_vid = 0;
(*postgres_rows)[seq].cost = centrality_results[v_i];
if (std::is_same<directed_category, boost::bidirectional_tag>::value) {
(*postgres_rows)[seq].cost = centrality_results[v_i]/2.0;
}
seq++;
}
}
};

} // namespace metrics
} // namespace pgrouting

#endif // INCLUDE_METRICS_BETWEENNESSCENTRALITY_HPP_
35 changes: 19 additions & 16 deletions pgtap/metrics/betweennessCentrality/edge_cases.pg
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ RETURN QUERY
SELECT lives_ok('idless4_q');

RETURN QUERY
SELECT results_eq('idless4_q', 'idless4_r');
SELECT results_eq('idless4_q', 'idless4_r', 'test 4');


PREPARE idless3_q AS
Expand All @@ -95,7 +95,7 @@ RETURN QUERY
SELECT lives_ok('idless3_q');

RETURN QUERY
SELECT results_eq('idless3_q', 'idless3_r');
SELECT results_eq('idless3_q', 'idless3_r', 'test 6');

PREPARE idless2_q AS
SELECT * FROM pgr_betweennessCentrality(
Expand All @@ -120,7 +120,7 @@ SELECT results_eq('idless2_q', 'idless2_r');
PREPARE idless5ud_q AS
SELECT * FROM pgr_betweennessCentrality(
'SELECT id, source, target, cost, reverse_cost
FROM edges WHERE id < 5', directed => false ) ORDER BY vid;
FROM edges WHERE id < 5', directed => false ) ORDER BY vid;

PREPARE idless5ud_r AS
SELECT * FROM (VALUES
Expand All @@ -135,18 +135,20 @@ RETURN QUERY
SELECT lives_ok('idless5ud_q');

RETURN QUERY
SELECT results_eq('idless5ud_q', 'idless5ud_r');
SELECT results_eq('idless5ud_q', 'idless5ud_r', 'test 10');


PREPARE idless4ud_q AS
SELECT * FROM pgr_betweennessCentrality(
'SELECT id, source, target, cost, reverse_cost
FROM edges WHERE id < 4', directed => false ) ORDER BY vid;
FROM edges WHERE id < 4', directed => false) ORDER BY vid;

PREPARE idless4ud_r AS
SELECT * FROM (VALUES
(5::BIGINT , 0::FLOAT),
(6 , 0.6666666666666666),
(10 , 0.6666666666666666), (15 , 0))
(10 , 0.6666666666666666),
(15 , 0))
AS t(vid, centrality);

RETURN QUERY
Expand All @@ -159,7 +161,7 @@ SELECT results_eq('idless4ud_q', 'idless4ud_r');
PREPARE idless3ud_q AS
SELECT * FROM pgr_betweennessCentrality(
'SELECT id, source, target, cost, reverse_cost
FROM edges WHERE id < 3', directed => false ) ORDER BY vid;
FROM edges WHERE id < 3', directed => false) ORDER BY vid;

PREPARE idless3ud_r AS
SELECT * FROM (VALUES
Expand All @@ -172,7 +174,7 @@ RETURN QUERY
SELECT lives_ok('idless3ud_q');

RETURN QUERY
SELECT results_eq('idless3ud_q', 'idless3ud_r');
SELECT results_eq('idless3ud_q', 'idless3ud_r', 'test 14');

PREPARE idless2ud_q AS
SELECT * FROM pgr_betweennessCentrality(
Expand All @@ -190,15 +192,15 @@ RETURN QUERY
SELECT lives_ok('idless2ud_q');

RETURN QUERY
SELECT results_eq('idless2ud_q', 'idless2ud_r');
SELECT results_eq('idless2ud_q', 'idless2ud_r', 'test 16');

/* Explicit Directed Cases */


PREPARE idless5d_q AS
SELECT * FROM pgr_betweennessCentrality(
'SELECT id, source, target, cost, reverse_cost
FROM edges WHERE id < 5', directed => true ) ORDER BY vid;
FROM edges WHERE id < 5', directed => true ) ORDER BY vid;

PREPARE idless5d_r AS
SELECT * FROM (VALUES
Expand All @@ -213,13 +215,13 @@ RETURN QUERY
SELECT lives_ok('idless5d_q');

RETURN QUERY
SELECT results_eq('idless5d_q', 'idless5d_r');
SELECT results_eq('idless5d_q', 'idless5d_r', 'test 18');


PREPARE idless4d_q AS
SELECT * FROM pgr_betweennessCentrality(
'SELECT id, source, target, cost, reverse_cost
FROM edges WHERE id < 4', directed => true ) ORDER BY vid;
FROM edges WHERE id < 4', directed => true) ORDER BY vid;

PREPARE idless4d_r AS
SELECT * FROM (VALUES
Expand All @@ -233,13 +235,13 @@ RETURN QUERY
SELECT lives_ok('idless4d_q');

RETURN QUERY
SELECT results_eq('idless4d_q', 'idless4d_r');
SELECT results_eq('idless4d_q', 'idless4d_r', 'test 20');


PREPARE idless3d_q AS
SELECT * FROM pgr_betweennessCentrality(
'SELECT id, source, target, cost, reverse_cost
FROM edges WHERE id < 3', directed => true ) ORDER BY vid;
FROM edges WHERE id < 3', directed => true) ORDER BY vid;

PREPARE idless3d_r AS
SELECT * FROM (VALUES
Expand All @@ -252,7 +254,8 @@ RETURN QUERY
SELECT lives_ok('idless3d_q');

RETURN QUERY
SELECT results_eq('idless3d_q', 'idless3d_r');
SELECT results_eq('idless3d_q', 'idless3d_r', 'test 22');


PREPARE idless2d_q AS
SELECT * FROM pgr_betweennessCentrality(
Expand All @@ -270,7 +273,7 @@ RETURN QUERY
SELECT lives_ok('idless2d_q');

RETURN QUERY
SELECT results_eq('idless2d_q', 'idless2d_r');
SELECT results_eq('idless2d_q', 'idless2d_r', 'test 24');

END;
$BODY$
Expand Down
2 changes: 1 addition & 1 deletion src/metrics/betweennessCentrality.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ process(
result_count,
&log_msg,
&err_msg);
time_msg(" processing Centrality", start_t, clock());
time_msg(" processing pgr_betweenessCentrality", start_t, clock());

if (err_msg && (*result_tuples)) {
pfree(*result_tuples);
Expand Down
Loading
Loading