Example #1
0
def sa_optimize_step(nodes, solution, number_of_nodes, t):
    global nn
    # Pick X and Y at random.
    ci = random.randint(0, number_of_nodes - 1)
    yi = (ci + 1) % number_of_nodes
    xi = random.randint(0, number_of_nodes - 1)
    zi = (xi + 1) % number_of_nodes

    if xi != ci and xi != yi:
        c = solution[ci]
        y = solution[yi]
        x = solution[xi]
        z = solution[zi]
        cy = length(c, y)
        xz = length(x, z)
        cx = length(c, x)
        yz = length(y, z)

        gain = (cy + xz) - (cx + yz)
        if gain < 0:
            # We only accept a negative gain conditionally
            # The probability is based on the magnitude of the gain
            # and the temperature.
            u = math.exp(gain / t)
        elif gain > 0.05:
            u = 1  # always except a good gain.
        else:
            u = 0  # No idea why I did this....

        # random chance, picks a number in [0,1)
        if (random.random() < u):
            nn = nn + 1
            #print "      ", gain
            # Make a new solution with both edges swapped.
            new_solution = range(0, number_of_nodes)
            new_solution[0] = solution[ci]
            n = 1
            while xi != yi:
                new_solution[n] = solution[xi]
                n = n + 1
                xi = (xi - 1) % number_of_nodes
            new_solution[n] = solution[yi]
            n = n + 1
            while zi != ci:
                new_solution[n] = solution[zi]
                n = n + 1
                zi = (zi + 1) % number_of_nodes

            # Create an animation frame for this step
            if anim:
                frame(nodes, new_solution, number_of_nodes, t, c, y, x, z,
                      gain)

            return new_solution
        else:
            return solution
    else:
        return solution
Example #2
0
def area_triangle(n1, n2, n3):
    # Area of triangle via Heron's Formula
    # <https://en.wikipedia.org/wiki/Heron%27s_formula>
    a = length(n1, n2)
    b = length(n2, n3)
    c = length(n3, n1)
    p = (a + b + c)/2.0
    area = math.sqrt(p*(p-a)*(p-b)*(p-c))
    return area
Example #3
0
def area_triangle(n1, n2, n3):
    # Area of triangle via Heron's Formula
    # <https://en.wikipedia.org/wiki/Heron%27s_formula>
    a = length(n1, n2)
    b = length(n2, n3)
    c = length(n3, n1)
    p = (a + b + c)/2.0
    area = math.sqrt(p*(p-a)*(p-b)*(p-c))
    return area
Example #4
0
def sa_optimize_step(nodes, solution, number_of_nodes, t):
    global nn
    # Pick X and Y at random.
    ci = random.randint(0, number_of_nodes-1)
    yi = (ci + 1) % number_of_nodes
    xi = random.randint(0, number_of_nodes-1)
    zi = (xi + 1) % number_of_nodes

    if xi != ci and xi != yi:
        c = solution[ci]
        y = solution[yi]
        x = solution[xi]
        z = solution[zi]
        cy = length(c, y)
        xz = length(x, z)
        cx = length(c, x)
        yz = length(y, z)

        gain = (cy + xz) - (cx + yz)
        if gain < 0:
            # We only accept a negative gain conditionally
            # The probability is based on the magnitude of the gain
            # and the temperature.
            u = math.exp( gain / t )
        elif gain > 0.05:
            u = 1 # always except a good gain.
        else:
            u = 0 # No idea why I did this....

        # random chance, picks a number in [0,1)
        if (random.random() < u):
            nn = nn + 1
            #print "      ", gain
            # Make a new solution with both edges swapped.
            new_solution = range(0,number_of_nodes)
            new_solution[0] = solution[ci]
            n = 1
            while xi != yi:
                new_solution[n] = solution[xi]
                n = n + 1
                xi = (xi-1)%number_of_nodes
            new_solution[n] = solution[yi]
            n = n + 1
            while zi != ci:
                new_solution[n] = solution[zi]
                n = n + 1
                zi = (zi+1)%number_of_nodes

            # Create an animation frame for this step
            frame(nodes, new_solution, number_of_nodes, t, c, y, x, z, gain)

            return new_solution
        else:
            return solution
    else:
        return solution
