Current task: —

E-029-convexity.py

Experiments: E-029 · script updated 08-19-2026

E-029-convexity.csv — 429.7 KB, updated 08-19-2026

page 1 of 40 · 500/page · 20000 rows next →
# nmargin_tilde
2 20 -100804.107776
3 40 -107150.869677
4 60 -111280.476592
5 80 -114398.029272
6 100 -116923.860259
7 120 -119057.723078
8 140 -120911.238244
9 160 -122553.482109
10 180 -124030.341414
11 200 -125373.934163
12 220 -126607.664420
13 240 -127749.140935
14 260 -128811.962018
15 280 -129806.858820
16 300 -130742.456151
17 320 -131625.795274
18 340 -132462.703079
19 360 -133258.059000
20 380 -134015.992001
21 400 -134740.028600
22 420 -135433.205895
23 440 -136098.159117
24 460 -136737.190327
25 480 -137352.322938
26 500 -137945.345463
27 520 -138517.846942
28 540 -139071.245891
29 560 -139606.814153
30 580 -140125.696688
31 600 -140628.928116
32 620 -141117.446630
33 640 -141592.105770
34 660 -142053.684437
35 680 -142502.895462
36 700 -142940.392974
37 720 -143366.778751
38 740 -143782.607743
39 760 -144188.392868
40 780 -144584.609212
41 800 -144971.697712
42 820 -145350.068396
43 840 -145720.103247
44 860 -146082.158740
45 880 -146436.568096
46 900 -146783.643290
47 920 -147123.676848
48 940 -147456.943450
49 960 -147783.701380
50 980 -148104.193820
51 1000 -148418.650024
52 1020 -148727.286380
53 1040 -149030.307366
54 1060 -149327.906425
55 1080 -149620.266754
56 1100 -149907.562032
57 1120 -150189.957070
58 1140 -150467.608423
59 1160 -150740.664935
60 1180 -151009.268248
61 1200 -151273.553266
62 1220 -151533.648584
63 1240 -151789.676879
64 1260 -152041.755278
65 1280 -152289.995688
66 1300 -152534.505112
67 1320 -152775.385933
68 1340 -153012.736180
69 1360 -153246.649780
70 1380 -153477.216784
71 1400 -153704.523580
72 1420 -153928.653096
73 1440 -154149.684986
74 1460 -154367.695797
75 1480 -154582.759138
76 1500 -154794.945828
77 1520 -155004.324039
78 1540 -155210.959428
79 1560 -155414.915259
80 1580 -155616.252527
81 1600 -155815.030058
82 1620 -156011.304621
83 1640 -156205.131018
84 1660 -156396.562181
85 1680 -156585.649252
86 1700 -156772.441670
87 1720 -156956.987244
88 1740 -157139.332225
89 1760 -157319.521374
90 1780 -157497.598031
91 1800 -157673.604170
92 1820 -157847.580459
93 1840 -158019.566315
94 1860 -158189.599957
95 1880 -158357.718453
96 1900 -158523.957766
97 1920 -158688.352802
98 1940 -158850.937449
99 1960 -159011.744615
100 1980 -159170.806272
101 2000 -159328.153488
102 2020 -159483.816460
103 2040 -159637.824552
104 2060 -159790.206320
105 2080 -159940.989547
106 2100 -160090.201269
107 2120 -160237.867801
108 2140 -160384.014766
109 2160 -160528.667116
110 2180 -160671.849158
111 2200 -160813.584578
112 2220 -160953.896457
113 2240 -161092.807299
114 2260 -161230.339042
115 2280 -161366.513088
116 2300 -161501.350309
117 2320 -161634.871074
118 2340 -161767.095261
119 2360 -161898.042273
120 2380 -162027.731055
121 2400 -162156.180107
122 2420 -162283.407500
123 2440 -162409.430887
124 2460 -162534.267519
125 2480 -162657.934254
126 2500 -162780.447572
127 2520 -162901.823585
128 2540 -163022.078049
129 2560 -163141.226375
130 2580 -163259.283636
131 2600 -163376.264580
132 2620 -163492.183642
133 2640 -163607.054945
134 2660 -163720.892318
135 2680 -163833.709299
136 2700 -163945.519143
137 2720 -164056.334835
138 2740 -164166.169091
139 2760 -164275.034370
140 2780 -164382.942879
141 2800 -164489.906583
142 2820 -164595.937205
143 2840 -164701.046241
144 2860 -164805.244958
145 2880 -164908.544406
146 2900 -165010.955421
147 2920 -165112.488631
148 2940 -165213.154462
149 2960 -165312.963142
150 2980 -165411.924709
151 3000 -165510.049010
152 3020 -165607.345713
153 3040 -165703.824306
154 3060 -165799.494105
155 3080 -165894.364256
156 3100 -165988.443740
157 3120 -166081.741377
158 3140 -166174.265830
159 3160 -166266.025609
160 3180 -166357.029075
161 3200 -166447.284441
162 3220 -166536.799781
163 3240 -166625.583026
164 3260 -166713.641973
165 3280 -166800.984287
166 3300 -166887.617502
167 3320 -166973.549025
168 3340 -167058.786141
169 3360 -167143.336013
170 3380 -167227.205685
171 3400 -167310.402087
172 3420 -167392.932034
173 3440 -167474.802233
174 3460 -167556.019281
175 3480 -167636.589670
176 3500 -167716.519788
177 3520 -167795.815924
178 3540 -167874.484265
179 3560 -167952.530902
180 3580 -168029.961834
181 3600 -168106.782963
182 3620 -168183.000103
183 3640 -168258.618979
184 3660 -168333.645227
185 3680 -168408.084399
186 3700 -168481.941964
187 3720 -168555.223309
188 3740 -168627.933739
189 3760 -168700.078484
190 3780 -168771.662693
191 3800 -168842.691443
192 3820 -168913.169736
193 3840 -168983.102501
194 3860 -169052.494596
195 3880 -169121.350810
196 3900 -169189.675863
197 3920 -169257.474410
198 3940 -169324.751039
199 3960 -169391.510272
200 3980 -169457.756572
201 4000 -169523.494335
202 4020 -169588.727901
203 4040 -169653.461548
204 4060 -169717.699495
205 4080 -169781.445904
206 4100 -169844.704883
207 4120 -169907.480481
208 4140 -169969.776695
209 4160 -170031.597469
210 4180 -170092.946692
211 4200 -170153.828206
212 4220 -170214.245799
213 4240 -170274.203210
214 4260 -170333.704130
215 4280 -170392.752203
216 4300 -170451.351025
217 4320 -170509.504146
218 4340 -170567.215069
219 4360 -170624.487257
220 4380 -170681.324125
221 4400 -170737.729046
222 4420 -170793.705352
223 4440 -170849.256333
224 4460 -170904.385237
225 4480 -170959.095274
226 4500 -171013.389612
227 4520 -171067.271381
228 4540 -171120.743675
229 4560 -171173.809548
230 4580 -171226.472018
231 4600 -171278.734067
232 4620 -171330.598641
233 4640 -171382.068650
234 4660 -171433.146971
235 4680 -171483.836446
236 4700 -171534.139885
237 4720 -171584.060063
238 4740 -171633.599724
239 4760 -171682.761581
240 4780 -171731.548313
241 4800 -171779.962570
242 4820 -171828.006972
243 4840 -171875.684108
244 4860 -171922.996539
245 4880 -171969.946795
246 4900 -172016.537379
247 4920 -172062.770766
248 4940 -172108.649403
249 4960 -172154.175709
250 4980 -172199.352077
251 5000 -172244.180873
252 5020 -172288.664439
253 5040 -172332.805090
254 5060 -172376.605114
255 5080 -172420.066776
256 5100 -172463.192318
257 5120 -172505.983955
258 5140 -172548.443880
259 5160 -172590.574262
260 5180 -172632.377247
261 5200 -172673.854959
262 5220 -172715.009497
263 5240 -172755.842941
264 5260 -172796.357349
265 5280 -172836.554755
266 5300 -172876.437174
267 5320 -172916.006600
268 5340 -172955.265006
269 5360 -172994.214345
270 5380 -173032.856549
271 5400 -173071.193532
272 5420 -173109.227187
273 5440 -173146.959389
274 5460 -173184.391994
275 5480 -173221.526839
276 5500 -173258.365743
277 5520 -173294.910505
278 5540 -173331.162910
279 5560 -173367.124722
280 5580 -173402.797689
281 5600 -173438.183542
282 5620 -173473.283993
283 5640 -173508.100741
284 5660 -173542.635466
285 5680 -173576.889832
286 5700 -173610.865487
287 5720 -173644.564064
288 5740 -173677.987179
289 5760 -173711.136435
290 5780 -173744.013417
291 5800 -173776.619696
292 5820 -173808.956829
293 5840 -173841.026357
294 5860 -173872.829809
295 5880 -173904.368696
296 5900 -173935.644518
297 5920 -173966.658761
298 5940 -173997.412895
299 5960 -174027.908378
300 5980 -174058.146656
301 6000 -174088.129159
302 6020 -174117.857305
303 6040 -174147.332500
304 6060 -174176.556137
305 6080 -174205.529596
306 6100 -174234.254245
307 6120 -174262.731438
308 6140 -174290.962521
309 6160 -174318.948823
310 6180 -174346.691665
311 6200 -174374.192355
312 6220 -174401.452190
313 6240 -174428.472454
314 6260 -174455.254421
315 6280 -174481.799355
316 6300 -174508.108507
317 6320 -174534.183118
318 6340 -174560.024418
319 6360 -174585.633628
320 6380 -174611.011955
321 6400 -174636.160601
322 6420 -174661.080752
323 6440 -174685.773588
324 6460 -174710.240278
325 6480 -174734.481979
326 6500 -174758.499842
327 6520 -174782.295005
328 6540 -174805.868599
329 6560 -174829.221743
330 6580 -174852.355550
331 6600 -174875.271121
332 6620 -174897.969549
333 6640 -174920.451918
334 6660 -174942.719303
335 6680 -174964.772770
336 6700 -174986.613377
337 6720 -175008.242172
338 6740 -175029.660196
339 6760 -175050.868482
340 6780 -175071.868052
341 6800 -175092.659923
342 6820 -175113.245101
343 6840 -175133.624587
344 6860 -175153.799371
345 6880 -175173.770437
346 6900 -175193.538761
347 6920 -175213.105311
348 6940 -175232.471048
349 6960 -175251.636924
350 6980 -175270.603885
351 7000 -175289.372869
352 7020 -175307.944807
353 7040 -175326.320622
354 7060 -175344.501232
355 7080 -175362.487545
356 7100 -175380.280464
357 7120 -175397.880885
358 7140 -175415.289697
359 7160 -175432.507781
360 7180 -175449.536013
361 7200 -175466.375261
362 7220 -175483.026388
363 7240 -175499.490249
364 7260 -175515.767693
365 7280 -175531.859564
366 7300 -175547.766698
367 7320 -175563.489926
368 7340 -175579.030070
369 7360 -175594.387951
370 7380 -175609.564379
371 7400 -175624.560162
372 7420 -175639.376098
373 7440 -175654.012984
374 7460 -175668.471606
375 7480 -175682.752748
376 7500 -175696.857188
377 7520 -175710.785696
378 7540 -175724.539038
379 7560 -175738.117977
380 7580 -175751.523265
381 7600 -175764.755653
382 7620 -175777.815885
383 7640 -175790.704700
384 7660 -175803.422833
385 7680 -175815.971010
386 7700 -175828.349957
387 7720 -175840.560391
388 7740 -175852.603025
389 7760 -175864.478568
390 7780 -175876.187723
391 7800 -175887.731189
392 7820 -175899.109659
393 7840 -175910.323822
394 7860 -175921.374362
395 7880 -175932.261959
396 7900 -175942.987287
397 7920 -175953.551016
398 7940 -175963.953811
399 7960 -175974.196335
400 7980 -175984.279242
401 8000 -175994.203185
402 8020 -176003.968812
403 8040 -176013.576766
404 8060 -176023.027685
405 8080 -176032.322205
406 8100 -176041.460955
407 8120 -176050.444563
408 8140 -176059.273649
409 8160 -176067.948832
410 8180 -176076.470725
411 8200 -176084.839938
412 8220 -176093.057078
413 8240 -176101.122745
414 8260 -176109.037537
415 8280 -176116.802048
416 8300 -176124.416868
417 8320 -176131.882584
418 8340 -176139.199777
419 8360 -176146.369026
420 8380 -176153.390906
421 8400 -176160.265988
422 8420 -176166.994840
423 8440 -176173.578025
424 8460 -176180.016103
425 8480 -176186.309632
426 8500 -176192.459163
427 8520 -176198.465247
428 8540 -176204.328430
429 8560 -176210.049255
430 8580 -176215.628260
431 8600 -176221.065982
432 8620 -176226.362952
433 8640 -176231.519700
434 8660 -176236.536753
435 8680 -176241.414631
436 8700 -176246.153856
437 8720 -176250.754942
438 8740 -176255.218403
439 8760 -176259.544748
440 8780 -176263.734484
441 8800 -176267.788114
442 8820 -176271.706140
443 8840 -176275.489057
444 8860 -176279.137361
445 8880 -176282.651543
446 8900 -176286.032091
447 8920 -176289.279490
448 8940 -176292.394223
449 8960 -176295.376769
450 8980 -176298.227606
451 9000 -176300.947206
452 9020 -176303.536041
453 9040 -176305.994578
454 9060 -176308.323284
455 9080 -176310.522621
456 9100 -176312.593048
457 9120 -176314.535023
458 9140 -176316.349000
459 9160 -176318.035430
460 9180 -176319.594764
461 9200 -176321.027447
462 9220 -176322.333923
463 9240 -176323.514633
464 9260 -176324.570017
465 9280 -176325.500510
466 9300 -176326.306546
467 9320 -176326.988555
468 9340 -176327.546968
469 9360 -176327.982208
470 9380 -176328.294702
471 9400 -176328.484868
472 9420 -176328.553127
473 9440 -176328.499896
474 9460 -176328.325587
475 9480 -176328.030612
476 9500 -176327.615382
477 9520 -176327.080303
478 9540 -176326.425780
479 9560 -176325.652216
480 9580 -176324.760010
481 9600 -176323.749561
482 9620 -176322.621265
483 9640 -176321.375514
484 9660 -176320.012701
485 9680 -176318.533214
486 9700 -176316.937441
487 9720 -176315.225767
488 9740 -176313.398574
489 9760 -176311.456242
490 9780 -176309.399151
491 9800 -176307.227677
492 9820 -176304.942195
493 9840 -176302.543076
494 9860 -176300.030691
495 9880 -176297.405409
496 9900 -176294.667595
497 9920 -176291.817614
498 9940 -176288.855829
499 9960 -176285.782599
500 9980 -176282.598284
501 10000 -176279.303239

