使用Python进行高效的动态编程

时间:2018-06-21 17:25:32

标签: python dynamic-programming

我正在进行一项动态编程任务,即沿着有向图找到一条最小成本路径(所有可能的路径都具有相同数量的加权节点)。

解决问题的方法是使用递归函数和动态编程。

由于在代码编写过程中许多不相关的问题都遇到了这种动态编程任务,因此线程化的概念可能会有所帮助。

问题是,在python中,' threading '并没有太大帮助。 在python中处理此类任务的有效方法是什么?

代码如下:

    def rec_fun(pos, path_size, weights, directions):
        cost = weights[d][i, j]
        if path_size == 0:
            key = str(i) + ',' + str(j) + ',' + str(d)
            dict.update({key: pix_cost})
            return cost
        else:
            key = str(i) + ',' + str(j) + ',' + str(d)
            if key in dict:
                return dict[key]
            else:

                val = cost + min(rec_fun(pos + direction[0], path_size - 1, weights, direction),
                                 rec_fun(pos + direction[1], path_size - 1, weights, direction),
                                 rec_fun(pos + direction[2], path_size - 1, weights, direction))
                dict.update({key: val})
                return val

2 个答案:

答案 0 :(得分:2)

因此,首先,动态编程只是解决特定类型问题的简单范例。一般而言,实际上没有什么可以做的来优化动态编程的,反过来,这意味着可以应用常规的python优化。

因此,从您发布的代码中,我看到的最引人注目的是使用递归,这在python中效率相对较低,因此从移至for(理想)或while循环开始。

以下列出了一些可能的方法,这些方法可以使您的代码在python中更快地运行(付出更多的努力):

  1. 尝试使用Numba可以显着加快您的功能。在某些情况下,只需很少的工作(通常使用@jit装饰器就足够了)来将代码优化到接近cython级别。

  2. 在可能的情况下利用Numpy对代码进行矢量化。

  3. 您可能已经发现,
  4. 使用进程multiprocessing.Process代替线程,由于全局解释器锁定,python线程的工作方式与其他编程语言不同。我认为在这里有必要注意,在进程之间共享内存并不是真正的好习惯,如果可能的话,您应该避免这种情况。

  5. 使用Python的C扩展Cython编写代码的所有性能关键部分。

答案 1 :(得分:0)

使用Python 3,您可以使用 functools 中的find a working, interactive example here缓存递归调用的结果,轻松实现动态编程。

您可以这样包装函数:

@functools.lru_cache(max_size=None)
def rec_fun(pos, path_size, weights, directions):
    # your code...

注意:与使用自己的数组或列表实现DP相比,由于此方法可以缓存所有调用,因此它可以存储比您所需的结果更多的结果。