问题
I have this function compute an equivalence class
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;;
and this function to collect all the classes are equivalence
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;;
I have this function to compare two equivalence 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
After I used this function to sort it by using List.sort
let sort_eq_classes m = List.sort (cmp_classes m);;
My matrix is an boolean matrix, and I computed it with transitive closure.
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
I tested with many counter example to test all these functions, for example with the graph (matrix)
EDIT
matrix:
a <-> b c <-> d
|
v
e
matrix_2:
a <-> b -> e -> f
| |
v v
h <------- g
| |
v v
u k
I input the boolean matrix:
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 |];
|]
output of matrix 1:
equivalence classes: e d c b a
sort equivalence classes: e d c b a
output of matrix 2:
equivalence classes: u h g e b a k f
sort equivalence classes : u h k g f e b a
And the result is correct order like I expected. But when I test it with my data, which is an xsds data, more complicated depended relations. It output for me a wrong order. I had test with function transform to boolean matrix from xsds, and tested transitive closure, it is correct. So I think may be their is some bugs in my functions, (eq_class) or (cmp_classes).
Could you please help me to see what wrong in these code?
回答1:
The problem is in cmp_classes function.
From your 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
Obviously, your code doesn't fulfill your requirement. Several errors could be mentioned:
- If
m.(i).(j) = true, you don't compare betweeniandjat all. - If
m.(i).(j) = false, you suppose to compare other combinations thaniandj, but here you wrongly returns-1. - You only compare using the heads of
candc'and ignore other elements while you suppose to use any pair of elements in two lists before reaching a conclusion.
In your small examples, you got correct results because equivalence classes often have one element. Since they are collected in the order that there is no path from former ones to later ones, your returning of -1 is fortunately correct. It's no longer the case with arbitrary input from xsd trees.
It's not difficult to fix the function if you can define it clearly. Now I still don't know the order of two equivalence classes without any path connecting them together ({a,b} and {c, d} classes in matrix).
In order that you can test your fix more easily, this is a small example which will produce a wrong order:
a <-> b c <-> d
^ ^ ^ ^
| | | |
e e e e
来源:https://stackoverflow.com/questions/8850604/debuging-all-the-code-computing-and-sorting-equivalence-classes