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 2 of 40 · 500/page · 20000 rows next →
# nmargin_tilde
502 10020 -176275.897820
503 10040 -176272.382379
504 10060 -176268.757267
505 10080 -176265.022834
506 10100 -176261.179425
507 10120 -176257.227386
508 10140 -176253.167061
509 10160 -176248.998792
510 10180 -176244.722918
511 10200 -176240.339777
512 10220 -176235.849706
513 10240 -176231.253039
514 10260 -176226.550109
515 10280 -176221.741246
516 10300 -176216.826781
517 10320 -176211.807040
518 10340 -176206.682350
519 10360 -176201.453034
520 10380 -176196.119416
521 10400 -176190.681816
522 10420 -176185.140553
523 10440 -176179.495945
524 10460 -176173.748307
525 10480 -176167.897955
526 10500 -176161.945200
527 10520 -176155.890355
528 10540 -176149.733727
529 10560 -176143.475626
530 10580 -176137.116357
531 10600 -176130.656226
532 10620 -176124.095536
533 10640 -176117.434589
534 10660 -176110.673684
535 10680 -176103.813121
536 10700 -176096.853196
537 10720 -176089.794207
538 10740 -176082.636446
539 10760 -176075.380207
540 10780 -176068.025781
541 10800 -176060.573458
542 10820 -176053.023526
543 10840 -176045.376273
544 10860 -176037.631984
545 10880 -176029.790944
546 10900 -176021.853434
547 10920 -176013.819738
548 10940 -176005.690134
549 10960 -175997.464902
550 10980 -175989.144319
551 11000 -175980.728660
552 11020 -175972.218201
553 11040 -175963.613215
554 11060 -175954.913974
555 11080 -175946.120748
556 11100 -175937.233807
557 11120 -175928.253419
558 11140 -175919.179851
559 11160 -175910.013368
560 11180 -175900.754235
561 11200 -175891.402714
562 11220 -175881.959068
563 11240 -175872.423556
564 11260 -175862.796438
565 11280 -175853.077973
566 11300 -175843.268416
567 11320 -175833.368024
568 11340 -175823.377050
569 11360 -175813.295749
570 11380 -175803.124372
571 11400 -175792.863169
572 11420 -175782.512391
573 11440 -175772.072286
574 11460 -175761.543101
575 11480 -175750.925083
576 11500 -175740.218476
577 11520 -175729.423524
578 11540 -175718.540470
579 11560 -175707.569557
580 11580 -175696.511023
581 11600 -175685.365109
582 11620 -175674.132053
583 11640 -175662.812093
584 11660 -175651.405463
585 11680 -175639.912400
586 11700 -175628.333138
587 11720 -175616.667908
588 11740 -175604.916944
589 11760 -175593.080476
590 11780 -175581.158733
591 11800 -175569.151945
592 11820 -175557.060339
593 11840 -175544.884142
594 11860 -175532.623579
595 11880 -175520.278875
596 11900 -175507.850254
597 11920 -175495.337938
598 11940 -175482.742149
599 11960 -175470.063108
600 11980 -175457.301033
601 12000 -175444.456145
602 12020 -175431.528660
603 12040 -175418.518795
604 12060 -175405.426767
605 12080 -175392.252789
606 12100 -175378.997076
607 12120 -175365.659841
608 12140 -175352.241296
609 12160 -175338.741651
610 12180 -175325.161118
611 12200 -175311.499905
612 12220 -175297.758220
613 12240 -175283.936271
614 12260 -175270.034265
615 12280 -175256.052407
616 12300 -175241.990901
617 12320 -175227.849953
618 12340 -175213.629764
619 12360 -175199.330537
620 12380 -175184.952472
621 12400 -175170.495771
622 12420 -175155.960633
623 12440 -175141.347257
624 12460 -175126.655839
625 12480 -175111.886578
626 12500 -175097.039669
627 12520 -175082.115308
628 12540 -175067.113689
629 12560 -175052.035006
630 12580 -175036.879451
631 12600 -175021.647216
632 12620 -175006.338493
633 12640 -174990.953472
634 12660 -174975.492343
635 12680 -174959.955295
636 12700 -174944.342514
637 12720 -174928.654190
638 12740 -174912.890507
639 12760 -174897.051652
640 12780 -174881.137809
641 12800 -174865.149164
642 12820 -174849.085898
643 12840 -174832.948195
644 12860 -174816.736236
645 12880 -174800.450202
646 12900 -174784.090275
647 12920 -174767.656633
648 12940 -174751.149455
649 12960 -174734.568920
650 12980 -174717.915204
651 13000 -174701.188485
652 13020 -174684.388938
653 13040 -174667.516739
654 13060 -174650.572062
655 13080 -174633.555081
656 13100 -174616.465969
657 13120 -174599.304898
658 13140 -174582.072041
659 13160 -174564.767567
660 13180 -174547.391648
661 13200 -174529.944454
662 13220 -174512.426152
663 13240 -174494.836911
664 13260 -174477.176900
665 13280 -174459.446284
666 13300 -174441.645231
667 13320 -174423.773905
668 13340 -174405.832472
669 13360 -174387.821096
670 13380 -174369.739941
671 13400 -174351.589169
672 13420 -174333.368943
673 13440 -174315.079424
674 13460 -174296.720775
675 13480 -174278.293155
676 13500 -174259.796723
677 13520 -174241.231640
678 13540 -174222.598063
679 13560 -174203.896151
680 13580 -174185.126061
681 13600 -174166.287949
682 13620 -174147.381973
683 13640 -174128.408286
684 13660 -174109.367045
685 13680 -174090.258402
686 13700 -174071.082513
687 13720 -174051.839530
688 13740 -174032.529606
689 13760 -174013.152892
690 13780 -173993.709541
691 13800 -173974.199701
692 13820 -173954.623525
693 13840 -173934.981161
694 13860 -173915.272758
695 13880 -173895.498465
696 13900 -173875.658430
697 13920 -173855.752800
698 13940 -173835.781722
699 13960 -173815.745342
700 13980 -173795.643806
701 14000 -173775.477258
702 14020 -173755.245844
703 14040 -173734.949707
704 14060 -173714.588991
705 14080 -173694.163839
706 14100 -173673.674393
707 14120 -173653.120794
708 14140 -173632.503186
709 14160 -173611.821707
710 14180 -173591.076499
711 14200 -173570.267701
712 14220 -173549.395452
713 14240 -173528.459891
714 14260 -173507.461157
715 14280 -173486.399386
716 14300 -173465.274717
717 14320 -173444.087286
718 14340 -173422.837228
719 14360 -173401.524680
720 14380 -173380.149777
721 14400 -173358.712654
722 14420 -173337.213444
723 14440 -173315.652281
724 14460 -173294.029299
725 14480 -173272.344631
726 14500 -173250.598407
727 14520 -173228.790761
728 14540 -173206.921823
729 14560 -173184.991725
730 14580 -173163.000596
731 14600 -173140.948567
732 14620 -173118.835766
733 14640 -173096.662323
734 14660 -173074.428366
735 14680 -173052.134023
736 14700 -173029.779422
737 14720 -173007.364689
738 14740 -172984.889951
739 14760 -172962.355335
740 14780 -172939.760967
741 14800 -172917.106970
742 14820 -172894.393471
743 14840 -172871.620593
744 14860 -172848.788460
745 14880 -172825.897197
746 14900 -172802.946925
747 14920 -172779.937768
748 14940 -172756.869848
749 14960 -172733.743286
750 14980 -172710.558204
751 15000 -172687.314723
752 15020 -172664.012963
753 15040 -172640.653044
754 15060 -172617.235086
755 15080 -172593.759207
756 15100 -172570.225528
757 15120 -172546.634165
758 15140 -172522.985238
759 15160 -172499.278863
760 15180 -172475.515158
761 15200 -172451.694240
762 15220 -172427.816224
763 15240 -172403.881227
764 15260 -172379.889365
765 15280 -172355.840752
766 15300 -172331.735502
767 15320 -172307.573732
768 15340 -172283.355553
769 15360 -172259.081081
770 15380 -172234.750427
771 15400 -172210.363706
772 15420 -172185.921028
773 15440 -172161.422507
774 15460 -172136.868254
775 15480 -172112.258379
776 15500 -172087.592995
777 15520 -172062.872211
778 15540 -172038.096137
779 15560 -172013.264884
780 15580 -171988.378561
781 15600 -171963.437276
782 15620 -171938.441138
783 15640 -171913.390256
784 15660 -171888.284737
785 15680 -171863.124689
786 15700 -171837.910219
787 15720 -171812.641434
788 15740 -171787.318441
789 15760 -171761.941345
790 15780 -171736.510252
791 15800 -171711.025268
792 15820 -171685.486497
793 15840 -171659.894045
794 15860 -171634.248016
795 15880 -171608.548513
796 15900 -171582.795640
797 15920 -171556.989502
798 15940 -171531.130200
799 15960 -171505.217837
800 15980 -171479.252516
801 16000 -171453.234338
802 16020 -171427.163405
803 16040 -171401.039819
804 16060 -171374.863680
805 16080 -171348.635090
806 16100 -171322.354147
807 16120 -171296.020953
808 16140 -171269.635607
809 16160 -171243.198208
810 16180 -171216.708856
811 16200 -171190.167648
812 16220 -171163.574684
813 16240 -171136.930061
814 16260 -171110.233877
815 16280 -171083.486230
816 16300 -171056.687216
817 16320 -171029.836932
818 16340 -171002.935476
819 16360 -170975.982942
820 16380 -170948.979427
821 16400 -170921.925026
822 16420 -170894.819835
823 16440 -170867.663949
824 16460 -170840.457462
825 16480 -170813.200468
826 16500 -170785.893062
827 16520 -170758.535336
828 16540 -170731.127386
829 16560 -170703.669303
830 16580 -170676.161181
831 16600 -170648.603113
832 16620 -170620.995189
833 16640 -170593.337503
834 16660 -170565.630146
835 16680 -170537.873210
836 16700 -170510.066785
837 16720 -170482.210962
838 16740 -170454.305833
839 16760 -170426.351486
840 16780 -170398.348012
841 16800 -170370.295502
842 16820 -170342.194043
843 16840 -170314.043725
844 16860 -170285.844638
845 16880 -170257.596869
846 16900 -170229.300508
847 16920 -170200.955641
848 16940 -170172.562357
849 16960 -170144.120743
850 16980 -170115.630886
851 17000 -170087.092874
852 17020 -170058.506793
853 17040 -170029.872729
854 17060 -170001.190768
855 17080 -169972.460997
856 17100 -169943.683501
857 17120 -169914.858365
858 17140 -169885.985675
859 17160 -169857.065515
860 17180 -169828.097969
861 17200 -169799.083123
862 17220 -169770.021059
863 17240 -169740.911863
864 17260 -169711.755617
865 17280 -169682.552405
866 17300 -169653.302309
867 17320 -169624.005413
868 17340 -169594.661799
869 17360 -169565.271550
870 17380 -169535.834746
871 17400 -169506.351471
872 17420 -169476.821806
873 17440 -169447.245831
874 17460 -169417.623629
875 17480 -169387.955279
876 17500 -169358.240863
877 17520 -169328.480460
878 17540 -169298.674152
879 17560 -169268.822017
880 17580 -169238.924135
881 17600 -169208.980585
882 17620 -169178.991448
883 17640 -169148.956801
884 17660 -169118.876723
885 17680 -169088.751294
886 17700 -169058.580590
887 17720 -169028.364690
888 17740 -168998.103671
889 17760 -168967.797612
890 17780 -168937.446589
891 17800 -168907.050680
892 17820 -168876.609961
893 17840 -168846.124508
894 17860 -168815.594400
895 17880 -168785.019710
896 17900 -168754.400516
897 17920 -168723.736893
898 17940 -168693.028917
899 17960 -168662.276662
900 17980 -168631.480204
901 18000 -168600.639618
902 18020 -168569.754978
903 18040 -168538.826359
904 18060 -168507.853835
905 18080 -168476.837480
906 18100 -168445.777367
907 18120 -168414.673571
908 18140 -168383.526163
909 18160 -168352.335219
910 18180 -168321.100810
911 18200 -168289.823009
912 18220 -168258.501889
913 18240 -168227.137522
914 18260 -168195.729980
915 18280 -168164.279335
916 18300 -168132.785658
917 18320 -168101.249021
918 18340 -168069.669496
919 18360 -168038.047153
920 18380 -168006.382063
921 18400 -167974.674297
922 18420 -167942.923925
923 18440 -167911.131018
924 18460 -167879.295645
925 18480 -167847.417877
926 18500 -167815.497782
927 18520 -167783.535432
928 18540 -167751.530894
929 18560 -167719.484237
930 18580 -167687.395532
931 18600 -167655.264846
932 18620 -167623.092248
933 18640 -167590.877806
934 18660 -167558.621588
935 18680 -167526.323662
936 18700 -167493.984097
937 18720 -167461.602958
938 18740 -167429.180315
939 18760 -167396.716233
940 18780 -167364.210781
941 18800 -167331.664024
942 18820 -167299.076029
943 18840 -167266.446863
944 18860 -167233.776592
945 18880 -167201.065282
946 18900 -167168.312999
947 18920 -167135.519808
948 18940 -167102.685776
949 18960 -167069.810966
950 18980 -167036.895446
951 19000 -167003.939278
952 19020 -166970.942529
953 19040 -166937.905263
954 19060 -166904.827544
955 19080 -166871.709437
956 19100 -166838.551005
957 19120 -166805.352312
958 19140 -166772.113423
959 19160 -166738.834401
960 19180 -166705.515309
961 19200 -166672.156210
962 19220 -166638.757168
963 19240 -166605.318245
964 19260 -166571.839504
965 19280 -166538.321008
966 19300 -166504.762818
967 19320 -166471.164998
968 19340 -166437.527609
969 19360 -166403.850713
970 19380 -166370.134371
971 19400 -166336.378645
972 19420 -166302.583597
973 19440 -166268.749288
974 19460 -166234.875779
975 19480 -166200.963130
976 19500 -166167.011403
977 19520 -166133.020657
978 19540 -166098.990954
979 19560 -166064.922353
980 19580 -166030.814915
981 19600 -165996.668699
982 19620 -165962.483766
983 19640 -165928.260174
984 19660 -165893.997983
985 19680 -165859.697253
986 19700 -165825.358042
987 19720 -165790.980410
988 19740 -165756.564416
989 19760 -165722.110117
990 19780 -165687.617573
991 19800 -165653.086841
992 19820 -165618.517981
993 19840 -165583.911049
994 19860 -165549.266105
995 19880 -165514.583205
996 19900 -165479.862407
997 19920 -165445.103769
998 19940 -165410.307348
999 19960 -165375.473201
1000 19980 -165340.601385
1001 20000 -165305.691957

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