bipartite graph and dynamic programming - dynamic-programming

I am solving a problem, which has a weighted complete bipartite graph(X,Y,XxY), where X has n nodes and Y has m nodes and n is less than m. I want to have a perfect cross free matching graph, such that no two edges cross while matching set X to set Y and all the nodes in X are taken at the end.The sum of weights of the resulting graph should be minimal, I need to devise a dynammic programming algorithm. This is how I thought of it:
nodes in X and Y are arranged x0, xi can have a horizontal edge to Y0,Yi and so on, but Y has more nodes than X.
For every node in X (i) I consider two options either horizontal neighbor which is j in set Y, or diagonal neighbors (i, j-1), (i,j+1) and choose the edge which minimizes the cost.and I keep track of the nodes in X and Y that are already taken.time complexity O(nm)
Is there a better way I can implement this. Any help is appreciated. This is a question I got in my midterm but I left it in choice.

Let w(x, y) be edge weight between nodes x in X and y in Y, and let M(i, j) be solution (minimum cross free matching graph) for vertices {x_0, x_1, ..., x_i} subset X and {y_0, y_1, ..., y_j} subset Y, where i < |X| and j < |Y|.
E.g. M(0, j) = min( w(x_0, y_a) ) for 0 <= a <= j. M(i, i-1) = infinity since there is no matching when 'right' set is smaller.
For i, j there are two possibilities: x_i is connected to y_j or not. Because of that recursion holds:
M(i, j) = min( w(i,j) + M(i-1, j-1), M(i, j-1) )

Related

Boundary enclosing a given set of points

