调试所有代码计算和排序等价类

时间:2012-01-13 12:29:26

标签: debugging ocaml

我有这个函数计算等价类

let eq_class m i =
  let column = m.(i)
  and set = ref [] in
  Array.iteri begin fun j l ->
    if j = i || column.(j) && m.(j).(i) then
      set := j :: !set else ignore l
  end column;
  !set;;

这个收集所有类的函数是等价的

let eq_classes m =
  let classes = ref [] in
  Array.iteri begin fun e _ ->
    if not (List.exists (List.mem e) !classes) then
      classes := eq_class m e :: !classes
  end m;
  !classes;;

我有这个功能来比较两个等价类:

let cmp_classes m c c' = if c = c' then 0 else
  match c, c' with
    | i :: _, j :: _ -> if m.(i).(j) then 1 else -1
    | _ -> assert false

使用此函数后,使用List.sort

对其进行排序
let sort_eq_classes m = List.sort (cmp_classes m);;

我的矩阵是一个布尔矩阵,我用传递闭包计算它。

let transClosure m =
  let n = Array.length m in
  for k = 0 to n - 1 do
    let mk = m.(k) in
    for i = 0 to n - 1 do
      let mi = m.(i) in
      for j = 0 to n - 1 do
    mi.(j) <- max mi.(j) (min mi.(k) mk.(j))
      done;
    done;
  done;
  m;;

let tc = transClosure matrix
let eq = eq_classes tc
let sort_eq = sort_eq_classes tc eq

我测试了许多计数器示例来测试所有这些函数,例如使用图形(矩阵)

修改

矩阵

 a <-> b  c <-> d
 |          
 v          
 e

matrix_2:

a <-> b -> e -> f
|          |
v          v
h <------- g 
|          |
v          v  
u          k    

我输入布尔矩阵:

    let matrix =
   [|
   [|false; true; false; false; false|];
   [|true; false; false; false; false|];
   [|false; false; false; true; false|];
   [|false; false; true; false; false|];
   [|false; false; false; false; false|];
   |];;

let matrix_2 =
    [|
    [| false; false; false; false; false; false; false; false |];
    [| false; false; false; false; false; false; false; false |];
    [| false; false; false; true; false; false; true; false |];
    [| false; false; true; false; true; false; false; false |];
    [| true; false; false; false; false; true; false; false |];
    [| false; true; false; false; false; false; true; false |];
    [| false; false; false; false; false; false; false; true |];
    [| false; false; false; false; false; false; false; false |];
    |]

矩阵1的输出: 等价类:e d c b a

排序等价类:e d c b a

矩阵2的输出: 等价类:u h g e b a k f

排序等价类:u h k g f e b a

结果是正确的顺序,就像我预期的那样。但是当我用我的数据测试它时,这是一个xsds数据,更复杂的依赖关系。它为我输出了错误的订单。我从xsds测试了函数变换为布尔矩阵,并测试了传递闭包,这是正确的。所以我认为可能是我的函数中存在一些错误(eq_class)或(cmp_classes)。

你能帮我看看这些代码有什么问题吗?

1 个答案:

答案 0 :(得分:1)

问题出在cmp_classes函数中。

来自source code

(* We check that if two elements are in the same equivalence class they are
   equal (0); if they have a path from i to j then i < j (-1)
   otherwise i > j (1). We assumes that: each equivalence class only
   appears once and each equivalence class contains at least one
   element. *)

let cmp_classes m c c' = if c = c' then 0 else
  match c, c' with
    | i :: _, j :: _ -> if m.(i).(j) then 1 else -1
    | _ -> assert false

显然,您的代码无法满足您的要求。可以提到几个错误:

  1. 如果m.(i).(j) = true,您根本不会在ij之间进行比较。
  2. 如果m.(i).(j) = false,您希望比较ij之外的其他组合,但在此错误地返回-1
  3. 您只能使用cc'的头部进行比较而忽略其他元素,而您希望在得出结论之前在两个列表中使用任何元素对。
  4. 在您的小例子中,您得到了正确的结果,因为等价类通常有一个元素。由于它们是按照从前者到后者的路径的顺序收集的,所以回归-1是幸运的。来自xsd树的任意输入不再是这种情况。

    如果你能清楚地定义它,修复这个功能并不困难。现在我仍然不知道两个等价类的顺序,没有任何路径将它们连接在一起({a,b}中的{c, d}matrix类。

    为了让您可以更轻松地测试修复,这是一个小例子,会产生错误的订单:

     a <-> b  c <-> d
     ^     ^  ^     ^
     |     |  |     |
     e     e  e     e