Coverage for mlos_core/mlos_core/tests/spaces/adapters/llamatune_test.py: 99%

172 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-01-21 01:50 +0000

1# 

2# Copyright (c) Microsoft Corporation. 

3# Licensed under the MIT License. 

4# 

5"""Tests for LlamaTune space adapter.""" 

6 

7# pylint: disable=missing-function-docstring 

8 

9from collections.abc import Iterator 

10from typing import Any 

11 

12import ConfigSpace as CS 

13import pandas as pd 

14import pytest 

15 

16from mlos_core.spaces.adapters import LlamaTuneAdapter 

17from mlos_core.spaces.converters.util import ( 

18 QUANTIZATION_BINS_META_KEY, 

19 monkey_patch_cs_quantization, 

20) 

21 

22# Explicitly test quantized values with llamatune space adapter. 

23# TODO: Add log scale sampling tests as well. 

24 

25 

26def construct_parameter_space( # pylint: disable=too-many-arguments 

27 *, 

28 n_continuous_params: int = 0, 

29 n_quantized_continuous_params: int = 0, 

30 n_integer_params: int = 0, 

31 n_quantized_integer_params: int = 0, 

32 n_categorical_params: int = 0, 

33 seed: int = 1234, 

34) -> CS.ConfigurationSpace: 

35 """Helper function for construct an instance of `ConfigSpace.ConfigurationSpace`.""" 

36 input_space = CS.ConfigurationSpace( 

37 seed=seed, 

38 space=[ 

39 *( 

40 CS.UniformFloatHyperparameter(name=f"cont_{idx}", lower=0, upper=64) 

41 for idx in range(n_continuous_params) 

42 ), 

43 *( 

44 CS.UniformFloatHyperparameter( 

45 name=f"cont_{idx}", lower=0, upper=64, meta={QUANTIZATION_BINS_META_KEY: 6} 

46 ) 

47 for idx in range(n_quantized_continuous_params) 

48 ), 

49 *( 

50 CS.UniformIntegerHyperparameter(name=f"int_{idx}", lower=-1, upper=256) 

51 for idx in range(n_integer_params) 

52 ), 

53 *( 

54 CS.UniformIntegerHyperparameter( 

55 name=f"int_{idx}", lower=0, upper=256, meta={QUANTIZATION_BINS_META_KEY: 17} 

56 ) 

57 for idx in range(n_quantized_integer_params) 

58 ), 

59 *( 

60 CS.CategoricalHyperparameter( 

61 name=f"str_{idx}", choices=[f"option_{idx}" for idx in range(5)] 

62 ) 

63 for idx in range(n_categorical_params) 

64 ), 

65 ], 

66 ) 

67 return monkey_patch_cs_quantization(input_space) 

68 

69 

70@pytest.mark.parametrize( 

71 ("num_target_space_dims", "param_space_kwargs"), 

72 ( 

73 [ 

74 (num_target_space_dims, param_space_kwargs) 

75 for num_target_space_dims in (2, 4) 

76 for num_orig_space_factor in (1.5, 4) 

77 for param_space_kwargs in ( 

78 {"n_continuous_params": int(num_target_space_dims * num_orig_space_factor)}, 

79 {"n_integer_params": int(num_target_space_dims * num_orig_space_factor)}, 

80 {"n_categorical_params": int(num_target_space_dims * num_orig_space_factor)}, 

81 {"n_categorical_params": int(num_target_space_dims * num_orig_space_factor)}, 

82 {"n_quantized_integer_params": int(num_target_space_dims * num_orig_space_factor)}, 

83 { 

84 "n_quantized_continuous_params": int( 

85 num_target_space_dims * num_orig_space_factor 

86 ) 

87 }, 

88 # Mix of all three types 

89 { 

90 "n_continuous_params": int(num_target_space_dims * num_orig_space_factor / 3), 

91 "n_integer_params": int(num_target_space_dims * num_orig_space_factor / 3), 

92 "n_categorical_params": int(num_target_space_dims * num_orig_space_factor / 3), 

93 }, 

94 ) 

95 ] 

96 ), 

97) 

98def test_num_low_dims( 

99 num_target_space_dims: int, 

100 param_space_kwargs: dict, 

101) -> None: # pylint: disable=too-many-locals 

102 """Tests LlamaTune's low-to-high space projection method.""" 

103 input_space = construct_parameter_space(**param_space_kwargs) 

104 

105 # Number of target parameter space dimensions should be fewer than those of the original space 