Example #5
0
def optimize(nodes, solution, sn, t):
    global nn
    # Pick X and Y at random.
    ci = random.randint(0, sn - 1)
    yi = (ci + 1) % sn
    xi = random.randint(0, sn - 1)
    zi = (xi + 1) % sn

    if xi != ci and xi != yi:
        c = solution[ci]
        y = solution[yi]
        x = solution[xi]
        z = solution[zi]
        cy = length(c, y)
        xz = length(x, z)
        cx = length(c, x)
        yz = length(y, z)

        gain = (cy + xz) - (cx + yz)
        if gain < 0:
            # For a negative gain we only except
            # it depending on the magnitude in combination
            # with the temperature.
            u = math.exp(gain / t)
        elif gain > 0.05:
            u = 1  # always except a good gain.
        else:
            u = 0  # No idea why I did this....

        # random chance, picks a number in [0,1)
        if (random.random() < u):
            nn = nn + 1
            #print "      ", gain
            # Make a new solution with both edges swapped.
            new_solution = range(0, sn)
            new_solution[0] = solution[ci]
            n = 1
            while xi != yi:
                new_solution[n] = solution[xi]
                n = n + 1
                xi = (xi - 1) % sn
            new_solution[n] = solution[yi]
            n = n + 1
            while zi != ci:
                new_solution[n] = solution[zi]
                n = n + 1
                zi = (zi + 1) % sn

            frame(nodes, new_solution, sn, t, c, y, x, z, gain)

            return new_solution
        else:
            return solution
    else:
        return solution
Example #6
0
def optimize( nodes, solution, sn, t ):
    global nn
    ci = random.randint(0, sn-1)
    yi = (ci + 1) % sn
    xi = random.randint(0, sn-1)
    zi = (xi + 1) % sn

    if xi != ci and xi != yi:
        c = solution[ ci ]
        y = solution[ yi ]
        x = solution[ xi ]
        z = solution[ zi ]
        cy = length( c, y )
        xz = length( x, z )
        cx = length( c, x )
        yz = length( y, z )

        gain = (cy + xz) - (cx + yz)
        if gain < 0:
            u = math.exp( gain / t )
        elif gain > 0.05:
            u = 1
        else:
            u = 0

        if (random.random() < u):
            nn = nn + 1
            #print "      ", gain
            new_solution = range(0,sn)
            new_solution[0] = solution[ci]
            n = 1
            while xi != yi:
                new_solution[n] = solution[xi]
                n = n + 1
                xi = (xi-1)%sn
            new_solution[n] = solution[yi]
            n = n + 1
            while zi != ci:
                new_solution[n] = solution[zi]
                n = n + 1
                zi = (zi+1)%sn

            frame( nodes, new_solution, sn, t, c,y,x,z, gain )

            return new_solution
        else:
            return solution
    else:
        return solution
Example #7
0
def optimize2opt( nodes, solution, sn, t ):
    best = 0
    best_move = None
    for ci in range(0, sn):
        for xi in range(0, sn):
            yi = (ci + 1) % sn
            zi = (xi + 1) % sn

            c = solution[ ci ]
            y = solution[ yi ]
            x = solution[ xi ]
            z = solution[ zi ]
            cy = length( c, y )
            xz = length( x, z )
            cx = length( c, x )
            yz = length( y, z )


            if xi != ci and xi != yi:
                gain = (cy + xz) - (cx + yz)
                if gain > best:
                    best_move = (ci,yi,xi,zi)
                    best = gain

    print best_move, best
    if best_move is not None:
        (ci,yi,xi,zi) = best_move
        c = solution[ ci ]
        y = solution[ yi ]
        x = solution[ xi ]
        z = solution[ zi ]

        new_solution = range(0,sn)
        new_solution[0] = solution[ci]
        n = 1
        while xi != yi:
            new_solution[n] = solution[xi]
            n = n + 1
            xi = (xi-1)%sn
        new_solution[n] = solution[yi]
        n = n + 1
        while zi != ci:
            new_solution[n] = solution[zi]
            n = n + 1
            zi = (zi+1)%sn
        frame4( nodes, new_solution, sn, t, c,y,x,z, gain )
        return (True,new_solution)
    else:
        return (False,solution)
