News:

The Forum Rules and Guidelines
Our forum has Rules and Guidelines. Please, be kind and read them ;).

possible bug with the way pax choose lines.

Started by ӔO, February 12, 2012, 04:28:01 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ӔO

I've noticed this in the network game and it's rather strange.
The pax will choose the slower, less frequent, less comfortable line instead of an express that has a direct route.
It seems to occur on quite a lot of sections of the network, but it is most pronounced for the lines between Workmere and Woolham.

Lines in question are Rail East | Branch - Hatley and Rail Central | Express - Thurmouth to Woolham under AEO railways ownership. It also occurs between Highing to Crawby to Newhall, and Curlden to Thurmouth, but it is not as noticeable.

http://dl.dropbox.com/u/17111233/client1-network.sve
My Sketchup open project sources
various projects rolled up: http://dl.dropbox.com/u/17111233/Roll_up.rar

Colour safe chart:

Carl

In general terms: as I understand it, when a slower train to the destination arrives, passengers undertake a calculation as to whether they should board or wait for the next express. Also, I think that once pax have been waiting for a certain amount of time they will board any service to their destination. (Is this right?) So it should not be too surprising to sometimes find them boarding the slow train rather than waiting for the fast train, especially when there are significant gaps between express service.

ӔO

actually, no, the express trains are approximately 16/mo (12:00 waiting between each train), while the branch is 6/mo (32:00 waiting). There's almost no gap in service between the express trains, but the branch will sit there for quite a while.

From what I see, the pax seem to take the first train to arrive to the station. Which means the branch that sits there collects all the pax between the 2 or 3 express that arrive after it.

most observable at woolham.
My Sketchup open project sources
various projects rolled up: http://dl.dropbox.com/u/17111233/Roll_up.rar

Colour safe chart:

Carl

That chimes with my findings, actually -- the calculation will almost always result in pax joining the slower service rather than waiting for the fast, no matter what the gap. The equation certainly needs balancing.

However, caution is needed. Back in (e.g.) version 8.2 the behaviour used to be opposite -- pax would almost *never* join a slower service, even if it was only slower by a minute or two. This was highly frustrating. I'd certainly prefer what we have now over what we had then, given the choice. But obviously something more moderate would be preferable!

jamespetts

Thank you both for looking into this. Carl - would you be able to have a look into the code and see if you can get a more reasonable intermediate value here? It would be very helpful.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

Carl

Yes, I'll take a look at the relevant section in simhalt.cc and see if I can work out why the current formula most often leads to pax boarding slower convoys.

jamespetts

Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

dustNbone

I don't think it's that they pick the slower one, they seem to pick the first one that's going directly to their destination.  I've had networks where the local train and express use mostly the same track, with the express stopping at 1/4 or so of the stops on the way.  Express trains are faster, and have the ability to pass locals stopped on some platforms so their trip time will always be faster than the locals, usually by quite a margin as every local gets passed by at least one express on it's way.  But passengers will still tend to get on a local and ride it all the way to their destination.

Carl

I've rewritten this function in order to give a more moderate behaviour. As well as fixing the specific problems in the save AEO uploaded, it seems to perform better generally. The revised simhalt.cc file is here:
http://dl.dropbox.com/u/61716/simhalt.cc (the relevant section starts at line 1607)


Here's an explanation of how the new formula works:


SHORT EXPLANATION:
When a slower convoy arrives, passengers ask themselves up to two questions:

1. "How much slower is this service than the fastest service?"
If the answer is "not very much", they board the slower service. If the answer is "much slower", they ask question
two:

2. "How long have I been waiting?"
If the answer is "too long", they board the slower service. If not, they wait for the faster service.



LONGER EXPLANATION & RATIONALE:

Question one above has not been in the code before, but it seems to me to be the most crucial aspect of the decision. If the "slower" convoy is only one minute slower than the fast convoy, then I should not hesitate before boarding. This fixes a bug which used to be reported a lot: that when two lines running identical convoys share a portion of their route, passengers will only board one of these routes even if it is only slightly faster.

In more detail: my code gives passengers a "tolerance" for slower convoys -- a tolerance which varies depending on how long the next hop is. So, if the next hop is only ten minutes, passengers will gladly board a convoy which takes fifteen minutes (50% tolerance). But if the next hop is two hours, they will not board any convoy which takes longer than 2.5 hours (25% tolerance). So -- as you'd expect -- the tolerance decreases the longer the journey. If the journey is short, passengers are more likely to board whatever convoy shows up (as long as it is not MUCH slower).

You might think that these tolerances are quite generous, but in practice they turn out to be just tolerant enough. They also sit well with real-life examples. Here's one: there are several different kinds of train from Leeds to Sheffield. The fastest trains take 40 minutes, semi-fast trains take 55 minutes, and slow trains take 73-84 minutes. As you'd expect, real-life passengers from Leeds to Sheffield board semi-fast services as well as the fast services (since these are only 15 minutes slower) --- and the code I've written would have this result too, since the tolerance for journeys of between 31 and 60 minutes is 40%. (That is, 55/40 < 1.4). Similarly, the code would have the result that passengers would not board a slow train for a Leeds-Sheffield journey, because it is much slower (that is, 73/40 > 1.4).