106 with pytest.raises(ValueError): 

107 LlamaTuneAdapter( 

108 orig_parameter_space=input_space, num_low_dims=len(list(input_space.keys())) 

109 ) 

110 

111 # Enable only low-dimensional space projections 

112 adapter = LlamaTuneAdapter( 

113 orig_parameter_space=input_space, 

114 num_low_dims=num_target_space_dims, 

115 special_param_values=None, 

116 max_unique_values_per_param=None, 

117 ) 

118 

119 sampled_configs = adapter.target_parameter_space.sample_configuration(size=100) 

120 for sampled_config in sampled_configs: # pylint: disable=not-an-iterable # (false positive) 

121 # Transform low-dim config to high-dim point/config 

122 sampled_config_sr = pd.Series(dict(sampled_config)) 

123 orig_config_sr = adapter.transform(sampled_config_sr) 

124 

125 # High-dim (i.e., original) config should be valid 

126 orig_config = CS.Configuration(input_space, values=orig_config_sr.to_dict()) 

127 orig_config.check_valid_configuration() 

128 

129 # Transform high-dim config back to low-dim 

130 target_config_sr = adapter.inverse_transform(orig_config_sr) 

131 

132 # Sampled config and this should be the same 

133 target_config = CS.Configuration( 

134 adapter.target_parameter_space, 

135 values=target_config_sr.to_dict(), 

136 ) 

137 assert target_config == sampled_config 

138 

139 # Try inverse projection (i.e., high-to-low) for previously unseen configs 

140 unseen_sampled_configs = adapter.target_parameter_space.sample_configuration(size=25) 

141 for ( 

142 unseen_sampled_config 

143 ) in unseen_sampled_configs: # pylint: disable=not-an-iterable # (false positive) 

144 if ( 

145 unseen_sampled_config 

146 in sampled_configs # pylint: disable=unsupported-membership-test # (false positive) 

147 ): 

148 continue 

149 

150 unseen_sampled_config_sr = pd.Series(dict(unseen_sampled_config)) 

151 with pytest.raises(ValueError): 

152 _ = adapter.inverse_transform( 

153 unseen_sampled_config_sr 

154 ) # pylint: disable=redefined-variable-type 

155 

156 

157def test_special_parameter_values_validation() -> None: 

158 """Tests LlamaTune's validation process of user-provided special parameter values 

159 dictionary. 

160 """ 

161 input_space = CS.ConfigurationSpace(seed=1234) 

162 input_space.add( 

163 CS.CategoricalHyperparameter(name="str", choices=[f"choice_{idx}" for idx in range(5)]) 

164 ) 

165 input_space.add(CS.UniformFloatHyperparameter(name="cont", lower=-1, upper=100)) 

166 input_space.add(CS.UniformIntegerHyperparameter(name="int", lower=0, upper=100)) 

167 

168 # Only UniformIntegerHyperparameters are currently supported 

169 with pytest.raises(NotImplementedError): 

170 special_param_values_dict_1 = {"str": "choice_1"} 

171 LlamaTuneAdapter( 

172 orig_parameter_space=input_space, 

173 num_low_dims=2, 

174 special_param_values=special_param_values_dict_1, 

175 max_unique_values_per_param=None, 

176 ) 

177 

178 with pytest.raises(NotImplementedError): 

179 special_param_values_dict_2 = {"cont": -1} 

180 LlamaTuneAdapter( 

181 orig_parameter_space=input_space, 

182 num_low_dims=2, 

183 special_param_values=special_param_values_dict_2, 

184 max_unique_values_per_param=None, 

185 ) 

186 

187 # Special value should belong to parameter value domain 

188 with pytest.raises(ValueError, match="value domain"): 

189 special_param_values_dict = {"int": -1} 

190 LlamaTuneAdapter( 

191 orig_parameter_space=input_space, 

192 num_low_dims=2, 

193 special_param_values=special_param_values_dict, 

194 max_unique_values_per_param=None, 

195 ) 

196 

197 # Invalid dicts; ValueError should be thrown 

198 invalid_special_param_values_dicts: list[dict[str, Any]] = [ 

199 {"int-Q": 0}, # parameter does not exist 

200 {"int": {0: 0.2}}, # invalid definition 

201 {"int": 0.2}, # invalid parameter value 

202 {"int": (0.4, 0)}, # (biasing %, special value) instead of (special value, biasing %) 

203 {"int": [0, 0]}, # duplicate special values 

204 {"int": []}, # empty list 

205 {"int": [{0: 0.2}]}, 

206 {"int": [(0.4, 0), (1, 0.7)]}, # first tuple is inverted; second is correct 

207 {"int": [(0, 0.1), (0, 0.2)]}, # duplicate special values 

208 ] 

