Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OptimizationNetworks/HeuristicLab.Networks/3.3/AlgorithmNode.cs @ 14488

Last change on this file since 14488 was 13799, checked in by jkarder, 8 years ago

#2205: worked on optimization networks

  • improved network visualization
File size: 10.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2014 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 System.Threading;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Core.Networks;
29using HeuristicLab.Operators;
30using HeuristicLab.Optimization;
31using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
32
33namespace HeuristicLab.Networks {
34  [Item("AlgorithmNode", "A node of a network which contains a HeuristicLab algorithm.")]
35  [StorableClass]
36  public class AlgorithmNode : Node, IAlgorithmNode {
37    protected object locker = new object();
38
39    new public PortCollection Ports {
40      get { return base.Ports; }
41    }
42
43    [Storable]
44    private IAlgorithm algorithm;
45    public IAlgorithm Algorithm {
46      get { return algorithm; }
47      set {
48        if (value != algorithm) {
49          algorithm = value;
50          OnAlgorithmChanged();
51        }
52      }
53    }
54
55    [Storable]
56    private RunCollection runs;
57    public RunCollection Runs {
58      get { return runs; }
59    }
60
61    [Storable]
62    private IItemCollection<IAlgorithm> startedAlgorithms;
63    public IItemCollection<IAlgorithm> StartedAlgorithms {
64      get { return startedAlgorithms; }
65    }
66
67    [StorableConstructor]
68    protected AlgorithmNode(bool deserializing) : base(deserializing) { }
69    protected AlgorithmNode(AlgorithmNode original, Cloner cloner)
70      : base(original, cloner) {
71      algorithm = cloner.Clone(original.algorithm);
72      runs = cloner.Clone(original.runs);
73      startedAlgorithms = cloner.Clone(original.startedAlgorithms);
74      RegisterStartedAlgorithmsEvents();
75    }
76    public AlgorithmNode()
77      : base("AlgorithmNode") {
78      runs = new RunCollection();
79      startedAlgorithms = new ItemCollection<IAlgorithm>();
80      RegisterStartedAlgorithmsEvents();
81    }
82
83    public AlgorithmNode(string name)
84      : base(name) {
85      runs = new RunCollection();
86      startedAlgorithms = new ItemCollection<IAlgorithm>();
87      RegisterStartedAlgorithmsEvents();
88    }
89    public AlgorithmNode(string name, string description)
90      : base(name, description) {
91      runs = new RunCollection();
92      startedAlgorithms = new ItemCollection<IAlgorithm>();
93      RegisterStartedAlgorithmsEvents();
94    }
95
96    public override IDeepCloneable Clone(Cloner cloner) {
97      return new AlgorithmNode(this, cloner);
98    }
99
100    [StorableHook(HookType.AfterDeserialization)]
101    private void AfterDeserialization() {
102      RegisterStartedAlgorithmsEvents();
103    }
104
105    protected virtual void RegisterStartedAlgorithmsEvents() {
106      startedAlgorithms.ItemsAdded += StartedAlgorithms_ItemsChanged;
107      startedAlgorithms.ItemsRemoved += StartedAlgorithms_ItemsChanged;
108    }
109
110    private void StartedAlgorithms_ItemsChanged(object sender, Collections.CollectionItemsChangedEventArgs<IAlgorithm> e) {
111      OnStartedAlgorithmsChanged();
112    }
113
114    protected virtual void Configure(IConfigurationPort port, IMessage message, CancellationToken token) {
115      // set algorithm and problem parameters
116      lock (locker) {
117        if (algorithm != null) {
118          foreach (var v in message.Values) {
119            IParameter param = null;
120            if (Algorithm.Parameters.TryGetValue(v.Name, out param)) {
121              var vp = param as IValueParameter;
122              if (vp != null) vp.Value = v.Value;
123            }
124            if (Algorithm.Problem.Parameters.TryGetValue(v.Name, out param)) {
125              var vp = param as IValueParameter;
126              if (vp != null) vp.Value = v.Value;
127            }
128          }
129        }
130      }
131    }
132
133    protected virtual void Execute(IExecutionPort port, IMessage message, CancellationToken token) {
134      if (Algorithm == null) throw new InvalidOperationException("Algorithm is null");
135
136      IAlgorithm algorithm;
137      lock (locker) {
138        // prevent cloning of ports in hook operators
139        var cloner = new Cloner();
140        foreach (var hook in Algorithm.GetObjectGraphObjects(new HashSet<object>() { Algorithm.Results, Algorithm.Runs }).OfType<IHookOperator>()) {
141          cloner.RegisterClonedObject(hook.Port, hook.Port);
142        }
143        algorithm = (IAlgorithm)Algorithm.Clone(cloner);
144      }
145
146      // set parameters
147      foreach (var v in message.Values) {
148        IParameter param = null;
149        if (algorithm.Parameters.TryGetValue(v.Name, out param)) {
150          var vp = param as IValueParameter;
151          if (vp != null) vp.Value = v.Value;
152        }
153        if (algorithm.Problem.Parameters.TryGetValue(v.Name, out param)) {
154          var vp = param as IValueParameter;
155          if (vp != null) vp.Value = v.Value;
156        }
157      }
158
159      token.ThrowIfCancellationRequested();
160
161      Exception exception = null;
162      using (var started = new AutoResetEvent(false))
163      using (var stopped = new AutoResetEvent(false))
164      using (var ctr = token.Register(() => {
165        started.WaitOne();
166        try { algorithm.Stop(); }
167        catch (InvalidOperationException) {
168          // NOTE:
169          // After the algorithm's engine is stopped, all stateful items in the algorithm are cleared before the execution state of the algorithm is set to stopped.
170          // When algorithm.Stop() is called during that operation, an InvalidOperationException is thrown because Stop is called on the engine but the engine is already stopped.
171          // This exception can be ignored, as the algorithm will stop immediately after the clearing of its stateful items is finished.
172        }
173      })) {
174        algorithm.StoreAlgorithmInEachRun = false;
175        algorithm.Prepare(true);
176        algorithm.ExceptionOccurred += (sender, args) => { exception = args.Value; };
177        algorithm.Started += (sender, args) => { started.Set(); startedAlgorithms.Add((IAlgorithm)sender); };
178        algorithm.Stopped += (sender, args) => { stopped.Set(); startedAlgorithms.Remove((IAlgorithm)sender); };
179        algorithm.Start();
180        stopped.WaitOne();
181      }
182
183      if (exception != null) throw exception;
184      token.ThrowIfCancellationRequested();
185
186      // retrieve results
187      var run = algorithm.Runs.First();
188      foreach (var v in message.Values) {
189        IItem result = null;
190        if (run.Results.TryGetValue(v.Name, out result)) {
191          v.Value = result;
192        }
193      }
194
195      lock (locker) {
196        Runs.Add(run);
197      }
198    }
199
200    public event EventHandler AlgorithmChanged;
201    protected virtual void OnAlgorithmChanged() {
202      var handler = AlgorithmChanged;
203      if (handler != null) handler(this, EventArgs.Empty);
204    }
205
206    public event EventHandler StartedAlgorithmsChanged;
207    protected virtual void OnStartedAlgorithmsChanged() {
208      var handler = StartedAlgorithmsChanged;
209      if (handler != null) handler(this, EventArgs.Empty);
210    }
211
212    #region Ports Events
213    protected override void RegisterPortsEvents() {
214      base.RegisterPortsEvents();
215      foreach (var p in Ports)
216        RegisterPortEvents(p);
217    }
218    protected override void Ports_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
219      base.Ports_ItemsAdded(sender, e);
220      foreach (var p in e.Items)
221        RegisterPortEvents(p);
222    }
223    protected override void Ports_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
224      base.Ports_ItemsRemoved(sender, e);
225      foreach (var p in e.Items)
226        DeregisterPortEvents(p);
227    }
228    protected override void Ports_ItemsReplaced(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
229      base.Ports_ItemsReplaced(sender, e);
230      foreach (var p in e.OldItems)
231        DeregisterPortEvents(p);
232      foreach (var p in e.Items)
233        RegisterPortEvents(p);
234    }
235    protected override void Ports_CollectionReset(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
236      base.Ports_CollectionReset(sender, e);
237      foreach (var p in e.OldItems)
238        DeregisterPortEvents(p);
239      foreach (var p in e.Items)
240        RegisterPortEvents(p);
241    }
242    #endregion
243
244    #region Port Events
245    private void RegisterPortEvents(IPort port) {
246      IConfigurationPort c = port as IConfigurationPort;
247      if (c != null) {
248        c.MessageReceived += ConfigurationPort_MessageReceived;
249      }
250      IExecutionPort e = port as IExecutionPort;
251      if (e != null) {
252        e.MessageReceived += ExecutionPort_MessageReceived;
253      }
254    }
255    private void DeregisterPortEvents(IPort port) {
256      IConfigurationPort c = port as IConfigurationPort;
257      if (c != null) {
258        c.MessageReceived -= ConfigurationPort_MessageReceived;
259      }
260      IExecutionPort e = port as IExecutionPort;
261      if (e != null) {
262        e.MessageReceived -= ExecutionPort_MessageReceived;
263      }
264    }
265    protected virtual void ConfigurationPort_MessageReceived(object sender, EventArgs<IMessage, CancellationToken> e) {
266      Configure((IConfigurationPort)sender, e.Value, e.Value2);
267    }
268    protected virtual void ExecutionPort_MessageReceived(object sender, EventArgs<IMessage, CancellationToken> e) {
269      Execute((IExecutionPort)sender, e.Value, e.Value2);
270    }
271    #endregion
272  }
273}
Note: See TracBrowser for help on using the repository browser.