This commit is contained in:
Leonie Gallois 2020-11-23 12:38:57 +01:00
джерело f0b0e8554d
коміт 96f15c7045
12 змінених файлів з 58 додано та 76 видалено

@ -4,7 +4,7 @@ type path = id list
(*type record avec id noeud et son cout*) (*type record avec id noeud et son cout*)
type t_cost={ type t_cost={
mutable cout:int; mutable cout:float;
mutable father:int mutable father:int
} }
@ -12,12 +12,12 @@ let blf gr id_src id_dest=
(*je compte le nb de noeuds dans le graphe pour instancier mon tableau*) (*je compte le nb de noeuds dans le graphe pour instancier mon tableau*)
let nb_n=n_fold gr (fun acu id->acu+1) 0 in let nb_n=n_fold gr (fun acu id->acu+1) 0 in
let cost ={cout=max_int; father=(-1)} in let cost ={cout=max_float; father=(-1)} in
let acu =Array.make nb_n cost in let acu =Array.make nb_n cost in
(*je fais un fold_left pour pouvoir individualiser au niveau de la mémoire les cases de la table*) (*je fais un fold_left pour pouvoir individualiser au niveau de la mémoire les cases de la table*)
let blf_tab=n_fold gr (fun acu id->acu.(id)<-{cout=max_int; father=(-1)}; acu ) acu in let blf_tab=n_fold gr (fun acu id->acu.(id)<-{cout=max_float; father=(-1)}; acu ) acu in
blf_tab.(id_src).cout<-0; blf_tab.(id_src).cout<-0.0;
let file_id=[id_src] in let file_id=[id_src] in
let file_marque =[] in let file_marque =[] in
@ -29,9 +29,9 @@ let blf gr id_src id_dest=
match l_out_arc with match l_out_arc with
|[]-> blf_rec gr file (a::file_marque) |[]-> blf_rec gr file (a::file_marque)
|(id,label)::d-> |(id,label)::d->
if label != 0 && (blf_tab.(a).cout+label)<blf_tab.(id).cout then if label != 0.0 && (Float.add blf_tab.(a).cout label)<(blf_tab.(id).cout) then
begin begin
blf_tab.(id).cout<-(blf_tab.(a).cout+label); blf_tab.(id).cout<-(Float.add blf_tab.(a).cout label);
blf_tab.(id).father<-a; blf_tab.(id).father<-a;
if not (List.mem id file_marque) then loop_suc d blf_tab (id::file) else loop_suc d blf_tab file if not (List.mem id file_marque) then loop_suc d blf_tab (id::file) else loop_suc d blf_tab file
end end

@ -3,10 +3,10 @@ open Graph
type path = id list type path = id list
type t_cost={ type t_cost={
mutable cout:int; mutable cout:float;
mutable father:int mutable father:int
} }
val blf: int graph -> id -> id -> t_cost array val blf: float graph -> id -> id -> t_cost array
val get_path: int graph -> id -> id -> path option val get_path: float graph -> id -> id -> path option

