├── README.md ├── RM_Polar_Profile.m ├── References.m ├── Z_polarization_fast.m ├── calc_met_gaussian.m ├── genparity_Rone_logical.m ├── main_PAC.m ├── pac_decode2.m ├── phiF_vec.mat ├── phi_vector2.mat └── polarencode.m /README.md: -------------------------------------------------------------------------------- 1 | # Performance-and-computational-analysis-of-polarization-adjusted-convolutional-PAC-codes 2 | Performance and computational analysis of polarization-adjusted convolutional (PAC) codes; Fano decoding algorithm 3 | 4 | You may reference the following works if you are using our implementation. You are welcome to contact me for further discussion or cooperation. 5 | 6 | [1] Moradi, Mohsen. Performance and computational analysis of polarization-adjusted convolutional (PAC) codes. Diss. Bilkent University, 2022. 7 | 8 | [2] Moradi, Mohsen. (2021). "On Sequential Decoding Metric Function of PolarizationAdjusted Convolutional (PAC) Codes.” IEEE Transactions on Communications (DOI 10.1109/TCOMM.2021.3111018). 9 | 10 | [3] Moradi, M., Mozammel, A. (2021). "A Tree Pruning Technique for Decoding Complexity Reduction of Polar Codes and PAC Codes.” arXiv preprint arXiv:2207.11946. Under revision IEEE Transactions on Communications. 11 | 12 | [4] Moradi, M., Mozammel, A., Qin, K., and Arıkan, E. (2020). "Performance and Complexity of Sequential Decoding of PAC Codes." arXiv preprint arXiv:2012.04990. 13 | 14 | [5] Moradi, M., Mozammel, A. (2021). "A Monte-Carlo Based Construction of PolarizationAdjusted Convolutional (PAC) Codes.” arXiv preprint arXiv:2106.08118. 15 | 16 | [6] Moradi, M., Mozammel, A. (2022). "Concatenated Reed-Solomon and PolarizationAdjusted Convolutional (PAC) Codes." Accepted by IEEE International Black Sea Conference on Communications and Networking (BlackSeaCom) [25]. 17 | 18 | [7] Moradi, Mohsen. (2022). "Bit-Flipping for Stack Decoding of Polarization-Adjusted Convolutional (PAC) Codes." Accepted by IEEE 10th International Workshop on Signal Design and its Applications in Communications (IWSDA). 19 | 20 | [8] Mozammel, Amir. "Hardware implementation of Fano decoder for polarization-adjusted convolutional (PAC) codes." IEEE Transactions on Circuits and Systems II: Express Briefs 69.3 (2021): 1632-1636. 21 | 22 | [9] Moradi, Mohsen. (2022). "Application of Guessing to Sequential Decoding of Polarization-Adjusted Convolutional (PAC) Codes.” arXiv preprint arXiv:2208.04010. Submitted to IEEE Transactions on Communications. 23 | 24 | -------------------------------------------------------------------------------- /RM_Polar_Profile.m: -------------------------------------------------------------------------------- 1 | function RP = RM_Polar_Profile(N, K, SNR, type) 2 | % type 1 -------> GA consttruction, see [2] 3 | % type 2 -------> RMpolar construction see [1]. 4 | % type 3 -------> Tse RMpolar construction 5 | % type 4 -------> RM profile, see [4, 2] 6 | % N = 1024; K = 512; SNR = 2; 7 | R = K/N; 8 | 9 | EbNo_X = 10^(SNR/10); 10 | sigma_X = 1/sqrt(2*R*EbNo_X); 11 | ZW_X = Z_polarization_fast(N,sigma_X); 12 | 13 | if type == 1 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | % PRP rate profile (K most reliable channels) 16 | RP = false(1,N); 17 | [~,I] = mink(ZW_X, K); 18 | RP(I) = true; 19 | % sum(RP) 20 | 21 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 22 | elseif type == 2 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | Klow1 = 0; 25 | n = log2(N); 26 | i = n; 27 | while Klow1 < K 28 | if Klow1 + nchoosek(n,i) < K 29 | Klow1 = Klow1 + nchoosek(n,i); 30 | else 31 | break; 32 | end 33 | i = i-1; 34 | end 35 | 36 | [RP, w] = RM_profile(Klow1,N); 37 | idx_w = find(w==i); % rows with weight i 38 | 39 | E0_X = log2(2./(1+ZW_X)); 40 | 41 | X = zeros(1,N); 42 | X(idx_w) = E0_X(idx_w); 43 | [~,I] = sort(X,'descend'); 44 | I(K-Klow1+1:end) = []; % most reliable rows with weight i 45 | RP(I) = true; 46 | % sum(RP) 47 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 48 | elseif type == 3 49 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 50 | % Klow2 > K and we choose the most reliable ones from it 51 | Klow2 = 0; 52 | n = log2(N); 53 | i = n; 54 | while Klow2 <= K 55 | Klow2 = Klow2 + nchoosek(n,i); 56 | i = i-1; 57 | end 58 | [RP, ~] = RM_profile(Klow2,N); 59 | 60 | E0_X = log2(2./(1+ZW_X)); 61 | 62 | E = 1e6*E0_X; 63 | RP_X = RP.*E; 64 | [~,I] = maxk(RP_X, K); 65 | 66 | RP = false(1,N); 67 | RP(I) = true; 68 | % sum(RP) 69 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 70 | elseif type == 4 71 | [RP, ~] = RM_profile(K,N); 72 | end 73 | 74 | end 75 | 76 | 77 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 78 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 79 | function [P, w] = RM_profile(K,N) 80 | w = sum(dec2bin(0:N-1)-'0',2); 81 | [~, index] = sort(w,'descend'); 82 | kindex = index(1:K); 83 | P = false(1,N); 84 | P(kindex) = true; 85 | end 86 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 87 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /References.m: -------------------------------------------------------------------------------- 1 | % References 2 | 3 | % [1] Moradi, Mohsen. Performance and computational analysis of 4 | % polarization-adjusted convolutional (PAC) codes. Diss. Bilkent University, 2022. 5 | 6 | % [2] Moradi, Mohsen. (2021). "On Sequential Decoding Metric Function 7 | % of PolarizationAdjusted Convolutional (PAC) Codes.” IEEE Transactions 8 | % on Communications (DOI 10.1109/TCOMM.2021.3111018). 9 | 10 | % [3] Moradi, M., Mozammel, A. (2022). "A Tree Pruning Technique for 11 | % Decoding Complexity Reduction of Polar Codes and PAC Codes." 12 | % Submitted to the IEEE Transactions on Communications. 13 | 14 | % [4] Moradi, M., Mozammel, A., Qin, K., and Arıkan, E. (2020). 15 | % "Performance and Complexity of Sequential Decoding of PAC 16 | % Codes." arXiv preprint arXiv:2012.04990. 17 | 18 | % [5] Moradi, M., Mozammel, A. (2021). "A Monte-Carlo Based Construction 19 | % of PolarizationAdjusted Convolutional (PAC) Codes.” 20 | % arXiv preprint arXiv:2106.08118. 21 | 22 | % [6] Moradi, M., Mozammel, A. (2022). "Concatenated Reed-Solomon and 23 | % PolarizationAdjusted Convolutional (PAC) Codes." Accepted by IEEE 24 | % International Black Sea Conference on Communications and 25 | % Networking (BlackSeaCom) [25]. 26 | 27 | % [7] Moradi, Mohsen. (2022). "Bit-Flipping for Stack Decoding of 28 | % Polarization-Adjusted Convolutional (PAC) Codes." Accepted by IEEE 29 | % 10th International Workshop on Signal Design and its Applications 30 | % in Communications (IWSDA). 31 | 32 | % [8] Mozammel, Amir. "Hardware implementation of Fano decoder for 33 | % polarization-adjusted convolutional (PAC) codes." IEEE Transactions 34 | % on Circuits and Systems II: Express Briefs 69.3 (2021): 1632-1636. -------------------------------------------------------------------------------- /Z_polarization_fast.m: -------------------------------------------------------------------------------- 1 | function ZW = Z_polarization_fast(N,sigma) 2 | % SNR_dB = SNR_vec(i); % 2.5dB 3 | % ebn0 = 10^(SNR_dB/10); % R = .5; 4 | % sigma = 1/sqrt(2*R*ebn0); % sigma = 0.7499; 5 | 6 | fc = @(t) phi_inv(1-(1-phi_fun(t))^2); % Check node(left branch) operation 7 | fv = @(t) 2*t; % Bit node(right branch) operation 8 | 9 | n = log2(N); 10 | m = zeros(1,2*N-1); % all the tree nodes 11 | m(1) = 2/sigma^2; % Ititialize the tree root mean 12 | % In the tree, the left branch is check operation(fc) and right branch is 13 | % node operation(fv) 14 | for d = 1:n 15 | u = 0; 16 | for i = 0:2^d-1 17 | if u == 2^d 18 | break; % nodes in the depth d finished 19 | end 20 | if mod(i+1,2) == 1 % left branch operation 21 | m(2^d+i) = fc(m(2^(d-1)+floor(i/2))) ; 22 | else % right branch operation 23 | m(2^d+i) = fv(m(2^(d-1)+floor(i/2))); 24 | end 25 | u = u+1; 26 | end 27 | end 28 | 29 | ZW = exp(-m(N:2*N-1)/4); % Z(W) = e^(-1/2sigma^2), m = 2/sigma^2; 30 | 31 | end 32 | 33 | function phi = phi_fun(t) 34 | % The phi function in the Gaussian approximation 35 | load('phiF_vec.mat'); 36 | if t == 0 37 | phi = 1; 38 | elseif t < 50 39 | [~,I] = min(abs(A-t)); 40 | phi = phi_vec(I) ; 41 | % syms z 42 | % F = tanh(z/2).*exp(-(z-t).^2./(4*t)); 43 | % phi = 1 - 1./(sqrt(4*pi*t)).*double(int(F,z,-100,100)); 44 | else 45 | phi = 1.1795e-06; 46 | end 47 | 48 | end 49 | 50 | function t = phi_inv(y) 51 | load('phi_vector2.mat'); % contains x = .01:.01:45; and corresponding phi values 52 | if y == 1 53 | t = 0; 54 | else 55 | [~,I] = min(abs(phi_vector-y)); 56 | t = x(I) ; 57 | end 58 | end 59 | 60 | % The way I calculated phi_vector.mat 61 | % x = .01:.01:45; 62 | % syms z 63 | % F = tanh(z/2).*exp(-(z-x).^2./(4*x)); 64 | % Integ = int(F,z,-100,100); 65 | % Integ = double(Integ); 66 | % phi_vector = 1 - 1./(sqrt(4*pi*x)).*Integ; 67 | % semilogy(x,phi_vector,'-b'); 68 | % % Q_1 = exp(-0.4527*x^0.86 + 0.0218); % 010 % GA Approximations 70 | 71 | 72 | 73 | 74 | % 75 | % % The way I calculated phi_vector for inverse.mat 76 | % x = .01:.1:45; 77 | % syms z 78 | % F = tanh(z/2).*exp(-(z-x).^2./(4*x)); 79 | % Integ = int(F,z,-100,100); 80 | % Integ = double(Integ); 81 | % phi_vector = 1 - 1./(sqrt(4*pi*x)).*Integ; 82 | % semilogy(x,phi_vector,'-b'); 83 | % % Q_1 = exp(-0.4527*x^0.86 + 0.0218); % 010 % GA Approximations 85 | 86 | 87 | 88 | 89 | % 90 | % % the way I calculated phiF_vec.mat for forward phi 91 | % clear; clc; close all 92 | % A = 0.1:0.1:50; 93 | % phi_vec = zeros(1,length(A)); 94 | % parfor i = 1:length(A) 95 | % phi_vec(i) = phi_fun(A(i)); 96 | % 97 | % end 98 | % 99 | % plot(A,phi_vec) -------------------------------------------------------------------------------- /calc_met_gaussian.m: -------------------------------------------------------------------------------- 1 | function metric = calc_met_gaussian(LLR,u,b) 2 | % Compute the Fano metric for conv coded data through polarized channel for 3 | % BPSK modulated signal with the following mapping 4 | % 0 --> +1 5 | % 1 --> -1 6 | % LLR = soft output of SC decoder 7 | % u = hypothesis 8 | % b = bias 9 | Lj = exp(LLR); 10 | % if u == 0 11 | % metric = log2(2/(1+1/Lj)) - b; 12 | % else 13 | % metric = log2(2/(1+Lj)) - b; 14 | % end 15 | 16 | if u == 0 17 | metric = 1 - log2(1+1/Lj) - b; 18 | else 19 | metric = 1 - log2(1+Lj) - b; 20 | end 21 | 22 | -------------------------------------------------------------------------------- /genparity_Rone_logical.m: -------------------------------------------------------------------------------- 1 | function u = genparity_Rone_logical(inp,state,polyL) 2 | % convolutional encoder for a given state of the blocks 3 | % polyL is PAC conv of 133 --> 1 011 011 4 | % for a given inout inp, output is u 5 | new_state = [inp state]; 6 | u = mod(sum(new_state(polyL)),2); 7 | 8 | -------------------------------------------------------------------------------- /main_PAC.m: -------------------------------------------------------------------------------- 1 | clear; clc; close all 2 | 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | % This is for "parfor" and CoreNum = 1 is like using simple "for" 5 | CoreNum = 4; 6 | poolobj = gcp('nocreate'); 7 | if isempty(poolobj) 8 | parpool(CoreNum); 9 | else 10 | disp('matlab pool already started'); 11 | end 12 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 13 | s = rng(100); % Seed the RNG for repeatability 14 | 15 | % delta is a Fano decoder parameter whose effect on decoding PAC codes is 16 | % described in [2]. If the complexity is not finite, you may use 2. 17 | delta = 2; 18 | % You may use a finite #cycles in practice or large N 19 | maxcycles = 1e15; 20 | 21 | EbNo_vec = 1:0.5:3; % we have loop for different SNR values 22 | 23 | 24 | % SNR_Cons is the construction SNR for Gaussian app, or RM-polar construction. 25 | % We use RM construction in [2,3 ...]. 26 | % An MC-based constrction is introduced in [5] based on the channel 27 | % polarization. You may use or introduce any Cons that works well for PAC codes. 28 | K = 64; N = 128; R = K/N; Rc = R; SNR_Cons = 1; 29 | 30 | % rate profile 31 | type = 4; % 1--> GA, 3--> Tse_RMpolar, 4 --> RM 32 | RP = RM_Polar_Profile(N, K, SNR_Cons, type); 33 | sum(RP) 34 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35 | 36 | % Convolutional code that we use matrix T in our references. 37 | % We designed c(x) = 3211 as explained in [4, Ch6.2 1]. You may use your poly. 38 | % You may implement conv encoding in a better way for longer poly 39 | poly = 3211; 40 | polyb = dec2bin(base2dec(num2str(poly), 8)) - '0'; % 1 011 011 41 | constraint = length(polyb); % 7 42 | C = constraint - 1; 43 | tr = poly2trellis(constraint,poly); % #of states is 2^C 44 | outputs = tr.outputs; 45 | nextStates = tr.nextStates; 46 | 47 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 48 | 49 | FER = zeros(1,length(EbNo_vec)); % Frame error rate for each SNR 50 | FE = zeros(1,length(EbNo_vec)); % #of frames in errors 51 | V = zeros(1,length(EbNo_vec)); % #of visits for every SNR 52 | Nruns = zeros(1,length(EbNo_vec)); % #of actual runs 53 | 54 | maxRun = 1e9; 55 | 56 | ClustNum = [500 500 1e3 5e3*(ones(1,length(EbNo_vec)-3))]; % adjust this based on N and K 57 | maxFE = 100; % maximum number of frame errors, you may use 300 for smoother curves 58 | 59 | fprintf('-------------------------------------\n'); 60 | for EbNo_count = 1:length(EbNo_vec) 61 | tic; 62 | EbNo_dB = EbNo_vec(EbNo_count); 63 | EbNo = 10^(EbNo_dB/10); 64 | sigma = 1/sqrt(2*Rc*EbNo); 65 | 66 | % We use bit-channel cutoff rate E0 as the bias value for the Fano decoder. 67 | % Refere to [2] for its implementation and its affect on the complexity. In 68 | % [4] we use fixed bias which is different for different R. In hardware you 69 | % may 1 bit quantize the vector E0 as E0(E0>=.5)=1 & E0(E0<.5)=0. 70 | ZW = Z_polarization_fast(N,sigma); 71 | E0 = log2(2./(1+ZW)); 72 | % IW = I_polarization(N,sigma); insted of E0 gives better FER for low 73 | % SNR values (higher complexity), see [2]. 74 | 75 | Nblkerrs = 0; 76 | Visit = 0; 77 | % updateDisp(SNR_vec,percent,FE,FER,Nruns,i); 78 | fprintf('[%02d:%02d] Starting! SNR = %.2f\n',0,0, EbNo_dB); 79 | for i = 1:maxRun/ClustNum(EbNo_count) 80 | 81 | parfor j = 1:ClustNum(EbNo_count) 82 | %Generate random message 83 | msg = randi([0 1],1,K); 84 | code = zeros(1,N); 85 | code(RP) = msg; % rate profiling step 86 | % Convolutional encoding 87 | u = convenc(code,tr); % convolutional encoder step. 88 | % Polar transformation 89 | x = polarencode(u); 90 | % BPSK modulation 91 | modulated = 2*x - 1; 92 | % AWGN 93 | r = modulated + randn(1,N)*sigma; 94 | % Decoding 95 | [~,~,decoded,VPC] = ... 96 | pac_decode2(r,delta,maxcycles,poly,RP,sigma,E0); 97 | % You may count visits only for forward move, or forward\backward node 98 | % visits or f/g-like visits [2]. 99 | Visit = Visit + VPC; 100 | 101 | Nblkerrs = Nblkerrs + any(decoded(RP)~=msg'); 102 | end 103 | if Nblkerrs >= maxFE 104 | break; 105 | end 106 | t = toc; 107 | elapsed_m = t/60; 108 | elapsed_h = floor(elapsed_m/60); 109 | elapsed_m = floor(elapsed_m - elapsed_h*60); 110 | fprintf(2,'[%02d:%02d] EbNo = %.2f, Frame = %d, FE = %d\n',elapsed_h,elapsed_m,EbNo_dB,i*ClustNum(EbNo_count),Nblkerrs); 111 | end 112 | t = toc; 113 | elapsed_m = t/60; 114 | elapsed_h = floor(elapsed_m/60); 115 | elapsed_m = floor(elapsed_m - elapsed_h*60); 116 | fprintf(2,'[%02d:%02d] SNR = %.1f, Frame = %d, FE = %d\n',elapsed_h,elapsed_m,EbNo_dB,i*ClustNum(EbNo_count),Nblkerrs); 117 | 118 | temp = (i*ClustNum(EbNo_count)); 119 | Nruns(EbNo_count) = temp; 120 | FER(EbNo_count) = Nblkerrs/temp; 121 | FE(EbNo_count) = Nblkerrs; 122 | V(EbNo_count) = Visit; 123 | fprintf('-------------------------------------\n'); 124 | end 125 | 126 | rng(s); % Restore RNG 127 | 128 | % Creating sim_state 129 | res.trials = Nruns; 130 | res.frame_errors = FE; 131 | res.FER = FE./Nruns; 132 | res.avg_visit = V./Nruns; 133 | 134 | res.SNR = EbNo_vec; 135 | res.rate_profile = type; 136 | res.K = K; 137 | res.delta = delta; 138 | 139 | res.max_cycles_allowed = maxcycles; 140 | res.max_trials = maxRun; 141 | res.max_frame_errors = maxFE; 142 | 143 | 144 | filename = sprintf('outputs/pac_K%d_N%d_SNR%0.1f_delta%0.1f_poly%d.mat',K,N,EbNo_vec(1),delta,poly); 145 | save(filename,'res'); 146 | 147 | -------------------------------------------------------------------------------- /pac_decode2.m: -------------------------------------------------------------------------------- 1 | % vectorized Go back 2 | function [metric,cycles,data,VPC] = ... 3 | pac_decode2(r,delta,maxcycles,poly,RP,sigma,E0) 4 | % For detailed explenation of PAC Fano decoder refere to [Ch2. 1] and [2]. 5 | % For low memery stack/heap decoder see [Ch3.5 1]. 6 | % For fast SCL (avoiding sorting) (idea from Fano decoder) see [3 (or Ch5 1)]. 7 | % For implementing stack with small stack size see [7]. 8 | % For improved (fast) stack decoder based on polarized channels [3 (or Ch5.2 1)]; 9 | 10 | % The Fano algorithm for decoding of Rate one convolutional code 11 | % wmc: With Metric Calculator 12 | % r = [r(0), r(1), ... r(L-1)] 13 | % bias = fano metric bias value 14 | % delta = Threshold increment size 15 | % snr = current snr in decimal (not dB) 16 | % maxcycles = Decoding timeout in cycles per bit 17 | % poly: generator polynomials in octal 18 | % RP = rate profile: a 1xL (1xK) vector forcing the decoder to chose a particular path 19 | % ------ 0:chose path 0(frozen bit), 1: chose best path 20 | 21 | % visits = zeros(1,length(RP)); 22 | VPC = 0; 23 | polyb = dec2bin(base2dec(num2str(poly), 8))-'0'; 24 | polyL = polyb == 1; % Logical array 25 | c = length(polyb) - 1; % Constraint Length 26 | 27 | 28 | N = size(r,2); % number of branches 29 | i = 1; % node index 30 | T = 0; % threshold 31 | M = zeros(N+2,1); % list of metrics 32 | M(1) = -inf; % metric backward from root 33 | M(2) = 0; % metric at root 34 | 35 | t = zeros(N,1); % branch being tested at each node 36 | inpseq = zeros(N,1); % input sequence to current node 37 | parseq = zeros(N,1); % convolutional parity sequence to current node 38 | tm = zeros(2,1); % sorted metrics for current hypotheses 39 | tb = zeros(2,1); % current hypotheses sorted by corresponding metric 40 | parity = zeros(2,1); % current parity sorted by corresponding metric 41 | 42 | reg = zeros(1,c + N); % shift register (Conv encoder replica in the decoder 43 | 44 | maxcycles = maxcycles * N; % bitwise maximum cycle 45 | dobreakA = 0; 46 | 47 | % Metric calculator parameters 48 | n = log2(N); 49 | llr = zeros(1,N); % output beliefs 50 | L = zeros(n+1,N); % node beliefs 51 | ucap = zeros(n+1,N); % decisions 52 | ns = zeros(1,2*N-1); % node state vector 53 | 54 | Tanf = @(x) abs(log(tanh(abs(x)/2))); 55 | f = @(a,b) (1-2*(a<0)).*(1-2*(b<0)).*Tanf(Tanf(abs(a))+Tanf(abs(b))); 56 | % f = @(a,b) (1-2*(a<0)).*(1-2*(b<0)).*min(abs(a),abs(b)); 57 | g = @(a,b,c) b+(1-2*c).*a; 58 | L(1,:) = -2*(1/sigma^2)*r; % belief of root 59 | node = 0; depth = 0; % start at root 60 | % done = 0; % decoder has finished 61 | 62 | cycles = 0; 63 | 64 | while cycles <= maxcycles % loop A 65 | t(i) = 1; % branch with the best metric is chosen (t(i) = 2, second best) 66 | if(dobreakA) 67 | break; 68 | end 69 | while(1) % loop B 70 | cycles = cycles + 1; 71 | if i - 1 < node % i is starting from one, -1 make it start from 0 72 | % we node to go back, we should update the states like we have not 73 | % gone more than node i-1, we sould erase future from node i-1 74 | 75 | ucap(n+1,:) = parseq; 76 | %%%%%%%%%%%%%%%%%%%%%%Erasing Future%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 77 | % when we go up, states should be zero as the case we have not 78 | % touched these nodes 79 | 80 | for I = (node+1):-1:i+1 % going back in the leaf node 81 | npos = (2^depth-1) + I; 82 | 83 | % % % %%%%%%%%%%%%%%%%%%%%%%%%%vectorize going back%%%%%%%%%%%%% 84 | % % % v = 2.^(-(0:n)); 85 | % % % Nozero = 1- logical((v*npos*2)-floor(v*npos*2) ); 86 | % % % Future = nonzeros ( floor( (v*npos).*Nozero ) )'; 87 | % % % ns(Future(1:end-1)) = 0; 88 | % % % ns(Future(end))= 1; 89 | % % % %%%%%%%%%%%%%%%%%%%%%%%%%vectorize going back rnd%%%%%%%%% 90 | 91 | ns(npos) = 0; % always we start with going up 92 | tempU = npos; 93 | while (mod(tempU,2) == 0) % condition which we should go up more 94 | tempU = tempU/2; 95 | ns(tempU) = 0; 96 | % ns(tempU-1) = 2; % the nodes we went right ( we have tendency to 97 | %go right [every node we had gone up, in its left node we go right]), 98 | % in goback we had this step, but actually we dont need it. 99 | end 100 | tempL = floor(tempU/2); %we can go up to a limit, then we start to go right. 101 | ns(tempL) = 1; 102 | end 103 | depth = n; % we are in the leaf 104 | node = (i-1); % at the end node position is updated to the place we need the llr 105 | 106 | llr(node+1) = L(n+1,node+1); % llr starts from 1 107 | %%%%%%%%%%%%%%%%%%%%%%%%%End%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 108 | else 109 | stop = i; % want to depolarize upto leaf node i-1 (nodes start from zero) 110 | ucap(n+1,:) = parseq; 111 | %%%%%%%%%%%%%%%%%%%%%%Depolarize%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 112 | % this script is used in fano_polar_wmc 113 | % stop must be defined 114 | done = 0; % decoder has finished 115 | while(done == 0) 116 | if depth == n % leaf or not 117 | llr(node+1) = L(n+1,node+1); 118 | if node == (stop-1) % stop = i; 119 | done = 1; 120 | else 121 | node = floor(node/2); depth = depth - 1; 122 | end 123 | else 124 | % nonleaf 125 | npos = (2^depth-1) + node + 1; % position of node in node state vector 126 | if ns(npos) == 0 % step L and go to the left child 127 | temp = 2^(n-depth); 128 | Ln = L(depth+1,temp*node+1:temp*(node+1)); % incomin beliefs 129 | a = Ln(1:temp/2); b = Ln(temp/2+1:end); 130 | node = node*2; depth = depth+1; % next node: left child 131 | temp = temp/2; % incoming belief length for left child 132 | L(depth+1,temp*node+1:temp*(node+1)) = f(a,b); 133 | ns(npos) = 1; 134 | else 135 | if ns(npos) == 1 % step R and go to the right chilc 136 | temp = 2^(n-depth); 137 | Ln = L(depth+1,temp*node+1:temp*(node+1)); % incomin beliefs 138 | a = Ln(1:temp/2); b = Ln(temp/2+1:end); 139 | lnode = 2*node; ldepth = depth+1; % left child 140 | ltemp = temp/2; 141 | ucapn = ucap(ldepth+1,ltemp*lnode+1:ltemp*(lnode+1)); 142 | node = node*2+1; depth = depth+1; % next node: right child 143 | temp = temp/2; % incoming belief length for right child 144 | L(depth+1,temp*node+1:temp*(node+1)) = g(a,b,ucapn); 145 | ns(npos) = 2; 146 | else % Step U and go to the parent 147 | temp = 2^(n-depth); 148 | lnode = 2*node; rnode = 2*node+1; cdepth = depth+1; % left and right child 149 | ctemp = temp/2; 150 | ucapl = ucap(cdepth+1,ctemp*lnode+1:ctemp*(lnode+1)); 151 | ucapr = ucap(cdepth+1,ctemp*rnode+1:ctemp*(rnode+1)); 152 | ucap(depth+1,temp*node+1:temp*(node+1)) = [mod(ucapl+ucapr,2) ucapr]; 153 | node = floor(node/2); depth = depth - 1; 154 | ns(npos) = 3; 155 | end 156 | end 157 | end 158 | end 159 | %%%%%%%%%%%%%%%%%%%%%%%%%End%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 160 | end 161 | ri = llr(i); 162 | state = reg(1:c);% state at current node, by moving forward/backward state will change 163 | 164 | if ~RP(i) % Frozen bit 165 | % visits(i) = visits(i) + 1; 166 | u0 = genparity_Rone_logical(0,state,polyL); % conv encovder 167 | m = calc_met_gaussian(ri,u0,E0(i)); 168 | M(i+2) = M(i+1) + m; 169 | inpseq(i) = 0; 170 | parseq(i) = u0; % we show conv output with u 171 | else % information bit 172 | % visits(i) = visits(i) + 1; 173 | u0 = genparity_Rone_logical(0,state,polyL); 174 | m0 = calc_met_gaussian(ri,u0,E0(i)); % bit metric 175 | 176 | u1 = genparity_Rone_logical(1,state,polyL); 177 | m1 = calc_met_gaussian(ri,u1,E0(i)); 178 | 179 | if m1 > m0 180 | tm(1) = m1; 181 | tb(1) = 1; 182 | parity(1) = u1; % we show conv output with u 183 | tm(2) = m0; 184 | tb(2) = 0; 185 | parity(2) = u0; 186 | else 187 | tm(1) = m0; 188 | tb(1) = 0; 189 | parity(1) = u0; 190 | tm(2) = m1; 191 | tb(2) = 1; 192 | parity(2) = u1; 193 | end 194 | 195 | % M(i+2) = forwards node metric; Mf 196 | % M(i+1) = current node metric; M 197 | M(i+2) = M(i+1) + tm(t(i)); 198 | inpseq(i) = tb(t(i)); 199 | parseq(i) = parity(t(i)); 200 | end 201 | 202 | % if M(i+1) < T + delta %if the previous node violates T+delta, currenct node has visited for the first time 203 | % if RP(i) % Frozen bit 204 | % visits_Inf = visits_Inf + 1; 205 | % end 206 | % visits = visits + 1; 207 | % end 208 | 209 | if M(i+2) >= T % Node is acceptable (Mf >= T) 210 | if M(i+1) < T + delta % First time visit; tighten threshold 211 | % visits(i) = visits(i) + 1; 212 | % visits = visits + 1; 213 | 214 | while T + delta <= M(i+2) 215 | T = T + delta; 216 | end 217 | end 218 | % Move forward 219 | %register shifted to right and the first reg is replaces by input 220 | reg = [inpseq(i) reg(1,1:end-1)]; 221 | i = i + 1; 222 | VPC = VPC + 1; 223 | if i == N + 1 % we have reached the end of sequence 224 | dobreakA = 1; 225 | end 226 | break % go to loop A 227 | else % Metric does not exceed threshold 228 | dobreak = 0; 229 | while(1) % loop C 230 | if M(i) < T 231 | T = T - delta; 232 | dobreak = 1; 233 | break 234 | else 235 | % Move back 236 | i = i - 1; 237 | reg = [reg(2:end) 0];%for the next input reg[end] will be replaced by reg[n-1], so no difference what we write in reg[end] 238 | t(i) = t(i) + 1; 239 | if ~RP(i) % non-branching node -> look back 240 | continue 241 | end 242 | if t(i) == 3 % worst node -> look back 243 | 244 | continue; % go to loop C 245 | end 246 | break % go to loop B (since dobreak = 0) 247 | end 248 | end % end of loop C 249 | if(dobreak) 250 | break; % break out of loop B and go to loop A 251 | end 252 | end 253 | 254 | end % end of loop B 255 | end 256 | data = inpseq; 257 | % metric = M(i+1); 258 | metric = M; 259 | 260 | -------------------------------------------------------------------------------- /phiF_vec.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moradi-coding/Performance-and-computational-analysis-of-polarization-adjusted-convolutional-PAC-codes/bfb379280c51a5129a2fc3b8bfe5fb1741f95c31/phiF_vec.mat -------------------------------------------------------------------------------- /phi_vector2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moradi-coding/Performance-and-computational-analysis-of-polarization-adjusted-convolutional-PAC-codes/bfb379280c51a5129a2fc3b8bfe5fb1741f95c31/phi_vector2.mat -------------------------------------------------------------------------------- /polarencode.m: -------------------------------------------------------------------------------- 1 | function x = polarencode(u) 2 | N = length(u); 3 | n = log2(N); 4 | x = u; 5 | m =1; % #of bits combined 6 | for d = n-1:-1:0 7 | for i = 1:2*m:N 8 | a = x(i:i+m-1); % first part 9 | b = x(i+m:i+2*m-1); % second part 10 | x(i:i+2*m-1) = [mod(a+b,2) b]; % Combining 11 | end 12 | m = m*2; 13 | end 14 | end --------------------------------------------------------------------------------