Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 11554 was 11554, checked in by swagner, 9 years ago

#2205: Implemented review comments:

  • added cloning of Port in HookOperator and prevented cloning of hook operator ports in AlgorithmNode instead
  • added additional checks that port parameters of a hook operator port match with parameters of hook operator
File size: 8.5 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.Persistence.Default.CompositeSerializers.Storable;
27using System;
28using System.Collections.Generic;
29using System.Linq;
30using System.Threading;
31
32namespace HeuristicLab.Optimization.Networks {
33  [Item("AlgorithmNode", "A node of an optimization network which contains a HeuristicLab algorithm.")]
34  [StorableClass]
35  public class AlgorithmNode : Node, IAlgorithmNode {
36    private object locker = new object();
37    private Dictionary<IAlgorithm, AutoResetEvent> waitHandles = new Dictionary<IAlgorithm, AutoResetEvent>();
38    private Dictionary<IAlgorithm, Exception> exceptions = new Dictionary<IAlgorithm, Exception>();
39
40    new public PortCollection Ports {
41      get { return base.Ports; }
42    }
43
44    [Storable]
45    private IAlgorithm algorithm;
46    public IAlgorithm Algorithm {
47      get { return algorithm; }
48      set {
49        if (value != algorithm) {
50          algorithm = value;
51          OnAlgorithmChanged();
52        }
53      }
54    }
55
56    [Storable]
57    private RunCollection runs;
58    public RunCollection Runs {
59      get { return runs; }
60    }
61
62    [StorableConstructor]
63    protected AlgorithmNode(bool deserializing) : base(deserializing) { }
64    protected AlgorithmNode(AlgorithmNode original, Cloner cloner)
65      : base(original, cloner) {
66      algorithm = cloner.Clone(original.algorithm);
67      runs = cloner.Clone(original.runs);
68    }
69    public AlgorithmNode()
70      : base("AlgorithmNode") {
71      runs = new RunCollection();
72    }
73    public AlgorithmNode(string name)
74      : base(name) {
75      runs = new RunCollection();
76    }
77    public AlgorithmNode(string name, string description)
78      : base(name, description) {
79      runs = new RunCollection();
80    }
81
82    public override IDeepCloneable Clone(Cloner cloner) {
83      return new AlgorithmNode(this, cloner);
84    }
85
86    protected virtual void Configure(IConfigurationPort port, IMessage message, CancellationToken token) {
87      // set algorithm and problem parameters
88      lock (locker) {
89        if (algorithm != null) {
90          foreach (var v in message.Values) {
91            IParameter param = null;
92            if (Algorithm.Parameters.TryGetValue(v.Name, out param)) {
93              var vp = param as IValueParameter;
94              if (vp != null) vp.Value = v.Value;
95            }
96            if (Algorithm.Problem.Parameters.TryGetValue(v.Name, out param)) {
97              var vp = param as IValueParameter;
98              if (vp != null) vp.Value = v.Value;
99            }
100          }
101        }
102      }
103    }
104
105    protected virtual void Execute(IExecutionPort port, IMessage message, CancellationToken token) {
106      if (Algorithm == null) throw new InvalidOperationException("Algorithm is null");
107
108      IAlgorithm algorithm;
109      lock (locker) {
110        // prevent cloning of ports in hook operators
111        var cloner = new Cloner();
112        foreach (var hook in Algorithm.GetObjectGraphObjects(new HashSet<object>() { Algorithm.Results, Algorithm.Runs }).OfType<IHookOperator>()) {
113          cloner.RegisterClonedObject(hook.Port, hook.Port);
114        }
115        algorithm = (IAlgorithm)Algorithm.Clone(cloner);
116        waitHandles.Add(algorithm, new AutoResetEvent(false));
117      }
118
119      // set parameters
120      foreach (var v in message.Values) {
121        IParameter param = null;
122        if (algorithm.Parameters.TryGetValue(v.Name, out param)) {
123          var vp = param as IValueParameter;
124          if (vp != null) vp.Value = v.Value;
125        }
126        if (algorithm.Problem.Parameters.TryGetValue(v.Name, out param)) {
127          var vp = param as IValueParameter;
128          if (vp != null) vp.Value = v.Value;
129        }
130      }
131
132      algorithm.StoreAlgorithmInEachRun = false;
133      algorithm.Prepare(true);
134      algorithm.ExceptionOccurred += Algorithm_ExceptionOccurred;
135      algorithm.Stopped += Algorithm_Stopped;
136
137      using (token.Register(() => { algorithm.Stop(); })) {
138        algorithm.Start();
139        waitHandles[algorithm].WaitOne();
140      }
141
142      lock (locker) {
143        waitHandles[algorithm].Dispose();
144        waitHandles.Remove(algorithm);
145
146        Exception ex = null;
147        if (exceptions.TryGetValue(algorithm, out ex)) {
148          exceptions.Remove(algorithm);
149          throw ex;
150        }
151      }
152
153      // retrieve results
154      var run = algorithm.Runs.First();
155      foreach (var v in message.Values) {
156        IItem result = null;
157        if (run.Results.TryGetValue(v.Name, out result)) {
158          v.Value = result;
159        }
160      }
161
162      lock (locker) {
163        Runs.Add(run);
164      }
165    }
166
167    private void Algorithm_ExceptionOccurred(object sender, EventArgs<Exception> e) {
168      var algorithm = (IAlgorithm)sender;
169      lock (locker) {
170        exceptions.Add(algorithm, e.Value);
171      }
172      algorithm.Stop();
173    }
174    private void Algorithm_Stopped(object sender, EventArgs e) {
175      lock (locker) {
176        waitHandles[(IAlgorithm)sender].Set();
177      }
178    }
179
180    public event EventHandler AlgorithmChanged;
181    protected virtual void OnAlgorithmChanged() {
182      var handler = AlgorithmChanged;
183      if (handler != null) handler(this, EventArgs.Empty);
184    }
185
186    #region Ports Events
187    protected override void RegisterPortsEvents() {
188      base.RegisterPortsEvents();
189      foreach (var p in Ports)
190        RegisterPortEvents(p);
191    }
192    protected override void Ports_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
193      base.Ports_ItemsAdded(sender, e);
194      foreach (var p in e.Items)
195        RegisterPortEvents(p);
196    }
197    protected override void Ports_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
198      base.Ports_ItemsRemoved(sender, e);
199      foreach (var p in e.Items)
200        DeregisterPortEvents(p);
201    }
202    protected override void Ports_ItemsReplaced(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
203      base.Ports_ItemsReplaced(sender, e);
204      foreach (var p in e.OldItems)
205        DeregisterPortEvents(p);
206      foreach (var p in e.Items)
207        RegisterPortEvents(p);
208    }
209    protected override void Ports_CollectionReset(object sender, Collections.CollectionItemsChangedEventArgs<IPort> e) {
210      base.Ports_CollectionReset(sender, e);
211      foreach (var p in e.OldItems)
212        DeregisterPortEvents(p);
213      foreach (var p in e.Items)
214        RegisterPortEvents(p);
215    }
216    #endregion
217
218    #region Port Events
219    private void RegisterPortEvents(IPort port) {
220      IConfigurationPort c = port as IConfigurationPort;
221      if (c != null) {
222        c.MessageReceived += ConfigurationPort_MessageReceived;
223      }
224      IExecutionPort e = port as IExecutionPort;
225      if (e != null) {
226        e.MessageReceived += ExecutionPort_MessageReceived;
227      }
228    }
229    private void DeregisterPortEvents(IPort port) {
230      IConfigurationPort c = port as IConfigurationPort;
231      if (c != null) {
232        c.MessageReceived -= ConfigurationPort_MessageReceived;
233      }
234      IExecutionPort e = port as IExecutionPort;
235      if (e != null) {
236        e.MessageReceived -= ExecutionPort_MessageReceived;
237      }
238    }
239    protected virtual void ConfigurationPort_MessageReceived(object sender, EventArgs<IMessage, CancellationToken> e) {
240      Configure((IConfigurationPort)sender, e.Value, e.Value2);
241    }
242    protected virtual void ExecutionPort_MessageReceived(object sender, EventArgs<IMessage, CancellationToken> e) {
243      Execute((IExecutionPort)sender, e.Value, e.Value2);
244    }
245    #endregion
246  }
247}
Note: See TracBrowser for help on using the repository browser.