From d85bfc05e7a13515c5c7627c010a6f609a76bf10 Mon Sep 17 00:00:00 2001 From: mpadge Date: Wed, 16 Oct 2019 12:09:51 +0200 Subject: [PATCH] add dodgr_centrality fn; closes #90 --- DESCRIPTION | 2 +- NAMESPACE | 1 + R/RcppExports.R | 4 +-- R/centrality.R | 68 +++++++++++++++++++++++++++++++++++++++++ _pkgdown.yml | 1 + codemeta.json | 4 +-- man/dodgr_centrality.Rd | 37 ++++++++++++++++++++++ src/RcppExports.cpp | 8 ++--- src/centrality.cpp | 14 ++++----- src/run_sp.h | 2 +- 10 files changed, 124 insertions(+), 17 deletions(-) create mode 100644 R/centrality.R create mode 100644 man/dodgr_centrality.Rd diff --git a/DESCRIPTION b/DESCRIPTION index a12274d75..474df7a16 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: dodgr Title: Distances on Directed Graphs -Version: 0.2.5.005 +Version: 0.2.5.006 Authors@R: c( person("Mark", "Padgham", email="mark.padgham@email.com", role=c("aut", "cre")), person("Andreas", "Petutschnig", role="aut"), diff --git a/NAMESPACE b/NAMESPACE index a4412fb71..5d0a1d2ce 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -7,6 +7,7 @@ export(clear_dodgr_cache) export(compare_heaps) export(dodgr_cache_off) export(dodgr_cache_on) +export(dodgr_centrality) export(dodgr_components) export(dodgr_contract_graph) export(dodgr_distances) diff --git a/R/RcppExports.R b/R/RcppExports.R index 286ad42ee..4769c4146 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -4,8 +4,8 @@ #' rcpp_centrality #' #' @noRd -rcpp_centrality <- function(graph, vert_map_in, heap_type, vertices) { - .Call(`_dodgr_rcpp_centrality`, graph, vert_map_in, heap_type, vertices) +rcpp_centrality <- function(graph, vert_map_in, heap_type, edges) { + .Call(`_dodgr_rcpp_centrality`, graph, vert_map_in, heap_type, edges) } #' Make unordered_set of all new edge names diff --git a/R/centrality.R b/R/centrality.R new file mode 100644 index 000000000..86bfd5476 --- /dev/null +++ b/R/centrality.R @@ -0,0 +1,68 @@ +#' dodgr_centrality +#' +#' Calculate betweenness centrality for a `dodgr` network, in either vertex- or +#' edge-based form. +#' +#' @param graph `data.frame` or equivalent object representing the network +#' graph (see Details) +#' @param contract If `TRUE`, centrality is calculated on contracted graph +#' before mapping back on to the original full graph. Note that for street +#' networks, in particular those obtained from the \pkg{osmdata} package, vertex +#' placement is effectively arbitrary except at junctions; centrality for such +#' graphs should only be calculated between the latter points, and thus +#' `contract` should always be `TRUE`. +#' @param edges If `TRUE`, centrality is calculated for graph edges, returning +#' the input `graph` with an additional `centrality` column; otherwise +#' centrality is calculated for vertices, returning the equivalent of +#' `dodgr_vertices(graph)`, with an additional vertex-based `centrality` column. +#' @param heap Type of heap to use in priority queue. Options include +#' Fibonacci Heap (default; `FHeap`), Binary Heap (`BHeap`), +#' `Radix`, Trinomial Heap (`TriHeap`), Extended Trinomial Heap +#' (`TriHeapExt`, and 2-3 Heap (`Heap23`). +#' @return Modified version of graph with additonal `centrality` column added. +#' +#' @export +dodgr_centrality <- function (graph, contract = TRUE, edges = TRUE, heap = "BHeap") +{ + if ("centrality" %in% names (graph)) + warning ("graph already has a 'centrality' column; ", + "this will be overwritten") + + hps <- get_heap (heap, graph) + heap <- hps$heap + graph <- hps$graph + + gr_cols <- dodgr_graph_cols (graph) + + if (contract & !methods::is (graph, "dodgr_contracted")) + { + graph_full <- graph + graph <- dodgr_contract_graph (graph) + hashc <- get_hash (graph, hash = FALSE) + fname_c <- file.path (tempdir (), + paste0 ("dodgr_edge_map_", hashc, ".Rds")) + if (!file.exists (fname_c)) + stop ("something went wrong extracting the edge_map ... ") # nocov + edge_map <- readRDS (fname_c) + } + + vert_map <- make_vert_map (graph, gr_cols) + + graph2 <- convert_graph (graph, gr_cols) + + centrality <- rcpp_centrality (graph2, vert_map, "BHeap", edges) + + if (edges) + { + graph$centrality <- centrality + if (contract) + graph <- uncontract_graph (graph, edge_map, graph_full) + res <- graph + } else + { + res <- dodgr_vertices (graph) + res$centrality <- centrality + } + + return (res) +} diff --git a/_pkgdown.yml b/_pkgdown.yml index 3d46c5183..2e4eaa436 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -39,6 +39,7 @@ reference: - title: Miscellaneous Functions contents: - compare_heaps + - dodgr_centrality - dodgr_flowmap - dodgr_full_cycles - dodgr_fundamental_cycles diff --git a/codemeta.json b/codemeta.json index 8cd90afd9..d2863db02 100644 --- a/codemeta.json +++ b/codemeta.json @@ -10,7 +10,7 @@ "codeRepository": "https://github.com/ATFutures/dodgr", "issueTracker": "https://github.com/ATFutures/dodgr/issues", "license": "https://spdx.org/licenses/GPL-3.0", - "version": "0.2.5.5", + "version": "0.2.5.6", "programmingLanguage": { "@type": "ComputerLanguage", "name": "R", @@ -392,5 +392,5 @@ } ], "relatedLink": "https://CRAN.R-project.org/package=dodgr", - "fileSize": "639.821KB" + "fileSize": "640.631KB" } diff --git a/man/dodgr_centrality.Rd b/man/dodgr_centrality.Rd new file mode 100644 index 000000000..b96af6d33 --- /dev/null +++ b/man/dodgr_centrality.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/centrality.R +\name{dodgr_centrality} +\alias{dodgr_centrality} +\title{dodgr_centrality} +\usage{ +dodgr_centrality(graph, contract = TRUE, edges = TRUE, + heap = "BHeap") +} +\arguments{ +\item{graph}{\code{data.frame} or equivalent object representing the network +graph (see Details)} + +\item{contract}{If \code{TRUE}, centrality is calculated on contracted graph +before mapping back on to the original full graph. Note that for street +networks, in particular those obtained from the \pkg{osmdata} package, vertex +placement is effectively arbitrary except at junctions; centrality for such +graphs should only be calculated between the latter points, and thus +\code{contract} should always be \code{TRUE}.} + +\item{edges}{If \code{TRUE}, centrality is calculated for graph edges, returning +the input \code{graph} with an additional \code{centrality} column; otherwise +centrality is calculated for vertices, returning the equivalent of +\code{dodgr_vertices(graph)}, with an additional vertex-based \code{centrality} column.} + +\item{heap}{Type of heap to use in priority queue. Options include +Fibonacci Heap (default; \code{FHeap}), Binary Heap (\code{BHeap}), +\code{Radix}, Trinomial Heap (\code{TriHeap}), Extended Trinomial Heap +(\code{TriHeapExt}, and 2-3 Heap (\code{Heap23}).} +} +\value{ +Modified version of graph with additonal \code{centrality} column added. +} +\description{ +Calculate betweenness centrality for a \code{dodgr} network, in either vertex- or +edge-based form. +} diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index c88c8863b..e203d43e7 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -6,16 +6,16 @@ using namespace Rcpp; // rcpp_centrality -Rcpp::NumericVector rcpp_centrality(const Rcpp::DataFrame graph, const Rcpp::DataFrame vert_map_in, const std::string& heap_type, bool vertices); -RcppExport SEXP _dodgr_rcpp_centrality(SEXP graphSEXP, SEXP vert_map_inSEXP, SEXP heap_typeSEXP, SEXP verticesSEXP) { +Rcpp::NumericVector rcpp_centrality(const Rcpp::DataFrame graph, const Rcpp::DataFrame vert_map_in, const std::string& heap_type, bool edges); +RcppExport SEXP _dodgr_rcpp_centrality(SEXP graphSEXP, SEXP vert_map_inSEXP, SEXP heap_typeSEXP, SEXP edgesSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< const Rcpp::DataFrame >::type graph(graphSEXP); Rcpp::traits::input_parameter< const Rcpp::DataFrame >::type vert_map_in(vert_map_inSEXP); Rcpp::traits::input_parameter< const std::string& >::type heap_type(heap_typeSEXP); - Rcpp::traits::input_parameter< bool >::type vertices(verticesSEXP); - rcpp_result_gen = Rcpp::wrap(rcpp_centrality(graph, vert_map_in, heap_type, vertices)); + Rcpp::traits::input_parameter< bool >::type edges(edgesSEXP); + rcpp_result_gen = Rcpp::wrap(rcpp_centrality(graph, vert_map_in, heap_type, edges)); return rcpp_result_gen; END_RCPP } diff --git a/src/centrality.cpp b/src/centrality.cpp index 43c10b71e..1a9be364d 100644 --- a/src/centrality.cpp +++ b/src/centrality.cpp @@ -218,7 +218,7 @@ void PF::PathFinder::Centrality_edge ( Rcpp::NumericVector rcpp_centrality (const Rcpp::DataFrame graph, const Rcpp::DataFrame vert_map_in, const std::string& heap_type, - bool vertices) + bool edges) { std::vector from = graph ["from"]; std::vector to = graph ["to"]; @@ -247,10 +247,10 @@ Rcpp::NumericVector rcpp_centrality (const Rcpp::DataFrame graph, one_iso); */ std::vector w (nverts), cent; - if (vertices) - cent.resize (nverts); - else + if (edges) cent.resize (nedges); + else + cent.resize (nverts); std::fill (cent.begin (), cent.end (), 0.0); for (unsigned int i = 0; i < nverts; i++) @@ -261,10 +261,10 @@ Rcpp::NumericVector rcpp_centrality (const Rcpp::DataFrame graph, pathfinder->init (g); // specify the graph - if (vertices) - pathfinder->Centrality_vertex (w, cent, i); - else + if (edges) pathfinder->Centrality_edge (w, cent, i, nedges); + else + pathfinder->Centrality_vertex (w, cent, i); } Rcpp::NumericVector dout = Rcpp::wrap (cent); diff --git a/src/run_sp.h b/src/run_sp.h index 2c0e5848c..455982773 100644 --- a/src/run_sp.h +++ b/src/run_sp.h @@ -64,5 +64,5 @@ Rcpp::List rcpp_get_paths (const Rcpp::DataFrame graph, Rcpp::NumericVector rcpp_centrality (const Rcpp::DataFrame graph, const Rcpp::DataFrame vert_map_in, const std::string& heap_type, - bool vertices); // FALSE for edge centrality + bool edges); // FALSE for vertex centrality