Skip to content

Commit

Permalink
more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
J-morag committed Jan 26, 2023
1 parent 0eabd59 commit daa832b
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 44 deletions.
24 changes: 18 additions & 6 deletions src/main/java/BasicMAPF/Instances/Maps/MapFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
import BasicMAPF.Instances.Maps.Coordinates.Coordinate_2D;
import BasicMAPF.Instances.Maps.Coordinates.I_Coordinate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;

/**
* Responsible for the creation of instances of all classes that implement {@link I_Map}.
Expand All @@ -16,17 +13,17 @@ public class MapFactory {

/**
* Generates a new 4-connected {@link GraphMap} from a square, 2D grid.
*
* Simple - Only 2 {@link Enum_MapLocationType location types} exist, {@link Enum_MapLocationType#EMPTY} and
* {@link Enum_MapLocationType#WALL}. {@link Enum_MapLocationType#EMPTY} locations are passable, and can only connect to other
* {@link Enum_MapLocationType#EMPTY} locations. {@link Enum_MapLocationType#WALL} locations are impassable, and can not connect to
* any other location, so they will not be generated.
* @param rectangle_2D_Map A rectangle grid representing a map, containing only {@link Enum_MapLocationType#EMPTY} and
* {@link Enum_MapLocationType#WALL}. The length of its first dimension should correspond to the
* original map's x dimension.
* @param isOneConnectedComponent if the grid is one connected component.
* @return a new 4-connected {@link GraphMap}.
*/
public static GraphMap newSimple4Connected2D_GraphMap(Enum_MapLocationType[][] rectangle_2D_Map){
public static GraphMap newSimple4Connected2D_GraphMap(Enum_MapLocationType[][] rectangle_2D_Map, boolean isOneConnectedComponent){
int xAxis_length = rectangle_2D_Map.length;
int yAxis_length = rectangle_2D_Map[0].length;
GraphMapVertex[][] locations = new GraphMapVertex[xAxis_length][yAxis_length]; //rectangle map
Expand Down Expand Up @@ -64,6 +61,21 @@ public static GraphMap newSimple4Connected2D_GraphMap(Enum_MapLocationType[][] r
return new GraphMap(allLocations);
}

/**
* Generates a new 4-connected {@link GraphMap} from a square, 2D grid.
* Simple - Only 2 {@link Enum_MapLocationType location types} exist, {@link Enum_MapLocationType#EMPTY} and
* {@link Enum_MapLocationType#WALL}. {@link Enum_MapLocationType#EMPTY} locations are passable, and can only connect to other
* {@link Enum_MapLocationType#EMPTY} locations. {@link Enum_MapLocationType#WALL} locations are impassable, and can not connect to
* any other location, so they will not be generated.
* @param rectangle_2D_Map A rectangle grid representing a map, containing only {@link Enum_MapLocationType#EMPTY} and
* {@link Enum_MapLocationType#WALL}. The length of its first dimension should correspond to the
* original map's x dimension.
* @return a new 4-connected {@link GraphMap}.
*/
public static GraphMap newSimple4Connected2D_GraphMap(Enum_MapLocationType[][] rectangle_2D_Map){
return newSimple4Connected2D_GraphMap(rectangle_2D_Map, true);
}

/* nicetohave - 8 connected 2D map
public static GraphMap newSimple8Connected2D_GraphMap(Enum_MapLocationType[][] map_2D){
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package BasicMAPF.Solvers.AStar.CostsAndHeuristics;

import BasicMAPF.Instances.Maps.Coordinates.I_Coordinate;
import BasicMAPF.Solvers.AStar.SingleAgentAStar_Solver;

public class UnitCostsAndManhattanDistance implements AStarGAndH {
private final I_Coordinate target;

public UnitCostsAndManhattanDistance(I_Coordinate target) {
this.target = target;
}

@Override
public float getH(SingleAgentAStar_Solver.AStarState state) {
return state.move.currLocation.getCoordinate().distance(target);
}
@Override
public boolean isConsistent() {
return true;
}
}
41 changes: 16 additions & 25 deletions src/main/java/BasicMAPF/Solvers/AStar/SingleAgentAStar_Solver.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import BasicMAPF.Instances.Maps.I_Map;
import BasicMAPF.Instances.Maps.I_Location;
import BasicMAPF.Solvers.AStar.CostsAndHeuristics.AStarGAndH;
import BasicMAPF.Solvers.AStar.CostsAndHeuristics.UnitCostsAndManhattanDistance;
import BasicMAPF.Solvers.ConstraintsAndConflicts.ConflictManagement.I_ConflictAvoidanceTable;
import Environment.Metrics.InstanceReport;
import BasicMAPF.Solvers.*;
Expand Down Expand Up @@ -84,26 +85,17 @@ protected void init(MAPF_Instance instance, RunParameters runParameters){
this.existingSolution.putPlan(this.existingPlan);
}

if(runParameters instanceof RunParameters_SAAStar parameters
&& ((RunParameters_SAAStar) runParameters).heuristicFunction != null){
this.gAndH = parameters.heuristicFunction;
}
else{
this.gAndH = new defaultGAndH();
}
if (! this.gAndH.isConsistent()){
throw new IllegalArgumentException("Support for inconsistent heuristic is not implemented.");
}

if(runParameters instanceof RunParameters_SAAStar parameters
&& ((RunParameters_SAAStar) runParameters).problemStartTime >= 0){
this.problemStartTime = parameters.problemStartTime;
}

if(runParameters instanceof RunParameters_SAAStar parameters
&& ((RunParameters_SAAStar) runParameters).conflictAvoidanceTable != null){
this.conflictAvoidanceTable = parameters.conflictAvoidanceTable;
}
// else keep the value that it has already been initialised with (above)

if(runParameters instanceof RunParameters_SAAStar parameters){
this.sourceCoor = parameters.sourceCoor != null ? parameters.sourceCoor : agent.source;
this.targetCoor = parameters.targetCoor != null ? parameters.targetCoor : agent.target;
Expand All @@ -112,15 +104,25 @@ protected void init(MAPF_Instance instance, RunParameters runParameters){
this.sourceCoor = agent.source;
this.targetCoor = agent.target;
}

if(runParameters instanceof RunParameters_SAAStar parameters
&& ((RunParameters_SAAStar) runParameters).heuristicFunction != null){
this.gAndH = parameters.heuristicFunction;
}
else{
this.gAndH = new UnitCostsAndManhattanDistance(this.targetCoor);
}
if (! this.gAndH.isConsistent()){
throw new IllegalArgumentException("Support for inconsistent heuristic is not implemented.");
}

if(runParameters instanceof RunParameters_SAAStar parameters){
this.fBudget = parameters.fBudget;
}
else{
this.fBudget = Float.POSITIVE_INFINITY;
}

// this.openList = new OpenList<>(stateFComparator);
// this.closed = new HashSet<>();
this.expandedNodes = 0;
this.generatedNodes = 0;
}
Expand Down Expand Up @@ -262,7 +264,7 @@ public class AStarState implements Comparable<AStarState>{
* is to say, if all tie breaking methods still result in equality, tie break for using serialID.
*/
private final int serialID = SingleAgentAStar_Solver.this.generatedNodes++; // take and increment
private final Move move;
public final Move move;
private final AStarState prev;
private final int g;
private final float h;
Expand Down Expand Up @@ -436,17 +438,6 @@ public String toString() {

} ////////// end AStarState

private class defaultGAndH implements AStarGAndH {
@Override
public float getH(AStarState state) {
return state.move.currLocation.getCoordinate().distance(SingleAgentAStar_Solver.this.targetCoor);
}
@Override
public boolean isConsistent() {
return true;
}
}


/**
* For sorting the open list.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package BasicMAPF.Solvers.AStar;

import BasicMAPF.Instances.Agent;
import BasicMAPF.Instances.MAPF_Instance;
import BasicMAPF.Instances.Maps.*;
import BasicMAPF.Instances.Maps.Coordinates.Coordinate_2D;
import BasicMAPF.Instances.Maps.Coordinates.I_Coordinate;
import BasicMAPF.Solvers.AStar.CostsAndHeuristics.DistanceTableAStarHeuristic;
import Environment.Metrics.InstanceReport;
import org.junit.jupiter.api.Test;

import static BasicMAPF.TestConstants.Agents.agent04to00;
import static BasicMAPF.TestConstants.Maps.mapH;
import static BasicMAPF.TestConstants.Maps.mapWithPocket;
import static org.junit.jupiter.api.Assertions.*;

import java.util.HashMap;
Expand Down Expand Up @@ -112,4 +116,13 @@ public void test(){
assertTrue(equalsAllAgentMap(expected, distanceTableAStarHeuristic.getDistanceDictionaries()));
}

@Test
void failIfMapIsNotOneConnectedComponent(){
MAPF_Instance testInstance = new MAPF_Instance("pocket", mapWithPocket, new Agent[]{agent04to00});

DistanceTableAStarHeuristic distanceTableAStarHeuristic = new DistanceTableAStarHeuristic(testInstance.agents, testInstance.map);
SingleAgentAStar_Solver solver = new SingleAgentAStar_Solver();
assertThrows(IllegalArgumentException.class, () -> solver.solve(testInstance, new RunParameters_SAAStar(new InstanceReport(), distanceTableAStarHeuristic)));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import BasicMAPF.Instances.Maps.Coordinates.Coordinate_2D;
import BasicMAPF.Solvers.AStar.CostsAndHeuristics.AStarGAndH;
import BasicMAPF.Solvers.AStar.CostsAndHeuristics.DistanceTableAStarHeuristic;
import BasicMAPF.Solvers.AStar.CostsAndHeuristics.UnitCostsAndManhattanDistance;
import Environment.IO_Package.IO_Manager;
import BasicMAPF.Instances.Agent;
import BasicMAPF.Instances.InstanceBuilders.InstanceBuilder_BGU;
Expand Down Expand Up @@ -382,7 +384,7 @@ public String toString() {
}
}

private AStarGAndH unitCostAndNoHeuristic = new UnitCostAndNoHeuristic();
private final AStarGAndH unitCostAndNoHeuristic = new UnitCostAndNoHeuristic();

private static List<I_Location> planLocations(SingleAgentPlan planFromAStar) {
List<I_Location> aStarPlanLocations = new ArrayList<>();
Expand Down Expand Up @@ -427,25 +429,66 @@ void optimalVsUCS4(){
}
@Test
void optimalVsUCSDynamic(){
Map<I_ExplicitMap, String> maps = singleStronglyConnectedComponentMapsWithNames;
for (I_ExplicitMap testMap :
stronglyConnectedComponentMapsWithNames.keySet()) {
maps.keySet()) {
for (I_Location source :
testMap.getAllLocations()) {
for (I_Location target :
testMap.getAllLocations()) {
if ( ! source.equals(target)){
Agent agent = new Agent(0, source.getCoordinate(), target.getCoordinate());
MAPF_Instance testInstance = new MAPF_Instance(
stronglyConnectedComponentMapsWithNames.get(testMap) + " " + agent, testMap, new Agent[]{agent});
maps.get(testMap) + " " + agent, testMap, new Agent[]{agent});
compareAStarAndUCS(aStar, new InstanceReport(),
agent, testInstance, unitCostAndNoHeuristic);
}
}
}
}
}
@Test
void optimalVsUCSDynamicWithDistanceTableHeuristic(){
Map<I_ExplicitMap, String> maps = singleStronglyConnectedComponentMapsWithNames;
for (I_ExplicitMap testMap :
maps.keySet()) {
for (I_Location source :
testMap.getAllLocations()) {
for (I_Location target :
testMap.getAllLocations()) {
if ( ! source.equals(target)){
Agent agent = new Agent(0, source.getCoordinate(), target.getCoordinate());
MAPF_Instance testInstance = new MAPF_Instance(
maps.get(testMap) + " " + agent, testMap, new Agent[]{agent});
DistanceTableAStarHeuristic distanceTableAStarHeuristic = new DistanceTableAStarHeuristic(testInstance.agents, testInstance.map);
compareAStarAndUCS(aStar, new InstanceReport(),
agent, testInstance, distanceTableAStarHeuristic);
}
}
}
}
}
@Test
void optimalVsUCSDDynamicWithManhattanDistanceHeuristic(){
Map<I_ExplicitMap, String> maps = singleStronglyConnectedComponentGridMapsWithNames; // grid maps only!
for (I_ExplicitMap testMap :
maps.keySet()) {
for (I_Location source :
testMap.getAllLocations()) {
for (I_Location target :
testMap.getAllLocations()) {
if ( ! source.equals(target)){
Agent agent = new Agent(0, source.getCoordinate(), target.getCoordinate());
MAPF_Instance testInstance = new MAPF_Instance(
maps.get(testMap) + " " + agent, testMap, new Agent[]{agent});
compareAStarAndUCS(aStar, new InstanceReport(), agent, testInstance, new UnitCostsAndManhattanDistance(agent.target));
}
}
}
}
}

private class RandomButStableCostsFrom1To10AndNoHeuristic implements AStarGAndH{
private static class RandomButStableCostsFrom1To10AndNoHeuristic implements AStarGAndH{
Map<Edge, Integer> randomButStableCosts = new HashMap<>();
Random rand;

Expand Down Expand Up @@ -482,47 +525,48 @@ public String toString() {
void optimalVsUCSWeightedEdges1(){
MAPF_Instance testInstance = instanceMaze1;
Agent agent = testInstance.agents.get(0);
AStarGAndH randomStableCosts = new RandomButStableCostsFrom1To10AndNoHeuristic((long)(agent.hashCode()));
AStarGAndH randomStableCosts = new RandomButStableCostsFrom1To10AndNoHeuristic((long) (agent.hashCode()));

compareAStarAndUCS(aStar, instanceReport, agent, testInstance, randomStableCosts);
}
@Test
void optimalVsUCSWeightedEdges2(){
MAPF_Instance testInstance = instanceMaze2;
Agent agent = testInstance.agents.get(0);
AStarGAndH randomStableCosts = new RandomButStableCostsFrom1To10AndNoHeuristic((long)(agent.hashCode()));
AStarGAndH randomStableCosts = new RandomButStableCostsFrom1To10AndNoHeuristic((long) (agent.hashCode()));

compareAStarAndUCS(aStar, instanceReport, agent, testInstance, randomStableCosts);
}
@Test
void optimalVsUCSWeightedEdges3(){
MAPF_Instance testInstance = instanceMaze3;
Agent agent = testInstance.agents.get(0);
AStarGAndH randomStableCosts = new RandomButStableCostsFrom1To10AndNoHeuristic((long)(agent.hashCode()));
AStarGAndH randomStableCosts = new RandomButStableCostsFrom1To10AndNoHeuristic((long) (agent.hashCode()));

compareAStarAndUCS(aStar, instanceReport, agent, testInstance, randomStableCosts);
}
@Test
void optimalVsUCSWeightedEdges4(){
MAPF_Instance testInstance = instanceMaze4;
Agent agent = testInstance.agents.get(0);
AStarGAndH randomStableCosts = new RandomButStableCostsFrom1To10AndNoHeuristic((long)(agent.hashCode()));
AStarGAndH randomStableCosts = new RandomButStableCostsFrom1To10AndNoHeuristic((long) (agent.hashCode()));

compareAStarAndUCS(aStar, instanceReport, agent, testInstance, randomStableCosts);
}
@Test
void optimalVsUCSWeightedEdgesDynamic(){
Map<I_ExplicitMap, String> maps = singleStronglyConnectedComponentMapsWithNames;
for (I_ExplicitMap testMap :
stronglyConnectedComponentMapsWithNames.keySet()) {
maps.keySet()) {
for (I_Location source :
testMap.getAllLocations()) {
for (I_Location target :
testMap.getAllLocations()) {
if ( ! source.equals(target)){
Agent agent = new Agent(0, source.getCoordinate(), target.getCoordinate());
MAPF_Instance testInstance = new MAPF_Instance(
stronglyConnectedComponentMapsWithNames.get(testMap) + " " + agent, testMap, new Agent[]{agent});
AStarGAndH randomStableCosts = new RandomButStableCostsFrom1To10AndNoHeuristic((long)(agent.hashCode()));
maps.get(testMap) + " " + agent, testMap, new Agent[]{agent});
AStarGAndH randomStableCosts = new RandomButStableCostsFrom1To10AndNoHeuristic((long) (agent.hashCode()));
compareAStarAndUCS(aStar, new InstanceReport(), agent, testInstance, randomStableCosts);
}
}
Expand Down
9 changes: 7 additions & 2 deletions src/test/java/BasicMAPF/TestConstants/Maps.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class Maps {
{e, e, w, e, w, w},
{w, e, w, e, e, e},
};
public static final I_ExplicitMap mapWithPocket = MapFactory.newSimple4Connected2D_GraphMap(map_2D_withPocket);
public static final I_ExplicitMap mapWithPocket = MapFactory.newSimple4Connected2D_GraphMap(map_2D_withPocket, false);

public static final Enum_MapLocationType[][] map_2D_smallMaze = {
{e, e, e, w, e, w},
Expand Down Expand Up @@ -141,10 +141,15 @@ private static I_ExplicitMap createRandomStronglyConnectedGraphMap(int seed, int
return MapFactory.newArbitraryGraphMap(coordinatesAdjacencyLists, coordinatesEdgeWeights, coordinatesLocationTypes, true);
}

public static final Map<I_ExplicitMap, String> stronglyConnectedComponentMapsWithNames = Map.of(
public static final Map<I_ExplicitMap, String> singleStronglyConnectedComponentMapsWithNames = Map.of(
mapCircle, "mapCircle", mapEmpty, "mapEmpty", mapSmallMaze, "mapSmallMaze", mapH, "mapH",
mapHLong, "mapHLong", randomArbitraryGraphMap1, "randomArbitraryGraphMap1",
randomArbitraryGraphMap2, "randomArbitraryGraphMap2", randomArbitraryGraphMap3, "randomArbitraryGraphMap3",
randomArbitraryGraphMap4, "randomArbitraryGraphMap4", randomArbitraryGraphMap5, "randomArbitraryGraphMap5"
);

public static final Map<I_ExplicitMap, String> singleStronglyConnectedComponentGridMapsWithNames = Map.of(
mapCircle, "mapCircle", mapEmpty, "mapEmpty", mapSmallMaze, "mapSmallMaze", mapH, "mapH",
mapHLong, "mapHLong"
);
}

0 comments on commit daa832b

Please sign in to comment.