def _get_num_target_derivations(source, target, rules, verbose):
  """Return number of derivations of target."""
  goal_target_string = " ".join(target)

  def node_fn(unused_span_begin, unused_span_end, rule, children):
    """Represent nodes as (target string, int count of possible derivations)."""
    target_strings = [target_string for target_string, _ in children]
    new_target_string = qcfg_rule.apply_target(rule, target_strings)

    child_counts = [child_count for _, child_count in children]

    count = _aggregate_counts(child_counts)

    return (new_target_string, count)

  def postprocess_fn(nodes):
    """Discard nodes that cannot reach goal and aggregate counts."""
    counts_dict = collections.defaultdict(int)
    for target_string, count in nodes:
      # Discard any targets that are not substrings of goal target.
      if target_string not in goal_target_string:
        continue
      counts_dict[target_string] += count
    return [
        (target_string, count) for target_string, count in counts_dict.items()
    ]

  outputs = qcfg_parser.parse(
      source,
      rules,
      node_fn=node_fn,
      postprocess_cell_fn=postprocess_fn,
      verbose=verbose)

  for target_string, count in outputs:
    if target_string == goal_target_string:
      return count

  raise ValueError("No target derivation for example (%s, %s)" %
                   (source, target))
Return number of derivations of target.
language/compgen/nqg/model/induction/codelength_utils.py