@ -2,8 +2,8 @@ open Graph
open Tool open Tool
open BLF open BLF
let g_to_string gr = gmap gr string_of_int let g_to_string gr = gmap gr string_of_float
let g_to_int gr = gmap gr int_of_string let g_to_float gr = gmap gr float_of_string
(* Create a list of pairs (origin,end) from a list of nodes *) (* Create a list of pairs (origin,end) from a list of nodes *)
@ -15,8 +15,8 @@ let rec create_arcs_from_nodes = function
(* Return the minimum value of a path's edge*) (* Return the minimum value of a path's edge*)
let get_min_label_from_path (graph : int graph) (path : (id * id) list) = let get_min_label_from_path (graph : float graph) (path : (id * id) list) =
let min = Some 999 in let min = Some 999.0 in
let min = List.fold_left let min = List.fold_left
( (
fun acu (id1, id2) -> fun acu (id1, id2) ->
@ -24,12 +24,12 @@ let get_min_label_from_path (graph : int graph) (path : (id * id) list) =
if label < acu then label else acu if label < acu then label else acu
) min path in ) min path in
match min with match min with
|None -> 999 |None -> 999.0
|Some x -> x |Some x -> x
(* Add a value to every egde of a path *) (* Add a value to every egde of a path *)
let add_value_to_arcs (graph : int graph) (path : (id * id) list) (value : int) = let add_value_to_arcs (graph : float graph) (path : (id * id) list) (value : float) =
List.fold_left List.fold_left
( (
fun acu (id1, id2) -> fun acu (id1, id2) ->
@ -45,27 +45,27 @@ let rev_arcs (path : (id * id) list) =
(* Removes the edges whose label = 0 *) (* Removes the edges whose label = 0 *)
let remove_zeroes (graph : int graph) = let remove_zeroes (graph : float graph) =
let initGraph = clone_nodes graph in let initGraph = clone_nodes graph in
e_fold graph e_fold graph
( (
fun acu id1 id2 x -> fun acu id1 id2 x ->
if x = 0 then acu else new_arc acu id1 id2 x if x = 0.0 then acu else new_arc acu id1 id2 x
) initGraph ) initGraph
(* Remove bi-directional edges between 2 nodes*) (* Remove bi-directional edges between 2 nodes*)
let only_one_edge (graph : int graph) = let only_one_edge (graph : float graph) =
let graphWithZeroes = e_fold graph let graphWithZeroes = e_fold graph
( (
fun acu id1 id2 x -> fun acu id1 id2 x ->
let path = [(id1,id2);(id2,id1)] in let path = [(id1,id2);(id2,id1)] in
let label_rev = (match find_arc graph id2 id1 with let label_rev = (match find_arc graph id2 id1 with
|None -> 0 |None -> 0.0
|Some x -> x) in |Some x -> x) in
let mini = min x label_rev in let mini = min x label_rev in
let gr = add_value_to_arcs graph path (-mini) in let gr = add_value_to_arcs graph path (Float.neg mini) in
if x = 0 || mini = 0 then acu else gr if x = 0.0 || mini = 0.0 then acu else gr
) )
graph in graph in
let graphWithoutZeroes = remove_zeroes graphWithZeroes in let graphWithoutZeroes = remove_zeroes graphWithZeroes in
@ -75,7 +75,7 @@ let only_one_edge (graph : int graph) =
(* Get the final graph after the FFalgorithm (* Get the final graph after the FFalgorithm
The label of every arc becomes "x/max_capacity" where x The label of every arc becomes "x/max_capacity" where x
is the value of the opposite arc on the residual graph*) is the value of the opposite arc on the residual graph*)
let get_final_graph (initGraph : int graph) (residualGraph : int graph) = let get_final_graph (initGraph : float graph) (residualGraph : float graph) =
(* First get the initial and residual graph as string graphs *) (* First get the initial and residual graph as string graphs *)
let initGraphString = g_to_string initGraph in let initGraphString = g_to_string initGraph in
@ -85,7 +85,7 @@ let get_final_graph (initGraph : int graph) (residualGraph : int graph) =
(* For every arc in the initial graph, we get its label (aka max_capacity) (* For every arc in the initial graph, we get its label (aka max_capacity)
then, we get the label of the opposite arc in the residual graph. then, we get the label of the opposite arc in the residual graph.
If it exists then the arc of the final graph gets the label "x/max_capacity", If it exists then the arc of the final graph gets the label "x/max_capacity",
"0/max_capacity" otherwise*) "0.0/max_capacity" otherwise*)
e_fold initGraph e_fold initGraph
( (
fun acu id1 id2 x -> fun acu id1 id2 x ->
@ -99,8 +99,8 @@ let get_final_graph (initGraph : int graph) (residualGraph : int graph) =
) )
finalGraph finalGraph
let ford_fulk_algorithm (graph : int graph) (origin : id) (sink : id) = let ford_fulk_algorithm (graph : float graph) (origin : id) (sink : id) =
let flow = 0 in let flow = 0.0 in
let graph = only_one_edge graph in let graph = only_one_edge graph in
let initGraph = graph in let initGraph = graph in
@ -119,7 +119,7 @@ let ford_fulk_algorithm (graph : int graph) (origin : id) (sink : id) =
let min = get_min_label_from_path graph arcs in let min = get_min_label_from_path graph arcs in
(* Substract the min to every arc of the path *) (* Substract the min to every arc of the path *)
let graph = add_value_to_arcs graph arcs (-min) in let graph = add_value_to_arcs graph arcs (Float.neg min) in
(* Get the reverse path *) (* Get the reverse path *)
@ -129,7 +129,7 @@ let ford_fulk_algorithm (graph : int graph) (origin : id) (sink : id) =
let graph = add_value_to_arcs graph reverse min in let graph = add_value_to_arcs graph reverse min in
(* Add the min to the flow *) (* Add the min to the flow *)
let flow = flow + min in let flow = Float.add flow min in
boucle graph origin sink flow) in boucle graph origin sink flow) in
let (maxFlow, residualGraph) = boucle graph origin sink flow in let (maxFlow, residualGraph) = boucle graph origin sink flow in
let finalGraph = get_final_graph initGraph residualGraph in let finalGraph = get_final_graph initGraph residualGraph in

