Generated on Thu Nov 2 14:49:35 2006 for Gecode/J by doxygen 1.5.0

SpaceNode.java

Go to the documentation of this file.
00001 /* -*- indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Marco Kuhlmann <kuhlmann@ps.uni-sb.de>
00005  *     Guido Tack <tack@gecode.org>
00006  *
00007  *  Contributing authors:
00008  *     Mikael Lagerkvist <lagerkvist@gecode.org>
00009  *
00010  *  Copyright:
00011  *     Marco Kuhlmann, 2005
00012  *     Guido Tack, 2006
00013  *
00014  *  Last modified:
00015  *     $Date: 2006-10-26 11:31:58 +0200 (Thu, 26 Oct 2006) $ by $Author: tack $
00016  *     $Revision: 3796 $
00017  *
00018  *  This file is part of Gecode, the generic constraint
00019  *  development environment:
00020  *     http://www.gecode.org
00021  *
00022  *  See the file "LICENSE" for information on usage and
00023  *  redistribution of this file, and for a
00024  *     DISCLAIMER OF ALL WARRANTIES.
00025  *
00026  */
00027 
00028 package org.gecode.gist;
00029 
00030 import java.util.*;
00031 import org.gecode.*;
00032 
00033 public abstract class SpaceNode extends VisualNode {
00034 
00035     class Branch {
00036         int alternative;
00037         BranchingDesc desc;
00038         Space ownBest = null;
00039         Branch(int a, BranchingDesc d) {
00040             alternative = a;
00041             desc = d;
00042         }
00043         Branch(int a, BranchingDesc d, Space best) {
00044             alternative = a;
00045             desc = d;
00046             ownBest = best;
00047         }
00048     }
00049 
00050     protected Statistics stats;
00051     
00052     private Space copy;
00053     public Space workingSpace;
00054 
00055     private BranchingDesc desc;
00056     private int alternative;
00057     private NodeStatus status = NodeStatus.UNDETERMINED;
00058     
00059     public BestSpace curBest = null;
00060     private Space ownBest = null;
00061 
00062     private int noOfOpenChildren = 0;
00063     private boolean hasFailedChildren = false;
00064     private boolean hasSolvedChildren = false;
00065     
00066     public SpaceNode(int alt, Statistics theStats) {
00067         super();
00068         alternative = alt;
00069         stats = theStats;
00070     }
00071     
00072     public SpaceNode(int alt, BestSpace best, Statistics theStats) {
00073         super();
00074         alternative = alt;
00075         curBest = best;
00076         stats = theStats;
00077     }
00078 
00079     public SpaceNode(Space root, Statistics theStats) {
00080         super();
00081         workingSpace = root;
00082         if (!root.failed()) {
00083             copy = root.cloneSpace();
00084         } else {
00085             copy = root;
00086         }
00087         stats = theStats;
00088     }
00089 
00090     public void initCurBest(BestSpace c) {
00091             curBest = c;
00092     }
00093         
00094     protected int recompute() {
00095             int rdist = 0;
00096             if (workingSpace == null) {
00097             SpaceNode curNode = this;
00098             Stack<Branch> stack = new Stack<Branch>();
00099 
00100             while (curNode.copy==null) {
00101                 SpaceNode parent = (SpaceNode)curNode.getParent();
00102                 Branch b;
00103                 if (curBest != null) {
00104                         b = new Branch(curNode.alternative, parent.desc, curNode.ownBest);
00105                 } else {
00106                         b = new Branch(curNode.alternative, parent.desc);
00107                 }
00108                 stack.push(b);
00109                 curNode = parent;
00110                 rdist++;
00111             }
00112             Space curSpace = curNode.copy.cloneSpace();
00113 
00114             Space lastBest = null;
00115             SpaceNode middleNode = curNode;
00116             int curDist = 0;
00117             while (!stack.empty()) {
00118                 if (Config.a_d() >= 0 && 
00119                     curDist > Config.a_d() && 
00120                     curDist == rdist / 2) {
00121                     middleNode.copy = curSpace.cloneSpace();
00122                 }
00123                 Branch b = (Branch)stack.pop();
00124                 curSpace.commit(b.desc, b.alternative);
00125 
00126                 if (b.ownBest != lastBest && b.ownBest != null) {
00127                     curSpace.constrain(b.ownBest);
00128                     lastBest = b.ownBest;
00129                 }
00130                 curDist++;
00131                 middleNode = (SpaceNode) middleNode.getChild(b.alternative);
00132             }
00133             workingSpace = curSpace;
00134         }
00135             return rdist;
00136     }
00137 
00138     private Space donateSpace(int alt, Space ownBest) {
00139         Space ret = workingSpace;
00140         if (ret != null) {            
00141             workingSpace = null;
00142             ret.commit(desc, alt);
00143 
00144             if (ownBest != null) {
00145                 ret.constrain(ownBest);
00146             }
00147         }
00148         return ret;
00149     }
00150     
00151     private Space checkLAO(int alt, Space ownBest) {
00152         Space ret = null;
00153             if (copy != null && noOfOpenChildren == 1 && getParent() != null) {
00154             // last alternative optimization
00155             ret = copy;
00156             copy = null;
00157             ret.commit(desc, alt);
00158 
00159             if (ownBest != null) {
00160                 ret.constrain(ownBest);
00161             }
00162             }
00163             return ret;
00164     }
00165     
00166     protected void acquireSpace() {
00167             SpaceNode p = (SpaceNode) getParent();
00168         if (status==Undetermined && curBest != null && ownBest == null && 
00169             p != null && curBest.s != p.ownBest) {
00170                 ownBest = curBest.s;
00171         }
00172             if (workingSpace == null && p != null)
00173             workingSpace = p.donateSpace(alternative, ownBest);
00174         if (workingSpace == null) {
00175                 if ( recompute() > Config.mrd() && Config.mrd() >= 0 &&
00176                      workingSpace.status(new long[1]) == SpaceStatus.SS_BRANCH ) {
00177                     copy = workingSpace.cloneSpace();
00178             }
00179         }
00180         if (copy == null && p != null) {
00181             copy = p.checkLAO(alternative, ownBest);
00182         }
00183     }
00184 
00185     public Space getSpace() {
00186             acquireSpace();
00187             if (workingSpace.status(new long[1]) != SpaceStatus.SS_FAILED) {
00188             return workingSpace.cloneSpace();
00189             }
00190             return workingSpace;
00191     }
00192     
00193     private void solveUp() {
00194         SpaceNode p = (SpaceNode)getParent();
00195         hasSolvedChildren = true;
00196         if (p != null && !p.hasSolvedChildren)
00197             p.solveUp();
00198     }
00199     void closeChild(boolean hadFailures, boolean hadSolutions) {
00200             noOfOpenChildren--;
00201         hasFailedChildren = hasFailedChildren || hadFailures;
00202         hasSolvedChildren = hasSolvedChildren || hadSolutions;
00203             SpaceNode p = (SpaceNode)getParent();
00204             if (noOfOpenChildren == 0) {
00205             stats.close();
00206             if (p != null)
00207                 p.closeChild(hasFailedChildren, hasSolvedChildren);
00208         } else if (hadSolutions) {
00209             solveUp();
00210         }
00211     }
00212 
00213     public void hideFailed() {
00214         DefaultNodeCursor cursor =
00215             new DefaultNodeCursor(this) {
00216                 public boolean mayMoveDownwards() {
00217                     SpaceNode snode = (SpaceNode) getCurrentNode();
00218                     return
00219                         super.mayMoveDownwards() &&
00220                         (snode.hasSolvedChildren ||
00221                          snode.noOfOpenChildren > 0);
00222                 }
00223                 public void processCurrentNode() {
00224                     SpaceNode snode = (SpaceNode) getCurrentNode();
00225                     if (snode.getStatus() == NodeStatus.BRANCH &&
00226                         !snode.hasSolvedChildren &&
00227                         snode.noOfOpenChildren == 0)
00228                         snode.hide();
00229                 }
00230             };
00231         PreOrderNodeVisitor visitor = new PreOrderNodeVisitor(cursor);
00232         visitor.run();
00233     }
00234     
00235     public Iterator reversedChildrenIterator() {
00236         // only needed for the sake of the side effect
00237         int numberNotNeeded = getNumberOfChildNodes();
00238         return super.reversedChildrenIterator();
00239     }
00240     
00241     public int getNumberOfChildNodes() {
00242         int kids = getNumberOfChildren();
00243         if (kids == -1) {
00244             stats.newDetermined();
00245             acquireSpace();
00246             status = NodeStatus.valueOf(workingSpace.status());
00247             switch (status) {
00248             case FAILED:
00249                 workingSpace.delete();
00250                 workingSpace = null;
00251                 kids = 0;
00252                 hasSolvedChildren = false;
00253                 hasFailedChildren = true;
00254                 stats.newFailure();
00255                 stats.newDepth(getDepth());
00256                 if (getParent() != null)
00257                     ((SpaceNode)getParent()).closeChild(true,false);
00258                 break;
00259             case SOLVED:
00260                 kids = 0;
00261                 hasSolvedChildren = true;
00262                 hasFailedChildren = false;
00263                 stats.newSolution();
00264                 stats.newDepth(getDepth());
00265                     if (curBest != null) {
00266                     curBest.s = workingSpace.cloneSpace();
00267                     }
00268                 if (getParent() != null)
00269                     ((SpaceNode)getParent()).closeChild(false,true);
00270                 break;
00271             case BRANCH:
00272                 desc = workingSpace.description();
00273                 kids = (int) desc.alternatives();
00274                 stats.newChoice();
00275                 stats.newOpen();
00276                 stats.newUndetermined(kids);
00277                 stats.newDepth(getDepth() + 1);
00278                 break;
00279             }
00280             setNumberOfChildren(kids);
00281             noOfOpenChildren = kids;
00282             dirtyUp();
00283             for (int i = 0; i < kids; i++) {
00284                 SpaceNode child = createChild(i);
00285                 setNextChild(i, child);
00286                 child.dirtyUp();
00287             }
00288         }
00289         return kids;
00290     }
00291 
00292     public NodeStatus getStatus() {
00293         return status;
00294     }
00295     public void setStatus(NodeStatus s) {
00296         status = s;
00297     }
00298 
00299     public boolean isOpen() {
00300         return status==Undetermined || noOfOpenChildren > 0;
00301     }
00302 
00303     public boolean hasFailedChildren() {
00304         return hasFailedChildren;
00305     }
00306     public boolean hasSolvedChildren() {
00307         return hasSolvedChildren;
00308     }
00309 
00310     protected abstract SpaceNode createChild(int i);
00311 
00312     protected int getAlternative() {
00313         return alternative;
00314     }
00315 }