4

さて、これは奇妙な質問のように思えるかもしれませんが、私に耐えてください。

そのため、.mファイルにランダムなベクトルがあり、特定の制約が組み込まれています。これが私のコードです:

 randvecall = randsample(done, done, true);
 randvec = randvecall([1;diff(randvecall(:))]~=0);

「完了」は、サンプルを取得する値の範囲にすぎないため、心配する必要はありません。ご覧のとおり、このrandsamplesは値の範囲からサンプリングし、diff関数を使用してこのランダムベクトルを削除し、連続する重複値を削除します。ベクトルに重複する値が存在する可能性はありますが、それらを連続させることはできません。

これはすべてうまく機能し、完全に正常に機能します。

したがって、たとえば、randvecは次のようになります。

randvec =

    54
    47
    52
    26
    39
     2
    14
    51
    24
     6
    19
    56
    34
    46
    12
     7
    41
    18
    29
     7

実際にはもっと長く、60〜70の値のようなものですが、要点はわかります。

私がやりたいのは、このベクトルに少し余分な制約を追加することです。このベクトルからサンプリングすると、値は範囲に従って分類されます。したがって、1〜15の値はカテゴリ1、16〜30はカテゴリ2、というように続きます。この理由は重要ではありませんが、プログラムのかなり重要な部分です。したがって、上記で提供した値を見ると、次のようなセクションが表示されます。

     7
    41
    18
    29
     7

これは私のプログラムにとって実際には悪いことです。値の範囲は別々に扱われるため、41、18、および29は7とは異なる方法で使用されます。したがって、すべての意図と目的のために、7が私のスクリプトに連続して表示されています。私がやりたいのは、ベクトルが生成されたときに、ベクトルを解析/変更/何でもして、特定の範囲の同じ番号が、それらの間に異なる範囲の他の番号がいくつあるかに関係なく、「連続して」表示されないようにすることです。これは理にかなっていますか/私はこれをうまく説明しましたか?したがって、MATLABでベクトルを検索し、特定の範囲(1〜15、16〜30、31〜45、46〜60)内のすべての値について、同じ範囲の「連続する」値が同一でないことを確認します。

だから、それが私がやりたいことです。これは決してこれを行うための最良の方法ではないかもしれないので、アドバイス/代替案はもちろんありがたいです。複数のベクトルを使用するとこれをより適切に実行できることはわかっていますが、さまざまな理由から、これを単一の長いベクトルにする必要があります(スクリプトの設計方法では、値の範囲ごとに個別のベクトルがあると機能しません) 。

4

4 に答える 4

3

カテゴリごとに1つずつ、合計4つのランダムベクトルを作成し、それらに2つの連続する等しい値が含まれていないことを確認してから、ランダムカテゴリから値を順序付けて選択することにより、最終的なランダムベクトルを作成します。

%# make a 50-by-nCategories array of random numbers
categories = [1,16,31,46;15,30,45,60]; %# category min/max
nCategories = size(categories,2);
randomCategories = zeros(50,nCategories);

for c=1:nCategories
   %# draw 100 numbers for good measure
   tmp = randi(categories(:,c),[100 1]);
   tmp(diff(tmp==0)) = []; %# remove consecutive duplicates

   %# store
   randomCategories(:,c) = tmp(1:50);
end

%# select from which bins to pick. Use half the numbers, so that we don't force the 
%# numbers of entries per category to be exactly equal

bins = randi(nCategories,[100,1]);

%# combine the output, i.e. replace e.g. the numbers
%# '3' in 'bins' with the consecutive entries
%# from the third category
out = zeros(100,1);
for c = 1:nCategories
   cIdx = find(bins==c);
   out(cIdx) = randomCategories(1:length(cIdx),c);
end
于 2012-07-03T16:00:52.290 に答える
2

まず、各要素に、その要素が含まれる範囲のビン番号を割り当てます。

[~,bins] = histc(randvec, [1 16 31 46 61]);

次に、範囲ごとにループし、それらのカテゴリの要素を見つけます。たとえば、1〜16の最初の範囲では、次のようになります。

>> ind = find(bins==1);       %# bin#1 of 1-16
>> x = randvec(ind)
ans =
     2
    14
     6
    12
     7
     7

これで、連続する重複を削除するのと同じプロセスを適用できます。

>> idx = ([1;diff(x)] == 0)
idx =
     0
     0
     0
     0
     0
     1
>> problematicIndices = ind(idx)   %# indices into the vector: randvec

すべての範囲でこれを行い、問題のあるインデックスを収集します。次に、それらにどのように対処するかを決定します(それらを削除し、代わりに他の番号を生成するなど...)

于 2012-07-03T16:11:05.900 に答える
1

私があなたの問題を正しく理解していれば、それが一つの解決策だと思います。一意を使用しますが、ベクトルの各サブ範囲に適用します。インデックスの範囲内で重複している値は、それらを処理できるように識別されます。

cat_inds = [1,16,31,46,60];  % need to include last element
for i=2:numel(cat_inds)
  randvec_part = randvec( cat_inds(i-1):cat_inds(i) );
  % Find the indices for the first unique elements in this part of the array
  [~,uniqInds] = unique(randvec_part,'first');

  % this binary vector identifies the indices that are duplicated in
  % this part of randvec
  %
  % NB: they are indices into randvec_part
  %
  inds_of_duplicates = ~ismember(1:numel(randvec_part), uniqInds);

  % code to deal with the problem indices goes here.  Modify randvec_part accordingly...

  % Write it back to the original vector (assumes that the length is the same)
  randvec( cat_inds(i-1):cat_inds(i) ) = randvec_part;
end
于 2012-07-03T17:45:51.607 に答える
1

これは、他の誰もが投げてきたものとは異なるアプローチです。私がここで取り組んでいる前提は、反復なしでベクトル内の値をランダムに配置したいということです。入力を行う前に、他にどのような制約を適用しているかわかりません。

私の考えは、randperm関数を使用することです。

これがどのように機能するかのサンプルコードです:

%randvec is your vector of random values
randvec2 = unique(randvec); % This will return the sorted list of values from randvec.
randomizedvector = randvec2(randperm(length(randvec2)); 
% Note: if randvec is multidimensional you'll have to use numel instead of length

この時点randomizedvectorで、初期からのすべての一意の値が含まれている必要がありますがrandvec、一意の関数呼び出し後に「シャッフル」または再ランダム化されます。これで、randvecを別の方法でシードして、一意の関数呼び出しが不要になるようにすることができます。これを呼び出すだけrandperm(n)で、1からnの範囲の値を持つランダム化されたベクトルが返されます。

壁から2セント離れたところ=Pお楽しみください!

于 2012-07-03T18:30:08.323 に答える