我有一个函数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
,据我所知,最终应该回溯到正确的解决方案,但是脚本始终返回一个空列表。我在其他列表上也尝试过使用谓词,也提供了有效的解决方案,但我不确定出什么问题以及如何解决此脚本以执行所需的操作。我不确定返回空列表是否表明没有找到解决方案,还是只是在中间某个地方中断了。
答案 0 :(得分:0)
这部分可疑:
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