<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def find_centroid_alleles(alleles, bp=28, t=0.025):
 """Reduce list of alleles to set of centroid alleles based on size grouping, ends matching and hierarchical clustering Workflow for finding centroid alleles: - grouping by size (e.g. 100bp, 101bp, 103bp, etc) - then grouped by `bp` nucleotides at ends matching - size and ends grouped alleles hierarchically clustered (Hamming distance, complete linkage) - tree cutting at threshold `t` - select allele with minimum distance to other alleles in cluster as centroid Args: alleles (iterable):
 collection of allele nucleotide sequences bp (int):
 number of bp matching at allele ends for size grouping (default=28 due to default blastn megablast word size) t (float):
 cluster generation (tree cutting) distance threshold for size grouped alleles Returns: set of str: centroid alleles """

    centroid_alleles = set()
    len_allele = group_alleles_by_size(alleles)
    for length, seqs in len_allele.items():
        # if only one alelle of a particular size, add as centroid, move onto next size group
        if len(seqs) == 1:
            centroid_alleles.add(seqs[0])
            continue
        # convert allele nucleotide sequences to integer matrix
        seq_arr = seq_int_arr(seqs)
        # group alleles by matching ends
        starts_ends_idxs = group_alleles_by_start_end_Xbp(seq_arr, bp=bp)
        for k, idxs in starts_ends_idxs.items():
            # if only one allele for a particular matching ends group, then add as centroid and move onto next ends group
            if len(idxs) == 1:
                centroid_alleles.add(seqs[idxs[0]])
                continue
            # fetch subset of int allele sequences for a matching ends group
            seq_arr_subset = seq_arr[idxs]
            # Hamming distances between alleles
            dists = pdist(seq_arr_subset, 'hamming')
            # create flat clusters (tree cut) at t threshold
            cl = allele_clusters(dists, t=t)
            # for each allele cluster
            dm_sq = squareform(dists)
            for cl_key, cl_idxs in cl.items():
                # if only 1 or 2 alleles in cluster then return first
                if len(cl_idxs) == 1 or len(cl_idxs) == 2:
                    # get first cluster index and get nt seq for that index
                    centroid_alleles.add(seq_int_arr_to_nt(seq_arr_subset[cl_idxs[0]]))
                    continue
                # else find allele with min distances to all other alleles in cluster
                dm_sub = dm_subset(dm_sq, cl_idxs)
                min_idx = min_row_dist_sum_idx(dm_sub)
                # add nucleotide seq for cluster centroid allele to centroids set
                centroid_alleles.add(seq_int_arr_to_nt(seq_arr_subset[min_idx]))
            #end for cl_key, cl_idxs in cl.iteritems():
        #end for k, idxs in starts_ends_idxs.iteritems():
    #end for length, seqs in alleles.iteritems():
    return centroid_alleles