Return candidate set with smallest goal functional.

def _get_best_subset(self, ritz):
        '''Return candidate set with smallest goal functional.'''

        # (c,\omega(c)) for all considered subsets c
        overall_evaluations = {}

        def evaluate(_subset, _evaluations):
            try:
                _evaluations[_subset] = \
                    self.subset_evaluator.evaluate(ritz, _subset)
            except utils.AssumptionError:
                # no evaluation possible -> move on
                pass

        # I in algo
        current_subset = frozenset()

        # evaluate empty set
        evaluate(current_subset, overall_evaluations)

        while True:
            # get a list of subset candidates for inclusion in current_subset
            # (S in algo)
            remaining_subset = set(range(len(ritz.values))) \
                .difference(current_subset)
            subsets = self.subsets_generator.generate(ritz, remaining_subset)

            # no more candidates to check?
            if len(subsets) == 0:
                break

            # evaluate candidates
            evaluations = {}
            for subset in subsets:
                eval_subset = current_subset.union(subset)
                evaluate(eval_subset, evaluations)

            if len(evaluations) > 0:
                current_subset = min(evaluations, key=evaluations.get)
            else:
                # fallback: pick the subset with smallest residual
                # note: only a bound is used if the subset consists of more
                #       than one index.
                resnorms = [numpy.sum(ritz.resnorms[list(subset)])
                            for subset in subsets]
                subset = subsets[numpy.argmin(resnorms)]
                current_subset = current_subset.union(subset)

            overall_evaluations.update(evaluations)

        if len(overall_evaluations) > 0:
        # if there was a successfull evaluation: pick the best one
            selection = list(min(overall_evaluations,
                             key=overall_evaluations.get))
        else:
            # otherwise: return empty list
            selection = []

        # debug output requested?
        if self.print_results == 'number':
            print('# of selected deflation vectors: {0}'
                  .format(len(selection)))
        elif self.print_results == 'values':
            print('{0} Ritz values corresponding to selected deflation '
                  .format(len(selection)) + 'vectors: '
                  + (', '.join([str(el) for el in ritz.values[selection]])))
        elif self.print_results == 'timings':
            import operator
            print('Timings for all successfully evaluated choices of '
                  'deflation vectors with corresponding Ritz values:')
            for subset, time in sorted(overall_evaluations.items(),
                                       key=operator.itemgetter(1)):
                print(' {0}s: '.format(time)
                      + ', '.join([str(el)
                                   for el in ritz.values[list(subset)]]))
        elif self.print_results is None:
            pass
        else:
            raise utils.ArgumentError(
                'Invalid value `{0}` for argument `print_result`. '
                .format(self.print_results)
                + 'Valid are `None`, `number`, `values` and `timings`.')

        return selection