okstra 0.130.4 → 0.131.1

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.
Files changed (365) hide show
  1. package/README.md +0 -1
  2. package/docs/architecture.md +2 -2
  3. package/docs/cli.md +1 -1
  4. package/docs/for-ai/README.md +0 -2
  5. package/docs/for-ai/skills/okstra-run.md +13 -2
  6. package/docs/for-ai/skills/okstra-setup.md +4 -1
  7. package/docs/project-structure-overview.md +5 -4
  8. package/docs/task-process/implementation-planning.md +13 -0
  9. package/docs/task-process/implementation.md +17 -2
  10. package/package.json +1 -1
  11. package/runtime/BUILD.json +2 -2
  12. package/runtime/agents/workers/report-writer-worker.md +7 -0
  13. package/runtime/bin/lib/okstra/usage.sh +4 -4
  14. package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
  15. package/runtime/prompts/lead/plan-body-verification.md +26 -5
  16. package/runtime/prompts/lead/report-writer.md +6 -2
  17. package/runtime/prompts/profiles/_common-contract.md +2 -1
  18. package/runtime/prompts/profiles/_implementation-deliverable.md +6 -1
  19. package/runtime/prompts/profiles/_implementation-executor.md +2 -2
  20. package/runtime/prompts/profiles/_implementation-verifier.md +33 -10
  21. package/runtime/prompts/profiles/final-verification.md +21 -6
  22. package/runtime/prompts/profiles/implementation-planning.md +16 -4
  23. package/runtime/python/okstra_ctl/codex_dispatch.py +31 -0
  24. package/runtime/python/okstra_ctl/conformance.py +49 -11
  25. package/runtime/python/okstra_ctl/report_finalize.py +52 -1
  26. package/runtime/python/okstra_ctl/run.py +15 -3
  27. package/runtime/python/okstra_ctl/worker_prompt_contract.py +14 -6
  28. package/runtime/python/okstra_ctl/worker_prompt_policy.py +19 -1
  29. package/runtime/python/okstra_vendor/__init__.py +0 -44
  30. package/runtime/schemas/final-report-v1.0.schema.json +99 -5
  31. package/runtime/skills/okstra-run/SKILL.md +11 -4
  32. package/runtime/skills/okstra-setup/SKILL.md +3 -2
  33. package/runtime/skills/okstra-setup/references/project-config.md +16 -7
  34. package/runtime/templates/reports/final-report.template.md +15 -9
  35. package/runtime/templates/reports/i18n/en.json +1 -0
  36. package/runtime/templates/reports/i18n/ko.json +1 -0
  37. package/runtime/validators/lib/fixtures.sh +6 -0
  38. package/runtime/validators/validate-run.py +2019 -96
  39. package/src/cli-registry.mjs +0 -7
  40. package/src/commands/lifecycle/doctor.mjs +0 -9
  41. package/src/lib/skill-catalog.mjs +0 -1
  42. package/docs/for-ai/skills/okstra-graphify.md +0 -64
  43. package/runtime/python/okstra_ctl/graphify_cmd.py +0 -225
  44. package/runtime/python/okstra_vendor/graphify/.vendored-version +0 -1
  45. package/runtime/python/okstra_vendor/graphify/__init__.py +0 -28
  46. package/runtime/python/okstra_vendor/graphify/__main__.py +0 -1371
  47. package/runtime/python/okstra_vendor/graphify/analyze.py +0 -540
  48. package/runtime/python/okstra_vendor/graphify/benchmark.py +0 -129
  49. package/runtime/python/okstra_vendor/graphify/build.py +0 -107
  50. package/runtime/python/okstra_vendor/graphify/cache.py +0 -169
  51. package/runtime/python/okstra_vendor/graphify/cluster.py +0 -137
  52. package/runtime/python/okstra_vendor/graphify/detect.py +0 -510
  53. package/runtime/python/okstra_vendor/graphify/export.py +0 -1014
  54. package/runtime/python/okstra_vendor/graphify/extract.py +0 -3277
  55. package/runtime/python/okstra_vendor/graphify/hooks.py +0 -220
  56. package/runtime/python/okstra_vendor/graphify/ingest.py +0 -297
  57. package/runtime/python/okstra_vendor/graphify/manifest.py +0 -4
  58. package/runtime/python/okstra_vendor/graphify/report.py +0 -175
  59. package/runtime/python/okstra_vendor/graphify/security.py +0 -203
  60. package/runtime/python/okstra_vendor/graphify/serve.py +0 -373
  61. package/runtime/python/okstra_vendor/graphify/skill-aider.md +0 -1184
  62. package/runtime/python/okstra_vendor/graphify/skill-claw.md +0 -1184
  63. package/runtime/python/okstra_vendor/graphify/skill-codex.md +0 -1242
  64. package/runtime/python/okstra_vendor/graphify/skill-copilot.md +0 -1268
  65. package/runtime/python/okstra_vendor/graphify/skill-droid.md +0 -1239
  66. package/runtime/python/okstra_vendor/graphify/skill-kiro.md +0 -1183
  67. package/runtime/python/okstra_vendor/graphify/skill-opencode.md +0 -1238
  68. package/runtime/python/okstra_vendor/graphify/skill-trae.md +0 -1208
  69. package/runtime/python/okstra_vendor/graphify/skill-vscode.md +0 -253
  70. package/runtime/python/okstra_vendor/graphify/skill-windows.md +0 -1245
  71. package/runtime/python/okstra_vendor/graphify/skill.md +0 -1319
  72. package/runtime/python/okstra_vendor/graphify/transcribe.py +0 -182
  73. package/runtime/python/okstra_vendor/graphify/validate.py +0 -72
  74. package/runtime/python/okstra_vendor/graphify/watch.py +0 -188
  75. package/runtime/python/okstra_vendor/graphify/wiki.py +0 -214
  76. package/runtime/python/okstra_vendor/networkx/__init__.py +0 -62
  77. package/runtime/python/okstra_vendor/networkx/algorithms/__init__.py +0 -134
  78. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/__init__.py +0 -26
  79. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/clique.py +0 -259
  80. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/clustering_coefficient.py +0 -71
  81. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/connectivity.py +0 -412
  82. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/density.py +0 -396
  83. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/distance_measures.py +0 -150
  84. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/dominating_set.py +0 -149
  85. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/kcomponents.py +0 -369
  86. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/matching.py +0 -44
  87. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/maxcut.py +0 -143
  88. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/ramsey.py +0 -53
  89. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/steinertree.py +0 -265
  90. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/traveling_salesman.py +0 -1508
  91. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/treewidth.py +0 -255
  92. package/runtime/python/okstra_vendor/networkx/algorithms/approximation/vertex_cover.py +0 -83
  93. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/__init__.py +0 -5
  94. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/connectivity.py +0 -122
  95. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/correlation.py +0 -302
  96. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/mixing.py +0 -255
  97. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/neighbor_degree.py +0 -160
  98. package/runtime/python/okstra_vendor/networkx/algorithms/assortativity/pairs.py +0 -127
  99. package/runtime/python/okstra_vendor/networkx/algorithms/asteroidal.py +0 -164
  100. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/__init__.py +0 -88
  101. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/basic.py +0 -322
  102. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/centrality.py +0 -290
  103. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/cluster.py +0 -289
  104. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/covering.py +0 -57
  105. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/edgelist.py +0 -360
  106. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/extendability.py +0 -105
  107. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/generators.py +0 -603
  108. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/link_analysis.py +0 -316
  109. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/matching.py +0 -590
  110. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/matrix.py +0 -232
  111. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/projection.py +0 -526
  112. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/redundancy.py +0 -112
  113. package/runtime/python/okstra_vendor/networkx/algorithms/bipartite/spectral.py +0 -69
  114. package/runtime/python/okstra_vendor/networkx/algorithms/boundary.py +0 -168
  115. package/runtime/python/okstra_vendor/networkx/algorithms/bridges.py +0 -205
  116. package/runtime/python/okstra_vendor/networkx/algorithms/broadcasting.py +0 -164
  117. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/__init__.py +0 -20
  118. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/betweenness.py +0 -591
  119. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/betweenness_subset.py +0 -236
  120. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/closeness.py +0 -282
  121. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_betweenness.py +0 -364
  122. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_betweenness_subset.py +0 -227
  123. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/current_flow_closeness.py +0 -96
  124. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/degree_alg.py +0 -150
  125. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/dispersion.py +0 -107
  126. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/eigenvector.py +0 -357
  127. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/flow_matrix.py +0 -130
  128. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/group.py +0 -787
  129. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/harmonic.py +0 -88
  130. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/katz.py +0 -331
  131. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/laplacian.py +0 -150
  132. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/load.py +0 -200
  133. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/percolation.py +0 -128
  134. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/reaching.py +0 -209
  135. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/second_order.py +0 -141
  136. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/subgraph_alg.py +0 -361
  137. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/trophic.py +0 -181
  138. package/runtime/python/okstra_vendor/networkx/algorithms/centrality/voterank_alg.py +0 -95
  139. package/runtime/python/okstra_vendor/networkx/algorithms/chains.py +0 -172
  140. package/runtime/python/okstra_vendor/networkx/algorithms/chordal.py +0 -443
  141. package/runtime/python/okstra_vendor/networkx/algorithms/clique.py +0 -818
  142. package/runtime/python/okstra_vendor/networkx/algorithms/cluster.py +0 -732
  143. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/__init__.py +0 -4
  144. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/equitable_coloring.py +0 -505
  145. package/runtime/python/okstra_vendor/networkx/algorithms/coloring/greedy_coloring.py +0 -565
  146. package/runtime/python/okstra_vendor/networkx/algorithms/communicability_alg.py +0 -163
  147. package/runtime/python/okstra_vendor/networkx/algorithms/community/__init__.py +0 -28
  148. package/runtime/python/okstra_vendor/networkx/algorithms/community/asyn_fluid.py +0 -153
  149. package/runtime/python/okstra_vendor/networkx/algorithms/community/bipartitions.py +0 -354
  150. package/runtime/python/okstra_vendor/networkx/algorithms/community/centrality.py +0 -171
  151. package/runtime/python/okstra_vendor/networkx/algorithms/community/community_utils.py +0 -30
  152. package/runtime/python/okstra_vendor/networkx/algorithms/community/divisive.py +0 -216
  153. package/runtime/python/okstra_vendor/networkx/algorithms/community/kclique.py +0 -79
  154. package/runtime/python/okstra_vendor/networkx/algorithms/community/label_propagation.py +0 -338
  155. package/runtime/python/okstra_vendor/networkx/algorithms/community/leiden.py +0 -162
  156. package/runtime/python/okstra_vendor/networkx/algorithms/community/local.py +0 -220
  157. package/runtime/python/okstra_vendor/networkx/algorithms/community/louvain.py +0 -384
  158. package/runtime/python/okstra_vendor/networkx/algorithms/community/lukes.py +0 -227
  159. package/runtime/python/okstra_vendor/networkx/algorithms/community/modularity_max.py +0 -452
  160. package/runtime/python/okstra_vendor/networkx/algorithms/community/quality.py +0 -347
  161. package/runtime/python/okstra_vendor/networkx/algorithms/components/__init__.py +0 -6
  162. package/runtime/python/okstra_vendor/networkx/algorithms/components/attracting.py +0 -115
  163. package/runtime/python/okstra_vendor/networkx/algorithms/components/biconnected.py +0 -394
  164. package/runtime/python/okstra_vendor/networkx/algorithms/components/connected.py +0 -282
  165. package/runtime/python/okstra_vendor/networkx/algorithms/components/semiconnected.py +0 -71
  166. package/runtime/python/okstra_vendor/networkx/algorithms/components/strongly_connected.py +0 -359
  167. package/runtime/python/okstra_vendor/networkx/algorithms/components/weakly_connected.py +0 -196
  168. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/__init__.py +0 -11
  169. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/connectivity.py +0 -811
  170. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/cuts.py +0 -616
  171. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/disjoint_paths.py +0 -408
  172. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/edge_augmentation.py +0 -1270
  173. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/edge_kcomponents.py +0 -592
  174. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/kcomponents.py +0 -220
  175. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/kcutsets.py +0 -235
  176. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/stoerwagner.py +0 -152
  177. package/runtime/python/okstra_vendor/networkx/algorithms/connectivity/utils.py +0 -88
  178. package/runtime/python/okstra_vendor/networkx/algorithms/core.py +0 -588
  179. package/runtime/python/okstra_vendor/networkx/algorithms/covering.py +0 -142
  180. package/runtime/python/okstra_vendor/networkx/algorithms/cuts.py +0 -416
  181. package/runtime/python/okstra_vendor/networkx/algorithms/cycles.py +0 -1234
  182. package/runtime/python/okstra_vendor/networkx/algorithms/d_separation.py +0 -677
  183. package/runtime/python/okstra_vendor/networkx/algorithms/dag.py +0 -1392
  184. package/runtime/python/okstra_vendor/networkx/algorithms/distance_measures.py +0 -1095
  185. package/runtime/python/okstra_vendor/networkx/algorithms/distance_regular.py +0 -272
  186. package/runtime/python/okstra_vendor/networkx/algorithms/dominance.py +0 -142
  187. package/runtime/python/okstra_vendor/networkx/algorithms/dominating.py +0 -268
  188. package/runtime/python/okstra_vendor/networkx/algorithms/efficiency_measures.py +0 -167
  189. package/runtime/python/okstra_vendor/networkx/algorithms/euler.py +0 -470
  190. package/runtime/python/okstra_vendor/networkx/algorithms/flow/__init__.py +0 -11
  191. package/runtime/python/okstra_vendor/networkx/algorithms/flow/boykovkolmogorov.py +0 -370
  192. package/runtime/python/okstra_vendor/networkx/algorithms/flow/capacityscaling.py +0 -407
  193. package/runtime/python/okstra_vendor/networkx/algorithms/flow/dinitz_alg.py +0 -238
  194. package/runtime/python/okstra_vendor/networkx/algorithms/flow/edmondskarp.py +0 -241
  195. package/runtime/python/okstra_vendor/networkx/algorithms/flow/gomory_hu.py +0 -178
  196. package/runtime/python/okstra_vendor/networkx/algorithms/flow/maxflow.py +0 -611
  197. package/runtime/python/okstra_vendor/networkx/algorithms/flow/mincost.py +0 -356
  198. package/runtime/python/okstra_vendor/networkx/algorithms/flow/networksimplex.py +0 -662
  199. package/runtime/python/okstra_vendor/networkx/algorithms/flow/preflowpush.py +0 -425
  200. package/runtime/python/okstra_vendor/networkx/algorithms/flow/shortestaugmentingpath.py +0 -300
  201. package/runtime/python/okstra_vendor/networkx/algorithms/flow/utils.py +0 -194
  202. package/runtime/python/okstra_vendor/networkx/algorithms/graph_hashing.py +0 -435
  203. package/runtime/python/okstra_vendor/networkx/algorithms/graphical.py +0 -483
  204. package/runtime/python/okstra_vendor/networkx/algorithms/hierarchy.py +0 -57
  205. package/runtime/python/okstra_vendor/networkx/algorithms/hybrid.py +0 -196
  206. package/runtime/python/okstra_vendor/networkx/algorithms/isolate.py +0 -107
  207. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/__init__.py +0 -7
  208. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/ismags.py +0 -1306
  209. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/isomorph.py +0 -336
  210. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/isomorphvf2.py +0 -1262
  211. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/matchhelpers.py +0 -352
  212. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/temporalisomorphvf2.py +0 -308
  213. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/tree_isomorphism.py +0 -264
  214. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/vf2pp.py +0 -1102
  215. package/runtime/python/okstra_vendor/networkx/algorithms/isomorphism/vf2userfunc.py +0 -192
  216. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/__init__.py +0 -2
  217. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/hits_alg.py +0 -337
  218. package/runtime/python/okstra_vendor/networkx/algorithms/link_analysis/pagerank_alg.py +0 -498
  219. package/runtime/python/okstra_vendor/networkx/algorithms/link_prediction.py +0 -687
  220. package/runtime/python/okstra_vendor/networkx/algorithms/lowest_common_ancestors.py +0 -280
  221. package/runtime/python/okstra_vendor/networkx/algorithms/matching.py +0 -1148
  222. package/runtime/python/okstra_vendor/networkx/algorithms/minors/__init__.py +0 -27
  223. package/runtime/python/okstra_vendor/networkx/algorithms/minors/contraction.py +0 -738
  224. package/runtime/python/okstra_vendor/networkx/algorithms/mis.py +0 -78
  225. package/runtime/python/okstra_vendor/networkx/algorithms/moral.py +0 -59
  226. package/runtime/python/okstra_vendor/networkx/algorithms/node_classification.py +0 -219
  227. package/runtime/python/okstra_vendor/networkx/algorithms/non_randomness.py +0 -155
  228. package/runtime/python/okstra_vendor/networkx/algorithms/operators/__init__.py +0 -4
  229. package/runtime/python/okstra_vendor/networkx/algorithms/operators/all.py +0 -324
  230. package/runtime/python/okstra_vendor/networkx/algorithms/operators/binary.py +0 -468
  231. package/runtime/python/okstra_vendor/networkx/algorithms/operators/product.py +0 -633
  232. package/runtime/python/okstra_vendor/networkx/algorithms/operators/unary.py +0 -77
  233. package/runtime/python/okstra_vendor/networkx/algorithms/perfect_graph.py +0 -73
  234. package/runtime/python/okstra_vendor/networkx/algorithms/planar_drawing.py +0 -464
  235. package/runtime/python/okstra_vendor/networkx/algorithms/planarity.py +0 -1463
  236. package/runtime/python/okstra_vendor/networkx/algorithms/polynomials.py +0 -306
  237. package/runtime/python/okstra_vendor/networkx/algorithms/reciprocity.py +0 -98
  238. package/runtime/python/okstra_vendor/networkx/algorithms/regular.py +0 -167
  239. package/runtime/python/okstra_vendor/networkx/algorithms/richclub.py +0 -138
  240. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/__init__.py +0 -5
  241. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/astar.py +0 -239
  242. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/dense.py +0 -264
  243. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/generic.py +0 -716
  244. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/unweighted.py +0 -625
  245. package/runtime/python/okstra_vendor/networkx/algorithms/shortest_paths/weighted.py +0 -2542
  246. package/runtime/python/okstra_vendor/networkx/algorithms/similarity.py +0 -2107
  247. package/runtime/python/okstra_vendor/networkx/algorithms/simple_paths.py +0 -966
  248. package/runtime/python/okstra_vendor/networkx/algorithms/smallworld.py +0 -404
  249. package/runtime/python/okstra_vendor/networkx/algorithms/smetric.py +0 -30
  250. package/runtime/python/okstra_vendor/networkx/algorithms/sparsifiers.py +0 -296
  251. package/runtime/python/okstra_vendor/networkx/algorithms/structuralholes.py +0 -374
  252. package/runtime/python/okstra_vendor/networkx/algorithms/summarization.py +0 -564
  253. package/runtime/python/okstra_vendor/networkx/algorithms/swap.py +0 -406
  254. package/runtime/python/okstra_vendor/networkx/algorithms/threshold.py +0 -981
  255. package/runtime/python/okstra_vendor/networkx/algorithms/time_dependent.py +0 -142
  256. package/runtime/python/okstra_vendor/networkx/algorithms/tournament.py +0 -406
  257. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/__init__.py +0 -5
  258. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/beamsearch.py +0 -90
  259. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/breadth_first_search.py +0 -576
  260. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/depth_first_search.py +0 -529
  261. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/edgebfs.py +0 -185
  262. package/runtime/python/okstra_vendor/networkx/algorithms/traversal/edgedfs.py +0 -182
  263. package/runtime/python/okstra_vendor/networkx/algorithms/tree/__init__.py +0 -7
  264. package/runtime/python/okstra_vendor/networkx/algorithms/tree/branchings.py +0 -1042
  265. package/runtime/python/okstra_vendor/networkx/algorithms/tree/coding.py +0 -413
  266. package/runtime/python/okstra_vendor/networkx/algorithms/tree/decomposition.py +0 -88
  267. package/runtime/python/okstra_vendor/networkx/algorithms/tree/distance_measures.py +0 -219
  268. package/runtime/python/okstra_vendor/networkx/algorithms/tree/mst.py +0 -1281
  269. package/runtime/python/okstra_vendor/networkx/algorithms/tree/operations.py +0 -106
  270. package/runtime/python/okstra_vendor/networkx/algorithms/tree/recognition.py +0 -273
  271. package/runtime/python/okstra_vendor/networkx/algorithms/triads.py +0 -500
  272. package/runtime/python/okstra_vendor/networkx/algorithms/vitality.py +0 -76
  273. package/runtime/python/okstra_vendor/networkx/algorithms/voronoi.py +0 -86
  274. package/runtime/python/okstra_vendor/networkx/algorithms/walks.py +0 -77
  275. package/runtime/python/okstra_vendor/networkx/algorithms/wiener.py +0 -278
  276. package/runtime/python/okstra_vendor/networkx/classes/__init__.py +0 -13
  277. package/runtime/python/okstra_vendor/networkx/classes/coreviews.py +0 -435
  278. package/runtime/python/okstra_vendor/networkx/classes/digraph.py +0 -1363
  279. package/runtime/python/okstra_vendor/networkx/classes/filters.py +0 -95
  280. package/runtime/python/okstra_vendor/networkx/classes/function.py +0 -1549
  281. package/runtime/python/okstra_vendor/networkx/classes/graph.py +0 -2082
  282. package/runtime/python/okstra_vendor/networkx/classes/graphviews.py +0 -269
  283. package/runtime/python/okstra_vendor/networkx/classes/multidigraph.py +0 -977
  284. package/runtime/python/okstra_vendor/networkx/classes/multigraph.py +0 -1294
  285. package/runtime/python/okstra_vendor/networkx/classes/reportviews.py +0 -1447
  286. package/runtime/python/okstra_vendor/networkx/convert.py +0 -502
  287. package/runtime/python/okstra_vendor/networkx/convert_matrix.py +0 -1314
  288. package/runtime/python/okstra_vendor/networkx/drawing/__init__.py +0 -7
  289. package/runtime/python/okstra_vendor/networkx/drawing/layout.py +0 -2036
  290. package/runtime/python/okstra_vendor/networkx/drawing/nx_agraph.py +0 -470
  291. package/runtime/python/okstra_vendor/networkx/drawing/nx_latex.py +0 -570
  292. package/runtime/python/okstra_vendor/networkx/drawing/nx_pydot.py +0 -361
  293. package/runtime/python/okstra_vendor/networkx/drawing/nx_pylab.py +0 -2978
  294. package/runtime/python/okstra_vendor/networkx/exception.py +0 -131
  295. package/runtime/python/okstra_vendor/networkx/generators/__init__.py +0 -34
  296. package/runtime/python/okstra_vendor/networkx/generators/atlas.dat.gz +0 -0
  297. package/runtime/python/okstra_vendor/networkx/generators/atlas.py +0 -227
  298. package/runtime/python/okstra_vendor/networkx/generators/classic.py +0 -1091
  299. package/runtime/python/okstra_vendor/networkx/generators/cographs.py +0 -68
  300. package/runtime/python/okstra_vendor/networkx/generators/community.py +0 -1070
  301. package/runtime/python/okstra_vendor/networkx/generators/degree_seq.py +0 -886
  302. package/runtime/python/okstra_vendor/networkx/generators/directed.py +0 -572
  303. package/runtime/python/okstra_vendor/networkx/generators/duplication.py +0 -174
  304. package/runtime/python/okstra_vendor/networkx/generators/ego.py +0 -66
  305. package/runtime/python/okstra_vendor/networkx/generators/expanders.py +0 -499
  306. package/runtime/python/okstra_vendor/networkx/generators/geometric.py +0 -1037
  307. package/runtime/python/okstra_vendor/networkx/generators/harary_graph.py +0 -163
  308. package/runtime/python/okstra_vendor/networkx/generators/internet_as_graphs.py +0 -443
  309. package/runtime/python/okstra_vendor/networkx/generators/intersection.py +0 -125
  310. package/runtime/python/okstra_vendor/networkx/generators/interval_graph.py +0 -70
  311. package/runtime/python/okstra_vendor/networkx/generators/joint_degree_seq.py +0 -664
  312. package/runtime/python/okstra_vendor/networkx/generators/lattice.py +0 -405
  313. package/runtime/python/okstra_vendor/networkx/generators/line.py +0 -501
  314. package/runtime/python/okstra_vendor/networkx/generators/mycielski.py +0 -110
  315. package/runtime/python/okstra_vendor/networkx/generators/nonisomorphic_trees.py +0 -259
  316. package/runtime/python/okstra_vendor/networkx/generators/random_clustered.py +0 -117
  317. package/runtime/python/okstra_vendor/networkx/generators/random_graphs.py +0 -1416
  318. package/runtime/python/okstra_vendor/networkx/generators/small.py +0 -1070
  319. package/runtime/python/okstra_vendor/networkx/generators/social.py +0 -554
  320. package/runtime/python/okstra_vendor/networkx/generators/spectral_graph_forge.py +0 -120
  321. package/runtime/python/okstra_vendor/networkx/generators/stochastic.py +0 -54
  322. package/runtime/python/okstra_vendor/networkx/generators/sudoku.py +0 -131
  323. package/runtime/python/okstra_vendor/networkx/generators/time_series.py +0 -74
  324. package/runtime/python/okstra_vendor/networkx/generators/trees.py +0 -1070
  325. package/runtime/python/okstra_vendor/networkx/generators/triads.py +0 -94
  326. package/runtime/python/okstra_vendor/networkx/lazy_imports.py +0 -188
  327. package/runtime/python/okstra_vendor/networkx/linalg/__init__.py +0 -13
  328. package/runtime/python/okstra_vendor/networkx/linalg/algebraicconnectivity.py +0 -650
  329. package/runtime/python/okstra_vendor/networkx/linalg/attrmatrix.py +0 -466
  330. package/runtime/python/okstra_vendor/networkx/linalg/bethehessianmatrix.py +0 -77
  331. package/runtime/python/okstra_vendor/networkx/linalg/graphmatrix.py +0 -168
  332. package/runtime/python/okstra_vendor/networkx/linalg/laplacianmatrix.py +0 -512
  333. package/runtime/python/okstra_vendor/networkx/linalg/modularitymatrix.py +0 -166
  334. package/runtime/python/okstra_vendor/networkx/linalg/spectrum.py +0 -186
  335. package/runtime/python/okstra_vendor/networkx/readwrite/__init__.py +0 -17
  336. package/runtime/python/okstra_vendor/networkx/readwrite/adjlist.py +0 -330
  337. package/runtime/python/okstra_vendor/networkx/readwrite/edgelist.py +0 -489
  338. package/runtime/python/okstra_vendor/networkx/readwrite/gexf.py +0 -1084
  339. package/runtime/python/okstra_vendor/networkx/readwrite/gml.py +0 -879
  340. package/runtime/python/okstra_vendor/networkx/readwrite/graph6.py +0 -427
  341. package/runtime/python/okstra_vendor/networkx/readwrite/graphml.py +0 -1053
  342. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/__init__.py +0 -19
  343. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/adjacency.py +0 -156
  344. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/cytoscape.py +0 -190
  345. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/node_link.py +0 -261
  346. package/runtime/python/okstra_vendor/networkx/readwrite/json_graph/tree.py +0 -137
  347. package/runtime/python/okstra_vendor/networkx/readwrite/leda.py +0 -108
  348. package/runtime/python/okstra_vendor/networkx/readwrite/multiline_adjlist.py +0 -393
  349. package/runtime/python/okstra_vendor/networkx/readwrite/p2g.py +0 -113
  350. package/runtime/python/okstra_vendor/networkx/readwrite/pajek.py +0 -286
  351. package/runtime/python/okstra_vendor/networkx/readwrite/sparse6.py +0 -379
  352. package/runtime/python/okstra_vendor/networkx/readwrite/text.py +0 -851
  353. package/runtime/python/okstra_vendor/networkx/relabel.py +0 -285
  354. package/runtime/python/okstra_vendor/networkx/utils/__init__.py +0 -8
  355. package/runtime/python/okstra_vendor/networkx/utils/backends.py +0 -2171
  356. package/runtime/python/okstra_vendor/networkx/utils/configs.py +0 -396
  357. package/runtime/python/okstra_vendor/networkx/utils/decorators.py +0 -1233
  358. package/runtime/python/okstra_vendor/networkx/utils/heaps.py +0 -338
  359. package/runtime/python/okstra_vendor/networkx/utils/mapped_queue.py +0 -297
  360. package/runtime/python/okstra_vendor/networkx/utils/misc.py +0 -703
  361. package/runtime/python/okstra_vendor/networkx/utils/random_sequence.py +0 -198
  362. package/runtime/python/okstra_vendor/networkx/utils/rcm.py +0 -159
  363. package/runtime/python/okstra_vendor/networkx/utils/union_find.py +0 -106
  364. package/runtime/skills/okstra-graphify/SKILL.md +0 -169
  365. package/src/commands/graphify.mjs +0 -32
@@ -1,352 +0,0 @@
1
- """Functions which help end users define customize node_match and
2
- edge_match functions to use during isomorphism checks.
3
- """
4
-
5
- import math
6
- import types
7
- from itertools import permutations
8
-
9
- __all__ = [
10
- "categorical_node_match",
11
- "categorical_edge_match",
12
- "categorical_multiedge_match",
13
- "numerical_node_match",
14
- "numerical_edge_match",
15
- "numerical_multiedge_match",
16
- "generic_node_match",
17
- "generic_edge_match",
18
- "generic_multiedge_match",
19
- ]
20
-
21
-
22
- def copyfunc(f, name=None):
23
- """Returns a deepcopy of a function."""
24
- return types.FunctionType(
25
- f.__code__, f.__globals__, name or f.__name__, f.__defaults__, f.__closure__
26
- )
27
-
28
-
29
- def allclose(x, y, rtol=1.0000000000000001e-05, atol=1e-08):
30
- """Returns True if x and y are sufficiently close, elementwise.
31
-
32
- Parameters
33
- ----------
34
- rtol : float
35
- The relative error tolerance.
36
- atol : float
37
- The absolute error tolerance.
38
-
39
- """
40
- # assume finite weights, see numpy.allclose() for reference
41
- return all(math.isclose(xi, yi, rel_tol=rtol, abs_tol=atol) for xi, yi in zip(x, y))
42
-
43
-
44
- categorical_doc = """
45
- Returns a comparison function for a categorical node attribute.
46
-
47
- The value(s) of the attr(s) must be hashable and comparable via the ==
48
- operator since they are placed into a set([]) object. If the sets from
49
- G1 and G2 are the same, then the constructed function returns True.
50
-
51
- Parameters
52
- ----------
53
- attr : string | list
54
- The categorical node attribute to compare, or a list of categorical
55
- node attributes to compare.
56
- default : value | list
57
- The default value for the categorical node attribute, or a list of
58
- default values for the categorical node attributes.
59
-
60
- Returns
61
- -------
62
- match : function
63
- The customized, categorical `node_match` function.
64
-
65
- Examples
66
- --------
67
- >>> import networkx.algorithms.isomorphism as iso
68
- >>> nm = iso.categorical_node_match("size", 1)
69
- >>> nm = iso.categorical_node_match(["color", "size"], ["red", 2])
70
-
71
- """
72
-
73
-
74
- def categorical_node_match(attr, default):
75
- if isinstance(attr, str):
76
-
77
- def match(data1, data2):
78
- return data1.get(attr, default) == data2.get(attr, default)
79
-
80
- else:
81
- attrs = list(zip(attr, default)) # Python 3
82
-
83
- def match(data1, data2):
84
- return all(data1.get(attr, d) == data2.get(attr, d) for attr, d in attrs)
85
-
86
- return match
87
-
88
-
89
- categorical_edge_match = copyfunc(categorical_node_match, "categorical_edge_match")
90
-
91
-
92
- def categorical_multiedge_match(attr, default):
93
- if isinstance(attr, str):
94
-
95
- def match(datasets1, datasets2):
96
- values1 = {data.get(attr, default) for data in datasets1.values()}
97
- values2 = {data.get(attr, default) for data in datasets2.values()}
98
- return values1 == values2
99
-
100
- else:
101
- attrs = list(zip(attr, default)) # Python 3
102
-
103
- def match(datasets1, datasets2):
104
- values1 = set()
105
- for data1 in datasets1.values():
106
- x = tuple(data1.get(attr, d) for attr, d in attrs)
107
- values1.add(x)
108
- values2 = set()
109
- for data2 in datasets2.values():
110
- x = tuple(data2.get(attr, d) for attr, d in attrs)
111
- values2.add(x)
112
- return values1 == values2
113
-
114
- return match
115
-
116
-
117
- # Docstrings for categorical functions.
118
- categorical_node_match.__doc__ = categorical_doc
119
- categorical_edge_match.__doc__ = categorical_doc.replace("node", "edge")
120
- tmpdoc = categorical_doc.replace("node", "edge")
121
- tmpdoc = tmpdoc.replace("categorical_edge_match", "categorical_multiedge_match")
122
- categorical_multiedge_match.__doc__ = tmpdoc
123
-
124
-
125
- numerical_doc = """
126
- Returns a comparison function for a numerical node attribute.
127
-
128
- The value(s) of the attr(s) must be numerical and sortable. If the
129
- sorted list of values from G1 and G2 are the same within some
130
- tolerance, then the constructed function returns True.
131
-
132
- Parameters
133
- ----------
134
- attr : string | list
135
- The numerical node attribute to compare, or a list of numerical
136
- node attributes to compare.
137
- default : value | list
138
- The default value for the numerical node attribute, or a list of
139
- default values for the numerical node attributes.
140
- rtol : float
141
- The relative error tolerance.
142
- atol : float
143
- The absolute error tolerance.
144
-
145
- Returns
146
- -------
147
- match : function
148
- The customized, numerical `node_match` function.
149
-
150
- Examples
151
- --------
152
- >>> import networkx.algorithms.isomorphism as iso
153
- >>> nm = iso.numerical_node_match("weight", 1.0)
154
- >>> nm = iso.numerical_node_match(["weight", "linewidth"], [0.25, 0.5])
155
-
156
- """
157
-
158
-
159
- def numerical_node_match(attr, default, rtol=1.0000000000000001e-05, atol=1e-08):
160
- if isinstance(attr, str):
161
-
162
- def match(data1, data2):
163
- return math.isclose(
164
- data1.get(attr, default),
165
- data2.get(attr, default),
166
- rel_tol=rtol,
167
- abs_tol=atol,
168
- )
169
-
170
- else:
171
- attrs = list(zip(attr, default)) # Python 3
172
-
173
- def match(data1, data2):
174
- values1 = [data1.get(attr, d) for attr, d in attrs]
175
- values2 = [data2.get(attr, d) for attr, d in attrs]
176
- return allclose(values1, values2, rtol=rtol, atol=atol)
177
-
178
- return match
179
-
180
-
181
- numerical_edge_match = copyfunc(numerical_node_match, "numerical_edge_match")
182
-
183
-
184
- def numerical_multiedge_match(attr, default, rtol=1.0000000000000001e-05, atol=1e-08):
185
- if isinstance(attr, str):
186
-
187
- def match(datasets1, datasets2):
188
- values1 = sorted(data.get(attr, default) for data in datasets1.values())
189
- values2 = sorted(data.get(attr, default) for data in datasets2.values())
190
- return allclose(values1, values2, rtol=rtol, atol=atol)
191
-
192
- else:
193
- attrs = list(zip(attr, default)) # Python 3
194
-
195
- def match(datasets1, datasets2):
196
- values1 = []
197
- for data1 in datasets1.values():
198
- x = tuple(data1.get(attr, d) for attr, d in attrs)
199
- values1.append(x)
200
- values2 = []
201
- for data2 in datasets2.values():
202
- x = tuple(data2.get(attr, d) for attr, d in attrs)
203
- values2.append(x)
204
- values1.sort()
205
- values2.sort()
206
- for xi, yi in zip(values1, values2):
207
- if not allclose(xi, yi, rtol=rtol, atol=atol):
208
- return False
209
- else:
210
- return True
211
-
212
- return match
213
-
214
-
215
- # Docstrings for numerical functions.
216
- numerical_node_match.__doc__ = numerical_doc
217
- numerical_edge_match.__doc__ = numerical_doc.replace("node", "edge")
218
- tmpdoc = numerical_doc.replace("node", "edge")
219
- tmpdoc = tmpdoc.replace("numerical_edge_match", "numerical_multiedge_match")
220
- numerical_multiedge_match.__doc__ = tmpdoc
221
-
222
-
223
- generic_doc = """
224
- Returns a comparison function for a generic attribute.
225
-
226
- The value(s) of the attr(s) are compared using the specified
227
- operators. If all the attributes are equal, then the constructed
228
- function returns True.
229
-
230
- Parameters
231
- ----------
232
- attr : string | list
233
- The node attribute to compare, or a list of node attributes
234
- to compare.
235
- default : value | list
236
- The default value for the node attribute, or a list of
237
- default values for the node attributes.
238
- op : callable | list
239
- The operator to use when comparing attribute values, or a list
240
- of operators to use when comparing values for each attribute.
241
-
242
- Returns
243
- -------
244
- match : function
245
- The customized, generic `node_match` function.
246
-
247
- Examples
248
- --------
249
- >>> from operator import eq
250
- >>> from math import isclose
251
- >>> from networkx.algorithms.isomorphism import generic_node_match
252
- >>> nm = generic_node_match("weight", 1.0, isclose)
253
- >>> nm = generic_node_match("color", "red", eq)
254
- >>> nm = generic_node_match(["weight", "color"], [1.0, "red"], [isclose, eq])
255
-
256
- """
257
-
258
-
259
- def generic_node_match(attr, default, op):
260
- if isinstance(attr, str):
261
-
262
- def match(data1, data2):
263
- return op(data1.get(attr, default), data2.get(attr, default))
264
-
265
- else:
266
- attrs = list(zip(attr, default, op)) # Python 3
267
-
268
- def match(data1, data2):
269
- for attr, d, operator in attrs:
270
- if not operator(data1.get(attr, d), data2.get(attr, d)):
271
- return False
272
- else:
273
- return True
274
-
275
- return match
276
-
277
-
278
- generic_edge_match = copyfunc(generic_node_match, "generic_edge_match")
279
-
280
-
281
- def generic_multiedge_match(attr, default, op):
282
- """Returns a comparison function for a generic attribute.
283
-
284
- The value(s) of the attr(s) are compared using the specified
285
- operators. If all the attributes are equal, then the constructed
286
- function returns True. Potentially, the constructed edge_match
287
- function can be slow since it must verify that no isomorphism
288
- exists between the multiedges before it returns False.
289
-
290
- Parameters
291
- ----------
292
- attr : string | list
293
- The edge attribute to compare, or a list of node attributes
294
- to compare.
295
- default : value | list
296
- The default value for the edge attribute, or a list of
297
- default values for the edgeattributes.
298
- op : callable | list
299
- The operator to use when comparing attribute values, or a list
300
- of operators to use when comparing values for each attribute.
301
-
302
- Returns
303
- -------
304
- match : function
305
- The customized, generic `edge_match` function.
306
-
307
- Examples
308
- --------
309
- >>> from operator import eq
310
- >>> from math import isclose
311
- >>> from networkx.algorithms.isomorphism import generic_node_match
312
- >>> nm = generic_node_match("weight", 1.0, isclose)
313
- >>> nm = generic_node_match("color", "red", eq)
314
- >>> nm = generic_node_match(["weight", "color"], [1.0, "red"], [isclose, eq])
315
-
316
- """
317
-
318
- # This is slow, but generic.
319
- # We must test every possible isomorphism between the edges.
320
- if isinstance(attr, str):
321
- attr = [attr]
322
- default = [default]
323
- op = [op]
324
- attrs = list(zip(attr, default)) # Python 3
325
-
326
- def match(datasets1, datasets2):
327
- values1 = []
328
- for data1 in datasets1.values():
329
- x = tuple(data1.get(attr, d) for attr, d in attrs)
330
- values1.append(x)
331
- values2 = []
332
- for data2 in datasets2.values():
333
- x = tuple(data2.get(attr, d) for attr, d in attrs)
334
- values2.append(x)
335
- for vals2 in permutations(values2):
336
- for xi, yi in zip(values1, vals2):
337
- if not all(map(lambda x, y, z: z(x, y), xi, yi, op)):
338
- # This is not an isomorphism, go to next permutation.
339
- break
340
- else:
341
- # Then we found an isomorphism.
342
- return True
343
- else:
344
- # Then there are no isomorphisms between the multiedges.
345
- return False
346
-
347
- return match
348
-
349
-
350
- # Docstrings for numerical functions.
351
- generic_node_match.__doc__ = generic_doc
352
- generic_edge_match.__doc__ = generic_doc.replace("node", "edge")
@@ -1,308 +0,0 @@
1
- """
2
- *****************************
3
- Time-respecting VF2 Algorithm
4
- *****************************
5
-
6
- An extension of the VF2 algorithm for time-respecting graph isomorphism
7
- testing in temporal graphs.
8
-
9
- A temporal graph is one in which edges contain a datetime attribute,
10
- denoting when interaction occurred between the incident nodes. A
11
- time-respecting subgraph of a temporal graph is a subgraph such that
12
- all interactions incident to a node occurred within a time threshold,
13
- delta, of each other. A directed time-respecting subgraph has the
14
- added constraint that incoming interactions to a node must precede
15
- outgoing interactions from the same node - this enforces a sense of
16
- directed flow.
17
-
18
- Introduction
19
- ------------
20
-
21
- The TimeRespectingGraphMatcher and TimeRespectingDiGraphMatcher
22
- extend the GraphMatcher and DiGraphMatcher classes, respectively,
23
- to include temporal constraints on matches. This is achieved through
24
- a semantic check, via the semantic_feasibility() function.
25
-
26
- As well as including G1 (the graph in which to seek embeddings) and
27
- G2 (the subgraph structure of interest), the name of the temporal
28
- attribute on the edges and the time threshold, delta, must be supplied
29
- as arguments to the matching constructors.
30
-
31
- A delta of zero is the strictest temporal constraint on the match -
32
- only embeddings in which all interactions occur at the same time will
33
- be returned. A delta of one day will allow embeddings in which
34
- adjacent interactions occur up to a day apart.
35
-
36
- Examples
37
- --------
38
-
39
- Examples will be provided when the datetime type has been incorporated.
40
-
41
-
42
- Temporal Subgraph Isomorphism
43
- -----------------------------
44
-
45
- A brief discussion of the somewhat diverse current literature will be
46
- included here.
47
-
48
- References
49
- ----------
50
-
51
- [1] Redmond, U. and Cunningham, P. Temporal subgraph isomorphism. In:
52
- The 2013 IEEE/ACM International Conference on Advances in Social
53
- Networks Analysis and Mining (ASONAM). Niagara Falls, Canada; 2013:
54
- pages 1451 - 1452. [65]
55
-
56
- For a discussion of the literature on temporal networks:
57
-
58
- [3] P. Holme and J. Saramaki. Temporal networks. Physics Reports,
59
- 519(3):97–125, 2012.
60
-
61
- Notes
62
- -----
63
-
64
- Handles directed and undirected graphs and graphs with parallel edges.
65
-
66
- """
67
-
68
- import networkx as nx
69
-
70
- from .isomorphvf2 import DiGraphMatcher, GraphMatcher
71
-
72
- __all__ = ["TimeRespectingGraphMatcher", "TimeRespectingDiGraphMatcher"]
73
-
74
-
75
- class TimeRespectingGraphMatcher(GraphMatcher):
76
- def __init__(self, G1, G2, temporal_attribute_name, delta):
77
- """Initialize TimeRespectingGraphMatcher.
78
-
79
- G1 and G2 should be nx.Graph or nx.MultiGraph instances.
80
-
81
- Examples
82
- --------
83
- To create a TimeRespectingGraphMatcher which checks for
84
- syntactic and semantic feasibility:
85
-
86
- >>> from networkx.algorithms import isomorphism
87
- >>> from datetime import timedelta
88
- >>> G1 = nx.Graph(nx.path_graph(4, create_using=nx.Graph()))
89
-
90
- >>> G2 = nx.Graph(nx.path_graph(4, create_using=nx.Graph()))
91
-
92
- >>> GM = isomorphism.TimeRespectingGraphMatcher(
93
- ... G1, G2, "date", timedelta(days=1)
94
- ... )
95
- """
96
- self.temporal_attribute_name = temporal_attribute_name
97
- self.delta = delta
98
- super().__init__(G1, G2)
99
-
100
- def one_hop(self, Gx, Gx_node, neighbors):
101
- """
102
- Edges one hop out from a node in the mapping should be
103
- time-respecting with respect to each other.
104
- """
105
- dates = []
106
- for n in neighbors:
107
- if isinstance(Gx, nx.Graph): # Graph G[u][v] returns the data dictionary.
108
- dates.append(Gx[Gx_node][n][self.temporal_attribute_name])
109
- else: # MultiGraph G[u][v] returns a dictionary of key -> data dictionary.
110
- for edge in Gx[Gx_node][
111
- n
112
- ].values(): # Iterates all edges between node pair.
113
- dates.append(edge[self.temporal_attribute_name])
114
- if any(x is None for x in dates):
115
- raise ValueError("Datetime not supplied for at least one edge.")
116
- return not dates or max(dates) - min(dates) <= self.delta
117
-
118
- def two_hop(self, Gx, core_x, Gx_node, neighbors):
119
- """
120
- Paths of length 2 from Gx_node should be time-respecting.
121
- """
122
- return all(
123
- self.one_hop(Gx, v, [n for n in Gx[v] if n in core_x] + [Gx_node])
124
- for v in neighbors
125
- )
126
-
127
- def semantic_feasibility(self, G1_node, G2_node):
128
- """Returns True if adding (G1_node, G2_node) is semantically
129
- feasible.
130
-
131
- Any subclass which redefines semantic_feasibility() must
132
- maintain the self.tests if needed, to keep the match() method
133
- functional. Implementations should consider multigraphs.
134
- """
135
- neighbors = [n for n in self.G1[G1_node] if n in self.core_1]
136
- if not self.one_hop(self.G1, G1_node, neighbors): # Fail fast on first node.
137
- return False
138
- if not self.two_hop(self.G1, self.core_1, G1_node, neighbors):
139
- return False
140
- # Otherwise, this node is semantically feasible!
141
- return True
142
-
143
-
144
- class TimeRespectingDiGraphMatcher(DiGraphMatcher):
145
- def __init__(self, G1, G2, temporal_attribute_name, delta):
146
- """Initialize TimeRespectingDiGraphMatcher.
147
-
148
- G1 and G2 should be nx.DiGraph or nx.MultiDiGraph instances.
149
-
150
- Examples
151
- --------
152
- To create a TimeRespectingDiGraphMatcher which checks for
153
- syntactic and semantic feasibility:
154
-
155
- >>> from networkx.algorithms import isomorphism
156
- >>> from datetime import timedelta
157
- >>> G1 = nx.DiGraph(nx.path_graph(4, create_using=nx.DiGraph()))
158
-
159
- >>> G2 = nx.DiGraph(nx.path_graph(4, create_using=nx.DiGraph()))
160
-
161
- >>> GM = isomorphism.TimeRespectingDiGraphMatcher(
162
- ... G1, G2, "date", timedelta(days=1)
163
- ... )
164
- """
165
- self.temporal_attribute_name = temporal_attribute_name
166
- self.delta = delta
167
- super().__init__(G1, G2)
168
-
169
- def get_pred_dates(self, Gx, Gx_node, core_x, pred):
170
- """
171
- Get the dates of edges from predecessors.
172
- """
173
- pred_dates = []
174
- if isinstance(Gx, nx.DiGraph): # Graph G[u][v] returns the data dictionary.
175
- for n in pred:
176
- pred_dates.append(Gx[n][Gx_node][self.temporal_attribute_name])
177
- else: # MultiGraph G[u][v] returns a dictionary of key -> data dictionary.
178
- for n in pred:
179
- for edge in Gx[n][
180
- Gx_node
181
- ].values(): # Iterates all edge data between node pair.
182
- pred_dates.append(edge[self.temporal_attribute_name])
183
- return pred_dates
184
-
185
- def get_succ_dates(self, Gx, Gx_node, core_x, succ):
186
- """
187
- Get the dates of edges to successors.
188
- """
189
- succ_dates = []
190
- if isinstance(Gx, nx.DiGraph): # Graph G[u][v] returns the data dictionary.
191
- for n in succ:
192
- succ_dates.append(Gx[Gx_node][n][self.temporal_attribute_name])
193
- else: # MultiGraph G[u][v] returns a dictionary of key -> data dictionary.
194
- for n in succ:
195
- for edge in Gx[Gx_node][
196
- n
197
- ].values(): # Iterates all edge data between node pair.
198
- succ_dates.append(edge[self.temporal_attribute_name])
199
- return succ_dates
200
-
201
- def one_hop(self, Gx, Gx_node, core_x, pred, succ):
202
- """
203
- The ego node.
204
- """
205
- pred_dates = self.get_pred_dates(Gx, Gx_node, core_x, pred)
206
- succ_dates = self.get_succ_dates(Gx, Gx_node, core_x, succ)
207
- return self.test_one(pred_dates, succ_dates) and self.test_two(
208
- pred_dates, succ_dates
209
- )
210
-
211
- def two_hop_pred(self, Gx, Gx_node, core_x, pred):
212
- """
213
- The predecessors of the ego node.
214
- """
215
- return all(
216
- self.one_hop(
217
- Gx,
218
- p,
219
- core_x,
220
- self.preds(Gx, core_x, p),
221
- self.succs(Gx, core_x, p, Gx_node),
222
- )
223
- for p in pred
224
- )
225
-
226
- def two_hop_succ(self, Gx, Gx_node, core_x, succ):
227
- """
228
- The successors of the ego node.
229
- """
230
- return all(
231
- self.one_hop(
232
- Gx,
233
- s,
234
- core_x,
235
- self.preds(Gx, core_x, s, Gx_node),
236
- self.succs(Gx, core_x, s),
237
- )
238
- for s in succ
239
- )
240
-
241
- def preds(self, Gx, core_x, v, Gx_node=None):
242
- pred = [n for n in Gx.predecessors(v) if n in core_x]
243
- if Gx_node:
244
- pred.append(Gx_node)
245
- return pred
246
-
247
- def succs(self, Gx, core_x, v, Gx_node=None):
248
- succ = [n for n in Gx.successors(v) if n in core_x]
249
- if Gx_node:
250
- succ.append(Gx_node)
251
- return succ
252
-
253
- def test_one(self, pred_dates, succ_dates):
254
- """
255
- Edges one hop out from Gx_node in the mapping should be
256
- time-respecting with respect to each other, regardless of
257
- direction.
258
- """
259
- time_respecting = True
260
- dates = pred_dates + succ_dates
261
-
262
- if any(x is None for x in dates):
263
- raise ValueError("Date or datetime not supplied for at least one edge.")
264
-
265
- dates.sort() # Small to large.
266
- if 0 < len(dates) and not (dates[-1] - dates[0] <= self.delta):
267
- time_respecting = False
268
- return time_respecting
269
-
270
- def test_two(self, pred_dates, succ_dates):
271
- """
272
- Edges from a dual Gx_node in the mapping should be ordered in
273
- a time-respecting manner.
274
- """
275
- time_respecting = True
276
- pred_dates.sort()
277
- succ_dates.sort()
278
- # First out before last in; negative of the necessary condition for time-respect.
279
- if (
280
- 0 < len(succ_dates)
281
- and 0 < len(pred_dates)
282
- and succ_dates[0] < pred_dates[-1]
283
- ):
284
- time_respecting = False
285
- return time_respecting
286
-
287
- def semantic_feasibility(self, G1_node, G2_node):
288
- """Returns True if adding (G1_node, G2_node) is semantically
289
- feasible.
290
-
291
- Any subclass which redefines semantic_feasibility() must
292
- maintain the self.tests if needed, to keep the match() method
293
- functional. Implementations should consider multigraphs.
294
- """
295
- pred, succ = (
296
- [n for n in self.G1.predecessors(G1_node) if n in self.core_1],
297
- [n for n in self.G1.successors(G1_node) if n in self.core_1],
298
- )
299
- if not self.one_hop(
300
- self.G1, G1_node, self.core_1, pred, succ
301
- ): # Fail fast on first node.
302
- return False
303
- if not self.two_hop_pred(self.G1, G1_node, self.core_1, pred):
304
- return False
305
- if not self.two_hop_succ(self.G1, G1_node, self.core_1, succ):
306
- return False
307
- # Otherwise, this node is semantically feasible!
308
- return True