source: stable/HeuristicLab.Optimization/3.3/RunCollection.cs @ 11170

Last change on this file since 11170 was 11170, checked in by ascheibe, 8 years ago

#2115 updated copyright year in stable branch

File size: 18.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2014 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.Collections;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Data;
29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
30
31namespace HeuristicLab.Optimization {
32  [Item("Run Collection", "Represents a collection of runs.")]
33  [Creatable("Testing & Analysis")]
34  [StorableClass]
35  public class RunCollection : ItemCollection<IRun>, IStringConvertibleMatrix, IStorableContent {
36    public string Filename { get; set; }
37
38    [StorableConstructor]
39    protected RunCollection(bool deserializing)
40      : base(deserializing) {
41      updateOfRunsInProgress = false;
42    }
43    protected RunCollection(RunCollection original, Cloner cloner)
44      : base(original, cloner) {
45      updateOfRunsInProgress = false;
46      optimizerName = original.optimizerName;
47
48      resultNames = new List<string>(original.resultNames);
49      parameterNames = new List<string>(original.parameterNames);
50      dataTypes = new Dictionary<string, HashSet<Type>>();
51      foreach (string s in original.dataTypes.Keys)
52        dataTypes[s] = new HashSet<Type>(original.dataTypes[s]);
53
54      constraints = new RunCollectionConstraintCollection(original.constraints.Select(x => cloner.Clone(x)));
55      modifiers = new CheckedItemList<IRunCollectionModifier>(original.modifiers.Select(cloner.Clone));
56      foreach (IRunCollectionConstraint constraint in constraints)
57        constraint.ConstrainedValue = this;
58      RegisterConstraintsEvents();
59      RegisterConstraintEvents(constraints);
60
61      UpdateFiltering(true);
62    }
63    public RunCollection() : base() { Initialize(); }
64    public RunCollection(int capacity) : base(capacity) { Initialize(); }
65    public RunCollection(IEnumerable<IRun> collection) : base(collection) { Initialize(); this.OnItemsAdded(collection); }
66    private void Initialize() {
67      updateOfRunsInProgress = false;
68      parameterNames = new List<string>();
69      resultNames = new List<string>();
70      dataTypes = new Dictionary<string, HashSet<Type>>();
71      constraints = new RunCollectionConstraintCollection();
72      modifiers = new CheckedItemList<IRunCollectionModifier>();
73      RegisterConstraintsEvents();
74    }
75
76    [Storable]
77    private Dictionary<string, HashSet<Type>> dataTypes;
78    public IEnumerable<Type> GetDataType(string columnName) {
79      if (!dataTypes.ContainsKey(columnName))
80        return new Type[0];
81      return dataTypes[columnName];
82    }
83
84    [Storable]
85    private RunCollectionConstraintCollection constraints;
86    public RunCollectionConstraintCollection Constraints {
87      get { return constraints; }
88    }
89
90    [Storable]
91    private CheckedItemList<IRunCollectionModifier> modifiers;
92    public CheckedItemList<IRunCollectionModifier> Modifiers {
93      get { return modifiers; }
94    }
95
96
97    private bool updateOfRunsInProgress;
98    public bool UpdateOfRunsInProgress {
99      get { return updateOfRunsInProgress; }
100      set {
101        if (updateOfRunsInProgress != value) {
102          updateOfRunsInProgress = value;
103          OnUpdateOfRunsInProgressChanged();
104        }
105      }
106    }
107
108    private string optimizerName = string.Empty;
109    [Storable]
110    public string OptimizerName {
111      get { return optimizerName; }
112      set {
113        if (value != optimizerName && !string.IsNullOrEmpty(value)) {
114          optimizerName = value;
115          OnOptimizerNameChanged();
116        }
117      }
118    }
119
120    // BackwardsCompatibility3.3
121    #region Backwards compatible code, remove with 3.4
122    [Storable(AllowOneWay = true)]
123    private string AlgorithmName {
124      set { optimizerName = value; }
125    }
126    #endregion
127
128    [StorableHook(HookType.AfterDeserialization)]
129    private void AfterDeserialization() {
130      if (constraints == null) constraints = new RunCollectionConstraintCollection();
131      if (modifiers == null) modifiers = new CheckedItemList<IRunCollectionModifier>();
132      RegisterConstraintsEvents();
133      RegisterConstraintEvents(constraints);
134      UpdateFiltering(true);
135    }
136
137    public override IDeepCloneable Clone(Cloner cloner) {
138      return new RunCollection(this, cloner);
139    }
140
141    public event EventHandler UpdateOfRunsInProgressChanged;
142    protected virtual void OnUpdateOfRunsInProgressChanged() {
143      var handler = UpdateOfRunsInProgressChanged;
144      if (handler != null) handler(this, EventArgs.Empty);
145    }
146
147    public event EventHandler OptimizerNameChanged;
148    protected virtual void OnOptimizerNameChanged() {
149      var handler = OptimizerNameChanged;
150      if (handler != null) handler(this, EventArgs.Empty);
151    }
152
153    protected override void OnCollectionReset(IEnumerable<IRun> items, IEnumerable<IRun> oldItems) {
154      parameterNames.Clear();
155      resultNames.Clear();
156      dataTypes.Clear();
157      foreach (IRun run in items) {
158        foreach (KeyValuePair<string, IItem> parameter in run.Parameters)
159          AddParameter(parameter.Key, parameter.Value);
160        foreach (KeyValuePair<string, IItem> result in run.Results)
161          AddResult(result.Key, result.Value);
162      }
163      columnNameCache = null;
164      OnColumnsChanged();
165      OnColumnNamesChanged();
166      rowNamesCache = null;
167      base.OnCollectionReset(items, oldItems);
168      OnRowsChanged();
169      OnRowNamesChanged();
170      OnReset();
171      UpdateFiltering(false);
172    }
173    protected override void OnItemsAdded(IEnumerable<IRun> items) {
174      bool columnsChanged = false;
175      foreach (IRun run in items) {
176        foreach (KeyValuePair<string, IItem> parameter in run.Parameters)
177          columnsChanged |= AddParameter(parameter.Key, parameter.Value);
178        foreach (KeyValuePair<string, IItem> result in run.Results)
179          columnsChanged |= AddResult(result.Key, result.Value);
180      }
181      if (columnsChanged) columnNameCache = null;
182      rowNamesCache = null;
183      base.OnItemsAdded(items);
184      OnReset();
185      OnRowsChanged();
186      OnRowNamesChanged();
187      if (columnsChanged) {
188        OnColumnsChanged();
189        OnColumnNamesChanged();
190      }
191      UpdateFiltering(false);
192    }
193    protected override void OnItemsRemoved(IEnumerable<IRun> items) {
194      bool columnsChanged = false;
195      foreach (IRun run in items) {
196        foreach (string parameterName in run.Parameters.Keys)
197          columnsChanged |= RemoveParameterName(parameterName);
198        foreach (string resultName in run.Results.Keys)
199          columnsChanged |= RemoveResultName(resultName);
200      }
201      if (columnsChanged) columnNameCache = null;
202      rowNamesCache = null;
203      base.OnItemsRemoved(items);
204      OnReset();
205      OnRowsChanged();
206      OnRowNamesChanged();
207      if (columnsChanged) {
208        OnColumnsChanged();
209        OnColumnNamesChanged();
210      }
211    }
212
213    private bool AddParameter(string name, IItem value) {
214      if (value == null)
215        return false;
216      if (!parameterNames.Contains(name)) {
217        parameterNames.Add(name);
218        dataTypes[name] = new HashSet<Type>();
219        dataTypes[name].Add(value.GetType());
220        return true;
221      }
222      dataTypes[name].Add(value.GetType());
223      return false;
224    }
225    private bool AddResult(string name, IItem value) {
226      if (value == null)
227        return false;
228      if (!resultNames.Contains(name)) {
229        resultNames.Add(name);
230        dataTypes[name] = new HashSet<Type>();
231        dataTypes[name].Add(value.GetType());
232        return true;
233      }
234      dataTypes[name].Add(value.GetType());
235      return false;
236    }
237    private bool RemoveParameterName(string name) {
238      if (!list.Any(x => x.Parameters.ContainsKey(name))) {
239        parameterNames.Remove(name);
240        return true;
241      }
242      return false;
243    }
244    private bool RemoveResultName(string name) {
245      if (!list.Any(x => x.Results.ContainsKey(name))) {
246        resultNames.Remove(name);
247        return true;
248      }
249      return false;
250    }
251
252    public IItem GetValue(int rowIndex, int columnIndex) {
253      IRun run = this.list[rowIndex];
254      return GetValue(run, columnIndex);
255    }
256
257    public IItem GetValue(IRun run, int columnIndex) {
258      string name = ((IStringConvertibleMatrix)this).ColumnNames.ElementAt(columnIndex);
259      return GetValue(run, name);
260    }
261
262    public IItem GetValue(IRun run, string columnName) {
263      IItem value = null;
264      if (run.Parameters.ContainsKey(columnName))
265        value = run.Parameters[columnName];
266      else if (run.Results.ContainsKey(columnName))
267        value = run.Results[columnName];
268      return value;
269    }
270
271    #region IStringConvertibleMatrix Members
272    [Storable]
273    private List<string> parameterNames;
274    public IEnumerable<string> ParameterNames {
275      get { return this.parameterNames; }
276    }
277    [Storable]
278    private List<string> resultNames;
279    public IEnumerable<string> ResultNames {
280      get { return this.resultNames; }
281    }
282    int IStringConvertibleMatrix.Rows {
283      get { return this.Count; }
284      set { throw new NotSupportedException(); }
285    }
286    int IStringConvertibleMatrix.Columns {
287      get { return parameterNames.Count + resultNames.Count; }
288      set { throw new NotSupportedException(); }
289    }
290    private List<string> columnNameCache;
291    IEnumerable<string> IStringConvertibleMatrix.ColumnNames {
292      get {
293        if (columnNameCache == null) {
294          columnNameCache = new List<string>(parameterNames);
295          columnNameCache.AddRange(resultNames);
296          columnNameCache.Sort();
297        }
298        return columnNameCache;
299      }
300      set { throw new NotSupportedException(); }
301    }
302    private List<string> rowNamesCache;
303    IEnumerable<string> IStringConvertibleMatrix.RowNames {
304      get {
305        if (rowNamesCache == null)
306          rowNamesCache = list.Select(x => x.Name).ToList();
307        return rowNamesCache;
308      }
309      set { throw new NotSupportedException(); }
310    }
311    bool IStringConvertibleMatrix.SortableView {
312      get { return true; }
313      set { throw new NotSupportedException(); }
314    }
315    bool IStringConvertibleMatrix.ReadOnly {
316      get { return true; }
317    }
318
319    string IStringConvertibleMatrix.GetValue(int rowIndex, int columnIndex) {
320      IItem value = GetValue(rowIndex, columnIndex);
321      if (value == null)
322        return string.Empty;
323      return value.ToString();
324    }
325
326    public event EventHandler<EventArgs<int, int>> ItemChanged;
327    protected virtual void OnItemChanged(int rowIndex, int columnIndex) {
328      EventHandler<EventArgs<int, int>> handler = ItemChanged;
329      if (handler != null) handler(this, new EventArgs<int, int>(rowIndex, columnIndex));
330      OnToStringChanged();
331    }
332    public event EventHandler Reset;
333    protected virtual void OnReset() {
334      EventHandler handler = Reset;
335      if (handler != null) handler(this, EventArgs.Empty);
336      OnToStringChanged();
337    }
338    public event EventHandler ColumnsChanged;
339    protected virtual void OnColumnsChanged() {
340      var handler = ColumnsChanged;
341      if (handler != null) handler(this, EventArgs.Empty);
342    }
343    public event EventHandler RowsChanged;
344    protected virtual void OnRowsChanged() {
345      var handler = RowsChanged;
346      if (handler != null) handler(this, EventArgs.Empty);
347    }
348    public event EventHandler ColumnNamesChanged;
349    protected virtual void OnColumnNamesChanged() {
350      EventHandler handler = ColumnNamesChanged;
351      if (handler != null) handler(this, EventArgs.Empty);
352    }
353    public event EventHandler RowNamesChanged;
354    protected virtual void OnRowNamesChanged() {
355      EventHandler handler = RowNamesChanged;
356      if (handler != null) handler(this, EventArgs.Empty);
357    }
358    public event EventHandler SortableViewChanged;
359    protected virtual void OnSortableViewChanged() {
360      EventHandler handler = SortableViewChanged;
361      if (handler != null) handler(this, EventArgs.Empty);
362    }
363
364    public bool Validate(string value, out string errorMessage) { throw new NotSupportedException(); }
365    public bool SetValue(string value, int rowIndex, int columnIndex) { throw new NotSupportedException(); }
366    #endregion
367
368    #region Filtering
369    private void UpdateFiltering(bool reset) {
370      UpdateOfRunsInProgress = true;
371      if (reset)
372        list.ForEach(r => r.Visible = true);
373      foreach (IRunCollectionConstraint constraint in this.constraints)
374        constraint.Check();
375      UpdateOfRunsInProgress = false;
376    }
377
378    private void RegisterConstraintsEvents() {
379      constraints.ItemsAdded += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_ItemsAdded);
380      constraints.ItemsRemoved += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_ItemsRemoved);
381      constraints.CollectionReset += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_CollectionReset);
382    }
383
384    protected virtual void RegisterConstraintEvents(IEnumerable<IRunCollectionConstraint> constraints) {
385      foreach (IRunCollectionConstraint constraint in constraints) {
386        constraint.ActiveChanged += new EventHandler(Constraint_ActiveChanged);
387        constraint.ConstrainedValueChanged += new EventHandler(Constraint_ConstrainedValueChanged);
388        constraint.ConstraintOperationChanged += new EventHandler(Constraint_ConstraintOperationChanged);
389        constraint.ConstraintDataChanged += new EventHandler(Constraint_ConstraintDataChanged);
390      }
391    }
392    protected virtual void DeregisterConstraintEvents(IEnumerable<IRunCollectionConstraint> constraints) {
393      foreach (IRunCollectionConstraint constraint in constraints) {
394        constraint.ActiveChanged -= new EventHandler(Constraint_ActiveChanged);
395        constraint.ConstrainedValueChanged -= new EventHandler(Constraint_ConstrainedValueChanged);
396        constraint.ConstraintOperationChanged -= new EventHandler(Constraint_ConstraintOperationChanged);
397        constraint.ConstraintDataChanged -= new EventHandler(Constraint_ConstraintDataChanged);
398      }
399    }
400
401    protected virtual void Constraints_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
402      DeregisterConstraintEvents(e.OldItems);
403      RegisterConstraintEvents(e.Items);
404      this.UpdateFiltering(true);
405    }
406    protected virtual void Constraints_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
407      RegisterConstraintEvents(e.Items);
408      foreach (IRunCollectionConstraint constraint in e.Items)
409        constraint.ConstrainedValue = this;
410      this.UpdateFiltering(false);
411    }
412    protected virtual void Constraints_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
413      DeregisterConstraintEvents(e.Items);
414      this.UpdateFiltering(true);
415    }
416    protected virtual void Constraint_ActiveChanged(object sender, EventArgs e) {
417      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
418      this.UpdateFiltering(!constraint.Active);
419    }
420    protected virtual void Constraint_ConstrainedValueChanged(object sender, EventArgs e) {
421      //mkommend: this method is intentionally left empty, because the constrainedValue is set in the ItemsAdded method
422    }
423    protected virtual void Constraint_ConstraintOperationChanged(object sender, EventArgs e) {
424      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
425      if (constraint.Active)
426        this.UpdateFiltering(true);
427    }
428    protected virtual void Constraint_ConstraintDataChanged(object sender, EventArgs e) {
429      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
430      if (constraint.Active)
431        this.UpdateFiltering(true);
432    }
433    #endregion
434
435    #region Modification
436    public void Modify() {
437      UpdateOfRunsInProgress = true;
438      var runs = this.ToList();
439      var selectedRuns = runs.Where(r => r.Visible).ToList();
440      int nSelected = selectedRuns.Count;
441      if (nSelected > 0) {
442        foreach (var modifier in Modifiers.CheckedItems)
443          modifier.Value.Modify(selectedRuns);
444        if (nSelected != selectedRuns.Count || HaveDifferentOrder(selectedRuns, runs.Where(r => r.Visible))) {
445          Clear();
446          AddRange(ReplaceVisibleRuns(runs, selectedRuns));
447        } else if (runs.Count > 0) {
448          OnCollectionReset(this, runs);
449        }
450      }
451      UpdateOfRunsInProgress = false;
452    }
453
454    private static IEnumerable<IRun> ReplaceVisibleRuns(IEnumerable<IRun> runs, IEnumerable<IRun> visibleRuns) {
455      var newRuns = new List<IRun>();
456      var runIt = runs.GetEnumerator();
457      var visibleRunIt = visibleRuns.GetEnumerator();
458      while (runIt.MoveNext()) {
459        if (runIt.Current != null && !runIt.Current.Visible)
460          newRuns.Add(runIt.Current);
461        else if (visibleRunIt.MoveNext())
462          newRuns.Add(visibleRunIt.Current);
463      }
464      while (visibleRunIt.MoveNext())
465        newRuns.Add(visibleRunIt.Current);
466      return newRuns;
467    }
468
469    private static bool HaveDifferentOrder(IEnumerable<IRun> l1, IEnumerable<IRun> l2) {
470      return l1.Zip(l2, (r1, r2) => r1 != r2).Any();
471    }
472    #endregion
473  }
474}
Note: See TracBrowser for help on using the repository browser.