Putting graph on a grid - algorithm

I have a directed graph with no loops with the following additional information:
Every vertex has outdegree at most 4.
Every edge is labeled 'up', 'right', 'down' or 'left'.
If there is an 'up' edge from A to B, then there is a 'down' edge from B to A (i.e. it is symmetric).
All edges which start at the same vertex have different labels.
I am looking for an algorithm that would assign 2d integer coordinates to each vertex, such that y(B) > y(A) whenever there is an 'up' edge from A to B, and similarly for other types of edges. Moreover, edges should not intersect.
For example, this is a picture of such a graph with 8 vertices:
1-------2---3
| |
| 4 |
| | |
5---6---7---8
Note, that y(4) < y(1), since otherwise there would be intersecting edges.
I realize that the solution is far from unique, so one may require the result to have the minimal size in some sense.

Related

divide and conquer algorithm for finding a 3-colored triangle in an undirected graph with the following properties?

In an undirected Graph G=(V,E) the vertices are colored either red, yellow or green. Furthermore there exist a way to partition the graph into two subsets so that |V1|=|V2| or |V1|=|V2|+1 where the following conditions apply: either every vertex of V1 is connected to every vertex of V2 or no Vertex of V1 is connected to a vertex of V2 . This applies recursively to all induced subgraphs of V1 and V2
I can find all triangles in the Graph by multiplying the adjacency matrix with itself three times and step up the nodes corresponding to the non zero entries of the main diagonal. Then I can see if the nodes of the triangle are colored the right way. O(n^~2,8)! But given the unique properties of the graph I want to find a solution using divide and conquer to find the colored triangle.
this is an example graph with the given properties. I need to find the bold triangle:
Blue boxes symbolize the partitions are fully connected, purple boxes mean no connection between the partitions
It can be done in O(E*V) without using the partition property.
Start by deleting all edges with the same color on both vertexes, this can be done in O(E).
In the modified graph G', every triangle is a 3-colored triangle.
Finding the triangles in a graph:
for each edge e(u,v):
for each vertex w:
if e(v,w) and e(u,w) in G':
add (u,v,w) to triangle list
If you keep adjacency list as well as adjacency matrix, you can improve the time of the inner loop by checking only w's in the adjacency list of v.
In that case the complexity is O(E * max(deg(v)).
Problem Statement:
To find all the triangles in an undirected graph with vertices of different colours. (Red, Yellow and Green).
Assumptions:
There exists a way to partition the graph into two subsets so that |V1|=|V2| or |V1|=|V2|+1 where the following conditions apply: either every vertex of V1 is connected to every vertex of V2 or no Vertex of V1 is connected to a vertex of V2 . This applies recursively to all induced subgraphs of V1 and V2.
Logic:
We can break the graph into two subgraphs recursively and find a triangle formed between one vertex in V1 and other two in V2 or one vertex in V2 and other two in V1.
At each recursive call, we can partition the given graph into V1, V2 which will satisfy the above property (function partition already given). The recursion breaks when the size of either V1, V2 becomes zero or both become equal to 1. This function is called recursively for both V1 and V2. If there is no edge between V1 and V2, we need not consider this partition for our final triangle list; so we return from this call.
Now, for each vertex in V2, we add to a globally declared colour map for the three colour combinations. Using this map, for each vertex in V2,we check the corresponding other colour combination and add this to the triangle list.
Pseudo Implementation
//let g be the given graph.
//Vertex be the class representing each vertex ( will have attributes 'vertex_number' + 'colour')
//let Edge be the class representing edges ( will have attributes 'a' and 'b' corresponding to two edges
//let (v1,v2) = partition(g) be the given function which can partition the graph into V1, v2.
//let adjacency_list be the ArrayList<ArrayList<Vertex>> containing the Adjacency list for the given vertices
//Main Callee Method
HashMap<String, List<Edge>> edge_list = new HashMap<String, List<Edge>>()
ArrayList<ArrayList<Vertex>> adjacency_list = new ArrayList<ArrayList<Vertex>>()
edge_list.put('rg', new ArrayList<Edge>())
edge_list.put('gy', new ArrayList<Edge>())
edge_list.put('yr', new ArrayList<Edge>())
ArrayList<new ArrayList<Vertex>> triangle_list = new ArrayList<new ArrayList<Vertex>>()
getColouredTriangles(g)
//Recursive Implementation of Coloured Triangle method
getColouredTriangles(g):
(v1,v2) = partition(g)
//If size is zero or both have size as 1 no triangles can be formed
if v1.size() == 0 || v2.size() == 0 || (v1.size() == 1 && v2.size() == 1):
return
//Calling recursively for both v1 and v2
getColouredTriangles(v1)
getColouredTriangles(v2)
//If there is no edge between the two subgraphs, return as no triangle is possible now between v1 and v2.
if not edge(v1.get(0), v2.get(0)):
return
//call for one vertex in v1, two in v2
getTrianglesInTwoGraphs(v1,v2)
//call for one vertex in v2, two in v1
getTrianglesInTwoGraphs(v2,v1)
//Method to get triangles between two graphs with one vertex in v1 and other two in v2.
getTrianglesInTwoGraphs(v1,v2):
//Form edge_list having colour to Edge mapping
for v in v2:
for vertex in adjacency_list.get(v):
if vertex in v2:
String colour = v.colour + vertex.colour
if(edge_list.get(colour) == null):
colour = vertex.colour + v.colour
edge_list.colour.put(colour,vertex.edge)
//for each v in v1, check other coloured edges from edge_list
for v in v1:
ArrayList<Edge> edges = new ArrayList<Edge>()
if v.colour == r:
edges = edge_list.get("gy")
else if v.colour == g:
edges = edge_list.get("yr")
else:
edges = edge_list.get("rg")
for edge in edges:
ArrayList<Vertex> vertices = new ArrayList<Vertex>()
vertices.add(v)
vertices.add(edge.a)
vertices.add(edge.b)
triangle_list.add(vertices)
Result:
The global variable triangle_list contains the vertex groups with coloured triangles.

Finding all the rectangles within a given rectangle that do not intersect with an arbitrary shape

I need to find an algorithm to find the least number of overlapping rectangles within a given rectangle R that do not intersect with the union of a set of other rectangles contained within R. These inner rectangles can overlap. Here's a terrible ASCII drawing of an example R:
A-----------------B-------------------------+
| |
| |
| |
| |
| +--------+ |
| |........| |
| |........| |
C +---D........| |
| |.........+--+ |
| |.........| |
| ++........+------+ |
| |...............| |
G +---H...........| |
| |...........| |
| |...........| |
| |...........| |
| +-----------+ |
| |
| |
| |
E-------------I----F------------------------+
The rectangles here would include (A, D), (A, I), (G, F). This seems like a problem for which the solution is well-understood, but for which I simply lack the vocabulary. Any answers, pointers, RTFMs cheerfully and gratefully accepted. Thanks!
EDIT: As per #Paul's observation below, what I'm trying to do is find a set of rectangles that cover the space in R without covering any of polygon comprised of the union of the inner set. If that makes sense.
I believe this is one possible way to solve.
I will refer to the overlapping rectangles as "white", and the ones in the solution as "black"
First of all, let's assume we have a data structure suitable for search on intersection. One possible data structure is an Interval Tree, using points on one of the coordinates as intervals (for example, if a rectangle is defined by two points (x0,y0) and (x1, y1), use (x0, y1) as interval. The link also explain how to extend to higher dimensions (in your case you need 2).
I won't go in the detail of an implementation of such data structure, but let's assume we have one called Rectangles, with the following API defined:
void add(Rectangle r)
void remove(Rectangle r)
Rectangle[] getIntersecting(Rectangle r)
Rectangle[] getAdjacent(Rectangle r)
Ok, now create two instances of Rectangles called black and white. Initialize white with all the white rectangles. Initializie black with the R rectangle (the whole domain).
For each rectangle rw in white get the array arr of intersecting rectangles from black.
For each rectangle rb in black, determine the result of rw-rb. This is a set set of 0, 1, 2, 3 or 4 rectangles, depending on how the two rectangles intersect.
remove rw from white, and add the content of set to it. This may require merging rectangles from set with rectangle already in white, if such rectangles together form a larger rectangle (they're adjacent sharing one side)
remove rb from black
repeat from 1 until there are no more rectangles in black
Using some basic math, we could say the solution to your problem would be the decomposition of the rectilinear polygon R \ union(rs), where union(rs) represents the polygon inside R. Calculating R \ union(rs) can be done using the Greiner-Hormann-algorithm. Note that this step will result in a polygon with holes and - only if the inner polygon contains holes - multiple other polygons. The decomposition is described here (this is only an approximation, but i wasn't able to find a precise algorithm so far).

find the outline of adjacent polygons

I'm searching for a way to find the outline of two adjacent polygons.
The polygons are defined by a list of points ordered by occurrence in the polygon. In my use case, there are no overlapping polygons, there are no gaps between the polygons, and there are no polygons with "holes".
I want to calculate the outline of the two polygons without any "holes".
These pictures show the expected results.
I know that there are a lot of libraries for clipping polygons, but for most of them the performance is not very good because they work for any kind of polygon (with holes, overlapping polygons etc.). In my use case the algorithm has to work in real time for a lot of polygons (>20.000). How can I most efficiently calculate the outline?
Given
no overlapping polygons, there are no gaps between the polygons and there are no polygons with "holes"
the following algorithm should do the trick.
Discard duplicate line segments.
Compute the natural combinatorial embedding of what's left as a doubly connected edge list. Each segment gives rise to two nodes (half edges, reverses of each other, with one endpoint of the segment being the head (respectively, the tail) and the other being the tail (respectively, the head)), and each half edge links to the next half edge with the same head in counterclockwise order.
Extract the faces. A face in the combinatorial embedding is a minimal, nonempty set of half edges such that, for each half edge e, the reverse of the next half edge from e is in the set. The set of faces is a partition of the half edges. See the ASCII art diagram below.
U----V----W
| | |
| | |
Z----Y----X
The infinite face is {U->Z, Z->Y, Y->X, X->W, W->V, V->U}. The next half edge from W->V is U->V. The reverse of the next half edge from W->V is V->U. The other faces are {U->V, V->Y, Y->Z, Z->U} and {V->W, W->X, X->Y, Y->V}.
Retain only the infinite faces by summing signed counterclockwise angles and testing the sign. A finite face like {U->V, V->Y, Y->Z, Z->U} has negative sum
/_UVY - 180 + /_VYZ - 180 + /_YZU - 180 + /_ZUV - 180
= 4 * (90 - 180) = -360.
The infinite face has positive sum
/_UZY - 180 + /_ZYX - 180 + /_YXW - 180 + /_XWV - 180 + /_WVU - 180 + /_VUZ - 180
= 4 * (270 - 180) + 2 * (180 - 180) = 360.

Optimizing the layout of a graph with given (erroneous) node-distances

I have a loosely connected graph. For every edge in this graph, I know the approximate distance d(v,w) between node v and w at positions p(v) and p(w) as a vector in R3, not only as an euclidean distance. The error shall be small (lets say < 3%) and the first node is at <0,0,0>.
If there were no errors at all, I can calculate the node-positions this way:
set p(first_node) = <0,0,0>
calculate_position(first_node)
calculate_position(v):
for (v,w) in Edges:
if p(w) is not set:
set p(w) = p(v) + d(v,w)
calculate_position(w)
for (u,v) in Edges:
if p(u) is not set:
set p(u) = p(v) - d(u,v)
calculate_position(u)
The errors of the distance are not equal. But to keep things simple, assume the relative error (d(v,w)-d'(v,w))/E(v,w) is N(0,1)-normal-distributed. I want to minimize the sum of the squared error
sum( ((p(v)-p(w)) - d(v,w) )^2/E(v,w)^2 ) for all edges
The graph may have a moderate amount of Nodes ( > 100 ) but with just some connections between the nodes and have been "prefiltered" (split into subgraphs, if there is only one connection between these subgraphs).
I have tried a simplistic "physical model" with hooks low but its slow and unstable. Is there a better algorithm or heuristic for this kind of problem?
This looks like linear regression. Take error terms of the following form, i.e. without squares and split into separate coordinates:
(px(v) - px(w) - dx(v,w))/E(v,w)
(py(v) - py(w) - dy(v,w))/E(v,w)
(pz(v) - pz(w) - dz(v,w))/E(v,w)
If I understood you correctly, you are looking for values px(v), py(v) and pz(v) for all nodes v such that the sum of squares of the above terms is minimized.
You can do this by creating a matrix A and a vector b in the following way: every row corresponds to one of equation of the above form, and every column of A corresponds to one variable, i.e. a single coordinate. For n vertices and m edges, the matrix A will have 3m rows (since you separate coordinates) and 3n−3 columns (since you also fix the first node px(0)=py(0)=pz(0)=0).
The row for (px(v) - px(w) - dx(v,w))/E(v,w) would have an entry 1/E(v,w) in the column for px(v) and an entry -1/E(v,w) in the column for px(w). All other columns would be zero. The corresponding entry in the vector b would be dx(v,w)/E(v,w).
Now solve the linear equation (AT·A)x = AT·b where AT denotes the transpose of A. The solution vector x will contain the coordinates for your vertices. You can break this into three independent problems, one for each coordinate direction, to keep the size of the linear equation system down.

How to find the polygon enclosing a point from a set of lines?

I have a set of non-intersecting lines, some of which are connected at vertices. I'm trying to find the smallest polygon, if one exists, that encloses a given point. So, in the image below, out of the list of all the line segments, given the point in red, I want to get the blue ones only. I'm using Python, but could probably adapt an algorithm from other languages; I have no idea what this problem is called.
First, remove all line segments that have at least one free endpoint, not coincident with any other segment. Do that repeatedly until no such segment remains.
Now you have a plane nicely subdivided into polygonal areas.
Find a segment closest to your point. Not the closest endpoint but the closest segment, mind you. Find out which direction along the segment you need (your point should be to the right of the directed segment). Go to the endpoint, turn right (that is, take the segment next to the one you came from, counting counterclockwise). Continue going to the next endpoint and turning right until you hit the closest segment again.
Then, check if the polygon encloses the given point. If it is not, then you have found an "island"; remove that polygon and the entire connected component it belongs to, and start over by selecting the nearest segment again. Connected components can be found with a simple DFS.
This gives you a clockwise-oriented polygon. If you want counterclockwise, which is often the default "positive" direction in both the software an the literature, start with the point to your left, and turn left at each intersection.
It surely helps if, given an endpoint, you can quickly find all segments incident with it.
This is really just an implementation of #n.m.'s answer.
This is how far I got before the bounty expired; it's completely untested.
def smallestPolygon(point,segments):
"""
:param point: the point (x,y) to surrond
:param segments: the line segments ( ( (a,b),(c,d) ) , . . . )
that will make the polygon
(assume no duplicates and no intersections)
:returns: the segments forming the smallest polygon containing the point
"""
connected = list(segments)
def endPointMatches(segment1,segment2):
"""
Which endpoints of segment1 are in segment2 (with (F,F) if they're equal)
"""
if ( segment1 == segment2 or segment1 == segment2[::-1] ):
return ( False, False )
return ( segment1[0] in segment2 , segment1[1] in segment2 )
keepPruning = True
while ( keepPruning ):
keepPruning = False
for segment in connected:
from functors import partial
endPointMatcher = partial(endPointMatches,segment1=segment)
endPointMatchings = map(endPointMatcher,connected)
if ( not and(*map(any,zip(*endPointMatchings))) ):
connected.remove(segment)
keepPruning = True
def xOfIntersection(seg,y):
"""
:param seg: a line segment ( (x0,y0), (x1,y1) )
:param y: a y-coordinate
:returns: the x coordinate so that (x,y) is on the line through the segment
"""
return seg[0][0]+(y-seg[0][1])*(seg[1][0]-seg[0][0])/(seg[1][1]-seg[0][1])
def aboveAndBelow(segment):
return ( segment[0][1] <= point[1] ) != ( segment[1][1] <= point[1] )
# look for first segment to the right
closest = None
smallestDist = float("inf")
for segment in filter(aboveAndBelow,connected):
dist = xOfIntersection(segment,point[1])-point[0]
if ( dist >= 0 and dist < smallestDist ):
smallestDist = dist
closest = segment
# From the bottom of closest:
# Go to the other end, look at the starting point, turn right until
# we hit the next segment. Take that, and repeat until we're back at closest.
# If there are an even number of segments directly to the right of point[0],
# then point is not in the polygon we just found, and we need to delete that
# connected component and start over
# If there are an odd number, then point is in the polygon we found, and we
# return the polygon
Approach.
I suggest to interpret the input as a PSLG, G, which consists of vertices and edges. Then your question reduces to finding the face of G that is hit by the point p. This is done by shooting a ray from p to some direction to find an edge of the boundary of the face and traverse the boundary of the face in some direction. However, the first edge hit could be a face that is not hit by p, but itself enclosed by the face hit by p. Hence, we may need to keep search along the ray emanated by p.
Implementational details.
In the code below I shoot a ray to east direction and run around the face in clockwise direction, i.e., at each vertex I take the next counter-clockwise edge, until I end up at the first vertex again. The resulting face is returned as a sequence of vertices of G.
If you want to return a simple polygon then you have to clean-up the input graph G by pruning of trees in G such that only the simple faces remain.
def find_smallest_enclosing_polygon(G, p, simple=False):
"""Find face of PSLG G hit by point p. If simple is True
then the face forms a simple polygon, i.e., "trees"
attached to vertices are pruned."""
if simple:
# Make G comprise simple faces only, i.e., all vertices
# have degree >= 2.
done = False
while not done:
done = True
for v in [v in vertices if degree(v) <= 1]:
# Remove vertex v and all incident edges
G.remove(v)
done = False
# Shoot a ray from p to the east direction and get all edges.
ray = Ray(p, Vector(1, 0))
for e in G.iter_edges_hit(ray):
# There is no enclosing face; p is in the outer face of G
if e is None:
return None
# Let oriented edge (u, v) point clockwise around the face enclosing p
u, v = G.get_vertices(e)
if u.y < v.y
u, v = v, u
# Construct the enclosing face in clockwise direction
face = [u, v]
# While not closed
while face[-1] != face[0]:
# Get next counter-clockwise edge at last vertex at last edge.
# If face[-1] is of degree 1 then I assume to get e again.
e = G.get_next_ccw_edge(face[-2], face[-1])
face.append(G.get_opposite_vertex(e, face[-1]))
# Check whether face encloses p.
if contains(face, p):
return face
return None
Complexity.
Let n denote the number of vertices. Note that in a PSLG the number of edges are in O(n). The pruning part may take O(n^2) time the way it is implemented above. But it could be one in O(n) time by identifying the degree-1 vertices and keep traversing from those.
The ray intersection routine can be implemented trivially in O(n) time. Constructing the face takes O(m) time, where m is the size of the polygon constructed. We may need to test multiple polygons but the sum of sizes of all polygons is still in O(n). The test contains(face, p) could be done by checking whether face contains an uneven number of edges returned by G.iter_edges_hit(ray), i.e., in O(m) time.
With some preprocessing you can build up a data structure that finds the face hit by p in O(log n) time by classical point location algorithms in computational geometry and you can store the resulting polygons upfront, for the simple and/or non-simple cases.
If you're doing this a number of times with the same lines and different points, it would be worthwhile preprocessing to figure out all the polygons. Then it's straightforward: draw a line from the point to infinity (conceptually speaking). Every time the you cross a line, increment the crossing count of each polygon the line is a part of. At the end, the first polygon with an odd crossing count is the smallest enclosing polygon. Since any arbitrary line will do just as well as any other (it doesn't even need to be straight), simplify the arithmetic by drawing a vertical or horizontal line, but watch out for crossing actual endpoints.
You could do this without preprocessing by creating the polygons as you cross each line. This basically reduces to n.m.'s algorithm but without all the special case checks.
Note that a line can belong to two polygons. Indeed, it could belong to more, but it's not clear to me how you would tell: consider the following:
+---------------------------+
| |
| +-------------------+ |
| | | |
| | +-----------+ | |
| | | | | |
| | | | | |
+---+---+-----------+---+---+

Resources