Modelling what might have been in southeast BC and northwest Wasington

Role selection without sufficient suitable cars

My process to restage cars in staging by finding a role for each car relies on being able to find at least one suitable role for each car that is restaged. If no role can be found the car must be removed temporarily to storage. This approach works well when there are enough suitable roles to select from for a given car, but it breaks down when there are not. Too many cars may end up in storage when the entire point of the exercise is to run trains! A solution to keep cars moving is to substitute roles that are not a perfect match and carry on. Colin mentioned that he and Gary often have to do just that when using their traditional paper car card and waybill system. I’d like to capture some of the ideas behind how this “forced” matching is worked out and implement it in the program.

There are obvious things we can do in some cases. For example, if the particular car to be restaged has 6 foot doors but there are no roles asking for a 6 foot door, only 8 foot, then we may decide to send the car anyway, even though its door is narrower than what is requested and a real shipper would be angry because their forklift truck would not fit. The basic notion here is that there may be some parts of the car spec that can get ignored to help find a match, without causing too much grief. In this case we ignored the door attribute because it really doesn’t matter, nothing will actually be loaded. Maybe there is an order of things that we can ignore in the hope of finding a match so that the car does not have to get pulled off into storage. For example, if we don’t find a match to start, first ignore the door spec, if still no match, then ignore the car class, and so on until we run out of things we are willing to compromise on and the car has to be moved to storage. I suspect that people go through something like this in their minds when selecting paper waybills. I’d like to try to capture that in some simple rules that I can implement in the program.

Role “Legs”

In addition to the Car Specification, a role also defines where the car goes on the layout to fulfil the role. Each of these segments of the car’s journey are currently called a “Leg”. This probably needs a better name, but it will do for now.

A leg includes the type of car bill, the destination track, the load, and the wait time after arrival for loading or unloading, or whatever.

Typical types of car bills are “Empty Supply”, “Freight Waybill”, “Empty Return”, and so on. I call them all “waybills” even though that is not technically correct, but so be it.

Loads will normally be specified only for the freight leg of the journey, but it can be anything that makes sense to the user. A car could be used to deliver one load and back-haul a different load.

The notion of legs can easily be expanded beyond the typical waybills to include extra car moves such as for icing, cleaning, custom’s inspection, and so forth. There can be any number of legs in a role. Each leg also includes the wait time that a car must remain at its destination before being eligible to move again. Usually this is about a day, but could be as short as a couple of hours for icing, etc. Again, it depeneds on the desired effect.

To help visualize all of this, here are a couple of example roles, expressed in English:

Role One:
– Suitable for a Boxcar, 40 feet, Rough, with 8 foot doors, at CPR Staging.

– Empty Supply to Shipper A;
– Freight Shipment of Lumber to Receiver B;
– Empty Return to CPR Staging.

Role Two:
– Suitable for a Boxcar, any length, Clean, any width doors, at GN Staging.

– Freight Shipment of Appliances to Receiver C;
– Empty Return to GN Staging.

Roles also include a weighting, or a kind of priority, that is used to influence the random selection from all suitable roles. Roles with a higher weighting will have more chance to be selected, while roles that should only be picked on occasion should have much lower weights.

There are all sorts of ways that this concept could be improved going forward. I can see having some of the legs optional with some sort of probability, so as to reduce repetition and boredom. And, it might be possible to have roles that are continuous for cars in captive service that just go back and forth between two locations. Lots to think about.

Roles and car specifications

Ok, so now we have a bunch of attributes that describe a car, but how do we use this when restaging cars? The things that will make use of all of this car attribute stuff are called “Roles”. A Role includes basic shipment information, but it also contains the entire life-cycle of a car from staging, on to the layout, and eventually back to staging. Some of the phases of that life-cycle have the car being moved empty for supply or return, so there really is no shipment for those parts, hence the new name “Role”. Roles now replace the earlier primitive shipment model that made too many assumptions and caused a lot of grief.

