121 lines
3.1 KiB
OCaml
121 lines
3.1 KiB
OCaml
open Graph
|
|
open Printf
|
|
|
|
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.
|
|
|
|
%% 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
|
|
|
|
*)
|
|
|
|
let write_file path graph =
|
|
|
|
(* Open a write-file. *)
|
|
let ff = open_out path in
|
|
|
|
(* Write in this file. *)
|
|
fprintf ff "%% This is a graph.\n\n" ;
|
|
|
|
(* Write all nodes (with fake coordinates) *)
|
|
n_iter_sorted graph (fun id -> fprintf ff "n %.1f 1.0\n" (float_of_int id)) ;
|
|
fprintf ff "\n" ;
|
|
|
|
(* Write all arcs *)
|
|
e_iter graph (fun id1 id2 (a,b) -> fprintf ff "e %d %d %s %s\n" id1 id2 a b) ;
|
|
|
|
fprintf ff "\n%% End of graph\n" ;
|
|
|
|
|
|
|
|
close_out ff ;
|
|
()
|
|
|
|
(* Reads a line with a node. *)
|
|
let read_node id graph line =
|
|
try Scanf.sscanf line "n %f %f" (fun _ _ -> 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_arc graph line =
|
|
try Scanf.sscanf line "e %d %d %s %s"
|
|
(fun id1 id2 cout capa -> new_arc (ensure (ensure graph id1) id2) id1 id2 (cout,capa))
|
|
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 from_file path =
|
|
|
|
let infile = open_in path in
|
|
|
|
(* Read all lines until end of file.
|
|
* n is the current node counter. *)
|
|
let rec loop n graph =
|
|
try
|
|
let line = input_line infile in
|
|
|
|
(* Remove leading and trailing spaces. *)
|
|
let line = String.trim line in
|
|
|
|
let (n2, graph2) =
|
|
(* Ignore empty lines *)
|
|
if line = "" then (n, graph)
|
|
|
|
(* The first character of a line determines its content : n or e. *)
|
|
else match line.[0] with
|
|
| 'n' -> (n+1, read_node n graph line)
|
|
| 'e' -> (n, read_arc graph line)
|
|
|
|
(* It should be a comment, otherwise we complain. *)
|
|
| _ -> (n, read_comment graph line)
|
|
in
|
|
loop n2 graph2
|
|
|
|
with End_of_file -> graph (* Done *)
|
|
in
|
|
|
|
let final_graph = loop 0 empty_graph in
|
|
|
|
close_in infile ;
|
|
final_graph
|
|
|
|
|
|
(* Write the graph in a .dot file*)
|
|
let export path graph =
|
|
(* Open a write-file. *)
|
|
let ff = open_out (path^".dot") in
|
|
|
|
(* Write in this file. *)
|
|
fprintf ff "digraph graphique1 {\n\tsize=\"20\"\n\tnode [shape = circle];\n";
|
|
|
|
(* Write all arcs *)
|
|
e_iter graph (fun id1 id2 (a,b) -> fprintf ff "\t%d -> %d [ label = \"%s, %s\" ];\n" id1 id2 a b) ;
|
|
|
|
fprintf ff "}\n" ;
|
|
|
|
close_out ff ;
|
|
()
|