Use of 'ArrayValued' in Matlab numerical integration - matlab

Why when performing numerical integration in Matlab with integral does this case need 'ArrayValued' to be set to true:
f = #(x) 5;
integral(f,0,2,'ArrayValued',true)
... while in this case the option isn't needed?:
f = #(x) x;
integral(f,0,2)

From the documentation for integral describing the integrand argument:
For scalar-valued problems, the function y = fun(x) must accept a
vector argument, x, and return a vector result, y. This generally
means that fun must use array operators instead of matrix operators.
For example, use .* (times) rather than * (mtimes). If you set the
'ArrayValued' option to true, then fun must accept a scalar and return
an array of fixed size.
So, a constant function like f = #(x) 5 does not return a result the same size as x if x is a vector. The integral function requires this because under the hood it is vectorized for scalar functions for performance – it actually evaluates the integrand at multiple points simultaneously with a single function call.
You can make your constant function compliant and not require 'ArrayValued' to be true with something like this:
f = #(x) 5+0*x;
integral(f,0,2)

Related

bsxfun doesn't work as I expect on a constant function

In Matlab R2016a, I have a large set of small X-vectors and Y-vectors which are paired (e.g. 10,000 1x3 X-vectors paired with 10,000 1x3 Y vectors). For each {X,Y} pair, I want to calculate a 2-scalar-argument function for every pairwise combination of the elements in X and Y, (so in my example I would get 10,000 3x3 matrices).
I thought I could use bsxfun to perform these calculations, but it doesn't work when I try to do some simple tests. bsxfun(#(x,y) x*y,[1 2],[1 2]') returns:
ans =
1 2
2 4
Which is what I would expect. However, bsxfun(#(x,y) 1,[1 2],[1 2]') returns:
Error using bsxfun
Specified function handle produces invalid output dimensions. The function handle
must be a binary elementwise function.
Which makes no sense. The function handle is a binary elementwise function that always returns the scalar 1, so bsxfun should give the same result as ones(2,2), unless I'm not understanding how bsxfun works.
The inputs to the function handle that are passed to bsxfun are not scalars. In versions prior to R2016b, the inputs are either scalar or they are the same size.
FUNC can also be a handle to any binary element-wise function not listed
above. A binary element-wise function in the form of C = FUNC(A,B)
accepts arrays A and B of arbitrary but equal size and returns output
of the same size. Each element in the output array C is the result
of an operation on the corresponding elements of A and B only. FUNC must
also support scalar expansion, such that if A or B is a scalar, C is the
result of applying the scalar to every element in the other input array.
In releases since R2016b, they do not have to be equal sizes, but should be compatible sizes
In the example you have shown, the first input to the function handle is a scalar and the second is a vector (y) and the function is evaluated for every element of x and the output is expected to be the size of y
In the case you've posted, the call to bsxfun is essentially the equivalent of:
x = [1 2];
y = [1 2].';
yourfunc = #(x,y)x * y;
for k = 1:numel(x)
output(:,k) = yourfunc(x(k), y)
end
If you want to return a 1 for every entry, you need to replace your function with something that yields the appropriately sized output.
bsxfun(#(x,y)ones(max(size(x), size(y))), [1 2], [1 2]')
How you formulate the function handle really depends upon your specific problem

Get an array of results of a function using as input an array of values (in Matlab)

I want to get the array of results of a function using as input an array of values. The function receives two variables (x1, x2) and a constant x3, so I'm trying to input all combination of it in a range using mesh.
The result is incorrect, I'm missing something.
Sample:
fun = #(x1,x2,x3) (x2-x1^2)^2+(1-x1)^2 + x3;
x3 = 7;
fun2 = #(x) fun(x(1,1),x(1,2),x3);
x0 = [2 3];
min = fminsearch(fun2, x0);
disp(min);
x = min(1)-10:1:min(1)+10;
y = min(2)-10:1:min(2)+10;
[X,Y] = meshgrid(x,y);
% I'm getting strange values here, like z < 0, how it is possible if everything is squared in the function.
Z = fun(X,Y,x3);
It's important to note that there is a difference between matrix and element-wise operations in MATLAB.
Matrix operations are defined via plain operators, such as *, or ^. So for example, A*B performs a matrix multiplication between A and B.
Element-wise operators make use of the dot . before the operator, i.e., .*, .^, and so on. Thus, A.*B performs an element-wise multiplication of A and B. The end result of this operation is an array of the same size as A and B (whose sizes must be equal), where the jj'th element of the array is equal to A(jj)*B(jj).
Now, consider your definition of fun:
fun = #(x1,x2,x3) (x2-x1^2)^2+(1-x1)^2 + x3;
What happens when MATLAB evaluates this expression is that it applies the matrix operations, such as ^ to the input arrays. However, to obtain your desired result of applying the operation to every individual element in your input arrays x1, x2, you should be using element-wise operations.
A new definition
fun = #(x1,x2,x3) (x2-x1.^2).^2+(1-x1).^2 + x3;
should provide the desired result.

Symbolic function for matrices

How to create symbolic function for matrices?
For example, I want to have matrix multiplication
A = sym('A',[5,1])
B = sym('B',[1,5])
f = symfun(A * B,[A, B])
But I have an error because A and B have different dimensions, and I can't use square brackets.
symfun only supports scalar arguments, thus you can only define a symbolic function with 10 scalar arguments:
f = symfun(A * B,[A(:); B(:)])
I recommend to work with the symbolic expression instead and use subs to evaluate:
f=A*B
Further you can also use a function handle:
f=#(a,b)(a*b);
f(A,B)

Refactor a function in MATLAB to accept originally scalar argument as an array

Imagine you have a function in MATLAB of two variables, f(x,y). And it was written in a way that x can be a scalar or a 1D array, but y is strictly meant to be a scalar. For an array x the function returns the array of elements of the same length as x.
Next, you need to refactor this function to accept both x and y to be 1D arrays of equal length, the value of a function f([x1,x1],[y1,y2]) = [f(x1,y1), f(x2,y2)].
How would you do this in the most efficient way?
This is exactly suited for arrayfun:
f = #(x,y) y*x.^2; %an example where y should not be an array, x can
fnew = #(xv,yv) arrayfun(f,xv,yv);
This new function will return f(xv(k),yv(k)) for each k as long as the two arrays are of the same size.
Note that arrayfun is quite slow, so using a loop to the same effect or implementing the vectorization for the specific function f (possibly making use of bsxfun) might be faster.
The explicit looping alternative would be
function fv=fnew(xv,yv)
if numel(xv)~=numel(yv)
exit('fnew> xv and yv should have same length');
end
fv=zeros(size(xv));
for k=1:numel(xv)
fv(k) = f(xv(k),yv(k));
end
You can spare some runtime by skipping the size check, similar checks are the reason why arrayfun tends to be slower.

Use fminsearch to find local minimizer and the minima at that value

I am having trouble using fminsearch: getting the error that there were not enough input arguments for my function.
f = #(x1,x2,x3) x1.^2 + 3.*x2.^2 + 4.*x3.^2 - 2.*x1.*x2 + 5.*x1 + 3.*x2 + 2.*x3;
[x, val] = fminsearch(f,0)
Is there something wrong with my function? I keep getting errors anytime I want to use it as an input function with any other command.
I am having trouble using fminsearch [...]
Stop right there and think some more about the function you're trying to minimize.
Numerical optimization (which is what fminsearch does) is unnecessary, here. Your function is a quadratic function of vector x; in other words, its value at x can be expressed as
x^T A x + b^T x
where matrix A and vector b are defined as follows (using MATLAB notation):
A = [ 1 -1 0;
-1 3 0;
0 0 4]
and
b = [5 3 2].'
Because A is positive definite, your function has one and only one minimum, which can be computed in MATLAB with
x_sol = -0.5 * A \ b;
Now, if you're curious about the cause of the error you ran into, have a look at fuesika's answer; but do without fminsearch whenever you can.
It is exactly what Matlab is telling you: your function expects three arguments. You are passing only one.
Instead of
[x, val] = fminsearch(f,0)
you should call it like
[x, val] = fminsearch(f,[0,0,0])
since you define the function f to accept a three dimensional vector as input only.
You can read more about the specification of fminsearch in the online documentation at http://mathworks.com/help/matlab/ref/fminsearch.html:
x = fminsearch(fun,x0) starts at the point x0 and returns a value x
that is a local minimizer of the function described in fun. x0 can be
a scalar, vector, or matrix. fun is a function_handle.