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,255 @@
|
|
|
1
|
+
"""
|
|
2
|
+
synkit.Chem.Mapper
|
|
3
|
+
==================
|
|
4
|
+
|
|
5
|
+
Atom-to-atom mapping offers several explicit workflows:
|
|
6
|
+
|
|
7
|
+
* Platform wheels include the shared C++ PABS–SLAP core. Custom builds use
|
|
8
|
+
``_native.build.build_mapper_native``. The
|
|
9
|
+
``map_reaction_implicit`` interface scores heavy-atom classes
|
|
10
|
+
with minimum implicit-H Lewis completion, without expanding hydrogen.
|
|
11
|
+
Optional OR-Tools builds add checked integer LP bounds; floating solver
|
|
12
|
+
status and heuristic proposals never establish optimality on their own.
|
|
13
|
+
* ``Mapper(method='propagate').map(...)`` provides one interface and result
|
|
14
|
+
type for eight named methods. ``Mapper.methods()`` lists their names.
|
|
15
|
+
* ``map_reaction(...)`` defaults to full-space Python exact propagation search.
|
|
16
|
+
``backend='cpp'`` selects the optional compiled minimum and cost-range search.
|
|
17
|
+
Reaction SMILES use Lewis CD (bonds plus nonbonding-electron changes) and
|
|
18
|
+
explicit hydrogens by default. ``objective='bond'`` selects bond-only CD.
|
|
19
|
+
Omitting CD enumerates all minimum-distance classes; native search also
|
|
20
|
+
supports numeric ``CD_mode='at_most'`` for classes at distance <= CD.
|
|
21
|
+
* ``AAMapper().map_smiles(...)`` defaults to the approximate WL/SLAP mapper.
|
|
22
|
+
* ``AAMapper().map_smiles(..., enumerate_exact=True)`` runs SLAP followed by
|
|
23
|
+
exact refinement of a reduced uncertainty kernel.
|
|
24
|
+
* ``AAMapper().map_smiles(..., certify='exact')`` requests optional kernel MILP
|
|
25
|
+
certification of the SLAP results.
|
|
26
|
+
* ``AAMapper().enumerate_smiles(...)`` or ``map_smiles(..., CD=...)`` runs the
|
|
27
|
+
established full-distance search; SLAP may provide a seed for a minimum query.
|
|
28
|
+
|
|
29
|
+
PABS means Propagation and Assignment-Bounded Search. It is the package's
|
|
30
|
+
descriptive name for the exact interface used by ``map_reaction`` and
|
|
31
|
+
``enumerate_pabs_mappings``. Its Python solver combines one-to-one domain
|
|
32
|
+
propagation with LAP bounds; its C++ backend uses a separate traversal.
|
|
33
|
+
LAP means linear assignment problem. SLAP uses sequential LAP decisions for
|
|
34
|
+
heuristic matching. A kernel is the reduced subproblem extracted from SLAP
|
|
35
|
+
results for optional refinement; optimality within it is scoped to its fixed
|
|
36
|
+
assignments and candidate domains. The PABS routes search without extracting
|
|
37
|
+
this uncertainty kernel or invoking its MILP solver.
|
|
38
|
+
|
|
39
|
+
Research basis
|
|
40
|
+
--------------
|
|
41
|
+
The approximate SLAP mapper develops the mapping idea from:
|
|
42
|
+
Shin-ichi Koda and Shinji Saito, "General and scalable atom-to-atom mapping
|
|
43
|
+
via Weisfeiler-Lehman-like approximate graph matching", ChemRxiv (2025).
|
|
44
|
+
DOI: 10.26434/chemrxiv-2025-hthwn
|
|
45
|
+
|
|
46
|
+
Quick start
|
|
47
|
+
-----------
|
|
48
|
+
>>> from synkit.Chem.Mapper import Mapper
|
|
49
|
+
>>> result = Mapper(method="propagate").map("CO>>CO")
|
|
50
|
+
>>> result.complete, result.minimum_cost
|
|
51
|
+
(True, 0.0)
|
|
52
|
+
|
|
53
|
+
Several inequivalent symmetry classes can share a minimum. Inspect
|
|
54
|
+
``result.mapped_reactions`` and ``result.complete`` separately.
|
|
55
|
+
``Mapper("native")`` uses the bundled wheel library; an explicit
|
|
56
|
+
``library_path`` selects a custom build. The older
|
|
57
|
+
``solvers.exact.native.build.build_native`` ABI3-only builder remains supported.
|
|
58
|
+
|
|
59
|
+
Package layout
|
|
60
|
+
--------------
|
|
61
|
+
:mod:`synkit.Chem.Mapper.graph`
|
|
62
|
+
Labeled-graph data structure, WL/2-WL refinement, automorphisms,
|
|
63
|
+
block-cut-tree decomposition.
|
|
64
|
+
:mod:`synkit.Chem.Mapper.solvers.slap`
|
|
65
|
+
Sequential-LAP engine (:class:`GraphMatcher`) and LAP utilities
|
|
66
|
+
(chemical distance, Gilmore-Lawler lower bound).
|
|
67
|
+
:mod:`synkit.Chem.Mapper.solvers.exact`
|
|
68
|
+
Distinct exact methods live in ``distance_search/``, ``kernel_solvers/``,
|
|
69
|
+
``pabs/``, and ``native/``. Shared LAP proofs live in ``assignment/`` and
|
|
70
|
+
feasible-incumbent heuristics in ``seeds/``. ``enumerate_pabs_mappings``
|
|
71
|
+
selects Python or C++ through one interface. The legacy ABI3 source and
|
|
72
|
+
builder are adjacent in ``solvers/exact/native/``.
|
|
73
|
+
:mod:`synkit.Chem.Mapper.solvers.native`
|
|
74
|
+
Thin bindings, explicit immutable builds and chemistry preparation for the
|
|
75
|
+
shared C++ core in ``solvers/native/cpp/``. Production builds omit internal oracle exports;
|
|
76
|
+
a separate ``test_hooks=True`` build enables mathematical tests.
|
|
77
|
+
:mod:`synkit.Chem.Mapper.reaction_search`
|
|
78
|
+
Unmapped reaction SMILES, exact symmetry class representatives,
|
|
79
|
+
explicit or compressed hydrogen, and optional missing-atom padding.
|
|
80
|
+
:mod:`synkit.Chem.Mapper.chem`
|
|
81
|
+
RDKit SMILES I/O and ITS-based deduplication / electron-balance checks.
|
|
82
|
+
:mod:`synkit.Chem.Mapper.io`
|
|
83
|
+
Index-mapping-string helpers.
|
|
84
|
+
:mod:`synkit.Chem.Mapper.validation`
|
|
85
|
+
AAM validation, identifiability, and bond/annotation/cohort evaluation.
|
|
86
|
+
:mod:`synkit.Chem.Mapper.reporting`
|
|
87
|
+
Reference-blinded shell analysis, ITS spectra, structural alternatives,
|
|
88
|
+
and native two-sided orbit reports.
|
|
89
|
+
:mod:`synkit.Chem.Mapper.adapters`
|
|
90
|
+
Prediction seeds, validated class correspondences, and executable rules.
|
|
91
|
+
|
|
92
|
+
Historical flat module imports remain aliases to the same implementation
|
|
93
|
+
objects. See ``README.rst`` beside this module for method scopes and examples.
|
|
94
|
+
|
|
95
|
+
Public API
|
|
96
|
+
----------
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
from ._compat import (
|
|
100
|
+
MAPPER_MODULE_ALIASES as _MAPPER_MODULE_ALIASES,
|
|
101
|
+
)
|
|
102
|
+
from ._compat import (
|
|
103
|
+
register_module_aliases as _register_module_aliases,
|
|
104
|
+
install_solver_aliases as _install_solver_aliases,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
from .adapters.template import (
|
|
108
|
+
ClassCorrespondence,
|
|
109
|
+
ProductRecoveryScore,
|
|
110
|
+
SourceReplayResult,
|
|
111
|
+
class_correspondence_from_export,
|
|
112
|
+
correspondence_from_export,
|
|
113
|
+
executable_rule_from_correspondence,
|
|
114
|
+
mapped_reaction_from_correspondence,
|
|
115
|
+
prospective_products,
|
|
116
|
+
replay_executable_rule_on_source,
|
|
117
|
+
score_product_recovery,
|
|
118
|
+
)
|
|
119
|
+
from .chem.aam import AAMapper
|
|
120
|
+
from .chem.blind import BlindedReactionProblem, blinded_mapped_reaction_problem
|
|
121
|
+
from .solvers.exact.core import (
|
|
122
|
+
ITSComponentReduction,
|
|
123
|
+
reduce_to_reference_its_components,
|
|
124
|
+
)
|
|
125
|
+
from .solvers.exact.distance_search.search import (
|
|
126
|
+
CertificateVerificationError,
|
|
127
|
+
DistanceEnumerationCertificate,
|
|
128
|
+
DistanceEnumerationResult,
|
|
129
|
+
ExactEnumerationLimitError,
|
|
130
|
+
enumerate_distance_mappings,
|
|
131
|
+
verify_distance_enumeration_certificate,
|
|
132
|
+
)
|
|
133
|
+
from .solvers.exact.edit_support import (
|
|
134
|
+
BinaryEditBudget,
|
|
135
|
+
BinaryEditSupportResult,
|
|
136
|
+
binary_edit_budget,
|
|
137
|
+
enumerate_binary_edit_support_mappings,
|
|
138
|
+
)
|
|
139
|
+
from .solvers.exact.hybrid import (
|
|
140
|
+
HybridBackend,
|
|
141
|
+
HybridBackendDecision,
|
|
142
|
+
enumerate_hybrid_distance_mappings,
|
|
143
|
+
)
|
|
144
|
+
from .solvers.exact.hydrogen import (
|
|
145
|
+
HydrogenEnumerationResult,
|
|
146
|
+
HydrogenTransferPlan,
|
|
147
|
+
enumerate_lgp_hydrogen_transfers,
|
|
148
|
+
enumerate_minimal_hydrogen_transfers,
|
|
149
|
+
)
|
|
150
|
+
from .solvers.exact.pabs.propagation import PropagationConfig, enumerate_synister_cp_mappings
|
|
151
|
+
from .solvers.exact.search import enumerate_pabs_mappings
|
|
152
|
+
from .graph.labeled_graph import LabeledGraph
|
|
153
|
+
from .mapper import Mapper, MappingResult
|
|
154
|
+
from .reaction_search import ReactionMapping, ReactionMappingResult, map_reaction
|
|
155
|
+
from .reporting.alternatives import (
|
|
156
|
+
AlternativeTarget,
|
|
157
|
+
ExactITSAlternative,
|
|
158
|
+
ExactITSAlternativeResult,
|
|
159
|
+
MappedReactionITSAlternativeResult,
|
|
160
|
+
SeedMode,
|
|
161
|
+
enumerate_exact_its_alternatives,
|
|
162
|
+
enumerate_mapped_reaction_its_alternatives,
|
|
163
|
+
)
|
|
164
|
+
from .reporting.analysis import (
|
|
165
|
+
GlobalShellAnalysisResult,
|
|
166
|
+
GlobalShellConfig,
|
|
167
|
+
ReactionCenterSpectrum,
|
|
168
|
+
analyze_reference_blinded_global_shell,
|
|
169
|
+
)
|
|
170
|
+
from .reporting.spectrum import (
|
|
171
|
+
ExactStructureSpectrum,
|
|
172
|
+
ExactStructureSpectrumAccumulator,
|
|
173
|
+
exact_its_and_template_codes,
|
|
174
|
+
)
|
|
175
|
+
from .solvers.slap.sequential import GraphMatcher
|
|
176
|
+
from .solvers.native.implicit import map_reaction_implicit
|
|
177
|
+
from .validation.aam_validator import AAMValidator
|
|
178
|
+
from .solvers import exact, native as _native, slap
|
|
179
|
+
|
|
180
|
+
RESEARCH_BASIS_TITLE = (
|
|
181
|
+
"General and scalable atom-to-atom mapping via "
|
|
182
|
+
"Weisfeiler-Lehman-like approximate graph matching"
|
|
183
|
+
)
|
|
184
|
+
RESEARCH_BASIS_DOI = "10.26434/chemrxiv-2025-hthwn"
|
|
185
|
+
RESEARCH_BASIS_URL = f"https://doi.org/{RESEARCH_BASIS_DOI}"
|
|
186
|
+
RESEARCH_BASIS_AUTHORS = "Shin-ichi Koda and Shinji Saito"
|
|
187
|
+
|
|
188
|
+
__all__ = [
|
|
189
|
+
"RESEARCH_BASIS_AUTHORS",
|
|
190
|
+
"RESEARCH_BASIS_DOI",
|
|
191
|
+
"RESEARCH_BASIS_TITLE",
|
|
192
|
+
"RESEARCH_BASIS_URL",
|
|
193
|
+
"AAMValidator",
|
|
194
|
+
"AAMapper",
|
|
195
|
+
"AlternativeTarget",
|
|
196
|
+
"BinaryEditBudget",
|
|
197
|
+
"BinaryEditSupportResult",
|
|
198
|
+
"BlindedReactionProblem",
|
|
199
|
+
"CertificateVerificationError",
|
|
200
|
+
"ClassCorrespondence",
|
|
201
|
+
"DistanceEnumerationCertificate",
|
|
202
|
+
"DistanceEnumerationResult",
|
|
203
|
+
"ExactEnumerationLimitError",
|
|
204
|
+
"ExactITSAlternative",
|
|
205
|
+
"ExactITSAlternativeResult",
|
|
206
|
+
"ExactStructureSpectrum",
|
|
207
|
+
"ExactStructureSpectrumAccumulator",
|
|
208
|
+
"GlobalShellAnalysisResult",
|
|
209
|
+
"GlobalShellConfig",
|
|
210
|
+
"GraphMatcher",
|
|
211
|
+
"HybridBackend",
|
|
212
|
+
"HybridBackendDecision",
|
|
213
|
+
"HydrogenEnumerationResult",
|
|
214
|
+
"HydrogenTransferPlan",
|
|
215
|
+
"ITSComponentReduction",
|
|
216
|
+
"LabeledGraph",
|
|
217
|
+
"MappedReactionITSAlternativeResult",
|
|
218
|
+
"Mapper",
|
|
219
|
+
"MappingResult",
|
|
220
|
+
"ProductRecoveryScore",
|
|
221
|
+
"PropagationConfig",
|
|
222
|
+
"ReactionCenterSpectrum",
|
|
223
|
+
"ReactionMapping",
|
|
224
|
+
"ReactionMappingResult",
|
|
225
|
+
"SeedMode",
|
|
226
|
+
"SourceReplayResult",
|
|
227
|
+
"analyze_reference_blinded_global_shell",
|
|
228
|
+
"binary_edit_budget",
|
|
229
|
+
"blinded_mapped_reaction_problem",
|
|
230
|
+
"class_correspondence_from_export",
|
|
231
|
+
"correspondence_from_export",
|
|
232
|
+
"enumerate_binary_edit_support_mappings",
|
|
233
|
+
"enumerate_distance_mappings",
|
|
234
|
+
"enumerate_exact_its_alternatives",
|
|
235
|
+
"enumerate_hybrid_distance_mappings",
|
|
236
|
+
"enumerate_lgp_hydrogen_transfers",
|
|
237
|
+
"enumerate_mapped_reaction_its_alternatives",
|
|
238
|
+
"enumerate_minimal_hydrogen_transfers",
|
|
239
|
+
"enumerate_pabs_mappings",
|
|
240
|
+
"enumerate_synister_cp_mappings",
|
|
241
|
+
"exact_its_and_template_codes",
|
|
242
|
+
"executable_rule_from_correspondence",
|
|
243
|
+
"map_reaction",
|
|
244
|
+
"map_reaction_implicit",
|
|
245
|
+
"mapped_reaction_from_correspondence",
|
|
246
|
+
"prospective_products",
|
|
247
|
+
"reduce_to_reference_its_components",
|
|
248
|
+
"replay_executable_rule_on_source",
|
|
249
|
+
"score_product_recovery",
|
|
250
|
+
"verify_distance_enumeration_certificate",
|
|
251
|
+
]
|
|
252
|
+
|
|
253
|
+
# Preserve flat imports while keeping implementation files in focused packages.
|
|
254
|
+
_install_solver_aliases()
|
|
255
|
+
_register_module_aliases(__name__, _MAPPER_MODULE_ALIASES)
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""Historical module names for the reorganized mapper implementation.
|
|
2
|
+
|
|
3
|
+
Aliases share module objects, so monkeypatching and classes retain their
|
|
4
|
+
identity across old and new imports. Internal code uses canonical paths.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from importlib import import_module
|
|
8
|
+
from importlib.abc import Loader, MetaPathFinder
|
|
9
|
+
from importlib.util import find_spec, spec_from_loader
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
MAPPER_MODULE_ALIASES = {
|
|
14
|
+
"analysis": "reporting.analysis",
|
|
15
|
+
"native_analysis": "reporting.native_analysis",
|
|
16
|
+
"spectrum": "reporting.spectrum",
|
|
17
|
+
"alternatives": "reporting.alternatives",
|
|
18
|
+
"prediction_adapter": "adapters.prediction",
|
|
19
|
+
"template_adapter": "adapters.template",
|
|
20
|
+
"aam_validator": "validation.aam_validator",
|
|
21
|
+
"identifiability": "validation.identifiability",
|
|
22
|
+
"evaluation": "validation.bonds",
|
|
23
|
+
"annotation_evaluation": "validation.annotations",
|
|
24
|
+
"orbit_evaluation": "validation.orbits",
|
|
25
|
+
"cohort_evaluation": "validation.cohorts",
|
|
26
|
+
"numerical_scope": "validation.numerical_scope",
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
EXACT_MODULE_ALIASES = {
|
|
30
|
+
"distance": "distance_search.search",
|
|
31
|
+
"distance_bounds": "distance_search.bounds",
|
|
32
|
+
"distance_inputs": "distance_search.inputs",
|
|
33
|
+
"distance_records": "distance_search.records",
|
|
34
|
+
"distance_verify": "distance_search.verify",
|
|
35
|
+
"assignment_certificate": "assignment.assignment_certificate",
|
|
36
|
+
"assignment_domains": "assignment.assignment_domains",
|
|
37
|
+
"assignment_verification": "assignment.assignment_verification",
|
|
38
|
+
"incremental_assignment": "assignment.incremental_assignment",
|
|
39
|
+
"kernel": "kernel_solvers.kernel",
|
|
40
|
+
"branching": "kernel_solvers.branching",
|
|
41
|
+
"exhaustive": "distance_search.exhaustive",
|
|
42
|
+
"milp": "kernel_solvers.milp",
|
|
43
|
+
"enumerate": "kernel_solvers.enumerate",
|
|
44
|
+
"enumeration_result": "kernel_solvers.enumeration_result",
|
|
45
|
+
"propagation": "pabs.propagation",
|
|
46
|
+
"propagation_search": "pabs.propagation_search",
|
|
47
|
+
"propagation_bounds": "pabs.propagation_bounds",
|
|
48
|
+
"propagation_limits": "pabs.propagation_limits",
|
|
49
|
+
"propagation_symmetry": "pabs.propagation_symmetry",
|
|
50
|
+
"multi_shell": "pabs.multi_shell",
|
|
51
|
+
"suffix_spectrum": "pabs.suffix_spectrum",
|
|
52
|
+
"factor_spectrum": "pabs.factor_spectrum",
|
|
53
|
+
"separator_spectrum": "pabs.separator_spectrum",
|
|
54
|
+
"separator_bound": "pabs.separator_bound",
|
|
55
|
+
"cost_lattice": "pabs.cost_lattice",
|
|
56
|
+
"residual_typed_bonds": "pabs.residual_typed_bonds",
|
|
57
|
+
"reward_frontier": "pabs.reward_frontier",
|
|
58
|
+
"sparse_reward_bound": "pabs.sparse_reward_bound",
|
|
59
|
+
"seed": "seeds.seed",
|
|
60
|
+
"seed_fragments": "seeds.seed_fragments",
|
|
61
|
+
"seed_relaxation": "seeds.seed_relaxation",
|
|
62
|
+
"native_candidates": "native.candidates",
|
|
63
|
+
"native_canonical": "native.canonical",
|
|
64
|
+
"native_frontier": "native.frontier",
|
|
65
|
+
"native_its": "native.its",
|
|
66
|
+
"native_parallel": "native.parallel",
|
|
67
|
+
"native_search": "native.search",
|
|
68
|
+
"orbit_aggregation": "native.orbit_aggregation",
|
|
69
|
+
"disk_frontier": "native.disk_frontier",
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
_SOLVER_PREFIXES = {
|
|
74
|
+
f"{namespace}.{old}": f"synkit.Chem.Mapper.solvers.{new}"
|
|
75
|
+
for namespace in ("synkit.Chem.Mapper", "synkit.Chem.Reaction.Mapper")
|
|
76
|
+
for old, new in (("exact", "exact"), ("slap", "slap"), ("_native", "native"))
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class _SolverAliasLoader(Loader):
|
|
81
|
+
"""Resolve a historical solver module without creating a second implementation."""
|
|
82
|
+
|
|
83
|
+
def __init__(self, canonical_name):
|
|
84
|
+
self.canonical_name = canonical_name
|
|
85
|
+
|
|
86
|
+
def create_module(self, spec):
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
def exec_module(self, module):
|
|
90
|
+
sys.modules[module.__spec__.name] = import_module(self.canonical_name)
|
|
91
|
+
|
|
92
|
+
def get_code(self, fullname):
|
|
93
|
+
# runpy requests code without importing the alias. Call the canonical
|
|
94
|
+
# builder's main directly so its relative imports keep their new base.
|
|
95
|
+
if self.canonical_name.endswith((".build", ".native_build", ".reaction_build")):
|
|
96
|
+
source = f"from importlib import import_module\nimport_module({self.canonical_name!r}).main()\n"
|
|
97
|
+
else:
|
|
98
|
+
source = f"import runpy\nrunpy.run_module({self.canonical_name!r}, run_name='__main__')\n"
|
|
99
|
+
return compile(source, f"<compatibility {fullname}>", "exec")
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class _SolverAliasFinder(MetaPathFinder):
|
|
103
|
+
def find_spec(self, fullname, path=None, target=None):
|
|
104
|
+
for old, canonical in _SOLVER_PREFIXES.items():
|
|
105
|
+
if fullname == old or fullname.startswith(old + "."):
|
|
106
|
+
name = canonical + fullname[len(old):]
|
|
107
|
+
original = find_spec(name)
|
|
108
|
+
if original is None:
|
|
109
|
+
return None
|
|
110
|
+
return spec_from_loader(
|
|
111
|
+
fullname, _SolverAliasLoader(name),
|
|
112
|
+
origin=original.origin,
|
|
113
|
+
is_package=original.submodule_search_locations is not None,
|
|
114
|
+
)
|
|
115
|
+
return None
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def install_solver_aliases():
|
|
119
|
+
"""Keep old solver imports and build commands working after the source move."""
|
|
120
|
+
if not any(isinstance(finder, _SolverAliasFinder) for finder in sys.meta_path):
|
|
121
|
+
sys.meta_path.insert(0, _SolverAliasFinder())
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def register_module_aliases(package_name, aliases):
|
|
125
|
+
"""Bind historical children to canonical modules on an existing package."""
|
|
126
|
+
package = sys.modules[package_name]
|
|
127
|
+
for old_name, canonical_name in aliases.items():
|
|
128
|
+
module = import_module(f".{canonical_name}", package_name)
|
|
129
|
+
sys.modules[f"{package_name}.{old_name}"] = module
|
|
130
|
+
setattr(package, old_name, module)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Prediction seeds and conversion of mapping classes into executable rules."""
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Reference-free prediction inputs and strict coordinate alignment.
|
|
2
|
+
|
|
3
|
+
The connectivity contract matches :mod:`identifiability`. Alignment uses only
|
|
4
|
+
each endpoint graph; neither a deposited mapping nor an optimal candidate set
|
|
5
|
+
is accepted by this interface. Alternative endpoint isomorphisms differ by
|
|
6
|
+
endpoint automorphisms, so quotient bond scores are independent of that choice.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from collections import defaultdict
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
|
|
12
|
+
import networkx as nx
|
|
13
|
+
from rdkit import Chem
|
|
14
|
+
|
|
15
|
+
from ..validation.bonds import _graph
|
|
16
|
+
from ..validation.identifiability import extract_label, parse_reaction
|
|
17
|
+
from ..solvers.slap.sequential import GraphMatcher
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def unmapped_input(reaction: str) -> str:
|
|
21
|
+
"""Remove all map labels before serialization; retain every component.
|
|
22
|
+
|
|
23
|
+
Coordinates for the prediction study are those of the returned string.
|
|
24
|
+
Stereo is intentionally removed for the connectivity-only task, after the
|
|
25
|
+
strict parser rejects unsupported inventories, isotopes and radicals.
|
|
26
|
+
"""
|
|
27
|
+
parse_reaction(reaction)
|
|
28
|
+
sides = []
|
|
29
|
+
for side in reaction.split(">>"):
|
|
30
|
+
params = Chem.SmilesParserParams()
|
|
31
|
+
params.removeHs = False
|
|
32
|
+
mol = Chem.MolFromSmiles(side, params)
|
|
33
|
+
for atom in mol.GetAtoms():
|
|
34
|
+
atom.SetAtomMapNum(0)
|
|
35
|
+
mol = Chem.RemoveHs(mol)
|
|
36
|
+
sides.append(Chem.MolToSmiles(mol, canonical=False, isomericSmiles=False))
|
|
37
|
+
result = ">>".join(sides)
|
|
38
|
+
parse_reaction(result)
|
|
39
|
+
return result
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _map_ids(side):
|
|
43
|
+
params = Chem.SmilesParserParams()
|
|
44
|
+
params.removeHs = False
|
|
45
|
+
mol = Chem.MolFromSmiles(side, params)
|
|
46
|
+
if mol is None:
|
|
47
|
+
raise ValueError("Invalid predicted SMILES")
|
|
48
|
+
# RemoveHs retains heavy-atom relative order. H mapping is outside scope.
|
|
49
|
+
ids = tuple(a.GetAtomMapNum() for a in mol.GetAtoms() if a.GetAtomicNum() > 1)
|
|
50
|
+
if not ids or any(i <= 0 for i in ids) or len(set(ids)) != len(ids):
|
|
51
|
+
raise ValueError("Every predicted heavy atom needs one unique positive map ID")
|
|
52
|
+
return ids
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _align(source, target):
|
|
56
|
+
matcher = nx.algorithms.isomorphism.GraphMatcher(
|
|
57
|
+
_graph(source), _graph(target),
|
|
58
|
+
node_match=nx.algorithms.isomorphism.categorical_node_match("color", None),
|
|
59
|
+
edge_match=nx.algorithms.isomorphism.categorical_edge_match("order", None),
|
|
60
|
+
)
|
|
61
|
+
match = next(matcher.isomorphisms_iter(), None)
|
|
62
|
+
if match is None:
|
|
63
|
+
raise ValueError("Prediction changed an attributed endpoint graph")
|
|
64
|
+
return tuple(match[i] for i in range(len(source.atomic_numbers)))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@dataclass(frozen=True)
|
|
68
|
+
class AlignedPrediction:
|
|
69
|
+
mapping: tuple[int, ...]
|
|
70
|
+
reactant_to_output: tuple[int, ...]
|
|
71
|
+
product_to_output: tuple[int, ...]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def align_mapped_prediction(unmapped_reaction: str, mapped_output: str) -> AlignedPrediction:
|
|
75
|
+
"""Validate an untouched mapped output and return alignment witnesses."""
|
|
76
|
+
r, p = parse_reaction(unmapped_reaction)
|
|
77
|
+
rr, pp = parse_reaction(mapped_output)
|
|
78
|
+
rid, pid = map(_map_ids, mapped_output.split(">>"))
|
|
79
|
+
if set(rid) != set(pid):
|
|
80
|
+
raise ValueError("Predicted map-ID inventories differ between endpoints")
|
|
81
|
+
ra, pa = _align(r, rr), _align(p, pp)
|
|
82
|
+
product_by_id = {pid[out]: original for original, out in enumerate(pa)}
|
|
83
|
+
mapping = tuple(product_by_id[rid[out]] for out in ra)
|
|
84
|
+
extract_label(r, p, mapping) # complete element-compatible permutation
|
|
85
|
+
return AlignedPrediction(mapping, ra, pa)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def predict_slap(unmapped_reaction: str):
|
|
89
|
+
"""SLAP heavy-atom symmetry splitting with deterministic residual ties.
|
|
90
|
+
|
|
91
|
+
Requests splitting for every heavy atom, uses the first returned partition,
|
|
92
|
+
then pairs sorted indices
|
|
93
|
+
within each common final label. This is a declared single-map baseline,
|
|
94
|
+
not an exact optimizer, a ground-truth repair, or a claim that all unresolved
|
|
95
|
+
label blocks contain automorphism-equivalent atoms.
|
|
96
|
+
"""
|
|
97
|
+
r, p = parse_reaction(unmapped_reaction)
|
|
98
|
+
matcher = GraphMatcher(binary=False, max_lap_fingerprints=1000,
|
|
99
|
+
cache_label_blocks=True, deterministic_labels=True)
|
|
100
|
+
matcher.get_maps([r.graph(), p.graph()], break_sym_targets=list(range(len(r.atomic_numbers))))
|
|
101
|
+
if not matcher.results:
|
|
102
|
+
raise ValueError("SLAP returned no partition")
|
|
103
|
+
result = matcher.results[0]
|
|
104
|
+
lr, lp = result["lgp"]
|
|
105
|
+
left, right = defaultdict(list), defaultdict(list)
|
|
106
|
+
for i, label in enumerate(lr.labels):
|
|
107
|
+
left[label].append(i)
|
|
108
|
+
for i, label in enumerate(lp.labels):
|
|
109
|
+
right[label].append(i)
|
|
110
|
+
if set(left) != set(right) or any(len(left[k]) != len(right[k]) for k in left):
|
|
111
|
+
raise ValueError("SLAP partition multiplicities disagree")
|
|
112
|
+
mapping = [-1] * len(r.atomic_numbers)
|
|
113
|
+
for label in sorted(left):
|
|
114
|
+
for i, j in zip(left[label], right[label]):
|
|
115
|
+
mapping[i] = j
|
|
116
|
+
extract_label(r, p, mapping)
|
|
117
|
+
return {
|
|
118
|
+
"method": "slap-heavy-split-v1",
|
|
119
|
+
"mapping": mapping,
|
|
120
|
+
"raw_reactant_labels": list(lr.labels),
|
|
121
|
+
"raw_product_labels": list(lp.labels),
|
|
122
|
+
"returned_partition_count": len(matcher.results),
|
|
123
|
+
"reported_partition_cost": int(result["val"]),
|
|
124
|
+
"heavy_atom_splitting": True,
|
|
125
|
+
"tie_policy": "first-returned-partition_then_increasing-index-within-label",
|
|
126
|
+
}
|