A *搜索实施“旅行推销员P”

时间:2016-01-17 17:43:20

标签: algorithm python-2.7 traveling-salesman

在编写 A * Search 算法后,我一直在苦苦挣扎,因为当城市数量大于8时,算法将不会返回任何答案(或者说是非常缓慢)。

城市存储在二维数组中,其中点cityList[x][y]是城市x和城市y之间的距离(它也与cityList[y][x]相同)

由于我必须同时使用city类和每条路线的开头来记住路线长度以及已经尝试过哪条路线,所以有点麻烦。

还为添加的每个城市创建了新路线。

任何人都可以帮助优化它或确保它可以在越来越多的城市中运作。

class city(object):
    def __init__(self, number):
        self.number = number
        global size
        self.possibleChildren = []
        for i in range(0,size):
            if i != number:
                self.possibleChildren.append(i)
    def getNo(self):
        return self.number
    def getSize(self):
        return len(self.possibleChildren)
    def getOptions(self, i):
        self.i = i
        return self.possibleChildren[self.i]
    def deleteNo(self, option):
        self.option = option
        if(self.option in self.possibleChildren):
            self.possibleChildren.remove(self.option)
    def addFinalStep(self, beginning):
        self.beginning = beginning
        self.possibleChildren.append(self.beginning)


def Astar():
    routeList = []
    #routeList[i][0] = distance travelled, routeList[i][1] = number of cities past
    for i in range(0, size):
        newRoute = []
        newCity = city(i)
        newRoute.append(0)
        newRoute.append(1)
        newRoute.append(newCity)
        routeList.append(newRoute)
    while True:
        toUse = 0
        smallest = -2
        #Now search through the routeList to find the shortest route length
        for i in range(0, len(routeList)):
            #getSize() checks if there are any cities that can be visited by
             this route that have not already been tried, this list is
             stored in the city class
            if routeList[i][1 + routeList[i][1]].getSize() != 0:
                if routeList[i][0] < smallest or smallest == -2:
                    smallest = routeList[i][0]
                    toUse = i
            elif routeList[i][1 + routeList[i][1]].getSize() == 0:
                routeList.remove(i)
        routeRec = []
        #Creates the new route
        for i in range (0, len(routeList[toUse])):
            routeRec.append(routeList[toUse][i])

        currentCity = routeRec[1 + routeRec[1]]
        possibleChildren = []
        for i in range(0, currentCity.getSize()):
            possibleChildren.append(currentCity.getOptions(i))

        smallest = 0
        newCityNo = 2    
        for i in range(0, size):
            if(i in possibleChildren):
                #Finds the closest city
                if smallest > cityList[currentCity.getNo()][i] or smallest == 0:
                    newCityNo = i
                    smallest = cityList[currentCity.getNo()][i]
        #If the new city to visit is the same as the first, the algorithm
        #has looped to the beginning and finished
        if newCityNo == routeRec[2].getNo():
            print("Tour Length")
            print(routeRec[0] + smallest)
            print("Route: ")
            for i in range(2,len(routeRec)):
                print(routeRec[i].getNo())
            return(routeRec[0] + smallest)

        #deletes all cities that have been tried
        routeList[toUse][1 + routeRec[1]].deleteNo(newCityNo)
        nextCity = city(newCityNo)
        #deletes all cities that are already in the route
        for i in range(2, 2 + routeRec[1]):
               nextCity.deleteNo(routeRec[i].getNo())

        #When the route is full, it can return to the first city                   
        routeRec[1] = routeRec[1] + 1
        print(routeRec[1])
        if routeRec[1] == size:
            #first city added to potential cities to visit
            nextCity.addFinalStep(routeRec[2].getNo())

        routeRec.append(nextCity)
        routeRec[0] = routeRec[0] + smallest
        routeList.append(routeRec)

1 个答案:

答案 0 :(得分:0)

你需要在这里做一些分解。 您需要数据结构来保存和获取要扩展的节点,在本例中为堆。 您还需要一些启发式,您可以将其作为参数传递。

实施A *

# A* Algorithm
#   heuristic - Heuristic function expecting state as operand
#   world - Global
#   sstate - Start state
#   endstate - End state, state to find
#   expandfn - function(world, state) returning array of tuples (nstate, cost)
#       where nstate is the state reached from expanded state and cost is the 'size'
#       of the edge.
def Astar(heuristic, world, sstate, endstate, expandfn):
    been = set()
    heap = Heap()
    end = None

    # We hape tuples (state, pathlen, parent state tuple) in heap
    heap.push((sstate, 0, None), 0) # Heap inserting with weight 0

    while not heap.isempty():

        # Get next state to expand from heap
        nstate = heap.pop()

        # If already seen state not expand
        if nstate[0] in been:
            continue

        # If goal reached
        if nstate[0] === endstate:
            end = nstate
            break

        # Add state as expanded
        been.add(nstate[0])

        # For each state reached from current state
        for expstate in expandfn(world, nstate[0]):
            pathlen = nstate[1] + expstate[1]

            # Expanding state with heap weight 'path length + heuristic'
            heap.push((expstate[0], pathlen, nstate), pathlen + heuristic(expstate[0]))
    # End of while loop

    if end is None:
        return None

    # Getting path from end node
    pathlen = end[1]
    res = []
    while end[2] is not None:
        res.append(end[0])
        end = end[2]
    res.reverse()

    return res, pathlen