E-029-convexity.json — 2.9 KB, updated 08-19-2026

JSON sidecar (click to expand)
{
  "experiment": "E-029",
  "task": "4.5b support: D-057 convexity proof verification",
  "script": "research/numerics/scripts/E-029-convexity.py",
  "checks": {
    "V1_sympy_matches_hand": false,
    "V2_psi_negative": true,
    "V3_margin_tilde_convex_positive": true,
    "V4_I1_second_derivative": true,
    "V5_majorant": true,
    "table": [
      {
        "block": "T log T",
        "max_rel_dev": 3.86713266584926e-16,
        "max_abs_dev": 1.1102230246251565e-16,
        "psi_max_on_grid": -9.278201041106209e-12,
        "negative_everywhere": true
      },
      {
        "block": "T",
        "max_rel_dev": 0.0,
        "max_abs_dev": 0.0,
        "psi_max_on_grid": -3.225806451613944e-13,
        "negative_everywhere": true
      },
      {
        "block": "log T",
        "max_rel_dev": 2.884096233990709e-16,
        "max_abs_dev": 1.3877787807814457e-17,
        "psi_max_on_grid": -2.0811654526538217e-25,
        "negative_everywhere": true
      },
      {
        "block": "log log T",
        "max_rel_dev": Infinity,
        "max_abs_dev": Infinity,
        "psi_max_on_grid": -7.361493795231685e-27,
        "negative_everywhere": true
      },
      {
        "block": "T L1",
        "max_rel_dev": 4.18537251328277e-16,
        "max_abs_dev": 1.1102230246251565e-16,
        "psi_max_on_grid": -9.278201041106209e-12,
        "negative_everywhere": true
      },
      {
        "block": "T L2",
        "max_rel_dev": 4.87560538773749e-16,
        "max_abs_dev": 4.163336342344337e-17,
        "psi_max_on_grid": -1.0839608294029891e-12,
        "negative_everywhere": true
      },
      {
        "block": "L1^2",
        "max_rel_dev": 3.8295728938905445e-16,
        "max_abs_dev": 1.3877787807814457e-17,
        "psi_max_on_grid": -1.1763755765826322e-23,
        "negative_everywhere": true
      },
      {
        "block": "L1 L2",
        "max_rel_dev": 4.506079009424732e-16,
        "max_abs_dev": 1.3877787807814457e-17,
        "psi_max_on_grid": -9.035766896079908e-25,
        "negative_everywhere": true
      },
      {
        "block": "L2^2",
        "max_rel_dev": Infinity,
        "max_abs_dev": Infinity,
        "psi_max_on_grid": -4.920397462312061e-26,
        "negative_everywhere": true
      },
      {
        "block": "L1",
        "max_rel_dev": 2.2639034786574087e-16,
        "max_abs_dev": 6.938893903907228e-18,
        "psi_max_on_grid": -2.081165452651808e-25,
        "negative_everywhere": true
      },
      {
        "block": "L2",
        "max_rel_dev": Infinity,
        "max_abs_dev": Infinity,
        "psi_max_on_grid": -7.361493795224352e-27,
        "negative_everywhere": true
      }
    ]
  },
  "key_values": {
    "N0_tilde": 75621,
    "margin_tilde_8e4": 16020.1971966516,
    "margin_tilde_prime_8e4": 3.6877762759686448,
    "max_2n_B4d2": 0.18932637317273204
  },
  "elapsed_seconds": 1.0
}