Question two retains an element of the old behaviour: if passengers have been waiting for too long, they will board the slower convoy.  But what counts as "too long"? Once again, that depends on how much slower the slower service is. If it's only slightly slower, then passengers won't have to be waiting long (double the average waiting time) before they choose to board that instead. On the other hand, if the slow service is a lot slower (think Carlisle to Lancaster via the Cumbrian Coast line instead of via the West Coast Main Line -- quadruple the journey time...) then passengers will have to be waiting a long time (5x average waiting time) before they board the super-slow service.


I've tested this both with the network save and several other games. It seems to work very well. Passengers will board services which are almost as fast as the fastest service, but will almost always refrain from boarding services which are much slower -- unless, of course, they have been waiting for a long time.


No doubt the function could be more complex still -- but I think this version is nuanced enough to give the right results in almost all of the most interesting possible cases.

jamespetts

Thank you very much for your work on this - it is much appreciated! From the description, this seems excellent. Haven't had a chance to test it, I am afraid, as still wading through treacle with the desyncs bug, but shall look forward to giving it a go. Thank you for your work!
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

Junna

carl, would it perhaps not be useful if this was coupled with some sort of information on the station screen, showing destinations and times by line? It would be handy to see the travel times for each service, especially if, hopefully, they will tend to use more than just one if they are close enough in time. I guess it would have to depend on how difficult it would be to implement.

Carl

James -- no problem, my pleasure! I look forward to hearing what you think of it in action.

Junna -- I agree, that would be very useful. In general the station detail window could do with tidying up, and listing different journey times per line would be useful information to provide. I'm looking into this part of the code now, but I think it might be beyond my abilities. We shall see...

Note that there is a workaround using the present system. Suppose you have lines like this:

A
  \
   C----D
  /
B

Say the A-C-D line is fastest between C and D. If you want to know how long the B-C-D line takes between C and D, you can look at the journey times from station B and subtract the journey time to C from the journey time to D. Although this isn't a flawless method, it'll give you some idea of the journey time.

Of course, it would be easier to simply have this all displayed in C's station detail window!

dannyman

Hello,

So, this is fascinating and thank you carlbaker for code.

What I see in the station detail window are lists of destinations, and travel and wait time.  I have been curious how frequently these are updated, and whether waiting time is an average or an estimate based on when the next convoy is expected ...

I assume it is an average, and even if it is, if this data is available in the simulator, per line, maybe the pax can make a decision like:
a) what is travel time + wait for convoy a?
b) what is travel time + wait for convoy b?
When convoy a shows up, take convoy a if travel time < (convoy b travel + wait)

Depending on how useful the "waiting time" metric is then that might be more useful than how long the pax has been waiting.  If I have been waiting a long time but know the express train is coming two minutes after this local departs, I'm going to hold out for the express!

It would also be neat if the Station details screen could break the travel / wait metric out for me for multiple lines:
Destination: Foosburg Town Hall
Travel Time: 2:00h (30m waiting) via line A
Travel Time: 1:00h (1h waiting) via line B
(...or such...)

I have been having fun with this in my current game, where there's a rather extensive bus network competing with a more limited, but growing rail network.  It is fulfilling to see that while the trains get plenty of business, plenty of pax still prefer the slower, less comfortable buses to get more directly to destinations.  It is also somewhat reassuring to know that if the trains get messed up somehow, the passengers will flock to the buses, or vice versa.  (Road traffic gets insane, especially with the present citycar queueing bug!)  THIS sort of balance is why the Experimental branch is so rewarding to play!  Thank you all!

-danny

jamespetts

Danny,

thank you for your input. To answer some of your questions: the "waiting time" is indeed the average waiting time. They are updated every time that the paths are refreshed (you can see in the display dialogue when this happens).

It would be very difficult to assign particular waiting times to particular lines, however: how would one apportion wait times between lines without arbitrariness? Suppose for example that Line A and Line B serve a given pair of origins and destinations. Suppose further that Line B is delayed for some reason - will the waiting time for Line A increase because it gets Line B's delayed passengers, whilst Line B's waiting time remains unaltered because all the passengers have boarded Line A?

The difficulty with the passengers who have been waiting a long time holding out for the express if they know that it will be coming in two minutes is that there is no way in the game to predict when the next convoy will, in fact, arrive - one can only use averages.

Glad that you are enjoying the way in which Experimental is set up, however, and thank you again for your thoughts!
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

dannyman

jamespetts,

Thank you for the clarification.  It is good and in a way reassuring to understand that the passengers have a fairly naive understanding of the world, which is consistent with most of my experience at least with transit systems: you may know there's an express and a local, but you don't really know when they're going to show up, and even if there is a published time table, you still don't know if the express might be delayed ... a bird in the hand or a bet on the bird in the bush?  (Thus, if I have been waiting long enough and an express doesn't show, screw it, I'm taking this local -- perfectly consistent with the year I lived in Brooklyn!)

