Free cookie consent management tool by TermsFeed Policy Generator

source: branches/XmlTextWriterBranch/HeuristicLab.Scheduling.JSSP/ScheduleTree.cs @ 165

Last change on this file since 165 was 119, checked in by gkronber, 17 years ago

created a branch that uses XmlTextWriter instead of XMLDocument to save documents. Investigating ticket #103.

File size: 7.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 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.Collections.Generic;
24using System.Text;
25using System.Xml;
26using HeuristicLab.Data;
27using HeuristicLab.Core;
28
29namespace HeuristicLab.Scheduling.JSSP {
30
31  public class ScheduleTreeNode {
32    private TimeSlot data;
33    private ScheduleTreeNode left;
34    private ScheduleTreeNode right;
35    private ScheduleTreeNode parent;
36
37    public ScheduleTreeNode(TimeSlot t) {
38      data = t;
39    }
40
41    public ScheduleTreeNode Left {
42      get { return left; }
43      set { left = value; }
44    }
45
46    public ScheduleTreeNode Right {
47      get { return right; }
48      set { right = value; }
49    }
50
51    public ScheduleTreeNode Parent {
52      get { return parent; }
53      set { parent = value; }
54    }
55
56    public void SetLeft(ScheduleTreeNode child) {
57      this.Left = child;
58      child.Parent = this;
59    }
60
61    public void SetRight(ScheduleTreeNode child) {
62      this.Right = child;
63      child.Parent = this;
64    }
65
66    public TimeSlot Data {
67      get { return data; }
68      set { data = value; }
69    }
70  }
71
72  public class ScheduleTree : StorableBase {
73    private ScheduleTreeNode root;
74
75    public ScheduleTreeNode Root {
76      get { return root; }
77    }
78
79    private int timespan;
80    public int Timespan {
81      get { return timespan; }
82    }
83
84    public ScheduleTree(int timespan) {
85      root = new ScheduleTreeNode(new TimeSlot(0, timespan));
86      this.timespan = timespan;
87    }
88
89    public ScheduleTree() : this(10000) { }
90
91    private int InsertOperation(Operation op) {
92      return Insert(this.Root, op);
93    }
94
95    private int InsertOperation(TimeSlot t) {
96      return Insert(this.Root, t.operation);
97    }
98
99    // ToDo: Rewrite code! (not efficient)
100    public int Insert(Operation op) {
101      foreach(ScheduleTreeNode node in this.InOrder) {
102        int start = Math.Max(node.Data.start, op.Start);
103        if((IsLeaf(node)) && (FitsIntoEmptySlot(node.Data, start, op.Duration))) {
104          op.Start = start;
105          return Insert(node, op);
106        }
107      }
108      return -1;
109    }
110
111    private bool FitsIntoEmptySlot(TimeSlot slot, int start, int duration) {
112      return ((slot.free >= duration) && (slot.start <= start) && (slot.end >= start + duration));
113    }
114
115    private void UpdateMaxFreeSlot(ScheduleTreeNode slot) {
116      while(slot != null) {
117        if(!IsLeaf(slot)) {
118          int newMax = Math.Max(slot.Left.Data.maxFreeSlot, slot.Right.Data.maxFreeSlot);
119          slot.Data.free = slot.Left.Data.free + slot.Right.Data.free;
120          slot.Data.maxFreeSlot = newMax;
121        }
122        slot = slot.Parent;
123      }
124    }
125
126    private int Insert(ScheduleTreeNode slot, Operation op) {
127      if (op == null) {
128        return -1;
129      }
130      int end = op.Start + op.Duration;;
131      if(slot.Data.maxFreeSlot < op.Duration) {
132        return -1;
133      }
134      if(IsLeaf(slot)) {
135        // fits exactly into slot
136        if((slot.Data.start == op.Start) && (slot.Data.end == end)) {
137          slot.Data = new TimeSlot(op);
138          UpdateMaxFreeSlot(slot);
139          return op.Start;
140        }
141        // empty slot before op.
142        if(slot.Data.start < op.Start) {
143          ScheduleTreeNode empty1 = new ScheduleTreeNode(new TimeSlot(slot.Data.start, op.Start));
144          slot.SetLeft(empty1);
145          if(slot.Data.end > end) {
146            ScheduleTreeNode empty2 = new ScheduleTreeNode(new TimeSlot(op.Start, slot.Data.end));
147            slot.SetRight(empty2);
148            return Insert(empty2, op);
149          } else {
150            slot.SetRight(new ScheduleTreeNode(new TimeSlot(op)));
151            UpdateMaxFreeSlot(slot);
152            return op.Start;
153          }
154        }
155        // empty after op.
156        if(slot.Data.end > end) {
157          ScheduleTreeNode occupied = new ScheduleTreeNode(new TimeSlot(op));
158          ScheduleTreeNode empty2 = new ScheduleTreeNode(new TimeSlot(end, slot.Data.end));
159          slot.SetRight(empty2);
160          slot.SetLeft(occupied);
161          UpdateMaxFreeSlot(slot);
162          return op.Start;
163        }
164      } else {
165        if(slot.Left.Data.end < end) {
166          return Insert(slot.Right, op);
167        } else {
168          return Insert(slot.Left, op);
169        }
170      }
171      return -1;
172    }
173
174    public bool IsLeaf(ScheduleTreeNode slot) {
175      return ((slot.Right == null) && (slot.Left == null));
176    }
177
178    public override string ToString() {
179      StringBuilder builder = new StringBuilder();
180      foreach(ScheduleTreeNode node in this.InOrder) {
181        if(IsLeaf(node)) {
182          builder.Append(node.Data.ToString());
183          builder.Append(";");
184        }
185      }
186      return builder.ToString();
187    }
188
189    #region IEnumerable Members
190    public IEnumerable<ScheduleTreeNode> InOrder {
191      get { return ScanInOrder(root); }
192    }
193
194    IEnumerable<ScheduleTreeNode> ScanInOrder(ScheduleTreeNode root) {
195      if(root.Left != null) {
196        foreach(ScheduleTreeNode node in ScanInOrder(root.Left)) {
197          yield return node;
198        }
199      }
200      yield return root;
201      if(root.Right != null) {
202        foreach(ScheduleTreeNode node in ScanInOrder(root.Right)) {
203          yield return node;
204        }
205      }
206    }
207    #endregion
208
209    #region IStorable Members
210    //public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid,IStorable> persistedObjects) {
211    //  XmlNode node = base.GetXmlNode(name, document, persistedObjects);
212    //  node.InnerText = this.ToString();
213    //  return node;
214    //}
215    public override void Persist(string name, XmlWriter writer, IDictionary<Guid, IStorable> persistedObjects) {
216      base.Persist(name, writer, persistedObjects);
217      writer.WriteValue(ToString());
218    }
219
220    public override void Populate(XmlNode node, IDictionary<Guid,IStorable> restoredObjects) {
221      base.Populate(node, restoredObjects);
222      string[] tokens = node.InnerText.Split(';');
223      for(int i = 0; i < tokens.Length - 1; i++) {
224        TimeSlot t = new TimeSlot(tokens[i]);
225        if(t.job > -1) {
226          this.InsertOperation(t);
227        }
228      }
229    }
230
231    public override object Clone(IDictionary<Guid, object> clonedObjects) {
232      ScheduleTree clone = new ScheduleTree(timespan);
233      clonedObjects.Add(Guid, clone);
234      foreach (ScheduleTreeNode node in this.InOrder) {
235        if (IsLeaf(node) && (node.Data.job > -1)) {
236          clone.InsertOperation(node.Data);
237        }
238      }
239      return clone;
240    }
241
242    #endregion
243  }
244}
Note: See TracBrowser for help on using the repository browser.