BỘ CÔNG THƯƠNG
TRƯỜNG ĐẠI HỌC CÔNG NGHIỆP THỰC PHẨM TP.HỒ CHÍ MINH
KHOA CƠNG NGHỆ THƠNG TIN
-----o0o----
BÀI TẬP CUỐI KHĨA HỌC PHẦN
TRUYỀN THÔNG KỸ THUẬT SỐ
Giảng viên hướng dẫn: VŨ ĐỨC THỊNH
Sinh viên thực hiện:
1. Lý Gia Nghi – 2033190098
2. Hoàng Mạnh Cường - 2001160180
3. Nguyễn Ngọc Bảo Trân - 2033190131
Thành phố Hồ Chí Minh, tháng 12 năm 2021
LỜI CẢM ƠN
Đầu tiên, chúng em xin gửi lời cảm ơn chân thành đến Trường Đại học Công
nghiệp Thực phẩm và Khoa Công Nghệ Thông Tin đã đưa môn học“ Truyền Thơng Kỹ
Thuật Số” vào chương trình giảng dạy.
Đặc biệt chúng em xin gửi lời cảm ơn sâu sắc đến thầy Vũ Đức Thịnh đã truyền
đạt những kiến thức quý báu cho chúng em, đã trực tiếp hướng dẫn và tận tình giúp đỡ
chúng em trong suốt thời gian học môn “ Truyền Thông Kỹ Thuật Số ”.
Mặc dù đã cố gắng trong q trình tìm hiểu nhưng khơng thể tránh khỏi những sai
sót. Chúng em mong nhận được sự góp ý, nhận xét của q thầy cơ về nội dung cũng như
hình thức trình bày để bài báo cáo được hồn thiện.
Lời cuối cùng, chúng em xin kính chúc quý thầy cô và các bạn sức khỏe, luôn
thành công trong công việc và cuộc sống.
Chúng em xin chân thành cảm ơn thầy cô !
I.
LÝ THUYẾT
Xây dựng chương trình bảng thử mã cho một bộ mã của một nguồn
tin
1. Tổng quan về mã hiệu
a/ Khái niệm
Mã hiệu (code) là tập hữu hạn các ký hiệu và phép ánh xạ các tin/bản tin của
nguồn tin thành các dãy ký hiệu tương ứng. Tập các ký hiệu và phép ánh xạ này thường
sẽ đáp ứng các yêu cầu mà hệ thống truyền tin đặt ra.
Trong hệ thống truyền tin, bản tin thường phải thông qua một số phép đổi ở đầu
phát gọi là mã hóa, và ở đầu thu bản tin phải thông qua những phép biến đổi ngược lại
gọi là giải mã.
Sử dụng mã hóa nhằm tăng tốc độ truyền tin và khả năng chống nhiễu của hệ
thống. Đối với kênh có nhiễu, cần quan tâm đến đọ chính xác của sự truyền tin hay các
tin truyền đi ít bị sai nhầm.
Ví dụ 1: X = {0,1}
0: là một mã hiệu
1: Là một mã hiệu
Ta có 2 mã hiệu 0, 1
b/ Các thơng số cơ bản
Chiều dài trung bình của bộ mã
: chiều dài trung bình
n: Số từ mã tương ứng số tin nguồn
: Chiều dài từ mã tương ứng với tin của nguồn
: xác suất xuất hiện của tin
Độ dài trung bình ngắn nhất
Mã có độ dài ngắn nhất khi giải mã được và có độ dài trung bình khơng dài hơn độ
dài trung bình của các mã giải mã được khác cho cùng 1 nguồn
Ví dụ1:
S1
S2
0.5
0.1
Code A
10
01
Code B
0
110
Mã A có độ dài trung bình = 2 kí hiệu mã/tin
Mã B có độ dài trung bình =0.5*1 + 0.1*3 =0.8 kí hiệu mã /tin.
Vậy mã B có độ dài trung bình dài hơn mã A
Tập các ký hiệu mã dùng để biểu diễn gọi là bảng ký hiệu mã, còn số các ký hiệu
thì được gọi là cơ số mã (m)
Độ đo của từ mã: Để thuận tiện cho việc sử dụng mã hiệu, mỗi từ mã được gán
cho một độ đo: trọng số
c/ Phân loại mã
Dựa vào độ dài của mã: Mã có độ dài khơng đổi gọi là mã đều. Mã có độ dài thay đổi
gọi là mã không đều.
+ Mã đều: {00, 01,10, 11}
+ Mã không đều: {0, 10, 011, 11001}
Một bộ mã đều có cơ số mã m, chiều dài từ mã l và số lượng từ mã n bằng với ml
thì được gọi là mã đầy, ngược lại thì gọi là mã vơi.
+ Mã đầy: {0, 1, 01, 00, 10, 11}
+ Mã vơi: {0, 10, 11}
Dựa vào trọng lượng của từ mã: Mã có trọng lượng khơng đổi và mã có trọng
lượng thay đổi.
Dựa vào khoảng cách của 2 từ mã kế nhau: Mã có khoảng cách khơng đổi và
mã có khoảng cách thay đổi.
Dựa vào cơ số mã: Mã nhị phân (cơ số 2), mã bát phân (cơ số 8), mã hexa (cơ
số 16). Trong đó mã nhị phân được dùng phổ biến.
Dựa vào độ tin cậy: Mã có thể phát hiện sửa lỗi và mã khơng thể phát hiện sửa
lỗi.
Ví dụ 2: Cho bảng ký hiệu mã A = {0, 1}
+ X1 = {00, 10, 11} mã đều, vơi
+ X2 = {00, 01, 10, 11} mã đều, đầy
d/ Ưu điểm của mã hiệu
+ Tính phân tách được quyết định việc giải mã
+ Tối ưu về độ dài
+ Tối ưu về khả năng sửa sai
+ Tối ưu về thời gian giải mã
e/ Phương pháp biểu diễn mã
Phương pháp liệt kê (bảng mã ASCII)
Sử dụng bảng mã để kê khai tất cả các lớp tin và từ mã tương ứng với mỗi lớp tin
Đơn giản, tiện dụng song rất cồng kềnh khi số các lớp tin trong nguồn là lớn
Cách liệt kê không thấy được tính chất quan trọng
Ví dụ:
Tin
Từ mã
a
00
b
01
C
110
D
111
Cây mã
Cây mã gồm các nút và nhánh cây, gốc cây gọi là nút gốc
Mỗi từ mã được biểu diễn bằng một nút, tương ứng với đường dẫn từ gốc đến nút
đó.
Nút phân đi hai nhánh tương ứng với 0 (bên trái) và 1 (bên phải)
Mỗi nút cuối tương đương với một từ mã.
Dựa vào cây mã, ta xác định được mã đầy, mã vơi, mã không đều, mã đều
Ví dụ: 00, 010, 10, 110, 111
0
0
1
1
10
00
1
0
0
1
Mặt tọa độ mã
010
110
111
Từ mã được biểu diễn bằng một điểm trong hệ tọa độ 2 chiều (l, b)
Thiết lập một bề mặt có hai tọa dộ trên đó mỗi từ mã được biểu diễn bằng một
điểm duy nhất
b=
m: cơ số mã
c: trị ký hiệu thứ k trong từ mã
l: chiều dài
b: trọng số
Không thể tồn tại hai hay nhiều từ mã lại giống nhau (n, b)
Ví dụ:
Tin
a1
Từ mã
00
Chiều dài 2
a2
010
3
a3
011
3
a4
10
2
l
Trọng
0
5
1
số 2
b
b
5
4
3
2
1
0
Các
1
2
3
4
- Căn cứ tính prefix của mã:
l
+ Nhanh
+ Chống nhiễu kém
- Căn cứ dấu phân tách:
+ Chống nhiễu tốt
+ Hiệu suất thấp
- Căn cứ chiều dài từ mã:
+ Đơn giản
+ Chống nhiễu kém
2. Tách mã
Phương pháp giải mã được sử dụng như sau: chỉ giải mã khi nào đã nhận được
đoạn mã với độ dài bằng độ dài của từ mã dài nhất.
Ví dụ 1: Xét biến ngẫu nhiên X = {x1, x2} có bảng mã tương ứng A= {a1 = 0, a2 = 01}.
Giả sử dãy mã nhận được (cần giải mã) là: 0010000101001.
Bảng thử mã:
1
0
01
2
1
Mã này phân tách được
Có thể chi tiết hóa các bước giải mã dãy từ mã trên như sau:
Nhận được đoạn 00 -> Giải ra x1, còn lại 0.
Nhận tiếp 1 ->01 -> Giải ra x2.
Nhận tiếp 00 -> Giải ra x1, còn lại 0.
Nhận tiếp 0 -> 00 -> Giải ra x1, còn lại 0.
Nhận tiếp 0 -> 00 -> Giải ra x1, còn lại 0.
Nhận tiếp 1 -> 01 -> Giải ra x2.
Nhận tiếp 01 -> Giải ra x2.
Nhận tiếp 00 -> Giải ra x1, còn lại 0.
Nhận tiếp 1 -> 01 -> Giải ra x2.
Kết quả dãy thơng báo là: x1x2x1x1x1x2x2x1x2.
Ví dụ 2: X1 = {0, 10, 11} mã hóa nguồn A = {a, b, c}, x = abaac, y = 0100011
Tách mã: 0 | 10 | 0 | 0 | 11 abaac
Ví dụ 3:
Bộ mã A (00, 01, 100, 1010, 1011)
Nhận dãy kí hiệu 1000101001011101101
Phân tách thành: 100 | 01 | 01 | 00 | 1011 | 1011 | 01
3. Xây dựng bảng thử mã
+ Sắp xếp các từ mã đề cho thành 1 cột (đánh dấu cột đó là cột 1)
+ So sánh các từ mã ngắn với từ mã dài ở cột 1
+ Nếu từ mã ngắn giống phần đầu của từ mã dài thì lấy phần phía sau trừ phần giống đầu
đưa vào cột tiếp theo (cột 2).
+ Tiếp tục so sánh các mã mới ở cột 2 với các từ mã ở cột 1, lấy phần còn lại trừ phần
giống nhau ở đầu ghi vào cột tiếp theo (cột 3) …
+ Tương tự với các cột còn lại đối chiếu đến cột thứ n sẽ là kết quả đối chiếu của các tổ
hợp trong cột n - 1 với cột 1.
+ Làm cho đến khi cột phải điền khơng cịn thể thêm, hoặc cột thêm trùng với một cột
trước đó hoặc có một chuỗi trong cột trùng với một từ mã.
Ví dụ: B = {010, 0101, 10100}
1
2
3
4
5
6
010
1
0100
0
10
100
101
00
0101
10100
Khơng thể thêm cột mới => B là mã phân tách được
Để nhận biết một bộ mã có phân tích được hay khơng, người thường dùng một công
cụ được gọi là bảng thử mã
4. Mã phân tách được
Bộ mã sẽ chắc chắn phân tách được nếu từ mã ngắn hơn không là phần đầu, phần
cuối hoặc là phần giữa của từ mã khác dài hơn, hoặc việc ghép hai hay nhiều từ mã lại
thành chuỗi ký hiệu mã không tạo thành một đoạn ký hiệu mã trùng với một từ mã khác
chúng.
Ví dụ: X = 01010100101, A = {010,0101,10100}
0101 | 010 | 0101
Mã tách được
Ví dụ: A = {00, 01, 100, 1010, 1011,1001,11111}
1
00
01
100
1010
1011
2
1001
11111
Các từ mã ngắn {00, 01} không là phần đầu hoặc cuối của các từ mã dài
A là bộ mã phân tách được
=> Định lý: Điều kiện cần và đủ để mã có tính phân tách là khơng có một tổ hợp mã
nào trong các cột từ j >= 2 trùng với một từ mã trong cột 1.
5. Mã không phân tách được
Bảng mã không tách được là bảng mã mà khi mã hóa thơng báo Msg ta sẽ nhận
được một dãy các từ mã ws, và khi giải mã dãy các từ mã ws thì ta có thể nhận được
nhiều thơng báo Msg khác nhau.
Ví dụ 1: X = {0,10,01}, A = {a, b, c}, y = 01010
0 | 10 | 10 abb = 1/3
01 | 0 | 10 cab = 1/3
01 | 01 | 0 cca = 1/3
Bên nhận sẽ khơng biết chính xác bên phát phát mẫu tin nào
Mã không tách được
Ví dụ 2: B = {00, 01, 011, 100, 00010} trên chuỗi 000101100
1
00
01
011
1100
00010
2
010
1
3
0
100
4
0
1
11
0010
5
0
1
11
0010
100
00
=>Cột 5 có tổ hợp mã 00 trùng từ mã 00 ở cột 1
=>B là mã không phân tách được
=>Mã có hai cách phân tách khác nhau (00 | 01 | 011 | 00) và (00010 | 1100)
Ví dụ: A = {010, 0001, 0110, 1100, 00011, 00110, 11110, 101011}
1
010
0001
0110
1100
00011
00110
11110
101011
2
1
3
100
1110
01011
4
11
5
00
110
6
01
0
011
110
7
0
10
001
110
0011
0110
6. Không phân tách được thì sẽ có hai dãy tin trùng
Ví dụ 1:
Xét biến ngẫu nhiên X = {x1, x2, x3, x4}, W = {w1 = 0, w2 = 1, w3 = 01, w4 = 10}. Giả
sử thơng báo nguồn có nội dung: x1x2x3x4x3x2x1. Khi đó dãy mã tương ứng viết từ W
có dạng: 0101100110.
Nếu giải mã tuần tự từ trái qua phải ta nhận kết quả: x1x2x1x2x2x1x1x2x2x1. Nhưng
nếu bằng phương pháp khác ta có thể nhận được kết quả: x3x3x4x3x4 và nhiều thơng báo
khác nữa.
Ví dụ 2: E = {00, 01, 110, 111, 0111}
1
00
01
110
111
0111
2
11
3
0
1
4
0
1
10
111
Cột 4 mã 111 trùng với cột 1 mã 111
E là bộ mã khơng tách được
Ví dụ 3: B = {x1 = 00, x2 = 01, x3 = 011, x4 = 110, x5 = 00010} trên chuỗi 000101100.
Không phân tách được.
1
00
01
011
1100
00010
2
010
1
3
0
100
Vì có hai cách phân tách:
Nhận đoạn 000- > giải ra x1
Nhận tiếp 1 -> 01 -> giải ra x2
Nhận tiếp 01-> giải ra x2
Nhận tiếp 10
Nhận tiếp 10
Không giải được.
Nhận đoạn 000 -> x1
Nhận tiếp 1 -> 01 -> x2
Nhận tiếp 011 -> x3
Nhân tiếp 00 -> x1
Sau phân tách: 00 | 01 | 011 | 00
Nhận đoạn 00010 -> x5
4
0
1
11
0010
5
0
1
11
0010
100
00
Nhận đoạn 1100 -> x4.
Sau phân tách: 00010 | 1100
Vậy ở đây có 2 đoạn mã trùng.
7. Độ Chậm Giải Mã Của Nguồn Tin
a/ Định Nghĩa:
Khi nhận một dãy kí hiệu mã, để có thể phân tách được một cách duy nhất và chính
xác bộ mã cần thỏa mãn điều kiện cần và đủ là bất kì dãy các từ mã nào của bộ mã cũng
không được trùng với dãy từ mã khác của cùng một bộ mã. Do vậy, trong trường hợp có
sự trùng nhau nhau cột k, l với k khác l và k, l ≥ 2 giống nhau thì mã này phân tách được
nhưng quá trình tách mã sẽ khó khăn vì bên nhận phải có đủ hết số kí hiệu mới có thể
tách mã
Hiểu đơn giản độ chậm giải mã là quá trình giải mã chậm trễ
Quá trình giải mã chậm trễ
Người ta gọi quá trình này là Độ Chậm Giải Mã.
Độ chậm giải mã là số ký hiệu phải nhận được đủ để có thể phân tách (nhận dạng)
được từ mã.
Độ chậm giải mã là vô hạn khi nhận hết được bản tin mới có thể tiến hành phân tách
hoặc trong q trình phân tách có hai cột k, l với k khác l và k, l ≥ 2 giống nhau thì mã
này phân tách được nhưng có độ chậm giải mã cũng là vơ hạn.
b/ Cách tính độ chậm giải mã
Bảng thử mã phân tách cho phép đánh giá độ chậm giải mã:
Công thức:
[]nmin ≤ Tch ≤ [ ]nmax
j: Số thử cột rỗng.
nmin & nmax: Độ dài từ mã ngắn nhất và dài nhất.
Ví dụ 1: Xét Bộ Mã A = {00, 01, 100, 1010, 1011} có bảng thử mã như sau:
1
2
00
01
100
1010
1011
Trong trường hợp này, các cột từ cột 2 rỗng, nghĩa là bộ mã phân tách được. Khơng có
từ mã nào trùng với phần đầu từ mã khác nên khi nhận hết ký hiệu của một từ mã thì
khơng có từ mã nào khác nhận các ký hiệu này làm phần đầu nữa nên đây chính là thời
điểm cắt mã. Độ chậm giải mã sẽ bằng chiều dài từ mã.
Ví Dụ 2: Xét Bộ Mã A = {01, 10, 011, 100} có bảng thử mã như sau:
1
01
10
011
100
2
1
0
3
0
00
1
11
4
1
11
0
00
Độ chậm giải mã là vơ hạn vì có chuỗi trùng nhau ở cột 3 & 4. Độ trễ quá trình lớn
II. CHƯƠNG TRÌNH
1. Source code
using System;
using System.Collections.Generic;
using System.Linq;
namespace TTKTS
{
public struct DecodeTable
{
public List<ColTable> cols;
}
public struct ColTable
{
public int Index;
public List<string> Code;
}
public class Program
{
public static ColTable MakeColsFromBase(ColTable col, ColTable lastcol)
{
if(col.Code == null || col.Code.Count() <= 0)
{
throw new Exception("Null Collumn");
}
if (lastcol.Code == null || lastcol.Code.Count() <= 0)
{
throw new Exception("Null Collumn");
}
var created = new ColTable()
{
Index = lastcol.Index + 1,
Code = new List<string>(),
};
foreach(var s in lastcol.Code.OrderBy(x => x.Length))
{
foreach(var compstr in col.Code.OrderBy(x=>x.Length).Where(x => !
x.Equals(s)))
{
if(compstr.Length >= s.Length)
{
var check = compstr.Substring(0, s.Length);
if (check.Equals(s))
{
var subed = compstr.Substring(s.Length);
if (subed != null)
{
created.Code.Add(subed);
}
}
}
if (lastcol.Index != col.Index && compstr.Length < s.Length)
{
var check = s.Substring(0, compstr.Length);
if (check.Equals(compstr))
{
var subed = s.Substring(compstr.Length);
if (subed != null)
{
created.Code.Add(subed);
}
}
}
}
}
//foreach(var str in created.Code)
//{
//
Console.WriteLine($"{created.Index} : {str}");
//}
return created;
}
public static bool CheckDivideAble(DecodeTable basetable)
{
if (basetable.cols == null || basetable.cols.Count() <= 0)
{
throw new Exception("Null Table");
}
var basecol = basetable.cols.Where(x=>x.Index==1).FirstOrDefault();
foreach(var c in basetable.cols.Where(x => x.Index != 1))
{
bool hasMatch = c.Code.Intersect(basecol.Code).Any();
if (hasMatch)
{
return !hasMatch;
}
}
return true;
}
public static bool CheckSpeed(DecodeTable basetable)
{
if (basetable.cols == null || basetable.cols.Count() <= 0)
{
throw new Exception("Null Table");
}
foreach (var col in basetable.cols.Where(x => x.Index != 1))
{
foreach (var compcol in basetable.cols.Where(x => x.Index != 1 &&
x.Index != col.Index))
{
var col1 = col.Code.OrderByDescending(x => x);
var col2 = compcol.Code.OrderByDescending(x => x);
if (col1.SequenceEqual(col2))
{
return false;
}
}
}
return true;
}
public static DecodeTable CreateFromBase(DecodeTable basetable)
{
if(basetable.cols == null || basetable.cols.Count() < 1)
{
throw new Exception("Null Table");
}
if(basetable.cols.Count() >= 2)
{
if (!CheckDivideAble(basetable))
{
Console.WriteLine("Code can not be divided");
return basetable;
}
}
if(basetable.cols.Count() >= 3)
{
if (!CheckSpeed(basetable))
{
Console.WriteLine("Code can be divided but the time it takes is
infinite");
return basetable;
}
}
var col = MakeColsFromBase(basetable.cols.OrderBy(x =>
x.Index).FirstOrDefault(), basetable.cols.OrderByDescending(x =>
x.Index).FirstOrDefault());
if (col.Code.Count() != 0)
{
basetable.cols.Add(col);
CreateFromBase(basetable);
}
if(col.Code.Count() == 0)
{
Console.WriteLine("Code can be divided");
}
return basetable;
}
public static void ShowTable(DecodeTable basetable)
{
foreach(var col in basetable.cols)
{
Console.Write($"{col.Index}\t");
}
Console.Write($"\n");
var rownum =
basetable.cols.OrderByDescending(x=>x.Code.Count).FirstOrDefault().Code.Count;
for (int i = 0;i < rownum; i++)
{
foreach(var col in basetable.cols.OrderBy(x => x.Index))
{
if (col.Code.Count > i)
{
Console.Write($"{col.Code[i]}\t");
}
else
{
Console.Write($" \t");
}
}
Console.Write($"\n");
}
}
static void Main(string[] args)
{
Console.WriteLine("Input code set : ");
Console.WriteLine("Example : 00,010,...,10011");
var input = Console.ReadLine();
try
{
input = input.Replace(" ", "");
var baseArr = input.Split(',').ToList();
var table = new DecodeTable();
table.cols = new List<ColTable>();
table.cols.Add(new ColTable()
{
Index = 1,
Code = baseArr
});
var finaleTable = CreateFromBase(table);
ShowTable(finaleTable);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
Kết quả
2. Demo