Matlab:构造满足水平和垂直约束的二元矩阵

时间:2018-01-22 22:43:11

标签: matlab

我想启动一个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吗?

提前致谢。

2 个答案:

答案 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