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 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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 ;
|
||||||
|
|
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")
|
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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 *)
|
||||||
|
|
|
@ -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*)
|
||||||
()
|
()
|
||||||
|
|
||||||
|
|
14
src/gfile.ml
14
src/gfile.ml
|
@ -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
|
||||||
|
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue