00001 package gov.nasa.arc.ase.util.graph;
00002
00003 import java.io.*;
00004 import java.util.TreeSet;
00005 import java.util.List;
00006 import java.util.LinkedList;
00007 import java.util.Iterator;
00008 import java.util.Set;
00009 import java.util.TreeSet;
00010 import java.util.StringTokenizer;
00011 import java.util.Vector;
00012
00013
00014 public class SFSReduction {
00015 private static TreeSet getPrevN(Node currNode, boolean prevPO[][]) {
00016 List edges = currNode.getOutgoingEdges();
00017 LinkedList neighbors = new LinkedList();
00018 ITypeNeighbor iNeigh;
00019 TreeSet prevN = new TreeSet();
00020
00021
00022 for (Iterator i = edges.iterator(); i.hasNext();) {
00023 Edge currEdge = (Edge)i.next();
00024 iNeigh = new ITypeNeighbor(currEdge.getNext().
00025 getIntAttribute("_prevColor"),
00026 currEdge.getGuard());
00027 neighbors.add(iNeigh);
00028 }
00029
00030
00031 if (neighbors.size() == 0)
00032 return prevN;
00033
00034
00035
00036
00037
00038
00039
00040 boolean useless;
00041 do {
00042 useless = false;
00043 iNeigh = (ITypeNeighbor)neighbors.removeFirst();
00044 for (Iterator i = neighbors.iterator(); i.hasNext();) {
00045 ITypeNeighbor nNeigh = (ITypeNeighbor)i.next();
00046 ITypeNeighbor dominating = iDominates(iNeigh, nNeigh, prevPO);
00047 if (dominating == iNeigh)
00048 i.remove();
00049 if (dominating == nNeigh) {
00050 useless = true;
00051 break;
00052 }
00053 }
00054 if (!useless)
00055 prevN.add(iNeigh);
00056 } while (neighbors.size() > 0);
00057
00058
00059 return prevN;
00060 }
00061
00062
00063
00064 private static ITypeNeighbor iDominates(ITypeNeighbor iNeigh,
00065 ITypeNeighbor nNeigh,
00066 boolean prevPO[][]) {
00067 String iTerm = iNeigh.getTransition();
00068 String nTerm = nNeigh.getTransition();
00069 int iColor = iNeigh.getColor();
00070 int nColor = nNeigh.getColor();
00071 String theSubterm = subterm(iTerm, nTerm);
00072 if (theSubterm == iTerm) {
00073 if (prevPO[nColor-1][iColor-1]) {
00074
00075 return iNeigh;
00076 } else {
00077 return null;
00078 }
00079 }
00080 if (theSubterm == nTerm) {
00081 if (prevPO[iColor-1][nColor-1]) {
00082
00083 return nNeigh;
00084 } else {
00085 return null;
00086 }
00087 }
00088 if (theSubterm.equals("true")) {
00089 if (prevPO[nColor-1][iColor-1])
00090
00091 return iNeigh;
00092 else if (prevPO[iColor-1][nColor-1])
00093
00094 return nNeigh;
00095 }
00096 return null;
00097 }
00098 private static boolean iDominateSet(TreeSet setOne, TreeSet setTwo,
00099 boolean prevPO[][]) {
00100 TreeSet working = new TreeSet(setTwo);
00101 for (Iterator i = working.iterator(); i.hasNext();) {
00102 ITypeNeighbor neighTwo = (ITypeNeighbor)i.next();
00103 for (Iterator j = setOne.iterator(); j.hasNext();) {
00104 ITypeNeighbor neighOne = (ITypeNeighbor)j.next();
00105 ITypeNeighbor dominating = iDominates(neighOne, neighTwo, prevPO);
00106 if (dominating == neighOne) {
00107 i.remove();
00108 break;
00109 }
00110 }
00111 }
00112 if (working.size() == 0)
00113 return true;
00114
00115
00116 return false;
00117 }
00118 private static boolean isAccepting(Node nodeIn) {
00119 return (nodeIn.getBooleanAttribute("accepting"));
00120 }
00121 public static void main(String[] args) {
00122 if(args.length > 1) {
00123 System.out.println("usage:");
00124 System.out.println("\tjava gov.nasa.arc.ase.util.graph.SFSReduction [<filename>]");
00125 return;
00126 }
00127
00128
00129 Graph g = null;
00130
00131
00132 try {
00133 if(args.length == 0)
00134 g = Graph.load();
00135 else
00136 g = Graph.load(args[0]);
00137 } catch(IOException e) {
00138 System.out.println("Can't load the graph.");
00139 return;
00140 }
00141
00142
00143
00144 Graph reduced = reduce(g);
00145
00146
00147 reduced.save();
00148 }
00149 private static Graph reachabilityGraph(Graph g) {
00150 Vector work = new Vector();
00151 Vector reachable = new Vector();
00152 work.add(g.getInit());
00153 while(!work.isEmpty()) {
00154 Node currNode = (Node)work.firstElement();
00155 reachable.add(currNode);
00156 if (currNode != null) {
00157 List outgoingEdges = currNode.getOutgoingEdges();
00158 for (Iterator i=outgoingEdges.iterator();i.hasNext();) {
00159 Edge currEdge = (Edge)i.next();
00160 Node nextNode = (Node)currEdge.getNext();
00161 if (!(work.contains(nextNode) || reachable.contains(nextNode)))
00162 work.add(nextNode);
00163 }
00164 }
00165 if (work.remove(0) != currNode)
00166 System.out.println("ERROR");
00167 }
00168 List nodes = g.getNodes();
00169 if (nodes != null) {
00170 for (Iterator i=nodes.iterator();i.hasNext();) {
00171 Node n = (Node)i.next();
00172 if (!reachable.contains(n))
00173 g.removeNode(n);
00174 }
00175 }
00176 return g;
00177 }
00178 public static Graph reduce(Graph g) {
00179
00180
00181 int currNumColors;
00182 int prevNumColors = 1;
00183 int currNumPO = 4;
00184 int prevNumPO = prevNumColors;
00185 TreeSet newColorSet = null;
00186 LinkedList newColorList = null;
00187 boolean accepting = false;
00188 boolean nonaccepting = false;
00189
00190
00191
00192 List nodes = g.getNodes();
00193 for (Iterator i = nodes.iterator(); i.hasNext();) {
00194 Node currNode = (Node)i.next();
00195 currNode.setIntAttribute("_prevColor", 1);
00196 if (isAccepting(currNode)) {
00197 currNode.setIntAttribute("_currColor", 1);
00198 accepting = true;
00199 }
00200 else {
00201 currNode.setIntAttribute("_currColor", 2);
00202 nonaccepting = true;
00203 }
00204 }
00205 if (accepting && nonaccepting)
00206 currNumColors = 2;
00207 else
00208 currNumColors = 1;
00209
00210 boolean currPO[][] = new boolean[2][2];
00211 boolean prevPO[][];
00212 for (int i=0; i<2; i++) {
00213 for (int j=0; j<2; j++) {
00214 if (i >= j)
00215 currPO[i][j] = true;
00216 else
00217 currPO[i][j] = false;
00218 }
00219 }
00220
00221
00222 while ((currNumColors != prevNumColors) || (currNumPO != prevNumPO)) {
00223
00224 for (Iterator i = nodes.iterator(); i.hasNext();) {
00225 Node currNode = (Node)i.next();
00226 currNode.setIntAttribute("_prevColor",
00227 currNode.getIntAttribute("_currColor"));
00228 }
00229 prevPO = currPO;
00230 prevNumColors = currNumColors;
00231
00232
00233
00234 newColorList = new LinkedList();
00235 newColorSet = new TreeSet();
00236 for (Iterator i = nodes.iterator(); i.hasNext();) {
00237 Node currNode = (Node)i.next();
00238 ColorPair currPair =
00239 new ColorPair(currNode.getIntAttribute("_prevColor"),
00240 getPrevN(currNode, prevPO));
00241 newColorList.add(new Pair(currNode.getId(), currPair));
00242 newColorSet.add(currPair);
00243 }
00244 currNumColors = newColorSet.size();
00245
00246 if (prevNumColors == currNumColors)
00247 break;
00248
00249
00250
00251 LinkedList ordered = new LinkedList();
00252 for (Iterator i = newColorSet.iterator(); i.hasNext();) {
00253 ColorPair currPair = (ColorPair)i.next();
00254 ordered.add(currPair);
00255 }
00256
00257
00258
00259 for (Iterator i = newColorList.iterator(); i.hasNext();) {
00260 Pair cPair = (Pair)i.next();
00261 ColorPair currPair = (ColorPair)cPair.getElement();
00262 g.getNode(cPair.getValue()).setIntAttribute("_currColor",
00263 ordered.indexOf(currPair) + 1);
00264 }
00265
00266
00267 currPO = new boolean[currNumColors][currNumColors];
00268 for (Iterator i = newColorList.iterator(); i.hasNext();) {
00269 ColorPair currPairOne = (ColorPair)((Pair)i.next()).getElement();
00270 for(Iterator j = newColorList.iterator(); j.hasNext();) {
00271 ColorPair currPairTwo = (ColorPair)((Pair)j.next()).getElement();
00272 boolean po = prevPO[currPairTwo.getColor()-1][currPairOne.getColor()-1];
00273 boolean dominate = iDominateSet(currPairOne.getIMaxSet(),
00274 currPairTwo.getIMaxSet(), prevPO);
00275 if (po && dominate ) {
00276 currPO[ordered.indexOf(currPairTwo)][ordered.indexOf(currPairOne)]
00277 = true;
00278 }
00279 else
00280 currPO[ordered.indexOf(currPairTwo)][ordered.indexOf(currPairOne)]
00281 = false;
00282 }
00283 }
00284 }
00285
00286
00287
00288 Graph result;
00289 if (newColorList == null)
00290 result = g;
00291
00292
00293 else {
00294
00295
00296 result = new Graph();
00297 Node newNodes[] = new Node[currNumColors];
00298 for (int i=0; i< currNumColors; i++) {
00299 Node n = new Node(result);
00300 newNodes[i] = n;
00301 }
00302
00303
00304 for (Iterator i = newColorList.iterator();i.hasNext();) {
00305 Pair nodePair = (Pair)i.next();
00306 int origNodeId = nodePair.getValue();
00307 ColorPair colPair = (ColorPair)nodePair.getElement();
00308
00309
00310 if (newColorSet.contains(colPair)) {
00311 newColorSet.remove(colPair);
00312 TreeSet pairSet = (TreeSet)colPair.getIMaxSet();
00313 int color = colPair.getColor();
00314 Node currNode = newNodes[color-1];
00315
00316 for (Iterator j = pairSet.iterator(); j.hasNext();) {
00317 ITypeNeighbor neigh = (ITypeNeighbor)j.next();
00318 int neighPos = neigh.getColor()-1;
00319 Edge currEdge = new Edge(currNode, newNodes[neighPos], neigh.getTransition());
00320 }
00321
00322 if (g.getInit().getId() == origNodeId)
00323 result.setInit(currNode);
00324
00325
00326
00327 if (isAccepting(g.getNode(origNodeId)))
00328 currNode.setBooleanAttribute("accepting", true);
00329
00330
00331 }
00332 }
00333 }
00334 return reachabilityGraph(result);
00335
00336 }
00337 private static String subterm(String pred1, String pred2) {
00338
00339
00340 if (pred1.equals("-") && pred2.equals("-"))
00341 return "true";
00342 if (pred1.equals("-"))
00343 return pred1;
00344 if (pred2.equals("-"))
00345 return pred2;
00346
00347 if ((pred1.indexOf("true") != -1) && (pred2.indexOf("true") != -1))
00348 return "true";
00349 if (pred1.indexOf("true") != -1)
00350 return pred1;
00351 if (pred2.indexOf("true") != -1)
00352 return pred2;
00353
00354
00355
00356
00357
00358 String alphaStr;
00359 String tauStr;
00360
00361
00362 if (pred1.length() <= pred2.length()) {
00363 alphaStr = pred1;
00364 tauStr = pred2;
00365 } else {
00366 alphaStr = pred2;
00367 tauStr = pred1;
00368 }
00369
00370 StringTokenizer alphaTk = new StringTokenizer(alphaStr, "&");
00371 StringTokenizer tauTk = new StringTokenizer(tauStr, "&");
00372 LinkedList tauLst = new LinkedList();
00373
00374
00375
00376 while (tauTk.hasMoreTokens()) {
00377 String token = tauTk.nextToken();
00378 tauLst.add(token);
00379 }
00380 while (alphaTk.hasMoreTokens()) {
00381 String alphaLit = alphaTk.nextToken();
00382 if (!tauLst.contains(alphaLit))
00383 return "false";
00384 }
00385 if (pred1.length() == pred2.length())
00386 return "true";
00387 return alphaStr;
00388 }
00389 }