Freight Car Routing - My university project moves on


davidpen

Long Haired David
I am busy working away on the project. Although it is, supposedly, a software project, the University sees it as a project report. I am expecting to have a working prototype to accord to the the original design once the course ends but the University deliverable is a 10,000 word report. To help me develop this, I have created a blog where I am slowly developing the ideas. The first part is all about the technical structure of the hardware, servers and software but now I have to start developing the main decision engine so I am working on developing the ideas before I need to get stuck in and write the code.

Please note, I am putting my ideas down as I consider them. At no point yet have I developed a final proposal for the decision engine. In fact, I am likely to go back and change elements of the previous thoughts.

My tutor requires that I have third party involvement.

You can see how I am getting on by following my blog HERE.

I would welcome suggestions as to where to go forward but, after previous experiences, could you please be polite. I can't change the basis of the project so any suggestions that I shouldn't start from here would not be helpful. In fact, even if I fail in producing a working program, I will still be able to write my report and finish my B.Sc.(Hons).

I am looking forward to hearing from you.
 
In reality the inbound and the outbound car movements are not as closely linked as your description implies. There is an inbound flow of livestock based on the ability to consume product and an outbound flow of finished goods based on the ability to produce product.

The livestock was in reality bought a week or more before the car arrived at the packing plant, and the time the animals spend in the car has to minimized. The slack in that process is not the in the railroad its in the packing plant. It has a different flow of cars than, lets say a printing plant. If a printing plant buys 5 cars of paper, and only uses 1 car of paper a day, it can put the five cars in a track and order one car of paper to be spotted a day. Not so much with livestock. If a packing plant buys five cars of livestock, it has to spot the livestock ASAP and unload them all at once into holding pens at the plant and feed the cattle from the pens, not the cars into the plant.

Meat reefers are specialized cars and the customer will order an allotment weeks or months in advance to make sure they have them on hand. They can't just call up the railroad and order one, because the railroad doesn't own any (virtually all the meat reefers were privately owned by meat companies), so it could take weeks to get one if they run out. Icing isn't a "customer" its a service (just like car cleaning). The customer would order a car and specify it has to be pre-iced, the railroad would take a car from where they were stored (nearby) and spot it to be iced, then spot at the packing plant. The ice dock doesn't order a car, the meat packer orders a car in a specific condition (pre-iced). Depending on how long the car sat and how hot it is, the car might have to be topped off again before its actually shipped.

Unfortunately, the meat trade was one of the more complicated examples you could have picked, hope this helps fill in the gaps.
 
Its interesting that you don't think the databases need to be normalized, especially since the prototype ones are.
 
Not using a SQL database. On a Key/Value database, there isn't any normalising. You have multiple copies of data under different keys.

Using an example of my model shop web data base:

key -> Value
SaleID -> sale record.
Client Name -> sale record list
Client ID -> sale record list
and so on.

Just out of interest -Amazon use a similar database.

david
 
Last edited by a moderator:
On a key/value database, if you change something don't you then have to track down all the places that field exists and change the value in multiple tables?
 
Only if you are using it as though it was a SQL db (which would be pointless).

KV databases are used for fast access by keys - not by searching. There are objects in buckets accessed by keys. You use it by dumping and reading complete records ( not an expression that I like - I prefer "objects"). So, in my prototype, there is very little data that gets changed for each train creation. Think of a railroad with 100 locos and 450 cars. At any one time you are building a single train with 3 locos and 50 cars, say. That looks like a lot of data to be saved as each car needs to know what train it is on and where it is going. However, each car record is minuscule and without the payload of a SQL record. Modern servers can write that lot out almost instantly. - 3 loco objects updated, 50 cars re-written, one new train saved. When you want the data, the train holds the ids of all the cars and locos so no searching required.
 
I was thinking more along the lines of lets say I have a station "Coateville". So all the routes and all the customers and cars at that station get the station name applied. About the 3rd session, I notice that I misspelled it and it should be "Coatesville", with an S in the middle. Wouldn't the system have to check every record in every table in the database to correct the spelling? Trivial example but it can happen and if you match on spelling it can create mismatches if its not consistent.
 
I think that you are thinking about traditional databases. The only thing that matters in this scenario is "this train". The system builds the train for you. You use the information; tell the system that you have moved all of the items; the system updates for the new locations and then that whole action is forgotten. There is no concept of a history report - who cares what happened 10 trains ago?

The data is all entered at start up-currently, the scope of the project does NOT include any data maintenance at all. Should this become anything other than a toy for me to play with whilst i move trains then this element would be addressed but, at the worst, it would require only the cars at that location to have their data changed - and they are all stored under a key for location.

Think of my shop database. A customer tells me of a misspelling in the town in their address. This would only affect future sales as all of the last ones have gone and been finished with. It does require a new mindset.
 
