#region License Information
/* HeuristicLab
* Copyright (C) 2002-2016 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.Linq;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Data;
using HeuristicLab.Optimization;
using HeuristicLab.Encodings.PermutationEncoding;
using HeuristicLab.Encodings.RealVectorEncoding;
using HeuristicLab.Parameters;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
// ReSharper disable once CheckNamespace
namespace HeuristicLab.Algorithms.EGO {
[StorableClass]
[Item("LatinHyperCubeDesignCreator", "A latin hypercube sampling strategy for real valued optimization")]
public class LatinHyperCubeDesignCreator : RealVectorCreator, IInitialSampling {
private IValueLookupParameter DesignSize => (IValueLookupParameter)Parameters["DesignSize"];
[Storable]
private Queue design = new Queue();
[StorableConstructor]
protected LatinHyperCubeDesignCreator(bool deserializing) : base(deserializing) { }
protected LatinHyperCubeDesignCreator(LatinHyperCubeDesignCreator original, Cloner cloner) : base(original, cloner) {
design = new Queue(original.design.Select(cloner.Clone));
}
public LatinHyperCubeDesignCreator() {
Parameters.Add(new ValueLookupParameter("DesignSize", "The size of the LHS-design produced by this creator"));
}
public override IDeepCloneable Clone(Cloner cloner) {
return new LatinHyperCubeDesignCreator(this, cloner);
}
public RealVector[] GetSamples(int noSamples, RealVector[] existingSamples, IEncoding encoding, IRandom random) {
var enc = encoding as RealVectorEncoding;
return GetSamples(random, enc.Length, enc.Bounds, noSamples);
}
public RealVector[] GetSamples(IRandom random, int dimensions, DoubleMatrix bounds, int noSamples) {
if (noSamples < 1) throw new ArgumentException("Designs need to have at least 1 Point");
var samples = new RealVector[noSamples];
for (var i = 0; i < noSamples; i++) samples[i] = new RealVector(dimensions);
for (var i = 0; i < dimensions; i++) {
var permutations = new Permutation(PermutationTypes.Absolute, noSamples, random);
var row = i % bounds.Rows;
var offset = bounds[row, 0];
var range = (bounds[row, 1] - offset) / noSamples;
for (var j = 0; j < noSamples; j++) samples[j][i] = offset + (permutations[j] + random.NextDouble()) * range;
}
return samples;
}
protected override RealVector Create(IRandom random, IntValue length, DoubleMatrix bounds) {
if (design.Count == 0) design = new Queue(GetSamples(random, length.Value, bounds, DesignSize.ActualValue.Value));
return design.Dequeue();
}
}
}