Example #8
0
def greedy_algorithm(nodes):
    # Greedy Algorithm
    print('Computing greedy path')

    free_nodes = nodes[:]
    solution = []
    n = free_nodes[0]
    free_nodes.remove(n)
    solution.append( n )
    while len(free_nodes) > 0:
        print(len(free_nodes))
        min_l = None
        min_n = None
        for c in free_nodes:
            l = length( c, n )
            if min_l is None:
                min_l = l
                min_n = c
            elif l < min_l:
                min_l = l
                min_n = c
        solution.append(min_n)
        free_nodes.remove(min_n)
        n = min_n
    return solution
Example #9
0
def greedy_algorithm(nodes):
    # Greedy Algorithm
    print 'Computing greedy path'

    free_nodes = nodes[:]
    solution = []
    n = free_nodes[0]
    free_nodes.remove(n)
    solution.append( n )
    while len(free_nodes) > 0:
        print(len(free_nodes))
        min_l = None
        min_n = None
        for c in free_nodes:
            l = length( c, n )
            if min_l is None:
                min_l = l
                min_n = c
            elif l < min_l:
                min_l = l
                min_n = c
        solution.append(min_n)
        free_nodes.remove(min_n)
        n = min_n
    return solution
Example #10
0
def miss_perry_s_compass(nodes, number_of_nodes):
    # Compute Center of all nodes
    sum_x = 0
    sum_y = 0
    for n in nodes:
        sum_x += n.x
        sum_y += n.y
    c_x = sum_x / number_of_nodes
    c_y = sum_y / number_of_nodes
    # Make a node for this center.
    center_node = Node(-1, c_x, c_y)
    sorted_nodes = []
    done = [False] * number_of_nodes

    # Sort the nodes based on the distance from the center node.
    for i in range(number_of_nodes):
        max_l = -1
        furthest = None
        for j in range(number_of_nodes):
            if done[j]:
                pass
            else:
                l = length(center_node, nodes[j])
                if l > max_l:
                    furthest = j
                    max_l = l
        sorted_nodes.append(nodes[furthest])
        done[furthest] = True

    # Create initial polygon
    solution = [sorted_nodes[0], sorted_nodes[1], sorted_nodes[2]]
    for i in range(3, number_of_nodes):
        new_node = sorted_nodes[i]
        closest = sorted_nodes[0]
        min_l = length(closest, new_node)
        index_in_list = 0
        for j in range(1, i):
            l = length(sorted_nodes[j], new_node)
            if l < min_l:
                index_in_list = j
                closest = sorted_nodes[j]
                min_l = l

        # Is the node inside or outside the polygon?
        if point_in_poly(new_node.x, new_node.y, solution):
            idx_before = (index_in_list - 1) % i
            idx_after  = (index_in_list + 1) % i
            # it is Inside
            area1 = area_triangle(new_node, closest, solution[idx_before])
            area2 = area_triangle(new_node, closest, solution[idx_after])
            if area1 < area2:
                # Insert new node between closest and next
                pass
            else:
                # Insert
                pass
            pass
        else:
            # it is outside
            pass

    return sorted_nodes
