Terrain
from sIArena.terrain.Terrain import Terrain
The main element is the Terrain. This element represent a map or grid where the search algorithm will be performed.
It is a matrix of size NxM where each cell or tile contains an integer value.
Each value represents the height of the terrain at that point.
The difference of value between adjacent cells is used to determine the cost of moving from one cell to another.
The terrain has within it cells 2 special cells: the origin and the destination. These cells are used to determine the start and end of the path to be found. It also counts with a cost_function that is used to determine the cost of moving from one cell to another depending on their values.
Attributes
n: number of rowsm: number of columnsmatrix:numpymatrix of sizeNxMorigin:tuple(int,int)with the coordinates of the origin celldestination:tuple(int,int)with the coordinates of the destination cellcost_function: function that receives 2 integersx,yand returns the cost of moving from one cell with valuexto another with valuey
Built-in Methods
str: returns a string representation of the matrix of the terrain. The origin and destination cells are marked with the characters+andxrespectively.getitem [Coordinate]: returns the value of the cell at the given coordinates. i.e.terrain[(0,0)].ctor: constructor that receives a matrix.matrix:numpymatrix of sizeNxMorigin:Coordinatewith the coordinates of the origin cell. IfNoneis provided, the origin will be set to(0,0)destination:Coordinatewith the coordinates of the destination cell. IfNoneis provided, the destination will be set to(n-1,m-1)cost_function: function that receives 2 integersx,yand returns the cost of moving from one cell with valuexto another with valuey. In case is not provided, the Default cost function will be used.
Methods
size: returns a tuple with(n,m).get_neighbors: returns a list of the coordinates of the cells that are adjacent to the given cell. -pos:Coordinateget_cost: returns the cost of moving from one cell to another. -pos1:Coordinate-pos2:Coordinateget_path_cost: returns the cost of a whole Path. -path:Pathis_complete_path: returnsTrueif the given Path is valid and complete. -path:Pathwhy_complete_path: returns the same value asis_complete_pathand also retrieves a string with information why the path is not complete (if this is the case). -path:Path
Some of this methods use the element Path that is seeing afterwards.
Cost Function
The cost function is a function that receives 2 integers x,y
referring to the height of 2 adjacent cells,
and returns the cost of moving from one cell with value x to another with value y.
Default cost function
The default cost function is as follows:
If the origin cell and the target cell are at same height (
x==y), the cost is1.If the origin cell is higher than the target cell (
x>y), it means it moves down, and the cost is their difference:x-y.If the origin cell is lower than the target cell (
x<y), it means it moves up, and the cost is double their difference:2*(y-x).
The following snippet shows the implementation of the default cost function:
def default_cost_function(x,y):
if x == y: return 1
elif x > y: return x-y
else: return 2*(y-x)
Visualization
There are several ways to easily visualize the terrain:
String
Function str returns a string representation of the matrix of the terrain:
The origin and destination cells are marked with the characters + and x respectively.
print(terrain)
+---+---+---+---+---+
|+3 | 9 | 3 | 9 | 3 |
+---+---+---+---+---+
| 9 | 2 | 0 | 3 | 0 |
+---+---+---+---+---+
| 3 | 9 | 3 | 3 | 3 |
+---+---+---+---+---+
| 0 | 6 | 3 | 0 | 6 |
+---+---+---+---+---+
| 3 | 9 | 3 | 3 |x3 |
+---+---+---+---+---+
2D plot
In order to learn how to visualize a 2D plot of the terrain, please refer to the 2D Plot section.
3D plot
In order to learn how to visualize a 3D plot of the terrain, please refer to the 3D Plot section.
Multiple Destinations Terrain
There is other class for Terrain that is called MultipleDestinationTerrain.
This class allows to have multiple destinations in the terrain.
This means that the path must pass through all of them in order to be considered complete.
The destinations are not sorted, so they can be visited in any order.
from sIArena.terrain.Terrain import MultipleDestinationTerrain
The use and methods of this class are similar to Terrain ones.
It changes:
The argument
destinationin the constructor is now a set ofCoordinate.The method
is_complete_pathnow checks if the path passes through all the destinations.To get the destinations, use the attribute
destinations, that is a set ofCoordinate.
Example on how to create a MultipleDestinationTerrain:
from sIArena.terrain.Terrain import MultipleDestinationTerrain
from sIArena.terrain.Coordinate import Coordinate
matrix = np.array(...)
destinations = {Coordinate(4,4), Coordinate(0,4)}
# It uses the top-left cell as origin by default
terrain = MultipleDestinationTerrain(matrix, destination=destinations)
# To get the destinations of the terrain
destinations = terrain.destinations
Multi Endpoint Terrain
There is another Terrain class called MultiEndpointTerrain.
This class is used when the problem has several possible starting points and several possible ending points.
Paths valid are those that start in any of the allowed origins and end in any of the allowed destinations, as long as they are valid paths in the terrain.
from sIArena.terrain.Terrain import MultiEndpointTerrain
Difference with Terrain
The complete-path rule for MultiEndpointTerrain is:
The path must be valid: every consecutive pair of coordinates must be neighbors in the terrain.
The first coordinate of the path must belong to the set of allowed origins.
The last coordinate of the path must belong to the set of allowed destinations.
The path may pass through other origins or destinations in the middle, but this is not required.
The path does not need to visit all destinations.
This MultiEndpointTerrain class is similar to Terrain with some minor differences:
Method get_origins() returns the set of allowed origins, instead of a single origin.
Method get_destinations() returns the set of allowed destinations, instead of a single destination.
There is no attribute
originordestination.
The constructor keeps the same parameter names as the standard Terrain constructor:
origin: a singleCoordinateor a collection ofCoordinatevalues.destination: a singleCoordinateor a collection ofCoordinatevalues.
Examples
Example with several origins and several destinations:
from sIArena.terrain.Terrain import MultiEndpointTerrain
matrix = [
[0, 0, 0, 0],
[0, 5, 5, 0],
[0, 0, 0, 0],
]
terrain = MultiEndpointTerrain(
matrix,
origin={(0, 0), (2, 0)},
destination={(0, 3), (2, 3)},
)
path = [(2, 0), (2, 1), (2, 2), (2, 3)]
terrain.is_complete_path(path) # True
terrain.get_origins() # {(0, 0), (2, 0)}
terrain.get_destinations() # {(0, 3), (2, 3)}
The following path is also complete in the same terrain, because it starts in another valid origin and ends in another valid destination:
other_path = [(0, 0), (0, 1), (0, 2), (0, 3)]
terrain.is_complete_path(other_path) # True
However, this path is not complete, even if it is a valid sequence of neighboring cells, because it does not start in one of the allowed origins:
wrong_start = [(1, 0), (2, 0), (2, 1), (2, 2), (2, 3)]
terrain.is_valid_path(wrong_start) # True
terrain.is_complete_path(wrong_start) # False
And this path is not complete because it does not end in one of the allowed destinations:
wrong_end = [(2, 0), (2, 1), (2, 2)]
terrain.is_valid_path(wrong_end) # True
terrain.is_complete_path(wrong_end) # False
Sequential Destinations Terrain
There is other class for Terrain that is called SequentialDestinationTerrain.
This class have multiple destinations, but in this case the path must pass through them in the same order as they are provided.
from sIArena.terrain.Terrain import SequentialDestinationTerrain
The use and methods of this class are similar to Terrain ones.
It changes:
The argument
destinationin the constructor is now a list ofCoordinate.The method
is_complete_pathnow checks if the path passes through all the destinations in the same order as they are provided.To get the destinations, use the attribute
destinations, that is a list ofCoordinate.
Example on how to create a SequentialDestinationTerrain:
from sIArena.terrain.Terrain import SequentialDestinationTerrain
from sIArena.terrain.Coordinate import Coordinate
matrix = np.array(...)
destinations = [Coordinate(4,4), Coordinate(0,4)]
# It uses the top-left cell as origin by default
terrain = SequentialDestinationTerrain(matrix, destination=destinations)
# To get the destinations of the terrain
destinations = terrain.destinations