【问题标题】:Optimization solution / algorithm for occupying tenants in houses (combinations)房屋占用租户优化方案/算法(组合)
【发布时间】:2019-06-06 09:22:00
【问题描述】:

我需要解决一个优化问题,其中租户必须根据首选位置和邻居占用房屋。

这是输入:

n 个房子:h1,h2,...,hn, m 个租户:t1,t2,...,tm

选择: 每个租户必须根据优先级 1-第一优先级、2-第二优先级、3-第三优先级选择最多 3 个位置。 每个租户必须根据优先级选择最多 3 个邻居 1-第一优先级、2-第二优先级、3-第三优先级(也可以是不居住的人...)

例如: t1 想住在房子里: 最高优先级(1):h12 中优先级 (2):h5 最低优先级(3):h3

t1 希望以下内容成为他的邻居: 最高优先级 (1):t5 中等优先级 (2):t15 最低优先级 (3):t6

  • 对于所需位置和邻居之间的平衡,可以考虑(非强制性)一个加权因子,例如,对于希望他的朋友对他关闭但不关心他的房子将在哪里的租户来说,0 位置和 1 个邻居位于,或 1 个位置和 0 个邻居用于想要高优先级位置且不关心他的邻居是谁的租户(0.5 个位置和 0.5 个邻居用于希望算法平等平衡其选择的租户)

我正在寻找一种优化算法来提供最佳解决方案(如果存在),以便根据输入占用所需房屋中的租户。 这是什么类型的问题?优化?解决此类问题的最佳方法是什么?线性规划? 注意:可以更改输入以简化解决方案或让算法更可靠地收敛。

我如何数学公式化: (1)表示房屋(生成树?)的房屋位置邻近关系,如何表示距离较近或较远的房屋? (2) 具有优先级的相邻关系(租户想住在 X 旁边但不想住在 Y 旁边)? 如何将这些条件/约束写成方程式?

我需要一个好的起点,学术论文,想法,文档,如何解决这个问题。

非常感谢您的帮助!

我可以使用 Matlab、Python 或任何编码语言/平台来测试想法。

【问题讨论】:

  • 我已经使用混合整数规划模型来解决类似的问题。
  • 这不完全符合您的问题,但您可能会发现 stable roommates problem 的方法和目标函数很有帮助。

标签: algorithm optimization combinatorics linear-programming


【解决方案1】:

这确实是一个优化问题,只要你有一个想要最大化的适应度函数。

如果您的问题只有“我想要这所房子”类型的优先级。这将是一个分配问题。您可以使用匈牙利(也称为 Kuhn-Munkres)算法来解决它。

这个想法是建立一个对偶图,一侧是房屋,另一侧是租户。您根据优先级在每对房屋/租户之间放置权重(即,如果想要这所房子,则为 1,否则为 0)。您还必须在具有较少节点的一侧创建接收节点,因为该算法将准确地为每个租户分配一个房屋,以最大化所选的权重。例如,如果 n>m,则创建 n-m 个幽灵租户(所有边的权重为 0)以匹配左侧的空房子。 该算法的复杂度为 O(N^3),N = max(n, m)。

“我喜欢这个邻居”类型的优先级处理起来相当复杂。他们带来的约束就像推销员问题。每个租户都希望拥有最好的下一个邻居(权重 A/B = A 想要 B + B 想要 A)。不幸的是,这个问题是 NP 完全的,这意味着您必须测试大多数组合数学才能找到最佳解决方案 (O(!N))。

如果 N 非常大,可以使用启发式解决方案。你接受有一个可能不是最好的好的解决方案。例如使用贪心算法:你首先将几个具有最佳权重的邻居放在一起,等等。

编辑:如果您真的想要最佳解决方案。它是最大化适应度函数 F(来自权重优先级)的函数。

首先,计算每个租户 i 的潜在“幸福感”Pi,即

  • 最佳房屋重量,
  • 两个最佳邻居权重。

然后使用启发式方法找到一个好的解决方案 F0。例如一个简单的贪心算法。你把房客一个一个地带到最幸福的房子里。如果可能,从具有更高位置优先级的租户开始,并以具有更高邻居优先级的租户结束。

现在您想探索提高 Fmax 的可能性树,目前为 F0。但是您无法探索完整的树(!N 种可能性)。所以你必须“修剪”一些分支。这意味着每次您将租户安置在房屋中时,您都会计算该分支的潜力。对于每个租户,您检查哪些愿望不能再完成,并总结出最好的剩余选择。如果 F Fmax,你找到了一个更好的解决方案,更新 Fmax。

