尝试为 Python 中的医生和医院创建匹配算法,卡在条件下

Trying to create a matching algorithm for doctors and hospitals in Python, stuck on conditions

首先,我想指出,我在python中是一个菜鸟,所以如果我的措辞或问题本身听起来很愚蠢,请耐心等待,只是想学习。

我创建了两本词典,一本是给医院排名的医生,另一本是给医生排名的医院。 医生到医院:

{'Doctor_5': {1.0: 'Hospital_7', 2.0: 'Hospital_6', 3.0: 'Hospital_8', 4.0: 'Hospital_5', 5.0: 'Hospital_9', 6.0: 'Hospital_4', 7.0: 'Hospital_10', 8.0: 'Hospital_3', 9.0: 'Hospital_2', 10.0: 'Hospital_1'}, 'Doctor_9': {1.0: 'Hospital_9', 2.0: 'Hospital_8', 3.0: 'Hospital_10', 4.0: 'Hospital_7', 5.0: 'Hospital_6', 6.0: 'Hospital_5', 7.0: 'Hospital_4', 8.0: 'Hospital_3', 9.0: 'Hospital_2', 10.0: 'Hospital_1'}, 'Doctor_8': {1.0: 'Hospital_8', 2.0: 'Hospital_9', 3.0: 'Hospital_10', 4.0: 'Hospital_7', 5.0: 'Hospital_6', 6.0: 'Hospital_5', 7.0: 'Hospital_4', 8.0: 'Hospital_3', 9.0: 'Hospital_2', 10.0: 'Hospital_1'}, 'Doctor_1': {1.0: 'Hospital_1', 2.0: 'Hospital_2', 3.0: 'Hospital_3', 4.0: 'Hospital_4', 5.0: 'Hospital_5', 6.0: 'Hospital_6', 7.0: 'Hospital_7', 8.0: 'Hospital_8', 9.0: 'Hospital_9', 10.0: 'Hospital_10'}, 'Doctor_4': {1.0: 'Hospital_5', 2.0: 'Hospital_6', 3.0: 'Hospital_4', 4.0: 'Hospital_7', 5.0: 'Hospital_3', 6.0: 'Hospital_2', 7.0: 'Hospital_1', 8.0: 'Hospital_8', 9.0: 'Hospital_9', 10.0: 'Hospital_10'}, 'Doctor_3': {1.0: 'Hospital_4', 2.0: 'Hospital_3', 3.0: 'Hospital_2', 4.0: 'Hospital_1', 5.0: 'Hospital_5', 6.0: 'Hospital_6', 7.0: 'Hospital_7', 8.0: 'Hospital_8', 9.0: 'Hospital_9', 10.0: 'Hospital_10'}, 'Doctor_6': {1.0: 'Hospital_7', 2.0: 'Hospital_8', 3.0: 'Hospital_6', 4.0: 'Hospital_9', 5.0: 'Hospital_5', 6.0: 'Hospital_10', 7.0: 'Hospital_4', 8.0: 'Hospital_3', 9.0: 'Hospital_2', 10.0: 'Hospital_1'}, 'Doctor_7': {1.0: 'Hospital_8', 2.0: 'Hospital_7', 3.0: 'Hospital_9', 4.0: 'Hospital_6', 5.0: 'Hospital_5', 6.0: 'Hospital_4', 7.0: 'Hospital_3', 8.0: 'Hospital_2', 9.0: 'Hospital_1'}, 'Doctor_10': {1.0: 'Hospital_10', 2.0: 'Hospital_9', 3.0: 'Hospital_8', 4.0: 'Hospital_7', 5.0: 'Hospital_6', 6.0: 'Hospital_5', 7.0: 'Hospital_4', 8.0: 'Hospital_3', 9.0: 'Hospital_2', 10.0: 'Hospital_1'}, 'Doctor_2': {1.0: 'Hospital_3', 2.0: 'Hospital_2', 3.0: 'Hospital_4', 4.0: 'Hospital_1', 5.0: 'Hospital_5', 6.0: 'Hospital_6', 7.0: 'Hospital_7', 8.0: 'Hospital_8', 9.0: 'Hospital_9', 10.0: 'Hospital_10'}}

