【问题标题】:What is wrong with this implementation of IDA* algorithm in Haskell? Bad heuristic or simply bad code?Haskell 中 IDA* 算法的这种实现有什么问题?糟糕的启发式或只是糟糕的代码?
【发布时间】:2015-07-25 14:51:03
【问题描述】:

我正在尝试编写一个可以解决魔方的haskell 程序。首先我尝试了this,但没有找到避免编写大量代码的方法,所以我尝试使用 IDA* 搜索这个任务。

但我不知道这里适合哪种启发式方法:我尝试将问题划分为子问题,并测量距离处于缩减状态的距离,但结果令人失望:程序无法缩减距离为三步的立方体在合理的时间内一个标准立方体。我尝试测量边缘的某些部分,然后对它们求和,或者使用最大值......但这些都不起作用,结果几乎相同。

所以我想知道代码的问题是什么:我使用的启发式是不可接受的吗?还是我的代码导致了一些我没有检测到的无限循环?或两者?以及如何解决这个问题?代码(相关部分)如下:

--Some type declarations
data Colors = R | B | W | Y | G | O
type R3 = (Int, Int, Int)
type Cube = R3 -> Colors
points :: [R3] --list of coordinates of facelets of a cube; there are 48 of them.
mU :: Cube -> Cube --and other 5 similar moves.

type Actions = [Cube -> Cube]

turn :: Cube -> Actions -> Cube --chains the actions and turns the cube.

edges :: [R3] --The edges of cubes

totheu1 :: Cube -> Int  -- Measures how far away the cube is from having the cross of the first layer solved.
totheu1 c = sum $ map (\d -> if d then 0 else 1)
                      [c (-2, 3, 0) == c (0, 3, 0),
                       c (2, 3, 0) == c (0, 3, 0),
                       c (0, 3, -2) == c (0, 3, 0),
                       c (0, 3, 2) == c (0, 3, 0),
                       c (0, 2, -3) == c (0, 0, -3),
                       c (-3, 2, 0) == c (-3, 0, 0),
                       c (0, 2, 3) == c (0, 0, 3),
                       c (3, 2, 0) == c (3, 0, 0)]

expandnr :: (Cube -> Cube) -> Cube -> [(Cube, String)] -- Generates a list of tuples of cubes and strings, 

-- the result after applying a move, and the string represents that move, while avoiding moving on the same face as the last one, 

-- and avoiding repetitions caused by commuting moves, like U * D = D * U.

type StateSpace = (Int, [String], Cube) -- Int -> f value, [String] = actions applied so far, Cube = result cube.

fstst :: StateSpace -> Int
fstst s@(x, y, z) = x

stst :: StateSpace -> [String]
stst s@(x, y, z) = y

cbst :: StateSpace -> Cube
cbst s@(x, y, z) = z

stage1 :: Cube -> StateSpace
stage1 c = (\(x, y, z) -> (x, [sconcat y], z)) t
 where
 bound = totheu1 c
 t = looping c bound
 looping c bound = do let re = search (c, [""]) (\j -> j) 0 bound
                      let found = totheu1 $ cbst re
                      if found == 0 then re else looping c found
 sconcat [] = ""
 sconcat (x:xs) = x ++ (sconcat xs)

straction :: String -> Actions -- Converts strings to actions

search :: (Cube, [String]) -> (Cube -> Cube) -> Int -> Int -> StateSpace
search cs@(c, s) k g bound
 | f > bound = (f, s, c)
 | totheu1 c == 0 = (0, s, c)
 | otherwise = ms
 where
 f = g + totheu1 c
 olis = do
         (succs, st) <- expandnr k c
         let [newact] = straction st
         let t = search (succs, s ++ [st]) newact (g + 1) bound
         return t
 lis = map fstst olis
 mlis = minimum lis
 ms = olis !! (ind)
 Just ind = elemIndex mlis lis

我知道这个启发式是不一致的,但不确定它是否真的可以接受,也许问题在于它的不可接受性?

非常感谢任何想法、提示和建议,在此先感谢。

【问题讨论】:

  • 如果距离解决问题还有三步之遥,那么即使使用简单的启发式方法,您也应该可以使用 IDA* 轻松解决问题 - 不进行切割并将扩展按任何顺序排列。摆脱启发式并尝试让您消除或确定启发式是问题的根源。
  • @Cirdec 我将启发式更改为 0,如果减少,否则为 1,但程序仍然没有输出任何内容......我认为代码一定是错误的地方。

标签: algorithm haskell iterative-deepening


【解决方案1】:

你的启发式是不可接受的。可接受的启发式必须是解决方案实际成本的下限。

您正在尝试使用第一层不正确的边片数量作为启发式,或者可能是第一层的边片的不正确的数量' t 正确,这是你实际写的。无论哪种方式,启发式都是不可接受的。

下面的立方体只是1 远离被解决,但第一层中的4 的位置不正确,并且面的4 的颜色错误。任何一种启发式方法都会说这个谜题至少需要4 移动来解决,而它只能用1 移动来解决。启发式是不可接受的,因为它们不是解决方案实际成本的下限。

【讨论】:

  • 感谢您的解释。但是如果减少,将启发式更改为 0,否则更改为 1 并没有多大帮助:在这种情况下,启发式应该是可以接受的,对吧?也许我应该重新编写代码。
  • 我鼓励您重构代码,以便为任何问题通用编写 IDA* 搜索,并且后继魔方移动独立于启发式。这将使您可以将每个部分与其他部分分开测试。 IDA* 搜索可以写成 heuristic :: Num cost =&gt; node -&gt; cost 和后继函数 expand :: node -&gt; [(cost, node)] 给整个函数类型 idastar :: Num cost, Alternative f =&gt; (node -&gt; cost) -&gt; (node -&gt; [(cost, node)]) -&gt; node -&gt; f node
  • 我在 Haskell 方面的经验不足,无法理解您提出的功能:它与 Alternative here 有什么关系?为什么idastar的结果在f节点​​?我应该使用既形成 Monoid 又是 Applicative 函子的东西?感谢您提出分离启发式和扩展的建议!最后请问我写的stage1有问题吗?也就是说,它是否会导致任何明显的无限循环?还是那段代码太混乱而无法正确理解?
  • @awllower 您可以只使用Maybe 表示“可能有结果”,而不是任何Alternative f =&gt; f。使用Alternative 中的&lt;|&gt; 可能仍然有用,因为Maybe 的monoid 实例是无用的。 Applicative/Alternative 实例 Maybe 只是 pure = Just&lt;*&gt;liftA2 组合 Justs、empty = Nothing&lt;|&gt; 采用第一个 Just。使用Alternative,您可以替换一个列表并按顺序获得所有答案。
  • 你的意思是当不可能减少多维数据集时,结果将是空?好的,我会朝着这个方向努力。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-07
  • 2015-07-23
  • 1970-01-01
  • 1970-01-01
  • 2021-02-13
  • 2011-03-16
  • 2014-01-05
相关资源
最近更新 更多