Pass function as argument to function - matlab

So I have these two made up .m files. This is an example of the problem I'm having and the math is pseudo-math
rectangle.m:
function [vol, surfArea] = rectangle(side1, side2, side3)
vol = ...;
surfArea = ...;
end
ratio.m:
function r = ratio(f,constant)
% r should return a scaled value of the volume to surface area ratio
% based on the constant provided.
% This line doesn't work but shows what I'm intending to do.
[vol,surfArea] = f
r = constant*vol*surfArea;
end
What I'm unsure how to do is pass the rectangle function as f and then access vol and surfArea from within the ratio function. I've read and the Mathworks page on function handles and function functions and have come up empty handed on figuring out how to do this. I'm new to MATLAB so that doesn't help either.
Let me know if you need anymore info.
Thanks!

The correct way of passing the function rectangle as and argument of ratio is
r = ratio( #recangle, constant )
You can then call [vol,surfArea] = f(s1,s2,s3) from within ratio, but it requires the sideX arguments to be known.
If ratio should not require to know these arguments, then you could create an object function and pass this as a reference argument. Or better, you could create a rectangle class altogether:
classdef Rectangle < handle
properties
side1, side2, side3;
end
methods
% Constructor
function self = Rectangle(s1,s2,s3)
if nargin == 3
self.set_sides(s1,s2,s3);
end
end
% Set sides in one call
function set_sides(self,s1,s2,s3)
self.side1 = s1;
self.side2 = s2;
self.side3 = s3;
end
function v = volume(self)
% compute volume
end
function s = surface_area(self)
% compute surface area
end
function r = ratio(self)
r = self.volume() / self.surface_area();
end
function r = scaled_ratio(self,constant)
r = constant * self.ratio();
end
end
end

While I didn't bring this up in my question above, this is what I was searching for.
So what I wanted to do was pass some of rectangles arguments to ratio while being able to manipulate any chosen number of rectangles arguments from within the ratio function. Given my .m files that above, a third .m would look something like this. This solution ended up using MATLAB's anonymous functions.
CalcRatio.m:
function cr = calcRatio(length)
% Calculates different volume to surface area ratios given
% given different lengths of side2 of the rectangle.
cr = ratio(#(x) rectangle(4,x,7); %<-- allows the 2nd argument to be
% manipulated by ratio function
end
ratio.m:
function r = ratio(f,constant)
% r should return a scaled value of the volume to surface area ratio
% based on the constant provided.
% Uses constant as length for side2 -
% again, math doesnt make any sense, just showing what I wanted to do.
[vol,surfArea] = f(constant);
r = constant*vol*surfArea;
end

Related

Body of this Matlab function works, but not the function itself (interp1 error)

I've written the following piece of subcode (with parameters commented) for an Euler policy iteration algorithm. When I try to run the body of the function (everything below global) for say, a1 = 1, it works, and returns a scalar. However, when I call the function as euler_diff_test(1), I get an error. (Pasted below)
function diff = euler_diff_test(a1)
%the following comments are example parameters. They are in the global line originally.
% r = 0.2, a = 0.5, y = 1.1, a_grid = linspace(0.5,7,100)
%policy_guess = zeros(2,N);
%policy_guess(1,:) = 0.3*a_grid;
%policy_guess(2,:) = 0.3*a_grid;
% M = zeros(2,2); %M for markov transition kernel
% M(1,1) = p;
% M(2,2) = p;
% M(2,1) = 1-p;
% M(1,2) = 1-p;
% j = 1
global r a y a_grid policy_guess M j;
c = (1+r)*a + y - a1; %consumption formula
if c<=1e-02 %don't care about consumption being negative
diff = 888888888888888888888;
else
policy_func = interp1(a_grid', policy_guess', a1, 'linear');
diff = 1/c - beta*(1+r)*(1 ./ policy_func)*M(j,:)';
end
end
Error Reads:
Any help is much appreciated!
The problem is that you dont understand globals nor how they work!
You seem to be doing something like:
N=100; p=0.1;
r = 0.2, a = 0.5, y = 1.1, a_grid = linspace(0.5,7,100)
policy_guess = zeros(2,N);
policy_guess(1,:) = 0.3*a_grid;
policy_guess(2,:) = 0.3*a_grid;
M = zeros(2,2); %M for markov transition kernel
M(1,1) = p;
M(2,2) = p;
M(2,1) = 1-p;
M(1,2) = 1-p;
euler_diff_test(1)
And this is causing the error you show. Of course it is!
First, you need to learn what a global is and what worskpaces are. Each fucntion has its own worskpace or "scope". That means that only variables defined within the workspace are visible by the function itself.
A global variable is one that exist for all workspaces, and everyone can modify it. You seem to want all those variables defined outside the function, inside your function. But realise! when the variables are defined, they are not global. The function starts, and in its first line, it does only know about the existence of a1. Then, later, you define a bunch of variables as global, that the function did not know about. So what does the function do? just create them empty, for you.
If you want your the variables that you create in the main script scope to be global, you need to declare them as global then, not inside the function. So cut your line global ... from the fucntion, and put it on top of the script where you declare all your variables, i.e. on top of
% here!
N=100; p=0.1;
...
in my example.
Now, the important stuff: Global variables are bad. When you have globals, you don't know who modifies, and its super easy to lost track of what is happening to them, because every function that uses a variable a will modify the global a, so its a pain to debug. Almost no one uses globals because of this. The best way is to pass them to the function as input, i.e. define your function as:
function diff = euler_diff_test(a1,r, a, y, a_grid, policy_guess, M, j)

Matlab class dynamic filling of a property

I'm trying to dynamically fill a property in a Matlab class.
I pass vectors to a method function and then compute various parameters. I would like to fill the properties in a for loop, see code example. The OwnClassFunction is just an example of a further function in the class, but is not implemented in the code example. How can I do this correctly?
classdef Sicherung < handle
properties
x = ([],1)
end
methods
function examplefunction(object,...
single_parameter_vector) % (n,1) n can be any size
for i=1:length(param_vector)
[object.x(i,1)] = object.OwnClassFunction(single_parameter_vector(i,1));
end
end
end
end
If i try something like that
...
properties
x = []
end
...
function ...(object,parameter)
for i=1:length(parameter)
[object.x(i)] = function(parameter(i));
end
I get the error message Subscripted assignment dimension mismatch.
I don’t have MATLAB in hand to test, but the following should work.
Your code is pretty close to a correctly functioning method. Change it as follows:
classdef Sicherung < handle
properties
x = [] % initialize to empty array
end
methods
function examplefunction(object,param_vector)
if ~isvector(param_vector)
error('vector expected') % check input
end
n = numel(param_vector)
object.x = zeros(n,1); % preallocate
for i=1:n
object.x(i) = object.OwnClassFunction(param_vector(i));
end
end
end
end

Undefined function 'minus' for input argument of type 'iddata'

This is a followup to a previous issue I was having.
I want to give an offset to a signal then add some delay in it and calculate RMSE for that but when taking difference I am having the following issue:
I would like to ask the following things:
How can I solve the above problem?
Will anybody please explain in simple words what iddata does - because I have studied different portals including MATLAB but remained unable to get a good concept.
How can I store data of type iddata in cell for subtraction in the last part of my code?
Code with Problem :
drv(1)=load('123.mat');
t = drv(1).x;
ref = drv(1).y;
angle = drv(1).z;
Fs = 1000;
t1 =t';
ref1= ref';
d_data = iddata(ref1, t1, 1/Fs);
%% Add offset:
x = 1;
afterOffset1= {};
for i = 100:10:130
T = getTrend(d_data);
% <detrend data if needed>
T.InputOffset = i;
T.OutputOffset = i;
afterOffset = retrend(d_data,T);
afterOffset1{x,1}= afterOffset;
x= x+1 ;
end
%% Add delay:
y=20;
afterDelay1= {};
for i = 1:1:4
% delaySamples = i; % Must be a non-negative value
% afterDelay = iddata([NaN(delaySamples,1); d_data.OutputData],...
% [d_data.InputData; NaN(delaySamples,1)], 1/Fs);
afterOffset1{i}.Tstart = y;
afterDelay1{i,1}= afterOffset1{i};
y= y+10;
end
%% Plot:
n = size(afterDelay1,1);
figure();
for i=1:1:n
subplot(2,2,i);
plot(d_data);
hold all
plot(afterDelay1{i});
end
sig_diff = angle(1)-afterDelay1;
square_error(i,:) = (sig_diff(i)).^2;
mse(i,:)= mean(square_error(i));
rmse(i,:) = sqrt(mse(i));
sig_diff = d_data_1 - afterDelay; % <<<<<<<<<<<<<<<<<<<<<< Problem is here
% square_error = (sig_diff).^2;
% mse= mean(square_error);
% rmse = sqrt(mse);
end
You most likely want the OutputData attribute from the iddata object which is the output or y signal of your problem:
sig_diff = angle(1)-afterDelay1.OutputData;
Also note that this will give you a column vector, but your code later on assumes it's a row vector. You may want to transpose this data after you perform the above calculation before proceeding:
sig_diff = angle(1)-afterDelay1.OutputData;
sig_diff = sig_diff.';
In general, iddata is a function that creates an object that represents input and output time or frequency domain data. Take note that when you create an iddata object, the input matrix can potentially have multiple sources and so each column dictates a source. The same can be said for the output where each column dictates an output. Therefore, it is very important that you transpose your data prior to using this function to ensure that each signal is in a separate column, or just use a single column to represent one input / output.
Inside the object has a variety of attributes, including the sampling time or sampling frequency, the valid domain and range that the function takes on and finally accessing the input and output data. OutputData is one of these fields. I'd recommend looking at the documentation that talks about all of the attributes that you can access with iddata. OutputData is clearly defined here: https://www.mathworks.com/help/ident/ref/iddata.html

Plotting brownian motion matlab

First of all, I just want to say that I'm not that used to using matlab, but I need for an assignment, I'm supposed to create a "brownian movement". My code is currently looking like this:
clf
hold on
prompt = 'Ge ett input';
size = input(prompt) ;
numParticles = input('Ange antal partiklar');
axis([-size size -size size]);
Part = [];
color = 'brkgmyco';
for i = drange(1:numParticles)
Part = [Part [0;0]];
end
for i = drange(1:200)
dxdy = randn(2,numParticles);
k = Part
Part = Part + dxdy;
My concern is how to print, I would even want like a small delay on every print, so you really can see what's happening for the assignment, is this possible to achieve from the code I've written for now or should anything be changed? Thanks in advance!
Here are some basic problems with your code, regardless of what you are trying to do:
You use size as a variable name. Doing so overrides MATLAB's function size.
The function zeros creates an array initialized by zeros, no need for a loop for that.
Instead of calculating randn for 200 times in a loop, you can do it once, with dxdy = randn(2,numParticles,200) and then simply refer to dxdy(:,:,i) within the loop.
The same holds for summation. Instead of summing within a loop to get the cumulative sum, use cumsum like Part = cumsum(randn(2,numParticles,200),3); and then refer to Part(:,:,i), within the loop.
Now to your task. You said you want to know how to print, but I believe you want to plot because you use some commands like axis, clf and hold, that refer to graphic objects. However, you never really do plot anything.
The basic and general function for plotting in 2D is plot, but there are many other more specific functions. One of them is scatter, and it has a sister function gscatter, that takes triples of x, y and groupand plot each (x(k),y(k)) colored by their group(k).
This code plots the particles on an axes, and animate their movement:
prompt = 'Ge ett input';
scope = input(prompt) ;
numParticles = input('Ange antal partiklar');
N = 500;
Part = cumsum(randn(2,numParticles,N)*scope/100,3);
h = gscatter(Part(1,:,1),Part(2,:,1),1:numParticles);
axis([-scope scope -scope scope]);
legend off
for k = 2:N
for p = 1:numParticles
h(p).XData = Part(1,p,k);
h(p).YData = Part(2,p,k);
end
drawnow
end
Is this what you look for?

Matlab Function and Input

function area = traparea(a,b,h)
% traparea(a,b,h) Computes the area of a trapezoid given
% the dimensions a, b and h, where a and b
% are the lengths of the parallel sides and
% h is the distance between these sides
% Compute the area, but suppress printing of the result
area = 0.5*(a+b)*h;
This is just an example. I would like to know how to declare the values suppose a=5,b=4,h=8 in a seperate .m file and calling it into original function ie, traparea, using .in statement?
for example
.in a=5
like that
Please help
If I understand, you want to create a script file. Create a filename called "myscript.m" (pick any name you like), and place it in the same folder as "traparea.m" is located. Then, in the file "myscript.m", put the following:
a = 5;
b = 4;
h = 8;
result = traparea(a,b,h) % this is one way to show the result
fprintf('my result is %f\n', result); % this is another way to display the result
Once you have created the two files "myscript.m", and "traparea.m", you just type "myscript" at the command line.