How to pass the value of an array to a mathematical function in Matlab? - matlab

I have a defined mathematical function: f =Inline('x1^2+x2^2+2*x1*x2','x1','x2')
and I have an array that represents the number value of x1 and x2. (e.g. the array is A=[1 2])
I want to automate the process of getting the f(x1,x2), but I couldn't figure out the right way that Matlab can take in the array and assign values to x1 and x2.
What can I do to pass in the array values to the mathematical model and get the function value?

You should be using anonymous functions instead of inline since inline will be removed in a future release of MATLAB.
Example (from the docs):
sqr = #(x) x.^2;
a = sqr(5)
a =
25
In your case:
f = #(x) x(1)^2+x(2)^2+2*x(1)*x(2);
Now it expects x to be a two (or more) value array.
A = [1 2];
f(A) =
9
Note:
I don't have MATLAB on my home computer so I haven't actually tested this but it should get you going in the right direction. Have a look over the docs and you'll be fine.

Related

How to assign values to variables in a handle function?

This is simplified but take as an example the following MATLAB function handle:
F = #(x)[x(1)-x(2);x(2)-x(3)]
The system has of course has many solutions. Is it possible to obtain a solution for a function like this one after substituting at least one variable? For example, substituting x(3)=1 the function would become:
G = #(x)[x(1)-x(2);x(2)-1]
And a solution for the other variables can be obtained. I use fsolve and it works quite well for the system of equations I have. Of course what I need to do can be done using the Symbolic Toolbox, but calling it in a big for loop makes it too slow to use for my code.
I'm trying to come up with some code that can return G given F and a set of indices in x to replace with given values.
What you're basically asking to do is have G call F with values in x reassigned based on a logical replacement index index and a set of replacement values values, which is doable but messy since anonymous functions can only have a single executable statement.
The solution is similar to what is done in this answer, but instead of using the functional form for subscripted reference we'll need to use the functional form for subscripted assignment: subsasgn. Here's what it would look like:
F = #(x)[x(1)-x(2); x(2)-x(3)];
values = [3 2 1];
index = logical([0 0 1]);
G = #(x) F(subsasgn(x, struct('type', '()', 'subs', {{index}}), values(index)));
And here's a test:
>> F([3 2 3])
ans =
1
-1
>> F([3 2 1]) % Replace the last element by 1
ans =
1
1
>> G([3 2 3]) % G handles replacing the last element by 1
ans =
1
1

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.

How to take elements of a Matrix and use each one as Input-Variable for the same function?

I have given a matrix with 485x1 elements. MatLab shall take the first 12 of them and make them a new matrix.
Then I have a variable named C and a function f(C).
MatLab shall take the first element of the new matrix and make it C. Then it shall perform f(C) and save the result as result1.
Then it should take the second element of the new matrix and make it C. Then it shall perform f(C) again and save the result as result2 and so on.
So in the end I need 12 result variables.
How can I program this?
This is question asks for very basic stuff. Like adressing the first 12 elements of a matrix. You might want to consider reading a few FAQs.
However a basic solution can look like this:
M = [1:485]'; %// a 485x1 matrix (vector)
newMatrix = M(1:12); %// newMatrix contains the first 12 elements of M (also vector)
result = cell(1,12); %// result as a cell
f = #(x) x+1; % a function f
for i = 1:12
C = newMatrix(i); % get each value from newMatrix, call it C
result{i} = f(C); % apply f() on c and store the result
end
It is not a good idea to generate variables result1, result2, ..., result12, you can read more about it here. Better use a cell for storing the variables, you can then adress the i-th result as result{i}.

matlab constant anonymous function returns only one value instead of an array

I've been searching the net for a couple of mornings and found nothing, hope you can help.
I have an anonymous function like this
f = #(x,y) [sin(2*pi*x).*cos(2*pi*y), cos(2*pi*x).*sin(2*pi*y)];
that needs to be evaluated on an array of points, something like
x = 0:0.1:1;
y = 0:0.1:1;
w = f(x',y');
Now, in the above example everything works fine, the result w is a 11x2 matrix with in each row the correct value f(x(i), y(i)).
The problem comes when I change my function to have constant values:
f = #(x,y) [0, 1];
Now, even with array inputs like before, I only get out a 1x2 array like w = [0,1];
while of course I want to have the same structure as before, i.e. a 11x2 matrix.
I have no idea why Matlab is doing this...
EDIT 1
Sorry, I thought it was pretty clear from what I wrote in the original question, but I see some of you asking, so here is a clarification: what I want is to have again a 11x2 matrix, since I am feeding the function with arrays with 11 elements.
This means I expect to have an output exactly like in the first example, just with changed values in it: a matrix with 11 rows and 2 columns, with only values 0 in the first column and only values 1 in the second, since for all x(i) and y(i) the answer should be the vector [0,1].
It means I expect to have:
w = [0 1
0 1
0 1
...
0 1]
seems pretty natural to me...
You are defining a function f = #(x,y) [0, 1]; which has the input parameters x,y and the output [0,1]. What else do you expect to happen?
Update:
This should match your description:
g=#(x,y)[zeros(size(x)),ones(size(y))]
g(x',y')
Defining an anonymous function f as
f = #(x,y) [0,1];
naturally returns [0,1] for any inputs x and y regardless of the length of those vectors.
This behavior puzzled me also until I realized that I expected f(a,b) to loop over a and b as if I had written
for inc = 1:length(a)
f(a(inc), b(inc))
end
However, f(a,b) does not loop over the length of its inputs, so it merely returns [0,1] regardless of the length of a and b.
The desired behavior can be obtained by defining f as
g=#(x,y)[zeros(size(x)),ones(size(y))]
as Daniel stated in his answer.