Every car in staging that is about to return on to the layout requires a role that governs all of the places that car will go. For every car being restaged, the program searches through all of the available roles to find those that are suitable for that car by considering all of its attributes. Roles contain a Car Specification that gets tested for a match to the car. A very simple example role might say that it wants a “Boxcar:40” and is silent on the other attributes, so they are considered as “don’t cares”, and only the Car Type and Nominal Length of the Car will be considered. In this case, every 40 foot box car waiting to be restaged would be a match.

This is all part of the process that we go through manually with paper Car Cards and Waybill systems during restaging, I just want to capture the essence of the process and automate it.

Roles usually specify a car type and a couple of the other attributes, but the process of matching cars to roles can get quite complex when we start to think about more subtle issues. What if a shipper can accept cars of different lengths, but not just any length, say 40 or 50 foot, but no longer. And how do we handle roles that apply only to specific individual cars and no others, even if they share the same attributes? A good example of this would be captive service between two industries. And of course there is the owner railroad, and reporting marks to consider. The combinations can grow to be quite complex in order to handle all of these special cases, but we still want the system to be easy to define for the much more common simple cases without becoming so complex that it is hard to understand.

This sounds like it is getting very complicated to set up the data, but please remember that all of these fields can be left blank or filled with just an asterisk (*) and they will not be considered during selection. Only a few of the fields will be routinely used, such as Car Type and Nominal Length. 

My solution is to use a series of “Specifications” that each contain a description of which car attributes are “acceptable” to the Role for that piece. The combination of all of these specs is referred to as the Car Specification. So, what is a specification? In simple terms it holds zero or more car attributes that can be matched to a specific car to see if they match or not. The whole notion of a “match” is non-trivial, as we must handle multiple acceptable values, an empty list that signifies that we don’t care about that particular car attribute, and cars that have empty attributes.

Some examples should help makes this clearer. Let’s consider a car’s nominal length. If an industry can accept only 40 foot cars due to loading dock spacing, that would be specified simply as “40”. If it can handle 40 or 50, but no other lengths, it would be specified as “40|50”, where the “|” (vertical bar) signifies “either”. A specification list can hold as many alternatives as needed. In this case, when the role is being considered for a particular car being restaged, it will be included as a possible candidate for any car with a length of 40 or 50 feet. Other actions will affect which role finally gets selected, but it first must be a candidate role that matches the car. The overall selection process does this matching for all non-empty specifications.

On the other hand, if we don’t care about the length of the car, for say a team track, then the specification becomes a simple asterisk, “*”, meaning “don’t care”, and the role will match any car length.

A more complete example would be for a Boxcar, 40 or 50 foot, Clean or High class, with 6 or 8 foot Doors, but we don’t care about a Subtype, or a Capacity. The car specification for this would be:


The complete specification will also include more don’t cares for the initials, number, and owner railroad, but these have not been added in yet.

Ordering car attributes

Given that we now have six attributes to describe a car, we need to decide on a typical order for them when they get displayed. Some are more often used, like the main Car Type, and some are less frequently used, such as Door style. I am thinking that we want them to be arranged from left to right in decreasing order of usage. So here is what I came up with:

Type : NomLength : SubType : Class : Door : Capacity

Those that are blank will simply not be included. Examples again from Colin’s railroad:

  • Boxcar:40:H:D8
  • Autorack:85:2 Deck
  • Tank:40:Vinegar
  • Tank:40:Oil:8000

And one with everything, just not sure what it all means together:

  • Boxcar:40:Insulated:H:D8:6000

More thinking about optional car attributes

I started to think more about the car attributes and which ones are really necessary. I had said that we need the Car Type and Nominal Length, but not always the other four attributes. Now I am thinking that they are all optional. Stay with me for a moment, and it may make sense. Ok, we do need the Car ID, namely the Road and Number, otherwise we can’t find the car to move, and we need the actual length to make sure there is space for it. But as for the other things, they are only used to select suitable shipments for the cars when they get restaged. It would work even if we had all six attributes blank, meaning “don’t care”, or “unknown” for everything. That means that such a car could be given any role, as there is nothing to match on. While this sounds silly, it is a good way to get a new system started by generating lots of car movements without any real regard to what is going where and in what type of car. Not very prototypical for sure, but it can help prove out a train scheduling scheme and get lots of cars moving about. There is nothing really that dictates that only one specific type or class of car can be delivered to a certain industry. It is all 4’- 8 1/2” between the rails and any car can physically go anywhere. After some experience is gained with how the cars move with the trains according to their timetables, more specific roles and car types can be introduced to narrow things down and get more prototypical movements.

