在MatLab中迭代来自固定总和的值

时间:2012-03-19 22:04:20

标签: matlab combinatorics loops

假设我有大理石,每种都可以是8种颜色中的一种。我想迭代所有可能的大理石颜色组合值。我怎样才能在MatLab中做到这一点?

例如,如果n = 2,那么我想迭代:

2 0 0 0 0 0 0 0

1 1 0 0 0 0 0 0

1 0 1 0 0 0 0 0

1 0 0 1 0 0 0 0

1 0 0 0 1 0 0 0

1 0 0 0 0 1 0 0

1 0 0 0 0 0 1 0

1 0 0 0 0 0 0 1

0 2 0 0 0 0 0 0

0 1 1 0 0 0 0 0

0 1 0 1 0 0 0 0

编辑:

这是一些伪代码的样子,但你可以看到它非常草率。我对这样做更简洁,并且不需要if语句......

for i8 = 0:1:n
    for i7 = 0:1:n - i8
        for i6 = 0:1:n - i8 - i7
            for i5 = 0:1:n - i8 - i7 - i6
                for i4 = 0:1:n - i8 - i7 - i6 - i5
                    for i3 = 0:1:n - i8 - i7 - i6 - i5 - i4
                        for i2 = 0:1:n - i8 - i7 - i6 - i5 - i4 - i3
                            for i1 = 0:1:n - i8 - i7 - i6 - i5 - i4 - i3 - i2
                                if i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 == n
                                    i = [i1, i2, i3, i4, i5, i6, i7, i8]
                                end
                            end
                        end
                    end
                end
            end
        end
    end
end

5 个答案:

答案 0 :(得分:5)

这是解决方案(代码在GNU / Octave中测试,它也应该在Matlab中工作)。 此代码源自Octave-Forge multinom_exp.m

function conf = marbin (nmar,nbin)
%% Returns the position of nmar in nbis, allowing the marbles to be in the same bin.

%% This is standard stars and bars.
 numsymbols = nbin+nmar-1;
 stars = nchoosek (1:numsymbols, nmar);

%% Star labels minus their consecutive position becomes their index
%% position!
 idx = bsxfun (@minus, stars, [0:nmar-1]);

%% Manipulate indices into the proper shape for accumarray.
 nr = size (idx, 1);
 a = repmat ([1:nr], nmar, 1);
 b = idx';
 conf = [a(:), b(:)];
 conf = accumarray (conf, 1);

答案 1 :(得分:2)

我认为你更容易想到弹珠的状态,而不是颜色的状态。然后根据需要从大理石状态转换为颜色状态。例如,如果考虑所有可能的大理石状态的有序列表,您可以创建看起来像这样的函数(使用全零作为“全部完成”标志):

function state = nextmarblestate(state, nMarbles, nColors)
%Increment the marble state by 1

%Add one to the last marble
state(end) = state(end)+1;

%Propogate change towards the first marble as colors overflow
for ixCurrent = nMarbles:-1:2
    if state(ixCurrent) > nColors;
        state(ixCurrent) = 1;
        state(ixCurrent-1) = state(ixCurrent-1)+1;
    else
        return;
    end
end

%Check to see if we are done (reset to 0)
if state(1) > nColors
    state = zeros(1,nMarbles);
end

然后你可以编写一个快速循环来遍历所有大理石状态:

nMarbles = 2;
nColors = 8;

marblestate = ones(1,nMarbles);
while sum(marblestate)>0
    disp(['Marblestate = [' num2str(marblestate) ']'])
    marblestate = nextmarblestate(marblestate, nMarbles, nColors);
end

或者,为了得到你想要的结果,写一个从大理石状态到颜色状态的转换,就像这样(对不起这里的简洁性,这可以扩展到更漂亮的版本):

marbleState2colorState = @(marblestate) arrayfun(@(color)sum(marblestate==color), 1:nColors);

然后使用该转换函数,像这样展开上面的while循环:

