# Path: tensorflow_constrained_optimization/python/rates/helpers.py
# class RateObject(object):
# class UniqueList(RateObject):
# def convert_to_1d_tensor(tensor, name=None):
# def get_num_columns_of_2d_tensor(tensor, name="tensor"):
# def get_num_elements_of_tensor(tensor, name="tensor"):
#   def __init__(self, collection=None, element_type=None):
#   def list(self):
#   def append(self, element):
#   def __eq__(self, other):
#   def __ne__(self, other):
#   def __len__(self):
#   def __iter__(self):
#   def __add__(self, other):
#   def __radd__(self, other):
#   def __getitem__(self, slice_spec):


from tensorflow_constrained_optimization.python.rates import helpers
A `ConstraintList` is basically a stripped-down list of `Constraint` objects,
with the additional property that if one attempts to add a duplicate
`Constraint` to the list, then it will be ignored. In the past, we used a set,
but realized that it's desirable for the constraints to appear in the resulting
`RateMinimizationProblem` in the order in which they were added.
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function



class Constraint(helpers.RateObject):
  """Represents an inequality constraint.

  This class is nothing but a thin wrapper around an `Expression`, and
  represents the constraint that the wrapped expression is non-positive.
  """

  def __init__(self, expression):
    """Constructs a new `Constraint` object from an `Expression`."""
    self._expression = expression

  @property
  def expression(self):
    """Returns the `Expression` that is constrained to be non-positive."""
    return self._expression



# Path: tensorflow_constrained_optimization/python/rates/helpers.py
# class RateObject(object):
# class UniqueList(RateObject):
# def convert_to_1d_tensor(tensor, name=None):
# def get_num_columns_of_2d_tensor(tensor, name="tensor"):
# def get_num_elements_of_tensor(tensor, name="tensor"):
#   def __init__(self, collection=None, element_type=None):
#   def list(self):
#   def append(self, element):
#   def __eq__(self, other):
#   def __ne__(self, other):
#   def __len__(self):
#   def __iter__(self):
#   def __add__(self, other):
#   def __radd__(self, other):
#   def __getitem__(self, slice_spec):


# Path: tensorflow_constrained_optimization/python/rates/constraint.py
from tensorflow_constrained_optimization.python.rates import helpers

A `ConstraintList` is basically a stripped-down list of `Constraint` objects,
with the additional property that if one attempts to add a duplicate
`Constraint` to the list, then it will be ignored. In the past, we used a set,
but realized that it's desirable for the constraints to appear in the resulting
`RateMinimizationProblem` in the order in which they were added.
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function



class Constraint(helpers.RateObject):
  """Represents an inequality constraint.

  This class is nothing but a thin wrapper around an `Expression`, and
  represents the constraint that the wrapped expression is non-positive.
  """

  def __init__(self, expression):
    """Constructs a new `Constraint` object from an `Expression`."""
    self._expression = expression

  @property
  def expression(self):
    """Returns the `Expression` that is constrained to be non-positive."""
    return self._expression



class ConstraintList(helpers.UniqueList):