Search code examples
pyomo

Why does a decision variable domain declaration not work in Pyomo v5.7 that worked with v5.6.9


I have a decision variable declaration that does not work in Pyomo 5.7 that did work in 5.6.9.

The line in question is part of building a (concrete) model:

    model.v = pe.Var(within = pe.RealSet)    #pe = pyomo.environ

This ran fine when I had Pyomo version 5.6.9, but now gives errors described below in the provided code block.

To run with 5.7 I had to drop the within statement so I am left with:

    model.v = pe.Var()

What is the reasoning for no longer supporting an explicit statement that the domain includes all reals?

When running with the original statement with Pyomo 5.7, I get this error (CPython 3.7.1 on Windows 10):

    ERROR: Constructing component 'v' from data=None failed: TypeError: __new__()
    takes 1 positional argument but 2 were given
    Traceback (most recent call last):
      File "runscript.py", line 216, in <module>
        payoff_matrix = my_matrix
      File "C:\Users\myusername\Documents\modelbuildscript.py", line 24, in __init__
        model.v = pe.Var(within = pe.RealSet)
      File "C:\EngTools\Anaconda3\2018.12\lib\site-packages\pyomo\core\base\block.py", line 543, in __setattr__
        self.add_component(name, val)
      File "C:\EngTools\Anaconda3\2018.12\lib\site-packages\pyomo\core\base\block.py", line 1081, in add_component
        val.construct(data)
      File "C:\EngTools\Anaconda3\2018.12\lib\site-packages\pyomo\core\base\var.py", line 613, in construct
        self._initialize_members((None,))
      File "C:\EngTools\Anaconda3\2018.12\lib\site-packages\pyomo\core\base\var.py", line 682, in_initialize_members
        self.domain = self._domain_init_rule(self._parent())
    TypeError: __new__() takes 1 positional argument but 2 were given

Solution

  • The short answer is that you should use

    model.v = pe.Var(within=pe.Reals)
    

    The slightly longer answer is that the Pyomo global sets (Reals, NonNegativeReals, Integers, PositiveIntegers, Binary, etc.) were originally defined using their own class hierarchy independent of the Set and RangeSet components. Unfortunately, that led to numerous problems (correctly detecting discrete sets, performing set operations using global sets, etc). Pyomo 5.7 switched to a new rewrite of the Set / RangeSet components that among numerous other bug fixes moved to a new paradigm where all sets in Pyomo were either Set or RangeSet components (even global sets). We put in a backwards compatibility layer that caught all the legacy uses of the RealSet class in the test suite, but your use case (while it worked) was not a documented / tested case. PR 1619 will restore this functionality (likely will be included in Pyomo 5.7.1), and adds an official deprecation warning for use of RealSet.