# Path: third_party/bi_att_flow/my/tensorflow/general.py
# def exp_mask(val, mask, name=None):
#   """Give very negative number to unmasked elements in val.
# 
#     For example, [-3, -2, 10], [True, True, False] -> [-3, -2, -1e9].
#     Typically, this effectively masks in exponential space (e.g. softmax)
#     Args:
#         val: values to be masked
#         mask: masking boolean tensor, same shape as tensor
#         name: name for output tensor
# 
#     Returns:
#         Same shape as val, where some elements are very small (exponentially
#         zero)
#     """
#   if name is None:
#     name = 'exp_mask'
#   return tf.add(
#       val, (1 - tf.cast(mask, 'float')) * VERY_NEGATIVE_NUMBER, name=name)
# 
# def flatten(tensor, keep):
#   fixed_shape = tensor.get_shape().as_list()
#   start = len(fixed_shape) - keep
#   left = reduce(mul,
#                 [fixed_shape[i] or tf.shape(tensor)[i] for i in range(start)])
#   out_shape = [left] + [
#       fixed_shape[i] or tf.shape(tensor)[i]
#       for i in range(start, len(fixed_shape))
#   ]
#   flat = tf.reshape(tensor, out_shape)
#   return flat
# 
# Path: third_party/bi_att_flow/my/tensorflow/nn.py
# def linear(args,
#            output_size,
#            bias,
#            bias_start=0.0,
#            scope=None,
#            squeeze=False,
#            wd=0.0,
#            input_keep_prob=1.0,
#            is_train=None):
#   if args is None or (nest.is_sequence(args) and not args):
#     raise ValueError("`args` must be specified")
#   if not nest.is_sequence(args):
#     args = [args]
# 
#   flat_args = [flatten(arg, 1) for arg in args]
#   if input_keep_prob < 1.0:
#     assert is_train is not None
#     flat_args = [
#         tf.cond(is_train, lambda: tf.nn.dropout(arg, input_keep_prob),
#                 lambda: arg) for arg in flat_args
#     ]
# 
#   flat_out = _linear(
#       flat_args, output_size, bias, bias_start=bias_start, scope=scope)
#   out = reconstruct(flat_out, args[0], 1)
#   if squeeze:
#     out = tf.squeeze(out, [len(args[0].get_shape().as_list()) - 1])
#   if wd:
#     add_wd(wd)
# 
#   return out
# 
# def softsel(target, logits, mask=None, scope=None):
#   """
# 
#     :param target: [ ..., J, d] dtype=float
#     :param logits: [ ..., J], dtype=float
#     :param mask: [ ..., J], dtype=bool
#     :param scope:
#     :return: [..., d], dtype=float
#     """
#   with tf.name_scope(scope or "Softsel"):
#     a = softmax(logits, mask=mask)
#     target_rank = len(target.get_shape().as_list())
#     out = tf.reduce_sum(tf.expand_dims(a, -1) * target, target_rank - 2)
#     return out
# 
# def double_linear_logits(args,
#                          size,
#                          bias,
#                          bias_start=0.0,
#                          scope=None,
#                          mask=None,
#                          wd=0.0,
#                          input_keep_prob=1.0,
#                          is_train=None):
#   with tf.variable_scope(scope or "Double_Linear_Logits"):
#     first = tf.tanh(
#         linear(
#             args,
#             size,
#             bias,
#             bias_start=bias_start,
#             scope="first",
#             wd=wd,
#             input_keep_prob=input_keep_prob,
#             is_train=is_train))
#     second = linear(
#         first,
#         1,
#         bias,
#         bias_start=bias_start,
#         squeeze=True,
#         scope="second",
#         wd=wd,
#         input_keep_prob=input_keep_prob,
#         is_train=is_train)
#     if mask is not None:
#       second = exp_mask(second, mask)
#     return second


import tensorflow as tf
from third_party.bi_att_flow.my.tensorflow.general import exp_mask, flatten
from third_party.bi_att_flow.my.tensorflow.nn import linear, softsel, double_linear_logits
            for each in state
        ]
      else:
        tiled_states = [tf.tile(tf.expand_dims(state, 1), [1, _memory_size, 1])]

      # [N, M, d]
      in_ = tf.concat(2, [tiled_inputs] + tiled_states + [memory])
      out = double_linear_logits(
          in_, size, bias, input_keep_prob=input_keep_prob, is_train=is_train)
      return out

    return double_linear_controller

  @staticmethod
  def get_linear_controller(bias, input_keep_prob=1.0, is_train=None):

    def linear_controller(inputs, state, memory):
      rank = len(memory.get_shape())
      _memory_size = tf.shape(memory)[rank - 2]
      tiled_inputs = tf.tile(tf.expand_dims(inputs, 1), [1, _memory_size, 1])
      if isinstance(state, tuple):
        tiled_states = [
            tf.tile(tf.expand_dims(each, 1), [1, _memory_size, 1])
            for each in state
        ]
      else:
        tiled_states = [tf.tile(tf.expand_dims(state, 1), [1, _memory_size, 1])]

      # [N, M, d]
      in_ = tf.concat(2, [tiled_inputs] + tiled_states + [memory])