(Of course, now we passengers get countdown clocks but I reckon most of us play simutrans in the past, when taking a bus or a train meant embracing a greater degree of mystery. =)

Thanks Again,
-danny

Carl

In relation to James's post here (implying that floating point arithmetic is not network safe), I should emphasize that this patch includes one instance of floating point division. Therefore this particular operation may need to be converted into the deterministic class you mentioned in that topic in order to make this patch network-safe.




As far as I can see, the floating point division here is not dispensable, since the calculation involves working out the slower convoy's journey time as a percentage of the faster convoy's journey time. If one uses integer division then the result will always come out as "100%", "200%", or some other multiple of 100 -- rendering the feature useless.

jamespetts

Quote from: carlbaker on February 22, 2012, 12:01:05 PM
In relation to James's post here (implying that floating point arithmetic is not network safe), I should emphasize that this patch includes one instance of floating point division. Therefore this particular operation may need to be converted into the deterministic class you mentioned in that topic in order to make this patch network-safe.




As far as I can see, the floating point division here is not dispensable, since the calculation involves working out the slower convoy's journey time as a percentage of the faster convoy's journey time. If one uses integer division then the result will always come out as "100%", "200%", or some other multiple of 100 -- rendering the feature useless.

Ahh, thank you for pointing this out. I have not had a chance to look at your code yet, but, if you are after percentages, could you not simply multiply then divide again? For example, if you want to do:


int percent;
double a = (double)some_int;
double b = (double)some_other_int;
double result = a / b;
percent = (int)(result * 100.0);


could you not instead do this:


percent = (some_int * 100) / some_other_int;


?
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

Carl

#17
Of course! I don't know why I didn't think of that before. My maths must be rusty.

I'll alter the code as such and post a modified version here this afternoon.


----------


Edit: I've attached a revised patch, incorporating both the "boarding slower convoys" fix discussed here and the "spacing and loading" patch.


Thanks for your suggestion above, James -- the altered code seems to work fine and to have just the same effect.




jamespetts

Excellent - thank you very much! I'll try to get around to making progress on this as soon as I can.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

chs

Following up on carlbakers EXPLANATION above, with an example situation to get from A to B
- line 1: average waiting time 20 min, travelling time 50 min, total 70 min
- line 2: average waiting time 25 min, travelling time 55 min, total 80 min
Passenger arriving in station A waits for line 1, he waited for 10 min. Then line 2 arrives. Under what circumstances does he take line 2? This pax has a max waiting time of 50 min before he "boards anything" (takes any vehicle that gets him to B).

I personally would take line 2, if (expected waiting time + travelling time for line 1) >= (travelling time for line 2). For this, the length of the journey does not matter to me. The time I have been waiting matters: I expect that I have to wait less because I already waited for some time. The maximum time I am willing to wait (before I board anything) also matters - the higher it is, the more willing I am to wait longer. Maybe this could be calculated like:
expected waiting time = average waiting  time - (x% of average waiting time)
where x = the time I already waited in % of the maximum waiting time

So after 10, 20, 30 minutes, I would take line 2. But after 40 min, I would keep waiting for line 1, because I think it must come any moment. Both using the above formula.
Not sure how realistic this is, because 10 min later (50 min waiting, >= max waiting time) I would board anything. I think the key point is, how do we calculate the expected waiting time.

What also matters are factors like service reliability (which maybe could be measured as the standard deviation from the average waiting time), comfort, nof waiting pax, though I think they are all less important.

Carl

Hi chs,

In my patch, waiting times do not play the kind of role you're describing -- they only play the "has the passenger been waiting too long?" role.

The reason for this is that waiting times are the most elusive and changeable part of the routeing system. Although the formula you describe above sounds good in theory, in practice it doesn't work because of the unreliability of waiting times. Journey times are much more reliable at present, and so it makes sense for them to do the heavy lifting in this feature.

I've experimented with a number of different ways of doing this, and giving waiting times anything like the role you describe doesn't give good results.

I think this patch appeals to a very important part of the passenger's decision-making process which is (a) based on data which Experimental is very good at discerning and (b) has so far been absent from the code at all.

(Note that there is no "passenger will board anything" feature in my new patch: rather, as time passes pax will gradually become willing to board slower and slower convoys (as one would expect), until eventually they will board anything that arrives.)

chs

Hi carlbaker

Thank your for your answer. I am looking forward to test your patch in the next version (I am only using win binaries).

As you said, waiting times are very difficult to calculate, since it varies a lot. As soon as a passenger knows the waiting time, he can choose the optimal connection.
In reality, the synchronized schedule (in german "taktfahrplan", meaning you have regular connection every 2, 1, one half etc. hours) did change this a lot. As soon as pax learn that these connections are reliable, the waiting time is minimized and nof passenger should increase (actually, this is what happened in switzerland).

Do you think it would be useful to include the reliability of connections in the game? Generally, this would lead to "known" (at least better known) waiting times, causing passengers to optimize their travel time. And as travel time gets shorter, there would be more passengers.