Matthias,
The recursive approach to Abstract model construction is actually intriguing. I do not see an obvious argument against supporting it, apart from a couple trivially-manageable ones. The biggest is that CPython supports only a rather shallow stack, so people who heavily rely on the recursion (think, writing your model in reverse order) could run across a stack overflow. Similarly, unless you keep / manage the recursion stack yourself (or switch the Component constructed flag from a binary to a three state indicator), circular references would result in infinite recursion (until blowing the Python maximum stack depth). You would also need some form of a global data portal object so that implicitly constructed components could find their data.
From a procedural programming standpoint, it still makes me uneasy (it flies in the face of most declarative programming models) – but I concede that this may come from spending too much time writing procedural code.
The best path forward from here is to file an enhancement ticket in the project Trac site. I don’t think that we will be implementing it anytime soon (you will see that we have a large backlog of other things we want to do). That said, we certainly welcome patches (especially when they come with unit tests!) and folks who want to become more involved with Pyomo development. :)
john
You received this message because you are subscribed to a topic in the Google Groups "Pyomo Forum" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/pyomo-forum/dLbD2ly_hZo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to pyomo-forum...@googlegroups.com.
Matthias,
Final notes (mostly so that it is captured somewhere in the archives):
- The stack depth is the function call depth. When we construct a component, the component’s construct() generally calls a helper function that iterates over the indices calling the individual rules. Within a rule, you can have a number of function calls related to operator overloading (this is how we build up the expression trees). Finally within that, there will be a call to the Var/whatnot’s __getitem__ method. It is at this point that we can realize that the Var is not constructed and call its constructor – likely with a helper function. So, it is not unreasonable to assume you could get O(10) function calls on the stack each time you recurse back one component.
- I was thinking to convert the “_constructed” flag to be a 3-state variable (maybe None, False, True) and not add another class attribute. False might indicate ‘not constructed’, None could indicate ‘constructing’ and True would be ‘constructed’. If you do it correctly, you can leave most of the existing tests for constructed the same (they should all use “if not self._constructed” – and False and None will both map to logical False).