Symbolic diff in matlab should return vector - matlab

If I have a symbolic function p(r,s) = r^3 in MATLAB, I obtain the derivatives dp/dr = 3r^2 and dp/ds = 0, but my goal is to use matlabFunction to convert these expressions to function handles, with vector inputs (r,s). I want something similar to zeros(size(s)), for the derivative dp/ds so I don't obtain a scalar output if my input (r,s) is a vector.
This code I tried:
syms r s
p = r^3
dpds = diff(p,s)
gives a scalar zero not variable size zero, i.e scalar output if we have vector input.

This is the nature of how matlabFunction works. If you provide an equation that has no independent variables as part of the equation, it will default to giving you an anonymous function with no inputs and give you a scalar result.
For example:
>> syms r s;
>> p = r^3;
>> dpds = diff(p,s);
>> dpdsFunc = matlabFunction(dpds)
dpdsFunc =
#()0.0
This will only give you a single scalar value each time. This also applies to any scalar function that gives a non-zero output. If you'd like to override this behaviour and give a variable length of this scalar that is dependent on the length of the input, you can first detect if there are any input variables in the function by checking how many variables there are. You can use symvar for that. You would check if this array has a length of 0, and if it does, you override the function.
Something like this comes to mind:
syms r s;
p = r^3;
dpds = diff(p,s);
if numel(symvar(dpds)) == 0
dpdsFunc = #(s) ones(size(s))*double(dpds); %// Thanks Daniel!
else
dpdsFunc = matlabFunction(dpds);
end
This should achieve what you want.
Minor Note
I actually think this variable length of zeroes business is something that should be put into MATLAB by default, rather than defaulting to a single value. It makes vectorizing code a lot easier. I'm tempted to submit a feature request to MathWorks in the future.

Related

Matlab: Detect number of input arguments for function handle from outside of the function

I begin with a symbolic function of one variable, calculate the symbolic derivatives of orders 1 through N, and then convert those symbolic functions into function handles and store the function handles in a cell array. I then evaluate each function handle at the same input value using a loop. The problem I have is that it is possible for one of the derivatives to be a constant (with higher order derivatives being zero, of course). As I was trying to give each function handle an input, I face the "Too many input arguments" error. I would like to be able to check, in advance, whether the function handle is a constant so I can avoid the error, but I can't figure out how to do that.
In case a small working example is helpful, I provide the following
symVar = sym('symVar');
startFunc = symVar^4 + symVar^3 + symVar^2;
derivesCell = cell(5);
for J=1:5
derivesCell(J) = {matlabFunction(diff(startFunc,symVar,J))};
end
cumSum = 0;
evalPoint = 2;
for J=1:5
cumSum = cumSum + derivesCell{J}(evalPoint);
end
Execution produces "Error using symengine>#()2.4e1
Too many input arguments."
tl;dr: You can do this with nargin:
>> nargin(derivesCell{5})
ans =
0
>> nargin(derivesCell{3})
ans =
1
Explanation:
Most people are familiar with the use of nargin as a "special variable" inside the function, but it can be used outside the context of a function definition, as a function that takes a function_handle argument, returning the number of input arguments that function handle takes. From the documentation:
NARGIN(FUN) returns the number of declared inputs for the
M-file function FUN. The number of arguments is negative if the
function has a variable number of input arguments. FUN can be
a function handle that maps to a specific function, or a string
containing the name of that function.

fminsearch with vector inputs

