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 30 of 40 · 500/page · 20000 rows next →
# nmargin_tilde
14502 290020 942953.954719
14503 290040 943050.741529
14504 290060 943147.529399
14505 290080 943244.318327
14506 290100 943341.108314
14507 290120 943437.899360
14508 290140 943534.691464
14509 290160 943631.484628
14510 290180 943728.278849
14511 290200 943825.074129
14512 290220 943921.870467
14513 290240 944018.667864
14514 290260 944115.466318
14515 290280 944212.265831
14516 290300 944309.066401
14517 290320 944405.868030
14518 290340 944502.670716
14519 290360 944599.474460
14520 290380 944696.279261
14521 290400 944793.085120
14522 290420 944889.892037
14523 290440 944986.700011
14524 290460 945083.509042
14525 290480 945180.319130
14526 290500 945277.130275
14527 290520 945373.942477
14528 290540 945470.755737
14529 290560 945567.570053
14530 290580 945664.385425
14531 290600 945761.201855
14532 290620 945858.019341
14533 290640 945954.837883
14534 290660 946051.657482
14535 290680 946148.478137
14536 290700 946245.299849
14537 290720 946342.122616
14538 290740 946438.946440
14539 290760 946535.771319
14540 290780 946632.597255
14541 290800 946729.424246
14542 290820 946826.252293
14543 290840 946923.081395
14544 290860 947019.911553
14545 290880 947116.742767
14546 290900 947213.575036
14547 290920 947310.408360
14548 290940 947407.242739
14549 290960 947504.078174
14550 290980 947600.914663
14551 291000 947697.752207
14552 291020 947794.590806
14553 291040 947891.430460
14554 291060 947988.271169
14555 291080 948085.112932
14556 291100 948181.955750
14557 291120 948278.799622
14558 291140 948375.644548
14559 291160 948472.490529
14560 291180 948569.337563
14561 291200 948666.185652
14562 291220 948763.034795
14563 291240 948859.884991
14564 291260 948956.736242
14565 291280 949053.588546
14566 291300 949150.441904
14567 291320 949247.296315
14568 291340 949344.151780
14569 291360 949441.008298
14570 291380 949537.865870
14571 291400 949634.724494
14572 291420 949731.584172
14573 291440 949828.444903
14574 291460 949925.306687
14575 291480 950022.169523
14576 291500 950119.033413
14577 291520 950215.898355
14578 291540 950312.764349
14579 291560 950409.631397
14580 291580 950506.499496
14581 291600 950603.368648
14582 291620 950700.238852
14583 291640 950797.110109
14584 291660 950893.982417
14585 291680 950990.855778
14586 291700 951087.730190
14587 291720 951184.605654
14588 291740 951281.482170
14589 291760 951378.359738
14590 291780 951475.238357
14591 291800 951572.118027
14592 291820 951668.998749
14593 291840 951765.880523
14594 291860 951862.763347
14595 291880 951959.647223
14596 291900 952056.532150
14597 291920 952153.418127
14598 291940 952250.305156
14599 291960 952347.193235
14600 291980 952444.082366
14601 292000 952540.972546
14602 292020 952637.863778
14603 292040 952734.756059
14604 292060 952831.649391
14605 292080 952928.543774
14606 292100 953025.439206
14607 292120 953122.335689
14608 292140 953219.233222
14609 292160 953316.131804
14610 292180 953413.031437
14611 292200 953509.932119
14612 292220 953606.833851
14613 292240 953703.736633
14614 292260 953800.640464
14615 292280 953897.545344
14616 292300 953994.451274
14617 292320 954091.358253
14618 292340 954188.266281
14619 292360 954285.175359
14620 292380 954382.085485
14621 292400 954478.996660
14622 292420 954575.908884
14623 292440 954672.822157
14624 292460 954769.736479
14625 292480 954866.651849
14626 292500 954963.568267
14627 292520 955060.485734
14628 292540 955157.404249
14629 292560 955254.323813
14630 292580 955351.244425
14631 292600 955448.166084
14632 292620 955545.088792
14633 292640 955642.012548
14634 292660 955738.937351
14635 292680 955835.863202
14636 292700 955932.790101
14637 292720 956029.718047
14638 292740 956126.647041
14639 292760 956223.577082
14640 292780 956320.508171
14641 292800 956417.440306
14642 292820 956514.373489
14643 292840 956611.307719
14644 292860 956708.242996
14645 292880 956805.179319
14646 292900 956902.116690
14647 292920 956999.055107
14648 292940 957095.994570
14649 292960 957192.935081
14650 292980 957289.876637
14651 293000 957386.819241
14652 293020 957483.762890
14653 293040 957580.707585
14654 293060 957677.653327
14655 293080 957774.600115
14656 293100 957871.547948
14657 293120 957968.496828
14658 293140 958065.446753
14659 293160 958162.397724
14660 293180 958259.349740
14661 293200 958356.302802
14662 293220 958453.256910
14663 293240 958550.212063
14664 293260 958647.168261
14665 293280 958744.125504
14666 293300 958841.083792
14667 293320 958938.043125
14668 293340 959035.003504
14669 293360 959131.964927
14670 293380 959228.927394
14671 293400 959325.890907
14672 293420 959422.855464
14673 293440 959519.821065
14674 293460 959616.787711
14675 293480 959713.755402
14676 293500 959810.724136
14677 293520 959907.693915
14678 293540 960004.664737
14679 293560 960101.636604
14680 293580 960198.609515
14681 293600 960295.583469
14682 293620 960392.558467
14683 293640 960489.534509
14684 293660 960586.511594
14685 293680 960683.489723
14686 293700 960780.468896
14687 293720 960877.449111
14688 293740 960974.430370
14689 293760 961071.412672
14690 293780 961168.396017
14691 293800 961265.380405
14692 293820 961362.365835
14693 293840 961459.352309
14694 293860 961556.339825
14695 293880 961653.328384
14696 293900 961750.317986
14697 293920 961847.308630
14698 293940 961944.300316
14699 293960 962041.293045
14700 293980 962138.286816
14701 294000 962235.281629
14702 294020 962332.277484
14703 294040 962429.274381
14704 294060 962526.272320
14705 294080 962623.271300
14706 294100 962720.271323
14707 294120 962817.272387
14708 294140 962914.274492
14709 294160 963011.277639
14710 294180 963108.281828
14711 294200 963205.287057
14712 294220 963302.293328
14713 294240 963399.300640
14714 294260 963496.308993
14715 294280 963593.318387
14716 294300 963690.328822
14717 294320 963787.340297
14718 294340 963884.352814
14719 294360 963981.366371
14720 294380 964078.380968
14721 294400 964175.396606
14722 294420 964272.413284
14723 294440 964369.431003
14724 294460 964466.449761
14725 294480 964563.469560
14726 294500 964660.490399
14727 294520 964757.512278
14728 294540 964854.535196
14729 294560 964951.559155
14730 294580 965048.584153
14731 294600 965145.610190
14732 294620 965242.637268
14733 294640 965339.665384
14734 294660 965436.694540
14735 294680 965533.724735
14736 294700 965630.755970
14737 294720 965727.788243
14738 294740 965824.821556
14739 294760 965921.855907
14740 294780 966018.891298
14741 294800 966115.927727
14742 294820 966212.965195
14743 294840 966310.003701
14744 294860 966407.043246
14745 294880 966504.083829
14746 294900 966601.125451
14747 294920 966698.168111
14748 294940 966795.211809
14749 294960 966892.256545
14750 294980 966989.302319
14751 295000 967086.349132
14752 295020 967183.396982
14753 295040 967280.445869
14754 295060 967377.495795
14755 295080 967474.546758
14756 295100 967571.598758
14757 295120 967668.651796
14758 295140 967765.705871
14759 295160 967862.760984
14760 295180 967959.817134
14761 295200 968056.874321
14762 295220 968153.932544
14763 295240 968250.991805
14764 295260 968348.052103
14765 295280 968445.113437
14766 295300 968542.175808
14767 295320 968639.239216
14768 295340 968736.303660
14769 295360 968833.369140
14770 295380 968930.435657
14771 295400 969027.503210
14772 295420 969124.571800
14773 295440 969221.641425
14774 295460 969318.712086
14775 295480 969415.783784
14776 295500 969512.856517
14777 295520 969609.930286
14778 295540 969707.005090
14779 295560 969804.080931
14780 295580 969901.157806
14781 295600 969998.235717
14782 295620 970095.314664
14783 295640 970192.394645
14784 295660 970289.475662
14785 295680 970386.557714
14786 295700 970483.640801
14787 295720 970580.724923
14788 295740 970677.810080
14789 295760 970774.896271
14790 295780 970871.983498
14791 295800 970969.071758
14792 295820 971066.161054
14793 295840 971163.251383
14794 295860 971260.342747
14795 295880 971357.435146
14796 295900 971454.528578
14797 295920 971551.623045
14798 295940 971648.718545
14799 295960 971745.815080
14800 295980 971842.912648
14801 296000 971940.011250
14802 296020 972037.110886
14803 296040 972134.211555
14804 296060 972231.313258
14805 296080 972328.415994
14806 296100 972425.519764
14807 296120 972522.624567
14808 296140 972619.730403
14809 296160 972716.837272
14810 296180 972813.945174
14811 296200 972911.054109
14812 296220 973008.164077
14813 296240 973105.275078
14814 296260 973202.387112
14815 296280 973299.500178
14816 296300 973396.614276
14817 296320 973493.729407
14818 296340 973590.845570
14819 296360 973687.962766
14820 296380 973785.080994
14821 296400 973882.200254
14822 296420 973979.320545
14823 296440 974076.441869
14824 296460 974173.564225
14825 296480 974270.687612
14826 296500 974367.812031
14827 296520 974464.937482
14828 296540 974562.063964
14829 296560 974659.191478
14830 296580 974756.320023
14831 296600 974853.449599
14832 296620 974950.580207
14833 296640 975047.711845
14834 296660 975144.844515
14835 296680 975241.978216
14836 296700 975339.112947
14837 296720 975436.248709
14838 296740 975533.385502
14839 296760 975630.523326
14840 296780 975727.662180
14841 296800 975824.802064
14842 296820 975921.942979
14843 296840 976019.084924
14844 296860 976116.227900
14845 296880 976213.371905
14846 296900 976310.516941
14847 296920 976407.663006
14848 296940 976504.810102
14849 296960 976601.958227
14850 296980 976699.107381
14851 297000 976796.257566
14852 297020 976893.408780
14853 297040 976990.561023
14854 297060 977087.714296
14855 297080 977184.868598
14856 297100 977282.023930
14857 297120 977379.180290
14858 297140 977476.337680
14859 297160 977573.496098
14860 297180 977670.655545
14861 297200 977767.816021
14862 297220 977864.977526
14863 297240 977962.140060
14864 297260 978059.303622
14865 297280 978156.468212
14866 297300 978253.633831
14867 297320 978350.800479
14868 297340 978447.968154
14869 297360 978545.136858
14870 297380 978642.306589
14871 297400 978739.477349
14872 297420 978836.649136
14873 297440 978933.821952
14874 297460 979030.995795
14875 297480 979128.170665
14876 297500 979225.346564
14877 297520 979322.523489
14878 297540 979419.701443
14879 297560 979516.880423
14880 297580 979614.060431
14881 297600 979711.241466
14882 297620 979808.423528
14883 297640 979905.606616
14884 297660 980002.790732
14885 297680 980099.975875
14886 297700 980197.162044
14887 297720 980294.349240
14888 297740 980391.537463
14889 297760 980488.726712
14890 297780 980585.916988
14891 297800 980683.108290
14892 297820 980780.300618
14893 297840 980877.493972
14894 297860 980974.688353
14895 297880 981071.883759
14896 297900 981169.080192
14897 297920 981266.277650
14898 297940 981363.476134
14899 297960 981460.675643
14900 297980 981557.876179
14901 298000 981655.077740
14902 298020 981752.280326
14903 298040 981849.483937
14904 298060 981946.688574
14905 298080 982043.894236
14906 298100 982141.100923
14907 298120 982238.308635
14908 298140 982335.517373
14909 298160 982432.727135
14910 298180 982529.937921
14911 298200 982627.149733
14912 298220 982724.362569
14913 298240 982821.576430
14914 298260 982918.791315
14915 298280 983016.007224
14916 298300 983113.224158
14917 298320 983210.442116
14918 298340 983307.661098
14919 298360 983404.881104
14920 298380 983502.102134
14921 298400 983599.324188
14922 298420 983696.547266
14923 298440 983793.771367
14924 298460 983890.996492
14925 298480 983988.222641
14926 298500 984085.449813
14927 298520 984182.678009
14928 298540 984279.907228
14929 298560 984377.137470
14930 298580 984474.368735
14931 298600 984571.601024
14932 298620 984668.834335
14933 298640 984766.068669
14934 298660 984863.304026
14935 298680 984960.540406
14936 298700 985057.777808
14937 298720 985155.016233
14938 298740 985252.255681
14939 298760 985349.496151
14940 298780 985446.737643
14941 298800 985543.980158
14942 298820 985641.223695
14943 298840 985738.468253
14944 298860 985835.713834
14945 298880 985932.960437
14946 298900 986030.208062
14947 298920 986127.456708
14948 298940 986224.706376
14949 298960 986321.957066
14950 298980 986419.208777
14951 299000 986516.461510
14952 299020 986613.715264
14953 299040 986710.970039
14954 299060 986808.225836
14955 299080 986905.482653
14956 299100 987002.740492
14957 299120 987099.999351
14958 299140 987197.259232
14959 299160 987294.520133
14960 299180 987391.782055
14961 299200 987489.044998
14962 299220 987586.308961
14963 299240 987683.573945
14964 299260 987780.839949
14965 299280 987878.106973
14966 299300 987975.375018
14967 299320 988072.644082
14968 299340 988169.914167
14969 299360 988267.185272
14970 299380 988364.457397
14971 299400 988461.730541
14972 299420 988559.004705
14973 299440 988656.279889
14974 299460 988753.556093
14975 299480 988850.833316
14976 299500 988948.111558
14977 299520 989045.390820
14978 299540 989142.671101
14979 299560 989239.952401
14980 299580 989337.234720
14981 299600 989434.518059
14982 299620 989531.802416
14983 299640 989629.087792
14984 299660 989726.374187
14985 299680 989823.661600
14986 299700 989920.950032
14987 299720 990018.239483
14988 299740 990115.529952
14989 299760 990212.821440
14990 299780 990310.113945
14991 299800 990407.407469
14992 299820 990504.702011
14993 299840 990601.997572
14994 299860 990699.294150
14995 299880 990796.591746
14996 299900 990893.890359
14997 299920 990991.189991
14998 299940 991088.490640
14999 299960 991185.792307
15000 299980 991283.094991
15001 300000 991380.398693

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