I want to write this matlab code in python but I do not know what LEV(1:n+1:n^2) = 0; or LEV(i,:) means. Can anyone explain me what are this notation? Thank you!
function A = ILU_p(A,p)
n = length(A);
LEV = inf(n);
LEV(find(A)) = 0;
LEV(1:n+1:n^2) = 0;
for i = 2:n
for k = 1:i-1
if LEV(i,k) > p
continue
end
A(i,k) = A(i,k) / A(k,k);
A(i,k+1:n) = A(i,k+1:n) - A(i,k) * A(k,k+1:n);
LEV(i,k+1:n) = min([LEV(i,k+1:n); LEV(i,k) + LEV(k,k+1:n) + 1]);
end
A(i,find(LEV(i,:)>p)) = 0;
end
The below sets up a vector of values to be used in an index. If n=10 then the below would yield a row vector of [1 12 23 34 45 56 67 78 89 100]
1:n+1:n^2
Since LEV is set up as an nxn matrix and the above row vector picks up the diagonal elements, i.e., LEV(1) = LEV(1,1), LEV(12) = LEV(2,2), etc.
LEV(i,:) is MATLAB's shorthand for referencing all columns in row i.
Related
I have a simple 2D matrix like this in MATLAB:
A = [34 10;
23 10;
64 10];
What I need to do is to find max(A(:,1)), then while A(j,1) < max(A(:,1)) add rows like [A(j,1)+1 10] to the matrix, so I want to eventually get this:
A = [34 10;
35 10;
36 10;
37 10;
.
.
.
62 10;
63 10;
64 10;
.
23 10;
24 10;
25 10;
.
.
.
62 10
63 10
64 10
.
64 10];
I have written the following but it does not work:
for j = 1:size(A,1)
while A(j,1) < max(A(:,1))
A(end+1,:) = [A(j,1)+1 10];
end
end
Any ideas how I could do that?
You can try the following, for Matlab without loops:
my_max = max(A(:,1));
my_arrays = arrayfun(#(x) [x:my_max]', A(:,1), 'uni', 0);
my_expanded_column = cat(1,my_arrays{:});
my_output = [my_expanded_column, 10*ones(size(my_expanded_column))]
It first finds the maximum,
Then expands each entry to a range to the maximum,
Then combines all the ranges to one,
Then tacks on the second column of 10's.
Your while-loop gets stuck checking the same element over and over again (because you don't increment anything).
You could instead use a for-loop to count up from each element in A's first column. And make sure you add the rows to a new matrix, otherwise your loop will recursively expand A ad infinitum.
For example:
B = [];
index = 1; % keeps track of the last element of B
for j = 1:size(A,1)
for k = A(j,1):max(A(:,1))
B(index,:) = [k A(j,2)];
index = index + 1;
end
end
Scope
Matlab does include a function, named dvbs2ldpc, to construct a parity check matrix to be used at LDPC encoding stage in DVB-S2 standard.
This standard counts with two different transmission modes (SHORT and NORMAL), depending on the size of the resulting codeword. However dvbs2ldpc function only applies for NORMAL one. Thus I am trying to build up a function to be used in SHORT transmission mode.
Code description
You may find below all the related code in functions dvbs2ldpcShort.m, where I am to construct a parity check matrix for SHORT transmission mode, and LDPC.m, where I perform some BER simulations to check out the results.
You may see that dvbs2ldpcShort resembles quite a lot to dvbs2ldpc, which appears in Matlab Communication Toolbox. The two only differences that I included were changing the length of the codeword and the accumulator bits of the parity check matrix that it may correspond (please see annexes B and C from this link for further information).
Code
dvbs2ldpcShort.m
function H = dvbs2ldpcShort(R)
if R = 1/2
Rreal = 4/9; % Actual rate (as k = 7200 and N = 16200)
end
lenCodeWord = 16200; % Length of codeword for DVB-S.2
NB = 360; % Node indices parameter for DVB-S.2.
numInfoBits = lenCodeWord * Rreal;
numParityBits = lenCodeWord - numInfoBits;
[ct1, ct2] = getchecknodetable(R);
ck1 = nodeindices(ct1, numParityBits, NB);
ck2 = nodeindices(ct2, numParityBits, NB);
d = [size(ck1,2) size(ck1,1) size(ck2,2) size(ck2,1) numParityBits-1 2 1 1];
r = [ck1(:); ck2(:); 0; reshape(ones(2,1)*(1:numParityBits-1),[],1)];
S = zeros(length(r),1);
numGroup = length(d)/2;
n = 0;
ncol = 1;
for i = 1:numGroup
p = d(2*i-1)*d(2*i);
S(n+1:n+p) = reshape(ones(d(2*i),1)*(ncol:ncol+d(2*i-1)-1),p,1);
ncol = ncol + d(2*i-1);
n = n + p;
end
% Parity-check matrix (sparse) for DVB-S.2
outputFormat = 'sparse'; % Sparse matrix by default
if nargin == 2
if ~strcmp(varargin{1}, 'sparse') && ~strcmp(varargin{1}, 'indices')
error(message('comm:dvbs2ldpc:InvalidOutputFormat'));
end
outputFormat = varargin{1};
end
if strcmp(outputFormat, 'sparse')
H = logical(sparse(double(r+1), S, 1));
else
H = [double(r+1), double(S)];
end
%--------------------------------------------------------------------------
function ck = nodeindices(ct, M, NB)
% ct: check node table (single group)
% M: number of parity bits
% NB: block size
[N, D] = size(ct);
q = (M/NB);
b = (1:NB);
bq = (b-1).'*q;
ck = zeros(D, NB*N);
for r=1:N
ck(:, NB*(r-1)+1:NB*r) = mod(addcr(bq, ct(r,:)), M)';
end
%--------------------------------------------------------------------------
function A = addcr(c, r)
M = length(c);
N = length(r);
A = zeros(M, N);
for m = 1:M
A(m, :) = r + c(m);
end
%--------------------------------------------------------------------------
function [ct1, ct2] = getchecknodetable(R)
switch R
case 1/2 % There are all cases, but here I only include the R=1/2 one
ct1 = [20 712 2386 6354 4061 1062 5045 5158
21 2543 5748 4822 2348 3089 6328 5876
22 926 5701 269 3693 2438 3190 3507
23 2802 4520 3577 5324 1091 4667 4449
24 5140 2003 1263 4742 6497 1185 6202];
ct2 = [0 4046 6934
1 2855 66
2 6694 212
3 3439 1158
4 3850 4422
5 5924 290
6 1467 4049
7 7820 2242
8 4606 3080
9 4633 7877
10 3884 6868
11 8935 4996
12 3028 764
13 5988 1057
14 7411 3450];
end
LDPC.m
r = 1/2;
k = 7200;
ldpcEnc = comm.LDPCEncoder(dvbs2ldpcShort(r));
psk4Mod = comm.PSKModulator(4, 'BitInput',true);
EsNo = 0.2 : 0.1 : 1.2;
BER = zeros(size(EsNo));
for k = 1 : 1 : length(EsNo)
awgnChan = comm.AWGNChannel(...
'NoiseMethod','Signal to noise ratio (Es/No)','EsNo',EsNo(k));
psk4Demod = comm.PSKDemodulator(4, 'BitOutput',true,...
'DecisionMethod','Approximate log-likelihood ratio', ...
'Variance', 1/(2*10^(awgnChan.EsNo/10)));
ldpcDec = comm.LDPCDecoder(dvbs2ldpcShort(r));
ber = comm.ErrorRate;
for counter = 1:100
data = logical(randi([0 1], k, 1));
encodedData = ldpcEnc(data);
modSignal = psk4Mod(encodedData);
receivedSignal = awgnChan(modSignal);
demodSignal = psk4Demod(receivedSignal);
receivedBits = ldpcDec(demodSignal);
errorStats = ber(data, receivedBits);
end
BER(k) = errorStats(1);
end
Question
The corresponding BER curve does not resemble at all to how it is for NORMAL transmission mode (these represent the BER as function of SNR. and mine are function of EbNo, but the difference shouldn't be really big at all). Instead, results seem to be unexpectedly good. Can you see anything wrong with my code?
What could be wrong in my code?
Many thanks in advance, and may you have a nice weekend!
Thanks for the note on LDPC code identifier and Effective LDPC rate.
Your example-performance should be better, because you use more redundancy: 5/9 (0.56) of code word whereas in the MATLAB example they use (1 - 2/3) = 1/3 (0.33) of code word as redundancy.
I would like to add a note also: In the ETSI standard they also use a parameter q, that is equal to q = (M/NB); (M -- num of parity bits, NB = 360) when the n_ldpc = 64800, but if n_ldpc = 16200 the q should be used according a table in the ETSI standard.
Let's look at my solution: dvbs2ldpc_custom
I have a matrix and i want to select a range of elements.
for example i want to select all the elements that are lower than 182 and swap/change them.
does someone know an easy way or command to do this in matlab ?
thanx
Since you say "swap", I understand you mean a vector, not a matrix. You can do it as follows:
x = [ 1 34 66 22 200 55 301 ]; % data
[ values, ind ] = find(x<182);
x(ind) = x(ind(end:-1:1));
To simply replace them by another value such as NaN, do as follows. Note that this works also for matrices:
x = [ 1 34 66 22 200 55 301 ]; % data
x(x<182) = NaN;
Such things can usually be accomplished via logical indexing:
A = randn(1,100);
B = randn(size(A));
test = (A>1|A<0); % For example, values that are greater than 1 or less than 0
A(test) = B(test);
or another example:
A = randn(1,100);
test = (A>1|A<0);
A(test) = randn(1,nnz(test));
or another:
A = randn(1,100);
A(A>1|A<0) = NaN;
You may use loop like this:
for i = 1:length(matrix(:,1))
for j = 1:length(matrix(1,:))
if matrix(i,j) < 182
matrix(i,j) = NaN;
end
end
end
Hi everyone this is What I did to carry out an iteration method(gauss seidel) and I want when iteration number greater than 30 it will stop and generate the corresponding result up to 30 iteration. But I wonder why the output result were so weird and I try to check the value on the command window by typing x_ans(:,1) it gives me the correct value. It really made me frustrated why the generate result were not the same. Or any other circumstance or function can be used to set for not converging condition. Sincerely thanks in advance for every single help.
clear;clc
A = [2 8 3 1;0 2 -1 4;7 -2 1 2;-1 0 5 2]
B = [-2;4;3;5]
Es = 1e-5
n = length(B);
x = zeros(n,1);
Ea = ones(n,1);
iter = 0;
while max(Ea) >= Es
if iter <= 30
iter = iter + 1;
x_old = x;
for i = 1:n
j = 1:n;
j(i) = [];
x_cal = x;
x_cal(i) = [];
x(i) = (B(i) - sum(A(i,j) * x_cal)) / A(i,i);
end
else
break
end
x_ans(:,iter) = x;
Ea(:,iter) =abs(( x - x_old) ./ x);
end
result = [1:iter; x_ans; Ea]'
I've gone through the formulas and they are all OK. On a side note, the sum is not necessary. The problem lies with your input data - try reordering! check for example the following, which works
A = [7 -2 1 2;
2 8 3 1;
-1 0 5 2;
0 2 -1 4;]
B = [3;-2;5;4]
see the wiki under convergence.
When I answered this question, my answer started with: "For starters, you can get rid of all the if-statements by storing all the names in a cell."
The "For starters" bit was because I thought that I could add an edit with a vectorized solution. But when I tried to do so I ran into trouble vectorizing the use of mrdivide (b/a).
My question (marked below in the code) is if it is possible to solve b(z,:)/a(z,:) without using a loop. In other words, to solve b/a independently for each row of the matrices.
person = [98 206 35 114;
60 206 28 52;
100 210 31 116;
69 217 26 35;
88 213 42 100];
person1 = [93 208 34 107];
allNames = {'Cameron'; 'David'; 'Mike'; 'Bill'; 'Joe'};
n = 5;
a = max(person,repmat(person1,n,1));
b = min(person,repmat(person1,n,1));
for z = 1:5
percent_error = b(z,:)/a(z,:); %// Here is my question
if percent_error >= 0.85
disp(['Match, its ', allNames{z} ,'!'])
end
end
You can indeed eliminate the loop by vectorizing the operation. The trick is working with diagonal block matrices. Each block is matrix with only one row (each time a different row). After you create such a block matrix for a and for b, you can use mrdivide:
% # Without loop
tic
A = zeros(size(a) * size(a, 1));
B = zeros(size(b) * size(b, 1));
V = ones(size(a, 2), 1) * (1:size(a, 1));
idx = (0:size(A, 1):numel(A) - 1) + (V(:)' - 1) * size(a, 1) + 1;
A(idx) = a';
B(idx) = b';
X = diag(B / A);
percent_error1 = X(1:size(a, 1):end);
toc
% # With loop
tic
percent_error2 = zeros(5, 1);
for z = 1:5
percent_error2(z) = b(z,:) / a(z,:);
end
toc
The result is:
Elapsed time is 0.000160 seconds.
Elapsed time is 0.000048 seconds.
percent_error1 =
0.9741
0.8516
0.9670
0.8221
0.9611
percent_error2 =
0.9741
0.8516
0.9670
0.8221
0.9611
Note that this is one of those cases where matrix division of large arrays takes longer than a for loop.
I was thinking about this:
person/person1
But this would only give good result when every index in person is bigger than the corresponding index in person1.