<?xml version="1.0"?>

<st-source>
<time-stamp>From VisualWorks® NonCommercial, 7.4.1 of May 30, 2006 on January 31, 2007 at 4:34:29 am</time-stamp>
<!-- Package SmallGraph* -->


<name-space>
<name>Graph</name>
<environment>Smalltalk</environment>
<private>false</private>
<imports>
			private Smalltalk.*
			</imports>
<category>SmallGraph</category>
<attributes>
<package>SmallGraph</package>
</attributes>
</name-space>

<class>
<name>Stack</name>
<environment>Graph</environment>
<super>Core.Object</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>stack </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>SmallGraph</category>
<attributes>
<package>SmallGraph</package>
</attributes>
</class>

<comment>
<class-id>Graph.Stack</class-id>
<body>Standard simple stack data structure.

Basic use:
|a|
a:= Stack new.
a push: 'a'.
a push:'b'.
a pop. (return b)
a top (return a)


Instance Variables:
	stack	&lt;OrderedCollection&gt;	 simulates the stack

</body>
</comment>

<class>
<name>Node</name>
<environment>Graph</environment>
<super>Core.Object</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>name id visited </inst-vars>
<class-inst-vars>NextId </class-inst-vars>
<imports></imports>
<category>SmallGraph</category>
<attributes>
<package>SmallGraph</package>
</attributes>
</class>

<comment>
<class-id>Graph.Node</class-id>
<body>Represents a single Node 

Instance Variables:
	id	      &lt;int&gt;	      unique node id number
	visited	&lt;Boolean&gt;	flag used for various algorithms
      name    &lt;string&gt;      name of the node. 

</body>
</comment>

<class>
<name>DFSAlgorithm</name>
<environment>Graph</environment>
<super>Core.Object</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>result startNode matrix </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>SmallGraph</category>
<attributes>
<package>SmallGraph</package>
</attributes>
</class>

<comment>
<class-id>Graph.DFSAlgorithm</class-id>
<body>Implements a simple DFS Traversal of a graph.

Instance Variables:
	matrix	&lt;AdjacencyMatrix&gt;	        the adjacency matrix for the algorithm
	result	&lt;(Collection of: Object)&gt;	  the collection that holds the results of the algorithm 
	startNode	&lt;Node&gt;	                    description of startNode

</body>
</comment>

<class>
<name>AdjacencyMatrix</name>
<environment>Graph</environment>
<super>Core.Object</super>
<private>false</private>
<indexed-type>none</indexed-type>
<inst-vars>rows directed nodes </inst-vars>
<class-inst-vars></class-inst-vars>
<imports></imports>
<category>SmallGraph</category>
<attributes>
<package>SmallGraph</package>
</attributes>
</class>

<comment>
<class-id>Graph.AdjacencyMatrix</class-id>
<body>Represents a basic graph adjacency matrix.

Instance Variables:
	directed	&lt;Boolean&gt;	flag to indicate whether graph is directed.  true = directed.
	nodes	&lt;Dictionary&gt;	a dictionary of nodes keyed by id.
	rows	&lt;(Collection of: (Collection of: int))&gt;	the rows of the matrix

</body>
</comment>






<methods>
<class-id>Graph.Node class</class-id> <category>instance creation</category>

<body package="SmallGraph" selector="nextID:">nextID: aNum
    "initialize nextid.  THIS SHOULD ONLY BE CALLED ONCE!! Calling after nodes are created may cause node id's to be duplicated"
    NextId := aNum.</body>

<body package="SmallGraph" selector="named:">named: aName
    "Create a new instance of Node, and set up its values"
     | inst |
     inst := Node new initialize.
     inst name:  aName.
     ^inst</body>

<body package="SmallGraph" selector="nextID">nextID
   "get the next sequential id."
    NextId := NextId + 1.
    ^NextId.</body>

<body package="SmallGraph" selector="intialize">intialize
      super initialize.
	NextId := 0.</body>
</methods>


<methods>
<class-id>Graph.Node</class-id> <category>printing</category>

<body package="SmallGraph" selector="printString">printString
    "convert myself to printing string"
	^'Node: ',self name,' ID: ', self id printString.</body>

<body package="SmallGraph" selector="asString">asString
    "answer with my string representation"
	^'Node: ',self name,' ID: ', self id printString.</body>
</methods>

<methods>
<class-id>Graph.Node</class-id> <category>initialize-release</category>

<body package="SmallGraph" selector="initialize">initialize
	"Initialize a newly created instance. This method must answer the receiver."

	" *** Edit the following to properly initialize instance variables ***"
	name := 'none'.
	id := Node nextID.
      visited := false.
	" *** And replace this comment with additional initialization code *** "
	^self</body>
</methods>

