🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

2回答

1718閲覧

通信路容量を導出するプログラム/ランダムな値が収束しない

kaneko_

総合スコア10

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2020/11/23 13:26

前提・実現したいこと:8PSKでの通信路容量の導出

Visual Studio 2019 でAWGM環境下で各変調ごとの通信路容量を導出するプログラムをC言語で書いています。BPSK,QPSKでの通信路容量は完璧に導出できたのですが、8PSKでの通信路容量のグラフの値がどれだけ多くの試行回数を重ねても収束しません。
BPSK,QPSKでは完璧にうまくいっているので、プログラムの内容自体はあっていると思うのですが、、、(つまり、私はこの問題は乱数が正規分布に収束していないという問題だと認識しています。)
どなたか助言いただける方がいたら、よろしくお願いします。
なお、エラーメッセージは一つも出ていません。
以下が、作りたいグラフです。
イメージ説明
以下、出力時のグラフです。
イメージ説明

C

1#include<stdio.h> 2#include<stdlib.h> 3#include<math.h> 4#include<time.h> 5#include<complex.h> 6#include"MT.h" 7#pragma warning(disable : 4996) 8#define modulation_level 8//BPSK:2 QPSK:4 8PSK:8 16QAM:16 変調多値数 9#define N 10000000 //受信信号の要素数 10#define EbN0db_max 20//プロットするEs/N0[db]の最大値[db] 11#define EbN0db_min -10 //プロットするEs/N0[db]の最小値[db] 12#define EbN0db_plot 31 //プロットする点数 13#define Ns 1//1シンボル当たりのサンプル数 14#define PI 3.1415926 15#define amplitude 1 //雑音と信号の比が重要なので、振幅は1で固定 16 17int genpulse() 18{ 19 return genrand_int32() & 1; 20} 21 22int generate_constellation_diagram()//コンスタレーション上のプロットを表す数値を出力 23{ 24 int pulse_number=0; 25 26 for (int i = 0; i < log2(modulation_level); i++) 27 { 28 int pulse = genpulse(); 29 pulse_number+=pow(2, i)* pulse; 30 } 31 32 return pulse_number; 33} 34 35_Dcomplex generate_noise(long double N0)//N0を引数にして雑音(noise_I+j*noise_Q)を返す関数 36{ 37 long double sigma = pow((long double)N0 / 2, 0.5); 38 long double u1 = genrand_real3(); //(0,1)乱数を作成 39 long double u2 = genrand_real3(); 40 long double noise_I = sigma* pow(-2 * log(u1), 0.5)* cos(2 * PI * u2); 41 long double noise_Q = sigma* pow(-2 * log(u1), 0.5)* sin(2 * PI * u2); 42 _Dcomplex noise = _Cbuild(noise_I, noise_Q); 43 44 return noise; 45} 46 47long double calc_entropy_function(long double N0,int constellation_number) 48{ 49 _Dcomplex constellation_point[modulation_level]; 50 if (modulation_level == 2) 51 { 52 constellation_point[0] = _Cbuild(amplitude, 0); 53 constellation_point[1] = _Cbuild(-amplitude, 0); 54 } 55 56 else if (modulation_level == 4) 57 { 58 constellation_point[0] = _Cbuild(pow(2, -1 * 0.5) * amplitude, pow(2, -1 * 0.5) * amplitude); 59 constellation_point[1] = _Cbuild(pow(2, -1 * 0.5) * amplitude, -pow(2, -1 * 0.5) * amplitude); 60 constellation_point[2] = _Cbuild(-pow(2, -1 * 0.5) * amplitude, pow(2, -1 * 0.5) * amplitude); 61 constellation_point[3] = _Cbuild(-pow(2, -1 * 0.5) * amplitude, -pow(2, -1 * 0.5) * amplitude); 62 } 63 64 else if (modulation_level == 8) 65 { 66 constellation_point[0] = _Cbuild(amplitude ,0); 67 constellation_point[1] = _Cbuild(amplitude/sqrt(2), amplitude / sqrt(2)); 68 constellation_point[2] = _Cbuild(0,amplitude); 69 constellation_point[3] = _Cbuild(amplitude / sqrt(2), -1 * amplitude / sqrt(2)); 70 constellation_point[4] = _Cbuild(0,-1*amplitude); 71 constellation_point[5] = _Cbuild( -1*amplitude / sqrt(2), -1*amplitude / sqrt(2)); 72 constellation_point[6] = _Cbuild(0, -1*amplitude); 73 constellation_point[7] = _Cbuild(amplitude/sqrt(2),-1*amplitude/sqrt(2)); 74 } 75 _Dcomplex noise=generate_noise(N0); 76 _Dcomplex constellation_noise = _Cbuild(creal(noise)+creal(constellation_point[constellation_number]), cimag(noise)+cimag(constellation_point[constellation_number]));//得られる点のコンスタレーション上の座標 77 long double tmp2=0; 78 for (int i = 0; i < modulation_level; i++)//分子の合計をtmp2に返す 79 { 80 if (i == constellation_number) 81 { 82 long double tmp = 0; 83 tmp = cabs(noise); 84 tmp2 += exp(-1 * tmp * tmp / N0); 85 86 } 87 88 else 89 { 90 long double tmp = 0; 91 tmp = cabs(_Cbuild(creal(constellation_noise) - creal(constellation_point[i]), cimag(constellation_noise) - cimag(constellation_point[i]))); 92 tmp2 += exp(-1 * tmp * tmp / N0); 93 } 94 95 } 96 97 long double tmp=0; 98 99 tmp = cabs(noise); 100 101 return (log2(tmp2)-log2( exp(-1 * tmp * tmp / N0))); 102} 103 104int main() 105{ 106 init_genrand((unsigned)time(NULL)); 107 long double channel_capacity=0;//C 108 long double entropy_function=0;//H(x|y) 109 int constellation_number; 110 111 FILE* fp; 112 113 if ((fp = fopen("d.txt","w")) == NULL) 114 { 115 printf("cannot open!"); 116 exit(1); 117 } 118 119 for (int i = 0; i < EbN0db_plot; i++) 120 { 121 122 long double EsN0db =i*((long double)EbN0db_max - EbN0db_min) / ((long double)EbN0db_plot -1)+ EbN0db_min;//-10~20まで31点プロット 123 124 long double N0 = pow(10, -1 * EsN0db / 10); 125 126 constellation_number=generate_constellation_diagram();//コンスタレーション上のプロットを表す整数を出力 127 128 entropy_function = 0;//(nI+j*nQ)の整数とN0を引数にしてH(x|y)を求める関数 129 for (int j = 0; j < N; j++) 130 { 131 entropy_function+= calc_entropy_function(N0, constellation_number); 132 } 133 entropy_function /= N; 134 135 channel_capacity = log2(modulation_level) - entropy_function;//チャネル容量 136 137 fprintf(fp, "%f,%lg\n", EsN0db, channel_capacity); 138 139 printf("finish Es/N0=%f\n", EsN0db); 140 } 141 142 fclose(fp); 143 144 return 0; 145 146}

