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 6 of 40 · 500/page · 20000 rows next →
# nmargin_tilde
2502 50020 -87290.844508
2503 50040 -87227.892249
2504 50060 -87164.929992
2505 50080 -87101.957744
2506 50100 -87038.975509
2507 50120 -86975.983293
2508 50140 -86912.981101
2509 50160 -86849.968940
2510 50180 -86786.946814
2511 50200 -86723.914729
2512 50220 -86660.872691
2513 50240 -86597.820704
2514 50260 -86534.758775
2515 50280 -86471.686909
2516 50300 -86408.605111
2517 50320 -86345.513387
2518 50340 -86282.411742
2519 50360 -86219.300181
2520 50380 -86156.178711
2521 50400 -86093.047336
2522 50420 -86029.906062
2523 50440 -85966.754895
2524 50460 -85903.593839
2525 50480 -85840.422900
2526 50500 -85777.242084
2527 50520 -85714.051396
2528 50540 -85650.850841
2529 50560 -85587.640425
2530 50580 -85524.420153
2531 50600 -85461.190030
2532 50620 -85397.950062
2533 50640 -85334.700255
2534 50660 -85271.440613
2535 50680 -85208.171142
2536 50700 -85144.891847
2537 50720 -85081.602733
2538 50740 -85018.303807
2539 50760 -84954.995073
2540 50780 -84891.676536
2541 50800 -84828.348203
2542 50820 -84765.010077
2543 50840 -84701.662165
2544 50860 -84638.304472
2545 50880 -84574.937004
2546 50900 -84511.559764
2547 50920 -84448.172759
2548 50940 -84384.775995
2549 50960 -84321.369475
2550 50980 -84257.953206
2551 51000 -84194.527193
2552 51020 -84131.091441
2553 51040 -84067.645956
2554 51060 -84004.190742
2555 51080 -83940.725805
2556 51100 -83877.251150
2557 51120 -83813.766782
2558 51140 -83750.272707
2559 51160 -83686.768930
2560 51180 -83623.255455
2561 51200 -83559.732289
2562 51220 -83496.199437
2563 51240 -83432.656903
2564 51260 -83369.104693
2565 51280 -83305.542812
2566 51300 -83241.971265
2567 51320 -83178.390058
2568 51340 -83114.799196
2569 51360 -83051.198683
2570 51380 -82987.588525
2571 51400 -82923.968728
2572 51420 -82860.339295
2573 51440 -82796.700234
2574 51460 -82733.051547
2575 51480 -82669.393242
2576 51500 -82605.725323
2577 51520 -82542.047794
2578 51540 -82478.360662
2579 51560 -82414.663931
2580 51580 -82350.957607
2581 51600 -82287.241694
2582 51620 -82223.516198
2583 51640 -82159.781124
2584 51660 -82096.036476
2585 51680 -82032.282261
2586 51700 -81968.518482
2587 51720 -81904.745146
2588 51740 -81840.962257
2589 51760 -81777.169821
2590 51780 -81713.367842
2591 51800 -81649.556325
2592 51820 -81585.735276
2593 51840 -81521.904700
2594 51860 -81458.064601
2595 51880 -81394.214985
2596 51900 -81330.355857
2597 51920 -81266.487221
2598 51940 -81202.609084
2599 51960 -81138.721449
2600 51980 -81074.824322
2601 52000 -81010.917709
2602 52020 -80947.001613
2603 52040 -80883.076040
2604 52060 -80819.140995
2605 52080 -80755.196483
2606 52100 -80691.242509
2607 52120 -80627.279078
2608 52140 -80563.306195
2609 52160 -80499.323865
2610 52180 -80435.332093
2611 52200 -80371.330884
2612 52220 -80307.320242
2613 52240 -80243.300174
2614 52260 -80179.270683
2615 52280 -80115.231775
2616 52300 -80051.183455
2617 52320 -79987.125727
2618 52340 -79923.058597
2619 52360 -79858.982069
2620 52380 -79794.896149
2621 52400 -79730.800842
2622 52420 -79666.696151
2623 52440 -79602.582083
2624 52460 -79538.458642
2625 52480 -79474.325833
2626 52500 -79410.183661
2627 52520 -79346.032131
2628 52540 -79281.871248
2629 52560 -79217.701016
2630 52580 -79153.521441
2631 52600 -79089.332527
2632 52620 -79025.134280
2633 52640 -78960.926703
2634 52660 -78896.709803
2635 52680 -78832.483584
2636 52700 -78768.248050
2637 52720 -78704.003207
2638 52740 -78639.749060
2639 52760 -78575.485612
2640 52780 -78511.212870
2641 52800 -78446.930838
2642 52820 -78382.639521
2643 52840 -78318.338923
2644 52860 -78254.029050
2645 52880 -78189.709906
2646 52900 -78125.381497
2647 52920 -78061.043826
2648 52940 -77996.696899
2649 52960 -77932.340720
2650 52980 -77867.975295
2651 53000 -77803.600627
2652 53020 -77739.216723
2653 53040 -77674.823586
2654 53060 -77610.421222
2655 53080 -77546.009635
2656 53100 -77481.588830
2657 53120 -77417.158812
2658 53140 -77352.719585
2659 53160 -77288.271155
2660 53180 -77223.813525
2661 53200 -77159.346702
2662 53220 -77094.870689
2663 53240 -77030.385491
2664 53260 -76965.891113
2665 53280 -76901.387560
2666 53300 -76836.874836
2667 53320 -76772.352947
2668 53340 -76707.821896
2669 53360 -76643.281689
2670 53380 -76578.732330
2671 53400 -76514.173824
2672 53420 -76449.606176
2673 53440 -76385.029390
2674 53460 -76320.443472
2675 53480 -76255.848425
2676 53500 -76191.244255
2677 53520 -76126.630965
2678 53540 -76062.008562
2679 53560 -75997.377049
2680 53580 -75932.736431
2681 53600 -75868.086713
2682 53620 -75803.427899
2683 53640 -75738.759995
2684 53660 -75674.083004
2685 53680 -75609.396932
2686 53700 -75544.701783
2687 53720 -75479.997561
2688 53740 -75415.284272
2689 53760 -75350.561919
2690 53780 -75285.830508
2691 53800 -75221.090044
2692 53820 -75156.340530
2693 53840 -75091.581971
2694 53860 -75026.814372
2695 53880 -74962.037738
2696 53900 -74897.252074
2697 53920 -74832.457383
2698 53940 -74767.653670
2699 53960 -74702.840940
2700 53980 -74638.019198
2701 54000 -74573.188448
2702 54020 -74508.348695
2703 54040 -74443.499943
2704 54060 -74378.642196
2705 54080 -74313.775460
2706 54100 -74248.899739
2707 54120 -74184.015038
2708 54140 -74119.121360
2709 54160 -74054.218711
2710 54180 -73989.307095
2711 54200 -73924.386517
2712 54220 -73859.456981
2713 54240 -73794.518492
2714 54260 -73729.571053
2715 54280 -73664.614671
2716 54300 -73599.649349
2717 54320 -73534.675091
2718 54340 -73469.691903
2719 54360 -73404.699788
2720 54380 -73339.698752
2721 54400 -73274.688799
2722 54420 -73209.669932
2723 54440 -73144.642158
2724 54460 -73079.605480
2725 54480 -73014.559902
2726 54500 -72949.505429
2727 54520 -72884.442066
2728 54540 -72819.369818
2729 54560 -72754.288687
2730 54580 -72689.198680
2731 54600 -72624.099800
2732 54620 -72558.992052
2733 54640 -72493.875441
2734 54660 -72428.749970
2735 54680 -72363.615644
2736 54700 -72298.472468
2737 54720 -72233.320446
2738 54740 -72168.159583
2739 54760 -72102.989882
2740 54780 -72037.811349
2741 54800 -71972.623988
2742 54820 -71907.427803
2743 54840 -71842.222798
2744 54860 -71777.008978
2745 54880 -71711.786348
2746 54900 -71646.554912
2747 54920 -71581.314673
2748 54940 -71516.065637
2749 54960 -71450.807808
2750 54980 -71385.541191
2751 55000 -71320.265789
2752 55020 -71254.981607
2753 55040 -71189.688649
2754 55060 -71124.386920
2755 55080 -71059.076424
2756 55100 -70993.757166
2757 55120 -70928.429150
2758 55140 -70863.092379
2759 55160 -70797.746860
2760 55180 -70732.392595
2761 55200 -70667.029589
2762 55220 -70601.657847
2763 55240 -70536.277372
2764 55260 -70470.888170
2765 55280 -70405.490244
2766 55300 -70340.083599
2767 55320 -70274.668239
2768 55340 -70209.244169
2769 55360 -70143.811392
2770 55380 -70078.369913
2771 55400 -70012.919736
2772 55420 -69947.460867
2773 55440 -69881.993308
2774 55460 -69816.517064
2775 55480 -69751.032139
2776 55500 -69685.538539
2777 55520 -69620.036266
2778 55540 -69554.525325
2779 55560 -69489.005722
2780 55580 -69423.477458
2781 55600 -69357.940540
2782 55620 -69292.394972
2783 55640 -69226.840756
2784 55660 -69161.277899
2785 55680 -69095.706404
2786 55700 -69030.126275
2787 55720 -68964.537516
2788 55740 -68898.940132
2789 55760 -68833.334127
2790 55780 -68767.719506
2791 55800 -68702.096272
2792 55820 -68636.464429
2793 55840 -68570.823982
2794 55860 -68505.174936
2795 55880 -68439.517293
2796 55900 -68373.851059
2797 55920 -68308.176238
2798 55940 -68242.492834
2799 55960 -68176.800850
2800 55980 -68111.100292
2801 56000 -68045.391163
2802 56020 -67979.673468
2803 56040 -67913.947211
2804 56060 -67848.212395
2805 56080 -67782.469026
2806 56100 -67716.717107
2807 56120 -67650.956642
2808 56140 -67585.187636
2809 56160 -67519.410093
2810 56180 -67453.624017
2811 56200 -67387.829412
2812 56220 -67322.026281
2813 56240 -67256.214631
2814 56260 -67190.394463
2815 56280 -67124.565784
2816 56300 -67058.728596
2817 56320 -66992.882904
2818 56340 -66927.028711
2819 56360 -66861.166023
2820 56380 -66795.294843
2821 56400 -66729.415176
2822 56420 -66663.527025
2823 56440 -66597.630394
2824 56460 -66531.725288
2825 56480 -66465.811711
2826 56500 -66399.889666
2827 56520 -66333.959159
2828 56540 -66268.020192
2829 56560 -66202.072771
2830 56580 -66136.116898
2831 56600 -66070.152579
2832 56620 -66004.179817
2833 56640 -65938.198617
2834 56660 -65872.208982
2835 56680 -65806.210916
2836 56700 -65740.204424
2837 56720 -65674.189510
2838 56740 -65608.166177
2839 56760 -65542.134430
2840 56780 -65476.094273
2841 56800 -65410.045709
2842 56820 -65343.988743
2843 56840 -65277.923379
2844 56860 -65211.849621
2845 56880 -65145.767473
2846 56900 -65079.676939
2847 56920 -65013.578023
2848 56940 -64947.470728
2849 56960 -64881.355060
2850 56980 -64815.231021
2851 57000 -64749.098617
2852 57020 -64682.957851
2853 57040 -64616.808726
2854 57060 -64550.651248
2855 57080 -64484.485419
2856 57100 -64418.311245
2857 57120 -64352.128728
2858 57140 -64285.937873
2859 57160 -64219.738684
2860 57180 -64153.531166
2861 57200 -64087.315320
2862 57220 -64021.091153
2863 57240 -63954.858668
2864 57260 -63888.617868
2865 57280 -63822.368758
2866 57300 -63756.111341
2867 57320 -63689.845622
2868 57340 -63623.571605
2869 57360 -63557.289293
2870 57380 -63490.998691
2871 57400 -63424.699802
2872 57420 -63358.392630
2873 57440 -63292.077179
2874 57460 -63225.753454
2875 57480 -63159.421458
2876 57500 -63093.081194
2877 57520 -63026.732668
2878 57540 -62960.375882
2879 57560 -62894.010841
2880 57580 -62827.637549
2881 57600 -62761.256009
2882 57620 -62694.866226
2883 57640 -62628.468203
2884 57660 -62562.061944
2885 57680 -62495.647454
2886 57700 -62429.224735
2887 57720 -62362.793792
2888 57740 -62296.354629
2889 57760 -62229.907250
2890 57780 -62163.451658
2891 57800 -62096.987858
2892 57820 -62030.515853
2893 57840 -61964.035647
2894 57860 -61897.547244
2895 57880 -61831.050647
2896 57900 -61764.545862
2897 57920 -61698.032891
2898 57940 -61631.511738
2899 57960 -61564.982408
2900 57980 -61498.444903
2901 58000 -61431.899229
2902 58020 -61365.345388
2903 58040 -61298.783385
2904 58060 -61232.213224
2905 58080 -61165.634907
2906 58100 -61099.048440
2907 58120 -61032.453825
2908 58140 -60965.851067
2909 58160 -60899.240170
2910 58180 -60832.621136
2911 58200 -60765.993971
2912 58220 -60699.358678
2913 58240 -60632.715261
2914 58260 -60566.063723
2915 58280 -60499.404068
2916 58300 -60432.736301
2917 58320 -60366.060424
2918 58340 -60299.376442
2919 58360 -60232.684358
2920 58380 -60165.984177
2921 58400 -60099.275901
2922 58420 -60032.559536
2923 58440 -59965.835083
2924 58460 -59899.102548
2925 58480 -59832.361934
2926 58500 -59765.613245
2927 58520 -59698.856485
2928 58540 -59632.091656
2929 58560 -59565.318764
2930 58580 -59498.537812
2931 58600 -59431.748803
2932 58620 -59364.951741
2933 58640 -59298.146630
2934 58660 -59231.333474
2935 58680 -59164.512277
2936 58700 -59097.683042
2937 58720 -59030.845772
2938 58740 -58964.000472
2939 58760 -58897.147146
2940 58780 -58830.285797
2941 58800 -58763.416428
2942 58820 -58696.539044
2943 58840 -58629.653648
2944 58860 -58562.760244
2945 58880 -58495.858836
2946 58900 -58428.949426
2947 58920 -58362.032020
2948 58940 -58295.106621
2949 58960 -58228.173231
2950 58980 -58161.231856
2951 59000 -58094.282499
2952 59020 -58027.325163
2953 59040 -57960.359852
2954 59060 -57893.386569
2955 59080 -57826.405319
2956 59100 -57759.416105
2957 59120 -57692.418931
2958 59140 -57625.413800
2959 59160 -57558.400717
2960 59180 -57491.379684
2961 59200 -57424.350705
2962 59220 -57357.313784
2963 59240 -57290.268925
2964 59260 -57223.216131
2965 59280 -57156.155406
2966 59300 -57089.086753
2967 59320 -57022.010177
2968 59340 -56954.925681
2969 59360 -56887.833267
2970 59380 -56820.732941
2971 59400 -56753.624706
2972 59420 -56686.508565
2973 59440 -56619.384521
2974 59460 -56552.252580
2975 59480 -56485.112743
2976 59500 -56417.965015
2977 59520 -56350.809399
2978 59540 -56283.645900
2979 59560 -56216.474519
2980 59580 -56149.295262
2981 59600 -56082.108132
2982 59620 -56014.913131
2983 59640 -55947.710265
2984 59660 -55880.499536
2985 59680 -55813.280948
2986 59700 -55746.054505
2987 59720 -55678.820209
2988 59740 -55611.578066
2989 59760 -55544.328078
2990 59780 -55477.070248
2991 59800 -55409.804581
2992 59820 -55342.531080
2993 59840 -55275.249749
2994 59860 -55207.960590
2995 59880 -55140.663609
2996 59900 -55073.358807
2997 59920 -55006.046189
2998 59940 -54938.725758
2999 59960 -54871.397519
3000 59980 -54804.061473
3001 60000 -54736.717625

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