1 pnkfelix 1.1.2.1 // AbstractGraph.java, created Tue Jul 25 15:52:49 2000 by pnkfelix
  2 cananian 1.1.2.4 // Copyright (C) 2000 Felix S. Klock II <pnkfelix@mit.edu>
  3 pnkfelix 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 pnkfelix 1.1.2.1 package harpoon.Analysis.GraphColoring;
  5 pnkfelix 1.1.2.1 
  6 cananian 1.4     import net.cscott.jutil.UnmodifiableIterator;
  7 cananian 1.4     import net.cscott.jutil.Default;
  8 cananian 1.4     import net.cscott.jutil.FilterIterator;
  9 pnkfelix 1.1.2.1 
 10 pnkfelix 1.1.2.1 import java.util.Iterator;
 11 pnkfelix 1.1.2.1 import java.util.Collection;
 12 pnkfelix 1.1.2.1 import java.util.AbstractCollection;
 13 pnkfelix 1.1.2.1 import java.util.Set;
 14 pnkfelix 1.1.2.1 import java.util.AbstractSet;
 15 pnkfelix 1.1.2.1 import java.util.HashSet;
 16 pnkfelix 1.1.2.1 import java.util.List;
 17 pnkfelix 1.1.2.1 
 18 pnkfelix 1.1.2.1 /**
 19 pnkfelix 1.1.2.1  * <code>AbstractGraph</code> is a skeletal implementation of the
 20 pnkfelix 1.1.2.1  * <code>Graph</code> interface, to minimize the effort required to
 21 pnkfelix 1.1.2.1  * implement this interface.
 22 pnkfelix 1.1.2.1  * 
 23 pnkfelix 1.1.2.1  * To implement an unmodifiable graph, the programmer needs only to
 24 pnkfelix 1.1.2.1  * extend this class and provide implementations for the
 25 pnkfelix 1.1.2.1  * <code>nodeSet</code> and <code>neighborsOf</code> methods. 
 26 pnkfelix 1.1.2.1  *
 27 pnkfelix 1.1.2.1  * To implement a modifiable graph, the programmer must additionally
 28 pnkfelix 1.1.2.1  * override this class's <code>addNode</code> and <code>addEdge</code>
 29 pnkfelix 1.1.2.1  * methods  (which otherwise throws UnsupportedOperationException).
 30 pnkfelix 1.1.2.1  *
 31 cananian 1.1.2.4  * @author  Felix S. Klock II <pnkfelix@mit.edu>
 32 cananian 1.4      * @version $Id: AbstractGraph.java,v 1.4 2004/02/08 01:52:03 cananian Exp $
 33 pnkfelix 1.1.2.1  */
 34 pnkfelix 1.1.2.1 public abstract class AbstractGraph implements Graph {
 35 pnkfelix 1.1.2.1     
 36 pnkfelix 1.1.2.1     /** Creates a <code>AbstractGraph</code>. */
 37 pnkfelix 1.1.2.1     public AbstractGraph() { }
 38 pnkfelix 1.1.2.1     public abstract Set nodeSet();
 39 pnkfelix 1.1.2.1     public abstract Collection neighborsOf(Object n);
 40 pnkfelix 1.1.2.1 
 41 pnkfelix 1.1.2.1 
 42 pnkfelix 1.1.2.1     public boolean addNode(Object n) { 
 43 pnkfelix 1.1.2.1         throw new UnsupportedOperationException(); 
 44 pnkfelix 1.1.2.1     }
 45 pnkfelix 1.1.2.1     public boolean addEdge(Object m, Object n) { 
 46 pnkfelix 1.1.2.1         throw new UnsupportedOperationException(); 
 47 pnkfelix 1.1.2.1     }
 48 pnkfelix 1.1.2.1     public int getDegree(Object n) { 
 49 pnkfelix 1.1.2.1         return neighborsOf(n).size(); 
 50 pnkfelix 1.1.2.1     }
 51 pnkfelix 1.1.2.1     public Collection edgesFor(final Object n) { 
 52 pnkfelix 1.1.2.1         final FilterIterator.Filter filter = new FilterIterator.Filter(){
 53 pnkfelix 1.1.2.1             public Object map(Object o) { return Default.pair(n, o); }
 54 pnkfelix 1.1.2.1         };
 55 pnkfelix 1.1.2.1         return new AbstractCollection() {
 56 pnkfelix 1.1.2.1             public int size() { return neighborsOf(n).size(); }
 57 pnkfelix 1.1.2.1             public Iterator iterator() {
 58 pnkfelix 1.1.2.1                 return new FilterIterator(neighborsOf(n).iterator(), 
 59 pnkfelix 1.1.2.1                                           filter);
 60 pnkfelix 1.1.2.1             }
 61 pnkfelix 1.1.2.1         };
 62 pnkfelix 1.1.2.1     }
 63 pnkfelix 1.1.2.1 
 64 pnkfelix 1.1.2.1     public Collection edges() {
 65 pnkfelix 1.1.2.1         return new AbstractCollection() {
 66 pnkfelix 1.1.2.1             public int size() {
 67 pnkfelix 1.1.2.1                 int d = 0;
 68 pnkfelix 1.1.2.1                 for(Iterator nodes=nodeSet().iterator();nodes.hasNext();){
 69 pnkfelix 1.1.2.1                     Object n = nodes.next();
 70 pnkfelix 1.1.2.1                     d += neighborsOf(n).size();
 71 pnkfelix 1.1.2.1                 }
 72 pnkfelix 1.1.2.1                 return d/2;
 73 pnkfelix 1.1.2.1             }
 74 pnkfelix 1.1.2.1             public Iterator iterator() {
 75 pnkfelix 1.1.2.1                 final Iterator nodes = nodeSet().iterator();
 76 pnkfelix 1.1.2.1 
 77 pnkfelix 1.1.2.2                 // visited holds all previous values for curr in
 78 pnkfelix 1.1.2.2                 // returned Iterator
 79 pnkfelix 1.1.2.1                 final Set visited = new HashSet();
 80 pnkfelix 1.1.2.1                 
 81 pnkfelix 1.1.2.1                 final Object first;
 82 pnkfelix 1.1.2.1                 if (nodes.hasNext()) {
 83 pnkfelix 1.1.2.1                     first = nodes.next();
 84 pnkfelix 1.1.2.1                 } else {
 85 pnkfelix 1.1.2.1                     first = null;
 86 pnkfelix 1.1.2.1                 }
 87 pnkfelix 1.1.2.1                 final Iterator firstNeighbors;
 88 pnkfelix 1.1.2.1                 if (first != null) {
 89 pnkfelix 1.1.2.1                     firstNeighbors = neighborsOf(first).iterator();
 90 pnkfelix 1.1.2.1                 } else {
 91 pnkfelix 1.1.2.1                     firstNeighbors = Default.nullIterator;
 92 pnkfelix 1.1.2.1                 }
 93 pnkfelix 1.1.2.1 
 94 pnkfelix 1.1.2.1                 return new UnmodifiableIterator(){
 95 pnkfelix 1.1.2.3                     // (nbor != null)  ==> next edge is <curr, nbor>
 96 pnkfelix 1.1.2.1                     Object curr = first, nbor = null;
 97 pnkfelix 1.1.2.1                     
 98 pnkfelix 1.1.2.3                     // (curr == null)  ==> !niter.hasNext()
 99 pnkfelix 1.1.2.1                     // niter.hasNext() ==> niter.next() is next
100 pnkfelix 1.1.2.1                     //                     potential nbor
101 pnkfelix 1.1.2.1                     Iterator niter = firstNeighbors;
102 pnkfelix 1.1.2.1 
103 pnkfelix 1.1.2.3                     // (nbor == null)  ==> push up to next nbor val
104 pnkfelix 1.1.2.1                     public boolean hasNext() {
105 pnkfelix 1.1.2.1                         if(nbor!=null) {
106 pnkfelix 1.1.2.1                             return true;
107 pnkfelix 1.1.2.1                         } else {
108 pnkfelix 1.1.2.1                             // loop until 
109 pnkfelix 1.1.2.1                             // <curr, nbor> is a valid new edge 
110 pnkfelix 1.1.2.1                             // or (!niter.hasNext() /\ !nodes.hasNext())
111 pnkfelix 1.1.2.1                             while(true) {
112 pnkfelix 1.1.2.1                                 while(niter.hasNext()) {
113 pnkfelix 1.1.2.1                                     nbor = niter.next();
114 pnkfelix 1.1.2.1                                     if(!visited.contains(nbor)) 
115 pnkfelix 1.1.2.1                                         return true;
116 pnkfelix 1.1.2.1                                 }
117 pnkfelix 1.1.2.1                                 
118 pnkfelix 1.1.2.1                                 // finished with neighbors for curr 
119 pnkfelix 1.1.2.1                                 nbor = null;
120 pnkfelix 1.1.2.1                                 
121 pnkfelix 1.1.2.1                                 if(nodes.hasNext()) {
122 pnkfelix 1.1.2.1                                     visited.add(curr);
123 pnkfelix 1.1.2.2                                     curr = nodes.next();
124 pnkfelix 1.1.2.1                                     niter = neighborsOf(curr).iterator();
125 pnkfelix 1.1.2.1                                 } else {
126 pnkfelix 1.1.2.1                                     return false;
127 pnkfelix 1.1.2.1                                 }
128 pnkfelix 1.1.2.1                             }
129 pnkfelix 1.1.2.1                         }
130 pnkfelix 1.1.2.1                     }
131 pnkfelix 1.1.2.1                     public Object next() {
132 pnkfelix 1.1.2.1                         if(hasNext()){
133 pnkfelix 1.1.2.1                             List edge = Default.pair(curr, nbor);
134 pnkfelix 1.1.2.1                             nbor = null;
135 pnkfelix 1.1.2.1                             return edge;
136 pnkfelix 1.1.2.1                         } else {
137 pnkfelix 1.1.2.1                             throw new java.util.NoSuchElementException();
138 pnkfelix 1.1.2.1                         }
139 pnkfelix 1.1.2.1                     }
140 pnkfelix 1.1.2.1                 };
141 pnkfelix 1.1.2.1             }
142 pnkfelix 1.1.2.1         };
143 pnkfelix 1.1.2.1     }
144 cananian 1.2     }