using System.Linq; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Operators; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Problems.MetaOptimization { /// /// TODO /// [Item("ReferenceQualityAnalyzer", "")] [StorableClass] public sealed class ReferenceQualityAnalyzer : SingleSuccessorOperator, IAnalyzer { public bool EnabledByDefault { get { return true; } } public ValueLookupParameter ResultsParameter { get { return (ValueLookupParameter)Parameters["Results"]; } } public ScopeTreeLookupParameter ParameterConfigurationParameter { get { return (ScopeTreeLookupParameter)Parameters["ParameterConfigurationTree"]; } } public ScopeTreeLookupParameter QualityParameter { get { return (ScopeTreeLookupParameter)Parameters["Quality"]; } } public LookupParameter ReferenceQualityAveragesParameter { get { return (LookupParameter)Parameters["ReferenceQualityAverages"]; } } public LookupParameter ReferenceQualityDeviationsParameter { get { return (LookupParameter)Parameters["ReferenceQualityDeviations"]; } } public LookupParameter ReferenceEvaluatedSolutionAveragesParameter { get { return (LookupParameter)Parameters["ReferenceEvaluatedSolutionAverages"]; } } public LookupParameter> ProblemsParameter { get { return (LookupParameter>)Parameters[MetaOptimizationProblem.ProblemsParameterName]; } } public LookupParameter MaximizationParameter { get { return (LookupParameter)Parameters["Maximization"]; } } public LookupParameter QualityWeightParameter { get { return (LookupParameter)Parameters[MetaOptimizationProblem.QualityWeightParameterName]; } } public LookupParameter StandardDeviationWeightParameter { get { return (LookupParameter)Parameters[MetaOptimizationProblem.StandardDeviationWeightParameterName]; } } public LookupParameter EvaluatedSolutionsWeightParameter { get { return (LookupParameter)Parameters[MetaOptimizationProblem.EvaluatedSolutionsWeightParameterName]; } } public ReferenceQualityAnalyzer() : base() { Parameters.Add(new ScopeTreeLookupParameter("Quality", "")); Parameters.Add(new ValueLookupParameter("Results", "")); Parameters.Add(new ScopeTreeLookupParameter("ParameterConfigurationTree", "")); Parameters.Add(new LookupParameter("ReferenceQualityAverages", "")); Parameters.Add(new LookupParameter("ReferenceQualityDeviations", "")); Parameters.Add(new LookupParameter("ReferenceEvaluatedSolutionAverages", "")); Parameters.Add(new LookupParameter>(MetaOptimizationProblem.ProblemsParameterName)); Parameters.Add(new LookupParameter("Maximization", "Set to false if the problem should be minimized.")); Parameters.Add(new LookupParameter(MetaOptimizationProblem.QualityWeightParameterName)); Parameters.Add(new LookupParameter(MetaOptimizationProblem.StandardDeviationWeightParameterName)); Parameters.Add(new LookupParameter(MetaOptimizationProblem.EvaluatedSolutionsWeightParameterName)); } [StorableConstructor] private ReferenceQualityAnalyzer(bool deserializing) : base(deserializing) { } private ReferenceQualityAnalyzer(ReferenceQualityAnalyzer original, Cloner cloner) : base(original, cloner) { } public override IDeepCloneable Clone(Cloner cloner) { return new ReferenceQualityAnalyzer(this, cloner); } public override IOperation Apply() { ResultCollection results = ResultsParameter.ActualValue; ItemArray solutions = ParameterConfigurationParameter.ActualValue; ItemArray qualities = QualityParameter.ActualValue; bool maximization = MaximizationParameter.ActualValue.Value; double qualityWeight = QualityWeightParameter.ActualValue.Value; double standardDeviationWeight = StandardDeviationWeightParameter.ActualValue.Value; double evaluatedSolutionsWeight = EvaluatedSolutionsWeightParameter.ActualValue.Value; if (ReferenceQualityAveragesParameter.ActualValue == null) { // this is generation zero. calculate the reference values and apply them on population. in future generations `AlgorithmRunsAnalyzer` will do the nomalization DoubleArray referenceQualityAverages = CalculateReferenceQualityAverages(solutions, maximization); DoubleArray referenceQualityDeviations = CalculateReferenceQualityDeviations(solutions, maximization); DoubleArray referenceEvaluatedSolutionAverages = CalculateReferenceEvaluatedSolutionAverages(solutions, maximization); ReferenceQualityAveragesParameter.ActualValue = referenceQualityAverages; ReferenceQualityDeviationsParameter.ActualValue = referenceQualityDeviations; ReferenceEvaluatedSolutionAveragesParameter.ActualValue = referenceEvaluatedSolutionAverages; NormalizePopulation(solutions, qualities, referenceQualityAverages, referenceQualityDeviations, referenceEvaluatedSolutionAverages, qualityWeight, standardDeviationWeight, evaluatedSolutionsWeight, maximization); results.Add(new Result("ReferenceQualities", referenceQualityAverages)); results.Add(new Result("ReferenceQualityDeviations", referenceQualityDeviations)); results.Add(new Result("ReferenceEvaluatedSolutionAverages", referenceEvaluatedSolutionAverages)); } return base.Apply(); } private DoubleArray CalculateReferenceQualityAverages(ItemArray solutions, bool maximization) { DoubleArray references = new DoubleArray(ProblemsParameter.ActualValue.Count); for (int pi = 0; pi < ProblemsParameter.ActualValue.Count; pi++) { if (maximization) references[pi] = solutions.Where(x => x.AverageQualities != null).Select(x => x.AverageQualities[pi]).Max(); else references[pi] = solutions.Where(x => x.AverageQualities != null).Select(x => x.AverageQualities[pi]).Min(); } return references; } private DoubleArray CalculateReferenceQualityDeviations(ItemArray solutions, bool maximization) { DoubleArray references = new DoubleArray(ProblemsParameter.ActualValue.Count); for (int pi = 0; pi < ProblemsParameter.ActualValue.Count; pi++) { if (maximization) references[pi] = solutions.Where(x => x.QualityStandardDeviations != null).Select(x => x.QualityStandardDeviations[pi]).Max(); else references[pi] = solutions.Where(x => x.QualityStandardDeviations != null).Select(x => x.QualityStandardDeviations[pi]).Min(); } return references; } private DoubleArray CalculateReferenceEvaluatedSolutionAverages(ItemArray solutions, bool maximization) { DoubleArray references = new DoubleArray(ProblemsParameter.ActualValue.Count); for (int pi = 0; pi < ProblemsParameter.ActualValue.Count; pi++) { if (maximization) references[pi] = solutions.Where(x => x.AverageEvaluatedSolutions != null).Select(x => x.AverageEvaluatedSolutions[pi]).Max(); else references[pi] = solutions.Where(x => x.AverageEvaluatedSolutions != null).Select(x => x.AverageEvaluatedSolutions[pi]).Min(); } return references; } private void NormalizePopulation(ItemArray solutions, ItemArray qualities, DoubleArray referenceQualityAverages, DoubleArray referenceQualityDeviations, DoubleArray referenceEvaluatedSolutionAverages, double qualityAveragesWeight, double qualityDeviationsWeight, double evaluatedSolutionsWeight, bool maximization) { for (int i = 0; i < solutions.Length; i++) { if (solutions[i].AverageQualities == null || solutions[i].QualityStandardDeviations == null || solutions[i].AverageEvaluatedSolutions == null) { // this parameterConfigurationTree has not been evaluated correctly (due to a faulty configuration, which led to an exception) // since we are in generation zero, there is no WorstQuality available for a penalty value double penaltyValue = maximization ? double.MinValue : double.MaxValue; qualities[i].Value = penaltyValue; } else { qualities[i].Value = MetaOptimizationUtil.Normalize(solutions[i], referenceQualityAverages.ToArray(), referenceQualityDeviations.ToArray(), referenceEvaluatedSolutionAverages.ToArray(), qualityAveragesWeight, qualityDeviationsWeight, evaluatedSolutionsWeight, maximization); } } } } }