@ -3,18 +3,18 @@ open Tool
open BLF open BLF
val g_to_int: string graph -> int graph val g_to_float: string graph -> float graph
val ford_fulk_algorithm : int graph -> id -> id -> (int * string graph) val ford_fulk_algorithm : float graph -> id -> id -> (float * string graph)
(* val g_to_string: int graph -> string graph *) (* val g_to_string: float graph -> string graph *)
(* val only_one_edge: int graph -> int graph *) (* val only_one_edge: float graph -> float graph *)
(* for testing purpose *) (* for testing purpose *)
(* val rev_arcs: (id * id) list -> (id * id) list (* val rev_arcs: (id * id) list -> (id * id) list
val add_value_to_arcs: int graph -> (id * id) list -> int -> int graph val add_value_to_arcs: float graph -> (id * id) list -> float -> float graph
val get_final_graph: int graph -> int graph -> string graph *) val get_final_graph: float graph -> float graph -> string graph *)

@ -31,12 +31,12 @@ let () =
(* Open file *) (* Open file *)
let (graph, l_id) = from_file infile in let (graph, l_id) = from_file infile in
let initGraph = g_to_int graph in let initGraph = g_to_float graph in
(* Rewrite the graph that has been read. *) (* Rewrite the graph that has been read. *)
let (flow,finalGraph) = ford_fulk_algorithm initGraph _source _sink in let (flow,finalGraph) = ford_fulk_algorithm initGraph _source _sink in
let () = printf "max flow = %d\n" flow in let () = printf "max flow = %f\n" flow in
let () = write_file outfile finalGraph l_id in let () = write_file outfile finalGraph l_id in
let () = export outfile finalGraph in let () = export outfile finalGraph in
(* let () = export infile graph in *) (* let () = export infile graph in *)

@ -13,8 +13,8 @@ type path = string
u Macha u Macha
% You can now enter your payements as it follows: p userWhoPaid [forWhichUser1; forWhichUser2 ..] amount % You can now enter your payements as it follows: p userWhoPaid [forWhichUser1; forWhichUser2 ..] amount
p Flo [Gaby; Flo; Macha] 11.0 p Flo Gaby,Flo,Macha 11.0
p Gaby [Flo] 8.5 p Gaby Flo 8.5
*) *)
@ -34,7 +34,7 @@ let write_file path graph l_id=
fprintf ff "%% Here are the reimbursements to be made.\n\n" ; fprintf ff "%% Here are the reimbursements to be made.\n\n" ;
(* Write all arcs *) (* Write all arcs *)
e_iter graph (fun id1 id2 lbl -> fprintf ff "p %d %d %s\n" (get_user id1 l_id) (get_user id2 l_id) lbl) ; e_iter graph (fun id1 id2 lbl -> fprintf ff "p %s %s %s\n" (get_user id1 l_id) (get_user id2 l_id) lbl) ;
fprintf ff "\n%% End of reimbursements\n" ; fprintf ff "\n%% End of reimbursements\n" ;
@ -50,7 +50,7 @@ let read_comment graph line l_id=
failwith "from_file" failwith "from_file"
(* Reads a line with a user. *) (* Reads a line with a user. *)
let read_user id graph line l_id= let read_user id graph l_id line =
try Scanf.sscanf line "u %s" (fun user l_id-> ((init_node graph user id), l_id) ) try Scanf.sscanf line "u %s" (fun user l_id-> ((init_node graph user id), l_id) )
with e -> with e ->
Printf.printf "Cannot read node in line - %s:\n%s\n%!" (Printexc.to_string e) line ; Printf.printf "Cannot read node in line - %s:\n%s\n%!" (Printexc.to_string e) line ;
@ -58,8 +58,8 @@ let read_user id graph line l_id=
(* Reads a line with a payement. *) (* Reads a line with a payement. *)
let read_payement graph line l_id= let read_payement graph line l_id=
try Scanf.sscanf line "p %s %r %f" try Scanf.sscanf line "p %s %s %f"
(fun u l_u label -> ((paiement graph u l_u label), l_id)) (fun u l_u label -> ((paiement graph u (String.split_on_char ',' l_u) label), l_id))
with e -> with e ->
Printf.printf "Cannot read arc in line - %s:\n%s\n%!" (Printexc.to_string e) line ; Printf.printf "Cannot read arc in line - %s:\n%s\n%!" (Printexc.to_string e) line ;
failwith "from_file" failwith "from_file"
@ -83,8 +83,8 @@ let from_file path =
(* The first character of a line determines its content : n or e. *) (* The first character of a line determines its content : n or e. *)
else match line.[0] with else match line.[0] with
| 'u' -> (n+1, read_node n graph line l_id ) | 'u' -> (n+1, (read_user n graph l_id line))
| 'p' -> (n, read_arc graph line l_id) | 'p' -> (n, read_payement graph line l_id)
(* It should be a comment, otherwise we complain. *) (* It should be a comment, otherwise we complain. *)
| _ -> (n, read_comment graph line l_id) | _ -> (n, read_comment graph line l_id)

