def caixa_preta(
        algorithm=1,
        generations=50,
        population=[],
        is_single=False,
        is_uniform=True,
        is_elitist=True,
        is_ultra_elitist=False,
        elitism=0.85,
        xfactor=0.3,
        win_factor=1
    ):
    """Realiza o algoritmo evlutivo para o problema"""

    data_fit = []

    if algorithm == 1:
        for gen in range(generations):
            # calcula o fitness da população
            fit = fitness(population)
            # faz a seleção por torneio
            f_selec_torn, f_perd_torn = torneio(population, fit, win_factor)
            # faz o cruzamento
            child_sliced = cruzamento(f_selec_torn, is_single=is_single, is_uniform=is_uniform)
            # faz a mutação do filho
            child_mutaded = mutacao(child_sliced, xfactor=xfactor)
            # seleciona a nova população
            population = substituicao(population, father=f_selec_torn, children=child_mutaded, elitism=elitism, is_ultra_elitist=is_ultra_elitist, is_elitist=is_elitist)

            if type(population[0][0]) != int:
                import pdb;pdb.set_trace()

            fit = fitness(population)

            data_fit.append(best_fitness(fit))

    else:
        for gen in range(generations):
            # calcula o fitness da população
            fit = fitness(population)
            # calcula a média do fitness do conjunto
            fit_avg = fitness_medio(fit)
            # calcula a probabilidade de seleção
            prob_selec = selecao_prob(population, fit, fit_avg)
            # faz a seleção por rodeio
            f_selec_rol = roleta(population, prob_selec)
            # faz o cruzamento
            child_sliced = cruzamento(f_selec_rol, is_single=is_single, is_uniform=is_uniform)
            # faz a mutação do filho
            child_mutaded = mutacao(child_sliced, xfactor)
            # seleciona a nova população
            population = substituicao(population, f_selec_rol, child_mutaded, elitism, is_elitist)
            fit = fitness(population)

            data_fit.append(best_fitness(fit))

    return data_fit
Beispiel #2
0
def test():

    nIter = 100
    nPop = 100
    nAr = 100
    nChr = 3
    func = function
    c1 = 1.49445
    c2 = 2
    lb = -2
    rb = 2
    Vmax = 0.2
    Vmin = -0.2
    M = 50
    paretoPops, paretoFits = MOPSO(nIter, nPop, nAr, nChr, \
        func, c1, c2, lb, rb, Vmax, Vmin, M)

    print(paretoPops.shape)
    print('=' * 20)
    #print(paretoPops)

    # 理论最优解集合
    x = np.linspace(-1 / np.sqrt(3), 1 / np.sqrt(3), 116).reshape(116, 1)
    X = np.tile(x, 3)  # 理论最佳帕累托解集
    thFits = fitness(X, function)

    plt.rcParams['font.sans-serif'] = 'KaiTi'  # 设置显示中文
    fig = plt.figure(dpi=400)
    ax = fig.add_subplot(111)
    ax.plot(thFits[:,0], thFits[:,1], color='green',\
         label="理论帕累托前沿")
    ax.scatter(paretoFits[:,0], paretoFits[:,1], \
        color='red', label="实际求解")
    ax.legend()
    fig.savefig('test.png', dpi=400)
Beispiel #3
0
def main():
    nIter = 50
    nChr = 3
    nPop = 100
    pc = 0.6
    pm = 0.1
    etaC = 1
    etaM = 1
    func = function
    lb = -2
    rb = 2
    paretoPops, paretoFits = NSGA2(nIter, nChr, nPop, pc, pm, etaC, etaM, func,
                                   lb, rb)
    print(paretoFits)
    print(f"paretoFront: {paretoFits.shape}")

    # 理论最优解集合
    x = np.linspace(-1 / np.sqrt(3), 1 / np.sqrt(3), 116).reshape(116, 1)
    X = np.concatenate((x, x, x), axis=1)
    thFits = fitness(X, function)

    plt.rcParams['font.sans-serif'] = 'KaiTi'  # 设置显示中文
    fig = plt.figure(dpi=400)
    ax = fig.add_subplot(111)
    ax.plot(thFits[:, 0], thFits[:, 1], color='green', label='理论帕累托前沿')
    ax.scatter(paretoFits[:, 0], paretoFits[:, 1], color='red', label='实际解集')
    ax.legend()
    fig.savefig('test.png', dpi=400)

    print(paretoPops)
