Variables are the same but shouldn't be? Python

时间:2019-03-17 22:39:20

标签: python iteration traveling-salesman

I am having some trouble with variables being set as the same when they shouldn't be and I can't figure out why they're doing it. In my case, LCT and MCT are being set as the last route generated in the function, but I only have them being set when the route is less than or more than the least cost or most cost, respectively. Basically, I'm creating a pseudo-random list of the integers from 0-13 as city labels, and finding the distance between them using an i-by-j array lookup where the value indicates the distance when traveled from city i to city j. This is part of my TSP project. Here's some code for reference:

import random

def distance(x1, y1, x2, y2):
     """
     Finds the distance between two points with coordinates (x1, y1) and (x2, y2)
     :param x1: x-coordinate of first point
     :type x1: float or int
     :param y1: y-coordinate of first point
     :type y1: float or int
     :param x2: x-coordinate of second point
     :type x2: float or int
     :param y2: y-coordinate of second point
     :type y2: float or int
     :return: distance between two points
     :rtype: float
     """
     return (((x2-x1)**2) + ((y2-y1)**2)) ** 0.5

def shuffle(idxs):
    """
    Performs random swaps n times with random seeded generator
    :param idxs: Set of items to choose from
    :type idxs: list, tuple, or dict
    :return: modified idxs
    :rtype modified idxs: type(idxs)
    """
    n = 32
    for k in range(n):
        random.seed()
        a, b = random.randint(0, 13), random.randint(0, 13)
        swap(idxs, a, b)
        # print(idxs)
    return idxs


def swap(mylist, a, b):
    """
    Swaps two values
    :param mylist: order of things to choose from
    :type mylist: list, tuple, or dict
    :param a: first index
    :type a: list/tuple: int; dict: key
    :param b: second index
    :type b: list/tuple: int; dict: key
    :return: none; edits items in place
    """
    temp = mylist[a]
    mylist[a] = mylist[b]
    mylist[b] = temp

mat = [[0.430796749, 0.660341257],
      [0.869607109, 0.145710154],
      [0.272249997, 0.281035268],
      [0.310050105, 0.717362826],
      [0.847481151, 0.505130257],
      [0.054921944, 0.597324847],
      [0.565507064, 0.578311901],
      [0.578311901, 0.636552793],
      [0.170565332, 0.160881561],
      [0.800726237, 0.384045138],
      [0.622627218, 0.957622127],
      [0.608021461, 0.736718151],
      [0.628737267, 0.622146623],
      [0.665929436, 0.720342005]]

distances = [[distance(x1=mat[i][0], y1=mat[i][1],
                 x2=mat[j][0], y2=mat[j][1]) for j in range(14)] for i in range(14)]

route = [i for i in range(14)]
bigN = 1000
LC = 100
MC = 0

for j in range(bigN):
    this_dist = 0
    route = shuffle(route)
    # print('Route:', route)

    # Get the distance for the route
    for stop in range(len(route)):
        if stop != len(route) - 1:  # if its not the last node
            this_dist += distances[route[stop]][route[stop + 1]]
        else:  # Add cost from last item to first item
            this_dist += distances[route[stop]][route[0]]
    # print('Distance:', this_dist)

    # Update min/max
    if this_dist < LC:
        LC = this_dist
        LCT = route
        print('New low:', LCT, 'Distance:', LC)
    elif this_dist > MC:
        MC = this_dist
        MCT = route
        print('New high:', MCT, 'Distance:', MC)

print('Last route:', route, 'Last distance:', this_dist)

# Output
print('Least cost:', LC)
print('Least cost trip:', LCT)
print('Most cost:', MC)
print('Most cost trip:', MCT)

If you just copy and paste this into an IDE and run it, you will see what I mean. LCT and MCT are being set as the last route generated (even though it's not the least/most cost trip), when I only have them being changed when the current route is shorter/longer than the current least/most cost. Why is this happening and what can I do to have it properly set as the LCT/MCT? I am very confused and sorry if this is a long post, but I can't figure this out. I'm using Python 3.7, if that helps any. Edit: problem clarification.

I expect LCT/MCT to at least be different because they would have different routes and different distances associated with them. My issue is that the variables are being set as the very last route generated, regardless of if it's actually shorter/longer than the actual shortest/longest route. Each time the current route is shorter/longer than the actual shortest/longest route, I have it print out the new route and the new shortest distance. LCT/MCT should be set as the last respective one printed out.

Last edit: jasonharper's solution in the comments worked (sorry if I butchered the username, you can't see them in edit mode and I don't have enough rep to post comments). I just had to add [:] to the end of routes when I copied them to LCT/MCT. Thanks!

1 个答案:

答案 0 :(得分:0)

Basically route is mutable and it is changed each time. When you set LCT/MCT it is a pointer to route. You can use the suggestion from @jasonharper and update the code as follows:

# Update min/max
if this_dist < LC:
    LC = this_dist
    LCT = route[:]
    print('New low:', LCT, 'Distance:', LC)
elif this_dist > MC:
    MC = this_dist
    MCT = route[:]
    print('New high:', MCT, 'Distance:', MC)