def compute_kwinners(x, k, dutyCycles, boostStrength):
  """
  Use the boost strength to compute a boost factor for each unit represented
  in x. These factors are used to increase the impact of each unit to improve
  their chances of being chosen. This encourages participation of more columns
  in the learning process.

  The boosting function is a curve defined as: boostFactors = exp[ -
  boostStrength * (dutyCycle - targetDensity)] Intuitively this means that
  units that have been active (i.e. in the top-k) at the target activation
  level have a boost factor of 1, meaning their activity is not boosted.
  Columns whose duty cycle drops too much below that of their neighbors are
  boosted depending on how infrequently they have been active. Unit that has
  been active more than the target activation level have a boost factor below
  1, meaning their activity is suppressed and they are less likely to be in
  the top-k.

  Note that we do not transmit the boosted values. We only use boosting to
  determine the winning units.

  The target activation density for each unit is k / number of units. The
  boostFactor depends on the dutyCycle via an exponential function:

          boostFactor
              ^
              |
              |\
              | \
        1  _  |  \
              |    _
              |      _ _
              |          _ _ _ _
              +--------------------> dutyCycle
                 |
            targetDensity

  :param x:
    Current activity of each unit.

  :param k:
    The activity of the top k units will be allowed to remain, the rest are
    set to zero.

  :param dutyCycles:
    The averaged duty cycle of each unit.

  :param boostStrength:
    A boost strength of 0.0 has no effect on x.

  :return:
    A tensor representing the activity of x after k-winner take all.
  """

  k = tf.convert_to_tensor(k, dtype=tf.int32)
  boostStrength = tf.math.maximum(boostStrength, 0.0, name="boostStrength")
  targetDensity = tf.cast(k / x.shape[1], tf.float32, name="targetDensity")
  boostFactors = tf.exp((targetDensity - dutyCycles) * boostStrength,
                        name="boostFactors")
  boosted = tf.multiply(x, boostFactors, name="boosted")

  # Take the boosted version of the input x, find the top k winners.
  # Compute an output that contains the values of x corresponding to the top k
  # boosted values
  topk, _ = tf.math.top_k(input=boosted, k=k, sorted=False,
                          name="compute_kwinners")
  bottom = tf.reduce_min(topk, axis=1, keepdims=True,
                         name="compute_kwinners")
  mask = tf.cast(tf.greater_equal(boosted, bottom), dtype=x.dtype,
                 name="compute_kwinners")

  return x * mask