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,500 +0,0 @@
|
|
|
1
|
-
# See https://github.com/networkx/networkx/pull/1474
|
|
2
|
-
# Copyright 2011 Reya Group <http://www.reyagroup.com>
|
|
3
|
-
# Copyright 2011 Alex Levenson <alex@isnotinvain.com>
|
|
4
|
-
# Copyright 2011 Diederik van Liere <diederik.vanliere@rotman.utoronto.ca>
|
|
5
|
-
"""Functions for analyzing triads of a graph."""
|
|
6
|
-
|
|
7
|
-
from collections import defaultdict
|
|
8
|
-
from itertools import combinations, permutations
|
|
9
|
-
|
|
10
|
-
import networkx as nx
|
|
11
|
-
from networkx.utils import not_implemented_for, py_random_state
|
|
12
|
-
|
|
13
|
-
__all__ = [
|
|
14
|
-
"triadic_census",
|
|
15
|
-
"is_triad",
|
|
16
|
-
"all_triads",
|
|
17
|
-
"triads_by_type",
|
|
18
|
-
"triad_type",
|
|
19
|
-
]
|
|
20
|
-
|
|
21
|
-
#: The integer codes representing each type of triad.
|
|
22
|
-
#:
|
|
23
|
-
#: Triads that are the same up to symmetry have the same code.
|
|
24
|
-
TRICODES = (
|
|
25
|
-
1,
|
|
26
|
-
2,
|
|
27
|
-
2,
|
|
28
|
-
3,
|
|
29
|
-
2,
|
|
30
|
-
4,
|
|
31
|
-
6,
|
|
32
|
-
8,
|
|
33
|
-
2,
|
|
34
|
-
6,
|
|
35
|
-
5,
|
|
36
|
-
7,
|
|
37
|
-
3,
|
|
38
|
-
8,
|
|
39
|
-
7,
|
|
40
|
-
11,
|
|
41
|
-
2,
|
|
42
|
-
6,
|
|
43
|
-
4,
|
|
44
|
-
8,
|
|
45
|
-
5,
|
|
46
|
-
9,
|
|
47
|
-
9,
|
|
48
|
-
13,
|
|
49
|
-
6,
|
|
50
|
-
10,
|
|
51
|
-
9,
|
|
52
|
-
14,
|
|
53
|
-
7,
|
|
54
|
-
14,
|
|
55
|
-
12,
|
|
56
|
-
15,
|
|
57
|
-
2,
|
|
58
|
-
5,
|
|
59
|
-
6,
|
|
60
|
-
7,
|
|
61
|
-
6,
|
|
62
|
-
9,
|
|
63
|
-
10,
|
|
64
|
-
14,
|
|
65
|
-
4,
|
|
66
|
-
9,
|
|
67
|
-
9,
|
|
68
|
-
12,
|
|
69
|
-
8,
|
|
70
|
-
13,
|
|
71
|
-
14,
|
|
72
|
-
15,
|
|
73
|
-
3,
|
|
74
|
-
7,
|
|
75
|
-
8,
|
|
76
|
-
11,
|
|
77
|
-
7,
|
|
78
|
-
12,
|
|
79
|
-
14,
|
|
80
|
-
15,
|
|
81
|
-
8,
|
|
82
|
-
14,
|
|
83
|
-
13,
|
|
84
|
-
15,
|
|
85
|
-
11,
|
|
86
|
-
15,
|
|
87
|
-
15,
|
|
88
|
-
16,
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
#: The names of each type of triad. The order of the elements is
|
|
92
|
-
#: important: it corresponds to the tricodes given in :data:`TRICODES`.
|
|
93
|
-
TRIAD_NAMES = (
|
|
94
|
-
"003",
|
|
95
|
-
"012",
|
|
96
|
-
"102",
|
|
97
|
-
"021D",
|
|
98
|
-
"021U",
|
|
99
|
-
"021C",
|
|
100
|
-
"111D",
|
|
101
|
-
"111U",
|
|
102
|
-
"030T",
|
|
103
|
-
"030C",
|
|
104
|
-
"201",
|
|
105
|
-
"120D",
|
|
106
|
-
"120U",
|
|
107
|
-
"120C",
|
|
108
|
-
"210",
|
|
109
|
-
"300",
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
#: A dictionary mapping triad code to triad name.
|
|
114
|
-
TRICODE_TO_NAME = {i: TRIAD_NAMES[code - 1] for i, code in enumerate(TRICODES)}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
def _tricode(G, v, u, w):
|
|
118
|
-
"""Returns the integer code of the given triad.
|
|
119
|
-
|
|
120
|
-
This is some fancy magic that comes from Batagelj and Mrvar's paper. It
|
|
121
|
-
treats each edge joining a pair of `v`, `u`, and `w` as a bit in
|
|
122
|
-
the binary representation of an integer.
|
|
123
|
-
|
|
124
|
-
"""
|
|
125
|
-
combos = ((v, u, 1), (u, v, 2), (v, w, 4), (w, v, 8), (u, w, 16), (w, u, 32))
|
|
126
|
-
return sum(x for u, v, x in combos if v in G[u])
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
@not_implemented_for("undirected")
|
|
130
|
-
@nx._dispatchable
|
|
131
|
-
def triadic_census(G, nodelist=None):
|
|
132
|
-
"""Determines the triadic census of a directed graph.
|
|
133
|
-
|
|
134
|
-
The triadic census is a count of how many of the 16 possible types of
|
|
135
|
-
triads are present in a directed graph. If a list of nodes is passed, then
|
|
136
|
-
only those triads are taken into account which have elements of nodelist in them.
|
|
137
|
-
|
|
138
|
-
Parameters
|
|
139
|
-
----------
|
|
140
|
-
G : digraph
|
|
141
|
-
A NetworkX DiGraph
|
|
142
|
-
nodelist : list
|
|
143
|
-
List of nodes for which you want to calculate triadic census
|
|
144
|
-
|
|
145
|
-
Returns
|
|
146
|
-
-------
|
|
147
|
-
census : dict
|
|
148
|
-
Dictionary with triad type as keys and number of occurrences as values.
|
|
149
|
-
|
|
150
|
-
Examples
|
|
151
|
-
--------
|
|
152
|
-
>>> G = nx.DiGraph([(1, 2), (2, 3), (3, 1), (3, 4), (4, 1), (4, 2)])
|
|
153
|
-
>>> triadic_census = nx.triadic_census(G)
|
|
154
|
-
>>> for key, value in triadic_census.items():
|
|
155
|
-
... print(f"{key}: {value}")
|
|
156
|
-
003: 0
|
|
157
|
-
012: 0
|
|
158
|
-
102: 0
|
|
159
|
-
021D: 0
|
|
160
|
-
021U: 0
|
|
161
|
-
021C: 0
|
|
162
|
-
111D: 0
|
|
163
|
-
111U: 0
|
|
164
|
-
030T: 2
|
|
165
|
-
030C: 2
|
|
166
|
-
201: 0
|
|
167
|
-
120D: 0
|
|
168
|
-
120U: 0
|
|
169
|
-
120C: 0
|
|
170
|
-
210: 0
|
|
171
|
-
300: 0
|
|
172
|
-
|
|
173
|
-
Notes
|
|
174
|
-
-----
|
|
175
|
-
This algorithm has complexity $O(m)$ where $m$ is the number of edges in
|
|
176
|
-
the graph.
|
|
177
|
-
|
|
178
|
-
For undirected graphs, the triadic census can be computed by first converting
|
|
179
|
-
the graph into a directed graph using the ``G.to_directed()`` method.
|
|
180
|
-
After this conversion, only the triad types 003, 102, 201 and 300 will be
|
|
181
|
-
present in the undirected scenario.
|
|
182
|
-
|
|
183
|
-
Raises
|
|
184
|
-
------
|
|
185
|
-
ValueError
|
|
186
|
-
If `nodelist` contains duplicate nodes or nodes not in `G`.
|
|
187
|
-
If you want to ignore this you can preprocess with `set(nodelist) & G.nodes`
|
|
188
|
-
|
|
189
|
-
See also
|
|
190
|
-
--------
|
|
191
|
-
triad_graph
|
|
192
|
-
|
|
193
|
-
References
|
|
194
|
-
----------
|
|
195
|
-
.. [1] Vladimir Batagelj and Andrej Mrvar, A subquadratic triad census
|
|
196
|
-
algorithm for large sparse networks with small maximum degree,
|
|
197
|
-
University of Ljubljana,
|
|
198
|
-
http://vlado.fmf.uni-lj.si/pub/networks/doc/triads/triads.pdf
|
|
199
|
-
|
|
200
|
-
"""
|
|
201
|
-
nodeset = set(G.nbunch_iter(nodelist))
|
|
202
|
-
if nodelist is not None and len(nodelist) != len(nodeset):
|
|
203
|
-
raise ValueError("nodelist includes duplicate nodes or nodes not in G")
|
|
204
|
-
|
|
205
|
-
N = len(G)
|
|
206
|
-
Nnot = N - len(nodeset) # can signal special counting for subset of nodes
|
|
207
|
-
|
|
208
|
-
# create an ordering of nodes with nodeset nodes first
|
|
209
|
-
m = {n: i for i, n in enumerate(nodeset)}
|
|
210
|
-
if Nnot:
|
|
211
|
-
# add non-nodeset nodes later in the ordering
|
|
212
|
-
not_nodeset = G.nodes - nodeset
|
|
213
|
-
m.update((n, i + N) for i, n in enumerate(not_nodeset))
|
|
214
|
-
|
|
215
|
-
# build all_neighbor dicts for easy counting
|
|
216
|
-
# After Python 3.8 can leave off these keys(). Speedup also using G._pred
|
|
217
|
-
# nbrs = {n: G._pred[n].keys() | G._succ[n].keys() for n in G}
|
|
218
|
-
nbrs = {n: G.pred[n].keys() | G.succ[n].keys() for n in G}
|
|
219
|
-
dbl_nbrs = {n: G.pred[n].keys() & G.succ[n].keys() for n in G}
|
|
220
|
-
|
|
221
|
-
if Nnot:
|
|
222
|
-
sgl_nbrs = {n: G.pred[n].keys() ^ G.succ[n].keys() for n in not_nodeset}
|
|
223
|
-
# find number of edges not incident to nodes in nodeset
|
|
224
|
-
sgl = sum(1 for n in not_nodeset for nbr in sgl_nbrs[n] if nbr not in nodeset)
|
|
225
|
-
sgl_edges_outside = sgl // 2
|
|
226
|
-
dbl = sum(1 for n in not_nodeset for nbr in dbl_nbrs[n] if nbr not in nodeset)
|
|
227
|
-
dbl_edges_outside = dbl // 2
|
|
228
|
-
|
|
229
|
-
# Initialize the count for each triad to be zero.
|
|
230
|
-
census = {name: 0 for name in TRIAD_NAMES}
|
|
231
|
-
# Main loop over nodes
|
|
232
|
-
for v in nodeset:
|
|
233
|
-
vnbrs = nbrs[v]
|
|
234
|
-
dbl_vnbrs = dbl_nbrs[v]
|
|
235
|
-
if Nnot:
|
|
236
|
-
# set up counts of edges attached to v.
|
|
237
|
-
sgl_unbrs_bdy = sgl_unbrs_out = dbl_unbrs_bdy = dbl_unbrs_out = 0
|
|
238
|
-
for u in vnbrs:
|
|
239
|
-
if m[u] <= m[v]:
|
|
240
|
-
continue
|
|
241
|
-
unbrs = nbrs[u]
|
|
242
|
-
neighbors = (vnbrs | unbrs) - {u, v}
|
|
243
|
-
# Count connected triads.
|
|
244
|
-
for w in neighbors:
|
|
245
|
-
if m[u] < m[w] or (m[v] < m[w] < m[u] and v not in nbrs[w]):
|
|
246
|
-
code = _tricode(G, v, u, w)
|
|
247
|
-
census[TRICODE_TO_NAME[code]] += 1
|
|
248
|
-
|
|
249
|
-
# Use a formula for dyadic triads with edge incident to v
|
|
250
|
-
if u in dbl_vnbrs:
|
|
251
|
-
census["102"] += N - len(neighbors) - 2
|
|
252
|
-
else:
|
|
253
|
-
census["012"] += N - len(neighbors) - 2
|
|
254
|
-
|
|
255
|
-
# Count edges attached to v. Subtract later to get triads with v isolated
|
|
256
|
-
# _out are (u,unbr) for unbrs outside boundary of nodeset
|
|
257
|
-
# _bdy are (u,unbr) for unbrs on boundary of nodeset (get double counted)
|
|
258
|
-
if Nnot and u not in nodeset:
|
|
259
|
-
sgl_unbrs = sgl_nbrs[u]
|
|
260
|
-
sgl_unbrs_bdy += len(sgl_unbrs & vnbrs - nodeset)
|
|
261
|
-
sgl_unbrs_out += len(sgl_unbrs - vnbrs - nodeset)
|
|
262
|
-
dbl_unbrs = dbl_nbrs[u]
|
|
263
|
-
dbl_unbrs_bdy += len(dbl_unbrs & vnbrs - nodeset)
|
|
264
|
-
dbl_unbrs_out += len(dbl_unbrs - vnbrs - nodeset)
|
|
265
|
-
# if nodeset == G.nodes, skip this b/c we will find the edge later.
|
|
266
|
-
if Nnot:
|
|
267
|
-
# Count edges outside nodeset not connected with v (v isolated triads)
|
|
268
|
-
census["012"] += sgl_edges_outside - (sgl_unbrs_out + sgl_unbrs_bdy // 2)
|
|
269
|
-
census["102"] += dbl_edges_outside - (dbl_unbrs_out + dbl_unbrs_bdy // 2)
|
|
270
|
-
|
|
271
|
-
# calculate null triads: "003"
|
|
272
|
-
# null triads = total number of possible triads - all found triads
|
|
273
|
-
total_triangles = (N * (N - 1) * (N - 2)) // 6
|
|
274
|
-
triangles_without_nodeset = (Nnot * (Nnot - 1) * (Nnot - 2)) // 6
|
|
275
|
-
total_census = total_triangles - triangles_without_nodeset
|
|
276
|
-
census["003"] = total_census - sum(census.values())
|
|
277
|
-
|
|
278
|
-
return census
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
@nx._dispatchable
|
|
282
|
-
def is_triad(G):
|
|
283
|
-
"""Returns True if the graph G is a triad, else False.
|
|
284
|
-
|
|
285
|
-
Parameters
|
|
286
|
-
----------
|
|
287
|
-
G : graph
|
|
288
|
-
A NetworkX Graph
|
|
289
|
-
|
|
290
|
-
Returns
|
|
291
|
-
-------
|
|
292
|
-
istriad : boolean
|
|
293
|
-
Whether G is a valid triad
|
|
294
|
-
|
|
295
|
-
Examples
|
|
296
|
-
--------
|
|
297
|
-
>>> G = nx.DiGraph([(1, 2), (2, 3), (3, 1)])
|
|
298
|
-
>>> nx.is_triad(G)
|
|
299
|
-
True
|
|
300
|
-
>>> G.add_edge(0, 1)
|
|
301
|
-
>>> nx.is_triad(G)
|
|
302
|
-
False
|
|
303
|
-
"""
|
|
304
|
-
if isinstance(G, nx.Graph):
|
|
305
|
-
if G.order() == 3 and nx.is_directed(G):
|
|
306
|
-
if not any((n, n) in G.edges() for n in G.nodes()):
|
|
307
|
-
return True
|
|
308
|
-
return False
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
@not_implemented_for("undirected")
|
|
312
|
-
@nx._dispatchable(returns_graph=True)
|
|
313
|
-
def all_triads(G):
|
|
314
|
-
"""A generator of all possible triads in G.
|
|
315
|
-
|
|
316
|
-
Parameters
|
|
317
|
-
----------
|
|
318
|
-
G : digraph
|
|
319
|
-
A NetworkX DiGraph
|
|
320
|
-
|
|
321
|
-
Returns
|
|
322
|
-
-------
|
|
323
|
-
all_triads : generator of DiGraphs
|
|
324
|
-
Generator of triads (order-3 DiGraphs)
|
|
325
|
-
|
|
326
|
-
Examples
|
|
327
|
-
--------
|
|
328
|
-
>>> G = nx.DiGraph([(1, 2), (2, 3), (3, 1), (3, 4), (4, 1), (4, 2)])
|
|
329
|
-
>>> for triad in nx.all_triads(G):
|
|
330
|
-
... print(triad.edges)
|
|
331
|
-
[(1, 2), (2, 3), (3, 1)]
|
|
332
|
-
[(1, 2), (4, 1), (4, 2)]
|
|
333
|
-
[(3, 1), (3, 4), (4, 1)]
|
|
334
|
-
[(2, 3), (3, 4), (4, 2)]
|
|
335
|
-
|
|
336
|
-
"""
|
|
337
|
-
triplets = combinations(G.nodes(), 3)
|
|
338
|
-
for triplet in triplets:
|
|
339
|
-
yield G.subgraph(triplet).copy()
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
@not_implemented_for("undirected")
|
|
343
|
-
@nx._dispatchable
|
|
344
|
-
def triads_by_type(G):
|
|
345
|
-
"""Returns a list of all triads for each triad type in a directed graph.
|
|
346
|
-
There are exactly 16 different types of triads possible. Suppose 1, 2, 3 are three
|
|
347
|
-
nodes, they will be classified as a particular triad type if their connections
|
|
348
|
-
are as follows:
|
|
349
|
-
|
|
350
|
-
- 003: 1, 2, 3
|
|
351
|
-
- 012: 1 -> 2, 3
|
|
352
|
-
- 102: 1 <-> 2, 3
|
|
353
|
-
- 021D: 1 <- 2 -> 3
|
|
354
|
-
- 021U: 1 -> 2 <- 3
|
|
355
|
-
- 021C: 1 -> 2 -> 3
|
|
356
|
-
- 111D: 1 <-> 2 <- 3
|
|
357
|
-
- 111U: 1 <-> 2 -> 3
|
|
358
|
-
- 030T: 1 -> 2 -> 3, 1 -> 3
|
|
359
|
-
- 030C: 1 <- 2 <- 3, 1 -> 3
|
|
360
|
-
- 201: 1 <-> 2 <-> 3
|
|
361
|
-
- 120D: 1 <- 2 -> 3, 1 <-> 3
|
|
362
|
-
- 120U: 1 -> 2 <- 3, 1 <-> 3
|
|
363
|
-
- 120C: 1 -> 2 -> 3, 1 <-> 3
|
|
364
|
-
- 210: 1 -> 2 <-> 3, 1 <-> 3
|
|
365
|
-
- 300: 1 <-> 2 <-> 3, 1 <-> 3
|
|
366
|
-
|
|
367
|
-
Refer to the :doc:`example gallery </auto_examples/graph/plot_triad_types>`
|
|
368
|
-
for visual examples of the triad types.
|
|
369
|
-
|
|
370
|
-
Parameters
|
|
371
|
-
----------
|
|
372
|
-
G : digraph
|
|
373
|
-
A NetworkX DiGraph
|
|
374
|
-
|
|
375
|
-
Returns
|
|
376
|
-
-------
|
|
377
|
-
tri_by_type : dict
|
|
378
|
-
Dictionary with triad types as keys and lists of triads as values.
|
|
379
|
-
|
|
380
|
-
Examples
|
|
381
|
-
--------
|
|
382
|
-
>>> G = nx.DiGraph([(1, 2), (1, 3), (2, 3), (3, 1), (5, 6), (5, 4), (6, 7)])
|
|
383
|
-
>>> dict = nx.triads_by_type(G)
|
|
384
|
-
>>> dict["120C"][0].edges()
|
|
385
|
-
OutEdgeView([(1, 2), (1, 3), (2, 3), (3, 1)])
|
|
386
|
-
>>> dict["012"][0].edges()
|
|
387
|
-
OutEdgeView([(1, 2)])
|
|
388
|
-
|
|
389
|
-
References
|
|
390
|
-
----------
|
|
391
|
-
.. [1] Snijders, T. (2012). "Transitivity and triads." University of
|
|
392
|
-
Oxford.
|
|
393
|
-
https://web.archive.org/web/20170830032057/http://www.stats.ox.ac.uk/~snijders/Trans_Triads_ha.pdf
|
|
394
|
-
"""
|
|
395
|
-
# num_triads = o * (o - 1) * (o - 2) // 6
|
|
396
|
-
# if num_triads > TRIAD_LIMIT: print(WARNING)
|
|
397
|
-
all_tri = all_triads(G)
|
|
398
|
-
tri_by_type = defaultdict(list)
|
|
399
|
-
for triad in all_tri:
|
|
400
|
-
name = triad_type(triad)
|
|
401
|
-
tri_by_type[name].append(triad)
|
|
402
|
-
return tri_by_type
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
@not_implemented_for("undirected")
|
|
406
|
-
@nx._dispatchable
|
|
407
|
-
def triad_type(G):
|
|
408
|
-
"""Returns the sociological triad type for a triad.
|
|
409
|
-
|
|
410
|
-
Parameters
|
|
411
|
-
----------
|
|
412
|
-
G : digraph
|
|
413
|
-
A NetworkX DiGraph with 3 nodes
|
|
414
|
-
|
|
415
|
-
Returns
|
|
416
|
-
-------
|
|
417
|
-
triad_type : str
|
|
418
|
-
A string identifying the triad type
|
|
419
|
-
|
|
420
|
-
Examples
|
|
421
|
-
--------
|
|
422
|
-
>>> G = nx.DiGraph([(1, 2), (2, 3), (3, 1)])
|
|
423
|
-
>>> nx.triad_type(G)
|
|
424
|
-
'030C'
|
|
425
|
-
>>> G.add_edge(1, 3)
|
|
426
|
-
>>> nx.triad_type(G)
|
|
427
|
-
'120C'
|
|
428
|
-
|
|
429
|
-
Notes
|
|
430
|
-
-----
|
|
431
|
-
There can be 6 unique edges in a triad (order-3 DiGraph) (so 2^^6=64 unique
|
|
432
|
-
triads given 3 nodes). These 64 triads each display exactly 1 of 16
|
|
433
|
-
topologies of triads (topologies can be permuted). These topologies are
|
|
434
|
-
identified by the following notation:
|
|
435
|
-
|
|
436
|
-
{m}{a}{n}{type} (for example: 111D, 210, 102)
|
|
437
|
-
|
|
438
|
-
Here:
|
|
439
|
-
|
|
440
|
-
{m} = number of mutual ties (takes 0, 1, 2, 3); a mutual tie is (0,1)
|
|
441
|
-
AND (1,0)
|
|
442
|
-
{a} = number of asymmetric ties (takes 0, 1, 2, 3); an asymmetric tie
|
|
443
|
-
is (0,1) BUT NOT (1,0) or vice versa
|
|
444
|
-
{n} = number of null ties (takes 0, 1, 2, 3); a null tie is NEITHER
|
|
445
|
-
(0,1) NOR (1,0)
|
|
446
|
-
{type} = a letter (takes U, D, C, T) corresponding to up, down, cyclical
|
|
447
|
-
and transitive. This is only used for topologies that can have
|
|
448
|
-
more than one form (eg: 021D and 021U).
|
|
449
|
-
|
|
450
|
-
References
|
|
451
|
-
----------
|
|
452
|
-
.. [1] Snijders, T. (2012). "Transitivity and triads." University of
|
|
453
|
-
Oxford.
|
|
454
|
-
https://web.archive.org/web/20170830032057/http://www.stats.ox.ac.uk/~snijders/Trans_Triads_ha.pdf
|
|
455
|
-
"""
|
|
456
|
-
if not is_triad(G):
|
|
457
|
-
raise nx.NetworkXAlgorithmError("G is not a triad (order-3 DiGraph)")
|
|
458
|
-
num_edges = len(G.edges())
|
|
459
|
-
if num_edges == 0:
|
|
460
|
-
return "003"
|
|
461
|
-
elif num_edges == 1:
|
|
462
|
-
return "012"
|
|
463
|
-
elif num_edges == 2:
|
|
464
|
-
e1, e2 = G.edges()
|
|
465
|
-
if set(e1) == set(e2):
|
|
466
|
-
return "102"
|
|
467
|
-
elif e1[0] == e2[0]:
|
|
468
|
-
return "021D"
|
|
469
|
-
elif e1[1] == e2[1]:
|
|
470
|
-
return "021U"
|
|
471
|
-
elif e1[1] == e2[0] or e2[1] == e1[0]:
|
|
472
|
-
return "021C"
|
|
473
|
-
elif num_edges == 3:
|
|
474
|
-
for e1, e2, e3 in permutations(G.edges(), 3):
|
|
475
|
-
if set(e1) == set(e2):
|
|
476
|
-
if e3[0] in e1:
|
|
477
|
-
return "111U"
|
|
478
|
-
# e3[1] in e1:
|
|
479
|
-
return "111D"
|
|
480
|
-
elif set(e1).symmetric_difference(set(e2)) == set(e3):
|
|
481
|
-
if {e1[0], e2[0], e3[0]} == {e1[0], e2[0], e3[0]} == set(G.nodes()):
|
|
482
|
-
return "030C"
|
|
483
|
-
# e3 == (e1[0], e2[1]) and e2 == (e1[1], e3[1]):
|
|
484
|
-
return "030T"
|
|
485
|
-
elif num_edges == 4:
|
|
486
|
-
for e1, e2, e3, e4 in permutations(G.edges(), 4):
|
|
487
|
-
if set(e1) == set(e2):
|
|
488
|
-
# identify pair of symmetric edges (which necessarily exists)
|
|
489
|
-
if set(e3) == set(e4):
|
|
490
|
-
return "201"
|
|
491
|
-
if {e3[0]} == {e4[0]} == set(e3).intersection(set(e4)):
|
|
492
|
-
return "120D"
|
|
493
|
-
if {e3[1]} == {e4[1]} == set(e3).intersection(set(e4)):
|
|
494
|
-
return "120U"
|
|
495
|
-
if e3[1] == e4[0]:
|
|
496
|
-
return "120C"
|
|
497
|
-
elif num_edges == 5:
|
|
498
|
-
return "210"
|
|
499
|
-
elif num_edges == 6:
|
|
500
|
-
return "300"
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Vitality measures.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from functools import partial
|
|
6
|
-
|
|
7
|
-
import networkx as nx
|
|
8
|
-
|
|
9
|
-
__all__ = ["closeness_vitality"]
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@nx._dispatchable(edge_attrs="weight")
|
|
13
|
-
def closeness_vitality(G, node=None, weight=None, wiener_index=None):
|
|
14
|
-
"""Returns the closeness vitality for nodes in the graph.
|
|
15
|
-
|
|
16
|
-
The *closeness vitality* of a node, defined in Section 3.6.2 of [1],
|
|
17
|
-
is the change in the sum of distances between all node pairs when
|
|
18
|
-
excluding that node.
|
|
19
|
-
|
|
20
|
-
Parameters
|
|
21
|
-
----------
|
|
22
|
-
G : NetworkX graph
|
|
23
|
-
A strongly-connected graph.
|
|
24
|
-
|
|
25
|
-
weight : string
|
|
26
|
-
The name of the edge attribute used as weight. This is passed
|
|
27
|
-
directly to the :func:`~networkx.wiener_index` function.
|
|
28
|
-
|
|
29
|
-
node : object
|
|
30
|
-
If specified, only the closeness vitality for this node will be
|
|
31
|
-
returned. Otherwise, a dictionary mapping each node to its
|
|
32
|
-
closeness vitality will be returned.
|
|
33
|
-
|
|
34
|
-
Other parameters
|
|
35
|
-
----------------
|
|
36
|
-
wiener_index : number
|
|
37
|
-
If you have already computed the Wiener index of the graph
|
|
38
|
-
`G`, you can provide that value here. Otherwise, it will be
|
|
39
|
-
computed for you.
|
|
40
|
-
|
|
41
|
-
Returns
|
|
42
|
-
-------
|
|
43
|
-
dictionary or float
|
|
44
|
-
If `node` is None, this function returns a dictionary
|
|
45
|
-
with nodes as keys and closeness vitality as the
|
|
46
|
-
value. Otherwise, it returns only the closeness vitality for the
|
|
47
|
-
specified `node`.
|
|
48
|
-
|
|
49
|
-
The closeness vitality of a node may be negative infinity if
|
|
50
|
-
removing that node would disconnect the graph.
|
|
51
|
-
|
|
52
|
-
Examples
|
|
53
|
-
--------
|
|
54
|
-
>>> G = nx.cycle_graph(3)
|
|
55
|
-
>>> nx.closeness_vitality(G)
|
|
56
|
-
{0: 2.0, 1: 2.0, 2: 2.0}
|
|
57
|
-
|
|
58
|
-
See Also
|
|
59
|
-
--------
|
|
60
|
-
closeness_centrality
|
|
61
|
-
|
|
62
|
-
References
|
|
63
|
-
----------
|
|
64
|
-
.. [1] Ulrik Brandes, Thomas Erlebach (eds.).
|
|
65
|
-
*Network Analysis: Methodological Foundations*.
|
|
66
|
-
Springer, 2005.
|
|
67
|
-
<http://books.google.com/books?id=TTNhSm7HYrIC>
|
|
68
|
-
|
|
69
|
-
"""
|
|
70
|
-
if wiener_index is None:
|
|
71
|
-
wiener_index = nx.wiener_index(G, weight=weight)
|
|
72
|
-
if node is not None:
|
|
73
|
-
after = nx.wiener_index(G.subgraph(set(G) - {node}), weight=weight)
|
|
74
|
-
return wiener_index - after
|
|
75
|
-
vitality = partial(closeness_vitality, G, weight=weight, wiener_index=wiener_index)
|
|
76
|
-
return {v: vitality(node=v) for v in G}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
"""Functions for computing the Voronoi cells of a graph."""
|
|
2
|
-
|
|
3
|
-
import networkx as nx
|
|
4
|
-
from networkx.utils import groups
|
|
5
|
-
|
|
6
|
-
__all__ = ["voronoi_cells"]
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@nx._dispatchable(edge_attrs="weight")
|
|
10
|
-
def voronoi_cells(G, center_nodes, weight="weight"):
|
|
11
|
-
"""Returns the Voronoi cells centered at `center_nodes` with respect
|
|
12
|
-
to the shortest-path distance metric.
|
|
13
|
-
|
|
14
|
-
If $C$ is a set of nodes in the graph and $c$ is an element of $C$,
|
|
15
|
-
the *Voronoi cell* centered at a node $c$ is the set of all nodes
|
|
16
|
-
$v$ that are closer to $c$ than to any other center node in $C$ with
|
|
17
|
-
respect to the shortest-path distance metric. [1]_
|
|
18
|
-
|
|
19
|
-
For directed graphs, this will compute the "outward" Voronoi cells,
|
|
20
|
-
as defined in [1]_, in which distance is measured from the center
|
|
21
|
-
nodes to the target node. For the "inward" Voronoi cells, use the
|
|
22
|
-
:meth:`DiGraph.reverse` method to reverse the orientation of the
|
|
23
|
-
edges before invoking this function on the directed graph.
|
|
24
|
-
|
|
25
|
-
Parameters
|
|
26
|
-
----------
|
|
27
|
-
G : NetworkX graph
|
|
28
|
-
|
|
29
|
-
center_nodes : set
|
|
30
|
-
A nonempty set of nodes in the graph `G` that represent the
|
|
31
|
-
center of the Voronoi cells.
|
|
32
|
-
|
|
33
|
-
weight : string or function
|
|
34
|
-
The edge attribute (or an arbitrary function) representing the
|
|
35
|
-
weight of an edge. This keyword argument is as described in the
|
|
36
|
-
documentation for :func:`~networkx.multi_source_dijkstra_path`,
|
|
37
|
-
for example.
|
|
38
|
-
|
|
39
|
-
Returns
|
|
40
|
-
-------
|
|
41
|
-
dictionary
|
|
42
|
-
A mapping from center node to set of all nodes in the graph
|
|
43
|
-
closer to that center node than to any other center node. The
|
|
44
|
-
keys of the dictionary are the element of `center_nodes`, and
|
|
45
|
-
the values of the dictionary form a partition of the nodes of
|
|
46
|
-
`G`.
|
|
47
|
-
|
|
48
|
-
Examples
|
|
49
|
-
--------
|
|
50
|
-
To get only the partition of the graph induced by the Voronoi cells,
|
|
51
|
-
take the collection of all values in the returned dictionary::
|
|
52
|
-
|
|
53
|
-
>>> G = nx.path_graph(6)
|
|
54
|
-
>>> center_nodes = {0, 3}
|
|
55
|
-
>>> cells = nx.voronoi_cells(G, center_nodes)
|
|
56
|
-
>>> partition = set(map(frozenset, cells.values()))
|
|
57
|
-
>>> sorted(map(sorted, partition))
|
|
58
|
-
[[0, 1], [2, 3, 4, 5]]
|
|
59
|
-
|
|
60
|
-
Raises
|
|
61
|
-
------
|
|
62
|
-
ValueError
|
|
63
|
-
If `center_nodes` is empty.
|
|
64
|
-
|
|
65
|
-
References
|
|
66
|
-
----------
|
|
67
|
-
.. [1] Erwig, Martin. (2000),"The graph Voronoi diagram with applications."
|
|
68
|
-
*Networks*, 36: 156--163.
|
|
69
|
-
https://doi.org/10.1002/1097-0037(200010)36:3<156::AID-NET2>3.0.CO;2-L
|
|
70
|
-
|
|
71
|
-
"""
|
|
72
|
-
# Determine the shortest paths from any one of the center nodes to
|
|
73
|
-
# every node in the graph.
|
|
74
|
-
#
|
|
75
|
-
# This raises `ValueError` if `center_nodes` is an empty set.
|
|
76
|
-
paths = nx.multi_source_dijkstra_path(G, center_nodes, weight=weight)
|
|
77
|
-
# Determine the center node from which the shortest path originates.
|
|
78
|
-
nearest = {v: p[0] for v, p in paths.items()}
|
|
79
|
-
# Get the mapping from center node to all nodes closer to it than to
|
|
80
|
-
# any other center node.
|
|
81
|
-
cells = groups(nearest)
|
|
82
|
-
# We collect all unreachable nodes under a special key, if there are any.
|
|
83
|
-
unreachable = set(G) - set(nearest)
|
|
84
|
-
if unreachable:
|
|
85
|
-
cells["unreachable"] = unreachable
|
|
86
|
-
return cells
|