feat: add baseline scores JSON, inference script, and update Dockerfile for improved project structure
6d74982 | // Package env defines all data models for the GridMind-RL environment. | |
| package env | |
| // BatchJob represents a pending industrial/commercial batch process job. | |
| type BatchJob struct { | |
| ID int `json:"id"` // Unique job identifier | |
| DeadlineSlot int `json:"deadline_slot"` // Latest timestep by which the job must run | |
| Duration int `json:"duration"` // Steps the job takes to complete | |
| PowerDraw float64 `json:"power_draw"` // kW drawn when job is running | |
| Scheduled bool `json:"scheduled"` // Whether a time slot has been assigned | |
| ScheduledAt int `json:"scheduled_at"` // Timestep at which job was scheduled (-1 if not yet) | |
| Completed bool `json:"completed"` // Whether the job finished execution | |
| MissedDeadline bool `json:"missed_deadline"` // True if deadline was exceeded | |
| } | |
| // BuildingState holds the full simulation state for a single building. | |
| type BuildingState struct { | |
| // Core physical state | |
| IndoorTemperature float64 `json:"indoor_temperature"` // °C | |
| ThermalStorageLevel float64 `json:"thermal_storage_level"` // 0.0–1.0 normalized | |
| ProcessDemand float64 `json:"process_demand"` // kW current process need | |
| // Market & grid signals | |
| CurrentPrice float64 `json:"current_price"` // $/kWh | |
| GridStressSignal float64 `json:"grid_stress_signal"` // 0.0–1.0 (DR urgency) | |
| CarbonIntensity float64 `json:"carbon_intensity"` // gCO2/kWh | |
| // Temporal | |
| HourOfDay int `json:"hour_of_day"` // 0–23 | |
| Step int `json:"step"` // 0–95 within a 96-step (24h) episode | |
| // Batch job queue: pending deadlines (raw slots) | |
| BatchQueue []int `json:"batch_queue"` // deadline slots of pending jobs | |
| // Running cost tracker | |
| CumulativeCost float64 `json:"cumulative_cost"` // $ total this episode | |
| CumulativeCarbon float64 `json:"cumulative_carbon"` // gCO2 total this episode | |
| // Internal tracking (not exposed in observation) | |
| Jobs []BatchJob `json:"-"` | |
| OutdoorTemperature float64 `json:"-"` // °C for weather perturbation | |
| PrevHVACLevel float64 `json:"-"` // for stability penalty | |
| BaselineCost float64 `json:"-"` // always-on policy running cost | |
| BaselineCarbon float64 `json:"-"` // baseline policy gCO2 (for grading) | |
| SetpointTemperature float64 `json:"-"` // target indoor temp (°C) | |
| MaxHVACPower float64 `json:"-"` // kW | |
| MaxStorageCapacity float64 `json:"-"` // kWh | |
| ThermalLossRate float64 `json:"-"` // fraction lost per step | |
| BuildingID int `json:"-"` // which building in federation | |
| } | |
| // ObservationModel is the JSON-serializable observation returned on each step/state. | |
| type ObservationModel struct { | |
| IndoorTemperature float64 `json:"indoor_temperature"` | |
| ThermalStorageLevel float64 `json:"thermal_storage_level"` | |
| ProcessDemand float64 `json:"process_demand"` | |
| CurrentPrice float64 `json:"current_price"` | |
| GridStressSignal float64 `json:"grid_stress_signal"` | |
| CarbonIntensity float64 `json:"carbon_intensity"` | |
| HourOfDay int `json:"hour_of_day"` | |
| BatchQueue []int `json:"batch_queue"` | |
| CumulativeCost float64 `json:"cumulative_cost"` | |
| Step int `json:"step"` | |
| BuildingID int `json:"building_id"` | |
| } | |
| // ActionModel is the parsed agent action for a single step. | |
| type ActionModel struct { | |
| HVACPowerLevel float64 `json:"hvac_power_level"` // 0.0–1.0 | |
| ThermalChargeRate float64 `json:"thermal_charge_rate"` // -1.0 to 1.0 | |
| BatchJobSlot int `json:"batch_job_slot"` // 0–4 (0=now, 1–4=defer) | |
| LoadShedFraction float64 `json:"load_shed_fraction"` // 0.0–0.5 | |
| BuildingID int `json:"building_id"` // which building to act on | |
| } | |
| // RewardComponents holds the individual components of the dense reward signal. | |
| type RewardComponents struct { | |
| CostSavings float64 `json:"cost_savings"` // negative = expensive | |
| TempConstraint float64 `json:"temp_constraint"` // positive = within bounds | |
| GridResponse float64 `json:"grid_response"` // bonus for DR compliance | |
| DeadlinePenalty float64 `json:"deadline_penalty"` // negative for missed jobs | |
| EfficiencyBonus float64 `json:"efficiency_bonus"` // storage arbitrage | |
| StabilityPenalty float64 `json:"stability_penalty"` // HVAC oscillation penalty | |
| CarbonReward float64 `json:"carbon_reward"` // low-carbon bonus | |
| Total float64 `json:"total"` | |
| } | |
| // StepResponse is the full HTTP body returned from POST /step. | |
| type StepResponse struct { | |
| Observation ObservationModel `json:"observation"` | |
| Reward float64 `json:"reward"` | |
| Done bool `json:"done"` | |
| Info StepInfo `json:"info"` | |
| } | |
| // StepInfo carries auxiliary information per step. | |
| type StepInfo struct { | |
| RewardComponents RewardComponents `json:"reward_components"` | |
| EnergyUsed float64 `json:"energy_used_kwh"` | |
| CarbonEmitted float64 `json:"carbon_emitted_gco2"` | |
| PriceSignal float64 `json:"price_signal"` | |
| GridStress float64 `json:"grid_stress"` | |
| BatchCompleted []int `json:"batch_completed"` // IDs completed this step | |
| BatchMissed []int `json:"batch_missed"` // IDs that missed deadline | |
| Episode int `json:"episode"` | |
| Step int `json:"step"` | |
| } | |
| // ResetRequest is the JSON body for POST /reset. | |
| type ResetRequest struct { | |
| Seed *int64 `json:"seed,omitempty"` // optional random seed | |
| TaskID int `json:"task_id"` // 1, 2, or 3 | |
| Difficulty string `json:"difficulty,omitempty"` // "easy", "medium", "hard" or "" (auto) | |
| NumBuildings int `json:"num_buildings,omitempty"` // 1–3 for federation | |
| } | |
| // ResetResponse is returned from POST /reset. | |
| type ResetResponse struct { | |
| Observations []ObservationModel `json:"observations"` // one per building | |
| Episode int `json:"episode"` | |
| TaskID int `json:"task_id"` | |
| Seed int64 `json:"seed"` | |
| } | |
| // StateResponse is returned from GET /state. | |
| type StateResponse struct { | |
| Buildings []BuildingStatePublic `json:"buildings"` | |
| PriceCurve []float64 `json:"price_curve_episode"` // full episode ToU prices | |
| CarbonCurve []float64 `json:"carbon_curve_episode"` // full episode carbon intensities | |
| Episode int `json:"episode"` | |
| Step int `json:"step"` | |
| TaskID int `json:"task_id"` | |
| Done bool `json:"done"` | |
| Seed int64 `json:"seed"` | |
| } | |
| // BuildingStatePublic is the dashboard-friendly full state per building. | |
| type BuildingStatePublic struct { | |
| ObservationModel | |
| OutdoorTemperature float64 `json:"outdoor_temperature"` | |
| SetpointTemperature float64 `json:"setpoint_temperature"` | |
| BaselineCost float64 `json:"baseline_cost"` | |
| BaselineCarbon float64 `json:"baseline_carbon"` | |
| CumulativeCarbon float64 `json:"cumulative_carbon"` | |
| Jobs []BatchJob `json:"jobs"` | |
| // History for chart rendering | |
| TempHistory []float64 `json:"temp_history"` | |
| CostHistory []float64 `json:"cost_history"` | |
| HVACHistory []float64 `json:"hvac_history"` | |
| LoadShedHistory []float64 `json:"load_shed_history"` | |
| RewardHistory []RewardComponents `json:"reward_history"` | |
| } | |
| // ReplayEntry records a single timestep for episode replay export. | |
| type ReplayEntry struct { | |
| Step int `json:"step"` | |
| Observation ObservationModel `json:"observation"` | |
| Action ActionModel `json:"action"` | |
| Reward float64 `json:"reward"` | |
| Components RewardComponents `json:"components"` | |
| Done bool `json:"done"` | |
| } | |
| // EpisodeGrade is the final grade returned for a completed episode. | |
| type EpisodeGrade struct { | |
| TaskID int `json:"task_id"` | |
| Score float64 `json:"score"` // 0.0–1.0 | |
| SubScores map[string]float64 `json:"sub_scores"` | |
| ExploitDetected bool `json:"exploit_detected"` | |
| PenaltyApplied float64 `json:"penalty_applied"` | |
| Details map[string]interface{} `json:"details"` | |
| } | |