Skip to content

Commit

Permalink
Merge branch 'main' into add_grey_box
Browse files Browse the repository at this point in the history
  • Loading branch information
ZedongPeng committed Sep 8, 2023
2 parents ec05a3d + 0e0f0cd commit 5048b42
Show file tree
Hide file tree
Showing 21 changed files with 492 additions and 246 deletions.
2 changes: 1 addition & 1 deletion examples/doc/samples/case_studies/network_flow/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def supplyDemandRule(nn, model):
model.supplyDemand = Constraint(model.places, rule=supplyDemandRule)
}}}

What we did was just construct a few additional variables; this wasn't required but makes reading and understanding the code much, much simpler. The variable "amountIn" looks at each route to find ones that end in this location, then adds the amount on each of those routes together to determine how much flows to each location. The "amountOut" variable functions similarly for the flow out. Then we just create an "input" and "output" and ensure they're equal. Like in some of the previous constraints, we feed the set of places into the constraint as an arguement so it will index over that set, and thus this rule functions for all the places in our network.
What we did was just construct a few additional variables; this wasn't required but makes reading and understanding the code much, much simpler. The variable "amountIn" looks at each route to find ones that end in this location, then adds the amount on each of those routes together to determine how much flows to each location. The "amountOut" variable functions similarly for the flow out. Then we just create an "input" and "output" and ensure they're equal. Like in some of the previous constraints, we feed the set of places into the constraint as an argument so it will index over that set, and thus this rule functions for all the places in our network.

We have now finished creating the model. Save this as a .py file before continuing.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ \subsection*{Build the model}
model.supplyDemand = Constraint(model.places, rule=supplyDemandRule)
\end{verbatim}

What we did was just construct a few additional variables; this wasn't required but makes reading and understanding the code much, much simpler. The variable ``amountIn'' looks at each route to find ones that end in this location, then adds the amount on each of those routes together to determine how much flows to each location. The ``amountOut'' variable functions similarly for the flow out. Then we just create an ``input'' and ``output'' and ensure they're equal. As in some of the previous constraints, we feed the set of places into the constraint as an arguement so it will index over that set, and thus this rule functions for all the places in our network.
What we did was just construct a few additional variables; this wasn't required but makes reading and understanding the code much, much simpler. The variable ``amountIn'' looks at each route to find ones that end in this location, then adds the amount on each of those routes together to determine how much flows to each location. The ``amountOut'' variable functions similarly for the flow out. Then we just create an ``input'' and ``output'' and ensure they're equal. As in some of the previous constraints, we feed the set of places into the constraint as an argument so it will index over that set, and thus this rule functions for all the places in our network.

We have now finished creating the model. Save this as a .py file before continuing.

