Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Optimization/3.3/RunCollection.cs @ 8962

Last change on this file since 8962 was 8962, checked in by mkommend, 11 years ago

#1673: Added space in view caption between the optimizer name and the view name. Renamed AlgorithmName in RunCollection to OptimizerName as suggested by ascheibe.

File size: 17.9 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.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    [Storable(AllowOneWay = true)]
121    private string AlgorithmName {
122      set { optimizerName = value; }
123    }
124
125    [StorableHook(HookType.AfterDeserialization)]
126    private void AfterDeserialization() {
127      if (constraints == null) constraints = new RunCollectionConstraintCollection();
128      if (modifiers == null) modifiers = new CheckedItemList<IRunCollectionModifier>();
129      RegisterConstraintsEvents();
130      RegisterConstraintEvents(constraints);
131      UpdateFiltering(true);
132    }
133
134    public override IDeepCloneable Clone(Cloner cloner) {
135      return new RunCollection(this, cloner);
136    }
137
138    public event EventHandler UpdateOfRunsInProgressChanged;
139    protected virtual void OnUpdateOfRunsInProgressChanged() {
140      var handler = UpdateOfRunsInProgressChanged;
141      if (handler != null) handler(this, EventArgs.Empty);
142    }
143
144    public event EventHandler OptimizerNameChanged;
145    protected virtual void OnOptimizerNameChanged() {
146      var handler = OptimizerNameChanged;
147      if (handler != null) handler(this, EventArgs.Empty);
148    }
149
150    protected override void OnCollectionReset(IEnumerable<IRun> items, IEnumerable<IRun> oldItems) {
151      parameterNames.Clear();
152      resultNames.Clear();
153      dataTypes.Clear();
154      foreach (IRun run in items) {
155        foreach (KeyValuePair<string, IItem> parameter in run.Parameters)
156          AddParameter(parameter.Key, parameter.Value);
157        foreach (KeyValuePair<string, IItem> result in run.Results)
158          AddResult(result.Key, result.Value);
159      }
160      columnNameCache = null;
161      OnColumnsChanged();
162      OnColumnNamesChanged();
163      rowNamesCache = null;
164      base.OnCollectionReset(items, oldItems);
165      OnRowsChanged();
166      OnRowNamesChanged();
167      OnReset();
168      UpdateFiltering(false);
169    }
170    protected override void OnItemsAdded(IEnumerable<IRun> items) {
171      bool columnsChanged = false;
172      foreach (IRun run in items) {
173        foreach (KeyValuePair<string, IItem> parameter in run.Parameters)
174          columnsChanged |= AddParameter(parameter.Key, parameter.Value);
175        foreach (KeyValuePair<string, IItem> result in run.Results)
176          columnsChanged |= AddResult(result.Key, result.Value);
177      }
178      if (columnsChanged) columnNameCache = null;
179      rowNamesCache = null;
180      base.OnItemsAdded(items);
181      OnReset();
182      OnRowsChanged();
183      OnRowNamesChanged();
184      if (columnsChanged) {
185        OnColumnsChanged();
186        OnColumnNamesChanged();
187      }
188      UpdateFiltering(false);
189    }
190    protected override void OnItemsRemoved(IEnumerable<IRun> items) {
191      bool columnsChanged = false;
192      foreach (IRun run in items) {
193        foreach (string parameterName in run.Parameters.Keys)
194          columnsChanged |= RemoveParameterName(parameterName);
195        foreach (string resultName in run.Results.Keys)
196          columnsChanged |= RemoveResultName(resultName);
197      }
198      if (columnsChanged) columnNameCache = null;
199      rowNamesCache = null;
200      base.OnItemsRemoved(items);
201      OnReset();
202      OnRowsChanged();
203      OnRowNamesChanged();
204      if (columnsChanged) {
205        OnColumnsChanged();
206        OnColumnNamesChanged();
207      }
208    }
209
210    private bool AddParameter(string name, IItem value) {
211      if (value == null)
212        return false;
213      if (!parameterNames.Contains(name)) {
214        parameterNames.Add(name);
215        dataTypes[name] = new HashSet<Type>();
216        dataTypes[name].Add(value.GetType());
217        return true;
218      }
219      dataTypes[name].Add(value.GetType());
220      return false;
221    }
222    private bool AddResult(string name, IItem value) {
223      if (value == null)
224        return false;
225      if (!resultNames.Contains(name)) {
226        resultNames.Add(name);
227        dataTypes[name] = new HashSet<Type>();
228        dataTypes[name].Add(value.GetType());
229        return true;
230      }
231      dataTypes[name].Add(value.GetType());
232      return false;
233    }
234    private bool RemoveParameterName(string name) {
235      if (!list.Any(x => x.Parameters.ContainsKey(name))) {
236        parameterNames.Remove(name);
237        return true;
238      }
239      return false;
240    }
241    private bool RemoveResultName(string name) {
242      if (!list.Any(x => x.Results.ContainsKey(name))) {
243        resultNames.Remove(name);
244        return true;
245      }
246      return false;
247    }
248
249    public IItem GetValue(int rowIndex, int columnIndex) {
250      IRun run = this.list[rowIndex];
251      return GetValue(run, columnIndex);
252    }
253
254    public IItem GetValue(IRun run, int columnIndex) {
255      string name = ((IStringConvertibleMatrix)this).ColumnNames.ElementAt(columnIndex);
256      return GetValue(run, name);
257    }
258
259    public IItem GetValue(IRun run, string columnName) {
260      IItem value = null;
261      if (run.Parameters.ContainsKey(columnName))
262        value = run.Parameters[columnName];
263      else if (run.Results.ContainsKey(columnName))
264        value = run.Results[columnName];
265      return value;
266    }
267
268    #region IStringConvertibleMatrix Members
269    [Storable]
270    private List<string> parameterNames;
271    public IEnumerable<string> ParameterNames {
272      get { return this.parameterNames; }
273    }
274    [Storable]
275    private List<string> resultNames;
276    public IEnumerable<string> ResultNames {
277      get { return this.resultNames; }
278    }
279    int IStringConvertibleMatrix.Rows {
280      get { return this.Count; }
281      set { throw new NotSupportedException(); }
282    }
283    int IStringConvertibleMatrix.Columns {
284      get { return parameterNames.Count + resultNames.Count; }
285      set { throw new NotSupportedException(); }
286    }
287    private List<string> columnNameCache;
288    IEnumerable<string> IStringConvertibleMatrix.ColumnNames {
289      get {
290        if (columnNameCache == null) {
291          columnNameCache = new List<string>(parameterNames);
292          columnNameCache.AddRange(resultNames);
293          columnNameCache.Sort();
294        }
295        return columnNameCache;
296      }
297      set { throw new NotSupportedException(); }
298    }
299    private List<string> rowNamesCache;
300    IEnumerable<string> IStringConvertibleMatrix.RowNames {
301      get {
302        if (rowNamesCache == null)
303          rowNamesCache = list.Select(x => x.Name).ToList();
304        return rowNamesCache;
305      }
306      set { throw new NotSupportedException(); }
307    }
308    bool IStringConvertibleMatrix.SortableView {
309      get { return true; }
310      set { throw new NotSupportedException(); }
311    }
312    bool IStringConvertibleMatrix.ReadOnly {
313      get { return true; }
314    }
315
316    string IStringConvertibleMatrix.GetValue(int rowIndex, int columnIndex) {
317      IItem value = GetValue(rowIndex, columnIndex);
318      if (value == null)
319        return string.Empty;
320      return value.ToString();
321    }
322
323    public event EventHandler<EventArgs<int, int>> ItemChanged;
324    protected virtual void OnItemChanged(int rowIndex, int columnIndex) {
325      EventHandler<EventArgs<int, int>> handler = ItemChanged;
326      if (handler != null) handler(this, new EventArgs<int, int>(rowIndex, columnIndex));
327      OnToStringChanged();
328    }
329    public event EventHandler Reset;
330    protected virtual void OnReset() {
331      EventHandler handler = Reset;
332      if (handler != null) handler(this, EventArgs.Empty);
333      OnToStringChanged();
334    }
335    public event EventHandler ColumnsChanged;
336    protected virtual void OnColumnsChanged() {
337      var handler = ColumnsChanged;
338      if (handler != null) handler(this, EventArgs.Empty);
339    }
340    public event EventHandler RowsChanged;
341    protected virtual void OnRowsChanged() {
342      var handler = RowsChanged;
343      if (handler != null) handler(this, EventArgs.Empty);
344    }
345    public event EventHandler ColumnNamesChanged;
346    protected virtual void OnColumnNamesChanged() {
347      EventHandler handler = ColumnNamesChanged;
348      if (handler != null) handler(this, EventArgs.Empty);
349    }
350    public event EventHandler RowNamesChanged;
351    protected virtual void OnRowNamesChanged() {
352      EventHandler handler = RowNamesChanged;
353      if (handler != null) handler(this, EventArgs.Empty);
354    }
355    public event EventHandler SortableViewChanged;
356    protected virtual void OnSortableViewChanged() {
357      EventHandler handler = SortableViewChanged;
358      if (handler != null) handler(this, EventArgs.Empty);
359    }
360
361    public bool Validate(string value, out string errorMessage) { throw new NotSupportedException(); }
362    public bool SetValue(string value, int rowIndex, int columnIndex) { throw new NotSupportedException(); }
363    #endregion
364
365    #region Filtering
366    private void UpdateFiltering(bool reset) {
367      UpdateOfRunsInProgress = true;
368      if (reset)
369        list.ForEach(r => r.Visible = true);
370      foreach (IRunCollectionConstraint constraint in this.constraints)
371        constraint.Check();
372      UpdateOfRunsInProgress = false;
373    }
374
375    private void RegisterConstraintsEvents() {
376      constraints.ItemsAdded += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_ItemsAdded);
377      constraints.ItemsRemoved += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_ItemsRemoved);
378      constraints.CollectionReset += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_CollectionReset);
379    }
380
381    protected virtual void RegisterConstraintEvents(IEnumerable<IRunCollectionConstraint> constraints) {
382      foreach (IRunCollectionConstraint constraint in constraints) {
383        constraint.ActiveChanged += new EventHandler(Constraint_ActiveChanged);
384        constraint.ConstrainedValueChanged += new EventHandler(Constraint_ConstrainedValueChanged);
385        constraint.ConstraintOperationChanged += new EventHandler(Constraint_ConstraintOperationChanged);
386        constraint.ConstraintDataChanged += new EventHandler(Constraint_ConstraintDataChanged);
387      }
388    }
389    protected virtual void DeregisterConstraintEvents(IEnumerable<IRunCollectionConstraint> constraints) {
390      foreach (IRunCollectionConstraint constraint in constraints) {
391        constraint.ActiveChanged -= new EventHandler(Constraint_ActiveChanged);
392        constraint.ConstrainedValueChanged -= new EventHandler(Constraint_ConstrainedValueChanged);
393        constraint.ConstraintOperationChanged -= new EventHandler(Constraint_ConstraintOperationChanged);
394        constraint.ConstraintDataChanged -= new EventHandler(Constraint_ConstraintDataChanged);
395      }
396    }
397
398    protected virtual void Constraints_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
399      DeregisterConstraintEvents(e.OldItems);
400      RegisterConstraintEvents(e.Items);
401      this.UpdateFiltering(true);
402    }
403    protected virtual void Constraints_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
404      RegisterConstraintEvents(e.Items);
405      foreach (IRunCollectionConstraint constraint in e.Items)
406        constraint.ConstrainedValue = this;
407      this.UpdateFiltering(false);
408    }
409    protected virtual void Constraints_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
410      DeregisterConstraintEvents(e.Items);
411      this.UpdateFiltering(true);
412    }
413    protected virtual void Constraint_ActiveChanged(object sender, EventArgs e) {
414      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
415      this.UpdateFiltering(!constraint.Active);
416    }
417    protected virtual void Constraint_ConstrainedValueChanged(object sender, EventArgs e) {
418      //mkommend: this method is intentionally left empty, because the constrainedValue is set in the ItemsAdded method
419    }
420    protected virtual void Constraint_ConstraintOperationChanged(object sender, EventArgs e) {
421      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
422      if (constraint.Active)
423        this.UpdateFiltering(true);
424    }
425    protected virtual void Constraint_ConstraintDataChanged(object sender, EventArgs e) {
426      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
427      if (constraint.Active)
428        this.UpdateFiltering(true);
429    }
430    #endregion
431
432    #region Modification
433    public void Modify() {
434      UpdateOfRunsInProgress = true;
435      var runs = this.ToList();
436      var selectedRuns = runs.Where(r => r.Visible).ToList();
437      int nSelected = selectedRuns.Count;
438      if (nSelected > 0) {
439        foreach (var modifier in Modifiers.CheckedItems)
440          modifier.Value.Modify(selectedRuns);
441        if (nSelected != selectedRuns.Count || HaveDifferentOrder(selectedRuns, runs.Where(r => r.Visible))) {
442          Clear();
443          AddRange(ReplaceVisibleRuns(runs, selectedRuns));
444        } else if (runs.Count > 0) {
445          OnCollectionReset(this, runs);
446        }
447      }
448      UpdateOfRunsInProgress = false;
449    }
450
451    private static IEnumerable<IRun> ReplaceVisibleRuns(IEnumerable<IRun> runs, IEnumerable<IRun> visibleRuns) {
452      var newRuns = new List<IRun>();
453      var runIt = runs.GetEnumerator();
454      var visibleRunIt = visibleRuns.GetEnumerator();
455      while (runIt.MoveNext()) {
456        if (runIt.Current != null && !runIt.Current.Visible)
457          newRuns.Add(runIt.Current);
458        else if (visibleRunIt.MoveNext())
459          newRuns.Add(visibleRunIt.Current);
460      }
461      while (visibleRunIt.MoveNext())
462        newRuns.Add(visibleRunIt.Current);
463      return newRuns;
464    }
465
466    private static bool HaveDifferentOrder(IEnumerable<IRun> l1, IEnumerable<IRun> l2) {
467      return l1.Zip(l2, (r1, r2) => r1 != r2).Any();
468    }
469    #endregion
470  }
471}
Note: See TracBrowser for help on using the repository browser.