Изменение тела ограничения без вычисления его значения - PullRequest
0 голосов
/ 01 июня 2019

Я программирую на python 3.6 с использованием pyomo 5.3

Я хочу изменить тело неиндексированного ограничения (в случае, если оно не в требуемом стандартном формате).Проблема в том, что значение ограничения в конкретной точке вычисляется при вычитании из тела.Тем не менее, мне требуется тело в форме функции, потому что я должен построить Objective, который является максимумом всех нелинейных ограничений, приводящих к проблеме min-max.

Я попытался установитьТело ограничения передано функции, но я получаю вывод, что атрибут не может быть установлен.Есть ли функция для установки тела ограничения?

Редактировать: Вот решение, которое я нашел:

constraint._body = ...

Я хочу использоватьэто позволяет изменить форму задачи оптимизации.

(извините за неанглийские комментарии)

Вот функции, используемые в этом примере:

  1. Первый ослабляет домены всех переменных до действительных значений.
  2. Второй создает новую модель с использованием метода эпиграфа.(Здесь я использую ._body для изменения ограничений.
def cont_relax_model_same_bounds(model_vars):
    for var in model_vars:
        if str(var.domain) in int_type:
            var.domain = Reals

def epgraph_reformulation_without_bounds(model):

    #Erstelle Epigraph-Modell
    epi_model = model.clone()
    epi_model.alpha_epi = Var(within = Reals)

    #Speichere alle nichtlinearen Restriktionen des usprünglichen Modells in einer Liste
    nonlinear_constrs = []
    for constr in model.component_objects(Constraint):
        if not (constr.body.polynomial_degree() in [0, 1]):
            nonlinear_constrs.append(constr)

    #Speichere alle nichtlinearen Restriktionen des umformulierten Modells in einer Liste
    epi_nonlinear_constrs = []
    for constr in epi_model.component_objects(Constraint):
        if not (constr.body.polynomial_degree() in [0, 1]):
            epi_nonlinear_constrs.append(constr)

    #Kontrollausgabe, ob die Restriktionen richtig in der Liste gespeichert werden        
    for k, constr in enumerate(epi_nonlinear_constrs):
        print(epi_nonlinear_constrs[k].body)

    #Formuliere die nichtlinearen Restriktionen neu
    for k, constr in enumerate(nonlinear_constrs):
        epi_nonlinear_constrs[k]._body = (nonlinear_constrs[k].body - epi_model.alpha_epi)

    epi_model.obj = Objective(expr = epi_model.alpha_epi, sense = minimize)
    return epi_model

Вот исходная модель:

model_ESH = ConcreteModel(name = "Example 1")

model_ESH.x1 = Var(bounds=(1,20), domain=Reals)
model_ESH.x2 = Var(bounds=(1,20), domain=Integers)

model_ESH.obj = Objective(expr=(-1)*model_ESH.x1-model_ESH.x2)

model_ESH.g1 = Constraint(expr=0.15*((model_ESH.x1 - 8)**2)+0.1*((model_ESH.x2 - 6)**2)+0.025*exp(model_ESH.x1)*((model_ESH.x2)**(-2))-5<=0)
model_ESH.g2 = Constraint(expr=(model_ESH.x1)**(-1) + (model_ESH.x2)**(-1) - ((model_ESH.x1)**(0.5)) * ((model_ESH.x2) ** (0.5))+4<=0)
model_ESH.l1 = Constraint(expr=2 * (model_ESH.x1) - 3 * (model_ESH.x2) -2<=0)
model_ESH.pprint()

Затем я клонирую модель и ослабляю целочисленные переменные

NLP_model = model_ESH.clone()

#Relaxiere das Problem und deaktiviere die nichtlinearen Restriktionen
#Das funktioniert schonmal

cont_relax_model_same_bounds(get_model_vars(NLP_model))
NLP_model.pprint()

2 Var Declarations
    x1 : Size=1, Index=None
        Key  : Lower : Value : Upper : Fixed : Stale : Domain
        None :     1 :  None :    20 : False :  True :  Reals
    x2 : Size=1, Index=None
        Key  : Lower : Value : Upper : Fixed : Stale : Domain
        None :     1 :  None :    20 : False :  True :  Reals

1 Objective Declarations
    obj : Size=1, Index=None, Active=True
        Key  : Active : Sense    : Expression
        None :   True : minimize :  - x1 - x2

3 Constraint Declarations
    g1 : Size=1, Index=None, Active=True
        Key  : Lower : Body                                                                             : Upper : Active
        None :  -Inf : -5 + 0.15*( -8 + x1 )**2.0 + 0.1*( -6 + x2 )**2.0 + 0.025 * exp( x1 ) * x2**-2.0 :   0.0 :   True
    g2 : Size=1, Index=None, Active=True
        Key  : Lower : Body                                        : Upper : Active
        None :  -Inf : 4 + x1**-1.0 + x2**-1.0 - x1**0.5 * x2**0.5 :   0.0 :   True
    l1 : Size=1, Index=None, Active=True
        Key  : Lower : Body             : Upper : Active
        None :  -Inf : -2 + 2*x1 - 3*x2 :   0.0 :   True

6 Declarations: x1 x2 obj g1 g2 l1

Теперь я использую свою функцию для изменения / модификации модели:

epi_model_ESH = epgraph_reformulation_without_bounds(NLP_model)
epi_model_ESH.pprint()

WARNING: Implicitly replacing the Component attribute obj (type=<class
    'pyomo.core.base.objective.SimpleObjective'>) on block Example 1 with a
    new Component (type=<class 'pyomo.core.base.objective.SimpleObjective'>).
    This is usually indicative of a modelling error. To avoid this warning,
    use block.del_component() and block.add_component().
3 Var Declarations
    alpha_epi : Size=1, Index=None
        Key  : Lower : Value : Upper : Fixed : Stale : Domain
        None :  None :  None :  None : False :  True :  Reals
    x1 : Size=1, Index=None
        Key  : Lower : Value             : Upper : Fixed : Stale : Domain
        None :     1 : 8.636750397018059 :    20 : False : False :  Reals
    x2 : Size=1, Index=None
        Key  : Lower : Value              : Upper : Fixed : Stale : Domain
        None :     1 : 12.335071455814422 :    20 : False : False :  Reals

1 Objective Declarations
    obj : Size=1, Index=None, Active=True
        Key  : Active : Sense    : Expression
        None :   True : minimize :  alpha_epi

3 Constraint Declarations
    g1 : Size=1, Index=None, Active=True
        Key  : Lower : Body                                                                                         : Upper : Active
        None :  -Inf : -5 + 0.15*( -8 + x1 )**2.0 + 0.1*( -6 + x2 )**2.0 + 0.025 * exp( x1 ) * x2**-2.0 - alpha_epi :   0.0 :   True
    g2 : Size=1, Index=None, Active=True
        Key  : Lower : Body                                                    : Upper : Active
        None :  -Inf : 4 + x1**-1.0 + x2**-1.0 - x1**0.5 * x2**0.5 - alpha_epi :   0.0 :   True
    l1 : Size=1, Index=None, Active=True
        Key  : Lower : Body             : Upper : Active
        None :  -Inf : -2 + 2*x1 - 3*x2 :   0.0 :   True

7 Declarations: x1 x2 g1 g2 l1 alpha_epi obj

Однако, если я пытаюсь использовать IPOPT для решения вновь созданной модели, я получаю следующую ошибку:

opt = SolverFactory('ipopt')
#opt.options['bonmin.algorithm'] = 'Bonmin'
print('using IPOPT')
# Set Options for solver.
#opt.options['bonmin.solution_limit'] = '1'
#opt.options['bonmin.time_limit'] = 1800
results = opt.solve(epi_model_ESH, tee = True)
results.write()

using IPOPT
ERROR: Variable 'x1' is not part of the model being written out, but appears
    in an expression used on this model.
ERROR: Variable 'x2' is not part of the model being written out, but appears
    in an expression used on this model.

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-22-dcc4023897c3> in <module>
      5 #opt.options['bonmin.solution_limit'] = '1'
      6 #opt.options['bonmin.time_limit'] = 1800
----> 7 results = opt.solve(epi_model_ESH, tee = True)
      8 results.write()

~\Anaconda3\envs\seminarorsteinss2019\lib\site-packages\pyomo\opt\base\solvers.py in solve(self, *args, **kwds)
    594             initial_time = time.time()
    595 
--> 596             self._presolve(*args, **kwds)
    597 
    598             presolve_completion_time = time.time()

~\Anaconda3\envs\seminarorsteinss2019\lib\site-packages\pyomo\opt\solver\shellcmd.py in _presolve(self, *args, **kwds)
    194         self._keepfiles = kwds.pop("keepfiles", False)
    195 
--> 196         OptSolver._presolve(self, *args, **kwds)
    197 
    198         #

~\Anaconda3\envs\seminarorsteinss2019\lib\site-packages\pyomo\opt\base\solvers.py in _presolve(self, *args, **kwds)
    691                                       self._problem_format,
    692                                       self._valid_problem_formats,
--> 693                                       **kwds)
    694             total_time = time.time() - write_start_time
    695             if self._report_timing:

~\Anaconda3\envs\seminarorsteinss2019\lib\site-packages\pyomo\opt\base\solvers.py in _convert_problem(self, args, problem_format, valid_problem_formats, **kwds)
    762                                valid_problem_formats,
    763                                self.has_capability,
--> 764                                **kwds)
    765 
    766     def _default_results_format(self, prob_format):

~\Anaconda3\envs\seminarorsteinss2019\lib\site-packages\pyomo\opt\base\convert.py in convert_problem(args, target_problem_type, valid_problem_types, has_capability, **kwds)
    108                     tmpkw = kwds
    109                     tmpkw['capabilities'] = has_capability
--> 110                     problem_files, symbol_map = converter.apply(*tmp, **tmpkw)
    111                     return problem_files, ptype, symbol_map
    112 

~\Anaconda3\envs\seminarorsteinss2019\lib\site-packages\pyomo\solvers\plugins\converter\model.py in apply(self, *args, **kwds)
    190                             format=args[1],
    191                             solver_capability=capabilities,
--> 192                             io_options=io_options)
    193                 return (problem_filename,), symbol_map_id
    194             else:

~\Anaconda3\envs\seminarorsteinss2019\lib\site-packages\pyomo\core\base\block.py in write(self, filename, format, solver_capability, io_options)
   1645                                           filename,
   1646                                           solver_capability,
