# Creating a For loop with fzero having multiple variables and selecting at random an output value

2 views (last 30 days)
Johan Bietmann on 4 Dec 2019
Commented: J. Alex Lee on 4 Dec 2019
The problem is as follows:
Demand and supply in a given market interact in a way that we have three possible equilibrium prices (ptstar) for rt.
u= @(ptstar,rt) (ptstar.^(-1/9) + 2 + rt.* ptstar.^(-1) - ptstar.^(-8/9)) - (2+rt);
Above, you can see the equation which sets demand and supply equal by subtracting supply(2+rt) from demand and solving for zero.
The thing is there are 50 different time periods rt and I need to find the three equilibrium prices for each period(so a total of 150).
After this process, I need to select one value for ptstar of the three possible ones by setting equal probabilities to the maximum(first) and minimum(third) value of the equilibrium price.
Here is my approach( I have no idea how to handle the part with selecting one value for ptstar):
rbar=0.77;
a=6*10^-3;
b=0;
et=a.*randn(50,1)+b;
rt = rbar+et
for i=linspace(rt(1),rt(50),50)
u= @(ptstar,i) (ptstar.^(-1/9) + 2 + i .* ptstar.^(-1) - ptstar.^(-8/9)) - (2+i);
ptstarMax=fzero(u,[1.1, 1e4],[],i)
ptstarMiddle=fzero(u,,[],i)
ptstarMin=fzero(u,[0.1, 0.7],[],i)
end
rt is a column vector of 50 numbers following a random distribution with mean 0 and standard dev.6*10^-3 plus 0.77.
Sometimes I get a result, however, the ptstarMax values comein ascending order which makes no sense, because the values of rt are random and in no particular order..
I suspect there is a problem with the linspace function looping rt(1) to rt(50) through each fzero function
Finnaly, sometimes this gets printed: However, sometimes it doesn't appear:
Error using fzero (line 290)
The function values at the interval endpoints must differ in sign.
Error in try2 (line 12)
ptstarMin=fzero(u,[0.1, 0.7],[],i)
I really appreciate the help! Thanks a lot!

J. Alex Lee on 4 Dec 2019
I see at least 2 problems.
1. looping; you're correct there's an issue, misuse of linspace
2. your initial guesses for fzero
For the loop issue, this should correct it (with better usage of function handle; or maybe its a personal style)
rbar=0.77;
a=6*10^-3;
b=0;
% this defines your randomized vector
et=a.*randn(50,1)+b;
rt = rbar+et
for i = 1:50
u = @(ptstar) (ptstar.^(-1/9) + 2 + rt(i) .* ptstar.^(-1) - ptstar.^(-8/9)) - (2+rt(i));
ptstarMax=fzero(u,[1.1, 1e4])
ptstarMiddle=fzero(u,)
ptstarMin=fzero(u,[0.1, 0.7])
end
The initial guess problem is less a coding problem and more a math problem. For ptstartMax and ptstartMin, you give end-points to your fzero search, whereas for the middle you only give it a starting point. You can get rid of the error you saw by only giving it a starting point for each, but then you are not guaranteed to find the correct stationary point, or any solution at all.
You can use the concept of path following if you know the locations of your 3 stationary points at some particular value of rt; for example if you know your currently supplied initial guess/bounds for
rt = rtbar - 3
, you can do
rbar=0.77;
a=6*10^-3;
b=0;
% this defines your randomized vector
et = a*linspace(-3,3,50) + b;
rt = rbar+et
u = @(ptstar) (ptstar.^(-1/9) + 2 + rt(1) .* ptstar.^(-1) - ptstar.^(-8/9)) - (2+rt(1));
ptstarMax=fzero(u,[1.1, 1e4])
ptstarMiddle=fzero(u,)
ptstarMin=fzero(u,[0.1, 0.7])
for i = 2:50
u = @(ptstar) (ptstar.^(-1/9) + 2 + rt(i) .* ptstar.^(-1) - ptstar.^(-8/9)) - (2+rt(i));
ptstarMax=fzero(u,ptstarMax)
ptstarMiddle=fzero(u,ptstarMiddle)
ptstarMin=fzero(u,ptstarMin)
end

Johan Bietmann on 4 Dec 2019
Regarding the first probem thank you! The loop works now. I understand what you are doing to solve the second problem, however it doesn't seem to work. Below is the list for the 50 values of rt.
rt =
0.7715
0.7757
0.7708
0.7637
0.7638
0.7767
0.7778
0.7696
0.7697
0.7686
0.7583
0.7751
0.7705
0.7593
0.7714
0.7694
0.7712
0.7694
0.7651
0.7695
0.7577
0.7705
0.7730
0.7671
0.7714
0.7692
0.7661
0.7535
0.7698
0.7698
0.7860
0.7729
0.7579
0.7793
0.7754
0.7663
0.7726
0.7577
0.7781
0.7853
0.7722
0.7728
0.7706
0.7768
0.7665
0.7750
0.7719
0.7728
0.7708
0.7700
They are all located around 0.77. In terms of my initial guess, I am really struggling to come up with values. If for example r=0.7717, ptstarmax would be 2, ptstarmiddle 1, and ptstarMin 0.5. How should I pathfollow then?
As you mentioned this shows up as well indicating that there is no solution at all.
Exiting fzero: aborting search for an interval containing a sign change
because complex function value encountered during search.
(Function value at -0.122801 is 0.09018+1.7745i.)
Check function or try again with a different starting value.
This error shows up right now:
Error using fzero (line 230)
Second argument must be finite.
Error in try2 (line 18)
ptstarMin=fzero(u,ptstarMin)
Currently my script looks like this:
rbar=0.77;
a=6*10^-3;
b=0;
et=a.*randn(50,1)+b;
rt = rbar+et;
u = @(ptstar) (ptstar.^(-1/9) + 2 + rt(1) .* ptstar.^(-1) - ptstar.^(-8/9)) - (2+rt(1));
ptstarMax=fzero(u,[1.1, 1e4])
ptstarMiddle=fzero(u,[0.7, 1.2])
ptstarMin=fzero(u,[0.1, 0.7])
for i = 2:50
u = @(ptstar) (ptstar.^(-1/9) + 2 + rt(i) .* ptstar.^(-1) - ptstar.^(-8/9)) - (2+rt(i));
ptstarMax=fzero(u,ptstarMax)
ptstarMiddle=fzero(u,ptstarMiddle)
ptstarMin=fzero(u,ptstarMin)
end
J. Alex Lee on 4 Dec 2019
Path following won't work if you skip around randomly on the parameter rt. The concept is that you know the solutions at some value of rt, so if you ever so slightly move the value of rt, the solutions should be very close to the original solutions. And so using the old solution as the initial guess for the new solution should work as long as you changed the value of rt by a sufficiently small amount. The trick is "how small", and that depends problem-to-problem.
If you know the solutions at rt=0.7717, your loop should start with that value and then "gradually" go up or down, and then you may have to go the opposite way depending on what span of values of rt you want to solve your problem for.