How do functions really work in MATLAB? - matlab

function [dhdt, x] = velocity(t, h)
dhdt = -9.8 * t;
x = 4 * t;
end
So this is basically my function (with filename velocity.m). At first I thought that what's between the brackets [] would be the output. When I typed in the Command Window I only got one answer.
velocity(1)
%// -9.8
I expected to get a two-element vector containing both dhdt and x
velocity(1)
%// -9.8 4
Why is this?

Matlab only displays one output if you don't store them to variables... Type [dhdt, x] = velocity(1) and you'll see both values, as well as having them stored to variables.
Also, you only get away in this case with not providing the h parameter because it's not used in the function. If you used h in velocity() and called velocity(1) it would break.

Related

How to create a function that takes a matrix as an input?

I am new to MatLab.
Write a function that takes as input a matrix D ∈ R^(N×2), D_i = (x_i,y_i), and the period ω and returns a plot showing a fit of the data without noise.
I need help with creating the function that takes the input as a matrix and period ω. Here is what I have so far. Am I on the right track?
function F = fftfuntion(D, omega)
check = 0;
x = D(:,1);
y = D(;,2);
You are on track but there are 3 problems:
First: you are using p variable inside your function which is not defined there. If it is defined in your main code you have to insert it to this function by adding an input to your function as p and when the function is called you have to put p there. Your other solution is to set p as a global variable which is not recommended.
function F = fftfuntion(D, omega,p)
Second: you have said that you need omega as an input and you are changing it with omega = 2*pi which is not right.
Finally I don't see any output which I think that's because you are not still done with the function.
Good luck

matlab can't use dot operator on object

I came across a weird problem today while practicing using classes in MATLAB. It seems like MATLAB can't parse parentheses around an object.
I created a user-defined class named vector that has various attributes: magnitude, angle, length in the x and y directions. I overloaded the unary minus operator so that I can have
a = vector(5,50) % creates a vector with magnitude 5 and angle 50 (in degrees)
a.ang % prints the angle
b = -a
b.ang % 230 degrees
This is all fine and good, but say that I want to find the angle of the -a in one line. You'd expect something like
(-a).ang
to work but instead I get
(-a).ang
|
Error: Unexpected MATLAB operator.
I can't use
-a.ang
either because the dot operator has higher precedence than the minus. Any explanation of why matlab can't parse parentheses around an object?
EDIT: Here's the vector class that I created.
classdef vector
properties
mag
ang % in degrees
x
y
end
methods
function v = vector(mag,ang)
if nargin == 2
v.mag = mag;
v.ang = ang;
v.x = mag*cosd(ang);
v.y = mag*sind(ang);
end
end
function res = plus(u,v)
x = u.x + v.x;
y = u.y + v.y;
res = vector(norm([x,y]), atan2d(y,x));
end
function res = minus(u,v)
x = u.x - v.x;
y = u.y - v.y;
res = vector(norm([x,y]), atan2d(y,x));
end
function res = uminus(v)
res = vector;
res.x = -v.x;
res.y = -v.y;
res.mag = v.mag;
res.ang = mod(v.ang+180,360);
end
end
end
I think I've found the answer. In general, Matlab does not support two sets of parentheses chained together because it could either be an indexing or a function call.
MATLAB's parser is limited, partly for historical reasons. It has never
been possible to do something like f(4)(1) because of the ambiguity. Does it mean that f(4) is a function handle and then we want to pass 1 into that function or does it mean that f is a function, we pass 4 into that function, it returns a vector and then we index into the first element of that? Well, the parser doesn't know either. It could be defined, but it hasn't up till now.
Source: https://www.mathworks.com/matlabcentral/newsreader/view_thread/280225
Also, once I had realized that the two side-by-side parentheses were the problem, it seems that the main workarounds are either:
Use the SUBSREF function to explicitly evaluate the parentheses
Define your own anonymous function to perform the indexing and array handling for you.
Those workarounds are explained in the first two answers in the below link.
How can I index a MATLAB array returned by a function without first assigning it to a local variable?
Thanks for looking over my question guys!
I cannot replicate vector function but for a simple structure like this
a.ang=[2,4,6,8]
what you need is
-a.ang
instead of
(-a).ang
which will reproduce the error you mentioned

Why Self-defined Matlab Function Return Empty Matrix

