Call a function within a function matlab - matlab

I have defined a function called CARE_SAV which contains a recursive process, the code is
function [miu_tau_c,miu_tau] = CARE_SAV(beta,Yt,t,miu_1)
global miu_tau
global t
global miu_1
if t > 1
miu_tau_c = beta(1)+beta(2) * ...
[CARE_SAV(beta, Yt, t-1, miu_1)]+beta(3)*abs(Yt(t-1));
miu_tau = [miu_tau;miu_tau_c];
else
miu_tau_c = miu_1;
miu_tau = [miu_tau;miu_tau_c];
end
The function itself runs perfectly. However, when I define another function (ALS) and call this CARE_SAV, the error keeps popping out saying the local variable may have been changed to match local variable value. And hence there is error on ALS line 6. The ALS code is shown below
function sum = ALS(tau,Yt,beta,miu_1,CARE_SAV)
s = 0; % set the initial value for the ALS sum
global t
global miu_1
t = size(Yt,1); % indicate the length of the simulated data
[~,miu_tau]=CARE_SAV(beta,Yt,t,miu_1); % call the CARE_SAV function to get miu_tau value
for i = 1:size(Yt,1) % conduct the ALS summation process for each t
if Yt(i) < miu_tau(i) % set the indicator function
s = s+abs(tau-1)*(Yt(i) - miu_tau(i))^2;
else
s = s+abs(tau-0)*(Yt(i) - miu_tau(i))^2;
end
end
sum = s;
Can someone explain to me what I happening here? Much appreciated.

In CARE_SAV, you have this:
miu_tau_c = miu_1; - being miu_1 a global variable.
Then, in the other function, you have as input miu_1 AGAIN and you call global miu_1 AGAIN. This is the issue.
Try to remove miu_1 from input in the second function. It might work, but using globals in functions like this it's not recommended.

Related

function handles in Octave

I have a question regarding function(handles) in Octave.
So, I want to call a function, which accepts two variables and returns two(the implementation is faulty; but not relevant in this case).
According to the documentation this should be quite straightforward:
function [ret-list] = name (arg-list)
body
endfunction
I'm trying the following:
function two_d_comp = twodcomp
twodcomp.twoDperp=#perp;
^
end
function twoDperp[vmag, vangle]=perp(x,y)
W = hypot(y,x);
vmag = y/W;
vangle = x/y;
end;
I saved the function in a file called twodcomp.m.
When I call the function as follows:
[X, Y] = twodcomp.twoDperp(1,2)
Octave spits out the following:
error: #perp: no function and no method found
error: called from
twodcomp at line 2 column 20
I managed to remove the error by removing the output arguments vmag and vangle, as follows:
function twoDperp=perp(x,y)
But this is obviously not really what I want.
Do you guys happen to have some pointers as to what I'm doing wrong?
Cheers
Your initial function twodcomp: you cannot have the output variable (before the =) be named the same as your function name (after the =).
Then if you want to assign an anonymous function (MATLAB docs, Octave docs) using the # notation, you can still pass the desired inputs.
So rewrite it like:
% Include empty parentheses after a function name to make it clear which is the output
function output = twodcomp()
% Not sure why you're assigning this function to a struct, but
% still give yourself the ability to pass arguments.
% I'm assuming you want to use the output variable,
% and not reuse the main function name (again)
output.twoDperp = #(x,y) perp(x,y);
end
With your second function, you just need to remove the twoDperp before your output arguments. In your question you state the expected syntax from the docs, but then didn't follow it...
function [vmag, vangle] = perp(x,y)
W = hypot(y,x);
vmag = y/W;
vangle = x/y;
end
Now these can be used like so:
% Deliberately using different variable names to make it clear where things
% overlap from the function output. twodcomp output is some struct.
myStruct = twodcomp();
% The output struct has the field "twoDperp" which is a function with 2 outputs
[m, a] = myStruct.twoDperp(1,2);

Looping a Function in Matlab

