Algorithm 利用电晕限制优化活动座位分配

Algorithm 利用电晕限制优化活动座位分配,algorithm,optimization,linear-programming,knapsack-problem,sat,Algorithm,Optimization,Linear Programming,Knapsack Problem,Sat,问题: 给定一组组注册,每个注册针对不同数量的人(1-7), 以及一组1-4个座位不等的座位组(不变,至少相隔2米), 我想找到座位组的最佳人员分配: 人员组可分为几个座位组(但最好不分) 座位组不能由不同的人群共享 (可选)分配应尽量减少“浪费”座位的数量,即最大限度地增加空座位组中的座位数量 (理想情况下,它应该在谷歌应用程序脚本中运行,因此内存和计算复杂性应该尽可能小) 第一次尝试: 我对决策问题(是否可行?)以及优化问题(参见可选优化函数)感兴趣。我将其建模为SAT问题,但这并没有找

问题: 给定一组组注册,每个注册针对不同数量的人(1-7), 以及一组1-4个座位不等的座位组(不变,至少相隔2米), 我想找到座位组的最佳人员分配:

  • 人员组可分为几个座位组(但最好不分)
  • 座位组不能由不同的人群共享
  • (可选)分配应尽量减少“浪费”座位的数量,即最大限度地增加空座位组中的座位数量
  • (理想情况下,它应该在谷歌应用程序脚本中运行,因此内存和计算复杂性应该尽可能小)
第一次尝试: 我对决策问题(是否可行?)以及优化问题(参见可选优化函数)感兴趣。我将其建模为SAT问题,但这并没有找到最佳解决方案

出于这个原因,我尝试将其建模为一个优化问题。我正在考虑(远程)多种背包的变化,但我还不能命名:

  • 项目:座位组(尺寸->重量)
  • 背包:人员组(大小->容器大小)
  • 约束:组合项目重量>=容器大小
  • 优化:最小化项目数量

如您所见,与标准问题相比,约束和优化是反向的。所以我的问题是:我在这条路上走对了吗?还是你会用另一种方式?如果它是正确的,这个优化问题有名字吗?

你可以把它看作一个整数线性规划问题,定义如下:

let P = the set of people groups, people group i consists of p_i people;
let T = the set of tables, table j has t_j places;
let x_ij be 1 if people from people group i are placed at table j, 0 otherwise
let M be a large penalty factor for empty seats
let N be a large penalty factor for splitting groups

     // # of free spaces = # unavailable - # occupied
     // every time a group uses more than one table,
     // a penalty of N * (#tables - 1) is incurred
min  M * [SUM_j(SUM_i[x_ij] * t_j) - SUM_i(p_i)] + N * SUM_i[(SUM_j(x_ij) - 1)]

     // at most one group per table
s.t. SUM_i(x_ij) <= 1 for all j

     // every group has enough seats
     SUM_j(x_ij * t_j) = p_i for all i

     0 <= x_ij <= 1
设P=人员组集合,人员组i由P_i人员组成;
设T=表集合,表j有T_j个位置;
如果将来自人员组i的人员放在表j中,则x_ij为1,否则为0
设M为空座位的大惩罚因子
设N是分裂群的一个大惩罚因子
//#可用空间数=#不可用-#已占用
//每次一个组使用多个表时,
//产生N*(#表-1)的罚款
最小M*[SUM_j(SUM_i[x_ij]*t_j)-SUM_i(p_i)]+N*SUM_i[(SUM_j(x_ij)-1]
//每桌最多一组

s、 t.SUM_i(x_ij)相关:由于您已经将问题建模为SAT问题,您可以使用加权MaxSAT来解决优化问题。@tphilipp好建议,我将研究它。我认为我的SAT解决方案可能不是最好的,因为它需要很多子句:关于sp²子句和sp变量,p是人数,s是座位数。相比之下,鲁本下面的ILP解决方案没有对个人或座位进行建模,将问题规模减少了约20倍,甚至减少了约束的数量(组*#表)。我想知道,使用此SAT解决方案的加权MaxSAT或Ruben提出的解决方案的任何ILP解算器是否可能运行更多的内存和时间效率。@Josta改进SAT编码的方法有很多。有时,即使在子句或变量上出现二次放大,也没有必要对其进行改进。取决于用例,SAT/MaxSAT可以显著优于ILP,或者可以解决ILP解算器根本无法解决的实例。另一个方向也适用我喜欢这个解决方案的简洁性和可扩展性,但我和你一样担心ILP解算器可能无法在谷歌应用程序中运行,即使是小规模的问题(但我没有LP经验)。如果我没有弄错的话,
M*[SUM_j(t_j)-SUM_I(p_I)]
是一个不变量。你可能想写一些类似于
M*[SUM_j[(1-MULT_i(1-x_ij))*t_j]-SUM_i(p_i)]
?我还假设它应该是伪代码倒数第二行中的
SUM_j
,你说的
SUM_j
是对的
M*[SUM_j(t_j)-SUM_i(p_i)]
确实是一个不变量,但我将
SUM_j(t_j)
更改为
SUM_j(SUM_i[x_ij]*t_j)
以确保不计算自由表。由于另一个约束,
SUM_i[x_ij]
对于每个表是0或1