Expand Down
2 changes: 1 addition & 1 deletion pyomo/common/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2019,7 +2019,7 @@ def generate_documentation(
)
if item_body is not None:
deprecation_warning(
f"Overriding 'item_body' by passing strings to "
"Overriding 'item_body' by passing strings to "
"generate_documentation is deprecated. Create an instance of a "
"StringConfigFormatter and pass it as the 'format' argument.",
version='6.6.0',
Expand Down
2 changes: 1 addition & 1 deletion pyomo/contrib/pynumero/interfaces/pyomo_grey_box_nlp.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from pyomo.contrib.pynumero.interfaces.nlp_projections import ProjectedNLP


# Todo: make some of the numpy arise not writable from __init__
# Todo: make some of the numpy arrays not writable from __init__
class PyomoNLPWithGreyBoxBlocks(NLP):
def __init__(self, pyomo_model):
super(PyomoNLPWithGreyBoxBlocks, self).__init__()
Expand Down
79 changes: 79 additions & 0 deletions pyomo/core/base/suffix.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,3 +521,82 @@ def __eq__(self, other):
def __ne__(self, other):
"""Not implemented."""
raise NotImplementedError("Suffix components are not comparable")


class SuffixFinder(object):
def __init__(self, name, default=None):
"""This provides an efficient utility for finding suffix values on a
(hierarchical) Pyomo model.
Parameters
----------
name: str
Name of Suffix to search for.
default:
Default value to return from `.find()` if no matching Suffix
is found.
"""
self.name = name
self.default = default
self._suffixes_by_block = ComponentMap({None: []})
self.all_suffixes = []

def find(self, component_data):
"""Find suffix value for a given component data object in model tree
Suffixes are searched by traversing the model hierarchy in three passes:
1. Search for a Suffix matching the specific component_data,
starting at the `root` and descending down the tree to
the component_data. Return the first match found.
2. Search for a Suffix matching the component_data's container,
starting at the `root` and descending down the tree to
the component_data. Return the first match found.
3. Search for a Suffix with key `None`, starting from the
component_data and working up the tree to the `root`.
Return the first match found.
4. Return the default value
Parameters
----------
component_data: ComponentDataBase
Component or component data object to find suffix value for.
Returns
-------
The value for Suffix associated with component data if found, else None.
"""
# Walk parent tree and search for suffixes
suffixes = self._get_suffix_list(component_data.parent_block())
# Pass 1: look for the component_data, working root to leaf
for s in suffixes:
if component_data in s:
return s[component_data]
# Pass 2: look for the component container, working root to leaf
parent_comp = component_data.parent_component()
if parent_comp is not component_data:
for s in suffixes:
if parent_comp in s:
return s[parent_comp]
# Pass 3: look for None, working leaf to root
for s in reversed(suffixes):
if None in s:
return s[None]
return self.default

def _get_suffix_list(self, parent):
if parent in self._suffixes_by_block:
return self._suffixes_by_block[parent]
suffixes = list(self._get_suffix_list(parent.parent_block()))
self._suffixes_by_block[parent] = suffixes
s = parent.component(self.name)
if s is not None and s.ctype is Suffix and s.active:
suffixes.append(s)
self.all_suffixes.append(s)
return suffixes
7 changes: 7 additions & 0 deletions pyomo/core/expr/relational_expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,3 +458,10 @@ def _generate_relational_expression(etype, lhs, rhs):
)
else:
return InequalityExpression((lhs, rhs), _relational_op[etype][2])


def tuple_to_relational_expr(args):
if len(args) == 2:
return EqualityExpression(args)
else:
return inequality(*args)
7 changes: 6 additions & 1 deletion pyomo/core/expr/template_expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
Numeric_NPV_Mixin,
register_arg_type,
ARG_TYPE,
_balanced_parens,
)
from pyomo.core.expr.numvalue import (
NumericValue,
Expand All @@ -34,6 +35,7 @@
value,
is_constant,
)
from pyomo.core.expr.relational_expr import tuple_to_relational_expr
from pyomo.core.expr.visitor import (
ExpressionReplacementVisitor,
StreamBasedExpressionVisitor,
Expand Down Expand Up @@ -1173,4 +1175,7 @@ def templatize_rule(block, rule, index_set):


def templatize_constraint(con):
return templatize_rule(con.parent_block(), con.rule, con.index_set())
expr, indices = templatize_rule(con.parent_block(), con.rule, con.index_set())
if expr.__class__ is tuple:
expr = tuple_to_relational_expr(expr)
return expr, indices
6 changes: 2 additions & 4 deletions pyomo/core/kernel/suffix.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,11 @@ def __init__(self, *args, **kwds):
# Interface
#

@property
def export_enabled(self):
"""Returns :const:`True` when this suffix is enabled
for export to solvers."""
return bool(self._direction & suffix.EXPORT)

@property
def import_enabled(self):
"""Returns :const:`True` when this suffix is enabled
for import from solutions."""
Expand Down Expand Up @@ -233,7 +231,7 @@ def export_suffix_generator(blk, datatype=_noarg, active=True, descend_into=True
"""
for suf in filter(
lambda x: (
x.export_enabled and ((datatype is _noarg) or (x.datatype is datatype))
x.export_enabled() and ((datatype is _noarg) or (x.datatype is datatype))
),
blk.components(ctype=suffix._ctype, active=active, descend_into=descend_into),
):
Expand Down Expand Up @@ -267,7 +265,7 @@ def import_suffix_generator(blk, datatype=_noarg, active=True, descend_into=True
"""
for suf in filter(
lambda x: (
x.import_enabled and ((datatype is _noarg) or (x.datatype is datatype))
x.import_enabled() and ((datatype is _noarg) or (x.datatype is datatype))
),
blk.components(ctype=suffix._ctype, active=active, descend_into=descend_into),
):
Expand Down
Loading

0 comments on commit 5048b42

Please sign in to comment.