Subsets and set aliases

1,418 views
Skip to first unread message

lobianco

unread,
Apr 29, 2015, 10:41:44 AM4/29/15
to pyomo...@googlegroups.com
In GAMS you can specify either subsets and aliases with the following syntax:

Sets t Towns /  New-York, Paris, Berlin, Manila /
     ct(t) coastal towns
     lt(t) land towns
alias (i,t)

The main difference is that subsets are empty at declaration time and need to be defined - and GAMS check that the elements given are elements of the main set, while the alias keyword create a virtual set that is a reference to the main one.

What would be the equivalent in Pyomo?
Am I correct that the subset would be something like:
model.ct  = Set(model.t)
while the alias would be:
model.i   = Set(initialize = model.t)

??

In particular simply defining model.i = model.t would rise the error "Attempting to re-assign the component 't' to the same block under a different name (i)".

/Antonello

Gabriel Hackebeil

unread,
Apr 29, 2015, 11:17:34 AM4/29/15
to pyomo...@googlegroups.com
Antonello,

See descriptions below. I believe you’re looking for (2) (subset) and (4) (alias).

(1) model.ct = Set(model.t)  # model.ct is “dictionary” of sets, i.e., model.ct[i] = Set() for all i in model.t

(2) model.ct = Set(within=model.t) # model.ct is a subset of model.t, Pyomo will do the verification of this

(3) model.i = Set(initialize=model.t) # makes a copy of whatever is in model.t during the time of construction

(4) model.i = SetOf(model.t) # references whatever is in model.t at runtime (alias)

Regards,
Gabe

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

Carl Laird

unread,
Apr 29, 2015, 11:21:33 AM4/29/15
to pyomo...@googlegroups.com
Awesome description Gabe. I will ask someone to post this on the Pyomo blog.

I will also point out that Pyomo is more similar to AMPL than it is to GAMS, and there is less need for the alias construct. I will try and get an example posted in the next couple of days that illustrates this. 

Sent from my iPhone

Antonello Lobianco

unread,
Apr 29, 2015, 11:23:08 AM4/29/15
to pyomo...@googlegroups.com
Thank you both for the quick (clear) reply...
Antonello Lobianco
AgroParisTech, Laboratoire d'Economie Forestière
14 Rue Girardet - 54000 Nancy, France
Tel: +33.383396865
Email: antonello...@nancy.inra.fr
http://antonello.lobianco.org

Siirola, John D

unread,
Apr 29, 2015, 11:23:18 AM4/29/15
to pyomo...@googlegroups.com

Antonello,

 

Close.  You specify the allowable domain of a set with the within keyword. Your definition of model.ct actually creates an indexed set. The literal translation of your GAMS snippet (assuming a Concrete Model) would be:

 

model.t  = Set(doc=’Towns’, initialize=[’New-York’,’Paris’,’Berlin’,’Manila’])

model.ct = Set(doc=’coastal towns’, within=model.t)

model.lt = Set(doc=’land towns’, within=model.t)

model.i  = Set(initialize=model.t)

 

That said, you do not need to initialize aliases to sets in Pyomo.  Sets are somewhat simple containers for “plain old data”, and we do not implicitly track which set an index comes out of.  This means that it is perfectly legal (and arguably recommended) to use the same indexing set more than once in a component declaration.  That is:

 

     model.x = Var(model.t, model.t)

 

is fine.  In GAMS, they explicitly track which set an index originated from – which requires the use of aliases.  This also allows them to do stronger error checking for cases where a user inadvertently transposes the indexes (something that we unfortunately cannot currently do).

 

A final note: you might consider building sets like this in the other order (that is, from the most specific up):

 

model.ct = Set(doc=’coastal towns’, initialize=[’New-York’, ’Manila’])

model.lt = Set(doc=’land towns’, initialize=[’Paris’,’Berlin’])

model.t  = model.ct | model.lt

 

john

--

Watson, Jean-Paul

unread,
Apr 29, 2015, 11:31:09 AM4/29/15
to pyomo...@googlegroups.com
For what it’s worth – the SetOf component is not currently referenced on our online documentation…

jpw

Siirola, John D

unread,
Apr 29, 2015, 11:36:24 AM4/29/15
to pyomo...@googlegroups.com

Nor is it particularly well tested (at least according to the Jenkins coverage report).  Maybe this should go over on the developers’ list, but if it hasn’t been documented yet, then before we do, would it be more intuitive to rename it “AliasSet” or “SetAlias”???

 

john

Watson, Jean-Paul

unread,
Apr 29, 2015, 11:40:53 AM4/29/15
to pyomo...@googlegroups.com
Absolutely. SetOf sounds like “subset” to me. I like “SetAlias”.

jpw

Siirola, John D

unread,
Apr 29, 2015, 11:47:24 AM4/29/15
to pyomo...@googlegroups.com

Cool.  I do too.  It was never documented in The Book or online, so it should be “safe” to change the API.  Bill designed the set infrastructure, so if he also concurs I will start making that change on trunk.

David Woodruff

unread,
Apr 29, 2015, 11:53:36 AM4/29/15
to pyomo...@googlegroups.com
I there something special about sets that makes them need a special Alias token?  As an alternative, this could also be done by creating an Expression to make a so-called alias to reference the set, unless I am missing something.
   Dave

Siirola, John D

unread,
Apr 29, 2015, 12:01:03 PM4/29/15
to pyomo...@googlegroups.com

I don’t follow…  Is the “Expression” you are referring to the Pyomo Expression component?  The Expression component is simply a component container for an expression tree fragment – I don’t see how to use that for a Set.

 

Our Sets (with the exception of VirtualSets generated through the set operators like | and *) all own (contain copies) of the set members.  The role for SetOf (nee, SetAlias) is to have a Set object that doesn’t contain copies of the set members, but is rather somewhat “virtual” and  references data stored in some other (external) object (in this case, another Set).

Gabriel Hackebeil

unread,
Apr 29, 2015, 12:14:31 PM4/29/15
to pyomo...@googlegroups.com
Changing forums…

Before we add SetOf (or SetAlias) to the docs lets consider a lightweight wrapper around any component using weakref. Ideally my answer to the original question would be just use a builtin Python tool that’s made for this.

model.t = weakref.proxy(model.s)

But this results in the same "Attempting to re-assign the component 's' to the same block…” error.

Weakref.ref() gets around that, but the wrong reference appears on the other side of an AbstractModel construction operation:

instance.t() -> model.s

Therefore, the most robust solution at this point is

model.__dict__[‘new_name’] = model.s

But this always always prints as model.s and doesn’t become invalid if model.s get’s removed.

Surely there’s a simple (<50 line) wrapper class we could implement that get’s around the fail-to-clone construction issue, perhaps updates pprint (Hey I’m an Alias!), and yet behaves like a weak proxy to another object. Something like (untested)

Thoughts?

Gabe

Gabriel Hackebeil

unread,
Apr 29, 2015, 12:15:45 PM4/29/15
to pyomo...@googlegroups.com
Changing forums…

Actually, not changing forums…

Gabe

Watson, Jean-Paul

unread,
Apr 29, 2015, 12:17:19 PM4/29/15
to pyomo...@googlegroups.com
Excellent generalization.

Watson, Jean-Paul

unread,
Apr 29, 2015, 12:18:03 PM4/29/15
to pyomo...@googlegroups.com
And by offering this excellent idea, I’m assuming you are volunteering to implement it? :)

David Woodruff

unread,
Apr 29, 2015, 12:18:41 PM4/29/15
to pyomo...@googlegroups.com
Curses!

Well, first, thanks for the quick reply. You are totally correct. In my mind, Expression was an implementation of a macro facility, but it is not that. It is something that placated me back when I was begging for a macro facility.

But now I am now back to the question: why do we want an Alias thing for sets rather than a general macro facility that could be used to "alias" anything (and do more)?  I'm not saying there is not a good answer, I am just saying that I don't see it.
  Dave

Siirola, John D

unread,
Apr 29, 2015, 12:24:34 PM4/29/15
to pyomo...@googlegroups.com

Merging threads,  Gabe:  are you proposing what Dave is also asking for: a simple “Alias” component that behaves like whatever it is aliasing?

 

FWIW, I think there is still a use for a SetOf like thing – where you want a Set (that supports membership tests, operations, iteration, etc), but does not copy the data from some other external source (a large dict or database or something).  That was the original use of SetOf – to convert large dicts or lists into Set objects.  Using SetOf as an Alias mechanism is (I think) a bit of an abuse of Bill’s original design intent.  [but still very useful]

David Woodruff

unread,
Apr 29, 2015, 12:43:04 PM4/29/15
to pyomo...@googlegroups.com
So now this conversation is splitting into an Alias conversation and a SetOf conversation based on John's good point.

SetOf;
With respect to the (inferred) original intent of SetOf, I think John makes a very good point about the need for that functionality. It would probably benefit from a different name like ReferencedAsSet or something.

Alias:
Gabe answered my question about why one might want an alias and not a macro reference, and I really like the combination of his and JP's suggestions on the topic :)

Bill Hart

unread,
Apr 29, 2015, 8:20:28 PM4/29/15
to pyomo...@googlegroups.com
I want to chime in that John is right.  The Set() object will create a copy of the data that it is initialized with, and SetOf() will not.

It's not obvious what GAMS is doing with 'alias'.

Given the semantic confusion about SetOf(), I recommend calling this SetView().  The term 'alias' does not seem to refer to the key point of this construct:  that it manages memory differently.

--Bill

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum+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 Forum" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum+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 Forum" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum+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 Forum" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum+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 Forum" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum+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 Forum" group.

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum+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 Forum" group.

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

Bill Hart

unread,
Apr 29, 2015, 8:22:27 PM4/29/15
to pyomo...@googlegroups.com
Chiming in again ...  Note that this is semantically different from what SetOf() does today.

What is the point of creating an alias for model components?

--Bill
Changing forums…

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum+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 Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum+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 Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum+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 Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum+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 Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum+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 Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum+unsubscribe@googlegroups.com.
For more options, visi
...

David Woodruff

unread,
Apr 29, 2015, 9:39:57 PM4/29/15
to pyomo...@googlegroups.com
Bill,
  Bear in mind that Alias-type-stuff and SetView-type-stuff (SetView is a truly great name, IMO) are really separate issues as noted by John.

  To give one answer to your question (and the only answer that I know of, but maybe others have something better): It can improve readability. Here is a use case: You have a model where indexes into the nodes of a network should be called "cities" some of the time, but for other things they should be called "nodes" in the interest of clarity.

So far as I know, it is never imperative to have an alias, just sometimes handy (e.g., when cutting and pasting code from one model into another).

Dave


Changing forums…

To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum...@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 Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum...@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 Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum...@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 Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum...@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 Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum...@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 Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum...@googlegroups.com.
For more options, visi
...

--
You received this message because you are subscribed to the Google Groups "Pyomo Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyomo-forum...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages