Probabilistic Error Correction
오류정정코드 II — erasure · fountain · LDPC · trellis · indel
확신의 정도를 수치로 전달 → 소실된 가닥과 이동된 위치의 복원. 위치 고정 가정을 넘어서는 부호 체계.
← → 이동S 목차R 읽기 모드F 전체화면
Reed–Solomon 단독으로 다루기 어려운 세 문제
4-1강의 전제: 위치 고정 · 기호는 맞거나 틀리거나 둘 중 하나
① 다수 가닥의 소실 (dropout)
합성 실패 · PCR 편향 · 보관 중 분해 → 한 번도 읽히지 않는 oligo 발생 · 소실 개수 사전 예측 불가
→ erasure 부호 · fountain
② 불확실한 판독 (soft information)
시퀀서가 염기별 신뢰도(Q-score) 제공 · 0/1 경판정 시 해당 정보 손실
→ LLR · LDPC · turbo
③ 위치 이동 (indel)
염기 하나의 삭제 · 삽입 → 이후 모든 위치 이동 · 거리 척도 자체의 변경 필요
→ edit distance · VT · marker · HEDGES · consensus
BEC
LT · peeling
convolutional · Viterbi
homopolymer 용량
대표 코덱 비교
Code Families — fountain · graph · trellis · indel
부호화와 복호 방식에 따른 분류 · block code(4-1강) 이외의 네 계열
Fountain (rateless) code
원본 조각 일부를 무작위 선택 → XOR → droplet · 생성 개수 제한 없음 · 원본 수보다 약간 많은 droplet 수집 시 복원 · 부호율 비고정 — LT · Raptor · DNA Fountain
Graph code (LDPC)
검사식별 소수 bit만 관여(희소 행렬) · 검사식–bit 연결 그래프(Tanner graph) 위 메시지 교환 · 반복 복호 — 5G · SSD · Chandak 2019
Trellis code (convolutional · turbo)
현재 bit와 직전 bit들로 출력 결정(기억을 가진 부호기) · 시간축 상태 격자(trellis)에서 최소 비용 경로 탐색(Viterbi) · turbo = 두 부호기의 반복 복호 — LTE · 심우주 통신 · HEDGES의 토대
Indel-correcting code
삽입 · 삭제 전용 · checksum으로 삭제 위치 계산(VT) · 표식 삽입(marker) · 가설 트리 탐색(HEDGES) — DNA 채널의 핵심 과제
block code: 행렬 · 다항식에 의한 일괄 부호화와 대수적 복호 · 이번 강의의 계열: 반복(iterative) 또는 탐색(search) 기반 복호
실습 안내 — Lab 9–14
코드 상자 우측 상단 [복사] → MATLAB Online 새 스크립트에 붙여넣기 → 실행(F5)
| Lab | 내용 | 툴박스 |
|---|---|---|
| 9 | XOR 패리티에 의한 소실 가닥 복원 | 불필요 |
| 10 | LT fountain — 필요 droplet 수 측정 | 불필요 |
| 11 | LDPC bit-flipping · 장부호 연판정 복호 | 앞 뒤 |
| 12 | (7,5) convolutional 부호 · Viterbi 복호 | 앞 뒤 |
| 13 | edit distance · VT 부호의 삭제 복원 | 불필요 |
| 14 | homopolymer 제약의 용량 | 불필요 |
Lab 11 · 12의 뒤쪽 %% 섹션에 필요 · 확인: ver 목록에 "Communications Toolbox" 표시 여부 · 사용 준비 절차는 4-1강 슬라이드 참조
Lab 9 · 10 · 11 · 14 → 실행마다 결과 소폭 변동 · 슬라이드의 결과 = 1회 실행 예
MathWorks 문서 — Convolutional Codes · Block Codes (LDPC 절) · ldpcDecode
연판정 정보와 소실 채널
Reliability as a Number
- 확률적 복호: 가장 그럴듯한 codeword
- Q-score와 LLR: 독립 증거의 합
- BEC: 위치를 아는 오류 · 용량 1 − ε
확률적 복호 — ML · MAP — 정의 · 예제
가장 그럴듯한 codeword 선택
- ML: P(r | c)를 최대로 하는 codeword 선택
- MAP: P(c | r)을 최대로 하는 codeword 선택 (사전확률 반영)
- 경판정: 0/1만 사용 · 연판정: 신뢰도(확률)까지 사용
- {000, 111}, BSC p = 0.1, 수신 010
- P(010 | 000) = 0.9² × 0.1 = 0.081
- P(010 | 111) = 0.1² × 0.9 = 0.009
- → 000 선택 (= 가장 가까운 codeword)
MacWilliams & Sloane p.8–9 · Pless p.11
판독 신뢰도의 정량화 — Q-score와 LLR
염기별 신뢰도를 0/1로 자르지 않고 수치로 전달
| Q | 오류 확률 p | |LLR| = ln((1−p)/p) |
|---|---|---|
| Q10 | 0.1 | 2.20 |
| Q20 | 0.01 | 4.60 |
| Q30 | 0.001 | 6.91 |
| Q40 | 0.0001 | 9.21 |
독립 증거 → LLR의 합 · 부호 = 판정, 크기 = 확신
대화형 예시 — 같은 위치를 읽은 read 5개
이진 소실 채널(BEC) — 위치를 아는 오류의 가치
bit가 확률 ε로 "?"(소실)로 변환 · 값이 틀리지는 않음
| ε 또는 p | 0.01 | 0.05 | 0.1 | 0.2 |
|---|---|---|---|---|
| BEC (위치 앎) | 0.990 | 0.950 | 0.900 | 0.800 |
| BSC (위치 모름) | 0.919 | 0.714 | 0.531 | 0.278 |
같은 10 % → 위치를 알 때 0.9 bit, 모를 때 0.531 bit · 4-1강의 2e + s < d와 같은 원리
가닥 dropout = index로 위치를 아는 소실 · 신뢰도 낮은 자리를 "?"로 표시 → error를 erasure로 변환
소실 부호 — XOR · outer
Recovering What Is Missing
- XOR 패리티: 식 1개로 소실 1개 복원
- 연접 부호: inner(가닥 안) + outer(가닥 사이)
- error → erasure 변환의 이득
XOR 패리티 부호 — 정의 · 예제
소실 가닥 1개 복원
- 데이터 가닥 D1, …, Dk + 패리티 가닥
- 소실 1개 복원 · 소실 2개 이상 불가
- A = 01010011, B = 01001011
- C = A ⊕ B = 00011000
- B 소실 → A ⊕ C = 01001011 = B
MacWilliams & Sloane p.2 · Bornholt 2016
XOR 패리티 — 가닥 하나의 소실 복원
C = A ⊕ B 동시 저장 → 셋 중 임의의 둘로 나머지 계산 · 근거: a ⊕ a = 0
대화형 예시 — 가닥 소실 시뮬레이션
- 식 1개 = 미지수 1개 → 소실 1개 복원
- 소실 2개 → 식 1개에 미지수 2개 → 복원 불가
- RAID 5 디스크 배열과 동일한 원리
Bornholt 2016: XOR 가닥으로 중복 1.5배(Goldman 2013의 4중 겹침 대비) · ACS Nano 2026(우리 연구실): 파일 앞 절반 ⊕ 뒤 절반, pool의 약 33 %
소실 가닥의 위치 정보 필수 · 오류 가닥이 섞이면 XOR이 오류를 확산 → inner 부호의 "복호 실패" 표시 필요
연접 부호(concatenated code) — 정의 · 예제
inner(가닥 안) + outer(가닥 사이)
- inner 부호: 가닥 안의 오류 정정 · 실패 시 "?" 표시
- outer 부호: 가닥 사이 · 사라지거나 "?"인 가닥 복원
- 부호율 R = Rin × Rout
- inner Hamming (7, 4) + outer XOR (3, 2)
- R = 4/7 × 2/3 ≈ 0.38
- DNA: Grass 2015 (RS + RS) · ACS Nano 2026 (RS + XOR)
Forney 1966 · Blahut Ch. 10
연접 구조 — 가닥 안(inner)과 가닥 사이(outer)
inner 복호 실패의 표시("?") → outer 부호가 소실로 처리
- 가닥별 inner 부호(오른쪽 점선 열)로 치환 정정
- 정정 실패 → 결과 폐기 · "?" 표시 (error → erasure 변환)
- 같은 위치끼리 세로로 건 outer RS(n, k) → 소실 · "?" 가닥 합계 n − k개까지 복원
| 연구 | inner | outer |
|---|---|---|
| Grass 2015 | RS | RS |
| Organick 2018 | — | RS |
| ACS Nano 2026 (우리) | RS | XOR |
Lab 9 — XOR 패리티에 의한 소실 가닥 복원
문자 4개 가닥 2개 + 패리티 · 가닥 4개 + 패리티 1개(RAID 5 방식)
%% Lab 9 — XOR 패리티로 사라진 가닥 되살리기 (툴박스 불필요)
A = double('SONG'); B = double('KIM!');
C = bitxor(A, B); % 패리티 가닥 C = A xor B
fprintf('C = %s (hex)\n', strjoin(string(dec2hex(C,2)), ' '));
B2 = bitxor(A, C); % B 가 사라짐 → A xor C
fprintf('복원된 B = %s\n', char(B2));
%% 가닥 4개 + 패리티 1개 (RAID 5 와 같은 원리)
D = randi([0 255], 4, 8); % 가닥 4개 x 8 byte
P = bitxor(bitxor(D(1,:), D(2,:)), bitxor(D(3,:), D(4,:)));
lost = 3; % 3번 가닥이 안 읽혔다
R = P;
for i = setdiff(1:4, lost)
R = bitxor(R, D(i,:)); % 남은 것을 모두 XOR
end
fprintf('%d번 가닥 복원: %d\n', lost, isequal(R, D(lost,:)));Fountain 부호
Rateless Codes
- 무작위 XOR droplet의 무제한 생성
- peeling 복호: degree 1부터 순차 확정
- DNA Fountain: screening 결합 · 작은 K의 한계
Fountain 부호 — LT — 정의 · 예제
개수만 채우면 복원
- droplet = 원본 조각 몇 개를 무작위로 골라 XOR
- 섞을 조각 수(degree)는 확률분포에서 선택 · seed로 재현
- droplet 무제한 생성 → 원본보다 조금 많이 모으면 복원
- x1 = 10, x2 = 01, x3 = 11
- D1 = x2 = 01 · D2 = x1 ⊕ x2 = 11 · D3 = x2 ⊕ x3 = 10
- D1 → x2 · D2 ⊕ x2 → x1 = 10 · D3 ⊕ x2 → x3 = 11
Luby 2002 · Erlich & Zielinski 2017
Fountain 부호 — 부호율 비고정(rateless) 소실 부호
LT · Raptor · 개수만 채우면 복원되는 소실 부호
확률분포에서
같은 seed = 같은 선택
oligo 1개
→ peeling 복호
- 송신 측: droplet 무제한 생성 · 소실 개수 사전 설정 불필요
- 수신 측: droplet의 종류와 무관 · 개수 충족 시 복원 → dropout에 강함
- seed를 droplet에 함께 기록 → 수신 측이 섞인 조각 재계산
- Raptor = 가벼운 pre-code + LT → 필요 여분 감소
| degree d | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|
| 비율 (ideal soliton, K = 100) | 1 % | 50 % | 17 % | 8 % | 5 % |
대부분 2–3조각 혼합 · degree 1 droplet = 복호의 출발점 · 실제 사용: 이를 보강한 robust soliton
Luby 2002 (LT) · Shokrollahi 2006 (Raptor)
Peeling 복호 — degree 1 droplet부터 순차 확정
원본 4조각(각 4 bit) · droplet 5개 · 소실 조합에 따른 복원 가능 여부
대화형 예시 — droplet을 눌러 소실 · 수신 전환
- 미지 조각이 하나뿐인 droplet 탐색 → 그 조각 값 확정
- 확정된 조각을 포함한 다른 droplet에서 XOR로 제거 → degree 감소
- 반복 · degree 1 droplet이 없으면 정지
DNA Fountain (Erlich & Zielinski 2017)
fountain + screening · 제약을 부호가 아니라 선별로 충족
- droplet 생성 → DNA 서열로 변환
- GC 45–55 % · homopolymer ≤ 3 미충족 → 폐기 후 다음 seed
- 통과 droplet만 합성
droplet 내 오류의 검출 후 폐기용 · 오류 droplet이 섞이면 peeling이 오류 확산 · indel read도 폐기
조각 수 K가 작을수록 여분 증가(Lab 10: K = 20 → 57 %, K = 100 → 30 %) · droplet이 조금만 부족해도 복원 급락(cliff effect)
Erlich & Zielinski, Science 2017
Lab 10 — LT fountain의 필요 droplet 수
robust soliton으로 droplet 생성 · peeling 완료까지 수신 · K = 20, 100 각 30회
%% Lab 10 — LT(fountain) 부호: droplet 몇 개면 되나? (툴박스 불필요)
% 값 대신 "그 조각을 알아냈는가"만 추적해 필요한 droplet 수를 센다
for K = [20 100] % 원본 조각 수
c = 0.1; delta = 0.5; % robust soliton 모수
d = 2:K;
rho = [1/K, 1./(d.*(d-1))]; % ideal soliton
R = c*log(K/delta)*sqrt(K); s = floor(K/R);
tau = zeros(1, K);
tau(1:s-1) = R./((1:s-1)*K);
tau(s) = R*log(R/delta)/K;
cdf = cumsum((rho+tau) / sum(rho+tau));
need = zeros(1, 30);
for trial = 1:30
known = false(1, K); eqs = {};
while ~all(known)
deg = find(rand <= cdf, 1);
eqs{end+1} = randperm(K, deg); % droplet 하나
changed = true; % peeling 복호
while changed
changed = false;
for e = 1:numel(eqs)
u = eqs{e}(~known(eqs{e}));
if numel(u) == 1
known(u) = true; changed = true;
end
end
end
end
need(trial) = numel(eqs);
end
fprintf('K=%3d: 평균 %.1f개 필요 (여분 %.0f%%)\n', ...
K, mean(need), 100*(mean(need)/K - 1));
end툴박스 불필요
K= 20: 평균 31.4개 필요 (여분 57%) K=100: 평균 130.0개 필요 (여분 30%)
cdf— degree 분포의 누적합 ·find(rand <= cdf, 1)→ degree 1개 추출randperm(K, deg)— K 조각 중 deg개 비복원 선택eqs{end+1}— 수신 droplet 목록(cell 배열)에 추가- 확장 과제: K = 500 → 여분의 변화
조각 수가 적을수록 비율상 여분 증가 · 주소당 oligo 수십 개인 소형 풀에서 fountain에 불리
퀴즈 1 — 연판정 정보와 소실
문제를 누르면 답 표시
ε = 0.2인 BEC와 p = 0.2인 BSC의 용량을 비교하라.
BEC 0.8 · BSC 1 − H(0.2) = 0.278 → 위치 정보로 약 3배
A, B, C = A ⊕ B 중 A와 C가 소실되었다. 복원 가능한가?
불가 · B 하나 → 식 A ⊕ B = C 하나에 미지수 두 개(A, C)
같은 위치의 read 3개: 0(Q40), 1(Q20), 1(Q20). 다수결과 LLR의 판정은?
다수결 1 · LLR = +9.21 − 4.60 − 4.60 = +0.02 → 0, 확신 50.5 % → 소실("?") 처리 대상
LDPC (graph)
Sparse Checks, Iterative Decoding
- 희소 검사행렬과 Tanner graph
- bit-flipping: 경판정 반복 복호
- min-sum: LLR 메시지 전달
LDPC 부호 — 정의 · 예제
희소 검사행렬
- 검사행렬 H의 대부분이 0인 선형 부호
- 검사식 하나 = bit 몇 개만 관여
- bit와 검사식을 잇는 그래프(Tanner graph)에서 반복 복호
- 3 × 6 H · c = 001011
- x1⊕x2⊕x4 = 0 · x2⊕x3⊕x5 = 0 · x1⊕x3⊕x6 = 0
- 실제 부호: DVB-S2 64,800 bit (Lab 11)
Gallager 1962 · MacKay & Neal 1996
LDPC 부호와 Tanner graph
Low-Density Parity-Check · 검사행렬 H의 대부분이 0 (희소)
| 1 | 1 | 0 | 1 | 0 | 0 |
| 0 | 1 | 1 | 0 | 1 | 0 |
| 1 | 0 | 1 | 0 | 0 | 1 |
- 검사식 하나 → bit 몇 개만 관여 · bit 하나 → 검사식 몇 개에만 관여
- 실제 부호: 길이 수천~수만 bit, 행마다 1이 수 개 → 계산량이 길이에 비례
- 복호: 그래프 위에서 bit와 검사식이 메시지를 교환하며 반복
- 블록이 길수록 Shannon 한계에 근접
5G 데이터 채널 · 위성 방송 DVB-S2 · SSD(NAND) 컨트롤러
Chandak 2019 — 파일 전체를 LDPC 한 블록(256,000 bit)으로 부호화 · 'AGT' 동기 marker 삽입 · 같은 정확도에서 읽기 비용 30–40 % 절감
Gallager 1962 · MacKay & Neal 1996 · Chandak 2019
Bit-flipping 복호 — Gallager의 경판정 알고리즘
깨진 검사식이 가장 많이 가리키는 bit를 뒤집기 → 반복 · codeword c = 001011
대화형 예시 — bit(○)를 눌러 오류 주입 → [한 단계 복호]
- 검사식마다 합(mod 2) 계산 → 1이면 깨진 식(빨강)
- bit마다 연결된 깨진 식의 수 집계 (원 아래 숫자)
- 최댓값 bit 뒤집기 → 모든 식 만족 시 종료
동률 · 다중 오류에서 진동 가능 · 확신(LLR)을 쓰지 않는 경판정 → 연판정 복호로 개선
연판정 복호 — min-sum 메시지 전달
검사식이 각 bit에 "다른 bit들을 보면 너는 이 값이어야 한다"는 확신(LLR)을 전송
- 부호의 곱: 나머지 bit들의 짝·홀 판정 → 이 bit가 가져야 할 값
- 최솟값: 가장 약한 고리만큼만 신뢰
- bit j의 새 LLR = 채널 LLR + 연결된 모든 검사식의 메시지 합
- 부호로 판정 → 모든 검사식 만족 시 종료 · 아니면 반복
채널 LLR의 원천 = Q-score와 coverage(read 수) · NAND의 hard → soft LDPC 전환(여러 번 읽어 LLR 확보) = DNA에서 더 많이 읽는 것과 같은 구조
손계산 — 검사식 x₁ ⊕ x₂ ⊕ x₃ = 0
| bit | 채널 LLR | 채널만의 판정 |
|---|---|---|
| x₁ | +4.6 | 0 (확신) |
| x₂ | −0.5 | 1 (흐릿) |
| x₃ | +3.0 | 0 (확신) |
x₁, x₃가 0이면 짝수 조건상 x₂도 0 · 흐릿한 채널 판정이 이웃의 확신으로 교정
Lab 11 — LDPC 경판정 · 연판정 복호
앞: 위의 작은 H로 bit-flipping · 뒤: DVB-S2 LDPC(64,800 bit)와 LLR 복호
%% Lab 11 — LDPC bit-flipping (툴박스 불필요)
H = [1 1 0 1 0 0; % 검사식 3개, bit 6개
0 1 1 0 1 0;
1 0 1 0 0 1];
c = [0 0 1 0 1 1]; % codeword (H*c' = 0)
r = c; r(3) = ~r(3); % 3번 bit 오류
for it = 1:5
s = mod(H*r', 2); % 깨진 검사식 = 1
if ~any(s), break, end
cnt = s' * H; % bit 마다 깨진 검사식 수
[~, b] = max(cnt);
fprintf('반복 %d: 깨진 식 %s, bit %d 뒤집기\n', ...
it, num2str(s','%d'), b);
r(b) = ~r(b);
end
fprintf('복원 %s, 정답과 같음 %d\n', num2str(r,'%d'), isequal(r,c));
%% (Communications Toolbox) 긴 LDPC + soft 정보(LLR)
H2 = dvbsLDPCPCM('1/2'); % 32400 x 64800 희소 행렬
enc = ldpcEncoderConfig(H2);
dec = ldpcDecoderConfig(H2);
msg = randi([0 1], enc.NumInformationBits, 1);
cw = ldpcEncode(msg, enc);
sg = 0.8; % 잡음 크기
y = (1 - 2*cw) + sg*randn(size(cw)); % 0 → +1, 1 → -1
llr = 2*y / sg^2; % 양수면 0 쪽
nerr = sum((llr < 0) ~= cw); % hard 판정 오류
fprintf('복호 전 bit 오류 %d / %d\n', nerr, numel(cw));
out = ldpcDecode(llr, dec, 50);
fprintf('LDPC 후 bit 오류 %d\n', sum(out ~= msg));앞 섹션: 툴박스 불필요 뒤 섹션: 툴박스
반복 1: 깨진 식 011, bit 3 뒤집기 복원 001011, 정답과 같음 1 복호 전 bit 오류 6833 / 64800 LDPC 후 bit 오류 0
cnt = s' * H— bit별 깨진 검사식 수를 행렬곱 한 번으로llr = 2*y/sg^2— 잡음 섞인 신호 → LLR (양수 = 0 쪽)- 복호 전 약 10.5 % 오류 → 부호율 1/2 LDPC로 0
- 확장 과제:
sg를 0.9 · 1.0으로 → 실패 시작점 확인
문서 — ldpcEncode · ldpcDecode · ldpcEncoderConfig · dvbsLDPCPCM
Trellis 부호
Codes with Memory
- convolutional 부호: 합성곱 부호화
- trellis와 Viterbi: 동적 계획법
- turbo · polar · HEDGES로의 확장
Convolutional 부호 — 정의 · 예제
기억을 가진 부호기
- 출력 = 현재 bit와 직전 bit들의 XOR
- 기억 m → 상태 2m개
- u = 1 (+ 꼬리 00) → 11 10 11
- u = 1011 (+ 꼬리 00) → 11 10 00 01 01 11
Elias 1955 · Neubauer §3
Convolutional 부호 — 기억을 가진 부호기
출력 = 현재 bit + 직전 bit들 · (7,5) 부호: 기억 길이 3, 부호율 1/2
| t | ut | 상태 (ut−1 ut−2) | o₁ o₂ |
|---|---|---|---|
| 1 | 1 | 00 | 11 |
| 2 | 0 | 10 | 10 |
| 3 | 1 | 01 | 00 |
| 4 | 1 | 10 | 01 |
| 5 (꼬리) | 0 | 11 | 01 |
| 6 (꼬리) | 0 | 01 | 11 |
message 1011 → codeword 11 10 00 01 01 11 · 꼬리 00으로 상태 00 복귀(termination)
MATLAB 표기: poly2trellis(3, [7 5]) — 기억 길이 3, 생성기 8진수 7 · 5
Elias 1955
Viterbi 알고리즘 — 정의 · 예제
최소 비용 경로 = 가장 그럴듯한 codeword
- trellis = 상태 × 시간 격자 · codeword = 경로
- 가지 비용 = 받은 bit와 다른 칸 수
- 상태마다 최소 비용 경로 하나만 보존 → 끝에서 역추적
- 상태 00에 두 경로 도착: 비용 2 vs 3 → 2만 보존
- 수신 10 10 00 01 11 11 (2칸 오류) → message 1011 복원
Viterbi 1967
Trellis 표현과 Viterbi 복호
상태 4개 × 시간 = 격자 · 모든 codeword = 격자 위의 경로 하나
대화형 예시 — 받은 bit를 눌러 오류 조정
- 가지마다 출력 2 bit · 받은 2 bit와 다른 칸 수 = 가지 비용
- 상태마다 도착 경로 중 누적 비용 최소 하나만 보존 (노드 위 숫자)
- 끝 상태 00에서 역추적 → message
(7,5) 부호의 자유 거리(free distance) 5 → 서로 떨어진 2 bit 오류 정정 · 계산량은 상태 수 × 길이에 비례
Viterbi 1967
Trellis 계열의 확장 — Turbo · Polar · HEDGES
반복 복호, 채널 분극, 그리고 indel로의 확장
Turbo (Berrou 1993)
- convolutional 부호기 2개 + interleaver(순서 섞기)
- 복호기 2개가 LLR을 교환하며 반복
- Shannon 한계 근처 성능
- 3G · 4G(LTE) 데이터 채널 · 심우주 통신
Polar (Arıkan 2009)
- 채널을 "매우 좋은 것 · 매우 나쁜 것"으로 분극
- 좋은 채널에만 정보 bit 배치
- 용량 달성이 증명된 최초의 실용 구성
- 5G 제어 채널
HEDGES (Press 2020)
- 이전 bit · 위치를 hash → 다음 염기 결정 (convolutional식 부호기)
- 복호: 트리 탐색으로 치환 · 삽입 · 삭제 가설 동시 검정
- 잔여 오류 → outer RS(255,223)
- 부호율 0.6에서 1.34 % 오류 무오류 복원
| 구조 | 부호화 | 복호 | 강점 |
|---|---|---|---|
| block (4-1강) | 행렬 · 다항식 한 번 | 신드롬 · 대수 계산 | 정정 개수 보장 · burst(RS) |
| graph (LDPC) | 희소 H | 메시지 전달 반복 | 긴 블록 · 연판정 · 한계 근접 |
| trellis (conv · turbo) | shift register | Viterbi · 반복(turbo) | 연속 흐름 · 연판정 |
| fountain | 무작위 XOR droplet | peeling | 소실 다수 · 부호율 가변 |
Berrou 1993 · Arıkan 2009 · Press 2020
Lab 12 — (7,5) convolutional 부호와 Viterbi 복호
앞: shift register를 직접 구현 · 뒤: poly2trellis · convenc · vitdec로 검증과 복호
%% Lab 12 — convolutional 부호 (7,5) 와 Viterbi
u = [1 0 1 1 0 0]; % message 1011 + 꼬리 00
s = [0 0]; % 상태 = 직전 두 bit
c = [];
for t = 1:numel(u)
o1 = mod(u(t) + s(1) + s(2), 2); % 생성기 7 = 111
o2 = mod(u(t) + s(2), 2); % 생성기 5 = 101
c = [c o1 o2];
s = [u(t) s(1)]; % 기억을 한 칸 민다
end
fprintf('손 부호기: %s\n', num2str(c, '%d'));
%% (Communications Toolbox) 같은 부호와 Viterbi 복호
tr = poly2trellis(3, [7 5]); % 기억 3칸, 생성기 7, 5
c2 = convenc(u, tr);
fprintf('convenc 와 같은가: %d\n', isequal(c, c2));
r = c2; r([2 9]) = ~r([2 9]); % bit 2개 오류
d = vitdec(r, tr, 5, 'term', 'hard');
fprintf('받은 %s\n', num2str(r, '%d'));
fprintf('복호 %s\n', num2str(d(1:4), '%d'));앞 섹션: 툴박스 불필요 뒤 섹션: 툴박스
손 부호기: 111000010111 convenc 와 같은가: 1 받은 101000011111 복호 1011
s = [u(t) s(1)]— 기억을 한 칸 이동vitdec(r, tr, 5, 'term', 'hard')— 역추적 깊이 5, 끝 상태 0 가정, 경판정- 2 · 9번 bit 오류 → message 1011 복원
- 확장 과제: 오류를 인접한 두 bit에 넣으면?
문서 — poly2trellis · convenc · vitdec · Convolutional Codes 해설
삽입 · 삭제 오류
When Positions Shift
- edit distance: 삽입 · 삭제 · 치환의 최소 횟수
- VT 부호: checksum에 의한 단일 삭제 정정
- marker · HEDGES · consensus
Edit(Levenshtein) distance — 정의 · 예제
삽입 · 삭제를 포함하는 거리
- a → b 변환에 필요한 삽입 · 삭제 · 치환의 최소 횟수
- 길이가 달라도 정의
- Hamming distance: 같은 길이 · 치환만
- ACGT → AGT: 삭제 1 → 1
- ACGTACGT vs CGTACGTA → Hamming 8 · edit 2
Levenshtein 1966
삽입 · 삭제 오류와 edit distance
Hamming distance = 자리별 비교 · edit(Levenshtein) distance = 삽입 · 삭제 · 치환의 최소 횟수
대화형 예시 — 염기를 눌러 삭제
- 염기 1개 삭제 → 이후 모든 자리 이동 → Hamming distance 폭증
- 위치 고정 부호(Hamming · BCH · RS) → 정정 불가, 오정정 위험
- 관행: primer 위치로 길이가 어긋난 read 폐기 (DNA Fountain, 우리 연구실 기존 파이프라인) → coverage 손실
| 실측 (array 합성 + Illumina) | 비율 |
|---|---|
| 치환 | 0.4 % |
| 삭제 | 0.85 % |
| 삽입 | 0.05 % |
Chandak 2019
Varshamov–Tenengolts(VT) 부호 — 정의 · 예제
가중 checksum으로 삭제 1개 복원
- 위 조건을 만족하는 길이 n 이진 단어의 집합
- 삭제(또는 삽입) 1개 정정 · 여분 ≈ log2(n + 1) bit
- VT0(4) = {0000, 0110, 1001, 1111}
- 0110: 2 + 3 = 5 ≡ 0 (mod 5)
- 0110에서 1개 삭제 → 010 → 0110 복원
Varshamov & Tenengolts 1965 · Levenshtein 1966
Varshamov–Tenengolts(VT) 부호 — 단일 삭제 정정
VTa(n) = { x : Σ i·xi ≡ a (mod n+1) }
대화형 예시 — VT₀(6) codeword의 bit를 눌러 삭제
- D ≤ w → 삭제된 bit = 0 · 오른쪽에 1이 D개가 되는 자리에 0 삽입
- D > w → 삭제된 bit = 1 · 왼쪽에 0이 D − w − 1개가 되는 자리에 1 삽입
0110의 둘째 bit 삭제 → y = 010 · w = 1 · Σ = 2 · D = (0 − 2) mod 5 = 3 > 1 → 1 삽입, 왼쪽 0이 1개 → 0110
여분 ≈ log₂(n + 1) bit · 삭제 1개 정정 · 다중 indel과 DNA 4진 알파벳으로의 확장은 현재 연구 주제
Varshamov & Tenengolts 1965 · Levenshtein 1966
DNA 코덱의 indel 대응 전략
부호 안에서 해결하거나, 읽기 단계에서 indel을 치환 · 소실로 변환
동기 표식 (marker · watermark)
- 알려진 짧은 서열을 일정 간격으로 삽입
- 표식 위치로 밀림 탐지 · 재정렬
- 예: Chandak 2019 'AGT' marker
탐색형 부호 (HEDGES)
- hash 기반 convolutional식 부호
- 치환 · 삽입 · 삭제 가설을 트리로 탐색
- 잔여 오류 → outer RS
읽기 단계 정렬 (consensus)
- clustering: 같은 가닥의 read 묶기
- 다중 정렬(MSA) → 자리별 다수결
- indel → 치환 · "?"로 변환 후 inner · outer 복호
폐기
- 길이 · primer 위치가 어긋난 read 버리기
- 구현 간단 · coverage 손실
- DNA Fountain, 우리 연구실 기존 파이프라인
치환 전용 부호의 성능 = 그 앞 단계가 indel을 얼마나 제거했는가에 좌우 · 채널에서 indel 비중이 클수록(나노포어, 효소 합성) 부호 설계 단계에서의 대응 필요
Lab 13 — edit distance와 VT 복호
DP 표로 Levenshtein 거리 계산 · VT₀(6)의 모든 codeword × 모든 삭제 위치 복원 검증
%% Lab 13 — 자리가 밀리는 오류와 VT 부호 (툴박스 불필요)
a = 'ACGTACGTAC';
b = a; b(4) = []; % 4번 염기 삭제
b(end+1) = 'A'; % 길이만 맞춰 비교
fprintf('Hamming %d칸 vs edit distance %d\n', ...
sum(a ~= b), editdist(a, b));
%% VT0(6): sum(i * x_i) mod 7 == 0 인 단어들
n = 6;
X = dec2bin(0:2^n-1) - '0';
C = X(mod(X*(1:n)', n+1) == 0, :);
fprintf('VT0(%d) codeword %d개\n', n, size(C, 1));
ok = 0; tot = 0;
for i = 1:size(C, 1)
for p = 1:n % 모든 자리를 하나씩 삭제
y = C(i,:); y(p) = [];
ok = ok + isequal(vtdecode(y, n), C(i,:));
tot = tot + 1;
end
end
fprintf('단일 삭제 복원 %d / %d\n', ok, tot);
function d = editdist(a, b) % Levenshtein 거리 (DP 표)
D = zeros(numel(a)+1, numel(b)+1);
D(:,1) = 0:numel(a); D(1,:) = 0:numel(b);
for i = 2:numel(a)+1
for j = 2:numel(b)+1
D(i,j) = min([D(i-1,j)+1, D(i,j-1)+1, ...
D(i-1,j-1) + (a(i-1) ~= b(j-1))]);
end
end
d = D(end, end);
end
function x = vtdecode(y, n) % VT0(n) 단일 삭제 복호
w = sum(y); % 남은 1의 수
D = mod(-sum((1:n-1) .* y), n+1); % 모자란 checksum
if D <= w % 지워진 것은 0
r = [cumsum(y, 'reverse') 0]; % 그 자리 오른쪽 1의 수
p = find(r == D, 1); ins = 0;
else % 지워진 것은 1
l = [0 cumsum(1 - y)]; % 그 자리 왼쪽 0의 수
p = find(l == D - w - 1, 1); ins = 1;
end
x = [y(1:p-1) ins y(p:end)];
end툴박스 불필요
Hamming 7칸 vs edit distance 2 VT0(6) codeword 10개 단일 삭제 복원 60 / 60
- 스크립트 끝의
function— 스크립트 안 지역 함수 (R2016b 이상) D(i,j)— 앞 i글자 ↔ 앞 j글자의 최소 편집 횟수- edit distance 2 = 삭제 1 + 끝에 붙인 'A' 1
- 확장 과제: n = 8로 → 모든 경우 복원 확인
문서 — 스크립트의 지역 함수 · cumsum
제약 부호
Preventing Errors Before Correcting
- homopolymer · GC 제약
- 허용 서열 수의 증가율 = 용량
- constrained coding · screening · scrambling
제약 부호(constrained code) — 정의 · 예제
허용 서열만 사용
- 허용 서열(예: 같은 염기 연속 ≤ r, GC 40–60 %)만 쓰는 부호화
- 용량 = 허용 서열 수의 증가율 (bit/nt)
- 연속 금지(r = 1) → 직전과 다른 3개 중 선택 → log23 = 1.585 bit/nt
- r = 3 → 1.982 bit/nt
- 길이 2: 16개 중 12개 허용 (AA · CC · GG · TT 제외)
Goldman 2013 · Erlich & Zielinski 2017
제약 부호 — homopolymer 제약의 용량
오류를 정정하기 전에 오류를 부르는 서열을 배제 · 허용 서열의 개수 증가율 = 용량
- r = 3 → 1.982 bit/nt · 2 bit/nt 대비 손실 약 1 %
- r = 1 → log₂3 = 1.585 · Goldman 2013 회전 부호와 동일
- 무작위 서열은 대부분 불합격 → 인코더가 제약을 보장해야 함
| 전략 | 방법 | 예 |
|---|---|---|
| constrained coding | 허용 서열만 나오도록 매핑 | Goldman 회전 부호 · DNA-Aeon |
| screening | 불합격 조각 폐기 후 재생성 | DNA Fountain |
| scrambling | seed별로 섞어 합격본 선택 | 우리 연구실 SHA-256 seed (5주차) |
Lab 14 — 제약 용량과 무작위 서열의 통과율
상태 = 현재 연속 길이인 전이행렬의 최대 고윳값 → 용량 · 무작위 150 nt 1만 개로 통과율 측정
%% Lab 14 — homopolymer 제약의 용량 (툴박스 불필요)
for r = 1:5 % 같은 염기 최대 r 개 연속
T = zeros(r); % 상태 = 지금 run 길이
T(:, 1) = 3; % 다른 염기 3개 → run 1
for k = 1:r-1
T(k, k+1) = 1; % 같은 염기 → run + 1
end
lam = max(abs(eig(T))); % 가짓수가 늘어나는 비율
fprintf('run <= %d : %.3f bit/nt\n', r, log2(lam));
end
%% 무작위 150 nt 가 제약을 통과할 확률
N = 1e4; ok = 0;
for i = 1:N
s = randi(4, 1, 150); % 1 A, 2 T, 3 G, 4 C
runs = diff([0 find(diff(s) ~= 0) 150]);
gc = mean(s >= 3);
ok = ok + (max(runs) <= 3 && gc >= 0.4 && gc <= 0.6);
end
fprintf('run<=3, GC 40-60%% 통과율 %.1f%%\n', 100*ok/N);툴박스 불필요
run <= 1 : 1.585 bit/nt run <= 2 : 1.923 bit/nt run <= 3 : 1.982 bit/nt run <= 4 : 1.996 bit/nt run <= 5 : 1.999 bit/nt run<=3, GC 40-60% 통과율 17.0%
max(abs(eig(T)))— 길이가 1 늘 때 허용 서열 수가 곱해지는 비율diff([0 find(diff(s) ~= 0) 150])— 연속 구간 길이 목록- 통과율은 난수에 따라 변동 · 이론값(연속 길이 조건만) 16.5 %
DNA 코덱 구성
Putting the Layers Together
- 쓰기 · 읽기 파이프라인
- 층별 담당 오류의 분리
- 대표 DNA 코덱의 부호 구성 비교
DNA 코덱의 구성 — 쓰기와 읽기 파이프라인
4주차 부호의 배치 위치: 가닥 안(inner) · 가닥 사이(outer) · 읽기 단계
쓰기
scrambling
XOR · RS · fountain
RS · LDPC · HEDGES
읽기
indel → 치환 · ?
(error → erasure)
각 층이 담당 오류를 분리 · inner는 치환, 읽기 단계는 indel, outer는 소실 · 층 사이의 정보 전달("?" 표시, LLR)이 전체 성능 결정
대표 DNA 코덱의 부호 구성 비교
같은 틀(제약 · inner · outer · indel)에 배치한 주요 연구
| 연구 | 제약 처리 | 가닥 안 (inner) | 가닥 사이 (outer) | indel 대응 |
|---|---|---|---|---|
| Church 2012 | 1 bit/nt 축퇴 매핑 (homopolymer ≤ 3) | 없음 | 없음 | — |
| Goldman 2013 | 3진 회전 부호 | parity trit | 4중 겹침 반복 | — |
| Grass 2015 | GF(47) 코돈 | RS | RS | — |
| Bornholt 2016 | (Goldman 방식) | — | XOR | — |
| Erlich 2017 DNA Fountain | screening | RS 2 byte (검출) | LT fountain | read 폐기 |
| Organick 2018 | — | — | RS | clustering · consensus |
| Chandak 2019 | 압축 · 암호화로 무작위화 | index BCH | LDPC 한 블록 | 'AGT' marker · MSA |
| Press 2020 HEDGES | hash 부호기에 내장 | HEDGES | RS(255,223) | 트리 탐색 |
| Welzel 2023 DNA-Aeon | arithmetic 제약 부호 | 제약 부호 + CRC | Raptor | stack 복호 |
| Kang…Song 2026 (우리) | 3D DTL | RS (bit = 기호) | XOR (33 %) | primer 위치로 read 폐기 |
— = 해당 층 없음 또는 원 논문에서 미확인
요약 — 오류 유형이 부호를 결정
4주차 두 강의의 부호를 오류 유형별로 정리
| 오류 | 성격 | 부호 · 방법 | 다룬 곳 |
|---|---|---|---|
| 치환 (substitution) | 자리 고정 · 값 오류 | Hamming · BCH · RS · LDPC · convolutional | 4-1 · 4-2 PART 4–5 |
| 소실 (erasure · dropout) | 빠진 위치를 앎 | XOR · outer RS · fountain | 4-2 PART 1–3 |
| burst | 오류가 한곳에 집중 | 기호 단위 RS + interleaving | 4-1 PART 8 |
| 삽입 · 삭제 (indel) | 이후 위치 이동 | VT · marker · HEDGES · 정렬 consensus | 4-2 PART 6 |
| 합성 곤란 서열 | 오류를 유발하는 서열 | 제약 부호 · screening · scrambling | 4-2 PART 7 |
| 복원 확인 | 정정 성공 여부 불명 | CRC · hash | 4-1 PART 6 · 5주차 |
① 확신은 LLR로 전달 · 독립 증거는 합산 ② 위치를 아는 소실 = 오류의 절반 비용 ③ fountain: 개수만 채우면 복원 · 작은 K에서 여분 증가 ④ LDPC: 희소 검사식 간 메시지 전달 ⑤ trellis: 기억 있는 부호기 · Viterbi = 최소 비용 경로 ⑥ indel: 거리의 정의 자체가 달라 전용 부호 · 정렬 필요
퀴즈 2 · 과제
문제를 누르면 답 표시
VT₀(4)에서 한 칸이 삭제된 y = 101을 받았다. 원래 codeword는?
w = 2 · Σ = 1 + 3 = 4 · D = (0 − 4) mod 5 = 1 ≤ 2 → 0 삽입, 오른쪽 1이 1개 → 1001
(7,5) 부호기로 message 11(꼬리 00 포함)을 부호화하라.
11 01 01 11
같은 염기의 연속을 금지(r = 1)하면 염기 하나에 최대 몇 bit인가? 어떤 방식과 같은가?
log₂3 = 1.585 bit · Goldman 2013의 회전 부호(직전 염기를 제외한 3개 중 선택)
① Lab 10에서 K = 20 · 50 · 100 · 200 → 여분(%) 그래프 ② Lab 13을 VT₀(8)로 확장 · 전체 단일 삭제 복원 확인 ③ Lab 11의 sg를 0.8 → 1.0으로 → LDPC 실패 시작점 기록
Press 2020(HEDGES) Fig. 1 → "hash가 다음 염기를 결정"하는 과정을 3줄 요약 · Viterbi와의 공통점 · 차이점 서술
확신을 숫자로, 모르는 것은 "모른다"로
소실 · 흐릿함 · 자리 이동 → erasure · LLR · indel 부호로 대응
다음 주(5주차): hash coding — 복원의 증명과 서열 설계