MATLAB: sym function does not works - matlab

In matlab I want to create symbolic vector:
X = sym(['x_n' 'x_(n-1)' 'x(n-2)'])
however, I get
??? Error using ==> sym.sym>expression2ref at 2408
Error: Unexpected 'identifier' [line 1, col 11]
Error in ==> sym.sym>char2ref at 2378
s = expression2ref(x);
Error in ==> sym.sym>tomupad at 2147
S = char2ref(x);
Error in ==> sym.sym>sym.sym at 102
S.s = tomupad(x,'');
if I try create, e.g. just X = sym(['x_n' 'x_(n-1)']), it's ok, so what's wrong?

If you want to create a symbolic vector (or matrix) you just need one set of quotes around the square brackets:
X = sym('[x_(n) x_(n-1) x_(n-2)]')
Or
X = sym('[x_(n);x_(n-1);x_(n-2)]')
I'm assuming that you had typos in the first and third element of the vector and desire to define x_ as a function of n (if not, see below). However, this often isn't the most flexible way of building symbolic arrays. I'd use the syms function instead of sym and avoid building strings (though sometimes creating large vector/matrix equations systematically with strings can be easier):
syms x_(n)
X = [x_(n) x_(n-1) x_(n-2)]
Lastly, as the help for sym indicates, one can also automatically create vectors and matrices of enumerated variables, e.g.:
X = sym('x_',[1 3])
If you don't actually want to specify a vector of functions, then this option is very convenient.

Related

How can we put element of vector to symsum?

I am trying to use symsum using Matlab. But I get a strange error.
I am trying to put elements of a vector into symsum:
a=[1,2,3,40,51,61];
syms u n
S1(u) = symsum((a(n+1)*(-u)^n)/factorial(n),n,[0,6])
Error is:
Invalid indexing or function definition. When defining a function, ensure that the arguments are symbolic variables and the body of the function is a SYM expression. When indexing, the input must be numeric, logical, or ':'.
First, I can see a mistake where you write a(n+1), for n going from 0 to 6. When n equals 6, you will have a(7) which doesn't exist. a only has 6 elements.
Then, you have another problem because you are indexing a with a symbol, and symbolic indexing is not allowed (see this post).
Does n really need to be a symbol and do you really need to use symsum? If not, you can try:
a = [1,2,3,40,51,61];
n = 0:5;
syms u
S1(u) = sum( sym( (a(n+1).*(-u).^n)./factorial(n) ) )
This returns:
S1(u) =
- (61*u^5)/120 + (17*u^4)/8 - (20*u^3)/3 + (3*u^2)/2 - 2*u + 1

Using `lsqnonlin` with vector inputs

I have a question about using the lsqnonlin function.
In my case I have two functions:
f_1=#(t,x)sin(t+x.^2);
f_2=#(t,x)cos(x.^2)+3.*t.^2;
f = {f_1, f_2};
I want to find the values of the arguments t and x which would result in the least square error, defined as: f_1(t,x)^2+f_2(t,x)^2. In other words, argmin for LSE.
My code is as follow with initial guess [1,2]:
lsqnonlin(f,[1,2])
And I'm getting the error:
Error in lsqnonlin (line 196)
initVals.F = feval(funfcn{3},xCurrent,varargin{:});
Caused by:
Failure in initial objective function evaluation. LSQNONLIN cannot continue.
lsqnonlin can be used for vector function and vector input according to the documentation. I wonder how to prepare corresponding codes for it. Could anyone suggest the solution?
You are getting an error because lsqnonlin expects a scalar function handle that maps a vector to a vector, whereas you specify a cell array of function handles. To fix this, instead of a vector of functions outputting one scalar each, you need to rewrite it into a single function that accepts a vector of inputs and also outputs a vector:
f = #(xt)[sin(xt(2)+xt(1).^2), cos(xt(1).^2)+3.*xt(2).^2];
% xt = [x,t]
% f = [f_1(xt), f_2(xt)]
so f and xt are both vectors of 2 elements.
Then, the solver works:
lsqnonlin(f,[1,2])
ans =
1.6144 0.5354

matlab Dimensions of matrices being concatenated are not consistent

here is my code:
C=#(k) [k,k,2.*k;3,2.*k,5;1,k,k];
AV=#(k,t) [3*t, 6, 9]*C(k)*[3*t ;6 ;9];
avaint=#(k,a,b) quadgk(#(k) AV(k,t),a,b);
AVAR=#(t) avaint(t,0,87600);
Is shows:
Error using vertcat
Dimensions of matrices being concatenated are not consistent.
when I want to print AVAR(3)
Source of Error
The quadgk function passes a vector of integration points to the function handle given to it.
From the documentation:
The function y = fun(x) should accept a vector argument x and return a vector result y, where y is the integrand evaluated at each element of x.
This creates the dimension mismatch causing the error.
Solutions
To get around this implementation, you can perform the numerical integration using the integral function with the ('ArrayValued',true) option pair:
avaint = #(t,a,b) integral(#(k) AV(k,t),a,b,'ArrayValued',true);
Or, you can use arrayfun within AV to abide by the requirement of quadgk:
AV = #(k,t) arrayfun(#(k_el) [3*t, 6, 9]*(C(k_el)*[3*t ;6 ;9]),k);

Evaluate Matlab symbolic function

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.

Octave fminsearch: Problems with minimization and options

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