synkit 1.6.5__py3-none-win_amd64.whl

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 (636) hide show
  1. synkit/CRN/Benchmark/__init__.py +53 -0
  2. synkit/CRN/Benchmark/crosschecks.py +13 -0
  3. synkit/CRN/Benchmark/kegg.py +12 -0
  4. synkit/CRN/Benchmark/networks.py +13 -0
  5. synkit/CRN/Benchmark/scaling.py +13 -0
  6. synkit/CRN/Benchmark/validate.py +13 -0
  7. synkit/CRN/Construct/__init__.py +16 -0
  8. synkit/CRN/Construct/abstract.py +668 -0
  9. synkit/CRN/Construct/arity.py +36 -0
  10. synkit/CRN/Construct/builder.py +619 -0
  11. synkit/CRN/Construct/derivation.py +63 -0
  12. synkit/CRN/Construct/flattener.py +100 -0
  13. synkit/CRN/Construct/keys.py +14 -0
  14. synkit/CRN/Construct/mixtures.py +117 -0
  15. synkit/CRN/Construct/rdkit_worker.py +69 -0
  16. synkit/CRN/Construct/smiles.py +99 -0
  17. synkit/CRN/Construct/state.py +31 -0
  18. synkit/CRN/Construct/strategy.py +75 -0
  19. synkit/CRN/Construct/worker.py +42 -0
  20. synkit/CRN/IO/__init__.py +36 -0
  21. synkit/CRN/IO/sbml.py +925 -0
  22. synkit/CRN/Pathway/__init__.py +72 -0
  23. synkit/CRN/Pathway/_adapter.py +333 -0
  24. synkit/CRN/Pathway/pathfinder.py +500 -0
  25. synkit/CRN/Pathway/reachability.py +796 -0
  26. synkit/CRN/Pathway/realizability.py +1322 -0
  27. synkit/CRN/Petrinet/__init__.py +93 -0
  28. synkit/CRN/Petrinet/analyzer.py +486 -0
  29. synkit/CRN/Petrinet/minimal_semiflows.py +436 -0
  30. synkit/CRN/Petrinet/net.py +1041 -0
  31. synkit/CRN/Petrinet/persistence.py +97 -0
  32. synkit/CRN/Petrinet/semiflows.py +483 -0
  33. synkit/CRN/Petrinet/siphon_search.py +402 -0
  34. synkit/CRN/Petrinet/structure.py +286 -0
  35. synkit/CRN/Props/__init__.py +130 -0
  36. synkit/CRN/Props/_rank.py +29 -0
  37. synkit/CRN/Props/deficiency.py +953 -0
  38. synkit/CRN/Props/dynamics.py +832 -0
  39. synkit/CRN/Props/helper.py +151 -0
  40. synkit/CRN/Props/stoich.py +751 -0
  41. synkit/CRN/Props/thermo.py +584 -0
  42. synkit/CRN/Query/__init__.py +66 -0
  43. synkit/CRN/Query/cache.py +41 -0
  44. synkit/CRN/Query/kegg_api.py +99 -0
  45. synkit/CRN/Query/kegg_extract.py +714 -0
  46. synkit/CRN/Query/kegg_impute.py +707 -0
  47. synkit/CRN/Query/kegg_parse.py +480 -0
  48. synkit/CRN/Query/to_syncrn.py +290 -0
  49. synkit/CRN/README.md +234 -0
  50. synkit/CRN/Structure/__init__.py +12 -0
  51. synkit/CRN/Structure/_graph_io.py +713 -0
  52. synkit/CRN/Structure/_matrices.py +88 -0
  53. synkit/CRN/Structure/_parse.py +544 -0
  54. synkit/CRN/Structure/reaction.py +237 -0
  55. synkit/CRN/Structure/rule.py +55 -0
  56. synkit/CRN/Structure/species.py +46 -0
  57. synkit/CRN/Structure/syncrn.py +929 -0
  58. synkit/CRN/Symmetry/__init__.py +20 -0
  59. synkit/CRN/Symmetry/_common.py +1059 -0
  60. synkit/CRN/Symmetry/_ir.py +940 -0
  61. synkit/CRN/Symmetry/automorphism.py +472 -0
  62. synkit/CRN/Symmetry/canon.py +441 -0
  63. synkit/CRN/Symmetry/isomorphism.py +412 -0
  64. synkit/CRN/Symmetry/symmetry.py +61 -0
  65. synkit/CRN/Symmetry/wl_canon.py +967 -0
  66. synkit/CRN/Visualize/__init__.py +11 -0
  67. synkit/CRN/Visualize/labels.py +113 -0
  68. synkit/CRN/Visualize/layout.py +708 -0
  69. synkit/CRN/Visualize/palette.py +292 -0
  70. synkit/CRN/Visualize/validation.py +122 -0
  71. synkit/CRN/Visualize/vis.py +1152 -0
  72. synkit/CRN/__init__.py +233 -0
  73. synkit/CRN/_build.py +50 -0
  74. synkit/CRN/_native_build.py +175 -0
  75. synkit/CRN/analysis.py +629 -0
  76. synkit/CRN/backend.py +74 -0
  77. synkit/CRN/cpp/CMakeLists.txt +58 -0
  78. synkit/CRN/cpp/algebra.cpp +46 -0
  79. synkit/CRN/cpp/closure.cpp +29 -0
  80. synkit/CRN/cpp/exact.h +55 -0
  81. synkit/CRN/cpp/pathway.cpp +46 -0
  82. synkit/CRN/cpp/semiflows.cpp +209 -0
  83. synkit/CRN/cpp/structural.cpp +240 -0
  84. synkit/CRN/cpp/symmetry.cpp +45 -0
  85. synkit/CRN/cpp/write_manifest.cmake +28 -0
  86. synkit/CRN/kinds.py +137 -0
  87. synkit/CRN/lib/synkit_crn.dll +0 -0
  88. synkit/CRN/lib/synkit_crn.json +33 -0
  89. synkit/CRN/native.py +388 -0
  90. synkit/CRN/native_analysis.py +459 -0
  91. synkit/Chem/Cluster/__init__.py +0 -0
  92. synkit/Chem/Cluster/butina.py +140 -0
  93. synkit/Chem/Fingerprint/__init__.py +0 -0
  94. synkit/Chem/Fingerprint/fp_calculator.py +155 -0
  95. synkit/Chem/Fingerprint/smiles_featurizer.py +258 -0
  96. synkit/Chem/Fingerprint/transformation_fp.py +139 -0
  97. synkit/Chem/Mapper/README.rst +43 -0
  98. synkit/Chem/Mapper/__init__.py +255 -0
  99. synkit/Chem/Mapper/_compat.py +130 -0
  100. synkit/Chem/Mapper/adapters/__init__.py +1 -0
  101. synkit/Chem/Mapper/adapters/prediction.py +126 -0
  102. synkit/Chem/Mapper/adapters/template.py +412 -0
  103. synkit/Chem/Mapper/chem/__init__.py +52 -0
  104. synkit/Chem/Mapper/chem/aam.py +673 -0
  105. synkit/Chem/Mapper/chem/blind.py +160 -0
  106. synkit/Chem/Mapper/chem/its.py +309 -0
  107. synkit/Chem/Mapper/chem/smiles.py +564 -0
  108. synkit/Chem/Mapper/graph/__init__.py +66 -0
  109. synkit/Chem/Mapper/graph/automorphism.py +395 -0
  110. synkit/Chem/Mapper/graph/blockcut.py +98 -0
  111. synkit/Chem/Mapper/graph/labeled_graph.py +104 -0
  112. synkit/Chem/Mapper/graph/refine.py +176 -0
  113. synkit/Chem/Mapper/graph/synkit_adapter.py +110 -0
  114. synkit/Chem/Mapper/io/__init__.py +13 -0
  115. synkit/Chem/Mapper/io/idxmapstr.py +82 -0
  116. synkit/Chem/Mapper/mapper.py +685 -0
  117. synkit/Chem/Mapper/reaction_search.py +554 -0
  118. synkit/Chem/Mapper/reporting/__init__.py +1 -0
  119. synkit/Chem/Mapper/reporting/alternatives.py +451 -0
  120. synkit/Chem/Mapper/reporting/analysis.py +681 -0
  121. synkit/Chem/Mapper/reporting/native_analysis.py +485 -0
  122. synkit/Chem/Mapper/reporting/spectrum.py +642 -0
  123. synkit/Chem/Mapper/solvers/__init__.py +1 -0
  124. synkit/Chem/Mapper/solvers/exact/__init__.py +141 -0
  125. synkit/Chem/Mapper/solvers/exact/assignment/__init__.py +1 -0
  126. synkit/Chem/Mapper/solvers/exact/assignment/assignment_certificate.py +113 -0
  127. synkit/Chem/Mapper/solvers/exact/assignment/assignment_domains.py +162 -0
  128. synkit/Chem/Mapper/solvers/exact/assignment/assignment_verification.py +58 -0
  129. synkit/Chem/Mapper/solvers/exact/assignment/incremental_assignment.py +247 -0
  130. synkit/Chem/Mapper/solvers/exact/certificate.py +128 -0
  131. synkit/Chem/Mapper/solvers/exact/core.py +183 -0
  132. synkit/Chem/Mapper/solvers/exact/distance_search/__init__.py +1 -0
  133. synkit/Chem/Mapper/solvers/exact/distance_search/bounds.py +319 -0
  134. synkit/Chem/Mapper/solvers/exact/distance_search/exhaustive.py +179 -0
  135. synkit/Chem/Mapper/solvers/exact/distance_search/inputs.py +283 -0
  136. synkit/Chem/Mapper/solvers/exact/distance_search/records.py +242 -0
  137. synkit/Chem/Mapper/solvers/exact/distance_search/search.py +1025 -0
  138. synkit/Chem/Mapper/solvers/exact/distance_search/verify.py +378 -0
  139. synkit/Chem/Mapper/solvers/exact/edit_support.py +375 -0
  140. synkit/Chem/Mapper/solvers/exact/hybrid.py +224 -0
  141. synkit/Chem/Mapper/solvers/exact/hydrogen.py +264 -0
  142. synkit/Chem/Mapper/solvers/exact/kernel_solvers/__init__.py +1 -0
  143. synkit/Chem/Mapper/solvers/exact/kernel_solvers/branching.py +499 -0
  144. synkit/Chem/Mapper/solvers/exact/kernel_solvers/enumerate.py +1050 -0
  145. synkit/Chem/Mapper/solvers/exact/kernel_solvers/enumeration_result.py +30 -0
  146. synkit/Chem/Mapper/solvers/exact/kernel_solvers/kernel.py +256 -0
  147. synkit/Chem/Mapper/solvers/exact/kernel_solvers/milp.py +194 -0
  148. synkit/Chem/Mapper/solvers/exact/native/__init__.py +1 -0
  149. synkit/Chem/Mapper/solvers/exact/native/build.py +154 -0
  150. synkit/Chem/Mapper/solvers/exact/native/candidates.py +593 -0
  151. synkit/Chem/Mapper/solvers/exact/native/canonical.py +396 -0
  152. synkit/Chem/Mapper/solvers/exact/native/disk_frontier.py +415 -0
  153. synkit/Chem/Mapper/solvers/exact/native/frontier.py +390 -0
  154. synkit/Chem/Mapper/solvers/exact/native/hydrogen_quotient.py +213 -0
  155. synkit/Chem/Mapper/solvers/exact/native/its.py +528 -0
  156. synkit/Chem/Mapper/solvers/exact/native/native_distance.cpp +2803 -0
  157. synkit/Chem/Mapper/solvers/exact/native/orbit_aggregation.py +328 -0
  158. synkit/Chem/Mapper/solvers/exact/native/parallel.py +205 -0
  159. synkit/Chem/Mapper/solvers/exact/native/pmcd.py +203 -0
  160. synkit/Chem/Mapper/solvers/exact/native/runtime.py +40 -0
  161. synkit/Chem/Mapper/solvers/exact/native/search.py +294 -0
  162. synkit/Chem/Mapper/solvers/exact/native/separator.py +224 -0
  163. synkit/Chem/Mapper/solvers/exact/native_build.py +12 -0
  164. synkit/Chem/Mapper/solvers/exact/pabs/__init__.py +1 -0
  165. synkit/Chem/Mapper/solvers/exact/pabs/cost_lattice.py +43 -0
  166. synkit/Chem/Mapper/solvers/exact/pabs/factor_spectrum.py +110 -0
  167. synkit/Chem/Mapper/solvers/exact/pabs/multi_shell.py +368 -0
  168. synkit/Chem/Mapper/solvers/exact/pabs/propagation.py +679 -0
  169. synkit/Chem/Mapper/solvers/exact/pabs/propagation_bounds.py +436 -0
  170. synkit/Chem/Mapper/solvers/exact/pabs/propagation_limits.py +13 -0
  171. synkit/Chem/Mapper/solvers/exact/pabs/propagation_search.py +856 -0
  172. synkit/Chem/Mapper/solvers/exact/pabs/propagation_symmetry.py +66 -0
  173. synkit/Chem/Mapper/solvers/exact/pabs/residual_typed_bonds.py +136 -0
  174. synkit/Chem/Mapper/solvers/exact/pabs/reward_frontier.py +201 -0
  175. synkit/Chem/Mapper/solvers/exact/pabs/separator_bound.py +258 -0
  176. synkit/Chem/Mapper/solvers/exact/pabs/separator_spectrum.py +308 -0
  177. synkit/Chem/Mapper/solvers/exact/pabs/sparse_reward_bound.py +207 -0
  178. synkit/Chem/Mapper/solvers/exact/pabs/suffix_spectrum.py +299 -0
  179. synkit/Chem/Mapper/solvers/exact/search.py +55 -0
  180. synkit/Chem/Mapper/solvers/exact/seeds/__init__.py +1 -0
  181. synkit/Chem/Mapper/solvers/exact/seeds/seed.py +104 -0
  182. synkit/Chem/Mapper/solvers/exact/seeds/seed_fragments.py +148 -0
  183. synkit/Chem/Mapper/solvers/exact/seeds/seed_relaxation.py +181 -0
  184. synkit/Chem/Mapper/solvers/exact/symmetry.py +223 -0
  185. synkit/Chem/Mapper/solvers/native/__init__.py +4 -0
  186. synkit/Chem/Mapper/solvers/native/assignment.py +99 -0
  187. synkit/Chem/Mapper/solvers/native/astar.py +22 -0
  188. synkit/Chem/Mapper/solvers/native/build.py +385 -0
  189. synkit/Chem/Mapper/solvers/native/classification.py +641 -0
  190. synkit/Chem/Mapper/solvers/native/core.py +378 -0
  191. synkit/Chem/Mapper/solvers/native/cpp/CMakeLists.txt +120 -0
  192. synkit/Chem/Mapper/solvers/native/cpp/examples/map_reaction.cpp +29 -0
  193. synkit/Chem/Mapper/solvers/native/cpp/examples/slap_graph.cpp +63 -0
  194. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/assignment/assignment.h +18 -0
  195. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/astar/astar.h +18 -0
  196. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/astar/bound.h +33 -0
  197. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/core/pmcd_witness.h +16 -0
  198. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/core/runtime.h +130 -0
  199. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/hydrogen/hydrogen.h +73 -0
  200. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/mapper.h +175 -0
  201. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/mces/mces.h +9 -0
  202. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/pabs/seed.h +34 -0
  203. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/reaction/reaction.h +30 -0
  204. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/sepdp/sepdp.h +21 -0
  205. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/slap.h +72 -0
  206. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/solvers/solvers.h +16 -0
  207. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/symmetry/classification.h +140 -0
  208. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/symmetry/cpabs.h +33 -0
  209. synkit/Chem/Mapper/solvers/native/cpp/src/assignment/abb.cpp +302 -0
  210. synkit/Chem/Mapper/solvers/native/cpp/src/astar/CMakeLists.txt +12 -0
  211. synkit/Chem/Mapper/solvers/native/cpp/src/astar/README.md +47 -0
  212. synkit/Chem/Mapper/solvers/native/cpp/src/astar/astar.cpp +228 -0
  213. synkit/Chem/Mapper/solvers/native/cpp/src/astar/astar_graph.cpp +37 -0
  214. synkit/Chem/Mapper/solvers/native/cpp/src/astar/bound.cpp +212 -0
  215. synkit/Chem/Mapper/solvers/native/cpp/src/core/dispatch.cpp +272 -0
  216. synkit/Chem/Mapper/solvers/native/cpp/src/core/pmcd_witness.cpp +36 -0
  217. synkit/Chem/Mapper/solvers/native/cpp/src/hydrogen/hydrogen.cpp +380 -0
  218. synkit/Chem/Mapper/solvers/native/cpp/src/mces/README.md +57 -0
  219. synkit/Chem/Mapper/solvers/native/cpp/src/mces/mces.cpp +287 -0
  220. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/bridge.cpp +334 -0
  221. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/chemical_floor.inc +181 -0
  222. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/endpoint_symmetry.inc +104 -0
  223. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/exact_helpers.h +20 -0
  224. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_assignment_certificate.h +165 -0
  225. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_certificate.h +125 -0
  226. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_model.h +365 -0
  227. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_provider.inc +319 -0
  228. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_rounding.inc +170 -0
  229. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_test_hooks.h +342 -0
  230. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/objective_reduction.inc +137 -0
  231. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/overlap_dual.inc +351 -0
  232. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/profile_seed.inc +214 -0
  233. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/seed_heuristics.inc +640 -0
  234. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/sparse_embedding.cpp +430 -0
  235. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/sparse_root_lp.h +176 -0
  236. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/test_hooks.inc +262 -0
  237. synkit/Chem/Mapper/solvers/native/cpp/src/reaction/reaction.cpp +611 -0
  238. synkit/Chem/Mapper/solvers/native/cpp/src/sepdp/README.md +61 -0
  239. synkit/Chem/Mapper/solvers/native/cpp/src/sepdp/sepdp.cpp +253 -0
  240. synkit/Chem/Mapper/solvers/native/cpp/src/slap.cpp +810 -0
  241. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/formulation.h +138 -0
  242. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/maxsat.cpp +526 -0
  243. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/ortools.cpp +475 -0
  244. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/seed.h +80 -0
  245. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/weighted_cnf.h +256 -0
  246. synkit/Chem/Mapper/solvers/native/cpp/src/supporting/README.md +43 -0
  247. synkit/Chem/Mapper/solvers/native/cpp/src/supporting/dfs.cpp +123 -0
  248. synkit/Chem/Mapper/solvers/native/cpp/src/supporting/edit_support.cpp +224 -0
  249. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification.cpp +553 -0
  250. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification_pipeline.cpp +124 -0
  251. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification_stream.h +13 -0
  252. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/cpabs.cpp +455 -0
  253. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/edge_deck.cpp +743 -0
  254. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/COPYRIGHT +44 -0
  255. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/LICENSE-2.0.txt +202 -0
  256. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naugraph.c +732 -0
  257. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naurng.c +94 -0
  258. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naurng.h +49 -0
  259. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nausparse.c +1771 -0
  260. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nausparse.h +133 -0
  261. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nautil.c +750 -0
  262. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naututil.h +355 -0
  263. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nauty.c +1256 -0
  264. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nauty.h +1544 -0
  265. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/schreier.c +1131 -0
  266. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/schreier.h +70 -0
  267. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/sorttemplates.c +580 -0
  268. synkit/Chem/Mapper/solvers/native/hydrogen.py +711 -0
  269. synkit/Chem/Mapper/solvers/native/implicit.py +506 -0
  270. synkit/Chem/Mapper/solvers/native/implicit_certificate.py +187 -0
  271. synkit/Chem/Mapper/solvers/native/implicit_preparation.py +309 -0
  272. synkit/Chem/Mapper/solvers/native/lib/synkit_mapper.dll +0 -0
  273. synkit/Chem/Mapper/solvers/native/mces.py +16 -0
  274. synkit/Chem/Mapper/solvers/native/reaction.py +179 -0
  275. synkit/Chem/Mapper/solvers/native/reaction_build.py +277 -0
  276. synkit/Chem/Mapper/solvers/native/reaction_text.py +26 -0
  277. synkit/Chem/Mapper/solvers/native/runtime.py +242 -0
  278. synkit/Chem/Mapper/solvers/native/sepdp.py +47 -0
  279. synkit/Chem/Mapper/solvers/native/slap.py +266 -0
  280. synkit/Chem/Mapper/solvers/native/solvers.py +67 -0
  281. synkit/Chem/Mapper/solvers/native/stereo.py +86 -0
  282. synkit/Chem/Mapper/solvers/native/supporting.py +34 -0
  283. synkit/Chem/Mapper/solvers/native/symmetry.py +91 -0
  284. synkit/Chem/Mapper/solvers/slap/__init__.py +29 -0
  285. synkit/Chem/Mapper/solvers/slap/lap.py +174 -0
  286. synkit/Chem/Mapper/solvers/slap/sequential.py +696 -0
  287. synkit/Chem/Mapper/validation/__init__.py +1 -0
  288. synkit/Chem/Mapper/validation/aam_validator.py +442 -0
  289. synkit/Chem/Mapper/validation/annotations.py +274 -0
  290. synkit/Chem/Mapper/validation/bonds.py +124 -0
  291. synkit/Chem/Mapper/validation/cohorts.py +72 -0
  292. synkit/Chem/Mapper/validation/identifiability.py +150 -0
  293. synkit/Chem/Mapper/validation/numerical_scope.py +36 -0
  294. synkit/Chem/Mapper/validation/orbits.py +137 -0
  295. synkit/Chem/Molecule/__init__.py +0 -0
  296. synkit/Chem/Molecule/_chirality_loci.py +165 -0
  297. synkit/Chem/Molecule/_chirality_types.py +231 -0
  298. synkit/Chem/Molecule/_helical_loci.py +167 -0
  299. synkit/Chem/Molecule/_stereo_axis_evidence.py +202 -0
  300. synkit/Chem/Molecule/_stereo_element_detection.py +193 -0
  301. synkit/Chem/Molecule/_stereo_orientation_constraints.py +511 -0
  302. synkit/Chem/Molecule/_tetrahedral_carriers.py +63 -0
  303. synkit/Chem/Molecule/atom_features.py +379 -0
  304. synkit/Chem/Molecule/chirality.py +1041 -0
  305. synkit/Chem/Molecule/cip_assignment.py +569 -0
  306. synkit/Chem/Molecule/cip_ranking.py +843 -0
  307. synkit/Chem/Molecule/coordinate_stereo.py +503 -0
  308. synkit/Chem/Molecule/derived_stereo_naming.py +165 -0
  309. synkit/Chem/Molecule/descriptors.py +452 -0
  310. synkit/Chem/Molecule/formula.py +249 -0
  311. synkit/Chem/Molecule/global_stereo.py +175 -0
  312. synkit/Chem/Molecule/graph_annotator.py +300 -0
  313. synkit/Chem/Molecule/standardize.py +817 -0
  314. synkit/Chem/Molecule/stereo_evidence.py +179 -0
  315. synkit/Chem/Molecule/stereo_perception.py +1032 -0
  316. synkit/Chem/Molecule/valence.py +123 -0
  317. synkit/Chem/Reaction/Mapper/__init__.py +44 -0
  318. synkit/Chem/Reaction/__init__.py +20 -0
  319. synkit/Chem/Reaction/aam_validator.py +5 -0
  320. synkit/Chem/Reaction/balance_check.py +138 -0
  321. synkit/Chem/Reaction/canon_rsmi.py +249 -0
  322. synkit/Chem/Reaction/cleaning.py +58 -0
  323. synkit/Chem/Reaction/deionize.py +199 -0
  324. synkit/Chem/Reaction/explicit_h_audit.py +232 -0
  325. synkit/Chem/Reaction/fix_aam.py +64 -0
  326. synkit/Chem/Reaction/neutralize.py +207 -0
  327. synkit/Chem/Reaction/radical_wildcard.py +224 -0
  328. synkit/Chem/Reaction/standardize.py +203 -0
  329. synkit/Chem/Reaction/tautomerize.py +205 -0
  330. synkit/Chem/__init__.py +1 -0
  331. synkit/Chem/utils.py +315 -0
  332. synkit/Data/__init__.py +0 -0
  333. synkit/Data/aldol.json.gz +1 -0
  334. synkit/Data/gen_partial_aam.py +147 -0
  335. synkit/Data/paracetamol.json.gz +1 -0
  336. synkit/Graph/Canon/__init__.py +16 -0
  337. synkit/Graph/Canon/_native/__init__.py +13 -0
  338. synkit/Graph/Canon/_native/build.py +93 -0
  339. synkit/Graph/Canon/_native/lib/synkit_canon.dll +0 -0
  340. synkit/Graph/Canon/_native/prepare.py +49 -0
  341. synkit/Graph/Canon/_native/runtime.py +140 -0
  342. synkit/Graph/Canon/_native/search.py +137 -0
  343. synkit/Graph/Canon/canon_algs.py +228 -0
  344. synkit/Graph/Canon/canon_graph.py +531 -0
  345. synkit/Graph/Canon/cpp/CMakeLists.txt +42 -0
  346. synkit/Graph/Canon/cpp/README.md +123 -0
  347. synkit/Graph/Canon/cpp/examples/canonical_graph.cpp +16 -0
  348. synkit/Graph/Canon/cpp/include/synkit_canon/canon.h +85 -0
  349. synkit/Graph/Canon/cpp/src/canonical.cpp +391 -0
  350. synkit/Graph/Canon/cpp/src/symmetry.h +83 -0
  351. synkit/Graph/Canon/cpp/tests/symmetry.cpp +93 -0
  352. synkit/Graph/Canon/exact.py +1020 -0
  353. synkit/Graph/Canon/exact_refinement.py +368 -0
  354. synkit/Graph/Canon/nauty.py +143 -0
  355. synkit/Graph/Context/__init__.py +0 -0
  356. synkit/Graph/Context/hier_context.py +244 -0
  357. synkit/Graph/Context/radius_expand.py +252 -0
  358. synkit/Graph/FG/__init__.py +19 -0
  359. synkit/Graph/FG/api.py +39 -0
  360. synkit/Graph/FG/audit.py +155 -0
  361. synkit/Graph/FG/catalog.py +919 -0
  362. synkit/Graph/FG/detector.py +288 -0
  363. synkit/Graph/FG/model.py +97 -0
  364. synkit/Graph/FG/recognizers.py +274 -0
  365. synkit/Graph/FG/ring_system.py +154 -0
  366. synkit/Graph/Feature/Descriptors/topology.py +857 -0
  367. synkit/Graph/Feature/Fingerprint/__init__.py +0 -0
  368. synkit/Graph/Feature/Fingerprint/wl_rxn_fps.py +222 -0
  369. synkit/Graph/Feature/__init__.py +5 -0
  370. synkit/Graph/Feature/graph_descriptors.py +323 -0
  371. synkit/Graph/Feature/graph_fps.py +96 -0
  372. synkit/Graph/Feature/graph_signature.py +239 -0
  373. synkit/Graph/Feature/hash_fps.py +133 -0
  374. synkit/Graph/Feature/morgan_fps.py +88 -0
  375. synkit/Graph/Feature/path_fps.py +81 -0
  376. synkit/Graph/Feature/wl_hash.py +134 -0
  377. synkit/Graph/Fusion/__init__.py +85 -0
  378. synkit/Graph/Fusion/candidate.py +559 -0
  379. synkit/Graph/Fusion/constructor.py +877 -0
  380. synkit/Graph/Fusion/identity.py +184 -0
  381. synkit/Graph/Fusion/interface.py +700 -0
  382. synkit/Graph/Fusion/search.py +241 -0
  383. synkit/Graph/Hyrogen/__init__.py +6 -0
  384. synkit/Graph/Hyrogen/_misc.py +591 -0
  385. synkit/Graph/Hyrogen/hcomplete.py +995 -0
  386. synkit/Graph/Hyrogen/hcomplete_legacy.py +368 -0
  387. synkit/Graph/Hyrogen/hcompletion_algorithms.py +713 -0
  388. synkit/Graph/Hyrogen/hextend.py +570 -0
  389. synkit/Graph/Hyrogen/hextend_legacy.py +215 -0
  390. synkit/Graph/ITS/__init__.py +4 -0
  391. synkit/Graph/ITS/its_builder.py +120 -0
  392. synkit/Graph/ITS/its_construction.py +719 -0
  393. synkit/Graph/ITS/its_decompose.py +572 -0
  394. synkit/Graph/ITS/its_destruction.py +331 -0
  395. synkit/Graph/ITS/its_expand.py +1251 -0
  396. synkit/Graph/ITS/its_relabel.py +187 -0
  397. synkit/Graph/ITS/its_reverter.py +356 -0
  398. synkit/Graph/ITS/normalize_aam.py +145 -0
  399. synkit/Graph/ITS/partial_its.py +238 -0
  400. synkit/Graph/ITS/rc_extractor.py +656 -0
  401. synkit/Graph/ITS/stereo.py +74 -0
  402. synkit/Graph/MTG/__init__.py +107 -0
  403. synkit/Graph/MTG/gluing.py +451 -0
  404. synkit/Graph/MTG/history.py +928 -0
  405. synkit/Graph/MTG/inventory.py +118 -0
  406. synkit/Graph/MTG/local.py +447 -0
  407. synkit/Graph/MTG/mcs_matcher.py +246 -0
  408. synkit/Graph/MTG/mtg.py +611 -0
  409. synkit/Graph/MTG/mtg_explore.py +74 -0
  410. synkit/Graph/MTG/observation.py +209 -0
  411. synkit/Graph/MTG/process.py +577 -0
  412. synkit/Graph/MTG/queries.py +66 -0
  413. synkit/Graph/MTG/realization.py +95 -0
  414. synkit/Graph/MTG/series_parallel.py +107 -0
  415. synkit/Graph/MTG/utils.py +424 -0
  416. synkit/Graph/Matcher/__init__.py +10 -0
  417. synkit/Graph/Matcher/approx_mcs.py +1264 -0
  418. synkit/Graph/Matcher/auto_est.py +736 -0
  419. synkit/Graph/Matcher/automorphism.py +314 -0
  420. synkit/Graph/Matcher/batch_cluster.py +224 -0
  421. synkit/Graph/Matcher/dedup_matches.py +247 -0
  422. synkit/Graph/Matcher/graph_cluster.py +191 -0
  423. synkit/Graph/Matcher/graph_matcher.py +312 -0
  424. synkit/Graph/Matcher/graph_morphism.py +421 -0
  425. synkit/Graph/Matcher/mcs_matcher.py +804 -0
  426. synkit/Graph/Matcher/multi_turbo_iso.py +186 -0
  427. synkit/Graph/Matcher/orbit.py +284 -0
  428. synkit/Graph/Matcher/partial_matcher.py +694 -0
  429. synkit/Graph/Matcher/sing.py +544 -0
  430. synkit/Graph/Matcher/subgraph_matcher.py +812 -0
  431. synkit/Graph/Matcher/turbo_iso.py +272 -0
  432. synkit/Graph/Matcher/wl_sel.py +537 -0
  433. synkit/Graph/Mech/__init__.py +26 -0
  434. synkit/Graph/Mech/conversion.py +1466 -0
  435. synkit/Graph/Mech/conversion_debug.py +237 -0
  436. synkit/Graph/Mech/electron_accounting.py +200 -0
  437. synkit/Graph/Mech/lwg_editor.py +406 -0
  438. synkit/Graph/Mech/lwg_ops.py +313 -0
  439. synkit/Graph/Morphism/__init__.py +99 -0
  440. synkit/Graph/Morphism/constraints.py +460 -0
  441. synkit/Graph/Morphism/llg.py +999 -0
  442. synkit/Graph/Morphism/morphism.py +349 -0
  443. synkit/Graph/Morphism/stereo.py +258 -0
  444. synkit/Graph/Morphism/stereo_morphism.py +383 -0
  445. synkit/Graph/Morphism/stereo_morphism_helpers.py +957 -0
  446. synkit/Graph/Morphism/stereo_morphism_types.py +117 -0
  447. synkit/Graph/Stereo/__init__.py +376 -0
  448. synkit/Graph/Stereo/_descriptor_core.py +207 -0
  449. synkit/Graph/Stereo/_descriptor_serialization.py +138 -0
  450. synkit/Graph/Stereo/canonical.py +648 -0
  451. synkit/Graph/Stereo/changes.py +964 -0
  452. synkit/Graph/Stereo/composition.py +391 -0
  453. synkit/Graph/Stereo/configured.py +946 -0
  454. synkit/Graph/Stereo/couplings.py +245 -0
  455. synkit/Graph/Stereo/descriptors.py +1030 -0
  456. synkit/Graph/Stereo/enumeration.py +597 -0
  457. synkit/Graph/Stereo/extended_descriptors.py +406 -0
  458. synkit/Graph/Stereo/global_configured.py +152 -0
  459. synkit/Graph/Stereo/global_stereo.py +304 -0
  460. synkit/Graph/Stereo/identity.py +648 -0
  461. synkit/Graph/Stereo/interchange.py +496 -0
  462. synkit/Graph/Stereo/legacy.py +460 -0
  463. synkit/Graph/Stereo/matching.py +899 -0
  464. synkit/Graph/Stereo/native.py +154 -0
  465. synkit/Graph/Stereo/orbits.py +668 -0
  466. synkit/Graph/Stereo/outcomes.py +99 -0
  467. synkit/Graph/Stereo/pairwise.py +350 -0
  468. synkit/Graph/Stereo/rdkit_adapter.py +662 -0
  469. synkit/Graph/Stereo/rdkit_identity.py +118 -0
  470. synkit/Graph/Stereo/rdkit_resonance.py +140 -0
  471. synkit/Graph/Stereo/reaction_interchange.py +266 -0
  472. synkit/Graph/Stereo/semantics.py +296 -0
  473. synkit/Graph/Stereo/supports.py +257 -0
  474. synkit/Graph/Stereo/wire.py +339 -0
  475. synkit/Graph/Wildcard/__init__.py +0 -0
  476. synkit/Graph/Wildcard/fuse_graph.py +156 -0
  477. synkit/Graph/Wildcard/graph_wc.py +303 -0
  478. synkit/Graph/Wildcard/its_merge.py +857 -0
  479. synkit/Graph/Wildcard/radwc.py +114 -0
  480. synkit/Graph/Wildcard/wc_matcher.py +576 -0
  481. synkit/Graph/Wildcard/wildcard.py +225 -0
  482. synkit/Graph/__init__.py +17 -0
  483. synkit/Graph/canon_graph.py +14 -0
  484. synkit/Graph/syn_graph.py +199 -0
  485. synkit/Graph/utils.py +324 -0
  486. synkit/IO/__init__.py +4 -0
  487. synkit/IO/chem_converter.py +1059 -0
  488. synkit/IO/combinatorial/__init__.py +8 -0
  489. synkit/IO/combinatorial/gml_to_graph.py +223 -0
  490. synkit/IO/combinatorial/graph_to_gml.py +280 -0
  491. synkit/IO/combinatorial/graph_to_smarts.py +186 -0
  492. synkit/IO/combinatorial/smarts_expander.py +147 -0
  493. synkit/IO/combinatorial/smarts_generalizer.py +133 -0
  494. synkit/IO/combinatorial/smarts_to_graph.py +179 -0
  495. synkit/IO/conversion.py +42 -0
  496. synkit/IO/data_io.py +269 -0
  497. synkit/IO/data_process.py +143 -0
  498. synkit/IO/debug.py +73 -0
  499. synkit/IO/gml_to_nx.py +150 -0
  500. synkit/IO/graph_to_mol.py +199 -0
  501. synkit/IO/mol_to_graph.py +1105 -0
  502. synkit/IO/mol_to_graph_chemistry.py +545 -0
  503. synkit/IO/nx_to_gml.py +209 -0
  504. synkit/IO/smiles_to_id.py +123 -0
  505. synkit/Mechanism/__init__.py +151 -0
  506. synkit/Mechanism/adapters.py +136 -0
  507. synkit/Mechanism/audit.py +323 -0
  508. synkit/Mechanism/benchmark.py +638 -0
  509. synkit/Mechanism/compatibility.py +13 -0
  510. synkit/Mechanism/drawing.py +85 -0
  511. synkit/Mechanism/electron_models.py +725 -0
  512. synkit/Mechanism/equivalence.py +521 -0
  513. synkit/Mechanism/evidence.py +262 -0
  514. synkit/Mechanism/interchange.py +141 -0
  515. synkit/Mechanism/model.py +918 -0
  516. synkit/Mechanism/neighbor_stereo.py +312 -0
  517. synkit/Mechanism/radical_data.py +740 -0
  518. synkit/Mechanism/replay.py +986 -0
  519. synkit/Mechanism/schema.py +264 -0
  520. synkit/Mechanism/stereo_state.py +416 -0
  521. synkit/Mechanism/symbols.py +91 -0
  522. synkit/Rule/Apply/__init__.py +35 -0
  523. synkit/Rule/Apply/conditions.py +45 -0
  524. synkit/Rule/Apply/dpo.py +998 -0
  525. synkit/Rule/Apply/rule_matcher.py +218 -0
  526. synkit/Rule/Apply/validation.py +354 -0
  527. synkit/Rule/Compose/__init__.py +106 -0
  528. synkit/Rule/Compose/_identity.py +43 -0
  529. synkit/Rule/Compose/composition.py +976 -0
  530. synkit/Rule/Compose/laws.py +439 -0
  531. synkit/Rule/Compose/search.py +771 -0
  532. synkit/Rule/Compose/synrule.py +170 -0
  533. synkit/Rule/Modify/__init__.py +0 -0
  534. synkit/Rule/Modify/implict_rule.py +56 -0
  535. synkit/Rule/Modify/longest_path.py +92 -0
  536. synkit/Rule/Modify/molecule_rule.py +115 -0
  537. synkit/Rule/Modify/prune_templates.py +78 -0
  538. synkit/Rule/Modify/rule_utils.py +194 -0
  539. synkit/Rule/Modify/strip_rule.py +97 -0
  540. synkit/Rule/__init__.py +28 -0
  541. synkit/Rule/generic_stereo.py +884 -0
  542. synkit/Rule/stereo_identity.py +271 -0
  543. synkit/Rule/syn_rule.py +1090 -0
  544. synkit/Synthesis/MSR/__init__.py +0 -0
  545. synkit/Synthesis/MSR/path_finder.py +239 -0
  546. synkit/Synthesis/Metrics/__init__.py +0 -0
  547. synkit/Synthesis/Metrics/_base.py +52 -0
  548. synkit/Synthesis/Metrics/_plot.py +129 -0
  549. synkit/Synthesis/Metrics/_ranking.py +179 -0
  550. synkit/Synthesis/RBL/__init__.py +80 -0
  551. synkit/Synthesis/RBL/engine.py +1249 -0
  552. synkit/Synthesis/RBL/matching.py +652 -0
  553. synkit/Synthesis/RBL/overlap.py +336 -0
  554. synkit/Synthesis/RBL/pipeline.py +376 -0
  555. synkit/Synthesis/RBL/policy.py +139 -0
  556. synkit/Synthesis/RBL/proof.py +370 -0
  557. synkit/Synthesis/RBL/reaction.py +506 -0
  558. synkit/Synthesis/RBL/state.py +169 -0
  559. synkit/Synthesis/RBL/validation.py +1060 -0
  560. synkit/Synthesis/Reactor/__init__.py +60 -0
  561. synkit/Synthesis/Reactor/core/__init__.py +1 -0
  562. synkit/Synthesis/Reactor/core/engine.py +967 -0
  563. synkit/Synthesis/Reactor/core/product.py +621 -0
  564. synkit/Synthesis/Reactor/core/rewrite.py +561 -0
  565. synkit/Synthesis/Reactor/core/strategy.py +44 -0
  566. synkit/Synthesis/Reactor/matching/__init__.py +1 -0
  567. synkit/Synthesis/Reactor/matching/mixin.py +920 -0
  568. synkit/Synthesis/Reactor/matching/policy.py +345 -0
  569. synkit/Synthesis/Reactor/matching/symmetry.py +309 -0
  570. synkit/Synthesis/Reactor/output/__init__.py +1 -0
  571. synkit/Synthesis/Reactor/output/deduplication.py +703 -0
  572. synkit/Synthesis/Reactor/output/policy.py +16 -0
  573. synkit/Synthesis/Reactor/output/serialization.py +485 -0
  574. synkit/Synthesis/Reactor/output/structural.py +893 -0
  575. synkit/Synthesis/Reactor/stereo/__init__.py +1 -0
  576. synkit/Synthesis/Reactor/stereo/assignment.py +35 -0
  577. synkit/Synthesis/Reactor/stereo/mixin.py +780 -0
  578. synkit/Synthesis/Reactor/variants/__init__.py +1 -0
  579. synkit/Synthesis/Reactor/variants/imbalanced.py +180 -0
  580. synkit/Synthesis/Reactor/variants/partial.py +84 -0
  581. synkit/Synthesis/Reactor/workflow/__init__.py +1 -0
  582. synkit/Synthesis/Reactor/workflow/batch.py +550 -0
  583. synkit/Synthesis/Reactor/workflow/benchmark.py +143 -0
  584. synkit/Synthesis/Reactor/workflow/postprocess.py +267 -0
  585. synkit/Synthesis/Reactor/workflow/rule_filter.py +210 -0
  586. synkit/Synthesis/__init__.py +0 -0
  587. synkit/Synthesis/reactor_utils.py +316 -0
  588. synkit/Utils/__init__.py +0 -0
  589. synkit/Utils/utils.py +172 -0
  590. synkit/Vis/__init__.py +91 -0
  591. synkit/Vis/crn/__init__.py +40 -0
  592. synkit/Vis/epd/__init__.py +20 -0
  593. synkit/Vis/epd/arrows.py +425 -0
  594. synkit/Vis/epd/chem.py +197 -0
  595. synkit/Vis/epd/constants.py +83 -0
  596. synkit/Vis/epd/layout.py +283 -0
  597. synkit/Vis/epd/mapping.py +51 -0
  598. synkit/Vis/epd/models.py +136 -0
  599. synkit/Vis/epd/render.py +543 -0
  600. synkit/Vis/epd/utils.py +108 -0
  601. synkit/Vis/epd/visualizer.py +811 -0
  602. synkit/Vis/graph_visualizer.py +375 -0
  603. synkit/Vis/its/__init__.py +19 -0
  604. synkit/Vis/its/drawer.py +615 -0
  605. synkit/Vis/its_drawer.py +35 -0
  606. synkit/Vis/molecule/__init__.py +31 -0
  607. synkit/Vis/molecule/drawer.py +563 -0
  608. synkit/Vis/molecule/reaction.py +285 -0
  609. synkit/Vis/molecule_drawer.py +33 -0
  610. synkit/Vis/mtg/__init__.py +17 -0
  611. synkit/Vis/mtg/drawer.py +769 -0
  612. synkit/Vis/mtg_drawer.py +34 -0
  613. synkit/Vis/pdf_writer.py +146 -0
  614. synkit/Vis/reaction/__init__.py +19 -0
  615. synkit/Vis/reaction/rule.py +141 -0
  616. synkit/Vis/reaction/rxn.py +532 -0
  617. synkit/Vis/reaction_drawer.py +41 -0
  618. synkit/Vis/space/__init__.py +17 -0
  619. synkit/Vis/space/chemical.py +80 -0
  620. synkit/Vis/space/embedding.py +87 -0
  621. synkit/Vis/vis_synedu/Vis/__init__.py +7 -0
  622. synkit/Vis/vis_synedu/Vis/dpo.py +862 -0
  623. synkit/Vis/vis_synedu/rxn_vis.py +377 -0
  624. synkit/Vis/vis_synedu/vis.py +501 -0
  625. synkit/Vis/visual_drawer.py +215 -0
  626. synkit/Vis/visual_model.py +520 -0
  627. synkit/__init__.py +3 -0
  628. synkit/_native.py +91 -0
  629. synkit/examples.py +50 -0
  630. synkit/version.py +23 -0
  631. synkit-1.6.5.dist-info/METADATA +156 -0
  632. synkit-1.6.5.dist-info/RECORD +636 -0
  633. synkit-1.6.5.dist-info/WHEEL +4 -0
  634. synkit-1.6.5.dist-info/licenses/LICENSE +21 -0
  635. synkit-1.6.5.dist-info/licenses/synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/COPYRIGHT +44 -0
  636. synkit-1.6.5.dist-info/licenses/synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/LICENSE-2.0.txt +202 -0