Example #11
0
def optimize2opt(nodes, solution, number_of_nodes):
    best = 0
    best_move = None
    # For all combinations of the nodes
    for ci in range(0, number_of_nodes):
        for xi in range(0, number_of_nodes):
            yi = (ci + 1) % number_of_nodes  # C is the node before Y
            zi = (xi + 1) % number_of_nodes  # Z is the node after X

            c = solution[ ci ]
            y = solution[ yi ]
            x = solution[ xi ]
            z = solution[ zi ]
            # Compute the lengths of the four edges.
            cy = length( c, y )
            xz = length( x, z )
            cx = length( c, x )
            yz = length( y, z )

            # Only makes sense if all nodes are distinct
            if xi != ci and xi != yi:
                # What will be the reduction in length.
                gain = (cy + xz) - (cx + yz)
                # Is is any better then best one sofar?
                if gain > best:
                    # Yup, remember the nodes involved
                    best_move = (ci,yi,xi,zi)
                    best = gain

    print(best_move, best)
    if best_move is not None:
        (ci,yi,xi,zi) = best_move
        # This four are needed for the animation later on.
        c = solution[ ci ]
        y = solution[ yi ]
        x = solution[ xi ]
        z = solution[ zi ]

        # Create an empty solution
        new_solution = list(range(0,number_of_nodes))
        # In the new solution C is the first node.
        # This we we only need two copy loops instead of three.
        new_solution[0] = solution[ci]

        n = 1
        # Copy all nodes between X and Y including X and Y
        # in reverse direction to the new solution
        while xi != yi:
            new_solution[n] = solution[xi]
            n = n + 1
            xi = (xi-1)%number_of_nodes
        new_solution[n] = solution[yi]

        n = n + 1
        # Copy all the nodes between Z and C in normal direction.
        while zi != ci:
            new_solution[n] = solution[zi]
            n = n + 1
            zi = (zi+1)%number_of_nodes
        # Create a new animation frame
        frame4(nodes, new_solution, number_of_nodes, c, y, x, z, gain)
        return (True,new_solution)
    else:
        return (False,solution)
Example #12
0
def create_animation( nodes ):
    global nn
    global l_min
    sn = len( nodes )
    print 'Size {}'.format( sn )

    if True:
        # Greedy Algorithm
        print 'Computing greedy path'

        free_nodes = nodes[:]
        solution = []
        n = free_nodes[0]
        free_nodes.remove(n)
        solution.append( n )
        while len( free_nodes ) > 0:
            print len( free_nodes ),
            min_l = None
            min_n = None
            for c in free_nodes:
                l = length( c, n )
                if min_l is None:
                    min_l = l
                    min_n = c
                elif l < min_l:
                    min_l = l
                    min_n = c
            solution.append(min_n)
            free_nodes.remove(min_n)
            n = min_n
    else:
        solution = [ n for n in nodes ]

    if True:
        # Only cities
        solution0 = [ n for n in nodes ]
        for i in range(2,sn):
            s = solution0[0:i]
            framec(s,sn)
        for i in range(20):
            framec(s,sn)

        # Random Search
        for i in range(2,sn):
            s = solution0[0:i]
            frame0(s,solution0, total_length(nodes,s), "(1)  Random Path")
        s = solution0
        for i in range(60):
            frame0(s,solution, total_length(nodes,s), "(1)  Random Path")

        # Greedy
        for i in range(2,sn):
            s = solution[0:i]
            frame0(s,solution, total_length(nodes,s), "(2)  Greedy Search")
        s = solution
        for i in range(60):
            frame0(s,solution, total_length(nodes,s), "(2)  Greedy Search")


    print "2-Opt"
    solution = [ n for n in nodes ]
    t = 100
    go = True
    while go:
        (go,solution) = optimize2opt( nodes, solution, sn, t )
    s = solution
    for i in range(60):
        frame0(s,solution, total_length(nodes,s), "(3)  2-Opt")



    print "SA"
    solution = [ n for n in nodes ]
    t = 100
    l_min = total_length( nodes, solution )
    best_solution = []
    i = 0
    while True:
        i = i + 1
        solution = optimize( nodes, solution, sn, t )
        if i >= 200:
            i = 0
            l = total_length( nodes, solution )
            print "    ", l, t, nn
            t = t*0.9995

            if l_min is None:
                l_min = l
            elif l < l_min:
                l_min = l
                print "++", l, t
                best_solution = solution[:]
            else:
                pass
        if t < 0.1:
            break

    s = best_solution
    for i in range(60):
        frame0(s, solution, total_length(nodes,s), "(4)  SA")


    return best_solution
