Skip to content

Address AttributeError raised when Constraint with SumExpression is declared after replace_expressions #2673

Open
@shermanjasonaf

Description

@shermanjasonaf

Summary

In event a Constraint expression contains a SumExpression obtained through the core.util.replace_expressions function, an AttributeError may be raised, as it appears that the args attribute of a sum expression is set to a tuple rather than a list.

Steps to reproduce the issue

import pyomo.environ as pyo
from pyomo.core.expr.visitor import replace_expressions

m = pyo.ConcreteModel()

m.p = pyo.Param(range(3), initialize=1, mutable=True)

m.x = pyo.Var()
m.v = pyo.Var(range(3), initialize=1)

# note: the lower bound is a SumExpression here
m.c = pyo.Constraint(expr=2 + 3 * m.p[2] == m.x)

lower_expr = replace_expressions(m.c.lower, {id(m.p[2]): m.v[2]})
body_expr = replace_expressions(m.c.body, {id(m.p[2]): m.v[2]})

# build constraint with v[2] substituted for p[2].
# causes error, as the `args` attribute of a SumExpression
# somewhere is a tuple (not list)
m.c2 = pyo.Constraint(expr=lower_expr == body_expr)

Error Message

$
ERROR: Rule failed when generating expression for Constraint c2 with index
    None: AttributeError: 'tuple' object has no attribute 'append'
ERROR: Constructing component 'c2' from data=None failed: AttributeError:
    'tuple' object has no attribute 'append'
Traceback (most recent call last):
  File "/home/jasherma/Documents/vim_example/pyomo_features_examples/test_err_constraint_add.py", line 34, in <module>
    m.c2 = pyo.Constraint(expr=lower_expr == body_expr)
  File "/home/jasherma/Documents/cmu/phd-project/pyomo_repo/pyomo/pyomo/core/base/block.py", line 649, in __setattr__
    self.add_component(name, val)
  File "/home/jasherma/Documents/cmu/phd-project/pyomo_repo/pyomo/pyomo/core/base/block.py", line 1219, in add_component
    val.construct(data)
  File "/home/jasherma/Documents/cmu/phd-project/pyomo_repo/pyomo/pyomo/core/base/disable_methods.py", line 116, in construct
    return base.construct(self, data)
  File "/home/jasherma/Documents/cmu/phd-project/pyomo_repo/pyomo/pyomo/core/base/constraint.py", line 763, in construct
    self._setitem_when_not_present(index, rule(block, index))
  File "/home/jasherma/Documents/cmu/phd-project/pyomo_repo/pyomo/pyomo/core/base/indexed_component.py", line 1005, in _setitem_when_not_present
    obj.set_value(value)
  File "/home/jasherma/Documents/cmu/phd-project/pyomo_repo/pyomo/pyomo/core/base/constraint.py", line 922, in set_value
    return super(ScalarConstraint, self).set_value(expr)
  File "/home/jasherma/Documents/cmu/phd-project/pyomo_repo/pyomo/pyomo/core/base/constraint.py", line 589, in set_value
    self._body = args[0] - args[1]
  File "/home/jasherma/Documents/cmu/phd-project/pyomo_repo/pyomo/pyomo/core/expr/numvalue.py", line 673, in __sub__
    return _generate_sum_expression(_sub,self,other)
  File "/home/jasherma/Documents/cmu/phd-project/pyomo_repo/pyomo/pyomo/core/expr/numeric_expr.py", line 1335, in _generate_sum_expression
    return _self.add(-_other)
  File "/home/jasherma/Documents/cmu/phd-project/pyomo_repo/pyomo/pyomo/core/expr/numeric_expr.py", line 642, in add
    self._args_.append(new_arg)
AttributeError: 'tuple' object has no attribute 'append'

Information on your system

Pyomo version: 6.4.3dev0
Python version: 3.9.13
Operating system: Ubuntu 20.04
How Pyomo was installed (PyPI, conda, source): source
Solver (if applicable): N/A

Additional information

  • This exception is also raised in the event the expression is added to a ConstraintList (such as through ConstraintList.add). The PyROS solver (contrib.pyros) adds constraints to subproblems of two-stage RO models in this way. So PyROS users may be affected.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions