Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraint.cs @ 17928

Last change on this file since 17928 was 17906, checked in by gkronber, 4 years ago

#3073 bugfixing

File size: 6.3 KB
RevLine 
[17887]1#region License Information
2
3/* HeuristicLab
[17896]4 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[17887]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      private set {
38        if (variable == value)
39          return;
40        variable = value;
[17896]41        OnToStringChanged();
[17887]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;
[17896]59        OnToStringChanged();
[17887]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;
[17896]73        OnToStringChanged();
[17887]74        OnChanged();
75      }
76    }
77
78    [Storable]
79    private IntervalCollection regions;
80    public IntervalCollection Regions {
81      get => regions;
82      set {
83        if (regions != value) {
[17896]84          if (regions != null) regions.Changed -= regions_Changed;
[17887]85          regions = value;
[17896]86          if (regions != null) regions.Changed += regions_Changed;
87          OnToStringChanged();
[17887]88          OnChanged();
89        }
90      }
91    }
92
[17896]93
[17887]94    [Storable]
95    private double weight = 1.0;
96    public double Weight {
97      get => weight;
98      set {
[17900]99        if (weight <= 0.0) throw new ArgumentOutOfRangeException("Weight must be larger than zero.");
[17887]100        if (weight != value) {
101          weight = value;
[17896]102          OnToStringChanged();
[17887]103          OnChanged();
104        }
105      }
106    }
107
108    [StorableConstructor]
109    private ShapeConstraint(StorableConstructorFlag _) : base(_) { }
110
[17896]111    [StorableHook(HookType.AfterDeserialization)]
112    private void AfterDeserialization() {
113      if (regions != null) regions.Changed += regions_Changed;
114    }
115
[17887]116    // without derivation
[17891]117    public ShapeConstraint(Interval interval, double weight)
[17887]118      : this(string.Empty, 0,
[17891]119         interval, new IntervalCollection(), weight) { }
[17887]120
[17891]121    public ShapeConstraint(Interval interval, IntervalCollection regions, double weight)
[17887]122      : this(string.Empty, 0,
[17891]123         interval, regions, weight) { }
[17887]124
125    public ShapeConstraint(string variable, int numberOfDerivations,
[17891]126                              Interval interval, double weight)
[17887]127      : this(variable, numberOfDerivations,
[17891]128             interval, new IntervalCollection(), weight) { }
[17887]129
130    public ShapeConstraint(string variable, int numberOfDerivations,
[17891]131                              Interval interval, IntervalCollection regions, double weight) {
[17896]132      Variable = variable;
133      NumberOfDerivations = numberOfDerivations;
134      Interval = interval;
135      Regions = regions;
136      Weight = weight;
[17887]137    }
138
139    public override IDeepCloneable Clone(Cloner cloner) {
140      return new ShapeConstraint(this, cloner);
141    }
142
143    private ShapeConstraint(ShapeConstraint original, Cloner cloner)
144      : base(original, cloner) {
145      Variable = original.Variable;
146      NumberOfDerivations = original.NumberOfDerivations;
147      Interval = original.Interval;
[17896]148      Regions = cloner.Clone(original.Regions);
149      Weight = original.weight;
[17887]150    }
151
152    public event EventHandler Changed;
153
154    private void OnChanged() {
155      var handlers = Changed;
156      if (handlers != null)
157        handlers(this, EventArgs.Empty);
158    }
159
160
[17896]161    private void regions_Changed(object sender, EventArgs e) {
162      OnToStringChanged();
163      OnChanged();
164    }
[17887]165
166    public override string ToString() {
167      return GenerateExpressionString();
168    }
169
170
171    private string GenerateExpressionString() {
172      string expression;
[17906]173      string write(double val) => double.IsPositiveInfinity(val) ? "inf." : double.IsNegativeInfinity(val) ? "-inf." : $"{val}";
[17887]174      if (!IsDerivative) {
[17906]175        expression = string.Format($"f in [{write(Interval.LowerBound)} .. {write(Interval.UpperBound)}]");
[17887]176        if (Regions != null) {
177          foreach (var region in Regions.GetReadonlyDictionary())
[17906]178            expression += $", {region.Key} in [{write(region.Value.LowerBound)} .. {write(region.Value.UpperBound)}]";
[17887]179        }
[17891]180        if (Weight != 1.0) {
181          expression += $" weight: {weight}";
182        }
[17887]183
184        return expression;
185      }
186
187      var derivationString = string.Empty;
188      switch (numberOfDerivations) {
189        case 1:
190          derivationString = ""; break;
191        case 2:
192          derivationString = "²"; break;
193        case 3:
194          derivationString = "³"; break;
195      }
[17906]196      expression = string.Format($"∂{derivationString}f/∂{Variable}{derivationString} in [{write(Interval.LowerBound)} .. {write(Interval.UpperBound)}]");
[17887]197      if (Regions != null) {
198        foreach (var region in Regions.GetReadonlyDictionary())
[17906]199          expression += $", {region.Key} in [{write(region.Value.LowerBound)} .. {write(region.Value.UpperBound)}]";
[17887]200      }
[17896]201      if (Weight != 1.0) {
[17891]202        expression += $" weight: {weight}";
203      }
[17887]204      return expression;
205    }
206  }
207}
Note: See TracBrowser for help on using the repository browser.