コード例 #1
0
def random_model(n1, n2, k, cap):
    """
    create a graph with the partition A of size n1
    and partition B of size n2 using the random model
    :param n1: size of partition A
    :param n2: size of partition B
    :param k: length of preference list for vertices in A
    :param cap: capacity of a vertex in partition B
    :return: bipartite graph with above properties
    """
    def order_by_master_list(l, master_list):
        return sorted(l, key=master_list.index)

    g = Graph()

    # create the sets R and H, r_1 ... r_n1, h_1 .. h_n2
    R = set('r{}'.format(i) for i in range(1, n1 + 1))
    H = set('h{}'.format(i) for i in range(1, n2 + 1))

    for res in R:
        g.residents.append(Resident(res))

    for hosp in H:
        g.hospitals.append(Hospital(hosp, 0, cap))

    # prepare a master list
    # master_list = list(h for h in H)
    # random.shuffle(master_list)

    pref_lists_H, pref_lists_R = collections.defaultdict(list), {}
    for resident in R:
        r_ind = resident[1:]
        pref_list = random.sample(H, min(
            len(H), k))  # random.randint(1, len(H)))  # sample houses
        pref_lists_R[
            resident] = pref_list  # order_by_master_list(pref_list, master_list)
        # add these residents to the preference list for the corresponding hospital
        for hospital in pref_list:
            h_ind = hospital[1:]
            pref_lists_H[hospital].append(resident)
            g.edges.append(Edge(r_ind, h_ind))

        res = g.get_resident(resident)
        for hosp in pref_lists_R[resident]:
            res.pref.append(g.get_hospital(hosp))

    for hospital in H:
        random.shuffle(pref_lists_H[hospital])
        hosp = g.get_hospital(hospital)
        for res in pref_lists_H[hospital]:
            hosp.pref.append(g.get_resident(res))

    return g
コード例 #2
0
def seat_model_generator(n1, n2, k_low, k_up):
    """
    create a graph with the partition R of size n1 and
    partition H of size n2
    :param n1: size of partition R
    :param n2: size of partition H
    :param k_low, k_up: range for length of resident preference lists
    """
    def order_by_master_list(l, master_list):
        return sorted(l, key=master_list.index)

    possible_credits = [5, 10, 15, 20]
    # set up geometric distribution among above possible hospital credits
    probs = np.random.geometric(p=0.10, size=len(possible_credits))
    probs = probs / np.sum(probs)

    def get_hosp_credits():
        return list(
            np.random.choice(possible_credits, size=1, replace=False,
                             p=probs))[0]

    def get_hosp_capacity_uniform():
        # returns the average hospital capacity based on resident, hospital credits
        res_cap_sum = 0
        hosp_cred_sum = 0
        for r in g.residents:
            res_cap_sum += r.uq
        for h in g.hospitals:
            hosp_cred_sum += h.credits

        return int(np.ceil((1.5 * res_cap_sum) / hosp_cred_sum))

    def get_hosp_capacity_non_uniform(cap):
        low = int(np.ceil(0.3 * cap))
        high = int(np.ceil(1.7 * cap))
        return random.randint(low, high)

    g = Graph()

    # default hospital capacity
    cap = 60

    # create the sets R and H, r_1 ... r_n1, h_1 .. h_n2
    R = list('r{}'.format(i) for i in range(1, n1 + 1))
    H = list('h{}'.format(i) for i in range(1, n2 + 1))

    for res in R:
        g.residents.append(Resident(res))

    for hosp in H:
        g.hospitals.append(Hospital(hosp, 0, cap, get_hosp_credits()))

    # prepare a master list
    master_list = list(r for r in R)
    random.shuffle(master_list)

    # setup a probability distribution over the hospitals
    p = np.random.geometric(p=0.10, size=len(H))

    # normalize the distribution
    p = p / np.sum(p)  # p is a ndarray, so this operation is correct

    prob_dict = dict(zip(H, p))
    master_list_h = sorted(H, key=lambda h: prob_dict[h], reverse=True)

    pref_H, pref_R = collections.defaultdict(list), {}
    for r in R:
        # sample hospitals according to the probability distribution and without replacement
        k = random.randint(k_low, k_up)
        pref_R[r] = list(
            np.random.choice(H, size=min(len(H), k), replace=False, p=p))
        # add these residents to the preference list for the corresponding hospitals
        for h in pref_R[r]:
            pref_H[h].append(r)

    for r in R:
        pref_R[r] = order_by_master_list(pref_R[r], master_list_h)
        # random.shuffle(pref_R[r])
        res = g.get_resident(r)
        for hosp in pref_R[r]:
            res.pref.append(g.get_hospital(hosp))

    for h in H:
        pref_H[h] = order_by_master_list(pref_H[h], master_list)
        # random.shuffle(pref_H[h])
        hosp = g.get_hospital(h)
        for res in pref_H[h]:
            hosp.pref.append(g.get_resident(res))

    g.init_resident_capacities()

    # get average capacity for hospitals
    cap = get_hosp_capacity_uniform()
    for h in g.hospitals:
        h.uq = get_hosp_capacity_non_uniform(cap)

    # initialize class constraints for residents
    g.init_all_resident_class()

    # initialize master class constraints applicable to all residents
    g.init_master_classes_disjoint()

    return g
