As an input, I have a "map", which is a polygon. All its sides are parallel to x- or y-axis (so all these polygons are described by rectangles which they consist of, size of all polygons are integers). Here you can see an example of a correct and a bad input.
The second input is a set of rectangles I want to fit in. All rectangles are described by theirs sizes width*height (every rectangle could have different integer size).
For a given input, I want to find out if it is possible to put all rectangles to the map. And if so, I want to get positions of all rectangles. Moreover, I could have some more conditions on location of rectangles. For example, I know that a two rectangles A,B in a map must be connected by one side.
Is there any efficient algorithm to this problem? I would say it can be transformed to some graph problem, but I have no idea how to represent it. Thanks for any help!
There's almost certainly no always-efficient algorithm, because this problem is NP-hard. To see this, notice that you can reduce any instance of the NP-hard Partition Problem to an instance of your problem:
For each number x_i in the partition problem, create a 1-by-x_i rectangle.
Set the "first input rectangle" size 2-by-(0.5*s), where s is the sum of all the x_i.
The instance of your problem described above has a solution if and only if the original Partition Problem instance has a solution, so if there was an efficient way to solve your problem, then you could use that same algorithm to efficiently solve the Partition Problem (and, via similar reductions, every other NP-hard problem).
Related
For example we have two rectangles and they overlap. I want to get the exact range of the union of them. What is a good way to compute this?
These are the two overlapping rectangles. Suppose the cords of vertices are all known:
How can I compute the cords of the vertices of their union polygon? And what if I have more than two rectangles?
There exists a Line Sweep Algorithm to calculate area of union of n rectangles. Refer the link for details of the algorithm.
As said in article, there exist a boolean array implementation in O(N^2) time. Using the right data structure (balanced binary search tree), it can be reduced to O(NlogN) time.
Above algorithm can be extended to determine vertices as well.
Details:
Modify the event handling as follows:
When you add/remove the edge to the active set, note the starting point and ending point of the edge. If any point lies inside the already existing active set, then it doesn't constitute a vertex, otherwise it does.
This way you are able to find all the vertices of resultant polygon.
Note that above method can be extended to general polygon but it is more involved.
For a relatively simple and reliable way, you can work as follows:
sort all abscissas (of the vertical sides) and ordinates (of the horizontal sides) independently, and discard any duplicate.
this establishes mappings between the coordinates and integer indexes.
create a binary image of size NxN, filled with black.
for every rectangle, fill the image in white between the corresponding indexes.
then scan the image to find the corners, by contour tracing, and revert to the original coordinates.
This process isn't efficient as it takes time proportional to N² plus the sum of the (logical) areas of the rectangles, but it can be useful for a moderate amount of rectangles. It easily deals with coincidences.
In the case of two rectangles, there aren't so many different configurations possible and you can precompute all vertex sequences for the possible configuration (a small subset of the 2^9 possible images).
There is no need to explicitly create the image, just associate vertex sequences to the possible permutations of the input X and Y.
Look into binary space partitioning (BSP).
https://en.wikipedia.org/wiki/Binary_space_partitioning
If you had just two rectangles then a bit of hacking could yield some result, but for finding intersections and unions of multiple polygons you'll want to implement BSP.
Chapter 13 of Geometric Tools for Computer Graphics by Schneider and Eberly covers BSP. Be sure to download the errata for the book!
Eberly, one of the co-authors, has a wonderful website with PDFs and code samples for individual topics:
https://www.geometrictools.com/
http://www.geometrictools.com/Books/Books.html
Personally I believe this problem should be solved just as all other geometry problems are solved in engineering programs/languages, meshing.
So first convert your vertices into rectangular grids of fixed size, using for example:
MatLab meshgrid
Then go through all of your grid elements and remove any with duplicate edge elements. Now sum the number of remaining meshes and times it by the area of the mesh you have chosen.
I have different dimension of small rectangles (1cm x 2xm, 2cmx3cm, 4cm*6cm etc). The number of different type rectangles may vary depending on case. Each type of different rectangles may have different number of counts.
I need to create a big rectangle with all these small rectangles which these small rectangles can only be placed on the edges. no rotations. The final outer rectangle should ideally be smiliar to a square shape. X ~Y. Not all edges need to be filled up. There can be gaps in between smaller rectangles. Picture Example:
http://i.stack.imgur.com/GqI5z.png
I am trying to write a code that finds out the minimum possible area that can be formed.
I have an algorithm that loop through all possible placement to find out the minimum area possible. But that takes a long run time as number of different type rectangles and number of rectangles increase. i.e. 2 type of rectangles, each has 100 + rectangles. 8 for loops. That will be ~100^8 iterations
Any ideas on better and faster algorithm to calculate the minimum possible area? code is in python, but any algorithm concept is fine.
for rectange_1_top_count in (range(0,all_rectangles[1]["count"]+1)):
for rectange_1_bottom_count in range(0,all_rectangles[1]["count"]-rectange_1_top_count+1):
for rectange_1_left_count in (range(0,all_rectangles[1]["count"]-rectange_1_top_count-rectange_1_bottom_count+1)):
for rectange_1_right_count in ([all_rectangles[1]["count"]-rectange_1_top_count-rectange_1_bottom_count-rectange_1_left_count]):
for rectange_2_top_count in (range(0,all_rectangles[2]["count"]+1)):
for rectange_2_bottom_count in (range(0,all_rectangles[2]["count"]-rectange_2_top_count+1)):
for rectange_2_left_count in (range(0,all_rectangles[2]["count"]-rectange_2_bottom_count-rectange_2_top_count+1)):
for rectange_2_right_count in [(all_rectangles[2]["count"]-rectange_2_bottom_count-rectange_2_left_count-rectange_2_top_count)]:
area=calculate_minimum_area()
if area< minimum_area:
minimum_area=area
This looks like an NP-hard problem, so there exists no simple and efficient algorithm. It doesn't mean that there is no good heuristic that you can use, but if you have many small rectangles, you won't find the optimal solution fast.
Why is it NP-hard? Let's assume all your rectangles have height 1 and you have on rectangle of height 2, then it would make sense to look for a solution with total height 2 (basically, you try to form two horizontal lines of height-1 rectangles with the same length). To figure out if such a solution exists, you would have to form two subsets of your small rectangles, both adding up to the same total width. This is called the partition problem and it is NP-complete. Even if there may be gaps and the total widths are not required to be the same, this is still an NP-hard problem. You can reduce the partition problem to your rectangle problem by converting the elements to partition into rectangles of height 1 as outlined above.
I'll wait for the answer to the questions I posted in the comments to your question and then think about it again.
I've got a binary matrix and I'm trying to find all the largest rectangles that can be formed by adjoining elements in the matrix. By largest rectangles I mean, all the rectangles which are unique, non subsets of any other rectangles. For example, the following matrix contains six such rectangles.
This is related to the set cover problem, though here I'm interested in the maximum number of rectangles, not the minimum. An approach I've tried is to find all the rectangles regardless of size, then compare rectangles and remove them if they are a subset of another rectangle. This is not an optimal approach. It seems like this case of the set cover problem shouldn't be too hard.
I've had a look and not found anything similar to this problem. There is this paper, which has some good ideas, but still wide of the mark. Is there another name for this particular problem? Are there any existing algorithms for finding all possible rectangles in a set cover problem?
After a bit more work, I've realised this is not really related to the set cover problem. It's actually the 'finding the unique rectangles that are not contained within in any other rectangle in a binary matrix problem'.
I have come up with something that works well, but I have no idea about it's complexity.
Basically, line sweep across the matrix horizontally and vertically. In each case, look for contiguous groups of 1's that can form rectangles with the next line. This results in a number of rectangles, some of which are duplicates or sub rectangles of others. These rectangles are reduced to a unique set where no rectangle is a sub rectangle of another. Then you have all the rectangles.
Here is a diagram that relates to the image in the original post:
i dont speek english very wheel but, maximal rectangles overlapping is a problem that resolve many pb, if you somme maximal rectangles, geometrique sommation you find optimal volume that you derive to find queleton etc
This question already has answers here:
Algorithm for finding the fewest rectangles to cover a set of rectangles without overlapping
(2 answers)
Closed 5 years ago.
Simplified, I have to solve the following problem:
You have a 2-dimensional array filled with 0s and 1s. Find the minimum number of rectangles such that they cover all 1s. Rectangles should not overlap.
The function signature might look like:
List<Rectangle> FindCoveringRectangles(bool[,] array)
I already have a solution that is "good enough" but doesn't always find the minimum number of rectangles. I'd like to know if there is some well known and efficient algorithm that can be applied to solve this problem?
Example:
An input array of:
..........
.1.....11.
.......11.
...111....
...111....
...111....
....1111..
....1111..
......11..
..........
(0s replaced by dots for readability)
Might result in the following rectangles:
(2,2,2,2),
(2,8,3,9),
(4,4,6,6),
(7,5,8,8),
(9,7,9,8)
(top, left, bottom, right), 1-based
There can be more than one solution, but one is enough.
This is a matching problem of a kind, that could easily have shown NP-hard. However it seems there is actually a very fast solution!
Using a bfs flood-fill you can find each connected component, O(n). Hence wlog we can assume that we just have to fill one connected area.
If the area doesn't have holes in it, you can use the algorithm described in this paper (or here on google scholar.)
An O(n log log n) algorithm is proposed for minimally rectangular partitioning a simple rectilinear polygon. For any simple rectilinear polygon P, a vertex-edge visible pair is a vertex and an edge that can be connected by a horizontal or vertical line segment that lies entirely inside P. It is shown that, if the vertex-edge visible pairs are found, the maximum matching and the maximum independent set of the bipartite graph derived from the chords of a simple rectilinear polygon can be found in linear time without constructing the bipartite graph. Using this algorithm, the minimum partition problem for convex rectilinear polygons and vertically (horizontally) convex rectilinear polygons can be solved in O(n) time
Some of the papers referred to also cover the case of an area with holes. These run in O(n^(3/2)logn) though, but they still seam pretty good.
Alternatively, one thing you might do is solving the problem without holes, solving the problem for each hole, and then subtract. This might not give an optimal solution though, but would keep the runtime.
You could also try and split the shape in its different topological parts, but that would likely run exponentially in the number of holes.
Thirdly you could try to adapt the proposed algorithm for the more general case, but it might be hard.
Given are two sets of three-dimensional points, a source and a destination set. The number of points on each set is arbitrary (may be zero). The task is to assign one or no source point to every destination point, so that the sum of all distances is minimal. If there are more source than destination points, the additional points are to be ignored.
There is a brute-force solution to this problem, but since the number of points may be big, it is not feasible. I heard this problem is easy in 2D with equal set sizes, but sadly these preconditions are not given here.
I'm interested in both approximations and exact solutions.
Edit: Haha, yes, I suppose it does sound like homework. Actually, it's not. I'm writing a program that receives positions of a large number of cars and i'm trying to map them to their respective parking cells. :)
One way you could approach this problem is to treat is as the classical assignment problem: http://en.wikipedia.org/wiki/Assignment_problem
You treat the points as the vertices of the graph, and the weights of the edges are the distance between points. Because the fastest algorithms assume that you are looking for maximum matching (and not minimum as in your case), and that the weights are non-negative, you can redefine weights to be e.g.:
weight(A, B) = bigNumber- distance(A,B)
where bigNumber is bigger than your longest distance.
Obviously you end up with a bipartite graph. Then you use one of the standard algorithms for maximum weighted bipartite matching (lots of resources on the web, e.g. http://valis.cs.uiuc.edu/~sariel/teach/courses/473/notes/27_matchings_notes.pdf or Wikipedia for overview: http://en.wikipedia.org/wiki/Perfect_matching#Maximum_bipartite_matchings) This way you will end-up with a O(NM max(N,M)) algoritms, where N and M are sizes of your sets of points.
Off the top of my head, spatial sort followed by simulated annealing.
Grid the space & sort the sets into spatial cells.
Solve the O(NM) problem within each cell, then within cell neighborhoods, and so on, to get a trial matching.
Finally, run lots of cycles of simulated annealing, in which you randomly alter matches, so as to explore the nearby space.
This is heuristic, getting you a good answer though not necessarily the best, and it should be fairly efficient due to the initial grid sort.
Although I don't really have an answer to your question, I can suggest looking into the following topics. (I know very little about this, but encountered it previously on Stack Overflow.)
Nearest Neighbour Search
kd-tree
Hope this helps a bit.