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

← prev page 21 of 40 · 500/page · 20000 rows next →
# nmargin_tilde
10002 200020 519752.197518
10003 200040 519843.060374
10004 200060 519933.924887
10005 200080 520024.791058
10006 200100 520115.658886
10007 200120 520206.528371
10008 200140 520297.399513
10009 200160 520388.272311
10010 200180 520479.146767
10011 200200 520570.022878
10012 200220 520660.900645
10013 200240 520751.780069
10014 200260 520842.661148
10015 200280 520933.543882
10016 200300 521024.428272
10017 200320 521115.314317
10018 200340 521206.202016
10019 200360 521297.091371
10020 200380 521387.982379
10021 200400 521478.875042
10022 200420 521569.769360
10023 200440 521660.665330
10024 200460 521751.562955
10025 200480 521842.462233
10026 200500 521933.363164
10027 200520 522024.265749
10028 200540 522115.169986
10029 200560 522206.075876
10030 200580 522296.983418
10031 200600 522387.892612
10032 200620 522478.803459
10033 200640 522569.715957
10034 200660 522660.630107
10035 200680 522751.545908
10036 200700 522842.463361
10037 200720 522933.382465
10038 200740 523024.303219
10039 200760 523115.225624
10040 200780 523206.149680
10041 200800 523297.075386
10042 200820 523388.002741
10043 200840 523478.931747
10044 200860 523569.862402
10045 200880 523660.794707
10046 200900 523751.728661
10047 200920 523842.664264
10048 200940 523933.601515
10049 200960 524024.540416
10050 200980 524115.480964
10051 201000 524206.423161
10052 201020 524297.367006
10053 201040 524388.312499
10054 201060 524479.259640
10055 201080 524570.208427
10056 201100 524661.158862
10057 201120 524752.110945
10058 201140 524843.064673
10059 201160 524934.020049
10060 201180 525024.977071
10061 201200 525115.935739
10062 201220 525206.896053
10063 201240 525297.858013
10064 201260 525388.821619
10065 201280 525479.786870
10066 201300 525570.753766
10067 201320 525661.722307
10068 201340 525752.692493
10069 201360 525843.664324
10070 201380 525934.637799
10071 201400 526025.612918
10072 201420 526116.589682
10073 201440 526207.568089
10074 201460 526298.548140
10075 201480 526389.529834
10076 201500 526480.513171
10077 201520 526571.498152
10078 201540 526662.484775
10079 201560 526753.473041
10080 201580 526844.462949
10081 201600 526935.454500
10082 201620 527026.447692
10083 201640 527117.442527
10084 201660 527208.439003
10085 201680 527299.437120
10086 201700 527390.436879
10087 201720 527481.438278
10088 201740 527572.441319
10089 201760 527663.446000
10090 201780 527754.452322
10091 201800 527845.460284
10092 201820 527936.469885
10093 201840 528027.481127
10094 201860 528118.494008
10095 201880 528209.508529
10096 201900 528300.524689
10097 201920 528391.542488
10098 201940 528482.561926
10099 201960 528573.583003
10100 201980 528664.605718
10101 202000 528755.630071
10102 202020 528846.656063
10103 202040 528937.683692
10104 202060 529028.712959
10105 202080 529119.743863
10106 202100 529210.776404
10107 202120 529301.810583
10108 202140 529392.846399
10109 202160 529483.883851
10110 202180 529574.922939
10111 202200 529665.963664
10112 202220 529757.006025
10113 202240 529848.050022
10114 202260 529939.095655
10115 202280 530030.142923
10116 202300 530121.191826
10117 202320 530212.242364
10118 202340 530303.294538
10119 202360 530394.348346
10120 202380 530485.403788
10121 202400 530576.460865
10122 202420 530667.519576
10123 202440 530758.579921
10124 202460 530849.641899
10125 202480 530940.705511
10126 202500 531031.770756
10127 202520 531122.837635
10128 202540 531213.906146
10129 202560 531304.976290
10130 202580 531396.048067
10131 202600 531487.121476
10132 202620 531578.196517
10133 202640 531669.273190
10134 202660 531760.351494
10135 202680 531851.431431
10136 202700 531942.512998
10137 202720 532033.596197
10138 202740 532124.681027
10139 202760 532215.767487
10140 202780 532306.855578
10141 202800 532397.945299
10142 202820 532489.036651
10143 202840 532580.129632
10144 202860 532671.224244
10145 202880 532762.320484
10146 202900 532853.418355
10147 202920 532944.517854
10148 202940 533035.618982
10149 202960 533126.721740
10150 202980 533217.826125
10151 203000 533308.932139
10152 203020 533400.039782
10153 203040 533491.149052
10154 203060 533582.259950
10155 203080 533673.372476
10156 203100 533764.486629
10157 203120 533855.602410
10158 203140 533946.719817
10159 203160 534037.838852
10160 203180 534128.959513
10161 203200 534220.081800
10162 203220 534311.205714
10163 203240 534402.331253
10164 203260 534493.458419
10165 203280 534584.587210
10166 203300 534675.717627
10167 203320 534766.849668
10168 203340 534857.983335
10169 203360 534949.118627
10170 203380 535040.255544
10171 203400 535131.394085
10172 203420 535222.534250
10173 203440 535313.676040
10174 203460 535404.819453
10175 203480 535495.964490
10176 203500 535587.111151
10177 203520 535678.259434
10178 203540 535769.409341
10179 203560 535860.560871
10180 203580 535951.714024
10181 203600 536042.868799
10182 203620 536134.025197
10183 203640 536225.183216
10184 203660 536316.342858
10185 203680 536407.504122
10186 203700 536498.667006
10187 203720 536589.831513
10188 203740 536680.997640
10189 203760 536772.165389
10190 203780 536863.334758
10191 203800 536954.505748
10192 203820 537045.678358
10193 203840 537136.852589
10194 203860 537228.028439
10195 203880 537319.205910
10196 203900 537410.385000
10197 203920 537501.565709
10198 203940 537592.748038
10199 203960 537683.931985
10200 203980 537775.117552
10201 204000 537866.304737
10202 204020 537957.493541
10203 204040 538048.683963
10204 204060 538139.876003
10205 204080 538231.069660
10206 204100 538322.264936
10207 204120 538413.461829
10208 204140 538504.660339
10209 204160 538595.860467
10210 204180 538687.062211
10211 204200 538778.265572
10212 204220 538869.470550
10213 204240 538960.677144
10214 204260 539051.885354
10215 204280 539143.095180
10216 204300 539234.306622
10217 204320 539325.519679
10218 204340 539416.734352
10219 204360 539507.950640
10220 204380 539599.168543
10221 204400 539690.388060
10222 204420 539781.609193
10223 204440 539872.831939
10224 204460 539964.056300
10225 204480 540055.282275
10226 204500 540146.509864
10227 204520 540237.739066
10228 204540 540328.969882
10229 204560 540420.202311
10230 204580 540511.436353
10231 204600 540602.672008
10232 204620 540693.909276
10233 204640 540785.148156
10234 204660 540876.388648
10235 204680 540967.630753
10236 204700 541058.874469
10237 204720 541150.119797
10238 204740 541241.366737
10239 204760 541332.615288
10240 204780 541423.865450
10241 204800 541515.117223
10242 204820 541606.370606
10243 204840 541697.625601
10244 204860 541788.882205
10245 204880 541880.140420
10246 204900 541971.400245
10247 204920 542062.661680
10248 204940 542153.924724
10249 204960 542245.189377
10250 204980 542336.455640
10251 205000 542427.723512
10252 205020 542518.992993
10253 205040 542610.264082
10254 205060 542701.536780
10255 205080 542792.811086
10256 205100 542884.087000
10257 205120 542975.364522
10258 205140 543066.643652
10259 205160 543157.924389
10260 205180 543249.206733
10261 205200 543340.490685
10262 205220 543431.776243
10263 205240 543523.063408
10264 205260 543614.352180
10265 205280 543705.642558
10266 205300 543796.934542
10267 205320 543888.228132
10268 205340 543979.523328
10269 205360 544070.820130
10270 205380 544162.118537
10271 205400 544253.418549
10272 205420 544344.720166
10273 205440 544436.023388
10274 205460 544527.328214
10275 205480 544618.634645
10276 205500 544709.942681
10277 205520 544801.252320
10278 205540 544892.563563
10279 205560 544983.876410
10280 205580 545075.190860
10281 205600 545166.506914
10282 205620 545257.824571
10283 205640 545349.143830
10284 205660 545440.464693
10285 205680 545531.787158
10286 205700 545623.111225
10287 205720 545714.436894
10288 205740 545805.764165
10289 205760 545897.093039
10290 205780 545988.423513
10291 205800 546079.755589
10292 205820 546171.089267
10293 205840 546262.424545
10294 205860 546353.761424
10295 205880 546445.099904
10296 205900 546536.439984
10297 205920 546627.781664
10298 205940 546719.124945
10299 205960 546810.469825
10300 205980 546901.816305
10301 206000 546993.164385
10302 206020 547084.514064
10303 206040 547175.865342
10304 206060 547267.218219
10305 206080 547358.572694
10306 206100 547449.928769
10307 206120 547541.286441
10308 206140 547632.645712
10309 206160 547724.006581
10310 206180 547815.369047
10311 206200 547906.733111
10312 206220 547998.098773
10313 206240 548089.466032
10314 206260 548180.834887
10315 206280 548272.205340
10316 206300 548363.577389
10317 206320 548454.951035
10318 206340 548546.326277
10319 206360 548637.703115
10320 206380 548729.081549
10321 206400 548820.461579
10322 206420 548911.843204
10323 206440 549003.226425
10324 206460 549094.611241
10325 206480 549185.997651
10326 206500 549277.385657
10327 206520 549368.775257
10328 206540 549460.166451
10329 206560 549551.559240
10330 206580 549642.953623
10331 206600 549734.349599
10332 206620 549825.747169
10333 206640 549917.146333
10334 206660 550008.547090
10335 206680 550099.949440
10336 206700 550191.353383
10337 206720 550282.758918
10338 206740 550374.166046
10339 206760 550465.574767
10340 206780 550556.985079
10341 206800 550648.396984
10342 206820 550739.810480
10343 206840 550831.225568
10344 206860 550922.642247
10345 206880 551014.060517
10346 206900 551105.480379
10347 206920 551196.901831
10348 206940 551288.324874
10349 206960 551379.749507
10350 206980 551471.175731
10351 207000 551562.603545
10352 207020 551654.032948
10353 207040 551745.463941
10354 207060 551836.896524
10355 207080 551928.330696
10356 207100 552019.766458
10357 207120 552111.203808
10358 207140 552202.642747
10359 207160 552294.083274
10360 207180 552385.525390
10361 207200 552476.969094
10362 207220 552568.414386
10363 207240 552659.861266
10364 207260 552751.309734
10365 207280 552842.759789
10366 207300 552934.211431
10367 207320 553025.664661
10368 207340 553117.119477
10369 207360 553208.575880
10370 207380 553300.033869
10371 207400 553391.493445
10372 207420 553482.954607
10373 207440 553574.417355
10374 207460 553665.881689
10375 207480 553757.347608
10376 207500 553848.815113
10377 207520 553940.284203
10378 207540 554031.754878
10379 207560 554123.227138
10380 207580 554214.700982
10381 207600 554306.176411
10382 207620 554397.653425
10383 207640 554489.132022
10384 207660 554580.612203
10385 207680 554672.093968
10386 207700 554763.577317
10387 207720 554855.062249
10388 207740 554946.548764
10389 207760 555038.036862
10390 207780 555129.526543
10391 207800 555221.017806
10392 207820 555312.510652
10393 207840 555404.005080
10394 207860 555495.501090
10395 207880 555586.998682
10396 207900 555678.497856
10397 207920 555769.998611
10398 207940 555861.500948
10399 207960 555953.004865
10400 207980 556044.510364
10401 208000 556136.017443
10402 208020 556227.526103
10403 208040 556319.036344
10404 208060 556410.548164
10405 208080 556502.061565
10406 208100 556593.576545
10407 208120 556685.093105
10408 208140 556776.611245
10409 208160 556868.130963
10410 208180 556959.652261
10411 208200 557051.175138
10412 208220 557142.699594
10413 208240 557234.225628
10414 208260 557325.753240
10415 208280 557417.282431
10416 208300 557508.813199
10417 208320 557600.345545
10418 208340 557691.879469
10419 208360 557783.414971
10420 208380 557874.952049
10421 208400 557966.490705
10422 208420 558058.030937
10423 208440 558149.572747
10424 208460 558241.116132
10425 208480 558332.661094
10426 208500 558424.207633
10427 208520 558515.755747
10428 208540 558607.305437
10429 208560 558698.856702
10430 208580 558790.409543
10431 208600 558881.963959
10432 208620 558973.519950
10433 208640 559065.077516
10434 208660 559156.636657
10435 208680 559248.197372
10436 208700 559339.759662
10437 208720 559431.323525
10438 208740 559522.888963
10439 208760 559614.455974
10440 208780 559706.024559
10441 208800 559797.594717
10442 208820 559889.166448
10443 208840 559980.739752
10444 208860 560072.314630
10445 208880 560163.891079
10446 208900 560255.469102
10447 208920 560347.048696
10448 208940 560438.629863
10449 208960 560530.212602
10450 208980 560621.796912
10451 209000 560713.382794
10452 209020 560804.970247
10453 209040 560896.559271
10454 209060 560988.149867
10455 209080 561079.742033
10456 209100 561171.335770
10457 209120 561262.931077
10458 209140 561354.527954
10459 209160 561446.126402
10460 209180 561537.726419
10461 209200 561629.328007
10462 209220 561720.931163
10463 209240 561812.535889
10464 209260 561904.142185
10465 209280 561995.750049
10466 209300 562087.359482
10467 209320 562178.970483
10468 209340 562270.583053
10469 209360 562362.197192
10470 209380 562453.812898
10471 209400 562545.430172
10472 209420 562637.049014
10473 209440 562728.669424
10474 209460 562820.291401
10475 209480 562911.914945
10476 209500 563003.540056
10477 209520 563095.166733
10478 209540 563186.794978
10479 209560 563278.424788
10480 209580 563370.056165
10481 209600 563461.689108
10482 209620 563553.323617
10483 209640 563644.959692
10484 209660 563736.597332
10485 209680 563828.236538
10486 209700 563919.877308
10487 209720 564011.519644
10488 209740 564103.163544
10489 209760 564194.809009
10490 209780 564286.456039
10491 209800 564378.104633
10492 209820 564469.754790
10493 209840 564561.406512
10494 209860 564653.059797
10495 209880 564744.714646
10496 209900 564836.371058
10497 209920 564928.029034
10498 209940 565019.688572
10499 209960 565111.349673
10500 209980 565203.012337
10501 210000 565294.676563

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())