简体   繁体   English

使用约束规划解决稳定婚姻问题 - BoundedLinearExpression object 不可迭代

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM