Fill structure more efficient - matlab

How can a structure i.e. 'settings' be filled more easily than with this code:
settings(1).exposure = 1;
settings(1).rebalancing = 0;
settings(2).exposure = 0;
settings(2).rebalancing = 0;
settings(3).exposure = 1;
settings(3).rebalancing = 1;
settings(4).exposure = 0;
settings(4).rebalancing = 1;
settings(5).exposure = 'benchmark';
settings(5).rebalancing = 0;
settings(6).exposure = 'benchmark';
settings(6).rebalancing = 1;

You can compress it using the struct function:
>> s = struct('exposure',{1,0,1,0,'benchmark','benchmark'},'rebalancing',{0,0,1,1,0,1});
>> s(6)
ans =
exposure: 'benchmark'
rebalancing: 1
The array literals can be replaced by any variable that contains your data, as long as all arrays are conforming in size.

you can create an array / matrix with [ 1 2 3 4 5 6]
then in a for loop, for each number ask an input
i=1:6;
for i:6;
settings(i).exposure=input(...);
settings(i).rebalancing=input(...);
end
I think you should be able with this. (its been sometime since I last used a computer with MatLab so I can't confirm)

Related

MATLAB Global Variable and Scripts

I have an m-file ParamStruct.m. Below are the contents of that file:
global Params
total_params = [];
Params.one = 1;
Params.two = 2;
Params.three = 3;
total_params = [total_params;Params];
Params.one = 4;
Params.two = 5;
Params.three = 6;
total_params = [total_params;Params];
for ii = length(total_params)
Add_Param_Vals
end
Then I have another m-file which I use as a script called Add_Param_Values. The contents of that file are as follows:
global Params
disp("adding values: ")
Params.one + Params.two
The purpose of the two m-files is to 1.) define two Params structs in ParamStruct.m, then call Add_Param_Values from ParamStruct so that for each call, I can utilize the current Params struct as indexed by the for loop in ParamStruct. For example, when I run ParamStruct at the output I would like to see the following:
adding values:
ans =
3
adding values:
ans =
9
But instead I am seeing
adding values:
ans =
9
So it seems like it is only utilizing the last element in the total_params variable and I dont know how to correct that. I do not want to modify anything in the Add_Param_Vals m-file as I am not the owner of it. Any ideas??
Sorry for the post. I was able to figure it out. Here is what I ended up doing:
global Params
total_params = [];
Params.one = 1;
Params.two = 2;
Params.three = 3;
total_params = [total_params;Params];
Params.one = 4;
Params.two = 5;
Params.three = 6;
total_params = [total_params;Params];
for ii = 1:length(total_params)
Params = total_params(ii);
Add_Param_Vals
end

MATLAB — How to eliminate equal matrices that are created randomly inside loop?

