计算每次比较两个事物的比较等级

时间:2016-05-28 15:51:33

标签: algorithm ranking

当输入数据如下时,如何计算表达一个人的相对偏好的10件事物的权重:

10个事物的列表以随机对的形式呈现(忽略顺序,因此可能显示A对B,或B对A,但不是两者;而不是自身的项目);

A is better than B
D is better than F
H is better than B
C is better than J

有没有办法对像这样的数据中的10个项目进行排名或加权?有没有办法缩短10的序列! /(2!(10 - 2)!)= 45个问题。

3 个答案:

答案 0 :(得分:3)

你在这里做出了一个危险的心理假设:你认为"比#34;更好。关系是传递性的,所以来自

A > B
B > C

直接遵循

A > C

即,不失一般性,不是人类喜好的情况。所以这使你的整个方法处于可疑的状态。

但是,如果你可以证明这个假设是正确的,那么,这就分解了一个排序问题。那里有一大堆排序算法,只依赖于排序关系的存在">"。那么你的体重就是排序列表中的位置。

每个真实的编程语言都可能有一个包含至少一个分类器算法的库;大多数语言也有一种方法可以指定要调用哪个函数来比较两个元素,所以这实际上归结为调用带有未排序列表的分类器函数和比较两个函数时要调用的函数。

如果假设"优于"关系是不可传递的,事情变得复杂得多。基本上,您可以构建有向图并尝试通过它查找路径,但该图可能不是无周期的,并且可能没有明确的可能性来分配任何权重。

有几十年的心理学方法研究如何测试这些东西;我建议找一所提供心理学课程并向那里的人询问的大学。

答案 1 :(得分:3)

为了使用这样的规则对数据进行排名,关系"better"必须是transitive

  

所以可能会显示A vs B,或者B vs A,但不是两者

这是朝着正确方向迈出的一步,但这不太具有传递性。你仍然可以这样做:

A is better than B
B is better than C
C is better than A

现在您有一个周期,因此上述三条规则不能用于对项目进行排名。

如果没有周期,您可以使订单符合规则。但是,排序可能不一定是唯一的。例如,如果您的规则看起来像这样

A is better than B
C is better than B

你需要订购{A,B,C}" ACB"和" CAB"符合你的规则。

如果您正在寻找基于规则的任何一致排序,您可以先构建一个由您的" X优于Y"规则,然后使用该树来决定十个项目的相对顺序。

答案 2 :(得分:0)

TL; DR: 将列表中的每个元素彼此比较,并为获胜的选择分配权重或值。然后,根据获得的“获胜”次数对每个元素进行排名。

这些都是非常有效的有效回复,指出了需要提出的限制,但没有提供解决方案。我提供一个...

进行相对比较时,在此示例中,根据主观偏爱进行排名,毫无疑问,缺乏一致性会破坏传递性的完整性。但是,您可以克服这一点。怎么样?好吧,使用问题中建议的内容:权重。

将列表中的每个元素彼此比较,并为获胜的选择分配权重或值。然后,根据获得的“胜利”数量对每个元素进行排名。

每场胜利不必具有相同的权重。例如,如果一个元素击败了排名较高或排名最高的元素,它将获得额外的积分或其他奖励。 Idk,发疯!

因此,这并不是一个科学的明确排名系统(如果没有客观的衡量,您永远都不会获得这种排名),但是我认为,采用这种方法,您可以取得相当不错的成绩。

我编写了一个简单的java命令行程序来比较水果。 下面是我的解决方案,它对我一直在寻找的东西“足够好”。我希望其他人也能找到帮助。

package com.example;

import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;

public class ComparativeRanking {

    public static void main(String[] args) throws Exception {
        ComparativeRanking instance = new ComparativeRanking();
        final List<Fruit> fruits = Lists.newArrayList(
                new Fruit("banana"),
                new Fruit("apple"),
                new Fruit("kiwi"),
                new Fruit("strawberry"),
                new Fruit("mango"));
        Fruit[] fruitArray = fruits.toArray(new Fruit[0]);
        instance.compute(fruitArray);
    }

    void compute(Fruit[] fruitArray) throws Exception {
        for (int i = 0; i < fruitArray.length; i++) {
            for (int k = i + 1; k < fruitArray.length; k++) {
                Fruit choice1 = fruitArray[i];
                Fruit choice2 = fruitArray[k];
                System.out.println(String.format("Enter '1' for %s and '2' for %s", choice1.name, choice2.name));
                Scanner scanner = new Scanner(System.in);
                int selection = scanner.nextInt();
                switch (selection) {
                    case 1:
                        choice1.addWin();
                        break;
                    case 2:
                        choice2.addWin();
                        break;
                    default:
                        throw new Exception("Hey idiot, pick 1 or 2.");
                }
            }
        }

        List<Fruit> fruitsRankedByWins = Lists.newArrayList(fruitArray)
                .stream()
                .sorted(Comparator.comparing(Fruit::getWins).reversed())
                .collect(Collectors.toList());

        System.out.println("Result:");
        for (Fruit fruit : fruitsRankedByWins) {
            System.out.println(String.format("Fruit: %s | Wins: %s", fruit.getName(), fruit.getWins()));
        }
    }

    @Getter
    @Setter
    static class Fruit {
        String name;
        int wins;
        public Fruit(String name) {this.name = name;}
        void addWin() {
            wins++;
        }
    }
}