我想启动一个mxn二进制矩阵。对于j = 1..n,矩阵的每列的总和等于给定值s(j)。此外,矩阵每一行的总和应在给定范围的范围内:lhs为dl(i),rhs为du(i),i = 1..m。
现在我只能随机生成二进制列,其中每个列的总和等于该列的s(j),例如以下代码。
xij = zeros(m,n);
for j=1:n
randRows=randperm(m); %a row vector containing a random permutation of the integers from 1 to m inclusive.
rowsWithOne=randRows(1:sj(j)); %row indices having 1, and sum up to sj
xij(rowsWithOne,j)=1;
end
然而,xij通常不满足水平约束。我在想我应该创建一个矩阵首先满足行约束lhs(下界)dl(i),然后是列约束s(j),最后填充偏移以满足rhs du(i),但我不会&#39 ; t知道如何在Matlab中实现它。有什么想法来创建xij吗?
提前致谢。
答案 0 :(得分:0)
首先要考虑几件事情,主要是如果问题甚至可以通过给定的约束来解决。首先,您必须检查s(j),sum(s)
的总和是否大于下限约束sum(dl)
的总和,还要小于上限约束的总和{{ 1}}。
一个简单的if语句应该可以检查这个。完成此操作后,以下代码应该是问题的一种解决方案,但鉴于问题的性质,可能不会有唯一的解决方案。
sum(du)
第一个for循环在行上添加1,这样每行都满足最小约束。下一个for循环在列上添加1,以便每列添加到所需的值。第一个for循环中的%initialize counters
x = 1;
y = 1;
%make sure the lower bounds are first satisfied
for k = 1:nrows
while (dl(k) > 0)
if (s(y) > 0)
xij(k,y) = 1;
dl(k) = dl(k)-1;
du(k) = du(k)-1;
s(y) = s(y)-1;
end
y = y+1;
end
y = 1;
end
%make sure the columns all add to their specified values
for k = 1:ncols
while (s(k) > 0)
if (xij(x,k) == 0 && du(x) > 0)
xij(x,k) = 1;
du(x) = du(x)-1;
s(k) = s(k)-1;
end
x = x+1;
end
x = 1;
end
语句确保如果该列已经达到其期望值,则不添加1,并且第二个for循环中的if
语句确保1不是添加到一行,使其超过行的最大值。
为了跟踪1的数量,每次将1添加到相应的行时,if
会降低1,同样,每个减去所需的值du
减去1时间a 1被添加到s(j)
矩阵的该列。
答案 1 :(得分:0)
%Create an initial xij matrix, each column of which consists of a random binary xij sequence, but sum of ones in each column equals to sj
Init_xij = zeros(nShift,nCombo);
for j=1:nCombo
randRows=randperm(nShift); %a row vector containing a random permutation of the integers from 1 to nShift inclusive.
rowsWithOne=randRows(1:sj(j)); %row indices having 1, and sum up to sj
Init_xij(rowsWithOne,j)=1;
end
%Adjust the initial xij matrix to make it feasible, satisfying horizontal
%LHS (dli) and RHS (dui) constraints
Init_xij_Feasible=Init_xij;
k=1;
while k
RowSum=sum(Init_xij_Feasible,2); %create a column vector containing the sum of each row
CheckLB=lt(RowSum,dli); %if RowSum <dli, true
CheckUB=gt(RowSum,dui); %if RowSum >dui, true
if ~any(CheckLB)&&~any(CheckUB) %if any element in CheckLB and CheckUB is zero
break,
else
[~,RowIdxMin]=min(RowSum);
[~,RowIdxMax]=max(RowSum);
ColIdx=find(Init_xij_Feasible(RowIdxMax,:) & ~Init_xij_Feasible(RowIdxMin,:),1); % returns the first 1 column index corresponding to the nonzero elements in row RowIdxMax and zero elements in row RowIdxMin.
%swap the min and max elements
[Init_xij_Feasible(RowIdxMin,ColIdx),Init_xij_Feasible(RowIdxMax,ColIdx)]=deal(Init_xij_Feasible(RowIdxMax,ColIdx),Init_xij_Feasible(RowIdxMin,ColIdx));
end
k=k+1;
end