Infinite subtraction loop - optimization

The problem is like this :
Suppose a , b two integers,
We say that (a,b) are infinite if we can repeat the following function infinitely:
if a > b :
a=a-b
b=2*b
if b > a :
b=b-a
a=2*a
and 'a' will never be equal to 'b' in any iteration.
Is there a way to test if two integers are infinite without resorting to loops ?
Example 1: a=1,b=4
(1, 4) -> (2, 3) -> (4, 1 -> (3, 2) -> (1, 4) and so on ===> Infinite
Example 2: a=3,b=5
(3, 5 -> (6, 2) -> (4, 4) ====> Not Infinite

Let's rewrite your function as follows:
a=|a-b|
b=2*min(a,b)
Now we can see that if the difference between a and b is odd, then a will be odd in the next round (we just said the difference was odd), and b will be even (2*k is always even). Therefore the difference will be odd in the next iteration, and in all future iterations, so a will never equal b and the pair is "infinite".
If the difference between a and b is even, then this will be true for all future iterations (by similar logic). To work on this case, let's work backwards from the final state. If the pair is finite, then the end of the iterative process will produce a pair (k,k). The smaller integer in the prior iteration therefore was k/2, so the larger one was 3k/2: (k/2,3k/2). Continuing to follow the process backwards, the prior step then was (k/4,k/4+3k/2)=(k/4,7k/4), preceded by (k/8,k/8+7k/4)=(k/8,15k/8). If we abstract this pattern, we can see that any pair of the form (m,(2^n-1)m) (for any n) is finite.
This isn't a complete proof, but I believe that an even-differenced pair is finite if and only if one member of the pair is the product of the other and a value one less than a power of two. Please let me know if you can find a counter-example.
Here's the beginning of the brute-force process I used to come to that conclusion:
(1,1) <- impossible
(2,2) <- (3,1)
(3,3) <- impossible
(4,4) <- (6,2) <- (7,1)
(6,6) <- (9,3)
(8,8) <- (12,4) <- (14,2) <- (15,1)
(10,10) <- (15,5)
(12,12) <- (18,6) <- (21,3)
(14,14) <- (21,7)
(16,16) <- (24,8) <- (28,4) <- (30,2) <- (31,1)
[*3] [*7] [*15] [*31]
(18,18) <- (27,9)
(20,20) <- (30,10) <- (35,5)
Thanks, this was fun to work through.

Consider the first half of the function, where a>b. If this remains iteration after iteration we have:
The "no-infinite" condition is an=bn for some "n". So
The second half of the funtion is just a swap(a,b) when some ak< bk
a0 &lt b0(1+2k+1)
The problem becomes finding if a0 is a multiple of b0 with the factor (1+2k+1) for some 'k'.
This is another problem. You can discard any pair (a,b) when a=2k·b. You only have to test several k while a>2k·b
Note
I do not have checked all my maths. You may find errors. The general idea remains.
Note 2
#Nvioli found an error. The right factor is (2k+1-1)

Related

Minimum of empty Seq is infinite, Why?

I'm working on this weeks PerlWChallenge.
You are given an array of integers #A. Write a script to create an
array that represents the smaller element to the left of each
corresponding index. If none found then use 0.
Here's my approach:
my #A = (7, 8, 3, 12, 10);
my $L = #A.elems - 1;
say gather for 1 .. $L -> $i { take #A[ 0..$i-1 ].grep( * < #A[$i] ).min };
Which kinda works and outputs:
(7 Inf 3 3)
The Infinity obviously comes from the empty grep. Checking:
> raku -e "().min.say"
Inf
But why is the minimum of an empty Seq Infinity? If anything it should be -Infinity. Or zero?
It's probably a good idea to test for the empty sequence anyway.
I ended up using
take .min with #A[ 0..$i-1 ].grep( * < #A[$i] ) or 0
or
take ( #A[ 0..$i-1 ].grep( * < #A[$i] ) or 0 ).min
Generally, Inf works out quite well in the face of further operations. For example, consider a case where we have a list of lists, and we want to find the minimum across all of them. We can do this:
my #a = [3,1,3], [], [-5,10];
say #a>>.min.min
And it will just work, since (1, Inf, -5).min comes out as -5. Were min to instead have -Inf as its value, then it'd get this wrong. It will also behave reasonably in comparisons, e.g. if #a.min > #b.min { }; by contrast, an undefined value will warn.
TL;DR say min displays Inf.
min is, or at least behaves like, a reduction.
Per the doc for reduction of a List:
When the list contains no elements, an exception is thrown, unless &with is an operator with a known identity value (e.g., the identity value of infix:<+> is 0).
Per the doc for min:
a comparison Callable can be specified with the named argument :by
by is min's spelling of with.
To easily see the "identity value" of an operator/function, call it without any arguments:
say min # Inf
Imo the underlying issue here is one of many unsolved wide challenges of documenting Raku. Perhaps comments here in this SO about doc would best focus on the narrow topic of solving the problem just for min (and maybe max and minmax).
I think, there is inspiration from
infimum
(the greatest lower bound). Let we have the set of integers (or real
numbers) and add there the greatest element Inf and the lowest -Inf.
Then infimum of the empty set (as the subset of the previous set) is the
greatest element Inf. (Every element satisfies that is smaller than
any element of the empty set and Inf is the greatest element that
satisfies this.) Minimum and infimum of any nonempty finite set of real
numbers are equal.
Similarly, min in Raku works as infimum for some Range.
1 ^.. 10
andthen .min; #1
but 1 is not from 1 ^.. 10, so 1 is not minimum, but it is infimum
of the range.
It is useful for some algorithm, see the answer by Jonathan
Worthington or
q{3 1 3
-2
--
-5 10
}.lines
andthen .map: *.comb( /'-'?\d+/ )».Int # (3, 1, 3), (-2,), (), (-5, 10)
andthen .map: *.min # 1,-2,Inf,-5
andthen .produce: &[min]
andthen .fmt: '%2d',',' # 1,-2,-2,-5
this (from the docs) makes sense to me
method min(Range:D:)
Returns the start point of the range.
say (1..5).min; # OUTPUT: «1␤»
say (1^..^5).min; # OUTPUT: «1␤»
and I think the infinimum idea is quite a good mnemonic for the excludes case which also could be 5.1^.. , 5.0001^.. etc.

Ranking Big O Functions By Complexity

I am trying to rank these functions — 2n, n100, (n + 1)2, n·lg(n), 100n, n!, lg(n), and n99 + n98 — so that each function is the big-O of the next function, but I do not know a method of determining if one function is the big-O of another. I'd really appreciate if someone could explain how I would go about doing this.
Assuming you have some programming background. Say you have below code:
void SomeMethod(int x)
{
for(int i = 0; i< x; i++)
{
// Do Some Work
}
}
Notice that the loop runs for x iterations. Generalizing, we say that you will get the solution after N iterations (where N will be the value of x ex: number of items in array/input etc).
so This type of implementation/algorithm is said to have Time Complexity of Order of N written as O(n)
Similarly, a Nested For (2 Loops) is O(n-squared) => O(n^2)
If you have Binary decisions made and you reduce possibilities into halves and pick only one half for solution. Then complexity is O(log n)
Found this link to be interesting.
For: Himanshu
While the Link explains how log(base2)N complexity comes into picture very well, Lets me put the same in my words.
Suppose you have a Pre-Sorted List like:
1,2,3,4,5,6,7,8,9,10
Now, you have been asked to Find whether 10 exists in the list. The first solution that comes to mind is Loop through the list and Find it. Which means O(n). Can it be made better?
Approach 1:
As we know that List of already sorted in ascending order So:
Break list at center (say at 5).
Compare the value of Center (5) with the Search Value (10).
If Center Value == Search Value => Item Found
If Center < Search Value => Do above steps for Right Half of the List
If Center > Search Value => Do above steps for Left Half of the List
For this simple example we will find 10 after doing 3 or 4 breaks (at: 5 then 8 then 9) (depending on how you implement)
That means For N = 10 Items - Search time was 3 (or 4). Putting some mathematics over here;
2^3 + 2 = 10 for simplicity sake lets say
2^3 = 10 (nearly equals --- this is just to do simple Logarithms base 2)
This can be re-written as:
Log-Base-2 10 = 3 (again nearly)
We know 10 was number of items & 3 was the number of breaks/lookup we had to do to find item. It Becomes
log N = K
That is the Complexity of the alogorithm above. O(log N)
Generally when a loop is nested we multiply the values as O(outerloop max value * innerloop max value) n so on. egfor (i to n){ for(j to k){}} here meaning if youll say for i=1 j=1 to k i.e. 1 * k next i=2,j=1 to k so i.e. the O(max(i)*max(j)) implies O(n*k).. Further, if you want to find order you need to recall basic operations with logarithmic usage like O(n+n(addition)) <O(n*n(multiplication)) for log it minimizes the value in it saying O(log n) <O(n) <O(n+n(addition)) <O(n*n(multiplication)) and so on. By this way you can acheive with other functions as well.
Approach should be better first generalised the equation for calculating time complexity. liken! =n*(n-1)*(n-2)*..n-(n-1)so somewhere O(nk) would be generalised formated worst case complexity like this way you can compare if k=2 then O(nk) =O(n*n)

Parameters model estimation

I have this data (t, TR and h) and need to estimate the parameters (a, b, c, d and e) for this model: h = (alog(TR)+b)(c*(t^d)-e)*41.59
t <- c(120,60,50,40,30,20,10,180,120,60,50,40,30,20,10,120,60,50,40,30,20,10,120,60,50,40,30,20,10)
TR <- c(2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,10,10,10,10,10,10,10,20,20,20,20,20,20,20)
h <- c(49.4,41.6,39.1,36.2,31.9,25.1,15.9,80.2,70.3,55.2,51.6,47.3,41.7,33.2,22.1,84.2,64.1,59.9,54.6,48.1,38.6,26.2,97.5,72.8,67.9,61.6,54.3,43.7,30.1)
bell <- nls(h ~ ((a1*log(TR)+a2)*(a3*(t^b)-a4)*41.59), start = list(a=0.6,
b2=0.3, c=0.4, d=0.30, e=0.4))
I tried the "nls" and the "nls2" process but these didn't work because of this:
Error in nlsModel(formula, mf, start, wts) :
singular gradient matrix at initial parameter estimates
So,I founded a possible solution following this procedure (I think it's a Linearly Constrained Optimization):
Solve this system of equations
U1 <- log(TR)*(c1*t^d1-e1)*41.59
U2 <- (c1*t^d1-e1)*41.59
U3 <- t^d1*(a1*log(TR)+b1)*41.59
U4 <- c1*t^d1*log(t)*((a1*log(TR))+b1)*41.59
U5 <- -(a1*log(TR)+b1)*41.59
From the initial values assumed for the parameters of the model,
successively the system of linear equations, in order to obtain values of the deviations each time nearest zero.
ΣZ = (a1-a) ΣU1,i + (b1-b) ΣU2,i + (c1-c) ΣU3,1 + (d1-d) ΣU4,i + (e1-e) ΣU5,i
For each iteration, the values of the parameters assume those obtained in
previous iteration, plus the deviations...
How could I do this in R?
I'm sorry cause I'm a R beginner and I don't speak english very well.
Many thanks for any help you can give me.

Np.where function

I've got a little problem understanding the where function in numpy.
The ‘times’ array contains the discrete epochs at which GPS measurements exist (rounded to the nearest second).
The ‘locations’ array contains the discrete values of the latitude, longitude and altitude of the satellite interpolated from 10 seconds intervals to 1 second intervals at the ‘times’ epochs.
The ‘tracking’ array contains an array for each epoch in ‘times’ (array within an array). The arrays have 5 columns and 32 rows. The 32 rows correspond to the 32 satellites of the GPS constellation. The 0th row corresponds to the 1st satellite, the 31st to the 32nd. The columns contain the following (in order): is the satellite tracked (0), is L1 locked (1), is L2 locked (2), is L1 unexpectedly lost (3), is L2 unexpectedly lost (4).
We need to find all the unexpected losses and put them in an array so we can plot it on a map.
What we tried to do is:
i = 0
with np.load(r’folderpath\%i.npz' %i) as oneday_data: #replace folderpath with your directory
times = oneday_data['times']
locations = oneday_data['locations']
tracking = oneday_data['tracking']
A = np.where(tracking[:][:][4] ==1)
This should give us all the positions of the losses. With this indices it is easy to get the right locations. But it keeps returning useless data.
Can someone help us?
I think the problem is your dual slices. Further, having an array of arrays could lead to weird problems (I assume you mean an object array of 2D arrays).
So I think you need to dstack tracking into a 3D array, then do where on that. If the array is already 3D, then you can skip the dstack part. This will get the places where L2 is unexpectedly lost, which is what you did in your example:
tracking3d = np.dstack(tracking)
A0, A2 = np.where(tracking3d[:, 4, :]==1)
A0 is the position of the 1 along axis 0 (satellite), while A2 is the position of the same 1 along axis 2 (time epoch).
If the values of tracking can only be 0 or 1, you can simplify this by just doing np.where(tracking3d[:, 4, :]).
You can also roll the axes back into the configuration you were using (0: time epoch, 1: satellite, 2: tracking status)
tracking3d = np.rollaxis(np.dstack(tracking), 2, 0)
A0, A1 = np.where(tracking3d[:, :, 4]==1)
If you want to find the locations where L1 or L2 are unexpectedly lost, you can do this:
tracking3d = np.rollaxis(np.dstack(tracking), 2, 0)
A0, A1, _ = np.where(tracking3d[:, :, 3:]==1)
In this case it is the same, except there is a dummy variable _ used for the location along the last axis, since you don't care whether it was lost for L1 or L2 (if you do care, you could just do np.where independently for each axis).

Fast way of multiplying two 1-D arrays

I have the following data:
A = [a0 a1 a2 a3 a4 a5 .... a24]
B = [b0 b1 b2 b3 b4 b5 .... b24]
which I then want to multiply as follows:
C = A * B' = [a0b0 a1b1 a2b2 ... a24b24]
This clearly involves 25 multiplies.
However, in my scenario, only 5 new values are shifted into A per "loop iteration" (and 5 old values are shifted out of A). Is there any fast way to exploit the fact that data is shifting through A rather than being completely new? Ideally I want to minimize the number of multiplication operations (at a cost of perhaps more additions/subtractions/accumulations). I initially thought a systolic array might help, but it doesn't (I think!?)
Update 1: Note B is fixed for long periods, but can be reprogrammed.
Update 2: the shifting of A is like the following: a[24] <= a[19], a[23] <= a[18]... a[1] <= new01, a[0] <= new00. And so on so forth each clock cycle
Many thanks!
Is there any fast way to exploit the fact that data is shifting through A rather than being completely new?
Even though all you're doing is the shifting and adding new elements to A, the products in C will, in general, all be different since one of the operands will generally change after each iteration. If you have additional information about the way the elements of A or B are structured, you could potentially use that structure to reduce the number of multiplications. Barring any such structural considerations, you will have to compute all 25 products each loop.
Ideally I want to minimize the number of multiplication operations (at a cost of perhaps more additions/subtractions/accumulations).
In theory, you can reduce the number of multiplications to 0 by shifting and adding the array elements to simulate multiplication. In practice, this will be slower than a hardware multiplication so you're better off just using any available hardware-based multiplication unless there's some additional, relevant constraint you haven't mentioned.
on the very first 5 data set you could be saving upto 50 multiplications. but after that its a flat road of multiplications. since for every set after the first 5 set you need to multiply with the new set of data.
i'l assume all the arrays are initialized to zero.
i dont think those 50 saved are of any use considering the amount of multiplication on the whole.
But still i will give you a hint on how to save those 50 maybe you could find an extension to it?
1st data set arrived : multiply the first data set in a with each of the data set in b. save all in a, copy only a[0] to a[4] to c. 25 multiplications here.
2nd data set arrived : multiply only a[0] to a[4](having new data) with b[0] to b[4] resp. save in a[0] to a[4],copy to a[0->9] to c. 5 multiplications here
3rd data set arrived : multiply a[0] to a[9] with b[0] to b[9] this time and copy to corresponding a[0->14] to c.10 multiplications here
4th data set : multiply a[0] to a[14] with corresponding b copy corresponding a[0->19] to c. 15 multiplications here.
5th data set : mutiply a[0] to a[19] with corresponding b copy corresponding a[0->24] to c. 20 multiplications here.
total saved mutiplications : 50 multiplications.
6th data set : usual data multiplications. 25 each. this is because for each set in the array a there a new data set avaiable so multiplication is unavoidable.
Can you add another array D to flag the changed/unchanged value in A. Each time you check this array to decide whether to do new multiplications or not.