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

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 -&gt; \y -&gt; x*y &lt; 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 方法的回调结果总是返回一个空对象?

为啥空列表中的任何一个都返回不同的东西?

为啥 ContentProvider 在 App 更新后返回空游标?

为啥返回空字节作为响应?

为啥与空列表连接时返回列表但与新列表连接时不返回?