Skip to content
This repository has been archived by the owner on Nov 19, 2020. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
 - Adding Tolerance to the interface of IConstraint
 - Add GetViolation and IsViolated as extension methods to IConstraint (removing duplicated code)

GH-820:
 - Changing all references from NonlinearConstraint to IConstraint in AugmentedLagrangian.cs.
 - Updating the documentation to give an example of using LinearConstraints in the AugmentedLagrangian
  • Loading branch information
CatchemAL committed Oct 11, 2017
1 parent 94207a2 commit 77edbc3
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 156 deletions.
1 change: 1 addition & 0 deletions Sources/Accord.Math/Accord.Math.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@
<Compile Include="Matrix\Vector.MinMax.cs" />
<Compile Include="Matrix\Matrix.MinMax.cs" />
<Compile Include="Optimization\Base\IFunctionOptimizationMethod.cs" />
<Compile Include="Optimization\Constrained\Constraints\ConstraintExtensions.cs" />
<Compile Include="Optimization\Losses\BinaryCrossEntropyLoss.cs" />
<Compile Include="Optimization\Losses\CategoryCrossEntropyLoss.cs" />
<Compile Include="Optimization\Losses\HammingLoss.cs" />
Expand Down
32 changes: 16 additions & 16 deletions Sources/Accord.Math/Optimization/Constrained/AugmentedLagrangian.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public enum AugmentedLagrangianStatus

/// <summary>
/// The optimization could not make progress towards finding a feasible
/// solution. Try increasing the <see cref="NonlinearConstraint.Tolerance"/>
/// solution. Try increasing the <see cref="IConstraint.Tolerance"/>
/// of the constraints.
/// </summary>
///
Expand Down Expand Up @@ -115,9 +115,9 @@ public class AugmentedLagrangian : BaseGradientOptimizationMethod, IGradientOpti

IGradientOptimizationMethod dualSolver;

NonlinearConstraint[] lesserThanConstraints;
NonlinearConstraint[] greaterThanConstraints;
NonlinearConstraint[] equalityConstraints;
IConstraint[] lesserThanConstraints;
IConstraint[] greaterThanConstraints;
IConstraint[] equalityConstraints;


