I'd like to compare multiple, 2-dimensional logical variables with each other. I can think of solving this problem with a loop, however I suspect it could be done with inbuilt functions.
Do I need an extra function or can this be achieved using inbuilt functions?
Code:
a=logical(randi([0 1],5,5));
b=logical(randi([0 1],5,5));
c=logical(randi([0 1],5,5));
%d,e,f... etc.
and(a,b,c)
However this gives you an error:
Error using &
Too many input arguments.
Working loop solution:
%example function to solve this
function out=extended_and(varargin)
out=varargin{1};
for ind=2:numel(varargin)
out=out & varargin{ind};
end
end
If a, b, c (d, e, f) are all related, they should be in the same array. Something like:
L(:,:,1)=logical(randi([0 1],5,5));
L(:,:,2)=logical(randi([0 1],5,5));
L(:,:,3)=logical(randi([0 1],5,5));
%L(:,:,4)... etc.
%or, more simply:
% L = logical(randi([0 1], 5, 5, 327)); or however may arrays you want
Then you can use all:
R = all(L, 3);
If you have to have a, b, c, ... you can concatenate them first:
L = cat(3, a, b, c);
Related
I've been trying to plot a graph of function f(x) on interval 0,6. For some reason maple doesn't plot the graph when I use 'f(x)' as an argument. It works fine when I substitute assigned function as an argument. What can be the reason? How can I plot it using 'f(x)' as an argument?
My code is as follows and the error is on the pictures:
mystep:=proc(x,a,b,c)
if x<a
then
b;
else
c;
end if:
end proc:
f(x):=mystep(x,3,-2,7);
plot('f(x)', x=0..6);
enter image description here
Your syntax for creation of the operator (that you hope to assign to f) is incorrect for 1D plaintext input.
Here is the usual syntax for creation of such an operator, and assignment to name f.
restart;
mystep:=proc(x,a,b,c)
if x<a then b; else c; end if:
end proc:
f:=x->mystep(x,3,-2,7);
These should now all work as you expect.
plot('f(x)', x=0..6);
plot(f, 0..6);
plot(x->mystep(x,3,-2,7), 0..6);
In recent versions of Maple the syntax that you used can work in (only) 2D Input mode. But it is a poor syntax to use, since is easily confused with the 1D syntax for assigning into the remember table of an operator (and with even more confusion ensuing). You should avoid ambiguous syntax.
The type of function you have is piecewise-defined function (see this wikipedia page https://en.wikipedia.org/wiki/Piecewise). And in Maple there is already a command for defining this type of a function, piecewise, see its help page for a complete explanation of how to use it. Now for your mysetup, you have a condition x < a, and a value for when this happens, b, and a value for otherwise, c. So you want piecewise( x < a, b, c ). I think it is better to just use this command, but if it is really necessary to define a new procedure, then your mysetup becomes like the following.
mystep := proc(x, a, b, c)
return( piecewise( x < a, b, c ) ):
end proc:
Now for your plot you can use either
plot( piecewise( x < 3, -2, 7 ), x = 0..6 );
or
f(x) := mystep(x, 3, -2, 7);
plot( f(x), x = 0..6);
I have a set of experimental points
Xdata=[xd1 xd2...]
Ydata=[yd1 yd2...]
And a function y=myfunction(xsimul,a,b,c) that indirectly simulates:
Ysimul=[ys1 ys2...]
for a Xsimul=Xdata
By indirectly I mean there is no direct calculation y=Function(x,a,b,c). It is instead obtained within two for loops by minimization of another function g=f(z)(using fminsearch) followed by Ysimul=(g(targetvalue)).
The goal is to fit the simulation to the experimental data and retrieve optimum a, b and c values by a least-squares method.
I can give a good initial guess to the parameters. However having 3 fitting parameters, along with the already big computing time for determining Ysimul makes this problem quite cumbersome.
So what I would like to know is:
Is this problem feasible using functions like lsqcurvefit?
If so, can you provide hints on how to do it?
Just the solution
This is a pretty standard use of lsqnonlin, you just need to get it formatted correctly. That means something like this:
%First, define a function whose inputs are a single vector, and whose
%outputs can be minimized
funToMinimize = #(abc) myfunction(Xdata,abc(1), abc(2), abc(3)) - Ydata;
%Define an initial guess of the values (including the size of the vector)
abcInitial = [0 0 0]; %Or whatever your best guess is
%Then use the nonlinear fit
abcFit = lsqnonlin(funToMinimize , abcInitial);
Demonstration
I obviously can't generate a solution to your myfunction problem, but we can still walk through the important steps.
First, let's define a function to simulate your myfunction, Xdata, and Ydata.
%Define some complicated-ish "myfuction", with inputs that match yours
myfunction = #(xsimul, a, b, c) sqrt(abs(xsimul))*a + sin(xsimul)*b*a^2 + c;
%Define "Xdata"
Xdata = linspace(0,10,100);
%Define "Ydata", note that I'm sneaking in a set of (a, b, c) values here
Ydata = myfunction(Xdata, 1, 2, 3);
Now, let's run the steps in the answer above:
funToMinimize = #(abc) myfunction(Xdata,abc(1), abc(2), abc(3)) - Ydata;
abcInitial = [0 0 0];
abcFit = lsqnonlin(funToMinimize , abcInitial)
The last step should return [1 2 3], matching the (a, b, c) values used to generate Ydata.
I have the following code:
s(i+1)=NRK(Dt*f(tv(i+1),x)+s(i)-x,s(i));
Where NRK=NRK(function , numeric scalar) This was the symbolic implementation, with f=symbolic function, and x a symbolic array of unknowns.
The thing is that working with symbolic expressions can solve the issue, but this goes inside a loop, and symbolic tools slow down suprisingly the performance in a ratio of 100 times! However, anonymous functions do a perfect job.
My try was the following:
h=#([arguments (i.e. a, b, c, ...])Dt*f(t(i+1),[arguments (i.e. a, b, c,...])+s(i)-[a b c ...];
s(i+1)=NRK(#h,s(i));
How can I write these arguments? Is it possible?
You can specify them in the parenthesis:
h = #( a, b, c ) Dt*f( t(ii+1), a, b, c ) + s(ii);
Then call
s(ii+1) = NRK( h, s(ii) );
Some remarks:
- You do not need to write an extra # when providing h to NRK, since h is already defined as a function handle.
- It is best not to use i as a variable name in Matlab.
In Matlab you can do the following
x = {1:4, rand(3,3,3), 3};
[a, b, c] = cellfun(#size, x);
The above though not scalar output, does not require UniformOutput to be false.
If instead I have
x = {1:4, rand(3,3,3), 3};
[a,b,c] = cellfun(#(my_dummy_fun) [1, 2, 3], x); % GIVES ERROR
I get an error. How is this different than #size? Is there a way to get the same behavior for the custom function as for size?
thanks!
You where confused by size. Size allows a single output (vector) or multiple output arguments.
%three outputs
[a,b,c]=size(rand(3,3,3))
%one output
[x]=size(rand(3,3,3))
where x =[a,b,c]
You are successfully using size with three output arguments, but your function handle has only one output argument (which is a vector).
I don't know any possible syntax to directly define a anonymous function with multiple output arguments. To work around this, I wrote this small wrapper function:
function varargout=vec2nargout(in)
varargout=mat2cell(in(:),ones(1,nargout));
end
It allows:
[a,b,c] = cellfun(#(my_dummy_fun)vec2nargout([1,2,3]), x);
Is there an equivalent to bsxfun for non-numeric data?
For example, I want to compare all pairs of strings stored in two cell-arrays:
>> a = {'aa', 'bb', 'cc'};
>> b = {'dd', 'aa'};
>> bsxfun( #strcmp, a, b' ); % not working for cells :-(
I like Rody's solution, but you could also do a workaround like this:
ia=(1:length(a)).'; ib=1:length(b);
a=a(:);
bsxfun(#(ii,jj) strcmp( a(ii),b(jj) ) ,ia, ib);
I'm afraid there's no such equivalent for cell-arrays :-(
As far as I can see, you can either:
Follow Oleg's suggestion and use loops
Use existing implementations such as mAryCellFcn or csxfun from the File Exchange.
Roll your own function. For example, here's a variant of Robert's idea that works for inputs of any dimensions (under the restrictions of bsxfun, of course) and an arbitrary binary function func:
function C = mybsxfun(func, A, B)
idx_A = reshape(1:numel(A), size(A));
idx_B = reshape(1:numel(B), size(B));
C = bsxfun(#(ii, jj)func(A(ii), B(jj)), idx_A, idx_B);
If your function can operate on entire cell arrays element-wise, you could perform a singleton expansion on your cell arrays first, and then feed them directly to the function func:
mask = bsxfun(#or, true(size(A)), true(size(B)));
idx_A = bsxfun(#times, mask, reshape(1:numel(A), size(A)));
idx_B = bsxfun(#times, mask, reshape(1:numel(B), size(B)));
C = func(A(idx_A), B(idx_B));
The latter method might be faster if func is optimized for vectorized operations on cell arrays.
How about
[str,ia,ib] = intersect(a,b)
?
As the error message says, broadcasting only works for numeric types. Here are other possible alternatives:
a = {'aa', 'bb', 'cc'};
b = {'dd'; 'aa'};
%# obviously doesnt work
%#bsxfun(#strcmp, a, b)
%# do the singleton expansion ourselves
strcmp(repmat(a,size(b)), repmat(b,size(a)))
%# if you dislike REPMAT, we can use Tony's trick
strcmp(a(ones(size(b)),:), b(:,ones(size(a))))
%# we could also use CELLFUN
cell2mat(cellfun(#(s)strcmp(a,s), b, 'UniformOutput',false))