Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HiveHiveEngine/HeuristicLab.Clients.Hive/3.3/HiveTasks/OptimizerHiveTask.cs @ 12547

Last change on this file since 12547 was 7259, checked in by swagner, 13 years ago

Updated year of copyrights to 2012 (#1716)

File size: 17.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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.Linq;
25using HeuristicLab.Clients.Hive.Jobs;
26using HeuristicLab.Collections;
27using HeuristicLab.Common;
28using HeuristicLab.Optimization;
29using HeuristicLab.PluginInfrastructure;
30
31namespace HeuristicLab.Clients.Hive {
32  public class OptimizerHiveTask : HiveTask<OptimizerTask> {
33
34    #region Constructors and Cloning
35    public OptimizerHiveTask() { }
36    public OptimizerHiveTask(IOptimizer optimizer)
37      : this() {
38      this.ItemTask = new OptimizerTask(optimizer);
39    }
40    public OptimizerHiveTask(OptimizerTask optimizerJob)
41      : this() {
42      this.ItemTask = optimizerJob;
43    }
44    protected OptimizerHiveTask(OptimizerHiveTask original, Cloner cloner)
45      : base(original, cloner) {
46    }
47    public override IDeepCloneable Clone(Cloner cloner) {
48      return new OptimizerHiveTask(this, cloner);
49    }
50    #endregion
51
52    /// <summary>
53    /// if this.Optimizer is an experiment
54    ///   Uses the child-optimizers of this.HiveTask and creates HiveTask-childs
55    /// if this.Optimizer is a batchrun
56    ///   Creates a number of child-jobs according to repetitions
57    /// </summary>
58    protected override void UpdateChildHiveTasks() {
59      base.UpdateChildHiveTasks();
60      if (Task != null && syncTasksWithOptimizers) {
61        if (!ItemTask.ComputeInParallel) {
62          this.childHiveTasks.Clear();
63        } else {
64          if (ItemTask.Item is Optimization.Experiment) {
65            Optimization.Experiment experiment = (Optimization.Experiment)ItemTask.Item;
66            foreach (IOptimizer childOpt in experiment.Optimizers) {
67              var optimizerHiveTask = new OptimizerHiveTask(childOpt);
68              optimizerHiveTask.Task.Priority = Task.Priority; //inherit priority from parent
69              this.childHiveTasks.Add(optimizerHiveTask);
70            }
71          } else if (ItemTask.Item is Optimization.BatchRun) {
72            Optimization.BatchRun batchRun = ItemTask.OptimizerAsBatchRun;
73            if (batchRun.Optimizer != null) {
74              while (this.childHiveTasks.Count < batchRun.Repetitions) {
75                var optimizerHiveTask = new OptimizerHiveTask(batchRun.Optimizer);
76                optimizerHiveTask.Task.Priority = Task.Priority;
77                this.childHiveTasks.Add(optimizerHiveTask);
78              }
79              while (this.childHiveTasks.Count > batchRun.Repetitions) {
80                this.childHiveTasks.Remove(this.childHiveTasks.Last());
81              }
82            }
83          }
84        }
85      }
86    }
87
88    protected override void RegisterItemTaskEvents() {
89      base.RegisterItemTaskEvents();
90      if (ItemTask != null) {
91        if (ItemTask.Item is Optimization.Experiment) {
92          Optimization.Experiment experiment = ItemTask.OptimizerAsExperiment;
93          experiment.Optimizers.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
94          experiment.Optimizers.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
95          experiment.Optimizers.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
96          experiment.Optimizers.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
97        } else if (ItemTask.Item is Optimization.BatchRun) {
98          Optimization.BatchRun batchRun = ItemTask.OptimizerAsBatchRun;
99          batchRun.RepetitionsChanged += new EventHandler(batchRun_RepetitionsChanged);
100          batchRun.OptimizerChanged += new EventHandler(batchRun_OptimizerChanged);
101        }
102      }
103    }
104    protected override void DergisterItemTaskEvents() {
105      base.DergisterItemTaskEvents();
106      if (ItemTask != null) {
107        if (ItemTask.Item is Optimization.Experiment) {
108          Optimization.Experiment experiment = ItemTask.OptimizerAsExperiment;
109          experiment.Optimizers.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
110          experiment.Optimizers.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
111          experiment.Optimizers.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
112          experiment.Optimizers.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
113        } else if (ItemTask.Item is Optimization.BatchRun) {
114          Optimization.BatchRun batchRun = ItemTask.OptimizerAsBatchRun;
115          batchRun.RepetitionsChanged -= new EventHandler(batchRun_RepetitionsChanged);
116          batchRun.OptimizerChanged -= new EventHandler(batchRun_OptimizerChanged);
117        }
118      }
119    }
120
121    private void batchRun_OptimizerChanged(object sender, EventArgs e) {
122      if (syncTasksWithOptimizers) {
123        UpdateChildHiveTasks();
124      }
125    }
126
127    private void batchRun_RepetitionsChanged(object sender, EventArgs e) {
128      if (syncTasksWithOptimizers) {
129        UpdateChildHiveTasks();
130      }
131    }
132
133    private void Optimizers_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
134      if (syncTasksWithOptimizers && this.ItemTask.ComputeInParallel) {
135        childHiveTasksLock.EnterWriteLock();
136        try {
137          foreach (var item in e.Items) {
138            if (GetChildByOptimizer(item.Value) == null && item.Value.Name != "Placeholder") {
139              this.childHiveTasks.Add(new OptimizerHiveTask(item.Value));
140            }
141          }
142        }
143        finally { childHiveTasksLock.ExitWriteLock(); }
144      }
145    }
146    private void Optimizers_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
147      if (syncTasksWithOptimizers && this.ItemTask.ComputeInParallel) {
148        childHiveTasksLock.EnterWriteLock();
149        try {
150          foreach (var item in e.OldItems) {
151            this.childHiveTasks.Remove(this.GetChildByOptimizer(item.Value));
152          }
153          foreach (var item in e.Items) {
154            if (GetChildByOptimizer(item.Value) == null && item.Value.Name != "Placeholder") {
155              this.childHiveTasks.Add(new OptimizerHiveTask(item.Value));
156            }
157          }
158        }
159        finally { childHiveTasksLock.ExitWriteLock(); }
160      }
161    }
162    private void Optimizers_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
163      if (syncTasksWithOptimizers && this.ItemTask.ComputeInParallel) {
164        childHiveTasksLock.EnterWriteLock();
165        try {
166          foreach (var item in e.Items) {
167            this.childHiveTasks.Remove(this.GetChildByOptimizer(item.Value));
168          }
169        }
170        finally { childHiveTasksLock.ExitWriteLock(); }
171      }
172    }
173    private void Optimizers_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
174      if (syncTasksWithOptimizers && this.ItemTask.ComputeInParallel) {
175        childHiveTasksLock.EnterWriteLock();
176        try {
177          foreach (var item in e.Items) {
178            this.childHiveTasks.Remove(this.GetChildByOptimizer(item.Value));
179          }
180        }
181        finally { childHiveTasksLock.ExitWriteLock(); }
182      }
183    }
184
185    /// <summary>
186    /// if this.Optimizer is Experiment
187    ///   replace the child-optimizer in the experiment
188    /// if this.Optimizer is BatchRun
189    ///   add the runs from the optimizerTask to the batchrun and replace the Optimizer
190    /// </summary>
191    public override void IntegrateChild(ItemTask task, Guid childTaskId) {
192      var optimizerTask = (OptimizerTask)task;
193      syncTasksWithOptimizers = false; // don't sync with optimizers during this method
194
195      if (this.ItemTask != null && this.ItemTask.Item != null) {
196        if (this.ItemTask.Item is Optimization.Experiment) {
197          UpdateOptimizerInExperiment(this.ItemTask.OptimizerAsExperiment, optimizerTask);
198        } else if (this.ItemTask.Item is Optimization.BatchRun) {
199          UpdateOptimizerInBatchRun(this.ItemTask.OptimizerAsBatchRun, optimizerTask);
200        }
201      }
202
203      IEnumerable<HiveTask> childs = this.ChildHiveTasks.Where(j => j.Task.Id == childTaskId);
204      //TODO: in very rare cases childs is empty. This shouldn't be the case and should be further investigated.
205      if (childs.Count() > 0) {
206        OptimizerHiveTask child = childs.First() as OptimizerHiveTask;
207
208        if (child != null && !optimizerTask.ComputeInParallel) {
209          child.syncTasksWithOptimizers = false;
210          child.ItemTask = optimizerTask;
211          child.syncTasksWithOptimizers = true;
212        }
213      }
214
215      syncTasksWithOptimizers = true;
216    }
217
218    /// <summary>
219    /// Adds the runs from the optimizerTask to the batchrun and replaces the Optimizer
220    /// Sideeffect: the optimizerTask.Optimizer will be prepared (scopes are deleted and executionstate will be reset)
221    /// </summary>
222    private void UpdateOptimizerInBatchRun(BatchRun batchRun, OptimizerTask optimizerTask) {
223      if (batchRun.Optimizer == null) {
224        batchRun.Optimizer = (IOptimizer)optimizerTask.Item; // only set the first optimizer as Optimizer. if every time the Optimizer would be set, the runs would be cleared each time
225      }
226      foreach (IRun run in optimizerTask.Item.Runs) {
227        if (!batchRun.Runs.Contains(run)) {
228          run.Name = GetNewRunName(run, batchRun.Runs);
229          batchRun.Runs.Add(run);
230        }
231      }
232    }
233
234    /// <summary>
235    /// replace the child-optimizer in the experiment
236    /// Sideeffect: the optimizerTask.Optimizer will be prepared (scopes are deleted and executionstate will be reset)
237    /// </summary>
238    private void UpdateOptimizerInExperiment(Optimization.Experiment experiment, OptimizerTask optimizerTask) {
239      if (optimizerTask.IndexInParentOptimizerList < 0)
240        throw new IndexOutOfRangeException("IndexInParentOptimizerList must be equal or greater than zero! The Task is invalid and the optimizer-tree cannot be reassembled.");
241
242      while (experiment.Optimizers.Count < optimizerTask.IndexInParentOptimizerList) {
243        experiment.Optimizers.Add(new UserDefinedAlgorithm("Placeholder")); // add dummy-entries to Optimizers so that its possible to insert the optimizerTask at the correct position
244      }
245      if (experiment.Optimizers.Count < optimizerTask.IndexInParentOptimizerList + 1) {
246        experiment.Optimizers.Add(optimizerTask.Item);
247      } else {
248        // if ComputeInParallel==true, don't replace the optimizer (except it is still a Placeholder)
249        // this is because Jobs with ComputeInParallel get submitted to hive with their child-optimizers deleted
250        if (!optimizerTask.ComputeInParallel || experiment.Optimizers[optimizerTask.IndexInParentOptimizerList].Name == "Placeholder") {
251          experiment.Optimizers[optimizerTask.IndexInParentOptimizerList] = optimizerTask.Item;
252        }
253      }
254    }
255
256    /// <summary>
257    /// Sets the IndexInParentOptimizerList property of the OptimizerJob
258    /// according to the position in the OptimizerList of the parentHiveTask.Task
259    /// Recursively updates all the child-jobs as well
260    /// </summary>
261    internal void SetIndexInParentOptimizerList(OptimizerHiveTask parentHiveTask) {
262      if (parentHiveTask != null) {
263        if (parentHiveTask.ItemTask.Item is Optimization.Experiment) {
264          this.ItemTask.IndexInParentOptimizerList = parentHiveTask.ItemTask.OptimizerAsExperiment.Optimizers.IndexOf(this.ItemTask.Item);
265        } else if (parentHiveTask.ItemTask.Item is Optimization.BatchRun) {
266          this.ItemTask.IndexInParentOptimizerList = 0;
267        } else {
268          throw new NotSupportedException("Only Experiment and BatchRuns are supported");
269        }
270      }
271      childHiveTasksLock.EnterReadLock();
272      try {
273        foreach (OptimizerHiveTask child in childHiveTasks) {
274          child.SetIndexInParentOptimizerList(this);
275        }
276      }
277      finally { childHiveTasksLock.ExitReadLock(); }
278    }
279
280    public override void AddChildHiveTask(HiveTask hiveTask) {
281      base.AddChildHiveTask(hiveTask);
282      var optimizerHiveJob = (OptimizerHiveTask)hiveTask;
283      syncTasksWithOptimizers = false;
284      if (this.ItemTask != null && optimizerHiveJob.ItemTask != null) {
285        // if task is in state Paused, it has to preserve its ResultCollection, which is cleared when a optimizer is added to an experiment
286        OptimizerTask optimizerJobClone = null;
287        if (optimizerHiveJob.Task.State == TaskState.Paused) {
288          optimizerJobClone = (OptimizerTask)optimizerHiveJob.ItemTask.Clone();
289        }
290
291        if (this.ItemTask.Item is Optimization.Experiment) {
292          if (!this.ItemTask.OptimizerAsExperiment.Optimizers.Contains(optimizerHiveJob.ItemTask.Item)) {
293            UpdateOptimizerInExperiment(this.ItemTask.OptimizerAsExperiment, optimizerHiveJob.ItemTask);
294          }
295        } else if (this.ItemTask.Item is Optimization.BatchRun) {
296          UpdateOptimizerInBatchRun(this.ItemTask.OptimizerAsBatchRun, optimizerHiveJob.ItemTask);
297        }
298
299        if (optimizerHiveJob.Task.State == TaskState.Paused) {
300          optimizerHiveJob.ItemTask = optimizerJobClone;
301        }
302      }
303      syncTasksWithOptimizers = true;
304    }
305
306    /// <summary>
307    /// Creates a TaskData object containing the Task and the IJob-Object as byte[]
308    /// </summary>
309    /// <param name="withoutChildOptimizers">
310    ///   if true the Child-Optimizers will not be serialized (if the task contains an Experiment)
311    /// </param>
312    public override TaskData GetAsTaskData(bool withoutChildOptimizers, out List<IPluginDescription> plugins) {
313      plugins = new List<IPluginDescription>();
314      if (this.itemTask == null) // || this.jobItem.Optimizer == null
315        return null;
316
317      IEnumerable<Type> usedTypes;
318      byte[] jobByteArray;
319      if (withoutChildOptimizers && this.ItemTask.Item is Optimization.Experiment) {
320        OptimizerTask clonedJob = (OptimizerTask)this.ItemTask.Clone(); // use a cloned task, so that the childHiveJob don't get confused
321        clonedJob.OptimizerAsExperiment.Optimizers.Clear();
322        jobByteArray = PersistenceUtil.Serialize(clonedJob, out usedTypes);
323      } else if (withoutChildOptimizers && this.ItemTask.Item is Optimization.BatchRun) {
324        OptimizerTask clonedJob = (OptimizerTask)this.ItemTask.Clone();
325        clonedJob.OptimizerAsBatchRun.Optimizer = null;
326        jobByteArray = PersistenceUtil.Serialize(clonedJob, out usedTypes);
327      } else if (this.ItemTask.Item is IAlgorithm) {
328        ((IAlgorithm)this.ItemTask.Item).StoreAlgorithmInEachRun = false; // avoid storing the algorithm in runs to reduce size
329        jobByteArray = PersistenceUtil.Serialize(this.ItemTask, out usedTypes);
330      } else {
331        jobByteArray = PersistenceUtil.Serialize(this.ItemTask, out usedTypes);
332      }
333
334      TaskData jobData = new TaskData() { TaskId = task.Id, Data = jobByteArray };
335      PluginUtil.CollectDeclaringPlugins(plugins, usedTypes);
336      return jobData;
337    }
338
339    public OptimizerHiveTask GetChildByOptimizerTask(OptimizerTask optimizerTask) {
340      childHiveTasksLock.EnterReadLock();
341      try {
342        foreach (OptimizerHiveTask child in childHiveTasks) {
343          if (child.ItemTask == optimizerTask)
344            return child;
345        }
346        return null;
347      }
348      finally { childHiveTasksLock.ExitReadLock(); }
349    }
350
351    public HiveTask<OptimizerTask> GetChildByOptimizer(IOptimizer optimizer) {
352      childHiveTasksLock.EnterReadLock();
353      try {
354        foreach (OptimizerHiveTask child in childHiveTasks) {
355          if (child.ItemTask.Item == optimizer)
356            return child;
357        }
358        return null;
359      }
360      finally { childHiveTasksLock.ExitReadLock(); }
361    }
362
363    #region Helpers
364    /// <summary>
365    /// Parses the run numbers out of runs and renames the run to the next number
366    /// </summary>
367    private static string GetNewRunName(IRun run, RunCollection runs) {
368      int idx = run.Name.IndexOf("Run ") + 4;
369
370      if (idx == 3 || runs.Count == 0)
371        return run.Name;
372
373      int maxRunNumber = int.MinValue;
374      foreach (IRun r in runs) {
375        int number = GetRunNumber(r.Name);
376        maxRunNumber = Math.Max(maxRunNumber, number);
377      }
378
379      return run.Name.Substring(0, idx) + (maxRunNumber + 1).ToString();
380    }
381
382    /// <summary>
383    /// Parses the number of a Run out of its name. Example "Genetic Algorithm Run 3" -> 3
384    /// </summary>
385    private static int GetRunNumber(string runName) {
386      int idx = runName.IndexOf("Run ") + 4;
387      if (idx == 3) {
388        return 0;
389      } else {
390        return int.Parse(runName.Substring(idx, runName.Length - idx));
391      }
392    }
393    #endregion
394  }
395}
Note: See TracBrowser for help on using the repository browser.