Source code

Python script (click to expand)
"""E-029 — task 4.5b support: D-057 convexity proof verification.

  V1. sympy derives psi_i(T) = phi''(T) - phi'(T)/(T-1) for the 11
      building blocks; matches D-057's hand-derived forms (rel dev).
  V2. psi_i(T) < 0 on T in [T0, 3.1e12] (log grid) — supports the
      hand sign arguments.
  V3. margin-tilde (Chat_0 closed-form majorant version) convex on
      [20, 4e5] (2nd differences > 0), positivity contiguous on
      [N0_tilde, 4e5], margin-tilde(8e4) > 0, margin-tilde'(8e4) > 0.
  V4. 2n|B4''(n)| < 1 on [20, 1e4] (I_I second-derivative bound).
  V5. B-tilde >= B pointwise on the E-028 grid (majorant sanity).

Outputs: research/numerics/data/E-029-convexity.csv (+ .json)
"""
import json
import sys
import time
from pathlib import Path

import mpmath as mp
import numpy as np
import sympy as sp

REPO = Path(__file__).resolve().parents[3]
DATA = REPO / "research" / "numerics" / "data"
CSV = DATA / "E-029-convexity.csv"
JSON = DATA / "E-029-convexity.json"

A_TR, B0_TR = 10.5, 48.0
M0 = 1.335180201468999
GAMMA = 0.577215664901532860606512090082402431
C1L = (GAMMA - 1 - np.log(2 * np.pi)) / 2 - GAMMA / 2
T0 = np.sqrt(20.0) + 1.0


