<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _findRedundantProteins(protToPeps, pepToProts, proteins=None):
 """Returns a set of proteins with redundant peptide evidence. After removing the redundant proteins from the "protToPeps" and "pepToProts" mapping, all remaining proteins have at least one unique peptide. The remaining proteins are a "minimal" set of proteins that are able to explain all peptides. However, this is not guaranteed to be the optimal solution with the least number of proteins. In addition it is possible that multiple solutions with the same number of "minimal" proteins exist. Procedure for finding the redundant proteins: 1. Generate a list of proteins that do not contain any unique peptides, a unique peptide has exactly one protein entry in "pepToProts". 2. Proteins are first sorted in ascending order of the number of peptides. Proteins with an equal number of peptides are sorted in descending order of their sorted peptide frequencies (= proteins per peptide). If two proteins are still equal, they are sorted alpha numerical in descending order according to their protein names. For example in the case of a tie between proteins "A" and "B", protein "B" would be removed. 3. Parse this list of sorted non unique proteins; If all its peptides have a frequency value of greater 1; mark the protein as redundant; remove its peptides from the peptide frequency count, continue with the next entry. 4. Return the set of proteins marked as redundant. :param pepToProts: dict, for each peptide (=key) contains a set of parent :param protToPeps: dict, for each protein (=key) contains a set of :param proteins: iterable, proteins that are tested for being redundant. If None all proteins in "protToPeps" are parsed. :returns: a set of redundant proteins, i.e. proteins that are not necessary to explain all peptides """

    if proteins is None:
        proteins = viewkeys(protToPeps)

    pepFrequency = _getValueCounts(pepToProts)
    protPepCounts = _getValueCounts(protToPeps)

    getCount = operator.itemgetter(1)
    getProt = operator.itemgetter(0)

    #TODO: quick and dirty solution
    #NOTE: add a test for merged proteins
    proteinTuples = list()
    for protein in proteins:
        if isinstance(protein, tuple):
            proteinTuples.append(protein)
        else:
            proteinTuples.append(tuple([protein]))

    sort = list()
    for protein in sorted(proteinTuples, reverse=True):
        if len(protein) == 1:
            protein = protein[0]

        protPepFreq = [pepFrequency[pep] for pep in protToPeps[protein]]
        if min(protPepFreq) > 1:
            sortValue = (len(protPepFreq)*-1, sorted(protPepFreq, reverse=True))
            sort.append((protein, sortValue))
    sortedProteins = map(getProt, sorted(sort, key=getCount, reverse=True))

    redundantProteins = set()
    for protein in sortedProteins:
        for pep in protToPeps[protein]:
            if pepFrequency[pep] <= 1:
                break
        else:
            protPepFrequency = Counter(protToPeps[protein])
            pepFrequency.subtract(protPepFrequency)
            redundantProteins.add(protein)
    return redundantProteins