不知道如何使用Cython优化代码

时间:2020-10-08 19:12:18

标签: python optimization cython cythonize

我刚开始尝试使用cython进行优化,因此我需要一些帮助,因为我知道我可以进行更多优化,但是我不知道该怎么做。

首先,我在C中声明了变量,但是其中很多是对象,我不知道如何声明。

然后我有了该类,在HTML中,每次代码想要获取该类的对象时,我都可以看到它很慢,因此我也想对其进行优化,而且我不知道该怎么做:(

import math
import random

def class City:
  def __init__(self, city_name='NoName', posx=0, posy=0):
    self.name = city_name
    self.x = posx
    self.y = posy

def distance_between_cities( object C1, object C2 ):
    """Compute distance between two cities"""
    dx = C1.x - C2.x
    dy = C1.y - C2.y
    return math.sqrt( dx*dx + dy*dy )

def read_cities_from_file ( str filename ):
    """Read list of Cities from text file"""
    cdef list Cities= [] # List of Empty Cities
    cdef list R = []
    with open(filename) as file:
        for line in file:
            R= line.split()
            Cities.append ( City( R[0], float(R[1]), float(R[2]) ) )
    return Cities

def path_distance( object Cities ):
    """Compute total distance of the path traversing all cities in order"""
    cdef int i = 0
    cdef double D = 0
    for i in range( len(Cities) ):
        D = D + distance_between_cities ( Cities[i],
                                          Cities[i+1 if i+1<len(Cities) else 0])
    return D

cdef int closerCity( object City, object Cities ):
    """Compute position of the city C in the list of Cities that is closer to City"""
    cdef float minDist = 2*1000*1000
    cdef int minIndex= 0
    cdef int i = 0
    cdef double dx = 0
    cdef double dy = 0
    cdef double dist = 0
    for i in range(len(Cities)):
        c = Cities[i]
        dx = City.x - c.x
        dy = City.y - c.y
        dist = dx*dx + dy*dy
        if dist < minDist:
            minDist = dist
            minIndex= i
    return minIndex

def GoodPath( object Cities ):
    """Generate a path with small total distance using greedy algorithm"""
    cdef list NotVisited = []
    cdef int len_C = len(Cities)
    cdef int i = 0
    for i in range(len_C):
      NotVisited.append(Cities[i])
    Path= [ Cities[0] ] # Start path with first city
    del NotVisited[0]
    while len(NotVisited) > 0:
        pos = closerCity( Path[-1], NotVisited )
        Path.append( NotVisited[pos] )
        del NotVisited[pos]
    return Path

if __name__ == "__main__":
  import argparse as arg
  parser = arg.ArgumentParser(prog='ARGUMENTS', usage='%(prog)s [options]')
  parser.add_argument("input",  type=str, help="File containing list of Cities")
  args = parser.parse_args()
  
  ListOfCities= read_cities_from_file ( str(args.input) )
  GoodList    = GoodPath( ListOfCities )
  print ( "Initial Distance =", path_distance( ListOfCities ),
          "  Good Distance =",  path_distance( GoodList) )

这是我进行cythonize时从HTML中获得的内容: Part 1 of the HTML Part 2

任何帮助将不胜感激

谢谢!

1 个答案:

答案 0 :(得分:0)

算法的复杂度为 O(n^2) (城市为n)。实际上,您会遍历所有城市,并针对每个城市再次遍历大多数城市(O(n)个城市)。另请注意,项目删除是在O(n)时间内进行的。可以使用更有效的 O(n log n) 算法来计算结果:

您可以在O(n log n)时间建立K-d tree结构,或更具体地说,建立Quad-tree结构,然后在O(log n)时间找到其他任何城市的最近城市结构体。另外,最好将NotVisited的类型更改为 set 而不是list,以避免缓慢删除列表项。

除此之外,我建议您将object类型的变量替换为较低级别的类型(例如,数组或double / int的元组),以便Cython可以生成更快的C代码。

请注意,您的方法通常找不到总的最短路径,甚至可能找不到非常小的路径。有better algorithms,但价格更高。