分支限界和回溯算法分析

1,336 阅读4分钟

写在前面:两种算法很相似,都是对于求解空间树T上检索问题的算法。在通常情况下,分支限界法和回溯法求解目标是不同的。回溯法求得的是T中满足约束条件的所有解,而分支限界法的求解目标是找出满足约束条件的一个解,或是在满足约束条件的解中找出使某一目标函数值达到极值的解(最优解

分支限界算法

本质上以广度优先遍历搜索空间树T,只关心使给定函数得到最优解。若算法找到一个代价为n的解,当有一个部分解,它的代价 > n,那么不会对该部分解进行扩展进一步探索其代价

基本思路

每一个活跃的节点都只有一次机会称为扩展节点,一旦活跃节点成为扩展节点,就会一次性产生所有的儿子节点,然后在这些儿子节点中进行筛选,把那些代价大于n的儿子节点删除,剩下的儿子节点作为活跃节点存在。不断重复这个过程,直到找到最优解或不存在任意一个活跃节点为止

分支限界示意图

剪枝策略

对某个节点进行搜索时,会先估算出目标的解(预估值),再确定是否继续向下搜索(选择最小损耗的结点进行检索)

常用方法

队列式(FIFO)分支限界法:使用普通的队列,按照广度优先遍历的次序从队列中拿出先放入队列中的结点

优先队列(PQ)分支限界法:使用覆写比较运算的堆或者按优先级排序的队列,并不是先进的一定先出,是最佳优先


回溯算法

本质上是决策树深度优先遍历问题,用的是穷举思路,但实现过程中通过添加剪枝策略可以达到避免无效搜索的目的

基本思路

每一个节点只有在依次遍历完所有儿子节点后(穷举),才从扩展节点变成非活跃节点。要点:路径(已经做出的选择),选择列表(当前可以做出的选择),结束条件(达到决策树底层,无法再做选择)

回溯流程示意图

剪枝策略

  • 约束函数:在能产生子选择的结点(没有产生完)处剪去不满足约束条件的无效选择子树
    • 显式约束:对选择进行直接施加约束
    • 隐式约束:通过其它因素的互相作用来间接对选择施加约束
  • 限界函数:减去得不到最优解的子树(需要提前预判或使用预估值)

回溯框架

递归

# N皇后问题
result = []
def backtrack(路径, 选择列表):
    if 满足结束条件:
        result.add(路径)
        return

    for 选择 in 选择列表:
        做选择
        backtrack(路径, 选择列表)
        撤销选择

迭代

def backtrack():
	result = []
	if 不满足结束条件:
		for 选择 in 选择列表:
        	if 满足约束条件或限界条件:
        		result.add(路径)
       		else:
       			继续向下检索
     else:
     	触底,返回上一层重新选择

子集树

# 0-1背包问题【一个N数的集合里有多少符合条件的子集 (模式挖掘)】
def backtrack(路径, 选择列表):
	if 满足结束条件:
		result.add(路径)
	else:
		for 选择 in 选择列表:
			if 满足约束条件或限界条件:
				backtrack(路径, 选择列表) # 进入下一层
            撤销选择

排列树

# 旅行售货员问题
def backtrack(路径, 选择列表):
	if 满足结束条件:
		result.add(路径)
	else:
		for 选择 in 选择列表:
			做选择
			if 满足约束条件或限界条件:
				backtrack(路径, 选择列表) # 进入下一层
			做选择

HUIM中的运用

解空间

  • 对于数据集中的所有交易项的子集,用树型结构的思路进行挖掘

  • 对于项集的所有子集,不同的算法采用不同的子集树结构

约束条件

utility(X)minUtilutility(X) \ge minUtil

HUI-Miner

思路:使用回溯算法,深度遍历直到探底,对各个节点采用分支限界函数,筛选掉不合格的节点,避免无效检索

剪枝策略:使用上边界 U(X)(iu(X,Ti)+ru(X,Ti))(iu(X,Ti)+ru(X,Ti))U(X') \le \sum(iu(X', T_i) + ru(X', T_i)) \le (iu(X, T_i) + ru(X, T_i)),其中 XXX \subseteq X'

HUI-Miner检索子集树

EFIM

思路:与HUI-Miner同样

剪枝策略:U(X)su(X)<lu(X)<TWU(X)TWU(X)U(X') \le su(X') < lu(X') < TWU(X') \le TWU(X),其中 XXX \subseteq X'

EFIM检索子集树

FHM

思路:以每个一元项节点为根,再使用回溯算法,进行深度遍历

剪枝策略:u(X)=(iutils(X))<(iutils(X)+rutils(X))TWU(X)TWU(X)u(X') = \sum(iutils(X')) < \sum(iutils(X) + rutils(X)) \le TWU(X') \le TWU(X)

参考

  1. labuladong:回溯算法套路详解
  2. 高大宽333:回溯算法的递归和迭代
  3. 晓强DL:分支限界法
  4. 于星:回溯法、分支限界法