Returns a list that associates all the winners of a profile under The Chamberlin–Courant rule.

        :ivar Profile profile: A Profile object that represents an election profile.

def single_peaked_winners(self, profile, d=1, K=3, funcType='Borda', scoringVector=[]):
        """
        Returns a list that associates all the winners of a profile under The Chamberlin–Courant rule.

        :ivar Profile profile: A Profile object that represents an election profile.
        """

        # Currently, we expect the profile to contain complete ordering over candidates. Ties are
        # allowed however.
        elecType = profile.getElecType()
        if elecType != "soc" and elecType != "toc" and elecType != "csv":
            print("ERROR: unsupported election type")
            exit()

        # ------------------1. INITIALIZATION-----------------------------
        m = profile.numCands
        n = profile.numVoters
        cand = list(profile.candMap.keys())
        cand.append(cand[m - 1] + 1)
        theta = n - d
        if funcType == 'Borda':
            scoringVector = MechanismBorda().getScoringVector(profile)
        z = dict()
        for k in range(1, K + 2):  # k = 1,...,K + 1
            z[k] = dict()
            for j in range(1, m + 2):
                z[k][j] = dict()

        for j in range(1, m + 2):
            for t in range(0, theta + 1):
                z[1][j][t] = self.s(profile, 1, j, t, {cand[j - 1]}, scoringVector)
                for k in range(1, K + 1):
                    z[k + 1][j][t] = float("-inf")

        # ------------------2. MAIN LOOP-----------------------------
        for k in range(1, K + 1):
            # Predecessors loop:
            for p in range(1, m + 1):
                for u in range(0, theta + 1):
                    if z[k][p][u] != float("-inf"):
                        # Successors sub-loop:
                        for j in range(p + 1, m + 2):
                            for t in range(u, theta + 1):
                                z[k + 1][j][t] = max(z[k + 1][j][t], z[k][p][u]
                                                     + self.s(profile, p + 1, j, t - u, {cand[p - 1], cand[j - 1]},
                                                              scoringVector))

        max_utility = z[K + 1][m + 1][theta]
        print("max_utility=", max_utility)
        # --------------------3. OUTPUT WINNERS---------------------------
        winners = []
        temp_max = max_utility
        j = m + 1
        t = theta
        for k in range(K + 1, 1, -1):
            z_k_j_t = array(
                [[z[k - 1][p][u] + self.s(profile, p + 1, j, t - u, {cand[p - 1], cand[j - 1]}, scoringVector)
                  for u in range(0, theta + 1)] for p in range(1, m + 1)])
            p_ind = where(temp_max == z_k_j_t)[0][0]
            u_ind = where(temp_max == z_k_j_t)[0][0]
            p0 = list(range(1, m + 1))[p_ind]
            u0 = list(range(0, theta + 1))[u_ind]
            winners.append(p0)
            temp_max = z[k][p0][u0]
            j = p0
            t = u0

        return sorted(winners)