1

かなり単純な目的関数を最小化したいのですが、Python API から CPLEX への正しい呼び出しを行う際に問題が発生しています。

私は使用方法set_quadraticset_quadratic_coefficients ここを見ましたが、それは私の問題の解決にはなりませんでした。

目的関数には一連の線形変数と一連の二次変数があります

varCoefs = [1]*(numB + numQ)
varLower = [0]*(numB + numQ)
varNames = [(x,"b%s"%x) for x in range( numB )]
varNames += [(len(varNames) + x,"q%s"%x) for x in range( numQ )]

varCoefs += [10]*len(deltas)
varLower += [1]*len(deltas)
varNames += [(len(varNames) + x,"delta%s"%x) for x in range( len(deltas) )]

varCoefs += [0]*len(target.v)
varLower += [0]*len(target.v)

sContent = [(len(varNames) + x,"s%s"%x) for x in range( len(target.v) )]
varNames += sContent

varCoefs += [-1]
varLower += [0]
varNames += [(len(varNames),'mu')]


problem.variables.add(obj = varCoefs, lb = varLower)
problem.variables.set_names(varNames)

# problem.objective.set_quadratic_coefficients([[['s%s' % x], [1]] for x in range( len(target.v) )])

problem.objective.set_quadratic(
    [cplex.SparsePair(ind=[sContent[x][0]], val=[1]) for x in range( len(target.v) )]
    )

最後の呼び出しまですべてが機能し、二次項が追加されます。その時点で、CPLEXCPLEX Error 1226: Array entry 13919 not ascending.はコマンドを無視して次のエラーを 2 回スローし、Python コードは続行します。

エラーを調べましたが、それも役に立たなかったようです。

上記を書き直して、最初に名前と下限で変数を追加してみました...そして呼び出しset_linearてからですset_quadraticが、それも役に立ちません。

ここで何が欠けていますか?

4

2 に答える 2

1

set_quadratic分離可能な二次目的関数で呼び出している場合は、 CPXXcopyqpsepに対応します。set_quadratic分離できない二次目的関数で呼び出している場合は、 CPXXcopyquadに対応します。あなたが得ているエラーは特に有用ではないことに同意しますが、Callable C Library のどこから来ているかを知っていれば、もう少し理にかなっています。

そうは言っても、スニペットを使用していくつかのダミー入力を使用した完全な例を次に示します。

import cplex

class MockTarget(object):
    pass

# Dummy data for testing

numB = 3
numQ = 3
deltas = [0.1, 0.1, 0.1]
problem = cplex.Cplex()

target = MockTarget()
target.v = [1, 2, 3]

# Build the problem

varCoefs = [1]*(numB + numQ)
varLower = [0]*(numB + numQ)
varNames = [(x,"b%s"%x) for x in range( numB )]
varNames += [(len(varNames) + x,"q%s"%x) for x in range( numQ )]

varCoefs += [10]*len(deltas)
varLower += [1]*len(deltas)
varNames += [(len(varNames) + x,"delta%s"%x) for x in range( len(deltas) )]

varCoefs += [0]*len(target.v)
varLower += [0]*len(target.v)

sContent = [(len(varNames) + x,"s%s"%x) for x in range( len(target.v) )]
varNames += sContent

varCoefs += [-1]
varLower += [0]
varNames += [(len(varNames),'mu')]


problem.variables.add(obj = varCoefs, lb = varLower)
problem.variables.set_names(varNames)

# Print without quadratic terms so you can see the progression.
problem.write('test1.lp')

# Separable Q

qsepvec = []
for tpl in varNames:
    if tpl in sContent:
        qsepvec.append(1.0)
    else:
        qsepvec.append(0.0)
print qsepvec

problem.objective.set_quadratic(qsepvec)

problem.write('test2.lp')

# Inseparable Q (overwrites previous Q)

qmat = []
for tpl in varNames:
    if tpl in sContent:
        sp = cplex.SparsePair(ind=[tpl[0]], val=[1.0])
        qmat.append(sp)
    else:
        sp = cplex.SparsePair(ind=[], val=[])
        qmat.append(sp)
print qmat

problem.objective.set_quadratic(qmat)

problem.write('test3.lp')

もう少し明確にするために、リスト内包表記を使用するのではなく、長い形式でそれを書きました。LP ファイルの内容は次のとおりです。

test1.lp:

\ENCODING=ISO-8859-1
\Problem name: 

Minimize
 obj: b0 + b1 + b2 + q0 + q1 + q2 + 10 delta0 + 10 delta1 + 10 delta2 + 0 s0
      + 0 s1 + 0 s2 - mu
Bounds
      delta0 >= 1
      delta1 >= 1
      delta2 >= 1
End

test2.lp

\ENCODING=ISO-8859-1
\Problem name: 

Minimize
 obj: b0 + b1 + b2 + q0 + q1 + q2 + 10 delta0 + 10 delta1 + 10 delta2 + 0 s0
      + 0 s1 + 0 s2 - mu + [ s0 ^2 + s1 ^2 + s2 ^2 ] / 2
Bounds
      delta0 >= 1
      delta1 >= 1
      delta2 >= 1
End

test3.lp

\ENCODING=ISO-8859-1
\Problem name: 

Minimize
 obj: b0 + b1 + b2 + q0 + q1 + q2 + 10 delta0 + 10 delta1 + 10 delta2 + 0 s0
      + 0 s1 + 0 s2 - mu + [ s0 ^2 + s1 ^2 + s2 ^2 ] / 2
Bounds
      delta0 >= 1
      delta1 >= 1
      delta2 >= 1
End

test2.lp と test3.lp が同じであることがわかります (後者は前者を上書きしますが、同じことを行います)。うまくいけば、それが少し理解しやすくなります。一般に、非常に単純な問題に対して LP を出力するこの手法を使用することは、より有用なデバッグ手法の 1 つです。

CPLEX に同梱されている Python の例も確認してください。たとえば、qpex1.py、miqpex1.py、indefqpex1.py です。

于 2016-08-15T16:39:23.673 に答える
0

最初に二次項を追加し、それらの係数を設定してから、別の呼び出しで線形項を追加することで問題を解決しました。以下を参照してください。

problem.objective.set_sense(problem.objective.sense.minimize)

varLower = [0]*len(target.v)
varNames = ["s%s"%x for x in range( len(target.v) )]

problem.variables.add(names=varNames, lb=varLower)

problem.objective.set_quadratic(
    [[[x],[1]] for x in range( len(target.v) )]
    )

varCoefs = [-1]
varLower = [0]
varNames = ['mu']


varCoefs += [1]*(numB + numQ)
varLower += [0]*(numB + numQ)
varNames += ["b%s"%x for x in range( numB )]
varNames += ["q%s"%x for x in range( numQ )]

varCoefs += [10]*len(deltas)
varLower += [1]*len(deltas)
varNames += ["delta%s"%x for x in range( len(deltas) )]

problem.variables.add(names=varNames, lb=varLower, obj=varCoefs)

ただし、なぜそれがこのように機能し、他の方法では機能しないのかを知りたいです。

于 2016-08-15T18:07:33.527 に答える