' Copyright 2025, Gurobi Optimization, LLC
'
' This example considers the following nonconvex nonlinear problem
'
' maximize 2 x + y
' subject to exp(x) + 4 sqrt(y) <= 9
' x, y >= 0
'
' We show you two approaches to solve this:
'
' 1) Use a piecewise-linear approach to handle general function
' constraints (such as exp and sqrt).
' a) Add two variables
' u = exp(x)
' v = sqrt(y)
' b) Compute points (x, u) of u = exp(x) for some step length (e.g., x
' = 0, 1e-3, 2e-3, ..., xmax) and points (y, v) of v = sqrt(y) for
' some step length (e.g., y = 0, 1e-3, 2e-3, ..., ymax). We need to
' compute xmax and ymax (which is easy for this example, but this
' does not hold in general).
' c) Use the points to add two general constraints of type
' piecewise-linear.
'
' 2) Use the Gurobis built-in general function constraints directly (EXP
' and POW). Here, we do not need to compute the points and the maximal
' possible values, which will be done internally by Gurobi. In this
' approach, we show how to "zoom in" on the optimal solution and
' tighten tolerances to improve the solution quality.
Imports System
Imports Gurobi
Class gc_pwl_func_vb
Shared Function f(u As Double) As Double
Return Math.Exp(u)
End Function
Shared Function g(u As Double) As Double
Return Math.Sqrt(u)
End Function
Shared Sub printsol(m As GRBModel, x As GRBVar, _
y As GRBVar, u As GRBVar, v As GRBVar)
Console.WriteLine("x = " & x.X & ", u = " & u.X)
Console.WriteLine("y = " & y.X & ", v = " & v.X)
Console.WriteLine("Obj = " & m.ObjVal)
' Calculate violation of exp(x) + 4 sqrt(y) <= 9
Dim vio As Double = f(x.X) + 4 * g(y.X) - 9
If vio < 0.0 Then
vio = 0.0
End If
Console.WriteLine("Vio = " & vio)
End Sub
Shared Sub Main()
Try
' Create environment
Dim env As New GRBEnv()
' Create a new m
Dim m As New GRBModel(env)
Dim lb As Double = 0.0
Dim ub As Double = GRB.INFINITY
Dim x As GRBVar = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "x")
Dim y As GRBVar = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "y")
Dim u As GRBVar = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "u")
Dim v As GRBVar = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "v")
' Set objective
m.SetObjective(2*x + y, GRB.MAXIMIZE)
' Add linear constraint
m.AddConstr(u + 4*v <= 9, "l1")
' PWL constraint approach
Dim intv As Double = 1e-3
Dim xmax As Double = Math.Log(9.0)
Dim npts As Integer = Math.Ceiling(xmax/intv) + 1
Dim xpts As Double() = new Double(npts -1) {}
Dim upts As Double() = new Double(npts -1) {}
For i As Integer = 0 To npts - 1
xpts(i) = i*intv
upts(i) = f(i*intv)
Next
Dim gc1 As GRBGenConstr = m.AddGenConstrPWL(x, u, xpts, upts, "gc1")
Dim ymax As Double = (9.0/4.0)*(9.0/4.0)
npts = Math.Ceiling(ymax/intv) + 1
Dim ypts As Double() = new Double(npts -1) {}
Dim vpts As Double() = new Double(npts -1) {}
For i As Integer = 0 To npts - 1
ypts(i) = i*intv
vpts(i) = g(i*intv)
Next
Dim gc2 As GRBGenConstr = m.AddGenConstrPWL(y, v, ypts, vpts, "gc2")
' Optimize the model and print solution
m.Optimize()
printsol(m, x, y, u, v)
' General function approach with auto PWL translation by Gurobi
m.Reset()
m.Remove(gc1)
m.Remove(gc2)
m.Update()
Dim gcf1 As GRBGenConstr = m.AddGenConstrExp(x, u, "gcf1", "")
Dim gcf2 As GRBGenConstr = m.AddGenConstrPow(y, v, 0.5, "gcf2", "")
' Use the equal piece length approach with the length = 1e-3
m.Parameters.FuncPieces = 1
m.Parameters.FuncPieceLength = 1e-3
' Optimize the model and print solution
m.Optimize()
printsol(m, x, y, u, v)
' Use optimal solution to reduce the ranges and use smaller pclen to solve
x.LB = Math.Max(x.LB, x.X-0.01)
x.UB = Math.Min(x.UB, x.X+0.01)
y.LB = Math.Max(y.LB, y.X-0.01)
y.UB = Math.Min(y.UB, y.X+0.01)
m.Update()
m.Reset()
m.Parameters.FuncPieceLength = 1e-5
' Optimize the model and print solution
m.Optimize()
printsol(m, x, y, u, v)
' Dispose of model and environment
m.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message)
End Try
End Sub
End Class