@@ -0,0 +1,181 @@
1
+ // Private to bridge.cpp; exact algebraic lower bound.
2
+ // Integer normalized objective variables obey 2*e_i+h_i+sum_j b_ij=c_type.
3
+ // Conserved total h then makes total CD even. CD2 is impossible: a single
4
+ // bond edit has odd endpoint degree, while two bond units cannot have zero
5
+ // signed degree everywhere. Pure unary changes cost at least3. Therefore a
6
+ // nonzero distance is >=4 (raw doubled cost>=8). Guards are checked exactly;
7
+ // component/WL disagreement is only a negative isomorphism certificate.
8
+ int chemical_positive_floor(const Problem &p, const Perm &tr, const Perm &tp,
9
+ int64_t known_lower, Budget &budget,
10
+ int *reason = nullptr) {
11
+ const int n = p.n;
12
+ if (reason)
13
+ *reason = 0;
14
+ if (n < 3 || n > 256 || budget.remaining() < 0.05)
15
+ return 0;
16
+ const auto started = Clock::now();
17
+ const double allowance = std::min(0.005, budget.remaining() * 0.01);
18
+ auto expired = [&]() {
19
+ budget.check();
20
+ return elapsed(started) >= allowance;
21
+ };
22
+ std::map<int, int> counts, other_counts, positions;
23
+ for (int i = 0; i < n; ++i) {
24
+ ++counts[tr[i]];
25
+ ++other_counts[tp[i]];
26
+ positions[tp[i]] = i;
27
+ }
28
+ if (counts != other_counts)
29
+ return 0;
30
+ Perm dr(n, 0), dp(n, 0);
31
+ std::vector<Perm> ar(n), ap(n);
32
+ for (int i = 0; i < n; ++i) {
33
+ if (expired())
34
+ return 0;
35
+ if (p.a2[i * n + i] || p.b2[i * n + i])
36
+ return 0;
37
+ for (int j = 0; j < n; ++j) {
38
+ const int64_t a = p.a2[i * n + j], b = p.b2[i * n + j];
39
+ if (a < 0 || b < 0 || a % 2 || b % 2 || a != p.a2[j * n + i] ||
40
+ b != p.b2[j * n + i] || a > 1024 || b > 1024)
41
+ return 0;
42
+ dr[i] += a / 2;
43
+ dp[i] += b / 2;
44
+ if (a)
45
+ ar[i].push_back(j);
46
+ if (b)
47
+ ap[i].push_back(j);
48
+ }
49
+ }
50
+ int er = -1, hr = -1, ep = -1, hp = -1;
51
+ for (int orientation = 0; orientation < 2 && er < 0; ++orientation) {
52
+ const int e = n - 2 + orientation, h = n - 1 - orientation;
53
+ if (counts[tr[e]] != 1 || counts[tr[h]] != 1)
54
+ continue;
55
+ const int pe = positions[tr[e]], ph = positions[tr[h]];
56
+ if (p.a2[e * n + h] || p.b2[pe * n + ph] || dr[h] != dp[ph])
57
+ continue;
58
+ std::map<int, int64_t> constants;
59
+ bool valid = true;
60
+ for (int side = 0; side < 2 && valid; ++side) {
61
+ const auto &types = side ? tp : tr;
62
+ const auto &degree = side ? dp : dr;
63
+ const auto *matrix = side ? p.b2 : p.a2;
64
+ const int electron = side ? pe : e, hydrogen = side ? ph : h;
65
+ for (int i = 0; i < n; ++i)
66
+ if (i != electron && i != hydrogen) {
67
+ const int64_t value = degree[i] + matrix[i * n + electron] / 2;
68
+ auto entry = constants.emplace(types[i], value);
69
+ if (entry.first->second != value) {
70
+ valid = false;
71
+ break;
72
+ }
73
+ }
74
+ }
75
+ if (valid) {
76
+ er = e;
77
+ hr = h;
78
+ ep = pe;
79
+ hp = ph;
80
+ }
81
+ }
82
+ if (er < 0 || expired())
83
+ return 0;
84
+ if (known_lower > 0) {
85
+ if (reason)
86
+ *reason = 1;
87
+ return 8;
88
+ }
89
+ auto components = [&](const Perm &types, const std::vector<Perm> &adj,
90
+ const int64_t *matrix, int e, int h) {
91
+ std::vector<std::vector<int64_t>> signatures;
92
+ Perm seen(n, 0);
93
+ seen[e] = seen[h] = 1;
94
+ for (int root = 0; root < n; ++root)
95
+ if (!seen[root]) {
96
+ std::vector<std::vector<int64_t>> vertices;
97
+ Perm pending{root};
98
+ seen[root] = 1;
99
+ while (!pending.empty()) {
100
+ int i = pending.back();
101
+ pending.pop_back();
102
+ int degree = 0, weight = 0;
103
+ for (int j : adj[i])
104
+ if (j != e && j != h) {
105
+ ++degree;
106
+ weight += matrix[i * n + j];
107
+ if (!seen[j]) {
108
+ seen[j] = 1;
109
+ pending.push_back(j);
110
+ }
111
+ }
112
+ vertices.push_back(
113
+ {types[i], matrix[i * n + e], matrix[i * n + h], degree, weight});
114
+ }
115
+ std::sort(vertices.begin(), vertices.end());
116
+ std::vector<int64_t> key{static_cast<int64_t>(vertices.size())};
117
+ for (const auto &vertex : vertices)
118
+ key.insert(key.end(), vertex.begin(), vertex.end());
119
+ signatures.push_back(std::move(key));
120
+ }
121
+ std::sort(signatures.begin(), signatures.end());
122
+ return signatures;
123
+ };
124
+ auto left = components(tr, ar, p.a2, er, hr),
125
+ right = components(tp, ap, p.b2, ep, hp);
126
+ if (expired())
127
+ return 0;
128
+ if (left != right) {
129
+ if (reason)
130
+ *reason = 2;
131
+ return 8;
132
+ }
133
+ Perm cr = tr, cp = tp;
134
+ std::set<int> previous(tr.begin(), tr.end());
135
+ size_t previous_count = previous.size();
136
+ for (int round = 0; round < 6; ++round) {
137
+ std::map<std::vector<int64_t>, int> intern;
138
+ auto refine = [&](const Perm &colors, const std::vector<Perm> &adj,
139
+ const int64_t *matrix, Perm &next) {
140
+ next.resize(n);
141
+ for (int i = 0; i < n; ++i) {
142
+ if (expired())
143
+ return false;
144
+ std::vector<std::pair<int, int64_t>> neighbors;
145
+ for (int j : adj[i])
146
+ neighbors.emplace_back(colors[j], matrix[i * n + j]);
147
+ std::sort(neighbors.begin(), neighbors.end());
148
+ std::vector<int64_t> key{colors[i],
149
+ static_cast<int64_t>(neighbors.size())};
150
+ for (auto edge : neighbors) {
151
+ key.push_back(edge.first);
152
+ key.push_back(edge.second);
153
+ }
154
+ next[i] = intern.emplace(std::move(key), intern.size()).first->second;
155
+ }
156
+ return true;
157
+ };
158
+ Perm nr, np;
159
+ if (!refine(cr, ar, p.a2, nr) || !refine(cp, ap, p.b2, np))
160
+ return 0;
161
+ Perm balance(intern.size(), 0);
162
+ for (int color : nr)
163
+ ++balance[color];
164
+ for (int color : np)
165
+ --balance[color];
166
+ if (std::any_of(balance.begin(), balance.end(),
167
+ [](int value) { return value != 0; })) {
168
+ if (expired())
169
+ return 0;
170
+ if (reason)
171
+ *reason = 3;
172
+ return 8;
173
+ }
174
+ if (intern.size() == previous_count)
175
+ break;
176
+ previous_count = intern.size();
177
+ cr = std::move(nr);
178
+ cp = std::move(np);
179
+ }
180
+ return 0;
181
+ }
@@ -0,0 +1,104 @@
1
+ // Private to bridge.cpp; verified endpoint automorphism subgroups.
2
+ std::vector<int> twin_generators(const Problem &p, bool product) {
3
+ const int n = p.n;
4
+ const auto *matrix = product ? p.b2 : p.a2;
5
+ const auto *types = product ? p.types_p : p.types_r;
6
+ const auto *nodes = product ? p.node_colors_p : p.node_colors_r;
7
+ const auto *edges = product ? p.edge_colors_p : p.edge_colors_r;
8
+ std::vector<int> generators;
9
+ for (int i = 0; i < n; ++i)
10
+ for (int k = i + 1; k < n; ++k) {
11
+ if (types[i] != types[k] || (nodes && nodes[i] != nodes[k]) ||
12
+ (edges && edges[i * n + i] != edges[k * n + k]))
13
+ continue;
14
+ bool equal = true;
15
+ for (int j = 0; j < n; ++j)
16
+ if (j != i && j != k &&
17
+ (matrix[i * n + j] != matrix[k * n + j] ||
18
+ (edges && edges[i * n + j] != edges[k * n + j]))) {
19
+ equal = false;
20
+ break;
21
+ }
22
+ if (!equal)
23
+ continue;
24
+ for (int j = 0; j < n; ++j)
25
+ generators.push_back(j == i ? k : j == k ? i : j);
26
+ break;
27
+ }
28
+ return generators;
29
+ }
30
+
31
+ // Individualization/refinement only discovers candidate symmetries. Every
32
+ // retained permutation is verified against all typed, attributed, weighted
33
+ // endpoint edges by NativeCanon::accept. A discovery cutoff retains a subgroup
34
+ // and can only weaken pruning; it cannot remove a feasible mapping class.
35
+ std::vector<int> endpoint_generators(const Problem &p, bool product,
36
+ Budget &budget) {
37
+ const int n = p.n;
38
+ auto result = twin_generators(p, product);
39
+ const auto *weights = product ? p.b2 : p.a2;
40
+ const auto *types = product ? p.types_p : p.types_r;
41
+ const auto *nodes = product ? p.node_colors_p : p.node_colors_r;
42
+ const auto *edges = product ? p.edge_colors_p : p.edge_colors_r;
43
+ std::map<std::pair<int32_t, int32_t>, int> node_ids;
44
+ std::map<std::pair<int64_t, int32_t>, int> edge_ids;
45
+ Perm colors(n), palette(n * n, 0), parent(n);
46
+ std::iota(parent.begin(), parent.end(), 0);
47
+ auto find = [&](int x) {
48
+ while (parent[x] != x) {
49
+ parent[x] = parent[parent[x]];
50
+ x = parent[x];
51
+ }
52
+ return x;
53
+ };
54
+ for (int i = 0; i < n; ++i) {
55
+ colors[i] = node_ids
56
+ .emplace(std::make_pair(types[i], nodes ? nodes[i] : 0),
57
+ node_ids.size())
58
+ .first->second;
59
+ for (int j = 0; j < n; ++j) {
60
+ const int64_t weight = weights[i * n + j];
61
+ const int32_t edge = edges ? edges[i * n + j] : 0;
62
+ if (weight || edge)
63
+ palette[i * n + j] =
64
+ edge_ids.emplace(std::make_pair(weight, edge), edge_ids.size() + 1)
65
+ .first->second;
66
+ }
67
+ }
68
+ const double seconds = std::min(0.05, budget.remaining() * 0.02);
69
+ NativeCanon canon(n, colors.data(), palette.data(), seconds, 10000);
70
+ for (size_t offset = 0; offset < result.size(); offset += n) {
71
+ Perm generator(result.begin() + offset, result.begin() + offset + n);
72
+ canon.accept(generator);
73
+ // The existing exact transpositions connect freely interchangeable twins,
74
+ // including adjacent true twins. They may be individualized together.
75
+ for (int i = 0; i < n; ++i)
76
+ if (generator[i] != i) {
77
+ const int x = find(i), y = find(generator[i]);
78
+ parent[y] = x;
79
+ }
80
+ }
81
+ for (int i = 0; i < n; ++i)
82
+ canon.twin_class[i] = find(i);
83
+ const size_t initial = canon.generators.size();
84
+ std::map<int, Perm> buckets;
85
+ for (int i = 0; i < n; ++i)
86
+ buckets[colors[i]].push_back(i);
87
+ NativeCanon::Partition partition;
88
+ for (auto &entry : buckets)
89
+ partition.push_back(std::move(entry.second));
90
+ partition = canon.refine(std::move(partition));
91
+ bool twins_only = true;
92
+ for (const auto &cell : partition)
93
+ for (int x : cell)
94
+ if (canon.twin_class[x] != canon.twin_class[cell.front()])
95
+ twins_only = false;
96
+ if (!twins_only && seconds > 0)
97
+ canon.visit(std::move(partition), true);
98
+ const size_t stop = std::min(canon.generators.size(), initial + 32);
99
+ for (size_t k = initial; k < stop; ++k)
100
+ result.insert(result.end(), canon.generators[k].begin(),
101
+ canon.generators[k].end());
102
+ budget.check();
103
+ return result;
104
+ }
@@ -0,0 +1,20 @@
1
+ #pragma once
2
+ #include <cstdint>
3
+
4
+ namespace synkit_mapper::pabs {
5
+ // Exhaustively compare small weighted deletion decks. A timeout preserves only
6
+ // levels already excluded; hashes are filters, exact canonical forms decide.
7
+ int edge_deck(int n, const int64_t *a, const int64_t *b, const int32_t *types_r,
8
+ const int32_t *types_p, int units, double seconds,
9
+ int64_t node_limit, int64_t upper2, int32_t *mapping,
10
+ int64_t *lower2, int64_t *witness2, int64_t *statistics);
11
+ int edge_deck_sizes(int n, const int64_t *a, const int64_t *b,
12
+ const int32_t *types_r, const int32_t *types_p, int units,
13
+ int64_t *sizes);
14
+ // Proposal only. Failure or truncation never supplies an optimality bound.
15
+ int sparse_embedding_seed(int n, const int64_t *a, const int64_t *b,
16
+ const int32_t *types_r, const int32_t *types_p,
17
+ int64_t target2, double seconds, int64_t node_limit,
18
+ int32_t *mapping, int64_t *cost2,
19
+ int64_t *statistics);
20
+ } // namespace synkit_mapper::pabs
@@ -0,0 +1,165 @@
1
+ #pragma once
2
+ // A call-local, exact assignment relaxation of the checked original LP dual.
3
+ // No primal anchors, guessed domains or previous solves enter this certificate.
4
+ #include "lp_certificate.h"
5
+ namespace synkit_mapper {
6
+ namespace sparse_root_lp {
7
+ struct AssignmentCertificate {
8
+ bool ready = false;
9
+ int n = 0, m = 0;
10
+ int64_t root_bound2 = 0;
11
+ #ifdef SYNKIT_MAPPER_TEST_HOOKS
12
+ int64_t calls = 0, prunes = 0;
13
+ #endif // SYNKIT_MAPPER_TEST_HOOKS
14
+ #if defined(__SIZEOF_INT128__)
15
+ Wide base = 0, quantum = 1;
16
+ int64_t gcd = 0, mass = 0;
17
+ std::vector<int> rows, columns, row_position, column_position;
18
+ std::vector<int> penalties;
19
+
20
+ int64_t round_bound(Wide numerator) const {
21
+ Wide value = numerator >= 0
22
+ ? (numerator + certificate_scale - 1) / certificate_scale
23
+ : numerator / certificate_scale;
24
+ if (gcd) {
25
+ const Wide step = 2 * Wide(gcd);
26
+ Wide correction = (Wide(mass) - value) % step;
27
+ if (correction < 0)
28
+ correction += step;
29
+ value += correction;
30
+ }
31
+ // The complete typed space has a mapping of cost at most mass. Clipping
32
+ // only weakens an optional bound and keeps the legacy callback arithmetic
33
+ // within the production graph mass guard.
34
+ return int64_t(std::max(Wide(0), std::min(Wide(mass), value)));
35
+ }
36
+
37
+ template <class Check>
38
+ static AssignmentCertificate
39
+ build(const PreparedModel &model, const IntegerCertificate &certificate,
40
+ const std::vector<Wide> &reduced, Check check) {
41
+ AssignmentCertificate result;
42
+ result.n = model.n;
43
+ result.m = int(model.variable_rows.size());
44
+ result.mass = model.mass;
45
+ result.gcd = model.gcd;
46
+ if (!result.m || result.n > 256 || result.m != int(model.columns.size()) ||
47
+ reduced.size() != size_t(model.assignment_variables))
48
+ return result;
49
+ check();
50
+ const int n = result.n, m = result.m;
51
+ result.rows = model.variable_rows;
52
+ result.columns = model.columns;
53
+ result.row_position.assign(n, -1);
54
+ result.column_position.assign(n, -1);
55
+ for (int i = 0; i < m; ++i) {
56
+ result.row_position[result.rows[i]] = i;
57
+ result.column_position[result.columns[i]] = i;
58
+ }
59
+ result.base = certificate.numerator;
60
+ for (Wide value : reduced)
61
+ result.base -= std::min(Wide(0), value);
62
+ std::vector<Wide> shifts(m);
63
+ Wide largest = 0;
64
+ for (int i = 0; i < m; ++i) {
65
+ check();
66
+ int row = result.rows[i];
67
+ const auto &domain = model.domains[row];
68
+ if (domain.empty())
69
+ return AssignmentCertificate{};
70
+ Wide minimum = reduced[model.assignment[row * n + domain[0]]];
71
+ for (int image : domain)
72
+ minimum = std::min(minimum, reduced[model.assignment[row * n + image]]);
73
+ shifts[i] = minimum;
74
+ result.base += minimum;
75
+ for (int image : domain)
76
+ largest = std::max(largest, reduced[model.assignment[row * n + image]] -
77
+ minimum);
78
+ }
79
+ const int safe_entry = INF / (8 * m) - 1;
80
+ if (safe_entry < 1)
81
+ return AssignmentCertificate{};
82
+ result.quantum = std::max(Wide(1), (largest + safe_entry - 1) / safe_entry);
83
+ std::vector<int> cost(m * m, INF);
84
+ for (int i = 0; i < m; ++i) {
85
+ check();
86
+ int row = result.rows[i];
87
+ for (int image : model.domains[row]) {
88
+ int col = result.column_position[image];
89
+ if (col < 0)
90
+ return AssignmentCertificate{};
91
+ Wide value = (reduced[model.assignment[row * n + image]] - shifts[i]) /
92
+ result.quantum;
93
+ if (value < 0 || value > safe_entry)
94
+ return AssignmentCertificate{};
95
+ cost[i * m + col] = int(value);
96
+ }
97
+ }
98
+ check();
99
+ Perm match, u, v;
100
+ int optimum = Solver::assignment(cost, m, match, u, v);
101
+ check();
102
+ if (optimum >= INF / 2 || int(match.size()) != m ||
103
+ int(u.size()) != m + 1 || int(v.size()) != m + 1)
104
+ return AssignmentCertificate{};
105
+ int64_t dual = 0, primal = 0;
106
+ std::vector<char> used(m, false);
107
+ result.penalties.assign(m * m, INF);
108
+ for (int i = 0; i < m; ++i) {
109
+ check();
110
+ int image = match[i];
111
+ if (image < 0 || image >= m || used[image]++ ||
112
+ cost[i * m + image] >= INF / 2)
113
+ return AssignmentCertificate{};
114
+ primal += cost[i * m + image];
115
+ dual += int64_t(u[i + 1]) + v[i + 1];
116
+ for (int j = 0; j < m; ++j)
117
+ if (cost[i * m + j] < INF / 2) {
118
+ int64_t value = int64_t(cost[i * m + j]) - u[i + 1] - v[j + 1];
119
+ if (value < 0 || value >= INF)
120
+ return AssignmentCertificate{};
121
+ result.penalties[i * m + j] = int(value);
122
+ }
123
+ }
124
+ if (primal != optimum || dual != optimum)
125
+ return AssignmentCertificate{};
126
+ result.base += result.quantum * optimum;
127
+ result.root_bound2 = result.round_bound(result.base);
128
+ check();
129
+ result.ready = true;
130
+ return result;
131
+ }
132
+
133
+ int64_t bound(const int *mapping, const int *used) const {
134
+ if (!ready)
135
+ return 0;
136
+ Wide extra = 0;
137
+ for (int i = 0; i < m; ++i) {
138
+ int image = mapping[rows[i]];
139
+ if (image >= 0) {
140
+ if (image >= n || column_position[image] < 0)
141
+ return mass;
142
+ int penalty = penalties[i * m + column_position[image]];
143
+ if (penalty >= INF / 2)
144
+ return mass;
145
+ extra += penalty;
146
+ } else if (m <= 64) {
147
+ // Dropping nonnegative future-row minima for larger problems gives
148
+ // a weaker valid certificate with O(m) prefix evaluation.
149
+ int least = INF;
150
+ for (int j = 0; j < m; ++j)
151
+ if (!used[columns[j]])
152
+ least = std::min(least, penalties[i * m + j]);
153
+ if (least >= INF / 2)
154
+ return mass;
155
+ extra += least;
156
+ }
157
+ }
158
+ return round_bound(base + quantum * extra);
159
+ }
160
+ #else
161
+ int64_t bound(const int *, const int *) const { return 0; }
162
+ #endif
163
+ };
164
+ } // namespace sparse_root_lp
165
+ } // namespace synkit_mapper
@@ -0,0 +1,125 @@
1
+ #pragma once
2
+
3
+ // Mathematical authority for the optional LP bound. No numerical solver or
4
+ // solver status is trusted: any sign-valid integer multiplier vector gives a
5
+ // box-Lagrangian lower bound on the original exact integer formulation.
6
+ #include "lp_model.h"
7
+ #include <cmath>
8
+ #include <limits>
9
+ #include <stdexcept>
10
+ #include <string>
11
+
12
+ namespace synkit_mapper {
13
+ namespace sparse_root_lp {
14
+ constexpr int64_t certificate_scale = 1000000;
15
+
16
+ #if defined(__SIZEOF_INT128__)
17
+ __extension__ typedef __int128 Wide;
18
+ struct IntegerCertificate {
19
+ Wide numerator = 0;
20
+ int64_t bound2 = 0;
21
+ std::vector<int64_t> dual;
22
+ };
23
+
24
+ inline std::string decimal(Wide value) {
25
+ if (!value)
26
+ return "0";
27
+ const bool negative = value < 0;
28
+ if (negative)
29
+ value = -value;
30
+ std::string result;
31
+ while (value) {
32
+ result.push_back(char('0' + value % 10));
33
+ value /= 10;
34
+ }
35
+ if (negative)
36
+ result.push_back('-');
37
+ std::reverse(result.begin(), result.end());
38
+ return result;
39
+ }
40
+
41
+ // Equality multipliers are free. Upper-inequality multipliers must be <= 0.
42
+ // For 0<=z<=1 and Az<=b this is C+b*d+sum(min(0,c-A^T*d)).
43
+ template <class Check>
44
+ IntegerCertificate evaluate_integer_dual(const PreparedModel &model,
45
+ const std::vector<int64_t> &dual,
46
+ Check check,
47
+ std::vector<Wide> *assignment_reduced = nullptr) {
48
+ if (dual.size() != model.rows.size() || model.costs.size() > max_variables ||
49
+ model.rows.size() > max_constraints)
50
+ throw std::invalid_argument("Invalid LP certificate dimensions");
51
+ std::vector<Wide> reduced;
52
+ reduced.reserve(model.costs.size());
53
+ for (int64_t cost : model.costs)
54
+ reduced.push_back(Wide(cost) * certificate_scale);
55
+ Wide lower = Wide(model.constant) * certificate_scale;
56
+ size_t nonzeros = 0;
57
+ for (size_t i = 0; i < model.rows.size(); ++i) {
58
+ if (!(i % 128))
59
+ check();
60
+ const auto &row = model.rows[i];
61
+ const int64_t multiplier = dual[i];
62
+ if ((!row.equality && multiplier > 0) || multiplier < -1000000000000LL ||
63
+ multiplier > 1000000000000LL)
64
+ throw std::invalid_argument("Invalid LP certificate multiplier");
65
+ lower += Wide(row.rhs) * multiplier;
66
+ nonzeros += row.terms.size();
67
+ if (nonzeros > max_nonzeros)
68
+ throw std::invalid_argument("LP certificate exceeds nonzero cap");
69
+ for (const auto &term : row.terms) {
70
+ if (term.column < 0 || size_t(term.column) >= reduced.size())
71
+ throw std::invalid_argument("Invalid LP certificate column");
72
+ reduced[term.column] -= Wide(term.coefficient) * multiplier;
73
+ }
74
+ }
75
+ for (Wide value : reduced)
76
+ if (value < 0)
77
+ lower += value;
78
+ Wide rounded = lower >= 0
79
+ ? (lower + certificate_scale - 1) / certificate_scale
80
+ : lower / certificate_scale;
81
+ // Every true mapping has cost mass-2*overlap, hence the ORIGINAL matrix
82
+ // lattice mass modulo 2*gcd. No floating rounding enters this step.
83
+ if (model.gcd) {
84
+ const Wide step = 2 * Wide(model.gcd);
85
+ Wide residue = (Wide(model.mass) - rounded) % step;
86
+ if (residue < 0)
87
+ residue += step;
88
+ rounded += residue;
89
+ }
90
+ check();
91
+ if (rounded < std::numeric_limits<int64_t>::min() ||
92
+ rounded > std::numeric_limits<int64_t>::max())
93
+ throw std::overflow_error("LP certificate bound exceeds int64");
94
+ if (assignment_reduced)
95
+ assignment_reduced->assign(reduced.begin(),
96
+ reduced.begin() + model.assignment_variables);
97
+ return {lower, int64_t(rounded), dual};
98
+ }
99
+
100
+ // Floating vectors are only proposals; clipping/projection cannot invalidate
101
+ // the subsequent exact bound. Even a numerical failure may yield a usable
102
+ // vector, provided its original dimensions are correct.
103
+ template <class Check>
104
+ IntegerCertificate certify_proposal(const PreparedModel &model,
105
+ const std::vector<double> &proposal,
106
+ Check check,
107
+ std::vector<Wide> *assignment_reduced = nullptr) {
108
+ if (proposal.size() != model.rows.size())
109
+ throw std::invalid_argument("Invalid LP proposal dimensions");
110
+ std::vector<int64_t> dual(proposal.size());
111
+ for (size_t i = 0; i < proposal.size(); ++i) {
112
+ if (!(i % 128))
113
+ check();
114
+ double value = std::isfinite(proposal[i]) ? proposal[i] : 0;
115
+ value = std::max(-1000000.0, std::min(1000000.0, value));
116
+ int64_t encoded = std::llround(value * certificate_scale);
117
+ if (!model.rows[i].equality)
118
+ encoded = std::min(int64_t{0}, encoded);
119
+ dual[i] = encoded;
120
+ }
121
+ return evaluate_integer_dual(model, dual, check, assignment_reduced);
122
+ }
123
+ #endif // exact wide arithmetic; unsupported compilers use the PABS fallback.
124
+ } // namespace sparse_root_lp
125
+ } // namespace synkit_mapper