00001 package gov.nasa.arc.ase.util.graph;
00002
00003 import java.io.*;
00004 import java.util.BitSet;
00005
00006
00007
00008
00009 import java.util.List;
00010 import java.util.Iterator;
00011
00012
00013 public class SCCReduction {
00014 private static boolean anyAcceptingState(List scc, Graph g) {
00015 String type = g.getStringAttribute("type");
00016 String ac = g.getStringAttribute("ac");
00017
00018 if(type.equals("ba")) {
00019 if(ac.equals("nodes")) {
00020 for(Iterator i = scc.iterator(); i.hasNext(); ) {
00021 Node n = (Node)i.next();
00022
00023 if(n.getBooleanAttribute("accepting"))
00024 return true;
00025 }
00026 } else if(ac.equals("edges")) {
00027 for(Iterator i = scc.iterator(); i.hasNext(); ) {
00028 Node n = (Node)i.next();
00029
00030 for(Iterator j = n.getOutgoingEdges().iterator(); j.hasNext(); ) {
00031 Edge e = (Edge)j.next();
00032
00033 if(e.getBooleanAttribute("accepting"))
00034 return true;
00035 }
00036 }
00037 } else
00038 throw new RuntimeException("invalid accepting type: " + ac);
00039 } else if(type.equals("gba")) {
00040 int nsets = g.getIntAttribute("nsets");
00041
00042 if(ac.equals("nodes")) {
00043 for(Iterator i = scc.iterator(); i.hasNext(); ) {
00044 Node n = (Node)i.next();
00045
00046 for(int j = 0; j < nsets; j++)
00047 if(n.getBooleanAttribute("acc"+j))
00048 return true;
00049 }
00050 } else if(ac.equals("edges")) {
00051 for(Iterator i = scc.iterator(); i.hasNext(); ) {
00052 Node n = (Node)i.next();
00053
00054 for(Iterator j = n.getOutgoingEdges().iterator(); j.hasNext(); ) {
00055 Edge e = (Edge)j.next();
00056
00057 for(int k = 0; k < nsets; k++)
00058 if(e.getBooleanAttribute("acc"+j))
00059 return true;
00060 }
00061 }
00062 } else
00063 throw new RuntimeException("invalid accepting type: " + ac);
00064 } else
00065 throw new RuntimeException("invalid graph type: " + type);
00066
00067 return false;
00068 }
00069 private static void clearAccepting(List scc, Graph g) {
00070 String type = g.getStringAttribute("type");
00071 String ac = g.getStringAttribute("ac");
00072
00073 if(type.equals("ba")) {
00074 if(ac.equals("nodes")) {
00075 for(Iterator i = scc.iterator(); i.hasNext(); ) {
00076 Node n = (Node)i.next();
00077
00078 n.setBooleanAttribute("accepting", false);
00079 }
00080 } else if(ac.equals("edges")) {
00081 for(Iterator i = scc.iterator(); i.hasNext(); ) {
00082 Node n = (Node)i.next();
00083
00084 for(Iterator j = n.getOutgoingEdges().iterator(); j.hasNext(); ) {
00085 Edge e = (Edge)j.next();
00086
00087 e.setBooleanAttribute("accepting", false);
00088 }
00089 }
00090 } else
00091 throw new RuntimeException("invalid accepting type: " + ac);
00092 } else if(type.equals("gba")) {
00093 int nsets = g.getIntAttribute("nsets");
00094
00095 if(ac.equals("nodes")) {
00096 for(Iterator i = scc.iterator(); i.hasNext(); ) {
00097 Node n = (Node)i.next();
00098
00099 for(int j = 0; j < nsets; j++)
00100 n.setBooleanAttribute("acc"+j, false);
00101 }
00102 } else if(ac.equals("edges")) {
00103 for(Iterator i = scc.iterator(); i.hasNext(); ) {
00104 Node n = (Node)i.next();
00105
00106 for(Iterator j = n.getOutgoingEdges().iterator(); j.hasNext(); ) {
00107 Edge e = (Edge)j.next();
00108
00109 for(int k = 0; k < nsets; k++)
00110 e.setBooleanAttribute("acc"+k, false);
00111 }
00112 }
00113 } else
00114 throw new RuntimeException("invalid accepting type: " + ac);
00115 } else
00116 throw new RuntimeException("invalid graph type: " + type);
00117 }
00118 private static void clearExternalEdges(List scc, Graph g) {
00119 String type = g.getStringAttribute("type");
00120 String ac = g.getStringAttribute("ac");
00121
00122 if(type.equals("ba")) {
00123 if(ac.equals("nodes")) {
00124 } else if(ac.equals("edges")) {
00125 for(Iterator i = scc.iterator(); i.hasNext(); ) {
00126 Node n = (Node)i.next();
00127
00128 for(Iterator j = n.getOutgoingEdges().iterator(); j.hasNext(); ) {
00129 Edge e = (Edge)j.next();
00130
00131 if(!scc.contains(e.getNext()))
00132 e.setBooleanAttribute("accepting", false);
00133 }
00134 }
00135 } else
00136 throw new RuntimeException("invalid accepting type: " + ac);
00137 } else if(type.equals("gba")) {
00138 int nsets = g.getIntAttribute("nsets");
00139
00140 if(ac.equals("nodes")) {
00141 } else if(ac.equals("edges")) {
00142 for(Iterator i = scc.iterator(); i.hasNext(); ) {
00143 Node n = (Node)i.next();
00144
00145 for(Iterator j = n.getOutgoingEdges().iterator(); j.hasNext(); ) {
00146 Edge e = (Edge)j.next();
00147
00148 if(!scc.contains(e.getNext()))
00149 for(int k = 0; k < nsets; k++)
00150 e.setBooleanAttribute("acc"+k, false);
00151 }
00152 }
00153 } else
00154 throw new RuntimeException("invalid accepting type: " + ac);
00155 } else
00156 throw new RuntimeException("invalid graph type: " + type);
00157 }
00158 private static boolean isAccepting(List scc, Graph g) {
00159 String type = g.getStringAttribute("type");
00160 String ac = g.getStringAttribute("ac");
00161
00162 if(type.equals("ba")) {
00163 if(ac.equals("nodes")) {
00164 for(Iterator i = scc.iterator(); i.hasNext(); )
00165 if(((Node)i.next()).getBooleanAttribute("accepting"))
00166 return true;
00167
00168 return false;
00169 } else if(ac.equals("edges")) {
00170 for(Iterator i = scc.iterator(); i.hasNext(); ) {
00171 Node n = (Node)i.next();
00172
00173 for(Iterator j = n.getOutgoingEdges().iterator(); j.hasNext(); ) {
00174 Edge e = (Edge)j.next();
00175
00176 if(e.getBooleanAttribute("accepting"))
00177 return true;
00178 }
00179 }
00180
00181 return false;
00182 } else
00183 throw new RuntimeException("invalid accepting type: " + ac);
00184 } else if(type.equals("gba")) {
00185 int nsets = g.getIntAttribute("nsets");
00186 BitSet found = new BitSet(nsets);
00187 int nsccs = 0;
00188
00189 if(ac.equals("nodes")) {
00190 for(Iterator i = scc.iterator(); i.hasNext(); ) {
00191 Node n = (Node)i.next();
00192
00193 for(int j = 0; j < nsets; j++) {
00194 if(n.getBooleanAttribute("acc"+j))
00195 if(!found.get(j)) {
00196 found.set(j);
00197 nsccs++;
00198 }
00199 }
00200 }
00201 } else if(ac.equals("edges")) {
00202 for(Iterator i = scc.iterator(); i.hasNext(); ) {
00203 Node n = (Node)i.next();
00204
00205 for(Iterator j = n.getOutgoingEdges().iterator(); j.hasNext(); ) {
00206 Edge e = (Edge)j.next();
00207
00208 for(int k = 0; k < nsets; k++) {
00209 if(e.getBooleanAttribute("acc"+k))
00210 if(!found.get(k)) {
00211 found.set(k);
00212 nsccs++;
00213 }
00214 }
00215 }
00216 }
00217 } else
00218 throw new RuntimeException("invalid accepting type: " + ac);
00219
00220 return nsccs == nsets;
00221 } else
00222 throw new RuntimeException("invalid graph type: " + type);
00223 }
00224 private static boolean isTerminal(List scc) {
00225 for(Iterator i = scc.iterator(); i.hasNext(); ) {
00226 Node n = (Node)i.next();
00227
00228 for(Iterator j = n.getOutgoingEdges().iterator(); j.hasNext(); )
00229 if(!scc.contains(((Edge)j.next()).getNext()))
00230 return false;
00231 }
00232
00233 return true;
00234 }
00235 private static boolean isTransient(List scc) {
00236 if(scc.size() != 1) return false;
00237
00238 Node n = (Node)scc.get(0);
00239 for(Iterator i = n.getOutgoingEdges().iterator();
00240 i.hasNext(); )
00241 if(((Edge)i.next()).getNext() == n) return false;
00242
00243 return true;
00244 }
00245 public static void main(String[] args) {
00246 if(args.length > 1) {
00247 System.out.println("usage:");
00248 System.out.println("\tjava gov.nasa.arc.ase.util.graph.SCCReduction [<filename>]");
00249 return;
00250 }
00251
00252 Graph g = null;
00253
00254 try {
00255 if(args.length == 0)
00256 g = Graph.load();
00257 else
00258 g = Graph.load(args[0]);
00259 } catch(IOException e) {
00260 System.out.println("Can't load the graph.");
00261 return;
00262 }
00263
00264 g = reduce(g);
00265
00266 g.save();
00267 }
00268 public static Graph reduce(Graph g) {
00269 boolean changed;
00270 String type = g.getStringAttribute("type");
00271 String ac = g.getStringAttribute("ac");
00272 boolean acNodes = ac.equals("nodes");
00273
00274 for(Iterator i = SCC.scc(g).iterator(); i.hasNext(); )
00275 clearExternalEdges((List)i.next(), g);
00276
00277 do {
00278 changed = false;
00279
00280 List sccs = SCC.scc(g);
00281
00282 for(Iterator i = sccs.iterator(); i.hasNext(); ) {
00283 List scc = (List)i.next();
00284 boolean accepting = isAccepting(scc, g);
00285
00286
00287 if(!accepting && isTerminal(scc)) {
00288 changed = true;
00289
00290 for(Iterator j = scc.iterator(); j.hasNext(); )
00291 ((Node)j.next()).remove();
00292 } else if(isTransient(scc) || !accepting) {
00293 changed |= anyAcceptingState(scc, g);
00294 clearAccepting(scc, g);
00295 }
00296 }
00297 } while(changed);
00298
00299 return g;
00300 }
00301 }