Given two segments in 3D, compute closest point between them using CGAL - c++

Given two segments in 3D in CGAL, I would like to compute the closest points between one segment and another. These two segment may be anywhere in space.
I have looked in CGAL and there is a function which computes distance between both segments (https://doc.cgal.org/latest/Kernel_23/group__squared__distance__grp.html), and with that I guess I could create two spheres and compute the intersection between them, but this seems slow and cumbersome.
Is there something out of the box?

Sorry to say, there are no out-of-the-box way in the CGAL library to see two points, defining the shortest segment between two line segments in 3D. I'm saying "to see" because these two points are actually computed deeply inside the CGAL::squared_distance function, then the distance between them is calculated, and then these two points are discarded.
If you really need these two points you can modify the Distance_3/Segment_3_Segment_3.h file and add a function with an additional argument:
template <class K>
inline
typename K::FT
squared_distance(const Segment_3<K>& seg1,
const Segment_3<K>& seg2,
Segment_3<K>& res)
{
// ... modifications
}
Of course you'll need to modify other code in this file as well.

Analytically:
You want to minimize the function
(A + p AB - C - q CD)²
under inequality constraints 0 ≤ p ≤ 1 and 0 ≤ q ≤ 1.
By differentiation, you get a linear system of 2 equations in the 2 unknowns p and q. After resolution, if these values fall in the allowed range, you are done.
p AB² - q AB.CD = AB.AC
p CD.AB - q CD² = CD.AC
Otherwise, you need to saturate one constraint (p=0, p=1, q=0 or q=1) and check if the other parameter is in range. (Endpoint to segment distances.)
Otherwise, you saturate both constraints (4 combinations). (Endpoint to endpoint distances.)
Finally, you keep the feasible solution that yields the smallest distance.
If the two segments are parallel or collinear, there can be an infinity of solution points.
Addendum:
WLOG, AB.CD ≤ 0 (otherwise swap two endpoints). Then then from the inequalities we draw
- AB.CD ≤ p AB² - q AB.CD ≤ AB²
- AB.CD ≤ p AB.CD - q CD² ≤ CD²
which directly gives us the condition for existence of a segment-segment solution:
- AB.CD ≤ AB.AC ≤ AB²
- AB.CD ≤ CD.AC ≤ CD²
We get the conditions for endpoint-segment solutions by substituting 0 or 1 for p or q.

Related

MILP BigM : variable must remains in defined boundaries or set to 0

I'm modeling some energy systems via MILP / Pyomo.
In that context I'm modeling a bi-directional elec. converter.
Power/energy can flow in both ways:
However, In one way, the power P can only be within boundaries [LB;UB], otherwise it must be 0.
I use this formulation to ensure that:
LB - P <= LB * x
P <= UB * (1 - x)
x being a binary variable
and it seems to be working...
in the other way, the power P can only be within [-UB;-LB], otherwise 0.
but I'm struggling hard to ensure that, I just can't get the logic behind to build that kind of constraint...
Any help and explanation would be appreciated.
Thanks a lot,
Max
I would think you have three states (or feasible regions):
p = 0
p ∈ [L,U]
p ∈ [-U,-L]
I don't think that can be done with one binary variable.
You can do something like :
δ1*L-δ2*U ≤ p ≤ δ1*U-δ2*L
δ1+δ2 ≤ 1
δ1,δ2 ∈ {0,1}
This is essentially:
δ1=δ2=0 => p = 0
δ1=1,δ2=0 => p ∈ [L,U]
δ1=0,δ2=1 => p ∈ [-U,-L]
δ1=δ2=1: not allowed

Reaching from first index to last with minimum product without using Graphs?

Solving this problem on codechef:
After visiting a childhood friend, Chef wants to get back to his home.
Friend lives at the first street, and Chef himself lives at the N-th
(and the last) street. Their city is a bit special: you can move from
the X-th street to the Y-th street if and only if 1 <= Y - X <= K,
where K is the integer value that is given to you. Chef wants to get
to home in such a way that the product of all the visited streets'
special numbers is minimal (including the first and the N-th street).
Please, help him to find such a product. Input
The first line of input consists of two integer numbers - N and K -
the number of streets and the value of K respectively. The second line
consist of N numbers - A1, A2, ..., AN respectively, where Ai equals
to the special number of the i-th street. Output
Please output the value of the minimal possible product, modulo
1000000007. Constraints
1 ≤ N ≤ 10^5 1 ≤ Ai ≤ 10^5 1 ≤ K ≤ N Example
Input: 4 2 1 2 3 4.
Output: 8
It could be solved using graphs based on this tutorial
I tried to solve it without using graphs and just using recursion and DP.
My approach:
Take an array and calculate the min product to reach every index and store it in the respective index.
This could be calculated using top down approach and recursively sending index (eligible) until starting index is reached.
Out of all calculated values store the minimum one.
If it is already calculated return it else calculate.
CODE:
#include<iostream>
#include<cstdio>
#define LI long int
#define MAX 100009
#define MOD 1000000007
using namespace std;
LI dp[MAX]={0};
LI ar[MAX],k,orig;
void cal(LI n)
{
if(n==0)
return;
if(dp[n]!=0)
return;
LI minn=MAX;
for(LI i=n-1;i>=0;i--)
{
if(ar[n]-ar[i]<=k && ar[n]-ar[i]>=1)
{
cal(i);
minn=(min(dp[i]*ar[n],minn))%MOD;
}
}
dp[n]=minn%MOD;
return;
}
int main()
{
LI n,i;
scanf("%ld %ld",&n,&k);
orig=n;
for(i=0;i<n;i++)
scanf("%ld",&ar[i]);
dp[0]=ar[0];
cal(n-1);
if(dp[n-1]==MAX)
printf("0");
else printf("%ld",dp[n-1]);
return 0;
}
Its been 2 days and I have checked every corner cases and constraints but it still gives Wrong answer! Whats wrong with the solution?
Need Help.
Analysis
There are many problems. Here is what I found:
You restrict the product to a value inferior to 100009 without reason. The product can be way higher that that (this is indeed the reason why the problem only asked the value modulo 1000000007)
You restrict your moves from streets whose difference in special number is K whereas the problem statement says that you can move between any cities whose index difference is inferior to K
In you dynamic programming function you compute the product and store the modulo of the product. This can lead to a problem because the modulo of a big number can be lower than the modulo of a lower number. This may corrupt later computations.
The integral type you use, long int, is too short.
The complexity of your algorithm is too high.
From all these problems, the last one is the most serious. I fixed it by changing the whole aproach and using a better datastructure.
1st Problem
In your main() function:
if(dp[n-1]==MAX)
printf("0");
In your cal() function:
LI minn=MAX;
You should replace this line with:
LI minn = std::numeric_limits<LI>::max();
Do not forget to:
#include <limits>
2nd Problem
for(LI i=n-1;i>=0;i--)
{
if(ar[n]-ar[i]<=k && ar[n]-ar[i]>=1)
{
. . .
}
}
You should replace the for loop condition:
for(LI i=n-1;i>=n-k;i--)
And remove altogether the condition on the special numbers.
3rd Problem
You are looking for the path whose product of special numbers is the lowest. In your current setting, you compare path's product after having taken the modulo of the product. This is wrong, as the modulo of a higher number may become very low (for instance a path whose product is 1000000008 will have a modulo of 1 and you will choose this path, even if there is a path whose product is only 2).
This means you should compare the real products, without taking their modulo. As these products can become very high you should take their logarithm. This will allow you to compare the products with a simple double. Remember that:
log(a*b) = log(a) + log(b)
4th Problem
Use unsigned long long.
5th Problem
I fixed all these issues and submitted on codechef CHRL4. I got all but one test case accepted. The testcase not accepted was because of a timeout. This is due to the fact that your algorithm has got a complexity of O(k*n).
You can achieve O(n) complexity using a bottom-up dynamic programming approach, instead of top-down and using a data structure that will return the minimum log value of the k previous streets. You can lookup sliding window minimum algorithm to find how to do.
References
numeric_limits::max()
my own codechef CHRL4 solution: bottom-up dp + sliding window minimum

Predict the required number of preallocated nodes in a kD-Tree

I'm implementing a dynamic kD-Tree in array representation (storing the nodes in std::vector) in breadth-first fashion. Each i-th non-leaf node have a left child at (i<<1)+1 and a right child at (i<<1)+2. It would support incremental insertion of points and collection of points.
However I'm facing problem determining the required number of possible nodes to incrementally preallocate space.
I've found a formula on the web, which seems to be wrong:
N = min(m − 1, 2n − ½m − 1),
where m is the smallest power of 2 greater than or equal to n, the
number of points.
My implementation of the formula is the following:
size_t required(size_t n)
{
size_t m = nextPowerOf2(n);
return min(m - 1, (n<<1) - (m>>1) - 1);
}
function nextPowerOf2 returns a power of 2 largest or equal to n
Any help would be appreciated.
Each node of a kd-tree divides the space into two spaces. Hence, the number of nodes in the kd-tree depends on how you perform this division:
1) If you divide them in the midpoint of the space (that is, if the space is from x1 to x2, you divide the space with the x3=(x1+x2)/2 line), then:
i) Each point will be allocated its own node, and
ii) Each intermediate node will be empty.
In this case, the number of nodes will depend on how large the coordinates of the points are. If the coordinates are bounded by |X|, then the total number of nodes in the kd-tree should be slightly less than log |X| * n (more precisely, around log |X| * n - n log n + 2n) in the worst case. To see this, consider the following way to add the points: you add multiple collections, each collection has two extremely nearby points located at random. For each pair of point, the tree will need to continuously divide the space log |X| times, and if log |X| is significantly larger than log n, creating log |X| intermediate nodes in the process.
2) If you divide them by using a point as a dividing line, then each node (including the intermediate nodes) will contain a point. Thus, the total number of nodes is simply n. However, note that using a point to divide the space may yield to a very bad performance if the points are not given in a random order (for example, if the points are given in an ascending order of X, the depth of the tree would be O(n). For comparison, the depth of the tree in (1) is at most O(log |X|) ).

