capacities + comments

This commit is contained in:
Kevin Cavailles 2020-12-12 18:57:15 +01:00
parent b16e217c5c
commit 5cc770b412
8 changed files with 105 additions and 61 deletions

View file

@ -1,11 +1,25 @@
%% %% Enter the 2 sets one after the other
%% each element separated by a coma
s a,b,c,d,e,f s a,b,c,d,e,f
s j1,j2,j3,j4,j5,j6 s j1,j2,j3,j4,j5,j6
%% preferences' format : p x -> y : pref n°Z %% Enter the capacity for the second set /!\ INT only
%% (Z from 1 to size of the second set (|S2|) ) %% either a single number which will be the capacity of every second set's element
%% or a list of number such as |list| = |S2|
%% ex :
%% s a,b,c,d,e,f,g,h,i,j,k,l
%% s j1,j2,j3
%% c 5,20,10
%% (c 5 <=> c 5,5,5 in this case)
c 1
%% Enter the preferences one by one with the format : elemS1 -> elemS2 : pref n°X /!\ INT only for X
%% with X from 1 to |S2|, 1 being the most desired, |S2| being the least desired
%% (You can actually put any number, the rule is that for X and Y, X < Y,
%% the element corresponding to X is more preferred than the one corresponding to Y)
p a -> j2 : pref n°1 p a -> j2 : pref n°1
p a -> j3 : pref n°2 p a -> j3 : pref n°2

View file