but now I have to start developing the main decision engine so I am working on developing the ideas before I need to get stuck in and write the code. Please note, I am putting my ideas down as I consider them. At no point yet have I developed a final proposal for the decision engine. In fact, I am likely to go back and change elements of the previous thoughts.

I would welcome suggestions as to where to go forward but, after previous experiences, could you please be polite.
I am looking forward to hearing from you.
I don't see any reaction to any of the thoughts people gave on the 2/12 thread. Should we repeat those here?

What sort of model are you thinking about for your decision engine. Are you going to use basic algebraic logic, or predicate calculus type expressions with variables (PROLOG language) and or rules with some sort of expert system tool?

Industry X -> Car Type A
When Industry X Needs Random(number) Cars -> Create Train
When Create Train ADD Car type (Industry X.CarType)

The blog talks much about lists of things. Several smart folks believe all knowledge and therefore intelligence can be characterized as lists of lists. With them being so prominent in the March 22 post have you considered just using the LISP or Scheme language straight up? The tuples (key value pairs) would be a simple list like tupleName(key,value). There have to be plenty of inference engines written in LISP sitting out there in the public domain.
 
Last edited by a moderator:
Industry X -> Car Type A
When Industry X Needs Random(number) Cars -> Create Train
When Create Train ADD Car type (Industry X.CarType)

I write in Smalltalk and in pseudo code that comes out as:

Car Type A sendTo: IndustryX;
[IndustryX needsRandomCars(aNumber)] ifTrue:[ CreateTrain new(IndustryX, carType, numberOfCars)];

CreateTrain newFor: anIndustry carType: carType carNumbers: numberOfCars);
| o |
o := self new;
o industry: anIndustry;
o addCarType: carType;
o carNumbers: numberOfCars;
o make train

This is gibberish of course but you can see how it can be modelled.

There will be about four iterations as I implement better logic.

I will release the prototype as I go along.

I have been caught up finishing another course which ends tomorrow so I am back on this project full time from next Monday.

David
 
Industry X -> Car Type A
When Industry X Needs Random(number) Cars -> Create Train
When Create Train ADD Car type (Industry X.CarType)

Other than a unit train, a real railroad doesn't run a train when an industry loads x number of cars, typically what a railroad does is run a train on a time basis, with whatever cars are ready at that time. Rather than "Industry A is going to ship 5 cars, I am going to run a train.", real railroads operate like "Its time to run a train, how many cars do I have for this train's route." If it is smaller than a certain threshold them may wait until the minimum is reached, if its more than the maximum they will truncate the train and roll the excess cars to the next train or run a second train later.

For what I understand the concept of this program, the train size is the driver. To do that it actually needs to work backwards.

I want to run a train.
What are the industries on the trains route.
Loop through those industries in a random order.
Select a random number of cars, up to the industry max, that match that that industry's needs.
If the total number of cars is below the train max, go to the next industry.
When the max number of cars has been reached, or all the industries have reached their max car limit, print a list and run the train.

If its just a one sided system then commodity doesn't matter, just car type. If the system is going to figure both ends of shipment, the shipper and the consignee, then its going to have to take commodity into account. I can't just ship boxcars from industry A that uses boxcars to industry B that uses boxcars, or I can end up with the company making bolts shipping to the company that ships powdered milk.
 
This is how it works. I was just explaining to the previous poster how my software looked like his pseudo code.

My blog at https://tm470routingproject.blog explains:
"the DE has to track through every location that could source or require a car and assess any need. Once this analysis is done, there is, theoretically, a train. However, collecting cars from industries that have either been emptied or loaded will always be available but providing empty cars from the yard depends on what is available on site. Note: for the first pass at the full DE, requests for cars that cannot be executed because of the non-availability of empty cars will be discarded. A future expansion of the DE would need to keep the list of non-executed deliveries for allocation to the next available train.

*Next, the total length of allocated cars will be assessed against the permitted length of the train. Should this be exceeded, then a decision will need to be taken regarding cars to be dropped.*

Lastly, the available locomotive fleet will be assessed to provide suitable “front end” power.

This should result in a suitable train. However, should sufficient power not be available, then the processing would revert back to * to reduce the cars by an acceptable number."
 
My blog at https://tm470routingproject.blog explains:
"the DE has to track through every location that could source or require a car and assess any need. Once this analysis is done, there is, theoretically, a train."

No there is demand or there are cars to be moved, ore there is a switch list, but there isn't a train yet.

However, collecting cars from industries that have either been emptied or loaded will always be available but providing empty cars from the yard depends on what is available on site. Note: for the first pass at the full DE, requests for cars that cannot be executed because of the non-availability of empty cars will be discarded. A future expansion of the DE would need to keep the list of non-executed deliveries for allocation to the next available train.

