文档库 最新最全的文档下载
当前位置:文档库 › Viterbi译码程序代码

Viterbi译码程序代码

Viterbi译码程序代码
Viterbi译码程序代码

译码主要部分

#include"stdafx.h"

//#define DEBUG

void deci2bin(int d, int size, int *b);

int bin2deci(int *b, int size);

int nxt_stat(int current_state, int input, int *memory_contents);

void init_quantizer(void);

void init_adaptive_quant(float es_ovr_n0);

int soft_quant(float channel_symbol);

int soft_metric(int data, int guess);

int quantizer_table[256];

void sdvd(int g[2][K], float es_ovr_n0, long channel_length, float*channel_output_vector, int *decoder_output_matrix)

{

int i, j, l, ll; //循环控制变量

long t; //时间

int memory_contents[K]; //记录输入内容

int input[TWOTOTHEM][TWOTOTHEM]; //对当前状态以及下一个状态映射

int output[TWOTOTHEM][2]; //卷积码编码输出矩阵

int nextstate[TWOTOTHEM][2]; //下一个状态矩阵

int accum_err_metric[TWOTOTHEM][2]; //误差累计矩阵

int state_history[TWOTOTHEM][K * 5 + 1]; //历史状态表

int state_sequence[K * 5 + 1]; //状态序列

int *channel_output_matrix; //信道输出序列

int binary_output[2];

int branch_output[2]; //0或者1的输出分支

int m, n, number_of_states, depth_of_trellis, step, branch_metric,

sh_ptr, sh_col, x, xx, h, hh, next_state, last_stop;

n = 2; //1/2为卷积码传输数据的码率

m = K - 1;//寄存器个数

number_of_states = (int)pow(2.0, m);//状态个数number of states = 2^(K - 1) = 2^m

depth_of_trellis = K * 5;

for (i = 0; i < number_of_states; i++)

{

for (j = 0; j < number_of_states; j++)

input[i][j] = 0; //输入数组初始化

for (j = 0; j < n; j++)

{

nextstate[i][j] = 0;//下一个状态数组初始化

output[i][j] = 0; //输出数组初始化

}

for (j = 0; j <= depth_of_trellis; j++)

{

state_history[i][j] = 0;//历史状态数组初始化state_history[4][16] }

accum_err_metric[i][0] = 0;//误差累计矩阵第一列初始化为0

accum_err_metric[i][1] = MAXINT;//误差累计矩阵第二列初始化为一个很大的数

}

/*前向纠错简称FEC(Forward Error Correction),

其原理是:发送方将要发送的数据附加上一定的冗余纠错码一并发送,

接收方则根据纠错码对数据进行差错检测,如发现差错,由接收方进行纠正*/

/*产生状态转移矩阵、输出矩阵、输入矩阵*/

//输入矩阵表示的是FEC编码传输给下一个状态

//下一个状态由输入和当前状态给出

//输出矩阵

for (j = 0; j < number_of_states; j++)

{

for (l = 0; l < n; l++)

{

next_state = nxt_stat(j, l, memory_contents);

input[j][next_state] = l;

/*计算给定的卷积编码器输出当前状态数和输入值*/

branch_output[0] = 0;

branch_output[1] = 0;

for (i = 0; i < K; i++)

{

branch_output[0] = branch_output[0] ^ memory_contents[i] & g[0][i];

branch_output[1] = branch_output[1] ^ memory_contents[i] & g[1][i];

}

nextstate[j][l] = next_state;//下一个状态

output[j][l] = bin2deci(branch_output, 2);//输出十进制

}

}

#ifdef DEBUG

printf("\nInput:");

for (j = 0; j < number_of_states; j++)

{

printf("\n");

for (l = 0; l < number_of_states; l++)

printf("%2d ", input[j][l]);

}

printf("\nOutput:");

for (j = 0; j < number_of_states; j++)

{

printf("\n");

for (l = 0; l < n; l++)

printf("%2d ", output[j][l]);

}

printf("\nNext State:");

for (j = 0; j < number_of_states; j++)

{

printf("\n");

for (l = 0; l < n; l++)

printf("%2d ", nextstate[j][l]);

}

#endif

channel_output_matrix =(int *)malloc(channel_length * sizeof(int));

if (channel_output_matrix == NULL)

{

printf("allocation is failure!!\n");

exit(1);

}

printf("\n");

/*信道输出为n行,2列,每行对应于一个通道符号给定的位和每一列对应于一个已编码的位*/ channel_length = channel_length / n;

init_adaptive_quant(es_ovr_n0);//进行优化,匹配过信噪比的量化矩阵

//量化信道输出,将浮点型数据转化为整形

for (t = 0; t < (channel_length * n); t = t + n)

{

for (i = 0; i < n; i++)

{

*(channel_output_matrix + (t / n) + (i * channel_length)) =

soft_quant(*(channel_output_vector + (t + i)));

//printf("%d ",*(channel_output_matrix + (t / n) + (i * channel_length)));

}

}

/*结束设置:利用网格遍历开始译码通道,在编码完成后结束*/

for (t = 0; t < channel_length - m; t++)

{

if (t <= m)

//假设从零,所以只是计算路径的所有零状态

step = (int)pow(2.0, m - t * 1);//如果不写成2.0,会出现函数重载不明确的错误else

step = 1;

//利用state_history矩阵作为循环缓冲区

sh_ptr = (int)((t + 1) % (depth_of_trellis + 1));//sh_ptr为state history矩阵的指针

for (j = 0; j < number_of_states; j += step)

{

//重复每个可能的卷积编码器的输出组

for (l = 0; l < n; l++)

{

branch_metric = 0;

//计算每个通道符号的分支度量,以及所有的信道总和在卷积编码器的输出组信道符号

binary_output[0] = (output[j][l] & 0x00000002) >> 1;

binary_output[1] = output[j][l] & 0x00000001;

branch_metric = branch_metric +

abs(*(channel_output_matrix + (0 * channel_length + t)) - 7 *

binary_output[0])

+ abs(*(channel_output_matrix + (1 * channel_length + t)) - 7 * binary_output[1]);

//选择累加误差最小的

if (accum_err_metric[nextstate[j][l]][1] > accum_err_metric[j][0] + branch_metric)

{

accum_err_metric[nextstate[j][l]][1] = accum_err_metric[j][0] + branch_metric;

state_history[nextstate[j][l]][sh_ptr] = j;

//printf("state_history[%d][%d]=%d\n", nextstate[j][l], sh_ptr,

state_history[nextstate[j][l]][sh_ptr]);

}

} //循环l结束

} //j结束,更新网格

//accum_err_metric矩阵第二列移到第一列,第二列标志为一个很大的数

for (j = 0; j < number_of_states; j++)

{

accum_err_metric[j][0] = accum_err_metric[j][1];

//printf("accum_err_metric[%d][0]=%d\n", j, accum_err_metric[j][0]);

accum_err_metric[j][1] = MAXINT;

}

//如果网格填充完成,现在需要追踪

{

for (j = 0; j <= depth_of_trellis; j++)//初始化状态序列矩阵

state_sequence[j] = 0;

// 找到的最小累积state_history元素

x = MAXINT;

for (j = 0; j < (number_of_states / 2); j++)

{

if(accum_err_metric[j][0] < accum_err_metric[number_of_states - 1 - j][0])

{

xx = accum_err_metric[j][0];

hh = j;

}

else

{

xx = accum_err_metric[number_of_states - 1 - j][0];

hh = number_of_states - 1 - j;

}

if (xx < x)

{

x = xx;

h = hh;

}

}

state_sequence[depth_of_trellis] = h;

for (j = depth_of_trellis; j > 0; j--)

{

sh_col = j + (sh_ptr - depth_of_trellis);

if (sh_col < 0)

sh_col = sh_col + depth_of_trellis + 1;

state_sequence[j - 1] = state_history[state_sequence[j]][sh_col];

}

//找出输入序列对应的状态序列在最佳路径

*(decoder_output_matrix + t - depth_of_trellis + 1) =

input[state_sequence[0]][state_sequence[1]];

//printf("译码输出:%d\n", *(decoder_output_matrix + t - depth_of_trellis + 1));

} //if状态

} // 结束t循环

//译码信道中的数据

for (t = channel_length - m; t < channel_length; t++)

{

sh_ptr = (int)((t + 1) % (depth_of_trellis + 1));

last_stop = number_of_states / pow(2.0, t - channel_length + m);//不需要考虑输入的状态是1,所以确定最高可能的状态数是0

for (j = 0; j < last_stop; j++)

{

branch_metric = 0;

deci2bin(output[j][0], n, binary_output);

for (ll = 0; ll < n; ll++)

{

branch_metric = branch_metric + soft_metric(*(channel_output_matrix + (ll * channel_length + t)), binary_output[ll]);

}

if ((accum_err_metric[nextstate[j][0]][1] > accum_err_metric[j][0] +

branch_metric))

{

accum_err_metric[nextstate[j][0]][1] = accum_err_metric[j][0] +

branch_metric;

state_history[nextstate[j][0]][sh_ptr] = j;

}

}

for (j = 0; j < number_of_states; j++)

{

accum_err_metric[j][0] = accum_err_metric[j][1];

accum_err_metric[j][1] = MAXINT;

}

//对所选路径进行选择

{

for (j = 0; j <= depth_of_trellis; j++)

state_sequence[j] = 0;

x = accum_err_metric[0][0];

h = 0;

for (j = 1; j < last_stop; j++)

{

if (accum_err_metric[j][0] < x)

{

x = accum_err_metric[j][0];

h = j;

}

}

state_sequence[depth_of_trellis] = h;

for (j = depth_of_trellis; j > 0; j--)

{

sh_col = j + (sh_ptr - depth_of_trellis);

if (sh_col < 0)

sh_col = sh_col + depth_of_trellis + 1;

state_sequence[j - 1] = state_history[state_sequence[j]][sh_col];

}

*(decoder_output_matrix + t - depth_of_trellis + 1) =

input[state_sequence[0]][state_sequence[1]];

} //if条件状态

} //结束t循环

for (i = 1; i < depth_of_trellis - m; i++)

*(decoder_output_matrix + channel_length - depth_of_trellis + i) =

input[state_sequence[i]][state_sequence[i + 1]];

free(channel_output_matrix);

return;

}

