Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 12005 was 11713, checked in by swagner, 10 years ago

#2205: Implemented review comments:

  • checked and adapted item descriptions
File size: 8.6 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 HeuristicLab.Common;
23using HeuristicLab.Core;
24using HeuristicLab.Core.Networks;
25using HeuristicLab.Operators;
26using HeuristicLab.Optimization;
27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Threading;
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    private 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    [StorableConstructor]
62    protected AlgorithmNode(bool deserializing) : base(deserializing) { }
63    protected AlgorithmNode(AlgorithmNode original, Cloner cloner)
64      : base(original, cloner) {
65      algorithm = cloner.Clone(original.algorithm);
66      runs = cloner.Clone(original.runs);
67    }
68    public AlgorithmNode()
69      : base("AlgorithmNode") {
70      runs = new RunCollection();
71    }
72    public AlgorithmNode(string name)
73      : base(name) {
74      runs = new RunCollection();
75    }
76    public AlgorithmNode(string name, string description)
77      : base(name, description) {
78      runs = new RunCollection();
79    }
80
81    public override IDeepCloneable Clone(Cloner cloner) {
82      return new AlgorithmNode(this, cloner);
83    }
84
85    protected virtual void Configure(IConfigurationPort port, IMessage message, CancellationToken token) {
86      // set algorithm and problem parameters
87      lock (locker) {
88        if (algorithm != null) {
89          foreach (var v in message.Values) {
90            IParameter param = null;
91            if (Algorithm.Parameters.TryGetValue(v.Name, out param)) {
92              var vp = param as IValueParameter;
93              if (vp != null) vp.Value = v.Value;
94            }
95            if (Algorithm.Problem.Parameters.TryGetValue(v.Name, out param)) {
96              var vp = param as IValueParameter;
97              if (vp != null) vp.Value = v.Value;
98            }
99          }
100        }
101      }
102    }
103
104    protected virtual void Execute(IExecutionPort port, IMessage message, CancellationToken token) {
105      if (Algorithm == null) throw new InvalidOperationException("Algorithm is null");
106
107      IAlgorithm algorithm;
108      lock (locker) {
109        // prevent cloning of ports in hook operators
110        var cloner = new Cloner();
111        foreach (var hook in Algorithm.GetObjectGraphObjects(new HashSet<object>() { Algorithm.Results, Algorithm.Runs }).OfType<IHookOperator>()) {
112          cloner.RegisterClonedObject(hook.Port, hook.Port);
113        }
114        algorithm = (IAlgorithm)Algorithm.Clone(cloner);
115      }
116
117      // set parameters
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      token.ThrowIfCancellationRequested();
131
132      Exception exception = null;
133      using (var started = new AutoResetEvent(false))
134      using (var stopped = new AutoResetEvent(false))
135      using (var ctr = token.Register(() => {
136        started.WaitOne();
137        try { algorithm.Stop(); }
138        catch (InvalidOperationException) {
139          // NOTE:
140          // 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.
141          // 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.
142          // This exception can be ignored, as the algorithm will stop immediately after the clearing of its stateful items is finished.
143        }
144      })) {
145        algorithm.StoreAlgorithmInEachRun = false;
146        algorithm.Prepare(true);
147        algorithm.ExceptionOccurred += (sender, args) => { exception = args.Value; };
148        algorithm.Started += (sender, args) => { started.Set(); };
149        algorithm.Stopped += (sender, args) => { stopped.Set(); };
150        algorithm.Start();
151        stopped.WaitOne();
152      }
153
154      if (exception != null) throw exception;
155      token.ThrowIfCancellationRequested();
156
157      // retrieve results
158      var run = algorithm.Runs.First();
159      foreach (var v in message.Values) {
160        IItem result = null;
161        if (run.Results.TryGetValue(v.Name, out result)) {
162          v.Value = result;
163        }
164      }
165
166      lock (locker) {
167        Runs.Add(run);
168      }
169    }
170
171    public event EventHandler AlgorithmChanged;
172    protected virtual void OnAlgorithmChanged() {
173      var handler = AlgorithmChanged;
174      if (handler != null) handler(this, EventArgs.Empty);
175    }
176
177    #region Ports Events
178    protected override void RegisterPortsEvents() {
179      base.RegisterPortsEvents();
180      foreach (var p in Ports)
181        RegisterPortEvents(p);
182    }
183    protected override void Ports_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
184      base.Ports_ItemsAdded(sender, e);
185      foreach (var p in e.Items)
186        RegisterPortEvents(p);
187    }
188    protected override void Ports_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
189      base.Ports_ItemsRemoved(sender, e);
190      foreach (var p in e.Items)
191        DeregisterPortEvents(p);
192    }
193    protected override void Ports_ItemsReplaced(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
194      base.Ports_ItemsReplaced(sender, e);
195      foreach (var p in e.OldItems)
196        DeregisterPortEvents(p);
197      foreach (var p in e.Items)
198        RegisterPortEvents(p);
199    }
200    protected override void Ports_CollectionReset(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
201      base.Ports_CollectionReset(sender, e);
202      foreach (var p in e.OldItems)
203        DeregisterPortEvents(p);
204      foreach (var p in e.Items)
205        RegisterPortEvents(p);
206    }
207    #endregion
208
209    #region Port Events
210    private void RegisterPortEvents(IPort port) {
211      IConfigurationPort c = port as IConfigurationPort;
212      if (c != null) {
213        c.MessageReceived += ConfigurationPort_MessageReceived;
214      }
215      IExecutionPort e = port as IExecutionPort;
216      if (e != null) {
217        e.MessageReceived += ExecutionPort_MessageReceived;
218      }
219    }
220    private void DeregisterPortEvents(IPort port) {
221      IConfigurationPort c = port as IConfigurationPort;
222      if (c != null) {
223        c.MessageReceived -= ConfigurationPort_MessageReceived;
224      }
225      IExecutionPort e = port as IExecutionPort;
226      if (e != null) {
227        e.MessageReceived -= ExecutionPort_MessageReceived;
228      }
229    }
230    protected virtual void ConfigurationPort_MessageReceived(object sender, EventArgs<IMessage, CancellationToken> e) {
231      Configure((IConfigurationPort)sender, e.Value, e.Value2);
232    }
233    protected virtual void ExecutionPort_MessageReceived(object sender, EventArgs<IMessage, CancellationToken> e) {
234      Execute((IExecutionPort)sender, e.Value, e.Value2);
235    }
236    #endregion
237  }
238}
Note: See TracBrowser for help on using the repository browser.