source: branches/3073_IA_constraint_splitting_reintegration/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/ShapeConstraint.cs @ 17896

Last change on this file since 17896 was 17896, checked in by gkronber, 17 months ago

#3073: refactoring to prepare for trunk integration

File size: 6.1 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 != value) {
100          weight = value;
101          OnToStringChanged();
102          OnChanged();
103        }
104      }
105    }
106
107    [StorableConstructor]
108    private ShapeConstraint(StorableConstructorFlag _) : base(_) { }
109
110    [StorableHook(HookType.AfterDeserialization)]
111    private void AfterDeserialization() {
112      if (regions != null) regions.Changed += regions_Changed;
113    }
114
115    // without derivation
116    public ShapeConstraint(Interval interval, double weight)
117      : this(string.Empty, 0,
118         interval, new IntervalCollection(), weight) { }
119
120    public ShapeConstraint(Interval interval, IntervalCollection regions, double weight)
121      : this(string.Empty, 0,
122         interval, regions, weight) { }
123
124    public ShapeConstraint(string variable, int numberOfDerivations,
125                              Interval interval, double weight)
126      : this(variable, numberOfDerivations,
127             interval, new IntervalCollection(), weight) { }
128
129    public ShapeConstraint(string variable, int numberOfDerivations,
130                              Interval interval, IntervalCollection regions, double weight) {
131      Variable = variable;
132      NumberOfDerivations = numberOfDerivations;
133      Interval = interval;
134      Regions = regions;
135      Weight = weight;
136    }
137
138    public override IDeepCloneable Clone(Cloner cloner) {
139      return new ShapeConstraint(this, cloner);
140    }
141
142    private ShapeConstraint(ShapeConstraint original, Cloner cloner)
143      : base(original, cloner) {
144      Variable = original.Variable;
145      NumberOfDerivations = original.NumberOfDerivations;
146      Interval = original.Interval;
147      Regions = cloner.Clone(original.Regions);
148      Weight = original.weight;
149    }
150
151    public event EventHandler Changed;
152
153    private void OnChanged() {
154      var handlers = Changed;
155      if (handlers != null)
156        handlers(this, EventArgs.Empty);
157    }
158
159
160    private void regions_Changed(object sender, EventArgs e) {
161      OnToStringChanged();
162      OnChanged();
163    }
164
165    public override string ToString() {
166      return GenerateExpressionString();
167    }
168
169
170    private string GenerateExpressionString() {
171      string expression;
172
173      if (!IsDerivative) {
174        expression = string.Format($"f in [{Interval?.LowerBound} .. {Interval?.UpperBound}]");
175        if (Regions != null) {
176          foreach (var region in Regions.GetReadonlyDictionary())
177            expression += $", {region.Key} in [{region.Value.LowerBound} .. {region.Value.UpperBound}]";
178        }
179        if (Weight != 1.0) {
180          expression += $" weight: {weight}";
181        }
182
183        return expression;
184      }
185
186      var derivationString = string.Empty;
187      switch (numberOfDerivations) {
188        case 1:
189          derivationString = ""; break;
190        case 2:
191          derivationString = "²"; break;
192        case 3:
193          derivationString = "³"; break;
194      }
195      expression = string.Format($"∂{derivationString}f/∂{Variable}{derivationString} in [{Interval?.LowerBound} .. {Interval?.UpperBound}]");
196      if (Regions != null) {
197        foreach (var region in Regions.GetReadonlyDictionary())
198          expression += $", {region.Key} in [{region.Value.LowerBound} .. {region.Value.UpperBound}]";
199      }
200      if (Weight != 1.0) {
201        expression += $" weight: {weight}";
202      }
203      return expression;
204    }
205  }
206}
Note: See TracBrowser for help on using the repository browser.