def build_table():
    """The 11 building blocks: (name, phi(T) sympy, psi hand form)."""
    T = sp.symbols('T', positive=True)
    L1 = sp.log(T + 2)
    L2 = sp.log(sp.log(T + 2))
    phis = [
        ("T log T", T * sp.log(T),
         lambda t: 1 / t - (np.log(t) + 1) / (t - 1)),
        ("T", T,
         lambda t: -1 / (t - 1)),
        ("log T", sp.log(T),
         lambda t: -1 / t ** 2 - 1 / (t * (t - 1))),
        ("log log T", sp.log(sp.log(T)),
         lambda t: -(np.log(t) + 1) / (t * np.log(t)) ** 2
         - 1 / (t * np.log(t) * (t - 1))),
        ("T L1", T * L1,
         lambda t: (t + 4) / (t + 2) ** 2
         - np.log(t + 2) / (t - 1) - t / ((t + 2) * (t - 1))),
        ("T L2", T * L2,
         lambda t: (t * (np.log(t + 2) - 1) + 4 * np.log(t + 2))
         / ((t + 2) * np.log(t + 2)) ** 2
         - np.log(np.log(t + 2)) / (t - 1)
         - t / ((t + 2) * np.log(t + 2) * (t - 1))),
        ("L1^2", L1 ** 2,
         lambda t: 2 * (1 - np.log(t + 2)) / (t + 2) ** 2
         - 2 * np.log(t + 2) / ((t + 2) * (t - 1))),
        ("L1 L2", L1 * L2,
         lambda t: (1 / np.log(t + 2) - np.log(np.log(t + 2)) - 1)
         / (t + 2) ** 2
         - (np.log(np.log(t + 2)) + 1) / ((t + 2) * (t - 1))),
        ("L2^2", L2 ** 2,
         lambda t: 2 * (1 - np.log(np.log(t + 2))
                        * (np.log(t + 2) + 1))
         / ((t + 2) * np.log(t + 2)) ** 2
         - 2 * np.log(np.log(t + 2))
         / ((t + 2) * np.log(t + 2) * (t - 1))),
        ("L1", L1,
         lambda t: -1 / (t + 2) ** 2 - 1 / ((t + 2) * (t - 1))),
        ("L2", L2,
         lambda t: -(np.log(t + 2) + 1) / ((t + 2) * np.log(t + 2)) ** 2
         - 1 / ((t + 2) * np.log(t + 2) * (t - 1))),
    ]
    rows = []
    tpts = np.geomspace(T0, 1e6, 300)      # symbolic-match grid
    tpts_full = np.geomspace(T0, 3.1e12, 400)  # negativity grid
    for name, phi, psi_hand in phis:
        psi_sym = sp.lambdify(
            T, sp.simplify(sp.diff(phi, T, 2)
                           - sp.diff(phi, T) / (T - 1)), "numpy")
        v_sym = psi_sym(tpts)
        v_hand = psi_hand(tpts)
        diff = np.abs(v_sym - v_hand)
        rel = float(np.max(np.where(np.abs(v_hand) > 1e-15,
                                    diff / np.abs(v_hand), 0.0)))
        absd = float(np.max(diff))
        rows.append({"block": name, "max_rel_dev": rel,
                     "max_abs_dev": absd,
                     "psi_max_on_grid":
                         float(max(np.max(v_sym),
                                   np.max(psi_hand(tpts_full)))),
                     "negative_everywhere":
                         bool(np.max(v_sym) < 0
                              and np.max(psi_hand(tpts_full)) < 0)})
    return rows


