Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive/3.4/ExperimentManager/OptimizerHiveJob.cs @ 6033

Last change on this file since 6033 was 6033, checked in by cneumuel, 13 years ago

#1233

  • created baseclass for jobs (ItemJob) which derives OperatorJobs and EngineJobs
  • created special view for OptimizerJobs which derives from a more general view
  • removed logic from domain class HiveExperiment and moved it into RefreshableHiveExperiment
  • improved ItemTreeView
  • corrected plugin dependencies
  • fixed bug in database trigger when deleting HiveExperiments
  • added delete cascade for Plugin and PluginData
  • lots of fixes
File size: 16.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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.ExperimentManager {
32  public class OptimizerHiveJob : HiveJob<OptimizerJob> {
33
34    #region Constructors and Cloning
35    public OptimizerHiveJob() { }
36    public OptimizerHiveJob(IOptimizer optimizer)
37      : this() {
38      this.JobItem = new OptimizerJob(optimizer);
39    }
40    public OptimizerHiveJob(OptimizerJob optimizerJob)
41      : this() {
42      this.JobItem = optimizerJob;
43    }
44    protected OptimizerHiveJob(OptimizerHiveJob original, Cloner cloner)
45      : base(original, cloner) {
46    }
47    public override IDeepCloneable Clone(Cloner cloner) {
48      return new OptimizerHiveJob(this, cloner);
49    }
50    #endregion
51
52    /// <summary>
53    /// if this.Optimizer is an experiment
54    ///   Uses the child-optimizers of this.HiveJob and creates HiveJob-childs
55    /// if this.Optimizer is a batchrun
56    ///   Creates a number of child-jobs according to repetitions
57    /// </summary>
58    protected override void UpdateChildHiveJobs() {
59      base.UpdateChildHiveJobs();
60      if (Job != null && syncJobsWithOptimizers) {
61        if (!JobItem.ComputeInParallel) {
62          this.childHiveJobs.Clear();
63        } else {
64          if (JobItem.Item is Optimization.Experiment) {
65            Optimization.Experiment experiment = (Optimization.Experiment)JobItem.Item;
66            foreach (IOptimizer childOpt in experiment.Optimizers) {
67              this.childHiveJobs.Add(new OptimizerHiveJob(childOpt));
68            }
69          } else if (JobItem.Item is Optimization.BatchRun) {
70            Optimization.BatchRun batchRun = JobItem.OptimizerAsBatchRun;
71            if (batchRun.Optimizer != null) {
72              while (this.childHiveJobs.Count < batchRun.Repetitions) {
73                this.childHiveJobs.Add(new OptimizerHiveJob(batchRun.Optimizer));
74              }
75              while (this.childHiveJobs.Count > batchRun.Repetitions) {
76                this.childHiveJobs.Remove(this.childHiveJobs.Last());
77              }
78            }
79          }
80        }
81      }
82    }
83
84    protected override void RegisterJobItemEvents() {
85      base.RegisterJobItemEvents();
86      if (JobItem != null) {
87        if (JobItem.Item is Optimization.Experiment) {
88          Optimization.Experiment experiment = JobItem.OptimizerAsExperiment;
89          experiment.Optimizers.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
90          experiment.Optimizers.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
91          experiment.Optimizers.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
92          experiment.Optimizers.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
93        } else if (JobItem.Item is Optimization.BatchRun) {
94          Optimization.BatchRun batchRun = JobItem.OptimizerAsBatchRun;
95          batchRun.RepetitionsChanged += new EventHandler(batchRun_RepetitionsChanged);
96          batchRun.OptimizerChanged += new EventHandler(batchRun_OptimizerChanged);
97        }
98      }
99    }
100    protected override void DergisterJobItemsEvents() {
101      base.DergisterJobItemsEvents();
102      if (JobItem != null) {
103        if (JobItem.Item is Optimization.Experiment) {
104          Optimization.Experiment experiment = JobItem.OptimizerAsExperiment;
105          experiment.Optimizers.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsAdded);
106          experiment.Optimizers.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsReplaced);
107          experiment.Optimizers.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_ItemsRemoved);
108          experiment.Optimizers.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<IOptimizer>>(Optimizers_CollectionReset);
109        } else if (JobItem.Item is Optimization.BatchRun) {
110          Optimization.BatchRun batchRun = JobItem.OptimizerAsBatchRun;
111          batchRun.RepetitionsChanged -= new EventHandler(batchRun_RepetitionsChanged);
112          batchRun.OptimizerChanged -= new EventHandler(batchRun_OptimizerChanged);
113        }
114      }
115    }
116
117    private void batchRun_OptimizerChanged(object sender, EventArgs e) {
118      if (syncJobsWithOptimizers) {
119        UpdateChildHiveJobs();
120      }
121    }
122
123    private void batchRun_RepetitionsChanged(object sender, EventArgs e) {
124      if (syncJobsWithOptimizers) {
125        UpdateChildHiveJobs();
126      }
127    }
128
129    private void Optimizers_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
130      if (syncJobsWithOptimizers && this.JobItem.ComputeInParallel) {
131        foreach (var item in e.Items) {
132          if (GetChildByOptimizer(item.Value) == null && item.Value.Name != "Placeholder") {
133            this.childHiveJobs.Add(new OptimizerHiveJob(item.Value));
134          }
135        }
136      }
137    }
138    private void Optimizers_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
139      if (syncJobsWithOptimizers && this.JobItem.ComputeInParallel) {
140        foreach (var item in e.OldItems) {
141          this.childHiveJobs.Remove(this.GetChildByOptimizer(item.Value));
142        }
143        foreach (var item in e.Items) {
144          if (GetChildByOptimizer(item.Value) == null && item.Value.Name != "Placeholder") {
145            this.childHiveJobs.Add(new OptimizerHiveJob(item.Value));
146          }
147        }
148      }
149    }
150    private void Optimizers_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
151      if (syncJobsWithOptimizers && this.JobItem.ComputeInParallel) {
152        foreach (var item in e.Items) {
153          this.childHiveJobs.Remove(this.GetChildByOptimizer(item.Value));
154        }
155      }
156    }
157    private void Optimizers_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<IOptimizer>> e) {
158      if (syncJobsWithOptimizers && this.JobItem.ComputeInParallel) {
159        foreach (var item in e.Items) {
160          this.childHiveJobs.Remove(this.GetChildByOptimizer(item.Value));
161        }
162      }
163    }
164
165    /// <summary>
166    /// if this.Optimizer is Experiment
167    ///   replace the child-optimizer in the experiment
168    /// if this.Optimizer is BatchRun
169    ///   add the runs from the optimizerJob to the batchrun and replace the Optimizer
170    /// </summary>
171    public void UpdateChildOptimizer(OptimizerJob optimizerJob, Guid childJobId) {
172      syncJobsWithOptimizers = false; // don't sync with optimizers during this method
173
174      if (this.JobItem != null && this.JobItem.Item != null) {
175        if (this.JobItem.Item is Optimization.Experiment) {
176          UpdateOptimizerInExperiment(this.JobItem.OptimizerAsExperiment, optimizerJob);
177        } else if (this.JobItem.Item is Optimization.BatchRun) {
178          UpdateOptimizerInBatchRun(this.JobItem.OptimizerAsBatchRun, optimizerJob);
179        }
180      }
181
182      OptimizerHiveJob child = (OptimizerHiveJob)this.ChildHiveJobs.Single(j => j.Job.Id == childJobId);
183      if (!optimizerJob.ComputeInParallel) {
184        child.syncJobsWithOptimizers = false;
185        child.JobItem = optimizerJob;
186        child.syncJobsWithOptimizers = true;
187      }
188      syncJobsWithOptimizers = true;
189    }
190
191    /// <summary>
192    /// Adds the runs from the optimizerJob to the batchrun and replaces the Optimizer
193    /// Sideeffect: the optimizerJob.Optimizer will be prepared (scopes are deleted and executionstate will be reset)
194    /// </summary>
195    private void UpdateOptimizerInBatchRun(BatchRun batchRun, OptimizerJob optimizerJob) {
196      if (batchRun.Optimizer == null) {
197        batchRun.Optimizer = (IOptimizer)optimizerJob.Item; // only set the first optimizer as Optimizer. if every time the Optimizer would be set, the runs would be cleared each time
198      }
199      foreach (IRun run in optimizerJob.Item.Runs) {
200        if (!batchRun.Runs.Contains(run)) {
201          run.Name = GetNewRunName(run, batchRun.Runs);
202          batchRun.Runs.Add(run);
203        }
204      }
205    }
206
207    /// <summary>
208    /// replace the child-optimizer in the experiment
209    /// Sideeffect: the optimizerJob.Optimizer will be prepared (scopes are deleted and executionstate will be reset)
210    /// </summary>
211    private void UpdateOptimizerInExperiment(Optimization.Experiment experiment, OptimizerJob optimizerJob) {
212      if (optimizerJob.IndexInParentOptimizerList < 0)
213        throw new IndexOutOfRangeException("IndexInParentOptimizerList must be equal or greater than zero! The Job is invalid and the optimizer-tree cannot be reassembled.");
214
215      while (experiment.Optimizers.Count < optimizerJob.IndexInParentOptimizerList) {
216        experiment.Optimizers.Add(new UserDefinedAlgorithm("Placeholder")); // add dummy-entries to Optimizers so that its possible to insert the optimizerJob at the correct position
217      }
218      if (experiment.Optimizers.Count < optimizerJob.IndexInParentOptimizerList + 1) {
219        experiment.Optimizers.Add(optimizerJob.Item);
220      } else {
221        // if ComputeInParallel==true, don't replace the optimizer (except it is still a Placeholder)
222        // this is because Jobs with ComputeInParallel get submitted to hive with their child-optimizers deleted
223        if (!optimizerJob.ComputeInParallel || experiment.Optimizers[optimizerJob.IndexInParentOptimizerList].Name == "Placeholder") {
224          experiment.Optimizers[optimizerJob.IndexInParentOptimizerList] = optimizerJob.Item;
225        }
226      }
227    }
228
229    /// <summary>
230    /// Sets the IndexInParentOptimizerList property of the OptimizerJob
231    /// according to the position in the OptimizerList of the parentHiveJob.Job
232    /// Recursively updates all the child-jobs as well
233    /// </summary>
234    internal void SetIndexInParentOptimizerList(OptimizerHiveJob parentHiveJob) {
235      if (parentHiveJob != null) {
236        if (parentHiveJob.JobItem.Item is Optimization.Experiment) {
237          this.JobItem.IndexInParentOptimizerList = parentHiveJob.JobItem.OptimizerAsExperiment.Optimizers.IndexOf(this.JobItem.Item);
238        } else if (parentHiveJob.JobItem.Item is Optimization.BatchRun) {
239          this.JobItem.IndexInParentOptimizerList = 0;
240        } else {
241          throw new NotSupportedException("Only Experiment and BatchRuns are supported");
242        }
243      }
244      foreach (OptimizerHiveJob child in childHiveJobs) {
245        child.SetIndexInParentOptimizerList(this);
246      }
247    }
248
249    public override void AddChildHiveJob(HiveJob hiveJob) {
250      base.AddChildHiveJob(hiveJob);
251      var optimizerHiveJob = (OptimizerHiveJob)hiveJob;
252      syncJobsWithOptimizers = false;
253      if (this.JobItem != null && optimizerHiveJob.JobItem != null) {
254        // if job is in state Paused, it has to preserve its ResultCollection, which is cleared when a optimizer is added to an experiment
255        OptimizerJob optimizerJobClone = null;
256        if (optimizerHiveJob.Job.State == JobState.Paused) {
257          optimizerJobClone = (OptimizerJob)optimizerHiveJob.JobItem.Clone();
258        }
259
260        if (this.JobItem.Item is Optimization.Experiment) {
261          if (!this.JobItem.OptimizerAsExperiment.Optimizers.Contains(optimizerHiveJob.JobItem.Item)) {
262            UpdateOptimizerInExperiment(this.JobItem.OptimizerAsExperiment, optimizerHiveJob.JobItem);
263          }
264        } else if (this.JobItem.Item is Optimization.BatchRun) {
265          UpdateOptimizerInBatchRun(this.JobItem.OptimizerAsBatchRun, optimizerHiveJob.JobItem);
266        }
267
268        if (optimizerHiveJob.Job.State == JobState.Paused) {
269          optimizerHiveJob.JobItem = optimizerJobClone;
270        }
271      }
272      syncJobsWithOptimizers = true;
273    }
274
275    /// <summary>
276    /// Creates a JobData object containing the Job and the IJob-Object as byte[]
277    /// </summary>
278    /// <param name="withoutChildOptimizers">
279    ///   if true the Child-Optimizers will not be serialized (if the job contains an Experiment)
280    /// </param>
281    public override JobData GetAsJobData(bool withoutChildOptimizers, out List<IPluginDescription> plugins) {
282      plugins = new List<IPluginDescription>();
283      if (this.jobItem == null) // || this.jobItem.Optimizer == null
284        return null;
285
286      IEnumerable<Type> usedTypes;
287      byte[] jobByteArray;
288      if (withoutChildOptimizers && this.JobItem.Item is Optimization.Experiment) {
289        OptimizerJob clonedJob = (OptimizerJob)this.JobItem.Clone(); // use a cloned job, so that the childHiveJob don't get confused
290        clonedJob.OptimizerAsExperiment.Optimizers.Clear();
291        jobByteArray = PersistenceUtil.Serialize(clonedJob, out usedTypes);
292      } else if (withoutChildOptimizers && this.JobItem.Item is Optimization.BatchRun) {
293        OptimizerJob clonedJob = (OptimizerJob)this.JobItem.Clone();
294        clonedJob.OptimizerAsBatchRun.Optimizer = null;
295        jobByteArray = PersistenceUtil.Serialize(clonedJob, out usedTypes);
296      } else if (this.JobItem.Item is IAlgorithm) {
297        ((IAlgorithm)this.JobItem.Item).StoreAlgorithmInEachRun = false; // avoid storing the algorithm in runs to reduce size
298        jobByteArray = PersistenceUtil.Serialize(this.JobItem, out usedTypes);
299      } else {
300        jobByteArray = PersistenceUtil.Serialize(this.JobItem, out usedTypes);
301      }
302
303      JobData jobData = new JobData() {
304        JobId = job.Id,
305        Data = jobByteArray
306      };
307
308      PluginUtil.CollectDeclaringPlugins(plugins, usedTypes);
309
310      return jobData;
311    }
312
313    public OptimizerHiveJob GetChildByOptimizerJob(OptimizerJob optimizerJob) {
314      foreach (OptimizerHiveJob child in ChildHiveJobs) {
315        if (child.JobItem == optimizerJob)
316          return child;
317      }
318      return null;
319    }
320
321    public HiveJob<OptimizerJob> GetChildByOptimizer(IOptimizer optimizer) {
322      foreach (OptimizerHiveJob child in ChildHiveJobs) {
323        if (child.JobItem.Item == optimizer)
324          return child;
325      }
326      return null;
327    }
328
329    #region Helpers
330    /// <summary>
331    /// Parses the run numbers out of runs and renames the run to the next number
332    /// </summary>
333    private static string GetNewRunName(IRun run, RunCollection runs) {
334      int idx = run.Name.IndexOf("Run ") + 4;
335
336      if (idx == -1 || runs.Count == 0)
337        return run.Name;
338
339      int maxRunNumber = int.MinValue;
340      foreach (IRun r in runs) {
341        int number = GetRunNumber(r.Name);
342        maxRunNumber = Math.Max(maxRunNumber, number);
343      }
344
345      return run.Name.Substring(0, idx) + (maxRunNumber + 1).ToString();
346    }
347
348    /// <summary>
349    /// Parses the number of a Run out of its name. Example "Genetic Algorithm Run 3" -> 3
350    /// </summary>
351    private static int GetRunNumber(string runName) {
352      int idx = runName.IndexOf("Run ") + 4;
353      if (idx == -1) {
354        return 0;
355      } else {
356        return int.Parse(runName.Substring(idx, runName.Length - idx));
357      }
358    }
359    #endregion
360  }
361}
Note: See TracBrowser for help on using the repository browser.