Beispiel #4
0
def main(): 
    nIter = 100      
    nChr = 3 
    nPop = 50  
    F = 0.2 
    Cr = 0.9   
    func = function 
    lb = -2 
    rb = 2 
    paretoPops, paretoFits = MODE(nIter, nChr, nPop, F, Cr, func, lb, rb) 
    # print(paretoFits) 
    print(f"paretoFront: {paretoFits.shape}") 

    # 理论最优解集合 
    x = np.linspace(-1/np.sqrt(3), 1/np.sqrt(3), 116).reshape(116,1) 
    X = np.tile(x, 3)  # 理论最佳帕累托解集 
    thFits = fitness(X, function) 

    plt.rcParams['font.sans-serif'] = 'KaiTi'  # 设置显示中文 
    fig = plt.figure(dpi=400) 
    ax = fig.add_subplot(111) 
    ax.plot(thFits[:,0], thFits[:,1], color='green',\
         label="理论帕累托前沿") 
    ax.scatter(paretoFits[:,0], paretoFits[:,1], \
        color='red', label="实际求解") 
    ax.legend() 
    fig.savefig('test.png', dpi=400) 
Beispiel #5
0
def sel(k,l,n,alpha,c,beta):
    w = fitness(0,k,n,c)
    wm = fitness_m(k,n,c)
    p = 0 if wm == 0 else k*w/(n*wm)
    termoInd = comb(n,l)*p**l*(1-p)**(n-l)
    #termoGr = (1-beta+2*beta*pVencer(alpha,k,n)) if beta > 0 else wm
    termoGr = 1-beta+2*beta*pVencer(alpha,k,n)
    return termoGr*termoInd
Beispiel #6
0
def sel(k, l, n, delta, alpha, b, c, w0, beta):
    w = fitness(0, k, n, delta, b, c, w0)
    wm = fitness_m(k, n, delta, b, c, w0)
    p = 0 if wm == 0 else k * w / (n * wm)
    termoInd = scipy.misc.comb(n, l) * p**l * (1 - p)**(n - l)
    #termoGr = (1-beta+2*beta*pVencer(alpha,k,n)) if beta > 0 else wm
    termoGr = 1 - beta + 2 * beta * pVencer(alpha, k, n)
    return termoGr * termoInd
Beispiel #7
0
def sel(k,l,n,delta, alpha,b,c,w0,beta):
    w = fitness(0,k,n,delta,b,c,w0)
    wm = fitness_m(k,n,delta,b,c,w0)
    p = 0 if wm == 0 else k*w/(n*wm)
    termoInd = scipy.misc.comb(n,l)*p**l*(1-p)**(n-l)
    #termoGr = (1-beta+2*beta*pVencer(alpha,k,n)) if beta > 0 else wm
    termoGr = 1-beta+2*beta*pVencer(alpha,k,n)
    return termoGr*termoInd
Beispiel #8
0
def intial_population(population_size, num_queens):
    population = []
    for chromo in range(population_size):
        individual = []
        for gene in range(num_queens):
            new_ind = Chromosome(num_queens)
            individual.append(new_ind)
        individual = fitness(individual)
        population.append(individual)
    return population
Beispiel #9
0
def sel(k, l, n, alpha, c, beta):
    """
        Calculates the average number of groups of type `k`
        that become type `l` by selection forces
    """
    w = fitness(0, c)
    wm = avg_fitness(n, k, c)
    p = 0 if wm == 0 else k * w / (n * wm)
    indiv_term = comb(n, l) * p**l * (1 - p)**(n - l)
    group_term = 1 - beta + 2 * beta * winning_prob(alpha, k, n)
    return group_term * indiv_term