A Car Classification Conundrum

So far my Car Forwarding program has only considered a car’s basic type and length when doing restaging. This is not specific enough to be realistic, but it was sufficient to get the rest of the code working correctly. Now it is time to expand the attributes for a car so that we can have more realistic assignments for cars leaving staging.

After a lot of analysis and discussion, it looks like there needs to be six main attributes to describe a car. It is always possible to add more later on if the need arises, but this should work well for now.

The additional attributes are car Subtype, Class, Door, and Capacity. All of these are user definable as to what they actually mean, but the terms are there to help guide the process and be familiar. None of these are actually numeric, but symbolic, at least for now. For example, a capacity of 6000 cannot be compared to 7000 numerically, but is just a label that can be displayed and printed, and should make some sense to the user. Later on, if there is a need to specify some kind of numeric comparison, such as “any car length less than 50” it can be added.

Not all attributes will apply to a given car, for example, tank cars usually don’t have doors. In this case, the field is simply left blank and it will be ignored.

The purpose of all this is to allow the car restaging process to be able to match suitable roles to the cars in staging. We don’t want to assign a tank car shipment to a boxcar, or vice versa. There is a lot of flexibility in this process, as a role can be told to ignore, or “don’t care” about any or all car attributes so that there is very fine grained control over the assignment process.

The following are some examples of the six car attributes, taken from Colin’s railroad.

Covered Hopper


2 Deck
3 Deck
Drop Bottom




In the car description data any or all of these attributes can be left blank which implies that the attribute is not important and will be ignored when matching the car to roles. Obviously tank cars do not have doors, etc. Even the main car type can be ignored, if for instance we had some generic shipments to a team track that can accept any type of car.

More attributes can be added if necessary, but this should handle most situations based on local discussions.

Other attributes that help identify the car are its owner railroad and reporting mark initials and number. These may get added to the role data model so that roles can be made very specific down to an individual car or set of cars.

Some format is needed to be able to display the complete car attribute information, so the following is proposed. The complete string will consist of a concatenation of the non blank attributes, separated with colons, “:”. Something similar applies to the roles, but more details of that will come later. The order of the attributes was selected to move from most common on the left, to least on the right. All cars should have a type and length, so those are the first two , followed by subtype, class, door, and capacity. So some examples:

  • A 40’ boxcar with 8’ doors, for clean loading would be specified by: “Boxcar:40:Clean:D8”. 
  • A Shipment that needs a clean 40’ boxcar, but with any door width would request it as “Boxcar:40:Clean:*”, where the door width is specified with an asterisk, indicating “any” width will do. The same can be done for the length, etc. 
  • Another Shipment that only cares that it has any kind of a boxcar would use “Boxcar:*:*:*”, with asterisks for everything except the basic car type. 

One issue that is not completely resolved at this time is how to handle missing attributes. If we want to be able to parse a car attribute string, it gets difficult if it has an unpredictable number of parts, for example “Boxcar” versus “Boxcar:40:Clean:D8”. The simplistic approach would be to require all such strings to have a fixed number of parts, but this will look very messy with lots of “*”. A better solution is to require that all of the attribute names be unique and then the program can search for each name and from it determine if it represents the car’s length, class, door, or whatever. This seems to be a good compromise in that each attribute tends to be quite different in the types of names used, so not allowing the same name for different attributes should not be a problem. For example, lengths tend to be two digits (40), while capacities are 4 digits or more (6000). Time will tell if this assumption holds true or not as more car attributes are encountered from the real world.

The format of a role string, on the other hand, must include all of the parts in the correct sequence, because it must know which are to be ignored. It might be possible to make this more flexible with some more thought and testing, but for now this will have to be the case.

Calendar equivalents for 2020

I like to hang up old calendars that match the current year in order to enhance the period feel around the layout.

2020 is a leap-year, so there are far fewer calendars that will match it exactly, as they also must be leap-years. This is a good year for just matching January – February, and then changing again for March – December.

So, for 2020, the matches are:

Full year:
1908, 1936, 1964, and 1992

1902, 1908, 1913, 1919, 1930, 1936, 1941, 1947, 1958, 1964, 1969, 1975, 1986, 1992, 1997, 2003, and 2014

1903, 1908, 1914, 1925, 1931, 1936, 1942, 1953, 1959, 1964, 1970, 1981, 1987, 1992, 1998, 2009, and 2015

November 30th work session

Another great session on Saturday. The scenery around Curlew is looking great thanks to the guys.

Atlas/Kato GP7 LED headlights

Many years ago Atlas sold a variety of locomotives in the so-called “Yellow Boxes”. A number of these were made by Kato for Atlas, and have proven to be some of the best running locomotives of all time. They are still worth picking up at swap meets. In this series there were two numbers for Canadian Pacific in the block lettering scheme, and many of us have acquired these over the years. They of course need to be converted to DCC, but fortunately a number of the DCC vendors make drop-in boards that snap on to the mounting points perfectly. The lighting, however, is another story.

The original design used a single incandescent bulb sitting up above the motor, so that the light would shine in both directions through clear plastic light guides, and out the end headlights and number boards. With DCC, we can now control each light independently, so we need two LEDs. The first photo shows the new DCC decoder mounted, but still with the original light guides in the shell.

Chassis with new NCE decoder and the shell with the original clear plastic light guides before shortening.
Continue reading “Atlas/Kato GP7 LED headlights”

Goldilocks and the three metrics

Q Factor formula

How do we measure the “goodness” of an operations scheme for running a model railroad? Well, having a computer program that can easily run studies of a layout over many days with different operating schemes, train timetables, and other parameters, we can generate a lot of statistics from each run and then compare them, but what measures indicate a better or a worse outcome? We have all attended good and not so good operating sessions and can probably list a number of aspects that made one better than the other. The trick is to find a way to quantify at least some of these so that the program can better serve as a planning tool, and we don’t need to impose on our friends while we “try it and see”. There are certainly some aspects that people enjoy about a session that can’t be quantified, but maybe we can find some way to approximate a measure of “goodness”.

Stepping back from calculations for a moment, the main purpose of an operating session is to move cars around a layout to where they should be, through the running of various trains according to some operating scheme. The non train aspects, such as dispatching, train orders, etc., are outside of the scope of this discussion, because they are not simulated by the program. With that in mind, I think that the following characteristics can be accepted as indicative of a good, well run operating session.

  • Industries should have the number of cars they require.
  • A good number of the cars should move at least once.
  • All cars that are ready to move should move.
  • Only specialized cars should be off the layout in storage.
  • Yards, interchange, and other nonrevenue locations should have a minimum number of cars.

In other words, the layout should be well utilized, cars should flow smoothly to where they should be going, and there should be lots of activity to keep the crews busy during the session. Layouts with too few cars in play to provide sufficient interest or those with so many cars plugging up everywhere that hardly anything moves tend to be less satisfying for crews. Some variation is of course desirable, but extremes are not.

So the trick is to find some measures in the program that can capture these ideas so that we can judge if one operating scheme is better than another. The idea is to have a number of metrics about a session that can be combined to produce an overall score. If each one has a maximum value of 1.0, meaning that the aspect is as good as it can be, then we may be able to just multiply them together and still consider 1.0 as the “perfect” result.

Some of these characteristics tend to be at odds with one another. For example, if we add more cars to a layout so that we have a higher fraction of the industries fully served, it may result in cars not flowing through yards as quickly due to congestion and limits. This reduces the overall mobility and can lead to gridlock.