The code segment I'm working on is given below:
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
i = 1;
while i <= 10 %number of iterations
ind = randi([1 NphaseSteps],10,10);
inField{i} = phases(ind);
save('inField.mat', 'inField')
i = i + 1;
end
Now, what I want is to keep track of these randomly created matrices "inField{i}" and eliminate the ones that are equal to each other. I know that I can use "if" condition but since I'm new to programming I don't know how to use it more efficiently so that it doesn't take too much time. So, I need your help for a fast working program that does the job. Thanks in advance.
My actual code segment (after making the changes suggested by #bisherbas) is the following. Note that I actually want to use the variable "inField" inside the loop for every random created matrix and the loop advances only if the result satisfies a specific condition. So, I think the answer given by #bisherbas doesn't really eliminate the equal inField matrices before they are used in the calculation. This is, of course, my fault since I didn't declare that in the beginning.
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
nIterations = 5;
inField = cell(1,nIterations);
i = 1;
j = 1;
while i <= nIterations % number of iterations
ind = randi([1 NphaseSteps],TMsize,TMsize);
tmp = phases(ind);
idx = cellfun(#(x) isequal(x,tmp),inField);
if ~any(idx)
inField{i} = tmp;
end
j = j+1;
outField{i} = TM * inField{i};
outI = abs(outField{i}).^2;
targetIafter{i} = abs(outField{i}(focusX,focusY)).^2;
middleI = targetIafter{i} / 2;
if (max(max(outI)) == targetIafter{i})...
&& ( sum(sum((outI > middleI).*(outI < max(max(outI))))) == 0 )
save('inFieldA.mat', 'inField')
i = i + 1;
end
if mod(j-1,10^6) == 0
fprintf('The number of random matrices tried is: %d million \n',(j-1)/10^6)
end
end
Additionally, I've written a seemingly long expression for my loop condition:
if (max(max(outI)) == targetIafter{i})...
&& ( sum(sum((outI > middleI).*(outI < max(max(outI))))) == 0 )
save('inFieldA.mat', 'inField')
i = i + 1;
end
Here I want a maximum element at some point (focusX, focusY) in the outField matrix. So the first condition decides whether the focus point has the maximum element for the matrix. But I additionally want all other elements to be smaller than a specific number (middleI) and that's why the second part of the if condition is written. However, I'm not very comfortable with this second condition and I'm open to any helps.
Try this:
NphaseSteps = 6;
phases = exp( 2*pi*1i * (0:(NphaseSteps-1))/NphaseSteps );
i = 1;
inField = cell(1,NphaseSteps);
while i <= NphaseSteps %number of iterations
ind = randi([1 NphaseSteps],NphaseSteps,NphaseSteps);
tmp = phases(ind);
idx = cellfun(#(x) isequal(x,tmp),inField);
if ~any(idx)
inField{i} = tmp;
end
save('inField.mat', 'inField')
i = i + 1;
end
Read more on cellfun here:
https://www.mathworks.com/help/matlab/ref/cellfun.html

How can I display different types of output in a matix in matlab?

please consider that I have different types of output in each iteration , how I can show all of them in a matrix?or in a table ? I need to have label for each column and to be accessible when I need it for calling or comparing or etc ...
for example outputs of iterations:
myfilename =
file35.txt
a_Count =
3
PPS_Count =
16
PPP_Count =
8
emo =
'trust'
x =
1
for example outputs of iteration 2:
myfilename =
file36.txt
a_Count =
5
PPS_Count =
10
PPP_Count =
8
emo =
'anger'
x =
0
for example outputs of iteration 3:
myfilename =
file37.txt
a_Count =
6
PPS_Count =
32
PPP_Count =
8
emo =
'trust'
x =
0
thanks in advance.
Here is a tutorial on creating a struct array and documentation for struct.
In your case what I would do is first create the empty struct and then loop through the files:
data_struct = struct('a_Count',{},'PPS_Count',{},'PPP_Count',{},'emo',{},'x',{});
numfiles = 1; % just for testing purposes
for findex = 1:numfiles
% Code to read in file data goes here. Replace from here to next comment.
new_a_Count = 3;
new_PPS_Count = 16;
new_PPP_Count = 8;
new_emo = 'trust';
new_x = 1;
% Replace down to here populating variables:
% new_a_Count, new_PPS_Count, new_PPP_Count, new_emo, new_x
data_struct(findex).a_Count = new_a_Count;
data_struct(findex).PPS_Count = new_PPS_Count;
data_struct(findex).PPP_Count = new_PPP_Count;
data_struct(findex).emo = new_emo;
data_struct(findex).x = new_x;
end;
% display all values in data_struct(1):
disp("data_struct(1) = ");
disp(data_struct(1));
disp("\n");
% display just the first field "a_Count"
disp("data_struct(1).a_Count = ");
disp(data_struct(1).a_Count);
Note that you can call those new variables anything, including the same names as the struct fields. Here's the output you should get when you run this:
data_struct (1) =
{
PPP_Count = 8
PPS_Count = 16
a_Count = 3
emo = trust
x = 1
}
data_struct(1).a_Count =
3

For loop running over different variables

Good day,
I would like to do the following in Matlab:
var1 = 10;
var2 = 15;
var3 = 20;
j = 1;
for i = [var1,var2,var3]
a(j) = i + 10;
j = j + 1;
end
clear j;
With result:
a(1) = var1 + 10 = 20
a(2) = var1 + 10 = 25
a(3) = var1 + 10 = 30
Any ideas?
Engaging heavy use of crystal ball. It appears that you'd like to dynamically generate the names var1, var2, etc. Don't. There is just about never an advantage to naming variables this way. Use cell arrays instead:
var{1} = 10;
var{2} = 15;
var{3} = 20;
so that you can just use:
for i = 1:length(var)
a(j) = var{i} + 10;
...
Note the curly brace.
If your variables are all the same size, it's even better to use array slices. var(:, i) or var(:,:,:,i), for example
There was a similar question with a successful answer: foreach loop with strings in Matlab
maybe use the cell array syntax with {}:
for i = {var1,var2,var3}
a(j) = i + 10;
j = j + 1;
end
Both #FloHin and #Peter have mentioned using cells, which is a great method to help you when you have a limited number of non-scalar variables. In case you are dealing with unknown number of such variables that follow a certain format, you can use eval function to get the value of the current variable on-demand:
var1 = 10;
var2 = 15;
var3 = 20;
var4 = 30;
# ...
# more variables following the varN = x pattern
all_variables = who('var*');
num = numel(all_variables);
a = zeros(num, 1);
for i = 1:num
a(i) = eval(all_variables{i}) + 10;
end

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.