Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OptimizationNetworks/HeuristicLab.Optimization.Networks/3.3/Nodes/AlgorithmServiceNode.cs @ 11500

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

#2205: Worked on optimization networks

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