ZisIsNotZis
ZisIsNotZis

Reputation: 1740

Least square on linear N-way-equal problem

Suppose I want to find the "intersection point" of 2 arbitrary high-dimensional lines. The two lines won't actually intersect, but I still want to find the most intersect point (i.e. a point that is as close to all lines as possible).

Suppose those lines have direction vectors A, B and initial points C, D, I can find the most intersect point by simply set up a linear least square problem: converting the line-intersection equation

Ax + C = By + D

to least-square form

[A, -B] @ [[x, y]] = D - C 

where @ standards for matrix times vector, and then I can use e.g. np.linalg.lstsq to solve it.

But how can I find the "most intersect point" of 3 or more arbitrary lines? If I follow the same rule, I now have

Ax + D = By + E = Cz + F

The only way I can think of is decomposing this into three equations:

Ax + D = By + E
Ax + D = Cz + F
By + E = Cz + F

and converting them to least-square form

[A, -B,  0]                 [E - D]
[A,  0, -C] @ [[x, y, z]] = [F - D]
[0,  B, -C]                 [F - E]

The problem is the size of the least-square problem increases quadraticly about the number of lines. I'm wondering are there more efficient way to solve n-way-equal least-square linear problem?

I was thinking about the necessity of By + E = Cz + F above providing the other two terms. But since this problem do not have exact solution (i.e. they don't actually intersect), I believe doing so will create more "weight" on some variable?

Thank you for your help!

EDIT

I just tested pairing the first term with all other terms in the n-way-equality (and no other pairs) using the following code

def lineIntersect(k, b):
    "k, b: N-by-D matrices describing N D-dimensional lines: k[i] * x + b[i]"

    # Convert the problem to least-square form `Ax = B`
    # A is temporarily defined 3-dimensional for convenience
    A = np.zeros((len(k)-1, k.shape[1], len(k)), k.dtype)
    A[:,:,0] = k[0]
    A[range(len(k)-1),:,range(1,len(k))] = -k[1:]

    # Convert to 2-dimensional matrix by flattening first two dimensions
    A = A.reshape(-1, len(k))

    # B should be 1-dimensional vector
    B = (b[1:] - b[0]).ravel()

    x = np.linalg.lstsq(A, B, None)[0]

    return (x[:,None] * k + b).mean(0)

The result below indicates doing so is not correct because the first term in the n-way-equality is "weighted differently".

The first output is difference between the regular result and the result of different input order (line order should not matter) where the first term did not change.

The second output is the same with the first term did change.

k = np.random.rand(10, 100)
b = np.random.rand(10, 100)
print(np.linalg.norm(lineIntersect(k, b) - lineIntersect(np.r_[k[:1],k[:0:-1]], np.r_[b[:1],b[:0:-1]])))
print(np.linalg.norm(lineIntersect(k, b) - lineIntersect(k[::-1], b[::-1])))

results in

7.889616961715915e-16
0.10702479853076755

Upvotes: 3

Views: 440

Answers (4)

dmuir
dmuir

Reputation: 4431

Another criterion for the 'almost intersection point' would be a point x such that the sum of the squares of the distances of x to the lines is as small as possible. Like your criterion, if the lines actually do intersect then the almost intersection point will be the actual intersection point. However I think the sum of distances squared criterion makes it straightforward to compute the point in question:

Suppose we represent a line by a point and a unit vector along the line. So if a line is represented by p,t then the points on the line are of the form

p + l*t for scalar l

The distance-squared of a point x from a line p,t is

(x-p)'*(x-p) - square( t'*(x-p))

If we have N lines p[i],t[i] then the sum of the distances squared from a point x is

   Sum { (x-p[i])'*(x-p[i]) - square( t[i]'*(x[i]-p[i]))}

Expanding this out I get the above to be

x'*S*x - 2*x'*V + K

where

