5 public class GraphAnalysis {
6 Termination termination;
7 static final int WORKS=0;
8 static final int ERR_NOREPAIR=1;
9 static final int ERR_CYCLE=2;
10 static final int ERR_RULE=3;
11 static final int ERR_ABSTRACT=4;
13 public GraphAnalysis(Termination t) {
17 public Set doAnalysis() {
18 HashSet cantremove=new HashSet();
19 HashSet mustremove=new HashSet();
20 cantremove.addAll(termination.scopenodes);
21 cantremove.addAll(termination.abstractrepair);
25 HashSet nodes=new HashSet();
26 nodes.addAll(termination.conjunctions);
27 nodes.removeAll(mustremove);
28 GraphNode.computeclosure(nodes,mustremove);
29 Set cycles=GraphNode.findcycles(nodes);
30 Set couldremove=new HashSet();
31 couldremove.addAll(termination.conjunctions);
32 couldremove.addAll(termination.updatenodes);
33 couldremove.addAll(termination.consequencenodes);
34 couldremove.retainAll(cycles);
37 /* Look for constraints which can only be satisfied one way */
39 Vector constraints=termination.state.vConstraints;
40 for(int i=0;i<constraints.size();i++) {
41 Constraint c=(Constraint)constraints.get(i);
42 Set conjunctionset=(Set)termination.conjunctionmap.get(c);
43 HashSet tmpset=new HashSet();
44 tmpset.addAll(conjunctionset);
45 tmpset.removeAll(mustremove);
46 if (tmpset.size()==1) {
47 int oldsize=cantremove.size();
48 cantremove.addAll(tmpset);
49 if (cantremove.size()!=oldsize)
53 HashSet newset=new HashSet();
54 for(Iterator cit=cantremove.iterator();cit.hasNext();) {
55 GraphNode gn=(GraphNode)cit.next();
56 boolean nomodify=true;
57 HashSet toremove=new HashSet();
58 if (termination.conjunctions.contains(gn)) {
59 for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
60 GraphNode.Edge e=(GraphNode.Edge)edgeit.next();
61 GraphNode gn2=e.getTarget();
62 TermNode tn2=(TermNode)gn2.getOwner();
63 if (tn2.getType()==TermNode.ABSTRACT) {
64 AbstractRepair ar=tn2.getAbstract();
65 if (ar.getType()==AbstractRepair.MODIFYRELATION) {
69 HashSet updateset=new HashSet();
70 for(Iterator upit=gn2.edges();upit.hasNext();) {
71 GraphNode.Edge e2=(GraphNode.Edge)upit.next();
72 GraphNode gn3=e2.getTarget();
73 TermNode tn3=(TermNode)gn3.getOwner();
74 if (tn3.getType()==TermNode.UPDATE)
77 updateset.removeAll(mustremove);
78 if (updateset.size()==1)
79 toremove.addAll(updateset);
83 newset.addAll(toremove);
88 int oldsize=cantremove.size();
89 cantremove.addAll(newset);
90 if (cantremove.size()!=oldsize)
94 /* Look for required actions for scope nodes */
95 for(Iterator scopeit=termination.scopenodes.iterator();scopeit.hasNext();) {
96 GraphNode gn=(GraphNode)scopeit.next();
97 HashSet tmpset=new HashSet();
98 for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
99 GraphNode.Edge e=(GraphNode.Edge)edgeit.next();
100 tmpset.add(e.getTarget());
102 tmpset.removeAll(mustremove);
103 if (tmpset.size()==1) {
104 int oldsize=cantremove.size();
105 cantremove.addAll(tmpset);
106 if (cantremove.size()!=oldsize)
111 Set cycles2=GraphNode.findcycles(cantremove);
112 for(Iterator it=cycles2.iterator();it.hasNext();) {
113 GraphNode gn=(GraphNode)it.next();
114 if (termination.conjunctions.contains(gn))
115 return null; // Out of luck
119 for(Iterator it=termination.conjunctions.iterator();it.hasNext();) {
120 GraphNode gn=(GraphNode)it.next();
121 boolean foundnocycle=false;
123 for (Iterator edgeit=gn.edges();edgeit.hasNext();) {
124 GraphNode.Edge e=(GraphNode.Edge)edgeit.next();
125 GraphNode gn2=e.getTarget();
126 TermNode tn2=(TermNode)gn2.getOwner();
127 if (tn2.getType()!=TermNode.ABSTRACT)
129 for (Iterator edgeit2=gn2.edges();edgeit2.hasNext();) {
130 GraphNode.Edge e2=(GraphNode.Edge)edgeit2.next();
131 GraphNode gn3=e2.getTarget();
132 TermNode tn3=(TermNode)gn3.getOwner();
133 if (tn3.getType()!=TermNode.UPDATE)
135 boolean containsgn=cantremove.contains(gn);
136 boolean containsgn3=cantremove.contains(gn3);
139 Set cycle=GraphNode.findcycles(cantremove);
140 if (cycle.contains(gn3)) {
141 if (!mustremove.contains(gn3)) {
146 if (!mustremove.contains(gn3)&&!cycle.contains(gn)) {
150 cantremove.remove(gn);
152 cantremove.remove(gn3);
156 if (!mustremove.contains(gn)) {
162 couldremove.removeAll(mustremove);
163 couldremove.removeAll(cantremove);
165 Vector couldremovevector=new Vector();
166 couldremovevector.addAll(couldremove);
167 Vector combination=new Vector();
169 continue; //recalculate
171 System.out.println("Searching set of "+couldremove.size()+" nodes.");
172 System.out.println("Eliminated must "+mustremove.size()+" nodes");
173 System.out.println("Eliminated cant "+cantremove.size()+" nodes");
174 System.out.println("Searching following set:");
175 for(Iterator it=couldremove.iterator();it.hasNext();) {
176 GraphNode gn=(GraphNode)it.next();
177 System.out.println(gn.getTextLabel());
182 if (illegal(combination,couldremovevector))
184 Set combinationset=buildset(combination,couldremovevector);
185 combinationset.addAll(mustremove);
186 if (combinationset!=null) {
187 System.out.println("Checkabstract="+checkAbstract(combinationset));
188 System.out.println("Checkrepairs="+checkRepairs(combinationset));
189 System.out.println("Checkall="+checkAll(combinationset));
191 if (checkAbstract(combinationset)==0&&
192 checkRepairs(combinationset)==0&&
193 checkAll(combinationset)==0) {
194 return combinationset;
197 increment(combination,couldremovevector);
203 private static Set buildset(Vector combination, Vector couldremove) {
205 for(int i=0;i<combination.size();i++) {
206 int index=((Integer)combination.get(i)).intValue();
207 Object o=couldremove.get(index);
216 private static boolean illegal(Vector combination, Vector couldremove) {
217 if (combination.size()>couldremove.size())
221 private static void increment(Vector combination, Vector couldremove) {
222 boolean incremented=false;
223 boolean forcereset=false;
224 for(int i=0;i<combination.size();i++) {
225 int newindex=((Integer)combination.get(i)).intValue()+1;
226 if (newindex==couldremove.size()||forcereset) {
228 if ((i+1)==combination.size()) {
231 newindex=((Integer)combination.get(i+1)).intValue()+2;
232 for(int j=i;j>=0;j--) {
233 combination.set(j,new Integer(newindex));
236 if (newindex>couldremove.size())
240 combination.set(i,new Integer(newindex));
244 if (incremented==false) /* Increase length */ {
245 combination.add(new Integer(0));
246 System.out.println("Expanding to :"+combination.size());
250 /* This function checks the graph as a whole for bad cycles */
251 public int checkAll(Collection removed) {
252 Set nodes=new HashSet();
253 nodes.addAll(termination.conjunctions);
254 nodes.removeAll(removed);
255 GraphNode.computeclosure(nodes,removed);
256 Set cycles=GraphNode.findcycles(nodes);
257 for(Iterator it=cycles.iterator();it.hasNext();) {
258 GraphNode gn=(GraphNode)it.next();
259 TermNode tn=(TermNode)gn.getOwner();
260 switch(tn.getType()) {
261 case TermNode.UPDATE:
262 case TermNode.CONJUNCTION:
264 case TermNode.ABSTRACT:
265 case TermNode.RULESCOPE:
266 case TermNode.CONSEQUENCE:
274 /* This function checks that
275 1) All abstract repairs have a corresponding data structure update
277 2) All scope nodes have either a consequence node or a compensation
278 node that isn't removed.
280 public int checkRepairs(Collection removed) {
281 Set nodes=new HashSet();
282 nodes.addAll(termination.conjunctions);
283 nodes.removeAll(removed);
284 GraphNode.computeclosure(nodes,removed);
285 Set toretain=new HashSet();
286 toretain.addAll(termination.abstractrepair);
287 toretain.addAll(termination.scopenodes);
288 nodes.retainAll(toretain);
289 /* Nodes is now the reachable set of abstractrepairs */
290 /* Check to see that each has an implementation */
291 for(Iterator it=nodes.iterator();it.hasNext();) {
292 GraphNode gn=(GraphNode)it.next();
293 TermNode tn=(TermNode)gn.getOwner();
294 if (tn.getType()==TermNode.RULESCOPE) {
295 boolean foundnode=false;
296 for (Iterator edgeit=gn.edges();edgeit.hasNext();) {
297 GraphNode.Edge edge=(GraphNode.Edge)edgeit.next();
298 GraphNode gn2=edge.getTarget();
299 if (!removed.contains(gn2)) {
300 TermNode tn2=(TermNode)gn2.getOwner();
301 if ((tn2.getType()==TermNode.CONSEQUENCE)||
302 (tn2.getType()==TermNode.UPDATE)) {
309 System.out.println(gn.getTextLabel());
312 } else if (tn.getType()==TermNode.ABSTRACT) {
313 boolean foundnode=false;
314 for (Iterator edgeit=gn.edges();edgeit.hasNext();) {
315 GraphNode.Edge edge=(GraphNode.Edge)edgeit.next();
316 GraphNode gn2=edge.getTarget();
317 if (!removed.contains(gn2)) {
318 TermNode tn2=(TermNode)gn2.getOwner();
319 if (tn2.getType()==TermNode.UPDATE) {
327 } else throw new Error("Unanticipated Node");
331 /* This method checks that all constraints have conjunction nodes
332 and that there are no bad cycles in the abstract portion of the graph.
334 public int checkAbstract(Collection removed) {
335 Vector constraints=termination.state.vConstraints;
336 for(int i=0;i<constraints.size();i++) {
337 Constraint c=(Constraint)constraints.get(i);
338 Set conjunctionset=(Set)termination.conjunctionmap.get(c);
340 boolean foundrepair=false;
341 for(Iterator it=conjunctionset.iterator();it.hasNext();) {
342 GraphNode gn=(GraphNode)it.next();
343 if (!removed.contains(gn)) {
350 Set abstractnodes=new HashSet();
351 abstractnodes.addAll(termination.conjunctions);
352 abstractnodes.removeAll(removed);
353 GraphNode.computeclosure(abstractnodes,removed);
355 Set tset=new HashSet();
356 tset.addAll(termination.conjunctions);
357 tset.addAll(termination.abstractrepair);
358 tset.addAll(termination.scopenodes);
359 tset.addAll(termination.consequencenodes);
360 abstractnodes.retainAll(tset);
361 Set cycles=GraphNode.findcycles(abstractnodes);
363 for(Iterator it=cycles.iterator();it.hasNext();) {
364 GraphNode gn=(GraphNode)it.next();
365 System.out.println("NODE: "+gn.getTextLabel());
366 TermNode tn=(TermNode)gn.getOwner();
367 switch(tn.getType()) {
368 case TermNode.CONJUNCTION:
369 case TermNode.ABSTRACT:
371 case TermNode.UPDATE:
372 throw new Error("No Update Nodes should be here");