Beispiel #10
0
def rotate(funfcn,Best,fBest,SE,Range,alpha,beta):
	Pop_Lb = np.tile(Range[0],(SE,1))
	Pop_Ub = np.tile(Range[1],(SE,1))
	oldBest = Best
	State = op_rotate(Best,SE,alpha)
	changeRows = State > Pop_Ub
	State[changeRows] = Pop_Ub[changeRows]
	changeRows = State < Pop_Lb
	State[changeRows] = Pop_Lb[changeRows]
	newBest,fGBest = fitness(funfcn,State)
	if fGBest < fBest:
		fBest,Best = fGBest,newBest
		State = op_translate(oldBest,Best,SE,beta)
		changeRows = State > Pop_Ub
		State[changeRows] = Pop_Ub[changeRows]
		changeRows = State < Pop_Lb
		State[changeRows] = Pop_Lb[changeRows]
		newBest,fGBest = fitness(funfcn,State)
		if fGBest < fBest:
			fBest,Best = fGBest,newBest
	return Best,fBest
Beispiel #11
0
def Experiment1():
    #Experiment 1 - loss of gradient1
    pop1 = list()
    pop2 = list()

    for i in range(POP_SIZE):
        pop1.append(resident(dimensions=1))
        pop2.append(resident(dimensions=1))

    for i in range(GENERATIONS):  # repeat
        if (i % 10) == 0:
            print '.',
        #plot data
        Plot(i, pop1 + pop2
             )  #i is generation, pop1+pop2 gives all the residents in one list
        #write data
        Write(pop1, pop2)
        #evaluate fitness of all individuals
        for a in pop1:  #for each member in population 1
            #make a sample of SAMPLE_SIZE from pop2
            sample = list()
            for z in range(SAMPLE_SIZE):
                i = int(math.floor(random.random() * POP_SIZE))
                sample.append(pop2[i])
            a.fitness = fitness(a, sample)

        for a in pop2:  #for each member in population 2
            #make a sample of SAMPLE_SIZE from pop1
            sample = list()
            for z in range(SAMPLE_SIZE):
                i = int(math.floor(random.random() *
                                   POP_SIZE))  #pick one from the population
                sample.append(pop1[i])  #
            a.fitness = fitness(a, sample)

        #select and replace
        pop1 = FPS(pop1)
        pop2 = FPS(pop2)
def substituicao(population, father, children, elitism=0.85, is_elitist=True, is_ultra_elitist=False, loser=[], is_loser=False):
    """Realiza substituição do conjunto de dados"""
    
    father_order = order_by_fitness(father, fitness(father), True)

    children_order = order_by_fitness(children, fitness(children), True)

    population = order_by_fitness(population, fitness(population), False)

    if is_ultra_elitist == True:
        best_pop = father_order + children_order
        best_gen = order_by_fitness(best_pop, fitness(best_pop), True)
        population = order_by_fitness(population, fitness(population), False)
        slice_point = int(len(population)*elitism)
        population = best_gen[0:slice_point] + population[slice_point:]

    elif is_elitist:

        for i in range(int(len(population)/2)):

            if r.random() < elitism:
                if children_order[i] > father_order[i]:
                    population[i] = children_order[i]
                else:
                    population[i] = father_order[i]
            else:
                population[i] = children_order[i]
        
        if is_loser:
            for i in range(int(len(population)/2)):
                population[int(len(population)/2) + i] = loser[i]

    else:

        population = father_order + children_order

    return population
Beispiel #13
0
def NSGA2(nIter, nChr, nPop, pc, pm, etaC, etaM, func, lb, rb):
    """非支配遗传算法主程序 
    Params:
        nIter: 迭代次数 
        nPop: 种群大小 
        pc: 交叉概率 
        pm: 变异概率 
        func: 优化的函数 
        lb: 自变量下界
        rb: 自变量上界 
    """
    # 生成初始种群
    pops = initPops(nPop, nChr, lb, rb)
    fits = fitness(pops, func)

    # 开始第1次迭代
    iter = 1
    while iter <= nIter:
        # 进度条
        print("【进度】【{0:20s}】【正在进行{1}代...】【共{2}代】".\
            format('▋'*int(iter/nIter*20), iter, nIter), end='\r')
        ranks = nonDominationSort(pops, fits)  # 非支配排序
        distances = crowdingDistanceSort(pops, fits, ranks)  # 拥挤度
        pops, fits = select1(nPop, pops, fits, ranks, distances)
        chrpops = crossover(pops, pc, etaC, lb, rb)  # 交叉产生子种群
        chrpops = mutate(chrpops, pm, etaM, lb, rb)  # 变异产生子种群
        chrfits = fitness(chrpops, func)
        # 从原始种群和子种群中筛选
        pops, fits = optSelect(pops, fits, chrpops, chrfits)
        iter += 1
    # 对最后一代进行非支配排序
    ranks = nonDominationSort(pops, fits)  # 非支配排序
    distances = crowdingDistanceSort(pops, fits, ranks)  # 拥挤度
    paretoPops = pops[ranks == 0]
    paretoFits = fits[ranks == 0]
    return paretoPops, paretoFits
