Skip to content

Conversation

@mattwigway
Copy link
Contributor

This makes the linking distance and minimum subgraph size configurable through the TransportNetworkConfig, and adds a test that it works. There's been a long-standing comment that these should be configurable but it has not previously been done. It also creates two separate linking distances—one for stops and one for pointsets/StreetRouter origins and destinations.

I have a project now where I'm combining R5 with MissingLinks.jl to identify places in the street network where modifications could be made to improve transit accessibility. One of the issues I ran into was that island removal and the very long default maximum linking distance meant that many improvements in the network did not actually have any effect in R5, because they would create links to islands of sidewalk around a bus stop; R5 would remove those islands and link the bus stop to a neighborhood several hundred meters away instead. So I needed to configure these to be lower in that particular application.

This PR doesn't change the defaults so I would not expect any changes to results. I will admit I don't fully know how TransportNetworkConfig is used internally in Conveyal infrastructure, but based on the comments I think that by using boxed ints and doubles and defaulting them to NULL in the config means this will be a backwards-compatible change.

@mattwigway
Copy link
Contributor Author

Commit 438ebfd gets the CI to work again, so could be cherry-picked into a separate PR. Github has switched to Gradle 9, and a few things in build.gradle weren't compatible with Gradle 9, notably the shadow plugin needed to be updated, and targetCompatibility.getMajorVersion() is no longer supported, and an explicit test runtime dependency on the junit launcher is required. There are also a number of Gradle 9 deprecations that I have not addressed but will need to be addressed prior to Gradle 10.

I have confirmed that the MANIFEST.MF is the same after this change as the latest Github release:

This change

Manifest-Version: 1.0
Automatic-Module-Name: com.conveyal.r5
Main-Class: com.conveyal.analysis.BackendMain
Build-Jdk-Spec: 21
Implementation-Title: Conveyal Analysis Backend
Implementation-Vendor: Conveyal LLC
Implementation-Version: v7.4-rc.4-6-ga5293b2.dirty
Multi-Release: true

Latest Github release: r5-v7.4-rc.4-3-g76124de.jar:

Manifest-Version: 1.0
Automatic-Module-Name: com.conveyal.r5
Main-Class: com.conveyal.analysis.BackendMain
Build-Jdk-Spec: 21
Implementation-Title: Conveyal Analysis Backend
Implementation-Vendor: Conveyal LLC
Implementation-Version: v7.4-rc.4-3-g76124de

@mattwigway
Copy link
Contributor Author

It may also make sense to use ./gradlew instead of gradle in the CI script so the supported version of gradle is downloaded.

@abyrd
Copy link
Member

abyrd commented Sep 3, 2025

many improvements in the network did not actually have any effect in R5, because they would create links to islands of sidewalk around a bus stop; R5 would remove those islands and link the bus stop to a neighborhood several hundred meters away instead. So I needed to configure these to be lower in that particular application.

Just trying to understand the context: Do you mean that disconnected subgraphs of sidewalk legitimately exist in the input OSM data, so there are bus stops surrounded by sidewalks that do not connect to the rest of the street network? Does "improvements in the network" mean scenarios containing changes to the street network only, and does "create links to islands" mean that such scenarios add new road links that connect disconnected subgraphs to the rest of the graph? So then the problem is that R5 is removing these disconnected subgraphs before the scenario ever gets a chance to connect them?

@abyrd
Copy link
Member

abyrd commented Sep 3, 2025

It may also make sense to use ./gradlew instead of gradle in the CI script so the supported version of gradle is downloaded.

We don't have the gradle wrapper set up. I know it's the recommended way of using gradle but I have always been a bit wary of it. My sense is that like curl-bash it may normalize practices that increase the risk of supply chain attacks. In this case running a script that employs an opaque JAR to download executable code from the internet, then directly run that code to build an application that will be distributed. It may belong to a family of convenience mechanisms that I find a little too complacent.

I think the only reason we switched to Gradle was that it allowed dynamically setting the artifact version from git describe. I believe Maven can do this now, and though Maven XML config is kind of ugly, Maven is much more stable than it was 10+ years ago, and these days I prefer Maven XML to Gradle's ever-shifting open-ended scripting approach. It would be interesting to try a Maven build some time.

public static final int MIN_SUBGRAPH_SIZE = 40;
private int minSubgraphSize = 40;

public int getMinSubgraphSize() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R5 generally eschews the ceremony of Java accessor methods and uses public fields for everything, treating instances as immutable after construction but not relying on the compiler to enforce this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I can make that change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in ceb8cb0

@mattwigway
Copy link
Contributor Author

mattwigway commented Sep 11, 2025

many improvements in the network did not actually have any effect in R5, because they would create links to islands of sidewalk around a bus stop; R5 would remove those islands and link the bus stop to a neighborhood several hundred meters away instead. So I needed to configure these to be lower in that particular application.

Just trying to understand the context: Do you mean that disconnected subgraphs of sidewalk legitimately exist in the input OSM data, so there are bus stops surrounded by sidewalks that do not connect to the rest of the street network? Does "improvements in the network" mean scenarios containing changes to the street network only, and does "create links to islands" mean that such scenarios add new road links that connect disconnected subgraphs to the rest of the graph? So then the problem is that R5 is removing these disconnected subgraphs before the scenario ever gets a chance to connect them?

Yes, that's exactly it - there are lots of places in NC where there is a little bit of sidewalk around a bus stop, and then a sidewalk gap, so the bus stop legitimately is connected to an island (of course the people who use these stops find a way to get to them—walking on major arterials and/or cutting through the bushes—but that's not a very good user experience, which is what I'm modeling here). The working paper about this is here if you're interested.

@mattwigway mattwigway force-pushed the configurable-linking-distance branch from 5200455 to ceb8cb0 Compare September 11, 2025 20:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants