def optimizedBestSearch(fname, max_iter=100, pop_size=50, percentToSwitch=5):
    city_locs = tsp.load_city_locs(fname)
    n = len(city_locs)
    curr_gen = [tsp.rand_perm(n) for i in range(pop_size)]
    curr_gen = [(tsp.total_dist(p, city_locs), p) for p in curr_gen]
    curr_gen.sort()

    bestScore = curr_gen[0][0]
    bestPermuation = curr_gen[0][1]
    useMutateSearch = False

    print(
        f'Optimized bestEdges("{fname}", max_iter={max_iter}, pop_size={pop_size}) ...'
    )
    for i in range(max_iter):
        print("iteration: ", i)
        top_half = [p[1] for p in curr_gen[:int(pop_size / 2)]]
        next_gen = top_half[:]
        while len(next_gen) < pop_size:
            parentA = random.choice(top_half)
            parentB = random.choice(top_half)
            while parentA == parentB:
                parentA = random.choice(top_half)
                parentB = random.choice(top_half)
            if (useMutateSearch):
                first = parentA[:]
                second = parentB[:]
            else:
                first, second = bestEdgesSearch(parentA, parentB, city_locs)

            tsp.do_rand_swap(first)
            tsp.do_rand_swap(second)
            next_gen.append(first)
            next_gen.append(second)

        next_gen = next_gen[:pop_size]
        assert len(next_gen) == pop_size
        curr_gen = [(tsp.total_dist(p, city_locs), p) for p in next_gen]
        curr_gen.sort()

        useMutateSearch = ifSwitchToMutate(bestScore, curr_gen[0][0],
                                           percentToSwitch)

        if (curr_gen[0][0] < bestScore):
            bestScore = curr_gen[0][0]
            bestPermuation = curr_gen[0][1]

    print(
        f'... Optimized bestEdges("{fname}", max_iter={max_iter}, pop_size={pop_size})'
    )
    print()
    print(
        f'After {max_iter} generations of {pop_size} permutations, the best is:'
    )
    print(f'score = {bestScore}')
    print(bestPermuation)
    assert tsp.is_good_perm(bestPermuation)
def bestEdgesSearch(parentA, parentB, cities):

    n = len(parentA)
    A = parentA[:]
    B = parentB[:]

    # Retrieve best vertices from best edges
    bestVerticesA = getBestEdgeVertices(A, cities)
    bestVerticesB = getBestEdgeVertices(B, cities)

    # Marking vertices that aren't in best edges as -1
    bestVerticesA = [-1 if x not in bestVerticesA else x for x in A]
    bestVerticesB = [-1 if x not in bestVerticesB else x for x in B]

    # Making offspring
    offSpringA = makePermBestEdges(bestVerticesA, B)
    offSpringB = makePermBestEdges(bestVerticesB, A)

    assert tsp.is_good_perm(offSpringA)
    assert tsp.is_good_perm(offSpringB)

    return offSpringA, offSpringB
Example #3
0
def orderCrossover(parentA, parentB):
    assert tsp.is_good_perm(parentA)
    assert tsp.is_good_perm(parentB)
    assert len(parentA) == len(parentB)
    n = len(parentA)

    firstCutPoint, secondCutPoint = generateCrosspoints(n)

    # Split the parents up to sublists
    # - parent 1
    leftParentA, middleParentA, rightParentA = splitParent(
        parentA, firstCutPoint, secondCutPoint)
    # - parent 2
    leftParentB, middleParentB, rightParentB = splitParent(
        parentB, firstCutPoint, secondCutPoint)

    offspringA = makeOffSpringOrder(middleParentA,
                                    rightParentB + leftParentB + middleParentB,
                                    firstCutPoint)
    offspringB = makeOffSpringOrder(middleParentB,
                                    rightParentA + leftParentA + middleParentA,
                                    firstCutPoint)
    return offspringA, offspringB
Example #4
0
def partiallyMappedCrossover(parentA, parentB):
    assert tsp.is_good_perm(parentA)
    assert tsp.is_good_perm(parentB)
    assert len(parentA) == len(parentB)
    n = len(parentA)

    # Generate cut points for partitoning
    firstCutPoint, secondCutPoint = generateCrosspoints(n)

    # Split the parents up to sublists
    # - parent 1
    leftParentA, middleParentA, rightParentA = splitParent(
        parentA, firstCutPoint, secondCutPoint)

    # - parent 2
    leftParentB, middleParentB, rightParentB = splitParent(
        parentB, firstCutPoint, secondCutPoint)
    # Make offspring
    offspringA = makeOffspringPartialMap(leftParentA, rightParentA,
                                         middleParentA, middleParentB)
    offspringB = makeOffspringPartialMap(leftParentB, rightParentB,
                                         middleParentB, middleParentA)

    return offspringA, offspringB
