Bellman-Ford Algorithm Short predecessor Array - bellman-ford

Having this Algorithm of Bellman-Ford with a slight change:
In line 7, instead of the inequality sign, we put >= so it becomes:
d[v] >= d[u] + w(u,v)
Now I know for a fact that it will not change the distances array and it will give me a correct answer.
But how will it affect my predecessor array on line 9? will it still give a correct answer?

If you have non positive edges it may not be a tree, for example for the following graph and starting from n1:
In the first pass:
by visiting e1: d[n2] = d[n1] + w[e1] = 1 & p[n2] = n1
by visiting e2: d[n3] = d[n2] + w[e2] = 1 & p[n3] = n2
by visiting e3: d[n4] = d[n3] + w[e3] = 1 & p[n4] = n3
by visiting e4: d[n2] = d[n4] + w[e4] = 1 & p[n2] = n4
and in all remaining passes, this will repeat. so at the end if you iterate over predecessor for example for n2 your will get: n2 <- n4 <- n3 <- n2 <- n4 <- ...
But I think if you don't have non-negative edges it works fine.

Related

Hash function that returns the same hash for a sum even if different terms lead to the same sum

let's say I have:
n = 14
n is the result of the following sums of integers:
[5, 2, 7] -> 5 + 2 + 7 = 14 = n
[3, 4, 5, 2] -> 3 + 4 + 5 + 2 = 14 = n
[1, 13] -> 1 + 13 = 14 = n
[13, 1] -> 13 + 1 = 14 = n
[4, 3, 5, 2] -> 4 + 3 + 5 + 2 = 14 = n
...
I would need a hash function h so that:
h([5, 2, 7]) = h([3, 4, 5, 2]) = h([1, 13]) = h([13, 1]) = h([4, 3, 5, 2]) = h(...)
I.e. it doesn't matter the order of the integer terms and as long as their integer sum is the same, their hash should also the same.
I need to do this without computing the sum n, because the terms as well as n can be very high and easily overflow (they don't fit the bits of an int), that's why I am asking this question.
Are you aware or maybe do you have an insight on how I can implement such a hash function?
Given a list/sequence of integers, this hash function must return the same hash if the sum of the integers would be the same, but without computing the sum.
Thank you for your attention.
EDIT: I elaborated on #derpirscher's answer and modified his function a bit further as I had collisions on multiples of BIG_PRIME (this example is in JavaScript):
function hash(seq) {
const BIG_PRIME = 999999999989;
const MAX_SAFE_INTEGER_DIV_2_FLOOR = Math.floor(Number.MAX_SAFE_INTEGER / 2);
let h = 0;
for (i = 0; i < seq.length; i++) {
let value = seq[i];
if (h > MAX_SAFE_INTEGER_DIV_2_FLOOR) {
h = h % BIG_PRIME;
}
if (value > MAX_SAFE_INTEGER_DIV_2_FLOOR) {
value = value % BIG_PRIME;
}
h += value;
}
return h;
}
My question now would be: what do you think about this function? Are there some edge cases I didn't take into account?
Thank you.
EDIT 2:
Using the above function hash([1,2]); and hash([4504 * BIG_PRIME +1, 4504 * BIG_PRIME + 2]) will collide as mentioned by #derpirscher.
Here is another modified of version of the above function, which computes the modulo % BIG_PRIME only to one of the two terms if either of the two are greater than MAX_SAFE_INTEGER_DIV_2_FLOOR:
function hash(seq) {
const BIG_PRIME = 999999999989;
const MAX_SAFE_INTEGER_DIV_2_FLOOR = Math.floor(Number.MAX_SAFE_INTEGER / 2);
let h = 0;
for (let i = 0; i < seq.length; i++) {
let value = seq[i];
if (
h > MAX_SAFE_INTEGER_DIV_2_FLOOR &&
value > MAX_SAFE_INTEGER_DIV_2_FLOOR
) {
if (h > MAX_SAFE_INTEGER_DIV_2_FLOOR) {
h = h % BIG_PRIME;
} else if (value > MAX_SAFE_INTEGER_DIV_2_FLOOR) {
value = value % BIG_PRIME;
}
}
h += value;
}
return h;
}
I think this version lowers the number of collisions a bit further.
What do you think? Thank you.
EDIT 3:
Even though I tried to elaborate on #derpirscher's answer, his implementation of hash is the correct one and the one to use.
Use his version if you need such an hash function.
You could calculate the sum modulo some big prime. If you want to stay within the range of int, you need to know what the maximum integer is, in the language you are using. Then select a BIG_PRIME that's just below maxint / 2
Assuming an int to be 4 bytes, maxint = 2147483647 thus the biggest prime < maxint/2 would be 1073741789;
int hash(int[] seq) {
BIG_PRIME = 1073741789;
int h = 0;
for (int i = 0; i < seq.Length; i++) {
h = (h + seq[i] % BIG_PRIME) % BIG_PRIME;
}
return h;
}
As at every step both summands will always be below maxint/2 you won't get any overflows.
Edit
From a mathematical point of view, the following property which may be important for your use case holds:
(a + b + c + ...) % N == (a % N + b % N + c % N + ...) % N
But yeah, of course, as in every hash function you will have collisions. You can't have a hash function without collisions, because the size of the domain of the hash function (ie the number of possible input values) is generally much bigger than the the size of the codomain (ie the number of possible output values).
For your example the size of the domain is (in principle) infinite, as you can have any count of numbers from 1 to 2000000000 in your sequence. But your codomain is just ~2000000000 elements (ie the range of int)

Why Is Matlab Ignoring My If Statements?

So I have to write program that solves for these rules:
Find a six digit number in which the first digit is one more than the third, the second digit is one less than the fourth, the fifth digit is one less than the third, and the sixth digit is one more than the fourth. The sum of the second and third digits equals the first. The sum of all digits is thirty.
I am only allowed to use nested for and if statements and this is what I came up with:
for I = inf
for n4 = (1:9)
n6 = n4 + 1;
n2 = n4 -1;
for n3 = (1:9)
n1 = n3 + 1;
n5 = n3 - 1;
if (n1 - n2 == n3)
if (n1 + n2 + n3 + n4 + n5 + n6 == 30)
break
end
end
end
end
end
The issue I am having is that Matlab ignores all my if statements because at the end of the program, n1 - n2 = 0, n3 = 9, and the sum n1+n2+...+n6 = 22 not 30. This is my first project in Matlab so I hope I gave enough information for this question,
Thank you!
Code works perfectly and give right result, the only problem:
as already told break interrupts only 1 inner for loop.
If this is the whole code of your program you can use return instead of break.
Another way:
use some logical index.
For example:
flag = 0;
for I = inf
for n4 = (1:9)
n6 = n4 + 1;
n2 = n4 -1;
for n3 = (1:9)
n1 = n3 + 1;
n5 = n3 - 1;
if (n1 - n2 == n3)
if (n1 + n2 + n3 + n4 + n5 + n6 == 30)
flag = 1;
break
end
end
end
if flag==1
break
end
end
end
By the way. The answer is 918273.

The expression to the left of the equals sign is not a valid target for an assignment Matlab

Trying to write a loop that checks if one norm is bigger than the other.
for i = 1:360;
V1 = X(:, i);
N1 = norm(V1);
V2 = X(:, (i+1));
N2 = norm(V2);
N1 = highNorm;
if (N2 >= N1)
(P = N2)
end
However, I'm getting an error associated with P = N2:
Error: The expression to the left of the equals
sign is not a valid target for an assignment.
How do I fix this?
Get rid of the brackets around P=N2

Fast way to test whether n^2 + (n+1)^2 is perfect square

I am trying to program a code to test whether n^2 + (n+1)^2 is a perfect.
As i do not have much experience in programming, I only have Matlab at my disposal.
So far this is what I have tried
function [ Liste ] = testSquare(N)
if exist('NumberTheory')
load NumberTheory.mat
else
MaxT = 0;
end
if MaxT > N
return
elseif MaxT > 0
L = 1 + MaxT;
else
L = 1;
end
n = (L:N)'; % Makes a list of numbers from L to N
m = n.^2 + (n+1).^2; % Makes a list of numbers on the form A^2+(A+1)^2
P = dec2hex(m); % Converts this list to hexadecimal
Length = length(dec2hex(P(N,:))); %F inds the maximum number of digits in the hexidecimal number
Modulo = ['0','1','4','9']'; % Only numbers ending on 0,1,4 or 9 can be perfect squares in hex
[d1,~] = ismember(P(:,Length),Modulo); % Finds all numbers that end on 0,1,4 or 9
m = m(d1); % Removes all numbers not ending on 0,1,4 or 9
n = n(d1); % -------------------||-----------------------
mm = sqrt(m); % Takes the square root of all the possible squares
A = (floor(mm + 0.5).^2 == m); % Tests wheter these are actually squares
lA = length(A(A>0)); % Finds the number of such numbers
MaxT = N;
save NumberTheory.mat MaxT;
if lA>0
m = m(A); % makes a list of all the square numbers
n = n(A); % finds the corresponding n values
mm = mm(A); % Finds the squareroot values of m
fid = fopen('Tallteori.txt','wt'); % Writes everything to a simple text.file
for ii = 1:lA
fprintf(fid,'%20d %20d %20d\t',n(ii),m(ii),mm(ii));
fprintf(fid,'\n');
end
fclose(fid);
end
end
Which will write the squares with the corresponding n values to a file. Now I saw that using hexadecimal was a fast way to find perfect squares in C+, and tried to use this in matlab. However I am a tad unsure if this is the best approach.
The code above breaks down when m > 2^52 due to the hexadecimal conversion.
Is there an alternative way/faster to write all the perfect squares on the form n^2 + (n+1)^2 to a text file from 1 to N ?
There is a much faster way that doesn't even require testing. You need a bit of elementary number theory to find that way, but here goes:
If n² + (n+1)² is a perfect square, that means there is an m such that
m² = n² + (n+1)² = 2n² + 2n + 1
<=> 2m² = 4n² + 4n + 1 + 1
<=> 2m² = (2n+1)² + 1
<=> (2n+1)² - 2m² = -1
Equations of that type are easily solved, starting from the "smallest" (positive) solution
1² - 2*1² = -1
of
x² - 2y² = -1
corresponding to the number 1 + √2, you obtain all further solutions by multiplying that with a power of the primitive solution of
a² - 2b² = 1
which is (1 + √2)² = 3 + 2*√2.
Writing that in matrix form, you obtain all solutions of x² - 2y² = -1 as
|x_k| |3 4|^k |1|
|y_k| = |2 3| * |1|
and all x_k are necessarily odd, thus can be written as 2*n + 1.
The first few solutions (x,y) are
(1,1), (7,5), (41,29), (239,169)
corresponding to (n,m)
(0,1), (3,5), (20,29), (119,169)
You can get the next (n,m) solution pair via
(n_(k+1), m_(k+1)) = (3*n_k + 2*m_k + 1, 4*n_k + 3*m_k + 2)
starting from (n_0, m_0) = (0,1).
Quick Haskell code since I don't speak MatLab:
Prelude> let next (n,m) = (3*n + 2*m + 1, 4*n + 3*m + 2) in take 20 $ iterate next (0,1)
[(0,1),(3,5),(20,29),(119,169),(696,985),(4059,5741),(23660,33461),(137903,195025)
,(803760,1136689),(4684659,6625109),(27304196,38613965),(159140519,225058681)
,(927538920,1311738121),(5406093003,7645370045),(31509019100,44560482149)
,(183648021599,259717522849),(1070379110496,1513744654945),(6238626641379,8822750406821)
,(36361380737780,51422757785981),(211929657785303,299713796309065)]
Prelude> map (\(n,m) -> (n^2 + (n+1)^2 - m^2)) it
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
Edit by EitanT:
Here's the MATLAB code to calculate the first N numbers:
res = zeros(1, N);
nm = [0, 1];
for k = 1:N
nm = nm * [3 4; 2 3] + [1, 2];
res(k) = nm(1);
end
The resulting array res should hold the values of n that satisfy the condition of the perfect square.

Double summation with vectorized loops in Matlab

I want to vectorize this double for loop because it is a bottleneck in my code. Since Matlab is a based-one indexing language I have to create an additional term for M = 0.
R,r,lambda are constants
Slm(L,M),Clm(L,M) are matrices 70x70
Plm(L,M) is a matrix 70x71
Cl(L),Pl(L) are vectors 70x1
% function dU_r
s1 = 0;
for L = 2:70
s1 = s1 + ((R/r)^L)*(L+1)*Pl(L)*Cl(L);
for m = 1:L
s1 = s1 + ((R/r)^L)*(L+1)*Plm(L,M)*(Clm(L,M)*...
cos(M*lambda) + Slm(L,M)*sin(M*lambda));
end
end
dU_r = -(mu_p/(r^2))*s1;
% function dU_phi
s2=0;
for L = 2:70
s2 = s2 + ((R/r)^L))*Plm(L,1)*Cl(L);
for m = 1:l
s2 = s2 + ((R/r)^L)*(Plm(L,M+1)-M*tan(phi)*Plm(L,M))*...
(Clm(L,M)*cos(M*lambda) + Slm(L,M)*sin(M*lambda));
end;
end;
dU_phi = (mu_p/r)*s2;
% function dU_lambda
s3=0;
for L=2:70
for m=1:L
s3 = s3 + ((R/r)^L)*M*Plm(L,M)*(Slm(L,M)*cos(M*lambda)...
- Clm(L,M)*sin(M*lambda));
end;
dU_lambda = (mu_p/r)*s3;
I think the following code may be a part of the solution (only partially vectorized), for a full vectorization you might want to look at meshgrid, ndgrid, bsxfun and/or repmat, I suppose.
s2 = 0;
L = 2:70;
PlCl = Pl.*Cl;
PlmClm = Plm.*Clm;
Rrl = (R/r).^(L).*(L+1);
COS = cos((1:70)*lambda);
SIN = sin((1:70)*lambda);
for l=L
M = 1:l;
s1 = sum(Rrl(l-1)*PlmClm(l,M).*(COS(M) + Slm(l,M).*SIN(M)));
s2 = s2 + s1;
end;
s2 = s2 + sum(Rrl(L).*PlCl(L));
I haven't tried to run this code, so if it may complain about some dimensions. You should be able to figure that out (just some transposes here or there may do).
Just a note on the side: try to keep away from short variable names (and certainly ambiguous ones like l (that can be misread for a 1, a I or an l). Also, it might be easier to vectorize your code if you have actual (i.e. not coded) expressions to start with.
edit: applied corections suggested by gnovice
For this particular situation, it will likely be more efficient for you to not fully vectorize your solution. As Egon illustrates, it's possible to replace the inner loop through vectorization, but replacing the outer for loop as well could potentially slow-down your solution.
The reason? If you pay attention to how you index the matrices Plm, Clm, and Slm in your loop, you only ever use values from the lower triangular parts of them. All of the values above the main diagonal are ignored. By fully vectorizing your solution, such that it uses matrix operations instead of a loop, you would end up performing unnecessary multiplications with the zeroed-out upper triangular portions of the matrices. This is one of those cases where a for loop may be a better option.
As such, here's a refined and corrected version of Egon's answer that should be close to optimum with regard to the number of mathematical operations performed:
index = 2:70;
coeff = ((R/r).^index).*(index+1);
lambda = lambda.*(1:70).'; %'
cosVector = cos(lambda);
sinVector = sin(lambda);
s2 = coeff*(Pl(index).*Cl(index));
for L = index
M = 1:L;
s2 = s2 + coeff(L-1)*((Plm(L,M).*Clm(L,M))*cosVector(M) + ...
(Plm(L,M).*Slm(L,M))*sinVector(M));
end
Taking like reference a solution given by Jan Simon 1, I have written the following code for my problem
Rr = R/r;
RrL = Rr;
cosLambda = cos((1:70)* lambda);
sinLambda = sin((1:70)* lambda);
u1 = uint8(1);
s1 = 0;
s2 = 0;
s3 = 0;
for j = uint8(2):uint8(70)
RrL = RrL * Rr;
q1 = RrL * (double(j) + 1);
t1 = Pl(j) * datos.Cl(j);
q2 = RrL;
t2 = Plm(j,1) * Cl(j);
t3 = 0;
for m = u1:j
t1 = t1 + Plm(j,m) * ...
(Clm(j, m) * cosLambda(m) + ...
Slm(j, m) * sinLambda(m));
t2 = t2 + (Plm(j,m+1)-double(m)*tan_phi*Plm(j,m))*...
(Clm(j,m)*cosLambda(m) + Slm(j,m)*sinLambda(m));
t3 = t3 + double(m)*Plm(j,m)*(Slm(j,m)*cosLambda(m)...
- Clm(j,m)*sinLambda(m));
end
s1 = s1 + q1 * t1;
s2 = s2 + q2 * t2;
s3 = s3 + q2 * t3;
end
dU_r = -(mu_p/(r^2))*s1;
dU_phi = (mu_p/r)*s2;
dU_lambda = (mu_p/r)*s3