I want to minimize this function:
function [GCV2]=GCV(y,x,k)
[n, p]=size(x);
A=(x'*x+k*eye(p));
A=A\x';
A=x*A;
I_mat=eye(n);
num2=(I_mat-A);
num2=num2*y;
num2=norm(num2);
num2=num2^2;
num2=num2/n;
%(norm((I_mat-A)*y)^2)/n;
den2=(I_mat-A);
den2=trace(den2);
den2=den2/n;
den2=den2^2;
GCV2=num2/den2;
end
The x and y values are 13-by-4) and 13-by-1 arrays, respectively, and these values are already defined in the Matlab workspace. I want to optimize on the k value so that the function value GCV is minimized.
The parameter being optimized as well as the output are scalar so fminsearch should be appropriate.
But I can't get it to run?
I've tried several methods, the latest being:
k_min = fminsearch(#GCV,(x;y;0));
??? k_min = fminsearch(#GCV,(x;y;0));
|
Error: Unbalanced or unexpected parenthesis or bracket.
What am I doing wrong?
Looks like you're learning about anonymous functions. fminsearch minimizes a single variable (which may be a vector). Your objective function must therefore have only one input. You have a function, GCV, that takes three inputs. Two are static and are defined in the workspace outside of the minimization, while k is the one to be minimized. To create a function with one input from GCV, you can use any anonymous function, taking care to specify which variables are parameters:
x = ...
y = ...
k0 = 0;
k_min = fminsearch(#(k)GCV(y,x,k),k0);
The second input to fminsearch is the starting parameter (i.e. k0), so specify a starting value of k. Then you can define an anonymous helper function and optimize on that:
>> % define x,y
>> GCVk = #(k) GCV(y,x,k);
>> k0 = 0;
>> k_min = fminsearch(GCVk,k0)
There is probably another way to do this, but this is one of the listed ways of passing additional parameters for the optimizer.
And since there are no bonus points for being first, how about humor. Let's have an example:
>> x=1; y=1;
>> GCVk = #(k) x+y+k; k0=0;
>> k_min = fminsearch(GCVk,k0)
Exiting: Maximum number of function evaluations has been exceeded
- increase MaxFunEvals option.
Current function value: -316912650057057490000000000.000000
k_min =
-3.1691e+26
Found it - the lowest number (minus 2) in the world! Profit?

MATLAB Function (Solving an Error)

I have one file with the following code:
function fx=ff(x)
fx=x;
I have another file with the following code:
function g = LaplaceTransform(s,N)
g = ff(x)*exp(-s*x);
a=0;
b=1;
If=0;
h=(b-a)/N;
If=If+g(a)*h/2+g(b)*h/2;
for i=1:(N-1)
If=If+g(a+h*i)*h;
end;
If
Whenever I run the second file, I get the following error:
Undefined function or variable 'x'.
What I am trying to do is integrate the function g between 0 and 1 using trapezoidal approximations. However, I am unsure how to deal with x and that is clearly causing problems as can be seen with the error.
Any help would be great. Thanks.
Looks like what you're trying to do is create a function in the variable g. That is, you want the first line to mean,
"Let g(x) be a function that is calculated like this: ff(x)*exp(-s*x)",
rather than
"calculate the value of ff(x)*exp(-s*x) and put the result in g".
Solution
You can create a subfunction for this
function result = g(x)
result = ff(x) * exp(-s * x);
end
Or you can create an anonymous function
g = #(x) ff(x) * exp(-s * x);
Then you can use g(a), g(b), etc to calculate what you want.
You can also use the TRAPZ function to perform trapezoidal numerical integration. Here is an example:
%# parameters
a = 0; b = 1;
N = 100; s = 1;
f = #(x) x;
%# integration
X = linspace(a,b,N);
Y = f(X).*exp(-s*X);
If = trapz(X,Y) %# value returned: 0.26423
%# plot
area(X,Y, 'FaceColor',[.5 .8 .9], 'EdgeColor','b', 'LineWidth',2)
grid on, set(gca, 'Layer','top', 'XLim',[a-0.5 b+0.5])
title('$\int_0^1 f(x) e^{-sx} \,dx$', 'Interpreter','latex', 'FontSize',14)
The error message here is about as self-explanatory as it gets. You aren't defining a variable called x, so when you reference it on the first line of your function, MATLAB doesn't know what to use. You need to either define it in the function before referencing it, pass it into the function, or define it somewhere further up the stack so that it will be accessible when you call LaplaceTransform.
Since you're trying to numerically integrate with respect to x, I'm guessing you want x to take on values evenly spaced on your domain [0,1]. You could accomplish this using e.g.
x = linspace(a,b,N);
EDIT: There are a couple of other problems here: first, when you define g, you need to use .* instead of * to multiply the elements in the arrays (by default MATLAB interprets multiplication as matrix multiplication). Second, your calls g(a) and g(b) are treating g as a function instead of as an array of function values. This is something that takes some getting used to in MATLAB; instead of g(a), you really want the first element of the vector g, which is given by g(1). Similarly, instead of g(b), you want the last element of g, which is given by g(length(g)) or g(end). If this doesn't make sense, I'd suggest looking at a basic MATLAB tutorial to get a handle on how vectors and functions are used.

nlfilter taking same values twice

I used nlfilter for a test function of mine as follows:
function funct
clear all;
clc;
I = rand(11,11);
ld = input('Enter the lag = ') % prompt for lag distance
A = nlfilter(I, [7 7], #dirvar);
% Subfunction
function [h] = dirvar(I)
c = (size(I)+1)/2
EW = I(c(1),c(2):end)
h = length(EW) - ld
end
end
The function works fine but it is expected that nlfilter progresses element by element, but in first two iterations the values of EW will be same 0.2089 0.4162 0.9398 0.1058. But then onwards for all iterations the next element is selected, for 3rd it is 0.4162 0.9398 0.1058 0.1920, for 4th it is 0.9398 0.1058 0.1920 0.5201 and so on. Why is it so?
This is nothing to worry about. It happens because nlfilter needs to evaluate your function to know what kind of output to create. So it uses feval once before starting to move across the image. The output from this feval call is what you see the first time.
From the nlfilter code:
% Find out what output type to make.
rows = 0:(nhood(1)-1);
cols = 0:(nhood(2)-1);
b = mkconstarray(class(feval(fun,aa(1+rows,1+cols),params{:})), 0, size(a));
% Apply fun to each neighborhood of a
f = waitbar(0,'Applying neighborhood operation...');
for i=1:ma,
for j=1:na,
x = aa(i+rows,j+cols);
b(i,j) = feval(fun,x,params{:});
end
waitbar(i/ma)
end
The 4th line call to eval is what you observe as the first output from EW, but it is not used to anything other than making the b matrix the right class. All the proper iterations happen in the for loop below. This means that the "duplicate" values you observe does not affect your final output matrix, and you need not worry.
I hope you know what the length function does? It does not give you the Euclidean length of a vector, but rather the largest dimension of a vector (so in your case, that should be 4). If you want the Euclidean length (or 2-norm), use the function norm instead. If your code does the right thing, you might want to use something like:
sz = size(I,2);
h = sz - (sz+1)/2 - ld;
In your example, this means that depending on the lag you provide, the output should be constant. Also note that you might want to put semicolons after each line in your subfunction and that using clear all as the first line of a function is useless since a function will always be executed in its own workspace (that will however clear persistent or global variables, but you don't use them in your code).

How do I make a function from a symbolic expression in MATLAB?

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}