class IndividualTest(unittest.TestCase):

    def setUp(self):
        self.maxDiff = True

    def test_binary_encoding(self):
        ''' Make sure individual can decode and encode binary gene correctly.
        '''
        indv = BinaryIndividual(ranges=[(0, 1)], eps=0.001)
        indv.init(solution=[0.398])

        # Test binary chromsome.
        ref_chromsome = [0, 1, 1, 0, 0, 1, 0, 1, 1]
        self.assertListEqual(indv.chromsome, ref_chromsome)

        # Test decode.
        self.assertListEqual(indv.decode(), [0.396484375])

        indv = BinaryIndividual(ranges=[(0, 1), (-1, 1)],  eps=0.001)
        indv.init(solution=[0.398, 0.66])

        # Test binary chromsome.
        ref_chromsome = [0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1]
        self.assertListEqual(indv.chromsome, ref_chromsome)

        # Test decode.
        self.assertListEqual(indv.decode(), [0.396484375, 0.658203125])

    def test_descriptors(self):
        ''' Make sure descriptors can check the parameters correctly.
        '''
        self.assertRaises(TypeError, BinaryIndividual, ranges=0.1, eps=0.001)
        self.assertRaises(TypeError, BinaryIndividual, ranges=[(0, 1)], eps='asdf')
        self.assertRaises(ValueError, BinaryIndividual, ranges=[(0, 1)], eps=10.0)
        self.assertRaises(ValueError, BinaryIndividual, ranges=[(0, 1)], eps=[1, 2])

    def test_init(self):
        ''' Make sure the individual can be initialized correctly.
        '''
        indv = BinaryIndividual(ranges=[(0, 1)], eps=0.001)

        # Check chromsome initialization.
        indv.init(chromsome=[0, 1, 1, 0, 0, 0, 1, 1, 1, 0])
        
        self.assertListEqual([0, 1, 1, 0, 0, 0, 1, 1, 1, 0], indv.chromsome)
        self.assertListEqual(indv.solution, [0.388671875])

        # Check solution initialization.
        indv.init(solution=[0.398])
        
        self.assertListEqual(indv.solution, [0.398])
        self.assertListEqual(indv.chromsome, [0, 1, 1, 0, 0, 1, 0, 1, 1])

    def test_clone(self):
        ''' Make sure individual can be cloned correctly.
        '''
        indv = BinaryIndividual(ranges=[(0, 1)],
                                eps=0.001).init(solution=[0.398])
        indv_clone = indv.clone()

        self.assertListEqual(indv.chromsome, indv_clone.chromsome)
        self.assertAlmostEqual(indv.solution[0], indv_clone.solution[0], places=2)
        self.assertEqual(indv.ranges, indv_clone.ranges)
        self.assertEqual(indv.eps, indv_clone.eps)

    def test_multi_precisions(self):
        ''' Make sure we can construct individual using different decrete precisions.
        '''
        indv = BinaryIndividual(ranges=[(0, 1), (0, 10)], eps=[0.01, 1.0]).init(solution=[0.3, 0.5])
        self.assertNotEqual(indv.precisions[0], indv.precisions[1]) class PopulationTest(unittest.TestCase):

    def setUp(self):
        self.maxDiff = True
        self.indv_template = BinaryIndividual(ranges=[(0, 1)])
        def fitness(indv):
            x, = indv.solution
            return x**3 - 60*x**2 + 900*x + 100
        self.fitness = fitness

    def test_initialization(self):
        ''' Make sure a population can be initialized correctly. '''
        population = Population(indv_template=self.indv_template, size=10)

        self.assertListEqual(population.individuals, [])

        population.init()
        self.assertEqual(len(population.individuals), 10)

        # Check individual.
        self.assertTrue(isinstance(population[0], BinaryIndividual))

    def test_new_population(self):
        ''' Make sure population can clone a new population. '''
        population = Population(indv_template=self.indv_template, size=10)
        population.init()
        new_population = population.new()
        self.assertEqual(new_population.size, 10)
        self.assertListEqual(new_population.individuals, [])

    def test_all_fits(self):
        population = Population(indv_template=self.indv_template, size=10)
        population.init()
        all_fits = population.all_fits(fitness=self.fitness)

        self.assertEqual(len(all_fits), 10)

        for fit in all_fits:
            self.assertTrue(type(fit) is float) class RouletteWheelSelectionTest(unittest.TestCase):

    def setUp(self):
        self.maxDiff
        def fitness(indv):
            x, = indv.solution
            return x**3 - 60*x**2 + 900*x + 100
        self.fitness = fitness

    def test_selection(self):
        indv = BinaryIndividual(ranges=[(0, 30)])
        p = Population(indv)
        p.init()

        selection = RouletteWheelSelection()
        father, mother = selection.select(p, fitness=self.fitness)

        self.assertTrue(isinstance(father, BinaryIndividual))
        self.assertTrue(isinstance(mother, BinaryIndividual))
        self.assertNotEqual(father.chromsome, mother.chromsome) class UniformCrossoverTest(unittest.TestCase):

    def setUp(self):
        self.maxDiff

    def test_cross(self):
        ''' Make sure individuals can be crossed correctly.
        '''
        father = BinaryIndividual(ranges=[(0, 1)]).init(solution=[0.398])
        mother = BinaryIndividual(ranges=[(0, 1)]).init(solution=[0.298])
        crossover = UniformCrossover(pc=1.0, pe=0.5)
        child1, child2 = crossover.cross(father, mother) class FlipBitMutationTest(unittest.TestCase):

    def setUp(self):
        self.maxDiff

    def test_mutate_binary_indv(self):
        ''' Make sure the individual can be mutated correctly.
        '''
        indv = BinaryIndividual(ranges=[(0, 1)]).init(solution=[0.398])
        mutation = FlipBitMutation(pm=1.0)
        chromsome_before = [0, 1, 1, 0, 0, 1, 0, 1, 1]
        chromsome_after = [1, 0, 0, 1, 1, 0, 1, 0, 0]
        self.assertListEqual(indv.chromsome, chromsome_before)
        mutation.mutate(indv, engine=None)
        self.assertListEqual(indv.chromsome, chromsome_after)

    def test_mutate_decimal_indv(self):
        ''' Make sure individual with decimal encoding can be mutated correctly.
        '''
        indv = DecimalIndividual(ranges=[(0, 1), (0, 2)]).init(solution=[0.5, 1.5])
        mutation = FlipBitMutation(pm=1.0)
        chromsome_before = [0.5, 1.5]
        self.assertListEqual(indv.chromsome, chromsome_before)
        mutation.mutate(indv, engine=None)
        for a, b in zip(indv.chromsome, chromsome_before):
            self.assertNotEqual(a, b) class MPIUtilTest(unittest.TestCase):

    def setUp(self):
        self.maxDiff = True

    def test_split_seq(self):
        '''
        Make sure sequence can be splited according to process number correctly.
        '''
        seq = list(range(10))

        if mpi.size == 1:
            self.assertListEqual(mpi.split_seq(seq), seq)
        elif mpi.size == 2:
            if mpi.rank == 0:
                self.assertListEqual(mpi.split_seq(seq), [0, 1, 2, 3, 4])
            elif mpi.rank == 1:
                self.assertListEqual(mpi.split_seq(seq), [5, 6, 7, 8, 9])

    def test_merge_seq(self):
        '''
        Make sure sequence in different processes can be merged correctly.
        '''
        if mpi.size == 1:
            self.assertListEqual(mpi.merge_seq([1, 2, 3]), [1, 2, 3])
        if mpi.size == 2:
            if mpi.rank == 0:
                recv_data = mpi.merge_seq([1, 2, 3])
            elif mpi.rank == 1:
                recv_data = mpi.merge_seq([2, 3, 4])
            self.assertListEqual(recv_data, [1, 2, 3, 2, 3, 4])

    def test_split_size(self):
        '''
        Make sure a size number can be splited correctly.
        '''
        if mpi.size == 1:
            self.assertEqual(mpi.split_size(50), 50)
        if mpi.size == 2:
            if mpi.rank == 0:
                self.assertEqual(mpi.split_size(49), 25)
                self.assertEqual(mpi.split_size(1), 1)
            elif mpi.rank == 1:
                self.assertEqual(mpi.split_size(49), 24)
                self.assertEqual(mpi.split_size(1), 0) class GAEngineTest(unittest.TestCase):

    def setUp(self):
        self.maxDiff = True

    def test_binary_run(self):
        '''
        Make sure GA engine can run correctly.
        '''
        indv_template = BinaryIndividual(ranges=[(0, 10)], eps=0.001)
        population = Population(indv_template=indv_template, size=50).init()

        # Create genetic operators.
        selection = RouletteWheelSelection()
        crossover = UniformCrossover(pc=0.8, pe=0.5)
        mutation = FlipBitMutation(pm=0.1)

        # Create genetic algorithm engine.
        engine = GAEngine(population=population, selection=selection,
                          crossover=crossover, mutation=mutation)

        @engine.fitness_register
        @engine.minimize
        def fitness(indv):
            x, = indv.solution
            return x + 10*sin(5*x) + 7*cos(4*x)

        engine.run(50)

    def test_decimal_run(self):
        '''
        Make sure GA engine can run correctly with decimal encoding individuals.
        '''
        indv_template = DecimalIndividual(ranges=[(0, 10)], eps=0.001)
        population = Population(indv_template=indv_template, size=50).init()

        # Create genetic operators.
        selection = RouletteWheelSelection()
        crossover = UniformCrossover(pc=0.8, pe=0.5)
        mutation = FlipBitMutation(pm=0.1)

        # Create genetic algorithm engine.
        engine = GAEngine(population=population, selection=selection,
                          crossover=crossover, mutation=mutation)

        @engine.fitness_register
        @engine.minimize
        def fitness(indv):
            x, = indv.solution
            return x + 10*sin(5*x) + 7*cos(4*x)

        engine.run(50) class TournamentSelectionTest(unittest.TestCase):

    def setUp(self):
        self.maxDiff
        def fitness(indv):
            x, = indv.solution
            return x**3 - 60*x**2 + 900*x + 100
        self.fitness = fitness

    def test_selection(self):
        indv = BinaryIndividual(ranges=[(0, 30)])
        p = Population(indv)
        p.init()

        selection = TournamentSelection()
        father, mother = selection.select(p, fitness=self.fitness)

        self.assertTrue(isinstance(father, BinaryIndividual))
        self.assertTrue(isinstance(mother, BinaryIndividual)) class LinearRankingSelectionTest(unittest.TestCase):

    def setUp(self):
        self.maxDiff
        def fitness(indv):
            x, = indv.solution
            return x**3 - 60*x**2 + 900*x + 100
        self.fitness = fitness

    def test_selection(self):
        indv = BinaryIndividual(ranges=[(0, 30)])
        p = Population(indv)
        p.init()

        selection = LinearRankingSelection()
        father, mother = selection.select(p, fitness=self.fitness)

        self.assertTrue(isinstance(father, BinaryIndividual))
        self.assertTrue(isinstance(mother, BinaryIndividual))
        self.assertNotEqual(father.chromsome, mother.chromsome) class ExponentialRankingSelectionTest(unittest.TestCase):

    def setUp(self):
        self.maxDiff
        def fitness(indv):
            x, = indv.solution
            return x**3 - 60*x**2 + 900*x + 100
        self.fitness = fitness

    def test_selection(self):
        indv = BinaryIndividual(ranges=[(0, 30)])
        p = Population(indv)
        p.init()

        selection = ExponentialRankingSelection()
        father, mother = selection.select(p, fitness=self.fitness)

        self.assertTrue(isinstance(father, BinaryIndividual))
        self.assertTrue(isinstance(mother, BinaryIndividual))
        self.assertNotEqual(father.chromsome, mother.chromsome) class LinearScalingTest(unittest.TestCase):

    def setUp(self):
        self.maxDiff = True

    def test_run(self):
        '''
        Make sure GA engine can run correctly.
        '''
        indv_template = BinaryIndividual(ranges=[(0, 10)], eps=0.001)
        population = Population(indv_template=indv_template, size=50).init()

        # Create genetic operators.
        selection = RouletteWheelSelection()
        crossover = UniformCrossover(pc=0.8, pe=0.5)
        mutation = FlipBitMutation(pm=0.1)

        # Create genetic algorithm engine.
        engine = GAEngine(population=population, selection=selection,
                          crossover=crossover, mutation=mutation)

        @engine.fitness_register
        @engine.linear_scaling(target='max', ksi=0.5)
        def fitness(indv):
            x, = indv.solution
            return x + 10*sin(5*x) + 7*cos(4*x)

        engine.run(50) class DynamicLinearScalingTest(unittest.TestCase):

    def setUp(self):
        self.maxDiff = True

    def test_run(self):
        '''
        Make sure GA engine can run correctly.
        '''
        indv_template = BinaryIndividual(ranges=[(0, 10)], eps=0.001)
        population = Population(indv_template=indv_template, size=50).init()

        # Create genetic operators.
        selection = RouletteWheelSelection()
        crossover = UniformCrossover(pc=0.8, pe=0.5)
        mutation = FlipBitMutation(pm=0.1)

        # Create genetic algorithm engine.
        engine = GAEngine(population=population, selection=selection,
                          crossover=crossover, mutation=mutation)

        @engine.fitness_register
        @engine.dynamic_linear_scaling()
        def fitness(indv):
            x, = indv.solution
            return x + 10*sin(5*x) + 7*cos(4*x)

        engine.run(50) class FlipBitBigMutationTest(unittest.TestCase):

    def setUp(self):
        self.maxDiff

    def test_mutate(self):
        ''' Make sure the individual can be mutated correctly.
        '''
        indv_template = BinaryIndividual(ranges=[(0, 10)], eps=0.001)
        population = Population(indv_template=indv_template, size=50).init()

        # Create genetic operators.
        selection = RouletteWheelSelection()
        crossover = UniformCrossover(pc=0.8, pe=0.5)
        mutation = FlipBitBigMutation(pm=0.03, pbm=0.2, alpha=0.6)

        # Create genetic algorithm engine.
        engine = GAEngine(population=population, selection=selection,
                          crossover=crossover, mutation=mutation)

        @engine.fitness_register
        def fitness(indv):
            x, = indv.solution
            return x + 10*sin(5*x) + 7*cos(4*x)

        mutation.mutate(indv_template, engine)
import unittest
from .individual_test import IndividualTest
from .population_test import PopulationTest
from .roulette_wheel_selection_test import RouletteWheelSelectionTest
from .uniform_crossover_test import UniformCrossoverTest
from .flip_bit_mutation_test import FlipBitMutationTest
from .mpiutil_test import MPIUtilTest
from .engine_test import GAEngineTest
from .tournament_selection_test import TournamentSelectionTest
from .linear_ranking_selection_test import LinearRankingSelectionTest
from .exponential_ranking_selection_test import ExponentialRankingSelectionTest
from .linear_scaling_test import LinearScalingTest
from .dynamic_linear_scaling_test import DynamicLinearScalingTest
from .flip_bit_big_mutation_test import FlipBitBigMutationTest
#!/usr/bin/env python
# -*- coding: utf-8 -*-

''' Module for all test in ga.py
'''



def suite():
    ''' Generate test suite for all test cases in GAFT
    '''
    test_cases = [
        IndividualTest,
        PopulationTest,
        RouletteWheelSelectionTest,
        UniformCrossoverTest,
        FlipBitMutationTest,

        MPIUtilTest,