Flex and polygonal.de graph classes in pathfinding? - apache-flex

I am wondering if someone have done this already, to send me into right direction..
The issue is as follow : I have a 2 dimensional array, on which i hold integer numbers, if the number is 0 - the item shall not be included into the graph, if it is 1 - it must be included.
The result graph shall be used for patfinding ( the shortest path ) to some element.
how to turn this 2 dimensional array into the graph ? ( with polygona.de classes if possible ),
I am currently trying with Polygonal.de classes. any suggestions and points into the right direction is more than appreciated.
This is the 2 dimensional structure. The red cells is prohibited to walk on, and there must be found optimal path from "start" to the "end". But 1st things 1st - i need to turn this 2 dimensional structure into a graph now :|

The way I see it, your 2D array is already a graph. A node of the graph is represented by a pair (i, j) and may have neighbor nodes such as (i + 1, j), (i, j + 1), etc. You can write a utility function for your array that hides these low-level neighbor definitions and skips the cells that are occupied.
The de.polygonal.ds API for the Graph data structure contains this example for the construction of a graph:
var graph = new de.polygonal.ds.Graph<String>();
var a = graph.addNode("a");
var b = graph.addNode("b");
var c = graph.addNode("c");
graph.addSingleArc(a, b, 1.0);
graph.addSingleArc(b, a, 1.0);
graph.addMutualArc(a, c, 1.0);
Adjust the example to construct a 2D array that contains a node for each free (i, j) of the original 2D array. Then traverse the 2D array of nodes and call addMutualArc() to connect adjacent nodes.

Related

Detecting cycles in Topological sort using Kahn's algorithm (in degree / out degree)

