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,203 @@
|
|
|
1
|
+
"""Prove normalized full Lewis PMCD without adding or enumerating H atoms.
|
|
2
|
+
|
|
3
|
+
Ordinary terminal H is represented by counts on heavy atoms. For a proposed
|
|
4
|
+
heavy bijection f its exact minimum H cost is sum_i |h_R[i]-h_P[f(i)]|, also
|
|
5
|
+
with unequal H inventories under zero-state dummy padding. This term enters
|
|
6
|
+
the native objective before optimization. No H graph, transport enumeration,
|
|
7
|
+
ITS classification or mapped-reaction rendering is performed.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from collections import Counter
|
|
13
|
+
from dataclasses import asdict, dataclass
|
|
14
|
+
import math
|
|
15
|
+
from numbers import Real
|
|
16
|
+
import time
|
|
17
|
+
|
|
18
|
+
from rdkit import Chem
|
|
19
|
+
|
|
20
|
+
from synkit.IO.mol_to_graph import MolToGraph
|
|
21
|
+
from ....graph.labeled_graph import LabeledGraph
|
|
22
|
+
from ...slap.lap import _adjacency_and_elements, chemical_distance
|
|
23
|
+
from .candidates import minimize_native_candidates, prepare_native_candidates
|
|
24
|
+
from .search import _profile_seed
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class _UnsupportedHydrogen(ValueError):
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True)
|
|
32
|
+
class PMCDProofResult:
|
|
33
|
+
"""An optimum proof, separate from complete mapping-class enumeration.
|
|
34
|
+
|
|
35
|
+
heavy_mapping uses the padded heavy-atom order (real atoms, then dummies).
|
|
36
|
+
minimum_cost is set only after a completed proof. The feasible incumbent
|
|
37
|
+
can remain available if the proof is interrupted. Unsupported H states
|
|
38
|
+
are explicit and never silently drop out of the objective.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
minimum_cost: float | None
|
|
42
|
+
incumbent_cost: float | None
|
|
43
|
+
optimality_proven: bool
|
|
44
|
+
status: str
|
|
45
|
+
reason: str | None
|
|
46
|
+
heavy_mapping: tuple[int, ...] | None
|
|
47
|
+
heavy_atom_counts: tuple[int, int] | None
|
|
48
|
+
hydrogen_counts: tuple[int, int] | None
|
|
49
|
+
search_atoms: int
|
|
50
|
+
visited_nodes: int
|
|
51
|
+
elapsed_seconds: float
|
|
52
|
+
search_result: dict | None = None
|
|
53
|
+
objective: str = "normalized_full_lewis_distance"
|
|
54
|
+
hydrogen_nodes_added: int = 0
|
|
55
|
+
hydrogen_vertices_searched: int = 0
|
|
56
|
+
enumeration_complete: bool = False
|
|
57
|
+
|
|
58
|
+
def as_dict(self):
|
|
59
|
+
return asdict(self)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# Keep hydrogen eligibility, balancing and anchor construction in one reduction.
|
|
63
|
+
def _implicit_quotient_graphs(reaction, balance): # noqa: C901
|
|
64
|
+
"""Read endpoint H counts and electron states without Chem.AddHs."""
|
|
65
|
+
if not isinstance(reaction, str):
|
|
66
|
+
raise TypeError("reaction must be reaction SMILES")
|
|
67
|
+
parts = reaction.split(">")
|
|
68
|
+
if len(parts) != 3 or not parts[0] or not parts[2]:
|
|
69
|
+
raise ValueError("Expected reactants>agents>products or reactants>>products")
|
|
70
|
+
endpoints = []
|
|
71
|
+
for side in (parts[0], parts[2]):
|
|
72
|
+
params = Chem.SmilesParserParams()
|
|
73
|
+
params.removeHs = False
|
|
74
|
+
mol = Chem.MolFromSmiles(side, params)
|
|
75
|
+
if mol is None:
|
|
76
|
+
raise ValueError("Could not parse reaction endpoint")
|
|
77
|
+
heavy = []
|
|
78
|
+
for atom in mol.GetAtoms():
|
|
79
|
+
atom.SetAtomMapNum(0)
|
|
80
|
+
if atom.GetAtomicNum() == 0:
|
|
81
|
+
raise ValueError("Wildcard atoms require a concrete element")
|
|
82
|
+
if atom.GetAtomicNum() != 1:
|
|
83
|
+
heavy.append(atom)
|
|
84
|
+
continue
|
|
85
|
+
if atom.GetIsotope():
|
|
86
|
+
raise _UnsupportedHydrogen("isotopic_hydrogen")
|
|
87
|
+
if atom.GetFormalCharge() or atom.GetNumRadicalElectrons():
|
|
88
|
+
raise _UnsupportedHydrogen("nonneutral_or_radical_hydrogen")
|
|
89
|
+
bonds = list(atom.GetBonds())
|
|
90
|
+
if (len(bonds) != 1 or bonds[0].GetBondTypeAsDouble() != 1
|
|
91
|
+
or bonds[0].GetOtherAtom(atom).GetAtomicNum() <= 1):
|
|
92
|
+
raise _UnsupportedHydrogen("nonordinary_terminal_hydrogen")
|
|
93
|
+
labels = [(atom.GetAtomicNum(), atom.GetIsotope()) for atom in heavy]
|
|
94
|
+
hcounts = [MolToGraph._total_h_count(atom) for atom in heavy]
|
|
95
|
+
electrons = [2 * MolToGraph.estimate_lone_pairs(atom)
|
|
96
|
+
+ atom.GetNumRadicalElectrons() for atom in heavy]
|
|
97
|
+
endpoints.append((mol, heavy, labels, hcounts, electrons))
|
|
98
|
+
inventories = [Counter(value[2]) for value in endpoints]
|
|
99
|
+
totals = tuple(sum(value[3]) for value in endpoints)
|
|
100
|
+
if balance == "strict" and (inventories[0] != inventories[1] or totals[0] != totals[1]):
|
|
101
|
+
raise ValueError("Unbalanced atom inventories; select balance='dummy' explicitly")
|
|
102
|
+
universe = inventories[0] | inventories[1]
|
|
103
|
+
graphs = []
|
|
104
|
+
for (mol, heavy, labels, hcounts, electrons), inventory in zip(endpoints, inventories):
|
|
105
|
+
positions = {atom.GetIdx(): i for i, atom in enumerate(heavy)}
|
|
106
|
+
missing = sorted((universe - inventory).elements())
|
|
107
|
+
labels = labels + missing
|
|
108
|
+
hcounts = hcounts + [0] * len(missing)
|
|
109
|
+
electrons = electrons + [0] * len(missing)
|
|
110
|
+
size = len(labels)
|
|
111
|
+
adjacency = {i: {} for i in range(size + 2)}
|
|
112
|
+
for bond in mol.GetBonds():
|
|
113
|
+
i, j = bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()
|
|
114
|
+
if i in positions and j in positions:
|
|
115
|
+
x, y = positions[i], positions[j]
|
|
116
|
+
adjacency[x][y] = adjacency[y][x] = bond.GetBondTypeAsDouble()
|
|
117
|
+
# Separate forced anchors encode the electron and minimum-H unary terms.
|
|
118
|
+
for i, (count, electron) in enumerate(zip(hcounts, electrons)):
|
|
119
|
+
if electron:
|
|
120
|
+
adjacency[i][size] = adjacency[size][i] = electron / 2
|
|
121
|
+
if count:
|
|
122
|
+
adjacency[i][size + 1] = adjacency[size + 1][i] = count
|
|
123
|
+
graph = LabeledGraph(adjacency, labels + [(0, -1), (0, -2)])
|
|
124
|
+
graph.props["hcounts"] = hcounts + [0, 0]
|
|
125
|
+
graph.props["electrons"] = electrons + [0, 0]
|
|
126
|
+
graphs.append(graph)
|
|
127
|
+
return tuple(graphs), tuple(len(value[1]) for value in endpoints), totals
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def prove_reaction_pmcd(
|
|
131
|
+
reaction,
|
|
132
|
+
*,
|
|
133
|
+
library_path,
|
|
134
|
+
balance="strict",
|
|
135
|
+
time_limit_seconds=10.0,
|
|
136
|
+
symmetry=True,
|
|
137
|
+
):
|
|
138
|
+
"""Prove full Lewis PMCD using only heavy vertices and H counts.
|
|
139
|
+
|
|
140
|
+
Supported H atoms are neutral, nonradical, nonisotopic terminal single-bond
|
|
141
|
+
H. Other H states return status='unsupported' without expanding anything.
|
|
142
|
+
Stereo does not need expansion for the existing numerical CD objective:
|
|
143
|
+
it remains an output-class distinction, and this API returns no classes.
|
|
144
|
+
The ordinary map_reaction/Mapper minimum query still enumerates all minima.
|
|
145
|
+
"""
|
|
146
|
+
started = time.perf_counter()
|
|
147
|
+
if balance not in {"strict", "dummy"}:
|
|
148
|
+
raise ValueError("balance must be 'strict' or 'dummy'")
|
|
149
|
+
if not isinstance(symmetry, bool):
|
|
150
|
+
raise TypeError("symmetry must be boolean")
|
|
151
|
+
if time_limit_seconds is not None and (
|
|
152
|
+
isinstance(time_limit_seconds, bool) or not isinstance(time_limit_seconds, Real)
|
|
153
|
+
or not math.isfinite(time_limit_seconds) or time_limit_seconds < 0
|
|
154
|
+
):
|
|
155
|
+
raise ValueError("time limit must be finite and nonnegative")
|
|
156
|
+
deadline = None if time_limit_seconds is None else started + time_limit_seconds
|
|
157
|
+
|
|
158
|
+
def outcome(record=None, *, reason=None, status=None, graphs=(), heavy=None, hydrogens=None):
|
|
159
|
+
proven = record is not None and record["complete"]
|
|
160
|
+
mapping = tuple(record["mapping"][:-2]) if record else None
|
|
161
|
+
return PMCDProofResult(
|
|
162
|
+
minimum_cost=record["minimum_cost"] if proven else None,
|
|
163
|
+
incumbent_cost=record["incumbent_cost"] if record else None,
|
|
164
|
+
optimality_proven=proven,
|
|
165
|
+
status=status or ("proven" if proven else "time_limit"),
|
|
166
|
+
reason=reason if reason is not None else record["reason"] if record else None,
|
|
167
|
+
heavy_mapping=mapping, heavy_atom_counts=heavy, hydrogen_counts=hydrogens,
|
|
168
|
+
search_atoms=len(graphs[0].labels) if graphs else 0,
|
|
169
|
+
visited_nodes=record["visited_nodes"] if record else 0,
|
|
170
|
+
elapsed_seconds=time.perf_counter() - started, search_result=record,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
graphs, heavy, hydrogens = _implicit_quotient_graphs(reaction, balance)
|
|
175
|
+
except _UnsupportedHydrogen as error:
|
|
176
|
+
return outcome(status="unsupported", reason=str(error))
|
|
177
|
+
if len(graphs[0].labels) > 256:
|
|
178
|
+
return outcome(status="unsupported", reason="native_node_limit", graphs=graphs,
|
|
179
|
+
heavy=heavy, hydrogens=hydrogens)
|
|
180
|
+
if deadline is not None and time.perf_counter() >= deadline:
|
|
181
|
+
return outcome(status="time_limit", reason="time_limit", graphs=graphs,
|
|
182
|
+
heavy=heavy, hydrogens=hydrogens)
|
|
183
|
+
a, labels = _adjacency_and_elements(graphs[0], False)
|
|
184
|
+
b, product_labels = _adjacency_and_elements(graphs[1], False)
|
|
185
|
+
if len(set(a.ravel()) | set(b.ravel())) > 16:
|
|
186
|
+
return outcome(status="unsupported", reason="native_bond_level_limit", graphs=graphs,
|
|
187
|
+
heavy=heavy, hydrogens=hydrogens)
|
|
188
|
+
seed = _profile_seed(a, b, labels, product_labels)
|
|
189
|
+
prepared = prepare_native_candidates(
|
|
190
|
+
graphs, 0, library_path=library_path, initial_mapping=seed,
|
|
191
|
+
binary=False, symmetry=symmetry, node_properties=(), allow_partial_symmetry=True,
|
|
192
|
+
)
|
|
193
|
+
seconds = 1e100 if deadline is None else max(0, deadline - time.perf_counter())
|
|
194
|
+
record = minimize_native_candidates(
|
|
195
|
+
graphs, library_path=library_path, initial_mapping=seed,
|
|
196
|
+
time_limit_seconds=seconds, _prepared=prepared,
|
|
197
|
+
)
|
|
198
|
+
if chemical_distance(graphs, record["mapping"], False) != record["incumbent_cost"]:
|
|
199
|
+
raise RuntimeError("Native proof witness does not match its reduced Lewis cost")
|
|
200
|
+
return outcome(record, graphs=graphs, heavy=heavy, hydrogens=hydrogens)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
__all__ = ["PMCDProofResult", "prove_reaction_pmcd"]
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Optional operating-system controls for native mapper workers."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
WORKER_ADDRESS_SPACE_BYTES = 4 * 1024**3
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def limit_worker_address_space(resource):
|
|
9
|
+
"""Lower supported soft limits, preserving inherited soft and hard ceilings."""
|
|
10
|
+
if resource is None or not hasattr(resource, "RLIMIT_AS"):
|
|
11
|
+
return None
|
|
12
|
+
try:
|
|
13
|
+
soft, hard = resource.getrlimit(resource.RLIMIT_AS)
|
|
14
|
+
ceilings = [value for value in (soft, hard) if value != resource.RLIM_INFINITY]
|
|
15
|
+
limit = min([WORKER_ADDRESS_SPACE_BYTES, *ceilings])
|
|
16
|
+
resource.setrlimit(resource.RLIMIT_AS, (limit, hard))
|
|
17
|
+
return limit
|
|
18
|
+
except (OSError, ValueError):
|
|
19
|
+
# Some macOS kernels expose RLIMIT_AS but reject setting this limit.
|
|
20
|
+
# This optional control must not prevent worker startup and barriers.
|
|
21
|
+
return None
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def worker_cpus(workers):
|
|
25
|
+
"""Return available CPU IDs to pin, or an empty list when unsupported."""
|
|
26
|
+
if not hasattr(os, "sched_getaffinity") or not hasattr(os, "sched_setaffinity"):
|
|
27
|
+
return []
|
|
28
|
+
try:
|
|
29
|
+
return sorted(os.sched_getaffinity(0))[:workers]
|
|
30
|
+
except OSError:
|
|
31
|
+
return []
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def pin_worker_cpu(cpu):
|
|
35
|
+
"""Apply optional CPU pinning without making an OS tuning failure fatal."""
|
|
36
|
+
if cpu is not None and hasattr(os, "sched_setaffinity"):
|
|
37
|
+
try:
|
|
38
|
+
os.sched_setaffinity(0, {cpu})
|
|
39
|
+
except OSError:
|
|
40
|
+
pass
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
"""Full-space minimum and distance-range adapters for optional C++ search."""
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
import time
|
|
5
|
+
from collections import Counter
|
|
6
|
+
from functools import partial
|
|
7
|
+
from numbers import Integral, Real
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
from scipy.optimize import linear_sum_assignment
|
|
11
|
+
|
|
12
|
+
from ...slap.lap import _adjacency_and_elements
|
|
13
|
+
from ..distance_search.bounds import atom_profile_costs
|
|
14
|
+
from ..distance_search.records import (
|
|
15
|
+
DistanceEnumerationResult,
|
|
16
|
+
ExactEnumerationLimitError,
|
|
17
|
+
normalize_distance_target,
|
|
18
|
+
)
|
|
19
|
+
from ..pabs.cost_lattice import CostLattice
|
|
20
|
+
from .candidates import (
|
|
21
|
+
enumerate_native_range,
|
|
22
|
+
minimize_native_candidates,
|
|
23
|
+
prepare_native_candidates,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _profile_seed(a, b, labels, product_labels):
|
|
28
|
+
"""Choose a compatible feasible incumbent; its cost is verified in C++."""
|
|
29
|
+
profiles = atom_profile_costs(a, b, labels, product_labels)
|
|
30
|
+
mapping = [-1] * len(labels)
|
|
31
|
+
for element in dict.fromkeys(labels):
|
|
32
|
+
rows = [i for i, value in enumerate(labels) if value == element]
|
|
33
|
+
columns = [i for i, value in enumerate(product_labels) if value == element]
|
|
34
|
+
left, right = linear_sum_assignment(profiles[np.ix_(rows, columns)])
|
|
35
|
+
for i, j in zip(left, right):
|
|
36
|
+
mapping[rows[i]] = columns[j]
|
|
37
|
+
return mapping
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def enumerate_cpp_mappings( # noqa: C901
|
|
41
|
+
lgp,
|
|
42
|
+
*,
|
|
43
|
+
library_path,
|
|
44
|
+
CD="minimal",
|
|
45
|
+
CD_mode="exact",
|
|
46
|
+
binary=True,
|
|
47
|
+
initial_mapping=None,
|
|
48
|
+
max_bijections=1_000_000,
|
|
49
|
+
max_mappings=None,
|
|
50
|
+
time_limit_seconds=None,
|
|
51
|
+
collect_mappings=True,
|
|
52
|
+
mapping_callback=None,
|
|
53
|
+
compute_minimum_cost=True,
|
|
54
|
+
tolerance=1e-9,
|
|
55
|
+
symmetry=False,
|
|
56
|
+
node_properties=(),
|
|
57
|
+
separator_config=None,
|
|
58
|
+
):
|
|
59
|
+
"""Prove PMCD and enumerate its full shell, or enumerate a supplied CD.
|
|
60
|
+
|
|
61
|
+
A numeric query defaults to CD_mode='exact'. 'at_most' instead selects
|
|
62
|
+
every distance at or below CD in one traversal. Returned distances and
|
|
63
|
+
callbacks carry each mapping's actual cost.
|
|
64
|
+
|
|
65
|
+
The default preserves every compatible labeled mapping. symmetry=True uses
|
|
66
|
+
verified side automorphisms preserving node_properties; partial subgroup
|
|
67
|
+
discovery only weakens pruning. Chemical frontends still perform exact ITS
|
|
68
|
+
classification and report representative counts separately from labeled
|
|
69
|
+
counts. Requires 1..256 atoms, symmetric loop-free half-integer weights and
|
|
70
|
+
at most 16 bond levels. Compilation remains explicit.
|
|
71
|
+
|
|
72
|
+
Minimum proof and complete enumeration are independent passes sharing one
|
|
73
|
+
deadline. An interrupted proof never publishes its incumbent as PMCD.
|
|
74
|
+
``separator_config`` explicitly enables an experimental bounded residual
|
|
75
|
+
oracle, with ``residual_limit`` (0..12) and ``max_states`` per call. Unknown
|
|
76
|
+
oracle results retain ordinary search. The default leaves it disabled.
|
|
77
|
+
"""
|
|
78
|
+
started = time.perf_counter()
|
|
79
|
+
target = normalize_distance_target(CD)
|
|
80
|
+
minimum_function = minimize_native_candidates
|
|
81
|
+
range_function = enumerate_native_range
|
|
82
|
+
separator_options = separator_statistics = None
|
|
83
|
+
if separator_config is not None:
|
|
84
|
+
from .separator import (
|
|
85
|
+
_normalize_separator_config,
|
|
86
|
+
enumerate_native_range_separator,
|
|
87
|
+
minimize_native_candidates_separator,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
separator_options = _normalize_separator_config(separator_config)
|
|
91
|
+
minimum_function = partial(minimize_native_candidates_separator, **separator_options)
|
|
92
|
+
range_function = partial(enumerate_native_range_separator, **separator_options)
|
|
93
|
+
separator_statistics = dict.fromkeys(("calls", "known", "pruned", "states"), 0)
|
|
94
|
+
if CD_mode not in {"exact", "at_most"}:
|
|
95
|
+
raise ValueError("CD_mode must be 'exact' or 'at_most'")
|
|
96
|
+
if target == "minimal" and CD_mode != "exact":
|
|
97
|
+
raise ValueError("CD_mode='at_most' requires numeric CD")
|
|
98
|
+
for name, value in (
|
|
99
|
+
("binary", binary),
|
|
100
|
+
("collect_mappings", collect_mappings),
|
|
101
|
+
("compute_minimum_cost", compute_minimum_cost),
|
|
102
|
+
("symmetry", symmetry),
|
|
103
|
+
):
|
|
104
|
+
if not isinstance(value, bool):
|
|
105
|
+
raise TypeError(f"{name} must be boolean")
|
|
106
|
+
for name, value in (
|
|
107
|
+
("max_bijections", max_bijections),
|
|
108
|
+
("max_mappings", max_mappings),
|
|
109
|
+
):
|
|
110
|
+
if value is not None and (
|
|
111
|
+
isinstance(value, bool) or not isinstance(value, Integral) or value < 1
|
|
112
|
+
):
|
|
113
|
+
raise ValueError(f"{name} must be a positive integer or None")
|
|
114
|
+
if time_limit_seconds is not None and (
|
|
115
|
+
isinstance(time_limit_seconds, bool)
|
|
116
|
+
or not isinstance(time_limit_seconds, Real)
|
|
117
|
+
or not math.isfinite(time_limit_seconds)
|
|
118
|
+
or time_limit_seconds < 0
|
|
119
|
+
):
|
|
120
|
+
raise ValueError("time_limit_seconds must be finite and non-negative")
|
|
121
|
+
if (
|
|
122
|
+
isinstance(tolerance, bool)
|
|
123
|
+
or not isinstance(tolerance, Real)
|
|
124
|
+
or not math.isfinite(tolerance)
|
|
125
|
+
or not 0 <= tolerance < 0.25
|
|
126
|
+
):
|
|
127
|
+
raise ValueError("C++ tolerance must be finite, nonnegative and less than 0.25")
|
|
128
|
+
if mapping_callback is not None and not callable(mapping_callback):
|
|
129
|
+
raise TypeError("mapping_callback must be callable")
|
|
130
|
+
a, labels = _adjacency_and_elements(lgp[0], binary)
|
|
131
|
+
b, product_labels = _adjacency_and_elements(lgp[1], binary)
|
|
132
|
+
if a.shape != b.shape or Counter(labels) != Counter(product_labels):
|
|
133
|
+
raise ValueError("Endpoints must have equal atom-type inventories")
|
|
134
|
+
total = math.prod(math.factorial(count) for count in Counter(labels).values())
|
|
135
|
+
if max_bijections is not None and total > max_bijections:
|
|
136
|
+
raise ExactEnumerationLimitError(
|
|
137
|
+
f"{total:,} bijections exceed max_bijections={max_bijections:,}"
|
|
138
|
+
)
|
|
139
|
+
maximum = float(np.abs(a).sum() + np.abs(b).sum()) / 2
|
|
140
|
+
if maximum > 250000:
|
|
141
|
+
raise ValueError("C++ total distance range exceeds 250000")
|
|
142
|
+
seed = (
|
|
143
|
+
_profile_seed(a, b, labels, product_labels)
|
|
144
|
+
if initial_mapping is None
|
|
145
|
+
else initial_mapping
|
|
146
|
+
)
|
|
147
|
+
prepared = prepare_native_candidates(
|
|
148
|
+
lgp,
|
|
149
|
+
0,
|
|
150
|
+
library_path=library_path,
|
|
151
|
+
initial_mapping=seed,
|
|
152
|
+
binary=binary,
|
|
153
|
+
symmetry=symmetry,
|
|
154
|
+
node_properties=node_properties,
|
|
155
|
+
allow_partial_symmetry=True,
|
|
156
|
+
)
|
|
157
|
+
lattice = CostLattice.from_matrices(np.rint(a * 4), np.rint(b * 4))
|
|
158
|
+
deadline = None if time_limit_seconds is None else started + time_limit_seconds
|
|
159
|
+
nodes = leaves = pruned = count = 0
|
|
160
|
+
minimum = reason = proof = None
|
|
161
|
+
mappings, distances = [], []
|
|
162
|
+
first_cost = None
|
|
163
|
+
mixed_costs = False
|
|
164
|
+
|
|
165
|
+
def remaining():
|
|
166
|
+
return 1e100 if deadline is None else max(0, deadline - time.perf_counter())
|
|
167
|
+
|
|
168
|
+
def record_statistics(record):
|
|
169
|
+
nonlocal nodes, leaves, pruned
|
|
170
|
+
nodes += int(record["visited_nodes"])
|
|
171
|
+
leaves += int(record["visited_leaves"])
|
|
172
|
+
pruned += int(record["pruned"])
|
|
173
|
+
if separator_statistics is not None:
|
|
174
|
+
for name in separator_statistics:
|
|
175
|
+
separator_statistics[name] += record["separator_statistics"][name]
|
|
176
|
+
|
|
177
|
+
if target == "minimal" or compute_minimum_cost:
|
|
178
|
+
proof = minimum_function(
|
|
179
|
+
lgp,
|
|
180
|
+
library_path=library_path,
|
|
181
|
+
initial_mapping=seed,
|
|
182
|
+
time_limit_seconds=remaining(),
|
|
183
|
+
_prepared=prepared,
|
|
184
|
+
)
|
|
185
|
+
record_statistics(proof)
|
|
186
|
+
minimum = proof["minimum_cost"]
|
|
187
|
+
reason = proof["reason"]
|
|
188
|
+
|
|
189
|
+
def receive(mapping, cost):
|
|
190
|
+
nonlocal count, first_cost, mixed_costs
|
|
191
|
+
count += 1
|
|
192
|
+
if first_cost is None:
|
|
193
|
+
first_cost = cost
|
|
194
|
+
elif cost != first_cost:
|
|
195
|
+
mixed_costs = True
|
|
196
|
+
if collect_mappings:
|
|
197
|
+
mappings.append(list(mapping))
|
|
198
|
+
distances.append(cost)
|
|
199
|
+
if mapping_callback is not None:
|
|
200
|
+
mapping_callback(list(mapping), cost)
|
|
201
|
+
|
|
202
|
+
selected = minimum if target == "minimal" else float(target)
|
|
203
|
+
if reason is None and selected is not None:
|
|
204
|
+
if CD_mode == "at_most":
|
|
205
|
+
lower = 0.0
|
|
206
|
+
upper = min(
|
|
207
|
+
maximum, math.floor((min(selected, maximum) + tolerance) * 2) / 2
|
|
208
|
+
)
|
|
209
|
+
reachable = lattice.intersects(0, round(upper * 4))
|
|
210
|
+
elif selected > maximum + tolerance:
|
|
211
|
+
reachable = False
|
|
212
|
+
else:
|
|
213
|
+
lower = upper = round(selected * 2) / 2
|
|
214
|
+
reachable = (
|
|
215
|
+
abs(selected - upper) <= tolerance
|
|
216
|
+
and upper <= maximum
|
|
217
|
+
and lattice.intersects(round(upper * 4), round(upper * 4))
|
|
218
|
+
)
|
|
219
|
+
if reachable:
|
|
220
|
+
record = range_function(
|
|
221
|
+
lgp,
|
|
222
|
+
lower,
|
|
223
|
+
upper,
|
|
224
|
+
library_path=library_path,
|
|
225
|
+
time_limit_seconds=remaining(),
|
|
226
|
+
max_mappings=None if max_mappings is None else int(max_mappings),
|
|
227
|
+
callback=receive,
|
|
228
|
+
_prepared=prepared,
|
|
229
|
+
)
|
|
230
|
+
record_statistics(record)
|
|
231
|
+
reason = record["reason"]
|
|
232
|
+
complete = reason is None
|
|
233
|
+
reactant_order, product_order = prepared[6:8]
|
|
234
|
+
group_order = (
|
|
235
|
+
reactant_order * product_order
|
|
236
|
+
if reactant_order is not None and product_order is not None
|
|
237
|
+
else None
|
|
238
|
+
)
|
|
239
|
+
labeled_count = count if count == 0 or not symmetry or group_order == 1 else None
|
|
240
|
+
symmetry_complete = prepared.symmetry_search_complete
|
|
241
|
+
generator_count = len(prepared[4]) + len(prepared[5]) - 2
|
|
242
|
+
return DistanceEnumerationResult(
|
|
243
|
+
target=target,
|
|
244
|
+
cost=first_cost if count and not mixed_costs else None,
|
|
245
|
+
minimum_cost=minimum,
|
|
246
|
+
mappings=mappings,
|
|
247
|
+
distances=distances,
|
|
248
|
+
total_bijections=total,
|
|
249
|
+
maximum_cost_upper_bound=maximum,
|
|
250
|
+
visited_leaves=leaves,
|
|
251
|
+
pruned_branches=pruned,
|
|
252
|
+
visited_nodes=nodes,
|
|
253
|
+
elapsed_seconds=time.perf_counter() - started,
|
|
254
|
+
status=("complete" if count else "no_solutions") if complete else "timeout",
|
|
255
|
+
complete=complete,
|
|
256
|
+
truncation_reason=reason,
|
|
257
|
+
scope=(
|
|
258
|
+
"atom_compatible_assignment_space_modulo_verified_side_symmetry"
|
|
259
|
+
if symmetry
|
|
260
|
+
else "complete_atom_compatible_assignment_space"
|
|
261
|
+
),
|
|
262
|
+
selected_mapping_count=count,
|
|
263
|
+
selected_labeled_mapping_count=labeled_count,
|
|
264
|
+
symmetry_automorphism_count=generator_count + 1,
|
|
265
|
+
symmetry_search_complete=symmetry_complete,
|
|
266
|
+
symmetry_group_order=group_order,
|
|
267
|
+
symmetry_quotient_complete=complete and symmetry_complete,
|
|
268
|
+
backend="pabs_cpp",
|
|
269
|
+
backend_statistics={
|
|
270
|
+
"method": "PABS",
|
|
271
|
+
"requested_backend": "cpp",
|
|
272
|
+
"implementation": "native_assignment_branch_and_bound",
|
|
273
|
+
"minimum_shell_probes": 0,
|
|
274
|
+
"minimum_optimization": proof,
|
|
275
|
+
"CD_mode": CD_mode,
|
|
276
|
+
"mapping_count_scope": (
|
|
277
|
+
"symmetry_candidates" if symmetry else "labeled_mappings"
|
|
278
|
+
),
|
|
279
|
+
"symmetry_enabled": symmetry,
|
|
280
|
+
"side_groups_complete": symmetry_complete,
|
|
281
|
+
"symmetry_generator_count": generator_count,
|
|
282
|
+
"library_path": str(library_path),
|
|
283
|
+
"cost_lattice_modulus_quarters": lattice.modulus,
|
|
284
|
+
"cost_lattice_residue_quarters": lattice.residue,
|
|
285
|
+
**(
|
|
286
|
+
{"separator_config": separator_options,
|
|
287
|
+
"separator_statistics": separator_statistics}
|
|
288
|
+
if separator_options is not None else {}
|
|
289
|
+
),
|
|
290
|
+
},
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
__all__ = ["enumerate_cpp_mappings"]
|