language-Modula2-0.1: examples/Modula-2_Libraries/C.-Lins_Modula-2_Software_Component_Library/Vol3/GRAPHS/DIGSBUIU.MOD
IMPLEMENTATION MODULE DigSBUIUtil;
(*====================================================================
Version : V2.01 08 December 1989.
Compiler : JPI TopSpeed Modula-2
Code size: 1474 bytes
Component: DigraphSBUI Utilities
INTRODUCTION
This module provides the implementation of utility operations
supporting the digraph SBUI abstract data type.
REVISION HISTORY
v1.00 24 May 1988 C. Lins:
Initial TML Modula-2 implementation
v1.01 26 Jan 1989 C. Lins:
Revised to conform with DigraphSBMI implementation.
v1.03 14 Mar 1989 C. Lins:
Changed name of HasPath to IsReachable.
v2.00 24 Oct 1989 C. Lins
Created generic pc version
v2.01 08 Dec 1989 I.S.C. Houston.
Adapted to JPI Compiler:
Used type transfer functions instead of VAL.
Used shortened library module names for DOS and OS/2.
(C) Copyright 1989 Charles A. Lins
====================================================================*)
FROM DigrSBUI IMPORT
(*--cons*) NullGraph, NullEdge, NullVertex,
(*--type*) Graph, Vertex, Edge, VertexLoopProc,
(*--proc*) FirstVertex, NextVertex, FirstEdge, NextEdge,
InDegree, OutDegree, FinalOf, TravVertices;
FROM TypeManager IMPORT
(*--Proc*) Create, LongCardTypeID;
FROM Items IMPORT
(*--Type*) Item;
IMPORT SetSUUN;
IMPORT QSUUN;
(*
13.5.1 Graph Utility Operations
*)
VAR minimum : CARDINAL; (*-- current minimum degree *)
PROCEDURE FindMinDegree ( theVertex : Vertex (*--in *));
VAR degree : CARDINAL; (*-- degree of the current vertex *)
BEGIN
degree := InDegree(theVertex) + OutDegree(theVertex);
IF (degree < minimum) THEN
minimum := degree;
END (*--if*);
END FindMinDegree;
(*-------------------------*)
PROCEDURE MinDegree ( theGraph : Graph (*-- in *))
: CARDINAL (*-- out *);
BEGIN
IF (theGraph = NullGraph) THEN
RETURN 0;
ELSE
minimum := MAX(CARDINAL);
TravVertices(theGraph, FindMinDegree);
RETURN minimum;
END (*--if*);
END MinDegree;
(*-------------------------*)
VAR maximum : CARDINAL; (*-- current minimum degree *)
PROCEDURE FindMaxDegree ( theVertex : Vertex (*--in *));
VAR degree : CARDINAL; (*-- degree of the current vertex *)
BEGIN
degree := InDegree(theVertex) + OutDegree(theVertex);
IF (degree > maximum) THEN
maximum := degree;
END (*--if*);
END FindMaxDegree;
(*-------------------------*)
PROCEDURE MaxDegree ( theGraph : Graph (*-- in *))
: CARDINAL (*-- out *);
BEGIN
maximum := MIN(CARDINAL);
IF (theGraph # NullGraph) THEN
TravVertices(theGraph, FindMaxDegree);
END (*--if*);
RETURN maximum;
END MaxDegree;
(*-------------------------*)
PROCEDURE IsLoopFree ( theGraph : Graph (*--in *))
: BOOLEAN (*--out *);
VAR theVertex : Vertex;
BEGIN
IF (theGraph # NullGraph) THEN
theVertex := FirstVertex(theGraph);
WHILE (theVertex # NullVertex) DO
IF HasSelfLoops(theVertex) THEN
RETURN FALSE;
END (*--if*);
theVertex := NextVertex(theVertex);
END (*--while*);
END (*--if*);
RETURN TRUE;
END IsLoopFree;
(*-------------------------*)
(*
13.5.2 Vertex Utility Operations
*)
PROCEDURE IsTerminal ( theVertex : Vertex (*-- in *))
: BOOLEAN (*-- out *);
BEGIN
RETURN FirstEdge(theVertex) = NullEdge;
END IsTerminal;
(*-------------------------*)
PROCEDURE IsIsolated ( theVertex : Vertex (*-- in *))
: BOOLEAN (*-- out *);
BEGIN
RETURN (FirstEdge(theVertex) = NullEdge) & (InDegree(theVertex) = 0);
END IsIsolated;
(*-------------------------*)
PROCEDURE HasSelfLoops ( theVertex : Vertex (*-- in *))
: BOOLEAN (*-- out *);
VAR theEdge : Edge; (*-- loop pointer over edges of this vertex *)
BEGIN
theEdge := FirstEdge(theVertex);
WHILE (theEdge # NullEdge) DO
IF (FinalOf(theEdge) = theVertex) THEN
RETURN TRUE;
END (*--if*);
theEdge := NextEdge(theEdge);
END (*--while*);
RETURN FALSE;
END HasSelfLoops;
(*-------------------------*)
PROCEDURE IsReachable ( fromVertex: Vertex (*--in *);
toVertex : Vertex (*--in *))
: BOOLEAN (*--out *);
VAR visited : SetSUUN.Set; (*-- set of vertices already visited *)
pathFound: BOOLEAN; (*-- true when path between vertices is found *)
PROCEDURE Visit (v : Vertex);
VAR e : Edge; (*-- loop index over edges from v *)
VAR w : Vertex; (*-- destination vertex of an edge *)
BEGIN
pathFound := (v = toVertex);
IF ~pathFound THEN
(*-- add v to the set of vertices already visited *)
SetSUUN.Include(Item(v), visited);
e := FirstEdge(v);
WHILE (e # NullEdge) & ~pathFound DO
w := FinalOf(e);
IF ~SetSUUN.IsAMember(Item(w), visited) THEN
Visit(w);
END (*--if*);
e := NextEdge(e);
END (*--while*);
END (*--if*);
END Visit;
BEGIN
visited := SetSUUN.Create(LongCardTypeID());
Visit(fromVertex);
SetSUUN.Destroy(visited);
RETURN pathFound;
END IsReachable;
(*-------------------------*)
(*
11.5.3 Graph Traversal Utilities
*)
PROCEDURE DFS ( theGraph : Graph (*--in *);
process : VertexLoopProc (*--in *));
VAR v : Vertex; (*-- loop index over vertices *)
continue : BOOLEAN; (*-- controls termination of DFS *)
visited : SetSUUN.Set; (*-- set of vertices already visited *)
PROCEDURE Visit (v : Vertex);
VAR e : Edge; (*-- loop index over edges from v *)
VAR w : Vertex; (*-- destination vertex of an edge *)
BEGIN
continue := process(v);
IF continue THEN
(*-- add v to the set of vertices already visited *)
SetSUUN.Include(Item(v), visited);
e := FirstEdge(v);
WHILE (e # NullEdge) & continue DO
w := FinalOf(e);
IF ~SetSUUN.IsAMember(Item(w), visited) THEN
Visit(w);
END (*--if*);
e := NextEdge(e);
END (*--while*);
END (*--if*);
END Visit;
BEGIN
continue := TRUE;
visited := SetSUUN.Create(LongCardTypeID());
v := FirstVertex(theGraph);
LOOP
IF (v = NullVertex) THEN
EXIT (*--loop*);
END (*--if*);
IF ~SetSUUN.IsAMember(Item(v), visited) THEN
Visit(v);
IF ~continue THEN
EXIT (*--loop*);
END (*--if*);
END (*--if*);
v := NextVertex(v);
END (*--loop*);
SetSUUN.Destroy(visited);
END DFS;
(*-------------------------*)
PROCEDURE BFS ( theGraph : Graph (*--in *);
process : VertexLoopProc (*--in *));
VAR u, v, w : Vertex; (*-- loop indexes over vertices *)
e : Edge; (*-- loop index over edges *)
continue : BOOLEAN; (*-- controls termination of DFS *)
visited : SetSUUN.Set; (*-- set of vertices already visited *)
toVisit : QSUUN.Queue; (*-- vertices waiting to be visited *)
BEGIN
continue := TRUE;
visited := SetSUUN.Create(LongCardTypeID());
toVisit := QSUUN.Create();
u := FirstVertex(theGraph);
WHILE continue & (u # NullVertex) DO
IF ~SetSUUN.IsAMember(Item(u), visited) THEN
SetSUUN.Include(Item(u), visited);
QSUUN.Arrive(toVisit, Item(u));
WHILE continue & ~QSUUN.IsEmpty(toVisit) DO
v := Vertex(QSUUN.FrontOf(toVisit));
QSUUN.Depart(toVisit);
continue := process(v);
e := FirstEdge(v);
WHILE continue & (e # NullEdge) DO
w := FinalOf(e);
IF ~SetSUUN.IsAMember(Item(w), visited) THEN
QSUUN.Arrive(toVisit, Item(w));
SetSUUN.Include(Item(w), visited);
END (*--if*);
e := NextEdge(e);
END (*--while*);
END (*--while*);
END (*--if*);
u := NextVertex(u);
END (*--while*);
SetSUUN.Destroy(visited);
QSUUN.Destroy(toVisit);
END BFS;
(*-------------------------*)
END DigSBUIUtil.