[英]Solve Stable Marriages Problem using constraint programming - BoundedLinearExpression object is not iterable
I'm taking a course on Discrete Optimization , and we're working through constraint programming.我正在学习离散优化课程,我们正在学习约束编程。 In a topic about reification, we're working through the Stable Marriages Problem (SPM).在关于具体化的主题中,我们正在解决稳定婚姻问题(SPM)。
The model formulation is model的配方是
enum Men = [George, Hugh, Will, Clive];
enum Women = [Julia, Halle, Angelina, Keira];
# mensRanking[Hugh, Julia] is Hugh's ranking of Julia
# lower the number, the higher the preference
int mensRanking[Men, Women];
int womensRanking[Women, Men];
# Decision variables below
# Array of decision variables called wives that is indexed on men stores the wife
# of man
var{Women} wives[Men]
# Array of decision variables called husbands that is indexed on women stores the
# husband of woman
var{Men} husbands[Women]
# Constraints below
solve {
# The husband of wife of man must equal man
forall(m in Men)
husband[wife[m]] = m;
# The wife of husband of woman must equal woman
forall(w in Women)
wife[husband[w]] = w;
# NEED HELP with the constraints below
forall(m in Man)
forall(w in Women)
# If man m prefers woman w over his wife, then
# woman w must prefer her husband over m
if (mensRanking[m,w] < mensRanking[m,wife[m]])
womensRanking[w,husband[w]] < womensRanking[w, m]
# If woman w prefers man m over her husband, then
# man m must prefer his wife over w
if (womensRanking[w,m] < womensRanking[w, husband[w]])
mensRanking[m,wife[m]] < mensRanking[m, w]
}
I can't figure out how to do the ranking comparison.我不知道如何进行排名比较。 Here's my attempt via or-tools in Python:这是我在 Python 中通过 or-tools 进行的尝试:
def main():
n = 4
men = range(n)
women = range(n)
# mensRanking[man][woman] is man's ranking of woman.
# lower the number, the higher the preference
mensRanking = [random.sample(range(n),n) for _ in men]
womensRanking = [random.sample(range(n),n) for _ in women]
model = cp_model.CpModel()
# For wife 'Julia', who is her husband?
husbands = [model.NewIntVar(0, n-1, f'woman{i}') for i in women]
# For husband 'George', who is his wife?
wives = [model.NewIntVar(0, n-1, f'man{i}') for i in men]
for man in men:
# The husband of wife of man must equal man
# I.e., husbands[wife] = man
wife = wives[man]
model.AddElement(wife, husbands, man)
for woman in women:
# The wife of husband of woman must equal woman
# I.e., wives[husband] = woman
husband = husbands[woman]
model.AddElement(husband, wives, woman)
for m in men:
for w in women:
womans_rank_of_husband = model.NewIntVar(0, n-1, '')
model.AddElement(husbands[w], womensRanking[w], womans_rank_of_husband)
mans_rank_of_wife = model.NewIntVar(0, n-1, '')
model.AddElement(wives[m], mensRanking[m], mans_rank_of_wife)
# If man m prefers woman w over his wife, then
# woman w must prefer her husband over m
# TypeError: 'BoundedLinearExpression' object is not iterable
model.Add(womans_rank_of_husband < womensRanking[w][m]).OnlyEnforceIf(
mensRanking[m][w] < mans_rank_of_wife
)
# If woman w prefers man m over her husband, then
# man m must prefer his wife over w
# TypeError: 'BoundedLinearExpression' object is not iterable
model.Add(mans_rank_of_wife < mensRanking[m][w]).OnlyEnforceIf(
womensRanking[w][m] < womans_rank_of_husband
)
solver = cp_model.CpSolver()
solution_printer = SolutionPrinter(x)
status = solver.SearchForAllSolutions(model, solution_printer)
print(solver.ResponseStats())
print(status)
Basically, I need to do an inequality check while using a decision variable as an index.基本上,我需要在使用决策变量作为索引时进行不等式检查。 I'm familiar with doing an EQUALITY check via model.AddElement(index, array, target)
for array[index] == target
, but can't figure out how to do array[index] < target
when index
is a decision variable.我熟悉通过model.AddElement(index, array, target)
对array[index] == target
进行 EQUALITY 检查,但不知道如何做array[index] < target
when index
is a decision variable .
EDIT : I used a temp_var as suggested by @Laurent-Perron, but now I'm getting the error:编辑:我按照@Laurent-Perron 的建议使用了 temp_var,但现在出现错误:
# TypeError: 'BoundedLinearExpression' object is not iterable
Any idea why?知道为什么吗? I also tried AddImplication
:我也试过AddImplication
:
womans_rank_of_husband = model.NewIntVar(0, n-1, '')
model.AddElement(husbands[w], womensRanking[w], womans_rank_of_husband)
mans_rank_of_wife = model.NewIntVar(0, n-1, '')
model.AddElement(wives[m], mensRanking[m], mans_rank_of_wife)
# If man m prefers woman w over his wife, then
# woman w must prefer her husband over m
model.AddImplication(mensRanking[m][w] < mans_rank_of_wife,
womans_rank_of_husband < womensRanking[w][m])
# If woman w prefers man m over her husband, then
# man m must prefer his wife over w
model.AddImplication(womensRanking[w][m] < womans_rank_of_husband,
mans_rank_of_wife < mensRanking[m][w])
But that gave me the error但这给了我错误
TypeError: NotSupported: model.GetOrMakeBooleanIndex(unnamed_var_12 <= 1)
at model.AddImplication()
.在model.AddImplication()
。
Create an intermediate var tmp_var, the use tmp_var in the inequality.创建一个中间变量 tmp_var,在不等式中使用 tmp_var。
AddElement(index, array, tmp_var)
Add(tmp_var < target)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.