total newbie here. I'm having problems looping a function that I've created. I'm having some problems copying the code over but I'll give a general idea of it:
function[X]=Test(A,B,C,D)
other parts of the code
.
.
.
X = linsolve(K,L)
end
where K,L are other matrices I derived from the 4 variables A,B,C,D
The problem is whenever I execute the function Test(1,2,3,4), I can only get one answer out. I'm trying to loop this process for one variable, keep the other 3 variables constant.
For example, I want to get answers for A = 1:10, while B = 2, C = 3, D = 4
I've tried the following method and they did not work:
Function[X] = Test(A,B,C,D)
for A = 1:10
other parts of the code...
X=linsolve(K,L)
end
Whenever I keyed in the command Test(1,2,3,4), it only gave me the output of Test(10,2,3,4)
Then I read somewhere that you have to call the function from somewhere else, so I edited the Test function to be Function[X] = Test(B,C,D) and left A out where it can be assigned in another script eg:
global A
for A = 1:10
Test(A,2,3,4)
end
But this gives an error as well, as Test function requires A to be defined. As such I'm a little lost and can't seem to find any information on how can this be done. Would appreciate all the help I can get.
Cheers guys
I think this is what you're looking for:
A=1:10; B=2; C=3; D=4;
%Do pre-allocation for X according to the dimensions of your output
for iter = 1:length(A)
X(:,:,iter)= Test(A(iter),B,C,D);
end
X
where
function [X]=Test(A,B,C,D)
%other parts of the code
X = linsolve(K,L)
end
Try this:
function X = Test(A,B,C,D)
% allocate output (it is faster than changing the size in every loop)
X = {};
% loop for each position in A
for i = 1:numel(A);
%in the other parts you have to use A(i) instead of just A
... other parts of code
%overwrite the value in X at position i
X{i} = linsolve(K,L);
end
end
and run it with Test(1:10,2,3,4)
To answer what went wrong before:
When you loop with 'for A=1:10' you overwrite the A that was passed to the function (so the function will ignore the A that you passed it) and in each loop you overwrite the X calculated in the previous loop (that is why you can only see the answer for A=10).
The second try should work if you have created a file named Test.m with the function X = (A,B,C,D) as the first code in the file. Although the global assignment is unnecessary. In fact I would strongly recommend you not to use global variables as it gets very messy very fast.

How to adjust the size of block.outputport.data in Matlab?

