Matlab - define a general variable - matlab

I want to calculate Fourier series for some function func.
I build this method:
function y = CalcFourier(accurate, func, a, b, val_x)
f = #(x) eval(func);
% calculate coefficients
a0 = (2 / (b - a)) * calcArea(func, a , b);
an = (2 / (b - a)) * calcArea(strcat(func, '*cos(2*n*pi*x / (b - a))'), a , b);
an = (2 / (b - a)) * calcArea(strcat(func, '*sin(2*n*pi*x / (b - a))'), a , b);
partial = 0;
an_f = #(n) an;
bn_f = #(n) bn;
for n = 1:accurate
partial = partial + an_f(n)* cos(2*n*pi*val_x / (b - a)) + bn_f(n) * sin(2*n*pi*val_x / (b - a));
end
y = (a0 / 2) + partial;
end
And this - to approximate the coefficient's:
function area = calcArea(func, a, b)
f = #(x) eval(func);
area = (a - b) * (f(a) - f(b)) / 2;
end
On line an = (2 / (b - a)) * calcArea(strcat(func, '*cos(2*n*pi*x / (b - a))'), a , b); I'm getting error:
??? Error using ==> eval
Undefined function or variable 'n'.
Error in ==> calcArea>#(x)eval(func) at 2
f = #(x) eval(func);
Error in ==> calcArea at 3
area = (a - b) * (f(a) - f(b)) / 2;
Error in ==> CalcFourier at 5
an = (2 / (b - a)) * calcArea(strcat(func,
'*cos(2*n*pi*x / (b - a))'), a , b);
>>
Is there any option to declate n as "some constant"? Thanks!

You try to use a variable called n in line 4 of your code. However at that time n is not defined yet, that only happens in the for loop. (Tip: Use dbstop if error at all times, that way you can spot the problem more easily).
Though I don't fully grasp what you are doing I believe you need something like this:
n=1 at the start of your CalcFourier function. Of course you can also choose to input n as a variable, or to move the corresponding line to a place where n is actually defined.
Furthermore you seem to use n in calcArea, but you don't try to pass it to the function at all.
All of this would be easier to find if you avoided the use of eval, perhaps you can try creating the function without it, and then matlab will more easily guide you to the problems in your code.

if the symbolic toolbox is available it can be used to declare symbolic variables , which can be treated as 'some variable' and substituted with a value later.
however a few changes should be made for it to be implemented, generally converting anonymous functions to symbolic functions and any function of n to symbolic functions. And finally the answer produced will need to be converted from a symbolic value to some more easy to handle value e.g. double
quickly implementing this to your code as follows;
function y = test(accurate, func, a, b, val_x)
syms n x % declare symbolic variables
%f = symfun(eval(func),x); commented out as not used
The two lines above show the declaration of symbolic variables and the syntax for creating a symbolic function
% calculate coefficients
a0 = symfun((2 / (b - a)) * calcArea(func, a , b),x);
an = symfun((2 / (b - a)) * calcArea(strcat(func, '*cos(2*n*pi*x / (b - a))'),...
... a , b),[x n]);
bn = symfun((2 / (b - a)) * calcArea(strcat(func, '*sin(2*n*pi*x / (b - a))'),...
... a , b),[x n]);
partial = 0;
the function definitions in in your code are combined into the lines above, note they functions are of x and n, the substitution of x_val is done later here...
for n = 1:accurate
partial = partial + an(val_x,n)* cos(2*n*pi*val_x / (b - a)) +...
... bn(val_x,n) * sin(2*n*pi*val_x / (b - a));
end
The for loop which now replaces the symbolic n with values and calls the symbolic functions with x_val and each n value
y = (a0 / 2) + partial;
y = double(y);
end
Finally the solution is calculated and then converted to double;
Disclaimer: I have not checked if this code generates the correct solution, however I hope it gives you enough information to understand what has been changed and why to carry out the process given in your code above, using the symbolic toolbox to address the issue...

Related

Function and its gradient in Matlab