S = N*I - Sum{ t[i]*t[i]'}
V = Sum{ p[i] - (t[i]'*p[i])*t[i] }

and K does not depend on x

Unless all the lines are parallel, S will be (strictly) positive definite and hence invertible, and in that case our sum of distances squared is

(x-inv(S)*V)'*S*(x-inv(S)*V) + K - V'*inv(S)*V

Thus the minimising x is

inv(S)*V

So the drill is: normalise your 'direction vectors' (and scale each point by the same factor as used to scale the direction), form S and V as above, solve

S*x = V for x

Upvotes: 3

overfull hbox
overfull hbox

Reputation: 861

This question might be better suited for the math stackexchange. Also, does anyone have a good way of formatting math here? Sorry that it's hard to read, I did my best with unicode.

EDIT: I misinterpreted what @ZisIsNotZis meant by the lines Ax+C so what disregard the next paragraph.

I'm not convinced that your method is stated correctly. Would you mind posting your code and a small example of the output (maybe in 2d with 3 or 4 lines so we can plot it)? When you're trying to find the intersection of two lines shouldn't you do Ax+C = Bx+D? If you do Ax+C=By+D you can pick some x on the first line and some y on the second line and satisfy both equations exactly. Because here x and y should be the same size as A and B which is the dimension of the space rather than scalars.

There are many ways to understand the problem of finding a point that is as close to all lines as possible. I think the most natural one is that the sum of squares of euclidian distance to each line is minimized.

Suppose we have a line in R^n: c^Tz + d = 0 (where c is unit length) and another point x. Then the shortest vector from x to the line is: (I-cc^T)(x-d) so the square of the distance from x to the line is ║(I-cc^T)(x-d)║^2. We can find the closest point to the line by minimizing this distance. Note that this is a standard least squares problem of the form min_x ║b-Ax║_2.

Now, suppose we have lines given by c_iz+d_i for i=1,...,m. The squared distance d_i^2 from a point x to the i-th line is d_i^2 = ║(I-cc^T)(x-d)║_2^2. We now want to solve the problem of min_x \sum_{i=1}^{m} d_i^2.

In matrix form we have:

      ║ ⎡ (I-c_1 c_1^T)(x-d_1) ⎤ ║
      ║ | (I-c_2 c_2^T)(x-d_2) | ║
min_x ║ |      ...             | ║
      ║ ⎣ (I-c_n c_n^T)(x-d_n) ⎦ ║_2

This is again in the form min_x ║b - Ax║_2 so there are good solvers available.

Each block has size n (dimension of the space) and there are m blocks (number of lines). So the system is mn byn. In particular, it is linear in the number of lines and quadratic in the dimension of the space.

It also has the advantage that if you add a line you simply add another block to the least squares system. This also offers the possibility of updating solutions iteratively as you add lines.

I'm not sure if there are special solvers for this type of least squares system. Note that each block is the identity minus a rank one matrix, so that might give some additional structure which can be used to speed things up. That said, I think using existing solvers will almost always work better than writing your own, unless you have quite a bit of background in numerical analysis or have a very specialized class of systems to solve.

Upvotes: 2

Richard
Richard

Reputation: 61289

You say that you have two "high-dimensional" lines. This implies that the matrix indicating the lines has many more columns than rows.

If this is the case and you can efficiently find a low-rank decomposition such that A=LRᵀ, then you can rewrite the solution of the least squares problem min ||Ax-y||₂ as x=(Rᵀ RLᵀ L)⁻¹ Lᵀ y.

If m is the number of lines and n the dimension of the lines, then this reduces the least-squares time complexity from O(mn²+nʷ) to O(nr²+mr²) where r=min(m,n).

The problem then is to find such a decomposition.

Upvotes: 0

MBo
MBo

Reputation: 80197

Not a solution, some thoughts:

If line in nD space has parametric equation (with unit Dir vector)

 L(t) = Base + Dir * t

then squared distance from point P to this line is

W = P - Base
Dist^2 = (W - (W.dot.Dir) * Dir)^2

If it is possible to write Min(Sum(Dist[i]^2)) in form suitable for LSQ method (make partial derivatives by every point coordinate), so resulting system might be solved for (x1..xn) coordinate vector.

(Situation resembles reversal of many points and single line of usual LSQ)

Upvotes: 1

Related Questions