Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 17115 was 17105, checked in by mkommend, 5 years ago

#2520: Merged 16584, 16585,16594,16595, 16625, 16658, 16659, 16672, 16707, 16729, 16792, 16796, 16797, 16799, 16819, 16906, 16907, 16908, 16933, 16945, 16992, 16994, 16995, 16996, 16997, 17014, 17015, 17017, 17020, 17021, 17022, 17023, 17024, 17029, 17086, 17087, 17088, 17089 into stable.

File size: 22.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2019 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.ComponentModel;
25using System.Linq;
26using HeuristicLab.Collections;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HEAL.Attic;
31
32namespace HeuristicLab.Optimization {
33  [Item("Run Collection", "Represents a collection of runs.")]
34  [Creatable(CreatableAttribute.Categories.TestingAndAnalysis, Priority = 120)]
35  [StorableType("6A9E959B-62DB-4998-BFC6-BF3BAE66BED4")]
36  public class RunCollection : ItemCollection<IRun>, IStringConvertibleMatrix, IStorableContent {
37    public string Filename { get; set; }
38
39    [StorableConstructor]
40    protected RunCollection(StorableConstructorFlag _) : base(_) {
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      foreach (var run in this) {
62        RegisterRunParametersEvents(run);
63        RegisterRunResultsEvents(run);
64      }
65
66      UpdateFiltering(true);
67    }
68    public RunCollection() : base() { Initialize(); }
69    public RunCollection(int capacity) : base(capacity) { Initialize(); }
70    public RunCollection(IEnumerable<IRun> collection) : base(collection) { Initialize(); this.OnItemsAdded(collection); }
71    private void Initialize() {
72      updateOfRunsInProgress = false;
73      parameterNames = new List<string>();
74      resultNames = new List<string>();
75      dataTypes = new Dictionary<string, HashSet<Type>>();
76      constraints = new RunCollectionConstraintCollection();
77      modifiers = new CheckedItemList<IRunCollectionModifier>();
78      RegisterConstraintsEvents();
79    }
80
81    [Storable]
82    private Dictionary<string, HashSet<Type>> dataTypes;
83    public IEnumerable<Type> GetDataType(string columnName) {
84      if (!dataTypes.ContainsKey(columnName))
85        return new Type[0];
86      return dataTypes[columnName];
87    }
88
89    [Storable]
90    private RunCollectionConstraintCollection constraints;
91    public RunCollectionConstraintCollection Constraints {
92      get { return constraints; }
93    }
94
95    [Storable]
96    private CheckedItemList<IRunCollectionModifier> modifiers;
97    public CheckedItemList<IRunCollectionModifier> Modifiers {
98      get { return modifiers; }
99    }
100
101
102    private bool updateOfRunsInProgress;
103    public bool UpdateOfRunsInProgress {
104      get { return updateOfRunsInProgress; }
105      set {
106        if (updateOfRunsInProgress != value) {
107          updateOfRunsInProgress = value;
108          OnUpdateOfRunsInProgressChanged();
109        }
110      }
111    }
112
113    private string optimizerName = string.Empty;
114    [Storable]
115    public string OptimizerName {
116      get { return optimizerName; }
117      set {
118        if (value != optimizerName && !string.IsNullOrEmpty(value)) {
119          optimizerName = value;
120          OnOptimizerNameChanged();
121        }
122      }
123    }
124
125    // BackwardsCompatibility3.3
126    #region Backwards compatible code, remove with 3.4
127    [Storable(OldName = "AlgorithmName")]
128    private string AlgorithmName {
129      set { optimizerName = value; }
130    }
131    #endregion
132
133    [StorableHook(HookType.AfterDeserialization)]
134    private void AfterDeserialization() {
135      if (constraints == null) constraints = new RunCollectionConstraintCollection();
136      if (modifiers == null) modifiers = new CheckedItemList<IRunCollectionModifier>();
137      RegisterConstraintsEvents();
138      RegisterConstraintEvents(constraints);
139
140      foreach (var run in this) {
141        RegisterRunParametersEvents(run);
142        RegisterRunResultsEvents(run);
143      }
144      UpdateFiltering(true);
145    }
146
147    public override IDeepCloneable Clone(Cloner cloner) {
148      return new RunCollection(this, cloner);
149    }
150
151    public event EventHandler UpdateOfRunsInProgressChanged;
152    protected virtual void OnUpdateOfRunsInProgressChanged() {
153      var handler = UpdateOfRunsInProgressChanged;
154      if (handler != null) handler(this, EventArgs.Empty);
155    }
156
157    public event EventHandler OptimizerNameChanged;
158    protected virtual void OnOptimizerNameChanged() {
159      var handler = OptimizerNameChanged;
160      if (handler != null) handler(this, EventArgs.Empty);
161    }
162
163    protected override void OnCollectionReset(IEnumerable<IRun> items, IEnumerable<IRun> oldItems) {
164      parameterNames.Clear();
165      resultNames.Clear();
166      dataTypes.Clear();
167      foreach (IRun run in items) {
168        foreach (KeyValuePair<string, IItem> parameter in run.Parameters)
169          AddParameter(parameter.Key, parameter.Value);
170        foreach (KeyValuePair<string, IItem> result in run.Results)
171          AddResult(result.Key, result.Value);
172        run.PropertyChanged += RunOnPropertyChanged;
173        RegisterRunParametersEvents(run);
174        RegisterRunResultsEvents(run);
175      }
176      foreach (IRun run in oldItems) {
177        run.PropertyChanged -= RunOnPropertyChanged;
178        DeregisterRunParametersEvents(run);
179        DeregisterRunResultsEvents(run);
180      }
181      columnNameCache = null;
182      OnColumnsChanged();
183      OnColumnNamesChanged();
184      rowNamesCache = null;
185      base.OnCollectionReset(items, oldItems);
186      OnRowsChanged();
187      OnRowNamesChanged();
188      OnReset();
189      UpdateFiltering(false);
190    }
191    protected override void OnItemsAdded(IEnumerable<IRun> items) {
192      bool columnsChanged = false;
193      foreach (IRun run in items) {
194        foreach (KeyValuePair<string, IItem> parameter in run.Parameters)
195          columnsChanged |= AddParameter(parameter.Key, parameter.Value);
196        foreach (KeyValuePair<string, IItem> result in run.Results)
197          columnsChanged |= AddResult(result.Key, result.Value);
198        run.PropertyChanged += RunOnPropertyChanged;
199        RegisterRunParametersEvents(run);
200        RegisterRunResultsEvents(run);
201      }
202      if (columnsChanged) columnNameCache = null;
203      rowNamesCache = null;
204      base.OnItemsAdded(items);
205      OnReset();
206      OnRowsChanged();
207      OnRowNamesChanged();
208      if (columnsChanged) {
209        OnColumnsChanged();
210        OnColumnNamesChanged();
211      }
212      UpdateFiltering(false);
213    }
214    protected override void OnItemsRemoved(IEnumerable<IRun> items) {
215      bool columnsChanged = false;
216      foreach (IRun run in items) {
217        foreach (string parameterName in run.Parameters.Keys)
218          columnsChanged |= RemoveParameterName(parameterName);
219        foreach (string resultName in run.Results.Keys)
220          columnsChanged |= RemoveResultName(resultName);
221        run.PropertyChanged -= RunOnPropertyChanged;
222        DeregisterRunParametersEvents(run);
223        DeregisterRunResultsEvents(run);
224      }
225      if (columnsChanged) columnNameCache = null;
226      rowNamesCache = null;
227      base.OnItemsRemoved(items);
228      OnReset();
229      OnRowsChanged();
230      OnRowNamesChanged();
231      if (columnsChanged) {
232        OnColumnsChanged();
233        OnColumnNamesChanged();
234      }
235    }
236
237    private void RunOnPropertyChanged(object sender, PropertyChangedEventArgs e) {
238      if (e.PropertyName == "Parameters") {
239        RegisterRunParametersEvents((IRun)sender);
240      } else if (e.PropertyName == "Results") {
241        RegisterRunResultsEvents((IRun)sender);
242      }
243    }
244
245    private void RegisterRunParametersEvents(IRun run) {
246      IObservableDictionary<string, IItem> dict = run.Parameters;
247      dict.ItemsAdded += RunOnParameterChanged;
248      dict.ItemsRemoved += RunOnParameterRemoved;
249      dict.ItemsReplaced += RunOnParameterChanged;
250      dict.CollectionReset += RunOnParameterChanged;
251    }
252
253    private void RegisterRunResultsEvents(IRun run) {
254      IObservableDictionary<string, IItem> dict = run.Results;
255      dict.ItemsAdded += RunOnResultChanged;
256      dict.ItemsRemoved += RunOnResultRemoved;
257      dict.ItemsReplaced += RunOnResultChanged;
258      dict.CollectionReset += RunOnResultChanged;
259    }
260
261    private void DeregisterRunParametersEvents(IRun run) {
262      IObservableDictionary<string, IItem> dict = run.Parameters;
263      dict.ItemsAdded -= RunOnParameterChanged;
264      dict.ItemsRemoved -= RunOnParameterRemoved;
265      dict.ItemsReplaced -= RunOnParameterChanged;
266      dict.CollectionReset -= RunOnParameterChanged;
267    }
268
269    private void DeregisterRunResultsEvents(IRun run) {
270      IObservableDictionary<string, IItem> dict = run.Results;
271      dict.ItemsAdded -= RunOnResultChanged;
272      dict.ItemsRemoved -= RunOnResultRemoved;
273      dict.ItemsReplaced -= RunOnResultChanged;
274      dict.CollectionReset -= RunOnResultChanged;
275    }
276
277    private void RunOnParameterChanged(object sender, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>> e) {
278      bool columnsChanged = false;
279      foreach (var param in e.Items)
280        columnsChanged |= AddParameter(param.Key, param.Value);
281      foreach (var param in e.OldItems)
282        columnsChanged |= RemoveParameterName(param.Key);
283      if (columnsChanged) columnNameCache = null;
284      OnReset();
285      if (columnsChanged) {
286        OnColumnsChanged();
287        OnColumnNamesChanged();
288      }
289    }
290
291    private void RunOnParameterRemoved(object sender, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>> e) {
292      bool columnsChanged = false;
293      foreach (var param in e.Items)
294        columnsChanged |= RemoveParameterName(param.Key);
295      if (columnsChanged) columnNameCache = null;
296      OnReset();
297      if (columnsChanged) {
298        OnColumnsChanged();
299        OnColumnNamesChanged();
300      }
301    }
302
303    private void RunOnResultChanged(object sender, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>> e) {
304      bool columnsChanged = false;
305      foreach (var result in e.Items)
306        columnsChanged |= AddResult(result.Key, result.Value);
307      foreach (var result in e.OldItems)
308        columnsChanged |= RemoveResultName(result.Key);
309      if (columnsChanged) columnNameCache = null;
310      OnReset();
311      if (columnsChanged) {
312        OnColumnsChanged();
313        OnColumnNamesChanged();
314      }
315    }
316
317    private void RunOnResultRemoved(object sender, CollectionItemsChangedEventArgs<KeyValuePair<string, IItem>> e) {
318      bool columnsChanged = false;
319      foreach (var result in e.Items)
320        columnsChanged |= RemoveResultName(result.Key);
321      if (columnsChanged) columnNameCache = null;
322      OnReset();
323      if (columnsChanged) {
324        OnColumnsChanged();
325        OnColumnNamesChanged();
326      }
327    }
328
329    private bool AddParameter(string name, IItem value) {
330      if (value == null)
331        return false;
332      if (!parameterNames.Contains(name)) {
333        parameterNames.Add(name);
334        dataTypes[name] = new HashSet<Type>();
335        dataTypes[name].Add(value.GetType());
336        return true;
337      }
338      dataTypes[name].Add(value.GetType());
339      return false;
340    }
341    private bool AddResult(string name, IItem value) {
342      if (value == null)
343        return false;
344      if (!resultNames.Contains(name)) {
345        resultNames.Add(name);
346        dataTypes[name] = new HashSet<Type>();
347        dataTypes[name].Add(value.GetType());
348        return true;
349      }
350      dataTypes[name].Add(value.GetType());
351      return false;
352    }
353    private bool RemoveParameterName(string name) {
354      if (!list.Any(x => x.Parameters.ContainsKey(name))) {
355        parameterNames.Remove(name);
356        return true;
357      }
358      return false;
359    }
360    private bool RemoveResultName(string name) {
361      if (!list.Any(x => x.Results.ContainsKey(name))) {
362        resultNames.Remove(name);
363        return true;
364      }
365      return false;
366    }
367
368    public IItem GetValue(int rowIndex, int columnIndex) {
369      IRun run = this.list[rowIndex];
370      return GetValue(run, columnIndex);
371    }
372
373    public IItem GetValue(IRun run, int columnIndex) {
374      string name = ((IStringConvertibleMatrix)this).ColumnNames.ElementAt(columnIndex);
375      return GetValue(run, name);
376    }
377
378    public IItem GetValue(IRun run, string columnName) {
379      IItem value = null;
380      if (run.Parameters.ContainsKey(columnName))
381        value = run.Parameters[columnName];
382      else if (run.Results.ContainsKey(columnName))
383        value = run.Results[columnName];
384      return value;
385    }
386
387    #region IStringConvertibleMatrix Members
388    [Storable]
389    private List<string> parameterNames;
390    public IEnumerable<string> ParameterNames {
391      get { return this.parameterNames; }
392    }
393    [Storable]
394    private List<string> resultNames;
395    public IEnumerable<string> ResultNames {
396      get { return this.resultNames; }
397    }
398    int IStringConvertibleMatrix.Rows {
399      get { return this.Count; }
400      set { throw new NotSupportedException(); }
401    }
402    int IStringConvertibleMatrix.Columns {
403      get { return parameterNames.Count + resultNames.Count; }
404      set { throw new NotSupportedException(); }
405    }
406    private List<string> columnNameCache;
407    IEnumerable<string> IStringConvertibleMatrix.ColumnNames {
408      get {
409        if (columnNameCache == null) {
410          columnNameCache = new List<string>(parameterNames);
411          columnNameCache.AddRange(resultNames);
412          columnNameCache.Sort();
413        }
414        return columnNameCache;
415      }
416      set { throw new NotSupportedException(); }
417    }
418    private List<string> rowNamesCache;
419    IEnumerable<string> IStringConvertibleMatrix.RowNames {
420      get {
421        if (rowNamesCache == null)
422          rowNamesCache = list.Select(x => x.Name).ToList();
423        return rowNamesCache;
424      }
425      set { throw new NotSupportedException(); }
426    }
427    bool IStringConvertibleMatrix.SortableView {
428      get { return true; }
429      set { throw new NotSupportedException(); }
430    }
431    bool IStringConvertibleMatrix.ReadOnly {
432      get { return true; }
433    }
434
435    string IStringConvertibleMatrix.GetValue(int rowIndex, int columnIndex) {
436      IItem value = GetValue(rowIndex, columnIndex);
437      if (value == null)
438        return string.Empty;
439      return value.ToString();
440    }
441
442    public event EventHandler<EventArgs<int, int>> ItemChanged;
443    protected virtual void OnItemChanged(int rowIndex, int columnIndex) {
444      EventHandler<EventArgs<int, int>> handler = ItemChanged;
445      if (handler != null) handler(this, new EventArgs<int, int>(rowIndex, columnIndex));
446    }
447    public event EventHandler Reset;
448    protected virtual void OnReset() {
449      EventHandler handler = Reset;
450      if (handler != null) handler(this, EventArgs.Empty);
451    }
452    public event EventHandler ColumnsChanged;
453    protected virtual void OnColumnsChanged() {
454      var handler = ColumnsChanged;
455      if (handler != null) handler(this, EventArgs.Empty);
456    }
457    public event EventHandler RowsChanged;
458    protected virtual void OnRowsChanged() {
459      var handler = RowsChanged;
460      if (handler != null) handler(this, EventArgs.Empty);
461    }
462    public event EventHandler ColumnNamesChanged;
463    protected virtual void OnColumnNamesChanged() {
464      EventHandler handler = ColumnNamesChanged;
465      if (handler != null) handler(this, EventArgs.Empty);
466    }
467    public event EventHandler RowNamesChanged;
468    protected virtual void OnRowNamesChanged() {
469      EventHandler handler = RowNamesChanged;
470      if (handler != null) handler(this, EventArgs.Empty);
471    }
472    public event EventHandler SortableViewChanged;
473    protected virtual void OnSortableViewChanged() {
474      EventHandler handler = SortableViewChanged;
475      if (handler != null) handler(this, EventArgs.Empty);
476    }
477
478    public bool Validate(string value, out string errorMessage) { throw new NotSupportedException(); }
479    public bool SetValue(string value, int rowIndex, int columnIndex) { throw new NotSupportedException(); }
480    #endregion
481
482    #region Filtering
483    private void UpdateFiltering(bool reset) {
484      if (reset)
485        list.ForEach(r => r.Visible = true);
486      foreach (IRunCollectionConstraint constraint in this.constraints)
487        constraint.Check();
488    }
489
490    private void RegisterConstraintsEvents() {
491      constraints.ItemsAdded += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_ItemsAdded);
492      constraints.ItemsRemoved += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_ItemsRemoved);
493      constraints.CollectionReset += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_CollectionReset);
494    }
495
496    private void RegisterConstraintEvents(IEnumerable<IRunCollectionConstraint> constraints) {
497      foreach (IRunCollectionConstraint constraint in constraints) {
498        constraint.ActiveChanged += new EventHandler(Constraint_ActiveChanged);
499        constraint.ConstrainedValueChanged += new EventHandler(Constraint_ConstrainedValueChanged);
500        constraint.ConstraintOperationChanged += new EventHandler(Constraint_ConstraintOperationChanged);
501        constraint.ConstraintDataChanged += new EventHandler(Constraint_ConstraintDataChanged);
502      }
503    }
504    private void DeregisterConstraintEvents(IEnumerable<IRunCollectionConstraint> constraints) {
505      foreach (IRunCollectionConstraint constraint in constraints) {
506        constraint.ActiveChanged -= new EventHandler(Constraint_ActiveChanged);
507        constraint.ConstrainedValueChanged -= new EventHandler(Constraint_ConstrainedValueChanged);
508        constraint.ConstraintOperationChanged -= new EventHandler(Constraint_ConstraintOperationChanged);
509        constraint.ConstraintDataChanged -= new EventHandler(Constraint_ConstraintDataChanged);
510      }
511    }
512
513    protected virtual void Constraints_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
514      DeregisterConstraintEvents(e.OldItems);
515      RegisterConstraintEvents(e.Items);
516      this.UpdateFiltering(true);
517    }
518    protected virtual void Constraints_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
519      RegisterConstraintEvents(e.Items);
520      foreach (IRunCollectionConstraint constraint in e.Items)
521        constraint.ConstrainedValue = this;
522      this.UpdateFiltering(false);
523    }
524    protected virtual void Constraints_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
525      DeregisterConstraintEvents(e.Items);
526      this.UpdateFiltering(true);
527    }
528    protected virtual void Constraint_ActiveChanged(object sender, EventArgs e) {
529      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
530      this.UpdateFiltering(!constraint.Active);
531    }
532    protected virtual void Constraint_ConstrainedValueChanged(object sender, EventArgs e) {
533      //mkommend: this method is intentionally left empty, because the constrainedValue is set in the ItemsAdded method
534    }
535    protected virtual void Constraint_ConstraintOperationChanged(object sender, EventArgs e) {
536      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
537      if (constraint.Active) {
538        var oldUpdateRuns = UpdateOfRunsInProgress;
539        try {
540          UpdateOfRunsInProgress = true;
541          UpdateFiltering(true);
542        } finally { UpdateOfRunsInProgress = oldUpdateRuns; }
543      }
544    }
545    protected virtual void Constraint_ConstraintDataChanged(object sender, EventArgs e) {
546      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
547      if (constraint.Active) {
548        var oldUpdateRuns = UpdateOfRunsInProgress;
549        try {
550          UpdateOfRunsInProgress = true;
551          UpdateFiltering(true);
552        } finally { UpdateOfRunsInProgress = oldUpdateRuns; }
553      }
554    }
555    #endregion
556
557    #region Modification
558    public void Modify() {
559      var runs = this.ToList();
560      var selectedRuns = runs.Where(r => r.Visible).ToList();
561      int nSelected = selectedRuns.Count;
562      if (nSelected > 0) {
563        foreach (var modifier in Modifiers.CheckedItems)
564          modifier.Value.Modify(selectedRuns);
565        if (nSelected != selectedRuns.Count || HaveDifferentOrder(selectedRuns, runs.Where(r => r.Visible))) {
566          Clear();
567          AddRange(ReplaceVisibleRuns(runs, selectedRuns));
568        } else if (runs.Count > 0) {
569          OnCollectionReset(this, runs);
570        }
571      }
572    }
573
574    private static IEnumerable<IRun> ReplaceVisibleRuns(IEnumerable<IRun> runs, IEnumerable<IRun> visibleRuns) {
575      var newRuns = new List<IRun>();
576      var runIt = runs.GetEnumerator();
577      var visibleRunIt = visibleRuns.GetEnumerator();
578      while (runIt.MoveNext()) {
579        if (runIt.Current != null && !runIt.Current.Visible)
580          newRuns.Add(runIt.Current);
581        else if (visibleRunIt.MoveNext())
582          newRuns.Add(visibleRunIt.Current);
583      }
584      while (visibleRunIt.MoveNext())
585        newRuns.Add(visibleRunIt.Current);
586      return newRuns;
587    }
588
589    private static bool HaveDifferentOrder(IEnumerable<IRun> l1, IEnumerable<IRun> l2) {
590      return l1.Zip(l2, (r1, r2) => r1 != r2).Any();
591    }
592    #endregion
593  }
594}
Note: See TracBrowser for help on using the repository browser.