Beispiel #14
0
def Experiment1():
	#Experiment 1 - loss of gradient1
	pop1 = list()
	pop2 = list()

	for i in range(POP_SIZE):
		pop1.append(resident(dimensions=1))
		pop2.append(resident(dimensions=1))
	
	for i in range(GENERATIONS): # repeat
		if (i % 10) == 0:
			print '.',
		#plot data
		Plot(i, pop1 + pop2) #i is generation, pop1+pop2 gives all the residents in one list
		#write data
		Write(pop1, pop2)
		#evaluate fitness of all individuals
		for a in pop1: #for each member in population 1
			#make a sample of SAMPLE_SIZE from pop2
			sample = list()
			for z in range(SAMPLE_SIZE):
				i = int(math.floor(random.random() * POP_SIZE))
				sample.append(pop2[i])
			a.fitness = fitness(a, sample)
		
		for a in pop2: #for each member in population 2
			#make a sample of SAMPLE_SIZE from pop1
			sample = list()
			for z in range(SAMPLE_SIZE):
				i = int(math.floor(random.random() * POP_SIZE))#pick one from the population
				sample.append(pop1[i])#
			a.fitness = fitness(a, sample)
		
		#select and replace
		pop1 = FPS(pop1)
		pop2 = FPS(pop2)
Beispiel #15
0
def Test():
	a = resident(size = 10, dimensions = 1)
	print(a._string)
	print(a._value)	
	b = resident(size = 10, dimensions = 1)
	c = resident(size = 10, dimensions = 1)
	population = list()
	population.append(b)
	population.append(c)
	print("values:\n\ta=")
	print(a._value)
	print("\tb=")
	print(b._value)
	print("\tc=")
	print(c._value)
	a.fitness = fitness(a, population)
	print("fitness of a = %d" % a.fitness)
	#test 2D
	a = resident(size = 10)
	b = resident(size = 10)
	c = resident(size = 10)
	a._value = [1, 6]
	b._value = [4, 5]
	c._value = [2, 4]
	population = list()
	population.append(a)
	population.append(b)
	population.append(c)
	print("values:\n\ta=")
	print(a._value)
	print("\tb=")
	print(b._value)
	print("\tc=")
	print(c._value)
	a.fitness = fitness2(a, population)
	b.fitness = fitness2(b, population)
	c.fitness = fitness2(c, population)
	print("fitness2 of a = %d" % a.fitness)
	print("fitness2 of b = %d" % b.fitness)
	print("fitness2 of c = %d" % c.fitness)
	
	a.fitness = fitness3(a, population)
	b.fitness = fitness3(b, population)
	c.fitness = fitness3(c, population)
	print("fitness3 of a = %d" % a.fitness)
	print("fitness3 of b = %d" % b.fitness)
	print("fitness3 of c = %d" % c.fitness)
Beispiel #16
0
def Test():
    a = resident(size=10, dimensions=1)
    print(a._string)
    print(a._value)
    b = resident(size=10, dimensions=1)
    c = resident(size=10, dimensions=1)
    population = list()
    population.append(b)
    population.append(c)
    print("values:\n\ta=")
    print(a._value)
    print("\tb=")
    print(b._value)
    print("\tc=")
    print(c._value)
    a.fitness = fitness(a, population)
    print("fitness of a = %d" % a.fitness)
    #test 2D
    a = resident(size=10)
    b = resident(size=10)
    c = resident(size=10)
    a._value = [1, 6]
    b._value = [4, 5]
    c._value = [2, 4]
    population = list()
    population.append(a)
    population.append(b)
    population.append(c)
    print("values:\n\ta=")
    print(a._value)
    print("\tb=")
    print(b._value)
    print("\tc=")
    print(c._value)
    a.fitness = fitness2(a, population)
    b.fitness = fitness2(b, population)
    c.fitness = fitness2(c, population)
    print("fitness2 of a = %d" % a.fitness)
    print("fitness2 of b = %d" % b.fitness)
    print("fitness2 of c = %d" % c.fitness)

    a.fitness = fitness3(a, population)
    b.fitness = fitness3(b, population)
    c.fitness = fitness3(c, population)
    print("fitness3 of a = %d" % a.fitness)
    print("fitness3 of b = %d" % b.fitness)
    print("fitness3 of c = %d" % c.fitness)