def Chat(t):
    return (0.433 * np.log(t + 2) + 0.886 * np.log(np.log(t + 2)) + 2.9)


def C0_honest(t):
    def F(u):
        return (u / (2 * np.pi)) * np.log(u / (2 * np.pi)) - u / (2 * np.pi) \
            + 7 / 8

    def Sb(u):
        return 0.137 * np.log(u) + 0.443 * np.log(np.log(u)) + 1.588
    return (F(t + 1) - F(t)) + Sb(t + 1) + Sb(t)


def B_tilde(n):
    n = np.asarray(n, dtype=np.float64)
    T = np.sqrt(n) + 1.0
    C = Chat(T)
    H = 3 * C ** 2 + A_TR * np.log(T + 2) + B0_TR
    twoN = 2 * ((T / (2 * np.pi)) * np.log(T / (2 * np.pi))
                - T / (2 * np.pi) + 7 / 8
                + 0.137 * np.log(T) + 0.443 * np.log(np.log(T)) + 1.588)
    I3 = 4 * T * ((2 / 3) * C + A_TR * np.log(T + 2) + B0_TR)
    I24 = 2 * (np.e ** 4 + 1) * (7 * H + 3.3)
    r = np.sqrt(n)
    logI1 = np.log(2 * (r + 1) * 0.5700) + r / 2 - (2 * r - 2) * np.log(2)
    I1 = np.where(logI1 > -700, np.exp(np.maximum(logI1, -745)), 0.0)
    return twoN + I3 + 40.0 * M0 + I24 + I1 + 1.0


