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,309 @@
|
|
|
1
|
+
"""Reference-blind implicit-H Lewis proofs with exact H-component offsets.
|
|
2
|
+
|
|
3
|
+
This preparation does not call a mapper or expand H. Product isotope-zero H
|
|
4
|
+
may be ordinary neutral terminal H, isolated isotope-zero H, or isolated
|
|
5
|
+
ordinary H2. Free positive-electron H is matched by sorted electron counts
|
|
6
|
+
when positive-electron isotope-zero source H is also isolated. Source
|
|
7
|
+
free/charged/radical/H2/isotopic H is supported by separating its
|
|
8
|
+
mapping-independent objective terms. Matched
|
|
9
|
+
ordinary H2 bonds contribute a constant alongside attached-H counts. It returns
|
|
10
|
+
prepared heavy graphs and an **integer doubled-CD offset**, never H classes.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from collections import Counter
|
|
14
|
+
|
|
15
|
+
from rdkit import Chem
|
|
16
|
+
|
|
17
|
+
from synkit.Chem.Mapper.graph.labeled_graph import LabeledGraph
|
|
18
|
+
from synkit.IO.mol_to_graph import MolToGraph
|
|
19
|
+
|
|
20
|
+
from .reaction_text import split_reaction_fields
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class UnsupportedImplicitHydrogen(ValueError):
|
|
24
|
+
"""The stated constant/count reduction cannot prove this model."""
|
|
25
|
+
|
|
26
|
+
def __init__(self, reason):
|
|
27
|
+
self.reason = reason
|
|
28
|
+
super().__init__(reason)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _weight2(bond):
|
|
32
|
+
value = bond.GetBondTypeAsDouble() * 2
|
|
33
|
+
encoded = round(value)
|
|
34
|
+
if abs(value - encoded) > 1e-9 or encoded < 0:
|
|
35
|
+
raise UnsupportedImplicitHydrogen("non_half_integer_bond_weight")
|
|
36
|
+
return encoded
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _electrons(atom):
|
|
40
|
+
return 2 * MolToGraph.estimate_lone_pairs(atom) + atom.GetNumRadicalElectrons()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# Model guards and reduction offsets must remain paired with their endpoint data.
|
|
44
|
+
def prepare_implicit_problem(reaction, *, balance="dummy"): # noqa: C901
|
|
45
|
+
"""Return ``(heavy_graphs, offset2, metadata)`` for a mapless reaction.
|
|
46
|
+
|
|
47
|
+
Native proof costs for these graphs are in CD units; add offset2/2 once to
|
|
48
|
+
minimum/incumbent costs, or offset2 once to their doubled-CD counterparts.
|
|
49
|
+
This reduction is numeric/proof-only: it does not infer reference H truth
|
|
50
|
+
or enumerate H/class output. All map tags are forbidden at this blind API.
|
|
51
|
+
|
|
52
|
+
``UnsupportedImplicitHydrogen.reason`` gives an explicit unsupported-model
|
|
53
|
+
code. Invalid SMILES, maps, wildcards and strict inventory mismatch raise
|
|
54
|
+
ordinary ValueError. A caller may then use a separately labeled full-H
|
|
55
|
+
native proof with the remaining original budget.
|
|
56
|
+
"""
|
|
57
|
+
if not isinstance(reaction, str):
|
|
58
|
+
raise TypeError("reaction must be mapless reaction SMILES")
|
|
59
|
+
if balance not in {"dummy", "strict"}:
|
|
60
|
+
raise ValueError("balance must be 'dummy' or 'strict'")
|
|
61
|
+
parts = split_reaction_fields(
|
|
62
|
+
reaction,
|
|
63
|
+
error_message="Expected reactants>agents>products or reactants>>products",
|
|
64
|
+
)
|
|
65
|
+
if not parts[0] or not parts[2]:
|
|
66
|
+
raise ValueError("Expected reactants>agents>products or reactants>>products")
|
|
67
|
+
params = Chem.SmilesParserParams()
|
|
68
|
+
params.removeHs = False
|
|
69
|
+
mols = [Chem.MolFromSmiles(parts[i], params) for i in (0, 2)]
|
|
70
|
+
if any(mol is None for mol in mols):
|
|
71
|
+
raise ValueError("Could not parse reaction endpoint")
|
|
72
|
+
if any(atom.GetAtomMapNum() for mol in mols for atom in mol.GetAtoms()):
|
|
73
|
+
raise ValueError("Reference-blind PMCD preparation requires mapless endpoints")
|
|
74
|
+
if any(atom.GetAtomicNum() == 0 for mol in mols for atom in mol.GetAtoms()):
|
|
75
|
+
raise ValueError("Wildcard atoms require a concrete element")
|
|
76
|
+
|
|
77
|
+
heavy = [[atom for atom in mol.GetAtoms() if atom.GetAtomicNum() != 1] for mol in mols]
|
|
78
|
+
counts = [[MolToGraph._non_neighbor_h_count(atom) for atom in atoms] for atoms in heavy]
|
|
79
|
+
positions = [{atom.GetIdx(): i for i, atom in enumerate(atoms)} for atoms in heavy]
|
|
80
|
+
hydrogen_inventories = []
|
|
81
|
+
for side, mol in enumerate(mols):
|
|
82
|
+
inventory = Counter({0: sum(counts[side])})
|
|
83
|
+
for atom in mol.GetAtoms():
|
|
84
|
+
if atom.GetAtomicNum() == 1:
|
|
85
|
+
inventory[atom.GetIsotope()] += 1
|
|
86
|
+
hydrogen_inventories.append(+inventory)
|
|
87
|
+
|
|
88
|
+
# Positive-electron isotope-zero H must be free on both endpoints.
|
|
89
|
+
# Sorted electron matching is disjoint from attached-H and H2 matches.
|
|
90
|
+
product_positive_free_ids = set()
|
|
91
|
+
product_free_electrons = []
|
|
92
|
+
for atom in mols[1].GetAtoms():
|
|
93
|
+
if atom.GetAtomicNum() != 1 or atom.GetIsotope() or not _electrons(atom):
|
|
94
|
+
continue
|
|
95
|
+
if atom.GetDegree() or MolToGraph._non_neighbor_h_count(atom):
|
|
96
|
+
raise UnsupportedImplicitHydrogen("product_nonfree_positive_electron_hydrogen")
|
|
97
|
+
product_positive_free_ids.add(atom.GetIdx())
|
|
98
|
+
product_free_electrons.append(_electrons(atom))
|
|
99
|
+
source_free_electrons = []
|
|
100
|
+
if product_free_electrons:
|
|
101
|
+
for atom in mols[0].GetAtoms():
|
|
102
|
+
if atom.GetAtomicNum() != 1 or atom.GetIsotope() or not _electrons(atom):
|
|
103
|
+
continue
|
|
104
|
+
if atom.GetDegree() or MolToGraph._non_neighbor_h_count(atom):
|
|
105
|
+
raise UnsupportedImplicitHydrogen(
|
|
106
|
+
"source_nonfree_positive_electron_hydrogen_for_product_free_H_extension"
|
|
107
|
+
)
|
|
108
|
+
source_free_electrons.append(_electrons(atom))
|
|
109
|
+
source_free_electrons.sort(reverse=True)
|
|
110
|
+
product_free_electrons.sort(reverse=True)
|
|
111
|
+
preserved_free_electrons = sum(min(a, b) for a, b in zip(source_free_electrons, product_free_electrons))
|
|
112
|
+
# H2 components and heavy-attached H use disjoint vertices on both sides.
|
|
113
|
+
# Thus maximum preserved H-H bonds and maximum preserved heavy-H bonds
|
|
114
|
+
# can be attained simultaneously for every fixed typed heavy bijection.
|
|
115
|
+
# Isotopic source H-H bonds cannot match isotope-zero product dimers.
|
|
116
|
+
product_h2_atoms = set()
|
|
117
|
+
product_h2 = source_h2 = 0
|
|
118
|
+
for bond in mols[1].GetBonds():
|
|
119
|
+
pair = (bond.GetBeginAtom(), bond.GetEndAtom())
|
|
120
|
+
if not all(atom.GetAtomicNum() == 1 for atom in pair):
|
|
121
|
+
continue
|
|
122
|
+
if any(atom.GetIsotope() for atom in pair):
|
|
123
|
+
raise UnsupportedImplicitHydrogen("product_isotopic_hydrogen")
|
|
124
|
+
if _weight2(bond) != 2 or any(
|
|
125
|
+
atom.GetFormalCharge()
|
|
126
|
+
or atom.GetNumRadicalElectrons()
|
|
127
|
+
or atom.GetDegree() != 1
|
|
128
|
+
or _electrons(atom)
|
|
129
|
+
or MolToGraph._non_neighbor_h_count(atom)
|
|
130
|
+
for atom in pair
|
|
131
|
+
):
|
|
132
|
+
raise UnsupportedImplicitHydrogen("product_nonordinary_hydrogen_H2_component")
|
|
133
|
+
product_h2 += 1
|
|
134
|
+
product_h2_atoms.update(atom.GetIdx() for atom in pair)
|
|
135
|
+
if product_h2:
|
|
136
|
+
for bond in mols[0].GetBonds():
|
|
137
|
+
pair = (bond.GetBeginAtom(), bond.GetEndAtom())
|
|
138
|
+
if not all(atom.GetAtomicNum() == 1 for atom in pair):
|
|
139
|
+
continue
|
|
140
|
+
if _weight2(bond) != 2 or any(atom.GetDegree() != 1 for atom in pair):
|
|
141
|
+
raise UnsupportedImplicitHydrogen("source_nonisolated_or_nonunit_HH_for_H2_extension")
|
|
142
|
+
if all(atom.GetIsotope() == 0 for atom in pair):
|
|
143
|
+
if any(atom.GetFormalCharge() or atom.GetNumRadicalElectrons() or _electrons(atom) for atom in pair):
|
|
144
|
+
raise UnsupportedImplicitHydrogen("source_nonordinary_H2_for_product_H2_extension")
|
|
145
|
+
source_h2 += 1
|
|
146
|
+
|
|
147
|
+
offset_hh2 = offset_electrons2 = offset_isotope_edges2 = 0
|
|
148
|
+
source_free0 = source_isotope = source_attached0 = product_free0 = 0
|
|
149
|
+
for side, mol in enumerate(mols):
|
|
150
|
+
for atom in mol.GetAtoms():
|
|
151
|
+
if atom.GetAtomicNum() != 1:
|
|
152
|
+
continue
|
|
153
|
+
if MolToGraph._non_neighbor_h_count(atom):
|
|
154
|
+
raise UnsupportedImplicitHydrogen("non_neighbor_hydrogen_on_hydrogen")
|
|
155
|
+
neighbors = [
|
|
156
|
+
(bond.GetOtherAtom(atom), bond)
|
|
157
|
+
for bond in atom.GetBonds()
|
|
158
|
+
if bond.GetOtherAtom(atom).GetAtomicNum() != 1
|
|
159
|
+
]
|
|
160
|
+
if side == 1:
|
|
161
|
+
if atom.GetIdx() in product_positive_free_ids:
|
|
162
|
+
product_free0 += 1
|
|
163
|
+
continue
|
|
164
|
+
if atom.GetIdx() in product_h2_atoms:
|
|
165
|
+
continue
|
|
166
|
+
if atom.GetIsotope():
|
|
167
|
+
raise UnsupportedImplicitHydrogen("product_isotopic_hydrogen")
|
|
168
|
+
# Isolated isotope-zero product H with zero modeled electron
|
|
169
|
+
# weight is a free reservoir, like a zero-incidence typed H
|
|
170
|
+
# dummy. In particular H+ needs no vertex expansion. Its
|
|
171
|
+
# endpoint charge/state remains in the caller's raw molecule.
|
|
172
|
+
if not atom.GetBonds() and not atom.GetNumRadicalElectrons() and not _electrons(atom):
|
|
173
|
+
product_free0 += 1
|
|
174
|
+
continue
|
|
175
|
+
if (
|
|
176
|
+
atom.GetFormalCharge()
|
|
177
|
+
or atom.GetNumRadicalElectrons()
|
|
178
|
+
or len(atom.GetBonds()) != 1
|
|
179
|
+
or len(neighbors) != 1
|
|
180
|
+
or _weight2(neighbors[0][1]) != 2
|
|
181
|
+
):
|
|
182
|
+
raise UnsupportedImplicitHydrogen("product_nonordinary_hydrogen")
|
|
183
|
+
if _electrons(atom):
|
|
184
|
+
raise UnsupportedImplicitHydrogen("product_nonzero_hydrogen_electrons")
|
|
185
|
+
counts[side][positions[side][neighbors[0][0].GetIdx()]] += 1
|
|
186
|
+
continue
|
|
187
|
+
|
|
188
|
+
# Begin with source H electron loss. When positive-electron
|
|
189
|
+
# product H is supported, subtract the optimal free-H overlap
|
|
190
|
+
# after both endpoints have been counted.
|
|
191
|
+
offset_electrons2 += _electrons(atom)
|
|
192
|
+
if atom.GetIsotope():
|
|
193
|
+
# Product has no real isotope-H: all such source atoms map to
|
|
194
|
+
# typed zero-state dummies. Their heavy edges are all lost.
|
|
195
|
+
source_isotope += 1
|
|
196
|
+
offset_isotope_edges2 += sum(_weight2(bond) for _, bond in neighbors)
|
|
197
|
+
elif not neighbors:
|
|
198
|
+
source_free0 += 1
|
|
199
|
+
elif len(neighbors) == 1 and _weight2(neighbors[0][1]) == 2:
|
|
200
|
+
counts[side][positions[side][neighbors[0][0].GetIdx()]] += 1
|
|
201
|
+
source_attached0 += 1
|
|
202
|
+
else:
|
|
203
|
+
raise UnsupportedImplicitHydrogen("source_nonunit_or_multiple_heavy_hydrogen_incidence")
|
|
204
|
+
if side == 0:
|
|
205
|
+
offset_hh2 = sum(
|
|
206
|
+
_weight2(bond)
|
|
207
|
+
for bond in mol.GetBonds()
|
|
208
|
+
if bond.GetBeginAtom().GetAtomicNum() == bond.GetEndAtom().GetAtomicNum() == 1
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
source_hh2 = offset_hh2
|
|
212
|
+
offset_hh2 += 2 * product_h2 - 4 * min(source_h2, product_h2)
|
|
213
|
+
if sum(counts[1]) + product_free0 + 2 * product_h2 != hydrogen_inventories[1].get(0, 0):
|
|
214
|
+
raise UnsupportedImplicitHydrogen("product_hydrogen_count_model_mismatch")
|
|
215
|
+
inventories = [Counter((atom.GetAtomicNum(), atom.GetIsotope()) for atom in atoms) for atoms in heavy]
|
|
216
|
+
if balance == "strict" and (inventories[0] != inventories[1] or hydrogen_inventories[0] != hydrogen_inventories[1]):
|
|
217
|
+
raise ValueError("Unbalanced atom inventories; select balance='dummy' explicitly")
|
|
218
|
+
universe = inventories[0] | inventories[1]
|
|
219
|
+
graphs = []
|
|
220
|
+
for side, atoms in enumerate(heavy):
|
|
221
|
+
missing = sorted((universe - inventories[side]).elements())
|
|
222
|
+
labels = [(atom.GetAtomicNum(), atom.GetIsotope()) for atom in atoms] + missing
|
|
223
|
+
hcounts = counts[side] + [0] * len(missing)
|
|
224
|
+
electrons = [_electrons(atom) for atom in atoms] + [0] * len(missing)
|
|
225
|
+
n = len(labels)
|
|
226
|
+
adjacency = {i: {} for i in range(n + 2)}
|
|
227
|
+
for bond in mols[side].GetBonds():
|
|
228
|
+
left, right = bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()
|
|
229
|
+
if left in positions[side] and right in positions[side]:
|
|
230
|
+
i, j = positions[side][left], positions[side][right]
|
|
231
|
+
adjacency[i][j] = adjacency[j][i] = _weight2(bond) / 2
|
|
232
|
+
for i, (hydrogen, electron) in enumerate(zip(hcounts, electrons)):
|
|
233
|
+
if hydrogen:
|
|
234
|
+
adjacency[i][n + 1] = adjacency[n + 1][i] = hydrogen
|
|
235
|
+
if electron:
|
|
236
|
+
adjacency[i][n] = adjacency[n][i] = electron / 2
|
|
237
|
+
graph = LabeledGraph(adjacency, labels + [(0, -1), (0, -2)])
|
|
238
|
+
graph.props["hcounts"] = hcounts + [0, 0]
|
|
239
|
+
graph.props["electrons"] = electrons + [0, 0]
|
|
240
|
+
graphs.append(graph)
|
|
241
|
+
|
|
242
|
+
offset_electrons2 += sum(product_free_electrons) - 2 * preserved_free_electrons
|
|
243
|
+
offset2 = offset_hh2 + offset_electrons2 + offset_isotope_edges2
|
|
244
|
+
metadata = {
|
|
245
|
+
"model": (
|
|
246
|
+
"full_lewis_pmcd_source_H_constant_and_product_H_counts_with_free_zero_electron_reservoir"
|
|
247
|
+
if product_free0
|
|
248
|
+
else "full_lewis_pmcd_source_H_constant_and_ordinary_product_H_counts"
|
|
249
|
+
),
|
|
250
|
+
"objective": "normalized_full_lewis_distance",
|
|
251
|
+
"balance": balance,
|
|
252
|
+
"references_used": False,
|
|
253
|
+
"offset_units": "doubled_chemical_distance",
|
|
254
|
+
"offset2": offset2,
|
|
255
|
+
"offset_HH2": offset_hh2,
|
|
256
|
+
"offset_H_electrons2": offset_electrons2,
|
|
257
|
+
"offset_isotope_H_heavy2": offset_isotope_edges2,
|
|
258
|
+
"heavy_atoms_r": len(heavy[0]),
|
|
259
|
+
"heavy_atoms_p": len(heavy[1]),
|
|
260
|
+
"heavy_original_indices_r": [atom.GetIdx() for atom in heavy[0]],
|
|
261
|
+
"heavy_original_indices_p": [atom.GetIdx() for atom in heavy[1]],
|
|
262
|
+
"hydrogens_r": sum(hydrogen_inventories[0].values()),
|
|
263
|
+
"hydrogens_p": sum(hydrogen_inventories[1].values()),
|
|
264
|
+
"source_explicit_isotope0_attached": source_attached0,
|
|
265
|
+
"source_explicit_isotope0_zero_heavy_incidence": source_free0,
|
|
266
|
+
"source_explicit_isotopic_H": source_isotope,
|
|
267
|
+
"product_explicit_isotope0_zero_heavy_incidence": product_free0,
|
|
268
|
+
"product_H_ordinary": product_free0 == 0,
|
|
269
|
+
"product_H_supported_domain": ("ordinary_terminal_or_isolated_zero_electron_isotope0"),
|
|
270
|
+
"search_atoms": len(graphs[0].labels),
|
|
271
|
+
"hydrogen_nodes_added": 0,
|
|
272
|
+
"hydrogen_vertices_searched": 0,
|
|
273
|
+
"scope": "numeric_PMCD_proof_only_no_H_or_class_enumeration",
|
|
274
|
+
}
|
|
275
|
+
if product_h2:
|
|
276
|
+
metadata.update(
|
|
277
|
+
model="full_lewis_pmcd_attached_H_counts_and_isolated_ordinary_H2_v1",
|
|
278
|
+
product_H_supported_domain="ordinary_terminal_or_isolated_zero_electron_isotope0_or_ordinary_H2",
|
|
279
|
+
product_H_ordinary=False,
|
|
280
|
+
product_explicit_isotope0_zero_heavy_incidence=product_free0 + 2 * product_h2,
|
|
281
|
+
product_isolated_zero_electron_reservoir=product_free0,
|
|
282
|
+
product_H2_molecules=product_h2,
|
|
283
|
+
source_ordinary_H2_molecules=source_h2,
|
|
284
|
+
source_HH_bond_weight2=source_hh2,
|
|
285
|
+
preserved_H2_bonds=min(source_h2, product_h2),
|
|
286
|
+
H2_reduction="disjoint_attached_H_and_ordinary_H2_matching_v1",
|
|
287
|
+
)
|
|
288
|
+
if product_free_electrons:
|
|
289
|
+
metadata.update(
|
|
290
|
+
model="full_lewis_pmcd_free_H_electron_reservoir_with_attached_H_and_H2_v1",
|
|
291
|
+
product_H_supported_domain=metadata["product_H_supported_domain"] + "_or_free_positive_electron_isotope0_H",
|
|
292
|
+
product_H_ordinary=False,
|
|
293
|
+
source_free_H_electrons=source_free_electrons,
|
|
294
|
+
product_free_H_electrons=product_free_electrons,
|
|
295
|
+
preserved_free_H_electron_overlap=preserved_free_electrons,
|
|
296
|
+
product_isolated_zero_electron_reservoir=product_free0 - len(product_free_electrons),
|
|
297
|
+
free_H_electron_reduction="descending_positive_free_H_electron_matching_v1",
|
|
298
|
+
)
|
|
299
|
+
return tuple(graphs), offset2, metadata
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
# The experiment API retains the same callable and exception identities.
|
|
303
|
+
prepare_implicit_pmcd = prepare_implicit_problem
|
|
304
|
+
|
|
305
|
+
__all__ = [
|
|
306
|
+
"UnsupportedImplicitHydrogen",
|
|
307
|
+
"prepare_implicit_pmcd",
|
|
308
|
+
"prepare_implicit_problem",
|
|
309
|
+
]
|
|
Binary file
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Weighted common-edge overlap mapping through a native association graph."""
|
|
2
|
+
|
|
3
|
+
from .core import enumerate_core_mappings, map_reaction_core
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def enumerate_mces_mappings(lgp, *, library_path, **options):
|
|
7
|
+
"""Enumerate full-bijection minimum/exact/at-most weighted Lewis mappings."""
|
|
8
|
+
return enumerate_core_mappings(
|
|
9
|
+
lgp, library_path=library_path, backend="mces", **options
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def map_reaction_mces(reaction, *, library_path, **options):
|
|
14
|
+
return map_reaction_core(
|
|
15
|
+
reaction, library_path=library_path, backend="mces", **options
|
|
16
|
+
)
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"""Thin bindings for the complete optional RDKit C++ reaction pipeline."""
|
|
2
|
+
|
|
3
|
+
import ctypes as ct
|
|
4
|
+
import json
|
|
5
|
+
import math
|
|
6
|
+
from functools import lru_cache
|
|
7
|
+
from numbers import Integral
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from ..exact.distance_search.records import normalize_distance_target
|
|
11
|
+
from .runtime import BACKENDS, Request
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class _Options(ct.Structure):
|
|
15
|
+
_fields_ = [
|
|
16
|
+
(name, ct.c_int32)
|
|
17
|
+
for name in (
|
|
18
|
+
"abi_version",
|
|
19
|
+
"explicit_hydrogens",
|
|
20
|
+
"lewis_objective",
|
|
21
|
+
"dummy_balance",
|
|
22
|
+
"binary",
|
|
23
|
+
"hydrogen_quotient",
|
|
24
|
+
"empty_numeric_shell",
|
|
25
|
+
)
|
|
26
|
+
] + [("max_canonical_nodes", ct.c_int64), ("max_hydrogen_plans", ct.c_int64)]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@lru_cache(maxsize=8)
|
|
30
|
+
def _load(path):
|
|
31
|
+
library = ct.CDLL(str(Path(path).resolve()))
|
|
32
|
+
if library.synkit_mapper_reaction_abi() != 1:
|
|
33
|
+
raise RuntimeError("Unsupported native reaction ABI")
|
|
34
|
+
library.synkit_mapper_reaction_error.restype = ct.c_char_p
|
|
35
|
+
library.synkit_mapper_rdkit_version.restype = ct.c_char_p
|
|
36
|
+
library.synkit_mapper_reaction_solve.argtypes = [
|
|
37
|
+
ct.c_char_p,
|
|
38
|
+
ct.POINTER(_Options),
|
|
39
|
+
ct.POINTER(Request),
|
|
40
|
+
ct.POINTER(ct.c_void_p),
|
|
41
|
+
]
|
|
42
|
+
library.synkit_mapper_reaction_free.argtypes = [ct.c_void_p]
|
|
43
|
+
return library
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _cap(value, name):
|
|
47
|
+
if value is None:
|
|
48
|
+
return -1
|
|
49
|
+
if (
|
|
50
|
+
isinstance(value, bool)
|
|
51
|
+
or not isinstance(value, Integral)
|
|
52
|
+
or not 0 < value < 2**63
|
|
53
|
+
):
|
|
54
|
+
raise ValueError(f"{name} must be a positive int64 or None")
|
|
55
|
+
return int(value)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# ABI option checks and hydrogen fallback share the native reaction deadline.
|
|
59
|
+
def map_reaction_native( # noqa: C901
|
|
60
|
+
reaction,
|
|
61
|
+
*,
|
|
62
|
+
library_path,
|
|
63
|
+
backend="pabs",
|
|
64
|
+
CD="minimal",
|
|
65
|
+
CD_mode="exact",
|
|
66
|
+
objective="lewis",
|
|
67
|
+
hydrogen=None,
|
|
68
|
+
balance="strict",
|
|
69
|
+
binary=False,
|
|
70
|
+
hydrogen_quotient=False,
|
|
71
|
+
time_limit_seconds=10,
|
|
72
|
+
max_mappings=100000,
|
|
73
|
+
max_classes=None,
|
|
74
|
+
max_states=None,
|
|
75
|
+
max_frontier=None,
|
|
76
|
+
memory_limit_bytes=None,
|
|
77
|
+
classification_max_search_nodes=100000,
|
|
78
|
+
max_hydrogen_plans=10000,
|
|
79
|
+
proof_only=False,
|
|
80
|
+
cancel_token=None,
|
|
81
|
+
):
|
|
82
|
+
"""Return native JSON records after C++ parsing, search and mapped rendering.
|
|
83
|
+
|
|
84
|
+
This adapter imports no Python RDKit chemistry functions. It loads the
|
|
85
|
+
explicitly built reaction library, converts options and decodes its JSON.
|
|
86
|
+
Unsupported H quotient states fall back to full explicit native search on
|
|
87
|
+
the remaining shared budget; the result records that fallback and its reason.
|
|
88
|
+
"""
|
|
89
|
+
if not isinstance(reaction, str):
|
|
90
|
+
raise TypeError("reaction must be reaction SMILES")
|
|
91
|
+
if "\x00" in reaction:
|
|
92
|
+
raise ValueError("reaction cannot contain a NUL character")
|
|
93
|
+
if backend not in BACKENDS:
|
|
94
|
+
raise ValueError(f"Unknown native backend: {backend}")
|
|
95
|
+
if objective not in {"lewis", "bond"} or balance not in {"strict", "dummy"}:
|
|
96
|
+
raise ValueError("objective must be lewis/bond and balance strict/dummy")
|
|
97
|
+
hydrogen = hydrogen or ("explicit" if objective == "lewis" else "heavy")
|
|
98
|
+
if hydrogen not in {"explicit", "heavy"}:
|
|
99
|
+
raise ValueError(
|
|
100
|
+
"Native reaction frontend requires explicit or heavy hydrogens"
|
|
101
|
+
)
|
|
102
|
+
for name, flag in (
|
|
103
|
+
("binary", binary),
|
|
104
|
+
("hydrogen_quotient", hydrogen_quotient),
|
|
105
|
+
("proof_only", proof_only),
|
|
106
|
+
):
|
|
107
|
+
if not isinstance(flag, bool):
|
|
108
|
+
raise TypeError(f"{name} must be boolean")
|
|
109
|
+
if objective == "lewis" and (hydrogen != "explicit" or binary):
|
|
110
|
+
raise ValueError("Lewis objective requires explicit H and weighted bonds")
|
|
111
|
+
if time_limit_seconds is not None and (
|
|
112
|
+
isinstance(time_limit_seconds, bool)
|
|
113
|
+
or not isinstance(time_limit_seconds, (int, float))
|
|
114
|
+
or not math.isfinite(time_limit_seconds)
|
|
115
|
+
or time_limit_seconds < 0
|
|
116
|
+
):
|
|
117
|
+
raise ValueError("time_limit_seconds must be finite and nonnegative or None")
|
|
118
|
+
target = normalize_distance_target(CD)
|
|
119
|
+
if CD_mode not in {"exact", "at_most"} or (
|
|
120
|
+
CD_mode == "at_most" and target == "minimal"
|
|
121
|
+
):
|
|
122
|
+
raise ValueError("at_most requires numeric CD; otherwise use exact")
|
|
123
|
+
if proof_only and target != "minimal":
|
|
124
|
+
raise ValueError("proof_only requires minimal CD")
|
|
125
|
+
query = (
|
|
126
|
+
3
|
|
127
|
+
if proof_only
|
|
128
|
+
else 0
|
|
129
|
+
if target == "minimal"
|
|
130
|
+
else 2
|
|
131
|
+
if CD_mode == "at_most"
|
|
132
|
+
else 1
|
|
133
|
+
)
|
|
134
|
+
empty = False
|
|
135
|
+
target2 = 0
|
|
136
|
+
if target != "minimal":
|
|
137
|
+
scaled = min(target * 2, 2**62)
|
|
138
|
+
target2 = math.floor(scaled + 1e-9) if query == 2 else round(scaled)
|
|
139
|
+
empty = query == 1 and abs(target - target2 / 2) > 1e-9
|
|
140
|
+
request = Request()
|
|
141
|
+
request.abi_version = 1
|
|
142
|
+
request.backend = BACKENDS[backend]
|
|
143
|
+
request.query = query
|
|
144
|
+
request.symmetry = int(backend in {"pabs", "cpabs"})
|
|
145
|
+
request.workers = 1
|
|
146
|
+
request.target2 = target2
|
|
147
|
+
request.seconds = -1 if time_limit_seconds is None else time_limit_seconds
|
|
148
|
+
request.slap_max_fingerprints = 10000
|
|
149
|
+
for name, value in (
|
|
150
|
+
("max_states", max_states),
|
|
151
|
+
("max_candidates", max_mappings),
|
|
152
|
+
("max_classes", max_classes),
|
|
153
|
+
("max_frontier", max_frontier),
|
|
154
|
+
("memory_limit_bytes", memory_limit_bytes),
|
|
155
|
+
):
|
|
156
|
+
setattr(request, name, _cap(value, name))
|
|
157
|
+
request.cancel_token = None if cancel_token is None else cancel_token.pointer
|
|
158
|
+
options = _Options(
|
|
159
|
+
1,
|
|
160
|
+
hydrogen == "explicit",
|
|
161
|
+
objective == "lewis",
|
|
162
|
+
balance == "dummy",
|
|
163
|
+
binary,
|
|
164
|
+
hydrogen_quotient,
|
|
165
|
+
empty,
|
|
166
|
+
_cap(classification_max_search_nodes, "classification_max_search_nodes"),
|
|
167
|
+
_cap(max_hydrogen_plans, "max_hydrogen_plans"),
|
|
168
|
+
)
|
|
169
|
+
library = _load(str(library_path))
|
|
170
|
+
output = ct.c_void_p()
|
|
171
|
+
result = library.synkit_mapper_reaction_solve(
|
|
172
|
+
reaction.encode(), ct.byref(options), ct.byref(request), ct.byref(output)
|
|
173
|
+
)
|
|
174
|
+
if result:
|
|
175
|
+
raise ValueError(library.synkit_mapper_reaction_error().decode())
|
|
176
|
+
try:
|
|
177
|
+
return json.loads(ct.string_at(output))
|
|
178
|
+
finally:
|
|
179
|
+
library.synkit_mapper_reaction_free(output)
|