How to: Create a Custom Solver Report using the Solver APIs

Solver Foundation 3.0

If you are using a third-party solver, you can use the Solver reporting APIs to report data about custom properties. The following linear programming example demonstrates how to create a sensitivity and infeasibility report at the solver level. In this example, an oil refinery must procure crude oil from two sources. The objective is to minimize the purchase costs of crude oils that differ in quality and meet minimum production levels of 2000 barrels of gasoline, 1500 barrels of jet fuel, and 500 barrels of machine lubricant. Meanwhile, the suppliers cannot exceed their maximum daily production of crude oil. The following table shows the cost and capabilities of the two different crude oils.


Saudi Arabia Refining

Venezuela Refining





9000 barrels

6000 barrels

Refining Percentages:

30% gasoline

40% jet fuel

20% lubricant

10% waste

40% gasoline

20% jet fuel

30% lubricant

10% waste

The following steps show how to use Solver Foundation to create and solve the refining model by developing directly against the solvers. Then, the steps show how to create custom sensitivity and infeasibility reports at the solver level.

To create custom sensitivity and infeasibility solver reports

  1. Create a Console Application named PetroChem.

  2. Add a reference to Microsoft Solver Foundation on the .NET tab.

  3. Add the following Imports or using statements to the top of the Program code file.

    using Microsoft.SolverFoundation.Common;
    using Microsoft.SolverFoundation.Services;
    using Microsoft.SolverFoundation.Solvers;
  4. In the Main method, add a solver by typing the following code.

    SimplexSolver solver = new SimplexSolver();
  5. Add variables to the solver together with their lower and upper bounds. The sources of crude oil are Saudi Arabia and Venezuela; add these by using the AddVariable method. Define their maximum daily productions of crude oil by using the SetBounds method.

    int savid, vzvid;
    solver.AddVariable("Saudi Arabia", out savid);
    solver.SetBounds(savid, 0, 9000);
    solver.AddVariable("Venezuela", out vzvid);
    solver.SetBounds(vzvid, 0, 6000);
  6. Add three row identifiers for the gasoline, jet fuel, and machine lubricant constraints, and then add a row identifier to represent the minimum cost of refining.

    int gasoline, jetfuel, machinelubricant, cost;
    solver.AddRow("gasoline", out gasoline);
    solver.AddRow("jetfuel", out jetfuel);
    solver.AddRow("machinelubricant", out machinelubricant);
    solver.AddRow("cost", out cost);
  7. Add coefficients to the constraint rows and set bounds. Use decimals to add the refining capabilities of the crude oil for each supplier. For example, the Saudi Arabian crude oil produces 30% gasoline (0.3) and the Venezuelan crude oil produces 40% gasoline (0.4). Set these values by using the SetCoefficient method. Set the minimum production levels of 2000 barrels of gasoline, 1500 barrels of jet fuel, and 500 barrels of machine lubricant by using the SetBounds method.

    solver.SetCoefficient(gasoline, savid, 0.3);
    solver.SetCoefficient(gasoline, vzvid, 0.4);
    solver.SetBounds(gasoline, 2000, Rational.PositiveInfinity);
    solver.SetCoefficient(jetfuel, savid, 0.4);
    solver.SetCoefficient(jetfuel, vzvid, 0.2);
    solver.SetBounds(jetfuel, 1500, Rational.PositiveInfinity);
    solver.SetCoefficient(machinelubricant, savid, 0.2);
    solver.SetCoefficient(machinelubricant, vzvid, 0.3);
    solver.SetBounds(machinelubricant, 500, Rational.PositiveInfinity);
  8. Add the costs of the crude oils to the model and then specify that the solver should minimize the goal by setting the third parameter to true. A value of false would maximize the goal.

    solver.SetCoefficient(cost, savid, 20);
    solver.SetCoefficient(cost, vzvid, 15);
    solver.AddGoal(cost, 1, true);
  9. Create solver parameters to enable the sensitivity and infeasibility reports. Then, solve the model and get the default report, sensitivity report, and infeasibility report.

    SimplexSolverParams solverParams = new SimplexSolverParams();
    solverParams.GetSensitivityReport = true;
    solverParams.GetInfeasibilityReport = true;
    Console.WriteLine("SA {0}, VZ {1}, Gasoline {2}, Jet Fuel {3}, Machine Lubricant {4}, Cost {5}",
    ILinearSolverReport reportSensitivity = solver.GetReport(LinearSolverReportType.Sensitivity);
    if (reportSensitivity != null) {
      ILinearSolverSensitivityReport sensitivityReport = reportSensitivity as ILinearSolverSensitivityReport;
      foreach (var row in solver.RowIndices) {
        if (!solver.IsGoal(row)) {
          Console.WriteLine("Key: "+ solver.GetKeyFromIndex(row) + " Dual Value: " + sensitivityReport.GetDualValue(row).ToDouble());
    ILinearSolverReport reportInfeasibility = solver.GetReport(LinearSolverReportType.Infeasibility);
    if (reportInfeasibility == null) {
      Console.WriteLine("This model is not infeasible, so there is no infeasibility report.");
  10. Press F5 to build and run the code.

    The command window shows the following results.

    SA 2000, VZ 3500, Gasoline 2000, Jet Fuel 1500, Machine Lubricant 1450, Cost 92500

    Key: gasoline Dual Value: 20

    Key: jetfuel Dual Value: 35

    Key: machinelubricant Dual Value: 0

    There is no infeasibility report because the model inputs are not infeasible.