001    package aima.test.search.searches;
002    
003    import junit.framework.TestCase;
004    import aima.basic.BasicEnvironmentView;
005    import aima.search.map.ExtendableMap;
006    import aima.search.map.MapAgent;
007    import aima.search.map.MapEnvironment;
008    import aima.search.uninformed.BidirectionalSearch;
009    
010    /**
011     * @author Ciaran O'Reilly
012     * 
013     */
014    public class BidirectionalSearchTest extends TestCase {
015    
016            StringBuffer envChanges;
017    
018            BidirectionalSearch bidirectionalSearch;
019    
020            @Override
021            public void setUp() {
022    
023                    envChanges = new StringBuffer();
024    
025                    bidirectionalSearch = new BidirectionalSearch();
026            }
027    
028            //
029            // Test IG(A)
030            public void test_A_StartingAtGoal() {
031                    ExtendableMap aMap = new ExtendableMap();
032    
033                    MapEnvironment me = new MapEnvironment(aMap);
034                    MapAgent ma = new MapAgent(me, bidirectionalSearch,
035                                    new String[] { "A" });
036                    me.addAgent(ma, "A");
037                    me.registerView(new BasicEnvironmentView() {
038                            @Override
039                            public void envChanged(String command) {
040                                    envChanges.append(command).append(":");
041                            }
042                    });
043                    me.stepUntilDone();
044    
045                    assertEquals(
046                                    "CurrentLocation=In(A), Goal=In(A):NoOP:METRIC[pathCost]=0.0:METRIC[maxQueueSize]=2:METRIC[queueSize]=0:METRIC[nodesExpanded]=2:NoOP:",
047                                    envChanges.toString());
048    
049                    assertEquals(
050                                    BidirectionalSearch.SearchOutcome.PATH_FOUND_BETWEEN_PROBLEMS,
051                                    bidirectionalSearch.getSearchOutcome());
052            }
053    
054            //
055            // Test IG(A)<->(B)<->(C)
056            public void test_ABC_StartingAtGoal() {
057                    ExtendableMap aMap = new ExtendableMap();
058                    aMap.addBidirectionalLink("A", "B", 5.0);
059                    aMap.addBidirectionalLink("B", "C", 5.0);
060    
061                    MapEnvironment me = new MapEnvironment(aMap);
062                    MapAgent ma = new MapAgent(me, bidirectionalSearch,
063                                    new String[] { "A" });
064                    me.addAgent(ma, "A");
065                    me.registerView(new BasicEnvironmentView() {
066                            @Override
067                            public void envChanged(String command) {
068                                    envChanges.append(command).append(":");
069                            }
070                    });
071                    me.stepUntilDone();
072    
073                    assertEquals(
074                                    "CurrentLocation=In(A), Goal=In(A):NoOP:METRIC[pathCost]=0.0:METRIC[maxQueueSize]=2:METRIC[queueSize]=2:METRIC[nodesExpanded]=2:NoOP:",
075                                    envChanges.toString());
076    
077                    assertEquals(
078                                    BidirectionalSearch.SearchOutcome.PATH_FOUND_BETWEEN_PROBLEMS,
079                                    bidirectionalSearch.getSearchOutcome());
080            }
081    
082            //
083            // Test I(A)<->G(B)
084            public void test_AB_BothWaysPath() {
085                    ExtendableMap aMap = new ExtendableMap();
086                    aMap.addBidirectionalLink("A", "B", 5.0);
087    
088                    MapEnvironment me = new MapEnvironment(aMap);
089                    MapAgent ma = new MapAgent(me, bidirectionalSearch,
090                                    new String[] { "B" });
091                    me.addAgent(ma, "A");
092                    me.registerView(new BasicEnvironmentView() {
093                            @Override
094                            public void envChanged(String command) {
095                                    envChanges.append(command).append(":");
096                            }
097                    });
098                    me.stepUntilDone();
099    
100                    assertEquals(
101                                    "CurrentLocation=In(A), Goal=In(B):B:METRIC[pathCost]=5.0:METRIC[maxQueueSize]=2:METRIC[queueSize]=2:METRIC[nodesExpanded]=2:NoOP:",
102                                    envChanges.toString());
103    
104                    assertEquals(
105                                    BidirectionalSearch.SearchOutcome.PATH_FOUND_BETWEEN_PROBLEMS,
106                                    bidirectionalSearch.getSearchOutcome());
107            }
108    
109            //
110            // Test I(A)<->(B)<->G(C)
111            public void test_ABC_BothWaysPath() {
112                    ExtendableMap aMap = new ExtendableMap();
113                    aMap.addBidirectionalLink("A", "B", 5.0);
114                    aMap.addBidirectionalLink("B", "C", 5.0);
115    
116                    MapEnvironment me = new MapEnvironment(aMap);
117                    MapAgent ma = new MapAgent(me, bidirectionalSearch,
118                                    new String[] { "C" });
119                    me.addAgent(ma, "A");
120                    me.registerView(new BasicEnvironmentView() {
121                            @Override
122                            public void envChanged(String command) {
123                                    envChanges.append(command).append(":");
124                            }
125                    });
126                    me.stepUntilDone();
127    
128                    assertEquals(
129                                    "CurrentLocation=In(A), Goal=In(C):B:C:METRIC[pathCost]=10.0:METRIC[maxQueueSize]=4:METRIC[queueSize]=4:METRIC[nodesExpanded]=4:NoOP:",
130                                    envChanges.toString());
131    
132                    assertEquals(
133                                    BidirectionalSearch.SearchOutcome.PATH_FOUND_BETWEEN_PROBLEMS,
134                                    bidirectionalSearch.getSearchOutcome());
135            }
136    
137            //
138            // Test I(A)<->(B)<->(C)<->(D)
139            public void test_ABCD_BothWaysPath() {
140                    ExtendableMap aMap = new ExtendableMap();
141                    aMap.addBidirectionalLink("A", "B", 5.0);
142                    aMap.addBidirectionalLink("B", "C", 5.0);
143                    aMap.addBidirectionalLink("C", "D", 5.0);
144    
145                    MapEnvironment me = new MapEnvironment(aMap);
146                    MapAgent ma = new MapAgent(me, bidirectionalSearch,
147                                    new String[] { "D" });
148                    me.addAgent(ma, "A");
149                    me.registerView(new BasicEnvironmentView() {
150                            @Override
151                            public void envChanged(String command) {
152                                    envChanges.append(command).append(":");
153                            }
154                    });
155                    me.stepUntilDone();
156    
157                    assertEquals(
158                                    "CurrentLocation=In(A), Goal=In(D):B:C:D:METRIC[pathCost]=15.0:METRIC[maxQueueSize]=4:METRIC[queueSize]=4:METRIC[nodesExpanded]=4:NoOP:",
159                                    envChanges.toString());
160    
161                    assertEquals(
162                                    BidirectionalSearch.SearchOutcome.PATH_FOUND_BETWEEN_PROBLEMS,
163                                    bidirectionalSearch.getSearchOutcome());
164            }
165    
166            //
167            // Test I(A)->G(B)
168            public void test_AB_OriginalOnlyPath() {
169                    ExtendableMap aMap = new ExtendableMap();
170                    aMap.addUnidirectionalLink("A", "B", 5.0);
171    
172                    MapEnvironment me = new MapEnvironment(aMap);
173                    MapAgent ma = new MapAgent(me, bidirectionalSearch,
174                                    new String[] { "B" });
175                    me.addAgent(ma, "A");
176                    me.registerView(new BasicEnvironmentView() {
177                            @Override
178                            public void envChanged(String command) {
179                                    envChanges.append(command).append(":");
180                            }
181                    });
182                    me.stepUntilDone();
183    
184                    assertEquals(
185                                    "CurrentLocation=In(A), Goal=In(B):B:METRIC[pathCost]=5.0:METRIC[maxQueueSize]=2:METRIC[queueSize]=1:METRIC[nodesExpanded]=2:NoOP:",
186                                    envChanges.toString());
187    
188                    assertEquals(
189                                    BidirectionalSearch.SearchOutcome.PATH_FOUND_FROM_ORIGINAL_PROBLEM,
190                                    bidirectionalSearch.getSearchOutcome());
191            }
192    
193            //
194            // Test I(A)->(B)->G(C)
195            public void test_ABC_OriginalOnlyPath() {
196                    ExtendableMap aMap = new ExtendableMap();
197                    aMap.addUnidirectionalLink("A", "B", 5.0);
198                    aMap.addUnidirectionalLink("B", "C", 5.0);
199    
200                    MapEnvironment me = new MapEnvironment(aMap);
201                    MapAgent ma = new MapAgent(me, bidirectionalSearch,
202                                    new String[] { "C" });
203                    me.addAgent(ma, "A");
204                    me.registerView(new BasicEnvironmentView() {
205                            @Override
206                            public void envChanged(String command) {
207                                    envChanges.append(command).append(":");
208                            }
209                    });
210                    me.stepUntilDone();
211    
212                    assertEquals(
213                                    "CurrentLocation=In(A), Goal=In(C):B:C:METRIC[pathCost]=10.0:METRIC[maxQueueSize]=2:METRIC[queueSize]=0:METRIC[nodesExpanded]=4:NoOP:",
214                                    envChanges.toString());
215    
216                    assertEquals(
217                                    BidirectionalSearch.SearchOutcome.PATH_FOUND_FROM_ORIGINAL_PROBLEM,
218                                    bidirectionalSearch.getSearchOutcome());
219            }
220    
221            //
222            // Test I(A)->(B)->(C)<->(D)<->G(E)
223            public void test_ABCDE_OriginalOnlyPath() {
224                    ExtendableMap aMap = new ExtendableMap();
225                    aMap.addBidirectionalLink("A", "B", 5.0);
226                    aMap.addUnidirectionalLink("B", "C", 5.0);
227                    aMap.addBidirectionalLink("C", "D", 5.0);
228                    aMap.addBidirectionalLink("D", "E", 5.0);
229    
230                    MapEnvironment me = new MapEnvironment(aMap);
231                    MapAgent ma = new MapAgent(me, bidirectionalSearch,
232                                    new String[] { "E" });
233                    me.addAgent(ma, "A");
234                    me.registerView(new BasicEnvironmentView() {
235                            @Override
236                            public void envChanged(String command) {
237                                    envChanges.append(command).append(":");
238                            }
239                    });
240                    me.stepUntilDone();
241    
242                    assertEquals(
243                                    "CurrentLocation=In(A), Goal=In(E):B:C:D:E:METRIC[pathCost]=20.0:METRIC[maxQueueSize]=4:METRIC[queueSize]=3:METRIC[nodesExpanded]=5:NoOP:",
244                                    envChanges.toString());
245    
246                    assertEquals(
247                                    BidirectionalSearch.SearchOutcome.PATH_FOUND_FROM_ORIGINAL_PROBLEM,
248                                    bidirectionalSearch.getSearchOutcome());
249            }
250    
251            //
252            // Test I(A)<-G(B)
253            public void test_AB_ReverseOnlyPath() {
254                    ExtendableMap aMap = new ExtendableMap();
255                    aMap.addUnidirectionalLink("B", "A", 5.0);
256    
257                    MapEnvironment me = new MapEnvironment(aMap);
258                    MapAgent ma = new MapAgent(me, bidirectionalSearch,
259                                    new String[] { "B" });
260                    me.addAgent(ma, "A");
261                    me.registerView(new BasicEnvironmentView() {
262                            @Override
263                            public void envChanged(String command) {
264                                    envChanges.append(command).append(":");
265                            }
266                    });
267                    me.stepUntilDone();
268    
269                    assertEquals(
270                                    "CurrentLocation=In(A), Goal=In(B):NoOP:METRIC[pathCost]=0.0:METRIC[maxQueueSize]=2:METRIC[queueSize]=0:METRIC[nodesExpanded]=3:NoOP:",
271                                    envChanges.toString());
272    
273                    assertEquals(BidirectionalSearch.SearchOutcome.PATH_NOT_FOUND,
274                                    bidirectionalSearch.getSearchOutcome());
275            }
276    
277            //
278            // Test I(A)<-(B)<-G(C)
279            public void test_ABC_ReverseOnlyPath() {
280                    ExtendableMap aMap = new ExtendableMap();
281                    aMap.addUnidirectionalLink("B", "A", 5.0);
282                    aMap.addUnidirectionalLink("C", "B", 5.0);
283    
284                    MapEnvironment me = new MapEnvironment(aMap);
285                    MapAgent ma = new MapAgent(me, bidirectionalSearch,
286                                    new String[] { "C" });
287                    me.addAgent(ma, "A");
288                    me.registerView(new BasicEnvironmentView() {
289                            @Override
290                            public void envChanged(String command) {
291                                    envChanges.append(command).append(":");
292                            }
293                    });
294                    me.stepUntilDone();
295    
296                    assertEquals(
297                                    "CurrentLocation=In(A), Goal=In(C):NoOP:METRIC[pathCost]=0.0:METRIC[maxQueueSize]=2:METRIC[queueSize]=0:METRIC[nodesExpanded]=4:NoOP:",
298                                    envChanges.toString());
299    
300                    assertEquals(BidirectionalSearch.SearchOutcome.PATH_NOT_FOUND,
301                                    bidirectionalSearch.getSearchOutcome());
302            }
303    
304            // Test I(A)<->(B)<->(C)<-(D)<-G(E)
305            public void test_ABCDE_ReverseOnlyPath() {
306                    ExtendableMap aMap = new ExtendableMap();
307                    aMap.addBidirectionalLink("A", "B", 5.0);
308                    aMap.addBidirectionalLink("B", "C", 5.0);
309                    aMap.addUnidirectionalLink("D", "C", 5.0);
310                    aMap.addUnidirectionalLink("E", "D", 5.0);
311    
312                    MapEnvironment me = new MapEnvironment(aMap);
313                    MapAgent ma = new MapAgent(me, bidirectionalSearch,
314                                    new String[] { "E" });
315                    me.addAgent(ma, "A");
316                    me.registerView(new BasicEnvironmentView() {
317                            @Override
318                            public void envChanged(String command) {
319                                    envChanges.append(command).append(":");
320                            }
321                    });
322                    me.stepUntilDone();
323    
324                    assertEquals(
325                                    "CurrentLocation=In(A), Goal=In(E):NoOP:METRIC[pathCost]=0.0:METRIC[maxQueueSize]=3:METRIC[queueSize]=0:METRIC[nodesExpanded]=8:NoOP:",
326                                    envChanges.toString());
327    
328                    assertEquals(BidirectionalSearch.SearchOutcome.PATH_NOT_FOUND,
329                                    bidirectionalSearch.getSearchOutcome());
330            }
331    
332            // Test I(A)<->(B)<->(C)<->(D)<->(E)<->G(F)
333            // | +
334            // -------------------------
335            public void test_ABCDEF_OriginalFirst() {
336                    ExtendableMap aMap = new ExtendableMap();
337                    aMap.addBidirectionalLink("A", "B", 5.0);
338                    aMap.addBidirectionalLink("B", "C", 5.0);
339                    aMap.addBidirectionalLink("C", "D", 5.0);
340                    aMap.addBidirectionalLink("D", "E", 5.0);
341                    aMap.addBidirectionalLink("E", "F", 5.0);
342                    aMap.addUnidirectionalLink("B", "F", 5.0);
343    
344                    MapEnvironment me = new MapEnvironment(aMap);
345                    MapAgent ma = new MapAgent(me, bidirectionalSearch,
346                                    new String[] { "F" });
347                    me.addAgent(ma, "A");
348                    me.registerView(new BasicEnvironmentView() {
349                            @Override
350                            public void envChanged(String command) {
351                                    envChanges.append(command).append(":");
352                            }
353                    });
354                    me.stepUntilDone();
355    
356                    assertEquals(
357                                    "CurrentLocation=In(A), Goal=In(F):B:F:METRIC[pathCost]=10.0:METRIC[maxQueueSize]=5:METRIC[queueSize]=5:METRIC[nodesExpanded]=6:NoOP:",
358                                    envChanges.toString());
359    
360                    assertEquals(
361                                    BidirectionalSearch.SearchOutcome.PATH_FOUND_FROM_ORIGINAL_PROBLEM,
362                                    bidirectionalSearch.getSearchOutcome());
363            }
364    
365            // Test I(A)<->(B)<->(C)<->(D)<->(E)<->G(F)
366            // + |
367            // -------------------------
368            public void test_ABCDEF_ReverseFirstButNotFromOriginal() {
369                    ExtendableMap aMap = new ExtendableMap();
370                    aMap.addBidirectionalLink("A", "B", 5.0);
371                    aMap.addBidirectionalLink("B", "C", 5.0);
372                    aMap.addBidirectionalLink("C", "D", 5.0);
373                    aMap.addBidirectionalLink("D", "E", 5.0);
374                    aMap.addBidirectionalLink("E", "F", 5.0);
375                    aMap.addUnidirectionalLink("E", "A", 5.0);
376    
377                    MapEnvironment me = new MapEnvironment(aMap);
378                    MapAgent ma = new MapAgent(me, bidirectionalSearch,
379                                    new String[] { "F" });
380                    me.addAgent(ma, "A");
381                    me.registerView(new BasicEnvironmentView() {
382                            @Override
383                            public void envChanged(String command) {
384                                    envChanges.append(command).append(":");
385                            }
386                    });
387                    me.stepUntilDone();
388    
389                    assertEquals(
390                                    "CurrentLocation=In(A), Goal=In(F):B:C:D:E:F:METRIC[pathCost]=25.0:METRIC[maxQueueSize]=6:METRIC[queueSize]=6:METRIC[nodesExpanded]=7:NoOP:",
391                                    envChanges.toString());
392    
393                    assertEquals(
394                                    BidirectionalSearch.SearchOutcome.PATH_FOUND_BETWEEN_PROBLEMS,
395                                    bidirectionalSearch.getSearchOutcome());
396            }
397    
398            // -------------
399            // + +
400            // Test I(A)<->(B)<->(C)<->(D)<->(E)<-G(F)
401            // + +
402            // -------------------------
403            public void test_ABCDEF_MoreComplexReverseFirstButNotFromOriginal() {
404                    ExtendableMap aMap = new ExtendableMap();
405                    aMap.addBidirectionalLink("A", "B", 5.0);
406                    aMap.addBidirectionalLink("B", "C", 5.0);
407                    aMap.addBidirectionalLink("C", "D", 5.0);
408                    aMap.addBidirectionalLink("D", "E", 5.0);
409                    aMap.addUnidirectionalLink("F", "E", 5.0);
410                    aMap.addBidirectionalLink("E", "A", 5.0);
411                    aMap.addBidirectionalLink("D", "F", 5.0);
412    
413                    MapEnvironment me = new MapEnvironment(aMap);
414                    MapAgent ma = new MapAgent(me, bidirectionalSearch,
415                                    new String[] { "F" });
416                    me.addAgent(ma, "A");
417                    me.registerView(new BasicEnvironmentView() {
418                            @Override
419                            public void envChanged(String command) {
420                                    envChanges.append(command).append(":");
421                            }
422                    });
423                    me.stepUntilDone();
424    
425                    assertEquals(
426                                    "CurrentLocation=In(A), Goal=In(F):B:C:D:F:METRIC[pathCost]=20.0:METRIC[maxQueueSize]=9:METRIC[queueSize]=9:METRIC[nodesExpanded]=7:NoOP:",
427                                    envChanges.toString());
428    
429                    assertEquals(
430                                    BidirectionalSearch.SearchOutcome.PATH_FOUND_BETWEEN_PROBLEMS,
431                                    bidirectionalSearch.getSearchOutcome());
432            }
433    }