|
|
|
@ -19,66 +19,66 @@ namespace MathNet.Numerics.Optimization.ObjectiveFunctions |
|
|
|
public class ForwardDifferenceGradientObjectiveFunction : IObjectiveFunction |
|
|
|
{ |
|
|
|
public IObjectiveFunction InnerObjectiveFunction { get; protected set; } |
|
|
|
protected Vector<double> _lower_bound; |
|
|
|
protected Vector<double> _upper_bound; |
|
|
|
protected Vector<double> LowerBound { get; set; } |
|
|
|
protected Vector<double> UpperBound { get; set; } |
|
|
|
|
|
|
|
protected Vector<double> _point; |
|
|
|
protected bool _value_evaluated = false; |
|
|
|
protected bool _gradient_evaluated = false; |
|
|
|
protected Vector<double> _gradient; |
|
|
|
protected bool ValueEvaluated { get; set; } = false; |
|
|
|
protected bool GradientEvaluated { get; set; } = false; |
|
|
|
private Vector<double> _gradient; |
|
|
|
|
|
|
|
public double MinimumIncrement { get; set; } |
|
|
|
public double RelativeIncrement { get; set; } |
|
|
|
|
|
|
|
public double MinimumIncrement; |
|
|
|
public double RelativeIncrement; |
|
|
|
|
|
|
|
public ForwardDifferenceGradientObjectiveFunction(IObjectiveFunction valueOnlyObj, Vector<double> lowerBound, Vector<double> upperBound, double relativeIncrement=1e-5, double minimumIncrement=1e-8) |
|
|
|
{ |
|
|
|
this.InnerObjectiveFunction = valueOnlyObj; |
|
|
|
_lower_bound = lowerBound; |
|
|
|
_upper_bound = upperBound; |
|
|
|
_gradient = new LinearAlgebra.Double.DenseVector(_lower_bound.Count); |
|
|
|
this.RelativeIncrement = relativeIncrement; |
|
|
|
this.MinimumIncrement = minimumIncrement; |
|
|
|
InnerObjectiveFunction = valueOnlyObj; |
|
|
|
LowerBound = lowerBound; |
|
|
|
UpperBound = upperBound; |
|
|
|
_gradient = new LinearAlgebra.Double.DenseVector(LowerBound.Count); |
|
|
|
RelativeIncrement = relativeIncrement; |
|
|
|
MinimumIncrement = minimumIncrement; |
|
|
|
} |
|
|
|
|
|
|
|
protected void EvaluateValue() |
|
|
|
{ |
|
|
|
_value_evaluated = true; |
|
|
|
ValueEvaluated = true; |
|
|
|
} |
|
|
|
|
|
|
|
protected void EvaluateGradient() |
|
|
|
{ |
|
|
|
if (!_value_evaluated) |
|
|
|
this.EvaluateValue(); |
|
|
|
if (!ValueEvaluated) |
|
|
|
EvaluateValue(); |
|
|
|
|
|
|
|
var tmp_point = _point.Clone(); |
|
|
|
var tmp_obj = this.InnerObjectiveFunction.CreateNew(); |
|
|
|
var tmp_point = Point.Clone(); |
|
|
|
var tmp_obj = InnerObjectiveFunction.CreateNew(); |
|
|
|
for (int ii = 0; ii < _gradient.Count; ++ii) |
|
|
|
{ |
|
|
|
var orig_point = tmp_point[ii]; |
|
|
|
var rel_incr = orig_point * this.RelativeIncrement; |
|
|
|
var h = Math.Max(rel_incr, this.MinimumIncrement); |
|
|
|
var rel_incr = orig_point * RelativeIncrement; |
|
|
|
var h = Math.Max(rel_incr, MinimumIncrement); |
|
|
|
var mult = 1; |
|
|
|
if (orig_point + h > _upper_bound[ii]) |
|
|
|
if (orig_point + h > UpperBound[ii]) |
|
|
|
mult = -1; |
|
|
|
|
|
|
|
tmp_point[ii] = orig_point + mult*h; |
|
|
|
tmp_obj.EvaluateAt(tmp_point); |
|
|
|
double bumped_value = tmp_obj.Value; |
|
|
|
_gradient[ii] = (mult * bumped_value - mult * this.InnerObjectiveFunction.Value) / h; |
|
|
|
_gradient[ii] = (mult * bumped_value - mult * InnerObjectiveFunction.Value) / h; |
|
|
|
|
|
|
|
tmp_point[ii] = orig_point; |
|
|
|
} |
|
|
|
_gradient_evaluated = true; |
|
|
|
GradientEvaluated = true; |
|
|
|
} |
|
|
|
|
|
|
|
public Vector<double> Gradient |
|
|
|
{ |
|
|
|
get |
|
|
|
{ |
|
|
|
if (!_gradient_evaluated) |
|
|
|
this.EvaluateGradient(); |
|
|
|
if (!GradientEvaluated) |
|
|
|
EvaluateGradient(); |
|
|
|
return _gradient; |
|
|
|
} |
|
|
|
protected set { _gradient = value; } |
|
|
|
} |
|
|
|
|
|
|
|
public Matrix<double> Hessian |
|
|
|
@ -105,47 +105,41 @@ namespace MathNet.Numerics.Optimization.ObjectiveFunctions |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public Vector<double> Point |
|
|
|
{ |
|
|
|
get |
|
|
|
{ |
|
|
|
return _point; |
|
|
|
} |
|
|
|
} |
|
|
|
public Vector<double> Point { get; protected set; } |
|
|
|
|
|
|
|
public double Value |
|
|
|
{ |
|
|
|
get |
|
|
|
{ |
|
|
|
if (!_value_evaluated) |
|
|
|
this.EvaluateValue(); |
|
|
|
if (!ValueEvaluated) |
|
|
|
EvaluateValue(); |
|
|
|
return this.InnerObjectiveFunction.Value; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public IObjectiveFunction CreateNew() |
|
|
|
{ |
|
|
|
var tmp = new ForwardDifferenceGradientObjectiveFunction(this.InnerObjectiveFunction.CreateNew(), _lower_bound, _upper_bound, this.RelativeIncrement, this.MinimumIncrement); |
|
|
|
var tmp = new ForwardDifferenceGradientObjectiveFunction(this.InnerObjectiveFunction.CreateNew(), LowerBound, UpperBound, this.RelativeIncrement, this.MinimumIncrement); |
|
|
|
return tmp; |
|
|
|
} |
|
|
|
|
|
|
|
public void EvaluateAt(Vector<double> point) |
|
|
|
{ |
|
|
|
_point = point; |
|
|
|
_value_evaluated = false; |
|
|
|
_gradient_evaluated = false; |
|
|
|
this.InnerObjectiveFunction.EvaluateAt(point); |
|
|
|
Point = point; |
|
|
|
ValueEvaluated = false; |
|
|
|
GradientEvaluated = false; |
|
|
|
InnerObjectiveFunction.EvaluateAt(point); |
|
|
|
} |
|
|
|
|
|
|
|
public IObjectiveFunction Fork() |
|
|
|
{ |
|
|
|
var tmp = new ForwardDifferenceGradientObjectiveFunction(this.InnerObjectiveFunction.Fork(), _lower_bound, _upper_bound, this.RelativeIncrement, this.MinimumIncrement); |
|
|
|
tmp._point = _point?.Clone(); |
|
|
|
tmp._gradient_evaluated = _gradient_evaluated; |
|
|
|
tmp._value_evaluated = _value_evaluated; |
|
|
|
tmp._gradient = _gradient?.Clone(); |
|
|
|
|
|
|
|
return tmp; |
|
|
|
return new ForwardDifferenceGradientObjectiveFunction(this.InnerObjectiveFunction.Fork(), LowerBound, UpperBound, this.RelativeIncrement, this.MinimumIncrement) |
|
|
|
{ |
|
|
|
Point = Point?.Clone(), |
|
|
|
GradientEvaluated = GradientEvaluated, |
|
|
|
ValueEvaluated = ValueEvaluated, |
|
|
|
_gradient = _gradient?.Clone() |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|