Beispiel #17
0
    def __init__(self, pop_size, LIMITS, param_no, precision, fitness):
        """
        
        :param pop_size: number of chromosomes in population
        :param LIMITS: limits of chromosome's parameters
        :param param_no: number of parameters for a chromosome
        :param precision: precision of parameters' float values
        """

        self.MEMBERS = [
            Chromosome(param_no, LIMITS, precision) for _ in xrange(pop_size)
        ]
        for member in self.MEMBERS:
            member.fitness = (round(fitness(member.params_float), precision))
        self.__fitness = fitness
        self.__precision = precision
        self.__LIMITS = LIMITS
Beispiel #18
0
    def __init__(self, f, x0, ranges=[ ], fmt='f', fitness=Fitness,
                 selection=RouletteWheel, crossover=TwoPoint,
                 mutation=BitToBit, elitist=True):
        '''
        Initializes the population and the algorithm.

        On the initialization of the population, a lot of parameters can be set.
        Those will deeply affect the results. The parameters are:

        :Parameters:
          f
            A multivariable function to be evaluated. The nature of the
            parameters in the objective function will depend of the way you want
            the genetic algorithm to process. It can be a standard function that
            receives a one-dimensional array of values and computes the value of
            the function. In this case, the values will be passed as a tuple,
            instead of an array. This is so that integer, floats and other types
            of values can be passed and processed. In this case, the values will
            depend of the format string (see below)

            If you don't supply a format, your objective function will receive a
            ``Chromosome`` instance, and it is the responsability of the
            function to decode the array of bits in any way. Notice that, while
            it is more flexible, it is certainly more difficult to deal with.
            Your function should process the bits and compute the return value
            which, in any case, should be a scalar.

            Please, note that genetic algorithms maximize functions, so project
            your objective function accordingly. If you want to minimize a
            function, return its negated value.

          x0
            A population of first estimates. This is a list, array or tuple of
            one-dimension arrays, each one corresponding to an estimate of the
            position of the minimum. The population size of the algorithm will
            be the same as the number of estimates in this list. Each component
            of the vectors in this list are one of the variables in the function
            to be optimized.

          ranges
            Since messing with the bits can change substantially the values
            obtained can diverge a lot from the maximum point. To avoid this,
            you can specify a range for each of the variables. ``range``
            defaults to ``[ ]``, this means that no range checkin will be done.
            If given, then every variable will be checked. There are two ways to
            specify the ranges.

            It might be a tuple of two values, ``(x0, x1)``, where ``x0`` is the
            start of the interval, and ``x1`` its end. Obviously, ``x0`` should
            be smaller than ``x1``. If ``range`` is given in this way, then this
            range will be used for every variable.

            It can be specified as a list of tuples with the same format as
            given above. In that case, the list must have one range for every
            variable specified in the format and the ranges must appear in the
            same order as there. That is, every variable must have a range
            associated to it.

          fmt
            A ``struct``-format string. The ``struct`` module is a standard
            Python module that packs and unpacks informations in bits. These
            are used to inform the algorithm what types of data are to be used.
            For example, if you are maximizing a function of three real
            variables, the format should be something like ``"fff"``. Any type
            supported by the ``struct`` module can be used. The GA will decode
            the bit array according to this format and send it as is to your 
            fitness function -- your function *must* know what to do with them.

            Alternatively, the format can be an integer. In that case, the GA
            will not try to decode the bit sequence. Instead, the bits are
            passed without modification to the objective function, which must
            deal with them. Notice that, if this is used this way, the
            ``ranges`` property (see below) makes no sense, so it is set to
            ``None``. Also, no sanity checks will be performed.

            It defaults to `"f"`, that is, a single floating point variable.

          fitness
            A fitness method to be applied over the objective function. This
            parameter must be a ``Fitness`` instance or subclass. It will be
            applied over the objective function to compute the fitness of every
            individual in the population. Please, see the documentation on the
            ``Fitness`` class.

          selection
            This specifies the selection method. You can use one given in the
            ``selection`` sub-module, or you can implement your own. In any
            case, the ``selection`` parameter must be an instance of
            ``Selection`` or of a subclass. Please, see the documentation on the
            ``selection`` module for more information. Defaults to
            ``RouletteWheel``. If made ``None``, then selection will not be
            present in the GA.

          crossover
            This specifies the crossover method. You can use one given in the
            ``crossover`` sub-module, or you can implement your own. In any
            case, the ``crossover`` parameter must be an instance of
            ``Crossover`` or of a subclass. Please, see the documentation on the
            ``crossover`` module for more information. Defaults to
            ``TwoPoint``. If made ``None``, then crossover will not be
            present in the GA.

          mutation
            This specifies the mutation method. You can use one given in the
            ``mutation`` sub-module, or you can implement your own. In any
            case, the ``mutation`` parameter must be an instance of ``Mutation``
            or of a subclass. Please, see the documentation on the ``mutation``
            module for more information. Defaults to ``BitToBit``.  If made
            ``None``, then mutation will not be present in the GA.

          elitist
            Defines if the population is elitist or not. An elitist population
            will never discard the fittest individual when a new generation is
            computed. Defaults to ``True``.
        '''
        list.__init__(self, [ ])
        self.__fx = [ ]
        for x in x0:
            x = array(x).ravel()
            c = Chromosome(fmt)
            c.encode(tuple(x))
            self.append(c)
            self.__fx.append(f(x))
        self.__f = f
        self.__csize = self[0].size
        self.elitist = elitist
        '''If ``True``, then the population is elitist.'''

        if type(fmt) == int:
            self.ranges = None
        elif ranges is None:
            self.ranges = zip(amin(self, axis=0), amax(self, axis=1))
        else:
            ranges = list(ranges)
            if len(ranges) == 1:
                self.ranges = array(ranges * len(x0[0]))
            else:
                self.ranges = array(ranges)
                '''Holds the ranges for every variable. Although it is a
                writable property, care should be taken in changing parameters
                before ending the convergence.'''

        # Sanitizes the first estimate. It is not expected that the values
        # received as first estimates are outside the ranges, but a check is
        # made anyway. If any estimate is outside the bounds, a new random
        # vector is choosen.
        if self.ranges is not None: self.sanity()

        # Verifies the validity of the fitness method
        try:
            issubclass(fitness, Fitness)
            fitness = fitness()
        except TypeError:
            pass
        if not isinstance(fitness, Fitness):
            raise TypeError, 'not a valid fitness function'
        else:
            self.__fit = fitness
        self.__fitness = self.__fit(self.__fx)

        # Verifies the validity of the selection method
        try:
            issubclass(selection, Selection)
            selection = selection()
        except TypeError:
            pass
        if not isinstance(selection, Selection):
            raise TypeError, 'not a valid selection method'
        else:
            self.__select = selection

        # Verifies the validity of the crossover method
        try:
            issubclass(crossover, Crossover)
            crossover = crossover()
        except TypeError:
            pass
        if not isinstance(crossover, Crossover) and crossover is not None:
            raise TypeError, 'not a valid crossover method'
        else:
            self.__crossover = crossover

        # Verifies the validity of the mutation method
        try:
            issubclass(mutation, Mutation)
            mutation = mutation()
        except TypeError:
            pass
        if not isinstance(mutation, Mutation) and mutation is not None:
            raise TypeError, 'not a valid mutation method'
        else:
            self.__mutate = mutation
