DHDRL commited on
Commit
4265fdb
·
verified ·
1 Parent(s): cf0d95b

Update zone_observation.py

Browse files
Files changed (1) hide show
  1. zone_observation.py +59 -0
zone_observation.py CHANGED
@@ -143,6 +143,9 @@ class ForecastConfig:
143
  belief_update_radius: int = 2 # spatial propagation radius (zone cells)
144
  belief_increase_rate: float = 0.30 # update magnitude when event confirmed
145
  belief_decrease_rate: float = 0.05 # update magnitude when event absent
 
 
 
146
 
147
  # --- Economics ---
148
  alert_value: float = 100.0 # reward for correct advisory issuance
@@ -154,6 +157,10 @@ class ForecastConfig:
154
  zone_visit_bonus: float = 1.5 # raw bonus, first visit to a zone only
155
  unvisited_zone_penalty: float = 40.0 # raw penalty * (unvisited/active) at terminate
156
 
 
 
 
 
157
  economic_randomization: bool = False
158
  clean_episode_ratio: float = 0.7
159
  event_spatial_correlation: float = 0.85
@@ -194,6 +201,20 @@ class ForecastConfig:
194
  raise ValueError(f"ForecastConfig: zone_visit_bonus must be >= 0")
195
  if self.unvisited_zone_penalty < 0:
196
  raise ValueError(f"ForecastConfig: unvisited_zone_penalty must be >= 0")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  if self.horizon_days < 1:
198
  raise ValueError(f"ForecastConfig: horizon_days must be >= 1")
199
  if self.n_zones < 1:
@@ -230,6 +251,10 @@ class ForecastConfig:
230
  self.inspection_cost = float(_clip(self.inspection_cost, 0.01, 1_000.0))
231
  self.zone_visit_bonus = float(_clip(self.zone_visit_bonus, 0.0, 1_000.0))
232
  self.unvisited_zone_penalty = float(_clip(self.unvisited_zone_penalty, 0.0, 10_000.0))
 
 
 
 
233
  self.prior_belief = float(_clip(self.prior_belief, 0.001, 0.999))
234
  self.belief_floor = float(_clip(self.belief_floor, 0.001, 0.5))
235
  self.clean_episode_ratio = float(_clip(self.clean_episode_ratio, 0.0, 1.0))
@@ -263,12 +288,16 @@ class ForecastConfig:
263
  "belief_update_radius": self.belief_update_radius,
264
  "belief_increase_rate": self.belief_increase_rate,
265
  "belief_decrease_rate": self.belief_decrease_rate,
 
266
  "alert_value": self.alert_value,
267
  "false_alert_penalty": self.false_alert_penalty,
268
  "miss_penalty": self.miss_penalty,
269
  "inspection_cost": self.inspection_cost,
270
  "zone_visit_bonus": self.zone_visit_bonus,
271
  "unvisited_zone_penalty": self.unvisited_zone_penalty,
 
 
 
272
  "economic_randomization": self.economic_randomization,
273
  "clean_episode_ratio": self.clean_episode_ratio,
274
  "event_spatial_correlation": self.event_spatial_correlation,
@@ -1378,6 +1407,36 @@ if __name__ == "__main__":
1378
  _assert(False, "ForecastConfig accepted invalid forecast_backend")
1379
  except ValueError:
1380
  pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1381
  print(f" ForecastConfig rational_threshold={cfg.rational_termination_threshold:.4f}"
1382
  f" belief_floor={cfg.belief_floor:.4f} pipeline fields OK")
1383
 
 
143
  belief_update_radius: int = 2 # spatial propagation radius (zone cells)
144
  belief_increase_rate: float = 0.30 # update magnitude when event confirmed
145
  belief_decrease_rate: float = 0.05 # update magnitude when event absent
146
+ belief_prior_weight: float = 0.70 # weight on episode prior vs. zone signal when
147
+ # seeding zone_belief at reset:
148
+ # prior_w*prior + (1-prior_w)*signal
149
 
150
  # --- Economics ---
151
  alert_value: float = 100.0 # reward for correct advisory issuance
 
157
  zone_visit_bonus: float = 1.5 # raw bonus, first visit to a zone only
158
  unvisited_zone_penalty: float = 40.0 # raw penalty * (unvisited/active) at terminate
159
 
160
+ uncertainty_decay: float = 0.70 # forecast_uncertainty[zone] *= this on inspection
161
+ info_gain_scale: float = 5.0 # multiplier on belief info-gain in step reward
162
+ uncertainty_penalty_scale: float = 5.0 # multiplier on mean uncertainty at termination
163
+
164
  economic_randomization: bool = False
165
  clean_episode_ratio: float = 0.7
166
  event_spatial_correlation: float = 0.85
 
201
  raise ValueError(f"ForecastConfig: zone_visit_bonus must be >= 0")
202
  if self.unvisited_zone_penalty < 0:
203
  raise ValueError(f"ForecastConfig: unvisited_zone_penalty must be >= 0")
