Unusual observation during LLyod algorithm implementation in 2D matrix. How can I pinpoint error? - matlab

During the implementation of llyod algorithm in 2D matrix, I encountered unusual value assigned by code. The region belonging to same partition is assigned different value, particularly 0 that is causing the problem. How can I pinpoint the error?
The code is written in Matlab.
.
On execution of following custom code in Matlab to implement llyod max quantizer
%This code perform quantization using llyod max quantizer algorithm
%
function [mat2encode,distor,rel_distor,d,r]=llyod_quant(mat2quant_scal_f)
%declaring quantization matrix
quant_mat=zeros(size(mat2quant_scal_f));
bts=input('enter the number of bits to represent decision level for llyod quantizer: ');
lvl=2.^(bts);
[e1,e2]=size(mat2quant_scal_f);
row_vector=reshape(mat2quant_scal_f,[1,e1*e2]);
[M1,N1]=size(row_vector);
tot_num=M1*N1;
[d, r, distor,rel_distor] = lloyds(row_vector,lvl);
for k=1:lvl-1
if k==size(d,2)
[v1,v2]=find(mat2quant_scal_f>=d(k-1) & mat2quant_scal_f<d(k));
for j=1:length(v1)
quant_mat(v1(j),v2(j))=round(r(k));
end
else
[v1,v2]=find(mat2quant_scal_f>=d(k) & mat2quant_scal_f<d(k+1));
for j=1:length(v1)
quant_mat(v1(j),v2(j))=round(r(k));
end
end
end
mat2encode=quant_mat;
end
The output for element (1,33) and (9,33) element of matrix is (89) and (0) as shown below:
The code should have assigned the output 89 to both elements but that's not the case. I am perplexed.
Edit
Input matrix is uploaded here.

Related

Array indices must be positive integers or logical value when read images in matlab

trying to read multi images in matlab in loop so error Array indices must be positive integers or logical values is appear
for i=1:12 % we have 16 images we have in or folder
clc;clear;
images ='/home/mohamed/Downloads/Lab6-20200415/Lab6-20200421/Lab6/Lab6/';
jpgfiles=dir(fullfile(images,'\*.jpg*'));
n=numel(jpgfiles(i));
im=jpgfiles(i).name;
im1=imread(fullfile(images,im));
d1 = rg2gray(iml);
imshow(im1);
end
Here is a minimal example demonstrating your problem:
for i=1:10
clear
jpgfiles=rand(10,1); %some dummy data to replace your actual code
jpgfiles(i);
end
the clear deletes the variable i which means i is the imaginary unit, not a valid index. Avoid the variable name i, it leads to difficult to debug problems. With other variable names, the much clearer error message would have been:
Unrecognized function or variable 'ix'.
Error in foo (line 4)
jpgfiles(ix);

How can I make each array multiply by each other in a nested for loop, using MATLAB?

Currently, I'm working on a school project involving buck converters. As current increase through an inductor, its inductance decrease (most likely). Each phase is adding an inductor. By adding an inductor, I divide the current by each added inductor. The current is ramped from 0 to 500.
My issue with the following code is that it does not use each array value of i_L(i,j) correctly. I receive some negative values, which is absolutely wrong.
In example...
At 500 Amps with 10 phases, each inductor uses 50 amps. Now L will be designed after
i_L(i,j)=current(j)./phases(i)= 500/10=50amps
L(i,j)= (-9.22297516731983*10^(-16).*(50^(4)))+(9.96260934359008*10^(-14).*(50^(3)))-(3.6355216850551*10^(-12).*(50^(2)))+(9.0205832462444*10^(-12).*(50^(1)))+1.06054781561763E-07 = 1.04106*10^(-7)
and so on
creating 10x10 = 100 cells
clc; clear all;
phases=linspace(1,10,10);
current=linspace(0,500,10);
for j = 1:10
for i=1:10
i_L(i,j)=current(j)./phases(i);
L(i,j)=(-0.000000000000000922297516731983*(i_L(i,j).^(4)))+(0.000000000000099626093435900800*(i_L(i,j).^(3)))-(0.000000000003635521685055100000*(i_L(i,j).^(2)))+(0.000000000009020583246244400000*(i_L(i,j).^(1)))+0.000000106054781561763000000000;
end
end
Thank you!
Your matrix i_L(i,j) got values up to 500=500(current)/1(amp).
The polynomial you're using is generating negative solutions for values greater than 130.
So the operation is using each array value correct.
Maybe you should reevaluate the polynomial, if you're dissatisfied with the solution.
Try:
x=[0:1:500];
y=(-9.22297516731983*10^(-16).*(x.^(4)))+(9.96260934359008*10^(-14).*(x.^(3)))-(3.6355216850551*10^(-12).*(x.^(2)))+(9.0205832462444*10^(-12).*(x.^(1)))+1.06054781561763E-07;
plot(x,y)
You will see the polynomial will diverge against negative infinite for positive values.

for loop over the first column of a matrix and mean

I have codes to solve some stochastic equations.
My function file
[S,T]=simByEuler(MDL, nPeriods,'DeltaTime',params.dt);
is running fine where S is a matrix its first column is theta and the second column is phi. S has 1001 rows. T is a vector of time of dimension 1001*1. Please ignore T. Focus on S which has 2 columns theta and phi,
i.e S=[theta, phi]. Dimension of S is 1001*2.
I want to write a for loop to generate 500 sample of the theta then take the mean of all of these 500. To start, the code I put in the question has random parameters. This code should be inside the for loop so that as the loop start again the code:
[S,T]=simByEuler(MDL, nPeriods,'DeltaTime',params.dt);
will generate random variable and run the for loop till end to generate new theta. What I am looking for is to have a block of these 500 theta (remember theta is a column). This block should be of size 1001*500. Then I want to take the mean of all columns in this block so the mean should be of size 1001*1.
My questions are:
1) How to write a for loop to generate this block of size 1001*500.
2) How to take the mean of all columns in the block so that the mean will be of size 1001*1.
I hope my questions are clear and I really appreciate any help.
Is this what you look for?
N = 500; % the size of a block
S = zeros(1001,2,N);
for k = 1:N
[S(:,:,k),T]=simByEuler(MDL, nPeriods,'DeltaTime',params.dt);
end
mean_theta = mean(squeeze(S(:,1,:)),2);

MATLAB: Using FZERO on a function which has a vector output

