Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2521_ProblemRefactoring/HeuristicLab.Problems.Scheduling/3.3/JobShopSchedulingProblem.cs @ 17745

Last change on this file since 17745 was 17745, checked in by mkommend, 4 years ago

#2971: Added first draft of results implementation and problem adaptation.

File size: 11.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Drawing;
24using System.Linq;
25using System.Threading;
26using HEAL.Attic;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Encodings.PermutationEncoding;
31using HeuristicLab.Encodings.ScheduleEncoding;
32using HeuristicLab.Optimization;
33using HeuristicLab.Parameters;
34using HeuristicLab.Problems.Instances;
35
36namespace HeuristicLab.Problems.Scheduling {
37  public enum JSSPObjective { Makespan, Tardiness }
38
39  [Item("Job Shop Scheduling Problem (JSSP)", "Represents a standard Job Shop Scheduling Problem")]
40  [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 120)]
41  [StorableType("d6c72bd1-c6cc-4efb-9cc5-b73bb3845799")]
42  public sealed class JobShopSchedulingProblem : SingleObjectiveProblem<IScheduleEncoding, IScheduleSolution>, IProblemInstanceConsumer<JSSPData>, IProblemInstanceExporter<JSSPData>, IStorableContent {
43    #region Default Instance
44    private static readonly JSSPData DefaultInstance = new JSSPData() {
45      Jobs = 10,
46      Resources = 10,
47      BestKnownQuality = 930,
48      ProcessingTimes = new double[,] {
49          { 29, 78,  9, 36, 49, 11, 62, 56, 44, 21 },
50          { 43, 90, 75, 11, 69, 28, 46, 46, 72, 30 },
51          { 91, 85, 39, 74, 90, 10, 12, 89, 45, 33 },
52          { 81, 95, 71, 99,  9, 52, 85, 98, 22, 43 },
53          { 14,  6, 22, 61, 26, 69, 21, 49, 72, 53 },
54          { 84,  2, 52, 95, 48, 72, 47, 65,  6, 25 },
55          { 46, 37, 61, 13, 32, 21, 32, 89, 30, 55 },
56          { 31, 86, 46, 74, 32, 88, 19, 48, 36, 79 },
57          { 76, 69, 76, 51, 85, 11, 40, 89, 26, 74 },
58          { 85, 13, 61,  7, 64, 76, 47, 52, 90, 45 }
59        },
60      Demands = new int[,] {
61          { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
62          { 0, 2, 4, 9, 3, 1, 6, 5, 7, 8 },
63          { 1, 0, 3, 2, 8, 5, 7, 6, 9, 4 },
64          { 1, 2, 0, 4, 6, 8, 7, 3, 9, 5 },
65          { 2, 0, 1, 5, 3, 4, 8, 7, 9, 6 },
66          { 2, 1, 5, 3, 8, 9, 0, 6, 4, 7 },
67          { 1, 0, 3, 2, 6, 5, 9, 8, 7, 4 },
68          { 2, 0, 1, 5, 4, 6, 8, 9, 7, 3 },
69          { 0, 1, 3, 5, 2, 9, 6, 7, 4, 8 },
70          { 1, 0, 2, 6, 8, 9, 5, 3, 4, 7 }
71        }
72    };
73    #endregion
74
75    public override Image ItemImage {
76      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
77    }
78
79    #region Parameter Properties
80    [Storable] public ReferenceParameter<ItemList<Job>> JobDataParameter { get; private set; }
81    [Storable] public OptionalValueParameter<Schedule> BestKnownSolutionParameter { get; private set; }
82    [Storable] public ReferenceParameter<IntValue> JobsParameter { get; private set; }
83    [Storable] public ReferenceParameter<IntValue> ResourcesParameter { get; private set; }
84    [Storable] public IFixedValueParameter<EnumValue<JSSPObjective>> ObjectiveParameter { get; private set; }
85    #endregion
86
87    #region Properties
88    public ItemList<Job> JobData {
89      get { return JobDataParameter.Value; }
90      set { JobDataParameter.Value = value; }
91    }
92    public Schedule BestKnownSolution {
93      get { return BestKnownSolutionParameter.Value; }
94      set { BestKnownSolutionParameter.Value = value; }
95    }
96    public int Jobs {
97      get { return JobsParameter.Value.Value; }
98      set { JobsParameter.Value.Value = value; }
99    }
100    public int Resources {
101      get { return ResourcesParameter.Value.Value; }
102      set { ResourcesParameter.Value.Value = value; }
103    }
104    public JSSPObjective Objective {
105      get { return ObjectiveParameter.Value.Value; }
106      set { ObjectiveParameter.Value.Value = value; }
107    }
108
109    public new IScheduleEncoding Encoding {
110      get { return base.Encoding; }
111      set { base.Encoding = value; }
112    }
113    #endregion
114
115    [StorableConstructor]
116    private JobShopSchedulingProblem(StorableConstructorFlag _) : base(_) { }
117    [StorableHook(HookType.AfterDeserialization)]
118    private void AfterDeserialization() {
119      RegisterEventHandlers();
120    }
121
122    private JobShopSchedulingProblem(JobShopSchedulingProblem original, Cloner cloner)
123      : base(original, cloner) {
124      JobDataParameter = cloner.Clone(original.JobDataParameter);
125      BestKnownSolutionParameter = cloner.Clone(original.BestKnownSolutionParameter);
126      JobsParameter = cloner.Clone(original.JobsParameter);
127      ResourcesParameter = cloner.Clone(original.ResourcesParameter);
128      ObjectiveParameter = cloner.Clone(original.ObjectiveParameter);
129
130      RegisterEventHandlers();
131    }
132    public override IDeepCloneable Clone(Cloner cloner) {
133      return new JobShopSchedulingProblem(this, cloner);
134    }
135
136    public JobShopSchedulingProblem()
137      : base(new JobSequenceMatrixEncoding()) {
138      Parameters.Add(JobDataParameter = new ReferenceParameter<ItemList<Job>>("JobData", "Jobdata defining the precedence relationships and the duration of the tasks in this JSSP-Instance.", Encoding.JobDataParameter));
139      Parameters.Add(BestKnownSolutionParameter = new OptionalValueParameter<Schedule>("BestKnownSolution", "The best known solution of this JSSP instance."));
140      Parameters.Add(JobsParameter = new ReferenceParameter<IntValue>("Jobs", "The number of jobs used in this JSSP instance.", Encoding.JobsParameter));
141      Parameters.Add(ResourcesParameter = new ReferenceParameter<IntValue>("Resources", "The number of resources used in this JSSP instance.", Encoding.ResourcesParameter));
142      Parameters.Add(ObjectiveParameter = new FixedValueParameter<EnumValue<JSSPObjective>>("Objective", "The objective to use in the evaluation of a schedule.", new EnumValue<JSSPObjective>(JSSPObjective.Makespan)));
143      EncodingParameter.Hidden = false;
144
145      RegisterEventHandlers();
146      Load(DefaultInstance);
147    }
148
149    public override ISingleObjectiveEvaluationResult Evaluate(IScheduleSolution solution, IRandom random, CancellationToken cancellationToken) {
150      var schedule = Encoding.Decode(solution, JobData);
151      switch (Objective) {
152        case JSSPObjective.Makespan:
153          return new SingleObjectiveEvaluationResult(Makespan.Calculate(schedule));
154        case JSSPObjective.Tardiness:
155          return new SingleObjectiveEvaluationResult(MeanTardiness.Calculate(schedule, JobData));
156        default:
157          throw new InvalidOperationException("Objective " + Objective + " unknown");
158      }
159    }
160
161    public override void Analyze(ISingleObjectiveSolutionContext<IScheduleSolution>[] solutionContexts, IRandom random) {
162      base.Analyze(solutionContexts, random);
163
164      //TODO: reimplement code below using results directly
165
166      //bool max = Maximization;
167
168      //int i = -1;
169      //if (!max)
170      //  i = qualities.Select((x, index) => new { index, x }).OrderBy(x => x.x).First().index;
171      //else i = qualities.Select((x, index) => new { index, x }).OrderByDescending(x => x.x).First().index;
172
173      //if (double.IsNaN(BestKnownQuality) ||
174      //    max && qualities[i] > BestKnownQuality ||
175      //    !max && qualities[i] < BestKnownQuality) {
176      //  BestKnownQuality = qualities[i];
177      //  BestKnownSolution = Encoding.Decode(solutions[i], JobData);
178      //}
179      //Schedule bestSolution;
180      //if (results.TryGetValue("Best Scheduling Solution", out var result)) {
181      //  bestSolution = result.Value as Schedule;
182      //} else bestSolution = null;
183
184      //if (bestSolution == null || IsBetter(bestSolution.Quality, qualities[i]))
185      //  results.AddOrUpdateResult("Best Scheduling Solution", Encoding.Decode(solutions[i], JobData));
186    }
187
188    protected override void OnEncodingChanged() {
189      base.OnEncodingChanged();
190      var jobData = (ItemList<Job>)JobData.Clone();
191      var jobs = Jobs;
192      var resources = Resources;
193      Parameters.Remove(JobDataParameter);
194      Parameters.Add(JobDataParameter = new ReferenceParameter<ItemList<Job>>("JobData", "Jobdata defining the precedence relationships and the duration of the tasks in this JSSP-Instance.", Encoding.JobDataParameter));
195      Parameters.Remove(JobsParameter);
196      Parameters.Add(JobsParameter = new ReferenceParameter<IntValue>("Jobs", "The number of jobs used in this JSSP instance.", Encoding.JobsParameter));
197      Parameters.Remove(ResourcesParameter);
198      Parameters.Add(ResourcesParameter = new ReferenceParameter<IntValue>("Resources", "The number of resources used in this JSSP instance.", Encoding.ResourcesParameter));
199      JobData = jobData;
200      Jobs = jobs;
201      Resources = resources;
202
203      RegisterEventHandlers();
204    }
205
206
207    private void RegisterEventHandlers() {
208      ItemListParameterChangeHandler<Job>.Create(JobDataParameter, JobDataOnChanged);
209    }
210
211    private void JobDataOnChanged() {
212      Jobs = JobData.Count;
213      Resources = JobData.SelectMany(x => x.Tasks).Select(x => x.ResourceNr).Distinct().Count();
214    }
215
216
217    #region Problem Instance Handling
218    public void Load(JSSPData data) {
219      var jobData = new ItemList<Job>(data.Jobs);
220      for (int j = 0; j < data.Jobs; j++) {
221        var job = new Job(j, data.DueDates != null ? data.DueDates[j] : double.MaxValue);
222        for (int t = 0; t < data.Resources; t++) {
223          job.Tasks.Add(new Task(t, data.Demands[j, t], j, data.ProcessingTimes[j, t]));
224        }
225        jobData.Add(job);
226      }
227
228      BestKnownQuality = data.BestKnownQuality ?? double.NaN;
229      if (data.BestKnownSchedule != null) {
230        var enc = new JSM(0);
231        for (int i = 0; i < data.Resources; i++) {
232          enc.JobSequenceMatrix.Add(new Permutation(PermutationTypes.Absolute, new int[data.Jobs]));
233          for (int j = 0; j < data.Jobs; j++) {
234            enc.JobSequenceMatrix[i][j] = data.BestKnownSchedule[i, j];
235          }
236        }
237        BestKnownSolution = JSMDecoder.Decode(enc, jobData, JSMDecodingErrorPolicy.RandomPolicy, JSMForcingStrategy.SwapForcing);
238        switch (Objective) {
239          case JSSPObjective.Makespan:
240            BestKnownQuality = Makespan.Calculate(BestKnownSolution);
241            break;
242          case JSSPObjective.Tardiness:
243            BestKnownQuality = MeanTardiness.Calculate(BestKnownSolution, jobData);
244            break;
245        }
246      }
247
248      JobData = jobData;
249      Resources = data.Resources;
250    }
251
252    public JSSPData Export() {
253      var result = new JSSPData {
254        Name = Name,
255        Description = Description,
256        Jobs = Jobs,
257        Resources = Resources,
258        ProcessingTimes = new double[Jobs, Resources],
259        Demands = new int[Jobs, Resources],
260        DueDates = new double[Jobs]
261      };
262
263      foreach (var job in JobData) {
264        var counter = 0;
265        result.DueDates[job.Index] = job.DueDate;
266        foreach (var task in job.Tasks) {
267          result.ProcessingTimes[task.JobNr, counter] = task.Duration;
268          result.Demands[task.JobNr, counter] = task.ResourceNr;
269          counter++;
270        }
271      }
272      return result;
273    }
274    #endregion
275
276  }
277}
Note: See TracBrowser for help on using the repository browser.