Spaces:
Running on Zero
Running on Zero
Download src/integration/decision_engine.py from vish07anth/ATA: direct link, hf CLI and curl.
- Browser
- Download file 5.55 kB
-
https://huggingface.co/spaces/vish07anth/ATA/resolve/main/src/integration/decision_engine.py
- Command line
-
hf download hf://spaces/vish07anth/ATA/src/integration/decision_engine.py
-
curl -L -o decision_engine.py https://huggingface.co/spaces/vish07anth/ATA/resolve/main/src/integration/decision_engine.py
5.55 kB
| class DecisionEngine: | |
| """ | |
| Selects the best valid signal phase based on: | |
| - traffic demand | |
| - predicted traffic | |
| - priority | |
| - fairness | |
| - risk | |
| This module only makes a decision. | |
| It does NOT directly control traffic signals. | |
| """ | |
| def __init__( | |
| self, | |
| demand_weight=0.35, | |
| prediction_weight=0.25, | |
| priority_weight=0.20, | |
| fairness_weight=0.10, | |
| risk_weight=0.10 | |
| ): | |
| self.weights = { | |
| "demand": demand_weight, | |
| "prediction": prediction_weight, | |
| "priority": priority_weight, | |
| "fairness": fairness_weight, | |
| "risk": risk_weight | |
| } | |
| total = sum(self.weights.values()) | |
| if total <= 0: | |
| raise ValueError( | |
| "Decision weights must have a positive total" | |
| ) | |
| # Normalize weights so they sum to 1 | |
| for key in self.weights: | |
| self.weights[key] /= total | |
| def calculate_phase_score( | |
| self, | |
| demand, | |
| prediction, | |
| priority, | |
| fairness, | |
| risk | |
| ): | |
| """ | |
| Calculate the score for one phase. | |
| All inputs must be normalized to [0, 1]. | |
| Higher score = better phase. | |
| """ | |
| values = { | |
| "demand": demand, | |
| "prediction": prediction, | |
| "priority": priority, | |
| "fairness": fairness, | |
| "risk": risk | |
| } | |
| for name, value in values.items(): | |
| if not 0 <= value <= 1: | |
| raise ValueError( | |
| f"{name} must be between 0 and 1" | |
| ) | |
| score = ( | |
| self.weights["demand"] * demand | |
| + self.weights["prediction"] * prediction | |
| + self.weights["priority"] * priority | |
| + self.weights["fairness"] * fairness | |
| + self.weights["risk"] * risk | |
| ) | |
| return score | |
| def calculate_phase_prediction( | |
| self, | |
| predictions, | |
| sensor_ids | |
| ): | |
| """ | |
| Convert GNN predictions for multiple sensors | |
| into one prediction score for a signal phase. | |
| Parameters | |
| ---------- | |
| predictions : array-like | |
| GNN predictions for all sensors. | |
| sensor_ids : list | |
| Sensor IDs belonging to this phase. | |
| Returns | |
| ------- | |
| float | |
| Normalized phase prediction score [0, 1]. | |
| """ | |
| if predictions is None: | |
| raise ValueError( | |
| "predictions cannot be None" | |
| ) | |
| if not sensor_ids: | |
| raise ValueError( | |
| "sensor_ids cannot be empty" | |
| ) | |
| predictions = list(predictions) | |
| # Validate sensor IDs | |
| for sensor_id in sensor_ids: | |
| if not isinstance(sensor_id, int): | |
| raise ValueError( | |
| "sensor IDs must be integers" | |
| ) | |
| if sensor_id < 0 or sensor_id >= len(predictions): | |
| raise ValueError( | |
| f"Invalid sensor ID: {sensor_id}" | |
| ) | |
| # Extract predictions for this phase | |
| phase_predictions = [ | |
| float(predictions[sensor_id]) | |
| for sensor_id in sensor_ids | |
| ] | |
| # GNN predictions represent predicted traffic demand. | |
| # | |
| # We clamp negative values to zero because traffic | |
| # demand cannot be negative. | |
| phase_predictions = [ | |
| max(0.0, value) | |
| for value in phase_predictions | |
| ] | |
| # Use the average predicted demand for the phase. | |
| phase_prediction = ( | |
| sum(phase_predictions) | |
| / len(phase_predictions) | |
| ) | |
| return phase_prediction | |
| def select_best_phase(self, phase_scores): | |
| """ | |
| Select the phase with the highest score. | |
| phase_scores: | |
| { | |
| phase_id: score | |
| } | |
| """ | |
| if not phase_scores: | |
| raise ValueError( | |
| "No phase scores were provided" | |
| ) | |
| best_phase = max( | |
| phase_scores, | |
| key=phase_scores.get | |
| ) | |
| return { | |
| "selected_phase": best_phase, | |
| "score": phase_scores[best_phase], | |
| "all_scores": phase_scores | |
| } | |
| if __name__ == "__main__": | |
| engine = DecisionEngine() | |
| # Example GNN prediction | |
| predictions = [ | |
| 0.8, | |
| 0.4, | |
| 0.2, | |
| 0.6 | |
| ] | |
| # Example phase prediction | |
| phase_prediction = engine.calculate_phase_prediction( | |
| predictions, | |
| sensor_ids=[0, 1] | |
| ) | |
| print("Phase prediction:") | |
| print(phase_prediction) | |
| # Example phase scores | |
| phase_scores = { | |
| "Phase_1": engine.calculate_phase_score( | |
| demand=0.80, | |
| prediction=phase_prediction, | |
| priority=0.20, | |
| fairness=0.60, | |
| risk=0.10 | |
| ), | |
| "Phase_2": engine.calculate_phase_score( | |
| demand=0.40, | |
| prediction=0.50, | |
| priority=0.90, | |
| fairness=0.80, | |
| risk=0.20 | |
| ), | |
| "Phase_3": engine.calculate_phase_score( | |
| demand=0.60, | |
| prediction=0.60, | |
| priority=0.30, | |
| fairness=0.40, | |
| risk=0.10 | |
| ) | |
| } | |
| result = engine.select_best_phase( | |
| phase_scores | |
| ) | |
| print() | |
| print("Phase scores:") | |
| print(phase_scores) | |
| print() | |
| print("Decision:") | |
| print(result) |