001 package aima.gui.applications.search.map; 002 003 import java.util.ArrayList; 004 005 import aima.gui.framework.AgentAppController; 006 import aima.gui.framework.AgentAppFrame; 007 import aima.gui.framework.AgentAppModel; 008 import aima.gui.framework.SimpleAgentAppDemo; 009 import aima.search.framework.SearchFactory; 010 import aima.search.map.AdaptableHeuristicFunction; 011 import aima.search.map.ExtendableMap; 012 import aima.search.map.MapAgent; 013 import aima.search.map.MapEnvironment; 014 import aima.search.map.Point2D; 015 import aima.search.map.Scenario; 016 import aima.search.map.SimplifiedRoadMapOfAustralia; 017 import aima.search.map.SimplifiedRoadMapOfPartOfRomania; 018 019 /** 020 * Demo example of a route planning agent application with GUI. The main method 021 * starts a map agent frame and supports runtime experiments. This 022 * implementation is based on the {@link aima.search.map.MapAgent} and the 023 * {@link aima.search.map.MapEnvironment}. It can be used 024 * as a code template for creating new applications with different specialized 025 * kinds of agents and environments. 026 * 027 * @author R. Lunde 028 */ 029 public class RoutePlanningAgentAppDemo extends SimpleAgentAppDemo { 030 031 /** Creates a <code>MapAgentModel</code>. */ 032 @Override 033 public AgentAppModel createModel() { 034 return new MapAgentModel(); 035 } 036 037 /** Creates and configures a <code>RoutePlanningAgentFrame</code>. */ 038 @Override 039 public AgentAppFrame createFrame() { 040 return new RoutePlanningAgentFrame(); 041 } 042 043 /** Creates a <code>RoutePlanningAgentController</code>. */ 044 @Override 045 public AgentAppController createController() { 046 return new RoutePlanningAgentController(); 047 } 048 049 // ////////////////////////////////////////////////////////// 050 // local classes 051 052 /** Frame for a graphical route planning agent application. */ 053 protected static class RoutePlanningAgentFrame extends MapAgentFrame { 054 public static enum MapType { 055 ROMANIA, AUSTRALIA 056 }; 057 058 private MapType usedMap = null; 059 private static String[] ROMANIA_DESTS = new String[] { 060 "D1 (to Bucharest)", "D2 (to Eforie)", "D3 (to Neamt)", 061 "D4 (to random)" }; 062 private static String[] AUSTRALIA_DESTS = new String[] { 063 "D1 (to Port Hedland)", "D2 (to Albany)", "D3 (to Melbourne)", 064 "D4 (to random)" }; 065 066 /** Creates a new frame. */ 067 public RoutePlanningAgentFrame() { 068 setTitle("RPA - the Route Planning Agent"); 069 setSelectorItems(SCENARIO_SEL, new String[] { 070 "S1 (Romania, from Arad)", "S2 (Romania, from Lugoj)", 071 "S3 (Romania, from Fagaras)", 072 "S4 (Australia, from Sydney)", 073 "S4 (Australia, from Random)" }, 0); 074 setSelectorItems(SEARCH_MODE_SEL, SearchFactory.getInstance() 075 .getSearchModeNames(), 1); // change the default! 076 setSelectorItems(HEURISTIC_SEL, new String[] { "H1 (=0)", 077 "H2 (sld to goal)" }, 1); 078 } 079 080 /** 081 * Changes the destination selector items depending on the scenario 082 * selection if necessary, and calls the super class implementation 083 * afterwards. 084 */ 085 @Override 086 protected void selectionChanged() { 087 SelectionState state = getSelection(); 088 int scenarioIdx = state.getValue(MapAgentFrame.SCENARIO_SEL); 089 RoutePlanningAgentFrame.MapType mtype = (scenarioIdx < 3) ? MapType.ROMANIA 090 : MapType.AUSTRALIA; 091 if (mtype != usedMap) { 092 usedMap = mtype; 093 String[] items = null; 094 switch (mtype) { 095 case ROMANIA: 096 items = ROMANIA_DESTS; 097 break; 098 case AUSTRALIA: 099 items = AUSTRALIA_DESTS; 100 break; 101 } 102 setSelectorItems(DESTINATION_SEL, items, 0); 103 } 104 super.selectionChanged(); 105 } 106 } 107 108 /** Controller for a graphical route planning agent application. */ 109 protected static class RoutePlanningAgentController extends 110 AbstractMapAgentController { 111 /** 112 * Configures a scenario and a list of destinations. Note that for route 113 * planning problems, the size of the list needs to be 1. 114 */ 115 @Override 116 protected void selectScenarioAndDest(int scenarioIdx, int destIdx) { 117 ExtendableMap map = new ExtendableMap(); 118 MapEnvironment env = new MapEnvironment(map); 119 String agentLoc = null; 120 switch (scenarioIdx) { 121 case 0: 122 SimplifiedRoadMapOfPartOfRomania.initMap(map); 123 agentLoc = SimplifiedRoadMapOfPartOfRomania.ARAD; 124 break; 125 case 1: 126 SimplifiedRoadMapOfPartOfRomania.initMap(map); 127 agentLoc = SimplifiedRoadMapOfPartOfRomania.LUGOJ; 128 break; 129 case 2: 130 SimplifiedRoadMapOfPartOfRomania.initMap(map); 131 agentLoc = SimplifiedRoadMapOfPartOfRomania.FAGARAS; 132 break; 133 case 3: 134 SimplifiedRoadMapOfAustralia.initMap(map); 135 agentLoc = SimplifiedRoadMapOfAustralia.SYDNEY; 136 break; 137 case 4: 138 SimplifiedRoadMapOfAustralia.initMap(map); 139 agentLoc = map.randomlyGenerateDestination(); 140 break; 141 } 142 scenario = new Scenario(env, map, agentLoc); 143 144 destinations = new ArrayList<String>(); 145 if (scenarioIdx < 3) { 146 switch (destIdx) { 147 case 0: 148 destinations 149 .add(SimplifiedRoadMapOfPartOfRomania.BUCHAREST); 150 break; 151 case 1: 152 destinations.add(SimplifiedRoadMapOfPartOfRomania.EFORIE); 153 break; 154 case 2: 155 destinations.add(SimplifiedRoadMapOfPartOfRomania.NEAMT); 156 break; 157 case 3: 158 destinations.add(map.randomlyGenerateDestination()); 159 break; 160 } 161 } else { 162 switch (destIdx) { 163 case 0: 164 destinations.add(SimplifiedRoadMapOfAustralia.PORT_HEDLAND); 165 break; 166 case 1: 167 destinations.add(SimplifiedRoadMapOfAustralia.ALBANY); 168 break; 169 case 2: 170 destinations.add(SimplifiedRoadMapOfAustralia.MELBOURNE); 171 break; 172 case 3: 173 destinations.add(map.randomlyGenerateDestination()); 174 break; 175 } 176 } 177 } 178 179 /** 180 * Prepares the model for the previously specified scenario and 181 * destinations. 182 */ 183 @Override 184 protected void prepareModel() { 185 ((MapAgentModel) model).prepare(scenario, destinations); 186 } 187 188 /** 189 * Returns the trivial zero function or a simple heuristic which is 190 * based on straight-line distance computation. 191 */ 192 @Override 193 protected AdaptableHeuristicFunction createHeuristic(int heuIdx) { 194 switch (heuIdx) { 195 case 0: 196 return new H1(); 197 default: 198 return new H2(); 199 } 200 } 201 202 /** 203 * Creates environment and agent, starts the agent and initiates some 204 * text outputs describing the state of the agent. 205 */ 206 @Override 207 protected void startAgent() { 208 if (destinations.size() != 1) { 209 frame.logMessage("Error: This agent requires exact one destination."); 210 return; 211 } 212 frame.logMessage("<route-planning-simulation-protocol>"); 213 frame.logMessage("search: " + search.getClass().getName()); 214 MapEnvironment env = scenario.getEnv(); 215 String goal = destinations.get(0); 216 MapAgent agent = new MapAgent(env, search, new String[] { goal }); 217 if (heuristic != null) { 218 frame 219 .logMessage("heuristic: " 220 + heuristic.getClass().getName()); 221 agent.setHeuristicFunction(heuristic.getAdaptation(goal, 222 scenario.getAgentMap())); 223 } 224 env.addAgent(agent, scenario.getInitAgentLocation()); 225 env.stepUntilDone(); 226 frame.logMessage("</route-planning-simulation-protocol>\n"); 227 } 228 } 229 230 /** 231 * Returns always the heuristic value 0. 232 */ 233 static class H1 extends AdaptableHeuristicFunction { 234 235 public double getHeuristicValue(Object state) { 236 return 0.0; 237 } 238 } 239 240 /** 241 * A simple heuristic which interprets <code>state</code> and 242 * {@link #goal} as location names and uses the straight-line distance 243 * between them as heuristic value. 244 */ 245 static class H2 extends AdaptableHeuristicFunction { 246 247 public double getHeuristicValue(Object state) { 248 double result = 0.0; 249 Point2D pt1 = map.getPosition((String) state); 250 Point2D pt2 = map.getPosition((String) goal); 251 if (pt1 != null && pt2 != null) 252 result = pt1.distance(pt2); 253 return result; 254 } 255 } 256 257 // ////////////////////////////////////////////////////////// 258 // starter method 259 260 /** Application starter. */ 261 public static void main(String args[]) { 262 new RoutePlanningAgentAppDemo().startApplication(); 263 } 264 }