Using for in a loop with different intervals - matlab

I have a for loop testing the max of a function:
function Start
max_i = 0;
max_j = 0;
max_value = 0;
for i =1:3500
for j = 1:3500
new_value = CalcUFamily(i,j);
if new_value > max_value;
max_value = new_value;
max_i = i;
max_j = j;
end
end
end
max_i
max_j
end
function uFamily = CalcUFamily(hh,hw) %h = male, w = wife
(code)
end
The basic is that it is testing a function that I have been trying to optimize (with some help from here) but which I have so far failed to do. I therefore want to test to make a loop that tests all possible values, work hours for a husband and a wife, from 1 h to 3500 h (yearly). I then want to get the highest utility value from CalcUFamily and its corresponding input variables, hh and hw (called i and j in the function above).
My code works well, apart from the fact that it takes too long to run since it runs 12 250 000 times. I therefore want to rase the test interval from 1 to 10 or maybe even 100. Is this possible with the for code, or do I have to rewrite it somehow?
Thanks a lot for your help!

Reshape CalcUFamily into a vector using colon (or reshape) and use max to find the maximum value (max_value) and its linear index. Now use ind2sub to convert this linear index into the equivalent row (hh or max_i) and column (hw or max_j) subscripts.
[max_value, max_Ind] = max(CalcUFamily(:));
[hh, hw] = ind2sub(size(CalcUFamily), max_Ind);

I found a solution myself! :)
max_hh = 0;
max_hw = 0;
max_value_hhhw = -50000;
max_value_u = -50000;
hh = 1;
hw = 1;
runs = 0;
interval = 10;
datestr(clock)
while hw < 3501
while hh < 3501 %runs hh to all posible values
new_value = CalcUFamily(hh,hw);
if new_value > max_value_u
max_value_hhhw = [hh hw]; %working hour husband, working hour wife, and its utility value
max_value_u = new_value;
end
hh = hh + interval;
runs = runs + 1; % number of runs
end
hh = 1;
hw = hw + interval;
end
runs
datestr(clock)
max_value_hhhw

Related

How to write this equation that runs partitions?

I don't know where to go with this. I think I have the right stuff down but I don't understand.
https://imgur.com/a/V6gdDdr
It keeps running the loop forever and I don't know why.
n=9;
r =0;
p = 0;
syms x
v=1.7;
while abs(v-r) > 10^(-5)
n=n+1;
r = 0;
a = 0;
b= 1/n;
for i = 1:n
r = r + exp(((i+1)+exp(i))/2)*(b-a)
end
['done']
end
The output should be 85. But I'm getting like a couple thousand. I have tried changing the equation in the for loop but I do not know why it is giving me symbolic errors.
Several problems with the posted code:
The parentheses are misaligned in the r=r + ... statement
Instead of exp(i) and exp(i+1), you should use exp(bi) and exp(b(i+1)) in order to account for the given spacing.
Your value of "v" which is supposed be the exact answer should equal e-1, which is 1.71828. Using the approximate 1.7 is going to be very problematic when you are trying to converge to the exact solution within 5 decimal places.
Your for loop should go from 0 to n-1, this way you don't add up any values past your integral range.
n=9;
r =0;
p = 0;
v=e-1;
while abs(v-r) > 10^(-5)
n=n+1;
r = 0;
a = 0;
b= 1/n;
for i = 0:n-1
r = r + ((exp(b*(i+1))+exp(b*i))/2)*(b-a);
end
end

MATLAB — How to eliminate equal matrices that are created randomly inside loop?

