def confusion_matrix(class_match_set, class_nonmatch_set, true_match_set,
                     all_comparisons):
  """Compute the confusion (error) matrix which has the following form:

     +-----------------+-----------------------+----------------------+
     |                 |  Predicted Matches    | Predicted NonMatches |
     +=================+=======================+======================+
     | True  Matches   | True Positives (TP)   | False Negatives (FN) |
     +-----------------+-----------------------+----------------------+
     | True NonMatches | False Positives (FP)  | True Negatives (TN)  |
     +-----------------+-----------------------+----------------------+

     The four values calculated in the confusion matrix (TP, FP, TN, and FN)
     are then the basis of linkag equality measures such as precision and
     recall.

     Parameter Description:
       class_match_set    : Set of classified matches (record identifier
                            pairs)
       class_nonmatch_set : Set of classified non-matches (record identifier
                            pairs)
       true_match_set     : Set of true matches (record identifier pairs)
       all_comparisons    : The total number of comparisons between all record
                            pairs

     This function returns a list with four values representing TP, FP, FN,
     and TN.
  """

  print('Calculating confusion matrix using %d classified matches, %d ' % \
        (len(class_match_set), len(class_nonmatch_set)) + 'classified ' + \
        'non-matches, and %d true matches' % (len(true_match_set)))

  num_tp = 0  # number of true positives
  num_fp = 0  # number of false positives
  num_tn = 0  # number of true negatives
  num_fn = 0  # number of false negatives

  # Iterate through the classified matches to check if they are true matches or
  # not
  #
  for rec_id_tuple in class_match_set:
    if (rec_id_tuple in true_match_set):
      num_tp += 1
    else:
      num_fp += 1

  # Iterate through the classified non-matches to check of they are true
  # non-matches or not
  #
  for rec_id_tuple in class_nonmatch_set:

    # Check a record tuple is only counted once
    #
    assert rec_id_tuple not in class_match_set, rec_id_tuple

    if (rec_id_tuple in true_match_set):
      num_fn += 1
    else:
      num_tn += 1

  # Finally count all missed true matches to the false negatives
  #
  for rec_id_tuple in true_match_set:
    if ((rec_id_tuple not in class_match_set) and \
        (rec_id_tuple not in class_nonmatch_set)):
      num_fn += 1

  num_tn = all_comparisons - num_tp - num_fp - num_fn

  print('  TP=%s, FP=%d, FN=%d, TN=%d' % (num_tp, num_fp, num_fn, num_tn))
  print('')

  return [num_tp, num_fp, num_fn, num_tn]