I am working on a Matlab project and I want to make the gradient of the following function in Matlab:
f(x) = c^T * x - sum (log(bi - (ai ^ T) * x)).
Where ai^T are the rows of a random A matrix nxm , where n=2, and m=20
c is random matrix nx1, and x is also random nx1.
b is random matrix mx1.
I've done the following but the results i get don't seem to be right..
function gc0 = gc(x, c, b, A)
for k = 1 : length(A(:,1))
f1(k) = sum(log(b - A(k,:)'*x(k)));
end
gradient(-f1)
gc0 = c - gradient(f1)';
Any ideas? I'd appreciate your help, I'm newbie in Matlab..
It seems that your loop contains a mistake. Looking at the formula above,
I think that the function evaluation should be
f1 = c'*x;
for k = 1 : length(A(1,:))
f1 = f1 - log(b(k) - A(:,k)'*x)
end
A shorter and faster notation for this in Matlab is
f = c'*x - sum(log(b - A' * x)) ;
The function 'gradient' does not calculate the gradient that I think you
want: it returns the differences of matrix entries, and your function f
is a scalar.
Instead, I suggest calculating the derivatives symbolically:
Gradf = c' + sum( A'./(b - A' * x) );

How to determine the size of an input argument for a function handle

I am creating a function that takes in data (x,y,z) and an anonymous function (M) as inputs. M's inputs are data (x,y,z) and a parameter (theta).
I need to determine the dimension of the parameter theta inside FUNC
EDIT: (To add some context)
I have data that follows a known data generating process (DGP). For example, I can generate data using a linear instrumental variable DGP with 1 endogenous variable (hence theta will be dimension 1):
n = 100; q = 10;
theta0 = 1; % true param value
e = randn(n, 1); % 2nd stage error
u = randn(n, 1); % 1st stage error
z = randn(n, q); % instrument
x = z * ones(q, 1) + u; % endog variable
y = x * theta0 + e; % dependent variable
Then I want to estimate theta0 using my own variation of generalized linear methods (FUNC)
M = #(x,y,z,theta) z' * (y - x * theta); % moment condition
thetahat = FUNC(M, x, y, z); % estimate theta0
and FUNC.m is
function out = FUNC(M, x, y, z)
k = ; % (!!!) <-- this is what I need to find out!
objFunc = #(theta) M(x, y, z, theta)' * M(x, y, z, theta);
out = fminunc(objFunc, ones(1, k)); % <-- this is where its used
end
In the above example, the DGP is a linear IV model. However, I should be able to use my function for any other DGP.
Other DGPs could, for example, define M as follows:
% E.g. 1) theta is dimension 1
M=#(x,y,z,theta) z' * (y - x * theta);
% E.g. 2) theta is dimension 2
M=#(x,y,z,theta) z' * (y - (x * theta(1))^theta(2));
% E.g. 3) theta is dimension 3
M=#(x,y,z,theta) z' * (y - (theta(1) + x * theta(2))^theta(3));
The (super bad) hack that I am currently using for (!!!) is:
for ktest = [3,2,1] % the dimension of theta will never be higher than 3
try
M(x, y, z, ones(1, ktest);
k = ktest;
end
end
Since you know already what the form and requirements of your function M will be when you pass it to FUNC, it doesn't make much sense to then require FUNC to determine it based only on M. It would make much more sense to pass flag values or needed information to FUNC when you pass it M. I would write FUNC in one of two ways:
function out = FUNC(M, x, y, z, k) % Accept k as an argument
...
end
function out = FUNC(M, x, y, z, theta0) % Pass the initial guess, of the correct size
...
end
If you really want to let FUNC do the extra work, then the answer from excaza is how I would do it.
Old answer below. not really valid since the question was clarified, but I'm leaving it temporarily...
I think you have two better options here...
Make M a cell array of anonymous functions:
You could make your input M a cell array of possible anonymous functions and use the number of values in theta as the index. You would pass this M to FUNC:
M = {#(x,y,z,theta) z' * (y - x * theta), ...
#(x,y,z,theta) z' * (y - (x * theta(1))^theta(2)), ...
#(x,y,z,theta) z' * (y - (theta(1) + x * theta(2))^theta(3))};
Then somewhere inside FUNC:
out = M{numel(theta)}(x, y, z, theta);
Make M a normal function instead of an anonymous one:
An anonymous function is good for quick, simple formulas. Add in conditional logic and you should probably just make it a fully-fledged function. Here's an example with a switch statement (good for if you have a number of different formulas):
function out = M(x, y, x, theta)
switch numel(theta)
case 1
out = z' * (y - x * theta);
case 2
out = z' * (y - (x * theta(1))^theta(2));
case 3
out = z' * (y - (theta(1) + x * theta(2))^theta(3));
end
end
And here's an example that sets some defaults for parameters (good for if you have one formula with different ways to set its parameters, like you seem to have):
function out = M(x, y, x, theta)
switch numel(theta)
case 1
p1 = 0;
p2 = theta;
p3 = 1;
case 2
p1 = 0;
p2 = theta(1);
p3 = theta(2);
case 3
p1 = theta(1);
p2 = theta(2);
p3 = theta(3);
end
out = z' * (y - (p1 + x * p2)^p3);
end
MATLAB doesn't store any information about the size of the inputs to an anonymous function. While a better idea would be to modify your code so you don't have to do these kinds of gymnastics, if your function definition is known to fit a narrow band of possibilities you could use a regular expression to parse the function definition itself. You can get this string from the return of functions.
For example:
function [nelements] = findsizetheta(fh)
defstr = func2str(fh);
test = regexp(defstr, 'theta\((\d+)\)', 'tokens');
if isempty(test)
% Assume we have theta instead of theta(1)
nelements = 1;
else
nelements = max(str2double([test{:}]));
end
end
Which returns 1, 2, and 3 for your example definitions of M.
This assumes that theta is present in you anonymous function and that it is defined as a vector.
Also note that MATLAB cautions against utilizing functions in a programmatic manner, as its behavior may change in future releases. This was tested to function in R2017b.

Trapezodial Rule Matlab

I am completing an assignment for a class. We were to follow a flow chart to find the values for the trap rule code. I believe the problem is with my main code.
I am not sure if there is a problem with my function code or my main code, any help would be appreciated.
when I run the section, it display the function as the answer
The following is my mainscript code:
f = #(x) (4*sin (x)) / (exp(2*x)) ;
trap_haskell(f , 0 , 3 , 7)
The rest is my trapezoidal rule code
function [f] = trap_haskell(f, a, b, n)
x = a ;
h = (b - a) / n ;
s = f (a) ;
for k=1:1:n-1
x = x + h ;
s = s + 2 * f(x) ;
end
s = s + f(b) ;
I = (b - a) * s / (2 * n) ;
end
You're returning f as the output argument of trap_haskell which is the input function into trap_haskell itself. The variable I in your code actually stores the integral so it's simply a matter of changing the output variable of the function definition to return the integral instead:
%// ------ Change here
%// |
%// V
function [I] = trap_haskell(f, a, b, n)

How to compute log of multvariate gaussian in matlab

I am trying to compute log(N(x | mu, sigma)) in MATLAB where
x is the data vector(Dimensions D x 1) , mu(Dimensions D x 1) is mean and sigma(Dimensions D x D) is covariance.
My present implementation is
function [loggaussian] = logmvnpdf(x,mu,Sigma)
[D,~] = size(x);
const = -0.5 * D * log(2*pi);
term1 = -0.5 * ((x - mu)' * (inv(Sigma) * (x - mu)));
term2 = - 0.5 * logdet(Sigma);
loggaussian = const + term1 + term2;
end
function y = logdet(A)
y = log(det(A));
end
For some cases I get an error
Warning: Matrix is close to singular or badly scaled. Results may be inaccurate. RCOND =
NaN
I know you will point out that my data is not consistent, but I need to implement the function so that I can get the best approximate instead of throwing an warning. . How do I ensure that I always get a value.
I think the warning comes from using inv(Sigma). According to the documentation, you should avoid using inv where its use can be replaced by \ (mldivide). This will give you both better speed and accuracy.
For your code, instead of inv(Sigma) * (x - mu) use Sigma \ (x - mu).
The following approach should be (a little) less sensitive to ill-conditioning of the covariance matrix:
function logpdf = logmvnpdf (x, mu, K)
n = length (x);
R = chol (K);
const = 0.5 * n * log (2 * pi);
term1 = 0.5 * sum (((R') \ (x - mu)) .^ 2);
term2 = sum (log (diag (R)));
logpdf = - (const + term1 + term2);
end
If K is singular or near-singular, you can still have warnings (or errors) when calling chol.

how to solve a system of Ordinary Differential Equations (ODE's) in Matlab

I have to solve a system of ordinary differential equations of the form:
dx/ds = 1/x * [y* (g + s/y) - a*x*f(x^2,y^2)]
dy/ds = 1/x * [-y * (b + y) * f()] - y/s - c
where x, and y are the variables I need to find out, and s is the independent variable; the rest are constants. I've tried to solve this with ode45 with no success so far:
y = ode45(#yprime, s, [1 1]);
function dyds = yprime(s,y)
global g a v0 d
dyds_1 = 1./y(1) .*(y(2) .* (g + s ./ y(2)) - a .* y(1) .* sqrt(y(1).^2 + (v0 + y(2)).^2));
dyds_2 = - (y(2) .* (v0 + y(2)) .* sqrt(y(1).^2 + (v0 + y(2)).^2))./y(1) - y(2)./s - d;
dyds = [dyds_1; dyds_2];
return
where #yprime has the system of equations. I get the following error message:
YPRIME returns a vector of length 0, but the length of initial
conditions vector is 2. The vector returned by YPRIME and the initial
conditions vector must have the same number of elements.
Any ideas?
thanks
Certainly, you should have a look at your function yprime. Using some simple model that shares the number of differential state variables with your problem, have a look at this example.
function dyds = yprime(s, y)
dyds = zeros(2, 1);
dyds(1) = y(1) + y(2);
dyds(2) = 0.5 * y(1);
end
yprime must return a column vector that holds the values of the two right hand sides. The input argument s can be ignored because your model is time-independent. The example you show is somewhat difficult in that it is not of the form dy/dt = f(t, y). You will have to rearrange your equations as a first step. It will help to rename x into y(1) and y into y(2).
Also, are you sure that your global g a v0 d are not empty? If any one of those variables remains uninitialized, you will be multiplying state variables with an empty matrix, eventually resulting in an empty vector dyds being returned. This can be tested with
assert(~isempty(v0), 'v0 not initialized');
in yprime, or you could employ a debugging breakpoint.
the syntax for ODE solvers is [s y]=ode45(#yprime, [1 10], [2 2])
and you dont need to do elementwise operation in your case i.e. instead of .* just use *