图搜索算法失败

Graph search algorithm fails

我试图修改我的代码,该代码使用 Graph a 来查找连接到顶点 n 的任何顶点。这里连接的定义是顶点 m 直接连接到顶点 n(通过边)或连接到顶点 k,后者又连接到顶点 n .

我要修改的代码

-- ** Code 1 **

findPath :: Eq a => Graph a -> a -> [a]
findPath (Graph v w) a
    | [x | x<-v, x==a] == [] = []
    | otherwise = findPath' (Graph v w) [a]

findPath' :: Eq a => Graph a -> [a] -> [a]
findPath' (Graph [] _) _ = []
findPath' (Graph _ _) [] = []
findPath' (Graph v w) (tp:st)
    | [x | x<-v, x==tp] == [] = findPath' (Graph vv w) st
    | otherwise = tp : findPath' (Graph vv w) (adjacent ++ st)
    where
        adjacent = [x | (x,y)<-w, y==tp] ++ [x | (y,x)<-w, y==tp]
        vv = [x | x<-v, x/=tp]

connected :: Eq a => Graph a -> a -> a -> Bool
connected g a b =  if (a `elem` (findPath g b)) == True then True else False

我的修改尝试

-- **Code 2**

convert :: [a] -> [(a, a)]
convert [] = []
convert (k:v:t) = (k, v) : convert t


-- a is vertex
-- [a] is a list from neighbors
getEdges :: Eq a => a -> [a] -> [a]
getEdges _ [] = []
getEdges a (y:ys) = a : y : getEdges a ys


-- vertices :: Eq a => Graph a -> [a]
-- neighbors :: Eq a => Graph a -> a -> [a]
-- [a] is a list of vertex
mergeEdges :: Eq a => Graph a -> [a] -> [a]
mergeEdges _ [] = []
mergeEdges g (x:xs) = getEdges x (neighbors g x) ++ mergeEdges g xs

removeElements :: Eq a => [(a,a)] -> [(a,a)]
removeElements [] = []
removeElements ((a,b) : (v,w) : xs) =  [(a,b)] ++ removeElements xs

--v = vertex, w = edges
findPath :: Eq a => [a] -> [(a,a)] -> a -> [a]
findPath v w a
    | [x | x<-v, x==a] == [] = []
    | otherwise = findPath' v w [a]

--v = vertex, w = edges
findPath' :: Eq a => [a] -> [(a,a)] -> [a] -> [a]
findPath' [] _ _ = []
findPath' _ _ [] = []
findPath' v w (tp:st)
    | [x | x<-v, x==tp] == [] = findPath' vv w st
    | otherwise = tp : findPath' vv w (adjacent ++ st)
    where
        adjacent = [x | (x, y)<-w, y==tp] ++ [x | (y,x)<-w, y==tp]
        vv = [x | x<-v, x/=tp]

getParam :: Eq a => Graph a -> [(a,a)]
getParam g = removeElements ((convert(mergeEdges g (vertices g))))


connected :: Eq a => Graph a -> a -> a -> Bool
connected g a b = if (a `elem` (findPath (vertices g) (getParam g) b ) ) == True then True else False

测试代码

这是我的图表:Graph {vers = [-6,-3,5,3], edgs = [(-6,5),(3,-3),(-3,5)]}

代码 1:

ghci> connected g 3 5
True

代码 2:

ghci> connected g 3 5
False

我最好的猜测是,当我将参数从图 a 更改为元组列表 [(a,a)] 时,我的代码在这里停止工作,但我不明白为什么:

| otherwise = tp : findPath' vv w (adjacent ++ st)
where
    adjacent = [x | (x, y)<-w, y==tp] ++ [x | (y,x)<-w, y==tp]

我不能使用图 a, (..) 中的构造函数,因为它是不允许的:-( 因此我需要修改我的代码。

添加附加代码

data Graph a = Graph {
  vers :: [Vertex a],
  edgs    :: [Edge a]
} deriving (Show, Eq, Read)

neighbors :: Eq a => Graph a -> a -> [a]
neighbors (Graph x []) _ = []
neighbors (Graph x ((v, w) : xs)) a
     | a == v = w : neighbors (Graph x xs) a
     | a == w = v : neighbors (Graph x xs) a
     | (v, w) : xs == [] = []
     | otherwise = neighbors (Graph x xs) a

当我 运行 你 getParam 在你的示例输入 Graph {vers = [-6,-3,5,3], edgs = [(-6,5),(3,-3),(-3,5)]} 上运行时,我得到:

ghci> getParam g
[(-6,5),(-3,5),(5,-3)]

这里可以看到边(-3,5)和(5,-3)重复了,边(3,-3)消失了。所以,我认为你的 removeElements 功能太简单了。您也许可以尝试先对元组进行排序然后删除重复项的函数:

import Data.List (nub)

...

sortTuple :: Ord a => (a, a) -> (a, a)
sortTuple (x, y)
  | x <= y = (x, y)
  | otherwise = (y, x)

removeElements :: Ord a => [(a, a)] -> [(a, a)]
removeElements xs = nub (map sortTuple xs)

-- also change the types of some other functions:
getParam :: Ord a => Graph a -> [(a,a)]
connected :: Ord a => Graph a -> a -> a -> Bool

使用该函数我得到 getParam g == [(-6,5),(-3,3),(-3,5)]connected g 3 5 == True.

但我还想知道你为什么不直接使用 getParams g = edgs g