def _get_rule_penalty(rule, config, examples, verbose=False):
  """Returns a "penalty" for the rule based on the given set of examples."""
  # TODO(petershaw): This could potentially be more effecient by pre-indexing
  # the examples in a data structure such as a Trie.
  # TODO(petershaw): Could also consider sub-sampling the dataset for the
  # purpose of computing these correlations.

  # Optionally compute over a sample of examples only.
  sample_size = config.get("sample_size", 0)

  num_examples_match_source = 0
  num_examples_match_target = 0
  num_examples_match_source_and_target = 0
  for source_str, target_str in examples:
    source = tuple(source_str.split())
    target = tuple(target_str.split())
    match_source = rule_utils.rhs_can_maybe_derive(rule.source, source)
    match_target = rule_utils.rhs_can_maybe_derive(rule.target, target)
    if match_source:
      num_examples_match_source += 1
    if match_target:
      num_examples_match_target += 1
    if match_source and match_target:
      num_examples_match_source_and_target += 1

    if sample_size and num_examples_match_source_and_target >= sample_size:
      # Break early if using sample size and found sufficient sample.
      break

  # Ensure that at least one example is found.
  if not num_examples_match_source_and_target:
    print("Rule did not match any examples.")
    # TODO(petershaw): Raise instead?
    return 0.0
  if not num_examples_match_source:
    raise ValueError("num_examples_match_source: %s" %
                     num_examples_match_source)
  if not num_examples_match_target:
    raise ValueError("num_examples_match_target: %s" %
                     num_examples_match_target)

  if verbose:
    print("_get_rule_cost: %s" % rule)
    print("num_examples_match_source: %s" % num_examples_match_source)
    print("num_examples_match_target: %s" % num_examples_match_target)
    print("num_examples_match_source_and_target: %s" %
          num_examples_match_source_and_target)

  cost = 0.0
  p_source_given_target = (
      float(num_examples_match_source_and_target) / num_examples_match_target)
  cost -= (
      config["source_given_target_coef"] * math.log2(p_source_given_target))
  p_target_given_source = (
      float(num_examples_match_source_and_target) / num_examples_match_source)
  cost -= (
      config["target_given_source_coef"] * math.log2(p_target_given_source))
  return cost
Returns a "penalty" for the rule based on the given set of examples.
language/compgen/csl/induction/objective_utils.py