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.
- synkit/CRN/Benchmark/__init__.py +53 -0
- synkit/CRN/Benchmark/crosschecks.py +13 -0
- synkit/CRN/Benchmark/kegg.py +12 -0
- synkit/CRN/Benchmark/networks.py +13 -0
- synkit/CRN/Benchmark/scaling.py +13 -0
- synkit/CRN/Benchmark/validate.py +13 -0
- synkit/CRN/Construct/__init__.py +16 -0
- synkit/CRN/Construct/abstract.py +668 -0
- synkit/CRN/Construct/arity.py +36 -0
- synkit/CRN/Construct/builder.py +619 -0
- synkit/CRN/Construct/derivation.py +63 -0
- synkit/CRN/Construct/flattener.py +100 -0
- synkit/CRN/Construct/keys.py +14 -0
- synkit/CRN/Construct/mixtures.py +117 -0
- synkit/CRN/Construct/rdkit_worker.py +69 -0
- synkit/CRN/Construct/smiles.py +99 -0
- synkit/CRN/Construct/state.py +31 -0
- synkit/CRN/Construct/strategy.py +75 -0
- synkit/CRN/Construct/worker.py +42 -0
- synkit/CRN/IO/__init__.py +36 -0
- synkit/CRN/IO/sbml.py +925 -0
- synkit/CRN/Pathway/__init__.py +72 -0
- synkit/CRN/Pathway/_adapter.py +333 -0
- synkit/CRN/Pathway/pathfinder.py +500 -0
- synkit/CRN/Pathway/reachability.py +796 -0
- synkit/CRN/Pathway/realizability.py +1322 -0
- synkit/CRN/Petrinet/__init__.py +93 -0
- synkit/CRN/Petrinet/analyzer.py +486 -0
- synkit/CRN/Petrinet/minimal_semiflows.py +436 -0
- synkit/CRN/Petrinet/net.py +1041 -0
- synkit/CRN/Petrinet/persistence.py +97 -0
- synkit/CRN/Petrinet/semiflows.py +483 -0
- synkit/CRN/Petrinet/siphon_search.py +402 -0
- synkit/CRN/Petrinet/structure.py +286 -0
- synkit/CRN/Props/__init__.py +130 -0
- synkit/CRN/Props/_rank.py +29 -0
- synkit/CRN/Props/deficiency.py +953 -0
- synkit/CRN/Props/dynamics.py +832 -0
- synkit/CRN/Props/helper.py +151 -0
- synkit/CRN/Props/stoich.py +751 -0
- synkit/CRN/Props/thermo.py +584 -0
- synkit/CRN/Query/__init__.py +66 -0
- synkit/CRN/Query/cache.py +41 -0
- synkit/CRN/Query/kegg_api.py +99 -0
- synkit/CRN/Query/kegg_extract.py +714 -0
- synkit/CRN/Query/kegg_impute.py +707 -0
- synkit/CRN/Query/kegg_parse.py +480 -0
- synkit/CRN/Query/to_syncrn.py +290 -0
- synkit/CRN/README.md +234 -0
- synkit/CRN/Structure/__init__.py +12 -0
- synkit/CRN/Structure/_graph_io.py +713 -0
- synkit/CRN/Structure/_matrices.py +88 -0
- synkit/CRN/Structure/_parse.py +544 -0
- synkit/CRN/Structure/reaction.py +237 -0
- synkit/CRN/Structure/rule.py +55 -0
- synkit/CRN/Structure/species.py +46 -0
- synkit/CRN/Structure/syncrn.py +929 -0
- synkit/CRN/Symmetry/__init__.py +20 -0
- synkit/CRN/Symmetry/_common.py +1059 -0
- synkit/CRN/Symmetry/_ir.py +940 -0
- synkit/CRN/Symmetry/automorphism.py +472 -0
- synkit/CRN/Symmetry/canon.py +441 -0
- synkit/CRN/Symmetry/isomorphism.py +412 -0
- synkit/CRN/Symmetry/symmetry.py +61 -0
- synkit/CRN/Symmetry/wl_canon.py +967 -0
- synkit/CRN/Visualize/__init__.py +11 -0
- synkit/CRN/Visualize/labels.py +113 -0
- synkit/CRN/Visualize/layout.py +708 -0
- synkit/CRN/Visualize/palette.py +292 -0
- synkit/CRN/Visualize/validation.py +122 -0
- synkit/CRN/Visualize/vis.py +1152 -0
- synkit/CRN/__init__.py +233 -0
- synkit/CRN/_build.py +50 -0
- synkit/CRN/_native_build.py +175 -0
- synkit/CRN/analysis.py +629 -0
- synkit/CRN/backend.py +74 -0
- synkit/CRN/cpp/CMakeLists.txt +58 -0
- synkit/CRN/cpp/algebra.cpp +46 -0
- synkit/CRN/cpp/closure.cpp +29 -0
- synkit/CRN/cpp/exact.h +55 -0
- synkit/CRN/cpp/pathway.cpp +46 -0
- synkit/CRN/cpp/semiflows.cpp +209 -0
- synkit/CRN/cpp/structural.cpp +240 -0
- synkit/CRN/cpp/symmetry.cpp +45 -0
- synkit/CRN/cpp/write_manifest.cmake +28 -0
- synkit/CRN/kinds.py +137 -0
- synkit/CRN/lib/synkit_crn.dll +0 -0
- synkit/CRN/lib/synkit_crn.json +33 -0
- synkit/CRN/native.py +388 -0
- synkit/CRN/native_analysis.py +459 -0
- synkit/Chem/Cluster/__init__.py +0 -0
- synkit/Chem/Cluster/butina.py +140 -0
- synkit/Chem/Fingerprint/__init__.py +0 -0
- synkit/Chem/Fingerprint/fp_calculator.py +155 -0
- synkit/Chem/Fingerprint/smiles_featurizer.py +258 -0
- synkit/Chem/Fingerprint/transformation_fp.py +139 -0
- synkit/Chem/Mapper/README.rst +43 -0
- synkit/Chem/Mapper/__init__.py +255 -0
- synkit/Chem/Mapper/_compat.py +130 -0
- synkit/Chem/Mapper/adapters/__init__.py +1 -0
- synkit/Chem/Mapper/adapters/prediction.py +126 -0
- synkit/Chem/Mapper/adapters/template.py +412 -0
- synkit/Chem/Mapper/chem/__init__.py +52 -0
- synkit/Chem/Mapper/chem/aam.py +673 -0
- synkit/Chem/Mapper/chem/blind.py +160 -0
- synkit/Chem/Mapper/chem/its.py +309 -0
- synkit/Chem/Mapper/chem/smiles.py +564 -0
- synkit/Chem/Mapper/graph/__init__.py +66 -0
- synkit/Chem/Mapper/graph/automorphism.py +395 -0
- synkit/Chem/Mapper/graph/blockcut.py +98 -0
- synkit/Chem/Mapper/graph/labeled_graph.py +104 -0
- synkit/Chem/Mapper/graph/refine.py +176 -0
- synkit/Chem/Mapper/graph/synkit_adapter.py +110 -0
- synkit/Chem/Mapper/io/__init__.py +13 -0
- synkit/Chem/Mapper/io/idxmapstr.py +82 -0
- synkit/Chem/Mapper/mapper.py +685 -0
- synkit/Chem/Mapper/reaction_search.py +554 -0
- synkit/Chem/Mapper/reporting/__init__.py +1 -0
- synkit/Chem/Mapper/reporting/alternatives.py +451 -0
- synkit/Chem/Mapper/reporting/analysis.py +681 -0
- synkit/Chem/Mapper/reporting/native_analysis.py +485 -0
- synkit/Chem/Mapper/reporting/spectrum.py +642 -0
- synkit/Chem/Mapper/solvers/__init__.py +1 -0
- synkit/Chem/Mapper/solvers/exact/__init__.py +141 -0
- synkit/Chem/Mapper/solvers/exact/assignment/__init__.py +1 -0
- synkit/Chem/Mapper/solvers/exact/assignment/assignment_certificate.py +113 -0
- synkit/Chem/Mapper/solvers/exact/assignment/assignment_domains.py +162 -0
- synkit/Chem/Mapper/solvers/exact/assignment/assignment_verification.py +58 -0
- synkit/Chem/Mapper/solvers/exact/assignment/incremental_assignment.py +247 -0
- synkit/Chem/Mapper/solvers/exact/certificate.py +128 -0
- synkit/Chem/Mapper/solvers/exact/core.py +183 -0
- synkit/Chem/Mapper/solvers/exact/distance_search/__init__.py +1 -0
- synkit/Chem/Mapper/solvers/exact/distance_search/bounds.py +319 -0
- synkit/Chem/Mapper/solvers/exact/distance_search/exhaustive.py +179 -0
- synkit/Chem/Mapper/solvers/exact/distance_search/inputs.py +283 -0
- synkit/Chem/Mapper/solvers/exact/distance_search/records.py +242 -0
- synkit/Chem/Mapper/solvers/exact/distance_search/search.py +1025 -0
- synkit/Chem/Mapper/solvers/exact/distance_search/verify.py +378 -0
- synkit/Chem/Mapper/solvers/exact/edit_support.py +375 -0
- synkit/Chem/Mapper/solvers/exact/hybrid.py +224 -0
- synkit/Chem/Mapper/solvers/exact/hydrogen.py +264 -0
- synkit/Chem/Mapper/solvers/exact/kernel_solvers/__init__.py +1 -0
- synkit/Chem/Mapper/solvers/exact/kernel_solvers/branching.py +499 -0
- synkit/Chem/Mapper/solvers/exact/kernel_solvers/enumerate.py +1050 -0
- synkit/Chem/Mapper/solvers/exact/kernel_solvers/enumeration_result.py +30 -0
- synkit/Chem/Mapper/solvers/exact/kernel_solvers/kernel.py +256 -0
- synkit/Chem/Mapper/solvers/exact/kernel_solvers/milp.py +194 -0
- synkit/Chem/Mapper/solvers/exact/native/__init__.py +1 -0
- synkit/Chem/Mapper/solvers/exact/native/build.py +154 -0
- synkit/Chem/Mapper/solvers/exact/native/candidates.py +593 -0
- synkit/Chem/Mapper/solvers/exact/native/canonical.py +396 -0
- synkit/Chem/Mapper/solvers/exact/native/disk_frontier.py +415 -0
- synkit/Chem/Mapper/solvers/exact/native/frontier.py +390 -0
- synkit/Chem/Mapper/solvers/exact/native/hydrogen_quotient.py +213 -0
- synkit/Chem/Mapper/solvers/exact/native/its.py +528 -0
- synkit/Chem/Mapper/solvers/exact/native/native_distance.cpp +2803 -0
- synkit/Chem/Mapper/solvers/exact/native/orbit_aggregation.py +328 -0
- synkit/Chem/Mapper/solvers/exact/native/parallel.py +205 -0
- synkit/Chem/Mapper/solvers/exact/native/pmcd.py +203 -0
- synkit/Chem/Mapper/solvers/exact/native/runtime.py +40 -0
- synkit/Chem/Mapper/solvers/exact/native/search.py +294 -0
- synkit/Chem/Mapper/solvers/exact/native/separator.py +224 -0
- synkit/Chem/Mapper/solvers/exact/native_build.py +12 -0
- synkit/Chem/Mapper/solvers/exact/pabs/__init__.py +1 -0
- synkit/Chem/Mapper/solvers/exact/pabs/cost_lattice.py +43 -0
- synkit/Chem/Mapper/solvers/exact/pabs/factor_spectrum.py +110 -0
- synkit/Chem/Mapper/solvers/exact/pabs/multi_shell.py +368 -0
- synkit/Chem/Mapper/solvers/exact/pabs/propagation.py +679 -0
- synkit/Chem/Mapper/solvers/exact/pabs/propagation_bounds.py +436 -0
- synkit/Chem/Mapper/solvers/exact/pabs/propagation_limits.py +13 -0
- synkit/Chem/Mapper/solvers/exact/pabs/propagation_search.py +856 -0
- synkit/Chem/Mapper/solvers/exact/pabs/propagation_symmetry.py +66 -0
- synkit/Chem/Mapper/solvers/exact/pabs/residual_typed_bonds.py +136 -0
- synkit/Chem/Mapper/solvers/exact/pabs/reward_frontier.py +201 -0
- synkit/Chem/Mapper/solvers/exact/pabs/separator_bound.py +258 -0
- synkit/Chem/Mapper/solvers/exact/pabs/separator_spectrum.py +308 -0
- synkit/Chem/Mapper/solvers/exact/pabs/sparse_reward_bound.py +207 -0
- synkit/Chem/Mapper/solvers/exact/pabs/suffix_spectrum.py +299 -0
- synkit/Chem/Mapper/solvers/exact/search.py +55 -0
- synkit/Chem/Mapper/solvers/exact/seeds/__init__.py +1 -0
- synkit/Chem/Mapper/solvers/exact/seeds/seed.py +104 -0
- synkit/Chem/Mapper/solvers/exact/seeds/seed_fragments.py +148 -0
- synkit/Chem/Mapper/solvers/exact/seeds/seed_relaxation.py +181 -0
- synkit/Chem/Mapper/solvers/exact/symmetry.py +223 -0
- synkit/Chem/Mapper/solvers/native/__init__.py +4 -0
- synkit/Chem/Mapper/solvers/native/assignment.py +99 -0
- synkit/Chem/Mapper/solvers/native/astar.py +22 -0
- synkit/Chem/Mapper/solvers/native/build.py +385 -0
- synkit/Chem/Mapper/solvers/native/classification.py +641 -0
- synkit/Chem/Mapper/solvers/native/core.py +378 -0
- synkit/Chem/Mapper/solvers/native/cpp/CMakeLists.txt +120 -0
- synkit/Chem/Mapper/solvers/native/cpp/examples/map_reaction.cpp +29 -0
- synkit/Chem/Mapper/solvers/native/cpp/examples/slap_graph.cpp +63 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/assignment/assignment.h +18 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/astar/astar.h +18 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/astar/bound.h +33 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/core/pmcd_witness.h +16 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/core/runtime.h +130 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/hydrogen/hydrogen.h +73 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/mapper.h +175 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/mces/mces.h +9 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/pabs/seed.h +34 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/reaction/reaction.h +30 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/sepdp/sepdp.h +21 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/slap.h +72 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/solvers/solvers.h +16 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/symmetry/classification.h +140 -0
- synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/symmetry/cpabs.h +33 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/assignment/abb.cpp +302 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/astar/CMakeLists.txt +12 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/astar/README.md +47 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/astar/astar.cpp +228 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/astar/astar_graph.cpp +37 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/astar/bound.cpp +212 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/core/dispatch.cpp +272 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/core/pmcd_witness.cpp +36 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/hydrogen/hydrogen.cpp +380 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/mces/README.md +57 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/mces/mces.cpp +287 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/bridge.cpp +334 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/chemical_floor.inc +181 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/endpoint_symmetry.inc +104 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/exact_helpers.h +20 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_assignment_certificate.h +165 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_certificate.h +125 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_model.h +365 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_provider.inc +319 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_rounding.inc +170 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_test_hooks.h +342 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/objective_reduction.inc +137 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/overlap_dual.inc +351 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/profile_seed.inc +214 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/seed_heuristics.inc +640 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/sparse_embedding.cpp +430 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/sparse_root_lp.h +176 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/pabs/test_hooks.inc +262 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/reaction/reaction.cpp +611 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/sepdp/README.md +61 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/sepdp/sepdp.cpp +253 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/slap.cpp +810 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/solvers/formulation.h +138 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/solvers/maxsat.cpp +526 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/solvers/ortools.cpp +475 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/solvers/seed.h +80 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/solvers/weighted_cnf.h +256 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/supporting/README.md +43 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/supporting/dfs.cpp +123 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/supporting/edit_support.cpp +224 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification.cpp +553 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification_pipeline.cpp +124 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification_stream.h +13 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/cpabs.cpp +455 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/edge_deck.cpp +743 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/COPYRIGHT +44 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/LICENSE-2.0.txt +202 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naugraph.c +732 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naurng.c +94 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naurng.h +49 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nausparse.c +1771 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nausparse.h +133 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nautil.c +750 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naututil.h +355 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nauty.c +1256 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nauty.h +1544 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/schreier.c +1131 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/schreier.h +70 -0
- synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/sorttemplates.c +580 -0
- synkit/Chem/Mapper/solvers/native/hydrogen.py +711 -0
- synkit/Chem/Mapper/solvers/native/implicit.py +506 -0
- synkit/Chem/Mapper/solvers/native/implicit_certificate.py +187 -0
- synkit/Chem/Mapper/solvers/native/implicit_preparation.py +309 -0
- synkit/Chem/Mapper/solvers/native/lib/synkit_mapper.dll +0 -0
- synkit/Chem/Mapper/solvers/native/mces.py +16 -0
- synkit/Chem/Mapper/solvers/native/reaction.py +179 -0
- synkit/Chem/Mapper/solvers/native/reaction_build.py +277 -0
- synkit/Chem/Mapper/solvers/native/reaction_text.py +26 -0
- synkit/Chem/Mapper/solvers/native/runtime.py +242 -0
- synkit/Chem/Mapper/solvers/native/sepdp.py +47 -0
- synkit/Chem/Mapper/solvers/native/slap.py +266 -0
- synkit/Chem/Mapper/solvers/native/solvers.py +67 -0
- synkit/Chem/Mapper/solvers/native/stereo.py +86 -0
- synkit/Chem/Mapper/solvers/native/supporting.py +34 -0
- synkit/Chem/Mapper/solvers/native/symmetry.py +91 -0
- synkit/Chem/Mapper/solvers/slap/__init__.py +29 -0
- synkit/Chem/Mapper/solvers/slap/lap.py +174 -0
- synkit/Chem/Mapper/solvers/slap/sequential.py +696 -0
- synkit/Chem/Mapper/validation/__init__.py +1 -0
- synkit/Chem/Mapper/validation/aam_validator.py +442 -0
- synkit/Chem/Mapper/validation/annotations.py +274 -0
- synkit/Chem/Mapper/validation/bonds.py +124 -0
- synkit/Chem/Mapper/validation/cohorts.py +72 -0
- synkit/Chem/Mapper/validation/identifiability.py +150 -0
- synkit/Chem/Mapper/validation/numerical_scope.py +36 -0
- synkit/Chem/Mapper/validation/orbits.py +137 -0
- synkit/Chem/Molecule/__init__.py +0 -0
- synkit/Chem/Molecule/_chirality_loci.py +165 -0
- synkit/Chem/Molecule/_chirality_types.py +231 -0
- synkit/Chem/Molecule/_helical_loci.py +167 -0
- synkit/Chem/Molecule/_stereo_axis_evidence.py +202 -0
- synkit/Chem/Molecule/_stereo_element_detection.py +193 -0
- synkit/Chem/Molecule/_stereo_orientation_constraints.py +511 -0
- synkit/Chem/Molecule/_tetrahedral_carriers.py +63 -0
- synkit/Chem/Molecule/atom_features.py +379 -0
- synkit/Chem/Molecule/chirality.py +1041 -0
- synkit/Chem/Molecule/cip_assignment.py +569 -0
- synkit/Chem/Molecule/cip_ranking.py +843 -0
- synkit/Chem/Molecule/coordinate_stereo.py +503 -0
- synkit/Chem/Molecule/derived_stereo_naming.py +165 -0
- synkit/Chem/Molecule/descriptors.py +452 -0
- synkit/Chem/Molecule/formula.py +249 -0
- synkit/Chem/Molecule/global_stereo.py +175 -0
- synkit/Chem/Molecule/graph_annotator.py +300 -0
- synkit/Chem/Molecule/standardize.py +817 -0
- synkit/Chem/Molecule/stereo_evidence.py +179 -0
- synkit/Chem/Molecule/stereo_perception.py +1032 -0
- synkit/Chem/Molecule/valence.py +123 -0
- synkit/Chem/Reaction/Mapper/__init__.py +44 -0
- synkit/Chem/Reaction/__init__.py +20 -0
- synkit/Chem/Reaction/aam_validator.py +5 -0
- synkit/Chem/Reaction/balance_check.py +138 -0
- synkit/Chem/Reaction/canon_rsmi.py +249 -0
- synkit/Chem/Reaction/cleaning.py +58 -0
- synkit/Chem/Reaction/deionize.py +199 -0
- synkit/Chem/Reaction/explicit_h_audit.py +232 -0
- synkit/Chem/Reaction/fix_aam.py +64 -0
- synkit/Chem/Reaction/neutralize.py +207 -0
- synkit/Chem/Reaction/radical_wildcard.py +224 -0
- synkit/Chem/Reaction/standardize.py +203 -0
- synkit/Chem/Reaction/tautomerize.py +205 -0
- synkit/Chem/__init__.py +1 -0
- synkit/Chem/utils.py +315 -0
- synkit/Data/__init__.py +0 -0
- synkit/Data/aldol.json.gz +1 -0
- synkit/Data/gen_partial_aam.py +147 -0
- synkit/Data/paracetamol.json.gz +1 -0
- synkit/Graph/Canon/__init__.py +16 -0
- synkit/Graph/Canon/_native/__init__.py +13 -0
- synkit/Graph/Canon/_native/build.py +93 -0
- synkit/Graph/Canon/_native/lib/synkit_canon.dll +0 -0
- synkit/Graph/Canon/_native/prepare.py +49 -0
- synkit/Graph/Canon/_native/runtime.py +140 -0
- synkit/Graph/Canon/_native/search.py +137 -0
- synkit/Graph/Canon/canon_algs.py +228 -0
- synkit/Graph/Canon/canon_graph.py +531 -0
- synkit/Graph/Canon/cpp/CMakeLists.txt +42 -0
- synkit/Graph/Canon/cpp/README.md +123 -0
- synkit/Graph/Canon/cpp/examples/canonical_graph.cpp +16 -0
- synkit/Graph/Canon/cpp/include/synkit_canon/canon.h +85 -0
- synkit/Graph/Canon/cpp/src/canonical.cpp +391 -0
- synkit/Graph/Canon/cpp/src/symmetry.h +83 -0
- synkit/Graph/Canon/cpp/tests/symmetry.cpp +93 -0
- synkit/Graph/Canon/exact.py +1020 -0
- synkit/Graph/Canon/exact_refinement.py +368 -0
- synkit/Graph/Canon/nauty.py +143 -0
- synkit/Graph/Context/__init__.py +0 -0
- synkit/Graph/Context/hier_context.py +244 -0
- synkit/Graph/Context/radius_expand.py +252 -0
- synkit/Graph/FG/__init__.py +19 -0
- synkit/Graph/FG/api.py +39 -0
- synkit/Graph/FG/audit.py +155 -0
- synkit/Graph/FG/catalog.py +919 -0
- synkit/Graph/FG/detector.py +288 -0
- synkit/Graph/FG/model.py +97 -0
- synkit/Graph/FG/recognizers.py +274 -0
- synkit/Graph/FG/ring_system.py +154 -0
- synkit/Graph/Feature/Descriptors/topology.py +857 -0
- synkit/Graph/Feature/Fingerprint/__init__.py +0 -0
- synkit/Graph/Feature/Fingerprint/wl_rxn_fps.py +222 -0
- synkit/Graph/Feature/__init__.py +5 -0
- synkit/Graph/Feature/graph_descriptors.py +323 -0
- synkit/Graph/Feature/graph_fps.py +96 -0
- synkit/Graph/Feature/graph_signature.py +239 -0
- synkit/Graph/Feature/hash_fps.py +133 -0
- synkit/Graph/Feature/morgan_fps.py +88 -0
- synkit/Graph/Feature/path_fps.py +81 -0
- synkit/Graph/Feature/wl_hash.py +134 -0
- synkit/Graph/Fusion/__init__.py +85 -0
- synkit/Graph/Fusion/candidate.py +559 -0
- synkit/Graph/Fusion/constructor.py +877 -0
- synkit/Graph/Fusion/identity.py +184 -0
- synkit/Graph/Fusion/interface.py +700 -0
- synkit/Graph/Fusion/search.py +241 -0
- synkit/Graph/Hyrogen/__init__.py +6 -0
- synkit/Graph/Hyrogen/_misc.py +591 -0
- synkit/Graph/Hyrogen/hcomplete.py +995 -0
- synkit/Graph/Hyrogen/hcomplete_legacy.py +368 -0
- synkit/Graph/Hyrogen/hcompletion_algorithms.py +713 -0
- synkit/Graph/Hyrogen/hextend.py +570 -0
- synkit/Graph/Hyrogen/hextend_legacy.py +215 -0
- synkit/Graph/ITS/__init__.py +4 -0
- synkit/Graph/ITS/its_builder.py +120 -0
- synkit/Graph/ITS/its_construction.py +719 -0
- synkit/Graph/ITS/its_decompose.py +572 -0
- synkit/Graph/ITS/its_destruction.py +331 -0
- synkit/Graph/ITS/its_expand.py +1251 -0
- synkit/Graph/ITS/its_relabel.py +187 -0
- synkit/Graph/ITS/its_reverter.py +356 -0
- synkit/Graph/ITS/normalize_aam.py +145 -0
- synkit/Graph/ITS/partial_its.py +238 -0
- synkit/Graph/ITS/rc_extractor.py +656 -0
- synkit/Graph/ITS/stereo.py +74 -0
- synkit/Graph/MTG/__init__.py +107 -0
- synkit/Graph/MTG/gluing.py +451 -0
- synkit/Graph/MTG/history.py +928 -0
- synkit/Graph/MTG/inventory.py +118 -0
- synkit/Graph/MTG/local.py +447 -0
- synkit/Graph/MTG/mcs_matcher.py +246 -0
- synkit/Graph/MTG/mtg.py +611 -0
- synkit/Graph/MTG/mtg_explore.py +74 -0
- synkit/Graph/MTG/observation.py +209 -0
- synkit/Graph/MTG/process.py +577 -0
- synkit/Graph/MTG/queries.py +66 -0
- synkit/Graph/MTG/realization.py +95 -0
- synkit/Graph/MTG/series_parallel.py +107 -0
- synkit/Graph/MTG/utils.py +424 -0
- synkit/Graph/Matcher/__init__.py +10 -0
- synkit/Graph/Matcher/approx_mcs.py +1264 -0
- synkit/Graph/Matcher/auto_est.py +736 -0
- synkit/Graph/Matcher/automorphism.py +314 -0
- synkit/Graph/Matcher/batch_cluster.py +224 -0
- synkit/Graph/Matcher/dedup_matches.py +247 -0
- synkit/Graph/Matcher/graph_cluster.py +191 -0
- synkit/Graph/Matcher/graph_matcher.py +312 -0
- synkit/Graph/Matcher/graph_morphism.py +421 -0
- synkit/Graph/Matcher/mcs_matcher.py +804 -0
- synkit/Graph/Matcher/multi_turbo_iso.py +186 -0
- synkit/Graph/Matcher/orbit.py +284 -0
- synkit/Graph/Matcher/partial_matcher.py +694 -0
- synkit/Graph/Matcher/sing.py +544 -0
- synkit/Graph/Matcher/subgraph_matcher.py +812 -0
- synkit/Graph/Matcher/turbo_iso.py +272 -0
- synkit/Graph/Matcher/wl_sel.py +537 -0
- synkit/Graph/Mech/__init__.py +26 -0
- synkit/Graph/Mech/conversion.py +1466 -0
- synkit/Graph/Mech/conversion_debug.py +237 -0
- synkit/Graph/Mech/electron_accounting.py +200 -0
- synkit/Graph/Mech/lwg_editor.py +406 -0
- synkit/Graph/Mech/lwg_ops.py +313 -0
- synkit/Graph/Morphism/__init__.py +99 -0
- synkit/Graph/Morphism/constraints.py +460 -0
- synkit/Graph/Morphism/llg.py +999 -0
- synkit/Graph/Morphism/morphism.py +349 -0
- synkit/Graph/Morphism/stereo.py +258 -0
- synkit/Graph/Morphism/stereo_morphism.py +383 -0
- synkit/Graph/Morphism/stereo_morphism_helpers.py +957 -0
- synkit/Graph/Morphism/stereo_morphism_types.py +117 -0
- synkit/Graph/Stereo/__init__.py +376 -0
- synkit/Graph/Stereo/_descriptor_core.py +207 -0
- synkit/Graph/Stereo/_descriptor_serialization.py +138 -0
- synkit/Graph/Stereo/canonical.py +648 -0
- synkit/Graph/Stereo/changes.py +964 -0
- synkit/Graph/Stereo/composition.py +391 -0
- synkit/Graph/Stereo/configured.py +946 -0
- synkit/Graph/Stereo/couplings.py +245 -0
- synkit/Graph/Stereo/descriptors.py +1030 -0
- synkit/Graph/Stereo/enumeration.py +597 -0
- synkit/Graph/Stereo/extended_descriptors.py +406 -0
- synkit/Graph/Stereo/global_configured.py +152 -0
- synkit/Graph/Stereo/global_stereo.py +304 -0
- synkit/Graph/Stereo/identity.py +648 -0
- synkit/Graph/Stereo/interchange.py +496 -0
- synkit/Graph/Stereo/legacy.py +460 -0
- synkit/Graph/Stereo/matching.py +899 -0
- synkit/Graph/Stereo/native.py +154 -0
- synkit/Graph/Stereo/orbits.py +668 -0
- synkit/Graph/Stereo/outcomes.py +99 -0
- synkit/Graph/Stereo/pairwise.py +350 -0
- synkit/Graph/Stereo/rdkit_adapter.py +662 -0
- synkit/Graph/Stereo/rdkit_identity.py +118 -0
- synkit/Graph/Stereo/rdkit_resonance.py +140 -0
- synkit/Graph/Stereo/reaction_interchange.py +266 -0
- synkit/Graph/Stereo/semantics.py +296 -0
- synkit/Graph/Stereo/supports.py +257 -0
- synkit/Graph/Stereo/wire.py +339 -0
- synkit/Graph/Wildcard/__init__.py +0 -0
- synkit/Graph/Wildcard/fuse_graph.py +156 -0
- synkit/Graph/Wildcard/graph_wc.py +303 -0
- synkit/Graph/Wildcard/its_merge.py +857 -0
- synkit/Graph/Wildcard/radwc.py +114 -0
- synkit/Graph/Wildcard/wc_matcher.py +576 -0
- synkit/Graph/Wildcard/wildcard.py +225 -0
- synkit/Graph/__init__.py +17 -0
- synkit/Graph/canon_graph.py +14 -0
- synkit/Graph/syn_graph.py +199 -0
- synkit/Graph/utils.py +324 -0
- synkit/IO/__init__.py +4 -0
- synkit/IO/chem_converter.py +1059 -0
- synkit/IO/combinatorial/__init__.py +8 -0
- synkit/IO/combinatorial/gml_to_graph.py +223 -0
- synkit/IO/combinatorial/graph_to_gml.py +280 -0
- synkit/IO/combinatorial/graph_to_smarts.py +186 -0
- synkit/IO/combinatorial/smarts_expander.py +147 -0
- synkit/IO/combinatorial/smarts_generalizer.py +133 -0
- synkit/IO/combinatorial/smarts_to_graph.py +179 -0
- synkit/IO/conversion.py +42 -0
- synkit/IO/data_io.py +269 -0
- synkit/IO/data_process.py +143 -0
- synkit/IO/debug.py +73 -0
- synkit/IO/gml_to_nx.py +150 -0
- synkit/IO/graph_to_mol.py +199 -0
- synkit/IO/mol_to_graph.py +1105 -0
- synkit/IO/mol_to_graph_chemistry.py +545 -0
- synkit/IO/nx_to_gml.py +209 -0
- synkit/IO/smiles_to_id.py +123 -0
- synkit/Mechanism/__init__.py +151 -0
- synkit/Mechanism/adapters.py +136 -0
- synkit/Mechanism/audit.py +323 -0
- synkit/Mechanism/benchmark.py +638 -0
- synkit/Mechanism/compatibility.py +13 -0
- synkit/Mechanism/drawing.py +85 -0
- synkit/Mechanism/electron_models.py +725 -0
- synkit/Mechanism/equivalence.py +521 -0
- synkit/Mechanism/evidence.py +262 -0
- synkit/Mechanism/interchange.py +141 -0
- synkit/Mechanism/model.py +918 -0
- synkit/Mechanism/neighbor_stereo.py +312 -0
- synkit/Mechanism/radical_data.py +740 -0
- synkit/Mechanism/replay.py +986 -0
- synkit/Mechanism/schema.py +264 -0
- synkit/Mechanism/stereo_state.py +416 -0
- synkit/Mechanism/symbols.py +91 -0
- synkit/Rule/Apply/__init__.py +35 -0
- synkit/Rule/Apply/conditions.py +45 -0
- synkit/Rule/Apply/dpo.py +998 -0
- synkit/Rule/Apply/rule_matcher.py +218 -0
- synkit/Rule/Apply/validation.py +354 -0
- synkit/Rule/Compose/__init__.py +106 -0
- synkit/Rule/Compose/_identity.py +43 -0
- synkit/Rule/Compose/composition.py +976 -0
- synkit/Rule/Compose/laws.py +439 -0
- synkit/Rule/Compose/search.py +771 -0
- synkit/Rule/Compose/synrule.py +170 -0
- synkit/Rule/Modify/__init__.py +0 -0
- synkit/Rule/Modify/implict_rule.py +56 -0
- synkit/Rule/Modify/longest_path.py +92 -0
- synkit/Rule/Modify/molecule_rule.py +115 -0
- synkit/Rule/Modify/prune_templates.py +78 -0
- synkit/Rule/Modify/rule_utils.py +194 -0
- synkit/Rule/Modify/strip_rule.py +97 -0
- synkit/Rule/__init__.py +28 -0
- synkit/Rule/generic_stereo.py +884 -0
- synkit/Rule/stereo_identity.py +271 -0
- synkit/Rule/syn_rule.py +1090 -0
- synkit/Synthesis/MSR/__init__.py +0 -0
- synkit/Synthesis/MSR/path_finder.py +239 -0
- synkit/Synthesis/Metrics/__init__.py +0 -0
- synkit/Synthesis/Metrics/_base.py +52 -0
- synkit/Synthesis/Metrics/_plot.py +129 -0
- synkit/Synthesis/Metrics/_ranking.py +179 -0
- synkit/Synthesis/RBL/__init__.py +80 -0
- synkit/Synthesis/RBL/engine.py +1249 -0
- synkit/Synthesis/RBL/matching.py +652 -0
- synkit/Synthesis/RBL/overlap.py +336 -0
- synkit/Synthesis/RBL/pipeline.py +376 -0
- synkit/Synthesis/RBL/policy.py +139 -0
- synkit/Synthesis/RBL/proof.py +370 -0
- synkit/Synthesis/RBL/reaction.py +506 -0
- synkit/Synthesis/RBL/state.py +169 -0
- synkit/Synthesis/RBL/validation.py +1060 -0
- synkit/Synthesis/Reactor/__init__.py +60 -0
- synkit/Synthesis/Reactor/core/__init__.py +1 -0
- synkit/Synthesis/Reactor/core/engine.py +967 -0
- synkit/Synthesis/Reactor/core/product.py +621 -0
- synkit/Synthesis/Reactor/core/rewrite.py +561 -0
- synkit/Synthesis/Reactor/core/strategy.py +44 -0
- synkit/Synthesis/Reactor/matching/__init__.py +1 -0
- synkit/Synthesis/Reactor/matching/mixin.py +920 -0
- synkit/Synthesis/Reactor/matching/policy.py +345 -0
- synkit/Synthesis/Reactor/matching/symmetry.py +309 -0
- synkit/Synthesis/Reactor/output/__init__.py +1 -0
- synkit/Synthesis/Reactor/output/deduplication.py +703 -0
- synkit/Synthesis/Reactor/output/policy.py +16 -0
- synkit/Synthesis/Reactor/output/serialization.py +485 -0
- synkit/Synthesis/Reactor/output/structural.py +893 -0
- synkit/Synthesis/Reactor/stereo/__init__.py +1 -0
- synkit/Synthesis/Reactor/stereo/assignment.py +35 -0
- synkit/Synthesis/Reactor/stereo/mixin.py +780 -0
- synkit/Synthesis/Reactor/variants/__init__.py +1 -0
- synkit/Synthesis/Reactor/variants/imbalanced.py +180 -0
- synkit/Synthesis/Reactor/variants/partial.py +84 -0
- synkit/Synthesis/Reactor/workflow/__init__.py +1 -0
- synkit/Synthesis/Reactor/workflow/batch.py +550 -0
- synkit/Synthesis/Reactor/workflow/benchmark.py +143 -0
- synkit/Synthesis/Reactor/workflow/postprocess.py +267 -0
- synkit/Synthesis/Reactor/workflow/rule_filter.py +210 -0
- synkit/Synthesis/__init__.py +0 -0
- synkit/Synthesis/reactor_utils.py +316 -0
- synkit/Utils/__init__.py +0 -0
- synkit/Utils/utils.py +172 -0
- synkit/Vis/__init__.py +91 -0
- synkit/Vis/crn/__init__.py +40 -0
- synkit/Vis/epd/__init__.py +20 -0
- synkit/Vis/epd/arrows.py +425 -0
- synkit/Vis/epd/chem.py +197 -0
- synkit/Vis/epd/constants.py +83 -0
- synkit/Vis/epd/layout.py +283 -0
- synkit/Vis/epd/mapping.py +51 -0
- synkit/Vis/epd/models.py +136 -0
- synkit/Vis/epd/render.py +543 -0
- synkit/Vis/epd/utils.py +108 -0
- synkit/Vis/epd/visualizer.py +811 -0
- synkit/Vis/graph_visualizer.py +375 -0
- synkit/Vis/its/__init__.py +19 -0
- synkit/Vis/its/drawer.py +615 -0
- synkit/Vis/its_drawer.py +35 -0
- synkit/Vis/molecule/__init__.py +31 -0
- synkit/Vis/molecule/drawer.py +563 -0
- synkit/Vis/molecule/reaction.py +285 -0
- synkit/Vis/molecule_drawer.py +33 -0
- synkit/Vis/mtg/__init__.py +17 -0
- synkit/Vis/mtg/drawer.py +769 -0
- synkit/Vis/mtg_drawer.py +34 -0
- synkit/Vis/pdf_writer.py +146 -0
- synkit/Vis/reaction/__init__.py +19 -0
- synkit/Vis/reaction/rule.py +141 -0
- synkit/Vis/reaction/rxn.py +532 -0
- synkit/Vis/reaction_drawer.py +41 -0
- synkit/Vis/space/__init__.py +17 -0
- synkit/Vis/space/chemical.py +80 -0
- synkit/Vis/space/embedding.py +87 -0
- synkit/Vis/vis_synedu/Vis/__init__.py +7 -0
- synkit/Vis/vis_synedu/Vis/dpo.py +862 -0
- synkit/Vis/vis_synedu/rxn_vis.py +377 -0
- synkit/Vis/vis_synedu/vis.py +501 -0
- synkit/Vis/visual_drawer.py +215 -0
- synkit/Vis/visual_model.py +520 -0
- synkit/__init__.py +3 -0
- synkit/_native.py +91 -0
- synkit/examples.py +50 -0
- synkit/version.py +23 -0
- synkit-1.6.5.dist-info/METADATA +156 -0
- synkit-1.6.5.dist-info/RECORD +636 -0
- synkit-1.6.5.dist-info/WHEEL +4 -0
- synkit-1.6.5.dist-info/licenses/LICENSE +21 -0
- synkit-1.6.5.dist-info/licenses/synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/COPYRIGHT +44 -0
- 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
|
+
"""Bounded typed quadratic-overlap relaxation for feasible search seeds."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from scipy.optimize import linear_sum_assignment
|
|
5
|
+
from scipy.sparse import csr_matrix
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def improve_relaxed_seed_mapping( # noqa: C901
|
|
9
|
+
a, b, er, ep, mapping, *, iterations=40, fixed_mapping=None
|
|
10
|
+
):
|
|
11
|
+
"""Find a better typed bijection using four bounded relaxed starts.
|
|
12
|
+
|
|
13
|
+
At permutation vertices, layered same-sign bond overlap equals a constant
|
|
14
|
+
minus chemical distance. Sparse matrix products give its quadratic gradient;
|
|
15
|
+
element-blocked LAP steps and quadratic line searches optimize a doubly
|
|
16
|
+
stochastic relaxation. Only a fully evaluated feasible mapping is returned.
|
|
17
|
+
The relaxation is a heuristic, never an optimality certificate or a domain
|
|
18
|
+
restriction. Size/layer limits bound this optional preprocessing.
|
|
19
|
+
"""
|
|
20
|
+
n = len(mapping)
|
|
21
|
+
fixed = dict(fixed_mapping or {})
|
|
22
|
+
if any(i < 0 or i >= n or mapping[i] != image for i, image in fixed.items()):
|
|
23
|
+
raise ValueError("seed must agree with heuristic anchors")
|
|
24
|
+
if sorted(mapping) != list(range(len(er))) or any(
|
|
25
|
+
er[i] != ep[image] for i, image in enumerate(mapping)
|
|
26
|
+
):
|
|
27
|
+
raise ValueError("seed must be a complete element-compatible bijection")
|
|
28
|
+
if n > 256 or not np.isfinite(a).all() or not np.isfinite(b).all():
|
|
29
|
+
return list(mapping), {"iterations": 0, "skipped": "size_or_nonfinite_input"}
|
|
30
|
+
if len(np.unique(np.concatenate((a.ravel(), b.ravel())))) > 16:
|
|
31
|
+
return list(mapping), {"iterations": 0, "skipped": "weight_layer_limit"}
|
|
32
|
+
fixed_images = set(fixed.values())
|
|
33
|
+
blocks = [
|
|
34
|
+
(
|
|
35
|
+
np.asarray(
|
|
36
|
+
[i for i in range(n) if er[i] == e and i not in fixed], dtype=int
|
|
37
|
+
),
|
|
38
|
+
np.asarray(
|
|
39
|
+
[j for j in range(n) if ep[j] == e and j not in fixed_images], dtype=int
|
|
40
|
+
),
|
|
41
|
+
)
|
|
42
|
+
for e in sorted(set(er))
|
|
43
|
+
]
|
|
44
|
+
blocks = [(rows, cols) for rows, cols in blocks if len(rows)]
|
|
45
|
+
layers = []
|
|
46
|
+
for sign in (1, -1):
|
|
47
|
+
values = np.unique(np.concatenate(((sign * a).ravel(), (sign * b).ravel())))
|
|
48
|
+
previous = 0.0
|
|
49
|
+
for value in values[values > 0]:
|
|
50
|
+
ar = csr_matrix((sign * a >= value).astype(float))
|
|
51
|
+
bp = csr_matrix((sign * b >= value).astype(float))
|
|
52
|
+
layers.append((float(value - previous), ar, bp, ar.T.tocsr(), bp.T.tocsr()))
|
|
53
|
+
previous = value
|
|
54
|
+
|
|
55
|
+
def gradient(p):
|
|
56
|
+
g = np.zeros_like(p)
|
|
57
|
+
for weight, ar, bp, at, bt in layers:
|
|
58
|
+
g += weight * ((bp @ (ar @ p).T).T + (bt @ (at @ p).T).T)
|
|
59
|
+
return g
|
|
60
|
+
|
|
61
|
+
def project(p):
|
|
62
|
+
result = np.asarray(mapping).copy()
|
|
63
|
+
for rows, cols in blocks:
|
|
64
|
+
i, j = linear_sum_assignment(-p[np.ix_(rows, cols)])
|
|
65
|
+
result[rows[i]] = cols[j]
|
|
66
|
+
return result
|
|
67
|
+
|
|
68
|
+
def cost(m):
|
|
69
|
+
return 0.5 * float(np.abs(a - b[np.ix_(m, m)]).sum())
|
|
70
|
+
|
|
71
|
+
best = np.asarray(mapping).copy()
|
|
72
|
+
best_cost = cost(best)
|
|
73
|
+
identity = np.zeros((n, n))
|
|
74
|
+
identity[np.arange(n), best] = 1
|
|
75
|
+
uniform = np.zeros((n, n))
|
|
76
|
+
for i, j in fixed.items():
|
|
77
|
+
uniform[i, j] = 1
|
|
78
|
+
for rows, cols in blocks:
|
|
79
|
+
uniform[np.ix_(rows, cols)] = 1 / len(cols)
|
|
80
|
+
count = 0
|
|
81
|
+
for mixing in (0.95, 0.7, 0.3, 0.0):
|
|
82
|
+
p = mixing * identity + (1 - mixing) * uniform
|
|
83
|
+
for _ in range(iterations):
|
|
84
|
+
g = gradient(p)
|
|
85
|
+
candidate = project(g)
|
|
86
|
+
candidate_cost = cost(candidate)
|
|
87
|
+
if candidate_cost < best_cost:
|
|
88
|
+
best, best_cost = candidate.copy(), candidate_cost
|
|
89
|
+
q = np.zeros_like(p)
|
|
90
|
+
q[np.arange(n), candidate] = 1
|
|
91
|
+
d = q - p
|
|
92
|
+
slope = float((g * d).sum())
|
|
93
|
+
curve = 0.5 * float((d * gradient(d)).sum())
|
|
94
|
+
t = (
|
|
95
|
+
min(1.0, max(0.0, -slope / (2 * curve)))
|
|
96
|
+
if curve < 0
|
|
97
|
+
else float(slope + curve > 0)
|
|
98
|
+
)
|
|
99
|
+
count += 1
|
|
100
|
+
if t < 1e-8 or np.linalg.norm(d) < 1e-8:
|
|
101
|
+
break
|
|
102
|
+
p += t * d
|
|
103
|
+
candidate = project(p)
|
|
104
|
+
candidate_cost = cost(candidate)
|
|
105
|
+
if candidate_cost < best_cost:
|
|
106
|
+
best, best_cost = candidate.copy(), candidate_cost
|
|
107
|
+
return best.tolist(), {
|
|
108
|
+
"cost": best_cost,
|
|
109
|
+
"iterations": count,
|
|
110
|
+
"max_iterations_per_start": iterations,
|
|
111
|
+
"starts": 4,
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def refine_seed_mapping(a, b, er, ep, mapping, *, restarts=24):
|
|
116
|
+
"""Polish relaxed seeds and escape local basins with bounded typed shakes.
|
|
117
|
+
|
|
118
|
+
A graph-only profile lower bound stops optional work once the incumbent
|
|
119
|
+
reaches it. This stopping check makes no proof claim; exact search follows.
|
|
120
|
+
Deterministic perturbations change only the heuristic seed, never domains.
|
|
121
|
+
"""
|
|
122
|
+
from ..distance_search.bounds import atom_profile_costs, blocked_assignment_extreme
|
|
123
|
+
from .seed import improve_seed_mapping
|
|
124
|
+
|
|
125
|
+
best, initial = improve_relaxed_seed_mapping(a, b, er, ep, mapping)
|
|
126
|
+
if "skipped" in initial:
|
|
127
|
+
return best, initial
|
|
128
|
+
best, _ = improve_seed_mapping(a, b, er, ep, best)
|
|
129
|
+
best = np.asarray(best, dtype=int)
|
|
130
|
+
|
|
131
|
+
def cost(m):
|
|
132
|
+
return 0.5 * float(np.abs(a - b[np.ix_(m, m)]).sum())
|
|
133
|
+
|
|
134
|
+
best_cost = cost(best)
|
|
135
|
+
bound = blocked_assignment_extreme(
|
|
136
|
+
atom_profile_costs(a, b, er, ep), range(len(er)), range(len(ep)), er, ep
|
|
137
|
+
)
|
|
138
|
+
statistics = {
|
|
139
|
+
"initial": initial,
|
|
140
|
+
"profile_lower_bound": bound,
|
|
141
|
+
"restarts": 0,
|
|
142
|
+
"refinements": 0,
|
|
143
|
+
"improvements": 0,
|
|
144
|
+
}
|
|
145
|
+
for _ in range(2):
|
|
146
|
+
if best_cost <= bound + 1e-9:
|
|
147
|
+
break
|
|
148
|
+
candidate, _ = improve_relaxed_seed_mapping(a, b, er, ep, best.tolist())
|
|
149
|
+
candidate, _ = improve_seed_mapping(a, b, er, ep, candidate)
|
|
150
|
+
candidate_cost = cost(candidate)
|
|
151
|
+
statistics["refinements"] += 1
|
|
152
|
+
if candidate_cost >= best_cost:
|
|
153
|
+
break
|
|
154
|
+
best, best_cost = np.asarray(candidate), candidate_cost
|
|
155
|
+
statistics["improvements"] += 1
|
|
156
|
+
left, right = np.triu_indices(len(er), 1)
|
|
157
|
+
labels = np.asarray(er)
|
|
158
|
+
compatible = labels[left] == labels[right]
|
|
159
|
+
left, right = left[compatible], right[compatible]
|
|
160
|
+
rng = np.random.default_rng(0)
|
|
161
|
+
for attempt in range(restarts):
|
|
162
|
+
if not len(left) or best_cost <= bound + 1e-9:
|
|
163
|
+
break
|
|
164
|
+
scores = np.abs(a - b[np.ix_(best, best)]).sum(axis=1)
|
|
165
|
+
weights = scores[left] + scores[right] + 0.1
|
|
166
|
+
weights /= weights.sum()
|
|
167
|
+
candidate = best.copy()
|
|
168
|
+
for index in rng.choice(
|
|
169
|
+
len(left), size=min(2 + attempt % 5, len(left)), replace=False, p=weights
|
|
170
|
+
):
|
|
171
|
+
i, j = left[index], right[index]
|
|
172
|
+
candidate[i], candidate[j] = candidate[j], candidate[i]
|
|
173
|
+
candidate, _ = improve_relaxed_seed_mapping(a, b, er, ep, candidate.tolist())
|
|
174
|
+
candidate, _ = improve_seed_mapping(a, b, er, ep, candidate)
|
|
175
|
+
candidate_cost = cost(candidate)
|
|
176
|
+
statistics["restarts"] += 1
|
|
177
|
+
if candidate_cost < best_cost:
|
|
178
|
+
best, best_cost = np.asarray(candidate), candidate_cost
|
|
179
|
+
statistics["improvements"] += 1
|
|
180
|
+
statistics["cost"] = best_cost
|
|
181
|
+
return best.tolist(), statistics
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"""Memory-bounded permutation-group helpers for exact mapper branching."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
_MAX_STABILIZER_GENERATORS = 512
|
|
6
|
+
_MAX_SCHREIER_WORK = 100_000
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _identity(size):
|
|
10
|
+
return tuple(range(size))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _compose(first, second):
|
|
14
|
+
"""Return ``second`` after ``first`` for image-tuple permutations."""
|
|
15
|
+
return tuple(second[first[index]] for index in range(len(first)))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _inverse(permutation):
|
|
19
|
+
inverse = [0] * len(permutation)
|
|
20
|
+
for source, image in enumerate(permutation):
|
|
21
|
+
inverse[image] = source
|
|
22
|
+
return tuple(inverse)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _deduplicate_generators(generators):
|
|
26
|
+
generators = tuple(tuple(permutation) for permutation in generators)
|
|
27
|
+
if not generators:
|
|
28
|
+
return ()
|
|
29
|
+
identity = _identity(len(generators[0]))
|
|
30
|
+
return tuple(dict.fromkeys(g for g in generators if g != identity))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _point_stabilizer_data(
|
|
34
|
+
generators,
|
|
35
|
+
point,
|
|
36
|
+
*,
|
|
37
|
+
max_generators=_MAX_STABILIZER_GENERATORS,
|
|
38
|
+
max_work=_MAX_SCHREIER_WORK,
|
|
39
|
+
):
|
|
40
|
+
"""Return stabilizer generators, orbit size, and budget-completion status."""
|
|
41
|
+
seeds = _deduplicate_generators(generators)
|
|
42
|
+
if not seeds:
|
|
43
|
+
return (), 1, True
|
|
44
|
+
if all(generator[point] == point for generator in seeds):
|
|
45
|
+
# Identity transports reproduce the input subgroup; preserve budgets.
|
|
46
|
+
if len(seeds) > max_work or len(seeds) > max_generators:
|
|
47
|
+
return (), 1, False
|
|
48
|
+
return seeds, 1, True
|
|
49
|
+
size = len(seeds[0])
|
|
50
|
+
identity = _identity(size)
|
|
51
|
+
transversals = {point: identity}
|
|
52
|
+
pending = [point]
|
|
53
|
+
work = 0
|
|
54
|
+
while pending:
|
|
55
|
+
current = pending.pop()
|
|
56
|
+
current_transversal = transversals[current]
|
|
57
|
+
for generator in seeds:
|
|
58
|
+
work += 1
|
|
59
|
+
if work > max_work:
|
|
60
|
+
return (), len(transversals), False
|
|
61
|
+
image = generator[current]
|
|
62
|
+
if image not in transversals:
|
|
63
|
+
transversals[image] = _compose(current_transversal, generator)
|
|
64
|
+
pending.append(image)
|
|
65
|
+
|
|
66
|
+
inverses = {image: _inverse(transport) for image, transport in transversals.items()}
|
|
67
|
+
stabilizers = {}
|
|
68
|
+
for current, current_transversal in transversals.items():
|
|
69
|
+
for generator in seeds:
|
|
70
|
+
image = generator[current]
|
|
71
|
+
schreier = _compose(
|
|
72
|
+
_compose(current_transversal, generator),
|
|
73
|
+
inverses[image],
|
|
74
|
+
)
|
|
75
|
+
if schreier == identity:
|
|
76
|
+
continue
|
|
77
|
+
stabilizers.setdefault(schreier, None)
|
|
78
|
+
if len(stabilizers) > max_generators:
|
|
79
|
+
return (), len(transversals), False
|
|
80
|
+
return tuple(stabilizers), len(transversals), True
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def point_stabilizer_generators_checked(
|
|
84
|
+
generators,
|
|
85
|
+
point,
|
|
86
|
+
*,
|
|
87
|
+
max_generators=_MAX_STABILIZER_GENERATORS,
|
|
88
|
+
max_work=_MAX_SCHREIER_WORK,
|
|
89
|
+
):
|
|
90
|
+
"""Return ``(generators, complete)`` for the subgroup fixing ``point``.
|
|
91
|
+
|
|
92
|
+
``complete=False`` means the bounded Schreier construction deliberately
|
|
93
|
+
disabled deeper symmetry pruning. Callers that only need safe pruning may
|
|
94
|
+
ignore the flag; callers deriving orbit multiplicities must retain it.
|
|
95
|
+
"""
|
|
96
|
+
stabilizers, _, complete = _point_stabilizer_data(
|
|
97
|
+
generators,
|
|
98
|
+
point,
|
|
99
|
+
max_generators=max_generators,
|
|
100
|
+
max_work=max_work,
|
|
101
|
+
)
|
|
102
|
+
return stabilizers, complete
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def point_stabilizer_generators(
|
|
106
|
+
generators,
|
|
107
|
+
point,
|
|
108
|
+
*,
|
|
109
|
+
max_generators=_MAX_STABILIZER_GENERATORS,
|
|
110
|
+
max_work=_MAX_SCHREIER_WORK,
|
|
111
|
+
):
|
|
112
|
+
"""Return Schreier generators fixing ``point``, or identity on budget exit.
|
|
113
|
+
|
|
114
|
+
Returning no generators on a work-budget exit is conservative: subsequent
|
|
115
|
+
levels perform less symmetry pruning but cannot lose a mapping.
|
|
116
|
+
"""
|
|
117
|
+
stabilizers, _ = point_stabilizer_generators_checked(
|
|
118
|
+
generators,
|
|
119
|
+
point,
|
|
120
|
+
max_generators=max_generators,
|
|
121
|
+
max_work=max_work,
|
|
122
|
+
)
|
|
123
|
+
return stabilizers
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def permutation_group_order(
|
|
127
|
+
generators,
|
|
128
|
+
*,
|
|
129
|
+
max_generators=_MAX_STABILIZER_GENERATORS,
|
|
130
|
+
max_work=_MAX_SCHREIER_WORK,
|
|
131
|
+
):
|
|
132
|
+
"""Return the generated subgroup order without enumerating its elements.
|
|
133
|
+
|
|
134
|
+
Orbit--stabilizer is applied along a deterministic point chain. ``None``
|
|
135
|
+
is returned on a Schreier work-budget exit, so callers never promote a
|
|
136
|
+
partial stabilizer calculation to an exact labeled-solution count.
|
|
137
|
+
"""
|
|
138
|
+
stabilizers = _deduplicate_generators(generators)
|
|
139
|
+
if not stabilizers:
|
|
140
|
+
return 1
|
|
141
|
+
size = len(stabilizers[0])
|
|
142
|
+
order = 1
|
|
143
|
+
for point in range(size):
|
|
144
|
+
stabilizers, orbit_size, complete = _point_stabilizer_data(
|
|
145
|
+
stabilizers,
|
|
146
|
+
point,
|
|
147
|
+
max_generators=max_generators,
|
|
148
|
+
max_work=max_work,
|
|
149
|
+
)
|
|
150
|
+
if not complete:
|
|
151
|
+
return None
|
|
152
|
+
order *= orbit_size
|
|
153
|
+
if not stabilizers:
|
|
154
|
+
break
|
|
155
|
+
return order
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def orbital_candidate_witnesses(candidates, generators):
|
|
159
|
+
"""Map candidates to ``None`` representatives or exact pruning witnesses."""
|
|
160
|
+
candidates = tuple(sorted(candidates))
|
|
161
|
+
seeds = _deduplicate_generators(generators)
|
|
162
|
+
if not seeds:
|
|
163
|
+
return {candidate: None for candidate in candidates}
|
|
164
|
+
|
|
165
|
+
size = len(seeds[0])
|
|
166
|
+
identity = _identity(size)
|
|
167
|
+
candidate_set = set(candidates)
|
|
168
|
+
seen = set()
|
|
169
|
+
witnesses = {}
|
|
170
|
+
for representative in candidates:
|
|
171
|
+
if representative in seen:
|
|
172
|
+
continue
|
|
173
|
+
transversals = {representative: identity}
|
|
174
|
+
pending = [representative]
|
|
175
|
+
while pending:
|
|
176
|
+
current = pending.pop()
|
|
177
|
+
current_transversal = transversals[current]
|
|
178
|
+
for generator in seeds:
|
|
179
|
+
image = generator[current]
|
|
180
|
+
if image in transversals:
|
|
181
|
+
continue
|
|
182
|
+
transversals[image] = _compose(current_transversal, generator)
|
|
183
|
+
pending.append(image)
|
|
184
|
+
orbit = candidate_set.intersection(transversals)
|
|
185
|
+
seen.update(orbit)
|
|
186
|
+
witnesses[representative] = None
|
|
187
|
+
for candidate in orbit:
|
|
188
|
+
if candidate != representative:
|
|
189
|
+
# The inverse transporter maps the rejected candidate to the
|
|
190
|
+
# least representative while fixing the existing prefix.
|
|
191
|
+
witnesses[candidate] = _inverse(transversals[candidate])
|
|
192
|
+
return witnesses
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def largest_cyclic_subgroup(permutations, *, max_order=256):
|
|
196
|
+
"""Return the largest fully enumerated cyclic subgroup found safely."""
|
|
197
|
+
permutations = tuple(tuple(permutation) for permutation in permutations)
|
|
198
|
+
if not permutations:
|
|
199
|
+
return ()
|
|
200
|
+
identity = _identity(len(permutations[0]))
|
|
201
|
+
best = (identity,)
|
|
202
|
+
for generator in permutations:
|
|
203
|
+
powers = [identity]
|
|
204
|
+
current = identity
|
|
205
|
+
while len(powers) <= max_order:
|
|
206
|
+
current = _compose(current, generator)
|
|
207
|
+
if current == identity:
|
|
208
|
+
if len(powers) > len(best):
|
|
209
|
+
best = tuple(powers)
|
|
210
|
+
break
|
|
211
|
+
if current in powers:
|
|
212
|
+
break
|
|
213
|
+
powers.append(current)
|
|
214
|
+
return best
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
__all__ = [
|
|
218
|
+
"largest_cyclic_subgroup",
|
|
219
|
+
"orbital_candidate_witnesses",
|
|
220
|
+
"permutation_group_order",
|
|
221
|
+
"point_stabilizer_generators",
|
|
222
|
+
"point_stabilizer_generators_checked",
|
|
223
|
+
]
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Native assignment B&B and explicitly restricted uncertainty kernels."""
|
|
2
|
+
|
|
3
|
+
import ctypes as ct
|
|
4
|
+
from numbers import Integral
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
from .core import enumerate_core_mappings
|
|
9
|
+
from .runtime import INT, load_core
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def kernel_domains(mappings, types_r, types_p, *, library_path, close_block_size=4):
|
|
13
|
+
"""Build restricted domains in C++ from compatible supplied candidates.
|
|
14
|
+
|
|
15
|
+
Agreement among heuristic candidates is not a global-optimality proof.
|
|
16
|
+
"""
|
|
17
|
+
left, right = list(types_r), list(types_p)
|
|
18
|
+
n = len(left)
|
|
19
|
+
rows = list(mappings)
|
|
20
|
+
if not 1 <= n <= 1024 or len(right) != n or not rows:
|
|
21
|
+
raise ValueError(
|
|
22
|
+
"Kernel requires nonempty equal endpoint inventories and candidates"
|
|
23
|
+
)
|
|
24
|
+
if any(len(row) != n for row in rows) or any(
|
|
25
|
+
isinstance(j, bool) or not isinstance(j, Integral) or not 0 <= j < n
|
|
26
|
+
for row in rows
|
|
27
|
+
for j in row
|
|
28
|
+
):
|
|
29
|
+
raise ValueError("Kernel candidates require valid integer image indices")
|
|
30
|
+
if (
|
|
31
|
+
isinstance(close_block_size, bool)
|
|
32
|
+
or not isinstance(close_block_size, Integral)
|
|
33
|
+
or not 0 <= close_block_size < 2**31
|
|
34
|
+
):
|
|
35
|
+
raise ValueError("close_block_size must be a nonnegative C ABI integer")
|
|
36
|
+
registry = {}
|
|
37
|
+
codes = [
|
|
38
|
+
np.asarray(
|
|
39
|
+
[registry.setdefault(v, len(registry)) for v in side], dtype=np.int32
|
|
40
|
+
)
|
|
41
|
+
for side in (left, right)
|
|
42
|
+
]
|
|
43
|
+
permutations = np.ascontiguousarray(rows, dtype=np.int32)
|
|
44
|
+
domains = np.zeros((n, n), dtype=np.uint8)
|
|
45
|
+
lib = load_core(str(library_path))
|
|
46
|
+
if not hasattr(lib, "synkit_mapper_kernel_domains"):
|
|
47
|
+
raise RuntimeError("Library lacks native uncertainty-kernel construction")
|
|
48
|
+
lib.synkit_mapper_assignment_error.restype = ct.c_char_p
|
|
49
|
+
lib.synkit_mapper_kernel_domains.argtypes = [
|
|
50
|
+
ct.c_int32,
|
|
51
|
+
ct.c_int64,
|
|
52
|
+
INT,
|
|
53
|
+
INT,
|
|
54
|
+
INT,
|
|
55
|
+
ct.c_int32,
|
|
56
|
+
ct.POINTER(ct.c_uint8),
|
|
57
|
+
]
|
|
58
|
+
result = lib.synkit_mapper_kernel_domains(
|
|
59
|
+
n,
|
|
60
|
+
len(rows),
|
|
61
|
+
permutations.ctypes.data_as(INT),
|
|
62
|
+
*[v.ctypes.data_as(INT) for v in codes],
|
|
63
|
+
close_block_size,
|
|
64
|
+
domains.ctypes.data_as(ct.POINTER(ct.c_uint8)),
|
|
65
|
+
)
|
|
66
|
+
if result:
|
|
67
|
+
raise ValueError(lib.synkit_mapper_assignment_error().decode())
|
|
68
|
+
return domains
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def enumerate_assignment_mappings(lgp, *, library_path, **options):
|
|
72
|
+
return enumerate_core_mappings(
|
|
73
|
+
lgp, library_path=library_path, backend="abb", **options
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def enumerate_kernel_mappings(kernel, *, library_path, backend="kbb", **options):
|
|
78
|
+
"""Solve an existing Kernel in its fixed/uncertain domains, entirely natively."""
|
|
79
|
+
if backend not in {"kbb", "kmilp"}:
|
|
80
|
+
raise ValueError("Kernel backend must be kbb or kmilp")
|
|
81
|
+
n = len(kernel.lgp[0].labels)
|
|
82
|
+
allowed = np.zeros((n, n), dtype=np.uint8)
|
|
83
|
+
for i, j in kernel.fixed_mapping.items():
|
|
84
|
+
allowed[i, j] = 1
|
|
85
|
+
for position, i in enumerate(kernel.r_idx):
|
|
86
|
+
candidates = (
|
|
87
|
+
kernel.p_idx
|
|
88
|
+
if kernel.candidate_images is None
|
|
89
|
+
else kernel.candidate_images[position]
|
|
90
|
+
)
|
|
91
|
+
allowed[i, candidates] = 1
|
|
92
|
+
return enumerate_core_mappings(
|
|
93
|
+
kernel.lgp,
|
|
94
|
+
library_path=library_path,
|
|
95
|
+
backend=backend,
|
|
96
|
+
binary=kernel.binary,
|
|
97
|
+
allowed_domains=allowed,
|
|
98
|
+
**options,
|
|
99
|
+
)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Thin adapter for the full-space native best-first weighted A* backend."""
|
|
2
|
+
|
|
3
|
+
from .core import enumerate_core_mappings, map_reaction_core
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def enumerate_astar_mappings(graphs, *, library_path, **options):
|
|
7
|
+
"""Enumerate the requested labeled shell; frontend classifies exact ITSs.
|
|
8
|
+
|
|
9
|
+
All search decisions and admissible assignment bounds execute in C++.
|
|
10
|
+
The backend uses no symmetry pruning. Its memory cap measures accounted
|
|
11
|
+
frontier allocations, not whole-process RSS. A weighted chemical objective
|
|
12
|
+
is optimized with heuristic multiplier one, preserving exactness.
|
|
13
|
+
"""
|
|
14
|
+
return enumerate_core_mappings(
|
|
15
|
+
graphs, library_path=library_path, backend="astar", **options
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def map_reaction_astar(reaction, *, library_path, **options):
|
|
20
|
+
return map_reaction_core(
|
|
21
|
+
reaction, library_path=library_path, backend="astar", **options
|
|
22
|
+
)
|