204
+ if not (0.0 <= self.belief_prior_weight <= 1.0):
205
+ raise ValueError(
206
+ f"ForecastConfig: belief_prior_weight={self.belief_prior_weight} "
207
+ f"must be in [0, 1]"
208
+ )
209
+ if not (0.0 <= self.uncertainty_decay <= 1.0):
210
+ raise ValueError(
211
+ f"ForecastConfig: uncertainty_decay={self.uncertainty_decay} "
212
+ f"must be in [0, 1]"
213
+ )
214
+ if self.info_gain_scale < 0:
215
+ raise ValueError(f"ForecastConfig: info_gain_scale must be >= 0")
216
+ if self.uncertainty_penalty_scale < 0:
217
+ raise ValueError(f"ForecastConfig: uncertainty_penalty_scale must be >= 0")
218
  if self.horizon_days < 1:
219
  raise ValueError(f"ForecastConfig: horizon_days must be >= 1")
220
  if self.n_zones < 1:
 
251
  self.inspection_cost = float(_clip(self.inspection_cost, 0.01, 1_000.0))
252
  self.zone_visit_bonus = float(_clip(self.zone_visit_bonus, 0.0, 1_000.0))
253
  self.unvisited_zone_penalty = float(_clip(self.unvisited_zone_penalty, 0.0, 10_000.0))
254
+ self.belief_prior_weight = float(_clip(self.belief_prior_weight, 0.0, 1.0))
255
+ self.uncertainty_decay = float(_clip(self.uncertainty_decay, 0.0, 1.0))
256
+ self.info_gain_scale = float(_clip(self.info_gain_scale, 0.0, 1_000.0))
257
+ self.uncertainty_penalty_scale = float(_clip(self.uncertainty_penalty_scale, 0.0, 1_000.0))
258
  self.prior_belief = float(_clip(self.prior_belief, 0.001, 0.999))
259
  self.belief_floor = float(_clip(self.belief_floor, 0.001, 0.5))
260
  self.clean_episode_ratio = float(_clip(self.clean_episode_ratio, 0.0, 1.0))
 
288
  "belief_update_radius": self.belief_update_radius,
289
  "belief_increase_rate": self.belief_increase_rate,
290
  "belief_decrease_rate": self.belief_decrease_rate,
291
+ "belief_prior_weight": self.belief_prior_weight,
292
  "alert_value": self.alert_value,
293
  "false_alert_penalty": self.false_alert_penalty,
294
  "miss_penalty": self.miss_penalty,
295
  "inspection_cost": self.inspection_cost,
296
  "zone_visit_bonus": self.zone_visit_bonus,
297
  "unvisited_zone_penalty": self.unvisited_zone_penalty,
298
+ "uncertainty_decay": self.uncertainty_decay,
299
+ "info_gain_scale": self.info_gain_scale,
300
+ "uncertainty_penalty_scale": self.uncertainty_penalty_scale,
301
  "economic_randomization": self.economic_randomization,
302
  "clean_episode_ratio": self.clean_episode_ratio,
303
  "event_spatial_correlation": self.event_spatial_correlation,
 
1407
  _assert(False, "ForecastConfig accepted invalid forecast_backend")
1408
  except ValueError:
1409
  pass
1410
+
1411
+ _assert(cfg2.belief_prior_weight == 0.70, "belief_prior_weight default round-trip")
1412
+ _assert(cfg2.uncertainty_decay == 0.70, "uncertainty_decay default round-trip")
1413
+ _assert(cfg2.info_gain_scale == 5.0, "info_gain_scale default round-trip")
1414
+ _assert(cfg2.uncertainty_penalty_scale == 5.0, "uncertainty_penalty_scale default round-trip")
1415
+ cfg_belief = ForecastConfig(
1416
+ belief_prior_weight=0.35,
1417
+ uncertainty_decay=0.5,
1418
+ info_gain_scale=2.0,
1419
+ uncertainty_penalty_scale=8.0,
1420
+ )
1421
+ cfg_belief_back = ForecastConfig.from_dict(cfg_belief.to_dict())
1422
+ _assert(cfg_belief_back.belief_prior_weight == 0.35,
1423
+ "non-default belief_prior_weight round-trip")
1424
+ _assert(cfg_belief_back.uncertainty_decay == 0.5,
1425
+ "non-default uncertainty_decay round-trip")
1426
+ _assert(cfg_belief_back.info_gain_scale == 2.0,
1427
+ "non-default info_gain_scale round-trip")
1428
+ _assert(cfg_belief_back.uncertainty_penalty_scale == 8.0,
1429
+ "non-default uncertainty_penalty_scale round-trip")
1430
+ try:
1431
+ ForecastConfig(belief_prior_weight=1.5)
1432
+ _assert(False, "ForecastConfig accepted belief_prior_weight out of [0,1]")
1433
+ except ValueError:
1434
+ pass
1435
+ try:
1436
+ ForecastConfig(info_gain_scale=-1.0)
1437
+ _assert(False, "ForecastConfig accepted negative info_gain_scale")
1438
+ except ValueError:
1439
+ pass
1440
  print(f" ForecastConfig rational_threshold={cfg.rational_termination_threshold:.4f}"
1441
  f" belief_floor={cfg.belief_floor:.4f} pipeline fields OK")
1442