Почему Гекко не может найти решение с учетом начальных значений переменных

#python #mathematical-optimization #gekko

Вопрос:

У меня есть проблема оптимизации, которую я пытаюсь решить с помощью Gekko. Когда я устанавливаю начальные значения для переменных со значениями возможного решения, которое удовлетворяло ограничениям, Гекко не может найти решение. Как я могу найти первопричину?

Я получаю эту ошибку:

 Error: Exception: Access Violation
At line 1341 of file MUMPS/src/dmumps_part2.F
Traceback: not available, compile with -ftrace=frame or -ftrace=full

Error: 'results.json' not found. Check above for additional error details
did not managed to solve
((1)*((d_t200_3_1-d_t100_3_1)))
 

Вот модель оптимизации, которую я запускаю

 m = GEKKO(remote=False)
m.options.MAX_ITER=1000
m.options.IMODE=3 

d_t200_3_0 = m.Var(540, name='d_t200_3_0')
d_t200_3_2 = m.Var(180, name='d_t200_3_2')
d_t200_3_1 = m.Var(360, name='d_t200_3_1')
d_t100_3_0 = m.Var(60, name='d_t100_3_0')
d_t100_3_2 = m.Var(20, name='d_t100_3_2')
d_t100_3_1 = m.Var(40, name='d_t100_3_1')
m.Equation(m.abs2(d_t100_3_0) >= 0.0)
m.Equation(200 > m.abs2(d_t100_3_0))
m.Equation(m.abs2(d_t100_3_2) >= 0.0)
m.Equation(200 > m.abs2(d_t100_3_2))
m.Equation(m.abs2(d_t100_3_1) >= 0.0)
m.Equation(200 > m.abs2(d_t100_3_1))
m.Equation(m.abs2(-1.0*m.abs2(d_t100_3_0) - -1.0*m.abs2(d_t100_3_2)) >= 0.0)
m.Equation(200 > m.abs2(-1.0*m.abs2(d_t100_3_0) - -1.0*m.abs2(d_t100_3_2)))
m.Equation(m.abs2(-1.0*m.abs2(d_t100_3_0) - -1.0*m.abs2(d_t100_3_1)) >= 0.0)
m.Equation(200 > m.abs2(-1.0*m.abs2(d_t100_3_0) - -1.0*m.abs2(d_t100_3_1)))
m.Equation(m.abs2(-1.0*m.abs2(d_t100_3_2) - -1.0*m.abs2(d_t100_3_1)) >= 0.0)
m.Equation(200 > m.abs2(-1.0*m.abs2(d_t100_3_2) - -1.0*m.abs2(d_t100_3_1)))
m.Equation(m.abs2(d_t200_3_0) >= 200.0)
m.Equation(600 > m.abs2(d_t200_3_0))
m.Equation(m.abs2(d_t200_3_2) >= 0.0)
m.Equation(200 > m.abs2(d_t200_3_2))
m.Equation(m.abs2(d_t200_3_1) >= 200.0)
m.Equation(400 > m.abs2(d_t200_3_1))
m.Equation(m.abs2(-1.0*m.abs2(d_t200_3_0) - -1.0*m.abs2(d_t200_3_2)) >= 200.0)
m.Equation(400 > m.abs2(-1.0*m.abs2(d_t200_3_0) - -1.0*m.abs2(d_t200_3_2)))
m.Equation(m.abs2(-1.0*m.abs2(d_t200_3_0) - -1.0*m.abs2(d_t200_3_1)) >= 0.0)
m.Equation(200 > m.abs2(-1.0*m.abs2(d_t200_3_0) - -1.0*m.abs2(d_t200_3_1)))
m.Equation(m.abs2(-1.0*m.abs2(d_t200_3_2) - -1.0*m.abs2(d_t200_3_1)) >= 0.0)
m.Equation(200 > m.abs2(-1.0*m.abs2(d_t200_3_2) - -1.0*m.abs2(d_t200_3_1)))

m.Obj(d_t200_3_2 - d_t100_3_2)
m.solve(debug =1, disp=True)
 

При решении этой задачи без значений инициалов я получаю решение, но иногда возникает несоответствие, т. Е. другое решение для одной и той же проблемы. Есть какие-нибудь намеки на то, почему это могло произойти? Я думал, что происходит какое-то случайное инициирование и начальное значение меняется, но, согласно документации, начальные значения по умолчанию равны 0.

