source: pyomo/trunk/pyomo/core/plugins/transform/relax_integrality.py @ 9485

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

Fixes to push bounds changes into all
variable data

File size: 3.0 KB
Line 
1#  _________________________________________________________________________
2#
3#  Pyomo: Python Optimization Modeling Objects
4#  Copyright (c) 2008 Sandia Corporation.
5#  This software is distributed under the BSD License.
6#  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
7#  the U.S. Government retains certain rights in this software.
8#  _________________________________________________________________________
9
10from pyomo.util.plugin import alias
11from pyomo.core.base import Var
12from pyomo.core.base.set_types import BooleanSet, IntegerSet, Reals
13import pyomo.core.base
14from pyomo.core.plugins.transform.hierarchy import NonIsomorphicTransformation
15
16
17class RelaxIntegrality(NonIsomorphicTransformation):
18    """
19    This plugin relaxes integrality in a Pyomo model.
20    """
21
22    alias('base.relax_integrality',\
23          doc="Create a model where integer variables are replaced with real variables.")
24
25    def __init__(self, **kwds):
26        kwds['name'] = "relax_integrality"
27        super(RelaxIntegrality, self).__init__(**kwds)
28
29    def apply(self, model, **kwds):
30        #
31        # Clone the model
32        #
33        M = model.clone()
34        #
35        # Iterate over all variables, replacing the domain with a real-valued domain
36        # and setting appropriate bounds.
37        #
38        # Note: this technique is not extensible.  If a user creates a new integer variable
39        # class then we'd need to add it here (unless it was a subset of one of the sets we
40        # detect here.  Alternatively, we could make the variables responsible for managing
41        # the generation of a relaxed variable.  But that would pollute the variable objects
42        # with logic about generating a specific relaxation.  That's probably a worse alternative.
43        #
44        # TODO: rework this so it works with model instances
45        #
46        comp = M.components(Var)
47        for var in comp.values():
48            if isinstance(var.domain, BooleanSet):
49                var.domain=Reals
50                dbnd = ( 0.0, 1.0 )
51            elif isinstance(var.domain, IntegerSet):
52                dbnd = var.domain.bounds()
53                if dbnd is None:
54                    bnd = ( None, None )
55                var.domain=Reals
56            elif isinstance(var.domain, pyomo.core.base.RangeSet):
57                dbnd = var.domain.bounds()
58                if dbnd is None:
59                    bnd = ( None, None )
60                var.domain=Reals
61            else:
62                continue
63
64            bnd = var.domain.bounds()
65            if bnd is None:
66                bnd = ( None, None )
67
68            bnd = ( self._tightenBound(bnd[0], dbnd[0], max),
69                    self._tightenBound(bnd[1], dbnd[1], min) )
70            if bnd == (None, None):
71                var.domain._bounds = None
72            else:
73                var.domain._bounds = bnd
74            var._initialize_members(var._index)
75
76        return M
77
78    def _tightenBound(self, a, b, comp):
79        if a is None:
80            return b
81        if b is None:
82            return a
83        return comp(a,b)
Note: See TracBrowser for help on using the repository browser.