MATLAB: Test if anonymous vector is a subset of R^n

I'm trying to use MatLab code as a way to learn math as a programmer.
So reading I'm this post about subspaces and trying to build some simple matlab functions that do it for me.
Here is how far I got:
function performSubspaceTest(subset, numArgs)
% Just a quick and dirty function to perform subspace test on a vector(subset)
%
% INPUT
% subset is the anonymous function that defines the vector
% numArgs is the the number of argument that subset takes
% Author: Lasse Nørfeldt (Norfeldt)
% Date: 2012-05-30
% License: http://creativecommons.org/licenses/by-sa/3.0/
if numArgs == 1
subspaceTest = #(subset) single(rref(subset(rand)+subset(rand))) ...
== single(rref(rand*subset(rand)));
elseif numArgs == 2
subspaceTest = #(subset) single(rref(subset(rand,rand)+subset(rand,rand))) ...
== single(rref(rand*subset(rand,rand)));
end
% rand just gives a random number. Converting to single avoids round off
% errors.
% Know that the code can crash if numArgs isn't given or bigger than 2.
outcome = subspaceTest(subset);
if outcome == true
display(['subset IS a subspace of R^' num2str(size(outcome,2))])
else
display(['subset is NOT a subspace of R^' num2str(size(outcome,2))])
end
And these are the subset that I'm testing
%% Checking for subspaces
V = #(x) [x, 3*x]
performSubspaceTest(V, 1)
A = #(x) [x, 3*x+1]
performSubspaceTest(A, 1)
B = #(x) [x, x^2, x^3]
performSubspaceTest(B, 1)
C = #(x1, x3) [x1, 0, x3, -5*x1]
performSubspaceTest(C, 2)
running the code gives me this
V =
#(x)[x,3*x]
subset IS a subspace of R^2
A =
#(x)[x,3*x+1]
subset is NOT a subspace of R^2
B =
#(x)[x,x^2,x^3]
subset is NOT a subspace of R^3
C =
#(x1,x3)[x1,0,x3,-5*x1]
subset is NOT a subspace of R^4
The C is not working (only works if it only accepts one arg).
I know that my solution for numArgs is not optimal - but it was what I could come up with at the current moment..
Are there any way to optimize this code so C will work properly and perhaps avoid the elseif statments for more than 2 args..?
PS: I couldn't seem to find a build-in matlab function that does the hole thing for me..
Here's one approach. It tests if a given function represents a linear subspace or not. Technically it is only a probabilistic test, but the chance of it failing is vanishingly small.
First, we define a nice abstraction. This higher order function takes a function as its first argument, and applies the function to every row of the matrix x. This allows us to test many arguments to func at the same time.
function y = apply(func,x)
for k = 1:size(x,1)
y(k,:) = func(x(k,:));
end
Now we write the core function. Here func is a function of one argument (presumed to be a vector in R^m) which returns a vector in R^n. We apply func to 100 randomly selected vectors in R^m to get an output matrix. If func represents a linear subspace, then the rank of the output will be less than or equal to m.
function result = isSubspace(func,m)
inputs = rand(100,m);
outputs = apply(func,inputs);
result = rank(outputs) <= m;
Here it is in action. Note that the functions take only a single argument - where you wrote c(x1,x2)=[x1,0,x2] I write c(x) = [x(1),0,x(2)], which is slightly more verbose, but has the advantage that we don't have to mess around with if statements to decide how many arguments our function has - and this works for functions that take input in R^m for any m, not just 1 or 2.
>> v = #(x) [x,3*x]
>> isSubspace(v,1)
ans =
1
>> a = #(x) [x(1),3*x(1)+1]
>> isSubspace(a,1)
ans =
0
>> c = #(x) [x(1),0,x(2),-5*x(1)]
>> isSubspace(c,2)
ans =
1
The solution of not being optimal barely scratches the surface of the problem.
I think you're doing too much at once: rref should not be used and is complicating everything. especially for numArgs greater then 1.
Think it through: [1 0 3 -5] and [3 0 3 -5] are both members of C, but their sum [4 0 6 -10] (which belongs in C) is not linear product of the multiplication of one of the previous vectors (e.g. [2 0 6 -10] ). So all the rref in the world can't fix your problem.
So what can you do instead?
you need to check if
(randn*subset(randn,randn)+randn*subset(randn,randn)))
is a member of C, which, unless I'm mistaken is a difficult problem: Conceptually you need to iterate through every element of the vector and make sure it matches the predetermined condition. Alternatively, you can try to find a set such that C(x1,x2) gives you the right answer. In this case, you can use fminsearch to solve this problem numerically and verify the returned value is within a defined tolerance:
[s,error] = fminsearch(#(x) norm(C(x(1),x(2)) - [2 0 6 -10]),[1 1])
s =
1.999996976386119 6.000035034493023
error =
3.827680714104862e-05
Edit: you need to make sure you can use negative numbers in your multiplication, so don't use rand, but use something else. I changed it to randn.