1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.

122 lines
4.2 KiB
MiniZinc

include "globals.mzn";
%%% Date file
% include "skill_allocation_mzn_4d_1.dzn";
% include "skill_allocation_mzn_4d_2.dzn";
% include "skill_allocation_mzn_5d_1.dzn";
% include "skill_allocation_mzn_5d_2.dzn";
% include "skill_allocation_mzn_5d_3.dzn";
% include "skill_allocation_mzn_2w_1.dzn";
% include "skill_allocation_mzn_2w_2.dzn";
% include "skill_allocation_mzn_1m_1.dzn";
% include "skill_allocation_mzn_1m_2.dzn";
% include "skill_allocation_mzn_1m_3.dzn";
% include "skill_allocation_mzn_2m_1.dzn";
% include "skill_allocation_mzn_2m_2.dzn";
% include "skill_allocation_mzn_2m_3.dzn";
% include "skill_allocation_mzn_3m_1.dzn";
% include "skill_allocation_mzn_3m_2.dzn";
% include "skill_allocation_mzn_3m_3.dzn";
%%%%%% Input %%%%%%%
int: nNewSkillsPerPerson; % Number of new skills a person is allowed to learn
int: nTrainingCap = -1; % Number of training allowed in during the considered period in total. This is to put a cap on the training budget.
int: nInterstateCap = -1; % -1 - no cap
int: nOverseasCap = 5; % -1 - no cap
int: nMaxJobs; % Maximum number of jobs a person is allowed to perform, 0 - switch off the constraint
int: nMinJobs = 0; % Minimum number of jobs a person is allowed to perform, 0 - switch off the constraint
bool: allEng = false; % Allow an engineer to perform any job, i.e. skill matching contraint is not applied.
%%%%%%%%%%%%%%%%%
%%% All Skills
array[int] of string: sSkills;
set of int: SKILLS = index_set(sSkills);
%%% Training
set of int: TRAINING = 1..nNewSkillsPerPerson;
%%% Employee data
array[int,int] of int: engineer_skills;
array[int] of int: engineer_location; % Postcode
set of int: ENGS = index_set_1of2(engineer_skills);
%%% Service Calls
array[int,int] of int: jobs;
set of int: JOBS = index_set_1of2(jobs);
%%% DECISION VARIABLES
array[JOBS] of var ENGS: allocations;
%%% Set of possible engineers for each job
array[ENGS,TRAINING] of var 0..0 union SKILLS: new_skills;
constraint forall(e in ENGS, t in TRAINING)(
let {
set of int: NEWSKILLS = {s | s in SKILLS where engineer_skills[e,s]==0}
} in
new_skills[e,t] in 0..0 union NEWSKILLS
);
constraint if allEng then true else forall(i in JOBS)(
let {
set of int: POSENGS = {e | e in ENGS where engineer_skills[e,jobs[i,1]] == 1},
} in
(allocations[i] in POSENGS)
\/ exists(e in ENGS, t in TRAINING)(jobs[i,1] == new_skills[e,t] /\ allocations[i]==e)
) endif;
constraint if nTrainingCap < 0 then true else sum(e in ENGS, t in TRAINING)(
new_skills[e,t] > 0
)<=nTrainingCap
endif;
%%% Number of jobs allowed per engineer
constraint
if nMaxJobs == 0 then true else forall(e in ENGS)(
sum(i in JOBS)( allocations[i] == e) <= nMaxJobs )
endif
;
constraint
if nMinJobs <= 0 then true else forall(e in ENGS)(
sum(i in JOBS)( allocations[i] == e) >= nMinJobs )
endif
;
%%% Number of jobs overseas jobs per engineer
constraint
if nOverseasCap < 0 then true else forall(e in ENGS)(
sum(i in JOBS)( (allocations[i] == e) * (jobs[i,5]==1) ) <= nOverseasCap )
endif
;
%%% Number of jobs interstate jobs per engineer
constraint
if nInterstateCap < 0 then true else forall(e in ENGS where engineer_location[e] > 0)(
sum(i in JOBS)( (allocations[i] == e) * not (ceil(jobs[i,4]/1000) == ceil(engineer_location[e]/1000) ) ) <= nInterstateCap )
endif;
var int: objective;
constraint objective == sum(e in ENGS, t in TRAINING)(
new_skills[e,t] > 0
);
solve
::seq_search( [
int_search([new_skills[e,t] | t in TRAINING, e in ENGS],input_order, indomain_min, complete),
int_search([allocations[i] | i in JOBS],input_order, indomain_min, complete),
])
minimize objective;
output [
"allocations = array1d(\(JOBS), \(allocations));\n",
"new_skills = array2d(\(ENGS), \(TRAINING), \(new_skills));\n",
"objective = \(objective);\n"
];
% output
% ["Eng \(e): " ++ show( sort([i| i in JOBS where fix(allocations[i])==e])) ++ "\n" | e in ENGS where length([i | i in JOBS where fix(allocations[i])==e])>0 ] ++
% ["Allocations: \(allocations)\n" ] ++
% ["New Skill of Eng \(e): " ++ show( sort([new_skills[e,t]| t in TRAINING where fix(new_skills[e,t])>0])) ++ "\n" | e in ENGS where length([new_skills[e,t]| t in TRAINING where fix(new_skills[e,t])>0])>0 ] ++
% ["Total Jobs - \(card(JOBS))\n"] ++
% ["Obj - NoOfTraining: \(objective)"];