1#  ___________________________________________________________________________
2#
3#  Pyomo: Python Optimization Modeling Objects
4#  Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
5#  Under the terms of Contract DE-NA0003525 with National Technology and
6#  Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
7#  rights in this software.
8#  This software is distributed under the 3-clause BSD License.
9#  ___________________________________________________________________________
10
11"""Automatically initialize variables."""
12from __future__ import division
13
14from pyomo.core.base.var import Var
15from pyomo.core.base.transformation import TransformationFactory
16from pyomo.core.expr.numvalue import value
17from pyomo.core.plugins.transform.hierarchy import IsomorphicTransformation
18
19
20@TransformationFactory.register(
21        'contrib.init_vars_midpoint',
22        doc="Initialize non-fixed variables to the midpoint of their bounds.")
23class InitMidpoint(IsomorphicTransformation):
24    """Initialize non-fixed variables to the midpoint of their bounds.
25
26    - If the variable does not have bounds, set the value to zero.
27    - If the variable is missing one bound, set the value to that of the
28      existing bound.
29    """
30
31    def _apply_to(self, instance, overwrite=False):
32        """Apply the transformation.
33
34        Kwargs:
35            overwrite: if False, transformation will not overwrite existing
36                variable values.
37        """
38        for var in instance.component_data_objects(
39                ctype=Var, descend_into=True):
40            if var.fixed:
41                continue
42            if var.value is not None and not overwrite:
43                continue
44            if var.lb is None and var.ub is None:
45                # If LB and UB do not exist, set variable value to 0
46                var.set_value(0)
47            elif var.lb is None:
48                # if one bound does not exist, set variable value to the other
49                var.set_value(value(var.ub))
50            elif var.ub is None:
51                # if one bound does not exist, set variable value to the other
52                var.set_value(value(var.lb))
53            else:
54                var.set_value((value(var.lb) + value(var.ub)) / 2.)
55
56
57@TransformationFactory.register(
58        'contrib.init_vars_zero',
59        doc="Initialize non-fixed variables to zero.")
60class InitZero(IsomorphicTransformation):
61    """Initialize non-fixed variables to zero.
62
63    - If setting the variable value to zero will violate a bound, set the
64      variable value to the relevant bound value.
65
66    """
67
68    def _apply_to(self, instance, overwrite=False):
69        """Apply the transformation.
70
71        Kwargs:
72            overwrite: if False, transformation will not overwrite existing
73                variable values.
74        """
75        for var in instance.component_data_objects(
76                ctype=Var, descend_into=True):
77            if var.fixed:
78                continue
79            if var.value is not None and not overwrite:
80                continue
81            if var.lb is not None and value(var.lb) > 0:
82                var.set_value(value(var.lb))
83            elif var.ub is not None and value(var.ub) < 0:
84                var.set_value(value(var.ub))
85            else:
86                var.set_value(0)
87