状態遷移のプログラムの課題

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Black Bird

状態遷移のプログラムの課題

#1

投稿記事 by Black Bird » 10年前

プログラミング初心者で困ってます。課題が出たのですがどうしていいか分かりません。

問題
0を発生する状態Aと1を発生する状態Bがあり、状態遷移確率が
0→0;90% 0→1;10%
1→0;60% 1→1;40% 
である。これを1000回繰り返して発生した状態をXとし、異なる乱数seedを3000回用いて、
状態Xを発生させる。この時、状態XがAである確率とBである確率を求めなさい。

どうすればいいのか教えてください。お願いします。

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: 状態遷移のプログラムの課題

#2

投稿記事 by beatle » 10年前

どの程度プログラミングは初心者ですか?
Hello worldプログラムは書けますか?
rand()関数を使えば乱数を求められますが、使い方分かりますか?

Black Bird

Re: 状態遷移のプログラムの課題

#3

投稿記事 by Black Bird » 10年前

ループ文、if文、一次元配列はとりあえず大丈夫です。
多次元配列、構造体についてはあまり理解できていません。
Hello worldのプログラムは大丈夫です。
rand()関数、srand()関数についてはネットで調べたのである程度なら。

box
記事: 2002
登録日時: 13年前

Re: 状態遷移のプログラムの課題

#4

投稿記事 by box » 10年前

Black Bird さんが書きました: である。これを1000回繰り返して発生した状態をXとし、異なる乱数seedを3000回用いて、
状態Xを発生させる。この時、状態XがAである確率とBである確率を求めなさい。
プログラムを書く前に、上記の1000回とか3000回とかを
簡単のために10回とか30回とかにしたとして、
どういう操作をするのか書き下すことはできますでしょうか。

私には、1000回と3000回との関連性がよくわかりません。
たぶん、私に読解力が欠けているためだと思います。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

non
記事: 1097
登録日時: 13年前

Re: 状態遷移のプログラムの課題

#5

投稿記事 by non » 10年前

Black Bird さんが書きました:問題
0を発生する状態Aと1を発生する状態Bがあり、状態遷移確率が
0→0;90% 0→1;10%
1→0;60% 1→1;40% 
である。これを1000回繰り返して発生した状態をXとし、異なる乱数seedを3000回用いて、
状態Xを発生させる。この時、状態XがAである確率とBである確率を求めなさい。
私も問題の意味が、わからないのですが、私なりに解読してみました。

まず、乱数で0か1か発生させる。(確率1/2)
次を3000回行う
0だった場合は90%の割合で0を発生させ、10%の割合で1を発生させる。
1だった場合は60%の割合で0を発生させ、40%の割合で1を発生させる。
0になった回数と、1になった回数をカウントする。
最初に戻り、1000回繰り返し行う。

数学的に見ると、
最初0が出る確率は0.5、1が出る確率も0.5
0だったとき再び0になるのは0.9なので、0.45、
1だったとき0になるのは、0.6なので、0.3
従って、最終的に0になるのは、0.45+0.3=0.75
かな?
non

non
記事: 1097
登録日時: 13年前

Re: 状態遷移のプログラムの課題

#6

投稿記事 by non » 10年前

送信してから思ったのですが、状態遷移を続けて3000回行った後の最終的な値が0か1かを
求めるのかも。それを1000回行う。
たぶん、こっちの方が課題として良いと思う。
non

アバター
usao
記事: 1887
登録日時: 11年前

Re: 状態遷移のプログラムの課題

#7

投稿記事 by usao » 10年前

うーん,
「0を発生する」「1を発生する」の意味が不明ですね.

単に

「状態が{A,B}二通りあって,状態遷移確率が,
 A→Aが90%, A→Bが10%
 B→Aが60%, B→Bが40%
 であり,(初期状態がどっちなのかわからないけど,例えばAから始めるとして)
 1000回の状態遷移機会を与えてみて,両状態にあった回数をカウントしてみろ」
で,これを,乱数のseedナンバーを変えて3000回ほど試行してみて,
その結果を集計して,状態がAであった率を求めてみろ

ってことなんじゃないでしょうか??

non
記事: 1097
登録日時: 13年前

Re: 状態遷移のプログラムの課題

#8

投稿記事 by non » 10年前

私と、回数が逆ね。もう一度、課題を読むとusaoさんの可能性が高い。
non

アバター
usao
記事: 1887
登録日時: 11年前

Re: 状態遷移のプログラムの課題

#9