@ -93,10 +93,10 @@ let get_final_graph (initGraph : (int * int) graph) (residualGraph : (int * int)
let busacker_gowen_algorithm (graph : (int * int) graph) (origin : id) (sink : id) = let busacker_gowen_algorithm (graph : (int * int) graph) (origin : id) (sink : id) =
let flow = 0 in let flow = 0 in
let totalCost = 0 in let totalCost = 0 in
let initGraph = graph in let initGraph = graph in
let rec boucle graph origin sink flow totalCost = let rec boucle graph origin sink flow totalCost =
let path = get_path graph origin sink in let path = get_path graph origin sink in
match path with match path with
|None -> (flow, totalCost, graph) |None -> (flow, totalCost, graph)

View file

@ -6,20 +6,35 @@ open Str
type path = string type path = string
(* Format of text files: (* Format of text files:
% %% Enter the 2 sets one after the other
%% each element separated by a coma
%
s a,b,c,d,e,f s a,b,c,d,e,f
s j1,j2,j3,j4,j5,j6 s j1,j2,j3,j4,j5,j6
% %% Enter the capacity for the second set /!\ INT only
%% either a single number which will be the capacity of every second set's element
%% or a list of number such as |list| = |S2|
%% ex :
%% s a,b,c,d,e,f,g,h,i,j,k,l
%% s j1,j2,j3
%% c 5,20,10
%% (c 5 <=> c 5,5,5 in this case)
c 1
%% Enter the preferences one by one with the format : elemS1 -> elemS2 : pref n°X /!\ INT only for X
%% with X from 1 to |S2|, 1 being the most desired, |S2| being the least desired
%% (You can actually put any number, the rule is that for X and Y, X < Y,
%% the element corresponding to X is more preferred than the one corresponding to Y)
p a -> j2 : pref n°1 p a -> j2 : pref n°1
p a -> j3 : pref n°1 p a -> j3 : pref n°2
p c -> j1 : pref n°1 p c -> j1 : pref n°1
p c -> j4 : pref n°1 p c -> j4 : pref n°2
p d -> j3 : pref n°1 p d -> j3 : pref n°1
p e -> j3 : pref n°1 p e -> j3 : pref n°1
p e -> j4 : pref n°1 p e -> j4 : pref n°2
p f -> j6 : pref n°1 p f -> j6 : pref n°1
*) *)
@ -45,20 +60,27 @@ let read_comment graph line =
Printf.printf "Unknown line:\n%s\n%!" line ; Printf.printf "Unknown line:\n%s\n%!" line ;
failwith "from_file" failwith "from_file"
(* Reads a line with a user. *) (* Reads a line with a set of nodes. *)
let read_set graph id lId setNumber line = let read_set graph id lId setNumber line =
(* let regexSplit = Str.regexp "(\\[|,|\\])" in *)
try Scanf.sscanf line "s %s" (fun set -> set_lNodes graph (String.split_on_char ',' set) id lId setNumber ) try Scanf.sscanf line "s %s" (fun set -> set_lNodes graph (String.split_on_char ',' set) id lId setNumber )
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 set in line - %s:\n%s\n%!" (Printexc.to_string e) line ;
failwith "from_file" failwith "from_file"
(* Reads a line with a payement. *) (* Reads a line with a preference. *)
let read_preference graph lId line = let read_preference graph lId line =
try Scanf.sscanf line "p %s -> %s : pref n°%s" try Scanf.sscanf line "p %s -> %s : pref n°%s"
(fun nodeSet1 nodeSet2 weight -> set_preference graph nodeSet1 nodeSet2 weight lId) (fun nodeSet1 nodeSet2 weight -> set_preference graph nodeSet1 nodeSet2 weight lId)
with e -> with e ->
Printf.printf "Cannot read arc in line - %s:\n%s\n%!" (Printexc.to_string e) line ; Printf.printf "Cannot read preference in line - %s:\n%s\n%!" (Printexc.to_string e) line ;
failwith "from_file"
(* Reads a line with the capacity for the second set. *)
let read_capacity line =
try Scanf.sscanf line "c %s"
(fun capacity -> (String.split_on_char ',' capacity))
with e ->
Printf.printf "Cannot read capacity in line - %s:\n%s\n%!" (Printexc.to_string e) line ;
failwith "from_file" failwith "from_file"
@ -69,34 +91,34 @@ let from_file path =
(* Read all lines until end of file. (* Read all lines until end of file.
* n is the current node counter. *) * n is the current node counter. *)
let rec loop n graph lId setNumber= let rec loop n graph lId setNumber capacitySet2=
try try
let line = input_line infile in let line = input_line infile in
(* Remove leading and trailing spaces. *) (* Remove leading and trailing spaces. *)
let line = String.trim line in let line = String.trim line in
let ((n2, graph2, l2) , setNumber2) = let ((n2, graph2, l2) , setNumber2, capacitySet22) =
(* Ignore empty lines *) (* Ignore empty lines *)
if line = "" then ((n, graph, lId), setNumber) if line = "" then ((n, graph, lId), setNumber, capacitySet2 )
(* The first character of a line determines its content : u or p. *) (* The first character of a line determines its content : u or p. *)
else match line.[0] with else match line.[0] with
| 's' -> (read_set graph n lId setNumber line, setNumber+1) | 's' -> (read_set graph n lId setNumber line, setNumber+1, capacitySet2)
| 'p' -> ((n, read_preference graph lId line, lId), 0) | 'p' -> ((n, read_preference graph lId line, lId), 0, capacitySet2)
| 'c' -> ((n, graph, lId), 0, read_capacity line)
(* It should be a comment, otherwise we complain. *) (* It should be a comment, otherwise we complain. *)
| _ -> ((n, read_comment graph line, lId), 1) | _ -> ((n, read_comment graph line, lId), 1, capacitySet2)
in in
loop n2 graph2 l2 setNumber2 loop n2 graph2 l2 setNumber2 capacitySet22
with End_of_file -> (graph, lId) (* Done *) with End_of_file -> (graph, lId, capacitySet2) (* Done *)
in in
let (graph, lId) = loop 1 empty_graph [] 1 in let (graph, lId, capacitySet2) = loop 1 empty_graph [] 1 [] in
(* Users with negative balance linked to the origin (* Users with negative balance linked to the origin
Users with positive balance linked to sink *) Users with positive balance linked to sink *)
let graph = create_source_sink_and_link graph lId in let graph = create_source_sink_and_link graph lId capacitySet2 in
(* Link users between themselves with *) (* Link users between themselves with *)
(*let graph = link_users graph lId in *) (*let graph = link_users graph lId in *)
close_in infile ; close_in infile ;

View file

@ -31,6 +31,7 @@ let set_preference graph (nodeNameSet1 : string) (nodeNameSet2 : string) (weight
new_arc graph idS1 idS2 (weight, "1") new_arc graph idS1 idS2 (weight, "1")
(* Link the source to every node with "setNumber"=1 with cost=capacity=1 *)
let link_node_to_set graph lId nodeId = let link_node_to_set graph lId nodeId =
List.fold_left ( List.fold_left (
fun acu (_,id,setNumber) -> fun acu (_,id,setNumber) ->
@ -40,21 +41,38 @@ let link_node_to_set graph lId nodeId =
) graph lId ) graph lId
let link_set_to_node graph lId nodeId = (* Link the every node with "setNumber"=2 to the sink with cost=1 and capacity=capacitySet2
List.fold_left ( Corresponds to the case where every node should have the same capacity*)
fun acu (_,id,setNumber) -> let rec link_set_to_node_single graph lId nodeId capacitySet2 =
if setNumber = 2 List.fold_left (
then new_arc acu id nodeId ("1", "1") fun acu (_,id,setNumber) ->
else acu if setNumber = 2
) graph lId then new_arc acu id nodeId ("1",List.hd capacitySet2)
else acu
) graph lId
(* Link the every node with "setNumber"=2 to the sink with cost=1 and different capacities
Corresponds to the case where every node should have a different capacity*)
let rec link_set_to_node_multiple graph lId nodeId capacitySet2 = match lId with
|[] -> graph
|(_,id,setNumber) :: rest1 -> if setNumber = 2 then
begin
match capacitySet2 with
|[]-> graph
|e :: rest2 -> link_set_to_node_multiple (new_arc graph id nodeId ("1",e)) rest1 nodeId rest2
end
else link_set_to_node_multiple graph rest1 nodeId capacitySet2
let create_source_sink_and_link graph lId = let create_source_sink_and_link graph lId capacitySet2 =
let graph = new_node graph 0 in let graph = new_node graph 0 in
let sinkId = (get_max_id graph)+1 in let sinkId = (get_max_id graph)+1 in
let graph = new_node graph sinkId in let graph = new_node graph sinkId in
let graph = link_node_to_set graph lId 0 in let graph = link_node_to_set graph lId 0 in
link_set_to_node graph lId sinkId if List.length capacitySet2 = 1
then link_set_to_node_single graph lId sinkId capacitySet2
else link_set_to_node_multiple graph lId sinkId capacitySet2
let remove_source_sink_zeroes graph = let remove_source_sink_zeroes graph =
let max_id = (get_max_id graph) in let max_id = (get_max_id graph) in

View file

@ -19,10 +19,10 @@ val set_lNodes : (string * string ) graph -> string list -> id -> (string * id *
(* Creates an arc between two nodes with a certain weight (cost) and a capacity of 1 (weigth, 1) in a (string * string) graph *) (* Creates an arc between two nodes with a certain weight (cost) and a capacity of 1 (weigth, 1) in a (string * string) graph *)
val set_preference : (string * string ) graph -> string -> string -> string -> (string * id * int) list -> (string * string ) graph val set_preference : (string * string ) graph -> string -> string -> string -> (string * id * int) list -> (string * string ) graph
(* Creates a source with id=0 and a sink with id=n+1, n number of nodes in the graph. (* Creates a source with id=0 and a sink with id=n+1, with n the number of nodes in the graph.
Then creates an arc between the source and every node with setNumber=1 Then creates an arc between the source and every node with setNumber=1
and an arc between the sink and every node with setNumber=2*) and an arc between the sink and every node with setNumber=2 with the specified capacities, either a single number or a set of capacity*)
val create_source_sink_and_link : (string * string ) graph -> (string * id * int) list -> (string * string ) graph val create_source_sink_and_link : (string * string ) graph -> (string * id * int) list -> string list -> (string * string ) graph
(* Create a new graph without : the source and its arcs, the sink and its arcs, every arc whose flow=0 *) (* Create a new graph without : the source and its arcs, the sink and its arcs, every arc whose flow=0 *)
val remove_source_sink_zeroes : (string * string) graph -> (string * string) graph val remove_source_sink_zeroes : (string * string) graph -> (string * string) graph

View file

@ -2,7 +2,6 @@ open BPgfile
open Tool open Tool
open BGAlgorithm open BGAlgorithm
open BLF open BLF
open Format
open Sys open Sys
open Printf open Printf
open Bp open Bp
@ -23,15 +22,11 @@ let () =
(* Arguments are : infile(1) source-id(2)*) (* Arguments are : infile(1) source-id(2)*)
let infile = Sys.argv.(1) let infile = Sys.argv.(1)
and outfile = Sys.argv.(2) and outfile = Sys.argv.(2)
in in
let () = printf "debug args\n" in
(* These command-line arguments are not used for the moment. *) (* These command-line arguments are not used for the moment. *)
(* Open file *) (* Open file *)

View file

@ -1,11 +1,8 @@
open Gfile open Gfile
open Tool open Tool
open BGAlgorithm open BGAlgorithm
open BLF
open Format
open Sys open Sys
open Printf open Printf
open Bp
let () = let () =
@ -14,13 +11,14 @@ let () =
ex : ./ftest_basic.native graphs/graph1 graphs/graph3 0 5 *) ex : ./ftest_basic.native graphs/graph1 graphs/graph3 0 5 *)
(* Check the number of command-line arguments *) (* Check the number of command-line arguments *)
if Array.length Sys.argv <> 5 then if Array.length Sys.argv <> 5 then
begin begin
Printf.printf "\nUsage: %s infile source sink outfile\n\n%!" Sys.argv.(0) ; Printf.printf "\nUsage: %s infile source sink outfile\n\n%!" Sys.argv.(0) ;
exit 0 exit 0
end ; end ;
(* Arguments are : infile(1) outfile(2) source-id(3) sink-id(4) *) (* Arguments are : infile(1) outfile(2) source-id(3) sink-id(4) *)
@ -34,8 +32,6 @@ let () =
in in
let () = printf "debug args\n" in
(* These command-line arguments are not used for the moment. *) (* These command-line arguments are not used for the moment. *)
(* Open file *) (* Open file *)
@ -47,15 +43,12 @@ let () =
(* Rewrite the graph that has been read. *) (* Rewrite the graph that has been read. *)
let (flow, cout, finalGraph) = busacker_gowen_algorithm initGraph _source _sink in let (flow, cout, finalGraph) = busacker_gowen_algorithm initGraph _source _sink in
(*let finalGraph = remove_ss_zeroes finalGraph in*)
let () = printf "max flow = %d, cout = %d\n" flow cout in let () = printf "max flow = %d, cout = %d\n" flow cout in
let () = write_file outfile finalGraph in let () = write_file outfile finalGraph in
let () = export outfile finalGraph in let () = export outfile finalGraph in
(* let () = export infile graph in *)
(*Uncomment the following line if you have graphviz installed *) (*Uncomment the following line if you have graphviz installed *)
let retour = command ("dot -Tsvg "^outfile^".dot > "^outfile^".svg") in (*let retour = command ("dot -Tsvg "^outfile^".dot > "^outfile^".svg") in*)
() ()

View file

@ -4,17 +4,19 @@ open Printf
type path = string type path = string
(* Format of text files: (* Format of text files:
% This is a comment %% This is a comment
% A node with its coordinates (which are not used). %% A node with its coordinates (which are not used).
n 88.8 209.7 n 88.8 209.7
n 408.9 183.0 n 408.9 183.0
% The first node has id 0, the next is 1, and so on. %% The first node has id 0, the next is 1, and so on.
% Edges: e source dest label %% Enter the edges from one node to another one by one
e 3 1 11 %% format to test basic program :
e 0 2 8 %% e id1 id2 cost capacity
e 3 1 5 20
e 0 2 8 10
*) *)