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 27 of 40 · 500/page · 20000 rows next →
# nmargin_tilde
13002 260020 799017.973928
13003 260040 799113.066045
13004 260060 799208.159368
13005 260080 799303.253898
13006 260100 799398.349634
13007 260120 799493.446577
13008 260140 799588.544725
13009 260160 799683.644080
13010 260180 799778.744640
13011 260200 799873.846406
13012 260220 799968.949378
13013 260240 800064.053556
13014 260260 800159.158939
13015 260280 800254.265527
13016 260300 800349.373321
13017 260320 800444.482319
13018 260340 800539.592523
13019 260360 800634.703932
13020 260380 800729.816545
13021 260400 800824.930363
13022 260420 800920.045386
13023 260440 801015.161613
13024 260460 801110.279045
13025 260480 801205.397680
13026 260500 801300.517520
13027 260520 801395.638564
13028 260540 801490.760812
13029 260560 801585.884263
13030 260580 801681.008919
13031 260600 801776.134778
13032 260620 801871.261840
13033 260640 801966.390106
13034 260660 802061.519575
13035 260680 802156.650247
13036 260700 802251.782122
13037 260720 802346.915200
13038 260740 802442.049481
13039 260760 802537.184964
13040 260780 802632.321650
13041 260800 802727.459539
13042 260820 802822.598630
13043 260840 802917.738923
13044 260860 803012.880418
13045 260880 803108.023116
13046 260900 803203.167015
13047 260920 803298.312116
13048 260940 803393.458419
13049 260960 803488.605923
13050 260980 803583.754629
13051 261000 803678.904536
13052 261020 803774.055645
13053 261040 803869.207954
13054 261060 803964.361465
13055 261080 804059.516176
13056 261100 804154.672089
13057 261120 804249.829202
13058 261140 804344.987516
13059 261160 804440.147030
13060 261180 804535.307744
13061 261200 804630.469659
13062 261220 804725.632774
13063 261240 804820.797089
13064 261260 804915.962604
13065 261280 805011.129319
13066 261300 805106.297233
13067 261320 805201.466347
13068 261340 805296.636661
13069 261360 805391.808174
13070 261380 805486.980886
13071 261400 805582.154797
13072 261420 805677.329908
13073 261440 805772.506217
13074 261460 805867.683725
13075 261480 805962.862432
13076 261500 806058.042338
13077 261520 806153.223442
13078 261540 806248.405744
13079 261560 806343.589245
13080 261580 806438.773944
13081 261600 806533.959841
13082 261620 806629.146936
13083 261640 806724.335228
13084 261660 806819.524719
13085 261680 806914.715407
13086 261700 807009.907293
13087 261720 807105.100376
13088 261740 807200.294656
13089 261760 807295.490133
13090 261780 807390.686808
13091 261800 807485.884679
13092 261820 807581.083748
13093 261840 807676.284013
13094 261860 807771.485475
13095 261880 807866.688133
13096 261900 807961.891988
13097 261920 808057.097039
13098 261940 808152.303286
13099 261960 808247.510729
13100 261980 808342.719369
13101 262000 808437.929204
13102 262020 808533.140235
13103 262040 808628.352461
13104 262060 808723.565883
13105 262080 808818.780501
13106 262100 808913.996314
13107 262120 809009.213322
13108 262140 809104.431525
13109 262160 809199.650923
13110 262180 809294.871516
13111 262200 809390.093304
13112 262220 809485.316287
13113 262240 809580.540464
13114 262260 809675.765835
13115 262280 809770.992401
13116 262300 809866.220161
13117 262320 809961.449115
13118 262340 810056.679264
13119 262360 810151.910606
13120 262380 810247.143142
13121 262400 810342.376871
13122 262420 810437.611794
13123 262440 810532.847911
13124 262460 810628.085221
13125 262480 810723.323724
13126 262500 810818.563421
13127 262520 810913.804310
13128 262540 811009.046392
13129 262560 811104.289668
13130 262580 811199.534135
13131 262600 811294.779796
13132 262620 811390.026649
13133 262640 811485.274694
13134 262660 811580.523932
13135 262680 811675.774361
13136 262700 811771.025983
13137 262720 811866.278797
13138 262740 811961.532802
13139 262760 812056.788000
13140 262780 812152.044389
13141 262800 812247.301969
13142 262820 812342.560741
13143 262840 812437.820704
13144 262860 812533.081858
13145 262880 812628.344204
13146 262900 812723.607740
13147 262920 812818.872467
13148 262940 812914.138385
13149 262960 813009.405494
13150 262980 813104.673793
13151 263000 813199.943282
13152 263020 813295.213962
13153 263040 813390.485832
13154 263060 813485.758892
13155 263080 813581.033142
13156 263100 813676.308582
13157 263120 813771.585212
13158 263140 813866.863031
13159 263160 813962.142040
13160 263180 814057.422239
13161 263200 814152.703627
13162 263220 814247.986204
13163 263240 814343.269970
13164 263260 814438.554925
13165 263280 814533.841069
13166 263300 814629.128402
13167 263320 814724.416923
13168 263340 814819.706633
13169 263360 814914.997532
13170 263380 815010.289619
13171 263400 815105.582894
13172 263420 815200.877357
13173 263440 815296.173009
13174 263460 815391.469848
13175 263480 815486.767875
13176 263500 815582.067090
13177 263520 815677.367492
13178 263540 815772.669082
13179 263560 815867.971859
13180 263580 815963.275824
13181 263600 816058.580976
13182 263620 816153.887315
13183 263640 816249.194840
13184 263660 816344.503553
13185 263680 816439.813452
13186 263700 816535.124539
13187 263720 816630.436811
13188 263740 816725.750270
13189 263760 816821.064915
13190 263780 816916.380747
13191 263800 817011.697764
13192 263820 817107.015968
13193 263840 817202.335357
13194 263860 817297.655933
13195 263880 817392.977694
13196 263900 817488.300640
13197 263920 817583.624772
13198 263940 817678.950089
13199 263960 817774.276592
13200 263980 817869.604279
13201 264000 817964.933152
13202 264020 818060.263209
13203 264040 818155.594452
13204 264060 818250.926879
13205 264080 818346.260490
13206 264100 818441.595286
13207 264120 818536.931267
13208 264140 818632.268432
13209 264160 818727.606780
13210 264180 818822.946313
13211 264200 818918.287030
13212 264220 819013.628931
13213 264240 819108.972015
13214 264260 819204.316284
13215 264280 819299.661735
13216 264300 819395.008370
13217 264320 819490.356188
13218 264340 819585.705190
13219 264360 819681.055375
13220 264380 819776.406742
13221 264400 819871.759293
13222 264420 819967.113026
13223 264440 820062.467942
13224 264460 820157.824040
13225 264480 820253.181321
13226 264500 820348.539784
13227 264520 820443.899429
13228 264540 820539.260257
13229 264560 820634.622266
13230 264580 820729.985458
13231 264600 820825.349831
13232 264620 820920.715386
13233 264640 821016.082123
13234 264660 821111.450041
13235 264680 821206.819140
13236 264700 821302.189421
13237 264720 821397.560882
13238 264740 821492.933525
13239 264760 821588.307349
13240 264780 821683.682354
13241 264800 821779.058539
13242 264820 821874.435905
13243 264840 821969.814452
13244 264860 822065.194178
13245 264880 822160.575086
13246 264900 822255.957173
13247 264920 822351.340441
13248 264940 822446.724888
13249 264960 822542.110515
13250 264980 822637.497323
13251 265000 822732.885309
13252 265020 822828.274476
13253 265040 822923.664822
13254 265060 823019.056347
13255 265080 823114.449051
13256 265100 823209.842935
13257 265120 823305.237997
13258 265140 823400.634239
13259 265160 823496.031659
13260 265180 823591.430258
13261 265200 823686.830035
13262 265220 823782.230991
13263 265240 823877.633126
13264 265260 823973.036439
13265 265280 824068.440930
13266 265300 824163.846598
13267 265320 824259.253445
13268 265340 824354.661470
13269 265360 824450.070673
13270 265380 824545.481053
13271 265400 824640.892611
13272 265420 824736.305346
13273 265440 824831.719258
13274 265460 824927.134348
13275 265480 825022.550615
13276 265500 825117.968058
13277 265520 825213.386679
13278 265540 825308.806476
13279 265560 825404.227451
13280 265580 825499.649601
13281 265600 825595.072928
13282 265620 825690.497432
13283 265640 825785.923112
13284 265660 825881.349968
13285 265680 825976.778000
13286 265700 826072.207208
13287 265720 826167.637591
13288 265740 826263.069151
13289 265760 826358.501886
13290 265780 826453.935797
13291 265800 826549.370883
13292 265820 826644.807144
13293 265840 826740.244581
13294 265860 826835.683192
13295 265880 826931.122979
13296 265900 827026.563941
13297 265920 827122.006077
13298 265940 827217.449388
13299 265960 827312.893873
13300 265980 827408.339533
13301 266000 827503.786368
13302 266020 827599.234376
13303 266040 827694.683559
13304 266060 827790.133916
13305 266080 827885.585447
13306 266100 827981.038151
13307 266120 828076.492029
13308 266140 828171.947081
13309 266160 828267.403307
13310 266180 828362.860705
13311 266200 828458.319278
13312 266220 828553.779023
13313 266240 828649.239941
13314 266260 828744.702032
13315 266280 828840.165297
13316 266300 828935.629734
13317 266320 829031.095343
13318 266340 829126.562125
13319 266360 829222.030080
13320 266380 829317.499207
13321 266400 829412.969506
13322 266420 829508.440978
13323 266440 829603.913621
13324 266460 829699.387436
13325 266480 829794.862424
13326 266500 829890.338582
13327 266520 829985.815913
13328 266540 830081.294415
13329 266560 830176.774088
13330 266580 830272.254933
13331 266600 830367.736949
13332 266620 830463.220136
13333 266640 830558.704494
13334 266660 830654.190022
13335 266680 830749.676722
13336 266700 830845.164592
13337 266720 830940.653633
13338 266740 831036.143844
13339 266760 831131.635226
13340 266780 831227.127778
13341 266800 831322.621500
13342 266820 831418.116392
13343 266840 831513.612453
13344 266860 831609.109685
13345 266880 831704.608087
13346 266900 831800.107658
13347 266920 831895.608398
13348 266940 831991.110308
13349 266960 832086.613388
13350 266980 832182.117636
13351 267000 832277.623054
13352 267020 832373.129640
13353 267040 832468.637396
13354 267060 832564.146320
13355 267080 832659.656413
13356 267100 832755.167674
13357 267120 832850.680104
13358 267140 832946.193702
13359 267160 833041.708469
13360 267180 833137.224403
13361 267200 833232.741506
13362 267220 833328.259777
13363 267240 833423.779215
13364 267260 833519.299821
13365 267280 833614.821595
13366 267300 833710.344536
13367 267320 833805.868645
13368 267340 833901.393921
13369 267360 833996.920364
13370 267380 834092.447975
13371 267400 834187.976752
13372 267420 834283.506696
13373 267440 834379.037807
13374 267460 834474.570085
13375 267480 834570.103529
13376 267500 834665.638140
13377 267520 834761.173917
13378 267540 834856.710860
13379 267560 834952.248970
13380 267580 835047.788245
13381 267600 835143.328687
13382 267620 835238.870294
13383 267640 835334.413067
13384 267660 835429.957006
13385 267680 835525.502110
13386 267700 835621.048380
13387 267720 835716.595815
13388 267740 835812.144415
13389 267760 835907.694181
13390 267780 836003.245111
13391 267800 836098.797206
13392 267820 836194.350466
13393 267840 836289.904891
13394 267860 836385.460480
13395 267880 836481.017234
13396 267900 836576.575153
13397 267920 836672.134235
13398 267940 836767.694482
13399 267960 836863.255893
13400 267980 836958.818467
13401 268000 837054.382206
13402 268020 837149.947108
13403 268040 837245.513175
13404 268060 837341.080404
13405 268080 837436.648797
13406 268100 837532.218354
13407 268120 837627.789073
13408 268140 837723.360956
13409 268160 837818.934002
13410 268180 837914.508211
13411 268200 838010.083582
13412 268220 838105.660117
13413 268240 838201.237814
13414 268260 838296.816673
13415 268280 838392.396695
13416 268300 838487.977879
13417 268320 838583.560225
13418 268340 838679.143734
13419 268360 838774.728404
13420 268380 838870.314237
13421 268400 838965.901231
13422 268420 839061.489387
13423 268440 839157.078704
13424 268460 839252.669183
13425 268480 839348.260824
13426 268500 839443.853625
13427 268520 839539.447588
13428 268540 839635.042712
13429 268560 839730.638996
13430 268580 839826.236442
13431 268600 839921.835048
13432 268620 840017.434816
13433 268640 840113.035743
13434 268660 840208.637831
13435 268680 840304.241080
13436 268700 840399.845488
13437 268720 840495.451057
13438 268740 840591.057786
13439 268760 840686.665674
13440 268780 840782.274723
13441 268800 840877.884931
13442 268820 840973.496299
13443 268840 841069.108827
13444 268860 841164.722513
13445 268880 841260.337359
13446 268900 841355.953365
13447 268920 841451.570529
13448 268940 841547.188853
13449 268960 841642.808335
13450 268980 841738.428976
13451 269000 841834.050776
13452 269020 841929.673734
13453 269040 842025.297851
13454 269060 842120.923126
13455 269080 842216.549560
13456 269100 842312.177152
13457 269120 842407.805902
13458 269140 842503.435809
13459 269160 842599.066875
13460 269180 842694.699098
13461 269200 842790.332479
13462 269220 842885.967018
13463 269240 842981.602714
13464 269260 843077.239567
13465 269280 843172.877578
13466 269300 843268.516746
13467 269320 843364.157071
13468 269340 843459.798553
13469 269360 843555.441191
13470 269380 843651.084987
13471 269400 843746.729939
13472 269420 843842.376047
13473 269440 843938.023312
13474 269460 844033.671733
13475 269480 844129.321311
13476 269500 844224.972044
13477 269520 844320.623934
13478 269540 844416.276980
13479 269560 844511.931181
13480 269580 844607.586538
13481 269600 844703.243051
13482 269620 844798.900719
13483 269640 844894.559543
13484 269660 844990.219521
13485 269680 845085.880655
13486 269700 845181.542945
13487 269720 845277.206389
13488 269740 845372.870988
13489 269760 845468.536742
13490 269780 845564.203650
13491 269800 845659.871713
13492 269820 845755.540931
13493 269840 845851.211303
13494 269860 845946.882829
13495 269880 846042.555509
13496 269900 846138.229344
13497 269920 846233.904332
13498 269940 846329.580475
13499 269960 846425.257771
13500 269980 846520.936220
13501 270000 846616.615824

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