Here is an example where fplot doesn't plot anything:
a=0.336;
Ta=9.476;
Te=1.208;
Tw=1.498;
eqh=[0.661;0.619;0.568];
ex=[-1.24;-1.346;-1.441];
en=-ex;
ey=[0.376;0.705;0.968];
eqx=[-0.309;-0.357;-0.392];
eh=[1.594;1.583;1.545];
eyqh=[0.642;0.78;0.897];
a0=a*Ta*Te^2;
syms bt Td Ki Kp;
a1=sym([]);a2=sym([]);a3=sym([]);a4=sym([]);exqh=sym([]);
for i=1:3
Kp=1/bt;
exqh(i)=en(i)*eqh(i)+eqx(i)*eh(i);
Ki=1/(bt*Td);
a1(i)=Ta*Tw*eqh(i)+a*Te^2*en(i)+a*Te^2*ey(i)*Kp;
a2(i)=a*Te^2*ey(i)*Ki+Ta+Tw*exqh(i)-eyqh(i)*Kp*Tw;
a3(i)=en(i)+ey(i)*Kp-eyqh(i)*Ki*Tw;
a4(i)=ey(i)*Ki;
assume(bt~=0)
f=#(bt) a1(i)
fplot(f,[0.01 1],'b')
hold on
end
And here is another example, where fplot works:
syms y x;
y=#(x) 2/x+6;
z=y;
assume(x~=0)
fplot(z,[-1 1],'b')
I cannot understand the difference between these two cases. In my opinion, they are the same.
Would anyone please explain why the top example doesn't work, but the bottom one does?
fplot requires an expression that returns a numeric value. f returns a sym (symbolic expression), so it doesn't work, whereas z returns a number - so it does. That's all the difference.
Note that in the working example, you overwrote the y sym on the 2nd row, which means you provided a "proper" function handle to fplot, "by mistake". In fact, you need much less code for that example to work:
fplot( #(x)2./x+6, [-1 1], 'b');
The easiest way to get the top code working is by using matlabFunction. In other words, you can fix your code by changing this line:
f=#(bt) a1(i)
to this:
f = matlabFunction(a1(i));
Related
Having such a function:
y=1.2*sin(x)+2*log(x+2)-5; I am looking for zeros of that function using fzero() functon- just for testing, I indicate other methods.
I received error and I am looking for the solution of that. fzero() is for nonlinear functions but for complex ones...? Doyou know similar method to fzero()?
The function in the example has a pole, but you can treat this case by looking at it's real part, get the zero and check it to see the imaginary part is zero:
syms x y yr
yr= #(x) real(1.2*sin(x)+2*log(x+2)-5);
fr=fzero(yr,0);
fr =
6.8458
y= #(x) (1.2*sin(x)+2*log(x+2)-5);
y(fr)
ans =
-8.8818e-16
Why does the error message of this code return: "Subscript indices must either be real positive integers or logicals.", when I am using ceil for every subscript?
A=1:1:100;
B=1:1:100;
C=1;
D=1:1:100;
E=2;
F=1:1:100;
G=1:1:100;
H=0.1:0.1:10;
fun_1=#(t)integral(#(ti)G(ceil(ti)).*H(ceil(t-ti)),0.1,t-1);
fun_2=#(t)integral(#(ti)G(ceil(ti)).*B(ceil(ti)).*(C.*D(t).^E)./F(t).*...
exp(-integral(#(x)(C.*D(ceil(x)).^E)./F(ceil(x)),ti,5)-K.*(t-ti)),0.1,t-
1,'ArrayValued',true);
I=500;
J=1000;
K=2;
fun_3=#(t)I*integral(#(ti)min(fun_2(ceil(ti)),J).*exp(-(K+I).*(t-ti)),0.1,t-
1);
t=1:1:5;
figure(1)
fplot(fun_1,t);
figure(2)
fplot(fun_2,t);
figure(3)
fplot(fun_3,t);
fplot see documentation Called as fplot(f,xinterval) evaluates your function handle f over the interval xinterval. IT will evaluate f at automatically determined steps along that given interval.
From the docs:
xinterval — Interval for x [–5 5] (default) | two-element vector of
form [xmin xmax]
You seem to be trying to specify exactly where you want your functions evaluated
t=1:1:5;
...
fplot(fun_1,t);
But it doesn't work that way. What is happening is that fplot is evaluating the function from 1 to 2 (the first 2 elements of t). So for example it might feed values of t = 1, 1.05, 1.1,... ,2 into your fun_# functions.
You can tell this because you first function which does work actually plots over the x-range of 1 to 2.
The reason you are getting a subscript indices error is because in fun_2 you have this ...(C.*D(t).^E)./F(t).*... Since fplot is feeding in values for t which are spaced between 1 and 2 (ex. 1.1) that is not a valid index.
If you really just want the values of your functions at t = 1:1:5 The you probably do not want to use fplot and just want evaluate the functions at those times and plot it.
y = feval(fun_1,t);
plot(t,y)
EDIT: The above code doesn't work
You will need to do something like the code below. This is because the 2nd & 3rd trems to the intergral function need to be scalar (1x1). If you feed them an array for t then they crash. So evaluate at each t not all at once.
figure(1)
y_1 = arrayfun(fun_1,t);
plot(t,y_1);
figure(2)
y_2 = arrayfun(fun_2,t);
plot(t,y_2);
figure(3)
y_3 = arrayfun(fun_3,t);
plot(t,y_3);
Note: the Third function still errors ... and I'm not 100% sure why. I didn't really look at it.
I have a problem with symbolic functions. I am creating function of my own whose first argument is a string. Then I am converting that string to symbolic function:
f = syms(func)
Lets say my string is sin(x). So now I want to calculate it using subs.
a = subs(f, 1)
The result is sin(1) instead of number.
For 0 it works and calculates correctly. What should I do to get the actual result, not only sin(1) or sin(2), etc.?
You can use also use eval() to evaluate the function that you get by subs() function
f=sin(x);
a=eval(subs(f,1));
disp(a);
a =
0.8415
syms x
f = sin(x) ;
then if you want to assign a value to x , e.g. pi/2 you can do the following:
subs(f,x,pi/2)
ans =
1
You can evaluate functions efficiently by using matlabFunction.
syms s t
x =[ 2 - 5*t - 2*s, 9*s + 12*t - 5, 7*s + 2*t - 1];
x=matlabFunction(x);
then you can type x in the command window and make sure that the following appears:
x
x =
#(s,t)[s.*-2.0-t.*5.0+2.0,s.*9.0+t.*1.2e1-5.0,s.*7.0+t.*2.0-1.0]
you can see that your function is now defined by s and t. You can call this function by writing x(1,2) where s=1 and t=1. It should generate a value for you.
Here are some things to consider: I don't know which is more accurate between this method and subs. The precision of different methods can vary. I don't know which would run faster if you were trying to generate enormous matrices. If you are not doing serious research or coding for speed then these things probably do not matter.
I am trying to use Octave's fminsearch function, which I have used in MATLAB before. The function seems not sufficiently documented (for me at least), and I have no idea how to set to options such that it would actually minimize.
I tried fitting a very simple exponential function using the code at the end of this message. I want the following:
I want the function to take as input the x- and y-values, just like MATLAB would do. Furthermore, I want some control over the options, to make sure that it actually minimizes (i.e. to a minimum!).
Of course, in the end I want to fit functions that are more complicated than exponential, but I want to be able to fit exponentials at least.
I have several problems with fminsearch:
I tried handing over the x- and y-value to the function, but a matlab-style thing like this:
[xx,fval]=fminsearch(#exponential,[1000 1],x,y);
or
[xx,fval]=fminsearch(#exponential,[33000 1],options,x,y)
produces errors:
error: options(6) does not correspond to known algorithm
error: called from:
error: /opt/local/share/octave/packages/optim-1.0.6/fmins.m at line 72, column 16
error: /opt/local/share/octave/packages/optim-1.0.6/fminsearch.m at line 29, column 4
Or, respectively (for the second case above):
error: `x' undefined near line 4 column 3
error: called from:
error: /Users/paul/exponential.m at line 4, column 2
error: /opt/local/share/octave/packages/optim-1.0.6/nmsmax.m at line 63, column 6
error: /opt/local/share/octave/packages/optim-1.0.6/fmins.m at line 77, column 9
error: /opt/local/share/octave/packages/optim-1.0.6/fminsearch.m at line 29, column 4
Apparently, the order of arguments that fminsearch takes is different from the one in MATLAB. So, how is this order??
How can I make fminsearch take values and options?
I found a workaround to the problem that the function would not take values: I defined the x- and y values as global. Not elegant, but at least then the values are available in the function.
Nonetheless, fminsearch does not minimize properly.
This is shown below:
Here is the function:
function f=exponential(coeff)
global x
global y
X=x;
Y=y;
a= coeff(1);
b= coeff(2);
Y_fun = a .* exp(-X.*b);
DIFF = Y_fun - Y;
SQ_DIFF = DIFF.^2;
f=sum(SQ_DIFF);
end
Here is the code:
global x
global y
x=[0:1:200];
y=4930*exp(-0.0454*x);
options(10)=10000000;
[cc,fval]=fminsearch(#exponential,[5000 0.01])
This is the output:
cc =
4930.0 5184.6
fval = 2.5571e+08
Why does fminsearch not find the solution?
There is an fminsearch implementation in the octave-forge package "optim".
You can see in its implementation file that the third parameter is always an options vector, the fourth is always a grad vector, so your ,x,y invocations will not work.
You can also see in the implementation that it calls an fmins implementation.
The documentation of that fmins implementation states:
if options(6)==0 && options(5)==0 - regular simplex
if options(6)==0 && options(5)==1 - right-angled simplex
Comment: the default is set to "right-angled simplex".
this works better for me on a broad range of problems,
although the default in nmsmax is "regular simplex"
A recent problem of mine would solve fine with matlab's fminsearch, but not with this octave-forge implementation. I had to specify an options vector [0 1e-3 0 0 0 0] to have it use a regular simplex instead of a 'right-angled simplex'. The octave default makes no sense if your coefficients differ vastly in scale.
The optimization function fminsearch will always try to find a minimum, no matter what the options are. So if you are finding it's not finding a minimum, it's because it failed to do so.
From the code you provide, I cannot determine what goes wrong. The solution with the globals should work, and indeed does work over here, so something else on your side must be going awry. (NOTE: I do use MATLAB, not Octave, so those two functions could be slightly different...)
Anyway, why not do it like this?
function f = exponential(coeff)
x = 0:1:200;
y = 4930*exp(-0.0454*x);
a = coeff(1);
b = coeff(2);
Y_fun = a .* exp(-x.*b);
f = sum((Y_fun-y).^2);
end
Or, if you must pass x and y as external parameters,
x = [0:1:200];
y = 4930*exp(-0.0454*x);
[cc,fval] = fminsearch(#(c)exponential(c,x,y),[5000 0.01])
function f = exponential(coeff,x,y)
a = coeff(1);
b = coeff(2);
Y_fun = a .* exp(-x.*b);
f = sum((Y_fun-y).^2);
end
How can I make a function from a symbolic expression? For example, I have the following:
syms beta
n1,n2,m,aa= Constants
u = sqrt(n2-beta^2);
w = sqrt(beta^2-n1);
a = tan(u)/w+tanh(w)/u;
b = tanh(u)/w;
f = (a+b)*cos(aa*u+m*pi)+a-b*sin(aa*u+m*pi); %# The main expression
If I want to use f in a special program to find its zeroes, how can I convert f to a function? Or, what should I do to find the zeroes of f and such nested expressions?
You have a couple of options...
Option #1: Automatically generate a function
If you have version 4.9 (R2007b+) or later of the Symbolic Toolbox you can convert a symbolic expression to an anonymous function or a function M-file using the matlabFunction function. An example from the documentation:
>> syms x y
>> r = sqrt(x^2 + y^2);
>> ht = matlabFunction(sin(r)/r)
ht =
#(x,y)sin(sqrt(x.^2+y.^2)).*1./sqrt(x.^2+y.^2)
Option #2: Generate a function by hand
Since you've already written a set of symbolic equations, you can simply cut and paste part of that code into a function. Here's what your above example would look like:
function output = f(beta,n1,n2,m,aa)
u = sqrt(n2-beta.^2);
w = sqrt(beta.^2-n1);
a = tan(u)./w+tanh(w)./u;
b = tanh(u)./w;
output = (a+b).*cos(aa.*u+m.*pi)+(a-b).*sin(aa.*u+m.*pi);
end
When calling this function f you have to input the values of beta and the 4 constants and it will return the result of evaluating your main expression.
NOTE: Since you also mentioned wanting to find zeroes of f, you could try using the SOLVE function on your symbolic equation:
zeroValues = solve(f,'beta');
Someone has tagged this question with Matlab so I'll assume that you are concerned with solving the equation with Matlab. If you have a copy of the Matlab Symbolic toolbox you should be able to solve it directly as a previous respondent has suggested.
If not, then I suggest you write a Matlab m-file to evaluate your function f(). The pseudo-code you're already written will translate almost directly into lines of Matlab. As I read it your function f() is a function only of the variable beta since you indicate that n1,n2,m and a are all constants. I suggest that you plot the values of f(beta) for a range of values. The graph will indicate where the 0s of the function are and you can easily code up a bisection or similar algorithm to give you their values to your desired degree of accuracy.
If you broad intention is to have numeric values of certain symbolic expressions you have, for example, you have a larger program that generates symbolic expressions and you want to use these expression for numeric purposes, you can simply evaluate them using 'eval'. If their parameters have numeric values in the workspace, just use eval on your expression. For example,
syms beta
%n1,n2,m,aa= Constants
% values to exemplify
n1 = 1; n2 = 3; m = 1; aa = 5;
u = sqrt(n2-beta^2);
w = sqrt(beta^2-n1);
a = tan(u)/w+tanh(w)/u;
b = tanh(u)/w;
f = (a+b)*cos(aa*u+m*pi)+a-b*sin(aa*u+m*pi); %# The main expression
If beta has a value
beta = 1.5;
eval(beta)
This will calculate the value of f for a particular beta. Using it as a function. This solution will suit you in the scenario of using automatically generated symbolic expressions and will be interesting for fast testing with them. If you are writing a program to find zeros, it will be enough using eval(f) when you have to evaluate the function. When using a Matlab function to find zeros using anonymous function will be better, but you can also wrap the eval(f) inside a m-file.
If you're interested with just the answer for this specific equation, Try Wolfram Alpha, which will give you answers like:
alt text http://www4c.wolframalpha.com/Calculate/MSP/MSP642199013hbefb463a9000051gi6f4heeebfa7f?MSPStoreType=image/gif&s=15
If you want to solve this type of equation programatically, you probably need to use some software packages for symbolic algebra, like SymPy for python.
quoting the official documentation:
>>> from sympy import I, solve
>>> from sympy.abc import x, y
Solve a polynomial equation:
>>> solve(x**4-1, x)
[1, -1, -I, I]
Solve a linear system:
>>> solve((x+5*y-2, -3*x+6*y-15), x, y)
{x: -3, y: 1}