citymind-engine 1.0.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.
citymind/__init__.py ADDED
@@ -0,0 +1,16 @@
1
+ """CITYMIND: Urban Human Systems Intelligence Framework.
2
+
3
+ Independent Subsystem Modeling with AI-Enhanced Aggregation.
4
+ Urban Health Index (UHI) composite metric for city governance.
5
+ """
6
+
7
+ __version__ = "1.0.0"
8
+ __author__ = "Samir Baladi"
9
+ __email__ = "gitdeeper@gmail.com"
10
+ __license__ = "MIT"
11
+ __doi__ = "10.5281/zenodo.20444647"
12
+
13
+ from citymind.pipeline import CityMindAssessor
14
+ from citymind.uhi import UrbanHealthIndex
15
+
16
+ __all__ = ["CityMindAssessor", "UrbanHealthIndex"]
@@ -0,0 +1,17 @@
1
+ """AI enhancement layer for CITYMIND.
2
+
3
+ AI is ONLY:
4
+ - a predictive improvement tool
5
+ - a calibration mechanism for system outputs
6
+ - an adaptive weighting and anomaly detection layer
7
+
8
+ AI is NOT:
9
+ - a redefiner of the domain structure
10
+ - a unifier of subsystems
11
+ - a replacement of the underlying model logic
12
+ """
13
+
14
+ from citymind.ai_enhancement.weight_optimizer import AIWeightOptimizer
15
+ from citymind.ai_enhancement.anomaly_detector import AnomalyDetector
16
+
17
+ __all__ = ["AIWeightOptimizer", "AnomalyDetector"]
@@ -0,0 +1,71 @@
1
+ """Anomaly detection for urban subsystems.
2
+
3
+ AI-assisted anomaly detection for identifying stressed subsystems.
4
+ """
5
+
6
+ import numpy as np
7
+ from typing import Dict, List, Optional
8
+
9
+
10
+ class AnomalyDetector:
11
+ """
12
+ Anomaly detection for urban subsystems.
13
+
14
+ Identifies which subsystem is experiencing stress.
15
+ Does NOT modify subsystem models.
16
+ """
17
+
18
+ def __init__(self, threshold: float = 2.0):
19
+ self.threshold = threshold
20
+ self.history: List[Dict[str, float]] = []
21
+
22
+ def detect(self, scores: Dict[str, float]) -> Dict[str, any]:
23
+ """
24
+ Detect anomalies in subsystem scores.
25
+
26
+ Returns:
27
+ Dictionary with detection results
28
+ """
29
+ self.history.append(scores)
30
+
31
+ if len(self.history) < 3:
32
+ return {"anomaly_detected": False, "affected_subsystems": []}
33
+
34
+ anomalies = []
35
+
36
+ for subsystem, score in scores.items():
37
+ recent_scores = [h[subsystem] for h in self.history[-5:] if subsystem in h]
38
+
39
+ if len(recent_scores) >= 3:
40
+ mean = np.mean(recent_scores)
41
+ std = np.std(recent_scores)
42
+
43
+ if std > 0:
44
+ z_score = abs(score - mean) / std
45
+ if z_score > self.threshold:
46
+ anomalies.append({
47
+ "subsystem": subsystem,
48
+ "score": score,
49
+ "deviation": z_score,
50
+ "severity": "HIGH" if z_score > 3 else "MEDIUM"
51
+ })
52
+
53
+ return {
54
+ "anomaly_detected": len(anomalies) > 0,
55
+ "affected_subsystems": anomalies,
56
+ "threshold": self.threshold
57
+ }
58
+
59
+ def get_stressed_subsystem(self, scores: Dict[str, float]) -> Optional[str]:
60
+ """Identify the most stressed subsystem."""
61
+ result = self.detect(scores)
62
+
63
+ if not result["anomaly_detected"]:
64
+ return None
65
+
66
+ anomalies = result["affected_subsystems"]
67
+ if not anomalies:
68
+ return None
69
+
70
+ # Return subsystem with highest deviation
71
+ return max(anomalies, key=lambda x: x["deviation"])["subsystem"]
@@ -0,0 +1,90 @@
1
+ """AI-enhanced weight optimization for Urban Health Index.
2
+
3
+ AI strictly bounded to optimization of weights (Σ w_i = 1.0)
4
+ Does NOT modify subsystem models or merge them.
5
+ """
6
+
7
+ import numpy as np
8
+ from typing import Dict, Optional
9
+
10
+
11
+ class AIWeightOptimizer:
12
+ """
13
+ AI weight optimizer for UHI aggregation.
14
+
15
+ Adjusts weights based on historical performance and anomaly detection.
16
+ Maintains constraint: Σ w_i = 1.0
17
+ """
18
+
19
+ def __init__(self, learning_rate: float = 0.01):
20
+ self.learning_rate = learning_rate
21
+ self.historical_scores = []
22
+ self.current_weights = {
23
+ "transport": 0.20,
24
+ "population": 0.20,
25
+ "energy": 0.20,
26
+ "mobility": 0.20,
27
+ "infrastructure": 0.20
28
+ }
29
+
30
+ def optimize_weights(self, scores: Dict[str, float]) -> Dict[str, float]:
31
+ """
32
+ Optimize subsystem weights based on recent performance.
33
+
34
+ Higher performing subsystems receive higher weights.
35
+ Constraint: Σ w_i = 1.0
36
+ """
37
+ self.historical_scores.append(scores)
38
+
39
+ # Calculate performance-based weights
40
+ total_performance = sum(scores.values())
41
+ if total_performance > 0:
42
+ raw_weights = {k: v / total_performance for k, v in scores.items()}
43
+ else:
44
+ raw_weights = self.current_weights.copy()
45
+
46
+ # Apply learning rate for smooth transition
47
+ for k in self.current_weights:
48
+ self.current_weights[k] = (1 - self.learning_rate) * self.current_weights[k] + \
49
+ self.learning_rate * raw_weights[k]
50
+
51
+ # Ensure sum to 1.0
52
+ total = sum(self.current_weights.values())
53
+ if total > 0:
54
+ self.current_weights = {k: v / total for k, v in self.current_weights.items()}
55
+
56
+ return self.current_weights.copy()
57
+
58
+ def detect_anomaly(self, scores: Dict[str, float], threshold: float = 0.3) -> bool:
59
+ """Detect anomalies in subsystem scores."""
60
+ if len(self.historical_scores) < 5:
61
+ return False
62
+
63
+ recent_scores = self.historical_scores[-5:]
64
+ mean_scores = {}
65
+ std_scores = {}
66
+
67
+ for subsystem in scores.keys():
68
+ values = [s[subsystem] for s in recent_scores]
69
+ mean_scores[subsystem] = np.mean(values)
70
+ std_scores[subsystem] = np.std(values)
71
+
72
+ for subsystem in scores.keys():
73
+ deviation = abs(scores[subsystem] - mean_scores[subsystem])
74
+ if std_scores[subsystem] > 0 and deviation / std_scores[subsystem] > threshold:
75
+ return True
76
+
77
+ return False
78
+
79
+ def forecast_uhi(self, scores: Dict[str, float], horizon_hours: int = 48) -> float:
80
+ """Forecast future UHI using simple trend extrapolation."""
81
+ if len(self.historical_scores) < 10:
82
+ return sum(scores.values()) / len(scores)
83
+
84
+ # Simple linear trend
85
+ recent_uhi = [sum(s.values()) / len(s) for s in self.historical_scores[-10:]]
86
+ trend = (recent_uhi[-1] - recent_uhi[0]) / len(recent_uhi)
87
+
88
+ forecast = recent_uhi[-1] + trend * (horizon_hours / 24)
89
+
90
+ return max(0.0, min(forecast, 1.0))
@@ -0,0 +1,6 @@
1
+ """Data archival with SHA-256 integrity."""
2
+
3
+ from citymind.archival.writer import ArchivalWriter
4
+ from citymind.archival.checksum import compute_checksum
5
+
6
+ __all__ = ["ArchivalWriter", "compute_checksum"]
@@ -0,0 +1,20 @@
1
+ """SHA-256 checksum for data integrity."""
2
+
3
+ import hashlib
4
+
5
+
6
+ def compute_checksum(filepath: str, algorithm: str = "sha256") -> str:
7
+ """Compute file checksum for integrity verification."""
8
+ hash_func = hashlib.new(algorithm)
9
+
10
+ with open(filepath, "rb") as f:
11
+ for chunk in iter(lambda: f.read(4096), b""):
12
+ hash_func.update(chunk)
13
+
14
+ return hash_func.hexdigest()
15
+
16
+
17
+ def verify_integrity(filepath: str, expected_checksum: str) -> bool:
18
+ """Verify file integrity against expected checksum."""
19
+ actual = compute_checksum(filepath)
20
+ return actual == expected_checksum
@@ -0,0 +1,31 @@
1
+ """Append-only data archival writer."""
2
+
3
+ import json
4
+ import csv
5
+ from datetime import datetime
6
+ from pathlib import Path
7
+ from typing import Dict, Any
8
+
9
+
10
+ class ArchivalWriter:
11
+ """Append-only data archival writer."""
12
+
13
+ def __init__(self, base_path: str = "./data/archival"):
14
+ self.base_path = Path(base_path)
15
+ self.base_path.mkdir(parents=True, exist_ok=True)
16
+
17
+ def write_json(self, data: Dict[str, Any], filename: str):
18
+ """Write data to JSON file with timestamp."""
19
+ filepath = self.base_path / f"{filename}_{datetime.now().strftime('%Y%m%d')}.json"
20
+
21
+ record = {
22
+ "timestamp": datetime.now().isoformat(),
23
+ "data": data
24
+ }
25
+
26
+ with open(filepath, "a") as f:
27
+ f.write(json.dumps(record) + "\n")
28
+
29
+ def write_uhi_record(self, uhi_result: Dict):
30
+ """Write UHI assessment record."""
31
+ self.write_json(uhi_result, "uhi_assessment")
@@ -0,0 +1,5 @@
1
+ """Real-time monitoring dashboard for CITYMIND."""
2
+
3
+ from citymind.monitoring.app import run_dashboard
4
+
5
+ __all__ = ["run_dashboard"]
@@ -0,0 +1,185 @@
1
+ """Streamlit application entry point for CITYMIND dashboard."""
2
+
3
+ import streamlit as st
4
+ import plotly.graph_objects as go
5
+ import plotly.express as px
6
+ import pandas as pd
7
+ import numpy as np
8
+ from datetime import datetime, timedelta
9
+
10
+ from citymind.pipeline import CityMindAssessor
11
+
12
+
13
+ def run_dashboard():
14
+ """Launch the CITYMIND monitoring dashboard."""
15
+ st.set_page_config(
16
+ page_title="CITYMIND Dashboard",
17
+ page_icon="🏙️",
18
+ layout="wide"
19
+ )
20
+
21
+ st.title("🏙️ CITYMIND - Urban Health Intelligence Dashboard")
22
+ st.markdown("*Independent Subsystem Modeling with AI-Enhanced Aggregation*")
23
+
24
+ # Initialize assessor
25
+ assessor = CityMindAssessor()
26
+
27
+ # Sidebar
28
+ with st.sidebar:
29
+ st.header("⚙️ Controls")
30
+ refresh = st.button("🔄 Refresh Data", type="primary")
31
+ ai_enabled = st.checkbox("🤖 AI Enhancement", value=True)
32
+
33
+ st.markdown("---")
34
+ st.markdown("### 🏗️ Urban Subsystems")
35
+ st.markdown("- 🚗 Transport Flow")
36
+ st.markdown("- 👥 Population Density")
37
+ st.markdown("- ⚡ Energy Consumption")
38
+ st.markdown("- 🚶 Mobility Behavior")
39
+ st.markdown("- 🏗️ Infrastructure Load")
40
+
41
+ st.markdown("---")
42
+ st.markdown("### 📊 Governance Thresholds")
43
+ st.markdown("🟢 UHI ≥ 0.85 - Optimized")
44
+ st.markdown("🟠 0.70 ≤ UHI < 0.85 - Stressed")
45
+ st.markdown("🟠 0.55 ≤ UHI < 0.70 - Mitigation")
46
+ st.markdown("🔴 UHI < 0.55 - Critical")
47
+
48
+ # Get results
49
+ if ai_enabled:
50
+ assessor.ai_enhancement = True
51
+ else:
52
+ assessor.ai_enhancement = False
53
+
54
+ result = assessor.evaluate()
55
+
56
+ # Main dashboard
57
+ col1, col2, col3 = st.columns(3)
58
+
59
+ with col1:
60
+ # UHI Gauge
61
+ fig = go.Figure(go.Indicator(
62
+ mode="gauge+number",
63
+ value=result.uhi_result.uhi,
64
+ title={"text": "Urban Health Index (UHI)"},
65
+ gauge={
66
+ "axis": {"range": [0, 1], "tickwidth": 1},
67
+ "bar": {"color": _get_uhi_color(result.uhi_result.uhi)},
68
+ "steps": [
69
+ {"range": [0, 0.55], "color": "#C0392B", "name": "Critical"},
70
+ {"range": [0.55, 0.70], "color": "#E67E22", "name": "Mitigation"},
71
+ {"range": [0.70, 0.85], "color": "#F39C12", "name": "Stressed"},
72
+ {"range": [0.85, 1.0], "color": "#27AE60", "name": "Optimized"}
73
+ ],
74
+ "threshold": {
75
+ "line": {"color": "black", "width": 4},
76
+ "thickness": 0.75,
77
+ "value": result.uhi_result.uhi
78
+ }
79
+ }
80
+ ))
81
+ fig.update_layout(height=300)
82
+ st.plotly_chart(fig, use_container_width=True)
83
+
84
+ # Signal badge
85
+ signal_color = {
86
+ "🟢 OPTIMIZED_URBAN_FLOW": "green",
87
+ "🟠 STRESSED_SUBSYSTEM_WARNING": "orange",
88
+ "🟠 SYSTEMIC_MITIGATION_PHASE": "orange",
89
+ "🔴 CRITICAL_INFRASTRUCTURE_BREACH": "red"
90
+ }.get(result.uhi_result.signal.value, "gray")
91
+
92
+ st.markdown(f"""
93
+ <div style="background-color: {signal_color}20; padding: 15px; border-radius: 10px; text-align: center;">
94
+ <h2>{result.uhi_result.signal.value}</h2>
95
+ </div>
96
+ """, unsafe_allow_html=True)
97
+
98
+ with col2:
99
+ st.metric("🚗 Transport", f"{result.uhi_result.transport_score:.3f}")
100
+ st.metric("👥 Population", f"{result.uhi_result.population_score:.3f}")
101
+ st.metric("⚡ Energy", f"{result.uhi_result.energy_score:.3f}")
102
+
103
+ with col3:
104
+ st.metric("🚶 Mobility", f"{result.uhi_result.mobility_score:.3f}")
105
+ st.metric("🏗️ Infrastructure", f"{result.uhi_result.infrastructure_score:.3f}")
106
+ st.metric("🤖 AI Anomaly", "Detected" if result.anomaly_detected else "None")
107
+
108
+ # Subsystem scores chart
109
+ st.markdown("---")
110
+ st.subheader("📊 Subsystem Performance")
111
+
112
+ scores_df = pd.DataFrame({
113
+ "Subsystem": ["Transport", "Population", "Energy", "Mobility", "Infrastructure"],
114
+ "Score": [
115
+ result.uhi_result.transport_score,
116
+ result.uhi_result.population_score,
117
+ result.uhi_result.energy_score,
118
+ result.uhi_result.mobility_score,
119
+ result.uhi_result.infrastructure_score
120
+ ],
121
+ "Weight": [
122
+ result.ai_weights.get("transport", 0.2),
123
+ result.ai_weights.get("population", 0.2),
124
+ result.ai_weights.get("energy", 0.2),
125
+ result.ai_weights.get("mobility", 0.2),
126
+ result.ai_weights.get("infrastructure", 0.2)
127
+ ]
128
+ })
129
+
130
+ fig = px.bar(scores_df, x="Subsystem", y="Score", color="Score",
131
+ color_continuous_scale="RdYlGn", range_color=[0, 1],
132
+ title="Subsystem Health Scores")
133
+ fig.update_layout(height=400)
134
+ st.plotly_chart(fig, use_container_width=True)
135
+
136
+ # AI weights
137
+ col1, col2 = st.columns(2)
138
+
139
+ with col1:
140
+ st.subheader("🤖 AI-Optimized Weights")
141
+ weights_df = pd.DataFrame({
142
+ "Subsystem": list(result.ai_weights.keys()),
143
+ "Weight": list(result.ai_weights.values())
144
+ })
145
+ fig = px.pie(weights_df, values="Weight", names="Subsystem", title="Weight Distribution")
146
+ fig.update_layout(height=350)
147
+ st.plotly_chart(fig, use_container_width=True)
148
+
149
+ with col2:
150
+ st.subheader("📈 Forecast")
151
+ if result.forecast_uhi:
152
+ st.metric("48h UHI Forecast", f"{result.forecast_uhi:.3f}")
153
+ trend = result.forecast_uhi - result.uhi_result.uhi
154
+ st.metric("Trend", f"{trend:+.3f}", delta=trend)
155
+ else:
156
+ st.info("AI enhancement disabled. Enable AI for forecasting.")
157
+
158
+ # Governance action
159
+ st.subheader("📋 Recommended Action")
160
+ action = assessor.uhi.get_governance_action(result.uhi_result.signal)
161
+ st.info(action)
162
+
163
+ # Footer
164
+ st.markdown("---")
165
+ st.markdown("""
166
+ <div style="text-align: center; color: gray; font-size: 12px;">
167
+ CITYMIND v1.0.0 | Urban Human Systems Intelligence |
168
+ Independent Subsystem Modeling with AI-Enhanced Aggregation
169
+ </div>
170
+ """, unsafe_allow_html=True)
171
+
172
+
173
+ def _get_uhi_color(uhi: float) -> str:
174
+ if uhi >= 0.85:
175
+ return "#27AE60"
176
+ elif uhi >= 0.70:
177
+ return "#F39C12"
178
+ elif uhi >= 0.55:
179
+ return "#E67E22"
180
+ else:
181
+ return "#C0392B"
182
+
183
+
184
+ if __name__ == "__main__":
185
+ run_dashboard()
@@ -0,0 +1,45 @@
1
+ """CSII governance dashboard layout."""
2
+
3
+ import streamlit as st
4
+ import plotly.graph_objects as go
5
+
6
+
7
+ def create_dashboard(uhi_value: float, signal: str, scores: dict):
8
+ """Create full UHI governance dashboard."""
9
+ col1, col2, col3 = st.columns(3)
10
+
11
+ with col1:
12
+ fig = go.Figure(go.Indicator(
13
+ mode="gauge+number",
14
+ value=uhi_value,
15
+ title={"text": "UHI Score"},
16
+ gauge={
17
+ "axis": {"range": [0, 1]},
18
+ "bar": {"color": _get_color(uhi_value)},
19
+ "steps": [
20
+ {"range": [0, 0.55], "color": "red"},
21
+ {"range": [0.55, 0.70], "color": "orange"},
22
+ {"range": [0.70, 0.85], "color": "yellow"},
23
+ {"range": [0.85, 1.0], "color": "green"},
24
+ ]
25
+ }
26
+ ))
27
+ st.plotly_chart(fig)
28
+
29
+ with col2:
30
+ st.metric("Urban Signal", signal)
31
+
32
+ with col3:
33
+ for name, score in scores.items():
34
+ st.metric(name.capitalize(), f"{score:.3f}")
35
+
36
+
37
+ def _get_color(uhi: float) -> str:
38
+ if uhi >= 0.85:
39
+ return "green"
40
+ elif uhi >= 0.70:
41
+ return "yellow"
42
+ elif uhi >= 0.55:
43
+ return "orange"
44
+ else:
45
+ return "red"
citymind/pipeline.py ADDED
@@ -0,0 +1,107 @@
1
+ """CITYMIND main assessment pipeline."""
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Dict, Optional
5
+
6
+ import numpy as np
7
+
8
+ from citymind.uhi import UrbanHealthIndex, UHIResult, UrbanSignal
9
+ from citymind.subsystems.transport import TransportSubsystem
10
+ from citymind.subsystems.population import PopulationSubsystem
11
+ from citymind.subsystems.energy import EnergySubsystem
12
+ from citymind.subsystems.mobility import MobilitySubsystem
13
+ from citymind.subsystems.infrastructure import InfrastructureSubsystem
14
+ from citymind.ai_enhancement.weight_optimizer import AIWeightOptimizer
15
+
16
+
17
+ @dataclass
18
+ class PipelineResult:
19
+ """Complete pipeline assessment result."""
20
+ uhi_result: UHIResult
21
+ subsystem_scores: Dict[str, float]
22
+ ai_weights: Dict[str, float]
23
+ anomaly_detected: bool
24
+ forecast_uhi: Optional[float]
25
+
26
+
27
+ class CityMindAssessor:
28
+ """
29
+ CITYMIND main assessment pipeline.
30
+
31
+ Integrates five independent urban subsystems with AI enhancement
32
+ strictly bounded to optimization and anomaly detection.
33
+ """
34
+
35
+ def __init__(
36
+ self,
37
+ config: Optional[Dict] = None,
38
+ ai_enhancement: bool = True
39
+ ):
40
+ self.config = config or {}
41
+ self.ai_enhancement = ai_enhancement
42
+
43
+ # Initialize five independent subsystems
44
+ self.transport = TransportSubsystem()
45
+ self.population = PopulationSubsystem()
46
+ self.energy = EnergySubsystem()
47
+ self.mobility = MobilitySubsystem()
48
+ self.infrastructure = InfrastructureSubsystem()
49
+
50
+ # Initialize AI enhancement layer
51
+ self.ai_weight_optimizer = AIWeightOptimizer() if ai_enhancement else None
52
+ self.uhi = UrbanHealthIndex(ai_weight_optimization=ai_enhancement)
53
+
54
+ def evaluate(self) -> PipelineResult:
55
+ """
56
+ Run full CITYMIND assessment pipeline.
57
+
58
+ Each subsystem is evaluated independently. AI only enhances
59
+ weight optimization and anomaly detection.
60
+ """
61
+ # Evaluate each subsystem independently
62
+ transport_score = self.transport.compute()
63
+ population_score = self.population.compute()
64
+ energy_score = self.energy.compute()
65
+ mobility_score = self.mobility.compute()
66
+ infrastructure_score = self.infrastructure.compute()
67
+
68
+ subsystem_scores = {
69
+ "transport": transport_score,
70
+ "population": population_score,
71
+ "energy": energy_score,
72
+ "mobility": mobility_score,
73
+ "infrastructure": infrastructure_score
74
+ }
75
+
76
+ # AI-enhanced weight optimization
77
+ if self.ai_enhancement and self.ai_weight_optimizer:
78
+ weights = self.ai_weight_optimizer.optimize_weights(subsystem_scores)
79
+ anomaly_detected = self.ai_weight_optimizer.detect_anomaly(subsystem_scores)
80
+ forecast_uhi = self.ai_weight_optimizer.forecast_uhi(subsystem_scores)
81
+ else:
82
+ weights = None
83
+ anomaly_detected = False
84
+ forecast_uhi = None
85
+
86
+ # Compute UHI composite index
87
+ uhi_result = self.uhi.compute(
88
+ transport_score=transport_score,
89
+ population_score=population_score,
90
+ energy_score=energy_score,
91
+ mobility_score=mobility_score,
92
+ infrastructure_score=infrastructure_score,
93
+ weights=weights
94
+ )
95
+
96
+ return PipelineResult(
97
+ uhi_result=uhi_result,
98
+ subsystem_scores=subsystem_scores,
99
+ ai_weights=weights or self.uhi.DEFAULT_WEIGHTS,
100
+ anomaly_detected=anomaly_detected,
101
+ forecast_uhi=forecast_uhi
102
+ )
103
+
104
+ def get_urban_signal(self) -> UrbanSignal:
105
+ """Get current urban governance signal."""
106
+ result = self.evaluate()
107
+ return result.uhi_result.signal
@@ -0,0 +1,6 @@
1
+ """Urban sensor integration for CITYMIND."""
2
+
3
+ from citymind.sensors.traffic_sensor import TrafficSensor
4
+ from citymind.sensors.energy_sensor import EnergySensor
5
+
6
+ __all__ = ["TrafficSensor", "EnergySensor"]
@@ -0,0 +1,24 @@
1
+ """Energy consumption sensor data processor."""
2
+
3
+ import numpy as np
4
+ from typing import Dict
5
+
6
+
7
+ class EnergySensor:
8
+ """Energy grid sensor data processor."""
9
+
10
+ def __init__(self):
11
+ pass
12
+
13
+ def process(self, demand: float, supply: float) -> Dict:
14
+ """Process energy data."""
15
+ return {
16
+ "demand": demand,
17
+ "supply": supply,
18
+ "deficit_ratio": max(0, (demand - supply) / supply) if supply > 0 else 1.0,
19
+ "score": (supply - demand) / supply if supply > demand else 0.0
20
+ }
21
+
22
+ def detect_deficit(self, demand: float, supply: float) -> bool:
23
+ """Detect energy deficit."""
24
+ return demand > supply * 0.95
@@ -0,0 +1,24 @@
1
+ """Traffic sensor data processor."""
2
+
3
+ import numpy as np
4
+ from typing import Dict, Optional
5
+
6
+
7
+ class TrafficSensor:
8
+ """Traffic flow sensor data processor."""
9
+
10
+ def __init__(self, sampling_rate: float = 60.0):
11
+ self.sampling_rate = sampling_rate
12
+
13
+ def process(self, raw_data: np.ndarray) -> Dict:
14
+ """Process raw traffic sensor data."""
15
+ return {
16
+ "volume": float(np.mean(raw_data)),
17
+ "peak": float(np.max(raw_data)),
18
+ "congestion_ratio": float(np.mean(raw_data) / 10000),
19
+ "timestamp": None
20
+ }
21
+
22
+ def detect_congestion(self, volume: float, capacity: float = 10000) -> bool:
23
+ """Detect traffic congestion."""
24
+ return volume / capacity > 0.85
@@ -0,0 +1,5 @@
1
+ """Validation and simulation environment for CITYMIND."""
2
+
3
+ from citymind.simulation.benchmarks import run_validation_suite
4
+
5
+ __all__ = ["run_validation_suite"]