#region License Information /* HeuristicLab * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using DistributedGA.Core.Domain; using DistributedGA.Core.Implementation; using DistributedGA.Core.Interface; using DistributedGA.Core.Util; using DistributedGA.Hive; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Operators; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Optimization.Operators { [Item("P2PMigrationAnalyzer", "Migrates individuals using a P2P network.")] [StorableClass] public class P2PMigrationAnalyzer : SingleSuccessorOperator, IAnalyzer, ISingleObjectiveOperator, IDisposable { // state: messagehandler [ExcludeFromObjectGraphTraversalAttribute] private IMessageHandler h; public bool EnabledByDefault { get { return false; } } public ILookupParameter MaximizationParameter { get { return (ILookupParameter)Parameters["Maximization"]; } } // for name translation public ScopeTreeLookupParameter QualityParameter { get { return (ScopeTreeLookupParameter)Parameters["Quality"]; } } public ILookupParameter MigrationIterationsParameter { get { return (ILookupParameter)Parameters["MigrationIterations"]; } } public IValueParameter MigrationRatesParameter { get { return (IValueParameter)Parameters["MigrationRate"]; } } public IValueParameter CommunicationRatesParameter { get { return (IValueParameter)Parameters["CommunicationRate"]; } } public IValueParameter MessageCacheCapacityParameter { get { return (IValueParameter)Parameters["MessageCacheCapacity"]; } } public ILookupParameter RandomParameter { get { return (ILookupParameter)Parameters["Random"]; } } public IValueParameter MigrationIntervalParameter { get { return (IValueParameter)Parameters["MigrationInterval"]; } } public IValueParameter LogParameter { get { return (IValueParameter)Parameters["Log"]; } } public IValueParameter JobGuidParameter { get { return (IValueParameter)Parameters["JobGUID"]; } } public IConstrainedValueParameter> MigrationStrategySelectParameter { get { return (IConstrainedValueParameter>)Parameters["MigrationStrategySelect"]; } } public IConstrainedValueParameter> MigrationStrategyReplaceParameter { get { return (IConstrainedValueParameter>)Parameters["MigrationStrategyReplace"]; } } public BoolValue Maximization { get { return MaximizationParameter.ActualValue; } } public IntValue MigrationIterations { get { return MigrationIterationsParameter.ActualValue; } } public IntValue MigrationInterval { get { return MigrationIntervalParameter.Value; } } public IRandom Random { get { return RandomParameter.ActualValue; } } [StorableConstructor] protected P2PMigrationAnalyzer(bool deserializing) : base(deserializing) { } protected P2PMigrationAnalyzer(P2PMigrationAnalyzer original, Cloner cloner) : base(original, cloner) { } public P2PMigrationAnalyzer() : base() { Parameters.Add(new LookupParameter("MigrationIterations")); Parameters.Add(new LookupParameter("Maximization")); Parameters.Add(new ScopeTreeLookupParameter("Quality", 1)); Parameters.Add(new ValueParameter("MigrationInterval", "", new IntValue(5))); Parameters.Add(new ValueParameter("MigrationRate", "", new PercentValue(0.05))); Parameters.Add(new ValueParameter("CommunicationRate", "", new PercentValue(0.25))); Parameters.Add(new ValueParameter("MessageCacheCapacity", "", new IntValue(40))); Parameters.Add(new ValueParameter("LanIpPrefix", "", new StringValue("10."))); Parameters.Add(new LookupParameter("Random", "The random number generator")); Parameters.Add(new ValueParameter("ContactServerURL", "", new StringValue("net.tcp://10.20.71.18:9090/DistributedGA.ContactServer/ContactService"))); Parameters.Add(new ValueParameter("JobGUID", "", new StringValue(Guid.NewGuid().ToString()))); Parameters.Add(new ValueParameter("Log", "The log", new Log(1000))); Parameters.Add(new ValueParameter("ByteArraysAllocated", new IntValue(0))); Parameters.Add(new ValueParameter("ByteArraysFreed", new IntValue(0))); Parameters.Add(new ValueParameter("ByteArraysAlive", new IntValue(0))); var validValues = new ItemSet>(); validValues.Add(new EnumValue(MigrationStrategy.Best)); validValues.Add(new EnumValue(MigrationStrategy.Worst)); validValues.Add(new EnumValue(MigrationStrategy.Random)); Parameters.Add(new ConstrainedValueParameter>("MigrationStrategySelect", validValues, (new EnumValue(MigrationStrategy.Random)))); Parameters.Add(new ConstrainedValueParameter>("MigrationStrategyReplace", validValues, (new EnumValue(MigrationStrategy.Random)))); } public override IDeepCloneable Clone(Cloner cloner) { return new P2PMigrationAnalyzer(this, cloner); } public override void ClearState() { base.ClearState(); Dispose(); } private void Init() { h = new PeerNetworkMessageHandler(); var lanIpPrefix = ((StringValue)(Parameters["LanIpPrefix"].ActualValue)).Value; var contactServerUri = ((StringValue)(Parameters["ContactServerURL"].ActualValue)).Value; var problemInstance = ((StringValue)Parameters["JobGUID"].ActualValue).Value; var communicationRate = ((PercentValue)Parameters["CommunicationRate"].ActualValue).Value; var messageCacheCapacity = ((IntValue)Parameters["MessageCacheCapacity"].ActualValue).Value; h.Init(lanIpPrefix, contactServerUri, problemInstance, messageCacheCapacity, (int)(100 * communicationRate)); h.ExceptionOccurend += ExceptionThrown; } public override IOperation Apply() { if (h == null) { Init(); } if (MigrationIterationsParameter.ActualValue == null) { MigrationIterationsParameter.ActualValue = new IntValue(0); } if (MigrationIterations.Value % MigrationInterval.Value == 0) { IScope scope = ExecutionContext.Scope; List emigrantsList = new List(); //define how many migrants to send var migrationRate = ((PercentValue)Parameters["MigrationRate"].ActualValue).Value; int noOfEmigrants = Convert.ToInt32(scope.SubScopes.Count * migrationRate); if (noOfEmigrants == 0 && scope.SubScopes.Count > 0) { noOfEmigrants = 1; } var popQualities = QualityParameter.ActualValue; var pop = new List(scope.SubScopes); List sortedPop; if (Maximization.Value) { sortedPop = pop.Zip(popQualities, Tuple.Create).OrderByDescending(t => t.Item2).Select(t => t.Item1).ToList(); } else { sortedPop = pop.Zip(popQualities, Tuple.Create).OrderBy(t => t.Item2).Select(t => t.Item1).ToList(); } var selectedMigStratSelect = MigrationStrategySelectParameter.Value.Value; var selectedMigStratReplace = MigrationStrategyReplaceParameter.Value.Value; var rand = Random; int replIdx = 0; IScope emigrants = null; for (int i = 0; i < noOfEmigrants; i++) { //select emigrant depending on strategy switch (selectedMigStratSelect) { case MigrationStrategy.Best: emigrants = sortedPop[i]; emigrantsList.Add(emigrants); break; case MigrationStrategy.Random: replIdx = rand.Next(sortedPop.Count); emigrants = sortedPop[replIdx]; emigrantsList.Add(emigrants); break; case MigrationStrategy.Worst: emigrants = sortedPop[scope.SubScopes.Count - i - 1]; emigrantsList.Add(emigrants); break; } } { // send for (int ei = 0; ei < emigrantsList.Count; ei++) { using (var stream = new MemoryStream()) { byte[] message; var emigrantScope = emigrantsList[ei]; var msgScope = new Scope(); var cloner = new Cloner(); foreach (var variable in emigrantScope.Variables) { msgScope.Variables.Add((IVariable)variable.Clone(cloner)); } HeuristicLab.Persistence.Default.Xml.XmlGenerator.Serialize(msgScope, stream); message = stream.GetBuffer(); h.PublishDataToNetwork(ByteArrayWrapper.CreateByteArrayWrapper(message)); } } } { // recieve var message = h.GetDataFromNetwork(); List> immigrants = new List>(); //limit number of immigrants to use if (noOfEmigrants < message.Count) { immigrants = message.Skip(Math.Max(0, message.Count() - noOfEmigrants)).ToList(); } else { immigrants = message; } // remove individuals from population to make place for immigrants for (int i = 0; i < immigrants.Count; i++) { switch (selectedMigStratReplace) { case MigrationStrategy.Best: scope.SubScopes.Remove(sortedPop[0]); sortedPop.RemoveAt(0); break; case MigrationStrategy.Random: replIdx = rand.Next(sortedPop.Count); scope.SubScopes.Remove(sortedPop[replIdx]); sortedPop.RemoveAt(replIdx); break; case MigrationStrategy.Worst: //replace random scope.SubScopes.Remove(sortedPop[sortedPop.Count - 1]); sortedPop.RemoveAt(sortedPop.Count - 1); break; } } //insert individual sorted in population var qualities = QualityParameter.ActualValue; var qualityTranslatedName = QualityParameter.TranslatedName; foreach (var msg in immigrants) { using (var stream = new MemoryStream(msg.Value.Array)) { var immigrantScope = HeuristicLab.Persistence.Default.Xml.XmlParser.Deserialize(stream); var qImmigrant = ((DoubleValue)immigrantScope.Variables[qualityTranslatedName].Value).Value; var insertPos = scope.SubScopes.Count; var maximization = Maximization.Value; for (int i = 0; i < qualities.Length; i++) { var qi = qualities[i].Value; if ((maximization && qi < qImmigrant) || (!maximization && qi > qImmigrant)) { insertPos = i; break; } } scope.SubScopes.Insert(insertPos, immigrantScope); var log = LogParameter.Value; double quality = qImmigrant; log.LogMessage(string.Format("Recieved individual with quality {0} from peer {1}:{2} ; Job: {3}", quality, msg.Key.IpAddress, msg.Key.Port, msg.Key.ProblemInstance)); } } } } MigrationIterations.Value++; ((IValueParameter)Parameters["ByteArraysAllocated"]).Value.Value = ByteArrayWrapper.AllocatedCounter; ((IValueParameter)Parameters["ByteArraysFreed"]).Value.Value = ByteArrayWrapper.FreedCounter; ((IValueParameter)Parameters["ByteArraysAlive"]).Value.Value = ByteArrayWrapper.AliveCounter; return base.Apply(); } private void ExceptionThrown(object sender, Exception e) { var log = LogParameter.Value; log.LogMessage(e.Message); } public void Dispose() { h.Dispose(); h = null; } } }