为什么我的回溯总是返回一个空列表?

问题描述

我有一个函数test p xs = [(x,y) | (x:ys) <- tails xs,y <- ys,p x y],它为指定列表(例如(\x -> \y -> x*y < 45))返回满足谓词(例如[2..11])的所有元组的列表。我想创建一个最大的最大独立集:列表中的每个数字仅包含一次,不多也不少。上述谓词和列表的示例解决方案是[(2,11),(3,10),(4,9),(5,8),(6,7)]

我当前的回溯脚本如下:

notinList pair list
 | list == [] = True
 | (fst pair) `elem` (tupletoList list) || (snd pair) `elem` (tupletoList list) = False
 | otherwise = True

gen pairs final len = do
 pair <- pairs
 guard $ notinList pair final
 if (length final) == len
 then return [pair]
 else do
  next <- gen (delete pair pairs) (pair : final) len
  return $ pair : next

tupletoList :: [(a,a)] -> [a]
tupletoList ((a,b):xs) = a : b : tupletoList xs
tupletoList _ = []

我运行gen (test (\x -> \y -> x*y < 45) [2..11]) [] 5,据我所知,最终应该回溯到正确的解决方案,但是脚本始终返回一个空列表。我在其他列表上也尝试过使用谓词,也提供了有效的解决方案,但我不确定出什么问题以及如何解决此脚本以执行所需的操作。我不确定返回空列表是否表明没有找到解决方案,还是只是在中间某个地方中断了。

解决方法

这部分可疑:

 guard $ notInList pair final
 if (length final) == len

假设final是一个最大的独立集,所以length final == len,其中len是您事先知道的结果的长度。然后,守卫必须是虚假的,这样您就可以回溯而不会到达那个if

在函数开始处测试是否获得了最终结果:

gen :: Eq a => [(a,a)] -> [(a,a)] -> Int -> [[(a,a)]]
gen pairs final len | length final == len = return final
gen pairs final len | otherwise = do
 -- Take a "pair" out and shadow "pairs" with the remainder.
 -- Use "tails" to avoid creating duplicate sets.
 -- For example,if you have a list [p1,p2,...] you want
 -- to try to pick p1 then p2,but after backtracking,it's no use trying p2 then p1.
 pair : pairs <- tails pairs
 guard $ notInList pair final
 gen pairs (pair : final) len