I have been practicing graph questions lately.
https://leetcode.com/problems/course-schedule-ii/
https://leetcode.com/problems/alien-dictionary/
The current way I detect cycles is to use two hashsets. One for visiting nodes, and one for fully visited nodes. And I push the result onto a stack with DFS traversal.
If I ever visit a node that is currently in the visiting set, then it is a cycle.
The code is pretty verbose and the length is long.
Can anyone please explain how I can use a more standard top-sort algorithm (Kahn's) to detect cycles and generate the top sort sequence?
I just want my method to exit or set some global variable which flags that a cycle has been detected.
Many thanks.
Khan's algorithm with cycle detection (summary)
Step 1: Compute In-degree: First we create compute a lookup for the in-degrees of every node. In this particular Leetcode problem, each node has a unique integer identifier, so we can simply store all the in-degrees values using a list where indegree[i] tells us the in-degree of node i.
Step 2: Keep track of all nodes with in-degree of zero: If a node has an in-degree of zero it means it is a course that we can take right now. There are no other courses that it depends on. We create a queue q of all these nodes that have in-degree of zero. At any step of Khan's algorithm, if a node is in q then it is guaranteed that it's "safe to take this course" because it does not depend on any courses that "we have not taken yet".
Step 3: Delete node and edges, then repeat: We take one of these special safe courses x from the queue q and conceptually treat everything as if we have deleted the node x and all its outgoing edges from the graph g. In practice, we don't need to update the graph g, for Khan's algorithm it is sufficient to just update the in-degree value of its neighbours to reflect that this node no longer exists.
This step is basically as if a person took and passed the exam for
course x, and now we want to update the other courses dependencies
to show that they don't need to worry about x anymore.
Step 4: Repeat: When we removing these edges from x, we are decreasing the in-degree of x's neighbours; this can introduce more nodes with an in-degree of zero. During this step, if any more nodes have their in-degree become zero then they are added to q. We repeat step 3 to process these nodes. Each time we remove a node from q we add it to the final topological sort list result.
Step 5. Detecting Cycle with Khan's Algorithm: If there is a cycle in the graph then result will not include all the nodes in the graph, result will return only some of the nodes. To check if there is a cycle, you just need to check whether the length of result is equal to the number of nodes in the graph, n.
Why does this work?:
Suppose there is a cycle in the graph: x1 -> x2 -> ... -> xn -> x1, then none of these nodes will appear in the list because their in-degree will not reach 0 during Khan's algorithm. Each node xi in the cycle can't be put into the queue q because there is always some other predecessor node x_(i-1) with an edge going from x_(i-1) to xi preventing this from happening.
Full solution to Leetcode course-schedule-ii in Python 3:
from collections import defaultdict
def build_graph(edges, n):
g = defaultdict(list)
for i in range(n):
g[i] = []
for a, b in edges:
g[b].append(a)
return g
def topsort(g, n):
# -- Step 1 --
indeg = [0] * n
for u in g:
for v in g[u]:
indeg[v] += 1
# -- Step 2 --
q = []
for i in range(n):
if indeg[i] == 0:
q.append(i)
# -- Step 3 and 4 --
result = []
while q:
x = q.pop()
result.append(x)
for y in g[x]:
indeg[y] -= 1
if indeg[y] == 0:
q.append(y)
return result
def courses(n, edges):
g = build_graph(edges, n)
ordering = topsort(g, n)
# -- Step 5 --
has_cycle = len(ordering) < n
return [] if has_cycle else ordering

Ideas on how to beat a greedy search algorithm in maze by collecting maximum items?

First I'll explain the problem. I have a player in a closed maze filled with items that he should collect to win the game. We also have an opponent which tries to do just the same.The player with the biggest amount for items collected wins. Suppose the opponent follows a BFS algorithm to collect the items, and we have access to all its decisions for every turn, can we make some prediction on what items in the maze should we go to first (so it doesn't get a chance in having the ones close to it), or just pin point a location where items are more dense?
It feels like randomness could also affect this very badly (most of the items land next to the opponent for example). What about if the opponent follows an A* algorithm?
I have already implemented an A* algorithm for our player.First, I look for the closest item heuristically using manhattan distance, then i go collect it and look for the new closest one again and so on.I feel like the "looking for the closest item" method might not be that efficient, maybe pin pointing (somehow haha) a location where the items are more dense is better as i said.
def astar(start, items, mazeMap):
# mazeMap is a dictionary with nodes and as a key for every node
is associated another dictionary containing the neighbors as keys
and the weight of edges to them as values
# items is a list of pairs giving the location of each item
# Apparent goal
# goal is a pair (closest_item, distance_to_closest_item)
goal = closest_item(start, items)
# Set of nodes not needed to be checked anymore
# closedSet = {node: [gscore, fscore]}
closedSet = {}
# Set of potential short-path nodes
# openSet = {node: [gscore, fscore]}
openSet = {start: [0, goal[1]]}
# Set to construct the optimal path
cameFrom = {}
while len(openSet) > 0:
# Looking for the node with the smallest fscore
current = list(openSet.keys())[0]
for keys, values in openSet.items():
if values[1] < openSet[current][1]:
current = keys
# If the chosen node is an item of cheese, we are done
if current in items:
return reconstruct_path(cameFrom, current)
# The current node no longer needs to be checked
closedSet[current] = openSet[current]
del openSet[current]
for keys, values in mazeMap[current].items():
# We don't need to check the node if it's already been done
if keys in list(closedSet.keys()):
continue
# Calculate Gscore
tentative_gscore = closedSet[current][0] + values
if keys not in list(openSet.keys()):
openSet[keys] = [0, 0]
elif tentative_gscore >= openSet[keys][0]:
continue
# This new path is better than the previous one, save it !
cameFrom[keys] = current
openSet[keys][0] = tentative_gscore
openSet[keys][1] = tentative_gscore + manhattan_distance(keys, goal[0])
return "Impossible"

Calculate length of a shared edge of two polygones in PostGIS

I have a database of several polygones. Each polygon has a lot of nodes which define it. Additionally each polygone has at least one neighbour. For a calculation I need to determine the length of the shared edge of two neighboured polygones. In the example picture such a case is shown. The two polygones share the red edges. How can I calculate the length of the red edge with the help of PostGIS? I didn't find a function for that.
You can get the intersection of two polygons, then get the length(s) of any LineStrings. For example, take two geometries:
SELECT ST_Length(ST_CollectionExtract(ST_Intersection(a_geom, b_geom), 2))
FROM (
SELECT
'POLYGON((70 170,160 250,240 220,270 130,185 62,90 80,70 170))'::geometry AS a_geom,
'POLYGON((160 250,236 314,380 290,390 150,270 130,240 220,160 250))'::geometry AS b_geom
) f;
Or do this for all pairs of polygons in a table mypoly that touch:
SELECT a.gid AS gid_a, b.gid AS gid_b,
ST_Length(ST_CollectionExtract(ST_Intersection(a.geom, b.geom), 2))
FROM mypoly a, mypoly b
WHERE a.gid < b.gid AND ST_Touches(a.geom, b.geom);
You can also explore the Topology extension, which is part of PostGIS 2.x.

Search common subgraph between two graphs

I have two graphs G, H labeled and I want to extract all common subgraph of two graphs, I got to a part that is:
1 - extract all the nodes that are in common, but I'm stuck on the part that includes:
2 - Step 1: Take the First vertex and store it in a set P = {first element} (which will be the set of all common subgraph), and go to 2nd if it is adjacent to the first of the two P graph G and H, we add it, and so on, but I do not know how to do it when i have more than 2
That is a NP-complete problem. See http://en.wikipedia.org/wiki/Subgraph_isomorphism_problem

