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,584 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any, Optional
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
from .stoich import right_nullspace, stoichiometric_matrix
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class ThermoSummary:
|
|
13
|
+
"""
|
|
14
|
+
Lightweight container summarizing thermodynamic-like stoichiometric
|
|
15
|
+
properties of a chemical reaction network.
|
|
16
|
+
|
|
17
|
+
This dataclass gathers the main outputs of the thermo module into a single
|
|
18
|
+
object for convenient downstream inspection, reporting, or serialization.
|
|
19
|
+
It is intentionally compact and stores only the most interpretable summary
|
|
20
|
+
flags and one example conservation-law vector when available.
|
|
21
|
+
|
|
22
|
+
:param conservative:
|
|
23
|
+
Whether the network is conservative, i.e. whether there exists a
|
|
24
|
+
strictly positive vector :math:`m > 0` such that :math:`m^T S = 0`.
|
|
25
|
+
The value may be ``None`` if the check is inconclusive.
|
|
26
|
+
:type conservative: Optional[bool]
|
|
27
|
+
:param consistent:
|
|
28
|
+
Whether the network is consistent, i.e. whether there exists a strictly
|
|
29
|
+
positive vector :math:`v > 0` such that :math:`S v = 0`. The value may
|
|
30
|
+
be ``None`` if the check is inconclusive.
|
|
31
|
+
:type consistent: Optional[bool]
|
|
32
|
+
:param example_conservation_law:
|
|
33
|
+
Example normalized strictly positive left-kernel vector when one is
|
|
34
|
+
found, otherwise ``None``.
|
|
35
|
+
:type example_conservation_law: Optional[numpy.ndarray]
|
|
36
|
+
:param irreversible_futile_cycles:
|
|
37
|
+
Boolean indicator of whether the right kernel :math:`\\ker(S)` is
|
|
38
|
+
non-trivial. This is used here as a structural proxy for the presence
|
|
39
|
+
of futile-cycle-like steady flux modes.
|
|
40
|
+
:type irreversible_futile_cycles: bool
|
|
41
|
+
|
|
42
|
+
.. code-block:: python
|
|
43
|
+
|
|
44
|
+
from synkit.CRN.Props.thermo import compute_thermo_summary
|
|
45
|
+
|
|
46
|
+
summary = compute_thermo_summary(hg)
|
|
47
|
+
print(summary.conservative)
|
|
48
|
+
print(summary.consistent)
|
|
49
|
+
print(summary.irreversible_futile_cycles)
|
|
50
|
+
print(summary.example_conservation_law)
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
conservative: Optional[bool]
|
|
54
|
+
consistent: Optional[bool]
|
|
55
|
+
example_conservation_law: Optional[np.ndarray]
|
|
56
|
+
irreversible_futile_cycles: bool
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _normalize_positive(vec: np.ndarray, *, eps: float = 1e-8) -> Optional[np.ndarray]:
|
|
60
|
+
"""Normalize a strictly signed vector to a positive unit-:math:`\\ell_1` vector.
|
|
61
|
+
|
|
62
|
+
This helper accepts a candidate vector and checks whether all entries are
|
|
63
|
+
strictly positive or strictly negative up to the threshold ``eps``. If the
|
|
64
|
+
vector is strictly negative, it is sign-flipped. A valid vector is then
|
|
65
|
+
normalized to unit 1-norm and returned.
|
|
66
|
+
|
|
67
|
+
This is primarily used to post-process candidate conservation laws or flux
|
|
68
|
+
modes so they are easier to inspect and compare numerically.
|
|
69
|
+
|
|
70
|
+
:param vec:
|
|
71
|
+
Input vector to test and normalize.
|
|
72
|
+
:type vec: numpy.ndarray
|
|
73
|
+
:param eps:
|
|
74
|
+
Absolute threshold used to determine strict positivity or negativity.
|
|
75
|
+
:type eps: float
|
|
76
|
+
:return:
|
|
77
|
+
A strictly positive vector normalized to sum to 1, or ``None`` if the
|
|
78
|
+
input does not have a uniform strict sign.
|
|
79
|
+
:rtype: Optional[numpy.ndarray]
|
|
80
|
+
|
|
81
|
+
.. code-block:: python
|
|
82
|
+
|
|
83
|
+
import numpy as np
|
|
84
|
+
from synkit.CRN.Props.thermo import _normalize_positive
|
|
85
|
+
|
|
86
|
+
v = np.array([2.0, 3.0, 5.0])
|
|
87
|
+
out = _normalize_positive(v)
|
|
88
|
+
print(out) # array summing to 1.0
|
|
89
|
+
"""
|
|
90
|
+
v = np.asarray(vec, dtype=float).reshape(-1)
|
|
91
|
+
if np.all(v > eps):
|
|
92
|
+
s = float(np.sum(v))
|
|
93
|
+
if s > 0:
|
|
94
|
+
return v / s
|
|
95
|
+
if np.all(v < -eps):
|
|
96
|
+
v = -v
|
|
97
|
+
s = float(np.sum(v))
|
|
98
|
+
if s > 0:
|
|
99
|
+
return v / s
|
|
100
|
+
return None
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _find_positive_left_kernel_vector(
|
|
104
|
+
S: np.ndarray,
|
|
105
|
+
*,
|
|
106
|
+
eps: float = 1e-8,
|
|
107
|
+
rtol: float = 1e-12,
|
|
108
|
+
) -> tuple[Optional[bool], Optional[np.ndarray]]:
|
|
109
|
+
"""Attempt to find a strictly positive conservation-law vector
|
|
110
|
+
:math:`m > 0` satisfying :math:`m^T S = 0`.
|
|
111
|
+
|
|
112
|
+
This helper implements the main conservativity search logic used by
|
|
113
|
+
:func:`is_conservative` and :func:`compute_conservativity`. The search is
|
|
114
|
+
performed in several stages:
|
|
115
|
+
|
|
116
|
+
1. compute a basis of :math:`\\ker(S^T)`,
|
|
117
|
+
2. test whether any basis vector is already strictly positive up to sign,
|
|
118
|
+
3. project the all-ones vector into the left kernel and test whether the
|
|
119
|
+
projection is strictly positive,
|
|
120
|
+
4. if SciPy is available, solve a linear feasibility problem enforcing
|
|
121
|
+
:math:`S^T m = 0` and :math:`m_i \\ge \\varepsilon`.
|
|
122
|
+
|
|
123
|
+
This layered approach makes the routine useful both with and without SciPy.
|
|
124
|
+
|
|
125
|
+
:param S:
|
|
126
|
+
Stoichiometric matrix of shape ``(n_species, n_reactions)``.
|
|
127
|
+
:type S: numpy.ndarray
|
|
128
|
+
:param eps:
|
|
129
|
+
Absolute threshold used to test strict positivity.
|
|
130
|
+
:type eps: float
|
|
131
|
+
:param rtol:
|
|
132
|
+
Relative tolerance used in nullspace computations.
|
|
133
|
+
:type rtol: float
|
|
134
|
+
:return:
|
|
135
|
+
A tuple ``(flag, m)`` where ``flag`` is:
|
|
136
|
+
|
|
137
|
+
- ``True`` if a strictly positive conservation law was found,
|
|
138
|
+
- ``False`` if no such law exists,
|
|
139
|
+
- ``None`` if the result is inconclusive,
|
|
140
|
+
|
|
141
|
+
and ``m`` is an example normalized positive conservation law if one was
|
|
142
|
+
found, otherwise ``None``.
|
|
143
|
+
:rtype: Tuple[Optional[bool], Optional[numpy.ndarray]]
|
|
144
|
+
|
|
145
|
+
.. code-block:: python
|
|
146
|
+
|
|
147
|
+
import numpy as np
|
|
148
|
+
from synkit.CRN.Props.thermo import _find_positive_left_kernel_vector
|
|
149
|
+
|
|
150
|
+
S = np.array([[-1.0], [1.0]])
|
|
151
|
+
flag, m = _find_positive_left_kernel_vector(S)
|
|
152
|
+
print(flag)
|
|
153
|
+
print(m)
|
|
154
|
+
"""
|
|
155
|
+
S = np.asarray(S, dtype=float)
|
|
156
|
+
n_species, n_reactions = S.shape
|
|
157
|
+
|
|
158
|
+
# No reactions: every species is trivially conserved
|
|
159
|
+
if n_reactions == 0:
|
|
160
|
+
if n_species == 0:
|
|
161
|
+
return True, None
|
|
162
|
+
m = np.ones(n_species, dtype=float)
|
|
163
|
+
m /= np.sum(m)
|
|
164
|
+
return True, m
|
|
165
|
+
|
|
166
|
+
B = left_nullspace_from_matrix(S, rtol=rtol)
|
|
167
|
+
if B is None or B.size == 0:
|
|
168
|
+
return False, None
|
|
169
|
+
|
|
170
|
+
B = np.atleast_2d(B)
|
|
171
|
+
|
|
172
|
+
# 1) quick scan of basis columns
|
|
173
|
+
for j in range(B.shape[1]):
|
|
174
|
+
m = _normalize_positive(B[:, j], eps=eps)
|
|
175
|
+
if m is not None:
|
|
176
|
+
return True, m
|
|
177
|
+
|
|
178
|
+
# 2) projection fallback:
|
|
179
|
+
# project the all-ones vector onto ker(S^T)
|
|
180
|
+
ones = np.ones(n_species, dtype=float)
|
|
181
|
+
# works whether or not B is perfectly orthonormal enough for practice
|
|
182
|
+
coeff = B.T @ ones
|
|
183
|
+
proj = B @ coeff
|
|
184
|
+
m = _normalize_positive(proj, eps=eps)
|
|
185
|
+
if m is not None:
|
|
186
|
+
return True, m
|
|
187
|
+
|
|
188
|
+
# 3) exact LP feasibility check, if SciPy is available
|
|
189
|
+
try:
|
|
190
|
+
from scipy.optimize import linprog # type: ignore
|
|
191
|
+
|
|
192
|
+
c = np.zeros(n_species, dtype=float)
|
|
193
|
+
A_eq = S.T
|
|
194
|
+
b_eq = np.zeros(n_reactions, dtype=float)
|
|
195
|
+
bounds = [(1.0, None) for _ in range(n_species)]
|
|
196
|
+
|
|
197
|
+
res = linprog(c, A_eq=A_eq, b_eq=b_eq, bounds=bounds, method="highs")
|
|
198
|
+
if res.success and res.x is not None:
|
|
199
|
+
m = _normalize_positive(np.asarray(res.x, dtype=float), eps=eps)
|
|
200
|
+
if m is not None:
|
|
201
|
+
return True, m
|
|
202
|
+
return False, None
|
|
203
|
+
return False, None
|
|
204
|
+
except Exception:
|
|
205
|
+
pass
|
|
206
|
+
|
|
207
|
+
# Without LP, 1D kernel is definitive; higher-dimensional is otherwise inconclusive.
|
|
208
|
+
if B.shape[1] == 1:
|
|
209
|
+
return False, None
|
|
210
|
+
|
|
211
|
+
return None, None
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def left_nullspace_from_matrix(S: np.ndarray, *, rtol: float = 1e-12) -> np.ndarray:
|
|
215
|
+
"""Compute a basis for the left kernel :math:`\\ker(S^T)` directly from a
|
|
216
|
+
stoichiometric matrix.
|
|
217
|
+
|
|
218
|
+
This helper is a matrix-level analogue of the graph-based nullspace
|
|
219
|
+
functions in :mod:`stoich`. It is useful when the stoichiometric matrix is
|
|
220
|
+
already available and one wants to avoid reconstructing it from the CRN
|
|
221
|
+
representation.
|
|
222
|
+
|
|
223
|
+
If SciPy is available, the function uses :func:`scipy.linalg.null_space`.
|
|
224
|
+
Otherwise it falls back to an SVD-based implementation using NumPy.
|
|
225
|
+
|
|
226
|
+
:param S:
|
|
227
|
+
Stoichiometric matrix of shape ``(n_species, n_reactions)``.
|
|
228
|
+
:type S: numpy.ndarray
|
|
229
|
+
:param rtol:
|
|
230
|
+
Relative tolerance used to determine the effective numerical rank in
|
|
231
|
+
the nullspace computation.
|
|
232
|
+
:type rtol: float
|
|
233
|
+
:return:
|
|
234
|
+
Matrix whose columns form a basis for :math:`\\ker(S^T)`. The returned
|
|
235
|
+
array has shape ``(n_species, k)``, where ``k`` is the dimension of the
|
|
236
|
+
left kernel.
|
|
237
|
+
:rtype: numpy.ndarray
|
|
238
|
+
|
|
239
|
+
.. code-block:: python
|
|
240
|
+
|
|
241
|
+
import numpy as np
|
|
242
|
+
from synkit.CRN.Props.thermo import left_nullspace_from_matrix
|
|
243
|
+
|
|
244
|
+
S = np.array([[-1.0], [1.0]])
|
|
245
|
+
L = left_nullspace_from_matrix(S)
|
|
246
|
+
print(L.shape)
|
|
247
|
+
"""
|
|
248
|
+
from .stoich import _null_space
|
|
249
|
+
|
|
250
|
+
return _null_space(np.asarray(S, dtype=float).T, rtol=rtol)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def is_conservative(
|
|
254
|
+
crn: Any,
|
|
255
|
+
*,
|
|
256
|
+
eps: float = 1e-8,
|
|
257
|
+
rtol: float = 1e-12,
|
|
258
|
+
) -> Optional[bool]:
|
|
259
|
+
"""Check whether the chemical reaction network is conservative.
|
|
260
|
+
|
|
261
|
+
A network is called conservative here if there exists a strictly positive
|
|
262
|
+
vector :math:`m > 0` such that
|
|
263
|
+
|
|
264
|
+
.. math::
|
|
265
|
+
|
|
266
|
+
m^T S = 0,
|
|
267
|
+
|
|
268
|
+
where :math:`S` is the stoichiometric matrix. Such a vector can be
|
|
269
|
+
interpreted as a positive conservation law over species.
|
|
270
|
+
|
|
271
|
+
This function returns only the Boolean-style status of the check. Use
|
|
272
|
+
:func:`compute_conservativity` when an example conservation-law vector is
|
|
273
|
+
also desired.
|
|
274
|
+
|
|
275
|
+
:param crn:
|
|
276
|
+
Hypergraph or bipartite NetworkX graph representing the chemical
|
|
277
|
+
reaction network.
|
|
278
|
+
:type crn: Any
|
|
279
|
+
:param eps:
|
|
280
|
+
Absolute threshold used to test strict positivity of candidate
|
|
281
|
+
conservation-law vectors.
|
|
282
|
+
:type eps: float
|
|
283
|
+
:param rtol:
|
|
284
|
+
Relative tolerance used in nullspace-based computations.
|
|
285
|
+
:type rtol: float
|
|
286
|
+
:return:
|
|
287
|
+
- ``True`` if a strictly positive conservation law exists,
|
|
288
|
+
- ``False`` if no such law exists,
|
|
289
|
+
- ``None`` if the result is inconclusive.
|
|
290
|
+
:rtype: Optional[bool]
|
|
291
|
+
|
|
292
|
+
.. code-block:: python
|
|
293
|
+
|
|
294
|
+
from synkit.CRN.Props.thermo import is_conservative
|
|
295
|
+
|
|
296
|
+
flag = is_conservative(hg)
|
|
297
|
+
print("Conservative?", flag)
|
|
298
|
+
"""
|
|
299
|
+
from ..backend import resolve_backend
|
|
300
|
+
|
|
301
|
+
if resolve_backend()[0] == "cpp":
|
|
302
|
+
from ..native_analysis import positive_kernel
|
|
303
|
+
|
|
304
|
+
result = positive_kernel(crn, kind="p")
|
|
305
|
+
return result[0]
|
|
306
|
+
S = stoichiometric_matrix(crn)
|
|
307
|
+
flag, _m = _find_positive_left_kernel_vector(S, eps=eps, rtol=rtol)
|
|
308
|
+
return flag
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def compute_conservativity(
|
|
312
|
+
crn: Any,
|
|
313
|
+
*,
|
|
314
|
+
rtol: float = 1e-12,
|
|
315
|
+
eps: float = 1e-8,
|
|
316
|
+
) -> tuple[Optional[bool], Optional[np.ndarray]]:
|
|
317
|
+
"""Compute the conservativity status of a network together with an example
|
|
318
|
+
positive conservation law when available.
|
|
319
|
+
|
|
320
|
+
This is the more informative counterpart of :func:`is_conservative`. It
|
|
321
|
+
checks whether there exists a strictly positive vector :math:`m > 0` such
|
|
322
|
+
that :math:`m^T S = 0`, and if successful it also returns one normalized
|
|
323
|
+
example vector.
|
|
324
|
+
|
|
325
|
+
:param crn:
|
|
326
|
+
Hypergraph or bipartite NetworkX graph representing the chemical
|
|
327
|
+
reaction network.
|
|
328
|
+
:type crn: Any
|
|
329
|
+
:param rtol:
|
|
330
|
+
Relative tolerance used in nullspace-based computations.
|
|
331
|
+
:type rtol: float
|
|
332
|
+
:param eps:
|
|
333
|
+
Absolute threshold used to test strict positivity of candidate
|
|
334
|
+
conservation-law vectors.
|
|
335
|
+
:type eps: float
|
|
336
|
+
:return:
|
|
337
|
+
Tuple ``(flag, m)`` where ``flag`` is the conservativity result and
|
|
338
|
+
``m`` is an example normalized strictly positive conservation law if
|
|
339
|
+
one was found, otherwise ``None``.
|
|
340
|
+
:rtype: Tuple[Optional[bool], Optional[numpy.ndarray]]
|
|
341
|
+
|
|
342
|
+
.. code-block:: python
|
|
343
|
+
|
|
344
|
+
from synkit.CRN.Props.thermo import compute_conservativity
|
|
345
|
+
|
|
346
|
+
flag, m = compute_conservativity(hg)
|
|
347
|
+
print("Conservative?", flag)
|
|
348
|
+
if m is not None:
|
|
349
|
+
print("Example law:", m)
|
|
350
|
+
"""
|
|
351
|
+
from ..backend import resolve_backend
|
|
352
|
+
|
|
353
|
+
if resolve_backend()[0] == "cpp":
|
|
354
|
+
from ..native_analysis import positive_kernel
|
|
355
|
+
|
|
356
|
+
result = positive_kernel(crn, kind="p")
|
|
357
|
+
return result
|
|
358
|
+
S = stoichiometric_matrix(crn)
|
|
359
|
+
return _find_positive_left_kernel_vector(S, eps=eps, rtol=rtol)
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def is_consistent(crn: Any, *, eps: float = 1e-8) -> Optional[bool]:
|
|
363
|
+
"""Check whether the chemical reaction network is consistent.
|
|
364
|
+
|
|
365
|
+
Consistency is tested here by asking whether there exists a strictly
|
|
366
|
+
positive flux vector :math:`v > 0` such that
|
|
367
|
+
|
|
368
|
+
.. math::
|
|
369
|
+
|
|
370
|
+
S v = 0,
|
|
371
|
+
|
|
372
|
+
where :math:`S` is the stoichiometric matrix. In CRN terminology, this
|
|
373
|
+
corresponds to the existence of a strictly positive right-kernel vector,
|
|
374
|
+
or equivalently a positive T-semiflow.
|
|
375
|
+
|
|
376
|
+
If SciPy is available, the function attempts a linear-programming check.
|
|
377
|
+
Otherwise it falls back to a nullspace-based heuristic.
|
|
378
|
+
|
|
379
|
+
:param crn:
|
|
380
|
+
Hypergraph or bipartite NetworkX graph representing the chemical
|
|
381
|
+
reaction network.
|
|
382
|
+
:type crn: Any
|
|
383
|
+
:param eps:
|
|
384
|
+
Absolute lower bound used to enforce strict positivity of candidate
|
|
385
|
+
flux vectors.
|
|
386
|
+
:type eps: float
|
|
387
|
+
:return:
|
|
388
|
+
- ``True`` if a strictly positive right-kernel vector exists,
|
|
389
|
+
- ``False`` if no such vector exists,
|
|
390
|
+
- ``None`` if the result is inconclusive.
|
|
391
|
+
:rtype: Optional[bool]
|
|
392
|
+
|
|
393
|
+
.. code-block:: python
|
|
394
|
+
|
|
395
|
+
from synkit.CRN.Props.thermo import is_consistent
|
|
396
|
+
|
|
397
|
+
flag = is_consistent(hg)
|
|
398
|
+
print("Consistent?", flag)
|
|
399
|
+
"""
|
|
400
|
+
from ..backend import resolve_backend
|
|
401
|
+
|
|
402
|
+
if resolve_backend()[0] == "cpp":
|
|
403
|
+
from ..native_analysis import positive_kernel
|
|
404
|
+
|
|
405
|
+
result = positive_kernel(crn, kind="t")
|
|
406
|
+
return result[0]
|
|
407
|
+
S = stoichiometric_matrix(crn)
|
|
408
|
+
n_species, n_reactions = S.shape
|
|
409
|
+
|
|
410
|
+
if n_reactions == 0:
|
|
411
|
+
return False if n_species > 0 else True
|
|
412
|
+
|
|
413
|
+
try:
|
|
414
|
+
from scipy.optimize import linprog # type: ignore
|
|
415
|
+
|
|
416
|
+
c = np.ones(n_reactions)
|
|
417
|
+
A_eq = S
|
|
418
|
+
b_eq = np.zeros(n_species)
|
|
419
|
+
bounds = [(1.0, None) for _ in range(n_reactions)]
|
|
420
|
+
res = linprog(c, A_eq=A_eq, b_eq=b_eq, bounds=bounds, method="highs")
|
|
421
|
+
|
|
422
|
+
if res.success and res.x is not None:
|
|
423
|
+
v = res.x
|
|
424
|
+
residual = S @ v
|
|
425
|
+
max_v = float(np.max(np.abs(v))) or 1.0
|
|
426
|
+
rel_err = np.linalg.norm(residual, ord=np.inf) / max_v
|
|
427
|
+
return bool(rel_err <= 1e-8 and np.all(v >= 1.0 - 1e-7))
|
|
428
|
+
return False
|
|
429
|
+
except Exception:
|
|
430
|
+
pass
|
|
431
|
+
|
|
432
|
+
B = right_nullspace(crn)
|
|
433
|
+
if B is None or B.size == 0:
|
|
434
|
+
return False
|
|
435
|
+
|
|
436
|
+
for k in range(B.shape[1]):
|
|
437
|
+
v = B[:, k]
|
|
438
|
+
if np.all(v > eps) or np.all(v < -eps):
|
|
439
|
+
return True
|
|
440
|
+
|
|
441
|
+
# projection fallback onto ker(S)
|
|
442
|
+
B = np.atleast_2d(B)
|
|
443
|
+
ones = np.ones(B.shape[0], dtype=float)
|
|
444
|
+
coeff = B.T @ ones
|
|
445
|
+
proj = B @ coeff
|
|
446
|
+
if np.all(proj > eps) or np.all(proj < -eps):
|
|
447
|
+
return True
|
|
448
|
+
|
|
449
|
+
return None
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def has_irreversible_futile_cycles(crn: Any, *, rtol: float = 1e-12) -> bool:
|
|
453
|
+
"""Check whether the network admits non-trivial steady-state flux modes.
|
|
454
|
+
|
|
455
|
+
This function tests whether a nonnegative nonzero right-kernel vector exists.
|
|
456
|
+
This is a structural circulation test and does not establish Gibbs-energy
|
|
457
|
+
feasibility. The legacy function name is retained for compatibility.
|
|
458
|
+
|
|
459
|
+
Previously this tested whether the right kernel :math:`\\ker(S)` is
|
|
460
|
+
non-trivial, i.e. whether there exists a nonzero vector :math:`v` such that
|
|
461
|
+
|
|
462
|
+
.. math::
|
|
463
|
+
|
|
464
|
+
S v = 0.
|
|
465
|
+
|
|
466
|
+
A non-trivial right kernel indicates the presence of flux-mode-like
|
|
467
|
+
directions that do not change net species amounts. In this module, this is
|
|
468
|
+
used as a structural proxy for irreversible futile cycles, although it
|
|
469
|
+
should be interpreted cautiously as a stoichiometric indicator rather than
|
|
470
|
+
a full mechanistic proof.
|
|
471
|
+
|
|
472
|
+
:param crn:
|
|
473
|
+
Hypergraph or bipartite NetworkX graph representing the chemical
|
|
474
|
+
reaction network.
|
|
475
|
+
:type crn: Any
|
|
476
|
+
:param rtol:
|
|
477
|
+
Relative tolerance used in the nullspace computation.
|
|
478
|
+
:type rtol: float
|
|
479
|
+
:return:
|
|
480
|
+
``True`` if :math:`\\ker(S)` is non-trivial, otherwise ``False``.
|
|
481
|
+
:rtype: bool
|
|
482
|
+
|
|
483
|
+
.. code-block:: python
|
|
484
|
+
|
|
485
|
+
from synkit.CRN.Props.thermo import has_irreversible_futile_cycles
|
|
486
|
+
|
|
487
|
+
has_cycles = has_irreversible_futile_cycles(hg)
|
|
488
|
+
print("Has futile-cycle-like modes?", has_cycles)
|
|
489
|
+
"""
|
|
490
|
+
from scipy.optimize import linprog
|
|
491
|
+
|
|
492
|
+
S = stoichiometric_matrix(crn)
|
|
493
|
+
if S.shape[1] == 0:
|
|
494
|
+
return False
|
|
495
|
+
result = linprog(
|
|
496
|
+
np.zeros(S.shape[1]),
|
|
497
|
+
A_eq=np.vstack([S, np.ones((1, S.shape[1]))]),
|
|
498
|
+
b_eq=np.r_[np.zeros(S.shape[0]), 1.0],
|
|
499
|
+
bounds=(0, None),
|
|
500
|
+
method="highs",
|
|
501
|
+
)
|
|
502
|
+
return bool(
|
|
503
|
+
result.success
|
|
504
|
+
and result.x is not None
|
|
505
|
+
and np.min(result.x) >= -1e-9
|
|
506
|
+
and np.max(np.abs(S @ result.x), initial=0) < 1e-8
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
def has_stoichiometric_dependencies(crn: Any, *, rtol: float = 1e-12) -> bool:
|
|
511
|
+
"""Whether reaction vectors are linearly dependent, without sign constraints."""
|
|
512
|
+
return right_nullspace(crn, rtol=rtol).shape[1] > 0
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
def compute_thermo_summary(
|
|
516
|
+
crn: Any, *, rtol: float = 1e-12, eps: float = 1e-8
|
|
517
|
+
) -> ThermoSummary:
|
|
518
|
+
"""Compute a composite :class:`ThermoSummary` describing key thermodynamic-like
|
|
519
|
+
and structural stoichiometric properties of a chemical reaction network.
|
|
520
|
+
|
|
521
|
+
This helper combines the main thermo-related analyses into a single call:
|
|
522
|
+
|
|
523
|
+
* Conservativity: whether a strictly positive vector :math:`m > 0` exists
|
|
524
|
+
such that :math:`m^T S = 0`.
|
|
525
|
+
* Consistency: whether a strictly positive flux vector :math:`v > 0`
|
|
526
|
+
exists such that :math:`S v = 0`.
|
|
527
|
+
* Irreversible futile-cycle proxy: whether the right kernel
|
|
528
|
+
:math:`\\ker(S)` is non-trivial.
|
|
529
|
+
* Example conservation law: a normalized strictly positive left-kernel
|
|
530
|
+
vector, when one can be found.
|
|
531
|
+
|
|
532
|
+
The returned summary is intended as a lightweight diagnostic object for
|
|
533
|
+
quick inspection of CRN thermodynamic structure without calling each helper
|
|
534
|
+
individually.
|
|
535
|
+
|
|
536
|
+
:param crn:
|
|
537
|
+
Hypergraph or bipartite NetworkX graph representing the chemical
|
|
538
|
+
reaction network.
|
|
539
|
+
:type crn: Any
|
|
540
|
+
:param rtol:
|
|
541
|
+
Relative tolerance used in nullspace-based computations, especially
|
|
542
|
+
when estimating kernel dimensions or checking whether the right kernel
|
|
543
|
+
is non-trivial.
|
|
544
|
+
:type rtol: float
|
|
545
|
+
:param eps:
|
|
546
|
+
Absolute positivity threshold used when testing whether a candidate
|
|
547
|
+
conservation law or flux mode is strictly positive.
|
|
548
|
+
:type eps: float
|
|
549
|
+
:return:
|
|
550
|
+
A :class:`ThermoSummary` instance containing conservativity,
|
|
551
|
+
consistency, an optional example positive conservation law, and a
|
|
552
|
+
Boolean indicator for non-trivial steady-state flux cycles.
|
|
553
|
+
:rtype: ThermoSummary
|
|
554
|
+
|
|
555
|
+
.. code-block:: python
|
|
556
|
+
|
|
557
|
+
from synkit.CRN.Props.thermo import compute_thermo_summary
|
|
558
|
+
|
|
559
|
+
summary = compute_thermo_summary(hg)
|
|
560
|
+
|
|
561
|
+
print("Conservative:", summary.conservative)
|
|
562
|
+
print("Consistent:", summary.consistent)
|
|
563
|
+
print("Has futile-cycle proxy:", summary.irreversible_futile_cycles)
|
|
564
|
+
|
|
565
|
+
if summary.example_conservation_law is not None:
|
|
566
|
+
print("Example conservation law:", summary.example_conservation_law)
|
|
567
|
+
|
|
568
|
+
.. note::
|
|
569
|
+
|
|
570
|
+
The field ``irreversible_futile_cycles`` is used here as a structural
|
|
571
|
+
proxy based on the existence of nonzero vectors in :math:`\\ker(S)`.
|
|
572
|
+
It should be interpreted as a stoichiometric indicator rather than as a
|
|
573
|
+
full mechanistic proof of thermodynamic infeasibility.
|
|
574
|
+
"""
|
|
575
|
+
conservative, m = compute_conservativity(crn, rtol=rtol, eps=eps)
|
|
576
|
+
consistent = is_consistent(crn, eps=eps)
|
|
577
|
+
cyc = has_irreversible_futile_cycles(crn, rtol=rtol)
|
|
578
|
+
|
|
579
|
+
return ThermoSummary(
|
|
580
|
+
conservative=conservative,
|
|
581
|
+
consistent=consistent,
|
|
582
|
+
example_conservation_law=m,
|
|
583
|
+
irreversible_futile_cycles=cyc,
|
|
584
|
+
)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""KEGG retrieval, parsing and curation utilities for CRN construction.
|
|
2
|
+
|
|
3
|
+
This subpackage is the entry point for reaction networks derived from a curated
|
|
4
|
+
biological pathway rather than from rule-based expansion.
|
|
5
|
+
|
|
6
|
+
.. rubric:: Example
|
|
7
|
+
|
|
8
|
+
.. code-block:: python
|
|
9
|
+
|
|
10
|
+
from synkit.CRN.Query import KEGGExtractor
|
|
11
|
+
|
|
12
|
+
data = KEGGExtractor().build_module_json("M00001")
|
|
13
|
+
print(sorted(data)[:5])
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from .kegg_api import KEGGClient
|
|
19
|
+
from .kegg_extract import KEGGExtractor
|
|
20
|
+
from .kegg_impute import KEGGImputer
|
|
21
|
+
from .kegg_parse import (
|
|
22
|
+
KEGGEquation,
|
|
23
|
+
equation_to_text,
|
|
24
|
+
expand_stoichiometry,
|
|
25
|
+
get_compound_ids_from_equations,
|
|
26
|
+
get_compound_ids_from_text,
|
|
27
|
+
molblock_to_smiles,
|
|
28
|
+
normalize_module_id,
|
|
29
|
+
orient_equation_to_module,
|
|
30
|
+
parse_equation,
|
|
31
|
+
parse_kegg_field_blocks,
|
|
32
|
+
parse_module_reaction_directions,
|
|
33
|
+
parse_side,
|
|
34
|
+
reaction_smiles_from_equation,
|
|
35
|
+
)
|
|
36
|
+
from .to_syncrn import (
|
|
37
|
+
CURRENCY_COMPOUNDS,
|
|
38
|
+
syncrn_from_kegg_equations,
|
|
39
|
+
syncrn_from_kegg_module,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
__all__ = [
|
|
43
|
+
"KEGGClient",
|
|
44
|
+
"KEGGExtractor",
|
|
45
|
+
"KEGGImputer",
|
|
46
|
+
"KEGGEquation",
|
|
47
|
+
"equation_to_text",
|
|
48
|
+
"expand_stoichiometry",
|
|
49
|
+
"get_compound_ids_from_equations",
|
|
50
|
+
"get_compound_ids_from_text",
|
|
51
|
+
"molblock_to_smiles",
|
|
52
|
+
"normalize_module_id",
|
|
53
|
+
"orient_equation_to_module",
|
|
54
|
+
"parse_equation",
|
|
55
|
+
"parse_kegg_field_blocks",
|
|
56
|
+
"parse_module_reaction_directions",
|
|
57
|
+
"parse_side",
|
|
58
|
+
"reaction_smiles_from_equation",
|
|
59
|
+
"CURRENCY_COMPOUNDS",
|
|
60
|
+
"syncrn_from_kegg_equations",
|
|
61
|
+
"syncrn_from_kegg_module",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
from .cache import build_cached_kegg_crn, load_kegg_cache
|
|
65
|
+
|
|
66
|
+
__all__ += ["build_cached_kegg_crn", "load_kegg_cache"]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""User-supplied offline KEGG caches, independent of research fixtures."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
import json
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from collections.abc import Mapping
|
|
7
|
+
from .to_syncrn import syncrn_from_kegg_equations
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def load_kegg_cache(path):
|
|
11
|
+
"""Read a KEGG module cache from an explicit path; never fetch data.
|
|
12
|
+
|
|
13
|
+
Expected schema: {"modules": {module_id: {"equations": {...},
|
|
14
|
+
"compound_names": {...}}}}. No manuscript modules or default file are implied.
|
|
15
|
+
"""
|
|
16
|
+
data = json.loads(Path(path).read_text(encoding="utf-8"))
|
|
17
|
+
if not isinstance(data, dict) or not isinstance(data.get("modules"), dict):
|
|
18
|
+
raise ValueError("KEGG cache must contain a modules object")
|
|
19
|
+
for module_id, entry in data["modules"].items():
|
|
20
|
+
if not isinstance(entry, dict) or not isinstance(entry.get("equations"), dict):
|
|
21
|
+
raise ValueError(f"{module_id}: expected an equations object")
|
|
22
|
+
if not all(
|
|
23
|
+
isinstance(k, str) and isinstance(v, str)
|
|
24
|
+
for k, v in entry["equations"].items()
|
|
25
|
+
):
|
|
26
|
+
raise ValueError(f"{module_id}: equations must map ids to equation strings")
|
|
27
|
+
return data
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def build_cached_kegg_crn(
|
|
31
|
+
cache, module_id, *, drop_compounds=(), expand_reversible=True
|
|
32
|
+
):
|
|
33
|
+
"""Convert one cached module; retain all participants by default."""
|
|
34
|
+
data = cache if isinstance(cache, Mapping) else load_kegg_cache(cache)
|
|
35
|
+
entry = data["modules"][module_id]
|
|
36
|
+
return syncrn_from_kegg_equations(
|
|
37
|
+
entry["equations"],
|
|
38
|
+
names=entry.get("compound_names"),
|
|
39
|
+
drop_compounds=drop_compounds,
|
|
40
|
+
expand_reversible=expand_reversible,
|
|
41
|
+
)
|