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 10 of 40 · 500/page · 20000 rows next →
# nmargin_tilde
4502 90020 53603.496617
4503 90040 53679.712993
4504 90060 53755.933912
4505 90080 53832.159373
4506 90100 53908.389374
4507 90120 53984.623914
4508 90140 54060.862992
4509 90160 54137.106607
4510 90180 54213.354757
4511 90200 54289.607440
4512 90220 54365.864656
4513 90240 54442.126404
4514 90260 54518.392681
4515 90280 54594.663487
4516 90300 54670.938820
4517 90320 54747.218679
4518 90340 54823.503062
4519 90360 54899.791969
4520 90380 54976.085398
4521 90400 55052.383348
4522 90420 55128.685817
4523 90440 55204.992804
4524 90460 55281.304309
4525 90480 55357.620328
4526 90500 55433.940862
4527 90520 55510.265909
4528 90540 55586.595467
4529 90560 55662.929536
4530 90580 55739.268113
4531 90600 55815.611199
4532 90620 55891.958790
4533 90640 55968.310887
4534 90660 56044.667488
4535 90680 56121.028591
4536 90700 56197.394195
4537 90720 56273.764299
4538 90740 56350.138902
4539 90760 56426.518002
4540 90780 56502.901599
4541 90800 56579.289690
4542 90820 56655.682274
4543 90840 56732.079350
4544 90860 56808.480918
4545 90880 56884.886975
4546 90900 56961.297520
4547 90920 57037.712552
4548 90940 57114.132070
4549 90960 57190.556072
4550 90980 57266.984558
4551 91000 57343.417525
4552 91020 57419.854973
4553 91040 57496.296900
4554 91060 57572.743305
4555 91080 57649.194187
4556 91100 57725.649544
4557 91120 57802.109376
4558 91140 57878.573680
4559 91160 57955.042456
4560 91180 58031.515702
4561 91200 58107.993417
4562 91220 58184.475600
4563 91240 58260.962249
4564 91260 58337.453363
4565 91280 58413.948942
4566 91300 58490.448983
4567 91320 58566.953485
4568 91340 58643.462447
4569 91360 58719.975869
4570 91380 58796.493747
4571 91400 58873.016082
4572 91420 58949.542872
4573 91440 59026.074116
4574 91460 59102.609812
4575 91480 59179.149959
4576 91500 59255.694556
4577 91520 59332.243602
4578 91540 59408.797095
4579 91560 59485.355035
4580 91580 59561.917419
4581 91600 59638.484246
4582 91620 59715.055516
4583 91640 59791.631227
4584 91660 59868.211378
4585 91680 59944.795967
4586 91700 60021.384994
4587 91720 60097.978456
4588 91740 60174.576353
4589 91760 60251.178684
4590 91780 60327.785446
4591 91800 60404.396640
4592 91820 60481.012264
4593 91840 60557.632315
4594 91860 60634.256794
4595 91880 60710.885699
4596 91900 60787.519029
4597 91920 60864.156781
4598 91940 60940.798956
4599 91960 61017.445552
4600 91980 61094.096568
4601 92000 61170.752002
4602 92020 61247.411853
4603 92040 61324.076120
4604 92060 61400.744801
4605 92080 61477.417896
4606 92100 61554.095403
4607 92120 61630.777321
4608 92140 61707.463648
4609 92160 61784.154384
4610 92180 61860.849527
4611 92200 61937.549076
4612 92220 62014.253029
4613 92240 62090.961386
4614 92260 62167.674145
4615 92280 62244.391305
4616 92300 62321.112864
4617 92320 62397.838822
4618 92340 62474.569177
4619 92360 62551.303928
4620 92380 62628.043074
4621 92400 62704.786613
4622 92420 62781.534544
4623 92440 62858.286867
4624 92460 62935.043579
4625 92480 63011.804679
4626 92500 63088.570167
4627 92520 63165.340041
4628 92540 63242.114299
4629 92560 63318.892941
4630 92580 63395.675966
4631 92600 63472.463371
4632 92620 63549.255156
4633 92640 63626.051320
4634 92660 63702.851862
4635 92680 63779.656779
4636 92700 63856.466072
4637 92720 63933.279738
4638 92740 64010.097776
4639 92760 64086.920186
4640 92780 64163.746966
4641 92800 64240.578114
4642 92820 64317.413630
4643 92840 64394.253512
4644 92860 64471.097760
4645 92880 64547.946371
4646 92900 64624.799345
4647 92920 64701.656681
4648 92940 64778.518376
4649 92960 64855.384431
4650 92980 64932.254843
4651 93000 65009.129612
4652 93020 65086.008736
4653 93040 65162.892214
4654 93060 65239.780045
4655 93080 65316.672228
4656 93100 65393.568761
4657 93120 65470.469644
4658 93140 65547.374874
4659 93160 65624.284452
4660 93180 65701.198374
4661 93200 65778.116641
4662 93220 65855.039252
4663 93240 65931.966204
4664 93260 66008.897497
4665 93280 66085.833129
4666 93300 66162.773100
4667 93320 66239.717408
4668 93340 66316.666051
4669 93360 66393.619030
4670 93380 66470.576341
4671 93400 66547.537985
4672 93420 66624.503961
4673 93440 66701.474265
4674 93460 66778.448899
4675 93480 66855.427860
4676 93500 66932.411147
4677 93520 67009.398759
4678 93540 67086.390695
4679 93560 67163.386953
4680 93580 67240.387533
4681 93600 67317.392433
4682 93620 67394.401652
4683 93640 67471.415189
4684 93660 67548.433042
4685 93680 67625.455211
4686 93700 67702.481694
4687 93720 67779.512490
4688 93740 67856.547598
4689 93760 67933.587016
4690 93780 68010.630744
4691 93800 68087.678780
4692 93820 68164.731123
4693 93840 68241.787771
4694 93860 68318.848725
4695 93880 68395.913982
4696 93900 68472.983540
4697 93920 68550.057400
4698 93940 68627.135560
4699 93960 68704.218019
4700 93980 68781.304775
4701 94000 68858.395827
4702 94020 68935.491174
4703 94040 69012.590815
4704 94060 69089.694749
4705 94080 69166.802974
4706 94100 69243.915490
4707 94120 69321.032295
4708 94140 69398.153388
4709 94160 69475.278767
4710 94180 69552.408432
4711 94200 69629.542382
4712 94220 69706.680615
4713 94240 69783.823129
4714 94260 69860.969925
4715 94280 69938.121000
4716 94300 70015.276354
4717 94320 70092.435985
4718 94340 70169.599892
4719 94360 70246.768074
4720 94380 70323.940530
4721 94400 70401.117258
4722 94420 70478.298258
4723 94440 70555.483528
4724 94460 70632.673067
4725 94480 70709.866874
4726 94500 70787.064948
4727 94520 70864.267287
4728 94540 70941.473891
4729 94560 71018.684758
4730 94580 71095.899886
4731 94600 71173.119276
4732 94620 71250.342925
4733 94640 71327.570833
4734 94660 71404.802998
4735 94680 71482.039419
4736 94700 71559.280095
4737 94720 71636.525025
4738 94740 71713.774208
4739 94760 71791.027642
4740 94780 71868.285327
4741 94800 71945.547260
4742 94820 72022.813442
4743 94840 72100.083870
4744 94860 72177.358544
4745 94880 72254.637463
4746 94900 72331.920624
4747 94920 72409.208028
4748 94940 72486.499673
4749 94960 72563.795558
4750 94980 72641.095682
4751 95000 72718.400043
4752 95020 72795.708640
4753 95040 72873.021472
4754 95060 72950.338539
4755 95080 73027.659838
4756 95100 73104.985369
4757 95120 73182.315131
4758 95140 73259.649122
4759 95160 73336.987342
4760 95180 73414.329788
4761 95200 73491.676460
4762 95220 73569.027358
4763 95240 73646.382478
4764 95260 73723.741822
4765 95280 73801.105386
4766 95300 73878.473171
4767 95320 73955.845175
4768 95340 74033.221396
4769 95360 74110.601835
4770 95380 74187.986489
4771 95400 74265.375357
4772 95420 74342.768439
4773 95440 74420.165732
4774 95460 74497.567237
4775 95480 74574.972952
4776 95500 74652.382875
4777 95520 74729.797006
4778 95540 74807.215343
4779 95560 74884.637885
4780 95580 74962.064632
4781 95600 75039.495581
4782 95620 75116.930733
4783 95640 75194.370085
4784 95660 75271.813636
4785 95680 75349.261386
4786 95700 75426.713333
4787 95720 75504.169477
4788 95740 75581.629815
4789 95760 75659.094347
4790 95780 75736.563072
4791 95800 75814.035988
4792 95820 75891.513095
4793 95840 75968.994391
4794 95860 76046.479875
4795 95880 76123.969546
4796 95900 76201.463403
4797 95920 76278.961445
4798 95940 76356.463671
4799 95960 76433.970079
4800 95980 76511.480668
4801 96000 76588.995438
4802 96020 76666.514386
4803 96040 76744.037513
4804 96060 76821.564816
4805 96080 76899.096295
4806 96100 76976.631949
4807 96120 77054.171776
4808 96140 77131.715775
4809 96160 77209.263946
4810 96180 77286.816286
4811 96200 77364.372796
4812 96220 77441.933473
4813 96240 77519.498317
4814 96260 77597.067327
4815 96280 77674.640501
4816 96300 77752.217838
4817 96320 77829.799338
4818 96340 77907.384998
4819 96360 77984.974819
4820 96380 78062.568798
4821 96400 78140.166935
4822 96420 78217.769229
4823 96440 78295.375678
4824 96460 78372.986281
4825 96480 78450.601038
4826 96500 78528.219946
4827 96520 78605.843006
4828 96540 78683.470216
4829 96560 78761.101574
4830 96580 78838.737080
4831 96600 78916.376732
4832 96620 78994.020530
4833 96640 79071.668472
4834 96660 79149.320558
4835 96680 79226.976785
4836 96700 79304.637153
4837 96720 79382.301662
4838 96740 79459.970308
4839 96760 79537.643093
4840 96780 79615.320014
4841 96800 79693.001070
4842 96820 79770.686261
4843 96840 79848.375585
4844 96860 79926.069041
4845 96880 80003.766628
4846 96900 80081.468345
4847 96920 80159.174190
4848 96940 80236.884163
4849 96960 80314.598263
4850 96980 80392.316488
4851 97000 80470.038838
4852 97020 80547.765310
4853 97040 80625.495905
4854 97060 80703.230621
4855 97080 80780.969457
4856 97100 80858.712411
4857 97120 80936.459484
4858 97140 81014.210673
4859 97160 81091.965977
4860 97180 81169.725396
4861 97200 81247.488928
4862 97220 81325.256572
4863 97240 81403.028328
4864 97260 81480.804193
4865 97280 81558.584168
4866 97300 81636.368250
4867 97320 81714.156439
4868 97340 81791.948734
4869 97360 81869.745133
4870 97380 81947.545636
4871 97400 82025.350241
4872 97420 82103.158947
4873 97440 82180.971754
4874 97460 82258.788659
4875 97480 82336.609663
4876 97500 82414.434763
4877 97520 82492.263959
4878 97540 82570.097250
4879 97560 82647.934635
4880 97580 82725.776112
4881 97600 82803.621681
4882 97620 82881.471340
4883 97640 82959.325088
4884 97660 83037.182924
4885 97680 83115.044848
4886 97700 83192.910857
4887 97720 83270.780952
4888 97740 83348.655130
4889 97760 83426.533391
4890 97780 83504.415734
4891 97800 83582.302158
4892 97820 83660.192660
4893 97840 83738.087242
4894 97860 83815.985901
4895 97880 83893.888636
4896 97900 83971.795446
4897 97920 84049.706330
4898 97940 84127.621287
4899 97960 84205.540317
4900 97980 84283.463417
4901 98000 84361.390587
4902 98020 84439.321826
4903 98040 84517.257132
4904 98060 84595.196505
4905 98080 84673.139943
4906 98100 84751.087446
4907 98120 84829.039012
4908 98140 84906.994641
4909 98160 84984.954330
4910 98180 85062.918080
4911 98200 85140.885889
4912 98220 85218.857756
4913 98240 85296.833680
4914 98260 85374.813659
4915 98280 85452.797694
4916 98300 85530.785782
4917 98320 85608.777922
4918 98340 85686.774115
4919 98360 85764.774358
4920 98380 85842.778650
4921 98400 85920.786990
4922 98420 85998.799378
4923 98440 86076.815812
4924 98460 86154.836291
4925 98480 86232.860815
4926 98500 86310.889381
4927 98520 86388.921990
4928 98540 86466.958639
4929 98560 86544.999328
4930 98580 86623.044056
4931 98600 86701.092821
4932 98620 86779.145624
4933 98640 86857.202462
4934 98660 86935.263334
4935 98680 87013.328240
4936 98700 87091.397178
4937 98720 87169.470148
4938 98740 87247.547148
4939 98760 87325.628177
4940 98780 87403.713234
4941 98800 87481.802319
4942 98820 87559.895429
4943 98840 87637.992565
4944 98860 87716.093724
4945 98880 87794.198907
4946 98900 87872.308111
4947 98920 87950.421336
4948 98940 88028.538581
4949 98960 88106.659845
4950 98980 88184.785126
4951 99000 88262.914424
4952 99020 88341.047737
4953 99040 88419.185065
4954 99060 88497.326406
4955 99080 88575.471759
4956 99100 88653.621124
4957 99120 88731.774500
4958 99140 88809.931884
4959 99160 88888.093277
4960 99180 88966.258676
4961 99200 89044.428082
4962 99220 89122.601493
4963 99240 89200.778908
4964 99260 89278.960326
4965 99280 89357.145746
4966 99300 89435.335167
4967 99320 89513.528587
4968 99340 89591.726006
4969 99360 89669.927424
4970 99380 89748.132837
4971 99400 89826.342247
4972 99420 89904.555651
4973 99440 89982.773048
4974 99460 90060.994438
4975 99480 90139.219820
4976 99500 90217.449192
4977 99520 90295.682554
4978 99540 90373.919904
4979 99560 90452.161241
4980 99580 90530.406564
4981 99600 90608.655873
4982 99620 90686.909166
4983 99640 90765.166442
4984 99660 90843.427701
4985 99680 90921.692940
4986 99700 90999.962160
4987 99720 91078.235359
4988 99740 91156.512535
4989 99760 91234.793689
4990 99780 91313.078819
4991 99800 91391.367923
4992 99820 91469.661002
4993 99840 91547.958053
4994 99860 91626.259076
4995 99880 91704.564070
4996 99900 91782.873034
4997 99920 91861.185966
4998 99940 91939.502867
4999 99960 92017.823734
5000 99980 92096.148566
5001 100000 92174.477363

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