Components and merging

A run of the model computes components. A component is a direct trip from origin to destination (walking, cycling or by car), or public transport with one type of pre-transport and one type of post-transport. Each component has its own output folder. The merge combines the components of a variant into one Pareto front per origin-destination pair. Which components a run computes is set with the switches of the variant; see The variant on Model parameters.

Contents


The components

Classifications/Components lists every component (#117, #133):

  • the direct trips WW (walking), CC (cycling) and Car (AA in ModeUsed, with start and parking time);
  • the public transport components <pre-transport code>_PT_<post-transport code>: every combination of the five pre-transport types (W, C, C_RM, C_RMT, C_Ric) and the five post-transport types (W, C, RM_C, RMT_C, OVf_C), 25 in all, such as W_PT_W, C_PT_OVf_C or C_RM_PT_W. The types are described on Walking and cycling legs.

A direct trip is a component of its own and never part of a public transport component. It needs no chains, the car keeps several routes per pair (Advanced/ParetoLegs_Car), and walking and cycling do not depend on the departure moment.

One component per run step

One GeoDmsRun computes one component, Impl/ComponentName. It follows from ConfigSettings/Overridable/RunComponent, which batch\UpdateAll.cmd sets per step in the environment variable GEODMS_Overridable_RunComponent; in GeoDmsGui, ModelParameters/GuiComponent takes its place. Everything else follows from the name: the pre- and post-transport type, the direct trips, the output folder and its signature.

What a component needs:

  • A public transport component reads the pre- and post-transport caches and the chain cache (Classifications/Components/WithPT). The output step joins them as described on From chains to journeys.
  • Car reads the car caches (DirectCar).
  • WW and CC compute their trips in the output step itself.

UpdateAll.cmd therefore skips the chain cache for the direct components, and the car caches for every component but Car. The public transport components share the chain cache when their pre-transport types have the same maximum time, because its signature carries the longest pre-transport leg (_v<PT_Max_V_Time>) and not the types.

Output folder and departure moments

The output folder of a component is <Analysis_date>_<OutputLabel>_<component> (Classifications/Components/OutputSuffix), with _fb after the component when it cycles on the network of the Fietsersbond (Impl/CyclingNetwork_DirTag). Its subfolder PerBlock holds tt_<moment>_<n>of<N>.parquet (or .csv); the date and the component are in the folder name, which keeps the paths short.

WW and CC, and Car without Impl/CarTimeDependent, do not depend on the departure moment. They compute one moment per block, the congestion moment of the part of the day (Classifications/Components/SingleDepartureMoment, 07:30 in the morning rush).

The signature of the output folder mentions the chain cache and the public transport settings only for a public transport component, and the car settings only for Car.

The direct trips in the output

The direct components go through the same output step as the public transport components (PerDepartureMoment_T), without pre-transport, chains and post-transport (Impl/WithPT FALSE): their options (AllOptions) are the direct trips of the component.

  1. The trips come from PublicTransport_Prep/Direct: Walking and Cycling (see step 5 of Walking and cycling legs) and the car per congestion moment (see Private transport).
  2. PublicTransport_Prep/Direct_OD holds the direct trips of the component that do not depend on the departure moment, with duration, distance, price, augmented price and mode. NetworkSetup/impl/Direct_OD adds, once for all blocks, the places of origin and destination, the ownership the trip needs (NeedsCar, NeedsBike) and the origin block and part of each row; each part selects its rows.
  3. With Impl/CarTimeDependent (default with the TomTom network) the car trip depends on the departure moment and is not in Direct_OD. Each departure moment reads the rows of its origins from the car cache of that moment (CarRows) and makes the front on travel time and distance there (DirectCar, template CarFront_T).
  4. A direct trip leaves at the departure moment and arrives after its duration. Its time, distance and price are in the pre-transport columns (PretransTime, TravelDist_V, PretransPrice); public transport and post-transport are zero. ModeUsed is WW, CC or AA.
  5. The two condensations of step 7 of From chains to journeys keep the front per pair. Walking and cycling have one route per pair. The car keeps the routes of its front on travel time and distance, whose price follows from the distance.

The price of a direct trip:

Trip Price Price_augm
walking Direct_Walking_Time_Costs per minute with Advanced/IncludeWalkingCostsInPrice, else 0 Direct_Walking_Time_Costs per minute
cycling Direct_Cycling_Time_Costs per minute with Advanced/IncludeCyclingCostsInPrice, else 0 Direct_Cycling_Time_Costs per minute
car the distance times Car_CostPerKm plus Car_FixedCosts_PerTrip, with Advanced/IncludeCarCostsInPrice equal to Price

Car and bicycle ownership as criteria

MinimiseCriteria, and in the merge MergeCriteria, can also name Car and Bike (#117). Each adds a criterion that is true or false:

  • NeedsCar: the direct car trip (AA). There is no park-and-ride pre-transport, so no public transport journey needs a car.
  • NeedsBike: the direct cycling trip (CC), and a journey with a pre- or post-transport leg on one’s own bicycle. The OV-fiets is rented, so OVf_C does not need one’s own bicycle (Classifications/TimeInvariantTypes/NeedsOwnBike).

The criteria are minimised, false before true. An option that needs neither a car nor a bicycle is therefore never dominated by one that does: a public transport journey that is dearer and slower than the car trip stays next to it, whereas a car trip that is dearer and slower than a public transport journey still drops out. One front then serves every group of travellers:

  • with a car and a bicycle: all rows;
  • without a car: the rows with NeedsCar 0;
  • without a car and a bicycle: the rows with NeedsCar and NeedsBike both 0.

Without these criteria such journeys drop out, and an analysis of travellers without a car finds no option on those pairs, or a slower one than exists. Output/PostAnalysis/FindMedian, for example, leaves out the car trips (ExcludedModes = 'AA') to describe accessibility without a car.

Rules:

  • Within one component each criterion is the same for every option, so in the run of a component it does not change the front. The criteria matter in the merge; the default of MinimiseCriteria ('Price,Time') does not name them and that of MergeCriteria ('Price,Time,Car,Bike') does.
  • A criterion that cannot differ between the options is left out (Classifications/OwnershipParetoAttr_Candidates/IsRelevant), also from the signature: NeedsCar counts only with the direct car trip, NeedsBike only with the direct cycling trip or a pre- or post-transport type on one’s own bicycle, and in the merge only when a merged component needs one’s own bicycle (Classifications/Components/NeedsBike).
  • The chain cache does not depend on them: the chain joiner computes public transport only.
  • The signature of the output carries the extra criteria in its MinCrit part, as the letters of ModeUsed: MinCrit-Price_Time_A_C.
  • Both columns, NeedsCar and NeedsBike (0 or 1), are in the csv output of a component and in the merged output, whatever the criteria; in the parquet output of a component they are constant and left out.
  • The criteria need the true-or-false criteria of pareto_optimal_eps (GeoDMS #1287), which every engine that the model accepts has.

How many options of each component the criteria keep in a merge is shown under MergeCriteria.

Merging the components

Merging is optional and computes no trips itself. With ModelParameters/Merge on, batch\UpdateAll.cmd ends with the merge, as the component Merged, when the variant has two components or more. It merges, per origin block and departure moment, the output of the components of the variant into one Pareto front per origin-destination pair (NetworkSetup/ComponentMerge).

The steps

  1. The merge reads the parquet files of the components (<Analysis_date>_<OutputLabel>_<component>/PerBlock), with a reader per kind of component (Classifications/Components/ExportClass: Direct, Car or PT). The components must therefore be written with OutputFormat 'parquet', with the times in whole seconds: the merge stops when the signature of a component does not name _parquet-s- (ComponentMerge_Def/PerComp/<component>/Stored), because GDAL would read an older output with the times in minutes as seconds without a warning. A component with one departure moment (WW, CC, and Car without CarTimeDependent) serves every departure moment of the merge.
  2. It fills in the columns that are constant in a component or follow from its columns: the price of WW and CC from the travel time and that of Car from the distance, as in PublicTransport_Prep/Direct; ModeUsed WW, CC or AA; NeedsCar and NeedsBike from the component; zeros for the missing times and distances. Every row gets the column Component, the component it comes from.
  3. It keeps per origin-destination pair the rows that are not dominated, with pareto_optimal_eps on Classifications/OutputParetoAttr, the same operator and epsilons as in a run, with price and time in cents and seconds. The rows are in the order of the components in Classifications/Components, direct trips first; of rows that are equal on every criterion the first stays.
  4. It writes the result in OutputFormat, parquet or csv, to <Analysis_date>_<OutputLabel>_Merged<MergeRunNr>, one block per phase, with the counts per block in Tellingen, which batch\OdTellingen.py adds up.

Criteria

The merge has its own criteria, MergeCriteria (default 'Price,Time,Car,Bike'), apart from MinimiseCriteria of the components: any subset of Price (or Price_Augm), Time, Car and Bike, with at least Price or Time (an integrity check). With 'Time' or 'Price' alone each pair and departure moment keeps exactly one row, the fastest or the cheapest. Car and Bike count only as far as a merged component can need them.

With IncludeWalkingCostsInPrice FALSE, the default, walking is free. The direct walking trip then stays in the merged front of every pair within walking range, and an option that is not more than 1% faster drops out against it.

Signature

The folder name holds MergeRunNr instead of the merged components, which keeps it short. The signature of the folder lists the components, the criteria, the format (<OutputFormat>-m2) and the signatures of the components themselves, so that it changes when a component is computed again with other settings.

Merging against one run

Because the 1% rule of the front is not transitive, merging can keep or drop a few options that lie within about 2% of a cheaper one, compared with one run over the same options. Example: CC, C_PT_W and C_PT_OVf_C merged, against one run over the same options (Dronten, 5 blocks, morning rush of 2023), differed in 275 of 359,127 lines; every pair kept an option, and every differing line was within 2.5% of the travel time of an equal or cheaper option in both.