def _fixed_memory_luong_score(query, keys, scale):
  """Implements Luong-style (multiplicative) scoring function.

  Assumes that keys have batch dimension of 1 (i.e., fixed memory bank).

  Args:
    query: Tensor, shape `[batch_size, num_units]` to compare to keys.
    keys: Processed memory, shape `[1, max_time, num_units]`.
    scale: Whether to apply a scale to the score function.

  Returns:
    A `[batch_size, max_time]` tensor of unnormalized score values.

  Raises:
    ValueError: If `key` and `query` depths do not match.
  """
  depth = query.get_shape()[-1]
  key_units = keys.get_shape()[-1]
  if depth != key_units:
    raise ValueError(
        "Incompatible or unknown inner dimensions between query and keys.  "
        "Query (%s) has units: %s.  Keys (%s) have units: %s.  "
        "Perhaps you need to set num_units to the keys' dimension (%s)?"
        % (query, depth, keys, key_units, key_units))
  dtype = query.dtype

  # Reshape from [1, memory_size, depth] to [memory_size, depth] for matmul.
  keys = array_ops.squeeze(keys, 0)

  # Inner product along the query units dimension.
  # matmul shapes: query is [batch_size, depth] and
  #                keys is [max_time, depth].
  # the inner product is asked to **transpose keys' inner shape** to get a
  # matmul on:
  #   [batch_size, depth] . [depth, max_time]
  # resulting in an output shape of:
  #   [batch_size, max_time].
  # we then squeeze out the center singleton dimension.
  score = math_ops.matmul(query, keys, transpose_b=True)

  if scale:
    # Scalar used in weight scaling
    g = variable_scope.get_variable(
        "attention_g", dtype=dtype,
        initializer=init_ops.ones_initializer, shape=())
    score = g * score
  return score
Implements Luong-style (multiplicative) scoring function.

  Assumes that keys have batch dimension of 1 (i.e., fixed memory bank).

  Args:
    query: Tensor, shape `[batch_size, num_units]` to compare to keys.
    keys: Processed memory, shape `[1, max_time, num_units]`.
    scale: Whether to apply a scale to the score function.

  Returns:
    A `[batch_size, max_time]` tensor of unnormalized score values.

  Raises:
    ValueError: If `key` and `query` depths do not match.
  
language/labs/consistent_zero_shot_nmt/modules/attention_wrappers.py