Changing a code to get the Goldbach conjecture - matlab

To test the Golbach conjecture I have found the following code, but when I ren it out, this only gives me the number of combinations of primes, but in fact what I was searching for are the primes,I mean the couple of primes such that I get the even number.
Can someone help me to change the below code in matlab to get the couple of primes?
function y=goldbach_partition(n)
if mod(n,2)==0
y=0;
for i=2:floor(n/2)
if isprime(i) & isprime(n-i)
y=y+1;
end;
end;
end;
Thanks a lot in advance :)

That's pretty simple. Create a new array that will store the prime number i (or n-i... can't say for sure) in an array should the value i (and n-i) pass the criterion, then return that array. BTW, you should move your y=0 statement outside of the if statement, because if n is odd, you will never see y being output and you'll get an error.
Something like this:
function [y,pmes]=goldbach_partition(n) %// Change
y = 0; %// Change
pmes = []; %// Change
if mod(n,2)==0
for i=2:floor(n/2)
if isprime(i) & isprime(n-i)
y=y+1;
pmes = [pmes; i n-i]; %// Change
end
end
end
I'm not sure which prime number you're after - if it's i or n-i, so I've added them both. I've also made sure that both primes should they meet the condition be placed in a single row of your matrix. This way, each row will give you when a pair of primes has passed the condition.
Therefore, the above code will not only return the total number of primes, it'll return an array of all of the primes that passed the condition.
You would then call your function this way in MATLAB:
[y,pmes] = goldbach_partition(n);

Related

Declaring a vector in matlab whose size we don't know

Suppose we are running an infinite for loop in MATLAB, and we want to store the iterative values in a vector. How can we declare the vector without knowing the size of it?
z=??
for i=1:inf
z(i,1)=i;
if(condition)%%condition is met then break out of the loop
break;
end;
end;
Please note first that this is bad practise, and you should preallocate where possible.
That being said, using the end keyword is the best option for extending arrays by a single element:
z = [];
for ii = 1:x
z(end+1, 1) = ii; % Index to the (end+1)th position, extending the array
end
You can also concatenate results from previous iterations, this tends to be slower since you have the assignment variable on both sides of the equals operator
z = [];
for ii = 1:x
z = [z; ii];
end
Sadar commented that directly indexing out of bounds (as other answers are suggesting) is depreciated by MathWorks, I'm not sure on a source for this.
If your condition computation is separate from the output computation, you could get the required size first
k = 0;
while ~condition
condition = true; % evaluate the condition here
k = k + 1;
end
z = zeros( k, 1 ); % now we can pre-allocate
for ii = 1:k
z(ii) = ii; % assign values
end
Depending on your use case you might not know the actual number of iterations and therefore vector elements, but you might know the maximum possible number of iterations. As said before, resizing a vector in each loop iteration could be a real performance bottleneck, you might consider something like this:
maxNumIterations = 12345;
myVector = zeros(maxNumIterations, 1);
for n = 1:maxNumIterations
myVector(n) = someFunctionReturningTheDesiredValue(n);
if(condition)
vecLength = n;
break;
end
end
% Resize the vector to the length that has actually been filled
myVector = myVector(1:vecLength);
By the way, I'd give you the advice to NOT getting used to use i as an index in Matlab programs as this will mask the imaginary unit i. I ran into some nasty bugs in complex calculations inside loops by doing so, so I would advise to just take n or any other letter of your choice as your go-to loop index variable name even if you are not dealing with complex values in your functions ;)
You can just declare an empty matrix with
z = []
This will create a 0x0 matrix which will resize when you write data to it.
In your case it will grow to a vector ix1.
Keep in mind that this is much slower than initializing your vector beforehand with the zeros(dim,dim) function.
So if there is any way to figure out the max value of i you should initialize it withz = zeros(i,1)
cheers,
Simon
You can initialize z to be an empty array, it'll expand automatically during looping ...something like:
z = [];
for i = 1:Inf
z(i) = i;
if (condition)
break;
end
end
However this looks nasty (and throws a warning: Warning: FOR loop index is too large. Truncating to 9223372036854775807), I would do here a while (true) or the condition itself and increment manually.
z = [];
i = 0;
while !condition
i=i+1;
z[i]=i;
end
And/or if your example is really what you need at the end, replace the re-creation of the array with something like:
while !condition
i=i+1;
end
z = 1:i;
As mentioned in various times in this thread the resizing of an array is very processing intensive, and could take a lot of time.
If processing time is not an issue:
Then something like #Wolfie mentioned would be good enough. In each iteration the array length will be increased and that is that:
z = [];
for ii = 1:x
%z = [z; ii];
z(end+1) = ii % Best way
end
If processing time is an issue:
If the processing time is a large factor, and you want it to run as smooth as possible, then you need to preallocating.If you have a rough idea of the maximum number of iterations that will run then you can use #PluginPenguin's suggestion. But there could still be a change of hitting that preset limit, which will break (or severely slow down) the program.
My suggestion:
If your loop is running infinitely until you stop it, you could do occasional resizing. Essentially extending the size as you go, but only doing it once in a while. For example every 100 loops:
z = zeros(100,1);
for i=1:inf
z(i,1)=i;
fprintf("%d,\t%d\n",i,length(z)); % See it working
if i+1 >= length(z) %The array as run out of space
%z = [z; zeros(100,1)]; % Extend this array (note the semi-colon)
z((length(z)+100),1) = 0; % Seems twice as fast as the commented method
end
if(condition)%%condition is met then break out of the loop
break;
end;
end
This means that the loop can run forever, the array will increase with it, but only every once in a while. This means that the processing time hit will be minimal.
Edit:
As #Cris kindly mentioned MATLAB already does what I proposed internally. This makes two of my comments completely wrong. So the best will be to follow what #Wolfie and #Cris said with:
z(end+1) = i
Hope this helps!