Example #5
0
def orderCrossoverTest(fname, max_iter, pop_size):
    city_locs = tsp.load_city_locs(fname)
    n = len(city_locs)
    # generate permutations for a specific population size
    curr_gen = [tsp.rand_perm(n) for i in range(pop_size)]
    # per population calculate total distance
    curr_gen = [(tsp.total_dist(p, city_locs), p) for p in curr_gen]
    curr_gen.sort()
    assert len(curr_gen) == pop_size

    print(
        f'orderCrossover("{fname}", max_iter={max_iter}, pop_size={pop_size}) ...'
    )
    for i in range(max_iter):
        # copy the top 50% of the population to the next generation, and for the rest randomly
        # cross-breed pairs
        top_half = [p[1] for p in curr_gen[:int(pop_size / 2)]]
        next_gen = top_half[:]
        while len(next_gen) < pop_size:
            parentA = random.choice(top_half)
            parentB = random.choice(top_half)
            while parentA == parentB:
                parentA = random.choice(top_half)
                parentB = random.choice(top_half)
            first, second = orderCrossover(parentA, parentB)
            tsp.do_rand_swap(first)
            tsp.do_rand_swap(second)

            next_gen.append(first)
            next_gen.append(second)

        next_gen = next_gen[:pop_size]

        # create the next generation of (score, permutations) pairs
        assert len(next_gen) == pop_size
        curr_gen = [(tsp.total_dist(p, city_locs), p) for p in next_gen]
        curr_gen.sort()

    print(
        f'... orderCrossover("{fname}", max_iter={max_iter}, pop_size={pop_size})'
    )
    print()
    print(
        f'After {max_iter} generations of {pop_size} permutations, the best is:'
    )
    print(f'score = {curr_gen[0][0]}')
    # print(curr_gen[0][1])
    assert tsp.is_good_perm(curr_gen[0][1])
Example #6
0
def GA_mutate_search(fname, max_iter, prev_pop):

    pop_size = len(prev_pop)
    city_locs = tsp.load_city_locs(fname)
    n = len(city_locs)

    curr_gen = prev_pop
    curr_gen.sort()

    scores = []
    print(
        f'mutate_search("{fname}", max_iter={max_iter}, pop_size={pop_size}) ...'
    )
    for i in range(max_iter):
        # put best permutation from curr_gen into next generation unchanged
        scores.append(curr_gen[0][0])
        best_curr_gen = curr_gen[0][1]
        next_gen = [best_curr_gen]

        # the rest of the next generation is filled with random swap-mutations
        # of best_curr_gen
        # for j in range(pop_size-1):
        #     perm = best_curr_gen[:]  # make a copy of best_curr_gen
        #     tsp.do_rand_swap(perm)       # randomly swap two cities
        #     next_gen.append(perm)    # add it to next_gen

        with concurrent.futures.ThreadPoolExecutor(max_workers=n) as executor:
            futures = {
                executor.submit(mutate_thread_full, best_curr_gen): j
                for j in range(pop_size - 1)
            }
            for future in concurrent.futures.as_completed(futures):
                next_gen.append(future.result())

        # create the next generation of (score, permutations) pairs
        assert len(next_gen) == pop_size
        curr_gen = [(tsp.total_dist(p, city_locs), p) for p in next_gen]
        curr_gen.sort()

    # print(f'... mutate_search("{fname}", max_iter={max_iter}, pop_size={pop_size})')
    # print()
    # print(f'After {max_iter} generations of {pop_size} permutations, the best is:')
    # print(f'score = {curr_gen[0][0]}')
    # print(curr_gen[0][1])
    assert tsp.is_good_perm(curr_gen[0][1])

    return curr_gen, scores
Example #7
0
def GA_crossover_search(fname, max_iter, prev_pop):

    pop_size = len(prev_pop)
    city_locs = tsp.load_city_locs(fname)
    n = len(city_locs)

    curr_gen = prev_pop

    scores = []
    print(
        f'crossover_search("{fname}", max_iter={max_iter}, pop_size={pop_size}) ...'
    )
    for i in range(max_iter):
        # copy the top 50% of the population to the next generation, and for the rest randomly
        # cross-breed pairs
        scores.append(curr_gen[0][0])
        top_half = [p[1] for p in curr_gen[:int(n / 2)]]
        next_gen = top_half[:]
        while len(next_gen) < pop_size:
            s = random.choice(top_half)
            t = random.choice(top_half)
            first, second = tsp.pmx(s, t)
            next_gen.append(first)
            next_gen.append(second)

        next_gen = next_gen[:pop_size]

        # create the next generation of (score, permutations) pairs
        assert len(next_gen) == pop_size
        curr_gen = [(tsp.total_dist(p, city_locs), p) for p in next_gen]
        curr_gen.sort()

    # print(f'... crossover_search("{fname}", max_iter={max_iter}, pop_size={pop_size})')
    # print()
    # print(f'After {max_iter} generations of {pop_size} permutations, the best is:')
    # print(f'score = {curr_gen[0][0]}')
    # print(curr_gen[0][1])
    assert tsp.is_good_perm(curr_gen[0][1])

    return curr_gen, scores