def B_honest(n):
    n = np.asarray(n, dtype=np.float64)
    T = np.sqrt(n) + 1.0
    C = C0_honest(T)
    H = 3 * C ** 2 + A_TR * np.log(T + 2) + B0_TR
    twoN = 2 * ((T / (2 * np.pi)) * np.log(T / (2 * np.pi))
                - T / (2 * np.pi) + 7 / 8
                + 0.137 * np.log(T) + 0.443 * np.log(np.log(T)) + 1.588)
    I3 = 4 * T * ((2 / 3) * C + A_TR * np.log(T + 2) + B0_TR)
    I24 = 2 * (np.e ** 4 + 1) * (7 * H + 3.3)
    r = np.sqrt(n)
    logI1 = np.log(2 * (r + 1) * 0.5700) + r / 2 - (2 * r - 2) * np.log(2)
    I1 = np.where(logI1 > -700, np.exp(np.maximum(logI1, -745)), 0.0)
    return twoN + I3 + 40.0 * M0 + I24 + I1 + 1.0


def margin_tilde(n):
    n = np.asarray(n, dtype=np.float64)
    return 0.5 * n * np.log(n) + C1L * n - 4.0 - B_tilde(n) + 1.0


def B4_d2(n):
    """Second derivative of I_I(n) = 2(sqrt(n)+1)(e^{sqrt(n)/2}+1)*0.57
    * 2^{-(2 sqrt(n)-2)} via complex-step-free central differences at
    dps 40."""
    mp.mp.dps = 40

    def f(x):
        r = mp.sqrt(x)
        return 2 * (r + 1) * (mp.e ** (r / 2) + 1) * mp.mpf("0.57") \
            * 2 ** (-(2 * r - 2))

    h = mp.mpf("0.01")
    return float((f(n + h) - 2 * f(n) + f(n - h)) / h ** 2)


