def test_custom_centroids(use_kd_tree): centroids = np.array([[-0.25, -0.25], [0.25, 0.25]]) archive = CVTArchive(centroids.shape[0], [(-1, 1), (-1, 1)], custom_centroids=centroids, use_kd_tree=use_kd_tree) archive.initialize(solution_dim=3) assert archive.samples is None assert (archive.centroids == centroids).all()
def _cvt_archive(): """Deterministically created CVTArchive.""" archive = CVTArchive(100, [(-1, 1), (-1, 1)], samples=1000, use_kd_tree=True, seed=42) archive.initialize(solution_dim=2) _add_uniform_sphere(archive, (-1, 1), (-1, 1)) return archive
def _long_cvt_archive(): """Same as above, but the behavior space is longer in one direction.""" archive = CVTArchive(100, [(-2, 2), (-1, 1)], samples=1000, use_kd_tree=True, seed=42) archive.initialize(solution_dim=2) _add_uniform_sphere(archive, (-2, 2), (-1, 1)) return archive
def test_custom_centroids_bad_shape(use_kd_tree): with pytest.raises(ValueError): # The centroids array should be of shape (10, 2) instead of just (1, 2), # hence a ValueError will be raised. CVTArchive(10, [(-1, 1), (-1, 1)], custom_centroids=[[0.0, 0.0]], use_kd_tree=use_kd_tree)
def test_heatmap_fails_on_non_2d(archive_type): archive = { "grid": lambda: GridArchive([20, 20, 20], [(-1, 1)] * 3), "cvt": lambda: CVTArchive(100, [(-1, 1)] * 3, samples=100), "sliding": lambda: SlidingBoundariesArchive([20, 20, 20], [(-1, 1)] * 3), }[archive_type]() archive.initialize(solution_dim=2) # Arbitrary. with pytest.raises(ValueError): { "grid": grid_archive_heatmap, "cvt": cvt_archive_heatmap, "sliding": sliding_boundaries_archive_heatmap, }[archive_type](archive)
def setup(): archive = CVTArchive(1000, [(-1, 1), (-1, 1)], samples=20_000, use_kd_tree=use_kd_tree) archive.initialize(solutions.shape[1]) # Let numba compile. archive.add(solutions[0], objective_values[0], behavior_values[0]) return (archive,), {}
def benchmark_get_10k_random_elites(use_kd_tree, benchmark, benchmark_data_10k): n, solutions, objective_values, behavior_values = benchmark_data_10k archive = CVTArchive(1000, [(-1, 1), (-1, 1)], samples=20_000, use_kd_tree=use_kd_tree) archive.initialize(solutions.shape[1]) for i in range(n): archive.add(solutions[i], objective_values[i], behavior_values[i]) @benchmark def get_elites(): for i in range(n): sol, obj, beh = archive.get_random_elite()
def benchmark_as_pandas_2000_items(benchmark): bins = 2000 archive = CVTArchive(bins, [(-1, 1), (-1, 1)], use_kd_tree=True, samples=50_000) archive.initialize(10) for x, y in archive.centroids: sol = np.random.random(10) sol[0] = x sol[1] = y archive.add(sol, 1.0, np.array([x, y])) # Archive should be full. assert len(archive.as_pandas()) == bins benchmark(archive.as_pandas)
def main(): """Creates archives, times insertion into them, and plots results.""" archive = None n_bins = [10, 50, 100, 500, 1_000, 5_000, 10_000, 100_000] # Pre-made solutions to insert. n_vals = 100_000 solutions = np.random.uniform(-1, 1, (n_vals, 10)) objective_values = np.random.randn(n_vals) behavior_values = np.random.uniform(-1, 1, (n_vals, 2)) # Set up these archives so we can use the same centroids across all # experiments for a certain number of bins (and also save time). ref_archives = { bins: CVTArchive( bins, [(-1, 1), (-1, 1)], # Use 200k bins to avoid dropping clusters. samples=n_vals if bins != 10_000 else 200_000, use_kd_tree=False) for bins in n_bins }
def get_archive_data(name, dtype=np.float64): """Returns ArchiveFixtureData to use for testing each archive. The archives vary, but there will always be an empty 2D archive, as well as a 2D archive with a single solution added to it. This solution will have a value of [1, 2, 3], its objective value will be 1.0, and its behavior values will be [0.25, 0.25]. The name is the name of an archive to create. It should come from ARCHIVE_NAMES. """ # Characteristics of a single solution to insert into archive_with_entry. solution = np.array([1, 2, 3]) objective_value = 1.0 behavior_values = np.array([0.25, 0.25]) grid_indices = None centroid = None if name == "GridArchive": # Grid archive with 10 bins and range (-1, 1) in first dim, and 20 bins # and range (-2, 2) in second dim. bins = 10 * 20 archive = GridArchive([10, 20], [(-1, 1), (-2, 2)], dtype=dtype) archive.initialize(len(solution)) archive_with_entry = GridArchive([10, 20], [(-1, 1), (-2, 2)], dtype=dtype) archive_with_entry.initialize(len(solution)) grid_indices = (6, 11) elif name.startswith("CVTArchive-"): # CVT archive with bounds (-1,1) and (-1,1), and 4 centroids at (0.5, # 0.5), (-0.5, 0.5), (-0.5, -0.5), and (0.5, -0.5). The entry in # archive_with_entry should match with centroid (0.5, 0.5). bins = 4 kd_tree = name == "CVTArchive-kd_tree" samples = [[0.5, 0.5], [-0.5, 0.5], [-0.5, -0.5], [0.5, -0.5]] centroid = [0.5, 0.5] archive = CVTArchive(4, [(-1, 1), (-1, 1)], samples=samples, use_kd_tree=kd_tree, dtype=dtype) archive.initialize(len(solution)) archive_with_entry = CVTArchive(4, [(-1, 1), (-1, 1)], samples=samples, use_kd_tree=kd_tree, dtype=dtype) archive_with_entry.initialize(len(solution)) elif name == "SlidingBoundariesArchive": # Sliding boundary archive with 10 bins and range (-1, 1) in first dim, # and 20 bins and range (-2, 2) in second dim. bins = 10 * 20 archive = SlidingBoundariesArchive([10, 20], [(-1, 1), (-2, 2)], remap_frequency=100, buffer_capacity=1000, dtype=dtype) archive.initialize(len(solution)) archive_with_entry = SlidingBoundariesArchive([10, 20], [(-1, 1), (-2, 2)], remap_frequency=100, buffer_capacity=1000, dtype=dtype) archive_with_entry.initialize(len(solution)) grid_indices = (6, 11) archive_with_entry.add(solution, objective_value, behavior_values) return ArchiveFixtureData( archive, archive_with_entry, solution, objective_value, behavior_values, grid_indices, centroid, bins, )
def init(): archive = CVTArchive(1000, [(-1, 1), (-1, 1)], samples=20_000, use_kd_tree=use_kd_tree) archive.initialize(solution_dim=2)
def setup(bins, use_kd_tree): nonlocal archive archive = CVTArchive(bins, [(-1, 1), (-1, 1)], custom_centroids=ref_archives[bins].centroids, use_kd_tree=use_kd_tree) archive.initialize(solutions.shape[1])
def test_samples_bad_shape(use_kd_tree): # The behavior space is 2D but samples are 3D. with pytest.raises(ValueError): CVTArchive(10, [(-1, 1), (-1, 1)], samples=[[-1, -1, -1], [1, 1, 1]], use_kd_tree=use_kd_tree)