MIP Examples#
This section contains examples of how to use the cuOpt MIP Python API.
Note
The examples in this section are not exhaustive. They are provided to help you get started with the cuOpt mixed integer linear programming Python API. For more examples, please refer to the cuopt-examples GitHub repository.
Mixed Integer Linear Programming Example#
1# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2# SPDX-License-Identifier: Apache-2.0
3
4"""
5Mixed Integer Linear Programming Example
6
7This example demonstrates how to:
8- Create a mixed integer programming problem
9- Add integer variables with bounds
10- Add constraints with integer variables
11- Solve a MIP problem
12
13Problem:
14 Maximize: 5*x + 3*y
15 Subject to:
16 2*x + 4*y >= 230
17 3*x + 2*y <= 190
18 10 <= y <= 50
19 x, y are integers
20
21Expected Output:
22 Optimal solution found in 0.00 seconds
23 x = 36.0
24 y = 41.0
25 Objective value = 303.0
26"""
27
28from cuopt.linear_programming.problem import Problem, INTEGER, MAXIMIZE
29from cuopt.linear_programming.solver_settings import SolverSettings
30
31
32def main():
33 """Run the simple MIP example."""
34 # Create a new MIP problem
35 problem = Problem("Simple MIP")
36
37 # Add integer variables with bounds
38 x = problem.addVariable(vtype=INTEGER, name="V_x")
39 y = problem.addVariable(lb=10, ub=50, vtype=INTEGER, name="V_y")
40
41 # Add constraints
42 problem.addConstraint(2 * x + 4 * y >= 230, name="C1")
43 problem.addConstraint(3 * x + 2 * y <= 190, name="C2")
44
45 # Set objective function
46 problem.setObjective(5 * x + 3 * y, sense=MAXIMIZE)
47
48 # Configure solver settings
49 settings = SolverSettings()
50 settings.set_parameter("time_limit", 60)
51
52 # Solve the problem
53 problem.solve(settings)
54
55 # Check solution status and results
56 if problem.Status.name == "Optimal":
57 print(f"Optimal solution found in {problem.SolveTime:.2f} seconds")
58 print(f"x = {x.getValue()}")
59 print(f"y = {y.getValue()}")
60 print(f"Objective value = {problem.ObjValue}")
61 else:
62 print(f"Problem status: {problem.Status.name}")
63
64
65if __name__ == "__main__":
66 main()
The response is as follows:
Optimal solution found in 0.00 seconds
x = 36.0
y = 41.0
Objective value = 303.0
Semi-continuous Variable Example#
1# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2# SPDX-License-Identifier: Apache-2.0
3
4"""
5Semi-continuous Variable Example
6
7This example demonstrates how to:
8- Add a semi-continuous variable
9- Solve a small MIP that uses the semi-continuous domain
10
11Problem:
12 Minimize: x
13 Subject to:
14 x + y = 1
15 x is either 0 or in [5, 10]
16 0 <= y <= 1
17
18Expected Output:
19 Optimal solution found in 0.00 seconds
20 x = 0.0
21 y = 1.0
22 Objective value = 0.0
23"""
24
25from cuopt.linear_programming.problem import (
26 CONTINUOUS,
27 MINIMIZE,
28 SEMI_CONTINUOUS,
29 Problem,
30)
31from cuopt.linear_programming.solver_settings import SolverSettings
32
33
34def main():
35 """Run the semi-continuous variable example."""
36 problem = Problem("Semi-continuous")
37
38 x = problem.addVariable(lb=5.0, ub=10.0, vtype=SEMI_CONTINUOUS, name="x")
39 y = problem.addVariable(lb=0.0, ub=1.0, vtype=CONTINUOUS, name="y")
40
41 problem.addConstraint(x + y == 1.0)
42 problem.setObjective(x, sense=MINIMIZE)
43
44 settings = SolverSettings()
45 settings.set_parameter("time_limit", 10)
46
47 problem.solve(settings)
48
49 if problem.Status.name == "Optimal":
50 print(f"Optimal solution found in {problem.SolveTime:.2f} seconds")
51 print(f"x = {x.getValue()}")
52 print(f"y = {y.getValue()}")
53 print(f"Objective value = {problem.ObjValue}")
54 else:
55 print(f"Problem status: {problem.Status.name}")
56
57
58if __name__ == "__main__":
59 main()
The response is as follows:
Optimal solution found in 0.00 seconds
x = 0.0
y = 1.0
Objective value = 0.0
Working with Incumbent Solutions#
Incumbent solutions are intermediate feasible solutions found during the MIP solving process. They represent the best integer-feasible solution discovered so far and can be accessed through callback functions.
Note
Incumbent solutions are only available for Mixed Integer Programming (MIP) problems, not for pure Linear Programming (LP) problems.
incumbent_solutions_example.py
1# SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2# SPDX-License-Identifier: Apache-2.0
3
4"""
5Working with Incumbent Solutions Example
6
7This example demonstrates:
8- Using callbacks to receive intermediate solutions during MIP solving
9- Using Problem.getIncumbentValues() to extract variable values from
10 incumbent solutions
11- Tracking solution progress as the solver improves the solution
12- Accessing incumbent (best so far) solutions before final optimum
13- Custom callback class implementation
14
15Incumbent solutions are intermediate feasible solutions found during the MIP
16solving process. They represent the best integer-feasible solution discovered
17so far.
18
19Note:
20 Incumbent solutions are only available for Mixed Integer Programming (MIP)
21 problems, not for pure Linear Programming (LP) problems.
22
23Problem:
24 Maximize: 5*x + 3*y
25 Subject to:
26 2*x + 4*y >= 230
27 3*x + 2*y <= 190
28 x, y are integers
29
30Expected Output:
31 Incumbent 1: x=36.0, y=41.0, cost: 303.00
32
33 === Final Results ===
34 Problem status: Optimal
35 Solve time: 0.27 seconds
36 Final solution: x=36.0, y=41.0
37 Final objective value: 303.00
38"""
39
40from cuopt.linear_programming.problem import Problem, INTEGER, MAXIMIZE
41from cuopt.linear_programming.solver_settings import SolverSettings
42from cuopt.linear_programming.solver.solver_parameters import CUOPT_TIME_LIMIT
43from cuopt.linear_programming.internals import GetSolutionCallback
44
45
46class IncumbentCallback(GetSolutionCallback):
47 """Callback to receive and track incumbent solutions during solving.
48
49 Uses Problem.getIncumbentValues() to extract variable values from the
50 raw incumbent solution array.
51 """
52
53 def __init__(self, problem, variables, user_data):
54 super().__init__()
55 self.problem = problem
56 self.variables = variables
57 self.solutions = []
58 self.n_callbacks = 0
59 self.user_data = user_data
60
61 def get_solution(self, solution, solution_cost, solution_bound, user_data):
62 """Called whenever the solver finds a new incumbent solution."""
63 assert user_data is self.user_data
64 self.n_callbacks += 1
65
66 # Use getIncumbentValues to extract values for specific variables
67 values = self.problem.getIncumbentValues(solution, self.variables)
68
69 incumbent = {
70 "values": values,
71 "cost": float(solution_cost[0]),
72 "bound": float(solution_bound[0]),
73 "iteration": self.n_callbacks,
74 }
75 self.solutions.append(incumbent)
76
77 print(f"Incumbent {self.n_callbacks}:", end=" ")
78 for i, var in enumerate(self.variables):
79 print(f"{var.VariableName}={values[i]}", end=" ")
80 print(f"cost: {incumbent['cost']:.2f}")
81
82
83def main():
84 """Run the incumbent solutions example."""
85 problem = Problem("Incumbent Example")
86
87 # Add integer variables
88 x = problem.addVariable(vtype=INTEGER, name="x")
89 y = problem.addVariable(vtype=INTEGER, name="y")
90
91 # Add constraints
92 problem.addConstraint(2 * x + 4 * y >= 230)
93 problem.addConstraint(3 * x + 2 * y <= 190)
94
95 # Set objective to maximize
96 problem.setObjective(5 * x + 3 * y, sense=MAXIMIZE)
97
98 # Configure solver settings with callback
99 settings = SolverSettings()
100 user_data = {"source": "incumbent_solutions_example"}
101 incumbent_callback = IncumbentCallback(problem, [x, y], user_data)
102 settings.set_mip_callback(incumbent_callback, user_data)
103 settings.set_parameter(CUOPT_TIME_LIMIT, 30)
104
105 # Solve the problem
106 problem.solve(settings)
107
108 # Display final results
109 print("\n=== Final Results ===")
110 print(f"Problem status: {problem.Status.name}")
111 print(f"Solve time: {problem.SolveTime:.2f} seconds")
112 print("Final solution: ", end=" ")
113 for i, var in enumerate(problem.getVariables()):
114 print(f"{var.VariableName}={var.getValue()} ", end=" ")
115 print(f"\nFinal objective value: {problem.ObjValue:.2f}")
116
117 print(
118 f"\nTotal incumbent solutions found: "
119 f"{len(incumbent_callback.solutions)}"
120 )
121
122
123if __name__ == "__main__":
124 main()
The response is as follows:
Optimal solution found.
Incumbent 1: x=36.0 y=41.0 cost: 303.00
Solution objective: 303.000000 , relative_mip_gap 0.000000 solution_bound 303.000000 presolve_time 0.103659 total_solve_time 0.173678 max constraint violation 0.000000 max int violation 0.000000 max var bounds violation 0.000000 nodes 0 simplex_iterations 2
=== Final Results ===
Problem status: Optimal
Solve time: 0.17 seconds
Final solution: x=36.0 y=41.0
Final objective value: 303.00
Total incumbent solutions found: 1