py3plex 2.0.8__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.8/py3plex.egg-info → py3plex-2.0.92}/PKG-INFO +7 -3
  2. {py3plex-2.0.8 → py3plex-2.0.92}/README.md +4 -2
  3. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/_version.py +1 -1
  4. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/agent.py +1 -1
  5. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/attribute_correlation.py +3 -3
  6. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/centrality/approx_betweenness.py +20 -12
  7. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/centrality/approx_closeness.py +43 -44
  8. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/layer_similarity.py +4 -2
  9. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/centrality.py +1 -1
  10. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/temporal/centrality.py +21 -4
  11. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/benchmarks/runners.py +7 -2
  12. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/centrality/robustness.py +9 -0
  13. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/sidecar.py +3 -1
  14. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/lazy_evaluation.py +20 -2
  15. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/multinet.py +36 -26
  16. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/parsers.py +64 -49
  17. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/temporal_multinet.py +47 -17
  18. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/ast.py +21 -5
  19. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/builder.py +28 -2
  20. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/executor.py +55 -21
  21. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/cache.py +2 -0
  22. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/program.py +8 -0
  23. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/result.py +76 -20
  24. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl_legacy.py +7 -0
  25. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/formats/arrow_format.py +26 -13
  26. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/multinet_bridge.py +61 -79
  27. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/nullmodels/models.py +27 -23
  28. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/optimizer/logical_plan.py +58 -7
  29. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/optimizer/optimizer.py +52 -9
  30. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/optimizer/physical_plan.py +30 -2
  31. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/optimizer/plan_nodes.py +1 -0
  32. py3plex-2.0.92/py3plex/optimizer/rules.py +1024 -0
  33. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/paths/algorithms.py +5 -1
  34. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/temporal_utils.py +16 -9
  35. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/temporal_view.py +26 -35
  36. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/wrappers/benchmark_nodes.py +5 -2
  37. {py3plex-2.0.8 → py3plex-2.0.92/py3plex.egg-info}/PKG-INFO +7 -3
  38. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex.egg-info/SOURCES.txt +66 -0
  39. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex.egg-info/requires.txt +6 -0
  40. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex_mcp/__init__.py +1 -1
  41. {py3plex-2.0.8 → py3plex-2.0.92}/pyproject.toml +2 -0
  42. py3plex-2.0.92/tests/test_agent_loading_stats.py +63 -0
  43. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_approximate_centrality.py +2 -2
  44. py3plex-2.0.92/tests/test_approximation_dispatch_regressions.py +65 -0
  45. py3plex-2.0.92/tests/test_approximation_sample_scope_regressions.py +65 -0
  46. py3plex-2.0.92/tests/test_arrow_scalar_ids.py +75 -0
  47. py3plex-2.0.92/tests/test_ast_json_specs_regressions.py +39 -0
  48. py3plex-2.0.92/tests/test_ast_json_target_regressions.py +41 -0
  49. py3plex-2.0.92/tests/test_benchmark_runner_modes.py +75 -0
  50. py3plex-2.0.92/tests/test_benchmark_runner_seeds.py +55 -0
  51. py3plex-2.0.92/tests/test_betweenness_sampling_scaling_regression.py +69 -0
  52. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_book_conf.py +1 -1
  53. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_book_manuscript_integrity.py +1 -1
  54. py3plex-2.0.92/tests/test_bridge_edge_attributes.py +140 -0
  55. py3plex-2.0.92/tests/test_bridge_empty_export.py +57 -0
  56. py3plex-2.0.92/tests/test_bridge_node_identifiers.py +72 -0
  57. py3plex-2.0.92/tests/test_bridge_replica_collisions.py +40 -0
  58. py3plex-2.0.92/tests/test_builder_ast_replay_regressions.py +37 -0
  59. py3plex-2.0.92/tests/test_cache_method_identity.py +119 -0
  60. py3plex-2.0.92/tests/test_canonical_ast_isolation_regressions.py +74 -0
  61. py3plex-2.0.92/tests/test_canonical_projection_order_regressions.py +42 -0
  62. py3plex-2.0.92/tests/test_canonical_query_settings_regressions.py +85 -0
  63. py3plex-2.0.92/tests/test_closeness_allocation_regressions.py +67 -0
  64. py3plex-2.0.92/tests/test_closeness_direction_regressions.py +48 -0
  65. py3plex-2.0.92/tests/test_closeness_normalization_regressions.py +74 -0
  66. py3plex-2.0.92/tests/test_closeness_seed_regressions.py +46 -0
  67. py3plex-2.0.92/tests/test_configuration_directed_degrees.py +104 -0
  68. py3plex-2.0.92/tests/test_correlation_mixed_identities.py +72 -0
  69. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dependency_cleanup.py +7 -1
  70. py3plex-2.0.92/tests/test_dependency_cleanup_compat.py +34 -0
  71. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl.py +29 -0
  72. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_community_uq_integration.py +18 -0
  73. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_executor_additional.py +40 -0
  74. py3plex-2.0.92/tests/test_dsl_optimizer_integration.py +131 -0
  75. py3plex-2.0.92/tests/test_dsl_optimizer_rewrites.py +264 -0
  76. py3plex-2.0.92/tests/test_edgelist_reload_regression.py +59 -0
  77. py3plex-2.0.92/tests/test_erdos_renyi_directed.py +76 -0
  78. py3plex-2.0.92/tests/test_flow_direction.py +99 -0
  79. py3plex-2.0.92/tests/test_flow_parallel_capacity.py +109 -0
  80. py3plex-2.0.92/tests/test_gml_data_preservation.py +45 -0
  81. py3plex-2.0.92/tests/test_gpickle_directed_conversion.py +37 -0
  82. py3plex-2.0.92/tests/test_gpickle_layer_data.py +51 -0
  83. py3plex-2.0.92/tests/test_graphml_loading.py +77 -0
  84. py3plex-2.0.92/tests/test_layer_shuffle_seed_order.py +100 -0
  85. py3plex-2.0.92/tests/test_layer_similarity_edge_orientation.py +39 -0
  86. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_link_checker.py +1 -0
  87. py3plex-2.0.92/tests/test_load_directed_default.py +46 -0
  88. py3plex-2.0.92/tests/test_matrix_network_weights.py +38 -0
  89. py3plex-2.0.92/tests/test_mixed_layer_enumeration.py +44 -0
  90. py3plex-2.0.92/tests/test_multiedgelist_weights_regressions.py +41 -0
  91. py3plex-2.0.92/tests/test_numeric_cache_mutations.py +91 -0
  92. py3plex-2.0.92/tests/test_numeric_parallel_weights.py +90 -0
  93. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_optimizer_submodules.py +3 -1
  94. py3plex-2.0.92/tests/test_parse_nx_direction.py +46 -0
  95. py3plex-2.0.92/tests/test_result_by_id_conflicts.py +174 -0
  96. py3plex-2.0.92/tests/test_result_difference_attributes.py +62 -0
  97. py3plex-2.0.92/tests/test_result_edge_identifier_export.py +66 -0
  98. py3plex-2.0.92/tests/test_result_networkx_direction.py +107 -0
  99. py3plex-2.0.92/tests/test_result_networkx_edge_keys.py +73 -0
  100. py3plex-2.0.92/tests/test_result_networkx_edge_metrics.py +76 -0
  101. py3plex-2.0.92/tests/test_result_networkx_node_lists.py +69 -0
  102. py3plex-2.0.92/tests/test_result_symmetric_difference_attributes.py +135 -0
  103. py3plex-2.0.92/tests/test_result_union_falsy_identifiers.py +93 -0
  104. py3plex-2.0.92/tests/test_robustness_directed_paths.py +40 -0
  105. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_roundtrip_invariants.py +18 -7
  106. py3plex-2.0.92/tests/test_scoped_canonical_embedding_regressions.py +33 -0
  107. py3plex-2.0.92/tests/test_sidecar_empty_tables.py +58 -0
  108. py3plex-2.0.92/tests/test_sparse_conversion_preserves_data.py +100 -0
  109. py3plex-2.0.92/tests/test_streaming_degree_normalization.py +65 -0
  110. py3plex-2.0.92/tests/test_streaming_pagerank_dangling.py +100 -0
  111. py3plex-2.0.92/tests/test_streaming_pagerank_selfloops.py +68 -0
  112. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal.py +4 -3
  113. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_algorithms.py +68 -0
  114. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_multinet.py +125 -0
  115. py3plex-2.0.92/tests/test_temporal_numeric_strings.py +36 -0
  116. py3plex-2.0.92/tests/test_temporal_single_timestamp.py +89 -0
  117. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_utils.py +26 -5
  118. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_view.py +102 -0
  119. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_windowed_queries.py +27 -0
  120. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_version_consistency.py +2 -2
  121. py3plex-2.0.92/tests/test_weighted_betweenness_identity_regression.py +66 -0
  122. py3plex-2.0.92/tests/test_weighted_multigraph_sampling_regression.py +70 -0
  123. py3plex-2.0.92/tests/test_wrappers_optional_gensim.py +48 -0
  124. py3plex-2.0.92/tests/test_wrappers_topk_zero.py +23 -0
  125. py3plex-2.0.8/py3plex/optimizer/rules.py +0 -536
  126. {py3plex-2.0.8 → py3plex-2.0.92}/LICENSE +0 -0
  127. {py3plex-2.0.8 → py3plex-2.0.92}/MANIFEST.in +0 -0
  128. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/__init__.py +0 -0
  129. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/__main__.py +0 -0
  130. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/_parallel.py +0 -0
  131. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/_safe_expression.py +0 -0
  132. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/__init__.py +0 -0
  133. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/backend.py +0 -0
  134. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/closure.py +0 -0
  135. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/fixed_point.py +0 -0
  136. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/lift.py +0 -0
  137. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/paths.py +0 -0
  138. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/registry.py +0 -0
  139. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/semiring.py +0 -0
  140. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/witness.py +0 -0
  141. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/__init__.py +0 -0
  142. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/advanced_random_generators.py +0 -0
  143. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/centrality/__init__.py +0 -0
  144. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/centrality/approx_pagerank.py +0 -0
  145. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/centrality/explain.py +0 -0
  146. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/centrality_toolkit.py +0 -0
  147. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_comparison.py +0 -0
  148. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/NoRC.py +0 -0
  149. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/__init__.py +0 -0
  150. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/auto_select.py +0 -0
  151. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/autocommunity.py +0 -0
  152. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/autocommunity_executor.py +0 -0
  153. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/budget.py +0 -0
  154. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/community_louvain.py +0 -0
  155. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/community_measures.py +0 -0
  156. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/community_ranking.py +0 -0
  157. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/community_wrapper.py +0 -0
  158. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/distributional.py +0 -0
  159. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/flow_hierarchy.py +0 -0
  160. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/__init__.py +0 -0
  161. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/conftest.py +0 -0
  162. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-bipartite.py +0 -0
  163. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-file-io.py +0 -0
  164. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-multiplex.py +0 -0
  165. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-networkx.py +0 -0
  166. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-simple.py +0 -0
  167. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-trigram-expanded.py +0 -0
  168. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-trigram.py +0 -0
  169. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/infomap.py +0 -0
  170. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/interfaces/python/setup.py +0 -0
  171. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/label_propagation.py +0 -0
  172. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/leiden_multilayer.py +0 -0
  173. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/leiden_uq.py +0 -0
  174. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/mdl_benchmark.py +0 -0
  175. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/multilayer_benchmark.py +0 -0
  176. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/multilayer_modularity.py +0 -0
  177. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/multilayer_quality_metrics.py +0 -0
  178. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/node_ranking.py +0 -0
  179. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/runner.py +0 -0
  180. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/sbm_metrics.py +0 -0
  181. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/sbm_wrapper.py +0 -0
  182. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/spectral_multilayer.py +0 -0
  183. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/successive_halving.py +0 -0
  184. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/curvature/__init__.py +0 -0
  185. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/curvature/ollivier_ricci_multilayer.py +0 -0
  186. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/general/__init__.py +0 -0
  187. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/general/benchmark_classification.py +0 -0
  188. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/general/walkers.py +0 -0
  189. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/graph_summarization.py +0 -0
  190. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/__init__.py +0 -0
  191. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/__main__.py +0 -0
  192. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/assets/builtin.n3 +0 -0
  193. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/__init__.py +0 -0
  194. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/converters.py +0 -0
  195. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/example.py +0 -0
  196. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/helpers.py +0 -0
  197. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/kb.py +0 -0
  198. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/load.py +0 -0
  199. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/predicate.py +0 -0
  200. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/rule.py +0 -0
  201. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/settings.py +0 -0
  202. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/term_parsers.py +0 -0
  203. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/learners/__init__.py +0 -0
  204. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/learners/bottomup.py +0 -0
  205. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/learners/learner.py +0 -0
  206. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/learners/optimal.py +0 -0
  207. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/__init__.py +0 -0
  208. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/adjustment.py +0 -0
  209. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/scorefunctions.py +0 -0
  210. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/significance.py +0 -0
  211. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/validate.py +0 -0
  212. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/meta_flow_report.py +0 -0
  213. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multicentrality.py +0 -0
  214. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/__init__.py +0 -0
  215. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/entanglement.py +0 -0
  216. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/multirank.py +0 -0
  217. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/multixrank.py +0 -0
  218. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/supra_matrix_function_centrality.py +0 -0
  219. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/versatility.py +0 -0
  220. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_clustering.py +0 -0
  221. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/network_classification/PPR.py +0 -0
  222. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/network_classification/__init__.py +0 -0
  223. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/network_classification/label_propagation.py +0 -0
  224. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/node_ranking/__init__.py +0 -0
  225. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/node_ranking/node_ranking.py +0 -0
  226. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/requirements_registry.py +0 -0
  227. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/robustness_testing.py +0 -0
  228. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/routing/__init__.py +0 -0
  229. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/routing/multiplex_paths.py +0 -0
  230. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/__init__.py +0 -0
  231. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/conversions.py +0 -0
  232. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/diagnostics.py +0 -0
  233. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/inference_vi.py +0 -0
  234. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/model_selection.py +0 -0
  235. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/multilayer_sbm.py +0 -0
  236. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/objectives.py +0 -0
  237. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/uq.py +0 -0
  238. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/utils.py +0 -0
  239. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sir_multiplex.py +0 -0
  240. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistical_report.py +0 -0
  241. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/__init__.py +0 -0
  242. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/basic_statistics.py +0 -0
  243. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/bayesian_distances.py +0 -0
  244. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/bayesiantests.py +0 -0
  245. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/correlation_networks.py +0 -0
  246. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/critical_distances.py +0 -0
  247. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/enrichment_modules.py +0 -0
  248. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/multilayer_statistics.py +0 -0
  249. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/powerlaw.py +0 -0
  250. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/stats_comparison.py +0 -0
  251. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/topology.py +0 -0
  252. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/temporal/__init__.py +0 -0
  253. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/temporal/community.py +0 -0
  254. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/temporal_multiplex/__init__.py +0 -0
  255. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/term_parsers/__init__.py +0 -0
  256. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/alignment/__init__.py +0 -0
  257. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/alignment/features.py +0 -0
  258. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/alignment/metrics.py +0 -0
  259. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/alignment/solvers.py +0 -0
  260. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/benchmarks/__init__.py +0 -0
  261. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/benchmarks/budget.py +0 -0
  262. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/benchmarks/metrics.py +0 -0
  263. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/centrality/__init__.py +0 -0
  264. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/claims/__init__.py +0 -0
  265. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/claims/generator.py +0 -0
  266. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/claims/learner.py +0 -0
  267. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/claims/scorer.py +0 -0
  268. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/claims/types.py +0 -0
  269. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/cli.py +0 -0
  270. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/comparison/__init__.py +0 -0
  271. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/comparison/executor.py +0 -0
  272. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/comparison/metrics.py +0 -0
  273. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/comparison/result.py +0 -0
  274. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/__init__.py +0 -0
  275. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/convert.py +0 -0
  276. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/converters/__init__.py +0 -0
  277. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/converters/dgl_converter.py +0 -0
  278. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/converters/igraph_converter.py +0 -0
  279. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/converters/networkx_converter.py +0 -0
  280. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/converters/pyg_converter.py +0 -0
  281. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/converters/scipy_converter.py +0 -0
  282. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/equality.py +0 -0
  283. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/exceptions.py +0 -0
  284. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/ir.py +0 -0
  285. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/schema.py +0 -0
  286. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/config.py +0 -0
  287. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/contracts/__init__.py +0 -0
  288. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/contracts/contract.py +0 -0
  289. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/contracts/engine.py +0 -0
  290. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/contracts/failure_modes.py +0 -0
  291. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/contracts/predicates.py +0 -0
  292. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/contracts/result.py +0 -0
  293. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/HINMINE/IO.py +0 -0
  294. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/HINMINE/__init__.py +0 -0
  295. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/HINMINE/dataStructures.py +0 -0
  296. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/HINMINE/decomposition.py +0 -0
  297. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/__init__.py +0 -0
  298. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/converters.py +0 -0
  299. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/immutable.py +0 -0
  300. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/nx_compat.py +0 -0
  301. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/random_generators.py +0 -0
  302. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/schema_validation.py +0 -0
  303. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/supporting.py +0 -0
  304. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/types.py +0 -0
  305. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterexamples/__init__.py +0 -0
  306. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterexamples/claim_lang.py +0 -0
  307. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterexamples/ddmin.py +0 -0
  308. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterexamples/engine.py +0 -0
  309. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterexamples/types.py +0 -0
  310. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterexamples/witness.py +0 -0
  311. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterfactual/__init__.py +0 -0
  312. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterfactual/comparator.py +0 -0
  313. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterfactual/engine.py +0 -0
  314. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterfactual/presets.py +0 -0
  315. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterfactual/result.py +0 -0
  316. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterfactual/spec.py +0 -0
  317. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/datasets/__init__.py +0 -0
  318. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/datasets/_data/aarhus_cs.edges +0 -0
  319. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/datasets/_data/synthetic_multilayer.edges +0 -0
  320. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/datasets/_generators.py +0 -0
  321. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/datasets/_loaders.py +0 -0
  322. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/diagnostics/__init__.py +0 -0
  323. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/diagnostics/builders.py +0 -0
  324. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/diagnostics/codes.py +0 -0
  325. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/diagnostics/core.py +0 -0
  326. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/diagnostics/utils.py +0 -0
  327. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/__init__.py +0 -0
  328. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/algebra.py +0 -0
  329. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/attribution.py +0 -0
  330. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/benchmark.py +0 -0
  331. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/benchmark_result.py +0 -0
  332. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/builder_parser.py +0 -0
  333. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/cache.py +0 -0
  334. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/communities.py +0 -0
  335. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/community_uq.py +0 -0
  336. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/compositional_uq.py +0 -0
  337. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/context.py +0 -0
  338. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/errors.py +0 -0
  339. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/executor_semiring.py +0 -0
  340. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/executors/__init__.py +0 -0
  341. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/executors/benchmark_executor.py +0 -0
  342. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/explain.py +0 -0
  343. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/export.py +0 -0
  344. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/expressions.py +0 -0
  345. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/fastpath.py +0 -0
  346. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/layers.py +0 -0
  347. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/__init__.py +0 -0
  348. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/diagnostic.py +0 -0
  349. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/lint_context.py +0 -0
  350. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/__init__.py +0 -0
  351. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/base.py +0 -0
  352. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl001_unknown_layer.py +0 -0
  353. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl002_unknown_attribute.py +0 -0
  354. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl101_type_mismatch.py +0 -0
  355. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl201_unsatisfiable.py +0 -0
  356. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl202_redundant.py +0 -0
  357. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/perf301_full_scan.py +0 -0
  358. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/perf302_cross_layer.py +0 -0
  359. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/schema.py +0 -0
  360. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/type_resolver.py +0 -0
  361. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/types.py +0 -0
  362. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/metrics.py +0 -0
  363. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/operator_registry.py +0 -0
  364. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/operators.py +0 -0
  365. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/patterns/__init__.py +0 -0
  366. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/patterns/builder.py +0 -0
  367. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/patterns/compiler.py +0 -0
  368. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/patterns/engine.py +0 -0
  369. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/patterns/ir.py +0 -0
  370. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/patterns/result.py +0 -0
  371. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/plan.py +0 -0
  372. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/planner.py +0 -0
  373. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/predictive.py +0 -0
  374. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/__init__.py +0 -0
  375. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/cost.py +0 -0
  376. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/diff.py +0 -0
  377. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/distribution.py +0 -0
  378. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/executor.py +0 -0
  379. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/explain.py +0 -0
  380. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/rewrite.py +0 -0
  381. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/types.py +0 -0
  382. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/provenance.py +0 -0
  383. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/reduction.py +0 -0
  384. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/registry.py +0 -0
  385. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/selection_uq.py +0 -0
  386. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/serializer.py +0 -0
  387. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/uq_algebra.py +0 -0
  388. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/uq_resolution.py +0 -0
  389. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/warnings.py +0 -0
  390. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/__init__.py +0 -0
  391. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/_utils.py +0 -0
  392. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/ast.py +0 -0
  393. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/builder.py +0 -0
  394. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/compartmental.py +0 -0
  395. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/config.py +0 -0
  396. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/core.py +0 -0
  397. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/errors.py +0 -0
  398. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/executor.py +0 -0
  399. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/models.py +0 -0
  400. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/processes.py +0 -0
  401. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/registry.py +0 -0
  402. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/result.py +0 -0
  403. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/serializer.py +0 -0
  404. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/embeddings/__init__.py +0 -0
  405. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/embeddings/base.py +0 -0
  406. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/embeddings/cache.py +0 -0
  407. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/embeddings/link_ops.py +0 -0
  408. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/embeddings/metapath2vec.py +0 -0
  409. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/embeddings/netmf.py +0 -0
  410. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ergonomics.py +0 -0
  411. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/errors.py +0 -0
  412. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/exceptions.py +0 -0
  413. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/__init__.py +0 -0
  414. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/artifacts.py +0 -0
  415. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/cli.py +0 -0
  416. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/env.py +0 -0
  417. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/errors.py +0 -0
  418. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/model.py +0 -0
  419. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/runner.py +0 -0
  420. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/store.py +0 -0
  421. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/utils.py +0 -0
  422. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/fast_examples.py +0 -0
  423. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/graph_ops.py +0 -0
  424. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/__init__.py +0 -0
  425. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/api.py +0 -0
  426. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/canonical_format.py +0 -0
  427. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/converters.py +0 -0
  428. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/exceptions.py +0 -0
  429. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/formats/__init__.py +0 -0
  430. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/formats/csv_format.py +0 -0
  431. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/formats/json_format.py +0 -0
  432. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/parquet_format.py +0 -0
  433. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/schema.py +0 -0
  434. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/lab/__init__.py +0 -0
  435. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/lab/base.py +0 -0
  436. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/linter.py +0 -0
  437. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/logging_config.py +0 -0
  438. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/meta/__init__.py +0 -0
  439. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/meta/builder.py +0 -0
  440. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/meta/result.py +0 -0
  441. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/meta/stats.py +0 -0
  442. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/meta/utils.py +0 -0
  443. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/__init__.py +0 -0
  444. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/__init__.py +0 -0
  445. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/base.py +0 -0
  446. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/deepwalk.py +0 -0
  447. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/evaluation.py +0 -0
  448. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/line.py +0 -0
  449. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/metapath2vec.py +0 -0
  450. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/multiplex.py +0 -0
  451. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/netmf.py +0 -0
  452. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/node2vec.py +0 -0
  453. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/similarity.py +0 -0
  454. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/trainer.py +0 -0
  455. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/utils.py +0 -0
  456. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/multinet/__init__.py +0 -0
  457. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/multinet/aggregation.py +0 -0
  458. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/nullmodels/__init__.py +0 -0
  459. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/nullmodels/executor.py +0 -0
  460. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/nullmodels/result.py +0 -0
  461. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/optimizer/__init__.py +0 -0
  462. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/optimizer/cost_model.py +0 -0
  463. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/__init__.py +0 -0
  464. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/cli.py +0 -0
  465. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/errors.py +0 -0
  466. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/executor.py +0 -0
  467. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/network.py +0 -0
  468. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/operators.py +0 -0
  469. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/readers.py +0 -0
  470. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/schema.py +0 -0
  471. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/spill.py +0 -0
  472. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/utils.py +0 -0
  473. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/paths/__init__.py +0 -0
  474. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/paths/executor.py +0 -0
  475. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/paths/result.py +0 -0
  476. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/pipeline.py +0 -0
  477. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/plugins/__init__.py +0 -0
  478. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/plugins/base.py +0 -0
  479. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/plugins/examples.py +0 -0
  480. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/plugins/registry.py +0 -0
  481. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/profiling.py +0 -0
  482. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/provenance/__init__.py +0 -0
  483. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/provenance/bundle.py +0 -0
  484. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/provenance/capture.py +0 -0
  485. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/provenance/replay.py +0 -0
  486. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/provenance/schema.py +0 -0
  487. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/requirements.py +0 -0
  488. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/robustness/__init__.py +0 -0
  489. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/robustness/experiments.py +0 -0
  490. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/robustness/perturbations.py +0 -0
  491. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/runtime/__init__.py +0 -0
  492. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/runtime/capabilities.py +0 -0
  493. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/safe_dsl_expression.py +0 -0
  494. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/selection/__init__.py +0 -0
  495. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/selection/capabilities.py +0 -0
  496. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/selection/community_registry.py +0 -0
  497. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/selection/evaluate.py +0 -0
  498. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/selection/metric_registry.py +0 -0
  499. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/selection/result.py +0 -0
  500. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/selection/wins.py +0 -0
  501. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/semiring/__init__.py +0 -0
  502. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/semiring/core.py +0 -0
  503. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/semiring/engine.py +0 -0
  504. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/semiring/pareto.py +0 -0
  505. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/semiring/registry.py +0 -0
  506. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/semiring/types.py +0 -0
  507. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/sensitivity/__init__.py +0 -0
  508. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/sensitivity/executor.py +0 -0
  509. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/sensitivity/metrics.py +0 -0
  510. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/sensitivity/perturbations.py +0 -0
  511. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/sensitivity/types.py +0 -0
  512. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/stats/__init__.py +0 -0
  513. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/stats/provenance.py +0 -0
  514. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/stats/registry.py +0 -0
  515. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/stats/statvalue.py +0 -0
  516. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/stats/uncertainty.py +0 -0
  517. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/temporal_utils_extended.py +0 -0
  518. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/__init__.py +0 -0
  519. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/bootstrap.py +0 -0
  520. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/ci_utils.py +0 -0
  521. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/community_ensemble.py +0 -0
  522. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/community_result.py +0 -0
  523. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/context.py +0 -0
  524. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/estimation.py +0 -0
  525. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/noise_models.py +0 -0
  526. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/null_models.py +0 -0
  527. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/partition.py +0 -0
  528. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/partition_metrics.py +0 -0
  529. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/partition_reducers.py +0 -0
  530. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/partition_types.py +0 -0
  531. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/partition_uq.py +0 -0
  532. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/plan.py +0 -0
  533. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/reducers/__init__.py +0 -0
  534. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/reducers/base.py +0 -0
  535. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/resampling_graph.py +0 -0
  536. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/runner.py +0 -0
  537. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/selection_execution.py +0 -0
  538. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/selection_reducers.py +0 -0
  539. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/selection_types.py +0 -0
  540. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/selection_uq.py +0 -0
  541. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/stratification.py +0 -0
  542. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/types.py +0 -0
  543. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/utils.py +0 -0
  544. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/validation.py +0 -0
  545. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/__init__.py +0 -0
  546. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/benchmark_visualizations.py +0 -0
  547. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/bezier.py +0 -0
  548. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/colors.py +0 -0
  549. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/drawing_machinery.py +0 -0
  550. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/embedding_visualization/__init__.py +0 -0
  551. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/embedding_visualization/embedding_tools.py +0 -0
  552. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/embedding_visualization/embedding_visualization.py +0 -0
  553. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/fa2/__init__.py +0 -0
  554. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/fa2/fa2util.py +0 -0
  555. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/fa2/forceatlas2.py +0 -0
  556. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/layout_algorithms.py +0 -0
  557. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/multilayer.py +0 -0
  558. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/polyfit.py +0 -0
  559. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/pymnet_style.py +0 -0
  560. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/ricci_layout.py +0 -0
  561. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/ricci_multilayer_vis.py +0 -0
  562. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/sankey.py +0 -0
  563. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/workflows.py +0 -0
  564. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/wrappers/__init__.py +0 -0
  565. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/wrappers/r_interop.py +0 -0
  566. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/wrappers/train_node2vec_embedding.py +0 -0
  567. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex.egg-info/dependency_links.txt +0 -0
  568. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex.egg-info/entry_points.txt +0 -0
  569. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex.egg-info/not-zip-safe +0 -0
  570. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex.egg-info/top_level.txt +0 -0
  571. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex_mcp/errors.py +0 -0
  572. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex_mcp/registry.py +0 -0
  573. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex_mcp/safe_paths.py +0 -0
  574. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex_mcp/schemas.py +0 -0
  575. {py3plex-2.0.8 → py3plex-2.0.92}/py3plex_mcp/server.py +0 -0
  576. {py3plex-2.0.8 → py3plex-2.0.92}/setup.cfg +0 -0
  577. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_advanced_metrics_properties.py +0 -0
  578. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_agent_api.py +0 -0
  579. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_agents_documentation_claims.py +0 -0
  580. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_agents_ergonomics_features.py +0 -0
  581. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_agents_golden_paths.py +0 -0
  582. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_aggregation.py +0 -0
  583. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algebra_backend.py +0 -0
  584. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algebra_core.py +0 -0
  585. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algebra_fixed_point.py +0 -0
  586. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algebra_paths.py +0 -0
  587. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algebra_registry.py +0 -0
  588. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algebra_witness.py +0 -0
  589. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algorithm_properties.py +0 -0
  590. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algorithms_attribute_correlation.py +0 -0
  591. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algorithms_correlation_networks.py +0 -0
  592. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algorithms_init.py +0 -0
  593. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algorithms_random_generators.py +0 -0
  594. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algorithms_requirements_registry.py +0 -0
  595. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algorithms_statistics_bayesian_distances.py +0 -0
  596. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_alignment.py +0 -0
  597. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_alignment_contracts.py +0 -0
  598. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_alignment_correctness_additional.py +0 -0
  599. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ast_roundtrip.py +0 -0
  600. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ast_roundtrip_integration.py +0 -0
  601. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_attribute_correlation.py +0 -0
  602. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_attribute_correlation_contracts.py +0 -0
  603. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_auto_community.py +0 -0
  604. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_autocommunity_benchmarks.py +0 -0
  605. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_autocommunity_executor.py +0 -0
  606. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_autocommunity_meta.py +0 -0
  607. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_autocommunity_successive_halving.py +0 -0
  608. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_bayesian_distances.py +0 -0
  609. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_bench_aggregation_unit.py +0 -0
  610. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_benchmark_budget_fairness.py +0 -0
  611. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_benchmark_dsl_basic.py +0 -0
  612. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_benchmark_integration.py +0 -0
  613. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_benchmark_multiplex_centrality.py +0 -0
  614. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_benchmark_time.py +0 -0
  615. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_benchmarks_budget.py +0 -0
  616. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_benchmarks_init.py +0 -0
  617. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_book_snippets.py +0 -0
  618. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_builder_dsl_mutate.py +0 -0
  619. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_capabilities_basic.py +0 -0
  620. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_capabilities_optional_missing.py +0 -0
  621. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_centrality_explain.py +0 -0
  622. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_centrality_explain_integration.py +0 -0
  623. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_centrality_robustness.py +0 -0
  624. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_centrality_robustness_oracles.py +0 -0
  625. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_centrality_uncertainty.py +0 -0
  626. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_centrality_weight_handling.py +0 -0
  627. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_check_api_consistency.py +0 -0
  628. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_check_doc_coverage.py +0 -0
  629. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_check_type_coverage.py +0 -0
  630. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ci_python_versions.py +0 -0
  631. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_claim_learning.py +0 -0
  632. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_claims_types.py +0 -0
  633. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_cli.py +0 -0
  634. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_cli_check.py +0 -0
  635. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_cli_ergonomics.py +0 -0
  636. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_cli_piping.py +0 -0
  637. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_clustering_multilayer.py +0 -0
  638. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_code_improvements.py +0 -0
  639. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_community_comparison_coverage.py +0 -0
  640. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_community_detection_modules.py +0 -0
  641. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_community_distribution.py +0 -0
  642. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_community_measures.py +0 -0
  643. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_community_measures_coverage.py +0 -0
  644. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_comparison.py +0 -0
  645. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_comparison_executor.py +0 -0
  646. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_comparison_metrics.py +0 -0
  647. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_comparison_metrics_additional.py +0 -0
  648. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_comparison_result.py +0 -0
  649. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_comparison_uninitialized_and_resistance_oracles.py +0 -0
  650. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_compat_exceptions.py +0 -0
  651. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_compat_roundtrip.py +0 -0
  652. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_config_api.py +0 -0
  653. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_config_benchmark.py +0 -0
  654. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_contracts.py +0 -0
  655. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_contracts_basic.py +0 -0
  656. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_contracts_extended.py +0 -0
  657. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_contracts_failure_modes.py +0 -0
  658. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_contracts_integration.py +0 -0
  659. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_functionality.py +0 -0
  660. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_immutable.py +0 -0
  661. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_lazy_evaluation.py +0 -0
  662. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_multinet_and_parsers.py +0 -0
  663. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_multinet_correctness.py +0 -0
  664. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_multiplex_edges.py +0 -0
  665. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_schema_validation.py +0 -0
  666. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_supporting.py +0 -0
  667. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_correlation_networks.py +0 -0
  668. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_counterexamples.py +0 -0
  669. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_counterexamples_properties.py +0 -0
  670. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_counterfactual.py +0 -0
  671. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_counterfactual_presets.py +0 -0
  672. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_coverage_grouping.py +0 -0
  673. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_create_mosaic_banner.py +0 -0
  674. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_create_showcase_flow.py +0 -0
  675. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_crosshair_pure_functions.py +0 -0
  676. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_data_files_presence.py +0 -0
  677. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_datasets.py +0 -0
  678. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_datasets_contracts.py +0 -0
  679. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_datasets_oracles.py +0 -0
  680. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_degenerate_networks.py +0 -0
  681. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_determinism_randomness.py +0 -0
  682. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_diagnostics.py +0 -0
  683. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_diagnostics_utils.py +0 -0
  684. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_doc_conf.py +0 -0
  685. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_docs_embeddings_section.py +0 -0
  686. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_docs_examples.py +0 -0
  687. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_docs_quality_pass.py +0 -0
  688. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_doctests.py +0 -0
  689. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dplyr_integration.py +0 -0
  690. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_aggregation_enhancements.py +0 -0
  691. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_ast_equivalence.py +0 -0
  692. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_ast_immutability.py +0 -0
  693. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_auto_community.py +0 -0
  694. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_communities.py +0 -0
  695. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_community_filtering.py +0 -0
  696. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_compact_compute.py +0 -0
  697. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_compiler_explain.py +0 -0
  698. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_compiler_pipeline.py +0 -0
  699. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_compositional_uq.py +0 -0
  700. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_condition_semantics.py +0 -0
  701. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_d_factory.py +0 -0
  702. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_documentation_examples.py +0 -0
  703. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_dplyr_style.py +0 -0
  704. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_dynamics_integration.py +0 -0
  705. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_edge_grouping_coverage.py +0 -0
  706. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_edge_queries.py +0 -0
  707. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_enhancements.py +0 -0
  708. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_ergonomics.py +0 -0
  709. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_errors.py +0 -0
  710. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_errors_extended.py +0 -0
  711. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_explain.py +0 -0
  712. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_export.py +0 -0
  713. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_expressions.py +0 -0
  714. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_extensions.py +0 -0
  715. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_graphops_equivalence.py +0 -0
  716. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_grouping_coverage.py +0 -0
  717. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_interactive.py +0 -0
  718. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_joins.py +0 -0
  719. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_layer_resolution.py +0 -0
  720. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_layer_selection.py +0 -0
  721. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_layer_set_algebra.py +0 -0
  722. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_legacy_approximate.py +0 -0
  723. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_legacy_edges.py +0 -0
  724. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_lint.py +0 -0
  725. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_metric_registry.py +0 -0
  726. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_multilayer_measure_topology.py +0 -0
  727. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_operators.py +0 -0
  728. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_patterns.py +0 -0
  729. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_patterns_correctness.py +0 -0
  730. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_patterns_quick_reference.py +0 -0
  731. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_pipes.py +0 -0
  732. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_planner.py +0 -0
  733. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_planner_config.py +0 -0
  734. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_predict_reduce.py +0 -0
  735. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_program_rewrite.py +0 -0
  736. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_program_types.py +0 -0
  737. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_progress_logging.py +0 -0
  738. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_properties.py +0 -0
  739. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_provenance.py +0 -0
  740. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_query_optimization.py +0 -0
  741. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_query_zoo.py +0 -0
  742. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_result_algebra_edge_cases.py +0 -0
  743. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_selection_fastpath.py +0 -0
  744. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_semiring_integration.py +0 -0
  745. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_serializer.py +0 -0
  746. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_smart_defaults.py +0 -0
  747. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_temporal_range_execution.py +0 -0
  748. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_uncertainty.py +0 -0
  749. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_uq_ergonomics.py +0 -0
  750. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_uq_propagation.py +0 -0
  751. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_v2.py +0 -0
  752. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_zoo_features.py +0 -0
  753. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics.py +0 -0
  754. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_algorithm_contracts.py +0 -0
  755. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_config_and_results_correctness.py +0 -0
  756. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_conservation.py +0 -0
  757. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_core.py +0 -0
  758. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_executor_edge_cases.py +0 -0
  759. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_metamorphic.py +0 -0
  760. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_parallel_determinism.py +0 -0
  761. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_reference_runs.py +0 -0
  762. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_uq_integration.py +0 -0
  763. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_utils.py +0 -0
  764. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_edge_cases.py +0 -0
  765. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_edgelist_format.py +0 -0
  766. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_embeddings_direct_units.py +0 -0
  767. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ergonomic_helpers.py +0 -0
  768. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ergonomics.py +0 -0
  769. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ergonomics_helpers.py +0 -0
  770. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_errors.py +0 -0
  771. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_errors_coverage.py +0 -0
  772. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_CBSSD.py +0 -0
  773. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_community_detection.py +0 -0
  774. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_decomposition_and_classification.py +0 -0
  775. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_decomposition_ground_truth.py +0 -0
  776. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_dsl_builder_api.py +0 -0
  777. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_dynamics_core_examples.py +0 -0
  778. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_embedding_construction.py +0 -0
  779. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_embedding_visualization.py +0 -0
  780. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_incidence_gadget_encoding.py +0 -0
  781. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_interactive_multilayer.py +0 -0
  782. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_inverse_network.py +0 -0
  783. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_layer_extraction.py +0 -0
  784. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_manipulation.py +0 -0
  785. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_multilayer_vectorized_aggregation.py +0 -0
  786. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_multiplex_aggregate.py +0 -0
  787. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_multiplex_dynamics.py +0 -0
  788. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_n2v_embedding.py +0 -0
  789. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_network_decomposition.py +0 -0
  790. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_network_decomposition_meta_paths.py +0 -0
  791. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_numeric_encoding.py +0 -0
  792. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_pattern_matching.py +0 -0
  793. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_ppr.py +0 -0
  794. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_examples_zoo_consolidation.py +0 -0
  795. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_exception_taxonomy.py +0 -0
  796. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_exceptions.py +0 -0
  797. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_experiments.py +0 -0
  798. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_explain_attribution.py +0 -0
  799. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_fast_examples.py +0 -0
  800. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_flagship_progress_demo.py +0 -0
  801. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_flow_hierarchy.py +0 -0
  802. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_formal_phase1_alignment.py +0 -0
  803. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_fuzzing_properties.py +0 -0
  804. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_generate_all_outputs.py +0 -0
  805. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_generate_quickstart_outputs.py +0 -0
  806. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_generate_visualization_images.py +0 -0
  807. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_golden_toy_examples.py +0 -0
  808. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_graph_ops.py +0 -0
  809. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_graph_summarization.py +0 -0
  810. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_hedwig_adjustment.py +0 -0
  811. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_hedwig_significance.py +0 -0
  812. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_improved_errors.py +0 -0
  813. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_incidence_gadget_encoding.py +0 -0
  814. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_infomap_fix.py +0 -0
  815. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_interlayer_links_fix.py +0 -0
  816. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_api_edge_cases.py +0 -0
  817. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_arrow.py +0 -0
  818. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_contracts_additional.py +0 -0
  819. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_conversion_formats.py +0 -0
  820. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_converters.py +0 -0
  821. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_exceptions.py +0 -0
  822. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_integration.py +0 -0
  823. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_roundtrip.py +0 -0
  824. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_schema.py +0 -0
  825. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_issue_19_fix.py +0 -0
  826. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_lab.py +0 -0
  827. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_lab_additional.py +0 -0
  828. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_lab_correctness.py +0 -0
  829. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_label_propagation.py +0 -0
  830. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_layer_extraction_fix.py +0 -0
  831. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_layer_similarity.py +0 -0
  832. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_layout_algorithms.py +0 -0
  833. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_lazy_evaluation.py +0 -0
  834. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_leiden_multilayer.py +0 -0
  835. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_linter.py +0 -0
  836. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_logging_config_unit.py +0 -0
  837. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_logging_conversion.py +0 -0
  838. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_main_module.py +0 -0
  839. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_master_regulators_example.py +0 -0
  840. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_math_invariants.py +0 -0
  841. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_mcp_server.py +0 -0
  842. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_mdl_benchmark.py +0 -0
  843. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_mdl_score.py +0 -0
  844. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_mdl_score_corruption_monotonicity.py +0 -0
  845. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_mdl_score_reference_differential.py +0 -0
  846. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_mdl_score_resolution_limit_sweep.py +0 -0
  847. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_meta_analysis.py +0 -0
  848. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_meta_flow_report.py +0 -0
  849. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_meta_utils.py +0 -0
  850. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_metamorphic.py +0 -0
  851. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_metapath2vec.py +0 -0
  852. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ml_embedding_evaluation.py +0 -0
  853. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ml_embedding_primitives.py +0 -0
  854. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_monoplex_nx_wrapper.py +0 -0
  855. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_mpc.py +0 -0
  856. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_centrality.py +0 -0
  857. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_clustering_coefficients.py +0 -0
  858. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_cornercases.py +0 -0
  859. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_edge_fix.py +0 -0
  860. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_embedding_models.py +0 -0
  861. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_integration.py +0 -0
  862. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_leiden_uq.py +0 -0
  863. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_modularity.py +0 -0
  864. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_quality_metrics.py +0 -0
  865. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_quality_metrics_coverage.py +0 -0
  866. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_statistics.py +0 -0
  867. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_visualizations.py +0 -0
  868. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multinet_aggregation.py +0 -0
  869. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multinet_aggregation_additional.py +0 -0
  870. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multiplex_layer_interop.py +0 -0
  871. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multiplex_participation.py +0 -0
  872. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multiplex_properties.py +0 -0
  873. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multirank.py +0 -0
  874. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multixrank.py +0 -0
  875. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_network_conversion.py +0 -0
  876. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_network_version.py +0 -0
  877. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_networkx_compatibility.py +0 -0
  878. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_new_algorithms.py +0 -0
  879. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_new_multilayer_metrics.py +0 -0
  880. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_node_edge_parity.py +0 -0
  881. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_node_ranking_comprehensive.py +0 -0
  882. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_norc.py +0 -0
  883. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_nullmodel_sanity.py +0 -0
  884. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_nullmodels.py +0 -0
  885. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_nullmodels_contracts.py +0 -0
  886. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_nx_compat_extended.py +0 -0
  887. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ollivier_ricci_multilayer.py +0 -0
  888. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_out_of_core.py +0 -0
  889. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_parallel.py +0 -0
  890. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_parallel_execution.py +0 -0
  891. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_parsers_comprehensive.py +0 -0
  892. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_parsers_coverage.py +0 -0
  893. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_partition_uq.py +0 -0
  894. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_partition_uq_integration.py +0 -0
  895. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_paths.py +0 -0
  896. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_paths_additional.py +0 -0
  897. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_paths_contracts.py +0 -0
  898. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_paths_executor.py +0 -0
  899. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_paths_result.py +0 -0
  900. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_performance_core.py +0 -0
  901. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_pipeline.py +0 -0
  902. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_plugin_examples.py +0 -0
  903. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_plugin_system.py +0 -0
  904. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_plugins.py +0 -0
  905. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_plugins_contracts.py +0 -0
  906. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_profiling.py +0 -0
  907. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_profiling_additional.py +0 -0
  908. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_program.py +0 -0
  909. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_program_cache_identity.py +0 -0
  910. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_program_cost_executor.py +0 -0
  911. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_properties.py +0 -0
  912. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_provenance_canonical.py +0 -0
  913. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_provenance_replay.py +0 -0
  914. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_provenance_schema.py +0 -0
  915. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_public_api_exports.py +0 -0
  916. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_pymnet_style.py +0 -0
  917. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_pypi_publish_workflow.py +0 -0
  918. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_query_algebra.py +0 -0
  919. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_query_equivalence.py +0 -0
  920. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_r_interop.py +0 -0
  921. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_random_generators_additional.py +0 -0
  922. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_random_generators_extended.py +0 -0
  923. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_random_walkers.py +0 -0
  924. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_random_walks.py +0 -0
  925. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_readme_contributor_onboarding.py +0 -0
  926. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_readme_flagship_example.py +0 -0
  927. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_requirements.py +0 -0
  928. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_result_explain_debug.py +0 -0
  929. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ricci_visualization.py +0 -0
  930. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_robustness.py +0 -0
  931. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_robustness_additional.py +0 -0
  932. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_robustness_testing.py +0 -0
  933. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_root_conftest.py +0 -0
  934. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_run_quickstart_snippets.py +0 -0
  935. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_safe_expression.py +0 -0
  936. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sankey_visualization.py +0 -0
  937. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sbm_autocommunity.py +0 -0
  938. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sbm_generator.py +0 -0
  939. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sbm_metrics.py +0 -0
  940. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sbm_runner_integration.py +0 -0
  941. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_schema_and_immutable.py +0 -0
  942. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_seeding.py +0 -0
  943. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_selection_uq.py +0 -0
  944. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_selection_uq_empty_groups.py +0 -0
  945. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_selection_uq_integration.py +0 -0
  946. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_semiring_negative_cases.py +0 -0
  947. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_semiring_pareto.py +0 -0
  948. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_semiring_registry.py +0 -0
  949. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_semiring_types.py +0 -0
  950. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_semiring_verification.py +0 -0
  951. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sensitivity_executor.py +0 -0
  952. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sidecar.py +0 -0
  953. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sir_epidemic.py +0 -0
  954. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sir_long_convergence.py +0 -0
  955. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sir_multiplex.py +0 -0
  956. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_spectral_multilayer.py +0 -0
  957. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_statistical_report.py +0 -0
  958. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_comparison.py +0 -0
  959. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_core.py +0 -0
  960. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_edge_cases.py +0 -0
  961. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_provenance.py +0 -0
  962. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_provenance_dataclass.py +0 -0
  963. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_registry.py +0 -0
  964. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_scalar_uncertainty.py +0 -0
  965. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_verify.py +0 -0
  966. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stratified_uq.py +0 -0
  967. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_streaming_topk.py +0 -0
  968. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_successive_halving.py +0 -0
  969. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_supporting_extended.py +0 -0
  970. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_supra_matrix_function_centrality.py +0 -0
  971. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_builder.py +0 -0
  972. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_dsl.py +0 -0
  973. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_duration_parsing.py +0 -0
  974. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_utils_extended.py +0 -0
  975. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_tensor_representation.py +0 -0
  976. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_tutorial_10min.py +0 -0
  977. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_type_coverage_scan.py +0 -0
  978. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty.py +0 -0
  979. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty_additional.py +0 -0
  980. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty_builder_integration.py +0 -0
  981. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty_defaults.py +0 -0
  982. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty_dsl_integration.py +0 -0
  983. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty_engines.py +0 -0
  984. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty_oracles.py +0 -0
  985. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty_runner.py +0 -0
  986. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uq_algebra.py +0 -0
  987. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uq_integration.py +0 -0
  988. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uq_resolution.py +0 -0
  989. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uq_spine.py +0 -0
  990. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_user_journey_simulation.py +0 -0
  991. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_utils.py +0 -0
  992. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_utils_coverage.py +0 -0
  993. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_utils_extended.py +0 -0
  994. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_utils_search_paths.py +0 -0
  995. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_validation.py +0 -0
  996. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_validation_module.py +0 -0
  997. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_verification_api_differential.py +0 -0
  998. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_verification_centrality.py +0 -0
  999. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_verification_communities.py +0 -0
  1000. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_verification_determinism_parallelism.py +0 -0
  1001. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_verification_dsl_equivalence.py +0 -0
  1002. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_verification_metamorphic_harness.py +0 -0
  1003. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_verification_provenance_oracles.py +0 -0
  1004. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_versatility.py +0 -0
  1005. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_benchmark.py +0 -0
  1006. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_bezier.py +0 -0
  1007. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_colors.py +0 -0
  1008. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_imports.py +0 -0
  1009. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_layouts.py +0 -0
  1010. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_multilayer_additional.py +0 -0
  1011. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_polyfit.py +0 -0
  1012. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_ricci_layout_helpers.py +0 -0
  1013. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_supra_heatmap.py +0 -0
  1014. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualize_matrix_fix.py +0 -0
  1015. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_workflows.py +0 -0
  1016. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_wrappers_additional.py +0 -0
  1017. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_wrappers_benchmark_nodes.py +0 -0
  1018. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_wrappers_node2vec.py +0 -0
  1019. {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_wrappers_r_interop.py +0 -0
  1020. {py3plex-2.0.8 → 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.8
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.8K-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.8K-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:
@@ -1,3 +1,3 @@
1
1
  """Single source for py3plex release version metadata."""
2
2
 
3
- __version__ = "2.0.8"
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)
@@ -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:
@@ -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
@@ -360,7 +360,10 @@ def _encode_multilayer_network(core_network, directed):
360
360
  except (KeyError, IndexError, ValueError, TypeError):
361
361
  weight = 1
362
362
 
363
- simple_graph.add_edge(nmap[node_first], nmap[node_second], weight=weight)
363
+ # A numeric adjacency entry is the sum of parallel edge weights.
364
+ u, v = nmap[node_first], nmap[node_second]
365
+ previous_weight = simple_graph.get_edge_data(u, v, {}).get("weight", 0.0)
366
+ simple_graph.add_edge(u, v, weight=previous_weight + weight)
364
367
 
365
368
  vectors = nx_to_scipy_sparse_matrix(simple_graph)
366
369
  return vectors, simple_graph.nodes()
@@ -620,6 +623,9 @@ class multi_layer_network:
620
623
  """Increment the mutation counter by 1 (no-op when suspended)."""
621
624
  if not self._suspend_version_bump:
622
625
  self._network_version += 1
626
+ # Matrix exports must be rebuilt from the new graph structure.
627
+ self.numeric_core_network = None
628
+ self.node_order_in_matrix = None
623
629
 
624
630
  # ═════════════════════════════════════════════════════════════════════════
625
631
  # Core Data Access Methods
@@ -824,8 +830,11 @@ class multi_layer_network:
824
830
  def layers(self) -> List[Any]:
825
831
  """List of unique layer identifiers in the network.
826
832
 
833
+ Comparable identifiers are sorted. Otherwise, layers retain their
834
+ first-occurrence order in the network.
835
+
827
836
  Returns:
828
- list: Sorted list of layer identifiers
837
+ list: Layer identifiers in sorted or first-occurrence order
829
838
 
830
839
  Examples:
831
840
  >>> net = multi_layer_network()
@@ -839,9 +848,14 @@ class multi_layer_network:
839
848
  if self.core_network is None:
840
849
  return []
841
850
  try:
842
- unique_layers = {n[1] for n in self.core_network.nodes()
843
- if isinstance(n, tuple) and len(n) >= 2}
844
- return sorted(unique_layers)
851
+ unique_layers = dict.fromkeys(
852
+ n[1] for n in self.core_network.nodes()
853
+ if isinstance(n, tuple) and len(n) >= 2
854
+ )
855
+ try:
856
+ return sorted(unique_layers)
857
+ except TypeError:
858
+ return list(unique_layers)
845
859
  except (TypeError, IndexError):
846
860
  return []
847
861
 
@@ -871,7 +885,7 @@ class multi_layer_network:
871
885
  `split_to_layers()`) or defaults to the `layers` property.
872
886
 
873
887
  Returns:
874
- list: Sorted list of layer identifiers
888
+ list: Layer identifiers using the ordering of the layers property
875
889
 
876
890
  Examples:
877
891
  >>> net = multi_layer_network()
@@ -973,7 +987,7 @@ class multi_layer_network:
973
987
  def load_network(
974
988
  self,
975
989
  input_file: Optional[str] = None,
976
- directed: bool = False,
990
+ directed: Optional[bool] = None,
977
991
  input_type: str = "gml",
978
992
  label_delimiter: str = "---",
979
993
  ) -> "multi_layer_network":
@@ -989,10 +1003,12 @@ class multi_layer_network:
989
1003
 
990
1004
  Args:
991
1005
  input_file: Path to the network file to load
992
- directed: Whether the network is directed
1006
+ directed: Whether the network is directed. If omitted or None,
1007
+ retain the current setting (initially set by the constructor).
993
1008
  input_type: Format of the input file. Supported values:
994
1009
  - 'gml': Graph Modeling Language format
995
- - 'graphml': GraphML XML format
1010
+ - 'graphml': GraphML XML format (node 'type' selects layer;
1011
+ missing types use the GraphML default or 'generic')
996
1012
  - 'edgelist': Simple edge list (source target [weight])
997
1013
  - 'multiedgelist': Multilayer edge list (node1 layer1 node2 layer2 weight)
998
1014
  - 'multiplex_edges': Multiplex format (layer node1 node2 weight)
@@ -1030,6 +1046,9 @@ class multi_layer_network:
1030
1046
  if input_type != "nx":
1031
1047
  assert input_file is not None, "input_file must be provided for non-nx input types"
1032
1048
 
1049
+ if directed is None:
1050
+ directed = self.directed
1051
+
1033
1052
  self.input_file = input_file
1034
1053
  self.input_type = input_type
1035
1054
  self.directed = directed
@@ -1285,23 +1304,13 @@ class multi_layer_network:
1285
1304
  parsers.save_gpickle(self.core_network, output_file=output_file)
1286
1305
 
1287
1306
  def add_dummy_layers(self):
1288
- """
1289
- Internal function, for conversion between objects
1290
- """
1291
-
1292
- self.tmp_core_network = self.core_network
1293
- self.core_network = self._create_graph()
1294
-
1295
- for edge in self.tmp_core_network.edges():
1296
- self.add_edges(
1297
- {
1298
- "source": edge[0],
1299
- "target": edge[1],
1300
- "source_type": self.dummy_layer,
1301
- "target_type": self.dummy_layer,
1302
- }
1303
- )
1304
- del self.tmp_core_network
1307
+ """Wrap monoplex nodes in the dummy layer, preserving graph data."""
1308
+ graph_type = nx.MultiDiGraph if self.directed else nx.MultiGraph
1309
+ # Copy the complete graph so isolates, attributes and multiedge keys
1310
+ # survive. Rebuilding from bare edges loses all of that information.
1311
+ self.core_network = nx.relabel_nodes(
1312
+ graph_type(self.core_network), lambda node: (node, self.dummy_layer)
1313
+ )
1305
1314
  return self
1306
1315
 
1307
1316
  def sparse_to_px(self, directed=None):
@@ -1317,6 +1326,7 @@ class multi_layer_network:
1317
1326
  self.core_network = nx_from_scipy_sparse_matrix(
1318
1327
  self.core_network, create_using=(nx.DiGraph() if directed else nx.Graph())
1319
1328
  )
1329
+ self.directed = directed
1320
1330
  self.add_dummy_layers()
1321
1331
  self.sparse_enabled = False
1322
1332