Exemplo n.º 1
0
 def __init__(self, max_generation=1, population_size=10, mutation=0.2, elite=0.1):
     self.__mutagen = mutation
     self.__elite = elite
     self.__maxGeneration = max_generation
     self._population = Population(population_size)
     self._newGeneration = Population(population_size)
Exemplo n.º 2
0
class GeneticAlgorithm(object):
    def __init__(self, max_generation=1, population_size=10, mutation=0.2, elite=0.1):
        self.__mutagen = mutation
        self.__elite = elite
        self.__maxGeneration = max_generation
        self._population = Population(population_size)
        self._newGeneration = Population(population_size)

    def create_population(self, workers, graph):
        self._population.create_area(workers, graph)

    def mutation(self, graph):
        specimens = random.sample(
            self._newGeneration.flock.keys(), int(round(self._newGeneration.get_count() * self.__mutagen))
        )
        for specimen in specimens:
            operator = self.__selectMutateOperator(random.random())
            newSpecimen = operator(specimen, graph)
            if not newSpecimen.is_valid():
                print newSpecimen
            del (self._newGeneration.flock[specimen])
            self._newGeneration.add_spiec(newSpecimen)

    def __replacement(self, specimen, *args):
        """
    Заменяет в одном из путей клиента на одного из необслуженных
    @param specimen Обход графа, который необходимо мутировать
    @param graph исходный граф
    @return Нового члена общества
    """
        t1 = time.time()
        unVisit = get_unvisit_client(specimen, args[0])
        if unVisit:
            newSpecimen = copy.deepcopy(specimen)
            random.shuffle(unVisit)
            for replVertex in unVisit:
                temp = newSpecimen.route.keys()
                random.shuffle(temp)
                for worker in temp:
                    if worker.is_valid_client(replVertex):
                        changePath = newSpecimen.route[worker]
                        flag = False
                        if changePath.get_len():
                            for i in xrange(1, len(changePath._vertex) - 1):
                                delVertex = changePath._vertex[i]
                                changePath.remove_vertex(delVertex)
                                changePath.insert_vertex(i, replVertex)
                                if newSpecimen.is_valid():
                                    flag = True
                                    break
                                newSpecimen.route[worker] = copy.deepcopy(specimen.route[worker])
                                changePath = newSpecimen.route[worker]
                        else:

                            changePath.insert_vertex(1, replVertex)
                            flag = True
                        if flag:
                            t2 = time.time()
                            print "Mutation(replacement): {0}".format(t2 - t1)
                            return newSpecimen
        return specimen

    def __delete(self, specimen, *args):
        t1 = time.time()
        stop = 0
        while stop < 30 and specimen.get_client_count():
            experimental = copy.deepcopy(specimen)
            path = random.choice(experimental.route.values())
            if path.get_len():
                vertex = random.choice(path._vertex[1:-1])
                path.remove_vertex(vertex)
                t2 = time.time()
                print "Mutation(delete): {0}".format(t2 - t1)
                return experimental
            stop += 1
        return specimen

    def __insert(self, specimen, *args):
        """
    Мутация путем вставки в путь необслуженного клиента
    @param specimen Обход графа, который необходимо мутировать
    @param args Необходим для совмещения с другими функциями мутации
    @return Нового члена общества
    """
        t1 = time.time()
        unVisit = get_unvisit_client(specimen, args[0])
        if unVisit:
            random.shuffle(unVisit)
            for insVertex in unVisit:
                clone = copy.deepcopy(specimen)
                workers = clone.route.keys()
                random.shuffle(workers)
                for worker in workers:
                    if worker.is_valid_client(insVertex):
                        etalonPath = specimen.route[worker]
                        for index in xrange(1, etalonPath.get_len() + 2):
                            insPath = clone.route[worker]
                            insPath.insert_vertex(index, insVertex)
                            if clone.is_valid():
                                t2 = time.time()
                                print "Mutation(insert): {0}".format(t2 - t1)
                                return clone
                            clone = copy.deepcopy(specimen)
        return specimen

    def __swapIn(self, specimen, *args):
        """
    Мутация путем обмена клиентов между путями монтеров
    @param specimen Обход графа, который необходимо мутировать
    @param args Необходим для совмещения с другими функциями мутации
    @return Нового члена общества
    """
        t1 = time.time()
        stop = 0
        while True and specimen.get_client_count() and stop < 30:
            mutateVertex = {}
            choiceRoute = copy.deepcopy(specimen.route)
            for i in xrange(2):
                worker = random.choice(choiceRoute.keys())
                if choiceRoute[worker].get_len():
                    choiceVertex = random.choice(choiceRoute[worker]._vertex[1:-1])
                    del (choiceRoute[worker])
                    mutateVertex[worker] = choiceVertex
                else:
                    mutateVertex[worker] = None
            flag = True
            if len(list(set(mutateVertex.values()))) > 1:
                for k in mutateVertex:
                    for v in mutateVertex.values():
                        if v and not k.is_valid_client(v):
                            flag = False

                if flag:
                    experimental = copy.deepcopy(specimen)
                    experimental.swap(mutateVertex.values())
                    if experimental.is_valid():
                        t2 = time.time()
                        print "Mutation(swap): {0}".format(t2 - t1)
                        return experimental
            stop += 1
        return specimen

    def __shuffle(self, specimen, *args):
        t1 = time.time()
        clone = copy.deepcopy(specimen)
        allPath = [p for p in clone.route.values() if p.get_len() > 1]
        if allPath:
            random.shuffle(allPath)
            for path in allPath:
                etalon = copy.deepcopy(path)
                vertex = path._vertex[1:-1]
                stop = 0
                while stop < 10:
                    stop += 1
                    random.shuffle(vertex)
                    path._vertex[1:-1] = vertex
                    path.remove_useless_edge()
                    if clone.is_valid():
                        t2 = time.time()
                        print "Shuffle: {0}".format(t2 - t1)
                        return clone
                    path = etalon

        return specimen

    def __selectMutateOperator(self, chance):
        if chance < 0.1:
            operator = self.__delete
        elif chance < 0.25:
            operator = self.__replacement
        elif chance < 0.4:
            operator = self.__insert
        elif chance < 0.7:
            operator = self.__shuffle
        else:
            operator = self.__swapIn
        return operator

    def crossover(self, parents):
        """
    BCRC оператор скрещивания
    @param parents Список с родителями
    @return список новых потомка
    """
        childCnt = len(parents) / 2
        offspring = []
        for i in xrange(childCnt):
            childs = copy.deepcopy(random.sample(parents, 2))
            if random.random() > 0.85:
                parents = list(set(parents) - set(childs))
                replacePath = [
                    copy.deepcopy(random.choice(childs[0].route.values())),
                    copy.deepcopy(random.choice(childs[1].route.values())),
                ]

                for i, j in zip(replacePath[0]._vertex[1:-1], replacePath[1]._vertex[1:-1]):
                    childs[1].remove_vertex(i)
                    childs[0].remove_vertex(j)
                replaceVertex = replacePath[0]._vertex[1:-1] + replacePath[1]._vertex[1:-1]
                for vertex in replaceVertex:
                    for individ in childs:
                        if not individ.has_vertex(vertex):
                            individ.insert_vertex(vertex)
            offspring.extend(childs)
        return offspring

    def selection(self):
        for spec in sorted(self._population.flock.iteritems(), key=operator.itemgetter(1), reverse=True):
            if self._newGeneration.get_count() >= self._newGeneration._size:
                break
            self._newGeneration.add_spiec(spec[0])

        self._population = copy.deepcopy(self._newGeneration)
        self._newGeneration.clear()

    def run(self, workers, graph):
        t1 = time.time()
        self.create_population(workers, graph)
        t2 = time.time()
        print "Create population: {0}".format(t2 - t1)
        for j in xrange(self.__maxGeneration):
            print "Поколение: {0}".format(j)
            parents = self._population.get_parents()
            t3 = time.time()
            childs = self.crossover(parents)
            t4 = time.time()
            print "Crossover: {0}".format(t4 - t3)
            for child in childs:
                self._newGeneration.add_spiec(child)
            print self._newGeneration.get_count()
            self.mutation(graph)
            self.selection()
            best = sorted(self._population.flock.iteritems(), key=operator.itemgetter(1))[-1]
            print "Лучший: " + str(best[1])
            print "Худший: " + str(sorted(self._population.flock.iteritems(), key=operator.itemgetter(1))[0][1])
            print [x._vertex for x in best[0].route.values()]
            print "=========================="