marblestate = ones(1,nMarbles);
while sum(marblestate)>0
    disp(['Marblestate = [' num2str(marblestate) '],  Colorstate = [' num2str(marbleState2colorState(marblestate)) ']'])
    marblestate = nextmarblestate(marblestate, nMarbles, nColors);
end

产生以下输出:

Marblestate = [1  1],  Colorstate = [2  0  0  0  0  0  0  0]
Marblestate = [1  2],  Colorstate = [1  1  0  0  0  0  0  0]
Marblestate = [1  3],  Colorstate = [1  0  1  0  0  0  0  0]
Marblestate = [1  4],  Colorstate = [1  0  0  1  0  0  0  0]
Marblestate = [1  5],  Colorstate = [1  0  0  0  1  0  0  0]
Marblestate = [1  6],  Colorstate = [1  0  0  0  0  1  0  0]
Marblestate = [1  7],  Colorstate = [1  0  0  0  0  0  1  0]
Marblestate = [1  8],  Colorstate = [1  0  0  0  0  0  0  1]
Marblestate = [2  1],  Colorstate = [1  1  0  0  0  0  0  0]
Marblestate = [2  2],  Colorstate = [0  2  0  0  0  0  0  0]
Marblestate = [2  3],  Colorstate = [0  1  1  0  0  0  0  0]
Marblestate = [2  4],  Colorstate = [0  1  0  1  0  0  0  0]
Marblestate = [2  5],  Colorstate = [0  1  0  0  1  0  0  0]
Marblestate = [2  6],  Colorstate = [0  1  0  0  0  1  0  0]
Marblestate = [2  7],  Colorstate = [0  1  0  0  0  0  1  0]
Marblestate = [2  8],  Colorstate = [0  1  0  0  0  0  0  1]
Marblestate = [3  1],  Colorstate = [1  0  1  0  0  0  0  0]
Marblestate = [3  2],  Colorstate = [0  1  1  0  0  0  0  0]
Marblestate = [3  3],  Colorstate = [0  0  2  0  0  0  0  0]
Marblestate = [3  4],  Colorstate = [0  0  1  1  0  0  0  0]
Marblestate = [3  5],  Colorstate = [0  0  1  0  1  0  0  0]
Marblestate = [3  6],  Colorstate = [0  0  1  0  0  1  0  0]
Marblestate = [3  7],  Colorstate = [0  0  1  0  0  0  1  0]
Marblestate = [3  8],  Colorstate = [0  0  1  0  0  0  0  1]
Marblestate = [4  1],  Colorstate = [1  0  0  1  0  0  0  0]
Marblestate = [4  2],  Colorstate = [0  1  0  1  0  0  0  0]
Marblestate = [4  3],  Colorstate = [0  0  1  1  0  0  0  0]
Marblestate = [4  4],  Colorstate = [0  0  0  2  0  0  0  0]
Marblestate = [4  5],  Colorstate = [0  0  0  1  1  0  0  0]
Marblestate = [4  6],  Colorstate = [0  0  0  1  0  1  0  0]
Marblestate = [4  7],  Colorstate = [0  0  0  1  0  0  1  0]
Marblestate = [4  8],  Colorstate = [0  0  0  1  0  0  0  1]
Marblestate = [5  1],  Colorstate = [1  0  0  0  1  0  0  0]
Marblestate = [5  2],  Colorstate = [0  1  0  0  1  0  0  0]
Marblestate = [5  3],  Colorstate = [0  0  1  0  1  0  0  0]
Marblestate = [5  4],  Colorstate = [0  0  0  1  1  0  0  0]
Marblestate = [5  5],  Colorstate = [0  0  0  0  2  0  0  0]
Marblestate = [5  6],  Colorstate = [0  0  0  0  1  1  0  0]
Marblestate = [5  7],  Colorstate = [0  0  0  0  1  0  1  0]
Marblestate = [5  8],  Colorstate = [0  0  0  0  1  0  0  1]
Marblestate = [6  1],  Colorstate = [1  0  0  0  0  1  0  0]
Marblestate = [6  2],  Colorstate = [0  1  0  0  0  1  0  0]
Marblestate = [6  3],  Colorstate = [0  0  1  0  0  1  0  0]
Marblestate = [6  4],  Colorstate = [0  0  0  1  0  1  0  0]
Marblestate = [6  5],  Colorstate = [0  0  0  0  1  1  0  0]
Marblestate = [6  6],  Colorstate = [0  0  0  0  0  2  0  0]
Marblestate = [6  7],  Colorstate = [0  0  0  0  0  1  1  0]
Marblestate = [6  8],  Colorstate = [0  0  0  0  0  1  0  1]
Marblestate = [7  1],  Colorstate = [1  0  0  0  0  0  1  0]
Marblestate = [7  2],  Colorstate = [0  1  0  0  0  0  1  0]
Marblestate = [7  3],  Colorstate = [0  0  1  0  0  0  1  0]
Marblestate = [7  4],  Colorstate = [0  0  0  1  0  0  1  0]
Marblestate = [7  5],  Colorstate = [0  0  0  0  1  0  1  0]
Marblestate = [7  6],  Colorstate = [0  0  0  0  0  1  1  0]
Marblestate = [7  7],  Colorstate = [0  0  0  0  0  0  2  0]
Marblestate = [7  8],  Colorstate = [0  0  0  0  0  0  1  1]
Marblestate = [8  1],  Colorstate = [1  0  0  0  0  0  0  1]
Marblestate = [8  2],  Colorstate = [0  1  0  0  0  0  0  1]
Marblestate = [8  3],  Colorstate = [0  0  1  0  0  0  0  1]
Marblestate = [8  4],  Colorstate = [0  0  0  1  0  0  0  1]
Marblestate = [8  5],  Colorstate = [0  0  0  0  1  0  0  1]
Marblestate = [8  6],  Colorstate = [0  0  0  0  0  1  0  1]
Marblestate = [8  7],  Colorstate = [0  0  0  0  0  0  1  1]
Marblestate = [8  8],  Colorstate = [0  0  0  0  0  0  0  2]

