capacities + comments
This commit is contained in:
parent
b16e217c5c
commit
5cc770b412
8 changed files with 105 additions and 61 deletions
|
@ -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 j1,j2,j3,j4,j5,j6
|
||||
|
||||
%% preferences' format : p x -> y : pref n°Z
|
||||
%% (Z from 1 to size of the second set (|S2|) )
|
||||
%% 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 -> j3 : pref n°2
|
||||
|
|
|
@ -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 flow = 0 in
|
||||
let totalCost = 0 in
|
||||
|
||||
|
||||
let initGraph = graph in
|
||||
let rec boucle graph origin sink flow totalCost =
|
||||
|
||||
|
||||
let path = get_path graph origin sink in
|
||||
match path with
|
||||
|None -> (flow, totalCost, graph)
|
||||
|
|
|
@ -6,20 +6,35 @@ open Str
|
|||
type path = string
|
||||
|
||||
(* 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 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 -> j3 : pref n°1
|
||||
p a -> j3 : pref n°2
|
||||
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 e -> j3 : pref n°1
|
||||
p e -> j4 : pref n°1
|
||||
p e -> j4 : pref n°2
|
||||
p f -> j6 : pref n°1
|
||||
|
||||
*)
|
||||
|
@ -45,20 +60,27 @@ let read_comment graph line =
|
|||
Printf.printf "Unknown line:\n%s\n%!" line ;
|
||||
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 regexSplit = Str.regexp "(\\[|,|\\])" in *)
|
||||
try Scanf.sscanf line "s %s" (fun set -> set_lNodes graph (String.split_on_char ',' set) id lId setNumber )
|
||||
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"
|
||||
|
||||
(* Reads a line with a payement. *)
|
||||
(* Reads a line with a preference. *)
|
||||
let read_preference graph lId line =
|
||||
try Scanf.sscanf line "p %s -> %s : pref n°%s"
|
||||
(fun nodeSet1 nodeSet2 weight -> set_preference graph nodeSet1 nodeSet2 weight lId)
|
||||
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"
|
||||
|
||||
|
||||
|
@ -69,34 +91,34 @@ let from_file path =
|
|||
(* Read all lines until end of file.
|
||||
* n is the current node counter. *)
|
||||
|
||||
let rec loop n graph lId setNumber=
|
||||
let rec loop n graph lId setNumber capacitySet2=
|
||||
try
|
||||
let line = input_line infile in
|
||||
|
||||
(* Remove leading and trailing spaces. *)
|
||||
let line = String.trim line in
|
||||
|
||||
let ((n2, graph2, l2) , setNumber2) =
|
||||
let ((n2, graph2, l2) , setNumber2, capacitySet22) =
|
||||
(* 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. *)
|
||||
else match line.[0] with
|
||||
| 's' -> (read_set graph n lId setNumber line, setNumber+1)
|
||||
| 'p' -> ((n, read_preference graph lId line, lId), 0)
|
||||
| 's' -> (read_set graph n lId setNumber line, setNumber+1, capacitySet2)
|
||||
| '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. *)
|
||||
| _ -> ((n, read_comment graph line, lId), 1)
|
||||
| _ -> ((n, read_comment graph line, lId), 1, capacitySet2)
|
||||
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
|
||||
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 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 *)
|
||||
(*let graph = link_users graph lId in *)
|
||||
close_in infile ;
|
||||
|
|
38
src/bp.ml
38
src/bp.ml
|
@ -31,6 +31,7 @@ let set_preference graph (nodeNameSet1 : string) (nodeNameSet2 : string) (weight
|
|||
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 =
|
||||
List.fold_left (
|
||||
fun acu (_,id,setNumber) ->
|
||||
|
@ -40,21 +41,38 @@ let link_node_to_set graph lId nodeId =
|
|||
) graph lId
|
||||
|
||||
|
||||
let link_set_to_node graph lId nodeId =
|
||||
List.fold_left (
|
||||
fun acu (_,id,setNumber) ->
|
||||
if setNumber = 2
|
||||
then new_arc acu id nodeId ("1", "1")
|
||||
else acu
|
||||
) graph lId
|
||||
(* Link the every node with "setNumber"=2 to the sink with cost=1 and capacity=capacitySet2
|
||||
Corresponds to the case where every node should have the same capacity*)
|
||||
let rec link_set_to_node_single graph lId nodeId capacitySet2 =
|
||||
List.fold_left (
|
||||
fun acu (_,id,setNumber) ->
|
||||
if setNumber = 2
|
||||
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 sinkId = (get_max_id graph)+1 in
|
||||
let graph = new_node graph sinkId in
|
||||
let graph = link_node_to_set graph lId 0 in
|
||||
link_set_to_node graph lId sinkId
|
||||
let graph = link_node_to_set graph lId 0 in
|
||||
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 max_id = (get_max_id graph) in
|
||||
|
|
|
@ -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 *)
|
||||
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
|
||||
and an arc between the sink and every node with setNumber=2*)
|
||||
val create_source_sink_and_link : (string * string ) graph -> (string * id * int) list -> (string * string ) graph
|
||||
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 list -> (string * string ) graph
|
||||
|
||||
(* 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
|
||||
|
|
|
@ -2,7 +2,6 @@ open BPgfile
|
|||
open Tool
|
||||
open BGAlgorithm
|
||||
open BLF
|
||||
open Format
|
||||
open Sys
|
||||
open Printf
|
||||
open Bp
|
||||
|
@ -23,15 +22,11 @@ let () =
|
|||
|
||||
(* Arguments are : infile(1) source-id(2)*)
|
||||
|
||||
|
||||
|
||||
let infile = Sys.argv.(1)
|
||||
and outfile = Sys.argv.(2)
|
||||
|
||||
in
|
||||
|
||||
let () = printf "debug args\n" in
|
||||
|
||||
(* These command-line arguments are not used for the moment. *)
|
||||
|
||||
(* Open file *)
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
open Gfile
|
||||
open Tool
|
||||
open BGAlgorithm
|
||||
open BLF
|
||||
open Format
|
||||
open Sys
|
||||
open Printf
|
||||
open Bp
|
||||
|
||||
let () =
|
||||
|
||||
|
@ -14,13 +11,14 @@ let () =
|
|||
ex : ./ftest_basic.native graphs/graph1 graphs/graph3 0 5 *)
|
||||
|
||||
(* Check the number of command-line arguments *)
|
||||
|
||||
|
||||
if Array.length Sys.argv <> 5 then
|
||||
begin
|
||||
Printf.printf "\nUsage: %s infile source sink outfile\n\n%!" Sys.argv.(0) ;
|
||||
exit 0
|
||||
end ;
|
||||
|
||||
|
||||
(* Arguments are : infile(1) outfile(2) source-id(3) sink-id(4) *)
|
||||
|
||||
|
||||
|
@ -34,8 +32,6 @@ let () =
|
|||
|
||||
in
|
||||
|
||||
let () = printf "debug args\n" in
|
||||
|
||||
(* These command-line arguments are not used for the moment. *)
|
||||
|
||||
(* Open file *)
|
||||
|
@ -47,15 +43,12 @@ let () =
|
|||
(* Rewrite the graph that has been read. *)
|
||||
|
||||
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 () = write_file outfile finalGraph in
|
||||
let () = export outfile finalGraph in
|
||||
(* let () = export infile graph in *)
|
||||
|
||||
|
||||
(*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*)
|
||||
()
|
||||
|
||||
|
|
14
src/gfile.ml
14
src/gfile.ml
|
@ -4,17 +4,19 @@ open Printf
|
|||
type path = string
|
||||
|
||||
(* 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 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
|
||||
e 3 1 11
|
||||
e 0 2 8
|
||||
%% Enter the edges from one node to another one by one
|
||||
%% format to test basic program :
|
||||
%% e id1 id2 cost capacity
|
||||
e 3 1 5 20
|
||||
e 0 2 8 10
|
||||
|
||||
*)
|
||||
|
||||
|
|
Loading…
Reference in a new issue