【问题标题】:Assignement problem in a subscription system订阅系统中的分配问题
【发布时间】:2022-08-13 21:36:18
【问题描述】:

我正在开发订阅系统,我需要处理输出数据以正确且自动地注册订阅者。

我主要使用 PHP/Mysql,但这不是 PHP/Mysql 问题,而是数据排序问题。

我的数据有两组:

\"topics\"=> [
    \"Women rights\"=> [\"capacity\"=>3]
    \"Chelter\"=> [\"capacity\"=>5]
    \"Charity\"=> [\"capacity\"=>7]
    \"Training\"=> [\"capacity\"=>17]
    \"Child care\"=> [\"capacity\"=>13]
    \"Nursing\"=> [\"capacity\"=>8]
    \"Garbage collection\"=> [\"capacity\"=>2]
    \"Managing\"=> [\"capacity\"=>1]
]
\"applications\"= [
    \"Alan\"=>[
        [\"topic\"=>\"Charity\",            \"priority\"=>1, \"rankInTopic\"=>1],
        [\"topic\"=>\"Chelter\",            \"priority\"=>2, \"rankInTopic\"=>3],
        [\"topic\"=>\"Garbage collection\", \"priority\"=>3, \"rankInTopic\"=>1],
        [\"topic\"=>\"Managing\",           \"priority\"=>4, \"rankInTopic\"=>12]
        ]
    \"David\"=>[
        [\"topic\"=>\"Women rights\",       \"priority\"=>4, \"rankInTopic\"=>2],
        [\"topic\"=>\"Chelter\",            \"priority\"=>3, \"rankInTopic\"=>2],
        [\"topic\"=>\"Garbage collection\", \"priority\"=>1, \"rankInTopic\"=>3],
        [\"topic\"=>\"Managing\",           \"priority\"=>2, \"rankInTopic\"=>9]
        [\"topic\"=>\"Nursing\",            \"priority\"=>5, \"rankInTopic\"=>3]
        [\"topic\"=>\"Charity\",            \"priority\"=>6, \"rankInTopic\"=>3]
        ]
    \"Sonia\"=>[
        [\"topic\"=>\"Chelter\",            \"priority\"=>2, \"rankInTopic\"=>1],
        [\"topic\"=>\"Training\",           \"priority\"=>1, \"rankInTopic\"=>5]
        ]
    \"Robert\"=>[
        [\"topic\"=>\"Garbage collection\", \"priority\"=>6, \"rankInTopic\"=>2],
        [\"topic\"=>\"Child care\",         \"priority\"=>3, \"rankInTopic\"=>2],
        [\"topic\"=>\"Women rights\",       \"priority\"=>1, \"rankInTopic\"=>1],
        [\"topic\"=>\"Managing\",           \"priority\"=>2, \"rankInTopic\"=>4]
        [\"topic\"=>\"Nursing\",            \"priority\"=>5, \"rankInTopic\"=>1]
        [\"topic\"=>\"Charity\",            \"priority\"=>4, \"rankInTopic\"=>5]
        ]
    \"Diana\"=>[
        [\"topic\"=>\"Child care\",         \"priority\"=>1, \"rankInTopic\"=>1]
        ]
    ]

我只想为每个申请人订阅一个主题。 主题按“rankInTopic”字段排序,然后按“优先级”字段排序。 谢谢

    标签: sorting processing


    【解决方案1】:

    你想做的事情的术语是匹配而不是排名或排序。

    这个问题可以表示为加权二分匹配。有时这也称为“分配问题”。

    数据结构是具有边权重的无向图。一组顶点将是主题区域中的“座位”。每单位容量一个顶点。另一组将是申请人。每个申请人的偏好都是各自席位的优势。边的权重是一个整数。为了兼顾优先级和排名,您需要以单个数字表示的词典顺序。足够大的东西,例如rankInTopic * sum(all priorities) + priority 会起作用。

    现在,一个标准的加权二分匹配算法将选择将每个申请人与一个座位匹配的边。它选择的边集将具有最小的可能总和。 (一些实现被连接到找到最大值。然后你会想要否定边缘权重。)

    Hungarian Algorithm 是经典解决方案。 Iirc,一个好的实现是 O(n^3) 的顶点数。您可以寻找一个库或自己实现它。这不是微不足道的,但也不可怕。

    我实际上使用此算法将学生与学术环境中的所需课程相匹配。它运作良好。我添加了一些参数来使用比连续偏好更复杂的权重。例如。如果我想通过让其他人获得不太理想的作业来支持给最大数量的学生他们的第一偏好,我可以尝试像 1,5,6,7... 这样的权重优先级 1,2,3,4.. . 或者,如果我想让所有学生都获得前 3 名,我会使用 1,2,3,10,.... 能够解释算法并充满信心地说出来真是太好了分配是最佳的。

    编辑

    您找到了一个需要方阵作为输入的实现。这比允许矩形的效率低,但应该没问题。所以它处理 N 个事物以匹配 N 个其他事物。 IE。匹配将是完美的。

    让矩阵的列成为这些主题的座位。所以前三个将是“妇女权利”,接下来的 5 个将是“切尔特”,等等。看起来总共有 54 个。

    行将是人。只有5个,那么其他49个怎么办?用非常高的相等权重填充它们。我认为 1e6 会工作。该算法将确保首先使用基于优先级的低得多的加权边缘。这些都将连接到“真实”的人。 49位“伪人物”将最后匹配未使用的话题席位。这些匹配将毫无意义并被忽略。

    对于position [person P, seat in Topic T]中的权重,使用(priority * 10000 + rankInTopic),其中priority和rank是P对T的权重。如果P已经表示对T没有偏好,那么使用大数的意思“无穷”。像一百万这样的东西应该可以工作。

    将此传递给算法。返回值应该是一个包含 54 个元素的数组。前五行将显示每个人匹配的座位。您可以从中确定他们所在的主题。其余的将包含与任意未使用席位的匹配。

    对于此类问题,PHP 是一个性能不佳的环境(除非您以某种方式编译为本机代码,即使那样)。此外,此实现将浪费内存和时间来计算不需要的匹配。维基百科页面中提到的 Java 实现接受一个矩形数组,因此更适合这个任务。将 Java 转换为 PHP 可能需要几个小时。

    【讨论】:

    • 我不是数学家,所以我仍然在同一点上。我可以计算矩阵,并在 PHP 中找到了匈牙利算法的实现:github.com/rpfk/Hungarian 我正在尝试使用它但没有成功。
    • 你好。我添加了一些实现说明。
    • 非常感谢吉恩,你很有帮助。事实上,我错了。我使用的排名女巫是基于计算的分数。这些分数和偏好有一些重复。我不知道是否存在三个维度的解决方案。我用旧的方式解决了这个问题,通过增加主题和偏好的分数来填充座位的所有选择,然后丢弃未满足的偏好和填充的主题。
    • 嗨 Gene,我在 php 中发现了这个可以处理矩形矩阵的实现。我想用它。此分配问题中最重要的参数是,首先通过每个主题中基于十进制 100 的分数的数值将人员分配给主题,然后按偏好(1 到 10)分配。理想情况下,最终结果将在该顺序内填充每个主题席位。非常感谢。 github.com/SarahJehin/php-munkres
    猜你喜欢
    • 1970-01-01
    • 2014-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 2011-03-04
    相关资源
    最近更新 更多