Generated on Fri Oct 6 16:26:43 2006 for Gecode/J by doxygen 1.4.7

ExplorerController.java

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Mikael Lagerkvist <lagerkvist@gecode.org>
00004  *     Guido Tack <tack@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Mikael Lagerkvist, 2006
00008  *     Guido Tack, 2006
00009  *
00010  *  Last modified:
00011  *     $Date: 2006-09-26 17:05:54 +0200 (Tue, 26 Sep 2006) $ by $Author: tack $
00012  *     $Revision: 3707 $
00013  *
00014  *  This file is part of Gecode, the generic constraint
00015  *  development environment:
00016  *     http://www.gecode.org
00017  *
00018  *  See the file "LICENSE" for information on usage and
00019  *  redistribution of this file, and for a
00020  *     DISCLAIMER OF ALL WARRANTIES.
00021  *
00022  */
00023 
00024 package org.gecode.explorer;
00025 
00026 import org.gecode.*;
00027 import org.gecode.explorer.postscript.*;
00028 import java.util.Hashtable;
00029 import java.util.Enumeration;
00030 import java.io.File;
00031 
00032 public class ExplorerController
00033     implements StatisticsListener {
00034 
00035     private Space _rootSpace;
00036     private boolean _bab;
00037 
00038     private SpaceNode _root;
00039     private SpaceNode _currentNode;
00040 
00041     private ExplorerUIInterface _ui;
00042 
00043     private Statistics _stats;
00044     private int breakAfterSolutions = 0;
00045     private int solutionsSinceBreak = 0;
00046     private int breakAfterNodes = 0;
00047     private int nodesSinceBreak = 0;
00048     private boolean cancelSearch = false;
00049 
00050     private Hashtable<String, ExplorerEventListener> _actionTable;
00051     private String _selectedAction;
00052 
00053     public ExplorerController(Space rootSpace, boolean bab) {
00054         _rootSpace = rootSpace;
00055         _bab = bab;
00056         _stats = new Statistics();
00057         _stats.registerSolutionListener(this);
00058         _actionTable = new Hashtable<String, ExplorerEventListener>();
00059         _selectedAction = "default";
00060         if (rootSpace instanceof ExplorerEventListener) {
00061             ExplorerEventListener e = (ExplorerEventListener) rootSpace;
00062             _actionTable.put(e.getName(), e);
00063             _selectedAction=e.getName();
00064         }
00065     }
00066 
00067     public void selectInspectionAction(String action) {
00068         _selectedAction = action;
00069     }
00070     public String getSelectedAction() {
00071         return _selectedAction;
00072     }
00073     public Enumeration<String> getListeners() {
00074         return _actionTable.keys();
00075     }
00076 
00077     public void registerUI(ExplorerUIInterface ui) {
00078         _ui = ui;
00079         _rootSpace.status(new long[1]);
00080         if (_rootSpace.failed()) {
00081             _root = ui.createRoot(_rootSpace, _bab, _stats);
00082         } else {
00083             _root = ui.createRoot(_rootSpace.cloneSpace(), _bab, _stats);
00084         }
00085         _currentNode = _root;
00086         _root.layout();
00087     }
00088 
00089     public void exploreOne() {
00090         breakAfterSolutions = 1;
00091         solutionsSinceBreak = 0;
00092         breakAfterNodes = Config.searchCutoff();
00093         nodesSinceBreak = 0;
00094         cancelSearch = false;
00095         DFS dfs = new DFS();
00096         dfs.setup(_currentNode);
00097         while ( (!dfs.step()) && (!cancelSearch) );
00098         searchDone();
00099     }
00100 
00101     public void exploreAll() {
00102         breakAfterSolutions = 0;
00103         breakAfterNodes = Config.searchCutoff();
00104         nodesSinceBreak = 0;
00105         cancelSearch = false;
00106         DFS dfs = new DFS();
00107         dfs.setup(_currentNode);
00108         while ( (!dfs.step()) && (!cancelSearch) );
00109         searchDone();
00110     }
00111 
00112     public void exploreN() {
00113         breakAfterSolutions = Config.n();
00114         solutionsSinceBreak = 0;
00115         breakAfterNodes = Config.searchCutoff();
00116         nodesSinceBreak = 0;
00117         cancelSearch = false;
00118         DFS dfs = new DFS();
00119         dfs.setup(_currentNode);
00120         while ( (!dfs.step()) && (!cancelSearch) );
00121         searchDone();
00122     }
00123 
00124     public void reset() {
00125         _stats.reset();
00126         if (_rootSpace.failed()) {
00127             _root = _ui.createRoot(_rootSpace, _bab, _stats);
00128         } else {
00129             _root = _ui.createRoot(_rootSpace.cloneSpace(), _bab, _stats);
00130         }
00131         _currentNode = _root;
00132         _root.dirtyUp();
00133         stateChanged();
00134     }
00135 
00136     public void saveAs() {
00137         File file = _ui.saveFilename();
00138         if (file != null) {
00139             String fn = file.getName().toLowerCase();
00140             if (! (fn.endsWith(".eps") || fn.endsWith(".ps") ) ) {
00141                 file = new File(file.getParentFile(), fn+".eps");
00142             }
00143             if (file.exists() && ! _ui.overwriteDialog() ) {
00144                 return;
00145             }
00146             try {
00147                 Postscript.saveAs(_root,file);
00148             } catch (java.io.IOException e) {
00149                 _ui.reportError("Error",
00150                                 "Error while saving postscript file:\n"
00151                                         +e.getMessage());
00152             }
00153         }
00154     }
00155     
00156     public void addEventListener(ExplorerEventListener e) {
00157         _actionTable.put(e.getName(), e);
00158         _selectedAction=e.getName();
00159         _ui.updateEventListeners();
00160     }
00161 
00162     public void setCurrentNode(SpaceNode c) {
00163         _currentNode = c;
00164         _ui.setCurrentNode(c);
00165         switch (_currentNode.getStatus()) {
00166         case FAILED :
00167             _ui.menuInspectActive(false, _currentNode.isRoot(), true);
00168             _ui.menuSearchActive(false);
00169             _ui.menuHideNodeActive(false, false);
00170             _ui.menuUnhideAllActive(false);
00171             _ui.menuHideFailedActive(false);
00172             break;
00173         case SOLVED:
00174             _ui.menuInspectActive(true, _currentNode.isRoot(), true);
00175             _ui.menuSearchActive(false);
00176             _ui.menuHideNodeActive(false, false);
00177             _ui.menuUnhideAllActive(false);
00178             _ui.menuHideFailedActive(false);
00179             break;
00180         case UNDETERMINED :
00181             _ui.menuInspectActive(true, _currentNode.isRoot(), false);
00182             _ui.menuSearchActive(true);
00183             _ui.menuHideNodeActive(false, false);
00184             _ui.menuUnhideAllActive(false);
00185             _ui.menuHideFailedActive(false);
00186             break;
00187         default:
00188             _ui.menuInspectActive(!_currentNode.isHidden(), 
00189                                   _currentNode.isRoot(), false);
00190             _ui.menuSearchActive(!_currentNode.isHidden() &&
00191                                  _currentNode.isOpen());
00192             _ui.menuHideNodeActive(true, _currentNode.isHidden());
00193             _ui.menuUnhideAllActive(true);
00194             _ui.menuHideFailedActive(!_currentNode.isHidden());
00195             break;
00196         }
00197     }
00198 
00199     public SpaceNode getCurrentNode() {
00200         return _currentNode;
00201     }
00202 
00203     private void invokeAction(SpaceNode node) {
00204         if (_selectedAction.equals("default")) {
00205             _ui.inspect(node.getSpace().toString());
00206         } else {
00207             ExplorerEventListener el = _actionTable.get(_selectedAction);
00208             if (el != null) {
00209                 el.nodeClickEvent(_ui, node);
00210             }
00211         }
00212     }
00213 
00214     public void inspect() {
00215         if (_currentNode.isHidden()) {
00216             toggleHidden();
00217             return;
00218         }
00219         switch (_currentNode.getStatus()) {
00220         case UNDETERMINED:
00221             {
00222                 DFS dfs = new DFS();
00223                 dfs.setup(_currentNode);
00224                 dfs.step();
00225                 stateChanged();
00226                 break;
00227             }
00228         case FAILED:
00229             break;
00230         default:
00231             invokeAction(_currentNode);
00232             break;
00233         }
00234 
00235     }
00236 
00237     public void inspectBranches() {
00238         if (_currentNode.isHidden()) {
00239             toggleHidden();
00240             return;
00241         }
00242         switch (_currentNode.getStatus()) {
00243         case FAILED :
00244             break;
00245         case SOLVED:
00246             inspect();
00247             break;
00248         case UNDETERMINED:
00249             {
00250                 DFS dfs = new DFS();
00251                 dfs.setup(_currentNode);
00252                 dfs.step();
00253                 stateChanged();
00254                 inspectBranches();
00255                 break;
00256             }
00257         default:
00258             {
00259                 String out = "";
00260                 Space s = _currentNode.getSpace();
00261                 s.status(new long[1]);
00262                 long alt = s.description().alternatives();
00263                 out += "There are " + alt + " branches available:\n";
00264                 for (int i = 0; i < alt; ++i) {
00265                     out += "Branch " + i + "\n";
00266                     Space v = s.cloneSpace();
00267                     v.status(new long[1]);
00268                     BranchingDesc desc = v.description();
00269                     v.commit(desc, i);
00270                     out += "\t" + v.toString().replaceAll("\n", "\n\t").trim() + "\n";
00271                 }
00272                 _ui.inspect(out);
00273                 break;
00274             }
00275         }       
00276     }
00277 
00278     public void inspectBeforePropagation() {
00279         if (_currentNode == _root) return;
00280         if (_currentNode.isHidden()) {
00281             toggleHidden();
00282             return;
00283         }
00284         switch (_currentNode.getStatus()) {
00285         case UNDETERMINED:
00286             {
00287                 DFS dfs = new DFS();
00288                 dfs.setup(_currentNode);
00289                 dfs.step();
00290                 stateChanged();
00291                 inspectBeforePropagation();
00292                 break;
00293             }
00294         default:
00295             {
00296                 String out = "Before propagation:\n";
00297                 Space s = ((SpaceNode)_currentNode.getParent()).getSpace();
00298                 s.status(new long[1]); 
00299                 BranchingDesc desc = s.description();
00300                 s.commit(desc, _currentNode.getAlternative());
00301                 out += "\t" + s.toString().replaceAll("\n", "\n\t").trim() + "\n";
00302                 _ui.inspect(out);
00303                 break;
00304             }
00305         }       
00306     }
00307 
00312     public int[] getStatistics() {
00313         int[] res = new int[5];
00314 
00315         res[0] = _stats.getSolutions();
00316         res[1] = _stats.getFailures();
00317         res[2] = _stats.getChoices();
00318         res[3] = _stats.getUndetermined();
00319         res[4] = _stats.getDepth();
00320 
00321         return res;
00322     }
00323     
00324     public SpaceNode getRoot() {
00325         return _root;
00326     }
00327 
00328     public void toggleHidden() {
00329         _currentNode.toggleHidden();
00330         stateChanged();
00331     }
00332     public void hideFailed() {
00333         _currentNode.hideFailed();
00334         stateChanged();
00335     }
00336     public void unhideAll() {
00337         _currentNode.unhideAll();
00338         stateChanged();
00339     }
00340 
00341     public void newSolution(int solutions) {
00342         solutionsSinceBreak++;
00343         if (breakAfterSolutions != 0 &&
00344             solutionsSinceBreak>=breakAfterSolutions)
00345             cancelSearch = true;
00346     }
00347 
00348     public void newNode() {
00349         nodesSinceBreak++;
00350         if (breakAfterNodes != 0 &&
00351             nodesSinceBreak>=breakAfterNodes)
00352             cancelSearch = true;
00353     }
00354 
00355     public void scaleToFit() {
00356         _ui.scaleToFit();
00357     }
00358 
00359     public void searchDone() {
00360         if (Config.hide())
00361           _currentNode.hideFailed();
00362         stateChanged(); 
00363     }
00364 
00365     private void stateChanged() {
00366         _root.layout();
00367         if (Config.zoom())
00368           _ui.scaleToFit();
00369         _ui.update();
00370         setCurrentNode(_currentNode);
00371     }
00372 
00373 
00374     public void navUp() {
00375         SpaceNode p = (SpaceNode) _currentNode.getParent();
00376         if (p != null)
00377             setCurrentNode(p);
00378     }
00379     public void navDown() {
00380         if (_currentNode.getStatus() == NodeStatus.BRANCH &&
00381             !_currentNode.isHidden())
00382             setCurrentNode((SpaceNode)_currentNode.getChild(0));
00383     }
00384     public void navLeft() {
00385         SpaceNode p = (SpaceNode) _currentNode.getParent();
00386         if (p != null) {
00387             int alt = _currentNode.getAlternative();
00388             if (alt > 0)
00389                 setCurrentNode((SpaceNode) p.getChild(alt-1));
00390         }
00391     }
00392     public void navRight() {
00393         SpaceNode p = (SpaceNode) _currentNode.getParent();
00394         if (p != null) {
00395             int alt = _currentNode.getAlternative();
00396             if (alt + 1 < p.getNumberOfChildren())
00397                 setCurrentNode((SpaceNode) p.getChild(alt+1));
00398         }
00399     }
00400 
00401     private void findNextSolution(SpaceNode current) {
00402         SpaceNode p = current;
00403         int alt;
00404         while (true) {
00405             if (p.getStatus() == NodeStatus.SOLVED) {
00406                 setCurrentNode(p);
00407                 return;
00408             } else if (p.hasSolvedChildren()) {
00409                 p = (SpaceNode) p.getChild(0);
00410             } else if (p.getParent() != null) {
00411                 SpaceNode pp = (SpaceNode)p.getParent();
00412                 alt = p.getAlternative();
00413                 if (alt + 1 < pp.getNumberOfChildren()) {
00414                     p = (SpaceNode)pp.getChild(alt+1);
00415                 } else {
00416                     return;
00417                 }
00418             } else {
00419                 return;
00420             }
00421         }
00422     }
00423 
00424     public void jumpNextSol() {
00425 
00426         if (_currentNode.getStatus() != NodeStatus.SOLVED &&
00427             _currentNode.hasSolvedChildren()) {
00428             findNextSolution(_currentNode);
00429         }
00430 
00431         SpaceNode p = (SpaceNode) _currentNode.getParent();
00432         int alt = _currentNode.getAlternative();
00433         while (p != null) {
00434             if (alt + 1 < p.getNumberOfChildren() &&
00435                 ((SpaceNode)p.getChild(alt+1)).hasSolvedChildren() ) {
00436                 p = (SpaceNode) p.getChild(alt+1);              
00437                 findNextSolution(p);
00438                 return;
00439             } else {
00440                 alt = p.getAlternative();
00441                 p = (SpaceNode) p.getParent();
00442             }
00443         }
00444     }
00445     public void jumpPrevSol() {
00446         SpaceNode p = (SpaceNode) _currentNode.getParent();
00447         int alt = _currentNode.getAlternative();
00448         while (p != null) {
00449             if (alt > 0 &&
00450                 ((SpaceNode)p.getChild(alt-1)).hasSolvedChildren() ) {
00451                 
00452                 p = (SpaceNode) p.getChild(alt-1);
00453 
00454                 while (true) {
00455                     if (p.getStatus() == NodeStatus.SOLVED) {
00456                         setCurrentNode(p);
00457                         return;
00458                     } else if (p.hasSolvedChildren()) {
00459                         p = (SpaceNode) p.getChild(p.getNumberOfChildren()-1);
00460                     } else if (p.getParent() != null) {
00461                         SpaceNode pp = (SpaceNode)p.getParent();
00462                         alt = p.getAlternative();
00463                         if (alt > 0) {
00464                             p = (SpaceNode)pp.getChild(alt-1);
00465                         } else {
00466                             return;
00467                         }
00468                     } else {
00469                         return;
00470                     }
00471                 }
00472             } else {
00473                 alt = p.getAlternative();
00474                 p = (SpaceNode) p.getParent();
00475             }
00476         }
00477 
00478     }
00479 
00480     public void jumpRoot() {
00481         setCurrentNode(_root);
00482     }
00483     public void jumpLeftmost() {
00484         SpaceNode p = _root;
00485         while (p.getNumberOfChildren() > 0) {
00486             p = (SpaceNode) p.getChild(0);
00487         }
00488         setCurrentNode(p);
00489     }
00490     public void jumpRightmost() {
00491         SpaceNode p = _root;
00492         while (p.getNumberOfChildren() > 0) {
00493             p = (SpaceNode) p.getChild(p.getNumberOfChildren()-1);
00494         }
00495         setCurrentNode(p);
00496     }
00497     
00498     public void centerCursor() {
00499         _ui.centerCursor();
00500     }
00501 }