FA-68891 / Tide and marine navigation tables / Open access
Cosine curve time for height: Inverse cosine uses the rising-branch complement · case 01
Heights near low water are reached at the wrong end of the half-cycle.
ROOT CAUSE
The inversion uses acos(2*frac-1), i.e. time measured back from the second turning point.
VERIFIED REPAIR
Invert with acos(1-2*frac).
Unsuccessful approach: Using asin(2*frac-1) shifts the result by a quarter cycle.
Case contract
Input [t1,h1,t2,h2,h] (hours, metres) for consecutive turning points with t2>t1 and h1!=h2. Height follows h1+(h2-h1)*(1-cos(pi*s/T))/2 with s elapsed and T=t2-t1. Return the time in whole minutes (rounded half up) when the height h is first reached on that half-cycle, or None when h lies outside the closed range of h1..h2.
Why this case matters
Tide tables and passage plans turn published predictions into go/no-go decisions about depth, clearance and timing.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
t1,h1,t2,h2,h=x
lo,hi=min(h1,h2),max(h1,h2)
if h<lo or h>hi: return None
frac=(h-h1)/(h2-h1)
T=t2-t1
s=T*math.acos(2*frac-1)/math.pi
return math.floor((t1+s)*60+0.5)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('cosine curve time for height [0, 0.6, 6.2, 4.4, 0.6]', [0, 0.6, 6.2, 4.4, 0.6], 0), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 1.0]', [0, 0.6, 6.2, 4.4, 1.0], 78), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 2.5]', [0, 0.6, 6.2, 4.4, 2.5], 186), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9]', [0, 0.6, 6.2, 4.4, 3.9], 284), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4]', [0, 0.6, 6.2, 4.4, 4.4], 372), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.5]', [0, 0.6, 6.2, 4.4, 4.5], None), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1]', [3.5, 5.1, 9.75, 1.2, 5.1], 210)], [('cosine curve time for height [0, 0.6, 6.2, 4.4, 1.0]', [0, 0.6, 6.2, 4.4, 1.0], 78), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9]', [0, 0.6, 6.2, 4.4, 3.9], 284), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4]', [0, 0.6, 6.2, 4.4, 4.4], 372), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.5]', [0, 0.6, 6.2, 4.4, 4.5], None), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1]', [3.5, 5.1, 9.75, 1.2, 5.1], 210), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 4.0]', [3.5, 5.1, 9.75, 1.2, 4.0], 344), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 3.15]', [3.5, 5.1, 9.75, 1.2, 3.15], 398)], [('cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9]', [0, 0.6, 6.2, 4.4, 3.9], 284), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 2.5]', [0, 0.6, 6.2, 4.4, 2.5], 186), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1]', [3.5, 5.1, 9.75, 1.2, 5.1], 210), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 4.0]', [3.5, 5.1, 9.75, 1.2, 4.0], 344), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 3.15]', [3.5, 5.1, 9.75, 1.2, 3.15], 398), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 1.3]', [3.5, 5.1, 9.75, 1.2, 1.3], 547), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 1.2]', [3.5, 5.1, 9.75, 1.2, 1.2], 585)], [('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4]', [0, 0.6, 6.2, 4.4, 4.4], 372), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9]', [0, 0.6, 6.2, 4.4, 3.9], 284), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 1.3]', [3.5, 5.1, 9.75, 1.2, 1.3], 547), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 1.2]', [3.5, 5.1, 9.75, 1.2, 1.2], 585), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 0.9]', [3.5, 5.1, 9.75, 1.2, 0.9], None), ('cosine curve time for height [10, 2.0, 22.4, 2.6, 2.3]', [10, 2.0, 22.4, 2.6, 2.3], 972), ('cosine curve time for height [0, 0, 2, 1, 0.25]', [0, 0, 2, 1, 0.25], 40)], [('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1]', [3.5, 5.1, 9.75, 1.2, 5.1], 210), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4]', [0, 0.6, 6.2, 4.4, 4.4], 372), ('cosine curve time for height [10, 2.0, 22.4, 2.6, 2.3]', [10, 2.0, 22.4, 2.6, 2.3], 972), ('cosine curve time for height [0, 0, 2, 1, 0.25]', [0, 0, 2, 1, 0.25], 40), ('cosine curve time for height [1.25, 1.0, 7.25, 3.0, 2.0]', [1.25, 1.0, 7.25, 3.0, 2.0], 255), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 0.6]', [0, 0.6, 6.2, 4.4, 0.6], 0), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 1.0]', [0, 0.6, 6.2, 4.4, 1.0], 78)]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| cosine curve time for height [0, 0.6, 6.2, 4.4, 0.6] | 372 | 0 | Failed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 1.0] | 294 | 78 | Failed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 2.5] | 186 | 186 | Passed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9] | 88 | 284 | Failed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4] | 0 | 372 | Failed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 4.5] | None | None | Passed |
| cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1] | 585 | 210 | Failed |
SHA-256 / 5539be11db2179e4f5e8a5962ded2c941abd470886851994e0d4e70e8efab9d4
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
t1,h1,t2,h2,h=x
lo,hi=min(h1,h2),max(h1,h2)
if h<lo or h>hi: return None
frac=(h-h1)/(h2-h1)
T=t2-t1
s=T*math.asin(2*frac-1)/math.pi
return math.floor((t1+s)*60+0.5)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('cosine curve time for height [0, 0.6, 6.2, 4.4, 0.6]', [0, 0.6, 6.2, 4.4, 0.6], 0), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 1.0]', [0, 0.6, 6.2, 4.4, 1.0], 78), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 2.5]', [0, 0.6, 6.2, 4.4, 2.5], 186), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9]', [0, 0.6, 6.2, 4.4, 3.9], 284), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4]', [0, 0.6, 6.2, 4.4, 4.4], 372), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.5]', [0, 0.6, 6.2, 4.4, 4.5], None), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1]', [3.5, 5.1, 9.75, 1.2, 5.1], 210)], [('cosine curve time for height [0, 0.6, 6.2, 4.4, 1.0]', [0, 0.6, 6.2, 4.4, 1.0], 78), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9]', [0, 0.6, 6.2, 4.4, 3.9], 284), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4]', [0, 0.6, 6.2, 4.4, 4.4], 372), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.5]', [0, 0.6, 6.2, 4.4, 4.5], None), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1]', [3.5, 5.1, 9.75, 1.2, 5.1], 210), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 4.0]', [3.5, 5.1, 9.75, 1.2, 4.0], 344), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 3.15]', [3.5, 5.1, 9.75, 1.2, 3.15], 398)], [('cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9]', [0, 0.6, 6.2, 4.4, 3.9], 284), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 2.5]', [0, 0.6, 6.2, 4.4, 2.5], 186), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1]', [3.5, 5.1, 9.75, 1.2, 5.1], 210), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 4.0]', [3.5, 5.1, 9.75, 1.2, 4.0], 344), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 3.15]', [3.5, 5.1, 9.75, 1.2, 3.15], 398), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 1.3]', [3.5, 5.1, 9.75, 1.2, 1.3], 547), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 1.2]', [3.5, 5.1, 9.75, 1.2, 1.2], 585)], [('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4]', [0, 0.6, 6.2, 4.4, 4.4], 372), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9]', [0, 0.6, 6.2, 4.4, 3.9], 284), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 1.3]', [3.5, 5.1, 9.75, 1.2, 1.3], 547), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 1.2]', [3.5, 5.1, 9.75, 1.2, 1.2], 585), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 0.9]', [3.5, 5.1, 9.75, 1.2, 0.9], None), ('cosine curve time for height [10, 2.0, 22.4, 2.6, 2.3]', [10, 2.0, 22.4, 2.6, 2.3], 972), ('cosine curve time for height [0, 0, 2, 1, 0.25]', [0, 0, 2, 1, 0.25], 40)], [('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1]', [3.5, 5.1, 9.75, 1.2, 5.1], 210), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4]', [0, 0.6, 6.2, 4.4, 4.4], 372), ('cosine curve time for height [10, 2.0, 22.4, 2.6, 2.3]', [10, 2.0, 22.4, 2.6, 2.3], 972), ('cosine curve time for height [0, 0, 2, 1, 0.25]', [0, 0, 2, 1, 0.25], 40), ('cosine curve time for height [1.25, 1.0, 7.25, 3.0, 2.0]', [1.25, 1.0, 7.25, 3.0, 2.0], 255), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 0.6]', [0, 0.6, 6.2, 4.4, 0.6], 0), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 1.0]', [0, 0.6, 6.2, 4.4, 1.0], 78)]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| cosine curve time for height [0, 0.6, 6.2, 4.4, 0.6] | -186 | 0 | Failed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 1.0] | -108 | 78 | Failed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 2.5] | 0 | 186 | Failed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9] | 98 | 284 | Failed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4] | 186 | 372 | Failed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 4.5] | None | None | Passed |
| cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1] | 23 | 210 | Failed |
SHA-256 / f479f2aa8dc7f36358105c6e936243cdf8f7385f5cc1ddffcb0a90e2f7bf2509
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
t1,h1,t2,h2,h=x
lo,hi=min(h1,h2),max(h1,h2)
if h<lo or h>hi: return None
frac=(h-h1)/(h2-h1)
T=t2-t1
s=T*math.acos(1-2*frac)/math.pi
return math.floor((t1+s)*60+0.5)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('cosine curve time for height [0, 0.6, 6.2, 4.4, 0.6]', [0, 0.6, 6.2, 4.4, 0.6], 0), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 1.0]', [0, 0.6, 6.2, 4.4, 1.0], 78), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 2.5]', [0, 0.6, 6.2, 4.4, 2.5], 186), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9]', [0, 0.6, 6.2, 4.4, 3.9], 284), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4]', [0, 0.6, 6.2, 4.4, 4.4], 372), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.5]', [0, 0.6, 6.2, 4.4, 4.5], None), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1]', [3.5, 5.1, 9.75, 1.2, 5.1], 210)], [('cosine curve time for height [0, 0.6, 6.2, 4.4, 1.0]', [0, 0.6, 6.2, 4.4, 1.0], 78), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9]', [0, 0.6, 6.2, 4.4, 3.9], 284), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4]', [0, 0.6, 6.2, 4.4, 4.4], 372), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.5]', [0, 0.6, 6.2, 4.4, 4.5], None), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1]', [3.5, 5.1, 9.75, 1.2, 5.1], 210), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 4.0]', [3.5, 5.1, 9.75, 1.2, 4.0], 344), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 3.15]', [3.5, 5.1, 9.75, 1.2, 3.15], 398)], [('cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9]', [0, 0.6, 6.2, 4.4, 3.9], 284), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 2.5]', [0, 0.6, 6.2, 4.4, 2.5], 186), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1]', [3.5, 5.1, 9.75, 1.2, 5.1], 210), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 4.0]', [3.5, 5.1, 9.75, 1.2, 4.0], 344), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 3.15]', [3.5, 5.1, 9.75, 1.2, 3.15], 398), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 1.3]', [3.5, 5.1, 9.75, 1.2, 1.3], 547), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 1.2]', [3.5, 5.1, 9.75, 1.2, 1.2], 585)], [('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4]', [0, 0.6, 6.2, 4.4, 4.4], 372), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9]', [0, 0.6, 6.2, 4.4, 3.9], 284), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 1.3]', [3.5, 5.1, 9.75, 1.2, 1.3], 547), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 1.2]', [3.5, 5.1, 9.75, 1.2, 1.2], 585), ('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 0.9]', [3.5, 5.1, 9.75, 1.2, 0.9], None), ('cosine curve time for height [10, 2.0, 22.4, 2.6, 2.3]', [10, 2.0, 22.4, 2.6, 2.3], 972), ('cosine curve time for height [0, 0, 2, 1, 0.25]', [0, 0, 2, 1, 0.25], 40)], [('cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1]', [3.5, 5.1, 9.75, 1.2, 5.1], 210), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4]', [0, 0.6, 6.2, 4.4, 4.4], 372), ('cosine curve time for height [10, 2.0, 22.4, 2.6, 2.3]', [10, 2.0, 22.4, 2.6, 2.3], 972), ('cosine curve time for height [0, 0, 2, 1, 0.25]', [0, 0, 2, 1, 0.25], 40), ('cosine curve time for height [1.25, 1.0, 7.25, 3.0, 2.0]', [1.25, 1.0, 7.25, 3.0, 2.0], 255), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 0.6]', [0, 0.6, 6.2, 4.4, 0.6], 0), ('cosine curve time for height [0, 0.6, 6.2, 4.4, 1.0]', [0, 0.6, 6.2, 4.4, 1.0], 78)]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| cosine curve time for height [0, 0.6, 6.2, 4.4, 0.6] | 0 | 0 | Passed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 1.0] | 78 | 78 | Passed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 2.5] | 186 | 186 | Passed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 3.9] | 284 | 284 | Passed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 4.4] | 372 | 372 | Passed |
| cosine curve time for height [0, 0.6, 6.2, 4.4, 4.5] | None | None | Passed |
| cosine curve time for height [3.5, 5.1, 9.75, 1.2, 5.1] | 210 | 210 | Passed |
SHA-256 / 5b6fd93f09cbb873419c7ffd885dcdc508cfee29bd14d0eccef187c3974562da
Verification & scope
A deterministic toy model with stipulated rules and constants; not certified hydrographic software or a substitute for official tide tables. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:48:06.424294+00:00.
Case digest / f1663e59420d9816cb1936350a690c6d0cb97b80d23fb60a2d67d267c63e30da