【转】几种不同语言实现蚁群算法的效率对比

Ant Colony Optimization for TSP in Psyco Python

http://go2web0.appspot.com/_?bG10aC50bkFub2h0eXAvbW9jLmduaXJwc2RuaW0uZW1vaC5zbmlsbG9yX2NpcmUvLzpwdHRo


This is a continuation of Parallel Ant Colony Optimization for TSP in Standard ML, Multi-Core Ant Colony Optimization for TSP in Haskell, Multi-Core Ant Colony Optimization for TSP in Erlang, and Multi-Core Ant Colony Optimization for TSP in Scala. See first page for Ant Colony and TSP problem description. Here the program has been rewritten in the programming language Python.

Python is a dynamically typed language and is normally interpreted. It is object-oriented but has some functional features such as map, reduce, and lambda functions. All functions in Python are Parametrically Polymorphic (see my article Types and Programming Languages for details), which creates difficulties for efficient compilation.

Psyco is a compiler for Python. It is a just-in-time compiler, and uses the run-time type usage information to determine which functions should be native-compiled. It is a specializing compiler -- it will create multiple instantiations of the same function with different type parameters. It is very easy to use; just add 2 lines to the top of your program:
import psyco
psyco.full()
It is an experimental project. The documentation warns that map and lambda perform poorly, and that list comprehensions (often a reasonable substitute) should be used instead. The original developer has moved on to work on the PyPy project; I should investigate that later.

Compared to other tested languages the performance of uncompiled Python is average; with Psyco compilation it is surprisingly good.

See previous for details of test environment. Same test as before, but only a single core and 1/4 the work.
Versions
Python 2.5.2 (r252:60911, Jun 25 2008, 17:58:32) [GCC 4.3.1] on linux2 from Debian apt-get.

Psyco psyco-1.6-linux.i386-2.5 from SourceForge
Command Lines
time ./ant.py
Results

Erlang   Haskell   Scala   MLton_SML  Python Psyco
93       22        10      1.5        40     5.5
All times in seconds.

python版:

 

#!/usr/bin/python

# ant.py
# Eric Rollins 2008

#   This program generates a random array of distances between cities, then uses
#   Ant Colony Optimization to find a short path traversing all the cities --
#   the Travelling Salesman Problem.
#
#   In this version of Ant Colony Optimization each ant starts in a random city.
#   Paths are randomly chosed with probability inversely proportional to to the
#   distance to the next city.  At the end of its travel the ant updates the
#   pheromone matrix with its path if this path is the shortest one yet found.
#   The probability of later ants taking a path is increased by the pheromone
#   value on that path.  Pheromone values evaporate (decrease) over time.
#
#   In this impementation weights between cities actually represent
#   (maxDistance - dist), so we are trying to maximize the score.
#
#   Usage: ant seed boost iterations cities
#     seed         seed for random number generator (1,2,3...).
#                  This seed controls the city distance array.  Remote
#                  executions have their seed values fixed (1,2) so each will
#                  produce a different result.
#     boost        pheromone boost for best path.  5 appears good. 
#                  0 disables pheromones, providing random search.
#     iterations   number of ants to be run.
#     cities       number of cities.

# enable psyco compiler
import psyco
psyco.full()

import random

# type Matrix = Array[Array[double]]
# type Path = List[int]
# type CitySet = HashSet[int]

# int * int * int -> Matrix
def randomMatrix(n, upperBound, seed):
    random.seed(seed)
    m = []
    for r in range(n):
        sm = []
        m.append(sm)
        for c in range(n):
             sm.append(upperBound * random.random())
    return m

# Path -> Path
def wrappedPath(path):
    return path[1:] + [path[0]]

# Matrix * Path -> double
def pathLength(cities, path):
    pairs = zip(path, wrappedPath(path))
    return sum([cities[r][c] for (r,c) in pairs])

# Boosts pheromones for cities on path.
# Matrix * Path * int -> unit
def updatePher(pher, path, boost):
    pairs = zip(path, wrappedPath(path))
    for (r,c) in pairs:
        pher[r][c] = pher[r][c] + boost

# Matrix * int * int -> unit
def evaporatePher(pher, maxIter, boost):
    decr = boost / float(maxIter)
    for r in range(len(pher)):
        for c in range(len(pher[r])):
            if pher[r][c] > decr:
                pher[r][c] = pher[r][c] - decr
            else:
                pher[r][c] = 0.0

# Sum weights for all paths to cities adjacent to current.
# Matrix * Matrix * CitySet * int -> double
def doSumWeight(cities, pher, used, current):
    runningTotal = 0.0
    for city in range(len(cities)):
        if not used.has_key(city):
            runningTotal = (runningTotal +
                            cities[current][city] * (1.0 + pher[current][city]))
    return runningTotal

# Returns city at soughtTotal.
# Matrix * Matrix * CitySet * int * double -> int
def findSumWeight(cities, pher, used, current, soughtTotal):
    runningTotal = 0.0
    next = 0
    for city in range(len(cities)):
        if runningTotal >= soughtTotal:
            break
        if not used.has_key(city):
            runningTotal = (runningTotal +
                            cities[current][city] * (1.0 + pher[current][city]))
            next = city
    return next

# Matrix * Matrix -> Path
def genPath(cities, pher):
    current = random.randint(0, len(cities)-1)
    path = [current]
    used = {current:1}
    while len(used) < len(cities):
        sumWeight = doSumWeight(cities, pher, used, current)
        rndValue = random.random() * sumWeight
        current = findSumWeight(cities, pher, used, current, rndValue)
        path.append(current)
        used[current] = 1
    return path

# Matrix * int * int * int ->Path
def bestPath(cities, seed, maxIter, boost):
    pher = randomMatrix(len(cities), 0, 0)
    random.seed(seed)
    bestLen = 0.0
    bestPath = []
    for iter in range(maxIter):
        path = genPath(cities, pher)
        pathLen = pathLength(cities, path)
        if pathLen > bestLen:
            # Remember we are trying to maximize score.
            updatePher(pher, path, boost)
            bestLen = pathLen
            bestPath = path
        evaporatePher(pher, maxIter, boost)
    return bestPath

def main():
    seed = 1
    boost = 5
    iter = 1000
    numCities = 200
    maxDistance = 100
    cityDistanceSeed = 1
    print "starting"
    cities = randomMatrix(numCities, maxDistance, cityDistanceSeed)
    path = bestPath(cities, seed, iter, boost)
    print path
    print "len = ", pathLength(cities, path)

if __name__ == "__main__":
    main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值