1
|
|
|
""" |
2
|
|
|
Optional: |
3
|
|
|
|
4
|
|
|
It might make sense to use a class instead of a dictionary for the search-space. |
5
|
|
|
The search-space can have specifc properties, that can be computed from the params (previously called search-space-dictionary). |
6
|
|
|
The search-space can have a certain size, has n dimensions, some of which are numeric, some of which are categorical. |
7
|
|
|
""" |
8
|
|
|
|
9
|
|
|
from collections.abc import MutableMapping |
10
|
|
|
|
11
|
|
|
from ._properties import calculate_properties |
12
|
|
|
|
13
|
|
|
|
14
|
|
View Code Duplication |
class SearchSpaceDictLike(MutableMapping): |
|
|
|
|
15
|
|
|
_search_space: dict = None |
16
|
|
|
|
17
|
|
|
def __init__(self, **param_space): |
18
|
|
|
self._search_space = dict(**param_space) |
19
|
|
|
|
20
|
|
|
def __getitem__(self, key): |
21
|
|
|
return self._search_space[key] |
22
|
|
|
|
23
|
|
|
def __setitem__(self, key, value): |
24
|
|
|
self._search_space[key] = value |
25
|
|
|
|
26
|
|
|
def __delitem__(self, key): |
27
|
|
|
del self._search_space[key] |
28
|
|
|
|
29
|
|
|
def __iter__(self): |
30
|
|
|
return iter(self._search_space) |
31
|
|
|
|
32
|
|
|
def __len__(self): |
33
|
|
|
return len(self._search_space) |
34
|
|
|
|
35
|
|
|
def __repr__(self): |
36
|
|
|
return f"{self.__class__.__name__}({self._search_space})" |
37
|
|
|
|
38
|
|
|
def __call__(self): |
39
|
|
|
return self._search_space |
40
|
|
|
|
41
|
|
|
def keys(self): |
42
|
|
|
return self._search_space.keys() |
43
|
|
|
|
44
|
|
|
def values(self): |
45
|
|
|
return self._search_space.values() |
46
|
|
|
|
47
|
|
|
def items(self): |
48
|
|
|
return self._search_space.items() |
49
|
|
|
|
50
|
|
|
|
51
|
|
View Code Duplication |
class SearchSpace(SearchSpaceDictLike): |
|
|
|
|
52
|
|
|
|
53
|
|
|
@calculate_properties |
54
|
|
|
def __init__(self, **param_space): |
55
|
|
|
super().__init__(**param_space) |
56
|
|
|
|
57
|
|
|
for key, value in param_space.items(): |
58
|
|
|
setattr(self, key, value) |
59
|
|
|
|
60
|
|
|
@calculate_properties |
61
|
|
|
def __setitem__(self, key, value): |
62
|
|
|
SearchSpaceDictLike.__setitem__(self, key, value) |
63
|
|
|
|
64
|
|
|
@calculate_properties |
65
|
|
|
def __delitem__(self, key): |
66
|
|
|
SearchSpaceDictLike.__delitem__(self, key) |
67
|
|
|
|
68
|
|
|
def print(self, indent=2, max_list_length=5): |
69
|
|
|
""" |
70
|
|
|
Prints the dictionary in a readable format. |
71
|
|
|
|
72
|
|
|
Args: |
73
|
|
|
indent (int): The number of spaces to indent nested structures. |
74
|
|
|
max_list_length (int): The maximum number of items to display from long lists. |
75
|
|
|
""" |
76
|
|
|
|
77
|
|
|
def format_value(value, level=0): |
78
|
|
|
prefix = " " * (level * indent) |
79
|
|
|
if isinstance(value, list): |
80
|
|
|
if len(value) > max_list_length: |
81
|
|
|
# Truncate long lists for readability |
82
|
|
|
result = "[\n" |
83
|
|
|
result += "".join( |
84
|
|
|
f"{prefix}{' ' * indent}{repr(item)},\n" |
85
|
|
|
for item in value[:max_list_length] |
86
|
|
|
) |
87
|
|
|
result += f"{prefix}{' ' * indent}... ({len(value) - max_list_length} more items)\n" |
88
|
|
|
result += f"{prefix}]" |
89
|
|
|
else: |
90
|
|
|
result = "[\n" |
91
|
|
|
result += "".join( |
92
|
|
|
f"{prefix}{' ' * indent}{repr(item)},\n" |
93
|
|
|
for item in value |
94
|
|
|
) |
95
|
|
|
result += f"{prefix}]" |
96
|
|
|
elif isinstance(value, dict): |
97
|
|
|
# Format nested dictionaries |
98
|
|
|
result = "{\n" |
99
|
|
|
for k, v in value.items(): |
100
|
|
|
result += f"{prefix}{' ' * indent}{repr(k)}: {format_value(v, level + 1)},\n" |
101
|
|
|
result += f"{prefix}}}" |
102
|
|
|
else: |
103
|
|
|
result = repr(value) |
104
|
|
|
return result |
105
|
|
|
|
106
|
|
|
for key, value in self.items(): |
107
|
|
|
print(f"{key}: {format_value(value)}") |
108
|
|
|
|