1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- G N A T . G R A P H S --
9 -- Copyright (C) 2018-2019, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 pragma Compiler_Unit_Warning;
34 with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables;
35 with GNAT.Lists; use GNAT.Lists;
36 with GNAT.Sets; use GNAT.Sets;
38 package GNAT.Graphs is
44 -- The following type denotes a strongly connected component handle
45 -- (referred to as simply "component") in a graph.
47 type Component_Id is new Natural;
48 No_Component : constant Component_Id;
50 function Hash_Component (Comp : Component_Id) return Bucket_Range_Type;
51 -- Map component Comp into the range of buckets
53 function Present (Comp : Component_Id) return Boolean;
54 -- Determine whether component Comp exists
60 -- The following package offers a directed graph abstraction with the
61 -- following characteristics:
63 -- * Dynamic resizing based on number of vertices and edges
64 -- * Creation of multiple instances, of different sizes
65 -- * Discovery of strongly connected components
66 -- * Iterable attributes
68 -- The following use pattern must be employed when operating this graph:
70 -- Graph : Instance := Create (<some size>, <some size>);
72 -- <various operations>
76 -- The destruction of the graph reclaims all storage occupied by it.
84 type Vertex_Id is private;
85 -- The handle of a vertex
87 No_Vertex : Vertex_Id;
88 -- An indicator for a nonexistent vertex
90 with function Hash_Vertex (V : Vertex_Id) return Bucket_Range_Type;
91 -- Map vertex V into the range of buckets
93 with function Same_Vertex
95 Right : Vertex_Id) return Boolean;
96 -- Compare vertex Left to vertex Right for identity
102 type Edge_Id is private;
103 -- The handle of an edge
106 -- An indicator for a nonexistent edge
108 with function Hash_Edge (E : Edge_Id) return Bucket_Range_Type;
109 -- Map edge E into the range of buckets
111 with function Same_Edge
113 Right : Edge_Id) return Boolean;
114 -- Compare edge Left to edge Right for identity
116 package Directed_Graph is
118 -- The following exceptions are raised when an attempt is made to add
119 -- the same edge or vertex in a graph.
121 Duplicate_Edge : exception;
122 Duplicate_Vertex : exception;
124 -- The following exceptions are raised when an attempt is made to delete
125 -- or reference a nonexistent component, edge, or vertex in a graph.
127 Missing_Component : exception;
128 Missing_Edge : exception;
129 Missing_Vertex : exception;
131 ----------------------
132 -- Graph operations --
133 ----------------------
135 -- The following type denotes a graph handle. Each instance must be
136 -- created using routine Create.
138 type Instance is private;
139 Nil : constant Instance;
145 Destination : Vertex_Id);
146 -- Add edge E to graph G which links vertex source Source and desination
147 -- vertex Destination. The edge is "owned" by vertex Source. This action
148 -- raises the following exceptions:
150 -- * Duplicate_Edge, when the edge is already present in the graph
152 -- * Iterated, when the graph has an outstanding edge iterator
154 -- * Missing_Vertex, when either the source or desination are not
155 -- present in the graph.
160 -- Add vertex V to graph G. This action raises the following exceptions:
162 -- * Duplicate_Vertex, when the vertex is already present in the graph
164 -- * Iterated, when the graph has an outstanding vertex iterator
168 V : Vertex_Id) return Component_Id;
169 -- Obtain the component where vertex V of graph G resides. This action
170 -- raises the following exceptions:
172 -- * Missing_Vertex, when the vertex is not present in the graph
174 function Contains_Component
176 Comp : Component_Id) return Boolean;
177 -- Determine whether graph G contains component Comp
179 function Contains_Edge
181 E : Edge_Id) return Boolean;
182 -- Determine whether graph G contains edge E
184 function Contains_Vertex
186 V : Vertex_Id) return Boolean;
187 -- Determine whether graph G contains vertex V
190 (Initial_Vertices : Positive;
191 Initial_Edges : Positive) return Instance;
192 -- Create a new graph with vertex capacity Initial_Vertices and edge
193 -- capacity Initial_Edges. This routine must be called at the start of
194 -- a graph's lifetime.
196 procedure Delete_Edge
199 -- Delete edge E from graph G. This action raises these exceptions:
201 -- * Iterated, when the graph has an outstanding edge iterator
203 -- * Missing_Edge, when the edge is not present in the graph
205 -- * Missing_Vertex, when the source vertex that "owns" the edge is
206 -- not present in the graph.
208 function Destination_Vertex
210 E : Edge_Id) return Vertex_Id;
211 -- Obtain the destination vertex of edge E of graph G. This action
212 -- raises the following exceptions:
214 -- * Missing_Edge, when the edge is not present in the graph
216 procedure Destroy (G : in out Instance);
217 -- Destroy the contents of graph G, rendering it unusable. This routine
218 -- must be called at the end of a graph's lifetime. This action raises
219 -- the following exceptions:
221 -- * Iterated, if the graph has any outstanding iterator
223 procedure Find_Components (G : Instance);
224 -- Find all components of graph G. This action raises the following
227 -- * Iterated, when the components or vertices of the graph have an
228 -- outstanding iterator.
230 function Is_Empty (G : Instance) return Boolean;
231 -- Determine whether graph G is empty
233 function Number_Of_Components (G : Instance) return Natural;
234 -- Obtain the total number of components of graph G
236 function Number_Of_Edges (G : Instance) return Natural;
237 -- Obtain the total number of edges of graph G
239 function Number_Of_Vertices (G : Instance) return Natural;
240 -- Obtain the total number of vertices of graph G
242 function Present (G : Instance) return Boolean;
243 -- Determine whether graph G exists
245 function Source_Vertex
247 E : Edge_Id) return Vertex_Id;
248 -- Obtain the source vertex that "owns" edge E of graph G. This action
249 -- raises the following exceptions:
251 -- * Missing_Edge, when the edge is not present in the graph
253 -------------------------
254 -- Iterator operations --
255 -------------------------
257 -- The following types represent iterators over various attributes of a
258 -- graph. Each iterator locks all mutation operations of its associated
259 -- attribute, and unlocks them once it is exhausted. The iterators must
260 -- be used with the following pattern:
262 -- Iter : Iterate_XXX (Graph);
263 -- while Has_Next (Iter) loop
264 -- Next (Iter, Element);
267 -- It is possible to advance the iterators by using Next only, however
268 -- this risks raising Iterator_Exhausted.
270 -- The following type represents an iterator over all edges of a graph
272 type All_Edge_Iterator is private;
274 function Has_Next (Iter : All_Edge_Iterator) return Boolean;
275 -- Determine whether iterator Iter has more edges to examine
277 function Iterate_All_Edges (G : Instance) return All_Edge_Iterator;
278 -- Obtain an iterator over all edges of graph G
281 (Iter : in out All_Edge_Iterator;
283 -- Return the current edge referenced by iterator Iter and advance to
284 -- the next available edge. This action raises the following exceptions:
286 -- * Iterator_Exhausted, when the iterator has been exhausted and
287 -- further attempts are made to advance it.
289 -- The following type represents an iterator over all vertices of a
292 type All_Vertex_Iterator is private;
294 function Has_Next (Iter : All_Vertex_Iterator) return Boolean;
295 -- Determine whether iterator Iter has more vertices to examine
297 function Iterate_All_Vertices (G : Instance) return All_Vertex_Iterator;
298 -- Obtain an iterator over all vertices of graph G
301 (Iter : in out All_Vertex_Iterator;
303 -- Return the current vertex referenced by iterator Iter and advance
304 -- to the next available vertex. This action raises the following
307 -- * Iterator_Exhausted, when the iterator has been exhausted and
308 -- further attempts are made to advance it.
310 -- The following type represents an iterator over all components of a
313 type Component_Iterator is private;
315 function Has_Next (Iter : Component_Iterator) return Boolean;
316 -- Determine whether iterator Iter has more components to examine
318 function Iterate_Components (G : Instance) return Component_Iterator;
319 -- Obtain an iterator over all components of graph G
322 (Iter : in out Component_Iterator;
323 Comp : out Component_Id);
324 -- Return the current component referenced by iterator Iter and advance
325 -- to the next component. This action raises the following exceptions:
327 -- * Iterator_Exhausted, when the iterator has been exhausted and
328 -- further attempts are made to advance it.
330 -- The following type represents an iterator over all outgoing edges of
333 type Outgoing_Edge_Iterator is private;
335 function Has_Next (Iter : Outgoing_Edge_Iterator) return Boolean;
336 -- Determine whether iterator Iter has more outgoing edges to examine
338 function Iterate_Outgoing_Edges
340 V : Vertex_Id) return Outgoing_Edge_Iterator;
341 -- Obtain an iterator over all the outgoing edges "owned" by vertex V of
345 (Iter : in out Outgoing_Edge_Iterator;
347 -- Return the current outgoing edge referenced by iterator Iter and
348 -- advance to the next available outgoing edge. This action raises the
349 -- following exceptions:
351 -- * Iterator_Exhausted, when the iterator has been exhausted and
352 -- further attempts are made to advance it.
354 -- The following type prepresents an iterator over all vertices of a
357 type Vertex_Iterator is private;
359 function Has_Next (Iter : Vertex_Iterator) return Boolean;
360 -- Determine whether iterator Iter has more vertices to examine
362 function Iterate_Vertices
364 Comp : Component_Id) return Vertex_Iterator;
365 -- Obtain an iterator over all vertices that comprise component Comp of
369 (Iter : in out Vertex_Iterator;
371 -- Return the current vertex referenced by iterator Iter and advance to
372 -- the next vertex. This action raises the following exceptions:
374 -- * Iterator_Exhausted, when the iterator has been exhausted and
375 -- further attempts are made to advance it.
378 pragma Unreferenced (No_Edge);
384 type Edge_Attributes is record
385 Destination : Vertex_Id := No_Vertex;
386 -- The target of a directed edge
388 Source : Vertex_Id := No_Vertex;
389 -- The origin of a directed edge. The source vertex "owns" the edge.
392 No_Edge_Attributes : constant Edge_Attributes :=
393 (Destination => No_Vertex,
394 Source => No_Vertex);
396 procedure Destroy_Edge_Attributes (Attrs : in out Edge_Attributes);
397 -- Destroy the contents of attributes Attrs
399 package Edge_Map is new Dynamic_HTable
400 (Key_Type => Edge_Id,
401 Value_Type => Edge_Attributes,
402 No_Value => No_Edge_Attributes,
403 Expansion_Threshold => 1.5,
404 Expansion_Factor => 2,
405 Compression_Threshold => 0.3,
406 Compression_Factor => 2,
408 Destroy_Value => Destroy_Edge_Attributes,
415 package Edge_Set is new Membership_Set
416 (Element_Type => Edge_Id,
424 procedure Destroy_Vertex (V : in out Vertex_Id);
425 -- Destroy the contents of a vertex
427 package Vertex_List is new Doubly_Linked_List
428 (Element_Type => Vertex_Id,
430 Destroy_Element => Destroy_Vertex);
436 type Vertex_Attributes is record
437 Component : Component_Id := No_Component;
438 -- The component where a vertex lives
440 Outgoing_Edges : Edge_Set.Instance := Edge_Set.Nil;
441 -- The set of edges that extend out from a vertex
444 No_Vertex_Attributes : constant Vertex_Attributes :=
445 (Component => No_Component,
446 Outgoing_Edges => Edge_Set.Nil);
448 procedure Destroy_Vertex_Attributes (Attrs : in out Vertex_Attributes);
449 -- Destroy the contents of attributes Attrs
451 package Vertex_Map is new Dynamic_HTable
452 (Key_Type => Vertex_Id,
453 Value_Type => Vertex_Attributes,
454 No_Value => No_Vertex_Attributes,
455 Expansion_Threshold => 1.5,
456 Expansion_Factor => 2,
457 Compression_Threshold => 0.3,
458 Compression_Factor => 2,
460 Destroy_Value => Destroy_Vertex_Attributes,
461 Hash => Hash_Vertex);
467 type Component_Attributes is record
468 Vertices : Vertex_List.Instance := Vertex_List.Nil;
471 No_Component_Attributes : constant Component_Attributes :=
472 (Vertices => Vertex_List.Nil);
474 procedure Destroy_Component_Attributes
475 (Attrs : in out Component_Attributes);
476 -- Destroy the contents of attributes Attrs
478 package Component_Map is new Dynamic_HTable
479 (Key_Type => Component_Id,
480 Value_Type => Component_Attributes,
481 No_Value => No_Component_Attributes,
482 Expansion_Threshold => 1.5,
483 Expansion_Factor => 2,
484 Compression_Threshold => 0.3,
485 Compression_Factor => 2,
487 Destroy_Value => Destroy_Component_Attributes,
488 Hash => Hash_Component);
495 All_Edges : Edge_Map.Instance := Edge_Map.Nil;
496 -- The map of edge -> edge attributes for all edges in the graph
498 All_Vertices : Vertex_Map.Instance := Vertex_Map.Nil;
499 -- The map of vertex -> vertex attributes for all vertices in the
502 Components : Component_Map.Instance := Component_Map.Nil;
503 -- The map of component -> component attributes for all components
511 type Instance is access Graph;
512 Nil : constant Instance := null;
518 type All_Edge_Iterator is new Edge_Map.Iterator;
519 type All_Vertex_Iterator is new Vertex_Map.Iterator;
520 type Component_Iterator is new Component_Map.Iterator;
521 type Outgoing_Edge_Iterator is new Edge_Set.Iterator;
522 type Vertex_Iterator is new Vertex_List.Iterator;
526 No_Component : constant Component_Id := Component_Id'First;
527 First_Component : constant Component_Id := No_Component + 1;