答案 2 :(得分:2)

如果你有2个弹珠,每个弹珠可以是8种颜色中的一种,那么这就足够了:

>> dec2base(0:63,8)
ans =
00
01
02
03
04
05
06
07
10
11
12
13
14
15
16
17
20
21
22
23
24
25
26
27
30
31
32
33
34
35
36
37
40
41
42
43
44
45
46
47
50
51
52
53
54
55
56
57
60
61
62
63
64
65
66
67
70
71
72
73
74
75
76
77

请注意,它以不同于您的方式存储信息,但存在相同的信息。如果您需要,可以很容易地转换为您的表单。

答案 3 :(得分:2)

我相信以下代码段适用于n = 2的情况。

这是用Octave编写的,因为我目前无法访问Matlab。

我已经使用各种低颜色值(2,3,4,5,6和8)测试了手动生成的结果。

colours = 4;
marbles = 2;

for i=1:colours
   a = zeros(1,colours);
   a(i) = marbles
   for j=i:colours-1
      a(j) = a(j) -1;
      a(j+1) = a(j+1)+1  
   endfor
endfor 

我仍然在处理代码片段,以获取任意数量的颜色和任意数量的大理石的一般情况。

答案 4 :(得分:2)

nc = 8;    % number colors
nm = 2;    % number marbles

% For now let marbles be unique. There are then nc^nm assignments of
% marbles to colors
nmc = nc^nm;

% Enumerate the assignments of marbles to colors: i.e., sub{k} is a row
% array giving the color of marble k for each of the nmc assignments
[sub{1:nm,1}] = ind2sub(nc*ones(1,nm),1:nmc);

% We'll use accumarray to map the marble color assignments in sub to number
% of marbles of each color
% Bring sub into form required for application of accumarray
s = mat2cell(cell2mat(sub),nm,ones(nmc,1));

% apply accumarray to each assignement of colors to marbles
a = cellfun(@(c)accumarray(c,1,[nc,1]),s,'UniformOutput',false);

% Each element of a is a column vector giving the number of marbles of each
% color. We want row vectors, and we want only the unique rows
a = unique(cell2mat(a)','rows'); 

% a is as desired.