Check for [] simulink - matlab

However I try to test if x is [] I fail, seems that it should be trivial, but can't figure out how to do it.
if I run x = rmi('get',subsystemPath);
ans = []
I've tried
x == []
x
isempty(fieldnames(x))
isEmpty(x)
but nothing works
function requirements = GetRequirementsFromSubsystem(subsystemPath)
x = rmi('get',subsystemPath);
if(isempty(fieldnames(x))) %%%%%%%%%%%%%%%%<------
requirements = 0;
else
requirements = {x.description}; % Fails if do this without a check
end
end
Any ideas?

x is a struct, right? In that case, according to this posting on the MATLAB newsgroup, there are two kinds of emptiness for structs:
S = struct() => no fields
isempty(S) is FALSE, because S is a [1 x 1] struct without fields
S = struct('Field1', {}) => fields, but no data
isempty(S) is TRUE, because S is a [0 x 0] struct with fields
For me, isempty(fieldnames(S)) works only for the first case in Octave, at least.
If x on the other hand, is an array, not a struct, then isempty(x) should work.
>> S = struct()
S =
scalar structure containing the fields:
>> isempty(S)
ans = 0
>> isempty(fieldnames(S))
ans = 1
>> S = struct('Field1',{})
S =
0x0 struct array containing the fields:
Field1
>> isempty(S)
ans = 1
>> isempty(fieldnames(S))
ans = 0
>> x = []
x = [](0x0)
>> isempty(x)
ans = 1

Related

Rearange matlab struct

