Changeset 13744 for branches/PerformanceComparison/HeuristicLab.Analysis/3.3/BestNScopesSolutionAnalyzer.cs
- Timestamp:
- 04/07/16 14:13:41 (9 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/PerformanceComparison/HeuristicLab.Analysis/3.3/BestNScopesSolutionAnalyzer.cs
r13739 r13744 20 20 #endregion 21 21 22 using System;23 using System.Collections.Generic;24 using System.Linq;25 22 using HeuristicLab.Common; 26 23 using HeuristicLab.Core; … … 28 25 using HeuristicLab.Operators; 29 26 using HeuristicLab.Optimization; 27 using HeuristicLab.Optimization.Operators; 30 28 using HeuristicLab.Parameters; 31 29 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; 30 using System; 31 using System.Collections.Generic; 32 using System.Linq; 32 33 33 34 namespace HeuristicLab.Analysis { … … 35 36 /// An operator that extracts (clones) the scope containing the best quality. 36 37 /// </summary> 37 [Item("Best ScopeSolutionAnalyzer", "An operator that extracts the scope containing the best quality.")]38 [Item("BestNScopesSolutionAnalyzer", "An operator that maintains at most N scopes containing good quality solutions.")] 38 39 [StorableClass] 39 public class Best ScopeSolutionAnalyzer : SingleSuccessorOperator, IAnalyzer, ISingleObjectiveOperator {40 public class BestNScopesSolutionAnalyzer : SingleSuccessorOperator, IAnalyzer, ISingleObjectiveOperator { 40 41 41 42 public virtual bool EnabledByDefault { … … 48 49 get { return (ScopeTreeLookupParameter<DoubleValue>)Parameters["Quality"]; } 49 50 } 50 public IFixedValueParameter<StringValue> BestSolutionResultNameParameter { 51 get { return (IFixedValueParameter<StringValue>)Parameters["BestSolution ResultName"]; } 52 } 53 public ILookupParameter<DoubleValue> BestKnownQualityParameter { 54 get { return (ILookupParameter<DoubleValue>)Parameters["BestKnownQuality"]; } 51 public IFixedValueParameter<StringValue> BestSolutionsResultNameParameter { 52 get { return (IFixedValueParameter<StringValue>)Parameters["BestSolutions ResultName"]; } 55 53 } 56 54 public IValueLookupParameter<ResultCollection> ResultsParameter { 57 55 get { return (IValueLookupParameter<ResultCollection>)Parameters["Results"]; } 58 56 } 57 public IValueParameter<ISolutionSimilarityCalculator> SimilarityCalculatorParameter { 58 get { return (IValueParameter<ISolutionSimilarityCalculator>)Parameters["SimilarityCalculator"]; } 59 } 60 private IFixedValueParameter<IntValue> NParameter { 61 get { return (IFixedValueParameter<IntValue>)Parameters["N"]; } 62 } 63 private IFixedValueParameter<DoubleValue> MaximumSimilarityParameter { 64 get { return (IFixedValueParameter<DoubleValue>)Parameters["MaximumSimilarity"]; } 65 } 59 66 60 public string BestSolutionResultName { 61 get { return BestSolutionResultNameParameter.Value.Value; } 62 set { BestSolutionResultNameParameter.Value.Value = value; } 67 public string BestSolutionsResultName { 68 get { return BestSolutionsResultNameParameter.Value.Value; } 69 set { BestSolutionsResultNameParameter.Value.Value = value; } 70 } 71 72 public int N { 73 get { return NParameter.Value.Value; } 74 set { NParameter.Value.Value = value; } 75 } 76 77 public double MaximumSimilarity { 78 get { return MaximumSimilarityParameter.Value.Value; } 79 set { MaximumSimilarityParameter.Value.Value = value; } 63 80 } 64 81 65 82 #region Storing & Cloning 66 83 [StorableConstructor] 67 protected Best ScopeSolutionAnalyzer(bool deserializing) : base(deserializing) { }68 protected Best ScopeSolutionAnalyzer(BestScopeSolutionAnalyzer original, Cloner cloner) : base(original, cloner) { }84 protected BestNScopesSolutionAnalyzer(bool deserializing) : base(deserializing) { } 85 protected BestNScopesSolutionAnalyzer(BestNScopesSolutionAnalyzer original, Cloner cloner) : base(original, cloner) { } 69 86 public override IDeepCloneable Clone(Cloner cloner) { 70 return new BestScopeSolutionAnalyzer(this, cloner); 71 } 72 73 [StorableHook(HookType.AfterDeserialization)] 74 private void AfterDeserialization() { 75 // BackwardsCompatibility3.3 76 #region Backwards compatible code, remove with 3.4 77 if (!Parameters.ContainsKey("BestSolution ResultName")) 78 Parameters.Add(new FixedValueParameter<StringValue>("BestSolution ResultName", "The name of the result for storing the best solution.", new StringValue("Best Solution"))); 79 if (Parameters.ContainsKey("BestSolution")) Parameters.Remove("BestSolution"); 80 if (Parameters.ContainsKey("BestKnownSolution")) Parameters.Remove("BestKnownSolution"); 81 #endregion 87 return new BestNScopesSolutionAnalyzer(this, cloner); 82 88 } 83 89 #endregion 84 public Best ScopeSolutionAnalyzer()90 public BestNScopesSolutionAnalyzer() 85 91 : base() { 86 92 Parameters.Add(new LookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem.")); 87 93 Parameters.Add(new ScopeTreeLookupParameter<DoubleValue>("Quality", "The qualities of the solutions.")); 88 Parameters.Add(new FixedValueParameter<StringValue>("BestSolution ResultName", "The name of the result for storing the best solution.", new StringValue("Best Solution"))); 89 Parameters.Add(new LookupParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution.")); 94 Parameters.Add(new FixedValueParameter<StringValue>("BestSolutions ResultName", "The name of the result for storing the best solution.", new StringValue("Best Solutions"))); 90 95 Parameters.Add(new ValueLookupParameter<ResultCollection>("Results", "The result collection where the solution should be stored.")); 96 Parameters.Add(new ValueParameter<ISolutionSimilarityCalculator>("SimilarityCalculator", "The solution similarity calculator that is used to compare two solution scopes.", new QualitySimilarityCalculator())); 97 Parameters.Add(new FixedValueParameter<IntValue>("N", "The N best solutions that are kept.", new IntValue(10))); 98 Parameters.Add(new FixedValueParameter<DoubleValue>("MaximumSimilarity", "The maximum similarity between two solutions in order to be remembered in the list.", new DoubleValue(0.8))); 91 99 } 92 100 93 101 public override IOperation Apply() { 94 ItemArray<DoubleValue> qualities = QualityParameter.ActualValue; 95 ResultCollection results = ResultsParameter.ActualValue; 96 bool max = MaximizationParameter.ActualValue.Value; 97 DoubleValue bestKnownQuality = BestKnownQualityParameter.ActualValue; 98 99 if (results.ContainsKey(BestSolutionResultName) && !typeof(IScope).IsAssignableFrom(results[BestSolutionResultName].DataType)) { 100 throw new InvalidOperationException(string.Format("Could not add best solution result, because there is already a result with the name \"{0}\" present in the result collection.", BestSolutionResultName)); 102 var results = ResultsParameter.ActualValue; 103 if (results.ContainsKey(BestSolutionsResultName) && !typeof(ScopeList).IsAssignableFrom(results[BestSolutionsResultName].DataType)) { 104 throw new InvalidOperationException(string.Format("Could not add best solutions result, because there is already a result with the name \"{0}\" present in the result collection.", BestSolutionsResultName)); 105 } 106 ScopeList bestScopes = null; 107 if (results.ContainsKey(BestSolutionsResultName)) { 108 bestScopes = (ScopeList)results[BestSolutionsResultName].Value; 109 } else { 110 bestScopes = new ScopeList(); 111 results.Add(new Result(BestSolutionsResultName, bestScopes)); 101 112 } 102 113 103 int i = -1; 104 if (!max) 105 i = qualities.Select((x, index) => new { index, x.Value }).OrderBy(x => x.Value).First().index; 106 else i = qualities.Select((x, index) => new { index, x.Value }).OrderByDescending(x => x.Value).First().index; 114 var max = MaximizationParameter.ActualValue.Value; 115 var simCalc = SimilarityCalculatorParameter.Value; 116 var maxSim = MaximumSimilarity; 117 var qualityName = QualityParameter.TranslatedName; 118 var depth = QualityParameter.Depth; 107 119 108 IEnumerable<IScope> scopes = new IScope[] { ExecutionContext.Scope };109 for ( int j = 0; j < QualityParameter.Depth; j++)120 IEnumerable<IScope> scopes = new [] { ExecutionContext.Scope }; 121 for (var j = 0; j < depth; j++) 110 122 scopes = scopes.SelectMany(x => x.SubScopes); 111 IScope currentBestScope = scopes.ToList()[i];112 123 113 if (bestKnownQuality == null || 114 max && qualities[i].Value > bestKnownQuality.Value 115 || !max && qualities[i].Value < bestKnownQuality.Value) { 116 BestKnownQualityParameter.ActualValue = new DoubleValue(qualities[i].Value); 124 scopes = max ? scopes.OrderByDescending(x => ((DoubleValue)x.Variables[qualityName].Value).Value) 125 : scopes.OrderBy(x => ((DoubleValue)x.Variables[qualityName].Value).Value); 126 127 var newList = new ScopeList(bestScopes.Take(N)); 128 var cloner = new Cloner(); 129 // avoid cloning the results collection that the solution is put in 130 cloner.RegisterClonedObject(results, new ResultCollection()); 131 132 foreach (var s in scopes) { 133 bool isDiverse = true, isBetterThanWorst = false, isIdentical = false; 134 var worstIdx = -1; 135 IScope worst = null; 136 var idx = 0; 137 foreach (var a in newList) { 138 if (IsBetter(s, a, qualityName, max)) { 139 isBetterThanWorst = true; 140 if (worst == null || IsBetter(worst, a, qualityName, max)) { 141 worst = a; 142 worstIdx = idx; 143 } 144 } 145 var similarity = simCalc.CalculateSolutionSimilarity(s, a); 146 if (similarity.IsAlmost(1.0)) isIdentical = true; 147 if (similarity > maxSim) isDiverse = false; 148 idx++; 149 150 if (isIdentical || (newList.Count >= N && !isDiverse)) break; 151 } 152 // to accept a new solution it needs to be 153 // A) not identical 154 // B) must be less similar than a certain value 155 // C) must be better than at least one solution already accepted 156 // The exception to B) and C) is when the list is not full yet 157 if (isIdentical || (newList.Count >= N && !(isDiverse && isBetterThanWorst))) continue; 158 // avoid cloning subscopes of the solution 159 cloner.RegisterClonedObject(s.SubScopes, new ScopeList()); 160 newList.Add(cloner.Clone(s)); 161 if (newList.Count > N) newList.RemoveAt(worstIdx); 117 162 } 118 163 119 if (!results.ContainsKey(BestSolutionResultName)) { 120 var cloner = new Cloner(); 121 //avoid cloning of subscopes and the results collection that the solution is put in 122 cloner.RegisterClonedObject(results, new ResultCollection()); 123 cloner.RegisterClonedObject(currentBestScope.SubScopes, new ScopeList()); 124 var solution = cloner.Clone(currentBestScope); 164 bestScopes.Replace(newList); 125 165 126 results.Add(new Result(BestSolutionResultName, solution)); 127 } else { 128 var bestSolution = (IScope)results[BestSolutionResultName].Value; 129 string qualityName = QualityParameter.TranslatedName; 130 if (bestSolution.Variables.ContainsKey(qualityName)) { 131 double bestQuality = ((DoubleValue)bestSolution.Variables[qualityName].Value).Value; 132 if (max && qualities[i].Value > bestQuality 133 || !max && qualities[i].Value < bestQuality) { 134 var cloner = new Cloner(); 135 //avoid cloning of subscopes and the results collection that the solution is put in 136 cloner.RegisterClonedObject(results, new ResultCollection()); 137 cloner.RegisterClonedObject(currentBestScope.SubScopes, new ScopeList()); 138 var solution = cloner.Clone(currentBestScope); 166 return base.Apply(); 167 } 139 168 140 results[BestSolutionResultName].Value = solution; 141 } 142 } 143 } 144 return base.Apply(); 169 private static bool IsBetter(IScope a, IScope b, string qualityName, bool max) { 170 return max ? ((DoubleValue)a.Variables[qualityName].Value).Value > ((DoubleValue)b.Variables[qualityName].Value).Value 171 : ((DoubleValue)a.Variables[qualityName].Value).Value < ((DoubleValue)b.Variables[qualityName].Value).Value; 145 172 } 146 173 }
Note: See TracChangeset
for help on using the changeset viewer.