def _target_codelength(source, target, rules, verbose=False):
  """Return codelength for encoding `target` given `source` and `rules`.

  The codelength of the target is computed as -log_2(P(y|x)).

  For P(y|x) we use a naive uniform distribution over derivations, such that:

  P(y|x) = # of derivations of <x,y> / # of derivations of <x,?>,

  where ? is any target strings.

  We therefore run a QCFG parser twice to determine the numberator and
  denominator counts.

  Args:
    source: Tuple of source tokens.
    target: Tuple of target tokens.
    rules: Set of QCFGRule instances.
    verbose: Print debug logging if True.

  Returns:
    Float representing codelength for encoding `target` given `source` and
    `rules`.
  """
  num_derivations = _get_num_all_derivations(source, rules, verbose=verbose)
  num_target_derivations = _get_num_target_derivations(
      source, target, rules, verbose=verbose)

  # Note log(B/A) = -log(A/B).
  codelength = math.log2(float(num_derivations) / float(num_target_derivations))
  if verbose:
    print("(%s, %s): %s derivations, %s target derivations, %s codelength" %
          (source, target, num_derivations, num_target_derivations, codelength))
  return codelength
Return codelength for encoding `target` given `source` and `rules`.

  The codelength of the target is computed as -log_2(P(y|x)).

  For P(y|x) we use a naive uniform distribution over derivations, such that:

  P(y|x) = # of derivations of <x,y> / # of derivations of <x,?>,

  where ? is any target strings.

  We therefore run a QCFG parser twice to determine the numberator and
  denominator counts.

  Args:
    source: Tuple of source tokens.
    target: Tuple of target tokens.
    rules: Set of QCFGRule instances.
    verbose: Print debug logging if True.

  Returns:
    Float representing codelength for encoding `target` given `source` and
    `rules`.
  
language/compgen/nqg/model/induction/codelength_utils.py