MiniZinc是否支持多维数组的数组?附员工排班建模咨询
Hi Nicolas! Great question—MiniZinc absolutely supports nested/multidimensional arrays, which are perfect for modeling your employee scheduling scenario. Let’s walk through how to set this up and add your required constraint step by step.
Declaring Your Multidimensional Array
First, let’s define the scope of your problem with constants (adjust these to match your actual data):
% Define core problem parameters int: NUM_EMPLOYEES = 5; % Total number of employees int: NUM_WEEKS = 4; % Number of weeks in your scheduling period int: NUM_WORKDAYS = 5; % e.g., Monday to Friday
You have two main options for declaring the array structure, both of which work for your use case:
Option 1: Fixed-Dimension 3D Array (Most Common)
This is the simplest approach for uniform scheduling (all employees have the same number of weeks/workdays):
% 3D array: [Employee Index, Week Index, Workday Index] -> 0/1 (unavailable/available) array[1..NUM_EMPLOYEES, 1..NUM_WEEKS, 1..NUM_WORKDAYS] of var 0..1: availability;
Each element availability[e, w, d] represents whether employee e is available on day d of week w (1 means available, 0 means unavailable).
Option 2: Array of Arrays (For Variable Sizes)
If you ever need flexibility (e.g., some employees have different scheduling periods), you can declare an array of arrays of arrays:
% Nested arrays: each employee has an array of weeks, each week has an array of workdays array[1..NUM_EMPLOYEES] of array[1..NUM_WEEKS] of array[1..NUM_WORKDAYS] of var 0..1: availability;
Access works similarly here: availability[e][w][d] is equivalent to availability[e, w, d] from the fixed-dimension array.
Initializing with Your Example Data
If you have pre-defined availability data (like your employee 1 example), you can initialize a constant array and link it to your decision variable:
% Example availability data for your scenario array[1..NUM_EMPLOYEES, 1..NUM_WEEKS, 1..NUM_WORKDAYS] of int: availability_data = [| % Employee 1: Week 1 (Mon/Fri available), Week 2 (Tue/Thu available) [|1,0,0,0,1|, |0,1,0,1,0|, |0,0,0,0,0|, |0,0,0,0,0|], % Add data for other employees here [|0,0,1,0,0|, |0,0,0,0,1|, |1,1,0,0,0|, |0,0,0,1,1|], % ... rest of employees |]; % Link the data to your decision variable array constraint forall(e in 1..NUM_EMPLOYEES, w in 1..NUM_WEEKS, d in 1..NUM_WORKDAYS) ( availability[e,w,d] = availability_data[e,w,d] );
Adding the "At Least One Available Day Per Week" Constraint
This is straightforward using MiniZinc's sum function and forall loops to enforce the rule across all employees and weeks:
% Core constraint: Every employee has at least 1 available day in each week constraint forall(e in 1..NUM_EMPLOYEES, w in 1..NUM_WEEKS) ( sum(d in 1..NUM_WORKDAYS) (availability[e,w,d]) >= 1 );
This loop checks that for every employee e and week w, the total number of available days (sum of 1s) is at least 1.
Bonus: Improve Readability with Enums
For more intuitive code, replace integer indices with named enums. This makes your model easier to debug and maintain:
% Use enums for meaningful labels enum Workday = {Mon, Tue, Wed, Thu, Fri}; enum Employee = {Alice, Bob, Charlie, Dana, Eve}; enum Week = {Week1, Week2, Week3, Week4}; % Array with named indices array[Employee, Week, Workday] of var 0..1: availability; % Constraint with enum ranges constraint forall(e in Employee, w in Week) ( sum(d in Workday) (availability[e,w,d]) >= 1 );
Now you can write availability[Alice, Week1, Mon] = 1 instead of remembering integer indices!
Hope this helps you get started with your scheduling model. Feel free to tweak the parameters and add additional constraints (like maximum workdays per week or consecutive rest rules) as needed.
内容的提问来源于stack exchange,提问作者Nicolaz

