okstra 0.130.4 → 0.131.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/README.md +0 -1
- package/docs/architecture.md +2 -2
- package/docs/cli.md +1 -1
- package/docs/for-ai/README.md +0 -2
- package/docs/for-ai/skills/okstra-run.md +13 -2
- package/docs/for-ai/skills/okstra-setup.md +4 -1
- package/docs/project-structure-overview.md +5 -4
- package/docs/task-process/implementation-planning.md +13 -0
- package/docs/task-process/implementation.md +17 -2
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/workers/report-writer-worker.md +7 -0
- package/runtime/bin/lib/okstra/usage.sh +4 -4
- package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
- package/runtime/prompts/lead/plan-body-verification.md +26 -5
- package/runtime/prompts/lead/report-writer.md +6 -2
- package/runtime/prompts/profiles/_common-contract.md +2 -1
- package/runtime/prompts/profiles/_implementation-deliverable.md +6 -1
- package/runtime/prompts/profiles/_implementation-executor.md +2 -2
- package/runtime/prompts/profiles/_implementation-verifier.md +33 -10
- package/runtime/prompts/profiles/final-verification.md +21 -6
- package/runtime/prompts/profiles/implementation-planning.md +16 -4
- package/runtime/python/okstra_ctl/codex_dispatch.py +31 -0
- package/runtime/python/okstra_ctl/conformance.py +49 -11
- package/runtime/python/okstra_ctl/report_finalize.py +52 -1
- package/runtime/python/okstra_ctl/run.py +15 -3
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +14 -6
- package/runtime/python/okstra_ctl/worker_prompt_policy.py +19 -1
- package/runtime/python/okstra_vendor/__init__.py +0 -44
- package/runtime/schemas/final-report-v1.0.schema.json +99 -5
- package/runtime/skills/okstra-run/SKILL.md +11 -4
- package/runtime/skills/okstra-setup/SKILL.md +3 -2
- package/runtime/skills/okstra-setup/references/project-config.md +16 -7
- package/runtime/templates/reports/final-report.template.md +15 -9
- package/runtime/templates/reports/i18n/en.json +1 -0
- package/runtime/templates/reports/i18n/ko.json +1 -0
- package/runtime/validators/lib/fixtures.sh +6 -0
- package/runtime/validators/validate-run.py +1722 -98
- package/src/cli-registry.mjs +0 -7
- package/src/commands/lifecycle/doctor.mjs +0 -9
- package/src/lib/skill-catalog.mjs +0 -1
- package/docs/for-ai/skills/okstra-graphify.md +0 -64
- package/runtime/python/okstra_ctl/graphify_cmd.py +0 -225
- package/runtime/python/okstra_vendor/graphify/.vendored-version +0 -1
- package/runtime/python/okstra_vendor/graphify/__init__.py +0 -28
- package/runtime/python/okstra_vendor/graphify/__main__.py +0 -1371
- package/runtime/python/okstra_vendor/graphify/analyze.py +0 -540
- package/runtime/python/okstra_vendor/graphify/benchmark.py +0 -129
- package/runtime/python/okstra_vendor/graphify/build.py +0 -107
- package/runtime/python/okstra_vendor/graphify/cache.py +0 -169
- package/runtime/python/okstra_vendor/graphify/cluster.py +0 -137
- package/runtime/python/okstra_vendor/graphify/detect.py +0 -510
- package/runtime/python/okstra_vendor/graphify/export.py +0 -1014
- package/runtime/python/okstra_vendor/graphify/extract.py +0 -3277
- package/runtime/python/okstra_vendor/graphify/hooks.py +0 -220
- package/runtime/python/okstra_vendor/graphify/ingest.py +0 -297
- package/runtime/python/okstra_vendor/graphify/manifest.py +0 -4
- package/runtime/python/okstra_vendor/graphify/report.py +0 -175
- package/runtime/python/okstra_vendor/graphify/security.py +0 -203
- package/runtime/python/okstra_vendor/graphify/serve.py +0 -373
- package/runtime/python/okstra_vendor/graphify/skill-aider.md +0 -1184
- package/runtime/python/okstra_vendor/graphify/skill-claw.md +0 -1184
- package/runtime/python/okstra_vendor/graphify/skill-codex.md +0 -1242
- package/runtime/python/okstra_vendor/graphify/skill-copilot.md +0 -1268
- package/runtime/python/okstra_vendor/graphify/skill-droid.md +0 -1239
- package/runtime/python/okstra_vendor/graphify/skill-kiro.md +0 -1183
- package/runtime/python/okstra_vendor/graphify/skill-opencode.md +0 -1238
- package/runtime/python/okstra_vendor/graphify/skill-trae.md +0 -1208
- package/runtime/python/okstra_vendor/graphify/skill-vscode.md +0 -253
- package/runtime/python/okstra_vendor/graphify/skill-windows.md +0 -1245
- package/runtime/python/okstra_vendor/graphify/skill.md +0 -1319
- package/runtime/python/okstra_vendor/graphify/transcribe.py +0 -182
- package/runtime/python/okstra_vendor/graphify/validate.py +0 -72
- package/runtime/python/okstra_vendor/graphify/watch.py +0 -188
- package/runtime/python/okstra_vendor/graphify/wiki.py +0 -214
- package/runtime/python/okstra_vendor/networkx/__init__.py +0 -62
- package/runtime/python/okstra_vendor/networkx/algorithms/__init__.py +0 -134
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/__init__.py +0 -26
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/clique.py +0 -259
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/clustering_coefficient.py +0 -71
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/connectivity.py +0 -412
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/density.py +0 -396
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/distance_measures.py +0 -150
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/dominating_set.py +0 -149
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/kcomponents.py +0 -369
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/matching.py +0 -44
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/maxcut.py +0 -143
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/ramsey.py +0 -53
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/steinertree.py +0 -265
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/traveling_salesman.py +0 -1508
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/treewidth.py +0 -255
- package/runtime/python/okstra_vendor/networkx/algorithms/approximation/vertex_cover.py +0 -83
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/__init__.py +0 -5
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/connectivity.py +0 -122
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/correlation.py +0 -302
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/mixing.py +0 -255
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/neighbor_degree.py +0 -160
- package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/pairs.py +0 -127
- package/runtime/python/okstra_vendor/networkx/algorithms/asteroidal.py +0 -164
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/__init__.py +0 -88
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/basic.py +0 -322
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/centrality.py +0 -290
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/cluster.py +0 -289
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/covering.py +0 -57
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/edgelist.py +0 -360
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/extendability.py +0 -105
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/generators.py +0 -603
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/link_analysis.py +0 -316
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/matching.py +0 -590
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/matrix.py +0 -232
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/projection.py +0 -526
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/redundancy.py +0 -112
- package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/spectral.py +0 -69
- package/runtime/python/okstra_vendor/networkx/algorithms/boundary.py +0 -168
- package/runtime/python/okstra_vendor/networkx/algorithms/bridges.py +0 -205
- package/runtime/python/okstra_vendor/networkx/algorithms/broadcasting.py +0 -164
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/__init__.py +0 -20
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/betweenness.py +0 -591
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/betweenness_subset.py +0 -236
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/closeness.py +0 -282
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_betweenness.py +0 -364
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_betweenness_subset.py +0 -227
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_closeness.py +0 -96
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/degree_alg.py +0 -150
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/dispersion.py +0 -107
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/eigenvector.py +0 -357
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/flow_matrix.py +0 -130
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/group.py +0 -787
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/harmonic.py +0 -88
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/katz.py +0 -331
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/laplacian.py +0 -150
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/load.py +0 -200
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/percolation.py +0 -128
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/reaching.py +0 -209
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/second_order.py +0 -141
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/subgraph_alg.py +0 -361
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/trophic.py +0 -181
- package/runtime/python/okstra_vendor/networkx/algorithms/centrality/voterank_alg.py +0 -95
- package/runtime/python/okstra_vendor/networkx/algorithms/chains.py +0 -172
- package/runtime/python/okstra_vendor/networkx/algorithms/chordal.py +0 -443
- package/runtime/python/okstra_vendor/networkx/algorithms/clique.py +0 -818
- package/runtime/python/okstra_vendor/networkx/algorithms/cluster.py +0 -732
- package/runtime/python/okstra_vendor/networkx/algorithms/coloring/__init__.py +0 -4
- package/runtime/python/okstra_vendor/networkx/algorithms/coloring/equitable_coloring.py +0 -505
- package/runtime/python/okstra_vendor/networkx/algorithms/coloring/greedy_coloring.py +0 -565
- package/runtime/python/okstra_vendor/networkx/algorithms/communicability_alg.py +0 -163
- package/runtime/python/okstra_vendor/networkx/algorithms/community/__init__.py +0 -28
- package/runtime/python/okstra_vendor/networkx/algorithms/community/asyn_fluid.py +0 -153
- package/runtime/python/okstra_vendor/networkx/algorithms/community/bipartitions.py +0 -354
- package/runtime/python/okstra_vendor/networkx/algorithms/community/centrality.py +0 -171
- package/runtime/python/okstra_vendor/networkx/algorithms/community/community_utils.py +0 -30
- package/runtime/python/okstra_vendor/networkx/algorithms/community/divisive.py +0 -216
- package/runtime/python/okstra_vendor/networkx/algorithms/community/kclique.py +0 -79
- package/runtime/python/okstra_vendor/networkx/algorithms/community/label_propagation.py +0 -338
- package/runtime/python/okstra_vendor/networkx/algorithms/community/leiden.py +0 -162
- package/runtime/python/okstra_vendor/networkx/algorithms/community/local.py +0 -220
- package/runtime/python/okstra_vendor/networkx/algorithms/community/louvain.py +0 -384
- package/runtime/python/okstra_vendor/networkx/algorithms/community/lukes.py +0 -227
- package/runtime/python/okstra_vendor/networkx/algorithms/community/modularity_max.py +0 -452
- package/runtime/python/okstra_vendor/networkx/algorithms/community/quality.py +0 -347
- package/runtime/python/okstra_vendor/networkx/algorithms/components/__init__.py +0 -6
- package/runtime/python/okstra_vendor/networkx/algorithms/components/attracting.py +0 -115
- package/runtime/python/okstra_vendor/networkx/algorithms/components/biconnected.py +0 -394
- package/runtime/python/okstra_vendor/networkx/algorithms/components/connected.py +0 -282
- package/runtime/python/okstra_vendor/networkx/algorithms/components/semiconnected.py +0 -71
- package/runtime/python/okstra_vendor/networkx/algorithms/components/strongly_connected.py +0 -359
- package/runtime/python/okstra_vendor/networkx/algorithms/components/weakly_connected.py +0 -196
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/__init__.py +0 -11
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/connectivity.py +0 -811
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/cuts.py +0 -616
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/disjoint_paths.py +0 -408
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/edge_augmentation.py +0 -1270
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/edge_kcomponents.py +0 -592
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/kcomponents.py +0 -220
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/kcutsets.py +0 -235
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/stoerwagner.py +0 -152
- package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/utils.py +0 -88
- package/runtime/python/okstra_vendor/networkx/algorithms/core.py +0 -588
- package/runtime/python/okstra_vendor/networkx/algorithms/covering.py +0 -142
- package/runtime/python/okstra_vendor/networkx/algorithms/cuts.py +0 -416
- package/runtime/python/okstra_vendor/networkx/algorithms/cycles.py +0 -1234
- package/runtime/python/okstra_vendor/networkx/algorithms/d_separation.py +0 -677
- package/runtime/python/okstra_vendor/networkx/algorithms/dag.py +0 -1392
- package/runtime/python/okstra_vendor/networkx/algorithms/distance_measures.py +0 -1095
- package/runtime/python/okstra_vendor/networkx/algorithms/distance_regular.py +0 -272
- package/runtime/python/okstra_vendor/networkx/algorithms/dominance.py +0 -142
- package/runtime/python/okstra_vendor/networkx/algorithms/dominating.py +0 -268
- package/runtime/python/okstra_vendor/networkx/algorithms/efficiency_measures.py +0 -167
- package/runtime/python/okstra_vendor/networkx/algorithms/euler.py +0 -470
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/__init__.py +0 -11
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/boykovkolmogorov.py +0 -370
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/capacityscaling.py +0 -407
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/dinitz_alg.py +0 -238
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/edmondskarp.py +0 -241
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/gomory_hu.py +0 -178
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/maxflow.py +0 -611
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/mincost.py +0 -356
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/networksimplex.py +0 -662
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/preflowpush.py +0 -425
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/shortestaugmentingpath.py +0 -300
- package/runtime/python/okstra_vendor/networkx/algorithms/flow/utils.py +0 -194
- package/runtime/python/okstra_vendor/networkx/algorithms/graph_hashing.py +0 -435
- package/runtime/python/okstra_vendor/networkx/algorithms/graphical.py +0 -483
- package/runtime/python/okstra_vendor/networkx/algorithms/hierarchy.py +0 -57
- package/runtime/python/okstra_vendor/networkx/algorithms/hybrid.py +0 -196
- package/runtime/python/okstra_vendor/networkx/algorithms/isolate.py +0 -107
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/__init__.py +0 -7
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/ismags.py +0 -1306
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/isomorph.py +0 -336
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/isomorphvf2.py +0 -1262
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/matchhelpers.py +0 -352
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/temporalisomorphvf2.py +0 -308
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tree_isomorphism.py +0 -264
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/vf2pp.py +0 -1102
- package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/vf2userfunc.py +0 -192
- package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/__init__.py +0 -2
- package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/hits_alg.py +0 -337
- package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/pagerank_alg.py +0 -498
- package/runtime/python/okstra_vendor/networkx/algorithms/link_prediction.py +0 -687
- package/runtime/python/okstra_vendor/networkx/algorithms/lowest_common_ancestors.py +0 -280
- package/runtime/python/okstra_vendor/networkx/algorithms/matching.py +0 -1148
- package/runtime/python/okstra_vendor/networkx/algorithms/minors/__init__.py +0 -27
- package/runtime/python/okstra_vendor/networkx/algorithms/minors/contraction.py +0 -738
- package/runtime/python/okstra_vendor/networkx/algorithms/mis.py +0 -78
- package/runtime/python/okstra_vendor/networkx/algorithms/moral.py +0 -59
- package/runtime/python/okstra_vendor/networkx/algorithms/node_classification.py +0 -219
- package/runtime/python/okstra_vendor/networkx/algorithms/non_randomness.py +0 -155
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/__init__.py +0 -4
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/all.py +0 -324
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/binary.py +0 -468
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/product.py +0 -633
- package/runtime/python/okstra_vendor/networkx/algorithms/operators/unary.py +0 -77
- package/runtime/python/okstra_vendor/networkx/algorithms/perfect_graph.py +0 -73
- package/runtime/python/okstra_vendor/networkx/algorithms/planar_drawing.py +0 -464
- package/runtime/python/okstra_vendor/networkx/algorithms/planarity.py +0 -1463
- package/runtime/python/okstra_vendor/networkx/algorithms/polynomials.py +0 -306
- package/runtime/python/okstra_vendor/networkx/algorithms/reciprocity.py +0 -98
- package/runtime/python/okstra_vendor/networkx/algorithms/regular.py +0 -167
- package/runtime/python/okstra_vendor/networkx/algorithms/richclub.py +0 -138
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/__init__.py +0 -5
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/astar.py +0 -239
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/dense.py +0 -264
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/generic.py +0 -716
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/unweighted.py +0 -625
- package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/weighted.py +0 -2542
- package/runtime/python/okstra_vendor/networkx/algorithms/similarity.py +0 -2107
- package/runtime/python/okstra_vendor/networkx/algorithms/simple_paths.py +0 -966
- package/runtime/python/okstra_vendor/networkx/algorithms/smallworld.py +0 -404
- package/runtime/python/okstra_vendor/networkx/algorithms/smetric.py +0 -30
- package/runtime/python/okstra_vendor/networkx/algorithms/sparsifiers.py +0 -296
- package/runtime/python/okstra_vendor/networkx/algorithms/structuralholes.py +0 -374
- package/runtime/python/okstra_vendor/networkx/algorithms/summarization.py +0 -564
- package/runtime/python/okstra_vendor/networkx/algorithms/swap.py +0 -406
- package/runtime/python/okstra_vendor/networkx/algorithms/threshold.py +0 -981
- package/runtime/python/okstra_vendor/networkx/algorithms/time_dependent.py +0 -142
- package/runtime/python/okstra_vendor/networkx/algorithms/tournament.py +0 -406
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/__init__.py +0 -5
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/beamsearch.py +0 -90
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/breadth_first_search.py +0 -576
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/depth_first_search.py +0 -529
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/edgebfs.py +0 -185
- package/runtime/python/okstra_vendor/networkx/algorithms/traversal/edgedfs.py +0 -182
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/__init__.py +0 -7
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/branchings.py +0 -1042
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/coding.py +0 -413
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/decomposition.py +0 -88
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/distance_measures.py +0 -219
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/mst.py +0 -1281
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/operations.py +0 -106
- package/runtime/python/okstra_vendor/networkx/algorithms/tree/recognition.py +0 -273
- package/runtime/python/okstra_vendor/networkx/algorithms/triads.py +0 -500
- package/runtime/python/okstra_vendor/networkx/algorithms/vitality.py +0 -76
- package/runtime/python/okstra_vendor/networkx/algorithms/voronoi.py +0 -86
- package/runtime/python/okstra_vendor/networkx/algorithms/walks.py +0 -77
- package/runtime/python/okstra_vendor/networkx/algorithms/wiener.py +0 -278
- package/runtime/python/okstra_vendor/networkx/classes/__init__.py +0 -13
- package/runtime/python/okstra_vendor/networkx/classes/coreviews.py +0 -435
- package/runtime/python/okstra_vendor/networkx/classes/digraph.py +0 -1363
- package/runtime/python/okstra_vendor/networkx/classes/filters.py +0 -95
- package/runtime/python/okstra_vendor/networkx/classes/function.py +0 -1549
- package/runtime/python/okstra_vendor/networkx/classes/graph.py +0 -2082
- package/runtime/python/okstra_vendor/networkx/classes/graphviews.py +0 -269
- package/runtime/python/okstra_vendor/networkx/classes/multidigraph.py +0 -977
- package/runtime/python/okstra_vendor/networkx/classes/multigraph.py +0 -1294
- package/runtime/python/okstra_vendor/networkx/classes/reportviews.py +0 -1447
- package/runtime/python/okstra_vendor/networkx/convert.py +0 -502
- package/runtime/python/okstra_vendor/networkx/convert_matrix.py +0 -1314
- package/runtime/python/okstra_vendor/networkx/drawing/__init__.py +0 -7
- package/runtime/python/okstra_vendor/networkx/drawing/layout.py +0 -2036
- package/runtime/python/okstra_vendor/networkx/drawing/nx_agraph.py +0 -470
- package/runtime/python/okstra_vendor/networkx/drawing/nx_latex.py +0 -570
- package/runtime/python/okstra_vendor/networkx/drawing/nx_pydot.py +0 -361
- package/runtime/python/okstra_vendor/networkx/drawing/nx_pylab.py +0 -2978
- package/runtime/python/okstra_vendor/networkx/exception.py +0 -131
- package/runtime/python/okstra_vendor/networkx/generators/__init__.py +0 -34
- package/runtime/python/okstra_vendor/networkx/generators/atlas.dat.gz +0 -0
- package/runtime/python/okstra_vendor/networkx/generators/atlas.py +0 -227
- package/runtime/python/okstra_vendor/networkx/generators/classic.py +0 -1091
- package/runtime/python/okstra_vendor/networkx/generators/cographs.py +0 -68
- package/runtime/python/okstra_vendor/networkx/generators/community.py +0 -1070
- package/runtime/python/okstra_vendor/networkx/generators/degree_seq.py +0 -886
- package/runtime/python/okstra_vendor/networkx/generators/directed.py +0 -572
- package/runtime/python/okstra_vendor/networkx/generators/duplication.py +0 -174
- package/runtime/python/okstra_vendor/networkx/generators/ego.py +0 -66
- package/runtime/python/okstra_vendor/networkx/generators/expanders.py +0 -499
- package/runtime/python/okstra_vendor/networkx/generators/geometric.py +0 -1037
- package/runtime/python/okstra_vendor/networkx/generators/harary_graph.py +0 -163
- package/runtime/python/okstra_vendor/networkx/generators/internet_as_graphs.py +0 -443
- package/runtime/python/okstra_vendor/networkx/generators/intersection.py +0 -125
- package/runtime/python/okstra_vendor/networkx/generators/interval_graph.py +0 -70
- package/runtime/python/okstra_vendor/networkx/generators/joint_degree_seq.py +0 -664
- package/runtime/python/okstra_vendor/networkx/generators/lattice.py +0 -405
- package/runtime/python/okstra_vendor/networkx/generators/line.py +0 -501
- package/runtime/python/okstra_vendor/networkx/generators/mycielski.py +0 -110
- package/runtime/python/okstra_vendor/networkx/generators/nonisomorphic_trees.py +0 -259
- package/runtime/python/okstra_vendor/networkx/generators/random_clustered.py +0 -117
- package/runtime/python/okstra_vendor/networkx/generators/random_graphs.py +0 -1416
- package/runtime/python/okstra_vendor/networkx/generators/small.py +0 -1070
- package/runtime/python/okstra_vendor/networkx/generators/social.py +0 -554
- package/runtime/python/okstra_vendor/networkx/generators/spectral_graph_forge.py +0 -120
- package/runtime/python/okstra_vendor/networkx/generators/stochastic.py +0 -54
- package/runtime/python/okstra_vendor/networkx/generators/sudoku.py +0 -131
- package/runtime/python/okstra_vendor/networkx/generators/time_series.py +0 -74
- package/runtime/python/okstra_vendor/networkx/generators/trees.py +0 -1070
- package/runtime/python/okstra_vendor/networkx/generators/triads.py +0 -94
- package/runtime/python/okstra_vendor/networkx/lazy_imports.py +0 -188
- package/runtime/python/okstra_vendor/networkx/linalg/__init__.py +0 -13
- package/runtime/python/okstra_vendor/networkx/linalg/algebraicconnectivity.py +0 -650
- package/runtime/python/okstra_vendor/networkx/linalg/attrmatrix.py +0 -466
- package/runtime/python/okstra_vendor/networkx/linalg/bethehessianmatrix.py +0 -77
- package/runtime/python/okstra_vendor/networkx/linalg/graphmatrix.py +0 -168
- package/runtime/python/okstra_vendor/networkx/linalg/laplacianmatrix.py +0 -512
- package/runtime/python/okstra_vendor/networkx/linalg/modularitymatrix.py +0 -166
- package/runtime/python/okstra_vendor/networkx/linalg/spectrum.py +0 -186
- package/runtime/python/okstra_vendor/networkx/readwrite/__init__.py +0 -17
- package/runtime/python/okstra_vendor/networkx/readwrite/adjlist.py +0 -330
- package/runtime/python/okstra_vendor/networkx/readwrite/edgelist.py +0 -489
- package/runtime/python/okstra_vendor/networkx/readwrite/gexf.py +0 -1084
- package/runtime/python/okstra_vendor/networkx/readwrite/gml.py +0 -879
- package/runtime/python/okstra_vendor/networkx/readwrite/graph6.py +0 -427
- package/runtime/python/okstra_vendor/networkx/readwrite/graphml.py +0 -1053
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/__init__.py +0 -19
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/adjacency.py +0 -156
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/cytoscape.py +0 -190
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/node_link.py +0 -261
- package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tree.py +0 -137
- package/runtime/python/okstra_vendor/networkx/readwrite/leda.py +0 -108
- package/runtime/python/okstra_vendor/networkx/readwrite/multiline_adjlist.py +0 -393
- package/runtime/python/okstra_vendor/networkx/readwrite/p2g.py +0 -113
- package/runtime/python/okstra_vendor/networkx/readwrite/pajek.py +0 -286
- package/runtime/python/okstra_vendor/networkx/readwrite/sparse6.py +0 -379
- package/runtime/python/okstra_vendor/networkx/readwrite/text.py +0 -851
- package/runtime/python/okstra_vendor/networkx/relabel.py +0 -285
- package/runtime/python/okstra_vendor/networkx/utils/__init__.py +0 -8
- package/runtime/python/okstra_vendor/networkx/utils/backends.py +0 -2171
- package/runtime/python/okstra_vendor/networkx/utils/configs.py +0 -396
- package/runtime/python/okstra_vendor/networkx/utils/decorators.py +0 -1233
- package/runtime/python/okstra_vendor/networkx/utils/heaps.py +0 -338
- package/runtime/python/okstra_vendor/networkx/utils/mapped_queue.py +0 -297
- package/runtime/python/okstra_vendor/networkx/utils/misc.py +0 -703
- package/runtime/python/okstra_vendor/networkx/utils/random_sequence.py +0 -198
- package/runtime/python/okstra_vendor/networkx/utils/rcm.py +0 -159
- package/runtime/python/okstra_vendor/networkx/utils/union_find.py +0 -106
- package/runtime/skills/okstra-graphify/SKILL.md +0 -169
- package/src/commands/graphify.mjs +0 -32
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
"""Provides functions for computing the efficiency of nodes and graphs."""
|
|
2
|
-
|
|
3
|
-
import networkx as nx
|
|
4
|
-
from networkx.exception import NetworkXNoPath
|
|
5
|
-
|
|
6
|
-
from ..utils import not_implemented_for
|
|
7
|
-
|
|
8
|
-
__all__ = ["efficiency", "local_efficiency", "global_efficiency"]
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@not_implemented_for("directed")
|
|
12
|
-
@nx._dispatchable
|
|
13
|
-
def efficiency(G, u, v):
|
|
14
|
-
"""Returns the efficiency of a pair of nodes in a graph.
|
|
15
|
-
|
|
16
|
-
The *efficiency* of a pair of nodes is the multiplicative inverse of the
|
|
17
|
-
shortest path distance between the nodes [1]_. Returns 0 if no path
|
|
18
|
-
between nodes.
|
|
19
|
-
|
|
20
|
-
Parameters
|
|
21
|
-
----------
|
|
22
|
-
G : :class:`networkx.Graph`
|
|
23
|
-
An undirected graph for which to compute the average local efficiency.
|
|
24
|
-
u, v : node
|
|
25
|
-
Nodes in the graph ``G``.
|
|
26
|
-
|
|
27
|
-
Returns
|
|
28
|
-
-------
|
|
29
|
-
float
|
|
30
|
-
Multiplicative inverse of the shortest path distance between the nodes.
|
|
31
|
-
|
|
32
|
-
Examples
|
|
33
|
-
--------
|
|
34
|
-
>>> G = nx.Graph([(0, 1), (0, 2), (0, 3), (1, 2), (1, 3)])
|
|
35
|
-
>>> nx.efficiency(G, 2, 3) # this gives efficiency for node 2 and 3
|
|
36
|
-
0.5
|
|
37
|
-
|
|
38
|
-
Notes
|
|
39
|
-
-----
|
|
40
|
-
Edge weights are ignored when computing the shortest path distances.
|
|
41
|
-
|
|
42
|
-
See also
|
|
43
|
-
--------
|
|
44
|
-
local_efficiency
|
|
45
|
-
global_efficiency
|
|
46
|
-
|
|
47
|
-
References
|
|
48
|
-
----------
|
|
49
|
-
.. [1] Latora, Vito, and Massimo Marchiori.
|
|
50
|
-
"Efficient behavior of small-world networks."
|
|
51
|
-
*Physical Review Letters* 87.19 (2001): 198701.
|
|
52
|
-
<https://doi.org/10.1103/PhysRevLett.87.198701>
|
|
53
|
-
|
|
54
|
-
"""
|
|
55
|
-
try:
|
|
56
|
-
eff = 1 / nx.shortest_path_length(G, u, v)
|
|
57
|
-
except NetworkXNoPath:
|
|
58
|
-
eff = 0
|
|
59
|
-
return eff
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
@not_implemented_for("directed")
|
|
63
|
-
@nx._dispatchable
|
|
64
|
-
def global_efficiency(G):
|
|
65
|
-
"""Returns the average global efficiency of the graph.
|
|
66
|
-
|
|
67
|
-
The *efficiency* of a pair of nodes in a graph is the multiplicative
|
|
68
|
-
inverse of the shortest path distance between the nodes. The *average
|
|
69
|
-
global efficiency* of a graph is the average efficiency of all pairs of
|
|
70
|
-
nodes [1]_.
|
|
71
|
-
|
|
72
|
-
Parameters
|
|
73
|
-
----------
|
|
74
|
-
G : :class:`networkx.Graph`
|
|
75
|
-
An undirected graph for which to compute the average global efficiency.
|
|
76
|
-
|
|
77
|
-
Returns
|
|
78
|
-
-------
|
|
79
|
-
float
|
|
80
|
-
The average global efficiency of the graph.
|
|
81
|
-
|
|
82
|
-
Examples
|
|
83
|
-
--------
|
|
84
|
-
>>> G = nx.Graph([(0, 1), (0, 2), (0, 3), (1, 2), (1, 3)])
|
|
85
|
-
>>> round(nx.global_efficiency(G), 12)
|
|
86
|
-
0.916666666667
|
|
87
|
-
|
|
88
|
-
Notes
|
|
89
|
-
-----
|
|
90
|
-
Edge weights are ignored when computing the shortest path distances.
|
|
91
|
-
|
|
92
|
-
See also
|
|
93
|
-
--------
|
|
94
|
-
local_efficiency
|
|
95
|
-
|
|
96
|
-
References
|
|
97
|
-
----------
|
|
98
|
-
.. [1] Latora, Vito, and Massimo Marchiori.
|
|
99
|
-
"Efficient behavior of small-world networks."
|
|
100
|
-
*Physical Review Letters* 87.19 (2001): 198701.
|
|
101
|
-
<https://doi.org/10.1103/PhysRevLett.87.198701>
|
|
102
|
-
|
|
103
|
-
"""
|
|
104
|
-
n = len(G)
|
|
105
|
-
denom = n * (n - 1)
|
|
106
|
-
if denom != 0:
|
|
107
|
-
lengths = nx.all_pairs_shortest_path_length(G)
|
|
108
|
-
g_eff = 0
|
|
109
|
-
for source, targets in lengths:
|
|
110
|
-
for target, distance in targets.items():
|
|
111
|
-
if distance > 0:
|
|
112
|
-
g_eff += 1 / distance
|
|
113
|
-
g_eff /= denom
|
|
114
|
-
# g_eff = sum(1 / d for s, tgts in lengths
|
|
115
|
-
# for t, d in tgts.items() if d > 0) / denom
|
|
116
|
-
else:
|
|
117
|
-
g_eff = 0
|
|
118
|
-
# TODO This can be made more efficient by computing all pairs shortest
|
|
119
|
-
# path lengths in parallel.
|
|
120
|
-
return g_eff
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
@not_implemented_for("directed")
|
|
124
|
-
@nx._dispatchable
|
|
125
|
-
def local_efficiency(G):
|
|
126
|
-
"""Returns the average local efficiency of the graph.
|
|
127
|
-
|
|
128
|
-
The *efficiency* of a pair of nodes in a graph is the multiplicative
|
|
129
|
-
inverse of the shortest path distance between the nodes. The *local
|
|
130
|
-
efficiency* of a node in the graph is the average global efficiency of the
|
|
131
|
-
subgraph induced by the neighbors of the node. The *average local
|
|
132
|
-
efficiency* is the average of the local efficiencies of each node [1]_.
|
|
133
|
-
|
|
134
|
-
Parameters
|
|
135
|
-
----------
|
|
136
|
-
G : :class:`networkx.Graph`
|
|
137
|
-
An undirected graph for which to compute the average local efficiency.
|
|
138
|
-
|
|
139
|
-
Returns
|
|
140
|
-
-------
|
|
141
|
-
float
|
|
142
|
-
The average local efficiency of the graph.
|
|
143
|
-
|
|
144
|
-
Examples
|
|
145
|
-
--------
|
|
146
|
-
>>> G = nx.Graph([(0, 1), (0, 2), (0, 3), (1, 2), (1, 3)])
|
|
147
|
-
>>> nx.local_efficiency(G)
|
|
148
|
-
0.9166666666666667
|
|
149
|
-
|
|
150
|
-
Notes
|
|
151
|
-
-----
|
|
152
|
-
Edge weights are ignored when computing the shortest path distances.
|
|
153
|
-
|
|
154
|
-
See also
|
|
155
|
-
--------
|
|
156
|
-
global_efficiency
|
|
157
|
-
|
|
158
|
-
References
|
|
159
|
-
----------
|
|
160
|
-
.. [1] Latora, Vito, and Massimo Marchiori.
|
|
161
|
-
"Efficient behavior of small-world networks."
|
|
162
|
-
*Physical Review Letters* 87.19 (2001): 198701.
|
|
163
|
-
<https://doi.org/10.1103/PhysRevLett.87.198701>
|
|
164
|
-
|
|
165
|
-
"""
|
|
166
|
-
efficiency_list = (global_efficiency(G.subgraph(G[v])) for v in G)
|
|
167
|
-
return sum(efficiency_list) / len(G)
|
|
@@ -1,470 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Eulerian circuits and graphs.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from itertools import combinations
|
|
6
|
-
|
|
7
|
-
import networkx as nx
|
|
8
|
-
|
|
9
|
-
from ..utils import arbitrary_element, not_implemented_for
|
|
10
|
-
|
|
11
|
-
__all__ = [
|
|
12
|
-
"is_eulerian",
|
|
13
|
-
"eulerian_circuit",
|
|
14
|
-
"eulerize",
|
|
15
|
-
"is_semieulerian",
|
|
16
|
-
"has_eulerian_path",
|
|
17
|
-
"eulerian_path",
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
@nx._dispatchable
|
|
22
|
-
def is_eulerian(G):
|
|
23
|
-
"""Returns True if and only if `G` is Eulerian.
|
|
24
|
-
|
|
25
|
-
A graph is *Eulerian* if it has an Eulerian circuit. An *Eulerian
|
|
26
|
-
circuit* is a closed walk that includes each edge of a graph exactly
|
|
27
|
-
once.
|
|
28
|
-
|
|
29
|
-
Graphs with isolated vertices (i.e. vertices with zero degree) are not
|
|
30
|
-
considered to have Eulerian circuits. Therefore, if the graph is not
|
|
31
|
-
connected (or not strongly connected, for directed graphs), this function
|
|
32
|
-
returns False.
|
|
33
|
-
|
|
34
|
-
Parameters
|
|
35
|
-
----------
|
|
36
|
-
G : NetworkX graph
|
|
37
|
-
A graph, either directed or undirected.
|
|
38
|
-
|
|
39
|
-
Examples
|
|
40
|
-
--------
|
|
41
|
-
>>> nx.is_eulerian(nx.DiGraph({0: [3], 1: [2], 2: [3], 3: [0, 1]}))
|
|
42
|
-
True
|
|
43
|
-
>>> nx.is_eulerian(nx.complete_graph(5))
|
|
44
|
-
True
|
|
45
|
-
>>> nx.is_eulerian(nx.petersen_graph())
|
|
46
|
-
False
|
|
47
|
-
|
|
48
|
-
If you prefer to allow graphs with isolated vertices to have Eulerian circuits,
|
|
49
|
-
you can first remove such vertices and then call `is_eulerian` as below example shows.
|
|
50
|
-
|
|
51
|
-
>>> G = nx.Graph([(0, 1), (1, 2), (0, 2)])
|
|
52
|
-
>>> G.add_node(3)
|
|
53
|
-
>>> nx.is_eulerian(G)
|
|
54
|
-
False
|
|
55
|
-
|
|
56
|
-
>>> G.remove_nodes_from(list(nx.isolates(G)))
|
|
57
|
-
>>> nx.is_eulerian(G)
|
|
58
|
-
True
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"""
|
|
62
|
-
if G.is_directed():
|
|
63
|
-
# Every node must have equal in degree and out degree and the
|
|
64
|
-
# graph must be strongly connected
|
|
65
|
-
return all(
|
|
66
|
-
G.in_degree(n) == G.out_degree(n) for n in G
|
|
67
|
-
) and nx.is_strongly_connected(G)
|
|
68
|
-
# An undirected Eulerian graph has no vertices of odd degree and
|
|
69
|
-
# must be connected.
|
|
70
|
-
return all(d % 2 == 0 for v, d in G.degree()) and nx.is_connected(G)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
@nx._dispatchable
|
|
74
|
-
def is_semieulerian(G):
|
|
75
|
-
"""Return True iff `G` is semi-Eulerian.
|
|
76
|
-
|
|
77
|
-
G is semi-Eulerian if it has an Eulerian path but no Eulerian circuit.
|
|
78
|
-
|
|
79
|
-
See Also
|
|
80
|
-
--------
|
|
81
|
-
has_eulerian_path
|
|
82
|
-
is_eulerian
|
|
83
|
-
"""
|
|
84
|
-
return has_eulerian_path(G) and not is_eulerian(G)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def _find_path_start(G):
|
|
88
|
-
"""Return a suitable starting vertex for an Eulerian path.
|
|
89
|
-
|
|
90
|
-
If no path exists, return None.
|
|
91
|
-
"""
|
|
92
|
-
if not has_eulerian_path(G):
|
|
93
|
-
return None
|
|
94
|
-
|
|
95
|
-
if is_eulerian(G):
|
|
96
|
-
return arbitrary_element(G)
|
|
97
|
-
|
|
98
|
-
if G.is_directed():
|
|
99
|
-
v1, v2 = (v for v in G if G.in_degree(v) != G.out_degree(v))
|
|
100
|
-
# Determines which is the 'start' node (as opposed to the 'end')
|
|
101
|
-
if G.out_degree(v1) > G.in_degree(v1):
|
|
102
|
-
return v1
|
|
103
|
-
else:
|
|
104
|
-
return v2
|
|
105
|
-
|
|
106
|
-
else:
|
|
107
|
-
# In an undirected graph randomly choose one of the possibilities
|
|
108
|
-
start = [v for v in G if G.degree(v) % 2 != 0][0]
|
|
109
|
-
return start
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def _simplegraph_eulerian_circuit(G, source):
|
|
113
|
-
if G.is_directed():
|
|
114
|
-
degree = G.out_degree
|
|
115
|
-
edges = G.out_edges
|
|
116
|
-
else:
|
|
117
|
-
degree = G.degree
|
|
118
|
-
edges = G.edges
|
|
119
|
-
vertex_stack = [source]
|
|
120
|
-
last_vertex = None
|
|
121
|
-
while vertex_stack:
|
|
122
|
-
current_vertex = vertex_stack[-1]
|
|
123
|
-
if degree(current_vertex) == 0:
|
|
124
|
-
if last_vertex is not None:
|
|
125
|
-
yield (last_vertex, current_vertex)
|
|
126
|
-
last_vertex = current_vertex
|
|
127
|
-
vertex_stack.pop()
|
|
128
|
-
else:
|
|
129
|
-
_, next_vertex = arbitrary_element(edges(current_vertex))
|
|
130
|
-
vertex_stack.append(next_vertex)
|
|
131
|
-
G.remove_edge(current_vertex, next_vertex)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def _multigraph_eulerian_circuit(G, source):
|
|
135
|
-
if G.is_directed():
|
|
136
|
-
degree = G.out_degree
|
|
137
|
-
edges = G.out_edges
|
|
138
|
-
else:
|
|
139
|
-
degree = G.degree
|
|
140
|
-
edges = G.edges
|
|
141
|
-
vertex_stack = [(source, None)]
|
|
142
|
-
last_vertex = None
|
|
143
|
-
last_key = None
|
|
144
|
-
while vertex_stack:
|
|
145
|
-
current_vertex, current_key = vertex_stack[-1]
|
|
146
|
-
if degree(current_vertex) == 0:
|
|
147
|
-
if last_vertex is not None:
|
|
148
|
-
yield (last_vertex, current_vertex, last_key)
|
|
149
|
-
last_vertex, last_key = current_vertex, current_key
|
|
150
|
-
vertex_stack.pop()
|
|
151
|
-
else:
|
|
152
|
-
triple = arbitrary_element(edges(current_vertex, keys=True))
|
|
153
|
-
_, next_vertex, next_key = triple
|
|
154
|
-
vertex_stack.append((next_vertex, next_key))
|
|
155
|
-
G.remove_edge(current_vertex, next_vertex, next_key)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
@nx._dispatchable
|
|
159
|
-
def eulerian_circuit(G, source=None, keys=False):
|
|
160
|
-
"""Returns an iterator over the edges of an Eulerian circuit in `G`.
|
|
161
|
-
|
|
162
|
-
An *Eulerian circuit* is a closed walk that includes each edge of a
|
|
163
|
-
graph exactly once.
|
|
164
|
-
|
|
165
|
-
Parameters
|
|
166
|
-
----------
|
|
167
|
-
G : NetworkX graph
|
|
168
|
-
A graph, either directed or undirected.
|
|
169
|
-
|
|
170
|
-
source : node, optional
|
|
171
|
-
Starting node for circuit.
|
|
172
|
-
|
|
173
|
-
keys : bool
|
|
174
|
-
If False, edges generated by this function will be of the form
|
|
175
|
-
``(u, v)``. Otherwise, edges will be of the form ``(u, v, k)``.
|
|
176
|
-
This option is ignored unless `G` is a multigraph.
|
|
177
|
-
|
|
178
|
-
Returns
|
|
179
|
-
-------
|
|
180
|
-
edges : iterator
|
|
181
|
-
An iterator over edges in the Eulerian circuit.
|
|
182
|
-
|
|
183
|
-
Raises
|
|
184
|
-
------
|
|
185
|
-
NetworkXError
|
|
186
|
-
If the graph is not Eulerian.
|
|
187
|
-
|
|
188
|
-
See Also
|
|
189
|
-
--------
|
|
190
|
-
is_eulerian
|
|
191
|
-
|
|
192
|
-
Notes
|
|
193
|
-
-----
|
|
194
|
-
This is a linear time implementation of an algorithm adapted from [1]_.
|
|
195
|
-
|
|
196
|
-
For general information about Euler tours, see [2]_.
|
|
197
|
-
|
|
198
|
-
References
|
|
199
|
-
----------
|
|
200
|
-
.. [1] J. Edmonds, E. L. Johnson.
|
|
201
|
-
Matching, Euler tours and the Chinese postman.
|
|
202
|
-
Mathematical programming, Volume 5, Issue 1 (1973), 111-114.
|
|
203
|
-
.. [2] https://en.wikipedia.org/wiki/Eulerian_path
|
|
204
|
-
|
|
205
|
-
Examples
|
|
206
|
-
--------
|
|
207
|
-
To get an Eulerian circuit in an undirected graph::
|
|
208
|
-
|
|
209
|
-
>>> G = nx.complete_graph(3)
|
|
210
|
-
>>> list(nx.eulerian_circuit(G))
|
|
211
|
-
[(0, 2), (2, 1), (1, 0)]
|
|
212
|
-
>>> list(nx.eulerian_circuit(G, source=1))
|
|
213
|
-
[(1, 2), (2, 0), (0, 1)]
|
|
214
|
-
|
|
215
|
-
To get the sequence of vertices in an Eulerian circuit::
|
|
216
|
-
|
|
217
|
-
>>> [u for u, v in nx.eulerian_circuit(G)]
|
|
218
|
-
[0, 2, 1]
|
|
219
|
-
|
|
220
|
-
"""
|
|
221
|
-
if not is_eulerian(G):
|
|
222
|
-
raise nx.NetworkXError("G is not Eulerian.")
|
|
223
|
-
if G.is_directed():
|
|
224
|
-
G = G.reverse()
|
|
225
|
-
else:
|
|
226
|
-
G = G.copy()
|
|
227
|
-
if source is None:
|
|
228
|
-
source = arbitrary_element(G)
|
|
229
|
-
if G.is_multigraph():
|
|
230
|
-
for u, v, k in _multigraph_eulerian_circuit(G, source):
|
|
231
|
-
if keys:
|
|
232
|
-
yield u, v, k
|
|
233
|
-
else:
|
|
234
|
-
yield u, v
|
|
235
|
-
else:
|
|
236
|
-
yield from _simplegraph_eulerian_circuit(G, source)
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
@nx._dispatchable
|
|
240
|
-
def has_eulerian_path(G, source=None):
|
|
241
|
-
"""Return True iff `G` has an Eulerian path.
|
|
242
|
-
|
|
243
|
-
An Eulerian path is a path in a graph which uses each edge of a graph
|
|
244
|
-
exactly once. If `source` is specified, then this function checks
|
|
245
|
-
whether an Eulerian path that starts at node `source` exists.
|
|
246
|
-
|
|
247
|
-
A directed graph has an Eulerian path iff:
|
|
248
|
-
- at most one vertex has out_degree - in_degree = 1,
|
|
249
|
-
- at most one vertex has in_degree - out_degree = 1,
|
|
250
|
-
- every other vertex has equal in_degree and out_degree,
|
|
251
|
-
- and all of its vertices belong to a single connected
|
|
252
|
-
component of the underlying undirected graph.
|
|
253
|
-
|
|
254
|
-
If `source` is not None, an Eulerian path starting at `source` exists if no
|
|
255
|
-
other node has out_degree - in_degree = 1. This is equivalent to either
|
|
256
|
-
there exists an Eulerian circuit or `source` has out_degree - in_degree = 1
|
|
257
|
-
and the conditions above hold.
|
|
258
|
-
|
|
259
|
-
An undirected graph has an Eulerian path iff:
|
|
260
|
-
- exactly zero or two vertices have odd degree,
|
|
261
|
-
- and all of its vertices belong to a single connected component.
|
|
262
|
-
|
|
263
|
-
If `source` is not None, an Eulerian path starting at `source` exists if
|
|
264
|
-
either there exists an Eulerian circuit or `source` has an odd degree and the
|
|
265
|
-
conditions above hold.
|
|
266
|
-
|
|
267
|
-
Graphs with isolated vertices (i.e. vertices with zero degree) are not considered
|
|
268
|
-
to have an Eulerian path. Therefore, if the graph is not connected (or not strongly
|
|
269
|
-
connected, for directed graphs), this function returns False.
|
|
270
|
-
|
|
271
|
-
Parameters
|
|
272
|
-
----------
|
|
273
|
-
G : NetworkX Graph
|
|
274
|
-
The graph to find an euler path in.
|
|
275
|
-
|
|
276
|
-
source : node, optional
|
|
277
|
-
Starting node for path.
|
|
278
|
-
|
|
279
|
-
Returns
|
|
280
|
-
-------
|
|
281
|
-
Bool : True if G has an Eulerian path.
|
|
282
|
-
|
|
283
|
-
Examples
|
|
284
|
-
--------
|
|
285
|
-
If you prefer to allow graphs with isolated vertices to have Eulerian path,
|
|
286
|
-
you can first remove such vertices and then call `has_eulerian_path` as below example shows.
|
|
287
|
-
|
|
288
|
-
>>> G = nx.Graph([(0, 1), (1, 2), (0, 2)])
|
|
289
|
-
>>> G.add_node(3)
|
|
290
|
-
>>> nx.has_eulerian_path(G)
|
|
291
|
-
False
|
|
292
|
-
|
|
293
|
-
>>> G.remove_nodes_from(list(nx.isolates(G)))
|
|
294
|
-
>>> nx.has_eulerian_path(G)
|
|
295
|
-
True
|
|
296
|
-
|
|
297
|
-
See Also
|
|
298
|
-
--------
|
|
299
|
-
is_eulerian
|
|
300
|
-
eulerian_path
|
|
301
|
-
"""
|
|
302
|
-
if nx.is_eulerian(G):
|
|
303
|
-
return True
|
|
304
|
-
|
|
305
|
-
if G.is_directed():
|
|
306
|
-
ins = G.in_degree
|
|
307
|
-
outs = G.out_degree
|
|
308
|
-
# Since we know it is not eulerian, outs - ins must be 1 for source
|
|
309
|
-
if source is not None and outs[source] - ins[source] != 1:
|
|
310
|
-
return False
|
|
311
|
-
|
|
312
|
-
unbalanced_ins = 0
|
|
313
|
-
unbalanced_outs = 0
|
|
314
|
-
for v in G:
|
|
315
|
-
if ins[v] - outs[v] == 1:
|
|
316
|
-
unbalanced_ins += 1
|
|
317
|
-
elif outs[v] - ins[v] == 1:
|
|
318
|
-
unbalanced_outs += 1
|
|
319
|
-
elif ins[v] != outs[v]:
|
|
320
|
-
return False
|
|
321
|
-
|
|
322
|
-
return (
|
|
323
|
-
unbalanced_ins <= 1 and unbalanced_outs <= 1 and nx.is_weakly_connected(G)
|
|
324
|
-
)
|
|
325
|
-
else:
|
|
326
|
-
# We know it is not eulerian, so degree of source must be odd.
|
|
327
|
-
if source is not None and G.degree[source] % 2 != 1:
|
|
328
|
-
return False
|
|
329
|
-
|
|
330
|
-
# Sum is 2 since we know it is not eulerian (which implies sum is 0)
|
|
331
|
-
return sum(d % 2 == 1 for v, d in G.degree()) == 2 and nx.is_connected(G)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
@nx._dispatchable
|
|
335
|
-
def eulerian_path(G, source=None, keys=False):
|
|
336
|
-
"""Return an iterator over the edges of an Eulerian path in `G`.
|
|
337
|
-
|
|
338
|
-
Parameters
|
|
339
|
-
----------
|
|
340
|
-
G : NetworkX Graph
|
|
341
|
-
The graph in which to look for an eulerian path.
|
|
342
|
-
source : node or None (default: None)
|
|
343
|
-
The node at which to start the search. None means search over all
|
|
344
|
-
starting nodes.
|
|
345
|
-
keys : Bool (default: False)
|
|
346
|
-
Indicates whether to yield edge 3-tuples (u, v, edge_key).
|
|
347
|
-
The default yields edge 2-tuples
|
|
348
|
-
|
|
349
|
-
Yields
|
|
350
|
-
------
|
|
351
|
-
Edge tuples along the eulerian path.
|
|
352
|
-
|
|
353
|
-
Warning: If `source` provided is not the start node of an Euler path
|
|
354
|
-
will raise error even if an Euler Path exists.
|
|
355
|
-
"""
|
|
356
|
-
if not has_eulerian_path(G, source):
|
|
357
|
-
raise nx.NetworkXError("Graph has no Eulerian paths.")
|
|
358
|
-
if G.is_directed():
|
|
359
|
-
G = G.reverse()
|
|
360
|
-
if source is None or nx.is_eulerian(G) is False:
|
|
361
|
-
source = _find_path_start(G)
|
|
362
|
-
if G.is_multigraph():
|
|
363
|
-
for u, v, k in _multigraph_eulerian_circuit(G, source):
|
|
364
|
-
if keys:
|
|
365
|
-
yield u, v, k
|
|
366
|
-
else:
|
|
367
|
-
yield u, v
|
|
368
|
-
else:
|
|
369
|
-
yield from _simplegraph_eulerian_circuit(G, source)
|
|
370
|
-
else:
|
|
371
|
-
G = G.copy()
|
|
372
|
-
if source is None:
|
|
373
|
-
source = _find_path_start(G)
|
|
374
|
-
if G.is_multigraph():
|
|
375
|
-
if keys:
|
|
376
|
-
yield from reversed(
|
|
377
|
-
[(v, u, k) for u, v, k in _multigraph_eulerian_circuit(G, source)]
|
|
378
|
-
)
|
|
379
|
-
else:
|
|
380
|
-
yield from reversed(
|
|
381
|
-
[(v, u) for u, v, k in _multigraph_eulerian_circuit(G, source)]
|
|
382
|
-
)
|
|
383
|
-
else:
|
|
384
|
-
yield from reversed(
|
|
385
|
-
[(v, u) for u, v in _simplegraph_eulerian_circuit(G, source)]
|
|
386
|
-
)
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
@not_implemented_for("directed")
|
|
390
|
-
@nx._dispatchable(returns_graph=True)
|
|
391
|
-
def eulerize(G):
|
|
392
|
-
"""Transforms a graph into an Eulerian graph.
|
|
393
|
-
|
|
394
|
-
If `G` is Eulerian the result is `G` as a MultiGraph, otherwise the result is a smallest
|
|
395
|
-
(in terms of the number of edges) multigraph whose underlying simple graph is `G`.
|
|
396
|
-
|
|
397
|
-
Parameters
|
|
398
|
-
----------
|
|
399
|
-
G : NetworkX graph
|
|
400
|
-
An undirected graph
|
|
401
|
-
|
|
402
|
-
Returns
|
|
403
|
-
-------
|
|
404
|
-
G : NetworkX multigraph
|
|
405
|
-
|
|
406
|
-
Raises
|
|
407
|
-
------
|
|
408
|
-
NetworkXError
|
|
409
|
-
If the graph is not connected.
|
|
410
|
-
|
|
411
|
-
See Also
|
|
412
|
-
--------
|
|
413
|
-
is_eulerian
|
|
414
|
-
eulerian_circuit
|
|
415
|
-
|
|
416
|
-
References
|
|
417
|
-
----------
|
|
418
|
-
.. [1] J. Edmonds, E. L. Johnson.
|
|
419
|
-
Matching, Euler tours and the Chinese postman.
|
|
420
|
-
Mathematical programming, Volume 5, Issue 1 (1973), 111-114.
|
|
421
|
-
.. [2] https://en.wikipedia.org/wiki/Eulerian_path
|
|
422
|
-
.. [3] http://web.math.princeton.edu/math_alive/5/Notes1.pdf
|
|
423
|
-
|
|
424
|
-
Examples
|
|
425
|
-
--------
|
|
426
|
-
>>> G = nx.complete_graph(10)
|
|
427
|
-
>>> H = nx.eulerize(G)
|
|
428
|
-
>>> nx.is_eulerian(H)
|
|
429
|
-
True
|
|
430
|
-
|
|
431
|
-
"""
|
|
432
|
-
if G.order() == 0:
|
|
433
|
-
raise nx.NetworkXPointlessConcept("Cannot Eulerize null graph")
|
|
434
|
-
if not nx.is_connected(G):
|
|
435
|
-
raise nx.NetworkXError("G is not connected")
|
|
436
|
-
odd_degree_nodes = [n for n, d in G.degree() if d % 2 == 1]
|
|
437
|
-
G = nx.MultiGraph(G)
|
|
438
|
-
if len(odd_degree_nodes) == 0:
|
|
439
|
-
return G
|
|
440
|
-
|
|
441
|
-
# get all shortest paths between vertices of odd degree
|
|
442
|
-
odd_deg_pairs_paths = [
|
|
443
|
-
(m, {n: nx.shortest_path(G, source=m, target=n)})
|
|
444
|
-
for m, n in combinations(odd_degree_nodes, 2)
|
|
445
|
-
]
|
|
446
|
-
|
|
447
|
-
# use the number of vertices in a graph + 1 as an upper bound on
|
|
448
|
-
# the maximum length of a path in G
|
|
449
|
-
upper_bound_on_max_path_length = len(G) + 1
|
|
450
|
-
|
|
451
|
-
# use "len(G) + 1 - len(P)",
|
|
452
|
-
# where P is a shortest path between vertices n and m,
|
|
453
|
-
# as edge-weights in a new graph
|
|
454
|
-
# store the paths in the graph for easy indexing later
|
|
455
|
-
Gp = nx.Graph()
|
|
456
|
-
for n, Ps in odd_deg_pairs_paths:
|
|
457
|
-
for m, P in Ps.items():
|
|
458
|
-
if n != m:
|
|
459
|
-
Gp.add_edge(
|
|
460
|
-
m, n, weight=upper_bound_on_max_path_length - len(P), path=P
|
|
461
|
-
)
|
|
462
|
-
|
|
463
|
-
# find the minimum weight matching of edges in the weighted graph
|
|
464
|
-
best_matching = nx.Graph(list(nx.max_weight_matching(Gp)))
|
|
465
|
-
|
|
466
|
-
# duplicate each edge along each path in the set of paths in Gp
|
|
467
|
-
for m, n in best_matching.edges():
|
|
468
|
-
path = Gp[m][n]["path"]
|
|
469
|
-
G.add_edges_from(nx.utils.pairwise(path))
|
|
470
|
-
return G
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
from .maxflow import *
|
|
2
|
-
from .mincost import *
|
|
3
|
-
from .boykovkolmogorov import *
|
|
4
|
-
from .dinitz_alg import *
|
|
5
|
-
from .edmondskarp import *
|
|
6
|
-
from .gomory_hu import *
|
|
7
|
-
from .preflowpush import *
|
|
8
|
-
from .shortestaugmentingpath import *
|
|
9
|
-
from .capacityscaling import *
|
|
10
|
-
from .networksimplex import *
|
|
11
|
-
from .utils import build_flow_dict, build_residual_network
|