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 if (!cantremove.contains(gn)) {
123 Set cycle=GraphNode.findcycles(cantremove);
124 if (cycle.contains(gn)) {
125 if (!mustremove.contains(gn)) {
130 cantremove.remove(gn);
133 couldremove.removeAll(mustremove);
134 couldremove.removeAll(cantremove);
136 Vector couldremovevector=new Vector();
137 couldremovevector.addAll(couldremove);
138 Vector combination=new Vector();
140 continue; //recalculate
142 System.out.println("Searching set of "+couldremove.size()+" nodes.");
143 System.out.println("Eliminated "+mustremove.size()+" nodes");
144 System.out.println("Searching following set:");
145 for(Iterator it=couldremove.iterator();it.hasNext();) {
146 GraphNode gn=(GraphNode)it.next();
147 System.out.println(gn.getTextLabel());
152 if (illegal(combination,couldremovevector))
154 Set combinationset=buildset(combination,couldremovevector);
155 combinationset.addAll(mustremove);
156 if (combinationset!=null) {
157 System.out.println("Checkabstract="+checkAbstract(combinationset));
158 System.out.println("Checkrepairs="+checkRepairs(combinationset));
159 System.out.println("Checkall="+checkAll(combinationset));
161 if (checkAbstract(combinationset)==0&&
162 checkRepairs(combinationset)==0&&
163 checkAll(combinationset)==0) {
164 return combinationset;
167 increment(combination,couldremovevector);
173 private static Set buildset(Vector combination, Vector couldremove) {
175 for(int i=0;i<combination.size();i++) {
176 int index=((Integer)combination.get(i)).intValue();
177 Object o=couldremove.get(index);
186 private static boolean illegal(Vector combination, Vector couldremove) {
187 if (combination.size()>couldremove.size())
191 private static void increment(Vector combination, Vector couldremove) {
192 boolean incremented=false;
193 boolean forcereset=false;
194 for(int i=0;i<combination.size();i++) {
195 int newindex=((Integer)combination.get(i)).intValue()+1;
196 if (newindex==couldremove.size()||forcereset) {
198 if ((i+1)==combination.size()) {
201 newindex=((Integer)combination.get(i+1)).intValue()+2;
202 for(int j=i;j>=0;j--) {
203 combination.set(j,new Integer(newindex));
206 if (newindex>couldremove.size())
210 combination.set(i,new Integer(newindex));
214 if (incremented==false) /* Increase length */ {
215 combination.add(new Integer(0));
216 System.out.println("Expanding to :"+combination.size());
220 /* This function checks the graph as a whole for bad cycles */
221 public int checkAll(Collection removed) {
222 Set nodes=new HashSet();
223 nodes.addAll(termination.conjunctions);
224 nodes.removeAll(removed);
225 GraphNode.computeclosure(nodes,removed);
226 Set cycles=GraphNode.findcycles(nodes);
227 for(Iterator it=cycles.iterator();it.hasNext();) {
228 GraphNode gn=(GraphNode)it.next();
229 TermNode tn=(TermNode)gn.getOwner();
230 switch(tn.getType()) {
231 case TermNode.UPDATE:
232 case TermNode.CONJUNCTION:
234 case TermNode.ABSTRACT:
235 case TermNode.RULESCOPE:
236 case TermNode.CONSEQUENCE:
244 /* This function checks that
245 1) All abstract repairs have a corresponding data structure update
247 2) All scope nodes have either a consequence node or a compensation
248 node that isn't removed.
250 public int checkRepairs(Collection removed) {
251 Set nodes=new HashSet();
252 nodes.addAll(termination.conjunctions);
253 nodes.removeAll(removed);
254 GraphNode.computeclosure(nodes,removed);
255 Set toretain=new HashSet();
256 toretain.addAll(termination.abstractrepair);
257 toretain.addAll(termination.scopenodes);
258 nodes.retainAll(toretain);
259 /* Nodes is now the reachable set of abstractrepairs */
260 /* Check to see that each has an implementation */
261 for(Iterator it=nodes.iterator();it.hasNext();) {
262 GraphNode gn=(GraphNode)it.next();
263 TermNode tn=(TermNode)gn.getOwner();
264 if (tn.getType()==TermNode.RULESCOPE) {
265 boolean foundnode=false;
266 for (Iterator edgeit=gn.edges();edgeit.hasNext();) {
267 GraphNode.Edge edge=(GraphNode.Edge)edgeit.next();
268 GraphNode gn2=edge.getTarget();
269 if (!removed.contains(gn2)) {
270 TermNode tn2=(TermNode)gn2.getOwner();
271 if ((tn2.getType()==TermNode.CONSEQUENCE)||
272 (tn2.getType()==TermNode.UPDATE)) {
279 System.out.println(gn.getTextLabel());
282 } else if (tn.getType()==TermNode.ABSTRACT) {
283 boolean foundnode=false;
284 for (Iterator edgeit=gn.edges();edgeit.hasNext();) {
285 GraphNode.Edge edge=(GraphNode.Edge)edgeit.next();
286 GraphNode gn2=edge.getTarget();
287 if (!removed.contains(gn2)) {
288 TermNode tn2=(TermNode)gn2.getOwner();
289 if (tn2.getType()==TermNode.UPDATE) {
297 } else throw new Error("Unanticipated Node");
301 /* This method checks that all constraints have conjunction nodes
302 and that there are no bad cycles in the abstract portion of the graph.
304 public int checkAbstract(Collection removed) {
305 Vector constraints=termination.state.vConstraints;
306 for(int i=0;i<constraints.size();i++) {
307 Constraint c=(Constraint)constraints.get(i);
308 Set conjunctionset=(Set)termination.conjunctionmap.get(c);
310 boolean foundrepair=false;
311 for(Iterator it=conjunctionset.iterator();it.hasNext();) {
312 GraphNode gn=(GraphNode)it.next();
313 if (!removed.contains(gn)) {
320 Set abstractnodes=new HashSet();
321 abstractnodes.addAll(termination.conjunctions);
322 abstractnodes.removeAll(removed);
323 GraphNode.computeclosure(abstractnodes,removed);
325 Set tset=new HashSet();
326 tset.addAll(termination.conjunctions);
327 tset.addAll(termination.abstractrepair);
328 tset.addAll(termination.scopenodes);
329 tset.addAll(termination.consequencenodes);
330 abstractnodes.retainAll(tset);
331 Set cycles=GraphNode.findcycles(abstractnodes);
333 for(Iterator it=cycles.iterator();it.hasNext();) {
334 GraphNode gn=(GraphNode)it.next();
335 System.out.println("NODE: "+gn.getTextLabel());
336 TermNode tn=(TermNode)gn.getOwner();
337 switch(tn.getType()) {
338 case TermNode.CONJUNCTION:
339 case TermNode.ABSTRACT:
341 case TermNode.UPDATE:
342 throw new Error("No Update Nodes should be here");