投稿記事 by usao » 10年前

…と,いうことで とりあえず
・問題の正しい解釈
・どこまではできていて(現状コードとか)
・何がわからないのか / 何に困っているのか
・(さらに,課題であれば期限はいつごろ?とか)
あたりを具体的に示してもらえないと役に立つ回答は得られないと思います.

Black Bird

Re: 状態遷移のプログラムの課題

#10

投稿記事 by Black Bird » 10年前

説明がうまくできていなくてすいませんでした。


1、初期状態を乱数を使って、0か1を決定する。

2、初期状態を使って、状態遷移確率に従って1000回遷移させる。

3、1000回遷移させた結果の状態を確認する。(0か1どちらになっているか)

4、1~3を3000回繰り返す。

5、1000回遷移させた結果が3000個用意されたので、そこから0と1の数を数える。

6、0と1の個数をそれぞれ3000で割って、確率とする。

という方針でおねがいします。期限は来週の水曜日までです。

アバター
usao
記事: 1887
登録日時: 11年前

Re: 状態遷移のプログラムの課題

#11

投稿記事 by usao » 10年前

なるほど,1000回の遷移を経た結果の状態を集計すればいいわけですね.

>・どこまではできていて(現状コードとか)
>・何がわからないのか / 何に困っているのか
については,どんな状態でしょうか.

>1、初期状態を乱数を使って、0か1を決定する。

>6、0と1の個数をそれぞれ3000で割って、確率とする。
のうち,どの程度できていますか?

YuO
記事: 947
登録日時: 13年前
住所: 東京都世田谷区

Re: 状態遷移のプログラムの課題

#12

投稿記事 by YuO » 10年前

> 初期状態を乱数を使って、0か1を決定する。
ここで,どの確率で0,1になるのですか。
結果は変わらないのですが,プログラムを組む上で必要になります。
► スポイラーを表示

Black Bird

Re: 状態遷移のプログラムの課題

#13

投稿記事 by Black Bird » 10年前

コード:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int main(void){
int a,b,i,j,x;

srand((unsigned)time(NULL));

for(i=0;i<3000;i++){
   x=rand()%2; 
for(j=0;j<1000;j++){

      if(x==0 &&   )     {x=0;}

else if(x==0 &&    )     {x=1;}

else if(x==1 &&    )     {x=0;}

else                     {x=1;}


}
}
/* aを0の個数、bを1の個数として求めたい */



/* a,bを求めて3000で割って出力する。*/  

printf("状態Aである確率は%f\n 状態Bである確率は%f\n",a/3000,b/3000);

return 0;}

かなり穴あきなものになってますし、おかしな点があれば教えてください。

状態遷移をどのように行えば良いかが分かりません。
また0と1の個数をどのようにして求めるのかという点で困ってます。

問題中に初期状態についての言及がないためなんとも言えませんが、
結果に変動がないのであれば任意で構わないと思います。

Black Bird

Re: 状態遷移のプログラムの課題

#14

投稿記事 by Black Bird » 10年前

コードはCです。
ちゃんと使いこなせてなくて変な風になってすいません。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 状態遷移のプログラムの課題

#15

投稿記事 by みけCAT » 10年前

「a/3000」「b/3000」だと、整数の割り算になって切り捨てられます。
「a/3000.0」「b/3000.0」としてください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

box
記事: 2002
登録日時: 13年前

Re: 状態遷移のプログラムの課題

#16

投稿記事 by box » 10年前

う~ん。
どこのサイトを使って、あるいはどの本を読んで勉強したら、
そういった字下げのコードを書くようになるのか、大いに興味があります。
個人的には、読みにくくて仕方がありません。

もし興味がおありでしたら、他の質問者さんへの回答として
私が示した字下げの方法をごらんになってみてください。
なお、それはあくまで私個人の流儀(だから、他の人の流儀とは異なる場合あり)であり、
かつ、私の流儀を押しつけるつもりはありません。念のため。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
usao
記事: 1887
登録日時: 11年前

Re: 状態遷移のプログラムの課題

#17

投稿記事 by usao » 10年前

「状態遷移」とか仰々しく言っているけど,要するに,

>A→Aが90%, A→Bが10%
とかいうのは,
「現在状態がAであるとき,(出る目の範囲が1~10の)10面さいころを振って,
 1~9だったらAのまま,10が出たら現在状態をBにする」
というだけのことでしょう.
(あなたは既に2面さいころを作れているから,10面さいころを作るのは問題ないはず)
状態Bからの遷移も同様です.

