简体   繁体   中英

Efficient way to turn a boolean matrix into a graph structure?

I am working on a maze-problem where the maze is represented in a two-dimensional array, so that if an element is false, the square is not possible to walt through, and the other way around. I have implemented a solving method that recursively tries to walk through all the neighbouring squares of the starting point in a depth first way, which works as it should.

I would however like to try to beat the DFS-algoritm, and I had the idea to simplify the maze into a graph, (and perhaps try to assign weights to the edges) and do a DFS on the graph and not every single square in the maze. The problem I run into is that the way I go about turning the maze into a grap seems very inefficient. Here is an outline of the method that turns the boolean matrix into a graph:

I begin at row 0, and go through each row from index 0, 0 to index n,0, then 0,1 .. n, 1 till n,n. Edit:to clarify: I let the x-values along the maze increase first. Then I link the nodes vertically in the next segment.

I'll call the true values in the matrix for open squares. *If a white square is on the edge of the board, I make a new sub-class of my Node class called Opening. I will keep a reference to that node. Continuing to the right, if I hit either a crossroad or if the next square is black, I make a node and an endge between the two. If I step from a black square to a white square, and if the next square to the right is not black, I make a node, and I make an edge between that node and the next node along the row.

All the nodes get added to a list of nodes. Then, I loop through all the colomns from (0, 0), (0, 1), ..., (0, n), (1, 0), (1, 1).. (1, n).. and make edges between all the nodes that are not seperated by black squares.

This feels like a very costly way of going about things. I would love to hear any recommendations as to how this should be done properly.

F F F F F F F F F F F F F
T T F T T T T T T T T T F
F T F F F F F F F T F F F
F T T T F T T T F T F T F
F F F T F T F T F F F T F
F T F T F T F T T T T T F
F T F T F T F F F F F F F
F T T T F T T T T T T T F
F T F F F F F F F F F T F
F T F T T T T T T T T T F
F T F T F F F F F F F T F
F T T T F T T T T T T T T
F F F F F F F F F F F F F

would make these nodes:

. . . . . . . . . . . . .
O O . O . . . . . O . O .
. . . . . . . . . . . . .
. O . O . O . O . . . . .
. . . . . . . . . . . . .
. . . . . . . O . . . O .
. . . . . . . . . . . . .
. O . O . O . . . . . O .
. . . . . . . . . . . . .
. . . O . . . . . . . O .
. . . . . . . . . . . . .
. O . O . O . . . . . O O
. . . . . . . . . . . . .

This does not show the edges, but maybe you get the idea.

I have two solutions in mind and one of them already implemented. Before I start to explain the first algorithm, here some assumptions the algorithm relies on:

Assumtions

  1. the maze is minimal in terms of: either the boarder tiles of the maze contain a walkable tile T or the whole maze is composed of unwalkable tiles F only.
  2. the maze defines a rectangle or in other words: each row of the maze have the same amount of columns.

Algorithm

I will explain the algorithm by using a simpler example, still touching many important cases. Consider the following maze composed of 5 rows and 3 columns:

在此处输入图片说明

Walkable tiles T are green while wall tiles F are blue.

Phase one of the algorithm starts at (x, y) = (0, 0), in search of a walkable boarder tile , by visiting boarder tiles moving clockwise. It prefers walkable tiles having either less or more than 2 open edges . An open edge is an edge for which we know one node but not yet the other buddy node .

It starts at tile (x, y) = (0, 0) and finds a walkable node having 2 open edges (represented as white arrows). It memorizes the candidate node (represented by an orange circle) and continues, hoping to find a preferable node as stated above.

At step 5 it finds a preferable node represented by the tile (2, 2), having 3 open edges . It marks the node as unprocessed (represented as a circle with either a white or grey background) and terminates phase one.

Phase two will pick an arbitrary unprocessed node and process it, by determining the buddy nodes of open edges , until no more unprocessed nodes exists. Afterwards it will mark the node as processed . Determining buddy nodes may result in marking additional nodes as unprocessed .

在此处输入图片说明

The only unprocessed node available to pick is the boarder node at (2, 2) found in phase one. The algorithm picks it (represented by a circle having a grey background). The arbitrary selected open edge is represented as a gray arrow (in our case pointing south).

Now the algorithm searches for the buddy node by moving along walkable tiles until it finds a node (a tile having either less or more than 2 edges or being the tile the algorithm started at).

In our case the algorithm finds the buddy node in step 6 represented by the walkable tile (0, 2). Because this node is neither marked as processed nor as unprocessed it marks the node as unprocessed (represented by a circle having a white background). The open edge is now linked (represented by a black arrow) to its buddy node and vice versa.

在此处输入图片说明

The algorithm continues picking open edges of the selected node until all open edges are linked to their buddy nodes . In our example the next arbitrary picked open edge is pointing west.

The algorithm moves along walkable tiles and finds the buddy node represented by the tile (0, 2), which it already found before and which is already marked as unprocessed . Hence it links the open edge for both nodes and continues with the last open edge pointing north.

It finds the same node as before and links the last open edge . Now the selected node at (2, 2) has no more open edges and hence the algorithm marks it as processed (represented by circle having a green background).

The algorithm continues picking an arbitrary unprocessed node, finding the only one available represented by the tile at (0, 2). But because this node do not have any open edges it marks it immediately as processed and continues.

There are no more unprocessed nodes available and hence the algorithm terminates.

Applied to OP Example

If applied to the example provided by you the resulting graph would be much smaller without loosing any information about navigating the maze. Lets have a look at your graph (which I had to complete, because some nodes were missing):

在此处输入图片说明

The picture at the left shows the graph resulting from your example and suggested algorithm. The picture to the right shows the nodes the algorithm I described would not find because they may be optimized away without loosing any navigation information. They would either be replaced by an edge or completely eliminated. The result is shown below:

在此处输入图片说明

The picture at the left shows the replacements while the picture at the right is just a compressed version of it. The graph was reduced from 25 nodes to 8 nodes and from 23 to 7 edges. Overall a reduction of 2/3 nodes and edges.

Interesting Corner Cases

While I implemented the algorithm, I discovered some interesting corner cases I like to share with you. I will rush through the algorithm to keep the images small. I hope you already got how the algorithm works.

  1. Single walkable tile and hence no edges at all:

在此处输入图片说明

  1. Only boarder tiles are walkable :

在此处输入图片说明

  1. All tiles are walkable :

在此处输入图片说明

  1. Preferable boarder tile has single edge:

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM