Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3105_PythonFormatter/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraint.cs @ 17918

Last change on this file since 17918 was 17918, checked in by mkommend, 3 years ago

#3105: Merge trunk changes into branch.

File size: 6.3 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      private 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    [StorableConstructor]
109    private ShapeConstraint(StorableConstructorFlag _) : base(_) { }
110
111    [StorableHook(HookType.AfterDeserialization)]
112    private void AfterDeserialization() {
113      if (regions != null) regions.Changed += regions_Changed;
114    }
115
116    // without derivation
117    public ShapeConstraint(Interval interval, double weight)
118      : this(string.Empty, 0,
119         interval, new IntervalCollection(), weight) { }
120
121    public ShapeConstraint(Interval interval, IntervalCollection regions, double weight)
122      : this(string.Empty, 0,
123         interval, regions, weight) { }
124
125    public ShapeConstraint(string variable, int numberOfDerivations,
126                              Interval interval, double weight)
127      : this(variable, numberOfDerivations,
128             interval, new IntervalCollection(), weight) { }
129
130    public ShapeConstraint(string variable, int numberOfDerivations,
131                              Interval interval, IntervalCollection regions, double weight) {
132      Variable = variable;
133      NumberOfDerivations = numberOfDerivations;
134      Interval = interval;
135      Regions = regions;
136      Weight = weight;
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;
148      Regions = cloner.Clone(original.Regions);
149      Weight = original.weight;
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
161    private void regions_Changed(object sender, EventArgs e) {
162      OnToStringChanged();
163      OnChanged();
164    }
165
166    public override string ToString() {
167      return GenerateExpressionString();
168    }
169
170
171    private string GenerateExpressionString() {
172      string expression;
173      string write(double val) => double.IsPositiveInfinity(val) ? "inf." : double.IsNegativeInfinity(val) ? "-inf." : $"{val}";
174      if (!IsDerivative) {
175        expression = string.Format($"f in [{write(Interval.LowerBound)} .. {write(Interval.UpperBound)}]");
176        if (Regions != null) {
177          foreach (var region in Regions.GetReadonlyDictionary())
178            expression += $", {region.Key} in [{write(region.Value.LowerBound)} .. {write(region.Value.UpperBound)}]";
179        }
180        if (Weight != 1.0) {
181          expression += $" weight: {weight}";
182        }
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      }
196      expression = string.Format($"∂{derivationString}f/∂{Variable}{derivationString} in [{write(Interval.LowerBound)} .. {write(Interval.UpperBound)}]");
197      if (Regions != null) {
198        foreach (var region in Regions.GetReadonlyDictionary())
199          expression += $", {region.Key} in [{write(region.Value.LowerBound)} .. {write(region.Value.UpperBound)}]";
200      }
201      if (Weight != 1.0) {
202        expression += $" weight: {weight}";
203      }
204      return expression;
205    }
206  }
207}
Note: See TracBrowser for help on using the repository browser.