-> 1647                                           io_options)
   1648         smap_id = id(smap)
   1649         if not hasattr(self, 'solutions'):

~\Anaconda3\envs\seminarorsteinss2019\lib\site-packages\pyomo\repn\plugins\ampl\ampl_.py in __call__(self, model, filename, solver_capability, io_options)
    390                     skip_trivial_constraints=skip_trivial_constraints,
    391                     file_determinism=file_determinism,
--> 392                     include_all_variable_bounds=include_all_variable_bounds)
    393 
    394         self._symbolic_solver_labels = False

~\Anaconda3\envs\seminarorsteinss2019\lib\site-packages\pyomo\repn\plugins\ampl\ampl_.py in _print_model_NL(self, model, solver_capability, show_section_timing, skip_trivial_constraints, file_determinism, include_all_variable_bounds)
    959                         ampl_repn,
    960                         list(self_varID_map[id(var)] for var in ampl_repn._linear_vars),
--> 961                         list(self_varID_map[id(var)] for var in ampl_repn._nonlinear_vars))
    962                 except KeyError as err:
    963                     self._symbolMapKeyError(err, model, self_varID_map,

~\Anaconda3\envs\seminarorsteinss2019\lib\site-packages\pyomo\repn\plugins\ampl\ampl_.py in <genexpr>(.0)
    959                         ampl_repn,
    960                         list(self_varID_map[id(var)] for var in ampl_repn._linear_vars),
--> 961                         list(self_varID_map[id(var)] for var in ampl_repn._nonlinear_vars))
    962                 except KeyError as err:
    963                     self._symbolMapKeyError(err, model, self_varID_map,

KeyError: (200822968, "Variable 'x1' is not part of the model being written out, but appears in an expression used on this model.", "Variable 'x2' is not part of the model being written out, but appears in an expression used on this model.")

В pprint () новой модели по-прежнему перечисляются x1 и x2 в качестве переменных.

Я вызвал constraint._body = ... причиной этого?

1 Ответ

0 голосов
/ 05 июня 2019

Я нашел ошибку.

В

epi_nonlinear_constrs[k]._body = (epi_nonlinear_constrs[k].body - epi_model.alpha_epi)   

Я использовал тела ограничений другой модели nonlinear_constrs[k].body вместо тех же, что и в той же модели.Следовательно, ограничения имели переменные, которые не были указаны в модели.Следовательно, сообщение об ошибке от решателя.

...