Here are three ideas for what we might measure.

  • Pickup Ratio – The fraction of times when a car is ready to move, and a train should move it, but it does not pick it up due to some limit on length, space ahead, etc. If a car always gets moved when it is ready, then the score would be 1.0.
  • Q Factor – The fraction of cars that are at revenue tracks (industries) and staging, versus those on nonrevenue tracks and in storage. We want the cars to be moving about the layout and not sitting waiting somewhere. Again, 1.0 is best.
  • Revenue Usage – The fraction of the track space at industries that is occupied by cars. Obviously this cannot always be 100 percent, as some industries only receive cars infrequently, but we also don’t want them never more than say half full either.

These three metrics are easy to calculate by the program, and are reported in a summary file for each study run.

To play around with how all of this might look, I plotted these measures for the S&BC for different numbers of cars, and different interchange probabilities. Other posts talk about some of the issues we have had with too many cars clogging up the Grand Forks yard because they are waiting to be interchanged between the two railways. The solution seemed to be to minimize the shipments that require interchange by coercing them to be selected less often, so this was a good test case to see if these metrics would support this idea in a quantifiable way.

The following graph shows the effect of having 40, 60, 70, 80, and 98 cars on the layout, with the train schedules and everything else the same. The probabilities of interchange shipments were not reduced. We would expect that as more cars are added, the revenue track usage would go up, as it is very low with only 40 cars in play, but we might end up with so much congestion that cars start to be unable to move when they should. This in fact is what happens. The green line shows the track usage going up from just over 0.2 to 0.7, meaning that we have a lot more cars delivered to the industries from the additional cars. But, the yellow line shows that there is a price to pay for this, namely congestion, as the rate of car pickup drops from over 0.9 (very good) to about 0.35 (very bad), which means that a lot of the cars that are ready to move are being skipped by trains when they should otherwise be picking them up.

Qfactor graph with interchange at 1.0

The blue line is what I am calling the Qfactor, using the formula shown at the start of this post. It is the fraction of cars at revenue and staging tracks, divided by the total number of cars. It simply indicates what portion of the cars are on the “good” parts of the layout, actively participating in the running of trains, versus those that are mostly sitting idle for one reason or another. In this case it is mostly constant and independent of the number of cars in play because there is extra capacity at the industries that can accept more cars, however a roughly proportionate number of additional cars will also end up on the non-revenue tracks such as yards while they wait longer to be delivered. This is a good example of why we need more than one metric, as there are opposing tends at work.

And finally, the red line is just a combination of the other three, in an attempt to provide a single value. I’m not sure yet how much value this may have. Time will tell.

A second set of studies were then run with the same numbers of cars, but with a much lower probability for the interchange shipments. This should result in far fewer cars waiting in the Grand Forks yard to be interchanged from one train to another and more at the industries. All of the shipments that required interchange between trains were set to a very low probability, so that they would be selected only as a “last resort” if there were no other direct shipments available.

Qfactor graph with interchange at 0.01

This time we have a very different set of curves. The car pickup ratio (yellow) is very high throughout, meaning that cars never have to wait long after they are ready to move, which is what was expected. The industry tracks are never very full at only 30% (green) so that is a concern, and the Q factor (blue) starts out very good, but drops rapidly as more cars are added. A closer examination shows that this is because almost all of the extra cars end up getting stuck in storage and never making it on to the layout. This in turn is because none of the shipments will be exchanged in the yard, so there is nowhere for them to accumulate and be in play on the layout. In short, the trains leaving staging quickly get saturated by cars freely going between staging and the industries, with none sitting around waiting. The flat portions of the yellow and green lines shows that the extra cars have no effect on them. This would probably be considered a good operating session with freely flowing cars, so long as it was acceptable to have low utilization of the industries. One conclusion from this is that the “natural” number of cars for this operating scheme is somewhere between 40 and 60 cars. The way to have more cars on the layout is probably to run more trains so that there is more capacity out of staging to feed the layout. This might be worth trying sometime.

So, in summary, I think these three metrics give a good insight into the nature of an operating session simulation. I expect to improve my understanding of their implications as more experience is gained, but for now, they should serve well for planning, comparing, and contrasting different operational schemes. Oh, and what does Goldilocks have to do with this? Nothing at all.