試したこと

・乱数生成が一様分布でない
→乱数生成の関数をrand関数からメルセンヌツイスタへ変更
・計算結果がdouble型に収まっていない
→すべてのdouble型をlong double型に変更(complex.hに問題があるのかも?)
・測定回数が十分でない
→最大1000000000点で測定(終了まで15時間かかりました、、、)

補足情報(FW/ツールのバージョンなど)

実行環境:win10
visual studio 2019

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kaneko_

2020/12/01 06:07

ありがとうございます。もしサイズを増やしたかったら別の開発環境でコーディングしなきゃいけないですかね、、、
guest

回答2

0

c

1constellation_point[3] 2constellation_point[4]

が間違っていました????
初歩的な間違いで申し訳ございませんでした????

投稿2020/12/01 10:06

kaneko_

総合スコア10

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

calc_entropy_functionの8PSKのときの分岐で

C

1 else if (modulation_level == 8) 2 { 3 constellation_point[0] = _Cbuild(amplitude ,0); 4 constellation_point[1] = _Cbuild(amplitude/sqrt(2), amplitude / sqrt(2)); 5 constellation_point[2] = _Cbuild(0,amplitude); 6 constellation_point[3] = _Cbuild(amplitude / sqrt(2), -1 * amplitude / sqrt(2)); 7 constellation_point[4] = _Cbuild(0,-1*amplitude); 8 constellation_point[5] = _Cbuild( -1*amplitude / sqrt(2), -1*amplitude / sqrt(2)); 9 constellation_point[6] = _Cbuild(0, -1*amplitude); 10 constellation_point[7] = _Cbuild(amplitude/sqrt(2),-1*amplitude/sqrt(2)); 11 }

となってますが、constellation_point[4]がおかしいような気がします。

C

1constellation_point[4] = _Cbuild(-1*amplitude, 0);

じゃないですか?

投稿2020/11/24 00:55

crhg

総合スコア1177

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kaneko_

2020/12/01 06:06

本当ですね、間違っていました???? ごめんなさい ですが、指摘箇所を変更してもやはり変わらず収束しません、、
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問