예제 #1
0
def test_fittest_2d():

    INSERTION_POINTS = [0, 10, 20]  # where we copy the ref chromosome

    # using numpy as fancy indexing in TF is a pain and perf is not critical.
    ref_chromosome = np.random.randint(0, 2, (32, 32))
    pop1 = np.random.randint(0, 2, (64, 32, 32))
    pop2 = np.random.randint(0, 2, (64, 32, 32))
    for idx in INSERTION_POINTS:
        pop1[idx] = ref_chromosome

    ref_chromosome = B.tensor(ref_chromosome)
    pop1 = B.tensor(pop1)
    pop2 = B.tensor(pop2)

    fitness_function = InvertedCosineSimilarity(ref_chromosome)
    selector = SelectFittest()
    selected_pop, fitness_scores, metrics = selector(fitness_function, pop1,
                                                     pop2)
    print(selected_pop)
    assert selected_pop.shape == pop1.shape
    # check the exact chromosome is the three top choice
    assert B.tensor_equal(selected_pop[0], ref_chromosome)
    assert B.tensor_equal(selected_pop[1], ref_chromosome)
    assert B.tensor_equal(selected_pop[2], ref_chromosome)
예제 #2
0
def test_sum2d():
    t = [[[1, 1, 1], [1, 1, 1], [1, 1, 1]], [[1, 1, 1], [1, 1, 1], [1, 1, 1]],
         [[1, 1, 1], [1, 1, 1], [1, 1, 1]]]
    inputs = B.tensor(t)
    print(inputs)
    result = Sum().call(inputs)
    assert result.shape == (3, )
    print(result)

    expected = B.tensor([9, 9, 9])
    assert B.tensor_equal(result, expected)
예제 #3
0
def test_fittest():

    ref = B.tensor([2, 0, 1, 1, 0, 2, 1, 1])
    d = B.tensor([2, 1, 1, 0, 1, 1, 1, 1])
    pop = B.tensor([ref, d, ref, d, ref, d])

    fitness_function = InvertedCosineSimilarity(ref)
    selector = SelectFittest()
    selected_pop, fitness_scores, metrics = selector(fitness_function, pop,
                                                     pop)
    print(selected_pop)
    assert selected_pop.shape == pop.shape
    for chromosome in selected_pop:
        assert B.tensor_equal(chromosome, ref)
예제 #4
0
def test_cosine_similarity_1dpopulation(backends):
    "test the function works on a population and broadcast correctly"

    reference = [1, 0, 1, 1, 0, 1, 1, 1]
    different = [1, 1, 1, 0, 1, 1, 1, 1]

    r = B.tensor(reference)
    d = B.tensor(different)
    population = B.tensor([r, d, r])
    cs = InvertedCosineSimilarity(r)

    # similar vector have a distance of 1
    distances = cs(population)
    print("distances", distances)
    assert B.assert_near(distances[0], 1, absolute_tolerance=0.001)
    assert not B.assert_near(distances[1], 1, absolute_tolerance=0.001)
    assert B.assert_near(distances[2], 1, absolute_tolerance=0.001)
예제 #5
0
 def _flatten_population(self, population):
     """Convert the population to a 1D array as many ops (e.g norm) don't
     work on Ndimension
     """
     if len(population.shape) < 3:
         return population
     num_chromosomes = population.shape[0]
     flattened_size = int(B.prod(B.tensor(population.shape[1:])))
     return B.reshape(population, (num_chromosomes, flattened_size))
예제 #6
0
    def assign(self, chromosomes):
        """Assign concrete values to the input
        """
        chromosomes = B.tensor(chromosomes)

        if chromosomes.shape != self.shape:
            raise ValueError(
                'Incompatible input shape expected: %s - got: %s' %
                (self.shape, chromosomes.shape))
        self.chromosomes = chromosomes
예제 #7
0
    def call(self, population):

        if not self.debug:
            population = B.shuffle(population)

        # how many chromosomes to crossover
        num_reversed_chromosomes = int(population.shape[0] *
                                       self.population_fraction)

        self.print_debug('num chromosomes', num_reversed_chromosomes)

        # compute the shape needed for the mutation
        mutations_shape = [num_reversed_chromosomes]
        for idx, frac in enumerate(self.max_reverse_probability):
            max_genes = int(population.shape[idx + 1] * frac + 1)
            # ! not an error: reverse need at least 2 indices to make sense.
            if max_genes > 2:
                num_genes = B.randint(2, high=max_genes)
            else:
                num_genes = 2
            mutations_shape.append(num_genes)
            self.print_debug(idx, 'num_genes', num_genes, 'max', max_genes)

        self.print_debug("population_shape:", population.shape)
        self.print_debug("mutation_shape:", mutations_shape)

        # compute the fancy indexing dynamlically
        # ! the start point must be randomized
        slices = [slice(0, num_reversed_chromosomes)]
        for idx, crossover_size in enumerate(mutations_shape[1:]):
            # ! making indexing explicit as its a huge pitfall
            mutation_dim = idx + 1
            max_start = population.shape[mutation_dim] - crossover_size + 1
            start = B.randint(0, max_start)
            # start = random.randint(0, max_start)
            slices.append(slice(start, crossover_size + start))
        slices = tuple(slices)
        tslices = slices2array(slices)
        self.print_debug('slices', slices)

        # revesing
        reversed_population = population[slices]
        axis = B.tensor([x for x in range(1, len(reversed_population.shape))])
        reversed_population = B.reverse(reversed_population, axis)
        self.print_debug('reversed population', reversed_population)

        # assigning
        population = B.assign(population, reversed_population, tslices)

        return population
