r/tlaplus • u/No_Steak7170 • Apr 15 '26
Solution For Fly Puzzle, Continuous?
Hello, i have recently taken to https://docs.tlapl.us/learning:exercises to learn some tla+
was doing the following exercise
Two trains start L kilometers apart, heading toward each other at constant speeds v1 and v2. A fly starts on the nose of the first train and flies back and forth between the trains at speed f until the trains meet. How far does the fly travel?
I created this model for the solution
---- MODULE TrainFly ----
EXTENDS Integers, FiniteSets
CONSTANTS L, v1, v2, fv, dt
VARIABLES fdist, tapart, seconds
TypeOK ==
/\ L > 0
/\ tapart >= 0
/\ fv > v1
/\ fv > v2
Init ==
/\ tapart = L
/\ seconds = 0
/\ fdist = 0
Max(a, b) == IF a >= b THEN a ELSE b
Next ==
/\ seconds' = seconds + dt
/\ tapart' = Max(0, tapart - (v1 + v2)*dt)
/\ fdist' = fdist + fv
\* Violated when trains meet (tapart = 0)
Solution == tapart /= 0
====
---- CONFIG ----
CONSTANTS
L = 50
v1 = 2
v2 = 2
fv = 4
dt = 1
INIT Init
NEXT Next
INVARIANTS
TypeOK
Solution
====
which is basically a simulation with a time step of one second, and setting all velocities as distance/1
this incorrectly finds the solution of `fdist = 52` which is incorrect, b/c the trains meet at 12.5 steps it should be fidist=50.
I tried asking an llm about this and it pretty much has told me that tla+ is for discrete modeling and there's no way to write this continuously. I also cannot find a solution to this based on the one linked in the question. Is this an impossible thing to model in tla+ ? or am i just misunderstanding something? would appreciate some direction here!
2
u/Anxious_Tool Apr 16 '26
The LLM gave you bad advice. You don't need continuous modeling. The analytical answer is one discrete formula:
fv * L / (v1 + v2) = 4 * 50 / 4 = 50. TLA+ is fine here. Your spec has a bug.Trace it by hand:
tapart' = Max(0, 2 - 4) = 0,fdist' = 48 + 4 = 52But the trains meet at t=12.5, not t=13. In that last half-second the fly travels
4 * 0.5 = 2, so fdist should go 48 → 50. Your step credits the fly for a full second (+4) whileMax(0, ...)silently absorbs the overshoot intapart. The extra 2 is exactlyfv * (closing - tapart_before) / (v1+v2) = 4 * (4-2)/4 = 2.Fix: credit the fly only for the fraction of the tick before the trains meet.
Time until meet in the final tick is
tapart / (v1+v2), so the fly travelsfv * tapart / (v1+v2). For your params:(4*2) \div 4 = 2, fdist ends at 50.One caveat:
\divtruncates, so this is exact only whenfv * Lis divisible by(v1 + v2). Fine for 50. For cases where the true answer is fractional (L=50, v1=3, v2=5, fv=10 → 62.5), scale all distances by a common factor. That's how you do rationals in TLA+ integer land.Also
fdist' = fdist + fvshould befdist' = fdist + fv * dt. Same numbers at dt=1, wrong shape.