Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.Core/3.3/OperatorGraph.cs @ 17842

Last change on this file since 17842 was 17181, checked in by swagner, 5 years ago

#2875: Merged r17180 from trunk to stable

File size: 11.6 KB
RevLine 
[2]1#region License Information
2/* HeuristicLab
[17181]3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[2]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;
[9038]23using System.Collections.Generic;
[2653]24using System.Linq;
[4068]25using HeuristicLab.Collections;
26using HeuristicLab.Common;
[17097]27using HEAL.Attic;
[2]28
29namespace HeuristicLab.Core {
[776]30  /// <summary>
31  /// Represents a graph of operators.
32  /// </summary>
[3160]33  [Item("Operator Graph", "Represents a graph of operators.")]
[17097]34  [StorableType("4F3EDAFB-5363-489B-A2E2-67AAC589CDE7")]
[4419]35  public class OperatorGraph : Item, IStorableContent {
36    public string Filename { get; set; }
37
[3317]38    [Storable]
[2653]39    private OperatorSet operators;
[776]40    /// <summary>
41    /// Gets all operators of the current instance.
42    /// </summary>
[2653]43    public OperatorSet Operators {
44      get { return operators; }
[2]45    }
[1667]46
47    [Storable]
[2653]48    private IOperator initialOperator;
[776]49    /// <summary>
50    /// Gets or sets the initial operator (the starting one).
51    /// </summary>
52    /// <remarks>Calls <see cref="OnInitialOperatorChanged"/> in the setter.</remarks>
[2]53    public IOperator InitialOperator {
[2653]54      get { return initialOperator; }
[2]55      set {
[2653]56        if (initialOperator != value) {
57          if (value != null) Operators.Add(value);
58          initialOperator = value;
[2]59          OnInitialOperatorChanged();
60        }
61      }
62    }
63
[2853]64    [Storable]
65    private IDeepCloneable visualizationInfo;
[776]66    /// <summary>
[2853]67    /// Gets or sets the visualizationInfo.
68    /// </summary>
69    /// /// <remarks>The VisualizationInfo can only be set once and fires afterwards and InvalidOperationException</remarks>
70    public IDeepCloneable VisualizationInfo {
71      get { return visualizationInfo; }
72      set {
73        if (visualizationInfo != null)
74          throw new InvalidOperationException("The value of the property VisualizationInfo is already set and cannot be set again.");
75        visualizationInfo = value;
76      }
77    }
78
[4722]79    [StorableConstructor]
[17097]80    protected OperatorGraph(StorableConstructorFlag _) : base(_) { }
[4722]81    protected OperatorGraph(OperatorGraph original, Cloner cloner)
82      : base(original, cloner) {
83      operators = cloner.Clone(original.operators);
84      initialOperator = cloner.Clone(original.initialOperator);
85      visualizationInfo = cloner.Clone(original.visualizationInfo);
86      Initialize();
87    }
[2853]88    /// <summary>
[776]89    /// Initializes a new instance of <see cref="OperatorGraph"/>.
90    /// </summary>
[2]91    public OperatorGraph() {
[3317]92      operators = new OperatorSet();
[2653]93      initialOperator = null;
[2853]94      visualizationInfo = null;
[3317]95      Initialize();
[2]96    }
97
[5008]98    //mkommend: IMPORTANT DO NOT REMOVE THIS EVENT
[3386]99    //needed to register OperatorGraph events in GraphVisualizationInfo
100    public event EventHandler DeserializationFinished;
101    private void OnOperatorGraphDeserializationFinished() {
102      EventHandler handler = DeserializationFinished;
[4722]103      if (handler != null) handler(this, EventArgs.Empty);
[3386]104    }
[4722]105
[3317]106    [StorableHook(HookType.AfterDeserialization)]
[4722]107    private void AfterDeserialization() {
108      Initialize();
[5008]109      OnOperatorGraphDeserializationFinished();
[4722]110    }
[3317]111    private void Initialize() {
112      RegisterOperatorsEvents();
113    }
114
[776]115    /// <summary>
116    /// Clones the current instance (deep clone).
117    /// </summary>
[2526]118    /// <remarks>Deep clone through <see cref="cloner.Clone"/> method of helper class
[776]119    /// <see cref="Auxiliary"/>.</remarks>
120    /// <param name="clonedObjects">Dictionary of all already cloned objects. (Needed to avoid cycles.)</param>
121    /// <returns>The cloned object as <see cref="OperatorGraph"/>.</returns>
[2653]122    public override IDeepCloneable Clone(Cloner cloner) {
[4722]123      return new OperatorGraph(this, cloner);
[2]124    }
125
[776]126    /// <inheritdoc/>
[2653]127    public event EventHandler InitialOperatorChanged;
128    /// <summary>
129    /// Fires a new <c>InitialOperatorChanged</c> event.
130    /// </summary>
131    protected virtual void OnInitialOperatorChanged() {
[4722]132      var handler = InitialOperatorChanged;
133      if (handler != null) handler(this, EventArgs.Empty);
[2653]134    }
[2]135
[2653]136    #region Operators Events
137    private void AddOperator(IOperator op) {
138      RegisterOperatorEvents(op);
139      foreach (IParameter param in op.Parameters)
140        AddParameter(param);
141    }
142    private void RemoveOperator(IOperator op) {
143      foreach (IParameter param in op.Parameters)
144        RemoveParameter(param);
145      DeregisterOperatorEvents(op);
146
147      // remove edges to removed operator
[3729]148      IValueParameter[] opParams = (from o in Operators
149                                    from p in o.Parameters
150                                    where p is IValueParameter
151                                    where typeof(IOperator).IsAssignableFrom(((IValueParameter)p).DataType)
152                                    where (((IValueParameter)p).Value != null) && (((IValueParameter)p).Value == op)
153                                    select (IValueParameter)p).ToArray();
[3407]154      foreach (IValueParameter opParam in opParams)
[2653]155        opParam.Value = null;
156    }
157    private void AddParameter(IParameter param) {
[3407]158      IValueParameter valueParam = param as IValueParameter;
159      if ((valueParam != null) && (typeof(IOperator).IsAssignableFrom(valueParam.DataType))) {
160        RegisterOperatorParameterEvents(valueParam);
161        if (valueParam.Value != null) Operators.Add((IOperator)valueParam.Value);
[2]162      }
163    }
[2653]164    private void RemoveParameter(IParameter param) {
[3407]165      IValueParameter valueParam = param as IValueParameter;
166      if ((valueParam != null) && (typeof(IOperator).IsAssignableFrom(valueParam.DataType))) {
167        DeregisterOperatorParameterEvents(valueParam);
[2]168      }
169    }
[2653]170
171    private void RegisterOperatorsEvents() {
172      if (operators != null) {
173        operators.ItemsAdded += new CollectionItemsChangedEventHandler<IOperator>(Operators_ItemsAdded);
174        operators.ItemsRemoved += new CollectionItemsChangedEventHandler<IOperator>(Operators_ItemsRemoved);
175        operators.CollectionReset += new CollectionItemsChangedEventHandler<IOperator>(Operators_CollectionReset);
[2790]176        foreach (IOperator op in operators) {
177          RegisterOperatorEvents(op);
[3407]178          var opParams = from p in op.Parameters
179                         where p is IValueParameter
180                         where typeof(IOperator).IsAssignableFrom(((IValueParameter)p).DataType)
181                         select (IValueParameter)p;
182          foreach (IValueParameter opParam in opParams)
183            RegisterOperatorParameterEvents(opParam);
[2790]184        }
[2]185      }
186    }
[2653]187    private void RegisterOperatorEvents(IOperator op) {
188      op.Parameters.ItemsAdded += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded);
189      op.Parameters.ItemsRemoved += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved);
190      op.Parameters.ItemsReplaced += new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced);
191      op.Parameters.CollectionReset += new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset);
192    }
193    private void DeregisterOperatorEvents(IOperator op) {
194      op.Parameters.ItemsAdded -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsAdded);
195      op.Parameters.ItemsRemoved -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsRemoved);
196      op.Parameters.ItemsReplaced -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_ItemsReplaced);
197      op.Parameters.CollectionReset -= new CollectionItemsChangedEventHandler<IParameter>(Parameters_CollectionReset);
198    }
[3407]199    private void RegisterOperatorParameterEvents(IValueParameter opParam) {
[2653]200      opParam.ValueChanged += new EventHandler(opParam_ValueChanged);
201    }
[3407]202    private void DeregisterOperatorParameterEvents(IValueParameter opParam) {
[2653]203      opParam.ValueChanged -= new EventHandler(opParam_ValueChanged);
204    }
[2]205
[2653]206    private void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IOperator> e) {
207      foreach (IOperator op in e.Items)
208        AddOperator(op);
[2]209    }
[2653]210    private void Operators_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IOperator> e) {
211      foreach (IOperator op in e.Items)
212        RemoveOperator(op);
213      if (!Operators.Contains(InitialOperator)) InitialOperator = null;
[2]214    }
[2653]215    private void Operators_CollectionReset(object sender, CollectionItemsChangedEventArgs<IOperator> e) {
216      foreach (IOperator op in e.OldItems)
217        RemoveOperator(op);
218      foreach (IOperator op in e.Items)
219        AddOperator(op);
220      if (!Operators.Contains(InitialOperator)) InitialOperator = null;
[2]221    }
[2653]222    private void Parameters_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
223      foreach (IParameter param in e.Items)
224        AddParameter(param);
225    }
226    private void Parameters_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
227      foreach (IParameter param in e.Items)
228        RemoveParameter(param);
229    }
230    private void Parameters_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
231      foreach (IParameter param in e.OldItems)
232        RemoveParameter(param);
233      foreach (IParameter param in e.Items)
234        AddParameter(param);
235    }
236    private void Parameters_CollectionReset(object sender, CollectionItemsChangedEventArgs<IParameter> e) {
237      foreach (IParameter param in e.OldItems)
238        RemoveParameter(param);
239      foreach (IParameter param in e.Items)
240        AddParameter(param);
241    }
242    private void opParam_ValueChanged(object sender, EventArgs e) {
[3407]243      IValueParameter opParam = (IValueParameter)sender;
244      if (opParam.Value != null) Operators.Add((IOperator)opParam.Value);
[2653]245    }
246    #endregion
[9038]247
248    // <summary>
249    /// Iterates an operator graph so that it jumps from the intial operator to all other operators and yields each operator it touches.
250    /// Cycles are detected and not iterated twice.
251    /// </summary>
252    /// <returns>An enumeration of all the operators that could be found.</returns>
[9075]253    public virtual IEnumerable<IOperator> Iterate() {
[9038]254      if (InitialOperator == null) yield break;
255
256      var open = new Stack<IOperator>();
257      var visited = new HashSet<IOperator>();
258      open.Push(InitialOperator);
259
260      while (open.Any()) {
261        IOperator current = open.Pop();
262        if (visited.Contains(current)) continue;
263        visited.Add(current);
264
[9178]265        IOperatorGraphOperator operatorGraphOperator = current as IOperatorGraphOperator;
266        if (operatorGraphOperator != null) open.Push(operatorGraphOperator.OperatorGraph.InitialOperator);
267
[9038]268        foreach (var parameter in current.Parameters.OfType<IValueParameter>()) {
269          if (!typeof(IOperator).IsAssignableFrom(parameter.DataType)) continue;
270          if (parameter.Value == null) continue;
271
272          open.Push((IOperator)parameter.Value);
273        }
274
275        yield return current;
276      }
277    }
[2]278  }
279}
Note: See TracBrowser for help on using the repository browser.