예제 #8
0
파일: sum.py 프로젝트: pacificlion/evoflow
    def __init__(self, max_sum_value=None, **kwargs):
        """Compute the sum of the chromosomes as fitness values.

        Args:
            expected_max_sum_value (int, optional): What is the maximum value
            the sum per chromosome will reach. Used to normalize the fitness
            function between 0 and 1 if specified. Defaults to None.

        Note:
            This fitness function is used to solve the MAXONE problem.

        """
        super(Sum, self).__init__(**kwargs)
        if max_sum_value:
            self.max_sum_value = B.tensor(max_sum_value)
        else:
            self.max_sum_value = None
예제 #9
0
    def __init__(self, reference_chromosome, **kwargs):
        """Inverted Cosine similarity function that returns 1 when chromosomes
        are similar to the reference chromose and [0, 1[ when different

        For reference implementation see
        https://github.com/scipy/scipy/blob/v0.14.0/scipy/spatial/distance.py#L267  # noqa

        Args:
            reference_chromosome (tensor1D): reference_chromosome.
        """
        super(InvertedCosineSimilarity, self).__init__(**kwargs)

        # cache ref chromosome flattend
        self.ref_chromosome = B.flatten(B.tensor(reference_chromosome))

        # caching ref pop norm
        self.ref_norm = B.norm(B.cast(self.ref_chromosome, B.floatx()))
예제 #10
0
def test_helloworld():
    "Solve the MAXONE problem"
    NUM_EVOLUTIONS = 10
    SHAPE = (20, 20)
    MAX_VAL = 1

    population = randint_population(SHAPE, MAX_VAL)

    inputs = Input(SHAPE)
    x = RandomMutations1D(max_gene_value=1)(inputs)
    outputs = UniformCrossover1D()(x)
    gf = EvoFlow(inputs, outputs, debug=0)
    fitness_function = Sum(max_sum_value=SHAPE[1])
    evolution_strategy = SelectFittest()
    gf.compile(evolution_strategy, fitness_function)
    gf.summary()
    results = gf.evolve(population,
                        generations=NUM_EVOLUTIONS,
                        callbacks=[DummyCallback()],
                        verbose=0)
    assert results

    metrics = results.get_metrics_history()

    # check metrics
    for metric_grp, data in metrics.items():

        for metric_name, vals in data.items():
            assert isinstance(vals, list)
            if metric_grp == 'Fitness function':
                assert len(vals) == 10
                assert isinstance(vals[9], float)

                assert 'mean' in data
                assert 'max' in data

    # assert the engine solved the (Trivial) problem
    max_fitness = metrics['Fitness function']['max']
    assert max(max_fitness) == 1
    assert max_fitness[9] == 1
    assert min(max_fitness) < 1  # max sure we did improve

    # check population value
    population = results.get_populations()
    assert (population.shape) == SHAPE
    assert B.tensor_equal(population[0], B.tensor([1] * SHAPE[1]))
예제 #11
0
def uniform_population(shape, dtype=B.intx()):
    """Generate a uniform population made of Integers. Uniform means that
    each chromosome contains only one time each value and each chromosome
    have them in different order.

    Args:
        (set of ints): shape of the population. Its of the form
        (num_chromosomes, chromosome size)

        dtype (str): tensor type

    Returns:
        Tensor: uniform population.
    """
    population = []
    chromosome = B.range(shape[1], dtype=dtype)
    for i in range(shape[0]):
        chromosome = B.shuffle(chromosome)
        population.append(chromosome)
    return B.tensor(population)
예제 #12
0
def test_cosine_2d(backends):
    INSERTION_POINTS = [0, 10, 20]  # where we copy the ref chromosome

    ref_chromosome = B.randint(0, 2, (32, 32))
    ref_pop = B.randint(0, 2, (64, 32, 32))

    ref_pop = B.as_numpy_array(ref_pop)
    inserstion = B.as_numpy_array(ref_chromosome)
    for idx in INSERTION_POINTS:
        ref_pop[idx] = inserstion

    ref_pop = B.tensor(ref_pop)

    cs = InvertedCosineSimilarity(ref_chromosome)
    distances = cs(ref_pop)
    print(distances)

    for idx, dst in enumerate(distances):
        if idx in INSERTION_POINTS:
            assert B.assert_near(dst, 1.0, absolute_tolerance=0.001)
        else:
            assert dst < 1
            assert dst > 0
예제 #13
0
def test_eager():
    "when passing concrete value GF is suppposed to return a concrete value"
    val = B.tensor(42)
    assert Dummy(debug=True)(val) == val
예제 #14
0
def test_box_unbox_tensor():
    val = tensor([1, 2, 3])

    assert tensor_equal(unbox(box(val)), val)