コード例 #3
0
def mahadian_model(n1, n2, k, cap):
    """
    create a graph with the partition R of size n1 and
    partition H of size n2 using the model as described in
    Marriage, Honesty, and Stability
    Immorlica, Nicole and Mahdian, Mohammad
    Sixteenth Annual ACM-SIAM Symposium on Discrete Algorithms
    :param n1: size of partition R
    :param n2: size of partition H
    :param k: length of preference list for the residents
    :param cap: capacity of the hospitals
    :return: bipartite graph with above properties
    """
    def order_by_master_list(l, master_list):
        return sorted(l, key=master_list.index)

    g = Graph()

    # create the sets R and H, r_1 ... r_n1, h_1 .. h_n2
    R = list('r{}'.format(i) for i in range(1, n1 + 1))
    H = list('h{}'.format(i) for i in range(1, n2 + 1))

    # prepare a master list
    master_list = list(r for r in R)
    random.shuffle(master_list)

    for res in R:
        g.residents.append(Resident(res))

    for hosp in H:
        g.hospitals.append(Hospital(hosp, 0, cap))

    # setup a probability distribution over the hospitals
    p = np.random.geometric(p=0.10, size=len(H))

    # normalize the distribution
    p = p / np.sum(p)  # p is a ndarray, so this operation is correct

    prob_dict = dict(zip(H, p))
    master_list_h = sorted(H, key=lambda h: prob_dict[h], reverse=True)
    # print(prob_dict, master_list_h, sep='\n')

    pref_H, pref_R = collections.defaultdict(list), {}
    for r in R:
        # sample women according to the probability distribution and without replacement
        pref_R[r] = list(
            np.random.choice(H, size=min(len(H), k), replace=False, p=p))
        # add these man to the preference list for the corresponding women
        r_ind = r[1:]
        for h in pref_R[r]:
            h_ind = h[1:]
            pref_H[h].append(r)
            g.edges.append(Edge(r_ind, h_ind))

    for r in R:
        pref_R[r] = order_by_master_list(pref_R[r], master_list_h)
        res = g.get_resident(r)
        for hosp in pref_R[r]:
            res.pref.append(g.get_hospital(hosp))

    for h in H:
        pref_H[h] = order_by_master_list(pref_H[h], master_list)
        #random.shuffle(pref_H[h])
        hosp = g.get_hospital(h)
        for res in pref_H[h]:
            hosp.pref.append(g.get_resident(res))

    return g