google / transit

https://gtfs.org/
Apache License 2.0
557 stars 173 forks source link

GTFS-Fares v2 Zone-based fares #344

Open omar-kabbani opened 1 year ago

omar-kabbani commented 1 year ago

Hi everyone - we (MobilityData) are looking to add zone-based fares to GTFS as part of GTFS-Fares v2.

This requires the following changes:

Below is an example of how we envision the files and fields being used to describe zone-based fares.

Step 1: Define Zones

Consider a system with four zones; A, B, C, and D:

Use areas.txt to create the fare zones:

areas.txt area_id area_name
A Area A
B Area B
C Area C
D Area D

Step 2: Group zones

Grouping zones is necessary to describe zone-based fares that cross more than three zones. The origin zone is listed under from_area_id, the destination zone is listed under to_area_id, and the zones in between are grouped and listed under contains_area_id. In the original proposal, the file stop_areas.txt is used to to assign stops to areas and to group areas together using greater_area_id. However, this would probably get messy with three different layers being present in one file (stops, areas, and greater areas).

One option would be to have a new file to assign areas to greater areas: area_id greater_area_id
B areaBC
C areaBC

Another alternative would be to use the file areas.txt to assign areas to greater areas - the only downside to that is that an area cannot be assigned to more than one greater area.

Step 3: Define fare legs

Use fare_leg_rules.txt to define the cost of travel between the different zones:

from_area_id to_area_id contains_area_id fare_product_id
A B 3_dollar
B C 2_dollar
C D 1_dollar
A C B 4.5_dollar
A D BC 5.5_dollar

Any thoughts on how this example models zone-based fares? Is this in line with the expectations of data consumers and data producers? We would also like to hear your suggestions around greater_area_id.

Please share your thoughts here so we can come up with a way to move forward with zone-based fares.

npaun commented 1 year ago

When Transit evaluated the original Fares v2 draft spec, we felt that greater_area_id created significant complexity and confusion and shouldn't be added to the spec. We also found that contains_area_id couldn't express many real-world zone based fare systems like Translink (Vancouver) and TfL (London). We created a proposal to replace the single-valued contains_area_id, with a contains_area_set that selects a fare_leg_rule based on a particular set of areas passed through, and would welcome your feedback:

https://docs.google.com/document/d/1-yxBhqsnbDbAXY74DMaAQS0Jc5E1Fv4VaPu_8I-6Hqo/edit?usp=sharing

davidlewis-ito commented 1 year ago

We agree that "contains" as presented above does not meet the real world use cases.

Transit's more sophisticated approach is interesting,

If this is felt too complex, an alternative that we think would suffice for most cases is to add a modifier attribute that defines how to interpret the contains zone. contains_type: 1) The leg must have at least one stop in the contains zone 2) All stops of the leg must be in the contains zone 3) No stops of the leg must be in the contains zone

omar-kabbani commented 1 year ago

The proposal presented by @npaun seems to address the issue of going through multiple areas. When I wrote the initial message I was under the impression that fare_leg_rules.contains_area_id takes area_id and greater_area_id. However, I just checked and it only takes area_id. The proposal to add another file to group areas into sets also seems like a more elegant solution.

halbertram commented 1 year ago

We agree that @npaun's proposal looks good. Would I be right in thinking that the 'exhaustive list' is 'contains all of these areas, and no others' - ie an exact set match?

We feel that without the equivalent of a corresponding _type specification for how the sets are matched (as mentioned by @davidlewis-ito, and widened to sets), there are problems creating complementary rules: If there is a rule matching travelling through ABC, if would be useful to be able to create a rule that matches not travelling through ABC. Without that, you need to rely on the 'if no matching' mechanism which is clearly open to problems when combining with other rules that match sets on different criteria.

I don't believe the proposal as stands can implement complement rules - even if you create a set of all the areas other than A, B, or C, the and/or problem will stop it working as expected.

In addition to the intended use of zonal systems, we find the contains concept works well for detecting fare differences that depend on a simple via station - if that is placed in an area, being able to have a pair of rules for via that station and not (without having to worry about all the other areas traversed) is useful. It would be great to keep that use case in mind.

halbertram commented 1 year ago

Re greater_area_id, would the intention be to then allow area sets in from_area_id? If not, we would strongly prefer to retain greater_area_id. We find several situations where we have a station that generally obeys the rules of its area, but has some specific rules. For those cases, we place it into its own area (so we can address it individually), and connect that to the area it would otherwise be part of (so that it also picks up rules related to the area).

Without the ability to do that, we would need to expand the rules table considerably with various combinations, and hugely so once there are several such stations are in an area.

One final thought - would fare_leg_rules.contains_area_set_id be more consistent than fare_leg_rules.contains_area_set?

github-actions[bot] commented 2 months ago

This issue has been automatically marked as stale because it has not had recent activity. It may be closed manually after one month of inactivity. Thank you for your contributions.

tzujenchanmbd commented 1 month ago

The Fares v2 working group is currently discussing more complex zonal fare structure. Since this is a large topic, having a place for asynchronous discussion would be helpful. I would like to highlight this issue again to make it our place for asynchronous discussion. (Tagging our active working group members: @jfabi @westontrillium @halbertram @skinkie @npaun @jsteelz @bdferris-v2)

Resources:

Summary of the last meeting:

The meeting concluded with plans to delve deeper into the cases outlined in the research document and consider solutions to the open questions, continuing discussions in the next meeting.