using HeuristicLab.BioBoost.ProblemDescription; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.IntegerVectorEncoding; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Random; using System; using System.Linq; namespace HeuristicLab.BioBoost.Operators.Mutation { [StorableClass] public class CommonTargetSwappingIntegerVectorMutator : BoundedIntegerVectorManipulator { public LookupParameter ProblemDataParameter { get { return (LookupParameter) Parameters["ProblemData"]; } } public ValueLookupParameter AvgBundleMutationRatioParameter { get { return (ValueLookupParameter) Parameters["AvgBundleMutationRatio"]; } } public double AvgBundleMutationRatio { get { return AvgBundleMutationRatioParameter.ActualValue.Value; } } public BioBoostProblemData ProblemData { get { return ProblemDataParameter.ActualValue; } } #region Construction & Cloning [StorableConstructor] protected CommonTargetSwappingIntegerVectorMutator(bool isDeserializing) : base(isDeserializing) {} protected CommonTargetSwappingIntegerVectorMutator(CommonTargetSwappingIntegerVectorMutator orig, Cloner cloner) : base(orig, cloner) {} public CommonTargetSwappingIntegerVectorMutator() { Parameters.Add(new LookupParameter("ProblemData", "The problem instance description container.")); Parameters.Add(new ValueLookupParameter("AvgBundleMutationRatio", "The average ratio of modified targets in a bundle.", new PercentValue(0.25))); } public override IDeepCloneable Clone(Cloner cloner) { return new CommonTargetSwappingIntegerVectorMutator(this, cloner); } #endregion protected override void ManipulateBounded(IRandom random, IntegerVector integerVector, IntMatrix bounds) { var ratio = new NormalDistributedRandom(random, Math.Min(1, Math.Max(0, AvgBundleMutationRatio)), 0.25).NextDouble(); var targetGroups = integerVector .Select((t, i) => new {t, i}) .GroupBy(x => x.t, x => x.i) .Shuffle(random) .Take(2) .ToList(); if (targetGroups.Count == 2) { var targetList1 = targetGroups[0].Shuffle(random).ToList(); var targetList2 = targetGroups[1].Shuffle(random).ToList(); foreach (var i in targetList1.Take(Math.Max(1, (int)Math.Round(ratio*targetList1.Count)))) { integerVector[i] = targetGroups[1].Key; } foreach (var i in targetList2.Take(Math.Max(1, (int)Math.Round(ratio*targetList2.Count)))) { integerVector[i] = targetGroups[0].Key; } } else if (targetGroups.Count == 1) { integerVector[random.Next(integerVector.Length)] = random.Next(integerVector.Length); } } } }