I am trying to check if there is path from one vertex to any from several other vertices (in my particular case, i need to check if there is way from top of the wall to the any other brick that is on the ground, and every brick is a vertex).
I have found some algorithms, but i need simplified version just to check if the path exists. (it'd be good if i also could have number of the possible paths. )
I'm new to the graphs and searched a lot about these search algorithms before asking here, but i couldn't figure out how to implement them in my situation.
Edit 1: I forgot to add that i can have hundreds of bricks (vertices) and need fastest way of checking if path exists. I have searched Dijkstra's algorithm and it looks too complicated. And for some reason there are more tutorials and explanations for Directed graphs, so that's the reason why i am writing question here.
for now i have vertex class:
public class Vertex : MonoBehaviour {
public string id;
public float x; // Horizontal coord
public float y; // Vertical coord
public Vertex(string id, float x, float y)
{
this.id = id;
this.x = x;
this.y = y;
}
}
and edge class:
public class Edge : MonoBehaviour {
public Vertex Vertex1; // Vertex one
public Vertex Vertex2; // Vertex two
public Edge(Vertex Vertex1, Vertex Vertex2)
{
this.Vertex1 = Vertex1;
this.Vertex2 = Vertex2;
}
}
Dont really know how to represent them in graph, because as input i have 3 dimensional wall and after some bricks are destroyed i need to check if top brick has path to any of the bottom bricks that are on floor, because if not wall will basically collapse. So looks like I have to check in 3 dimensions for all paths.
Edit 2:
in vertex class i added neighbors list public List<Vertex> Neighbours;
but still can't figure out how to represent graph in 3d so at least you could tell me how it'd be represented in 2d.
ps(thank you all for comments and answers I really appreciate them).
To find any path, you can use depth-first search. To find a shortest path, you can use breadth-first search. To find all paths (hence the number of paths), you can use either of the above and modify to (a) continue after finding the target node and (b) see if other paths can reach the target node (though it may have been reached previously). To find the path of least weight to the node (in a weighted graph), you can use Dijkstra's algorithm (no negative edges), Bellman-Ford (negative edges OK) or Floyd-Warshall (no negative cycles).
With a bit of pre-processing, you can answer those queries in near-constant time, which is useful when you have to test several pairs of nodes (it seems like you do).
The pre-processing is simple: initialize a disjoint set with V items (V is the number of vertices), then for every edge (x,y) call union(x, y). This is almost linear in the number of edges ("almost" meaning it differs by an inverse Ackerman factor, which is so close to constant that it might as well be actually constant).
To find whether there is a path between x and y, test find(x) == find(y).
You could find the number of possible paths between any pair by raising the adjacency matrix to the V'th power (using any fast exponentiation algorithm, but it will still be relatively slow).
It is simple
Put source vertex into queue
check if queue is empty, you are done, no path if not
check if it is one of the vertexes from the destination set, if yes you are done, path exists, if not, put all neighbors of that vertex to queue repeat steep 2
You only want to test for a path existence, so your best bet from a graph theory perspective is to use a BFS.
You have a source vertex src and a set Stgt of target vertices.
Since your graph is undirected when the BFS is over you will have the set of vertices of the connected component containing src. Just check if Stgt is a subset of that set.
To sum up:
Let Sbfs be an empty hashset of vertices
Perform a BFS starting from src:
When you discover a vertex v, insert it into Sbfs
Perform the intersection of Sbfs and Stgt to get all the target vertices that are reachable from src
Since you are seeking a simple solution, I would use a breadth-first search. A less-simple solution would involve something like the All-Pairs shortest path algorithm to determine the shortest path between every pair of nodes in a graph.
Related
The program uses vertices in R^2 as nodes and there are edges between nodes, and ultimately more is built from there. There are a high number of circuitous ways that a point (x,y) in R^2 might be reached that may rely on layer after layer of trig functions. So it makes sense to define one vertex as the canonical vertex for all points in a square with side length 2*epsilon centered at the point. So various calculations happen, out comes a point (x,y) where I wish to put a vertex, a vertex factory checks to see if there is already vertex deemed as canonical that should be used for this point, if so it returns that vertex, if not a new vertex is created with the coordinates of the point and that vertex is now deemed canonical. I know this can lead to ambiguities given the possibility for overlap of the squares but that is immaterial for the moment, epsilon can be set to make the probability of such a case vanishingly small.
Clearly a list of canonical vertices must be kept.
I have working implementations using List<Vertex> and HashSet<Vertex>, however the vertex creation process seems to scale poorly when the number of vertices grows to over over 100,000 and incredibly poorly if the number gets anywhere near 1,000,000.
I have no idea how to efficiently implement the VertexFactory. Right now Vertex has method IsEquivalentTo(Vertex v) and returns true if v is contained in the square around the instance vertex calling it, false otherwise.
So the the vertex creation process looks like this:
Some point (x,y) get calculated and requests a new vertex from the vertex manager.
VertexManager creates a temporary vertex temp then uses a foreach to iterate over every vertex in the container using IsEquivalentTo(temp) to find a match and return it, if no match is found then add temp to the container and return it. I should state that if a match is found obviously it breaks out of the foreach loop.
I may be way off but my first guess would be put an order on the vertices such as
v1 < v2 iff ( (v1.X < v2.X) || ( (v1.X == v2.X) && (v1.Y < v2.Y) ) )
and then store the vertices in a sorted container. But to be honest I do not know enough about about the various containers to know which is the most appropriate for the purpose, standard C# best practices, etc
Edit:
I cannot mark the comment as an answer so thanks to GSerg whose comment guided me to kd-trees. This is exactly what I was looking for.
Thanks
My challenge is to randomly generate a voxel tree that looks something like these: https://imgur.com/a/LT17der (not my own voxel work in photo)
For now i'm Just looking for ideas on how best to approach creating the trunk. I was thinking I'd start with setting the width and height of the the trunk and add each block at coordinate positions layer by layer with some degree of randomness as to where exactly the blocks are placed.
Any thoughts and suggestions are appreciated - for now i'm looking to keep it simple.
I would try to make a recursive function to generate the voxel tree.
It would take 3 arguments:
A vector representing the base of the current node
A vector representing the extent of the node
A 3-dimensional array of booleans, which represents the cells of the tree which are filled by the algorithm.
A counter, to limit the recursion depth
In Unity3D C#, it would look like:
void fillTree(Vector3 base, Vector3 extent, bool[,,] output, int depth)
And the first call to this recursive function would be
bool[,,] output = new bool[sizeX, sizeY, sizeZ];
fillTree(Vector3.zero, Vector3.up, output, 0)`.
This function will then:
Check that depth is not greater than the maximum, else return
Using a voxelization algorithm, write output with a capsule going from base to base + extent, with a thickness equal to something like 0.5^depth, so that each subtree is twice less thick as its parent (This can be pretty hard, so if performance is not a problem, just iterate naively over the whole grid, filling all voxel whose distance to the line segment [base; base + extent] is less than the thickness. Don't forget to map the float coordinates to the grid coordinates, by adding to each component of the vector the half of the grid size in the same dimension)
Choose a random number of subtrees (>= 2)
For each subtree :
Set a random horizontal angle alpha to be close to the horizontal angle of the parent, which can be retrieved using atan2(extent.z, extent.x) (Beward, an angle is cyclic, so 1 is considered as close to 359)!. The greater depth is, the closer the new angle must be from the parent one (the range must be proportional to something like 0.5^depth, the same as the thickness).
Set a vertical angle beta to be less than the vertical angle of the parent tree, so that branches seem to fall (the vertical angle of the parent can be computed as atan2(extent.y, sqrt(extent.x*extent.x + extent.z * extent.z)))
Compute the extent of the subtree, newExtent with the coordinates (cos(alpha)*cos(beta), sin(beta), sin(alpha)*sin(beta)). Normalize this vector and multiply it with something like 0.5^depth
call fillTree(base + extent, newExtent, output, depth + 1)
I have neither tested this algorithm yet, nor implemented it, and it is for sure far less beautiful as what you are trying to achieve, but I hope it helps you.
I trying to make a game where player only move forward in an infinity map, and the path (just thing of them like points, the path is only the visual) is procedurally generated. I want those path to have different length (something like the tree of life, but only branches of the selected path are generated).
This is how I generate branches without overlap:
List<Vector3> everyPos; //predetermined position
public void Spawn(int amount)
{
List<Vector3> possiblePos = new List<Vector3>(everyPos);
for (int i = 0; i < amount; i++)
{
int index = Random(0, possiblePos.Count); //Find a random position
SpawnObjectAt(currentPosition+possiblePos[index]));//Create a point there
possiblePos.RemoveAt(index); //Remove that position from the list
}
}
The problem is , look at this image(I can't embed image yet):
Red is where player start, green is possible spawn position in the first move.
If there are 2 point spawned at 1 and 2, player choose point1, then the possible position in the second time will be a point in the black zone, which include point2, so if I keep continue there will eventually overlap.
How can I avoid this? I'm making a mobile game so I don't want to cache every single point. Any help would be really appreciated! Thanks!
This is a small web game that have somewhat similar mechanic to what I trying to achieve: newgrounds.com/portal/view/592325/
This is an attempt here to answer, but honestly, you need to provide more information.
Depending on the language you are writing in, you can handle this differently. You may need dynamic allocation, but for now lets assume, since your idea is quite small, that you can just do one large array predefined before compile time.
I assume you know how to make an array, so create one with say, 500 length to start. If you want to 'generate' a link like they did in that game, you simply need a random function, (there is a built in library in pretty much every language I think) and you need to do a little math.
Whatever language you use will surely have a built in graphics library, or you can use a popular easy to use one. I'll just draw a picture to make this clear.
There are a number of ways you can do this mathematically as shown in the image, using angles for example, the simplest way, however, is just to follow the boxes.
If you have worked with graphics before, you know what a vector is, if not, you will need to learn. The 9 vectors presented in this image (0,1) (1,0) (1,1) etc. can be created as vector objects, or even stored as individual ints.
To make your nodes 'move' into another path, you can simply do a rand 1-9 and then correlated the result to one of 9 possible vectors, and then add them to your position vector. It is easiest to do this in array and just use the rand int as the index. In most c derived languages you do that like this:
positionVector += changeVectorArray[rand(1,9)];
You then increment your position vector by one of the 9 vectors as shown above.
The simplest way of making the 'path' is to copy the position before you add the change vector, and then store all of the changes sequentially in another 'path' array.
To show the path on screen, simply draw a line between the first and second, second and third, third and forth elements of your path array. This formula (of joining lines) is discrete mathematics if I'm not mistaken, and you can do much more complicated path shapes if you want, but you get the gist.
That should at least start you off. Without more info I can't really help you.
I could go off on a tangent describe a bunch of different ways you can make this happen differently but its probably easier if you just ask for specifics.
EDIT>>>
Continuing with this answer, yes, looking at it now, the nodes can definitely overlap. To solve this problem you could use collision detection, every time you generate a new 'position', before adding it and drawing the line you have to loop through your array like this:
boolean copy = true;
for(int i = 0; i < getLength(pathArray); i++){
if( newVector == pathArray[i]){
copy=false;
}
}
Then of course, if copy still is true, copy the new position int the pathArray. NOTE: this whole solution is sloppy as hell, and as your array gets larger, your program is going to take longer and longer to search through that loop. This may not also guarantee that the path goes in one direction, but it is likely. And note that the lines will still be able to overlap each other, even though the position vectors can't be on top of one another.
All this considered, I think it will work, the optimization is up to you. I would suggest that there is probably a much more efficient solution using a discrete formula. You can also use such a formula to make the path go in particular directions and do other more complicated things.
You could also quite easily apply constraints on your random rolls if you want to make the path go in a particular direction. But there are so many ways of doing this I can't begin to explain. You could google path-finding algorithms for that.
Good luck.
I am making a grid based game where characters can move their units turn by turn. Each character has a move amount (for example 4 - where they can move 4 tiles).
I've implemented a DLS (which is limited to their move amount). Using this, all available tiles that the player can move to are highlighted.
This works fine. However, I would like modify the algorithm (or implement a specific one) to work out the route. For example, the player wants to G3 - what route should the character take (forward 1, left 1 etc).
Bearing in mind that each tile can have different properties (such as some may be blocked).
Code
private void DLS(int x, int z, int depth, float jump, float previousHeight)
{
int resistance=1;
if (depth >=0)
{
tiles[x,z].GetComponentInChildren<CheckIfClicked>().Selected();
if (x+1 < 25)
{
CheckTile(x+1, z, depth, jump, previousHeight);
}
if (x-1 >= 0)
{
CheckTile(x-1, z, depth, jump, previousHeight);
}
if (z+1 <25)
{
CheckTile(x, z+1, depth, jump, previousHeight);
}
if (z-1 >=0)
{
CheckTile(x, z-1, depth,jump, previousHeight);
}
}
}
private void CheckTile(int x, int z, int depth, float jump, float previousHeight)
{
float tileHeight = tiles[x, z].GetComponent<TileDimensions>().height;
float difference = tileHeight - previousHeight;
if (difference<0) difference*=-1;
if (!tiles[x, z].GetComponentInChildren<CheckIfClicked>().occupied && difference<jump)
{
int resistance = tiles[x, z].GetComponent<TileDimensions>().getResistance();
if (resistance<0) resistance=1;
DLS(x, z, depth-resistance, jump, tileHeight);
}
}
My code takes advantage of the different tile properties (such as the tiles resistance (some tiles limit the movement) and height (you can only climb so far up)).
If you wish to use a more efficient algorithm there are two suggested implementations:
A star. A star is best used when you know the destination you want to travel to but you need to find the way of getting there. e.g if you clicked in tile G3, and were in G1, you know where you need to go. A star takes advantage of a heuristic which tries to "guess" how much further you have to go. This means that when searching for potential routes, A star will attempt to take what should be the shortest route before attempting to look at other routes. There's a fantastic tutorial here: Link
Djikstra's algorithm. This is better used when you don't know where you're going but you want to find the nearest node that contains a certain "thing", i.e. you might want your A.I to search for the nearest health pack in an FPS. I've not implemented Djikstra's algorithm before but there are plenty of tutorials available online.
With both you can add properties such as resistance on certain tiles and whatever else.
Since your algorithm is working, I would like to give you a few suggestions to enhance your code, both involve using list/dictionary.
Perform path searching once
If you can highlight every movable tiles, that means you are able to traverse paths originating from a source tile to different destination tiles, which implies you are validating the tiles one by one until the character cannot make additional moves. Therefore, you can store the results into a dictionary of "destination tile - lists" pairs. Whenever you need to retrieve a path going to a particular tile, just get the previously stored path.
Perform path searching twice
As the aforementioned approach may take up a lot of memory usage, you can run your path-searching algorithm once more when the player makes a move. Time spent for the second execution should be less than the first one, as the player has specified certain tile to be the destination of the path. During the second search, keep updating a list/dictionary while recursively executing the path-searching functions. Have every valid intermediate tile saved to the list/dictionary, then you can get the path after the search.
If you are developing games on mobile platforms, even a little bit of memory usage does matter. I would then suggest to perform path searching twice as long as the time spent for searching is acceptable to players.
Of course, it is always a good practice to monitor the performance via the Unity Profiler to check which approach suits your needs in a better manner.
I have 2D world maps that are basically Mercator-Like projections, (If you walk west long enough you end up east of where you started)
Question I have: Can you use A* for computing paths on these types of maps as well?
I can't think of any reason why you couldn't (I'm thinking that you would simply represent the edge map nodes such that the North, South, East, Wed, "border" nodes simply connected to the opposite side).
Thanks in advance, if anyone has seen something like this before or can give me a few hints I would appreciate it.
Pathfinding algorithms don't really care about global topology of the map. The only tricky part is to get a good estimator for A* but using the 3D distance should be ok if your map is indeed a surface in a 3d space and step cost is step length.
Your map can have all sort of strange "connections" (including for example knotted bridges) and this will not be a problem if you implement A* correctly.
I can't imagine why a Mercator-Like projections would cause a problem for A*, as long as your heuristic function approximates distances correctly. I think something along the below function should work fine
float heuristic(point from, point to, size mapsize) {
float x = from.x - to.x;
if (abs(x) > mapsize.x/2)
x = mapsize.x - x;
float y = from.y - to.y;
if (abs(y) > mapsize.y/2)
y = mapsize.y - y;
return sqrt(x*x+y*y);
}
Edited: I realize know I was misled by the non-graph theoretical) use of the word edge (where the question title strongly suggested a graph algorithm question :))
Why do you suppose there are no edges? There are many logical discrete locations that you could model, and limited connections between (i.e. not where a wall is :)). There you go: you have your edges.
What you probably mean is that you don't want to represent your edges in data (which you don't have to, but still there are the logical edges that connect locations/points.)
That said:
you ask whether someone has seen things like this before. I vaguely recall seeing something relevant to this in Knuths Dancing Links article (DLX) which is an implementation technique for A* algorithms.
http://en.wikipedia.org/wiki/Dancing_Links
original publication [PDF]
The article specifically treats states as 'cells' (in a grid) with east/west/north/south links. It's been a long time so I don't quite recall how you would map (no pun intended) your problem on that algorithm.
The dance steps. One good way to implement algorithm X is to represent each 1 in the
matrix A as a data object x with five fields L[x]; R[x]; U [x]; D[x]; C[x]. Rows of the matrix
are doubly linked as circular lists via the L and R fields ("left" and "right"); columns are
doubly linked as circular lists via the U and D fields ("up" and "down"). Each column
list also includes a special data object called its list header.