//初始化三位软判决量化编码器

//加入噪声后的量化

void init_adaptive_quant(float es_ovr_n0)

{

int i, d;

float es, sn_ratio, sigma;

es = 1;

sn_ratio = (float)pow(10.0, (es_ovr_n0 / 10.0));

sigma = (float)sqrt(es / (2.0 * sn_ratio));

d = (int)(32 * 0.5 * sigma);

for (i = -128; i < (-3 * d); i++)

quantizer_table[i + 128] = 7;

for (i = (-3 * d); i < (-2 * d); i++)

quantizer_table[i + 128] = 6;

for (i = (-2 * d); i < (-1 * d); i++)

quantizer_table[i + 128] = 5;

for (i = (-1 * d); i < 0; i++)

quantizer_table[i + 128] = 4;

for (i = 0; i < (1 * d); i++)

quantizer_table[i + 128] = 3;

for (i = (1 * d); i < (2 * d); i++)

quantizer_table[i + 128] = 2;

for (i = (2 * d); i < (3 * d); i++)

quantizer_table[i + 128] = 1;

for (i = (3 * d); i < 128; i++)

quantizer_table[i + 128] = 0;

}

//channel_symbol信道中的值为-1或+1的加噪信号

int soft_quant(float channel_symbol)

{

int x;

x = (int)(32.0 * channel_symbol); //则x的平均值为-32或+32

if (x < -128) x = -128; //小于-128,输出128

if (x > 127) x = 127; //大于127则输出127

return(quantizer_table[x + 128]); //查找量化表

}

/* this metric is based on the algorithm given in Michelson and Levesque, page 323. */

int soft_metric(int data, int guess)

{

return(abs(data - (guess * 7)));

//当给出当前状态以及输入时,计算下一个状态,并且计算卷积码编码内容

int nxt_stat(int current_state, int input, int *memory_contents)

{

int binary_state[K - 1]; //二进制当前状态

int next_state_binary[K - 1]; //二进制下一个状态

int next_state; //十进制当前状态

int i;

deci2bin(current_state, K - 1, binary_state);

next_state_binary[0] = input;

for (i = 1; i < K - 1; i++)

next_state_binary[i] = binary_state[i - 1];

next_state = bin2deci(next_state_binary, K - 1);

memory_contents[0] = input;

for (i = 1; i < K; i++)

memory_contents[i] = binary_state[i - 1]; //编码内容

return(next_state);//返回十进制的下一个状态

}

//将十进制数据转化为特殊的二进制,例如:十进制“100011”输出二进制数据100011 void deci2bin(int d, int size, int *b) {

int i;

for (i = 0; i < size; i++)

b[i] = 0;

b[size - 1] = d & 0x01;

for (i = size - 2; i >= 0; i--) {

d = d >> 1;

b[i] = d & 0x01;

}

}

//将2进制数据转化为特殊的十进制,例如:二进制“100011”输出十进制数据100011 int bin2deci(int *b, int size) {

int i, d;

d = 0;

for (i = 0; i < size; i++)

d += b[i] << (siz

e - i - 1);

return(d);

}

程序辅助模块

// viterbi.cpp : 定义控制台应用程序的入口点。

//

#include"stdafx.h"

int* gen_data(long data_len)//使用指针函数返回生成的输入数组

{

int *array;

unsignedlong t; //系统时间t,产生随机数序列数字

srand((unsigned)time(NULL)); //头文件是#include

array = (int *)malloc(data_len * sizeof(int));//开辟动态数组,为了防止栈溢出//将产生的随机数序列写入一个输出数组

for (t = 0; t < data_len; t++)

{

*(array+t) = (int)(rand() / (RAND_MAX / 2) > 0.5);

/*

printf("%d ", *(array + t));

if ((t+1)%50==0)

printf("\n");

*/

}

returnarray;

}

int* conv(int g[2][K], long input_len, int *in_array)

{

int *out_array;

int m = K - 1; //编码存储长度,也就是寄存器的个数(K为编码约束长度)long t, tt;

int j, k;

int *unencoded_data; //指针型未编码数组

int shift_reg[K]; //移位寄存器

int sr_head; //指向一位寄存器的首位

int p, q; //异或门输出变量

unencoded_data = (int *)malloc((input_len + m) * sizeof(int));//给将要编码的序列扩展长度并分配动态内存

out_array = (int *)malloc(2 * (input_len + m) *sizeof(int));//一个输入对应两个输出,所以其长度为2 * (input_len + m)

if (unencoded_data == NULL) {

printf("allocation is faliure!!!");

exit(1);

}

for (t = 0; t < input_len; t++)//将系统生成的长度为Input_len的数据写入unencoded_data {

*(unencoded_data + t) = *(in_array + t);

//printf("%d\n", *(unencoded_data + t));

}

