1- # What's New in v0.8.0
2-
3- Pyribs v0.8.0 adds support for several new algorithms while making it easier
4- than ever to design new ones. Below we highlight some of the most notable
5- updates. For the full list of changes, please refer to our History page.
6-
7- ## 🧠 New Algorithms
8-
9- Pyribs v0.8.0 introduces implementations of several new algorithms:
10-
11- - ** Novelty Search**
12- ([ Lehman 2011] ( https://web.archive.org/web/20220707041732/https://eplex.cs.ucf.edu/papers/lehman_ecj11.pdf ) )
13- via the {class}` ~ribs.archives.ProximityArchive ` . We illustrate how to run
14- Novelty Search in our new tutorial, {doc}` /tutorials/ns_maze ` . Visualization
15- is available via {func}` ~ribs.visualize.proximity_archive_plot ` .
16- - Thanks to [ @gresavage ] ( https://github.com/gresavage ) for helping with this
17- implementation!
18- - ** Density Descent Search**
19- ([ Lee 2024] ( https://dl.acm.org/doi/10.1145/3638529.3654001 ) ) via the
20- {class}` ~ribs.archives.DensityArchive ` . We illustrate how to run Density
21- Descent Search in {doc}` examples/sphere ` .
22- - ** BOP-Elites**
23- ([ Kent 2024] ( https://ieeexplore.ieee.org/abstract/document/10472301 ) ) via
24- {class}` ~ribs.emitters.BayesianOptimizationEmitter ` and
25- {class}` ~ribs.schedulers.BayesianOptimizationScheduler ` . An example of running
26- BOP-Elites is available in the example here: {doc}` examples/bop_elites ` .
27- - As part of implementing BOP-Elites, a new
28- {class}` ~ribs.archives.GridArchive.retessellate ` method has been added to
29- GridArchive to allow changing the layout of the grid.
30- - Thanks to [ @szhaovas ] ( https://github.com/szhaovas ) for working on this
31- implementation!
32-
33- We have also added a {class}` ~ribs.archives.CategoricalArchive ` where the
34- measures can be categorical values, e.g., ` ["Cat", "Dog", "Mouse"] ` .
35-
36- The {doc}` supported-algorithms ` page now includes a list of algorithms supported
37- in pyribs.
38-
39- ## 📜 Single-File Implementations for Archives
40-
41- To make it easier to understand current archives and create new archives, we
42- have made each archive into a "single-file implementation." Previously,
43- {class}` ~ribs.archives.ArchiveBase ` contained a lot of archive logic. While this
44- made it easier to share code between archives, it also made it harder to
45- understand each archive's implementation. For instance, the implementation for
46- {class}` ~ribs.archives.GridArchive ` was split between the GridArchive file and
47- the ArchiveBase file. In addition, putting logic in ArchiveBase meant that new
48- implementations often had to override that logic, which quickly became
49- confusing. To overcome these issues, we have refactored ArchiveBase to be an
50- interface that contains almost no logic. All logic for archive implementations
51- is now placed in each archive's file, and to reduce repeated code, we have added
52- various utility functions. We anticipate that it will now be much easier to
53- understand how each archive operates.
54-
55- ## 🛠 Flexible Data Handling
56-
57- Archives now support more flexible data specifications. Notably, solutions are
58- no longer restricted to 1D arrays. They can now be scalars or multi-dimensional
59- arrays; simply pass the appropriate shape as the
60- {attr}` ~ribs.archives.ArchiveBase.solution_dim ` in the archive. Separate data
61- types for the solutions, objectives, and measures are also supported by passing
62- in a dict as the ` dtype ` argument for archives.
63-
64- For example, the following creates a GridArchive where the solutions can be
65- strings!
1+ # What's New in v0.9.0
2+
3+ We are excited to present pyribs 0.9.0, which introduces a host of new features
4+ intended to make the library more flexible than ever! This release supports
5+ Python 3.10 and up, with Python 3.9 being dropped due to being end-of-life.
6+
7+ ## Overhauling CVTArchive
8+
9+ This release introduces a number of new features and (unfortunately) breaking
10+ changes to {class}` ~ribs.archives.CVTArchive ` . For most users, it should suffice
11+ to know that an initialization of CVTArchive that once looked like this:
12+
13+ ``` python
14+ from ribs.archives import CVTArchive
15+
16+ archive = CVTArchive(
17+ solution_dim = 12 ,
18+ cells = 10000 ,
19+ ranges = [(- 1 , 1 ), (- 1 , 1 )],
20+ use_kd_tree = True ,
21+ )
22+ ```
23+
24+ Now looks like this. Note that ` cells ` has been replaced with ` centroids ` , and
25+ ` use_kd_tree ` has been replaced with ` nearest_neighbors ` .
6626
6727``` python
28+ from ribs.archives import CVTArchive
29+
30+ archive = CVTArchive(
31+ solution_dim = 12 ,
32+ centroids = 10000 ,
33+ ranges = [(- 1 , 1 ), (- 1 , 1 )],
34+ nearest_neighbors = " scipy_kd_tree" ,
35+ )
36+ ```
37+
38+ Our new tutorial serves as a starting point for using the new archive:
39+ {doc}` /tutorials/cvt_centroids ` .
40+
41+ ### Detailed Changes
42+
43+ Below we provide further details on the changes, with even more detail available
44+ in {issue}` 621 ` .
45+
46+ - ** Centroid generation has been moved out of CVTArchive.** In the past,
47+ CVTArchive contained methods for generating centroids that could be specified
48+ via the ` centroid_method ` parameter. However, centroid generation is extremely
49+ customizable, and we believe it should be left to the user rather than handled
50+ in the archive initialization itself. As such, ** we have removed the
51+ ` centroid_method ` parameter as well as these centroid generation methods,**
52+ and we have instead added a new tutorial that shows different options for
53+ specifying and generating centroids: {doc}` /tutorials/cvt_centroids ` .
54+
55+ In a similar vein, it is now possible to generate centroids with the
56+ {func}` ~ribs.archives.k_means_centroids ` function, which samples points in a
57+ measure space and performs k-means clustering to identify the centroids. This
58+ function, as well as other workflows with centroids, are included in the above
59+ tutorial.
60+
61+ Finally, since we have separated centroid generation from CVTArchive, ** the
62+ ` samples ` property is now deprecated, as is the ` plot_samples ` parameter** in
63+ {func}` ~ribs.visualize.cvt_archive_heatmap ` and
64+ {func}` ~ribs.visualize.cvt_archive_3d_plot ` .
65+
66+ - ** ` cells ` and ` custom_centroids ` are now replaced with the ` centroids `
67+ parameter.** We found that ` cells ` and ` custom_centroids ` were redundant with
68+ each other. Instead, the new ` centroids ` parameter can either be an int
69+ indicating the number of cells in the archive, or an array-like with the
70+ coordinates of the centroids. This supports the separation of centroid
71+ generation from CVTArchive by making it easier to specify centroids.
72+ Previously, both ` cells ` and ` custom_centroids ` had to be specified to use
73+ centroids created by the user, but now, only ` centroids ` is needed.
74+
75+ - ** Nearest-neighbor lookup is now more flexible.** Previously, we only
76+ supported two methods for nearest-neighbor lookup, via brute-force and via
77+ scipy's {class}` ~scipy.spatial.KDTree ` . To support more methods, ** we have
78+ deprecated the ` use_kd_tree ` parameter and replaced it with a new
79+ ` nearest_neighbors ` parameter.** This ` nearest_neighbors ` parameter can be set
80+ to ` "scipy_kd_tree" ` , ` "brute_force" ` , or the newest option, ` "sklearn_nn" ` ,
81+ which uses scikit-learn's {class}` ~sklearn.neighbors.NearestNeighbors ` .
82+
83+ Correspondingly, we have added ` sklearn_nn_kwargs ` and ` kdtree_query_kwargs ` ,
84+ which allow specifying more options to the internal objects used for
85+ nearest-neighbor search.
86+
87+ ## New dtype Specifications for Archives
88+
89+ Previously, we found specifying separate dtypes for the solution, objective, and
90+ measures in an archive to be complicated due to requiring passing a dict.
91+ Instead, we now allow passing in individual dtypes: ` solution_dtype ` ,
92+ ` objective_dtype ` , and ` measures_dtype ` . It is also still possible to pass in
93+ ` dtype ` to set all of these at once. For example, the following sets the
94+ solutions to be objects, while the objective and measures are float32:
95+
96+ ``` python
97+ import numpy as np
98+
99+ from ribs.archives import GridArchive
100+
68101archive = GridArchive(
69102 solution_dim = (),
70- dims = [10 , 20 ],
71- ranges = [(- 1 , 1 ), (- 2 , 2 )],
72- dtype = {
73- " solution" : object ,
74- " objective" : np.float32,
75- " measures" : np.float32
76- },
103+ dims = [20 , 20 ],
104+ ranges = [(1 , 10 ), (1 , 10 )],
105+ solution_dtype = object ,
106+ objective_dtype = np.float32,
107+ measures_dtype = np.float32,
77108)
109+ ```
110+
111+ (This example is taken from the tutorial {doc}` tutorials/qdaif ` .) For more info,
112+ see {pr}` 639 ` , {pr}` 643 ` , and {pr}` 661 ` .
113+
114+ ## Multi-Dimensional Solutions in Emitters
115+
116+ This release improves support for multi-dimensional solutions in emitters. In
117+ particular, the {class}` ~ribs.emitters.GaussianEmitter ` and
118+ {class}` ~ribs.emitters.IsoLineEmitter ` can now generate multi-dimensional
119+ solutions ({pr}` 650 ` ). In a similar vein, it is now possible to specify the
120+ bounds of the solution space in emitters via ` lower_bounds ` and ` upper_bounds `
121+ ({pr}` 649 ` , {pr}` 657 ` ). The original ` bounds ` parameter is still supported but
122+ cannot be used at the same time. Thus, the following creates a GaussianEmitter
123+ that generates solutions of shape ` (5, 5) ` bounded by -1.0 and 1.0 in each
124+ dimension:
78125
79- add_info = archive.add(
80- solution = [" This is Bob" , " Bob says hi" , " Good job Bob" ],
81- objective = [1.0 , 2.0 , 3.0 ],
82- measures = [[0 , 0 ], [0.25 , 0.25 ], [0.5 , 0.5 ]],
126+ ``` python
127+ import numpy as np
128+
129+ from ribs.archives import GridArchive
130+ from ribs.emitters import GaussianEmitter
131+
132+ archive = GridArchive(
133+ solution_dim = (5 , 5 ),
134+ dims = [20 , 20 ],
135+ ranges = [(- 2 , 2 ), (- 2 , 2 )],
83136)
137+
138+ emitters = [
139+ GaussianEmitter(
140+ archive,
141+ sigma = 0.1 ,
142+ x0 = np.zeros((5 , 5 )),
143+ lower_bounds = np.full((5 , 5 ), - 1.0 ),
144+ upper_bounds = np.full((5 , 5 ), 1.0 ),
145+ batch_size = 64 ,
146+ )
147+ ]
84148```
85149
86- ## 🚨 Breaking Changes
150+ ## 🚨 Additional Breaking Changes
151+
152+ - In {class}` ~ribs.archives.CVTArchive ` and
153+ {class}` ~ribs.archives.ProximityArchive ` , ` ckdtree_kwargs ` is now referred to
154+ as ` kdtree_kwargs ` , as we have stopped using scipy's cKDTree in favor of
155+ KDTree ({pr}` 676 ` )
156+ - In {class}` ~ribs.archives.ArrayStore ` , ` as_raw_dict ` and ` from_raw_dict ` have
157+ been removed as they were not being used ({pr}` 575 ` )
87158
88- v0.8.0 includes several ** backwards-incompatible changes** , most of which are
89- part of an ongoing effort to streamline the library:
159+ ## ✨ Additional Features
90160
91- - ` archive.dtype ` has been replaced with a more expressive ` archive.dtypes `
92- dictionary, since solutions, objectives and measures can now have different
93- dtypes.
94- - {class}` ~ribs.archives.cqd_score ` is now a separate utility function, instead
95- of being a method on the archives.
96- - The {attr}` ~ribs.archives.ArchiveBase.field_list ` and
97- {attr}` ~ribs.archives.ArchiveBase.dtypes ` properties on current archives
98- include the ` index ` field, since ` index ` is no longer a required part of
99- archives.
100- - Archive ` add ` methods and the {class}` ~ribs.archives.ArrayStore ` have been
101- simplified to no longer use "transforms," which significantly complicated the
102- implementation.
161+ - In the archives, {meth}` ~ribs.archives.ArchiveBase.sample_elites ` now supports
162+ the ` replace ` parameter to indicate whether elites should be replaced when
163+ sampling ({pr}` 682 ` )
164+ - {func}` ~ribs.visualize.parallel_axes_plot ` now supports plotting
165+ ` ProximityArchive ` ({pr}` 647 ` )
166+ - {class}` ~ribs.archives.ArrayStore ` now supports backends such as torch and
167+ cupy, drawing from the
168+ [ Python array API standard] ( https://data-apis.org/array-api/latest/ )
169+ ({issue}` 570 ` , {pr}` 645 ` )
103170
104- ## 🐛 Bug Fixes
171+ ## Developer Workflow
105172
106- In this release, we
107- [ fixed a bug in BanditScheduler] ( https://github.com/icaros-usc/pyribs/pull/489 )
108- thanks to [ @Tekexa ] ( https://github.com/Tekexa ) ! Now,
109- {class}` ~ribs.schedulers.BanditScheduler ` correctly maintains a stable number of
110- active emitters.
173+ Finally, in addition to the above library improvements, we have migrated from
174+ using yapf and pylint to using [ ruff] ( https://docs.astral.sh/ruff/ ) and
175+ [ ty] ( https://docs.astral.sh/ty/ ) for formatting, linting, and type checking.
111176
112177## Past Editions
113178
@@ -116,6 +181,7 @@ Past editions of "What's New" are available below.
116181``` {toctree}
117182:maxdepth: 1
118183
184+ whats-new/v0.8.0
119185whats-new/v0.7.0
120186whats-new/v0.5.0
121187```
0 commit comments