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,247 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Callable, Dict, FrozenSet, Iterable, List, Optional, Tuple
|
|
4
|
+
|
|
5
|
+
Sig = Tuple[Tuple, Tuple]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _build_host_orbit_index(
|
|
9
|
+
host_orbits: Iterable[FrozenSet[int]],
|
|
10
|
+
) -> Dict[int, int]:
|
|
11
|
+
"""Build host node -> host orbit index.
|
|
12
|
+
|
|
13
|
+
:param host_orbits:
|
|
14
|
+
Iterable of host orbits.
|
|
15
|
+
:return:
|
|
16
|
+
Dict mapping host node to orbit index.
|
|
17
|
+
"""
|
|
18
|
+
host_orbit_index: Dict[int, int] = {}
|
|
19
|
+
for idx, orb in enumerate(host_orbits):
|
|
20
|
+
for h in orb:
|
|
21
|
+
host_orbit_index[h] = idx
|
|
22
|
+
return host_orbit_index
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _make_host_repr(
|
|
26
|
+
host_orbits: Optional[Iterable[FrozenSet[int]]],
|
|
27
|
+
) -> Callable[[int], int]:
|
|
28
|
+
"""Create a function that maps host node to its representative.
|
|
29
|
+
|
|
30
|
+
If host orbits are provided, the representative is the host-orbit index.
|
|
31
|
+
This is sound only for a one-node mapping; callers with joint mappings
|
|
32
|
+
must supply the identity representation instead.
|
|
33
|
+
|
|
34
|
+
:param host_orbits:
|
|
35
|
+
Host orbits or None.
|
|
36
|
+
:return:
|
|
37
|
+
Callable mapping host node -> representative integer.
|
|
38
|
+
:raises ValueError:
|
|
39
|
+
If host orbits are provided but a host node is not covered.
|
|
40
|
+
"""
|
|
41
|
+
if host_orbits is None:
|
|
42
|
+
return lambda h: h
|
|
43
|
+
|
|
44
|
+
host_orbit_index = _build_host_orbit_index(host_orbits)
|
|
45
|
+
|
|
46
|
+
def _repr(h: int) -> int:
|
|
47
|
+
try:
|
|
48
|
+
return host_orbit_index[h]
|
|
49
|
+
except KeyError as exc:
|
|
50
|
+
raise ValueError(
|
|
51
|
+
f"Host node {h} not present in host_orbits; cannot canonicalize."
|
|
52
|
+
) from exc
|
|
53
|
+
|
|
54
|
+
return _repr
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _prepare_pattern_orbits(
|
|
58
|
+
pattern_orbits: Optional[Iterable[FrozenSet[int]]],
|
|
59
|
+
pattern_anchor: FrozenSet[int],
|
|
60
|
+
) -> Tuple[List[Tuple[int, ...]], Tuple[int, ...]]:
|
|
61
|
+
"""Prepare free pattern orbits and anchored nodes.
|
|
62
|
+
|
|
63
|
+
:param pattern_orbits:
|
|
64
|
+
Pattern orbits or None.
|
|
65
|
+
:param pattern_anchor:
|
|
66
|
+
Anchor nodes of the pattern.
|
|
67
|
+
:return:
|
|
68
|
+
(free_pattern_orbits, anchored_pattern_nodes)
|
|
69
|
+
"""
|
|
70
|
+
if pattern_orbits is None:
|
|
71
|
+
return ([], ())
|
|
72
|
+
|
|
73
|
+
orbits_sorted = [tuple(sorted(o, key=repr)) for o in pattern_orbits]
|
|
74
|
+
free_orbits = [o for o in orbits_sorted if not set(o) & pattern_anchor]
|
|
75
|
+
anchored_nodes = tuple(sorted(pattern_anchor, key=repr))
|
|
76
|
+
return (free_orbits, anchored_nodes)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _free_sig_from_pattern_orbits(
|
|
80
|
+
mapping: Dict[int, int],
|
|
81
|
+
free_pattern_orbits: List[Tuple[int, ...]],
|
|
82
|
+
host_repr: Callable[[int], int],
|
|
83
|
+
) -> Tuple:
|
|
84
|
+
"""Compute free signature using pattern orbits (partial-match safe).
|
|
85
|
+
|
|
86
|
+
Each orbit contributes a pair:
|
|
87
|
+
(present_pattern_nodes_sorted, sorted(host_repr(images)))
|
|
88
|
+
|
|
89
|
+
:param mapping:
|
|
90
|
+
Pattern -> host mapping.
|
|
91
|
+
:param free_pattern_orbits:
|
|
92
|
+
Pattern orbits disjoint from anchor.
|
|
93
|
+
:param host_repr:
|
|
94
|
+
Host representative function.
|
|
95
|
+
:return:
|
|
96
|
+
Free signature tuple.
|
|
97
|
+
"""
|
|
98
|
+
if not free_pattern_orbits:
|
|
99
|
+
return ()
|
|
100
|
+
|
|
101
|
+
m_keys = set(mapping.keys())
|
|
102
|
+
parts: List[Tuple[Tuple[int, ...], Tuple[int, ...]]] = []
|
|
103
|
+
|
|
104
|
+
for orbit in free_pattern_orbits:
|
|
105
|
+
present = [p for p in orbit if p in m_keys]
|
|
106
|
+
if not present:
|
|
107
|
+
continue
|
|
108
|
+
|
|
109
|
+
present_sorted = tuple(sorted(present, key=repr))
|
|
110
|
+
image = tuple(sorted((host_repr(mapping[p]) for p in present_sorted), key=repr))
|
|
111
|
+
parts.append((present_sorted, image))
|
|
112
|
+
|
|
113
|
+
return tuple(parts)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _free_sig_host_only(
|
|
117
|
+
mapping: Dict[int, int],
|
|
118
|
+
host_repr: Callable[[int], int],
|
|
119
|
+
) -> Tuple:
|
|
120
|
+
"""Compute free signature using host-only symmetry (mapping values only).
|
|
121
|
+
|
|
122
|
+
:param mapping:
|
|
123
|
+
Pattern -> host mapping.
|
|
124
|
+
:param host_repr:
|
|
125
|
+
Host representative function.
|
|
126
|
+
:return:
|
|
127
|
+
Free signature tuple.
|
|
128
|
+
"""
|
|
129
|
+
return (tuple(sorted((host_repr(h) for h in mapping.values()), key=repr)),)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _anchor_sig(
|
|
133
|
+
mapping: Dict[int, int],
|
|
134
|
+
anchored_pattern_nodes: Tuple[int, ...],
|
|
135
|
+
) -> Tuple:
|
|
136
|
+
"""Compute anchor signature: exact placement for anchored pattern nodes
|
|
137
|
+
that are present in the mapping.
|
|
138
|
+
|
|
139
|
+
Returned as (pattern_node, host_node) pairs for stability.
|
|
140
|
+
|
|
141
|
+
:param mapping:
|
|
142
|
+
Pattern -> host mapping.
|
|
143
|
+
:param anchored_pattern_nodes:
|
|
144
|
+
Sorted anchored pattern nodes.
|
|
145
|
+
:return:
|
|
146
|
+
Anchor signature tuple.
|
|
147
|
+
"""
|
|
148
|
+
if not anchored_pattern_nodes:
|
|
149
|
+
return ()
|
|
150
|
+
|
|
151
|
+
present = [p for p in anchored_pattern_nodes if p in mapping]
|
|
152
|
+
return tuple((p, mapping[p]) for p in present)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def deduplicate_matches_with_anchor(
|
|
156
|
+
matches: Iterable[Dict[int, int]],
|
|
157
|
+
*,
|
|
158
|
+
pattern_orbits: Optional[Iterable[FrozenSet[int]]] = None,
|
|
159
|
+
pattern_anchor: Optional[FrozenSet[int]] = None,
|
|
160
|
+
host_orbits: Optional[Iterable[FrozenSet[int]]] = None,
|
|
161
|
+
host_anchor: Optional[FrozenSet[int]] = None,
|
|
162
|
+
) -> List[Dict[int, int]]:
|
|
163
|
+
"""Deduplicate pattern→host matches with optional anchor-aware symmetry
|
|
164
|
+
breaking on both pattern and host sides.
|
|
165
|
+
|
|
166
|
+
This function supports *partial* mappings. Orbit partitions are sufficient
|
|
167
|
+
to quotient singleton mappings only; joint mappings are returned unchanged
|
|
168
|
+
because their equivalence requires complete automorphism group elements.
|
|
169
|
+
|
|
170
|
+
Rules
|
|
171
|
+
-----
|
|
172
|
+
- Matches are always interpreted as **pattern → host** mappings.
|
|
173
|
+
- For singleton mappings, if ``pattern_orbits`` is provided:
|
|
174
|
+
* Pattern nodes inside ``pattern_anchor`` are fixed when present.
|
|
175
|
+
* Pattern orbits disjoint from the anchor are deduplicated up to
|
|
176
|
+
permutation.
|
|
177
|
+
- If ``pattern_orbits`` is None and ``host_orbits`` is provided:
|
|
178
|
+
* A one-node mapping may be deduplicated by its host vertex orbit.
|
|
179
|
+
* Joint mappings remain distinct because vertex orbits do not encode
|
|
180
|
+
the simultaneous action of the host automorphism group.
|
|
181
|
+
- Joint mappings, or mappings with both orbit arguments absent, are
|
|
182
|
+
returned unchanged.
|
|
183
|
+
|
|
184
|
+
:param matches:
|
|
185
|
+
Iterable of pattern → host mapping dictionaries.
|
|
186
|
+
:param pattern_orbits:
|
|
187
|
+
Automorphism orbits of the pattern graph (optional).
|
|
188
|
+
:param pattern_anchor:
|
|
189
|
+
Anchor component of the pattern graph (optional).
|
|
190
|
+
:param host_orbits:
|
|
191
|
+
Automorphism orbits of the host graph (optional).
|
|
192
|
+
:param host_anchor:
|
|
193
|
+
Anchor component of the host graph (optional). Kept for API symmetry;
|
|
194
|
+
host anchoring is handled indirectly by orbit collapsing.
|
|
195
|
+
:return:
|
|
196
|
+
Deduplicated list of pattern → host mappings, preserving input order.
|
|
197
|
+
:raises ValueError:
|
|
198
|
+
If ``host_orbits`` is provided but a mapping contains a host node not
|
|
199
|
+
covered by any host orbit.
|
|
200
|
+
"""
|
|
201
|
+
# Reserved for API compatibility.
|
|
202
|
+
_ = host_anchor
|
|
203
|
+
|
|
204
|
+
if pattern_orbits is None and host_orbits is None:
|
|
205
|
+
return list(matches)
|
|
206
|
+
|
|
207
|
+
pattern_anchor = pattern_anchor or frozenset()
|
|
208
|
+
mappings = list(matches)
|
|
209
|
+
joint_mapping = any(len(mapping) > 1 for mapping in mappings)
|
|
210
|
+
if joint_mapping:
|
|
211
|
+
# Vertex orbits describe where one vertex may move. They do not encode
|
|
212
|
+
# which simultaneous permutations across one or several orbits belong
|
|
213
|
+
# to the same group element. A joint quotient needs the complete group
|
|
214
|
+
# action, not only its orbit partition.
|
|
215
|
+
return mappings
|
|
216
|
+
host_repr = _make_host_repr(None if joint_mapping else host_orbits)
|
|
217
|
+
|
|
218
|
+
free_pattern_orbits, anchored_pattern_nodes = _prepare_pattern_orbits(
|
|
219
|
+
pattern_orbits,
|
|
220
|
+
pattern_anchor,
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
use_pattern = bool(free_pattern_orbits) or bool(anchored_pattern_nodes)
|
|
224
|
+
seen: set[Sig] = set()
|
|
225
|
+
unique: List[Dict[int, int]] = []
|
|
226
|
+
|
|
227
|
+
for m in mappings:
|
|
228
|
+
if use_pattern:
|
|
229
|
+
free_sig = _free_sig_from_pattern_orbits(
|
|
230
|
+
m,
|
|
231
|
+
free_pattern_orbits,
|
|
232
|
+
host_repr,
|
|
233
|
+
)
|
|
234
|
+
else:
|
|
235
|
+
# host-only symmetry case
|
|
236
|
+
free_sig = _free_sig_host_only(m, host_repr)
|
|
237
|
+
|
|
238
|
+
anchor_part = _anchor_sig(m, anchored_pattern_nodes)
|
|
239
|
+
sig: Sig = (free_sig, anchor_part)
|
|
240
|
+
|
|
241
|
+
if sig in seen:
|
|
242
|
+
continue
|
|
243
|
+
|
|
244
|
+
seen.add(sig)
|
|
245
|
+
unique.append(m)
|
|
246
|
+
|
|
247
|
+
return unique
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import networkx as nx
|
|
2
|
+
from operator import eq
|
|
3
|
+
from collections import OrderedDict
|
|
4
|
+
from typing import List, Set, Dict, Any, Tuple, Optional, Callable, Mapping
|
|
5
|
+
from networkx.algorithms.isomorphism import generic_node_match, generic_edge_match
|
|
6
|
+
|
|
7
|
+
from synkit.Rule.Modify.rule_utils import strip_context
|
|
8
|
+
from synkit.Graph.Stereo.matching import stereo_isomorphic
|
|
9
|
+
from synkit.IO.gml_to_nx import GMLToNX
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _match_all(_left: Mapping[str, Any], _right: Mapping[str, Any]) -> bool:
|
|
13
|
+
"""Implement NetworkX's no-attribute-matcher semantics explicitly."""
|
|
14
|
+
return True
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _as_native_graph(rule: Any) -> nx.Graph:
|
|
18
|
+
"""Return a native ITS graph from a graph or serialized GML rule."""
|
|
19
|
+
if isinstance(rule, nx.Graph):
|
|
20
|
+
return rule
|
|
21
|
+
if isinstance(rule, str):
|
|
22
|
+
return GMLToNX(rule).transform()[2]
|
|
23
|
+
raise TypeError("Rules must be NetworkX graphs or GML strings.")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class GraphCluster:
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
node_label_names: List[str] = ["element", "charge"],
|
|
30
|
+
node_label_default: List[Any] = ["*", 0],
|
|
31
|
+
edge_attribute: str = "order",
|
|
32
|
+
backend: str = "nx",
|
|
33
|
+
):
|
|
34
|
+
"""Initializes the GraphCluster with customization options for node and
|
|
35
|
+
edge matching functions. This class is designed to facilitate
|
|
36
|
+
clustering of graph nodes and edges based on specified attributes and
|
|
37
|
+
their matching criteria.
|
|
38
|
+
|
|
39
|
+
:param node_label_names: A list of node attribute names to be considered
|
|
40
|
+
for matching. Each attribute name corresponds to a property of the nodes in the
|
|
41
|
+
graph. Default values provided.
|
|
42
|
+
:type node_label_names: List[str]
|
|
43
|
+
:param node_label_default: Default values for each of the node attributes
|
|
44
|
+
specified in `node_label_names`. These are used where node attributes are missing.
|
|
45
|
+
The length and order of this list should match `node_label_names`.
|
|
46
|
+
:type node_label_default: List[Any]
|
|
47
|
+
:param edge_attribute: The name of the edge attribute to consider for matching
|
|
48
|
+
edges. This attribute is used to assess edge similarity.
|
|
49
|
+
:type edge_attribute: str
|
|
50
|
+
|
|
51
|
+
:raises ValueError: If the lengths of `node_label_names` and `node_label_default` do not match.
|
|
52
|
+
"""
|
|
53
|
+
self.backend = backend.lower()
|
|
54
|
+
if self.backend != "nx":
|
|
55
|
+
raise ValueError(f"Unsupported backend: {backend!r}")
|
|
56
|
+
|
|
57
|
+
if len(node_label_names) != len(node_label_default):
|
|
58
|
+
raise ValueError(
|
|
59
|
+
"The lengths of `node_label_names` and `node_label_default` must match."
|
|
60
|
+
)
|
|
61
|
+
self.nodeLabelNames = node_label_names
|
|
62
|
+
self.nodeLabelDefault = node_label_default
|
|
63
|
+
self.edgeAttribute = edge_attribute
|
|
64
|
+
self.nodeMatch = generic_node_match(
|
|
65
|
+
self.nodeLabelNames,
|
|
66
|
+
self.nodeLabelDefault,
|
|
67
|
+
[eq for _ in node_label_names],
|
|
68
|
+
)
|
|
69
|
+
self.edgeMatch = generic_edge_match(self.edgeAttribute, 1, eq)
|
|
70
|
+
|
|
71
|
+
def available_backends(self) -> List[str]:
|
|
72
|
+
"""Return the native matching backend."""
|
|
73
|
+
return ["nx"]
|
|
74
|
+
|
|
75
|
+
def iterative_cluster(
|
|
76
|
+
self,
|
|
77
|
+
rules: List[Any],
|
|
78
|
+
attributes: Optional[List[Any]] = None,
|
|
79
|
+
nodeMatch: Optional[Callable] = None,
|
|
80
|
+
edgeMatch: Optional[Callable] = None,
|
|
81
|
+
) -> Tuple[List[Set[int]], Dict[int, int]]:
|
|
82
|
+
"""Clusters rules based on their similarities, which could include
|
|
83
|
+
structural or attribute-based similarities depending on the given
|
|
84
|
+
attributes.
|
|
85
|
+
|
|
86
|
+
:param rules: List of rules, potentially serialized strings of rule
|
|
87
|
+
representations.
|
|
88
|
+
:type rules: List[str]
|
|
89
|
+
:param attributes: Attributes associated with each rule for
|
|
90
|
+
preliminary comparison, e.g., labels or properties.
|
|
91
|
+
:type attributes: Optional[List[Any]]
|
|
92
|
+
|
|
93
|
+
:return: Rule-index clusters and a mapping from each rule index to its
|
|
94
|
+
cluster index.
|
|
95
|
+
:rtype: Tuple[List[Set[int]], Dict[int, int]]
|
|
96
|
+
"""
|
|
97
|
+
native_rules = [_as_native_graph(rule) for rule in rules]
|
|
98
|
+
|
|
99
|
+
if attributes is None:
|
|
100
|
+
attributes_sorted = [1] * len(rules)
|
|
101
|
+
else:
|
|
102
|
+
if len(attributes) != len(rules):
|
|
103
|
+
raise ValueError("attributes must have the same length as rules")
|
|
104
|
+
attributes_sorted = []
|
|
105
|
+
for value in attributes:
|
|
106
|
+
if isinstance(value, OrderedDict):
|
|
107
|
+
value = OrderedDict(sorted(value.items(), key=repr))
|
|
108
|
+
elif isinstance(value, (list, tuple, set, frozenset)):
|
|
109
|
+
value = tuple(sorted(value, key=repr))
|
|
110
|
+
attributes_sorted.append(value)
|
|
111
|
+
|
|
112
|
+
visited = set()
|
|
113
|
+
clusters = []
|
|
114
|
+
rule_to_cluster = {}
|
|
115
|
+
|
|
116
|
+
for i, rule_i in enumerate(native_rules):
|
|
117
|
+
if i in visited:
|
|
118
|
+
continue
|
|
119
|
+
cluster = {i}
|
|
120
|
+
visited.add(i)
|
|
121
|
+
rule_to_cluster[i] = len(clusters)
|
|
122
|
+
# fmt: off
|
|
123
|
+
for j, rule_j in enumerate(native_rules[i + 1:], start=i + 1):
|
|
124
|
+
# fmt: on
|
|
125
|
+
if attributes_sorted[i] == attributes_sorted[j] and j not in visited:
|
|
126
|
+
# ``stereo_isomorphic`` has chemistry-aware defaults,
|
|
127
|
+
# whereas this API defines ``None`` as matching every node
|
|
128
|
+
# or edge attribute. Preserve that contract while layering
|
|
129
|
+
# exact stereo-registry comparison over each candidate.
|
|
130
|
+
is_isomorphic = stereo_isomorphic(
|
|
131
|
+
rule_i,
|
|
132
|
+
rule_j,
|
|
133
|
+
node_match=nodeMatch or _match_all,
|
|
134
|
+
edge_match=edgeMatch or _match_all,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
if is_isomorphic:
|
|
138
|
+
cluster.add(j)
|
|
139
|
+
visited.add(j)
|
|
140
|
+
rule_to_cluster[j] = len(clusters)
|
|
141
|
+
|
|
142
|
+
clusters.append(cluster)
|
|
143
|
+
|
|
144
|
+
return clusters, rule_to_cluster
|
|
145
|
+
|
|
146
|
+
def fit(
|
|
147
|
+
self,
|
|
148
|
+
data: List[Dict],
|
|
149
|
+
rule_key: str = "gml",
|
|
150
|
+
attribute_key: str = "WLHash",
|
|
151
|
+
strip: bool = False,
|
|
152
|
+
) -> List[Dict]:
|
|
153
|
+
"""Automatically clusters the rules and assigns them cluster indices
|
|
154
|
+
based on the similarity, potentially using provided templates for
|
|
155
|
+
clustering, or generating new templates.
|
|
156
|
+
|
|
157
|
+
:param data: A list containing dictionaries, each representing a
|
|
158
|
+
rule along with metadata.
|
|
159
|
+
:type data: List[Dict]
|
|
160
|
+
:param rule_key: The key in the dictionaries under `data` where the rule data
|
|
161
|
+
is stored.
|
|
162
|
+
:type rule_key: str
|
|
163
|
+
:param attribute_key: The key in the dictionaries under `data` where rule
|
|
164
|
+
attributes are stored.
|
|
165
|
+
:type attribute_key: str
|
|
166
|
+
|
|
167
|
+
:return: Updated list of dictionaries with an added 'class' key for cluster identification.
|
|
168
|
+
:rtype: List[Dict]
|
|
169
|
+
"""
|
|
170
|
+
if not data:
|
|
171
|
+
return data
|
|
172
|
+
if isinstance(data[0][rule_key], str):
|
|
173
|
+
if strip:
|
|
174
|
+
rules = [strip_context(entry[rule_key]) for entry in data]
|
|
175
|
+
else:
|
|
176
|
+
rules = [entry[rule_key] for entry in data]
|
|
177
|
+
|
|
178
|
+
else:
|
|
179
|
+
rules = [entry[rule_key] for entry in data]
|
|
180
|
+
|
|
181
|
+
attributes = (
|
|
182
|
+
[entry.get(attribute_key) for entry in data] if attribute_key else None
|
|
183
|
+
)
|
|
184
|
+
_, rule_to_cluster_dict = self.iterative_cluster(
|
|
185
|
+
rules, attributes, self.nodeMatch, self.edgeMatch
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
for index, entry in enumerate(data):
|
|
189
|
+
entry["class"] = rule_to_cluster_dict.get(index, None)
|
|
190
|
+
|
|
191
|
+
return data
|