From 236600e387aa95072874c0aa7bbaddaebc1ff5f3 Mon Sep 17 00:00:00 2001 From: Arnaud Vergnet Date: Tue, 24 Nov 2020 15:20:02 +0100 Subject: [PATCH] add circulation problem resolution --- .gitignore | 5 +- Makefile | 29 +++++--- circulation_input_graphs/test1 | 27 ++++++++ graphs/test2 | 15 +++++ outfile.svg | 119 --------------------------------- src/circulationfile.ml | 100 +++++++++++++++++++++++++++ src/circulationfile.mli | 11 +++ src/circulationtest.ml | 38 +++++++++++ 8 files changed, 215 insertions(+), 129 deletions(-) create mode 100644 circulation_input_graphs/test1 create mode 100644 graphs/test2 delete mode 100644 outfile.svg create mode 100644 src/circulationfile.ml create mode 100644 src/circulationfile.mli create mode 100644 src/circulationtest.ml diff --git a/.gitignore b/.gitignore index 22038d5..d800d96 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ _build/ ftest.native +circulationtest.native outfile -*~ \ No newline at end of file +*~ +test/ +run/ \ No newline at end of file diff --git a/Makefile b/Makefile index c1ec0ad..b6e6336 100644 --- a/Makefile +++ b/Makefile @@ -20,33 +20,44 @@ edit: demo: build @echo $(EXECUTING) - ./ftest.native graphs/graph1 1 2 outfile + ./ftest.native graphs/graph1 1 2 test/outfile @echo $(RESULT) - @cat outfile + @cat test/outfile test: build @echo $(EXECUTING) - ./ftest.native graphs/graph1 1 2 outfile + ./ftest.native graphs/graph1 1 2 test/outfile @echo $(BUILDING_SVG) @echo "outfile..." - @dot -Tsvg outfile > outfile.svg + @dot -Tsvg test/outfile > test/outfile.svg @echo "graph_init..." - @dot -Tsvg graph_init > graph_init.svg + @dot -Tsvg test/graph_init > test/graph_init.svg @echo "graph_apply..." - @dot -Tsvg graph_apply > graph_apply.svg + @dot -Tsvg test/graph_apply > test/graph_apply.svg @echo "graph_res..." - @dot -Tsvg graph_res > graph_res.svg + @dot -Tsvg test/graph_res > test/graph_res.svg @echo "" run: build @echo $(EXECUTING) - ./ftest.native graphs/test1 0 3 solution + ./ftest.native graphs/test2 0 5 run/solution @echo $(BUILDING_SVG) @echo "solution..." - @dot -Tsvg solution > solution.svg + @dot -Tsvg run/solution > run/solution.svg @echo "" clean: -rm -rf _build/ -rm ftest.native + +build_circulation: + @echo $(COMPILING) + ocamlbuild circulationtest.native + +run_circulation: build_circulation + @echo $(EXECUTING) + ./circulationtest.native circulation_input_graphs/test1 run/circulation_solution + @echo $(BUILDING_SVG) + @echo "solution..." + @dot -Tsvg run/circulation_solution > run/circulation_solution.svg \ No newline at end of file diff --git a/circulation_input_graphs/test1 b/circulation_input_graphs/test1 new file mode 100644 index 0000000..bf20de4 --- /dev/null +++ b/circulation_input_graphs/test1 @@ -0,0 +1,27 @@ +% Factories +% factory id production_rate +factory 0 6 +factory 1 6 + +% Villages +% village id demand +village 5 10 +village 6 10 +village 7 10 + +% n id +node 2 +node 3 +node 4 + +road 0 1 2 +road 0 2 4 +road 0 3 4 +road 1 2 3 +road 1 4 3 +road 2 3 5 +road 4 3 3 +road 4 5 1 +road 4 6 5 +road 2 6 4 +road 2 7 1 diff --git a/graphs/test2 b/graphs/test2 new file mode 100644 index 0000000..bc622ce --- /dev/null +++ b/graphs/test2 @@ -0,0 +1,15 @@ +% Graph saved at Fri Nov 20 2020 14:11:39 GMT+0100 (Central European Standard Time) +n 130 200 +n 225 300 +n 325 300 +n 175 100 +n 275 100 +n 370 200 +e 0 1 15 +e 1 2 12 +e 2 5 7 +e 0 3 4 +e 3 4 10 +e 4 5 10 +e 2 3 3 +e 4 1 5 \ No newline at end of file diff --git a/outfile.svg b/outfile.svg deleted file mode 100644 index e8ccf8f..0000000 --- a/outfile.svg +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - -finite_state_machine - - - -0 - -0 - - - -1 - -1 - - - -0->1 - - -7 - - - -2 - -2 - - - -0->2 - - -8 - - - -3 - -3 - - - -0->3 - - -10 - - - -4 - -4 - - - -1->4 - - -1 - - - -5 - -5 - - - -1->5 - - -21 - - - -2->4 - - -12 - - - -3->1 - - -11 - - - -3->2 - - -2 - - - -3->4 - - -5 - - - -4->5 - - -14 - - - diff --git a/src/circulationfile.ml b/src/circulationfile.ml new file mode 100644 index 0000000..1eb0fa2 --- /dev/null +++ b/src/circulationfile.ml @@ -0,0 +1,100 @@ +open Graph +open Printf +open Ffalgo + +type path = string + +(* Format of text files: + % This is a comment + + % 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. + + % Edges: e source dest label + e 3 1 11 + e 0 2 8 + +*) + +let source = (-1) +let destination = (-2) + +let read_factory graph line = + try Scanf.sscanf line "factory %d %d" (fun id capacity -> new_arc (new_node graph id) source id capacity) + with e -> + Printf.printf "Cannot read factory in line - %s:\n%s\n%!" (Printexc.to_string e) line ; + failwith "from_file" + +let read_village graph line = + try Scanf.sscanf line "village %d %d" (fun id capacity -> new_arc (new_node graph id) id destination capacity) + with e -> + Printf.printf "Cannot read village in line - %s:\n%s\n%!" (Printexc.to_string e) line ; + failwith "from_file" + +(* Reads a line with a node. *) +let read_node graph line = + try Scanf.sscanf line "node %d" (fun id -> new_node graph id) + with e -> + Printf.printf "Cannot read node in line - %s:\n%s\n%!" (Printexc.to_string e) line ; + failwith "from_file" + +(* Ensure that the given node exists in the graph. If not, create it. + * (Necessary because the website we use to create online graphs does not generate correct files when some nodes have been deleted.) *) +let ensure graph id = if node_exists graph id then graph else new_node graph id + +(* Reads a line with an arc. *) +let read_road graph line = + try Scanf.sscanf line "road %d %d %d" + (fun id1 id2 capacity -> new_arc (ensure (ensure graph id1) id2) id1 id2 capacity) + with e -> + Printf.printf "Cannot read arc in line - %s:\n%s\n%!" (Printexc.to_string e) line ; + failwith "from_file" + +(* Reads a comment or fail. *) +let read_comment graph line = + try Scanf.sscanf line " %%" graph + with _ -> + Printf.printf "Unknown line:\n%s\n%!" line ; + failwith "from_file" + +let circulation_from_file path = + + let infile = open_in path in + (* create source and destination *) + let initial_graph = new_node (new_node empty_graph source) destination in + (* Read all lines until end of file. + * n is the current node counter. *) + let rec loop graph = + try + let line = input_line infile in + + (* Remove leading and trailing spaces. *) + let line = String.trim line in + + let graph2 = + (* Ignore empty lines *) + if line = "" then graph + + (* The first character of a line determines its content : n or e. *) + else match line.[0] with + | 'f' -> read_factory graph line + | 'v' -> read_village graph line + | 'n' -> read_node graph line + | 'r' -> read_road graph line + + (* It should be a comment, otherwise we complain. *) + | _ -> read_comment graph line + in + loop graph2 + + with End_of_file -> graph (* Done *) + in + + let final_graph = loop initial_graph in + + close_in infile ; + {graph = final_graph; origin = source; destination = destination} + diff --git a/src/circulationfile.mli b/src/circulationfile.mli new file mode 100644 index 0000000..a29e3bf --- /dev/null +++ b/src/circulationfile.mli @@ -0,0 +1,11 @@ +(* Read a graph from a file, + * Write a graph to a file. *) + +open Graph +open Ffalgo + +type path = string + +val circulation_from_file: path -> int network + + diff --git a/src/circulationtest.ml b/src/circulationtest.ml new file mode 100644 index 0000000..4afc637 --- /dev/null +++ b/src/circulationtest.ml @@ -0,0 +1,38 @@ +open Circulationfile +open Gfile +open Tools +open Ffalgo + + +let flow_to_string gr = gmap gr (fun fl -> String.concat "/" [(string_of_int fl.current); (string_of_int fl.capacity)]) + +let () = + + (* Check the number of command-line arguments *) + if Array.length Sys.argv <> 3 then + begin + Printf.printf "\nUsage: %s infile outfile\n\n%!" Sys.argv.(0) ; + exit 0 + end ; + + + (* Arguments are : infile(1) source-id(2) sink-id(3) outfile(4) *) + + let infile = Sys.argv.(1) + and outfile = Sys.argv.(2) + in + + (* Open file *) + let initial_network = circulation_from_file infile in + (* Execute FF *) + let solution_network = run_ff initial_network in + (* Print max flow *) + let () = Printf.printf "Max flow: %d\n%!" (get_max_flow solution_network) in + (* Convert to string for export *) + let final_graph = flow_to_string solution_network.graph in + + (* Rewrite the graph that has been read. *) + let () = export outfile final_graph in + + () +