be_ocaml/src/circulationfile.ml
Arnaud Vergnet 53246b1598 add comments
2020-11-25 10:01:11 +01:00

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}