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.
- {py3plex-2.0.8/py3plex.egg-info → py3plex-2.0.92}/PKG-INFO +7 -3
- {py3plex-2.0.8 → py3plex-2.0.92}/README.md +4 -2
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/_version.py +1 -1
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/agent.py +1 -1
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/attribute_correlation.py +3 -3
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/centrality/approx_betweenness.py +20 -12
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/centrality/approx_closeness.py +43 -44
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/layer_similarity.py +4 -2
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/centrality.py +1 -1
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/temporal/centrality.py +21 -4
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/benchmarks/runners.py +7 -2
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/centrality/robustness.py +9 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/sidecar.py +3 -1
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/lazy_evaluation.py +20 -2
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/multinet.py +36 -26
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/parsers.py +64 -49
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/temporal_multinet.py +47 -17
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/ast.py +21 -5
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/builder.py +28 -2
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/executor.py +55 -21
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/cache.py +2 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/program.py +8 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/result.py +76 -20
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl_legacy.py +7 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/formats/arrow_format.py +26 -13
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/multinet_bridge.py +61 -79
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/nullmodels/models.py +27 -23
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/optimizer/logical_plan.py +58 -7
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/optimizer/optimizer.py +52 -9
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/optimizer/physical_plan.py +30 -2
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/optimizer/plan_nodes.py +1 -0
- py3plex-2.0.92/py3plex/optimizer/rules.py +1024 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/paths/algorithms.py +5 -1
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/temporal_utils.py +16 -9
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/temporal_view.py +26 -35
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/wrappers/benchmark_nodes.py +5 -2
- {py3plex-2.0.8 → py3plex-2.0.92/py3plex.egg-info}/PKG-INFO +7 -3
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex.egg-info/SOURCES.txt +66 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex.egg-info/requires.txt +6 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex_mcp/__init__.py +1 -1
- {py3plex-2.0.8 → py3plex-2.0.92}/pyproject.toml +2 -0
- py3plex-2.0.92/tests/test_agent_loading_stats.py +63 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_approximate_centrality.py +2 -2
- py3plex-2.0.92/tests/test_approximation_dispatch_regressions.py +65 -0
- py3plex-2.0.92/tests/test_approximation_sample_scope_regressions.py +65 -0
- py3plex-2.0.92/tests/test_arrow_scalar_ids.py +75 -0
- py3plex-2.0.92/tests/test_ast_json_specs_regressions.py +39 -0
- py3plex-2.0.92/tests/test_ast_json_target_regressions.py +41 -0
- py3plex-2.0.92/tests/test_benchmark_runner_modes.py +75 -0
- py3plex-2.0.92/tests/test_benchmark_runner_seeds.py +55 -0
- py3plex-2.0.92/tests/test_betweenness_sampling_scaling_regression.py +69 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_book_conf.py +1 -1
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_book_manuscript_integrity.py +1 -1
- py3plex-2.0.92/tests/test_bridge_edge_attributes.py +140 -0
- py3plex-2.0.92/tests/test_bridge_empty_export.py +57 -0
- py3plex-2.0.92/tests/test_bridge_node_identifiers.py +72 -0
- py3plex-2.0.92/tests/test_bridge_replica_collisions.py +40 -0
- py3plex-2.0.92/tests/test_builder_ast_replay_regressions.py +37 -0
- py3plex-2.0.92/tests/test_cache_method_identity.py +119 -0
- py3plex-2.0.92/tests/test_canonical_ast_isolation_regressions.py +74 -0
- py3plex-2.0.92/tests/test_canonical_projection_order_regressions.py +42 -0
- py3plex-2.0.92/tests/test_canonical_query_settings_regressions.py +85 -0
- py3plex-2.0.92/tests/test_closeness_allocation_regressions.py +67 -0
- py3plex-2.0.92/tests/test_closeness_direction_regressions.py +48 -0
- py3plex-2.0.92/tests/test_closeness_normalization_regressions.py +74 -0
- py3plex-2.0.92/tests/test_closeness_seed_regressions.py +46 -0
- py3plex-2.0.92/tests/test_configuration_directed_degrees.py +104 -0
- py3plex-2.0.92/tests/test_correlation_mixed_identities.py +72 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dependency_cleanup.py +7 -1
- py3plex-2.0.92/tests/test_dependency_cleanup_compat.py +34 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl.py +29 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_community_uq_integration.py +18 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_executor_additional.py +40 -0
- py3plex-2.0.92/tests/test_dsl_optimizer_integration.py +131 -0
- py3plex-2.0.92/tests/test_dsl_optimizer_rewrites.py +264 -0
- py3plex-2.0.92/tests/test_edgelist_reload_regression.py +59 -0
- py3plex-2.0.92/tests/test_erdos_renyi_directed.py +76 -0
- py3plex-2.0.92/tests/test_flow_direction.py +99 -0
- py3plex-2.0.92/tests/test_flow_parallel_capacity.py +109 -0
- py3plex-2.0.92/tests/test_gml_data_preservation.py +45 -0
- py3plex-2.0.92/tests/test_gpickle_directed_conversion.py +37 -0
- py3plex-2.0.92/tests/test_gpickle_layer_data.py +51 -0
- py3plex-2.0.92/tests/test_graphml_loading.py +77 -0
- py3plex-2.0.92/tests/test_layer_shuffle_seed_order.py +100 -0
- py3plex-2.0.92/tests/test_layer_similarity_edge_orientation.py +39 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_link_checker.py +1 -0
- py3plex-2.0.92/tests/test_load_directed_default.py +46 -0
- py3plex-2.0.92/tests/test_matrix_network_weights.py +38 -0
- py3plex-2.0.92/tests/test_mixed_layer_enumeration.py +44 -0
- py3plex-2.0.92/tests/test_multiedgelist_weights_regressions.py +41 -0
- py3plex-2.0.92/tests/test_numeric_cache_mutations.py +91 -0
- py3plex-2.0.92/tests/test_numeric_parallel_weights.py +90 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_optimizer_submodules.py +3 -1
- py3plex-2.0.92/tests/test_parse_nx_direction.py +46 -0
- py3plex-2.0.92/tests/test_result_by_id_conflicts.py +174 -0
- py3plex-2.0.92/tests/test_result_difference_attributes.py +62 -0
- py3plex-2.0.92/tests/test_result_edge_identifier_export.py +66 -0
- py3plex-2.0.92/tests/test_result_networkx_direction.py +107 -0
- py3plex-2.0.92/tests/test_result_networkx_edge_keys.py +73 -0
- py3plex-2.0.92/tests/test_result_networkx_edge_metrics.py +76 -0
- py3plex-2.0.92/tests/test_result_networkx_node_lists.py +69 -0
- py3plex-2.0.92/tests/test_result_symmetric_difference_attributes.py +135 -0
- py3plex-2.0.92/tests/test_result_union_falsy_identifiers.py +93 -0
- py3plex-2.0.92/tests/test_robustness_directed_paths.py +40 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_roundtrip_invariants.py +18 -7
- py3plex-2.0.92/tests/test_scoped_canonical_embedding_regressions.py +33 -0
- py3plex-2.0.92/tests/test_sidecar_empty_tables.py +58 -0
- py3plex-2.0.92/tests/test_sparse_conversion_preserves_data.py +100 -0
- py3plex-2.0.92/tests/test_streaming_degree_normalization.py +65 -0
- py3plex-2.0.92/tests/test_streaming_pagerank_dangling.py +100 -0
- py3plex-2.0.92/tests/test_streaming_pagerank_selfloops.py +68 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal.py +4 -3
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_algorithms.py +68 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_multinet.py +125 -0
- py3plex-2.0.92/tests/test_temporal_numeric_strings.py +36 -0
- py3plex-2.0.92/tests/test_temporal_single_timestamp.py +89 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_utils.py +26 -5
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_view.py +102 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_windowed_queries.py +27 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_version_consistency.py +2 -2
- py3plex-2.0.92/tests/test_weighted_betweenness_identity_regression.py +66 -0
- py3plex-2.0.92/tests/test_weighted_multigraph_sampling_regression.py +70 -0
- py3plex-2.0.92/tests/test_wrappers_optional_gensim.py +48 -0
- py3plex-2.0.92/tests/test_wrappers_topk_zero.py +23 -0
- py3plex-2.0.8/py3plex/optimizer/rules.py +0 -536
- {py3plex-2.0.8 → py3plex-2.0.92}/LICENSE +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/MANIFEST.in +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/__main__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/_parallel.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/_safe_expression.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/backend.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/closure.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/fixed_point.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/lift.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/paths.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/semiring.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algebra/witness.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/advanced_random_generators.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/centrality/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/centrality/approx_pagerank.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/centrality/explain.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/centrality_toolkit.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_comparison.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/NoRC.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/auto_select.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/autocommunity.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/autocommunity_executor.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/budget.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/community_louvain.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/community_measures.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/community_ranking.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/community_wrapper.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/distributional.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/flow_hierarchy.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/conftest.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-bipartite.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-file-io.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-multiplex.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-networkx.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-simple.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-trigram-expanded.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/examples/python/example-trigram.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/infomap.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/infomap/interfaces/python/setup.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/label_propagation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/leiden_multilayer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/leiden_uq.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/mdl_benchmark.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/multilayer_benchmark.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/multilayer_modularity.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/multilayer_quality_metrics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/node_ranking.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/runner.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/sbm_metrics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/sbm_wrapper.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/spectral_multilayer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/community_detection/successive_halving.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/curvature/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/curvature/ollivier_ricci_multilayer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/general/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/general/benchmark_classification.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/general/walkers.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/graph_summarization.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/__main__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/assets/builtin.n3 +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/converters.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/example.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/helpers.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/kb.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/load.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/predicate.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/rule.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/settings.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/core/term_parsers.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/learners/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/learners/bottomup.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/learners/learner.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/learners/optimal.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/adjustment.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/scorefunctions.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/significance.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/hedwig/stats/validate.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/meta_flow_report.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multicentrality.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/entanglement.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/multirank.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/multixrank.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/supra_matrix_function_centrality.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_algorithms/versatility.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/multilayer_clustering.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/network_classification/PPR.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/network_classification/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/network_classification/label_propagation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/node_ranking/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/node_ranking/node_ranking.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/requirements_registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/robustness_testing.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/routing/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/routing/multiplex_paths.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/conversions.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/diagnostics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/inference_vi.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/model_selection.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/multilayer_sbm.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/objectives.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/uq.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sbm/utils.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/sir_multiplex.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistical_report.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/basic_statistics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/bayesian_distances.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/bayesiantests.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/correlation_networks.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/critical_distances.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/enrichment_modules.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/multilayer_statistics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/powerlaw.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/stats_comparison.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/statistics/topology.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/temporal/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/temporal/community.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/temporal_multiplex/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/algorithms/term_parsers/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/alignment/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/alignment/features.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/alignment/metrics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/alignment/solvers.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/benchmarks/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/benchmarks/budget.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/benchmarks/metrics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/centrality/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/claims/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/claims/generator.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/claims/learner.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/claims/scorer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/claims/types.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/cli.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/comparison/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/comparison/executor.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/comparison/metrics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/comparison/result.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/convert.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/converters/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/converters/dgl_converter.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/converters/igraph_converter.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/converters/networkx_converter.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/converters/pyg_converter.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/converters/scipy_converter.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/equality.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/exceptions.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/ir.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/compat/schema.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/config.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/contracts/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/contracts/contract.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/contracts/engine.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/contracts/failure_modes.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/contracts/predicates.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/contracts/result.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/HINMINE/IO.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/HINMINE/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/HINMINE/dataStructures.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/HINMINE/decomposition.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/converters.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/immutable.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/nx_compat.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/random_generators.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/schema_validation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/supporting.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/core/types.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterexamples/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterexamples/claim_lang.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterexamples/ddmin.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterexamples/engine.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterexamples/types.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterexamples/witness.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterfactual/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterfactual/comparator.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterfactual/engine.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterfactual/presets.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterfactual/result.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/counterfactual/spec.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/datasets/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/datasets/_data/aarhus_cs.edges +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/datasets/_data/synthetic_multilayer.edges +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/datasets/_generators.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/datasets/_loaders.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/diagnostics/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/diagnostics/builders.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/diagnostics/codes.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/diagnostics/core.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/diagnostics/utils.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/algebra.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/attribution.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/benchmark.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/benchmark_result.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/builder_parser.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/cache.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/communities.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/community_uq.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/compositional_uq.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/context.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/errors.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/executor_semiring.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/executors/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/executors/benchmark_executor.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/explain.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/export.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/expressions.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/fastpath.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/layers.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/diagnostic.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/lint_context.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/base.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl001_unknown_layer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl002_unknown_attribute.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl101_type_mismatch.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl201_unsatisfiable.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/dsl202_redundant.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/perf301_full_scan.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/rules/perf302_cross_layer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/schema.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/type_resolver.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/lint/types.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/metrics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/operator_registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/operators.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/patterns/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/patterns/builder.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/patterns/compiler.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/patterns/engine.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/patterns/ir.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/patterns/result.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/plan.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/planner.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/predictive.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/cost.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/diff.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/distribution.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/executor.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/explain.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/rewrite.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/program/types.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/provenance.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/reduction.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/selection_uq.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/serializer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/uq_algebra.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/uq_resolution.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dsl/warnings.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/_utils.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/ast.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/builder.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/compartmental.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/config.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/core.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/errors.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/executor.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/models.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/processes.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/result.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/dynamics/serializer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/embeddings/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/embeddings/base.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/embeddings/cache.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/embeddings/link_ops.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/embeddings/metapath2vec.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/embeddings/netmf.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ergonomics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/errors.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/exceptions.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/artifacts.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/cli.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/env.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/errors.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/model.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/runner.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/store.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/experiments/utils.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/fast_examples.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/graph_ops.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/api.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/canonical_format.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/converters.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/exceptions.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/formats/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/formats/csv_format.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/formats/json_format.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/parquet_format.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/io/schema.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/lab/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/lab/base.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/linter.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/logging_config.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/meta/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/meta/builder.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/meta/result.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/meta/stats.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/meta/utils.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/base.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/deepwalk.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/evaluation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/line.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/metapath2vec.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/multiplex.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/netmf.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/node2vec.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/similarity.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/trainer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/ml/embedding/utils.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/multinet/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/multinet/aggregation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/nullmodels/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/nullmodels/executor.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/nullmodels/result.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/optimizer/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/optimizer/cost_model.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/cli.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/errors.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/executor.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/network.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/operators.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/readers.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/schema.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/spill.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/out_of_core/utils.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/paths/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/paths/executor.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/paths/result.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/pipeline.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/plugins/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/plugins/base.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/plugins/examples.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/plugins/registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/profiling.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/provenance/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/provenance/bundle.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/provenance/capture.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/provenance/replay.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/provenance/schema.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/requirements.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/robustness/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/robustness/experiments.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/robustness/perturbations.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/runtime/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/runtime/capabilities.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/safe_dsl_expression.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/selection/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/selection/capabilities.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/selection/community_registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/selection/evaluate.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/selection/metric_registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/selection/result.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/selection/wins.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/semiring/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/semiring/core.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/semiring/engine.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/semiring/pareto.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/semiring/registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/semiring/types.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/sensitivity/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/sensitivity/executor.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/sensitivity/metrics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/sensitivity/perturbations.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/sensitivity/types.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/stats/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/stats/provenance.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/stats/registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/stats/statvalue.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/stats/uncertainty.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/temporal_utils_extended.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/bootstrap.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/ci_utils.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/community_ensemble.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/community_result.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/context.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/estimation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/noise_models.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/null_models.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/partition.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/partition_metrics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/partition_reducers.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/partition_types.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/partition_uq.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/plan.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/reducers/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/reducers/base.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/resampling_graph.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/runner.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/selection_execution.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/selection_reducers.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/selection_types.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/selection_uq.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/stratification.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/uncertainty/types.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/utils.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/validation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/benchmark_visualizations.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/bezier.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/colors.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/drawing_machinery.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/embedding_visualization/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/embedding_visualization/embedding_tools.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/embedding_visualization/embedding_visualization.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/fa2/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/fa2/fa2util.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/fa2/forceatlas2.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/layout_algorithms.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/multilayer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/polyfit.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/pymnet_style.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/ricci_layout.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/ricci_multilayer_vis.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/visualization/sankey.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/workflows.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/wrappers/__init__.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/wrappers/r_interop.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex/wrappers/train_node2vec_embedding.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex.egg-info/dependency_links.txt +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex.egg-info/entry_points.txt +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex.egg-info/not-zip-safe +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex.egg-info/top_level.txt +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex_mcp/errors.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex_mcp/registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex_mcp/safe_paths.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex_mcp/schemas.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/py3plex_mcp/server.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/setup.cfg +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_advanced_metrics_properties.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_agent_api.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_agents_documentation_claims.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_agents_ergonomics_features.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_agents_golden_paths.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_aggregation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algebra_backend.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algebra_core.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algebra_fixed_point.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algebra_paths.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algebra_registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algebra_witness.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algorithm_properties.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algorithms_attribute_correlation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algorithms_correlation_networks.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algorithms_init.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algorithms_random_generators.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algorithms_requirements_registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_algorithms_statistics_bayesian_distances.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_alignment.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_alignment_contracts.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_alignment_correctness_additional.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ast_roundtrip.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ast_roundtrip_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_attribute_correlation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_attribute_correlation_contracts.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_auto_community.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_autocommunity_benchmarks.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_autocommunity_executor.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_autocommunity_meta.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_autocommunity_successive_halving.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_bayesian_distances.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_bench_aggregation_unit.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_benchmark_budget_fairness.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_benchmark_dsl_basic.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_benchmark_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_benchmark_multiplex_centrality.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_benchmark_time.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_benchmarks_budget.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_benchmarks_init.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_book_snippets.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_builder_dsl_mutate.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_capabilities_basic.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_capabilities_optional_missing.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_centrality_explain.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_centrality_explain_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_centrality_robustness.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_centrality_robustness_oracles.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_centrality_uncertainty.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_centrality_weight_handling.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_check_api_consistency.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_check_doc_coverage.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_check_type_coverage.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ci_python_versions.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_claim_learning.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_claims_types.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_cli.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_cli_check.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_cli_ergonomics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_cli_piping.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_clustering_multilayer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_code_improvements.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_community_comparison_coverage.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_community_detection_modules.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_community_distribution.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_community_measures.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_community_measures_coverage.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_comparison.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_comparison_executor.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_comparison_metrics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_comparison_metrics_additional.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_comparison_result.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_comparison_uninitialized_and_resistance_oracles.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_compat_exceptions.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_compat_roundtrip.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_config_api.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_config_benchmark.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_contracts.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_contracts_basic.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_contracts_extended.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_contracts_failure_modes.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_contracts_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_functionality.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_immutable.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_lazy_evaluation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_multinet_and_parsers.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_multinet_correctness.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_multiplex_edges.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_schema_validation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_core_supporting.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_correlation_networks.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_counterexamples.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_counterexamples_properties.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_counterfactual.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_counterfactual_presets.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_coverage_grouping.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_create_mosaic_banner.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_create_showcase_flow.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_crosshair_pure_functions.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_data_files_presence.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_datasets.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_datasets_contracts.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_datasets_oracles.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_degenerate_networks.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_determinism_randomness.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_diagnostics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_diagnostics_utils.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_doc_conf.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_docs_embeddings_section.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_docs_examples.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_docs_quality_pass.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_doctests.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dplyr_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_aggregation_enhancements.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_ast_equivalence.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_ast_immutability.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_auto_community.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_communities.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_community_filtering.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_compact_compute.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_compiler_explain.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_compiler_pipeline.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_compositional_uq.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_condition_semantics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_d_factory.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_documentation_examples.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_dplyr_style.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_dynamics_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_edge_grouping_coverage.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_edge_queries.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_enhancements.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_ergonomics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_errors.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_errors_extended.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_explain.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_export.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_expressions.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_extensions.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_graphops_equivalence.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_grouping_coverage.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_interactive.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_joins.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_layer_resolution.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_layer_selection.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_layer_set_algebra.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_legacy_approximate.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_legacy_edges.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_lint.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_metric_registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_multilayer_measure_topology.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_operators.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_patterns.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_patterns_correctness.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_patterns_quick_reference.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_pipes.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_planner.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_planner_config.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_predict_reduce.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_program_rewrite.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_program_types.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_progress_logging.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_properties.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_provenance.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_query_optimization.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_query_zoo.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_result_algebra_edge_cases.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_selection_fastpath.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_semiring_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_serializer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_smart_defaults.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_temporal_range_execution.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_uncertainty.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_uq_ergonomics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_uq_propagation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_v2.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dsl_zoo_features.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_algorithm_contracts.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_config_and_results_correctness.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_conservation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_core.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_executor_edge_cases.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_metamorphic.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_parallel_determinism.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_reference_runs.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_uq_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_dynamics_utils.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_edge_cases.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_edgelist_format.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_embeddings_direct_units.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ergonomic_helpers.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ergonomics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ergonomics_helpers.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_errors.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_errors_coverage.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_CBSSD.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_community_detection.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_decomposition_and_classification.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_decomposition_ground_truth.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_dsl_builder_api.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_dynamics_core_examples.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_embedding_construction.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_embedding_visualization.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_incidence_gadget_encoding.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_interactive_multilayer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_inverse_network.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_layer_extraction.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_manipulation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_multilayer_vectorized_aggregation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_multiplex_aggregate.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_multiplex_dynamics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_n2v_embedding.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_network_decomposition.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_network_decomposition_meta_paths.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_numeric_encoding.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_pattern_matching.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_example_ppr.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_examples_zoo_consolidation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_exception_taxonomy.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_exceptions.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_experiments.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_explain_attribution.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_fast_examples.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_flagship_progress_demo.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_flow_hierarchy.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_formal_phase1_alignment.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_fuzzing_properties.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_generate_all_outputs.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_generate_quickstart_outputs.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_generate_visualization_images.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_golden_toy_examples.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_graph_ops.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_graph_summarization.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_hedwig_adjustment.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_hedwig_significance.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_improved_errors.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_incidence_gadget_encoding.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_infomap_fix.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_interlayer_links_fix.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_api_edge_cases.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_arrow.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_contracts_additional.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_conversion_formats.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_converters.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_exceptions.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_roundtrip.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_io_schema.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_issue_19_fix.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_lab.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_lab_additional.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_lab_correctness.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_label_propagation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_layer_extraction_fix.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_layer_similarity.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_layout_algorithms.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_lazy_evaluation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_leiden_multilayer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_linter.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_logging_config_unit.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_logging_conversion.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_main_module.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_master_regulators_example.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_math_invariants.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_mcp_server.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_mdl_benchmark.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_mdl_score.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_mdl_score_corruption_monotonicity.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_mdl_score_reference_differential.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_mdl_score_resolution_limit_sweep.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_meta_analysis.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_meta_flow_report.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_meta_utils.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_metamorphic.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_metapath2vec.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ml_embedding_evaluation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ml_embedding_primitives.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_monoplex_nx_wrapper.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_mpc.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_centrality.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_clustering_coefficients.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_cornercases.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_edge_fix.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_embedding_models.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_leiden_uq.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_modularity.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_quality_metrics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_quality_metrics_coverage.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_statistics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multilayer_visualizations.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multinet_aggregation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multinet_aggregation_additional.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multiplex_layer_interop.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multiplex_participation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multiplex_properties.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multirank.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_multixrank.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_network_conversion.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_network_version.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_networkx_compatibility.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_new_algorithms.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_new_multilayer_metrics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_node_edge_parity.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_node_ranking_comprehensive.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_norc.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_nullmodel_sanity.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_nullmodels.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_nullmodels_contracts.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_nx_compat_extended.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ollivier_ricci_multilayer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_out_of_core.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_parallel.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_parallel_execution.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_parsers_comprehensive.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_parsers_coverage.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_partition_uq.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_partition_uq_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_paths.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_paths_additional.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_paths_contracts.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_paths_executor.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_paths_result.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_performance_core.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_pipeline.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_plugin_examples.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_plugin_system.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_plugins.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_plugins_contracts.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_profiling.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_profiling_additional.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_program.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_program_cache_identity.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_program_cost_executor.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_properties.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_provenance_canonical.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_provenance_replay.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_provenance_schema.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_public_api_exports.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_pymnet_style.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_pypi_publish_workflow.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_query_algebra.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_query_equivalence.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_r_interop.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_random_generators_additional.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_random_generators_extended.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_random_walkers.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_random_walks.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_readme_contributor_onboarding.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_readme_flagship_example.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_requirements.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_result_explain_debug.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_ricci_visualization.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_robustness.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_robustness_additional.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_robustness_testing.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_root_conftest.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_run_quickstart_snippets.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_safe_expression.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sankey_visualization.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sbm_autocommunity.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sbm_generator.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sbm_metrics.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sbm_runner_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_schema_and_immutable.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_seeding.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_selection_uq.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_selection_uq_empty_groups.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_selection_uq_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_semiring_negative_cases.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_semiring_pareto.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_semiring_registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_semiring_types.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_semiring_verification.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sensitivity_executor.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sidecar.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sir_epidemic.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sir_long_convergence.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_sir_multiplex.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_spectral_multilayer.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_statistical_report.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_comparison.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_core.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_edge_cases.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_provenance.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_provenance_dataclass.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_registry.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_scalar_uncertainty.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stats_verify.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_stratified_uq.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_streaming_topk.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_successive_halving.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_supporting_extended.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_supra_matrix_function_centrality.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_builder.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_dsl.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_duration_parsing.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_temporal_utils_extended.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_tensor_representation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_tutorial_10min.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_type_coverage_scan.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty_additional.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty_builder_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty_defaults.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty_dsl_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty_engines.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty_oracles.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uncertainty_runner.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uq_algebra.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uq_integration.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uq_resolution.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_uq_spine.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_user_journey_simulation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_utils.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_utils_coverage.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_utils_extended.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_utils_search_paths.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_validation.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_validation_module.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_verification_api_differential.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_verification_centrality.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_verification_communities.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_verification_determinism_parallelism.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_verification_dsl_equivalence.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_verification_metamorphic_harness.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_verification_provenance_oracles.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_versatility.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_benchmark.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_bezier.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_colors.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_imports.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_layouts.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_multilayer_additional.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_polyfit.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_ricci_layout_helpers.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualization_supra_heatmap.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_visualize_matrix_fix.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_workflows.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_wrappers_additional.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_wrappers_benchmark_nodes.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_wrappers_node2vec.py +0 -0
- {py3plex-2.0.8 → py3plex-2.0.92}/tests/test_wrappers_r_interop.py +0 -0
- {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.
|
|
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
|
[](https://pypistats.org/packages/py3plex)
|
|
121
123
|

|
|
122
124
|

|
|
123
|
-

|
|
126
|
+

|
|
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
|
[](https://pypistats.org/packages/py3plex)
|
|
17
17
|

|
|
18
18
|

|
|
19
|
-

|
|
20
|
+

|
|
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:
|
|
@@ -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 =
|
|
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 =
|
|
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
|
|
207
|
-
vals2 = np.array([layer_attrs[l2][node] for node in
|
|
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
|
-
#
|
|
89
|
-
|
|
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
|
-
#
|
|
99
|
-
|
|
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
|
-
#
|
|
208
|
-
#
|
|
209
|
-
scale =
|
|
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
|
-
#
|
|
221
|
-
|
|
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:
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
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 =
|
|
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
|
-
#
|
|
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
|
|
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
|
|
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
|
|
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
|
-
#
|
|
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
|
-
|
|
205
|
-
|
|
206
|
+
other_landmarks = sum(landmark != v for landmark in landmarks)
|
|
207
|
+
reachable_frac = len(dists) / float(other_landmarks)
|
|
206
208
|
else:
|
|
207
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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] = (
|
|
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
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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(
|
|
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
|
-
#
|
|
131
|
-
|
|
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
|
-
|
|
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:
|
|
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 =
|
|
843
|
-
|
|
844
|
-
|
|
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:
|
|
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 =
|
|
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
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
self.
|
|
1293
|
-
|
|
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
|
|