とりあえず最初は「3000回やって云々」は忘れて,

・1000回さいころを振る
・各さいころで出た値によって,次の状態がAかBか決まる.そのルール(確率)は現在の状態による.
・1000回のさいころを振り終えた時点の状態はどっちになったか?

だけを実装してみてはいかがでしょうか.
仮に,いきなりコードで書くのが難しい ということであれば,↓のように日本語で書けばいいです.
日本語で書けたら 後はそれをCでの記述に変えればよいです.

コード:

現在状態=状態A;  //初期状態.※ここでは仮に状態Aとする.ランダムに決めるのならそうする.
//1000回の状態遷移機会
for( int i=0; i<1000; i++ )
{
    //さいころを振る
    今回のさいころの目 = 10面さいころをふった結果;

    //現在状態と,さいころの出た目によって,状態を変える
    if( 現在状態==状態A && 今回のさいころの目==10 )
    {   //状態Aからは10%の確率で状態Bに遷移する
       現在状態=状態B;
    }
    else if( ... )
    {
        ....
    }
}
//1000回終えた後での現在状態を表示
if( 現在状態==状態A )
{
    printf( "Aだった" );
}
else
{
    printf( "Bだった" );
}

アバター
usao
記事: 1887
登録日時: 11年前

Re: 状態遷移のプログラムの課題

#18

投稿記事 by usao » 10年前

↑ができたら,あとはこれを3000回繰り返すようにし,その繰り返しの中で
各「さいころ1000連発処理」の結果状態が
・Aだった回数
・Bだった回数
をそれぞれカウントするようにすればよいでしょう.
(実際は,総数が3000だとわかっているのだから,一方だけカウントすればいいけど)

Black Bird

Re: 状態遷移のプログラムの課題

#19

投稿記事 by Black Bird » 10年前

見にくいコードですいません。
コードを書いて人に見てもらう機会なかったため、
普段、字下げなどを気にして書いていませんでした。

誰が見てもわかりやすいコードを書かなければいけませんね。
コードを書く際には字下げにも気をつけるようにします。
ご指摘ありがとうございました。

Black Bird

Re: 状態遷移のプログラムの課題

#20

投稿記事 by Black Bird » 10年前

コード:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int main(void){
    
    int x,y,i;
    srand((unsigned)time(NULL));
    x=rand()%2;

    for (i=0; i<1000; i++){

        y=rand()%10;

        if(x==0 && 0<=y<=8)
        {
            x=0;   
        }

        else if(x==0 && y==9)
        {
            x=1;
        }

        else if(x==1&& 0<=y<=5)
        {
            x=0;
        }

        else
        {
            x=1;
        }

    }

    if(x==0)
    {
        printf("1000回目は状態Aです。\n");
    }
    
    else
    {
        printf("1000回目は状態Bです。\n");
    }

    return 0;}
とりあえずプログラム作成しましたが、これでは”1000回目は状態Aです。”しか現れず、
状態Bになることがありません。どこを直せばいいでしょうか。

たいちう
記事: 418
登録日時: 13年前

Re: 状態遷移のプログラムの課題

#21

投稿記事 by たいちう » 10年前

他にもまずい所は多そうですね。

× : if(x==0 && 0<=y<=8)
○ : if(x==0 && 0<=y && y<=8)

Black Bird

Re: 状態遷移のプログラムの課題

#22

投稿記事 by Black Bird » 10年前

たいちうさん、ありがとうございます。修正しました。

何度か実行しているうちに状態Bにもなりました。
どうも状態Bになる確率が結構低そうですね。

たいちう
記事: 418
登録日時: 13年前

Re: 状態遷移のプログラムの課題

#23

投稿記事 by たいちう » 10年前

実行してみた

結果が予想と違う

掲示板で質問

ではなく、


途中経過が予想通りか確認する

などのデバッグの工夫をしましょう。
上達したいならば、(筋道を立てて)できる限りの事をしてから質問です。
欲を言うと、できる限りの事+αをしてからですね。

どんな事情があるか知らないので、+αまで必須とは思いませんけど、
上達したいならば、地道な努力と閃きの両方が必要だということを、
忘れないでください。

# 半分は自分に言っているみたいなほろ酔いのたいちうでした。

Black Bird

Re: 状態遷移のプログラムの課題

#24

投稿記事 by Black Bird » 10年前

