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

您可能想要做的是创建四个随机向量,每个类别一个,确保它们不包含任何两个连续相等的值,然后通过从随机类别中有序选取值来构建最终的随机向量,即

%# 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

首先,我们为每个元素分配它所在范围的 bin 编号:

[~,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

这是一种与其他人一直在折腾的方法不同的方法。我在这里工作的前提是您希望在向量中随机排列值而不重复。我不确定在我们提供输入之前您还应用了哪些其他限制。

我的想法是使用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 回答
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 回答