How to determine the size of an input argument for a function handle - matlab

I am creating a function that takes in data (x,y,z) and an anonymous function (M) as inputs. M's inputs are data (x,y,z) and a parameter (theta).
I need to determine the dimension of the parameter theta inside FUNC
EDIT: (To add some context)
I have data that follows a known data generating process (DGP). For example, I can generate data using a linear instrumental variable DGP with 1 endogenous variable (hence theta will be dimension 1):
n = 100; q = 10;
theta0 = 1; % true param value
e = randn(n, 1); % 2nd stage error
u = randn(n, 1); % 1st stage error
z = randn(n, q); % instrument
x = z * ones(q, 1) + u; % endog variable
y = x * theta0 + e; % dependent variable
Then I want to estimate theta0 using my own variation of generalized linear methods (FUNC)
M = #(x,y,z,theta) z' * (y - x * theta); % moment condition
thetahat = FUNC(M, x, y, z); % estimate theta0
and FUNC.m is
function out = FUNC(M, x, y, z)
k = ; % (!!!) <-- this is what I need to find out!
objFunc = #(theta) M(x, y, z, theta)' * M(x, y, z, theta);
out = fminunc(objFunc, ones(1, k)); % <-- this is where its used
end
In the above example, the DGP is a linear IV model. However, I should be able to use my function for any other DGP.
Other DGPs could, for example, define M as follows:
% E.g. 1) theta is dimension 1
M=#(x,y,z,theta) z' * (y - x * theta);
% E.g. 2) theta is dimension 2
M=#(x,y,z,theta) z' * (y - (x * theta(1))^theta(2));
% E.g. 3) theta is dimension 3
M=#(x,y,z,theta) z' * (y - (theta(1) + x * theta(2))^theta(3));
The (super bad) hack that I am currently using for (!!!) is:
for ktest = [3,2,1] % the dimension of theta will never be higher than 3
try
M(x, y, z, ones(1, ktest);
k = ktest;
end
end

Since you know already what the form and requirements of your function M will be when you pass it to FUNC, it doesn't make much sense to then require FUNC to determine it based only on M. It would make much more sense to pass flag values or needed information to FUNC when you pass it M. I would write FUNC in one of two ways:
function out = FUNC(M, x, y, z, k) % Accept k as an argument
...
end
function out = FUNC(M, x, y, z, theta0) % Pass the initial guess, of the correct size
...
end
If you really want to let FUNC do the extra work, then the answer from excaza is how I would do it.
Old answer below. not really valid since the question was clarified, but I'm leaving it temporarily...
I think you have two better options here...
Make M a cell array of anonymous functions:
You could make your input M a cell array of possible anonymous functions and use the number of values in theta as the index. You would pass this M to FUNC:
M = {#(x,y,z,theta) z' * (y - x * theta), ...
#(x,y,z,theta) z' * (y - (x * theta(1))^theta(2)), ...
#(x,y,z,theta) z' * (y - (theta(1) + x * theta(2))^theta(3))};
Then somewhere inside FUNC:
out = M{numel(theta)}(x, y, z, theta);
Make M a normal function instead of an anonymous one:
An anonymous function is good for quick, simple formulas. Add in conditional logic and you should probably just make it a fully-fledged function. Here's an example with a switch statement (good for if you have a number of different formulas):
function out = M(x, y, x, theta)
switch numel(theta)
case 1
out = z' * (y - x * theta);
case 2
out = z' * (y - (x * theta(1))^theta(2));
case 3
out = z' * (y - (theta(1) + x * theta(2))^theta(3));
end
end
And here's an example that sets some defaults for parameters (good for if you have one formula with different ways to set its parameters, like you seem to have):
function out = M(x, y, x, theta)
switch numel(theta)
case 1
p1 = 0;
p2 = theta;
p3 = 1;
case 2
p1 = 0;
p2 = theta(1);
p3 = theta(2);
case 3
p1 = theta(1);
p2 = theta(2);
p3 = theta(3);
end
out = z' * (y - (p1 + x * p2)^p3);
end

MATLAB doesn't store any information about the size of the inputs to an anonymous function. While a better idea would be to modify your code so you don't have to do these kinds of gymnastics, if your function definition is known to fit a narrow band of possibilities you could use a regular expression to parse the function definition itself. You can get this string from the return of functions.
For example:
function [nelements] = findsizetheta(fh)
defstr = func2str(fh);
test = regexp(defstr, 'theta\((\d+)\)', 'tokens');
if isempty(test)
% Assume we have theta instead of theta(1)
nelements = 1;
else
nelements = max(str2double([test{:}]));
end
end
Which returns 1, 2, and 3 for your example definitions of M.
This assumes that theta is present in you anonymous function and that it is defined as a vector.
Also note that MATLAB cautions against utilizing functions in a programmatic manner, as its behavior may change in future releases. This was tested to function in R2017b.

Related

MATLAB error using fzero function to solve the loop

My following code generates the plot of V and D values in figure 1. In the graph, the parabolas and straigh lines intersect, and I need to find the roots from the plot from a loop. So I tried to use fzero function, but the error appeared:
Operands to the logical AND (&&) and OR (||) operators must be convertible to logical scalar values. Use the ANY or ALL functions to reduce operands to logical scalar values.
Error in fzero (line 326)
elseif ~isfinite(fx) || ~isreal(fx)
Error in HW1 (line 35)
x=fzero(fun,1);
My code is:
clear all; close all
W = 10000; %[N]
S = 40; %[m^2]
AR = 7;
cd0 = 0.01;
k = 1 / pi / AR;
clalpha = 2*pi;
Tsl=800;
figure(1);hold on; xlabel('V');ylabel('D')
for h=0:1:8;
i=0;
for alpha = 1:0.25:12
i=i+1;
rho(i)=1.2*exp(-h/10.4);
cl(i) = clalpha * alpha * pi/180;
V(i) = sqrt(2*W/rho(i)/S/cl(i));
L(i) = 0.5 * rho(i) * V(i) * V(i) * S * cl(i);
cd(i) = cd0 + k * cl(i) * cl(i);
D(i) = 0.5 * rho(i) * V(i) * V(i) * S * cd(i);
clcd(i) = cl(i)/cd(i);
p(i) = D(i)*V(i);
ang(i) = alpha;
T(i)=Tsl*(rho(i)/1.2).^0.75;
end
figure(1); plot(V,D); hold on
plot(V,T);
end
fun = #(V) 0.5*V.*V.*rho.*S.*cd-T;
x=fzero(fun,1);
Probably, I should not use the fzero function, but the task is to find the roots of V from a plot (figure 1). There are parabolas and straight lines respectively.
From the documentation for fzero(fun,x)
fun: Function to solve, specified as a handle to a scalar-valued function or the name of such a function. fun accepts a scalar x and returns a scalar fun(x).
Your function does not return a scalar value for a scalar input, it always returns a vector which is not valid for a function which is being used with fzero.
1.- Your codes doesn't plot V and D: Your code plots D(V) and T(V)
2.- T is completely flat, despite taking part in the inner for loop calculations with T(i)=Tsl*(rho(i)/1.2).^0.75; as it had to be somehow modified.
But in fact it remains constant for all samples of V, constant temperature (°C ?), and for all laps of the outer for loop sweeping variable h within [0:1:8].
The produced T(V) functions are the flat lines.
3.- Then you try building a 3rd function f that you put as if f(V) only but in fact it's f(V,T) with the right hand side of the function with a numerical expression, without a symbolic expression, the symbolic expression that fzero expects to attempt zero solving.
In MATLAB Zero finding has to be done either symbolically or numerically.
A symbolic zero-finding function like fzero doesn't work with numerical expressions like the ones you have calculated throughout the 2 loops for h and for alpha .
Examples of function expressions solvable by fzero :
3.1.-
fun = #(x)sin(cosh(x));
x0 = 1;
options = optimset('PlotFcns',{#optimplotx,#optimplotfval});
x = fzero(fun,x0,options)
3.2.-
fun = #sin; % function
x0 = 3; % initial point
x = fzero(fun,x0)
3.3.- put the following 3 lines in a separate file, call this file f.m
function y = f(x)
y = x.^3 - 2*x - 5;
and solve
fun = #f; % function
x0 = 2; % initial point
z = fzero(fun,x0)
3.4.- fzeros can solve parametrically
myfun = #(x,c) cos(c*x); % parameterized function
c = 2; % parameter
fun = #(x) myfun(x,c); % function of x alone
x = fzero(fun,0.1)
4.- So since you have already done all the numerical calculations and no symbolic expression is supplied, it's reasonable to solve numerically, not symbolically.
To this purpose there's a really useful function called intersections.m written by Douglas Schwarz available here
clear all; close all;clc
W = 10000; %[N]
S = 40; %[m^2]
AR = 7;
cd0 = 0.01;
k = 1 / pi / AR;
clalpha = 2*pi;
Tsl=800;
figure(1);
ax1=gca
hold(ax1,'on');xlabel(ax1,'V');ylabel(ax1,'D');grid(ax1,'on');
title(ax1,'1st graph');
reczeros={}
for h=0:1:8;
i=0;
for alpha = 1:0.25:12
i=i+1;
rho(i)=1.2*exp(-h/10.4);
cl(i) = clalpha * alpha * pi/180;
V(i) = sqrt(2*W/rho(i)/S/cl(i));
L(i) = 0.5 * rho(i) * V(i) * V(i) * S * cl(i);
cd(i) = cd0 + k * cl(i) * cl(i);
D(i) = 0.5 * rho(i) * V(i) * V(i) * S * cd(i);
clcd(i) = cl(i)/cd(i);
p(i) = D(i)*V(i);
ang(i) = alpha;
T(i)=Tsl*(rho(i)/1.2).^0.75;
end
plot(ax1,V,D); hold(ax1,'on');
plot(ax1,V,T);
[x0,y0]=intersections(V,D,V,T,'robust');
reczeros=[reczeros [x0 y0]];
for k1=1:1:numel(x0)
plot(ax1,x0,y0,'r*');hold(ax1,'on')
end
end
Because at each pair D(V) T(V) there may be no roots, 1 root or more than 1 root, it makes sense to use a cell, reczeros, to store whatever roots obtained.
To read obtained roots in let's say laps 3 and 5:
reczeros{3}
=
55.8850 692.5504
reczeros{5}
=
23.3517 599.5325
55.8657 599.5325
5.- And now the 2nd graph, the function that is defined in a different way as done in the double for loop:
P = 0.5*V.*V.*rho.*S.*cd-T;
figure(2);
ax2=gca
hold(ax2,'on');xlabel(ax2,'V');ylabel(ax2,'P');grid(ax2,'on');
title(ax2,'2nd graph')
plot(ax2,V,P)
plot(ax2,V,T)
[x0,y0]=intersections(V,T,V,P,'robust');
for k1=1:1:numel(x0)
plot(ax2,x0,y0,'r*');hold(ax2,'on')
end
format short
V0=x0
P0=y0
V0 =
86.9993
P0 =
449.2990

How to use matlab to quickly judge whether a function is convex?

For example, FX = x ^ 2 + sin (x)
Just for curiosity, I don't want to use the CVX toolbox to do this.
You can check this within some interval [a,b] by checking if the second derivative is nonnegative. For this you have to define a vector of x-values, find the numerical second derivative and check whether it is not too negative:
a = 0;
b = 1;
margin = 1e-5;
point_count = 100;
f=#(x) x.^2 + sin(x);
x = linspace(a, b, point_count)
is_convex = all(diff(x, 2) > -margin);
Since this is a numerical test, you need to adjust the parameter to the properties of the function, that is if the function does wild things on a small scale we might not be able to pick it up. E.g. with the parameters above the test will falsely report the function f=#(x)sin(99.5*2*pi*x-3) as convex.
clear
syms x real
syms f(x) d(x) d1(x)
f = x^2 + sin(x)
d = diff(f,x,2)==0
d1 = diff(f,x,2)
expSolution = solve(d, x)
if size(expSolution,1) == 0
if eval(subs(d1,x,0))>0
disp("condition 1- the graph is concave upward");
else
disp("condition 2 - the graph is concave download");
end
else
disp("condition 3 -- not certain")
end

I keep getting an error trying implementing midpoint method solving ODE

I am trying to implement Midpoint formulas y[n+1/2] = y[n] + h/2 f (x[n], y[n]) and y[n+1] = y[n] + h *f (x[n] + h/2, y[n + 1/2])
so it solves ODE using midpoint method.
My function is
function [ x, y ] = Midpoint_ODE ( f, xRange, yInitial, numSteps )
% f = name of file with function
% xrange Interval
% x(1) first meaning of x
% x(2) second meaning of x
x=zeros(numSteps+1,1);
x(1) = xRange(1);
h = ( xRange(2) - xRange(1) ) / numSteps; % calculated step size
y(1,:) = transpose(yInitial);
for n = 1 : numSteps
y(n+0.5,:)= (y(n) + (h * 0.5)*(transpose(feval( f, x(n), y(n)))));
y(n+1,:) = y(n,:) + h * transpose(feval(f, x(n)+ (h/2), y(n+0.5,:))); %evaluating the function
end
But I get an error :
**Index in position 1 is invalid. Array indices must be positive integers or logical values.
Error in Midpoint_ODE (line 11)Index in position 1 is invalid. Array indices must be positive integers or logical values.
Error in Midpoint_ODE (line 11)**
I checked it a couple of times, and can't get what's wrong and if I missed some logical piece.
You do not need to keep the half-step value. Thus the easiest is to not have in in the list of values
for n = 1 : numSteps
yhalfstep = (y(n,:) + (h * 0.5)*(transpose(feval( f, x(n), y(n,:)))));
y(n+1,:) = y(n,:) + h * transpose(feval( x(n)+ (h/2), yhalfstep));
end
Also remember that in matlab and similar, a single-index access to a multi-dimensional array gives back the element of the flattened array (column first). That is, in a=[ 1,2;3,4;5,6] you get from a(3) the number 5 as the 3rd element in the first column, while a(3,:) gives the 3rd row [5,6].

How to write/code several functions as one

I am trying to write a line composed of two segments as a single equation in :
y = m1*x + c1 , for x<=x1
y = m2*x + c2 , for x>=x1
My questions are:
How can I write the function of this combined line as a single equation?
How can I write multiple functions (valid in separate regions of a linear parameter space) as a single equation?
Please explain both how to express this mathematically and how to program this in general and in Matlab specifically.
You can write this equation as a single line by using the Heaviside step function, https://en.wikipedia.org/wiki/Heaviside_step_function.
Combining two functions into one:
In fact, what you are trying to do is
f(x) = a(x) (for x < x1)
f(x) = q (for x = x1), where q = a(x1) = b(x1)
f(x) = b(x) (for x > x1)
The (half-maximum) Heaviside function is defined as
H(x) = 0 (for x < 0)
H(x) = 0.5 (for x = 0)
H(x) = 1 (for x > 0)
Hence, your function will be
f(x) = H(x1-x) * a(c) + H(x-x1) * b(x)
and, therefore,
f(x) = H(x1-x) * (m1*x+c1) + H(x-x1) * (m2x+c2)
If you want to implement this, note that many programming languages will allow you to write something like
f(x) = (x<x1)?a(x):b(x)
which means if x<x1, then return value a(x), else return b(x), or in your case:
f(x) = (x<x1)?(m1*x+c1):(m2x+c2)
Matlab implementation:
In Matlab, you can write simple functions such as
a = #(x) m1.*x+c1,
b = #(x) m2.*x+c2,
assuming that you have previously defined m1, m2, and c1, c2.
There are several ways to using/implementing the Heaviside function
If you have the Symbolic Math Toolbox for Matlab, you can directly use heaviside() as a function.
#AndrasDeak (see comments below) pointed out that you can write your own half-maximum Heaviside function H in Matlab by entering
iif = #(varargin) varargin{2 * find([varargin{1:2:end}], 1, 'first')}();
H = #(x) iif(x<0,0,x>0,1,true,0.5);
If you want a continuous function that approximates the Heaviside function, you can use a logistic function H defined as
H = #(x) 1./(1+exp(-100.*x));
Independently of your implementation of the Heaviside function H, you can, create a one-liner in the following way (I am using x1=0 for simplicity) :
a = #(x) 2.*x + 3;
b = #(x) -1.5.*x + 3;
Which allows you to write your original function as a one-liner:
f = #(x) H(-x).*a(x) + H(x).*b(x);
You can then plot this function, for example from -10 to 10 by writing plot(-10:10, f(-10:10)) you will get the plot below.
Generalization:
Imagine you have
f(x) = a(x) (for x < x1)
f(x) = q (for x = x1), where q = a(x1) = b(x1)
f(x) = b(x) (for x1 < x < x2)
f(x) = r (for x = x2), where r = b(x2) = c(x2)
f(x) = c(x) (for x2 < x < x3)
f(x) = s (for x = x2), where s = c(x3) = d(x3)
f(x) = d(x) (for x3 < x)
By multiplying Heaviside functions, you can now determine zones where specific functions will be computed.
f(x) = H(x1-x)*a(c) + H(x-x1)*H(x2-x)*b(x) + H(x-x2)*H(x3-x)*c(x) + H(x-x3)*d(x)
PS: just realized that one of the comments above talks about the Heaviside function, too. Kudos to #AndrasDeak .

how to solve a system of Ordinary Differential Equations (ODE's) in Matlab

I have to solve a system of ordinary differential equations of the form:
dx/ds = 1/x * [y* (g + s/y) - a*x*f(x^2,y^2)]
dy/ds = 1/x * [-y * (b + y) * f()] - y/s - c
where x, and y are the variables I need to find out, and s is the independent variable; the rest are constants. I've tried to solve this with ode45 with no success so far:
y = ode45(#yprime, s, [1 1]);
function dyds = yprime(s,y)
global g a v0 d
dyds_1 = 1./y(1) .*(y(2) .* (g + s ./ y(2)) - a .* y(1) .* sqrt(y(1).^2 + (v0 + y(2)).^2));
dyds_2 = - (y(2) .* (v0 + y(2)) .* sqrt(y(1).^2 + (v0 + y(2)).^2))./y(1) - y(2)./s - d;
dyds = [dyds_1; dyds_2];
return
where #yprime has the system of equations. I get the following error message:
YPRIME returns a vector of length 0, but the length of initial
conditions vector is 2. The vector returned by YPRIME and the initial
conditions vector must have the same number of elements.
Any ideas?
thanks
Certainly, you should have a look at your function yprime. Using some simple model that shares the number of differential state variables with your problem, have a look at this example.
function dyds = yprime(s, y)
dyds = zeros(2, 1);
dyds(1) = y(1) + y(2);
dyds(2) = 0.5 * y(1);
end
yprime must return a column vector that holds the values of the two right hand sides. The input argument s can be ignored because your model is time-independent. The example you show is somewhat difficult in that it is not of the form dy/dt = f(t, y). You will have to rearrange your equations as a first step. It will help to rename x into y(1) and y into y(2).
Also, are you sure that your global g a v0 d are not empty? If any one of those variables remains uninitialized, you will be multiplying state variables with an empty matrix, eventually resulting in an empty vector dyds being returned. This can be tested with
assert(~isempty(v0), 'v0 not initialized');
in yprime, or you could employ a debugging breakpoint.
the syntax for ODE solvers is [s y]=ode45(#yprime, [1 10], [2 2])
and you dont need to do elementwise operation in your case i.e. instead of .* just use *