What’s New in v0.8.0¶
Pyribs v0.8.0 adds support for several new algorithms while making it easier than ever to design new ones. Below we highlight some of the most notable updates. For the full list of changes, please refer to our History page.
🧠 New Algorithms¶
Pyribs v0.8.0 introduces implementations of several new algorithms:
Novelty Search (Lehman 2011) via the
ProximityArchive. We illustrate how to run Novelty Search in our new tutorial, Exploring Deceptive Mazes with Novelty Search. Visualization is available viaproximity_archive_plot().Thanks to @gresavage for helping with this implementation!
Density Descent Search (Lee 2024) via the
DensityArchive. We illustrate how to run Density Descent Search in Sphere Function with Various Algorithms.BOP-Elites (Kent 2024) via
BayesianOptimizationEmitterandBayesianOptimizationScheduler. An example of running BOP-Elites is available in the example here: BOP-Elites.As part of implementing BOP-Elites, a new
retessellatemethod has been added to GridArchive to allow changing the layout of the grid.Thanks to @szhaovas for working on this implementation!
We have also added a CategoricalArchive where the
measures can be categorical values, e.g., ["Cat", "Dog", "Mouse"].
The Supported Algorithms page now includes a list of algorithms supported in pyribs.
📜 Single-File Implementations for Archives¶
To make it easier to understand current archives and create new archives, we
have made each archive into a “single-file implementation.” Previously,
ArchiveBase contained a lot of archive logic. While this
made it easier to share code between archives, it also made it harder to
understand each archive’s implementation. For instance, the implementation for
GridArchive was split between the GridArchive file and
the ArchiveBase file. In addition, putting logic in ArchiveBase meant that new
implementations often had to override that logic, which quickly became
confusing. To overcome these issues, we have refactored ArchiveBase to be an
interface that contains almost no logic. All logic for archive implementations
is now placed in each archive’s file, and to reduce repeated code, we have added
various utility functions. We anticipate that it will now be much easier to
understand how each archive operates.
🛠 Flexible Data Handling¶
Archives now support more flexible data specifications. Notably, solutions are
no longer restricted to 1D arrays. They can now be scalars or multi-dimensional
arrays; simply pass the appropriate shape as the
solution_dim in the archive. Separate data
types for the solutions, objectives, and measures are also supported by passing
in a dict as the dtype argument for archives.
For example, the following creates a GridArchive where the solutions can be strings!
archive = GridArchive(
solution_dim=(),
dims=[10, 20],
ranges=[(-1, 1), (-2, 2)],
dtype={
"solution": object,
"objective": np.float32,
"measures": np.float32
},
)
add_info = archive.add(
solution=["This is Bob", "Bob says hi", "Good job Bob"],
objective=[1.0, 2.0, 3.0],
measures=[[0, 0], [0.25, 0.25], [0.5, 0.5]],
)
🚨 Breaking Changes¶
v0.8.0 includes several backwards-incompatible changes, most of which are part of an ongoing effort to streamline the library:
archive.dtypehas been replaced with a more expressivearchive.dtypesdictionary, since solutions, objectives and measures can now have different dtypes.cqd_scoreis now a separate utility function, instead of being a method on the archives.The
field_listanddtypesproperties on current archives include theindexfield, sinceindexis no longer a required part of archives.Archive
addmethods and theArrayStorehave been simplified to no longer use “transforms,” which significantly complicated the implementation.
🐛 Bug Fixes¶
In this release, we
fixed a bug in BanditScheduler
thanks to @Tekexa! Now,
BanditScheduler correctly maintains a stable number of
active emitters.