Спасибо!

Просто чтобы уточнить, что я еще не нашел проблему, но если посмотреть на подмножество переменных оптимизации и соответствующие ограничения, я смогу получить результаты оптимизации. вот подмножество:

 d_t200_1_0 = m.Var(180, name='d_t200_1_0')
d_t200_1_2 = m.Var(180, name='d_t200_1_2')
d_t100_1_0 = m.Var(20, name='d_t100_1_0')
d_t100_1_2 = m.Var(20, name='d_t100_1_2')
m.Equation(m.abs2(d_t100_1_0) >= 0.0)
m.Equation(200 > m.abs2(d_t100_1_0))
m.Equation(m.abs2(d_t100_1_2) >= 0.0)
m.Equation(200 > m.abs2(d_t100_1_2))
m.Equation(m.abs2(-1.0*m.abs2(d_t100_1_0) - 1.0*m.abs2(d_t100_1_2)) >= 0.0)
m.Equation(200 > m.abs2(-1.0*m.abs2(d_t100_1_0) - 1.0*m.abs2(d_t100_1_2)))
m.Equation(m.abs2(d_t200_1_0) >= 0.0)
m.Equation(200 > m.abs2(d_t200_1_0))
m.Equation(m.abs2(d_t200_1_2) >= 0.0)
m.Equation(200 > m.abs2(d_t200_1_2))
m.Equation(m.abs2(-1.0*m.abs2(d_t200_1_0) - 1.0*m.abs2(d_t200_1_2)) >= 200.0)
m.Equation(400 > m.abs2(-1.0*m.abs2(d_t200_1_0) - 1.0*m.abs2(d_t200_1_2)))

 

Комментарии:

1. Просто чтобы уточнить, что я еще не нашел проблему, но если посмотреть на подмножество переменных оптимизации и соответствующие ограничения, я смогу получить результаты оптимизации. вот подмножество: « «

Ответ №1:

Переключение на abs3() помогает решить проблему. Кроме того, некоторые уравнения не нужны, потому что они всегда выполняются.

 from gekko import GEKKO
m = GEKKO(remote=False)
m.options.MAX_ITER=1000
m.options.IMODE=3 

d_t200_3_0 = m.Var(540, name='d_t200_3_0')
d_t200_3_2 = m.Var(180, name='d_t200_3_2')
d_t200_3_1 = m.Var(360, name='d_t200_3_1')
d_t100_3_0 = m.Var(60, name='d_t100_3_0')
d_t100_3_2 = m.Var(20, name='d_t100_3_2')
d_t100_3_1 = m.Var(40, name='d_t100_3_1')

# these equations are not needed
# all values will satisfy the equation
#m.Equation(m.abs3(d_t100_3_0) >= 0.0)
#m.Equation(m.abs3(d_t100_3_2) >= 0.0)
#m.Equation(m.abs3(d_t100_3_1) >= 0.0)
#m.Equation(m.abs3(d_t200_3_2) >= 0.0)

# reform to eliminate absolute value with simple inequalities
#m.Equation(200 > m.abs3(d_t100_3_0))
#m.Equation(200 > m.abs3(d_t100_3_2))
#m.Equation(200 > m.abs3(d_t100_3_1))
#m.Equation(200 > m.abs3(d_t200_3_2))
#m.Equation(600 > m.abs3(d_t200_3_0))
#m.Equation(400 > m.abs3(d_t200_3_1))
v = [d_t100_3_0,d_t100_3_2,d_t100_3_1,d_t200_3_2,d_t200_3_0,d_t200_3_1]
b = [200,200,200,200,600,400]
for i,vi in enumerate(v):
    vi.LOWER = -b[i]
    vi.UPPER =  b[i]