医院到医生:

{'Hospital_2': {1.0: 'Doctor_1', 2.0: 'Doctor_2', 3.0: 'Doctor_3', 4.0: 'Doctor_4', 5.0: 'Doctor_5', 6.0: 'Doctor_6', 7.0: 'Doctor_7', 8.0: 'Doctor_8', 9.0: 'Doctor_9', 10.0: 'Doctor_10'}, 'Hospital_1': {1.0: 'Doctor_1', 2.0: 'Doctor_2', 3.0: 'Doctor_3', 4.0: 'Doctor_4', 5.0: 'Doctor_5', 6.0: 'Doctor_6', 7.0: 'Doctor_7', 8.0: 'Doctor_8', 9.0: 'Doctor_9', 10.0: 'Doctor_10'}, 'Hospital_8': {1.0: 'Doctor_8', 2.0: 'Doctor_9', 3.0: 'Doctor_7', 4.0: 'Doctor_6', 5.0: 'Doctor_10', 6.0: 'Doctor_4', 7.0: 'Doctor_3', 8.0: 'Doctor_2', 9.0: 'Doctor_1'}, 'Hospital_7': {1.0: 'Doctor_5', 2.0: 'Doctor_6', 3.0: 'Doctor_7', 4.0: 'Doctor_8', 5.0: 'Doctor_3', 6.0: 'Doctor_2', 7.0: 'Doctor_9', 8.0: 'Doctor_1', 9.0: 'Doctor_10'}, 'Hospital_10': {1.0: 'Doctor_10', 2.0: 'Doctor_9', 3.0: 'Doctor_8', 4.0: 'Doctor_7', 5.0: 'Doctor_6', 6.0: 'Doctor_5', 7.0: 'Doctor_4', 8.0: 'Doctor_3', 9.0: 'Doctor_2', 10.0: 'Doctor_1'}, 'Hospital_3': {1.0: 'Doctor_1', 2.0: 'Doctor_2', 3.0: 'Doctor_3', 4.0: 'Doctor_4', 5.0: 'Doctor_5', 6.0: 'Doctor_6', 7.0: 'Doctor_7', 8.0: 'Doctor_8', 9.0: 'Doctor_9', 10.0: 'Doctor_10'}, 'Hospital_9': {1.0: 'Doctor_9', 2.0: 'Doctor_10', 3.0: 'Doctor_8', 4.0: 'Doctor_7', 5.0: 'Doctor_6', 6.0: 'Doctor_5', 7.0: 'Doctor_4', 8.0: 'Doctor_3', 9.0: 'Doctor_2', 10.0: 'Doctor_1'}, 'Hospital_5': {1.0: 'Doctor_4', 2.0: 'Doctor_3', 3.0: 'Doctor_2', 4.0: 'Doctor_1', 5.0: 'Doctor_5', 6.0: 'Doctor_6', 7.0: 'Doctor_7', 8.0: 'Doctor_8', 9.0: 'Doctor_9', 10.0: 'Doctor_10'}, 'Hospital_4': {1.0: 'Doctor_3', 2.0: 'Doctor_2', 3.0: 'Doctor_4', 4.0: 'Doctor_1', 5.0: 'Doctor_5', 6.0: 'Doctor_6', 7.0: 'Doctor_7', 8.0: 'Doctor_8', 9.0: 'Doctor_9', 10.0: 'Doctor_10'}, 'Hospital_6': {1.0: 'Doctor_4', 2.0: 'Doctor_5', 3.0: 'Doctor_6', 4.0: 'Doctor_3', 5.0: 'Doctor_2', 6.0: 'Doctor_1', 7.0: 'Doctor_8', 8.0: 'Doctor_9', 9.0: 'Doctor_10'}}

