我有这个函数计算等价类
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
)。
你能帮我看看这些代码有什么问题吗?
答案 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
显然,您的代码无法满足您的要求。可以提到几个错误:
m.(i).(j) = true
,您根本不会在i
和j
之间进行比较。m.(i).(j) = false
,您希望比较i
和j
之外的其他组合,但在此错误地返回-1
。c
和c'
的头部进行比较而忽略其他元素,而您希望在得出结论之前在两个列表中使用任何元素对。在您的小例子中,您得到了正确的结果,因为等价类通常有一个元素。由于它们是按照从前者到后者的路径的顺序收集的,所以回归-1
是幸运的。来自xsd树的任意输入不再是这种情况。
如果你能清楚地定义它,修复这个功能并不困难。现在我仍然不知道两个等价类的顺序,没有任何路径将它们连接在一起({a,b}
中的{c, d}
和matrix
类。
为了让您可以更轻松地测试修复,这是一个小例子,会产生错误的订单:
a <-> b c <-> d
^ ^ ^ ^
| | | |
e e e e