查找多个变量的所有组合,总计为1

时间:2015-02-13 19:15:33

标签: matlab matrix combinatorics diophantine

我正试图解决这个等式

x1 + x2 + x3 + .... + xn = 1

其中所有xi的值都限制为[0, 0.1, 0.2, ..., 0.9, 1]


目前,我通过首先生成一个n维数组mat来解决这个问题,其中每个元素位置的值是轴值的总和,它们在axisValues = 0:0.1:1中变化:

mat(i,j,k,...,q) = axisValues(i) + axisValues(j) + ... + axisValues(q).

然后我搜索结果数组中等于1的所有条目。代码(如下所示进一步说明)工作正常,已经过多达5个维度的测试。问题是,运行时间呈指数增长,我需要脚本工作超过几个维度。

clear all
dim = 2; % The dimension of the matrix is defined here. The script has been tested for dim ≤ 5
fractiles(:,1) = [0:0.1:1]; % Produces a vector containing the initial axis elements, which will be used to calculate the matrix elements
fractiles = repmat(fractiles,1,dim); % multiplies the vector to supply dim rows with the axis elements 0:0.1:1. These elements will be changed later, but the symmetry will remain the same.
dim_len = repmat(size(fractiles,1),1,size(fractiles,2)); % Here, the length of the dimensions is checked, which his needed to initialize the matrix mat, which will be filled with the axis element sums
mat = zeros(dim_len); % Here the matrix mat is initialized
Sub=cell(1,dim);
mat_size = size(mat);
% The following for loop fills each matrix elements of the dim dimensional matrix mat with the sum of the corresponding dim axis elements.
for ind=1:numel(mat)
    [Sub{:}]=ind2sub(mat_size,ind);
    SubMatrix=cell2mat(Sub);
    sum_indices = 0;
    for j = 1:dim
        sum_indices = sum_indices+fractiles(SubMatrix(j),j);
    end
    mat(ind) = sum_indices;
end
Ind_ones = find(mat==1); % Finally, the matrix elements equal to one are found.

我觉得使用问题对称性的以下想法可能有助于显着缩短计算时间:

对于2D矩阵,满足上述条件的所有条目都位于从mat(1,11)mat(11,1)的对角线上,即从x1的最大值到{{的最大值1}}。

对于3D矩阵,所有条目都满足x2mat(1,1,11)mat(1,11,1)的对角线平面上的条件,即mat(11,1,1)的最大值和x1 x2的最大值。

对于更高维度也是如此:所有感兴趣的矩阵元素都位于固定在每个维度的最高轴值上的x3维超平面上。


问题是:有没有办法直接确定这些n-1维超平面上元素的索引?如果是这样,整个问题可以在一个步骤中解决,而不需要计算n维矩阵的所有条目,然后搜索感兴趣的条目。

1 个答案:

答案 0 :(得分:3)

数学:

我们不是采用超立方体方式来解决方程式

x(1) + x(2) + ... + x(n) = 1

其中x(i)的每个[0, 1/k, 2/k, ... (k-1)/k, 1]可能会因k而异。在您的情况下,[0, 10, 20, ... 90, 100]将为10,因为这将导致百分比k。 乘以x(1) + x(2) + ... + x(n) = k, ,这对应于丢番图方程

x(i)

[0, 1, 2, ... k-1, k]中所有x1 + x2 + ... + xn = k的变化。

我们可以在此与combinations with repetition的组合概念之间建立一个双射。

维基百科的文章甚至隐含地提到了声明的潜在反对意见:

  

大小为k的多子集的数量是丢番图方程k=3的非负整数解的数量。

对于较小的示例,请说明我们将使用[0, 33, 66, 100]{1,2,3}中的百分比。给定集合RepCombs = 1 1 1 1 1 2 1 1 3 1 2 2 1 2 3 1 3 3 2 2 2 2 2 3 2 3 3 3 3 3 的所有k-多重化:

i

然后我们使用以下规则将这些映射到您的百分比: 对于每一行j,如果条目为1/3,则将百分比M(i,j)添加到相应的矩阵条目[1/3 + 1/3 + 1/3, 0, 0] = [1,0,0]。第一行将对应M = 1.0000 0 0 0.6667 0.3333 0 0.6667 0 0.3333 0.3333 0.6667 0 0.3333 0.3333 0.3333 0.3333 0 0.6667 0 1.0000 0 0 0.6667 0.3333 0 0.3333 0.6667 0 0 1.0000 。 此过程生成的整体矩阵如下所示:

nmultichoosek

代码:

现在,对于生成所有这些的MATLAB代码: 我使用this answeraccumarray中的function M = possibleMixturesOfNSubstances(N, percentageSteps) RepCombs = nmultichoosek(1:N, percentageSteps); numCombs = size(RepCombs,1); M = accumarray([repmat((1:numCombs).', percentageSteps, 1), RepCombs(:)], 1/percentageSteps, [numCombs, N]); 函数来完成我们的目标:

[0, 10, ... 90, 100]

如果您想要possibleMixturesOfNSubstances(4,10)中的百分比并且有4种物质,请使用{{1}}

调用此函数