@ -2,9 +2,9 @@ open Graph
type path = string type path = string
val from_file: path -> (string graph, (string,id) list) val from_file: path -> (string graph * (string * id) list)
val write_file: path -> string graph -> (string,id) list-> unit val write_file: path -> string graph -> (string * id) list-> unit
val export: path -> string graph -> unit val export: path -> string graph -> unit

@ -1,19 +0,0 @@
(* Read a graph from a file,
* Write a graph to a file. *)
open Graph
type path = string
(* Values are read as strings. *)
val from_file: path -> string graph
(* Similarly, we write only a string graph.
* If necessary, use gmap (to be written by you) to prepare the input graph. *)
val write_file: path -> string graph -> unit
val export: path -> string graph -> unit
(* The format of files is compatible with the files generated by:
https://www-m9.ma.tum.de/graph-algorithms/flow-ford-fulkerson/index_en.html
*)

@ -1,4 +1,5 @@
open Graph open Graph
open Tool
(*fonction qui créé le noeud associé à un utilisateur et rentre la correspondance dans la table des id*) (*fonction qui créé le noeud associé à un utilisateur et rentre la correspondance dans la table des id*)
@ -7,20 +8,20 @@ let init_node g user id l_id=
(*fonction qui renvoie l'id d'un utilisateur*) (*fonction qui renvoie l'id d'un utilisateur*)
let get_id utilisateur l_id= match l_id with let rec get_id utilisateur l_id= match l_id with
|[]-> raise Not_found |[]-> raise Not_found
|(a,id1)::b-> if a=utlisateur then id1 else get_id utilisateur b |(a,id1)::b-> if a=utilisateur then id1 else get_id utilisateur b
(*fonction qui renvoie le nom correspondant à un id*) (*fonction qui renvoie le nom correspondant à un id*)
let get_user id1 l_id= match l_id with let rec get_user id1 l_id= match l_id with
|[]-> raise Not_found |[]-> raise Not_found
|(nom,a)::b-> if a=id1 then nom else get_user id1 b |(nom,a)::b-> if a=id1 then nom else get_user id1 b
(*fonction qui rentre les paiements réalisés*) (*fonction qui rentre les paiements réalisés*)
let rec paiement g utilisateur l_utilisateurs montant l_id= match l_utilisateurs with let rec paiement g utilisateur l_utilisateurs montant l_id= match l_utilisateurs with
|[]-> (g, l_id) |[]-> (g, l_id)
|a::b-> if not(a=utlisateur) |a::b-> if not(a=utilisateur)
then paiement (add_arc g (get_id utilisateur l_id) (get_id a l_id) (montant/(List.length l_utilisateurs))) utilisateur b montant l_id then paiement (add_arc g (get_id utilisateur l_id) (get_id a l_id) (Float.div montant (Float.of_int(List.length l_utilisateurs)))) utilisateur b montant l_id
else paiement g utilisateur b montant l_id else paiement g utilisateur b montant l_id

@ -1,9 +1,9 @@
open Graph open Graph
val paiement: int graphe -> string -> string list -> float -> (string,id) list -> (int graphe, (string,id) list) val paiement: float graph -> string -> string list -> float -> (string * id) list -> (float graph * (string * id) list)
val init_node: int graphe -> string ->id -> (string,id) list-> (int graphe, (string,id) list) val init_node: float graph -> string ->id -> (string * id) list-> (float graph * (string * id) list)
val get_id: string -> (string, id) list -> id val get_id: string -> (string * id) list -> id
val get_user: id -> (string, id) list -> string val get_user: id -> (string * id) list -> string

@ -16,4 +16,4 @@ let add_arc g id1 id2 n =
let f = find_arc g id1 id2 in let f = find_arc g id1 id2 in
match f with match f with
|None->new_arc g id1 id2 n |None->new_arc g id1 id2 n
|Some x->new_arc g id1 id2 (n+x) |Some x->new_arc g id1 id2 (Float.add n x)

@ -6,4 +6,4 @@ val clone_nodes: 'a graph -> 'b graph
(* Apply a function f to every label of the graph's arcs *) (* Apply a function f to every label of the graph's arcs *)
val gmap: 'a graph -> ('a -> 'b) -> 'b graph val gmap: 'a graph -> ('a -> 'b) -> 'b graph
val add_arc: int graph -> id -> id -> int -> int graph val add_arc: float graph -> id -> id -> float -> float graph