Beispiel #19
0
    def __init__(self,
                 f,
                 x0,
                 ranges=[],
                 fmt='f',
                 fitness=Fitness,
                 selection=RouletteWheel,
                 crossover=TwoPoint,
                 mutation=BitToBit,
                 elitist=True):
        '''
        Initializes the population and the algorithm.

        On the initialization of the population, a lot of parameters can be set.
        Those will deeply affect the results. The parameters are:

        :Parameters:
          f
            A multivariable function to be evaluated. The nature of the
            parameters in the objective function will depend of the way you want
            the genetic algorithm to process. It can be a standard function that
            receives a one-dimensional array of values and computes the value of
            the function. In this case, the values will be passed as a tuple,
            instead of an array. This is so that integer, floats and other types
            of values can be passed and processed. In this case, the values will
            depend of the format string (see below)

            If you don't supply a format, your objective function will receive a
            ``Chromosome`` instance, and it is the responsability of the
            function to decode the array of bits in any way. Notice that, while
            it is more flexible, it is certainly more difficult to deal with.
            Your function should process the bits and compute the return value
            which, in any case, should be a scalar.

            Please, note that genetic algorithms maximize functions, so project
            your objective function accordingly. If you want to minimize a
            function, return its negated value.

          x0
            A population of first estimates. This is a list, array or tuple of
            one-dimension arrays, each one corresponding to an estimate of the
            position of the minimum. The population size of the algorithm will
            be the same as the number of estimates in this list. Each component
            of the vectors in this list are one of the variables in the function
            to be optimized.

          ranges
            Since messing with the bits can change substantially the values
            obtained can diverge a lot from the maximum point. To avoid this,
            you can specify a range for each of the variables. ``range``
            defaults to ``[ ]``, this means that no range checkin will be done.
            If given, then every variable will be checked. There are two ways to
            specify the ranges.

            It might be a tuple of two values, ``(x0, x1)``, where ``x0`` is the
            start of the interval, and ``x1`` its end. Obviously, ``x0`` should
            be smaller than ``x1``. If ``range`` is given in this way, then this
            range will be used for every variable.

            It can be specified as a list of tuples with the same format as
            given above. In that case, the list must have one range for every
            variable specified in the format and the ranges must appear in the
            same order as there. That is, every variable must have a range
            associated to it.

          fmt
            A ``struct``-format string. The ``struct`` module is a standard
            Python module that packs and unpacks informations in bits. These
            are used to inform the algorithm what types of data are to be used.
            For example, if you are maximizing a function of three real
            variables, the format should be something like ``"fff"``. Any type
            supported by the ``struct`` module can be used. The GA will decode
            the bit array according to this format and send it as is to your 
            fitness function -- your function *must* know what to do with them.

            Alternatively, the format can be an integer. In that case, the GA
            will not try to decode the bit sequence. Instead, the bits are
            passed without modification to the objective function, which must
            deal with them. Notice that, if this is used this way, the
            ``ranges`` property (see below) makes no sense, so it is set to
            ``None``. Also, no sanity checks will be performed.

            It defaults to `"f"`, that is, a single floating point variable.

          fitness
            A fitness method to be applied over the objective function. This
            parameter must be a ``Fitness`` instance or subclass. It will be
            applied over the objective function to compute the fitness of every
            individual in the population. Please, see the documentation on the
            ``Fitness`` class.

          selection
            This specifies the selection method. You can use one given in the
            ``selection`` sub-module, or you can implement your own. In any
            case, the ``selection`` parameter must be an instance of
            ``Selection`` or of a subclass. Please, see the documentation on the
            ``selection`` module for more information. Defaults to
            ``RouletteWheel``. If made ``None``, then selection will not be
            present in the GA.

          crossover
            This specifies the crossover method. You can use one given in the
            ``crossover`` sub-module, or you can implement your own. In any
            case, the ``crossover`` parameter must be an instance of
            ``Crossover`` or of a subclass. Please, see the documentation on the
            ``crossover`` module for more information. Defaults to
            ``TwoPoint``. If made ``None``, then crossover will not be
            present in the GA.

          mutation
            This specifies the mutation method. You can use one given in the
            ``mutation`` sub-module, or you can implement your own. In any
            case, the ``mutation`` parameter must be an instance of ``Mutation``
            or of a subclass. Please, see the documentation on the ``mutation``
            module for more information. Defaults to ``BitToBit``.  If made
            ``None``, then mutation will not be present in the GA.

          elitist
            Defines if the population is elitist or not. An elitist population
            will never discard the fittest individual when a new generation is
            computed. Defaults to ``True``.
        '''
        list.__init__(self, [])
        self.__fx = []
        for x in x0:
            x = array(x).ravel()
            c = Chromosome(fmt)
            c.encode(tuple(x))
            self.append(c)
            self.__fx.append(f(x))
        self.__f = f
        self.__csize = self[0].size
        self.elitist = elitist
        '''If ``True``, then the population is elitist.'''

        if type(fmt) == int:
            self.ranges = None
        elif ranges is None:
            self.ranges = zip(amin(self, axis=0), amax(self, axis=1))
        else:
            ranges = list(ranges)
            if len(ranges) == 1:
                self.ranges = array(ranges * len(x0[0]))
            else:
                self.ranges = array(ranges)
                '''Holds the ranges for every variable. Although it is a
                writable property, care should be taken in changing parameters
                before ending the convergence.'''

        # Sanitizes the first estimate. It is not expected that the values
        # received as first estimates are outside the ranges, but a check is
        # made anyway. If any estimate is outside the bounds, a new random
        # vector is choosen.
        if self.ranges is not None: self.sanity()

        # Verifies the validity of the fitness method
        try:
            issubclass(fitness, Fitness)
            fitness = fitness()
        except TypeError:
            pass
        if not isinstance(fitness, Fitness):
            raise TypeError, 'not a valid fitness function'
        else:
            self.__fit = fitness
        self.__fitness = self.__fit(self.__fx)

        # Verifies the validity of the selection method
        try:
            issubclass(selection, Selection)
            selection = selection()
        except TypeError:
            pass
        if not isinstance(selection, Selection):
            raise TypeError, 'not a valid selection method'
        else:
            self.__select = selection

        # Verifies the validity of the crossover method
        try:
            issubclass(crossover, Crossover)
            crossover = crossover()
        except TypeError:
            pass
        if not isinstance(crossover, Crossover) and crossover is not None:
            raise TypeError, 'not a valid crossover method'
        else:
            self.__crossover = crossover

        # Verifies the validity of the mutation method
        try:
            issubclass(mutation, Mutation)
            mutation = mutation()
        except TypeError:
            pass
        if not isinstance(mutation, Mutation) and mutation is not None:
            raise TypeError, 'not a valid mutation method'
        else:
            self.__mutate = mutation