How to determine endpoints of Arcs in GraphicsPath PathPoints and PathTypes arrays?

I have the following PathPoints and PathTypes arrays (format: X, Y, Type):
-177.477900, 11021.670000, 1
-614.447200, 11091.820000, 3
-1039.798000, 10842.280000, 3
-1191.761000, 10426.620000, 3
-1591.569000, 10493.590000, 3
-1969.963000, 10223.770000, 3
-2036.929000, 9823.960000, 3
-2055.820000, 9711.180000, 3
-2048.098000, 9595.546000, 3
-2014.380000, 9486.278000, 3
Here is what this GraphicsPath physically looks like. The 2 Arcs are very distinguishable:
I know that this GraphicsPath.PathData array was created by 2 AddArc commands. Stepping through the code in the debugger, I saw that the first 4 PathData values were added by the first AddArc command, and the remaining 6 points were added by the 2nd AddArc command.
By examining the raw pathpoints/pathtype arrays (without previously knowing that it was 2 AddArc commands so I would know that I have 2 start and end points), I would like to determine to start and end point of each arc.
I have tried several Bezier calculations to 'recreate' the points in the array, but am at a loss to determine how to determine the separate start and end points. It appears that GDI+ is combining the start/end point between the arcs (they are the same point and the arcs are connected), and I am losing the fact that one arc is ending and other one is starting.
Any ideas?
Use the GraphicsPathIterator class in combination with the GraphicsPath.SetMarkers method.
For example:
dim gp as new GraphicsPath
gp.AddArc(-50, 0, 100, 50, 270, 90) 'Arc1
gp.SetMarkers()
gp.AddArc(0, 25, 100, 50, 270, 90) 'Arc2
Dim iterator as New GraphicsPathIterator(gp)
Dim i as Integer = 0
Dim MyPts(3) As PointF
Dim temp as New GraphicsPath
Do until i > 2
iterator.NextMarker(temp)
MyPts(i) = temp.PathPoints(0)
MyPts(i + 1) = temp.GetLastPoint()
i += 2
Loop
'Free system resources...
iterator.Dispose()
temp.Dispose()
Arc1 -> start: MyPts(0); end: MyPts(1)
Arc2 -> start: MyPts(2); end: MyPts(3)
Hope this helps!
Take a look at the PathPointType Enum (System.Drawing.Drawing2D).
Value Meaning
0 Start (path)
1 Line
3 Bezier/Bezier3
7 PathType Mask
16 Dash Mode
32 Path Marker
128 Close Subpath
This one was bugging me a lot too! I had path created beyond my control without markers and couldn't figure out curve endpoints.
In this case you'd expect that the curve starts at [i + 1] but it is not! It turns out that GDI combines path points probably to make the points array shorter. In this case the curve points are: [0], [1], [2], [3].
It seems that if PathPointType.Start or PathPointType.Line is followed by PathPointType.Bezier, then you have to treat the PathPontType.Start or Path.PointType.Line as a first point of your Bezier curve, so in your example it should be like this:
-177.47, 11021.67, 1 // Draw line to this point AND use it as a Bezier start!
-614.44, 11091.82, 3 // Second Bezier point
-1039.79, 10842.28, 3 // Third Bezier point
-1191.76, 10426.62, 3 // Fourth Bezier point AND first point of the next Bezier!
-1591.56, 10493.59, 3 // Second Bezier point
-1969.96, 10223.77, 3 // Third Bezier point
-2036.92, 9823.96, 3 // Fourth Bezier point AND first point of the next Bezier!
-2055.82, 9711.18, 3 // Second Bezier point
-2048.09, 9595.54, 3 // Third Bezier point
-2014.38, 9486.27, 3 // Fourth Bezier point
So, when analysing PathPoints array point by point, you have to also check current and following indices. The docs on PatPointType might come in handy. In most cases you can probably ignore additional data stored on bits other than the first three (these three define Start, Line and Bezier). The only exception is CloseSubpath but it's irrelevant if you consider the next advice.
It's also worth noting that if you have a complex path that consists of huge number of PathPoints then it might be handy to split the path into chunks using GraphicsPathIterator. This simplifies the whole procedure as PathPointType.CloseSubpath can be ignored - it will be always the last point of your GraphicsPath chunk.
A quick look into Reflector or here might be helpful if you want to better understand PointTypes array.

Resources