209 for spv_dict in invalid_special_param_values_dicts: 

210 with pytest.raises(ValueError): 

211 LlamaTuneAdapter( 

212 orig_parameter_space=input_space, 

213 num_low_dims=2, 

214 special_param_values=spv_dict, 

215 max_unique_values_per_param=None, 

216 ) 

217 

218 # Biasing percentage of special value(s) are invalid 

219 invalid_special_param_values_dicts = [ 

220 {"int": (0, 1.1)}, # >1 probability 

221 {"int": (0, 0)}, # Zero probability 

222 {"int": (0, -0.1)}, # Negative probability 

223 {"int": (0, 20)}, # 2,000% instead of 20% 

224 {"int": [0, 1, 2, 3, 4, 5]}, # default biasing is 20%; 6 values * 20% > 100% 

225 {"int": [(0, 0.4), (1, 0.7)]}, # combined probability >100% 

226 {"int": [(0, -0.4), (1, 0.7)]}, # probability for value 0 is invalid. 

227 ] 

228 

229 for spv_dict in invalid_special_param_values_dicts: 

230 with pytest.raises(ValueError): 

231 LlamaTuneAdapter( 

232 orig_parameter_space=input_space, 

233 num_low_dims=2, 

234 special_param_values=spv_dict, 

235 max_unique_values_per_param=None, 

236 ) 

237 

238 

239def gen_random_configs(adapter: LlamaTuneAdapter, num_configs: int) -> Iterator[CS.Configuration]: 

240 for sampled_config in adapter.target_parameter_space.sample_configuration(size=num_configs): 

241 # Transform low-dim config to high-dim config 

242 sampled_config_sr = pd.Series(dict(sampled_config)) 

243 orig_config_sr = adapter.transform(sampled_config_sr) 

244 orig_config = CS.Configuration( 

245 adapter.orig_parameter_space, 

246 values=orig_config_sr.to_dict(), 

247 ) 

248 yield orig_config 

249 

250 

251def test_special_parameter_values_biasing() -> None: # pylint: disable=too-complex 

252 """Tests LlamaTune's special parameter values biasing methodology.""" 

253 input_space = CS.ConfigurationSpace(seed=1234) 

254 input_space.add(CS.UniformIntegerHyperparameter(name="int_1", lower=0, upper=100)) 

255 input_space.add(CS.UniformIntegerHyperparameter(name="int_2", lower=0, upper=100)) 

256 

257 num_configs = 400 

258 bias_percentage = LlamaTuneAdapter.DEFAULT_SPECIAL_PARAM_VALUE_BIASING_PERCENTAGE 

259 eps = 0.2 

260 

261 # Single parameter; single special value 

262 special_param_value_dicts: list[dict[str, Any]] = [ 

263 {"int_1": 0}, 

264 {"int_1": (0, bias_percentage)}, 

265 {"int_1": [0]}, 

266 {"int_1": [(0, bias_percentage)]}, 

267 ] 

268 

269 for spv_dict in special_param_value_dicts: 

270 adapter = LlamaTuneAdapter( 

271 orig_parameter_space=input_space, 

272 num_low_dims=1, 

273 special_param_values=spv_dict, 

274 max_unique_values_per_param=None, 

275 ) 

276 

277 special_value_occurrences = sum( 

278 1 for config in gen_random_configs(adapter, num_configs) if config["int_1"] == 0 

279 ) 

280 assert (1 - eps) * int(num_configs * bias_percentage) <= special_value_occurrences 

281 

282 # Single parameter; multiple special values 

283 special_param_value_dicts = [ 

284 {"int_1": [0, 1]}, 

285 {"int_1": [(0, bias_percentage), (1, bias_percentage)]}, 

286 ] 

287 

288 for spv_dict in special_param_value_dicts: 

289 adapter = LlamaTuneAdapter( 

290 orig_parameter_space=input_space, 

291 num_low_dims=1, 

292 special_param_values=spv_dict, 

293 max_unique_values_per_param=None, 

294 ) 

295 

296 special_values_occurrences = {0: 0, 1: 0} 

297 for config in gen_random_configs(adapter, num_configs): 

298 if config["int_1"] == 0: 

299 special_values_occurrences[0] += 1 

300 elif config["int_1"] == 1: 

