Beispiel #1
0
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 = SlidingBoundariesArchive([10, 20], [(-1, 1), (-2, 2)],
                                           remap_frequency=100,
                                           buffer_capacity=1000)
        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(benchmark, benchmark_data_10k):
    n, solutions, objective_values, behavior_values = benchmark_data_10k
    archive = SlidingBoundariesArchive([10, 20], [(-1, 1), (-2, 2)],
                                       remap_frequency=100,
                                       buffer_capacity=1000)
    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_2048_elements(benchmark):
    # TODO (btjanaka): Make this size smaller so that we do a remap.
    archive = SlidingBoundariesArchive([32, 64], [(-1, 1), (-2, 2)],
                                       remap_frequency=20000,
                                       buffer_capacity=20000)
    archive.initialize(10)

    for x in np.linspace(-1, 1, 100):
        for y in np.linspace(-2, 2, 100):
            sol = np.random.random(10)
            sol[0] = x
            sol[1] = y
            archive.add(sol, -(x**2 + y**2), np.array([x, y]))

    # Archive should be full.
    assert len(archive.as_pandas()) == 32 * 64

    benchmark(archive.as_pandas)
Beispiel #5
0
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,
    )
Beispiel #6
0
def _long_sliding_archive():
    """Same as above, but the behavior space is longer in one direction."""
    archive = SlidingBoundariesArchive([10, 20], [(-2, 2), (-1, 1)], seed=42)
    archive.initialize(solution_dim=2)
    _add_random_sphere(archive, (-2, 2), (-1, 1))
    return archive
Beispiel #7
0
def _sliding_archive():
    """Deterministically created SlidingBoundariesArchive."""
    archive = SlidingBoundariesArchive([10, 20], [(-1, 1), (-1, 1)], seed=42)
    archive.initialize(solution_dim=2)
    _add_random_sphere(archive, (-1, 1), (-1, 1))
    return archive
Beispiel #8
0
def test_initial_remap():
    """Checks that boundaries and entries are correct after initial remap."""
    # remap_frequency is (10 + 1) * (20 + 1)
    archive = SlidingBoundariesArchive([10, 20], [(-1, 1), (-2, 2)],
                                       remap_frequency=231,
                                       buffer_capacity=1000)
    archive.initialize(2)

    # Buffer should have 230 entries after this (since the first entry is
    # skipped).
    first = True
    expected_bcs = []
    for ix, x in enumerate(np.linspace(-1, 1, 11)):
        for iy, y in enumerate(np.linspace(-2, 2, 21)):
            if first:
                first = False
                continue

            # The second to last row and column get overridden by other entries
            # because we set their objective lower.
            if ix == 9 or iy == 19:
                obj = 1
            else:
                expected_bcs.append((x, y))
                obj = 2

            # Solutions are same as BCs.
            archive.add([x, y], obj, [x, y])

    # There are 199 entries because the last entry has not been inserted.
    # TODO(btjanaka): Use the archive.occupied property when it is available.
    assert len(archive.as_pandas(include_solutions=False)) == 199

    # Buffer should now have 231 entries; hence it remaps.
    archive.add([-1, -2], 1, [-1, -2])
    expected_bcs.append((-1, -2))

    # TODO(btjanaka): Use the archive.occupied property when it is available.
    assert len(archive.as_pandas(include_solutions=False)) == 200

    # Since we passed in unique entries generated with linspace, the boundaries
    # should come from linspace.
    assert np.isclose(archive.boundaries[0], np.linspace(-1, 1, 11)).all()
    assert np.isclose(archive.boundaries[1], np.linspace(-2, 2, 21)).all()

    # Check that all the BCs are as expected.
    pandas_bcs = archive.as_pandas(include_solutions=False)[[
        "behavior_0", "behavior_1"
    ]]
    bcs = list(pandas_bcs.itertuples(name=None, index=False))
    assert np.isclose(sorted(bcs), sorted(expected_bcs)).all()
Beispiel #9
0
def test_fails_on_dim_mismatch():
    with pytest.raises(ValueError):
        SlidingBoundariesArchive(
            dims=[10] * 2,  # 2D space here.
            ranges=[(-1, 1)] * 3,  # But 3D space here.
        )
Beispiel #10
0
def test_adds_solutions_from_old_archive():
    """Solutions from previous archive should be inserted during remap."""
    archive = SlidingBoundariesArchive([10, 20], [(-1, 1), (-2, 2)],
                                       remap_frequency=231,
                                       buffer_capacity=231)
    archive.initialize(2)

    for x in np.linspace(-1, 1, 11):
        for y in np.linspace(-2, 2, 21):
            archive.add([x, y], 2, [x, y])

    # TODO(btjanaka): Use the archive.occupied property when it is available.
    assert len(archive.as_pandas(include_solutions=False)) == 200

    # Archive gets remapped again, but it should maintain the same BCs since
    # solutions are the same. All the high-performing solutions should be
    # cleared from the buffer since the buffer only has capacity 200.
    for x in np.linspace(-1, 1, 11):
        for y in np.linspace(-2, 2, 21):
            archive.add([x, y], 1, [x, y])

    # TODO(btjanaka): Use the archive.occupied property when it is available.
    assert len(archive.as_pandas(include_solutions=False)) == 200

    # The objective values from the previous archive should remain because they
    # are higher.
    assert (archive.as_pandas(include_solutions=False)["objective"] == 2).all()