You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于主观偏好的排序算法迭代次数优化方案问询

如何在不降低确定性的前提下减少主观偏好排序算法的迭代次数

我需要实现一个基于用户主观偏好排序列表的交互算法,通过input()实现用户交互。核心目标是最大化结果确定性的同时,最小化用户需要回答的迭代次数。

当前我实现了一个简单算法:从列表中随机选取两项,询问用户偏好项,将未被选中项的部分分配系数转移至选中项,并调整双方系数。现咨询:如何在不降低算法确定性的前提下,减少该排序算法的迭代次数?

原实现代码(带中文注释)

# 给每个元素分配初始值为1.0的系数
def ListToDict(list_of_items):
    food_dict = {}
    for item in list_of_items:
        food_dict[item] = 1.0
    return food_dict

# 询问用户在两个选项中做选择
def AskUser(item_name_one, item_name_two):
    print("\n [" + item_name_one + "]  or  [" + item_name_two + "] ?")
    user_choice = input("--> ")
    if user_choice == "1" or user_choice == "2":
        return int(user_choice)
    else:
        print("\n请输入1或2!")
        return AskUser(item_name_one, item_name_two)

# PerformSort函数更新每个项的系数
# 每一步都会让用户在两个项中做选择
# 如果用户选第一个项,
#   第一个项的系数增加第二个项系数的0.1倍,
#   第二个项的系数减少第一个项系数的0.1倍(原逻辑存在计算顺序问题)
# 用户选第二个项时则相反
# number_of_iterations参数越高,结果确定性越强,但用户需要回答更多问题
def PerformSort(my_dict, number_of_iterations):
    from random import randint
    length_of_dict = len(my_dict)
    
    for i in range(number_of_iterations):
        print("\n---- 第" + str(i + 1) + "轮迭代 ----")
        remaining_items = list(my_dict.keys())
        while len(remaining_items) > 1: 
            item_one = remaining_items[randint(0, len(remaining_items) - 1)]
            item_two = remaining_items[randint(0, len(remaining_items) - 1)]
            while item_one == item_two:
                item_two = remaining_items[randint(0, len(remaining_items) - 1)]
            user_choice = AskUser(item_one, item_two)
            if user_choice == 1:
                my_dict[item_one] += 0.1 * my_dict[item_two]
                my_dict[item_two] -= 0.1 * my_dict[item_one]
            elif user_choice == 2:
                my_dict[item_one] -= 0.1 * my_dict[item_two]
                my_dict[item_two] += 0.1 * my_dict[item_one]
            remaining_items.remove(item_one)
            remaining_items.remove(item_two)
    return my_dict

# 根据系数对列表进行降序排序
def OrderByCoeficient(food_dict):
    list_of_keys = list(food_dict.keys())
    list_of_keys.sort(key=lambda x: food_dict[x], reverse=True)
    return list_of_keys


if __name__ == "__main__":
    items_to_sort = [ "披萨", "芝士汉堡", "牛肉", "汤", "冰淇淋" ]
    my_dict = ListToDict(items_to_sort)
    my_dict = PerformSort(my_dict, 3)
    print("\n 以下是你的偏好排序(从高到低):")
    print(OrderByCoeficient(my_dict))

优化方案

1. 优先对比系数最接近的项,而非随机配对

随机配对经常浪费用户时间在已有明确偏好的项上(比如系数差距大的两个),对提升结果确定性帮助极小。应该每次挑选当前系数最接近的一对让用户选择——这一对的排序是最不确定的,用户的选择能最大程度修正系数,快速缩小排序的不确定性。

2. 动态调整系数转移幅度,替代固定0.1

固定的0.1转移幅度在迭代后期效率很低:当两个项系数差距已经较大时,小幅度转移对排序结果几乎没有影响。可以根据两项的系数比例调整转移量:

  • 当系数比例在0.8~1.2之间(接近相等),转移更大比例(比如0.2),快速明确排序关系;
  • 当系数差距超过阈值(比如比例<0.5或>2),转移较小比例(比如0.05),避免过度修正。

3. 用“排序结果稳定”作为停止条件,替代固定迭代次数

固定迭代次数要么导致结果不够确定,要么做无用功。可以改成:当连续2~3次迭代后,排序结果的顺序完全没有变化,就停止迭代——既保证结果稳定,又不会让用户做多余回答。

4. 避免重复对比同一对项

维护一个已对比过的项对集合(比如用frozenset({item1, item2})存储),每次配对时跳过已经对比过的组合,彻底消除冗余提问。

5. 修正系数更新公式的逻辑错误

原代码中更新系数时,会先用修改后的item_one系数去计算item_two的减少量,导致逻辑矛盾。正确的做法是先计算固定的转移量,再同时更新两个系数:

# 用户选择item_one时的正确更新逻辑
transfer = 0.1 * my_dict[item_two]
my_dict[item_one] += transfer
my_dict[item_two] -= transfer

这样能避免数值误差累积,逻辑更严谨。

优化后的示例代码

def ListToDict(list_of_items):
    food_dict = {}
    for item in list_of_items:
        food_dict[item] = 1.0
    return food_dict

def AskUser(item_name_one, item_name_two):
    print("\n [" + item_name_one + "]  or  [" + item_name_two + "] ?")
    user_choice = input("--> ")
    if user_choice == "1" or user_choice == "2":
        return int(user_choice)
    else:
        print("\n请输入1或2!")
        return AskUser(item_name_one, item_name_two)

def GetClosestPair(item_dict):
    items = list(item_dict.keys())
    min_diff = float('inf')
    closest_pair = None
    # 遍历所有可能的项对,找到系数差最小的一对
    for i in range(len(items)):
        for j in range(i+1, len(items)):
            diff = abs(item_dict[items[i]] - item_dict[items[j]])
            if diff < min_diff:
                min_diff = diff
                closest_pair = (items[i], items[j])
    return closest_pair

def GetTransferRatio(coef1, coef2):
    ratio = min(coef1, coef2) / max(coef1, coef2)
    if ratio >= 0.8:
        return 0.2  # 系数接近时,转移更大比例
    elif ratio >= 0.5:
        return 0.15
    else:
        return 0.05  # 系数差距大时,转移小比例

def PerformSortOptimized(my_dict, max_stable_iterations=2):
    compared_pairs = set()
    last_order = None
    stable_count = 0

    while stable_count < max_stable_iterations:
        current_order = OrderByCoeficient(my_dict)
        # 如果排序结果和上一次一致,稳定计数加1
        if current_order == last_order:
            stable_count += 1
        else:
            stable_count = 0
            last_order = current_order

        remaining_items = list(my_dict.keys())
        while len(remaining_items) > 1:
            # 获取系数最接近的未对比过的项对
            pair = GetClosestPair({k:v for k,v in my_dict.items() if k in remaining_items})
            if not pair:
                break
            pair_frozen = frozenset(pair)
            # 如果已经对比过,跳过并移除其中一个项(避免死循环)
            if pair_frozen in compared_pairs:
                remaining_items.remove(pair[0])
                continue
            compared_pairs.add(pair_frozen)
            
            item_one, item_two = pair
            user_choice = AskUser(item_one, item_two)
            
            # 计算动态转移比例
            transfer_ratio = GetTransferRatio(my_dict[item_one], my_dict[item_two])
            if user_choice == 1:
                transfer = transfer_ratio * my_dict[item_two]
                my_dict[item_one] += transfer
                my_dict[item_two] -= transfer
            else:
                transfer = transfer_ratio * my_dict[item_one]
                my_dict[item_two] += transfer
                my_dict[item_one] -= transfer
            
            remaining_items.remove(item_one)
            remaining_items.remove(item_two)
        print("\n---- 当前排序已稳定{}轮 ----".format(stable_count+1))
    return my_dict

def OrderByCoeficient(food_dict):
    list_of_keys = list(food_dict.keys())
    list_of_keys.sort(key=lambda x: food_dict[x], reverse=True)
    return list_of_keys

if __name__ == "__main__":
    items_to_sort = [ "披萨", "芝士汉堡", "牛肉", "汤", "冰淇淋" ]
    my_dict = ListToDict(items_to_sort)
    my_dict = PerformSortOptimized(my_dict)
    print("\n 以下是你的偏好排序(从高到低):")
    print(OrderByCoeficient(my_dict))

内容的提问来源于stack exchange,提问作者Genaro.exe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 11:45:31