Undefined function or variable "new_m" - matlab

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.

Related

How do I adjust this code so that I can enter how many runs I want and it will store each run in a matrix?

I have created this code to generate a 1 set of lottery numbers, but I am trying to make it so that the user can enter how many sets they want (input n), and it will print out as one long matrix of size nX6? I was messing around with a few options from online suggestions, but to no avail. I put the initial for i=1:1:n at the beginning, but I do not know how to store each run into a growing matrix. Right now it still generates just 1 set.
function lottery(n)
for i=1:1:n
xlow=1;
xhigh=69;
m=5;
i=1;
while (i<=m)
lottonum(i)=floor(xlow+rand*(xhigh-xlow+1));
flag=0;
for j=1:i-1
if (lottonum(i)==lottonum(j))
flag=1;
end
end
if flag==0
i=i+1;
end
end
ylow=1;
yhigh=26;
m=1;
lottonum1=floor(ylow+rand*(yhigh-ylow+1));
z = horzcat(lottonum, lottonum1);
end
disp('The lotto numbers picked are')
fprintf('%g ',z)
disp (' ')
The problem is that you are not storing or displaying the newly generated numbers, only the last set. To solve this, initialize z with NaNs or zeros, and later index z to store each set in a row of z, by using z(i,:) = lottonum.
However, you are using i as iterator in the while loop already, so you should use another variable, e.g. k.
You can also set z as an output of the function, so you can use this matrix in some other part of a program.
function z = lottery(n)
% init z
z = NaN(n,6);
for k = 1:n
xlow=1;
xhigh=69;
m=5;
i=1;
while (i<=m)
lottonum(i)=floor(xlow+rand*(xhigh-xlow+1));
flag=0;
for j=1:i-1
if (lottonum(i)==lottonum(j))
flag=1;
end
end
if flag==0
i=i+1;
end
end
ylow=1;
yhigh=26;
lottonum1 = floor(ylow+rand*(yhigh-ylow+1));
z(k,:) = horzcat(lottonum, lottonum1); % put the numbers in a row of z
end
disp('The lotto numbers picked are')
disp(z) % prettier display than fprintf in this case.
disp (' ')
end
The nice answer from rinkert corrected your basic mistakes (like trying to modify your loop iterator i from within the loop => does not work), and answered your question on how to store all your results.
This left you with a working code, however, I'd like to propose to you a different way to look at it.
The porposed architecture is to divide the tasks into separate functions:
One function draw_numbers which can draw N numbers randomly (and does only that)
One function draw_lottery which call the previous function as many times as it needs (your n), collect the results and display them.
draw_lottery
This architecture has the benefit to greatly simplify your main function. It can now be as simple as:
function Draws = draw_lottery(n)
% define your draw parameters
xmin = 1 ; % minimum number drawn
xmax = 69 ; % maximum number drawn
nballs = 5 ; % number of number to draw
% pre allocate results
Draws = zeros( n , nballs) ;
for iDraw=1:1:n
% draw "nballs" numbers
thisDraw = draw_numbers(xmin,xmax,nballs) ;
% add them to the result matrix
Draws(iDraw,:) = thisDraw ;
end
disp('The lotto numbers picked are:')
disp (Draws)
disp (' ')
end
draw_numbers
Instead of using a intricated set of if conditions and several iterators (i/m/k) to branch the program flow, I made the function recursive. It means the function may have to call itself a number of time until a condition is satisfied. In our case the condition is to have a set of nballs unique numbers.
The function:
(1) draws N integer numbers randomly, using randi.
(2) remove duplicate numbers (if any). Using unique.
(3) count how many unique numbers are left Nu
(4a) if Nu = N => exit function
(4b) if Nu < N => Call itself again, sending the existing Nu numbers and asking to draw an additional N-Nu numbers to add to the collection. Then back to step (2).
in code, it looks like that:
function draw = draw_numbers(xmin,xmax,nballs,drawn_set)
% check if we received a partial set
if nargin == 4
% if yes, adjust the number of balls to draw
n2draw = nballs - numel(drawn_set) ;
else
% if not, make a full draw
drawn_set = [] ;
n2draw = nballs ;
end
% draw "nballs" numbers between "xmin" and "xmax"
% and concatenate these new numbers with the partial set
d = [drawn_set , randi([xmin xmax],1,n2draw)] ;
% Remove duplicate
drawn_set = unique(d) ;
% check if we have some more balls to draw
if numel(drawn_set) < nballs
% draw some more balls
draw = draw_numbers(xmin,xmax,nballs,drawn_set) ;
else
% we're good to go, assign output and exit funtion
draw = drawn_set ;
end
end
You can have both functions into the same file if you want.
I encourage you to look at the documentation of a couple of Matlab built-in functions used:
randi
unique

MATLAB parfor error

I have a Matlab function in which I use parfor and it goes like this:
sbestposition=zeros(8,38);
sbestvalue=zeros(8,1);
matlabpool open 8
parfor i=1:8
[ sbestvalue(i) sbestposition(i,1:i+30)] = pso(lb, ub, s2, i+31, 30,1,2,2 );
end
matlabpool close
The sizeof sbestposition depends of the value of i and it is (1,31) when i=1 and (1,38) when i=8; and I intend to keep their values in one variable.
The function works when it is [ sbestvalue(i) sbestposition(i,:)] = pso(lb, ub, s2, i+31, 30,1,2,2 ); But when I use it, the function will not work again because of the dimension mismatch error.
Instead, here it gives an error
The variable sbestposition in a parfor cannot be classified
How do I overcome this?
Thank you.
Why not use a cell array for sbestposition
parfor i = 1:8
[sbestvalue(i), sbestposition{i}] = ...
end
Matlab does not "know" how to slice a variable in such a complex pattern. Every iteration uses at most the full row, most less that the row. Make it obvious that the variable should be sliced row wise:
parfor i=1:8
p=zeros(1,38);
[sbestvalue(i),p(1:i+30)]=pso(lb, ub, s2, i+31, 30,1,2,2 );
sbestposition(i,:)=p;
end
In this code, the toolbox can push each row to one worker, having obviously no interference.
You are changing the dimension of the variable inside the parloop.

How to count the number of iterations

I'm working with k-means on MATLAB. To process the valid cluster, it needs to do a looping until the cluster position doesn't change any more. The looping will show the iterations process.
I want to count how many looping/iteration happens on that clustering process. Here is the snippet of looping/iteration processing part:
while 1,
d=DistMatrix3(data,c); %// calculate the distance
[z,g]=min(d,[],2); %// set the matrix g group
if g==temp, %// if the iteration does not change anymore
break; %// stop the iteration
else
temp=g; %// copy the matrix to the temporary variable
end
for i=1:k
f=find(g==i);
if f %// calculate the new centroid
c(i,:)=mean(data(find(g==i),:),1);
end
end
end
All I know that I have to do is define the iteration variable, and then write the calculation part. But, where do I have to define the variable? And how?
All the answers will be so much appreciated.
Thank you.
A Matlab while-loop is executed until the expression is false. The general setup is like this:
while <expression>
<statement>
end
If you want to count the number of times the while loop was entered, the easiest way is to declare a variable outside the loop and incrementing it inside:
LoopCounter = 0;
while <expression>
<statement>
LoopCounter = LoopCounter + 1;
end
The question whether to increment the LoopCounter before or after the <statement> depends on whether you need it to access vector entries. In that case, it should be incremented before the <statement> because 0 is not a valid index in Matlab.
Define before your loop, update in your loop.
iterations=0;
while 1,
d=DistMatrix3(data,c); % calculate the distance
[z,g]=min(d,[],2); % set the matrix g group
if g==temp, % if the iteration doesn't change anymore
break; % stop the iteration
else
temp=g; % copy the matrix to the temporary variable
end
for i=1:k
f=find(g==i);
if f % calculate the new centroid
c(i,:)=mean(data(find(g==i),:),1);
end
end
iterations=iterations+1;
end
fprintf('Did %d iterations.\n',iterations);

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.

Cell Array or Multi-Subscripted Array?

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