I want to solve a equation in MATLAB with fsolve
I'm trying to do that:
function F = root2d(P);
lambda = 2*10^-4;
th = -40:-1:-106;
PL1 = 10471285.480509; % (mw)
p1 = 10;
p2 = 6 ;
p3 = 8 ;
al = 2.5;
T = 10.^(th./10);
r = (p1*PL1^(-1)./T).^(1/al);
R = (p2*PL1^(-1)./T).^(1/al);
syms P
c = (lambda.*pi.*(R.^2));
j = 1:3;
D = zeros(3,67);
for k = 1:numel(j)
F(1) = (prod(D(k,:)==exp(P(1).*c.*(log(P(1)).^k/factorial(k))))).*exp(-(lambda*P(1).*pi.*(r.^2)))-P;
end
fun = #root2d;
P0 = 0;
P = fsolve(fun,P0)
Do you have an idea?
There are a couple of problems in this code. I will help you with the most tricky.
It is identified using rubberduck debugging. Let me exemplify it by explaining your code to you.
Starting from the top you define a function called root2d, which returns some object F, then in this function you define alot of constants. With these cosntants defined, you can define your symbolic function F, which we earlier saw was the output of the function. Continuing in this function, root2d, you now create a function handle fun to root2d, and then in the last line you call fsolve to solve fun.
Did you see the error?
fsolve calls fun which is a function handle to root2d. Thus fsolve calls root2d. Running root2d MATLAB comes across a new fsolve which calls root2d. I.e. root2d will be pushed unto the stack over and over again.
This is solved by taking the last three lines out of the function, and then running them from another script or from the terminal.
Doing so results in a new error:
Unable to perform assignment because the indices on the left side are
not compatible with the size of the right side.
Error in sym/privsubsasgn (line 1085)
L_tilde2 = builtin('subsasgn',L_tilde,struct('type','()','subs',{varargin}),R_tilde);
Error in sym/subsasgn (line 922)
C = privsubsasgn(L,R,inds{:});
Error in SO (line 18)
F(1) = (prod(D(k,:)==exp(P(1).*c.*(log(P(1)).^k/factorial(k))))).*exp(-(lambda*P(1).*pi.*(r.^2)))-P;
Error in fsolve (line 242)
fuser = feval(funfcn{3},x,varargin{:});
Caused by:
Failure in initial objective function evaluation. FSOLVE cannot
continue.
I.e. you have to ensure that your objective function, F(1) =... is correctly written.
Related
I have written a simple optimization code using genetic algorithm.I don't know why I get error during running the code.Here is my code:
f = #(x1,x2) 1-x1.^2+(x1-x2).^2;
A = [1 1;-1 2;2 1];
b =[2 2 3]' ;
Aeq = [];
beq = [];
Lb = [0 0]';
Ub = [];
[Xopt,Fval] = ga(f,2,A,b,Aeq,beq,Lb,Ub)
I don not know why matlab gives me error.I wrote this programm based on the "Genetic algorithm Documentation" bit still gives me error:
Error using #(x1,x2)1-x1.^2+(x1-x2).^2
Not enough input arguments.
Error in createAnonymousFcn>#(x)fcn(x,FcnArgs{:}) (line 11)
fcn_handle = #(x) fcn(x,FcnArgs{:});
Error in makeState (line 48)
firstMemberScore = FitnessFcn(state.Population(initScoreProvided+1,:));
Error in galincon (line 18)
state = makeState(GenomeLength,FitnessFcn,Iterate,output.problemtype,options);
Error in ga (line 351)
[x,fval,exitFlag,output,population,scores] = galincon(FitnessFcn,nvars, ...
Caused by:
Failure in initial user-supplied fitness function evaluation. GA cannot continue
Objective functions of all optimization methods in MATLAB only accept 1 argument. According to ga documents:
fun — Objective function
Objective
function, specified as a function handle or function name. Write the
objective function to accept a row vector of length nvars and return a
scalar value.
When the 'UseVectorized' option is true, write fun to accept a
pop-by-nvars matrix, where pop is the current population size. In this
case, fun returns a vector the same length as pop containing the
fitness function values. Ensure that fun does not assume any
particular size for pop, since ga can pass a single member of a
population even in a vectorized calculation.
Change you objective function and it should work:
f = #(x) 1-x(1).^2+(x(1)-x(2)).^2;
I am using MATLAB and I want to find the root of an equation F(x)-u=0. Here u=0.2861 and
F=normcdf(sqrt(lambda/t)*(t/mu-1))+exp(2*lambda/mu)*normcdf(-sqrt(lambda/t)*(t/mu+1)).
The value of lambda and mu are both 1.
I typed the following code
[x,fval] = fzero(#(t) normcdf(sqrt(lambda/t)*(t/mu-1))+exp(2*lambda/mu)*normcdf(-sqrt(lambda/t)*(t/mu+1))-u, 10);
and hope this can help me find the root. I can show mathematically that this equation has unique root. However, I keep on getting the following error
Error using erfc Input must be real and full.
Error in normcdf>localnormcdf (line 128) p(todo) = 0.5 * erfc(-z ./
sqrt(2));
Error in normcdf (line 50) [varargout{1:max(1,nargout)}] =
localnormcdf(uflag,x,varargin{:});
Error in
Test>#(t)normcdf(sqrt(lambda/t)*(t/mu-1))+exp(2*lambda/mu)*normcdf(-sqrt(lambda/t)*(t/mu+1))-u
Error in fzero (line 363)
a = x - dx; fa = FunFcn(a,varargin{:});
Then I did a "brutal force" method.
t = [0:0.001:20];
F = normcdf(sqrt(lambda./t).*(t/mu-1))+exp(2*lambda/mu).*normcdf(-sqrt(lambda./t).*(t/mu+1))-u;
plot(t,F)
I can clearly eyeball that F(t)-u is increasing in t and the root is around 0.4. My question is why fzero does not work in this case and is there a way to make fzero work?
The problem is that the function does not change sign, which is required as the docs say:
x = fzero(fun,x0) tries to find a point x where fun(x) = 0. This
solution is where fun(x) changes sign — fzero cannot find a root of a
function such as x^2.
I broke up your code to make it a bit clearer (at least for me).
lambda = 1;
mu = 1;
u = 1;
% break up function code
arg1 = #(t) +sqrt(lambda./t).*(t./mu-1);
arg2 = #(t) -sqrt(lambda./t).*(t./mu+1);
fnc = #(t) normcdf(arg1(t))+exp(2*lambda/mu).*normcdf(arg2(t))-u;
% call fzero to find the root
% [x,fval] = fzero(fnc, 10);
% plot
x = 0:0.01:10;
plot(x,fnc(x))
The function is not defined for any input t < 0 due to the sqrt in my function handle arg. So if you plot it for values t > 0, you see that it never passes zero.
EDITED: sign mix-up in the arguments. Thx flxx for pointing this out. Plot & code updated. The argument still holds.
I am trying to link SimEvent and the optimization module of MATLAB. For that, I first need to define a function that runs the simulation then call it in an optimization function. I got the idea of the simulation/optimization code from the link below:
http://au.mathworks.com/videos/optimizing-manufacturing-production-processes-68961.html
I tried to go through all the code I see in this video but, when I am applying it, it is not working. Here is my code:
function finalresults = SimOpt ()
intcon = [1];
A=[];
b=[];
Aeq=[];
beq = [];
lb = [1];
ub= [10];
finalresults= intlinprog(#f,intcon,A,b,Aeq,beq,lb,ub);
function obj = f(vecX)
NumServers = vecX(1);
NumTruck = vecX(2);
set_param('concreting10/Positioning and Unloading','NumberOfServers',num2str(NumServers));
set_param('concreting10/Washing','NumberOfServers',num2str(NumTruck));
simOut = sim('concreting10','SaveOutput','on','OutputSaveName','WaitingTimeInQueue');
z = simOut.get('WaitingTimeInQueue');
waiting = max(z);
cost = [100 200]*vecX';
obj = waiting*1000+cost;
end
end
When I run the whole code I get this warning:
Error using intlinprog (line 122) INTLINPROG requires the following inputs to be of data type double: 'f'.
Error in SimOpt (line 26) finalresults= intlinprog(#f,intcon,A,b,Aeq,beq,lb,ub);
Any help will be appreciated.
Change the last line in the function to
obj = waiting * 1000.0 + cost
MATLAB and many other HLLs convert data type to integer if multiplied by an integer type constant value. So it is necessary to multiply the constant as double type by adding a decimal point.
I have some code here which illustrates the nested nature of some integrals that I want to perform in matlab. When I run the following code I get the error
Error using .*
Matrix dimensions must agree.
Error in fun1/integrand (line 7)
f = x.^2.*t;
it seems that the way I have set it up now does not allow for vectorized output of the integral function. What can I do to make my code run? I have commented below what I want the functions to do.
My code is as follows:
%Main script:
z = linspace(0,10,10);
I = zeros(10,1);
for i = 1:10
I(i) = fun2(z(i));
end
%Function 1 in separate file:
function I = fun1(x)
I = integral(#integrand,-1,1);
function f = integrand(t)
f = x.^2.*t;
end
end
%Function 2 in separate file:
function I = fun2(z)
I = integral2(#integrand,-1,1,-1,1);
function f = integrand(x,y)
f = z.*fun1(x).*y; // here fun1 should return the value for all x that is swept through by integral2 during its call.
end
end
The problem with your code is you are using integral2 and integral1 in a combination. This way integral2 generates a grid for x and y and integral1 generates the t values. This way the t and x values don't match in size, and even if they would they are part of a different grid.
As already discussed, using ingetral3 is the right choice. Alternatively you could simply "fix" this introducing a loop, but this results in much slower code:
function I = fun1(x)
I=nan(size(x));
for ix=1:numel(x)
I(ix) = integral(#(t)integrand(x(ix),t),-1,1);
end
function f = integrand(x,t)
f = x.^2.*t;
end
end
I want to solve two nonlinear equations in MATLAB so i did the following:
part of my script
c=[A\u;A\v];
% parts of code are omitted.
x0=[1;1];
sol= fsolve(#myfunc,x0);
the myfunc function is as follows
function F = myfunc(x)
F=[ x(1)*c(1)+x(2)*c(2)+x(1)*x(2)*c(3)+c(4)-ii;
x(1)*c(5)+x(2)*c(6)+x(1)*x(2)*c(7)+c(8)-jj];
end
i have two unknowns x(1) and x(2)
my question is How to pass a values(c,ii,jj) to myfunc in every time i call it?
or how to overcome this error Undefined function or method 'c' for input arguments of type 'double'.
thanks
Edit: The previous answer was bogus and not contributing at all. Hence has been deleted. Here is the right way.
In your main code create a vector of the coefficients c,ii,jj and a dummy function handle f_d
coeffs = [c,ii,jj];
f_d = #(x0) myfunc(x0,coeffs); % f_d considers x0 as variables
sol = fsolve(f_d,x0);
Make your function myfunc capable of taking in 2 variables, x0 and coeffs
function F = myfunc(x, coeffs)
c = coeffs(1:end-2);
ii = coeffs(end-1);
jj = coeffs(end);
F(1) = x(1)*c(1)+x(2)*c(2)+x(1)*x(2)*c(3)+c(4)-ii;
F(2) = x(1)*c(5)+x(2)*c(6)+x(1)*x(2)*c(7)+c(8)-jj;
I think that should solve for x0(1) and x0(2).
Edit: Thank you Eitan_T. Changes have been made above.
There is an alternative option, that I prefer, if a function handle is not what you are looking for.
Say I have this function:
function y = i_have_a_root( x, a )
y = a*x^2;
end
You can pass in your initial guess for x and a value for a by just calling fsolve like so:
a = 5;
x0 = 0;
root = fsolve('i_have_a_root',x0,[],a);
Note: The [] is reserved for fsolve options, which you probably want to use. See the second call to fsolve in the documentation here for information on the options argument.