source: coopr.pyomo/trunk/coopr/pyomo/presolve/identify_vars.py @ 2064

Last change on this file since 2064 was 2064, checked in by wehart, 10 years ago

Misc rework of variable presolving. Now, model
statistics are stored in a more obvious location, and using more
verbose names.

File size: 5.1 KB
Line 
1#  _________________________________________________________________________
2#
3#  Coopr: A COmmon Optimization Python Repository
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#  For more information, see the FAST README.txt file.
9#  _________________________________________________________________________
10
11
12import pyutilib.plugin.core
13from coopr.pyomo.base import expr, _VarBase, Var, Constraint, Objective
14from coopr.pyomo.base.var import _VarValue, VarStatus
15from coopr.pyomo.base.numvalue import NumericConstant
16from coopr.pyomo.base import IPyomoPresolver, IPyomoPresolveAction
17
18
19class IdentifyVariablesPresolver(pyutilib.plugin.core.SingletonPlugin):
20    """
21    This plugin processes a Pyomo Model instance to define
22    the order of variables and to categorize constraints.
23    """
24
25    pyutilib.plugin.core.implements(IPyomoPresolveAction)
26
27    def __init__(self, **kwds):
28        kwds['name'] = "identify_variables"
29        pyutilib.plugin.core.Plugin.__init__(self, **kwds)
30
31    def rank(self):
32        return 1
33
34    #
35    # Recursively work through an exression to identify variables.
36    #
37    def _identify_variables(self, exp, model):
38        if exp.fixed_value():
39            return
40        #
41        # Product Expressions store stuff differently
42        #
43        if type(exp) is expr._ProductExpression:
44            for arg in exp._numerator:
45                self._identify_variables(arg, model)
46            for arg in exp._denominator:
47                self._identify_variables(arg, model)
48        #
49        # Expression
50        #
51        elif isinstance(exp,expr.Expression):
52            for arg in exp._args:
53                self._identify_variables(arg, model)
54        #
55        # Variable Value
56        #
57        elif isinstance(exp,_VarValue) or isinstance(exp,_VarBase):
58            exp.status = VarStatus.used
59            if isinstance(exp,_VarValue):
60                if exp.id in model._var:
61                    return
62                exp.id = self.vnum
63                model._var[self.vnum] = exp
64            else:
65                tmp = exp.as_numeric()
66                if tmp is exp:
67                    raise ValueError, "Variable %s appears in an expression without an index, but this variable is an indexed value." % exp.name
68                if tmp.id in model._var:
69                    return
70                tmp.id = self.vnum
71                model._var[self.vnum] = tmp
72            if model._var[self.vnum].is_binary():
73                model.statistics.number_of_binary_variables += 1
74            elif model._var[self.vnum].is_integer():
75                model.statistics.number_of_integer_variables += 1
76            else:
77                model.statistics.number_of_continuous_variables +=1
78            self.vnum += 1
79        #
80        # If not a constant, then this is an error
81        #
82        elif exp is not None:
83            raise ValueError, "Unexpected expression type in identify_variables: " + str(type(exp))+" "+str(exp)
84
85
86    def presolve(self,model):
87        """
88        The main routine to perform the presolve
89        """
90        Vars = model.active_components(Var)
91        Con = model.active_components(Constraint)
92        Obj = model.active_components(Objective)
93        self.vnum=0
94        self.cnum=0
95        self.onum=0
96        model.statistics.number_of_binary_variables = 0
97        model.statistics.number_of_integer_variables = 0
98        model.statistics.number_of_continuous_variables = 0
99        #
100        # Indicate that all variables are unused
101        #
102        for var in Vars.values():
103            for V in var._varval.keys():
104                var._varval[V].status = VarStatus.unused
105                var._varval[V].id = -1
106        #
107        # Call identify_variables to find the variables that are used in
108        # the objective and constraints
109        #
110        for key in Obj.keys():
111            for ondx in Obj[key]._data:
112                if not Obj[key]._data[ondx].active:
113                    continue
114                try:
115                    self._identify_variables(Obj[key]._data[ondx].expr, model)
116                except ValueError, err:
117                    raise "Problem processing objective %s (index %s): %s" % (str(key), str(ondx), str(err))
118
119                Obj[key]._data[ondx].id = self.onum
120                self.onum += 1
121        for key in Con.keys():
122            C = Con[key]
123            for cndx in C.keys():
124                if not C._data[cndx].active:
125                    continue
126                try:
127                    self._identify_variables(C._data[cndx].body, model)
128                except ValueError, err:
129                    raise "Problem processing constraint %s (index %s): %s" % (str(key), str(cndx), str(err))
130                C._data[cndx].id = self.cnum
131                model._con[self.cnum] = C._data[cndx]
132                self.cnum += 1
133        model.statistics.number_of_variables=self.vnum
134        model.statistics.number_of_constraints=self.cnum
135        model.statistics.number_of_objectives=self.onum
136        return model
137
Note: See TracBrowser for help on using the repository browser.