package aima.gui.fx.applications.agent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import aima.core.agent.Agent;
import aima.core.environment.map.ExtendableMap;
import aima.core.environment.map.MapEnvironment;
import aima.core.environment.map.MapFunctionFactory;
import aima.core.environment.map.Scenario;
import aima.core.environment.map.SimpleMapAgent;
import aima.core.environment.map.SimplifiedRoadMapOfAustralia;
import aima.core.environment.map.SimplifiedRoadMapOfPartOfRomania;
import aima.core.search.framework.SearchForActions;
import aima.core.search.framework.evalfunc.HeuristicFunction;
import aima.core.util.CancelableThread;
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.MapEnvironmentViewCtrl;
import aima.gui.util.SearchFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
/**
* Integrable application which demonstrates how different kinds of search
* algorithms perform an a route finding scenario.
*
* @author Ruediger Lunde
*
*/
public class RouteFindingAgentApp extends IntegrableApplication {
public static void main(String[] args) {
launch(args);
}
public static String PARAM_SCENARIO = "scenario";
public static String PARAM_DESTINATION_R = "destinationR";
public static String PARAM_DESTINATION_A = "destinationA";
public static String PARAM_SEARCH = "search";
public static String PARAM_Q_SEARCH_IMPL = "qsearch";
public static String PARAM_HEURISTIC = "heuristic";
private SimulationPaneCtrl simPaneCtrl;
private MapEnvironmentViewCtrl envViewCtrl;
protected MapEnvironment env = null;
protected Agent agent = null;
/** A scenario. */
protected Scenario scenario;
/**
* Some location names. For route finding problems, only one location should
* be specified.
*/
protected List<String> destinations;
/** Search method to be used. */
protected SearchForActions search;
/** Heuristic function to be used when performing informed search. */
protected HeuristicFunction heuristic;
public RouteFindingAgentApp() {
}
@Override
public String getTitle() {
return "Route Finding Agent 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 envView = new StackPane();
envViewCtrl = new MapEnvironmentViewCtrl(envView);
List<Parameter> params = createParameters();
SimulationPaneBuilder builder = new SimulationPaneBuilder();
builder.defineParameters(params);
builder.defineStateView(envView);
builder.defineInitMethod(this::initialize);
builder.defineSimMethod(this::simulate);
simPaneCtrl = builder.getResultFor(root);
return root;
}
protected List<Parameter> createParameters() {
Parameter p1 = new Parameter(PARAM_SCENARIO, "Romania, from Arad", "Romania, from Lugoj",
"Romania, from Fagaras", "Australia, from Sydney", "Australia, from Random");
p1.setValueNames("Romania, from Arad", "Romania, from Lugoj", "Romania, from Fagaras", "Australia, from Sydney",
"Australia, from Random");
Parameter p2r = new Parameter(PARAM_DESTINATION_R, "to Bucharest", "to Eforie", "to Neamt", "to Random");
p2r.setValueNames("to Bucharest", "to Eforie", "to Neamt", "to Random");
p2r.setDependency(PARAM_SCENARIO, "Romania, from Arad", "Romania, from Lugoj", "Romania, from Fagaras");
Parameter p2a = new Parameter(PARAM_DESTINATION_A, "to Port Hedland", "to Albany", "to Melbourne", "to Random");
p2a.setValueNames("to Port Hedland", "to Albany", "to Melbourne", "to Random");
p2a.setDependency(PARAM_SCENARIO, "Australia, from Sydney", "Australia, from Random");
Parameter p3 = new Parameter(PARAM_SEARCH, (Object[]) SearchFactory.getInstance().getSearchStrategyNames());
p3.setDefaultValueIndex(5);
Parameter p4 = new Parameter(PARAM_Q_SEARCH_IMPL, (Object[]) SearchFactory.getInstance().getQSearchImplNames());
p4.setDefaultValueIndex(1);
p4.setDependency(PARAM_SEARCH, "Depth First", "Breadth First", "Uniform Cost", "Greedy Best First", "A*");
Parameter p5 = new Parameter(PARAM_HEURISTIC, "0", "SLD");
p5.setDefaultValueIndex(1);
p5.setDependency(PARAM_SEARCH, "Greedy Best First", "A*", "Recursive Best First",
"Recursive Best First No Loops", "Hill Climbing");
return Arrays.asList(p1, p2r, p2a, p3, p4, p5);
}
/** Is called after each parameter selection change. */
@Override
public void initialize() {
ExtendableMap map = new ExtendableMap();
env = new MapEnvironment(map);
String agentLoc = null;
switch (simPaneCtrl.getParamValueIndex(PARAM_SCENARIO)) {
case 0:
SimplifiedRoadMapOfPartOfRomania.initMap(map);
agentLoc = SimplifiedRoadMapOfPartOfRomania.ARAD;
break;
case 1:
SimplifiedRoadMapOfPartOfRomania.initMap(map);
agentLoc = SimplifiedRoadMapOfPartOfRomania.LUGOJ;
break;
case 2:
SimplifiedRoadMapOfPartOfRomania.initMap(map);
agentLoc = SimplifiedRoadMapOfPartOfRomania.FAGARAS;
break;
case 3:
SimplifiedRoadMapOfAustralia.initMap(map);
agentLoc = SimplifiedRoadMapOfAustralia.SYDNEY;
break;
case 4:
SimplifiedRoadMapOfAustralia.initMap(map);
agentLoc = map.randomlyGenerateDestination();
break;
}
scenario = new Scenario(env, map, agentLoc);
destinations = new ArrayList<>();
if (simPaneCtrl.isParamVisible(PARAM_DESTINATION_R)) {
switch (simPaneCtrl.getParamValueIndex(PARAM_DESTINATION_R)) {
case 0:
destinations.add(SimplifiedRoadMapOfPartOfRomania.BUCHAREST);
break;
case 1:
destinations.add(SimplifiedRoadMapOfPartOfRomania.EFORIE);
break;
case 2:
destinations.add(SimplifiedRoadMapOfPartOfRomania.NEAMT);
break;
case 3:
destinations.add(map.randomlyGenerateDestination());
break;
}
} else if (simPaneCtrl.isParamVisible(PARAM_DESTINATION_A)) {
switch (simPaneCtrl.getParamValueIndex(PARAM_DESTINATION_A)) {
case 0:
destinations.add(SimplifiedRoadMapOfAustralia.PORT_HEDLAND);
break;
case 1:
destinations.add(SimplifiedRoadMapOfAustralia.ALBANY);
break;
case 2:
destinations.add(SimplifiedRoadMapOfAustralia.MELBOURNE);
break;
case 3:
destinations.add(map.randomlyGenerateDestination());
break;
}
}
switch (simPaneCtrl.getParamValueIndex(PARAM_HEURISTIC)) {
case 0:
heuristic = MapFunctionFactory.getZeroHeuristicFunction();
break;
default:
heuristic = MapFunctionFactory.getSLDHeuristicFunction(destinations.get(0), scenario.getAgentMap());
}
search = SearchFactory.getInstance().createSearch(simPaneCtrl.getParamValueIndex(PARAM_SEARCH),
simPaneCtrl.getParamValueIndex(PARAM_Q_SEARCH_IMPL), heuristic);
String goal = destinations.get(0);
agent = new SimpleMapAgent(env.getMap(), search, new String[] { goal });
env.addAgent(agent, scenario.getInitAgentLocation());
env.addEnvironmentView(envViewCtrl);
envViewCtrl.setGoal(goal);
envViewCtrl.initialize(env);
}
/** Starts the experiment. */
public void simulate() {
while (!env.isDone() && !CancelableThread.currIsCanceled()) {
env.step();
simPaneCtrl.waitAfterStep();
}
simPaneCtrl.setStatus(search.getMetrics().toString());
envViewCtrl.notify("pathCost=" + search.getMetrics().get("pathCost"));
}
@Override
public void cleanup() {
simPaneCtrl.cancelSimulation();
}
}