I have tried to generate a square pulsed clock. But it gives error. I tried this:
function pll( block)
setup(block);
function setup(block)
% Register number of ports
block.NumInputPorts = 1;
block.NumOutputPorts = 1;
% Override input port properties
block.InputPort(1).Dimensions = 1;
block.InputPort(1).DatatypeID = 8; % boolean
block.InputPort(1).Complexity = 'Real';
block.InputPort(1).DirectFeedthrough = false;
% Override output port properties
block.OutputPort(1).Dimensions = 1;
block.OutputPort(1).DatatypeID = 0; %double
block.OutputPort(1).Complexity = 'Real';
block.NumDialogPrms = 1;
block.DialogPrmsTunable = 0;
ts = 1/24000000'; %'
block.sample times= [ts 0];
block.SimStateCompliance = 'DefaultSimState'
function Outputs(block)
t = [0:1/(24000000):0.000001];
l = 0.1*exp(-6);
c = 220*exp(-9) + 60*exp(-9);
f = 1/(2*pi*sqrt(l*c));
block.OutputPort(1).Data = square(2*pi*f*t);
function Terminate(block)
But it gives me the error
"Error evaluating registered method 'Outputs' of M-S-Function 'pll' in
'untitled/Level-2 M-file S-Function'. Invalid assignment in
'untitled/Level-2 M-file S-Function': attempt to assign a vector of
width 24001 to a vector of width 1."
the error indicates on the line
block.OutputPort(1).Data = square(2*pi*f*t);
so what can be done to overcome this error?
It seems from your example that you're not really familiar with the way Simulink works. At each time step, each block in a Simulink model outputs a value (i.e the block's output value) corresponding to the current simulation time. In your case, within the block.Output function you are trying to output all time points at every simulation time step.
It appears that what you really want is to replace
t = [0:1/(24000000):0.000001];
with
t = block.CurrentTime;
And replace
block.OutputPort(1).Data = square(2*pi*f*t);
with
block.OutputPort(1).Data = sign(sin(2*pi*f*t));
Also, some other things to consider:
you don't seem to be registering the block's output method using:
block.RegBlockMethod('Outputs',#Output);
Why have you defined the block to have an input when it doesn't seem to require one?
Why are you doing this in an S-Function when a From Workspace block (or one of the many other ways to get data into a model) would seem to make more sense?

MATLAB: Saving While loop data

I'm running a while loop and I am running in to some problems.
I have the following piece of code:
Angle_int = 0.5; % Initial interpolation angle of attack
Clmax2d(1,1:length(Yle_wing)) = 3; % Dummy value
diff = 0; % Dummy value
while sum(diff < 0) > fix(tol*length(Yle_wing))
Angle_int = Angle_int + 0.5; % Interpolation angle increases with 0.5 with every iteration
for j = 1:length(Yle_wing)
CL3d = interp1(Angle,[cl_matrix(1,j) cl_matrix(2,j) cl_matrix(3,j)],Angle_int,'linear');
CL_3DD(:,j) = CL3d;
end
diff = (Clmax2d - CL_3DD); % Difference between Cl2d and Cl3d
Angle_stall = Angle_int;
CL_3D = CL_3DD;
end
For some reason, CL_3D = CL_3DD; and Angle_stall = Angle_int; seem to disappear when the while loop finishes. Hence, I cannot use their converged values ahead of the while loop since these variables are not recognized. I get the following error:
Undefined function or variable "CL_3D".
Hence, does someone knows what I am doing wrong? or any tips would be welcome as well.
Thanks in advance,
cheers
The error message:
Undefined function or variable "CL_3D".
is always because you're trying to use a variable or function that you haven't initialized yet. Often this happens in loops where you want to increment a counter, or compare values etc.
A common error is doing something like this without writing ii = 0 in front of the loop:
while ii < some_num
ii = ii + 1;
some_function();
end
With your dummy variables, you never enter the loop (unless tol < 0, which seems like an odd choice). You probably want to initialize diff = Inf or something like that. However, using diff as a variable name is not a good idea, since it's a builtin function.
You probably try to use CL_3D, when it's not yet initialized (somewhere else in your code, not in the part you posted). MATLAB tells you which line the error appears in, you should try using it!
Maybe initializing it like zeros(size(Clmax2d)); could work (it will definitely remove your error, but it might not give the desired behavior).
PS!
Using i and j as variables are not recommended as they represent the imaginary unit in MATLAB.

Matlab R2014a - defining a variable after a function is called

In a matlab script, is it possible to define a variable after the function is called?
(i.e. the script finds the function with the undefined variable, looks for the variable initialization and executes the function afterwards)
I need this because I have a large number of variables and functions and I don't want to order them in a sequential way but in the way that is appropriate for my problem.
E.g.
mean(x);
x = [1, 2, 3];
Thanks
Disclaimer: I think what you want to do is a really bad practice. If you find yourself in the need to do this, your code screams refactoring.
Yes, it is possible. There are two ways.
Using the try-catch statement:
try
x_mean = mean(x)
catch exception
if isequal(exception.identifier, 'MATLAB:UndefinedFunction')
x = [1,2,3];
x_mean = mean(x);
else
rethrow(exception);
end
end
The explanation: if the mean(x) fails, the code will enter in the catch branch. Then it verifies that the error is happening because a missing variable and if that's the case, the variable x is defined and the function re-run. There is a caveat: Matlab uses the same identifier for missing variable and for missing function.
Using the exist function:
if exist('x') == 1 %// the function have several return values
x_mean = mean(x);
else
x = [1, 2, 3];
x_mean = mean(x);
end
The explanation: the exist function will verify if a variable with the name x exists in the workspace. If it does exist, it will return 1 and you can execute your function. If it does not exist, then you can declare it first and then run mean. See documentation here.
My two cents: once again, this is a horrible way to achieve things. By going this way you will end up with pure spaghetti code. It will be a nightmare to debug. It will be a nightmare to maintain. There is a 99% chance that there are better ways to do what you want. It is just a matter of investing time and think a little bit. Even if it is a personal project or a quick script to solve a homework/task, you will learn much more by doing it the right way.
If I understand you question correctly, then yes it can be done by some ugly hacks.
The following class can be used:
classdef AdvancedFunctionHandle
properties(GetAccess = 'private', SetAccess = 'private')
handle
variables
end
methods
function obj = AdvancedFunctionHandle(fct, varargin)
if ~isa(fct,'function_handle')
error('The function must be a function handle!');
end
argins = numel(varargin);
variables = cell(1,argins);
for i = 1:argins
if ~ischar(varargin{i})
error('The variables must be represented by a string variabel name!');
end
if (~isvarname(varargin{i}) )
error('The variables must be a string representing a legal variabel name!');
end
variables{i} = varargin{i};
end
obj.handle = fct;
obj.variables = variables;
end
function val = subsindex(obj)
val = obj.calculate();
end
function val = calculate(obj)
try
vars = cell(1,numel(obj.variables));
for i = 1:numel(obj.variables)
v = evalin('base',obj.variables{i});
if isa(v,'AdvancedFunctionHandle')
vars{i} = v.calculate();
else
vars{i} = v;
end
end
val = obj.handle(vars{:});
catch
val = obj;
end
end
function display(obj)
disp([func2str(obj.handle),'(',strjoin(obj.variables,','),')']);
end
end
end
I made a small test script for it too:
clear
m = AdvancedFunctionHandle(#mean,'x');
s = AdvancedFunctionHandle(#(n)sum(1:n),'m');
m.calculate
x = [1,2,3];
s.calculate
I hope this solves your problem.
Notice that since the class refers to the base workspace, it will not work when run from a function, or if the script it is run from is run from a function.
I don't understand what you are trying to achieve, but if you want to define things after they are used, I think they have to be functions.
Example file:
function myfun()
mean(getX)
function X = getX
X = [1 2 3]
So though it is technically possible to define variables after they are used, you would really not want to do that.