m.Equation(m.abs3(d_t200_3_0) >= 200.0)
m.Equation(m.abs3(d_t200_3_1) >= 200.0)
m.Equation(m.abs3(-1.0*m.abs3(d_t100_3_0) - -1.0*m.abs3(d_t100_3_2)) >= 0.0)
m.Equation(200 > m.abs3(-1.0*m.abs3(d_t100_3_0) - -1.0*m.abs3(d_t100_3_2)))
m.Equation(m.abs3(-1.0*m.abs3(d_t100_3_0) - -1.0*m.abs3(d_t100_3_1)) >= 0.0)
m.Equation(200 > m.abs3(-1.0*m.abs3(d_t100_3_0) - -1.0*m.abs3(d_t100_3_1)))
m.Equation(m.abs3(-1.0*m.abs3(d_t100_3_2) - -1.0*m.abs3(d_t100_3_1)) >= 0.0)
m.Equation(200 > m.abs3(-1.0*m.abs3(d_t100_3_2) - -1.0*m.abs3(d_t100_3_1)))
m.Equation(m.abs3(-1.0*m.abs3(d_t200_3_0) - -1.0*m.abs3(d_t200_3_2)) >= 200.0)
m.Equation(400 > m.abs3(-1.0*m.abs3(d_t200_3_0) - -1.0*m.abs3(d_t200_3_2)))
m.Equation(m.abs3(-1.0*m.abs3(d_t200_3_0) - -1.0*m.abs3(d_t200_3_1)) >= 0.0)
m.Equation(200 > m.abs3(-1.0*m.abs3(d_t200_3_0) - -1.0*m.abs3(d_t200_3_1)))
m.Equation(m.abs3(-1.0*m.abs3(d_t200_3_2) - -1.0*m.abs3(d_t200_3_1)) >= 0.0)
m.Equation(200 > m.abs3(-1.0*m.abs3(d_t200_3_2) - -1.0*m.abs3(d_t200_3_1)))

m.Minimize(d_t200_3_2 - d_t100_3_2)
m.solve(disp=True)
 

Это дает успешное решение.

  --------- APM Model Size ------------
 Each time step contains
   Objects      :  0
   Constants    :  0
   Variables    :  172
   Intermediates:  0
   Connections  :  0
   Equations    :  129
   Residuals    :  129
 
 Number of state variables:    172
 Number of total equations: -  128
 Number of slack variables: -  90
 ---------------------------------------
 Degrees of freedom       :    -46
 
 * Warning: DOF <= 0
 ----------------------------------------------
 Steady State Optimization with APOPT Solver
 ----------------------------------------------
Iter:     1 I:  0 Tm:      0.02 NLPi:    8 Dpth:    0 Lvs:    3 Obj: -2.00E 02 Gap:       NaN
--Integer Solution:  -2.00E 02 Lowest Leaf:  -2.00E 02 Gap:   0.00E 00
Iter:     2 I:  0 Tm:      0.02 NLPi:    1 Dpth:    1 Lvs:    3 Obj: -2.00E 02 Gap:  0.00E 00
 Successful solution
 
 ---------------------------------------------------
 Solver         :  APOPT (v1.0)
 Solution time  :  0.0469 sec
 Objective      :  -200.0000000002
 Successful solution
 ---------------------------------------------------
 

Комментарии:

1. Спасибо! это работает. какова интуиция использования abs3 вместо abs 2.Я понимаю, что e abs2 возвращает абсолютное значение с непрерывными первой и второй производными, в то время как abs3 генерирует абсолютное значение с помощью двоичного переключателя. когда имеет смысл выбирать первое, а не второе? Спасибо!

2. Форма MPCC (2) обычно не работает так хорошо, когда существуют конкурирующие цели для переменных slack. В этих случаях я рекомендую вариант (3).

3. Спасибо, Джон! Интересно, что при изменении «реформы для устранения абсолютной величины с помощью простых неравенств» обратно на исходные неравенства решатель не может найти решение. Ты знаешь, почему? в чем разница между ними двумя?

4. Слабые переменные немного сложнее решить, чем общие неравенства. Я не уверен, почему, но, скорее всего, потому, что проблему легче решить.

5. Я заметил еще одну проблему, которая может быть связана с функциями abs. взяв ваш код из этого ответа и изменив внутренний порядок этой строки: m.Уравнение(m.abs3(-1,0*m.abs3(d_t200_3_0) — -1,0*m.abs3(d_t200_3_2)) >= 200,0), в этом порядке: m.Уравнение(m.abs3(-1,0*m.abs3(d_t200_3_2) — -1,0*m.abs3(d_t200_3_0)) >>= 200,0) и проблема теперь это неразрешимо. У вас есть идеи, почему? эти уравнения эквивалентны. В последнем случае измените внешний abs3 на abs2, и проблема снова разрешима. Я не уверен, почему?