MiniZinc:如何在一周的每一天最大化生产率

时间:2018-08-31 11:09:39

标签: optimization minizinc

我想安排商店的工作人员,并最大化一周中每天的生产率变量。该生产率var计算为一天的目标预算除以该天的工作小时数。

我的MiniZinc模型如下。

使用“解决满意”方法是可行的,但并不能根据目标预算优化工时或人事(工作人员)数。例如,当目标Bugget较小时,我希望有更少的时间。

“解决最大生产率”问题不起作用,因为它是一个数组。

有什么主意吗?


include "globals.mzn";

% Week in year

int: Week = 41;

% Days in week

enum Days = {Mo, Tu, We, Th, Fr, Sa, Su};

% Employees

enum Employees = {E01, E02, E03, E04, E05, E06, E07, E08, E20, E21, E22, E23};

% Week contracts in hour

array[Employees] of int: Contracts = [35, 35, 35, 35, 35, 35, 24, 24, 37, 40, 40, 40];

% Budget

array[Days] of int: Budget = [3500, 2500, 5000, 3500, 6000, 20000, 10000];

% Work hours

array[Employees, Days] of var 0..10: Work;

% Personnel effort

array[Days] of var int: Personnel_effort;

% Hour effort

array[Days] of var int: Hour_effort;

% Productivity

array[Days] of var int: Productivity;


% ===============================


% Constraints for the employees

% E01 can't work on We
% E01 work either on Sa or Su depending on Week odd or even

constraint forall (d in Days) (
 if d in {We} then Work[E01, d] = 0 endif
  /\
 if Week mod 2 = 0 then Work[E01, Su] = 0
 else Work[E01, Sa] = 0 endif
);

% E02 can't work on Sa

constraint forall (d in Days) (
  if d in {Sa} then Work[E02, d] = 0 endif
);

% E07 can't work on Tu, Wed, Th and Fr

constraint forall (d in Days) (
  if d in {Tu, We, Th, Fr} then Work[E07, d] = 0 endif
);

% E08 can't work on Mo, Tu, Wed and Th

constraint forall (d in Days) (
  if d in {Tu, We, Th, Fr} then Work[E08, d] = 0 endif
);

% For all employees minimum amount of hours by day is 7
% If employees are not off

constraint forall (e in Employees, d in Days) (
  if Work[e, d] != 0 then Work[e, d] >= 7 endif
);

% Employees with a Contract >= 35 must have exactly 2 days off

constraint forall (e in Employees) (
  if Contracts[e] >= 35 then exactly(2, Work[e, Days], 0) endif
);

% Employees must only work the amount of hours in their contract

constraint forall (e in Employees) (
  sum (d in Days) (Work[e,d]) = Contracts[e]
);

% Let's control the amount of employee's day off on We and Fr
% and Sa and Su

constraint forall (d in Days) (
  if d = Sa \/ d = Su then
    at_most(2, Work[Employees, d], 0)
  elseif d = We \/ d = Fr then
    at_most(3, Work[Employees, d], 0)
  else
    at_least(3, Work[Employees, d], 0)
  endif
);


% Personnel effort

constraint forall (d in Days) (
  Personnel_effort[d] = card(Employees) - among(Work[Employees, d], {0})
);

% Hour effort

constraint forall (d in Days) (
  Hour_effort[d] = (sum (e in Employees) (Work[e,d]))
  /\
  Hour_effort[d] >= 37 % (1m + 1e) and (1m + 2e)
);

% Productivity

constraint forall(d in Days) (
  Productivity[d] = (Budget[d] div Hour_effort[d])
   /\
  Productivity[d] > 40
);


% Solve

solve satisfy;
% solve maximize Productivity;


% Output

output [if d == Mo then show(Employees[e]) ++ "\t\t" else "" endif ++
    show(Days[d]) ++ ":" ++ show(Work[e,d]) ++
    if d == Su then "\n" else "\t" endif
    | e in Employees, d in Days ] ++
   [if d == Mo then "\nBudget\t\t" else "" endif ++
    show(Days[d]) ++ ":" ++ show(Budget[d]) ++ "\t"
    | d in Days ] ++
   [if d == Mo then "\nProd\t\t" else "" endif ++
    show(Days[d]) ++ ":" ++ show(Productivity[d]) ++ "\t"
    | d in Days ] ++
   [if d == Mo then "\nEffort (P)\t" else "" endif ++
    show(Days[d]) ++ ":" ++ show(Personnel_effort[d]) ++ "\t"
    | d in Days ] ++
   [if d == Mo then "\nEffort (h)\t" else "" endif ++
    show(Days[d]) ++ ":" ++ show(Hour_effort[d]) ++ "\t"
    | d in Days ];

1 个答案:

答案 0 :(得分:0)

正如hakank建议的那样,您需要一个函数来进行优化。最简单的方法就是优化生产力的总和:

solve maximize sum(d in Days) (Productivity[d]);

如果愿意,可以添加更复杂的功能。