forked from vouillon/coinst
-
Notifications
You must be signed in to change notification settings - Fork 1
/
repository.ml
258 lines (225 loc) · 7.95 KB
/
repository.ml
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
(* Co-installability tools
* http://coinst.irill.org/
* Copyright (C) 2010-2011 Jérôme Vouillon
* Laboratoire PPS - CNRS Université Paris Diderot
*
* These programs are free software; you can redistribute them and/or
* modify them under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*)
module type S = sig
type pool
module Package : sig
type t
val compare : t -> t -> int
val print : pool -> Format.formatter -> t -> unit
val print_name : pool -> Format.formatter -> t -> unit
val index : t -> int
val of_index : int -> t
val of_index_list : int list -> t list
end
module PSet : Set.S with type elt = Package.t
module PMap : Map.S with type key = Package.t
val pset_indices : PSet.t -> Util.IntSet.t
module PTbl : sig
type 'a t
val create : pool -> 'a -> 'a t
val init : pool -> (Package.t -> 'a) -> 'a t
val get : 'a t -> Package.t -> 'a
val set : 'a t -> Package.t -> 'a -> unit
val iteri : (Package.t -> 'a -> unit) -> 'a t -> unit
val map : ('a -> 'b) -> 'a t -> 'b t
val mapi : (Package.t -> 'a -> 'b) -> 'a t -> 'b t
val copy : 'a t -> 'a t
end
module type DISJ = sig
type t
val print : ?compact:bool -> pool -> Format.formatter -> t -> unit
val implies : t -> t -> bool
val equiv : t -> t -> bool
val lit : Package.t -> t
val lit_disj : Package.t list -> t
val _false : t
val disj : t -> t -> t
end
module Disj : sig
include DISJ
val iter : t -> (Package.t -> unit) -> unit
val fold : (Package.t -> 'a -> 'a) -> t -> 'a -> 'a
val cut : t -> Package.t -> t -> t
val for_all : (Package.t -> bool) -> t -> bool
val exists : (Package.t -> bool) -> t -> bool
val filter : (Package.t -> bool) -> t -> t
val compare : t -> t -> int
val implies1 : Package.t -> t -> bool
val to_lit : t -> Package.t option
val to_lits : t -> PSet.t
val of_lits : PSet.t -> t
val diff : t -> t -> t
val disj1 : Package.t -> t -> t
val cardinal : t -> int
module Set : Set.S with type elt = t
end
module Formula : sig
include DISJ
val _true : t
val conj : t -> t -> t
val conjl : t list -> t
val implies1 : t -> Disj.t -> bool
val iter : t -> (Disj.t -> unit) -> unit
val of_disj : Disj.t -> t
val fold : (Disj.t -> 'a -> 'a) -> t -> 'a -> 'a
val filter : (Disj.t -> bool) -> t -> t
val exists : (Disj.t -> bool) -> t -> bool
val normalize : t -> t
end
type dependencies = Formula.t PTbl.t
module Conflict : sig
type t
val create : pool -> t
val check : t -> Package.t -> Package.t -> bool
val add : t -> Package.t -> Package.t -> unit
val remove : t -> Package.t -> Package.t -> unit
val iter : t -> (Package.t -> Package.t -> unit) -> unit
val copy : t -> t
val has : t -> Package.t -> bool
val of_package : t -> Package.t -> PSet.t
val iter_on_packages : t -> (Package.t -> PSet.t -> unit) -> unit
val exists : t -> (Package.t -> bool) -> Package.t -> bool
val for_all : t -> (Package.t -> bool) -> Package.t -> bool
end
end
module F (M : Api.S) = struct
type pool = M.pool
module Package = struct
type t = int
let compare (x : int) y = compare x y
let print = M.print_pack
let print_name = M.print_pack_name
let index p = p
let of_index p = p
let of_index_list p = p
end
module PSet = Util.IntSet
let print_set ch pr sep l = Util.print_list ch pr sep (PSet.elements l)
let pset_of_lst l = List.fold_left (fun s x -> PSet.add x s) PSet.empty l
let pset_map f s = pset_of_lst (List.map f (PSet.elements s))
let pset_indices s = s
module PMap = Map.Make (Package)
module PTbl = struct
type 'a t = 'a array
let create pool v = Array.make (M.pool_size pool) v
let init pool f =
Array.init (M.pool_size pool) (fun i -> f (Package.of_index i))
let get a i = a.(Package.index i)
let set a i v = a.(Package.index i) <- v
let iteri f a = Array.iteri (fun i v -> f (Package.of_index i) v) a
let map = Array.map
let mapi f a = Array.mapi (fun i v -> f (Package.of_index i) v) a
let copy = Array.copy
end
module type DISJ = sig
type t
val print : ?compact:bool -> pool -> Format.formatter -> t -> unit
val implies : t -> t -> bool
val equiv : t -> t -> bool
val lit : Package.t -> t
val lit_disj : Package.t list -> t
val _false : t
val disj : t -> t -> t
end
module Disj = struct
type t = PSet.t
let print ?(compact=false) pool ch l =
if PSet.is_empty l then
Format.fprintf ch "MISSING"
else
print_set
(if compact then Package.print_name pool else Package.print pool)
" | " ch l
let implies = PSet.subset
let equiv = PSet.equal
let lit = PSet.singleton
let lit_disj l = List.fold_right PSet.add l PSet.empty
let _false = PSet.empty
let disj = PSet.union
let iter s f = PSet.iter f s
let cut d p d' = assert (PSet.mem p d); PSet.union (PSet.remove p d) d'
let fold = PSet.fold
let for_all = PSet.for_all
let exists = PSet.exists
let implies1 = PSet.mem
let to_lit l = if PSet.cardinal l = 1 then Some (PSet.choose l) else None
let to_lits l = l
let of_lits l = l
let filter = PSet.filter
let normalize d = pset_map (fun i -> i) d
let compare = PSet.compare
let diff = PSet.diff
let cardinal = PSet.cardinal
let disj1 = PSet.add
module Set = Set.Make (struct type t = PSet.t let compare = compare end)
end
module Formula = struct
type t = Disj.t list
let print ?compact pool ch d =
Util.print_list (Disj.print ?compact pool) ", " ch d
let of_disj d = [d]
let lit p = of_disj (Disj.lit p)
let lit_disj l = of_disj (Disj.lit_disj l)
let implies1 l1 y = List.exists (fun x -> Disj.implies x y) l1
let implies l1 l2 =
List.for_all (fun y -> implies1 l1 y) l2
let equiv l1 l2 =
List.for_all (fun y -> List.exists (fun x -> Disj.equiv x y) l1) l2 &&
List.for_all (fun y -> List.exists (fun x -> Disj.equiv x y) l2) l1
let _true = []
let conj1 l x =
if implies1 l x then l else
x :: List.filter (fun y -> not (Disj.implies x y)) l
let conj l1 l2 = List.fold_left conj1 l1 l2
let conjl l = List.fold_left conj _true l
let _false = of_disj (Disj._false)
let disj l1 l2 =
List.fold_left
(fun l x -> List.fold_left (fun l y -> conj1 l (Disj.disj x y)) l l2)
_true l1
let iter l f = List.iter f l
let fold f l = List.fold_right f l
let filter = List.filter
let exists = List.exists
let normalize f =
let f = List.map Disj.normalize f in
let f = List.sort PSet.compare f in
f
end
type dependencies = Formula.t PTbl.t
module Conflict = struct
type t = PSet.t PTbl.t
let create pool = PTbl.create pool PSet.empty
let has c p1 = not (PSet.is_empty (PTbl.get c p1))
let check c p1 p2 = PSet.mem p1 (PTbl.get c p2)
let add c p1 p2 =
PTbl.set c p1 (PSet.add p2 (PTbl.get c p1));
PTbl.set c p2 (PSet.add p1 (PTbl.get c p2))
let remove c p1 p2 =
PTbl.set c p1 (PSet.remove p2 (PTbl.get c p1));
PTbl.set c p2 (PSet.remove p1 (PTbl.get c p2))
let iter c f =
PTbl.iteri (fun i s -> PSet.iter (fun j -> if i < j then f i j) s) c
let iter_on_packages c f = PTbl.iteri f c
let of_package = PTbl.get
let copy = PTbl.copy
let exists c f p = PSet.exists f (PTbl.get c p)
let for_all c f p = PSet.for_all f (PTbl.get c p)
end
end