• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2018 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
15"""Defines abstract class for `ConstrainedMinimizationProblem`s.
16
17A ConstrainedMinimizationProblem consists of an objective function to minimize,
18and a set of constraint functions that are constrained to be nonpositive.
19"""
20
21from __future__ import absolute_import
22from __future__ import division
23from __future__ import print_function
24
25import abc
26
27import six
28
29
30@six.add_metaclass(abc.ABCMeta)
31class ConstrainedMinimizationProblem(object):
32  """Abstract class representing a `ConstrainedMinimizationProblem`.
33
34  A ConstrainedMinimizationProblem consists of an objective function to
35  minimize, and a set of constraint functions that are constrained to be
36  nonpositive.
37
38  In addition to the constraint functions, there may (optionally) be proxy
39  constraint functions: a ConstrainedOptimizer will attempt to penalize these
40  proxy constraint functions so as to satisfy the (non-proxy) constraints. Proxy
41  constraints could be used if the constraints functions are difficult or
42  impossible to optimize (e.g. if they're piecewise constant), in which case the
43  proxy constraints should be some approximation of the original constraints
44  that is well-enough behaved to permit successful optimization.
45  """
46
47  @abc.abstractproperty
48  def objective(self):
49    """Returns the objective function.
50
51    Returns:
52      A 0d tensor that should be minimized.
53    """
54    pass
55
56  @property
57  def num_constraints(self):
58    """Returns the number of constraints.
59
60    Returns:
61      An int containing the number of constraints.
62
63    Raises:
64      ValueError: If the constraints (or proxy_constraints, if present) do not
65        have fully-known shapes, OR if proxy_constraints are present, and the
66        shapes of constraints and proxy_constraints are fully-known, but they're
67        different.
68    """
69    constraints_shape = self.constraints.get_shape()
70    if self.proxy_constraints is None:
71      proxy_constraints_shape = constraints_shape
72    else:
73      proxy_constraints_shape = self.proxy_constraints.get_shape()
74
75    if (constraints_shape.ndims is None or
76        proxy_constraints_shape.ndims is None or
77        any(ii is None for ii in constraints_shape.as_list()) or
78        any(ii is None for ii in proxy_constraints_shape.as_list())):
79      raise ValueError(
80          "constraints and proxy_constraints must have fully-known shapes")
81    if constraints_shape != proxy_constraints_shape:
82      raise ValueError(
83          "constraints and proxy_constraints must have the same shape")
84
85    size = 1
86    for ii in constraints_shape.as_list():
87      size *= ii
88    return int(size)
89
90  @abc.abstractproperty
91  def constraints(self):
92    """Returns the vector of constraint functions.
93
94    Letting g_i be the ith element of the constraints vector, the ith constraint
95    will be g_i <= 0.
96
97    Returns:
98      A tensor of constraint functions.
99    """
100    pass
101
102  # This is a property, instead of an abstract property, since it doesn't need
103  # to be overridden: if proxy_constraints returns None, then there are no
104  # proxy constraints.
105  @property
106  def proxy_constraints(self):
107    """Returns the optional vector of proxy constraint functions.
108
109    The difference between `constraints` and `proxy_constraints` is that, when
110    proxy constraints are present, the `constraints` are merely EVALUATED during
111    optimization, whereas the `proxy_constraints` are DIFFERENTIATED. If there
112    are no proxy constraints, then the `constraints` are both evaluated and
113    differentiated.
114
115    For example, if we want to impose constraints on step functions, then we
116    could use these functions for `constraints`. However, because a step
117    function has zero gradient almost everywhere, we can't differentiate these
118    functions, so we would take `proxy_constraints` to be some differentiable
119    approximation of `constraints`.
120
121    Returns:
122      A tensor of proxy constraint functions.
123    """
124    return None
125
126  # This is a property, instead of an abstract property, since it doesn't need
127  # to be overridden: if pre_train_ops returns None, then there are no ops to
128  # run before train_op.
129  @property
130  def pre_train_ops(self):
131    """Returns a list of `Operation`s to run before the train_op.
132
133    When a `ConstrainedOptimizer` creates a train_op (in `minimize`
134    `minimize_unconstrained`, or `minimize_constrained`), it will include these
135    ops before the main training step.
136
137    Returns:
138      A list of `Operation`s.
139    """
140    return None
141