py3plex 2.0.6__tar.gz → 2.0.92__tar.gz

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 (1020) hide show
  1. {py3plex-2.0.6/py3plex.egg-info → py3plex-2.0.92}/PKG-INFO +7 -3
  2. {py3plex-2.0.6 → py3plex-2.0.92}/README.md +4 -2
  3. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/__init__.py +3 -2
  4. py3plex-2.0.92/py3plex/_version.py +3 -0
  5. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/agent.py +1 -1
  6. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/attribute_correlation.py +3 -3
  7. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/centrality/approx_betweenness.py +20 -12
  8. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/centrality/approx_closeness.py +43 -44
  9. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/layer_similarity.py +4 -2
  10. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/centrality.py +1 -1
  11. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/temporal/centrality.py +21 -4
  12. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/benchmarks/runners.py +7 -2
  13. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/centrality/robustness.py +9 -0
  14. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/cli.py +11 -14
  15. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/compat/sidecar.py +3 -1
  16. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/config.py +3 -2
  17. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/lazy_evaluation.py +20 -2
  18. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/multinet.py +56 -43
  19. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/parsers.py +64 -49
  20. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/temporal_multinet.py +47 -17
  21. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/ast.py +21 -5
  22. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/builder.py +29 -3
  23. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/executor.py +108 -23
  24. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/program/cache.py +2 -0
  25. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/program/program.py +11 -3
  26. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/result.py +138 -22
  27. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl_legacy.py +7 -0
  28. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/io/formats/arrow_format.py +26 -13
  29. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/io/multinet_bridge.py +61 -79
  30. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/nullmodels/models.py +27 -23
  31. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/optimizer/logical_plan.py +58 -7
  32. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/optimizer/optimizer.py +52 -9
  33. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/optimizer/physical_plan.py +30 -2
  34. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/optimizer/plan_nodes.py +1 -0
  35. py3plex-2.0.92/py3plex/optimizer/rules.py +1024 -0
  36. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/paths/algorithms.py +5 -1
  37. py3plex-2.0.92/py3plex/safe_dsl_expression.py +83 -0
  38. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/temporal_utils.py +16 -9
  39. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/temporal_view.py +26 -35
  40. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/wrappers/benchmark_nodes.py +5 -2
  41. {py3plex-2.0.6 → py3plex-2.0.92/py3plex.egg-info}/PKG-INFO +7 -3
  42. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex.egg-info/SOURCES.txt +68 -0
  43. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex.egg-info/requires.txt +6 -0
  44. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex_mcp/__init__.py +2 -2
  45. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex_mcp/server.py +4 -13
  46. {py3plex-2.0.6 → py3plex-2.0.92}/pyproject.toml +6 -1
  47. py3plex-2.0.92/tests/test_agent_loading_stats.py +63 -0
  48. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_approximate_centrality.py +2 -2
  49. py3plex-2.0.92/tests/test_approximation_dispatch_regressions.py +65 -0
  50. py3plex-2.0.92/tests/test_approximation_sample_scope_regressions.py +65 -0
  51. py3plex-2.0.92/tests/test_arrow_scalar_ids.py +75 -0
  52. py3plex-2.0.92/tests/test_ast_json_specs_regressions.py +39 -0
  53. py3plex-2.0.92/tests/test_ast_json_target_regressions.py +41 -0
  54. py3plex-2.0.92/tests/test_benchmark_runner_modes.py +75 -0
  55. py3plex-2.0.92/tests/test_benchmark_runner_seeds.py +55 -0
  56. py3plex-2.0.92/tests/test_betweenness_sampling_scaling_regression.py +69 -0
  57. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_book_conf.py +1 -1
  58. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_book_manuscript_integrity.py +4 -4
  59. py3plex-2.0.92/tests/test_bridge_edge_attributes.py +140 -0
  60. py3plex-2.0.92/tests/test_bridge_empty_export.py +57 -0
  61. py3plex-2.0.92/tests/test_bridge_node_identifiers.py +72 -0
  62. py3plex-2.0.92/tests/test_bridge_replica_collisions.py +40 -0
  63. py3plex-2.0.92/tests/test_builder_ast_replay_regressions.py +37 -0
  64. py3plex-2.0.92/tests/test_cache_method_identity.py +119 -0
  65. py3plex-2.0.92/tests/test_canonical_ast_isolation_regressions.py +74 -0
  66. py3plex-2.0.92/tests/test_canonical_projection_order_regressions.py +42 -0
  67. py3plex-2.0.92/tests/test_canonical_query_settings_regressions.py +85 -0
  68. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_cli.py +30 -0
  69. py3plex-2.0.92/tests/test_closeness_allocation_regressions.py +67 -0
  70. py3plex-2.0.92/tests/test_closeness_direction_regressions.py +48 -0
  71. py3plex-2.0.92/tests/test_closeness_normalization_regressions.py +74 -0
  72. py3plex-2.0.92/tests/test_closeness_seed_regressions.py +46 -0
  73. py3plex-2.0.92/tests/test_configuration_directed_degrees.py +104 -0
  74. py3plex-2.0.92/tests/test_correlation_mixed_identities.py +72 -0
  75. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_create_showcase_flow.py +2 -1
  76. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dependency_cleanup.py +7 -1
  77. py3plex-2.0.92/tests/test_dependency_cleanup_compat.py +34 -0
  78. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_doc_conf.py +9 -3
  79. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl.py +29 -0
  80. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_communities.py +6 -0
  81. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_community_uq_integration.py +18 -0
  82. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_executor_additional.py +40 -0
  83. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_export.py +49 -0
  84. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_multilayer_measure_topology.py +21 -12
  85. py3plex-2.0.92/tests/test_dsl_optimizer_integration.py +131 -0
  86. py3plex-2.0.92/tests/test_dsl_optimizer_rewrites.py +264 -0
  87. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_v2.py +19 -0
  88. py3plex-2.0.92/tests/test_edgelist_reload_regression.py +59 -0
  89. py3plex-2.0.92/tests/test_erdos_renyi_directed.py +76 -0
  90. py3plex-2.0.92/tests/test_flow_direction.py +99 -0
  91. py3plex-2.0.92/tests/test_flow_parallel_capacity.py +109 -0
  92. py3plex-2.0.92/tests/test_gml_data_preservation.py +45 -0
  93. py3plex-2.0.92/tests/test_gpickle_directed_conversion.py +37 -0
  94. py3plex-2.0.92/tests/test_gpickle_layer_data.py +51 -0
  95. py3plex-2.0.92/tests/test_graphml_loading.py +77 -0
  96. py3plex-2.0.92/tests/test_layer_shuffle_seed_order.py +100 -0
  97. py3plex-2.0.92/tests/test_layer_similarity_edge_orientation.py +39 -0
  98. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_link_checker.py +1 -0
  99. py3plex-2.0.92/tests/test_load_directed_default.py +46 -0
  100. py3plex-2.0.92/tests/test_matrix_network_weights.py +38 -0
  101. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_mcp_server.py +20 -0
  102. py3plex-2.0.92/tests/test_mixed_layer_enumeration.py +44 -0
  103. py3plex-2.0.92/tests/test_multiedgelist_weights_regressions.py +41 -0
  104. py3plex-2.0.92/tests/test_numeric_cache_mutations.py +91 -0
  105. py3plex-2.0.92/tests/test_numeric_parallel_weights.py +90 -0
  106. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_optimizer_submodules.py +3 -1
  107. py3plex-2.0.92/tests/test_parse_nx_direction.py +46 -0
  108. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_program.py +2 -1
  109. py3plex-2.0.92/tests/test_result_by_id_conflicts.py +174 -0
  110. py3plex-2.0.92/tests/test_result_difference_attributes.py +62 -0
  111. py3plex-2.0.92/tests/test_result_edge_identifier_export.py +66 -0
  112. py3plex-2.0.92/tests/test_result_networkx_direction.py +107 -0
  113. py3plex-2.0.92/tests/test_result_networkx_edge_keys.py +73 -0
  114. py3plex-2.0.92/tests/test_result_networkx_edge_metrics.py +76 -0
  115. py3plex-2.0.92/tests/test_result_networkx_node_lists.py +69 -0
  116. py3plex-2.0.92/tests/test_result_symmetric_difference_attributes.py +135 -0
  117. py3plex-2.0.92/tests/test_result_union_falsy_identifiers.py +93 -0
  118. py3plex-2.0.92/tests/test_robustness_directed_paths.py +40 -0
  119. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_roundtrip_invariants.py +18 -7
  120. py3plex-2.0.92/tests/test_scoped_canonical_embedding_regressions.py +33 -0
  121. py3plex-2.0.92/tests/test_sidecar_empty_tables.py +58 -0
  122. py3plex-2.0.92/tests/test_sparse_conversion_preserves_data.py +100 -0
  123. py3plex-2.0.92/tests/test_streaming_degree_normalization.py +65 -0
  124. py3plex-2.0.92/tests/test_streaming_pagerank_dangling.py +100 -0
  125. py3plex-2.0.92/tests/test_streaming_pagerank_selfloops.py +68 -0
  126. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_temporal.py +4 -3
  127. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_temporal_algorithms.py +68 -0
  128. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_temporal_multinet.py +125 -0
  129. py3plex-2.0.92/tests/test_temporal_numeric_strings.py +36 -0
  130. py3plex-2.0.92/tests/test_temporal_single_timestamp.py +89 -0
  131. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_temporal_utils.py +26 -5
  132. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_temporal_view.py +102 -0
  133. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_temporal_windowed_queries.py +27 -0
  134. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_version_consistency.py +35 -8
  135. py3plex-2.0.92/tests/test_weighted_betweenness_identity_regression.py +66 -0
  136. py3plex-2.0.92/tests/test_weighted_multigraph_sampling_regression.py +70 -0
  137. py3plex-2.0.92/tests/test_wrappers_optional_gensim.py +48 -0
  138. py3plex-2.0.92/tests/test_wrappers_topk_zero.py +23 -0
  139. py3plex-2.0.6/py3plex/optimizer/rules.py +0 -536
  140. {py3plex-2.0.6 → py3plex-2.0.92}/LICENSE +0 -0
  141. {py3plex-2.0.6 → py3plex-2.0.92}/MANIFEST.in +0 -0
  142. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/__main__.py +0 -0
  143. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/_parallel.py +0 -0
  144. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/_safe_expression.py +0 -0
  145. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algebra/__init__.py +0 -0
  146. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algebra/backend.py +0 -0
  147. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algebra/closure.py +0 -0
  148. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algebra/fixed_point.py +0 -0
  149. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algebra/lift.py +0 -0
  150. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algebra/paths.py +0 -0
  151. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algebra/registry.py +0 -0
  152. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algebra/semiring.py +0 -0
  153. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algebra/witness.py +0 -0
  154. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/__init__.py +0 -0
  155. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/advanced_random_generators.py +0 -0
  156. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/centrality/__init__.py +0 -0
  157. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/centrality/approx_pagerank.py +0 -0
  158. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/centrality/explain.py +0 -0
  159. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/centrality_toolkit.py +0 -0
  160. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_comparison.py +0 -0
  161. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/NoRC.py +0 -0
  162. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/__init__.py +0 -0
  163. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/auto_select.py +0 -0
  164. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/autocommunity.py +0 -0
  165. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/autocommunity_executor.py +0 -0
  166. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/budget.py +0 -0
  167. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/community_louvain.py +0 -0
  168. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/community_measures.py +0 -0
  169. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/community_ranking.py +0 -0
  170. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/community_wrapper.py +0 -0
  171. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/distributional.py +0 -0
  172. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/flow_hierarchy.py +0 -0
  173. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/__init__.py +0 -0
  174. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/conftest.py +0 -0
  175. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-bipartite.py +0 -0
  176. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-file-io.py +0 -0
  177. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-multiplex.py +0 -0
  178. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-networkx.py +0 -0
  179. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-simple.py +0 -0
  180. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-trigram-expanded.py +0 -0
  181. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-trigram.py +0 -0
  182. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/infomap.py +0 -0
  183. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/interfaces/python/setup.py +0 -0
  184. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/label_propagation.py +0 -0
  185. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/leiden_multilayer.py +0 -0
  186. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/leiden_uq.py +0 -0
  187. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/mdl_benchmark.py +0 -0
  188. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/multilayer_benchmark.py +0 -0
  189. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/multilayer_modularity.py +0 -0
  190. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/multilayer_quality_metrics.py +0 -0
  191. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/node_ranking.py +0 -0
  192. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/runner.py +0 -0
  193. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/sbm_metrics.py +0 -0
  194. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/sbm_wrapper.py +0 -0
  195. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/spectral_multilayer.py +0 -0
  196. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/community_detection/successive_halving.py +0 -0
  197. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/curvature/__init__.py +0 -0
  198. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/curvature/ollivier_ricci_multilayer.py +0 -0
  199. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/general/__init__.py +0 -0
  200. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/general/benchmark_classification.py +0 -0
  201. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/general/walkers.py +0 -0
  202. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/graph_summarization.py +0 -0
  203. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/__init__.py +0 -0
  204. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/__main__.py +0 -0
  205. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/assets/builtin.n3 +0 -0
  206. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/__init__.py +0 -0
  207. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/converters.py +0 -0
  208. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/example.py +0 -0
  209. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/helpers.py +0 -0
  210. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/kb.py +0 -0
  211. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/load.py +0 -0
  212. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/predicate.py +0 -0
  213. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/rule.py +0 -0
  214. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/settings.py +0 -0
  215. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/term_parsers.py +0 -0
  216. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/learners/__init__.py +0 -0
  217. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/learners/bottomup.py +0 -0
  218. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/learners/learner.py +0 -0
  219. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/learners/optimal.py +0 -0
  220. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/__init__.py +0 -0
  221. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/adjustment.py +0 -0
  222. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/scorefunctions.py +0 -0
  223. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/significance.py +0 -0
  224. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/validate.py +0 -0
  225. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/meta_flow_report.py +0 -0
  226. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/multicentrality.py +0 -0
  227. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/__init__.py +0 -0
  228. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/entanglement.py +0 -0
  229. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/multirank.py +0 -0
  230. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/multixrank.py +0 -0
  231. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/supra_matrix_function_centrality.py +0 -0
  232. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/versatility.py +0 -0
  233. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/multilayer_clustering.py +0 -0
  234. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/network_classification/PPR.py +0 -0
  235. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/network_classification/__init__.py +0 -0
  236. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/network_classification/label_propagation.py +0 -0
  237. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/node_ranking/__init__.py +0 -0
  238. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/node_ranking/node_ranking.py +0 -0
  239. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/requirements_registry.py +0 -0
  240. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/robustness_testing.py +0 -0
  241. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/routing/__init__.py +0 -0
  242. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/routing/multiplex_paths.py +0 -0
  243. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/sbm/__init__.py +0 -0
  244. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/sbm/conversions.py +0 -0
  245. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/sbm/diagnostics.py +0 -0
  246. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/sbm/inference_vi.py +0 -0
  247. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/sbm/model_selection.py +0 -0
  248. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/sbm/multilayer_sbm.py +0 -0
  249. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/sbm/objectives.py +0 -0
  250. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/sbm/uq.py +0 -0
  251. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/sbm/utils.py +0 -0
  252. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/sir_multiplex.py +0 -0
  253. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/statistical_report.py +0 -0
  254. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/statistics/__init__.py +0 -0
  255. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/statistics/basic_statistics.py +0 -0
  256. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/statistics/bayesian_distances.py +0 -0
  257. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/statistics/bayesiantests.py +0 -0
  258. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/statistics/correlation_networks.py +0 -0
  259. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/statistics/critical_distances.py +0 -0
  260. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/statistics/enrichment_modules.py +0 -0
  261. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/statistics/multilayer_statistics.py +0 -0
  262. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/statistics/powerlaw.py +0 -0
  263. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/statistics/stats_comparison.py +0 -0
  264. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/statistics/topology.py +0 -0
  265. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/temporal/__init__.py +0 -0
  266. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/temporal/community.py +0 -0
  267. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/temporal_multiplex/__init__.py +0 -0
  268. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/algorithms/term_parsers/__init__.py +0 -0
  269. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/alignment/__init__.py +0 -0
  270. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/alignment/features.py +0 -0
  271. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/alignment/metrics.py +0 -0
  272. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/alignment/solvers.py +0 -0
  273. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/benchmarks/__init__.py +0 -0
  274. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/benchmarks/budget.py +0 -0
  275. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/benchmarks/metrics.py +0 -0
  276. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/centrality/__init__.py +0 -0
  277. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/claims/__init__.py +0 -0
  278. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/claims/generator.py +0 -0
  279. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/claims/learner.py +0 -0
  280. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/claims/scorer.py +0 -0
  281. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/claims/types.py +0 -0
  282. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/comparison/__init__.py +0 -0
  283. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/comparison/executor.py +0 -0
  284. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/comparison/metrics.py +0 -0
  285. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/comparison/result.py +0 -0
  286. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/compat/__init__.py +0 -0
  287. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/compat/convert.py +0 -0
  288. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/compat/converters/__init__.py +0 -0
  289. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/compat/converters/dgl_converter.py +0 -0
  290. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/compat/converters/igraph_converter.py +0 -0
  291. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/compat/converters/networkx_converter.py +0 -0
  292. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/compat/converters/pyg_converter.py +0 -0
  293. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/compat/converters/scipy_converter.py +0 -0
  294. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/compat/equality.py +0 -0
  295. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/compat/exceptions.py +0 -0
  296. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/compat/ir.py +0 -0
  297. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/compat/schema.py +0 -0
  298. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/contracts/__init__.py +0 -0
  299. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/contracts/contract.py +0 -0
  300. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/contracts/engine.py +0 -0
  301. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/contracts/failure_modes.py +0 -0
  302. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/contracts/predicates.py +0 -0
  303. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/contracts/result.py +0 -0
  304. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/HINMINE/IO.py +0 -0
  305. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/HINMINE/__init__.py +0 -0
  306. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/HINMINE/dataStructures.py +0 -0
  307. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/HINMINE/decomposition.py +0 -0
  308. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/__init__.py +0 -0
  309. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/converters.py +0 -0
  310. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/immutable.py +0 -0
  311. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/nx_compat.py +0 -0
  312. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/random_generators.py +0 -0
  313. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/schema_validation.py +0 -0
  314. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/supporting.py +0 -0
  315. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/core/types.py +0 -0
  316. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/counterexamples/__init__.py +0 -0
  317. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/counterexamples/claim_lang.py +0 -0
  318. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/counterexamples/ddmin.py +0 -0
  319. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/counterexamples/engine.py +0 -0
  320. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/counterexamples/types.py +0 -0
  321. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/counterexamples/witness.py +0 -0
  322. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/counterfactual/__init__.py +0 -0
  323. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/counterfactual/comparator.py +0 -0
  324. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/counterfactual/engine.py +0 -0
  325. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/counterfactual/presets.py +0 -0
  326. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/counterfactual/result.py +0 -0
  327. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/counterfactual/spec.py +0 -0
  328. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/datasets/__init__.py +0 -0
  329. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/datasets/_data/aarhus_cs.edges +0 -0
  330. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/datasets/_data/synthetic_multilayer.edges +0 -0
  331. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/datasets/_generators.py +0 -0
  332. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/datasets/_loaders.py +0 -0
  333. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/diagnostics/__init__.py +0 -0
  334. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/diagnostics/builders.py +0 -0
  335. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/diagnostics/codes.py +0 -0
  336. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/diagnostics/core.py +0 -0
  337. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/diagnostics/utils.py +0 -0
  338. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/__init__.py +0 -0
  339. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/algebra.py +0 -0
  340. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/attribution.py +0 -0
  341. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/benchmark.py +0 -0
  342. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/benchmark_result.py +0 -0
  343. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/builder_parser.py +0 -0
  344. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/cache.py +0 -0
  345. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/communities.py +0 -0
  346. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/community_uq.py +0 -0
  347. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/compositional_uq.py +0 -0
  348. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/context.py +0 -0
  349. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/errors.py +0 -0
  350. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/executor_semiring.py +0 -0
  351. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/executors/__init__.py +0 -0
  352. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/executors/benchmark_executor.py +0 -0
  353. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/explain.py +0 -0
  354. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/export.py +0 -0
  355. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/expressions.py +0 -0
  356. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/fastpath.py +0 -0
  357. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/layers.py +0 -0
  358. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/__init__.py +0 -0
  359. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/diagnostic.py +0 -0
  360. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/lint_context.py +0 -0
  361. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/rules/__init__.py +0 -0
  362. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/rules/base.py +0 -0
  363. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl001_unknown_layer.py +0 -0
  364. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl002_unknown_attribute.py +0 -0
  365. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl101_type_mismatch.py +0 -0
  366. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl201_unsatisfiable.py +0 -0
  367. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl202_redundant.py +0 -0
  368. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/rules/perf301_full_scan.py +0 -0
  369. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/rules/perf302_cross_layer.py +0 -0
  370. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/schema.py +0 -0
  371. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/type_resolver.py +0 -0
  372. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/lint/types.py +0 -0
  373. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/metrics.py +0 -0
  374. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/operator_registry.py +0 -0
  375. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/operators.py +0 -0
  376. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/patterns/__init__.py +0 -0
  377. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/patterns/builder.py +0 -0
  378. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/patterns/compiler.py +0 -0
  379. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/patterns/engine.py +0 -0
  380. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/patterns/ir.py +0 -0
  381. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/patterns/result.py +0 -0
  382. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/plan.py +0 -0
  383. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/planner.py +0 -0
  384. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/predictive.py +0 -0
  385. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/program/__init__.py +0 -0
  386. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/program/cost.py +0 -0
  387. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/program/diff.py +0 -0
  388. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/program/distribution.py +0 -0
  389. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/program/executor.py +0 -0
  390. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/program/explain.py +0 -0
  391. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/program/rewrite.py +0 -0
  392. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/program/types.py +0 -0
  393. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/provenance.py +0 -0
  394. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/reduction.py +0 -0
  395. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/registry.py +0 -0
  396. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/selection_uq.py +0 -0
  397. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/serializer.py +0 -0
  398. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/uq_algebra.py +0 -0
  399. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/uq_resolution.py +0 -0
  400. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dsl/warnings.py +0 -0
  401. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dynamics/__init__.py +0 -0
  402. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dynamics/_utils.py +0 -0
  403. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dynamics/ast.py +0 -0
  404. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dynamics/builder.py +0 -0
  405. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dynamics/compartmental.py +0 -0
  406. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dynamics/config.py +0 -0
  407. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dynamics/core.py +0 -0
  408. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dynamics/errors.py +0 -0
  409. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dynamics/executor.py +0 -0
  410. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dynamics/models.py +0 -0
  411. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dynamics/processes.py +0 -0
  412. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dynamics/registry.py +0 -0
  413. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dynamics/result.py +0 -0
  414. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/dynamics/serializer.py +0 -0
  415. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/embeddings/__init__.py +0 -0
  416. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/embeddings/base.py +0 -0
  417. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/embeddings/cache.py +0 -0
  418. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/embeddings/link_ops.py +0 -0
  419. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/embeddings/metapath2vec.py +0 -0
  420. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/embeddings/netmf.py +0 -0
  421. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/ergonomics.py +0 -0
  422. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/errors.py +0 -0
  423. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/exceptions.py +0 -0
  424. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/experiments/__init__.py +0 -0
  425. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/experiments/artifacts.py +0 -0
  426. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/experiments/cli.py +0 -0
  427. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/experiments/env.py +0 -0
  428. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/experiments/errors.py +0 -0
  429. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/experiments/model.py +0 -0
  430. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/experiments/runner.py +0 -0
  431. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/experiments/store.py +0 -0
  432. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/experiments/utils.py +0 -0
  433. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/fast_examples.py +0 -0
  434. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/graph_ops.py +0 -0
  435. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/io/__init__.py +0 -0
  436. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/io/api.py +0 -0
  437. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/io/canonical_format.py +0 -0
  438. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/io/converters.py +0 -0
  439. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/io/exceptions.py +0 -0
  440. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/io/formats/__init__.py +0 -0
  441. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/io/formats/csv_format.py +0 -0
  442. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/io/formats/json_format.py +0 -0
  443. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/io/parquet_format.py +0 -0
  444. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/io/schema.py +0 -0
  445. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/lab/__init__.py +0 -0
  446. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/lab/base.py +0 -0
  447. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/linter.py +0 -0
  448. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/logging_config.py +0 -0
  449. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/meta/__init__.py +0 -0
  450. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/meta/builder.py +0 -0
  451. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/meta/result.py +0 -0
  452. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/meta/stats.py +0 -0
  453. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/meta/utils.py +0 -0
  454. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/ml/__init__.py +0 -0
  455. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/ml/embedding/__init__.py +0 -0
  456. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/ml/embedding/base.py +0 -0
  457. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/ml/embedding/deepwalk.py +0 -0
  458. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/ml/embedding/evaluation.py +0 -0
  459. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/ml/embedding/line.py +0 -0
  460. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/ml/embedding/metapath2vec.py +0 -0
  461. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/ml/embedding/multiplex.py +0 -0
  462. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/ml/embedding/netmf.py +0 -0
  463. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/ml/embedding/node2vec.py +0 -0
  464. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/ml/embedding/similarity.py +0 -0
  465. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/ml/embedding/trainer.py +0 -0
  466. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/ml/embedding/utils.py +0 -0
  467. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/multinet/__init__.py +0 -0
  468. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/multinet/aggregation.py +0 -0
  469. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/nullmodels/__init__.py +0 -0
  470. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/nullmodels/executor.py +0 -0
  471. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/nullmodels/result.py +0 -0
  472. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/optimizer/__init__.py +0 -0
  473. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/optimizer/cost_model.py +0 -0
  474. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/out_of_core/__init__.py +0 -0
  475. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/out_of_core/cli.py +0 -0
  476. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/out_of_core/errors.py +0 -0
  477. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/out_of_core/executor.py +0 -0
  478. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/out_of_core/network.py +0 -0
  479. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/out_of_core/operators.py +0 -0
  480. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/out_of_core/readers.py +0 -0
  481. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/out_of_core/schema.py +0 -0
  482. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/out_of_core/spill.py +0 -0
  483. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/out_of_core/utils.py +0 -0
  484. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/paths/__init__.py +0 -0
  485. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/paths/executor.py +0 -0
  486. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/paths/result.py +0 -0
  487. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/pipeline.py +0 -0
  488. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/plugins/__init__.py +0 -0
  489. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/plugins/base.py +0 -0
  490. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/plugins/examples.py +0 -0
  491. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/plugins/registry.py +0 -0
  492. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/profiling.py +0 -0
  493. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/provenance/__init__.py +0 -0
  494. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/provenance/bundle.py +0 -0
  495. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/provenance/capture.py +0 -0
  496. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/provenance/replay.py +0 -0
  497. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/provenance/schema.py +0 -0
  498. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/requirements.py +0 -0
  499. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/robustness/__init__.py +0 -0
  500. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/robustness/experiments.py +0 -0
  501. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/robustness/perturbations.py +0 -0
  502. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/runtime/__init__.py +0 -0
  503. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/runtime/capabilities.py +0 -0
  504. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/selection/__init__.py +0 -0
  505. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/selection/capabilities.py +0 -0
  506. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/selection/community_registry.py +0 -0
  507. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/selection/evaluate.py +0 -0
  508. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/selection/metric_registry.py +0 -0
  509. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/selection/result.py +0 -0
  510. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/selection/wins.py +0 -0
  511. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/semiring/__init__.py +0 -0
  512. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/semiring/core.py +0 -0
  513. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/semiring/engine.py +0 -0
  514. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/semiring/pareto.py +0 -0
  515. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/semiring/registry.py +0 -0
  516. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/semiring/types.py +0 -0
  517. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/sensitivity/__init__.py +0 -0
  518. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/sensitivity/executor.py +0 -0
  519. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/sensitivity/metrics.py +0 -0
  520. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/sensitivity/perturbations.py +0 -0
  521. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/sensitivity/types.py +0 -0
  522. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/stats/__init__.py +0 -0
  523. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/stats/provenance.py +0 -0
  524. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/stats/registry.py +0 -0
  525. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/stats/statvalue.py +0 -0
  526. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/stats/uncertainty.py +0 -0
  527. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/temporal_utils_extended.py +0 -0
  528. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/__init__.py +0 -0
  529. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/bootstrap.py +0 -0
  530. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/ci_utils.py +0 -0
  531. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/community_ensemble.py +0 -0
  532. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/community_result.py +0 -0
  533. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/context.py +0 -0
  534. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/estimation.py +0 -0
  535. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/noise_models.py +0 -0
  536. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/null_models.py +0 -0
  537. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/partition.py +0 -0
  538. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/partition_metrics.py +0 -0
  539. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/partition_reducers.py +0 -0
  540. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/partition_types.py +0 -0
  541. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/partition_uq.py +0 -0
  542. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/plan.py +0 -0
  543. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/reducers/__init__.py +0 -0
  544. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/reducers/base.py +0 -0
  545. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/resampling_graph.py +0 -0
  546. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/runner.py +0 -0
  547. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/selection_execution.py +0 -0
  548. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/selection_reducers.py +0 -0
  549. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/selection_types.py +0 -0
  550. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/selection_uq.py +0 -0
  551. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/stratification.py +0 -0
  552. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/uncertainty/types.py +0 -0
  553. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/utils.py +0 -0
  554. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/validation.py +0 -0
  555. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/__init__.py +0 -0
  556. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/benchmark_visualizations.py +0 -0
  557. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/bezier.py +0 -0
  558. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/colors.py +0 -0
  559. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/drawing_machinery.py +0 -0
  560. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/embedding_visualization/__init__.py +0 -0
  561. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/embedding_visualization/embedding_tools.py +0 -0
  562. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/embedding_visualization/embedding_visualization.py +0 -0
  563. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/fa2/__init__.py +0 -0
  564. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/fa2/fa2util.py +0 -0
  565. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/fa2/forceatlas2.py +0 -0
  566. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/layout_algorithms.py +0 -0
  567. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/multilayer.py +0 -0
  568. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/polyfit.py +0 -0
  569. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/pymnet_style.py +0 -0
  570. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/ricci_layout.py +0 -0
  571. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/ricci_multilayer_vis.py +0 -0
  572. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/visualization/sankey.py +0 -0
  573. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/workflows.py +0 -0
  574. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/wrappers/__init__.py +0 -0
  575. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/wrappers/r_interop.py +0 -0
  576. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex/wrappers/train_node2vec_embedding.py +0 -0
  577. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex.egg-info/dependency_links.txt +0 -0
  578. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex.egg-info/entry_points.txt +0 -0
  579. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex.egg-info/not-zip-safe +0 -0
  580. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex.egg-info/top_level.txt +0 -0
  581. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex_mcp/errors.py +0 -0
  582. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex_mcp/registry.py +0 -0
  583. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex_mcp/safe_paths.py +0 -0
  584. {py3plex-2.0.6 → py3plex-2.0.92}/py3plex_mcp/schemas.py +0 -0
  585. {py3plex-2.0.6 → py3plex-2.0.92}/setup.cfg +0 -0
  586. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_advanced_metrics_properties.py +0 -0
  587. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_agent_api.py +0 -0
  588. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_agents_documentation_claims.py +0 -0
  589. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_agents_ergonomics_features.py +0 -0
  590. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_agents_golden_paths.py +0 -0
  591. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_aggregation.py +0 -0
  592. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_algebra_backend.py +0 -0
  593. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_algebra_core.py +0 -0
  594. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_algebra_fixed_point.py +0 -0
  595. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_algebra_paths.py +0 -0
  596. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_algebra_registry.py +0 -0
  597. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_algebra_witness.py +0 -0
  598. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_algorithm_properties.py +0 -0
  599. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_algorithms_attribute_correlation.py +0 -0
  600. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_algorithms_correlation_networks.py +0 -0
  601. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_algorithms_init.py +0 -0
  602. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_algorithms_random_generators.py +0 -0
  603. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_algorithms_requirements_registry.py +0 -0
  604. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_algorithms_statistics_bayesian_distances.py +0 -0
  605. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_alignment.py +0 -0
  606. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_alignment_contracts.py +0 -0
  607. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_alignment_correctness_additional.py +0 -0
  608. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_ast_roundtrip.py +0 -0
  609. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_ast_roundtrip_integration.py +0 -0
  610. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_attribute_correlation.py +0 -0
  611. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_attribute_correlation_contracts.py +0 -0
  612. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_auto_community.py +0 -0
  613. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_autocommunity_benchmarks.py +0 -0
  614. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_autocommunity_executor.py +0 -0
  615. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_autocommunity_meta.py +0 -0
  616. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_autocommunity_successive_halving.py +0 -0
  617. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_bayesian_distances.py +0 -0
  618. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_bench_aggregation_unit.py +0 -0
  619. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_benchmark_budget_fairness.py +0 -0
  620. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_benchmark_dsl_basic.py +0 -0
  621. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_benchmark_integration.py +0 -0
  622. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_benchmark_multiplex_centrality.py +0 -0
  623. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_benchmark_time.py +0 -0
  624. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_benchmarks_budget.py +0 -0
  625. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_benchmarks_init.py +0 -0
  626. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_book_snippets.py +0 -0
  627. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_builder_dsl_mutate.py +0 -0
  628. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_capabilities_basic.py +0 -0
  629. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_capabilities_optional_missing.py +0 -0
  630. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_centrality_explain.py +0 -0
  631. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_centrality_explain_integration.py +0 -0
  632. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_centrality_robustness.py +0 -0
  633. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_centrality_robustness_oracles.py +0 -0
  634. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_centrality_uncertainty.py +0 -0
  635. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_centrality_weight_handling.py +0 -0
  636. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_check_api_consistency.py +0 -0
  637. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_check_doc_coverage.py +0 -0
  638. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_check_type_coverage.py +0 -0
  639. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_ci_python_versions.py +0 -0
  640. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_claim_learning.py +0 -0
  641. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_claims_types.py +0 -0
  642. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_cli_check.py +0 -0
  643. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_cli_ergonomics.py +0 -0
  644. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_cli_piping.py +0 -0
  645. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_clustering_multilayer.py +0 -0
  646. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_code_improvements.py +0 -0
  647. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_community_comparison_coverage.py +0 -0
  648. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_community_detection_modules.py +0 -0
  649. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_community_distribution.py +0 -0
  650. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_community_measures.py +0 -0
  651. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_community_measures_coverage.py +0 -0
  652. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_comparison.py +0 -0
  653. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_comparison_executor.py +0 -0
  654. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_comparison_metrics.py +0 -0
  655. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_comparison_metrics_additional.py +0 -0
  656. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_comparison_result.py +0 -0
  657. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_comparison_uninitialized_and_resistance_oracles.py +0 -0
  658. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_compat_exceptions.py +0 -0
  659. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_compat_roundtrip.py +0 -0
  660. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_config_api.py +0 -0
  661. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_config_benchmark.py +0 -0
  662. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_contracts.py +0 -0
  663. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_contracts_basic.py +0 -0
  664. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_contracts_extended.py +0 -0
  665. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_contracts_failure_modes.py +0 -0
  666. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_contracts_integration.py +0 -0
  667. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_core_functionality.py +0 -0
  668. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_core_immutable.py +0 -0
  669. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_core_lazy_evaluation.py +0 -0
  670. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_core_multinet_and_parsers.py +0 -0
  671. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_core_multinet_correctness.py +0 -0
  672. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_core_multiplex_edges.py +0 -0
  673. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_core_schema_validation.py +0 -0
  674. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_core_supporting.py +0 -0
  675. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_correlation_networks.py +0 -0
  676. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_counterexamples.py +0 -0
  677. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_counterexamples_properties.py +0 -0
  678. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_counterfactual.py +0 -0
  679. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_counterfactual_presets.py +0 -0
  680. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_coverage_grouping.py +0 -0
  681. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_create_mosaic_banner.py +0 -0
  682. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_crosshair_pure_functions.py +0 -0
  683. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_data_files_presence.py +0 -0
  684. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_datasets.py +0 -0
  685. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_datasets_contracts.py +0 -0
  686. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_datasets_oracles.py +0 -0
  687. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_degenerate_networks.py +0 -0
  688. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_determinism_randomness.py +0 -0
  689. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_diagnostics.py +0 -0
  690. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_diagnostics_utils.py +0 -0
  691. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_docs_embeddings_section.py +0 -0
  692. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_docs_examples.py +0 -0
  693. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_docs_quality_pass.py +0 -0
  694. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_doctests.py +0 -0
  695. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dplyr_integration.py +0 -0
  696. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_aggregation_enhancements.py +0 -0
  697. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_ast_equivalence.py +0 -0
  698. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_ast_immutability.py +0 -0
  699. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_auto_community.py +0 -0
  700. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_community_filtering.py +0 -0
  701. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_compact_compute.py +0 -0
  702. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_compiler_explain.py +0 -0
  703. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_compiler_pipeline.py +0 -0
  704. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_compositional_uq.py +0 -0
  705. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_condition_semantics.py +0 -0
  706. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_d_factory.py +0 -0
  707. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_documentation_examples.py +0 -0
  708. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_dplyr_style.py +0 -0
  709. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_dynamics_integration.py +0 -0
  710. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_edge_grouping_coverage.py +0 -0
  711. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_edge_queries.py +0 -0
  712. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_enhancements.py +0 -0
  713. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_ergonomics.py +0 -0
  714. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_errors.py +0 -0
  715. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_errors_extended.py +0 -0
  716. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_explain.py +0 -0
  717. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_expressions.py +0 -0
  718. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_extensions.py +0 -0
  719. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_graphops_equivalence.py +0 -0
  720. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_grouping_coverage.py +0 -0
  721. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_interactive.py +0 -0
  722. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_joins.py +0 -0
  723. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_layer_resolution.py +0 -0
  724. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_layer_selection.py +0 -0
  725. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_layer_set_algebra.py +0 -0
  726. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_legacy_approximate.py +0 -0
  727. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_legacy_edges.py +0 -0
  728. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_lint.py +0 -0
  729. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_metric_registry.py +0 -0
  730. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_operators.py +0 -0
  731. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_patterns.py +0 -0
  732. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_patterns_correctness.py +0 -0
  733. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_patterns_quick_reference.py +0 -0
  734. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_pipes.py +0 -0
  735. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_planner.py +0 -0
  736. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_planner_config.py +0 -0
  737. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_predict_reduce.py +0 -0
  738. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_program_rewrite.py +0 -0
  739. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_program_types.py +0 -0
  740. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_progress_logging.py +0 -0
  741. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_properties.py +0 -0
  742. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_provenance.py +0 -0
  743. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_query_optimization.py +0 -0
  744. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_query_zoo.py +0 -0
  745. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_result_algebra_edge_cases.py +0 -0
  746. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_selection_fastpath.py +0 -0
  747. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_semiring_integration.py +0 -0
  748. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_serializer.py +0 -0
  749. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_smart_defaults.py +0 -0
  750. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_temporal_range_execution.py +0 -0
  751. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_uncertainty.py +0 -0
  752. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_uq_ergonomics.py +0 -0
  753. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_uq_propagation.py +0 -0
  754. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dsl_zoo_features.py +0 -0
  755. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dynamics.py +0 -0
  756. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dynamics_algorithm_contracts.py +0 -0
  757. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dynamics_config_and_results_correctness.py +0 -0
  758. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dynamics_conservation.py +0 -0
  759. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dynamics_core.py +0 -0
  760. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dynamics_executor_edge_cases.py +0 -0
  761. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dynamics_metamorphic.py +0 -0
  762. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dynamics_parallel_determinism.py +0 -0
  763. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dynamics_reference_runs.py +0 -0
  764. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dynamics_uq_integration.py +0 -0
  765. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_dynamics_utils.py +0 -0
  766. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_edge_cases.py +0 -0
  767. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_edgelist_format.py +0 -0
  768. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_embeddings_direct_units.py +0 -0
  769. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_ergonomic_helpers.py +0 -0
  770. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_ergonomics.py +0 -0
  771. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_ergonomics_helpers.py +0 -0
  772. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_errors.py +0 -0
  773. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_errors_coverage.py +0 -0
  774. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_CBSSD.py +0 -0
  775. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_community_detection.py +0 -0
  776. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_decomposition_and_classification.py +0 -0
  777. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_decomposition_ground_truth.py +0 -0
  778. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_dsl_builder_api.py +0 -0
  779. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_dynamics_core_examples.py +0 -0
  780. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_embedding_construction.py +0 -0
  781. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_embedding_visualization.py +0 -0
  782. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_incidence_gadget_encoding.py +0 -0
  783. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_interactive_multilayer.py +0 -0
  784. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_inverse_network.py +0 -0
  785. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_layer_extraction.py +0 -0
  786. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_manipulation.py +0 -0
  787. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_multilayer_vectorized_aggregation.py +0 -0
  788. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_multiplex_aggregate.py +0 -0
  789. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_multiplex_dynamics.py +0 -0
  790. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_n2v_embedding.py +0 -0
  791. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_network_decomposition.py +0 -0
  792. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_network_decomposition_meta_paths.py +0 -0
  793. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_numeric_encoding.py +0 -0
  794. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_pattern_matching.py +0 -0
  795. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_example_ppr.py +0 -0
  796. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_examples_zoo_consolidation.py +0 -0
  797. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_exception_taxonomy.py +0 -0
  798. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_exceptions.py +0 -0
  799. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_experiments.py +0 -0
  800. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_explain_attribution.py +0 -0
  801. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_fast_examples.py +0 -0
  802. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_flagship_progress_demo.py +0 -0
  803. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_flow_hierarchy.py +0 -0
  804. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_formal_phase1_alignment.py +0 -0
  805. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_fuzzing_properties.py +0 -0
  806. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_generate_all_outputs.py +0 -0
  807. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_generate_quickstart_outputs.py +0 -0
  808. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_generate_visualization_images.py +0 -0
  809. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_golden_toy_examples.py +0 -0
  810. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_graph_ops.py +0 -0
  811. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_graph_summarization.py +0 -0
  812. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_hedwig_adjustment.py +0 -0
  813. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_hedwig_significance.py +0 -0
  814. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_improved_errors.py +0 -0
  815. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_incidence_gadget_encoding.py +0 -0
  816. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_infomap_fix.py +0 -0
  817. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_interlayer_links_fix.py +0 -0
  818. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_io_api_edge_cases.py +0 -0
  819. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_io_arrow.py +0 -0
  820. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_io_contracts_additional.py +0 -0
  821. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_io_conversion_formats.py +0 -0
  822. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_io_converters.py +0 -0
  823. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_io_exceptions.py +0 -0
  824. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_io_integration.py +0 -0
  825. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_io_roundtrip.py +0 -0
  826. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_io_schema.py +0 -0
  827. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_issue_19_fix.py +0 -0
  828. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_lab.py +0 -0
  829. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_lab_additional.py +0 -0
  830. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_lab_correctness.py +0 -0
  831. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_label_propagation.py +0 -0
  832. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_layer_extraction_fix.py +0 -0
  833. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_layer_similarity.py +0 -0
  834. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_layout_algorithms.py +0 -0
  835. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_lazy_evaluation.py +0 -0
  836. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_leiden_multilayer.py +0 -0
  837. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_linter.py +0 -0
  838. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_logging_config_unit.py +0 -0
  839. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_logging_conversion.py +0 -0
  840. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_main_module.py +0 -0
  841. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_master_regulators_example.py +0 -0
  842. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_math_invariants.py +0 -0
  843. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_mdl_benchmark.py +0 -0
  844. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_mdl_score.py +0 -0
  845. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_mdl_score_corruption_monotonicity.py +0 -0
  846. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_mdl_score_reference_differential.py +0 -0
  847. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_mdl_score_resolution_limit_sweep.py +0 -0
  848. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_meta_analysis.py +0 -0
  849. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_meta_flow_report.py +0 -0
  850. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_meta_utils.py +0 -0
  851. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_metamorphic.py +0 -0
  852. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_metapath2vec.py +0 -0
  853. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_ml_embedding_evaluation.py +0 -0
  854. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_ml_embedding_primitives.py +0 -0
  855. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_monoplex_nx_wrapper.py +0 -0
  856. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_mpc.py +0 -0
  857. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multilayer_centrality.py +0 -0
  858. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multilayer_clustering_coefficients.py +0 -0
  859. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multilayer_cornercases.py +0 -0
  860. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multilayer_edge_fix.py +0 -0
  861. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multilayer_embedding_models.py +0 -0
  862. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multilayer_integration.py +0 -0
  863. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multilayer_leiden_uq.py +0 -0
  864. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multilayer_modularity.py +0 -0
  865. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multilayer_quality_metrics.py +0 -0
  866. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multilayer_quality_metrics_coverage.py +0 -0
  867. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multilayer_statistics.py +0 -0
  868. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multilayer_visualizations.py +0 -0
  869. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multinet_aggregation.py +0 -0
  870. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multinet_aggregation_additional.py +0 -0
  871. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multiplex_layer_interop.py +0 -0
  872. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multiplex_participation.py +0 -0
  873. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multiplex_properties.py +0 -0
  874. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multirank.py +0 -0
  875. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_multixrank.py +0 -0
  876. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_network_conversion.py +0 -0
  877. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_network_version.py +0 -0
  878. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_networkx_compatibility.py +0 -0
  879. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_new_algorithms.py +0 -0
  880. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_new_multilayer_metrics.py +0 -0
  881. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_node_edge_parity.py +0 -0
  882. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_node_ranking_comprehensive.py +0 -0
  883. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_norc.py +0 -0
  884. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_nullmodel_sanity.py +0 -0
  885. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_nullmodels.py +0 -0
  886. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_nullmodels_contracts.py +0 -0
  887. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_nx_compat_extended.py +0 -0
  888. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_ollivier_ricci_multilayer.py +0 -0
  889. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_out_of_core.py +0 -0
  890. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_parallel.py +0 -0
  891. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_parallel_execution.py +0 -0
  892. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_parsers_comprehensive.py +0 -0
  893. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_parsers_coverage.py +0 -0
  894. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_partition_uq.py +0 -0
  895. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_partition_uq_integration.py +0 -0
  896. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_paths.py +0 -0
  897. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_paths_additional.py +0 -0
  898. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_paths_contracts.py +0 -0
  899. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_paths_executor.py +0 -0
  900. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_paths_result.py +0 -0
  901. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_performance_core.py +0 -0
  902. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_pipeline.py +0 -0
  903. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_plugin_examples.py +0 -0
  904. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_plugin_system.py +0 -0
  905. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_plugins.py +0 -0
  906. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_plugins_contracts.py +0 -0
  907. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_profiling.py +0 -0
  908. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_profiling_additional.py +0 -0
  909. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_program_cache_identity.py +0 -0
  910. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_program_cost_executor.py +0 -0
  911. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_properties.py +0 -0
  912. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_provenance_canonical.py +0 -0
  913. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_provenance_replay.py +0 -0
  914. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_provenance_schema.py +0 -0
  915. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_public_api_exports.py +0 -0
  916. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_pymnet_style.py +0 -0
  917. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_pypi_publish_workflow.py +0 -0
  918. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_query_algebra.py +0 -0
  919. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_query_equivalence.py +0 -0
  920. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_r_interop.py +0 -0
  921. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_random_generators_additional.py +0 -0
  922. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_random_generators_extended.py +0 -0
  923. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_random_walkers.py +0 -0
  924. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_random_walks.py +0 -0
  925. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_readme_contributor_onboarding.py +0 -0
  926. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_readme_flagship_example.py +0 -0
  927. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_requirements.py +0 -0
  928. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_result_explain_debug.py +0 -0
  929. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_ricci_visualization.py +0 -0
  930. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_robustness.py +0 -0
  931. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_robustness_additional.py +0 -0
  932. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_robustness_testing.py +0 -0
  933. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_root_conftest.py +0 -0
  934. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_run_quickstart_snippets.py +0 -0
  935. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_safe_expression.py +0 -0
  936. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_sankey_visualization.py +0 -0
  937. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_sbm_autocommunity.py +0 -0
  938. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_sbm_generator.py +0 -0
  939. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_sbm_metrics.py +0 -0
  940. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_sbm_runner_integration.py +0 -0
  941. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_schema_and_immutable.py +0 -0
  942. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_seeding.py +0 -0
  943. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_selection_uq.py +0 -0
  944. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_selection_uq_empty_groups.py +0 -0
  945. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_selection_uq_integration.py +0 -0
  946. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_semiring_negative_cases.py +0 -0
  947. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_semiring_pareto.py +0 -0
  948. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_semiring_registry.py +0 -0
  949. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_semiring_types.py +0 -0
  950. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_semiring_verification.py +0 -0
  951. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_sensitivity_executor.py +0 -0
  952. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_sidecar.py +0 -0
  953. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_sir_epidemic.py +0 -0
  954. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_sir_long_convergence.py +0 -0
  955. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_sir_multiplex.py +0 -0
  956. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_spectral_multilayer.py +0 -0
  957. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_statistical_report.py +0 -0
  958. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_stats_comparison.py +0 -0
  959. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_stats_core.py +0 -0
  960. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_stats_edge_cases.py +0 -0
  961. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_stats_provenance.py +0 -0
  962. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_stats_provenance_dataclass.py +0 -0
  963. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_stats_registry.py +0 -0
  964. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_stats_scalar_uncertainty.py +0 -0
  965. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_stats_verify.py +0 -0
  966. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_stratified_uq.py +0 -0
  967. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_streaming_topk.py +0 -0
  968. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_successive_halving.py +0 -0
  969. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_supporting_extended.py +0 -0
  970. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_supra_matrix_function_centrality.py +0 -0
  971. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_temporal_builder.py +0 -0
  972. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_temporal_dsl.py +0 -0
  973. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_temporal_duration_parsing.py +0 -0
  974. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_temporal_utils_extended.py +0 -0
  975. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_tensor_representation.py +0 -0
  976. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_tutorial_10min.py +0 -0
  977. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_type_coverage_scan.py +0 -0
  978. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_uncertainty.py +0 -0
  979. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_uncertainty_additional.py +0 -0
  980. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_uncertainty_builder_integration.py +0 -0
  981. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_uncertainty_defaults.py +0 -0
  982. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_uncertainty_dsl_integration.py +0 -0
  983. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_uncertainty_engines.py +0 -0
  984. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_uncertainty_oracles.py +0 -0
  985. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_uncertainty_runner.py +0 -0
  986. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_uq_algebra.py +0 -0
  987. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_uq_integration.py +0 -0
  988. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_uq_resolution.py +0 -0
  989. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_uq_spine.py +0 -0
  990. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_user_journey_simulation.py +0 -0
  991. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_utils.py +0 -0
  992. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_utils_coverage.py +0 -0
  993. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_utils_extended.py +0 -0
  994. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_utils_search_paths.py +0 -0
  995. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_validation.py +0 -0
  996. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_validation_module.py +0 -0
  997. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_verification_api_differential.py +0 -0
  998. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_verification_centrality.py +0 -0
  999. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_verification_communities.py +0 -0
  1000. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_verification_determinism_parallelism.py +0 -0
  1001. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_verification_dsl_equivalence.py +0 -0
  1002. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_verification_metamorphic_harness.py +0 -0
  1003. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_verification_provenance_oracles.py +0 -0
  1004. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_versatility.py +0 -0
  1005. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_visualization_benchmark.py +0 -0
  1006. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_visualization_bezier.py +0 -0
  1007. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_visualization_colors.py +0 -0
  1008. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_visualization_imports.py +0 -0
  1009. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_visualization_layouts.py +0 -0
  1010. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_visualization_multilayer_additional.py +0 -0
  1011. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_visualization_polyfit.py +0 -0
  1012. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_visualization_ricci_layout_helpers.py +0 -0
  1013. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_visualization_supra_heatmap.py +0 -0
  1014. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_visualize_matrix_fix.py +0 -0
  1015. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_workflows.py +0 -0
  1016. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_wrappers_additional.py +0 -0
  1017. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_wrappers_benchmark_nodes.py +0 -0
  1018. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_wrappers_node2vec.py +0 -0
  1019. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_wrappers_r_interop.py +0 -0
  1020. {py3plex-2.0.6 → py3plex-2.0.92}/tests/test_wrappers_train_node2vec.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py3plex
3
- Version: 2.0.6
3
+ Version: 2.0.92
4
4
  Summary: A Multilayer network analysis python3 library
5
5
  Author-email: Blaž Škrlj <blaz.skrlj@ijs.si>
6
6
  License: MIT
@@ -34,6 +34,7 @@ Requires-Dist: bitarray>=2.0.0
34
34
  Requires-Dist: seaborn>=0.11.0
35
35
  Provides-Extra: dev
36
36
  Requires-Dist: pytest>=7.0; extra == "dev"
37
+ Requires-Dist: tomli>=1.1.0; python_version < "3.11" and extra == "dev"
37
38
  Requires-Dist: pytest-timeout>=2.1; extra == "dev"
38
39
  Requires-Dist: pytest-cov>=4.0; extra == "dev"
39
40
  Requires-Dist: pytest-benchmark<5.0,>=4.0; extra == "dev"
@@ -49,6 +50,7 @@ Requires-Dist: z3-solver>=4.12.0; extra == "dev"
49
50
  Requires-Dist: hypothesis>=6.0; extra == "dev"
50
51
  Provides-Extra: tests
51
52
  Requires-Dist: pytest>=7.0; extra == "tests"
53
+ Requires-Dist: tomli>=1.1.0; python_version < "3.11" and extra == "tests"
52
54
  Requires-Dist: pytest-timeout>=2.1; extra == "tests"
