如何提高这个python代码的性能?

时间:2016-01-08 06:04:27

标签: python python-3.x optimization

我正在解决一个难题(找出是否存在给定自动机的输入,无论起始状态是什么,最终状态每次都相同)并编写以下python代码。一些测试用例在代码中用check方法编写。对于这些情况,程序运行得相当快。但是,对于存在50个列表(节点)的测试用例,程序将永远执行。我正在存储中间结果以便进一步使用。有人可以查看代码并提供有关如何提高代码性能的建议吗?

from itertools import product
from copy import deepcopy

class Node:
    def __init__(self,id):
        self.id = id
        self.dict = {}

    def __str__(self):
        return str(id) + " : " + str(self.dict)

    def __repr__(self):
        return str(id) + " : " + str(self.dict)

def tryDelete(nodes,_len):
    for id in nodes:
        y = deepcopy(nodes)
        x = y[id]
        del y[id]
        for id,node in y.items():
            for input,result in node.dict.items():
                if result == x:
                    if x.dict[input] == x:
                        node.dict[input] = node
                    else:
                        node.dict[input] = x.dict[input]
                    pass
        if pathPossible(y,_len ,False) == -1:
            return x.id
    return -2

target = {}
def FindTarget(node,p):
    if len(p) == 1:
        return node.dict[p[0]]
    if node not in target or p not in target[node]:
        x = FindTarget(node,p[:-1]).dict[p[-1]]
        if node not in target:
            target[node] = {}
        target[node][p] = x
    return target[node][p]

def allSatisy(nodes,p):
    x = None
    for key,node in nodes.items():
        if x is None:
            x = FindTarget(node,p)
        elif FindTarget(node,p) != x:
            return False
    return True

def allPossiblePaths(l,n):
    #x = int(((l+1)*(l+2))/2)
    for i in range(1, n+1):
        for p in product(range(l),repeat=i):
            yield p

def pathPossible(nodes,_len ,isItereate=True):
    i = 1
    isFound = False
    for p in allPossiblePaths(_len,len(nodes)):
        if allSatisy(nodes,p):
            isFound = True
            break

    if isFound:
        return -1
    elif not isItereate:
        return -2
    else:
        return tryDelete(nodes,_len)

def answer(li):
    nodes = {}
    for i in range(len(li)):
        nodes[i] = Node(i)
    for i in range(len(li)):
        for j in range(len(li[i])):
            nodes[i].dict[j] = nodes[li[i][j]]
    return pathPossible(nodes,len(nodes[0].dict))

def check(li,ans):
    # each item in the list is a node, each item i-th in the inner list tells to what node the transition happens for input i
    x = answer(li)
    print(str(li) + " : " + str(ans) + " : " + str(x))

def main():
    check([[2,1],[2,0],[3,1],[1,0]],-1)
    check([[1,2],[1,1],[2,2]],1)
    check([[1,3,0],[1,0,2],[1,1,2],[3,3,3]],-1)

if __name__ == '__main__':
    main()

更新:我做了很少的代码更改,但仍然需要您的一些评论。更改了代码:

from itertools import product
from copy import deepcopy

class Node:
    def __init__(self,id):
        self.id = id
        self.dict = {}

    def __str__(self):
        return str(self.id) + " : " + str(self.dict)

    def __repr__(self):
        return str(self.id) + " : " + str(self.dict)

def tryDelete(nodes,_len):
    for i in range(len(nodes)):
        y = nodes[:]
        x = y[i]
        del y[i]
        tNodes = []
        for node in y:
            for input,result in node.dict.items():
                if result == x:
                    node.tDict = deepcopy(node.dict)
                    if x.dict[input] == x.id:
                        node.dict[input] = node
                    else:
                        node.dict[input] = x.dict[input]

        if pathPossible(y,_len ,False) == -1:
            return x.id
        for n in tNodes:
            n.dict = n.tDict
            del n.tDict
    return -2

target = {}
def FindTarget(node,p):
    if len(p) == 1:
        return node.dict[p[0]]
    if node not in target or p not in target[node]:
        x = Gnodes[FindTarget(node,p[:-1])].dict[p[-1]]
        if node not in target:
            target[node] = {}
        target[node][p] = x
    return target[node][p]

def allSatisy(nodes,p):
    x = None
    for node in nodes:
        if x is None:
            x = FindTarget(node,p)
        elif FindTarget(node,p) != x:
            return False
    return True

def allPossiblePaths(l,n):
    #x = int(((l+1)*(l+2))/2)
    for i in range(1, n + 1):
        for p in product(range(l),repeat=i):
            yield p

def pathPossible(nodes,_len ,isItereate=True):
    i = 1
    isFound = False
    for p in allPossiblePaths(_len,len(nodes)):
        if allSatisy(nodes,p):
            isFound = True
            break

    if isFound:
        return -1
    elif not isItereate:
        return -2
    else:
        return tryDelete(nodes,_len)

Gnodes = []
def answer(li):  
    Gnodes[:] = []
    for i in range(len(li)):
        Gnodes.append(Node(i))#[i] = Node(i)
    for i in range(len(li)):
        for j in range(len(li[i])):
            Gnodes[i].dict[j] = li[i][j]
    return pathPossible(Gnodes,len(Gnodes[0].dict))

def check(li,ans):
    x = answer(li)
    print(str(li) + " : " + str(ans) + " : " + str(x))

def main():
    check([[2,1],[2,0],[3,1],[1,0]],-1)
    check([[1,2],[1,1],[2,2]],1)
    check([[1,3,0],[1,0,2],[1,1,2],[3,3,3]],-1)

if __name__ == '__main__':
    main()

1 个答案:

答案 0 :(得分:0)

有一个名为NetworkX的精彩图库。它涉及创建图形和路径查找。您可以指定图表中存在哪些边或路径,您可以使用多种算法(如广度优先搜索或A *)以及algorithms section中的许多其他算法来查找路径。优化时间的最佳方法是代码重用。 https://networkx.github.io