""" Autonomous Recommendations AI generates action plans automatically """ from typing import Dict, List, Optional, Tuple from dataclasses import dataclass from datetime import datetime @dataclass class ActionPlan: """An autonomous action plan""" plan_id: str target_goal: str budget_usd: float actions: List[Dict] expected_outcome: Dict confidence: float timeline_months: int def to_dict(self) -> Dict: return { "plan_id": self.plan_id, "target_goal": self.target_goal, "budget_usd": self.budget_usd, "actions": self.actions, "expected_outcome": self.expected_outcome, "confidence": round(self.confidence, 2), "timeline_months": self.timeline_months } class AutonomousRecommendationEngine: """Generates autonomous action plans""" def __init__(self): self.action_library = self._load_action_library() def _load_action_library(self) -> Dict: """Load available actions and their effects""" return { "replace_lighting": { "name": "Replace street lighting with LED", "cost_per_unit": 5000, "typical_units": 100, "effects": { "safety_index": +15, "night_activity": +20, "energy_efficiency": +25 }, "timeline_months": 4 }, "repair_sidewalks": { "name": "Repair damaged sidewalks", "cost_per_unit": 2000, "typical_units": 50, "effects": { "walkability": +20, "safety_index": +10, "accessibility": +15 }, "timeline_months": 3 }, "plant_trees": { "name": "Plant trees along streets", "cost_per_unit": 500, "typical_units": 40, "effects": { "shade_index": +25, "heat_stress": -15, "walkability": +10, "property_value": +5 }, "timeline_months": 12 }, "remove_graffiti": { "name": "Remove graffiti and paint walls", "cost_per_unit": 1000, "typical_units": 20, "effects": { "visual_maintenance": +30, "safety_index": +8, "property_value": +3 }, "timeline_months": 1 }, "add_bike_lanes": { "name": "Add dedicated bike lanes", "cost_per_unit": 15000, "typical_units": 10, "effects": { "bicycle_friendliness": +40, "walkability": +10, "traffic_intensity": -5 }, "timeline_months": 6 }, "improve_crossings": { "name": "Improve pedestrian crossings", "cost_per_unit": 3000, "typical_units": 15, "effects": { "walkability": +15, "safety_index": +12, "accessibility": +10 }, "timeline_months": 2 } } def generate_plan( self, target_goal: str, current_state: Dict[str, float], budget_usd: float, constraints: Optional[Dict] = None ) -> ActionPlan: """ Generate autonomous action plan Example: "Increase safety by 15% within 25M SEK budget" """ # Parse goal target_metric, target_improvement = self._parse_goal(target_goal) # Select best actions selected_actions = self._select_actions( target_metric, target_improvement, current_state, budget_usd ) # Calculate expected outcome expected_outcome = self._calculate_outcome(current_state, selected_actions) # Calculate confidence confidence = self._calculate_confidence(selected_actions, target_improvement) # Calculate timeline timeline = max(a["timeline_months"] for a in selected_actions) if selected_actions else 12 return ActionPlan( plan_id=f"PLAN-{datetime.utcnow().strftime('%Y%m%d-%H%M%S')}", target_goal=target_goal, budget_usd=budget_usd, actions=selected_actions, expected_outcome=expected_outcome, confidence=confidence, timeline_months=timeline ) def _parse_goal(self, goal: str) -> Tuple[str, float]: """Parse goal string""" # Simple parsing if "safety" in goal.lower(): return "safety_index", 15 elif "family" in goal.lower(): return "family_friendly", 12 elif "walk" in goal.lower(): return "walkability", 20 elif "green" in goal.lower(): return "greenery", 25 else: return "safety_index", 15 def _select_actions( self, target_metric: str, target_improvement: float, current_state: Dict[str, float], budget_usd: float ) -> List[Dict]: """Select best actions to achieve goal""" candidates = [] for action_id, action in self.action_library.items(): # Calculate effect on target metric effect = action["effects"].get(target_metric, 0) if effect > 0: cost = action["cost_per_unit"] * action["typical_units"] efficiency = effect / max(cost / 100000, 1) candidates.append({ "action_id": action_id, "name": action["name"], "cost": cost, "effect": effect, "efficiency": efficiency, "timeline_months": action["timeline_months"], "units": action["typical_units"] }) # Sort by efficiency candidates.sort(key=lambda x: x["efficiency"], reverse=True) # Select actions within budget selected = [] total_cost = 0 total_effect = 0 for candidate in candidates: if total_cost + candidate["cost"] <= budget_usd and total_effect < target_improvement: selected.append(candidate) total_cost += candidate["cost"] total_effect += candidate["effect"] return selected def _calculate_outcome( self, current_state: Dict[str, float], actions: List[Dict] ) -> Dict: """Calculate expected outcome""" outcome = current_state.copy() for action in actions: action_id = action["action_id"] action_def = self.action_library.get(action_id, {}) for metric, effect in action_def.get("effects", {}).items(): if metric in outcome: outcome[metric] = min(100, outcome[metric] + effect) return {k: round(v, 1) for k, v in outcome.items()} def _calculate_confidence(self, actions: List[Dict], target: float) -> float: """Calculate confidence in plan""" if not actions: return 0 # More actions = higher confidence action_confidence = min(0.9, len(actions) / 5) # Higher total effect = higher confidence total_effect = sum(a["effect"] for a in actions) effect_confidence = min(0.9, total_effect / target) if target > 0 else 0.5 return (action_confidence + effect_confidence) / 2 def optimize_budget( self, target_goal: str, current_state: Dict[str, float], budget_range: List[float] ) -> List[Dict]: """ Compare plans at different budget levels Returns: List of plans with different budgets """ plans = [] for budget in budget_range: plan = self.generate_plan(target_goal, current_state, budget) plans.append({ "budget": budget, "actions_count": len(plan.actions), "expected_improvement": self._get_improvement(current_state, plan.expected_outcome), "confidence": plan.confidence, "timeline_months": plan.timeline_months, "cost_per_improvement": budget / max(self._get_improvement(current_state, plan.expected_outcome), 1) }) return plans def _get_improvement( self, baseline: Dict[str, float], outcome: Dict[str, float] ) -> float: """Calculate total improvement""" improvements = [] for metric, baseline_value in baseline.items(): if metric in outcome: improvement = outcome[metric] - baseline_value improvements.append(improvement) return sum(improvements) / len(improvements) if improvements else 0 # Example usage def example_autonomous_plan(): """Example: Generate autonomous action plan""" engine = AutonomousRecommendationEngine() # Current state current_state = { "safety_index": 45, "walkability": 60, "night_activity": 35, "energy_efficiency": 40, "greenery": 25, "heat_stress": 80, "visual_maintenance": 30, "bicycle_friendliness": 30, "accessibility": 50 } # Generate plan print("=== Autonomous Action Plan ===") plan = engine.generate_plan( target_goal="Increase safety by 15%", current_state=current_state, budget_usd=25000000 # 25M SEK ≈ 2.5M USD ) print(f"Plan ID: {plan.plan_id}") print(f"Goal: {plan.target_goal}") print(f"Budget: ${plan.budget_usd:,}") print(f"Timeline: {plan.timeline_months} months") print(f"Confidence: {plan.confidence}") print("\nActions:") for i, action in enumerate(plan.actions, 1): print(f" {i}. {action['name']}") print(f" Cost: ${action['cost']:,}") print(f" Effect: +{action['effect']} safety") print(f" Timeline: {action['timeline_months']} months") print("\nExpected Outcome:") for metric, value in plan.expected_outcome.items(): old_value = current_state.get(metric, 0) if value != old_value: print(f" {metric}: {old_value} → {value} ({value - old_value:+.1f})") # Budget optimization print("\n=== Budget Optimization ===") budgets = [1000000, 2500000, 5000000, 10000000] comparisons = engine.optimize_budget("Increase safety", current_state, budgets) print("Budget | Actions | Improvement | Confidence | Cost/Eff") print("-" * 60) for comp in comparisons: print(f"${comp['budget']:>8,} | {comp['actions_count']:>7} | {comp['expected_improvement']:>11.1f} | {comp['confidence']:>10.2f} | ${comp['cost_per_improvement']:>7.0f}") return plan if __name__ == '__main__': example_autonomous_plan()