I am working on my thesis and running in some programming problems in Matlab. I am trying to implement the ''golden Bisection Method'' to speed up my code. To this end, I've consulted the build in function FZERO.
So I am determining the difference between two vectors which are both (1x20).
Difference = Clmax_dist-cl_vec;
Clmax_dist comes from a semi-empirical method and cl_vec comes from the excecution of an external AVL.exe file.
Essentially, this difference depends only on one single variable AOA because the Clmax_dist vector is a constant. Hence, I am constantly feeding a new AOA value to the AVL.exe to obtain a new cl_vec and compare this again to the constant Clmax_dist.
I am iterating this until one of the element in the vector becomes either zero or negative. My loop stops and reveals the final AOA. This is a time consuming method and I wanted to use FZERO to speed this up.
However, the FZERO documentation reveals that it only works on function which has a scalar as input. Hence, my question is: How can I use FZERO with a function which has a vector as an output. Or do i need to do something totally different?
I've tried the following:
[Difference] = obj.DATCOMSPANLOADING(AOA);
fun=#obj.DATCOMSPANLOADING;
AOA_init = [1 20];
AOA_root = fzero(fun,AOA_init,'iter');
this gave me the following error:
Operands to the || and && operators must be convertible to logical scalar values.
Error in fzero (line 423)
while fb ~= 0 && a ~= b
Error in CleanCLmax/run (line 11)
AOA_root = fzero(fun,AOA_init,'iter');
Error in InitiatorController/moduleRunner (line 11)
ModuleHandle.run;
Error in InitiatorController/runModule (line 95)
obj.moduleRunner(ModuleHandle);
Error in RunSteps (line 7)
C.runModule('CleanCLmax');
The DATCOMSPANDLOADING function contains the following:
function [Difference] = DATCOMSPANLOADING(obj,AOA)
[Input]= obj.CLmaxInput; % Creates Input structure and airfoil list
obj.writeAirfoils(Input); % Creates airfoil coordinate files in AVL directory
[Clmax_dist,YClmax,Cla_mainsections] = obj.Clmax_spanwise(Input); % Creates spanwise section CLmax with ESDU method
[CLa] = obj.WingLiftCurveSlope(Input,Cla_mainsections); % Wing lift curve slope
[Yle_wing,cl_vec] = obj.AVLspanloading(Input,CLa,AOA); % Creates spanloading with AVL
Difference = Clmax_dist-cl_vec;
end
If I need to elaborate further, feel free to ask. And of course, Thank you very much.
fzero indeed only works on scalars. However, you can turn your criterion into a scalar: You are interested in AOA where any of the elements in the vector becomes zero, in which case you rewrite your objective function to return two output arguments: minDifference, which is min(Difference), and Difference. The first output, minDifference is the minimum of the difference, i.e. what fzero should try to optimize (from your question, I'm assuming all values start positive). The second output you'd use to inspect your difference vector in the end.

Gauss-Seidel Method exceeds Machine Numbers?

Happy New Year everyone! :)
I'm writing a Gauss-Seidel function in Matlab and I'm encountering some problems.
The iteration must stop when we reach 6 decimal digits of precision. It means that the infinite norm (asked to use it) of x-xprevious must be less than 0.5*10^(-6).
Firstly, here's my function:
function [x] = ex1_3(A,b)
format long
sizeA=size(A,1);
x=zeros(sizeA,1);
%Just a check for the conditions of the Gauss-Seidel Method
for i=1:sizeA
sum=0;
for j=1:sizeA
if i~=j
sum=sum+A(i,j);
end
end
if A(i,i)<sum
fprintf('\nGauss-Seidel''s conditions not met!\n');
return
end
end
%Actual Gauss-Seidel Method
max_temp=10^(-6); %Pass first iteration
while max_temp>(0.5*10^(-6))
xprevious=x;
for i=1:sizeA
x(i,1)=b(i,1);
for j=1:sizeA
if i~=j
x(i,1)=x(i,1)-A(i,j)*x(j,1);
end
end
x(i,1)=x(i,1)/A(i,i);
end
x
%Calculating infinite norm of vector x-xprevious
temp=x-xprevious;
max_temp=temp(1,1);
for i=2:sizeA
if abs(temp(i,1))>max_temp
max_temp=abs(temp(i,1));
end
end
end
And now the problems! When I call the function for a 3x3 array, I think it works. However, when I call it for a 10x10 array x becomes Inf (I guess it's out of machine numbers limits). Is there anything I can do to prevent this, except for changing the infinite norm and the 6 decimal digits precision (I must use these two, because my tutor told me so) ?
In the array I use (which was given to me) the entries outside the diagonal are -1 and the ones on the diagonal are 3. b is like this b=[2;1;1;1;1;1;1;1;1;2] (for n=10)
Your condition of the Gauss-Seidel Method is not correct:
D=diag(diag(A));
L=-tril(A,-1);U=-triu(A,1);
B=(D-L)\U;
R = max(abs(eig(B)));
if R>=1
fprintf('\nGauss-Seidel''s conditions not met!\n');
return
end
R is called spectral radius of iterative matrix B. It has to be less than 1 that Gauss-Seidel converges. Actually the matrix A in your test case has the R=1.8092, thus Gauss-Seidel method won't converge.
Check this slide from page 18 for more details.
EDIT
According to #LutzL's comment, you may use Gershgorin circle theorem to estimate the eigenvalue rather than calculate them with computational cost.