source: branches/thasling/DistributedGA/DistributedGA.Hive/P2PMigrationAnalyzer.cs @ 14060

Last change on this file since 14060 was 14060, checked in by thasling, 5 years ago

#2615:
changed parameter in P2PMigrationAnalyzer, so that there is no invalid cast ExceptionThrown
other parameters still TBD
made WcfPeerListManager stateless by removing a stored ChannelFactory and creating a new one by each method call

File size: 12.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 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;
24using System.Collections.Generic;
25using System.IO;
26using System.Linq;
27using DistributedGA.Core.Domain;
28using DistributedGA.Core.Implementation;
29using DistributedGA.Core.Interface;
30using DistributedGA.Hive;
31using HeuristicLab.Common;
32using HeuristicLab.Core;
33using HeuristicLab.Data;
34using HeuristicLab.Operators;
35using HeuristicLab.Parameters;
36using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
37
38namespace HeuristicLab.Optimization.Operators {
39  [Item("P2PMigrationAnalyzer", "Migrates individuals using a P2P network.")]
40  [StorableClass]
41  public class P2PMigrationAnalyzer : SingleSuccessorOperator, IAnalyzer, ISingleObjectiveOperator {
42    // state: messagehandler
43    [ExcludeFromObjectGraphTraversalAttribute]
44    private IMessageHandler h;
45
46    public bool EnabledByDefault { get { return false; } }
47
48    public ILookupParameter<BoolValue> MaximizationParameter {
49      get { return (ILookupParameter<BoolValue>)Parameters["Maximization"]; }
50    }
51    // for name translation
52    public ScopeTreeLookupParameter<DoubleValue> QualityParameter {
53      get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; }
54    }
55    public ILookupParameter<IntValue> MigrationIterationsParameter {
56      get { return (ILookupParameter<IntValue>)Parameters["MigrationIterations"]; }
57    }
58    public ILookupParameter<PercentValue> MigrationRatesParameter {
59      get { return (ILookupParameter<PercentValue>)Parameters["MigrationRate"]; }
60    }
61    public ILookupParameter<PercentValue> CommunicationRatesParameter {
62      get { return (ILookupParameter<PercentValue>)Parameters["CommunicationRate"]; }
63    }
64    public ILookupParameter<IntValue> MessageCacheCapacityParameter {
65      get { return (ILookupParameter<IntValue>)Parameters["MessageCacheCapacity"]; }
66    }
67    public ILookupParameter<IRandom> RandomParameter {
68      get { return (ILookupParameter<IRandom>)Parameters["Random"]; }
69    }
70    public IValueParameter<IntValue> MigrationIntervalParameter {
71      get { return (IValueParameter<IntValue>)Parameters["MigrationInterval"]; }
72    }
73    public IValueParameter<ILog> LogParameter {
74      get { return (IValueParameter<ILog>)Parameters["Log"]; }
75    }
76    public IValueParameter<StringValue> JobGuidParameter {
77      get { return (IValueParameter<StringValue>)Parameters["JobGUID"]; }
78    }
79
80    public IConstrainedValueParameter<EnumValue<MigrationStrategy>> MigrationStrategySelectParameter {
81      get { return (IConstrainedValueParameter<EnumValue<MigrationStrategy>>)Parameters["MigrationStrategySelect"]; }
82    }
83
84    public IConstrainedValueParameter<EnumValue<MigrationStrategy>> MigrationStrategyReplaceParameter {
85      get { return (IConstrainedValueParameter<EnumValue<MigrationStrategy>>)Parameters["MigrationStrategyReplace"]; }
86    }
87
88    public BoolValue Maximization {
89      get { return MaximizationParameter.ActualValue; }
90    }
91    public IntValue MigrationIterations {
92      get { return MigrationIterationsParameter.ActualValue; }
93    }
94
95    public IntValue MigrationInterval {
96      get { return MigrationIntervalParameter.Value; }
97    }
98
99    public IRandom Random {
100      get { return RandomParameter.ActualValue; }
101    }
102
103    [StorableConstructor]
104    protected P2PMigrationAnalyzer(bool deserializing) : base(deserializing) { }
105    protected P2PMigrationAnalyzer(P2PMigrationAnalyzer original, Cloner cloner) : base(original, cloner) { }
106
107    public P2PMigrationAnalyzer()
108      : base() {
109      Parameters.Add(new LookupParameter<IntValue>("MigrationIterations"));
110      Parameters.Add(new LookupParameter<BoolValue>("Maximization"));
111      Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", 1));
112      Parameters.Add(new ValueParameter<IntValue>("MigrationInterval", "", new IntValue(5)));
113      Parameters.Add(new ValueParameter<PercentValue>("MigrationRate", "", new PercentValue(0.05)));
114      Parameters.Add(new ValueParameter<PercentValue>("CommunicationRate", "", new PercentValue(0.10)));
115      Parameters.Add(new ValueParameter<IntValue>("MessageCacheCapacity", "", new IntValue(1000)));
116      Parameters.Add(new ValueParameter<StringValue>("LanIpPrefix", "", new StringValue("10.")));
117      Parameters.Add(new LookupParameter<IRandom>("Random", "The random number generator"));
118      Parameters.Add(new ValueParameter<StringValue>("ContactServerURL", "", new StringValue("net.tcp://10.42.1.150:9090/DistributedGA.ContactServer/ContactService")));
119      Parameters.Add(new ValueParameter<StringValue>("JobGUID", "", new StringValue(Guid.NewGuid().ToString())));
120    //public ILookupParameter<StringValue> JobGuidParameter {
121    //  get { return (ILookupParameter<StringValue>)Parameters["JobGUID"]; }
122    //}
123
124      Parameters.Add(new ValueParameter<ILog>("Log", "The log", new Log(1000)));
125
126      var validValues = new ItemSet<EnumValue<MigrationStrategy>>();
127      validValues.Add(new EnumValue<MigrationStrategy>(MigrationStrategy.Best));
128      validValues.Add(new EnumValue<MigrationStrategy>(MigrationStrategy.Worst));
129      validValues.Add(new EnumValue<MigrationStrategy>(MigrationStrategy.Random));
130      Parameters.Add(new ConstrainedValueParameter<EnumValue<MigrationStrategy>>("MigrationStrategySelect", validValues, (new EnumValue<MigrationStrategy>(MigrationStrategy.Random))));
131      Parameters.Add(new ConstrainedValueParameter<EnumValue<MigrationStrategy>>("MigrationStrategyReplace", validValues, (new EnumValue<MigrationStrategy>(MigrationStrategy.Random))));
132
133    }
134
135    public override IDeepCloneable Clone(Cloner cloner) {
136      return new P2PMigrationAnalyzer(this, cloner);
137    }
138
139    public override void ClearState() {
140      base.ClearState();
141      h.Dispose();
142      h = null;
143    }
144
145    private void Init() {
146      h = new PeerNetworkMessageHandler();
147      var lanIpPrefix = ((StringValue)(Parameters["LanIpPrefix"].ActualValue)).Value;
148      var contactServerUri = ((StringValue)(Parameters["ContactServerURL"].ActualValue)).Value;
149      var problemInstance = ((StringValue)Parameters["JobGUID"].ActualValue).Value;
150      var communicationRate = ((PercentValue)Parameters["CommunicationRate"].ActualValue).Value;
151      var messageCacheCapacity = ((IntValue)Parameters["MessageCacheCapacity"].ActualValue).Value;
152      h.Init(lanIpPrefix, contactServerUri, problemInstance, (int)(100 * messageCacheCapacity), (int)(100 * communicationRate));
153      h.ExceptionOccurend += ExceptionThrown;
154    }
155
156    public override IOperation Apply() {
157      if (h == null) {
158        Init();
159      }
160
161      if (MigrationIterationsParameter.ActualValue == null) {
162        MigrationIterationsParameter.ActualValue = new IntValue(0);
163      }
164
165      if (MigrationIterations.Value % MigrationInterval.Value == 0) {
166
167        IScope scope = ExecutionContext.Scope;
168        List<IScope> emigrantsList = new List<IScope>();
169
170        //define how many migrants to send
171        var migrationRate = ((PercentValue)Parameters["MigrationRate"].ActualValue).Value;
172        int noOfEmigrants = Convert.ToInt32(scope.SubScopes.Count * migrationRate);
173        if (noOfEmigrants == 0 && scope.SubScopes.Count > 0) {
174          noOfEmigrants = 1;
175        }
176        var popQualities = QualityParameter.ActualValue;
177        var pop = new List<IScope>(scope.SubScopes);
178
179        List<IScope> sortedPop;
180        if (Maximization.Value) {
181          sortedPop = pop.Zip(popQualities, Tuple.Create).OrderByDescending(t => t.Item2).Select(t => t.Item1).ToList();
182        } else {
183          sortedPop = pop.Zip(popQualities, Tuple.Create).OrderBy(t => t.Item2).Select(t => t.Item1).ToList();
184        }
185
186        var selectedMigStratSelect = MigrationStrategySelectParameter.Value.Value;
187        var selectedMigStratReplace = MigrationStrategyReplaceParameter.Value.Value;
188
189        var rand = Random;
190        int replIdx = 0;
191        IScope emigrants = null;
192
193        for (int i = 0; i < noOfEmigrants; i++) {
194          //select emigrant depending on strategy
195          switch (selectedMigStratSelect) {
196            case MigrationStrategy.Best:
197              emigrants = sortedPop[i];
198              emigrantsList.Add(emigrants);
199              break;
200
201            case MigrationStrategy.Random:
202              replIdx = rand.Next(sortedPop.Count);
203              emigrants = sortedPop[replIdx];
204              emigrantsList.Add(emigrants);
205              break;
206
207            case MigrationStrategy.Worst:
208              emigrants = sortedPop[scope.SubScopes.Count - i - 1];
209              emigrantsList.Add(emigrants);
210              break;
211          }
212        }
213
214        {
215          // send
216          for (int ei = 0; ei < emigrantsList.Count; ei++) {
217            using (var stream = new MemoryStream()) {
218              byte[] message;
219              var emigrantScope = emigrantsList[ei];
220
221              var msgScope = new Scope();
222              var cloner = new Cloner();
223              foreach (var variable in emigrantScope.Variables) {
224                msgScope.Variables.Add((IVariable)variable.Clone(cloner));
225              }
226              HeuristicLab.Persistence.Default.Xml.XmlGenerator.Serialize(msgScope, stream);
227              message = stream.GetBuffer();
228              h.PublishDataToNetwork(message);
229            }
230          }
231        }
232
233
234        {
235          // recieve
236          var message = h.GetDataFromNetwork();
237          List<KeyValuePair<PeerInfo, byte[]>> immigrants = new List<KeyValuePair<PeerInfo, byte[]>>();
238          //limit number of immigrants to use
239          if(noOfEmigrants < message.Count)
240          {
241            immigrants = message.Skip(Math.Max(0, message.Count() - noOfEmigrants)).ToList();
242          } else {
243            immigrants = message;
244          }
245         
246          // remove individuals from population to make place for immigrants
247          for (int i = 0; i < immigrants.Count; i++) {
248            switch (selectedMigStratReplace) {
249              case MigrationStrategy.Best:
250                scope.SubScopes.Remove(sortedPop[0]);
251                sortedPop.RemoveAt(0);
252                break;
253
254              case MigrationStrategy.Random:
255                replIdx = rand.Next(sortedPop.Count);
256                scope.SubScopes.Remove(sortedPop[replIdx]);
257                sortedPop.RemoveAt(replIdx);
258                break;
259
260              case MigrationStrategy.Worst:
261                //replace random
262                scope.SubScopes.Remove(sortedPop[sortedPop.Count - 1]);
263                sortedPop.RemoveAt(sortedPop.Count - 1);
264                break;
265            }
266          }
267
268          //insert individual sorted in population
269          var qualities = QualityParameter.ActualValue;
270          var qualityTranslatedName = QualityParameter.TranslatedName;
271          foreach (var msg in immigrants) {
272            using (var stream = new MemoryStream(msg.Value)) {
273              var immigrantScope = HeuristicLab.Persistence.Default.Xml.XmlParser.Deserialize<IScope>(stream);
274
275              var qImmigrant = ((DoubleValue)immigrantScope.Variables[qualityTranslatedName].Value).Value;
276              var insertPos = scope.SubScopes.Count;
277              var maximization = Maximization.Value;
278              for (int i = 0; i < qualities.Length; i++) {
279                var qi = qualities[i].Value;
280                if ((maximization && qi < qImmigrant) || (!maximization && qi > qImmigrant)) {
281                  insertPos = i;
282                  break;
283                }
284              }
285
286              scope.SubScopes.Insert(insertPos, immigrantScope);
287
288              var log = LogParameter.Value;
289              double quality = qImmigrant;
290              log.LogMessage(string.Format("Recieved individual with quality {0} from peer {1}:{2} ; Job: {3}",
291                                            quality, msg.Key.IpAddress, msg.Key.Port, msg.Key.ProblemInstance));
292            }
293          }
294        }
295      }
296
297      MigrationIterations.Value++;
298      return base.Apply();
299    }
300
301    private void ExceptionThrown(object sender, Exception e) {
302      var log = LogParameter.Value;
303      log.LogMessage(e.Message);
304    }
305
306  }
307}
Note: See TracBrowser for help on using the repository browser.