简体   繁体   English

在Matlab中生成所有可能的列向量

[英]Generate all possible column vectors in matlab

I am essentially trying to figure out how to generate code for basis vectors of different configurations of M objects into N different states (for example, if I had 2 snacks between 2 kids, I could have (2,0) (0,2) or (1,1), terrible example, but thats the idea) 我本质上是在试图找出如何为M对象的不同配置的基向量生成代码到N个不同状态的代码(例如,如果我在2个孩子之间有2个零食,我可能会拥有(2,0)(0,2)或(1,1),一个可怕的例子,但这就是想法)

I am struggling to figure out how to do this without going into many different loops (I want this to be automatic). 我正在努力弄清楚如何做到这一点,而不必进入许多不同的循环(我希望这是自动的)。 The idea would be to create a Matrix where each row is a vector of length M. I would start with vec(1) = N then an if loop where if sum(vec) == N, Matrix(1,:)=vec; 想法是创建一个矩阵,其中每一行都是长度为M的向量。我将从vec(1)= N开始,然后是一个if循环,其中if sum(vec)== N,Matrix(1,:)= vec ; Then I could take vec(1)=Ni and do the same. 然后,我可以采用vec(1)= Ni并执行相同操作。

My only issue is I do not see how to use the if and forget it so that if I had maybe 2 objects in 5 locations, how would I do this to get (1 0 0 0 1). 我唯一的问题是我看不到如何使用if并忘记了它,所以如果我可能在5个位置中有2个对象,我将如何获得(1 0 0 0 1)。

I am not seeing how to do this. 我没有看到如何执行此操作。

You could use a recursive function: 您可以使用递归函数:

function out = combos(M,N)

if N == 1
  out = M;
else
  out = [];
  for i = 0:M
    subout = combos(M-i,N-1);
    subout(:,end+1) = i;
    out = [out;subout];
  end
end

I think this does what you want. 我认为这可以满足您的需求。

The key idea is to generate not the number of elements in each group, but the split points between groups. 关键思想是不生成每个组中元素的数量,而是生成组之间的分割点 This can be done via combinations with repetition . 这可以通过与重复结合来完成。 Matlab's nchoosek generates combinations without repetition, but these are easily converted into what we need. Matlab的nchoosek生成的组合没有重复,但是很容易将它们转换成我们需要的组合。

M = 5; % number of objects
N = 3; % number of groups
t = nchoosek(1:M+N-1, N-1); % combinations without repetition...
t = bsxfun(@minus, t, 1:N-1); % ...convert into combinations with repetition
t = diff([zeros(size(t,1), 1) t repmat(M, size(t,1), 1) ], [], 2); % the size of each
    % group is the distance between split points

In this example, the result is 在此示例中,结果是

t =
     0     0     5
     0     1     4
     0     2     3
     0     3     2
     0     4     1
     0     5     0
     1     0     4
     1     1     3
     1     2     2
     1     3     1
     1     4     0
     2     0     3
     2     1     2
     2     2     1
     2     3     0
     3     0     2
     3     1     1
     3     2     0
     4     0     1
     4     1     0
     5     0     0

This is a similar approach to Luis' without bsxfun . 这与没有bsxfun Luis相似。 Because we don't like fun. 因为我们不喜欢娱乐。

n = 5;
k = 3;

c = nchoosek(n+k-1, k-1);
result = diff([zeros(c, 1) nchoosek(1:(n+k-1), k-1) ones(c, 1)*(n+k)], [], 2) - 1;

This creates the partitions of the integer n with length k . 这将创建长度为k的整数n的分区。 Given an array of length n + (k-1) , we find all combinations of (k-1) places to place partitions between the (unary) integers. 给定长度为n + (k-1)的数组,我们找到(k-1)位置的所有组合,以在(一元)整数之间放置分区。 For 5 items and 3 locations, we have 7 choices of where to put the partitions: 对于5个项目和3个位置,我们有7种选择来放置分区:

[ 0 0 0 0 0 0 0 ]

If our chosen combination is [2 4] , we replace positions 2 and 4 with partitions to look like this: 如果我们选择的组合为[2 4] ,那么我们将24替换为分区,如下所示:

[ 0 | 0 | 0 0 0 ]

The O 's give the value in unary, so this combination is 1 1 3 . O给出一元值,因此此组合为1 1 3 To recover the values easily, we just augment the combinations with imaginary partitions at the next values to the left and right of the array ( 0 and n+k ) and take the difference and subtract 1 (because the partitions themselves don't contribute to the value): 为了轻松恢复这些值,我们只在数组左右两侧的下一个值( 0n+k )处用虚数分区扩展组合,然后求和并减去1 (因为分区本身对价值):

diff([0 2 4 8]) - 1
ans =

   1   1   3

By sliding the partitions in to each possible combination of positions, we get all of the partitions of n . 通过将分区滑入每个可能的位置组合,我们得到n所有分区。

Output: 输出:

result =

   0   0   5
   0   1   4
   0   2   3
   0   3   2
   0   4   1
   0   5   0
   1   0   4
   1   1   3
   1   2   2
   1   3   1
   1   4   0
   2   0   3
   2   1   2
   2   2   1
   2   3   0
   3   0   2
   3   1   1
   3   2   0
   4   0   1
   4   1   0
   5   0   0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM