python实现用Branch&Bound算法解决TSP问题

Posted on 2010-01-31 22:46  wanderxjtu  阅读(907)  评论(0)    收藏  举报
这个是作业。。。。写得有点水。
#/usr/bin/env python
# Use branch and bound to solve TSP
# by wander@xjtu copyleft
# 
# no negative edge, -1 stands for infty
# 8 city
#       A B C D E F G H
INFTY=10000
weight=((0, 2, -1, -1, -1, 1, -1, 1), 
        (2, 0, 1, -1, 1, -1, -1, -1),
        (-1, 1, 0, 1, -1, -1, -1, 5),
        (-1, -1, 1, 0, 2, -1, 1, -1),
        (-1, 1, -1, 2, 0, 1, -1, -1),
        (1, -1, -1, -1, 1, 0, 2, -1),
        (-1, -1, -1, 1, -1, 2, 0, 1),
        (1, -1, 5, -1, -1, -1, 1, 0))
v=range(len(weight))
s=[]
#print weight
def mst(w):
    def find(ei):
        li=range(dim-1,0,-1)
        for i in range(dim-1):
            if (sum(li[:i+1])>ei):
                break
#        print i,ei-sum(li[:i])+i+1
        return [i,ei-sum(li[:i])+i+1]
    def union(v1,v2):
        s2=vset[v2]
        vset[v2]=vset[v1]
        for i in range(len(vset)):        #not graceful
            try:
#                print vset
                vset[vset.index(s2)]=vset[v1]
            except ValueError:
#                print "union stop"
                break
    dim=len(w)
    e=[]    #edges
    for i in range(dim-1):
        e+=(w[i][i+1-dim:])
    vset=range(dim)    #tset[i] stands for v_i's vset
    msteset=[]
    while (len(msteset)<dim-1):
        try:
            ei=e.index(min(i for i in e if i>0))
        except ValueError:
            return INFTY
        v=find(ei)
        if (v[0]!=v[1]):
            union(v[0],v[1])
            msteset.append(e[ei])
        e[ei]=-2
#        print msteset,e
    return sum(msteset)
def lbound(s,w):
    si=s[:]
    la=si[0]     #start point of the route
    lb=si[-1]    #end point of the route
    si.sort()
    si.reverse() #delete backwards so we won't make mistake
    for j in si:
        w=[ w[i][:j]+w[i][j+1:] for i in range(len(w)) ]    #delect columns
    # look for the sortest route accessing the V-S area
    try:
        la=min(i for i in w[la] if i>0)
        lb=min(i for i in w[lb] if i>0)
    except ValueError:
        la=lb=0
    for i in si:    #delete rows
        w=w[:i]+w[i+1:] 
#    print w
    return mst(w)+la+lb
def distance(route):
    if (len(route)==len(weight)):
        if ( weight[route[0]][route[-1]]>0 ):
            return sum( weight[route[i]][route[i+1]] for i in range(len(route)-1) ) + weight[route[0]][route[-1]]
        return INFTY
    return sum( weight[route[i]][route[i+1]] for i in range(len(route)-1) )
def exp(node):
    s.append(v.pop(v.index(node)))    #getting a new point
    lowerbound=lbound(s,weight)+distance(s)
    global count
    count+=1
#    print 'vars',s,v,lowerbound,bestbound
    if (v==[]):
        global bestbound
        bestbound=lowerbound
        print s,bestbound
        global best
        best=s[:]    # saving 
        v.append(s.pop())
        return 
    elif (lowerbound < bestbound):    #expand
        pset=[i for i in range(len(weight)) if weight[s[-1]][i] > 0 and i not in s]
        for i in pset:
#            print 'next',s
            exp(i)
        v.append(s.pop())
        return 
    else:
        print s,'infty'
        v.append(s.pop())
        return 
if (__name__=='__main__'):
#    s.append(v.pop(0))    #start point
    lowerbound=INFTY     
    bestbound=INFTY
    count=0
    exp(v[0])
    print 'best route:',best
    print 'distance:',bestbound
    print 'looptimes:',count#,'in compare with',len(weight)!


博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3