The code segment I'm working on is given below:
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
i = 1;
while i <= 10 %number of iterations
ind = randi([1 NphaseSteps],10,10);
inField{i} = phases(ind);
save('inField.mat', 'inField')
i = i + 1;
end
Now, what I want is to keep track of these randomly created matrices "inField{i}" and eliminate the ones that are equal to each other. I know that I can use "if" condition but since I'm new to programming I don't know how to use it more efficiently so that it doesn't take too much time. So, I need your help for a fast working program that does the job. Thanks in advance.
My actual code segment (after making the changes suggested by #bisherbas) is the following. Note that I actually want to use the variable "inField" inside the loop for every random created matrix and the loop advances only if the result satisfies a specific condition. So, I think the answer given by #bisherbas doesn't really eliminate the equal inField matrices before they are used in the calculation. This is, of course, my fault since I didn't declare that in the beginning.
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
nIterations = 5;
inField = cell(1,nIterations);
i = 1;
j = 1;
while i <= nIterations % number of iterations
ind = randi([1 NphaseSteps],TMsize,TMsize);
tmp = phases(ind);
idx = cellfun(#(x) isequal(x,tmp),inField);
if ~any(idx)
inField{i} = tmp;
end
j = j+1;
outField{i} = TM * inField{i};
outI = abs(outField{i}).^2;
targetIafter{i} = abs(outField{i}(focusX,focusY)).^2;
middleI = targetIafter{i} / 2;
if (max(max(outI)) == targetIafter{i})...
&& ( sum(sum((outI > middleI).*(outI < max(max(outI))))) == 0 )
save('inFieldA.mat', 'inField')
i = i + 1;
end
if mod(j-1,10^6) == 0
fprintf('The number of random matrices tried is: %d million \n',(j-1)/10^6)
end
end
Additionally, I've written a seemingly long expression for my loop condition:
if (max(max(outI)) == targetIafter{i})...
&& ( sum(sum((outI > middleI).*(outI < max(max(outI))))) == 0 )
save('inFieldA.mat', 'inField')
i = i + 1;
end
Here I want a maximum element at some point (focusX, focusY) in the outField matrix. So the first condition decides whether the focus point has the maximum element for the matrix. But I additionally want all other elements to be smaller than a specific number (middleI) and that's why the second part of the if condition is written. However, I'm not very comfortable with this second condition and I'm open to any helps.
Try this:
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
i = 1;
inField = cell(1,NphaseSteps);
while i <= NphaseSteps %number of iterations
ind = randi([1 NphaseSteps],NphaseSteps,NphaseSteps);
tmp = phases(ind);
idx = cellfun(#(x) isequal(x,tmp),inField);
if ~any(idx)
inField{i} = tmp;
end
save('inField.mat', 'inField')
i = i + 1;
end
Read more on cellfun here:
https://www.mathworks.com/help/matlab/ref/cellfun.html

How can I speed up this MATLAB code with a whileloop?

I'm using a code that calculates expectation value of probabilities. This code contains a while-loop that finds all possible combinations and adds up products of probability combinations. However, when the number of elements becomes large(over 40) it takes too much time, and I want to make the code faster.
The code is as follow-
function pcs = combsum(N,K,prbv)
nprbv=1-prbv; %prbv: probability vector
WV = 1:K; % Working vector.
lim = K; % Sets the limit for working index.
inc = 0; % Controls which element of WV is being worked on.
pcs = 0;
stopp=0;
while stopp==0
if logical((inc+lim)-N)
stp = inc; % This is where the for loop below stops.
flg = 0; % Used for resetting inc.
else
stp = 1;
flg = 1;
end
for jj = 1:stp
WV(K + jj - inc) = lim + jj; % Faster than a vector assignment.
end
PV=nprbv;
PV(WV)=prbv(WV);
pcs=prod(PV)+pcs;
inc = inc*flg + 1; % Increment the counter.
lim = WV(K - inc + 1 ); % lim for next run.
if (inc==K)&&(lim==N-K)
stopp=1;
WV = (N-K+1):N;
PV=nprbv;
PV(WV)=prbv(WV);
pcs=prod(PV)+pcs;
end
end
Is there a way to reduce calculation time? I wonder if parallel computing using GPU would help.
I tried to remove dependent variables in a loop for parallel computing, and I made a matrix of possible combinations using 'combnk' function. This worked faster.
nprbv=1-prbv; %prbv : a probability vector
N = 40;
K = 4;
n_combnk = size(combnk(1:N,K),1);
PV_mat = repmat(nprbv,n_combnk,1);
cnt = 0;
tic;
for i = 1:N-K+1
for j = i+1:N-K+2
for k = j+1:N-K+3
for l = k+1:N-K+4
cnt = cnt+1;
PV_mat(cnt,i) = prbv(i);
PV_mat(cnt,j) = prbv(j);
PV_mat(cnt,k) = prbv(k);
PV_mat(cnt,l) = prbv(l);
end
end
end
end
toc;
tic;
pcs_rr = sum(prod(PV_mat,2));
toc;
However, when K value gets larger, an out-of-memory problem happens in building a combination matrix(PV_mat). How can I break up the big matrix into small ones to avoid memory problem?

Stopping the output of a for cycle in matlab

I'm facing an issue with this simple Fibonacci number generator program:
function f = fibonr(n)
f(1) = 1;
f(2) = 1;
for i = 3:n
f(i) = f(i-1) + f(i-2);
end
end
If I want to display only the n-th number of the sequence, what adjustments should I make?
function f = fibonr(n)
f = zeros(n,1); %//initialise the output array
f(1,1) = 1;
f(2,1) = 1;
for ii = 3:n
f(ii,1) = f(ii-1,1) + f(ii-2,1);
end
%//create a string with text and variables
str = sprintf('The %d th number in the Fibonacci sequence is %d',n,f(ii,1));
disp(str) %//display your output.
end
first up: don't use i as a variable. Secondly, I switched to using column vectors, since MATLAB processes them faster, as well as I initialised the array, which is way faster (hence the shiny orange wiggles below your f(i)= line).
Call your function:
output = fibonr(10);
The 10 th number in the Fibonacci sequence is 55
If you use e.g. n=20 and still want the 10th argument just call output(10)
if you want the specified output right away you can use nargin. This code will give you all of the sequence if you call fibonr(n), or you can specify a vector to get the fibonacy numbers at said positions. If you are interested in both, your specified output and all the numbers, you can call the function with:
[output, fibnumbers] = fibonr(n,v);
function [output,f] = fibonr(n,v)
f(1) = 1;
f(2) = 1;
for i = 3:n
f(i) = f(i-1) + f(i-2);
end
if nargin() > 1
output = f(v);
else
output = f;
end

index must be a positive integer or logical?

k = 0.019;
Pstar = 100;
H = 33;
h = 0.1;
X = 36;
N = round(X/h);
t = zeros(1,N+1);
P = zeros(1,N+1);
P(1) = 84;
t(1) = 0;
yHeun = zeros(1,N+1);
yHeun(1)=84;
a = 1; b = 100;
while b-a >0.5
c = (a+b)/2;
for n = 1:N
t(n+1) = t(n) + h;
Inside = nthroot(sin(2*pi*t/12),15);
Harvest = c*0.5*(Inside+1);
P(n+1) = P(n) + h*(k*P(n)*(Pstar-P(n))-Harvest(n));
if P < 0
P = 0;
end
yHeun(n+1) = yHeun(n) + h*0.5*((k*P(n)*(Pstar-P(n))-Harvest(n))+(k*P(n+1)*(Pstar-P(n+1))-Harvest(n+1)));
end
if sign(yHeun(c)) == sign(yHeun(a))
c = a;
else
c = b;
end
end
disp(['The root is between ' num2str(a) ' and ' num2str(b) '.'])
This is the code i'm trying to run and i know it probably sucks but im terrible at coding and every time i try to run the code, it says:
Attempted to access yHeun(50.5); index must be a positive integer or
logical.
Error in Matlab3Q4 (line 30)
if sign(yHeun(c)) == sign(yHeun(a))
I don't have ANY idea how to make yHeun(c or a or whatever) return anything that would be an integer. I dont think i did the while+for loop right either.
Question: "Begin with the higher bound of H being 100 (the high value results in a population of 0 after 36 months), and the lower bound being 1. Put the solver from Problem #3 above in the middle of a while loop and keep bisecting the higher and lower bounds of H until the difference between the higher and lower bound is less than 0.5."
I guess that line 30 (with the error) is this one:
if sign(yHeun(c)) == sign(yHeun(a))
Here, I guess c is equal to 50.5, as a result of c = (a+b)/2 above (BTW you can discover whether I guessed right by debugging - try adding disp(c) before line 30).
To force a number to be an integer, use floor:
c = floor((a+b)/2);
It seems you are trying to use some sort of divide-and-conquer algorithm; it should be enough to stop when b - a is equal to 1.