# Path: third_party/bi_att_flow/my/tensorflow/general.py
# def exp_mask(val, mask, name=None):
#   """Give very negative number to unmasked elements in val.
# 
#     For example, [-3, -2, 10], [True, True, False] -> [-3, -2, -1e9].
#     Typically, this effectively masks in exponential space (e.g. softmax)
#     Args:
#         val: values to be masked
#         mask: masking boolean tensor, same shape as tensor
#         name: name for output tensor
# 
#     Returns:
#         Same shape as val, where some elements are very small (exponentially
#         zero)
#     """
#   if name is None:
#     name = 'exp_mask'
#   return tf.add(
#       val, (1 - tf.cast(mask, 'float')) * VERY_NEGATIVE_NUMBER, name=name)
# 
# def flatten(tensor, keep):
#   fixed_shape = tensor.get_shape().as_list()
#   start = len(fixed_shape) - keep
#   left = reduce(mul,
#                 [fixed_shape[i] or tf.shape(tensor)[i] for i in range(start)])
#   out_shape = [left] + [
#       fixed_shape[i] or tf.shape(tensor)[i]
#       for i in range(start, len(fixed_shape))
#   ]
#   flat = tf.reshape(tensor, out_shape)
#   return flat
# 
# Path: third_party/bi_att_flow/my/tensorflow/nn.py
# def linear(args,
#            output_size,
#            bias,
#            bias_start=0.0,
#            scope=None,
#            squeeze=False,
#            wd=0.0,
#            input_keep_prob=1.0,
#            is_train=None):
#   if args is None or (nest.is_sequence(args) and not args):
#     raise ValueError("`args` must be specified")
#   if not nest.is_sequence(args):
#     args = [args]
# 
#   flat_args = [flatten(arg, 1) for arg in args]
#   if input_keep_prob < 1.0:
#     assert is_train is not None
#     flat_args = [
#         tf.cond(is_train, lambda: tf.nn.dropout(arg, input_keep_prob),
#                 lambda: arg) for arg in flat_args
#     ]
# 
#   flat_out = _linear(
#       flat_args, output_size, bias, bias_start=bias_start, scope=scope)
#   out = reconstruct(flat_out, args[0], 1)
#   if squeeze:
#     out = tf.squeeze(out, [len(args[0].get_shape().as_list()) - 1])
#   if wd:
#     add_wd(wd)
# 
#   return out
# 
# def softsel(target, logits, mask=None, scope=None):
#   """
# 
#     :param target: [ ..., J, d] dtype=float
#     :param logits: [ ..., J], dtype=float
#     :param mask: [ ..., J], dtype=bool
#     :param scope:
#     :return: [..., d], dtype=float
#     """
#   with tf.name_scope(scope or "Softsel"):
#     a = softmax(logits, mask=mask)
#     target_rank = len(target.get_shape().as_list())
#     out = tf.reduce_sum(tf.expand_dims(a, -1) * target, target_rank - 2)
#     return out
# 
# def double_linear_logits(args,
#                          size,
#                          bias,
#                          bias_start=0.0,
#                          scope=None,
#                          mask=None,
#                          wd=0.0,
#                          input_keep_prob=1.0,
#                          is_train=None):
#   with tf.variable_scope(scope or "Double_Linear_Logits"):
#     first = tf.tanh(
#         linear(
#             args,
#             size,
#             bias,
#             bias_start=bias_start,
#             scope="first",
#             wd=wd,
#             input_keep_prob=input_keep_prob,
#             is_train=is_train))
#     second = linear(
#         first,
#         1,
#         bias,
#         bias_start=bias_start,
#         squeeze=True,
#         scope="second",
#         wd=wd,
#         input_keep_prob=input_keep_prob,
#         is_train=is_train)
#     if mask is not None:
#       second = exp_mask(second, mask)
#     return second


# Path: third_party/bi_att_flow/my/tensorflow/rnn_cell.py
import tensorflow as tf
from third_party.bi_att_flow.my.tensorflow.general import exp_mask, flatten
from third_party.bi_att_flow.my.tensorflow.nn import linear, softsel, double_linear_logits

            for each in state
        ]
      else:
        tiled_states = [tf.tile(tf.expand_dims(state, 1), [1, _memory_size, 1])]

      # [N, M, d]
      in_ = tf.concat(2, [tiled_inputs] + tiled_states + [memory])
      out = double_linear_logits(
          in_, size, bias, input_keep_prob=input_keep_prob, is_train=is_train)
      return out

    return double_linear_controller

  @staticmethod
  def get_linear_controller(bias, input_keep_prob=1.0, is_train=None):

    def linear_controller(inputs, state, memory):
      rank = len(memory.get_shape())
      _memory_size = tf.shape(memory)[rank - 2]
      tiled_inputs = tf.tile(tf.expand_dims(inputs, 1), [1, _memory_size, 1])
      if isinstance(state, tuple):
        tiled_states = [
            tf.tile(tf.expand_dims(each, 1), [1, _memory_size, 1])
            for each in state
        ]
      else:
        tiled_states = [tf.tile(tf.expand_dims(state, 1), [1, _memory_size, 1])]

      # [N, M, d]
      in_ = tf.concat(2, [tiled_inputs] + tiled_states + [memory])

      out = linear(