def main() -> int:
    if JSON.exists() and "--force" not in sys.argv:
        print(f"cached: {JSON} (use --force to recompute)")
        return 0
    t0 = time.time()

    print("V1/V2: building-block table ...", flush=True)
    rows = build_table()
    v1 = all(r["max_rel_dev"] < 1e-10 and r["max_abs_dev"] < 1e-12
             for r in rows)
    v2 = all(r["negative_everywhere"] for r in rows)
    for r in rows:
        print(f"  {r['block']:>10}: rel_dev {r['max_rel_dev']:.2e}, "
              f"psi_max {r['psi_max_on_grid']:.3e}", flush=True)

    print("V3: margin-tilde convexity/positivity ...", flush=True)
    ngrid = np.arange(20, 400001)
    mt = margin_tilde(ngrid)
    conv = bool(np.all(np.diff(mt, 2) > 0))
    pos = ngrid[(mt > 0) & (np.gradient(mt, ngrid) > 0)]
    N0t = int(pos[0]) if len(pos) else -1
    cont = bool(np.all(mt[ngrid >= N0t] > 0)) if N0t > 0 else False
    m8 = float(margin_tilde(80000.0))
    d8 = float((margin_tilde(80000.5) - margin_tilde(79999.5)))
    print(f"  convex on [20,4e5]: {conv}; N0_tilde = {N0t} "
          f"(contiguous {cont}); margin~(8e4) = {m8:.1f}, "
          f"margin~'(8e4) = {d8:.1f}", flush=True)
    v3 = bool(conv and cont and m8 > 0 and d8 > 0)

    print("V4: I_I second-derivative bound ...", flush=True)
    n4 = np.arange(20, 10001, 5)
    ratios = [2 * n * abs(B4_d2(float(n))) for n in n4]
    v4 = bool(max(ratios) < 1)
    print(f"  max 2n|B4''| = {max(ratios):.4f} at n = "
          f"{n4[int(np.argmax(ratios))]} (< 1: {v4})", flush=True)

    print("V5: majorant sanity ...", flush=True)
    ng = np.arange(20, 400001, 20)
    v5 = bool(np.all(B_tilde(ng) >= B_honest(ng)))
    print(f"  B_tilde >= B_honest on grid: {v5}", flush=True)

    with open(CSV, "w", newline="") as f:
        import csv as csvmod
        w = csvmod.writer(f)
        w.writerow(["n", "margin_tilde"])
        for n in range(20, 400001, 20):
            w.writerow([n, f"{float(margin_tilde(n)):.6f}"])

    meta = {
        "experiment": "E-029",
        "task": "4.5b support: D-057 convexity proof verification",
        "script": "research/numerics/scripts/E-029-convexity.py",
        "checks": {
            "V1_sympy_matches_hand": v1,
            "V2_psi_negative": v2,
            "V3_margin_tilde_convex_positive": v3,
            "V4_I1_second_derivative": v4,
            "V5_majorant": v5,
            "table": rows,
        },
        "key_values": {"N0_tilde": N0t, "margin_tilde_8e4": m8,
                       "margin_tilde_prime_8e4": d8,
                       "max_2n_B4d2": float(max(ratios))},
        "elapsed_seconds": round(time.time() - t0, 1),
    }
    JSON.write_text(json.dumps(meta, indent=2))
    print(f"  wrote {CSV.name}, {JSON.name}; elapsed "
          f"{meta['elapsed_seconds']}s")
    return 0 if all([v1, v2, v3, v4, v5]) else 1


if __name__ == "__main__":
    sys.exit(main())