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 7 of 40 · 500/page · 20000 rows next →
# nmargin_tilde
3002 60020 -54669.365979
3003 60040 -54602.006538
3004 60060 -54534.639305
3005 60080 -54467.264283
3006 60100 -54399.881478
3007 60120 -54332.490891
3008 60140 -54265.092527
3009 60160 -54197.686389
3010 60180 -54130.272480
3011 60200 -54062.850805
3012 60220 -53995.421365
3013 60240 -53927.984166
3014 60260 -53860.539210
3015 60280 -53793.086502
3016 60300 -53725.626044
3017 60320 -53658.157839
3018 60340 -53590.681892
3019 60360 -53523.198206
3020 60380 -53455.706785
3021 60400 -53388.207631
3022 60420 -53320.700749
3023 60440 -53253.186141
3024 60460 -53185.663812
3025 60480 -53118.133764
3026 60500 -53050.596002
3027 60520 -52983.050528
3028 60540 -52915.497346
3029 60560 -52847.936460
3030 60580 -52780.367873
3031 60600 -52712.791589
3032 60620 -52645.207610
3033 60640 -52577.615940
3034 60660 -52510.016584
3035 60680 -52442.409543
3036 60700 -52374.794822
3037 60720 -52307.172425
3038 60740 -52239.542353
3039 60760 -52171.904612
3040 60780 -52104.259204
3041 60800 -52036.606133
3042 60820 -51968.945402
3043 60840 -51901.277014
3044 60860 -51833.600973
3045 60880 -51765.917283
3046 60900 -51698.225947
3047 60920 -51630.526968
3048 60940 -51562.820349
3049 60960 -51495.106095
3050 60980 -51427.384207
3051 61000 -51359.654691
3052 61020 -51291.917549
3053 61040 -51224.172784
3054 61060 -51156.420400
3055 61080 -51088.660401
3056 61100 -51020.892789
3057 61120 -50953.117568
3058 61140 -50885.334742
3059 61160 -50817.544314
3060 61180 -50749.746286
3061 61200 -50681.940664
3062 61220 -50614.127449
3063 61240 -50546.306645
3064 61260 -50478.478256
3065 61280 -50410.642285
3066 61300 -50342.798735
3067 61320 -50274.947610
3068 61340 -50207.088913
3069 61360 -50139.222647
3070 61380 -50071.348816
3071 61400 -50003.467423
3072 61420 -49935.578472
3073 61440 -49867.681965
3074 61460 -49799.777906
3075 61480 -49731.866298
3076 61500 -49663.947145
3077 61520 -49596.020450
3078 61540 -49528.086217
3079 61560 -49460.144448
3080 61580 -49392.195147
3081 61600 -49324.238317
3082 61620 -49256.273961
3083 61640 -49188.302084
3084 61660 -49120.322688
3085 61680 -49052.335776
3086 61700 -48984.341352
3087 61720 -48916.339419
3088 61740 -48848.329980
3089 61760 -48780.313039
3090 61780 -48712.288599
3091 61800 -48644.256663
3092 61820 -48576.217235
3093 61840 -48508.170317
3094 61860 -48440.115913
3095 61880 -48372.054027
3096 61900 -48303.984661
3097 61920 -48235.907819
3098 61940 -48167.823505
3099 61960 -48099.731720
3100 61980 -48031.632469
3101 62000 -47963.525756
3102 62020 -47895.411582
3103 62040 -47827.289952
3104 62060 -47759.160868
3105 62080 -47691.024334
3106 62100 -47622.880354
3107 62120 -47554.728929
3108 62140 -47486.570065
3109 62160 -47418.403763
3110 62180 -47350.230028
3111 62200 -47282.048861
3112 62220 -47213.860268
3113 62240 -47145.664250
3114 62260 -47077.460811
3115 62280 -47009.249955
3116 62300 -46941.031684
3117 62320 -46872.806001
3118 62340 -46804.572911
3119 62360 -46736.332415
3120 62380 -46668.084518
3121 62400 -46599.829222
3122 62420 -46531.566532
3123 62440 -46463.296449
3124 62460 -46395.018977
3125 62480 -46326.734120
3126 62500 -46258.441880
3127 62520 -46190.142260
3128 62540 -46121.835265
3129 62560 -46053.520897
3130 62580 -45985.199159
3131 62600 -45916.870055
3132 62620 -45848.533587
3133 62640 -45780.189759
3134 62660 -45711.838574
3135 62680 -45643.480035
3136 62700 -45575.114146
3137 62720 -45506.740909
3138 62740 -45438.360327
3139 62760 -45369.972405
3140 62780 -45301.577145
3141 62800 -45233.174549
3142 62820 -45164.764622
3143 62840 -45096.347367
3144 62860 -45027.922786
3145 62880 -44959.490883
3146 62900 -44891.051660
3147 62920 -44822.605122
3148 62940 -44754.151271
3149 62960 -44685.690110
3150 62980 -44617.221643
3151 63000 -44548.745872
3152 63020 -44480.262801
3153 63040 -44411.772433
3154 63060 -44343.274771
3155 63080 -44274.769818
3156 63100 -44206.257577
3157 63120 -44137.738052
3158 63140 -44069.211245
3159 63160 -44000.677159
3160 63180 -43932.135798
3161 63200 -43863.587166
3162 63220 -43795.031263
3163 63240 -43726.468095
3164 63260 -43657.897664
3165 63280 -43589.319974
3166 63300 -43520.735026
3167 63320 -43452.142825
3168 63340 -43383.543373
3169 63360 -43314.936674
3170 63380 -43246.322731
3171 63400 -43177.701546
3172 63420 -43109.073124
3173 63440 -43040.437466
3174 63460 -42971.794576
3175 63480 -42903.144457
3176 63500 -42834.487112
3177 63520 -42765.822545
3178 63540 -42697.150758
3179 63560 -42628.471754
3180 63580 -42559.785536
3181 63600 -42491.092108
3182 63620 -42422.391473
3183 63640 -42353.683633
3184 63660 -42284.968591
3185 63680 -42216.246352
3186 63700 -42147.516917
3187 63720 -42078.780290
3188 63740 -42010.036474
3189 63760 -41941.285471
3190 63780 -41872.527286
3191 63800 -41803.761921
3192 63820 -41734.989378
3193 63840 -41666.209662
3194 63860 -41597.422774
3195 63880 -41528.628719
3196 63900 -41459.827498
3197 63920 -41391.019116
3198 63940 -41322.203575
3199 63960 -41253.380879
3200 63980 -41184.551029
3201 64000 -41115.714030
3202 64020 -41046.869883
3203 64040 -40978.018593
3204 64060 -40909.160163
3205 64080 -40840.294594
3206 64100 -40771.421891
3207 64120 -40702.542056
3208 64140 -40633.655092
3209 64160 -40564.761003
3210 64180 -40495.859790
3211 64200 -40426.951458
3212 64220 -40358.036009
3213 64240 -40289.113447
3214 64260 -40220.183773
3215 64280 -40151.246992
3216 64300 -40082.303106
3217 64320 -40013.352118
3218 64340 -39944.394031
3219 64360 -39875.428848
3220 64380 -39806.456572
3221 64400 -39737.477206
3222 64420 -39668.490754
3223 64440 -39599.497217
3224 64460 -39530.496599
3225 64480 -39461.488903
3226 64500 -39392.474131
3227 64520 -39323.452288
3228 64540 -39254.423375
3229 64560 -39185.387396
3230 64580 -39116.344354
3231 64600 -39047.294251
3232 64620 -38978.237091
3233 64640 -38909.172876
3234 64660 -38840.101610
3235 64680 -38771.023295
3236 64700 -38701.937934
3237 64720 -38632.845530
3238 64740 -38563.746087
3239 64760 -38494.639607
3240 64780 -38425.526092
3241 64800 -38356.405547
3242 64820 -38287.277974
3243 64840 -38218.143375
3244 64860 -38149.001754
3245 64880 -38079.853114
3246 64900 -38010.697457
3247 64920 -37941.534786
3248 64940 -37872.365105
3249 64960 -37803.188416
3250 64980 -37734.004723
3251 65000 -37664.814027
3252 65020 -37595.616332
3253 65040 -37526.411641
3254 65060 -37457.199957
3255 65080 -37387.981283
3256 65100 -37318.755621
3257 65120 -37249.522975
3258 65140 -37180.283347
3259 65160 -37111.036740
3260 65180 -37041.783157
3261 65200 -36972.522601
3262 65220 -36903.255075
3263 65240 -36833.980582
3264 65260 -36764.699124
3265 65280 -36695.410705
3266 65300 -36626.115327
3267 65320 -36556.812993
3268 65340 -36487.503706
3269 65360 -36418.187470
3270 65380 -36348.864286
3271 65400 -36279.534158
3272 65420 -36210.197088
3273 65440 -36140.853080
3274 65460 -36071.502136
3275 65480 -36002.144258
3276 65500 -35932.779451
3277 65520 -35863.407717
3278 65540 -35794.029058
3279 65560 -35724.643478
3280 65580 -35655.250979
3281 65600 -35585.851564
3282 65620 -35516.445236
3283 65640 -35447.031998
3284 65660 -35377.611853
3285 65680 -35308.184803
3286 65700 -35238.750852
3287 65720 -35169.310001
3288 65740 -35099.862254
3289 65760 -35030.407615
3290 65780 -34960.946084
3291 65800 -34891.477667
3292 65820 -34822.002364
3293 65840 -34752.520180
3294 65860 -34683.031116
3295 65880 -34613.535176
3296 65900 -34544.032362
3297 65920 -34474.522678
3298 65940 -34405.006126
3299 65960 -34335.482708
3300 65980 -34265.952429
3301 66000 -34196.415290
3302 66020 -34126.871294
3303 66040 -34057.320444
3304 66060 -33987.762743
3305 66080 -33918.198193
3306 66100 -33848.626798
3307 66120 -33779.048560
3308 66140 -33709.463482
3309 66160 -33639.871567
3310 66180 -33570.272818
3311 66200 -33500.667237
3312 66220 -33431.054826
3313 66240 -33361.435590
3314 66260 -33291.809531
3315 66280 -33222.176650
3316 66300 -33152.536952
3317 66320 -33082.890439
3318 66340 -33013.237114
3319 66360 -32943.576979
3320 66380 -32873.910037
3321 66400 -32804.236291
3322 66420 -32734.555744
3323 66440 -32664.868399
3324 66460 -32595.174257
3325 66480 -32525.473323
3326 66500 -32455.765598
3327 66520 -32386.051086
3328 66540 -32316.329789
3329 66560 -32246.601710
3330 66580 -32176.866851
3331 66600 -32107.125216
3332 66620 -32037.376807
3333 66640 -31967.621627
3334 66660 -31897.859679
3335 66680 -31828.090965
3336 66700 -31758.315488
3337 66720 -31688.533251
3338 66740 -31618.744256
3339 66760 -31548.948506
3340 66780 -31479.146005
3341 66800 -31409.336754
3342 66820 -31339.520756
3343 66840 -31269.698015
3344 66860 -31199.868532
3345 66880 -31130.032311
3346 66900 -31060.189354
3347 66920 -30990.339664
3348 66940 -30920.483244
3349 66960 -30850.620096
3350 66980 -30780.750223
3351 67000 -30710.873627
3352 67020 -30640.990312
3353 67040 -30571.100280
3354 67060 -30501.203534
3355 67080 -30431.300076
3356 67100 -30361.389910
3357 67120 -30291.473037
3358 67140 -30221.549461
3359 67160 -30151.619184
3360 67180 -30081.682209
3361 67200 -30011.738539
3362 67220 -29941.788175
3363 67240 -29871.831122
3364 67260 -29801.867381
3365 67280 -29731.896956
3366 67300 -29661.919848
3367 67320 -29591.936061
3368 67340 -29521.945597
3369 67360 -29451.948459
3370 67380 -29381.944650
3371 67400 -29311.934172
3372 67420 -29241.917027
3373 67440 -29171.893220
3374 67460 -29101.862751
3375 67480 -29031.825624
3376 67500 -28961.781842
3377 67520 -28891.731407
3378 67540 -28821.674321
3379 67560 -28751.610588
3380 67580 -28681.540210
3381 67600 -28611.463190
3382 67620 -28541.379530
3383 67640 -28471.289233
3384 67660 -28401.192301
3385 67680 -28331.088738
3386 67700 -28260.978546
3387 67720 -28190.861727
3388 67740 -28120.738284
3389 67760 -28050.608220
3390 67780 -27980.471537
3391 67800 -27910.328238
3392 67820 -27840.178326
3393 67840 -27770.021803
3394 67860 -27699.858671
3395 67880 -27629.688935
3396 67900 -27559.512595
3397 67920 -27489.329654
3398 67940 -27419.140117
3399 67960 -27348.943983
3400 67980 -27278.741258
3401 68000 -27208.531942
3402 68020 -27138.316039
3403 68040 -27068.093551
3404 68060 -26997.864481
3405 68080 -26927.628832
3406 68100 -26857.386605
3407 68120 -26787.137804
3408 68140 -26716.882432
3409 68160 -26646.620490
3410 68180 -26576.351981
3411 68200 -26506.076908
3412 68220 -26435.795274
3413 68240 -26365.507081
3414 68260 -26295.212332
3415 68280 -26224.911029
3416 68300 -26154.603175
3417 68320 -26084.288772
3418 68340 -26013.967823
3419 68360 -25943.640330
3420 68380 -25873.306297
3421 68400 -25802.965725
3422 68420 -25732.618618
3423 68440 -25662.264977
3424 68460 -25591.904806
3425 68480 -25521.538107
3426 68500 -25451.164882
3427 68520 -25380.785134
3428 68540 -25310.398866
3429 68560 -25240.006079
3430 68580 -25169.606778
3431 68600 -25099.200963
3432 68620 -25028.788639
3433 68640 -24958.369806
3434 68660 -24887.944469
3435 68680 -24817.512628
3436 68700 -24747.074288
3437 68720 -24676.629450
3438 68740 -24606.178117
3439 68760 -24535.720292
3440 68780 -24465.255976
3441 68800 -24394.785173
3442 68820 -24324.307886
3443 68840 -24253.824115
3444 68860 -24183.333865
3445 68880 -24112.837138
3446 68900 -24042.333936
3447 68920 -23971.824261
3448 68940 -23901.308116
3449 68960 -23830.785505
3450 68980 -23760.256428
3451 69000 -23689.720889
3452 69020 -23619.178891
3453 69040 -23548.630435
3454 69060 -23478.075524
3455 69080 -23407.514162
3456 69100 -23336.946349
3457 69120 -23266.372089
3458 69140 -23195.791385
3459 69160 -23125.204238
3460 69180 -23054.610651
3461 69200 -22984.010627
3462 69220 -22913.404168
3463 69240 -22842.791277
3464 69260 -22772.171957
3465 69280 -22701.546208
3466 69300 -22630.914036
3467 69320 -22560.275440
3468 69340 -22489.630425
3469 69360 -22418.978992
3470 69380 -22348.321145
3471 69400 -22277.656885
3472 69420 -22206.986215
3473 69440 -22136.309137
3474 69460 -22065.625655
3475 69480 -21994.935769
3476 69500 -21924.239484
3477 69520 -21853.536801
3478 69540 -21782.827723
3479 69560 -21712.112252
3480 69580 -21641.390391
3481 69600 -21570.662143
3482 69620 -21499.927508
3483 69640 -21429.186491
3484 69660 -21358.439094
3485 69680 -21287.685318
3486 69700 -21216.925167
3487 69720 -21146.158643
3488 69740 -21075.385748
3489 69760 -21004.606485
3490 69780 -20933.820856
3491 69800 -20863.028864
3492 69820 -20792.230511
3493 69840 -20721.425800
3494 69860 -20650.614732
3495 69880 -20579.797311
3496 69900 -20508.973539
3497 69920 -20438.143418
3498 69940 -20367.306951
3499 69960 -20296.464140
3500 69980 -20225.614987
3501 70000 -20154.759495

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