用于优化人们偏好的软件

时间:2016-07-31 21:25:57

标签: optimization preference voting voting-system

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

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

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

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

我能用什么软件来“模仿”我们必须做出的全部牺牲? (例如,让所有人尽可能接近他们的第一选择)

1 个答案:

答案 0 :(得分:0)

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

这是一种混合整数编程方法(因为你的问题已经是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)