using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; 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; namespace HeuristicLab.BioBoost.Operators { [StorableClass] public class LimitedDistanceTransportTargetCreator : BioBoostOperator, IIntegerVectorCreator { #region IntegerVectorCreator public IValueLookupParameter RandomParameter { get { return (IValueLookupParameter) Parameters["Random"]; } } public IValueLookupParameter BoundsParameter { get { return (IValueLookupParameter) Parameters["Bounds"]; } } public IValueLookupParameter LengthParameter { get { return (IValueLookupParameter) Parameters["Length"]; } } public IValueLookupParameter TournamentSizeParameter { get { return (IValueLookupParameter) Parameters["TournamentSize"]; } } public ILookupParameter IntegerVectorParameter { get { return (ILookupParameter) Parameters["IntegerVector"]; } } public LookupParameter DistanceMatrixParameter { get { return (LookupParameter) Parameters["DistanceMatrix"]; } } public ValueParameter DistanceMatrixInProblemDataParameter { get { return (ValueParameter) Parameters["DistanceMatrixInProblemData"]; } } #endregion public bool DistanceMatrixInProblemData { get { return DistanceMatrixInProblemDataParameter.Value.Value; } } public DistanceMatrix DistanceMatrix { get { if (DistanceMatrixInProblemData) { return ((IValueParameter) ProblemData.Parameters[DistanceMatrixParameter.ActualName]).Value; } else { return DistanceMatrixParameter.ActualValue; } } } #region Construction & Cloning [StorableConstructor] protected LimitedDistanceTransportTargetCreator(bool isDeserializing) : base(isDeserializing) { } protected LimitedDistanceTransportTargetCreator(LimitedDistanceTransportTargetCreator orig, Cloner cloner) : base(orig, cloner) {} public LimitedDistanceTransportTargetCreator() { Parameters.Add(new ValueLookupParameter("Bounds", "The list of limits for each dimension (wrapped around if too short)")); Parameters.Add(new ValueLookupParameter("Length", "The length of the integer vector to be created")); Parameters.Add(new LookupParameter("IntegerVector", "The newly created integer vector")); Parameters.Add(new ValueLookupParameter("Random", "The random number generator to use.")); Parameters.Add(new ValueLookupParameter("TournamentSize", "The tournament size as a fraction of the length. (higher values yield closer targets, 0 is random)", new IntValue(5))); Parameters.Add(new LookupParameter("DistanceMatrix", "The distance matrix to use", "StreetDistanceMatrix")); // TODO: check this Parameters.Add(new ValueParameter("DistanceMatrixInProblemData", "Whether to look for the distance matrix in problem data or in scope.", new BoolValue(true))); DistanceMatrixParameter.Hidden = false; } public override IDeepCloneable Clone(Cloner cloner) { return new LimitedDistanceTransportTargetCreator(this, cloner); } #endregion public override IOperation Apply() { var random = RandomParameter.ActualValue; var length = LengthParameter.ActualValue.Value; var v = new IntegerVector(length); var tournamentSize = Math.Min(length, Math.Max(1, TournamentSizeParameter.ActualValue.Value)); var bounds = BoundsParameter.ActualValue; for (int i = 0; i < length; i++) { var min = bounds[i%bounds.Rows, 0]; var max = bounds[i%bounds.Rows, 1]; var range = max - min; var sample = tournamentSize > length/3 ? Enumerable.Range(min, range).SampleRandom(random, tournamentSize).ToList() : Enumerable.Range(0, tournamentSize).Select(j => random.Next(range) + min).ToList(); v[i] = sample .Select(j => new {j, dist = DistanceMatrix[i, j]}) .OrderBy(x => x.dist) .First().j; } IntegerVectorParameter.ActualValue = v; return base.Apply(); } } }