????????在新版本的 Gurobi 中,向 addConstr 這個方法中傳入一個 TempConstr 對象,在模型中就會根據這個對象生成一個約束。更重要的是:TempConstr 對象可以傳給所有addConstr系列方法,所以下面先介紹 TempConstr 對象
TempConstr?
? ? ? ??TempConstr 類的對象作為約束條件,其對象可以有以下幾種形式:
1. 線性約束:x + y <= 5
2. 帶上下界的線性約束:1 <= x + y <= 5
3. 二次約束:x * x + y * y <= 3
4. 用矩陣建立的線性約束:A @ x <= 1
5. 二次型約束:x @ Q @ x <= y @ A @ y
6. 帶絕對值的函數的約束:x == abs_(y)
7. 帶邏輯運算符的約束:x == or_(y, z)? ?或者? ?x == and_(y, z)
8. 帶最大值或最小值函數的約束:x == max_(y, z)? 或者? x == min_(y, z)
9. 借助 TempConstr 自定義的運算符 >> 作為表達式中的運算符:(x == 1) >> (y + z <= 5)
有以下幾點值得說明:
1. Gurobi 中所有關系運算符都必須帶等號,比如 <=, >=, == ,<, >, = 不合法,想要表示小于,例如 x + y < 5 這樣的嚴格不等式約束,可以引入一個很小的值??epsilon,輔助實現嚴格不等式
2. 上面說的第 7 點中,要求x,?y 和 z 都是二元變量,即在添加進模型的時候就設計為GRB.BINARY
3.?上面說的第 9?點中,(x == 1) >> (y + z <= 5) 表達的是,如果 x 為1,則 y + z 必須小于等于5,即 x 這個二元變量控制了后面的不等式約束是否存在
addConstr
Python定義:addConstr(constr, name='')
這個方法的第一個參數就是需要傳入 TempConstr 類型的對象
addConstrs
Python定義:addConstrs(generator, name='')
????????這個方法的第一個參數是 Python 語法中的生成器,也就是說可以傳入一個迭代器,通過循環就可以方便的在一行代碼中就生成多個約束,下面是這個方法使用的一些例子
m.addConstrs(x.sum(i, '*') <= capacity[i] for i in range(5))
m.addConstrs(x[i] + x[j] <= 1 for i in range(5) for j in range(5))
m.addConstrs(x[i]*x[i] + y[i]*y[i] <= 1 for i in range(5))
m.addConstrs(x.sum(i, '*') == [0, 2] for i in [1, 2, 4])
????????約束不可能憑空產生,起碼需要先添加變量,關于添加變量的方法,已經在我的另外一篇博客?addVar 和 addVars的使用?中進行了說明
????????考慮到讀者可能還不是很清楚 Gurobi 中 sum 方法的使用,這已經在我的另外一篇博客tupledict 中的 sum 方法?中進行了說明
? ? ? ? 對于第三個添加的約束,實際上是添加了一個二次約束,對于二次約束,在模型的結果上有很多與線性約束不同的地方,這寫不同點已經在我的另外一篇博客 帶二次約束的模型解構說明中進行了說明
? ? ? ? 如何建立起一個約束帶有上下界的線性優化模型?這在我的另一篇博客中Electricity Market Optimization 探索系列(一)已經進行了說明,
addQConstr
這個方法有兩個版本
版本一:addQConstr(lhs, sense=None, rhs=None, name='')
代碼示例:
model.addQConstr(x*x + y*y, GRB.LESS_EQUAL, z*z, "c0")
?版本二:使用 generator 添加約束
代碼示例:
model.addQConstr(x*x + y*y <= 2.0, "c1")
addMQConstr
Python 定義:addMQConstr(Q, c, sense, rhs, xQ_L=None, xQ_R=None, xc=None, name='')
實際上這里使用一個矩陣來定義二次約束,(注意可以不是二次型,而是帶有交叉項的二次式)
這個二次約束形如?? ??
? ??
?
其中sense是一個關系運算符,rhs是一個常數?
Q = np.full((2, 3), 1)
xL = model.addMVar(2)
xR = model.addMVar(3)
model.addMQConstr(Q, None, '<', 1.0, xL, xR)