[code=c#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int main(void){

int a=0,b,x,y,i,j;
srand((unsigned)time(NULL));
x=rand()%2;

for(j=0;j<3000;j++){
for (i=0; i<1000; i++){

y=rand()%10;

if(x==0 && 0<=y && y<=8)
{
x=0;
}

else if(x==0 && y==9)
{
x=1;
}

else if(x==1&& 0<=y && y<=5)
{
x=0;
}

else
{
x=1;
}

}

if(x==0)
{
a=a+1;
}

}

b=3000-a;

printf("状態A=%f\n状態B=%f\n",a/3000.0,b/3000.0);

return 0;}][/code]

usaoさんのアドバイスに従って作ってみました。おそらく大丈夫だと思うのですが、
どこか問題点があればご指摘ください。

Black Bird

Re: 状態遷移のプログラムの課題

#25

投稿記事 by Black Bird » 10年前

そうですね。これから多くのプログラムを組まなければならなくなるので、
上達するためにもしっかりとやっていきたいと思います。

たいちうさん、ありがとうございました。

超絶右留斗羅天才プログラマー
記事: 44
登録日時: 10年前

Re: 状態遷移のプログラムの課題

#26

投稿記事 by 超絶右留斗羅天才プログラマー » 10年前

以下が正解になります。
どんな質問にも答えますので、分からない点があれば教えてください。
課題、頑張ってくださいねヽ(*´∀`)ノ

コード:

#include <stdio.h>
#include <stdlib.h>
#include<time.h>
void main(void){
	// 最終状態A,Bを数えます
	int A=0,B=0;
	// seedを3000回用いります
	for( int i = 0; i < 3000; i++){
		srand(i);	// ←seedが3000回変化します
		int n=rand()%2;	// 状態Aか状態Bをランダムに設定します
		// 1000回状態を変化させてみます
		for( int j=0; j<1000; j++ ){
			int r=rand()%100;
			// 0→1になる確率は10%
			if(n==0){if(r<10){n=1;}}
			// 1→0になる確率は60%
			else if(n==1){if(r<60){n=0;}}
		}
		// 1000回繰り返したあと、
        // 状態Aか状態Bかを調べて加算します。
		if(n==0)A++;
		else B++;
	}
	printf("状態XがAである確率は%.2f%です\n",A/3000.0f*100.0f);
	printf("状態XがBである確率は%.2f%です\n",B/3000.0f*100.0f);
	// 何か入力があると終了します
	rewind(stdin);
	getchar();
}
ただの超絶右留斗羅天才プログラマーです。同人ゲーム制作進捗度:7%

アバター
usao
記事: 1887
登録日時: 11年前

Re: 状態遷移のプログラムの課題

#27

投稿記事 by usao » 10年前

>どこか問題点があればご指摘ください。
問題文を見た感じだと 超絶右留斗羅天才プログラマーさんが示したコードにあるように,
「3000回のループの中でsrand()を毎回つかう」ことが求められているようにも見えますね.
最初の投稿時の問題文が出された課題文そのものなのだとすれば,
直しておいてもよいのではないでしょうか.
もしコードを提出するのであれば,わたしだったら

コード:

for( int j=0; j<3000; j+++ )
{
    //意義はいまいち不明であるが,問題文を読むかぎりだと
    //3000回の試行では,異なるseed numberを用いることが指定されているようなので,
    //ここでsrand()する.
    srand( j );
    
    ...
とか,コメントを添えてしまうかもしれませんw

その他の点では,コードをざっと眺めた感じだと,特に問題無いように見えます.
(本当は,理論値と同程度の結果が出てくるかどうか見ればいいんだろうけど,
 理屈の上でどの程度の値が出てくることになるのかが,私にはわからんですw)

>どうも状態Bになる確率が結構低そうですね。
状態遷移確率から見て,Bにはかなりなりにくいと思います.
一度状態AになったらなかなかBに変わらないのに,Bになっても結構な確率ですぐAに戻ってしまう ので.

Black Bird

Re: 状態遷移のプログラムの課題

#28

投稿記事 by Black Bird » 10年前

みなさん、ありがとうございました( ´ ▽ ` )
おかげで無事に完成しました。
また困ったことがあれば質問させてもらいます(^-^)

Black Bird

Re: 状態遷移のプログラムの課題

#29

投稿記事 by Black Bird » 10年前

みなさん、ありがとうございました( ´ ▽ ` )
おかげで無事に完成しました。
また困ったことがあれば質問させてもらいます(^-^)

閉鎖

“C言語何でも質問掲示板” へ戻る