Lets have a struct defined like this:
s.a = [1, 11];
s.b = [2, 22];
How can I convert it to struct defined like this:
s(1).a = 1;
s(1).b = 2;
s(2).a = 11;
s(2).b = 22;
This need comes from textscan() function. I read large file using this function and then convert the result using cell2struct() function. In this case, however, each field contains whole column, so one has to address individual value by s.column_name(row_index). While I would prefer to do it by s(row_index).column_name.
This type of operation with a struct array does not usually result in pretty code, but here it goes:
s2 = cell2struct(num2cell(cell2mat(struct2cell(s))).', fieldnames(s), 2);
In general, indexing a struct array across its two "dimensions" (fields and array index) is problematic for this reason. Have you considered using a table instead? It allows both types of indexing in a natural way:
s = table; % initiallize as table
s.a = [1; 11]; % note: column vectors
s.b = [2; 22];
So now
>> s
s =
2×2 table
a b
__ __
1 2
11 22
>> s.a
ans =
1
11
>> s.a(2)
ans =
11
>> s(:, 'a') % note: gives a (sub)table
ans =
2×1 table
a
__
1
11
>> s{:, 'a'} % same as s.a
ans =
1
11
>> s{2, :}
ans =
11 22
>> s{2, 'a'} % same as s.a(2)
ans =
11
A possible simple solution would be the following:
fn = fieldnames(s);
for j = 1 : numel(fn)
for k = 1 : numel(s(1).(fn{j}))
s2(k).(fn{j}) = s.(fn{j})(k);
end
end

Summation of cell array of function handles

I have a cell array with size (n,1) that includes a function handle. Every cell has to include specific function handle and the summation of function handles in the previous cells. How can I perform this operation? To clarify this is an illustration.
A = cell(size(ones(n,1)));
for i = 1 : n
A{i,1} = #(x) A{i-1,1} + i .* x;
end
How to get A{n,1} at x = 2 (for example)
You are actually pretty close, but you need to add a special case for i = 1 and you need to call the function:
n = 10;
A = cell(size(ones(n,1)));
A{1,1} = #(x) 1 .* x;
for ii = 2 : n
A{ii,1} = #(x) A{ii-1,1}(x) + ii .* x;
end
I replaced i with ii, to avoid confusion with complex numbers. For the case n = 10:
>> A{n}(2)
ans =
110
Recalling #gnovice comment, you can also just make a cell array of the handles, and then call a function that sums them up to n:
N = 10;
A = cell(N,1);
A{1} = #(x) 1.*x;
for k = 2:N
A{k} = #(x) k.*x;
end
% the following function sums the output of A{1}(x) to A{n}(x):
f = #(n,x) sum(cellfun(#(c) c(x),A(1:n)));
The result:
>> f(5,2)
ans =
30
>> f(N,2)
ans =
110
This way, every change of the functions in A will have an immediate effect upon redefining f:
>> A{3} = #(x) -x;
>> f = #(n,x) sum(cellfun(#(c) c(x),A(1:n)));
>> f(N,2)
ans =
102
>> f(5,2)
ans =
22

Addition of two integer in binary representation

I would like to implement code which will add two integers by their binary representation.
For instance:
a = [1 1 1 0];
and
b = [1 0 1 1];
So I implemented the following algorithm:
function s=add_binary(a,b)
m=length(a);
s=zeros(m+1,0);
n=length(a);
c=0;
for ii=n:-1:1
d=floor((a(ii)+b(ii)+c)/2);
s(ii)=a(ii)+b(ii)+c-2*d;
c=d;
end
s(1)=c;
end
However, it returns this as a result:
s=add_binary(a,b)
s =
1 0 0 1
Here, there should be an additional 1 on the left, such that it would read:
1 1 0 0 1
Where am I making a mistake?
Since you're dealing with binary numbers, why not use logical operators?
function s = add_binary(a, b)
a = [0 a];
b = [0 b];
c = a&b;
while any(c)
b = xor(a, b);
a = circshift(c, -1);
c = a&b;
end
s = a+b;
end
And a test:
>> a = randi([0 1], [1 6])
a =
0 1 0 1 0 1
>> b = randi([0 1], [1 6])
b =
1 1 0 0 0 1
>> s = add_binary(a, b)
s =
1 0 0 0 1 1 0
here is my solution
function s=add_binary(a,b)
m=length(a);
s=zeros(m+1,1);
n=length(a);
c=0;
for ii=n:-1:1
d=floor((a(ii)+b(ii)+c)/2);
s(ii+1)=a(ii)+b(ii)+c-2*d;
c=d;
end
s(1)=c;
s=s';
end
>> s=add_binary(a,b)
s =
1 1 0 0 1
This problem was discussed in a 2011 question on MATLAB Answers. I'd like to mention 2 more solutions:
If you have the Communications System Toolbox, you can use bi2de and de2bi:
de2bi(bi2de(a,'left-msb') + bi2de(b,'left-msb'),'left-msb')
If the amount of "digits" in the input is known (and reasonable), one solution could be to store all possible input combinations in some data-structure, which would facilitate rapid access. One such example is the MapN class (though it can just as easily be done with regular numeric arrays). I will provide a small example to show this idea (including a benchmark):
function allResults = q43095156(allResults)
if nargin == 0
% Let's store all combinations of 8 binary digits:
in = uint8(0:255);
out = uint16(in)+uint16(in.');
outB = logical(de2bi(out(:),'left-msb'));
[in1,in2] = meshgrid(in,in);
allResults = MapN(...
num2cell([num2cell(in1(:),2),num2cell(in2(:),2)],2),...
num2cell(outB,2));
end
benchmark(allResults);
end
function benchmark(allResults)
rng(43095156);
a = logical(randi([0 1],10,8,'uint8'));
b = logical(randi([0 1],10,8,'uint8'));
% Test:
R{5} = de2bi(bi2de(a,'left-msb') + bi2de(b,'left-msb'),'left-msb');
R{4} = add_a_bunch_gnovice(a,b);
R{3} = add_a_bunch_Sardar(a,b);
R{2} = add_a_bunch_dato(a,b);
R{1} = getFromMap(a, b, allResults);
assert(isequal(R{:}));
% Benchmark:
a = logical(randi([0 1],1000,8,'uint8'));
b = logical(randi([0 1],1000,8,'uint8'));
fprintf(1,'\nSardar''s method:\t%f',timeit(#() add_a_bunch_Sardar(a, b) ));
fprintf(1,'\nDev-iL''s method:\t%f',timeit(#() getFromMap(a, b, allResults) ));
fprintf(1,'\ngnovice''s method:\t%f',timeit(#() add_a_bunch_gnovice(a, b) ));
fprintf(1,'\ndato''s method:\t\t%f',timeit(#() add_a_bunch_dato(a, b) ));
fprintf(1,'\nbi2de method:\t\t%f',timeit(#() de2bi(bi2de(a,'left-msb') + bi2de(b,'left-msb'),'left-msb')));
end
function out = getFromMap(a,b,map)
out = cell2mat(values(map, num2cell([ num2cell(bi2de(a,'left-msb'),2),...
num2cell(bi2de(b,'left-msb'),2)],2)));
end
function out = add_a_bunch_gnovice(a,b)
out = zeros(size(a)+[0,1],'logical');
for ind1 = 1:size(a,1)
out(ind1,:) = add_binary_gnovice(a(ind1,:), b(ind1,:));
end
end
function out = add_a_bunch_Sardar(a,b)
out = zeros(size(a)+[0,1],'logical');
for ind1 = 1:size(a,1)
out(ind1,:) = add_binary_Sardar(a(ind1,:), b(ind1,:));
end
end
function out = add_a_bunch_dato(a,b)
out = zeros(size(a)+[0,1],'logical');
for ind1 = 1:size(a,1)
out(ind1,:) = add_binary_dato(a(ind1,:), b(ind1,:));
end
end
function s = add_binary_gnovice(a, b)
a = [0 a];
b = [0 b];
c = a&b;
while any(c)
b = xor(a, b);
a = circshift(c, -1);
c = a&b;
end
s = a+b;
end
function s = add_binary_Sardar(a,b)
s = logical(str2double(num2cell(dec2bin(bin2dec(num2str(a)) +...
bin2dec(num2str(b)), numel(a)+1))));
end
function s = add_binary_dato(a,b)
m = length(a);
s = zeros(m+1,1);
n = length(a);
c = 0;
for ii = n:-1:1
d = floor((a(ii)+b(ii)+c)/2);
s(ii+1) = a(ii)+b(ii)+c-2*d;
c = d;
end
s(1) = c;
s = logical(s.');
end
And the results with my x64 MATLAB R2017a # Win10 are:
Sardar's method: 0.336414
Dev-iL's method: 0.061656
gnovice's method: 0.022031
dato's method: 0.002123
bi2de method: 0.000356
So this should give us an idea which methods are faster (unless I messed the wrapper functions up greatly)...
The advantage of the MapN method would be noticeable if the computation of the sum was some other, costlier operation.
Use num2str to convert a and b to strings and use bin2dec to convert them to decimal. Then add them and convert the sum back to binary using dec2bin. Use num2cell to split the string and finally use str2double to get the desired result.
s=str2double(num2cell(dec2bin(bin2dec(num2str(a))+bin2dec(num2‌​str(b)))))
% Output for given a and b
%---------------------------
% s =
% 1 1 0 0 1

Matlab how to vectorize double for loop? Setting values for nested structure array is very slow

I have a nested structure array t in the format of t.a.b = value, where and a and b are just random strings. t can have an arbitrary number of a's as field names and each a can have an arbitrary number of b's as field names. I need to make a copy of t called x, but set all x.a.b = 0. In addition I need to make another structure array in the form of y.a = 0 for all a in t. Right now I'm using a nested for loop solution but it is too slow if there are too many a's and b's. Can someone tell me if there's any way to vectorize this nested loop or any other operation in this code as to make this code run faster? Thanks.
names1 = fieldnames(t);
x = t;
y = {};
for i=1:length(names1)
y.(names1{i}) = 0;
names2 = fieldnames(x.(names1{i}));
for j=1:length(names2)
x.(names1{i}).(names2{j}) = 0;
end
end
Sample:
if t is such that
t.hello.world = 0.5
t.hello.mom = 0.2
t.hello.dad = 0.8
t.foo.bar = 0.7
t.foo.moo = 0.23
t.random.word = 0.38
then x should be:
x.hello.world = 0
x.hello.mom = 0
x.hello.dad = 0
x.foo.bar = 0
x.foo.moo = 0
x.random.word = 0
and y should be:
y.hello = 0
y.foo = 0
y.random = 0
You can get rid of all the loops by doing using structfun
function zeroed = always0(x)
zeroed = 0;
endfunction
function zeroedStruct = zeroSubfields(x)
zeroedStruct = structfun(#always0, x, 'UniformOutput', false);
endfunction
y = structfun(#always0, t, 'UniformOutput', false);
x = structfun(#zeroSubfields, t, 'UniformOutput', false);
If you had arbitrary nesting of fields zeroSubfields could be extended to
function zeroedStruct = zeroSubfields(x)
if(isstruct(x))
zeroedStruct = structfun(#zeroSubfields, x, 'UniformOutput', false);
else
zeroedStruct = 0;
endif
endfunction
To construct y, you can do something like this:
>> t.hello.world = 0.5;
>> t.hello.mom = 0.2;
>> t.hello.dad = 0.8;
>> t.foo.bar = 0.7;
>> t.foo.moo = 0.23;
>> t.random.word = 0.38;
>> f = fieldnames(t);
>> n = numel(f);
>> fi = cell(1,n*2);
>> fi(1:2:(n*2-1)) = f;
>> fi(2:2:(n*2)) = num2cell(zeros(n,1))
fi =
'hello' [0] 'foo' [0] 'random' [0]
>> y = struct(fi{:})
y =
hello: 0
foo: 0
random: 0
Basically you're just getting the fieldnames, interleaving them with zeros in a cell array, and then directly constructing the structure with a comma-separated list of fieldnames and values, from that cell array.
For x, I'm afraid you would still need to loop over the first level of fieldnames, I think. But you should be able to do something similar to the above within each loop iteration.

Logical indexing of cell array in MATLAB

I want to do
myCellArray = myCcellArray{indices}
where indices is just 0s and 1s, with same number of elements as the number of rows in myCellArray, but it doesn't work. What should I do?
You need to use parenthesis instead of curly braces to do the indexing.
>> arr = cell(2,2);
>> arr{1,1} = magic(4);
>> arr{1,2} = 'Hello';
>> arr{2,1} = 42;
>> arr{2,2} = pi;
>> arr
arr =
[4x4 double] 'Hello'
[ 42] [3.1416]
>> idx = logical(zeros(2,2));
>> idx(1,1) = true;
>> idx(2,2) = true;
>> arr(idx)
ans =
[4x4 double]
[ 3.1416]
If you want to slice a cell-array, use parentheses. Example:
%# random cellarray of strings, and a logical indices vector
myCcellArray = cellstr(num2str((1:10)','value %02d')); %'
indices = rand(size(myCcellArray)) > 0.5;
%# slicing
myCellArray = myCcellArray(indices)
What amro said is right, you should use parentheses.
But another critical thing is to use booleans not numeric 1 and 0 here.
so if you have numbers
I = [0 0 0 1 0 1]
you should use
myCellArray(I~=0)
to index it. Confusingly, a boolean array is displayed as ones and zeros in Matlab, although it is represented quite differently internally.