注意:您的初始解决方案 F0 越好,您不必探索的分支越多,您的代码运行速度就越快。对 F0 的小幅改进可以将执行时间改变几个数量级。

【讨论】:

  • 谢谢文斯。我明白。我可以以某种方式将邻居优先级“添加”到分配问题中吗?如果没有,你知道解决位置和邻居的方法吗?我可以忽略简化所需优先级的数量,但我确实想要房屋和邻居的组合。房屋和租户的数量相同(约 20 个,所以 N 相对较小),所以我不关心复杂性,如果需要它可以运行几个小时。
  • 不,您不能将邻居约束添加到分配问题。事实上,您必须一一测试完整的解决方案。 N=20 很小,但 !20 是巨大的。如果您真的想要最佳解决方案,我会在我的解决方案中添加一个编辑。
【解决方案2】:

一种选择是使用约束规划来解决这个问题。这是一个简单的 MiniZinc 模型 (https://www.minizinc.org),适用于房屋和租户数量相同 (=5) 的情况:

% data
int: n = 5;
set of int: HOUSE = 1..n;
set of int: PEOPLE = 1..n;

array[PEOPLE, HOUSE] of 0..3: houseValue = array2d(PEOPLE, HOUSE, [
    0, 2, 3, 1, 0,
    0, 2, 3, 1, 0,
    0, 2, 3, 0, 1,
    0, 3, 2, 1, 0,
    0, 2, 1, 3, 0]);
array[PEOPLE, PEOPLE] of 0..3: neighbourValue = array2d(PEOPLE, PEOPLE, [
    0, 2, 3, 1, 0,
    0, 0, 3, 1, 2,
    2, 0, 0, 1, 3,
    0, 3, 2, 0, 1,
    1, 2, 3, 0, 0]);

% model
include "globals.mzn";

% decision variables - who lives in each house?
array[HOUSE] of var PEOPLE: tenant;

% constraint - exactly one person lives in each house
constraint alldifferent(tenant);

var int: objHouse = 
    sum(h in HOUSE where tenant[h] > 0)(houseValue[tenant[h], h]);
var int: objNeighbours = 
    sum(h in HOUSE where h > 1)(neighbourValue[tenant[h], tenant[h-1]]) + % left neighbour
    sum(h in HOUSE where h < n)(neighbourValue[tenant[h], tenant[h+1]]); % right neighbour

solve 
maximize objHouse + objNeighbours;

output ["obj = \(objHouse + objNeighbours)\n"] ++ ["objHouse = \(objHouse)\n"] ++ ["objNeighbours = \(objNeighbours)\n"] ++ ["tenant = \(tenant)"];

对于较大的实例,混合整数规划模型可能会表现出更好的性能。

这个答案考虑了所有房屋都排成一排并且只有直接邻居重要的情况。

【讨论】:

  • 非常感谢马格努斯!非常有帮助!请解释输入,但主要是输出:obj = 18 objHouse=6 objNeighbours=12 tenant=[5, 3 , 2, 1, 4] obj=20 objHouse=8 objNeighbours=12 tenant = [5, 4 , 2, 1, 3] obj=22 objHouse=6 objNeighbours=16 tenant=[2, 5 , 3, 1, 4] obj=24 objHouse=8 objNeighbours=16 tenant=[4, 1 , 3, 5, 2] obj=25 objHouse=10 objNeighbours=15 tenant=[1, 4 , 2, 5, 3] 我如何知道为每个租户选择了哪所房子?选择了哪些邻居?
  • 输出显示逐渐改进的解决方案。最后的双线表示最后一个解决方案是最佳的。显示为每个租户选择的房屋的一种优雅方法是引入一个新变量array[PEOPLE] of var HOUSE: house;,并添加一个约束通道house 到tenant,如constraint inverse(tenant, house);。最后将新变量house 附加到输出语句中。
  • 输入参数houseValue和neighbourValue是我对你的数据的理解。每个人可以给房屋和其他人一次 3、2 和 1 值,其余为 0。在这里,如果您想对多个数据使用相同的模型,最好将数据和模型拆分为单独的文件。
猜你喜欢
  • 1970-01-01
  • 2013-11-22
  • 1970-01-01
  • 1970-01-01
  • 2011-09-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-20
  • 1970-01-01
相关资源
最近更新 更多