Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Core/3.3/OperatorGraph.cs @ 9333

Last change on this file since 9333 was 9178, checked in by mkommend, 12 years ago

#1996: Corrected OperatorGraph.Iterate to include AlgorithmOperators.

File size: 11.6 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.Persistence.Default.CompositeSerializers.Storable;
28
29namespace HeuristicLab.Core {
30  /// <summary>
31  /// Represents a graph of operators.
32  /// </summary>
33  [Item("Operator Graph", "Represents a graph of operators.")]
34  [StorableClass]
35  public class OperatorGraph : Item, IStorableContent {
36    public string Filename { get; set; }
37
38    [Storable]
39    private OperatorSet operators;
40    /// <summary>
41    /// Gets all operators of the current instance.
42    /// </summary>
43    public OperatorSet Operators {
44      get { return operators; }
45    }
46
47    [Storable]
48    private IOperator initialOperator;
49    /// <summary>
50    /// Gets or sets the initial operator (the starting one).
51    /// </summary>
52    /// <remarks>Calls <see cref="OnInitialOperatorChanged"/> in the setter.</remarks>
53    public IOperator InitialOperator {
54      get { return initialOperator; }
55      set {
56        if (initialOperator != value) {
57          if (value != null) Operators.Add(value);
58          initialOperator = value;
59          OnInitialOperatorChanged();
60        }
61      }
62    }
63
64    [Storable]
65    private IDeepCloneable visualizationInfo;
66    /// <summary>
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
79    [StorableConstructor]
80    protected OperatorGraph(bool deserializing) : base(deserializing) { }
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    }
88    /// <summary>
89    /// Initializes a new instance of <see cref="OperatorGraph"/>.
90    /// </summary>
91    public OperatorGraph() {
92      operators = new OperatorSet();
93      initialOperator = null;
94      visualizationInfo = null;
95      Initialize();
96    }
97
98    //mkommend: IMPORTANT DO NOT REMOVE THIS EVENT
99    //needed to register OperatorGraph events in GraphVisualizationInfo
100    public event EventHandler DeserializationFinished;
101    private void OnOperatorGraphDeserializationFinished() {
102      EventHandler handler = DeserializationFinished;
103      if (handler != null) handler(this, EventArgs.Empty);
104    }
105
106    [StorableHook(HookType.AfterDeserialization)]
107    private void AfterDeserialization() {
108      Initialize();
109      OnOperatorGraphDeserializationFinished();
110    }
111    private void Initialize() {
112      RegisterOperatorsEvents();
113    }
114
115    /// <summary>
116    /// Clones the current instance (deep clone).
117    /// </summary>
118    /// <remarks>Deep clone through <see cref="cloner.Clone"/> method of helper class
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>
122    public override IDeepCloneable Clone(Cloner cloner) {
123      return new OperatorGraph(this, cloner);
124    }
125
126    /// <inheritdoc/>
127    public event EventHandler InitialOperatorChanged;
128    /// <summary>
129    /// Fires a new <c>InitialOperatorChanged</c> event.
130    /// </summary>
131    protected virtual void OnInitialOperatorChanged() {
132      var handler = InitialOperatorChanged;
133      if (handler != null) handler(this, EventArgs.Empty);
134    }
135
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
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();
154      foreach (IValueParameter opParam in opParams)
155        opParam.Value = null;
156    }
157    private void AddParameter(IParameter param) {
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);
162      }
163    }
164    private void RemoveParameter(IParameter param) {
165      IValueParameter valueParam = param as IValueParameter;
166      if ((valueParam != null) && (typeof(IOperator).IsAssignableFrom(valueParam.DataType))) {
167        DeregisterOperatorParameterEvents(valueParam);
168      }
169    }
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);
176        foreach (IOperator op in operators) {
177          RegisterOperatorEvents(op);
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);
184        }
185      }
186    }
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    }
199    private void RegisterOperatorParameterEvents(IValueParameter opParam) {
200      opParam.ValueChanged += new EventHandler(opParam_ValueChanged);
201    }
202    private void DeregisterOperatorParameterEvents(IValueParameter opParam) {
203      opParam.ValueChanged -= new EventHandler(opParam_ValueChanged);
204    }
205
206    private void Operators_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IOperator> e) {
207      foreach (IOperator op in e.Items)
208        AddOperator(op);
209    }
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;
214    }
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;
221    }
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) {
243      IValueParameter opParam = (IValueParameter)sender;
244      if (opParam.Value != null) Operators.Add((IOperator)opParam.Value);
245    }
246    #endregion
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>
253    public virtual IEnumerable<IOperator> Iterate() {
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
265        IOperatorGraphOperator operatorGraphOperator = current as IOperatorGraphOperator;
266        if (operatorGraphOperator != null) open.Push(operatorGraphOperator.OperatorGraph.InitialOperator);
267
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    }
278  }
279}
Note: See TracBrowser for help on using the repository browser.