2016-08-15 3 views
0

Я хотел бы, чтобы минимизировать целевую функцию, которая является довольно простой, но я как-то возникли проблемы делая правильные вызовы к от API Python для CPLEXЛинейные и квадратичные члены в CPLEX целевой функции

Я смотрел на то, как используйте set_quadratic и set_quadratic_coefficientshere, но это не привело к решению моей проблемы.

Моя целевая функция имеет набор линейных переменных и множество квадратичных переменных

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))] 
    ) 

Все работает до последнего вызова добавить квадратичные члены. В этот момент CPLEX дважды вызывает следующую ошибку CPLEX Error 1226: Array entry 13919 not ascending., игнорируя команду, и код Python продолжается.

Я искал error, но мне это тоже не помогло.

Я попытался переписать вышеприведенное, чтобы добавить переменные по имени и нижней границе сначала ... и затем вызвать set_linear и set_quadratic после этого, но это тоже не помогает.

Что мне здесь не хватает?

ответ

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) 

Однако мне все же хотелось бы знать, почему он работает таким образом, а не наоборот.

+1

Я считаю, что причина этого в том, что, как говорится в документации для 'set_quadratic', вы должны называть ее« списком с длиной, равной числу переменных в задаче ». – rkersh

+0

Ahhh, я пропустил это. Еще раз, спасибо. – Constantine

1

Если вы звоните set_quadratic с квадратичной функцией цели, которая является разделимой, она соответствует CPXXcopyqpsep. Если вы вызываете set_quadratic с квадратичной целевой функцией, которая неотделима, она соответствует CPXXcopyquad. Я согласен с тем, что ошибка, которую вы получаете, не особенно полезна, но это имеет немного больший смысл, если вы знаете, откуда она появилась в библиотеке Callable C.

С учетом сказанного, вот полный пример, используя свой фрагмент кода, с некоторыми фиктивных входов:

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') 

я написал, что в длинной форме, а не с помощью списковых, чтобы сделать его немного более ясно , Содержание ЛВ файлов ниже:

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 для очень простых проблем является одним из наиболее полезных методов отладки.

Вы также должны проверить примеры python, поставляемые с CPLEX. Например, qpex1.py, miqpex1.py, indefqpex1.py.

+0

Спасибо за объяснение. Однако в вашем решении есть две проблемы: test1 не содержит квадратичных терминов, test3 фактически является репликацией теста 2, так как вы фактически не передаете 'qmat' в' set_quadratic', и если вы передали 'qmat', вы бы получили та же ошибка, что и у меня. Однако я уже решил проблему по-другому. См. Решение ниже. – Constantine

+0

Я экспортировал test1.lp без каких-либо квадратичных ограничений; так что вы могли видеть прогрессию. Извините за мою ошибку в конце. Я исправлю это. – rkersh

+1

Я исправил ошибку с qmat в конце. – rkersh

Смежные вопросы