for (t = 0; t < m; t++) //在unencoded_data需要编码存储个0

{

*(unencoded_data + input_len + t) = 0;

//printf("%d\n", *(unencoded_data + input_len+ t));

}

for (j = 0; j < K; j++) //初始化移位寄存器

shift_reg[j] = 0;

sr_head = 0; //移位寄存器的首指针

tt = 0;//初始化通道标志位输出指针

//卷积码编码

for (t = 0; t < input_len + m; t++) {

shift_reg[sr_head] = *(unencoded_data + t);//移位寄存器首指针指向unencoded_data

p = 0;

q = 0;

for (j = 0; j < K; j++) {

k = (j + sr_head) % K;

p =p^ shift_reg[k] & g[0][j];

q = q^shift_reg[k] & g[1][j];

}

//将异或门的两个输出端写入out_array

*(out_array + tt) = p;

tt = tt + 1;

*(out_array + tt) = q;

tt = tt + 1;

sr_head = sr_head-1; //使移位寄存器循环

if (sr_head < 0)

sr_head = m;

}

/*

for (int i = 0; i < tt; i++)

{

printf("%d ", *(out_array + i));

if ((i+ 1) % 50 == 0)

printf("\n");

}

*/

free(unencoded_data);//释放空间

return out_array;//返回out_array指针数组

}

float gngauss(float mean, float sigma) //使用极坐标方法产生高斯白噪声

{

double v1, v2, s, x1;

do

{

v1 = 2.0*rand() / RAND_MAX - 1;//第一步:产生两个独立同分布的V(0,1)

v2 = 2.0*rand() / RAND_MAX - 1;

s = v1*v1 + v2*v2; //第二步:计算s

} while (s >= 1); //第三步:若s大于1,则返回第一步

if//否则,计算x1

(!s) x1 = 0;

else

x1 = v1*sqrt(-2.0*log(s) / s); //log(s)默认对数的底为e

return (mean + sigma*x1);

}

float* addnoise(float es_ovr_n0, long channel_len, int *in_array)

{

float *out_array;

long t;

float mean, es, sn_ratio, sigma, signal;

mean = 0;

es = 1; //固定比特能量为es=1

sn_ratio = (float)pow(10, (es_ovr_n0 / 10));//信噪比,由dB形式转换成普通形式

sigma = (float)sqrt(es / (2 * sn_ratio)); //标准差

out_array = (float *)malloc(channel_len *sizeof(float));//给通过BPSK信道输出out_array 开辟空间

for (t = 0; t < channel_len; t++)

{

signal = 1 - 2 * (*(in_array + t));//如果输入的是0,经过BPSK变为+1;如果输入的是1,经过BPSK变为-1

*(out_array + t) = signal + gngauss(mean, sigma);//加入高斯白噪声

//printf("%f\n", *(out_array + t));

}

/*

for (int i = 0; i < channel_len; i++)

{

printf("%f ", *(out_array + i));

if ((i + 1) % 10== 0)

printf("\n");

}

*/

return out_array;

}

externvoid sdvd(int g[2][K], float es_ovr_n0, long channel_length, float *channel_output_vector, int *decoder_output_matrix);

int _tmain(int argc, _TCHAR* argv[])

{

/*

long data_len=LENGTH;

int a = 2;//给in_array,out_array两个动态数组提供起始地址

float b = 1.0;

int *in_array ;

int *out_array;

float *bpsk_array;

bpsk_array = &b;

in_array=out_array = &a;

int g[2][K] = { { 1, 1, 1 }, { 1, 0, 1 } };//当K=3时,两个子生成元

float mean, sigma;

printf("数据的长度:%d\n", data_len);

in_array=gen_data(data_len);

/*printf("%d \n", data_len);

for (int t = 0; t < data_len; t++)

{

printf("%d ", *(in_array + t));

}*/

/*

out_array=conv(g, data_len,in_array);

/*for (int i = 0; i<2*(data_len+K-1); i++)

printf("%d ", *(out_array + i));*/

/*mean = 0.0;

sigma = 0.1;

gngauss(mean, sigma);

printf("%f\n", gngauss(mean, sigma));*/

/*

long message = LENGTH;

long channel_len = 2*(message+K-1);//信道长度

long es_ovr_n0=LOESN0;

bpsk_array=addnoise(es_ovr_n0, channel_len, out_array);

for (int i = 0; i < channel_len; i++)

{

printf("%f ", *(bpsk_array + i));

if (i % 2 != 0)

{

printf("\n");

}

}

*/

long iter, t, msg_length, channel_length;

int *original;

int *encoded; /* original, encoded, & decoded data arrays */ int *decoded;

double start,finish;

float *noisy; //噪声序列

int m; // m = K - 1

float es_ovr_n0;

int number_errors_encoded;

#if K == 3

int g[2][K] = { { 1, 1, 1 }, /* 7 */

{ 1, 0, 1 } }; /* 5 */

#endif

#if K == 5

int g[2][K] = { { 1, 1, 1, 0, 1 }, /* 35 */

{ 1, 0, 0, 1, 1 } }; /* 23 */

#endif

#if K == 3

printf("g1 = %d%d%d", g[0][0], g[0][1], g[0][2]);

printf("\ng2 = %d%d%d\n", g[1][0], g[1][1], g[1][2]);

#endif

#if K == 5

printf("g1 = %d%d %d%d%d", g[0][0], g[0][1], g[0][2], g[0][3], g[0][4]);

printf("\ng2 = \n%d%d %d%d%d\n", g[1][0], g[1][1], g[1][2], g[1][3], g[1][4]); #endif

m = K - 1;

msg_length = MSG_LEN;

channel_length = (msg_length + m) * 2;

printf("信息length=%d\n", msg_length);

original = (int *)malloc(msg_length * sizeof(int));//原始发送码字(信息长度)if (original == NULL)

{

printf("Allocation is failure!!!");

exit(1);

}

encoded =(int *) malloc(channel_length * sizeof(int));//编码信道(信道长度)

if (encoded == NULL)

{

printf("Allocation is failure!!!");

exit(1);

}

noisy = (float *)malloc(channel_length * sizeof(float));//信号噪声(信道长度)if (noisy == NULL) {

printf("Allocation is failure!!!");

exit(1);

}

decoded = (int *)malloc(msg_length * sizeof(int));//译码输出(信息长度)

if (decoded == NULL) {

printf("Allocation is failure!!!");

exit(1);

}

for (es_ovr_n0 = LOESN0; es_ovr_n0 <= HIESN0; es_ovr_n0 += ESN0STEP)

