private void Init() { horizon = factoryData.Horizon; solver = new Solver("Factory Scheduling"); tasks = factoryData.getFlatTaskList(); taskTypes = factoryData.getTaskTypes(); taskStructures = new TaskAlternative[tasks.Length]; location2Task = new TaskAlternative[factoryData.NbWorkLocations][]; tool2Task = new List <IntervalVar> [factoryData.NbTools]; toolIntervalVar2TaskId = new List <int> [factoryData.NbTools]; tool2TransitionTimes = new List <IntVar> [factoryData.NbTools]; taskType2Tool = new List <Tool> [taskTypes.Length]; selectedTool = new List <IntVar>(); for (int tt = 0; tt < taskTypes.Length; tt++) { taskType2Tool[tt] = new List <Tool>(); } foreach (Tool tool in factoryData.Tools) { foreach (int taskType in tool.TaskTypes) { taskType2Tool[taskType].Add(tool); } } for (int d = 0; d < factoryData.NbWorkLocations; d++) { location2Task[d] = new TaskAlternative[factoryData.Locations[d].NbTasks]; } for (int t = 0; t < factoryData.NbTools; t++) { tool2Task[t] = new List <IntervalVar>(); toolIntervalVar2TaskId[t] = new List <int>(); tool2TransitionTimes[t] = new List <IntVar>(); } allToolSequences = new SequenceVar[factoryData.NbTools - 1]; startingTimes = new IntVar[factoryData.NbTools - 1][]; endTimes = new IntVar[factoryData.NbTools - 1][]; }
private void Model() { /* Building basic task data structures */ for (int i = 0; i < tasks.Length; i++) { /* Create a new set of possible IntervalVars & IntVar to decide * which one (and only 1) is performed */ taskStructures[i] = new TaskAlternative(tasks[i]); /* Container to use when posting constraints */ location2Task[tasks[i].LocationId][tasks[i].TaskPosition] = taskStructures[i]; /* Get task type */ int taskType = tasks[i].TaskType; /* Possible tool for this task */ List <Tool> tools = taskType2Tool[taskType]; bool optional = tools.Count > 1; /* List of boolean variables. If performedOnTool[t] == true then * the task is performed on tool t */ List <IntVar> performedOnTool = new List <IntVar>(); for (int t = 0; t < tools.Count; t++) { /* Creating an IntervalVar. If tools.Count > 1 the intervalVar * is *OPTIONAL* */ int toolId = tools[t].Id; Debug.Assert(tasks[i].Durations.ContainsKey(toolId)); int duration = tasks[i].Durations[toolId]; string name = "J " + tasks[i].Id + " [" + toolId + "]"; IntervalVar intervalVar; if (taskType == factoryData.Inspection) { /* We set a 0 time if the task is an inspection */ duration = 0; intervalVar = solver.MakeFixedDurationIntervalVar(0, horizon, duration, optional, name); IntVar start = intervalVar.SafeStartExpr(-1).Var(); intervalVar.SafeStartExpr(-1).Var().SetValues(factoryData.InspectionStarts); } else { intervalVar = solver.MakeFixedDurationIntervalVar(0, horizon, duration, optional, name); } taskStructures[i].Intervals.Add(intervalVar); tool2Task[toolId].Add(intervalVar); toolIntervalVar2TaskId[toolId].Add(i); /* Collecting all the bool vars, even if they are optional */ performedOnTool.Add(intervalVar.PerformedExpr().Var()); } /* Linking the bool var to a single integer variable: */ /* if alternativeToolVar == t <=> performedOnTool[t] == true */ string alternativeName = "J " + tasks[i].Id; IntVar alternativeToolVar = solver.MakeIntVar(0, tools.Count - 1, alternativeName); taskStructures[i].ToolVar = alternativeToolVar; solver.Add(solver.MakeMapDomain(alternativeToolVar, performedOnTool.ToArray())); Debug.Assert(performedOnTool.ToArray().Length == alternativeToolVar.Max() + 1); selectedTool.Add(alternativeToolVar); } /* Creates precedences on a work Location in order to enforce a * fully ordered set within the same location */ for (int d = 0; d < location2Task.Length; d++) { for (int i = 0; i < location2Task[d].Length - 1; i++) { TaskAlternative task1 = location2Task[d][i]; TaskAlternative task2 = location2Task[d][i + 1]; /* task1 must end before task2 starts */ /* Adding precedence for each possible alternative pair */ for (int t1 = 0; t1 < task1.Intervals.Count(); t1++) { IntervalVar task1Alternative = task1.Intervals[t1]; for (int t2 = 0; t2 < task2.Intervals.Count(); t2++) { IntervalVar task2Alternative = task2.Intervals[t2]; Constraint precedence = solver.MakeIntervalVarRelation( task2Alternative, Solver.STARTS_AFTER_END, task1Alternative); solver.Add(precedence); } } } } /* Adds disjunctive constraints on unary resources, and creates * sequence variables. */ for (int t = 0; t < factoryData.NbTools; t++) { string name = "Tool " + t; if (!factoryData.Tools[t].CanPerformTaskType(factoryData.Inspection)) { DisjunctiveConstraint ct = solver.MakeDisjunctiveConstraint(tool2Task[t].ToArray(), name); solver.Add(ct); allToolSequences[t] = ct.SequenceVar(); } PostTransitionTimeConstraints(t, true); } /* Collecting all tasks end for makespan objective function */ List <IntVar> intervalEnds = new List <IntVar>(); for (int i = 0; i < tasks.Length; i++) { foreach (IntervalVar var in taskStructures[i].Intervals) { intervalEnds.Add(var.SafeEndExpr(-1).Var()); } } /* Objective: minimize the makespan (maximum end times of all tasks) */ makespan = solver.MakeMax(intervalEnds.ToArray()).Var(); objective = solver.MakeMinimize(makespan, 1); }