Tải bản đầy đủ (.pdf) (12 trang)

BÁO cáo bài tập lớn lý thuyết thông tin

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (418.68 KB, 12 trang )

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI
VIỆN ĐIỆN TỬ - VIỄN THƠNG


BÁO CÁO BÀI TẬP LỚN
Lý thuyết thơng tin
Giảng viên hướng dẫn

: Thầy Nguyễn Hữu Phát

Nhóm sinh viên thực hiện

: Phan Việt Nam – 20193036

Mã lớp

Trần Đức Tin – 20193134
: 129189

Lớp

: Điện tử 10 K64

Tháng 1/2022


I. GIỚI THIỆU CHUNG VỀ ĐỀ TÀI
Trong Lý thuyết thông tin, mã thống kê tối ưu được thực hiện tại
nguồn nhằm giải quyết vấn đề thứ nhất của hệ thống truyền tin đó là
tốc độ truyền tin. Giả sử ta muốn truyền một đoạn tin nhắn có nội
dung là “aaaabbbbcccc” bằng mã Ascii thì chúng ta cần 8 bit cho một


ký tự, như vậy cần đến 96 bit để mã hóa được đoạn tin nhắn trên. Vì
vậy chúng ta cần tìm ra một phương pháp mã hóa nhằm tăng tốc độ
truyền tin, để làm được điều đó, người ta làm giảm chiều dài trung
bình của từ mã bằng cách các từ mã có xác suất nhỏ thì có chiều dài
lớn và từ mã có xác suất lớn thì chiều dài nhỏ.
Kết hợp q trình học tập mơn Lý thuyết thơng tin, nhóm chúng
em nhận thấy hai phương pháp mã hóa theo Shannon và Huffman có
tính dụng cao, nó giúp mã hóa thơng tin, nén dữ liệu dựa trên tần suất
xuất hiện của các ký tự cần mã hóa sao cho dung lượng sau khi mã
hóa được giảm bớt nhằm tối ưu mục đích lưu trữ. Vì vậy, chúng em
quyết định lựa chọn 2 phương pháp mã hóa này làm chủ đề cho bài
tập lớn.

II. NỘI DUNG ĐỀ TÀI
1. Các định lý và thông số của mã thống kê

 Định lý 1: Trong hệ nhị phân, entropy của nguồn luôn nhỏ hơn
hoặc bằng chiều dài trung bình của từ mã:
 Định lý 2: Trong hệ nhị phân, người ta ln tìm được bộ mã
thỏa mãn tính chất tối ưu với chiều dài trung bình nằm trong
khoảng []
Để đánh giá tính hiệu quả của mã thống kê, người ta đưa ra thông số
hệ số nén thông qua tỷ lệ:

2


2. Bài toán: Cho nguồn tin X = {x1, x2, x3, x4, x5,…} với xác suất
tương ứng là P(X)={p(x1), p(x2), p(x3), p(x4), p(x5), …}. Thực hiện mã
hóa nguồn tin trên.

2.1. Mã hóa theo Shannon
a. Thuật tốn
 Bước 1: Sắp xếp các nguồn tin theo thứ tự xác suất giảm dần
 Bước 2: Thay xác suất p(xi)=Pi
Trong đó
 Bước 3: Chuyển Pi từ dạng thập phân sang nhị phân tương ứng
 Bước 4: Xác định chiều dài li: H(xi) li H(xi) + 1
 Bước 5: Lấy phần sau dấu phảy có chiều dài bằng li
b. Code
Các khối trong code bao gồm:
 Khối nhập thông tin đầu vào: 2 phương thức nhập
