Bugs R Us
A Transit::Network Update

by Arne Sommer

Bugs R Us - A Transit::Network Update

[161] Published 19. December 2021.

Executive Summary: The vehicle part was broken in version 0.0.1, but is fixed in 0.0.2.

The last part of the documentation to be written before I released the Transit::Network module was the Railways article, and the very last text was the Toronto - Vancouver section.

I was kind of surprised that the program worked out on this extreme example: a train running once a week, and with a travel time of about 4 days. But it did, with some minor code changes here and there (mainly the «raw» version of the timingpoints).

It worked for daily departures as well. And departures every second day.

But it did not work for thrice-weekly departures, which relied on multiple intervals (i.e. 2, 2 and 3 days).

The first problem was the incorrect number of trains; 3 instead of 4. I made that one go away by adding a fourth interval value:

File: railways/ViaRail-12f.setup
## Networkplanner ##

route set 1 file:ViaRail-12.def interval:48h00;72h00;48h00;48h00 down:6h45 up:off
route set 2 file:ViaRail-12.def interval:48h00;72h00;48h00;48h00 down:off up:111h00

vehicles :days ViaRail-12b-vehicles.def

Note that the fix (yeah, well; workaround) is a strange one. Adding the fourth interval value should not matter at all (as the program starts over with the first one after finishing the first round of interval values), but it does.

This network setup file is not available in the zip file, as it is wrong. Copy the content manually, if you want to have a go at it.

The result was still wrong, but the number of trains was at least correct.

                  0001    0002    0003    0004
----------------------------------------------
Toronto   dep     0645  2+0645  5+0645  7+0645 
Vancouver arr   4+0500  6+1500 9+0500  11+0500 
Vancouver dep   4+1500  6+0500  9+1500  11+1500 
Toronto   arr   8+1429  10+1429  13+1429  15+1429 
Toronto   dep   9+0645  11+0645  14+0645  16+0645 

0000: Number of vehicles: 4
---------------------------------------
Total number of vehicles: 4

Some serious debugging uncovered that the multiple interval code was the problem. The vehicle counting code reads the intervals for the first route row for the given series, and uses that on all of them. What this means is that you can specify whatever you want as the interval for route 2 (in this case), and it does not matter at all.

This makes sort of sense, as the program will run into problems if the intervals differ when you combine routes. Using the same interval solves that issue, acting as a guard rail. (The code was written before support for multiple intervals was added.)

But it does not make sense if we use multiple intervals, that do sum up to the same value; as e.g. «3;7» and «10» or even «3;7» and «5». Multiple interval support was obviously not implemented correctly. My bad.

I then tried fixing that, at the end of a long day. That was not a success, so I reverted the changes, made a note of the problem in the Railways article, and published version 0.0.1 of the module.

Without testing it…

Oh, yes.

Big mistake.

For some reason I managed to screw up this line (line number 1002) in the module, that iterates through the intervals, starting over when it has reached the end of them.

This is the correct version:

$mins += @interval[$i++ % @interval.elems];

This is what it looks like in version 0.0.1:

$mins += @interval[$i++] % @interval.elems;

The point is that the variable $mins has the number of minutes to add to the previous departure time to get the next one, and it was almost zeroed out. So the program ended up practically showing the same departure times for every vehicle in the series.

It did not discover that change when I reversed the changes. So I released the module, with the error.

Lessons Learned

  • Do not make last minute changes
  • Testing is essential

Testing was missing from version 0.0.1, as the program design did not make it easy. I have started with unit testing, by moving all the current helper procedures into a helper module. More functionality will go that way.

The utlimate goal is to have tests for everything. One possibility is to use the examples in a test framework, and compare the result with what is described in these articles. Any code change breaking existing functionality will then be uncovered almost automatically.