信息论与编码实验指导书
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
信息论与编码实验指导书
1 课程实验目的
本课程是一门实践性很强的专业课和核心课程,根据课程理论教学的需要安排了6学时的配套实验教学,主要内容涉及信息度量的计算方法、典型信源编码方法、典型信道容量计算方法和数据压缩方法四个实验,这四个实验的开设一方面有助于学生消化、巩固课程理论教学的知识,另一方面又可培养学生实践动手能力,同时为后续课程做好准备。
2 课程实验要求
2.1 课程实验准备要求
(1)课程实验主要为设计性实验,要求学生熟悉掌握在VC环境下编写和调试C++程序的方法。
(2)要求学生在实验前复习实验所用到的预备知识。
可以查阅教材或者相关的参考资料,这需要学生有自主的学习意识和整理知识的能力。
(3)根据实验项目,设计相关的数据结构和算法,再转换为对应的书面程序,并进行静态检查,尽量减少语法错误和逻辑错误。
上机前的充分准备能高效利用机时,在有限的时间内完成更多的实验内容。
2.2 课程实验过程要求
(1)生成源代码。
将课前编写好的书面代码,利用VC自带的编辑器尽快输入为转换为源代码;
(2)程序调试和软件测试。
要求学生熟练掌握调试工具,调试正确后,认真整理源程序和注释,给出带有完整注释且格式良好的源程序清单和结果。
(3)完成实验报告。
根据实验内容和完成情况,按照附件1给定的格式完成课程实验报告的编写。
2.3 课程实验报告要求
在每次课程实验后要及时进行总结和整理,并编写课程实验报告。
报告格式按江西蓝天学院实验报告纸格式填写。
实验一二维随机变量信息熵的计算
[实验目的]
掌握二变量多种信息量的计算方法。
[实验学时]
2学时
[实验准备]
1.熟悉二变量多种信息量的计算方法,设计实验的数据结构和算法;
2.编写计算二维随机变量信息量的书面程序代码。
[实验内容及步骤]
离散二维随机变换熵的计算
说明:
(1)利用random函数和归一化方法构造一个二维离散随机变量(X,Y);
(2)分别计算X与Y的熵、联合熵、条件熵:H(X)、H(Y)、H(X,Y)H(X|Y)、I(X|Y);
(3)对测试通过的程序进行规范和优化;
(4)编写本次实验的实验报告。
附实验一主要内容及源程序
实验一离散二维随机变量信息熵的计算
1 实验内容
(1)利用random函数和归一化方法构造一个二维离散随机变量(X,Y);
(2)分别计算X与Y的熵、联合熵、条件熵:H(X)、H(Y)、H(X,Y)H(X|Y)、I(X|Y);
2 数据结构与算法描述
(1)函数的定义:函数的数据成员
1.随机生成函数的代码:
int k,n,t=0;
double a[4][4],b=0,c=0;
for(k=0;k<4;k++)
{
for(n=0;n<4;n++)
{
a[k][n]=rand()%100;
t+=a[k][n];
}
}
cout<<"从到间随机取得行列的random函数:"<<endl;
for(k=0;k<4;k++)
{
for(n=0;n<4;n++)
{
cout<<setw(5)<<a[k][n];
}
cout<<endl;
}
2.函数归一化代码:
cout<<"函数归一化:"<<endl;
for(k=0;k<4;k++)
{
for(n=0;n<4;n++)
{
cout<<setw(12)<<a[k][n]/t;
}
cout<<endl;
}
3. H(Y)、 H(X)计算代码:
cout<<"H(Y)计算:"<<setw(20)<<"H(X)计算:"<<endl;
int e=1;
for(k=0;k<4;k++)
{
double i=0,g=0;
for(n=0;n<4;n++)
{
i+=(a[k][n]/t);
g+=(a[n][k]/t);
}
cout<<"P(Y"<<k+1<<"):"<<i<<setw(8)<<"P(X"<<e<<"):"<<g<<endl;
++e;
b-=(i*log(i)/log(2.0));
c-=(g*log(g)/log(2.0));
}
cout<<"H(Y)=-∑p(Y)log p(Y)="<<b<<endl;
cout<<"H(X)=-∑p(X)log p(X)="<<c<<endl;
4.联合熵H(X,Y)计算代码:
cout<<"联合熵H(X,Y)计算:"<<endl;
b=0;
int r,u,h=0;
for(k=0;k<4;k++)
{
for(n=0;n<4;n++)
{
if(a[k][n]!=0)
{
b-=((a[k][n]/t)*log(a[k][n]/t)/log(2.0));
}
else
{
r=k,u=n;
h=1;
break;
}
}
}
if(h==0)
cout<<"H(X,Y)=-∑∑p(X,Y)log p(X,Y)="<<b<<endl;
else cout<<"P("<<r+1<<","<<u+1<<")为零,中断,无值"<<endl;
5.条件熵H(X|Y)计算代码:
cout<<"条件熵H(X|Y)计算:"<<endl;
b=0,h=0;
for(k=0;k<4;k++)
{
double i=0;
for(n=0;n<4;n++)
{
i+=(a[k][n]/t);
}
for(n=0;n<4;n++)
{
if(a[k][n]!=0)
{
b-=((a[k][n]/t)*log((a[k][n]/t)/i)/log(2.0));
}
else {h=1;break;}
}
}
if (h==0){cout<<"H(X|Y)=-∑∑P(X,Y)log(P(X,Y)/P(Y))="<<b<<endl;} else cout<<"P("<<r+1<<","<<u+1<<")为零,中断,无值"<<endl;
cout<<"I(X|Y)计算:"<<endl;
if(h==0)cout<<"I(X|Y)=H(X)-H(X|Y)="<<c-b<<endl;
else cout<<"P("<<r+1<<","<<u+1<<")为零,中断,无值"<<endl;
(2)主函数main()实现初始化操作,完成对子函数的调用
因为整个程序是写在main函数中,就不列出,会在下面源程序清单中给出程序。
3 实验数据与实验结果
这里设定函数为4行4列的随机矩阵。
然后函数归一化,即:把所有数字相加,再用每个数去除,就得到了归一化后的矩阵。
而H(X)、H(Y)、H(X,Y)H(X|Y)、I(X|Y)就根据课本上的公式,然后编程。
输出结果如下:
4 程序代码清单:
#include<stdio.h>
#include<cmath>
#include<iomanip>
#include<time.h>
#include<iostream>
using namespace std;
void main()
{
int k,n,t=0;
double a[4][4],b=0,c=0;
srand((unsigned)time(NULL));
for(k=0;k<4;k++)
{
for(n=0;n<4;n++)
{
a[k][n]=rand()%100;
t+=a[k][n];
}
}
cout<<"从0到100间随机取得行列的random函数:"<<endl;
for(k=0;k<4;k++)
{
for(n=0;n<4;n++)
{
cout<<setw(5)<<a[k][n];
}
cout<<endl;
}
cout<<"函数归一化:"<<endl;
for(k=0;k<4;k++)
{
for(n=0;n<4;n++)
{
cout<<setw(12)<<a[k][n]/t;
}
cout<<endl;
}
cout<<"H(Y)计算:"<<setw(20)<<"H(X)计算:"<<endl;
int e=1;
for(k=0;k<4;k++)
{
double i=0,g=0;
for(n=0;n<4;n++)
{
i+=(a[k][n]/t);
g+=(a[n][k]/t);
}
cout<<"P(Y"<<k+1<<"):"<<i<<setw(8)<<"P(X"<<e<<"):"<<g<<endl;
++e;
b-=(i*log(i)/log(2.0));
c-=(g*log(g)/log(2.0));
}
cout<<"H(Y)=-∑p(Y)log p(Y)="<<b<<endl;
cout<<"H(X)=-∑p(X)log p(X)="<<c<<endl;
cout<<"联合熵H(X,Y)计算:"<<endl;
b=0;
int r,u,h=0;
for(k=0;k<4;k++)
{
for(n=0;n<4;n++)
{
if(a[k][n]!=0)
{
b-=((a[k][n]/t)*log(a[k][n]/t)/log(2.0));
}
else
{
r=k,u=n;
h=1;
break;
}
}
}
if(h==0)
cout<<"H(X,Y)=-∑∑p(X,Y)log p(X,Y)="<<b<<endl;
else cout<<"P("<<r+1<<","<<u+1<<")为零,中断,无值"<<endl;
cout<<"条件熵H(X|Y)计算:"<<endl;
b=0,h=0;
for(k=0;k<4;k++)
{
double i=0;
for(n=0;n<4;n++)
{
i+=(a[k][n]/t);
}
for(n=0;n<4;n++)
{
if(a[k][n]!=0)
{
b-=((a[k][n]/t)*log((a[k][n]/t)/i)/log(2.0));
}
else {h=1;break;}
}
}
if (h==0){cout<<"H(X|Y)=-∑∑P(X,Y)log(P(X,Y)/P(Y))="<<b<<endl;} else cout<<"P("<<r+1<<","<<u+1<<")为零,中断,无值"<<endl;
cout<<"I(X|Y)计算:"<<endl;
if(h==0)cout<<"I(X|Y)=H(X)-H(X|Y)="<<c-b<<endl;
else cout<<"P("<<r+1<<","<<u+1<<")为零,中断,无值"<<endl;
}
实验二简单信源编码方法实现
[实验目的]
掌握Huffman编码方法。
[实验学时]
2学时
[实验准备]
1.熟悉离散信源的编码方法,重点是Huffman编码方法,设计Huffman编码的数据结构和算法;
2.编写Huffman编码的书面程序代码。
[实验内容及步骤]
离散信源的Huffman编、译码方法
说明:
(1)利用random函数构造一个一维离散随机变量分布P(X);
(2)构造离散随机变量的概率压缩表;
(3)根据概率压缩表构造Huffman编码表,并实现Huffman编码;
(4)完成Huffman译码;
(4)编写本次实验的实验报告。
附实验二实验内容及程序源程序
实验二离散信源的Huffman编、译码方法
1 实验内容
(1)利用random函数构造一个一维离散随机变量分布P(X);
(2)根据概率压缩表构造Huffman编码表,并实现Huffman编码;
(3)完成Huffman译码;
2 数据结构与算法描述
(1)函数的定义:函数的数据成员
1.随机生成归一化一维离散变量函数代码:
void aa(int n)
{
double w=0;
a=new double[n];
srand((unsigned)time(NULL));
cout<<"随机生成归一化一维离散变量:"<<endl;
for(int i=0;i<n;i++)
{
a[i]=rand()%50;
w+=a[i];
}
for(int i=0;i<n;i++)
{
a[i]=a[i]/w;
}
double p;
for(int i=0;i<n-1;i++)
{
for(int j=n-2;j>=i;j--)
{
if(a[j]<a[j+1])
{
p=a[j+1];
a[j+1]=a[j];
a[j]=p;
}
}
}
cout<<"P(X):";
for(int i=0;i<n;i++)
{
cout.precision(3);
cout<<a[i]<<setw(8);
}
}
2.Huffman译码函数代码:
void huffman(double *a,string *c,int n)
{
elem mp;stack s(n);
double *b;b=new double[n];for(int i=0;i<n;i++){b[i]=a[i];} double *d;d=new double[n];for(int i=0;i<n;i++){d[i]=i;}
double *e;e=new double[n];for(int i=0;i<n;i++){e[i]=i;}
string t;
for(int m=n;m>=2;m--)
{
b[m-2]+=b[m-1];
mp.a2=d[m-2];mp.a3=d[m-1];
s.push(mp);
double mp,mp1;
for(int i=0;i<n-1;i++)
{
for(int j=n-2;j>=i;j--)
{
if(b[j]<b[j+1])
{
mp=b[j+1]; mp1=d[j+1];
b[j+1]=b[j]; d[j+1]=d[j];
b[j]=mp;d[j]=mp1;
}
}
}
cout<<left<<setw(6)<<"\nP(X):";
for(int i=0;i<m-1;i++)
{
cout.precision(3);
cout<<setw(8)<<b[i];
}
}
while(!s.isEmpty())
{
mp=s.pop();
for(int i=0;i<n;i++)
{
if(mp.a2==e[i])
{
t=c[i];
}
}
for(int i=0;i<n;i++)
{
if(mp.a2==e[i])
{
c[i]=t;
c[i]+="0";
}
else if(mp.a3==e[i])
{
c[i]=t;
c[i]+="1";
}
}
}
}
(2)主函数main()实现初始化操作,完成对子函数的调用
void main()
{
int n;
cout<<"输入N:";
cin>>n;
c=new string[n];
aa(n);
huffman(a,c,n);
cout<<endl;
cout<<setw(6)<<"各项Huffman编码为:"<<endl;
for(int i=0;i<n;i++)
{
cout.precision(3);
cout<<setw(8)<<a[i];
cout.precision(0);
cout<<setw(n+4)<<c[i];
cout<<endl;
}
}
3 实验数据与实验结果
测试数据:随机生成归一化离散变量,如下图数据,并计算出各项Huffman编码。
实验结果:
4 程序代码清单:
#include<stdio.h>
#include<cstdio>
#include<iomanip>
#include<time.h>
#include<cassert>
#include<string>
#include<iostream>
using namespace std;
double *a;
string *c;
struct elem
{
double a2;
double a3;
};
class stack
{
int size;
int top;
elem *list;
public:
stack(const int sz=0){size=sz;top=0;list=new elem[sz];}
~stack(){delete []list;}
void clear(){top=0;}
void push(const elem& item){assert(top<size);list[top++]=item;} elem pop(){assert(!isEmpty());return list[--top];}
elem topValue() const{assert(!isEmpty());return list[top-1];} bool isEmpty() const{return top==0;}
};
void aa(int n)
{
double w=0;
a=new double[n];
srand((unsigned)time(NULL));
cout<<"随机生成归一化一维离散变量:"<<endl;
for(int i=0;i<n;i++)
{
a[i]=rand()%50;
w+=a[i];
}
for(int i=0;i<n;i++)
{
a[i]=a[i]/w;
}
double p;
for(int i=0;i<n-1;i++)
{
for(int j=n-2;j>=i;j--)
{
if(a[j]<a[j+1])
{
p=a[j+1];
a[j+1]=a[j];
a[j]=p;
}
}
}
cout<<"P(X):";
for(int i=0;i<n;i++)
{
cout.precision(3);
cout<<a[i]<<setw(8);
}
}
void huffman(double *a,string *c,int n)
{
elem mp;stack s(n);
double *b;b=new double[n];for(int i=0;i<n;i++){b[i]=a[i];} double *d;d=new double[n];for(int i=0;i<n;i++){d[i]=i;}
double *e;e=new double[n];for(int i=0;i<n;i++){e[i]=i;}
string t;
for(int m=n;m>=2;m--)
{
b[m-2]+=b[m-1];
mp.a2=d[m-2];mp.a3=d[m-1];
s.push(mp);
double mp,mp1;
for(int i=0;i<n-1;i++)
{
for(int j=n-2;j>=i;j--)
{
if(b[j]<b[j+1])
{
mp=b[j+1]; mp1=d[j+1];
b[j+1]=b[j]; d[j+1]=d[j];
b[j]=mp;d[j]=mp1;
}
}
}
cout<<left<<setw(6)<<"\nP(X):";
for(int i=0;i<m-1;i++)
{
cout.precision(3);
cout<<setw(8)<<b[i];
}
}
while(!s.isEmpty())
{
mp=s.pop();
for(int i=0;i<n;i++)
{
if(mp.a2==e[i])
{
t=c[i];
}
}
for(int i=0;i<n;i++)
{
if(mp.a2==e[i])
{
c[i]=t;
c[i]+="0";
}
else if(mp.a3==e[i])
{
c[i]=t;
c[i]+="1";
}
}
}
}
void main()
{
int n;
cout<<"输入N:";
cin>>n;
c=new string[n];
aa(n);
huffman(a,c,n);
cout<<endl;
cout<<setw(6)<<"各项Huffman编码为:"<<endl;
for(int i=0;i<n;i++)
{
cout.precision(3);
cout<<setw(8)<<a[i];
cout.precision(0);
cout<<setw(n+4)<<c[i];
cout<<endl;
}
}
实验三典型信道容量计算
[实验目的]
掌握用递推算法计算典型信道的容量的方法。
[实验学时]
2学时
[实验准备]
1.熟悉二进信道的概率转移矩阵表示,掌握信道容量的递推算法,设计用递推算法计算二进信道容量的数据结构和算法;
2.编写用递推算法计算二进信道容量的书面程序代码。
[实验内容及步骤]
用递推算法计算二进信道的容量
说明:
(1)构造各种二进信道的概率转移矩阵;
(2)用递推算法计算各种二进信道的容量;
(3)不断调整误差精度对系统进行测试,并进行对比分析;
(4)编写本次实验的实验报告。
附实验三内容及源程序
实验三用递推算法计算二进信道的容量1 实验内容
(1)构造各种二进信道的概率转移矩阵;
(2)用递推算法计算各种二进信道的容量;
(3)不断调整误差精度对系统进行测试,并进行对比分析;
2 数据结构与算法描述
(1)函数的定义:函数的数据成员
1.随机生成二元对称信道函数代码:
void aa()
{
double e=0;
cout<<"随机生成二元对称信道为:"<<endl;
int i=0;
for(int j=0;j<2;j++)
{
a[0][j]=rand()%100;
e+=a[0][j];
}
for(int j=0;j<2;j++)
{
a[0][j]=a[0][j]/e;
}
a[1][1]=a[0][0];a[1][0]=a[0][1];
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
cout<<setw(12)<<a[i][j];
}
cout<<endl;
}
}
2.随机生成二元删除信道函数代码:
void cc()
{
double e=0;
cout<<"随机生成二元删除信道为:"<<endl;
for(int j=0;j<2;j++)
{
b[0][j]=rand()%100;
e+=b[0][j];
}
for(int j=0;j<2;j++)
{
b[0][j]=b[0][j]/e;
}
b[0][2]=0;b[1][0]=0;
e=0;
for(int j=1;j<3;j++)
{
b[1][j]=rand()%100;
e+=b[1][j];
}
for(int j=1;j<3;j++)
{
b[1][j]=b[1][j]/e;
}
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++)
{
cout<<setw(12)<<b[i][j];
}
cout<<endl;
}
}
3.求二元对称信道最大信道容量和最大容量时w的值的函数代码:
void bb()
{
double w=0;
double e[2]={0,0};
for(w=0;w<=1;w+=0.01)
{
double tmp=0;
tmp=((w*a[0][0]+((1-w)*a[0][1]))*(log(1/(w*a[0][0]+((1-w)*a[0][1])))/log(2.0)))+(((w*a[ 0][1])+((1-w)*a[0][0]))*(log(1/((w*a[0][1])+((1-w)*a[0][0])))/log(2.0)))-(a[0][0]*(log(1/a[0 ][0])/log(2.0))+(a[0][1]*(log(1/a[0][1])/log(2.0))));
if(e[0]<tmp){e[0]=tmp;e[1]=w;}
}
cout<<"最大信道容量为:"<<setw(6)<<e[0]<<" 此时w的值为:"<<e[1]<<endl;
cout<<endl;
}
4. 求二元删除信道最大信道容量和最大容量时w的值的函数代码:
void dd()
{
double P[2][2];
P[1][0]=0;P[1][1]=1;
double temp[2]={0,1};
do{
double tmp1=0,tmp=0;
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++)
{
if(b[i][j]!=0){tmp1+=P[1][i]*b[i][j]*log(1.0/b[i][j])/log(2.0);} }
}
double temp2[2][3];
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++){temp2[i][j]=P[1][i]*b[i][j];}
}
for(int j=0;j<3;j++){temp2[0][j]=temp2[0][j]+temp2[1][j];}
for(int j=0;j<3;j++)
{
if(temp2[0][j]!=0){tmp-=temp2[0][j]*log(temp2[0][j])/log(2.0);} }
tmp-=tmp1;
if(tmp>=temp[0]){temp[0]=tmp;temp[1]=P[1][0];}
P[1][0]+=0.01;P[1][1]-=0.01;
}while(P[1][0]<=1.00);
cout<<"最大信道容量为:"<<temp[0]<<" 信源的w值为"<<temp[1]<<endl;
}
(2)主函数main()实现初始化操作,完成对子函数的调用
void main()
{
srand((unsigned)time(NULL));
aa();
bb();
cc();
dd();
}
3 实验数据与实验结果
测试数据:随机生成了2*2矩阵和2*3矩阵,并求得最大容量和w的值。
实验结果:
4 程序代码清单:
#include<iostream>
#include<time.h>
#include<iomanip>
#include<cmath>
using namespace std;
double a[2][2];
double b[2][3];
void aa()
{
double e=0;
cout<<"随机生成二元对称信道为:"<<endl;
int i=0;
for(int j=0;j<2;j++)
{
a[0][j]=rand()%100;
e+=a[0][j];
}
for(int j=0;j<2;j++)
{
}
a[1][1]=a[0][0];a[1][0]=a[0][1];
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
cout<<setw(12)<<a[i][j];
}
cout<<endl;
}
}
void bb()
{
double w=0;
double e[2]={0,0};
for(w=0;w<=1;w+=0.01)
{
double tmp=0;
tmp=((w*a[0][0]+((1-w)*a[0][1]))*(log(1/(w*a[0][0]+((1-w)*a[0][1])))/log(2.0)))+(((w*a[ 0][1])+((1-w)*a[0][0]))*(log(1/((w*a[0][1])+((1-w)*a[0][0])))/log(2.0)))-(a[0][0]*(log(1/a[0 ][0])/log(2.0))+(a[0][1]*(log(1/a[0][1])/log(2.0))));
if(e[0]<tmp){e[0]=tmp;e[1]=w;}
}
cout<<"最大信道容量为:"<<setw(6)<<e[0]<<" 此时w的值为:"<<e[1]<<endl;
cout<<endl;
}
void cc()
{
double e=0;
cout<<"随机生成二元删除信道为:"<<endl;
for(int j=0;j<2;j++)
{
b[0][j]=rand()%100;
e+=b[0][j];
}
for(int j=0;j<2;j++)
{
b[0][j]=b[0][j]/e;
}
b[0][2]=0;b[1][0]=0;
e=0;
for(int j=1;j<3;j++)
{
e+=b[1][j];
}
for(int j=1;j<3;j++)
{
b[1][j]=b[1][j]/e;
}
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++)
{
cout<<setw(12)<<b[i][j];
}
cout<<endl;
}
}
void dd()
{
double P[2][2];
P[1][0]=0;P[1][1]=1;
double temp[2]={0,1};
do{
double tmp1=0,tmp=0;
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++)
{
if(b[i][j]!=0){tmp1+=P[1][i]*b[i][j]*log(1.0/b[i][j])/log(2.0);} }
}
double temp2[2][3];
for(int i=0;i<2;i++)
{
for(int j=0;j<3;j++){temp2[i][j]=P[1][i]*b[i][j];}
}
for(int j=0;j<3;j++){temp2[0][j]=temp2[0][j]+temp2[1][j];}
for(int j=0;j<3;j++)
{
if(temp2[0][j]!=0){tmp-=temp2[0][j]*log(temp2[0][j])/log(2.0);} }
tmp-=tmp1;
if(tmp>=temp[0]){temp[0]=tmp;temp[1]=P[1][0];}
P[1][0]+=0.01;P[1][1]-=0.01;
}while(P[1][0]<=1.00);
cout<<"最大信道容量为:"<<temp[0]<<" 信源的w值为"<<temp[1]<<endl; }
void main()
{
srand((unsigned)time(NULL));
aa();
bb();
cc();
dd();
}。