Operators on SimpleExpression?

7 views
Skip to first unread message

Bill Hart

unread,
Dec 5, 2017, 9:21:10 AM12/5/17
to Pyomo Developers
What do you think the following code should do?

from pyomo.environ import *

model = ConcreteModel()
model.x = Var()
model.e = Expression()

model.e.expr = 3
model.e += model.x

print(model.e.expr)

Currently, this creates an erroneous expression that contains a cycle.

I think that model.e should be an expression with value "x+3".

Do you agree?  Or should we not allow operators on expression objects?

--Bill

Siirola, John D

unread,
Dec 5, 2017, 10:04:49 AM12/5/17
to pyomo-de...@googlegroups.com
To be pedantic, you are asking if:

m.e = Expression(expr=3)
m.e += m.x

Should give m.e as an Expression (capital E) containing the expression (little e) 3 + m.x, whereas it currently results in an Expression containing the expression 3 + m.e?

The current behavior is probably not what the user wanted ... a self-referential Expression is not good (walkers will recourse infinitely). To fix it, I suppose we would need to map all __i<OP>__ methods to convert things like “m.e += foo” to “m.e.expr += foo”?

John
--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-develope...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Laird, Carl Damon

unread,
Dec 5, 2017, 10:09:03 AM12/5/17
to pyomo-de...@googlegroups.com
This is a little strange since Expression (Cap E) is a Component. I don’t think we support += for any other component (at least not in a way that means the same as this). We only support this type of operation on (little e) expressions.

Maybe we should not allow this and only support model.e.expr += ?

Thoughts?

Bill Hart

unread,
Dec 5, 2017, 10:20:38 AM12/5/17
to Pyomo Developers
I'm inclined to allow += for E.  Named expressions are different from other components, and we currently allow users to use named expressions in equations.  If:

  3 + model.E

is valid, then why not

  model.E += 3?
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.

Bill Hart

unread,
Dec 5, 2017, 10:22:55 AM12/5/17
to Pyomo Developers
Yes, your example is the same as what I gave.

There's a simple fix (at least for Pyomo5).

--Bill
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.

David Woodruff

unread,
Dec 5, 2017, 10:29:36 AM12/5/17
to pyomo-de...@googlegroups.com
I have two thoughts:

-123: We should strive to capitalize Expression in sentences when appropriate (attaching "object" is probably not enough).
-122: We should not allow operators on Expression objects. If you want to build up an expression (lower case) and assign it to an Expression, do that.  In this particular case, I have to admit that reasonable people could disagree; however, I see modifying a component as a big deal, worthy of a function call and not something that should be done with operator overloading..
  Dave


David Woodruff

unread,
Dec 5, 2017, 10:34:19 AM12/5/17
to pyomo-de...@googlegroups.com
because model.E += 3 modfiies model.E and 3 + model.E does not

On Tue, Dec 5, 2017 at 7:20 AM, Bill Hart <whar...@gmail.com> wrote:
I'm inclined to allow += for E.  Named expressions are different from other components, and we currently allow users to use named expressions in equations.  If:

  3 + model.E

is valid, then why not

  model.E += 3?


On Tuesday, December 5, 2017 at 8:09:03 AM UTC-7, Laird, Carl Damon wrote:
This is a little strange since Expression (Cap E) is a Component. I don’t think we support += for any other component (at least not in a way that means the same as this). We only support this type of operation on (little e) expressions.

Maybe we should not allow this and only support model.e.expr += ?

Thoughts?

On Dec 5, 2017, at 10:04 AM, Siirola, John D <jds...@sandia.gov> wrote:

To be pedantic, you are asking if:

m.e = Expression(expr=3)
m.e += m.x

Should give m.e as an Expression (capital E) containing the expression (little e) 3 + m.x, whereas it currently results in an Expression containing the expression 3 + m.e?

The current behavior is probably not what the user wanted ... a self-referential Expression is not good (walkers will recourse infinitely). To fix it, I suppose we would need to map all __i<OP>__ methods to convert things like “m.e += foo” to “m.e.expr += foo”?

John

Laird, Carl Damon

unread,
Dec 5, 2017, 10:36:28 AM12/5/17
to pyomo-de...@googlegroups.com
-123: I agree with Woodruff. We have been pretty good about this. We have a capital E Expression component, and a little e expression object.
-122: I think I agree with Dave. We don’t allow this with other components That is, we don’t allow the following:

Model = ConcreteModel()
Model.x = Var()
Model.x += 3.

Or

Model.C = Constraint(expr=model.x + 3 >= 4)
Model.C += 3

It seems weird to me to support model.e += 3.

(I realize that Expression components are a little different than other components).
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-develope...@googlegroups.com.

Laird, Carl Damon

unread,
Dec 5, 2017, 10:37:54 AM12/5/17
to pyomo-de...@googlegroups.com
And unfortunately, in Bill’s example, he used a little “e” to be the name of the capital E Expression component :)

Michael Bynum

unread,
Dec 5, 2017, 10:39:44 AM12/5/17
to pyomo-de...@googlegroups.com
I agree with not allowing operations on Expression objects.

Michael

Siirola, John D

unread,
Dec 5, 2017, 10:45:49 AM12/5/17
to pyomo-de...@googlegroups.com
I don’t have a huge opinion as to if we want to allow it. However, one argument for supporting it is that we support:

m.e = Expression()
m.e = m.x + 3

(That is, the implicit call to set_value()).  As Dave said, “I can see how reasonable people would believe that += should also work”. 

John
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-develope...@googlegroups.com.

Bill Hart

unread,
Dec 5, 2017, 11:00:12 AM12/5/17
to Pyomo Developers
To follow-up, if we disallow the use of named expressions as numeric operators, then we are forcing them to explicitly reference the 'expr' component.  For example

