Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3119_AdditionalShapeConstraintFeatures/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraint.cs

Last change on this file was 17995, checked in by dpiringe, 4 years ago

#3119

  • added additional parameters to enable different evaluation options
  • added additive restrictions
  • added additional implementations for dynamic restrictions:
    • dynamic intervalls
    • exponatial smoothing
    • rising multiplier
  • adapted IntervalUtil to get model bounds and refactored some sections
  • adapted ShapeConstraintsParser for added features
  • added a ResultCollection in SymbolicRegressionSolution for shape constraint violations
File size: 8.0 KB
Line 
1#region License Information
2
3/* HeuristicLab
4 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
5 *
6 * This file is part of HeuristicLab.
7 *
8 * HeuristicLab is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * HeuristicLab is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#endregion
23using System;
24using HEAL.Attic;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27
28namespace HeuristicLab.Problems.DataAnalysis {
29  [StorableType("8109BE58-CCFB-4462-A2F4-EEE5DFADAFF7")]
30  [Item("ShapeConstraint", "Constraint on the shape of a function e.g. monotonicity.")]
31  public sealed class ShapeConstraint : Item {
32    [Storable]
33    private string variable;
34
35    public string Variable {
36      get => variable;
37      set {
38        if (variable == value)
39          return;
40        variable = value;
41        OnToStringChanged();
42        OnChanged();
43      }
44    }
45
46    public bool IsDerivative => NumberOfDerivations > 0;
47
48    [Storable]
49    private int numberOfDerivations;
50
51    public int NumberOfDerivations {
52      get => numberOfDerivations;
53      set {
54        if (value < 0 || value > 3)
55          throw new ArgumentException("Number of derivation has to be between 0 - 3.");
56        if (numberOfDerivations == value)
57          return;
58        numberOfDerivations = value;
59        OnToStringChanged();
60        OnChanged();
61      }
62    }
63
64    [Storable]
65    private Interval interval;
66
67    public Interval Interval {
68      get => interval;
69      set {
70        if (interval == value)
71          return;
72        interval = value;
73        OnToStringChanged();
74        OnChanged();
75      }
76    }
77
78    [Storable]
79    private IntervalCollection regions;
80    public IntervalCollection Regions {
81      get => regions;
82      set {
83        if (regions != value) {
84          if (regions != null) regions.Changed -= regions_Changed;
85          regions = value;
86          if (regions != null) regions.Changed += regions_Changed;
87          OnToStringChanged();
88          OnChanged();
89        }
90      }
91    }
92
93
94    [Storable]
95    private double weight = 1.0;
96    public double Weight {
97      get => weight;
98      set {
99        if (weight <= 0.0) throw new ArgumentOutOfRangeException("Weight must be larger than zero.");
100        if (weight != value) {
101          weight = value;
102          OnToStringChanged();
103          OnChanged();
104        }
105      }
106    }
107
108    [Storable]
109    private Interval threshold = new Interval(0, 0);
110    public Interval Threshold {
111      get => threshold;
112      set {
113        if (threshold == value)
114          return;
115        threshold = value;
116        OnToStringChanged();
117        OnChanged();
118      }
119    }
120
121
122    [Storable]
123    private Interval targetInterval;
124    public Interval TargetInterval {
125      get => targetInterval;
126      set {
127        if (targetInterval == value)
128          return;
129        targetInterval = value;
130        OnToStringChanged();
131        OnChanged();
132      }
133    }
134
135    [Storable]
136    private Interval dynInterval = new Interval(double.NegativeInfinity, double.PositiveInfinity);
137    public Interval DynInterval {
138      get => dynInterval;
139      set {
140        if (dynInterval == value)
141          return;
142        dynInterval = value;
143        OnToStringChanged();
144        OnChanged();
145      }
146    }
147
148    [StorableConstructor]
149    private ShapeConstraint(StorableConstructorFlag _) : base(_) { }
150
151    [StorableHook(HookType.AfterDeserialization)]
152    private void AfterDeserialization() {
153      if (regions != null) regions.Changed += regions_Changed;
154      if (TargetInterval == null)
155        TargetInterval = new Interval(interval.LowerBound, interval.UpperBound);
156    }
157
158    // without derivation
159    public ShapeConstraint(Interval interval, double weight, Interval threshold, Interval dynInterval)
160      : this(string.Empty, 0,
161         interval, new IntervalCollection(), weight, threshold, dynInterval) { }
162
163    public ShapeConstraint(Interval interval, IntervalCollection regions, double weight, Interval threshold, Interval dynInterval)
164      : this(string.Empty, 0,
165         interval, regions, weight, threshold, dynInterval) { }
166
167    public ShapeConstraint(string variable, int numberOfDerivations,
168                              Interval interval, double weight, Interval threshold, Interval dynInterval)
169      : this(variable, numberOfDerivations,
170             interval, new IntervalCollection(), weight, threshold, dynInterval) { }
171
172    public ShapeConstraint(string variable, int numberOfDerivations,
173                              Interval interval, IntervalCollection regions, double weight, Interval threshold, Interval dynInterval) {
174      Variable = variable;
175      NumberOfDerivations = numberOfDerivations;
176      Interval = interval;
177      Regions = regions;
178      Weight = weight;
179      Threshold = threshold;
180      DynInterval = dynInterval;
181      TargetInterval = new Interval(interval.LowerBound, interval.UpperBound);
182    }
183
184    public override IDeepCloneable Clone(Cloner cloner) {
185      return new ShapeConstraint(this, cloner);
186    }
187
188    private ShapeConstraint(ShapeConstraint original, Cloner cloner)
189      : base(original, cloner) {
190      Variable = original.Variable;
191      NumberOfDerivations = original.NumberOfDerivations;
192      Interval = original.Interval;
193      Regions = cloner.Clone(original.Regions);
194      Weight = original.weight;
195      Threshold = original.Threshold;
196      DynInterval = original.DynInterval;
197      TargetInterval = original.TargetInterval;
198    }
199
200    public event EventHandler Changed;
201
202    private void OnChanged() {
203      var handlers = Changed;
204      if (handlers != null)
205        handlers(this, EventArgs.Empty);
206    }
207
208
209    private void regions_Changed(object sender, EventArgs e) {
210      OnToStringChanged();
211      OnChanged();
212    }
213
214    public override string ToString() {
215      return GenerateExpressionString();
216    }
217
218
219    private string GenerateExpressionString() {
220      string expression;
221      string write(double val) => double.IsPositiveInfinity(val) ? "inf." : double.IsNegativeInfinity(val) ? "-inf." : $"{val}";
222      if (!IsDerivative) {
223        expression = string.Format($"f in [{write(TargetInterval.LowerBound)} .. {write(TargetInterval.UpperBound)}]");
224      } else {
225        var derivationString = string.Empty;
226        switch (numberOfDerivations) {
227          case 1:
228            derivationString = ""; break;
229          case 2:
230            derivationString = "²"; break;
231          case 3:
232            derivationString = "³"; break;
233        }
234        expression = string.Format($"∂{derivationString}f/∂{Variable}{derivationString} in [{write(TargetInterval.LowerBound)} .. {write(TargetInterval.UpperBound)}]");
235      }
236
237      if (Regions != null) {
238        foreach (var region in Regions.GetReadonlyDictionary())
239          expression += $", {region.Key} in [{write(region.Value.LowerBound)} .. {write(region.Value.UpperBound)}]";
240      }
241      if (Weight != 1.0) {
242        expression += $" weight: {weight}";
243      }
244
245      if (!double.IsNegativeInfinity(Threshold.LowerBound) || !double.IsPositiveInfinity(Threshold.UpperBound))
246        expression += $" threshold in [{write(Threshold.LowerBound)} .. {write(Threshold.UpperBound)}]";
247
248      if (!double.IsNegativeInfinity(DynInterval.LowerBound) && !double.IsPositiveInfinity(DynInterval.UpperBound))
249        expression += $" start in [{write(DynInterval.LowerBound)} .. {write(DynInterval.UpperBound)}]";
250
251      return expression;
252    }
253  }
254}
Note: See TracBrowser for help on using the repository browser.