301 special_values_occurrences[1] += 1 

302 

303 assert (1 - eps) * int(num_configs * bias_percentage) <= special_values_occurrences[0] 

304 assert (1 - eps) * int(num_configs * bias_percentage) <= special_values_occurrences[1] 

305 

306 # Multiple parameters; multiple special values; different biasing percentage 

307 spv_dict = { 

308 "int_1": [(0, bias_percentage), (1, bias_percentage / 2)], 

309 "int_2": [(2, bias_percentage / 2), (100, bias_percentage * 1.5)], 

310 } 

311 adapter = LlamaTuneAdapter( 

312 orig_parameter_space=input_space, 

313 num_low_dims=1, 

314 special_param_values=spv_dict, 

315 max_unique_values_per_param=None, 

316 ) 

317 

318 special_values_instances: dict[str, dict[int, int]] = { 

319 "int_1": {0: 0, 1: 0}, 

320 "int_2": {2: 0, 100: 0}, 

321 } 

322 for config in gen_random_configs(adapter, num_configs): 

323 if config["int_1"] == 0: 

324 special_values_instances["int_1"][0] += 1 

325 elif config["int_1"] == 1: 

326 special_values_instances["int_1"][1] += 1 

327 

328 if config["int_2"] == 2: 

329 special_values_instances["int_2"][2] += 1 

330 elif config["int_2"] == 100: 

331 special_values_instances["int_2"][100] += 1 

332 

333 assert (1 - eps) * int(num_configs * bias_percentage) <= special_values_instances["int_1"][0] 

334 assert (1 - eps) * int(num_configs * bias_percentage / 2) <= ( 

335 special_values_instances["int_1"][1] 

336 ) 

337 assert (1 - eps) * int(num_configs * bias_percentage / 2) <= ( 

338 special_values_instances["int_2"][2] 

339 ) 

340 assert (1 - eps) * int(num_configs * bias_percentage * 1.5) <= ( 

341 special_values_instances["int_2"][100] 

342 ) 

343 

344 

345def test_max_unique_values_per_param() -> None: 

346 """Tests LlamaTune's parameter values discretization implementation.""" 

347 # Define config space with a mix of different parameter types 

348 input_space = CS.ConfigurationSpace(seed=1234) 

349 input_space.add( 

350 CS.UniformFloatHyperparameter(name="cont_1", lower=0, upper=5), 

351 ) 

352 input_space.add(CS.UniformFloatHyperparameter(name="cont_2", lower=1, upper=100)) 

353 input_space.add(CS.UniformIntegerHyperparameter(name="int_1", lower=1, upper=10)) 

354 input_space.add(CS.UniformIntegerHyperparameter(name="int_2", lower=0, upper=2048)) 

355 input_space.add(CS.CategoricalHyperparameter(name="str_1", choices=["on", "off"])) 

356 input_space.add( 

357 CS.CategoricalHyperparameter(name="str_2", choices=[f"choice_{idx}" for idx in range(10)]) 

358 ) 

359 

360 # Restrict the number of unique parameter values 

361 num_configs = 200 

362 for max_unique_values_per_param in (5, 25, 100): 

363 adapter = LlamaTuneAdapter( 

364 orig_parameter_space=input_space, 

365 num_low_dims=3, 

366 special_param_values=None, 

367 max_unique_values_per_param=max_unique_values_per_param, 

368 ) 

369 

370 # Keep track of unique values generated for each parameter 

371 unique_values_dict: dict[str, set] = {param: set() for param in list(input_space.keys())} 

372 for config in gen_random_configs(adapter, num_configs): 

373 for param, value in config.items(): 

374 unique_values_dict[param].add(value) 

375 

376 # Ensure that their number is less than the maximum number allowed 

377 for _, unique_values in unique_values_dict.items(): 

378 assert len(unique_values) <= max_unique_values_per_param 

379 

380 

