using HeuristicLab.Optimization; using System; using System.Collections.Generic; using System.Linq; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Encodings.MoveVectorEncoding.Interfaces; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Data; using HeuristicLab.PluginInfrastructure; using HeuristicLab.Parameters; using HeuristicLab.Encodings.MoveVectorEncoding.Creators; using HeuristicLab.Data.MoveVectorData; namespace HeuristicLab.Encodings.MoveVectorEncoding { [Item("MoveVectorEncoding", "Describes a Move Vector encoding.")] [StorableClass] public sealed class MoveVectorEncoding : Encoding { #region Parameter Properties [Storable] private IFixedValueParameter lengthParameter; public IFixedValueParameter LengthParameter { get { return lengthParameter; } set { if (value == null) throw new ArgumentNullException("Length parameter must not be null."); if (value.Value == null) throw new ArgumentNullException("Length parameter value must not be null."); if (lengthParameter == value) return; if (lengthParameter != null) Parameters.Remove(lengthParameter); lengthParameter = value; Parameters.Add(lengthParameter); OnLengthParameterChanged(); } } [Storable] private IValueParameter boundsParameter; public IValueParameter BoundsParameter { get { return boundsParameter; } set { if (value == null) throw new ArgumentNullException("Bounds parameter must not be null."); if (boundsParameter == value) return; if (boundsParameter != null) Parameters.Remove(boundsParameter); boundsParameter = value; Parameters.Add(boundsParameter); OnBoundsParameterChanged(); } } #endregion #region Properties public int Length { get { return LengthParameter.Value.Value; } set { LengthParameter.Value.Value = value; } } public IntMatrix Bounds { get { return BoundsParameter.Value; } set { BoundsParameter.Value = value; } } #endregion #region Cloning [StorableConstructor] private MoveVectorEncoding(bool deserializing) : base(deserializing) { } [StorableHook(HookType.AfterDeserialization)] private void AfterDeserialization() { RegisterParameterEvents(); DiscoverOperators(); } public override IDeepCloneable Clone(Cloner cloner) { return new MoveVectorEncoding(this, cloner); } private MoveVectorEncoding(MoveVectorEncoding original, Cloner cloner) : base(original, cloner) { lengthParameter = cloner.Clone(original.lengthParameter); boundsParameter = cloner.Clone(original.boundsParameter); RegisterParameterEvents(); } #endregion public MoveVectorEncoding() : this("MoveVector", 10) { } public MoveVectorEncoding(string name) : this(name, 10) { } public MoveVectorEncoding(int length, int min, int max) : this("MoveVector", length, min, max) { } public MoveVectorEncoding(string name, int length, int min = int.MinValue, int max = int.MaxValue, int? step = null) : base(name) { if (min >= max) throw new ArgumentException("min must be less than max", "min"); if (step.HasValue && step.Value <= 0) throw new ArgumentException("step must be greater than zero or null", "step"); var bounds = new IntMatrix(1, step.HasValue ? 3 : 2); bounds[0, 0] = min; bounds[0, 1] = max; if (step.HasValue) bounds[0, 2] = step.Value; lengthParameter = new FixedValueParameter(Name + ".Length", new IntValue(length)); boundsParameter = new ValueParameter(Name + ".Bounds", bounds); Parameters.Add(lengthParameter); Parameters.Add(boundsParameter); SolutionCreator = new RandomMoveVectorCreator(); RegisterParameterEvents(); DiscoverOperators(); } #region Operators private static readonly IEnumerable encodingSpecificOperatorTypes; static MoveVectorEncoding() { encodingSpecificOperatorTypes = new List() { typeof(IMoveVectorOperator), typeof(IMoveVectorCreator), typeof(IMoveVectorCrossover), typeof(IMoveVectorManipulator) }; } private void DiscoverOperators() { var assembly = typeof(IMoveVectorOperator).Assembly; var discoveredTypes = ApplicationManager.Manager.GetTypes(encodingSpecificOperatorTypes, assembly, true, false, false); var operators = discoveredTypes.Select(t => (IOperator)Activator.CreateInstance(t)); var newOperators = operators.Except(Operators, new TypeEqualityComparer()).ToList(); ConfigureOperators(newOperators); foreach (var @operator in newOperators) AddOperator(@operator); } public override void ConfigureOperators(IEnumerable operators) { ConfigureBoundedOperators(operators.OfType()); ConfigureCreators(operators.OfType()); ConfigureCrossovers(operators.OfType()); ConfigureManipulators(operators.OfType()); ConfigureShakingOperators(operators.OfType()); } private void ConfigureBoundedOperators(IEnumerable boundedOperators) { foreach (var boundedOperator in boundedOperators) { boundedOperator.BoundsParameter.ActualName = BoundsParameter.Name; } } private void ConfigureCreators(IEnumerable creators) { foreach (var creator in creators) { creator.MoveVectorParameter.ActualName = Name; creator.BoundsParameter.ActualName = BoundsParameter.Name; creator.LengthParameter.ActualName = LengthParameter.Name; } } private void ConfigureCrossovers(IEnumerable crossovers) { foreach (var crossover in crossovers) { crossover.ChildParameter.ActualName = Name; crossover.ParentsParameter.ActualName = Name; } } private void ConfigureManipulators(IEnumerable manipulators) { foreach (var manipulator in manipulators) { manipulator.MoveVectorParameter.ActualName = Name; manipulator.MoveVectorParameter.Hidden = true; var sm = manipulator as ISelfAdaptiveManipulator; if (sm != null) { var p = sm.StrategyParameterParameter as ILookupParameter; if (p != null) { p.ActualName = Name + "Strategy"; } } } } private void ConfigureShakingOperators(IEnumerable shakingOperators) { foreach (var shakingOperator in shakingOperators) { shakingOperator.MoveVectorParameter.ActualName = Name; } } #endregion #region Events private void RegisterParameterEvents() { RegisterLengthParameterEvents(); RegisterBoundsParameterEvents(); } private void OnLengthParameterChanged() { RegisterLengthParameterEvents(); ConfigureOperators(Operators); } private void OnBoundsParameterChanged() { RegisterBoundsParameterEvents(); ConfigureOperators(Operators); } private void RegisterLengthParameterEvents() { LengthParameter.ValueChanged += (o, s) => ConfigureOperators(Operators); LengthParameter.Value.ValueChanged += (o, s) => ConfigureOperators(Operators); } private void RegisterBoundsParameterEvents() { BoundsParameter.ValueChanged += (o, s) => ConfigureOperators(Operators); boundsParameter.Value.ToStringChanged += (o, s) => ConfigureOperators(Operators); } #endregion } public static class IndividualExtensionMethods { public static MoveVector MoveVector(this Individual individual) { var encoding = individual.GetEncoding(); return individual.MoveVector(encoding.Name); } public static MoveVector MoveVector(this Individual individual, string name) { return (MoveVector)individual[name]; } } }