I'm writing a solution for the Usaco problem "Electric Fences".
In the problem you have to find the optimal location for a point among a large amount of linesegments, so the sum of point-linesegment distances is smallest possible.
I had an idea, that it might be possible to do a hillclimb, and it worked for all testcases. The given analysis used a similar method, but it did not explain why this would work.
Thus I'm still unable to either prove or disprove the existence of local optimums in the given tasks. I had an idea that it could be done using induction, but I haven't been able to make it work. Can you help me?
Updated definition
Given a set of (x1,y1,x2,y2) linesegments find the (x,y) point P, that minimizes the function:
def Val(x,y):
d = 0
for x1,y1,x2,y2 in LineSegments:
if triangle (x1,y1,x2,y2,x,y) is not obtuse in (x1,y1) or (x2,y2):
d += DistPointToLine(x,y,x1,y1,x2,y2)
else:
d += min(DistPointToPoint(x,y,x1,y1), DistPointToPoint(x,y,x2,y2))
return d
By some reason the problem contains only one local optima, and thus the following procedure can be used to solve it:
precision = ((-0.1,0), (0.1,0), (0,-0.1), (0,0.1))
def Solve(precision=0.1):
x = 0; y = 0
best = Val(x,y)
while True:
for dx,dy in precision:
if Val(x+dx, y+dy) > best:
x += dx; y += dy
best = Val(x,y)
break
else:
break
return (x,y)
The questions is: Why does this not get stuck somewhere on the way to the global optimum? Why is there no local hilltops to bring this naive procedure to its knees?
It is easy to prove the algorithm's correctness if we notice that the distance function for a single line segment is a convex function. Convex in this case means that if we think of the distance function as a surface z=f(x,y), then if we filled in the volume above the surface, we'd have a convex solid. In the case of the distance from a single line segment, the solid would look like a triangular wedge with conical ends.
Since the sum of convex functions is also convex, then the sum of distances from multiple line segments will also be a convex function. Therefore, any local minimum you find must also be a global minimum by virtue of the function being convex.
Related
Given (N+1) points. All the N points lie on x- axis. Remaining one point (HEAD point) lies anywhere in the coordinate plane.
Given a START point on x- axis.
Find the shortest distance to cover all the points starting from START point.We can traverse a point multiple times.
Example N+1=4
points on x axis
(0,1),(0,2),(0,3)
HEAD Point
(1,1) //only head point can lie anywhere //Rest all on x axis
START Point
(0,1)
I am looking for a method as of how to approach this problem.
Whether we should visit HEAD point first or HEAD point in between.
I tried to find a way using Graph Theory to simplify this problem and reduce the paths that need to be considered. If there is an elegant way to represent this problem using graphs to identify a solution, I was not able to find it. This approach becomes very inefficient as the n increases - the time and memory is O(2^n).
Looking at this as a tree graph, the root node would be the START point, then each of its child nodes would be the points it is connected to.
Since the START point and the rest of the points aside from the HEAD all lay on the x-axis, all non-HEAD points only need to be connected to adjacent points on the x-axis. This is because the distance of the path between any two points is the sum of the distances between any adjacent points along the path between those two points (the subset of nodes representing points on the x-axis does not need to form a complete graph). This reduces the brute force approach some.
Here's a simple example:
The upper left shows the original problem: points on the x-axis along with the START and HEAD points.
In the upper right, this has been transformed into a graph with each node representing a point from the original problem. The edges represent the paths that can be taken between points. This assumes that the START point only represents the first point in the path. Unlike the other nodes, it is only included in the path once. If that is not the case and the path can return to the START point, this would approximately double the possible paths, but the same approach can be followed.
In the bottom left, the START point, a, is the root of a tree graph, and each node connected to the START point is a child node. This process is repeated for each child node until either:
A path that is obviously not optimal is identified, in which case that node can just be excluded from the graph. See the nodes in red boxes; going back and forth between the same nodes is unnecessary.
All points are included when traversing the tree from the root to that node, producing a potential solution.
Note that when creating the tree graph, each time a node is repeated, its "potential" child nodes are the same as the first time the node was included. By "potential", I mean cases above still need to be checked, because the result might include a nonsensical path, in which case that node would not be included. It is also possible a potential solution results from the path after its child nodes are included.
The last step is to add up the distances for each of the potential solutions to determine which path is shortest.
This requires a careful examination of the different cases.
Assume for now START (S) is on the far left, and HEAD (H) is somewhere in the middle the path maybe something like
H
/ \
S ---- * ----*----* * --- * ----*
Or it might be shorter to from H to and from the one of the other node
H
//
S ---- * --- * -- *----------*---*
If S is not at one end you might have something like
H
/ \
* ---- * ----*----* * --- * ----*
--------S
Or even going direct from S to H on the first step
H
/ |
* ---- * ----*----* |
S
A full analysis of cases would be quite extensive.
Actually solving the problem, might depend on the number of nodes you have. If the number is small < 10, then compete enumeration might be possible. Just work out every possible path, eliminate the ones which are illegal, and choose the smallest. The number of paths is I think in the order of n!, so its computable for small n.
For large n you can break the problem into small segments. I think its enough just to consider a small patch with nodes either side of H and a small patch with nodes either side of S.
This is not really a solution, but a possible way to think about tackling the problem.
(To be pedantic stackoverflow.com is not the right site for this question in the stack exchange network. Computational Science : algorithms might be a better place.
This is a fun problem. First, lets try to find a brute force solution, as Poosh did.
Observations about the Shortest Path
No repeated points
You are in an Euclidean geometry, thus the triangle inequality holds: For all points a,b,c, the distance d(a,b) + d(b,c) <= d(a,c). Thus, whenever you have an optimal path that contains a point that occurs more than once, you can remove one of them, which means it is not an optimal path, which leads to a contradiction and proves that your optimal path contains each point exactly once.
Permutations
Our problem is thus to find the permutation, lets call it M_i, of the numbers 1...n for points P1...Pn (where P0 is the fixed start point and Pn the head point, P1...Pn-1 are ordered by increasing x value) that minimizes the sum of |(P_M_i)-(P_M_(i-1))| for i from 1 to n, || being the vector length sqrt(v_x²+v_y²).
The number of permutations of a set of size n is n!. In this case we have n+1 points, so a brute force approach testing all permutations would have complexity (n+1)!, which is higher than even 2^n and definitely not practical, so we need further observations to improve this.
Next Steps
My next step would now be to see if there are any other sequences that can be proven to be not optimal, leading to a reduction in the number of candidates to be tested.
Paths of non-head points
Lets look at all paths (sequences of indices of points that don't contain a head point and that are parts of the optimal path. If we don't change the start and end point of a path, then any other transpositions have no effect on the outside environment and we can perform purely local optimizations. We can prove that those sequences must have monotonic (increasing or decreasing) x coordinate values and thus monotonic indices (as they are ordered by ascending x coordinate between indices 0 and n-1):
We are in a purely one dimensional subspace and the total distance of the path is thus equal to the sum of the absolute values of the differences in x coordinates between one such point and the next. It is clear that this sum is minimized by ordering by x coordinate in either ascending or descending order and thus ordering the indices in the same way. Note that this is true for maximal such paths as well as for all continuous "subpaths" of them.
Wrapping it up
The only choices we have left are:
where do we place the head node in the optimal path?
which way do we order the two paths to the left and right?
This means we have n values for the index of the head node (1...n, 0 is fixed as the start node) and 2x2 values for sort order. So we have 4n choices which we can all calculate and pick the shortest one. One of the sort orders probably determines the other but I leave that to you.
Anyways, the complexity of this algorithm is O(4n) = O(n). Because reading in the input of the problems is in O(n) and writing the output is as well, I believe that is an algorithm of optimal complexity. However, if we could reformulate the problem somewhat, so that we could read and write the input and output in some compressed form, as in only the parameters that we actually need to solve the problem, then it is possible that we could do better.
P.S.: I'm not a mathematician so I probably used wrong words for some concepts and missed the usual notation for the variables and functions. I would be glad for some expert to check this for any obvious errors.
Is there a simple and efficient method to generate a random (uniformly distributed) point on a disk "hanging" in 3-dimensional space? The disk is defined by its normal.
Ideally, I would like to avoid rotation matrices, as I do not fully understand them, and I know they have issues.
So far, I've tried generating a 3D unit vector and projecting it onto the plane of the disk, which does ensure that the point is within the disk, but not that it's uniformly distributed.
I also tried scaling the generated vector according to some function of its length, but I couldn't get a uniform distribution back regardless.
I had an idea that involved creating 2 vectors perpendicular to each other and the normal, to define a local coordinate system. Then I could generate a point on the unit disk as in 2D and convert the result back to the global coordinate system. This seems like it would be quite efficient, as it involves some precomputation (which I'm completely fine with) and only simple calculations afterwards (this is for a raytracer, so it'll happen a lot). The problem is, I don't know how to reliably calculate the local coordinate system's basis vectors while avoiding possible issues like collinearity.
Any help is much appreciated.
A easy way to calculate orthogonal basis vectors u, v for a plane with normal n = (a,b,c) is finding the component with least absolute value, and making u orthogonal to that component; the rest pretty much follows. For example, if the first component is the one with minimal absolute value, you can pick these basis vectors:
u = (0, -c, b) // n·u = -bc+cb = 0
v = (b²+c², -ab, -ac) // n·v = ab²+ac²-ab²-ac² = 0, u·v = abc-abc = 0
I'm trying to take an array of 3D points and a plane and divide the points up into 2 arrays based on which side of the plane they are on. Before I get to heavily into debugging I wanted to post what I'm planning on doing to make sure my understanding of how to do this will work.
Basically I have the plane with 3 points and I use (pseudo code):
var v1 = new vector(plane.b.x-plane.a.x, plane.b.y-plane.a.y, plane.b.z-plane.a.z);
var v2 = new vector(plane.c.x-plane.a.x, plane.c.y-plane.a.y, plane.c.z-plane.a.z);
I take the cross product of these two vectors to get the normal vector.
Then I loop through my array of points and turn them into vectors and calculate the dot product against the normal.
Then i use the dot product to determine the side that the point is on.
Does this sound like it would work?
Let a*x+b*y+c*z+d=0 be the equation determining your plane.
Substitute the [x,y,z] coordinates of a point into the left hand side of the equation (I mean the a*x+b*y+c*z+d) and look at the sign of the result.
The points having the same sign are on the same side of the plane.
Honestly, I did not examine the details of what you wrote. I guess you agree that what I propose is simpler.
Following the 'put points into the plane's equation and check the sign' approach given previously. The equation can be easily obtained using SymPy. I used it to find location of points (saved as numpy arrays) in a list of points.
from sympy import Point3D, Plane
plane=Plane(Point3D(point1), Point3D(point2), Point3D(point3))
for point in pointList:
if plane.equation(x=point[0], y=point[1],z=point[2]) > 0:
print "point is on side A"
else:
print "point is on side B"
I haven't tested its speed compared to other methods mentioned above but is definitely the easiest method.
Your approach sounds good. However, when you say "and turn them into vectors", it might not be good (depending on the meaning of your sentence).
You should "turn your points into vector" by computing the difference in terms of coordinates between the current point and one of the points in the plane (for example, one of the 3 points defining the plane). As you wrote it, it sounds like you might have misunderstood that ; but apart from that, it's ok!
take into account the normal vector of the plane
example: for the point A=[-243.815437431962, -41.7407630281635, 10.0]
equation= -2663.1860000000006*Z +21305.488000000005=0
RESULt POSITIVE
but if equation= 2663.1860000000006*Z -21305.488000000005=0
RESULT NEGATIVE
I'm working in OpenCV but I don't think there is a function for this. I can find a function for finding affine transformations, but affine transformations include scaling, and I only want to consider rotation + translation.
Imagine I have two sets of points in 2d - let's say each set has exactly 50 points.
E.g. set A = {x1, y1, x2, y2, ... , x50, y50}
set B = {x1', y1', x2', y2', ... , x50', y50'}
I want to find the rotation and translation combination that gets closest to mapping set A onto set B. I guess I would define "closest" as minimises the average distance between points in A and corresponding points in B. I.e., minimises the average distance between (x1, y1) and (x1', y1'), etc.
I guess I could use brute force testing all possible translations and rotations but this would be extremely inefficient. Does anyone know a simpler way?
Thanks!
This problem has a very elegant solution in terms of singular value decomposition of the proximity matrix (distances between pairs of points). The name of this is the orthogonal Procrustes problem, after the Greek legend about a fellow who offered travellers a bed that would fit anyone.
The solution comes from finding the nearest orthogonal matrix to a given (not necessarily orthogonal) matrix.
The way I would do it in Excel is to make a couple columns representing the points.
Cells representing rotation/translation of a set (no need to rotate and translate both of them).
Then columns representing those same points rotated/translated.
Then another column for the distance between the points of the rotated/translated points.
Then a cell of the sum of the distances between points.
Finally, use Solver to optimize the rotation and translation cells.
If you fix some rotation you can get an answer using ternary search. Run search in x and for every tested x run it in y to get the best value. This will give you the correct answer since the function (sum of corresponding distances) is convex (this can be proved through observing that restriction of the function to any line is a one-dimensional convex function; and the last is a standard fact: the sum of several convex functions is convex).
Instead of brute force over the angle I can propose such a method based on the ternary search. Choose some not very large step S. Compute the target function for every angle in (0, S, 2S,...). Then, if S is small enough, we can exclude some of segments (iS, (i + 1)S) from consideration. Namely ones with relatively large values of function with angles iS and (i + 1)S. Being implemented carefully this can give an answer and can do it faster than brute force.
I just want to make sure this would work. Could you find the greatest path using Dijkstra's algorithm? Would you have to initialize the distance to something like -1 first and then change the relax subroutine to check if it's greater?
This is for a problem that will not have any negative weights.
This is actually the problem:
Suppose you are given a diagram of a telephone network, which is a graph
G whose vertices represent switches centers, and whose edges represent communication
lines between two centers. The edges are marked by their bandwidth of its lowest
bandwidth edge. Give an algorithm that, given a diagram and two switches centers a
and b, will output the maximum bandwidth of a path between a and b.
Would this work?
EDIT:
I did find this:
Hint: The basic subroutine will be very similar to the subroutine Relax in Dijkstra.
Assume that we have an edge (u, v). If min{d[u],w(u, v)} > d[v] then we should update
d[v] to min{d[u],w(u, v)} (because the path from a to u and then to v has bandwidth
min{d[u],w(u, v)}, which is more than the one we have currently).
Not exactly sure what that's suppose to mean though since all distance are infinity on initialization. So, i don't know how this would work. any clues?
I'm not sure Djikstra's is the way to go. Negative weights do bad, bad things to Djikstra's.
I'm thinking that you could sort by edge weight, and start removing the lowest weight edge (the worst bottleneck), and seeing if the graph is still connected (or at least your start and end points). The point at which the graph is broken is when you know you took out the bottleneck, and you can look at that edge's value to get the bandwidth. (If I'm not mistaken, each iteration takes O(E) time, and you will need O(E) iterations to find the bottleneck edge, so this is an O(E2) algorithm.
Edit: you have to realize that the greatest path isn't necessarily the highest bandwidth: you're looking to maximize the value of min({edges in path}), not sum({edges in path}).
You can solve this easily by modifying Dijkstra's to calculate maximum bandwidth to all other vertices.
You do not need to initialize the start vertex to -1.
Algorithm: Maximum Bandwidth(G,a)
Input: A simple undirected weighted graph G with non -ve edge weights, and a distinguished vertex a of G
Output: A label D[u], for each vertex u of G, such that D[u] is the maximum bandwidth available from a to u.
Initialize empty queue Q;
Start = a;
for each vertex u of G do,
D[u] = 0;
for all vertices z adjacent to Start do{ ---- 1
If D[Start] => D[z] && w(start, z) > D[z] {
Q.enqueue(z);
D[z] = min(D[start], D[z]);
}
}
If Q!=null {
Start = Q.dequeue;
Jump to 1
}
else
finish();
This may not be the most efficient way to calculate the bandwidth, but its what I could think of for now.
calculating flow may be more applicable, however flow allows for multiple paths to be used.
Just invert the edge weights. That is, if the edge weight is d, consider it instead as d^-1. Then do Dijkstra's as normal. Initialize all distances to infinity as normal.
You can use Dijkstra's algorithm to find a single longest path but since you only have two switch centers I don't see why you need to visit each node as in Dijkstra's. There is most likes a more optimal way of going this, such as a branch and bound algorithm.
Can you adjust some of the logic in algorithm AllPairsShortestPaths(Floyd-Warshall)?
http://www.algorithmist.com/index.php/Floyd-Warshall%27s_Algorithm
Initialize unconnected edges to negative infinity and instead of taking the min of the distances take the max?