2

私は DOCPLEX を使用して混合整数線形計画法 (MILP) 問題を構築しています。この問題は、Python で CPLEX を介して解決されます。ただし、IF-THEN 制約を使用して MILP 問題を解決しようとすると、次のエラーが表示されます。

DOcplexException: Model.if_then(), nbBus40 >= 3.0 is not discrete

これは、次のコードに示すように、nbbus40変数がContinuousであると宣言したために発生しています。

from docplex.mp.model import Model

mdl = Model(name='buses')
nbbus40 = mdl.continuous_var(name='nbBus40')
nbbus30 = mdl.integer_var(name='nbBus30')
mdl.add_constraint(nbbus40*40 + nbbus30*30 >= 300, 'kids')    
mdl.add(mdl.if_then((nbbus40>=3),(nbbus30>=7)))
mdl.minimize(nbbus40*500 + nbbus30*400)

mdl.solve()

for v in mdl.iter_integer_vars():
    print(v," = ",v.solution_value)

ただし、nbbus40変数を整数として保持すると、以下に示すように MILP 問題の解決策が得られます。

from docplex.mp.model import Model

mdl = Model(name='buses')
nbbus40 = mdl.integer_var(name='nbBus40')
nbbus30 = mdl.integer_var(name='nbBus30')
mdl.add_constraint(nbbus40*40 + nbbus30*30 >= 300, 'kids')  
mdl.add(mdl.if_then((nbbus40>=3),(nbbus30>=7)))
mdl.minimize(nbbus40*500 + nbbus30*400)

mdl.solve()

for v in mdl.iter_integer_vars():
    print(v," = ",v.solution_value)

結果:

nbBus40  =  0
nbBus30  =  10.0

連続変数に対して DOCPLEX で IF-THEN 制約を使用するにはどうすればよいですか?

4

1 に答える 1

4

ここから私の答えをコピーします:

if-then 制約に連続変数を使用することはできません。

その理由は次のとおりです。'if' 句は true または false のいずれかの値を取ることができます。これに応じて、「then」句がアクティブになるかどうかが決まります。nbBus40 が連続している場合、CPLEX は nbBus40 >= 3 と nbBus40 < 3 のケースを区別する必要があります。後者は厳密な不等式であることに注意してください。厳密な不等式は、線形計画法の理論ではサポートされていません。

nbBus40 が代わりに整数である場合、区別するケースは nbBus40 >= 3 および nbBus40 <= 2 として記述できます。これらのいずれも厳密な不等式ではありません。

これを回避する一般的な方法は、イプシロンを使用して、nbBus40 >= 3 と nbBus40 <= 3 - eps の 2 つのケースを定義することです。それも同様にサポートされます。ただし、eps は実際の式に依存する必要があるため、一般的な eps を選択する良い方法はありません。そのため、docplex はそれをユーザーに任せています。

次のように制約を記述できます。

 with Model() as m:
     nbBus40 = m.continuous_var()
     nbBus30 = m.continuous_var()
     helper = m.binary_var()

     eps = 1e-3
     m.add(m.if_then(helper == 0, nbBus40 <= 3 - eps))
     m.add(m.if_then(helper == 1, nbBus40 >= 3))
     m.add(m.if_then(helper == 1, nbBus30 >= 7))
     m.solve()

ただし、これらの eps を使用すると、数値の問題が頻繁に発生することに注意してください。したがって、連続式での if_then は避けるのが最善です。分数のバスを考慮したい理由を詳しく説明できるかもしれません。あなたが望むものを達成するための他の方法があるかもしれません.

于 2019-11-14T14:28:38.313 に答える