okstra 0.107.2 → 0.109.0
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.
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/prompts/lead/okstra-lead-contract.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +3 -2
- package/runtime/python/okstra_ctl/graphify_cmd.py +225 -0
- package/runtime/python/okstra_ctl/resolve_task_key.py +15 -9
- package/runtime/python/okstra_ctl/session.py +44 -0
- package/runtime/python/okstra_project/__init__.py +2 -0
- package/runtime/python/okstra_project/state.py +36 -0
- package/runtime/python/okstra_token_usage/claude.py +15 -9
- package/runtime/python/okstra_token_usage/cli.py +23 -0
- package/runtime/python/okstra_token_usage/collect.py +163 -4
- package/runtime/python/okstra_vendor/__init__.py +41 -0
- package/runtime/python/okstra_vendor/graphify/.vendored-version +1 -0
- package/runtime/python/okstra_vendor/graphify/__init__.py +28 -0
- package/runtime/python/okstra_vendor/graphify/__main__.py +1371 -0
- package/runtime/python/okstra_vendor/graphify/analyze.py +540 -0
- package/runtime/python/okstra_vendor/graphify/benchmark.py +129 -0
- package/runtime/python/okstra_vendor/graphify/build.py +107 -0
- package/runtime/python/okstra_vendor/graphify/cache.py +169 -0
- package/runtime/python/okstra_vendor/graphify/cluster.py +137 -0
- package/runtime/python/okstra_vendor/graphify/detect.py +510 -0
- package/runtime/python/okstra_vendor/graphify/export.py +1014 -0
- package/runtime/python/okstra_vendor/graphify/extract.py +3277 -0
- package/runtime/python/okstra_vendor/graphify/hooks.py +220 -0
- package/runtime/python/okstra_vendor/graphify/ingest.py +297 -0
- package/runtime/python/okstra_vendor/graphify/manifest.py +4 -0
- package/runtime/python/okstra_vendor/graphify/report.py +175 -0
- package/runtime/python/okstra_vendor/graphify/security.py +203 -0
- package/runtime/python/okstra_vendor/graphify/serve.py +373 -0
- package/runtime/python/okstra_vendor/graphify/skill-aider.md +1184 -0
- package/runtime/python/okstra_vendor/graphify/skill-claw.md +1184 -0
- package/runtime/python/okstra_vendor/graphify/skill-codex.md +1242 -0
- package/runtime/python/okstra_vendor/graphify/skill-copilot.md +1268 -0
- package/runtime/python/okstra_vendor/graphify/skill-droid.md +1239 -0
- package/runtime/python/okstra_vendor/graphify/skill-kiro.md +1183 -0
- package/runtime/python/okstra_vendor/graphify/skill-opencode.md +1238 -0
- package/runtime/python/okstra_vendor/graphify/skill-trae.md +1208 -0
- package/runtime/python/okstra_vendor/graphify/skill-vscode.md +253 -0
- package/runtime/python/okstra_vendor/graphify/skill-windows.md +1245 -0
- package/runtime/python/okstra_vendor/graphify/skill.md +1319 -0
- package/runtime/python/okstra_vendor/graphify/transcribe.py +182 -0
- package/runtime/python/okstra_vendor/graphify/validate.py +72 -0
- package/runtime/python/okstra_vendor/graphify/watch.py +188 -0
- package/runtime/python/okstra_vendor/graphify/wiki.py +214 -0
- package/runtime/python/okstra_vendor/networkx/__init__.py +62 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/__init__.py +134 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/__init__.py +26 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/clique.py +259 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/clustering_coefficient.py +71 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/connectivity.py +412 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/density.py +396 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/distance_measures.py +150 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/dominating_set.py +149 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/kcomponents.py +369 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/matching.py +44 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/maxcut.py +143 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/ramsey.py +53 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/steinertree.py +265 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_approx_clust_coeff.py +41 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_clique.py +112 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_connectivity.py +199 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_density.py +146 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_distance_measures.py +59 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_dominating_set.py +78 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_kcomponents.py +303 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_matching.py +8 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_maxcut.py +94 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_ramsey.py +31 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_steinertree.py +306 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_traveling_salesman.py +1014 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_treewidth.py +274 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/tests/test_vertex_cover.py +68 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/traveling_salesman.py +1508 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/treewidth.py +255 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/vertex_cover.py +83 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/__init__.py +5 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/connectivity.py +122 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/correlation.py +302 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/mixing.py +255 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/neighbor_degree.py +160 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/pairs.py +127 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/base_test.py +81 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_connectivity.py +143 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_correlation.py +122 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_mixing.py +174 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_neighbor_degree.py +107 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/tests/test_pairs.py +87 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/asteroidal.py +164 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/__init__.py +88 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/basic.py +322 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/centrality.py +290 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/cluster.py +289 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/covering.py +57 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/edgelist.py +360 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/extendability.py +105 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/generators.py +603 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/link_analysis.py +316 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/matching.py +590 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/matrix.py +232 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/projection.py +526 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/redundancy.py +112 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/spectral.py +69 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_basic.py +125 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_centrality.py +192 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_cluster.py +84 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_covering.py +33 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_edgelist.py +240 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_extendability.py +334 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_generators.py +407 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_link_analysis.py +218 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_matching.py +327 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_matrix.py +138 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_project.py +409 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_redundancy.py +35 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/tests/test_spectral_bipartivity.py +80 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/boundary.py +168 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/bridges.py +205 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/broadcasting.py +164 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/__init__.py +20 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/betweenness.py +591 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/betweenness_subset.py +236 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/closeness.py +282 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_betweenness.py +364 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_betweenness_subset.py +227 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_closeness.py +96 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/degree_alg.py +150 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/dispersion.py +107 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/eigenvector.py +357 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/flow_matrix.py +130 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/group.py +787 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/harmonic.py +88 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/katz.py +331 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/laplacian.py +150 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/load.py +200 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/percolation.py +128 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/reaching.py +209 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/second_order.py +141 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/subgraph_alg.py +361 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_betweenness_centrality.py +923 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_betweenness_centrality_subset.py +354 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_closeness_centrality.py +274 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_betweenness_centrality.py +259 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_betweenness_centrality_subset.py +147 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_current_flow_closeness.py +43 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_degree_centrality.py +144 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_dispersion.py +73 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_eigenvector_centrality.py +186 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_group.py +277 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_harmonic_centrality.py +122 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_katz_centrality.py +345 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_laplacian_centrality.py +220 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_load_centrality.py +344 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_percolation_centrality.py +87 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_reaching.py +140 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_second_order_centrality.py +82 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_subgraph.py +110 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_trophic.py +302 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/tests/test_voterank.py +64 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/trophic.py +181 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/voterank_alg.py +95 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/chains.py +172 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/chordal.py +443 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/clique.py +818 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/cluster.py +732 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/coloring/__init__.py +4 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/coloring/equitable_coloring.py +505 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/coloring/greedy_coloring.py +565 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/coloring/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/coloring/tests/test_coloring.py +863 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/communicability_alg.py +163 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/__init__.py +28 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/asyn_fluid.py +153 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/bipartitions.py +354 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/centrality.py +171 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/community_utils.py +30 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/divisive.py +216 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/kclique.py +79 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/label_propagation.py +338 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/leiden.py +162 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/local.py +220 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/louvain.py +384 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/lukes.py +227 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/modularity_max.py +452 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/quality.py +347 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_asyn_fluid.py +147 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_bipartitions.py +157 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_centrality.py +85 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_divisive.py +106 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_kclique.py +91 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_label_propagation.py +241 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_leiden.py +138 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_local.py +76 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_louvain.py +264 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_lukes.py +152 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_modularity_max.py +340 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_quality.py +139 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/community/tests/test_utils.py +26 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/__init__.py +6 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/attracting.py +115 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/biconnected.py +394 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/connected.py +282 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/semiconnected.py +71 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/strongly_connected.py +359 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_attracting.py +70 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_biconnected.py +248 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_connected.py +138 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_semiconnected.py +55 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_strongly_connected.py +193 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/tests/test_weakly_connected.py +96 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/components/weakly_connected.py +196 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/__init__.py +11 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/connectivity.py +811 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/cuts.py +616 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/disjoint_paths.py +408 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/edge_augmentation.py +1270 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/edge_kcomponents.py +592 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/kcomponents.py +220 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/kcutsets.py +235 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/stoerwagner.py +152 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_connectivity.py +421 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_cuts.py +309 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_disjoint_paths.py +249 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_edge_augmentation.py +502 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_edge_kcomponents.py +488 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_kcomponents.py +323 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_kcutsets.py +280 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/tests/test_stoer_wagner.py +102 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/utils.py +88 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/core.py +588 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/covering.py +142 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/cuts.py +416 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/cycles.py +1234 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/d_separation.py +677 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/dag.py +1392 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/distance_measures.py +1095 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/distance_regular.py +272 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/dominance.py +142 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/dominating.py +268 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/efficiency_measures.py +167 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/euler.py +470 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/__init__.py +11 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/boykovkolmogorov.py +370 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/capacityscaling.py +407 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/dinitz_alg.py +238 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/edmondskarp.py +241 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/gomory_hu.py +178 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/maxflow.py +611 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/mincost.py +356 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/networksimplex.py +662 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/preflowpush.py +425 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/shortestaugmentingpath.py +300 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/gl1.gpickle.bz2 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/gw1.gpickle.bz2 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/netgen-2.gpickle.bz2 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_gomory_hu.py +128 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_maxflow.py +573 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_maxflow_large_graph.py +155 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_mincost.py +475 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/test_networksimplex.py +481 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/tests/wlm3.gpickle.bz2 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/utils.py +194 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/graph_hashing.py +435 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/graphical.py +483 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/hierarchy.py +57 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/hybrid.py +196 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isolate.py +107 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/__init__.py +7 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/ismags.py +1306 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/isomorph.py +336 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/isomorphvf2.py +1262 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/matchhelpers.py +352 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/temporalisomorphvf2.py +308 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/iso_r01_s80.A99 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/iso_r01_s80.B99 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/si2_b06_m200.A99 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/si2_b06_m200.B99 +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_ismags.py +719 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_isomorphism.py +103 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_isomorphvf2.py +490 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_match_helpers.py +64 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_temporalisomorphvf2.py +212 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_tree_isomorphism.py +202 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2pp.py +1655 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2pp_helpers.py +3118 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tests/test_vf2userfunc.py +196 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tree_isomorphism.py +264 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/vf2pp.py +1102 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/vf2userfunc.py +192 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/__init__.py +2 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/hits_alg.py +337 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/pagerank_alg.py +498 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/test_hits.py +77 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/tests/test_pagerank.py +213 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/link_prediction.py +687 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/lowest_common_ancestors.py +280 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/matching.py +1148 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/minors/__init__.py +27 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/minors/contraction.py +738 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/minors/tests/test_contraction.py +544 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/mis.py +78 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/moral.py +59 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/node_classification.py +219 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/non_randomness.py +155 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/__init__.py +4 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/all.py +324 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/binary.py +468 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/product.py +633 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_all.py +328 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_binary.py +451 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_product.py +491 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/tests/test_unary.py +55 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/unary.py +77 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/perfect_graph.py +73 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/planar_drawing.py +464 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/planarity.py +1463 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/polynomials.py +306 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/reciprocity.py +98 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/regular.py +167 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/richclub.py +138 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/__init__.py +5 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/astar.py +239 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/dense.py +264 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/generic.py +716 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_astar.py +254 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_dense.py +212 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_dense_numpy.py +88 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_generic.py +511 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_unweighted.py +149 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/tests/test_weighted.py +983 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/unweighted.py +625 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/weighted.py +2542 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/similarity.py +2107 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/simple_paths.py +966 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/smallworld.py +404 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/smetric.py +30 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/sparsifiers.py +296 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/structuralholes.py +374 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/summarization.py +564 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/swap.py +406 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_asteroidal.py +23 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_boundary.py +154 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_bridges.py +144 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_broadcasting.py +109 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_chains.py +136 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_chordal.py +129 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_clique.py +300 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cluster.py +678 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_communicability.py +80 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_core.py +266 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_covering.py +85 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cuts.py +171 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_cycles.py +984 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_d_separation.py +340 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dag.py +835 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_distance_measures.py +831 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_distance_regular.py +85 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dominance.py +299 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_dominating.py +115 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_efficiency.py +58 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_euler.py +314 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_graph_hashing.py +872 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_graphical.py +163 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_hierarchy.py +46 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_hybrid.py +24 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_isolate.py +26 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_link_prediction.py +615 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_lowest_common_ancestors.py +459 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_matching.py +556 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_max_weight_clique.py +179 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_mis.py +62 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_moral.py +15 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_node_classification.py +140 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_non_randomness.py +60 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_perfect_graph.py +27 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_planar_drawing.py +274 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_planarity.py +556 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_polynomials.py +57 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_reciprocity.py +37 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_regular.py +88 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_richclub.py +149 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_similarity.py +1158 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_simple_paths.py +803 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_smallworld.py +76 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_smetric.py +8 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_sparsifiers.py +138 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_structuralholes.py +191 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_summarization.py +642 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_swap.py +179 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_threshold.py +270 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_time_dependent.py +431 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_tournament.py +161 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_triads.py +248 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_vitality.py +41 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_voronoi.py +103 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_walks.py +54 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tests/test_wiener.py +157 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/threshold.py +981 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/time_dependent.py +142 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tournament.py +406 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/__init__.py +5 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/beamsearch.py +90 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/breadth_first_search.py +576 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/depth_first_search.py +529 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/edgebfs.py +185 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/edgedfs.py +182 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_beamsearch.py +25 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_bfs.py +203 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_dfs.py +307 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_edgebfs.py +147 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/tests/test_edgedfs.py +131 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/__init__.py +7 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/branchings.py +1042 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/coding.py +413 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/decomposition.py +88 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/distance_measures.py +219 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/mst.py +1281 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/operations.py +106 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/recognition.py +273 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_branchings.py +624 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_coding.py +114 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_decomposition.py +79 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_distance_measures.py +99 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_mst.py +934 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_operations.py +53 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/tests/test_recognition.py +174 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/triads.py +500 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/vitality.py +76 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/voronoi.py +86 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/walks.py +77 -0
- package/runtime/python/okstra_vendor/networkx/algorithms/wiener.py +278 -0
- package/runtime/python/okstra_vendor/networkx/classes/__init__.py +13 -0
- package/runtime/python/okstra_vendor/networkx/classes/coreviews.py +435 -0
- package/runtime/python/okstra_vendor/networkx/classes/digraph.py +1363 -0
- package/runtime/python/okstra_vendor/networkx/classes/filters.py +95 -0
- package/runtime/python/okstra_vendor/networkx/classes/function.py +1549 -0
- package/runtime/python/okstra_vendor/networkx/classes/graph.py +2082 -0
- package/runtime/python/okstra_vendor/networkx/classes/graphviews.py +269 -0
- package/runtime/python/okstra_vendor/networkx/classes/multidigraph.py +977 -0
- package/runtime/python/okstra_vendor/networkx/classes/multigraph.py +1294 -0
- package/runtime/python/okstra_vendor/networkx/classes/reportviews.py +1447 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/dispatch_interface.py +192 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/historical_tests.py +476 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_coreviews.py +362 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_digraph.py +331 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_digraph_historical.py +110 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_filters.py +177 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_function.py +1045 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_graph.py +950 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_graph_historical.py +12 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_graphviews.py +349 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_multidigraph.py +459 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_multigraph.py +528 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_reportviews.py +1421 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_special.py +131 -0
- package/runtime/python/okstra_vendor/networkx/classes/tests/test_subgraphviews.py +371 -0
- package/runtime/python/okstra_vendor/networkx/conftest.py +261 -0
- package/runtime/python/okstra_vendor/networkx/convert.py +502 -0
- package/runtime/python/okstra_vendor/networkx/convert_matrix.py +1314 -0
- package/runtime/python/okstra_vendor/networkx/drawing/__init__.py +7 -0
- package/runtime/python/okstra_vendor/networkx/drawing/layout.py +2036 -0
- package/runtime/python/okstra_vendor/networkx/drawing/nx_agraph.py +470 -0
- package/runtime/python/okstra_vendor/networkx/drawing/nx_latex.py +570 -0
- package/runtime/python/okstra_vendor/networkx/drawing/nx_pydot.py +361 -0
- package/runtime/python/okstra_vendor/networkx/drawing/nx_pylab.py +2978 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_complex.png +0 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_empty_graph.png +0 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_house_with_colors.png +0 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_labels_and_colors.png +0 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_display_shortest_path.png +0 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/baseline/test_house_with_colors.png +0 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/test_agraph.py +237 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/test_image_comparison_pylab_mpl.py +229 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/test_latex.py +285 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/test_layout.py +631 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/test_pydot.py +146 -0
- package/runtime/python/okstra_vendor/networkx/drawing/tests/test_pylab.py +1582 -0
- package/runtime/python/okstra_vendor/networkx/exception.py +131 -0
- package/runtime/python/okstra_vendor/networkx/generators/__init__.py +34 -0
- package/runtime/python/okstra_vendor/networkx/generators/atlas.dat.gz +0 -0
- package/runtime/python/okstra_vendor/networkx/generators/atlas.py +227 -0
- package/runtime/python/okstra_vendor/networkx/generators/classic.py +1091 -0
- package/runtime/python/okstra_vendor/networkx/generators/cographs.py +68 -0
- package/runtime/python/okstra_vendor/networkx/generators/community.py +1070 -0
- package/runtime/python/okstra_vendor/networkx/generators/degree_seq.py +886 -0
- package/runtime/python/okstra_vendor/networkx/generators/directed.py +572 -0
- package/runtime/python/okstra_vendor/networkx/generators/duplication.py +174 -0
- package/runtime/python/okstra_vendor/networkx/generators/ego.py +66 -0
- package/runtime/python/okstra_vendor/networkx/generators/expanders.py +499 -0
- package/runtime/python/okstra_vendor/networkx/generators/geometric.py +1037 -0
- package/runtime/python/okstra_vendor/networkx/generators/harary_graph.py +163 -0
- package/runtime/python/okstra_vendor/networkx/generators/internet_as_graphs.py +443 -0
- package/runtime/python/okstra_vendor/networkx/generators/intersection.py +125 -0
- package/runtime/python/okstra_vendor/networkx/generators/interval_graph.py +70 -0
- package/runtime/python/okstra_vendor/networkx/generators/joint_degree_seq.py +664 -0
- package/runtime/python/okstra_vendor/networkx/generators/lattice.py +405 -0
- package/runtime/python/okstra_vendor/networkx/generators/line.py +501 -0
- package/runtime/python/okstra_vendor/networkx/generators/mycielski.py +110 -0
- package/runtime/python/okstra_vendor/networkx/generators/nonisomorphic_trees.py +259 -0
- package/runtime/python/okstra_vendor/networkx/generators/random_clustered.py +117 -0
- package/runtime/python/okstra_vendor/networkx/generators/random_graphs.py +1416 -0
- package/runtime/python/okstra_vendor/networkx/generators/small.py +1070 -0
- package/runtime/python/okstra_vendor/networkx/generators/social.py +554 -0
- package/runtime/python/okstra_vendor/networkx/generators/spectral_graph_forge.py +120 -0
- package/runtime/python/okstra_vendor/networkx/generators/stochastic.py +54 -0
- package/runtime/python/okstra_vendor/networkx/generators/sudoku.py +131 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_atlas.py +75 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_classic.py +642 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_cographs.py +20 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_community.py +362 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_degree_seq.py +224 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_directed.py +189 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_duplication.py +103 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_ego.py +39 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_expanders.py +182 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_geometric.py +488 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_harary_graph.py +133 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_internet_as_graphs.py +221 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_intersection.py +28 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_interval_graph.py +144 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_joint_degree_seq.py +125 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_lattice.py +264 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_line.py +316 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_mycielski.py +30 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_nonisomorphic_trees.py +82 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_random_clustered.py +33 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_random_graphs.py +495 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_small.py +220 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_spectral_graph_forge.py +49 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_stochastic.py +72 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_sudoku.py +92 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_time_series.py +64 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_trees.py +195 -0
- package/runtime/python/okstra_vendor/networkx/generators/tests/test_triads.py +15 -0
- package/runtime/python/okstra_vendor/networkx/generators/time_series.py +74 -0
- package/runtime/python/okstra_vendor/networkx/generators/trees.py +1070 -0
- package/runtime/python/okstra_vendor/networkx/generators/triads.py +94 -0
- package/runtime/python/okstra_vendor/networkx/lazy_imports.py +188 -0
- package/runtime/python/okstra_vendor/networkx/linalg/__init__.py +13 -0
- package/runtime/python/okstra_vendor/networkx/linalg/algebraicconnectivity.py +650 -0
- package/runtime/python/okstra_vendor/networkx/linalg/attrmatrix.py +466 -0
- package/runtime/python/okstra_vendor/networkx/linalg/bethehessianmatrix.py +77 -0
- package/runtime/python/okstra_vendor/networkx/linalg/graphmatrix.py +168 -0
- package/runtime/python/okstra_vendor/networkx/linalg/laplacianmatrix.py +512 -0
- package/runtime/python/okstra_vendor/networkx/linalg/modularitymatrix.py +166 -0
- package/runtime/python/okstra_vendor/networkx/linalg/spectrum.py +186 -0
- package/runtime/python/okstra_vendor/networkx/linalg/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/linalg/tests/test_algebraic_connectivity.py +400 -0
- package/runtime/python/okstra_vendor/networkx/linalg/tests/test_attrmatrix.py +108 -0
- package/runtime/python/okstra_vendor/networkx/linalg/tests/test_bethehessian.py +40 -0
- package/runtime/python/okstra_vendor/networkx/linalg/tests/test_graphmatrix.py +275 -0
- package/runtime/python/okstra_vendor/networkx/linalg/tests/test_laplacian.py +334 -0
- package/runtime/python/okstra_vendor/networkx/linalg/tests/test_modularity.py +86 -0
- package/runtime/python/okstra_vendor/networkx/linalg/tests/test_spectrum.py +70 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/__init__.py +17 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/adjlist.py +330 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/edgelist.py +489 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/gexf.py +1084 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/gml.py +879 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/graph6.py +427 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/graphml.py +1053 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/__init__.py +19 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/adjacency.py +156 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/cytoscape.py +190 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/node_link.py +261 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_adjacency.py +78 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_cytoscape.py +78 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_node_link.py +109 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tests/test_tree.py +48 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tree.py +137 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/leda.py +108 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/multiline_adjlist.py +393 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/p2g.py +113 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/pajek.py +286 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/sparse6.py +379 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_adjlist.py +354 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_edgelist.py +318 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_gexf.py +612 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_gml.py +744 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_graph6.py +181 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_graphml.py +1531 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_leda.py +30 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_p2g.py +63 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_pajek.py +128 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_sparse6.py +166 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/tests/test_text.py +1742 -0
- package/runtime/python/okstra_vendor/networkx/readwrite/text.py +851 -0
- package/runtime/python/okstra_vendor/networkx/relabel.py +285 -0
- package/runtime/python/okstra_vendor/networkx/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/tests/test_all_random_functions.py +248 -0
- package/runtime/python/okstra_vendor/networkx/tests/test_convert.py +321 -0
- package/runtime/python/okstra_vendor/networkx/tests/test_convert_numpy.py +531 -0
- package/runtime/python/okstra_vendor/networkx/tests/test_convert_pandas.py +349 -0
- package/runtime/python/okstra_vendor/networkx/tests/test_convert_scipy.py +281 -0
- package/runtime/python/okstra_vendor/networkx/tests/test_exceptions.py +40 -0
- package/runtime/python/okstra_vendor/networkx/tests/test_import.py +11 -0
- package/runtime/python/okstra_vendor/networkx/tests/test_lazy_imports.py +96 -0
- package/runtime/python/okstra_vendor/networkx/tests/test_relabel.py +349 -0
- package/runtime/python/okstra_vendor/networkx/tests/test_removed_functions_exception_messages.py +8 -0
- package/runtime/python/okstra_vendor/networkx/utils/__init__.py +8 -0
- package/runtime/python/okstra_vendor/networkx/utils/backends.py +2171 -0
- package/runtime/python/okstra_vendor/networkx/utils/configs.py +396 -0
- package/runtime/python/okstra_vendor/networkx/utils/decorators.py +1233 -0
- package/runtime/python/okstra_vendor/networkx/utils/heaps.py +338 -0
- package/runtime/python/okstra_vendor/networkx/utils/mapped_queue.py +297 -0
- package/runtime/python/okstra_vendor/networkx/utils/misc.py +703 -0
- package/runtime/python/okstra_vendor/networkx/utils/random_sequence.py +198 -0
- package/runtime/python/okstra_vendor/networkx/utils/rcm.py +159 -0
- package/runtime/python/okstra_vendor/networkx/utils/tests/__init__.py +0 -0
- package/runtime/python/okstra_vendor/networkx/utils/tests/test__init.py +11 -0
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_backends.py +225 -0
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_config.py +263 -0
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_decorators.py +510 -0
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_heaps.py +131 -0
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_mapped_queue.py +268 -0
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_misc.py +393 -0
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_random_sequence.py +53 -0
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_rcm.py +63 -0
- package/runtime/python/okstra_vendor/networkx/utils/tests/test_unionfind.py +55 -0
- package/runtime/python/okstra_vendor/networkx/utils/union_find.py +106 -0
- package/runtime/skills/okstra-graphify/SKILL.md +161 -0
- package/runtime/skills/okstra-inspect/SKILL.md +17 -9
- package/runtime/templates/reports/settings.template.json +4 -0
- package/runtime/validators/forbidden_actions.py +8 -2
- package/runtime/validators/validate_session_conformance.py +26 -5
- package/src/cli-registry.mjs +7 -0
- package/src/commands/graphify.mjs +32 -0
- package/src/commands/lifecycle/doctor.mjs +9 -0
- package/src/lib/skill-catalog.mjs +1 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""Algorithm to select influential nodes in a graph using VoteRank."""
|
|
2
|
+
|
|
3
|
+
import networkx as nx
|
|
4
|
+
|
|
5
|
+
__all__ = ["voterank"]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@nx._dispatchable
|
|
9
|
+
def voterank(G, number_of_nodes=None):
|
|
10
|
+
"""Select a list of influential nodes in a graph using VoteRank algorithm
|
|
11
|
+
|
|
12
|
+
VoteRank [1]_ computes a ranking of the nodes in a graph G based on a
|
|
13
|
+
voting scheme. With VoteRank, all nodes vote for each of its in-neighbors
|
|
14
|
+
and the node with the highest votes is elected iteratively. The voting
|
|
15
|
+
ability of out-neighbors of elected nodes is decreased in subsequent turns.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
G : graph
|
|
20
|
+
A NetworkX graph.
|
|
21
|
+
|
|
22
|
+
number_of_nodes : integer, optional
|
|
23
|
+
Number of ranked nodes to extract (default all nodes).
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
voterank : list
|
|
28
|
+
Ordered list of computed seeds.
|
|
29
|
+
Only nodes with positive number of votes are returned.
|
|
30
|
+
|
|
31
|
+
Examples
|
|
32
|
+
--------
|
|
33
|
+
>>> G = nx.Graph([(0, 1), (0, 2), (0, 3), (1, 4)])
|
|
34
|
+
>>> nx.voterank(G)
|
|
35
|
+
[0, 1]
|
|
36
|
+
|
|
37
|
+
The algorithm can be used both for undirected and directed graphs.
|
|
38
|
+
However, the directed version is different in two ways:
|
|
39
|
+
(i) nodes only vote for their in-neighbors and
|
|
40
|
+
(ii) only the voting ability of elected node and its out-neighbors are updated:
|
|
41
|
+
|
|
42
|
+
>>> G = nx.DiGraph([(0, 1), (2, 1), (2, 3), (3, 4)])
|
|
43
|
+
>>> nx.voterank(G)
|
|
44
|
+
[2, 3]
|
|
45
|
+
|
|
46
|
+
Notes
|
|
47
|
+
-----
|
|
48
|
+
Each edge is treated independently in case of multigraphs.
|
|
49
|
+
|
|
50
|
+
References
|
|
51
|
+
----------
|
|
52
|
+
.. [1] Zhang, J.-X. et al. (2016).
|
|
53
|
+
Identifying a set of influential spreaders in complex networks.
|
|
54
|
+
Sci. Rep. 6, 27823; doi: 10.1038/srep27823.
|
|
55
|
+
"""
|
|
56
|
+
influential_nodes = []
|
|
57
|
+
vote_rank = {}
|
|
58
|
+
if len(G) == 0:
|
|
59
|
+
return influential_nodes
|
|
60
|
+
if number_of_nodes is None or number_of_nodes > len(G):
|
|
61
|
+
number_of_nodes = len(G)
|
|
62
|
+
if G.is_directed():
|
|
63
|
+
# For directed graphs compute average out-degree
|
|
64
|
+
avgDegree = sum(deg for _, deg in G.out_degree()) / len(G)
|
|
65
|
+
else:
|
|
66
|
+
# For undirected graphs compute average degree
|
|
67
|
+
avgDegree = sum(deg for _, deg in G.degree()) / len(G)
|
|
68
|
+
# step 1 - initiate all nodes to (0,1) (score, voting ability)
|
|
69
|
+
for n in G.nodes():
|
|
70
|
+
vote_rank[n] = [0, 1]
|
|
71
|
+
# Repeat steps 1b to 4 until num_seeds are elected.
|
|
72
|
+
for _ in range(number_of_nodes):
|
|
73
|
+
# step 1b - reset rank
|
|
74
|
+
for n in G.nodes():
|
|
75
|
+
vote_rank[n][0] = 0
|
|
76
|
+
# step 2 - vote
|
|
77
|
+
for n, nbr in G.edges():
|
|
78
|
+
# In directed graphs nodes only vote for their in-neighbors
|
|
79
|
+
vote_rank[n][0] += vote_rank[nbr][1]
|
|
80
|
+
if not G.is_directed():
|
|
81
|
+
vote_rank[nbr][0] += vote_rank[n][1]
|
|
82
|
+
for n in influential_nodes:
|
|
83
|
+
vote_rank[n][0] = 0
|
|
84
|
+
# step 3 - select top node
|
|
85
|
+
n = max(G.nodes, key=lambda x: vote_rank[x][0])
|
|
86
|
+
if vote_rank[n][0] == 0:
|
|
87
|
+
return influential_nodes
|
|
88
|
+
influential_nodes.append(n)
|
|
89
|
+
# weaken the selected node
|
|
90
|
+
vote_rank[n] = [0, 0]
|
|
91
|
+
# step 4 - update voterank properties
|
|
92
|
+
for _, nbr in G.edges(n):
|
|
93
|
+
vote_rank[nbr][1] -= 1 / avgDegree
|
|
94
|
+
vote_rank[nbr][1] = max(vote_rank[nbr][1], 0)
|
|
95
|
+
return influential_nodes
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""Functions for finding chains in a graph."""
|
|
2
|
+
|
|
3
|
+
import networkx as nx
|
|
4
|
+
from networkx.utils import not_implemented_for
|
|
5
|
+
|
|
6
|
+
__all__ = ["chain_decomposition"]
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@not_implemented_for("directed")
|
|
10
|
+
@not_implemented_for("multigraph")
|
|
11
|
+
@nx._dispatchable
|
|
12
|
+
def chain_decomposition(G, root=None):
|
|
13
|
+
"""Returns the chain decomposition of a graph.
|
|
14
|
+
|
|
15
|
+
The *chain decomposition* of a graph with respect a depth-first
|
|
16
|
+
search tree is a set of cycles or paths derived from the set of
|
|
17
|
+
fundamental cycles of the tree in the following manner. Consider
|
|
18
|
+
each fundamental cycle with respect to the given tree, represented
|
|
19
|
+
as a list of edges beginning with the nontree edge oriented away
|
|
20
|
+
from the root of the tree. For each fundamental cycle, if it
|
|
21
|
+
overlaps with any previous fundamental cycle, just take the initial
|
|
22
|
+
non-overlapping segment, which is a path instead of a cycle. Each
|
|
23
|
+
cycle or path is called a *chain*. For more information, see [1]_.
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
G : undirected graph
|
|
28
|
+
|
|
29
|
+
root : node (optional)
|
|
30
|
+
A node in the graph `G`. If specified, only the chain
|
|
31
|
+
decomposition for the connected component containing this node
|
|
32
|
+
will be returned. This node indicates the root of the depth-first
|
|
33
|
+
search tree.
|
|
34
|
+
|
|
35
|
+
Yields
|
|
36
|
+
------
|
|
37
|
+
chain : list
|
|
38
|
+
A list of edges representing a chain. There is no guarantee on
|
|
39
|
+
the orientation of the edges in each chain (for example, if a
|
|
40
|
+
chain includes the edge joining nodes 1 and 2, the chain may
|
|
41
|
+
include either (1, 2) or (2, 1)).
|
|
42
|
+
|
|
43
|
+
Raises
|
|
44
|
+
------
|
|
45
|
+
NodeNotFound
|
|
46
|
+
If `root` is not in the graph `G`.
|
|
47
|
+
|
|
48
|
+
Examples
|
|
49
|
+
--------
|
|
50
|
+
>>> G = nx.Graph([(0, 1), (1, 4), (3, 4), (3, 5), (4, 5)])
|
|
51
|
+
>>> list(nx.chain_decomposition(G))
|
|
52
|
+
[[(4, 5), (5, 3), (3, 4)]]
|
|
53
|
+
|
|
54
|
+
Notes
|
|
55
|
+
-----
|
|
56
|
+
The worst-case running time of this implementation is linear in the
|
|
57
|
+
number of nodes and number of edges [1]_.
|
|
58
|
+
|
|
59
|
+
References
|
|
60
|
+
----------
|
|
61
|
+
.. [1] Jens M. Schmidt (2013). "A simple test on 2-vertex-
|
|
62
|
+
and 2-edge-connectivity." *Information Processing Letters*,
|
|
63
|
+
113, 241–244. Elsevier. <https://doi.org/10.1016/j.ipl.2013.01.016>
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
def _dfs_cycle_forest(G, root=None):
|
|
68
|
+
"""Builds a directed graph composed of cycles from the given graph.
|
|
69
|
+
|
|
70
|
+
`G` is an undirected simple graph. `root` is a node in the graph
|
|
71
|
+
from which the depth-first search is started.
|
|
72
|
+
|
|
73
|
+
This function returns both the depth-first search cycle graph
|
|
74
|
+
(as a :class:`~networkx.DiGraph`) and the list of nodes in
|
|
75
|
+
depth-first preorder. The depth-first search cycle graph is a
|
|
76
|
+
directed graph whose edges are the edges of `G` oriented toward
|
|
77
|
+
the root if the edge is a tree edge and away from the root if
|
|
78
|
+
the edge is a non-tree edge. If `root` is not specified, this
|
|
79
|
+
performs a depth-first search on each connected component of `G`
|
|
80
|
+
and returns a directed forest instead.
|
|
81
|
+
|
|
82
|
+
If `root` is not in the graph, this raises :exc:`KeyError`.
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
# Create a directed graph from the depth-first search tree with
|
|
86
|
+
# root node `root` in which tree edges are directed toward the
|
|
87
|
+
# root and nontree edges are directed away from the root. For
|
|
88
|
+
# each node with an incident nontree edge, this creates a
|
|
89
|
+
# directed cycle starting with the nontree edge and returning to
|
|
90
|
+
# that node.
|
|
91
|
+
#
|
|
92
|
+
# The `parent` node attribute stores the parent of each node in
|
|
93
|
+
# the DFS tree. The `nontree` edge attribute indicates whether
|
|
94
|
+
# the edge is a tree edge or a nontree edge.
|
|
95
|
+
#
|
|
96
|
+
# We also store the order of the nodes found in the depth-first
|
|
97
|
+
# search in the `nodes` list.
|
|
98
|
+
H = nx.DiGraph()
|
|
99
|
+
nodes = []
|
|
100
|
+
for u, v, d in nx.dfs_labeled_edges(G, source=root):
|
|
101
|
+
if d == "forward":
|
|
102
|
+
# `dfs_labeled_edges()` yields (root, root, 'forward')
|
|
103
|
+
# if it is beginning the search on a new connected
|
|
104
|
+
# component.
|
|
105
|
+
if u == v:
|
|
106
|
+
H.add_node(v, parent=None)
|
|
107
|
+
nodes.append(v)
|
|
108
|
+
else:
|
|
109
|
+
H.add_node(v, parent=u)
|
|
110
|
+
H.add_edge(v, u, nontree=False)
|
|
111
|
+
nodes.append(v)
|
|
112
|
+
# `dfs_labeled_edges` considers nontree edges in both
|
|
113
|
+
# orientations, so we need to not add the edge if it its
|
|
114
|
+
# other orientation has been added.
|
|
115
|
+
elif d == "nontree" and v not in H[u]:
|
|
116
|
+
H.add_edge(v, u, nontree=True)
|
|
117
|
+
else:
|
|
118
|
+
# Do nothing on 'reverse' edges; we only care about
|
|
119
|
+
# forward and nontree edges.
|
|
120
|
+
pass
|
|
121
|
+
return H, nodes
|
|
122
|
+
|
|
123
|
+
def _build_chain(G, u, v, visited):
|
|
124
|
+
"""Generate the chain starting from the given nontree edge.
|
|
125
|
+
|
|
126
|
+
`G` is a DFS cycle graph as constructed by
|
|
127
|
+
:func:`_dfs_cycle_graph`. The edge (`u`, `v`) is a nontree edge
|
|
128
|
+
that begins a chain. `visited` is a set representing the nodes
|
|
129
|
+
in `G` that have already been visited.
|
|
130
|
+
|
|
131
|
+
This function yields the edges in an initial segment of the
|
|
132
|
+
fundamental cycle of `G` starting with the nontree edge (`u`,
|
|
133
|
+
`v`) that includes all the edges up until the first node that
|
|
134
|
+
appears in `visited`. The tree edges are given by the 'parent'
|
|
135
|
+
node attribute. The `visited` set is updated to add each node in
|
|
136
|
+
an edge yielded by this function.
|
|
137
|
+
|
|
138
|
+
"""
|
|
139
|
+
while v not in visited:
|
|
140
|
+
yield u, v
|
|
141
|
+
visited.add(v)
|
|
142
|
+
u, v = v, G.nodes[v]["parent"]
|
|
143
|
+
yield u, v
|
|
144
|
+
|
|
145
|
+
# Check if the root is in the graph G. If not, raise NodeNotFound
|
|
146
|
+
if root is not None and root not in G:
|
|
147
|
+
raise nx.NodeNotFound(f"Root node {root} is not in graph")
|
|
148
|
+
|
|
149
|
+
# Create a directed version of H that has the DFS edges directed
|
|
150
|
+
# toward the root and the nontree edges directed away from the root
|
|
151
|
+
# (in each connected component).
|
|
152
|
+
H, nodes = _dfs_cycle_forest(G, root)
|
|
153
|
+
|
|
154
|
+
# Visit the nodes again in DFS order. For each node, and for each
|
|
155
|
+
# nontree edge leaving that node, compute the fundamental cycle for
|
|
156
|
+
# that nontree edge starting with that edge. If the fundamental
|
|
157
|
+
# cycle overlaps with any visited nodes, just take the prefix of the
|
|
158
|
+
# cycle up to the point of visited nodes.
|
|
159
|
+
#
|
|
160
|
+
# We repeat this process for each connected component (implicitly,
|
|
161
|
+
# since `nodes` already has a list of the nodes grouped by connected
|
|
162
|
+
# component).
|
|
163
|
+
visited = set()
|
|
164
|
+
for u in nodes:
|
|
165
|
+
visited.add(u)
|
|
166
|
+
# For each nontree edge going out of node u...
|
|
167
|
+
edges = ((u, v) for u, v, d in H.out_edges(u, data="nontree") if d)
|
|
168
|
+
for u, v in edges:
|
|
169
|
+
# Create the cycle or cycle prefix starting with the
|
|
170
|
+
# nontree edge.
|
|
171
|
+
chain = list(_build_chain(H, u, v, visited))
|
|
172
|
+
yield chain
|
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Algorithms for chordal graphs.
|
|
3
|
+
|
|
4
|
+
A graph is chordal if every cycle of length at least 4 has a chord
|
|
5
|
+
(an edge joining two nodes not adjacent in the cycle).
|
|
6
|
+
https://en.wikipedia.org/wiki/Chordal_graph
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
import networkx as nx
|
|
12
|
+
from networkx.algorithms.components import connected_components
|
|
13
|
+
from networkx.utils import arbitrary_element, not_implemented_for
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"is_chordal",
|
|
17
|
+
"find_induced_nodes",
|
|
18
|
+
"chordal_graph_cliques",
|
|
19
|
+
"chordal_graph_treewidth",
|
|
20
|
+
"NetworkXTreewidthBoundExceeded",
|
|
21
|
+
"complete_to_chordal_graph",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class NetworkXTreewidthBoundExceeded(nx.NetworkXException):
|
|
26
|
+
"""Exception raised when a treewidth bound has been provided and it has
|
|
27
|
+
been exceeded"""
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@not_implemented_for("directed")
|
|
31
|
+
@not_implemented_for("multigraph")
|
|
32
|
+
@nx._dispatchable
|
|
33
|
+
def is_chordal(G):
|
|
34
|
+
"""Checks whether G is a chordal graph.
|
|
35
|
+
|
|
36
|
+
A graph is chordal if every cycle of length at least 4 has a chord
|
|
37
|
+
(an edge joining two nodes not adjacent in the cycle).
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
G : graph
|
|
42
|
+
A NetworkX graph.
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
chordal : bool
|
|
47
|
+
True if G is a chordal graph and False otherwise.
|
|
48
|
+
|
|
49
|
+
Raises
|
|
50
|
+
------
|
|
51
|
+
NetworkXNotImplemented
|
|
52
|
+
The algorithm does not support DiGraph, MultiGraph and MultiDiGraph.
|
|
53
|
+
|
|
54
|
+
Examples
|
|
55
|
+
--------
|
|
56
|
+
>>> e = [
|
|
57
|
+
... (1, 2),
|
|
58
|
+
... (1, 3),
|
|
59
|
+
... (2, 3),
|
|
60
|
+
... (2, 4),
|
|
61
|
+
... (3, 4),
|
|
62
|
+
... (3, 5),
|
|
63
|
+
... (3, 6),
|
|
64
|
+
... (4, 5),
|
|
65
|
+
... (4, 6),
|
|
66
|
+
... (5, 6),
|
|
67
|
+
... ]
|
|
68
|
+
>>> G = nx.Graph(e)
|
|
69
|
+
>>> nx.is_chordal(G)
|
|
70
|
+
True
|
|
71
|
+
|
|
72
|
+
Notes
|
|
73
|
+
-----
|
|
74
|
+
The routine tries to go through every node following maximum cardinality
|
|
75
|
+
search. It returns False when it finds that the separator for any node
|
|
76
|
+
is not a clique. Based on the algorithms in [1]_.
|
|
77
|
+
|
|
78
|
+
Self loops are ignored.
|
|
79
|
+
|
|
80
|
+
References
|
|
81
|
+
----------
|
|
82
|
+
.. [1] R. E. Tarjan and M. Yannakakis, Simple linear-time algorithms
|
|
83
|
+
to test chordality of graphs, test acyclicity of hypergraphs, and
|
|
84
|
+
selectively reduce acyclic hypergraphs, SIAM J. Comput., 13 (1984),
|
|
85
|
+
pp. 566–579.
|
|
86
|
+
"""
|
|
87
|
+
if len(G.nodes) <= 3:
|
|
88
|
+
return True
|
|
89
|
+
return len(_find_chordality_breaker(G)) == 0
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@nx._dispatchable
|
|
93
|
+
def find_induced_nodes(G, s, t, treewidth_bound=sys.maxsize):
|
|
94
|
+
"""Returns the set of induced nodes in the path from s to t.
|
|
95
|
+
|
|
96
|
+
Parameters
|
|
97
|
+
----------
|
|
98
|
+
G : graph
|
|
99
|
+
A chordal NetworkX graph
|
|
100
|
+
s : node
|
|
101
|
+
Source node to look for induced nodes
|
|
102
|
+
t : node
|
|
103
|
+
Destination node to look for induced nodes
|
|
104
|
+
treewidth_bound: float
|
|
105
|
+
Maximum treewidth acceptable for the graph H. The search
|
|
106
|
+
for induced nodes will end as soon as the treewidth_bound is exceeded.
|
|
107
|
+
|
|
108
|
+
Returns
|
|
109
|
+
-------
|
|
110
|
+
induced_nodes : Set of nodes
|
|
111
|
+
The set of induced nodes in the path from s to t in G
|
|
112
|
+
|
|
113
|
+
Raises
|
|
114
|
+
------
|
|
115
|
+
NetworkXError
|
|
116
|
+
The algorithm does not support DiGraph, MultiGraph and MultiDiGraph.
|
|
117
|
+
If the input graph is an instance of one of these classes, a
|
|
118
|
+
:exc:`NetworkXError` is raised.
|
|
119
|
+
The algorithm can only be applied to chordal graphs. If the input
|
|
120
|
+
graph is found to be non-chordal, a :exc:`NetworkXError` is raised.
|
|
121
|
+
|
|
122
|
+
Examples
|
|
123
|
+
--------
|
|
124
|
+
>>> G = nx.Graph()
|
|
125
|
+
>>> G = nx.generators.classic.path_graph(10)
|
|
126
|
+
>>> induced_nodes = nx.find_induced_nodes(G, 1, 9, 2)
|
|
127
|
+
>>> sorted(induced_nodes)
|
|
128
|
+
[1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
129
|
+
|
|
130
|
+
Notes
|
|
131
|
+
-----
|
|
132
|
+
G must be a chordal graph and (s,t) an edge that is not in G.
|
|
133
|
+
|
|
134
|
+
If a treewidth_bound is provided, the search for induced nodes will end
|
|
135
|
+
as soon as the treewidth_bound is exceeded.
|
|
136
|
+
|
|
137
|
+
The algorithm is inspired by Algorithm 4 in [1]_.
|
|
138
|
+
A formal definition of induced node can also be found on that reference.
|
|
139
|
+
|
|
140
|
+
Self Loops are ignored
|
|
141
|
+
|
|
142
|
+
References
|
|
143
|
+
----------
|
|
144
|
+
.. [1] Learning Bounded Treewidth Bayesian Networks.
|
|
145
|
+
Gal Elidan, Stephen Gould; JMLR, 9(Dec):2699--2731, 2008.
|
|
146
|
+
http://jmlr.csail.mit.edu/papers/volume9/elidan08a/elidan08a.pdf
|
|
147
|
+
"""
|
|
148
|
+
if not is_chordal(G):
|
|
149
|
+
raise nx.NetworkXError("Input graph is not chordal.")
|
|
150
|
+
|
|
151
|
+
H = nx.Graph(G)
|
|
152
|
+
H.add_edge(s, t)
|
|
153
|
+
induced_nodes = set()
|
|
154
|
+
triplet = _find_chordality_breaker(H, s, treewidth_bound)
|
|
155
|
+
while triplet:
|
|
156
|
+
(u, v, w) = triplet
|
|
157
|
+
induced_nodes.update(triplet)
|
|
158
|
+
for n in triplet:
|
|
159
|
+
if n != s:
|
|
160
|
+
H.add_edge(s, n)
|
|
161
|
+
triplet = _find_chordality_breaker(H, s, treewidth_bound)
|
|
162
|
+
if induced_nodes:
|
|
163
|
+
# Add t and the second node in the induced path from s to t.
|
|
164
|
+
induced_nodes.add(t)
|
|
165
|
+
for u in G[s]:
|
|
166
|
+
if len(induced_nodes & set(G[u])) == 2:
|
|
167
|
+
induced_nodes.add(u)
|
|
168
|
+
break
|
|
169
|
+
return induced_nodes
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
@nx._dispatchable
|
|
173
|
+
def chordal_graph_cliques(G):
|
|
174
|
+
"""Returns all maximal cliques of a chordal graph.
|
|
175
|
+
|
|
176
|
+
The algorithm breaks the graph in connected components and performs a
|
|
177
|
+
maximum cardinality search in each component to get the cliques.
|
|
178
|
+
|
|
179
|
+
Parameters
|
|
180
|
+
----------
|
|
181
|
+
G : graph
|
|
182
|
+
A NetworkX graph
|
|
183
|
+
|
|
184
|
+
Yields
|
|
185
|
+
------
|
|
186
|
+
frozenset of nodes
|
|
187
|
+
Maximal cliques, each of which is a frozenset of
|
|
188
|
+
nodes in `G`. The order of cliques is arbitrary.
|
|
189
|
+
|
|
190
|
+
Raises
|
|
191
|
+
------
|
|
192
|
+
NetworkXError
|
|
193
|
+
The algorithm does not support DiGraph, MultiGraph and MultiDiGraph.
|
|
194
|
+
The algorithm can only be applied to chordal graphs. If the input
|
|
195
|
+
graph is found to be non-chordal, a :exc:`NetworkXError` is raised.
|
|
196
|
+
|
|
197
|
+
Examples
|
|
198
|
+
--------
|
|
199
|
+
>>> e = [
|
|
200
|
+
... (1, 2),
|
|
201
|
+
... (1, 3),
|
|
202
|
+
... (2, 3),
|
|
203
|
+
... (2, 4),
|
|
204
|
+
... (3, 4),
|
|
205
|
+
... (3, 5),
|
|
206
|
+
... (3, 6),
|
|
207
|
+
... (4, 5),
|
|
208
|
+
... (4, 6),
|
|
209
|
+
... (5, 6),
|
|
210
|
+
... (7, 8),
|
|
211
|
+
... ]
|
|
212
|
+
>>> G = nx.Graph(e)
|
|
213
|
+
>>> G.add_node(9)
|
|
214
|
+
>>> cliques = [c for c in chordal_graph_cliques(G)]
|
|
215
|
+
>>> cliques[0]
|
|
216
|
+
frozenset({1, 2, 3})
|
|
217
|
+
"""
|
|
218
|
+
for C in (G.subgraph(c).copy() for c in connected_components(G)):
|
|
219
|
+
if C.number_of_nodes() == 1:
|
|
220
|
+
if nx.number_of_selfloops(C) > 0:
|
|
221
|
+
raise nx.NetworkXError("Input graph is not chordal.")
|
|
222
|
+
yield frozenset(C.nodes())
|
|
223
|
+
else:
|
|
224
|
+
unnumbered = set(C.nodes())
|
|
225
|
+
v = arbitrary_element(C)
|
|
226
|
+
unnumbered.remove(v)
|
|
227
|
+
numbered = {v}
|
|
228
|
+
clique_wanna_be = {v}
|
|
229
|
+
while unnumbered:
|
|
230
|
+
v = _max_cardinality_node(C, unnumbered, numbered)
|
|
231
|
+
unnumbered.remove(v)
|
|
232
|
+
numbered.add(v)
|
|
233
|
+
new_clique_wanna_be = set(C.neighbors(v)) & numbered
|
|
234
|
+
sg = C.subgraph(clique_wanna_be)
|
|
235
|
+
if _is_complete_graph(sg):
|
|
236
|
+
new_clique_wanna_be.add(v)
|
|
237
|
+
if not new_clique_wanna_be >= clique_wanna_be:
|
|
238
|
+
yield frozenset(clique_wanna_be)
|
|
239
|
+
clique_wanna_be = new_clique_wanna_be
|
|
240
|
+
else:
|
|
241
|
+
raise nx.NetworkXError("Input graph is not chordal.")
|
|
242
|
+
yield frozenset(clique_wanna_be)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
@nx._dispatchable
|
|
246
|
+
def chordal_graph_treewidth(G):
|
|
247
|
+
"""Returns the treewidth of the chordal graph G.
|
|
248
|
+
|
|
249
|
+
Parameters
|
|
250
|
+
----------
|
|
251
|
+
G : graph
|
|
252
|
+
A NetworkX graph
|
|
253
|
+
|
|
254
|
+
Returns
|
|
255
|
+
-------
|
|
256
|
+
treewidth : int
|
|
257
|
+
The size of the largest clique in the graph minus one.
|
|
258
|
+
|
|
259
|
+
Raises
|
|
260
|
+
------
|
|
261
|
+
NetworkXError
|
|
262
|
+
The algorithm does not support DiGraph, MultiGraph and MultiDiGraph.
|
|
263
|
+
The algorithm can only be applied to chordal graphs. If the input
|
|
264
|
+
graph is found to be non-chordal, a :exc:`NetworkXError` is raised.
|
|
265
|
+
|
|
266
|
+
Examples
|
|
267
|
+
--------
|
|
268
|
+
>>> e = [
|
|
269
|
+
... (1, 2),
|
|
270
|
+
... (1, 3),
|
|
271
|
+
... (2, 3),
|
|
272
|
+
... (2, 4),
|
|
273
|
+
... (3, 4),
|
|
274
|
+
... (3, 5),
|
|
275
|
+
... (3, 6),
|
|
276
|
+
... (4, 5),
|
|
277
|
+
... (4, 6),
|
|
278
|
+
... (5, 6),
|
|
279
|
+
... (7, 8),
|
|
280
|
+
... ]
|
|
281
|
+
>>> G = nx.Graph(e)
|
|
282
|
+
>>> G.add_node(9)
|
|
283
|
+
>>> nx.chordal_graph_treewidth(G)
|
|
284
|
+
3
|
|
285
|
+
|
|
286
|
+
References
|
|
287
|
+
----------
|
|
288
|
+
.. [1] https://en.wikipedia.org/wiki/Tree_decomposition#Treewidth
|
|
289
|
+
"""
|
|
290
|
+
if not is_chordal(G):
|
|
291
|
+
raise nx.NetworkXError("Input graph is not chordal.")
|
|
292
|
+
|
|
293
|
+
max_clique = -1
|
|
294
|
+
for clique in nx.chordal_graph_cliques(G):
|
|
295
|
+
max_clique = max(max_clique, len(clique))
|
|
296
|
+
return max_clique - 1
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def _is_complete_graph(G):
|
|
300
|
+
"""Returns True if G is a complete graph."""
|
|
301
|
+
if nx.number_of_selfloops(G) > 0:
|
|
302
|
+
raise nx.NetworkXError("Self loop found in _is_complete_graph()")
|
|
303
|
+
n = G.number_of_nodes()
|
|
304
|
+
if n < 2:
|
|
305
|
+
return True
|
|
306
|
+
e = G.number_of_edges()
|
|
307
|
+
max_edges = (n * (n - 1)) / 2
|
|
308
|
+
return e == max_edges
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def _find_missing_edge(G):
|
|
312
|
+
"""Given a non-complete graph G, returns a missing edge."""
|
|
313
|
+
nodes = set(G)
|
|
314
|
+
for u in G:
|
|
315
|
+
missing = nodes - set(list(G[u].keys()) + [u])
|
|
316
|
+
if missing:
|
|
317
|
+
return (u, missing.pop())
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def _max_cardinality_node(G, choices, wanna_connect):
|
|
321
|
+
"""Returns a the node in choices that has more connections in G
|
|
322
|
+
to nodes in wanna_connect.
|
|
323
|
+
"""
|
|
324
|
+
max_number = -1
|
|
325
|
+
for x in choices:
|
|
326
|
+
number = len([y for y in G[x] if y in wanna_connect])
|
|
327
|
+
if number > max_number:
|
|
328
|
+
max_number = number
|
|
329
|
+
max_cardinality_node = x
|
|
330
|
+
return max_cardinality_node
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def _find_chordality_breaker(G, s=None, treewidth_bound=sys.maxsize):
|
|
334
|
+
"""Given a graph G, starts a max cardinality search
|
|
335
|
+
(starting from s if s is given and from an arbitrary node otherwise)
|
|
336
|
+
trying to find a non-chordal cycle.
|
|
337
|
+
|
|
338
|
+
If it does find one, it returns (u,v,w) where u,v,w are the three
|
|
339
|
+
nodes that together with s are involved in the cycle.
|
|
340
|
+
|
|
341
|
+
It ignores any self loops.
|
|
342
|
+
"""
|
|
343
|
+
if len(G) == 0:
|
|
344
|
+
raise nx.NetworkXPointlessConcept("Graph has no nodes.")
|
|
345
|
+
unnumbered = set(G)
|
|
346
|
+
if s is None:
|
|
347
|
+
s = arbitrary_element(G)
|
|
348
|
+
unnumbered.remove(s)
|
|
349
|
+
numbered = {s}
|
|
350
|
+
current_treewidth = -1
|
|
351
|
+
while unnumbered: # and current_treewidth <= treewidth_bound:
|
|
352
|
+
v = _max_cardinality_node(G, unnumbered, numbered)
|
|
353
|
+
unnumbered.remove(v)
|
|
354
|
+
numbered.add(v)
|
|
355
|
+
clique_wanna_be = set(G[v]) & numbered
|
|
356
|
+
sg = G.subgraph(clique_wanna_be)
|
|
357
|
+
if _is_complete_graph(sg):
|
|
358
|
+
# The graph seems to be chordal by now. We update the treewidth
|
|
359
|
+
current_treewidth = max(current_treewidth, len(clique_wanna_be))
|
|
360
|
+
if current_treewidth > treewidth_bound:
|
|
361
|
+
raise nx.NetworkXTreewidthBoundExceeded(
|
|
362
|
+
f"treewidth_bound exceeded: {current_treewidth}"
|
|
363
|
+
)
|
|
364
|
+
else:
|
|
365
|
+
# sg is not a clique,
|
|
366
|
+
# look for an edge that is not included in sg
|
|
367
|
+
(u, w) = _find_missing_edge(sg)
|
|
368
|
+
return (u, v, w)
|
|
369
|
+
return ()
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
@not_implemented_for("directed")
|
|
373
|
+
@nx._dispatchable(returns_graph=True)
|
|
374
|
+
def complete_to_chordal_graph(G):
|
|
375
|
+
"""Return a copy of G completed to a chordal graph
|
|
376
|
+
|
|
377
|
+
Adds edges to a copy of G to create a chordal graph. A graph G=(V,E) is
|
|
378
|
+
called chordal if for each cycle with length bigger than 3, there exist
|
|
379
|
+
two non-adjacent nodes connected by an edge (called a chord).
|
|
380
|
+
|
|
381
|
+
Parameters
|
|
382
|
+
----------
|
|
383
|
+
G : NetworkX graph
|
|
384
|
+
Undirected graph
|
|
385
|
+
|
|
386
|
+
Returns
|
|
387
|
+
-------
|
|
388
|
+
H : NetworkX graph
|
|
389
|
+
The chordal enhancement of G
|
|
390
|
+
alpha : Dictionary
|
|
391
|
+
The elimination ordering of nodes of G
|
|
392
|
+
|
|
393
|
+
Notes
|
|
394
|
+
-----
|
|
395
|
+
There are different approaches to calculate the chordal
|
|
396
|
+
enhancement of a graph. The algorithm used here is called
|
|
397
|
+
MCS-M and gives at least minimal (local) triangulation of graph. Note
|
|
398
|
+
that this triangulation is not necessarily a global minimum.
|
|
399
|
+
|
|
400
|
+
https://en.wikipedia.org/wiki/Chordal_graph
|
|
401
|
+
|
|
402
|
+
References
|
|
403
|
+
----------
|
|
404
|
+
.. [1] Berry, Anne & Blair, Jean & Heggernes, Pinar & Peyton, Barry. (2004)
|
|
405
|
+
Maximum Cardinality Search for Computing Minimal Triangulations of
|
|
406
|
+
Graphs. Algorithmica. 39. 287-298. 10.1007/s00453-004-1084-3.
|
|
407
|
+
|
|
408
|
+
Examples
|
|
409
|
+
--------
|
|
410
|
+
>>> from networkx.algorithms.chordal import complete_to_chordal_graph
|
|
411
|
+
>>> G = nx.wheel_graph(10)
|
|
412
|
+
>>> H, alpha = complete_to_chordal_graph(G)
|
|
413
|
+
"""
|
|
414
|
+
H = G.copy()
|
|
415
|
+
alpha = {node: 0 for node in H}
|
|
416
|
+
if nx.is_chordal(H):
|
|
417
|
+
return H, alpha
|
|
418
|
+
chords = set()
|
|
419
|
+
weight = {node: 0 for node in H.nodes()}
|
|
420
|
+
unnumbered_nodes = list(H.nodes())
|
|
421
|
+
for i in range(len(H.nodes()), 0, -1):
|
|
422
|
+
# get the node in unnumbered_nodes with the maximum weight
|
|
423
|
+
z = max(unnumbered_nodes, key=lambda node: weight[node])
|
|
424
|
+
unnumbered_nodes.remove(z)
|
|
425
|
+
alpha[z] = i
|
|
426
|
+
update_nodes = []
|
|
427
|
+
for y in unnumbered_nodes:
|
|
428
|
+
if G.has_edge(y, z):
|
|
429
|
+
update_nodes.append(y)
|
|
430
|
+
else:
|
|
431
|
+
# y_weight will be bigger than node weights between y and z
|
|
432
|
+
y_weight = weight[y]
|
|
433
|
+
lower_nodes = [
|
|
434
|
+
node for node in unnumbered_nodes if weight[node] < y_weight
|
|
435
|
+
]
|
|
436
|
+
if nx.has_path(H.subgraph(lower_nodes + [z, y]), y, z):
|
|
437
|
+
update_nodes.append(y)
|
|
438
|
+
chords.add((z, y))
|
|
439
|
+
# during calculation of paths the weights should not be updated
|
|
440
|
+
for node in update_nodes:
|
|
441
|
+
weight[node] += 1
|
|
442
|
+
H.add_edges_from(chords)
|
|
443
|
+
return H, alpha
|