Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PersistenceSpeedUp/HeuristicLab.Optimization/3.3/RunCollection.cs @ 10851

Last change on this file since 10851 was 6760, checked in by epitzer, 13 years ago

#1530 integrate changes from trunk

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