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 28 of 40 · 500/page · 20000 rows next →
# nmargin_tilde
13502 270020 846712.296580
13503 270040 846807.978490
13504 270060 846903.661554
13505 270080 846999.345770
13506 270100 847095.031140
13507 270120 847190.717662
13508 270140 847286.405337
13509 270160 847382.094166
13510 270180 847477.784146
13511 270200 847573.475279
13512 270220 847669.167565
13513 270240 847764.861003
13514 270260 847860.555593
13515 270280 847956.251336
13516 270300 848051.948230
13517 270320 848147.646276
13518 270340 848243.345474
13519 270360 848339.045824
13520 270380 848434.747326
13521 270400 848530.449979
13522 270420 848626.153783
13523 270440 848721.858739
13524 270460 848817.564846
13525 270480 848913.272104
13526 270500 849008.980513
13527 270520 849104.690073
13528 270540 849200.400783
13529 270560 849296.112645
13530 270580 849391.825657
13531 270600 849487.539819
13532 270620 849583.255132
13533 270640 849678.971596
13534 270660 849774.689209
13535 270680 849870.407972
13536 270700 849966.127886
13537 270720 850061.848949
13538 270740 850157.571162
13539 270760 850253.294525
13540 270780 850349.019038
13541 270800 850444.744700
13542 270820 850540.471511
13543 270840 850636.199472
13544 270860 850731.928581
13545 270880 850827.658840
13546 270900 850923.390248
13547 270920 851019.122805
13548 270940 851114.856510
13549 270960 851210.591364
13550 270980 851306.327367
13551 271000 851402.064518
13552 271020 851497.802818
13553 271040 851593.542265
13554 271060 851689.282861
13555 271080 851785.024605
13556 271100 851880.767497
13557 271120 851976.511537
13558 271140 852072.256725
13559 271160 852168.003060
13560 271180 852263.750543
13561 271200 852359.499173
13562 271220 852455.248951
13563 271240 852550.999876
13564 271260 852646.751948
13565 271280 852742.505167
13566 271300 852838.259533
13567 271320 852934.015045
13568 271340 853029.771705
13569 271360 853125.529511
13570 271380 853221.288464
13571 271400 853317.048563
13572 271420 853412.809809
13573 271440 853508.572201
13574 271460 853604.335739
13575 271480 853700.100423
13576 271500 853795.866253
13577 271520 853891.633228
13578 271540 853987.401350
13579 271560 854083.170617
13580 271580 854178.941030
13581 271600 854274.712588
13582 271620 854370.485291
13583 271640 854466.259140
13584 271660 854562.034134
13585 271680 854657.810273
13586 271700 854753.587556
13587 271720 854849.365985
13588 271740 854945.145558
13589 271760 855040.926276
13590 271780 855136.708139
13591 271800 855232.491146
13592 271820 855328.275297
13593 271840 855424.060592
13594 271860 855519.847032
13595 271880 855615.634615
13596 271900 855711.423343
13597 271920 855807.213214
13598 271940 855903.004229
13599 271960 855998.796388
13600 271980 856094.589690
13601 272000 856190.384136
13602 272020 856286.179725
13603 272040 856381.976457
13604 272060 856477.774332
13605 272080 856573.573350
13606 272100 856669.373512
13607 272120 856765.174816
13608 272140 856860.977262
13609 272160 856956.780852
13610 272180 857052.585584
13611 272200 857148.391458
13612 272220 857244.198474
13613 272240 857340.006633
13614 272260 857435.815934
13615 272280 857531.626377
13616 272300 857627.437962
13617 272320 857723.250689
13618 272340 857819.064557
13619 272360 857914.879567
13620 272380 858010.695719
13621 272400 858106.513011
13622 272420 858202.331446
13623 272440 858298.151021
13624 272460 858393.971738
13625 272480 858489.793595
13626 272500 858585.616594
13627 272520 858681.440733
13628 272540 858777.266013
13629 272560 858873.092434
13630 272580 858968.919995
13631 272600 859064.748696
13632 272620 859160.578538
13633 272640 859256.409520
13634 272660 859352.241642
13635 272680 859448.074904
13636 272700 859543.909306
13637 272720 859639.744848
13638 272740 859735.581530
13639 272760 859831.419351
13640 272780 859927.258312
13641 272800 860023.098412
13642 272820 860118.939651
13643 272840 860214.782030
13644 272860 860310.625548
13645 272880 860406.470205
13646 272900 860502.316000
13647 272920 860598.162935
13648 272940 860694.011008
13649 272960 860789.860220
13650 272980 860885.710570
13651 273000 860981.562059
13652 273020 861077.414686
13653 273040 861173.268451
13654 273060 861269.123355
13655 273080 861364.979396
13656 273100 861460.836575
13657 273120 861556.694892
13658 273140 861652.554347
13659 273160 861748.414940
13660 273180 861844.276670
13661 273200 861940.139537
13662 273220 862036.003542
13663 273240 862131.868684
13664 273260 862227.734963
13665 273280 862323.602379
13666 273300 862419.470932
13667 273320 862515.340622
13668 273340 862611.211448
13669 273360 862707.083411
13670 273380 862802.956511
13671 273400 862898.830747
13672 273420 862994.706120
13673 273440 863090.582628
13674 273460 863186.460273
13675 273480 863282.339054
13676 273500 863378.218971
13677 273520 863474.100023
13678 273540 863569.982211
13679 273560 863665.865535
13680 273580 863761.749995
13681 273600 863857.635590
13682 273620 863953.522320
13683 273640 864049.410185
13684 273660 864145.299186
13685 273680 864241.189321
13686 273700 864337.080592
13687 273720 864432.972997
13688 273740 864528.866537
13689 273760 864624.761212
13690 273780 864720.657021
13691 273800 864816.553965
13692 273820 864912.452043
13693 273840 865008.351255
13694 273860 865104.251602
13695 273880 865200.153082
13696 273900 865296.055696
13697 273920 865391.959445
13698 273940 865487.864327
13699 273960 865583.770342
13700 273980 865679.677492
13701 274000 865775.585774
13702 274020 865871.495190
13703 274040 865967.405739
13704 274060 866063.317422
13705 274080 866159.230237
13706 274100 866255.144186
13707 274120 866351.059267
13708 274140 866446.975481
13709 274160 866542.892828
13710 274180 866638.811307
13711 274200 866734.730918
13712 274220 866830.651662
13713 274240 866926.573539
13714 274260 867022.496547
13715 274280 867118.420688
13716 274300 867214.345960
13717 274320 867310.272365
13718 274340 867406.199901
13719 274360 867502.128569
13720 274380 867598.058368
13721 274400 867693.989299
13722 274420 867789.921361
13723 274440 867885.854555
13724 274460 867981.788879
13725 274480 868077.724335
13726 274500 868173.660922
13727 274520 868269.598640
13728 274540 868365.537488
13729 274560 868461.477467
13730 274580 868557.418577
13731 274600 868653.360817
13732 274620 868749.304187
13733 274640 868845.248688
13734 274660 868941.194319
13735 274680 869037.141081
13736 274700 869133.088972
13737 274720 869229.037993
13738 274740 869324.988144
13739 274760 869420.939424
13740 274780 869516.891834
13741 274800 869612.845374
13742 274820 869708.800043
13743 274840 869804.755841
13744 274860 869900.712769
13745 274880 869996.670826
13746 274900 870092.630012
13747 274920 870188.590326
13748 274940 870284.551770
13749 274960 870380.514342
13750 274980 870476.478043
13751 275000 870572.442872
13752 275020 870668.408830
13753 275040 870764.375916
13754 275060 870860.344130
13755 275080 870956.313473
13756 275100 871052.283943
13757 275120 871148.255541
13758 275140 871244.228268
13759 275160 871340.202122
13760 275180 871436.177103
13761 275200 871532.153213
13762 275220 871628.130449
13763 275240 871724.108813
13764 275260 871820.088304
13765 275280 871916.068923
13766 275300 872012.050668
13767 275320 872108.033541
13768 275340 872204.017540
13769 275360 872300.002666
13770 275380 872395.988919
13771 275400 872491.976298
13772 275420 872587.964804
13773 275440 872683.954436
13774 275460 872779.945194
13775 275480 872875.937079
13776 275500 872971.930089
13777 275520 873067.924226
13778 275540 873163.919488
13779 275560 873259.915876
13780 275580 873355.913390
13781 275600 873451.912030
13782 275620 873547.911795
13783 275640 873643.912685
13784 275660 873739.914701
13785 275680 873835.917842
13786 275700 873931.922108
13787 275720 874027.927499
13788 275740 874123.934015
13789 275760 874219.941656
13790 275780 874315.950421
13791 275800 874411.960311
13792 275820 874507.971326
13793 275840 874603.983465
13794 275860 874699.996728
13795 275880 874796.011116
13796 275900 874892.026628
13797 275920 874988.043263
13798 275940 875084.061023
13799 275960 875180.079906
13800 275980 875276.099914
13801 276000 875372.121045
13802 276020 875468.143299
13803 276040 875564.166677
13804 276060 875660.191178
13805 276080 875756.216802
13806 276100 875852.243550
13807 276120 875948.271421
13808 276140 876044.300414
13809 276160 876140.330531
13810 276180 876236.361770
13811 276200 876332.394132
13812 276220 876428.427617
13813 276240 876524.462224
13814 276260 876620.497953
13815 276280 876716.534805
13816 276300 876812.572778
13817 276320 876908.611874
13818 276340 877004.652092
13819 276360 877100.693432
13820 276380 877196.735894
13821 276400 877292.779477
13822 276420 877388.824182
13823 276440 877484.870008
13824 276460 877580.916956
13825 276480 877676.965025
13826 276500 877773.014215
13827 276520 877869.064527
13828 276540 877965.115959
13829 276560 878061.168513
13830 276580 878157.222187
13831 276600 878253.276982
13832 276620 878349.332897
13833 276640 878445.389933
13834 276660 878541.448090
13835 276680 878637.507367
13836 276700 878733.567764
13837 276720 878829.629281
13838 276740 878925.691919
13839 276760 879021.755676
13840 276780 879117.820553
13841 276800 879213.886550
13842 276820 879309.953667
13843 276840 879406.021903
13844 276860 879502.091259
13845 276880 879598.161734
13846 276900 879694.233328
13847 276920 879790.306041
13848 276940 879886.379874
13849 276960 879982.454825
13850 276980 880078.530896
13851 277000 880174.608085
13852 277020 880270.686393
13853 277040 880366.765820
13854 277060 880462.846365
13855 277080 880558.928028
13856 277100 880655.010810
13857 277120 880751.094710
13858 277140 880847.179728
13859 277160 880943.265864
13860 277180 881039.353118
13861 277200 881135.441490
13862 277220 881231.530980
13863 277240 881327.621587
13864 277260 881423.713312
13865 277280 881519.806154
13866 277300 881615.900114
13867 277320 881711.995191
13868 277340 881808.091385
13869 277360 881904.188696
13870 277380 882000.287124
13871 277400 882096.386669
13872 277420 882192.487331
13873 277440 882288.589109
13874 277460 882384.692004
13875 277480 882480.796016
13876 277500 882576.901144
13877 277520 882673.007388
13878 277540 882769.114748
13879 277560 882865.223225
13880 277580 882961.332817
13881 277600 883057.443526
13882 277620 883153.555350
13883 277640 883249.668290
13884 277660 883345.782345
13885 277680 883441.897516
13886 277700 883538.013803
13887 277720 883634.131205
13888 277740 883730.249722
13889 277760 883826.369354
13890 277780 883922.490101
13891 277800 884018.611963
13892 277820 884114.734941
13893 277840 884210.859032
13894 277860 884306.984239
13895 277880 884403.110560
13896 277900 884499.237995
13897 277920 884595.366545
13898 277940 884691.496210
13899 277960 884787.626988
13900 277980 884883.758880
13901 278000 884979.891887
13902 278020 885076.026007
13903 278040 885172.161241
13904 278060 885268.297589
13905 278080 885364.435051
13906 278100 885460.573626
13907 278120 885556.713314
13908 278140 885652.854116
13909 278160 885748.996031
13910 278180 885845.139059
13911 278200 885941.283200
13912 278220 886037.428454
13913 278240 886133.574821
13914 278260 886229.722301
13915 278280 886325.870893
13916 278300 886422.020598
13917 278320 886518.171415
13918 278340 886614.323345
13919 278360 886710.476387
13920 278380 886806.630541
13921 278400 886902.785807
13922 278420 886998.942186
13923 278440 887095.099676
13924 278460 887191.258278
13925 278480 887287.417991
13926 278500 887383.578817
13927 278520 887479.740753
13928 278540 887575.903802
13929 278560 887672.067961
13930 278580 887768.233232
13931 278600 887864.399614
13932 278620 887960.567106
13933 278640 888056.735710
13934 278660 888152.905425
13935 278680 888249.076250
13936 278700 888345.248186
13937 278720 888441.421233
13938 278740 888537.595390
13939 278760 888633.770658
13940 278780 888729.947035
13941 278800 888826.124523
13942 278820 888922.303121
13943 278840 889018.482829
13944 278860 889114.663647
13945 278880 889210.845575
13946 278900 889307.028612
13947 278920 889403.212759
13948 278940 889499.398015
13949 278960 889595.584381
13950 278980 889691.771857
13951 279000 889787.960441
13952 279020 889884.150135
13953 279040 889980.340937
13954 279060 890076.532849
13955 279080 890172.725869
13956 279100 890268.919998
13957 279120 890365.115236
13958 279140 890461.311583
13959 279160 890557.509038
13960 279180 890653.707601
13961 279200 890749.907272
13962 279220 890846.108052
13963 279240 890942.309940
13964 279260 891038.512936
13965 279280 891134.717039
13966 279300 891230.922251
13967 279320 891327.128570
13968 279340 891423.335997
13969 279360 891519.544531
13970 279380 891615.754173
13971 279400 891711.964922
13972 279420 891808.176778
13973 279440 891904.389742
13974 279460 892000.603813
13975 279480 892096.818990
13976 279500 892193.035274
13977 279520 892289.252665
13978 279540 892385.471163
13979 279560 892481.690768
13980 279580 892577.911479
13981 279600 892674.133296
13982 279620 892770.356219
13983 279640 892866.580249
13984 279660 892962.805385
13985 279680 893059.031627
13986 279700 893155.258974
13987 279720 893251.487428
13988 279740 893347.716987
13989 279760 893443.947652
13990 279780 893540.179423
13991 279800 893636.412299
13992 279820 893732.646280
13993 279840 893828.881367
13994 279860 893925.117558
13995 279880 894021.354855
13996 279900 894117.593257
13997 279920 894213.832763
13998 279940 894310.073375
13999 279960 894406.315091
14000 279980 894502.557911
14001 280000 894598.801837

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