分支定界算法可以纯功能实现吗?

时间:2013-03-27 00:06:52

标签: algorithm functional-programming branch-and-bound

分支和界限的一般描述

来自维基百科的Branch and Bound

  

此步骤称为修剪,通常通过维护来实现   全局变量 m (在树的所有节点之间共享)   记录所检查的所有次区域的最小上限   远。可以丢弃下限大于 m 的任何节点。

实际例子:旅行推销员问题

旅行商问题的一个简单解决方案是保留一个变量,例如: best,代表到目前为止发现的最短哈密顿环路(上界)。

每当我们考虑潜在新电路中的新步骤时,我们计算当前点的路径成本,例如cost,它是此路径成本的下限,并将其与best变量进行比较。如果在任何时候cost >= best,我们不需要考虑这条道路;我们可以修剪以此子路径开头的所有潜在路径。

在C等过程语言中实现这一点并不难,我们可以创建一个属于函数范围的变量。例如,

int best = -1; // no best path yet

node* solveTSP() {
    // best can be consulted and has a consistent
    // value across all recursive calls to solveTSP()
    ...
}

我的实际问题

我不清楚如何实现这样的算法纯功能。有没有办法模拟维基百科定义中提到的全局变量 m

我知道在Lisp中创建一个全局变量很简单,但这是否可以用更纯粹的函数语言来实现,比如Haskell?

2 个答案:

答案 0 :(得分:4)

您只需将当前最佳值作为附加参数传递给递归调用,并将更新后的最佳值作为其结果的一部分返回。因此,如果您具有a -> b类型的函数,它将变为类似a -> Int -> (b, Int)的函数。您不必读取全局变量,而是读取附加参数,而不是编写它,而是在函数完成时返回修改后的值。

可以使用the state monad很好地表达。类型Int -> (b, Int)State Int b同构,因此a -> b类型的函数变为a -> State Int b

答案 1 :(得分:1)

计算可变状态并不比没有它的计算强大。一个可以减少到另一个。

特别是,功能视点中的可变单元格成为连续值的序列,通常在某些排列中,新副本会影响较旧的副本(例如,在尾部递归中)。