104 lines
3.4 KiB
OCaml
104 lines
3.4 KiB
OCaml
open Graph
|
|
open Printf
|
|
open Ffalgo
|
|
|
|
type path = string
|
|
|
|
(* Format of text files:
|
|
% This is a comment
|
|
|
|
% define a factory with its id and production rate
|
|
factory 0 6
|
|
|
|
% define a village with its id and demand
|
|
village 1 10
|
|
|
|
% define a neutral node with its id
|
|
node 2
|
|
|
|
% define a road between 2 nodes using their ids and specifying the max capacity
|
|
road 0 1 2
|
|
|
|
*)
|
|
|
|
(* Source and destination node
|
|
We use negative ids to prevent conflicts
|
|
*)
|
|
let source = (-1)
|
|
let destination = (-2)
|
|
|
|
(* Reads a factory node, adds it to the graph and creates an arc from the source *)
|
|
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"
|
|
|
|
(* Reads a village node, adds it to the graph and creates an arc to the destination *)
|
|
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 neutral node and adds it to the graph *)
|
|
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 road and creates and arc between the nodes of the given id and capacity *)
|
|
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}
|
|
|