Converting mixed empty/non-empty cells into a numeric matrix

I am working on a code to extract my AR(1)-GARCH(1) parameter, which I estimated using an AR(1)-GJR(1,1) model to individual matrices so that I can use them as variables in my calculations. As I have 16 time series variables, I combine the code with a loop in the following way:
for i=1:nIndices
AA_ARCH(:,i) = cell2mat(fit{i}.Variance.ARCH)';
end;
My problem is that for some variables is are no for AA_ARCH(:,i) the dimension is lower than nIndices. Naturally, when I try to export the estimates in the loop which specified the dimension of (:,i) and nIndices matlab reports a dimension mismatch. I would like to tell Matlab to replace the NaN with 0 instead of leaving the spot empty so that it is able to produce a (1,nIndices) matrix from AA_ARCH.
I thought of something like the this:
fit{i}.Variance.Leverage(isnan(fit{i}.Variance.Leverage))=0
but I wasn't able to combine this part with the previous code.
I would be very happy about any hints!
Best, Carolin
UPDATE:
Here is a fully a runnable version of my code which produces my problem. Notice that the code produces a dimension mismatch error because there is no ARCH and GARCH estimate in the fit.gjr(1,1) for time series 1. For these missing values I would like to have 0 as a placeholder in the extracted matrix.
returns = randn(2,750)';
T = size(returns,1);
nIndices = 2;
model = arima('AR', NaN, 'Variance', gjr(1,1));
residuals = NaN(T, nIndices);
variances = NaN(T, nIndices);
fit = cell(nIndices,1);
options = optimset('fmincon');
options = optimset(options, 'Display' , 'off', 'Diagnostics', 'off', ...
'Algorithm', 'sqp', 'TolCon' , 1e-7);
for i = 1:nIndices
fit{i} = estimate(model, returns(:,i), 'print', false, 'options', options);
[residuals(:,i), variances(:,i)] = infer(fit{i}, returns(:,i));
end
for i=1:nIndices
AA_beta(:,i) = cell2mat(fit{i}.AR)';
AA_GARCH(:,i) = cell2mat(fit{i}.Variance.GARCH)';
AA_ARCH(:,i) = cell2mat(fit{i}.Variance.ARCH)';
AA_Leverage(:,i) = cell2mat(fit{i}.Variance.Leverage)';
end;
I have some general things to say about the code, but first a solution to your problem:
You can put a simple if/else structure in your loop to handle the case of an empty array:
for ind1=1:nIndices
AA_beta(:,ind1) = cell2mat(fit{ind1}.AR)'; %//'
%// GARCH
if isempty(cell2mat(fit{ind1}.Variance.GARCH)') %//'
AA_GARCH(1,ind1) = 0;
else
AA_GARCH(:,ind1) = cell2mat(fit{ind1}.Variance.GARCH)'; %//'
end
%// ARCH (same exact code, should probably be exported to a function)
if isempty(cell2mat(fit{ind1}.Variance.ARCH)') %//'
AA_ARCH(1,ind1) = 0;
else
AA_ARCH(:,ind1) = cell2mat(fit{ind1}.Variance.ARCH)'; %//'
end
AA_Leverage(:,ind1) = cell2mat(fit{ind1}.Variance.Leverage)'; %//'
end;
Side note: I initially tried something like this: soz = #(A)isempty(A)*0+~isempty(A)*A; as an inline replacement for the if/else, but it turns out that MATLAB doesn't handle [] + 0 the way I wanted (it results in [] instead of 0; unlike other languages like JS).
As for the other things I have to say:
I am a firm supporter of the notion that one shouldn't use i,j as loop indices, as this may cause compatibility problems in some cases where complex numbers are involved (e.g. if you loop index is i then 1*i now refers to the loop index instead of to the square root of -1).
Part of your problem was that the arrays you were writing into weren't preallocated - which also means the correct datatype was unknown to MATLAB at the time of their creation. Besides the obvious performance hit this entails, it could also result in errors like the one you encountered here. If, for example, you used cells for AA_beta etc. then they could contain empty values, which you could later replace with whichever placeholder your heart desired using a combination of cellfun and isempty. Bottom line: lint (aka the colorful square on the top right of the editor window) is your friend - don't ignore it :)

Modifying Iteration for Multiple Inputs

I am doing an iteration to find the corresponding latitude/longitude at a height (h_intercept). My code works perfectly for a single height value. However, I want to find the lat/long of 79 heights (1x79 matrix) and therefore have an output that is a 3x79 matrix (llh_test). I've tried a for loop but I can't seem to get the results I want. I am probably doing something stupid.
Basically, I need to modify it so it will run with rng_sat, u_sat and h_intercept all being 1x79 matrices. It needs to step through the entire iteration before moving to the next values of rng_sat, u_sat and h_intercept
Also, I want to store all of the llh_test values (3x79 matrix)
rng_sat= sat_look_tcs_pass1(3,1)/2e2;
u_sat=[sat_look_tcs_pass1(1,1)/sat_look_tcs_pass1(3,1);sat_look_tcs_pass1(2,1)/sat_look_tcs_pass1(3,1);sat_look_tcs_pass1(3,1)/sat_look_tcs_pass1(3,1)];
h_intercept=sat_look_pass1_llh(3,1)/2e3;
h_test=0;
rng_test_min=0;
rng_test_max=rng_sat;
err=0.01;
while abs(h_test-h_intercept)>err
rng_test=(rng_test_min+rng_test_max)/2;
tcs_test=u_sat*rng_test;
llh_test=tcs2llhT(tcs_test,station_llh);
h_test=llh_test(3,:);
if h_test>=h_intercept;
rng_test_max=rng_test;
else
rng_test_min=rng_test;
end
end
The easiest thing to do here would be to encapsulate this into a single for loop, and change the way you're accessing the core variables so that you're using the loop index instead. Looking at your code, I'm assuming that sat_look_tcs_pass1 is a 3 x 79 matrix. I'm also going to assume that the output height h_test is a single value because when you're doing h_test = llh_test(3,:), h_test will actually become a vector, as you are trying to get all of the columns for the third row. I'm going to assume that this is a single value, rather than an array.
To modify this code, this actually will take no effort at all, so here's where you need to modify. Anywhere you see %// NEW is where I modified and anything else is your original code:
llh_test = zeros(3,79); %// Preallocate
for k = 1 : 79 %// You have 79 values to go through
rng_sat = sat_look_tcs_pass1(3,k)/2e2; %// NEW Change to k
u_sat = [sat_look_tcs_pass1(1,k)/sat_look_tcs_pass1(3,k); ...
sat_look_tcs_pass1(2,k)/sat_look_tcs_pass1(3,k);...
sat_look_tcs_pass1(3,k)/sat_look_tcs_pass1(3,k)]; %// NEW - Change to k
h_intercept = sat_look_pass1_llh(3,k)/2e3; %// NEW - Change to k
rng_test_min=0;
rng_test_max=rng_sat;
err=0.01;
while abs(h_test-h_intercept) > err
rng_test=(rng_test_min+rng_test_max)/2;
tcs_test=u_sat*rng_test;
llh_test(:,k) = tcs2llhT(tcs_test,station_llh); %// NEW - llh_test is now a matrix
h_test = llh_test(3,k); %// NEW - Changed the way we are accessing llh_test
if h_test >= h_intercept
rng_test_max=rng_test;
else
rng_test_min=rng_test;
end
end
end
Take a look at the general pattern of your code. You essentially are changing all of the points where you were accessing the first column with the kth column. Also, llh_test is a matrix, and so for each iteration in your loop, you want to access the kth column. llh_test should now be a 3 x 79 matrix as per your specifications.
Good luck!

Mark values from loop for each iteration

I want to mark each value that comes out of my loop with a value.
Say I have a variable number of values that come out of each iteration. I want those values to be labeled by which iteration they came out of.
like
1-1,
2-1,
3-1,
1-2,
2-2,
3-2,
4-2,
etc.
where the first number is the value from the loop and the second is counting which iteration it came from.
I feel like there is a way I just cant find it.
ok so here is some code.
for c=1:1:npoints;
for i=1:1:NN;
if ((c-1)*spacepoints)<=PL(i+1) && ((c-1)*spacepoints)>=PL(i);
local(c)=((c)*spacepoints)-PL(i);
end
if ((c-1)*spacepoints)>=PL(NN);
local(c)=((c)*spacepoints)-PL(NN);
element(i)=NN;
end
end
I want to mark each local value with the iteration it came from for the i:NN. PL is a vector and the output is a set of vectors for each iteration.
For this sort of quick problem I like to create a cell array:
for k = 1:12
results{k} = complicated_function(...);
end
If the output is really complicated, then I return a struct with fields relating to the outputs:
for k = 1:12
results{k}.file = get_filename(...);
results{k}.result = ...;
end
Currently as it is right now, in your inner 1:NN loop, your local(c) variable is being updated or overwritten. You never apply the previous value of local, so it is not some iterative optimization algorithm(?)...
Perhaps an easy solution is to change the size/type of local from a vector to a matrix. Let's say that local is of size [npoints 1]. Instead you make it of size [npoints NN]. It is now a 2d-array (a matrix of npoints rows and NN columns). use the second dimension to store each (assumed column) vector from the inner loop:
local = zeros([npoints NN]);
%# ... code in bewteen ...
for c=1:1:npoints;
for i=1:1:NN;
if ((c-1)*spacepoints)<=PL(i+1) && ((c-1)*spacepoints)>=PL(i);
local(c, i)=((c)*spacepoints)-PL(i);
end
if ((c-1)*spacepoints)>=PL(NN);
local(c, i)=((c)*spacepoints)-PL(NN);
element(i)=NN;
end
end
end
The c'th row of your local matrix will then corresponds to the NN values from the inner loop. Please note that I have assumed your vector to be a column vector - if not, just change the order of the sizes.

MATLAB setting matrix values in an array

I'm trying to write some code to calculate a cumulative distribution function in matlab. When I try to actually put my results into an array it yells at me.
tempnum = ordered1(1);
k=2;
while(k<538)
count = 1;
while(ordered1(k)==tempnum)
count = count + 1;
k = k + 1;
end
if(ordered1(k)~=tempnum)
output = [output;[(count/537),tempnum]];
k = k + 1;
tempnum = ordered1(k);
end
end
The errors I'm getting look like this
??? Error using ==> vertcat
CAT arguments dimensions are not consistent.
Error in ==> lab8 at 1164
output = [output;[(count/537),tempnum]];
The line to add to the output matrice was given to me by my TA. He didn't teach us much syntax throughout the year so I'm not really sure what I'm doing wrong. Any help is greatly appreciated.
If you're building the matrix output from scratch, you should make sure it hasn't already been initialized to anything. To do this, you can set it to the empty matrix at the beginning of your code:
output = [];
Also, if you know how large output is going to be, your code will run more efficiently if you preallocate the array output and index into the array to assign values instead of appending values to it. In your case, output should have the same number of rows as there are unique values in the array ordered1, so you could use the function UNIQUE to preallocate output:
nRows = numel(unique(ordered1)); %# Get the number of unique values
output = zeros(nRows,2); %# Initialize output
You would then have to keep a separate counter (say r) to track which index into output you will be adding to next:
...
output(r,:) = [count/537 tempnum]; %# Overwrite a row in output
r = r+1; %# Increment the row index
...
Some additional advice...
Even if you solve the error you are getting, you're going to run into more with the code you have above:
I believe you are actually computing a probability density function (or PDF) with your code. In order to get the cumulative distribution function (or CDF), you have to perform a cumulative sum over the final values in the first column of output. You can do this with the function CUMSUM:
output(:,1) = cumsum(output(:,1));
Your loop will throw an error when it reaches the last element of ordered1. The value of k can become 538 in your inner while loop, which will then cause an error to be thrown when you try to access ordered1(k) anywhere. To get around this, you will have to add checks to the value of k at a number of points in your code. One such point is your inner while loop, which can be rewritten as:
while (k <= 537) && (ordered1(k) == tempnum)
count = count + 1;
k = k + 1;
end
This solution uses the short-circuit AND operator &&, which will first check if (k <= 537) is true or false. If it is false (i.e. k > 537), the second logical check is skipped since its result doesn't matter, and you avoid the error that would result from evaluating ordered1(k).
Bonus MATLAB coolness...
MATLAB has a lot of cool functions that can do a lot of the work for you. One such function is ACCUMARRAY. Your TA may want you to do things using loops like you have above, but you can actually reduce your whole code to just a few lines like so:
nValues = numel(ordered1); %# Get the number of values
p = accumarray(ordered1,ones(size(ordered1)))./nValues; %# Create a PDF
output = [cumsum(p) unique(ordered1)]; %# Create the CDF output