Example #13
0
def miss_perry_s_compass(nodes, number_of_nodes):
    # Compute Center of all nodes
    sum_x = 0
    sum_y = 0
    for n in nodes:
        sum_x += n.x
        sum_y += n.y
    c_x = sum_x / number_of_nodes
    c_y = sum_y / number_of_nodes
    # Make a node for this center.
    center_node = Node(-1, c_x, c_y)
    sorted_nodes = []
    done = [False] * number_of_nodes

    # Sort the nodes based on the distance from the center node.
    for i in range(number_of_nodes):
        max_l = -1
        furthest = None
        for j in range(number_of_nodes):
            if done[j]:
                pass
            else:
                l = length(center_node, nodes[j])
                if l > max_l:
                    furthest = j
                    max_l = l
        sorted_nodes.append(nodes[furthest])
        done[furthest] = True

    # Create initial polygon
    solution = [sorted_nodes[0], sorted_nodes[1], sorted_nodes[2]]
    for i in range(3, number_of_nodes):
        new_node = sorted_nodes[i]
        closest = sorted_nodes[0]
        min_l = length(closest, new_node)
        index_in_list = 0
        for j in range(1, i):
            l = length(sorted_nodes[j], new_node)
            if l < min_l:
                index_in_list = j
                closest = sorted_nodes[j]
                min_l = l

        # Is the node inside or outside the polygon?
        if point_in_poly(new_node.x, new_node.y, solution):
            idx_before = (index_in_list - 1) % i
            idx_after  = (index_in_list + 1) % i
            # it is Inside
            area1 = area_triangle(new_node, closest, solution[idx_before])
            area2 = area_triangle(new_node, closest, solution[idx_after])
            if area1 < area2:
                # Insert new node between closest and next
                pass
            else:
                # Insert
                pass
            pass
        else:
            # it is outside
            pass

    return sorted_nodes
Example #14
0
def optimize2opt(nodes, solution, number_of_nodes):
    best = 0
    best_move = None
    # For all combinations of the nodes
    for ci in range(0, number_of_nodes):
        for xi in range(0, number_of_nodes):
            yi = (ci + 1) % number_of_nodes  # C is the node before Y
            zi = (xi + 1) % number_of_nodes  # Z is the node after X

            c = solution[ ci ]
            y = solution[ yi ]
            x = solution[ xi ]
            z = solution[ zi ]
            # Compute the lengths of the four edges.
            cy = length( c, y )
            xz = length( x, z )
            cx = length( c, x )
            yz = length( y, z )

            # Only makes sense if all nodes are distinct
            if xi != ci and xi != yi:
                # What will be the reduction in length.
                gain = (cy + xz) - (cx + yz)
                # Is is any better then best one sofar?
                if gain > best:
                    # Yup, remember the nodes involved
                    best_move = (ci,yi,xi,zi)
                    best = gain

    print best_move, best
    if best_move is not None:
        (ci,yi,xi,zi) = best_move
        # This four are needed for the animation later on.
        c = solution[ ci ]
        y = solution[ yi ]
        x = solution[ xi ]
        z = solution[ zi ]

        # Create an empty solution
        new_solution = range(0,number_of_nodes)
        # In the new solution C is the first node.
        # This we we only need two copy loops instead of three.
        new_solution[0] = solution[ci]

        n = 1
        # Copy all nodes between X and Y including X and Y
        # in reverse direction to the new solution
        while xi != yi:
            new_solution[n] = solution[xi]
            n = n + 1
            xi = (xi-1)%number_of_nodes
        new_solution[n] = solution[yi]

        n = n + 1
        # Copy all the nodes between Z and C in normal direction.
        while zi != ci:
            new_solution[n] = solution[zi]
            n = n + 1
            zi = (zi+1)%number_of_nodes
        # Create a new animation frame
        frame4(nodes, new_solution, number_of_nodes, c, y, x, z, gain)
        return (True,new_solution)
    else:
        return (False,solution)
