Cell Array or Multi-Subscripted Array? - matlab

The following piece of code works when data is passed as a 1x50 array.
(Data is in fact a struct that passes several other parameters too). In the 1x50 case a 4x1 array of parameters is returned for each i (the value of de.nP is 600).
However I want to change it so that I can pass a matrix of data say d dates so that the matrix has dimension dx50. This will then return a 4xd array for each i.
My question is should I use a cell array or a 3D array to store the values?
Seems to me both methods could do the job?
for i=1:de.nP
betas(:,i)=NSS_betas(P1(:,i),data);
end
Going further into the code I will need to use
Params=vertcat(betas,P1);
Where P1 is a 2x1 array. So for each date (i) I need to concatenate the contents of P(1) to all the betas for that date.
Will this affect the choice of whether to use cellarray or 3D array?
It seems to me cellarray is better suited to vectorised code (Which is what I am trying to use as much as possible) but 3D array might be easier to use with functions like vertcat?
Here is the whole code
mats=[1:50];
mats2=[2 5 10 30];
betaTRUE=[5 -2 5 -5 1 3; 4 -3 6 -1 2 4];
for i=1:size(betaTRUE,1)
yM(i,:)=NSS(betaTRUE(i,:),mats);
y2(i,:)=NSS(betaTRUE(i,:),mats2);
end
dataList=struct('yM',yM,'mats',mats,'model',#NSS,'mats2',mats2,'y2',y2);
de=struct('min',[0; 2.5],'max', [2.5;5],'d',2,'nP',200,'nG',300,'ww',0.1,'F',0.5,'CR',0.99,'R',0,'oneElementfromPm',1);
beta=DElambdaVec(de,dataList,#OF);
function [output]=DElambdaVec(de,data,OF)
P1=zeros(de.d,de.nP);
Pu=zeros(de.d,de.nP);
for i=1:de.d
P1(i,:)=de.min(i,1)+(de.max(i,1)-de.min(i,1))*rand(de.nP,1);
end
P1(:,1:de.d)=diag(de.max);
P1(:,de.d+1:2*de.d)=diag(de.min);
for i=1:de.nP
betas(:,i)=NSS_betas(P1(:,i),data);
end
Params=vertcat(betas,P1);
Fbv=NaN(de.nG,1);
Fbest=realmax;
F=zeros(de.nP,1);
P=zeros(de.nP,1);
for i=1:de.nP
F(i)=OF(Params(:,i)',data);
P(i)=pen(P1(:,i),de,F(i));
F(i)=F(i)+P(i);
end
[Fbest indice] =min(F);
xbest=Params(:,indice);
%vF=vF+vP;
%NaN(de.nG,de.nP);
Col=1:de.nP;
for g=1:de.nG
P0=P1;
rowS=randperm(de.nP)';
colS=randperm(4)';
RS=circshift(rowS,colS(1));
R1=circshift(rowS,colS(2));
R2=circshift(rowS,colS(3));
R3=circshift(rowS,colS(4));
%mutate
Pm=P0(:,R1)+de.F*(P0(:,R2)-P0(:,R3));
%extra mutation
if de.R>0
Pm=Pm+de.r*randn(de.d,de.nP);
end
%crossover
PmElements=rand(de.d,de.nP)<de.CR;
%mPv(MI)=mP(Mi);
if de.oneElementfromPm
Row=unidrnd(de.d,1,de.nP);
ExtraPmElements=sparse(Row,Col,1,de.d,de.nP);
PmElements=PmElements|ExtraPmElements;
end
P0_Elements=~PmElements;
Pu(:,RS)=P0(:,RS).*P0_Elements+PmElements.*Pm;
for i=1:de.nP
betasPu(:,i)=NSS_betas(Pu(:,i),data);
end
ParamsPu=vertcat(betasPu,Pu);
flag=0;
for i=1:de.nP
Ftemp=OF(ParamsPu(:,i)',data);
Ptemp=pen(Pu(:,i),de,F(i));
Ftemp=Ftemp+Ptemp;
if Ftemp<=F(i);
P1(:,i)=Pu(:,i);
F(i)=Ftemp;
if Ftemp < Fbest
Fbest=Ftemp; xbest=ParamsPu(:,i); flag=1;
end
else
P1(:,i)=P0(:,i);
end
end
if flag
Fbv(g)=Fbest;
end
end
output.Fbest=Fbest; output.xbest=xbest; output.Fbv=Fbv;
end
function penVal=pen(mP,pso,vF)
minV=pso.min;
maxV=pso.max;
ww=pso.ww;
A=mP-maxV;
A=A+abs(A);
B=minV-mP;
B=B+abs(B);
C=ww*((mP(1,:)+mP(2,:))-abs(mP(1,:)+mP(2,:)));
penVal=ww*sum(A+B,1)*vF-C;
end
function betas=NSS_betas(lambda,data)
mats=data.mats2';
lambda=lambda;
yM=data.y2';
nObs=size(yM,1);
G= [ones(nObs,1) (1-exp(-mats./lambda(1)))./(mats./lambda(1)) ((1-exp(- mats./lambda(1)))./(mats./lambda(1))-exp(-mats./lambda(1))) ((1-exp(- mats./lambda(2)))./(mats./lambda(2))-exp(-mats./lambda(2)))];
betas=G\yM;
end

This does the trick will require extensive recoding in the rest of the function though!
betas=zeros(4,size(data.y2,1),de.nP);
for i=1:de.nP
betas(:,:,i)=NSS_betas(P1(:,i),data);
end

Related

Undefined function or variable "new_m"

I am new to Matlab. I have three functions. When I call co.m and pol_det.m they both work fine. However, when I call minor.m which in itself calls pol_det which in its turn calls co.m I get an error referring to the co.m: Undefined function or variable "new_m".
I am working with R2007b version. The three functions are below. Originally, they are written each in a separate .m document.
function [ k ] = pol_det(a)
%calculates the determinant of a general matrix (not just consisting of
%numbers)
dim=size(a); %dimensions of a matrix
if dim(1)~= dim(2)
disp('Only Square Matrices, please')
end
m=length(a);
k=0;
if(m==2)
k=sum_p(conv(a(1,1),a(2,2)),- conv(a(2,1),a(1,2))); %calc. the determinant of a 2x2 m.
else
for i=1:m
k=k+((-1)^(1+i))*conv(a(1,i),co(a,1,i)); %calc. the determinant using cofactor expansion
end
end
if (k==0)
disp('Matrix non-invertible')
end
end
function [ out ] = co( a,i,j )
%cofactor expansion,
%http://people.math.carleton.ca/~kcheung /math/notes/MATH1107/wk07/07_cofactor_expansion.html
[m,n]=size(a);
%create a new matrix by eliminating the row and column in which the %element is present
%new_m=zeros(m,n)
row=1;
col=1;
for i1=1:m
for j1=1:n
if(i1~=i && j1~=j)
new_m(row,col)=a(i1,j1);
col=col+1;
end
end
if(col~=1)
row=row+1;
end
col=1;
end
%new_m
out=pol_det(new_m);
end
function [ m ] = minor(a)
dim=size(a); %dimensions of a matrix
if dim(1)~= dim(2)
disp('Only Square Matrices, please')
end
a=a.';
for i=1:dim(1)
for j=1:dim(1)
a(i,:)=[];
a(:,j)=[];
m(i,j)= pol_det(a);
end
end
end
Your problem is that, given certain values of a, i, and j, you may never enter the conditional statement inside your loops that initializes new_m. In such a case, the variable won't exist when you then get to the following line out=pol_det(new_m);.
You should set a default value for newm before your loops and conditional statements, such as [], so that the variable will always have a value. You should also make sure pol_det can appropriately handle this default value. Best practice is to make use of preallocation, both to improve performance and avoid conditional existence of necessary variables.

Multiple boxplot with unequal length in MATLAB

Below is the MATLAB code that i used to plot multiple boxplots in one figure. However, this only works if the data is of equal length (n1,n2,n3,n4,n5,n6 =10 in this example). How do i change this so that it works for dataset with unequal length? For example: n1=10, n2=10, n3=15,n4=15,n5=5,n6=5?
clc
clear
n1=10;n2=10;n3=10;n4=10;n5=10;n6=10;
x=[rand(1,n1) rand(1,n2) rand(1,n3) rand(1,n4) rand(1,n5) rand(1,n6)];
n=10 ; xx=([1:6])'; % example
r=repmat(xx,1,n)';
g=r(:)';
positions = [1 2 3 4 5 6 ];
h=boxplot(x,g, 'positions', positions);
set(h,'linewidth',2)
set(gca,'xtick',[mean(positions(1:2)) mean(positions(3:4)) mean(positions(5:6)) ])
set(gca,'xticklabel',{'exp1','exp2','exp3'},'Fontsize',28)
color = ['c', 'y', 'c', 'y','c', 'y'];
h = findobj(gca,'Tag','Box');
for j=1:length(h)
patch(get(h(j),'XData'),get(h(j),'YData'),color(j),'FaceAlpha',.5);
end
clearvars
n1=10;n2=10;n3=15;n4=15;n5=5;n6=5;
A=zeros(n1,1);A=num2str(A);A(1:end)='1';
B=zeros(n1,1);B=num2str(B);B(1:end)='2';
C=zeros(n1,1);C=num2str(C);C(1:end)='3';
D=zeros(n1,1);D=num2str(D);D(1:end)='4';
E=zeros(n1,1);E=num2str(E);E(1:end)='5';
F=zeros(n1,1);F=num2str(F);F(1:end)='6';
x=[rand(1,n1) rand(1,n2) rand(1,n3) rand(1,n4) rand(1,n5) rand(1,n6)];
boxplot([x(1,1:n1)';x(1,n1+1:n1+n2)';x(1,n1+n2+1:n1+n2+n3)';x(1,n1+n2+n3+1:n1+n2+n3+n4)';...
x(1,n1+n2+n3+n4+1:n1+n2+n3+n4+n5)';x(1,n1+n2+n3+n4+n5+1:n1+n2+n3+n4+n5+n6)'],[A;B;C;D;E;F])
There are a couple issues with your code that cause it to fail. Check my code below which you should be able to replace with yours. Rather than having to specify n1,n2,...etc., put all n-values in an array. Note your set functions will not work if you change the number of elements in ns from 6, but my code on its own will. In the future, I suggest generalizing your code to be less dependent on such things, and define less variables.
ns=[20,7,16,5,6,7]; %rather than specifying all your n variables individually, put them in an array
x=rand(1,sum(ns(:))); %allocates membory for x
ns=[0,ns]; %used for easier indexing in for loop
for(i=2:length(ns))
g((1+sum(ns(1:(i-1)))):(ns(i)+sum(ns(1:(i-1)))))=repmat(i-1,1,ns(i)); % populates g array
end
positions=1:(length(ns)-1);
h=boxplot(x,g,'positions',positions)
or, if it makes more sense to you, you could replace
ns=[0,ns]; %used for easier indexing in for loop
for(i=2:length(ns))
g((1+sum(ns(1:(i-1)))):(ns(i)+sum(ns(1:(i-1)))))=repmat(i-1,1,ns(i)); % populates g array
end
with
g=[];
for(i=1:length(ns))
g=[g repmat(i,1,ns(i))];
end
though this is generally bad practice as the size of g changes with every loop,so Matlab may throw a warning if your ns get too big.

How to avoid sub2ind and decrease execution time in manipulating multidimensional arrays using original indexes

I would like your suggestions to make my code faster (and elegant). In particular, sub2ind (and the if-loop) slow it down dramatically according to the matlab profiler. I will try to explain what I need from my code as simply as I can.
Assuming I have the following problem, for simplicity.
Every citizen of every city has a car of a specific brand and a specific color.
What I would like to have is a 4D multidimensional array Data_4D(City,Citizen,Car_brand,Car_color) that I can manipulate (read and modify) using as indexes only these four dimensions.
Then, I want to reshape my multidimensional array into a 1D array Data_1D with
length(Data_1D)=(City*Citizen*Car_brand*Car_color)
The order of the elements must follow an indexing rule:
Example assuming City=2, Citizen=2, Car_brand=2, Car_color=2;
Data_1D(1)=Data_4D(1,1,1,1)
Data_1D(2)=Data_4D(1,1,1,2)
Data_1D(3)=Data_4D(1,1,2,1)
Data_1D(4)=Data_4D(1,1,2,2)
Data_1D(5)=Data_4D(1,2,1,1)
Data_1D(6)=Data_4D(1,2,1,2)
Data_1D(7)=Data_4D(1,2,2,1)
Data_1D(8)=Data_4D(1,2,2,2)
Data_1D(9)=Data_4D(2,1,1,1)
Data_1D(10)=Data_4D(2,1,1,2)
Data_1D(11)=Data_4D(2,1,2,1)
Data_1D(12)=Data_4D(2,1,2,2)
Data_1D(13)=Data_4D(2,2,1,1)
Data_1D(14)=Data_4D(2,2,1,2)
Data_1D(15)=Data_4D(2,2,2,1)
Data_1D(16)=Data_4D(2,2,2,2)
After that I will get this 1D array, shaped as above, I need to create a matrix Matrix_Final( NRows,length(Data_1D)) in which every row is an array Data_1D. In every row NRows, the array Data_1D will have the same amount of elements but with different values.
The amount of rows depends also on some (or all) of the four the dimensions City,Citizen,Car_brand,Car_color (respecting the same indexing rule as for Data_1D) and the array built in each line must be manipulated according also to the value of the matrix row (by using the four indexes, which is the common rule for both NRows and Data_1D).
Example:
Assuming City=2, Citizen=2, Car_brand=2, Car_color=2;
Assuming NRows depends on all the four dimensions.
I will have Matrix_Final( length(DATA_1D), length(DATA_1D)).
I want that all the data of my array DATA_1D are zeros, except one element, which has to be the element that has the same indexes values(City,Citizen,Car_brand,Car_color) as NRows(City,Citizen,Car_brand,Car_color)
So at the row NRows(1), only Data_1D(1) is non-zero. For this example, the result is an eye matrix.
clc
clear all
%Dimensions Definition
City=2;
Citizen=2;
Car_brand=2;
Car_color=2;
%Length of Data
Length_Data_1D=City*Citizen*Car_brand*Car_color;
%preallocation Matrix_Final
Matrix_Final=zeros(City*Citizen*Car_brand*Car_color, Length_Data_1D);
%indexes of the dimensions
indexes_array_carcolor=repmat(repelem([1:Car_color], 1), [1 City*Citizen*Car_brand]);
indexes_array_carbrand=repmat(repelem([1:Car_brand], Car_color), [1 City*Citizen]);
indexes_array_citizen=repmat(repelem([1:Citizen],Car_brand*Car_color),[1 City]);
indexes_array_city=repmat(repelem([1:City],Citizen*Car_brand*Car_color),[1 1]);
%Initializing loop variable
column_Matrix_final=1;
for CITY_selected=1:City
for CITIZEN_selected=1:Citizen
for CAR_BRAND_selected=1:Car_brand
for CAR_COLOR_selected=1:Car_color
%Data_4D Construction
Data_4D=zeros(City,Citizen,Car_brand,Car_color);
for city=1:length(indexes_array_city)
for citizen=1:length(indexes_array_citizen)
for car_brand=1:length(indexes_array_carbrand)
for car_color=1:length(indexes_array_carcolor)
if (indexes_array_city(city)==CITY_selected && indexes_array_citizen(citizen)==CITIZEN_selected ...
&& indexes_array_carbrand(car_brand)==CAR_BRAND_selected && ...
indexes_array_carcolor(car_color)==CAR_COLOR_selected)
Data_4D(sub2ind(size(Data_4D),indexes_array_city(city),indexes_array_citizen(citizen),...
indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color)))=1;
end
end
end
end
end
%Data_4D transformation into array Data_1D
Data_1D=zeros(1,City*Citizen*Car_brand*Car_color);
tic=1;
for city=1:City
for citizen=1:Citizen
for car_brand=1:Car_brand
for car_color=1:Car_color
Data_1D(tic)=Data_4D(city,citizen,car_brand,car_color);
tic=tic+1;
end
end
end
end
%Adding Data_1D to the next for of Matrix_Final
Matrix_Final(column_Matrix_final,:)=Data_1D;
column_Matrix_final=column_Matrix_final+1;
%Display of the four most external loops indexes to show code
%advancement
CAR_COLOR_selected
end
CAR_BRAND_selected
end
CITIZEN_selected
end
CITY_selected
end
spy(Matrix_Final)
If you add e.g.
&& indexes_array_carcolor(car_color)==2
in the if loop, only the elements of Data_1D(City,Citizen,Car_brand,Car_color=2) in NRows(City,Citizen,Car_brand,Car_color=2) will be non-zero.
I would like to know if there are faster ways to set up the problem, but keeping the same ability to manipulate Data_1D an Matrix_Final using the four indexes (City,Citizen,Car_brand,Car_color) and the ability to correlate NRows and the elements of Data_1D using these four indexes.
Thank you for your help!
This is how you have coded it
if (indexes_array_city(city)==CITY_selected && indexes_array_citizen(citizen)==CITIZEN_selected ...
&& indexes_array_carbrand(car_brand)==CAR_BRAND_selected && ...
indexes_array_carcolor(car_color)==CAR_COLOR_selected)
Data_4D(sub2ind(size(Data_4D),indexes_array_city(city),indexes_array_citizen(citizen),...
indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color)))=1;
end
Another way 1
if (indexes_array_city(city)==CITY_selected && indexes_array_citizen(citizen)==CITIZEN_selected ...
&& indexes_array_carbrand(car_brand)==CAR_BRAND_selected && ...
indexes_array_carcolor(car_color)==CAR_COLOR_selected)
Data_4D(indexes_array_city(city),indexes_array_citizen(citizen),...
indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color))=1;
end
Another way 2
Data_4D(indexes_array_city(city),indexes_array_citizen(citizen),...
indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color))=double((indexes_array_city(city)==CITY_selected)& ...
(indexes_array_citizen(citizen)==CITIZEN_selected)& ...
(indexes_array_carbrand(car_brand)==CAR_BRAND_selected)& ...
(indexes_array_carcolor(car_color)==CAR_COLOR_selected));
All three of them will yield same result. Try which is faster and use it.
%% Data_4D transformation into array Data_1D
Data_4D_size=size(Data_4D);
Data_1D_size=prod(Data_4D_size);
temp = permute(Data_4D, [4 3 2 1]);
Data_1D=reshape(temp,Data_1D_size,1);
Use this for 4D to 1D convertion
If still need more speed. Compile it to mex. Compiled code runs faster.

