Page 2 of 2
Re: combining train waiting conditions
Posted: Fri Jul 29, 2016 3:25 am
by guitarmanmike
kingarthur wrote:i had not read your post at the time i replied as yours wasnt showing yet. i didnt intend to copy what you had said already
I wasn't saying you had copied anything I was just saying that it was consistent with how I thought the algorithm works.
Re: combining train waiting conditions
Posted: Fri Jul 29, 2016 3:32 am
by kingarthur
oh got ya. ya weather or not the system as is functions as expected if we know what intended behavior is we can work with it and figure out ways to make it do what we want
Re: combining train waiting conditions
Posted: Fri Jul 29, 2016 11:16 am
by Jupiter
guitarmanmike wrote:It is top to bottom in the sense that the algorithm evaluates the operations sequentially top down and the result gets passed to the next operator.
If you think of it as an algorithm which would operate on an arbitrary array of operands it kinds of makes sense to call it top down.
Operands ops = [
B1
B2
B3
B4
]
(* is AND, + is OR)
Operations opts = [
*
+
*
]
int i =0
bool res = ops (B1)
for opt : opts
res = (if opt is +) res + ops[++i] : res * ops[++i]
end
return res (zero is false ,1 or higher is true)
There is probably a more elegant way to choose the operation to perform but I think it gets the point across.
For any devs reading this: if this is how it actually works then there is an obvious optimization to be made here: evaluate everything from bottom to top. This gives you 'lazy evaluation' meaning that, if you encounter an OR that is true, you don't have to evaluate the rest of the list. And if you encounter an AND that is false you can stop also.
With a 1000 trains in a map this might actually gain you extra performance.
Re: combining train waiting conditions
Posted: Fri Jul 29, 2016 11:59 am
by siggboy
Jupiter wrote:For any devs reading this: if this is how it actually works then there is an obvious optimization to be made here: evaluate everything from bottom to top. This gives you 'lazy evaluation' meaning that, if you encounter an OR that is true, you don't have to evaluate the rest of the list. And if you encounter an AND that is false you can stop also.
Yes, after we've figured it out I assumed this is what actually happens, and that Rseding91 actually meant "it accumulates from the bottom up" (instead of top-down). Because that would make a lot of sense with the "right-to-left parenthesizing" that happens right now.
Although I wouldn't call for making the optimization that Jupiter suggests. My plea is to rip this out and replace it with a boolean evaluation where AND takes precedence over OR; what we've learned in school (well, university maybe).
(But I understand now why it currently behaves as it does -- it's obviously easier to implement than proper boolean evaluation.)
Re: combining train waiting conditions
Posted: Fri Jul 29, 2016 2:08 pm
by Jupiter
siggboy wrote:Jupiter wrote:For any devs reading this: if this is how it actually works then there is an obvious optimization to be made here: evaluate everything from bottom to top. This gives you 'lazy evaluation' meaning that, if you encounter an OR that is true, you don't have to evaluate the rest of the list. And if you encounter an AND that is false you can stop also.
Yes, after we've figured it out I assumed this is what actually happens, and that Rseding91 actually meant "it accumulates from the bottom up" (instead of top-down). Because that would make a lot of sense with the "right-to-left parenthesizing" that happens right now.
Although I wouldn't call for making the optimization that Jupiter suggests. My plea is to rip this out and replace it with a boolean evaluation where AND takes precedence over OR; what we've learned in school (well, university maybe).
(But I understand now why it currently behaves as it does -- it's obviously easier to implement than proper boolean evaluation.)
I agree that that would be a better option. In addition to being a bit more intuitive it also gives more flexibility.
For example:
(A OR B) AND (C OR D)
Is impossible to formulate with how the system presumably works now. But it is possible (even though a little convoluted) with siggboy's suggestion (you would need to put several letters in their twice):
(A OR B) AND (C OR D) = (A AND C) OR (A AND D) OR (B AND C) OR (B AND D)
Re: combining train waiting conditions
Posted: Fri Jul 29, 2016 6:10 pm
by guitarmanmike
Jupiter wrote:
For example:
(A OR B) AND (C OR D)
Is impossible to formulate with how the system presumably works now.
It is not impossible if you can do one of the conditions in a combinator.
You could write it as (A OR B) AND (C OR D) = (A OR B) AND (X) so if you can do either C OR D or A OR B outside in a combinator you are fine. If not is pretty tricky I agree. (Not sure if impossible)
Re: combining train waiting conditions
Posted: Fri Jul 29, 2016 6:48 pm
by guitarmanmike
Jupiter wrote:
For any devs reading this: if this is how it actually works then there is an obvious optimization to be made here: evaluate everything from bottom to top. This gives you 'lazy evaluation' meaning that, if you encounter an OR that is true, you don't have to evaluate the rest of the list. And if you encounter an AND that is false you can stop also.
With a 1000 trains in a map this might actually gain you extra performance.
Code: Select all
int i = ops.length -1
bool res = ops[i]
bool quit = false
while i>0
quit = (res && (opt[i-1] is +)) or (!res && (opt[i-1] is *))
if quit
return res
else
res = (if opt[i-1] is +) res + ops[i--] : res * ops[i--]
end
return res
While this might be faster for examples where you have a very large list I am not sure it would be much of an improvement since the trains probably won't have more than 4 booleans in most cases and the quit expression takes about 4 evaluations /comparisons per item in the list while just doing the operation and moving on is about 3 operations so in the worst case it's 7 operations per list item vs the 3-4 per item in the worst case just going through all of them.
Re: combining train waiting conditions
Posted: Fri Jul 29, 2016 9:49 pm
by zebediah49
You can add one more to the list of people that understand predicate logic and don't consider it obvious how it works. I now understand, primarily from having looked over the truth tables, but I agree it's not obvious without experimentation.
However, since everyone is throwing out how they want conditions processed, I'll add mine: I think it should use RPN. That way, the mythical (A && B) || (C && D) can be done as easily as (A || B) && (C || D), with
Actually, come to think of it, the current execution method follows RPN, evaluated top-to-bottom, with the boolean operator immediately evaluated (rather than being allowed to be done later by using the stack).
Re: combining train waiting conditions
Posted: Sat Jul 30, 2016 3:16 am
by siggboy
RPN is too obscure.
We don't need anything obscure.
The best thing would be to make it dead obvious: have necessary and sufficient conditions, separate the two in the UI, find some symbols or terms that make clear what is happening, have a tooltip description, maybe a descriptive title or two in the user interface.
Even by using "AND"/"OR" and expecting the player to know the commonly used order of evaluation, one is already stretching the envelope. It's fairly technical, and it expects you to assume that the list is evaluated as a boolean expression from left to right.
Of course, the current implementation (UI + evaluation rules) might be one of the worst ways possible: it confuses beginners and experts alike.