## Now we have to sort the globalScheduleMap on value i.e fitness.
## But as a map has no order inherently, it would be a wise decision
## to get a sorted list of tuples of the form [(timeTableSchedule,fitness)],
## where the elements of the list are sorted on the fitness value

sortedGlobalScheduleMapList=sorted(globalScheduleMap.iteritems(),key=operator.itemgetter(1),reverse=True)

while(sortedGlobalScheduleMapList[0][1]<=requiredFitness):
		## Now perform crossover of first numInitialSelectedSchedules pairs of schedules and store them in a list 
		newTimeTablesList=[]
		for i in range(numInitialSelectedSchedules):
			newTimeTablesList+=[crossover(sortedGlobalScheduleMapList[2*i][0],sortedGlobalScheduleMapList[2*i+1][0])]
			
		## Perform mutation of the generated Time Tables
		for i in range(len(newTimeTablesList)):
			newTimeTablesList[i]=mutate(newTimeTablesList[i])

		## Check if the mutated time tables finess is better than the timetable with least fitness in the sortedGlobalScheduleMapList
		## If so replace that time table in the globalScheduleMap with the current map
		## else skip the current map
		for i in range (len(newTimeTablesList)):
			curFitness=fitness(newTimeTablesList[i])
			if curFitness>sortedGlobalScheduleMapList[len(sortedGlobalScheduleMapList)-1][1]):
				globalScheduleMap.pop(sortedGlobalScheduleMapList[len(sortedGlobalScheduleMapList)-1][0])
				globalScheduleMap[newTimeTablesList[i]]=curFitness
				## Update the sortedGlobalScheduleMapList as the globalScheduleMap is updated
				sortedGlobalScheduleMapList=sorted(globalScheduleMap.iteritems(),key=operator.itemgetter(1),reverse=True)

print "Timetable Schedule is finalized with required Fitness"
print sortedGlobalScheduleMapList[0][0]