private double rho;
Expand Down Expand Up @@ -206,9 +206,9 @@ public int MaxEvaluations
///
/// <param name="numberOfVariables">The number of free parameters in the optimization problem.</param>
/// <param name="constraints">
/// The <see cref="NonlinearConstraint"/>s to which the solution must be subjected.</param>
/// The <see cref="IConstraint"/>s to which the solution must be subjected.</param>
///
public AugmentedLagrangian(int numberOfVariables, IEnumerable<NonlinearConstraint> constraints)
public AugmentedLagrangian(int numberOfVariables, IEnumerable<IConstraint> constraints)
: base(numberOfVariables)
{
init(null, constraints, null);
Expand All @@ -220,9 +220,9 @@ public AugmentedLagrangian(int numberOfVariables, IEnumerable<NonlinearConstrain
///
/// <param name="function">The objective function to be optimized.</param>
/// <param name="constraints">
/// The <see cref="NonlinearConstraint"/>s to which the solution must be subjected.</param>
/// The <see cref="IConstraint"/>s to which the solution must be subjected.</param>
///
public AugmentedLagrangian(NonlinearObjectiveFunction function, IEnumerable<NonlinearConstraint> constraints)
public AugmentedLagrangian(NonlinearObjectiveFunction function, IEnumerable<IConstraint> constraints)
: base(function.NumberOfVariables)
{
init(function, constraints, null);
Expand All @@ -237,10 +237,10 @@ public AugmentedLagrangian(NonlinearObjectiveFunction function, IEnumerable<Nonl
/// problem.</param>
/// <param name="function">The objective function to be optimized.</param>
/// <param name="constraints">
/// The <see cref="NonlinearConstraint"/>s to which the solution must be subjected.</param>
/// The <see cref="IConstraint"/>s to which the solution must be subjected.</param>
///
public AugmentedLagrangian(IGradientOptimizationMethod innerSolver,
NonlinearObjectiveFunction function, IEnumerable<NonlinearConstraint> constraints)
NonlinearObjectiveFunction function, IEnumerable<IConstraint> constraints)
: base(innerSolver.NumberOfVariables)
{
if (innerSolver.NumberOfVariables != function.NumberOfVariables)
Expand All @@ -258,17 +258,17 @@ public AugmentedLagrangian(IGradientOptimizationMethod innerSolver,
/// optimization method</see> used internally to solve the dual of this optimization
/// problem.</param>
/// <param name="constraints">
/// The <see cref="NonlinearConstraint"/>s to which the solution must be subjected.</param>
/// The <see cref="IConstraint"/>s to which the solution must be subjected.</param>
///
public AugmentedLagrangian(IGradientOptimizationMethod innerSolver, IEnumerable<NonlinearConstraint> constraints)
public AugmentedLagrangian(IGradientOptimizationMethod innerSolver, IEnumerable<IConstraint> constraints)
: base(innerSolver.NumberOfVariables)
{
init(null, constraints, innerSolver);
}


private void init(NonlinearObjectiveFunction function,
IEnumerable<NonlinearConstraint> constraints, IGradientOptimizationMethod innerSolver)
IEnumerable<IConstraint> constraints, IGradientOptimizationMethod innerSolver)
{
if (function != null)
{
Expand All @@ -294,9 +294,9 @@ private void init(NonlinearObjectiveFunction function,
};
}

var equality = new List<NonlinearConstraint>();
var lesserThan = new List<NonlinearConstraint>();
var greaterThan = new List<NonlinearConstraint>();
var equality = new List<IConstraint>();
var lesserThan = new List<IConstraint>();
var greaterThan = new List<IConstraint>();

foreach (var c in constraints)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Accord Math Library
// The Accord.NET Framework
// http://accord-framework.net
//
// Copyright © César Souza, 2009-2017
// cesarsouza at gmail.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//

namespace Accord.Math.Optimization
{
using System;

/// <summary>
/// Extension methods on the <see cref="IConstraint"/> interface.
/// </summary>
public static class ConstraintExtensions
{

/// <summary>
/// Gets how much the constraint is being violated.
/// </summary>
///
/// <param name="input">The function point.</param>
///
/// <returns>
/// How much the constraint is being violated at the given point. Positive
/// value means the constraint is not being violated with the returned slack,
/// while a negative value means the constraint is being violated by the returned
/// amount.
/// </returns>
///
public static double GetViolation(this IConstraint constraint, double[] input)
{
double fx = constraint.Function(input);

switch (constraint.ShouldBe)
{
case ConstraintType.EqualTo:
return Math.Abs(fx - constraint.Value);

case ConstraintType.GreaterThanOrEqualTo:
return fx - constraint.Value;

case ConstraintType.LesserThanOrEqualTo:
return constraint.Value - fx;
}

throw new NotSupportedException();
}

/// <summary>
/// Gets whether this constraint is being violated
/// (within the current tolerance threshold).
/// </summary>
/// <param name="constraint">The constraint.</param>
/// <param name="input">The function point.</param>
/// <returns>
/// True if the constraint is being violated, false otherwise.
/// </returns>
public static bool IsViolated(this IConstraint constraint, double[] input)
{
return constraint.GetViolation(input) + constraint.Tolerance < 0;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,8 @@
namespace Accord.Math.Optimization
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

interface IConstraint
public interface IConstraint
{
/// <summary>
/// Gets the type of the constraint.
Expand All @@ -40,7 +37,13 @@ interface IConstraint
/// side of the constraint equation.
/// </summary>
///
double Value { get; }
double Value { get; }

/// <summary>
/// Gets the violation tolerance for the constraint.
/// </summary>
///
double Tolerance { get; }

/// <summary>
/// Gets the number of variables in the constraint.
Expand All @@ -61,20 +64,5 @@ interface IConstraint
/// </summary>
///
Func<double[], double[]> Gradient { get; }

/// <summary>
/// Gets how much the constraint is being violated.
/// </summary>
///
/// <param name="input">The function point.</param>
///
/// <returns>
/// How much the constraint is being violated at the given point. Positive
/// value means the constraint is not being violated with the returned slack,
/// while a negative value means the constraint is being violated by the returned
/// amount.
/// </returns>
///
double GetViolation(double[] input);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -247,52 +247,6 @@ public LinearConstraint(IObjectiveFunction function, Expression<Func<bool>> cons
this.Gradient = gradient;
}

/// <summary>
/// Gets how much the constraint is being violated.
/// </summary>
///
/// <param name="input">The function point.</param>
///
/// <returns>
/// How much the constraint is being violated at the given point. Positive
/// value means the constraint is not being violated with the returned slack,
/// while a negative value means the constraint is being violated by the returned
/// amount.
/// </returns>
///
public double GetViolation(double[] input)
{
double fx = compute(input);

switch (ShouldBe)
{
case ConstraintType.EqualTo:
return Math.Abs(fx - Value);

case ConstraintType.GreaterThanOrEqualTo:
return fx - Value;

case ConstraintType.LesserThanOrEqualTo:
return Value - fx;
}

throw new NotSupportedException();
}

/// <summary>
/// Gets whether this constraint is being violated
/// (within the current tolerance threshold).
/// </summary>
///
/// <param name="input">The function point.</param>
///
/// <returns>True if the constraint is being violated, false otherwise.</returns>
///
public bool IsViolated(double[] input)
{
return GetViolation(input) < -Tolerance;
}

/// <summary>
/// Attempts to create a <see cref="LinearConstraint"/>
/// from a <see cref="System.String"/> representation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,53 +56,7 @@ public class NonlinearConstraint : IConstraint, IFormattable
/// </summary>
///
public Func<double[], double[]> Gradient { get; private set; }

/// <summary>
/// Gets how much the constraint is being violated.
/// </summary>
///
/// <param name="input">The function point.</param>
///
/// <returns>
/// How much the constraint is being violated at the given point. Positive
/// value means the constraint is not being violated with the returned slack,
/// while a negative value means the constraint is being violated by the returned
/// amount.
/// </returns>
///
public double GetViolation(double[] input)
{
double fx = Function(input);

switch (ShouldBe)
{
case ConstraintType.EqualTo:
return Math.Abs(fx - Value);

case ConstraintType.GreaterThanOrEqualTo:
return fx - Value;

case ConstraintType.LesserThanOrEqualTo:
return Value - fx;
}

throw new NotSupportedException();
}

/// <summary>
/// Gets whether this constraint is being violated
/// (within the current tolerance threshold).
/// </summary>
///
/// <param name="input">The function point.</param>
///
/// <returns>True if the constraint is being violated, false otherwise.</returns>
///
public bool IsViolated(double[] input)
{
return GetViolation(input) < -Tolerance;
}


/// <summary>
/// Gets the type of the constraint.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,34 +379,19 @@ public void solve_vectors()
gradient: (x) => new[]
{
2 * (200 * Math.Pow(x[0], 3) - 200 * x[0] * x[1] + x[0] - 1), // df/dx = 2(200x³-200xy+x-1)
200 * (x[1] - x[0]*x[0]) // df/dy = 200(y-x²)
200 * (x[1] - x[0]*x[0]) // df/dy = 200(y-x²)
}
);

// Now we can start stating the constraints
var constraints = new List<NonlinearConstraint>()
{
// Add the non-negativity constraint for x
new NonlinearConstraint(f,
// 1st constraint: x should be greater than or equal to 0
function: (x) => x[0], // x
shouldBe: ConstraintType.GreaterThanOrEqualTo,
value: 0,
gradient: (x) => new[] { 1.0, 0.0 }
),

// Add the non-negativity constraint for y
new NonlinearConstraint(f,
// 2nd constraint: y should be greater than or equal to 0
function: (x) => x[1], // y
shouldBe: ConstraintType.GreaterThanOrEqualTo,
value: 0,
gradient: (x) => new[] { 0.0, 1.0 }
)
};
// As before, we state the constraints. However, to illustrate the flexibility
// of the AugmentedLagrangian, we shall use LinearConstraints to constrain the problem.
double[,] a = Matrix.Identity(2); // Set up the constraint matrix...
double[] b = Vector.Zeros(2); // ...and the values they must be greater than
int numberOfEqualities = 0;
var linearConstraints = LinearConstraintCollection.Create(a, b, numberOfEqualities);

// Finally, we create the non-linear programming solver
var solver = new AugmentedLagrangian(f, constraints);
var solver = new AugmentedLagrangian(f, linearConstraints);

// And attempt to find a minimum
bool success = solver.Minimize();
Expand All @@ -423,9 +408,9 @@ public void solve_vectors()
Assert.AreEqual(1, solver.Solution[0], 1e-6);
Assert.AreEqual(1, solver.Solution[1], 1e-6);

Assert.IsFalse(Double.IsNaN(minValue));
Assert.IsFalse(Double.IsNaN(solver.Solution[0]));
Assert.IsFalse(Double.IsNaN(solver.Solution[1]));
Assert.IsFalse(double.IsNaN(minValue));
Assert.IsFalse(double.IsNaN(solver.Solution[0]));
Assert.IsFalse(double.IsNaN(solver.Solution[1]));
}

[Test]
Expand Down

0 comments on commit 77edbc3

Please sign in to comment.