sedumipy 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sedumipy-0.0.1/CHANGELOG.md +81 -0
- sedumipy-0.0.1/CONTRIBUTING.md +309 -0
- sedumipy-0.0.1/LICENSE +340 -0
- sedumipy-0.0.1/MANIFEST.in +20 -0
- sedumipy-0.0.1/PKG-INFO +242 -0
- sedumipy-0.0.1/README.md +210 -0
- sedumipy-0.0.1/csrc/adendotd.c +246 -0
- sedumipy-0.0.1/csrc/adenscale.c +165 -0
- sedumipy-0.0.1/csrc/auxfwdpr1.c +122 -0
- sedumipy-0.0.1/csrc/auxgivens.c +191 -0
- sedumipy-0.0.1/csrc/blkaux.c +116 -0
- sedumipy-0.0.1/csrc/blkchol.c +442 -0
- sedumipy-0.0.1/csrc/blkchol2.c +565 -0
- sedumipy-0.0.1/csrc/blkmul.c +133 -0
- sedumipy-0.0.1/csrc/blksdp.h +212 -0
- sedumipy-0.0.1/csrc/bwblkslv.c +300 -0
- sedumipy-0.0.1/csrc/bwblkslv2.c +138 -0
- sedumipy-0.0.1/csrc/bwdpr1.c +277 -0
- sedumipy-0.0.1/csrc/cholsplit.c +186 -0
- sedumipy-0.0.1/csrc/choltmpsiz.c +175 -0
- sedumipy-0.0.1/csrc/ddot.c +310 -0
- sedumipy-0.0.1/csrc/dpr1fact.c +850 -0
- sedumipy-0.0.1/csrc/extractA.c +192 -0
- sedumipy-0.0.1/csrc/findblks.c +237 -0
- sedumipy-0.0.1/csrc/finsymbden.c +216 -0
- sedumipy-0.0.1/csrc/fwblkslv.c +322 -0
- sedumipy-0.0.1/csrc/fwdpr1.c +204 -0
- sedumipy-0.0.1/csrc/getada1.c +263 -0
- sedumipy-0.0.1/csrc/getada2.c +216 -0
- sedumipy-0.0.1/csrc/getada3.c +571 -0
- sedumipy-0.0.1/csrc/givens.h +52 -0
- sedumipy-0.0.1/csrc/givensrot.c +170 -0
- sedumipy-0.0.1/csrc/incorder.c +345 -0
- sedumipy-0.0.1/csrc/invcholfac.c +170 -0
- sedumipy-0.0.1/csrc/iswnbr.c +270 -0
- sedumipy-0.0.1/csrc/kernel_smoke/smoke_test.c +55 -0
- sedumipy-0.0.1/csrc/mJdetd.c +98 -0
- sedumipy-0.0.1/csrc/ordmmd.c +1158 -0
- sedumipy-0.0.1/csrc/ordmmd.h +10 -0
- sedumipy-0.0.1/csrc/ordmmdmex.c +141 -0
- sedumipy-0.0.1/csrc/partitA.c +156 -0
- sedumipy-0.0.1/csrc/psdframeit.c +170 -0
- sedumipy-0.0.1/csrc/psdinvjmul.c +229 -0
- sedumipy-0.0.1/csrc/qblkmul.c +118 -0
- sedumipy-0.0.1/csrc/qrK.c +298 -0
- sedumipy-0.0.1/csrc/quadadd.c +132 -0
- sedumipy-0.0.1/csrc/reflect.c +357 -0
- sedumipy-0.0.1/csrc/reflect.h +48 -0
- sedumipy-0.0.1/csrc/sdmauxCmp.c +205 -0
- sedumipy-0.0.1/csrc/sdmauxCone.c +199 -0
- sedumipy-0.0.1/csrc/sdmauxFill.c +75 -0
- sedumipy-0.0.1/csrc/sdmauxRdot.c +59 -0
- sedumipy-0.0.1/csrc/sdmauxScalarmul.c +70 -0
- sedumipy-0.0.1/csrc/sdmauxTriu.c +145 -0
- sedumipy-0.0.1/csrc/sdmauxTriudot.c +75 -0
- sedumipy-0.0.1/csrc/sedumi_platform.c +31 -0
- sedumipy-0.0.1/csrc/sedumi_platform.h +165 -0
- sedumipy-0.0.1/csrc/sortnnz.c +142 -0
- sedumipy-0.0.1/csrc/spscale.c +773 -0
- sedumipy-0.0.1/csrc/sqrtinv.c +147 -0
- sedumipy-0.0.1/csrc/symbchol.c +183 -0
- sedumipy-0.0.1/csrc/symbfwblk.c +379 -0
- sedumipy-0.0.1/csrc/symfct.c +2295 -0
- sedumipy-0.0.1/csrc/symfct.h +17 -0
- sedumipy-0.0.1/csrc/symfctmex.c +274 -0
- sedumipy-0.0.1/csrc/triuaux.c +741 -0
- sedumipy-0.0.1/csrc/triuaux.h +70 -0
- sedumipy-0.0.1/csrc/urotorder.c +492 -0
- sedumipy-0.0.1/csrc/vecsym.c +177 -0
- sedumipy-0.0.1/pyproject.toml +165 -0
- sedumipy-0.0.1/setup.cfg +4 -0
- sedumipy-0.0.1/setup.py +123 -0
- sedumipy-0.0.1/src/sedumipy/__init__.py +34 -0
- sedumipy-0.0.1/src/sedumipy/_native.py +2405 -0
- sedumipy-0.0.1/src/sedumipy/amul.py +34 -0
- sedumipy-0.0.1/src/sedumipy/checkpars.py +83 -0
- sedumipy-0.0.1/src/sedumipy/cone.py +785 -0
- sedumipy-0.0.1/src/sedumipy/deninfac.py +58 -0
- sedumipy-0.0.1/src/sedumipy/getada.py +63 -0
- sedumipy-0.0.1/src/sedumipy/getada_psd.py +114 -0
- sedumipy-0.0.1/src/sedumipy/getdatm.py +96 -0
- sedumipy-0.0.1/src/sedumipy/getdense.py +94 -0
- sedumipy-0.0.1/src/sedumipy/getsymbada.py +68 -0
- sedumipy-0.0.1/src/sedumipy/incorder.py +110 -0
- sedumipy-0.0.1/src/sedumipy/matio.py +106 -0
- sedumipy-0.0.1/src/sedumipy/maxstep.py +72 -0
- sedumipy-0.0.1/src/sedumipy/neighborhood.py +86 -0
- sedumipy-0.0.1/src/sedumipy/optstep.py +108 -0
- sedumipy-0.0.1/src/sedumipy/pcg.py +259 -0
- sedumipy-0.0.1/src/sedumipy/posttransfo.py +44 -0
- sedumipy-0.0.1/src/sedumipy/pretransfo.py +448 -0
- sedumipy-0.0.1/src/sedumipy/sddir.py +47 -0
- sedumipy-0.0.1/src/sedumipy/sdfactor.py +38 -0
- sedumipy-0.0.1/src/sedumipy/sdinit.py +72 -0
- sedumipy-0.0.1/src/sedumipy/sdpa.py +200 -0
- sedumipy-0.0.1/src/sedumipy/sedumi.py +367 -0
- sedumipy-0.0.1/src/sedumipy/stepdif.py +111 -0
- sedumipy-0.0.1/src/sedumipy/symbchol.py +43 -0
- sedumipy-0.0.1/src/sedumipy/symbcholden.py +65 -0
- sedumipy-0.0.1/src/sedumipy/trydif.py +58 -0
- sedumipy-0.0.1/src/sedumipy/updtransfo.py +89 -0
- sedumipy-0.0.1/src/sedumipy/widelen.py +125 -0
- sedumipy-0.0.1/src/sedumipy/wregion.py +185 -0
- sedumipy-0.0.1/src/sedumipy.egg-info/PKG-INFO +242 -0
- sedumipy-0.0.1/src/sedumipy.egg-info/SOURCES.txt +317 -0
- sedumipy-0.0.1/src/sedumipy.egg-info/dependency_links.txt +1 -0
- sedumipy-0.0.1/src/sedumipy.egg-info/requires.txt +10 -0
- sedumipy-0.0.1/src/sedumipy.egg-info/top_level.txt +1 -0
- sedumipy-0.0.1/tests/fixtures/adendotd/case1.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/adendotd/case2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/adenscale/case1.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/adenscale/case2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/adenscale/case3.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol/grid5x5_blkchol_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol/grid5x5_spd.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol/path5_blkchol_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol/path5_spd.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol/rand10_blkchol_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol/rand10_spd.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol/rand25_blkchol_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol/rand25_spd.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol/star5_blkchol_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol/star5_spd.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol_edge/pure_add.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol_edge/pure_add_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol_edge/pure_skip.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol_edge/pure_skip_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol_edge/skip_and_add.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol_edge/skip_and_add2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol_edge/skip_and_add2_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/blkchol_edge/skip_and_add_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/checkpars/alg0.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/checkpars/empty.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/checkpars/nested.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/checkpars/partial.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/checkpars/w.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/checkpars/w_bad.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster1/ddot_dense.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster1/ddot_offset.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster1/qblkmul.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster1/quadadd.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster1/vecsym.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster2/dpr1fact_n1.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster2/dpr1fact_n2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster3/K.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster3/givensrot.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster3/invcholfac.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster3/psdframeit.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster3/psdinvjmul.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster3/psdinvjmul_full.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster3/qrK.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster3/sqrtinv.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster3/urotorder.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster3/urotorder_permin.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster4/extractA.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster4/findblks.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster4/partitA.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster5/cholsplit.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cluster5/sortnnz.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cone/cone2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cone/cone2_frameit.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/cone/eigK.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/generate_blkchol_fixtures.py +57 -0
- sedumipy-0.0.1/tests/fixtures/generate_ordmmd_fixtures.py +75 -0
- sedumipy-0.0.1/tests/fixtures/getada/case1.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getada/case2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getada/case3.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getada/case4.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getada_psd/case1.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getada_psd/case2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getada_psd/case3.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getdense/case1.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getdense/case2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getdense/case3.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getdense/case4.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getdense/case5.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getsymbada/case1.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getsymbada/case2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getsymbada/case3.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/getsymbada/case4.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/incorder/case1.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/incorder/case2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/incorder/case3.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/incorder/case4.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/iswnbr/case1.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/iswnbr/case2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/iswnbr/case3.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/iswnbr/case4.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/grid5x5.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/grid5x5_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/grid5x5_symfct_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/path5.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/path5_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/path5_symfct_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/rand10.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/rand10_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/rand10_symfct_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/rand25.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/rand25_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/rand25_symfct_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/rand50.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/rand50_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/rand50_symfct_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/star5.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/star5_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/ordmmd/star5_symfct_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/posttransfo/complex_sdp.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/posttransfo/real_only.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/posttransfo/with_ycomplex.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/pretransfo/complex_sdp_all.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/pretransfo/complex_sdp_single.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/pretransfo/free_lorentz.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/pretransfo/free_split.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/pretransfo/kitchen_sink_lorentz.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/pretransfo/kitchen_sink_split.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/pretransfo/lorentz.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/pretransfo/lp_only.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/pretransfo/mixed_l_q_r.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/pretransfo/real_sdp.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/pretransfo/real_sdp_diag.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/pretransfo/rotated_lorentz.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/pretransfo/xcomplex_mixed.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/pretransfo/ycomplex.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/amul.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/deninfac_case1.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/deninfac_case2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/getdatm.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/getdatm_dense.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/maxstep.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/optstep.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/pcg.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/pcg_dense.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/popk.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/sddir.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/sdinit_case1.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/tdet_asmdxq.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/trydif.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/updtransfo.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/widelen.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/wregion_case1.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdinit/wregion_case2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sdpa/test_problem.dat-s +14 -0
- sedumipy-0.0.1/tests/fixtures/sdpa/test_problem_oracle.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/search_blkchol_diagadd.py +66 -0
- sedumipy-0.0.1/tests/fixtures/search_blkchol_diagadd2.py +65 -0
- sedumipy-0.0.1/tests/fixtures/search_blkchol_edge_cases.py +69 -0
- sedumipy-0.0.1/tests/fixtures/sedumi/lp_feasible.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sedumi/lp_free_feasible.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sedumi/lp_infeasible.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sedumi/lp_socp_sdp_dense_feasible.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sedumi/lp_sparse_feasible.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sedumi/rotated_cone_feasible.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sedumi/sdp_feasible.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sedumi/sdp_mixed_cones_feasible.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sedumi/socp_feasible.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/sedumi/socp_two_blocks.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/stepdif/case1_tpmtd_pos_sdpos.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/stepdif/case2_tpmtd_neg_sdpos.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/stepdif/case3_sdneg.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/stepdif/case4_sdzero.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/stepdif/case5_large_step.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/stepdif/case6_large_step_neg_tpmtd.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/stepdif/case7_interior_minimizer.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/stepdif/case8_breakpoint.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/symbcholden/case1.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/symbcholden/case2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/symbcholden/case3.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/symbfwblk/case1.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/symbfwblk/case2.mat +0 -0
- sedumipy-0.0.1/tests/fixtures/symbfwblk/case3.mat +0 -0
- sedumipy-0.0.1/tests/test_adendotd.py +52 -0
- sedumipy-0.0.1/tests/test_adenscale.py +48 -0
- sedumipy-0.0.1/tests/test_benchmarks.py +528 -0
- sedumipy-0.0.1/tests/test_blkchol.py +98 -0
- sedumipy-0.0.1/tests/test_blkchol_edge_cases.py +96 -0
- sedumipy-0.0.1/tests/test_checkpars.py +87 -0
- sedumipy-0.0.1/tests/test_cluster1.py +85 -0
- sedumipy-0.0.1/tests/test_cluster2.py +120 -0
- sedumipy-0.0.1/tests/test_cluster3.py +145 -0
- sedumipy-0.0.1/tests/test_cluster4.py +68 -0
- sedumipy-0.0.1/tests/test_cluster5.py +74 -0
- sedumipy-0.0.1/tests/test_cone.py +111 -0
- sedumipy-0.0.1/tests/test_cone2.py +179 -0
- sedumipy-0.0.1/tests/test_deninfac.py +103 -0
- sedumipy-0.0.1/tests/test_getada.py +100 -0
- sedumipy-0.0.1/tests/test_getada_psd.py +77 -0
- sedumipy-0.0.1/tests/test_getdatm.py +94 -0
- sedumipy-0.0.1/tests/test_getdense.py +72 -0
- sedumipy-0.0.1/tests/test_getsymbada.py +68 -0
- sedumipy-0.0.1/tests/test_golden_end_to_end.py +108 -0
- sedumipy-0.0.1/tests/test_golden_reference.py +89 -0
- sedumipy-0.0.1/tests/test_incorder.py +77 -0
- sedumipy-0.0.1/tests/test_iswnbr.py +38 -0
- sedumipy-0.0.1/tests/test_matio.py +137 -0
- sedumipy-0.0.1/tests/test_maxstep.py +51 -0
- sedumipy-0.0.1/tests/test_native_bindings.py +67 -0
- sedumipy-0.0.1/tests/test_native_sparse_solve.py +89 -0
- sedumipy-0.0.1/tests/test_optstep.py +92 -0
- sedumipy-0.0.1/tests/test_ordmmd.py +62 -0
- sedumipy-0.0.1/tests/test_pcg.py +190 -0
- sedumipy-0.0.1/tests/test_popk.py +53 -0
- sedumipy-0.0.1/tests/test_posttransfo.py +60 -0
- sedumipy-0.0.1/tests/test_pretransfo.py +130 -0
- sedumipy-0.0.1/tests/test_sddir.py +127 -0
- sedumipy-0.0.1/tests/test_sdinit.py +105 -0
- sedumipy-0.0.1/tests/test_sdpa.py +72 -0
- sedumipy-0.0.1/tests/test_sedumi.py +132 -0
- sedumipy-0.0.1/tests/test_sparse_solve_pipeline.py +77 -0
- sedumipy-0.0.1/tests/test_stepdif.py +58 -0
- sedumipy-0.0.1/tests/test_symbchol.py +103 -0
- sedumipy-0.0.1/tests/test_symbcholden.py +62 -0
- sedumipy-0.0.1/tests/test_symbfwblk.py +54 -0
- sedumipy-0.0.1/tests/test_symfct.py +80 -0
- sedumipy-0.0.1/tests/test_tdet_asmdxq.py +79 -0
- sedumipy-0.0.1/tests/test_trydif.py +88 -0
- sedumipy-0.0.1/tests/test_updtransfo.py +70 -0
- sedumipy-0.0.1/tests/test_widelen.py +73 -0
- sedumipy-0.0.1/tests/test_wregion.py +133 -0
- sedumipy-0.0.1/tools/build_libsedumi.sh +285 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. Format loosely
|
|
4
|
+
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). See
|
|
5
|
+
[`CONTRIBUTING.md`](CONTRIBUTING.md) §2 for the full phase-by-phase
|
|
6
|
+
status and history behind these entries, and
|
|
7
|
+
[`RELEASING.md`](RELEASING.md) for how a release is cut.
|
|
8
|
+
|
|
9
|
+
## [Unreleased]
|
|
10
|
+
|
|
11
|
+
## [0.0.1] - 2026-09-05
|
|
12
|
+
|
|
13
|
+
First release published to [PyPI](https://pypi.org/project/sedumipy/):
|
|
14
|
+
`pip install sedumipy`. Everything below is the work that got it there.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- Ported `sedumi()`, SeDuMi's top-level LP/SOCP/SDP interior-point
|
|
19
|
+
solver driver, to pure Python (NumPy/SciPy) plus a standalone C kernel
|
|
20
|
+
library (`libsedumi.so`/`.dylib`, no MATLAB/Octave/MEX dependency),
|
|
21
|
+
loaded via `ctypes`. LP, second-order-cone (SOCP), and semidefinite
|
|
22
|
+
(SDP, `K.s`) problems are in scope and verified against
|
|
23
|
+
original Octave/SeDuMi output (to tight numerical tolerances -- see
|
|
24
|
+
`docs/status.rst`), including on published
|
|
25
|
+
[SDPLIB](https://github.com/vsdp/SDPLIB) and
|
|
26
|
+
[DIMACS](https://github.com/vsdp/DIMACS) benchmark problems. Dense-
|
|
27
|
+
column preconditioning is implemented.
|
|
28
|
+
- `.mat` and sparse SDPA (`.dat-s`) problem/solution file I/O
|
|
29
|
+
(`sedumipy.read_mat`/`write_solution_mat`, `read_sdpa`/`write_sdpa`).
|
|
30
|
+
- Sphinx documentation (`docs/`), published to GitHub Pages.
|
|
31
|
+
- CI (`.github/workflows/ci.yml`): the test suite (Octave-generated
|
|
32
|
+
oracle fixtures, no Octave needed to run it) plus the fastest SDPLIB/
|
|
33
|
+
DIMACS benchmark subset, both on every push/PR, on Linux, macOS and
|
|
34
|
+
Windows. The BLAS implementation is the axis that actually matters for
|
|
35
|
+
these numerical comparisons, so the Linux job runs it against three:
|
|
36
|
+
reference Netlib and OpenBLAS (both a system package), and
|
|
37
|
+
scipy-openblas64 (pip-installed, ILP64 -- see below); Windows runs
|
|
38
|
+
OpenBLAS via MSYS2 and macOS runs Accelerate.
|
|
39
|
+
- `tools/build_libsedumi.sh` links [scipy-openblas64](
|
|
40
|
+
https://pypi.org/project/scipy-openblas64/) -- a pip-installable,
|
|
41
|
+
prebuilt ILP64 OpenBLAS, pinned to an exact version, the same package
|
|
42
|
+
numpy/scipy themselves build against -- as `libsedumi`'s BLAS on
|
|
43
|
+
Linux and Windows, whenever it's importable by the Python building it,
|
|
44
|
+
falling back to that OS's own system-BLAS story (`-lblas`/
|
|
45
|
+
`-lopenblas` on Linux, MSYS2's `-lopenblas` on Windows) only when it
|
|
46
|
+
isn't. It's a build-time-only dependency -- never installed at runtime
|
|
47
|
+
for end users -- since a wheel build vendors the resulting shared
|
|
48
|
+
library into the wheel itself, same as it already did for
|
|
49
|
+
`-lopenblas`. macOS deliberately keeps linking the system Accelerate
|
|
50
|
+
framework unconditionally instead: it never had Linux/Windows's
|
|
51
|
+
build/install pain (Accelerate needs no install step at all, unlike
|
|
52
|
+
`libblas-dev`/MSYS2), so there's nothing here for scipy-openblas64 to
|
|
53
|
+
save, only wheel bytes and a possible speed regression on Apple
|
|
54
|
+
Silicon to risk. See `csrc/sedumi_platform.h`'s `SEDUMI_BLAS_ILP64`/
|
|
55
|
+
`BLAS_SYMBOL_PREFIX`/`BLAS_SYMBOL_SUFFIX` for how the ILP64 integer
|
|
56
|
+
width and the symbol-mangling scipy-openblas64 needs (to coexist with
|
|
57
|
+
other OpenBLAS copies in one process) are handled.
|
|
58
|
+
- Wheel builds via cibuildwheel (`.github/workflows/wheels.yml`) for
|
|
59
|
+
Linux (manylinux), macOS, and Windows (MSYS2/MinGW toolchain, gcc
|
|
60
|
+
only now), uploaded to PyPI on release via Trusted Publishing (see
|
|
61
|
+
[`RELEASING.md`](RELEASING.md)). Linux and Windows now link
|
|
62
|
+
scipy-openblas64 (see above) as their BLAS, vendored into the wheel by
|
|
63
|
+
`auditwheel` on Linux and `delvewheel repair` (via
|
|
64
|
+
`tools/repair_windows_wheel.py`) on Windows; macOS is unchanged --
|
|
65
|
+
still the system Accelerate framework, nothing to vendor. The wheel
|
|
66
|
+
jobs print each repaired wheel's bundled libraries so this stays
|
|
67
|
+
verifiable rather than assumed.
|
|
68
|
+
- Windows support: `tools/build_libsedumi.sh` builds `libsedumi.dll` via
|
|
69
|
+
an MSYS2 MinGW64 toolchain (`mingw-w64-x86_64-gcc`) instead of
|
|
70
|
+
requiring MSVC -- `libsedumi.dll` is a plain ctypes-loaded DLL, not a
|
|
71
|
+
CPython extension, so it doesn't need to match whatever compiler built
|
|
72
|
+
Python itself. Exercised in CI on GitHub Actions' hosted Windows
|
|
73
|
+
runner; not yet hand-verified on a real Windows machine.
|
|
74
|
+
|
|
75
|
+
### Known limitations
|
|
76
|
+
|
|
77
|
+
- Complex Hermitian PSD problems (`K.scomplex`/`K.ycomplex`) are out of
|
|
78
|
+
scope.
|
|
79
|
+
- No wheels for Linux `aarch64`, Intel macOS, Alpine/musl, or 32-bit/ARM
|
|
80
|
+
Windows: those platforms install from the source distribution, which
|
|
81
|
+
needs a C compiler and a BLAS (see `docs/installation.rst`).
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# sedumipy Development Guide (Working Notes)
|
|
2
|
+
|
|
3
|
+
This document is a handoff resource for anyone new joining this project
|
|
4
|
+
to port SeDuMi off MATLAB/Octave — human or AI agent alike — so they can
|
|
5
|
+
keep working without getting lost. It summarizes what's done, what's
|
|
6
|
+
left, and the procedures/policies followed so far. For the detailed,
|
|
7
|
+
session-by-session bug-hunting narrative and the full history of how
|
|
8
|
+
each piece of work got done, see [`DEVLOG.md`](DEVLOG.md) — this file
|
|
9
|
+
stays focused on the current state and how to work on the project.
|
|
10
|
+
|
|
11
|
+
**On the repository layout:** this port originally lived under
|
|
12
|
+
`python_port/` inside `napinoco/sedumi` (a fork of `sqlp/sedumi`),
|
|
13
|
+
alongside the original MATLAB/C implementation. This repository
|
|
14
|
+
(`sedumipy`) is a clean spin-off containing only the code the port
|
|
15
|
+
needs. The original `.m`/MEX `.c` sources are kept for reference under
|
|
16
|
+
`vendor/sedumi-upstream/` (a submodule of `sqlp/sedumi`, pinned to the
|
|
17
|
+
commit the fork started from); oracle regeneration (producing comparison
|
|
18
|
+
data on real Octave) uses this submodule.
|
|
19
|
+
|
|
20
|
+
**Development environment prerequisites:** `pip install -e .[test]`
|
|
21
|
+
builds `libsedumi.so` on first import (`_native.py`'s `_ensure_built()`),
|
|
22
|
+
so a C compiler (`gcc`) must already be installed (`apt install
|
|
23
|
+
build-essential` on Debian/Ubuntu). For BLAS: **macOS always uses the
|
|
24
|
+
system Accelerate framework** (nothing to install — `tools/
|
|
25
|
+
build_libsedumi.sh`'s Darwin branch does this unconditionally, since
|
|
26
|
+
macOS never had Linux/Windows's "install/build your own BLAS" pain to
|
|
27
|
+
begin with, so scipy-openblas64 buys nothing there, and there's no
|
|
28
|
+
reason to give up Accelerate's Apple Silicon tuning just to match the
|
|
29
|
+
other platforms). On Linux/Windows, running `pip install
|
|
30
|
+
scipy-openblas64==0.3.34.106.0` before `pip install -e .[test]
|
|
31
|
+
--no-build-isolation` uses the same pip-installable, prebuilt ILP64
|
|
32
|
+
OpenBLAS (`scipy-openblas64`) that the published wheels themselves link
|
|
33
|
+
(`tools/build_libsedumi.sh` auto-detects whether it's importable; see
|
|
34
|
+
that file and `csrc/sedumi_platform.h`'s `SEDUMI_BLAS_ILP64` for
|
|
35
|
+
details). The version is pinned deliberately (so a breaking change
|
|
36
|
+
upstream doesn't suddenly break the build) — if you ever bump it, update
|
|
37
|
+
the same string in `.github/workflows/ci.yml`/`README.md`/
|
|
38
|
+
`docs/installation.rst` per the comment in `pyproject.toml`, and re-run
|
|
39
|
+
the tests and benchmarks. Without that package, it falls back to each
|
|
40
|
+
OS's system-build BLAS (on Linux, the `libblas`/`libopenblas` dev
|
|
41
|
+
headers, e.g. `apt install libopenblas-dev`; LAPACK is actually unused —
|
|
42
|
+
linking is BLAS-only). A bare container/CI environment may have neither
|
|
43
|
+
installed, causing the build to fail — if you hit a wall in a new
|
|
44
|
+
environment, suspect this first. (`.github/workflows/ci.yml` exercises
|
|
45
|
+
both paths on every run.)
|
|
46
|
+
|
|
47
|
+
**Windows development environment:** `tools/build_libsedumi.sh` is a
|
|
48
|
+
bash script and can't be run directly on Windows (`setup.py`/
|
|
49
|
+
`_native.py` explicitly invoke it via `bash tools/build_libsedumi.sh
|
|
50
|
+
...` only on Windows (`sys.platform == "win32"`)). Install
|
|
51
|
+
[MSYS2](https://www.msys2.org/), then from the MINGW64 shell run
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
pacman -S mingw-w64-x86_64-gcc
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
to put `bash`/`gcc` on Windows's `PATH` (`C:\msys64\mingw64\bin` and
|
|
58
|
+
`C:\msys64\usr\bin`); after that, building and testing follow the same
|
|
59
|
+
steps as on other OSes (BLAS uses the `scipy-openblas64` path above; if
|
|
60
|
+
you skip that, you'll also need to install
|
|
61
|
+
`mingw-w64-x86_64-openblas`). `libsedumi.dll` is dynamically linked
|
|
62
|
+
against the BLAS DLL and mingw runtime DLLs (it's a plain ctypes-loaded
|
|
63
|
+
DLL, not a CPython extension, so it was never tied to a particular
|
|
64
|
+
compiler), so producing a distributable wheel requires bundling those
|
|
65
|
+
with `delvewheel repair` (see `.github/workflows/wheels.yml`/
|
|
66
|
+
`tools/repair_windows_wheel.py`/`pyproject.toml`'s
|
|
67
|
+
`[tool.cibuildwheel.windows]`). This session had no real Windows machine
|
|
68
|
+
to verify behavior on (development on this repository happens on
|
|
69
|
+
Linux), so CI's results are the practical verification.
|
|
70
|
+
|
|
71
|
+
`tools/build_libsedumi.sh`'s Windows branch calls `gcc` neither via
|
|
72
|
+
`PATH` nor via MSYS2's `/mingw64` pseudo-path, but by a **Windows-style
|
|
73
|
+
absolute path**, `C:\msys64\mingw64\bin\gcc.exe` (overridable via the
|
|
74
|
+
`MSYS2_ROOT` environment variable). Two reasons, both confirmed on real
|
|
75
|
+
CI: (1) GitHub Actions' Windows runner ships with an unrelated,
|
|
76
|
+
pre-installed MinGW toolchain at `C:\mingw64`, and a bare `gcc` call
|
|
77
|
+
picks that one up instead (link fails for lack of `-lopenblas`). (2)
|
|
78
|
+
MSYS2's own POSIX-style `/mingw64` mount also doesn't resolve for a
|
|
79
|
+
non-interactive/non-login `bash script.sh` invocation (confirmed on CI:
|
|
80
|
+
even with `mingw-w64-x86_64-gcc` freshly installed, this produced
|
|
81
|
+
`/mingw64/bin/gcc.exe: No such file or directory`).
|
|
82
|
+
|
|
83
|
+
## 1. Project goal
|
|
84
|
+
|
|
85
|
+
Port SeDuMi (an interior-point solver for SDP/SOCP problems that runs on
|
|
86
|
+
MATLAB/Octave — roughly 96 `.m` files plus about 54 MEX `.c` files) to a
|
|
87
|
+
form with **zero dependency on either MATLAB or Octave**. Architecture
|
|
88
|
+
adopted (decided in an earlier session, "Option B"):
|
|
89
|
+
|
|
90
|
+
- The algorithm itself (interior-point iteration logic) → **Python
|
|
91
|
+
(NumPy/SciPy)**
|
|
92
|
+
- Performance-critical low-level kernels (Cholesky factorization, cone
|
|
93
|
+
arithmetic, etc.) → build the existing `.c` files with their MEX
|
|
94
|
+
dependency stripped out as a **standalone C library**
|
|
95
|
+
(`libsedumi.so`), called from Python via **ctypes**
|
|
96
|
+
|
|
97
|
+
The end goal is a `pip install`-able Python package with no
|
|
98
|
+
MATLAB/Octave dependency.
|
|
99
|
+
|
|
100
|
+
## 2. Overall phases and current progress
|
|
101
|
+
|
|
102
|
+
Per-phase tasks are tracked in the task-management tool (TaskList). As
|
|
103
|
+
of 2026-08-31:
|
|
104
|
+
|
|
105
|
+
| Phase | What | Status |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| Phase 0 | Verification harness (golden reference on real Octave) | **Done** |
|
|
108
|
+
| Phase 1 | Strip MEX from C kernels → standalone C library | **Done** |
|
|
109
|
+
| Phase 2 | Python bindings (ctypes) (clusters 1-5) | **Done** |
|
|
110
|
+
| Phase 3-a | Turn thin MEX-wrapper `.m` files into the public Python API | **Done** |
|
|
111
|
+
| Phase 3-b | Port cone-math utilities (eigK, psdeig, psdscale, etc.) | **Done** |
|
|
112
|
+
| Phase 3-c | Port interior-point iteration control logic (sdinit..optstep) | **Done** |
|
|
113
|
+
| Phase 3-d | Port `sedumi.m` itself + full verification against golden reference | **Done (LP+SOCP+PSD scope)** |
|
|
114
|
+
| Phase 4 | High-level API and I/O compatibility layer (.mat/SDPA) | **Done** |
|
|
115
|
+
| Phase 5 | Verification and benchmarking | **Done** |
|
|
116
|
+
| Phase 6 | Packaging and release | **Done** (Linux/macOS/Windows cibuildwheel builds in `.github/workflows/wheels.yml`, BLAS bundled into the wheels by `auditwheel`/`delvewheel`, source distribution completed by `MANIFEST.in` and install-tested in CI, published to PyPI on release via Trusted Publishing -- see [`RELEASING.md`](RELEASING.md)) |
|
|
117
|
+
|
|
118
|
+
Phase 3 (porting the interior-point algorithm itself) is **complete for
|
|
119
|
+
LP + SOCP (second-order cone) + PSD (positive semidefinite cone)
|
|
120
|
+
problems**: calling `sedumipy.sedumi.sedumi(A,b,c,K)` has been confirmed,
|
|
121
|
+
via real-oracle comparison, to return solutions that exactly match
|
|
122
|
+
Octave SeDuMi (`tests/test_sedumi.py`. The PSD-cone main-loop wiring is
|
|
123
|
+
in `getada_psd.py` (`build_aord`/`getada_psd`, using `incorder.py`/
|
|
124
|
+
`getsymbada.py`/`_native.getada1`/`getada2`/`getada3`), verified by the
|
|
125
|
+
same file's `sdp_feasible`/`sdp_mixed_cones_feasible` cases).
|
|
126
|
+
|
|
127
|
+
**Dense-column optimization is also ported** (`getdense.py`/
|
|
128
|
+
`symbcholden.py`/`deninfac.py`/`pcg.py`'s product-form preconditioning
|
|
129
|
+
correction, orchestrating `_native.symbfwblk`/`adendotd`/`adenscale`/
|
|
130
|
+
`dpr1fact`). Even on problems that actually contain dense columns
|
|
131
|
+
(`tests/test_sedumi.py::test_sedumi_dense_matches_octave`, deliberately
|
|
132
|
+
lowering `getdense.m`'s detection threshold via `pars.denf=3`), `iter`/
|
|
133
|
+
`numerr`/`pinf`/`dinf`/`x` all match the Octave version (see
|
|
134
|
+
[`DEVLOG.md`](DEVLOG.md) on "dual solution non-uniqueness" for `y`).
|
|
135
|
+
|
|
136
|
+
**Phase 5 (verification on real problems) is also complete**
|
|
137
|
+
(`tests/test_golden_end_to_end.py`): running `sedumipy.sedumi()` on the
|
|
138
|
+
real problems the Phase 0 golden reference targeted (from SDPLIB, under
|
|
139
|
+
`vendor/sedumi-upstream/examples/`: `nb`/`arch0`/`control07`/`trto3`/
|
|
140
|
+
`OH_2Pi_STO-6GN9r12g1T2` — `quantum` is excluded as out of scope, since
|
|
141
|
+
it's a complex-Hermitian PSD problem using `K.scomplex`/`K.ycomplex`)
|
|
142
|
+
confirmed the objective value matches the Octave golden reference. This
|
|
143
|
+
verification effort found and fixed two real bugs along the way — see
|
|
144
|
+
[`DEVLOG.md`](DEVLOG.md) for the details:
|
|
145
|
+
- The `K.s==0` (LP+SOCP only) path's ADA symbolic-Cholesky ordering was
|
|
146
|
+
missing part of the sparsity pattern that depends on the Lorentz
|
|
147
|
+
cone's arrow term (`d.q2`) — as `d.q2` grows, the Cholesky
|
|
148
|
+
factorization becomes inaccurate and PCG diverges (surfaced on
|
|
149
|
+
`nb.mat`, which has 396 SOCP blocks).
|
|
150
|
+
- `cpspdiag` (the diagonal-extraction helper the `K.s==0` branch of
|
|
151
|
+
`getada3` calls for diagnostics) used `bsearch()` via the `ibsearch`
|
|
152
|
+
macro, whose comparator hit the same qsort/bsearch
|
|
153
|
+
undefined-behavior class of bug as `sortnnz.c`/`iswnbr.c`. However,
|
|
154
|
+
since the actual `sedumi.py` call path never invokes `getada3` when
|
|
155
|
+
`K.s==0`, the real-world impact was limited to a test
|
|
156
|
+
(`test_getada_no_psd_blocks`).
|
|
157
|
+
|
|
158
|
+
## 3. Directory layout
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
sedumipy/ # repository root
|
|
162
|
+
vendor/
|
|
163
|
+
sedumi-upstream/ # submodule: sqlp/sedumi (pinned to the fork's starting commit, reference only)
|
|
164
|
+
csrc/ # standalone C kernel sources with mex.h stripped out (source for libsedumi.so)
|
|
165
|
+
*.c / *.h # forked to build MEX-free via sedumi_platform.h
|
|
166
|
+
sedumi_platform.c / .h
|
|
167
|
+
kernel_smoke/smoke_test.c # Phase 1 smoke test
|
|
168
|
+
src/
|
|
169
|
+
sedumipy/ # the ported Python package itself
|
|
170
|
+
_native.py # all ctypes bindings collected here (every C-kernel call goes through this)
|
|
171
|
+
libsedumi.so # built shared library (produced by tools/build_libsedumi.sh, gitignored)
|
|
172
|
+
cone.py # cone-math utilities (eigK, psdeig, psdscale, frameit, ...)
|
|
173
|
+
pretransfo.py / posttransfo.py # external <-> internal format conversion
|
|
174
|
+
sdinit.py # initial-point generation
|
|
175
|
+
sdfactor.py / sddir.py # self-dual embedding factorization and direction computation
|
|
176
|
+
pcg.py # preconditioned conjugate gradient (loopPcg/wrapPcg)
|
|
177
|
+
wregion.py # one iteration's predictor(+corrector) step
|
|
178
|
+
updtransfo.py # scaling-point update
|
|
179
|
+
maxstep.py / widelen.py / stepdif.py / trydif.py # step-length computation
|
|
180
|
+
getada.py / getdatm.py / deninfac.py # ADA matrix construction/factorization (K.s==0)
|
|
181
|
+
incorder.py / getsymbada.py / getada_psd.py # ADA matrix construction (K.s!=0)
|
|
182
|
+
symbchol.py # symbolic Cholesky of ADA (run once)
|
|
183
|
+
optstep.py # LP early-optimality check (optstep.m)
|
|
184
|
+
amul.py / checkpars.py # auxiliary utilities
|
|
185
|
+
sedumi.py # top-level driver (wires everything together)
|
|
186
|
+
matio.py # Phase 4: read/write .mat problem/solution files
|
|
187
|
+
sdpa.py # Phase 4: read/write SDPA sparse (.dat-s) format
|
|
188
|
+
tests/
|
|
189
|
+
test_*.py # per-module verification tests (oracle comparison)
|
|
190
|
+
fixtures/ # oracle data generated on real Octave (committed)
|
|
191
|
+
golden/ # Phase 0 golden reference
|
|
192
|
+
tools/
|
|
193
|
+
generate_*_oracle.m # per-test scripts that generate oracles from vendor/sedumi-upstream's Octave/MEX build
|
|
194
|
+
build_libsedumi.sh # builds libsedumi.so from csrc/
|
|
195
|
+
pyproject.toml
|
|
196
|
+
setup.py # Phase 6: build_ext hook that compiles libsedumi.so at wheel-build time
|
|
197
|
+
README.md # (somewhat stale — this CONTRIBUTING.md has the more current phase overview)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## 4. Development workflow (steps for porting a single `.m` file)
|
|
201
|
+
|
|
202
|
+
This is the procedure followed consistently so far. Follow it when
|
|
203
|
+
porting a new function.
|
|
204
|
+
|
|
205
|
+
1. **Read the target `.m` file's entire real source.** Understand the
|
|
206
|
+
implementation logic line by line, not just the comments. If it's a
|
|
207
|
+
thin MEX wrapper (a stub that just calls
|
|
208
|
+
`sedumi_binary_error()`), read the corresponding `.c` file instead.
|
|
209
|
+
2. **Write a faithful Python port.** Match variable names and
|
|
210
|
+
processing order to the `.m`/`.c` source as closely as possible, so
|
|
211
|
+
the two are easy to compare later. In the docstring, spell out what
|
|
212
|
+
was ported, which lines of the `.m` file it corresponds to, and any
|
|
213
|
+
parts deliberately omitted and why.
|
|
214
|
+
3. **Generate an oracle on real Octave.** Write
|
|
215
|
+
`tools/generate_<name>_oracle.m`, call the actual `.m`/MEX build
|
|
216
|
+
under `vendor/sedumi-upstream/` (with `install_sedumi` already run)
|
|
217
|
+
to save the input data and output to a `.mat` file.
|
|
218
|
+
```
|
|
219
|
+
octave-cli --no-gui --eval "cd tools; generate_<name>_oracle"
|
|
220
|
+
```
|
|
221
|
+
Reuse an existing fixture (e.g. `pretransfo`'s `K2`/`prep`) whenever
|
|
222
|
+
possible, rather than paying the cost of recomputing from scratch.
|
|
223
|
+
4. **Write `test_<name>.py` and compare.** Load the `.mat` file and
|
|
224
|
+
check the Python output against it with
|
|
225
|
+
`np.testing.assert_allclose`.
|
|
226
|
+
5. **When something doesn't match, debug by comparing intermediate
|
|
227
|
+
values one at a time.** Don't "fix it by feel" — print the same
|
|
228
|
+
variable from both the Octave side and the Python side and pin down
|
|
229
|
+
exactly where they first diverge. Every real bug found so far (see
|
|
230
|
+
[`DEVLOG.md`](DEVLOG.md)) was found this way.
|
|
231
|
+
6. **Run all of `python_port/tests/ -q` to check for regressions before
|
|
232
|
+
committing.** Commit messages should state what was ported, any bugs
|
|
233
|
+
found and fixed, and any deliberate scope limitations and why.
|
|
234
|
+
|
|
235
|
+
### A note on writing oracle scripts (random streams)
|
|
236
|
+
|
|
237
|
+
Octave's `rand('seed', N)` only resets the state of the uniform random
|
|
238
|
+
generator. `randn` is a separate stream, so any case using `randn` must
|
|
239
|
+
also call `randn('seed', N)` (forgetting this means a different dataset
|
|
240
|
+
is generated on every run, making the fixture unreproducible — this
|
|
241
|
+
actually happened and cost time in this session).
|
|
242
|
+
|
|
243
|
+
Also, inserting new code **in the middle** of an existing oracle-
|
|
244
|
+
generation script shifts every `rand()` call after it, silently
|
|
245
|
+
rewriting unrelated existing fixtures too. Always append new cases at
|
|
246
|
+
the **end** of the script, and check `git diff --stat` to confirm no
|
|
247
|
+
existing fixture file's size changed.
|
|
248
|
+
|
|
249
|
+
## 5. Scope limitations (deliberately unimplemented parts)
|
|
250
|
+
|
|
251
|
+
The following are not "gaps we didn't notice" but constraints
|
|
252
|
+
**deliberately rejected with `NotImplementedError`**, each documented
|
|
253
|
+
with its reasoning in the relevant module's docstring.
|
|
254
|
+
|
|
255
|
+
- **Rotated second-order cones (`K.r`)** are converted to standard
|
|
256
|
+
second-order cones (`K.q`) at the `pretransfo.py` stage, so no code
|
|
257
|
+
downstream needs to be aware of them (`sedumi.py`'s verification
|
|
258
|
+
tests include one rotated-cone case).
|
|
259
|
+
- **Console output, the v-plot, `pars.stopat`'s debug break, the
|
|
260
|
+
pre-solve rank diagnostic, and the DIMACS error metrics
|
|
261
|
+
(`info.err`)** are not ported. All of these are purely
|
|
262
|
+
diagnostic/display and have no effect on the returned `(x, y, info)`
|
|
263
|
+
values, so they were deprioritized.
|
|
264
|
+
|
|
265
|
+
## 6. Running the tests (and regenerating oracle fixtures)
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
cd sedumipy
|
|
269
|
+
git submodule update --init --recursive # first time only: fetches vendor/sedumi-upstream
|
|
270
|
+
.venv/bin/pip install -e .[test] # libsedumi.so is built automatically on first import
|
|
271
|
+
.venv/bin/python -m pytest tests/ -q
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
The test suite passes even without Octave installed (oracle data is
|
|
275
|
+
pre-generated and committed as `.mat` files, and the tests never call
|
|
276
|
+
Octave at runtime). Octave is only needed to **regenerate** an oracle
|
|
277
|
+
(with `install_sedumi` already run under `vendor/sedumi-upstream`):
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
octave-cli --no-gui --eval "cd tools; generate_<name>_oracle"
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## 7. Coding conventions and naming
|
|
284
|
+
|
|
285
|
+
- **`K` (the cone-structure struct) is represented as a Python `dict`.**
|
|
286
|
+
Field names match the `.m` version's `K.f`/`K.l`/`K.q`/... as closely
|
|
287
|
+
as possible (`K["l"]`, `K["mainblks"]`, etc.). Internal-only fields
|
|
288
|
+
computed by `pretransfo.py` (`mainblks`, `qblkstart`, `sblkstart`,
|
|
289
|
+
`lq`, `N`, `rsdpN`, etc.) are threaded through unchanged to every
|
|
290
|
+
downstream function.
|
|
291
|
+
- **Indexing is 0-indexed (Python-style) by default.** However, the
|
|
292
|
+
contents of `K` (e.g. `mainblks`) often still carry the original
|
|
293
|
+
`.m` file's 1-indexed values as-is, and callers convert with something
|
|
294
|
+
like `int(x) - 1` at each use site (there's no unified conversion
|
|
295
|
+
layer yet). When writing new code, mimic the indexing-conversion
|
|
296
|
+
pattern of the nearest existing similar function.
|
|
297
|
+
- **`scipy.sparse.csc_matrix` is the default sparse-matrix format.**
|
|
298
|
+
- **Every C-kernel call is collected in `_native.py`**; other modules
|
|
299
|
+
only ever touch C code through `_native.py`.
|
|
300
|
+
- **Every module's docstring states what it implements and what it
|
|
301
|
+
deliberately does not** — this project's consistent culture. A reader
|
|
302
|
+
should be able to tell the scope just from reading it.
|
|
303
|
+
|
|
304
|
+
## 8. Bugs found and detailed work history
|
|
305
|
+
|
|
306
|
+
See [`DEVLOG.md`](DEVLOG.md) for the full log of real bugs found during
|
|
307
|
+
porting (with root-cause analysis and measured before/after numbers) and
|
|
308
|
+
the session-by-session history of how packaging, benchmarking, and
|
|
309
|
+
performance work got done.
|