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,378 @@
|
|
|
1
|
+
"""Independent replay for exact chemical-distance certificates."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import math
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
from ...slap.lap import _adjacency_and_elements
|
|
10
|
+
from .bounds import (
|
|
11
|
+
blocked_assignment_extreme as _blocked_assignment_extreme,
|
|
12
|
+
internal_cost_interval as _internal_cost_interval,
|
|
13
|
+
)
|
|
14
|
+
from .records import (
|
|
15
|
+
CertificateVerificationError,
|
|
16
|
+
DistanceEnumerationCertificate,
|
|
17
|
+
_certificate_sha256,
|
|
18
|
+
_input_sha256,
|
|
19
|
+
_mappings_sha256,
|
|
20
|
+
normalize_distance_target,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def verify_distance_enumeration_certificate( # noqa: C901
|
|
25
|
+
lgp,
|
|
26
|
+
certificate: DistanceEnumerationCertificate | dict[str, object],
|
|
27
|
+
*,
|
|
28
|
+
mappings=None,
|
|
29
|
+
) -> bool:
|
|
30
|
+
"""Independently replay a complete exact-CD certificate.
|
|
31
|
+
|
|
32
|
+
The verifier reconstructs the atom-compatible decision tree, checks that
|
|
33
|
+
terminal prefixes are prefix-free and cover every branch, and recomputes
|
|
34
|
+
every terminal pruning bound without trusting search counters.
|
|
35
|
+
"""
|
|
36
|
+
if isinstance(certificate, dict):
|
|
37
|
+
certificate = DistanceEnumerationCertificate.from_dict(certificate)
|
|
38
|
+
if not isinstance(certificate, DistanceEnumerationCertificate):
|
|
39
|
+
raise TypeError("certificate must be a certificate object or dictionary")
|
|
40
|
+
if certificate.schema_version not in {1, 2, 3, 4}:
|
|
41
|
+
raise CertificateVerificationError("unsupported certificate schema")
|
|
42
|
+
if _certificate_sha256(certificate.as_dict()) != certificate.certificate_sha256:
|
|
43
|
+
raise CertificateVerificationError("certificate digest mismatch")
|
|
44
|
+
|
|
45
|
+
reactant, reactant_elements = _adjacency_and_elements(lgp[0], certificate.binary)
|
|
46
|
+
product, product_elements = _adjacency_and_elements(lgp[1], certificate.binary)
|
|
47
|
+
if reactant.shape != product.shape:
|
|
48
|
+
raise CertificateVerificationError("endpoint sizes differ")
|
|
49
|
+
if (
|
|
50
|
+
_input_sha256(
|
|
51
|
+
reactant,
|
|
52
|
+
product,
|
|
53
|
+
reactant_elements,
|
|
54
|
+
product_elements,
|
|
55
|
+
certificate.binary,
|
|
56
|
+
)
|
|
57
|
+
!= certificate.input_sha256
|
|
58
|
+
):
|
|
59
|
+
raise CertificateVerificationError("certificate input binding mismatch")
|
|
60
|
+
|
|
61
|
+
product_by_element: dict[object, tuple[int, ...]] = {}
|
|
62
|
+
for index, element in enumerate(product_elements):
|
|
63
|
+
product_by_element[element] = product_by_element.get(element, ()) + (index,)
|
|
64
|
+
reactant_counts: dict[object, int] = {}
|
|
65
|
+
for element in reactant_elements:
|
|
66
|
+
reactant_counts[element] = reactant_counts.get(element, 0) + 1
|
|
67
|
+
product_counts = {
|
|
68
|
+
element: len(images) for element, images in product_by_element.items()
|
|
69
|
+
}
|
|
70
|
+
if reactant_counts != product_counts:
|
|
71
|
+
raise CertificateVerificationError("atom-type multisets differ")
|
|
72
|
+
expected_total = math.prod(
|
|
73
|
+
math.factorial(count) for count in reactant_counts.values()
|
|
74
|
+
)
|
|
75
|
+
maximum_cost_upper_bound = 0.5 * float(
|
|
76
|
+
np.abs(reactant).sum() + np.abs(product).sum()
|
|
77
|
+
)
|
|
78
|
+
if expected_total != certificate.total_bijections:
|
|
79
|
+
raise CertificateVerificationError("bijection count mismatch")
|
|
80
|
+
if not math.isclose(
|
|
81
|
+
maximum_cost_upper_bound,
|
|
82
|
+
certificate.maximum_cost_upper_bound,
|
|
83
|
+
abs_tol=certificate.tolerance,
|
|
84
|
+
rel_tol=0.0,
|
|
85
|
+
):
|
|
86
|
+
raise CertificateVerificationError("maximum-CD bound mismatch")
|
|
87
|
+
|
|
88
|
+
target = normalize_distance_target(certificate.target)
|
|
89
|
+
if certificate.kind == "maximum_cost_upper_bound":
|
|
90
|
+
if target == "minimal" or not (
|
|
91
|
+
target > maximum_cost_upper_bound + certificate.tolerance
|
|
92
|
+
):
|
|
93
|
+
raise CertificateVerificationError("invalid maximum-CD proof")
|
|
94
|
+
if (
|
|
95
|
+
certificate.terminal_prefixes
|
|
96
|
+
or certificate.frontier_prefixes
|
|
97
|
+
or certificate.symmetry_prefixes
|
|
98
|
+
or certificate.lower_bound_prefixes
|
|
99
|
+
or certificate.upper_bound_prefixes
|
|
100
|
+
or certificate.selected_mapping_count
|
|
101
|
+
):
|
|
102
|
+
raise CertificateVerificationError("upper-bound proof contains mappings")
|
|
103
|
+
if certificate.cost is not None:
|
|
104
|
+
raise CertificateVerificationError("upper-bound proof has a cost")
|
|
105
|
+
if certificate.pruning_limit is not None:
|
|
106
|
+
raise CertificateVerificationError("upper-bound proof has a pruning limit")
|
|
107
|
+
if certificate.selected_mappings_sha256 != _mappings_sha256([]):
|
|
108
|
+
raise CertificateVerificationError("empty mapping digest mismatch")
|
|
109
|
+
if certificate.status != "no_solutions":
|
|
110
|
+
raise CertificateVerificationError("upper-bound proof status mismatch")
|
|
111
|
+
if mappings is not None and list(mappings):
|
|
112
|
+
raise CertificateVerificationError("claimed empty shell has mappings")
|
|
113
|
+
return True
|
|
114
|
+
if certificate.kind != "prefix_cover":
|
|
115
|
+
raise CertificateVerificationError("unknown certificate kind")
|
|
116
|
+
valid_scopes = {
|
|
117
|
+
"complete_atom_compatible_assignment_space",
|
|
118
|
+
"verified_product_automorphism_lex_leaders",
|
|
119
|
+
# Accepted for certificates emitted before the bounded-symmetry scope
|
|
120
|
+
# was named precisely.
|
|
121
|
+
"product_automorphism_orbit_representatives",
|
|
122
|
+
}
|
|
123
|
+
if certificate.mapping_scope not in valid_scopes:
|
|
124
|
+
raise CertificateVerificationError("certificate mapping scope mismatch")
|
|
125
|
+
symmetry_scopes = {
|
|
126
|
+
"verified_product_automorphism_lex_leaders",
|
|
127
|
+
"product_automorphism_orbit_representatives",
|
|
128
|
+
}
|
|
129
|
+
if certificate.symmetry_prefixes and certificate.mapping_scope not in (
|
|
130
|
+
symmetry_scopes
|
|
131
|
+
):
|
|
132
|
+
raise CertificateVerificationError("symmetry pruning requires quotient scope")
|
|
133
|
+
if certificate.schema_version == 1 and certificate.mapping_scope != (
|
|
134
|
+
"complete_atom_compatible_assignment_space"
|
|
135
|
+
):
|
|
136
|
+
raise CertificateVerificationError("schema-1 scope mismatch")
|
|
137
|
+
if target == "minimal":
|
|
138
|
+
if not certificate.frontier_prefixes and (
|
|
139
|
+
certificate.cost is None
|
|
140
|
+
or certificate.pruning_limit is None
|
|
141
|
+
or not math.isclose(
|
|
142
|
+
certificate.cost,
|
|
143
|
+
certificate.pruning_limit,
|
|
144
|
+
abs_tol=certificate.tolerance,
|
|
145
|
+
rel_tol=0.0,
|
|
146
|
+
)
|
|
147
|
+
):
|
|
148
|
+
raise CertificateVerificationError("invalid minimal pruning limit")
|
|
149
|
+
elif certificate.pruning_limit is None or not math.isclose(
|
|
150
|
+
certificate.pruning_limit,
|
|
151
|
+
target,
|
|
152
|
+
abs_tol=certificate.tolerance,
|
|
153
|
+
rel_tol=0.0,
|
|
154
|
+
):
|
|
155
|
+
raise CertificateVerificationError("numeric pruning limit mismatch")
|
|
156
|
+
|
|
157
|
+
atom_count = len(reactant_elements)
|
|
158
|
+
order = tuple(certificate.reactant_order)
|
|
159
|
+
if sorted(order) != list(range(atom_count)):
|
|
160
|
+
raise CertificateVerificationError("reactant order is not a permutation")
|
|
161
|
+
trie: dict[object, object] = {}
|
|
162
|
+
terminal = object()
|
|
163
|
+
frontier = object()
|
|
164
|
+
symmetry = object()
|
|
165
|
+
lower_bound = object()
|
|
166
|
+
upper_bound = object()
|
|
167
|
+
|
|
168
|
+
def add_prefix(prefix, marker) -> None:
|
|
169
|
+
node = trie
|
|
170
|
+
if len(prefix) > atom_count:
|
|
171
|
+
raise CertificateVerificationError("certificate prefix is too long")
|
|
172
|
+
for image in prefix:
|
|
173
|
+
if (
|
|
174
|
+
terminal in node
|
|
175
|
+
or frontier in node
|
|
176
|
+
or symmetry in node
|
|
177
|
+
or lower_bound in node
|
|
178
|
+
or upper_bound in node
|
|
179
|
+
):
|
|
180
|
+
raise CertificateVerificationError("certificate prefixes overlap")
|
|
181
|
+
node = node.setdefault(int(image), {})
|
|
182
|
+
if node:
|
|
183
|
+
raise CertificateVerificationError("certificate prefixes overlap")
|
|
184
|
+
node[marker] = True
|
|
185
|
+
|
|
186
|
+
for prefix in certificate.terminal_prefixes:
|
|
187
|
+
add_prefix(prefix, terminal)
|
|
188
|
+
for prefix in certificate.frontier_prefixes:
|
|
189
|
+
add_prefix(prefix, frontier)
|
|
190
|
+
for prefix, witness in certificate.symmetry_prefixes:
|
|
191
|
+
add_prefix(prefix, symmetry)
|
|
192
|
+
node = trie
|
|
193
|
+
for image in prefix:
|
|
194
|
+
node = node[int(image)]
|
|
195
|
+
node[symmetry] = tuple(witness)
|
|
196
|
+
for prefix in certificate.lower_bound_prefixes:
|
|
197
|
+
add_prefix(prefix, lower_bound)
|
|
198
|
+
for prefix in certificate.upper_bound_prefixes:
|
|
199
|
+
add_prefix(prefix, upper_bound)
|
|
200
|
+
|
|
201
|
+
selected_mappings: list[list[int]] = []
|
|
202
|
+
verified_symmetries: set[tuple[int, ...]] = set()
|
|
203
|
+
|
|
204
|
+
def verify_symmetry(witness: tuple[int, ...]) -> None:
|
|
205
|
+
if witness in verified_symmetries:
|
|
206
|
+
return
|
|
207
|
+
if sorted(witness) != list(range(atom_count)):
|
|
208
|
+
raise CertificateVerificationError("invalid symmetry permutation")
|
|
209
|
+
for image, transformed in enumerate(witness):
|
|
210
|
+
if product_elements[image] != product_elements[transformed]:
|
|
211
|
+
raise CertificateVerificationError("symmetry changes atom type")
|
|
212
|
+
transformed_product = product[
|
|
213
|
+
np.asarray(witness)[:, None], np.asarray(witness)[None, :]
|
|
214
|
+
]
|
|
215
|
+
if not np.array_equal(product, transformed_product):
|
|
216
|
+
raise CertificateVerificationError("symmetry changes product graph")
|
|
217
|
+
verified_symmetries.add(witness)
|
|
218
|
+
|
|
219
|
+
def prefix_cost(prefix: tuple[int, ...]) -> float:
|
|
220
|
+
cost = 0.0
|
|
221
|
+
for right_position, right_image in enumerate(prefix):
|
|
222
|
+
right_atom = order[right_position]
|
|
223
|
+
for left_position in range(right_position):
|
|
224
|
+
left_atom = order[left_position]
|
|
225
|
+
left_image = prefix[left_position]
|
|
226
|
+
cost += 0.5 * abs(
|
|
227
|
+
float(reactant[right_atom, left_atom])
|
|
228
|
+
- float(product[right_image, left_image])
|
|
229
|
+
)
|
|
230
|
+
cost += 0.5 * abs(
|
|
231
|
+
float(reactant[left_atom, right_atom])
|
|
232
|
+
- float(product[left_image, right_image])
|
|
233
|
+
)
|
|
234
|
+
return cost
|
|
235
|
+
|
|
236
|
+
def remaining_assignment_interval(prefix: tuple[int, ...]) -> tuple[float, float]:
|
|
237
|
+
depth = len(prefix)
|
|
238
|
+
remaining_atoms = list(order[depth:])
|
|
239
|
+
used = set(prefix)
|
|
240
|
+
remaining_products = [image for image in range(atom_count) if image not in used]
|
|
241
|
+
costs = np.zeros((atom_count, atom_count), dtype=float)
|
|
242
|
+
for reactant_atom in remaining_atoms:
|
|
243
|
+
for product_atom in remaining_products:
|
|
244
|
+
interaction = 0.0
|
|
245
|
+
for position, assigned_product in enumerate(prefix):
|
|
246
|
+
assigned_reactant = order[position]
|
|
247
|
+
interaction += 0.5 * abs(
|
|
248
|
+
float(reactant[reactant_atom, assigned_reactant])
|
|
249
|
+
- float(product[product_atom, assigned_product])
|
|
250
|
+
)
|
|
251
|
+
interaction += 0.5 * abs(
|
|
252
|
+
float(reactant[assigned_reactant, reactant_atom])
|
|
253
|
+
- float(product[assigned_product, product_atom])
|
|
254
|
+
)
|
|
255
|
+
costs[reactant_atom, product_atom] = interaction
|
|
256
|
+
cross_lower = _blocked_assignment_extreme(
|
|
257
|
+
costs,
|
|
258
|
+
remaining_atoms,
|
|
259
|
+
remaining_products,
|
|
260
|
+
reactant_elements,
|
|
261
|
+
product_elements,
|
|
262
|
+
)
|
|
263
|
+
cross_upper = _blocked_assignment_extreme(
|
|
264
|
+
costs,
|
|
265
|
+
remaining_atoms,
|
|
266
|
+
remaining_products,
|
|
267
|
+
reactant_elements,
|
|
268
|
+
product_elements,
|
|
269
|
+
maximize=True,
|
|
270
|
+
)
|
|
271
|
+
internal_lower, internal_upper = _internal_cost_interval(
|
|
272
|
+
reactant,
|
|
273
|
+
product,
|
|
274
|
+
remaining_atoms,
|
|
275
|
+
remaining_products,
|
|
276
|
+
)
|
|
277
|
+
return cross_lower + internal_lower, cross_upper + internal_upper
|
|
278
|
+
|
|
279
|
+
def replay(node, prefix: tuple[int, ...], used: frozenset[int]) -> None:
|
|
280
|
+
depth = len(prefix)
|
|
281
|
+
if frontier in node:
|
|
282
|
+
if len(node) != 1:
|
|
283
|
+
raise CertificateVerificationError("frontier has descendants")
|
|
284
|
+
return
|
|
285
|
+
if symmetry in node:
|
|
286
|
+
if len(node) != 1:
|
|
287
|
+
raise CertificateVerificationError("symmetry prefix has descendants")
|
|
288
|
+
witness = tuple(node[symmetry])
|
|
289
|
+
verify_symmetry(witness)
|
|
290
|
+
transformed = tuple(witness[image] for image in prefix)
|
|
291
|
+
if not transformed < prefix:
|
|
292
|
+
raise CertificateVerificationError("invalid symmetry lex leader")
|
|
293
|
+
return
|
|
294
|
+
if lower_bound in node:
|
|
295
|
+
if len(node) != 1:
|
|
296
|
+
raise CertificateVerificationError("lower-bound prefix has descendants")
|
|
297
|
+
limit = certificate.pruning_limit
|
|
298
|
+
bound, _ = remaining_assignment_interval(prefix)
|
|
299
|
+
bound += prefix_cost(prefix)
|
|
300
|
+
if limit is None or not bound > float(limit) + certificate.tolerance:
|
|
301
|
+
raise CertificateVerificationError("invalid assignment lower bound")
|
|
302
|
+
return
|
|
303
|
+
if upper_bound in node:
|
|
304
|
+
if len(node) != 1:
|
|
305
|
+
raise CertificateVerificationError("upper-bound prefix has descendants")
|
|
306
|
+
if target == "minimal":
|
|
307
|
+
raise CertificateVerificationError(
|
|
308
|
+
"upper bound cannot prune minimization"
|
|
309
|
+
)
|
|
310
|
+
_, bound = remaining_assignment_interval(prefix)
|
|
311
|
+
bound += prefix_cost(prefix)
|
|
312
|
+
if not bound < float(target) - certificate.tolerance:
|
|
313
|
+
raise CertificateVerificationError("invalid assignment upper bound")
|
|
314
|
+
return
|
|
315
|
+
if terminal in node:
|
|
316
|
+
if len(node) != 1:
|
|
317
|
+
raise CertificateVerificationError("terminal has descendants")
|
|
318
|
+
cost = prefix_cost(prefix)
|
|
319
|
+
if depth < atom_count:
|
|
320
|
+
limit = certificate.pruning_limit
|
|
321
|
+
if limit is None or not cost > float(limit) + certificate.tolerance:
|
|
322
|
+
raise CertificateVerificationError("invalid pruned-prefix bound")
|
|
323
|
+
return
|
|
324
|
+
mapping = [-1] * atom_count
|
|
325
|
+
for position, image in enumerate(prefix):
|
|
326
|
+
mapping[order[position]] = image
|
|
327
|
+
selected = (
|
|
328
|
+
certificate.cost is not None
|
|
329
|
+
and math.isclose(
|
|
330
|
+
cost,
|
|
331
|
+
certificate.cost,
|
|
332
|
+
abs_tol=certificate.tolerance,
|
|
333
|
+
rel_tol=0.0,
|
|
334
|
+
)
|
|
335
|
+
if target == "minimal"
|
|
336
|
+
else math.isclose(
|
|
337
|
+
cost,
|
|
338
|
+
target,
|
|
339
|
+
abs_tol=certificate.tolerance,
|
|
340
|
+
rel_tol=0.0,
|
|
341
|
+
)
|
|
342
|
+
)
|
|
343
|
+
if selected:
|
|
344
|
+
selected_mappings.append(mapping)
|
|
345
|
+
return
|
|
346
|
+
if depth == atom_count:
|
|
347
|
+
raise CertificateVerificationError("uncovered complete assignment")
|
|
348
|
+
atom = order[depth]
|
|
349
|
+
expected_images = {
|
|
350
|
+
image
|
|
351
|
+
for image in product_by_element.get(reactant_elements[atom], ())
|
|
352
|
+
if image not in used
|
|
353
|
+
}
|
|
354
|
+
actual_images = set(node)
|
|
355
|
+
if actual_images != expected_images:
|
|
356
|
+
raise CertificateVerificationError("terminal prefixes do not cover tree")
|
|
357
|
+
for image in sorted(expected_images):
|
|
358
|
+
replay(node[image], prefix + (image,), used | {image})
|
|
359
|
+
|
|
360
|
+
replay(trie, (), frozenset())
|
|
361
|
+
selected_digest = _mappings_sha256(selected_mappings)
|
|
362
|
+
if len(selected_mappings) != certificate.selected_mapping_count:
|
|
363
|
+
raise CertificateVerificationError("selected mapping count mismatch")
|
|
364
|
+
if selected_digest != certificate.selected_mappings_sha256:
|
|
365
|
+
raise CertificateVerificationError("selected mapping digest mismatch")
|
|
366
|
+
expected_status = (
|
|
367
|
+
"timeout"
|
|
368
|
+
if certificate.frontier_prefixes
|
|
369
|
+
else "complete" if selected_mappings else "no_solutions"
|
|
370
|
+
)
|
|
371
|
+
if certificate.status != expected_status:
|
|
372
|
+
raise CertificateVerificationError("certificate status mismatch")
|
|
373
|
+
if mappings is not None and _mappings_sha256(mappings) != selected_digest:
|
|
374
|
+
raise CertificateVerificationError("provided mappings differ from certificate")
|
|
375
|
+
return True
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
__all__ = ["verify_distance_enumeration_certificate"]
|