Coverage for o2/actions/batching_actions/random_action.py: 99%
75 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-05-16 11:18 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-05-16 11:18 +0000
1import random
2from typing import Union
4from typing_extensions import override
6from o2.actions.base_actions.add_datetime_rule_base_action import (
7 AddDateTimeRuleAction,
8 AddDateTimeRuleBaseActionParamsType,
9)
10from o2.actions.base_actions.add_ready_large_wt_rule_base_action import (
11 AddReadyLargeWTRuleAction,
12 AddReadyLargeWTRuleBaseActionParamsType,
13)
14from o2.actions.base_actions.add_size_rule_base_action import (
15 AddSizeRuleAction,
16 AddSizeRuleBaseActionParamsType,
17)
18from o2.actions.base_actions.base_action import (
19 BaseAction,
20 BaseActionParamsType,
21 RateSelfReturnType,
22)
23from o2.actions.base_actions.modify_size_rule_base_action import (
24 ModifySizeRuleAction,
25 ModifySizeRuleBaseActionParamsType,
26)
27from o2.actions.batching_actions.modify_daily_hour_rule_action import (
28 ModifyDailyHourRuleAction,
29 ModifyDailyHourRuleActionParamsType,
30)
31from o2.actions.batching_actions.remove_rule_action import (
32 RemoveRuleAction,
33 RemoveRuleActionParamsType,
34)
35from o2.models.days import DAYS
36from o2.models.self_rating import RATING
37from o2.models.settings import Settings
38from o2.models.solution import Solution
39from o2.models.timetable import RULE_TYPE
40from o2.models.timetable.time_period import TimePeriod
41from o2.store import Store
43ACTIONS: list[type[BaseAction]] = [
44 AddDateTimeRuleAction,
45 AddReadyLargeWTRuleAction,
46 AddSizeRuleAction,
47 ModifyDailyHourRuleAction,
48 ModifySizeRuleAction,
49 RemoveRuleAction,
50]
53class RandomActionParamsType(BaseActionParamsType):
54 """Parameter for RandomAction."""
56 pass
59class RandomAction(BaseAction):
60 """RandomAction will randomly select an action and apply it to the timetable.
62 This is only used by the Random Agents.
63 """
65 params: RandomActionParamsType
67 @override
68 @staticmethod
69 def rate_self(store: Store, input: Solution) -> RateSelfReturnType:
70 timetable = input.timetable
71 params: Union[BaseActionParamsType, None] = None
73 # We generate infinite actions
74 while True:
75 # Randomly select an action
76 action = random.choice(ACTIONS)
78 if action == AddDateTimeRuleAction:
79 task_id = random.choice(timetable.get_task_ids())
80 random_day = random.choice(DAYS)
81 random_start_time = random.randint(0, 23)
82 end_time = random_start_time + 1
83 time_period = TimePeriod.from_start_end(random_start_time, end_time, random_day)
84 duration_fn = store.constraints.get_duration_fn_for_task(task_id)
86 params = AddDateTimeRuleBaseActionParamsType(
87 task_id=task_id,
88 time_period=time_period,
89 duration_fn=duration_fn,
90 )
91 elif action == AddReadyLargeWTRuleAction:
92 task_id = random.choice(timetable.get_task_ids())
93 waiting_time = random.randint(1, 24 * 60 * 60)
94 rule_type = random.choice([RULE_TYPE.LARGE_WT, RULE_TYPE.READY_WT])
95 duration_fn = store.constraints.get_duration_fn_for_task(task_id)
96 params = AddReadyLargeWTRuleBaseActionParamsType(
97 task_id=task_id,
98 waiting_time=waiting_time,
99 type=rule_type, # type: ignore
100 duration_fn=duration_fn,
101 )
102 elif action == AddSizeRuleAction:
103 task_id = random.choice(timetable.get_task_ids())
104 size = 2
105 duration_fn = store.constraints.get_duration_fn_for_task(task_id)
106 params = AddSizeRuleBaseActionParamsType(
107 task_id=task_id,
108 size=size,
109 duration_fn=duration_fn,
110 )
111 elif action == ModifyDailyHourRuleAction:
112 all_daily_hour_rule_selectors = [
113 rule_selector
114 for batching_rule in timetable.batch_processing
115 for rule_selector in batching_rule.get_firing_rule_selectors(RULE_TYPE.DAILY_HOUR)
116 ]
117 if not all_daily_hour_rule_selectors:
118 continue
119 hour_increment = random.choice([-1, 1])
120 random_rule_selector = random.choice(all_daily_hour_rule_selectors)
121 params = ModifyDailyHourRuleActionParamsType(
122 rule=random_rule_selector,
123 hour_increment=hour_increment,
124 duration_fn=store.constraints.get_duration_fn_for_task(
125 random_rule_selector.batching_rule_task_id
126 ),
127 )
128 elif action == ModifySizeRuleAction:
129 all_size_rule_selectors = [
130 rule_selector
131 for batching_rule in timetable.batch_processing
132 for rule_selector in batching_rule.get_firing_rule_selectors(RULE_TYPE.SIZE)
133 ]
134 if not all_size_rule_selectors:
135 continue
136 random_rule_selector = random.choice(all_size_rule_selectors)
137 task_id = random.choice(timetable.get_task_ids())
138 size_increment = random.choice([-1, 1])
139 duration_fn = store.constraints.get_duration_fn_for_task(task_id)
140 params = ModifySizeRuleBaseActionParamsType(
141 rule=random_rule_selector,
142 size_increment=size_increment,
143 duration_fn=duration_fn,
144 )
145 elif action == RemoveRuleAction:
146 if Settings.DISABLE_REMOVE_ACTION_RULE:
147 continue
148 all_rule_selectors = [
149 rule_selector
150 for batching_rule in timetable.batch_processing
151 for rule_selector in batching_rule.get_firing_rule_selectors()
152 ]
153 if not all_rule_selectors:
154 continue
155 random_rule_selector = random.choice(all_rule_selectors)
156 duration_fn = store.constraints.get_duration_fn_for_task(
157 random_rule_selector.batching_rule_task_id
158 )
159 params = RemoveRuleActionParamsType(rule=random_rule_selector, duration_fn=duration_fn)
160 else:
161 raise ValueError(f"Unknown action: {action}")
163 yield (RATING.HIGH, action(params))