source: branches/2906_Transformations/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/RescaleTransformation.cs @ 15938

Last change on this file since 15938 was 15938, checked in by pfleck, 14 months ago

#2906

  • added Offset to log transformation
  • renamed parameter of linear transformation
  • added RescaleTransformation
File size: 5.7 KB
Line 
1// #region License Information
2// /* HeuristicLab
3//  * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
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.Problems.DataAnalysis {
32  [Item("Rescale", "Rescale the data to a given range (e.g. [0-1]).")]
33  [StorableClass]
34  public class RescaleTransformation : Transformation<double> {
35
36    #region Parameters
37    private IFixedValueParameter<DoubleRange> TargetRangeParameter {
38      get { return (IFixedValueParameter<DoubleRange>)Parameters["Target Range"]; }
39    }
40    private IFixedValueParameter<DoubleRange> OriginalRangeParameter {
41      get { return (IFixedValueParameter<DoubleRange>)Parameters["Original Range"]; }
42    }
43    #endregion
44
45    #region Properties
46    public double TargetMin {
47      get { return TargetRangeParameter.Value.Start; }
48      set { TargetRangeParameter.Value.Start = value; }
49    }
50    public double TargetMax {
51      get { return TargetRangeParameter.Value.End; }
52      set { TargetRangeParameter.Value.End = value; }
53    }
54    public double OriginalMin {
55      get { return OriginalRangeParameter.Value.Start; }
56      private set { OriginalRangeParameter.Value.Start = value; }
57    }
58    public double OriginalMax {
59      get { return OriginalRangeParameter.Value.End; }
60      private set { OriginalRangeParameter.Value.End = value; }
61    }
62    #endregion
63
64    #region Constructor, Cloning & Persistence
65    public RescaleTransformation()
66      : base() {
67      Parameters.Add(new FixedValueParameter<DoubleRange>("Target Range", new DoubleRange(0.0, 1.0)));
68      Parameters.Add(new FixedValueParameter<DoubleRange>("Original Range", new DoubleRange(double.NaN, double.NaN)) { Hidden = true });
69    }
70
71    protected RescaleTransformation(RescaleTransformation original, Cloner cloner)
72      : base(original, cloner) {
73    }
74    public override IDeepCloneable Clone(Cloner cloner) {
75      return new RescaleTransformation(this, cloner);
76    }
77
78    [StorableConstructor]
79    protected RescaleTransformation(bool deserializing)
80      : base(deserializing) {
81    }
82    #endregion
83
84    public override bool Check(IEnumerable<double> data, out string errorMessage) {
85      if (data.StandardDeviationPop().IsAlmost(0.0)) {
86        errorMessage = "Rescaling cannot be applied for data with a standard deviation of zero.";
87        return false;
88      }
89      return base.Check(data, out errorMessage);
90    }
91
92    public override void Configure(IEnumerable<double> data) {
93      Configure(data, out double originalMin, out double originalMax);
94      OriginalMin = originalMin;
95      OriginalMax = originalMax;
96      base.Configure(data);
97    }
98
99    public override IEnumerable<double> Apply(IEnumerable<double> data) {
100      if (double.IsNaN(OriginalMin) || double.IsNaN(OriginalMax))
101        throw new InvalidOperationException("Transformation is not configured");
102
103      return Apply(data, TargetMin, TargetMax, OriginalMin, OriginalMax);
104    }
105
106    public override IEnumerable<double> InverseApply(IEnumerable<double> data) {
107      if (double.IsNaN(OriginalMin) || double.IsNaN(OriginalMax))
108        throw new InvalidOperationException("Transformation is not configured");
109
110      return InverseApply(data, TargetMin, TargetMax, OriginalMin, OriginalMax);
111    }
112
113
114    public static void Configure(IEnumerable<double> data, out double originalMin, out double originalMax) {
115      originalMin = data.Min();
116      originalMax = data.Max();
117    }
118
119    public static IEnumerable<double> Apply(IEnumerable<double> data, double targetMin, double targetMax, double originalMin = double.NaN, double originalMax = double.NaN) {
120      if (double.IsNaN(originalMin)) originalMin = data.Min();
121      if (double.IsNaN(originalMax)) originalMax = data.Max();
122
123      GetLinearTransformationParameters(targetMin, targetMax, originalMin, originalMax, out double scale, out double offset);
124
125      return LinearTransformation.Apply(data, scale, offset);
126    }
127
128    public static IEnumerable<double> InverseApply(IEnumerable<double> data, double targetMin, double targetMax, double originalMin, double originalMax) {
129      GetLinearTransformationParameters(targetMin, targetMax, originalMin, originalMax, out double scale, out double offset);
130
131      return LinearTransformation.InverseApply(data, scale, offset);
132    }
133
134    private static void GetLinearTransformationParameters(double targetMin, double targetMax, double originalMin, double originalMax,
135        out double scale, out double offset) {
136      var originalRange = originalMax - originalMin;
137      var targetRange = targetMax - targetMin;
138
139      scale = targetRange / originalRange;
140      offset = targetMin - originalMin * scale;
141    }
142  }
143}
Note: See TracBrowser for help on using the repository browser.