Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00030 package hittingsetalg;
00031 
00032 import java.io.*;      
00033 import java.util.*;    
00034 
00035 import theoremprover.*;
00036 import utils.SortedIntList;
00037 
00047 public class MinHittingSets {
00048     
00049     protected final static int CS_COMPUTING = 0;
00050     
00051     public final static int CS_ALL_MIN_DIAGS_COMPUTED = 1;
00052 
00053     public final static int CS_MAX_HS_SIZE_REACHED = 2;
00054 
00055     public final static int CS_MAX_NUM_MIN_HS_REACHED = 3;
00056 
00057 
00058     
00059     protected ArrayList computedMinHS = new ArrayList();
00060     
00061     
00062     protected int maxHSSize;
00063 
00064     
00065     protected int maxNumMinHS;
00066 
00067     
00068     protected boolean conflictsAreMinimal;
00069 
00070     
00071 
00072 
00073 
00074 
00075     protected ArrayList conflictSets = null;
00076 
00077     
00078     protected ABTheoremProver theoremProver = null;
00079 
00080     
00081     protected ArrayList assumptions = null;
00082 
00083     
00084     
00085     protected SortedIntList components = null;
00086 
00087     
00088     protected boolean computeIncr;
00089 
00090     
00091     protected HSNode rootNode = null;
00092 
00093     
00094     protected ArrayList levels = new ArrayList();
00095 
00096     protected int computationState = -1;
00097 
00098     protected HSNode attemptedPruneNode = null;
00099 
00100 
00113     public MinHittingSets(boolean conflictsAreMinimal, ArrayList conflictSets) {
00114         
00115         assert(conflictSets.size() >= 1);
00116 
00117         computeIncr = false;
00118         this.conflictsAreMinimal = conflictsAreMinimal;
00119         this.conflictSets = conflictSets;
00120     }
00121 
00130     public MinHittingSets(boolean conflictsAreMinimal,
00131                           ABTheoremProver tp) {
00132         
00133         assert((tp != null) && (tp.getAssumptions().size() > 0));
00134         
00135         computeIncr = true;
00136         this.conflictsAreMinimal = conflictsAreMinimal;
00137         this.conflictSets = new ArrayList();
00138         this.theoremProver = tp;
00139         
00140         
00141         assumptions = tp.getAssumptions();
00142         components = new SortedIntList();
00143         Iterator it = assumptions.iterator();
00144         int tag = 0;
00145         System.out.println("Assumption tags: ");
00146         while(it.hasNext()) {
00147             Assumption a = (Assumption)it.next();
00148             a.setIntTag(tag);
00149             System.out.println((new Integer(tag)).toString() + ": " + (String)a.identifier);
00150             components.addSorted(tag);
00151             ++tag;
00152         }
00153 
00154         System.out.println();
00155     }
00156 
00165     public ArrayList getMinHS() {
00166 
00167         if (theoremProver == null) {
00168             throw new UnsupportedOperationException("class MinHittingSets: if no theorem prover is used "
00169                                                     + "for the dynamic computation of conflicts sets, then "
00170                                                     + "getMinHSAsIntegers() must be used instead of "
00171                                                     + "getMinHS() !!");
00172         }                                       
00173 
00174         ArrayList result = new ArrayList();
00175         result.ensureCapacity(computedMinHS.size());
00176 
00177         Iterator itMinHS = computedMinHS.iterator();
00178         while (itMinHS.hasNext()) {
00179             HSNode node = (HSNode)itMinHS.next();
00180             if (node.state != HSNode.STATE_PRUNED) {
00181                 assert(node.state == HSNode.STATE_MINIMAL);
00182 
00183                 ArrayList candidate = new ArrayList();
00184                 Iterator itAss = node.edgeLabels.iterator();
00185                 while (itAss.hasNext()) {
00186                     Integer index = (Integer)itAss.next();
00187                     candidate.add(theoremProver.getAssumptions().get(index.intValue()));
00188                 }
00189                 result.add(candidate);
00190 
00191             }
00192         }
00193 
00194         return result;
00195     }
00196 
00197     
00198 
00199 
00200 
00201 
00202 
00203 
00204     public ArrayList getMinHSAsIntLists() {
00205         ArrayList result = new ArrayList();
00206         result.ensureCapacity(computedMinHS.size());
00207 
00208         Iterator itMinHS = computedMinHS.iterator();
00209         while (itMinHS.hasNext()) {
00210             HSNode node = (HSNode)itMinHS.next();
00211             if (node.state != HSNode.STATE_PRUNED) {
00212                 assert(node.state == HSNode.STATE_MINIMAL);
00213 
00214                 result.add(node.edgeLabels);
00215             }
00216         }
00217 
00218         return result;
00219     }
00220 
00221     
00222 
00223 
00224 
00225 
00226 
00227     public ArrayList getConflictsAsAss() {
00228         ArrayList result = new ArrayList();
00229 
00230         Iterator itConflicts = conflictSets.iterator();
00231         while (itConflicts.hasNext()) {
00232             SortedIntList cs = (SortedIntList)itConflicts.next();
00233             if (cs != null) {  
00234                 ArrayList csAss = new ArrayList(cs.size());
00235 
00236                 Iterator itCS = cs.iterator();
00237                 while (itCS.hasNext()) {
00238                     int index = ((Integer)itCS.next()).intValue();
00239                     Assumption a = (Assumption)assumptions.get(index);
00240                     csAss.add(a);
00241                 }
00242                 
00243                 result.add(csAss);
00244             }
00245         }
00246 
00247         return result;
00248     }
00249 
00250     
00251 
00252 
00253 
00254 
00255 
00256 
00257     
00258 
00259 
00260     public int compute(int maxHSSize, int maxNumMinHS) {
00261         
00262         assert((maxHSSize >= 1) && (maxNumMinHS >= 1));
00263 
00264         
00265 
00266         computationState = CS_COMPUTING;
00267         this.maxHSSize = maxHSSize;
00268         this.maxNumMinHS = maxNumMinHS;
00269         LinkedList lastLevelNodes  = new LinkedList(); 
00270         int lastLevel = 0;
00271         levels.add(lastLevelNodes);
00272 
00273         
00274 
00275         rootNode = new HSNode();
00276         rootNode.edgeLabels = new SortedIntList();  
00277         lastLevelNodes.add(rootNode);
00278 
00279         
00280 
00281         while(computationState == CS_COMPUTING) {
00282 
00283             
00284             
00285 
00286             LinkedList newLevelNodes = new LinkedList();
00287             levels.add(newLevelNodes);
00288             processLastLevel(lastLevel, lastLevelNodes, newLevelNodes, true);
00289             
00290             
00291             lastLevelNodes = newLevelNodes;
00292             ++lastLevel;
00293 
00294             if (computationState == CS_COMPUTING) {
00295                 assert(lastLevelNodes.size() > 0);
00296                 if (lastLevel - 1 == maxHSSize) computationState = CS_MAX_HS_SIZE_REACHED;
00297             }   
00298         }
00299 
00300         assert(computationState != CS_COMPUTING);
00301         return computationState;
00302 
00303     }  
00304 
00305     public int computeMore(int newMaxHSSize, int newMaxNumMinHS) {
00306         assert((newMaxHSSize >= maxHSSize) && (newMaxNumMinHS >= maxNumMinHS));
00307 
00308         if (computationState == CS_ALL_MIN_DIAGS_COMPUTED) return CS_ALL_MIN_DIAGS_COMPUTED;
00309         else {
00310             
00311             this.maxHSSize = newMaxHSSize;
00312             this.maxNumMinHS = newMaxNumMinHS; 
00313             int lastLevel;
00314             LinkedList lastLevelNodes;
00315             LinkedList newLevelNodes;
00316 
00317             if (computationState == CS_MAX_HS_SIZE_REACHED) {
00318                 lastLevel = levels.size() - 1;
00319                 lastLevelNodes = (LinkedList)levels.get(lastLevel);
00320                 newLevelNodes = null;
00321             } else {
00322                 assert(computationState == CS_MAX_NUM_MIN_HS_REACHED);
00323                 lastLevel = levels.size() - 2;
00324                 lastLevelNodes = (LinkedList)levels.get(lastLevel);
00325                 newLevelNodes = (LinkedList)levels.get(lastLevel + 1);
00326             }
00327             
00328             if (computedMinHS.size() == maxNumMinHS) computationState = CS_MAX_NUM_MIN_HS_REACHED;
00329             else if (lastLevel - 1 == maxHSSize) computationState = CS_MAX_HS_SIZE_REACHED;
00330             else computationState = CS_COMPUTING;
00331 
00332             while(computationState == CS_COMPUTING) {
00333                  
00334                 if (newLevelNodes == null) {
00335                     newLevelNodes = new LinkedList();
00336                     levels.add(newLevelNodes);
00337                 }
00338                 
00339                 processLastLevel(lastLevel, lastLevelNodes, newLevelNodes, true);
00340                 lastLevelNodes = newLevelNodes;
00341                 ++lastLevel;
00342                 
00343                 if (computationState == CS_COMPUTING) {
00344                     if (lastLevelNodes.size() == 0) computationState = CS_ALL_MIN_DIAGS_COMPUTED;
00345                     else if (lastLevel - 1 == maxHSSize) computationState = CS_MAX_HS_SIZE_REACHED;
00346                 } 
00347             }
00348 
00349             assert(computationState != CS_COMPUTING);
00350             return computationState;
00351         }
00352     }
00353 
00354     
00355     
00356     protected SortedIntList callTheoremProver(SortedIntList edgeLabels) {
00357 
00358         SortedIntList assumptionSet = components.subtract(edgeLabels);  
00359 
00360         
00361 
00362         Iterator itAss = assumptionSet.iterator();
00363         while(itAss.hasNext()) {
00364             int assIndex = ((Integer)itAss.next()).intValue();
00365             Assumption a = (Assumption)assumptions.get(assIndex);
00366             
00367             if (a.getLabel() != true) {
00368                 a.setLabel(true);
00369                 a.propagateTrue();
00370             }
00371         }
00372 
00373         
00374         
00375         Iterator itNegAss = edgeLabels.iterator();
00376         while(itNegAss.hasNext()) {
00377             int negassIndex = ((Integer)itNegAss.next()).intValue();
00378             Assumption a = (Assumption)assumptions.get(negassIndex);
00379 
00380             if (a.getLabel() != false)
00381             {
00382                 ArrayList v = new ArrayList();
00383                 v = a.propagateFalse(v); 
00384                 Iterator ve = v.iterator();                                
00385                 while (ve.hasNext()) {
00386                     Proposition p = (Proposition)ve.next();
00387                     p.correctLabels();
00388                 }
00389             }
00390         }
00391 
00392         
00393 
00394         
00395 
00396         if (theoremProver.isConsistent()) {
00397             
00398             return null;  
00399         } else {
00400 
00401             
00402 
00403             ArrayList conflicts = theoremProver.contradiction().collectAssumptions();
00404             SortedIntList cs = new SortedIntList();
00405             Iterator itConflicts = conflicts.iterator();
00406             while(itConflicts.hasNext()) {
00407                 Assumption a = (Assumption)itConflicts.next();
00408                 cs.addSorted(a.getIntTag());
00409             }
00410             
00411             
00412             return cs;
00413         }
00414 
00415     }  
00416 
00417 
00418     
00419 
00420 
00421 
00422     protected void prune(HSNode node, HSNode prunedParent) {
00423 
00424         assert(nodeInvariant(node));
00425 
00426         if ((node.state == HSNode.STATE_OPEN) || (node.state == HSNode.STATE_MINIMAL)) {
00427 
00428             boolean hasAliveParents;  
00429             if (node.parents.size() == 1) hasAliveParents = false;
00430             else {
00431                 assert(node.parents.size() > 1);
00432                 
00433                 hasAliveParents = false;
00434 
00435                 Iterator itParents = node.parents.iterator();
00436                 while (itParents.hasNext()) {
00437                     HSNode parent = (HSNode)itParents.next();
00438                     if ((parent != prunedParent) && (parent.state != HSNode.STATE_PRUNED)) {
00439                         hasAliveParents = true;
00440                         break;
00441                     }
00442                 }
00443             }
00444 
00445             if (!hasAliveParents) {  
00446                 
00447                 node.state = HSNode.STATE_PRUNED;
00448                 
00449                 
00450 
00451                 Iterator itChildren = node.children.iterator();
00452                 while (itChildren.hasNext()) {
00453                     HSNode child = ((EdgeNodePair)itChildren.next()).node;
00454                     if (child.state != HSNode.STATE_PRUNED) {
00455                         prune(child, node);
00456                     }
00457                 }
00458             }
00459             else {
00460                 
00461             }
00462         }
00463 
00464         assert(nodeInvariant(node));
00465 
00466     }  
00467 
00468 
00469     
00470 
00471 
00472 
00473     protected void relabel(HSNode node, HSNode newNode) {
00474 
00475         
00476         
00477         assert((node.state != HSNode.STATE_MINIMAL) &&  newNode.label.properSubsetOf(node.label));
00478         assert(nodeInvariant(node));
00479         assert(nodeInvariant(newNode));
00480         assert(newNode == attemptedPruneNode);
00481 
00482         
00483 
00484         SortedIntList removeLabel = node.label.subtract(newNode.label);
00485         node.label = newNode.label;
00486         conflictSets.set(node.conflictSetIndex, newNode.label);
00487         
00488         newNode.conflictSetIndex = node.conflictSetIndex;                
00489 
00490         
00491 
00492         int prunedChildrenCount = 0;
00493         Iterator itChildren = node.children.iterator();
00494         while (itChildren.hasNext()) {
00495             EdgeNodePair child = (EdgeNodePair)itChildren.next();
00496 
00497             if (removeLabel.contains(child.edge)) {  
00498                 
00499                 if (child.node.state != HSNode.STATE_PRUNED) {
00500                     prune(child.node, node);
00501                 }
00502 
00503                 ++prunedChildrenCount;
00504             }    
00505             
00506             
00507         }
00508         assert(prunedChildrenCount == removeLabel.size());
00509         
00510         assert(nodeInvariant(node));
00511         assert(nodeInvariant(newNode));
00512         assert(node.label.equals(newNode.label));
00513     }  
00514 
00515 
00516     
00517     protected int computeNumUnprunedChildren(HSNode node) {
00518         int n = 0;
00519         Iterator itChildren = node.children.iterator();
00520         while (itChildren.hasNext()) {
00521             HSNode child = ((EdgeNodePair)itChildren.next()).node;
00522             if (child.state != HSNode.STATE_PRUNED) ++n;
00523         }
00524 
00525         return n;
00526     }
00527 
00528 
00529     
00530     protected void attemptPrune(HSNode node) {
00531         
00532         
00533         assert((node.state == HSNode.STATE_OPEN) && (node.label != null)               
00534                && (node.label.size() > 0) && (node != rootNode) && nodeInvariant(node));
00535 
00536         attemptedPruneNode = node;
00537         int oldConflictSetIndex = node.conflictSetIndex;
00538         boolean pruned = false;  
00539 
00540         
00541         rootNode.relevantForPruning = true;
00542         boolean relevantNodesExist = true;
00543 
00544         
00545 
00546         Iterator itLevels = levels.iterator();
00547         while(itLevels.hasNext() && relevantNodesExist) {
00548         
00549             relevantNodesExist = false;
00550 
00551             LinkedList level = (LinkedList)itLevels.next();
00552             Iterator itLevelNodes = level.iterator();
00553 
00554             SortedIntList intersectionSet = new SortedIntList();
00555 
00556             
00557 
00558             while(itLevelNodes.hasNext()) {
00559 
00560                 HSNode otherNode = (HSNode)itLevelNodes.next();
00561                 
00562                 if ((otherNode.state == HSNode.STATE_OPEN) && (otherNode.label != null) 
00563                     && otherNode.relevantForPruning) {
00564                     
00565                     
00566 
00567                     intersectionSet.clear();
00568                     boolean intersects = otherNode.label.intersection(node.label, intersectionSet);
00569                     assert((!intersects && (intersectionSet.size() == 0))
00570                            || (intersects && (intersectionSet.size() != 0)));
00571                    
00572                     
00573                     
00574                     boolean canPrune = (intersects && (intersectionSet.size() == node.label.size())
00575                                         && (node.label.size() < otherNode.label.size()));
00576                     assert(!canPrune || node.label.properSubsetOf(otherNode.label));
00577 
00578                     if (canPrune) {  
00579 
00580                         relabel(otherNode, node);
00581                         pruned = true;
00582 
00583                     } else {  
00584                         
00585                         if ((intersectionSet.size() > 0)        
00586                             && (otherNode.children.size() > 0)) {   
00587                             
00588                             
00589 
00590                             Iterator itIntersection = intersectionSet.iterator();
00591                             int nextItem;
00592                             if (itIntersection.hasNext()) 
00593                                 nextItem = ((Integer)itIntersection.next()).intValue();
00594                             else nextItem = Integer.MAX_VALUE;
00595                             
00596                             Iterator itChildren = otherNode.children.iterator();
00597                             while (itChildren.hasNext()) {
00598                                 EdgeNodePair child = (EdgeNodePair)itChildren.next();
00599                                 
00600                                 if (child.edge == nextItem) {
00601                                     child.node.relevantForPruning = false;
00602                                     assert(node.label.contains(child.edge));
00603                                     if (itIntersection.hasNext()) 
00604                                         nextItem = ((Integer)itIntersection.next()).intValue();
00605                                     else nextItem = Integer.MAX_VALUE;
00606                                 } else {
00607                                     child.node.relevantForPruning = true;
00608                                     relevantNodesExist = true;
00609                                 }
00610                             }
00611 
00612                             assert(!itIntersection.hasNext());
00613                             
00614                         } else {  
00615                             
00616                             Iterator itChildren = otherNode.children.iterator();
00617                             while (itChildren.hasNext()) {
00618                                 HSNode child = ((EdgeNodePair)itChildren.next()).node;
00619                                 child.relevantForPruning = true;
00620                             }
00621                             relevantNodesExist = true;
00622 
00623                         }
00624 
00625                     }  
00626 
00627                 }  
00628 
00629                 else if (!otherNode.relevantForPruning) {  
00630 
00631                     Iterator itChildren = otherNode.children.iterator();
00632                     while(itChildren.hasNext()) {
00633                         HSNode child = ((EdgeNodePair)itChildren.next()).node;
00634                         child.relevantForPruning = false;
00635                     }
00636 
00637                 }
00638 
00639             }  
00640 
00641         }  
00642 
00643         if (pruned) conflictSets.set(oldConflictSetIndex, null);
00644         attemptedPruneNode = null;
00645 
00646         assert(nodeInvariant(node));
00647 
00648     }  
00649 
00650     
00651 
00652 
00653 
00654 
00655 
00656 
00657 
00658     protected int searchRefutingCS(SortedIntList edgeLabel) {
00659         for (int i = 0; i < conflictSets.size(); ++i) {
00660             Object o = conflictSets.get(i);
00661             if (o != null) {  
00662                 SortedIntList cs = (SortedIntList)conflictSets.get(i);
00663                 assert(cs.size() > 0);
00664                 if (!edgeLabel.intersects(cs)) return i;
00665             }
00666         }
00667 
00668         return -1;
00669     }
00670     
00671 
00672     
00673 
00674 
00675 
00676 
00677     protected void computeLabel(HSNode node) {
00678 
00679         assert((node.state == HSNode.STATE_OPEN) && (node.label == null)
00680             && nodeInvariant(node));
00681 
00682         
00683 
00684         if (canClose(node)) {
00685             node.state = HSNode.STATE_CLOSED;
00686             
00687         }
00688 
00689         else {
00690 
00691             if (computeIncr) {
00692                 
00693                 int existingCSIndex = searchRefutingCS(node.edgeLabels);
00694                 if (existingCSIndex >= 0) {
00695                     assert(callTheoremProver(node.edgeLabels) != null);
00696                     SortedIntList existingCS = (SortedIntList)conflictSets.get(existingCSIndex);
00697                     node.label = existingCS;
00698                     node.conflictSetIndex = existingCSIndex;
00699                     
00700                     if (!conflictsAreMinimal && (node != rootNode)) attemptPrune(node);
00701                 }
00702                 else {
00703                     SortedIntList cs = callTheoremProver(node.edgeLabels);
00704                     if (cs == null) {
00705                         node.state = HSNode.STATE_MINIMAL;
00706                     }
00707                     else {
00708                         assert(cs.size() > 0);
00709                         conflictSets.add(cs);
00710                         node.label = cs;
00711                         node.conflictSetIndex = conflictSets.size() - 1;
00712                         
00713                         if (!conflictsAreMinimal && (node != rootNode)) attemptPrune(node);
00714                     }
00715                 }
00716 
00717             }
00718             
00719             else {  
00720                 
00721                 if (node.edgeLabels.size() == 0) {  
00722                     node.label = (SortedIntList)conflictSets.get(0);
00723                     node.conflictSetIndex = 0;
00724                 }
00725                 
00726                 else {  
00727                     
00728                     Iterator itCS = conflictSets.iterator();
00729                     int csIndex = 0;
00730                     boolean hitsAllCS = true;  
00731                     
00732                     
00733                     while(itCS.hasNext() && hitsAllCS) {
00734                         SortedIntList cs = (SortedIntList)itCS.next();
00735                         
00736                         if (!node.edgeLabels.intersects(cs)) {
00737                             hitsAllCS = false;
00738                             node.label = cs;
00739                             node.conflictSetIndex = csIndex;
00740                             assert(cs.equals(conflictSets.get(csIndex)));
00741                             
00742                         } else ++csIndex;
00743                     }
00744                     
00745                     if (hitsAllCS) {
00746                         node.state = HSNode.STATE_MINIMAL;
00747                         
00748                     } else {
00749                         if (!conflictsAreMinimal && (node != rootNode)) attemptPrune(node);
00750                     }
00751                     
00752                 }
00753                 
00754             }  
00755             
00756 
00757 
00758         }  
00759 
00760         assert(nodeInvariant(node));
00761 
00762     }  
00763 
00764 
00765     
00766     protected boolean canClose(HSNode node) {
00767         
00768         assert(nodeInvariant(node));
00769 
00770         Iterator itMinHS = computedMinHS.iterator();
00771         while (itMinHS.hasNext()) {
00772             HSNode n1 = (HSNode)itMinHS.next();
00773             if (n1.state == HSNode.STATE_MINIMAL) {
00774                 SortedIntList hs = n1.edgeLabels;
00775                 if (hs.subsetOf(node.edgeLabels)) {
00776                     assert(hs.properSubsetOf(node.edgeLabels));
00777                     return true;
00778                 }
00779             } else assert(n1.state == HSNode.STATE_PRUNED);
00780         }
00781 
00782         return false;
00783     }
00784 
00785     
00786 
00787 
00788 
00789 
00790     protected void processLastLevel(int lastLevel, LinkedList lastLevelNodes, 
00791                                     LinkedList newLevelNodes, boolean expandNodes) {
00792 
00793         
00794 
00795         boolean hasOpenNodes = false;
00796 
00797         Iterator itLastNodes = lastLevelNodes.iterator();
00798         while(itLastNodes.hasNext()) {
00799 
00800             HSNode node = (HSNode)itLastNodes.next();
00801             assert(nodeInvariant(node));
00802             if (node.state == HSNodeFM.STATE_OPEN) {
00803 
00804                 computeLabel(node);
00805 
00806                 if (node.state == HSNodeFM.STATE_MINIMAL) {
00807                     computedMinHS.add(node);
00808                     if (computedMinHS.size() == maxNumMinHS) {
00809                         computationState = CS_MAX_NUM_MIN_HS_REACHED;
00810                         break;
00811                     }
00812                 } else if (node.state == HSNodeFM.STATE_OPEN) {
00813                     hasOpenNodes = true;
00814                     if (expandNodes) {
00815                         expandNode(node, newLevelNodes, lastLevel);
00816                     }
00817                 }
00818             }
00819 
00820             assert(nodeInvariant(node));
00821 
00822         }  
00823 
00824         if ((computationState == CS_COMPUTING) && !hasOpenNodes) {
00825             computationState = CS_ALL_MIN_DIAGS_COMPUTED;
00826         }
00827     }
00828 
00829     
00830 
00831 
00832 
00833     protected void expandNode(HSNode node, LinkedList newNodes, int lastLevel) {
00834         
00835         assert((node.label != null) && (node.label.size() >= 1) && nodeInvariant(node));
00836 
00837         int oldNewNodesSize = newNodes.size();
00838 
00839         int newEdge;
00840 
00841         
00842 
00843         Iterator itLabel = node.label.iterator();
00844         while(itLabel.hasNext()) {
00845 
00846             
00847 
00848             newEdge = ((Integer)itLabel.next()).intValue();            
00849             SortedIntList newEdgeLabels = (SortedIntList)node.edgeLabels.clone();
00850             newEdgeLabels.addSorted(newEdge);
00851             
00852             
00853 
00854             
00855             
00856 
00857             boolean reused = false;
00858             Iterator itNewNodes = newNodes.iterator();
00859             for (int i = 0; i < oldNewNodesSize; ++i) {
00860                 HSNode m = (HSNode)itNewNodes.next();
00861                 if (newEdgeLabels.equals(m.edgeLabels)) {  
00862                     node.children.add(new EdgeNodePair(newEdge, m));
00863                     m.parents.add(node);
00864                     reused = true;
00865                     
00866                     break;
00867                 }
00868             }
00869 
00870             if (!reused) {  
00871 
00872                 HSNode newNode = new HSNode();
00873                 newNode.edgeLabels = newEdgeLabels;
00874 
00875                 node.children.add(new EdgeNodePair(newEdge, newNode));
00876                 newNode.parents.add(node);
00877                 newNodes.add(newNode);
00878 
00879                 
00880             }
00881 
00882         }  
00883  
00884         assert(nodeInvariant(node));
00885         
00886     }  
00887 
00888     public boolean checkMinimalityHS() {
00889 
00890         for (int i = 0; i < computedMinHS.size(); ++i) {
00891 
00892             HSNode node = (HSNode)computedMinHS.get(i);
00893 
00894             if (node.state == HSNode.STATE_MINIMAL) {
00895 
00896                 for (int j = i + 1; j < computedMinHS.size(); ++j) {
00897                     
00898                     HSNode otherNode = (HSNode)computedMinHS.get(j);
00899                     
00900                     if ((otherNode.state == HSNode.STATE_MINIMAL) 
00901                         && node.edgeLabels.subsetOf(otherNode.edgeLabels) 
00902                         || otherNode.edgeLabels.subsetOf(node.edgeLabels)) return false;
00903                     
00904                 }
00905             }
00906         }
00907 
00908         return true;
00909     }
00910 
00911     public boolean hitsAllConflictSets() {
00912 
00913         for (int i = 0; i < computedMinHS.size(); ++i) {
00914 
00915             HSNode node = (HSNode)computedMinHS.get(i);
00916             if (node.state == HSNode.STATE_MINIMAL) {
00917                 
00918                 Iterator itCS = conflictSets.iterator();
00919                 while (itCS.hasNext()) {
00920 
00921                     SortedIntList cs = (SortedIntList)itCS.next();
00922 
00923                     if (!node.edgeLabels.intersects(cs)) return false;
00924                     
00925                 }
00926 
00927             }
00928         }
00929 
00930         return true;
00931 
00932     }
00933 
00934     protected boolean nodeInvariant(HSNode node) {
00935 
00936         boolean a = ((node.label == null) || !node.label.intersects(node.edgeLabels));
00937         boolean b = ((node.conflictSetIndex == -1) 
00938                     || (node.label.equals(conflictSets.get(node.conflictSetIndex)))
00939                     || ((attemptedPruneNode != null) 
00940                         && attemptedPruneNode.label.equals(conflictSets.get(node.conflictSetIndex))));
00941         boolean c = ((node == rootNode) || (node.parents.size() >= 1));
00942 
00943         boolean result = (a && b && c);
00944 
00945         if (!result) {
00946             if (!a) {
00947                 System.out.println("NODE INVARIANT VIOLATED: a");
00948                 System.out.println("node.label: " + node.label);
00949                 System.out.println("node.edgeLabels: " + node.edgeLabels);
00950             }
00951             if (!b) System.out.println("NODE INVARIANT VIOLATED: b");
00952             if (!c) System.out.println("NODE INVARIANT VIOLATED: c");
00953         }
00954 
00955         if (!b) {
00956             System.out.println("node: " + node + "   |  " 
00957                                + (SortedIntList)conflictSets.get(node.conflictSetIndex)
00958                 + "   conflictSetIndex: " + node.conflictSetIndex);
00959             System.out.print("attemptedPruneNode: ");
00960             if (attemptedPruneNode != null) {
00961                 System.out.print("" + attemptedPruneNode);
00962                 System.out.println("   conflictSetIndex: " + attemptedPruneNode.conflictSetIndex);
00963                 System.out.println(conflictSets.get(attemptedPruneNode.conflictSetIndex));
00964             } else System.out.println("null");
00965         }
00966 
00967         return result; 
00968                  
00969                 
00970 
00971 
00972     }
00973 }
00974 
00975 
00976 class EdgeNodePair {
00977 
00978     public int edge = -1;
00979 
00980     public HSNode node;
00981 
00982     public EdgeNodePair(int edge, HSNode node) {
00983         this.edge = edge;
00984         this.node = node;
00985     }
00986 
00987 }
00988 
00989 
00990 class HSNode {
00991 
00992     final static int STATE_OPEN = 0;  
00993     final static int STATE_CLOSED = 1;  
00994     final static int STATE_MINIMAL = 2;  
00995     final static int STATE_PRUNED = 3;  
00996 
00997     int state = STATE_OPEN;
00998 
00999     
01000     SortedIntList edgeLabels;  
01001     
01002     
01003     ArrayList parents = new ArrayList();
01004     
01005     
01006     ArrayList children = new ArrayList();
01007 
01008     SortedIntList label;
01009    
01010     
01011     int conflictSetIndex = -1;
01012 
01013     
01014     
01015     boolean relevantForPruning = true;
01016 
01017     public String toString() {
01018 
01019         String result = "{" + edgeLabels + "}; ";
01020         
01021         if ((state == STATE_OPEN) || (state == STATE_PRUNED)) {
01022             if (label == null) result = result + "{??}";
01023             else {
01024                 result = result + "{" + label + "}";
01025             }
01026             if (state == STATE_PRUNED) result = result + "  PRUNED";
01027         } 
01028         else if (state == STATE_CLOSED) {
01029             result = result + "X";
01030         } else if (state == STATE_MINIMAL) {
01031             result = result + "!!!";
01032         }
01033 
01034         result = result + " csIndex: " + conflictSetIndex;
01035 
01036         result = result + "  #(parents): " + parents.size() 
01037             + "  #(children): " + children.size();
01038 
01039         return result;
01040     }
01041 
01042 
01043 }