Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2981_MRCPSP/HeuristicLab.Problem.Scheduling.MRCPSP/3.3/MultiModeFileImporter.cs @ 16755

Last change on this file since 16755 was 16598, checked in by ddorfmei, 6 years ago

#2981:

  • added problem definition
  • added improvers and crossover
  • added file importer
File size: 10.4 KB
Line 
1using HeuristicLab.Core;
2using HeuristicLab.Data;
3using System;
4using System.Collections.Generic;
5using System.IO;
6using System.Linq;
7using System.Text.RegularExpressions;
8
9namespace HeuristicLab.Problems.Scheduling.MRCPSP {
10
11  public static class MultiModeFileImporter {
12
13    public static MultiModeResourceConstrainedProjectSchedulingProblem Import(string file) {
14      var bounds = new Dictionary<string, int> {
15        {"J501_3", 25},
16        {"J502_2", 25},
17        {"J502_3", 22},
18        {"J502_4", 24},
19        {"J502_5", 23},
20        {"J504_1", 19},
21        {"J504_5", 22},
22        {"J507_1", 44},
23        {"J507_2", 42},
24        {"J507_3", 41},
25        {"J507_4", 45},
26        {"J507_5", 41},
27        {"J508_1", 37},
28        {"J508_2", 31},
29        {"J508_3", 33},
30        {"J508_4", 34},
31        {"J508_5", 42},
32        {"J509_1", 32},
33        {"J509_2", 24},
34        {"J509_3", 26},
35        {"J509_4", 26},
36        {"J509_5", 28},
37        {"J5010_1", 26},
38        {"J5010_2", 34},
39        {"J5010_3", 26},
40        {"J5010_4", 27},
41        {"J5010_5", 35},
42        {"J5011_1", 25},
43        {"J5011_2", 28},
44        {"J5011_3", 28},
45        {"J5011_4", 24},
46        {"J5011_5", 29},
47        {"J5012_1", 26},
48        {"J5012_2", 30},
49        {"J5012_3", 23},
50        {"J5012_4", 25},
51        {"J5012_5", 25},
52        {"J5020_1", 30},
53        {"J5020_2", 26},
54        {"J5020_4", 25},
55        {"J5020_5", 25},
56        {"J5021_1", 18},
57        {"J5021_5", 17},
58        {"J5022_1", 20},
59        {"J5023_1", 17},
60        {"J5023_4", 16},
61        {"J5043_1", 65},
62        {"J5043_2", 64},
63        {"J5043_3", 68},
64        {"J5043_4", 52},
65        {"J5043_5", 64},
66        {"J5044_1", 47},
67        {"J5044_2", 41},
68        {"J5044_3", 50},
69        {"J5044_4", 49},
70        {"J5044_5", 46},
71        {"J5045_1", 46},
72        {"J5045_2", 34},
73        {"J5045_3", 39},
74        {"J5045_4", 36},
75        {"J5045_5", 44},
76        {"J5046_1", 42},
77        {"J5046_2", 41},
78        {"J5046_3", 45},
79        {"J5046_4", 31},
80        {"J5046_5", 39},
81        {"J5047_1", 36},
82        {"J5047_2", 40},
83        {"J5047_3", 42},
84        {"J5047_4", 39},
85        {"J5047_5", 39},
86        {"J5048_1", 35},
87        {"J5048_2", 40},
88        {"J5048_3", 29},
89        {"J5048_4", 34},
90        {"J5048_5", 41},
91        {"J5056_1", 35},
92        {"J5056_3", 34},
93        {"J5056_4", 34},
94        {"J5056_5", 38},
95        {"J5057_3", 31},
96        {"J5058_1", 34},
97        {"J5058_4", 28},
98        {"J5058_5", 28},
99        {"J5074_5", 57},
100        {"J5079_1", 73},
101        {"J5079_2", 82},
102        {"J5079_3", 73},
103        {"J5079_4", 68},
104        {"J5079_5", 80},
105        {"J5080_1", 72},
106        {"J5080_2", 68},
107        {"J5080_3", 82},
108        {"J5080_4", 72},
109        {"J5080_5", 70},
110        {"J5081_1", 63},
111        {"J5081_3", 57},
112        {"J5081_4", 64},
113        {"J5081_5", 53},
114        {"J5082_1", 59},
115        {"J5082_2", 60},
116        {"J5082_3", 56},
117        {"J5082_4", 67},
118        {"J5082_5", 54},
119        {"J5083_1", 49},
120        {"J5083_4", 56},
121        {"J5083_5", 62},
122        {"J5084_1", 51},
123        {"J5084_2", 57},
124        {"J5084_3", 60},
125        {"J5084_4", 59},
126        {"J5084_5", 57},
127        {"J5092_4", 60},
128        {"J5094_2", 60},
129        {"J5094_3", 45},
130        {"J5094_4", 43},
131        {"J5096_2", 48}
132      };
133
134      var instance = ParseMultiModeFile(file);
135      instance.UpperBound = bounds.TryGetValue(Path.GetFileNameWithoutExtension(file), out var bound) ? bound : -1;
136      return CreateProblem(instance);
137    }
138
139    private static MultiModeResourceConstrainedProjectSchedulingProblem CreateProblem(MMRCPSP instance) {
140      var problem = new MultiModeResourceConstrainedProjectSchedulingProblem { Name = instance.Name };
141
142      if (instance.UpperBound > -1) {
143        problem.BestKnownQuality = instance.UpperBound;
144      }
145
146      if (instance.NbTasks != instance.Tasks.Count)
147        throw new InvalidDataException();
148
149      foreach (var task in instance.Tasks) {
150        var activity = new Activity {
151          Number = task.TaskId
152        };
153
154        foreach (var succ in task.Successors) {
155          activity.Successors.Add(new IntValue(succ));
156        }
157
158        foreach (var mode in instance.Modes.Where(m => m.TaskId == task.TaskId)) {
159          var m = new MRCPSP.Mode {
160            Number = mode.ModeId,
161            Duration = mode.Duration
162          };
163
164          var num = 1;
165          foreach (var demand in mode.DemRenewableRsrc) {
166            if (demand == 0) {
167              num++;
168              continue;
169            }
170            m.ResourceDemands.Add(new ResourceDemand { Demand = demand, Number = num++ });
171          }
172
173          foreach (var demand in mode.DemNonRenewableRsrc) {
174            if (demand == 0) {
175              num++;
176              continue;
177            }
178            m.ResourceDemands.Add(new ResourceDemand { Demand = demand, Number = num++ });
179          }
180
181          activity.Modes.Add(m);
182        }
183
184        problem.Activities.Add(activity);
185      }
186
187      problem.ResourceCapacities = new ItemList<ResourceCapacity>();
188
189      var number = 1;
190      foreach (var cap in instance.CapRenewableRsrc) {
191        problem.ResourceCapacities.Add(new ResourceCapacity {
192          Name = $"R{number}",
193          Number = number++,
194          Capacity = cap,
195          IsRenewable = true
196        });
197      }
198
199      foreach (var cap in instance.CapNonRenewableRsrc) {
200        problem.ResourceCapacities.Add(new ResourceCapacity {
201          Name = $"N{number - instance.NbRenewableRsrcs}",
202          Number = number++,
203          Capacity = cap,
204          IsRenewable = false
205        });
206      }
207
208      problem.InitEncoding();
209      return problem;
210    }
211
212    private static MMRCPSP ParseMultiModeFile(string filePath) {
213      var result = new MMRCPSP {
214        Name = Path.GetFileNameWithoutExtension(filePath),
215        Tasks = new List<Task>(),
216        Modes = new List<Mode>()
217      };
218
219      var section = 0;
220      var prevJob = 0;
221
222      foreach (var line in File.ReadLines(filePath).Select(l => l.Trim())) {
223        if (string.IsNullOrEmpty(line))
224          continue;
225
226        if (line.StartsWith("RESOURCES")) {
227          section = 1;
228          continue;
229        }
230
231        if (line.StartsWith("PRECEDENCE RELATIONS")) {
232          section = 2;
233          continue;
234        }
235
236        if (line.StartsWith("REQUESTS/DURATIONS")) {
237          section = 3;
238          continue;
239        }
240
241        if (line.StartsWith("RESOURCE AVAILABILITIES") || line.StartsWith("RESOURCEAVAILABILITIES")) {
242          section = 4;
243          continue;
244        }
245
246        switch (section) {
247          case 0: // Jobs
248            if (line.StartsWith("jobs", StringComparison.InvariantCultureIgnoreCase)) {
249              result.NbTasks = int.Parse(Regex.Match(line, @":[ \t]*(?<jobs>\d+)").Groups["jobs"].Value);
250            }
251
252            break;
253
254          case 1: // Resources
255            if (line.StartsWith("- nonrenewable")) {
256              result.NbNonRenewableRsrcs = int.Parse(Regex.Match(line, @":.*(?<nr>\d+).*N").Groups["nr"].Value);
257              result.CapNonRenewableRsrc = new int[result.NbNonRenewableRsrcs];
258            } else if (line.StartsWith("- renewable")) {
259              result.NbRenewableRsrcs = int.Parse(Regex.Match(line, @":.*(?<nr>\d+).*R").Groups["nr"].Value);
260              result.CapRenewableRsrc = new int[result.NbRenewableRsrcs];
261            }
262
263            break;
264
265          case 2: // Precedence Relations
266            if (char.IsDigit(line[0])) {
267              var numbers = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
268              var task = new Task {
269                TaskId = int.Parse(numbers[0]),
270                Successors = new List<int>(numbers.Skip(3).Select(x => int.Parse(x)))
271              };
272              result.Tasks.Add(task);
273            }
274
275            break;
276
277          case 3: // Requests/Durations
278            if (char.IsDigit(line[0])) {
279              var numbers = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
280              var mode = new Mode {
281                DemRenewableRsrc = new int[result.NbRenewableRsrcs],
282                DemNonRenewableRsrc = new int[result.NbNonRenewableRsrcs]
283              };
284              var next = 0;
285              if (numbers.Length == 3 + result.NbRenewableRsrcs + result.NbNonRenewableRsrcs) {
286                prevJob = int.Parse(numbers[next++]);
287              }
288              mode.TaskId = prevJob;
289              mode.ModeId = int.Parse(numbers[next++]);
290              mode.Duration = int.Parse(numbers[next++]);
291              for (var i = 0; i < result.NbRenewableRsrcs; i++) {
292                mode.DemRenewableRsrc[i] = int.Parse(numbers[next++]);
293              }
294              for (var i = 0; i < result.NbNonRenewableRsrcs; i++) {
295                mode.DemNonRenewableRsrc[i] = int.Parse(numbers[next++]);
296              }
297              result.Modes.Add(mode);
298            }
299
300            break;
301
302          case 4: // Resource Availabilities
303            if (char.IsDigit(line[0])) {
304              var numbers = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
305              var next = 0;
306              for (var i = 0; i < result.NbRenewableRsrcs; i++) {
307                result.CapRenewableRsrc[i] = int.Parse(numbers[next++]);
308              }
309              for (var i = 0; i < result.NbNonRenewableRsrcs; i++) {
310                result.CapNonRenewableRsrc[i] = int.Parse(numbers[next++]);
311              }
312            }
313
314            break;
315
316          default: // unkown section
317            continue;
318        }
319      }
320
321      return result;
322    }
323
324    private class MMRCPSP {
325      public int[] CapNonRenewableRsrc;
326      public int[] CapRenewableRsrc;
327      public List<Mode> Modes;
328      public string Name;
329      public int NbNonRenewableRsrcs;
330      public int NbRenewableRsrcs;
331      public int NbTasks;
332      public List<Task> Tasks;
333      public int UpperBound;
334    }
335
336    private class Mode {
337      public int[] DemNonRenewableRsrc;
338      public int[] DemRenewableRsrc;
339      public int Duration;
340      public int ModeId;
341      public int TaskId;
342    }
343
344    private class Task {
345      public List<int> Successors;
346      public int TaskId;
347    }
348  }
349}
Note: See TracBrowser for help on using the repository browser.