#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.Generic;
using System.Data.SqlTypes;
using System.IO;
using System.ServiceModel.Configuration;
using System.Threading;
using DistributedGA.Core.Domain;
using DistributedGA.Core.Implementation;
using DistributedGA.Core.Interface;
using DistributedGA.Hive;
using HeuristicLab.Clients.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 {
// state: messagehandler
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 ILookupParameter MigrationRatesParameter {
get { return (ILookupParameter)Parameters["MigrationRate"]; }
}
public ILookupParameter CommunicationRatesParameter {
get { return (ILookupParameter)Parameters["CommunicationRate"]; }
}
public ILookupParameter MessageCacheCapacityParameter {
get { return (ILookupParameter)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 IConstrainedValueParameter> MigrationStrategyParameter {
get { return (IConstrainedValueParameter>)Parameters["MigrationStrategy"]; }
}
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(1)));
Parameters.Add(new ValueParameter("MigrationRate", "", new PercentValue(0.05)));
Parameters.Add(new ValueParameter("CommunicationRate", "", new PercentValue(0.10)));
Parameters.Add(new ValueParameter("MessageCacheCapacity", "", new IntValue(100)));
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.42.1.150:9090/DistributedGA.ContactServer/ContactService")));
Parameters.Add(new ValueParameter("JobGUID", "", new StringValue(Guid.NewGuid().ToString())));
Parameters.Add(new ValueParameter("Log", "The log", new Log(1000)));
var validValues = new ItemSet>();
validValues.Add(new EnumValue(MigrationStrategy.TakeBestReplaceBad));
validValues.Add(new EnumValue(MigrationStrategy.TakeBestReplaceRandom));
validValues.Add(new EnumValue(MigrationStrategy.TakeRandomReplaceBad));
validValues.Add(new EnumValue(MigrationStrategy.TakeRandomReplaceRandom));
Parameters.Add(new ConstrainedValueParameter>("MigrationStrategy", validValues, (new EnumValue(MigrationStrategy.TakeBestReplaceBad))));
}
public override IDeepCloneable Clone(Cloner cloner) {
return new P2PMigrationAnalyzer(this, cloner);
}
public override void ClearState() {
base.ClearState();
h.Dispose();
h = null;
}
public override void InitializeState() {
base.InitializeState();
// init P2P
Init();
}
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, (int)(100 * 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;
var popQualities = QualityParameter.ActualValue;
var selectedMigStrat = MigrationStrategyParameter.Value.Value;
var rand = Random;
int replIdx = 0;
IScope emigrants = null;
//determine how many emigrants to send
int max = Convert.ToInt32(scope.SubScopes.Count * migrationRate);
if (max == 0 && scope.SubScopes.Count > 0) {
max = 0;
}
for (int i = 0; i < max; i++) {
//select emigrant depending on strategy
switch (selectedMigStrat) {
case MigrationStrategy.TakeBestReplaceBad:
emigrants = scope.SubScopes[i];
emigrantsList.Add(emigrants);
break;
case MigrationStrategy.TakeBestReplaceRandom:
emigrants = scope.SubScopes[i];
emigrantsList.Add(emigrants);
break;
case MigrationStrategy.TakeRandomReplaceBad:
replIdx = rand.Next(scope.SubScopes.Count);
emigrants = scope.SubScopes[replIdx];
emigrantsList.Add(emigrants);
break;
case MigrationStrategy.TakeRandomReplaceRandom:
replIdx = rand.Next(scope.SubScopes.Count);
emigrants = scope.SubScopes[replIdx];
emigrantsList.Add(emigrants);
break;
default:
break;
}
}
//each subscope is one emigrand
//IScope emigrants = scope.SubScopes[1];
//emigrantsList.Add(emigrants);
{
// send
var message = new byte[emigrantsList.Count][];
for (int ei = 0; ei < emigrantsList.Count; ei++) {
using (var stream = new MemoryStream()) {
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));
}
msgScope.ClearParentScopes();
HeuristicLab.Persistence.Default.Xml.XmlGenerator.Serialize(msgScope, stream);
message[ei] = stream.GetBuffer();
}
}
h.PublishDataToNetwork(message);
}
{
// recieve
var message = h.GetDataFromNetwork();
for (int ei = 0; ei < message.Length; ei++) {
using (var stream = new MemoryStream(message[ei])) {
var immigrantScope = HeuristicLab.Persistence.Default.Xml.XmlParser.Deserialize(stream);
// replace individual in current population
switch (selectedMigStrat) {
case MigrationStrategy.TakeBestReplaceBad:
scope.SubScopes.RemoveAt(0);
break;
case MigrationStrategy.TakeRandomReplaceBad:
scope.SubScopes.RemoveAt(0);
break;
case MigrationStrategy.TakeBestReplaceRandom:
//replace random
replIdx = rand.Next(scope.SubScopes.Count);
scope.SubScopes.RemoveAt(replIdx);
break;
case MigrationStrategy.TakeRandomReplaceRandom:
//replace random
replIdx = rand.Next(scope.SubScopes.Count);
scope.SubScopes.RemoveAt(replIdx);
break;
default:
break;
}
//insert individual sortet in population
var qualities = QualityParameter.ActualValue;
var qualityTranslatedName = QualityParameter.TranslatedName;
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 = 0.0;
quality = qImmigrant;
log.LogMessage(string.Format("Recieved individual with quality {0}", quality));
}
}
}
}
MigrationIterations.Value++;
return base.Apply();
}
private void ExceptionThrown(object sender, Exception e) {
var log = LogParameter.Value;
log.LogMessage(e.Message);
}
}
}