我还创建了一个医生列表,因为它用于创建由算法生成的 DataFrame 的索引:

['Doctor_5', 'Doctor_9', 'Doctor_8', 'Doctor_1', 'Doctor_4', 'Doctor_3', 'Doctor_6', 'Doctor_7', 'Doctor_10', 'Doctor_2']

现在我正在尝试创建一种算法,根据 Gale-Shapley 算法(无需了解具体细节)将医生分配给医院。

这是我到目前为止的想法,最后我将它呈现在 DataFrame 中,因为我发现它更容易解释:

Matches = {}
Matches['Doctors'] = (doctors)
First_round = []
for Doctor_ in ranking_by_doctors:
    First_round.append(ranking_by_doctors[Doctor_].get(1.0))
Matches['First round'] = (First_round)
Matches
Matches_round_1 = pd.DataFrame.from_dict(Matches)
Matches_round_1.set_index('Doctors', inplace=True)
Matches_round_1   

这是我的结果:

如您所见,我正在将每个医生最喜欢的医院分配给该医生。但我需要有关我的职能条件的帮助。截至目前,我的结果中存在重复项:doctor_7 和 doctor_8 都与 hospital_8 匹配,类似地 hospital_7 与两个不同的医生匹配。但是,我想在我的功能中添加一个条件,在这种情况下,检查医院最喜欢哪个医生,匹配那个医生,让另一个医生不匹配。之后,我想为未匹配的医生重新开始整个过程​​,从而在第 2 轮中得出新的结果。对于第二轮,已经匹配的医院应该有可能打破他们的匹配,因为医生接近他们时他们更喜欢他们的第一场匹配。

然而,在调整我的函数几个小时并探索 google 和列出理解指南以寻求帮助之后,我仍然没有找到解决方案。这就是为什么我转向 Whosebug 寻求帮助,也许你们中的一个人以前见过这个问题并且可以帮助我解决它。如果您还需要以上提供的信息,请告诉我!

非常感谢您,

我将 First_round 更改为字典,使其更直接一些。我还会建议一些其他的结构更改,但之后会更多。一个解决方案是简单地 pu in 一个 if 检查是否已经分配了特定的医院,然后如果他有更好的分数交换医生:

def hospital_ranking_of_doctor(hospital, doctor):
    return next(v for k, v in ranking_by_hospital[hospital].items() if v == doctor)

Matches = {}
Matches['Doctors'] = (doctors)
First_round = {}

# We loop through all the doctors one by one
for Doctor_ in ranking_by_doctors:

    # Then we find which hospital the doctor prefers
    favored_hospital = ranking_by_doctors[Doctor_].get(1.0)

    # We test if that hospital has already had a doctor assigned
    if favored_hospital not in First_round:
        # If it has not, then we just assign the current doctor
        First_round[favored_hospital] = Doctor_
    else:
        # If the hosptial was already assigned a doctor we compare 
        # that doctor with the new one and set the new one only if 
        # the hospital prefers him.
        previously_assigned_doctor = First_round[favored_hospital]
        if hospital_ranking_of_doctor(favored_hospital, previously_assigned_doctor) > hospital_ranking_of_doctor(favored_hospital, Doctor_):
            First_round[favored_hospital] = Doctor_

print(First_round)

现在对于结构更改,我认为您也应该将排名结构从一个范围从数字到 hospitals/doctors 的字典更改为只是一个有序的偏好列表或翻转它,所以关键是hospital/doctor 和 priority/score 是值。这将使检查医生的分数更自然,例如:

ranking_by_hospital['Hospital_2']['Doctor_2'] > ranking_by_hospital['Hospital_2']['Doctor_3']

因此您可以将排名函数更新为:

def hospital_ranking_of_doctor(hospital, doctor):
    return ranking_by_hospital[hospital][doctor]

或者简单地内联那些代码位。