← All NMath Code Examples
using System;
using CenterSpace.NMath.Core;
namespace CenterSpace.NMath.Examples.CSharp
{
/// <summary>
/// A .NET example in C# showing how to solve the Klee Minty cube linear
/// programming problem using both primal and dual simplex methods and
/// various pivoting strategies.
/// The Klee Minty cube is a unit cube with perturbed corners. Klee and
/// Minty showed that Dantzigs simplex algorithm can have worst-case
/// performance with this cube as the feasible region.
/// </summary>
public class PrimalDualSimplexExample
{
static void Main( string[] args )
{
int n = 200;
var lpProblem = KleeMintyCube( n );
Console.WriteLine( "Klee Minty Cube LP problem using Primal Simplex:" );
Console.WriteLine( "---------------------------------------------------" );
SolveKleeMintyProblemPrimal( lpProblem );
Console.WriteLine( "\n" );
Console.WriteLine( "Klee Minty Cube LP problem using Dual Simplex:" );
Console.WriteLine( "---------------------------------------------------" );
SolveKleeMintyProblemDual( lpProblem );
Console.WriteLine();
Console.WriteLine( "Press Enter Key" );
Console.Read();
}
/// <summary>
/// Solve the Klee Minty cube linear programming problem with the primal simplex
/// solver using different pivoting strategies.
/// </summary>
/// <param name="kleeMintyProblem">Klee Minty cube linear programming problem.</param>
static void SolveKleeMintyProblemPrimal( LinearProgrammingProblem kleeMintyProblem )
{
// Create a solver parameters object with the desired values.
// Here we set costing, or pivot strategy for selecting which
// variable enters the basis on a pivot, the maximum number of pivots
// to perform, tell the solver that we want to minimize, not maximize,
// the objective function. If the maximum number of pivots is exceeded
// the Result property of the solver will be SolveResult.SolverInterrupted.
var solverParams = new PrimalSimplexSolverParams
{
Costing = PrimalSimplexCosting.Partial, // Use partial pivoting.
MaxPivotCount = 5000, // Do not perform more than 5000 pivots
Minimize = true // minimize, not maximize the objective function.
};
// Create a primal simplex solver and solve with the above options.
var solver = new PrimalSimplexSolver();
solver.Solve( kleeMintyProblem, solverParams );
int partialPivotCount = solver.PivotCount;
Console.WriteLine( "Primal Simplex Solver, Partial pivot strategy result: " + solver.Result );
Console.WriteLine( "Partial pivot strategy pivot count = " + partialPivotCount );
Console.WriteLine();
// Now solve with best reduced cost pivoting strategy. This is the
// classic Dantzig rule.
solverParams.Costing = PrimalSimplexCosting.BestReducedCost;
solver.Solve( kleeMintyProblem, solverParams );
int bestReducedCostPivotCount = solver.PivotCount;
Console.WriteLine( "Primal Simplex Solver, Best Reduced Cost result: " + solver.Result );
Console.WriteLine( "Best reduced cost pivot strategy pivot count = " + bestReducedCostPivotCount );
Console.WriteLine();
// Is one pivoting strategy preferable?
if ( partialPivotCount < bestReducedCostPivotCount )
{
Console.WriteLine( "For Primal Simplex prefer steepest edge for Klee Minty problem" );
}
else if ( bestReducedCostPivotCount < partialPivotCount )
{
Console.WriteLine( "For Primal Simplex prefer best reduced cost for Klee Minty problem" );
}
else
{
Console.WriteLine( "For Primal Simplex both pivoting strategies yield the same number of pivots." );
}
}
/// <summary>
/// Solve the Klee Minty cube linear programming problem with the dual simplex
/// solver using different pivoting strategies.
/// </summary>
/// <param name="kleeMintyProblem">Klee Minty cube linear programming problem.</param>
static void SolveKleeMintyProblemDual( LinearProgrammingProblem kleeMintyProblem )
{
// Create a solver parameters object with the desired values. Note that
// partial pivoting is not an available option for the dual simplex
// solver.
var solverParams = new DualSimplexSolverParams
{
Costing = DualSimplexCosting.SteepestEdge, // Use steepest edge pivoting.
MaxPivotCount = 5000,
Minimize = true // minimize, not maximize the objective function.
};
// Create a dual simplex solver and solve with the above options.
var solver = new DualSimplexSolver();
solver.Solve( kleeMintyProblem, solverParams );
int steepestEdgePivotCount = solver.PivotCount;
Console.WriteLine( "Dual Simplex Solver, Steepest Edge result: " + solver.Result );
Console.WriteLine( "Steepest edge pivot strategy pivot count = " + steepestEdgePivotCount );
Console.WriteLine();
// Now solve with the best reduced cost pivot strategy. This is the
// classic Dantzig rule.
solverParams.Costing = DualSimplexCosting.BestReducedCost;
solver.Solve( kleeMintyProblem, solverParams );
int bestReducedCostPivotCount = solver.PivotCount;
Console.WriteLine( "Dual Simplex Solver, Best Reduced Cost result: " + solver.Result );
Console.WriteLine( "Best reduced cost pivot strategy pivot count = " + bestReducedCostPivotCount );
Console.WriteLine();
// Is one pivoting strategy preferable?
if ( steepestEdgePivotCount < bestReducedCostPivotCount )
{
Console.WriteLine( "For Dual Simplex prefer steepest edge for Klee Minty problem" );
}
else if ( bestReducedCostPivotCount < steepestEdgePivotCount )
{
Console.WriteLine( "For Dual Simplex prefer best reduced cost for Klee Minty problem" );
}
else
{
Console.WriteLine( "For Dual Simplex both pivoting strategies yield the same number of pivots." );
}
}
/// <summary>
/// Create the Klee Minty cube linear programming problem with the given dimension.
/// </summary>
/// <param name="n">The desired number of vertices.</param>
/// <returns><c>LinearProgramming</c> object describing the Klee Minty
/// cube linear programming problem.</returns>
static LinearProgrammingProblem KleeMintyCube( int n )
{
var objectiveCoeff = new DoubleVector( n );
objectiveCoeff[n - 1] = 1.0;
double eps = 1.0 / 300.0;
var problem = new LinearProgrammingProblem( objectiveCoeff );
problem.AddBounds( 0, 0.0, 1.0 );
for ( int i = 1; i < n; i++ )
{
// Lower bound constraint.
var lbConstraintCoeffs = new DoubleVector( n );
lbConstraintCoeffs[i] = 1.0;
lbConstraintCoeffs[i - 1] = -eps;
problem.AddLowerBoundConstraint( lbConstraintCoeffs, 0.0 );
// Upper bound constraint
var ubConstraintCoeffs = new DoubleVector( n );
ubConstraintCoeffs[i] = 1.0;
ubConstraintCoeffs[i - 1] = eps;
problem.AddUpperBoundConstraint( ubConstraintCoeffs, 1.0 );
}
return problem;
}
}
}
← All NMath Code Examples