381@pytest.mark.parametrize( 

382 ("num_target_space_dims", "param_space_kwargs"), 

383 ( 

384 [ 

385 (num_target_space_dims, param_space_kwargs) 

386 for num_target_space_dims in (2, 4) 

387 for num_orig_space_factor in (1.5, 4) 

388 for param_space_kwargs in ( 

389 {"n_continuous_params": int(num_target_space_dims * num_orig_space_factor)}, 

390 {"n_integer_params": int(num_target_space_dims * num_orig_space_factor)}, 

391 {"n_categorical_params": int(num_target_space_dims * num_orig_space_factor)}, 

392 {"n_quantized_integer_params": int(num_target_space_dims * num_orig_space_factor)}, 

393 { 

394 "n_quantized_continuous_params": int( 

395 num_target_space_dims * num_orig_space_factor 

396 ) 

397 }, 

398 # Mix of all three types 

399 { 

400 "n_continuous_params": int(num_target_space_dims * num_orig_space_factor / 3), 

401 "n_integer_params": int(num_target_space_dims * num_orig_space_factor / 3), 

402 "n_categorical_params": int(num_target_space_dims * num_orig_space_factor / 3), 

403 }, 

404 ) 

405 ] 

406 ), 

407) 

408def test_approx_inverse_mapping( 

409 num_target_space_dims: int, 

410 param_space_kwargs: dict, 

411) -> None: # pylint: disable=too-many-locals 

412 """Tests LlamaTune's approximate high-to-low space projection method, using pseudo- 

413 inverse. 

414 """ 

415 input_space = construct_parameter_space(**param_space_kwargs) 

416 

417 # Enable low-dimensional space projection, but disable reverse mapping 

418 adapter = LlamaTuneAdapter( 

419 orig_parameter_space=input_space, 

420 num_low_dims=num_target_space_dims, 

421 special_param_values=None, 

422 max_unique_values_per_param=None, 

423 use_approximate_reverse_mapping=False, 

424 ) 

425 

426 sampled_config = input_space.sample_configuration() # size=1) 

427 with pytest.raises(ValueError): 

428 sampled_config_sr = pd.Series(dict(sampled_config)) 

429 _ = adapter.inverse_transform(sampled_config_sr) 

430 

431 # Enable low-dimensional space projection *and* reverse mapping 

432 adapter = LlamaTuneAdapter( 

433 orig_parameter_space=input_space, 

434 num_low_dims=num_target_space_dims, 

435 special_param_values=None, 

436 max_unique_values_per_param=None, 

437 use_approximate_reverse_mapping=True, 

438 ) 

439 

440 # Warning should be printed the first time 

441 sampled_config = input_space.sample_configuration() # size=1) 

442 with pytest.warns(UserWarning): 

443 sampled_config_sr = pd.Series(dict(sampled_config)) 

444 target_config_sr = adapter.inverse_transform(sampled_config_sr) 

445 # Low-dim (i.e., target) config should be valid 

446 target_config = CS.Configuration( 

447 adapter.target_parameter_space, 

448 values=target_config_sr.to_dict(), 

449 ) 

450 target_config.check_valid_configuration() 

451 

452 # Test inverse transform with 100 random configs 

453 for _ in range(100): 

454 sampled_config = input_space.sample_configuration() # size=1) 

455 sampled_config_sr = pd.Series(dict(sampled_config)) 

456 target_config_sr = adapter.inverse_transform(sampled_config_sr) 

457 # Low-dim (i.e., target) config should be valid 

458 target_config = CS.Configuration( 

459 adapter.target_parameter_space, 

460 values=target_config_sr.to_dict(), 

461 ) 

462 target_config.check_valid_configuration() 

463 

464 

465@pytest.mark.parametrize( 

466 ("num_low_dims", "special_param_values", "max_unique_values_per_param"), 

467 ( 

468 [ 

469 (num_low_dims, special_param_values, max_unique_values_per_param) 

470 for num_low_dims in (8, 16) 

471 for special_param_values in ( 

472 {"int_1": -1, "int_2": -1, "int_3": -1, "int_4": [-1, 0]}, 

473 { 

474 "int_1": (-1, 0.1), 

475 "int_2": -1, 

476 "int_3": (-1, 0.3), 

477 "int_4": [(-1, 0.1), (0, 0.2)], 

478 }, 

479 ) 

480 for max_unique_values_per_param in (50, 250) 

481 ] 

482 ), 

483) 

484def test_llamatune_pipeline( 

485 num_low_dims: int, 

486 special_param_values: dict, 

487 max_unique_values_per_param: int, 

488) -> None: 

489 """Tests LlamaTune space adapter when all components are active.""" 

490 # pylint: disable=too-many-locals 

491 

492 # Define config space with a mix of different parameter types 

493 input_space = construct_parameter_space( 

494 n_continuous_params=10, 

495 n_integer_params=10, 

496 n_categorical_params=5, 

497 ) 

498 adapter = LlamaTuneAdapter( 

499 orig_parameter_space=input_space, 

500 num_low_dims=num_low_dims, 

501 special_param_values=special_param_values, 

502 max_unique_values_per_param=max_unique_values_per_param, 

503 ) 

