如何创建“至少n个”约束?

时间:2019-08-13 20:08:06

标签: python algorithm constraints constraint-programming or-tools

我是约束编程的新手,试图弄清楚如何进行“至少n个”约束。

例如,我的整数变量x,y和z都在0到5的范围内。

现在,我需要所有至少两个变量在2到3之间的解决方案。

类似于“给定条件之和> = 2”

我该如何在python中,最好是在Google的OR-Tools中做到这一点?

谢谢

2 个答案:

答案 0 :(得分:1)

假设您具有这些条件

x = 2.5
y = 4
z = 2.9

然后,您可以构建值列表,然后应用lambdamapsum来找出问题。例如:

# Create the list of values
values = [x, y, z]

# Apply a lambda to each element of the list, checking if they
# are within [2,3]. This would return a boolean, so I am translating
# those to 1 and 0
ones_or_zeroes = map(lambda x: 1 if 2<=x<=3 else 0, values)

# Check condition of how many matched the condition:
condition = sum(ones_or_zeroes)

当然可以压缩为:

if sum(map(lambda x: 1 if 2<=x<=3 else 0, values)) >= 2:
    # then at least 2 variables match the costraint
    pass

答案 1 :(得分:1)

from ortools.sat.python import cp_model
import collections


class SolutionPrinter(cp_model.CpSolverSolutionCallback):
    """Print intermediate solutions."""

    def __init__(self, variables):
        cp_model.CpSolverSolutionCallback.__init__(self)
        self.__variables = variables
        self.__num_vars = len(variables)
        self.__num_values = len(variables[0])
        self.__solution_count = 0

    def on_solution_callback(self):
        self.__solution_count += 1
        for var in range(self.__num_vars):
            for value in range(self.__num_values):
                if self.BooleanValue(self.__variables[var][value]):
                    print('var[%i]=%i' % (var, value), end=' ')
                    break
        print()

    def solution_count(self):
        return self.__solution_count


num_vars = 3
max_values = 5

model = cp_model.CpModel()
vars = collections.defaultdict(list)

for var in range(num_vars):
    for value in range(max_values + 1):
        vars[var].append(model.NewBoolVar('x_%i_%i' % (var, value)))

# Exactly one value per variable
for var in range(num_vars):
    model.Add(sum(vars[var]) == 1)

# At least 2 between 2 and 3
model.Add(sum(vars[var][2] for var in range(num_vars)) +
          sum(vars[var][3] for var in range(num_vars)) >= 2)

# Enumerate all solutions
solver = cp_model.CpSolver()
solution_printer = SolutionPrinter(vars)
status = solver.SearchForAllSolutions(model, solution_printer)

print('Status = %s' % solver.StatusName(status))
print('Number of solutions found: %i' % solution_printer.solution_count())

输出

var[0]=3      var[1]=2      var[2]=0 
var[0]=3      var[1]=2      var[2]=5 
var[0]=3      var[1]=2      var[2]=4 
var[0]=3      var[1]=2      var[2]=1 
var[0]=3      var[1]=2      var[2]=3 
var[0]=3      var[1]=0      var[2]=3 
var[0]=3      var[1]=1      var[2]=3 
var[0]=3      var[1]=5      var[2]=3 
var[0]=3      var[1]=4      var[2]=3 
var[0]=3      var[1]=4      var[2]=2 
var[0]=3      var[1]=0      var[2]=2 
var[0]=3      var[1]=1      var[2]=2 
var[0]=3      var[1]=2      var[2]=2 
var[0]=3      var[1]=5      var[2]=2 
var[0]=3      var[1]=3      var[2]=2 
var[0]=3      var[1]=3      var[2]=4 
var[0]=3      var[1]=3      var[2]=5 
var[0]=3      var[1]=3      var[2]=1 
var[0]=3      var[1]=3      var[2]=0 
var[0]=3      var[1]=3      var[2]=3 
var[0]=5      var[1]=3      var[2]=3 
var[0]=1      var[1]=3      var[2]=3 
var[0]=4      var[1]=3      var[2]=3 
var[0]=2      var[1]=3      var[2]=3 
var[0]=0      var[1]=3      var[2]=3 
var[0]=2      var[1]=3      var[2]=0 
var[0]=2      var[1]=3      var[2]=5 
var[0]=2      var[1]=3      var[2]=4 
var[0]=2      var[1]=3      var[2]=1 
var[0]=2      var[1]=3      var[2]=2 
var[0]=5      var[1]=3      var[2]=2 
var[0]=1      var[1]=3      var[2]=2 
var[0]=4      var[1]=3      var[2]=2 
var[0]=0      var[1]=3      var[2]=2 
var[0]=0      var[1]=2      var[2]=2 
var[0]=5      var[1]=2      var[2]=2 
var[0]=4      var[1]=2      var[2]=2 
var[0]=1      var[1]=2      var[2]=2 
var[0]=2      var[1]=2      var[2]=2 
var[0]=2      var[1]=0      var[2]=2 
var[0]=2      var[1]=1      var[2]=2 
var[0]=2      var[1]=5      var[2]=2 
var[0]=2      var[1]=4      var[2]=2 
var[0]=2      var[1]=2      var[2]=1 
var[0]=2      var[1]=2      var[2]=0 
var[0]=2      var[1]=2      var[2]=5 
var[0]=2      var[1]=2      var[2]=4 
var[0]=2      var[1]=2      var[2]=3 
var[0]=2      var[1]=0      var[2]=3 
var[0]=2      var[1]=1      var[2]=3 
var[0]=5      var[1]=2      var[2]=3 
var[0]=4      var[1]=2      var[2]=3 
var[0]=1      var[1]=2      var[2]=3 
var[0]=2      var[1]=5      var[2]=3 
var[0]=2      var[1]=4      var[2]=3 
var[0]=0      var[1]=2      var[2]=3 
Status = OPTIMAL
Number of solutions found: 56