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.
Files changed (319) hide show
  1. sedumipy-0.0.1/CHANGELOG.md +81 -0
  2. sedumipy-0.0.1/CONTRIBUTING.md +309 -0
  3. sedumipy-0.0.1/LICENSE +340 -0
  4. sedumipy-0.0.1/MANIFEST.in +20 -0
  5. sedumipy-0.0.1/PKG-INFO +242 -0
  6. sedumipy-0.0.1/README.md +210 -0
  7. sedumipy-0.0.1/csrc/adendotd.c +246 -0
  8. sedumipy-0.0.1/csrc/adenscale.c +165 -0
  9. sedumipy-0.0.1/csrc/auxfwdpr1.c +122 -0
  10. sedumipy-0.0.1/csrc/auxgivens.c +191 -0
  11. sedumipy-0.0.1/csrc/blkaux.c +116 -0
  12. sedumipy-0.0.1/csrc/blkchol.c +442 -0
  13. sedumipy-0.0.1/csrc/blkchol2.c +565 -0
  14. sedumipy-0.0.1/csrc/blkmul.c +133 -0
  15. sedumipy-0.0.1/csrc/blksdp.h +212 -0
  16. sedumipy-0.0.1/csrc/bwblkslv.c +300 -0
  17. sedumipy-0.0.1/csrc/bwblkslv2.c +138 -0
  18. sedumipy-0.0.1/csrc/bwdpr1.c +277 -0
  19. sedumipy-0.0.1/csrc/cholsplit.c +186 -0
  20. sedumipy-0.0.1/csrc/choltmpsiz.c +175 -0
  21. sedumipy-0.0.1/csrc/ddot.c +310 -0
  22. sedumipy-0.0.1/csrc/dpr1fact.c +850 -0
  23. sedumipy-0.0.1/csrc/extractA.c +192 -0
  24. sedumipy-0.0.1/csrc/findblks.c +237 -0
  25. sedumipy-0.0.1/csrc/finsymbden.c +216 -0
  26. sedumipy-0.0.1/csrc/fwblkslv.c +322 -0
  27. sedumipy-0.0.1/csrc/fwdpr1.c +204 -0
  28. sedumipy-0.0.1/csrc/getada1.c +263 -0
  29. sedumipy-0.0.1/csrc/getada2.c +216 -0
  30. sedumipy-0.0.1/csrc/getada3.c +571 -0
  31. sedumipy-0.0.1/csrc/givens.h +52 -0
  32. sedumipy-0.0.1/csrc/givensrot.c +170 -0
  33. sedumipy-0.0.1/csrc/incorder.c +345 -0
  34. sedumipy-0.0.1/csrc/invcholfac.c +170 -0
  35. sedumipy-0.0.1/csrc/iswnbr.c +270 -0
  36. sedumipy-0.0.1/csrc/kernel_smoke/smoke_test.c +55 -0
  37. sedumipy-0.0.1/csrc/mJdetd.c +98 -0
  38. sedumipy-0.0.1/csrc/ordmmd.c +1158 -0
  39. sedumipy-0.0.1/csrc/ordmmd.h +10 -0
  40. sedumipy-0.0.1/csrc/ordmmdmex.c +141 -0
  41. sedumipy-0.0.1/csrc/partitA.c +156 -0
  42. sedumipy-0.0.1/csrc/psdframeit.c +170 -0
  43. sedumipy-0.0.1/csrc/psdinvjmul.c +229 -0
  44. sedumipy-0.0.1/csrc/qblkmul.c +118 -0
  45. sedumipy-0.0.1/csrc/qrK.c +298 -0
  46. sedumipy-0.0.1/csrc/quadadd.c +132 -0
  47. sedumipy-0.0.1/csrc/reflect.c +357 -0
  48. sedumipy-0.0.1/csrc/reflect.h +48 -0
  49. sedumipy-0.0.1/csrc/sdmauxCmp.c +205 -0
  50. sedumipy-0.0.1/csrc/sdmauxCone.c +199 -0
  51. sedumipy-0.0.1/csrc/sdmauxFill.c +75 -0
  52. sedumipy-0.0.1/csrc/sdmauxRdot.c +59 -0
  53. sedumipy-0.0.1/csrc/sdmauxScalarmul.c +70 -0
  54. sedumipy-0.0.1/csrc/sdmauxTriu.c +145 -0
  55. sedumipy-0.0.1/csrc/sdmauxTriudot.c +75 -0
  56. sedumipy-0.0.1/csrc/sedumi_platform.c +31 -0
  57. sedumipy-0.0.1/csrc/sedumi_platform.h +165 -0
  58. sedumipy-0.0.1/csrc/sortnnz.c +142 -0
  59. sedumipy-0.0.1/csrc/spscale.c +773 -0
  60. sedumipy-0.0.1/csrc/sqrtinv.c +147 -0
  61. sedumipy-0.0.1/csrc/symbchol.c +183 -0
  62. sedumipy-0.0.1/csrc/symbfwblk.c +379 -0
  63. sedumipy-0.0.1/csrc/symfct.c +2295 -0
  64. sedumipy-0.0.1/csrc/symfct.h +17 -0
  65. sedumipy-0.0.1/csrc/symfctmex.c +274 -0
  66. sedumipy-0.0.1/csrc/triuaux.c +741 -0
  67. sedumipy-0.0.1/csrc/triuaux.h +70 -0
  68. sedumipy-0.0.1/csrc/urotorder.c +492 -0
  69. sedumipy-0.0.1/csrc/vecsym.c +177 -0
  70. sedumipy-0.0.1/pyproject.toml +165 -0
  71. sedumipy-0.0.1/setup.cfg +4 -0
  72. sedumipy-0.0.1/setup.py +123 -0
  73. sedumipy-0.0.1/src/sedumipy/__init__.py +34 -0
  74. sedumipy-0.0.1/src/sedumipy/_native.py +2405 -0
  75. sedumipy-0.0.1/src/sedumipy/amul.py +34 -0
  76. sedumipy-0.0.1/src/sedumipy/checkpars.py +83 -0
  77. sedumipy-0.0.1/src/sedumipy/cone.py +785 -0
  78. sedumipy-0.0.1/src/sedumipy/deninfac.py +58 -0
  79. sedumipy-0.0.1/src/sedumipy/getada.py +63 -0
  80. sedumipy-0.0.1/src/sedumipy/getada_psd.py +114 -0
  81. sedumipy-0.0.1/src/sedumipy/getdatm.py +96 -0
  82. sedumipy-0.0.1/src/sedumipy/getdense.py +94 -0
  83. sedumipy-0.0.1/src/sedumipy/getsymbada.py +68 -0
  84. sedumipy-0.0.1/src/sedumipy/incorder.py +110 -0
  85. sedumipy-0.0.1/src/sedumipy/matio.py +106 -0
  86. sedumipy-0.0.1/src/sedumipy/maxstep.py +72 -0
  87. sedumipy-0.0.1/src/sedumipy/neighborhood.py +86 -0
  88. sedumipy-0.0.1/src/sedumipy/optstep.py +108 -0
  89. sedumipy-0.0.1/src/sedumipy/pcg.py +259 -0
  90. sedumipy-0.0.1/src/sedumipy/posttransfo.py +44 -0
  91. sedumipy-0.0.1/src/sedumipy/pretransfo.py +448 -0
  92. sedumipy-0.0.1/src/sedumipy/sddir.py +47 -0
  93. sedumipy-0.0.1/src/sedumipy/sdfactor.py +38 -0
  94. sedumipy-0.0.1/src/sedumipy/sdinit.py +72 -0
  95. sedumipy-0.0.1/src/sedumipy/sdpa.py +200 -0
  96. sedumipy-0.0.1/src/sedumipy/sedumi.py +367 -0
  97. sedumipy-0.0.1/src/sedumipy/stepdif.py +111 -0
  98. sedumipy-0.0.1/src/sedumipy/symbchol.py +43 -0
  99. sedumipy-0.0.1/src/sedumipy/symbcholden.py +65 -0
  100. sedumipy-0.0.1/src/sedumipy/trydif.py +58 -0
  101. sedumipy-0.0.1/src/sedumipy/updtransfo.py +89 -0
  102. sedumipy-0.0.1/src/sedumipy/widelen.py +125 -0
  103. sedumipy-0.0.1/src/sedumipy/wregion.py +185 -0
  104. sedumipy-0.0.1/src/sedumipy.egg-info/PKG-INFO +242 -0
  105. sedumipy-0.0.1/src/sedumipy.egg-info/SOURCES.txt +317 -0
  106. sedumipy-0.0.1/src/sedumipy.egg-info/dependency_links.txt +1 -0
  107. sedumipy-0.0.1/src/sedumipy.egg-info/requires.txt +10 -0
  108. sedumipy-0.0.1/src/sedumipy.egg-info/top_level.txt +1 -0
  109. sedumipy-0.0.1/tests/fixtures/adendotd/case1.mat +0 -0
  110. sedumipy-0.0.1/tests/fixtures/adendotd/case2.mat +0 -0
  111. sedumipy-0.0.1/tests/fixtures/adenscale/case1.mat +0 -0
  112. sedumipy-0.0.1/tests/fixtures/adenscale/case2.mat +0 -0
  113. sedumipy-0.0.1/tests/fixtures/adenscale/case3.mat +0 -0
  114. sedumipy-0.0.1/tests/fixtures/blkchol/grid5x5_blkchol_oracle.mat +0 -0
  115. sedumipy-0.0.1/tests/fixtures/blkchol/grid5x5_spd.mat +0 -0
  116. sedumipy-0.0.1/tests/fixtures/blkchol/path5_blkchol_oracle.mat +0 -0
  117. sedumipy-0.0.1/tests/fixtures/blkchol/path5_spd.mat +0 -0
  118. sedumipy-0.0.1/tests/fixtures/blkchol/rand10_blkchol_oracle.mat +0 -0
  119. sedumipy-0.0.1/tests/fixtures/blkchol/rand10_spd.mat +0 -0
  120. sedumipy-0.0.1/tests/fixtures/blkchol/rand25_blkchol_oracle.mat +0 -0
  121. sedumipy-0.0.1/tests/fixtures/blkchol/rand25_spd.mat +0 -0
  122. sedumipy-0.0.1/tests/fixtures/blkchol/star5_blkchol_oracle.mat +0 -0
  123. sedumipy-0.0.1/tests/fixtures/blkchol/star5_spd.mat +0 -0
  124. sedumipy-0.0.1/tests/fixtures/blkchol_edge/pure_add.mat +0 -0
  125. sedumipy-0.0.1/tests/fixtures/blkchol_edge/pure_add_oracle.mat +0 -0
  126. sedumipy-0.0.1/tests/fixtures/blkchol_edge/pure_skip.mat +0 -0
  127. sedumipy-0.0.1/tests/fixtures/blkchol_edge/pure_skip_oracle.mat +0 -0
  128. sedumipy-0.0.1/tests/fixtures/blkchol_edge/skip_and_add.mat +0 -0
  129. sedumipy-0.0.1/tests/fixtures/blkchol_edge/skip_and_add2.mat +0 -0
  130. sedumipy-0.0.1/tests/fixtures/blkchol_edge/skip_and_add2_oracle.mat +0 -0
  131. sedumipy-0.0.1/tests/fixtures/blkchol_edge/skip_and_add_oracle.mat +0 -0
  132. sedumipy-0.0.1/tests/fixtures/checkpars/alg0.mat +0 -0
  133. sedumipy-0.0.1/tests/fixtures/checkpars/empty.mat +0 -0
  134. sedumipy-0.0.1/tests/fixtures/checkpars/nested.mat +0 -0
  135. sedumipy-0.0.1/tests/fixtures/checkpars/partial.mat +0 -0
  136. sedumipy-0.0.1/tests/fixtures/checkpars/w.mat +0 -0
  137. sedumipy-0.0.1/tests/fixtures/checkpars/w_bad.mat +0 -0
  138. sedumipy-0.0.1/tests/fixtures/cluster1/ddot_dense.mat +0 -0
  139. sedumipy-0.0.1/tests/fixtures/cluster1/ddot_offset.mat +0 -0
  140. sedumipy-0.0.1/tests/fixtures/cluster1/qblkmul.mat +0 -0
  141. sedumipy-0.0.1/tests/fixtures/cluster1/quadadd.mat +0 -0
  142. sedumipy-0.0.1/tests/fixtures/cluster1/vecsym.mat +0 -0
  143. sedumipy-0.0.1/tests/fixtures/cluster2/dpr1fact_n1.mat +0 -0
  144. sedumipy-0.0.1/tests/fixtures/cluster2/dpr1fact_n2.mat +0 -0
  145. sedumipy-0.0.1/tests/fixtures/cluster3/K.mat +0 -0
  146. sedumipy-0.0.1/tests/fixtures/cluster3/givensrot.mat +0 -0
  147. sedumipy-0.0.1/tests/fixtures/cluster3/invcholfac.mat +0 -0
  148. sedumipy-0.0.1/tests/fixtures/cluster3/psdframeit.mat +0 -0
  149. sedumipy-0.0.1/tests/fixtures/cluster3/psdinvjmul.mat +0 -0
  150. sedumipy-0.0.1/tests/fixtures/cluster3/psdinvjmul_full.mat +0 -0
  151. sedumipy-0.0.1/tests/fixtures/cluster3/qrK.mat +0 -0
  152. sedumipy-0.0.1/tests/fixtures/cluster3/sqrtinv.mat +0 -0
  153. sedumipy-0.0.1/tests/fixtures/cluster3/urotorder.mat +0 -0
  154. sedumipy-0.0.1/tests/fixtures/cluster3/urotorder_permin.mat +0 -0
  155. sedumipy-0.0.1/tests/fixtures/cluster4/extractA.mat +0 -0
  156. sedumipy-0.0.1/tests/fixtures/cluster4/findblks.mat +0 -0
  157. sedumipy-0.0.1/tests/fixtures/cluster4/partitA.mat +0 -0
  158. sedumipy-0.0.1/tests/fixtures/cluster5/cholsplit.mat +0 -0
  159. sedumipy-0.0.1/tests/fixtures/cluster5/sortnnz.mat +0 -0
  160. sedumipy-0.0.1/tests/fixtures/cone/cone2.mat +0 -0
  161. sedumipy-0.0.1/tests/fixtures/cone/cone2_frameit.mat +0 -0
  162. sedumipy-0.0.1/tests/fixtures/cone/eigK.mat +0 -0
  163. sedumipy-0.0.1/tests/fixtures/generate_blkchol_fixtures.py +57 -0
  164. sedumipy-0.0.1/tests/fixtures/generate_ordmmd_fixtures.py +75 -0
  165. sedumipy-0.0.1/tests/fixtures/getada/case1.mat +0 -0
  166. sedumipy-0.0.1/tests/fixtures/getada/case2.mat +0 -0
  167. sedumipy-0.0.1/tests/fixtures/getada/case3.mat +0 -0
  168. sedumipy-0.0.1/tests/fixtures/getada/case4.mat +0 -0
  169. sedumipy-0.0.1/tests/fixtures/getada_psd/case1.mat +0 -0
  170. sedumipy-0.0.1/tests/fixtures/getada_psd/case2.mat +0 -0
  171. sedumipy-0.0.1/tests/fixtures/getada_psd/case3.mat +0 -0
  172. sedumipy-0.0.1/tests/fixtures/getdense/case1.mat +0 -0
  173. sedumipy-0.0.1/tests/fixtures/getdense/case2.mat +0 -0
  174. sedumipy-0.0.1/tests/fixtures/getdense/case3.mat +0 -0
  175. sedumipy-0.0.1/tests/fixtures/getdense/case4.mat +0 -0
  176. sedumipy-0.0.1/tests/fixtures/getdense/case5.mat +0 -0
  177. sedumipy-0.0.1/tests/fixtures/getsymbada/case1.mat +0 -0
  178. sedumipy-0.0.1/tests/fixtures/getsymbada/case2.mat +0 -0
  179. sedumipy-0.0.1/tests/fixtures/getsymbada/case3.mat +0 -0
  180. sedumipy-0.0.1/tests/fixtures/getsymbada/case4.mat +0 -0
  181. sedumipy-0.0.1/tests/fixtures/incorder/case1.mat +0 -0
  182. sedumipy-0.0.1/tests/fixtures/incorder/case2.mat +0 -0
  183. sedumipy-0.0.1/tests/fixtures/incorder/case3.mat +0 -0
  184. sedumipy-0.0.1/tests/fixtures/incorder/case4.mat +0 -0
  185. sedumipy-0.0.1/tests/fixtures/iswnbr/case1.mat +0 -0
  186. sedumipy-0.0.1/tests/fixtures/iswnbr/case2.mat +0 -0
  187. sedumipy-0.0.1/tests/fixtures/iswnbr/case3.mat +0 -0
  188. sedumipy-0.0.1/tests/fixtures/iswnbr/case4.mat +0 -0
  189. sedumipy-0.0.1/tests/fixtures/ordmmd/grid5x5.mat +0 -0
  190. sedumipy-0.0.1/tests/fixtures/ordmmd/grid5x5_oracle.mat +0 -0
  191. sedumipy-0.0.1/tests/fixtures/ordmmd/grid5x5_symfct_oracle.mat +0 -0
  192. sedumipy-0.0.1/tests/fixtures/ordmmd/path5.mat +0 -0
  193. sedumipy-0.0.1/tests/fixtures/ordmmd/path5_oracle.mat +0 -0
  194. sedumipy-0.0.1/tests/fixtures/ordmmd/path5_symfct_oracle.mat +0 -0
  195. sedumipy-0.0.1/tests/fixtures/ordmmd/rand10.mat +0 -0
  196. sedumipy-0.0.1/tests/fixtures/ordmmd/rand10_oracle.mat +0 -0
  197. sedumipy-0.0.1/tests/fixtures/ordmmd/rand10_symfct_oracle.mat +0 -0
  198. sedumipy-0.0.1/tests/fixtures/ordmmd/rand25.mat +0 -0
  199. sedumipy-0.0.1/tests/fixtures/ordmmd/rand25_oracle.mat +0 -0
  200. sedumipy-0.0.1/tests/fixtures/ordmmd/rand25_symfct_oracle.mat +0 -0
  201. sedumipy-0.0.1/tests/fixtures/ordmmd/rand50.mat +0 -0
  202. sedumipy-0.0.1/tests/fixtures/ordmmd/rand50_oracle.mat +0 -0
  203. sedumipy-0.0.1/tests/fixtures/ordmmd/rand50_symfct_oracle.mat +0 -0
  204. sedumipy-0.0.1/tests/fixtures/ordmmd/star5.mat +0 -0
  205. sedumipy-0.0.1/tests/fixtures/ordmmd/star5_oracle.mat +0 -0
  206. sedumipy-0.0.1/tests/fixtures/ordmmd/star5_symfct_oracle.mat +0 -0
  207. sedumipy-0.0.1/tests/fixtures/posttransfo/complex_sdp.mat +0 -0
  208. sedumipy-0.0.1/tests/fixtures/posttransfo/real_only.mat +0 -0
  209. sedumipy-0.0.1/tests/fixtures/posttransfo/with_ycomplex.mat +0 -0
  210. sedumipy-0.0.1/tests/fixtures/pretransfo/complex_sdp_all.mat +0 -0
  211. sedumipy-0.0.1/tests/fixtures/pretransfo/complex_sdp_single.mat +0 -0
  212. sedumipy-0.0.1/tests/fixtures/pretransfo/free_lorentz.mat +0 -0
  213. sedumipy-0.0.1/tests/fixtures/pretransfo/free_split.mat +0 -0
  214. sedumipy-0.0.1/tests/fixtures/pretransfo/kitchen_sink_lorentz.mat +0 -0
  215. sedumipy-0.0.1/tests/fixtures/pretransfo/kitchen_sink_split.mat +0 -0
  216. sedumipy-0.0.1/tests/fixtures/pretransfo/lorentz.mat +0 -0
  217. sedumipy-0.0.1/tests/fixtures/pretransfo/lp_only.mat +0 -0
  218. sedumipy-0.0.1/tests/fixtures/pretransfo/mixed_l_q_r.mat +0 -0
  219. sedumipy-0.0.1/tests/fixtures/pretransfo/real_sdp.mat +0 -0
  220. sedumipy-0.0.1/tests/fixtures/pretransfo/real_sdp_diag.mat +0 -0
  221. sedumipy-0.0.1/tests/fixtures/pretransfo/rotated_lorentz.mat +0 -0
  222. sedumipy-0.0.1/tests/fixtures/pretransfo/xcomplex_mixed.mat +0 -0
  223. sedumipy-0.0.1/tests/fixtures/pretransfo/ycomplex.mat +0 -0
  224. sedumipy-0.0.1/tests/fixtures/sdinit/amul.mat +0 -0
  225. sedumipy-0.0.1/tests/fixtures/sdinit/deninfac_case1.mat +0 -0
  226. sedumipy-0.0.1/tests/fixtures/sdinit/deninfac_case2.mat +0 -0
  227. sedumipy-0.0.1/tests/fixtures/sdinit/getdatm.mat +0 -0
  228. sedumipy-0.0.1/tests/fixtures/sdinit/getdatm_dense.mat +0 -0
  229. sedumipy-0.0.1/tests/fixtures/sdinit/maxstep.mat +0 -0
  230. sedumipy-0.0.1/tests/fixtures/sdinit/optstep.mat +0 -0
  231. sedumipy-0.0.1/tests/fixtures/sdinit/pcg.mat +0 -0
  232. sedumipy-0.0.1/tests/fixtures/sdinit/pcg_dense.mat +0 -0
  233. sedumipy-0.0.1/tests/fixtures/sdinit/popk.mat +0 -0
  234. sedumipy-0.0.1/tests/fixtures/sdinit/sddir.mat +0 -0
  235. sedumipy-0.0.1/tests/fixtures/sdinit/sdinit_case1.mat +0 -0
  236. sedumipy-0.0.1/tests/fixtures/sdinit/tdet_asmdxq.mat +0 -0
  237. sedumipy-0.0.1/tests/fixtures/sdinit/trydif.mat +0 -0
  238. sedumipy-0.0.1/tests/fixtures/sdinit/updtransfo.mat +0 -0
  239. sedumipy-0.0.1/tests/fixtures/sdinit/widelen.mat +0 -0
  240. sedumipy-0.0.1/tests/fixtures/sdinit/wregion_case1.mat +0 -0
  241. sedumipy-0.0.1/tests/fixtures/sdinit/wregion_case2.mat +0 -0
  242. sedumipy-0.0.1/tests/fixtures/sdpa/test_problem.dat-s +14 -0
  243. sedumipy-0.0.1/tests/fixtures/sdpa/test_problem_oracle.mat +0 -0
  244. sedumipy-0.0.1/tests/fixtures/search_blkchol_diagadd.py +66 -0
  245. sedumipy-0.0.1/tests/fixtures/search_blkchol_diagadd2.py +65 -0
  246. sedumipy-0.0.1/tests/fixtures/search_blkchol_edge_cases.py +69 -0
  247. sedumipy-0.0.1/tests/fixtures/sedumi/lp_feasible.mat +0 -0
  248. sedumipy-0.0.1/tests/fixtures/sedumi/lp_free_feasible.mat +0 -0
  249. sedumipy-0.0.1/tests/fixtures/sedumi/lp_infeasible.mat +0 -0
  250. sedumipy-0.0.1/tests/fixtures/sedumi/lp_socp_sdp_dense_feasible.mat +0 -0
  251. sedumipy-0.0.1/tests/fixtures/sedumi/lp_sparse_feasible.mat +0 -0
  252. sedumipy-0.0.1/tests/fixtures/sedumi/rotated_cone_feasible.mat +0 -0
  253. sedumipy-0.0.1/tests/fixtures/sedumi/sdp_feasible.mat +0 -0
  254. sedumipy-0.0.1/tests/fixtures/sedumi/sdp_mixed_cones_feasible.mat +0 -0
  255. sedumipy-0.0.1/tests/fixtures/sedumi/socp_feasible.mat +0 -0
  256. sedumipy-0.0.1/tests/fixtures/sedumi/socp_two_blocks.mat +0 -0
  257. sedumipy-0.0.1/tests/fixtures/stepdif/case1_tpmtd_pos_sdpos.mat +0 -0
  258. sedumipy-0.0.1/tests/fixtures/stepdif/case2_tpmtd_neg_sdpos.mat +0 -0
  259. sedumipy-0.0.1/tests/fixtures/stepdif/case3_sdneg.mat +0 -0
  260. sedumipy-0.0.1/tests/fixtures/stepdif/case4_sdzero.mat +0 -0
  261. sedumipy-0.0.1/tests/fixtures/stepdif/case5_large_step.mat +0 -0
  262. sedumipy-0.0.1/tests/fixtures/stepdif/case6_large_step_neg_tpmtd.mat +0 -0
  263. sedumipy-0.0.1/tests/fixtures/stepdif/case7_interior_minimizer.mat +0 -0
  264. sedumipy-0.0.1/tests/fixtures/stepdif/case8_breakpoint.mat +0 -0
  265. sedumipy-0.0.1/tests/fixtures/symbcholden/case1.mat +0 -0
  266. sedumipy-0.0.1/tests/fixtures/symbcholden/case2.mat +0 -0
  267. sedumipy-0.0.1/tests/fixtures/symbcholden/case3.mat +0 -0
  268. sedumipy-0.0.1/tests/fixtures/symbfwblk/case1.mat +0 -0
  269. sedumipy-0.0.1/tests/fixtures/symbfwblk/case2.mat +0 -0
  270. sedumipy-0.0.1/tests/fixtures/symbfwblk/case3.mat +0 -0
  271. sedumipy-0.0.1/tests/test_adendotd.py +52 -0
  272. sedumipy-0.0.1/tests/test_adenscale.py +48 -0
  273. sedumipy-0.0.1/tests/test_benchmarks.py +528 -0
  274. sedumipy-0.0.1/tests/test_blkchol.py +98 -0
  275. sedumipy-0.0.1/tests/test_blkchol_edge_cases.py +96 -0
  276. sedumipy-0.0.1/tests/test_checkpars.py +87 -0
  277. sedumipy-0.0.1/tests/test_cluster1.py +85 -0
  278. sedumipy-0.0.1/tests/test_cluster2.py +120 -0
  279. sedumipy-0.0.1/tests/test_cluster3.py +145 -0
  280. sedumipy-0.0.1/tests/test_cluster4.py +68 -0
  281. sedumipy-0.0.1/tests/test_cluster5.py +74 -0
  282. sedumipy-0.0.1/tests/test_cone.py +111 -0
  283. sedumipy-0.0.1/tests/test_cone2.py +179 -0
  284. sedumipy-0.0.1/tests/test_deninfac.py +103 -0
  285. sedumipy-0.0.1/tests/test_getada.py +100 -0
  286. sedumipy-0.0.1/tests/test_getada_psd.py +77 -0
  287. sedumipy-0.0.1/tests/test_getdatm.py +94 -0
  288. sedumipy-0.0.1/tests/test_getdense.py +72 -0
  289. sedumipy-0.0.1/tests/test_getsymbada.py +68 -0
  290. sedumipy-0.0.1/tests/test_golden_end_to_end.py +108 -0
  291. sedumipy-0.0.1/tests/test_golden_reference.py +89 -0
  292. sedumipy-0.0.1/tests/test_incorder.py +77 -0
  293. sedumipy-0.0.1/tests/test_iswnbr.py +38 -0
  294. sedumipy-0.0.1/tests/test_matio.py +137 -0
  295. sedumipy-0.0.1/tests/test_maxstep.py +51 -0
  296. sedumipy-0.0.1/tests/test_native_bindings.py +67 -0
  297. sedumipy-0.0.1/tests/test_native_sparse_solve.py +89 -0
  298. sedumipy-0.0.1/tests/test_optstep.py +92 -0
  299. sedumipy-0.0.1/tests/test_ordmmd.py +62 -0
  300. sedumipy-0.0.1/tests/test_pcg.py +190 -0
  301. sedumipy-0.0.1/tests/test_popk.py +53 -0
  302. sedumipy-0.0.1/tests/test_posttransfo.py +60 -0
  303. sedumipy-0.0.1/tests/test_pretransfo.py +130 -0
  304. sedumipy-0.0.1/tests/test_sddir.py +127 -0
  305. sedumipy-0.0.1/tests/test_sdinit.py +105 -0
  306. sedumipy-0.0.1/tests/test_sdpa.py +72 -0
  307. sedumipy-0.0.1/tests/test_sedumi.py +132 -0
  308. sedumipy-0.0.1/tests/test_sparse_solve_pipeline.py +77 -0
  309. sedumipy-0.0.1/tests/test_stepdif.py +58 -0
  310. sedumipy-0.0.1/tests/test_symbchol.py +103 -0
  311. sedumipy-0.0.1/tests/test_symbcholden.py +62 -0
  312. sedumipy-0.0.1/tests/test_symbfwblk.py +54 -0
  313. sedumipy-0.0.1/tests/test_symfct.py +80 -0
  314. sedumipy-0.0.1/tests/test_tdet_asmdxq.py +79 -0
  315. sedumipy-0.0.1/tests/test_trydif.py +88 -0
  316. sedumipy-0.0.1/tests/test_updtransfo.py +70 -0
  317. sedumipy-0.0.1/tests/test_widelen.py +73 -0
  318. sedumipy-0.0.1/tests/test_wregion.py +133 -0
  319. 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.