synkit 1.1.0__tar.gz → 1.1.1__tar.gz
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-1.1.0 → synkit-1.1.1}/PKG-INFO +1 -1
- {synkit-1.1.0 → synkit-1.1.1}/pyproject.toml +1 -1
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Topo/canon.py +59 -254
- synkit-1.1.1/synkit/CRN/Topo/wl_canon.py +301 -0
- synkit-1.1.1/synkit/Graph/Matcher/auto_est.py +779 -0
- synkit-1.1.1/synkit/Graph/Matcher/automorphism.py +307 -0
- synkit-1.1.1/synkit/Graph/Matcher/dedup_matches.py +243 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Matcher/partial_matcher.py +5 -1
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Reactor/syn_reactor.py +16 -5
- synkit-1.1.0/synkit/Graph/Matcher/auto_est.py +0 -496
- synkit-1.1.0/synkit/Graph/Matcher/automorphism.py +0 -292
- {synkit-1.1.0 → synkit-1.1.1}/.gitignore +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/LICENSE +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/README.md +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/DAG/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/DAG/crn.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/DAG/dag.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/DAG/dcrn.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/DAG/mod_crn.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/DAG/sf.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/DAG/target_dag.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Hypergraph/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Hypergraph/backend.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Hypergraph/conversion.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Hypergraph/dag.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Hypergraph/hyperedge.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Hypergraph/hypergraph.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Hypergraph/rxn.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Path/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Path/realizability.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Petri/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Petri/analyzer.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Petri/net.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Petri/persistence.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Petri/semiflows.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Petri/structure.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Props/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Props/deficiency.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Props/injectivity.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Props/stoich.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Props/thermo.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Props/utils.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Stochastic/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Topo/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/Topo/automorphism.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/configs/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/configs/loader.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/configs/models.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/constants.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/crn_formula.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/enumerator.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/exceptions.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/explorer.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/helpers.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/motif.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/network.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/pathway.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/properties.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/reaction.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/utils.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/dev_crn/viz.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/CRN/viz/crn_vis.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Cluster/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Cluster/butina.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Fingerprint/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Fingerprint/fp_calculator.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Fingerprint/smiles_featurizer.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Fingerprint/transformation_fp.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Molecule/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Molecule/atom_features.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Molecule/descriptors.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Molecule/formula.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Molecule/graph_annotator.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Molecule/standardize.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Molecule/valence.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Reaction/Mapper/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Reaction/Mapper/wl_mapper.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Reaction/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Reaction/aam_validator.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Reaction/balance_check.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Reaction/canon_rsmi.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Reaction/cleaning.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Reaction/deionize.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Reaction/fix_aam.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Reaction/neutralize.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Reaction/radical_wildcard.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Reaction/standardize.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/Reaction/tautomerize.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Chem/utils.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Data/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Data/gen_partial_aam.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Canon/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Canon/canon_algs.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Canon/canon_graph.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Canon/nauty.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Context/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Context/hier_context.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Context/radius_expand.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Feature/Descriptors/topology.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Feature/Fingerprint/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Feature/Fingerprint/wl_rxn_fps.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Feature/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Feature/graph_descriptors.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Feature/graph_fps.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Feature/graph_signature.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Feature/hash_fps.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Feature/morgan_fps.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Feature/path_fps.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Feature/wl_hash.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Hyrogen/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Hyrogen/_misc.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Hyrogen/hcomplete.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Hyrogen/hextend.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/ITS/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/ITS/its_builder.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/ITS/its_construction.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/ITS/its_decompose.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/ITS/its_destruction.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/ITS/its_expand.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/ITS/its_relabel.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/ITS/normalize_aam.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/ITS/partial_its.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/MTG/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/MTG/group_comp.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/MTG/groupoid.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/MTG/mcs_matcher.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/MTG/mtg.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/MTG/mtg_explore.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/MTG/utils.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Matcher/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Matcher/approx_mcs.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Matcher/batch_cluster.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Matcher/graph_cluster.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Matcher/graph_matcher.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Matcher/graph_morphism.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Matcher/mcs_matcher.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Matcher/multi_turbo_iso.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Matcher/orbit.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Matcher/sing.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Matcher/subgraph_matcher.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Matcher/turbo_iso.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Matcher/wl_sel.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Wildcard/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Wildcard/fuse_graph.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Wildcard/graph_wc.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Wildcard/its_merge.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Wildcard/radwc.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Wildcard/wc_matcher.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/Wildcard/wildcard.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/canon_graph.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/syn_graph.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Graph/utils.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/chem_converter.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/combinatorial/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/combinatorial/gml_to_graph.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/combinatorial/graph_to_gml.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/combinatorial/graph_to_smarts.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/combinatorial/smarts_expander.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/combinatorial/smarts_generalizer.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/combinatorial/smarts_to_graph.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/data_io.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/data_process.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/debug.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/dg_to_gml.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/gml_to_nx.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/graph_to_mol.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/mol_to_graph.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/nx_to_gml.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/IO/smiles_to_id.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Apply/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Apply/reactor_rule.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Apply/retro_reactor.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Apply/rule_matcher.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Apply/rule_rbl.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Compose/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Compose/compose_rule.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Compose/rule_compose.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Compose/rule_mapping.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Compose/seq_comp.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Compose/valence_constrain.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Modify/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Modify/implict_rule.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Modify/longest_path.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Modify/molecule_rule.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Modify/prune_templates.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Modify/rule_utils.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/Modify/strip_rule.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Rule/syn_rule.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/MSR/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/MSR/multi_steps.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/MSR/path_finder.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Metrics/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Metrics/_base.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Metrics/_plot.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Metrics/_ranking.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Reactor/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Reactor/batch_reactor.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Reactor/benchmark.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Reactor/imba_engine.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Reactor/mod_aam.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Reactor/mod_reactor.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Reactor/partial_engine.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Reactor/post_syn.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Reactor/rbl_engine.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Reactor/rule_filter.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Reactor/single_predictor.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/Reactor/strategy.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Synthesis/reactor_utils.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Utils/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Utils/utils.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Vis/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Vis/chemical_space.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Vis/crn_vis.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Vis/embedding.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Vis/graph_visualizer.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Vis/pdf_writer.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Vis/rule_vis.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/Vis/rxn_vis.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/__init__.py +0 -0
- {synkit-1.1.0 → synkit-1.1.1}/synkit/examples.py +0 -0
|
@@ -10,19 +10,20 @@ from ..Hypergraph.backend import _CRNGraphBackend
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
# -------------------------------------------------------------------------
|
|
13
|
-
# Canon: Nauty-style
|
|
13
|
+
# Canon: Exact Nauty-style individualization + refinement (no heuristic pruning)
|
|
14
14
|
# -------------------------------------------------------------------------
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class CRNCanonicalizer(_CRNGraphBackend):
|
|
18
18
|
"""
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
Exact canonicalization and automorphism enumeration for a CRN via
|
|
20
|
+
individualization-refinement (IR) search.
|
|
21
|
+
|
|
22
|
+
This implementation is **exact**:
|
|
23
|
+
- No branch-shape skipping
|
|
24
|
+
- No prefix/label pruning that could drop valid automorphisms
|
|
25
|
+
- Enumerates all permutations achieving the minimal canonical label
|
|
26
|
+
(these correspond to automorphisms w.r.t. the labeling function)
|
|
26
27
|
"""
|
|
27
28
|
|
|
28
29
|
def __init__(
|
|
@@ -35,24 +36,6 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
35
36
|
integer_ids: bool = False,
|
|
36
37
|
include_stoich: bool = True,
|
|
37
38
|
) -> None:
|
|
38
|
-
"""
|
|
39
|
-
Initialize a canonicalizer for a CRN.
|
|
40
|
-
|
|
41
|
-
:param hg: Hypergraph to canonicalize.
|
|
42
|
-
:type hg: CRNHyperGraph
|
|
43
|
-
:param include_rule: If True, work on bipartite species→reaction→species
|
|
44
|
-
graph; if False, use collapsed species graph.
|
|
45
|
-
:type include_rule: bool
|
|
46
|
-
:param node_attr_keys: Node attribute keys used in partition refinement
|
|
47
|
-
and canonical label construction.
|
|
48
|
-
:type node_attr_keys: Iterable[str]
|
|
49
|
-
:param edge_attr_keys: Edge attribute keys included in canonical labels.
|
|
50
|
-
:type edge_attr_keys: Iterable[str]
|
|
51
|
-
:param integer_ids: If True, use integer node ids in the bipartite view.
|
|
52
|
-
:type integer_ids: bool
|
|
53
|
-
:param include_stoich: If True, include stoichiometry on bipartite edges.
|
|
54
|
-
:type include_stoich: bool
|
|
55
|
-
"""
|
|
56
39
|
super().__init__(
|
|
57
40
|
hg,
|
|
58
41
|
include_rule=include_rule,
|
|
@@ -63,10 +46,6 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
63
46
|
self.edge_attr_keys: Tuple[str, ...] = tuple(edge_attr_keys)
|
|
64
47
|
|
|
65
48
|
def __repr__(self) -> str:
|
|
66
|
-
"""
|
|
67
|
-
:returns: String representation of the canonicalizer.
|
|
68
|
-
:rtype: str
|
|
69
|
-
"""
|
|
70
49
|
return (
|
|
71
50
|
f"CRNCanonicalizer(include_rule={self.include_rule}, "
|
|
72
51
|
f"node_attr_keys={self.node_attr_keys}, "
|
|
@@ -78,37 +57,19 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
78
57
|
|
|
79
58
|
@staticmethod
|
|
80
59
|
def _freeze(x: Any) -> Any:
|
|
81
|
-
"""
|
|
82
|
-
Convert nested containers into hashable equivalents.
|
|
83
|
-
|
|
84
|
-
Lists become tuples; dicts become frozensets of sorted (key, value)
|
|
85
|
-
pairs; other types are returned unchanged.
|
|
86
|
-
|
|
87
|
-
:param x: Object to convert.
|
|
88
|
-
:type x: Any
|
|
89
|
-
:returns: Hashable representation of x.
|
|
90
|
-
:rtype: Any
|
|
91
|
-
"""
|
|
60
|
+
"""Convert nested containers into hashable equivalents."""
|
|
92
61
|
if isinstance(x, list):
|
|
93
62
|
return tuple(CRNCanonicalizer._freeze(v) for v in x)
|
|
94
63
|
if isinstance(x, dict):
|
|
95
64
|
return frozenset(
|
|
96
65
|
(k, CRNCanonicalizer._freeze(v)) for k, v in sorted(x.items())
|
|
97
66
|
)
|
|
67
|
+
if isinstance(x, set):
|
|
68
|
+
return tuple(sorted(CRNCanonicalizer._freeze(v) for v in x))
|
|
98
69
|
return x
|
|
99
70
|
|
|
100
71
|
def _init_part(self, G: nx.Graph) -> List[List[Any]]:
|
|
101
|
-
"""
|
|
102
|
-
Build the initial node partition for refinement.
|
|
103
|
-
|
|
104
|
-
Nodes are grouped by tuples of node_attr_keys. If no node_attr_keys
|
|
105
|
-
are provided, all nodes start in a single cell.
|
|
106
|
-
|
|
107
|
-
:param G: Graph whose nodes are to be partitioned.
|
|
108
|
-
:type G: nx.Graph
|
|
109
|
-
:returns: List of partition cells, each a list of nodes.
|
|
110
|
-
:rtype: List[List[Any]]
|
|
111
|
-
"""
|
|
72
|
+
"""Initial partition by node attributes."""
|
|
112
73
|
if not self.node_attr_keys:
|
|
113
74
|
return [sorted(G.nodes())]
|
|
114
75
|
buckets: Dict[Tuple[Any, ...], List[Any]] = {}
|
|
@@ -128,19 +89,13 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
128
89
|
part: List[List[Any]],
|
|
129
90
|
) -> Tuple[Any, ...]:
|
|
130
91
|
"""
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
:param v: Node whose signature is computed.
|
|
139
|
-
:type v: Any
|
|
140
|
-
:param part: Current node partition.
|
|
141
|
-
:type part: List[List[Any]]
|
|
142
|
-
:returns: Signature tuple used to split cells.
|
|
143
|
-
:rtype: Tuple[Any, ...]
|
|
92
|
+
Refinement signature for node v under current partition.
|
|
93
|
+
|
|
94
|
+
Uses:
|
|
95
|
+
- node attributes
|
|
96
|
+
- (in_degree, out_degree)
|
|
97
|
+
- neighbor counts per cell (undirected union for directed graphs)
|
|
98
|
+
- multiset of outgoing edge attributes
|
|
144
99
|
"""
|
|
145
100
|
node_attrs = tuple(
|
|
146
101
|
self._freeze(G.nodes[v].get(a, None)) for a in self.node_attr_keys
|
|
@@ -156,7 +111,8 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
156
111
|
|
|
157
112
|
counts: List[int] = []
|
|
158
113
|
for cell in part:
|
|
159
|
-
|
|
114
|
+
s = set(cell)
|
|
115
|
+
counts.append(sum(1 for n in nbrs if n in s))
|
|
160
116
|
counts_t = tuple(counts)
|
|
161
117
|
|
|
162
118
|
edge_mult: List[Tuple[Any, ...]] = []
|
|
@@ -174,56 +130,40 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
174
130
|
return (node_attrs, degree, counts_t, edge_mult_t)
|
|
175
131
|
|
|
176
132
|
def _refine(self, G: nx.DiGraph, part: List[List[Any]]) -> List[List[Any]]:
|
|
177
|
-
"""
|
|
178
|
-
Refine a partition until no further splits occur.
|
|
179
|
-
|
|
180
|
-
Each non-singleton cell is split by grouping nodes with identical
|
|
181
|
-
signatures from :meth:`_sig`. Refinement continues until stable.
|
|
182
|
-
|
|
183
|
-
:param G: Graph to refine.
|
|
184
|
-
:type G: nx.DiGraph
|
|
185
|
-
:param part: Current node partition.
|
|
186
|
-
:type part: List[List[Any]]
|
|
187
|
-
:returns: Refined partition.
|
|
188
|
-
:rtype: List[List[Any]]
|
|
189
|
-
"""
|
|
133
|
+
"""Refine partition until stable (exact, deterministic)."""
|
|
190
134
|
changed = True
|
|
191
|
-
cache: Dict[Any, Tuple[Any, ...]] = {}
|
|
135
|
+
cache: Dict[Tuple[Any, int], Tuple[Any, ...]] = {}
|
|
192
136
|
while changed:
|
|
193
137
|
changed = False
|
|
194
138
|
new_part: List[List[Any]] = []
|
|
139
|
+
# note: cache depends on part, but we keep it simple & exact:
|
|
140
|
+
# cache key includes an epoch id via id(part) to avoid reusing across parts.
|
|
141
|
+
epoch = id(tuple(tuple(c) for c in part))
|
|
195
142
|
for cell in part:
|
|
196
143
|
if len(cell) <= 1:
|
|
197
144
|
new_part.append(cell)
|
|
198
145
|
continue
|
|
199
146
|
sigs: Dict[Tuple[Any, ...], List[Any]] = {}
|
|
200
147
|
for v in cell:
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
148
|
+
ck = (v, epoch)
|
|
149
|
+
if ck not in cache:
|
|
150
|
+
cache[ck] = self._sig(G, v, part)
|
|
151
|
+
s = cache[ck]
|
|
204
152
|
sigs.setdefault(s, []).append(v)
|
|
153
|
+
|
|
205
154
|
if len(sigs) > 1:
|
|
206
155
|
changed = True
|
|
207
156
|
for s in sorted(sigs.keys()):
|
|
208
157
|
new_part.append(sorted(sigs[s]))
|
|
209
158
|
else:
|
|
210
|
-
new_part.append(cell)
|
|
159
|
+
new_part.append(sorted(cell))
|
|
211
160
|
part = new_part
|
|
212
161
|
return part
|
|
213
162
|
|
|
214
163
|
def _label(self, G: nx.DiGraph, perm: List[Any]) -> str:
|
|
215
164
|
"""
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
The label encodes node attributes in order, plus the full adjacency
|
|
219
|
-
pattern and selected edge attributes for all ordered node pairs.
|
|
220
|
-
|
|
221
|
-
:param G: Graph to label.
|
|
222
|
-
:type G: nx.DiGraph
|
|
223
|
-
:param perm: Full node permutation (ordering).
|
|
224
|
-
:type perm: List[Any]
|
|
225
|
-
:returns: Canonical label string for this permutation.
|
|
226
|
-
:rtype: str
|
|
165
|
+
Canonical label string for a full node permutation.
|
|
166
|
+
Deterministic and exact (no approximations).
|
|
227
167
|
"""
|
|
228
168
|
node_seg = "|".join(
|
|
229
169
|
":".join(
|
|
@@ -250,29 +190,6 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
250
190
|
edge_seg = "|".join(edge_bits)
|
|
251
191
|
return node_seg + "||" + edge_seg
|
|
252
192
|
|
|
253
|
-
def _partial_label(self, G: nx.DiGraph, prefix: List[Any]) -> str:
|
|
254
|
-
"""
|
|
255
|
-
Build a partial label for a permutation prefix.
|
|
256
|
-
|
|
257
|
-
A long sequence of ``'{'`` characters is appended so that partial
|
|
258
|
-
labels compare lexicographically larger than any full label with
|
|
259
|
-
the same prefix, enabling safe pruning.
|
|
260
|
-
|
|
261
|
-
:param G: Graph to label.
|
|
262
|
-
:type G: nx.DiGraph
|
|
263
|
-
:param prefix: Partial node permutation.
|
|
264
|
-
:type prefix: List[Any]
|
|
265
|
-
:returns: Partial label string.
|
|
266
|
-
:rtype: str
|
|
267
|
-
"""
|
|
268
|
-
node_seg = "|".join(
|
|
269
|
-
":".join(
|
|
270
|
-
str(self._freeze(G.nodes[v].get(a, ""))) for a in self.node_attr_keys
|
|
271
|
-
)
|
|
272
|
-
for v in prefix
|
|
273
|
-
)
|
|
274
|
-
return node_seg + "{" * 1000
|
|
275
|
-
|
|
276
193
|
def _search(
|
|
277
194
|
self,
|
|
278
195
|
G: nx.DiGraph,
|
|
@@ -287,29 +204,9 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
287
204
|
timeout_sec: Optional[float],
|
|
288
205
|
) -> bool:
|
|
289
206
|
"""
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
:type G: nx.DiGraph
|
|
294
|
-
:param part: Current node partition.
|
|
295
|
-
:type part: List[List[Any]]
|
|
296
|
-
:param prefix: Current permutation prefix.
|
|
297
|
-
:type prefix: List[Any]
|
|
298
|
-
:param best: Dict with keys ``"label"`` and ``"perm"`` for the best
|
|
299
|
-
full label and permutation seen so far.
|
|
300
|
-
:type best: Dict[str, Optional[str]]
|
|
301
|
-
:param perms: List to collect permutations that achieve the best label.
|
|
302
|
-
:type perms: List[List[Any]]
|
|
303
|
-
:param depth: Current recursion depth.
|
|
304
|
-
:type depth: int
|
|
305
|
-
:param max_depth: Optional maximum recursion depth; None for unlimited.
|
|
306
|
-
:type max_depth: Optional[int]
|
|
307
|
-
:param start: Start time (:func:`time.time`) for timeout accounting.
|
|
308
|
-
:type start: float
|
|
309
|
-
:param timeout_sec: Optional wall-clock timeout in seconds.
|
|
310
|
-
:type timeout_sec: Optional[float]
|
|
311
|
-
:returns: True if the search stopped early due to timeout/depth.
|
|
312
|
-
:rtype: bool
|
|
207
|
+
Exact recursive IR search for minimal canonical label.
|
|
208
|
+
|
|
209
|
+
Returns True only if stopped early due to max_depth/timeout.
|
|
313
210
|
"""
|
|
314
211
|
if timeout_sec is not None and (time.time() - start) > timeout_sec:
|
|
315
212
|
return True
|
|
@@ -318,32 +215,29 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
318
215
|
|
|
319
216
|
part = self._refine(G, part)
|
|
320
217
|
|
|
321
|
-
# Fully discrete partition:
|
|
218
|
+
# Fully discrete partition: finalize permutation and score it.
|
|
322
219
|
if all(len(c) == 1 for c in part):
|
|
323
220
|
perm = prefix + [v for c in part for v in c]
|
|
324
221
|
lab = self._label(G, perm)
|
|
325
222
|
if best["label"] is None or lab < best["label"]:
|
|
326
|
-
best["label"], best["perm"] = lab, perm
|
|
223
|
+
best["label"], best["perm"] = lab, perm # type: ignore[assignment]
|
|
327
224
|
perms.clear()
|
|
328
225
|
perms.append(perm)
|
|
329
226
|
elif lab == best["label"]:
|
|
330
227
|
perms.append(perm)
|
|
331
228
|
return False
|
|
332
229
|
|
|
333
|
-
# Choose
|
|
230
|
+
# Choose a non-singleton cell (deterministic choice keeps exactness).
|
|
334
231
|
idx = next(i for i, c in enumerate(part) if len(c) > 1)
|
|
335
|
-
cell = part[idx]
|
|
336
|
-
cell_sorted = sorted(cell)
|
|
232
|
+
cell = sorted(part[idx])
|
|
337
233
|
|
|
338
|
-
for v in
|
|
234
|
+
for v in cell:
|
|
339
235
|
rest = [w for w in cell if w != v]
|
|
340
236
|
new_part = (
|
|
341
237
|
part[:idx] + [[v]] + ([sorted(rest)] if rest else []) + part[idx + 1 :]
|
|
342
238
|
)
|
|
343
239
|
pref = prefix + [v]
|
|
344
|
-
|
|
345
|
-
if best["label"] is not None and p_lab > best["label"]:
|
|
346
|
-
continue
|
|
240
|
+
|
|
347
241
|
if self._search(
|
|
348
242
|
G,
|
|
349
243
|
new_part,
|
|
@@ -360,14 +254,7 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
360
254
|
|
|
361
255
|
@staticmethod
|
|
362
256
|
def _orbits_from_perms(perms: List[List[Any]]) -> List[Set[Any]]:
|
|
363
|
-
"""
|
|
364
|
-
Derive node orbits from a list of automorphism permutations.
|
|
365
|
-
|
|
366
|
-
:param perms: List of permutations (each a list of nodes).
|
|
367
|
-
:type perms: List[List[Any]]
|
|
368
|
-
:returns: List of disjoint sets of nodes, one per orbit.
|
|
369
|
-
:rtype: List[Set[Any]]
|
|
370
|
-
"""
|
|
257
|
+
"""Derive node orbits from a list of automorphism permutations."""
|
|
371
258
|
if not perms:
|
|
372
259
|
return []
|
|
373
260
|
orbit_map: Dict[Any, int] = {}
|
|
@@ -401,23 +288,13 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
401
288
|
def _maps_from_perms(
|
|
402
289
|
ref: List[Any], perms: List[List[Any]]
|
|
403
290
|
) -> List[Dict[Any, Any]]:
|
|
404
|
-
"""
|
|
405
|
-
Convert permutations into mapping dicts relative to a reference order.
|
|
406
|
-
|
|
407
|
-
:param ref: Reference permutation (canonical ordering of nodes).
|
|
408
|
-
:type ref: List[Any]
|
|
409
|
-
:param perms: List of permutations to convert.
|
|
410
|
-
:type perms: List[List[Any]]
|
|
411
|
-
:returns: List of mappings {ref_node -> perm_node}.
|
|
412
|
-
:rtype: List[Dict[Any, Any]]
|
|
413
|
-
"""
|
|
291
|
+
"""Convert permutations into mapping dicts relative to a reference order."""
|
|
414
292
|
maps: List[Dict[Any, Any]] = []
|
|
415
293
|
n = len(ref)
|
|
416
294
|
for p in perms:
|
|
417
295
|
if len(p) != n:
|
|
418
296
|
continue
|
|
419
|
-
|
|
420
|
-
maps.append(m)
|
|
297
|
+
maps.append({ref[i]: p[i] for i in range(n)})
|
|
421
298
|
return maps
|
|
422
299
|
|
|
423
300
|
def _canon(
|
|
@@ -433,21 +310,7 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
433
310
|
List[Dict[Any, Any]],
|
|
434
311
|
bool,
|
|
435
312
|
]:
|
|
436
|
-
"""
|
|
437
|
-
Compute canonical graph, minimal permutations, orbits and mappings.
|
|
438
|
-
|
|
439
|
-
:param max_depth: Optional maximum recursion depth; None for unlimited.
|
|
440
|
-
:type max_depth: Optional[int]
|
|
441
|
-
:param timeout_sec: Optional wall-clock timeout in seconds.
|
|
442
|
-
:type timeout_sec: Optional[float]
|
|
443
|
-
:returns: Tuple (G_can, perm, perms, orbits, maps, early_stop) where
|
|
444
|
-
G_can is the canonical graph, perm is a representative
|
|
445
|
-
minimal permutation, perms is the list of all minimal
|
|
446
|
-
permutations, orbits are node orbits, maps are mapping
|
|
447
|
-
dicts, and early_stop indicates early termination.
|
|
448
|
-
:rtype: Tuple[nx.DiGraph, List[Any], List[List[Any]], List[Set[Any]], List[Dict[Any, Any]], bool]
|
|
449
|
-
:raises RuntimeError: If no canonical form is found (e.g. due to early stop).
|
|
450
|
-
"""
|
|
313
|
+
"""Compute canonical graph, minimal permutations, orbits and mappings (exact)."""
|
|
451
314
|
G = self.G
|
|
452
315
|
best: Dict[str, Optional[str]] = {"label": None, "perm": None}
|
|
453
316
|
perms: List[List[Any]] = []
|
|
@@ -466,7 +329,7 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
466
329
|
timeout_sec=timeout_sec,
|
|
467
330
|
)
|
|
468
331
|
|
|
469
|
-
perm = best
|
|
332
|
+
perm = best.get("perm") # type: ignore[assignment]
|
|
470
333
|
if perm is None:
|
|
471
334
|
raise RuntimeError(
|
|
472
335
|
f"Canonical form not found; early stop (max_depth={max_depth}, timeout_sec={timeout_sec})"
|
|
@@ -487,16 +350,7 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
487
350
|
max_depth: Optional[int] = None,
|
|
488
351
|
timeout_sec: Optional[float] = None,
|
|
489
352
|
) -> nx.DiGraph:
|
|
490
|
-
"""
|
|
491
|
-
Return the canonical relabeled graph.
|
|
492
|
-
|
|
493
|
-
:param max_depth: Optional maximum recursion depth; None for unlimited.
|
|
494
|
-
:type max_depth: Optional[int]
|
|
495
|
-
:param timeout_sec: Optional wall-clock timeout in seconds.
|
|
496
|
-
:type timeout_sec: Optional[float]
|
|
497
|
-
:returns: Canonically relabeled DiGraph with nodes 1..N.
|
|
498
|
-
:rtype: nx.DiGraph
|
|
499
|
-
"""
|
|
353
|
+
"""Return the canonical relabeled graph."""
|
|
500
354
|
G_can, _, _, _, _, _ = self._canon(max_depth=max_depth, timeout_sec=timeout_sec)
|
|
501
355
|
return G_can
|
|
502
356
|
|
|
@@ -506,16 +360,7 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
506
360
|
max_depth: Optional[int] = None,
|
|
507
361
|
timeout_sec: Optional[float] = None,
|
|
508
362
|
) -> bool:
|
|
509
|
-
"""
|
|
510
|
-
Test whether the canonical graph has nontrivial automorphisms.
|
|
511
|
-
|
|
512
|
-
:param max_depth: Optional maximum recursion depth; None for unlimited.
|
|
513
|
-
:type max_depth: Optional[int]
|
|
514
|
-
:param timeout_sec: Optional wall-clock timeout in seconds.
|
|
515
|
-
:type timeout_sec: Optional[float]
|
|
516
|
-
:returns: True if more than one minimal-label permutation exists.
|
|
517
|
-
:rtype: bool
|
|
518
|
-
"""
|
|
363
|
+
"""True iff >1 minimal-label permutation exists."""
|
|
519
364
|
_, _, perms, _, _, _ = self._canon(max_depth=max_depth, timeout_sec=timeout_sec)
|
|
520
365
|
return len(perms) > 1
|
|
521
366
|
|
|
@@ -525,21 +370,11 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
525
370
|
max_depth: Optional[int] = None,
|
|
526
371
|
timeout_sec: Optional[float] = None,
|
|
527
372
|
) -> Dict[str, Any]:
|
|
528
|
-
"""
|
|
529
|
-
Run canonicalization and return a summary dictionary.
|
|
530
|
-
|
|
531
|
-
:param max_depth: Optional maximum recursion depth; None for unlimited.
|
|
532
|
-
:type max_depth: Optional[int]
|
|
533
|
-
:param timeout_sec: Optional wall-clock timeout in seconds.
|
|
534
|
-
:type timeout_sec: Optional[float]
|
|
535
|
-
:returns: Summary with permutations, mappings, orbits and diagnostics.
|
|
536
|
-
:rtype: Dict[str, Any]
|
|
537
|
-
"""
|
|
373
|
+
"""Run canonicalization and return a summary dictionary."""
|
|
538
374
|
G_can, perm, perms, orbits, maps, early = self._canon(
|
|
539
375
|
max_depth=max_depth,
|
|
540
376
|
timeout_sec=timeout_sec,
|
|
541
377
|
)
|
|
542
|
-
|
|
543
378
|
return {
|
|
544
379
|
"canon_graph": G_can,
|
|
545
380
|
"graph_type": self.graph_type,
|
|
@@ -559,16 +394,7 @@ class CRNCanonicalizer(_CRNGraphBackend):
|
|
|
559
394
|
max_depth: Optional[int] = None,
|
|
560
395
|
timeout_sec: Optional[float] = None,
|
|
561
396
|
) -> List[Set[Any]]:
|
|
562
|
-
"""
|
|
563
|
-
Compute node orbits for the canonical form.
|
|
564
|
-
|
|
565
|
-
:param max_depth: Optional maximum recursion depth; None for unlimited.
|
|
566
|
-
:type max_depth: Optional[int]
|
|
567
|
-
:param timeout_sec: Optional wall-clock timeout in seconds.
|
|
568
|
-
:type timeout_sec: Optional[float]
|
|
569
|
-
:returns: List of disjoint node sets representing orbits.
|
|
570
|
-
:rtype: List[Set[Any]]
|
|
571
|
-
"""
|
|
397
|
+
"""Compute node orbits for the canonical form."""
|
|
572
398
|
_, _, _, orbits, _, _ = self._canon(
|
|
573
399
|
max_depth=max_depth,
|
|
574
400
|
timeout_sec=timeout_sec,
|
|
@@ -593,31 +419,9 @@ def canonical(
|
|
|
593
419
|
timeout_sec: Optional[float] = None,
|
|
594
420
|
) -> CRNCanonicalizer:
|
|
595
421
|
"""
|
|
596
|
-
Run canonicalization and return a CRNCanonicalizer instance.
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
populate internal state; the returned object can then be queried.
|
|
600
|
-
|
|
601
|
-
:param hg: Hypergraph to canonicalize.
|
|
602
|
-
:type hg: CRNHyperGraph
|
|
603
|
-
:param include_rule: If True, use bipartite species→reaction→species view;
|
|
604
|
-
if False, use collapsed species graph.
|
|
605
|
-
:type include_rule: bool
|
|
606
|
-
:param node_attr_keys: Node attributes used in partition refinement and
|
|
607
|
-
canonical labels.
|
|
608
|
-
:type node_attr_keys: Iterable[str]
|
|
609
|
-
:param edge_attr_keys: Edge attributes included in canonical labels.
|
|
610
|
-
:type edge_attr_keys: Iterable[str]
|
|
611
|
-
:param integer_ids: If True, use integer node ids in bipartite view.
|
|
612
|
-
:type integer_ids: bool
|
|
613
|
-
:param include_stoich: If True, include stoichiometry on bipartite edges.
|
|
614
|
-
:type include_stoich: bool
|
|
615
|
-
:param max_depth: Optional maximum recursion depth; None for unlimited.
|
|
616
|
-
:type max_depth: Optional[int]
|
|
617
|
-
:param timeout_sec: Optional wall-clock timeout in seconds.
|
|
618
|
-
:type timeout_sec: Optional[float]
|
|
619
|
-
:returns: Canonicalizer instance with populated internal state.
|
|
620
|
-
:rtype: CRNCanonicalizer
|
|
422
|
+
Run canonicalization and return a CRNCanonicalizer instance (exact).
|
|
423
|
+
|
|
424
|
+
NOTE: returns the canonicalizer object (not the summary dict).
|
|
621
425
|
"""
|
|
622
426
|
canon = CRNCanonicalizer(
|
|
623
427
|
hg,
|
|
@@ -627,5 +431,6 @@ def canonical(
|
|
|
627
431
|
integer_ids=integer_ids,
|
|
628
432
|
include_stoich=include_stoich,
|
|
629
433
|
)
|
|
630
|
-
|
|
631
|
-
|
|
434
|
+
# compute once to validate / warm results (optional)
|
|
435
|
+
canon.summary(max_depth=max_depth, timeout_sec=timeout_sec)
|
|
436
|
+
return canon
|