package aima.gui.fx.applications.search; import java.util.Arrays; import java.util.List; import aima.core.search.csp.*; import aima.core.search.csp.examples.MapCSP; import aima.core.search.csp.inference.AC3Strategy; import aima.core.search.csp.inference.ForwardCheckingStrategy; import aima.gui.fx.framework.IntegrableApplication; import aima.gui.fx.framework.Parameter; import aima.gui.fx.framework.SimulationPaneBuilder; import aima.gui.fx.framework.SimulationPaneCtrl; import aima.gui.fx.views.CspViewCtrl; import javafx.application.Platform; import javafx.scene.layout.BorderPane; import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; /** * Application which demonstrates basic constraint algorithms based on map * coloring problems. It shows the constraint graph, lets the user select a * solution strategy, and allows then to follow the progress step by step. * * @author Ruediger Lunde */ public class MapColoringCspApp extends IntegrableApplication { public static void main(String[] args) { launch(args); } private final static String PARAM_MAP = "map"; private final static String PARAM_STRATEGY = "strategy"; private CspViewCtrl<Variable, String> stateViewCtrl; private SimulationPaneCtrl simPaneCtrl; private CSP<Variable, String> csp; private CspSolver<Variable, String> strategy; private int stepCounter; public MapColoringCspApp() { } @Override public String getTitle() { return "Map Coloring CSP App"; } /** * Defines state view, parameters, and call-back functions and calls the * simulation pane builder to create layout and controller objects. */ @Override public Pane createRootPane() { BorderPane root = new BorderPane(); StackPane stateView = new StackPane(); stateViewCtrl = new CspViewCtrl<>(stateView); List<Parameter> params = createParameters(); SimulationPaneBuilder builder = new SimulationPaneBuilder(); builder.defineParameters(params); builder.defineStateView(stateView); builder.defineInitMethod(this::initialize); builder.defineSimMethod(this::simulate); simPaneCtrl = builder.getResultFor(root); return root; } protected List<Parameter> createParameters() { Parameter p1 = new Parameter(PARAM_MAP, "Map of Australia", "Map of Australia NSW=BLUE (for LCV)", "Map of Australia WA=RED (for LCV)"); Parameter p2 = new Parameter(PARAM_STRATEGY, "Backtracking", "Backtracking + DEG", "Backtracking + Forward Checking", "Backtracking + Forward Checking + MRV", "Backtracking + Forward Checking + LCV", "Backtracking + AC3", "Backtracking + AC3 + MRV & DEG + LCV", "Min-Conflicts (50)"); return Arrays.asList(p1, p2); } /** * Displays the selected function on the state view. */ @Override public void initialize() { csp = null; switch (simPaneCtrl.getParamValueIndex(PARAM_MAP)) { case 0: csp = new MapCSP(); break; case 1: // three moves csp = new MapCSP(); csp.setDomain(MapCSP.NSW, new Domain<>(MapCSP.BLUE)); break; case 2: // three moves csp = new MapCSP(); csp.setDomain(MapCSP.WA, new Domain<>(MapCSP.RED)); break; } stateViewCtrl.clearMappings(); int c = 15; stateViewCtrl.setPositionMapping(MapCSP.WA, c*5, c*10); stateViewCtrl.setPositionMapping(MapCSP.NT, c*15, c*3); stateViewCtrl.setPositionMapping(MapCSP.SA, c*20, c*15); stateViewCtrl.setPositionMapping(MapCSP.Q, c*30, c*5); stateViewCtrl.setPositionMapping(MapCSP.NSW, c*35, c*15); stateViewCtrl.setPositionMapping(MapCSP.V, c*30, c*23); stateViewCtrl.setPositionMapping(MapCSP.T, c*33, c*30); stateViewCtrl.setColorMapping(MapCSP.RED, Color.RED); stateViewCtrl.setColorMapping(MapCSP.GREEN, Color.GREEN); stateViewCtrl.setColorMapping(MapCSP.BLUE, Color.BLUE); switch (simPaneCtrl.getParamValueIndex(PARAM_STRATEGY)) { case 0: strategy = new FlexibleBacktrackingSolver<>(); break; case 1: // DEG strategy = new FlexibleBacktrackingSolver<Variable, String>().set(CspHeuristics.deg()); break; case 2: // FC strategy = new FlexibleBacktrackingSolver<Variable, String>().set(new ForwardCheckingStrategy<>()); break; case 3: // MRV + FC strategy = new FlexibleBacktrackingSolver<Variable, String>().set(CspHeuristics.mrvDeg()) .set(new ForwardCheckingStrategy<>()); break; case 4: // LCV + FC strategy = new FlexibleBacktrackingSolver<Variable, String>().set(CspHeuristics.lcv()) .set(new ForwardCheckingStrategy<>()); break; case 5: // AC3 strategy = new FlexibleBacktrackingSolver<Variable, String>().set(new AC3Strategy<>()); break; case 6: // MRV & DEG + LCV + AC3 strategy = new FlexibleBacktrackingSolver<Variable, String>().setAll(); break; case 7: strategy = new MinConflictsSolver<>(50); break; } strategy.addCspListener((csp1, assignment) -> { stepCounter++; updateStateView(csp1, assignment); }); stateViewCtrl.initialize(csp); } @Override public void cleanup() { simPaneCtrl.cancelSimulation(); } /** * Starts the experiment. */ public void simulate() { stepCounter = 0; strategy.solve(csp); } /** * Caution: While the background thread should be slowed down, updates of * the GUI have to be done in the GUI thread! */ private void updateStateView(CSP<Variable, String> csp, Assignment<Variable, String> assignment) { Platform.runLater(() -> updateStateViewLater(csp, assignment)); simPaneCtrl.waitAfterStep(); } /** * Must be called by the GUI thread! */ private void updateStateViewLater(CSP<Variable, String> csp, Assignment<Variable, String> assignment) { stateViewCtrl.update(csp, assignment); String txt1 = "Step " + stepCounter + ": "; String txt2 = "Domain reduced"; if (assignment != null) txt2 = assignment.toString() + (assignment.isSolution(csp) ? " (Solution)" : ""); simPaneCtrl.setStatus(txt1 + txt2); } }