Matlab 求多个变量之和为1的所有组合
我正试图解这个方程Matlab 求多个变量之和为1的所有组合,matlab,matrix,combinatorics,diophantine,Matlab,Matrix,Combinatorics,Diophantine,我正试图解这个方程 x1 + x2 + x3 + .... + xn = 1 x(1) + x(2) + ... + x(n) = 1 x(1) + x(2) + ... + x(n) = k, 其中所有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
x1 + x2 + x3 + .... + xn = 1
x(1) + x(2) + ... + x(n) = 1
x(1) + x(2) + ... + x(n) = k,
其中所有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
的最大值到x2
的最大值
对于3D矩阵,所有条目都满足位于对角线平面上的条件,通过mat(1,1,11)
,mat(1,11,1)
,mat(11,1,1)
,即从x1
和x2
的最大值到x3
的最大值
更高维度也是如此:所有感兴趣的矩阵元素都位于固定在每个维度最高轴值上的n-1
维度超平面上
问题是:有没有办法直接确定这些
n-1
维超平面上元素的指数?如果是这样,整个问题可以一步解决,而不需要计算n维矩阵的所有条目,然后搜索感兴趣的条目 数学:
我们不走超立方体的路,而是解方程
x1 + x2 + x3 + .... + xn = 1
x(1) + x(2) + ... + x(n) = 1
x(1) + x(2) + ... + x(n) = k,
其中每个x(i)
可以在[0,1/k,2/k,…(k-1)/k,1]
中变化。在您的情况下,k
将是10,因为这将导致百分比[0,10,20,…90100]
。
乘以k
这对应于丢番图方程
x1 + x2 + x3 + .... + xn = 1
x(1) + x(2) + ... + x(n) = 1
x(1) + x(2) + ... + x(n) = k,
其中所有的x(i)
在[0,1,2,…k-1,k]
中变化
我们可以在这个和组合概念之间建立一个双射
维基百科的文章甚至在声明中含蓄地提到了潜在的双射:
那么大小为k的多子集的数目就是丢番图方程x1+x2+…+的非负整数解的数目xn=k
对于一个较小的例子,假设我们使用k=3
和[0,33,66100]
中的百分比。给定集合{1,2,3}
的所有k-多重组合:
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
然后,我们使用以下规则将其映射到您的百分比:
对于每一行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
代码:
现在来看生成所有这些的MATLAB代码:
我使用函数nmultichoosek
from和accumarray
来实现我们的目标:
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]
中,并且有4种物质,请使用可能的混合物质(4,10)
调用此函数如果您试图生成这个庞大的矩阵,它自然会以指数形式增加。你可以把速度加快一点,但是否值得,这取决于是否没有办法绕过这个矩阵。什么是应用程序?我还是不太明白。你想解决什么问题?你发布的代码解决了什么问题?我想这应该与向量的凸包有关e1
toen
。。。如果你有所有这些线性指数,你的下一步是什么?这些线性指数代表所有可能的n组分混合物(例如,n=3的氢+氧+氮)。该脚本运行完毕后,索引将被输入到另一个脚本中,该脚本将组件数据集的每个可能组成近似为参考(例如水),并找到最佳近似值(在本例中为0.1119 H+0.8881 O+0 Ti)。手边的这个脚本应该找到n个组件的所有可能组合,并将其传递给后续脚本以进行优化过程。(上图:nigtrogen=Tianium)问题主要是内存和运行时。当然,运行时将保持指数增长,但我喜欢将问题简化为实际感兴趣的矩阵元素,并避免计算不必要的值。因此是(超)平面,其中包括所有感兴趣的值。这个(超)平面实际上是凸包,在e1到en的最大值之间,我相信。所以基本上你并不真正关心超平面,而是要计算不同分量的混合百分比的所有可能组合,其中每个分量可以有一个:0,10,20,。。。,90100%?@AndreasSchönfeld:很高兴能帮忙!