ortools系列-整數規劃
有一些問題,要求一些但不是全部變數約束為整數,這類問題可以用混合整數規劃(mip)來解決,混合整數規劃也稱為混合整數線性規劃(milp)。這裡有幾個例子:
or-tools提供了幾種方法求解此類問題:
其中前兩個是一般性的求解器,能解決任何整數規劃問題,最後乙個最小成本流求解器用於求解那些能建模成網路流的問題,對於這類特殊問題,最小成本流求解器比一般的整數規劃和約束規劃要快的多。
ortools提供乙個混合整數規劃的介面用於呼叫不同的求解器,ortools內建了coin-or branch and cut (cbc)
,當然你也可以使用第三方的求解器,比如scip
,glpk
,gurobi
。cbc是乙個開源的混合整數規劃求解器,用c++開發。
我們看下面這個問題:
問題的解空間如下:
我們看ortools是如何解決這個問題的。
from ortools.linear_solver import pywraplp
def main():
# 首先,呼叫cbc求解器
# 還記得我們在lp問題中呼叫的求解器嗎,
# 是 pywraplp.solver.glop_linear_programming
solver = pywraplp.solver('solveintegerproblem',
pywraplp.solver.cbc_mixed_integer_programming)
# 和lp問題一樣,定義變數 x,y 並指定其定義域
# 這裡需要注意,我們定義的是int型別的變數
x = solver.intvar(0.0, solver.infinity(), 'x')
y = solver.intvar(0.0, solver.infinity(), 'y')
# 新增約束,方法和lp一樣,通過制定係數來新增約束
# 如果能像cp-sat那麼方便就好了
# x + 7 * y <= 17.5
constraint1 = solver.constraint(-solver.infinity(), 17.5)
constraint1.setcoefficient(x, 1)
constraint1.setcoefficient(y, 7)
# 新增約束
# x <= 3.5
constraint2 = solver.constraint(-solver.infinity(), 3.5)
constraint2.setcoefficient(x, 1)
constraint2.setcoefficient(y, 0)
# 定義目標函式
# maximize x + 10 * y.
objective = solver.objective()
objective.setcoefficient(x, 1)
objective.setcoefficient(y, 10)
objective.setmaximization()
# 求解問題,並列印結果,後面的**就很簡單了
result_status = solver.solve()
# the problem has an optimal solution.
assert result_status == pywraplp.solver.optimal
# the solution looks legit (when using solvers other than
# glop_linear_programming, verifying the solution is highly recommended!).
assert solver.verifysolution(1e-7, true)
print('number of variables =', solver.numvariables())
print('number of constraints =', solver.numconstraints())
# the objective value of the solution.
print('optimal objective value = %d' % solver.objective().value())
print()
# the value of each variable in the solution.
variable_list = [x, y]
for variable in variable_list:
print('%s = %d' % (variable.name(), variable.solution_value()))
if __name__ == '__main__':
main()
# 結果
number of variables = 2
number of constraints = 2
optimal objective value = 23
x = 3
y = 2
通過**可以看到,其實和lp問題基本一樣,思路是很清晰,就是囉嗦呢。
前面我們講了cbc解mip的問題。約束規劃是一種有別於經典優化理論的優化方法。cp的基礎是可行性(尋找問題的可行解),側重於約束和變數,而不是目標函式。對於許多態別的問題,cp可以比mip求解器更快地找到最優解。
那我們應該如何選擇cp還是mip呢。
對於乙個可行點必須滿足所有約束的標準整數規劃問題,mip求解器速度更快。在這種情況下,可行集是凸的:對於集合中的任意兩點,連線它們的線段完全位於集合中。
另一方面,對於高度非凸可行集的問題,cp-sat求解器通常比mip求解器快。當可行集由許多由or連線的約束定義時,就會出現這樣的問題,or意味著乙個點只需要滿足其中乙個約束就可以是可行的。
為了提高計算速度,cp-sat求解器和原始cp求解器都對整數進行運算。要解決某些約束具有非整數項的問題,必須首先將這些約束轉換為乙個足夠大的整數。下面的示例說明了這一點。
我們來看**:
from ortools.sat.python import cp_model
def main():
# 首先是建立模型
model = cp_model.cpmodel()
# 定義變數,指定變數的範圍
# 根據題目可以知道,x,y,z 的最大值肯定不超過50
# var_upper_bound 相當於減少了搜尋空間範圍
# 注意,我們這裡定義的是整數變數
var_upper_bound = max(50, 45, 37)
x = model.newintvar(0, var_upper_bound, 'x')
y = model.newintvar(0, var_upper_bound, 'y')
z = model.newintvar(0, var_upper_bound, 'z')
# 新增約束
# 注意到,我們第乙個約束條件是 x + 7⁄2 y + 3⁄2 z ≤ 25
# 但是 cp-sat 只能處理整數問題,所以需要對第乙個約束處理,使得係數全部是整數
# 方法很簡單,左邊右邊都乘以2就可以了
model.add(2 * x + 7 * y + 3 * z <= 50)
# 新增第二個約束
model.add(3 * x - 5 * y + 7 * z <= 45)
# 新增第三個約束
model.add(5 * x + 2 * y - 6 * z <= 37)
# 定義目標函式
model.maximize(2 * x + 2 * y + 3 * z)
# 求解並列印結果
solver = cp_model.cpsolver()
status = solver.solve(model)
if status == cp_model.optimal:
print('maximum of objective function: %i' % solver.objectivevalue())
print()
print('x value: ', solver.value(x))
print('y value: ', solver.value(y))
print('z value: ', solver.value(z))
if __name__ == '__main__':
main()
# 結果
maximum of objective function: 35
x value: 7
y value: 3
z value: 5
看起來也不複雜呢,因為我們的例子也不複雜啊,現實生活中的大部分問題都是大規模整數規劃問題,說不定跑半天都沒出結構。
ortools的文件中還是乙個例子,是用 original-cp 來求解上面的問題,和之前一樣的套路,感興趣的同學可以看看。
大家看完記得關注點贊.
master蘇.
線性規劃,整數規劃,非線性規劃,二次規劃
tx。約束條件一般有如下形式。對應的函式形式linprog c,a,b 它的返回值是向量x 的值 可轉化為線性規劃的問題 形如min x1 x2 x3 xn s.t.ax b 其中 x x1 xn t 要把上面的問題變換成線性規劃問題,只要注意到事實 對任意的xi 存在 ui vi 0 滿足 xi ...
非線性規劃
1.基本形式和求解模式。2.掌握凸函式和凸規劃的概念及性質。3.掌握0.618法。4.無約束優化的最優性質,熟練運用最速下降法和共軛方法。約束最優化的性質,懲罰函式。minf x s.t gi x 0 i 1,2,ph j x 0,j 1,2 q可行域為 x x r n gi x 0,i 1,2,p...
Matlab非線性規劃
在matlab非線性規劃數學模型可以寫成一下形式 minf x s.t.begin ax le b aeq x beq c x le 0 ceq x 0 end f x 為目標函式,a,b,aeq,beq為線性約束對應的矩陣和向量,c x ceq x 為非線性約束。matlab求解命令為 x fmi...