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 23 of 40 · 500/page · 20000 rows next →
# nmargin_tilde
11002 220020 611411.209900
11003 220040 611503.636382
11004 220060 611596.064340
11005 220080 611688.493773
11006 220100 611780.924682
11007 220120 611873.357067
11008 220140 611965.790927
11009 220160 612058.226262
11010 220180 612150.663072
11011 220200 612243.101357
11012 220220 612335.541117
11013 220240 612427.982351
11014 220260 612520.425060
11015 220280 612612.869243
11016 220300 612705.314900
11017 220320 612797.762031
11018 220340 612890.210635
11019 220360 612982.660713
11020 220380 613075.112265
11021 220400 613167.565289
11022 220420 613260.019787
11023 220440 613352.475758
11024 220460 613444.933201
11025 220480 613537.392117
11026 220500 613629.852505
11027 220520 613722.314366
11028 220540 613814.777699
11029 220560 613907.242503
11030 220580 613999.708780
11031 220600 614092.176528
11032 220620 614184.645747
11033 220640 614277.116438
11034 220660 614369.588600
11035 220680 614462.062233
11036 220700 614554.537337
11037 220720 614647.013911
11038 220740 614739.491956
11039 220760 614831.971471
11040 220780 614924.452456
11041 220800 615016.934911
11042 220820 615109.418836
11043 220840 615201.904231
11044 220860 615294.391095
11045 220880 615386.879429
11046 220900 615479.369232
11047 220920 615571.860503
11048 220940 615664.353244
11049 220960 615756.847453
11050 220980 615849.343131
11051 221000 615941.840278
11052 221020 616034.338892
11053 221040 616126.838975
11054 221060 616219.340525
11055 221080 616311.843543
11056 221100 616404.348029
11057 221120 616496.853982
11058 221140 616589.361402
11059 221160 616681.870290
11060 221180 616774.380644
11061 221200 616866.892465
11062 221220 616959.405753
11063 221240 617051.920507
11064 221260 617144.436728
11065 221280 617236.954414
11066 221300 617329.473567
11067 221320 617421.994185
11068 221340 617514.516269
11069 221360 617607.039819
11070 221380 617699.564834
11071 221400 617792.091313
11072 221420 617884.619258
11073 221440 617977.148668
11074 221460 618069.679543
11075 221480 618162.211882
11076 221500 618254.745685
11077 221520 618347.280952
11078 221540 618439.817684
11079 221560 618532.355879
11080 221580 618624.895539
11081 221600 618717.436661
11082 221620 618809.979247
11083 221640 618902.523297
11084 221660 618995.068809
11085 221680 619087.615784
11086 221700 619180.164222
11087 221720 619272.714123
11088 221740 619365.265486
11089 221760 619457.818311
11090 221780 619550.372599
11091 221800 619642.928348
11092 221820 619735.485560
11093 221840 619828.044232
11094 221860 619920.604367
11095 221880 620013.165962
11096 221900 620105.729019
11097 221920 620198.293537
11098 221940 620290.859515
11099 221960 620383.426955
11100 221980 620475.995854
11101 222000 620568.566215
11102 222020 620661.138035
11103 222040 620753.711315
11104 222060 620846.286056
11105 222080 620938.862255
11106 222100 621031.439915
11107 222120 621124.019034
11108 222140 621216.599612
11109 222160 621309.181649
11110 222180 621401.765145
11111 222200 621494.350100
11112 222220 621586.936514
11113 222240 621679.524386
11114 222260 621772.113716
11115 222280 621864.704504
11116 222300 621957.296750
11117 222320 622049.890455
11118 222340 622142.485616
11119 222360 622235.082236
11120 222380 622327.680312
11121 222400 622420.279846
11122 222420 622512.880837
11123 222440 622605.483284
11124 222460 622698.087188
11125 222480 622790.692549
11126 222500 622883.299366
11127 222520 622975.907640
11128 222540 623068.517369
11129 222560 623161.128555
11130 222580 623253.741196
11131 222600 623346.355292
11132 222620 623438.970844
11133 222640 623531.587852
11134 222660 623624.206314
11135 222680 623716.826232
11136 222700 623809.447604
11137 222720 623902.070430
11138 222740 623994.694712
11139 222760 624087.320447
11140 222780 624179.947637
11141 222800 624272.576281
11142 222820 624365.206378
11143 222840 624457.837930
11144 222860 624550.470934
11145 222880 624643.105392
11146 222900 624735.741304
11147 222920 624828.378668
11148 222940 624921.017485
11149 222960 625013.657755
11150 222980 625106.299478
11151 223000 625198.942653
11152 223020 625291.587280
11153 223040 625384.233360
11154 223060 625476.880891
11155 223080 625569.529874
11156 223100 625662.180308
11157 223120 625754.832195
11158 223140 625847.485532
11159 223160 625940.140321
11160 223180 626032.796560
11161 223200 626125.454251
11162 223220 626218.113392
11163 223240 626310.773983
11164 223260 626403.436025
11165 223280 626496.099518
11166 223300 626588.764460
11167 223320 626681.430852
11168 223340 626774.098694
11169 223360 626866.767985
11170 223380 626959.438726
11171 223400 627052.110916
11172 223420 627144.784555
11173 223440 627237.459643
11174 223460 627330.136180
11175 223480 627422.814166
11176 223500 627515.493600
11177 223520 627608.174482
11178 223540 627700.856813
11179 223560 627793.540591
11180 223580 627886.225818
11181 223600 627978.912492
11182 223620 628071.600613
11183 223640 628164.290182
11184 223660 628256.981198
11185 223680 628349.673662
11186 223700 628442.367572
11187 223720 628535.062929
11188 223740 628627.759732
11189 223760 628720.457982
11190 223780 628813.157678
11191 223800 628905.858820
11192 223820 628998.561409
11193 223840 629091.265443
11194 223860 629183.970922
11195 223880 629276.677848
11196 223900 629369.386218
11197 223920 629462.096034
11198 223940 629554.807294
11199 223960 629647.520000
11200 223980 629740.234150
11201 224000 629832.949745
11202 224020 629925.666785
11203 224040 630018.385268
11204 224060 630111.105196
11205 224080 630203.826567
11206 224100 630296.549382
11207 224120 630389.273641
11208 224140 630481.999344
11209 224160 630574.726489
11210 224180 630667.455078
11211 224200 630760.185110
11212 224220 630852.916585
11213 224240 630945.649502
11214 224260 631038.383862
11215 224280 631131.119664
11216 224300 631223.856908
11217 224320 631316.595595
11218 224340 631409.335723
11219 224360 631502.077293
11220 224380 631594.820305
11221 224400 631687.564758
11222 224420 631780.310652
11223 224440 631873.057988
11224 224460 631965.806764
11225 224480 632058.556982
11226 224500 632151.308640
11227 224520 632244.061738
11228 224540 632336.816277
11229 224560 632429.572256
11230 224580 632522.329675
11231 224600 632615.088534
11232 224620 632707.848832
11233 224640 632800.610571
11234 224660 632893.373748
11235 224680 632986.138365
11236 224700 633078.904421
11237 224720 633171.671916
11238 224740 633264.440850
11239 224760 633357.211222
11240 224780 633449.983033
11241 224800 633542.756282
11242 224820 633635.530969
11243 224840 633728.307094
11244 224860 633821.084657
11245 224880 633913.863658
11246 224900 634006.644097
11247 224920 634099.425972
11248 224940 634192.209285
11249 224960 634284.994036
11250 224980 634377.780223
11251 225000 634470.567846
11252 225020 634563.356907
11253 225040 634656.147404
11254 225060 634748.939337
11255 225080 634841.732706
11256 225100 634934.527512
11257 225120 635027.323753
11258 225140 635120.121430
11259 225160 635212.920542
11260 225180 635305.721090
11261 225200 635398.523073
11262 225220 635491.326491
11263 225240 635584.131344
11264 225260 635676.937632
11265 225280 635769.745354
11266 225300 635862.554511
11267 225320 635955.365102
11268 225340 636048.177128
11269 225360 636140.990587
11270 225380 636233.805480
11271 225400 636326.621807
11272 225420 636419.439567
11273 225440 636512.258761
11274 225460 636605.079388
11275 225480 636697.901448
11276 225500 636790.724941
11277 225520 636883.549867
11278 225540 636976.376225
11279 225560 637069.204016
11280 225580 637162.033239
11281 225600 637254.863894
11282 225620 637347.695981
11283 225640 637440.529500
11284 225660 637533.364451
11285 225680 637626.200833
11286 225700 637719.038647
11287 225720 637811.877891
11288 225740 637904.718567
11289 225760 637997.560674
11290 225780 638090.404212
11291 225800 638183.249180
11292 225820 638276.095578
11293 225840 638368.943407
11294 225860 638461.792666
11295 225880 638554.643355
11296 225900 638647.495474
11297 225920 638740.349023
11298 225940 638833.204001
11299 225960 638926.060409
11300 225980 639018.918245
11301 226000 639111.777511
11302 226020 639204.638206
11303 226040 639297.500329
11304 226060 639390.363881
11305 226080 639483.228862
11306 226100 639576.095271
11307 226120 639668.963108
11308 226140 639761.832373
11309 226160 639854.703066
11310 226180 639947.575186
11311 226200 640040.448734
11312 226220 640133.323710
11313 226240 640226.200112
11314 226260 640319.077942
11315 226280 640411.957199
11316 226300 640504.837882
11317 226320 640597.719993
11318 226340 640690.603529
11319 226360 640783.488492
11320 226380 640876.374881
11321 226400 640969.262696
11322 226420 641062.151937
11323 226440 641155.042604
11324 226460 641247.934696
11325 226480 641340.828214
11326 226500 641433.723157
11327 226520 641526.619525
11328 226540 641619.517318
11329 226560 641712.416535
11330 226580 641805.317178
11331 226600 641898.219245
11332 226620 641991.122736
11333 226640 642084.027651
11334 226660 642176.933990
11335 226680 642269.841754
11336 226700 642362.750941
11337 226720 642455.661551
11338 226740 642548.573585
11339 226760 642641.487043
11340 226780 642734.401923
11341 226800 642827.318226
11342 226820 642920.235953
11343 226840 643013.155102
11344 226860 643106.075673
11345 226880 643198.997667
11346 226900 643291.921083
11347 226920 643384.845921
11348 226940 643477.772180
11349 226960 643570.699862
11350 226980 643663.628965
11351 227000 643756.559490
11352 227020 643849.491436
11353 227040 643942.424803
11354 227060 644035.359591
11355 227080 644128.295800
11356 227100 644221.233430
11357 227120 644314.172480
11358 227140 644407.112951
11359 227160 644500.054841
11360 227180 644592.998152
11361 227200 644685.942883
11362 227220 644778.889034
11363 227240 644871.836604
11364 227260 644964.785594
11365 227280 645057.736003
11366 227300 645150.687831
11367 227320 645243.641078
11368 227340 645336.595745
11369 227360 645429.551829
11370 227380 645522.509333
11371 227400 645615.468255
11372 227420 645708.428595
11373 227440 645801.390353
11374 227460 645894.353529
11375 227480 645987.318123
11376 227500 646080.284135
11377 227520 646173.251564
11378 227540 646266.220411
11379 227560 646359.190675
11380 227580 646452.162355
11381 227600 646545.135453
11382 227620 646638.109968
11383 227640 646731.085899
11384 227660 646824.063246
11385 227680 646917.042010
11386 227700 647010.022190
11387 227720 647103.003786
11388 227740 647195.986798
11389 227760 647288.971226
11390 227780 647381.957069
11391 227800 647474.944328
11392 227820 647567.933002
11393 227840 647660.923091
11394 227860 647753.914594
11395 227880 647846.907513
11396 227900 647939.901847
11397 227920 648032.897594
11398 227940 648125.894757
11399 227960 648218.893333
11400 227980 648311.893323
11401 228000 648404.894728
11402 228020 648497.897546
11403 228040 648590.901778
11404 228060 648683.907423
11405 228080 648776.914481
11406 228100 648869.922953
11407 228120 648962.932838
11408 228140 649055.944135
11409 228160 649148.956845
11410 228180 649241.970968
11411 228200 649334.986503
11412 228220 649428.003450
11413 228240 649521.021810
11414 228260 649614.041581
11415 228280 649707.062765
11416 228300 649800.085360
11417 228320 649893.109366
11418 228340 649986.134784
11419 228360 650079.161613
11420 228380 650172.189853
11421 228400 650265.219503
11422 228420 650358.250565
11423 228440 650451.283037
11424 228460 650544.316920
11425 228480 650637.352213
11426 228500 650730.388916
11427 228520 650823.427030
11428 228540 650916.466553
11429 228560 651009.507485
11430 228580 651102.549828
11431 228600 651195.593579
11432 228620 651288.638740
11433 228640 651381.685310
11434 228660 651474.733289
11435 228680 651567.782677
11436 228700 651660.833474
11437 228720 651753.885679
11438 228740 651846.939292
11439 228760 651939.994314
11440 228780 652033.050744
11441 228800 652126.108581
11442 228820 652219.167827
11443 228840 652312.228480
11444 228860 652405.290540
11445 228880 652498.354008
11446 228900 652591.418883
11447 228920 652684.485165
11448 228940 652777.552854
11449 228960 652870.621949
11450 228980 652963.692451
11451 229000 653056.764360
11452 229020 653149.837675
11453 229040 653242.912396
11454 229060 653335.988523
11455 229080 653429.066056
11456 229100 653522.144994
11457 229120 653615.225338
11458 229140 653708.307088
11459 229160 653801.390243
11460 229180 653894.474802
11461 229200 653987.560767
11462 229220 654080.648137
11463 229240 654173.736911
11464 229260 654266.827089
11465 229280 654359.918672
11466 229300 654453.011660
11467 229320 654546.106051
11468 229340 654639.201846
11469 229360 654732.299045
11470 229380 654825.397648
11471 229400 654918.497654
11472 229420 655011.599063
11473 229440 655104.701875
11474 229460 655197.806091
11475 229480 655290.911709
11476 229500 655384.018730
11477 229520 655477.127154
11478 229540 655570.236980
11479 229560 655663.348209
11480 229580 655756.460839
11481 229600 655849.574872
11482 229620 655942.690306
11483 229640 656035.807142
11484 229660 656128.925379
11485 229680 656222.045018
11486 229700 656315.166058
11487 229720 656408.288500
11488 229740 656501.412342
11489 229760 656594.537585
11490 229780 656687.664229
11491 229800 656780.792273
11492 229820 656873.921717
11493 229840 656967.052562
11494 229860 657060.184807
11495 229880 657153.318452
11496 229900 657246.453496
11497 229920 657339.589940
11498 229940 657432.727784
11499 229960 657525.867027
11500 229980 657619.007669
11501 230000 657712.149710

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