Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 17462 was 17462, checked in by abeham, 5 years ago

#2521: worked on JSSP

File size: 11.1 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.ComponentModel;
24using System.Drawing;
25using System.Linq;
26using System.Threading;
27using HEAL.Attic;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31using HeuristicLab.Encodings.PermutationEncoding;
32using HeuristicLab.Encodings.ScheduleEncoding;
33using HeuristicLab.Optimization;
34using HeuristicLab.Parameters;
35using HeuristicLab.Problems.Instances;
36
37namespace HeuristicLab.Problems.Scheduling {
38  public enum JSSPObjective { Makespan, Tardiness }
39
40  [Item("Job Shop Scheduling Problem (JSSP)", "Represents a standard Job Shop Scheduling Problem")]
41  [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 120)]
42  [StorableType("d6c72bd1-c6cc-4efb-9cc5-b73bb3845799")]
43  public sealed class JobShopSchedulingProblem : SingleObjectiveProblem<IScheduleEncoding, IScheduleSolution>, IProblemInstanceConsumer<JSSPData>, IProblemInstanceExporter<JSSPData>, IStorableContent {
44    #region Default Instance
45    private static readonly JSSPData DefaultInstance = new JSSPData() {
46      Jobs = 10,
47      Resources = 10,
48      BestKnownQuality = 930,
49      ProcessingTimes = new double[,] {
50          { 29, 78,  9, 36, 49, 11, 62, 56, 44, 21 },
51          { 43, 90, 75, 11, 69, 28, 46, 46, 72, 30 },
52          { 91, 85, 39, 74, 90, 10, 12, 89, 45, 33 },
53          { 81, 95, 71, 99,  9, 52, 85, 98, 22, 43 },
54          { 14,  6, 22, 61, 26, 69, 21, 49, 72, 53 },
55          { 84,  2, 52, 95, 48, 72, 47, 65,  6, 25 },
56          { 46, 37, 61, 13, 32, 21, 32, 89, 30, 55 },
57          { 31, 86, 46, 74, 32, 88, 19, 48, 36, 79 },
58          { 76, 69, 76, 51, 85, 11, 40, 89, 26, 74 },
59          { 85, 13, 61,  7, 64, 76, 47, 52, 90, 45 }
60        },
61      Demands = new int[,] {
62          { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
63          { 0, 2, 4, 9, 3, 1, 6, 5, 7, 8 },
64          { 1, 0, 3, 2, 8, 5, 7, 6, 9, 4 },
65          { 1, 2, 0, 4, 6, 8, 7, 3, 9, 5 },
66          { 2, 0, 1, 5, 3, 4, 8, 7, 9, 6 },
67          { 2, 1, 5, 3, 8, 9, 0, 6, 4, 7 },
68          { 1, 0, 3, 2, 6, 5, 9, 8, 7, 4 },
69          { 2, 0, 1, 5, 4, 6, 8, 9, 7, 3 },
70          { 0, 1, 3, 5, 2, 9, 6, 7, 4, 8 },
71          { 1, 0, 2, 6, 8, 9, 5, 3, 4, 7 }
72        }
73    };
74    #endregion
75
76    public override Image ItemImage {
77      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
78    }
79   
80    #region Parameter Properties
81    [Storable] public IValueParameter<ItemList<Job>> JobDataParameter { get; private set; }
82    [Storable] public OptionalValueParameter<Schedule> BestKnownSolutionParameter { get; private set; }
83    [Storable] public IFixedValueParameter<IntValue> JobsParameter { get; private set; }
84    [Storable] public IFixedValueParameter<IntValue> ResourcesParameter { get; private set; }
85    [Storable] public IFixedValueParameter<EnumValue<JSSPObjective>> ObjectiveParameter { get; private set; }
86    #endregion
87
88    #region Properties
89    public ItemList<Job> JobData {
90      get { return JobDataParameter.Value; }
91      set { JobDataParameter.Value = value; }
92    }
93    public Schedule BestKnownSolution {
94      get { return BestKnownSolutionParameter.Value; }
95      set { BestKnownSolutionParameter.Value = value; }
96    }
97    public int Jobs {
98      get { return JobsParameter.Value.Value; }
99      set { JobsParameter.Value.Value = value; }
100    }
101    public int Resources {
102      get { return ResourcesParameter.Value.Value; }
103      set { ResourcesParameter.Value.Value = value; }
104    }
105    public JSSPObjective Objective {
106      get { return ObjectiveParameter.Value.Value; }
107      set { ObjectiveParameter.Value.Value = value; }
108    }
109    #endregion
110
111    [StorableConstructor]
112    private JobShopSchedulingProblem(StorableConstructorFlag _) : base(_) { }
113    [StorableHook(HookType.AfterDeserialization)]
114    private void AfterDeserialization() {
115      RegisterEventHandlers();
116    }
117
118    private JobShopSchedulingProblem(JobShopSchedulingProblem original, Cloner cloner)
119      : base(original, cloner) {
120      JobDataParameter = cloner.Clone(original.JobDataParameter);
121      BestKnownSolutionParameter = cloner.Clone(original.BestKnownSolutionParameter);
122      JobsParameter = cloner.Clone(original.JobsParameter);
123      ResourcesParameter = cloner.Clone(original.ResourcesParameter);
124      ObjectiveParameter = cloner.Clone(original.ObjectiveParameter);
125
126      RegisterEventHandlers();
127    }
128    public override IDeepCloneable Clone(Cloner cloner) {
129      return new JobShopSchedulingProblem(this, cloner);
130    }
131
132    public JobShopSchedulingProblem()
133      : base(new JobSequenceMatrixEncoding()) {
134      Parameters.Add(JobDataParameter = new ValueParameter<ItemList<Job>>("JobData", "Jobdata defining the precedence relationships and the duration of the tasks in this JSSP-Instance.", new ItemList<Job>()));
135      Parameters.Add(BestKnownSolutionParameter = new OptionalValueParameter<Schedule>("BestKnownSolution", "The best known solution of this JSSP instance."));
136      Parameters.Add(JobsParameter = new FixedValueParameter<IntValue>("Jobs", "The number of jobs used in this JSSP instance.", new IntValue()));
137      Parameters.Add(ResourcesParameter = new FixedValueParameter<IntValue>("Resources", "The number of resources used in this JSSP instance.", new IntValue()));
138      Parameters.Add(ObjectiveParameter = new FixedValueParameter<EnumValue<JSSPObjective>>("Objective", "The objective to use in the evaluation of a schedule.", new EnumValue<JSSPObjective>(JSSPObjective.Makespan)));
139      EncodingParameter.Hidden = false;
140
141      Encoding.ResourcesParameter = ResourcesParameter;
142      Encoding.JobsParameter = JobsParameter;
143      Encoding.JobDataParameter = JobDataParameter;
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(IScheduleSolution[] solutions, double[] qualities, ResultCollection results, IRandom random) {
162      base.Analyze(solutions, qualities, results, random);
163
164      bool max = Maximization;
165
166      int i = -1;
167      if (!max)
168        i = qualities.Select((x, index) => new { index, x }).OrderBy(x => x.x).First().index;
169      else i = qualities.Select((x, index) => new { index, x }).OrderByDescending(x => x.x).First().index;
170
171      if (double.IsNaN(BestKnownQuality) ||
172          max && qualities[i] > BestKnownQuality ||
173          !max && qualities[i] < BestKnownQuality) {
174        BestKnownQuality = qualities[i];
175        BestKnownSolution = Encoding.Decode(solutions[i], JobData);
176      }
177      Schedule bestSolution;
178      if (results.TryGetValue("Best Scheduling Solution", out var result)) {
179        bestSolution = result.Value as Schedule;
180      } else bestSolution = null;
181
182      if (bestSolution == null || IsBetter(bestSolution.Quality, qualities[i]))
183        results.AddOrUpdateResult("Best Scheduling Solution", Encoding.Decode(solutions[i], JobData));
184    }
185
186    protected override void OnEncodingChanged() {
187      base.OnEncodingChanged();
188      Encoding.ResourcesParameter = ResourcesParameter;
189      Encoding.JobsParameter = JobsParameter;
190      Encoding.JobDataParameter = JobDataParameter;
191    }
192
193
194    private void RegisterEventHandlers() {
195      JobDataParameter.ValueChanged += JobDataParameterOnValueChanged;
196      JobData.PropertyChanged += JobDataOnPropertyChanged;
197    }
198
199    private void JobDataParameterOnValueChanged(object sender, EventArgs e) {
200      JobData.PropertyChanged += JobDataOnPropertyChanged;
201      Jobs = JobData.Count;
202    }
203
204    private void JobDataOnPropertyChanged(object sender, PropertyChangedEventArgs e) {
205      if (e.PropertyName == nameof(JobData.Count)) {
206        Jobs = JobData.Count;
207      }
208    }
209
210    #region Problem Instance Handling
211    public void Load(JSSPData data) {
212      var jobData = new ItemList<Job>(data.Jobs);
213      for (int j = 0; j < data.Jobs; j++) {
214        var job = new Job(j, data.DueDates != null ? data.DueDates[j] : double.MaxValue);
215        for (int t = 0; t < data.Resources; t++) {
216          job.Tasks.Add(new Task(t, data.Demands[j, t], j, data.ProcessingTimes[j, t]));
217        }
218        jobData.Add(job);
219      }
220
221      BestKnownQuality = data.BestKnownQuality ?? double.NaN;
222      if (data.BestKnownSchedule != null) {
223        var enc = new JSM(0);
224        for (int i = 0; i < data.Resources; i++) {
225          enc.JobSequenceMatrix.Add(new Permutation(PermutationTypes.Absolute, new int[data.Jobs]));
226          for (int j = 0; j < data.Jobs; j++) {
227            enc.JobSequenceMatrix[i][j] = data.BestKnownSchedule[i, j];
228          }
229        }
230        BestKnownSolution = JSMDecoder.Decode(enc, jobData, JSMDecodingErrorPolicy.RandomPolicy, JSMForcingStrategy.SwapForcing);
231        switch (Objective) {
232          case JSSPObjective.Makespan:
233            BestKnownQuality = Makespan.Calculate(BestKnownSolution);
234            break;
235          case JSSPObjective.Tardiness:
236            BestKnownQuality = MeanTardiness.Calculate(BestKnownSolution, jobData);
237            break;
238        }
239      }
240
241      JobData = jobData;
242      Resources = data.Resources;
243    }
244
245    public JSSPData Export() {
246      var result = new JSSPData {
247        Name = Name,
248        Description = Description,
249        Jobs = Jobs,
250        Resources = Resources,
251        ProcessingTimes = new double[Jobs, Resources],
252        Demands = new int[Jobs, Resources],
253        DueDates = new double[Jobs]
254      };
255
256      foreach (var job in JobData) {
257        var counter = 0;
258        result.DueDates[job.Index] = job.DueDate;
259        foreach (var task in job.Tasks) {
260          result.ProcessingTimes[task.JobNr, counter] = task.Duration;
261          result.Demands[task.JobNr, counter] = task.ResourceNr;
262          counter++;
263        }
264      }
265      return result;
266    }
267    #endregion
268
269  }
270}
Note: See TracBrowser for help on using the repository browser.