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,421 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import itertools
|
|
3
|
+
from operator import eq
|
|
4
|
+
from typing import Callable, Optional, Union, List, Any, Dict
|
|
5
|
+
import networkx as nx
|
|
6
|
+
from networkx.algorithms import isomorphism
|
|
7
|
+
from networkx.algorithms.isomorphism import GraphMatcher
|
|
8
|
+
from networkx.algorithms.isomorphism import (
|
|
9
|
+
categorical_multiedge_match,
|
|
10
|
+
generic_node_match,
|
|
11
|
+
generic_edge_match,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
# Alias for any NetworkX graph type
|
|
15
|
+
graph_types = Union[nx.Graph, nx.DiGraph, nx.MultiGraph, nx.MultiDiGraph]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def find_graph_isomorphism(
|
|
19
|
+
G1: graph_types,
|
|
20
|
+
G2: graph_types,
|
|
21
|
+
node_match: Optional[Callable[[Dict[str, Any], Dict[str, Any]], bool]] = None,
|
|
22
|
+
edge_match: Optional[Callable[[Dict[str, Any], Dict[str, Any]], bool]] = None,
|
|
23
|
+
use_defaults: bool = True,
|
|
24
|
+
fast_invariant_check: bool = True,
|
|
25
|
+
logger: Optional[logging.Logger] = None,
|
|
26
|
+
) -> Optional[Dict[Any, Any]]:
|
|
27
|
+
"""Check whether two graphs are isomorphic and return the node-mapping.
|
|
28
|
+
|
|
29
|
+
:param G1: The first NetworkX graph to compare.
|
|
30
|
+
:type G1: nx.Graph | nx.DiGraph | nx.MultiGraph | nx.MultiDiGraph
|
|
31
|
+
:param G2: The second NetworkX graph to compare.
|
|
32
|
+
:type G2: nx.Graph | nx.DiGraph | nx.MultiGraph | nx.MultiDiGraph
|
|
33
|
+
:param node_match: Optional function taking two node attribute dicts
|
|
34
|
+
and returning True if they match.
|
|
35
|
+
:type node_match: callable or None
|
|
36
|
+
:param edge_match: Optional function taking two edge attribute dicts
|
|
37
|
+
and returning True if they match.
|
|
38
|
+
:type edge_match: callable or None
|
|
39
|
+
:param use_defaults: Whether to use default matchers when None.
|
|
40
|
+
:type use_defaults: bool
|
|
41
|
+
:param fast_invariant_check: Perform quick node/edge count and
|
|
42
|
+
degree sequence checks prior to matcher.
|
|
43
|
+
:type fast_invariant_check: bool
|
|
44
|
+
:param logger: Logger for debug messages. Defaults to root logger.
|
|
45
|
+
:type logger: logging.Logger or None
|
|
46
|
+
:return: A dict mapping nodes in G1 to nodes in G2 if isomorphic;
|
|
47
|
+
otherwise None.
|
|
48
|
+
:rtype: dict[Any, Any] or None
|
|
49
|
+
"""
|
|
50
|
+
log = logger or logging.getLogger(__name__)
|
|
51
|
+
|
|
52
|
+
# 1) Ensure same graph type
|
|
53
|
+
if type(G1) is not type(G2):
|
|
54
|
+
log.debug("Graph types differ: %r vs %r", type(G1), type(G2))
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
# 2) Quick invariants
|
|
58
|
+
if fast_invariant_check:
|
|
59
|
+
if G1.number_of_nodes() != G2.number_of_nodes():
|
|
60
|
+
log.debug(
|
|
61
|
+
"Node counts differ: %d vs %d",
|
|
62
|
+
G1.number_of_nodes(),
|
|
63
|
+
G2.number_of_nodes(),
|
|
64
|
+
)
|
|
65
|
+
return None
|
|
66
|
+
if G1.number_of_edges() != G2.number_of_edges():
|
|
67
|
+
log.debug(
|
|
68
|
+
"Edge counts differ: %d vs %d",
|
|
69
|
+
G1.number_of_edges(),
|
|
70
|
+
G2.number_of_edges(),
|
|
71
|
+
)
|
|
72
|
+
return None
|
|
73
|
+
degs1 = sorted(d for _, d in G1.degree())
|
|
74
|
+
degs2 = sorted(d for _, d in G2.degree())
|
|
75
|
+
if degs1 != degs2:
|
|
76
|
+
log.debug("Degree sequences differ")
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
# 3) Default matchers
|
|
80
|
+
if use_defaults:
|
|
81
|
+
if node_match is None:
|
|
82
|
+
node_match = isomorphism.categorical_node_match(
|
|
83
|
+
["element", "atom_map", "hcount"], ["*", 0, 0]
|
|
84
|
+
)
|
|
85
|
+
if edge_match is None:
|
|
86
|
+
edge_match = (
|
|
87
|
+
categorical_multiedge_match("order", 1)
|
|
88
|
+
if G1.is_multigraph()
|
|
89
|
+
else isomorphism.categorical_edge_match("order", 1)
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# 4) Select the correct matcher
|
|
93
|
+
if G1.is_multigraph():
|
|
94
|
+
Matcher = (
|
|
95
|
+
nx.algorithms.isomorphism.MultiDiGraphMatcher
|
|
96
|
+
if G1.is_directed()
|
|
97
|
+
else nx.algorithms.isomorphism.MultiGraphMatcher
|
|
98
|
+
)
|
|
99
|
+
else:
|
|
100
|
+
Matcher = (
|
|
101
|
+
nx.algorithms.isomorphism.DiGraphMatcher
|
|
102
|
+
if G1.is_directed()
|
|
103
|
+
else nx.algorithms.isomorphism.GraphMatcher
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
matcher = Matcher(G1, G2, node_match=node_match, edge_match=edge_match)
|
|
107
|
+
if matcher.is_isomorphic():
|
|
108
|
+
log.debug("Graphs are isomorphic; mapping found")
|
|
109
|
+
return matcher.mapping
|
|
110
|
+
else:
|
|
111
|
+
log.debug("Graphs are not isomorphic")
|
|
112
|
+
return None
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def graph_isomorphism(
|
|
116
|
+
graph_1: nx.Graph,
|
|
117
|
+
graph_2: nx.Graph,
|
|
118
|
+
node_match: Optional[Callable] = None,
|
|
119
|
+
edge_match: Optional[Callable] = None,
|
|
120
|
+
use_defaults: bool = False,
|
|
121
|
+
) -> bool:
|
|
122
|
+
"""Determines if two graphs are isomorphic, considering provided node and
|
|
123
|
+
edge matching functions. Uses default matching settings if none are
|
|
124
|
+
provided.
|
|
125
|
+
|
|
126
|
+
:param graph_1: The first graph to compare.
|
|
127
|
+
:type graph_1: nx.Graph
|
|
128
|
+
:param graph_2: The second graph to compare.
|
|
129
|
+
:type graph_2: nx.Graph
|
|
130
|
+
:param node_match: The function used to match nodes.
|
|
131
|
+
Uses default if None.
|
|
132
|
+
:type node_match: Optional[Callable]
|
|
133
|
+
:param edge_match: The function used to match edges.
|
|
134
|
+
Uses default if None.
|
|
135
|
+
:type edge_match: Optional[Callable]
|
|
136
|
+
|
|
137
|
+
:return: True if the graphs are isomorphic, False otherwise.
|
|
138
|
+
:rtype: bool
|
|
139
|
+
"""
|
|
140
|
+
# Define default node and edge attributes and match settings
|
|
141
|
+
if use_defaults:
|
|
142
|
+
node_label_names = ["element", "charge"]
|
|
143
|
+
node_label_default = ["*", 0]
|
|
144
|
+
edge_attribute = "order"
|
|
145
|
+
|
|
146
|
+
# Default node and edge match functions if not provided
|
|
147
|
+
if node_match is None:
|
|
148
|
+
node_match = generic_node_match(
|
|
149
|
+
node_label_names, node_label_default, [eq] * len(node_label_names)
|
|
150
|
+
)
|
|
151
|
+
if edge_match is None:
|
|
152
|
+
edge_match = generic_edge_match(edge_attribute, 1, eq)
|
|
153
|
+
|
|
154
|
+
# Perform the isomorphism check using NetworkX
|
|
155
|
+
return nx.is_isomorphic(
|
|
156
|
+
graph_1, graph_2, node_match=node_match, edge_match=edge_match
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def subgraph_isomorphism(
|
|
161
|
+
child_graph: nx.Graph,
|
|
162
|
+
parent_graph: nx.Graph,
|
|
163
|
+
node_label_names: List[str] = ["element", "charge"],
|
|
164
|
+
node_label_default: List[Any] = ["*", 0],
|
|
165
|
+
edge_attribute: str = "order",
|
|
166
|
+
use_filter: bool = False,
|
|
167
|
+
check_type: str = "induced", # "induced" or "monomorphism"
|
|
168
|
+
node_comparator: Optional[Callable[[Any, Any], bool]] = None,
|
|
169
|
+
edge_comparator: Optional[Callable[[Any, Any], bool]] = None,
|
|
170
|
+
) -> bool:
|
|
171
|
+
"""Enhanced checks if the child graph is a subgraph isomorphic to the
|
|
172
|
+
parent graph based on customizable node and edge attributes.
|
|
173
|
+
|
|
174
|
+
:param child_graph: The child graph.
|
|
175
|
+
:type child_graph: nx.Graph
|
|
176
|
+
:param parent_graph: The parent graph.
|
|
177
|
+
:type parent_graph: nx.Graph
|
|
178
|
+
:param node_label_names: Labels to compare.
|
|
179
|
+
:type node_label_names: List[str]
|
|
180
|
+
:param node_label_default: Defaults for missing node labels.
|
|
181
|
+
:type node_label_default: List[Any]
|
|
182
|
+
:param edge_attribute: The edge attribute to compare.
|
|
183
|
+
:type edge_attribute: str
|
|
184
|
+
:param use_filter: Whether to use pre-filters based on node and edge count.
|
|
185
|
+
:type use_filter: bool
|
|
186
|
+
:param check_type: "induced" (default) or "monomorphism" for the type of subgraph matching.
|
|
187
|
+
:type check_type: str
|
|
188
|
+
:param node_comparator: Custom comparator for node attributes.
|
|
189
|
+
:type node_comparator: Callable[[Any, Any], bool]
|
|
190
|
+
:param edge_comparator: Custom comparator for edge attributes.
|
|
191
|
+
:type edge_comparator: Callable[[Any, Any], bool]
|
|
192
|
+
|
|
193
|
+
:return: True if subgraph isomorphism is found, False otherwise.
|
|
194
|
+
:rtype: bool
|
|
195
|
+
"""
|
|
196
|
+
if use_filter:
|
|
197
|
+
# Initial quick filters based on node and edge counts
|
|
198
|
+
if len(child_graph) > len(parent_graph) or len(child_graph.edges) > len(
|
|
199
|
+
parent_graph.edges
|
|
200
|
+
):
|
|
201
|
+
return False
|
|
202
|
+
|
|
203
|
+
node_comparator = node_comparator or eq
|
|
204
|
+
edge_comparator = edge_comparator or eq
|
|
205
|
+
|
|
206
|
+
# Step 2: Every child node needs at least one compatible parent candidate.
|
|
207
|
+
for _, child_data in child_graph.nodes(data=True):
|
|
208
|
+
found_match = False
|
|
209
|
+
for _, parent_data in parent_graph.nodes(data=True):
|
|
210
|
+
match = True
|
|
211
|
+
# Compare only the 'element' and 'charge' attributes
|
|
212
|
+
for label, default in zip(node_label_names, node_label_default):
|
|
213
|
+
child_value = child_data.get(label, default)
|
|
214
|
+
parent_value = parent_data.get(label, default)
|
|
215
|
+
if not node_comparator(parent_value, child_value):
|
|
216
|
+
match = False
|
|
217
|
+
break
|
|
218
|
+
if match:
|
|
219
|
+
found_match = True
|
|
220
|
+
break
|
|
221
|
+
if not found_match:
|
|
222
|
+
return False
|
|
223
|
+
|
|
224
|
+
# Step 3: Every child edge label needs a compatible parent edge label.
|
|
225
|
+
# Node identifiers are deliberately irrelevant: the isomorphism has
|
|
226
|
+
# not been discovered yet.
|
|
227
|
+
if edge_attribute:
|
|
228
|
+
parent_edge_values = [
|
|
229
|
+
data.get(edge_attribute) for _, _, data in parent_graph.edges(data=True)
|
|
230
|
+
]
|
|
231
|
+
for _, _, child_data in child_graph.edges(data=True):
|
|
232
|
+
child_value = child_data.get(edge_attribute)
|
|
233
|
+
if not any(
|
|
234
|
+
edge_comparator(parent_value, child_value)
|
|
235
|
+
for parent_value in parent_edge_values
|
|
236
|
+
):
|
|
237
|
+
return False
|
|
238
|
+
|
|
239
|
+
# Setting up attribute comparison functions
|
|
240
|
+
node_comparator = node_comparator if node_comparator else eq
|
|
241
|
+
edge_comparator = edge_comparator if edge_comparator else eq
|
|
242
|
+
|
|
243
|
+
# Creating match conditions for nodes and edges based on custom or default comparators
|
|
244
|
+
node_match = generic_node_match(
|
|
245
|
+
node_label_names, node_label_default, [node_comparator] * len(node_label_names)
|
|
246
|
+
)
|
|
247
|
+
edge_match = (
|
|
248
|
+
generic_edge_match(edge_attribute, None, edge_comparator)
|
|
249
|
+
if edge_attribute
|
|
250
|
+
else None
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
# Graph matching setup
|
|
254
|
+
if child_graph.is_directed() != parent_graph.is_directed():
|
|
255
|
+
return False
|
|
256
|
+
if child_graph.is_multigraph() or parent_graph.is_multigraph():
|
|
257
|
+
raise NotImplementedError("subgraph_isomorphism does not support multigraphs")
|
|
258
|
+
matcher_cls = (
|
|
259
|
+
nx.algorithms.isomorphism.DiGraphMatcher
|
|
260
|
+
if parent_graph.is_directed()
|
|
261
|
+
else GraphMatcher
|
|
262
|
+
)
|
|
263
|
+
matcher = matcher_cls(
|
|
264
|
+
parent_graph, child_graph, node_match=node_match, edge_match=edge_match
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
# Executing the matching based on specified type
|
|
268
|
+
if check_type == "induced":
|
|
269
|
+
return matcher.subgraph_is_isomorphic()
|
|
270
|
+
else:
|
|
271
|
+
return matcher.subgraph_is_monomorphic()
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def maximum_connected_common_subgraph(
|
|
275
|
+
graph_1: nx.Graph,
|
|
276
|
+
graph_2: nx.Graph,
|
|
277
|
+
node_label_names: List[str] = ["element", "charge"],
|
|
278
|
+
node_label_default: List[Any] = ["*", 0],
|
|
279
|
+
edge_attribute: str = "standard_order",
|
|
280
|
+
) -> nx.Graph:
|
|
281
|
+
"""Computes the largest connected common subgraph (MCS) between two graphs
|
|
282
|
+
using subgraph isomorphism based on customizable node and edge attributes.
|
|
283
|
+
|
|
284
|
+
The function iterates over subsets of nodes from the smaller graph—starting from the largest
|
|
285
|
+
possible subgraph size down to 1—and returns the first (largest) candidate that is connected
|
|
286
|
+
and is isomorphic to a subgraph of the larger graph.
|
|
287
|
+
|
|
288
|
+
:param graph_1: The first graph for comparison.
|
|
289
|
+
:type graph_1: nx.Graph
|
|
290
|
+
:param graph_2: The second graph for comparison.
|
|
291
|
+
:type graph_2: nx.Graph
|
|
292
|
+
:param node_label_names: List of node attribute names used for matching.
|
|
293
|
+
:type node_label_names: List[str]
|
|
294
|
+
:param node_label_default: Default values for missing node attributes.
|
|
295
|
+
:type node_label_default: List[Any]
|
|
296
|
+
:param edge_attribute: The edge attribute to compare.
|
|
297
|
+
:type edge_attribute: str
|
|
298
|
+
|
|
299
|
+
:return: A graph representing the largest connected common subgraph found; if none exists, returns an empty graph.
|
|
300
|
+
:rtype: nx.Graph
|
|
301
|
+
"""
|
|
302
|
+
node_match = generic_node_match(
|
|
303
|
+
node_label_names, node_label_default, [eq] * len(node_label_names)
|
|
304
|
+
)
|
|
305
|
+
edge_match = generic_edge_match(edge_attribute, 1, eq)
|
|
306
|
+
|
|
307
|
+
if graph_1.is_directed() != graph_2.is_directed():
|
|
308
|
+
return nx.Graph()
|
|
309
|
+
if graph_1.is_multigraph() or graph_2.is_multigraph():
|
|
310
|
+
raise NotImplementedError(
|
|
311
|
+
"maximum_connected_common_subgraph does not support multigraphs"
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
# Determine which graph is smaller for efficiency.
|
|
315
|
+
if graph_1.number_of_nodes() <= graph_2.number_of_nodes():
|
|
316
|
+
smaller_graph, larger_graph = graph_1, graph_2
|
|
317
|
+
else:
|
|
318
|
+
smaller_graph, larger_graph = graph_2, graph_1
|
|
319
|
+
|
|
320
|
+
num_nodes_smaller = smaller_graph.number_of_nodes()
|
|
321
|
+
# Iterate over possible subgraph sizes from the largest to 1.
|
|
322
|
+
for subgraph_size in range(num_nodes_smaller, 0, -1):
|
|
323
|
+
for nodes_subset in itertools.combinations(
|
|
324
|
+
smaller_graph.nodes(), subgraph_size
|
|
325
|
+
):
|
|
326
|
+
candidate_subgraph = smaller_graph.subgraph(nodes_subset)
|
|
327
|
+
# If the subgraph has more than one node, check it is connected.
|
|
328
|
+
if candidate_subgraph.number_of_nodes() > 1:
|
|
329
|
+
connected = (
|
|
330
|
+
nx.is_weakly_connected(candidate_subgraph)
|
|
331
|
+
if candidate_subgraph.is_directed()
|
|
332
|
+
else nx.is_connected(candidate_subgraph)
|
|
333
|
+
)
|
|
334
|
+
if not connected:
|
|
335
|
+
continue
|
|
336
|
+
|
|
337
|
+
# Check for subgraph isomorphism in the larger graph.
|
|
338
|
+
matcher_cls = (
|
|
339
|
+
nx.algorithms.isomorphism.DiGraphMatcher
|
|
340
|
+
if larger_graph.is_directed()
|
|
341
|
+
else GraphMatcher
|
|
342
|
+
)
|
|
343
|
+
matcher = matcher_cls(
|
|
344
|
+
larger_graph,
|
|
345
|
+
candidate_subgraph,
|
|
346
|
+
node_match=node_match,
|
|
347
|
+
edge_match=edge_match,
|
|
348
|
+
)
|
|
349
|
+
if matcher.subgraph_is_isomorphic():
|
|
350
|
+
return candidate_subgraph.copy()
|
|
351
|
+
|
|
352
|
+
return smaller_graph.__class__()
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def heuristics_MCCS(
|
|
356
|
+
graphs: List[nx.Graph],
|
|
357
|
+
node_label_names: List[str] = ["element", "charge"],
|
|
358
|
+
node_label_default: List[Any] = ["*", 0],
|
|
359
|
+
edge_attribute: str = "standard_order",
|
|
360
|
+
) -> nx.Graph:
|
|
361
|
+
"""Computes the Maximum Connected Common Subgraph (MCCS) over a list of
|
|
362
|
+
graphs using a heuristic approach.
|
|
363
|
+
|
|
364
|
+
This function computes the MCCS between the first two graphs using the
|
|
365
|
+
`maximum_connected_common_subgraph` function based on customizable node and edge attributes.
|
|
366
|
+
For more than two graphs, it iteratively updates the common subgraph by calculating the MCCS
|
|
367
|
+
between the current common subgraph and each subsequent graph. An early exit occurs if the
|
|
368
|
+
intermediate common subgraph becomes empty.
|
|
369
|
+
|
|
370
|
+
:param graphs: A list of networkx graphs for which the common subgraph is to be computed.
|
|
371
|
+
:type graphs: List[nx.Graph]
|
|
372
|
+
:param node_label_names: List of node attribute names used for matching.
|
|
373
|
+
:type node_label_names: List[str]
|
|
374
|
+
:param node_label_default: Default values for missing node attributes.
|
|
375
|
+
:type node_label_default: List[Any]
|
|
376
|
+
:param edge_attribute: The edge attribute to compare.
|
|
377
|
+
:type edge_attribute: str
|
|
378
|
+
|
|
379
|
+
:return: Maximum connected common subgraph, or an empty graph when none
|
|
380
|
+
exists.
|
|
381
|
+
:rtype: nx.Graph
|
|
382
|
+
|
|
383
|
+
:raises ValueError: If the input list of graphs is empty.
|
|
384
|
+
"""
|
|
385
|
+
if not graphs:
|
|
386
|
+
raise ValueError("Input list of graphs is empty.")
|
|
387
|
+
|
|
388
|
+
if len(graphs) == 1:
|
|
389
|
+
return graphs[0].copy()
|
|
390
|
+
|
|
391
|
+
# Handle the two-graph case explicitly.
|
|
392
|
+
if len(graphs) == 2:
|
|
393
|
+
return maximum_connected_common_subgraph(
|
|
394
|
+
graphs[0],
|
|
395
|
+
graphs[1],
|
|
396
|
+
node_label_names=node_label_names,
|
|
397
|
+
node_label_default=node_label_default,
|
|
398
|
+
edge_attribute=edge_attribute,
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
# Iteratively compute the MCCS for more than two graphs.
|
|
402
|
+
current_mcs = maximum_connected_common_subgraph(
|
|
403
|
+
graphs[0],
|
|
404
|
+
graphs[1],
|
|
405
|
+
node_label_names=node_label_names,
|
|
406
|
+
node_label_default=node_label_default,
|
|
407
|
+
edge_attribute=edge_attribute,
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
for graph in graphs[2:]:
|
|
411
|
+
if current_mcs.number_of_nodes() == 0:
|
|
412
|
+
break # Early exit if no common subgraph remains.
|
|
413
|
+
current_mcs = maximum_connected_common_subgraph(
|
|
414
|
+
current_mcs,
|
|
415
|
+
graph,
|
|
416
|
+
node_label_names=node_label_names,
|
|
417
|
+
node_label_default=node_label_default,
|
|
418
|
+
edge_attribute=edge_attribute,
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
return current_mcs
|