There are two primary causes of this error: trying to add a two-sided constraint, and using NumPy scalars on the left-hand side of a constraint.
Adding a two-sided constraint
In version 9.0 and later of Gurobi, you may see this error when trying to add two-sided constraints like 1 <= x <= 2 through the Python API. Adding two-sided constraints is not supported in Gurobi 9.0. Although the same syntax did not result in an error in Gurobi 8.1.1 and earlier, adding two-sided constraints was not supported and the behavior was not as expected. This is noted in the Gurobi 8.1.1 documentation here:
"Note that double inequality constraints, like 1 <= x + y <= 2 or 1 <= x[i] + y[i] <= 2 for i in range(3) are NOT supported in this API, and will result in one of the inequalities to be silently disregarded, which will result in unexpected behavior."
For example, consider the following code:
m = Model()
x = m.addVar(name="x")
m.addConstr(1 <= x <= 2, name="twosided")
In Gurobi 8.1.1, this results in the following model (in LP format):
twosided: x <= 2
Note that the constraint 1 <= x is missing. Gurobi 9.0 actively prohibits this syntax by throwing an error, preventing unexpected behavior like this. Instead, each of the two constraints can be added to the model separately:
m.addConstr(1 <= x, name="lefthandside")
m.addConstr(x <= 2, name="righthandside")
Using NumPy scalars on left-hand side of constraint
This error can also occur when using NumPy scalars (such as numpy.int32, numpy.int64, numpy.float32, or numpy.float64) on the left-hand side of a constraint. For example, the following code results in the "Constraint has no bool value" error:
import numpy as np
import gurobipy as gp
model = gp.Model()
x = model.addVar()
a = np.float64(5)
model.addConstr(a >= x) # error!
The error is a result of Python using the __ge__ (or __le__) method from the appropriate NumPy data class, which is not meant for constructing Gurobi constraint expressions.
Two possible workarounds are:
- Recast the NumPy data structure into a standard Python numeric type like int or float. In this case, the last line becomes model.addConstr(int(a) >= x).
- Rewrite the constraint so the left-hand side expression begins with a Var or LinExpr object. With this workaround, the last line becomes instead model.addConstr(x <= a).