{

start = clock();

number_errors_encoded = 0;

//printf("产生输入信息如下:\n");

original=gen_data(msg_length);

//printf("卷积码编码如下:\n");

encoded = conv(g, msg_length, original);

//printf("\n加入噪声后的编码如下:\n");

noisy=addnoise(es_ovr_n0, channel_length, encoded);

//printf("\n译码输出如下:");

sdvd(g, es_ovr_n0, channel_length, noisy, decoded);

/*

for (int i = 0; i < msg_length; i++)

{

printf("%d ", *(decoded + i));

if ((i+ 1) % 50 == 0)

printf("\n");

}

*/

printf("\n");

for (t = 0; t < msg_length; t++)

{

if (*(original + t) != *(decoded + t))

{

*(original + t) = 0;

number_errors_encoded = number_errors_encoded + 1;

printf("第%d个错误位置是 %ld\n", number_errors_encoded, t);//判断出错位置

}

}

finish = clock();

printf("以%1.1fdB Es/No, ", es_ovr_n0);

printf("消耗时间:%fs", (finish - start) / CLOCKS_PER_SEC);

}

/*free(original);

free(encoded);

free(noisy);

free(decoded); */

return 0;

}

matlab相关图形实现代码

根据数据点绘制饼图和针状图: x=[1 2 3 4 5 6]; >> subplot(2,2,1);pie(x); >> subplot(2,2,2);pie3(x); >> subplot(2,2,3);stem(x); >>subplot(2,2,4);stem3(x); 5% 10% 14% 19% 24% 29% 24% 29% 19% 5%14% 10%0 2 4 6 2 4 6 5 10 01 2 05 10

根据数据点绘制向量场图、羽状图和罗盘图: x=[1 2 3 4 5 6];y=[1 2 3 4 5 6]; u=[1 2 3 4 5 6];v=[1 2 3 4 5 6]; subplot(2,2,1);quiver(x,y,u,v); subplot(2,2,2);quiver(x,y,u,v,'r'); subplot(2,2,3);feather(u,v); subplot(2,2,4);compass(u,v); 024680 246 802468 246 80 5 10 15 2 4 6 5 10 30 210 60240 90270 120 300 150330 180

rand(m,n)产生m ×n 均匀分布的随机矩阵,元素取值在0.0~1.0。 randn 函数:产生标准正态分布的随机数或矩阵的函数。 Y = randn(m,n) 或 Y = randn([m n])返回一个m*n 的随机项矩阵。 > theta=10*rand(1,50); %确定50个随机数theta >> Z=peaks; %确定Z 为峰值函数peaks >> x=0:0.01:2*pi;y=sin(x); %确定正弦函数数据点x.y >> t=randn(1000,1); %确定1000个随机数t >> subplot(2,2,1);rose(theta); %关于(theta )的玫瑰花图 >> subplot(2,2,2);area(x,y); %关于(x,y)的面积图 >> subplot(2,2,3);contour(Z); %关于Z 的等值线图(未填充) >> subplot(2,2,4);hist(t); %关于t 的柱状图 5 10 30 210 60 240 90270 120300150330 18000246 -1 -0.500.5 110 20 30 40 10 2030 40-4 -2 2 4 100 200 300

Viterbi译码的Matlab实现

2010年12月(上) Viterbi 译码的Matlab 实现 张慧 (盐城卫生职业技术学院,江苏盐城 224006) [摘要]本文主要介绍了Viterbi 译码是一种最大似然译码算法,是卷积编码的最佳译码算法。本文主要是以(2,1,2)卷积码为例,介 绍了Viterbi 译码的原理和过程,并用Matlab 进行仿真。[关键词]卷积码;Viterbi 译码 1卷积码的类型 卷积码的译码基本上可划分为两大类型:代数译码和概率译码,其中概率译码是实际中最常采用的卷积码译码方法。 2Viterbi 译码 Viterbi 译码是由Viterbi 在1967年提出的一种概率译码,其实质是最大似然译码,是卷积码的最佳译码算法。它利用编码网格图的特殊结构,降低了计算的复杂性。该算法考虑的是,去除不可能成为最大似然选择对象的网格图上的路径,即,如果有两条路径到达同一状态,则具有最佳量度的路径被选中,称为幸存路径( surviving path )。对所有状态都将进行这样的选路操作,译码器不断在网格图上深入,通过去除可能性最小的路径实现判决。较早地抛弃不可能的路径降低了译码器的复杂性。 为了更具体的理解Viterbi 译码的过程,我们以(2,1,2)卷积码为例,为简化讨论,假设信道为BSC 信道。译码过程的前几步如下:假定输入数据序列m ,码字U ,接收序列Z ,如图1所示,并假设译码器确知网格图的初始状态。 图1 时刻t 1接收到的码元是11,从状态00出发只有两种状态转移方向,00和10,如图a 所示。状态转换的分支量度是2;状态转换的分支径量度是0。时刻t 2从每个状态出发都有两种可能的分支,如图b 所示。这些分支的累积量度标识为状态量度┎a ,┎b ,┎c ,┎d ,与各自的结束状态相对应。同样地,图c 中时刻t 3从每个状态出发都有两个分支,因此,时刻时到达每个状态的路径都有两条,这两条路径中,累积路径量度较大的将被舍弃。如果这两条路径的路径量度恰好相等,则任意舍弃其中一条路径。到各个状态的幸存路径如图d 所示。译码过程进行到此时,时刻t 1和t 2之间仅有一条幸存路径,称为公共支(com-mon stem )。因此这时译码器可以判决时刻t 1和t 2之间的状态转移是00→10;因为这个状态转移是由输入比特1产生的,所以译码器输出1作为第一位译码比特。由此可以看出,用实线表示输入比特0,虚线表示输入比特1,可以为幸存路径译码带来很大的便利。注意,只有当路径量度计算进行到网格图较深处时,才产生第一位译码比特。在典型的译码器实现中,这代表了大约是约束长度5倍的译码延迟。 图2幸存路径选择 在译码过程的每—步,到达每个状态的可能路径总有两条,通过比较路径量度舍弃其中一条。图e 给出了译码过程的下一步:在时刻t 5到达各个状态的路径都有两条,其中一条被舍弃;图f 是时刻t 5的幸存路径。注意,此例中尚不能对第二位输入数据比特做出判决,因为在时刻t 2离开状态10的路径仍为两条。图g 中的时刻t 6同样有路径合并,图h 是时刻t 6的幸存路径,可见编码器输出的第二位译码比特是1,对应了时刻t 2和t 3之间的幸存路径。译码器在网格图上继续上述过程,通过不断舍弃路径直至仅剩一条,来对输入数据比特做出判决。 网格图的删减(通过路径的合并)确保了路径数不会超过状态数。对于此例的情况,可证明在图b 、d 、f 、h 中,每次删减后都只有4条路径。而对于未使用维特比算法的最大似然序列彻底比较法,其可能路径数(代表可能序列数)是序列长度的指数函数。对于分支字长为L 的二进制码字序列,共有2L 种可能的序列。下面我们用Matlab 函数viterbi (G,k,channel_output )来产生输入序列经Viterbi 译码器得到的输出序列,并将结果与输入卷积码编码器的信息序列进行比较。在这里,G =g ,k=k0,channel_output=output 。用Matlab 函数得到的译码输出为10011100110000111,这与我们经过理论分析得出的结果是一致的。 我们用subplot 函数将译码器最终的输出结果与(下转第261页) 250

DSP卷积码的维特比译码的分析与实现

编号: 《DSP技术与应用》课程论文卷积码的维特比译码的分析与实现 论文作者姓名:______ ______ 作者学号:___ ______ 所在学院: 所学专业:_____ ___ 导师姓名职称:__ _ 论文完成时间: _