Hash and Modular Arthmetic

Let h(y) be the function defined as (a*y+b)mod m. So h(y) can take values from 0 to m-1.
Now we are given 7 integers- a,b,x,n,c,d,m. Our task is to find the total count of h(x),h(x+1),h(x+2)...h(x+n) such that the value of h(x+i) falls in the range of [c,d].where 0<=i<=n
Integer limits are:
1 ≤ m ≤ 10^15, c ≤ d < m, a,b < m, x+n ≤ 10^15, and a*(x+n) + b ≤ 10^15
For Example.
for input set {1,0,0,8,0,8,9} the output should be 9. Please suggest an efficient algorithm. Thanks!!!
This isn't a particularly strong hash. The only hard part about this problem is the obtuse notation with single-letter variables and specifying the problem as a 7-tuple.
Each increment of x increases h(x) by a. Therefore the total distance along x to get from c to d is simply (d-c)/a. Add one for the fencepost problem, or specify the problem with a half-open range for the sake of sanity.

Find {E1,..En} (E1+E2+..En=N, N is given) with the following property that E1* E2*..En is Maximum

Given the number N, write a program that computes the numbers E1, E2, ...En with the following properties:
1) N = E1 + E2 + ... + En;
2) E1 * E2 * ... En is maximum.
3) E1..En, are integers. No negative values :)
How would you do that ? I have a solution based on divide et impera but i want to check if is optimal.
Example: N=10
5,5 S=10,P=25
3,2,3,2 S=10,P=36
No need for an algorithm, mathematic intuition can do it on its own:
Step 1: prove that a result set with numbers higher than 3 is at most as good as a result set with only 3's and 2's
Given any number x in your result set, one might consider whether it would be better to divide it into two numbers.
The sum should still be x.
When x is even, The maximum for t (x - t) is reached when t = x/2 , and except for the special case x = 2, then it is greater than x, and for the special case x = 4, equal to x (see note 1).
When x is odd, The maximum for t (x - t) is reached when t = (x ± 1)/2.
What does this show? Only that you should only have 3's and 2's in your final set, because otherwise it is suboptimal (or equivalent to an optimal set).
Step 2: you should have as many 3's as possible
Now, as 3² > 2³, you should have as many 3's as possible as long as the remainder is not 1.
Conclusion: for every N >= 3:
If N = 0 mod 3, then the result set is only 3's
If N = 1 mod 3, then the result set has one pair of 2's (or a 4) and the rest is 3's
If N = 2 mod 3, then the result set has one 2 and the rest is 3's
Please correct this post. The times when I was writing well-structured mathematical proofs is far away...
Note 1: (2,4) is the only pair of distinct integers such that x^y = y^x. You can prove that with:
x^y = y^x
y ln(x) = x ln(y)
ln(x)/x = ln(y) / y
and the function ln(t)/t is strictly decreasing after its global maximum, reached between 2 and 3, so if you want two distinct integers such that ln(x)/x = ln(y)/y, one of them must be lower or equal to 2. From that you can infer that only (2,4) works
This is not a complete solution, but might help.
First off note that if you fix n, and two of the terms E_i and E_j differ by more than one (for example 3 and 8), then you can do better by "equalizing" them as much as possible, i.e., if the number p = E_i + E_j is even, you do better both terms by p/2. If p is odd, you do better by replacing them with p/2 and p/2+1 (where / is integer division).
That said, then if you knew what the optimal number of terms, n, was, you'd be done: let all E_i's equal N/n and N/n+1 (again integer division), so that their sum is still N (this is now a straightforward problem).
So the question now is what is the optimal n. Suppose for the moment that you are allowed to use real numbers. Then the solution would be N/n for each term and you could write the product as (N/n)^n. If you differentiate this with respect to n and find its root you find that n should be equal to N/e (where e is the Neper number, also known as Euler's number, e = 2.71828....). Therefore, I'd look for a solution where either n = floor(N/e) or n = floor(N/e)+1, and then choose all the E_i's equal to either N/n or N/n+1, as above.
Hope that helps.
The Online Encycolpedia of Integer Sequences gives a recurrence relation for the solution to this problem.
I'll leave it up to someone else to compare complexities. Not sure I can figure out the complexity of OP's method.