我需要使用 BFS 制作一个算法来解决这个问题: 给定一个有向加权图,一个起始节点,一个停止节点和一个整数K,比如说在开始和停止之间是否存在一条至少为k的路径。
所以,首先我宣布了我的加权导向图类型,一个三元组列表:
type 'a graph = Gr of ('a * 'a * 'a) list;;
let grafo1 = Gr [(1,3,2);(1,1,5);(2,2,3);(5,5,3);(5,4,6);(3,1,6);(3,7,4);(6,2,7);(4,4,6)];;
在(x,y,z)
中,x
是起始节点,y
是边缘权重,z
是到达节点。
然后我做了一个 succ
功能:
let succ (Gr arcs) n=
let rec aux = function
[] -> []
| (x,y,z):: rest ->
if n = x then z::(aux rest)
else aux rest
in aux arcs;;
这个函数给我一个节点的后继者作为oputput,所以:
succ grafo1 1
给了我
int list = [2; 5]
作为输出。
最后,我创建了这个 bf_path
函数,它是一个修改过的BFS,可以找到2个节点之间的路径(否则会引发异常),需要3个输入:图形,谓词和起始节点
let bf_path g p start =
let rec aux visited = function
[] -> raise Not_found
| x::rest -> if List.mem x visited then aux visited rest
else if p x then [x]
else try aux (x::visited) rest
with Not_found ->
x:: aux (x::visited) (succ g x)
in aux [] [start];;
谓词指定条件,因此调用:
bf_path grafo1 ((=)7)1
给我int list = [1; 5; 6; 7]
作为输出,即节点1和7之间的路径。
现在,我可以找到一条路径,但我需要找到至少权重K
的路径,所以我做了一个小函数,它将三元组列表作为输入,它总重量值:
let rec tot = function
[] -> 0
|(v,c,p)::t -> c + (tot t);;
所以,呼叫和输出:
tot [(2,2,3);(4,5,6);(8,9,0)]
- : int = 16
我认为我需要的是在函数内部添加条件,所以我创建了这个函数,我添加了一个int K
作为输入和条件:(tot path >= k)
let bf_path_final g p start k =
let rec aux visited = function
[] -> raise Not_found
| x::rest -> if List.mem x visited then aux visited rest
else if p x then
if (tot [x]) >= k then [x]
else aux visited rest
else try aux (x::visited) rest
with Not_found ->
x:: aux (x::visited) (succ g x)
in aux [] [start];;
该函数编译没有问题:
val bf_path_final : ('a * int * 'b) graph ->
('a * int * 'b -> bool) -> 'a * int * 'b -> int -> ('a * int * 'b) list = <fun>
但是,当我尝试调用它时,我收到错误:
bf_path_final grafo1 ((=)4)1,13;;
^^^^^^
Error: This expression has type int graph_w
but an expression was expected of type ('a * int * 'b) graph_w
那么,函数是错误的还是我必须以另一种方式调用它?
另一个解决方案是将函数 bf_path 输出(路径)作为 tot 函数的输入,但我的输出是一个列表int,而不是三元组列表,所以我试图将我的第一个函数转换为三元组的输出:
(例如:代替[1;5;6;7]
,它应该提供[(1,1,5);(5,4,6);(6,2,7)]
)
let bf_path_tr g p start =
let rec aux visited = function
[] -> raise Not_found
| (x,y,z)::rest -> if List.mem x visited then aux visited rest
else if p x then [(x,y,z)]
else try aux (x::visited) rest
with Not_found ->
(x,y,z):: aux (x::visited) (succ_w g (x,y,z))
in aux [] [start];;
结果相同,编译函数
val bf_path_tr :
('a * 'b * 'c) graph ->
('a -> bool) -> 'a * 'b * 'c -> ('a * 'b * 'c) list = <fun>
但是我得到了同样的错误:
bf_path_tr grafo1 ((=)7)2
Characters 11-18:
bf_path_tr grafo1 ((=)7)2;;
^^^^^^
Error: This expression has type int graph
but an expression was expected of type ('a * 'b * 'c) graph
要解决这两个问题中的至少一个的任何想法?
答案 0 :(得分:0)
调试此类事情的最佳方法是开始在任何地方添加显式类型注释,直到找到您的期望与推断类型不匹配的位置。
let bf_path_final (g : int graph) (p : int -> bool) (start : int) (k : int) =
let rec aux (visited : int list) = function
[] -> raise Not_found
| x::rest -> if List.mem x visited then aux visited rest
else if p x then (
if (tot [x]) >= k then [x]
else aux visited rest )
else try aux (x::visited) rest
with Not_found ->
x:: aux (x::visited) (succ g x)
in aux [] [start];;
引发错误
File "test.ml", line 32, characters 17-18:
Error: This expression has type int but an expression was expected of type
'a * int * 'b
指向if (tot [x])
,其中tot
确实需要三元组列表,但您已将其传递给了一个int列表。
你真的打电话给tot [x]
吗?它不是任何东西; x只是那里的一个节点。