crca 1.4.0__py3-none-any.whl → 1.5.0__py3-none-any.whl
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.
- CRCA.py +172 -7
- MODEL_CARD.md +53 -0
- PKG-INFO +8 -2
- RELEASE_NOTES.md +17 -0
- STABILITY.md +19 -0
- architecture/hybrid/consistency_engine.py +362 -0
- architecture/hybrid/conversation_manager.py +421 -0
- architecture/hybrid/explanation_generator.py +452 -0
- architecture/hybrid/few_shot_learner.py +533 -0
- architecture/hybrid/graph_compressor.py +286 -0
- architecture/hybrid/hybrid_agent.py +4398 -0
- architecture/hybrid/language_compiler.py +623 -0
- architecture/hybrid/main,py +0 -0
- architecture/hybrid/reasoning_tracker.py +322 -0
- architecture/hybrid/self_verifier.py +524 -0
- architecture/hybrid/task_decomposer.py +567 -0
- architecture/hybrid/text_corrector.py +341 -0
- benchmark_results/crca_core_benchmarks.json +178 -0
- branches/crca_sd/crca_sd_realtime.py +6 -2
- branches/general_agent/__init__.py +102 -0
- branches/general_agent/general_agent.py +1400 -0
- branches/general_agent/personality.py +169 -0
- branches/general_agent/utils/__init__.py +19 -0
- branches/general_agent/utils/prompt_builder.py +170 -0
- {crca-1.4.0.dist-info → crca-1.5.0.dist-info}/METADATA +8 -2
- {crca-1.4.0.dist-info → crca-1.5.0.dist-info}/RECORD +303 -20
- crca_core/__init__.py +35 -0
- crca_core/benchmarks/__init__.py +14 -0
- crca_core/benchmarks/synthetic_scm.py +103 -0
- crca_core/core/__init__.py +23 -0
- crca_core/core/api.py +120 -0
- crca_core/core/estimate.py +208 -0
- crca_core/core/godclass.py +72 -0
- crca_core/core/intervention_design.py +174 -0
- crca_core/core/lifecycle.py +48 -0
- crca_core/discovery/__init__.py +9 -0
- crca_core/discovery/tabular.py +193 -0
- crca_core/identify/__init__.py +171 -0
- crca_core/identify/backdoor.py +39 -0
- crca_core/identify/frontdoor.py +48 -0
- crca_core/identify/graph.py +106 -0
- crca_core/identify/id_algorithm.py +43 -0
- crca_core/identify/iv.py +48 -0
- crca_core/models/__init__.py +67 -0
- crca_core/models/provenance.py +56 -0
- crca_core/models/refusal.py +39 -0
- crca_core/models/result.py +83 -0
- crca_core/models/spec.py +151 -0
- crca_core/models/validation.py +68 -0
- crca_core/scm/__init__.py +9 -0
- crca_core/scm/linear_gaussian.py +198 -0
- crca_core/timeseries/__init__.py +6 -0
- crca_core/timeseries/pcmci.py +181 -0
- crca_llm/__init__.py +12 -0
- crca_llm/client.py +85 -0
- crca_llm/coauthor.py +118 -0
- crca_llm/orchestrator.py +289 -0
- crca_llm/types.py +21 -0
- crca_reasoning/__init__.py +16 -0
- crca_reasoning/critique.py +54 -0
- crca_reasoning/godclass.py +206 -0
- crca_reasoning/memory.py +24 -0
- crca_reasoning/rationale.py +10 -0
- crca_reasoning/react_controller.py +81 -0
- crca_reasoning/tool_router.py +97 -0
- crca_reasoning/types.py +40 -0
- crca_sd/__init__.py +15 -0
- crca_sd/crca_sd_core.py +2 -0
- crca_sd/crca_sd_governance.py +2 -0
- crca_sd/crca_sd_mpc.py +2 -0
- crca_sd/crca_sd_realtime.py +2 -0
- crca_sd/crca_sd_tui.py +2 -0
- cuda-keyring_1.1-1_all.deb +0 -0
- cuda-keyring_1.1-1_all.deb.1 +0 -0
- docs/IMAGE_ANNOTATION_USAGE.md +539 -0
- docs/INSTALL_DEEPSPEED.md +125 -0
- docs/api/branches/crca-cg.md +19 -0
- docs/api/branches/crca-q.md +27 -0
- docs/api/branches/crca-sd.md +37 -0
- docs/api/branches/general-agent.md +24 -0
- docs/api/branches/overview.md +19 -0
- docs/api/crca/agent-methods.md +62 -0
- docs/api/crca/operations.md +79 -0
- docs/api/crca/overview.md +32 -0
- docs/api/image-annotation/engine.md +52 -0
- docs/api/image-annotation/overview.md +17 -0
- docs/api/schemas/annotation.md +34 -0
- docs/api/schemas/core-schemas.md +82 -0
- docs/api/schemas/overview.md +32 -0
- docs/api/schemas/policy.md +30 -0
- docs/api/utils/conversation.md +22 -0
- docs/api/utils/graph-reasoner.md +32 -0
- docs/api/utils/overview.md +21 -0
- docs/api/utils/router.md +19 -0
- docs/api/utils/utilities.md +97 -0
- docs/architecture/causal-graphs.md +41 -0
- docs/architecture/data-flow.md +29 -0
- docs/architecture/design-principles.md +33 -0
- docs/architecture/hybrid-agent/components.md +38 -0
- docs/architecture/hybrid-agent/consistency.md +26 -0
- docs/architecture/hybrid-agent/overview.md +44 -0
- docs/architecture/hybrid-agent/reasoning.md +22 -0
- docs/architecture/llm-integration.md +26 -0
- docs/architecture/modular-structure.md +37 -0
- docs/architecture/overview.md +69 -0
- docs/architecture/policy-engine-arch.md +29 -0
- docs/branches/crca-cg/corposwarm.md +39 -0
- docs/branches/crca-cg/esg-scoring.md +30 -0
- docs/branches/crca-cg/multi-agent.md +35 -0
- docs/branches/crca-cg/overview.md +40 -0
- docs/branches/crca-q/alternative-data.md +55 -0
- docs/branches/crca-q/architecture.md +71 -0
- docs/branches/crca-q/backtesting.md +45 -0
- docs/branches/crca-q/causal-engine.md +33 -0
- docs/branches/crca-q/execution.md +39 -0
- docs/branches/crca-q/market-data.md +60 -0
- docs/branches/crca-q/overview.md +58 -0
- docs/branches/crca-q/philosophy.md +60 -0
- docs/branches/crca-q/portfolio-optimization.md +66 -0
- docs/branches/crca-q/risk-management.md +102 -0
- docs/branches/crca-q/setup.md +65 -0
- docs/branches/crca-q/signal-generation.md +61 -0
- docs/branches/crca-q/signal-validation.md +43 -0
- docs/branches/crca-sd/core.md +84 -0
- docs/branches/crca-sd/governance.md +53 -0
- docs/branches/crca-sd/mpc-solver.md +65 -0
- docs/branches/crca-sd/overview.md +59 -0
- docs/branches/crca-sd/realtime.md +28 -0
- docs/branches/crca-sd/tui.md +20 -0
- docs/branches/general-agent/overview.md +37 -0
- docs/branches/general-agent/personality.md +36 -0
- docs/branches/general-agent/prompt-builder.md +30 -0
- docs/changelog/index.md +79 -0
- docs/contributing/code-style.md +69 -0
- docs/contributing/documentation.md +43 -0
- docs/contributing/overview.md +29 -0
- docs/contributing/testing.md +29 -0
- docs/core/crcagent/async-operations.md +65 -0
- docs/core/crcagent/automatic-extraction.md +107 -0
- docs/core/crcagent/batch-prediction.md +80 -0
- docs/core/crcagent/bayesian-inference.md +60 -0
- docs/core/crcagent/causal-graph.md +92 -0
- docs/core/crcagent/counterfactuals.md +96 -0
- docs/core/crcagent/deterministic-simulation.md +78 -0
- docs/core/crcagent/dual-mode-operation.md +82 -0
- docs/core/crcagent/initialization.md +88 -0
- docs/core/crcagent/optimization.md +65 -0
- docs/core/crcagent/overview.md +63 -0
- docs/core/crcagent/time-series.md +57 -0
- docs/core/schemas/annotation.md +30 -0
- docs/core/schemas/core-schemas.md +82 -0
- docs/core/schemas/overview.md +30 -0
- docs/core/schemas/policy.md +41 -0
- docs/core/templates/base-agent.md +31 -0
- docs/core/templates/feature-mixins.md +31 -0
- docs/core/templates/overview.md +29 -0
- docs/core/templates/templates-guide.md +75 -0
- docs/core/tools/mcp-client.md +34 -0
- docs/core/tools/overview.md +24 -0
- docs/core/utils/conversation.md +27 -0
- docs/core/utils/graph-reasoner.md +29 -0
- docs/core/utils/overview.md +27 -0
- docs/core/utils/router.md +27 -0
- docs/core/utils/utilities.md +97 -0
- docs/css/custom.css +84 -0
- docs/examples/basic-usage.md +57 -0
- docs/examples/general-agent/general-agent-examples.md +50 -0
- docs/examples/hybrid-agent/hybrid-agent-examples.md +56 -0
- docs/examples/image-annotation/image-annotation-examples.md +54 -0
- docs/examples/integration/integration-examples.md +58 -0
- docs/examples/overview.md +37 -0
- docs/examples/trading/trading-examples.md +46 -0
- docs/features/causal-reasoning/advanced-topics.md +101 -0
- docs/features/causal-reasoning/counterfactuals.md +43 -0
- docs/features/causal-reasoning/do-calculus.md +50 -0
- docs/features/causal-reasoning/overview.md +47 -0
- docs/features/causal-reasoning/structural-models.md +52 -0
- docs/features/hybrid-agent/advanced-components.md +55 -0
- docs/features/hybrid-agent/core-components.md +64 -0
- docs/features/hybrid-agent/overview.md +34 -0
- docs/features/image-annotation/engine.md +82 -0
- docs/features/image-annotation/features.md +113 -0
- docs/features/image-annotation/integration.md +75 -0
- docs/features/image-annotation/overview.md +53 -0
- docs/features/image-annotation/quickstart.md +73 -0
- docs/features/policy-engine/doctrine-ledger.md +105 -0
- docs/features/policy-engine/monitoring.md +44 -0
- docs/features/policy-engine/mpc-control.md +89 -0
- docs/features/policy-engine/overview.md +46 -0
- docs/getting-started/configuration.md +225 -0
- docs/getting-started/first-agent.md +164 -0
- docs/getting-started/installation.md +144 -0
- docs/getting-started/quickstart.md +137 -0
- docs/index.md +118 -0
- docs/js/mathjax.js +13 -0
- docs/lrm/discovery_proof_notes.md +25 -0
- docs/lrm/finetune_full.md +83 -0
- docs/lrm/math_appendix.md +120 -0
- docs/lrm/overview.md +32 -0
- docs/mkdocs.yml +238 -0
- docs/stylesheets/extra.css +21 -0
- docs_generated/crca_core/CounterfactualResult.md +12 -0
- docs_generated/crca_core/DiscoveryHypothesisResult.md +13 -0
- docs_generated/crca_core/DraftSpec.md +13 -0
- docs_generated/crca_core/EstimateResult.md +13 -0
- docs_generated/crca_core/IdentificationResult.md +17 -0
- docs_generated/crca_core/InterventionDesignResult.md +12 -0
- docs_generated/crca_core/LockedSpec.md +15 -0
- docs_generated/crca_core/RefusalResult.md +12 -0
- docs_generated/crca_core/ValidationReport.md +9 -0
- docs_generated/crca_core/index.md +13 -0
- examples/general_agent_example.py +277 -0
- examples/general_agent_quickstart.py +202 -0
- examples/general_agent_simple.py +92 -0
- examples/hybrid_agent_auto_extraction.py +84 -0
- examples/hybrid_agent_dictionary_demo.py +104 -0
- examples/hybrid_agent_enhanced.py +179 -0
- examples/hybrid_agent_general_knowledge.py +107 -0
- examples/image_annotation_quickstart.py +328 -0
- examples/test_hybrid_fixes.py +77 -0
- image_annotation/__init__.py +27 -0
- image_annotation/annotation_engine.py +2593 -0
- install_cuda_wsl2.sh +59 -0
- install_deepspeed.sh +56 -0
- install_deepspeed_simple.sh +87 -0
- mkdocs.yml +252 -0
- ollama/Modelfile +8 -0
- prompts/__init__.py +2 -1
- prompts/default_crca.py +9 -1
- prompts/general_agent.py +227 -0
- prompts/image_annotation.py +56 -0
- pyproject.toml +17 -2
- requirements-docs.txt +10 -0
- requirements.txt +21 -2
- schemas/__init__.py +26 -1
- schemas/annotation.py +222 -0
- schemas/conversation.py +193 -0
- schemas/hybrid.py +211 -0
- schemas/reasoning.py +276 -0
- schemas_export/crca_core/CounterfactualResult.schema.json +108 -0
- schemas_export/crca_core/DiscoveryHypothesisResult.schema.json +113 -0
- schemas_export/crca_core/DraftSpec.schema.json +635 -0
- schemas_export/crca_core/EstimateResult.schema.json +113 -0
- schemas_export/crca_core/IdentificationResult.schema.json +145 -0
- schemas_export/crca_core/InterventionDesignResult.schema.json +111 -0
- schemas_export/crca_core/LockedSpec.schema.json +646 -0
- schemas_export/crca_core/RefusalResult.schema.json +90 -0
- schemas_export/crca_core/ValidationReport.schema.json +62 -0
- scripts/build_lrm_dataset.py +80 -0
- scripts/export_crca_core_schemas.py +54 -0
- scripts/export_hf_lrm.py +37 -0
- scripts/export_ollama_gguf.py +45 -0
- scripts/generate_changelog.py +157 -0
- scripts/generate_crca_core_docs_from_schemas.py +86 -0
- scripts/run_crca_core_benchmarks.py +163 -0
- scripts/run_full_finetune.py +198 -0
- scripts/run_lrm_eval.py +31 -0
- templates/graph_management.py +29 -0
- tests/conftest.py +9 -0
- tests/test_core.py +2 -3
- tests/test_crca_core_discovery_tabular.py +15 -0
- tests/test_crca_core_estimate_dowhy.py +36 -0
- tests/test_crca_core_identify.py +18 -0
- tests/test_crca_core_intervention_design.py +36 -0
- tests/test_crca_core_linear_gaussian_scm.py +69 -0
- tests/test_crca_core_spec.py +25 -0
- tests/test_crca_core_timeseries_pcmci.py +15 -0
- tests/test_crca_llm_coauthor.py +12 -0
- tests/test_crca_llm_orchestrator.py +80 -0
- tests/test_hybrid_agent_llm_enhanced.py +556 -0
- tests/test_image_annotation_demo.py +376 -0
- tests/test_image_annotation_operational.py +408 -0
- tests/test_image_annotation_unit.py +551 -0
- tests/test_training_moe.py +13 -0
- training/__init__.py +42 -0
- training/datasets.py +140 -0
- training/deepspeed_zero2_0_5b.json +22 -0
- training/deepspeed_zero2_1_5b.json +22 -0
- training/deepspeed_zero3_0_5b.json +28 -0
- training/deepspeed_zero3_14b.json +28 -0
- training/deepspeed_zero3_h100_3gpu.json +20 -0
- training/deepspeed_zero3_offload.json +28 -0
- training/eval.py +92 -0
- training/finetune.py +516 -0
- training/public_datasets.py +89 -0
- training_data/react_train.jsonl +7473 -0
- utils/agent_discovery.py +311 -0
- utils/batch_processor.py +317 -0
- utils/conversation.py +78 -0
- utils/edit_distance.py +118 -0
- utils/formatter.py +33 -0
- utils/graph_reasoner.py +530 -0
- utils/rate_limiter.py +283 -0
- utils/router.py +2 -2
- utils/tool_discovery.py +307 -0
- webui/__init__.py +10 -0
- webui/app.py +229 -0
- webui/config.py +104 -0
- webui/static/css/style.css +332 -0
- webui/static/js/main.js +284 -0
- webui/templates/index.html +42 -0
- tests/test_crca_excel.py +0 -166
- tests/test_data_broker.py +0 -424
- tests/test_palantir.py +0 -349
- {crca-1.4.0.dist-info → crca-1.5.0.dist-info}/WHEEL +0 -0
- {crca-1.4.0.dist-info → crca-1.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Graph compression and abstraction module.
|
|
3
|
+
|
|
4
|
+
Provides functionality for creating composite nodes, latent factors,
|
|
5
|
+
and graph simplification through abstraction.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Dict, List, Optional, Set, Any
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
from templates.graph_management import GraphManager
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class GraphCompressor:
|
|
17
|
+
"""
|
|
18
|
+
Compresses and abstracts causal graphs through composite nodes and latent factors.
|
|
19
|
+
|
|
20
|
+
Features:
|
|
21
|
+
- Composite node creation (multiple variables → single node)
|
|
22
|
+
- Latent factor abstraction
|
|
23
|
+
- Graph simplification (remove low-confidence edges, merge redundant paths)
|
|
24
|
+
- Hierarchical structure creation
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, graph_manager: GraphManager):
|
|
28
|
+
"""
|
|
29
|
+
Initialize graph compressor.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
graph_manager: GraphManager instance to compress
|
|
33
|
+
"""
|
|
34
|
+
self.graph_manager = graph_manager
|
|
35
|
+
self.composite_nodes: Dict[str, List[str]] = {} # composite_name -> [original_nodes]
|
|
36
|
+
self.latent_factors: Dict[str, List[str]] = {} # latent_name -> [observed_nodes]
|
|
37
|
+
|
|
38
|
+
def create_composite_node(
|
|
39
|
+
self,
|
|
40
|
+
variables: List[str],
|
|
41
|
+
name: str,
|
|
42
|
+
preserve_originals: bool = True
|
|
43
|
+
) -> str:
|
|
44
|
+
"""
|
|
45
|
+
Create a composite node from multiple variables.
|
|
46
|
+
|
|
47
|
+
Example: "product quality" + "service quality" → "quality_factor"
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
variables: List of variable names to combine
|
|
51
|
+
name: Name for the composite node
|
|
52
|
+
preserve_originals: Whether to keep original nodes in graph
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
Name of the created composite node
|
|
56
|
+
"""
|
|
57
|
+
# Validate variables exist
|
|
58
|
+
for var in variables:
|
|
59
|
+
if var not in self.graph_manager.get_nodes():
|
|
60
|
+
logger.warning(f"Variable {var} not in graph, skipping composite creation")
|
|
61
|
+
return name
|
|
62
|
+
|
|
63
|
+
# Store composite mapping
|
|
64
|
+
self.composite_nodes[name] = variables.copy()
|
|
65
|
+
|
|
66
|
+
# Ensure composite node exists
|
|
67
|
+
self.graph_manager.ensure_node_exists(name)
|
|
68
|
+
|
|
69
|
+
# Aggregate edges from original variables
|
|
70
|
+
# Incoming edges: union of all incoming edges from original variables
|
|
71
|
+
incoming_sources: Set[str] = set()
|
|
72
|
+
for var in variables:
|
|
73
|
+
parents = self.graph_manager.get_parents(var)
|
|
74
|
+
incoming_sources.update(parents)
|
|
75
|
+
|
|
76
|
+
for source in incoming_sources:
|
|
77
|
+
# Aggregate strength from all original variables
|
|
78
|
+
total_strength = 0.0
|
|
79
|
+
count = 0
|
|
80
|
+
for var in variables:
|
|
81
|
+
strength = self.graph_manager.edge_strength(source, var)
|
|
82
|
+
if strength > 0:
|
|
83
|
+
total_strength += strength
|
|
84
|
+
count += 1
|
|
85
|
+
|
|
86
|
+
if count > 0:
|
|
87
|
+
avg_strength = total_strength / count
|
|
88
|
+
self.graph_manager.add_relationship(
|
|
89
|
+
source, name,
|
|
90
|
+
strength=avg_strength,
|
|
91
|
+
relation_type="composite_incoming"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Outgoing edges: union of all outgoing edges from original variables
|
|
95
|
+
outgoing_targets: Set[str] = set()
|
|
96
|
+
for var in variables:
|
|
97
|
+
children = self.graph_manager.get_children(var)
|
|
98
|
+
outgoing_targets.update(children)
|
|
99
|
+
|
|
100
|
+
for target in outgoing_targets:
|
|
101
|
+
# Aggregate strength from all original variables
|
|
102
|
+
total_strength = 0.0
|
|
103
|
+
count = 0
|
|
104
|
+
for var in variables:
|
|
105
|
+
strength = self.graph_manager.edge_strength(var, target)
|
|
106
|
+
if strength > 0:
|
|
107
|
+
total_strength += strength
|
|
108
|
+
count += 1
|
|
109
|
+
|
|
110
|
+
if count > 0:
|
|
111
|
+
avg_strength = total_strength / count
|
|
112
|
+
self.graph_manager.add_relationship(
|
|
113
|
+
name, target,
|
|
114
|
+
strength=avg_strength,
|
|
115
|
+
relation_type="composite_outgoing"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
# Optionally remove original nodes
|
|
119
|
+
if not preserve_originals:
|
|
120
|
+
for var in variables:
|
|
121
|
+
# Remove all edges involving this variable
|
|
122
|
+
children = self.graph_manager.get_children(var)
|
|
123
|
+
for child in children:
|
|
124
|
+
# Edge removal would need to be added to GraphManager
|
|
125
|
+
pass
|
|
126
|
+
parents = self.graph_manager.get_parents(var)
|
|
127
|
+
for parent in parents:
|
|
128
|
+
# Edge removal would need to be added to GraphManager
|
|
129
|
+
pass
|
|
130
|
+
|
|
131
|
+
return name
|
|
132
|
+
|
|
133
|
+
def abstract_to_latent(self, variables: List[str], latent_name: Optional[str] = None) -> str:
|
|
134
|
+
"""
|
|
135
|
+
Abstract multiple observed variables into a latent factor.
|
|
136
|
+
|
|
137
|
+
Example: "product quality", "service quality" → "quality_factor" (latent)
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
variables: List of observed variable names
|
|
141
|
+
latent_name: Name for latent factor (auto-generated if None)
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
Name of the created latent factor
|
|
145
|
+
"""
|
|
146
|
+
if latent_name is None:
|
|
147
|
+
latent_name = f"latent_{len(self.latent_factors)}"
|
|
148
|
+
|
|
149
|
+
# Store latent mapping
|
|
150
|
+
self.latent_factors[latent_name] = variables.copy()
|
|
151
|
+
|
|
152
|
+
# Ensure latent node exists
|
|
153
|
+
self.graph_manager.ensure_node_exists(latent_name)
|
|
154
|
+
|
|
155
|
+
# Create edges: latent → observed (latent causes observed)
|
|
156
|
+
for var in variables:
|
|
157
|
+
self.graph_manager.add_relationship(
|
|
158
|
+
latent_name, var,
|
|
159
|
+
strength=1.0,
|
|
160
|
+
relation_type="latent_to_observed"
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Inherit incoming edges from observed variables
|
|
164
|
+
incoming_sources: Set[str] = set()
|
|
165
|
+
for var in variables:
|
|
166
|
+
parents = self.graph_manager.get_parents(var)
|
|
167
|
+
incoming_sources.update(parents)
|
|
168
|
+
|
|
169
|
+
for source in incoming_sources:
|
|
170
|
+
if source not in variables: # Don't create self-loops
|
|
171
|
+
total_strength = 0.0
|
|
172
|
+
count = 0
|
|
173
|
+
for var in variables:
|
|
174
|
+
strength = self.graph_manager.edge_strength(source, var)
|
|
175
|
+
if strength > 0:
|
|
176
|
+
total_strength += strength
|
|
177
|
+
count += 1
|
|
178
|
+
|
|
179
|
+
if count > 0:
|
|
180
|
+
avg_strength = total_strength / count
|
|
181
|
+
self.graph_manager.add_relationship(
|
|
182
|
+
source, latent_name,
|
|
183
|
+
strength=avg_strength,
|
|
184
|
+
relation_type="latent_incoming"
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
return latent_name
|
|
188
|
+
|
|
189
|
+
def compress_subgraph(self, nodes: List[str]) -> Dict[str, Any]:
|
|
190
|
+
"""
|
|
191
|
+
Compress a subgraph by removing low-confidence edges and merging redundant paths.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
nodes: List of nodes in the subgraph to compress
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
Dictionary with compression statistics
|
|
198
|
+
"""
|
|
199
|
+
removed_edges = 0
|
|
200
|
+
merged_paths = 0
|
|
201
|
+
|
|
202
|
+
# Remove low-confidence edges (confidence < 0.3)
|
|
203
|
+
edges_to_remove = []
|
|
204
|
+
for source in nodes:
|
|
205
|
+
if source not in self.graph_manager.graph:
|
|
206
|
+
continue
|
|
207
|
+
for target, meta in self.graph_manager.graph[source].items():
|
|
208
|
+
if target not in nodes:
|
|
209
|
+
continue
|
|
210
|
+
if isinstance(meta, dict):
|
|
211
|
+
confidence = meta.get("confidence", 1.0)
|
|
212
|
+
if confidence < 0.3:
|
|
213
|
+
edges_to_remove.append((source, target))
|
|
214
|
+
|
|
215
|
+
# Note: Edge removal would need to be implemented in GraphManager
|
|
216
|
+
removed_edges = len(edges_to_remove)
|
|
217
|
+
|
|
218
|
+
# Merge redundant paths (simplified: detect and mark for merging)
|
|
219
|
+
# In a full implementation, would identify paths with same source/target
|
|
220
|
+
# and merge them into a single edge with aggregated strength
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
"removed_edges": removed_edges,
|
|
224
|
+
"merged_paths": merged_paths,
|
|
225
|
+
"original_nodes": len(nodes),
|
|
226
|
+
"compressed_nodes": len(nodes) # Would be reduced in full implementation
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
def simplify_graph(
|
|
230
|
+
self,
|
|
231
|
+
min_confidence: float = 0.3,
|
|
232
|
+
min_strength: float = 0.1
|
|
233
|
+
) -> Dict[str, Any]:
|
|
234
|
+
"""
|
|
235
|
+
Simplify entire graph by removing low-confidence/strength edges.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
min_confidence: Minimum confidence threshold
|
|
239
|
+
min_strength: Minimum strength threshold
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
Dictionary with simplification statistics
|
|
243
|
+
"""
|
|
244
|
+
all_nodes = self.graph_manager.get_nodes()
|
|
245
|
+
removed_edges = 0
|
|
246
|
+
|
|
247
|
+
edges_to_remove = []
|
|
248
|
+
for source in all_nodes:
|
|
249
|
+
if source not in self.graph_manager.graph:
|
|
250
|
+
continue
|
|
251
|
+
for target, meta in self.graph_manager.graph[source].items():
|
|
252
|
+
if isinstance(meta, dict):
|
|
253
|
+
confidence = meta.get("confidence", 1.0)
|
|
254
|
+
strength = meta.get("strength", 1.0)
|
|
255
|
+
if confidence < min_confidence or strength < min_strength:
|
|
256
|
+
edges_to_remove.append((source, target))
|
|
257
|
+
|
|
258
|
+
removed_edges = len(edges_to_remove)
|
|
259
|
+
|
|
260
|
+
# Note: Actual edge removal would need GraphManager.remove_edge method
|
|
261
|
+
# For now, just return statistics
|
|
262
|
+
|
|
263
|
+
return {
|
|
264
|
+
"removed_edges": removed_edges,
|
|
265
|
+
"remaining_nodes": len(all_nodes),
|
|
266
|
+
"min_confidence": min_confidence,
|
|
267
|
+
"min_strength": min_strength
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
def get_composite_mapping(self) -> Dict[str, List[str]]:
|
|
271
|
+
"""
|
|
272
|
+
Get mapping of composite nodes to original variables.
|
|
273
|
+
|
|
274
|
+
Returns:
|
|
275
|
+
Dictionary mapping composite node names to lists of original variables
|
|
276
|
+
"""
|
|
277
|
+
return self.composite_nodes.copy()
|
|
278
|
+
|
|
279
|
+
def get_latent_mapping(self) -> Dict[str, List[str]]:
|
|
280
|
+
"""
|
|
281
|
+
Get mapping of latent factors to observed variables.
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
Dictionary mapping latent factor names to lists of observed variables
|
|
285
|
+
"""
|
|
286
|
+
return self.latent_factors.copy()
|