hypergrid 0.0.1a1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 justin-yan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,25 @@
1
+ Metadata-Version: 2.1
2
+ Name: hypergrid
3
+ Version: 0.0.1a1
4
+ Summary: Hypergrid is a Python package for the concise declaration and manipulation of parameter grids, making hyperparameter optimization and batch job dispatch more manageable.
5
+ Author-email: Justin Yan <justin@iomorphic.com>
6
+ Project-URL: Homepage, https://github.com/justin-yan/hypergrid
7
+ Classifier: Development Status :: 2 - Pre-Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+
21
+ # hypergrid
22
+
23
+ Hypergrid is designed to enable concise declaration and manipulation of parameter grids possible, which are often required when tuning ML hyperparameters or defining large batch jobs.
24
+
25
+ Hypergrid allows you to easily define multi-dimensional parameter grids, and then combine them in various ways, including sum-types, product-types, and co-iteration. Once defined, you can easily map, filter, select, and apply arbitrary functions in order to easily compose and iterate over your grid.
@@ -0,0 +1,5 @@
1
+ # hypergrid
2
+
3
+ Hypergrid is designed to enable concise declaration and manipulation of parameter grids possible, which are often required when tuning ML hyperparameters or defining large batch jobs.
4
+
5
+ Hypergrid allows you to easily define multi-dimensional parameter grids, and then combine them in various ways, including sum-types, product-types, and co-iteration. Once defined, you can easily map, filter, select, and apply arbitrary functions in order to easily compose and iterate over your grid.
@@ -0,0 +1,68 @@
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "hypergrid"
7
+ version = "0.0.1a1"
8
+ authors = [
9
+ { name="Justin Yan", email="justin@iomorphic.com" }
10
+ ]
11
+ description = "Hypergrid is a Python package for the concise declaration and manipulation of parameter grids, making hyperparameter optimization and batch job dispatch more manageable."
12
+ readme = "README.md"
13
+ requires-python = ">=3.8"
14
+ classifiers = [
15
+ "Development Status :: 2 - Pre-Alpha",
16
+ "Intended Audience :: Developers",
17
+ "Operating System :: OS Independent",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.8",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ ]
26
+ dependencies = [
27
+ ]
28
+
29
+ [project.urls]
30
+ "Homepage" = "https://github.com/justin-yan/hypergrid"
31
+
32
+ [tool.setuptools]
33
+ zip-safe = false
34
+ include-package-data = true
35
+
36
+ [tool.setuptools.package-data]
37
+ "hypergrid" = ["py.typed"]
38
+
39
+ [tool.setuptools.packages.find]
40
+ where = ["src"]
41
+
42
+ #######
43
+ ### Miscellaneous Tool Configuration
44
+ #######
45
+ [tool.black]
46
+ line-length = 150
47
+ skip-string-normalization = true
48
+ target-version = ['py311']
49
+ include = '\.pyi?$'
50
+
51
+ [tool.ruff]
52
+ select = ["E", "F"]
53
+ line-length = 150
54
+ target-version = "py311"
55
+
56
+
57
+ [tool.pytest.ini_options]
58
+ addopts = "-ra -q"
59
+
60
+ [tool.mypy]
61
+ mypy_path = "src"
62
+ disallow_untyped_defs = true
63
+ disallow_any_unimported = true
64
+ no_implicit_optional = true
65
+ check_untyped_defs = true
66
+ warn_return_any = true
67
+ show_error_codes = true
68
+ warn_unused_ignores = true
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,211 @@
1
+ from __future__ import annotations
2
+
3
+ import itertools
4
+ from collections import OrderedDict, namedtuple
5
+ from typing import Any, Callable, List, Protocol
6
+
7
+
8
+ class IGrid(Protocol):
9
+ def __repr__(self) -> str:
10
+ ...
11
+
12
+ def __str__(self) -> str:
13
+ ...
14
+
15
+ def __iter__(self) -> Any:
16
+ ...
17
+
18
+ def __add__(self, other: IGrid) -> SumGrid:
19
+ return SumGrid(self, other)
20
+
21
+ def __mul__(self, other: IGrid) -> ProductGrid:
22
+ return ProductGrid(self, other)
23
+
24
+ def __and__(self, other: IGrid) -> CoGrid:
25
+ return CoGrid(self, other)
26
+
27
+ def apply(self, **kwargs: Callable[[Any], Any]) -> IGrid:
28
+ # TODO: what should we do if no lambda is provided?
29
+ # TODO: what should the expected signature of the lambda be? Should we unpack the namedtuple or receive a namedtuple instead?
30
+ applied_grids = []
31
+
32
+ for dim_name, transform in kwargs.items():
33
+ transformed_elements = [transform(grid_element) for grid_element in self]
34
+ new_grid = Grid(**{dim_name: transformed_elements})
35
+ applied_grids.append(new_grid)
36
+
37
+ final_co_grid: IGrid = applied_grids[0]
38
+ for grid in applied_grids[1:]:
39
+ final_co_grid = CoGrid(final_co_grid, grid)
40
+
41
+ return final_co_grid
42
+
43
+ def select(self, *dim_names: str) -> IGrid:
44
+ # TODO: what do we do if no dimnames are provided?
45
+ selected_elements: dict = {dim_name: [] for dim_name in dim_names}
46
+
47
+ for grid_element in self:
48
+ for dim_name in dim_names:
49
+ # TODO: How do we want to handle the case when a value isn't present?
50
+ selected_value = getattr(grid_element, dim_name)
51
+ selected_elements[dim_name].append(selected_value)
52
+
53
+ selected_grids = [Grid(**{dim_name: values}) for dim_name, values in selected_elements.items()]
54
+
55
+ final_co_grid: IGrid = selected_grids[0]
56
+ for grid in selected_grids[1:]:
57
+ final_co_grid = CoGrid(final_co_grid, grid)
58
+
59
+ return final_co_grid
60
+
61
+ def map(self, **kwargs: Callable[[Any], Any]) -> MapGrid:
62
+ return MapGrid(self, **kwargs)
63
+
64
+ def filter(self, predicate: Callable[[Any], bool]) -> FilterGrid:
65
+ return FilterGrid(self, predicate)
66
+
67
+
68
+ class SumGrid(IGrid):
69
+ def __init__(self, grid1: IGrid, grid2: IGrid) -> None:
70
+ self.grid1 = grid1
71
+ self.grid2 = grid2
72
+
73
+ def __repr__(self) -> str:
74
+ return f"SumGrid({repr(self.grid1)}, {repr(self.grid2)})"
75
+
76
+ def __str__(self) -> str:
77
+ return f"SumGrid({str(self.grid1)}, {str(self.grid2)})"
78
+
79
+ def __iter__(self) -> Any:
80
+ for grid_element in itertools.chain(self.grid1, self.grid2):
81
+ yield grid_element
82
+
83
+
84
+ class ProductGrid(IGrid):
85
+ # TODO: Make product grids fail if subdimensions collide? How does this work with things like maps, etc.?
86
+ def __init__(self, grid1: IGrid, grid2: IGrid) -> None:
87
+ self.grid1 = grid1
88
+ self.grid2 = grid2
89
+ self.namedtuple_cache: dict = {}
90
+
91
+ def __repr__(self) -> str:
92
+ return f"ProductGrid({repr(self.grid1)}, {repr(self.grid2)})"
93
+
94
+ def __str__(self) -> str:
95
+ return f"ProductGrid({str(self.grid1)}, {str(self.grid2)})"
96
+
97
+ def __iter__(self) -> Any:
98
+ # TODO: is there a way to do this without accessing private attributes?
99
+ for grid_element1, grid_element2 in itertools.product(self.grid1, self.grid2):
100
+ field_names1 = grid_element1._fields
101
+ field_names2 = grid_element2._fields
102
+ concatenated_field_names = list(field_names1) + list(field_names2)
103
+ field_names_key = tuple(concatenated_field_names)
104
+
105
+ if field_names_key not in self.namedtuple_cache:
106
+ self.namedtuple_cache[field_names_key] = namedtuple("GridElement", concatenated_field_names)
107
+
108
+ concatenated_namedtuple_class = self.namedtuple_cache[field_names_key]
109
+ concatenated_element = concatenated_namedtuple_class(*(grid_element1 + grid_element2))
110
+ yield concatenated_element
111
+
112
+
113
+ class Grid(IGrid):
114
+ dimensions: OrderedDict[str, List[Any]]
115
+
116
+ def __init__(self, **kwargs: List[Any]) -> None:
117
+ self.dimensions = OrderedDict()
118
+ for dim, values in kwargs.items():
119
+ self.dimensions[dim] = values
120
+
121
+ def __repr__(self) -> str:
122
+ dim_str = ", ".join([f"{dim}={values}" for dim, values in self.dimensions.items()])
123
+ return f"Grid({dim_str})"
124
+
125
+ def __str__(self) -> str:
126
+ return self.__repr__()
127
+
128
+ def __iter__(self) -> Any:
129
+ fieldnames: tuple = tuple(self.dimensions.keys())
130
+ namedtuple_class = namedtuple("GridElement", fieldnames) # type: ignore
131
+ for element_tuple in itertools.product(*self.dimensions.values()):
132
+ yield namedtuple_class(*element_tuple)
133
+
134
+
135
+ class GridShapeMismatchError(Exception):
136
+ pass
137
+
138
+
139
+ class CoGrid(IGrid):
140
+ def __init__(self, grid1: IGrid, grid2: IGrid) -> None:
141
+ if len(list(grid1)) == len(list(grid2)):
142
+ self.grid1 = grid1
143
+ self.grid2 = grid2
144
+ self.namedtuple_cache: dict = {}
145
+ else:
146
+ raise GridShapeMismatchError("The shapes of the input grids must be the same")
147
+
148
+ def __repr__(self) -> str:
149
+ return f"CoGrid({repr(self.grid1)}, {repr(self.grid2)})"
150
+
151
+ def __str__(self) -> str:
152
+ return f"CoGrid({str(self.grid1)}, {str(self.grid2)})"
153
+
154
+ def __iter__(self) -> Any:
155
+ for grid_element1, grid_element2 in zip(self.grid1, self.grid2):
156
+ field_names1 = grid_element1._fields
157
+ field_names2 = grid_element2._fields
158
+ concatenated_field_names = list(field_names1) + list(field_names2)
159
+ field_names_key = tuple(concatenated_field_names)
160
+
161
+ if field_names_key not in self.namedtuple_cache:
162
+ self.namedtuple_cache[field_names_key] = namedtuple("GridElement", concatenated_field_names)
163
+
164
+ concatenated_namedtuple_class = self.namedtuple_cache[field_names_key]
165
+ concatenated_element = concatenated_namedtuple_class(*(grid_element1 + grid_element2))
166
+ yield concatenated_element
167
+
168
+
169
+ class MapGrid(IGrid):
170
+ def __init__(self, grid: IGrid, **kwargs: Callable[[Any], Any]) -> None:
171
+ self.grid = grid
172
+ self.dimension_mapping = kwargs
173
+ self.namedtuple_cache: dict = {}
174
+
175
+ def __repr__(self) -> str:
176
+ mappings_str = ", ".join([f"{dim_name}={func.__name__}" for dim_name, func in self.dimension_mapping.items()])
177
+ return f"MapGrid({repr(self.grid)}, {mappings_str})"
178
+
179
+ def __str__(self) -> str:
180
+ return f"MapGrid({str(self.grid)}, {', '.join(self.dimension_mapping.keys())})"
181
+
182
+ def __iter__(self) -> Any:
183
+ for grid_element in self.grid:
184
+ new_values = {dim_name: func(grid_element) for dim_name, func in self.dimension_mapping.items()}
185
+ concatenated_values = tuple(grid_element) + tuple(new_values.values())
186
+ field_names = grid_element._fields + tuple(new_values.keys())
187
+
188
+ field_names_key = tuple(field_names)
189
+ if field_names_key not in self.namedtuple_cache:
190
+ self.namedtuple_cache[field_names_key] = namedtuple("GridElement", field_names)
191
+
192
+ concatenated_namedtuple_class = self.namedtuple_cache[field_names_key]
193
+ concatenated_element = concatenated_namedtuple_class(*concatenated_values)
194
+ yield concatenated_element
195
+
196
+
197
+ class FilterGrid(IGrid):
198
+ def __init__(self, grid: IGrid, predicate: Callable[[Any], bool]) -> None:
199
+ self.grid = grid
200
+ self.predicate = predicate
201
+
202
+ def __repr__(self) -> str:
203
+ return f"FilterGrid({repr(self.grid)}, {self.predicate.__name__})"
204
+
205
+ def __str__(self) -> str:
206
+ return f"FilterGrid({str(self.grid)}, {self.predicate.__name__})"
207
+
208
+ def __iter__(self) -> Any:
209
+ for grid_element in self.grid:
210
+ if self.predicate(grid_element):
211
+ yield grid_element
File without changes
@@ -0,0 +1,25 @@
1
+ Metadata-Version: 2.1
2
+ Name: hypergrid
3
+ Version: 0.0.1a1
4
+ Summary: Hypergrid is a Python package for the concise declaration and manipulation of parameter grids, making hyperparameter optimization and batch job dispatch more manageable.
5
+ Author-email: Justin Yan <justin@iomorphic.com>
6
+ Project-URL: Homepage, https://github.com/justin-yan/hypergrid
7
+ Classifier: Development Status :: 2 - Pre-Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+
21
+ # hypergrid
22
+
23
+ Hypergrid is designed to enable concise declaration and manipulation of parameter grids possible, which are often required when tuning ML hyperparameters or defining large batch jobs.
24
+
25
+ Hypergrid allows you to easily define multi-dimensional parameter grids, and then combine them in various ways, including sum-types, product-types, and co-iteration. Once defined, you can easily map, filter, select, and apply arbitrary functions in order to easily compose and iterate over your grid.
@@ -0,0 +1,11 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/hypergrid/__init__.py
5
+ src/hypergrid/grid.py
6
+ src/hypergrid/py.typed
7
+ src/hypergrid.egg-info/PKG-INFO
8
+ src/hypergrid.egg-info/SOURCES.txt
9
+ src/hypergrid.egg-info/dependency_links.txt
10
+ src/hypergrid.egg-info/not-zip-safe
11
+ src/hypergrid.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ hypergrid