Pyomo - неявное преобразование числового значения pyomo в целое число

Я пытаюсь оптимизировать абстрактную модель pyomo (m). Модель имеет (целочисленный) параметр с именем a. Я хочу вычислить другое целочисленное значение при построении модели. Пусть другая переменная будет c = a*(a-1)/2. И я хочу массив бинарных переменных размером c Для этого я пишу следующие строки -

#File - test.py#
from pyomo.environ import *
m = AbstractModel()
m.a = Param()
c = m.a*(m.a-1)/2
m.var = Var(range(1,c), within=Binary)
m.obj = Objective(expr = 0)

#File - data.dat#
param a := 5 ;

Чтобы решить эту проблему, я побежал - pyomo solve test.py data.dat --solver=glpk

После запуска я получаю следующую ошибку:

Implicit conversion of Pyomo NumericValue type `<class 
'pyomo.core.kernel.expr_coopr3._ProductExpression'>' to an integer 
is disabled. This error is often the result of using Pyomo components as 
arguments to one of the Python built-in math 
module functions when defining expressions. Avoid this error by using Pyomo-
provided math functions.

Я думаю, что ошибка возникает, когда я пытаюсь взять range(1,c). Поправьте меня, если я ошибаюсь.

У меня Python 2.7.12, Pyomo-5.3 (CPython-2.7.12 в Linux). Мне придется спросить у кого-нибудь метод установки, так как я его установил, так что это может занять время. Я обновлю метод установки, как только спрошу человека, который его установил.

Спасибо.


person Curious Iitian    schedule 19.02.2018    source источник
comment
В вашем примере не возникает никаких ошибок при использовании ни основного, ни текущего выпуска (5.3). Предоставьте следующую основную информацию: платформа, интерпретатор и версия Python, версия pyomo, метод установки и (минимальный) пример, демонстрирующий ошибку.   -  person jsiirola    schedule 20.02.2018
comment
Пожалуйста, взгляните на изменения @jsiirola. Спасибо   -  person Curious Iitian    schedule 21.02.2018
comment
Ваш пример по-прежнему не вызывает ошибку, о которой вы сообщаете. Это было бы проще с полным примером (например, как вы объявляете m.a?), полной ошибкой (ваша (что-то здесь) действительно полезная информация!), платформой, интерпретатором и версией Python, версия pyomo и метод установки.   -  person jsiirola    schedule 21.02.2018
comment
Спасибо за ваше терпение @jsiirola. Пожалуйста, взгляните на обновленный вопрос. Я попытался ответить на ваши вопросы.   -  person Curious Iitian    schedule 21.02.2018


Ответы (1)


Здесь происходит две вещи:

  1. Вы оцениваете параметр до его определения.
  2. Вы неявно приводите выражение Pyomo к целому числу.

Корень проблемы в том, что вы рассматриваете абстрактную модель так, как если бы она была конкретной моделью. Для абстрактных моделей при объявлении m.a вы только объявляете существование параметра a. Затем Python продолжает анализировать и выполнять остальную часть вашей модели. Когда он достигает c = m.a*(m.a-1)/2, Python генерирует дерево выражений Pyomo, представляющее правую часть. Наконец, когда дело доходит до m.var = Var(range(1,c), within=Binary), Python сначала выполняет range(1,c) перед вызовом конструктора Var(). range (функция Python) приводит свои аргументы к int перед созданием списка диапазонов. Именно это приведение и вызывает ошибку.

Вы можете обойти эту ошибку, явно оценив значение выражения (c) с помощью функции (Pyomo) value(c). Однако это вызовет другую (возможно, более информативную) ошибку, связанную с тем, что вы оцениваете параметр a до его создания. Это связано с тем, что на данный момент модель все еще абстрактна, а файл данных, содержащий значение для a, еще даже не прочитан.

Решение состоит в том, чтобы создать явный Pyomo Set, который будет выступать в качестве заполнителя для выражения и не будет создаваться до тех пор, пока не будет построена остальная часть модели (то есть вычисление выражения c откладывается). пока значение для a не будет доступно). Например:

from pyomo.environ import *
m = AbstractModel()
m.a = Param()
c = m.a*(m.a-1)/2
# Note that RangeSet includes the upper bound, whereas range stops one short
m.IDX = RangeSet(1,c-1) 
m.var = Var(m.IDX, within=Binary)
m.obj = Objective(expr = 0)
person jsiirola    schedule 21.02.2018