Detecting if some output arguments are unused - matlab

Matlab introduced for the ~ character in the list of output arguments of some routine in order to indicate we're not interested in this output value. For instance:
% Only interested for max position, not max value
[~, idx] = max(rand(1, 10));
For speed optimization reasons, is it possible from inside some routine to detect that some of the output arguments are not used ? For instance:
function [y, z] = myroutine(x)
%[
if (argout(1).NotUsed)
% Do not compute y output it is useless
y = [];
else
% Ok take time to compute y
y = timeConsummingComputations(x);
end
...
%]

It may not be the best one but an easy solution is to add another input argument
function [y, z] = myroutine(x, doYouWantY)
%[
if doYouWantY == 0
% Do not compute y output it is useless
y = [];
else
% Ok take time to compute y
y = timeConsummingComputations(x);
end
...
%]

nargout method, edited for 2nd output. Not very stable solution though, since whenever you call the function with one output argument, you need to be aware that the output is the second argument only.
function [y, z] = myroutine(x)
%[
if nargout==1
% Do not compute y output it is useless
y = [];
else
% Ok take time to compute y
y = timeConsummingComputations(x);
end
%]

Related

Run parallel function in Matlab

I tried to test with my really simple code as below, but the error is "Too many output arguments."
function func1(x,y)
plot(x, y), xlabel('x'), ylabel('Sin(x)'), title('Sin(x) Graph'),
grid on, axis equal
end
function func2(x,y)
plot(x, y), xlabel('x'), ylabel('Cos(x)'), title('Cos(x) Graph'),
grid on, axis equal
end
the main is
x = 0:0.01:10;
y1 = sin(x);
y2 = cos(x);
funcs = {#func1, #func2} ; % let fun1, fun2 be two functions
arguments = {x y1;x y2} ; % write the inputs of each function
solutions = cell(1,2); % initialize the solution
% use of parfor
parfor ii = 1:2
solutions{ii}=funcs{ii}(arguments{ii,:});
end
Please help!!!
The way you call the function
solutions{ii}=funcs{ii}(arguments{ii,:});
Expects an output, which you're assigning to solutions{ii}.
This wouldn't work within a normal loop, or even without a loop, the fact that you're trying to write a parfor is immaterial here...
Your functions are defined as
function func1(x,y)
% ...
function func2(x,y)
% ...
Neither of these have output arguments, so it's unclear what you expect to be assigning to solutions{ii} - this exactly matches the error message you're seeing "too many output arguments".
If you expect an output from your function, then declare one
function z = func1(x,y)
z = x + y;
% other stuff
end
Otherwise, don't request an output within the loop
parfor ii = 1:2
funcs{ii}(arguments{ii,:});
end

Why is my third MATLAB function outputing only zeros when using ode45?

I need to model negative, positive and simple regulation of a gene for my systems biology class using MATLAB. The problem is that the functions for negative and simple regulation work but the positive regulation function is only outputting zeros.
My script is as follows:
% Simulation of simple regulation, negative autoregulation and positive
% autoregulation
% Define constants
global a b K n
a = 1;
b = 1;
K = 0.5;
n = 2; % Hill coefficient
% Simulation time
tspan = [0,10];
% Initial condition
X0 = 0;
% Run simulations
[t1,X1] = ode45(#autoregulation_f0,tspan,X0); % Simple regulation
[t2,X2] = ode45(#autoregulation_f1,tspan,X0); % Negative autoregulation
[t3,X3] = ode23(#autoregulation_f2,tspan,X0); % Positive autoregulation
% Plot results
figure;
plot(t1,X1,t2,X2,t3,X3);
legend('simple','negative','Location','southeast');
And my functions are:
function dxdt = autoregulation_f0(t,X)
global a b
dxdt = b - a*X;
end
function dxdt = autoregulation_f1(t,X)
global a b K n
dxdt = b/(1+(X^n)/(K^n)) - a*X;
end
function dxdt = autoregulation_f2(t,X)
global a b K n
dxdt = b*X.^n./(K.^n+X.^n) + a*X;
end
The third function "autoregulation_f2(t,X)" is the one that outputs zeros and therefore when plotting the graph I just get a straight line.
Does anyone know what could be causing this?
Thanks in advance!
It looks to be the correct result for the given function. Your provided dxdt has an X in every term. The initial X0=0 will result in dxdt=0, giving you no change in X. As a result you just end up with a flat line.

Integration of multiple similar functions into one function in Matlab

I have two Matlab functions f=fun1(x) and f=fun2(x,y) which are very alike and I would like to integrate them into a single function f=fun(x,y).
For the first function I have
function f=fun1(x)
N=1000; % Some large number.
for j=1:N
f=x^2;
end
and for the second function
function f=fun2(x,y)
N=1000; % Some large number.
for j=1:N
f=x^2;
f=f+y;
end
. So actually fun1 is sort of a subfunction of fun2. I would like to construct a function f=fun(x,y,method_number) like
function f=fun(x,y,method_number)
N=1000; % Some large number.
for j=1:N
f=x^2; % If method_number==1 run only this command....
f=f+y; % If method_number==2 run also this command.
end
This is just a short simplified example of the problem I want to solve. My real problem is that I have three long functions f=fun1(x,y,z), f=fun2(x,y) and f=fun3(x) with several resemblances and of which fun3 is a subfunction of fun2 and fun2 is a subfunction of fun1 in the same meaning as here above. I do not believe using switch-case or if-else everywhere is an option since N can be very large, which would be inefficient. Furthermore, it would completely destroy the layout of the code.
In your case it seem each of your function have a different number of input argument. If it is the case, the matlab function nargin can detect that and you do not have to specify an additional method parameter.
For example:
function f = fun(x,y,z)
switch nargin
case 1
f = x.^2; %// run only if ONE argument was specified
case 2
f = fun(x) + y; %// run only if TWO arguments were specified
case 3
f = fun(x,y) ./ z ; %// run only if THREE arguments were specified
otherwise
disp('Houston, we have a problem !!') ; %// run if NO or more than 3 arguments were specified
end
You can call f with one argument, two or three without trouble, Matlab will only execute the function corresponding to the proper number of argument.
The function, when passed with 3 arguments, can call on itself to calculate the part with 2 argument (which can call on itself to calculate the part from the first argument).
Case two: If the recursion really cannot be taken out of the loop, the classic if ... then will work:
function f = fun(x,y,z)
if nargin == 3
threeArgs = true ;
twoArgs = true ;
elseif nargin == 2
threeArgs = false ;
twoArgs = true ;
elseif nargin == 1
threeArgs = false ;
twoArgs = false ;
end
for it=1:1e6
f = x.^2; %// If method_number==1 run only this command....
%// ... other computations
if twoArgs
f = f + y ; %// If method_number==2 run also this command.
%// ... other computations
if threeArgs
f = f ./z ; %// If method_number==3 run also this command.
%// ... other computations
end
%// ... other computations only relevant to f(x,y)
end
%// ... other computations only relevant to f(x)
end
This would totally exclude recursion and would insure the minimum number of computation.
Now I realise this looks a bit clumsy code and you asked for a solution without if ... then and switch. Depending on your calculation, there is a method which can avoid any if or switch but may not be practical for all cases.
The idea is to assign an invariant operator to y or z in case they are not called.
Example:
function f = fun(x,y,z)
if nargin < 3 ; z = 1 ; end
if nargin < 2 ; y = 0 ; end
for it=1:1e6
f = x.^2;
%// ... other computations just based on X
f = f + y ; %// This always run, but if "y" wasn't specified, it does not modify the result (f+0=f)
%// ... other computations
f = f ./z ; %// This always run, but if "z" wasn't specified, it does not modify the result (f./1=f)
%// ... other computations
end
This avoid any flow branch in the code but i would only keep this method for simple cases, because the computations are always done regardless of the case (although may be some JIT compiler are smart enough to not bother doing 'no effect' operations).
You can avoid checking for the number of input arguments nargin N-times by duplicating code. You will check once, which computation should be done and repeat it N times. In this example, the for-loop is the duplicated code. To some extent, this might be okay.
function f = fun(x, y, z)
N = 1000;
switch nargin
%// Do something if only x is given
case 1
for j = 1:N
f = x.^2;
end
%// Do something else if only x and y are given
case 2
for j = 1:N
f = x.^2 + y;
end
%// Do something else if x, y and z are given
case 3
for j = 1:N
f = x.^2 + y - z;
end
otherwise
error('Use fun.m with 1, 2 or 3 arguments only!');
end
end
This is a variation of Hoki`s answer. In fact, I started from it adding the for-loop and removing the recursive function calls by adding duplicated code.

Differentiation from FFT finding extrema

I'm trying to find zeros of a function. See my code below.
Because fft expects a numerical array, I didn't define the symbolic function to use fzero.
However, this approach is not accurate and depend on step. Do you have a better idea?
step=2000;
x=0:pi/step:2*pi;
y= 4+5*cos(10*x)+20*cos(40*x)+cos(100*x);
fy = fft(y');
fy(1:8) =0;
fy(12:end-10)=0;
fy(end-6:end)=0;
ffy = ifft(fy);
t=diff(ffy);
x=0:pi/step:2*pi-pi/step;
plot(x,t)
indices= find(t<5e-4 & t>-5e-4);
You could proceed along the array t and look for points where the values change sign. That would indicate the presence of a zero.
Actaully, MATLAB's fzero function uses a similar method. You said you didn't use it because you required an array, rather than an anonymous function, but you could convert the array into an anonymous function using simple linear interpolation like so:
func = #(k) interp1(x,t,k); % value of t(x) interpolated at x=k
fzero(func,initial_value);
EDIT : Just to clarify what I mean. If you have an array t and you want to find its zeros...
f = 5; % frequency of wave in Hz
x = 0:0.01:1; % time index
t = cos( 2*pi*f*x ); % cosine wave of frequency f
zeroList = []; % start with an empty list of zeros
for i = 2:length(t) % loop through the array t
current_t = t(i); % current value of t
previous_t = t(i-1); % previous value of t
if current_t == 0 % the case where the zero is exact
newZero = x(i);
zeroList = [zeroList,newZero];
elseif current_t*previous_t < 0 % a and b have opposite sign if a*b is -ve
% do a linear interpolation to find the zero (solve y=mx+b)
slope = (current_t-previous_t)/(x(i)-x(i-1));
newZero = x(i) - current_t/slope;
zeroList = [zeroList,newZero];
end
end
figure(1); hold on;
axis([ min(x) max(x) -(max(abs(t))) (max(abs(t))) ]);
plot(x,t,'b');
plot(x,zeros(length(x)),'k-.');
scatter(zeroList,zeros(size(zeroList)),'ro');
The zeros I get are correct:

how to output all the iteration results from a FOR loop into matrix and plot the graph

I have two for loops in a nested format. My second loop calculates the final equation. The display of the result is outside the second loop in order to display when the second loop is complete.
Below is the logic I used in MATLAB. I need to plot graph of eqn2 vs x.
L=100
for x=1:10
eqn1
for y=1:L
eqn2
end
value = num2strn eqn2
disp value
end
Currently the problem I am facing is that value or output of eqn2 is always replaced after each cycle until x reaches 10. Hence, the workspace table of eqn2 and value only shows the last value. My intention is to document all the output values of value in every cycle of x from 1:10.
How can I do this?
You pseudo-coded a little too strongly for my taste - I have tried to reconstruct what you were trying to do. If I understood correctly, this should do address your question (store intermediate results from the calculation in array Z):
L=100
z = zeros(L,10);
for x=1:10
% perform some calculations
eqn1
for y=1:L
% perform some more calculations; it is not clear whether the result of
% this loop over y=1:L yields one value, or L. I am going to assume L values
z(y, x) = eqn2(x, y)
end
value =num2strn eqn2
disp value
end
% now you have the value of each evaluation of the innermost loop available. You can plot it as follows:
figure;
plot( x, z); % multiple plots with a common x parameter; may need to use Z' (transpose)...
title 'this is my plot';
xlabel 'this is the x axis';
ylabel 'this is the y axis';
As for the other questions you asked in your comments, you could probably findd inspiration in the following:
L = 100;
nx = 20; ny = 99; % I am choosing how many x and y values to test
Z = zeros(ny, nx); % allocate space for the results
x = linspace(0, 10, nx); % x and y don't need to be integers
y = linspace(1, L, ny);
myFlag = 0; % flag can be used for breaking out of both loops
for xi = 1:nx % xi and yi are integers
for yi = 1:ny
% evaluate "some function" of x(xi) and y(yi)
% note that these are not constrained to be integers
Z(yi, xi) = (x(xi)-4).^2 + 3*(y(yi)-5).^2+2;
% the break condition you were asking for
if Z(yi, xi) < 5
fprintf(1, 'Z less than 5 with x=%.1f and y=%.1f\n', x(xi), y(yi));
myFlag = 1; % set flag so we break out of both loops
break
end
end
if myFlag==1, break; end % break out of the outer loop as well
end
This may not be what you had in mind - I cannot understand "run the loop untill all the values of z(y,x) <5 and then it should output x". If you run the outer loop to completion (that's the only way you know "all the values of z(y,x)" then your value of x will be the last value it was... This is why I was suggesting running through all values of x and y, collecting the whole matrix Z, and then examining Z for the things you want.
For example, if you wonder if there is a value for X for which all Z < 5, you could do this (if you didn't break out of the for loops):
highestZ = max(Z, [], 1); % "take the highest value of Z in the 1 dimension
fprintf(1, 'Z is always < 5 for x = %d\n', x(highestZ<5));
etc.
If you can't figure it out from here, I give up...