Skip to content

Commit b192c75

Browse files
author
Jérôme FERET
committed
first commit
1 parent 63822a4 commit b192c75

File tree

3 files changed

+262
-0
lines changed

3 files changed

+262
-0
lines changed

core/connected/connected.ml

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
type id = int
2+
type update = {id: id ; previous_size: int ; current_size: int}
3+
type updates = update list
4+
5+
type t =
6+
{
7+
rep: int option Mods.DynArray.t ;
8+
back: Mods.IntSet.t Mods.DynArray.t ;
9+
size: int Mods.DynArray.t;
10+
11+
blackboard : int option Mods.DynArray.t ;
12+
blackboard_keys: id list ;
13+
to_check: Mods.IntSet.t ;
14+
updates: update option Mods.DynArray.t ;
15+
update_keys: id list;
16+
}
17+
18+
(*val bind: t -> id -> id -> t
19+
val check: neightboor:(id -> id list) -> t -> id list -> t
20+
val flush_updates: t -> t * updates
21+
val convert_updates: updates -> (int * int * int) list *)
22+
23+
let init =
24+
{
25+
blackboard = Mods.DynArray.create 0 None ;
26+
blackboard_keys = [];
27+
to_check = Mods.IntSet.empty ;
28+
updates = Mods.DynArray.create 0 None;
29+
update_keys = [] ;
30+
rep = Mods.DynArray.create 0 None ;
31+
size = Mods.DynArray.create 0 0 ;
32+
back = Mods.DynArray.create 0 (Mods.IntSet.empty);
33+
}
34+
35+
let get_rep t i =
36+
let rec aux t x l =
37+
let rep_opt = Mods.DynArray.get t.rep x in
38+
match rep_opt with
39+
| Some rep ->
40+
if x = rep then
41+
let t = List.fold_left (fun t x -> let () = Mods.DynArray.set t.rep x (Some rep) in t) t l in
42+
t, rep
43+
else
44+
aux t rep (x::l)
45+
| None -> (* TO DO ERROR *) assert false
46+
in aux t i []
47+
48+
let get_rep_size t i =
49+
t, Mods.DynArray.get t.size i
50+
51+
let get_size t i =
52+
let t, rep = get_rep t i in
53+
get_rep_size t rep
54+
55+
let add_update t update =
56+
match
57+
Mods.DynArray.get t.updates update.id
58+
with
59+
| None ->
60+
let t, previous_size = get_size t update.id in
61+
if previous_size = update.current_size then
62+
t
63+
else
64+
let id = update.id in
65+
let () =
66+
Mods.DynArray.set
67+
t.updates
68+
69+
update.id
70+
(Some {id ; previous_size; current_size = update.current_size})
71+
in
72+
let update_keys = id :: t.update_keys in
73+
{t with update_keys}
74+
75+
| Some last ->
76+
let () =
77+
Mods.DynArray.set t.updates update.id (Some {last with current_size = update.current_size})
78+
in t
79+
80+
let flush_updates t =
81+
let updates, l =
82+
List.fold_left
83+
(fun (updates,l) i ->
84+
match Mods.DynArray.get t.updates i with
85+
| None -> (updates, l)
86+
| Some u ->
87+
let () = Mods.DynArray.set updates i None in
88+
updates,
89+
(u)::l)
90+
(t.updates,[])
91+
t.update_keys
92+
in
93+
{t with updates}, l
94+
95+
let create t i =
96+
let () = Mods.DynArray.set t.rep i (Some i) in
97+
let () = Mods.DynArray.set t.size i 1 in
98+
let () = Mods.DynArray.set t.back i (Mods.IntSet.singleton i) in
99+
add_update t {id=i; previous_size=0; current_size=1}
100+
101+
let get_back_set t i = Mods.DynArray.get t.back i
102+
103+
let bind t i j =
104+
let t, repi = get_rep t i in
105+
let t, repj = get_rep t j in
106+
if repi = repj then
107+
t
108+
else
109+
let t, sizei = get_size t repi in
110+
let t, sizej = get_size t repj in
111+
let size = sizei + sizej in
112+
let repi, repj = if repi < repj then repi, repj else repj, repi in
113+
let () = Mods.DynArray.set t.rep repj (Some repi) in
114+
let () = Mods.DynArray.set t.size repi size in
115+
let cc = Mods.IntSet.union (get_back_set t repi) (get_back_set t repj) in
116+
let () = Mods.DynArray.set t.back repi cc in
117+
let () = Mods.DynArray.set t.back repj (Mods.IntSet.empty) in
118+
t
119+
120+
(* TO DO *)
121+
let unbind t i j =
122+
let to_check = t.to_check in
123+
let to_check = Mods.IntSet.add i to_check in
124+
let to_check = Mods.IntSet.add j to_check in
125+
{t with to_check}
126+
127+
let degrade ~neightbor:f t i =
128+
let list = f i in
129+
List.fold_left
130+
(fun t j -> unbind t i j)
131+
t list
132+
133+
let scan i l =
134+
let rec aux i l acc =
135+
match l with
136+
| (k,d)::t when k = i -> (List.rev acc)@t, Some d
137+
| (k,d)::t -> aux i t ((k,d)::t)
138+
| [] -> List.rev acc, None
139+
in
140+
aux i l []
141+
142+
let scan2 i l l' =
143+
match scan i l with
144+
| l, Some a -> Some a, l, l'
145+
| _, None ->
146+
begin
147+
let l', a = scan i l' in a, l, l'
148+
end
149+
150+
151+
let flush ~neightbor:f t =
152+
let set = t.to_check in
153+
let l = Mods.IntSet.fold (fun i l -> (i,[i])::l) set [] in
154+
let rec aux to_visit to_visit_after t alias =
155+
match to_visit, to_visit_after with
156+
| [],[] -> t, alias
157+
| [], _ -> aux (List.rev to_visit_after) [] t alias
158+
| (_, [])::tail', _ -> aux tail' to_visit_after t alias
159+
| (i,(h::tail))::tail', _ ->
160+
begin
161+
match Mods.DynArray.get t.blackboard h with
162+
| None ->
163+
let () = Mods.DynArray.set t.blackboard h (Some i) in
164+
let blackboard_keys = h::t.blackboard_keys in
165+
let t = {t with blackboard_keys} in
166+
let tail =
167+
List.fold_left
168+
(fun l x -> x::l)
169+
tail (f h)
170+
in
171+
aux tail' ((i,tail)::to_visit_after) t alias
172+
| Some i' when i=i' ->
173+
(* already seen, nothing to do *)
174+
aux tail' ((i,tail)::to_visit_after) t alias
175+
| Some i' ->
176+
(* seen in another equialent class -> merge *)
177+
merge (i,tail) i' tail' to_visit_after t ((i,i')::alias)
178+
end
179+
180+
and merge (i,l1) j to_visit to_visit_after t alias =
181+
let lj_opt, to_visit, to_visit_after = scan2 j to_visit to_visit_after in
182+
match lj_opt with
183+
| None -> assert false
184+
| Some l2 ->
185+
begin
186+
match to_visit, to_visit_after with
187+
| [], [] -> t, []
188+
| _, _ ->
189+
let l = l1@l2 in
190+
let i = min i j in
191+
let to_visit_after = (i,l)::to_visit_after in
192+
aux to_visit to_visit_after t alias
193+
end
194+
in
195+
let t, aliases = aux l [] t [] in
196+
let t =
197+
match aliases with
198+
| [] -> t
199+
| _ ->
200+
begin
201+
let aliases = List.rev_map (fun (i,j) -> if i<j then i,j else j,i) aliases in
202+
let aliases = List.sort (fun (a,_) (b,_) -> compare a b) aliases in
203+
let aliases =
204+
List.fold_left
205+
(fun m (i,j) ->
206+
let im =
207+
match Mods.IntMap.find_option i m with
208+
| None -> i
209+
| Some j -> j
210+
in
211+
Mods.IntMap.add j im m)
212+
Mods.IntMap.empty aliases
213+
in
214+
let rec split l m =
215+
match l with
216+
| [] -> m
217+
| h::q ->
218+
begin
219+
match Mods.IntMap.find_option h aliases with
220+
| None -> assert false
221+
| Some a ->
222+
let oldset =
223+
match Mods.IntMap.find_option a m with
224+
| None -> []
225+
| Some a -> a
226+
in
227+
split q (Mods.IntMap.add a (h::oldset) m)
228+
end
229+
in
230+
let m = split t.blackboard_keys Mods.IntMap.empty in
231+
let _ = m in
232+
(* iterate over blackboard_keys, to change representant *)
233+
(* iterater *)
234+
t
235+
end
236+
in
237+
flush_updates t

core/connected/connected.mli

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
type t
2+
type id = int
3+
type update = {id: id ; previous_size: int ; current_size: int}
4+
type updates = update list
5+
6+
val init: t
7+
8+
val create: t -> id -> t
9+
val bind: t -> id -> id -> t
10+
val unbind: t -> id -> id -> t
11+
val degrade: neightbor:(id -> id list) -> t -> id -> t
12+
13+
val flush: neightbor:(id -> id list) -> t -> t * updates
14+

core/connected/dune

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
(library
2+
(name kappa_connected)
3+
(libraries unix yojson result logs stdlib-shims bigarray camlp-streams kappa-library.generic)
4+
(public_name kappa-library.connected)
5+
(flags
6+
(:standard
7+
-w
8+
@a
9+
-open
10+
Kappa_data_structures
11+
)))

0 commit comments

Comments
 (0)