目录 摘要: (1) 0 前言 (2) 1 理论基础 (2) 1.1信道理论基础 (2) 1.2差错控制技术 (3) 1.3纠错编码 (4) 1.4线性分组码 (5) 2 卷积码编码 (7) 2.1 卷积码概要 (7) 2.2 卷积码编码器 (8) 2.3卷积码的图解表示 (8) 2.4 卷积码的解析表示 (11) 3 卷积码的译码 (14) 3.1 维特比译码 (15) 3.2 代数译码 (17) 3.3 门限译码 (18) 4 维特比译码器实现 (18) 4.1 TMS320C54 系列DSP概述 (18) 4.2 Viterbi译码器的DSP实现 (19) 4.3 实现结果 (21) 5 结论 (21) 参考文献 (22) II

卷积码的维特比译码的分析与实现 摘要: 针对数据传输过程中的误码问题,本文论述了提高数据传输质量的一些编码及译码的实现问题。自P.Elias 首次提出卷积码编码以来,这一编码技术至今仍显示出强大的生命力。在与分组码同样的码率R 和设备复杂性的条件下,无论从理论上还是从实际上均己证明卷积码的性能至少不比分组码差,且实现最佳和准最佳译码也较分组码容易。目前,卷积码已广泛应用在无线通信标准中,其维特比译码则利用码树的重复性结构,对最大似然译码算法进行了简化。本文所做的主要工作: 首先对信道编码技术进行了研究,根据信道中可能出现的噪声等问题对卷积码编码方法进行了主要阐释。 其次,对卷积码维特比译码器的实现算法进行了研究,完成了译码器的软件设计。 最后,结合实例,采用DSP芯片实现卷积码的维特比译码算法的仿真和运行。 关键词: 卷积码维特比译码DSP Convolutional codes and Viterbi decoding analysis and realization Zhang Yi-Fei (School of Physics and Electronics, Henan University, Henan Kaifeng 475004, China) Abstract: Considering the error bit problem during data transmission,this thesis discussed some codings and decoders,aiming at enhancing transmission performance. From P.Elias first gave the concept of convolutional code, it has show its’ great advantage. Under the same condition and the same rate of block code, the performance of convolutional code is better than block code, and it’s easier to implement the best decoding.Convolutional codes have been widely used in wireless communication standards, the V iterbi decoding using the repetitive structure of the code tree, the maximum likelihood decoding algorithm has been simplified. Major work done in this article: First, the channel coding techniques have been studied, the main interpretation of the convolutional code encoding method according to the channel may be noise and other issues. Secondly, the convolutional code V iterbi decoder algorithm has been studied, the software design of the decoder. Finally, with examples, simulation and operation of the DSP chip convolutional codes, Viterbi decoding algorithm. 1

MATLAB程序代码

MATLAB 程序代码以及运行结果function [ ]= xy_1( A ) % Detailed explanation goes here x0=653.779 y0=604.47 %%%JD0的坐标 x1=757.119 y1=569.527 %%%JD1的坐标 dx=x0-x1 dy=y0-y1 L=(dx^2+dy^2)^0.5 %JD1到ID2的距离 T=T1(12,28,37) %%%切线长 xk0=T-L yk0=0 %JD2的局部坐标 c=0.9473 s=-0.3203 %%%预设cos和sin的值 %求左端缓和曲线坐标 for l=0:10:40 x=l-(l^5)/(40*(A^2))+l^9/(3456*(A^4)) %求左端缓和曲线X局部坐标 y=l^3/(6*A)-(l^7)/(336*(A^3)) %求左端缓和曲线Y局部坐标 dxk=x-xk0 dyk=y-yk0 B=[x0;y0]+[c,-s;s,c]*[dxk;dyk] %进行坐标换算 end end function [ T1 ] = T1( a,b,c) %求左端切线长 % Detailed explanation goes here A=a+b/60+c/3600 r=750 p1=p(40,750) p2=p(30,750) m1=m(40,750) T1=(r+p2-(r+p1)*cosd(A))/sind(A)+m1 end

function x = JZ1( ) %左端坐标系坐标转换矩阵 % Detailed explanation goes here x0=653.779 y0=604.47 %%%JD0的坐标 x1=757.119 y1=569.527 %%%JD1的坐标 dx=x0-x1 dy=y0-y1 L=(dx^2+dy^2)^0.5 %JD1到ID2的距离T=T1(12,28,37) %%%切线长 xk0=T-L yk0=0 %JD0的局部坐标 xk1=T yk1=0 %JD1的局部坐标 dxk=xk0-xk1 dyk=yk0-yk1 A=[dxk,-dyk;dyk,dxk] b=[dx,dy]' x=inv(A)*b %依次输出cos、sin 的值 end xy_1(30000) A = 30000 x0 = 653.7790 y0 = 604.4700 x1 =

Viterbi译码的MATLAB仿真研究

BUPT 卷积码编码及Viterbi译码 班级:07114 学号:070422 姓名:吴希龙 指导老师:彭岳星 邮箱:FusionBupt@https://www.wendangku.net/doc/4e4710280.html,

1. 序言 卷积码最早于1955年由Elias 提出,稍后,1957年Wozencraft 提出了一种有效地译码方法即序列译码。1963年Massey 提出了一种性能稍差但是比较实用的门限译码方法,使得卷积码开始走向实用化。而后1967年Viterbi 提出了最大似然译码算法,它对存储级数较小的卷积码很容易实现,被称作Viterbi 译码算法,广泛的应用于现代通信中。 2. 卷积码编码及译码原理 2.1 卷积码编码原理 卷积码是一种性能优越的信道编码,它的编码器和解码器都比较易于实现,同时还具有较强的纠错能力,这使得它的使用越来越广泛。卷积码一般表示为(n,k,K)的形式,即将k 各信息比特编码为n 个比特的码组,K 为编码约束长度,说明编码过程中相互约束的码段个数。卷积码编码后的n 各码元不经与当前组的k 个信息比特有关,还与前K-1个输入组的信息比特有关。编码过程中相互关联的码元有K*n 个。R=k/n 是编码效率。编码效率和约束长度是衡量卷积码的两个重要参数。典型的卷积码一般选n,k 较小,但K 值可取较大(>10),以获得简单而高性能的卷积码。 卷积码的编码描述方式有很多种:冲激响应描述法、生成矩阵描述法、多项式乘积描述法、状态图描述,树图描述,网格图描述等。 2.1.1 卷积码解析表示法 卷积码的解析表示发大致可以分为离散卷积法,生成矩阵法,码多项式法。下面以离散卷积为例进行说明。 卷积码的编码器一般比较简单,为一个具有k 个输入端,n 个输出端,m 级移位寄存器的有限状态有记忆系统。下图所示为(2,1,7)卷积码的编码器。 若输入序列为u =(u 0u 1u 2u 3……), 则对应两个码字序列c ①=(c 0①c 1①c 2①c 3①……)和c ②=(c 0②c 1②c 2②c 3② ……) 相应的编码方程可写为c ①=u ?g ①,c ②=u ?g ②,c=(c ①,c ②)。 “?” 符号表示卷积运算,g ①,g ②表示编码器的两个冲激响应,即编码器的输出可以由输入序列和编码器的两个冲击响应卷积而得到,故称为卷积码。这里的冲激响应指:当输入为[1 0 0 0 0 … … ]序列时,所观察到的两个输出序列值。由于上图K 值为7,故冲激响应至