<methods>
<class-id>Graph.Node</class-id> <category>accessing</category>

<body package="SmallGraph" selector="visited:">visited: aBool
     "set my visited status to aBool"
	visited := aBool.</body>

<body package="SmallGraph" selector="id">id
    "answer with my id"
	^id</body>

<body package="SmallGraph" selector="name:">name: aString
     "set my name to a new value"
	name := aString</body>

<body package="SmallGraph" selector="visited">visited
     "answer with my visited status"
	^ visited.</body>

<body package="SmallGraph" selector="name">name
    "answer with my name"
	^name</body>
</methods>


<methods>
<class-id>Graph.AdjacencyMatrix class</class-id> <category>initialize-release</category>

<body package="SmallGraph" selector="directed:">directed: aBoolean
    "Create a new Adjacency Matrix with directed flag set to aBoolean"
    |inst|
    inst := super new initialize.
    inst directed: aBoolean.
    ^inst.</body>
</methods>


<methods>
<class-id>Graph.AdjacencyMatrix</class-id> <category>accessing</category>

<body package="SmallGraph" selector="adjacencyListFor:">adjacencyListFor: aNode
   "search the matrix and return all nodes that are adjacent to this one"
    |row list index|
    row := rows at: aNode id.
    index := 1.
    list := OrderedCollection new.
    row do: [ :i | i  &gt; 0 ifTrue: [ list add: (nodes at: index)]. index := index +1. ].
    ^ list.</body>

<body package="SmallGraph" selector="nodeAt:">nodeAt: anID
   "return the node given its id"
   ^nodes at: anID</body>

<body package="SmallGraph" selector="directed:">directed: aBool
     "set status.  Treat this method as private used only for initialization"
	directed := aBool.</body>

<body package="SmallGraph" selector="expand">expand
   "expand the matrix by 1 row"
   "first we make a new row. then pad the entries with 0 to keep it square"
   | row |
   row := OrderedCollection new.
   rows add: row.
   1 to: rows size do: [ :i | row add: 0 ].
   1 to: (rows size) -1 do: [ :i | (rows at: i) add: 0].</body>

<body package="SmallGraph" selector="addNode:">addNode: aNode
   "add a node to the dictionary keyed by node id"
   nodes at: aNode id put: aNode</body>

<body package="SmallGraph" selector="directed">directed
     "return directed status"
	^directed.</body>

<body package="SmallGraph" selector="resetVisitStatus">resetVisitStatus
     "foreach node in the dictionary, set its status to false"
	nodes keysAndValuesDo: [ :k :v | v visited: false.]</body>
</methods>

<methods>
<class-id>Graph.AdjacencyMatrix</class-id> <category>initialize-release</category>

<body package="SmallGraph" selector="initialize">initialize	
   "initialize this object instance"
   rows := OrderedCollection new.
   nodes := Dictionary new.</body>
</methods>

<methods>
<class-id>Graph.AdjacencyMatrix</class-id> <category>printing</category>

<body package="SmallGraph" selector="print">print
   Transcript show: 'Adjacency Matrix: ' ; cr.
   rows isEmpty ifTrue:[Transcript show: 'Empty';cr.]
                     ifFalse:[
   rows do: [ :row | row do: [ :i | Transcript show: i printString ; show: ' '.] . Transcript cr.].
].</body>
</methods>

<methods>
<class-id>Graph.AdjacencyMatrix</class-id> <category>controlling</category>

<body package="SmallGraph" selector="addEdgeFrom:to:">addEdgeFrom: sourceNode to: destNode
   |row|
   "First check if nodes are in dict, if not add them"
   (nodes includesKey: sourceNode id) ifFalse: [ nodes at: sourceNode id put: sourceNode ].
   (nodes includesKey: destNode id) ifFalse: [ nodes at: destNode id put: destNode ].
   "Check for expansion and expand if necessary"
   [sourceNode id &gt; rows size]
         whileTrue:  [ self expand.].
   [destNode id &gt; rows size]
         whileTrue: [self expand.].
   "grab the correct row for the sourcenode and set edge"
   row := rows at: sourceNode id.
   row at: destNode id put: 1.
   "if not directed, add the opposite direction edge"
   directed ifFalse: [ row := rows at: destNode id. row at: sourceNode id put: 1].</body>

<body package="SmallGraph" selector="hasEdgeFrom:to:">hasEdgeFrom: sourceNode to: destNode
  "Check for an edge."
  | row |
  "First be sure that we have these nodes in the matrix"
  sourceNode id &gt; rows size ifTrue:[ ^false].
  destNode id &gt; rows size ifTrue: [^false].
  "Then just check the value"
  row := rows at: sourceNode id.
  ^ (row at: destNode id) &gt; 0</body>

