#region License Information
/* HeuristicLab
* Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using HEAL.Attic;
using HeuristicLab.Common;
using HeuristicLab.Core;
namespace HeuristicLab.Problems.DataAnalysis {
[StorableType("8109BE58-CCFB-4462-A2F4-EEE5DFADAFF7")]
[Item("Interval Constraint", "Constraint on intervals.")]
public sealed class IntervalConstraint : Item {
[Storable] private string expression;
public string Expression {
get => expression;
private set {
if (expression == value)
return;
expression = value;
OnChanged();
OnToStringChanged();
}
}
public string Definition => GetDefinitionString();
[Storable] private string variable;
public string Variable {
get => variable;
private set {
if (variable == value)
return;
variable = value;
UpdateExpression();
OnChanged();
}
}
[Storable] private string target;
public string Target {
get => target;
private set {
if (target == value)
return;
target = value;
UpdateExpression();
OnChanged();
}
}
public bool IsDerivative => NumberOfDerivations > 0;
[Storable] private int numberOfDerivations;
public int NumberOfDerivations {
get => numberOfDerivations;
set {
if (value < 0 || value > 3)
throw new ArgumentException("Number of derivation has to be between 0 - 3.");
if (numberOfDerivations == value)
return;
numberOfDerivations = value;
UpdateExpression();
OnChanged();
}
}
[Storable] private Interval interval;
public Interval Interval {
get => interval;
set {
if (interval == value)
return;
interval = value;
UpdateExpression();
OnChanged();
}
}
[Storable] private bool enabled;
public bool Enabled {
get => enabled;
set {
if (enabled == value)
return;
enabled = value;
OnChanged();
}
}
[Storable] private IEnumerable regions;
public IEnumerable Regions {
get => regions;
set {
if (regions != value) {
regions = value;
UpdateExpression();
OnChanged();
}
}
}
[Storable]
private double weight = 1.0;
public double Weight {
get => weight;
set {
if (weight != value) {
weight = value;
UpdateExpression();
OnChanged();
}
}
}
[StorableConstructor]
private IntervalConstraint(StorableConstructorFlag _) : base(_) { }
public IntervalConstraint(string expression, string variable, string target, int numberOfDerivations,
Interval interval, double weight, bool enabled)
: this(expression, variable, target, numberOfDerivations,
interval, Enumerable.Empty(), weight, enabled) { }
public IntervalConstraint(string expression, string variable, string target, int numberOfDerivations,
Interval interval, IEnumerable regions, double weight, bool enabled) {
this.regions = regions;
this.weight = weight;
this.expression = expression;
this.variable = variable;
this.target = target;
this.numberOfDerivations = numberOfDerivations;
this.interval = interval;
this.enabled = enabled;
}
public override IDeepCloneable Clone(Cloner cloner) {
return new IntervalConstraint(this, cloner);
}
private IntervalConstraint(IntervalConstraint original, Cloner cloner)
: base(original, cloner) {
Regions = new List(original.Regions?.Select(r => cloner.Clone(r)) ?? Enumerable.Empty());
Expression = original.Expression;
Variable = original.Variable;
Target = original.Target;
NumberOfDerivations = original.NumberOfDerivations;
Interval = original.Interval;
Enabled = original.Enabled;
}
public event EventHandler Changed;
private void OnChanged() {
var handlers = Changed;
if (handlers != null)
handlers(this, EventArgs.Empty);
}
private static string GetDerivationString(int derivation) {
switch (derivation) {
case 1:
return "";
case 2:
return "²";
case 3:
return "³";
default:
return "";
}
}
private void UpdateExpression() {
var expression = "";
if (!IsDerivative) {
expression = string.Format("Target:{0} in {1}{2} .. {3}{4}",
Variable,
"[",
Interval?.LowerBound,
Interval?.UpperBound,
"]");
if(Regions != null) {
foreach (var region in Regions)
expression += $", {region.VariableName}=({region.Interval.LowerBound} .. {region.Interval.UpperBound})";
}
Expression = expression;
return;
}
expression = string.Format("∂{6}{1}/∂{0}{6} in {2}{3} .. {4}{5}",
Variable,
Target,
"[",
Interval?.LowerBound,
Interval?.UpperBound,
"]",
GetDerivationString(numberOfDerivations));
if (Regions != null) {
foreach (var region in Regions)
expression += $", {region.VariableName}=({region.Interval.LowerBound} .. {region.Interval.UpperBound})";
}
Expression = expression;
}
private string GetDefinitionString() {
if (!IsDerivative) return "Target " + Variable;
var definition =
$"∂{GetDerivationString(numberOfDerivations)}Target/∂{Variable}{GetDerivationString(numberOfDerivations)}";
return definition;
}
public override string ToString() {
return Expression;
}
}
}