@@ -44,6 +44,7 @@ def setUp(self) -> None:
44
44
weights = get_weights ()
45
45
self .status_quo = arms [0 ]
46
46
self .sq_weight = weights [0 ]
47
+ self .new_sq = Arm (parameters = {"w" : 0.95 , "x" : 1 , "y" : "foo" , "z" : True })
47
48
self .arms = arms [1 :]
48
49
self .weights = weights [1 :]
49
50
self .batch .add_arms_and_weights (arms = self .arms , weights = self .weights )
@@ -145,7 +146,6 @@ def test_InitWithGeneratorRun(self) -> None:
145
146
self .assertEqual (len (self .batch .generator_run_structs ), 1 )
146
147
147
148
def test_StatusQuoOverlap (self ) -> None :
148
- new_sq = Arm (parameters = {"w" : 0.95 , "x" : 1 , "y" : "foo" , "z" : True })
149
149
# Set status quo to existing arm
150
150
self .batch .set_status_quo_with_weight (self .arms [0 ], self .sq_weight )
151
151
# Status quo weight is set to the average of other arms' weights.
@@ -158,36 +158,40 @@ def test_StatusQuoOverlap(self) -> None:
158
158
self .assertEqual (sum (self .batch .weights ), self .weights [1 ] + self .sq_weight )
159
159
160
160
# Set status quo to new arm, add it
161
- self .batch .set_status_quo_with_weight (new_sq , self .sq_weight )
161
+ self .batch .set_status_quo_with_weight (self . new_sq , self .sq_weight )
162
162
self .assertEqual (self .batch .status_quo .name , "status_quo_0" )
163
- self .batch .add_arms_and_weights ([new_sq ])
163
+ self .batch .add_arms_and_weights ([self . new_sq ])
164
164
self .assertEqual (
165
165
self .batch .generator_run_structs [1 ].generator_run .arms [0 ].name ,
166
166
"status_quo_0" ,
167
167
)
168
168
169
- def test_StatusQuo (self ) -> None :
170
- tot_weight = sum (self .batch .weights )
171
- new_sq = Arm (parameters = {"w" : 0.95 , "x" : 1 , "y" : "foo" , "z" : True })
172
-
173
- # Test negative weight
169
+ def test_status_quo_cannot_have_negative_weight (self ) -> None :
174
170
with self .assertRaises (ValueError ):
175
- self .batch .set_status_quo_with_weight (new_sq , - 1 )
171
+ self .batch .set_status_quo_with_weight (self . new_sq , - 1 )
176
172
173
+ def test_status_quo_cannot_be_set_directly (self ) -> None :
177
174
# Test that directly setting the status quo raises an error
178
175
with self .assertRaises (NotImplementedError ):
179
- self .batch .status_quo = new_sq
176
+ self .batch .status_quo = self . new_sq
180
177
178
+ def test_status_quo_can_be_set_to_a_new_arm (self ) -> None :
179
+ tot_weight = sum (self .batch .weights )
181
180
# Set status quo to new arm
182
- self .batch .set_status_quo_with_weight (new_sq , self .sq_weight )
183
- self .assertTrue (self .batch .status_quo == new_sq )
181
+ self .batch .set_status_quo_with_weight (self . new_sq , self .sq_weight )
182
+ self .assertTrue (self .batch .status_quo == self . new_sq )
184
183
self .assertEqual (self .batch .status_quo .name , "status_quo_0" )
185
184
self .assertEqual (sum (self .batch .weights ), tot_weight + self .sq_weight )
185
+
186
+ def test_status_quo_weight_is_ignored_when_none (self ) -> None :
187
+ tot_weight = sum (self .batch .weights )
186
188
# sq weight should be ignored when sq is None
187
189
self .batch .unset_status_quo ()
188
190
self .assertEqual (sum (self .batch .weights ), tot_weight )
191
+ self .assertIsNone (self .batch .status_quo )
192
+ self .assertIsNone (self .batch ._status_quo_weight_override )
189
193
190
- # Verify experiment status quo gets set on init
194
+ def test_status_quo_set_on_clone ( self ) -> None :
191
195
self .experiment .status_quo = self .status_quo
192
196
batch2 = self .batch .clone ()
193
197
self .assertEqual (batch2 .status_quo , self .experiment .status_quo )
@@ -198,24 +202,30 @@ def test_StatusQuo(self) -> None:
198
202
self .assertTrue (batch2 .status_quo not in batch2 .arm_weights )
199
203
self .assertEqual (sum (batch2 .weights ), sum (self .weights ))
200
204
201
- # Try setting sq to existing arm with different name
205
+ def test_status_quo_cannot_be_set_with_different_name (self ) -> None :
206
+ # Set status quo to new arm
207
+ self .batch .set_status_quo_with_weight (self .status_quo , self .sq_weight )
202
208
with self .assertRaises (ValueError ):
203
209
self .batch .set_status_quo_with_weight (
204
- Arm (new_sq .parameters , name = "new_name" ), 1
210
+ Arm (self . status_quo .parameters , name = "new_name" ), 1
205
211
)
206
212
207
- def test_StatusQuoOptimizeForPower (self ) -> None :
213
+ def test_cannot_optimizer_for_power_without_status_quo (self ) -> None :
214
+ self .experiment .status_quo = None
215
+ with self .assertRaises (ValueError ):
216
+ self .experiment .new_batch_trial (optimize_for_power = True )
217
+
218
+ def test_opt_for_power_sq_weight_is_one_for_empty_trial (self ) -> None :
208
219
self .experiment .status_quo = self .status_quo
209
220
batch = self .experiment .new_batch_trial (optimize_for_power = True )
210
221
self .assertEqual (batch ._status_quo_weight_override , 1 )
211
222
212
- self .experiment .status_quo = None
213
- with self .assertRaises (ValueError ):
214
- batch = self .experiment .new_batch_trial (optimize_for_power = True )
215
-
216
223
batch .add_arms_and_weights (arms = [])
217
224
self .assertTrue (batch ._status_quo_weight_override , 1 )
218
225
226
+ def test_opt_for_power_sq_weight_is_sqrt_k (self ) -> None :
227
+ self .experiment .status_quo = self .status_quo
228
+ batch = self .experiment .new_batch_trial (optimize_for_power = True )
219
229
batch .add_arms_and_weights (arms = self .arms , weights = self .weights )
220
230
expected_status_quo_weight = math .sqrt (sum (self .weights ))
221
231
self .assertTrue (
@@ -227,6 +237,13 @@ def test_StatusQuoOptimizeForPower(self) -> None:
227
237
)
228
238
)
229
239
240
+ def test_cannot_opt_for_power_without_status_quo (self ) -> None :
241
+ self .experiment .status_quo = None
242
+ with self .assertRaisesRegex (
243
+ ValueError , "Can only optimize for power if experiment has a status quo."
244
+ ):
245
+ self .experiment .new_batch_trial (optimize_for_power = True )
246
+
230
247
def test_ArmsByName (self ) -> None :
231
248
# Initializes empty
232
249
newbatch = self .experiment .new_batch_trial ()
0 commit comments