The function is supposed to return a value. However, when I type:
val(1d4)
it returns
ans =
[]
However, if I copied line by line, and set all parameters (V eps_today etc.), and run in the command window, it works fine...Have no clue where the problem is. Thanks:)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%This function calculates the value function of both small and big%
%investment %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function negval=val(k_next)
global V eps_today k_today eps_gv k_gv z_today delta xi
theta=0.5327; beta=0.95; rho=0.7675; sigma_eta=0.7704;
%identify the grid point that falls just below
klo=max(sum(k_next>k_gv),1);
%above
khi=klo+1;
%Linear Interpolation, effectively only on the dimension of k
if klo<size(k_gv,2)
V_temp=V(:,klo)+(k_next-k_gv(klo))/(k_gv(khi)-k_gv(klo))*(V(:,khi)-V(:,klo));
else
%when k_next> maximum point of k_gv
V_temp=V(:,size(k_gv,2));
end
EV=mean(V_temp,1);
negval=-(exp(z_today+eps_today)*k_today^theta-xi*k_today-(k_next-(1-delta)*k_today)+beta*EV);
end
I tried to replicate your problem but I couldn't. If I do not set the global variables Matlab shouts and refuses to proceed through the function. Setting some of them to empty values was the same (did not try them all). If I do set the globals then the function always gives me a value.
But I strongly suspect it has something to do with the globals anyway (can you show the code where they are initialized?). As I mentioned in the comment I would get rid of them, the code could look like this
Main programme
%set parameters
Pars.beta = beta=0.95;
Pars.theta = 0.5327;
Pars.rho=0.7675;
Pars.sigma_eta=0.7704;
Pars.delta = ...;
Pars.xi = ...;
%set grid
eps_gv = ...
k_gv = ...
ne = length(eps_gv);
nk = length(k_gv);
V = zeros(ne,nk);
k_next = ...;
value = val(k_next,V,eps_gv,k_gv,Pars);
Val function
negval = function val(k_next,V,eps_gv,k_gv,Pars)
theta=Pars.theta; beta=Pars.beta; rho=Pars.rho; etc.
You don't even need eps_today and k_today as these should be the values on the grid (ie eps_gv and k_gv). I don't know what z_today is but there should either be a grid for z or z_today should be a parameter, in which case it should be in Pars. Of course if you use eps_gv and k_gv instead of eps_today and k_today the negval = ... line needs to be modified to take account of them being arrays not scalars.
One last comment, there is a bug on the EV=mean(V_temp,1); line. The mean function calculates the average of (the columns of) V. To calculate the expected value you need to do a weighted average where you weight each row of V by the probability of eps being eps_gv(1) (ie sum(V(i,:)*prob_eps(i)), sum going over i) . What you did works only if all shocks have equal probability. Pointing out since I am not sure you are aware of that.

Function Definition Clarification in Matlab

I wrote some code that works just fine to evaluate theta on its own with some test input. However, I would like to take this code and turn it into a function that I can call within another matlab file. I keep getting the error message, "Function definitions are not permitted in this context."
I want to be able to define four vectors in another matlab file and call SP1 to evaluate theta for those inputs. I'm not sure where I'm going wrong, though. Please help!
Thanks so much.
clc
clear all
function theta = SP1(p,q1,w1,r)
% INPUT:
%function theta = SP1(p,q1,w1,r)
% p = [5; -7; 12];
% q1 = [17.3037; -3.1128; 2.48175];
% w1 = [1/sqrt(8); sqrt(3/8); 1/sqrt(2)];
% r = [1; 2; -3];
% Define vectors u and v as well as u' and v'.
u = p - r;
v = q1 - r;
w1_t = transpose(w1);
u_prime = u - w1 * w1_t * u;
v_prime = v - w1 * w1_t * v;
% Calculate theta if conditions are met for a solution to exist.
if (abs(norm(u_prime)-norm(v_prime))<0.01) & (abs((w1_t * u)-(w1_t * v))<0.01)
X = w1_t*cross(u_prime,v_prime);
Y = dot(u_prime,v_prime);
theta = atan2(X,Y)
else if (norm(u_prime) == 0 | norm(v_prime) == 0)
disp('Infinite Number of Solutions')
else
disp('Conditions not satisfied to find a solution')
end
end
I think you can just remove the top two lines,
clc
clear all
and save the rest of the code starting with function as SP1.m file.
Then you should be able to call this function as SP1 from other m files.
I think you're confused about how functions work. The first line of a function definition defines how many inputs and outputs MATLAB expects:
function theta = SP1(p,q1,w1,r)
This means that calling a function SP1 will require you to give four inputs, and will return one output. It doesn't mean that:
Your inputs need to be named p, q1 and so on
Your output will be called theta automatically
The function will automatically take in the input variables p, q1, etc if they exist in the workspace.
It also doesn't do any checking on the inputs; so if you require that inputs be of a certain type, size, etc. you need to write your own error checking at the start of the file. You might intend that those inputs be 3x1 vectors, but there's nothing in the function to tell MATLAB that. So, SP1(1,2,3,4) will work, to some extent - it will take those inputs and try to run them through the function, and if they don't cause an error it will give you an output. The output might be wrong, but the computer doesn't know that.
Once you have a function you can call it multiple ways from the command line or from within other functions or scripts. As previously mentioned you don't have to stick to the naming of variables within the function, as long as input variables exist when the function is called MATLAB will accept them:
theta = SP1(p8,q27,w35,not_r);
myoutput = SP1(any,variable,I,like);
I don't necessarily have to give an output (but then the first output will be routed to ans)
SP1(this,will,also,work);
If I have some variables stored in a *.mat file (the case you seem to be asking about), I can do it like this:
load('mydata.mat'); %this file contains stored variables p, q1, w1 and r
theta = SP1(p,q1,w1,r);

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.