为啥我的回溯总是返回一个空列表?
Posted
技术标签:
【中文标题】为啥我的回溯总是返回一个空列表?【英文标题】:Why does my backtracking always return an empty list?为什么我的回溯总是返回一个空列表? 【发布时间】:2020-11-04 22:33:26 【问题描述】:我有一个函数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
,据我所知,它最终会返回到正确的解决方案,但脚本总是返回一个空列表。我也用有效的解决方案在其他列表和谓词上尝试过它,但我不确定出了什么问题以及如何修复这个脚本来完成我需要它做的事情。我不确定返回空列表是否表明它没有找到解决方案,或者它只是在中间的某个地方中断。
【问题讨论】:
【参考方案1】:这部分很可疑:
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
【讨论】:
pair
不在此范围内。如果要信任类型,那可能应该是pairs
?
它似乎适用于使用[]
而不是pair
的较短列表,但它会尝试获取每个有效解决方案的所有可能排列,而不是出于某种原因只停留在一个?
好的,我已经解决了两个 cmets 的问题。以上是关于为啥我的回溯总是返回一个空列表?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 chrome.tabs.executeScript 方法的回调结果总是返回一个空对象?