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.
Related
I defined an inline function f that takes as argument a (1,3) vector
a = [3;0.5;1];
b = 3 ;
f = #(x) x*a+b ;
Suppose I have a matrix X of size (N,3). If I want to apply f to each row of X, I can simply write :
f(X)
I verified that f(X) is a (N,1) vector such that f(X)(i) = f(X(i,:)).
Now, if I a add a quadratic term :
f = #(x) x*A*x' + x*a + b ;
the command f(X) raises an error :
Error using +
Matrix dimensions must agree.
Error in #(x) x*A*x' + x*a + b
I guess Matlab is considering the whole matrix X as the input to f. So it does not create a vector with each row, i, being equal to f(X(i,:)). How can I do it ?
I found out that there exist a built-in function rowfun that could help me, but it seems to be available only in versions r2016 (I have version r2015a)
That is correct, and expected.
MATLAB tries to stay close to mathematical notation, and what you are doing (X*A*X' for A 3×3 and X N×3) is valid math, but not quite what you intend to do -- you'll end up with a N×N matrix, which you cannot add to the N×1 matrix x*a.
The workaround is simple, but ugly:
f_vect = #(x) sum( (x*A).*x, 2 ) + x*a + b;
Now, unless your N is enormous, and you have to do this billions of times every minute of every day, the performance of this is more than acceptable.
Iff however this really and truly is your program's bottleneck, than I'd suggest taking a look at MMX on the File Exchange. Together with permute(), this will allow you to use those fast BLAS/MKL operations to do this calculation, speeding it up a notch.
Note that bsxfun isn't going to work here, because that does not support mtimes() (matrix multiplication).
You can also upgrade to MATLAB R2016b, which will have built-in implicit dimension expansion, presumably also for mtimes() -- but better check, not sure about that one.
When generating C code using MATLAB Coder, the behaviour is different when an if happens in body of another if or in its elsesection. The following case easily creates C code with output having size 5x5:
function y = foo1(u)
if u > 0
y = zeros(2,2);
else
y = zeros(5,5);
end
Now this one works as well
function y = foo2(u,v)
if u > 0
y = zeros(2,2);
else
y = zeros(5,5);
if v > 0
y = 2 * y;
end
end
But this one fails to generate code, complaining about size mismatch:
function y = foo3(u,v)
if u > 0
y = zeros(2,2);
if v > 0
y = 2 * y;
end
else
y = zeros(5,5);
end
Here is the output in command-line:
>> codegen foo1.m -args {0}
>> codegen foo2.m -args {0,0}
>> codegen foo3.m -args {0,0}
??? Size mismatch (size [2 x 2] ~= size [5 x 5]).
The size to the left is the size of the left-hand side of the assignment.
Error in ==> foo3 Line: 8 Column: 5
Code generation failed: Open error report.
Error using codegen (line 144)
I have seen this behaviour in MATLAB R2013b and R2015a.
From the docs, Matlab codegen must know the size of a matrix at compile time unless codegen is told or infers that the matrix is of variable size. There are several ways to let Matlab know a matrix will be of variable size:
Using coder.varsize function, a matrix can be explicitly declared to be of variable size.
MATLAB can infer a matrix is of variable size from the structure of the code.
As your code suggests, option (2) apparently isn't robust. Matlab tries to infer in some cases when there's a simple if else statement, but that inference appears to be quite fragile, as shown by your example.
Rather than rely on MATLAB to correctly infer whether a matrix is variable size, a solution is to make an explicit declaration:
function y = foo3(u,v)
coder.varsize('y', []); % Let codegen know y is variable sized
% and can be arbitrary dimensions
% an alternative is: coder.varsize('y',[5,5]);
if u > 0
y = zeros(2,2);
if v > 0
y = 2 * y;
end
else
y = zeros(5,5);
end
Why might Matlab want to know this information? If a matrix's size is known at compile time, all kinds of additional optimizations may be possible (loop unrolling etc...).
I agree with Matthew Gunn's answer, this is to add some explanation for the behavior. A good mental model to have about how Coder analyzes your MATLAB code is that it looks at it from the top to the bottom.
Applying that mental model, in your first two examples, the assignments which determine sizes of y: y = zeros(2,2) and y = zeros(5,5), occur before the value of y is ever used. So Coder can merge both sizes to automatically make y a variable-sized array. In the third example, the assignment y = zeros(2,2) occurs and then y is used: y = 2 * y. At this point, Coder needs to determine the size and type of the multiplication 2 * y. Only the 2-by-2 assignment is seen so it is inferred that 2 * y must also return a 2-by-2 matrix.
Performing this inference then embeds the assumption that y is 2-by-2 into the code and essentially locks the size of y so that the subsequent assignment to y with a 5-by-5 matrix must fail.
I need help to add a function, from 1 to 10, using MATLAB. The function is ((1/n)*sin(n*pi*x)) where n goes from 1 to 10 and x stays as a variable. Ultimately I want to have a summation of ten sines (i.e K1*sin(pi*x)+K2*sin(2*pi*x)+k3*sin(3*pi*x)+...etc) where k is a constant. I would really appreciate any assistance. Thanks
Edit: Thanks to everyone who helped with my problem However I should have been more specific when asking my question. After getting the summation, I want to plot the sine series. I tried doing this but I kept getting an error saying that "conversion from sym to double is not possible" Now I tried doing a for loop to get my graph. My code is as follows:
n = 0:10;
while i <= n
for i = 1:length(n);
T = (1/n(i))*sin(n(i)*pi*x);
end
i = 1+i;
max = sum(T);
end
plot(x,max,'black')
However this doesn't work. I don't think that this is the proper way to get the sum of a double. I would really appreciate it if someone could help me again. Thanks again
Learn to exploit MATLAB's vector nature.
For one-off shots:
>> f = #(n,x) sin((1:n)*pi*x) * (1./(1:n).');
>> f(200, 0.5)
ans =
7.828982258896381e-001
To be able to evaluate f(n,x) with vector/matrix input x:
>> f = #(n,x) reshape( sin( bsxfun(#times, (1:n)*pi, x(:)) ) * (1./(1:n).'), size(x) );
>> f(15,rand(2))
ans =
5.077194963950054e-001 2.660834723822258e-001
1.416130930552744e+000 1.012255979042172e-001
Replace (1./(1:n).') by [K1 K2 K3 ...].' when you want to use other constants than 1/n.
From my understanding you are trying to sum the multivariable expression. In your case, you have two variables n and x. You want to sum the expression from n = 1 to 10 keeping x as a variable. You can do this in MATLAB by using symsum function, whose syntax is
symsum(expr,var,a,b)
Where expression expr defines the terms of a series, with respect to the symbolic variable var. The value of the variable var changes from a to b. If you do not specify the variable, symsum uses the default variable determined by symvar. If expr is a constant, then the default variable is x.
So in your case
expr = (1/n*sin(n*pi*x)
var = n
a = 1
b = 10
The simple code would be
>>syms n x
>>F = symsum ((1/sym('n'))*sin(sym('n')*pi*x), n, 1, 10)
Answer to Edit: MATLAB cannot convert the sys variable to double. You can instead substitute the value of sym variable with variable from MATLAB workspace. For example you can plot the above function for the range 0 to 10 by using following command.
>> x = 0:0.1:10;
>> plot(x, subs(F))
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.
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.