Matlab的卷积码译码器的仿真要点

基于Matlab的卷积码译码器的 设计与仿真 学生姓名:指导老师:** 摘要本课程设计主要解决对一个卷积码序列进行维特比(Viterbi)译码输出, 并通过Matlab软件进行设计与仿真,并进行误码率分析。在课程设计中,系统开发平台为Windows Vista Ultimate,程序设计与仿真均采用Matlab R2007a(7.4),最后仿真详单与理论分析一致。 关键词课程设计;卷积码译码器;Matlab;Simulink;设计与仿真 1引言 本课程设计主要解决对一个卷积码序列进行维特比(Viterbi)译码输出,并通 过Matlab软件进行设计与仿真。卷积码的译码有两种方法——软判决和硬判决,此课程设计采用硬判决的维特比译码。 1.1课程设计目的 卷积码是一种向前纠错控制编码。它将连续的信息比特序列映射为连续的编码器输出符号。这种映射是高度结构化的,使得卷积码的译码方法与分组码译码所采用的方法完全不同。可以验证的是在同样复杂度情况下,卷积码的编码增益要大于分组码的编码增益。对于某个特定的应用,采用分组编码还是采用卷积编码哪一种更好则取决于这一应用的具体情况和进行比较时可用的技术[1]。 本课程设计便是通过Matlab设计一个硬判决维特比译码输出的完整电路,并进行误码率分析。

1.2 课程设计的原理 卷积码,又称连环码,是由伊莱亚斯(P.elias)于1955年提出来的一种非分组码。 卷积编码的最佳译码准则为:在给定已知编码结构、信道特性和接收序列的情况下,译码器将把与已经发送的序列最相似的序列作为传送的码字序列的估值。对于二进制对称信道,最相似传送序列就是在汉明距离上与接收序列最近的序列。 卷积码的译码方法有两大类:一类是大数逻辑译码,又称门限译码(硬判决,编者注);另一种是概率译码(软判决,编者注),概率译码又分为维特比译码和序列译码两种。门限译码方法是以分组码理论为基础的,其译码设备简单,速度快,但其误码性能要比概率译码法差[2]。 当卷积码的约束长度不太大时,与序列译码相比,维特比译码器比较简单,计算速度快。维特比译码算法是1967年由Viterbi提出,近年来有大的发展。目前在数字通信的前向纠错系统中用的较多,而且在卫星深空通信中应用更多,该算法在卫星通信中已被采用作为标准技术。 2维特比译码原理 采用概率译码的基本思想是:把已接收序列与所有可能的发送序列做比较,选择其中码距最小的一个序列作为发送序列。如果发送L组信息比特,那么对于(n,k)卷积码来说,可能发送的序列有2kL个,计算机或译码器需存储这些序列并进行比较,以找到码距最小的那个序列。当传信率和信息组数L较大时,使得译码器难以实现。维特比算法则对上述概率译码做了简化,以至成为了一种实用化的概率算法。它并不是在网格图上一次比较所有可能的2kL条路径(序列),而是接收一段,计算和比较一段,选择一段最大似然可能的码段,从而达到整个码序列是一个最大似然值得序列。 下面以图2.1的(2,1,3)卷积码编码器所编出的码为例,来说明维特比解码的方法和运作过程。为了能说明解码过程,这里给出该码的状态图,如图2.2所

卷积码编码和维特比译码

卷积码编码维特比译码实验设计报告 SUN 一、实验目的 掌握卷积码编码和维特比译码的基本原理,利用了卷积码的特性, 运用网格图和回溯以得到译码输出。 二、实验原理 1.卷积码是由连续输入的信息序列得到连续输出的已编码序列。其编码器将k个信息码元编为n个码元时,这n个码元不仅与当前段的k个信息有关,而且与前面的(m-1)段信息有关(m为编码的约束长度)。 2.一般地,最小距离d表明了卷积码在连续m段以内的距离特性,该码可以在m个连续码流内纠正(d-1)/2个错误。卷积码的纠错能力不仅与约束长度有关,还与采用的译码方式有关。 3. 维特比译码算法基本原理是将接收到的信号序列和所有可能的发送信号序列比较,选择其中汉明距离最小的序列认为是当前发送序列。卷积码的Viterbi 译码是根据接收码字序列寻找编码时通过网格图最佳路径的过程,找到最佳路径即完成了译码过程,并可以纠正接收码字中的错误比特。 4.所谓“最佳”, 是指最大后验条件概率:P( C/ R) = max [ P ( Cj/ R) ] , 一般来说, 信道模型并不使用后验条件概率,因此利用Beyes 公式、根据信道特性出结论:max[ P ( Cj/ R) ]与max[ P ( R/ Cj) ]等价。考虑到在系统实现中往往采用对数形式的运算,以求降低运算量,并且为求运算值为整数加入了修正因子a1 、a2 。令M ( R/ Cj) = log[ P ( R/ Cj) ] =Σa1 (log[ P( Rm/ Cmj ) ] + a2) 。其中, M 是组成序列的码字的个数。因此寻找最佳路径, 就变成寻找最大M( R/ Cj) , M( R/ Cj) 称为Cj 的分支路径量度,含义为发送Cj 而接收码元为R的似然度。 5.卷积码的viterbi译码是根据接收码字序列寻找编码时通过网格图最佳路径的过程,找到最佳路径即完成了译码过程并可以纠正接收码字中的错误比特。 三、实验代码 #include<> #include "" #define N 7 #include "" #include <> #include<> #define randomize() srand((unsigned)time(NULL)) encode( unsigned int *symbols, /*编码输出*/ unsigned int *data, /*编码输入*/ unsigned int nbytes, /*nbytes=n/16,n为实际输入码字的数目*/ unsigned int startstate /*定义初始化状态*/

Matlab程序代码

Matlab程序代码: clc; clear; N=20; T=0.1 t=0:T:N m=length(t) syms x1 x2 x3 fx=[0;x1+x2^2;x1-x2] gx=[exp(x2);exp(x2);0] hx=x3; R=10*eye(1) Q=[10 0 0;0 1 0;0 0 1] A=[0 1 0;0 0 1;0 0 0] B=[0;0;1] SS=B*inv(R)*B' [p1,p2,lamp,perr,wellposed,P]=aresolv(A,Q,SS) z1=hx z2=[diff(hx,x1) diff(hx,x2) diff(hx,x3)]*fx z3=[diff(z2,x1), diff(z2,x2), diff(z2,x3)]*fx ax=[diff(z3,x1), diff(z3,x2), diff(z3,x3)]*fx bx=[diff(z3,x1), diff(z3,x2), diff(z3,x3)]*gx z=[z1;z2;z3] k=inv(R)*B'*P %diff(z)=A*z+B*v=(A-B*K)*Z %x(0)=[1;0;0] abk=A-B*k x1(1)=1 x2(1)=0 x3(1)=1 z1(1)=x3(1) z2(1)=x1(1)-x2(1) z3(1)=-(x1+x2^2) for i=2:m z1(i)=z1(i-1)+T*(abk(1,1)*z1(i-1)+abk(1,2)*z2(i-1)+abk(1,3)*z3(i-1)) z2(i)=z2(i-1)+T*(abk(2,1)*z1(i-1)+abk(2,2)*z2(i-1)+abk(2,3)*z3(i-1)) z3(i)=z3(i-1)+T*(abk(3,1)*z1(i-1)+abk(3,2)*z2(i-1)+abk(3,3)*z3(i-1))

