How to: Create a Custom Solver Report using the Solver APIs
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.
|
Source: |
Saudi Arabia Refining |
Venezuela Refining |
|
Cost: |
$20/barrel |
$15/barrel |
|
Maximum: |
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
-
Create a Console Application named PetroChem.
-
Add a reference to Microsoft Solver Foundation on the .NET tab.
-
Add the following Imports or using statements to the top of the Program code file.
-
In the Main method, add a solver by typing the following code.
-
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.
-
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.
-
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)
-
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.
-
Create solver parameters to enable the sensitivity and infeasibility reports. Then, solve the model and get the default report, sensitivity report, and infeasibility report.
Dim solverParams As SimplexSolverParams = New SimplexSolverParams() solverParams.GetSensitivityReport = True solverParams.GetInfeasibilityReport = True solver.Solve(solverParams) Console.WriteLine("SA {0}, VZ {1}, Gasoline {2}, Jet Fuel {3}, Machine Lubricant {4}, Cost {5}", solver.GetValue(savid).ToDouble(), solver.GetValue(vzvid).ToDouble(), solver.GetValue(gasoline).ToDouble(), solver.GetValue(jetfuel).ToDouble(), solver.GetValue(machinelubricant).ToDouble(), solver.GetValue(cost).ToDouble()) Dim reportSensitivity As ILinearSolverReport = solver.GetReport(LinearSolverReportType.Sensitivity) If reportSensitivity IsNot Nothing Then Dim sensitivityReport As ILinearSolverSensitivityReport = TryCast(reportSensitivity, ILinearSolverSensitivityReport) For Each row As Integer In solver.RowIndices If Not solver.IsGoal(row) Then Console.WriteLine("Key: " & solver.GetKeyFromIndex(row) & " Dual Value: " & sensitivityReport.GetDualValue(row).ToDouble()) End If Next End If Dim reportInfeasibility As ILinearSolverReport = solver.GetReport(LinearSolverReportType.Infeasibility) If reportInfeasibility Is Nothing Then Console.WriteLine("The model is not infeasible, so there is no infeasibility report.") End If Console.ReadLine()
-
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.