nlobj_vb.vb#

' Copyright 2026, Gurobi Optimization, LLC
'
' This example formulates and solves the following simple nonlinear model
' using the nonlinear objective API:
'
'     minimize    sin(x) * x + x^2 * y
'     subject to  x + y  >= 1
'                -1 <= x <= 2
'                 0 <= y <= 2
'
' The example is split into two functions that show two ways to build a
' nonlinear objective with the new NL API:
'
'   - nlobjNLAPI(): uses the nonlinear expression API. The nonlinear
'     objective is built as a GRBNLExpr object with the overloaded
'     operators, the nonlinear functions hosted on GRBNLExpr, and the Pow()
'     helper, and passed directly to SetNLObj().
'
'   - nlobjNLAPIAdv(): uses the advanced expression-tree variant of
'     SetNLObj(), where the nonlinear expression is described
'     with arrays of opcodes, data, and parent pointers.
'
' In both cases we retrieve the nonlinear objective with GetNLObj(),
' delete it with DelNLObj(), replace it with a simple linear objective, and
' re-optimize.


Imports System
Imports Gurobi

Class nlobj_vb
    ' Run both ways of building nonlinear objectives: the nonlinear
    ' expression API and the advanced expression-tree API.
    Shared Sub Main()
        Try
            ' First, the nonlinear expression API
            nlobjNLAPI()

            ' Then, the advanced expression-tree API
            nlobjNLAPIAdv()

        Catch e As GRBException
            Console.WriteLine("Error code: " & e.ErrorCode & ". " & e.Message)
        End Try
    End Sub

    ' nlobjNLAPI(): formulates the nonlinear objective with the nonlinear
    ' expression API, passing a GRBNLExpr object to SetNLObj().
    Shared Sub nlobjNLAPI()
        ' Create environment
        Dim env As GRBEnv = New GRBEnv("nlobj.log")

        ' Create empty model
        Dim model As GRBModel = New GRBModel(env)

        ' Create variables
        Dim x As GRBVar = model.AddVar(-1.0, 2.0, 0.0, GRB.CONTINUOUS, "x")
        Dim y As GRBVar = model.AddVar(0.0, 2.0, 0.0, GRB.CONTINUOUS, "y")

        ' Add constraint: x + y >= 1
        model.AddConstr(x + y, GRB.GREATER_EQUAL, 1.0, "c0")

        ' Add nonlinear objective: sin(x)*x + x^2*y.
        ' The nonlinear expression is built as a GRBNLExpr:
        '   GRBNLExpr.Sin(x)      -> sin(x)
        '   GRBNLExpr.Pow(x, 2.0) -> x^2 (a SQUARE node)
        model.SetNLObj(GRBNLExpr.Sin(x) * x + GRBNLExpr.Pow(x, 2.0) * y)

        ' Optimize model
        model.Optimize()

        Console.WriteLine("")
        Console.WriteLine("First solve (nonlinear objective)")
        If model.Status = GRB.Status.OPTIMAL Then
            Console.WriteLine("Optimal objective: " & model.ObjVal.ToString("E4"))
            Console.WriteLine("  x=" & x.X.ToString("F6") & _
                              ", y=" & y.X.ToString("F6"))
        Else
            Console.WriteLine("Optimization did not produce an optimal solution")
        End If

        ' Retrieve the nonlinear objective as a GRBNLExpr and print it
        Dim nlobj As GRBNLExpr = model.GetNLObj()
        Console.WriteLine("")
        Console.WriteLine("Retrieved NL objective: """ & nlobj.ToString() & """")

        ' Delete the nonlinear objective
        model.DelNLObj()
        Console.WriteLine("Deleted nonlinear objective")

        ' Set a simple linear objective instead: minimize x + y
        model.SetObjective(x + y, GRB.MINIMIZE)

        ' Re-optimize
        model.Optimize()

        Console.WriteLine("")
        Console.WriteLine("Second solve (linear objective)")
        If model.Status = GRB.Status.OPTIMAL Then
            Console.WriteLine("Optimal objective: " & model.ObjVal.ToString("E4"))
            Console.WriteLine("  x=" & x.X.ToString("F6") & _
                              ", y=" & y.X.ToString("F6"))
        Else
            Console.WriteLine("Optimization did not produce an optimal solution")
        End If

        ' Dispose of model and env
        model.Dispose()
        env.Dispose()
    End Sub

    ' nlobjNLAPIAdv(): formulates the nonlinear objective with the advanced
    ' expression-tree variant of SetNLObj(), where the nonlinear expression
    ' is described with arrays of opcodes, data, and parent pointers.
    Shared Sub nlobjNLAPIAdv()
        ' Create environment
        Dim env As GRBEnv = New GRBEnv("nlobj.log")

        ' Create empty model
        Dim model As GRBModel = New GRBModel(env)

        ' Create variables
        Dim x As GRBVar = model.AddVar(-1.0, 2.0, 0.0, GRB.CONTINUOUS, "x")
        Dim y As GRBVar = model.AddVar(0.0, 2.0, 0.0, GRB.CONTINUOUS, "y")

        ' Add constraint: x + y >= 1
        model.AddConstr(x + y, GRB.GREATER_EQUAL, 1.0, "c0")

        ' Expression tree for sin(x) * x + x^2 * y (10 nodes)
        '
        '   node 0: PLUS       (root)
        '   node 1: MULTIPLY   (child of 0)  ->  sin(x) * x
        '   node 2: SIN        (child of 1)
        '   node 3: VARIABLE x (child of 2)
        '   node 4: VARIABLE x (child of 1)
        '   node 5: MULTIPLY   (child of 0)  ->  x^2 * y
        '   node 6: POW        (child of 5)
        '   node 7: VARIABLE x (child of 6)
        '   node 8: CONSTANT 2 (child of 6)
        '   node 9: VARIABLE y (child of 5)

        Dim opcode As Integer() = New Integer() { _
            GRB.OPCODE_PLUS, _
            GRB.OPCODE_MULTIPLY, _
            GRB.OPCODE_SIN, _
            GRB.OPCODE_VARIABLE, _
            GRB.OPCODE_VARIABLE, _
            GRB.OPCODE_MULTIPLY, _
            GRB.OPCODE_POW, _
            GRB.OPCODE_VARIABLE, _
            GRB.OPCODE_CONSTANT, _
            GRB.OPCODE_VARIABLE _
        }
        Dim data As Double() = New Double() { _
            -1.0, -1.0, -1.0, _
            x.Index, _
            x.Index, _
            -1.0, -1.0, _
            x.Index, _
            2.0, _
            y.Index _
        }
        Dim parent As Integer() = New Integer() {-1, 0, 1, 2, 1, 0, 5, 6, 6, 5}

        ' Set nonlinear objective
        model.SetNLObj(opcode, data, parent)

        ' Optimize model
        model.Optimize()

        Console.WriteLine("")
        Console.WriteLine("First solve (nonlinear objective)")
        If model.Status = GRB.Status.OPTIMAL Then
            Console.WriteLine("Optimal objective: " & model.ObjVal.ToString("E4"))
            Console.WriteLine("  x=" & x.X.ToString("F6") & _
                              ", y=" & y.X.ToString("F6"))
        Else
            Console.WriteLine("Optimization did not produce an optimal solution")
        End If

        ' Retrieve the nonlinear objective and print the number of nodes
        Dim nnodes As Integer
        model.GetNLObj(nnodes, Nothing, Nothing, Nothing)
        Console.WriteLine("")
        Console.WriteLine("Retrieved NL objective with " & nnodes & " nodes")

        ' Delete the nonlinear objective
        model.DelNLObj()
        Console.WriteLine("Deleted nonlinear objective")

        ' Set a simple linear objective instead: minimize x + y
        model.SetObjective(x + y, GRB.MINIMIZE)

        ' Re-optimize
        model.Optimize()

        Console.WriteLine("")
        Console.WriteLine("Second solve (linear objective)")
        If model.Status = GRB.Status.OPTIMAL Then
            Console.WriteLine("Optimal objective: " & model.ObjVal.ToString("E4"))
            Console.WriteLine("  x=" & x.X.ToString("F6") & _
                              ", y=" & y.X.ToString("F6"))
        Else
            Console.WriteLine("Optimization did not produce an optimal solution")
        End If

        ' Dispose of model and env
        model.Dispose()
        env.Dispose()
    End Sub
End Class