sorting nested cell as one arrange function

i have a mat data and extract 8 feature this file.
i should arrange this features as a cell and repeat that for 12 category
i want to arrange and uniform this code as one code?
feature_mean1=zeros(12,15);
for vmean1= 1:12
feature_mean1(vmean1,:)= mean(Catrgoryy1{vmean1});
end
feature_mean2=zeros(12,15);
for vmean2= 1:12
feature_mean2(vmean2,:)= mean(Catrgoryy2{vmean2});
end
%**********************
%***************
feature_min1=zeros(12,15);
for vmin1= 1:12
feature_min1(vmin1,:)= min(Catrgoryy1{vmin1});
end
feature_min2=zeros(12,15);
for vmin2= 1:12
feature_min2(vmin2,:)= min(Catrgoryy2{vmin2});
end
%***************
X=zeros(30,4);
h=1;
X_1=[feature_mean1(1,:)',feature_std1(1,:)',feature_min1(1,:)',feature_max1(1,:)',feature_mean2(1,:)',feature_std2(1,:)',feature_min2(1,:)',feature_max2(1,:)'];%
Y_1=repmat(1,length(X_1),1);
%%%**************222*************
X_2=[feature_mean1(2,:)',feature_std1(2,:)',feature_min1(2,:)',feature_max1(2,:)',feature_mean2(2,:)',feature_std2(2,:)',feature_min2(2,:)',feature_max2(2,:)'];
Y_2=repmat(2,length(X_2),1);
%%%**************333**************
.
.
.
X_12=[feature_mean1(12,:)',feature_std1(12,:)',feature_min1(12,:)',feature_max1(12,:)',feature_mean2(12,:)',feature_std2(12,:)',feature_min2(12,:)',feature_max2(12,:)'];
Y_12=repmat(12,length(X_12),1);
at first must be form 8 array for each of the Features
then insert all of them in the for loop
for o=1:12
Xf(o,:)=[feature_mean11{o},feature_std11{o},feature_min11{o},feature_max11{o},feature_mean22{o},feature_std22{o},feature_min22{o},feature_max22{o}];
end
finish

How do I create a vector that accepts strings?

Ok the problem is, I want to receive mathematical functions. And I won't know how many until the program runs.
When it runs i ask for an n number of functions i am going to receive and it starts saving them from the input.
So far I have this
function test()
n = input('number of equations?');
v = [1:n]
%in an ideal world, this ^ here would allow me to put a string in each position but
% they are not the same type and I understand that.. but how can I build a vector for saving my functions
%I want a vector where I can put strings in each position that is what I need
for i=1:n
x = input('what is the function?','s');
v(i)=x
end
v
%this would be my vector already changed with a function in each position.
end
When you want to store strings of different lengths, use cell arrays:
v = cell(1,n);
for i=1:n
v{i} = input('what is the function?','s'); #% note the curly braces
end
To use these as functions, use str2func:
for i=1:n
fh{i} = str2func(v{i});
end
fh is now a cell array containing handles to the functions defined by the user-input strings.