File: quotient.ml

package info (click to toggle)
coinst 1.01-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 652 kB
  • sloc: ml: 6,576; makefile: 119
file content (129 lines) | stat: -rw-r--r-- 3,696 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
module F (R : Repository.S) = struct

open R

type t =
  { pool : pool;
    count : int;
    repr_tbl : Package.t PTbl.t;
    repr_map : PSet.t PMap.t }

let trivial pool =
  let count = ref 0 in
  let repr_map = ref PMap.empty in
  let repr_tbl =
    PTbl.init pool
      (fun p ->
        incr count; repr_map := PMap.add p (PSet.singleton p) !repr_map; p)
  in
  { pool = pool; count = !count; repr_tbl = repr_tbl; repr_map = !repr_map }

let subset pool s =
  let count = ref 0 in
  let repr_map = ref PMap.empty in
  let repr_tbl =
    PTbl.init pool
      (fun p ->
         if PSet.mem p s then begin
           incr count; repr_map := PMap.add p (PSet.singleton p) !repr_map
         end;
         p)
  in
  { pool = pool; count = !count; repr_tbl = repr_tbl; repr_map = !repr_map }

let perform pool ?packages deps =
  let classes_by_dep = Hashtbl.create 17 in
  let class_count = ref 0 in
  let add_package p f =
    let f = Formula.normalize f in
    let s =
      try
        Hashtbl.find classes_by_dep f
      with Not_found ->
        incr class_count;
        let s = ref PSet.empty in
        Hashtbl.add classes_by_dep f s;
        s
    in
    s := PSet.add p !s
  in
  begin match packages with
    None   -> PTbl.iteri add_package deps
  | Some s -> PSet.iter (fun p -> add_package p (PTbl.get deps p)) s
  end;
  (* Compute good representatives *)
  let repr_tbl = PTbl.create pool (Package.of_index (-1)) in
  let repr_map = ref PMap.empty in
  Hashtbl.iter
    (fun f {contents = s} ->
       let s' =
         Formula.fold (fun d s -> PSet.union (Disj.to_lits d) s)
           f PSet.empty
       in
       let s' = PSet.inter s s' in
       let p = try PSet.choose s' with Not_found -> PSet.choose s in
       repr_map := PMap.add p s !repr_map;
       PSet.iter (fun q -> PTbl.set repr_tbl q p) s)
    classes_by_dep;
  {pool = pool; count = !class_count;
   repr_map = !repr_map; repr_tbl = repr_tbl}

let print_class quotient ch p =
  let n = PSet.cardinal (PMap.find p quotient.repr_map) in
  if n = 1 then
    Format.fprintf ch "%a" (Package.print_name quotient.pool) p
  else
    Format.fprintf ch "%a (x %d)" (Package.print_name quotient.pool) p n

let print quotient deps =
  (* Output equivalence classes *)
  Util.title (Format.sprintf "EQUIVALENCE CLASSES (%d)" quotient.count);
  PMap.iter
    (fun p s ->
       (* Skip the class of always installable packages *)
       if not (Formula.implies Formula._true (PTbl.get deps p)) then begin
         Format.printf "%a:" (print_class quotient) p;
         PSet.iter
           (fun q -> Format.printf " %a" (Package.print quotient.pool) q) s;
         Format.printf "@."
       end)
    quotient.repr_map;
  Format.printf "@."

let repr quotient p = PTbl.get quotient.repr_tbl p

let formula quotient f =
  Formula.fold
    (fun d f ->
       Formula.conj
         (Disj.fold
            (fun p d -> Formula.disj (Formula.lit (repr quotient p)) d)
            d Formula._false)
         f)
    f Formula._true

let dependencies quotient deps =
  let class_deps = PTbl.create quotient.pool Formula._false in
  PMap.iter
    (fun p _ -> PTbl.set class_deps p (formula quotient (PTbl.get deps p)))
    quotient.repr_map;
  class_deps

let conflicts quotient confl =
  let c = Conflict.create quotient.pool in
  Conflict.iter confl
    (fun p1 p2 -> Conflict.add c (repr quotient p1) (repr quotient p2));
  c

let package_set quotient s =
  PSet.fold (fun p s -> PSet.add (repr quotient p) s) s PSet.empty

let clss quotient p = PMap.find p quotient.repr_map

let class_size quotient p = PSet.cardinal (clss quotient p)

let iter f quotient = PMap.iter (fun p _ -> f p) quotient.repr_map

let pool q = q.pool

end