Browse Source

First commit working on optimization tools

(Patched by cdrnet: only taking root finding algorithm for now, rest
later)
v2
Scott Stephens 14 years ago
committed by Christoph Ruegg
parent
commit
35ccfec740
  1. 1
      src/Numerics/Numerics.csproj
  2. 78
      src/Numerics/Optimization/BisectionRootFinder.cs
  3. 30
      src/UnitTests/OptimizationTests/TestBisectionRootFinder.cs
  4. 2
      src/UnitTests/UnitTests.csproj

1
src/Numerics/Numerics.csproj

@ -113,6 +113,7 @@
<Compile Include="RootFinding\Bracketing.cs" /> <Compile Include="RootFinding\Bracketing.cs" />
<Compile Include="RootFinding\Algorithms\Brent.cs" /> <Compile Include="RootFinding\Algorithms\Brent.cs" />
<Compile Include="RootFinding\FloatingPointRoots.cs" /> <Compile Include="RootFinding\FloatingPointRoots.cs" />
<Compile Include="Optimization\BisectionRootFinder.cs" />
<Compile Include="SpecialFunctions\Evaluate.cs" /> <Compile Include="SpecialFunctions\Evaluate.cs" />
<Compile Include="SpecialFunctions\ModifiedStruve.cs" /> <Compile Include="SpecialFunctions\ModifiedStruve.cs" />
<Compile Include="SpecialFunctions\ModifiedBessel.cs" /> <Compile Include="SpecialFunctions\ModifiedBessel.cs" />

78
src/Numerics/Optimization/BisectionRootFinder.cs

@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MathNet.Numerics.Optimization
{
public class BisectionRootFinder
{
public double ObjectiveTolerance { get; set; }
public double XTolerance { get; set; }
public double LowerExpansionFactor { get; set; }
public double UpperExapansionFactor { get; set; }
public int MaxExpansionSteps { get; set; }
public BisectionRootFinder(double objective_tolerance=1e-5, double x_tolerance=1e-5, double lower_expansion_factor=-1.0, double upper_expansion_factor=-1.0, int max_expansion_steps=10)
{
this.ObjectiveTolerance = objective_tolerance;
this.XTolerance = x_tolerance;
this.LowerExpansionFactor = lower_expansion_factor;
this.UpperExapansionFactor = upper_expansion_factor;
this.MaxExpansionSteps = max_expansion_steps;
}
public double FindRoot(Func<double, double> objective_function, double lower_bound, double upper_bound)
{
double lower_val = objective_function(lower_bound);
double upper_val = objective_function(upper_bound);
if (lower_val == 0.0)
return lower_bound;
if (upper_val == 0.0)
return upper_bound;
this.ValidateEvaluation(lower_val, lower_bound);
this.ValidateEvaluation(upper_val, upper_bound);
if (Math.Sign(lower_val) == Math.Sign(upper_val) && this.LowerExpansionFactor <= 1.0 && this.UpperExapansionFactor <= 1.0)
throw new Exception("Bounds do not necessarily span a root, and StepExpansionFactor is not set to expand the interval in this case.");
while (Math.Abs(upper_val - lower_val) > 0.5 * this.ObjectiveTolerance || Math.Abs(upper_bound - lower_bound) > 0.5 * this.XTolerance)
{
double midpoint = 0.5 * (upper_bound + lower_bound);
double midval = objective_function(midpoint);
this.ValidateEvaluation(midval, midpoint);
if (Math.Sign(midval) == Math.Sign(lower_val))
{
lower_bound = midpoint;
lower_val = midval;
}
else if (Math.Sign(midval) == Math.Sign(upper_val))
{
upper_bound = midpoint;
upper_val = midval;
}
else
{
return midpoint;
}
}
return 0.5 * (lower_bound + upper_bound);
}
private void ValidateEvaluation(double output, double input)
{
if (!IsFinite(output))
throw new Exception(String.Format("Objective function returned non-finite result: f({0}) = {1}", input, output));
}
private static bool IsFinite(double x)
{
return !(Double.IsInfinity(x) || Double.IsNaN(x));
}
}
}

30
src/UnitTests/OptimizationTests/TestBisectionRootFinder.cs

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using MathNet.Numerics.Optimization;
namespace MathNet.Numerics.UnitTests.OptimizationTests
{
[TestFixture]
class TestBisectionRootFinder
{
[Test]
public void FindRoot_Works()
{
var algorithm = new BisectionRootFinder(0.001, 0.001);
var f1 = new Func<double, double>((x) => (x - 3) * (x - 4));
var r1 = algorithm.FindRoot(f1, 2.1, 3.9);
Assert.That(Math.Abs(f1(r1)), Is.LessThan(0.001));
Assert.That(Math.Abs(r1 - 3.0), Is.LessThan(0.001));
var f2 = new Func<double, double>((x) => (x - 3) * (x - 4));
var r2 = algorithm.FindRoot(f1, 2.1, 3.4);
Assert.That(Math.Abs(f2(r2)), Is.LessThan(0.001));
Assert.That(Math.Abs(r2 - 3.0), Is.LessThan(0.001));
}
}
}

2
src/UnitTests/UnitTests.csproj

@ -751,6 +751,7 @@
<Compile Include="NumberTheoryTests\GcdRelatedTest.cs" /> <Compile Include="NumberTheoryTests\GcdRelatedTest.cs" />
<Compile Include="NumberTheoryTests\GcdRelatedTestBigInteger.cs" /> <Compile Include="NumberTheoryTests\GcdRelatedTestBigInteger.cs" />
<Compile Include="NumberTheoryTests\IntegerTheoryTest.cs" /> <Compile Include="NumberTheoryTests\IntegerTheoryTest.cs" />
<Compile Include="OptimizationTests\TestBisectionRootFinder.cs" />
<Compile Include="PermutationTest.cs" /> <Compile Include="PermutationTest.cs" />
<Compile Include="PrecisionTest.cs" /> <Compile Include="PrecisionTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
@ -1087,6 +1088,7 @@
<ItemGroup> <ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

Loading…
Cancel
Save