Skip to content

Commit ea79178

Browse files
authored
fixes the Node.update for graphs with unlabeled nodes (#1340)
This operation doesn't make sense for graphs with unlabeled nodes and shall return the graph unchanged. A corresponding clarification comment is added. Also, cleans up the documentation a little bit.
1 parent d3ba459 commit ea79178

File tree

2 files changed

+43
-45
lines changed

2 files changed

+43
-45
lines changed

lib/graphlib/graphlib.mli

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ open Regular.Std
44
(**
55
{3 Graph library}
66
7-
{!Graphlib} is a generic library that extends a well known
8-
OCamlGraph library. {!Graphlib} uses its own and richer
7+
{!Graphlib} is a generic library that extends a OCamlGraph
8+
library.{!Graphlib} uses its own and richer
99
{!Graph} interface that is isomorphic to OCamlGraph's [Sigs.P]
1010
signature for persistent graphs. Two functors witnesses
1111
isomorphism of the interfaces:
1212
{!Graphlib.To_ocamlgraph} and {!Graphlib.Of_ocamlgraph}. Thanks
1313
to these functors, any algorithm written for OCamlGraph can be
14-
used on [Graphlibs] graph and vice verse.
14+
used on [Graphlibs] graph and vice versa.
1515
1616
The {!Graph} interface provides a richer interface in a Core
1717
style. Nodes and Edges implements the {!Opaque} interface,
@@ -62,25 +62,37 @@ open Regular.Std
6262
[G.Edge.insert].
6363
*)
6464
module Std : sig
65-
(** {!Graph} nodes. *)
66-
module type Node = sig
67-
(** Semantics of operations is denoted using mathematical model,
68-
described in {!Graph} interface. *)
6965

66+
(** {!Graph} nodes.
67+
Semantics of operations is denoted using mathematical model,
68+
described in {!Graph} interface.
69+
70+
The [node] and [label] types are almost always have identical
71+
representation. For labeled graphs the comparison function for
72+
the [node] is different than the comparison function for the
73+
label, therefore it is a good idea to hide their representation
74+
equality in the interface.
75+
*)
76+
module type Node = sig
7077
type t (** node type is opaque *)
71-
type graph
72-
type label
73-
type edge
78+
type graph (** the type of the node graph *)
79+
type label (** the label type *)
80+
type edge (** the edge type *)
7481

75-
(** [create label] creates a new node, and associates it with a
76-
a given [label]. *)
82+
(** [create x] creates a node labeled with [x].
83+
84+
For unlabeled graphs this is an identity function. *)
7785
val create : label -> t
7886

79-
(** [label n] returns a value associated with a node [n]. *)
87+
(** [label n] the label of the node [n]. *)
8088
val label : t -> label
8189

8290
(** [mem n g] is [true] if [n] is a member of nodes [N] of graph
83-
[g]. *)
91+
[g].
92+
93+
For labeled graphs the membership is tested without taking
94+
into account the label of the node.
95+
*)
8496
val mem : t -> graph -> bool
8597

8698
(** [succs node graph] returns a sequence of successors of a
@@ -114,8 +126,11 @@ module Std : sig
114126
*)
115127
val insert : t -> graph -> graph
116128

117-
(** [update n l g] if node [n] is not in [N(g)] then return [g],
118-
else return graph [g] where node [n] is labeled with [l].
129+
(** [update n l g] for a graph with labeled nodes if node [n] is
130+
not in [N(g)] then returns [g] else returns graph [g] where
131+
node [n] is labeled with [l].
132+
133+
For unlabeled graph returns [g].
119134
120135
Postconditions: {v
121136
- n ∉ N(g) -> n ∉ N(g').
@@ -212,18 +227,15 @@ module Std : sig
212227

213228
(** Graph signature. *)
214229
module type Graph = sig
215-
(** Graph is mathematical data structure that is used to represent
216-
relations between elements of a set. Usually, graph is defined
217-
as an ordered pair of two sets - a set of vertices and a set
218-
of edges that is a 2-subset of the set of nodes,
230+
231+
(** A graph is a set of relations between objects, defined
232+
as a pair of two sets
219233
220234
{v G = (V,E). v}
221235
222-
In Graphlib vertices (called nodes in our parlance) and edges
223-
are labeled. That means that we can associate data with edges
224-
and nodes. Thus graph should be considered as an associative
225-
data structure. And from mathematics perspective graph is
226-
represented as an ordered 6-tuple, consisting of a set of nodes,
236+
where $V$ is a set of vertices and E is a set of vertices,
237+
which is a subset of [V x V], therefore a more precise
238+
definition is a 6-tuple, consisting of a set of nodes,
227239
edges, node labels, edge labels, and two functions that maps
228240
nodes and edges to their corresponding labels:
229241
@@ -250,14 +262,6 @@ module Std : sig
250262
operation in terms of input and output arguments, we project
251263
graphs to its fields with the following notation
252264
[<field>(<graph>)], e.g., [N(g)] is a set of nodes of graph [g].
253-
254-
Only the strongest postcondition is specified, e.g., if it is
255-
specified that [νn = l], then it also means that
256-
257-
[n ∈ N ∧ ∃u((u,v) ∈ E ∨ (v,u) ∈ E) ∧ l ∈ N' ∧ ...]
258-
259-
In other words the structure [G] of the graph G is an invariant
260-
that is always preserved.
261265
*)
262266

263267
(** type of graph *)
@@ -714,12 +718,7 @@ module Std : sig
714718

715719
(** [Labeled(Node)(Node_label)(Edge_label)] creates a graph
716720
structure with both nodes and edges labeled with abitrary
717-
types.
718-
719-
Contrary to [Make] functor, where a node and a node label are
720-
unified, the [Labeled] functor creates a graph data structure,
721-
where they are different. Moreover, the node label is pure
722-
abstract and can be any type, including functional.*)
721+
types. *)
723722
module Labeled(Node : Opaque.S)(NL : T)(EL : T) : Graph
724723
with type node = (Node.t, NL.t) labeled
725724
and type Node.label = (Node.t, NL.t) labeled

lib/graphlib/graphlib_regular.ml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,11 @@ module Make(Node : Opaque.S)(Label : T) = struct
8282
let remove_arrows = update_arrows remove_arrow
8383

8484
let update n l g : graph = Map.find g n |> function
85-
| None -> g
86-
| Some {inc;out} ->
87-
let n = (create l) in
88-
Map.set g ~key:n ~data:{inc;out} |>
89-
insert_arrows Fields_of_node_info.out inc n |>
90-
insert_arrows Fields_of_node_info.inc out n
85+
| Some {inc;out} when Node.equal n l ->
86+
Map.set g ~key:l ~data:{inc;out} |>
87+
insert_arrows Fields_of_node_info.out inc l |>
88+
insert_arrows Fields_of_node_info.inc out l
89+
| _ -> g
9190

9291
let remove n g = match Map.find g n with
9392
| None -> g

0 commit comments

Comments
 (0)