Based on this, if you don't have an empty reefer in the yard, at least in the first iteration, you will never spot a reefer to the industry because it will be dropped. Even in the future version, it will just roll the demand to the next train. If there were unfulfilled orders for that cycle it would continue to roll them to the next train and so on. The problem I see with this is that if you have the engine proposing a higher demand than there are cars available, the owner will never know he is short of cars, and conversely if he never knows the engine is generating a higher demand, he won't know to adjust a parameter if the engine is generating too high a demand. The system should tell the user that there were XX cars assigned to spot, but YY orders for cars that were unfulfilled.

Similarly there needs to be a report that indicates there when cars were trimmed from a train due to length or power.

You said "but providing empty cars from the yard depends on what is available on site. " What about providing loads? The packing company receives inbound boxes in boxcars from Chicago. If a boxcar is being loaded with canned meat the system will look for an "empty" car in the yard. Where does the system look for inbound loaded cars?
 
"Empty box cars come from the general pool so can be sourced from either end of the railroad". This includes reefers.

"The problem I see with this is that if you have the engine proposing a higher demand than there are cars available, the owner will never know he is short of cars, and conversely if he never knows the engine is generating a higher demand, he won't know to adjust a parameter if the engine is generating too high a demand. "

I have been caught up finishing another course so I haven't been onto this for a few weeks. I expect to create additions to the blog to extend the thinking now that I only have this course to work on. Short of cars isn't an issue - so the train runs light. Must happen in the real world. Too many - good point but we aren't running a railroad, only a model so generating lots of lists for things that didn't happen aren't really necessary. If we generate 5 cars extra for every train, it would mean that, somewhere, there is a parameter that needs tweaking, rather than "Fred Brown is late getting his two box cars so we must ensure that we deliver them ASAP". Remember that most people run a railroad for a couple of hours and then come back to it sometime. Being reminded that there are 50 cars so far that haven't been shipped isn't really part of the "model" scenario.
David
P.S. Thanks for the comments. Keep them coming. I have to start coding this in a week or so so I will have to close this off soon.
 
crossover from the other forum.

The industry is the creation of the traffic. It sits in a division/subdivision with a yard its assigned to and a railroad. The system finds a from/to (from yard A to Industry 1). pickup-advance next route, from industry to yard, yardmaster gets list and sorts cars for next train. Next routing sends it to Yard B for sorting and next route sends it to Industry 2, next route sends it back to yard B. The car might have a home spot set for it so it might go back to Yard A, where it rests till the next assignment.

Think in terms of a single car move, the rest will follow. Your making me wanting to dig back into my programming... 8-D
 
Think in terms of a single car move, the rest will follow.

On a real railroad, there is a destination for each car. Loaded cars have a waybill, empty cars have a car order or an empty disposition.

Every car has a location. It could be a train or a station.

For each train there are defined blocks and locations where those blocks are set out of the train.

For each station that are defined blocks, which depending on how the definitions are written, each car schedules to a block. At each station, blocks are assigned to trains, or tracks in a class yard.

On a real railroad, trains and tracks have no car limit, there will be a warning that some defined limit may be exceeded, but you can still exceed it. Scheduling cars to trains or tracks is unlimited. If a train has an 8000 ft limit, the car scheduling system will schedule every car that makes the criteria, so it could have 50,000 ft of cars scheduled to a train with an 8000 ft limit. Similarly with a track. If the track is 1000 ft long, you can report 50,000 ft of cars in that track.
 
I write in Smalltalk and in pseudo code

I have been caught up finishing another course which ends tomorrow so I am back on this project full time from next Monday.
That's pretty cool. I've not seen Smalltalk actually used for years (maybe decades). I don't think I've personally ever actually used it for a real project, for that matter I don't remember enough of it to do a "hello world".... sad what I've forgotten.

Regardless, I think I see where you are going. The next thing I see a need for is the routing of the train, such that there is a train that collects all the needs of the industries in its direction. Otherwise it will produce 1 train for each industry in need of service which would be highly inefficient in the real world. As for what the others have been saying, several of my client railroads have scheduled trains that are "Planned", that is a train is planned to go from Kansas City to Heavener OK at 04:00. At some point (about 2.5 hours before on-duty time) a load estimator runs and determines whether or not to cancel the train, or change it into "ordered" status (at which point my system will call the appropriate crews for it). If it is a local and there are no set outs or pick ups it will not run. If an interchange yard suddenly starts receiving a bunch of un-anticipated cars and it looks like the planned trains will not be able to handle the traffic they might not wait for the next scheduled train but instead order up an extra train. Anticipating loads and needed crews remains a huge issue in the real world. My company has a whole group that works on nothing but the "optimization" issue alone.
I hope something in there might help. Looking forward to seeing what you come up with.

I can identify with the "another course", once in my college career I had taken on so much I finally just had to let a course go. I chose one, went to the professor and arranged an A, pass, fail type grade.
 
Last edited by a moderator:
You must be doing work for the "Hay wire" (the KCS).

I used to be part of a team that worked on crew balancing as well as the train line up issues and built software to support its management. I wasn't in programing, I was more defining the processes, measures and business rules.
 



Back
Top