3

以下のコードは、異なるシードを使用して乱数を 10 回生成し、それらを平均してより滑らかなグラフを取得する必要があると言われています。私は Matlab の使用経験があまりないため、ドキュメントを読んでもこれらのシードがどのように機能するかについてはよくわかりません。

% Create an array
S = 0:20;
CW = 0:5:100;
S(1) = 0;
CW(1) = 0;

counter = 2;  % Counter for the nuber of S 
N = 20;  % Number of nodes

% Collect data for each increment of 5 up to 100 for CW values
for i = 5:5:100

    T = 10000 / i;  % Total number of cycles

    % Create array of next transmission times for N nodes
    transmission_time = floor(i * rng(1, N)); 
    total_success = 0;

    % Loop for T cycles
    for t = 1:T

        % For 0 to the number of contention windows
        for pos = 0:i-1

           % Count the number of nodes that have the current CW
            count = 0;
            for node = 1:N
               if transmission_time(node) == pos
                   count = count + 1;
               end
            end

            % If there is more than 1, then a collision occurs
            collision = false;
            if count > 1
                collision = true;
            % If there is exactly 1, then there is a success
            elseif count == 1
                total_success = total_success + 1;
            end 

            % If there is a collision, reassign new transmissions times
            if collision == true
                for node = 1:N
                    if node == pos
                        transmission_time(node) = floor(i * rand(1));
                    end
                end
            end
        end
    end

    % Display the ratio of successes
    S(counter) = total_success / (T * i);
    counter = counter + 1;
end

% Plot the graph for Success vs CW
plot(CW, S, 'o-');
xlabel('Contention Window, CW');
ylabel('Throughput, S');
4

4 に答える 4

1

matlab docから

ジェネレーターを頻繁に再シードしても、出力の統計的特性は改善されず、出力が実際の意味でよりランダムになるわけではありません。再シードは、MATLAB を再起動するとき、または乱数を含む大規模な計算を実行する前に役立つ場合があります。ただし、乱数の統計的特性が悪影響を受ける可能性があるため、セッション内でジェネレーターを頻繁に再シードすることはお勧めできません。


で異なるシードを使用する必要はありませんrand。実行するたびに同じ数列が生成されるわけではありません。例えば

R = zeros(1e5,1);
for ii = 1:1e5
    R(ii) = rand;
end
Rsorted = sort(R);
dRsorted = diff(Rsorted);
find(dRsorted == 0)

が返され、空の行列: rand100,000 回の連続呼び出しで同一の乱数が返されることはありません。

また、あなたのコードには何か問題があります。行transmission_time = floor(i * rng(1, N));transmission_time = floor(i * rand(1, N));.

サイクルごとに異なるシードを使用する場合は、rand を初めて使用する前に次の呼び出しを追加できますrng(i);。これにより、生成される乱数を制御できます (rand予測可能な数列が生成されます)。

于 2013-10-29T17:03:37.850 に答える
1

確かに、ある種のシミュレーションがある場合、同じ乱数で複数回実行しても意味がありません。これには基本的に 2 つの解決策があります。

1. 非常に簡単で、再現性のある結果が得られない

コードの開始時に、 にrng基づいたものに設定しますnow

このようにして、毎回異なる結果が得られます。

2. 簡単で推奨される、再現可能な結果を​​生成する

シミュレーションをループでラップします。毎回順番に実行すると、シミュレーションとは異なる結果が得られ (したがって、平均化が可能になります)、結果を再現することができます。


通常、シミュレーションからのボラティリティを減らしたい場合は、複数回実行する必要はありませんが、より長く実行できることに注意してください。

于 2013-10-29T17:12:30.320 に答える
1

ストリームを 1 つにして、単純に 10 倍のデータ サンプルを生成する方が簡単に思えます。parforただし、たとえばを使用して、それらから並行してプルしたい場合は、異なるシードで 10 個のランダム ストリームを作成できます。これを行う方法をまだ探している場合は、十分に文書化された方法が 2 つあります。

  1. 任意のストリーム タイプの複数のストリーム
  2. 'mrg32k3a'および'mlfg6331_64'タイプのサブストリーム

複数のストリーム

異なるシードを持つ 10 個のストリームの cell 配列を作成する例から始めます。

s = 0:9;
r = arrayfun(@(t)RandStream('mcg16807','Seed',t),s,'uni',false); % RandStreams

で同じシードを使用するとs、決定論的シミュレーションが得られ、常に同じ結果が得られます。あれは、

>> r = arrayfun(@(t)RandStream('mcg16807','Seed',t),s,'uni',false);
>> r{1}.rand
ans =
          0.21895918632809
>> r{2}.rand
ans =
         0.512908935785717
>> clear r
>> r = arrayfun(@(t)RandStream('mcg16807','Seed',t),s,'uni',false);
>> r{1}.rand
ans =
          0.21895918632809
>> r{2}.rand
ans =
         0.512908935785717

RandomStreamcell 配列に格納されたインスタンスには、、、およびrというおなじみのメソッドがあります。このメソッドは、乱数の同じシーケンスを最初からやり直します。randrandnrandirandpermreset

シミュレーションを決定論的ではなく、ある意味でよりランダムにしたくない場合は、文書化されていない方法sを使用して、時間に基づいて別のシード ベクトルを作成できます。 shuffleSeed

s = zeros(1,10);
for i=1:numel(s), s(i)=RandStream.shuffleSeed; end

ストリームを再生成します。

サブストリーム

サブストリームは、シード (または「チェックポイント」) を乱数ストリームに均等に分散しようとします。ただし、サブストリームの本当の利点は、おそらく再現性の容易さです。1 つのストリームを作成し、必要に応じて別のストリームに切り替えるだけなので、これは非常に簡単に思えます。例えば、

>> stream = RandStream('mrg32k3a');
>> stream.get('Substream')
ans =
 1
>> samps1 = stream.rand(1,20);  % some samplesfrom substream 1

次に、サブストリームを変更して、より多くのサンプルを取得します。

>> stream.Substream = 2;
>> samps2 = stream.rand(1,20);  % some samplesfrom substream 2

ただし、これでもサンプルのランダム性は改善されないことに注意してください。

次のサブストリームに移動する前に、各サブストリームのすべての値を「使い切る」ことを心配する必要はありませんが、別の極端な方法を取って、新しい値を生成するたびに別のサブストリームにジャンプするのは無意味です。サブストリームはランダム性を追加するのではなく、値の再現を容易にするだけです。

そのため、アプリケーションで乱数を生成するために複数の乱数ストリーム/シードを使用する意味がわかりません。

于 2013-10-29T22:19:01.123 に答える
0

混乱して申し訳ありません。異なるストリームを生成する必要はなかったと言って、あなたの何人かは正しかったと思います。

上記のコードには、「if node == pos」という行がありますが、これは正しくなく、「if Transmission_time(node) == pos」のはずです。

その1行が、私のグラフをすべて狂わせていた原因でした. また、成功したデータ パケットに対しても新しい乱数を生成する必要がありました。

しかし、すべての提案をありがとう!ただし、Matlab のシードでランダム性がどのように機能するかについては、より多くのことを知っています!

于 2013-10-31T15:22:03.030 に答える