How to: Bind Data to Parameters and Output

Solver Foundation 3.0

You can use linear programming to minimize or maximize functions. In this example, an oil refinery must procure crude oil from two sources. The objective is to minimize the purchase cost of crude oils of varying quality and to meet minimum production levels of 2,000 barrels of gasoline, 1,500 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 costs and capabilities of the two different crude oils.


Saudi Arabia refining

Venezuela refining


$20 per barrel

$15 per barrel

Maximum daily production

9,000 barrels

6,000 barrels

Refining percentages

30% gasoline

40% jet fuel

20% lubricant

10% waste

40% gasoline

20% jet fuel

30% lubricant

10% waste

The following example demonstrates how to use Solver Foundation to create and solve the refining model by using the Solver Foundation Services layer.

To bind data to input parameters and output variables

  1. Create a console application named PetroChem.

  2. Add a reference to Microsoft Solver Foundation on the .NET tab of the Add Reference dialog box.

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

    Imports Microsoft.SolverFoundation.Common
    Imports Microsoft.SolverFoundation.Services
  4. Create the following class to define the information used to describe a country or region.

    Class CountryDef
        Public Property Country() As String
                Return m_Country
            End Get
            Set(ByVal value As String)
                m_Country = value
            End Set
        End Property
        Private m_Country As String
        Public Property MaxProduction() As Double
                Return m_MaxProduction
            End Get
            Set(ByVal value As Double)
                m_MaxProduction = value
            End Set
        End Property
        Private m_MaxProduction As Double
        Public Property Price() As Double
                Return m_Price
            End Get
            Set(ByVal value As Double)
                m_Price = value
            End Set
        End Property
        Private m_Price As Double
        Public Property Yield() As Double
                Return m_Yield
            End Get
            Set(ByVal value As Double)
                m_Yield = value
            End Set
        End Property
        Private m_Yield As Double
        Public Property Production() As Double
                Return m_Production
            End Get
            Set(ByVal value As Double)
                m_Production = value
            End Set
        End Property
        Private m_Production As Double
        Public Sub New(ByVal country As String, ByVal maxProduction As Double, ByVal price As Double, ByVal yield As Double)
            m_Country = country
            m_MaxProduction = maxProduction
            m_Price = price
            m_Yield = yield
            m_Production = -42
        End Sub
    End Class
  5. In the Main method, add the following code to instantiate the class and define the data that describes the country or region.

    Dim ProductionCapacity As CountryDef() = {
        New CountryDef("Venezuela", 9000, 15, 0.4),
        New CountryDef("Saudi Arabia", 6000, 20, 0.3)}
  6. Add the following code to get the context environment for a solver and create a new model.

    Dim context As SolverContext = SolverContext.GetContext()
    Dim model As Model = context.CreateModel()
  7. Create decision variables that represent the two sources of crude oil: Saudi Arabia and Venezuela.

    Dim vz As New Decision(Domain.RealNonnegative, "barrels_venezuela")
    Dim sa As New Decision(Domain.RealNonnegative, "barrels_saudiarabia")
  8. Bind data to the decisions by using LINQ. Then add the decisions to the model.

        (From row In ProductionCapacity Where row.Country = "Venezuela" Select row),
        (From row In ProductionCapacity Where row.Country = "Saudi Arabia" Select row),
    model.AddDecisions(vz, sa)
  9. Create two parameters that represent the input data for the model.

    Dim maxvz As New Parameter(Domain.RealNonnegative, "maxproduction_venezuela")
    Dim maxsa As New Parameter(Domain.RealNonnegative, "maxproduction_saudiarabia")
  10. Bind data to the parameters by using LINQ

        (From row In ProductionCapacity Where row.Country = "Venezuela" Select row),
        (From row In ProductionCapacity Where row.Country = "Saudi Arabia" Select row),
    model.AddParameters(maxvz, maxsa)
  11. Add two constraints that define the maximum daily production levels for the two refineries.

                         0 <= vz <= maxvz,
                         0 <= sa <= maxsa)
  12. Add three constraints that define the refining capabilities of each crude oil. In the following code, the constraints for the two suppliers are added as decimals. For example, the Saudi Arabian crude oil produces 30% gasoline and the Venezuelan crude oil produces 40% gasoline. The first half of the constraint is added as 0.3 * sa + 0.4 * vz. The second half of the constraint identifies the minimum production of 2,000 barrels of gasoline. Similar constraints are added for 1,500 barrels of jet fuel and 500 barrels of machine lubricant.

                         0.3 * sa + 0.4 * vz >= 2000,
                         0.4 * sa + 0.2 * vz >= 1500,
                         0.2 * sa + 0.3 * vz >= 500)
  13. Add the costs of the crude oils to the model. Specify that the solver should minimize the goal by setting the second parameter to GoalKind.Minimize.

    model.AddGoal("cost", GoalKind.Minimize, 20 * sa + 15 * vz)
  14. Solve the model, call the PropagateDecisions method to save the results, and then get the report.

    Dim solution As Solution = context.Solve(New SimplexDirective())
    Dim report As Report = solution.GetReport()
    Console.WriteLine("vz: {0}, sa: {1}", vz, sa)
    Console.Write("{0}", report)
  15. Press F5 to build and run the code.

    The Command window shows the following results.

    vz: 3500, sa: 2000

    ===Solver Foundation Service Report===

    Date: Date

    Version: Version

    Model Name: Default

    Capabilities Applied: LP

    Solve Time (ms): 138

    Total Time (ms): 272

    Solve Completion Status: Optimal

    Solver Selected: Microsoft.SolverFoundation.Solvers.SimplexSolver


    Simplex(TimeLimit = -1, MaximumGoalCount = -1, Arithmetic = Default, Pricing = Default, IterationLimit = -1, Algorithm = Default, Basis = Default, GetSensitivity = False)

    Algorithm: Primal

    Arithmetic: Double

    Variables: 2 -> 2 + 4

    Rows: 6 -> 4

    Nonzeros: 10

    Eliminated Slack Variables: 0

    Pricing (double): SteepestEdge

    Basis: Slack

    Pivot Count: 3

    Phase 1 Pivots: 3 + 0

    Phase 2 Pivots: 0 + 0

    Factorings: 4 + 0

    Degenerate Pivots: 0 (0.00 %)

    Branches: 0

    ===Solution Details===


    cost: 92500


    barrels_venezuela: 3500

    barrels_saudiarabia: 2000