I am having a bit of a problem with an algorithm that I am currently using. I wanted it to make a boundary.
Here is an example of the current behavior:
Here is an MSPaint example of wanted behavior:
Current code of Convex Hull in C#:https://hastebin.com/dudejesuja.cs
So here are my questions:
1) Is this even possible?
R: Yes
2) Is this even called Convex Hull? (I don't think so)
R: Nope it is called boundary, link: https://www.mathworks.com/help/matlab/ref/boundary.html
3) Will this be less performance friendly than a conventional convex hull?
R: Well as far as I researched it should be the same performance
4) Example of this algorithm in pseudo code or something similar?
R: Not answered yet or I didn't find a solution yet
Here is some Python code that computes the alpha-shape (concave hull) and keeps only the outer boundary. This is probably what matlab's boundary does inside.
from scipy.spatial import Delaunay
import numpy as np
def alpha_shape(points, alpha, only_outer=True):
"""
Compute the alpha shape (concave hull) of a set of points.
:param points: np.array of shape (n,2) points.
:param alpha: alpha value.
:param only_outer: boolean value to specify if we keep only the outer border
or also inner edges.
:return: set of (i,j) pairs representing edges of the alpha-shape. (i,j) are
the indices in the points array.
"""
assert points.shape[0] > 3, "Need at least four points"
def add_edge(edges, i, j):
"""
Add an edge between the i-th and j-th points,
if not in the list already
"""
if (i, j) in edges or (j, i) in edges:
# already added
assert (j, i) in edges, "Can't go twice over same directed edge right?"
if only_outer:
# if both neighboring triangles are in shape, it's not a boundary edge
edges.remove((j, i))
return
edges.add((i, j))
tri = Delaunay(points)
edges = set()
# Loop over triangles:
# ia, ib, ic = indices of corner points of the triangle
for ia, ib, ic in tri.vertices:
pa = points[ia]
pb = points[ib]
pc = points[ic]
# Computing radius of triangle circumcircle
# www.mathalino.com/reviewer/derivation-of-formulas/derivation-of-formula-for-radius-of-circumcircle
a = np.sqrt((pa[0] - pb[0]) ** 2 + (pa[1] - pb[1]) ** 2)
b = np.sqrt((pb[0] - pc[0]) ** 2 + (pb[1] - pc[1]) ** 2)
c = np.sqrt((pc[0] - pa[0]) ** 2 + (pc[1] - pa[1]) ** 2)
s = (a + b + c) / 2.0
area = np.sqrt(s * (s - a) * (s - b) * (s - c))
circum_r = a * b * c / (4.0 * area)
if circum_r < alpha:
add_edge(edges, ia, ib)
add_edge(edges, ib, ic)
add_edge(edges, ic, ia)
return edges
If you run it with the following test code you will get this figure, which looks like what you need:
from matplotlib.pyplot import *
# Constructing the input point data
np.random.seed(0)
x = 3.0 * np.random.rand(2000)
y = 2.0 * np.random.rand(2000) - 1.0
inside = ((x ** 2 + y ** 2 > 1.0) & ((x - 3) ** 2 + y ** 2 > 1.0)
points = np.vstack([x[inside], y[inside]]).T
# Computing the alpha shape
edges = alpha_shape(points, alpha=0.25, only_outer=True)
# Plotting the output
figure()
axis('equal')
plot(points[:, 0], points[:, 1], '.')
for i, j in edges:
plot(points[[i, j], 0], points[[i, j], 1])
show()
EDIT: Following a request in a comment, here is some code that "stitches" the output edge set into sequences of consecutive edges.
def find_edges_with(i, edge_set):
i_first = [j for (x,j) in edge_set if x==i]
i_second = [j for (j,x) in edge_set if x==i]
return i_first,i_second
def stitch_boundaries(edges):
edge_set = edges.copy()
boundary_lst = []
while len(edge_set) > 0:
boundary = []
edge0 = edge_set.pop()
boundary.append(edge0)
last_edge = edge0
while len(edge_set) > 0:
i,j = last_edge
j_first, j_second = find_edges_with(j, edge_set)
if j_first:
edge_set.remove((j, j_first[0]))
edge_with_j = (j, j_first[0])
boundary.append(edge_with_j)
last_edge = edge_with_j
elif j_second:
edge_set.remove((j_second[0], j))
edge_with_j = (j, j_second[0]) # flip edge rep
boundary.append(edge_with_j)
last_edge = edge_with_j
if edge0[0] == last_edge[1]:
break
boundary_lst.append(boundary)
return boundary_lst
You can then go over the list of boundary lists and append the points corresponding to the first index in each edge to get a boundary polygon.
I would use a different approach to solve this problem. Since we are working with a 2-D set of points, it is straightforward to compute the bounding rectangle of the points’ region. Then I would divide this rectangle into “cells” by horizontal and vertical lines, and for each cell simply count the number of pixels located within its bounds. Since each cell can have only 4 adjacent cells (adjacent by cell sides), then the boundary cells would be the ones that have at least one empty adjacent cell or have a cell side located at the bounding rectangle boundary. Then the boundary would be constructed along boundary cell sides. The boundary would look like a “staircase”, but choosing a smaller cell size would improve the result. As a matter of fact, the cell size should be determined experimentally; it could not be too small, otherwise inside the region may appear empty cells. An average distance between the points could be used as a lower boundary of the cell size.
Consider using an Alpha Shape, sometimes called a Concave Hull. https://en.wikipedia.org/wiki/Alpha_shape
It can be built from the Delaunay triangulation, in time O(N log N).
As pointed out by most previous experts, this might not be a convex hull but a concave hull, or an Alpha Shape in other words. Iddo provides a clean Python code to acquire this shape. However, you can also directly utilize some existing packages to realize that, perhaps with a faster speed and less computational memory if you are working with a large number of point clouds.
[1] Alpha Shape Toolbox: a toolbox for generating n-dimensional alpha shapes.
https://plotly.com/python/v3/alpha-shapes/
[2] Plotly: It can can generate a Mesh3d object, that depending on a key-value can be the convex hull of that set, its Delaunay triangulation, or an alpha set.
https://plotly.com/python/v3/alpha-shapes/
Here is the JavaScript code that builds concave hull: https://github.com/AndriiHeonia/hull Probably you can port it to C#.
One idea is creating triangles, a mesh, using the point cloud, perhaps through Delanuay triangulation,
and filling those triangles with a color then run level set, or active contour segmentation which will find the outer boundary of the shape whose color is now different then the outside "background" color.
https://xphilipp.developpez.com/contribuez/SnakeAnimation.gif
The animation above did not go all the way but many such algorithms can be configured to do that.
Note: The triangulation alg has to be tuned so that it doesn't merely create a convex hull - for example removing triangles with too large angles and sides from the delanuay result. A prelim code could look like
from scipy.spatial import Delaunay
points = np.array([[13.43, 12.89], [14.44, 13.86], [13.67, 15.87], [13.39, 14.95],\
[12.66, 13.86], [10.93, 14.24], [11.69, 15.16], [13.06, 16.24], [11.29, 16.35],\
[10.28, 17.33], [10.12, 15.49], [9.03, 13.76], [10.12, 14.08], [9.07, 15.87], \
[9.6, 16.68], [7.18, 16.19], [7.62, 14.95], [8.39, 16.79], [8.59, 14.51], \
[8.1, 13.43], [6.57, 11.59], [7.66, 11.97], [6.94, 13.86], [6.53, 14.84], \
[5.48, 12.84], [6.57, 12.56], [5.6, 11.27], [6.29, 10.08], [7.46, 10.45], \
[7.78, 7.21], [7.34, 8.72], [6.53, 8.29], [5.85, 8.83], [5.56, 10.24], [5.32, 7.8], \
[5.08, 9.86], [6.01, 5.75], [6.41, 7.48], [8.19, 5.69], [8.23, 4.72], [6.85, 6.34], \
[7.02, 4.07], [9.4, 3.2], [9.31, 4.99], [7.86, 3.15], [10.73, 2.82], [10.32, 4.88], \
[9.72, 1.58], [11.85, 5.15], [12.46, 3.47], [12.18, 1.58], [11.49, 3.69], \
[13.1, 4.99], [13.63, 2.61]])
tri = Delaunay(points,furthest_site=False)
res = []
for t in tri.simplices:
A,B,C = points[t[0]],points[t[1]],points[t[2]]
e1 = B-A; e2 = C-A
num = np.dot(e1, e2)
n1 = np.linalg.norm(e1); n2 = np.linalg.norm(e2)
denom = n1 * n2
d1 = np.rad2deg(np.arccos(num/denom))
e1 = C-B; e2 = A-B
num = np.dot(e1, e2)
denom = np.linalg.norm(e1) * np.linalg.norm(e2)
d2 = np.rad2deg(np.arccos(num/denom))
d3 = 180-d1-d2
res.append([n1,n2,d1,d2,d3])
res = np.array(res)
m = res[:,[0,1]].mean()*res[:,[0,1]].std()
mask = np.any(res[:,[2,3,4]] > 110) & (res[:,0] < m) & (res[:,1] < m )
plt.triplot(points[:,0], points[:,1], tri.simplices[mask])
Then fill with color and segment.

find point where barycentric weights have a specific value

I have triangle: a, b, c. Each vertex has a value: va, vb, vc. In my software the user drags point p around inside and outside of this triangle. I use barycentric coordinates to determine the value vp at p based on va, vb, and vc. So far, so good.
Now I want to limit p so that vp is within range min and max. If a user chooses p where vp is < min or > max, how can I find the point closest to p where vp is equal to min or max, respectively?
Edit: Here is an example where I test each point. Light gray is within min/max. How can I find the equations of the lines that make up the min/max boundary?
a = 200, 180
b = 300, 220
c = 300, 300
va = 1
vb = 1.4
vc = 3.2
min = 0.5
max = 3.5
Edit: FWIW, so far first I get the barycentric coordinates v,w for p using the triangle vertices a, b, c (standard stuff I think, but looks like this). Then to get vp:
u = 1 - w - v
vp = va * u + vb * w + vc * v
That is all fine. My trouble is that I need the line equations for min/max so I can choose a new position for p when vp is out of range. The new position for p is the point closest to p on the min or max line.
Note that p is an XY coordinate and vp is a value for that coordinate determined by the triangle and the values at each vertex. min and max are also values. The two line equations I need will give me XY coordinates for which the values determined by the triangle are min or max.
It doesn't matter if barycentric coordinates are used in the solution.
The trick is to use the ratio of value to cartesian distance to extend each triangle edge until it hits min or max. Easier to see with a pic:
The cyan lines show how the triangle edges are extended, the green Xs are points on the min or max lines. With just 2 of these points we know the slope if the line. The yellow lines show connecting the Xs aligns with the light gray.
The math works like this, first get the value distance between vb and vc:
valueDistBtoC = vc - vb
Then get the cartesian distance from b to c:
cartesianDistBtoC = b.distance(c)
Then get the value distance from b to max:
valueDistBtoMax = max - vb
Now we can cross multiply to get the cartesian distance from b to max:
cartesianDistBtoMax = (valueDistBtoMax * cartesianDistBtoC) / valueDistBtoC
Do the same for min and also for a,b and c,a. The 6 points are enough to restrict the position of p.
Consider your triangle to actually be a 3D triangle, with points (ax,ay,va), (bx,by,vb), and (cx,cy,vc). These three points define a plane, containing all the possible p,vp triplets obtainable through barycentric interpolation.
Now think of your constraints as two other planes, at z>=max and z<=min. Each of these planes intersects your triangle's plane along an infinite line; the infinite beam between them, projected back down onto the xy plane, represents the area of points which satisfy the constraints. Once you have the lines (projected down), you can just find which (if either) is violated by a particular point, and move it onto that constraint (along a vector which is perpendicular to the constraint).
Now I'm not sure about your hexagon, though. That's not the shape I would expect.
Mathematically speaking the problem is simply a change of coordinates. The more difficult part is finding a good notation for the quantities involved.
You have two systems of coordinates: (x,y) are the cartesian coordinates of your display and (v,w) are the baricentric coordinates with respect to the vectors (c-a),(b-a) which determine another (non orthogonal) system.
What you need is to find the equation of the two lines in the (x,y) system, then it will be easy to project the point p on these lines.
To achieve this you could explicitly find the matrix to pass from (x,y) coordinates to (v,w) coordinates and back. The function you are using toBaryCoords makes this computation to find the coordinates (v,w) from (x,y) and we can reuse that function.
We want to find the coefficients of the transformation from world coordinates (x,y) to barycentric coordinates (v,w). It must be in the form
v = O_v + x_v * x + y_v * y
w = O_w + x_w * x + y_w * y
i.e.
(v,w) = (O_v,O_w) + (x_v,y_y) * (x,y)
and you can determine (O_v,O_w) by computing toBaryCoord(0,0), then find (x_v,x_w) by computing the coordinates of (1,0) and find (y_v,y_w)=toBaryCoord(1,0) - (O_v,O_w) and then find (y_v,y_w) by computing (y_v,y_w) = toBaryCoord(0,1)-(O_v,O_w).
This computation requires calling toBaryCoord three times, but actually the coefficients are computed inside that routine every time, so you could modify it to compute at once all six values.
The value of your function vp can be computed as follows. I will use f instead of v because we are using v for a baricenter coordinate. Hence in the following I mean f(x,y) = vp, fa = va, fb = vb, fc = vc.
You have:
f(v,w) = fa + (fb-fa)*v + (fc-fa)*w
i.e.
f(x,y) = fa + (fb-fa) (O_v + x_v * x + y_v * y) + (fc-fa) (O_w + x_w * x + y_w * y)
where (x,y) are the coordinates of your point p. You can check the validity of this equation by inserting the coordinates of the three vertices a, b, c and verify that you obtain the three values fa, fb and fc. Remember that the barycenter coordinates of a are (0,0) hence O_v + x_v * a_x + y_v * a_y = 0 and so on... (a_x and a_y are the x,y coordinates of the point a).
If you let
q = fa + (fb_fa)*O_v + (fc-fa)*O_w
fx = (fb-fa)*x_v + (fc-fa) * x_w
fy = (fb-fa)*y_v + (fc-fa) * y_w
you get
f(x,y) = q + fx*x + fy * y
Notice that q, fx and fy can be computed once from a,b,c,fa,fb,fc and you can reuse them if you only change the coordinates (x,y) of the point p.
Now if f(x,y)>max, you can easily project (x,y) on the line where max is achieved. The coordinates of the projection are:
(x',y') = (x,y) - [(x,y) * (fx,fy) - max + q]/[(fx,fy) * (fx,fy)] (fx,fy)
Now. You would like to have the code. Well here is some pseudo-code:
toBarycoord(Vector2(0,0),a,b,c,O);
toBarycoord(Vector2(1,0),a,b,c,X);
toBarycoord(Vector2(0,1),a,b,c,Y);
X.sub(O); // X = X - O
Y.sub(O); // Y = Y - O
V = Vector2(fb-fa,fc-fa);
q = fa + V.dot(O); // q = fa + V*O
N = Vector2(V.dot(X),V.dot(Y)); // N = (V*X,V*Y)
// p is the point to be considered
f = q + N.dot(p); // f = q + N*p
if (f > max) {
Vector2 tmp;
tmp.set(N);
tmp.multiply((N.dot(p) - max + q)/(N.dot(N))); // scalar multiplication
p.sub(tmp);
}
if (f < min) {
Vector2 tmp;
tmp.set(N);
tmp.multiply((N.dot(p) - min + q)/(N.dot(N))); // scalar multiplication
p.sum(tmp);
}
We think of the problem as follows: The three points are interpreted as a triangle floating in 3D space with the value being the Z-axis and the cartesian coordinates mapped to the X- and Y- axes respectively.
Then the question is to find the gradient of the plane that is defined by the three points. The lines where the plane intersects with the z = min and z = max planes are the lines you want to restrict your points to.
If you have found a point p where v(p) > max or v(p) < min we need to go in the direction of the steepest slope (the gradient) until v(p + k * g) = max or min respectively. g is the direction of the gradient and k is the factor we need to find. The coordinates you are looking for (in the cartesian coordinates) are the corresponding components of p + k * g.
In order to determine g we calculate the orthonormal vector that is perpendicular to the plane that is determined by the three points using the cross product:
// input: px, py, pz,
// output: p2x, p2y
// local variables
var v1x, v1y, v1z, v2x, v2y, v2z, nx, ny, nz, tp, k,
// two vectors pointing from b to a and c respectively
v1x = ax - bx;
v1y = ay - by;
v1z = az - bz;
v2x = cx - bx;
v2y = cy - by;
v2z = cz - bz;
// the cross poduct
nx = v2y * v1z - v2z * v1y;
ny = v2z * v1x - v2x * v1z;
nz = v2x * v1y - v2y * v1x;
// using the right triangle altitude theorem
// we can calculate the vector that is perpendicular to n
// in our triangle we are looking for q where p is nz, and h is sqrt(nx*nx+ny*ny)
// the theorem says p*q = h^2 so p = h^2 / q - we use tp to disambiguate with the point p - we need to negate the value as it points into the opposite Z direction
tp = -(nx*nx + ny*ny) / nz;
// now our vector g = (nx, ny, tp) points into the direction of the steepest slope
// and thus is perpendicular to the bounding lines
// given a point p (px, py, pz) we can now calculate the nearest point p2 (p2x, p2y, p2z) where min <= v(p2z) <= max
if (pz > max){
// find k
k = (max - pz) / tp;
p2x = px + k * nx;
p2y = py + k * ny;
// proof: p2z = v = pz + k * tp = pz + ((max - pz) / tp) * tp = pz + max - pz = max
} else if (pz < min){
// find k
k = (min - pz) / tp;
p2x = px + k * nx;
p2y = py + k * ny;
} else {
// already fits
p2x = px;
p2y = py;
}
Note that obviously if the triangle is vertically oriented (in 2D it's not a triangle anymore actually), nz becomes zero and tp cannot be calculated. That's because there are no more two lines where the value is min or max respectively. For this case you will have to choose another value on the remaining line or point.

How to find coordinates (as Natural numbers) of two points that form a tangent line for a circle limited by the x axis?

Two points P and Q with coordinates (Px, Py) and (Qx, Qy) satisfy the following properties:
The coordinates Px, Py, Qx, and Qy are integers.
Px = −Qx.
The line PQ is tangent to a circle with center (0, 0) and radius r
0 < Px ≤ a for some integer limit a.
How do I find all such pairs of points P and Q?
For example, in the image below I have a circle with radius r=2 and the limit a = 6. The pair of points P = (6, 2) and Q = (−6, −7) are a solution, because:
The coordinates of P and Q are integers.
Px = −Qx.
The line PQ is tangent to the circle.
0 < Px ≤ 6.
But this is just one pair. I need to find all such pairs. There are a finite number of solutions.
So, is there a way to check if coordinates of points are tangent to the circle and are integers, then to list them all? I've looked at slope equations and shortest path from the center of the circle to the line equations, however, in the first case it requires coordinates to be known (which I could do by brute forcing every single digit, but I cannot see the pattern, because my guts tell me there should be some sort of equation I should apply), and in the second case I have to know the slope equation.
This is the algorithm I came up with but I don't think it is correct or good enough:
Find the slope equation y = mx + b for all 1 ≤ Px ≤ a and −a ≤ Qx ≤ −1.
For every y = mx + b check if it is tangent to the circle (how to do that???)
If true, return the pair
Line PQ has equation:
(x-Px)/(Qx-Px)=(y-Py)/(Qy-Py) or
(x-Px)*(Qy-Py)-(y-Py)*(Qx-Px)=0 or
x*(Qy-Py)+y*(Px-Qx)-Px*Qy+Px*Py+Py*Qx-Py*Px =
x*(Qy-Py)+y*2*Px-Px*(Qy+Py)=0
Distance from zero point to this line (circle radius) is
r=Px*(Qy+Py)/Sqrt((2*Px)^2+(Qy-Py)^2)
Note that radius and nominator are integers, so denominator must be integer too. It is possible when 2*Px and |Qy-Py| are members of some Pythagorean triple (for your example - 12^2+9^2 =15^2).So you can use "Generating a triple" method from the above link to significantly reduce the search and find all the possible point pairs (with radius checking)
Px = k * m * n (for m>=n, radius < k*m*n <= a)
|Qy-Py| = k * (m^2 - n^2)
With a=6 max value of n is 2, and your example corresponds to (k, m, n) set of (3, 2, 1)

solving string alignment in O(mn)

I need to solve the follow problem withing O(nm).
n = |T|
m = |P|
where T,P two strings
f is a scoring function.
the algorithm should return a substring T' of T such that score(P,T') value is the maximum.
score(A,B) is the max val for alignment A and B according f.
I know I can get it from DIST matrix which is a Monge matrix if f is discrete (meaning the diagonals of the matrix has weights not larger than C which is a constant, and the horizontal and vertical edges is 0 or some other constant), but in this case the f is a general function from (sigma * {-})x(sigma * {-}) to R (where '-' is a gap).
any ideas?
You've noticed that there are several algorithms that compute a shortest path in a graph whose arcs are (i, j) → (i + 1, j), (i + 1, j + 1), (i, j + 1). The most general form of this algorithm would allow every arc length to be specified separately, with the following meanings.
(i, j) → (i + 1, j): cost of aligning the (i+1)th letter of P with a gap in T
(i, j) → (i + 1, j + 1): cost of aligning the (i+1)th letter of P with the (j+1)th letter of T
(i, j) → (i, j + 1): cost of aligning a gap in P with the (j+1)th letter of T
Costs can be negative. To solve your substring problem, make the costs of all of the (i, j) → (i, j + 1) arcs zero so that we can delete from T without penalty.

Define a function for a circle caps the end of a line segment

I need a function that returns points on a circle in three dimensions.
The circle should "cap" a line segment defined by points A and B and it's radius. each cap is perpendicular to the line segment. and centered at one of the endpoints.
Here is a shitty diagram
Let N be the unit vector in the direction from A to B, i.e., N = (B-A) / length(A-B). The first step is to find two more vectors X and Y such that {N, X, Y} form a basis. That means you want two more vectors so that all pairs of {N, X, Y} are perpendicular to each other and also so that they are all unit vectors. Another way to think about this is that you want to create a new coordinate system whose x-axis lines up with the line segment. You need to find vectors pointing in the direction of the y-axis and z-axis.
Note that there are infinitely many choices for X and Y. You just need to somehow find two that work.
One way to do this is to first find vectors {N, W, V} where N is from above and W and V are two of (1,0,0), (0,1,0), and (0,0,1). Pick the two vectors for W and V that correspond to the smallest coordinates of N. So if N = (.31, .95, 0) then you pick (1,0,0) and (0,0,1) for W and V. (Math geek note: This way of picking W and V ensures that {N,W,V} spans R^3). Then you apply the Gram-Schmidt process to {N, W, V} to get vectors {N, X, Y} as above. Note that you need the vector N to be the first vector so that it doesn't get changed by the process.
So now you have two vectors that are perpendicular to the line segment and perpendicular to each other. This means the points on the circle around A are X * cos t + Y * sin t + A where 0 <= t < 2 * pi. This is exactly like the usual description of a circle in two dimensions; it is just written in the new coordinate system described above.
As David Norman noted the crux is to find two orthogonal unit vectors X,Y that are orthogonal to N. However I think a simpler way to compute these is by finding the householder reflection Q that maps N to a multiple of (1,0,0) and then to take as X the image of (0,1,0) under Q and Y as the image of (0,0,1) under Q. While this might sound complicated it comes down to:
s = (N[0] > 0.0) ? 1.0 : -1.0
t = N[0] + s; f = -1.0/(s*t);
X[0] = f*N[1]*t; X[1] = 1 + f*N[1]*N[1]; X[2] = f*N[1]*N[2];
Y[0] = f*N[2]*t; Y[1] = f*N[1]*N[2]; Y[2] = 1 + f*N[2]*N[2];

Resources