Example #15
0
def create_animation(nodes):
    global nn
    global l_min
    sn = len(nodes)
    print 'Size {}'.format(sn)

    if True:
        # Greedy Algorithm
        print 'Computing greedy path'

        free_nodes = nodes[:]
        solution = []
        n = free_nodes[0]
        free_nodes.remove(n)
        solution.append(n)
        while len(free_nodes) > 0:
            print len(free_nodes),
            min_l = None
            min_n = None
            for c in free_nodes:
                l = length(c, n)
                if min_l is None:
                    min_l = l
                    min_n = c
                elif l < min_l:
                    min_l = l
                    min_n = c
            solution.append(min_n)
            free_nodes.remove(min_n)
            n = min_n
    else:
        solution = [n for n in nodes]

    if True:
        # Only cities
        solution0 = [n for n in nodes]
        for i in range(2, sn):
            s = solution0[0:i]
            framec(s, sn)
        # Show all cities for an additional 20 frames.
        for i in range(20):
            framec(s, sn)

        # Random Search
        for i in range(2, sn):
            s = solution0[0:i]
            frame0(s, solution0, total_length(nodes, s), "(1)  Random Path")
        s = solution0
        for i in range(60):
            frame0(s, solution, total_length(nodes, s), "(1)  Random Path")

        # Greedy
        for i in range(2, sn):
            s = solution[0:i]
            frame0(s, solution, total_length(nodes, s), "(2)  Greedy Search")
        s = solution
        for i in range(60):
            frame0(s, solution, total_length(nodes, s), "(2)  Greedy Search")

    print "2-Opt"
    # Create an initial solution
    solution = [n for n in nodes]
    t = 100
    go = True
    # Try to optimize the solution with 2opt until
    # no further optimization is possible.
    while go:
        (go, solution) = optimize2opt(nodes, solution, sn, t)
    s = solution
    for i in range(60):
        frame0(s, solution, total_length(nodes, s), "(3)  2-Opt")

    #=== Simulated Annealing
    print "SA"
    # Create an initial solution that we can improve upon.
    solution = [n for n in nodes]

    # The temperature t. This is the most important parameter
    # of the SA algorithm. It starts at a high temperature and
    # is then slowly decreased.   Both rate of decrease and
    # initial values are parameters that need to be tuned to
    # get a good solution.

    # The initial temperature.
    # This should be high enough to allow the algorithm to
    # explore many sections of the search space.
    # Set too high it will waste a lot of computation time randomly
    # bouncing around the search space.
    t = 100

    # Length of the best solution so far.
    l_min = total_length(nodes, solution)
    best_solution = []
    i = 0
    while True:
        i = i + 1
        solution = optimize(nodes, solution, sn, t)
        # every ~200 steps
        if i >= 200:
            i = 0
            # Compute the length of the solution
            l = total_length(nodes, solution)
            print "    ", l, t, nn
            # Lower the temperature.
            # The slower we do this, the better then final solution
            # but also the more times it takes.
            t = t * 0.9995

            # See if current solution is a better solution then the previous
            # best one.
            if l_min is None:  # TODO: This can be removed, as l_min is set above.
                l_min = l
            elif l < l_min:
                # Yup it is, remember it.
                l_min = l
                print "++", l, t
                best_solution = solution[:]
            else:
                pass
        if t < 0.1:  # TODO: This should be part of the while condition.
            break

    # Show the best solution for an additional 60 frames.
    s = best_solution
    for i in range(60):
        frame0(s, solution, total_length(nodes, s), "(4)  SA")

    return best_solution