# Path: tensorflow_constrained_optimization/python/train/constrained_optimizer.py
# class Formulation(tf.Module):
# class ConstrainedOptimizerV1(tf.compat.v1.train.Optimizer):
# class ConstrainedOptimizerV2(tf.keras.optimizers.Optimizer):
#   def __init__(self, name=None):
#   def state(self):
#   def create_state(self, num_constraints):
#   def is_state_created(self):
#   def get_loss_fn(self, minimization_problem):
#   def __init__(self,
#                formulation,
#                optimizer,
#                num_constraints=None,
#                constraint_optimizer=None,
#                name="ConstrainedOptimizerV1"):
#   def num_constraints(self):
#   def num_constraints(self, num_constraints):
#   def variables(self):
#   def trainable_variables(self):
#   def non_trainable_variables(self):
#   def compute_gradients(self,
#                         loss,
#                         var_list=None,
#                         gate_gradients=tf.compat.v1.train.Optimizer.GATE_OP,
#                         aggregation_method=None,
#                         colocate_gradients_with_ops=False,
#                         grad_loss=None):
#   def _create_slots(self, var_list):
#   def _prepare(self):
#   def _apply_dense(self, gradient, variable, *args, **kwargs):
#   def _apply_sparse(self, gradient, variable, *args, **kwargs):
#   def _resource_apply_dense(self, gradient, handle, *args, **kwargs):
#   def _resource_apply_sparse(self, gradient, handle, *args, **kwargs):
#   def __init__(self,
#                formulation,
#                optimizer,
#                num_constraints=None,
#                constraint_optimizer=None,
#                name="ConstrainedOptimizerV2"):
#   def num_constraints(self):
#   def num_constraints(self, num_constraints):
#   def variables(self):
#   def trainable_variables(self):
#   def non_trainable_variables(self):
#   def get_gradients(self, loss, params):
#   def _split_var_list(self, var_list):
#   def _compute_gradients(self, loss, var_list, grad_loss=None, tape=None):
#   def _create_slots(self, var_list):
#   def _prepare(self, var_list):
#   def _create_hypers(self):
#   def get_config(self):
#   def _resource_apply_dense(self, gradient, handle, *args, **kwargs):
#   def _resource_apply_sparse(self, gradient, handle, *args, **kwargs):


import math
import numpy as np
import tensorflow as tf
from tensorflow_constrained_optimization.python.train import constrained_optimizer
      minimum_multiplier_radius: optional float in the range (0,1), only allowed
        if update_type="multiplicative". The constraint/objective weights will
        be lower bounded by "minimum_multiplier_radius" divided by one plus the
        number of constraints. Defaults to 10^-3.
      initial_multiplier_radius: optional float in the range [0,1], the initial
        value of each constraint weight (i.e. excluding the weight associated
        with the objective) will be "initial_multiplier_radius" divided by one
        plus the number of constraints. If update_type="multiplicative", it
        defaults to the value of minimum_multiplier_radius (and must be no
        smaller than minimum_multiplier_radius if it's explicitly specified),
        and defaults to zero if update_type="additive".
      name: as in `ConstrainedOptimizerV1`.

    Raises:
      ValueError: if the "regret_type" or "update_type" parameters are invalid,
        or if "minimum_multiplier_radius" or "initial_multiplier_radius" violate
        the conditions described above.
    """
    super(ProxyLagrangianOptimizerV1, self).__init__(
        _ProxyLagrangianFormulation(
            regret_type=regret_type,
            update_type=update_type,
            minimum_multiplier_radius=minimum_multiplier_radius,
            initial_multiplier_radius=initial_multiplier_radius),
        optimizer=optimizer,
        num_constraints=num_constraints,
        constraint_optimizer=constraint_optimizer,
        name=name)



# Path: tensorflow_constrained_optimization/python/train/constrained_optimizer.py
# class Formulation(tf.Module):
# class ConstrainedOptimizerV1(tf.compat.v1.train.Optimizer):
# class ConstrainedOptimizerV2(tf.keras.optimizers.Optimizer):
#   def __init__(self, name=None):
#   def state(self):
#   def create_state(self, num_constraints):
#   def is_state_created(self):
#   def get_loss_fn(self, minimization_problem):
#   def __init__(self,
#                formulation,
#                optimizer,
#                num_constraints=None,
#                constraint_optimizer=None,
#                name="ConstrainedOptimizerV1"):
#   def num_constraints(self):
#   def num_constraints(self, num_constraints):
#   def variables(self):
#   def trainable_variables(self):
#   def non_trainable_variables(self):
#   def compute_gradients(self,
#                         loss,
#                         var_list=None,
#                         gate_gradients=tf.compat.v1.train.Optimizer.GATE_OP,
#                         aggregation_method=None,
#                         colocate_gradients_with_ops=False,
#                         grad_loss=None):
#   def _create_slots(self, var_list):
#   def _prepare(self):
#   def _apply_dense(self, gradient, variable, *args, **kwargs):
#   def _apply_sparse(self, gradient, variable, *args, **kwargs):
#   def _resource_apply_dense(self, gradient, handle, *args, **kwargs):
#   def _resource_apply_sparse(self, gradient, handle, *args, **kwargs):
#   def __init__(self,
#                formulation,
#                optimizer,
#                num_constraints=None,
#                constraint_optimizer=None,
#                name="ConstrainedOptimizerV2"):
#   def num_constraints(self):
#   def num_constraints(self, num_constraints):
#   def variables(self):
#   def trainable_variables(self):
#   def non_trainable_variables(self):
#   def get_gradients(self, loss, params):
#   def _split_var_list(self, var_list):
#   def _compute_gradients(self, loss, var_list, grad_loss=None, tape=None):
#   def _create_slots(self, var_list):
#   def _prepare(self, var_list):
#   def _create_hypers(self):
#   def get_config(self):
#   def _resource_apply_dense(self, gradient, handle, *args, **kwargs):
#   def _resource_apply_sparse(self, gradient, handle, *args, **kwargs):


# Path: tensorflow_constrained_optimization/python/train/proxy_lagrangian_optimizer.py
import math
import numpy as np
import tensorflow as tf
from tensorflow_constrained_optimization.python.train import constrained_optimizer

      minimum_multiplier_radius: optional float in the range (0,1), only allowed
        if update_type="multiplicative". The constraint/objective weights will
        be lower bounded by "minimum_multiplier_radius" divided by one plus the
        number of constraints. Defaults to 10^-3.
      initial_multiplier_radius: optional float in the range [0,1], the initial
        value of each constraint weight (i.e. excluding the weight associated
        with the objective) will be "initial_multiplier_radius" divided by one
        plus the number of constraints. If update_type="multiplicative", it
        defaults to the value of minimum_multiplier_radius (and must be no
        smaller than minimum_multiplier_radius if it's explicitly specified),
        and defaults to zero if update_type="additive".
      name: as in `ConstrainedOptimizerV1`.

    Raises:
      ValueError: if the "regret_type" or "update_type" parameters are invalid,
        or if "minimum_multiplier_radius" or "initial_multiplier_radius" violate
        the conditions described above.
    """
    super(ProxyLagrangianOptimizerV1, self).__init__(
        _ProxyLagrangianFormulation(
            regret_type=regret_type,
            update_type=update_type,
            minimum_multiplier_radius=minimum_multiplier_radius,
            initial_multiplier_radius=initial_multiplier_radius),
        optimizer=optimizer,
        num_constraints=num_constraints,
        constraint_optimizer=constraint_optimizer,
        name=name)



class ProxyLagrangianOptimizerV2(constrained_optimizer.ConstrainedOptimizerV2):