def process_results(metrics):
    """Extract useful information from given metrics.

  Args:
    metrics: List of results dicts. These should have been written to disk by
        training jobs.

  Returns:
    Dict mapping stats names to values.

  Raises:
    ValueError: If max_npe or max_global_repetitions values are inconsistant
        across dicts in the `metrics` list.
  """
    count = len(metrics)
    success_count = 0
    total_npe = 0  # Counting NPE across all runs.
    success_npe = 0  # Counting NPE in successful runs only.
    max_npe = 0
    max_repetitions = 0
    for metric_dict in metrics:
        if not max_npe:
            max_npe = metric_dict['max_npe']
        elif max_npe != metric_dict['max_npe']:
            raise ValueError(
                'Invalid experiment. Different reps have different max-NPE settings.')
        if not max_repetitions:
            max_repetitions = metric_dict['max_global_repetitions']
        elif max_repetitions != metric_dict['max_global_repetitions']:
            raise ValueError(
                'Invalid experiment. Different reps have different num-repetition '
                'settings.')
        if metric_dict['found_solution']:
            success_count += 1
            success_npe += metric_dict['npe']
        total_npe += metric_dict['npe']
    stats = {'max_npe': max_npe, 'max_repetitions': max_repetitions, 'repetitions': count, 'successes': success_count,
             'failures': count - success_count, 'success_npe': success_npe, 'total_npe': total_npe}
    if success_count:
        # Only successful runs counted.
        stats['avg_success_npe'] = stats['success_npe'] / float(success_count)
    else:
        stats['avg_success_npe'] = 0.0
    if count:
        stats['success_rate'] = success_count / float(count)
        stats['avg_total_npe'] = stats['total_npe'] / float(count)
    else:
        stats['success_rate'] = 0.0
        stats['avg_total_npe'] = 0.0

    return stats