Decision variables capture the results of the optimization. In a feasible solution, the computed values for the decision variables satisfy all of the model constraints. Some of these constraints are associated with individual variables (e.g., variable bounds), while others capture relationships between variables. We'll first consider the different types of decision variables that can be added to a Gurobi model, and the implicit and explicit constraints associated with these variable types.
Before starting, we should point out one important thing about the variables in a mathematical programming model: their computed solution values will only satisfy bounds to tolerances, meaning that a variable may violate its stated bounds. Mathematical programming is fundamentally built on top of linear algebra and in particular on the numerical solution of systems of linear equations. These linear systems are solved using finite-precision arithmetic, which means that small errors are unavoidable. For some models, large errors are unavoidable too; we'll return to that topic later in this section.
The simplest and least constrained of the available variable types is the continuous variable. This variable can take any value between its lower and upper bound. In mathematical programming, the convention is that variables are non-negative unless stated otherwise, so if you don't explicitly provide bounds for a variable, you should assume that the lower bound is 0 and the upper bound is infinite.
The Gurobi APIs provides a symbolic constant to allow you to indicate
that a bound is infinite (
GRB_INFINITY in C and C++,
GRB.INFINITY in C#, Java, and Python). A variable can have an
infinite upper bound, an infinite lower bound (negative infinity), or
both. A variable with infinite upper and lower bounds is referred to
as a free variable. Any bound larger than 1e30 is treated as
As noted earlier, variables may violate their bounds by tolerances. In the case of variable bounds, the relevant tolerance value is the FeasibilityTol. You can reduce the value of this tolerance parameter, but due to numerical errors it may not be possible to achieve your desired accuracy.
General integer variables are more constrained than continuous variables. In addition to respecting the specified lower and upper bounds, integer variables also take integral values.
Due to the limitations of finite-precision arithmetic, integer variables will often take values that aren't exactly integral. The magnitude of the allowed integrality violation is controlled by the IntFeasTol parameter. You can tighten this parameter to reduce the magnitude of these integrality violations, but the cost of solving the optimization problem may increase significantly as a result.
The fact that modern computers represent integer values using 32-bit values places some restrictions on the range of an integral variable. Specifically, the largest and smallest bounds that can be placed on an integer variable are +/- 2,000,000,000. Furthermore, integer variables with infinite bounds actually have these values as their implicit bounds. A solution is not considered feasible unless all integer variables take values that satisfy these bounds.
Binary variables are the most constrained variable type that can be added to your model. A binary variable takes a value of either 0 or 1.
Again, due to the limitations of finite-precision arithmetic, binary variables will often take values that aren't exactly integral. The magnitude of the allowed integrality violation is controlled by the IntFeasTol parameter.
You can also add semi-continuous or semi-integer variables to your model. A semi-continuous variable has the property that it takes a value of 0, or a value between the specified lower and upper bounds. A semi-integer variable adds the additional restriction that the variable also take an integral value.
Again, these variables may violate these restrictions up to tolerances. In this case, the relevant tolerance is IntFeasTol (even for semi-continuous variables).