m.v = Var()
m.E = Expression(expr=2*m.v)

# This would not be valid
m.EE = Expression(expr = m.E + 3)

# The user would need to do this
m.EE = Expression(expr = m.E.expr + 3)

Is this really what Mike/Dave/Carl want???

--Bill

Michael Bynum

unread,
Dec 5, 2017, 11:06:56 AM12/5/17
to pyomo-de...@googlegroups.com
Actually, maybe I am changing my mind. Isn't the purpose of Expression objects to use them in other expressions? Then you can update the Expression object and know that all the expressions that use that Expression will also be updated?

Michael

Bill Hart

unread,
Dec 5, 2017, 11:07:00 AM12/5/17
to Pyomo Developers
I think there's an important consistency design issue.  Either we treat named expressions (e.g. Expression) as numeric values, or we don't.  Suppose we have:

m.v = Var()
m.E = Expression(expr=0)

then if we allow the expression

  M.E + 3

then we should allow the expression

  M.E += 3


Currently, the numeric operations are defined within the API for NumericValue.  It's a big change to segregate the operations like __add__ from __iadd__ in that API.

--Bill

P.S.  I suppose we could throw an expression if you call __iadd__ for a named expression, but I don't see why we wouldn't want to allow in-place modifications...

Michael Bynum

unread,
Dec 5, 2017, 11:07:21 AM12/5/17
to pyomo-de...@googlegroups.com
If we don't allow operations on named Expressions, what is their purpose?

Michael Bynum

unread,
Dec 5, 2017, 11:10:12 AM12/5/17
to pyomo-de...@googlegroups.com
Oh, I clearly misunderstood what Carl and Dave were suggesting. They were only suggesting to not use +=. My bad. 


Michael Bynum

unread,
Dec 5, 2017, 11:26:53 AM12/5/17
to pyomo-de...@googlegroups.com
Sorry, why not just override Expression's __iadd__ to do 

def __iadd__(self, other):
    self.expr += other

?

Siirola, John D

unread,
Dec 5, 2017, 11:27:49 AM12/5/17
to pyomo-de...@googlegroups.com

Bill,

 

I don’t think that anyone is suggesting that _ExpressionData does not expose the normal __add__ and __radd__ methods (and mul, sub, and div) from NumericValue.  So “m.E +3” would still work.

 

The question is what to do about the __iadd__ (and imul, isub, idiv) methods.  I see two options:

 

  1. Override the __i<OP>__ implementations from NumericValus in _ExpressionData so that they raise exceptions (thereby preventing their use)
  2. Override the __i<OP>__ implementations from NumericValus in _ExpressionData so that map the operator to the _ExpressionData.expr attribute, e.g.:

 

# class _ExpressionData(NumericValue):

def __iadd__(self, val):

                self.expr += val

                return self

I think I prefer option 2…

 

[Side note: this is solely to do with Expression components and has nothing to do with the expression tree system]

 

john

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-develope...@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-develope...@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-develope...@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-develope...@googlegroups.com.

Michael Bynum

unread,
Dec 5, 2017, 11:30:48 AM12/5/17
to pyomo-de...@googlegroups.com
I agree with John's option 2.

Michael

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.

David Woodruff

unread,
Dec 5, 2017, 11:58:40 AM12/5/17
to pyomo-de...@googlegroups.com
I can't keep up with the thread...

Bill Hart

unread,
Dec 5, 2017, 1:46:17 PM12/5/17
to Pyomo Developers
John:

I agree that (2) is preferable.

There are several ways to implement this.  I've drafted this for Pyomo5, but I'll think about this some more ...

--Bill

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.

Siirola, John D

unread,
Dec 5, 2017, 1:57:30 PM12/5/17
to pyomo-de...@googlegroups.com

Bill,

 

I am confused by “several ways to implement this”.  Why would you do anything other than implementing the __i<OP>__ methods on _ExpressionData?  This shouldn’t touch the expression system at all.  IMHO, this is a bug with Expression and should be implemented as a separate PR against master that we can put together and approve pretty quickly.

 

john

 

From: pyomo-de...@googlegroups.com [mailto:pyomo-de...@googlegroups.com] On Behalf Of Bill Hart
Sent: Tuesday, December 05, 2017 11:46 AM
To: Pyomo Developers <pyomo-de...@googlegroups.com>

Subject: Re: [EXTERNAL] Re: Operators on SimpleExpression?

 

John:

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-develope...@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-develope...@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-develope...@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-develope...@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-develope...@googlegroups.com.

Bill Hart

unread,
Dec 5, 2017, 5:54:07 PM12/5/17
to Pyomo Developers
John:

I've made the change in the expr_dev branch.  I don't think it's worth doing a PR for master.  After all, this is a latent bug that we haven't seen since, well, Coopr3!

--Bill


On Tuesday, December 5, 2017 at 11:57:30 AM UTC-7, John wrote:

Bill,

 

I am confused by “several ways to implement this”.  Why would you do anything other than implementing the __i<OP>__ methods on _ExpressionData?  This shouldn’t touch the expression system at all.  IMHO, this is a bug with Expression and should be implemented as a separate PR against master that we can put together and approve pretty quickly.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Pyomo Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-developers+unsubscribe@googlegroups.com.

Gabe Hackebeil

unread,
Dec 6, 2017, 2:47:10 AM12/6/17
to pyomo-de...@googlegroups.com
Note that I tried to deal with this behavior back when Expression was added for coopr3. However, the additional overload of things like __iadd__ broke the magic constants we used for cloning detection (because there was an additional reference in the call stack), so everything would go haywire. Sounds like this shouldn’t be an issue for Pyomo5.

Gabe
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-develope...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages