How can i save previous value of variable in Matlab Function - matlab

Hello I would like to know how to save the previous value of an output variable in a matlab function.
function y = fcn(x,d,yp)
yp=0; %here I want to initialize this value just at the start of simulation
if (x-yp<=d)
y=x;
else
y=yp + d;
end
yp=y; % here i want to load output value
Thanks for your help

Make yp persistent
function y = fcn(x,d,varargin)
persistent yp
if nargin>2
yp = varargin{1};
end
...
yp=y;
end
Since yp is persistent now next time you will call the function yp will already hold the value of y you calculated previously. The only problem is not to override it by yp=0 as you have currently.
I replaced yp in the list of function arguments with varargin which holds optional arguments. The first time you call fcn you should call it as y = fcn(x,d,0), where the zero will be passed to yp inside the function. Next time you should call it without the third argument not to override the value yp holds (i.e. y = fcn(x,d).

In addition to persistent variables, you can also save the value in a nested function and return a handle to that function:
function fun = fcn(yp0)
yp = yp0; % declared in the main function scope
fun = #(x,d) update(x,d); % function handle stores the value a yp above and updates below.
function y = update(x,d)
if (x-yp<=d)
y=x;
else
y=yp + d;
end
yp = y; % updated down here
end
end
And then you would use it like
fun = fcn(yp0);
y = fun(x,d);
I use this instead of persistent variables when I notice a performance increase from not checking the initialization of persistent variables.

Using a persistent variable is the correct way to go, but as you found out, you cannot use varargin in a MATLAB Function block. The trick is to check whether the variable is empty or not, as in:
function y = fcn(x,d,yp)
persistent yp
if isempty(yp)
yp=0; %only if yp is empty, i.e. at the beginning of the simulation
end
if (x-yp<=d)
y=x;
else
y=yp + d;
end
yp=y; % here i want to load output value

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)

Checking how function has been called in MATLAB

I have a task to write a function that has an optional output argument.
Let's say I have a function y = fun(a,b). From what I understood, depending on whether the user needs the value y, it will EITHER calculate y OR draw some diagram.
So I think it means that if user calls my function like this: z = fun(1,2), then it calculates y and returns it, but if he calls it like this: fun(3,4);, then it won't return anything and draw a diagram instead.
Is there any way to check how my function has been called inside it? If yes, then how?
You can use nargout here:
function y = q61527462(a,b)
if nargout > 0
% Calculate y
y = a + b;
else
% Plot
plot(a,b)
end
end
so when you call the function as:
>> y = q61527462(1,2)
you get:
y =
3
and when you call with:
>> q61527462(1,2)
you get the plot
Have a look at nargout, that roughly translates to number of argument to output (there is also a nargin to check the number of input arguments).
However, the function will return the return-value anyway if your just check for nargin. You will also need to use varargout (variable argument output) to make your function return something only if the output will be assigned to some external variable.
So you just write in your function
function varargout = fun()
if nargout % implicit cast to a logical. It is equivalent to nargout > 0
% return output
varargout{1} = true; % note that this requires to wrap your output in a cell
else
% do plotting
end
EDIT:
It is even not necessary to use varargout. If you don't assign a value to a return-variable, it won't appear. So MATLAB can manage a not-assigned return-variable (something I was surprised to learn myself^^). This even works with multiple outputs!

Can we configure MATLAB let variable have minium local scope?

Can we configure MATLAB let variable have minium local scope?
I want matlab something similiar like C below.
% after some configure ...
for i=1:1:100
a=i*i
end
% here we can not using 'a' any more for it have local scope in for loop.
Why I want it becase the scope in whole script sometimes leds to bug hard to find.
For example:
% get accumulate of b via 100 times of x_0
b=0;
for i=1:1:100
x0=100
b=b+x0
end
% get accumulate of a via 100 times of x_0
a=0
for i=1:1:100
x_0=200
a=a+x0 %mistype x_0 to x0, and hard to find
end
Thanks advance.
I don't think there is any way to force a local scope in a script/loop. However, you can create a function, in a separate file or in the same file. Each function will have it's own local scope. So for your example you can create a file myScript.m with the following:
% get accumulate of b via 100 times of x_0
accum_b(100)
% get accumulate of a via 100 times of x_0
accum_a(200)
function a = accum_a(x0)
a = 0;
for k = 1:100
a = a + x0;
end
end
function b = accum_b(x0)
b = 0;
for k = 1:100
b = b + x0;
end
end
In this particular example, you can of course call the accum_a function twice, with different x0 inputs. But each function you define in a file will have it's own local scope, and will thus result in an error when mistyping x_0/x0.

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

Saving a specific simulation time

I have a two-track model implemented in simulink. To control the velocity I use a PID-controller, so that the the output of the velocity looks like this:
now I want to implement a MATLAB function or simulink block that tracks the time when the velocity reaches a steady-state-behaviour and puts it into some kind of storage. I tried to implement something like this via the following MATLAB function with MATLAB-function-block:
function y = fcn(t,v,dv,tv)
%#codegen
if (v==tv+0.01) & (dv<0)
y=t
end
t is the clock-signal, v the velocity, dv the first derivation of the velocity and tv is the targetvelocity. The problem about this function is that there "y is not defined on some execution paths". do you have any ideas how to make this work?
I solved the problem without a MATLAB function using the simulink blocks data store memory and its read & write blocks. The signal that is coming in from bottom right side is the momentary velocity. The if statement is
(u1 >= 22.2) & (u1<=22.3) & (u2<0)
Since simulink is using time steps and the momentary velocity will never be exactly 22.2, you can not use u1==22.2
In SimuLink add a second output and a fifth input to your function. Then use that new output as a feedback to the function.
function [y, output] = fcn(t,v,dv,tv,input)
y = 0;
output = input;
if (v == tv + 0.01) && (dv < 0)
y = t;
if (input == -1)
output = t;
end
end
Attach the output to an IC block where you set the input initial value to -1 or whatever value you want to use. Then attach the IC block to the input of the function. output will be feedback constantly through the function. Once it's set it will reatin it's value forever.
function y = fcn(t,v,dv,tv)
%#codegen
y = zeros(length(t),1); % Initialise the array
for ii = 1:length(t)
if (v==tv+0.01) & (dv<0)
y(ii)=t;
else
y(ii)=0;
end
end
y(y==0)=[];
end
Two changes: added a semicolon after y=t to force it to not print it every time it is set. Second, your question, else y=[];, which means that y will be an empty matrix if you do not adhere to your if statement.
It now stores a 0 each time you do not adhere to the if statement. The line y(y==0)=[]; deletes all zeros, comment this line if you want your y to be the same length as the input variables.
function y = fcn(t,v,dv,tv)
%#codegen
y = zeros(length(t),1); % Initialise the array
ii=1;
while exist(t)
if (v==tv+0.01) & (dv<0)
y(ii)=t;
else
y(ii)=0;
end
ii = ii+1;
end
y(y==0)=[];
end