I am dealing with a rather large optimization problem (using MOSEK). To remind myself of the decision variables in this problem, I decided to try to store the variable names in a cell array in a struct, as desribed by MOSEK. However, I am unsure of how to do this. The relevant fragment of my code is listed below:
JiSet = 1:6; TiSet = [7 8]; nL = length(TiSet);
P = struct;
P.names.var{1} = 'gamma_i(k+1)'; % my first constraint
P.names.var{2:1+nL,1} = cellstr(strcat('nu_',int2str(TiSet(:)),'(k+1)')); % a series of constraints of varying length
When I run the above code I get the following error:
The right hand side of this assignment has too few values to satisfy the left hand side.
However, if I enter strcat('nu_',int2str(TiSet(:)),'(k+1)') in my command window, it shows an ans variable that is a 2x1 cell (as desired). How do I assign the values in this cell to the 2:1+nL,1 entries in the P.names.var cell?
Try the same line with round brackets ( ), which are used to select sets of cells.
P.names.var(2:1+nL,1) = cellstr(strcat('nu_',int2str(TiSet(:)),'(k+1)'));
MyCell{1:2} refers to the literal contents of the cells.
MyCell = {10,24,-60};
MyCell{1:2}
ans =
10
ans =
24
MyCell(1:2) refers to a collection of cells.
MyCell(1:2)
ans =
[10] [24]
Since cellstr(strcat('nu_',int2str(TiSet(:)),'(k+1)')); is a collection of cells, you need to assign it to a collection of cells, P.names.var(2:1+nL,1);
The problem is in how you structure your assignment in the last line. The right-hand side creates a single value, a 2x1 cell array. However, the left-hand refers to two separate fields. This behavior is likely a result of the nature of cell-arrays, which may except a different data-type in each cell. Cell arrays are set up to assign whatever is on the right-hand side to a single cell on the left-hand side. You can fix this with a simple modification:
P.names.var(2:1+nL,1) = cellstr(strcat('nu_',int2str(TiSet(:)),'(k+1)'));
This utilizes "array indexing" as opposed to "cell indexing".
Related
I have a MATLAB code and I do how understand how it works.In the main code
%Tuning
tunestruct = {samplefunc,numreps,data_type,MS_criterion};
[Xtrain,optk,optsig2,tuningExtras] = tuneSKSC(data,kernel_type,maxk,tunestruct);
tuneSKC.m starts with
function [Xtrain,optk,optsig2,extras] = tuneSKSC(datastruct,kernel,maxk,tunestruct)
My question is what is tunestruct?Then, are data,kernel_type,maxk,tunestruct arguments for function?
I have pasted tunestruct.m
http://pastebin.com/cFH433Md
tunestruct is actually a cell array made of a bunch of other variables.
A cell array is a data type with indexed data containers called cells, where each cell can contain any type of data. Cell arrays commonly contain either lists of text strings, combinations of text and numbers, or numeric arrays of different sizes.
The reason of making a cell array instead of passing those arguments as separate values each times, is that the code has a very specific pattern for handling this set of parameters, in case they are not passed as arguments, as described in this code segment you've provided:
if exist('tunestruct','var')
if ~iscell(tunestruct)
tunestruct = {tunestruct,1};
end;
if(strcmp(tunestruct{1},'furs'))
tunestruct{2} = 1; %furs is deterministic, only one repetition is enough
end
s1 = ~strcmp(tunestruct{3},'net_unw') && strcmp(tunestruct{4},'Modularity');
if(s1)
tunestruct{4} = 'AMS'; %Modularity is used for unweighted network data
warning('\nNot possible to use Modularity, using AMS instead...');
end
end;
I want to replace the value of the fields in a structure array. For example, I want to replace all 1's with 3's in the following construction.
a(1).b = 1;
a(2).b = 2;
a(3).b = 1;
a([a.b] == 1).b = 3; % This doesn't work and spits out:
% "Insufficient outputs from right hand side to satisfy comma separated
% list expansion on left hand side. Missing [] are the most likely cause."
Is there an easy syntax for this? I want to avoid ugly for loops for such simple operation.
Credits go to #Slayton, but you actually can do the same thing for assigning values too, using deal:
[a([a.b]==1).b]=deal(3)
So breakdown:
[a.b]
retrieves all b fields of the array a and puts this comma-separated-list in an array.
a([a.b]==1)
uses logical indexing to index only the elements of a that satisfy the constraint. Subsequently the full command above assigns the value 3 to all elements of the resulting comma-separated-list according to this.
You can retrieve that the value of a field for each struct in an array using cell notation.
bVals = {a.b};
bVals = cell2mat( bVals );
AFAIK, you can't do the same thing for inserting values into an array of structs. You'll have to use a loop.
I have a cell array of length 3 and I want to make a for loop with another cell array with length of 6 , so how can I add extra 3 cells for the first array in order to make the 2 cell arrays equal and to use my for loop in MATLAB?
For example, with 2 inputs:
type = { '12' '62' '5' };
colour = {'re' 'green' 'yellow' 'brown' 'blue' 'black'};
for i = 1:length(colour)
if isequal(colour(i), type(:))
result(i) = type(i);
else
end
end
I need to make the type cell array with the same size with colour cell array (I think I have to add extra 3 empty cells in side the type cell array).
I have to address several issues in your code first:
If you use a cell array, you must use curly braces ({}) to extract elements from it. Instead of writing colour(i) you should be writing colour{i}.
This is not a problem, but it's a matter of good practice. If you don't need to handle the else part of the if statement, don't write it at all.
Preallocate memory so that arrays don't grow inside the loop (it slows down the program). Specifically, add the line result = cell(size(colour)); before the for loop.
Your isequal logic is flawed. Practically, it would always return false because colour{1} is one element and type{:} is many.
According to your example, types contain numbers and colours letters, although they are both strings. Does it make sense to compare the two?
Now, regarding your question, it's up to you to decide how the for loop runs. Since you don't mention what you want to achieve (you rather ask how you want to achieve something without saying what exactly), I cannot say what your for loop should look like, if necessary at all. Maybe you meant to use ismember instead of isequal? If so, the fixed code can look like this:
result = cell(size(colour));
for i = 1:length(colour)
if ismember(colour{i}, type)
result{i} = type{i};
end
end
or shorter, like this:
result = cell(size(colour));
[found, idx] = ismember(colour, type);
result(found) = type{idx(found)}
If you provide more details, maybe I can refine my answer so that it helps you more.
I am writing a function to remove some values from a cell array, like so:
function left = remove(cells, item);
left = cells{cellfun(#(i) ~isequal(item, i), cells)};
But when I run this, left has only the first value, as the call to cells{} with a logical array returns all of the matching cells as separate values. How do I group these separate return values into a single cell array?
Also, perhaps there is already a way to remove a given item from a cell array? I could not find it in the documentation.
You have to use () instead of {} to index the cells:
function left = remove(cells, item)
left = cells(cellfun(#(i) ~isequal(item, i), cells));
Using () for indexing will give you a subset of cells, while using {} will return the contents of a subset of cells as a comma-separated list, and only the first entry of that list will get placed in left in your example.
You can check out this MATLAB documentation for more information on using cell arrays.
EDIT: Response to comment...
If you have an operation that ends up giving you a comma-separated list, you can place the individual elements of the list into cells of a cell array by surrounding the operation with curly braces. For your example, you could do:
left = {cells{cellfun(#(i) ~isequal(item, i), cells)}};
The inner set of curly braces creates a comma-separated list of the contents of cells that are not equal to item, and the outer set then collects this list into a cell array. This will, of course, give the same result as just using parentheses for the indexing, which is the more sensible approach in this case.
If you have a function that returns multiple output arguments, and you want to collect these multiple values into a cell array, then it's a bit more complicated. You first have to decide how many output arguments you will get, or you can use the function NARGOUT to get all possible outputs:
nOut = 3; %# Get the first three output arguments
%# Or...
nOut = nargout(#some_fcn); %# Get all the output arguments from some_fcn
Then you can collect the outputs into a 1-by-nOut cell array outArgs by doing the following:
[outArgs{1:nOut}] = some_fcn(...);
It should be noted that NARGOUT will return a negative value if the function has a variable number of output arguments, so you will have to choose the value for nOut yourself in such a case.
My question is easily summarized as: "Why does the following not work?"
teststruct = struct('a',3,'b',5,'c',9)
fields = fieldnames(teststruct)
for i=1:numel(fields)
fields(i)
teststruct.(fields(i))
end
output:
ans = 'a'
??? Argument to dynamic structure reference must evaluate to a valid field name.
Especially since teststruct.('a') does work. And fields(i) prints out ans = 'a'.
I can't get my head around it.
You have to use curly braces ({}) to access fields, since the fieldnames function returns a cell array of strings:
for i = 1:numel(fields)
teststruct.(fields{i})
end
Using parentheses to access data in your cell array will just return another cell array, which is displayed differently from a character array:
>> fields(1) % Get the first cell of the cell array
ans =
'a' % This is how the 1-element cell array is displayed
>> fields{1} % Get the contents of the first cell of the cell array
ans =
a % This is how the single character is displayed
Since fields or fns are cell arrays, you have to index with curly brackets {} in order to access the contents of the cell, i.e. the string.
Note that instead of looping over a number, you can also loop over fields directly, making use of a neat Matlab features that lets you loop through any array. The iteration variable takes on the value of each column of the array.
teststruct = struct('a',3,'b',5,'c',9)
fields = fieldnames(teststruct)
for fn=fields'
fn
%# since fn is a 1-by-1 cell array, you still need to index into it, unfortunately
teststruct.(fn{1})
end
Your fns is a cellstr array. You need to index in to it with {} instead of () to get the single string out as char.
fns{i}
teststruct.(fns{i})
Indexing in to it with () returns a 1-long cellstr array, which isn't the same format as the char array that the ".(name)" dynamic field reference wants. The formatting, especially in the display output, can be confusing. To see the difference, try this.
name_as_char = 'a'
name_as_cellstr = {'a'}
You can use the for each toolbox from http://www.mathworks.com/matlabcentral/fileexchange/48729-for-each.
>> signal
signal =
sin: {{1x1x25 cell} {1x1x25 cell}}
cos: {{1x1x25 cell} {1x1x25 cell}}
>> each(fieldnames(signal))
ans =
CellIterator with properties:
NumberOfIterations: 2.0000e+000
Usage:
for bridge = each(fieldnames(signal))
signal.(bridge) = rand(10);
end
I like it very much. Credit of course go to Jeremy Hughes who developed the toolbox.