ExplorerController.java
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
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 }