+ Nhập theo xác suất
+ Nhập theo tần số
void Source(float x[], int n)
{
cout<<"Moi ban chon phuong thuc nhap: "<cout<<"1. Nhap duoi dang xac suat: "<cout<<"2. Nhap duoi dang tan so: "<int c;
check_Number(c);
if(c==1)
{
cout<<"Moi ban nhap xac suat: "<for(int i=0; i{
do
{
cout<<"x["<check_Float(x[i]);
}

3


while(x[i]<=0||x[i]>=1);
}
}
if(c!=1)
{
float sum1=0;
cout<<"Moi ban nhap tan so: "<for(int i=0; i{
cout<<"x["<check_Float(x[i]);
}
for(int i=0; i{
sum1+=x[i];
}
for(int i=0; i{
x[i]=x[i]/sum1;
}
}
}

 Khối kiểm tra điều kiện: Dữ liệu nhập vào có thỏa mãn hay không
bao gồm các hàm: check_Number(), check_Float(), check()
- Hàm check_Number(): Đảm bảo số nguồn đầu vào phải là số
nguyên:

void check_Number(int &n)
{
int check = scanf("%d",&n);
//Nhap lai neu la chu hoac so < 1
while(check != 1 || n<1)
{
if(check != 1){
cout<<"Khong phai so!"<}else{
cout<<"So nhap phai >= 1"<}
fflush(stdin);
cout<<"Nhap lai: ";
check = scanf("%d",&n);
}
};

4


- Hàm check_Float(): Đảm bảo các xác suất nhập vào phải ở dạng
số thực:
void check_Float(float& n)
{
int check = scanf("%f",&n);
while(check != 1 )
{
cout<<"Nhap sai!"<fflush(stdin);
cout<<"Nhap lai: ";

check = scanf("%f",&n);
}
};

- Hàm Check(): Hàm này kiểm tra xem sau khi nhập xác suất vào
thì tổng các xác suất đầu vào có bằng 1 hay không:
bool Check(float x[], int n, float s)
{
s=0;
for(int i=0; i{
s+=x[i];
}
if(s==1) return true;
else return false;
}

 Khối sắp xếp và chuyển xác suất
Trong bài này, cụ thể ta sẽ sắp xếp theo thứ tự giảm dần:
// Hàm sắ p xế p theo giá trị xác suất giảm dần
void Sort(float x[], int n)
{
float temp;
for(int i = 0; i < n - 1; i++)
{
for(int j = i + 1; j < n; j++)
{
if(x[i] < x[j]){
5



// Hoan vi 2 so a[i] va a[j]
temp = x[i];
x[i] = x[j];
x[j] = temp;
}
}
}
}

Tiếp theo, thay xác suất p(xi)=Pi , với Pi = :
// Hàm tính xác suất cộng dồn
void Xacsuat(float x[], float p[], int n)
{
p[0]=0;
for(int i=1; i{
p[i]=p[i-1]+x[i-1];
}
}

 Khối mã hóa
void Binary(float l[], float l1[], float p[], float p1[], string str[],
int n)
{
for(int i=0; i{
p1[i]=p[i];
l1[i]=l[i];
while(l1[i]>0)

{
if(p1[i]*2>=1)
{
str[i]+="1";
p1[i]=p1[i]*2-1;
}
else
{
p1[i]=p1[i]*2;
str[i]+="0";
}
l1[i]--;
}
}
}

Trong khối này, ta sẽ sử dụng mảng chuỗi str[] để lưu trữ giá trị sau
khi mã hóa xác suất P i, l[] và l1[] là 2 mảng để truyền vào độ dài từ
mã li còn 2 mảng p[] và p1[] là xác suất sau khi cộng dồn của các
6


từ mã đó. Chúng ta mã hóa bằng cách chuyển P i từ cơ số 10 sang
dạng nhị phân theo quy tắc lấy xác suất p1[i] x 2, nếu p1[i]x2 mà
nhỏ hơn 1 thì bit đó bằng 0. Nếu p1[i]x2 ≥1 thì bit đó gán giá trị là
1 sau đó gán p1[i]= p1[i]x2-1. Tiếp tục thực hiện như trên cho đến
khi chuỗi có độ dài bằng với l1[i] thì dừng lại, chuỗi thu được
chính là từ mã cần mã hóa.
 Khối tính chiều dài trung bình
// Hàm tính chiều dài trung bình

float AverageLength(float x[], float l[], int n)
{
float sum1=0;
for(int i=0; i{
sum1+=x[i]*l[i];
}
return sum1;
}

 Khối tính entropy
// Hàm tính entropy
float Entropy(float x[], int n)
{
float sum=0;
for(int i=0; i{
sum+=-x[i]*log(x[i])/log(2);
}
return sum;
}

c. Kết quả: Như vậy với phương pháp mã hóa theo Shannon, đoạn tin
nhắn “aaaabbbbcccc” nêu ra trong phần I sẽ chỉ cần 24 bit (so với 96
bit khi mã hóa bằng Ascii) để mã hóa.
2.2. Mã hóa theo Huffman
a. Thuật tốn theo sơ đồ cây
 Bước 1: Sắp xếp các nguồn tin theo thứ tự xác suất tăng dần
hoặc giảm dần


7


 Bước 2: Chọn hai tin có xác suất nhỏ nhất, gán 1 tin cho bit 0,
tin còn lại cho bit 1
 Bước 3: Cộng xác suất của 2 tin đó lại ta thu được tin mới và
xác suất mới
 Bước 4: Nếu chỉ cịn lại 1 tin thì dừng lại, nếu không quay lại
bước 2.
 Bước 5: Đọc từ mã từ dưới lên
b. Code
Các khối trong code bao gồm:
 Khối nhập thông tin đầu vào: 2 phương thức nhập
+ Nhập dữ liệu đầu vào
int n;
cout<<"So ky tu: ";check_Number(n);
char s[100];
cout<<"Nhap Ky tu: "<for(int i=0;i{
cin>>s[i];
if(check_character(s,i)==false){
system("cls");
cout<<"Da co ky tu trung!"<cout<<"Ban da nhap: ";
for(int k=0;k{
cout<}
cout<<"\nMoi Nhap tiep: "<

i--;
}
};
cout<<"Da nhap xong ky tu!"<
+ Nhập theo xác suất
label:
float xs[100],sum=0;
cout<<"Nhap Xac Suat: "<
8


for(int i=0;i{
check_Float(xs[i]);
sum = sum + xs[i];
}
if(sum != 1){
cout<<"Ban nhap sai xac suat!"<goto label;
}
XS.insert(end(XS),begin(xs),begin(xs)+n);
cout<<"Da nhap xong xac suat!"<
+ Nhập theo tần số
cout<<"Nhap tan so: "<// sum: tong cac ky tu
float xs[100],sum;
for(int i=0;i

{
check_Number(Tanso[i]);
sum = sum + Tanso[i]*1.0;
}
for(int i=0;i{
xs[i] = float ((Tanso[i]*1.0)/(sum*1.0));
}
XS.insert(end(XS),begin(xs),begin(xs)+n);

 Khối kiểm tra điều kiện: Dữ liệu nhập vào có thỏa mãn hay
không
void check_Number(int &n)
{
int check = scanf("%d",&n);
//Nhap lai neu la chu hoac so < 1
while(check != 1 || n<1)
{
if(check != 1){
cout<<"Khong phai so!"<}else{
cout<<"So nhap phai >= 1"<}
fflush(stdin);
cout<<"Nhap lai: ";
check = scanf("%d",&n);
}
};

9



Khối này kiểm tra nhằm đảm bảo số nguồn đầu vào phải là số
nguyên dương.

void check_Float(float& n)
{
int check = scanf("%f",&n);
while(check != 1 )
{
cout<<"Nhap sai!"<fflush(stdin);
cout<<"Nhap lai: ";
check = scanf("%f",&n);
}
};

Khối này đảm bảo xác suất nhập vào phải là số thực.
bool check_character(char s[],int n)
{
for(int i=0;i{
for(int j=i+1;j{
if(s[i]==s[j])
{
fflush(stdin);
return false;
}
}

}
return true;
}

Khối này đảm bảo sao cho các nguồn nhập vào không bị trùng.
 Khối tạo cây
void Tao_Cay(vector<char>& KyTu, vector<float>& XSuat,vector<Li>&L,
size_t size)
{
Node* left;
Node* right;
//
priority_queue//
for(size_t i = 0; i < size; ++i)

10


{
minHeap.push(new Node(KyTu[i], XSuat[i]));
}
//
while(minHeap.size() != 1)
{
left = minHeap.top();
minHeap.pop();
right = minHeap.top();
minHeap.pop();
top = new Node('$', left->XacSuat + right->XacSuat);

top->left = left;
top->right = right;
minHeap.push(top);
};
print_Code(minHeap.top(), "",L);
}

Cây nhị phân được tạo ra dựa trên hàng đợi ưu tiên
priority_queue với thứ tự ưu tiên được thể hiện trong struct
compare:
struct compare
{
bool operator()(Node* l, Node* r)
{
return (l->XacSuat > r->XacSuat);
}
};

Theo quy tắc trên, ta sẽ tạo ra được một cây Huffman hoàn
chỉnh và với mỗi node được tạo ra bằng cách cộng xác suất của
2 node có xác suất nhỏ nhất, ta sẽ gán cho node đó một ký hiệu
để thuận tiện cho việc đọc ($)
 Khối mã hóa
void In_Ma(Node* root, string str,vector<Li> &L)
{
if(root == NULL)
return;
if(root->KyTu == '$')

11



{
In_Ma(root->left, str + "0",L);
In_Ma(root->right, str + "1",L);
}
if(root->KyTu != '$')
{
char s = root->KyTu;
Li new_Li(s,str);
L.push_back(new_Li);
In_Ma(root->left, str + "0",L);
In_Ma(root->right, str + "1",L);
}
};

Khối này thực chất là khối đọc thông tin từ cây Huffman đã
được tạo trước đó theo quy tắc, xét từ nút có giá trị xác suất
bằng 1 từ cây Huffman, đi về phía tay trái thì chuỗi cộng thêm
0, đi về phía tay phải thì chuỗi cộng thêm 1. Từ đó ta sẽ thu
được thơng tin sau khi mã hóa của các nguồn đầu vào.
 Khối tính chiều dài trung bình và entropy
for(int i=0;i{
H +=(float) - XacSuat[i]*log(XacSuat[i])/log(2);
Ltb +=(float) XacSuat[i]*L[i].L.length();
}

c. Kết quả: Như vậy với phương pháp mã hóa theo Huffman, đoạn tin
nhắn “aaaabbbbcccc” nêu ra trong phần I sẽ chỉ cần 20 bit (so với 96

bit khi mã hóa bằng Ascii) để mã hóa.

III. LỜI KẾT
Qua bài tập lớn Lý Thuyết Thông Tin này, chúng em đã hiểu và
nắm rõ hơn kiến thức về 2 phương pháp mã hóa Shannon và Huffman
cũng như củng cố và nhớ lại các kiến thức về ngơn ngữ lập trình C++
Lời cuối cùng, chúng xem xin chân thành cảm ơn thầy Nguyễn
Hữu Phát đã giảng dạy và giúp đỡ chúng em nhiệt tình trong quá trình
học tập. Chúng em xin kính chúc thầy ln mạnh khỏe và công tác
tốt.

12



×