Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 4311 was 4200, checked in by mkommend, 14 years ago

improved the performance of RunCollections by caching some properties and corrected some bugs in the RunCollectionTabularView (ticket #1144)

File size: 13.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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 {
36    [StorableConstructor]
37    protected RunCollection(bool deserializing) : base(deserializing) { }
38    public RunCollection() : base() { Initialize(); }
39    public RunCollection(int capacity) : base(capacity) { Initialize(); }
40    public RunCollection(IEnumerable<IRun> collection) : base(collection) { Initialize(); this.OnItemsAdded(collection); }
41    private void Initialize() {
42      parameterNames = new List<string>();
43      resultNames = new List<string>();
44      dataTypes = new Dictionary<string, HashSet<Type>>();
45      constraints = new RunCollectionConstraintCollection();
46      RegisterConstraintsEvents();
47    }
48
49    [Storable]
50    private Dictionary<string, HashSet<Type>> dataTypes;
51    public IEnumerable<Type> GetDataType(string columnName) {
52      if (!dataTypes.ContainsKey(columnName))
53        return new Type[0];
54      return dataTypes[columnName];
55    }
56
57    [Storable]
58    private RunCollectionConstraintCollection constraints;
59    public RunCollectionConstraintCollection Constraints {
60      get { return constraints; }
61    }
62
63    protected override void OnCollectionReset(IEnumerable<IRun> items, IEnumerable<IRun> oldItems) {
64      parameterNames.Clear();
65      resultNames.Clear();
66      foreach (IRun run in items) {
67        foreach (KeyValuePair<string, IItem> parameter in run.Parameters)
68          AddParameter(parameter.Key, parameter.Value);
69        foreach (KeyValuePair<string, IItem> result in run.Results)
70          AddResult(result.Key, result.Value);
71      }
72      base.OnCollectionReset(items, oldItems);
73      OnReset();
74      columnNameCache = null;
75      OnColumnNamesChanged();
76      rowNamesCache = null;
77      OnRowNamesChanged();
78    }
79    protected override void OnItemsAdded(IEnumerable<IRun> items) {
80      bool columnNamesChanged = false;
81      foreach (IRun run in items) {
82        foreach (KeyValuePair<string, IItem> parameter in run.Parameters)
83          columnNamesChanged |= AddParameter(parameter.Key, parameter.Value);
84        foreach (KeyValuePair<string, IItem> result in run.Results)
85          columnNamesChanged |= AddResult(result.Key, result.Value);
86      }
87      base.OnItemsAdded(items);
88      OnReset();
89      if (columnNamesChanged) {
90        columnNameCache = null;
91        OnColumnNamesChanged();
92      }
93      rowNamesCache = null;
94      OnRowNamesChanged();
95      this.UpdateFiltering(false);
96    }
97    protected override void OnItemsRemoved(IEnumerable<IRun> items) {
98      bool columnNamesChanged = false;
99      foreach (IRun run in items) {
100        foreach (string parameterName in run.Parameters.Keys)
101          columnNamesChanged |= RemoveParameterName(parameterName);
102        foreach (string resultName in run.Results.Keys)
103          columnNamesChanged |= RemoveResultName(resultName);
104      }
105      base.OnItemsRemoved(items);
106      OnReset();
107      if (columnNamesChanged) {
108        columnNameCache = null;
109        OnColumnNamesChanged();
110      }
111      rowNamesCache = null;
112      OnRowNamesChanged();
113    }
114
115    private bool AddParameter(string name, IItem value) {
116      if (value == null)
117        return false;
118      if (!parameterNames.Contains(name)) {
119        parameterNames.Add(name);
120        dataTypes[name] = new HashSet<Type>();
121        dataTypes[name].Add(value.GetType());
122        return true;
123      }
124      dataTypes[name].Add(value.GetType());
125      return false;
126    }
127    private bool AddResult(string name, IItem value) {
128      if (value == null)
129        return false;
130      if (!resultNames.Contains(name)) {
131        resultNames.Add(name);
132        dataTypes[name] = new HashSet<Type>();
133        dataTypes[name].Add(value.GetType());
134        return true;
135      }
136      dataTypes[name].Add(value.GetType());
137      return false;
138    }
139    private bool RemoveParameterName(string name) {
140      if (!list.Any(x => x.Parameters.ContainsKey(name))) {
141        parameterNames.Remove(name);
142        return true;
143      }
144      return false;
145    }
146    private bool RemoveResultName(string name) {
147      if (!list.Any(x => x.Results.ContainsKey(name))) {
148        resultNames.Remove(name);
149        return true;
150      }
151      return false;
152    }
153
154    public IItem GetValue(int rowIndex, int columnIndex) {
155      IRun run = this.list[rowIndex];
156      return GetValue(run, columnIndex);
157    }
158
159    public IItem GetValue(IRun run, int columnIndex) {
160      string name = ((IStringConvertibleMatrix)this).ColumnNames.ElementAt(columnIndex);
161      return GetValue(run, name);
162    }
163
164    public IItem GetValue(IRun run, string columnName) {
165      IItem value = null;
166      if (run.Parameters.ContainsKey(columnName))
167        value = run.Parameters[columnName];
168      else if (run.Results.ContainsKey(columnName))
169        value = run.Results[columnName];
170      return value;
171    }
172
173    [StorableHook(HookType.AfterDeserialization)]
174    private void AfterDeserializationHook() {
175      if (constraints == null) constraints = new RunCollectionConstraintCollection();
176      RegisterConstraintsEvents();
177      UpdateFiltering(true);
178    }
179
180    public override IDeepCloneable Clone(Cloner cloner) {
181      RunCollection clone = (RunCollection)base.Clone(cloner);
182      clone.resultNames = new List<string>(this.resultNames);
183      clone.parameterNames = new List<string>(this.parameterNames);
184      clone.dataTypes = new Dictionary<string, HashSet<Type>>();
185      foreach (string s in this.dataTypes.Keys)
186        clone.dataTypes[s] = new HashSet<Type>(this.dataTypes[s]);
187
188      clone.constraints = new RunCollectionConstraintCollection(this.constraints.Select(x => (IRunCollectionConstraint)cloner.Clone(x)));
189      foreach (IRunCollectionConstraint constraint in clone.constraints)
190        constraint.ConstrainedValue = clone;
191      clone.RegisterConstraintsEvents();
192      clone.RegisterConstraintEvents(clone.constraints);
193
194      clone.UpdateFiltering(true);
195      return clone;
196    }
197
198    #region IStringConvertibleMatrix Members
199    [Storable]
200    private List<string> parameterNames;
201    public IEnumerable<string> ParameterNames {
202      get { return this.parameterNames; }
203    }
204    [Storable]
205    private List<string> resultNames;
206    public IEnumerable<string> ResultNames {
207      get { return this.resultNames; }
208    }
209    int IStringConvertibleMatrix.Rows {
210      get { return this.Count; }
211      set { throw new NotSupportedException(); }
212    }
213    int IStringConvertibleMatrix.Columns {
214      get { return parameterNames.Count + resultNames.Count; }
215      set { throw new NotSupportedException(); }
216    }
217    private List<string> columnNameCache;
218    IEnumerable<string> IStringConvertibleMatrix.ColumnNames {
219      get {
220        if (columnNameCache == null) {
221          columnNameCache = new List<string>(parameterNames);
222          columnNameCache.AddRange(resultNames);
223          columnNameCache.Sort();
224        }
225        return columnNameCache;
226      }
227      set { throw new NotSupportedException(); }
228    }
229    private List<string> rowNamesCache;
230    IEnumerable<string> IStringConvertibleMatrix.RowNames {
231      get {
232        if (rowNamesCache == null)
233          rowNamesCache = list.Select(x => x.Name).ToList();
234        return rowNamesCache;
235      }
236      set { throw new NotSupportedException(); }
237    }
238    bool IStringConvertibleMatrix.SortableView {
239      get { return true; }
240      set { throw new NotSupportedException(); }
241    }
242    bool IStringConvertibleMatrix.ReadOnly {
243      get { return true; }
244    }
245
246    string IStringConvertibleMatrix.GetValue(int rowIndex, int columnIndex) {
247      IItem value = GetValue(rowIndex, columnIndex);
248      if (value == null)
249        return string.Empty;
250      return value.ToString();
251    }
252
253    public event EventHandler<EventArgs<int, int>> ItemChanged;
254    protected virtual void OnItemChanged(int rowIndex, int columnIndex) {
255      if (ItemChanged != null)
256        ItemChanged(this, new EventArgs<int, int>(rowIndex, columnIndex));
257      OnToStringChanged();
258    }
259    public event EventHandler Reset;
260    protected virtual void OnReset() {
261      if (Reset != null)
262        Reset(this, EventArgs.Empty);
263      OnToStringChanged();
264    }
265    public event EventHandler ColumnNamesChanged;
266    protected virtual void OnColumnNamesChanged() {
267      EventHandler handler = ColumnNamesChanged;
268      if (handler != null)
269        handler(this, EventArgs.Empty);
270    }
271    public event EventHandler RowNamesChanged;
272    protected virtual void OnRowNamesChanged() {
273      EventHandler handler = RowNamesChanged;
274      if (handler != null)
275        handler(this, EventArgs.Empty);
276    }
277    public event EventHandler SortableViewChanged;
278    protected virtual void OnSortableViewChanged() {
279      EventHandler handler = SortableViewChanged;
280      if (handler != null)
281        handler(this, EventArgs.Empty);
282    }
283
284    public bool Validate(string value, out string errorMessage) { throw new NotSupportedException(); }
285    public bool SetValue(string value, int rowIndex, int columnIndex) { throw new NotSupportedException(); }
286    #endregion
287
288    #region filtering
289    private void UpdateFiltering(bool reset) {
290      if (reset)
291        list.ForEach(r => r.Visible = true);
292      foreach (IRunCollectionConstraint constraint in this.constraints)
293        constraint.Check();
294    }
295
296    private void RegisterConstraintsEvents() {
297      constraints.ItemsAdded += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_ItemsAdded);
298      constraints.ItemsRemoved += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_ItemsRemoved);
299      constraints.CollectionReset += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_CollectionReset);
300    }
301
302    protected virtual void RegisterConstraintEvents(IEnumerable<IRunCollectionConstraint> constraints) {
303      foreach (IRunCollectionConstraint constraint in constraints) {
304        constraint.ActiveChanged += new EventHandler(Constraint_ActiveChanged);
305        constraint.ConstrainedValueChanged += new EventHandler(Constraint_ConstrainedValueChanged);
306        constraint.ConstraintOperationChanged += new EventHandler(Constraint_ConstraintOperationChanged);
307        constraint.ConstraintDataChanged += new EventHandler(Constraint_ConstraintDataChanged);
308      }
309    }
310    protected virtual void DeregisterConstraintEvents(IEnumerable<IRunCollectionConstraint> constraints) {
311      foreach (IRunCollectionConstraint constraint in constraints) {
312        constraint.ActiveChanged -= new EventHandler(Constraint_ActiveChanged);
313        constraint.ConstrainedValueChanged -= new EventHandler(Constraint_ConstrainedValueChanged);
314        constraint.ConstraintOperationChanged -= new EventHandler(Constraint_ConstraintOperationChanged);
315        constraint.ConstraintDataChanged -= new EventHandler(Constraint_ConstraintDataChanged);
316      }
317    }
318
319    protected virtual void Constraints_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
320      DeregisterConstraintEvents(e.OldItems);
321      RegisterConstraintEvents(e.Items);
322      this.UpdateFiltering(true);
323    }
324    protected virtual void Constraints_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
325      RegisterConstraintEvents(e.Items);
326      foreach (IRunCollectionConstraint constraint in e.Items)
327        constraint.ConstrainedValue = this;
328      this.UpdateFiltering(false);
329    }
330    protected virtual void Constraints_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
331      DeregisterConstraintEvents(e.Items);
332      this.UpdateFiltering(true);
333    }
334    protected virtual void Constraint_ActiveChanged(object sender, EventArgs e) {
335      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
336      this.UpdateFiltering(!constraint.Active);
337    }
338    protected virtual void Constraint_ConstrainedValueChanged(object sender, EventArgs e) {
339      //mkommend: this method is intentionally left empty, because the constrainedValue is set in the ItemsAdded method
340    }
341    protected virtual void Constraint_ConstraintOperationChanged(object sender, EventArgs e) {
342      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
343      if (constraint.Active)
344        this.UpdateFiltering(true);
345    }
346    protected virtual void Constraint_ConstraintDataChanged(object sender, EventArgs e) {
347      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
348      if (constraint.Active)
349        this.UpdateFiltering(true);
350    }
351    #endregion
352  }
353}
Note: See TracBrowser for help on using the repository browser.