flownet 0.3.0 introduces one new function for critical link
analysis and substantive performance improvements to
consolidate_graph() and
simplify_network().
critical_link_analysis(): New function
that computes edge-level detour costs and vulnerability ratios for any
graph. For each edge (u, v) it finds the shortest
alternative path from u to v after removing
that edge, without repeated graph deletion. The underlying C
implementation runs a multi-label Dijkstra once per unique source node,
tracking the two best distances that begin via different first edges.
Parallel edges are handled as distinct alternatives; edges with no
detour receive Inf. Supports directed and undirected
graphs, and parallelises per-source Dijkstra runs across
nthreads OpenMP threads.consolidate_graph()
ImprovementsSingleton-edge removal now uses a linear-time peel
(drop_singletons_linear()), avoiding repeated full-graph
scans on large networks.
Degree-2 chain contraction is now performed at C level
(C_contract_linear_nodes) by default. The C routine walks
each chain once using dense array indexing with no hash table. Set
options(flownet.use_c_contraction = FALSE) to force the
R-only fallback.
consolidate_graph_core() remaps from /
to to dense internal node indices
(funique.default() + fmatch()) before
contraction and maps aggregated endpoints back to original node IDs, so
results and downstream joins are unchanged.
consolidate_graph_core() now handles topology-only
graphs (no coordinate or attribute columns): when no nodes are kept for
aggregation, it correctly returns a data frame of contracted
groups.
When verbose = TRUE, phase timings are reported for
singleton peel, orientation, contraction, and aggregation
steps.
More testthat coverage for edge cases: recursion,
keep.nodes, long chains, C vs. R contraction equivalence,
and singleton-peel equivalence.
simplify_network()
ImprovementsNew nthreads parameter (default 1):
parallelises the per-chunk shortest-path computations in
method = "shortest-paths" using mirai daemons,
matching the multithreading interface of
run_assignment().
New cluster.algo.dbscan parameter (default
FALSE): when TRUE, spatial clustering of
remaining nodes uses dbscan::dbscan() instead of
leaderCluster. DBSCAN is substantially faster for larger
datasets. Requires the dbscan package.
New nodes.algo.rann parameter (default
FALSE): when TRUE, node-to-kept-node
assignment uses RANN’s fast k-d tree nearest-neighbour
search on 3-D Cartesian coordinates (converted from lon/lat via
lonlat_to_xyz()). Requires the RANN
package.
The simplified graph returned by method = "cluster"
now carries a keep.edges attribute containing the integer
indices of the edges retained from the original graph.
simplify_network(method = "shortest-paths"):
the two result attributes have been renamed for consistency with the
cluster method and consolidate_graph():
"edges" → "keep.edges" (integer vector of
retained edge indices)"edge_counts" → "edge.counts" (traversal
counts for each retained edge) Update any code that reads
attr(result, "edges") or
attr(result, "edge_counts").consolidate_graph() attaches
keep.edges and group.id together (aligned,
same length) for recursive = "none" or
"partial"; with the default recursive = "full"
they are omitted (the mapping would span multiple passes), which is now
stated in the documentation. create_undirected_graph() now
also exposes group.id and group.sizes
(previously only group.starts, and undocumented), and
consolidate_graph() strips any stale grouping attributes
carried in from upstream operations.Fixed issue in consolidate_graph() which used to
modify columns (from and to in-place). Users
in older versions are advised to input a data.table::copy()
of the graph to retain it.
Fixes issue with multithreading for newer versions of mirai (or R). Thanks @kent37 (#69).
angle.max constraint in run_assignment()
is now two-sided (angle measured from origin and destination node
against the straight line between them), rather than just one-sided
(from origin). Also, the implementation is slightly more efficient.Release blog post at: https://sebkrantz.github.io/Rblog/2026/02/09/introducing-flownet-efficient-transport-modeling-in-r/
Fixed bug in run_assignment with
return.extra = "edges" where edge indices were incorrectly
returned. Due to zero indexing in C vs. 1-indexing in R they where
offset by one, thus, in flownet versions <= 0.1.2, the
correct edge indices can be retained by subtracting 1 from
them.
Improved Step 7 (elimination of path with duplicate edges) in the route enumeration algorithm to properly handle directed paths, i.e., candidate paths where an intermediate node is approached via an edge and departed from via the same edge but in a different direction, are now also removed.
Added option return.extra = "PSF" which adds
"path_size_factors" to the results object. This should be
useful to calibrate the PSL model.
Added option return.extra = "eweights" which adds
"egde_weights" to the results object. Edge weights are the
sum of the path probabilities across all paths using that edge. These
weights are computed efficiently at C-level, with minimal overhead, if
requested.
Added verbosity to simplify_network() (default
verbose = TRUE).
Reordered elements in results object (class ‘flownet’) in a
natural way: providing first the final flows, followed by path and
edge-level additional results if requested through
return.extra.
Added more unit tests covering return.extra
options.
Added variable labels to included africa_* datasets
- try collapse::namlab() on them.
Small improvements to recursive logic in
consolidate_graph().
Bumped kit dependency to 0.0.21 (for
fpmin() and fpmax()).
In consolidate_graph(): argument
consolidate was renamed to contract for
improved clarity, while ensuring backwards compatibility.
Minor improvements to documentation and vignette.
run_assignment() @details
section using \subsection{} for better organization:
return.extra parameter documentation as a clear
table showing which options are available for each methodpaths returns edge indices, not node
indicesnthreads parameterrun_assignment() (AoN and PSL methods)normalize_graph(), nodes_from_graph(),
distances_from_graph()linestrings_to_graph(),
linestrings_from_graph(),
create_undirected_graph()consolidate_graph(),
simplify_network()melt_od_matrix()simplify_network() shortest-paths methodrun_assignment(): Core function for
traffic assignment using the path-sized logit (PSL) model
mirai.linestrings_to_graph(): Convert
LINESTRING geometries (sf objects) to graph data frames
create_undirected_graph(): Convert
directed graphs to undirected graphs
collapse::collap() with
customizable functionsconsolidate_graph(): Simplify network
topology by removing intermediate nodes
simplify_network(): Simplify networks
using shortest-paths or spatial clustering methods
leaderCluster algorithm and contracts the graphnormalize_graph(): Normalize node IDs
to consecutive integers starting from 1
nodes_from_graph(): Extract unique
nodes with coordinates from graph
linestrings_from_graph(): Convert
graph data frames back to LINESTRING geometries
linestrings_to_graph()distances_from_graph(): Compute
distance matrices for all node pairs
melt_od_matrix(): Convert
origin-destination matrices to long format
africa_network: A road transport
network with 2,825 LINESTRING features representing existing roads
(2,344 edges) and proposed new links (481 edges). Each edge includes
attributes such as distance, travel duration, border crossing costs,
terrain ruggedness, and road upgrade costs.
africa_cities_ports: 453 African
cities with population > 100,000 and international ports. Includes
population data, capital status, and port cargo outflows.
africa_segments: 14,358 raw network
segments representing intersected road routes. Useful for demonstrating
network consolidation and simplification functions.
africa_trade: Bilateral trade flows
between 47 African countries aggregated by HS section (21 product
categories). Values represent annual averages over 2012-2022.
The africa_network, africa_cities_ports,
and africa_segments datasets are from Krantz, S. (2024). Optimal Investments in
Africa’s Road Network. Policy Research Working Paper 10893. World
Bank. Replication materials are available at github.com/SebKrantz/OptimalAfricanRoads.
collapse package for fast data
transformationsigraph for graph operations and shortest path
algorithmsgeodist for fast geodesic distance
computationsleaderCluster for efficient spatial
clustering?flownet-packageGPL-3