MiniZinc: как максимизировать производительность для каждого дня недели - PullRequest
0 голосов
/ 31 августа 2018

Я хочу назначать сотрудников в магазине и максимизировать переменную производительности для каждого дня недели. Этот показатель производительности вычисляется как целевой бюджет на день, деленный на количество часов, отработанных в этот день.

Моя модель MiniZinc работает следующим образом.

Использование «решить удовлетворить» работает, но не оптимизирует количество часов или (персонал) в зависимости от целевого бюджета. Например, я хочу иметь меньше часов, когда целевой гаджет маленький.

«решить максимизировать производительность» не работает, потому что это массив.

Есть идеи?


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 голосов
/ 17 сентября 2018

Как рекомендует hakank, вам нужна одна функция для оптимизации. Самый простой - оптимизировать сумму производительности:

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

Вы можете добавить более сложную функцию, если хотите.

...