约束不受or-tools的尊重

问题描述

我有这个简单的CP程序:

from ortools.sat.python import cp_model
horizon = 5
model = cp_model.CpModel()
A = model.NewIntvar(1,horizon,'A')
C = model.NewIntvar(1,'C')
D = model.NewIntvar(1,'D')
E = model.NewIntvar(1,'E')
model.Add(max(A+C+D,A+D+E) > max(A+C+E,C+E+D))
solver = cp_model.cpsolver()
status = solver.solve(model)
if status in (cp_model.FEASIBLE,cp_model.OPTIMAL):
    print('status: ',status)
    print('A: ',solver.Value(A))
    print('C: ',solver.Value(C))
    print('D: ',solver.Value(D))
    print('E: ',solver.Value(E))
else:
    print('Could not solve')

运行它会给我:

status:  4
A:  5
C:  1
D:  1
E:  1

鉴于提供的约束,这是不正确的。我在做错什么吗?

解决方法

您不能将minmaxorand与ortools变量一起使用,因为它们会覆盖__ge____lt__创建线性表达式的神奇方法。

在这种情况下,您必须创建4个新变量(每个总和1个)和受model.AddMaxEquality约束的另外2个变量。您还可以使用2个布尔值来设置2个最大变量。

编辑:

acd = model.NewIntVar(1,3 * horizon,"ACD")
model.Add(acd == A + C + D)
ade = model.NewIntVar(1,"ADE")
model.Add(ade == A + D + E)
ace = model.NewIntVar(1,"ACE")
model.Add(ace == A + C + E)
ced = model.NewIntVar(1,"CED")
model.Add(ced == C + E + D)

max1 = model.NewIntVar(1,"max1")
max2 = model.NewIntVar(1,"max2")
model.AddMaxEquality(max1,[acd,ade])
model.AddMaxEquality(max2,[ace,ced])
model.Add(max1 > max2)
,

为了记录,请遵循Stradivari的答案:

#!/usr/bin/env python3
from ortools.sat.python import cp_model
horizon = 5
model = cp_model.CpModel()
A = model.NewIntVar(1,horizon,'A')
C = model.NewIntVar(1,'C')
D = model.NewIntVar(1,'D')
E = model.NewIntVar(1,'E')

#model.Add(max(A+C+D,A+D+E) > max(A+C+E,C+E+D))
acd = model.NewIntVar(1,ced])
model.Add(max1 > max2)

solver = cp_model.CpSolver()
status = solver.Solve(model)
if status in (cp_model.FEASIBLE,cp_model.OPTIMAL):
    print('status: ',status)
    print('A: ',solver.Value(A))
    print('C: ',solver.Value(C))
    print('D: ',solver.Value(D))
    print('E: ',solver.Value(E))

    print('ACD: ',solver.Value(acd))
    print('ADE: ',solver.Value(ade))
    print('max1: ',solver.Value(max1))

    print('ACE: ',solver.Value(ace))
    print('CED: ',solver.Value(ced))
    print('max2: ',solver.Value(max2))
else:
    print('Could not solve')

可能的输出:

%./max.py
status:  4
A:  2
C:  1
D:  2
E:  1
ACD:  5
ADE:  5
max1:  5
ACE:  4
CED:  4
max2:  4