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 22 of 40 · 500/page · 20000 rows next →
# nmargin_tilde
10502 210020 565386.342351
10503 210040 565478.009702
10504 210060 565569.678614
10505 210080 565661.349088
10506 210100 565753.021123
10507 210120 565844.694720
10508 210140 565936.369878
10509 210160 566028.046597
10510 210180 566119.724877
10511 210200 566211.404718
10512 210220 566303.086119
10513 210240 566394.769080
10514 210260 566486.453601
10515 210280 566578.139682
10516 210300 566669.827323
10517 210320 566761.516523
10518 210340 566853.207283
10519 210360 566944.899602
10520 210380 567036.593480
10521 210400 567128.288916
10522 210420 567219.985912
10523 210440 567311.684465
10524 210460 567403.384577
10525 210480 567495.086248
10526 210500 567586.789476
10527 210520 567678.494261
10528 210540 567770.200605
10529 210560 567861.908505
10530 210580 567953.617963
10531 210600 568045.328978
10532 210620 568137.041550
10533 210640 568228.755678
10534 210660 568320.471363
10535 210680 568412.188604
10536 210700 568503.907401
10537 210720 568595.627754
10538 210740 568687.349663
10539 210760 568779.073128
10540 210780 568870.798147
10541 210800 568962.524722
10542 210820 569054.252852
10543 210840 569145.982537
10544 210860 569237.713777
10545 210880 569329.446571
10546 210900 569421.180919
10547 210920 569512.916822
10548 210940 569604.654278
10549 210960 569696.393289
10550 210980 569788.133852
10551 211000 569879.875970
10552 211020 569971.619640
10553 211040 570063.364864
10554 211060 570155.111640
10555 211080 570246.859969
10556 211100 570338.609851
10557 211120 570430.361285
10558 211140 570522.114271
10559 211160 570613.868809
10560 211180 570705.624899
10561 211200 570797.382540
10562 211220 570889.141733
10563 211240 570980.902477
10564 211260 571072.664773
10565 211280 571164.428619
10566 211300 571256.194016
10567 211320 571347.960963
10568 211340 571439.729461
10569 211360 571531.499509
10570 211380 571623.271107
10571 211400 571715.044255
10572 211420 571806.818953
10573 211440 571898.595200
10574 211460 571990.372996
10575 211480 572082.152342
10576 211500 572173.933236
10577 211520 572265.715679
10578 211540 572357.499671
10579 211560 572449.285211
10580 211580 572541.072299
10581 211600 572632.860936
10582 211620 572724.651120
10583 211640 572816.442852
10584 211660 572908.236131
10585 211680 573000.030958
10586 211700 573091.827332
10587 211720 573183.625253
10588 211740 573275.424721
10589 211760 573367.225735
10590 211780 573459.028296
10591 211800 573550.832403
10592 211820 573642.638057
10593 211840 573734.445256
10594 211860 573826.254001
10595 211880 573918.064291
10596 211900 574009.876127
10597 211920 574101.689508
10598 211940 574193.504434
10599 211960 574285.320905
10600 211980 574377.138921
10601 212000 574468.958481
10602 212020 574560.779585
10603 212040 574652.602233
10604 212060 574744.426426
10605 212080 574836.252162
10606 212100 574928.079442
10607 212120 575019.908265
10608 212140 575111.738632
10609 212160 575203.570542
10610 212180 575295.403994
10611 212200 575387.238989
10612 212220 575479.075527
10613 212240 575570.913607
10614 212260 575662.753230
10615 212280 575754.594394
10616 212300 575846.437100
10617 212320 575938.281348
10618 212340 576030.127138
10619 212360 576121.974468
10620 212380 576213.823340
10621 212400 576305.673753
10622 212420 576397.525707
10623 212440 576489.379201
10624 212460 576581.234235
10625 212480 576673.090810
10626 212500 576764.948925
10627 212520 576856.808580
10628 212540 576948.669774
10629 212560 577040.532508
10630 212580 577132.396782
10631 212600 577224.262594
10632 212620 577316.129946
10633 212640 577407.998836
10634 212660 577499.869266
10635 212680 577591.741233
10636 212700 577683.614739
10637 212720 577775.489783
10638 212740 577867.366365
10639 212760 577959.244485
10640 212780 578051.124142
10641 212800 578143.005337
10642 212820 578234.888069
10643 212840 578326.772338
10644 212860 578418.658144
10645 212880 578510.545487
10646 212900 578602.434367
10647 212920 578694.324782
10648 212940 578786.216734
10649 212960 578878.110222
10650 212980 578970.005246
10651 213000 579061.901805
10652 213020 579153.799900
10653 213040 579245.699531
10654 213060 579337.600696
10655 213080 579429.503396
10656 213100 579521.407632
10657 213120 579613.313401
10658 213140 579705.220706
10659 213160 579797.129544
10660 213180 579889.039917
10661 213200 579980.951823
10662 213220 580072.865264
10663 213240 580164.780238
10664 213260 580256.696745
10665 213280 580348.614785
10666 213300 580440.534359
10667 213320 580532.455465
10668 213340 580624.378104
10669 213360 580716.302276
10670 213380 580808.227980
10671 213400 580900.155216
10672 213420 580992.083984
10673 213440 581084.014284
10674 213460 581175.946116
10675 213480 581267.879479
10676 213500 581359.814373
10677 213520 581451.750798
10678 213540 581543.688755
10679 213560 581635.628242
10680 213580 581727.569260
10681 213600 581819.511808
10682 213620 581911.455887
10683 213640 582003.401495
10684 213660 582095.348634
10685 213680 582187.297302
10686 213700 582279.247499
10687 213720 582371.199227
10688 213740 582463.152483
10689 213760 582555.107268
10690 213780 582647.063582
10691 213800 582739.021425
10692 213820 582830.980797
10693 213840 582922.941696
10694 213860 583014.904124
10695 213880 583106.868080
10696 213900 583198.833564
10697 213920 583290.800575
10698 213940 583382.769114
10699 213960 583474.739180
10700 213980 583566.710773
10701 214000 583658.683894
10702 214020 583750.658540
10703 214040 583842.634714
10704 214060 583934.612414
10705 214080 584026.591640
10706 214100 584118.572392
10707 214120 584210.554671
10708 214140 584302.538475
10709 214160 584394.523804
10710 214180 584486.510659
10711 214200 584578.499039
10712 214220 584670.488944
10713 214240 584762.480374
10714 214260 584854.473329
10715 214280 584946.467808
10716 214300 585038.463811
10717 214320 585130.461339
10718 214340 585222.460391
10719 214360 585314.460966
10720 214380 585406.463066
10721 214400 585498.466688
10722 214420 585590.471834
10723 214440 585682.478503
10724 214460 585774.486695
10725 214480 585866.496410
10726 214500 585958.507648
10727 214520 586050.520408
10728 214540 586142.534690
10729 214560 586234.550494
10730 214580 586326.567820
10731 214600 586418.586668
10732 214620 586510.607038
10733 214640 586602.628929
10734 214660 586694.652341
10735 214680 586786.677274
10736 214700 586878.703728
10737 214720 586970.731703
10738 214740 587062.761199
10739 214760 587154.792214
10740 214780 587246.824750
10741 214800 587338.858806
10742 214820 587430.894382
10743 214840 587522.931478
10744 214860 587614.970093
10745 214880 587707.010227
10746 214900 587799.051881
10747 214920 587891.095054
10748 214940 587983.139745
10749 214960 588075.185955
10750 214980 588167.233684
10751 215000 588259.282930
10752 215020 588351.333695
10753 215040 588443.385978
10754 215060 588535.439779
10755 215080 588627.495098
10756 215100 588719.551933
10757 215120 588811.610286
10758 215140 588903.670157
10759 215160 588995.731544
10760 215180 589087.794448
10761 215200 589179.858868
10762 215220 589271.924805
10763 215240 589363.992258
10764 215260 589456.061228
10765 215280 589548.131713
10766 215300 589640.203714
10767 215320 589732.277230
10768 215340 589824.352262
10769 215360 589916.428809
10770 215380 590008.506872
10771 215400 590100.586449
10772 215420 590192.667540
10773 215440 590284.750147
10774 215460 590376.834267
10775 215480 590468.919902
10776 215500 590561.007051
10777 215520 590653.095714
10778 215540 590745.185890
10779 215560 590837.277580
10780 215580 590929.370784
10781 215600 591021.465500
10782 215620 591113.561730
10783 215640 591205.659472
10784 215660 591297.758727
10785 215680 591389.859494
10786 215700 591481.961774
10787 215720 591574.065566
10788 215740 591666.170870
10789 215760 591758.277686
10790 215780 591850.386013
10791 215800 591942.495852
10792 215820 592034.607202
10793 215840 592126.720063
10794 215860 592218.834436
10795 215880 592310.950319
10796 215900 592403.067712
10797 215920 592495.186616
10798 215940 592587.307031
10799 215960 592679.428955
10800 215980 592771.552389
10801 216000 592863.677334
10802 216020 592955.803787
10803 216040 593047.931751
10804 216060 593140.061223
10805 216080 593232.192205
10806 216100 593324.324695
10807 216120 593416.458694
10808 216140 593508.594202
10809 216160 593600.731218
10810 216180 593692.869743
10811 216200 593785.009775
10812 216220 593877.151316
10813 216240 593969.294364
10814 216260 594061.438919
10815 216280 594153.584982
10816 216300 594245.732553
10817 216320 594337.881630
10818 216340 594430.032214
10819 216360 594522.184305
10820 216380 594614.337903
10821 216400 594706.493007
10822 216420 594798.649617
10823 216440 594890.807733
10824 216460 594982.967355
10825 216480 595075.128483
10826 216500 595167.291116
10827 216520 595259.455254
10828 216540 595351.620898
10829 216560 595443.788047
10830 216580 595535.956701
10831 216600 595628.126859
10832 216620 595720.298522
10833 216640 595812.471689
10834 216660 595904.646360
10835 216680 595996.822536
10836 216700 596089.000215
10837 216720 596181.179398
10838 216740 596273.360084
10839 216760 596365.542274
10840 216780 596457.725967
10841 216800 596549.911163
10842 216820 596642.097862
10843 216840 596734.286063
10844 216860 596826.475767
10845 216880 596918.666973
10846 216900 597010.859681
10847 216920 597103.053892
10848 216940 597195.249604
10849 216960 597287.446818
10850 216980 597379.645533
10851 217000 597471.845750
10852 217020 597564.047467
10853 217040 597656.250686
10854 217060 597748.455406
10855 217080 597840.661626
10856 217100 597932.869347
10857 217120 598025.078568
10858 217140 598117.289289
10859 217160 598209.501510
10860 217180 598301.715231
10861 217200 598393.930451
10862 217220 598486.147171
10863 217240 598578.365390
10864 217260 598670.585109
10865 217280 598762.806326
10866 217300 598855.029042
10867 217320 598947.253257
10868 217340 599039.478970
10869 217360 599131.706182
10870 217380 599223.934892
10871 217400 599316.165099
10872 217420 599408.396805
10873 217440 599500.630008
10874 217460 599592.864708
10875 217480 599685.100906
10876 217500 599777.338601
10877 217520 599869.577793
10878 217540 599961.818482
10879 217560 600054.060667
10880 217580 600146.304349
10881 217600 600238.549527
10882 217620 600330.796201
10883 217640 600423.044371
10884 217660 600515.294037
10885 217680 600607.545198
10886 217700 600699.797855
10887 217720 600792.052007
10888 217740 600884.307655
10889 217760 600976.564797
10890 217780 601068.823434
10891 217800 601161.083566
10892 217820 601253.345192
10893 217840 601345.608312
10894 217860 601437.872927
10895 217880 601530.139035
10896 217900 601622.406638
10897 217920 601714.675734
10898 217940 601806.946323
10899 217960 601899.218406
10900 217980 601991.491981
10901 218000 602083.767050
10902 218020 602176.043611
10903 218040 602268.321665
10904 218060 602360.601212
10905 218080 602452.882251
10906 218100 602545.164782
10907 218120 602637.448805
10908 218140 602729.734319
10909 218160 602822.021326
10910 218180 602914.309823
10911 218200 603006.599812
10912 218220 603098.891293
10913 218240 603191.184264
10914 218260 603283.478726
10915 218280 603375.774678
10916 218300 603468.072121
10917 218320 603560.371054
10918 218340 603652.671478
10919 218360 603744.973391
10920 218380 603837.276794
10921 218400 603929.581687
10922 218420 604021.888069
10923 218440 604114.195941
10924 218460 604206.505302
10925 218480 604298.816151
10926 218500 604391.128490
10927 218520 604483.442317
10928 218540 604575.757632
10929 218560 604668.074436
10930 218580 604760.392728
10931 218600 604852.712508
10932 218620 604945.033776
10933 218640 605037.356531
10934 218660 605129.680774
10935 218680 605222.006505
10936 218700 605314.333722
10937 218720 605406.662426
10938 218740 605498.992617
10939 218760 605591.324295
10940 218780 605683.657460
10941 218800 605775.992110
10942 218820 605868.328247
10943 218840 605960.665870
10944 218860 606053.004978
10945 218880 606145.345573
10946 218900 606237.687652
10947 218920 606330.031217
10948 218940 606422.376268
10949 218960 606514.722803
10950 218980 606607.070823
10951 219000 606699.420328
10952 219020 606791.771317
10953 219040 606884.123791
10954 219060 606976.477748
10955 219080 607068.833190
10956 219100 607161.190116
10957 219120 607253.548525
10958 219140 607345.908418
10959 219160 607438.269794
10960 219180 607530.632654
10961 219200 607622.996996
10962 219220 607715.362822
10963 219240 607807.730130
10964 219260 607900.098920
10965 219280 607992.469193
10966 219300 608084.840948
10967 219320 608177.214185
10968 219340 608269.588904
10969 219360 608361.965105
10970 219380 608454.342787
10971 219400 608546.721951
10972 219420 608639.102596
10973 219440 608731.484722
10974 219460 608823.868329
10975 219480 608916.253417
10976 219500 609008.639985
10977 219520 609101.028033
10978 219540 609193.417562
10979 219560 609285.808571
10980 219580 609378.201060
10981 219600 609470.595028
10982 219620 609562.990476
10983 219640 609655.387404
10984 219660 609747.785811
10985 219680 609840.185697
10986 219700 609932.587062
10987 219720 610024.989905
10988 219740 610117.394227
10989 219760 610209.800028
10990 219780 610302.207307
10991 219800 610394.616064
10992 219820 610487.026299
10993 219840 610579.438012
10994 219860 610671.851202
10995 219880 610764.265870
10996 219900 610856.682015
10997 219920 610949.099638
10998 219940 611041.518737
10999 219960 611133.939313
11000 219980 611226.361366
11001 220000 611318.784895

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