Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TranformationFactory('core.fix_discrete') doesn't work for cloned models #995

Closed
RomeoV opened this issue May 2, 2019 · 5 comments · Fixed by #996
Closed

TranformationFactory('core.fix_discrete') doesn't work for cloned models #995

RomeoV opened this issue May 2, 2019 · 5 comments · Fixed by #996

Comments

@RomeoV
Copy link
Contributor

RomeoV commented May 2, 2019

Summary

I have noticed that often times TransformationFactory('core.fix_discrete') doesn't work for a model, i.e. it doesn't actually fix the variables. I have found out that it happens to cloned models (whereas 'normal' models work as expected).

Minimal working example

from pyomo.environ import *
m = ConcreteModel()
m.y = Var(domain=Integers, bounds=(0,10), initialize=0)
m_clone = m.clone()
TransformationFactory('core.fix_discrete').apply_to(m_clone)
m_clone.pprint()

yields

1 Var Declarations
    y : Size=1, Index=None
        Key  : Lower : Value : Upper : Fixed : Stale : Domain
        None :     0 :     0 :    10 : False : False : Integers
1 Suffix Declarations
    _fixed_discrete_vars : Direction=Suffix.LOCAL, Datatype=Suffix.FLOAT
        Key  : Value
        None :    []
2 Declarations: y _fixed_discrete_vars

Notice that the variable y didn't actually get fixed. If the TranformationFactory is intead applied to model m, the behaviour is as expected.

Looking into the code

When diving into the code, the problem ends up being when the domain of the variable y is checked against a list of domains here

The expression var.domain in _discrete_relaxation_map will yield False, even though var is an Integer.

@qtothec
Copy link
Contributor

qtothec commented May 2, 2019

I think this is related to a discrepancy between is and == in the comparison due to the fact that Integer in the clone will have a different id than in the original.

@jsiirola
Copy link
Member

jsiirola commented May 2, 2019

This is a fundamental problem with the current Set system (continuous sets are not first-class Set components, and as such do not follow the block scoping rules within Block.clone())

This will be addressed by #326.

@RomeoV
Copy link
Contributor Author

RomeoV commented May 2, 2019

What can I do until #326 is fixed? It seems like it might be a while. I don't want to 'hand-code' the functionality again for cloned models.

@RomeoV
Copy link
Contributor Author

RomeoV commented May 2, 2019

I have noticed that the expression type(m.y) is type(m_clone.y) is True, so that has lead me to the following 'dirty' fix:
Replace

var.domain in _discrete_relaxation_map

with

any(type(var.domain) is type(domain) for domain in _discrete_relaxation_map)

This will be slightly slower (although not by that much), but the transformation shouldn't be critical for performance. Additionally, imo it doesn't sacrifice readibility - instead it indicates that we are looking for domains in _discrete_relaxation_map, which was not very clear before.

I can submitt a PR if you think this is acceptable (for now).

@qtothec
Copy link
Contributor

qtothec commented May 7, 2019

This issue can be seen as a consequence of #165.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants