Constraint Optimization

注:中文非直接翻译英文,而是理解加工后的笔记,记录英文仅为学其专业表述。

概述

Constraint optimization, or constraint programming(CP),约束优化(规划),用于在一个非常大的候选集合中找到可行解,其中的问题可以用任意约束来建模。

CP基于可行性(寻找可行解)而不是优化(寻找最优解),它更关注约束和变量,而不是目标函数。

SP-SAT Solver

CP-SAT求解器技术上优于传统CP求解器。

The CP-SAT solver is technologically superior to the original CP solver and should be preferred in almost all situations.

为了增加运算速度,CP求解器处理的都是整数。

如果有非整数项约束,可以先将其乘一个整数,使其变成整数项。

If you begin with a problem that has constraints with non-integer terms, you need to first multiply those constraints by a sufficiently large integer so that all terms are integers

来看一个简单例子:寻找可行解。

  • 变量x,y,z,每个只能取值0,1,2。
    • eg: x = model.NewIntVar(0, num_vals - 1, 'x')
  • 约束条件:x ≠ y
    • eg: model.Add(x != y)

核心步骤:

  • 声明模型
  • 创建变量
  • 创建约束条件
  • 调用求解器
  • 展示结果
from ortools.sat.python import cp_model

def SimpleSatProgram():
    """Minimal CP-SAT example to showcase calling the solver."""
    # Creates the model.
    model = cp_model.CpModel()

    # Creates the variables.
    num_vals = 3
    x = model.NewIntVar(0, num_vals - 1, 'x')
    y = model.NewIntVar(0, num_vals - 1, 'y')
    z = model.NewIntVar(0, num_vals - 1, 'z')

    # Creates the constraints.
    model.Add(x != y)

    # Creates a solver and solves the model.
    solver = cp_model.CpSolver()
    status = solver.Solve(model)

    if status == cp_model.FEASIBLE:
        print('x = %i' % solver.Value(x))
        print('y = %i' % solver.Value(y))
        print('z = %i' % solver.Value(z))

SimpleSatProgram()

运行得

x = 1
y = 0
z = 0

status = solver.Solve(model)返回值状态含义:

  • OPTIMAL 找到了最优解。
  • FEASIBLE 找到了一个可行解,不过不一定是最优解。
  • INFEASIBLE 无可行解。
  • MODEL_INVALID 给定的CpModelProto没有通过验证步骤。可以通过调用ValidateCpModel(model_proto)获得详细的错误。
  • UNKNOWN 由于达到了搜索限制,模型的状态未知。

加目标函数,寻找最优解

假设目标函数是求x + 2y + 3z的最大值,在求解器前加

model.Maximize(x + 2 * y + 3 * z)

并替换展示条件

if status == cp_model.OPTIMAL:

运行得

x = 1
y = 2
z = 2

加回调函数,展示所有可行解

去掉目标函数,加上打印回调函数

from ortools.sat.python import cp_model

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

    def __init__(self, variables):
        cp_model.CpSolverSolutionCallback.__init__(self)
        self.__variables = variables
        self.__solution_count = 0

    def on_solution_callback(self):
        self.__solution_count += 1
        for v in self.__variables:
            print('%s=%i' % (v, self.Value(v)), end=' ')
        print()

    def solution_count(self):
        return self.__solution_count

def SearchForAllSolutionsSampleSat():
    """Showcases calling the solver to search for all solutions."""
    # Creates the model.
    model = cp_model.CpModel()

    # Creates the variables.
    num_vals = 3
    x = model.NewIntVar(0, num_vals - 1, 'x')
    y = model.NewIntVar(0, num_vals - 1, 'y')
    z = model.NewIntVar(0, num_vals - 1, 'z')

    # Create the constraints.
    model.Add(x != y)

    # Create a solver and solve.
    solver = cp_model.CpSolver()
    solution_printer = VarArraySolutionPrinter([x, y, z])
    status = solver.SearchForAllSolutions(model, solution_printer)

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

SearchForAllSolutionsSampleSat()

运行得

x=0 y=1 z=0
x=1 y=2 z=0
x=1 y=2 z=1
x=1 y=2 z=2
x=1 y=0 z=2
x=1 y=0 z=1
x=2 y=0 z=1
x=2 y=1 z=1
x=2 y=1 z=2
x=2 y=0 z=2
x=0 y=1 z=2
x=0 y=1 z=1
x=0 y=2 z=1
x=0 y=2 z=2
x=1 y=0 z=0
x=2 y=0 z=0
x=2 y=1 z=0
x=0 y=2 z=0
Status = OPTIMAL
Number of solutions found: 18

展示 intermediate solutions

与展示所有可行解的异同主要在:

  • model.Maximize(x + 2 * y + 3 * z)
  • status = solver.SolveWithSolutionCallback(model, solution_printer)

输出结果为:

x=0 y=1 z=0
x=0 y=2 z=0
x=0 y=2 z=1
x=0 y=2 z=2
x=1 y=2 z=2
Status = OPTIMAL
Number of solutions found: 5

与官网结果不一致。https://developers.google.cn/optimization/cp/cp_solver?hl=es-419#run_intermediate_sol

猜你喜欢

转载自www.cnblogs.com/xrszff/p/10951094.html