<body package="SmallGraph" selector="clear">clear
   "clear out the matrix.  Not as efficient as zeroing everything out 
    and just reusing the already expanded matrix.  This way we truly
    have to start over"
   rows := OrderedCollection new.
   nodes := Dictionary new.</body>

<body package="SmallGraph" selector="removeEdgeFrom:to:">removeEdgeFrom: sourceNode to: destNode 
	"First be sure that we have these nodes in the matrix
       then just go to the correct position and set it to 0.
       If not directed, remove the mirror edge also"
	| row |
	sourceNode id &gt; rows size ifTrue: [^false].
	destNode id &gt; rows size ifTrue: [^false].
	row := rows at: sourceNode id.
	row at: destNode id put: 0.
	directed 
		ifFalse: 
			[row := rows at: destNode id.
			row at: sourceNode id put: 0]</body>
</methods>


<methods>
<class-id>Graph.DFSAlgorithm class</class-id> <category>instance creation</category>

<body package="SmallGraph" selector="on:">on: aMatrix
     "Create a new algorithm on aMatrix"
	|inst|
      inst := super new initialize.
      inst matrix: aMatrix.
      ^inst.</body>

<body package="SmallGraph" selector="new">new
	"Answer a newly created and initialized instance."

	^super new initialize</body>
</methods>


<methods>
<class-id>Graph.DFSAlgorithm</class-id> <category>accessing</category>

<body package="SmallGraph" selector="startNode">startNode
    "answer with the node to start from"
	^startNode</body>

<body package="SmallGraph" selector="result">result
     "answer with the result list"
	^result</body>

<body package="SmallGraph" selector="startNode:">startNode: aNode
    "setup the starting node"
	startNode := aNode</body>

<body package="SmallGraph" selector="matrix:">matrix: aMatrix
  "setup the matrix that the algorithm runs on"
   matrix := aMatrix.</body>
</methods>

<methods>
<class-id>Graph.DFSAlgorithm</class-id> <category>printing</category>

<body package="SmallGraph" selector="print">print
    Transcript show: 'DFS Results starting at node ' ; show: startNode ; cr.
    result do: [ :i | Transcript show: i ; show: ' '  ].
    Transcript cr.</body>
</methods>

<methods>
<class-id>Graph.DFSAlgorithm</class-id> <category>initialize-release</category>

<body package="SmallGraph" selector="initialize">initialize
	"Initialize a newly created instance. This method must answer the receiver."

	" *** Edit the following to properly initialize instance variables ***"
	result := nil.
	startNode := nil.
	" *** And replace this comment with additional initialization code *** "
	^self</body>
</methods>

<methods>
<class-id>Graph.DFSAlgorithm</class-id> <category>controlling</category>

<body package="SmallGraph" selector="runFromNode:">runFromNode: aNode
   "Run the standard DFS Algorithm"
    | stack node nodes |
    startNode := aNode.
    matrix resetVisitStatus.
    stack := Stack new.
    stack push: startNode.
    result := OrderedCollection new.
    [ stack notEmpty ] whileTrue: [
         node := stack pop.
         result add: node.
         node visited: true.
         nodes := matrix adjacencyListFor: node.
         nodes do: [ :n | n visited ifFalse: [ (stack contains: n ) ifFalse: [stack push: n]. ]. ].
         ].</body>
</methods>


<methods>
<class-id>Graph.Stack class</class-id> <category>instance creation</category>

<body package="SmallGraph" selector="new">new
	"Answer a newly created and initialized instance."

	^super new initialize</body>
</methods>


<methods>
<class-id>Graph.Stack</class-id> <category>initialize-release</category>

<body package="SmallGraph" selector="initialize">initialize
	"Initialize a newly created instance. This method must answer the receiver."

	" *** Edit the following to properly initialize instance variables ***"
	stack := OrderedCollection new.
	" *** And replace this comment with additional initialization code *** "
	^self</body>
</methods>

<methods>
<class-id>Graph.Stack</class-id> <category>accessing</category>

<body package="SmallGraph" selector="pop">pop
   "standard stack pop"
   | val |
   val := stack last.
   stack removeLast.
   ^val.</body>

<body package="SmallGraph" selector="top">top
   "peek at the top element of the stack, but do not remove it."
    ^ stack last.</body>

<body package="SmallGraph" selector="notEmpty">notEmpty
     "answer true if I have elements, otherwise false"
	^ stack size ~= 0.</body>

<body package="SmallGraph" selector="push:">push: anObject
   "push anObject onto the stack"
   stack add: anObject</body>

<body package="SmallGraph" selector="contains:">contains: anObject
     "check if anObject is on the stack"
	^ stack includes: anObject.</body>
</methods>



</st-source>