Viterbi译码器研究目的意义及现状

Viterbi译码器研究目的意义及现状Viterbi译码器研究目的意义及现状 1研究的目的和意义 由于卷积码的优良性能,被广泛的应用于深空通信,卫星通信和2G及3G移动通信中,卷积码有三种译码方法:门限译码,门限译码,概率译码和Viterbi 算法,其中Viterbi算法是一种基于网格图的最大似然译码算法,是卷积码的最佳译码方式,具有效率高、速度快等优点。Viterbi译码充分发挥了卷积码的特点,使译码错误概率达到最小,在码的约束度较小时,它具有译码算法效率高,速度快,译码器也简单的特点。 FPGA(Field,Programmable Gate Array),即现场可编程门阵列,它是在PAL、GAL、CPLD等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。 同时在FPGA的基础上实现Viterbi译码器,迎合了当前FPGA迅猛发展的趋势。把相对成熟的技术应用到某些特定领域如通讯,视频,信息处理等等开发出满足行业需要并能被行业客户接受的产品这方面主要是FPGA技术和专业技术的结合问题,另外还有就是与专业客户的界面问题产品设计还包括专业工具类产品及民用产品,前者重点在性能,后者对价格敏感产品设计以实现产品功能为主要目的,FPGA技术是一个实现手段在这个领域,FPGA因为具备接口,控制,功能IP,内嵌CPU等特点有条件实现一个构造简单,固化程度高,功能全面的系统产品设计将是FPGA技术应用最广大的市场,具有极大的爆发性的需求空间产品设计对技术人员的要求比较高,路途也比较漫长不过现在整个行业正处在组建“首发团队”的状态,只要加入,前途光明产品设计是一种职业发展方向定位,不是简单的爱好就能

213卷积码编码和译码

No.15 (2,1,3)卷积码的编码及译码 摘要: 本报告对于(2,1,3)卷积码原理部分的论述主要参照啜刚教材和课件,编程仿真部分绝对原创,所有的程序都是在Codeblocks 8.02环境下用C语言编写的,编译运行都正常。完成了卷积码的编码程序,译码程序,因为对于短于3组的卷积码,即2 bit或4 bit纠错是没有意义的,所以对正确的短序列直接译码,对长序列纠错后译码,都能得到正确的译码结果。含仿真结果和程序源代码。 如果您不使用Codeblocks运行程序,则可能不支持中文输出显示,但是所有的数码输出都是正确的。