504 

505 special_value_occurrences = { 

506 # pylint: disable=protected-access 

507 param: {special_value: 0 for special_value, _ in tuples_list} 

508 for param, tuples_list in adapter._special_param_values_dict.items() 

509 } 

510 unique_values_dict: dict[str, set] = {param: set() for param in input_space.keys()} 

511 

512 num_configs = 1000 

513 for ( 

514 config 

515 ) in adapter.target_parameter_space.sample_configuration( # pylint: disable=not-an-iterable 

516 size=num_configs 

517 ): 

518 # Transform low-dim config to high-dim point/config 

519 sampled_config_sr = pd.Series(dict(config)) 

520 orig_config_sr = adapter.transform(sampled_config_sr) 

521 # High-dim (i.e., original) config should be valid 

522 orig_config = CS.Configuration(input_space, values=orig_config_sr.to_dict()) 

523 orig_config.check_valid_configuration() 

524 

525 # Transform high-dim config back to low-dim 

526 target_config_sr = adapter.inverse_transform(orig_config_sr) 

527 # Sampled config and this should be the same 

528 target_config = CS.Configuration( 

529 adapter.target_parameter_space, 

530 values=target_config_sr.to_dict(), 

531 ) 

532 assert target_config == config 

533 

534 for param, value in orig_config.items(): 

535 # Keep track of special value occurrences 

536 if param in special_value_occurrences: 

537 if value in special_value_occurrences[param]: 

538 special_value_occurrences[param][value] += 1 

539 

540 # Keep track of unique values generated for each parameter 

541 unique_values_dict[param].add(value) 

542 

543 # Ensure that occurrences of special values do not significantly deviate from expected 

544 eps = 0.2 

545 for ( 

546 param, 

547 tuples_list, 

548 ) in adapter._special_param_values_dict.items(): # pylint: disable=protected-access 

549 for value, bias_percentage in tuples_list: 

550 assert (1 - eps) * int(num_configs * bias_percentage) <= special_value_occurrences[ 

551 param 

552 ][value] 

553 

554 # Ensure that number of unique values is less than the maximum number allowed 

555 for _, unique_values in unique_values_dict.items(): 

556 assert len(unique_values) <= max_unique_values_per_param 

557 

558 

559@pytest.mark.parametrize( 

560 ("num_target_space_dims", "param_space_kwargs"), 

561 ( 

562 [ 

563 (num_target_space_dims, param_space_kwargs) 

564 for num_target_space_dims in (2, 4) 

565 for num_orig_space_factor in (1.5, 4) 

566 for param_space_kwargs in ( 

567 {"n_continuous_params": int(num_target_space_dims * num_orig_space_factor)}, 

568 {"n_integer_params": int(num_target_space_dims * num_orig_space_factor)}, 

569 {"n_categorical_params": int(num_target_space_dims * num_orig_space_factor)}, 

570 # Mix of all three types 

571 { 

572 "n_continuous_params": int(num_target_space_dims * num_orig_space_factor / 3), 

573 "n_integer_params": int(num_target_space_dims * num_orig_space_factor / 3), 

574 "n_categorical_params": int(num_target_space_dims * num_orig_space_factor / 3), 

575 }, 

576 ) 

577 ] 

578 ), 

579) 

580def test_deterministic_behavior_for_same_seed( 

581 num_target_space_dims: int, 

582 param_space_kwargs: dict, 

583) -> None: 

584 """Tests LlamaTune's space adapter deterministic behavior when given same seed in 

585 the input parameter space. 

586 """ 

587 

588 def generate_target_param_space_configs(seed: int) -> list[CS.Configuration]: 

589 input_space = construct_parameter_space(**param_space_kwargs, seed=seed) 

590 

591 # Init adapter and sample points in the low-dim space 

592 adapter = LlamaTuneAdapter( 

593 orig_parameter_space=input_space, 

594 num_low_dims=num_target_space_dims, 

595 special_param_values=None, 

596 max_unique_values_per_param=None, 

597 use_approximate_reverse_mapping=False, 

598 ) 

599 

600 sample_configs: list[CS.Configuration] = ( 

601 adapter.target_parameter_space.sample_configuration(size=100) 

602 ) 

603 return sample_configs 

604 

605 assert generate_target_param_space_configs(42) == generate_target_param_space_configs(42) 

606 assert generate_target_param_space_configs(1234) != generate_target_param_space_configs(42)