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 24 of 40 · 500/page · 20000 rows next →
# nmargin_tilde
11502 230020 657805.293150
11503 230040 657898.437989
11504 230060 657991.584226
11505 230080 658084.731862
11506 230100 658177.880896
11507 230120 658271.031328
11508 230140 658364.183158
11509 230160 658457.336387
11510 230180 658550.491012
11511 230200 658643.647036
11512 230220 658736.804456
11513 230240 658829.963275
11514 230260 658923.123490
11515 230280 659016.285102
11516 230300 659109.448111
11517 230320 659202.612516
11518 230340 659295.778319
11519 230360 659388.945517
11520 230380 659482.114112
11521 230400 659575.284103
11522 230420 659668.455490
11523 230440 659761.628272
11524 230460 659854.802451
11525 230480 659947.978024
11526 230500 660041.154994
11527 230520 660134.333358
11528 230540 660227.513117
11529 230560 660320.694272
11530 230580 660413.876821
11531 230600 660507.060765
11532 230620 660600.246103
11533 230640 660693.432835
11534 230660 660786.620962
11535 230680 660879.810483
11536 230700 660973.001398
11537 230720 661066.193706
11538 230740 661159.387408
11539 230760 661252.582504
11540 230780 661345.778993
11541 230800 661438.976875
11542 230820 661532.176150
11543 230840 661625.376817
11544 230860 661718.578878
11545 230880 661811.782331
11546 230900 661904.987177
11547 230920 661998.193415
11548 230940 662091.401045
11549 230960 662184.610067
11550 230980 662277.820481
11551 231000 662371.032287
11552 231020 662464.245484
11553 231040 662557.460072
11554 231060 662650.676052
11555 231080 662743.893423
11556 231100 662837.112185
11557 231120 662930.332338
11558 231140 663023.553881
11559 231160 663116.776816
11560 231180 663210.001140
11561 231200 663303.226855
11562 231220 663396.453959
11563 231240 663489.682454
11564 231260 663582.912339
11565 231280 663676.143613
11566 231300 663769.376277
11567 231320 663862.610330
11568 231340 663955.845772
11569 231360 664049.082604
11570 231380 664142.320824
11571 231400 664235.560433
11572 231420 664328.801431
11573 231440 664422.043818
11574 231460 664515.287592
11575 231480 664608.532755
11576 231500 664701.779306
11577 231520 664795.027245
11578 231540 664888.276572
11579 231560 664981.527286
11580 231580 665074.779388
11581 231600 665168.032877
11582 231620 665261.287754
11583 231640 665354.544017
11584 231660 665447.801667
11585 231680 665541.060704
11586 231700 665634.321128
11587 231720 665727.582938
11588 231740 665820.846135
11589 231760 665914.110718
11590 231780 666007.376687
11591 231800 666100.644041
11592 231820 666193.912782
11593 231840 666287.182908
11594 231860 666380.454419
11595 231880 666473.727316
11596 231900 666567.001598
11597 231920 666660.277265
11598 231940 666753.554317
11599 231960 666846.832754
11600 231980 666940.112575
11601 232000 667033.393781
11602 232020 667126.676371
11603 232040 667219.960345
11604 232060 667313.245703
11605 232080 667406.532445
11606 232100 667499.820571
11607 232120 667593.110081
11608 232140 667686.400973
11609 232160 667779.693250
11610 232180 667872.986909
11611 232200 667966.281951
11612 232220 668059.578377
11613 232240 668152.876184
11614 232260 668246.175375
11615 232280 668339.475948
11616 232300 668432.777903
11617 232320 668526.081241
11618 232340 668619.385960
11619 232360 668712.692061
11620 232380 668805.999544
11621 232400 668899.308409
11622 232420 668992.618655
11623 232440 669085.930282
11624 232460 669179.243290
11625 232480 669272.557680
11626 232500 669365.873450
11627 232520 669459.190601
11628 232540 669552.509132
11629 232560 669645.829044
11630 232580 669739.150337
11631 232600 669832.473009
11632 232620 669925.797061
11633 232640 670019.122494
11634 232660 670112.449305
11635 232680 670205.777497
11636 232700 670299.107068
11637 232720 670392.438018
11638 232740 670485.770347
11639 232760 670579.104056
11640 232780 670672.439143
11641 232800 670765.775609
11642 232820 670859.113453
11643 232840 670952.452676
11644 232860 671045.793277
11645 232880 671139.135256
11646 232900 671232.478613
11647 232920 671325.823348
11648 232940 671419.169461
11649 232960 671512.516952
11650 232980 671605.865819
11651 233000 671699.216064
11652 233020 671792.567686
11653 233040 671885.920685
11654 233060 671979.275061
11655 233080 672072.630814
11656 233100 672165.987943
11657 233120 672259.346449
11658 233140 672352.706331
11659 233160 672446.067589
11660 233180 672539.430223
11661 233200 672632.794233
11662 233220 672726.159618
11663 233240 672819.526380
11664 233260 672912.894516
11665 233280 673006.264028
11666 233300 673099.634915
11667 233320 673193.007177
11668 233340 673286.380814
11669 233360 673379.755825
11670 233380 673473.132211
11671 233400 673566.509972
11672 233420 673659.889106
11673 233440 673753.269615
11674 233460 673846.651498
11675 233480 673940.034755
11676 233500 674033.419385
11677 233520 674126.805389
11678 233540 674220.192767
11679 233560 674313.581517
11680 233580 674406.971641
11681 233600 674500.363138
11682 233620 674593.756008
11683 233640 674687.150250
11684 233660 674780.545865
11685 233680 674873.942853
11686 233700 674967.341212
11687 233720 675060.740944
11688 233740 675154.142048
11689 233760 675247.544524
11690 233780 675340.948371
11691 233800 675434.353590
11692 233820 675527.760181
11693 233840 675621.168142
11694 233860 675714.577475
11695 233880 675807.988179
11696 233900 675901.400254
11697 233920 675994.813699
11698 233940 676088.228515
11699 233960 676181.644702
11700 233980 676275.062259
11701 234000 676368.481186
11702 234020 676461.901483
11703 234040 676555.323150
11704 234060 676648.746186
11705 234080 676742.170592
11706 234100 676835.596368
11707 234120 676929.023513
11708 234140 677022.452027
11709 234160 677115.881910
11710 234180 677209.313162
11711 234200 677302.745783
11712 234220 677396.179773
11713 234240 677489.615130
11714 234260 677583.051857
11715 234280 677676.489951
11716 234300 677769.929413
11717 234320 677863.370244
11718 234340 677956.812442
11719 234360 678050.256007
11720 234380 678143.700941
11721 234400 678237.147241
11722 234420 678330.594909
11723 234440 678424.043944
11724 234460 678517.494345
11725 234480 678610.946114
11726 234500 678704.399249
11727 234520 678797.853750
11728 234540 678891.309618
11729 234560 678984.766852
11730 234580 679078.225453
11731 234600 679171.685419
11732 234620 679265.146751
11733 234640 679358.609448
11734 234660 679452.073511
11735 234680 679545.538939
11736 234700 679639.005733
11737 234720 679732.473892
11738 234740 679825.943415
11739 234760 679919.414304
11740 234780 680012.886557
11741 234800 680106.360175
11742 234820 680199.835157
11743 234840 680293.311503
11744 234860 680386.789213
11745 234880 680480.268288
11746 234900 680573.748726
11747 234920 680667.230528
11748 234940 680760.713693
11749 234960 680854.198222
11750 234980 680947.684114
11751 235000 681041.171369
11752 235020 681134.659987
11753 235040 681228.149968
11754 235060 681321.641311
11755 235080 681415.134018
11756 235100 681508.628086
11757 235120 681602.123517
11758 235140 681695.620310
11759 235160 681789.118465
11760 235180 681882.617982
11761 235200 681976.118861
11762 235220 682069.621101
11763 235240 682163.124702
11764 235260 682256.629665
11765 235280 682350.135989
11766 235300 682443.643675
11767 235320 682537.152720
11768 235340 682630.663127
11769 235360 682724.174894
11770 235380 682817.688022
11771 235400 682911.202510
11772 235420 683004.718359
11773 235440 683098.235567
11774 235460 683191.754135
11775 235480 683285.274063
11776 235500 683378.795351
11777 235520 683472.317998
11778 235540 683565.842004
11779 235560 683659.367370
11780 235580 683752.894094
11781 235600 683846.422178
11782 235620 683939.951620
11783 235640 684033.482421
11784 235660 684127.014581
11785 235680 684220.548099
11786 235700 684314.082975
11787 235720 684407.619209
11788 235740 684501.156801
11789 235760 684594.695751
11790 235780 684688.236059
11791 235800 684781.777724
11792 235820 684875.320747
11793 235840 684968.865127
11794 235860 685062.410864
11795 235880 685155.957957
11796 235900 685249.506408
11797 235920 685343.056216
11798 235940 685436.607380
11799 235960 685530.159900
11800 235980 685623.713777
11801 236000 685717.269010
11802 236020 685810.825599
11803 236040 685904.383543
11804 236060 685997.942844
11805 236080 686091.503500
11806 236100 686185.065511
11807 236120 686278.628878
11808 236140 686372.193600
11809 236160 686465.759677
11810 236180 686559.327109
11811 236200 686652.895896
11812 236220 686746.466037
11813 236240 686840.037533
11814 236260 686933.610383
11815 236280 687027.184587
11816 236300 687120.760146
11817 236320 687214.337058
11818 236340 687307.915324
11819 236360 687401.494944
11820 236380 687495.075917
11821 236400 687588.658244
11822 236420 687682.241923
11823 236440 687775.826956
11824 236460 687869.413342
11825 236480 687963.001081
11826 236500 688056.590172
11827 236520 688150.180616
11828 236540 688243.772413
11829 236560 688337.365561
11830 236580 688430.960062
11831 236600 688524.555915
11832 236620 688618.153119
11833 236640 688711.751676
11834 236660 688805.351583
11835 236680 688898.952843
11836 236700 688992.555453
11837 236720 689086.159415
11838 236740 689179.764728
11839 236760 689273.371392
11840 236780 689366.979406
11841 236800 689460.588771
11842 236820 689554.199487
11843 236840 689647.811552
11844 236860 689741.424968
11845 236880 689835.039735
11846 236900 689928.655851
11847 236920 690022.273316
11848 236940 690115.892132
11849 236960 690209.512297
11850 236980 690303.133811
11851 237000 690396.756675
11852 237020 690490.380887
11853 237040 690584.006449
11854 237060 690677.633360
11855 237080 690771.261619
11856 237100 690864.891226
11857 237120 690958.522183
11858 237140 691052.154487
11859 237160 691145.788139
11860 237180 691239.423140
11861 237200 691333.059488
11862 237220 691426.697184
11863 237240 691520.336228
11864 237260 691613.976619
11865 237280 691707.618358
11866 237300 691801.261443
11867 237320 691894.905876
11868 237340 691988.551656
11869 237360 692082.198782
11870 237380 692175.847255
11871 237400 692269.497074
11872 237420 692363.148240
11873 237440 692456.800752
11874 237460 692550.454610
11875 237480 692644.109814
11876 237500 692737.766364
11877 237520 692831.424260
11878 237540 692925.083501
11879 237560 693018.744087
11880 237580 693112.406019
11881 237600 693206.069296
11882 237620 693299.733917
11883 237640 693393.399884
11884 237660 693487.067196
11885 237680 693580.735851
11886 237700 693674.405852
11887 237720 693768.077197
11888 237740 693861.749885
11889 237760 693955.423918
11890 237780 694049.099295
11891 237800 694142.776016
11892 237820 694236.454080
11893 237840 694330.133487
11894 237860 694423.814238
11895 237880 694517.496333
11896 237900 694611.179770
11897 237920 694704.864550
11898 237940 694798.550673
11899 237960 694892.238139
11900 237980 694985.926947
11901 238000 695079.617098
11902 238020 695173.308590
11903 238040 695267.001425
11904 238060 695360.695602
11905 238080 695454.391121
11906 238100 695548.087982
11907 238120 695641.786184
11908 238140 695735.485727
11909 238160 695829.186612
11910 238180 695922.888838
11911 238200 696016.592405
11912 238220 696110.297313
11913 238240 696204.003562
11914 238260 696297.711151
11915 238280 696391.420081
11916 238300 696485.130351
11917 238320 696578.841962
11918 238340 696672.554912
11919 238360 696766.269203
11920 238380 696859.984833
11921 238400 696953.701803
11922 238420 697047.420112
11923 238440 697141.139761
11924 238460 697234.860749
11925 238480 697328.583077
11926 238500 697422.306743
11927 238520 697516.031748
11928 238540 697609.758092
11929 238560 697703.485774
11930 238580 697797.214795
11931 238600 697890.945154
11932 238620 697984.676852
11933 238640 698078.409887
11934 238660 698172.144260
11935 238680 698265.879972
11936 238700 698359.617020
11937 238720 698453.355407
11938 238740 698547.095130
11939 238760 698640.836191
11940 238780 698734.578589
11941 238800 698828.322324
11942 238820 698922.067396
11943 238840 699015.813805
11944 238860 699109.561550
11945 238880 699203.310631
11946 238900 699297.061049
11947 238920 699390.812803
11948 238940 699484.565893
11949 238960 699578.320319
11950 238980 699672.076080
11951 239000 699765.833177
11952 239020 699859.591610
11953 239040 699953.351378
11954 239060 700047.112481
11955 239080 700140.874920
11956 239100 700234.638693
11957 239120 700328.403801
11958 239140 700422.170244
11959 239160 700515.938021
11960 239180 700609.707133
11961 239200 700703.477579
11962 239220 700797.249359
11963 239240 700891.022473
11964 239260 700984.796921
11965 239280 701078.572703
11966 239300 701172.349818
11967 239320 701266.128267
11968 239340 701359.908049
11969 239360 701453.689164
11970 239380 701547.471612
11971 239400 701641.255394
11972 239420 701735.040508
11973 239440 701828.826954
11974 239460 701922.614734
11975 239480 702016.403845
11976 239500 702110.194289
11977 239520 702203.986065
11978 239540 702297.779173
11979 239560 702391.573613
11980 239580 702485.369385
11981 239600 702579.166488
11982 239620 702672.964922
11983 239640 702766.764688
11984 239660 702860.565785
11985 239680 702954.368213
11986 239700 703048.171972
11987 239720 703141.977062
11988 239740 703235.783483
11989 239760 703329.591234
11990 239780 703423.400315
11991 239800 703517.210726
11992 239820 703611.022468
11993 239840 703704.835540
11994 239860 703798.649941
11995 239880 703892.465672
11996 239900 703986.282733
11997 239920 704080.101123
11998 239940 704173.920843
11999 239960 704267.741892
12000 239980 704361.564269
12001 240000 704455.387976

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