[原創] Matlab 指派問題模型代碼


指派問題的基本內容

一般來說指派問題解決的是如何將任務分配到人,使得任務完成的效益最大化(成本型效益則求最小值,利潤型效益則求最大值)。上述問題一個 0 - 1 整數規划問題。

問題圍繞着任務和人展開,即存在着 m 個任務,以及 n 個人。每個人處理每個任務都會有對應的效益,將所有人的情況寫在一起,就組成了一個 m*n 的效益矩陣。


當 m = n 時,即此時,任務數和人數相等,那么每個人都會處理一項任務,存在如下約束:

對於任務來說,每個任務必須分配一個人;

對於人來說,每個人必須分配一個任務。


類似的,當 m < n 時,任務數小於人數,則存在如下約束:

對於任務來說,每個任務必須分配一個人;

對於人來說,每個人可能會被分配到一個任務,也可能沒有分配到任務。


當 m > n 時,任務數大於人數,則存在如下約束:

對於任務來說,每個任務必須分配一個人;

對於人來說,每個人可能會被分配到一個或者多個任務,但最多不超過任務總數。


模型調用形式

 [x,min_fval,exitflag] = myTaskArrange2(f)

調用說明:

輸入變量為一個 m*n 的效益矩陣,其中 m 行為 m 個任務, n 列為 n 個人。

輸出變量 x 為與效益矩陣同型的 0-1 矩陣,1表示被安排,0表示不被安排;min_fval 為最優目標值;exitflag 為退出標識符,一般等於 1 表示解收斂。


模型代碼

function [x,min_fval,exitflag] = myTaskArrange2(f)
%% 程序功能說明
%求解不平衡任務指派問題
%====輸入參數====
%f            m行n列的效益矩陣,m個任務,n個人,
%====輸出參數====
%x            目標函數取最小值時的自變量值
%min_fval     目標函數的最小值
% exitflag    退出標識符
%程序編寫時間:2019年09月

%% 程序主體
[m,n] = size(f); % 獲取效益矩陣中任務的個數和人的個數

% 按行拉成一列向量
f = f';
F = f(:);

% 構造等式約束(每一行加起來等於1,即每個任務必須分配一人)
Aeq = cell(m,m);
Aeq(:) = {zeros(1,n)};
Aeq(eye(m,m)==1) = {ones(1,n)};
Aeq = cell2mat(Aeq);
Beq = ones(m,1);

% 取整變量地址
intcon = 1:m*n;

% 變量取值范圍(大於0小於1)
LB = zeros(m*n,1);
UB = ones(m*n,1);

if m == n       % 如果任務數等於人數
    % 構造等式約束(每個人一定會被安排)
    Aeq2 = repmat(eye(n,n),1,m);
    Beq2 = ones(n,1);
    Aeq = [Aeq;Aeq2];
    Beq = [Beq;Beq2];
    
    % 整數規划求解
    [x,min_fval, exitflag] = intlinprog(F,intcon,[],[],Aeq,Beq,LB,UB);
    
elseif m < n     % 如果任務數小於人數
    % 構造不等式約束(每一列加起來大於0小於1,即每個人可能被安排也可能不被安排一個任務)
    A = repmat(eye(n,n),1,m);
    B = ones(n,1);
    % 利用整數規划函數求解
    [x,min_fval, exitflag] = intlinprog(F,intcon,A,B,Aeq,Beq,LB,UB);
    
elseif m > n      % 如果任務數大於人數
    % 構造不等式約束(每一列加起來大於1小於m,即每個人可能被安排一個或者多個任務,最多不超過任務數m)
    A = repmat(eye(n,n),1,m);
    B = ones(n,1)*m;
    % 利用整數規划函數求解
    [x,min_fval, exitflag] = intlinprog(F,intcon,A,B,Aeq,Beq,LB,UB);
end
%% 將結果還原成效益矩陣對應形式
x = reshape(x,n,m)';

測試算例

為了驗證本模型的效果,提供如下測試算例,進行驗證:


% 4項任務,4個人完成 最優解:8
f1 = [6,1,3,8;
    6,3,5,2;
    1,1,1,4;
    7,2,5,2];

% 4項任務,5個人完成  最優解:127.8
f2 = [37.7,32.9,38.8,37,35.4;
    43.4,33.1,42.2,34.7,41.8;
    33.3,28.5,38.9,30.4,33.6;
    29.2,26.4,29.6,28.5,31.1];

% 5項任務,3個人完成 最優解:116
f3 = [25,39,34;
    29,38,27;
    31,26,28;
    4,20,40;
    37,18,32];


[x,min_fval,exitflag] = myTaskArrange2(f1) % 修改輸入測試效果


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM