【问题标题】:Software to optimise people's preferences优化人们偏好的软件
【发布时间】:2016-07-31 21:25:57
【问题描述】:

假设我有两种颜色的棒棒糖,每种颜色有五个棒棒糖(总共十个),我想将这些棒棒糖分发给我的朋友。我们每个人都会提交一些排名偏好:

本:1 - 橙色,2 - 绿色,3 - 红色

乔:1 - 绿色,2 - 蓝色,3 - 红色

蒂姆:1 - 橙色,2 - 红色,3 - 蓝色 等等

我可以使用任何软件来“最小化”我们必须做出的全部牺牲吗? (例如,让每个人尽可能接近他们的第一偏好)

【问题讨论】:

  • 您是否尝试过平方误差之和?(假设 ben、joe 和 tim 同等重要)或其加权版本(例如 ben 更重要)
  • help center 非常清楚地表明 要求我们推荐或查找书籍、工具、软件库、教程或其他非现场资源的问题对于 Stack Overflow 来说是题外话,因为它们倾向于吸引固执己见的答案和垃圾邮件。

标签: optimization preference voting voting-system


【解决方案1】:

这个问题缺乏一个好的模型。目标/损失的不同表述将导致完全不同的行为/解决方案。

这是一种混合整数编程方法(因为您的问题已经是 np-hard):

模型 A

  • 第一偏好给出满意 X,第二:Y,... (9, 4, 1, 0) = 平方反比
    • 这相当于最小二乘解/l2-范数解(= 较大的失误比较小的失误更难处罚)
  • 我们希望最大限度地提高总体满意度

模型效果

  • 不要尝试给每个人相同数量的棒棒糖

代码

import math
import numpy as np
from cvxpy import *

# PROBLEM
# -------
# colors = orange, green, red, blue
n_colors = 4
n_lollies_per_color = 5
n_lollies = n_colors * n_lollies_per_color
prefs = np.asarray([[0, 1, 2, 3],
                    [1, 3, 2, 0],
                    [0, 2, 3, 1]])
n_persons = prefs.shape[0]
n_lollies_per_person = n_lollies / n_persons

# SOLVER
# ------
per_person_per_lolly_satisfaction_vector = np.asarray([[n_colors -1 - np.where(prefs[p, :] == c)[0]
                                                        for c in range(n_colors)]
                                                        for p in range(n_persons)]).reshape((3,4))
# Decision-vars
X = Int(n_persons, n_colors)

# Constraints
constraints = []
# non-zero lollies
constraints.append(X >= 0)
# exactly n_lollies_per_color are distributed
for c in range(n_colors):
  constraints.append(sum_entries(X[:,c]) == n_lollies_per_color)

# Objective
objective = Maximize(sum_entries(mul_elemwise(np.square(per_person_per_lolly_satisfaction_vector), X)))

problem = Problem(objective, constraints)
problem.solve(verbose=False)
print(problem.value)
print(np.round(X.value))  # Rows -> persons; Columns -> amount of lollies they got

输出

129.9999999837688
[[ 1.  0.  0.  0.]
 [ 0.  5.  0.  5.]
 [ 4.  0.  5.  0.]]

观察

  • 第一个人只得到 1 个棒棒糖,而其他人得到 9/10(如预期的那样)

型号 B

  • 与 A 相同,但我们只允许在每个人之间获得 1 的棒棒糖数量差异 -> 这是硬编码到约束中(更强大的软约束更难实现 ->关键词:凸度)

效果

  • 根据获得的棒棒糖数量公平分配棒棒糖

代码差异

只需添加这些约束:

# lower and upper bound on lollies received -> at most 1 lolly less than      everyone else
for p in range(n_persons):
    constraints.append(sum_entries(X[p, :]) >= math.floor(n_lollies_per_person))
    constraints.append(sum_entries(X[p, :]) <= math.ceil(n_lollies_per_person))

输出

119.99999984107899
[[ 5.  0.  0.  1.]
 [-0.  5.  0.  2.]
 [ 0.  0.  5.  2.]]

观察

  • 我们以一定的代价获得了公平的分配:
    • 我们完全失去了满意度(120 对 130)

【讨论】:

    猜你喜欢
    • 2021-11-21
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-23
    • 1970-01-01
    相关资源
    最近更新 更多