Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Operators/3.3/DataReducer.cs @ 9813

Last change on this file since 9813 was 9456, checked in by swagner, 12 years ago

Updated copyright year and added some missing license headers (#1889)

File size: 11.3 KB
RevLine 
[7395]1#region License Information
2/* HeuristicLab
[9456]3 * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[7395]4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Parameters;
29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
30
31namespace HeuristicLab.Operators {
32  [Item("DataReducer", "An operator to reduce values of sub scopes.")]
33  [StorableClass]
34  public sealed class DataReducer : SingleSuccessorOperator {
35    #region Parameter Properties
36    public ScopeTreeLookupParameter<IItem> ParameterToReduce {
37      get { return (ScopeTreeLookupParameter<IItem>)Parameters["ParameterToReduce"]; }
38    }
39    public LookupParameter<IItem> TargetParameter {
40      get { return (LookupParameter<IItem>)Parameters["TargetParameter"]; }
41    }
42    public ValueParameter<ReductionOperation> ReductionOperation {
43      get { return (ValueParameter<ReductionOperation>)Parameters["ReductionOperation"]; }
44    }
45    public ValueParameter<ReductionOperation> TargetOperation {
46      get { return (ValueParameter<ReductionOperation>)Parameters["TargetOperation"]; }
47    }
48    #endregion
49
50    [StorableConstructor]
51    private DataReducer(bool deserializing) : base(deserializing) { }
52    private DataReducer(DataReducer original, Cloner cloner)
53      : base(original, cloner) {
54    }
55    public DataReducer()
56      : base() {
57      #region Create parameters
58      Parameters.Add(new ScopeTreeLookupParameter<IItem>("ParameterToReduce", "The parameter on which the reduction operation should be applied."));
59      Parameters.Add(new LookupParameter<IItem>("TargetParameter", "The target variable in which the reduced value should be stored."));
60      Parameters.Add(new ValueParameter<ReductionOperation>("ReductionOperation", "The operation which is applied on the parameters to reduce."));
61      Parameters.Add(new ValueParameter<ReductionOperation>("TargetOperation", "The operation used to apply the reduced value to the target variable."));
62      #endregion
63    }
64
65    public override IDeepCloneable Clone(Cloner cloner) {
66      return new DataReducer(this, cloner);
67    }
68
69    public override IOperation Apply() {
70      var values = ParameterToReduce.ActualValue;
71      if (values.Count() > 0) {
[8252]72        if (values.All(x => typeof(IntValue).IsAssignableFrom(x.GetType()))) {
73          CalculateResult(values.OfType<IntValue>().Select(x => x.Value), values.First().GetType());
74        } else if (values.All(x => typeof(DoubleValue).IsAssignableFrom(x.GetType()))) {
75          CalculateResult(values.OfType<DoubleValue>().Select(x => x.Value), values.First().GetType());
76        } else if (values.All(x => typeof(TimeSpanValue).IsAssignableFrom(x.GetType()))) {
77          CalculateResult(values.OfType<TimeSpanValue>().Select(x => x.Value), values.First().GetType());
[7395]78        } else {
79          throw new ArgumentException(string.Format("Type {0} is not supported by the DataReducer.", values.First().GetType()));
80        }
81      }
82      return base.Apply();
83    }
84
[8252]85    #region integer reduction
86    private void CalculateResult(IEnumerable<int> values, Type targetType) {
87      int result;
[7395]88      switch (ReductionOperation.Value.Value) {
89        case ReductionOperations.Sum:
[8252]90          result = values.Sum();
[7395]91          break;
[8252]92        case ReductionOperations.Product:
93          result = values.Aggregate(1, (x, y) => x * y);
[7395]94          break;
[8252]95        case ReductionOperations.Count:
96          result = values.Count();
[7395]97          break;
98        case ReductionOperations.Min:
[8252]99          result = values.Min();
[7395]100          break;
101        case ReductionOperations.Max:
[8252]102          result = values.Max();
[7395]103          break;
[8252]104        case ReductionOperations.Avg:
105          result = (int)Math.Round(values.Average());
106          break;
107        case ReductionOperations.Assign:
108          result = values.Last();
109          break;
[7395]110        default:
[8256]111          throw new InvalidOperationException(string.Format("Operation {0} is not supported as ReductionOperation for type: {1}.", ReductionOperation.Value.Value, targetType));
[7395]112      }
113
[8252]114      IntValue target;
[7395]115      switch (TargetOperation.Value.Value) {
116        case ReductionOperations.Sum:
[8252]117          target = InitializeTarget<IntValue, int>(targetType, 0);
[7395]118          target.Value += result;
119          break;
[8252]120        case ReductionOperations.Product:
121          target = InitializeTarget<IntValue, int>(targetType, 1);
122          target.Value = target.Value * result;
[7395]123          break;
[8252]124        case ReductionOperations.Min:
125          target = InitializeTarget<IntValue, int>(targetType, int.MaxValue);
126          target.Value = Math.Min(target.Value, result);
127          break;
128        case ReductionOperations.Max:
129          target = InitializeTarget<IntValue, int>(targetType, int.MinValue);
130          target.Value = Math.Max(target.Value, result);
131          break;
132        case ReductionOperations.Avg:
133          target = InitializeTarget<IntValue, int>(targetType, result);
134          target.Value = (int)Math.Round((target.Value + result) / 2.0);
135          break;
136        case ReductionOperations.Assign:
137          target = InitializeTarget<IntValue, int>(targetType, 0);
138          target.Value = result;
139          break;
[7395]140        default:
[8256]141          throw new InvalidOperationException(string.Format("Operation {0} is not supported as TargetOperation for type: {1}.", TargetOperation.Value.Value, targetType));
[7395]142      }
143    }
[8252]144    #endregion
145    #region double reduction
146    private void CalculateResult(IEnumerable<double> values, Type targetType) {
147      double result;
[7395]148      switch (ReductionOperation.Value.Value) {
149        case ReductionOperations.Sum:
[8252]150          result = values.Sum();
[7395]151          break;
[8252]152        case ReductionOperations.Product:
153          result = values.Aggregate(1.0, (x, y) => x * y);
[7395]154          break;
[8252]155        case ReductionOperations.Count:
156          result = values.Count();
[7395]157          break;
158        case ReductionOperations.Min:
[8252]159          result = values.Min();
[7395]160          break;
161        case ReductionOperations.Max:
[8252]162          result = values.Max();
[7395]163          break;
[8252]164        case ReductionOperations.Avg:
165          result = values.Average();
166          break;
167        case ReductionOperations.Assign:
168          result = values.Last();
169          break;
[7395]170        default:
[8256]171          throw new InvalidOperationException(string.Format("Operation {0} is not supported as ReductionOperation for type: {1}.", ReductionOperation.Value.Value, targetType));
[7395]172      }
173
[8252]174      DoubleValue target;
[7395]175      switch (TargetOperation.Value.Value) {
176        case ReductionOperations.Sum:
[8252]177          target = InitializeTarget<DoubleValue, double>(targetType, 0.0);
[7395]178          target.Value += result;
179          break;
[8252]180        case ReductionOperations.Product:
181          target = InitializeTarget<DoubleValue, double>(targetType, 1.0);
182          target.Value = target.Value * result;
[7395]183          break;
[8252]184        case ReductionOperations.Min:
185          target = InitializeTarget<DoubleValue, double>(targetType, double.MaxValue);
186          target.Value = Math.Min(target.Value, result);
187          break;
188        case ReductionOperations.Max:
189          target = InitializeTarget<DoubleValue, double>(targetType, double.MinValue);
190          target.Value = Math.Max(target.Value, result);
191          break;
192        case ReductionOperations.Avg:
193          target = InitializeTarget<DoubleValue, double>(targetType, result);
194          target.Value = (target.Value + result) / 2.0;
195          break;
196        case ReductionOperations.Assign:
197          target = InitializeTarget<DoubleValue, double>(targetType, 0.0);
198          target.Value = result;
199          break;
[7395]200        default:
[8256]201          throw new InvalidOperationException(string.Format("Operation {0} is not supported as TargetOperation for type: {1}.", TargetOperation.Value.Value, targetType));
[7395]202      }
203    }
[8252]204    #endregion
205    #region TimeSpan reduction
206    private void CalculateResult(IEnumerable<TimeSpan> values, Type targetType) {
207      TimeSpan result;
[7395]208      switch (ReductionOperation.Value.Value) {
209        case ReductionOperations.Sum:
[8252]210          result = values.Aggregate(new TimeSpan(), (x, y) => x + y);
[7395]211          break;
212        case ReductionOperations.Min:
[8252]213          result = values.Min();
[7395]214          break;
215        case ReductionOperations.Max:
[8252]216          result = values.Max();
[7395]217          break;
[8252]218        case ReductionOperations.Avg:
219          result = TimeSpan.FromMilliseconds(values.Average(x => x.TotalMilliseconds));
220          break;
221        case ReductionOperations.Assign:
222          result = values.Last();
223          break;
[7395]224        default:
[8256]225          throw new InvalidOperationException(string.Format("Operation {0} is not supported as ReductionOperation for type: {1}.", ReductionOperation.Value.Value, targetType));
[7395]226      }
227
[8252]228      TimeSpanValue target;
[7395]229      switch (TargetOperation.Value.Value) {
[8252]230        case ReductionOperations.Sum:
231          target = InitializeTarget<TimeSpanValue, TimeSpan>(targetType, new TimeSpan());
232          target.Value += result;
233          break;
234        case ReductionOperations.Min:
235          target = InitializeTarget<TimeSpanValue, TimeSpan>(targetType, TimeSpan.MaxValue);
236          target.Value = target.Value < result ? target.Value : result;
237          break;
238        case ReductionOperations.Max:
239          target = InitializeTarget<TimeSpanValue, TimeSpan>(targetType, TimeSpan.MinValue);
240          target.Value = target.Value > result ? target.Value : result;
241          break;
242        case ReductionOperations.Avg:
243          target = InitializeTarget<TimeSpanValue, TimeSpan>(targetType, result);
244          target.Value = TimeSpan.FromMilliseconds((target.Value.TotalMilliseconds + result.TotalMilliseconds) / 2);
245          break;
[7395]246        case ReductionOperations.Assign:
[8252]247          target = InitializeTarget<TimeSpanValue, TimeSpan>(targetType, new TimeSpan());
[7395]248          target.Value = result;
249          break;
250        default:
[8256]251          throw new InvalidOperationException(string.Format("Operation {0} is not supported as TargetOperation for type: {1}.", TargetOperation.Value.Value, targetType));
[7395]252      }
253    }
[8252]254    #endregion
255
256    #region helpers
257    private T1 InitializeTarget<T1, T2>(Type targetType, T2 initialValue)
258      where T1 : ValueTypeValue<T2>
259      where T2 : struct {
260      T1 target = (T1)TargetParameter.ActualValue;
261      if (target == null) {
262        target = (T1)Activator.CreateInstance(targetType);
263        TargetParameter.ActualValue = target;
264        target.Value = initialValue;
265      }
266      return target;
267    }
268    #endregion
[7395]269  }
270}
Note: See TracBrowser for help on using the repository browser.