一、 卷积码编码原理 卷积码编码器对输入的数据流每次1bit 或k bit 进行编码,输出n bit 编码符号。但是输出的分支码字的每个码元不仅于此时可输入的k 个嘻嘻有关,业余前m 个连续式可输入的信息有关,因此编码器应包含m 级寄存器以记录这些信息。 通常卷积码表示为 (n,k,m). 编码率 k r n = 当k=1时,卷积码编码器的结构包括一个由m 个串接的寄存器构成的移位寄存器(成为m 级移位寄存器、n 个连接到指定寄存器的模二加法器以及把模二加法器的输出转化为穿行的转换开关。 本报告所讲的(2,1,3)卷积码是最简单的卷积码。就是2n =,1k =,3m =的卷积码。每次输入1 bit 输入信息,经过3级移位寄存器,2个连接到指定寄存器的模二加法器,并把加法器输出转化为串行输出。 编码器如题所示。 二、卷积码编码器程序仿真 C 语言编写的仿真程序。 为了简单起见,这里仅仅提供数组长度30 bit 的仿真程序,当然如果需要可以修改数组大小。为了更精练的实现算法,程序输入模块没有提供非法字符处理过程,如果需要也可以增加相应的功能。 进入程序后,先提示输入数据的长度,请用户输入int (整型数)程序默认用户输入的数据小于30,然后提示输入01数码,读入数码存储与input 数组中,然后运算输出卷积码。经过实验仿真,编码完全正确。 以下是举例: a.课件上的输入101 输出11 10 00 的实验

基于matlab的计算器编程附代码

1.需求分析 本次的实验要求是设计一个计算器,主要功能如下: (1)实现基本数学运算(加减乘除等),而且要能进行混合运算 (2)实现部分函数功能,如求平方根、求倒数等 (3)能实现小数运算 界面与标准计算器界面类似 根据要求以及以前的学习情况,决定使用matlab进行编程。Matlab强大的计算功能以及便捷的GUI设计,可以较为简便的实现所要求的功能。按照要求,数据输入和输出支持小数点,支持四则混合运算,决定使用如下几个数据进行分析:(1+3)*5 Sqrt(4) 1/2 Sin4 用以检验是否可以进行加减乘除四则运算、平方根、倒数、正弦的运算。 2.程序设计 M atlab的程序设计较为简便,用GUI设计出一个计算器的模型,然后系统会自动生成一个框架,在框架中,写入每一个按键对应的程序就可以实现功能。 3.调式分析 编程的过程中遇到的问题不是很多,基本就是找要实现各个功能的子程序,通过上网和去图书馆,加上自己的编写,终于实现了实验要求的功能。但是有一点很重要,matlab不支持中文,所以从路径到文件名必须是全英文的,不然就无法识别。此外,给每个按键命名也是很重要的,不然在生成的程序框架里面,就无法识别各个按键的作用,编写程序的时候也就无法做到一一对应。 4.使用说明 程序的使用比较简单,由于是可视化界面,直接打开matlab,然后建立一个GUI 工程,再打开生成的fig文件,就是一个计算器的界面,直接按照市面上卖的计算器的

方法,按键使用即可。 5.测试结果 计算结果为20 4sqrt=2 Sin4结果为 1/2=0.5 经过计算,这些结果均与实际结果相吻合,计算器的功能实现的较为完好。 6.心得体会 本次试验由于不限制语言,于是计算功能强大,操作简便的matlab变成了首选,matlab的GUI设计,操作是较为简单的,首先建立一个GUI工程,然后用可视化界面,

基于MATLAB的潮流计算源程序代码(优.选)

%*************************电力系统直角坐标系下的牛顿拉夫逊法潮流计算********** clear clc load E:\data\IEEE014_Node.txt Node=IEEE014_Node; weishu=size(Node); nnum=weishu(1,1); %节点总数 load E:\data\IEEE014_Branch.txt branch=IEEE014_Branch; bwei=size(branch); bnum=bwei(1,1); %支路总数 Y=(zeros(nnum)); Sj=100; %********************************节点导纳矩阵******************************* for m=1:bnum; s=branch(m,1); %首节点 e=branch(m,2); %末节点 R=branch(m,3); %支路电阻 X=branch(m,4); %支路电抗 B=branch(m,5); %支路对地电纳 k=branch(m,6); if k==0 %无变压器支路情形 Y(s,e)=-1/(R+j*X); %互导纳 Y(e,s)=Y(s,e); end if k~=0 %有变压器支路情形 Y(s,e)=-(1/((R+j*X)*k)); Y(e,s)=Y(s,e); Y(s,s)=-(1-k)/((R+j*X)*k^2); Y(e,e)=-(k-1)/((R+j*X)*k); %对地导纳 end Y(s,s)=Y(s,s)-j*B/2; Y(e,e)=Y(e,e)-j*B/2; %自导纳的计算情形 end for t=1:nnum; Y(t,t)=-sum(Y(t,:))+Node(t,12)+j*Node(t,13); %求支路自导纳 end G=real(Y); %电导 B=imag(Y); %电纳 %******************节点分类************************************* * pq=0; pv=0; blancenode=0; pqnode=zeros(1,nnum); pvnode=zeros(1,nnum); for m=1:nnum; if Node(m,2)==3 blancenode=m; %平衡节点编号 else if Node(m,2)==0 pq=pq+1; pqnode(1,pq)=m; %PQ 节点编号 else if Node(m,2)==2 pv=pv+1; pvnode(1,pv)=m; %PV 节点编号 end end end end %*****************************设置电压初值********************************** Uoriginal=zeros(1,nnum); %对各节点电压矩阵初始化 for n=1:nnum Uoriginal(1,n)=Node(n,9); %对各点电压赋初值 if Node(n,9)==0;

Viterbi译码程序代码

译码主要部分 #include"stdafx.h" //#define DEBUG void deci2bin(int d, int size, int *b); int bin2deci(int *b, int size); int nxt_stat(int current_state, int input, int *memory_contents); void init_quantizer(void); void init_adaptive_quant(float es_ovr_n0); int soft_quant(float channel_symbol); int soft_metric(int data, int guess); int quantizer_table[256]; void sdvd(int g[2][K], float es_ovr_n0, long channel_length, float*channel_output_vector, int *decoder_output_matrix) { int i, j, l, ll; //循环控制变量 long t; //时间 int memory_contents[K]; //记录输入内容 int input[TWOTOTHEM][TWOTOTHEM]; //对当前状态以及下一个状态映射 int output[TWOTOTHEM][2]; //卷积码编码输出矩阵 int nextstate[TWOTOTHEM][2]; //下一个状态矩阵 int accum_err_metric[TWOTOTHEM][2]; //误差累计矩阵 int state_history[TWOTOTHEM][K * 5 + 1]; //历史状态表 int state_sequence[K * 5 + 1]; //状态序列 int *channel_output_matrix; //信道输出序列 int binary_output[2]; int branch_output[2]; //0或者1的输出分支 int m, n, number_of_states, depth_of_trellis, step, branch_metric, sh_ptr, sh_col, x, xx, h, hh, next_state, last_stop; n = 2; //1/2为卷积码传输数据的码率 m = K - 1;//寄存器个数 number_of_states = (int)pow(2.0, m);//状态个数number of states = 2^(K - 1) = 2^m depth_of_trellis = K * 5; for (i = 0; i < number_of_states; i++)

动态规划:卷积码的Viterbi译码算法

动态规划:卷积码的Viterbi译码算法 学院:网研院?姓名:xxx 学号:xxx一、动态规划原理 动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解,每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。 动态规划程序设计是对解最优化问题的一种途径、一种方法,而不是一种特殊算法。不象搜索或数值计算那样,具有一个标准的数学表达式和明确清晰的解题方法。动态规划程序设计往往是针对一种最优化问题,由于各种问题的性质不同,确定最优解的条件也互不相同,因而动态规划的设计方法对不同的问题,有各具特色的解题方法,而不存在一种万能的动态规划算法,可以解决各类最优化问题。 二、卷积码的Viterbi译码算法简介 在介绍维特比译码算法之前,首先了解一下卷积码编码,它常常与维特比译码结合使用。(2,1,3)卷积码编码器是最常见的卷积码编码器,在本次实验中也使用了(2,1,3)卷积码编码器,下面介绍它的原理。 (2,1,3)卷积码是把信源输出的信息序列,以1个码元为一段,通过编码器输出长为2的一段码段。该码段的值不仅与当前输入码元有关,而且也与其之前的2个输入码元有关。如下图所示,输出out1是输入、第一个编码器存储的值和第二个编码器存储的值逻辑加操作的结果,输出out2是输入和第二个编码器存储的值逻辑加操作的结果。 (2,1,3)卷积码编码器

MATLAB实现卷积码编译码-

本科生毕业论文(设计) 题目:MATLAB实现卷积码编译码 专业代码: 作者姓名: 学号: 单位: 指导教师: 年月日

目录 前言----------------------------------------------------- 1 1. 纠错码基本理论---------------------------------------- 2 1.1纠错码基本理论 ----------------------------------------------- 2 1.1.1纠错码概念 ------------------------------------------------- 2 1.1.2基本原理和性能参数 ----------------------------------------- 2 1.2几种常用的纠错码 --------------------------------------------- 6 2. 卷积码的基本理论-------------------------------------- 8 2.1卷积码介绍 --------------------------------------------------- 8 2.1.1卷积码的差错控制原理----------------------------------- 8 2.2卷积码编码原理 ---------------------------------------------- 10 2.2.1卷积码解析表示法-------------------------------------- 10 2.2.2卷积码图形表示法-------------------------------------- 11 2.3卷积码译码原理---------------------------------------------- 15 2.3.1卷积码三种译码方式------------------------------------ 15 2.3.2V ITERBI译码原理---------------------------------------- 16 3. 卷积码编译码及MATLAB仿真---------------------------- 18 3.1M ATLAB概述-------------------------------------------------- 18 3.1.1M ATLAB的特点------------------------------------------ 19 3.1.2M ATLAB工具箱和内容------------------------------------ 19 3.2卷积码编码及仿真 -------------------------------------------- 20 3.2.1编码程序 ---------------------------------------------- 20 3.3信道传输过程仿真-------------------------------------------- 21 3.4维特比译码程序及仿真 ---------------------------------------- 22 3.4.1维特比译码算法解析------------------------------------ 23 3.4.2V ITERBI译码程序--------------------------------------- 25 3.4.3 VITERBI译码MATLAB仿真----------------------------------- 28 3.4.4信噪比对卷积码译码性能的影响 -------------------------- 28

基本粒子群算法的matlab源程序

主函数源程序(main.m) %------基本粒子群优化算法(Particle Swarm Optimization)----------- %------名称:基本粒子群优化算法(PSO) %------作用:求解优化问题 %------说明:全局性,并行性,高效的群体智能算法 %------初始格式化-------------------------------------------------- clear all; clc; format long; %------给定初始化条件---------------------------------------------- c1=1.4962; %学习因子1 c2=1.4962; %学习因子2 w=0.7298; %惯性权重 MaxDT=1000; %最大迭代次数 D=10; %搜索空间维数(未知数个数) N=40; %初始化群体个体数目 eps=10^(-6); %设置精度(在已知最小值时候用) %------初始化种群的个体(可以在这里限定位置和速度的范围)------------ for i=1:N for j=1:D x(i,j)=randn; %随机初始化位置 v(i,j)=randn; %随机初始化速度 end end %------先计算各个粒子的适应度,并初始化Pi和Pg---------------------- for i=1:N p(i)=fitness(x(i,:),D); y(i,:)=x(i,:); end pg=x(1,:); %Pg为全局最优 for i=2:N if fitness(x(i,:),D) pg=x(i,:); end end %------进入主要循环,按照公式依次迭代,直到满足精度要求------------ for t=1:MaxDT for i=1:N v(i,:)=w*v(i,:)+c1*rand*(y(i,:)-x(i,:))+c2*rand*(pg-x(i,:)); x(i,:)=x(i,:)+v(i,:); if fitness(x(i,:),D) p(i)=fitness(x(i,:),D); y(i,:)=x(i,:);

相关文档