more reindent
This commit is contained in:
@@ -21,10 +21,8 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
|
||||
namespace FactoryProject
|
||||
{
|
||||
public class Task
|
||||
{
|
||||
namespace FactoryProject {
|
||||
public class Task {
|
||||
public int Id { get; private set; }
|
||||
public int TaskType { get; private set; }
|
||||
public int LocationId { get; private set; }
|
||||
@@ -32,8 +30,7 @@ public class Task
|
||||
public int TaskPosition { get; private set; }
|
||||
|
||||
public Task(int id, int taskType, int locationIndex, int taskPosition,
|
||||
Dictionary<int,int> durations)
|
||||
{
|
||||
Dictionary<int,int> durations) {
|
||||
Id = id;
|
||||
TaskType = taskType;
|
||||
LocationId = locationIndex;
|
||||
@@ -41,22 +38,18 @@ public class Task
|
||||
TaskPosition = taskPosition;
|
||||
}
|
||||
|
||||
public Task(int id, int taskType, int locationIndex, int taskPosition)
|
||||
{
|
||||
public Task(int id, int taskType, int locationIndex, int taskPosition) {
|
||||
Id = id;
|
||||
TaskType = taskType;
|
||||
LocationId = locationIndex;
|
||||
TaskPosition = taskPosition;
|
||||
Durations = new Dictionary<int,int>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class WorkLocation
|
||||
{
|
||||
public class WorkLocation {
|
||||
public int Id { get; private set; }
|
||||
public int NbTasks
|
||||
{
|
||||
public int NbTasks {
|
||||
get { Debug.Assert(Tasks != null); return Tasks.Length; }
|
||||
set { Debug.Assert(Tasks == null); Tasks = new Task[value]; }
|
||||
}
|
||||
@@ -68,15 +61,13 @@ public class WorkLocation
|
||||
}
|
||||
}
|
||||
|
||||
public class Tool
|
||||
{
|
||||
public class Tool {
|
||||
public int Id { get; private set; }
|
||||
public HashSet<int> TaskTypes { get; set; }
|
||||
public int[,] TravellingTime { get; set; }
|
||||
public int InitialLocationId { get; set; }
|
||||
|
||||
public Tool(int index, int initialLocation = 0)
|
||||
{
|
||||
public Tool(int index, int initialLocation = 0) {
|
||||
Id = index;
|
||||
InitialLocationId = initialLocation;
|
||||
TaskTypes = new HashSet<int>();
|
||||
@@ -89,11 +80,9 @@ public class Tool
|
||||
public bool CanPerformTaskType(int taskType) {
|
||||
return TaskTypes.Contains(taskType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class FactoryDescription
|
||||
{
|
||||
public class FactoryDescription {
|
||||
public Tool[] Tools { get; private set; }
|
||||
public WorkLocation[] Locations { get; private set; }
|
||||
|
||||
@@ -111,8 +100,7 @@ public class FactoryDescription
|
||||
|
||||
// horizon equal to 2 weeks (in minutes).
|
||||
public FactoryDescription(int nbTools, int nbLocations, int nbTaskPerCycle,
|
||||
int horizon = 14*24*60)
|
||||
{
|
||||
int horizon = 14*24*60) {
|
||||
Debug.Assert(nbTools > 0);
|
||||
Debug.Assert(nbLocations > 0);
|
||||
Debug.Assert(nbTaskPerCycle > 0);
|
||||
@@ -130,8 +118,7 @@ public class FactoryDescription
|
||||
InspectionStarts = new long[] { -1, 600, 1200, 1800, 2400, 2800 };
|
||||
}
|
||||
|
||||
public Tool[] getToolPerTaskType(int taskType)
|
||||
{
|
||||
public Tool[] getToolPerTaskType(int taskType) {
|
||||
var elements = from tool in Tools
|
||||
where tool.CanPerformTaskType(taskType)
|
||||
select tool;
|
||||
@@ -153,58 +140,44 @@ public class FactoryDescription
|
||||
|
||||
|
||||
// TODO: This should be enhanced
|
||||
public void SanityCheck()
|
||||
{
|
||||
public void SanityCheck() {
|
||||
foreach (Tool tool in Tools) {
|
||||
Debug.Assert(tool.TravellingTime.GetLength(0) == NbWorkLocations);
|
||||
Debug.Assert(tool.TravellingTime.GetLength(1) == NbWorkLocations);
|
||||
for (int i = 0; i < NbWorkLocations; i++)
|
||||
Debug.Assert(tool.TravellingTime[i, i] == 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interface DataReader
|
||||
{
|
||||
interface DataReader {
|
||||
FactoryDescription FetchData();
|
||||
}
|
||||
|
||||
public class SmallSyntheticData : DataReader
|
||||
{
|
||||
public class SmallSyntheticData : DataReader {
|
||||
|
||||
public SmallSyntheticData()
|
||||
{
|
||||
}
|
||||
public SmallSyntheticData() {}
|
||||
|
||||
public FactoryDescription FetchData()
|
||||
{
|
||||
public FactoryDescription FetchData() {
|
||||
// deterministic seed for result reproducibility
|
||||
Random randomDuration = new Random(2);
|
||||
|
||||
// FactoryDescription(nbTools, nblocations, nbTasks per cycle)
|
||||
FactoryDescription factoryDescription = new FactoryDescription(5, 4, 3);
|
||||
|
||||
#region Creating travellingTime
|
||||
|
||||
// Travelling time and distance are temporarily identical and they
|
||||
// are no different for different tools
|
||||
int[,] travellingTime = new int[factoryDescription.NbWorkLocations,
|
||||
factoryDescription.NbWorkLocations];
|
||||
for (int i = 0; i < travellingTime.GetLength(0); i++)
|
||||
{
|
||||
for (int j = 0; j < travellingTime.GetLength(1); j++)
|
||||
{
|
||||
for (int i = 0; i < travellingTime.GetLength(0); i++) {
|
||||
for (int j = 0; j < travellingTime.GetLength(1); j++) {
|
||||
if (i == j)
|
||||
travellingTime[i, j] = 0;
|
||||
else
|
||||
travellingTime[i, j] = (5 * Math.Abs(i - j)) * 10;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Tool Description
|
||||
factoryDescription.Tools[0].AddTaskType(0);
|
||||
factoryDescription.Tools[1].AddTaskType(0);
|
||||
factoryDescription.Tools[2].AddTaskType(1);
|
||||
@@ -214,27 +187,20 @@ public class SmallSyntheticData : DataReader
|
||||
|
||||
foreach (Tool tool in factoryDescription.Tools)
|
||||
tool.TravellingTime = travellingTime;
|
||||
#endregion
|
||||
|
||||
#region Work Location Description
|
||||
|
||||
int c = 0;
|
||||
int nbCyclePerWorkLocation = 2;
|
||||
int[] boll = new int[100];
|
||||
for (int i = 0; i < factoryDescription.NbWorkLocations; i++)
|
||||
{
|
||||
for (int i = 0; i < factoryDescription.NbWorkLocations; i++) {
|
||||
factoryDescription.Locations[i].NbTasks =
|
||||
nbCyclePerWorkLocation * factoryDescription.NbTaskPerCycle;
|
||||
for (int j = 0; j < nbCyclePerWorkLocation; j++)
|
||||
{
|
||||
for (int k = 0; k < factoryDescription.NbTaskPerCycle; k++)
|
||||
{
|
||||
for (int j = 0; j < nbCyclePerWorkLocation; j++) {
|
||||
for (int k = 0; k < factoryDescription.NbTaskPerCycle; k++) {
|
||||
Task t = new Task(c, k, i, k + j * factoryDescription.NbTaskPerCycle);
|
||||
|
||||
// Filling in tool-dependent durations
|
||||
Tool[] compatibleTools = factoryDescription.getToolPerTaskType(k);
|
||||
foreach (Tool tool in compatibleTools)
|
||||
{
|
||||
foreach (Tool tool in compatibleTools) {
|
||||
boll[c] = randomDuration.Next(13, 17) * 10; ;
|
||||
t.Durations[tool.Id] = boll[c];
|
||||
}
|
||||
@@ -244,35 +210,26 @@ public class SmallSyntheticData : DataReader
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
factoryDescription.SanityCheck();
|
||||
|
||||
return factoryDescription;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class RandomSelectToolHeuristic : NetDecisionBuilder
|
||||
{
|
||||
public class RandomSelectToolHeuristic : NetDecisionBuilder {
|
||||
|
||||
private FactoryScheduling factoryScheduling;
|
||||
private Random rnd;
|
||||
|
||||
public RandomSelectToolHeuristic(FactoryScheduling factoryScheduling,
|
||||
int seed)
|
||||
{
|
||||
int seed) {
|
||||
this.factoryScheduling = factoryScheduling;
|
||||
// deterministic seed for result reproducibility
|
||||
this.rnd = new Random(seed);
|
||||
}
|
||||
|
||||
public override Decision Next(Solver solver)
|
||||
{
|
||||
foreach (IntVar var in factoryScheduling.SelectedTool)
|
||||
{
|
||||
if (!var.Bound())
|
||||
{
|
||||
public override Decision Next(Solver solver) {
|
||||
foreach (IntVar var in factoryScheduling.SelectedTool) {
|
||||
if (!var.Bound()) {
|
||||
int min = (int) var.Min();
|
||||
int max = (int) var.Max();
|
||||
int rndVal = rnd.Next(min, max + 1);
|
||||
@@ -283,25 +240,20 @@ public class RandomSelectToolHeuristic : NetDecisionBuilder
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TaskAlternative {
|
||||
|
||||
public Task Task { get; private set; }
|
||||
public IntVar ToolVar { get; set; }
|
||||
public List<IntervalVar> Intervals { get; private set; }
|
||||
|
||||
public TaskAlternative(Task t)
|
||||
{
|
||||
public TaskAlternative(Task t) {
|
||||
Task = t;
|
||||
Intervals = new List<IntervalVar>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class FactoryScheduling
|
||||
{
|
||||
public class FactoryScheduling {
|
||||
private FactoryDescription factoryData;
|
||||
private Solver solver;
|
||||
|
||||
@@ -358,7 +310,7 @@ public class FactoryScheduling
|
||||
IntVar[][] endTimes;
|
||||
|
||||
|
||||
public FactoryScheduling(FactoryDescription data){
|
||||
public FactoryScheduling(FactoryDescription data) {
|
||||
factoryData = data;
|
||||
}
|
||||
|
||||
@@ -403,8 +355,7 @@ public class FactoryScheduling
|
||||
//if it is a inspection, we make sure there are no transitiontimes
|
||||
if (tool.CanPerformTaskType(factoryData.Inspection))
|
||||
tool2TransitionTimes[t].Add(null);
|
||||
else
|
||||
{
|
||||
else {
|
||||
int[,] tt = tool.TravellingTime;
|
||||
|
||||
SequenceVar seq = allToolSequences[t];
|
||||
@@ -436,39 +387,35 @@ public class FactoryScheduling
|
||||
// this is the virtual location for unperformed tasks
|
||||
taskIndex2locationId[s + 1] = factoryData.NbWorkLocations;
|
||||
|
||||
|
||||
#region Time Matrix Composition
|
||||
// Build the travelling time matrix with the additional virtual location
|
||||
int[][] ttWithVirtualLocation =
|
||||
new int[factoryData.NbWorkLocations + 1][];
|
||||
for (int d1 = 0; d1 < ttWithVirtualLocation.Length; d1++) {
|
||||
ttWithVirtualLocation[d1] = new int[factoryData.NbWorkLocations + 1];
|
||||
for (int d2 = 0; d2 < ttWithVirtualLocation.Length; d2++)
|
||||
if (d1 == factoryData.NbWorkLocations)
|
||||
if (d1 == factoryData.NbWorkLocations) {
|
||||
ttWithVirtualLocation[d1][d2] = 0;
|
||||
else
|
||||
ttWithVirtualLocation[d1][d2] = (d2 == factoryData.NbWorkLocations) ? 0 : tt[d1, d2];
|
||||
} else {
|
||||
ttWithVirtualLocation[d1][d2] =
|
||||
(d2 == factoryData.NbWorkLocations) ? 0 : tt[d1, d2];
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
for (int i = 0; i < nextLocation.Length; i++) {
|
||||
// this is the next-location associated with the i-th task
|
||||
nextLocation[i] =
|
||||
solver.MakeElement(taskIndex2locationId, seq.Next(i)).Var();
|
||||
solver.MakeElement(taskIndex2locationId, seq.Next(i )).Var();
|
||||
|
||||
int d = (i == 0)? tool.InitialLocationId : tasks[toolIntervalVar2TaskId[t][i - 1]].LocationId;
|
||||
if (i == 0)
|
||||
{
|
||||
int d = (i == 0) ? tool.InitialLocationId
|
||||
: tasks[toolIntervalVar2TaskId[t][i - 1]].LocationId;
|
||||
if (i == 0) {
|
||||
// To be changed - right now we don't have meaningful indata
|
||||
// of previous location Ugly way of setting initial travel
|
||||
// time to = 0, as this is how we find common grounds
|
||||
// between benchmark algorithm and this
|
||||
tool2TransitionTimes[t].Add(solver.MakeElement(
|
||||
new int[ttWithVirtualLocation[d].Length], nextLocation[i]).Var());
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
tool2TransitionTimes[t].Add(solver.MakeElement(
|
||||
ttWithVirtualLocation[d], nextLocation[i]).Var());
|
||||
}
|
||||
@@ -484,8 +431,7 @@ public class FactoryScheduling
|
||||
// previous task for the current tool
|
||||
endTimes[t][0] = solver.MakeIntConst(0);
|
||||
|
||||
for (int i = 0; i < s; i++)
|
||||
{
|
||||
for (int i = 0; i < s; i++) {
|
||||
startingTimes[t][i + 1] = tool2Task[t][i].SafeStartExpr(-1).Var();
|
||||
endTimes[t][i + 1] = tool2Task[t][i].SafeEndExpr(-1).Var();
|
||||
}
|
||||
@@ -495,18 +441,16 @@ public class FactoryScheduling
|
||||
|
||||
// Enforce (or not) that each task is separated by the
|
||||
// transition time to the next task
|
||||
for (int i = 0; i < nextLocation.Length; i++)
|
||||
{
|
||||
for (int i = 0; i < nextLocation.Length; i++) {
|
||||
IntVar nextStart =
|
||||
solver.MakeElement(startingTimes[t], seq.Next(i)).Var();
|
||||
solver.MakeElement(startingTimes[t], seq.Next(i).Var()).Var();
|
||||
if(postTransitionsConstraint)
|
||||
solver.Add(endTimes[t][i] + tool2TransitionTimes[t][i] <= nextStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Model()
|
||||
{
|
||||
private void Model() {
|
||||
/* Building basic task data structures */
|
||||
for (int i = 0; i < tasks.Length; i++) {
|
||||
|
||||
@@ -515,7 +459,8 @@ public class FactoryScheduling
|
||||
taskStructures[i] = new TaskAlternative(tasks[i]);
|
||||
|
||||
/* Container to use when posting constraints */
|
||||
location2Task[tasks[i].LocationId][tasks[i].TaskPosition] = taskStructures[i];
|
||||
location2Task[tasks[i].LocationId][tasks[i].TaskPosition] =
|
||||
taskStructures[i];
|
||||
|
||||
/* Get task type */
|
||||
int taskType = tasks[i].TaskType;
|
||||
@@ -536,18 +481,18 @@ public class FactoryScheduling
|
||||
string name = "J " + tasks[i].Id + " [" + toolId + "]";
|
||||
|
||||
IntervalVar intervalVar;
|
||||
if (taskType == factoryData.Inspection)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
intervalVar.SafeStartExpr(-1).Var().SetValues(
|
||||
factoryData.InspectionStarts);
|
||||
} else {
|
||||
intervalVar = solver.MakeFixedDurationIntervalVar(
|
||||
0, horizon, duration, optional, name);
|
||||
}
|
||||
|
||||
taskStructures[i].Intervals.Add(intervalVar);
|
||||
@@ -561,30 +506,33 @@ public class FactoryScheduling
|
||||
/* 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);
|
||||
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);
|
||||
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++){
|
||||
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++){
|
||||
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);
|
||||
Constraint precedence = solver.MakeIntervalVarRelation(
|
||||
task2Alternative, Solver.STARTS_AFTER_END, task1Alternative);
|
||||
solver.Add(precedence);
|
||||
}
|
||||
}
|
||||
@@ -596,9 +544,9 @@ public class FactoryScheduling
|
||||
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);
|
||||
if (!factoryData.Tools[t].CanPerformTaskType(factoryData.Inspection)) {
|
||||
DisjunctiveConstraint ct =
|
||||
solver.MakeDisjunctiveConstraint(tool2Task[t].ToArray(), name);
|
||||
solver.Add(ct);
|
||||
allToolSequences[t] = ct.SequenceVar();
|
||||
}
|
||||
@@ -616,7 +564,6 @@ public class FactoryScheduling
|
||||
/* Objective: minimize the makespan (maximum end times of all tasks) */
|
||||
makespan = solver.MakeMax(intervalEnds.ToArray()).Var();
|
||||
objective = solver.MakeMinimize(makespan, 1);
|
||||
|
||||
}
|
||||
|
||||
private void Search(){
|
||||
@@ -659,14 +606,13 @@ public class FactoryScheduling
|
||||
}
|
||||
}
|
||||
|
||||
public void Solve(){
|
||||
public void Solve() {
|
||||
Init();
|
||||
Model();
|
||||
Search();
|
||||
}
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
public static void Main(string[] args) {
|
||||
FactoryScheduling scheduling =
|
||||
new FactoryScheduling(new SmallSyntheticData().FetchData());
|
||||
scheduling.Solve();
|
||||
|
||||
Reference in New Issue
Block a user