Here's an example of what I'm looking for:
>> foo = [88, 12];
>> [x, y] = foo;
I'd expect something like this afterwards:
>> x
x =
88
>> y
y =
12
But instead I get errors like:
??? Too many output arguments.
I thought deal() might do it, but it seems to only work on cells.
>> [x, y] = deal(foo{:});
??? Cell contents reference from a non-cell array object.
How do I solve my problem? Must I constantly index by 1 and 2 if I want to deal with them separately?
You don't need deal at all (edit: for Matlab 7.0 or later) and, for your example, you don't need mat2cell; you can use num2cell with no other arguments::
foo = [88, 12];
fooCell = num2cell(foo);
[x y]=fooCell{:}
x =
88
y =
12
If you want to use deal for some other reason, you can:
foo = [88, 12];
fooCell = num2cell(foo);
[x y]=deal(fooCell{:})
x =
88
y =
12
Note that deal accepts a "list" as argument, not a cell array. So the following works as expected:
> [x,y] = deal(88,12)
x = 88
y = 12
The syntax c{:} transforms a cell array in a list, and a list is a comma separated values, like in function arguments. Meaning that you can use the c{:} syntax as argument to other functions than deal. To see that, try the following:
> z = plus(1,2)
z = 3
> c = {1,2};
> z = plus(c{:});
z = 3
To use the num2cell solution in one line, define a helper function list:
function varargout = list(x)
% return matrix elements as separate output arguments
% example: [a1,a2,a3,a4] = list(1:4)
varargout = num2cell(x);
end
What mtrw said. Basically, you want to use deal with a cell array (though deal(88,12) works as well).
Assuming you start with an array foo that is n-by-2, and you want to assign the first column to x and the second to y, you do the following:
foo = [88,12;89,13;90,14];
%# divide the columns of foo into separate cells, i.e. do mat2cell(foo,3,[1,1])
fooCell = mat2cell(foo,size(foo,1),ones(size(foo,2),1));
[x,y] = deal(fooCell{:});
DEAL is really useful, and really confusing. foo needs to be a cell array itself, I believe. The following seems to work in Octave, if I remember correctly it will work in MATLAB as well:
> foo = {88, 12}
foo =
{
[1,1] = 88
[1,2] = 12
}
> [x,y] = deal(foo{:})
x = 88
y = 12
I cannot comment other answers, so separate addition.
you can use deal(88,12) if you are starting from scalars
deal can be used as a one-liner for non-scalars as well, of course if you already have them in separate variables, say:
a = 123;
b = rand(3);
c = {a, b};
d = struct('field','val')
and now you deal them with one line:
>> [x,y,z,w] = deal(a,b,c,d)
x =
123
y =
0.6370 0.2165 0.6711
0.2945 0.8803 0.2705
0.7633 0.1537 0.0767
z =
[123] [3x3 double]
w =
field: 'val'
However, if they are packed in one variable, you can only deal them if they are in a cell or structure array - with deal(X{:}) for cell array and deal(S.field) for structure array. (In the latter case only one field is dealt, but from all structures in array.) With Matlab v.7+ you can use X{:} and S.field without deal, as noted in other answers.
Create a function arr2vars for convenience
function varargout = arr2vars(arr)
% Distribute elements over variables
N = numel(arr);
if nargout ~= N
error('Number of outputs does not match number of elements')
end
for k = 1:N
varargout{k} = arr(k);
end
You can use it then like this
[~,roi] = imcrop(im);
[x,w,y,h] = arr2vars(roi);
You might be looking for
>>> foo = [88, 12];
>>> [x, y] = deal(foo(1), foo(2))
resulting in
x =
88
y =
12
So you have a working one-liner.
There is an easier way.
x = foo (1, 1)
y = foo (1, 2)
Provides
>> x
x =
88
>> y
y =
12
Full documentation at Mathworks.
Related
I am programming commutative hypercomplex number class.
First of all: If that already exist, please tell. I have not found.
PS: Quaternion exists but are not commutative.
I am trying to reproduce all that Matlab can do with real and complex, but with hypercomplex. The solution that I am working on is to define a class. If a more smart method may be used, please tell.
Many codes with complex numbers exist, the idea is to overload smartly to make working all existing program with Hypercomplex. This work might be used by many users.
please see at the end of the post the main maths principle found in Ablamowicz1996 _ Clifford Algebras with Numeric and Symbolic Computations
My Hypercomplex class works for basic operation: I have overloaded the mtimes(a,b) = a*b operation.
For instance, I can do:
A = MyClass(1);
B = MyClass(2);
A*B; % ->that works
As a main problem, for instance in 2D, I would like to be able to use
[A B C].*[D ; E]
while using the element-wise behavior of Matlab, and for any dimension , and with my definition of *. For instance, while dealing with matrices of compatible size but not identical:
A = [1 2 3]; B = [1;2]
Matlab gives
A.*B
ans =
1 2 3
2 4 6
That works also for N dimension when compatible.
How can I overload times(a,b) = a.*b , power, rdivide.. in order to have the element-wise behavior of Matlab?
Here is my Class
classdef Hypercomplex < handle
properties (SetAccess = public, GetAccess = public)
A
end
properties (SetAccess = private, GetAccess = private)
eps,nu,e1,e2
end
methods
function s = Hypercomplex(Z) %% Conctruc
% Z might be real, complex or hypercomplex
if isa(Z,'Hypercomplex') % is HyperComplex
s = Z;
elseif ~isreal(Z) && length(Z) == 1 % is Complex
s = Hypercomplex([real(Z) imag(Z) 0 0]);
elseif isreal(Z) && length(Z) < 5
s.A = zeros(1,4);
for ii = 1:length(Z) % is vecteur
s.A(ii) = Z(ii);
end
end
end
function s = epsnu(s)
s.eps = (s.A(1) - s.A(4)) + 1i*(s.A(2)+s.A(3));
s.nu = (s.A(1) + s.A(4)) + 1i*(s.A(2)-s.A(3));
end
function s = e1e2(s)
s.e1 = Hypercomplex([0.5 0 0 -0.5]);
s.e2 = Hypercomplex([0.5 0 0 0.5]);
end
%% Overload
function out = cos(a)
a.epsnu.e1e2;
out = cos(a.eps)*a.e1 + cos(a.nu)*a.e2;
% I might also do for sin exp sqrt ...
end
function out = mtimes(a,b) % '*'
a = Hypercomplex(a).epsnu;
b = Hypercomplex(b).epsnu;
eps12 = 0.5*(a.eps * b.eps);% produit complex
nu12 = 0.5*(a.nu * b.nu );% produit complex
h1 = Hypercomplex([real(eps12) imag(eps12) imag(eps12) -real(eps12)]);
h2 = Hypercomplex([real(nu12) imag(nu12) -imag(nu12) real(nu12) ]);
out = h1+h2;
end
function out = mrdivide(a,b)
a = Hypercomplex(a);
b = Hypercomplex(b);
out = a * b.inverse;
end
function s = inverse(s)
s = Hypercomplex(s).epsnu.e1e2;
s = 1/(s.eps)*s.e1 + 1/(s.nu)*s.e2;
end
function out = plus(a,b)
a = Hypercomplex(a);
b = Hypercomplex(b);
out = Hypercomplex(a.A + b.A);
end
function out = minus(a,b)
a = Hypercomplex(a);
b = Hypercomplex(b);
out = Hypercomplex(a.A - b.A);
end
end
end
Example i^2 = -1 :
>> Ni = Hypercomplex([0 1 0 0]) ;
>> Ni*Ni
Hypercomplex with properties:
A: [-1 0 0 0]
I would think you need to loop over your arrays, and have a special case where, if for one dimension one of the inputs has size 1 and the other doesn't, then the same element for that array is used. A simple way to accomplish this is to index with (i-1)*step + 1, where step is 0 if the array has size 1, and 1 otherwise.
One thing to note is that, in your overloaded method, indexing doesn't use your custom indexing definition (subsref and subsasgn), but the built-in one.
For example, assuming you only allow 2D arrays of your class:
function C = times(A, B)
szA = size(A);
szB = size(B);
if numel(szA)~=2 || numel(szB)~=2
error('Only 2D arrays are supported')
end
szC = max(szA, szB);
stepA = [matchSizes(szA(1), szC(1)), matchSizes(szA(2), szC(2))];
stepB = [matchSizes(szB(1), szC(1)), matchSizes(szB(2), szC(2))];
C = MyClass.empty(szC);
for jj = 1:szC(2)
for ii = 1:szC(1)
C(ii,jj) = A((ii-1)*stepA(1)+1,(jj-1)*stepA(2)+1) * B((ii-1)*stepB(1)+1,(jj-1)*stepB(2)+1);
end
end
% private helper function, keep in the same file
function step = matchSizes(szIn, szOut)
step = 1;
if szIn ~= szOut
if szIn == 1
step = 0;
else
error('Sizes not compatible')
end
end
NOTE: Code not tested.
NOTE2: This is one of the cases where 0-based indexing is more convenient!
If MyClass has a property val to store numeric values I think (hope) that this should be possible (not tested):
function obj = times(A, B)
r = reshape([A.val], size(A)) .* reshape([B.val], size(B));
obj = arrayfun(#MyClass, r);
end
EDIT (because question is edited):
You can follow two ways to implement array of those numbers:
Array of objects
In this method each object just contains a hypercomplex number. It is the way that you have tried. As #CrisLuengo pointed out you can use loops to create the desired result or you can use a combination of vectorization and use of functions like arrayfun and cellfun. You need to know how to work with cell arrays and comma separated list and be familiar with verctorization operations like implicit expansion. Here I implemented plus and epsnu using vectorization and cellfun. They can work with both scalar and object arrays:
function out = plus(a,b)
a = Hypercomplex(a);
b = Hypercomplex(b);
AA = reshape([a.A], [4, size(a)]);
BB = reshape([b.A], [4, size(b)]])
CC = AA + BB;
A1 = reshape()
out = cellfun(#Hypercomplex, num2cell(reshape(CC, 4, []).', 2));
end
function s = epsnu(s)
AA = reshape([s.A], 4, []);
eps = num2cell(AA(1, :) - AA(4, :) + 1i.*(AA(2, :) + AA(3, :)));
nu = num2cell(AA(1, :) + AA(4, :) + 1i.*(AA(2, :) - AA(3, :)));
[s.eps] = eps{:};
[s.nu] = nu{:};
end
Object containing array of numbers
Instead of defining A as a [4 x 1] array you can define each coordinate (x,y,z,et) as a separate property of class each can contain array of numbers. you need to overload the cat operator to concatenate objects. As a result no object array is created but the underlying verctors are concatenated. You need tooverload subsref and subsasgn if you want to simulate element access. I think this method is simpler to implement than the first method.
I was wondering how to call a function handle with an vector of inputs - rather than the list of aguments.
So if I have a function handle which is defined: (I guess it will be clear that I am working on fitting functions here)
fitFunctionHandle = #(a1, wG1, x1,a2, wG2, x2, c, x)(FitGaussianFn(x, [a1, 0, wG1, x1]) +FitGaussianFn(x, [a2, 0, wG2, x2]) + c
And I have an vector of inputs to hand to it
a1Init = 1
wG1Init = 2
x1Init = 3
a2Init = 4
wG2Init = 5
x2Init = 6
a2Init = 7
x = 8
%startPoint = [a1Init, wG1, x1,a2, wG2, x2, c]
inputArray = [a1Init, wG1, x1,a2, wG2, x2, c, x]
How do I call it with the vector startPoint as the input. If I try (for example)
>> fitFunctionHandle(inputArray)
I get an error:
Not enough input arguments.
That makes sense since it is expecting 8 inputs rather than a 8 element vector - but I'm wondering whether there is a way of calling it like that. I think for example in python you can convert an array to a list or something.
I'm aware that I could simplify things in this example case where I have a list of known inputs so I could just do:
fitFunctionHandle(a1Init, wG1, x1,a2, wG2, x2, c, x)
or
fitFunctionHandle(inputArray(1),inputArray(2),inputArray(3,inputArray(4), inputArray(5), inputArray(6),inputArray(7),inputArray(8))
BUT! I guess I'm trying to allow for expansion where I don't know how many arguments there would be.
For bonus points (again since I'm working on fitting functions) - It would be cool to know how to call it when x is a vector as well. I suspect that I would be doing something like
arrayfunc(fitFunctionHandle([startPoint,x]), xVector)
Thanks in advance for your help.
If I understand correctly, you are looking for a way to pass a variable number of input arguments to an anonymous function.
Take a look at this example:
anonymousFunction = #(varargin)(image(varargin{:}));
x = [5 8];
y = [3 6];
C = [0 2 4 6; 8 10 12 14; 16 18 20 22];
input = {C};
anonymousFunction(input{:});
input = {x,y,C};
anonymousFunction(input{:});
You can see in the example that a variable number of inputs is used for calling the anonymous function. Of course, this depends on the actual function that is using the arguments (in this case, image)
Regarding the varargin, the general idea was already presented in UnbearableLightness' answer. I just wanted to address your specific case.
It seems, you want to have some dynamic linear combinations of your FitGaussianFn calls with varying parameters, resulting in some complex function handle. For variable amount of terms, I would recommend to write a separate function to generate the final function handle. I made up a small toy example.
That's my fitFunctionHandle.m function:
function h = fitFunctionHandle(varargin)
n = numel(varargin);
if (n < 2)
error('Not enough input arguments.');
end
% Last input argument is considered t
t = varargin{end};
h = #(x) 0;
for iArg = 1:n-1
a = varargin{iArg}(1);
b = varargin{iArg}(2);
h = #(x) h(x) + (a*sin(b*x+t));
end
end
Each input argument consists of two parameters, that form a sin term. An additional shift parameter t is always passed at last.
And, here's some test script:
% Set up parameters
a1 = 1; b1 = 1;
a2 = 2; b2 = 2;
a3 = 3; b3 = 3;
t = pi/16;
% Evaluation point
x = pi/4;
% Compare results with explicit function calls
h = fitFunctionHandle([a1, b1], t);
res = h(x)
cmp = sin(x+t)
h = fitFunctionHandle([a1, b1], [a2, b2], t);
res = h(x)
cmp = sin(x+t) + 2*sin(2*x+t)
h = fitFunctionHandle([a1, b1], [a2, b2], [a3, b3], t);
res = h(x)
cmp = sin(x+t) + 2*sin(2*x+t) + 3*sin(3*x+t)
You see, it doesn't matter, how many parameter vectors are passed.
The output reveals, that the passed function handles are correct:
res = 0.83147
cmp = 0.83147
res = 2.7930
cmp = 2.7930
res = 4.4598
cmp = 4.4598
Regarding your last question, let's see this test:
% Set up array of t parameters, and get set of function handles
t = [pi/16, pi/8, pi/4];
hh = arrayfun(#(x) fitFunctionHandle([a1, b1], x), t, 'UniformOutput', false);
% Compare results with explicit function calls
for iH = 1:numel(hh)
h = hh{iH};
res = h(x)
cmp = sin(x + t(iH))
end
Here, the t, which is used for all sin terms in fitFunctionHanle, is a vector. The arrayfun call will return a cell array of function handles. Again, the output shows comparable results:
res = 0.83147
cmp = 0.83147
res = 0.92388
cmp = 0.92388
res = 1
cmp = 1
Hope that helps!
I have a simple MATLAB function outputting multiple variables:
function [a,b] = MultipleOutputs()
a = 6;
b = 8;
end
I want to assign the two output variables to 2 certain elements in an existing vector:
x = ones(1,4);
x(2:3) = MultipleOutputs()
However, this gives me:
x =
1 6 6 1
Instead of:
x =
1 6 8 1
I have had this problem in multiple cases, was never able to find the solution.
You have 2 choices:
Concatenate the vectors after outputting them separately
[a,b] = MultipleOutputs();
x = ones(1,4);
x(2:3) = [a,b];
concatenate the vectors before outputting them
function a = MultipleOutputs()
a(1) = 6;
a(2) = 8;
end
x(2:3) = MultipleOutputs();
when you run MultipleOutputs() like that in another function, it only outputs only the first element, which in this case is a.
So eventually your statement x(2:3) = MultipleOutputs() is equivalent to x(2:3) = 6.
A simple fix would be to extract all the elements:
[a,b] = MultipleOutputs();
x(2:3) = [a b];
It has been very difficult to use google, MATLAB documentation, I've spent a few hours, and I cannot learn how to
x = 1
y = x
x = 10
y
ans = 10
what happens instead is:
x = 1
y = x
x = 10
y
ans = 1
The value of x is stored into y. But I want to dynamically update the value of y to equal x.
What operation do I use to do this?
Thanks.M
Matlab is 99% a pass-by-value environment, which is what you have just demonstrated. The 1% which is pass-by-reference is handles, either handle graphics (not relevant here) or handle classes, which are pretty close to what you want.
To use a handle class to do what you describe, put the following into a file call RefValue.
classdef RefValue < handle
properties
data = [];
end
end
This creates a "handle" class, with a single property called "data".
Now you can try:
x = RefValue;
x.data = 1;
y = x;
x.data = 10;
disp(y.data) %Displays 10.
you can try something of the following;
x=10;
y='x'
y
y =
x
eval(y)
x =
10
You can also define an implicit handle on x by defining a function on y and referring to it:
x = 1;
y = #(x) x;
y(x) % displays 1
x = 10;
y(x) % displays 10
In MATLAB, this is not possible. However, there are many ways to get similar behavior. For example, you could have an array a = [1, 5, 3, 1] and then index it by x and y. For x = 2, you could assign a(x) = 7, y = x, and once you change a(x) = 4, a(y) == 4.
So indexing may be the fastest way to emulate references, but if you want some elegant solution, you could go through symbolic variables as #natan points out. What's important to take from this is that there are no pointers in MATLAB.
I have a cell array:
X =
{1x2} {1x2}
X{1} = '' A
X{1 2} = 10 113
I wish to concatenate the sub cells in such a way that
Y = 10 113A
Thanks,
S :-)
y = cellfun(#(a, b) sprintf('%d%s', b, a), x{1}, x{2}, 'UniformOutput', false);
Assuming you have this cell array for X:
X = {{'' 'A'} {10 113}};
You can create your array Y using INT2STR and STRCAT:
Y = strcat(int2str([X{2}{:}].'),X{1}.').';
The Matlab File Exchange has a function written to do precisely this. uniqueRowsCA
For those interested, I think I found a solution.
I redefined my cell array as:
X1 =
{1x2}
X1 = '' 'A'
X2 =
[1x2 double]
X2 = 10 113
I then applied this for loop:
NUM = [];
for i = 1:size(X2') #take the transpose of X2
p = num2str(X2(i)); #convert doubles to strings
str = STRCAT(p, X1(i)); #concatenate
NUM = [NUM str]; #add to another array
end
NUM = '10' '113A'
I am sure there is a more efficient way but MATLAB and I will probably never be on good terms. Sometimes quick and dirty is sufficient!
Cheers,
S :-)