source: pyomo/trunk/pyomo/core/plugins/transform/equality_transform.py @ 9475

Last change on this file since 9475 was 9475, checked in by wehart, 4 years ago

Updating the version #.

Renaming transformations to 'base.*' if they didn't have a specific
naming. NOTE: these are in the pyomo.core package ... which seems
odd. But we agreed that 'core' provides a connotation that we don't
intend.

Adding some documentation changes for 'pyomo help -t'.

File size: 3.9 KB
Line 
1from pyomo.util.plugin import alias
2
3from pyomo.core import *
4from pyomo.core.base.numvalue import create_name
5
6from pyomo.core.plugins.transform.hierarchy import IsomorphicTransformation
7from pyomo.core.plugins.transform.util import collectAbstractComponents
8
9
10class EqualityTransform(IsomorphicTransformation):
11    """
12    Creates a new, equivalent model by introducing slack and excess variables
13    to eliminate inequality constraints.
14    """
15
16    alias("base.add_slack_vars", doc="Create an equivalent model by introducing slack variables to eliminate inequality constraints.")
17
18    def __init__(self, **kwds):
19        kwds["name"] = kwds.pop("name", "add_slack_vars")
20        super(EqualityTransform, self).__init__(**kwds)
21
22    def apply(self, model, **kwds):
23        """
24        Eliminate inequality constraints.
25
26        Required arguments:
27
28          model The model to transform.
29
30        Optional keyword arguments:
31
32          slack_root  The root name of auxiliary slack variables.
33                      Default is 'auxiliary_slack'.
34          excess_root The root name of auxiliary slack variables.
35                      Default is 'auxiliary_excess'.
36          lb_suffix   The suffix applied to converted upper bound constraints
37                      Default is '_lower_bound'.
38          ub_suffix   The suffix applied to converted lower bound constraints
39                      Default is '_upper_bound'.
40        """
41
42        # Optional naming schemes
43        slack_suffix = kwds.pop("slack_suffix", "slack")
44        excess_suffix = kwds.pop("excess_suffix", "excess")
45        lb_suffix = kwds.pop("lb_suffix", "lb")
46        ub_suffix = kwds.pop("ub_suffix", "ub")
47
48        equality = model.clone()
49        components = collectAbstractComponents(equality)
50
51        #
52        # Fix all Constraint objects
53        #
54        for con_name in components["Constraint"]:
55            con = equality.__getattribute__(con_name)
56
57            #
58            # Get all _ConstraintData objects
59            #
60            # We need to get the keys ahead of time because we are modifying
61            # con._data on-the-fly.
62            #
63            indices = con._data.keys()
64            for (ndx, cdata) in [(ndx, con._data[ndx]) for ndx in indices]:
65
66                qualified_con_name = create_name(con_name, ndx)
67
68                # Do nothing with equality constraints
69                if cdata._equality:
70                    continue
71
72                # Add an excess variable if the lower bound exists
73                if cdata.lower is not None:
74
75                    # Make the excess variable
76                    excess_name = "%s_%s" % (qualified_con_name, excess_suffix)
77                    equality.__setattr__(excess_name,
78                                         Var(within=NonNegativeReals))
79
80                    # Make a new lower bound constraint
81                    lb_name = "%s_%s" % (create_name("", ndx), lb_suffix)
82                    excess = equality.__getattribute__(excess_name)
83                    new_expr = (cdata.lower == cdata.body - excess)
84                    con.add(lb_name, new_expr)
85
86                # Add a slack variable if the lower bound exists
87                if cdata.upper is not None:
88
89                    # Make the excess variable
90                    slack_name = "%s_%s" % (qualified_con_name, slack_suffix)
91                    equality.__setattr__(slack_name,
92                                         Var(within=NonNegativeReals))
93
94                    # Make a new upper bound constraint
95                    ub_name = "%s_%s" % (create_name("", ndx), ub_suffix)
96                    slack = equality.__getattribute__(slack_name)
97                    new_expr = (cdata.upper == cdata.body + slack)
98                    con.add(ub_name, new_expr)
99
100                # Since we explicitly `continue` for equality constraints, we
101                # can safely remove the old _ConstraintData object
102                del con._data[ndx]
103
104        return equality.create()
Note: See TracBrowser for help on using the repository browser.