53
55
  Requires-Dist: pytest-cov>=4.0; extra == "tests"
54
56
  Requires-Dist: pytest-rerunfailures>=12.0; extra == "tests"
@@ -120,8 +122,8 @@ Dynamic: license-file
120
122
  [![PyPI - Downloads](https://img.shields.io/pypi/dm/py3plex)](https://pypistats.org/packages/py3plex)
121
123
  ![CLI Tool](https://img.shields.io/badge/CLI%20Tool-Available-brightgreen)
122
124
  ![Docker](https://img.shields.io/badge/Docker-Available-blue)
123
- ![Lines of Code](https://img.shields.io/badge/lines-213.6K-blue)
124
- ![Test Count](https://img.shields.io/badge/tests-9.7K-blue)
125
+ ![Lines of Code](https://img.shields.io/badge/lines-214.7K-blue)
126
+ ![Test Count](https://img.shields.io/badge/tests-9.9K-blue)
125
127
 
126
128
  *Multilayer networks* are complex networks with additional information assigned to nodes or edges (or both). This library includes
127
129
  some of the state-of-the-art algorithms for decomposition, visualization and analysis of such networks.
@@ -301,6 +303,8 @@ Safety notes for contributors:
301
303
  - Prefer running targeted tests first, then broader checks before opening a PR.
302
304
  - For docs-only updates, run `make docs-check` before opening a PR.
303
305
 
306
+ To report a bug, request a feature, or ask for help using py3plex, open an issue in the [issue tracker](https://github.com/SkBlaz/py3plex/issues). Include a minimal example and the py3plex and Python versions where relevant.
307
+
304
308
  ### MCP Integration (AI Agents)
305
309
 
306
310
  py3plex provides a Model Context Protocol (MCP) server for integration with AI coding assistants:
@@ -16,8 +16,8 @@
16
16
  [![PyPI - Downloads](https://img.shields.io/pypi/dm/py3plex)](https://pypistats.org/packages/py3plex)
17
17
  ![CLI Tool](https://img.shields.io/badge/CLI%20Tool-Available-brightgreen)
18
18
  ![Docker](https://img.shields.io/badge/Docker-Available-blue)
19
- ![Lines of Code](https://img.shields.io/badge/lines-213.6K-blue)
20
- ![Test Count](https://img.shields.io/badge/tests-9.7K-blue)
19
+ ![Lines of Code](https://img.shields.io/badge/lines-214.7K-blue)
20
+ ![Test Count](https://img.shields.io/badge/tests-9.9K-blue)
21
21
 
22
22
  *Multilayer networks* are complex networks with additional information assigned to nodes or edges (or both). This library includes
23
23
  some of the state-of-the-art algorithms for decomposition, visualization and analysis of such networks.
@@ -197,6 +197,8 @@ Safety notes for contributors:
197
197
  - Prefer running targeted tests first, then broader checks before opening a PR.
198
198
  - For docs-only updates, run `make docs-check` before opening a PR.
199
199
 
200
+ To report a bug, request a feature, or ask for help using py3plex, open an issue in the [issue tracker](https://github.com/SkBlaz/py3plex/issues). Include a minimal example and the py3plex and Python versions where relevant.
201
+
200
202
  ### MCP Integration (AI Agents)
201
203
 
202
204
  py3plex provides a Model Context Protocol (MCP) server for integration with AI coding assistants:
@@ -51,8 +51,9 @@ For detailed documentation, see: https://skblaz.github.io/py3plex/
51
51
  """
52
52
 
53
53
  # Version information
54
- __version__ = "2.0.6"
55
- __api_version__ = "2.0.6"
54
+ from ._version import __version__
55
+
56
+ __api_version__ = __version__
56
57
 
57
58
  from py3plex.core.multinet import multi_layer_network
58
59
  from py3plex.core.types import (
@@ -0,0 +1,3 @@
1
+ """Single source for py3plex release version metadata."""
2
+
3
+ __version__ = "2.0.92"
@@ -46,7 +46,7 @@ def load_network_from_path(
46
46
  """Load a network from path and return stable machine-facing payload."""
47
47
  net = multinet.multi_layer_network(directed=directed)
48
48
  net.load_network(path, input_type=input_type)
49
- layers = list(net.get_layers())
49
+ layers = net.layers
50
50
  return {
51
51
  "status": "ok",
52
52
  "assumptions": ["Network path is trusted and readable."],
@@ -200,11 +200,11 @@ def correlate_attributes_across_layers(
200
200
  for i, l1 in enumerate(layers):
201
201
  for l2 in layers[i+1:]:
202
202
  # Find common nodes
203
- common_nodes = set(layer_attrs[l1].keys()) & set(layer_attrs[l2].keys())
203
+ common_nodes = [node for node in layer_attrs[l1] if node in layer_attrs[l2]]
204
204
 
205
205
  if len(common_nodes) > 1:
206
- vals1 = np.array([layer_attrs[l1][node] for node in sorted(common_nodes)])
207
- vals2 = np.array([layer_attrs[l2][node] for node in sorted(common_nodes)])
206
+ vals1 = np.array([layer_attrs[l1][node] for node in common_nodes])
207
+ vals2 = np.array([layer_attrs[l2][node] for node in common_nodes])
208
208
 
209
209
  corr, pval = _compute_correlation(vals1, vals2, correlation_method)
210
210
  results[(l1, l2)] = (corr, pval)
@@ -77,7 +77,8 @@ def _brandes_sssp_weighted(
77
77
  - dist: Dict mapping each node to distance from source (inf if unreachable)
78
78
  """
79
79
  import heapq
80
-
80
+ from itertools import count
81
+
81
82
  S = []
82
83
  P = {v: [] for v in G}
83
84
  sigma = dict.fromkeys(G, 0.0)
@@ -85,22 +86,28 @@ def _brandes_sssp_weighted(
85
86
  dist = {v: float('inf') for v in G}
86
87
  dist[source] = 0.0
87
88
  seen = {source: 0.0}
88
- # Priority queue: (distance, node)
89
- Q = [(0.0, source)]
89
+ # A unique tie-breaker avoids comparing arbitrary node identifiers.
90
+ counter = count()
91
+ Q = [(0.0, next(counter), source)]
90
92
 
91
93
  while Q:
92
- (dist_v, v) = heapq.heappop(Q)
94
+ (dist_v, _, v) = heapq.heappop(Q)
93
95
  if dist_v > seen.get(v, float('inf')):
94
96
  continue # Already processed with shorter distance
95
97
  S.append(v)
96
98
 
97
99
  for w in G.neighbors(v):
98
- # Get edge weight
99
- vw_dist = dist[v] + G[v][w].get(weight, 1.0)
100
+ # NetworkX shortest paths use the minimum parallel-edge weight.
101
+ edge_data = G[v][w]
102
+ if G.is_multigraph():
103
+ edge_weight = min(data.get(weight, 1.0) for data in edge_data.values())
104
+ else:
105
+ edge_weight = edge_data.get(weight, 1.0)
106
+ vw_dist = dist[v] + edge_weight
100
107
  if vw_dist < dist[w]:
101
108
  dist[w] = vw_dist
102
109
  seen[w] = vw_dist
103
- heapq.heappush(Q, (vw_dist, w))
110
+ heapq.heappush(Q, (vw_dist, next(counter), w))
104
111
  sigma[w] = 0.0
105
112
  P[w] = []
106
113
  if vw_dist == dist[w]:
@@ -204,9 +211,9 @@ def approximate_betweenness_sampling(
204
211
  sumsq_c[v] += x * x
205
212
 
206
213
  # Scale to estimate sum over all sources
207
- # Estimator: (N-1) / n_samples * sum_over_samples
208
- # This is unbiased when sampling with replacement
209
- scale = (N - 1) / float(n_samples)
214
+ # Sources are sampled uniformly from all N nodes, including each target.
215
+ # The estimated population total is N times the sample mean.
216
+ scale = N / float(n_samples)
210
217
  betw = {v: scale * sum_c[v] for v in nodes}
211
218
 
212
219
  # Compute standard error if requested
@@ -217,8 +224,9 @@ def approximate_betweenness_sampling(
217
224
  mean = sum_c[v] / n_samples
218
225
  # Sample variance: E[X^2] - E[X]^2
219
226
  var = max(0.0, (sumsq_c[v] / n_samples) - mean * mean)
220
- # Standard error of scaled mean: scale * sqrt(var / n_samples)
221
- stderr[v] = scale * math.sqrt(var / n_samples) if var > 0 else 0.0
227
+ # The estimate is N times the sample mean, so its standard error
228
+ # scales by N (not the N / n_samples factor applied to the sum).
229
+ stderr[v] = N * math.sqrt(var / n_samples) if var > 0 else 0.0
222
230
 
223
231
  # Apply normalization and undirected correction
224
232
  # For undirected graphs, betweenness counts each path twice
@@ -56,7 +56,8 @@ def _allocate_landmarks(
56
56
 
57
57
  Args:
58
58
  components: List of connected components (sets of nodes)
59
- n_landmarks: Total number of landmarks to allocate
59
+ n_landmarks: Requested total, expanded if needed to cover each
60
+ non-trivial component
60
61
 
61
62
  Returns:
62
63
  List of landmark counts for each component (at least 1 for each non-trivial component)
@@ -64,31 +65,24 @@ def _allocate_landmarks(
64
65
  if not components:
65
66
  return []
66
67
 
67
- # Compute component sizes
68
- sizes = [len(c) for c in components]
69
- total_size = sum(sizes)
70
-
71
- if total_size == 0:
72
- return [0] * len(components)
73
-
74
- # Allocate proportionally, with at least 1 for non-trivial components
75
- allocation = []
76
- remaining = n_landmarks
77
-
78
- for i, size in enumerate(sizes):
79
- if size == 1:
80
- # Singleton component - no landmarks needed
81
- allocation.append(0)
82
- elif i == len(sizes) - 1:
83
- # Last component gets remaining landmarks
84
- allocation.append(max(1, remaining))
85
- else:
86
- # Allocate proportionally, at least 1
87
- count = max(1, int(round(n_landmarks * size / total_size)))
88
- count = min(count, remaining - (len(sizes) - i - 1)) # Save at least 1 for each remaining
89
- allocation.append(count)
90
- remaining -= count
91
-
68
+ allocation = [0] * len(components)
69
+ active = [i for i, comp in enumerate(components) if len(comp) > 1]
70
+ if not active:
71
+ return allocation
72
+
73
+ # Cover every non-trivial component, then apportion the remaining budget.
74
+ # A budget below the component count is expanded to retain that guarantee.
75
+ remaining = max(n_landmarks, len(active)) - len(active)
76
+ total_size = sum(len(components[i]) for i in active)
77
+ remainders = {}
78
+ for i in active:
79
+ extra, remainder = divmod(remaining * len(components[i]), total_size)
80
+ allocation[i] = 1 + extra
81
+ remainders[i] = remainder
82
+
83
+ leftover = max(n_landmarks, len(active)) - sum(allocation)
84
+ for i in sorted(active, key=lambda i: (-remainders[i], i))[:leftover]:
85
+ allocation[i] += 1
92
86
  return allocation
93
87
 
94
88
 
@@ -102,7 +96,8 @@ def approximate_closeness_landmarks(
102
96
  """Compute approximate closeness centrality using landmark sampling.
103
97
 
104
98
  For each node, this estimates closeness by computing average distance
105
- to randomly sampled landmark nodes. For undirected graphs, components
99
+ from randomly sampled landmark nodes, matching NetworkX inward
100
+ closeness for directed graphs. For undirected graphs, components
106
101
  are handled separately to avoid biasing estimates.
107
102
 
108
103
  Args:
@@ -118,9 +113,12 @@ def approximate_closeness_landmarks(
118
113
  - stderr_dict: Per-node standard error (None if diagnostics=False)
119
114
 
120
115
  Note:
121
- - For undirected graphs, landmarks are sampled per component
116
+ - For undirected graphs, landmarks are sampled per component, with at
117
+ least one per non-trivial component even if this exceeds n_landmarks
122
118
  - For directed graphs, landmarks are sampled globally
123
- - Closeness is defined as 1 / (average distance to reachable nodes)
119
+ - Directed closeness uses inward distances from reachable nodes
120
+ - Self-landmarks are excluded from the average and reachable fraction
121
+ - Uses NetworkX default Wasserman-Faust scaling for disconnected graphs
124
122
  - Time complexity: O(n_landmarks * (m + n log n)) for weighted graphs
125
123
  """
126
124
  rng = random.Random(seed)
@@ -139,9 +137,11 @@ def approximate_closeness_landmarks(
139
137
  comp_landmarks = _allocate_landmarks(comps, n_landmarks)
140
138
 
141
139
  # Sample landmarks from each component
140
+ # Preserve graph insertion order; component sets vary with PYTHONHASHSEED.
141
+ node_order = {node: i for i, node in enumerate(nodes)}
142
142
  landmarks = []
143
143
  for comp, k in zip(comps, comp_landmarks):
144
- comp_nodes = list(comp)
144
+ comp_nodes = sorted(comp, key=node_order.__getitem__)
145
145
  for _ in range(k):
146
146
  landmarks.append(comp_nodes[rng.randrange(len(comp_nodes))])
147
147
 
@@ -156,11 +156,11 @@ def approximate_closeness_landmarks(
156
156
  node_to_comp = None
157
157
 
158
158
  # Compute distances from each landmark
159
- # For directed graphs, we want distances TO landmarks, so we reverse
159
+ # Distances FROM landmarks estimate inward closeness for directed graphs.
160
160
  dist_maps = []
161
161
  for l in landmarks:
162
162
  dist = _single_source_shortest_path_lengths(
163
- G, l, weight=weight, reverse_for_directed=G.is_directed()
163
+ G, l, weight=weight
164
164
  )
165
165
  dist_maps.append(dist)
166
166
 
@@ -169,7 +169,7 @@ def approximate_closeness_landmarks(
169
169
  stderr = {} if diagnostics else None
170
170
 
171
171
  for v in nodes:
172
- # Collect distances from v to landmarks
172
+ # Collect distances from landmarks to v
173
173
  if node_to_comp is not None:
174
174
  # Undirected: use only landmarks from same component
175
175
  v_comp = node_to_comp[v]
@@ -177,11 +177,12 @@ def approximate_closeness_landmarks(
177
177
  for i, dist in enumerate(dist_maps):
178
178
  landmark = landmarks[i]
179
179
  l_comp = node_to_comp[landmark]
180
- if l_comp == v_comp and v in dist:
180
+ if l_comp == v_comp and landmark != v and v in dist:
181
181
  dists.append(dist[v])
182
182
  else:
183
183
  # Directed: use all landmarks
184
- dists = [dist[v] for dist in dist_maps if v in dist]
184
+ dists = [dist[v] for landmark, dist in zip(landmarks, dist_maps)
185
+ if landmark != v and v in dist]
185
186
 
186
187
  if not dists:
187
188
  # No reachable landmarks
@@ -199,12 +200,14 @@ def approximate_closeness_landmarks(
199
200
  else:
200
201
  base_closeness = 1.0 / mean_d
201
202
 
202
- # For directed graphs, adjust by reachable fraction
203
+ # NetworkX excludes the node itself and applies the Wasserman-Faust
204
+ # reachable fraction. Self-landmarks are not draws from other nodes.
203
205
  if G.is_directed():
204
- reachable_frac = len(dists) / float(len(landmarks)) if landmarks else 0.0
205
- closeness[v] = base_closeness * reachable_frac
206
+ other_landmarks = sum(landmark != v for landmark in landmarks)
207
+ reachable_frac = len(dists) / float(other_landmarks)
206
208
  else:
207
- closeness[v] = base_closeness
209
+ reachable_frac = (len(comps[v_comp]) - 1) / float(N - 1)
210
+ closeness[v] = base_closeness * reachable_frac
208
211
 
209
212
  # Compute standard error using delta method
210
213
  if diagnostics:
@@ -214,14 +217,10 @@ def approximate_closeness_landmarks(
214
217
  # Standard error of mean
215
218
  se_mean = math.sqrt(var_d / len(dists))
216
219
  # Delta method: var(1/X) ≈ (se/mean^2)^2 for small se
217
- stderr[v] = se_mean / (mean_d * mean_d)
220
+ stderr[v] = reachable_frac * se_mean / (mean_d * mean_d)
218
221
  else:
219
222
  stderr[v] = 0.0
220
223
 
221
- # Optional normalization (consistent with NetworkX)
222
- # NetworkX closeness_centrality normalizes by (N-1) for simple graphs
223
- # We keep raw estimates for now, but could add normalization flag if needed
224
-
225
224
  return closeness, stderr
226
225
 
227
226
 
@@ -60,10 +60,12 @@ def jaccard_layer_similarity(
60
60
  if isinstance(node, tuple) and len(node) >= 2 and node[1] == layer2}
61
61
 
62
62
  elif element == "edges":
63
- set1 = {(u[0], v[0]) for u, v in G.edges()
63
+ # Undirected edges are unordered, regardless of node insertion order.
64
+ edge_identity = tuple if G.is_directed() else frozenset
65
+ set1 = {edge_identity((u[0], v[0])) for u, v in G.edges()
64
66
  if isinstance(u, tuple) and isinstance(v, tuple) and
65
67
  len(u) >= 2 and len(v) >= 2 and u[1] == layer1 and v[1] == layer1}
66
- set2 = {(u[0], v[0]) for u, v in G.edges()
68
+ set2 = {edge_identity((u[0], v[0])) for u, v in G.edges()
67
69
  if isinstance(u, tuple) and isinstance(v, tuple) and
68
70
  len(u) >= 2 and len(v) >= 2 and u[1] == layer2 and v[1] == layer2}
69
71
  else:
@@ -1011,7 +1011,7 @@ class MultilayerCentrality:
1011
1011
  # Map back to node-layer pairs
1012
1012
  results = {}
1013
1013
  for node_layer, idx in node_layer_mapping.items():
1014
- results[node_layer] = nx_current_flow.get(idx, 0.0)
1014
+ results[node_layer] = max(0.0, nx_current_flow.get(idx, 0.0))
1015
1015
 
1016
1016
  return results
1017
1017
 
@@ -28,6 +28,9 @@ def streaming_pagerank(
28
28
  incrementally, using the previous window's scores as the starting point
29
29
  for the next window. This is much faster than recomputing from scratch
30
30
  for each window.
31
+
32
+ Scores held by nodes without outgoing edges are redistributed uniformly
33
+ among the current window's nodes at each power iteration.
31
34
 
32
35
  Args:
33
36
  temporal_network: TemporalMultiLayerNetwork instance
@@ -97,6 +100,11 @@ def streaming_pagerank(
97
100
  # Run limited power iteration
98
101
  for _ in range(max_iter_per_window):
99
102
  new_scores = {}
103
+ dangling_mass = sum(
104
+ scores[node]
105
+ for node in nodes
106
+ if (graph.out_degree(node) if graph.is_directed() else graph.degree(node)) == 0
107
+ ) / len(nodes)
100
108
 
101
109
  for node in nodes:
102
110
  # Compute incoming contribution
@@ -105,16 +113,24 @@ def streaming_pagerank(
105
113
  if pred in scores:
106
114
  # Get out-degree of predecessor
107
115
  out_degree = graph.out_degree(pred) if graph.is_directed() else graph.degree(pred)
116
+ if not graph.is_directed():
117
+ # Degree counts self-loops twice; PageRank traverses them once.
118
+ out_degree -= graph.number_of_edges(pred, pred)
108
119
  if out_degree > 0:
109
- incoming_score += scores[pred] / out_degree
120
+ edge_count = graph.number_of_edges(pred, node)
121
+ incoming_score += scores[pred] * edge_count / out_degree
110
122
 
111
123
  # Apply damping
112
- new_scores[node] = (1 - damping_factor) / len(nodes) + damping_factor * incoming_score
124
+ new_scores[node] = (
125
+ (1 - damping_factor) / len(nodes)
126
+ + damping_factor * (incoming_score + dangling_mass)
127
+ )
113
128
 
114
129
  # Check convergence
115
130
  if scores:
116
131
  max_change = max(abs(new_scores.get(n, 0) - scores.get(n, 0)) for n in nodes)
117
132
  if max_change < tolerance:
133
+ scores = new_scores
118
134
  break
119
135
 
120
136
  scores = new_scores
@@ -145,7 +161,8 @@ def streaming_degree_centrality(
145
161
  temporal_network: TemporalMultiLayerNetwork instance
146
162
  window_size: Size of each time window (required)
147
163
  step: Step size between windows (defaults to window_size)
148
- normalize: Whether to normalize by max possible degree (default: True)
164
+ normalize: Whether to divide total degree by n - 1 (default: True).
165
+ Directed, parallel, or self-loop degrees may yield values above 1.
149
166
 
150
167
  Yields:
151
168
  Tuples of (t_start, t_end, centrality_dict)
@@ -181,7 +198,7 @@ def streaming_degree_centrality(
181
198
  # Normalize if requested
182
199
  if normalize and degrees:
183
200
  n = graph.number_of_nodes()
184
- max_degree = 2 * (n - 1) if not graph.is_directed() else (n - 1)
201
+ max_degree = n - 1
185
202
  if max_degree > 0:
186
203
  degrees = {node: deg / max_degree for node, deg in degrees.items()}
187
204
 
@@ -399,14 +399,19 @@ class AutoCommunityRunner(CommunityAlgorithmRunner):
399
399
  if uq_spec and uq_spec.get("n_samples", 0) > 1:
400
400
  uq_method = uq_spec.get("method", "seed")
401
401
  n_samples = uq_spec.get("n_samples", 10)
402
- uq_seed = uq_spec.get("seed", seed or 42)
402
+ uq_seed = uq_spec.get("seed", seed if seed is not None else 42)
403
403
  ac = ac.uq(method=uq_method, n_samples=n_samples, seed=uq_seed)
404
404
 
405
405
  # Set selection mode
406
406
  if mode == "pareto":
407
407
  ac = ac.pareto()
408
408
  elif mode == "wins":
409
- ac = ac.select_by_wins()
409
+ raise AlgorithmError(
410
+ "AutoCommunityRunner does not support mode='wins'. "
411
+ "Use mode='pareto' for benchmarks, or call "
412
+ "auto_select_community(..., mode='wins') directly.",
413
+ algorithm_name="autocommunity",
414
+ )
410
415
  else:
411
416
  ac = ac.pareto()
412
417
 
@@ -300,6 +300,15 @@ def _compute_avg_shortest_path(graph: multinet.multi_layer_network) -> float:
300
300
  continue
301
301
 
302
302
  subgraph = G.subgraph(comp)
303
+ if G.is_directed():
304
+ # Weak connectivity does not imply that every ordered pair is
305
+ # reachable. Count only reachable pairs, preserving direction.
306
+ for source, distances in nx.all_pairs_shortest_path_length(subgraph):
307
+ for target, distance in distances.items():
308
+ if source != target:
309
+ total_length += distance
310
+ total_pairs += 1
311
+ continue
303
312
  try:
304
313
  # Use average_shortest_path_length for each component
305
314
  avg_len = nx.average_shortest_path_length(subgraph)
@@ -1779,11 +1779,10 @@ def cmd_query(args: argparse.Namespace) -> int:
1779
1779
  # Execute query. Some lower-level layout/progress utilities print
1780
1780
  # diagnostics directly to stdout; keep command stdout parseable.
1781
1781
  if args.dsl:
1782
- # Interpret as Python DSL builder syntax
1783
- from py3plex.dsl.builder_parser import parse_builder_query
1782
+ # Parse builder syntax as a restricted AST expression; never run it as Python.
1783
+ from py3plex.safe_dsl_expression import evaluate_dsl_expression
1784
1784
 
1785
- query_builder = parse_builder_query(query_str)
1786
-
1785
+ query_builder = evaluate_dsl_expression(query_str)
1787
1786
  with contextlib.redirect_stdout(sys.stderr):
1788
1787
  result = query_builder.execute(network)
1789
1788
  else:
@@ -1927,20 +1926,18 @@ def cmd_dsl_lint(args: argparse.Namespace) -> int:
1927
1926
  logger.error(f"Failed to load network: {e}")
1928
1927
  return 2
1929
1928
 
1930
- # Parse query using the restricted builder syntax.
1929
+ # Parse documented builder expressions without evaluating Python code.
1931
1930
  from py3plex.dsl import lint, explain
1932
- from py3plex.dsl.builder_parser import parse_builder_query
1933
-
1934
- # Try to parse as builder syntax first
1931
+ from py3plex.safe_dsl_expression import evaluate_dsl_expression
1932
+
1935
1933
  try:
1936
- query_builder = parse_builder_query(query_str)
1934
+ query_builder = evaluate_dsl_expression(query_str)
1937
1935
  query_ast = query_builder.to_ast()
1938
- except Exception:
1939
- # Fall back to treating it as a note that we need string DSL support
1940
- logger.error("String DSL syntax not yet supported for linting.")
1941
- logger.error("Please use builder syntax: Q.nodes().from_layers(L['social']).where(degree__gt=5)")
1936
+ except (ValueError, TypeError) as exc:
1937
+ logger.error("Invalid DSL builder expression: %s", exc)
1938
+ logger.error("Use builder syntax such as Q.nodes().from_layers(L['social']).where(degree__gt=5)")
1942
1939
  return 2
1943
-
1940
+
1944
1941
  # Run linting
1945
1942
  if args.explain:
1946
1943
  # Get detailed explanation
@@ -182,7 +182,9 @@ def _dict_to_dataframe(data: Dict[str, Any]) -> pd.DataFrame:
182
182
  result[f"attrs_{col}"] = [
183
183
  _encode_attr_value(item) for item in attrs_df[col].tolist()
184
184
  ]
185
- elif isinstance(value, list) and all(isinstance(item, dict) for item in value):
185
+ elif key == "attrs" and isinstance(value, list) and all(
186
+ isinstance(item, dict) for item in value
187
+ ):
186
188
  # List of dicts (attrs as records)
187
189
  attrs_df = pd.DataFrame(value)
188
190
  if row_count is not None:
@@ -218,8 +218,9 @@ WARN_DEPRECATED: bool = True
218
218
  # Library Metadata
219
219
  # ─────────────────────────────────────────────────────────────────────────────
220
220
 
221
- __api_version__ = "2.0.6"
222
- __version__ = "2.0.6"
221
+ from ._version import __version__
222
+
223
+ __api_version__ = __version__
223
224
 
224
225
  # ─────────────────────────────────────────────────────────────────────────────
225
226
  # Helper Functions
@@ -57,6 +57,19 @@ class LazyProperty:
57
57
  setattr(obj, cache_attr, value)
58
58
 
59
59
 
60
+ class _IdentityKey:
61
+ """Hash a receiver by identity, keeping it alive while its entry is cached."""
62
+
63
+ def __init__(self, obj: Any) -> None:
64
+ self.obj = obj
65
+
66
+ def __hash__(self) -> int:
67
+ return id(self.obj)
68
+
69
+ def __eq__(self, other: Any) -> bool:
70
+ return isinstance(other, _IdentityKey) and self.obj is other.obj
71
+
72
+
60
73
  class CacheManager:
61
74
  """Manages caching for expensive network computations.
62
75
 
@@ -127,8 +140,13 @@ class CacheManager:
127
140
  def decorator(func: Callable) -> Callable:
128
141
  @functools.wraps(func)
129
142
  def wrapper(obj_self, *args, **kwargs):
130
- # Generate cache key from function name and arguments
131
- cache_key = cache_manager._generate_cache_key(func.__name__, args, kwargs)
143
+ # Scope results to the method and receiver as well as its arguments.
144
+ # Retaining the receiver prevents reuse of its identity after GC.
145
+ cache_key = (
146
+ func,
147
+ _IdentityKey(obj_self),
148
+ cache_manager._generate_cache_key(func.__name__, args, kwargs),
149
+ )
132
150
  cache = cache_manager.get_cache(cache_name)
133
151
 
134
152
  # Check if result is cached