From 4a1e4d6005ef683c62e53a4b1e5deb9c0b099e2f Mon Sep 17 00:00:00 2001 From: Mizux Seiha Date: Fri, 4 Mar 2022 00:22:27 +0100 Subject: [PATCH] doc: update python doc --- docs/python/cp_model.html | 10271 ++++ docs/python/index.html | 57 +- docs/python/ortools/algorithms/index.html | 57 +- .../algorithms/pywrapknapsack_solver.html | 849 + .../ortools/constraint_solver/index.html | 57 +- .../ortools/constraint_solver/pywrapcp.html | 42106 ++++++++++++++++ docs/python/ortools/graph/index.html | 57 +- .../graph/ortools/graph/pywrapgraph.html | 1832 + docs/python/ortools/linear_solver/index.html | 57 +- .../ortools/linear_solver/pywraplp.html | 6407 +++ docs/python/ortools/sat/python/cp_model.html | 1461 +- docs/python/ortools/util/index.html | 57 +- .../util/python/sorted_interval_list.html | 339 + 13 files changed, 62763 insertions(+), 844 deletions(-) create mode 100644 docs/python/cp_model.html create mode 100644 docs/python/ortools/algorithms/ortools/algorithms/pywrapknapsack_solver.html create mode 100644 docs/python/ortools/constraint_solver/ortools/constraint_solver/pywrapcp.html create mode 100644 docs/python/ortools/graph/ortools/graph/pywrapgraph.html create mode 100644 docs/python/ortools/linear_solver/ortools/linear_solver/pywraplp.html create mode 100644 docs/python/ortools/util/ortools/util/python/sorted_interval_list.html diff --git a/docs/python/cp_model.html b/docs/python/cp_model.html new file mode 100644 index 0000000000..b0918be8ef --- /dev/null +++ b/docs/python/cp_model.html @@ -0,0 +1,10271 @@ + + + + + + + cp_model API documentation + + + + + + + + + +
+
+

+cp_model

+ +

Methods for building and solving CP-SAT models.

+ +

The following two sections describe the main +methods for building and solving CP-SAT models.

+ +
    +
  • cp_model.CpModel">CpModel: Methods for creating +models, including variables and constraints.
  • +
  • cp_model.CpSolver">CPSolver: Methods for solving +a model and evaluating solutions.
  • +
+ +

The following methods implement callbacks that the +solver calls each time it finds a new solution.

+ + + +

Additional methods for solving CP-SAT models:

+ +
    +
  • cp_model.Constraint">Constraint: A few utility methods for modifying +constraints created by CpModel.
  • +
  • LinearExpr: Methods for creating constraints +and the objective from large arrays of coefficients.
  • +
+ +

Other methods and functions listed are primarily used for developing OR-Tools, +rather than for solving specific optimization problems.

+
+ +
+ View Source +
# Copyright 2010-2021 Google LLC
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""Methods for building and solving CP-SAT models.
+
+The following two sections describe the main
+methods for building and solving CP-SAT models.
+
+* [`CpModel`](#cp_model.CpModel): Methods for creating
+models, including variables and constraints.
+* [`CPSolver`](#cp_model.CpSolver): Methods for solving
+a model and evaluating solutions.
+
+The following methods implement callbacks that the
+solver calls each time it finds a new solution.
+
+* [`CpSolverSolutionCallback`](#cp_model.CpSolverSolutionCallback):
+  A general method for implementing callbacks.
+* [`ObjectiveSolutionPrinter`](#cp_model.ObjectiveSolutionPrinter):
+  Print objective values and elapsed time for intermediate solutions.
+* [`VarArraySolutionPrinter`](#cp_model.VarArraySolutionPrinter):
+  Print intermediate solutions (variable values, time).
+* [`VarArrayAndObjectiveSolutionPrinter`]
+      (#cp_model.VarArrayAndObjectiveSolutionPrinter):
+  Print both intermediate solutions and objective values.
+
+Additional methods for solving CP-SAT models:
+
+* [`Constraint`](#cp_model.Constraint): A few utility methods for modifying
+  constraints created by `CpModel`.
+* [`LinearExpr`](#lineacp_model.LinearExpr): Methods for creating constraints
+  and the objective from large arrays of coefficients.
+
+Other methods and functions listed are primarily used for developing OR-Tools,
+rather than for solving specific optimization problems.
+"""
+
+import collections
+import threading
+import time
+import warnings
+
+from ortools.sat import cp_model_pb2
+from ortools.sat import sat_parameters_pb2
+from ortools.sat.python import cp_model_helper as cmh
+from ortools.sat.python import swig_helper
+from ortools.util.python import sorted_interval_list
+
+Domain = sorted_interval_list.Domain
+
+# The classes below allow linear expressions to be expressed naturally with the
+# usual arithmetic operators + - * / and with constant numbers, which makes the
+# python API very intuitive. See../ samples/*.py for examples.
+
+INT_MIN = -9223372036854775808  # hardcoded to be platform independent.
+INT_MAX = 9223372036854775807
+INT32_MAX = 2147483647
+INT32_MIN = -2147483648
+
+# CpSolver status (exported to avoid importing cp_model_cp2).
+UNKNOWN = cp_model_pb2.UNKNOWN
+MODEL_INVALID = cp_model_pb2.MODEL_INVALID
+FEASIBLE = cp_model_pb2.FEASIBLE
+INFEASIBLE = cp_model_pb2.INFEASIBLE
+OPTIMAL = cp_model_pb2.OPTIMAL
+
+# Variable selection strategy
+CHOOSE_FIRST = cp_model_pb2.DecisionStrategyProto.CHOOSE_FIRST
+CHOOSE_LOWEST_MIN = cp_model_pb2.DecisionStrategyProto.CHOOSE_LOWEST_MIN
+CHOOSE_HIGHEST_MAX = cp_model_pb2.DecisionStrategyProto.CHOOSE_HIGHEST_MAX
+CHOOSE_MIN_DOMAIN_SIZE = (
+    cp_model_pb2.DecisionStrategyProto.CHOOSE_MIN_DOMAIN_SIZE)
+CHOOSE_MAX_DOMAIN_SIZE = (
+    cp_model_pb2.DecisionStrategyProto.CHOOSE_MAX_DOMAIN_SIZE)
+
+# Domain reduction strategy
+SELECT_MIN_VALUE = cp_model_pb2.DecisionStrategyProto.SELECT_MIN_VALUE
+SELECT_MAX_VALUE = cp_model_pb2.DecisionStrategyProto.SELECT_MAX_VALUE
+SELECT_LOWER_HALF = cp_model_pb2.DecisionStrategyProto.SELECT_LOWER_HALF
+SELECT_UPPER_HALF = cp_model_pb2.DecisionStrategyProto.SELECT_UPPER_HALF
+
+# Search branching
+AUTOMATIC_SEARCH = sat_parameters_pb2.SatParameters.AUTOMATIC_SEARCH
+FIXED_SEARCH = sat_parameters_pb2.SatParameters.FIXED_SEARCH
+PORTFOLIO_SEARCH = sat_parameters_pb2.SatParameters.PORTFOLIO_SEARCH
+LP_SEARCH = sat_parameters_pb2.SatParameters.LP_SEARCH
+
+
+def DisplayBounds(bounds):
+    """Displays a flattened list of intervals."""
+    out = ''
+    for i in range(0, len(bounds), 2):
+        if i != 0:
+            out += ', '
+        if bounds[i] == bounds[i + 1]:
+            out += str(bounds[i])
+        else:
+            out += str(bounds[i]) + '..' + str(bounds[i + 1])
+    return out
+
+
+def ShortName(model, i):
+    """Returns a short name of an integer variable, or its negation."""
+    if i < 0:
+        return 'Not(%s)' % ShortName(model, -i - 1)
+    v = model.variables[i]
+    if v.name:
+        return v.name
+    elif len(v.domain) == 2 and v.domain[0] == v.domain[1]:
+        return str(v.domain[0])
+    else:
+        return '[%s]' % DisplayBounds(v.domain)
+
+
+def ShortExprName(model, e):
+    """Pretty-print LinearExpressionProto instances."""
+    if not e.vars:
+        return str(e.offset)
+    if len(e.vars) == 1:
+        var_name = ShortName(model, e.vars[0])
+        coeff = e.coeffs[0]
+        result = ''
+        if coeff == 1:
+            result = var_name
+        elif coeff == -1:
+            result = f'-{var_name}'
+        elif coeff != 0:
+            result = f'{coeff} * {var_name}'
+        if e.offset > 0:
+            result = f'{result} + {e.offset}'
+        elif e.offset < 0:
+            result = f'{result} - {-e.offset}'
+        return result
+    # TODO(user): Support more than affine expressions.
+    return str(e)
+
+
+class LinearExpr(object):
+    """Holds an integer linear expression.
+
+  A linear expression is built from integer constants and variables.
+  For example, `x + 2 * (y - z + 1)`.
+
+  Linear expressions are used in CP-SAT models in constraints and in the
+  objective:
+
+  * You can define linear constraints as in:
+
+  ```
+  model.Add(x + 2 * y <= 5)
+  model.Add(sum(array_of_vars) == 5)
+  ```
+
+  * In CP-SAT, the objective is a linear expression:
+
+  ```
+  model.Minimize(x + 2 * y + z)
+  ```
+
+  * For large arrays, using the LinearExpr class is faster that using the python
+  `sum()` function. You can create constraints and the objective from lists of
+  linear expressions or coefficients as follows:
+
+  ```
+  model.Minimize(cp_model.LinearExpr.Sum(expressions))
+  model.Add(cp_model.LinearExpr.WeightedSum(expressions, coefficients) >= 0)
+  ```
+  """
+
+    @classmethod
+    def Sum(cls, expressions):
+        """Creates the expression sum(expressions)."""
+        if len(expressions) == 1:
+            return expressions[0]
+        return _SumArray(expressions)
+
+    @classmethod
+    def WeightedSum(cls, expressions, coefficients):
+        """Creates the expression sum(expressions[i] * coefficients[i])."""
+        if LinearExpr.IsEmptyOrAllNull(coefficients):
+            return 0
+        elif len(expressions) == 1:
+            return expressions[0] * coefficients[0]
+        else:
+            return _WeightedSum(expressions, coefficients)
+
+    @classmethod
+    def Term(cls, expression, coefficient):
+        """Creates `expression * coefficient`."""
+        if cmh.is_zero(coefficient):
+            return 0
+        else:
+            return expression * coefficient
+
+    @classmethod
+    def IsEmptyOrAllNull(cls, coefficients):
+        for c in coefficients:
+            if not cmh.is_zero(c):
+                return False
+        return True
+
+    @classmethod
+    def RebuildFromLinearExpressionProto(cls, model, proto):
+        """Recreate a LinearExpr from a LinearExpressionProto."""
+        offset = proto.offset
+        num_elements = len(proto.vars)
+        if num_elements == 0:
+            return offset
+        elif num_elements == 1:
+            return IntVar(model, proto.vars[0], None) * proto.coeffs[0] + offset
+        else:
+            variables = []
+            coeffs = []
+            all_ones = True
+            for index, coeff in zip(proto.vars(), proto.coeffs()):
+                variables.append(IntVar(model, index, None))
+                coeffs.append(coeff)
+                if not cmh.is_one(coeff):
+                    all_ones = False
+            if all_ones:
+                return _SumArray(variables, offset)
+            else:
+                return _WeightedSum(variables, coeffs, offset)
+
+    def GetIntegerVarValueMap(self):
+        """Scans the expression, and returns (var_coef_map, constant)."""
+        coeffs = collections.defaultdict(int)
+        constant = 0
+        to_process = [(self, 1)]
+        while to_process:  # Flatten to avoid recursion.
+            expr, coeff = to_process.pop()
+            if cmh.is_integral(expr):
+                constant += coeff * int(expr)
+            elif isinstance(expr, _ProductCst):
+                to_process.append(
+                    (expr.Expression(), coeff * expr.Coefficient()))
+            elif isinstance(expr, _Sum):
+                to_process.append((expr.Left(), coeff))
+                to_process.append((expr.Right(), coeff))
+            elif isinstance(expr, _SumArray):
+                for e in expr.Expressions():
+                    to_process.append((e, coeff))
+                constant += expr.Constant() * coeff
+            elif isinstance(expr, _WeightedSum):
+                for e, c in zip(expr.Expressions(), expr.Coefficients()):
+                    to_process.append((e, coeff * c))
+                constant += expr.Constant() * coeff
+            elif isinstance(expr, IntVar):
+                coeffs[expr] += coeff
+            elif isinstance(expr, _NotBooleanVariable):
+                constant += coeff
+                coeffs[expr.Not()] -= coeff
+            else:
+                raise TypeError('Unrecognized linear expression: ' + str(expr))
+
+        return coeffs, constant
+
+    def GetFloatVarValueMap(self):
+        """Scans the expression. Returns (var_coef_map, constant, is_integer)."""
+        coeffs = {}
+        constant = 0
+        to_process = [(self, 1)]
+        while to_process:  # Flatten to avoid recursion.
+            expr, coeff = to_process.pop()
+            if cmh.is_integral(expr):  # Keep integrality.
+                constant += coeff * int(expr)
+            elif cmh.is_a_number(expr):
+                constant += coeff * float(expr)
+            elif isinstance(expr, _ProductCst):
+                to_process.append(
+                    (expr.Expression(), coeff * expr.Coefficient()))
+            elif isinstance(expr, _Sum):
+                to_process.append((expr.Left(), coeff))
+                to_process.append((expr.Right(), coeff))
+            elif isinstance(expr, _SumArray):
+                for e in expr.Expressions():
+                    to_process.append((e, coeff))
+                constant += expr.Constant() * coeff
+            elif isinstance(expr, _WeightedSum):
+                for e, c in zip(expr.Expressions(), expr.Coefficients()):
+                    to_process.append((e, coeff * c))
+                constant += expr.Constant() * coeff
+            elif isinstance(expr, IntVar):
+                if expr in coeffs:
+                    coeffs[expr] += coeff
+                else:
+                    coeffs[expr] = coeff
+            elif isinstance(expr, _NotBooleanVariable):
+                constant += coeff
+                if expr.Not() in coeffs:
+                    coeffs[expr.Not()] -= coeff
+                else:
+                    coeffs[expr.Not()] = -coeff
+            else:
+                raise TypeError('Unrecognized linear expression: ' + str(expr))
+        is_integer = cmh.is_integral(constant)
+        if is_integer:
+            for coeff in coeffs.values():
+                if not cmh.is_integral(coeff):
+                    is_integer = False
+                    break
+        return coeffs, constant, is_integer
+
+    def __hash__(self):
+        return object.__hash__(self)
+
+    def __abs__(self):
+        raise NotImplementedError(
+            'calling abs() on a linear expression is not supported, '
+            'please use CpModel.AddAbsEquality')
+
+    def __add__(self, arg):
+        if cmh.is_zero(arg):
+            return self
+        return _Sum(self, arg)
+
+    def __radd__(self, arg):
+        if cmh.is_zero(arg):
+            return self
+        return _Sum(self, arg)
+
+    def __sub__(self, arg):
+        if cmh.is_zero(arg):
+            return self
+        return _Sum(self, -arg)
+
+    def __rsub__(self, arg):
+        return _Sum(-self, arg)
+
+    def __mul__(self, arg):
+        arg = cmh.assert_is_a_number(arg)
+        if cmh.is_one(arg):
+            return self
+        elif cmh.is_zero(arg):
+            return 0
+        return _ProductCst(self, arg)
+
+    def __rmul__(self, arg):
+        arg = cmh.assert_is_a_number(arg)
+        if cmh.is_one(arg):
+            return self
+        elif cmh.is_zero(arg):
+            return 0
+        return _ProductCst(self, arg)
+
+    def __div__(self, _):
+        raise NotImplementedError(
+            'calling / on a linear expression is not supported, '
+            'please use CpModel.AddDivisionEquality')
+
+    def __truediv__(self, _):
+        raise NotImplementedError(
+            'calling // on a linear expression is not supported, '
+            'please use CpModel.AddDivisionEquality')
+
+    def __mod__(self, _):
+        raise NotImplementedError(
+            'calling %% on a linear expression is not supported, '
+            'please use CpModel.AddModuloEquality')
+
+    def __pow__(self, _):
+        raise NotImplementedError(
+            'calling ** on a linear expression is not supported, '
+            'please use CpModel.AddMultiplicationEquality')
+
+    def __lshift__(self, _):
+        raise NotImplementedError(
+            'calling left shift on a linear expression is not supported')
+
+    def __rshift__(self, _):
+        raise NotImplementedError(
+            'calling right shift on a linear expression is not supported')
+
+    def __and__(self, _):
+        raise NotImplementedError(
+            'calling and on a linear expression is not supported, '
+            'please use CpModel.AddBoolAnd')
+
+    def __or__(self, _):
+        raise NotImplementedError(
+            'calling or on a linear expression is not supported, '
+            'please use CpModel.AddBoolOr')
+
+    def __xor__(self, _):
+        raise NotImplementedError(
+            'calling xor on a linear expression is not supported, '
+            'please use CpModel.AddBoolXor')
+
+    def __neg__(self):
+        return _ProductCst(self, -1)
+
+    def __bool__(self):
+        raise NotImplementedError(
+            'Evaluating a LinearExpr instance as a Boolean is not implemented.')
+
+    def __eq__(self, arg):
+        if arg is None:
+            return False
+        if cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            return BoundedLinearExpression(self, [arg, arg])
+        else:
+            return BoundedLinearExpression(self - arg, [0, 0])
+
+    def __ge__(self, arg):
+        if cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            return BoundedLinearExpression(self, [arg, INT_MAX])
+        else:
+            return BoundedLinearExpression(self - arg, [0, INT_MAX])
+
+    def __le__(self, arg):
+        if cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            return BoundedLinearExpression(self, [INT_MIN, arg])
+        else:
+            return BoundedLinearExpression(self - arg, [INT_MIN, 0])
+
+    def __lt__(self, arg):
+        if cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            if arg == INT_MIN:
+                raise ArithmeticError('< INT_MIN is not supported')
+            return BoundedLinearExpression(self, [INT_MIN, arg - 1])
+        else:
+            return BoundedLinearExpression(self - arg, [INT_MIN, -1])
+
+    def __gt__(self, arg):
+        if cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            if arg == INT_MAX:
+                raise ArithmeticError('> INT_MAX is not supported')
+            return BoundedLinearExpression(self, [arg + 1, INT_MAX])
+        else:
+            return BoundedLinearExpression(self - arg, [1, INT_MAX])
+
+    def __ne__(self, arg):
+        if arg is None:
+            return True
+        if cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            if arg == INT_MAX:
+                return BoundedLinearExpression(self, [INT_MIN, INT_MAX - 1])
+            elif arg == INT_MIN:
+                return BoundedLinearExpression(self, [INT_MIN + 1, INT_MAX])
+            else:
+                return BoundedLinearExpression(
+                    self, [INT_MIN, arg - 1, arg + 1, INT_MAX])
+        else:
+            return BoundedLinearExpression(self - arg,
+                                           [INT_MIN, -1, 1, INT_MAX])
+
+
+class _Sum(LinearExpr):
+    """Represents the sum of two LinearExprs."""
+
+    def __init__(self, left, right):
+        for x in [left, right]:
+            if not cmh.is_a_number(x) and not isinstance(x, LinearExpr):
+                raise TypeError('Not an linear expression: ' + str(x))
+        self.__left = left
+        self.__right = right
+
+    def Left(self):
+        return self.__left
+
+    def Right(self):
+        return self.__right
+
+    def __str__(self):
+        return f'({self.__left} + {self.__right})'
+
+    def __repr__(self):
+        return f'Sum({repr(self.__left)}, {repr(self.__right)})'
+
+
+class _ProductCst(LinearExpr):
+    """Represents the product of a LinearExpr by a constant."""
+
+    def __init__(self, expr, coeff):
+        coeff = cmh.assert_is_a_number(coeff)
+        if isinstance(expr, _ProductCst):
+            self.__expr = expr.Expression()
+            self.__coef = expr.Coefficient() * coeff
+        else:
+            self.__expr = expr
+            self.__coef = coeff
+
+    def __str__(self):
+        if self.__coef == -1:
+            return '-' + str(self.__expr)
+        else:
+            return '(' + str(self.__coef) + ' * ' + str(self.__expr) + ')'
+
+    def __repr__(self):
+        return 'ProductCst(' + repr(self.__expr) + ', ' + repr(
+            self.__coef) + ')'
+
+    def Coefficient(self):
+        return self.__coef
+
+    def Expression(self):
+        return self.__expr
+
+
+class _SumArray(LinearExpr):
+    """Represents the sum of a list of LinearExpr and a constant."""
+
+    def __init__(self, expressions, constant=0):
+        self.__expressions = []
+        self.__constant = constant
+        for x in expressions:
+            if cmh.is_a_number(x):
+                if cmh.is_zero(x):
+                    continue
+                x = cmh.assert_is_a_number(x)
+                self.__constant += x
+            elif isinstance(x, LinearExpr):
+                self.__expressions.append(x)
+            else:
+                raise TypeError('Not an linear expression: ' + str(x))
+
+    def __str__(self):
+        if self.__constant == 0:
+            return '({})'.format(' + '.join(map(str, self.__expressions)))
+        else:
+            return '({} + {})'.format(' + '.join(map(str, self.__expressions)),
+                                      self.__constant)
+
+    def __repr__(self):
+        return 'SumArray({}, {})'.format(
+            ', '.join(map(repr, self.__expressions)), self.__constant)
+
+    def Expressions(self):
+        return self.__expressions
+
+    def Constant(self):
+        return self.__constant
+
+
+class _WeightedSum(LinearExpr):
+    """Represents sum(ai * xi) + b."""
+
+    def __init__(self, expressions, coefficients, constant=0):
+        self.__expressions = []
+        self.__coefficients = []
+        self.__constant = constant
+        if len(expressions) != len(coefficients):
+            raise TypeError(
+                'In the LinearExpr.WeightedSum method, the expression array and the '
+                ' coefficient array must have the same length.')
+        for e, c in zip(expressions, coefficients):
+            c = cmh.assert_is_a_number(c)
+            if cmh.is_zero(c):
+                continue
+            if cmh.is_a_number(e):
+                e = cmh.assert_is_a_number(e)
+                self.__constant += e * c
+            elif isinstance(e, LinearExpr):
+                self.__expressions.append(e)
+                self.__coefficients.append(c)
+            else:
+                raise TypeError('Not an linear expression: ' + str(e))
+
+    def __str__(self):
+        output = None
+        for expr, coeff in zip(self.__expressions, self.__coefficients):
+            if not output and cmh.is_one(coeff):
+                output = str(expr)
+            elif not output and cmh.is_minus_one(coeff):
+                output = '-' + str(expr)
+            elif not output:
+                output = '{} * {}'.format(coeff, str(expr))
+            elif cmh.is_one(coeff):
+                output += ' + {}'.format(str(expr))
+            elif cmh.is_minus_one(coeff):
+                output += ' - {}'.format(str(expr))
+            elif coeff > 1:
+                output += ' + {} * {}'.format(coeff, str(expr))
+            elif coeff < -1:
+                output += ' - {} * {}'.format(-coeff, str(expr))
+        if self.__constant > 0:
+            output += ' + {}'.format(self.__constant)
+        elif self.__constant < 0:
+            output += ' - {}'.format(-self.__constant)
+        if output is None:
+            output = '0'
+        return output
+
+    def __repr__(self):
+        return 'WeightedSum([{}], [{}], {})'.format(
+            ', '.join(map(repr, self.__expressions)),
+            ', '.join(map(repr, self.__coefficients)), self.__constant)
+
+    def Expressions(self):
+        return self.__expressions
+
+    def Coefficients(self):
+        return self.__coefficients
+
+    def Constant(self):
+        return self.__constant
+
+
+class IntVar(LinearExpr):
+    """An integer variable.
+
+  An IntVar is an object that can take on any integer value within defined
+  ranges. Variables appear in constraint like:
+
+      x + y >= 5
+      AllDifferent([x, y, z])
+
+  Solving a model is equivalent to finding, for each variable, a single value
+  from the set of initial values (called the initial domain), such that the
+  model is feasible, or optimal if you provided an objective function.
+  """
+
+    def __init__(self, model, domain, name):
+        """See CpModel.NewIntVar below."""
+        self.__model = model
+        self.__negation = None
+        # Python do not support multiple __init__ methods.
+        # This method is only called from the CpModel class.
+        # We hack the parameter to support the two cases:
+        # case 1:
+        #     model is a CpModelProto, domain is a Domain, and name is a string.
+        # case 2:
+        #     model is a CpModelProto, domain is an index (int), and name is None.
+        if cmh.is_integral(domain) and name is None:
+            self.__index = int(domain)
+            self.__var = model.variables[domain]
+        else:
+            self.__index = len(model.variables)
+            self.__var = model.variables.add()
+            self.__var.domain.extend(domain.FlattenedIntervals())
+            self.__var.name = name
+
+    def Index(self):
+        """Returns the index of the variable in the model."""
+        return self.__index
+
+    def Proto(self):
+        """Returns the variable protobuf."""
+        return self.__var
+
+    def IsEqualTo(self, other):
+        """Returns true if self == other in the python sense."""
+        if not isinstance(other, IntVar):
+            return False
+        return self.Index() == other.Index()
+
+    def __str__(self):
+        if not self.__var.name:
+            if len(self.__var.domain
+                  ) == 2 and self.__var.domain[0] == self.__var.domain[1]:
+                # Special case for constants.
+                return str(self.__var.domain[0])
+            else:
+                return 'unnamed_var_%i' % self.__index
+        return self.__var.name
+
+    def __repr__(self):
+        return '%s(%s)' % (self.__var.name, DisplayBounds(self.__var.domain))
+
+    def Name(self):
+        return self.__var.name
+
+    def Not(self):
+        """Returns the negation of a Boolean variable.
+
+    This method implements the logical negation of a Boolean variable.
+    It is only valid if the variable has a Boolean domain (0 or 1).
+
+    Note that this method is nilpotent: `x.Not().Not() == x`.
+    """
+
+        for bound in self.__var.domain:
+            if bound < 0 or bound > 1:
+                raise TypeError(
+                    'Cannot call Not on a non boolean variable: %s' % self)
+        if self.__negation is None:
+            self.__negation = _NotBooleanVariable(self)
+        return self.__negation
+
+
+class _NotBooleanVariable(LinearExpr):
+    """Negation of a boolean variable."""
+
+    def __init__(self, boolvar):
+        self.__boolvar = boolvar
+
+    def Index(self):
+        return -self.__boolvar.Index() - 1
+
+    def Not(self):
+        return self.__boolvar
+
+    def __str__(self):
+        return 'not(%s)' % str(self.__boolvar)
+
+    def __bool__(self):
+        raise NotImplementedError(
+            'Evaluating a literal as a Boolean value is not implemented.')
+
+
+class BoundedLinearExpression(object):
+    """Represents a linear constraint: `lb <= linear expression <= ub`.
+
+  The only use of this class is to be added to the CpModel through
+  `CpModel.Add(expression)`, as in:
+
+      model.Add(x + 2 * y -1 >= z)
+  """
+
+    def __init__(self, expr, bounds):
+        self.__expr = expr
+        self.__bounds = bounds
+
+    def __str__(self):
+        if len(self.__bounds) == 2:
+            lb = self.__bounds[0]
+            ub = self.__bounds[1]
+            if lb > INT_MIN and ub < INT_MAX:
+                if lb == ub:
+                    return str(self.__expr) + ' == ' + str(lb)
+                else:
+                    return str(lb) + ' <= ' + str(
+                        self.__expr) + ' <= ' + str(ub)
+            elif lb > INT_MIN:
+                return str(self.__expr) + ' >= ' + str(lb)
+            elif ub < INT_MAX:
+                return str(self.__expr) + ' <= ' + str(ub)
+            else:
+                return 'True (unbounded expr ' + str(self.__expr) + ')'
+        elif (len(self.__bounds) == 4 and self.__bounds[0] == INT_MIN and
+              self.__bounds[1] + 2 == self.__bounds[2] and
+              self.__bounds[3] == INT_MAX):
+            return str(self.__expr) + ' != ' + str(self.__bounds[1] + 1)
+        else:
+            return str(self.__expr) + ' in [' + DisplayBounds(
+                self.__bounds) + ']'
+
+    def Expression(self):
+        return self.__expr
+
+    def Bounds(self):
+        return self.__bounds
+
+    def __bool__(self):
+        coeffs_map, constant = self.__expr.GetIntegerVarValueMap()
+        all_coeffs = set(coeffs_map.values())
+        same_var = set([0])
+        eq_bounds = [0, 0]
+        different_vars = set([-1, 1])
+        ne_bounds = [INT_MIN, -1, 1, INT_MAX]
+        if (len(coeffs_map) == 1 and all_coeffs == same_var and
+                constant == 0 and
+            (self.__bounds == eq_bounds or self.__bounds == ne_bounds)):
+            return self.__bounds == eq_bounds
+        if (len(coeffs_map) == 2 and all_coeffs == different_vars and
+                constant == 0 and
+            (self.__bounds == eq_bounds or self.__bounds == ne_bounds)):
+            return self.__bounds == ne_bounds
+
+        raise NotImplementedError(
+            f'Evaluating a BoundedLinearExpression \'{self}\' as a Boolean value'
+            + ' is not supported.')
+
+
+class Constraint(object):
+    """Base class for constraints.
+
+  Constraints are built by the CpModel through the Add<XXX> methods.
+  Once created by the CpModel class, they are automatically added to the model.
+  The purpose of this class is to allow specification of enforcement literals
+  for this constraint.
+
+      b = model.NewBoolVar('b')
+      x = model.NewIntVar(0, 10, 'x')
+      y = model.NewIntVar(0, 10, 'y')
+
+      model.Add(x + 2 * y == 5).OnlyEnforceIf(b.Not())
+  """
+
+    def __init__(self, constraints):
+        self.__index = len(constraints)
+        self.__constraint = constraints.add()
+
+    def OnlyEnforceIf(self, *boolvar):
+        """Adds an enforcement literal to the constraint.
+
+    This method adds one or more literals (that is, a boolean variable or its
+    negation) as enforcement literals. The conjunction of all these literals
+    determines whether the constraint is active or not. It acts as an
+    implication, so if the conjunction is true, it implies that the constraint
+    must be enforced. If it is false, then the constraint is ignored.
+
+    BoolOr, BoolAnd, and linear constraints all support enforcement literals.
+
+    Args:
+      *boolvar: One or more Boolean literals.
+
+    Returns:
+      self.
+    """
+        for lit in ExpandGeneratorOrTuple(boolvar):
+            if (isinstance(lit, bool) and
+                    bool(lit)) or (cmh.is_integral(lit) and int(lit) == 1):
+                # Always true. Do nothing.
+                pass
+            else:
+                self.__constraint.enforcement_literal.append(lit.Index())
+        return self
+
+    def Index(self):
+        """Returns the index of the constraint in the model."""
+        return self.__index
+
+    def Proto(self):
+        """Returns the constraint protobuf."""
+        return self.__constraint
+
+
+class IntervalVar(object):
+    """Represents an Interval variable.
+
+  An interval variable is both a constraint and a variable. It is defined by
+  three integer variables: start, size, and end.
+
+  It is a constraint because, internally, it enforces that start + size == end.
+
+  It is also a variable as it can appear in specific scheduling constraints:
+  NoOverlap, NoOverlap2D, Cumulative.
+
+  Optionally, an enforcement literal can be added to this constraint, in which
+  case these scheduling constraints will ignore interval variables with
+  enforcement literals assigned to false. Conversely, these constraints will
+  also set these enforcement literals to false if they cannot fit these
+  intervals into the schedule.
+  """
+
+    def __init__(self, model, start, size, end, is_present_index, name):
+        self.__model = model
+        # As with the IntVar::__init__ method, we hack the __init__ method to
+        # support two use cases:
+        #   case 1: called when creating a new interval variable.
+        #      {start|size|end} are linear expressions, is_present_index is either
+        #      None or the index of a Boolean literal. name is a string
+        #   case 2: called when querying an existing interval variable.
+        #      start_index is an int, all parameters after are None.
+        if (size is None and end is None and is_present_index is None and
+                name is None):
+            self.__index = start
+            self.__ct = model.constraints[start]
+        else:
+            self.__index = len(model.constraints)
+            self.__ct = self.__model.constraints.add()
+            self.__ct.interval.start.CopyFrom(start)
+            self.__ct.interval.size.CopyFrom(size)
+            self.__ct.interval.end.CopyFrom(end)
+            if is_present_index is not None:
+                self.__ct.enforcement_literal.append(is_present_index)
+            if name:
+                self.__ct.name = name
+
+    def Index(self):
+        """Returns the index of the interval constraint in the model."""
+        return self.__index
+
+    def Proto(self):
+        """Returns the interval protobuf."""
+        return self.__ct.interval
+
+    def __str__(self):
+        return self.__ct.name
+
+    def __repr__(self):
+        interval = self.__ct.interval
+        if self.__ct.enforcement_literal:
+            return '%s(start = %s, size = %s, end = %s, is_present = %s)' % (
+                self.__ct.name, ShortExprName(self.__model, interval.start),
+                ShortExprName(self.__model, interval.size),
+                ShortExprName(self.__model, interval.end),
+                ShortName(self.__model, self.__ct.enforcement_literal[0]))
+        else:
+            return '%s(start = %s, size = %s, end = %s)' % (
+                self.__ct.name, ShortExprName(self.__model, interval.start),
+                ShortExprName(self.__model, interval.size),
+                ShortExprName(self.__model, interval.end))
+
+    def Name(self):
+        return self.__ct.name
+
+    def StartExpr(self):
+        return LinearExpr.RebuildFromLinearExpressionProto(
+            self.__model, self.__ct.interval.start)
+
+    def SizeExpr(self):
+        return LinearExpr.RebuildFromLinearExpressionProto(
+            self.__model, self.__ct.interval.size)
+
+    def EndExpr(self):
+        return LinearExpr.RebuildFromLinearExpressionProto(
+            self.__model, self.__ct.interval.end)
+
+
+def ObjectIsATrueLiteral(literal):
+    """Checks if literal is either True, or a Boolean literals fixed to True."""
+    if isinstance(literal, IntVar):
+        proto = literal.Proto()
+        return (len(proto.domain) == 2 and proto.domain[0] == 1 and
+                proto.domain[1] == 1)
+    if isinstance(literal, _NotBooleanVariable):
+        proto = literal.Not().Proto()
+        return (len(proto.domain) == 2 and proto.domain[0] == 0 and
+                proto.domain[1] == 0)
+    if cmh.is_integral(literal):
+        return int(literal) == 1
+    return False
+
+
+def ObjectIsAFalseLiteral(literal):
+    """Checks if literal is either False, or a Boolean literals fixed to False."""
+    if isinstance(literal, IntVar):
+        proto = literal.Proto()
+        return (len(proto.domain) == 2 and proto.domain[0] == 0 and
+                proto.domain[1] == 0)
+    if isinstance(literal, _NotBooleanVariable):
+        proto = literal.Not().Proto()
+        return (len(proto.domain) == 2 and proto.domain[0] == 1 and
+                proto.domain[1] == 1)
+    if cmh.is_integral(literal):
+        return int(literal) == 0
+    return False
+
+
+class CpModel(object):
+    """Methods for building a CP model.
+
+  Methods beginning with:
+
+  * ```New``` create integer, boolean, or interval variables.
+  * ```Add``` create new constraints and add them to the model.
+  """
+
+    def __init__(self):
+        self.__model = cp_model_pb2.CpModelProto()
+        self.__constant_map = {}
+
+    # Integer variable.
+
+    def NewIntVar(self, lb, ub, name):
+        """Create an integer variable with domain [lb, ub].
+
+    The CP-SAT solver is limited to integer variables. If you have fractional
+    values, scale them up so that they become integers; if you have strings,
+    encode them as integers.
+
+    Args:
+      lb: Lower bound for the variable.
+      ub: Upper bound for the variable.
+      name: The name of the variable.
+
+    Returns:
+      a variable whose domain is [lb, ub].
+    """
+
+        return IntVar(self.__model, Domain(lb, ub), name)
+
+    def NewIntVarFromDomain(self, domain, name):
+        """Create an integer variable from a domain.
+
+    A domain is a set of integers specified by a collection of intervals.
+    For example, `model.NewIntVarFromDomain(cp_model.
+         Domain.FromIntervals([[1, 2], [4, 6]]), 'x')`
+
+    Args:
+      domain: An instance of the Domain class.
+      name: The name of the variable.
+
+    Returns:
+        a variable whose domain is the given domain.
+    """
+        return IntVar(self.__model, domain, name)
+
+    def NewBoolVar(self, name):
+        """Creates a 0-1 variable with the given name."""
+        return IntVar(self.__model, Domain(0, 1), name)
+
+    def NewConstant(self, value):
+        """Declares a constant integer."""
+        return IntVar(self.__model, self.GetOrMakeIndexFromConstant(value),
+                      None)
+
+    # Linear constraints.
+
+    def AddLinearConstraint(self, linear_expr, lb, ub):
+        """Adds the constraint: `lb <= linear_expr <= ub`."""
+        return self.AddLinearExpressionInDomain(linear_expr, Domain(lb, ub))
+
+    def AddLinearExpressionInDomain(self, linear_expr, domain):
+        """Adds the constraint: `linear_expr` in `domain`."""
+        if isinstance(linear_expr, LinearExpr):
+            ct = Constraint(self.__model.constraints)
+            model_ct = self.__model.constraints[ct.Index()]
+            coeffs_map, constant = linear_expr.GetIntegerVarValueMap()
+            for t in coeffs_map.items():
+                if not isinstance(t[0], IntVar):
+                    raise TypeError('Wrong argument' + str(t))
+                c = cmh.assert_is_int64(t[1])
+                model_ct.linear.vars.append(t[0].Index())
+                model_ct.linear.coeffs.append(c)
+            model_ct.linear.domain.extend([
+                cmh.capped_subtraction(x, constant)
+                for x in domain.FlattenedIntervals()
+            ])
+            return ct
+        elif cmh.is_integral(linear_expr):
+            if not domain.Contains(int(linear_expr)):
+                return self.AddBoolOr([])  # Evaluate to false.
+            # Nothing to do otherwise.
+        else:
+            raise TypeError(
+                'Not supported: CpModel.AddLinearExpressionInDomain(' +
+                str(linear_expr) + ' ' + str(domain) + ')')
+
+    def Add(self, ct):
+        """Adds a `BoundedLinearExpression` to the model.
+
+    Args:
+      ct: A [`BoundedLinearExpression`](#boundedlinearexpression).
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        if isinstance(ct, BoundedLinearExpression):
+            return self.AddLinearExpressionInDomain(
+                ct.Expression(), Domain.FromFlatIntervals(ct.Bounds()))
+        elif ct and isinstance(ct, bool):
+            return self.AddBoolOr([True])
+        elif not ct and isinstance(ct, bool):
+            return self.AddBoolOr([])  # Evaluate to false.
+        else:
+            raise TypeError('Not supported: CpModel.Add(' + str(ct) + ')')
+
+    # General Integer Constraints.
+
+    def AddAllDifferent(self, *expressions):
+        """Adds AllDifferent(expressions).
+
+    This constraint forces all expressions to have different values.
+
+    Args:
+      *expressions: simple expressions of the form a * var + constant.
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        expanded = ExpandGeneratorOrTuple(expressions)
+        model_ct.all_diff.exprs.extend(
+            [self.ParseLinearExpression(x) for x in expanded])
+        return ct
+
+    def AddElement(self, index, variables, target):
+        """Adds the element constraint: `variables[index] == target`."""
+
+        if not variables:
+            raise ValueError('AddElement expects a non-empty variables array')
+
+        if cmh.is_integral(index):
+            return self.Add(list(variables)[int(index)] == target)
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.element.index = self.GetOrMakeIndex(index)
+        model_ct.element.vars.extend(
+            [self.GetOrMakeIndex(x) for x in variables])
+        model_ct.element.target = self.GetOrMakeIndex(target)
+        return ct
+
+    def AddCircuit(self, arcs):
+        """Adds Circuit(arcs).
+
+    Adds a circuit constraint from a sparse list of arcs that encode the graph.
+
+    A circuit is a unique Hamiltonian path in a subgraph of the total
+    graph. In case a node 'i' is not in the path, then there must be a
+    loop arc 'i -> i' associated with a true literal. Otherwise
+    this constraint will fail.
+
+    Args:
+      arcs: a list of arcs. An arc is a tuple (source_node, destination_node,
+        literal). The arc is selected in the circuit if the literal is true.
+        Both source_node and destination_node must be integers between 0 and the
+        number of nodes - 1.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: If the list of arcs is empty.
+    """
+        if not arcs:
+            raise ValueError('AddCircuit expects a non-empty array of arcs')
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        for arc in arcs:
+            tail = cmh.assert_is_int32(arc[0])
+            head = cmh.assert_is_int32(arc[1])
+            lit = self.GetOrMakeBooleanIndex(arc[2])
+            model_ct.circuit.tails.append(tail)
+            model_ct.circuit.heads.append(head)
+            model_ct.circuit.literals.append(lit)
+        return ct
+
+    def AddMultipleCircuit(self, arcs):
+        """Adds a multiple circuit constraint, aka the "VRP" constraint.
+
+    The direct graph where arc #i (from tails[i] to head[i]) is present iff
+    literals[i] is true must satisfy this set of properties:
+    - #incoming arcs == 1 except for node 0.
+    - #outgoing arcs == 1 except for node 0.
+    - for node zero, #incoming arcs == #outgoing arcs.
+    - There are no duplicate arcs.
+    - Self-arcs are allowed except for node 0.
+    - There is no cycle in this graph, except through node 0.
+
+    Args:
+      arcs: a list of arcs. An arc is a tuple (source_node, destination_node,
+        literal). The arc is selected in the circuit if the literal is true.
+        Both source_node and destination_node must be integers between 0 and the
+        number of nodes - 1.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: If the list of arcs is empty.
+    """
+        if not arcs:
+            raise ValueError(
+                'AddMultipleCircuit expects a non-empty array of arcs')
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        for arc in arcs:
+            tail = cmh.assert_is_int32(arc[0])
+            head = cmh.assert_is_int32(arc[1])
+            lit = self.GetOrMakeBooleanIndex(arc[2])
+            model_ct.routes.tails.append(tail)
+            model_ct.routes.heads.append(head)
+            model_ct.routes.literals.append(lit)
+        return ct
+
+    def AddAllowedAssignments(self, variables, tuples_list):
+        """Adds AllowedAssignments(variables, tuples_list).
+
+    An AllowedAssignments constraint is a constraint on an array of variables,
+    which requires that when all variables are assigned values, the resulting
+    array equals one of the  tuples in `tuple_list`.
+
+    Args:
+      variables: A list of variables.
+      tuples_list: A list of admissible tuples. Each tuple must have the same
+        length as the variables, and the ith value of a tuple corresponds to the
+        ith variable.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      TypeError: If a tuple does not have the same size as the list of
+          variables.
+      ValueError: If the array of variables is empty.
+    """
+
+        if not variables:
+            raise ValueError(
+                'AddAllowedAssignments expects a non-empty variables '
+                'array')
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.table.vars.extend([self.GetOrMakeIndex(x) for x in variables])
+        arity = len(variables)
+        for t in tuples_list:
+            if len(t) != arity:
+                raise TypeError('Tuple ' + str(t) + ' has the wrong arity')
+            ar = []
+            for v in t:
+                ar.append(cmh.assert_is_int64(v))
+            model_ct.table.values.extend(ar)
+        return ct
+
+    def AddForbiddenAssignments(self, variables, tuples_list):
+        """Adds AddForbiddenAssignments(variables, [tuples_list]).
+
+    A ForbiddenAssignments constraint is a constraint on an array of variables
+    where the list of impossible combinations is provided in the tuples list.
+
+    Args:
+      variables: A list of variables.
+      tuples_list: A list of forbidden tuples. Each tuple must have the same
+        length as the variables, and the *i*th value of a tuple corresponds to
+        the *i*th variable.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      TypeError: If a tuple does not have the same size as the list of
+                 variables.
+      ValueError: If the array of variables is empty.
+    """
+
+        if not variables:
+            raise ValueError(
+                'AddForbiddenAssignments expects a non-empty variables '
+                'array')
+
+        index = len(self.__model.constraints)
+        ct = self.AddAllowedAssignments(variables, tuples_list)
+        self.__model.constraints[index].table.negated = True
+        return ct
+
+    def AddAutomaton(self, transition_variables, starting_state, final_states,
+                     transition_triples):
+        """Adds an automaton constraint.
+
+    An automaton constraint takes a list of variables (of size *n*), an initial
+    state, a set of final states, and a set of transitions. A transition is a
+    triplet (*tail*, *transition*, *head*), where *tail* and *head* are states,
+    and *transition* is the label of an arc from *head* to *tail*,
+    corresponding to the value of one variable in the list of variables.
+
+    This automaton will be unrolled into a flow with *n* + 1 phases. Each phase
+    contains the possible states of the automaton. The first state contains the
+    initial state. The last phase contains the final states.
+
+    Between two consecutive phases *i* and *i* + 1, the automaton creates a set
+    of arcs. For each transition (*tail*, *transition*, *head*), it will add
+    an arc from the state *tail* of phase *i* and the state *head* of phase
+    *i* + 1. This arc is labeled by the value *transition* of the variables
+    `variables[i]`. That is, this arc can only be selected if `variables[i]`
+    is assigned the value *transition*.
+
+    A feasible solution of this constraint is an assignment of variables such
+    that, starting from the initial state in phase 0, there is a path labeled by
+    the values of the variables that ends in one of the final states in the
+    final phase.
+
+    Args:
+      transition_variables: A non-empty list of variables whose values
+        correspond to the labels of the arcs traversed by the automaton.
+      starting_state: The initial state of the automaton.
+      final_states: A non-empty list of admissible final states.
+      transition_triples: A list of transitions for the automaton, in the
+        following format (current_state, variable_value, next_state).
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: if `transition_variables`, `final_states`, or
+        `transition_triples` are empty.
+    """
+
+        if not transition_variables:
+            raise ValueError(
+                'AddAutomaton expects a non-empty transition_variables '
+                'array')
+        if not final_states:
+            raise ValueError('AddAutomaton expects some final states')
+
+        if not transition_triples:
+            raise ValueError('AddAutomaton expects some transition triples')
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.automaton.vars.extend(
+            [self.GetOrMakeIndex(x) for x in transition_variables])
+        starting_state = cmh.assert_is_int64(starting_state)
+        model_ct.automaton.starting_state = starting_state
+        for v in final_states:
+            v = cmh.assert_is_int64(v)
+            model_ct.automaton.final_states.append(v)
+        for t in transition_triples:
+            if len(t) != 3:
+                raise TypeError('Tuple ' + str(t) +
+                                ' has the wrong arity (!= 3)')
+            tail = cmh.assert_is_int64(t[0])
+            label = cmh.assert_is_int64(t[1])
+            head = cmh.assert_is_int64(t[2])
+            model_ct.automaton.transition_tail.append(tail)
+            model_ct.automaton.transition_label.append(label)
+            model_ct.automaton.transition_head.append(head)
+        return ct
+
+    def AddInverse(self, variables, inverse_variables):
+        """Adds Inverse(variables, inverse_variables).
+
+    An inverse constraint enforces that if `variables[i]` is assigned a value
+    `j`, then `inverse_variables[j]` is assigned a value `i`. And vice versa.
+
+    Args:
+      variables: An array of integer variables.
+      inverse_variables: An array of integer variables.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      TypeError: if variables and inverse_variables have different lengths, or
+          if they are empty.
+    """
+
+        if not variables or not inverse_variables:
+            raise TypeError(
+                'The Inverse constraint does not accept empty arrays')
+        if len(variables) != len(inverse_variables):
+            raise TypeError(
+                'In the inverse constraint, the two array variables and'
+                ' inverse_variables must have the same length.')
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.inverse.f_direct.extend(
+            [self.GetOrMakeIndex(x) for x in variables])
+        model_ct.inverse.f_inverse.extend(
+            [self.GetOrMakeIndex(x) for x in inverse_variables])
+        return ct
+
+    def AddReservoirConstraint(self, times, level_changes, min_level,
+                               max_level):
+        """Adds Reservoir(times, level_changes, min_level, max_level).
+
+    Maintains a reservoir level within bounds. The water level starts at 0, and
+    at any time, it must be between min_level and max_level.
+
+    If the affine expression `times[i]` is assigned a value t, then the current
+    level changes by `level_changes[i]`, which is constant, at time t.
+
+     Note that min level must be <= 0, and the max level must be >= 0. Please
+     use fixed level_changes to simulate initial state.
+
+     Therefore, at any time:
+         sum(level_changes[i] if times[i] <= t) in [min_level, max_level]
+
+    Args:
+      times: A list of affine expressions which specify the time of the filling
+        or emptying the reservoir.
+      level_changes: A list of integer values that specifies the amount of the
+        emptying or filling.
+      min_level: At any time, the level of the reservoir must be greater or
+        equal than the min level.
+      max_level: At any time, the level of the reservoir must be less or equal
+        than the max level.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: if max_level < min_level.
+
+      ValueError: if max_level < 0.
+
+      ValueError: if min_level > 0
+    """
+
+        if max_level < min_level:
+            return ValueError(
+                'Reservoir constraint must have a max_level >= min_level')
+
+        if max_level < 0:
+            return ValueError('Reservoir constraint must have a max_level >= 0')
+
+        if min_level > 0:
+            return ValueError('Reservoir constraint must have a min_level <= 0')
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.reservoir.time_exprs.extend(
+            [self.ParseLinearExpression(x) for x in times])
+        model_ct.reservoir.level_changes.extend(level_changes)
+        model_ct.reservoir.min_level = min_level
+        model_ct.reservoir.max_level = max_level
+        return ct
+
+    def AddReservoirConstraintWithActive(self, times, level_changes, actives,
+                                         min_level, max_level):
+        """Adds Reservoir(times, level_changes, actives, min_level, max_level).
+
+    Maintains a reservoir level within bounds. The water level starts at 0, and
+    at any time, it must be between min_level and max_level.
+
+    If the variable `times[i]` is assigned a value t, and `actives[i]` is
+    `True`, then the current level changes by `level_changes[i]`, which is
+    constant,
+    at time t.
+
+     Note that min level must be <= 0, and the max level must be >= 0. Please
+     use fixed level_changes to simulate initial state.
+
+     Therefore, at any time:
+         sum(level_changes[i] * actives[i] if times[i] <= t) in [min_level,
+         max_level]
+
+
+    The array of boolean variables 'actives', if defined, indicates which
+    actions are actually performed.
+
+    Args:
+      times: A list of affine expressions which specify the time of the filling
+        or emptying the reservoir.
+      level_changes: A list of integer values that specifies the amount of the
+        emptying or filling.
+      actives: a list of boolean variables. They indicates if the
+        emptying/refilling events actually take place.
+      min_level: At any time, the level of the reservoir must be greater or
+        equal than the min level.
+      max_level: At any time, the level of the reservoir must be less or equal
+        than the max level.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: if max_level < min_level.
+
+      ValueError: if max_level < 0.
+
+      ValueError: if min_level > 0
+    """
+
+        if max_level < min_level:
+            return ValueError(
+                'Reservoir constraint must have a max_level >= min_level')
+
+        if max_level < 0:
+            return ValueError('Reservoir constraint must have a max_level >= 0')
+
+        if min_level > 0:
+            return ValueError('Reservoir constraint must have a min_level <= 0')
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.reservoir.time_exprs.extend(
+            [self.ParseLinearExpression(x) for x in times])
+        model_ct.reservoir.level_changes.extend(level_changes)
+        model_ct.reservoir.active_literals.extend(
+            [self.GetOrMakeIndex(x) for x in actives])
+        model_ct.reservoir.min_level = min_level
+        model_ct.reservoir.max_level = max_level
+        return ct
+
+    def AddMapDomain(self, var, bool_var_array, offset=0):
+        """Adds `var == i + offset <=> bool_var_array[i] == true for all i`."""
+
+        for i, bool_var in enumerate(bool_var_array):
+            b_index = bool_var.Index()
+            var_index = var.Index()
+            model_ct = self.__model.constraints.add()
+            model_ct.linear.vars.append(var_index)
+            model_ct.linear.coeffs.append(1)
+            model_ct.linear.domain.extend([offset + i, offset + i])
+            model_ct.enforcement_literal.append(b_index)
+
+            model_ct = self.__model.constraints.add()
+            model_ct.linear.vars.append(var_index)
+            model_ct.linear.coeffs.append(1)
+            model_ct.enforcement_literal.append(-b_index - 1)
+            if offset + i - 1 >= INT_MIN:
+                model_ct.linear.domain.extend([INT_MIN, offset + i - 1])
+            if offset + i + 1 <= INT_MAX:
+                model_ct.linear.domain.extend([offset + i + 1, INT_MAX])
+
+    def AddImplication(self, a, b):
+        """Adds `a => b` (`a` implies `b`)."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.bool_or.literals.append(self.GetOrMakeBooleanIndex(b))
+        model_ct.enforcement_literal.append(self.GetOrMakeBooleanIndex(a))
+        return ct
+
+    def AddBoolOr(self, *literals):
+        """Adds `Or(literals) == true`: Sum(literals) >= 1."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.bool_or.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+    def AddAtLeastOne(self, *literals):
+        """Same as `AddBoolOr`: `Sum(literals) >= 1`."""
+        return self.AddBoolOr(*literals)
+
+    def AddAtMostOne(self, *literals):
+        """Adds `AtMostOne(literals)`: `Sum(literals) <= 1`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.at_most_one.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+    def AddExactlyOne(self, *literals):
+        """Adds `ExactlyOne(literals)`: `Sum(literals) == 1`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.exactly_one.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+    def AddBoolAnd(self, *literals):
+        """Adds `And(literals) == true`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.bool_and.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+    def AddBoolXOr(self, *literals):
+        """Adds `XOr(literals) == true`.
+
+    In contrast to AddBoolOr and AddBoolAnd, it does not support
+        .OnlyEnforceIf().
+
+    Args:
+      *literals: the list of literals in the constraint.
+
+    Returns:
+      An `Constraint` object.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.bool_xor.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+    def AddMinEquality(self, target, exprs):
+        """Adds `target == Min(exprs)`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.lin_max.exprs.extend(
+            [self.ParseLinearExpression(x, True) for x in exprs])
+        model_ct.lin_max.target.CopyFrom(
+            self.ParseLinearExpression(target, True))
+        return ct
+
+    def AddMaxEquality(self, target, exprs):
+        """Adds `target == Max(exprs)`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.lin_max.exprs.extend(
+            [self.ParseLinearExpression(x) for x in exprs])
+        model_ct.lin_max.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+    def AddDivisionEquality(self, target, num, denom):
+        """Adds `target == num // denom` (integer division rounded towards 0)."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.int_div.exprs.append(self.ParseLinearExpression(num))
+        model_ct.int_div.exprs.append(self.ParseLinearExpression(denom))
+        model_ct.int_div.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+    def AddAbsEquality(self, target, expr):
+        """Adds `target == Abs(var)`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.lin_max.exprs.append(self.ParseLinearExpression(expr))
+        model_ct.lin_max.exprs.append(self.ParseLinearExpression(expr, True))
+        model_ct.lin_max.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+    def AddModuloEquality(self, target, var, mod):
+        """Adds `target = var % mod`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.int_mod.exprs.append(self.ParseLinearExpression(var))
+        model_ct.int_mod.exprs.append(self.ParseLinearExpression(mod))
+        model_ct.int_mod.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+    def AddMultiplicationEquality(self, target, *expressions):
+        """Adds `target == expressions[0] * .. * expressions[n]`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.int_prod.exprs.extend([
+            self.ParseLinearExpression(expr)
+            for expr in ExpandGeneratorOrTuple(expressions)
+        ])
+        model_ct.int_prod.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+    # Scheduling support
+
+    def NewIntervalVar(self, start, size, end, name):
+        """Creates an interval variable from start, size, and end.
+
+    An interval variable is a constraint, that is itself used in other
+    constraints like NoOverlap.
+
+    Internally, it ensures that `start + size == end`.
+
+    Args:
+      start: The start of the interval. It can be an affine or constant
+        expression.
+      size: The size of the interval. It can be an affine or constant
+        expression.
+      end: The end of the interval. It can be an affine or constant expression.
+      name: The name of the interval variable.
+
+    Returns:
+      An `IntervalVar` object.
+    """
+
+        self.Add(start + size == end)
+
+        start_expr = self.ParseLinearExpression(start)
+        size_expr = self.ParseLinearExpression(size)
+        end_expr = self.ParseLinearExpression(end)
+        if len(start_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: start must be affine or constant.')
+        if len(size_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: size must be affine or constant.')
+        if len(end_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: end must be affine or constant.')
+        return IntervalVar(self.__model, start_expr, size_expr, end_expr, None,
+                           name)
+
+    def NewFixedSizeIntervalVar(self, start, size, name):
+        """Creates an interval variable from start, and a fixed size.
+
+    An interval variable is a constraint, that is itself used in other
+    constraints like NoOverlap.
+
+    Args:
+      start: The start of the interval. It can be an affine or constant
+        expression.
+      size: The size of the interval. It must be an integer value.
+      name: The name of the interval variable.
+
+    Returns:
+      An `IntervalVar` object.
+    """
+        size = cmh.assert_is_int64(size)
+        start_expr = self.ParseLinearExpression(start)
+        size_expr = self.ParseLinearExpression(size)
+        end_expr = self.ParseLinearExpression(start + size)
+        if len(start_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: start must be affine or constant.')
+        return IntervalVar(self.__model, start_expr, size_expr, end_expr, None,
+                           name)
+
+    def NewOptionalIntervalVar(self, start, size, end, is_present, name):
+        """Creates an optional interval var from start, size, end, and is_present.
+
+    An optional interval variable is a constraint, that is itself used in other
+    constraints like NoOverlap. This constraint is protected by an is_present
+    literal that indicates if it is active or not.
+
+    Internally, it ensures that `is_present` implies `start + size == end`.
+
+    Args:
+      start: The start of the interval. It can be an integer value, or an
+        integer variable.
+      size: The size of the interval. It can be an integer value, or an integer
+        variable.
+      end: The end of the interval. It can be an integer value, or an integer
+        variable.
+      is_present: A literal that indicates if the interval is active or not. A
+        inactive interval is simply ignored by all constraints.
+      name: The name of the interval variable.
+
+    Returns:
+      An `IntervalVar` object.
+    """
+
+        # Add the linear constraint.
+        self.Add(start + size == end).OnlyEnforceIf(is_present)
+
+        # Creates the IntervalConstraintProto object.
+        is_present_index = self.GetOrMakeBooleanIndex(is_present)
+        start_expr = self.ParseLinearExpression(start)
+        size_expr = self.ParseLinearExpression(size)
+        end_expr = self.ParseLinearExpression(end)
+        if len(start_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: start must be affine or constant.')
+        if len(size_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: size must be affine or constant.')
+        if len(end_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: end must be affine or constant.')
+        return IntervalVar(self.__model, start_expr, size_expr, end_expr,
+                           is_present_index, name)
+
+    def NewOptionalFixedSizeIntervalVar(self, start, size, is_present, name):
+        """Creates an interval variable from start, and a fixed size.
+
+    An interval variable is a constraint, that is itself used in other
+    constraints like NoOverlap.
+
+    Args:
+      start: The start of the interval. It can be an affine or constant
+        expression.
+      size: The size of the interval. It must be an integer value.
+      is_present: A literal that indicates if the interval is active or not. A
+        inactive interval is simply ignored by all constraints.
+      name: The name of the interval variable.
+
+    Returns:
+      An `IntervalVar` object.
+    """
+        size = cmh.assert_is_int64(size)
+        start_expr = self.ParseLinearExpression(start)
+        size_expr = self.ParseLinearExpression(size)
+        end_expr = self.ParseLinearExpression(start + size)
+        if len(start_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: start must be affine or constant.')
+        is_present_index = self.GetOrMakeBooleanIndex(is_present)
+        return IntervalVar(self.__model, start_expr, size_expr, end_expr,
+                           is_present_index, name)
+
+    def AddNoOverlap(self, interval_vars):
+        """Adds NoOverlap(interval_vars).
+
+    A NoOverlap constraint ensures that all present intervals do not overlap
+    in time.
+
+    Args:
+      interval_vars: The list of interval variables to constrain.
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.no_overlap.intervals.extend(
+            [self.GetIntervalIndex(x) for x in interval_vars])
+        return ct
+
+    def AddNoOverlap2D(self, x_intervals, y_intervals):
+        """Adds NoOverlap2D(x_intervals, y_intervals).
+
+    A NoOverlap2D constraint ensures that all present rectangles do not overlap
+    on a plane. Each rectangle is aligned with the X and Y axis, and is defined
+    by two intervals which represent its projection onto the X and Y axis.
+
+    Furthermore, one box is optional if at least one of the x or y interval is
+    optional.
+
+    Args:
+      x_intervals: The X coordinates of the rectangles.
+      y_intervals: The Y coordinates of the rectangles.
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.no_overlap_2d.x_intervals.extend(
+            [self.GetIntervalIndex(x) for x in x_intervals])
+        model_ct.no_overlap_2d.y_intervals.extend(
+            [self.GetIntervalIndex(x) for x in y_intervals])
+        return ct
+
+    def AddCumulative(self, intervals, demands, capacity):
+        """Adds Cumulative(intervals, demands, capacity).
+
+    This constraint enforces that:
+
+        for all t:
+          sum(demands[i]
+            if (start(intervals[i]) <= t < end(intervals[i])) and
+            (intervals[i] is present)) <= capacity
+
+    Args:
+      intervals: The list of intervals.
+      demands: The list of demands for each interval. Each demand must be >= 0.
+        Each demand can be an integer value, or an integer variable.
+      capacity: The maximum capacity of the cumulative constraint. It must be a
+        positive integer value or variable.
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.cumulative.intervals.extend(
+            [self.GetIntervalIndex(x) for x in intervals])
+        for d in demands:
+            model_ct.cumulative.demands.append(self.ParseLinearExpression(d))
+        model_ct.cumulative.capacity.CopyFrom(
+            self.ParseLinearExpression(capacity))
+        return ct
+
+    # Support for deep copy.
+    def CopyFrom(self, other_model):
+        """Reset the model, and creates a new one from a CpModelProto instance."""
+        self.__model.CopyFrom(other_model.Proto())
+
+        # Rebuild constant map.
+        self.__constant_map.clear()
+        for i, var in enumerate(self.__model.variables):
+            if len(var.domain) == 2 and var.domain[0] == var.domain[1]:
+                self.__constant_map[var.domain[0]] = i
+
+    def GetBoolVarFromProtoIndex(self, index):
+        """Returns an already created Boolean variable from its index."""
+        if index < 0 or index >= len(self.__model.variables):
+            raise ValueError(
+                f'GetBoolVarFromProtoIndex: out of bound index {index}')
+        var = self.__model.variables[index]
+        if len(var.domain) != 2 or var.domain[0] < 0 or var.domain[1] > 1:
+            raise ValueError(
+                f'GetBoolVarFromProtoIndex: index {index} does not reference' +
+                ' a Boolean variable')
+
+        return IntVar(self.__model, index, None)
+
+    def GetIntVarFromProtoIndex(self, index):
+        """Returns an already created integer variable from its index."""
+        if index < 0 or index >= len(self.__model.variables):
+            raise ValueError(
+                f'GetIntVarFromProtoIndex: out of bound index {index}')
+        return IntVar(self.__model, index, None)
+
+    def GetIntervalVarFromProtoIndex(self, index):
+        """Returns an already created interval variable from its index."""
+        if index < 0 or index >= len(self.__model.constraints):
+            raise ValueError(
+                f'GetIntervalVarFromProtoIndex: out of bound index {index}')
+        ct = self.__model.constraints[index]
+        if not ct.HasField('interval'):
+            raise ValueError(
+                f'GetIntervalVarFromProtoIndex: index {index} does not reference an'
+                + ' interval variable')
+
+        return IntervalVar(self.__model, index, None, None, None, None)
+
+    # Helpers.
+
+    def __str__(self):
+        return str(self.__model)
+
+    def Proto(self):
+        """Returns the underlying CpModelProto."""
+        return self.__model
+
+    def Negated(self, index):
+        return -index - 1
+
+    def GetOrMakeIndex(self, arg):
+        """Returns the index of a variable, its negation, or a number."""
+        if isinstance(arg, IntVar):
+            return arg.Index()
+        elif (isinstance(arg, _ProductCst) and
+              isinstance(arg.Expression(), IntVar) and arg.Coefficient() == -1):
+            return -arg.Expression().Index() - 1
+        elif cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            return self.GetOrMakeIndexFromConstant(arg)
+        else:
+            raise TypeError('NotSupported: model.GetOrMakeIndex(' + str(arg) +
+                            ')')
+
+    def GetOrMakeBooleanIndex(self, arg):
+        """Returns an index from a boolean expression."""
+        if isinstance(arg, IntVar):
+            self.AssertIsBooleanVariable(arg)
+            return arg.Index()
+        elif isinstance(arg, _NotBooleanVariable):
+            self.AssertIsBooleanVariable(arg.Not())
+            return arg.Index()
+        elif cmh.is_integral(arg):
+            cmh.assert_is_boolean(arg)
+            return self.GetOrMakeIndexFromConstant(int(arg))
+        else:
+            raise TypeError('NotSupported: model.GetOrMakeBooleanIndex(' +
+                            str(arg) + ')')
+
+    def GetIntervalIndex(self, arg):
+        if not isinstance(arg, IntervalVar):
+            raise TypeError('NotSupported: model.GetIntervalIndex(%s)' % arg)
+        return arg.Index()
+
+    def GetOrMakeIndexFromConstant(self, value):
+        if value in self.__constant_map:
+            return self.__constant_map[value]
+        index = len(self.__model.variables)
+        var = self.__model.variables.add()
+        var.domain.extend([value, value])
+        self.__constant_map[value] = index
+        return index
+
+    def VarIndexToVarProto(self, var_index):
+        if var_index >= 0:
+            return self.__model.variables[var_index]
+        else:
+            return self.__model.variables[-var_index - 1]
+
+    def ParseLinearExpression(self, linear_expr, negate=False):
+        """Returns a LinearExpressionProto built from a LinearExpr instance."""
+        result = cp_model_pb2.LinearExpressionProto()
+        mult = -1 if negate else 1
+        if cmh.is_integral(linear_expr):
+            result.offset = int(linear_expr) * mult
+            return result
+
+        if isinstance(linear_expr, IntVar):
+            result.vars.append(self.GetOrMakeIndex(linear_expr))
+            result.coeffs.append(mult)
+            return result
+
+        coeffs_map, constant = linear_expr.GetIntegerVarValueMap()
+        result.offset = constant * mult
+        for t in coeffs_map.items():
+            if not isinstance(t[0], IntVar):
+                raise TypeError('Wrong argument' + str(t))
+            c = cmh.assert_is_int64(t[1])
+            result.vars.append(t[0].Index())
+            result.coeffs.append(c * mult)
+        return result
+
+    def _SetObjective(self, obj, minimize):
+        """Sets the objective of the model."""
+        self.__model.ClearField('objective')
+        self.__model.ClearField('floating_point_objective')
+        if isinstance(obj, IntVar):
+            self.__model.objective.coeffs.append(1)
+            self.__model.objective.offset = 0
+            if minimize:
+                self.__model.objective.vars.append(obj.Index())
+                self.__model.objective.scaling_factor = 1
+            else:
+                self.__model.objective.vars.append(self.Negated(obj.Index()))
+                self.__model.objective.scaling_factor = -1
+        elif isinstance(obj, LinearExpr):
+            coeffs_map, constant, is_integer = obj.GetFloatVarValueMap()
+            if is_integer:
+                if minimize:
+                    self.__model.objective.scaling_factor = 1
+                    self.__model.objective.offset = constant
+                else:
+                    self.__model.objective.scaling_factor = -1
+                    self.__model.objective.offset = -constant
+                for v, c, in coeffs_map.items():
+                    self.__model.objective.coeffs.append(c)
+                    if minimize:
+                        self.__model.objective.vars.append(v.Index())
+                    else:
+                        self.__model.objective.vars.append(
+                            self.Negated(v.Index()))
+            else:
+                self.__model.floating_point_objective.maximize = not minimize
+                self.__model.floating_point_objective.offset = constant
+                for v, c, in coeffs_map.items():
+                    self.__model.floating_point_objective.coeffs.append(c)
+                    self.__model.floating_point_objective.vars.append(v.Index())
+        elif cmh.is_integral(obj):
+            self.__model.objective.offset = int(obj)
+            self.__model.objective.scaling_factor = 1
+        else:
+            raise TypeError('TypeError: ' + str(obj) +
+                            ' is not a valid objective')
+
+    def Minimize(self, obj):
+        """Sets the objective of the model to minimize(obj)."""
+        self._SetObjective(obj, minimize=True)
+
+    def Maximize(self, obj):
+        """Sets the objective of the model to maximize(obj)."""
+        self._SetObjective(obj, minimize=False)
+
+    def HasObjective(self):
+        return self.__model.HasField('objective')
+
+    def AddDecisionStrategy(self, variables, var_strategy, domain_strategy):
+        """Adds a search strategy to the model.
+
+    Args:
+      variables: a list of variables this strategy will assign.
+      var_strategy: heuristic to choose the next variable to assign.
+      domain_strategy: heuristic to reduce the domain of the selected variable.
+        Currently, this is advanced code: the union of all strategies added to
+          the model must be complete, i.e. instantiates all variables.
+          Otherwise, Solve() will fail.
+    """
+
+        strategy = self.__model.search_strategy.add()
+        for v in variables:
+            strategy.variables.append(v.Index())
+        strategy.variable_selection_strategy = var_strategy
+        strategy.domain_reduction_strategy = domain_strategy
+
+    def ModelStats(self):
+        """Returns a string containing some model statistics."""
+        return swig_helper.CpSatHelper.SerializedModelStats(
+            self.__model.SerializeToString())
+
+    def Validate(self):
+        """Returns a string indicating that the model is invalid."""
+        return swig_helper.CpSatHelper.SerializedValidateModel(
+            self.__model.SerializeToString())
+
+    def ExportToFile(self, file):
+        """Write the model as a protocol buffer to 'file'.
+
+    Args:
+      file: file to write the model to. If the filename ends with 'txt', the
+        model will be written as a text file, otherwise, the binary format will
+        be used.
+
+    Returns:
+      True if the model was correctly written.
+    """
+        return swig_helper.CpSatHelper.SerializedWriteModelToFile(
+            self.__model.SerializeToString(), file)
+
+    def AssertIsBooleanVariable(self, x):
+        if isinstance(x, IntVar):
+            var = self.__model.variables[x.Index()]
+            if len(var.domain) != 2 or var.domain[0] < 0 or var.domain[1] > 1:
+                raise TypeError('TypeError: ' + str(x) +
+                                ' is not a boolean variable')
+        elif not isinstance(x, _NotBooleanVariable):
+            raise TypeError('TypeError: ' + str(x) +
+                            ' is not a boolean variable')
+
+    def AddHint(self, var, value):
+        """Adds 'var == value' as a hint to the solver."""
+        self.__model.solution_hint.vars.append(self.GetOrMakeIndex(var))
+        self.__model.solution_hint.values.append(value)
+
+    def ClearHints(self):
+        """Remove any solution hint from the model."""
+        self.__model.ClearField('solution_hint')
+
+    def AddAssumption(self, lit):
+        """Add the literal 'lit' to the model as assumptions."""
+        self.__model.assumptions.append(self.GetOrMakeBooleanIndex(lit))
+
+    def AddAssumptions(self, literals):
+        """Add the literals to the model as assumptions."""
+        for lit in literals:
+            self.AddAssumption(lit)
+
+    def ClearAssumptions(self):
+        """Remove all assumptions from the model."""
+        self.__model.ClearField('assumptions')
+
+
+def ExpandGeneratorOrTuple(args):
+    if hasattr(args, '__len__'):  # Tuple
+        if len(args) != 1:
+            return args
+        if cmh.is_a_number(args[0]) or isinstance(args[0], LinearExpr):
+            return args
+    # Generator
+    return args[0]
+
+
+def EvaluateLinearExpr(expression, solution):
+    """Evaluate a linear expression against a solution."""
+    if cmh.is_integral(expression):
+        return int(expression)
+    if not isinstance(expression, LinearExpr):
+        raise TypeError('Cannot interpret %s as a linear expression.' %
+                        expression)
+
+    value = 0
+    to_process = [(expression, 1)]
+    while to_process:
+        expr, coeff = to_process.pop()
+        if cmh.is_integral(expr):
+            value += int(expr) * coeff
+        elif isinstance(expr, _ProductCst):
+            to_process.append((expr.Expression(), coeff * expr.Coefficient()))
+        elif isinstance(expr, _Sum):
+            to_process.append((expr.Left(), coeff))
+            to_process.append((expr.Right(), coeff))
+        elif isinstance(expr, _SumArray):
+            for e in expr.Expressions():
+                to_process.append((e, coeff))
+            value += expr.Constant() * coeff
+        elif isinstance(expr, _WeightedSum):
+            for e, c in zip(expr.Expressions(), expr.Coefficients()):
+                to_process.append((e, coeff * c))
+            value += expr.Constant() * coeff
+        elif isinstance(expr, IntVar):
+            value += coeff * solution.solution[expr.Index()]
+        elif isinstance(expr, _NotBooleanVariable):
+            value += coeff * (1 - solution.solution[expr.Not().Index()])
+        else:
+            raise TypeError(f'Cannot interpret {expr} as a linear expression.')
+
+    return value
+
+
+def EvaluateBooleanExpression(literal, solution):
+    """Evaluate a boolean expression against a solution."""
+    if cmh.is_integral(literal):
+        return bool(literal)
+    elif isinstance(literal, IntVar) or isinstance(literal,
+                                                   _NotBooleanVariable):
+        index = literal.Index()
+        if index >= 0:
+            return bool(solution.solution[index])
+        else:
+            return not solution.solution[-index - 1]
+    else:
+        raise TypeError(f'Cannot interpret {literal} as a boolean expression.')
+
+
+class CpSolver(object):
+    """Main solver class.
+
+  The purpose of this class is to search for a solution to the model provided
+  to the Solve() method.
+
+  Once Solve() is called, this class allows inspecting the solution found
+  with the Value() and BooleanValue() methods, as well as general statistics
+  about the solve procedure.
+  """
+
+    def __init__(self):
+        self.__model = None
+        self.__solution: cp_model_pb2.CpSolverResponse = None
+        self.parameters = sat_parameters_pb2.SatParameters()
+        self.log_callback = None
+        self.__solve_wrapper: swig_helper.SolveWrapper = None
+        self.__lock = threading.Lock()
+
+    def Solve(self, model, solution_callback=None):
+        """Solves a problem and passes each solution to the callback if not null."""
+        with self.__lock:
+            solve_wrapper = swig_helper.SolveWrapper()
+
+        swig_helper.SolveWrapper.SetSerializedParameters(
+            self.parameters.SerializeToString(), solve_wrapper)
+        if solution_callback is not None:
+            solve_wrapper.AddSolutionCallback(solution_callback)
+
+        if self.log_callback is not None:
+            solve_wrapper.AddLogCallback(self.log_callback)
+
+        self.__solution = cp_model_pb2.CpSolverResponse.FromString(
+            swig_helper.SolveWrapper.SerializedSolve(
+                model.Proto().SerializeToString(), solve_wrapper))
+
+        if solution_callback is not None:
+            solve_wrapper.ClearSolutionCallback(solution_callback)
+
+        with self.__lock:
+            self.__solve_wrapper = None
+
+        return self.__solution.status
+
+    def SolveWithSolutionCallback(self, model, callback):
+        """DEPRECATED Use Solve() with the callback argument."""
+        warnings.warn(
+            'SolveWithSolutionCallback is deprecated; use Solve() with' +
+            'the callback argument.', DeprecationWarning)
+        return self.Solve(model, callback)
+
+    def SearchForAllSolutions(self, model, callback):
+        """DEPRECATED Use Solve() with the right parameter.
+
+    Search for all solutions of a satisfiability problem.
+
+    This method searches for all feasible solutions of a given model.
+    Then it feeds the solution to the callback.
+
+    Note that the model cannot contain an objective.
+
+    Args:
+      model: The model to solve.
+      callback: The callback that will be called at each solution.
+
+    Returns:
+      The status of the solve:
+
+      * *FEASIBLE* if some solutions have been found
+      * *INFEASIBLE* if the solver has proved there are no solution
+      * *OPTIMAL* if all solutions have been found
+    """
+        warnings.warn(
+            'SearchForAllSolutions is deprecated; use Solve() with' +
+            'enumerate_all_solutions = True.', DeprecationWarning)
+        if model.HasObjective():
+            raise TypeError('Search for all solutions is only defined on '
+                            'satisfiability problems')
+        # Store old parameter.
+        enumerate_all = self.parameters.enumerate_all_solutions
+        self.parameters.enumerate_all_solutions = True
+
+        self.Solve(model, callback)
+
+        # Restore parameter.
+        self.parameters.enumerate_all_solutions = enumerate_all
+        return self.__solution.status
+
+    def StopSearch(self):
+        """Stops the current search asynchronously."""
+        with self.__lock:
+            if self.__solve_wrapper:
+                self.__solve_wrapper.StopSearch()
+
+    def Value(self, expression):
+        """Returns the value of a linear expression after solve."""
+        if not self.__solution:
+            raise RuntimeError('Solve() has not be called.')
+        return EvaluateLinearExpr(expression, self.__solution)
+
+    def BooleanValue(self, literal):
+        """Returns the boolean value of a literal after solve."""
+        if not self.__solution:
+            raise RuntimeError('Solve() has not be called.')
+        return EvaluateBooleanExpression(literal, self.__solution)
+
+    def ObjectiveValue(self):
+        """Returns the value of the objective after solve."""
+        return self.__solution.objective_value
+
+    def BestObjectiveBound(self):
+        """Returns the best lower (upper) bound found when min(max)imizing."""
+        return self.__solution.best_objective_bound
+
+    def StatusName(self, status=None):
+        """Returns the name of the status returned by Solve()."""
+        if status is None:
+            status = self.__solution.status
+        return cp_model_pb2.CpSolverStatus.Name(status)
+
+    def NumBooleans(self):
+        """Returns the number of boolean variables managed by the SAT solver."""
+        return self.__solution.num_booleans
+
+    def NumConflicts(self):
+        """Returns the number of conflicts since the creation of the solver."""
+        return self.__solution.num_conflicts
+
+    def NumBranches(self):
+        """Returns the number of search branches explored by the solver."""
+        return self.__solution.num_branches
+
+    def WallTime(self):
+        """Returns the wall time in seconds since the creation of the solver."""
+        return self.__solution.wall_time
+
+    def UserTime(self):
+        """Returns the user time in seconds since the creation of the solver."""
+        return self.__solution.user_time
+
+    def ResponseStats(self):
+        """Returns some statistics on the solution found as a string."""
+        return swig_helper.CpSatHelper.SerializedSolverResponseStats(
+            self.__solution.SerializeToString())
+
+    def ResponseProto(self):
+        """Returns the response object."""
+        return self.__solution
+
+    def SufficientAssumptionsForInfeasibility(self):
+        """Returns the indices of the infeasible assumptions."""
+        return self.__solution.sufficient_assumptions_for_infeasibility
+
+    def SolutionInfo(self):
+        """Returns some information on the solve process.
+
+    Returns some information on how the solution was found, or the reason
+    why the model or the parameters are invalid.
+    """
+        return self.__solution.solution_info
+
+
+class CpSolverSolutionCallback(swig_helper.SolutionCallback):
+    """Solution callback.
+
+  This class implements a callback that will be called at each new solution
+  found during search.
+
+  The method OnSolutionCallback() will be called by the solver, and must be
+  implemented. The current solution can be queried using the BooleanValue()
+  and Value() methods.
+
+  It inherits the following methods from its base class:
+
+  * `ObjectiveValue(self)`
+  * `BestObjectiveBound(self)`
+  * `NumBooleans(self)`
+  * `NumConflicts(self)`
+  * `NumBranches(self)`
+  * `WallTime(self)`
+  * `UserTime(self)`
+
+  These methods returns the same information as their counterpart in the
+  `CpSolver` class.
+  """
+
+    def __init__(self):
+        swig_helper.SolutionCallback.__init__(self)
+
+    def OnSolutionCallback(self):
+        """Proxy for the same method in snake case."""
+        self.on_solution_callback()
+
+    def BooleanValue(self, lit):
+        """Returns the boolean value of a boolean literal.
+
+    Args:
+        lit: A boolean variable or its negation.
+
+    Returns:
+        The Boolean value of the literal in the solution.
+
+    Raises:
+        RuntimeError: if `lit` is not a boolean variable or its negation.
+    """
+        if not self.HasResponse():
+            raise RuntimeError('Solve() has not be called.')
+        if cmh.is_integral(lit):
+            return bool(lit)
+        elif isinstance(lit, IntVar) or isinstance(lit, _NotBooleanVariable):
+            index = lit.Index()
+            return self.SolutionBooleanValue(index)
+        else:
+            raise TypeError(f'Cannot interpret {lit} as a boolean expression.')
+
+    def Value(self, expression):
+        """Evaluates an linear expression in the current solution.
+
+    Args:
+        expression: a linear expression of the model.
+
+    Returns:
+        An integer value equal to the evaluation of the linear expression
+        against the current solution.
+
+    Raises:
+        RuntimeError: if 'expression' is not a LinearExpr.
+    """
+        if not self.HasResponse():
+            raise RuntimeError('Solve() has not be called.')
+
+        value = 0
+        to_process = [(expression, 1)]
+        while to_process:
+            expr, coeff = to_process.pop()
+            if cmh.is_integral(expr):
+                value += int(expr) * coeff
+            elif isinstance(expr, _ProductCst):
+                to_process.append(
+                    (expr.Expression(), coeff * expr.Coefficient()))
+            elif isinstance(expr, _Sum):
+                to_process.append((expr.Left(), coeff))
+                to_process.append((expr.Right(), coeff))
+            elif isinstance(expr, _SumArray):
+                for e in expr.Expressions():
+                    to_process.append((e, coeff))
+                    value += expr.Constant() * coeff
+            elif isinstance(expr, _WeightedSum):
+                for e, c in zip(expr.Expressions(), expr.Coefficients()):
+                    to_process.append((e, coeff * c))
+                value += expr.Constant() * coeff
+            elif isinstance(expr, IntVar):
+                value += coeff * self.SolutionIntegerValue(expr.Index())
+            elif isinstance(expr, _NotBooleanVariable):
+                value += coeff * (1 -
+                                  self.SolutionIntegerValue(expr.Not().Index()))
+            else:
+                raise TypeError(
+                    f'Cannot interpret {expression} as a linear expression.')
+
+        return value
+
+    def Response(self):
+        """Returns the current solution response."""
+        return cp_model_pb2.CpSolverResponse.FromString(
+            swig_helper.SolutionCallback.SerializedResponse(self))
+
+
+class ObjectiveSolutionPrinter(CpSolverSolutionCallback):
+    """Display the objective value and time of intermediate solutions."""
+
+    def __init__(self):
+        CpSolverSolutionCallback.__init__(self)
+        self.__solution_count = 0
+        self.__start_time = time.time()
+
+    def on_solution_callback(self):
+        """Called on each new solution."""
+        current_time = time.time()
+        obj = self.ObjectiveValue()
+        print('Solution %i, time = %0.2f s, objective = %i' %
+              (self.__solution_count, current_time - self.__start_time, obj))
+        self.__solution_count += 1
+
+    def solution_count(self):
+        """Returns the number of solutions found."""
+        return self.__solution_count
+
+
+class VarArrayAndObjectiveSolutionPrinter(CpSolverSolutionCallback):
+    """Print intermediate solutions (objective, variable values, time)."""
+
+    def __init__(self, variables):
+        CpSolverSolutionCallback.__init__(self)
+        self.__variables = variables
+        self.__solution_count = 0
+        self.__start_time = time.time()
+
+    def on_solution_callback(self):
+        """Called on each new solution."""
+        current_time = time.time()
+        obj = self.ObjectiveValue()
+        print('Solution %i, time = %0.2f s, objective = %i' %
+              (self.__solution_count, current_time - self.__start_time, obj))
+        for v in self.__variables:
+            print('  %s = %i' % (v, self.Value(v)), end=' ')
+        print()
+        self.__solution_count += 1
+
+    def solution_count(self):
+        """Returns the number of solutions found."""
+        return self.__solution_count
+
+
+class VarArraySolutionPrinter(CpSolverSolutionCallback):
+    """Print intermediate solutions (variable values, time)."""
+
+    def __init__(self, variables):
+        CpSolverSolutionCallback.__init__(self)
+        self.__variables = variables
+        self.__solution_count = 0
+        self.__start_time = time.time()
+
+    def on_solution_callback(self):
+        """Called on each new solution."""
+        current_time = time.time()
+        print('Solution %i, time = %0.2f s' %
+              (self.__solution_count, current_time - self.__start_time))
+        for v in self.__variables:
+            print('  %s = %i' % (v, self.Value(v)), end=' ')
+        print()
+        self.__solution_count += 1
+
+    def solution_count(self):
+        """Returns the number of solutions found."""
+        return self.__solution_count
+
+ +
+ +
+
+
#   + + + def + DisplayBounds(bounds): +
+ +
+ View Source +
def DisplayBounds(bounds):
+    """Displays a flattened list of intervals."""
+    out = ''
+    for i in range(0, len(bounds), 2):
+        if i != 0:
+            out += ', '
+        if bounds[i] == bounds[i + 1]:
+            out += str(bounds[i])
+        else:
+            out += str(bounds[i]) + '..' + str(bounds[i + 1])
+    return out
+
+ +
+ +

Displays a flattened list of intervals.

+
+ + +
+
+
#   + + + def + ShortName(model, i): +
+ +
+ View Source +
def ShortName(model, i):
+    """Returns a short name of an integer variable, or its negation."""
+    if i < 0:
+        return 'Not(%s)' % ShortName(model, -i - 1)
+    v = model.variables[i]
+    if v.name:
+        return v.name
+    elif len(v.domain) == 2 and v.domain[0] == v.domain[1]:
+        return str(v.domain[0])
+    else:
+        return '[%s]' % DisplayBounds(v.domain)
+
+ +
+ +

Returns a short name of an integer variable, or its negation.

+
+ + +
+
+
#   + + + def + ShortExprName(model, e): +
+ +
+ View Source +
def ShortExprName(model, e):
+    """Pretty-print LinearExpressionProto instances."""
+    if not e.vars:
+        return str(e.offset)
+    if len(e.vars) == 1:
+        var_name = ShortName(model, e.vars[0])
+        coeff = e.coeffs[0]
+        result = ''
+        if coeff == 1:
+            result = var_name
+        elif coeff == -1:
+            result = f'-{var_name}'
+        elif coeff != 0:
+            result = f'{coeff} * {var_name}'
+        if e.offset > 0:
+            result = f'{result} + {e.offset}'
+        elif e.offset < 0:
+            result = f'{result} - {-e.offset}'
+        return result
+    # TODO(user): Support more than affine expressions.
+    return str(e)
+
+ +
+ +

Pretty-print LinearExpressionProto instances.

+
+ + +
+
+
+ #   + + + class + LinearExpr: +
+ +
+ View Source +
class LinearExpr(object):
+    """Holds an integer linear expression.
+
+  A linear expression is built from integer constants and variables.
+  For example, `x + 2 * (y - z + 1)`.
+
+  Linear expressions are used in CP-SAT models in constraints and in the
+  objective:
+
+  * You can define linear constraints as in:
+
+  ```
+  model.Add(x + 2 * y <= 5)
+  model.Add(sum(array_of_vars) == 5)
+  ```
+
+  * In CP-SAT, the objective is a linear expression:
+
+  ```
+  model.Minimize(x + 2 * y + z)
+  ```
+
+  * For large arrays, using the LinearExpr class is faster that using the python
+  `sum()` function. You can create constraints and the objective from lists of
+  linear expressions or coefficients as follows:
+
+  ```
+  model.Minimize(cp_model.LinearExpr.Sum(expressions))
+  model.Add(cp_model.LinearExpr.WeightedSum(expressions, coefficients) >= 0)
+  ```
+  """
+
+    @classmethod
+    def Sum(cls, expressions):
+        """Creates the expression sum(expressions)."""
+        if len(expressions) == 1:
+            return expressions[0]
+        return _SumArray(expressions)
+
+    @classmethod
+    def WeightedSum(cls, expressions, coefficients):
+        """Creates the expression sum(expressions[i] * coefficients[i])."""
+        if LinearExpr.IsEmptyOrAllNull(coefficients):
+            return 0
+        elif len(expressions) == 1:
+            return expressions[0] * coefficients[0]
+        else:
+            return _WeightedSum(expressions, coefficients)
+
+    @classmethod
+    def Term(cls, expression, coefficient):
+        """Creates `expression * coefficient`."""
+        if cmh.is_zero(coefficient):
+            return 0
+        else:
+            return expression * coefficient
+
+    @classmethod
+    def IsEmptyOrAllNull(cls, coefficients):
+        for c in coefficients:
+            if not cmh.is_zero(c):
+                return False
+        return True
+
+    @classmethod
+    def RebuildFromLinearExpressionProto(cls, model, proto):
+        """Recreate a LinearExpr from a LinearExpressionProto."""
+        offset = proto.offset
+        num_elements = len(proto.vars)
+        if num_elements == 0:
+            return offset
+        elif num_elements == 1:
+            return IntVar(model, proto.vars[0], None) * proto.coeffs[0] + offset
+        else:
+            variables = []
+            coeffs = []
+            all_ones = True
+            for index, coeff in zip(proto.vars(), proto.coeffs()):
+                variables.append(IntVar(model, index, None))
+                coeffs.append(coeff)
+                if not cmh.is_one(coeff):
+                    all_ones = False
+            if all_ones:
+                return _SumArray(variables, offset)
+            else:
+                return _WeightedSum(variables, coeffs, offset)
+
+    def GetIntegerVarValueMap(self):
+        """Scans the expression, and returns (var_coef_map, constant)."""
+        coeffs = collections.defaultdict(int)
+        constant = 0
+        to_process = [(self, 1)]
+        while to_process:  # Flatten to avoid recursion.
+            expr, coeff = to_process.pop()
+            if cmh.is_integral(expr):
+                constant += coeff * int(expr)
+            elif isinstance(expr, _ProductCst):
+                to_process.append(
+                    (expr.Expression(), coeff * expr.Coefficient()))
+            elif isinstance(expr, _Sum):
+                to_process.append((expr.Left(), coeff))
+                to_process.append((expr.Right(), coeff))
+            elif isinstance(expr, _SumArray):
+                for e in expr.Expressions():
+                    to_process.append((e, coeff))
+                constant += expr.Constant() * coeff
+            elif isinstance(expr, _WeightedSum):
+                for e, c in zip(expr.Expressions(), expr.Coefficients()):
+                    to_process.append((e, coeff * c))
+                constant += expr.Constant() * coeff
+            elif isinstance(expr, IntVar):
+                coeffs[expr] += coeff
+            elif isinstance(expr, _NotBooleanVariable):
+                constant += coeff
+                coeffs[expr.Not()] -= coeff
+            else:
+                raise TypeError('Unrecognized linear expression: ' + str(expr))
+
+        return coeffs, constant
+
+    def GetFloatVarValueMap(self):
+        """Scans the expression. Returns (var_coef_map, constant, is_integer)."""
+        coeffs = {}
+        constant = 0
+        to_process = [(self, 1)]
+        while to_process:  # Flatten to avoid recursion.
+            expr, coeff = to_process.pop()
+            if cmh.is_integral(expr):  # Keep integrality.
+                constant += coeff * int(expr)
+            elif cmh.is_a_number(expr):
+                constant += coeff * float(expr)
+            elif isinstance(expr, _ProductCst):
+                to_process.append(
+                    (expr.Expression(), coeff * expr.Coefficient()))
+            elif isinstance(expr, _Sum):
+                to_process.append((expr.Left(), coeff))
+                to_process.append((expr.Right(), coeff))
+            elif isinstance(expr, _SumArray):
+                for e in expr.Expressions():
+                    to_process.append((e, coeff))
+                constant += expr.Constant() * coeff
+            elif isinstance(expr, _WeightedSum):
+                for e, c in zip(expr.Expressions(), expr.Coefficients()):
+                    to_process.append((e, coeff * c))
+                constant += expr.Constant() * coeff
+            elif isinstance(expr, IntVar):
+                if expr in coeffs:
+                    coeffs[expr] += coeff
+                else:
+                    coeffs[expr] = coeff
+            elif isinstance(expr, _NotBooleanVariable):
+                constant += coeff
+                if expr.Not() in coeffs:
+                    coeffs[expr.Not()] -= coeff
+                else:
+                    coeffs[expr.Not()] = -coeff
+            else:
+                raise TypeError('Unrecognized linear expression: ' + str(expr))
+        is_integer = cmh.is_integral(constant)
+        if is_integer:
+            for coeff in coeffs.values():
+                if not cmh.is_integral(coeff):
+                    is_integer = False
+                    break
+        return coeffs, constant, is_integer
+
+    def __hash__(self):
+        return object.__hash__(self)
+
+    def __abs__(self):
+        raise NotImplementedError(
+            'calling abs() on a linear expression is not supported, '
+            'please use CpModel.AddAbsEquality')
+
+    def __add__(self, arg):
+        if cmh.is_zero(arg):
+            return self
+        return _Sum(self, arg)
+
+    def __radd__(self, arg):
+        if cmh.is_zero(arg):
+            return self
+        return _Sum(self, arg)
+
+    def __sub__(self, arg):
+        if cmh.is_zero(arg):
+            return self
+        return _Sum(self, -arg)
+
+    def __rsub__(self, arg):
+        return _Sum(-self, arg)
+
+    def __mul__(self, arg):
+        arg = cmh.assert_is_a_number(arg)
+        if cmh.is_one(arg):
+            return self
+        elif cmh.is_zero(arg):
+            return 0
+        return _ProductCst(self, arg)
+
+    def __rmul__(self, arg):
+        arg = cmh.assert_is_a_number(arg)
+        if cmh.is_one(arg):
+            return self
+        elif cmh.is_zero(arg):
+            return 0
+        return _ProductCst(self, arg)
+
+    def __div__(self, _):
+        raise NotImplementedError(
+            'calling / on a linear expression is not supported, '
+            'please use CpModel.AddDivisionEquality')
+
+    def __truediv__(self, _):
+        raise NotImplementedError(
+            'calling // on a linear expression is not supported, '
+            'please use CpModel.AddDivisionEquality')
+
+    def __mod__(self, _):
+        raise NotImplementedError(
+            'calling %% on a linear expression is not supported, '
+            'please use CpModel.AddModuloEquality')
+
+    def __pow__(self, _):
+        raise NotImplementedError(
+            'calling ** on a linear expression is not supported, '
+            'please use CpModel.AddMultiplicationEquality')
+
+    def __lshift__(self, _):
+        raise NotImplementedError(
+            'calling left shift on a linear expression is not supported')
+
+    def __rshift__(self, _):
+        raise NotImplementedError(
+            'calling right shift on a linear expression is not supported')
+
+    def __and__(self, _):
+        raise NotImplementedError(
+            'calling and on a linear expression is not supported, '
+            'please use CpModel.AddBoolAnd')
+
+    def __or__(self, _):
+        raise NotImplementedError(
+            'calling or on a linear expression is not supported, '
+            'please use CpModel.AddBoolOr')
+
+    def __xor__(self, _):
+        raise NotImplementedError(
+            'calling xor on a linear expression is not supported, '
+            'please use CpModel.AddBoolXor')
+
+    def __neg__(self):
+        return _ProductCst(self, -1)
+
+    def __bool__(self):
+        raise NotImplementedError(
+            'Evaluating a LinearExpr instance as a Boolean is not implemented.')
+
+    def __eq__(self, arg):
+        if arg is None:
+            return False
+        if cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            return BoundedLinearExpression(self, [arg, arg])
+        else:
+            return BoundedLinearExpression(self - arg, [0, 0])
+
+    def __ge__(self, arg):
+        if cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            return BoundedLinearExpression(self, [arg, INT_MAX])
+        else:
+            return BoundedLinearExpression(self - arg, [0, INT_MAX])
+
+    def __le__(self, arg):
+        if cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            return BoundedLinearExpression(self, [INT_MIN, arg])
+        else:
+            return BoundedLinearExpression(self - arg, [INT_MIN, 0])
+
+    def __lt__(self, arg):
+        if cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            if arg == INT_MIN:
+                raise ArithmeticError('< INT_MIN is not supported')
+            return BoundedLinearExpression(self, [INT_MIN, arg - 1])
+        else:
+            return BoundedLinearExpression(self - arg, [INT_MIN, -1])
+
+    def __gt__(self, arg):
+        if cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            if arg == INT_MAX:
+                raise ArithmeticError('> INT_MAX is not supported')
+            return BoundedLinearExpression(self, [arg + 1, INT_MAX])
+        else:
+            return BoundedLinearExpression(self - arg, [1, INT_MAX])
+
+    def __ne__(self, arg):
+        if arg is None:
+            return True
+        if cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            if arg == INT_MAX:
+                return BoundedLinearExpression(self, [INT_MIN, INT_MAX - 1])
+            elif arg == INT_MIN:
+                return BoundedLinearExpression(self, [INT_MIN + 1, INT_MAX])
+            else:
+                return BoundedLinearExpression(
+                    self, [INT_MIN, arg - 1, arg + 1, INT_MAX])
+        else:
+            return BoundedLinearExpression(self - arg,
+                                           [INT_MIN, -1, 1, INT_MAX])
+
+ +
+ +

Holds an integer linear expression.

+ +

A linear expression is built from integer constants and variables. +For example, x + 2 * (y - z + 1).

+ +

Linear expressions are used in CP-SAT models in constraints and in the +objective:

+ +
    +
  • You can define linear constraints as in:
  • +
+ +
model.Add(x + 2 * y <= 5)
+model.Add(sum(array_of_vars) == 5)
+
+ +
    +
  • In CP-SAT, the objective is a linear expression:
  • +
+ +
model.Minimize(x + 2 * y + z)
+
+ +
    +
  • For large arrays, using the LinearExpr class is faster that using the python +sum() function. You can create constraints and the objective from lists of +linear expressions or coefficients as follows:
  • +
+ +
model.Minimize(cp_model.LinearExpr.Sum(expressions))
+model.Add(cp_model.LinearExpr.WeightedSum(expressions, coefficients) >= 0)
+
+
+ + +
+
#   + + + LinearExpr() +
+ + + + +
+
+
#   + +
@classmethod
+ + def + Sum(cls, expressions): +
+ +
+ View Source +
    @classmethod
+    def Sum(cls, expressions):
+        """Creates the expression sum(expressions)."""
+        if len(expressions) == 1:
+            return expressions[0]
+        return _SumArray(expressions)
+
+ +
+ +

Creates the expression sum(expressions).

+
+ + +
+
+
#   + +
@classmethod
+ + def + WeightedSum(cls, expressions, coefficients): +
+ +
+ View Source +
    @classmethod
+    def WeightedSum(cls, expressions, coefficients):
+        """Creates the expression sum(expressions[i] * coefficients[i])."""
+        if LinearExpr.IsEmptyOrAllNull(coefficients):
+            return 0
+        elif len(expressions) == 1:
+            return expressions[0] * coefficients[0]
+        else:
+            return _WeightedSum(expressions, coefficients)
+
+ +
+ +

Creates the expression sum(expressions[i] * coefficients[i]).

+
+ + +
+
+
#   + +
@classmethod
+ + def + Term(cls, expression, coefficient): +
+ +
+ View Source +
    @classmethod
+    def Term(cls, expression, coefficient):
+        """Creates `expression * coefficient`."""
+        if cmh.is_zero(coefficient):
+            return 0
+        else:
+            return expression * coefficient
+
+ +
+ +

Creates expression * coefficient.

+
+ + +
+
+
#   + +
@classmethod
+ + def + IsEmptyOrAllNull(cls, coefficients): +
+ +
+ View Source +
    @classmethod
+    def IsEmptyOrAllNull(cls, coefficients):
+        for c in coefficients:
+            if not cmh.is_zero(c):
+                return False
+        return True
+
+ +
+ + + +
+
+
#   + +
@classmethod
+ + def + RebuildFromLinearExpressionProto(cls, model, proto): +
+ +
+ View Source +
    @classmethod
+    def RebuildFromLinearExpressionProto(cls, model, proto):
+        """Recreate a LinearExpr from a LinearExpressionProto."""
+        offset = proto.offset
+        num_elements = len(proto.vars)
+        if num_elements == 0:
+            return offset
+        elif num_elements == 1:
+            return IntVar(model, proto.vars[0], None) * proto.coeffs[0] + offset
+        else:
+            variables = []
+            coeffs = []
+            all_ones = True
+            for index, coeff in zip(proto.vars(), proto.coeffs()):
+                variables.append(IntVar(model, index, None))
+                coeffs.append(coeff)
+                if not cmh.is_one(coeff):
+                    all_ones = False
+            if all_ones:
+                return _SumArray(variables, offset)
+            else:
+                return _WeightedSum(variables, coeffs, offset)
+
+ +
+ +

Recreate a LinearExpr from a LinearExpressionProto.

+
+ + +
+
+
#   + + + def + GetIntegerVarValueMap(self): +
+ +
+ View Source +
    def GetIntegerVarValueMap(self):
+        """Scans the expression, and returns (var_coef_map, constant)."""
+        coeffs = collections.defaultdict(int)
+        constant = 0
+        to_process = [(self, 1)]
+        while to_process:  # Flatten to avoid recursion.
+            expr, coeff = to_process.pop()
+            if cmh.is_integral(expr):
+                constant += coeff * int(expr)
+            elif isinstance(expr, _ProductCst):
+                to_process.append(
+                    (expr.Expression(), coeff * expr.Coefficient()))
+            elif isinstance(expr, _Sum):
+                to_process.append((expr.Left(), coeff))
+                to_process.append((expr.Right(), coeff))
+            elif isinstance(expr, _SumArray):
+                for e in expr.Expressions():
+                    to_process.append((e, coeff))
+                constant += expr.Constant() * coeff
+            elif isinstance(expr, _WeightedSum):
+                for e, c in zip(expr.Expressions(), expr.Coefficients()):
+                    to_process.append((e, coeff * c))
+                constant += expr.Constant() * coeff
+            elif isinstance(expr, IntVar):
+                coeffs[expr] += coeff
+            elif isinstance(expr, _NotBooleanVariable):
+                constant += coeff
+                coeffs[expr.Not()] -= coeff
+            else:
+                raise TypeError('Unrecognized linear expression: ' + str(expr))
+
+        return coeffs, constant
+
+ +
+ +

Scans the expression, and returns (var_coef_map, constant).

+
+ + +
+
+
#   + + + def + GetFloatVarValueMap(self): +
+ +
+ View Source +
    def GetFloatVarValueMap(self):
+        """Scans the expression. Returns (var_coef_map, constant, is_integer)."""
+        coeffs = {}
+        constant = 0
+        to_process = [(self, 1)]
+        while to_process:  # Flatten to avoid recursion.
+            expr, coeff = to_process.pop()
+            if cmh.is_integral(expr):  # Keep integrality.
+                constant += coeff * int(expr)
+            elif cmh.is_a_number(expr):
+                constant += coeff * float(expr)
+            elif isinstance(expr, _ProductCst):
+                to_process.append(
+                    (expr.Expression(), coeff * expr.Coefficient()))
+            elif isinstance(expr, _Sum):
+                to_process.append((expr.Left(), coeff))
+                to_process.append((expr.Right(), coeff))
+            elif isinstance(expr, _SumArray):
+                for e in expr.Expressions():
+                    to_process.append((e, coeff))
+                constant += expr.Constant() * coeff
+            elif isinstance(expr, _WeightedSum):
+                for e, c in zip(expr.Expressions(), expr.Coefficients()):
+                    to_process.append((e, coeff * c))
+                constant += expr.Constant() * coeff
+            elif isinstance(expr, IntVar):
+                if expr in coeffs:
+                    coeffs[expr] += coeff
+                else:
+                    coeffs[expr] = coeff
+            elif isinstance(expr, _NotBooleanVariable):
+                constant += coeff
+                if expr.Not() in coeffs:
+                    coeffs[expr.Not()] -= coeff
+                else:
+                    coeffs[expr.Not()] = -coeff
+            else:
+                raise TypeError('Unrecognized linear expression: ' + str(expr))
+        is_integer = cmh.is_integral(constant)
+        if is_integer:
+            for coeff in coeffs.values():
+                if not cmh.is_integral(coeff):
+                    is_integer = False
+                    break
+        return coeffs, constant, is_integer
+
+ +
+ +

Scans the expression. Returns (var_coef_map, constant, is_integer).

+
+ + +
+
+
+
+ #   + + + class + IntVar(LinearExpr): +
+ +
+ View Source +
class IntVar(LinearExpr):
+    """An integer variable.
+
+  An IntVar is an object that can take on any integer value within defined
+  ranges. Variables appear in constraint like:
+
+      x + y >= 5
+      AllDifferent([x, y, z])
+
+  Solving a model is equivalent to finding, for each variable, a single value
+  from the set of initial values (called the initial domain), such that the
+  model is feasible, or optimal if you provided an objective function.
+  """
+
+    def __init__(self, model, domain, name):
+        """See CpModel.NewIntVar below."""
+        self.__model = model
+        self.__negation = None
+        # Python do not support multiple __init__ methods.
+        # This method is only called from the CpModel class.
+        # We hack the parameter to support the two cases:
+        # case 1:
+        #     model is a CpModelProto, domain is a Domain, and name is a string.
+        # case 2:
+        #     model is a CpModelProto, domain is an index (int), and name is None.
+        if cmh.is_integral(domain) and name is None:
+            self.__index = int(domain)
+            self.__var = model.variables[domain]
+        else:
+            self.__index = len(model.variables)
+            self.__var = model.variables.add()
+            self.__var.domain.extend(domain.FlattenedIntervals())
+            self.__var.name = name
+
+    def Index(self):
+        """Returns the index of the variable in the model."""
+        return self.__index
+
+    def Proto(self):
+        """Returns the variable protobuf."""
+        return self.__var
+
+    def IsEqualTo(self, other):
+        """Returns true if self == other in the python sense."""
+        if not isinstance(other, IntVar):
+            return False
+        return self.Index() == other.Index()
+
+    def __str__(self):
+        if not self.__var.name:
+            if len(self.__var.domain
+                  ) == 2 and self.__var.domain[0] == self.__var.domain[1]:
+                # Special case for constants.
+                return str(self.__var.domain[0])
+            else:
+                return 'unnamed_var_%i' % self.__index
+        return self.__var.name
+
+    def __repr__(self):
+        return '%s(%s)' % (self.__var.name, DisplayBounds(self.__var.domain))
+
+    def Name(self):
+        return self.__var.name
+
+    def Not(self):
+        """Returns the negation of a Boolean variable.
+
+    This method implements the logical negation of a Boolean variable.
+    It is only valid if the variable has a Boolean domain (0 or 1).
+
+    Note that this method is nilpotent: `x.Not().Not() == x`.
+    """
+
+        for bound in self.__var.domain:
+            if bound < 0 or bound > 1:
+                raise TypeError(
+                    'Cannot call Not on a non boolean variable: %s' % self)
+        if self.__negation is None:
+            self.__negation = _NotBooleanVariable(self)
+        return self.__negation
+
+ +
+ +

An integer variable.

+ +

An IntVar is an object that can take on any integer value within defined +ranges. Variables appear in constraint like:

+ +
x + y >= 5
+AllDifferent([x, y, z])
+
+ +

Solving a model is equivalent to finding, for each variable, a single value +from the set of initial values (called the initial domain), such that the +model is feasible, or optimal if you provided an objective function.

+
+ + +
+
#   + + + IntVar(model, domain, name) +
+ +
+ View Source +
    def __init__(self, model, domain, name):
+        """See CpModel.NewIntVar below."""
+        self.__model = model
+        self.__negation = None
+        # Python do not support multiple __init__ methods.
+        # This method is only called from the CpModel class.
+        # We hack the parameter to support the two cases:
+        # case 1:
+        #     model is a CpModelProto, domain is a Domain, and name is a string.
+        # case 2:
+        #     model is a CpModelProto, domain is an index (int), and name is None.
+        if cmh.is_integral(domain) and name is None:
+            self.__index = int(domain)
+            self.__var = model.variables[domain]
+        else:
+            self.__index = len(model.variables)
+            self.__var = model.variables.add()
+            self.__var.domain.extend(domain.FlattenedIntervals())
+            self.__var.name = name
+
+ +
+ +

See CpModel.NewIntVar below.

+
+ + +
+
+
#   + + + def + Index(self): +
+ +
+ View Source +
    def Index(self):
+        """Returns the index of the variable in the model."""
+        return self.__index
+
+ +
+ +

Returns the index of the variable in the model.

+
+ + +
+
+
#   + + + def + Proto(self): +
+ +
+ View Source +
    def Proto(self):
+        """Returns the variable protobuf."""
+        return self.__var
+
+ +
+ +

Returns the variable protobuf.

+
+ + +
+
+
#   + + + def + IsEqualTo(self, other): +
+ +
+ View Source +
    def IsEqualTo(self, other):
+        """Returns true if self == other in the python sense."""
+        if not isinstance(other, IntVar):
+            return False
+        return self.Index() == other.Index()
+
+ +
+ +

Returns true if self == other in the python sense.

+
+ + +
+
+
#   + + + def + Name(self): +
+ +
+ View Source +
    def Name(self):
+        return self.__var.name
+
+ +
+ + + +
+
+
#   + + + def + Not(self): +
+ +
+ View Source +
    def Not(self):
+        """Returns the negation of a Boolean variable.
+
+    This method implements the logical negation of a Boolean variable.
+    It is only valid if the variable has a Boolean domain (0 or 1).
+
+    Note that this method is nilpotent: `x.Not().Not() == x`.
+    """
+
+        for bound in self.__var.domain:
+            if bound < 0 or bound > 1:
+                raise TypeError(
+                    'Cannot call Not on a non boolean variable: %s' % self)
+        if self.__negation is None:
+            self.__negation = _NotBooleanVariable(self)
+        return self.__negation
+
+ +
+ +

Returns the negation of a Boolean variable.

+ +

This method implements the logical negation of a Boolean variable. +It is only valid if the variable has a Boolean domain (0 or 1).

+ +

Note that this method is nilpotent: x.Not().Not() == x.

+
+ + +
+ +
+
+
+ #   + + + class + BoundedLinearExpression: +
+ +
+ View Source +
class BoundedLinearExpression(object):
+    """Represents a linear constraint: `lb <= linear expression <= ub`.
+
+  The only use of this class is to be added to the CpModel through
+  `CpModel.Add(expression)`, as in:
+
+      model.Add(x + 2 * y -1 >= z)
+  """
+
+    def __init__(self, expr, bounds):
+        self.__expr = expr
+        self.__bounds = bounds
+
+    def __str__(self):
+        if len(self.__bounds) == 2:
+            lb = self.__bounds[0]
+            ub = self.__bounds[1]
+            if lb > INT_MIN and ub < INT_MAX:
+                if lb == ub:
+                    return str(self.__expr) + ' == ' + str(lb)
+                else:
+                    return str(lb) + ' <= ' + str(
+                        self.__expr) + ' <= ' + str(ub)
+            elif lb > INT_MIN:
+                return str(self.__expr) + ' >= ' + str(lb)
+            elif ub < INT_MAX:
+                return str(self.__expr) + ' <= ' + str(ub)
+            else:
+                return 'True (unbounded expr ' + str(self.__expr) + ')'
+        elif (len(self.__bounds) == 4 and self.__bounds[0] == INT_MIN and
+              self.__bounds[1] + 2 == self.__bounds[2] and
+              self.__bounds[3] == INT_MAX):
+            return str(self.__expr) + ' != ' + str(self.__bounds[1] + 1)
+        else:
+            return str(self.__expr) + ' in [' + DisplayBounds(
+                self.__bounds) + ']'
+
+    def Expression(self):
+        return self.__expr
+
+    def Bounds(self):
+        return self.__bounds
+
+    def __bool__(self):
+        coeffs_map, constant = self.__expr.GetIntegerVarValueMap()
+        all_coeffs = set(coeffs_map.values())
+        same_var = set([0])
+        eq_bounds = [0, 0]
+        different_vars = set([-1, 1])
+        ne_bounds = [INT_MIN, -1, 1, INT_MAX]
+        if (len(coeffs_map) == 1 and all_coeffs == same_var and
+                constant == 0 and
+            (self.__bounds == eq_bounds or self.__bounds == ne_bounds)):
+            return self.__bounds == eq_bounds
+        if (len(coeffs_map) == 2 and all_coeffs == different_vars and
+                constant == 0 and
+            (self.__bounds == eq_bounds or self.__bounds == ne_bounds)):
+            return self.__bounds == ne_bounds
+
+        raise NotImplementedError(
+            f'Evaluating a BoundedLinearExpression \'{self}\' as a Boolean value'
+            + ' is not supported.')
+
+ +
+ +

Represents a linear constraint: lb <= linear expression <= ub.

+ +

The only use of this class is to be added to the CpModel through +CpModel.Add(expression), as in:

+ +
model.Add(x + 2 * y -1 >= z)
+
+
+ + +
+
#   + + + BoundedLinearExpression(expr, bounds) +
+ +
+ View Source +
    def __init__(self, expr, bounds):
+        self.__expr = expr
+        self.__bounds = bounds
+
+ +
+ + + +
+
+
#   + + + def + Expression(self): +
+ +
+ View Source +
    def Expression(self):
+        return self.__expr
+
+ +
+ + + +
+
+
#   + + + def + Bounds(self): +
+ +
+ View Source +
    def Bounds(self):
+        return self.__bounds
+
+ +
+ + + +
+
+
+
+ #   + + + class + Constraint: +
+ +
+ View Source +
class Constraint(object):
+    """Base class for constraints.
+
+  Constraints are built by the CpModel through the Add<XXX> methods.
+  Once created by the CpModel class, they are automatically added to the model.
+  The purpose of this class is to allow specification of enforcement literals
+  for this constraint.
+
+      b = model.NewBoolVar('b')
+      x = model.NewIntVar(0, 10, 'x')
+      y = model.NewIntVar(0, 10, 'y')
+
+      model.Add(x + 2 * y == 5).OnlyEnforceIf(b.Not())
+  """
+
+    def __init__(self, constraints):
+        self.__index = len(constraints)
+        self.__constraint = constraints.add()
+
+    def OnlyEnforceIf(self, *boolvar):
+        """Adds an enforcement literal to the constraint.
+
+    This method adds one or more literals (that is, a boolean variable or its
+    negation) as enforcement literals. The conjunction of all these literals
+    determines whether the constraint is active or not. It acts as an
+    implication, so if the conjunction is true, it implies that the constraint
+    must be enforced. If it is false, then the constraint is ignored.
+
+    BoolOr, BoolAnd, and linear constraints all support enforcement literals.
+
+    Args:
+      *boolvar: One or more Boolean literals.
+
+    Returns:
+      self.
+    """
+        for lit in ExpandGeneratorOrTuple(boolvar):
+            if (isinstance(lit, bool) and
+                    bool(lit)) or (cmh.is_integral(lit) and int(lit) == 1):
+                # Always true. Do nothing.
+                pass
+            else:
+                self.__constraint.enforcement_literal.append(lit.Index())
+        return self
+
+    def Index(self):
+        """Returns the index of the constraint in the model."""
+        return self.__index
+
+    def Proto(self):
+        """Returns the constraint protobuf."""
+        return self.__constraint
+
+ +
+ +

Base class for constraints.

+ +

Constraints are built by the CpModel through the Add methods. +Once created by the CpModel class, they are automatically added to the model. +The purpose of this class is to allow specification of enforcement literals +for this constraint.

+ +
b = model.NewBoolVar('b')
+x = model.NewIntVar(0, 10, 'x')
+y = model.NewIntVar(0, 10, 'y')
+
+model.Add(x + 2 * y == 5).OnlyEnforceIf(b.Not())
+
+
+ + +
+
#   + + + Constraint(constraints) +
+ +
+ View Source +
    def __init__(self, constraints):
+        self.__index = len(constraints)
+        self.__constraint = constraints.add()
+
+ +
+ + + +
+
+
#   + + + def + OnlyEnforceIf(self, *boolvar): +
+ +
+ View Source +
    def OnlyEnforceIf(self, *boolvar):
+        """Adds an enforcement literal to the constraint.
+
+    This method adds one or more literals (that is, a boolean variable or its
+    negation) as enforcement literals. The conjunction of all these literals
+    determines whether the constraint is active or not. It acts as an
+    implication, so if the conjunction is true, it implies that the constraint
+    must be enforced. If it is false, then the constraint is ignored.
+
+    BoolOr, BoolAnd, and linear constraints all support enforcement literals.
+
+    Args:
+      *boolvar: One or more Boolean literals.
+
+    Returns:
+      self.
+    """
+        for lit in ExpandGeneratorOrTuple(boolvar):
+            if (isinstance(lit, bool) and
+                    bool(lit)) or (cmh.is_integral(lit) and int(lit) == 1):
+                # Always true. Do nothing.
+                pass
+            else:
+                self.__constraint.enforcement_literal.append(lit.Index())
+        return self
+
+ +
+ +

Adds an enforcement literal to the constraint.

+ +

This method adds one or more literals (that is, a boolean variable or its +negation) as enforcement literals. The conjunction of all these literals +determines whether the constraint is active or not. It acts as an +implication, so if the conjunction is true, it implies that the constraint +must be enforced. If it is false, then the constraint is ignored.

+ +

BoolOr, BoolAnd, and linear constraints all support enforcement literals.

+ +
Args
+ +
    +
  • *boolvar: One or more Boolean literals.
  • +
+ +
Returns
+ +
+

self.

+
+
+ + +
+
+
#   + + + def + Index(self): +
+ +
+ View Source +
    def Index(self):
+        """Returns the index of the constraint in the model."""
+        return self.__index
+
+ +
+ +

Returns the index of the constraint in the model.

+
+ + +
+
+
#   + + + def + Proto(self): +
+ +
+ View Source +
    def Proto(self):
+        """Returns the constraint protobuf."""
+        return self.__constraint
+
+ +
+ +

Returns the constraint protobuf.

+
+ + +
+
+
+
+ #   + + + class + IntervalVar: +
+ +
+ View Source +
class IntervalVar(object):
+    """Represents an Interval variable.
+
+  An interval variable is both a constraint and a variable. It is defined by
+  three integer variables: start, size, and end.
+
+  It is a constraint because, internally, it enforces that start + size == end.
+
+  It is also a variable as it can appear in specific scheduling constraints:
+  NoOverlap, NoOverlap2D, Cumulative.
+
+  Optionally, an enforcement literal can be added to this constraint, in which
+  case these scheduling constraints will ignore interval variables with
+  enforcement literals assigned to false. Conversely, these constraints will
+  also set these enforcement literals to false if they cannot fit these
+  intervals into the schedule.
+  """
+
+    def __init__(self, model, start, size, end, is_present_index, name):
+        self.__model = model
+        # As with the IntVar::__init__ method, we hack the __init__ method to
+        # support two use cases:
+        #   case 1: called when creating a new interval variable.
+        #      {start|size|end} are linear expressions, is_present_index is either
+        #      None or the index of a Boolean literal. name is a string
+        #   case 2: called when querying an existing interval variable.
+        #      start_index is an int, all parameters after are None.
+        if (size is None and end is None and is_present_index is None and
+                name is None):
+            self.__index = start
+            self.__ct = model.constraints[start]
+        else:
+            self.__index = len(model.constraints)
+            self.__ct = self.__model.constraints.add()
+            self.__ct.interval.start.CopyFrom(start)
+            self.__ct.interval.size.CopyFrom(size)
+            self.__ct.interval.end.CopyFrom(end)
+            if is_present_index is not None:
+                self.__ct.enforcement_literal.append(is_present_index)
+            if name:
+                self.__ct.name = name
+
+    def Index(self):
+        """Returns the index of the interval constraint in the model."""
+        return self.__index
+
+    def Proto(self):
+        """Returns the interval protobuf."""
+        return self.__ct.interval
+
+    def __str__(self):
+        return self.__ct.name
+
+    def __repr__(self):
+        interval = self.__ct.interval
+        if self.__ct.enforcement_literal:
+            return '%s(start = %s, size = %s, end = %s, is_present = %s)' % (
+                self.__ct.name, ShortExprName(self.__model, interval.start),
+                ShortExprName(self.__model, interval.size),
+                ShortExprName(self.__model, interval.end),
+                ShortName(self.__model, self.__ct.enforcement_literal[0]))
+        else:
+            return '%s(start = %s, size = %s, end = %s)' % (
+                self.__ct.name, ShortExprName(self.__model, interval.start),
+                ShortExprName(self.__model, interval.size),
+                ShortExprName(self.__model, interval.end))
+
+    def Name(self):
+        return self.__ct.name
+
+    def StartExpr(self):
+        return LinearExpr.RebuildFromLinearExpressionProto(
+            self.__model, self.__ct.interval.start)
+
+    def SizeExpr(self):
+        return LinearExpr.RebuildFromLinearExpressionProto(
+            self.__model, self.__ct.interval.size)
+
+    def EndExpr(self):
+        return LinearExpr.RebuildFromLinearExpressionProto(
+            self.__model, self.__ct.interval.end)
+
+ +
+ +

Represents an Interval variable.

+ +

An interval variable is both a constraint and a variable. It is defined by +three integer variables: start, size, and end.

+ +

It is a constraint because, internally, it enforces that start + size == end.

+ +

It is also a variable as it can appear in specific scheduling constraints: +NoOverlap, NoOverlap2D, Cumulative.

+ +

Optionally, an enforcement literal can be added to this constraint, in which +case these scheduling constraints will ignore interval variables with +enforcement literals assigned to false. Conversely, these constraints will +also set these enforcement literals to false if they cannot fit these +intervals into the schedule.

+
+ + +
+
#   + + + IntervalVar(model, start, size, end, is_present_index, name) +
+ +
+ View Source +
    def __init__(self, model, start, size, end, is_present_index, name):
+        self.__model = model
+        # As with the IntVar::__init__ method, we hack the __init__ method to
+        # support two use cases:
+        #   case 1: called when creating a new interval variable.
+        #      {start|size|end} are linear expressions, is_present_index is either
+        #      None or the index of a Boolean literal. name is a string
+        #   case 2: called when querying an existing interval variable.
+        #      start_index is an int, all parameters after are None.
+        if (size is None and end is None and is_present_index is None and
+                name is None):
+            self.__index = start
+            self.__ct = model.constraints[start]
+        else:
+            self.__index = len(model.constraints)
+            self.__ct = self.__model.constraints.add()
+            self.__ct.interval.start.CopyFrom(start)
+            self.__ct.interval.size.CopyFrom(size)
+            self.__ct.interval.end.CopyFrom(end)
+            if is_present_index is not None:
+                self.__ct.enforcement_literal.append(is_present_index)
+            if name:
+                self.__ct.name = name
+
+ +
+ + + +
+
+
#   + + + def + Index(self): +
+ +
+ View Source +
    def Index(self):
+        """Returns the index of the interval constraint in the model."""
+        return self.__index
+
+ +
+ +

Returns the index of the interval constraint in the model.

+
+ + +
+
+
#   + + + def + Proto(self): +
+ +
+ View Source +
    def Proto(self):
+        """Returns the interval protobuf."""
+        return self.__ct.interval
+
+ +
+ +

Returns the interval protobuf.

+
+ + +
+
+
#   + + + def + Name(self): +
+ +
+ View Source +
    def Name(self):
+        return self.__ct.name
+
+ +
+ + + +
+
+
#   + + + def + StartExpr(self): +
+ +
+ View Source +
    def StartExpr(self):
+        return LinearExpr.RebuildFromLinearExpressionProto(
+            self.__model, self.__ct.interval.start)
+
+ +
+ + + +
+
+
#   + + + def + SizeExpr(self): +
+ +
+ View Source +
    def SizeExpr(self):
+        return LinearExpr.RebuildFromLinearExpressionProto(
+            self.__model, self.__ct.interval.size)
+
+ +
+ + + +
+
+
#   + + + def + EndExpr(self): +
+ +
+ View Source +
    def EndExpr(self):
+        return LinearExpr.RebuildFromLinearExpressionProto(
+            self.__model, self.__ct.interval.end)
+
+ +
+ + + +
+
+
+
#   + + + def + ObjectIsATrueLiteral(literal): +
+ +
+ View Source +
def ObjectIsATrueLiteral(literal):
+    """Checks if literal is either True, or a Boolean literals fixed to True."""
+    if isinstance(literal, IntVar):
+        proto = literal.Proto()
+        return (len(proto.domain) == 2 and proto.domain[0] == 1 and
+                proto.domain[1] == 1)
+    if isinstance(literal, _NotBooleanVariable):
+        proto = literal.Not().Proto()
+        return (len(proto.domain) == 2 and proto.domain[0] == 0 and
+                proto.domain[1] == 0)
+    if cmh.is_integral(literal):
+        return int(literal) == 1
+    return False
+
+ +
+ +

Checks if literal is either True, or a Boolean literals fixed to True.

+
+ + +
+
+
#   + + + def + ObjectIsAFalseLiteral(literal): +
+ +
+ View Source +
def ObjectIsAFalseLiteral(literal):
+    """Checks if literal is either False, or a Boolean literals fixed to False."""
+    if isinstance(literal, IntVar):
+        proto = literal.Proto()
+        return (len(proto.domain) == 2 and proto.domain[0] == 0 and
+                proto.domain[1] == 0)
+    if isinstance(literal, _NotBooleanVariable):
+        proto = literal.Not().Proto()
+        return (len(proto.domain) == 2 and proto.domain[0] == 1 and
+                proto.domain[1] == 1)
+    if cmh.is_integral(literal):
+        return int(literal) == 0
+    return False
+
+ +
+ +

Checks if literal is either False, or a Boolean literals fixed to False.

+
+ + +
+
+
+ #   + + + class + CpModel: +
+ +
+ View Source +
class CpModel(object):
+    """Methods for building a CP model.
+
+  Methods beginning with:
+
+  * ```New``` create integer, boolean, or interval variables.
+  * ```Add``` create new constraints and add them to the model.
+  """
+
+    def __init__(self):
+        self.__model = cp_model_pb2.CpModelProto()
+        self.__constant_map = {}
+
+    # Integer variable.
+
+    def NewIntVar(self, lb, ub, name):
+        """Create an integer variable with domain [lb, ub].
+
+    The CP-SAT solver is limited to integer variables. If you have fractional
+    values, scale them up so that they become integers; if you have strings,
+    encode them as integers.
+
+    Args:
+      lb: Lower bound for the variable.
+      ub: Upper bound for the variable.
+      name: The name of the variable.
+
+    Returns:
+      a variable whose domain is [lb, ub].
+    """
+
+        return IntVar(self.__model, Domain(lb, ub), name)
+
+    def NewIntVarFromDomain(self, domain, name):
+        """Create an integer variable from a domain.
+
+    A domain is a set of integers specified by a collection of intervals.
+    For example, `model.NewIntVarFromDomain(cp_model.
+         Domain.FromIntervals([[1, 2], [4, 6]]), 'x')`
+
+    Args:
+      domain: An instance of the Domain class.
+      name: The name of the variable.
+
+    Returns:
+        a variable whose domain is the given domain.
+    """
+        return IntVar(self.__model, domain, name)
+
+    def NewBoolVar(self, name):
+        """Creates a 0-1 variable with the given name."""
+        return IntVar(self.__model, Domain(0, 1), name)
+
+    def NewConstant(self, value):
+        """Declares a constant integer."""
+        return IntVar(self.__model, self.GetOrMakeIndexFromConstant(value),
+                      None)
+
+    # Linear constraints.
+
+    def AddLinearConstraint(self, linear_expr, lb, ub):
+        """Adds the constraint: `lb <= linear_expr <= ub`."""
+        return self.AddLinearExpressionInDomain(linear_expr, Domain(lb, ub))
+
+    def AddLinearExpressionInDomain(self, linear_expr, domain):
+        """Adds the constraint: `linear_expr` in `domain`."""
+        if isinstance(linear_expr, LinearExpr):
+            ct = Constraint(self.__model.constraints)
+            model_ct = self.__model.constraints[ct.Index()]
+            coeffs_map, constant = linear_expr.GetIntegerVarValueMap()
+            for t in coeffs_map.items():
+                if not isinstance(t[0], IntVar):
+                    raise TypeError('Wrong argument' + str(t))
+                c = cmh.assert_is_int64(t[1])
+                model_ct.linear.vars.append(t[0].Index())
+                model_ct.linear.coeffs.append(c)
+            model_ct.linear.domain.extend([
+                cmh.capped_subtraction(x, constant)
+                for x in domain.FlattenedIntervals()
+            ])
+            return ct
+        elif cmh.is_integral(linear_expr):
+            if not domain.Contains(int(linear_expr)):
+                return self.AddBoolOr([])  # Evaluate to false.
+            # Nothing to do otherwise.
+        else:
+            raise TypeError(
+                'Not supported: CpModel.AddLinearExpressionInDomain(' +
+                str(linear_expr) + ' ' + str(domain) + ')')
+
+    def Add(self, ct):
+        """Adds a `BoundedLinearExpression` to the model.
+
+    Args:
+      ct: A [`BoundedLinearExpression`](#boundedlinearexpression).
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        if isinstance(ct, BoundedLinearExpression):
+            return self.AddLinearExpressionInDomain(
+                ct.Expression(), Domain.FromFlatIntervals(ct.Bounds()))
+        elif ct and isinstance(ct, bool):
+            return self.AddBoolOr([True])
+        elif not ct and isinstance(ct, bool):
+            return self.AddBoolOr([])  # Evaluate to false.
+        else:
+            raise TypeError('Not supported: CpModel.Add(' + str(ct) + ')')
+
+    # General Integer Constraints.
+
+    def AddAllDifferent(self, *expressions):
+        """Adds AllDifferent(expressions).
+
+    This constraint forces all expressions to have different values.
+
+    Args:
+      *expressions: simple expressions of the form a * var + constant.
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        expanded = ExpandGeneratorOrTuple(expressions)
+        model_ct.all_diff.exprs.extend(
+            [self.ParseLinearExpression(x) for x in expanded])
+        return ct
+
+    def AddElement(self, index, variables, target):
+        """Adds the element constraint: `variables[index] == target`."""
+
+        if not variables:
+            raise ValueError('AddElement expects a non-empty variables array')
+
+        if cmh.is_integral(index):
+            return self.Add(list(variables)[int(index)] == target)
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.element.index = self.GetOrMakeIndex(index)
+        model_ct.element.vars.extend(
+            [self.GetOrMakeIndex(x) for x in variables])
+        model_ct.element.target = self.GetOrMakeIndex(target)
+        return ct
+
+    def AddCircuit(self, arcs):
+        """Adds Circuit(arcs).
+
+    Adds a circuit constraint from a sparse list of arcs that encode the graph.
+
+    A circuit is a unique Hamiltonian path in a subgraph of the total
+    graph. In case a node 'i' is not in the path, then there must be a
+    loop arc 'i -> i' associated with a true literal. Otherwise
+    this constraint will fail.
+
+    Args:
+      arcs: a list of arcs. An arc is a tuple (source_node, destination_node,
+        literal). The arc is selected in the circuit if the literal is true.
+        Both source_node and destination_node must be integers between 0 and the
+        number of nodes - 1.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: If the list of arcs is empty.
+    """
+        if not arcs:
+            raise ValueError('AddCircuit expects a non-empty array of arcs')
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        for arc in arcs:
+            tail = cmh.assert_is_int32(arc[0])
+            head = cmh.assert_is_int32(arc[1])
+            lit = self.GetOrMakeBooleanIndex(arc[2])
+            model_ct.circuit.tails.append(tail)
+            model_ct.circuit.heads.append(head)
+            model_ct.circuit.literals.append(lit)
+        return ct
+
+    def AddMultipleCircuit(self, arcs):
+        """Adds a multiple circuit constraint, aka the "VRP" constraint.
+
+    The direct graph where arc #i (from tails[i] to head[i]) is present iff
+    literals[i] is true must satisfy this set of properties:
+    - #incoming arcs == 1 except for node 0.
+    - #outgoing arcs == 1 except for node 0.
+    - for node zero, #incoming arcs == #outgoing arcs.
+    - There are no duplicate arcs.
+    - Self-arcs are allowed except for node 0.
+    - There is no cycle in this graph, except through node 0.
+
+    Args:
+      arcs: a list of arcs. An arc is a tuple (source_node, destination_node,
+        literal). The arc is selected in the circuit if the literal is true.
+        Both source_node and destination_node must be integers between 0 and the
+        number of nodes - 1.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: If the list of arcs is empty.
+    """
+        if not arcs:
+            raise ValueError(
+                'AddMultipleCircuit expects a non-empty array of arcs')
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        for arc in arcs:
+            tail = cmh.assert_is_int32(arc[0])
+            head = cmh.assert_is_int32(arc[1])
+            lit = self.GetOrMakeBooleanIndex(arc[2])
+            model_ct.routes.tails.append(tail)
+            model_ct.routes.heads.append(head)
+            model_ct.routes.literals.append(lit)
+        return ct
+
+    def AddAllowedAssignments(self, variables, tuples_list):
+        """Adds AllowedAssignments(variables, tuples_list).
+
+    An AllowedAssignments constraint is a constraint on an array of variables,
+    which requires that when all variables are assigned values, the resulting
+    array equals one of the  tuples in `tuple_list`.
+
+    Args:
+      variables: A list of variables.
+      tuples_list: A list of admissible tuples. Each tuple must have the same
+        length as the variables, and the ith value of a tuple corresponds to the
+        ith variable.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      TypeError: If a tuple does not have the same size as the list of
+          variables.
+      ValueError: If the array of variables is empty.
+    """
+
+        if not variables:
+            raise ValueError(
+                'AddAllowedAssignments expects a non-empty variables '
+                'array')
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.table.vars.extend([self.GetOrMakeIndex(x) for x in variables])
+        arity = len(variables)
+        for t in tuples_list:
+            if len(t) != arity:
+                raise TypeError('Tuple ' + str(t) + ' has the wrong arity')
+            ar = []
+            for v in t:
+                ar.append(cmh.assert_is_int64(v))
+            model_ct.table.values.extend(ar)
+        return ct
+
+    def AddForbiddenAssignments(self, variables, tuples_list):
+        """Adds AddForbiddenAssignments(variables, [tuples_list]).
+
+    A ForbiddenAssignments constraint is a constraint on an array of variables
+    where the list of impossible combinations is provided in the tuples list.
+
+    Args:
+      variables: A list of variables.
+      tuples_list: A list of forbidden tuples. Each tuple must have the same
+        length as the variables, and the *i*th value of a tuple corresponds to
+        the *i*th variable.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      TypeError: If a tuple does not have the same size as the list of
+                 variables.
+      ValueError: If the array of variables is empty.
+    """
+
+        if not variables:
+            raise ValueError(
+                'AddForbiddenAssignments expects a non-empty variables '
+                'array')
+
+        index = len(self.__model.constraints)
+        ct = self.AddAllowedAssignments(variables, tuples_list)
+        self.__model.constraints[index].table.negated = True
+        return ct
+
+    def AddAutomaton(self, transition_variables, starting_state, final_states,
+                     transition_triples):
+        """Adds an automaton constraint.
+
+    An automaton constraint takes a list of variables (of size *n*), an initial
+    state, a set of final states, and a set of transitions. A transition is a
+    triplet (*tail*, *transition*, *head*), where *tail* and *head* are states,
+    and *transition* is the label of an arc from *head* to *tail*,
+    corresponding to the value of one variable in the list of variables.
+
+    This automaton will be unrolled into a flow with *n* + 1 phases. Each phase
+    contains the possible states of the automaton. The first state contains the
+    initial state. The last phase contains the final states.
+
+    Between two consecutive phases *i* and *i* + 1, the automaton creates a set
+    of arcs. For each transition (*tail*, *transition*, *head*), it will add
+    an arc from the state *tail* of phase *i* and the state *head* of phase
+    *i* + 1. This arc is labeled by the value *transition* of the variables
+    `variables[i]`. That is, this arc can only be selected if `variables[i]`
+    is assigned the value *transition*.
+
+    A feasible solution of this constraint is an assignment of variables such
+    that, starting from the initial state in phase 0, there is a path labeled by
+    the values of the variables that ends in one of the final states in the
+    final phase.
+
+    Args:
+      transition_variables: A non-empty list of variables whose values
+        correspond to the labels of the arcs traversed by the automaton.
+      starting_state: The initial state of the automaton.
+      final_states: A non-empty list of admissible final states.
+      transition_triples: A list of transitions for the automaton, in the
+        following format (current_state, variable_value, next_state).
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: if `transition_variables`, `final_states`, or
+        `transition_triples` are empty.
+    """
+
+        if not transition_variables:
+            raise ValueError(
+                'AddAutomaton expects a non-empty transition_variables '
+                'array')
+        if not final_states:
+            raise ValueError('AddAutomaton expects some final states')
+
+        if not transition_triples:
+            raise ValueError('AddAutomaton expects some transition triples')
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.automaton.vars.extend(
+            [self.GetOrMakeIndex(x) for x in transition_variables])
+        starting_state = cmh.assert_is_int64(starting_state)
+        model_ct.automaton.starting_state = starting_state
+        for v in final_states:
+            v = cmh.assert_is_int64(v)
+            model_ct.automaton.final_states.append(v)
+        for t in transition_triples:
+            if len(t) != 3:
+                raise TypeError('Tuple ' + str(t) +
+                                ' has the wrong arity (!= 3)')
+            tail = cmh.assert_is_int64(t[0])
+            label = cmh.assert_is_int64(t[1])
+            head = cmh.assert_is_int64(t[2])
+            model_ct.automaton.transition_tail.append(tail)
+            model_ct.automaton.transition_label.append(label)
+            model_ct.automaton.transition_head.append(head)
+        return ct
+
+    def AddInverse(self, variables, inverse_variables):
+        """Adds Inverse(variables, inverse_variables).
+
+    An inverse constraint enforces that if `variables[i]` is assigned a value
+    `j`, then `inverse_variables[j]` is assigned a value `i`. And vice versa.
+
+    Args:
+      variables: An array of integer variables.
+      inverse_variables: An array of integer variables.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      TypeError: if variables and inverse_variables have different lengths, or
+          if they are empty.
+    """
+
+        if not variables or not inverse_variables:
+            raise TypeError(
+                'The Inverse constraint does not accept empty arrays')
+        if len(variables) != len(inverse_variables):
+            raise TypeError(
+                'In the inverse constraint, the two array variables and'
+                ' inverse_variables must have the same length.')
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.inverse.f_direct.extend(
+            [self.GetOrMakeIndex(x) for x in variables])
+        model_ct.inverse.f_inverse.extend(
+            [self.GetOrMakeIndex(x) for x in inverse_variables])
+        return ct
+
+    def AddReservoirConstraint(self, times, level_changes, min_level,
+                               max_level):
+        """Adds Reservoir(times, level_changes, min_level, max_level).
+
+    Maintains a reservoir level within bounds. The water level starts at 0, and
+    at any time, it must be between min_level and max_level.
+
+    If the affine expression `times[i]` is assigned a value t, then the current
+    level changes by `level_changes[i]`, which is constant, at time t.
+
+     Note that min level must be <= 0, and the max level must be >= 0. Please
+     use fixed level_changes to simulate initial state.
+
+     Therefore, at any time:
+         sum(level_changes[i] if times[i] <= t) in [min_level, max_level]
+
+    Args:
+      times: A list of affine expressions which specify the time of the filling
+        or emptying the reservoir.
+      level_changes: A list of integer values that specifies the amount of the
+        emptying or filling.
+      min_level: At any time, the level of the reservoir must be greater or
+        equal than the min level.
+      max_level: At any time, the level of the reservoir must be less or equal
+        than the max level.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: if max_level < min_level.
+
+      ValueError: if max_level < 0.
+
+      ValueError: if min_level > 0
+    """
+
+        if max_level < min_level:
+            return ValueError(
+                'Reservoir constraint must have a max_level >= min_level')
+
+        if max_level < 0:
+            return ValueError('Reservoir constraint must have a max_level >= 0')
+
+        if min_level > 0:
+            return ValueError('Reservoir constraint must have a min_level <= 0')
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.reservoir.time_exprs.extend(
+            [self.ParseLinearExpression(x) for x in times])
+        model_ct.reservoir.level_changes.extend(level_changes)
+        model_ct.reservoir.min_level = min_level
+        model_ct.reservoir.max_level = max_level
+        return ct
+
+    def AddReservoirConstraintWithActive(self, times, level_changes, actives,
+                                         min_level, max_level):
+        """Adds Reservoir(times, level_changes, actives, min_level, max_level).
+
+    Maintains a reservoir level within bounds. The water level starts at 0, and
+    at any time, it must be between min_level and max_level.
+
+    If the variable `times[i]` is assigned a value t, and `actives[i]` is
+    `True`, then the current level changes by `level_changes[i]`, which is
+    constant,
+    at time t.
+
+     Note that min level must be <= 0, and the max level must be >= 0. Please
+     use fixed level_changes to simulate initial state.
+
+     Therefore, at any time:
+         sum(level_changes[i] * actives[i] if times[i] <= t) in [min_level,
+         max_level]
+
+
+    The array of boolean variables 'actives', if defined, indicates which
+    actions are actually performed.
+
+    Args:
+      times: A list of affine expressions which specify the time of the filling
+        or emptying the reservoir.
+      level_changes: A list of integer values that specifies the amount of the
+        emptying or filling.
+      actives: a list of boolean variables. They indicates if the
+        emptying/refilling events actually take place.
+      min_level: At any time, the level of the reservoir must be greater or
+        equal than the min level.
+      max_level: At any time, the level of the reservoir must be less or equal
+        than the max level.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: if max_level < min_level.
+
+      ValueError: if max_level < 0.
+
+      ValueError: if min_level > 0
+    """
+
+        if max_level < min_level:
+            return ValueError(
+                'Reservoir constraint must have a max_level >= min_level')
+
+        if max_level < 0:
+            return ValueError('Reservoir constraint must have a max_level >= 0')
+
+        if min_level > 0:
+            return ValueError('Reservoir constraint must have a min_level <= 0')
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.reservoir.time_exprs.extend(
+            [self.ParseLinearExpression(x) for x in times])
+        model_ct.reservoir.level_changes.extend(level_changes)
+        model_ct.reservoir.active_literals.extend(
+            [self.GetOrMakeIndex(x) for x in actives])
+        model_ct.reservoir.min_level = min_level
+        model_ct.reservoir.max_level = max_level
+        return ct
+
+    def AddMapDomain(self, var, bool_var_array, offset=0):
+        """Adds `var == i + offset <=> bool_var_array[i] == true for all i`."""
+
+        for i, bool_var in enumerate(bool_var_array):
+            b_index = bool_var.Index()
+            var_index = var.Index()
+            model_ct = self.__model.constraints.add()
+            model_ct.linear.vars.append(var_index)
+            model_ct.linear.coeffs.append(1)
+            model_ct.linear.domain.extend([offset + i, offset + i])
+            model_ct.enforcement_literal.append(b_index)
+
+            model_ct = self.__model.constraints.add()
+            model_ct.linear.vars.append(var_index)
+            model_ct.linear.coeffs.append(1)
+            model_ct.enforcement_literal.append(-b_index - 1)
+            if offset + i - 1 >= INT_MIN:
+                model_ct.linear.domain.extend([INT_MIN, offset + i - 1])
+            if offset + i + 1 <= INT_MAX:
+                model_ct.linear.domain.extend([offset + i + 1, INT_MAX])
+
+    def AddImplication(self, a, b):
+        """Adds `a => b` (`a` implies `b`)."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.bool_or.literals.append(self.GetOrMakeBooleanIndex(b))
+        model_ct.enforcement_literal.append(self.GetOrMakeBooleanIndex(a))
+        return ct
+
+    def AddBoolOr(self, *literals):
+        """Adds `Or(literals) == true`: Sum(literals) >= 1."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.bool_or.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+    def AddAtLeastOne(self, *literals):
+        """Same as `AddBoolOr`: `Sum(literals) >= 1`."""
+        return self.AddBoolOr(*literals)
+
+    def AddAtMostOne(self, *literals):
+        """Adds `AtMostOne(literals)`: `Sum(literals) <= 1`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.at_most_one.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+    def AddExactlyOne(self, *literals):
+        """Adds `ExactlyOne(literals)`: `Sum(literals) == 1`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.exactly_one.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+    def AddBoolAnd(self, *literals):
+        """Adds `And(literals) == true`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.bool_and.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+    def AddBoolXOr(self, *literals):
+        """Adds `XOr(literals) == true`.
+
+    In contrast to AddBoolOr and AddBoolAnd, it does not support
+        .OnlyEnforceIf().
+
+    Args:
+      *literals: the list of literals in the constraint.
+
+    Returns:
+      An `Constraint` object.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.bool_xor.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+    def AddMinEquality(self, target, exprs):
+        """Adds `target == Min(exprs)`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.lin_max.exprs.extend(
+            [self.ParseLinearExpression(x, True) for x in exprs])
+        model_ct.lin_max.target.CopyFrom(
+            self.ParseLinearExpression(target, True))
+        return ct
+
+    def AddMaxEquality(self, target, exprs):
+        """Adds `target == Max(exprs)`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.lin_max.exprs.extend(
+            [self.ParseLinearExpression(x) for x in exprs])
+        model_ct.lin_max.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+    def AddDivisionEquality(self, target, num, denom):
+        """Adds `target == num // denom` (integer division rounded towards 0)."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.int_div.exprs.append(self.ParseLinearExpression(num))
+        model_ct.int_div.exprs.append(self.ParseLinearExpression(denom))
+        model_ct.int_div.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+    def AddAbsEquality(self, target, expr):
+        """Adds `target == Abs(var)`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.lin_max.exprs.append(self.ParseLinearExpression(expr))
+        model_ct.lin_max.exprs.append(self.ParseLinearExpression(expr, True))
+        model_ct.lin_max.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+    def AddModuloEquality(self, target, var, mod):
+        """Adds `target = var % mod`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.int_mod.exprs.append(self.ParseLinearExpression(var))
+        model_ct.int_mod.exprs.append(self.ParseLinearExpression(mod))
+        model_ct.int_mod.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+    def AddMultiplicationEquality(self, target, *expressions):
+        """Adds `target == expressions[0] * .. * expressions[n]`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.int_prod.exprs.extend([
+            self.ParseLinearExpression(expr)
+            for expr in ExpandGeneratorOrTuple(expressions)
+        ])
+        model_ct.int_prod.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+    # Scheduling support
+
+    def NewIntervalVar(self, start, size, end, name):
+        """Creates an interval variable from start, size, and end.
+
+    An interval variable is a constraint, that is itself used in other
+    constraints like NoOverlap.
+
+    Internally, it ensures that `start + size == end`.
+
+    Args:
+      start: The start of the interval. It can be an affine or constant
+        expression.
+      size: The size of the interval. It can be an affine or constant
+        expression.
+      end: The end of the interval. It can be an affine or constant expression.
+      name: The name of the interval variable.
+
+    Returns:
+      An `IntervalVar` object.
+    """
+
+        self.Add(start + size == end)
+
+        start_expr = self.ParseLinearExpression(start)
+        size_expr = self.ParseLinearExpression(size)
+        end_expr = self.ParseLinearExpression(end)
+        if len(start_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: start must be affine or constant.')
+        if len(size_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: size must be affine or constant.')
+        if len(end_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: end must be affine or constant.')
+        return IntervalVar(self.__model, start_expr, size_expr, end_expr, None,
+                           name)
+
+    def NewFixedSizeIntervalVar(self, start, size, name):
+        """Creates an interval variable from start, and a fixed size.
+
+    An interval variable is a constraint, that is itself used in other
+    constraints like NoOverlap.
+
+    Args:
+      start: The start of the interval. It can be an affine or constant
+        expression.
+      size: The size of the interval. It must be an integer value.
+      name: The name of the interval variable.
+
+    Returns:
+      An `IntervalVar` object.
+    """
+        size = cmh.assert_is_int64(size)
+        start_expr = self.ParseLinearExpression(start)
+        size_expr = self.ParseLinearExpression(size)
+        end_expr = self.ParseLinearExpression(start + size)
+        if len(start_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: start must be affine or constant.')
+        return IntervalVar(self.__model, start_expr, size_expr, end_expr, None,
+                           name)
+
+    def NewOptionalIntervalVar(self, start, size, end, is_present, name):
+        """Creates an optional interval var from start, size, end, and is_present.
+
+    An optional interval variable is a constraint, that is itself used in other
+    constraints like NoOverlap. This constraint is protected by an is_present
+    literal that indicates if it is active or not.
+
+    Internally, it ensures that `is_present` implies `start + size == end`.
+
+    Args:
+      start: The start of the interval. It can be an integer value, or an
+        integer variable.
+      size: The size of the interval. It can be an integer value, or an integer
+        variable.
+      end: The end of the interval. It can be an integer value, or an integer
+        variable.
+      is_present: A literal that indicates if the interval is active or not. A
+        inactive interval is simply ignored by all constraints.
+      name: The name of the interval variable.
+
+    Returns:
+      An `IntervalVar` object.
+    """
+
+        # Add the linear constraint.
+        self.Add(start + size == end).OnlyEnforceIf(is_present)
+
+        # Creates the IntervalConstraintProto object.
+        is_present_index = self.GetOrMakeBooleanIndex(is_present)
+        start_expr = self.ParseLinearExpression(start)
+        size_expr = self.ParseLinearExpression(size)
+        end_expr = self.ParseLinearExpression(end)
+        if len(start_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: start must be affine or constant.')
+        if len(size_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: size must be affine or constant.')
+        if len(end_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: end must be affine or constant.')
+        return IntervalVar(self.__model, start_expr, size_expr, end_expr,
+                           is_present_index, name)
+
+    def NewOptionalFixedSizeIntervalVar(self, start, size, is_present, name):
+        """Creates an interval variable from start, and a fixed size.
+
+    An interval variable is a constraint, that is itself used in other
+    constraints like NoOverlap.
+
+    Args:
+      start: The start of the interval. It can be an affine or constant
+        expression.
+      size: The size of the interval. It must be an integer value.
+      is_present: A literal that indicates if the interval is active or not. A
+        inactive interval is simply ignored by all constraints.
+      name: The name of the interval variable.
+
+    Returns:
+      An `IntervalVar` object.
+    """
+        size = cmh.assert_is_int64(size)
+        start_expr = self.ParseLinearExpression(start)
+        size_expr = self.ParseLinearExpression(size)
+        end_expr = self.ParseLinearExpression(start + size)
+        if len(start_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: start must be affine or constant.')
+        is_present_index = self.GetOrMakeBooleanIndex(is_present)
+        return IntervalVar(self.__model, start_expr, size_expr, end_expr,
+                           is_present_index, name)
+
+    def AddNoOverlap(self, interval_vars):
+        """Adds NoOverlap(interval_vars).
+
+    A NoOverlap constraint ensures that all present intervals do not overlap
+    in time.
+
+    Args:
+      interval_vars: The list of interval variables to constrain.
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.no_overlap.intervals.extend(
+            [self.GetIntervalIndex(x) for x in interval_vars])
+        return ct
+
+    def AddNoOverlap2D(self, x_intervals, y_intervals):
+        """Adds NoOverlap2D(x_intervals, y_intervals).
+
+    A NoOverlap2D constraint ensures that all present rectangles do not overlap
+    on a plane. Each rectangle is aligned with the X and Y axis, and is defined
+    by two intervals which represent its projection onto the X and Y axis.
+
+    Furthermore, one box is optional if at least one of the x or y interval is
+    optional.
+
+    Args:
+      x_intervals: The X coordinates of the rectangles.
+      y_intervals: The Y coordinates of the rectangles.
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.no_overlap_2d.x_intervals.extend(
+            [self.GetIntervalIndex(x) for x in x_intervals])
+        model_ct.no_overlap_2d.y_intervals.extend(
+            [self.GetIntervalIndex(x) for x in y_intervals])
+        return ct
+
+    def AddCumulative(self, intervals, demands, capacity):
+        """Adds Cumulative(intervals, demands, capacity).
+
+    This constraint enforces that:
+
+        for all t:
+          sum(demands[i]
+            if (start(intervals[i]) <= t < end(intervals[i])) and
+            (intervals[i] is present)) <= capacity
+
+    Args:
+      intervals: The list of intervals.
+      demands: The list of demands for each interval. Each demand must be >= 0.
+        Each demand can be an integer value, or an integer variable.
+      capacity: The maximum capacity of the cumulative constraint. It must be a
+        positive integer value or variable.
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.cumulative.intervals.extend(
+            [self.GetIntervalIndex(x) for x in intervals])
+        for d in demands:
+            model_ct.cumulative.demands.append(self.ParseLinearExpression(d))
+        model_ct.cumulative.capacity.CopyFrom(
+            self.ParseLinearExpression(capacity))
+        return ct
+
+    # Support for deep copy.
+    def CopyFrom(self, other_model):
+        """Reset the model, and creates a new one from a CpModelProto instance."""
+        self.__model.CopyFrom(other_model.Proto())
+
+        # Rebuild constant map.
+        self.__constant_map.clear()
+        for i, var in enumerate(self.__model.variables):
+            if len(var.domain) == 2 and var.domain[0] == var.domain[1]:
+                self.__constant_map[var.domain[0]] = i
+
+    def GetBoolVarFromProtoIndex(self, index):
+        """Returns an already created Boolean variable from its index."""
+        if index < 0 or index >= len(self.__model.variables):
+            raise ValueError(
+                f'GetBoolVarFromProtoIndex: out of bound index {index}')
+        var = self.__model.variables[index]
+        if len(var.domain) != 2 or var.domain[0] < 0 or var.domain[1] > 1:
+            raise ValueError(
+                f'GetBoolVarFromProtoIndex: index {index} does not reference' +
+                ' a Boolean variable')
+
+        return IntVar(self.__model, index, None)
+
+    def GetIntVarFromProtoIndex(self, index):
+        """Returns an already created integer variable from its index."""
+        if index < 0 or index >= len(self.__model.variables):
+            raise ValueError(
+                f'GetIntVarFromProtoIndex: out of bound index {index}')
+        return IntVar(self.__model, index, None)
+
+    def GetIntervalVarFromProtoIndex(self, index):
+        """Returns an already created interval variable from its index."""
+        if index < 0 or index >= len(self.__model.constraints):
+            raise ValueError(
+                f'GetIntervalVarFromProtoIndex: out of bound index {index}')
+        ct = self.__model.constraints[index]
+        if not ct.HasField('interval'):
+            raise ValueError(
+                f'GetIntervalVarFromProtoIndex: index {index} does not reference an'
+                + ' interval variable')
+
+        return IntervalVar(self.__model, index, None, None, None, None)
+
+    # Helpers.
+
+    def __str__(self):
+        return str(self.__model)
+
+    def Proto(self):
+        """Returns the underlying CpModelProto."""
+        return self.__model
+
+    def Negated(self, index):
+        return -index - 1
+
+    def GetOrMakeIndex(self, arg):
+        """Returns the index of a variable, its negation, or a number."""
+        if isinstance(arg, IntVar):
+            return arg.Index()
+        elif (isinstance(arg, _ProductCst) and
+              isinstance(arg.Expression(), IntVar) and arg.Coefficient() == -1):
+            return -arg.Expression().Index() - 1
+        elif cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            return self.GetOrMakeIndexFromConstant(arg)
+        else:
+            raise TypeError('NotSupported: model.GetOrMakeIndex(' + str(arg) +
+                            ')')
+
+    def GetOrMakeBooleanIndex(self, arg):
+        """Returns an index from a boolean expression."""
+        if isinstance(arg, IntVar):
+            self.AssertIsBooleanVariable(arg)
+            return arg.Index()
+        elif isinstance(arg, _NotBooleanVariable):
+            self.AssertIsBooleanVariable(arg.Not())
+            return arg.Index()
+        elif cmh.is_integral(arg):
+            cmh.assert_is_boolean(arg)
+            return self.GetOrMakeIndexFromConstant(int(arg))
+        else:
+            raise TypeError('NotSupported: model.GetOrMakeBooleanIndex(' +
+                            str(arg) + ')')
+
+    def GetIntervalIndex(self, arg):
+        if not isinstance(arg, IntervalVar):
+            raise TypeError('NotSupported: model.GetIntervalIndex(%s)' % arg)
+        return arg.Index()
+
+    def GetOrMakeIndexFromConstant(self, value):
+        if value in self.__constant_map:
+            return self.__constant_map[value]
+        index = len(self.__model.variables)
+        var = self.__model.variables.add()
+        var.domain.extend([value, value])
+        self.__constant_map[value] = index
+        return index
+
+    def VarIndexToVarProto(self, var_index):
+        if var_index >= 0:
+            return self.__model.variables[var_index]
+        else:
+            return self.__model.variables[-var_index - 1]
+
+    def ParseLinearExpression(self, linear_expr, negate=False):
+        """Returns a LinearExpressionProto built from a LinearExpr instance."""
+        result = cp_model_pb2.LinearExpressionProto()
+        mult = -1 if negate else 1
+        if cmh.is_integral(linear_expr):
+            result.offset = int(linear_expr) * mult
+            return result
+
+        if isinstance(linear_expr, IntVar):
+            result.vars.append(self.GetOrMakeIndex(linear_expr))
+            result.coeffs.append(mult)
+            return result
+
+        coeffs_map, constant = linear_expr.GetIntegerVarValueMap()
+        result.offset = constant * mult
+        for t in coeffs_map.items():
+            if not isinstance(t[0], IntVar):
+                raise TypeError('Wrong argument' + str(t))
+            c = cmh.assert_is_int64(t[1])
+            result.vars.append(t[0].Index())
+            result.coeffs.append(c * mult)
+        return result
+
+    def _SetObjective(self, obj, minimize):
+        """Sets the objective of the model."""
+        self.__model.ClearField('objective')
+        self.__model.ClearField('floating_point_objective')
+        if isinstance(obj, IntVar):
+            self.__model.objective.coeffs.append(1)
+            self.__model.objective.offset = 0
+            if minimize:
+                self.__model.objective.vars.append(obj.Index())
+                self.__model.objective.scaling_factor = 1
+            else:
+                self.__model.objective.vars.append(self.Negated(obj.Index()))
+                self.__model.objective.scaling_factor = -1
+        elif isinstance(obj, LinearExpr):
+            coeffs_map, constant, is_integer = obj.GetFloatVarValueMap()
+            if is_integer:
+                if minimize:
+                    self.__model.objective.scaling_factor = 1
+                    self.__model.objective.offset = constant
+                else:
+                    self.__model.objective.scaling_factor = -1
+                    self.__model.objective.offset = -constant
+                for v, c, in coeffs_map.items():
+                    self.__model.objective.coeffs.append(c)
+                    if minimize:
+                        self.__model.objective.vars.append(v.Index())
+                    else:
+                        self.__model.objective.vars.append(
+                            self.Negated(v.Index()))
+            else:
+                self.__model.floating_point_objective.maximize = not minimize
+                self.__model.floating_point_objective.offset = constant
+                for v, c, in coeffs_map.items():
+                    self.__model.floating_point_objective.coeffs.append(c)
+                    self.__model.floating_point_objective.vars.append(v.Index())
+        elif cmh.is_integral(obj):
+            self.__model.objective.offset = int(obj)
+            self.__model.objective.scaling_factor = 1
+        else:
+            raise TypeError('TypeError: ' + str(obj) +
+                            ' is not a valid objective')
+
+    def Minimize(self, obj):
+        """Sets the objective of the model to minimize(obj)."""
+        self._SetObjective(obj, minimize=True)
+
+    def Maximize(self, obj):
+        """Sets the objective of the model to maximize(obj)."""
+        self._SetObjective(obj, minimize=False)
+
+    def HasObjective(self):
+        return self.__model.HasField('objective')
+
+    def AddDecisionStrategy(self, variables, var_strategy, domain_strategy):
+        """Adds a search strategy to the model.
+
+    Args:
+      variables: a list of variables this strategy will assign.
+      var_strategy: heuristic to choose the next variable to assign.
+      domain_strategy: heuristic to reduce the domain of the selected variable.
+        Currently, this is advanced code: the union of all strategies added to
+          the model must be complete, i.e. instantiates all variables.
+          Otherwise, Solve() will fail.
+    """
+
+        strategy = self.__model.search_strategy.add()
+        for v in variables:
+            strategy.variables.append(v.Index())
+        strategy.variable_selection_strategy = var_strategy
+        strategy.domain_reduction_strategy = domain_strategy
+
+    def ModelStats(self):
+        """Returns a string containing some model statistics."""
+        return swig_helper.CpSatHelper.SerializedModelStats(
+            self.__model.SerializeToString())
+
+    def Validate(self):
+        """Returns a string indicating that the model is invalid."""
+        return swig_helper.CpSatHelper.SerializedValidateModel(
+            self.__model.SerializeToString())
+
+    def ExportToFile(self, file):
+        """Write the model as a protocol buffer to 'file'.
+
+    Args:
+      file: file to write the model to. If the filename ends with 'txt', the
+        model will be written as a text file, otherwise, the binary format will
+        be used.
+
+    Returns:
+      True if the model was correctly written.
+    """
+        return swig_helper.CpSatHelper.SerializedWriteModelToFile(
+            self.__model.SerializeToString(), file)
+
+    def AssertIsBooleanVariable(self, x):
+        if isinstance(x, IntVar):
+            var = self.__model.variables[x.Index()]
+            if len(var.domain) != 2 or var.domain[0] < 0 or var.domain[1] > 1:
+                raise TypeError('TypeError: ' + str(x) +
+                                ' is not a boolean variable')
+        elif not isinstance(x, _NotBooleanVariable):
+            raise TypeError('TypeError: ' + str(x) +
+                            ' is not a boolean variable')
+
+    def AddHint(self, var, value):
+        """Adds 'var == value' as a hint to the solver."""
+        self.__model.solution_hint.vars.append(self.GetOrMakeIndex(var))
+        self.__model.solution_hint.values.append(value)
+
+    def ClearHints(self):
+        """Remove any solution hint from the model."""
+        self.__model.ClearField('solution_hint')
+
+    def AddAssumption(self, lit):
+        """Add the literal 'lit' to the model as assumptions."""
+        self.__model.assumptions.append(self.GetOrMakeBooleanIndex(lit))
+
+    def AddAssumptions(self, literals):
+        """Add the literals to the model as assumptions."""
+        for lit in literals:
+            self.AddAssumption(lit)
+
+    def ClearAssumptions(self):
+        """Remove all assumptions from the model."""
+        self.__model.ClearField('assumptions')
+
+ +
+ +

Methods for building a CP model.

+ +

Methods beginning with:

+ +
    +
  • New create integer, boolean, or interval variables.
  • +
  • Add create new constraints and add them to the model.
  • +
+
+ + +
+
#   + + + CpModel() +
+ +
+ View Source +
    def __init__(self):
+        self.__model = cp_model_pb2.CpModelProto()
+        self.__constant_map = {}
+
+ +
+ + + +
+
+
#   + + + def + NewIntVar(self, lb, ub, name): +
+ +
+ View Source +
    def NewIntVar(self, lb, ub, name):
+        """Create an integer variable with domain [lb, ub].
+
+    The CP-SAT solver is limited to integer variables. If you have fractional
+    values, scale them up so that they become integers; if you have strings,
+    encode them as integers.
+
+    Args:
+      lb: Lower bound for the variable.
+      ub: Upper bound for the variable.
+      name: The name of the variable.
+
+    Returns:
+      a variable whose domain is [lb, ub].
+    """
+
+        return IntVar(self.__model, Domain(lb, ub), name)
+
+ +
+ +

Create an integer variable with domain [lb, ub].

+ +

The CP-SAT solver is limited to integer variables. If you have fractional +values, scale them up so that they become integers; if you have strings, +encode them as integers.

+ +
Args
+ +
    +
  • lb: Lower bound for the variable.
  • +
  • ub: Upper bound for the variable.
  • +
  • name: The name of the variable.
  • +
+ +
Returns
+ +
+

a variable whose domain is [lb, ub].

+
+
+ + +
+
+
#   + + + def + NewIntVarFromDomain(self, domain, name): +
+ +
+ View Source +
    def NewIntVarFromDomain(self, domain, name):
+        """Create an integer variable from a domain.
+
+    A domain is a set of integers specified by a collection of intervals.
+    For example, `model.NewIntVarFromDomain(cp_model.
+         Domain.FromIntervals([[1, 2], [4, 6]]), 'x')`
+
+    Args:
+      domain: An instance of the Domain class.
+      name: The name of the variable.
+
+    Returns:
+        a variable whose domain is the given domain.
+    """
+        return IntVar(self.__model, domain, name)
+
+ +
+ +

Create an integer variable from a domain.

+ +

A domain is a set of integers specified by a collection of intervals. +For example, model.NewIntVarFromDomain(cp_model. + Domain.FromIntervals([[1, 2], [4, 6]]), 'x')

+ +
Args
+ +
    +
  • domain: An instance of the Domain class.
  • +
  • name: The name of the variable.
  • +
+ +
Returns
+ +
+

a variable whose domain is the given domain.

+
+
+ + +
+
+
#   + + + def + NewBoolVar(self, name): +
+ +
+ View Source +
    def NewBoolVar(self, name):
+        """Creates a 0-1 variable with the given name."""
+        return IntVar(self.__model, Domain(0, 1), name)
+
+ +
+ +

Creates a 0-1 variable with the given name.

+
+ + +
+
+
#   + + + def + NewConstant(self, value): +
+ +
+ View Source +
    def NewConstant(self, value):
+        """Declares a constant integer."""
+        return IntVar(self.__model, self.GetOrMakeIndexFromConstant(value),
+                      None)
+
+ +
+ +

Declares a constant integer.

+
+ + +
+
+
#   + + + def + AddLinearConstraint(self, linear_expr, lb, ub): +
+ +
+ View Source +
    def AddLinearConstraint(self, linear_expr, lb, ub):
+        """Adds the constraint: `lb <= linear_expr <= ub`."""
+        return self.AddLinearExpressionInDomain(linear_expr, Domain(lb, ub))
+
+ +
+ +

Adds the constraint: lb <= linear_expr <= ub.

+
+ + +
+
+
#   + + + def + AddLinearExpressionInDomain(self, linear_expr, domain): +
+ +
+ View Source +
    def AddLinearExpressionInDomain(self, linear_expr, domain):
+        """Adds the constraint: `linear_expr` in `domain`."""
+        if isinstance(linear_expr, LinearExpr):
+            ct = Constraint(self.__model.constraints)
+            model_ct = self.__model.constraints[ct.Index()]
+            coeffs_map, constant = linear_expr.GetIntegerVarValueMap()
+            for t in coeffs_map.items():
+                if not isinstance(t[0], IntVar):
+                    raise TypeError('Wrong argument' + str(t))
+                c = cmh.assert_is_int64(t[1])
+                model_ct.linear.vars.append(t[0].Index())
+                model_ct.linear.coeffs.append(c)
+            model_ct.linear.domain.extend([
+                cmh.capped_subtraction(x, constant)
+                for x in domain.FlattenedIntervals()
+            ])
+            return ct
+        elif cmh.is_integral(linear_expr):
+            if not domain.Contains(int(linear_expr)):
+                return self.AddBoolOr([])  # Evaluate to false.
+            # Nothing to do otherwise.
+        else:
+            raise TypeError(
+                'Not supported: CpModel.AddLinearExpressionInDomain(' +
+                str(linear_expr) + ' ' + str(domain) + ')')
+
+ +
+ +

Adds the constraint: linear_expr in domain.

+
+ + +
+
+
#   + + + def + Add(self, ct): +
+ +
+ View Source +
    def Add(self, ct):
+        """Adds a `BoundedLinearExpression` to the model.
+
+    Args:
+      ct: A [`BoundedLinearExpression`](#boundedlinearexpression).
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        if isinstance(ct, BoundedLinearExpression):
+            return self.AddLinearExpressionInDomain(
+                ct.Expression(), Domain.FromFlatIntervals(ct.Bounds()))
+        elif ct and isinstance(ct, bool):
+            return self.AddBoolOr([True])
+        elif not ct and isinstance(ct, bool):
+            return self.AddBoolOr([])  # Evaluate to false.
+        else:
+            raise TypeError('Not supported: CpModel.Add(' + str(ct) + ')')
+
+ +
+ +

Adds a BoundedLinearExpression to the model.

+ +
Args
+ + + +
Returns
+ +
+

An instance of the Constraint class.

+
+
+ + +
+
+
#   + + + def + AddAllDifferent(self, *expressions): +
+ +
+ View Source +
    def AddAllDifferent(self, *expressions):
+        """Adds AllDifferent(expressions).
+
+    This constraint forces all expressions to have different values.
+
+    Args:
+      *expressions: simple expressions of the form a * var + constant.
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        expanded = ExpandGeneratorOrTuple(expressions)
+        model_ct.all_diff.exprs.extend(
+            [self.ParseLinearExpression(x) for x in expanded])
+        return ct
+
+ +
+ +

Adds AllDifferent(expressions).

+ +

This constraint forces all expressions to have different values.

+ +
Args
+ +
    +
  • *expressions: simple expressions of the form a * var + constant.
  • +
+ +
Returns
+ +
+

An instance of the Constraint class.

+
+
+ + +
+
+
#   + + + def + AddElement(self, index, variables, target): +
+ +
+ View Source +
    def AddElement(self, index, variables, target):
+        """Adds the element constraint: `variables[index] == target`."""
+
+        if not variables:
+            raise ValueError('AddElement expects a non-empty variables array')
+
+        if cmh.is_integral(index):
+            return self.Add(list(variables)[int(index)] == target)
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.element.index = self.GetOrMakeIndex(index)
+        model_ct.element.vars.extend(
+            [self.GetOrMakeIndex(x) for x in variables])
+        model_ct.element.target = self.GetOrMakeIndex(target)
+        return ct
+
+ +
+ +

Adds the element constraint: variables[index] == target.

+
+ + +
+
+
#   + + + def + AddCircuit(self, arcs): +
+ +
+ View Source +
    def AddCircuit(self, arcs):
+        """Adds Circuit(arcs).
+
+    Adds a circuit constraint from a sparse list of arcs that encode the graph.
+
+    A circuit is a unique Hamiltonian path in a subgraph of the total
+    graph. In case a node 'i' is not in the path, then there must be a
+    loop arc 'i -> i' associated with a true literal. Otherwise
+    this constraint will fail.
+
+    Args:
+      arcs: a list of arcs. An arc is a tuple (source_node, destination_node,
+        literal). The arc is selected in the circuit if the literal is true.
+        Both source_node and destination_node must be integers between 0 and the
+        number of nodes - 1.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: If the list of arcs is empty.
+    """
+        if not arcs:
+            raise ValueError('AddCircuit expects a non-empty array of arcs')
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        for arc in arcs:
+            tail = cmh.assert_is_int32(arc[0])
+            head = cmh.assert_is_int32(arc[1])
+            lit = self.GetOrMakeBooleanIndex(arc[2])
+            model_ct.circuit.tails.append(tail)
+            model_ct.circuit.heads.append(head)
+            model_ct.circuit.literals.append(lit)
+        return ct
+
+ +
+ +

Adds Circuit(arcs).

+ +

Adds a circuit constraint from a sparse list of arcs that encode the graph.

+ +

A circuit is a unique Hamiltonian path in a subgraph of the total +graph. In case a node 'i' is not in the path, then there must be a +loop arc 'i -> i' associated with a true literal. Otherwise +this constraint will fail.

+ +
Args
+ +
    +
  • arcs: a list of arcs. An arc is a tuple (source_node, destination_node, +literal). The arc is selected in the circuit if the literal is true. +Both source_node and destination_node must be integers between 0 and the +number of nodes - 1.
  • +
+ +
Returns
+ +
+

An instance of the Constraint class.

+
+ +
Raises
+ +
    +
  • ValueError: If the list of arcs is empty.
  • +
+
+ + +
+
+
#   + + + def + AddMultipleCircuit(self, arcs): +
+ +
+ View Source +
    def AddMultipleCircuit(self, arcs):
+        """Adds a multiple circuit constraint, aka the "VRP" constraint.
+
+    The direct graph where arc #i (from tails[i] to head[i]) is present iff
+    literals[i] is true must satisfy this set of properties:
+    - #incoming arcs == 1 except for node 0.
+    - #outgoing arcs == 1 except for node 0.
+    - for node zero, #incoming arcs == #outgoing arcs.
+    - There are no duplicate arcs.
+    - Self-arcs are allowed except for node 0.
+    - There is no cycle in this graph, except through node 0.
+
+    Args:
+      arcs: a list of arcs. An arc is a tuple (source_node, destination_node,
+        literal). The arc is selected in the circuit if the literal is true.
+        Both source_node and destination_node must be integers between 0 and the
+        number of nodes - 1.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: If the list of arcs is empty.
+    """
+        if not arcs:
+            raise ValueError(
+                'AddMultipleCircuit expects a non-empty array of arcs')
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        for arc in arcs:
+            tail = cmh.assert_is_int32(arc[0])
+            head = cmh.assert_is_int32(arc[1])
+            lit = self.GetOrMakeBooleanIndex(arc[2])
+            model_ct.routes.tails.append(tail)
+            model_ct.routes.heads.append(head)
+            model_ct.routes.literals.append(lit)
+        return ct
+
+ +
+ +

Adds a multiple circuit constraint, aka the "VRP" constraint.

+ +

The direct graph where arc #i (from tails[i] to head[i]) is present iff +literals[i] is true must satisfy this set of properties:

+ +
    +
  • #incoming arcs == 1 except for node 0.
  • +
  • #outgoing arcs == 1 except for node 0.
  • +
  • for node zero, #incoming arcs == #outgoing arcs.
  • +
  • There are no duplicate arcs.
  • +
  • Self-arcs are allowed except for node 0.
  • +
  • There is no cycle in this graph, except through node 0.
  • +
+ +
Args
+ +
    +
  • arcs: a list of arcs. An arc is a tuple (source_node, destination_node, +literal). The arc is selected in the circuit if the literal is true. +Both source_node and destination_node must be integers between 0 and the +number of nodes - 1.
  • +
+ +
Returns
+ +
+

An instance of the Constraint class.

+
+ +
Raises
+ +
    +
  • ValueError: If the list of arcs is empty.
  • +
+
+ + +
+
+
#   + + + def + AddAllowedAssignments(self, variables, tuples_list): +
+ +
+ View Source +
    def AddAllowedAssignments(self, variables, tuples_list):
+        """Adds AllowedAssignments(variables, tuples_list).
+
+    An AllowedAssignments constraint is a constraint on an array of variables,
+    which requires that when all variables are assigned values, the resulting
+    array equals one of the  tuples in `tuple_list`.
+
+    Args:
+      variables: A list of variables.
+      tuples_list: A list of admissible tuples. Each tuple must have the same
+        length as the variables, and the ith value of a tuple corresponds to the
+        ith variable.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      TypeError: If a tuple does not have the same size as the list of
+          variables.
+      ValueError: If the array of variables is empty.
+    """
+
+        if not variables:
+            raise ValueError(
+                'AddAllowedAssignments expects a non-empty variables '
+                'array')
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.table.vars.extend([self.GetOrMakeIndex(x) for x in variables])
+        arity = len(variables)
+        for t in tuples_list:
+            if len(t) != arity:
+                raise TypeError('Tuple ' + str(t) + ' has the wrong arity')
+            ar = []
+            for v in t:
+                ar.append(cmh.assert_is_int64(v))
+            model_ct.table.values.extend(ar)
+        return ct
+
+ +
+ +

Adds AllowedAssignments(variables, tuples_list).

+ +

An AllowedAssignments constraint is a constraint on an array of variables, +which requires that when all variables are assigned values, the resulting +array equals one of the tuples in tuple_list.

+ +
Args
+ +
    +
  • variables: A list of variables.
  • +
  • tuples_list: A list of admissible tuples. Each tuple must have the same +length as the variables, and the ith value of a tuple corresponds to the +ith variable.
  • +
+ +
Returns
+ +
+

An instance of the Constraint class.

+
+ +
Raises
+ +
    +
  • TypeError: If a tuple does not have the same size as the list of +variables.
  • +
  • ValueError: If the array of variables is empty.
  • +
+
+ + +
+
+
#   + + + def + AddForbiddenAssignments(self, variables, tuples_list): +
+ +
+ View Source +
    def AddForbiddenAssignments(self, variables, tuples_list):
+        """Adds AddForbiddenAssignments(variables, [tuples_list]).
+
+    A ForbiddenAssignments constraint is a constraint on an array of variables
+    where the list of impossible combinations is provided in the tuples list.
+
+    Args:
+      variables: A list of variables.
+      tuples_list: A list of forbidden tuples. Each tuple must have the same
+        length as the variables, and the *i*th value of a tuple corresponds to
+        the *i*th variable.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      TypeError: If a tuple does not have the same size as the list of
+                 variables.
+      ValueError: If the array of variables is empty.
+    """
+
+        if not variables:
+            raise ValueError(
+                'AddForbiddenAssignments expects a non-empty variables '
+                'array')
+
+        index = len(self.__model.constraints)
+        ct = self.AddAllowedAssignments(variables, tuples_list)
+        self.__model.constraints[index].table.negated = True
+        return ct
+
+ +
+ +

Adds AddForbiddenAssignments(variables, [tuples_list]).

+ +

A ForbiddenAssignments constraint is a constraint on an array of variables +where the list of impossible combinations is provided in the tuples list.

+ +
Args
+ +
    +
  • variables: A list of variables.
  • +
  • tuples_list: A list of forbidden tuples. Each tuple must have the same +length as the variables, and the ith value of a tuple corresponds to +the ith variable.
  • +
+ +
Returns
+ +
+

An instance of the Constraint class.

+
+ +
Raises
+ +
    +
  • TypeError: If a tuple does not have the same size as the list of +variables.
  • +
  • ValueError: If the array of variables is empty.
  • +
+
+ + +
+
+
#   + + + def + AddAutomaton( + self, + transition_variables, + starting_state, + final_states, + transition_triples +): +
+ +
+ View Source +
    def AddAutomaton(self, transition_variables, starting_state, final_states,
+                     transition_triples):
+        """Adds an automaton constraint.
+
+    An automaton constraint takes a list of variables (of size *n*), an initial
+    state, a set of final states, and a set of transitions. A transition is a
+    triplet (*tail*, *transition*, *head*), where *tail* and *head* are states,
+    and *transition* is the label of an arc from *head* to *tail*,
+    corresponding to the value of one variable in the list of variables.
+
+    This automaton will be unrolled into a flow with *n* + 1 phases. Each phase
+    contains the possible states of the automaton. The first state contains the
+    initial state. The last phase contains the final states.
+
+    Between two consecutive phases *i* and *i* + 1, the automaton creates a set
+    of arcs. For each transition (*tail*, *transition*, *head*), it will add
+    an arc from the state *tail* of phase *i* and the state *head* of phase
+    *i* + 1. This arc is labeled by the value *transition* of the variables
+    `variables[i]`. That is, this arc can only be selected if `variables[i]`
+    is assigned the value *transition*.
+
+    A feasible solution of this constraint is an assignment of variables such
+    that, starting from the initial state in phase 0, there is a path labeled by
+    the values of the variables that ends in one of the final states in the
+    final phase.
+
+    Args:
+      transition_variables: A non-empty list of variables whose values
+        correspond to the labels of the arcs traversed by the automaton.
+      starting_state: The initial state of the automaton.
+      final_states: A non-empty list of admissible final states.
+      transition_triples: A list of transitions for the automaton, in the
+        following format (current_state, variable_value, next_state).
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: if `transition_variables`, `final_states`, or
+        `transition_triples` are empty.
+    """
+
+        if not transition_variables:
+            raise ValueError(
+                'AddAutomaton expects a non-empty transition_variables '
+                'array')
+        if not final_states:
+            raise ValueError('AddAutomaton expects some final states')
+
+        if not transition_triples:
+            raise ValueError('AddAutomaton expects some transition triples')
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.automaton.vars.extend(
+            [self.GetOrMakeIndex(x) for x in transition_variables])
+        starting_state = cmh.assert_is_int64(starting_state)
+        model_ct.automaton.starting_state = starting_state
+        for v in final_states:
+            v = cmh.assert_is_int64(v)
+            model_ct.automaton.final_states.append(v)
+        for t in transition_triples:
+            if len(t) != 3:
+                raise TypeError('Tuple ' + str(t) +
+                                ' has the wrong arity (!= 3)')
+            tail = cmh.assert_is_int64(t[0])
+            label = cmh.assert_is_int64(t[1])
+            head = cmh.assert_is_int64(t[2])
+            model_ct.automaton.transition_tail.append(tail)
+            model_ct.automaton.transition_label.append(label)
+            model_ct.automaton.transition_head.append(head)
+        return ct
+
+ +
+ +

Adds an automaton constraint.

+ +

An automaton constraint takes a list of variables (of size n), an initial +state, a set of final states, and a set of transitions. A transition is a +triplet (tail, transition, head), where tail and head are states, +and transition is the label of an arc from head to tail, +corresponding to the value of one variable in the list of variables.

+ +

This automaton will be unrolled into a flow with n + 1 phases. Each phase +contains the possible states of the automaton. The first state contains the +initial state. The last phase contains the final states.

+ +

Between two consecutive phases i and i + 1, the automaton creates a set +of arcs. For each transition (tail, transition, head), it will add +an arc from the state tail of phase i and the state head of phase +i + 1. This arc is labeled by the value transition of the variables +variables[i]. That is, this arc can only be selected if variables[i] +is assigned the value transition.

+ +

A feasible solution of this constraint is an assignment of variables such +that, starting from the initial state in phase 0, there is a path labeled by +the values of the variables that ends in one of the final states in the +final phase.

+ +
Args
+ +
    +
  • transition_variables: A non-empty list of variables whose values +correspond to the labels of the arcs traversed by the automaton.
  • +
  • starting_state: The initial state of the automaton.
  • +
  • final_states: A non-empty list of admissible final states.
  • +
  • transition_triples: A list of transitions for the automaton, in the +following format (current_state, variable_value, next_state).
  • +
+ +
Returns
+ +
+

An instance of the Constraint class.

+
+ +
Raises
+ +
    +
  • ValueError: if transition_variables, final_states, or +transition_triples are empty.
  • +
+
+ + +
+
+
#   + + + def + AddInverse(self, variables, inverse_variables): +
+ +
+ View Source +
    def AddInverse(self, variables, inverse_variables):
+        """Adds Inverse(variables, inverse_variables).
+
+    An inverse constraint enforces that if `variables[i]` is assigned a value
+    `j`, then `inverse_variables[j]` is assigned a value `i`. And vice versa.
+
+    Args:
+      variables: An array of integer variables.
+      inverse_variables: An array of integer variables.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      TypeError: if variables and inverse_variables have different lengths, or
+          if they are empty.
+    """
+
+        if not variables or not inverse_variables:
+            raise TypeError(
+                'The Inverse constraint does not accept empty arrays')
+        if len(variables) != len(inverse_variables):
+            raise TypeError(
+                'In the inverse constraint, the two array variables and'
+                ' inverse_variables must have the same length.')
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.inverse.f_direct.extend(
+            [self.GetOrMakeIndex(x) for x in variables])
+        model_ct.inverse.f_inverse.extend(
+            [self.GetOrMakeIndex(x) for x in inverse_variables])
+        return ct
+
+ +
+ +

Adds Inverse(variables, inverse_variables).

+ +

An inverse constraint enforces that if variables[i] is assigned a value +j, then inverse_variables[j] is assigned a value i. And vice versa.

+ +
Args
+ +
    +
  • variables: An array of integer variables.
  • +
  • inverse_variables: An array of integer variables.
  • +
+ +
Returns
+ +
+

An instance of the Constraint class.

+
+ +
Raises
+ +
    +
  • TypeError: if variables and inverse_variables have different lengths, or +if they are empty.
  • +
+
+ + +
+
+
#   + + + def + AddReservoirConstraint(self, times, level_changes, min_level, max_level): +
+ +
+ View Source +
    def AddReservoirConstraint(self, times, level_changes, min_level,
+                               max_level):
+        """Adds Reservoir(times, level_changes, min_level, max_level).
+
+    Maintains a reservoir level within bounds. The water level starts at 0, and
+    at any time, it must be between min_level and max_level.
+
+    If the affine expression `times[i]` is assigned a value t, then the current
+    level changes by `level_changes[i]`, which is constant, at time t.
+
+     Note that min level must be <= 0, and the max level must be >= 0. Please
+     use fixed level_changes to simulate initial state.
+
+     Therefore, at any time:
+         sum(level_changes[i] if times[i] <= t) in [min_level, max_level]
+
+    Args:
+      times: A list of affine expressions which specify the time of the filling
+        or emptying the reservoir.
+      level_changes: A list of integer values that specifies the amount of the
+        emptying or filling.
+      min_level: At any time, the level of the reservoir must be greater or
+        equal than the min level.
+      max_level: At any time, the level of the reservoir must be less or equal
+        than the max level.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: if max_level < min_level.
+
+      ValueError: if max_level < 0.
+
+      ValueError: if min_level > 0
+    """
+
+        if max_level < min_level:
+            return ValueError(
+                'Reservoir constraint must have a max_level >= min_level')
+
+        if max_level < 0:
+            return ValueError('Reservoir constraint must have a max_level >= 0')
+
+        if min_level > 0:
+            return ValueError('Reservoir constraint must have a min_level <= 0')
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.reservoir.time_exprs.extend(
+            [self.ParseLinearExpression(x) for x in times])
+        model_ct.reservoir.level_changes.extend(level_changes)
+        model_ct.reservoir.min_level = min_level
+        model_ct.reservoir.max_level = max_level
+        return ct
+
+ +
+ +

Adds Reservoir(times, level_changes, min_level, max_level).

+ +

Maintains a reservoir level within bounds. The water level starts at 0, and +at any time, it must be between min_level and max_level.

+ +

If the affine expression times[i] is assigned a value t, then the current +level changes by level_changes[i], which is constant, at time t.

+ +

Note that min level must be <= 0, and the max level must be >= 0. Please + use fixed level_changes to simulate initial state.

+ +

Therefore, at any time: + sum(level_changes[i] if times[i] <= t) in [min_level, max_level]

+ +
Args
+ +
    +
  • times: A list of affine expressions which specify the time of the filling +or emptying the reservoir.
  • +
  • level_changes: A list of integer values that specifies the amount of the +emptying or filling.
  • +
  • min_level: At any time, the level of the reservoir must be greater or +equal than the min level.
  • +
  • max_level: At any time, the level of the reservoir must be less or equal +than the max level.
  • +
+ +
Returns
+ +
+

An instance of the Constraint class.

+
+ +
Raises
+ +
    +
  • ValueError: if max_level < min_level.
  • +
  • ValueError: if max_level < 0.
  • +
  • ValueError: if min_level > 0
  • +
+
+ + +
+
+
#   + + + def + AddReservoirConstraintWithActive(self, times, level_changes, actives, min_level, max_level): +
+ +
+ View Source +
    def AddReservoirConstraintWithActive(self, times, level_changes, actives,
+                                         min_level, max_level):
+        """Adds Reservoir(times, level_changes, actives, min_level, max_level).
+
+    Maintains a reservoir level within bounds. The water level starts at 0, and
+    at any time, it must be between min_level and max_level.
+
+    If the variable `times[i]` is assigned a value t, and `actives[i]` is
+    `True`, then the current level changes by `level_changes[i]`, which is
+    constant,
+    at time t.
+
+     Note that min level must be <= 0, and the max level must be >= 0. Please
+     use fixed level_changes to simulate initial state.
+
+     Therefore, at any time:
+         sum(level_changes[i] * actives[i] if times[i] <= t) in [min_level,
+         max_level]
+
+
+    The array of boolean variables 'actives', if defined, indicates which
+    actions are actually performed.
+
+    Args:
+      times: A list of affine expressions which specify the time of the filling
+        or emptying the reservoir.
+      level_changes: A list of integer values that specifies the amount of the
+        emptying or filling.
+      actives: a list of boolean variables. They indicates if the
+        emptying/refilling events actually take place.
+      min_level: At any time, the level of the reservoir must be greater or
+        equal than the min level.
+      max_level: At any time, the level of the reservoir must be less or equal
+        than the max level.
+
+    Returns:
+      An instance of the `Constraint` class.
+
+    Raises:
+      ValueError: if max_level < min_level.
+
+      ValueError: if max_level < 0.
+
+      ValueError: if min_level > 0
+    """
+
+        if max_level < min_level:
+            return ValueError(
+                'Reservoir constraint must have a max_level >= min_level')
+
+        if max_level < 0:
+            return ValueError('Reservoir constraint must have a max_level >= 0')
+
+        if min_level > 0:
+            return ValueError('Reservoir constraint must have a min_level <= 0')
+
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.reservoir.time_exprs.extend(
+            [self.ParseLinearExpression(x) for x in times])
+        model_ct.reservoir.level_changes.extend(level_changes)
+        model_ct.reservoir.active_literals.extend(
+            [self.GetOrMakeIndex(x) for x in actives])
+        model_ct.reservoir.min_level = min_level
+        model_ct.reservoir.max_level = max_level
+        return ct
+
+ +
+ +

Adds Reservoir(times, level_changes, actives, min_level, max_level).

+ +

Maintains a reservoir level within bounds. The water level starts at 0, and +at any time, it must be between min_level and max_level.

+ +

If the variable times[i] is assigned a value t, and actives[i] is +True, then the current level changes by level_changes[i], which is +constant, +at time t.

+ +

Note that min level must be <= 0, and the max level must be >= 0. Please + use fixed level_changes to simulate initial state.

+ +

Therefore, at any time: + sum(level_changes[i] * actives[i] if times[i] <= t) in [min_level, + max_level]

+ +

The array of boolean variables 'actives', if defined, indicates which +actions are actually performed.

+ +
Args
+ +
    +
  • times: A list of affine expressions which specify the time of the filling +or emptying the reservoir.
  • +
  • level_changes: A list of integer values that specifies the amount of the +emptying or filling.
  • +
  • actives: a list of boolean variables. They indicates if the +emptying/refilling events actually take place.
  • +
  • min_level: At any time, the level of the reservoir must be greater or +equal than the min level.
  • +
  • max_level: At any time, the level of the reservoir must be less or equal +than the max level.
  • +
+ +
Returns
+ +
+

An instance of the Constraint class.

+
+ +
Raises
+ +
    +
  • ValueError: if max_level < min_level.
  • +
  • ValueError: if max_level < 0.
  • +
  • ValueError: if min_level > 0
  • +
+
+ + +
+
+
#   + + + def + AddMapDomain(self, var, bool_var_array, offset=0): +
+ +
+ View Source +
    def AddMapDomain(self, var, bool_var_array, offset=0):
+        """Adds `var == i + offset <=> bool_var_array[i] == true for all i`."""
+
+        for i, bool_var in enumerate(bool_var_array):
+            b_index = bool_var.Index()
+            var_index = var.Index()
+            model_ct = self.__model.constraints.add()
+            model_ct.linear.vars.append(var_index)
+            model_ct.linear.coeffs.append(1)
+            model_ct.linear.domain.extend([offset + i, offset + i])
+            model_ct.enforcement_literal.append(b_index)
+
+            model_ct = self.__model.constraints.add()
+            model_ct.linear.vars.append(var_index)
+            model_ct.linear.coeffs.append(1)
+            model_ct.enforcement_literal.append(-b_index - 1)
+            if offset + i - 1 >= INT_MIN:
+                model_ct.linear.domain.extend([INT_MIN, offset + i - 1])
+            if offset + i + 1 <= INT_MAX:
+                model_ct.linear.domain.extend([offset + i + 1, INT_MAX])
+
+ +
+ +

Adds var == i + offset <=> bool_var_array[i] == true for all i.

+
+ + +
+
+
#   + + + def + AddImplication(self, a, b): +
+ +
+ View Source +
    def AddImplication(self, a, b):
+        """Adds `a => b` (`a` implies `b`)."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.bool_or.literals.append(self.GetOrMakeBooleanIndex(b))
+        model_ct.enforcement_literal.append(self.GetOrMakeBooleanIndex(a))
+        return ct
+
+ +
+ +

Adds a => b (a implies b).

+
+ + +
+
+
#   + + + def + AddBoolOr(self, *literals): +
+ +
+ View Source +
    def AddBoolOr(self, *literals):
+        """Adds `Or(literals) == true`: Sum(literals) >= 1."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.bool_or.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+ +
+ +

Adds Or(literals) == true: Sum(literals) >= 1.

+
+ + +
+
+
#   + + + def + AddAtLeastOne(self, *literals): +
+ +
+ View Source +
    def AddAtLeastOne(self, *literals):
+        """Same as `AddBoolOr`: `Sum(literals) >= 1`."""
+        return self.AddBoolOr(*literals)
+
+ +
+ +

Same as AddBoolOr: Sum(literals) >= 1.

+
+ + +
+
+
#   + + + def + AddAtMostOne(self, *literals): +
+ +
+ View Source +
    def AddAtMostOne(self, *literals):
+        """Adds `AtMostOne(literals)`: `Sum(literals) <= 1`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.at_most_one.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+ +
+ +

Adds AtMostOne(literals): Sum(literals) <= 1.

+
+ + +
+
+
#   + + + def + AddExactlyOne(self, *literals): +
+ +
+ View Source +
    def AddExactlyOne(self, *literals):
+        """Adds `ExactlyOne(literals)`: `Sum(literals) == 1`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.exactly_one.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+ +
+ +

Adds ExactlyOne(literals): Sum(literals) == 1.

+
+ + +
+
+
#   + + + def + AddBoolAnd(self, *literals): +
+ +
+ View Source +
    def AddBoolAnd(self, *literals):
+        """Adds `And(literals) == true`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.bool_and.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+ +
+ +

Adds And(literals) == true.

+
+ + +
+
+
#   + + + def + AddBoolXOr(self, *literals): +
+ +
+ View Source +
    def AddBoolXOr(self, *literals):
+        """Adds `XOr(literals) == true`.
+
+    In contrast to AddBoolOr and AddBoolAnd, it does not support
+        .OnlyEnforceIf().
+
+    Args:
+      *literals: the list of literals in the constraint.
+
+    Returns:
+      An `Constraint` object.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.bool_xor.literals.extend([
+            self.GetOrMakeBooleanIndex(x)
+            for x in ExpandGeneratorOrTuple(literals)
+        ])
+        return ct
+
+ +
+ +

Adds XOr(literals) == true.

+ +

In contrast to AddBoolOr and AddBoolAnd, it does not support + .OnlyEnforceIf().

+ +
Args
+ +
    +
  • *literals: the list of literals in the constraint.
  • +
+ +
Returns
+ +
+

An Constraint object.

+
+
+ + +
+
+
#   + + + def + AddMinEquality(self, target, exprs): +
+ +
+ View Source +
    def AddMinEquality(self, target, exprs):
+        """Adds `target == Min(exprs)`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.lin_max.exprs.extend(
+            [self.ParseLinearExpression(x, True) for x in exprs])
+        model_ct.lin_max.target.CopyFrom(
+            self.ParseLinearExpression(target, True))
+        return ct
+
+ +
+ +

Adds target == Min(exprs).

+
+ + +
+
+
#   + + + def + AddMaxEquality(self, target, exprs): +
+ +
+ View Source +
    def AddMaxEquality(self, target, exprs):
+        """Adds `target == Max(exprs)`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.lin_max.exprs.extend(
+            [self.ParseLinearExpression(x) for x in exprs])
+        model_ct.lin_max.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+ +
+ +

Adds target == Max(exprs).

+
+ + +
+
+
#   + + + def + AddDivisionEquality(self, target, num, denom): +
+ +
+ View Source +
    def AddDivisionEquality(self, target, num, denom):
+        """Adds `target == num // denom` (integer division rounded towards 0)."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.int_div.exprs.append(self.ParseLinearExpression(num))
+        model_ct.int_div.exprs.append(self.ParseLinearExpression(denom))
+        model_ct.int_div.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+ +
+ +

Adds target == num // denom (integer division rounded towards 0).

+
+ + +
+
+
#   + + + def + AddAbsEquality(self, target, expr): +
+ +
+ View Source +
    def AddAbsEquality(self, target, expr):
+        """Adds `target == Abs(var)`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.lin_max.exprs.append(self.ParseLinearExpression(expr))
+        model_ct.lin_max.exprs.append(self.ParseLinearExpression(expr, True))
+        model_ct.lin_max.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+ +
+ +

Adds target == Abs(var).

+
+ + +
+
+
#   + + + def + AddModuloEquality(self, target, var, mod): +
+ +
+ View Source +
    def AddModuloEquality(self, target, var, mod):
+        """Adds `target = var % mod`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.int_mod.exprs.append(self.ParseLinearExpression(var))
+        model_ct.int_mod.exprs.append(self.ParseLinearExpression(mod))
+        model_ct.int_mod.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+ +
+ +

Adds target = var % mod.

+
+ + +
+
+
#   + + + def + AddMultiplicationEquality(self, target, *expressions): +
+ +
+ View Source +
    def AddMultiplicationEquality(self, target, *expressions):
+        """Adds `target == expressions[0] * .. * expressions[n]`."""
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.int_prod.exprs.extend([
+            self.ParseLinearExpression(expr)
+            for expr in ExpandGeneratorOrTuple(expressions)
+        ])
+        model_ct.int_prod.target.CopyFrom(self.ParseLinearExpression(target))
+        return ct
+
+ +
+ +

Adds target == expressions[0] * .. * expressions[n].

+
+ + +
+
+
#   + + + def + NewIntervalVar(self, start, size, end, name): +
+ +
+ View Source +
    def NewIntervalVar(self, start, size, end, name):
+        """Creates an interval variable from start, size, and end.
+
+    An interval variable is a constraint, that is itself used in other
+    constraints like NoOverlap.
+
+    Internally, it ensures that `start + size == end`.
+
+    Args:
+      start: The start of the interval. It can be an affine or constant
+        expression.
+      size: The size of the interval. It can be an affine or constant
+        expression.
+      end: The end of the interval. It can be an affine or constant expression.
+      name: The name of the interval variable.
+
+    Returns:
+      An `IntervalVar` object.
+    """
+
+        self.Add(start + size == end)
+
+        start_expr = self.ParseLinearExpression(start)
+        size_expr = self.ParseLinearExpression(size)
+        end_expr = self.ParseLinearExpression(end)
+        if len(start_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: start must be affine or constant.')
+        if len(size_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: size must be affine or constant.')
+        if len(end_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: end must be affine or constant.')
+        return IntervalVar(self.__model, start_expr, size_expr, end_expr, None,
+                           name)
+
+ +
+ +

Creates an interval variable from start, size, and end.

+ +

An interval variable is a constraint, that is itself used in other +constraints like NoOverlap.

+ +

Internally, it ensures that start + size == end.

+ +
Args
+ +
    +
  • start: The start of the interval. It can be an affine or constant +expression.
  • +
  • size: The size of the interval. It can be an affine or constant +expression.
  • +
  • end: The end of the interval. It can be an affine or constant expression.
  • +
  • name: The name of the interval variable.
  • +
+ +
Returns
+ +
+

An IntervalVar object.

+
+
+ + +
+
+
#   + + + def + NewFixedSizeIntervalVar(self, start, size, name): +
+ +
+ View Source +
    def NewFixedSizeIntervalVar(self, start, size, name):
+        """Creates an interval variable from start, and a fixed size.
+
+    An interval variable is a constraint, that is itself used in other
+    constraints like NoOverlap.
+
+    Args:
+      start: The start of the interval. It can be an affine or constant
+        expression.
+      size: The size of the interval. It must be an integer value.
+      name: The name of the interval variable.
+
+    Returns:
+      An `IntervalVar` object.
+    """
+        size = cmh.assert_is_int64(size)
+        start_expr = self.ParseLinearExpression(start)
+        size_expr = self.ParseLinearExpression(size)
+        end_expr = self.ParseLinearExpression(start + size)
+        if len(start_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: start must be affine or constant.')
+        return IntervalVar(self.__model, start_expr, size_expr, end_expr, None,
+                           name)
+
+ +
+ +

Creates an interval variable from start, and a fixed size.

+ +

An interval variable is a constraint, that is itself used in other +constraints like NoOverlap.

+ +
Args
+ +
    +
  • start: The start of the interval. It can be an affine or constant +expression.
  • +
  • size: The size of the interval. It must be an integer value.
  • +
  • name: The name of the interval variable.
  • +
+ +
Returns
+ +
+

An IntervalVar object.

+
+
+ + +
+
+
#   + + + def + NewOptionalIntervalVar(self, start, size, end, is_present, name): +
+ +
+ View Source +
    def NewOptionalIntervalVar(self, start, size, end, is_present, name):
+        """Creates an optional interval var from start, size, end, and is_present.
+
+    An optional interval variable is a constraint, that is itself used in other
+    constraints like NoOverlap. This constraint is protected by an is_present
+    literal that indicates if it is active or not.
+
+    Internally, it ensures that `is_present` implies `start + size == end`.
+
+    Args:
+      start: The start of the interval. It can be an integer value, or an
+        integer variable.
+      size: The size of the interval. It can be an integer value, or an integer
+        variable.
+      end: The end of the interval. It can be an integer value, or an integer
+        variable.
+      is_present: A literal that indicates if the interval is active or not. A
+        inactive interval is simply ignored by all constraints.
+      name: The name of the interval variable.
+
+    Returns:
+      An `IntervalVar` object.
+    """
+
+        # Add the linear constraint.
+        self.Add(start + size == end).OnlyEnforceIf(is_present)
+
+        # Creates the IntervalConstraintProto object.
+        is_present_index = self.GetOrMakeBooleanIndex(is_present)
+        start_expr = self.ParseLinearExpression(start)
+        size_expr = self.ParseLinearExpression(size)
+        end_expr = self.ParseLinearExpression(end)
+        if len(start_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: start must be affine or constant.')
+        if len(size_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: size must be affine or constant.')
+        if len(end_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: end must be affine or constant.')
+        return IntervalVar(self.__model, start_expr, size_expr, end_expr,
+                           is_present_index, name)
+
+ +
+ +

Creates an optional interval var from start, size, end, and is_present.

+ +

An optional interval variable is a constraint, that is itself used in other +constraints like NoOverlap. This constraint is protected by an is_present +literal that indicates if it is active or not.

+ +

Internally, it ensures that is_present implies start + size == end.

+ +
Args
+ +
    +
  • start: The start of the interval. It can be an integer value, or an +integer variable.
  • +
  • size: The size of the interval. It can be an integer value, or an integer +variable.
  • +
  • end: The end of the interval. It can be an integer value, or an integer +variable.
  • +
  • is_present: A literal that indicates if the interval is active or not. A +inactive interval is simply ignored by all constraints.
  • +
  • name: The name of the interval variable.
  • +
+ +
Returns
+ +
+

An IntervalVar object.

+
+
+ + +
+
+
#   + + + def + NewOptionalFixedSizeIntervalVar(self, start, size, is_present, name): +
+ +
+ View Source +
    def NewOptionalFixedSizeIntervalVar(self, start, size, is_present, name):
+        """Creates an interval variable from start, and a fixed size.
+
+    An interval variable is a constraint, that is itself used in other
+    constraints like NoOverlap.
+
+    Args:
+      start: The start of the interval. It can be an affine or constant
+        expression.
+      size: The size of the interval. It must be an integer value.
+      is_present: A literal that indicates if the interval is active or not. A
+        inactive interval is simply ignored by all constraints.
+      name: The name of the interval variable.
+
+    Returns:
+      An `IntervalVar` object.
+    """
+        size = cmh.assert_is_int64(size)
+        start_expr = self.ParseLinearExpression(start)
+        size_expr = self.ParseLinearExpression(size)
+        end_expr = self.ParseLinearExpression(start + size)
+        if len(start_expr.vars) > 1:
+            raise TypeError(
+                'cp_model.NewIntervalVar: start must be affine or constant.')
+        is_present_index = self.GetOrMakeBooleanIndex(is_present)
+        return IntervalVar(self.__model, start_expr, size_expr, end_expr,
+                           is_present_index, name)
+
+ +
+ +

Creates an interval variable from start, and a fixed size.

+ +

An interval variable is a constraint, that is itself used in other +constraints like NoOverlap.

+ +
Args
+ +
    +
  • start: The start of the interval. It can be an affine or constant +expression.
  • +
  • size: The size of the interval. It must be an integer value.
  • +
  • is_present: A literal that indicates if the interval is active or not. A +inactive interval is simply ignored by all constraints.
  • +
  • name: The name of the interval variable.
  • +
+ +
Returns
+ +
+

An IntervalVar object.

+
+
+ + +
+
+
#   + + + def + AddNoOverlap(self, interval_vars): +
+ +
+ View Source +
    def AddNoOverlap(self, interval_vars):
+        """Adds NoOverlap(interval_vars).
+
+    A NoOverlap constraint ensures that all present intervals do not overlap
+    in time.
+
+    Args:
+      interval_vars: The list of interval variables to constrain.
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.no_overlap.intervals.extend(
+            [self.GetIntervalIndex(x) for x in interval_vars])
+        return ct
+
+ +
+ +

Adds NoOverlap(interval_vars).

+ +

A NoOverlap constraint ensures that all present intervals do not overlap +in time.

+ +
Args
+ +
    +
  • interval_vars: The list of interval variables to constrain.
  • +
+ +
Returns
+ +
+

An instance of the Constraint class.

+
+
+ + +
+
+
#   + + + def + AddNoOverlap2D(self, x_intervals, y_intervals): +
+ +
+ View Source +
    def AddNoOverlap2D(self, x_intervals, y_intervals):
+        """Adds NoOverlap2D(x_intervals, y_intervals).
+
+    A NoOverlap2D constraint ensures that all present rectangles do not overlap
+    on a plane. Each rectangle is aligned with the X and Y axis, and is defined
+    by two intervals which represent its projection onto the X and Y axis.
+
+    Furthermore, one box is optional if at least one of the x or y interval is
+    optional.
+
+    Args:
+      x_intervals: The X coordinates of the rectangles.
+      y_intervals: The Y coordinates of the rectangles.
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.no_overlap_2d.x_intervals.extend(
+            [self.GetIntervalIndex(x) for x in x_intervals])
+        model_ct.no_overlap_2d.y_intervals.extend(
+            [self.GetIntervalIndex(x) for x in y_intervals])
+        return ct
+
+ +
+ +

Adds NoOverlap2D(x_intervals, y_intervals).

+ +

A NoOverlap2D constraint ensures that all present rectangles do not overlap +on a plane. Each rectangle is aligned with the X and Y axis, and is defined +by two intervals which represent its projection onto the X and Y axis.

+ +

Furthermore, one box is optional if at least one of the x or y interval is +optional.

+ +
Args
+ +
    +
  • x_intervals: The X coordinates of the rectangles.
  • +
  • y_intervals: The Y coordinates of the rectangles.
  • +
+ +
Returns
+ +
+

An instance of the Constraint class.

+
+
+ + +
+
+
#   + + + def + AddCumulative(self, intervals, demands, capacity): +
+ +
+ View Source +
    def AddCumulative(self, intervals, demands, capacity):
+        """Adds Cumulative(intervals, demands, capacity).
+
+    This constraint enforces that:
+
+        for all t:
+          sum(demands[i]
+            if (start(intervals[i]) <= t < end(intervals[i])) and
+            (intervals[i] is present)) <= capacity
+
+    Args:
+      intervals: The list of intervals.
+      demands: The list of demands for each interval. Each demand must be >= 0.
+        Each demand can be an integer value, or an integer variable.
+      capacity: The maximum capacity of the cumulative constraint. It must be a
+        positive integer value or variable.
+
+    Returns:
+      An instance of the `Constraint` class.
+    """
+        ct = Constraint(self.__model.constraints)
+        model_ct = self.__model.constraints[ct.Index()]
+        model_ct.cumulative.intervals.extend(
+            [self.GetIntervalIndex(x) for x in intervals])
+        for d in demands:
+            model_ct.cumulative.demands.append(self.ParseLinearExpression(d))
+        model_ct.cumulative.capacity.CopyFrom(
+            self.ParseLinearExpression(capacity))
+        return ct
+
+ +
+ +

Adds Cumulative(intervals, demands, capacity).

+ +
This constraint enforces that
+ +
+

for all t: + sum(demands[i] + if (start(intervals[i]) <= t < end(intervals[i])) and + (intervals[i] is present)) <= capacity

+
+ +
Args
+ +
    +
  • intervals: The list of intervals.
  • +
  • demands: The list of demands for each interval. Each demand must be >= 0. +Each demand can be an integer value, or an integer variable.
  • +
  • capacity: The maximum capacity of the cumulative constraint. It must be a +positive integer value or variable.
  • +
+ +
Returns
+ +
+

An instance of the Constraint class.

+
+
+ + +
+
+
#   + + + def + CopyFrom(self, other_model): +
+ +
+ View Source +
    def CopyFrom(self, other_model):
+        """Reset the model, and creates a new one from a CpModelProto instance."""
+        self.__model.CopyFrom(other_model.Proto())
+
+        # Rebuild constant map.
+        self.__constant_map.clear()
+        for i, var in enumerate(self.__model.variables):
+            if len(var.domain) == 2 and var.domain[0] == var.domain[1]:
+                self.__constant_map[var.domain[0]] = i
+
+ +
+ +

Reset the model, and creates a new one from a CpModelProto instance.

+
+ + +
+
+
#   + + + def + GetBoolVarFromProtoIndex(self, index): +
+ +
+ View Source +
    def GetBoolVarFromProtoIndex(self, index):
+        """Returns an already created Boolean variable from its index."""
+        if index < 0 or index >= len(self.__model.variables):
+            raise ValueError(
+                f'GetBoolVarFromProtoIndex: out of bound index {index}')
+        var = self.__model.variables[index]
+        if len(var.domain) != 2 or var.domain[0] < 0 or var.domain[1] > 1:
+            raise ValueError(
+                f'GetBoolVarFromProtoIndex: index {index} does not reference' +
+                ' a Boolean variable')
+
+        return IntVar(self.__model, index, None)
+
+ +
+ +

Returns an already created Boolean variable from its index.

+
+ + +
+
+
#   + + + def + GetIntVarFromProtoIndex(self, index): +
+ +
+ View Source +
    def GetIntVarFromProtoIndex(self, index):
+        """Returns an already created integer variable from its index."""
+        if index < 0 or index >= len(self.__model.variables):
+            raise ValueError(
+                f'GetIntVarFromProtoIndex: out of bound index {index}')
+        return IntVar(self.__model, index, None)
+
+ +
+ +

Returns an already created integer variable from its index.

+
+ + +
+
+
#   + + + def + GetIntervalVarFromProtoIndex(self, index): +
+ +
+ View Source +
    def GetIntervalVarFromProtoIndex(self, index):
+        """Returns an already created interval variable from its index."""
+        if index < 0 or index >= len(self.__model.constraints):
+            raise ValueError(
+                f'GetIntervalVarFromProtoIndex: out of bound index {index}')
+        ct = self.__model.constraints[index]
+        if not ct.HasField('interval'):
+            raise ValueError(
+                f'GetIntervalVarFromProtoIndex: index {index} does not reference an'
+                + ' interval variable')
+
+        return IntervalVar(self.__model, index, None, None, None, None)
+
+ +
+ +

Returns an already created interval variable from its index.

+
+ + +
+
+
#   + + + def + Proto(self): +
+ +
+ View Source +
    def Proto(self):
+        """Returns the underlying CpModelProto."""
+        return self.__model
+
+ +
+ +

Returns the underlying CpModelProto.

+
+ + +
+
+
#   + + + def + Negated(self, index): +
+ +
+ View Source +
    def Negated(self, index):
+        return -index - 1
+
+ +
+ + + +
+
+
#   + + + def + GetOrMakeIndex(self, arg): +
+ +
+ View Source +
    def GetOrMakeIndex(self, arg):
+        """Returns the index of a variable, its negation, or a number."""
+        if isinstance(arg, IntVar):
+            return arg.Index()
+        elif (isinstance(arg, _ProductCst) and
+              isinstance(arg.Expression(), IntVar) and arg.Coefficient() == -1):
+            return -arg.Expression().Index() - 1
+        elif cmh.is_integral(arg):
+            arg = cmh.assert_is_int64(arg)
+            return self.GetOrMakeIndexFromConstant(arg)
+        else:
+            raise TypeError('NotSupported: model.GetOrMakeIndex(' + str(arg) +
+                            ')')
+
+ +
+ +

Returns the index of a variable, its negation, or a number.

+
+ + +
+
+
#   + + + def + GetOrMakeBooleanIndex(self, arg): +
+ +
+ View Source +
    def GetOrMakeBooleanIndex(self, arg):
+        """Returns an index from a boolean expression."""
+        if isinstance(arg, IntVar):
+            self.AssertIsBooleanVariable(arg)
+            return arg.Index()
+        elif isinstance(arg, _NotBooleanVariable):
+            self.AssertIsBooleanVariable(arg.Not())
+            return arg.Index()
+        elif cmh.is_integral(arg):
+            cmh.assert_is_boolean(arg)
+            return self.GetOrMakeIndexFromConstant(int(arg))
+        else:
+            raise TypeError('NotSupported: model.GetOrMakeBooleanIndex(' +
+                            str(arg) + ')')
+
+ +
+ +

Returns an index from a boolean expression.

+
+ + +
+
+
#   + + + def + GetIntervalIndex(self, arg): +
+ +
+ View Source +
    def GetIntervalIndex(self, arg):
+        if not isinstance(arg, IntervalVar):
+            raise TypeError('NotSupported: model.GetIntervalIndex(%s)' % arg)
+        return arg.Index()
+
+ +
+ + + +
+
+
#   + + + def + GetOrMakeIndexFromConstant(self, value): +
+ +
+ View Source +
    def GetOrMakeIndexFromConstant(self, value):
+        if value in self.__constant_map:
+            return self.__constant_map[value]
+        index = len(self.__model.variables)
+        var = self.__model.variables.add()
+        var.domain.extend([value, value])
+        self.__constant_map[value] = index
+        return index
+
+ +
+ + + +
+
+
#   + + + def + VarIndexToVarProto(self, var_index): +
+ +
+ View Source +
    def VarIndexToVarProto(self, var_index):
+        if var_index >= 0:
+            return self.__model.variables[var_index]
+        else:
+            return self.__model.variables[-var_index - 1]
+
+ +
+ + + +
+
+
#   + + + def + ParseLinearExpression(self, linear_expr, negate=False): +
+ +
+ View Source +
    def ParseLinearExpression(self, linear_expr, negate=False):
+        """Returns a LinearExpressionProto built from a LinearExpr instance."""
+        result = cp_model_pb2.LinearExpressionProto()
+        mult = -1 if negate else 1
+        if cmh.is_integral(linear_expr):
+            result.offset = int(linear_expr) * mult
+            return result
+
+        if isinstance(linear_expr, IntVar):
+            result.vars.append(self.GetOrMakeIndex(linear_expr))
+            result.coeffs.append(mult)
+            return result
+
+        coeffs_map, constant = linear_expr.GetIntegerVarValueMap()
+        result.offset = constant * mult
+        for t in coeffs_map.items():
+            if not isinstance(t[0], IntVar):
+                raise TypeError('Wrong argument' + str(t))
+            c = cmh.assert_is_int64(t[1])
+            result.vars.append(t[0].Index())
+            result.coeffs.append(c * mult)
+        return result
+
+ +
+ +

Returns a LinearExpressionProto built from a LinearExpr instance.

+
+ + +
+
+
#   + + + def + Minimize(self, obj): +
+ +
+ View Source +
    def Minimize(self, obj):
+        """Sets the objective of the model to minimize(obj)."""
+        self._SetObjective(obj, minimize=True)
+
+ +
+ +

Sets the objective of the model to minimize(obj).

+
+ + +
+
+
#   + + + def + Maximize(self, obj): +
+ +
+ View Source +
    def Maximize(self, obj):
+        """Sets the objective of the model to maximize(obj)."""
+        self._SetObjective(obj, minimize=False)
+
+ +
+ +

Sets the objective of the model to maximize(obj).

+
+ + +
+
+
#   + + + def + HasObjective(self): +
+ +
+ View Source +
    def HasObjective(self):
+        return self.__model.HasField('objective')
+
+ +
+ + + +
+
+
#   + + + def + AddDecisionStrategy(self, variables, var_strategy, domain_strategy): +
+ +
+ View Source +
    def AddDecisionStrategy(self, variables, var_strategy, domain_strategy):
+        """Adds a search strategy to the model.
+
+    Args:
+      variables: a list of variables this strategy will assign.
+      var_strategy: heuristic to choose the next variable to assign.
+      domain_strategy: heuristic to reduce the domain of the selected variable.
+        Currently, this is advanced code: the union of all strategies added to
+          the model must be complete, i.e. instantiates all variables.
+          Otherwise, Solve() will fail.
+    """
+
+        strategy = self.__model.search_strategy.add()
+        for v in variables:
+            strategy.variables.append(v.Index())
+        strategy.variable_selection_strategy = var_strategy
+        strategy.domain_reduction_strategy = domain_strategy
+
+ +
+ +

Adds a search strategy to the model.

+ +
Args
+ +
    +
  • variables: a list of variables this strategy will assign.
  • +
  • var_strategy: heuristic to choose the next variable to assign.
  • +
  • domain_strategy: heuristic to reduce the domain of the selected variable. +Currently, this is advanced code: the union of all strategies added to + the model must be complete, i.e. instantiates all variables. + Otherwise, Solve() will fail.
  • +
+
+ + +
+
+
#   + + + def + ModelStats(self): +
+ +
+ View Source +
    def ModelStats(self):
+        """Returns a string containing some model statistics."""
+        return swig_helper.CpSatHelper.SerializedModelStats(
+            self.__model.SerializeToString())
+
+ +
+ +

Returns a string containing some model statistics.

+
+ + +
+
+
#   + + + def + Validate(self): +
+ +
+ View Source +
    def Validate(self):
+        """Returns a string indicating that the model is invalid."""
+        return swig_helper.CpSatHelper.SerializedValidateModel(
+            self.__model.SerializeToString())
+
+ +
+ +

Returns a string indicating that the model is invalid.

+
+ + +
+
+
#   + + + def + ExportToFile(self, file): +
+ +
+ View Source +
    def ExportToFile(self, file):
+        """Write the model as a protocol buffer to 'file'.
+
+    Args:
+      file: file to write the model to. If the filename ends with 'txt', the
+        model will be written as a text file, otherwise, the binary format will
+        be used.
+
+    Returns:
+      True if the model was correctly written.
+    """
+        return swig_helper.CpSatHelper.SerializedWriteModelToFile(
+            self.__model.SerializeToString(), file)
+
+ +
+ +

Write the model as a protocol buffer to 'file'.

+ +
Args
+ +
    +
  • file: file to write the model to. If the filename ends with 'txt', the +model will be written as a text file, otherwise, the binary format will +be used.
  • +
+ +
Returns
+ +
+

True if the model was correctly written.

+
+
+ + +
+
+
#   + + + def + AssertIsBooleanVariable(self, x): +
+ +
+ View Source +
    def AssertIsBooleanVariable(self, x):
+        if isinstance(x, IntVar):
+            var = self.__model.variables[x.Index()]
+            if len(var.domain) != 2 or var.domain[0] < 0 or var.domain[1] > 1:
+                raise TypeError('TypeError: ' + str(x) +
+                                ' is not a boolean variable')
+        elif not isinstance(x, _NotBooleanVariable):
+            raise TypeError('TypeError: ' + str(x) +
+                            ' is not a boolean variable')
+
+ +
+ + + +
+
+
#   + + + def + AddHint(self, var, value): +
+ +
+ View Source +
    def AddHint(self, var, value):
+        """Adds 'var == value' as a hint to the solver."""
+        self.__model.solution_hint.vars.append(self.GetOrMakeIndex(var))
+        self.__model.solution_hint.values.append(value)
+
+ +
+ +

Adds 'var == value' as a hint to the solver.

+
+ + +
+
+
#   + + + def + ClearHints(self): +
+ +
+ View Source +
    def ClearHints(self):
+        """Remove any solution hint from the model."""
+        self.__model.ClearField('solution_hint')
+
+ +
+ +

Remove any solution hint from the model.

+
+ + +
+
+
#   + + + def + AddAssumption(self, lit): +
+ +
+ View Source +
    def AddAssumption(self, lit):
+        """Add the literal 'lit' to the model as assumptions."""
+        self.__model.assumptions.append(self.GetOrMakeBooleanIndex(lit))
+
+ +
+ +

Add the literal 'lit' to the model as assumptions.

+
+ + +
+
+
#   + + + def + AddAssumptions(self, literals): +
+ +
+ View Source +
    def AddAssumptions(self, literals):
+        """Add the literals to the model as assumptions."""
+        for lit in literals:
+            self.AddAssumption(lit)
+
+ +
+ +

Add the literals to the model as assumptions.

+
+ + +
+
+
#   + + + def + ClearAssumptions(self): +
+ +
+ View Source +
    def ClearAssumptions(self):
+        """Remove all assumptions from the model."""
+        self.__model.ClearField('assumptions')
+
+ +
+ +

Remove all assumptions from the model.

+
+ + +
+
+
+
#   + + + def + ExpandGeneratorOrTuple(args): +
+ +
+ View Source +
def ExpandGeneratorOrTuple(args):
+    if hasattr(args, '__len__'):  # Tuple
+        if len(args) != 1:
+            return args
+        if cmh.is_a_number(args[0]) or isinstance(args[0], LinearExpr):
+            return args
+    # Generator
+    return args[0]
+
+ +
+ + + +
+
+
#   + + + def + EvaluateLinearExpr(expression, solution): +
+ +
+ View Source +
def EvaluateLinearExpr(expression, solution):
+    """Evaluate a linear expression against a solution."""
+    if cmh.is_integral(expression):
+        return int(expression)
+    if not isinstance(expression, LinearExpr):
+        raise TypeError('Cannot interpret %s as a linear expression.' %
+                        expression)
+
+    value = 0
+    to_process = [(expression, 1)]
+    while to_process:
+        expr, coeff = to_process.pop()
+        if cmh.is_integral(expr):
+            value += int(expr) * coeff
+        elif isinstance(expr, _ProductCst):
+            to_process.append((expr.Expression(), coeff * expr.Coefficient()))
+        elif isinstance(expr, _Sum):
+            to_process.append((expr.Left(), coeff))
+            to_process.append((expr.Right(), coeff))
+        elif isinstance(expr, _SumArray):
+            for e in expr.Expressions():
+                to_process.append((e, coeff))
+            value += expr.Constant() * coeff
+        elif isinstance(expr, _WeightedSum):
+            for e, c in zip(expr.Expressions(), expr.Coefficients()):
+                to_process.append((e, coeff * c))
+            value += expr.Constant() * coeff
+        elif isinstance(expr, IntVar):
+            value += coeff * solution.solution[expr.Index()]
+        elif isinstance(expr, _NotBooleanVariable):
+            value += coeff * (1 - solution.solution[expr.Not().Index()])
+        else:
+            raise TypeError(f'Cannot interpret {expr} as a linear expression.')
+
+    return value
+
+ +
+ +

Evaluate a linear expression against a solution.

+
+ + +
+
+
#   + + + def + EvaluateBooleanExpression(literal, solution): +
+ +
+ View Source +
def EvaluateBooleanExpression(literal, solution):
+    """Evaluate a boolean expression against a solution."""
+    if cmh.is_integral(literal):
+        return bool(literal)
+    elif isinstance(literal, IntVar) or isinstance(literal,
+                                                   _NotBooleanVariable):
+        index = literal.Index()
+        if index >= 0:
+            return bool(solution.solution[index])
+        else:
+            return not solution.solution[-index - 1]
+    else:
+        raise TypeError(f'Cannot interpret {literal} as a boolean expression.')
+
+ +
+ +

Evaluate a boolean expression against a solution.

+
+ + +
+
+
+ #   + + + class + CpSolver: +
+ +
+ View Source +
class CpSolver(object):
+    """Main solver class.
+
+  The purpose of this class is to search for a solution to the model provided
+  to the Solve() method.
+
+  Once Solve() is called, this class allows inspecting the solution found
+  with the Value() and BooleanValue() methods, as well as general statistics
+  about the solve procedure.
+  """
+
+    def __init__(self):
+        self.__model = None
+        self.__solution: cp_model_pb2.CpSolverResponse = None
+        self.parameters = sat_parameters_pb2.SatParameters()
+        self.log_callback = None
+        self.__solve_wrapper: swig_helper.SolveWrapper = None
+        self.__lock = threading.Lock()
+
+    def Solve(self, model, solution_callback=None):
+        """Solves a problem and passes each solution to the callback if not null."""
+        with self.__lock:
+            solve_wrapper = swig_helper.SolveWrapper()
+
+        swig_helper.SolveWrapper.SetSerializedParameters(
+            self.parameters.SerializeToString(), solve_wrapper)
+        if solution_callback is not None:
+            solve_wrapper.AddSolutionCallback(solution_callback)
+
+        if self.log_callback is not None:
+            solve_wrapper.AddLogCallback(self.log_callback)
+
+        self.__solution = cp_model_pb2.CpSolverResponse.FromString(
+            swig_helper.SolveWrapper.SerializedSolve(
+                model.Proto().SerializeToString(), solve_wrapper))
+
+        if solution_callback is not None:
+            solve_wrapper.ClearSolutionCallback(solution_callback)
+
+        with self.__lock:
+            self.__solve_wrapper = None
+
+        return self.__solution.status
+
+    def SolveWithSolutionCallback(self, model, callback):
+        """DEPRECATED Use Solve() with the callback argument."""
+        warnings.warn(
+            'SolveWithSolutionCallback is deprecated; use Solve() with' +
+            'the callback argument.', DeprecationWarning)
+        return self.Solve(model, callback)
+
+    def SearchForAllSolutions(self, model, callback):
+        """DEPRECATED Use Solve() with the right parameter.
+
+    Search for all solutions of a satisfiability problem.
+
+    This method searches for all feasible solutions of a given model.
+    Then it feeds the solution to the callback.
+
+    Note that the model cannot contain an objective.
+
+    Args:
+      model: The model to solve.
+      callback: The callback that will be called at each solution.
+
+    Returns:
+      The status of the solve:
+
+      * *FEASIBLE* if some solutions have been found
+      * *INFEASIBLE* if the solver has proved there are no solution
+      * *OPTIMAL* if all solutions have been found
+    """
+        warnings.warn(
+            'SearchForAllSolutions is deprecated; use Solve() with' +
+            'enumerate_all_solutions = True.', DeprecationWarning)
+        if model.HasObjective():
+            raise TypeError('Search for all solutions is only defined on '
+                            'satisfiability problems')
+        # Store old parameter.
+        enumerate_all = self.parameters.enumerate_all_solutions
+        self.parameters.enumerate_all_solutions = True
+
+        self.Solve(model, callback)
+
+        # Restore parameter.
+        self.parameters.enumerate_all_solutions = enumerate_all
+        return self.__solution.status
+
+    def StopSearch(self):
+        """Stops the current search asynchronously."""
+        with self.__lock:
+            if self.__solve_wrapper:
+                self.__solve_wrapper.StopSearch()
+
+    def Value(self, expression):
+        """Returns the value of a linear expression after solve."""
+        if not self.__solution:
+            raise RuntimeError('Solve() has not be called.')
+        return EvaluateLinearExpr(expression, self.__solution)
+
+    def BooleanValue(self, literal):
+        """Returns the boolean value of a literal after solve."""
+        if not self.__solution:
+            raise RuntimeError('Solve() has not be called.')
+        return EvaluateBooleanExpression(literal, self.__solution)
+
+    def ObjectiveValue(self):
+        """Returns the value of the objective after solve."""
+        return self.__solution.objective_value
+
+    def BestObjectiveBound(self):
+        """Returns the best lower (upper) bound found when min(max)imizing."""
+        return self.__solution.best_objective_bound
+
+    def StatusName(self, status=None):
+        """Returns the name of the status returned by Solve()."""
+        if status is None:
+            status = self.__solution.status
+        return cp_model_pb2.CpSolverStatus.Name(status)
+
+    def NumBooleans(self):
+        """Returns the number of boolean variables managed by the SAT solver."""
+        return self.__solution.num_booleans
+
+    def NumConflicts(self):
+        """Returns the number of conflicts since the creation of the solver."""
+        return self.__solution.num_conflicts
+
+    def NumBranches(self):
+        """Returns the number of search branches explored by the solver."""
+        return self.__solution.num_branches
+
+    def WallTime(self):
+        """Returns the wall time in seconds since the creation of the solver."""
+        return self.__solution.wall_time
+
+    def UserTime(self):
+        """Returns the user time in seconds since the creation of the solver."""
+        return self.__solution.user_time
+
+    def ResponseStats(self):
+        """Returns some statistics on the solution found as a string."""
+        return swig_helper.CpSatHelper.SerializedSolverResponseStats(
+            self.__solution.SerializeToString())
+
+    def ResponseProto(self):
+        """Returns the response object."""
+        return self.__solution
+
+    def SufficientAssumptionsForInfeasibility(self):
+        """Returns the indices of the infeasible assumptions."""
+        return self.__solution.sufficient_assumptions_for_infeasibility
+
+    def SolutionInfo(self):
+        """Returns some information on the solve process.
+
+    Returns some information on how the solution was found, or the reason
+    why the model or the parameters are invalid.
+    """
+        return self.__solution.solution_info
+
+ +
+ +

Main solver class.

+ +

The purpose of this class is to search for a solution to the model provided +to the Solve() method.

+ +

Once Solve() is called, this class allows inspecting the solution found +with the Value() and BooleanValue() methods, as well as general statistics +about the solve procedure.

+
+ + +
+
#   + + + CpSolver() +
+ +
+ View Source +
    def __init__(self):
+        self.__model = None
+        self.__solution: cp_model_pb2.CpSolverResponse = None
+        self.parameters = sat_parameters_pb2.SatParameters()
+        self.log_callback = None
+        self.__solve_wrapper: swig_helper.SolveWrapper = None
+        self.__lock = threading.Lock()
+
+ +
+ + + +
+
+
#   + + + def + Solve(self, model, solution_callback=None): +
+ +
+ View Source +
    def Solve(self, model, solution_callback=None):
+        """Solves a problem and passes each solution to the callback if not null."""
+        with self.__lock:
+            solve_wrapper = swig_helper.SolveWrapper()
+
+        swig_helper.SolveWrapper.SetSerializedParameters(
+            self.parameters.SerializeToString(), solve_wrapper)
+        if solution_callback is not None:
+            solve_wrapper.AddSolutionCallback(solution_callback)
+
+        if self.log_callback is not None:
+            solve_wrapper.AddLogCallback(self.log_callback)
+
+        self.__solution = cp_model_pb2.CpSolverResponse.FromString(
+            swig_helper.SolveWrapper.SerializedSolve(
+                model.Proto().SerializeToString(), solve_wrapper))
+
+        if solution_callback is not None:
+            solve_wrapper.ClearSolutionCallback(solution_callback)
+
+        with self.__lock:
+            self.__solve_wrapper = None
+
+        return self.__solution.status
+
+ +
+ +

Solves a problem and passes each solution to the callback if not null.

+
+ + +
+
+
#   + + + def + SolveWithSolutionCallback(self, model, callback): +
+ +
+ View Source +
    def SolveWithSolutionCallback(self, model, callback):
+        """DEPRECATED Use Solve() with the callback argument."""
+        warnings.warn(
+            'SolveWithSolutionCallback is deprecated; use Solve() with' +
+            'the callback argument.', DeprecationWarning)
+        return self.Solve(model, callback)
+
+ +
+ +

DEPRECATED Use Solve() with the callback argument.

+
+ + +
+
+
#   + + + def + SearchForAllSolutions(self, model, callback): +
+ +
+ View Source +
    def SearchForAllSolutions(self, model, callback):
+        """DEPRECATED Use Solve() with the right parameter.
+
+    Search for all solutions of a satisfiability problem.
+
+    This method searches for all feasible solutions of a given model.
+    Then it feeds the solution to the callback.
+
+    Note that the model cannot contain an objective.
+
+    Args:
+      model: The model to solve.
+      callback: The callback that will be called at each solution.
+
+    Returns:
+      The status of the solve:
+
+      * *FEASIBLE* if some solutions have been found
+      * *INFEASIBLE* if the solver has proved there are no solution
+      * *OPTIMAL* if all solutions have been found
+    """
+        warnings.warn(
+            'SearchForAllSolutions is deprecated; use Solve() with' +
+            'enumerate_all_solutions = True.', DeprecationWarning)
+        if model.HasObjective():
+            raise TypeError('Search for all solutions is only defined on '
+                            'satisfiability problems')
+        # Store old parameter.
+        enumerate_all = self.parameters.enumerate_all_solutions
+        self.parameters.enumerate_all_solutions = True
+
+        self.Solve(model, callback)
+
+        # Restore parameter.
+        self.parameters.enumerate_all_solutions = enumerate_all
+        return self.__solution.status
+
+ +
+ +

DEPRECATED Use Solve() with the right parameter.

+ +

Search for all solutions of a satisfiability problem.

+ +

This method searches for all feasible solutions of a given model. +Then it feeds the solution to the callback.

+ +

Note that the model cannot contain an objective.

+ +
Args
+ +
    +
  • model: The model to solve.
  • +
  • callback: The callback that will be called at each solution.
  • +
+ +
Returns
+ +
+

The status of the solve:

+ +
    +
  • FEASIBLE if some solutions have been found
  • +
  • INFEASIBLE if the solver has proved there are no solution
  • +
  • OPTIMAL if all solutions have been found
  • +
+
+
+ + +
+
+
#   + + + def + StopSearch(self): +
+ +
+ View Source +
    def StopSearch(self):
+        """Stops the current search asynchronously."""
+        with self.__lock:
+            if self.__solve_wrapper:
+                self.__solve_wrapper.StopSearch()
+
+ +
+ +

Stops the current search asynchronously.

+
+ + +
+
+
#   + + + def + Value(self, expression): +
+ +
+ View Source +
    def Value(self, expression):
+        """Returns the value of a linear expression after solve."""
+        if not self.__solution:
+            raise RuntimeError('Solve() has not be called.')
+        return EvaluateLinearExpr(expression, self.__solution)
+
+ +
+ +

Returns the value of a linear expression after solve.

+
+ + +
+
+
#   + + + def + BooleanValue(self, literal): +
+ +
+ View Source +
    def BooleanValue(self, literal):
+        """Returns the boolean value of a literal after solve."""
+        if not self.__solution:
+            raise RuntimeError('Solve() has not be called.')
+        return EvaluateBooleanExpression(literal, self.__solution)
+
+ +
+ +

Returns the boolean value of a literal after solve.

+
+ + +
+
+
#   + + + def + ObjectiveValue(self): +
+ +
+ View Source +
    def ObjectiveValue(self):
+        """Returns the value of the objective after solve."""
+        return self.__solution.objective_value
+
+ +
+ +

Returns the value of the objective after solve.

+
+ + +
+
+
#   + + + def + BestObjectiveBound(self): +
+ +
+ View Source +
    def BestObjectiveBound(self):
+        """Returns the best lower (upper) bound found when min(max)imizing."""
+        return self.__solution.best_objective_bound
+
+ +
+ +

Returns the best lower (upper) bound found when min(max)imizing.

+
+ + +
+
+
#   + + + def + StatusName(self, status=None): +
+ +
+ View Source +
    def StatusName(self, status=None):
+        """Returns the name of the status returned by Solve()."""
+        if status is None:
+            status = self.__solution.status
+        return cp_model_pb2.CpSolverStatus.Name(status)
+
+ +
+ +

Returns the name of the status returned by Solve().

+
+ + +
+
+
#   + + + def + NumBooleans(self): +
+ +
+ View Source +
    def NumBooleans(self):
+        """Returns the number of boolean variables managed by the SAT solver."""
+        return self.__solution.num_booleans
+
+ +
+ +

Returns the number of boolean variables managed by the SAT solver.

+
+ + +
+
+
#   + + + def + NumConflicts(self): +
+ +
+ View Source +
    def NumConflicts(self):
+        """Returns the number of conflicts since the creation of the solver."""
+        return self.__solution.num_conflicts
+
+ +
+ +

Returns the number of conflicts since the creation of the solver.

+
+ + +
+
+
#   + + + def + NumBranches(self): +
+ +
+ View Source +
    def NumBranches(self):
+        """Returns the number of search branches explored by the solver."""
+        return self.__solution.num_branches
+
+ +
+ +

Returns the number of search branches explored by the solver.

+
+ + +
+
+
#   + + + def + WallTime(self): +
+ +
+ View Source +
    def WallTime(self):
+        """Returns the wall time in seconds since the creation of the solver."""
+        return self.__solution.wall_time
+
+ +
+ +

Returns the wall time in seconds since the creation of the solver.

+
+ + +
+
+
#   + + + def + UserTime(self): +
+ +
+ View Source +
    def UserTime(self):
+        """Returns the user time in seconds since the creation of the solver."""
+        return self.__solution.user_time
+
+ +
+ +

Returns the user time in seconds since the creation of the solver.

+
+ + +
+
+
#   + + + def + ResponseStats(self): +
+ +
+ View Source +
    def ResponseStats(self):
+        """Returns some statistics on the solution found as a string."""
+        return swig_helper.CpSatHelper.SerializedSolverResponseStats(
+            self.__solution.SerializeToString())
+
+ +
+ +

Returns some statistics on the solution found as a string.

+
+ + +
+
+
#   + + + def + ResponseProto(self): +
+ +
+ View Source +
    def ResponseProto(self):
+        """Returns the response object."""
+        return self.__solution
+
+ +
+ +

Returns the response object.

+
+ + +
+
+
#   + + + def + SufficientAssumptionsForInfeasibility(self): +
+ +
+ View Source +
    def SufficientAssumptionsForInfeasibility(self):
+        """Returns the indices of the infeasible assumptions."""
+        return self.__solution.sufficient_assumptions_for_infeasibility
+
+ +
+ +

Returns the indices of the infeasible assumptions.

+
+ + +
+
+
#   + + + def + SolutionInfo(self): +
+ +
+ View Source +
    def SolutionInfo(self):
+        """Returns some information on the solve process.
+
+    Returns some information on how the solution was found, or the reason
+    why the model or the parameters are invalid.
+    """
+        return self.__solution.solution_info
+
+ +
+ +

Returns some information on the solve process.

+ +

Returns some information on how the solution was found, or the reason +why the model or the parameters are invalid.

+
+ + +
+
+
+
+ #   + + + class + CpSolverSolutionCallback(ortools.sat.python.swig_helper.SolutionCallback): +
+ +
+ View Source +
class CpSolverSolutionCallback(swig_helper.SolutionCallback):
+    """Solution callback.
+
+  This class implements a callback that will be called at each new solution
+  found during search.
+
+  The method OnSolutionCallback() will be called by the solver, and must be
+  implemented. The current solution can be queried using the BooleanValue()
+  and Value() methods.
+
+  It inherits the following methods from its base class:
+
+  * `ObjectiveValue(self)`
+  * `BestObjectiveBound(self)`
+  * `NumBooleans(self)`
+  * `NumConflicts(self)`
+  * `NumBranches(self)`
+  * `WallTime(self)`
+  * `UserTime(self)`
+
+  These methods returns the same information as their counterpart in the
+  `CpSolver` class.
+  """
+
+    def __init__(self):
+        swig_helper.SolutionCallback.__init__(self)
+
+    def OnSolutionCallback(self):
+        """Proxy for the same method in snake case."""
+        self.on_solution_callback()
+
+    def BooleanValue(self, lit):
+        """Returns the boolean value of a boolean literal.
+
+    Args:
+        lit: A boolean variable or its negation.
+
+    Returns:
+        The Boolean value of the literal in the solution.
+
+    Raises:
+        RuntimeError: if `lit` is not a boolean variable or its negation.
+    """
+        if not self.HasResponse():
+            raise RuntimeError('Solve() has not be called.')
+        if cmh.is_integral(lit):
+            return bool(lit)
+        elif isinstance(lit, IntVar) or isinstance(lit, _NotBooleanVariable):
+            index = lit.Index()
+            return self.SolutionBooleanValue(index)
+        else:
+            raise TypeError(f'Cannot interpret {lit} as a boolean expression.')
+
+    def Value(self, expression):
+        """Evaluates an linear expression in the current solution.
+
+    Args:
+        expression: a linear expression of the model.
+
+    Returns:
+        An integer value equal to the evaluation of the linear expression
+        against the current solution.
+
+    Raises:
+        RuntimeError: if 'expression' is not a LinearExpr.
+    """
+        if not self.HasResponse():
+            raise RuntimeError('Solve() has not be called.')
+
+        value = 0
+        to_process = [(expression, 1)]
+        while to_process:
+            expr, coeff = to_process.pop()
+            if cmh.is_integral(expr):
+                value += int(expr) * coeff
+            elif isinstance(expr, _ProductCst):
+                to_process.append(
+                    (expr.Expression(), coeff * expr.Coefficient()))
+            elif isinstance(expr, _Sum):
+                to_process.append((expr.Left(), coeff))
+                to_process.append((expr.Right(), coeff))
+            elif isinstance(expr, _SumArray):
+                for e in expr.Expressions():
+                    to_process.append((e, coeff))
+                    value += expr.Constant() * coeff
+            elif isinstance(expr, _WeightedSum):
+                for e, c in zip(expr.Expressions(), expr.Coefficients()):
+                    to_process.append((e, coeff * c))
+                value += expr.Constant() * coeff
+            elif isinstance(expr, IntVar):
+                value += coeff * self.SolutionIntegerValue(expr.Index())
+            elif isinstance(expr, _NotBooleanVariable):
+                value += coeff * (1 -
+                                  self.SolutionIntegerValue(expr.Not().Index()))
+            else:
+                raise TypeError(
+                    f'Cannot interpret {expression} as a linear expression.')
+
+        return value
+
+    def Response(self):
+        """Returns the current solution response."""
+        return cp_model_pb2.CpSolverResponse.FromString(
+            swig_helper.SolutionCallback.SerializedResponse(self))
+
+ +
+ +

Solution callback.

+ +

This class implements a callback that will be called at each new solution +found during search.

+ +

The method OnSolutionCallback() will be called by the solver, and must be +implemented. The current solution can be queried using the BooleanValue() +and Value() methods.

+ +

It inherits the following methods from its base class:

+ +
    +
  • ObjectiveValue(self)
  • +
  • BestObjectiveBound(self)
  • +
  • NumBooleans(self)
  • +
  • NumConflicts(self)
  • +
  • NumBranches(self)
  • +
  • WallTime(self)
  • +
  • UserTime(self)
  • +
+ +

These methods returns the same information as their counterpart in the +CpSolver class.

+
+ + +
+
#   + + + CpSolverSolutionCallback() +
+ +
+ View Source +
    def __init__(self):
+        swig_helper.SolutionCallback.__init__(self)
+
+ +
+ +

__init__(self: ortools.sat.python.swig_helper.SolutionCallback) -> None

+
+ + +
+
+
#   + + + def + OnSolutionCallback(self): +
+ +
+ View Source +
    def OnSolutionCallback(self):
+        """Proxy for the same method in snake case."""
+        self.on_solution_callback()
+
+ +
+ +

Proxy for the same method in snake case.

+
+ + +
+
+
#   + + + def + BooleanValue(self, lit): +
+ +
+ View Source +
    def BooleanValue(self, lit):
+        """Returns the boolean value of a boolean literal.
+
+    Args:
+        lit: A boolean variable or its negation.
+
+    Returns:
+        The Boolean value of the literal in the solution.
+
+    Raises:
+        RuntimeError: if `lit` is not a boolean variable or its negation.
+    """
+        if not self.HasResponse():
+            raise RuntimeError('Solve() has not be called.')
+        if cmh.is_integral(lit):
+            return bool(lit)
+        elif isinstance(lit, IntVar) or isinstance(lit, _NotBooleanVariable):
+            index = lit.Index()
+            return self.SolutionBooleanValue(index)
+        else:
+            raise TypeError(f'Cannot interpret {lit} as a boolean expression.')
+
+ +
+ +

Returns the boolean value of a boolean literal.

+ +
Args
+ +
    +
  • lit: A boolean variable or its negation.
  • +
+ +
Returns
+ +
+

The Boolean value of the literal in the solution.

+
+ +
Raises
+ +
    +
  • RuntimeError: if lit is not a boolean variable or its negation.
  • +
+
+ + +
+
+
#   + + + def + Value(self, expression): +
+ +
+ View Source +
    def Value(self, expression):
+        """Evaluates an linear expression in the current solution.
+
+    Args:
+        expression: a linear expression of the model.
+
+    Returns:
+        An integer value equal to the evaluation of the linear expression
+        against the current solution.
+
+    Raises:
+        RuntimeError: if 'expression' is not a LinearExpr.
+    """
+        if not self.HasResponse():
+            raise RuntimeError('Solve() has not be called.')
+
+        value = 0
+        to_process = [(expression, 1)]
+        while to_process:
+            expr, coeff = to_process.pop()
+            if cmh.is_integral(expr):
+                value += int(expr) * coeff
+            elif isinstance(expr, _ProductCst):
+                to_process.append(
+                    (expr.Expression(), coeff * expr.Coefficient()))
+            elif isinstance(expr, _Sum):
+                to_process.append((expr.Left(), coeff))
+                to_process.append((expr.Right(), coeff))
+            elif isinstance(expr, _SumArray):
+                for e in expr.Expressions():
+                    to_process.append((e, coeff))
+                    value += expr.Constant() * coeff
+            elif isinstance(expr, _WeightedSum):
+                for e, c in zip(expr.Expressions(), expr.Coefficients()):
+                    to_process.append((e, coeff * c))
+                value += expr.Constant() * coeff
+            elif isinstance(expr, IntVar):
+                value += coeff * self.SolutionIntegerValue(expr.Index())
+            elif isinstance(expr, _NotBooleanVariable):
+                value += coeff * (1 -
+                                  self.SolutionIntegerValue(expr.Not().Index()))
+            else:
+                raise TypeError(
+                    f'Cannot interpret {expression} as a linear expression.')
+
+        return value
+
+ +
+ +

Evaluates an linear expression in the current solution.

+ +
Args
+ +
    +
  • expression: a linear expression of the model.
  • +
+ +
Returns
+ +
+

An integer value equal to the evaluation of the linear expression + against the current solution.

+
+ +
Raises
+ +
    +
  • RuntimeError: if 'expression' is not a LinearExpr.
  • +
+
+ + +
+
+
#   + + + def + Response(self): +
+ +
+ View Source +
    def Response(self):
+        """Returns the current solution response."""
+        return cp_model_pb2.CpSolverResponse.FromString(
+            swig_helper.SolutionCallback.SerializedResponse(self))
+
+ +
+ +

Returns the current solution response.

+
+ + +
+
+
Inherited Members
+
+
ortools.sat.python.swig_helper.SolutionCallback
+
BestObjectiveBound
+
DeterministicTime
+
HasResponse
+
NumBinaryPropagations
+
NumBooleans
+
NumBranches
+
NumConflicts
+
NumIntegerPropagations
+
ObjectiveValue
+
SerializedResponse
+
SolutionBooleanValue
+
SolutionIntegerValue
+
StopSearch
+
UserTime
+
WallTime
+ +
+
+
+
+
+
+ #   + + + class + ObjectiveSolutionPrinter(CpSolverSolutionCallback): +
+ +
+ View Source +
class ObjectiveSolutionPrinter(CpSolverSolutionCallback):
+    """Display the objective value and time of intermediate solutions."""
+
+    def __init__(self):
+        CpSolverSolutionCallback.__init__(self)
+        self.__solution_count = 0
+        self.__start_time = time.time()
+
+    def on_solution_callback(self):
+        """Called on each new solution."""
+        current_time = time.time()
+        obj = self.ObjectiveValue()
+        print('Solution %i, time = %0.2f s, objective = %i' %
+              (self.__solution_count, current_time - self.__start_time, obj))
+        self.__solution_count += 1
+
+    def solution_count(self):
+        """Returns the number of solutions found."""
+        return self.__solution_count
+
+ +
+ +

Display the objective value and time of intermediate solutions.

+
+ + +
+
#   + + + ObjectiveSolutionPrinter() +
+ +
+ View Source +
    def __init__(self):
+        CpSolverSolutionCallback.__init__(self)
+        self.__solution_count = 0
+        self.__start_time = time.time()
+
+ +
+ +

__init__(self: ortools.sat.python.swig_helper.SolutionCallback) -> None

+
+ + +
+
+
#   + + + def + on_solution_callback(self): +
+ +
+ View Source +
    def on_solution_callback(self):
+        """Called on each new solution."""
+        current_time = time.time()
+        obj = self.ObjectiveValue()
+        print('Solution %i, time = %0.2f s, objective = %i' %
+              (self.__solution_count, current_time - self.__start_time, obj))
+        self.__solution_count += 1
+
+ +
+ +

Called on each new solution.

+
+ + +
+
+
#   + + + def + solution_count(self): +
+ +
+ View Source +
    def solution_count(self):
+        """Returns the number of solutions found."""
+        return self.__solution_count
+
+ +
+ +

Returns the number of solutions found.

+
+ + +
+
+
Inherited Members
+
+ +
ortools.sat.python.swig_helper.SolutionCallback
+
BestObjectiveBound
+
DeterministicTime
+
HasResponse
+
NumBinaryPropagations
+
NumBooleans
+
NumBranches
+
NumConflicts
+
NumIntegerPropagations
+
ObjectiveValue
+
SerializedResponse
+
SolutionBooleanValue
+
SolutionIntegerValue
+
StopSearch
+
UserTime
+
WallTime
+ +
+
+
+
+
+
+ #   + + + class + VarArrayAndObjectiveSolutionPrinter(CpSolverSolutionCallback): +
+ +
+ View Source +
class VarArrayAndObjectiveSolutionPrinter(CpSolverSolutionCallback):
+    """Print intermediate solutions (objective, variable values, time)."""
+
+    def __init__(self, variables):
+        CpSolverSolutionCallback.__init__(self)
+        self.__variables = variables
+        self.__solution_count = 0
+        self.__start_time = time.time()
+
+    def on_solution_callback(self):
+        """Called on each new solution."""
+        current_time = time.time()
+        obj = self.ObjectiveValue()
+        print('Solution %i, time = %0.2f s, objective = %i' %
+              (self.__solution_count, current_time - self.__start_time, obj))
+        for v in self.__variables:
+            print('  %s = %i' % (v, self.Value(v)), end=' ')
+        print()
+        self.__solution_count += 1
+
+    def solution_count(self):
+        """Returns the number of solutions found."""
+        return self.__solution_count
+
+ +
+ +

Print intermediate solutions (objective, variable values, time).

+
+ + +
+
#   + + + VarArrayAndObjectiveSolutionPrinter(variables) +
+ +
+ View Source +
    def __init__(self, variables):
+        CpSolverSolutionCallback.__init__(self)
+        self.__variables = variables
+        self.__solution_count = 0
+        self.__start_time = time.time()
+
+ +
+ +

__init__(self: ortools.sat.python.swig_helper.SolutionCallback) -> None

+
+ + +
+
+
#   + + + def + on_solution_callback(self): +
+ +
+ View Source +
    def on_solution_callback(self):
+        """Called on each new solution."""
+        current_time = time.time()
+        obj = self.ObjectiveValue()
+        print('Solution %i, time = %0.2f s, objective = %i' %
+              (self.__solution_count, current_time - self.__start_time, obj))
+        for v in self.__variables:
+            print('  %s = %i' % (v, self.Value(v)), end=' ')
+        print()
+        self.__solution_count += 1
+
+ +
+ +

Called on each new solution.

+
+ + +
+
+
#   + + + def + solution_count(self): +
+ +
+ View Source +
    def solution_count(self):
+        """Returns the number of solutions found."""
+        return self.__solution_count
+
+ +
+ +

Returns the number of solutions found.

+
+ + +
+
+
Inherited Members
+
+ +
ortools.sat.python.swig_helper.SolutionCallback
+
BestObjectiveBound
+
DeterministicTime
+
HasResponse
+
NumBinaryPropagations
+
NumBooleans
+
NumBranches
+
NumConflicts
+
NumIntegerPropagations
+
ObjectiveValue
+
SerializedResponse
+
SolutionBooleanValue
+
SolutionIntegerValue
+
StopSearch
+
UserTime
+
WallTime
+ +
+
+
+
+
+
+ #   + + + class + VarArraySolutionPrinter(CpSolverSolutionCallback): +
+ +
+ View Source +
class VarArraySolutionPrinter(CpSolverSolutionCallback):
+    """Print intermediate solutions (variable values, time)."""
+
+    def __init__(self, variables):
+        CpSolverSolutionCallback.__init__(self)
+        self.__variables = variables
+        self.__solution_count = 0
+        self.__start_time = time.time()
+
+    def on_solution_callback(self):
+        """Called on each new solution."""
+        current_time = time.time()
+        print('Solution %i, time = %0.2f s' %
+              (self.__solution_count, current_time - self.__start_time))
+        for v in self.__variables:
+            print('  %s = %i' % (v, self.Value(v)), end=' ')
+        print()
+        self.__solution_count += 1
+
+    def solution_count(self):
+        """Returns the number of solutions found."""
+        return self.__solution_count
+
+ +
+ +

Print intermediate solutions (variable values, time).

+
+ + +
+
#   + + + VarArraySolutionPrinter(variables) +
+ +
+ View Source +
    def __init__(self, variables):
+        CpSolverSolutionCallback.__init__(self)
+        self.__variables = variables
+        self.__solution_count = 0
+        self.__start_time = time.time()
+
+ +
+ +

__init__(self: ortools.sat.python.swig_helper.SolutionCallback) -> None

+
+ + +
+
+
#   + + + def + on_solution_callback(self): +
+ +
+ View Source +
    def on_solution_callback(self):
+        """Called on each new solution."""
+        current_time = time.time()
+        print('Solution %i, time = %0.2f s' %
+              (self.__solution_count, current_time - self.__start_time))
+        for v in self.__variables:
+            print('  %s = %i' % (v, self.Value(v)), end=' ')
+        print()
+        self.__solution_count += 1
+
+ +
+ +

Called on each new solution.

+
+ + +
+
+
#   + + + def + solution_count(self): +
+ +
+ View Source +
    def solution_count(self):
+        """Returns the number of solutions found."""
+        return self.__solution_count
+
+ +
+ +

Returns the number of solutions found.

+
+ + +
+
+
Inherited Members
+
+ +
ortools.sat.python.swig_helper.SolutionCallback
+
BestObjectiveBound
+
DeterministicTime
+
HasResponse
+
NumBinaryPropagations
+
NumBooleans
+
NumBranches
+
NumConflicts
+
NumIntegerPropagations
+
ObjectiveValue
+
SerializedResponse
+
SolutionBooleanValue
+
SolutionIntegerValue
+
StopSearch
+
UserTime
+
WallTime
+ +
+
+
+
+
+ + \ No newline at end of file diff --git a/docs/python/index.html b/docs/python/index.html index 3350c4095c..8ac15aaa3b 100644 --- a/docs/python/index.html +++ b/docs/python/index.html @@ -1,58 +1,7 @@ - + - - - Module List – pdoc 8.0.0 - - - - - - - - + - -
- - pdoc logo - -
-
-
- - \ No newline at end of file + diff --git a/docs/python/ortools/algorithms/index.html b/docs/python/ortools/algorithms/index.html index 21859caaca..05bc993401 100644 --- a/docs/python/ortools/algorithms/index.html +++ b/docs/python/ortools/algorithms/index.html @@ -1,58 +1,7 @@ - + - - - Module List – pdoc 8.0.0 - - - - - - - - + - -
- - pdoc logo - -
-
-
- - \ No newline at end of file + diff --git a/docs/python/ortools/algorithms/ortools/algorithms/pywrapknapsack_solver.html b/docs/python/ortools/algorithms/ortools/algorithms/pywrapknapsack_solver.html new file mode 100644 index 0000000000..dcf8e1cef7 --- /dev/null +++ b/docs/python/ortools/algorithms/ortools/algorithms/pywrapknapsack_solver.html @@ -0,0 +1,849 @@ + + + + + + + ortools.algorithms.pywrapknapsack_solver API documentation + + + + + + + + + +
+
+

+ortools.algorithms.pywrapknapsack_solver

+ + +
+ View Source +
# This file was automatically generated by SWIG (http://www.swig.org).
+# Version 4.0.2
+#
+# Do not make changes to this file unless you know what you are doing--modify
+# the SWIG interface file instead.
+
+from sys import version_info as _swig_python_version_info
+if _swig_python_version_info < (2, 7, 0):
+    raise RuntimeError("Python 2.7 or later required")
+
+# Import the low-level C/C++ module
+if __package__ or "." in __name__:
+    from . import _pywrapknapsack_solver
+else:
+    import _pywrapknapsack_solver
+
+try:
+    import builtins as __builtin__
+except ImportError:
+    import __builtin__
+
+def _swig_repr(self):
+    try:
+        strthis = "proxy of " + self.this.__repr__()
+    except __builtin__.Exception:
+        strthis = ""
+    return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+
+def _swig_setattr_nondynamic_instance_variable(set):
+    def set_instance_attr(self, name, value):
+        if name == "thisown":
+            self.this.own(value)
+        elif name == "this":
+            set(self, name, value)
+        elif hasattr(self, name) and isinstance(getattr(type(self), name), property):
+            set(self, name, value)
+        else:
+            raise AttributeError("You cannot add instance attributes to %s" % self)
+    return set_instance_attr
+
+
+def _swig_setattr_nondynamic_class_variable(set):
+    def set_class_attr(cls, name, value):
+        if hasattr(cls, name) and not isinstance(getattr(cls, name), property):
+            set(cls, name, value)
+        else:
+            raise AttributeError("You cannot add class attributes to %s" % cls)
+    return set_class_attr
+
+
+def _swig_add_metaclass(metaclass):
+    """Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass"""
+    def wrapper(cls):
+        return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy())
+    return wrapper
+
+
+class _SwigNonDynamicMeta(type):
+    """Meta class to enforce nondynamic attributes (no new attributes) for a class"""
+    __setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__)
+
+
+class KnapsackSolver(object):
+    r"""
+     This library solves knapsack problems.
+
+     Problems the library solves include:
+      - 0-1 knapsack problems,
+      - Multi-dimensional knapsack problems,
+
+    Given n items, each with a profit and a weight, given a knapsack of
+    capacity c, the goal is to find a subset of items which fits inside c
+    and maximizes the total profit.
+    The knapsack problem can easily be extended from 1 to d dimensions.
+    As an example, this can be useful to constrain the maximum number of
+    items inside the knapsack.
+    Without loss of generality, profits and weights are assumed to be positive.
+
+    From a mathematical point of view, the multi-dimensional knapsack problem
+    can be modeled by d linear constraints:
+
+        ForEach(j:1..d)(Sum(i:1..n)(weight_ij * item_i) <= c_j
+            where item_i is a 0-1 integer variable.
+
+    Then the goal is to maximize:
+
+        Sum(i:1..n)(profit_i * item_i).
+
+    There are several ways to solve knapsack problems. One of the most
+    efficient is based on dynamic programming (mainly when weights, profits
+    and dimensions are small, and the algorithm runs in pseudo polynomial time).
+    Unfortunately, when adding conflict constraints the problem becomes strongly
+    NP-hard, i.e. there is no pseudo-polynomial algorithm to solve it.
+    That's the reason why the most of the following code is based on branch and
+    bound search.
+
+    For instance to solve a 2-dimensional knapsack problem with 9 items,
+    one just has to feed a profit vector with the 9 profits, a vector of 2
+    vectors for weights, and a vector of capacities.
+    E.g.:
+
+      **Python**:
+
+      .. code-block:: python
+
+              profits = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
+              weights = [ [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
+                          [ 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
+                        ]
+              capacities = [ 34, 4 ]
+
+              solver = pywrapknapsack_solver.KnapsackSolver(
+                  pywrapknapsack_solver.KnapsackSolver
+                      .KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER,
+                  'Multi-dimensional solver')
+              solver.Init(profits, weights, capacities)
+              profit = solver.Solve()
+
+      **C++**:
+
+      .. code-block:: c++
+
+             const std::vector<int64_t> profits = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+             const std::vector<std::vector<int64_t>> weights =
+                 { { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+                   { 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
+             const std::vector<int64_t> capacities = { 34, 4 };
+
+             KnapsackSolver solver(
+                 KnapsackSolver::KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER,
+                 "Multi-dimensional solver");
+             solver.Init(profits, weights, capacities);
+             const int64_t profit = solver.Solve();
+
+      **Java**:
+
+      .. code-block:: java
+
+            final long[] profits = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+            final long[][] weights = { { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+                   { 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
+            final long[] capacities = { 34, 4 };
+
+            KnapsackSolver solver = new KnapsackSolver(
+                KnapsackSolver.SolverType.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER,
+                "Multi-dimensional solver");
+            solver.init(profits, weights, capacities);
+            final long profit = solver.solve();
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+    KNAPSACK_BRUTE_FORCE_SOLVER = _pywrapknapsack_solver.KnapsackSolver_KNAPSACK_BRUTE_FORCE_SOLVER
+    r"""
+     Brute force method.
+
+    Limited to 30 items and one dimension, this
+    solver uses a brute force algorithm, ie. explores all possible states.
+    Experiments show competitive performance for instances with less than
+    15 items.
+    """
+    KNAPSACK_64ITEMS_SOLVER = _pywrapknapsack_solver.KnapsackSolver_KNAPSACK_64ITEMS_SOLVER
+    r"""
+     Optimized method for single dimension small problems
+
+    Limited to 64 items and one dimension, this
+    solver uses a branch & bound algorithm. This solver is about 4 times
+    faster than KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER.
+    """
+    KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER = _pywrapknapsack_solver.KnapsackSolver_KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER
+    r"""
+     Dynamic Programming approach for single dimension problems
+
+    Limited to one dimension, this solver is based on a dynamic programming
+    algorithm. The time and space complexity is O(capacity *
+    number_of_items).
+    """
+    KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER = _pywrapknapsack_solver.KnapsackSolver_KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER
+    r"""
+     CBC Based Solver
+
+     This solver can deal with both large number of items and several
+    dimensions. This solver is based on Integer Programming solver CBC.
+    """
+    KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER = _pywrapknapsack_solver.KnapsackSolver_KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER
+    r"""
+     Generic Solver.
+
+    This solver can deal with both large number of items and several
+    dimensions. This solver is based on branch and bound.
+    """
+    KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER = _pywrapknapsack_solver.KnapsackSolver_KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER
+    r"""
+     SCIP based solver
+
+    This solver can deal with both large number of items and several
+    dimensions. This solver is based on Integer Programming solver SCIP.
+    """
+
+    def __init__(self, *args):
+        _pywrapknapsack_solver.KnapsackSolver_swiginit(self, _pywrapknapsack_solver.new_KnapsackSolver(*args))
+    __swig_destroy__ = _pywrapknapsack_solver.delete_KnapsackSolver
+
+    def Init(self, profits: "std::vector< int64_t > const &", weights: "std::vector< std::vector< int64_t > > const &", capacities: "std::vector< int64_t > const &") -> "void":
+        r"""Initializes the solver and enters the problem to be solved."""
+        return _pywrapknapsack_solver.KnapsackSolver_Init(self, profits, weights, capacities)
+
+    def Solve(self) -> "int64_t":
+        r"""Solves the problem and returns the profit of the optimal solution."""
+        return _pywrapknapsack_solver.KnapsackSolver_Solve(self)
+
+    def BestSolutionContains(self, item_id: "int") -> "bool":
+        r"""Returns true if the item 'item_id' is packed in the optimal knapsack."""
+        return _pywrapknapsack_solver.KnapsackSolver_BestSolutionContains(self, item_id)
+
+    def set_use_reduction(self, use_reduction: "bool") -> "void":
+        return _pywrapknapsack_solver.KnapsackSolver_set_use_reduction(self, use_reduction)
+
+    def set_time_limit(self, time_limit_seconds: "double") -> "void":
+        r"""
+         Time limit in seconds.
+
+        When a finite time limit is set the solution obtained might not be optimal
+        if the limit is reached.
+        """
+        return _pywrapknapsack_solver.KnapsackSolver_set_time_limit(self, time_limit_seconds)
+
+# Register KnapsackSolver in _pywrapknapsack_solver:
+_pywrapknapsack_solver.KnapsackSolver_swigregister(KnapsackSolver)
+
+ +
+ +
+
+
+ #   + + + class + KnapsackSolver: +
+ +
+ View Source +
class KnapsackSolver(object):
+    r"""
+     This library solves knapsack problems.
+
+     Problems the library solves include:
+      - 0-1 knapsack problems,
+      - Multi-dimensional knapsack problems,
+
+    Given n items, each with a profit and a weight, given a knapsack of
+    capacity c, the goal is to find a subset of items which fits inside c
+    and maximizes the total profit.
+    The knapsack problem can easily be extended from 1 to d dimensions.
+    As an example, this can be useful to constrain the maximum number of
+    items inside the knapsack.
+    Without loss of generality, profits and weights are assumed to be positive.
+
+    From a mathematical point of view, the multi-dimensional knapsack problem
+    can be modeled by d linear constraints:
+
+        ForEach(j:1..d)(Sum(i:1..n)(weight_ij * item_i) <= c_j
+            where item_i is a 0-1 integer variable.
+
+    Then the goal is to maximize:
+
+        Sum(i:1..n)(profit_i * item_i).
+
+    There are several ways to solve knapsack problems. One of the most
+    efficient is based on dynamic programming (mainly when weights, profits
+    and dimensions are small, and the algorithm runs in pseudo polynomial time).
+    Unfortunately, when adding conflict constraints the problem becomes strongly
+    NP-hard, i.e. there is no pseudo-polynomial algorithm to solve it.
+    That's the reason why the most of the following code is based on branch and
+    bound search.
+
+    For instance to solve a 2-dimensional knapsack problem with 9 items,
+    one just has to feed a profit vector with the 9 profits, a vector of 2
+    vectors for weights, and a vector of capacities.
+    E.g.:
+
+      **Python**:
+
+      .. code-block:: python
+
+              profits = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
+              weights = [ [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
+                          [ 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
+                        ]
+              capacities = [ 34, 4 ]
+
+              solver = pywrapknapsack_solver.KnapsackSolver(
+                  pywrapknapsack_solver.KnapsackSolver
+                      .KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER,
+                  'Multi-dimensional solver')
+              solver.Init(profits, weights, capacities)
+              profit = solver.Solve()
+
+      **C++**:
+
+      .. code-block:: c++
+
+             const std::vector<int64_t> profits = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+             const std::vector<std::vector<int64_t>> weights =
+                 { { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+                   { 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
+             const std::vector<int64_t> capacities = { 34, 4 };
+
+             KnapsackSolver solver(
+                 KnapsackSolver::KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER,
+                 "Multi-dimensional solver");
+             solver.Init(profits, weights, capacities);
+             const int64_t profit = solver.Solve();
+
+      **Java**:
+
+      .. code-block:: java
+
+            final long[] profits = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+            final long[][] weights = { { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+                   { 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
+            final long[] capacities = { 34, 4 };
+
+            KnapsackSolver solver = new KnapsackSolver(
+                KnapsackSolver.SolverType.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER,
+                "Multi-dimensional solver");
+            solver.init(profits, weights, capacities);
+            final long profit = solver.solve();
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+    KNAPSACK_BRUTE_FORCE_SOLVER = _pywrapknapsack_solver.KnapsackSolver_KNAPSACK_BRUTE_FORCE_SOLVER
+    r"""
+     Brute force method.
+
+    Limited to 30 items and one dimension, this
+    solver uses a brute force algorithm, ie. explores all possible states.
+    Experiments show competitive performance for instances with less than
+    15 items.
+    """
+    KNAPSACK_64ITEMS_SOLVER = _pywrapknapsack_solver.KnapsackSolver_KNAPSACK_64ITEMS_SOLVER
+    r"""
+     Optimized method for single dimension small problems
+
+    Limited to 64 items and one dimension, this
+    solver uses a branch & bound algorithm. This solver is about 4 times
+    faster than KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER.
+    """
+    KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER = _pywrapknapsack_solver.KnapsackSolver_KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER
+    r"""
+     Dynamic Programming approach for single dimension problems
+
+    Limited to one dimension, this solver is based on a dynamic programming
+    algorithm. The time and space complexity is O(capacity *
+    number_of_items).
+    """
+    KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER = _pywrapknapsack_solver.KnapsackSolver_KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER
+    r"""
+     CBC Based Solver
+
+     This solver can deal with both large number of items and several
+    dimensions. This solver is based on Integer Programming solver CBC.
+    """
+    KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER = _pywrapknapsack_solver.KnapsackSolver_KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER
+    r"""
+     Generic Solver.
+
+    This solver can deal with both large number of items and several
+    dimensions. This solver is based on branch and bound.
+    """
+    KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER = _pywrapknapsack_solver.KnapsackSolver_KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER
+    r"""
+     SCIP based solver
+
+    This solver can deal with both large number of items and several
+    dimensions. This solver is based on Integer Programming solver SCIP.
+    """
+
+    def __init__(self, *args):
+        _pywrapknapsack_solver.KnapsackSolver_swiginit(self, _pywrapknapsack_solver.new_KnapsackSolver(*args))
+    __swig_destroy__ = _pywrapknapsack_solver.delete_KnapsackSolver
+
+    def Init(self, profits: "std::vector< int64_t > const &", weights: "std::vector< std::vector< int64_t > > const &", capacities: "std::vector< int64_t > const &") -> "void":
+        r"""Initializes the solver and enters the problem to be solved."""
+        return _pywrapknapsack_solver.KnapsackSolver_Init(self, profits, weights, capacities)
+
+    def Solve(self) -> "int64_t":
+        r"""Solves the problem and returns the profit of the optimal solution."""
+        return _pywrapknapsack_solver.KnapsackSolver_Solve(self)
+
+    def BestSolutionContains(self, item_id: "int") -> "bool":
+        r"""Returns true if the item 'item_id' is packed in the optimal knapsack."""
+        return _pywrapknapsack_solver.KnapsackSolver_BestSolutionContains(self, item_id)
+
+    def set_use_reduction(self, use_reduction: "bool") -> "void":
+        return _pywrapknapsack_solver.KnapsackSolver_set_use_reduction(self, use_reduction)
+
+    def set_time_limit(self, time_limit_seconds: "double") -> "void":
+        r"""
+         Time limit in seconds.
+
+        When a finite time limit is set the solution obtained might not be optimal
+        if the limit is reached.
+        """
+        return _pywrapknapsack_solver.KnapsackSolver_set_time_limit(self, time_limit_seconds)
+
+ +
+ +

This library solves knapsack problems.

+ +

Problems the library solves include:

+ +
    +
  • 0-1 knapsack problems,
  • +
  • Multi-dimensional knapsack problems,
  • +
+ +

Given n items, each with a profit and a weight, given a knapsack of +capacity c, the goal is to find a subset of items which fits inside c +and maximizes the total profit. +The knapsack problem can easily be extended from 1 to d dimensions. +As an example, this can be useful to constrain the maximum number of +items inside the knapsack. +Without loss of generality, profits and weights are assumed to be positive.

+ +

From a mathematical point of view, the multi-dimensional knapsack problem +can be modeled by d linear constraints:

+ +
ForEach(j:1..d)(Sum(i:1..n)(weight_ij * item_i) <= c_j
+    where item_i is a 0-1 integer variable.
+
+ +
Then the goal is to maximize
+ +
+

Sum(i:1..n)(profit_i * item_i).

+
+ +

There are several ways to solve knapsack problems. One of the most +efficient is based on dynamic programming (mainly when weights, profits +and dimensions are small, and the algorithm runs in pseudo polynomial time). +Unfortunately, when adding conflict constraints the problem becomes strongly +NP-hard, i.e. there is no pseudo-polynomial algorithm to solve it. +That's the reason why the most of the following code is based on branch and +bound search.

+ +

For instance to solve a 2-dimensional knapsack problem with 9 items, +one just has to feed a profit vector with the 9 profits, a vector of 2 +vectors for weights, and a vector of capacities. +E.g.:

+ +

Python:

+ +

.. code-block:: python

+ +
      profits = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
+      weights = [ [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
+                  [ 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
+                ]
+      capacities = [ 34, 4 ]
+
+      solver = pywrapknapsack_solver.KnapsackSolver(
+          pywrapknapsack_solver.KnapsackSolver
+              .KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER,
+          'Multi-dimensional solver')
+      solver.Init(profits, weights, capacities)
+      profit = solver.Solve()
+
+ +

C++:

+ +

.. code-block:: c++

+ +
     const std::vector<int64_t> profits = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+     const std::vector<std::vector<int64_t>> weights =
+         { { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+           { 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
+     const std::vector<int64_t> capacities = { 34, 4 };
+
+     KnapsackSolver solver(
+         KnapsackSolver::KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER,
+         "Multi-dimensional solver");
+     solver.Init(profits, weights, capacities);
+     const int64_t profit = solver.Solve();
+
+ +

Java:

+ +

.. code-block:: java

+ +
    final long[] profits = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+    final long[][] weights = { { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+           { 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
+    final long[] capacities = { 34, 4 };
+
+    KnapsackSolver solver = new KnapsackSolver(
+        KnapsackSolver.SolverType.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER,
+        "Multi-dimensional solver");
+    solver.init(profits, weights, capacities);
+    final long profit = solver.solve();
+
+
+ + +
+
#   + + + KnapsackSolver(*args) +
+ +
+ View Source +
    def __init__(self, *args):
+        _pywrapknapsack_solver.KnapsackSolver_swiginit(self, _pywrapknapsack_solver.new_KnapsackSolver(*args))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + KNAPSACK_BRUTE_FORCE_SOLVER = 0 +
+ + +

Brute force method.

+ +

Limited to 30 items and one dimension, this +solver uses a brute force algorithm, ie. explores all possible states. +Experiments show competitive performance for instances with less than +15 items.

+
+ + +
+
+
#   + + KNAPSACK_64ITEMS_SOLVER = 1 +
+ + +

Optimized method for single dimension small problems

+ +

Limited to 64 items and one dimension, this +solver uses a branch & bound algorithm. This solver is about 4 times +faster than KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER.

+
+ + +
+
+
#   + + KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER = 2 +
+ + +

Dynamic Programming approach for single dimension problems

+ +

Limited to one dimension, this solver is based on a dynamic programming +algorithm. The time and space complexity is O(capacity * +number_of_items).

+
+ + +
+
+
#   + + KNAPSACK_MULTIDIMENSION_CBC_MIP_SOLVER = 3 +
+ + +

CBC Based Solver

+ +

This solver can deal with both large number of items and several +dimensions. This solver is based on Integer Programming solver CBC.

+
+ + +
+
+
#   + + KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER = 5 +
+ + +

Generic Solver.

+ +

This solver can deal with both large number of items and several +dimensions. This solver is based on branch and bound.

+
+ + +
+
+
#   + + KNAPSACK_MULTIDIMENSION_SCIP_MIP_SOLVER = 6 +
+ + +

SCIP based solver

+ +

This solver can deal with both large number of items and several +dimensions. This solver is based on Integer Programming solver SCIP.

+
+ + +
+
+
#   + + + def + Init( + self, + profits: 'std::vector< int64_t > const &', + weights: 'std::vector< std::vector< int64_t > > const &', + capacities: 'std::vector< int64_t > const &' +) -> 'void': +
+ +
+ View Source +
    def Init(self, profits: "std::vector< int64_t > const &", weights: "std::vector< std::vector< int64_t > > const &", capacities: "std::vector< int64_t > const &") -> "void":
+        r"""Initializes the solver and enters the problem to be solved."""
+        return _pywrapknapsack_solver.KnapsackSolver_Init(self, profits, weights, capacities)
+
+ +
+ +

Initializes the solver and enters the problem to be solved.

+
+ + +
+
+
#   + + + def + Solve(self) -> 'int64_t': +
+ +
+ View Source +
    def Solve(self) -> "int64_t":
+        r"""Solves the problem and returns the profit of the optimal solution."""
+        return _pywrapknapsack_solver.KnapsackSolver_Solve(self)
+
+ +
+ +

Solves the problem and returns the profit of the optimal solution.

+
+ + +
+
+
#   + + + def + BestSolutionContains(self, item_id: int) -> bool: +
+ +
+ View Source +
    def BestSolutionContains(self, item_id: "int") -> "bool":
+        r"""Returns true if the item 'item_id' is packed in the optimal knapsack."""
+        return _pywrapknapsack_solver.KnapsackSolver_BestSolutionContains(self, item_id)
+
+ +
+ +

Returns true if the item 'item_id' is packed in the optimal knapsack.

+
+ + +
+
+
#   + + + def + set_use_reduction(self, use_reduction: bool) -> 'void': +
+ +
+ View Source +
    def set_use_reduction(self, use_reduction: "bool") -> "void":
+        return _pywrapknapsack_solver.KnapsackSolver_set_use_reduction(self, use_reduction)
+
+ +
+ + + +
+
+
#   + + + def + set_time_limit(self, time_limit_seconds: 'double') -> 'void': +
+ +
+ View Source +
    def set_time_limit(self, time_limit_seconds: "double") -> "void":
+        r"""
+         Time limit in seconds.
+
+        When a finite time limit is set the solution obtained might not be optimal
+        if the limit is reached.
+        """
+        return _pywrapknapsack_solver.KnapsackSolver_set_time_limit(self, time_limit_seconds)
+
+ +
+ +

Time limit in seconds.

+ +

When a finite time limit is set the solution obtained might not be optimal +if the limit is reached.

+
+ + +
+
+
+ + \ No newline at end of file diff --git a/docs/python/ortools/constraint_solver/index.html b/docs/python/ortools/constraint_solver/index.html index 3a1ceaa37a..9f85df8c61 100644 --- a/docs/python/ortools/constraint_solver/index.html +++ b/docs/python/ortools/constraint_solver/index.html @@ -1,58 +1,7 @@ - + - - - Module List – pdoc 8.0.0 - - - - - - - - + - -
- - pdoc logo - -
-
-
- - \ No newline at end of file + diff --git a/docs/python/ortools/constraint_solver/ortools/constraint_solver/pywrapcp.html b/docs/python/ortools/constraint_solver/ortools/constraint_solver/pywrapcp.html new file mode 100644 index 0000000000..6c8b7239ad --- /dev/null +++ b/docs/python/ortools/constraint_solver/ortools/constraint_solver/pywrapcp.html @@ -0,0 +1,42106 @@ + + + + + + + ortools.constraint_solver.pywrapcp API documentation + + + + + + + + + +
+
+

+ortools.constraint_solver.pywrapcp

+ + +
+ View Source +
# This file was automatically generated by SWIG (http://www.swig.org).
+# Version 4.0.2
+#
+# Do not make changes to this file unless you know what you are doing--modify
+# the SWIG interface file instead.
+
+from sys import version_info as _swig_python_version_info
+if _swig_python_version_info < (2, 7, 0):
+    raise RuntimeError("Python 2.7 or later required")
+
+# Import the low-level C/C++ module
+if __package__ or "." in __name__:
+    from . import _pywrapcp
+else:
+    import _pywrapcp
+
+try:
+    import builtins as __builtin__
+except ImportError:
+    import __builtin__
+
+def _swig_repr(self):
+    try:
+        strthis = "proxy of " + self.this.__repr__()
+    except __builtin__.Exception:
+        strthis = ""
+    return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+
+def _swig_setattr_nondynamic_instance_variable(set):
+    def set_instance_attr(self, name, value):
+        if name == "thisown":
+            self.this.own(value)
+        elif name == "this":
+            set(self, name, value)
+        elif hasattr(self, name) and isinstance(getattr(type(self), name), property):
+            set(self, name, value)
+        else:
+            raise AttributeError("You cannot add instance attributes to %s" % self)
+    return set_instance_attr
+
+
+def _swig_setattr_nondynamic_class_variable(set):
+    def set_class_attr(cls, name, value):
+        if hasattr(cls, name) and not isinstance(getattr(cls, name), property):
+            set(cls, name, value)
+        else:
+            raise AttributeError("You cannot add class attributes to %s" % cls)
+    return set_class_attr
+
+
+def _swig_add_metaclass(metaclass):
+    """Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass"""
+    def wrapper(cls):
+        return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy())
+    return wrapper
+
+
+class _SwigNonDynamicMeta(type):
+    """Meta class to enforce nondynamic attributes (no new attributes) for a class"""
+    __setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__)
+
+
+import weakref
+
+class DefaultPhaseParameters(object):
+    r"""
+    This struct holds all parameters for the default search.
+    DefaultPhaseParameters is only used by Solver::MakeDefaultPhase methods.
+    Note this is for advanced users only.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+    CHOOSE_MAX_SUM_IMPACT = _pywrapcp.DefaultPhaseParameters_CHOOSE_MAX_SUM_IMPACT
+    CHOOSE_MAX_AVERAGE_IMPACT = _pywrapcp.DefaultPhaseParameters_CHOOSE_MAX_AVERAGE_IMPACT
+    CHOOSE_MAX_VALUE_IMPACT = _pywrapcp.DefaultPhaseParameters_CHOOSE_MAX_VALUE_IMPACT
+    SELECT_MIN_IMPACT = _pywrapcp.DefaultPhaseParameters_SELECT_MIN_IMPACT
+    SELECT_MAX_IMPACT = _pywrapcp.DefaultPhaseParameters_SELECT_MAX_IMPACT
+    NONE = _pywrapcp.DefaultPhaseParameters_NONE
+    NORMAL = _pywrapcp.DefaultPhaseParameters_NORMAL
+    VERBOSE = _pywrapcp.DefaultPhaseParameters_VERBOSE
+    var_selection_schema = property(_pywrapcp.DefaultPhaseParameters_var_selection_schema_get, _pywrapcp.DefaultPhaseParameters_var_selection_schema_set, doc=r"""
+    This parameter describes how the next variable to instantiate
+    will be chosen.
+    """)
+    value_selection_schema = property(_pywrapcp.DefaultPhaseParameters_value_selection_schema_get, _pywrapcp.DefaultPhaseParameters_value_selection_schema_set, doc=r""" This parameter describes which value to select for a given var.""")
+    initialization_splits = property(_pywrapcp.DefaultPhaseParameters_initialization_splits_get, _pywrapcp.DefaultPhaseParameters_initialization_splits_set, doc=r"""
+    Maximum number of intervals that the initialization of impacts will scan
+    per variable.
+    """)
+    run_all_heuristics = property(_pywrapcp.DefaultPhaseParameters_run_all_heuristics_get, _pywrapcp.DefaultPhaseParameters_run_all_heuristics_set, doc=r"""
+    The default phase will run heuristics periodically. This parameter
+    indicates if we should run all heuristics, or a randomly selected
+    one.
+    """)
+    heuristic_period = property(_pywrapcp.DefaultPhaseParameters_heuristic_period_get, _pywrapcp.DefaultPhaseParameters_heuristic_period_set, doc=r"""
+    The distance in nodes between each run of the heuristics. A
+    negative or null value will mean that we will not run heuristics
+    at all.
+    """)
+    heuristic_num_failures_limit = property(_pywrapcp.DefaultPhaseParameters_heuristic_num_failures_limit_get, _pywrapcp.DefaultPhaseParameters_heuristic_num_failures_limit_set, doc=r""" The failure limit for each heuristic that we run.""")
+    persistent_impact = property(_pywrapcp.DefaultPhaseParameters_persistent_impact_get, _pywrapcp.DefaultPhaseParameters_persistent_impact_set, doc=r"""
+    Whether to keep the impact from the first search for other searches,
+    or to recompute the impact for each new search.
+    """)
+    random_seed = property(_pywrapcp.DefaultPhaseParameters_random_seed_get, _pywrapcp.DefaultPhaseParameters_random_seed_set, doc=r""" Seed used to initialize the random part in some heuristics.""")
+    display_level = property(_pywrapcp.DefaultPhaseParameters_display_level_get, _pywrapcp.DefaultPhaseParameters_display_level_set, doc=r"""
+    This represents the amount of information displayed by the default search.
+    NONE means no display, VERBOSE means extra information.
+    """)
+    decision_builder = property(_pywrapcp.DefaultPhaseParameters_decision_builder_get, _pywrapcp.DefaultPhaseParameters_decision_builder_set, doc=r""" When defined, this overrides the default impact based decision builder.""")
+
+    def __init__(self):
+        _pywrapcp.DefaultPhaseParameters_swiginit(self, _pywrapcp.new_DefaultPhaseParameters())
+    __swig_destroy__ = _pywrapcp.delete_DefaultPhaseParameters
+
+# Register DefaultPhaseParameters in _pywrapcp:
+_pywrapcp.DefaultPhaseParameters_swigregister(DefaultPhaseParameters)
+
+class Solver(object):
+    r"""
+    Solver Class
+
+    A solver represents the main computation engine. It implements the entire
+    range of Constraint Programming protocols:
+      - Reversibility
+      - Propagation
+      - Search
+
+    Usually, Constraint Programming code consists of
+      - the creation of the Solver,
+      - the creation of the decision variables of the model,
+      - the creation of the constraints of the model and their addition to the
+        solver() through the AddConstraint() method,
+      - the creation of the main DecisionBuilder class,
+      - the launch of the solve() method with the decision builder.
+
+    For the time being, Solver is neither MT_SAFE nor MT_HOT.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+    INT_VAR_DEFAULT = _pywrapcp.Solver_INT_VAR_DEFAULT
+    r""" The default behavior is CHOOSE_FIRST_UNBOUND."""
+    INT_VAR_SIMPLE = _pywrapcp.Solver_INT_VAR_SIMPLE
+    r""" The simple selection is CHOOSE_FIRST_UNBOUND."""
+    CHOOSE_FIRST_UNBOUND = _pywrapcp.Solver_CHOOSE_FIRST_UNBOUND
+    r"""
+    Select the first unbound variable.
+    Variables are considered in the order of the vector of IntVars used
+    to create the selector.
+    """
+    CHOOSE_RANDOM = _pywrapcp.Solver_CHOOSE_RANDOM
+    r""" Randomly select one of the remaining unbound variables."""
+    CHOOSE_MIN_SIZE_LOWEST_MIN = _pywrapcp.Solver_CHOOSE_MIN_SIZE_LOWEST_MIN
+    r"""
+    Among unbound variables, select the variable with the smallest size,
+    i.e., the smallest number of possible values.
+    In case of a tie, the selected variables is the one with the lowest min
+    value.
+    In case of a tie, the first one is selected, first being defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_MIN_SIZE_HIGHEST_MIN = _pywrapcp.Solver_CHOOSE_MIN_SIZE_HIGHEST_MIN
+    r"""
+    Among unbound variables, select the variable with the smallest size,
+    i.e., the smallest number of possible values.
+    In case of a tie, the selected variable is the one with the highest min
+    value.
+    In case of a tie, the first one is selected, first being defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_MIN_SIZE_LOWEST_MAX = _pywrapcp.Solver_CHOOSE_MIN_SIZE_LOWEST_MAX
+    r"""
+    Among unbound variables, select the variable with the smallest size,
+    i.e., the smallest number of possible values.
+    In case of a tie, the selected variables is the one with the lowest max
+    value.
+    In case of a tie, the first one is selected, first being defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_MIN_SIZE_HIGHEST_MAX = _pywrapcp.Solver_CHOOSE_MIN_SIZE_HIGHEST_MAX
+    r"""
+    Among unbound variables, select the variable with the smallest size,
+    i.e., the smallest number of possible values.
+    In case of a tie, the selected variable is the one with the highest max
+    value.
+    In case of a tie, the first one is selected, first being defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_LOWEST_MIN = _pywrapcp.Solver_CHOOSE_LOWEST_MIN
+    r"""
+    Among unbound variables, select the variable with the smallest minimal
+    value.
+    In case of a tie, the first one is selected, "first" defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_HIGHEST_MAX = _pywrapcp.Solver_CHOOSE_HIGHEST_MAX
+    r"""
+    Among unbound variables, select the variable with the highest maximal
+    value.
+    In case of a tie, the first one is selected, first being defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_MIN_SIZE = _pywrapcp.Solver_CHOOSE_MIN_SIZE
+    r"""
+    Among unbound variables, select the variable with the smallest size.
+    In case of a tie, the first one is selected, first being defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_MAX_SIZE = _pywrapcp.Solver_CHOOSE_MAX_SIZE
+    r"""
+    Among unbound variables, select the variable with the highest size.
+    In case of a tie, the first one is selected, first being defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_MAX_REGRET_ON_MIN = _pywrapcp.Solver_CHOOSE_MAX_REGRET_ON_MIN
+    r"""
+    Among unbound variables, select the variable with the largest
+    gap between the first and the second values of the domain.
+    """
+    CHOOSE_PATH = _pywrapcp.Solver_CHOOSE_PATH
+    r"""
+    Selects the next unbound variable on a path, the path being defined by
+    the variables: var[i] corresponds to the index of the next of i.
+    """
+    INT_VALUE_DEFAULT = _pywrapcp.Solver_INT_VALUE_DEFAULT
+    r""" The default behavior is ASSIGN_MIN_VALUE."""
+    INT_VALUE_SIMPLE = _pywrapcp.Solver_INT_VALUE_SIMPLE
+    r""" The simple selection is ASSIGN_MIN_VALUE."""
+    ASSIGN_MIN_VALUE = _pywrapcp.Solver_ASSIGN_MIN_VALUE
+    r""" Selects the min value of the selected variable."""
+    ASSIGN_MAX_VALUE = _pywrapcp.Solver_ASSIGN_MAX_VALUE
+    r""" Selects the max value of the selected variable."""
+    ASSIGN_RANDOM_VALUE = _pywrapcp.Solver_ASSIGN_RANDOM_VALUE
+    r""" Selects randomly one of the possible values of the selected variable."""
+    ASSIGN_CENTER_VALUE = _pywrapcp.Solver_ASSIGN_CENTER_VALUE
+    r"""
+    Selects the first possible value which is the closest to the center
+    of the domain of the selected variable.
+    The center is defined as (min + max) / 2.
+    """
+    SPLIT_LOWER_HALF = _pywrapcp.Solver_SPLIT_LOWER_HALF
+    r"""
+    Split the domain in two around the center, and choose the lower
+    part first.
+    """
+    SPLIT_UPPER_HALF = _pywrapcp.Solver_SPLIT_UPPER_HALF
+    r"""
+    Split the domain in two around the center, and choose the lower
+    part first.
+    """
+    SEQUENCE_DEFAULT = _pywrapcp.Solver_SEQUENCE_DEFAULT
+    SEQUENCE_SIMPLE = _pywrapcp.Solver_SEQUENCE_SIMPLE
+    CHOOSE_MIN_SLACK_RANK_FORWARD = _pywrapcp.Solver_CHOOSE_MIN_SLACK_RANK_FORWARD
+    CHOOSE_RANDOM_RANK_FORWARD = _pywrapcp.Solver_CHOOSE_RANDOM_RANK_FORWARD
+    INTERVAL_DEFAULT = _pywrapcp.Solver_INTERVAL_DEFAULT
+    r""" The default is INTERVAL_SET_TIMES_FORWARD."""
+    INTERVAL_SIMPLE = _pywrapcp.Solver_INTERVAL_SIMPLE
+    r""" The simple is INTERVAL_SET_TIMES_FORWARD."""
+    INTERVAL_SET_TIMES_FORWARD = _pywrapcp.Solver_INTERVAL_SET_TIMES_FORWARD
+    r"""
+    Selects the variable with the lowest starting time of all variables,
+    and fixes its starting time to this lowest value.
+    """
+    INTERVAL_SET_TIMES_BACKWARD = _pywrapcp.Solver_INTERVAL_SET_TIMES_BACKWARD
+    r"""
+    Selects the variable with the highest ending time of all variables,
+    and fixes the ending time to this highest values.
+    """
+    TWOOPT = _pywrapcp.Solver_TWOOPT
+    r"""
+    Operator which reverses a sub-chain of a path. It is called TwoOpt
+    because it breaks two arcs on the path; resulting paths are called
+    two-optimal.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 -> 5
+    (where (1, 5) are first and last nodes of the path and can therefore not
+    be moved):
+      1 -> [3 -> 2] -> 4  -> 5
+      1 -> [4 -> 3  -> 2] -> 5
+      1 ->  2 -> [4 -> 3] -> 5
+    """
+    OROPT = _pywrapcp.Solver_OROPT
+    r"""
+    Relocate: OROPT and RELOCATE.
+    Operator which moves a sub-chain of a path to another position; the
+    specified chain length is the fixed length of the chains being moved.
+    When this length is 1, the operator simply moves a node to another
+    position.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 -> 5, for a chain
+    length of 2 (where (1, 5) are first and last nodes of the path and can
+    therefore not be moved):
+      1 ->  4 -> [2 -> 3] -> 5
+      1 -> [3 -> 4] -> 2  -> 5
+
+    Using Relocate with chain lengths of 1, 2 and 3 together is equivalent
+    to the OrOpt operator on a path. The OrOpt operator is a limited
+     version of 3Opt (breaks 3 arcs on a path).
+    """
+    RELOCATE = _pywrapcp.Solver_RELOCATE
+    r""" Relocate neighborhood with length of 1 (see OROPT comment)."""
+    EXCHANGE = _pywrapcp.Solver_EXCHANGE
+    r"""
+    Operator which exchanges the positions of two nodes.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 -> 5
+    (where (1, 5) are first and last nodes of the path and can therefore not
+    be moved):
+      1 -> [3] -> [2] ->  4  -> 5
+      1 -> [4] ->  3  -> [2] -> 5
+      1 ->  2  -> [4] -> [3] -> 5
+    """
+    CROSS = _pywrapcp.Solver_CROSS
+    r"""
+    Operator which cross exchanges the starting chains of 2 paths, including
+    exchanging the whole paths.
+    First and last nodes are not moved.
+    Possible neighbors for the paths 1 -> 2 -> 3 -> 4 -> 5 and 6 -> 7 -> 8
+    (where (1, 5) and (6, 8) are first and last nodes of the paths and can
+    therefore not be moved):
+      1 -> [7] -> 3 -> 4 -> 5  6 -> [2] -> 8
+      1 -> [7] -> 4 -> 5       6 -> [2 -> 3] -> 8
+      1 -> [7] -> 5            6 -> [2 -> 3 -> 4] -> 8
+    """
+    MAKEACTIVE = _pywrapcp.Solver_MAKEACTIVE
+    r"""
+    Operator which inserts an inactive node into a path.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 with 5 inactive
+    (where 1 and 4 are first and last nodes of the path) are:
+      1 -> [5] ->  2  ->  3  -> 4
+      1 ->  2  -> [5] ->  3  -> 4
+      1 ->  2  ->  3  -> [5] -> 4
+    """
+    MAKEINACTIVE = _pywrapcp.Solver_MAKEINACTIVE
+    r"""
+    Operator which makes path nodes inactive.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 (where 1 and 4 are
+    first and last nodes of the path) are:
+      1 -> 3 -> 4 with 2 inactive
+      1 -> 2 -> 4 with 3 inactive
+    """
+    MAKECHAININACTIVE = _pywrapcp.Solver_MAKECHAININACTIVE
+    r"""
+    Operator which makes a "chain" of path nodes inactive.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 (where 1 and 4 are
+    first and last nodes of the path) are:
+      1 -> 3 -> 4 with 2 inactive
+      1 -> 2 -> 4 with 3 inactive
+      1 -> 4 with 2 and 3 inactive
+    """
+    SWAPACTIVE = _pywrapcp.Solver_SWAPACTIVE
+    r"""
+    Operator which replaces an active node by an inactive one.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 with 5 inactive
+    (where 1 and 4 are first and last nodes of the path) are:
+      1 -> [5] ->  3  -> 4 with 2 inactive
+      1 ->  2  -> [5] -> 4 with 3 inactive
+    """
+    EXTENDEDSWAPACTIVE = _pywrapcp.Solver_EXTENDEDSWAPACTIVE
+    r"""
+    Operator which makes an inactive node active and an active one inactive.
+    It is similar to SwapActiveOperator except that it tries to insert the
+    inactive node in all possible positions instead of just the position of
+    the node made inactive.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 with 5 inactive
+    (where 1 and 4 are first and last nodes of the path) are:
+      1 -> [5] ->  3  -> 4 with 2 inactive
+      1 ->  3  -> [5] -> 4 with 2 inactive
+      1 -> [5] ->  2  -> 4 with 3 inactive
+      1 ->  2  -> [5] -> 4 with 3 inactive
+    """
+    PATHLNS = _pywrapcp.Solver_PATHLNS
+    r"""
+    Operator which relaxes two sub-chains of three consecutive arcs each.
+    Each sub-chain is defined by a start node and the next three arcs. Those
+    six arcs are relaxed to build a new neighbor.
+    PATHLNS explores all possible pairs of starting nodes and so defines
+    n^2 neighbors, n being the number of nodes.
+    Note that the two sub-chains can be part of the same path; they even may
+    overlap.
+    """
+    FULLPATHLNS = _pywrapcp.Solver_FULLPATHLNS
+    r"""
+    Operator which relaxes one entire path and all inactive nodes, thus
+    defining num_paths neighbors.
+    """
+    UNACTIVELNS = _pywrapcp.Solver_UNACTIVELNS
+    r"""
+    Operator which relaxes all inactive nodes and one sub-chain of six
+    consecutive arcs. That way the path can be improved by inserting
+    inactive nodes or swapping arcs.
+    """
+    INCREMENT = _pywrapcp.Solver_INCREMENT
+    r"""
+    Operator which defines one neighbor per variable. Each neighbor tries to
+    increment by one the value of the corresponding variable. When a new
+    solution is found the neighborhood is rebuilt from scratch, i.e., tries
+    to increment values in the variable order.
+    Consider for instance variables x and y. x is incremented one by one to
+    its max, and when it is not possible to increment x anymore, y is
+    incremented once. If this is a solution, then next neighbor tries to
+    increment x.
+    """
+    DECREMENT = _pywrapcp.Solver_DECREMENT
+    r"""
+    Operator which defines a neighborhood to decrement values.
+    The behavior is the same as INCREMENT, except values are decremented
+    instead of incremented.
+    """
+    SIMPLELNS = _pywrapcp.Solver_SIMPLELNS
+    r"""
+    Operator which defines one neighbor per variable. Each neighbor relaxes
+    one variable.
+    When a new solution is found the neighborhood is rebuilt from scratch.
+    Consider for instance variables x and y. First x is relaxed and the
+    solver is looking for the best possible solution (with only x relaxed).
+    Then y is relaxed, and the solver is looking for a new solution.
+    If a new solution is found, then the next variable to be relaxed is x.
+    """
+    GE = _pywrapcp.Solver_GE
+    r""" Move is accepted when the current objective value >= objective.Min."""
+    LE = _pywrapcp.Solver_LE
+    r""" Move is accepted when the current objective value <= objective.Max."""
+    EQ = _pywrapcp.Solver_EQ
+    r"""
+    Move is accepted when the current objective value is in the interval
+    objective.Min .. objective.Max.
+    """
+    DELAYED_PRIORITY = _pywrapcp.Solver_DELAYED_PRIORITY
+    r"""
+    DELAYED_PRIORITY is the lowest priority: Demons will be processed after
+    VAR_PRIORITY and NORMAL_PRIORITY demons.
+    """
+    VAR_PRIORITY = _pywrapcp.Solver_VAR_PRIORITY
+    r""" VAR_PRIORITY is between DELAYED_PRIORITY and NORMAL_PRIORITY."""
+    NORMAL_PRIORITY = _pywrapcp.Solver_NORMAL_PRIORITY
+    r""" NORMAL_PRIORITY is the highest priority: Demons will be processed first."""
+
+    def __init__(self, *args):
+        _pywrapcp.Solver_swiginit(self, _pywrapcp.new_Solver(*args))
+
+        self.__python_constraints = []
+
+
+
+    __swig_destroy__ = _pywrapcp.delete_Solver
+
+    def Parameters(self) -> "operations_research::ConstraintSolverParameters":
+        r""" Stored Parameters."""
+        return _pywrapcp.Solver_Parameters(self)
+
+    @staticmethod
+    def DefaultSolverParameters() -> "operations_research::ConstraintSolverParameters":
+        r""" Create a ConstraintSolverParameters proto with all the default values."""
+        return _pywrapcp.Solver_DefaultSolverParameters()
+
+    def AddConstraint(self, c: "Constraint") -> "void":
+        r"""
+        Adds the constraint 'c' to the model.
+
+        After calling this method, and until there is a backtrack that undoes the
+        addition, any assignment of variables to values must satisfy the given
+        constraint in order to be considered feasible. There are two fairly
+        different use cases:
+
+        - the most common use case is modeling: the given constraint is really
+        part of the problem that the user is trying to solve. In this use case,
+        AddConstraint is called outside of search (i.e., with state() ==
+        OUTSIDE_SEARCH). Most users should only use AddConstraint in this
+        way. In this case, the constraint will belong to the model forever: it
+        cannot not be removed by backtracking.
+
+        - a rarer use case is that 'c' is not a real constraint of the model. It
+        may be a constraint generated by a branching decision (a constraint whose
+        goal is to restrict the search space), a symmetry breaking constraint (a
+        constraint that does restrict the search space, but in a way that cannot
+        have an impact on the quality of the solutions in the subtree), or an
+        inferred constraint that, while having no semantic value to the model (it
+        does not restrict the set of solutions), is worth having because we
+        believe it may strengthen the propagation. In these cases, it happens
+        that the constraint is added during the search (i.e., with state() ==
+        IN_SEARCH or state() == IN_ROOT_NODE). When a constraint is
+        added during a search, it applies only to the subtree of the search tree
+        rooted at the current node, and will be automatically removed by
+        backtracking.
+
+        This method does not take ownership of the constraint. If the constraint
+        has been created by any factory method (Solver::MakeXXX), it will
+        automatically be deleted. However, power users who implement their own
+        constraints should do: solver.AddConstraint(solver.RevAlloc(new
+        MyConstraint(...));
+        """
+        return _pywrapcp.Solver_AddConstraint(self, c)
+
+    def Solve(self, *args) -> "bool":
+        return _pywrapcp.Solver_Solve(self, *args)
+
+    def NewSearch(self, *args) -> "void":
+        return _pywrapcp.Solver_NewSearch(self, *args)
+
+    def NextSolution(self) -> "bool":
+        return _pywrapcp.Solver_NextSolution(self)
+
+    def RestartSearch(self) -> "void":
+        return _pywrapcp.Solver_RestartSearch(self)
+
+    def EndSearch(self) -> "void":
+        return _pywrapcp.Solver_EndSearch(self)
+
+    def SolveAndCommit(self, *args) -> "bool":
+        return _pywrapcp.Solver_SolveAndCommit(self, *args)
+
+    def CheckAssignment(self, solution: "Assignment") -> "bool":
+        r""" Checks whether the given assignment satisfies all relevant constraints."""
+        return _pywrapcp.Solver_CheckAssignment(self, solution)
+
+    def CheckConstraint(self, ct: "Constraint") -> "bool":
+        r"""
+        Checks whether adding this constraint will lead to an immediate
+        failure. It will return false if the model is already inconsistent, or if
+        adding the constraint makes it inconsistent.
+        """
+        return _pywrapcp.Solver_CheckConstraint(self, ct)
+
+    def Fail(self) -> "void":
+        r""" Abandon the current branch in the search tree. A backtrack will follow."""
+        return _pywrapcp.Solver_Fail(self)
+
+    @staticmethod
+    def MemoryUsage() -> "int64_t":
+        r""" Current memory usage in bytes"""
+        return _pywrapcp.Solver_MemoryUsage()
+
+    def WallTime(self) -> "int64_t":
+        r"""
+        DEPRECATED: Use Now() instead.
+        Time elapsed, in ms since the creation of the solver.
+        """
+        return _pywrapcp.Solver_WallTime(self)
+
+    def Branches(self) -> "int64_t":
+        r""" The number of branches explored since the creation of the solver."""
+        return _pywrapcp.Solver_Branches(self)
+
+    def Solutions(self) -> "int64_t":
+        r""" The number of solutions found since the start of the search."""
+        return _pywrapcp.Solver_Solutions(self)
+
+    def Failures(self) -> "int64_t":
+        r""" The number of failures encountered since the creation of the solver."""
+        return _pywrapcp.Solver_Failures(self)
+
+    def AcceptedNeighbors(self) -> "int64_t":
+        r""" The number of accepted neighbors."""
+        return _pywrapcp.Solver_AcceptedNeighbors(self)
+
+    def Stamp(self) -> "uint64_t":
+        r"""
+        The stamp indicates how many moves in the search tree we have performed.
+        It is useful to detect if we need to update same lazy structures.
+        """
+        return _pywrapcp.Solver_Stamp(self)
+
+    def FailStamp(self) -> "uint64_t":
+        r""" The fail_stamp() is incremented after each backtrack."""
+        return _pywrapcp.Solver_FailStamp(self)
+
+    def IntVar(self, *args) -> "operations_research::IntVar *":
+        r"""
+        *Overload 1:*
+        MakeIntVar will create the best range based int var for the bounds given.
+
+        |
+
+        *Overload 2:*
+        MakeIntVar will create a variable with the given sparse domain.
+
+        |
+
+        *Overload 3:*
+        MakeIntVar will create a variable with the given sparse domain.
+
+        |
+
+        *Overload 4:*
+        MakeIntVar will create the best range based int var for the bounds given.
+
+        |
+
+        *Overload 5:*
+        MakeIntVar will create a variable with the given sparse domain.
+
+        |
+
+        *Overload 6:*
+        MakeIntVar will create a variable with the given sparse domain.
+        """
+        return _pywrapcp.Solver_IntVar(self, *args)
+
+    def BoolVar(self, *args) -> "operations_research::IntVar *":
+        r"""
+        *Overload 1:*
+        MakeBoolVar will create a variable with a {0, 1} domain.
+
+        |
+
+        *Overload 2:*
+        MakeBoolVar will create a variable with a {0, 1} domain.
+        """
+        return _pywrapcp.Solver_BoolVar(self, *args)
+
+    def IntConst(self, *args) -> "operations_research::IntVar *":
+        r"""
+        *Overload 1:*
+        IntConst will create a constant expression.
+
+        |
+
+        *Overload 2:*
+        IntConst will create a constant expression.
+        """
+        return _pywrapcp.Solver_IntConst(self, *args)
+
+    def Sum(self, vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::IntExpr *":
+        r""" sum of all vars."""
+        return _pywrapcp.Solver_Sum(self, vars)
+
+    def ScalProd(self, *args) -> "operations_research::IntExpr *":
+        r"""
+        *Overload 1:*
+        scalar product
+
+        |
+
+        *Overload 2:*
+        scalar product
+        """
+        return _pywrapcp.Solver_ScalProd(self, *args)
+
+    def MonotonicElement(self, values: "operations_research::Solver::IndexEvaluator1", increasing: "bool", index: "IntVar") -> "operations_research::IntExpr *":
+        r"""
+        Function based element. The constraint takes ownership of the
+        callback.  The callback must be monotonic. It must be able to
+        cope with any possible value in the domain of 'index'
+        (potentially negative ones too). Furtermore, monotonicity is not
+        checked. Thus giving a non-monotonic function, or specifying an
+        incorrect increasing parameter will result in undefined behavior.
+        """
+        return _pywrapcp.Solver_MonotonicElement(self, values, increasing, index)
+
+    def Element(self, *args) -> "operations_research::IntExpr *":
+        r"""
+        *Overload 1:*
+        values[index]
+
+        |
+
+        *Overload 2:*
+        values[index]
+
+        |
+
+        *Overload 3:*
+        Function-based element. The constraint takes ownership of the
+        callback. The callback must be able to cope with any possible
+        value in the domain of 'index' (potentially negative ones too).
+
+        |
+
+        *Overload 4:*
+        2D version of function-based element expression, values(expr1, expr2).
+
+        |
+
+        *Overload 5:*
+        vars[expr]
+        """
+        return _pywrapcp.Solver_Element(self, *args)
+
+    def IndexExpression(self, vars: "std::vector< operations_research::IntVar * > const &", value: "int64_t") -> "operations_research::IntExpr *":
+        r"""
+        Returns the expression expr such that vars[expr] == value.
+        It assumes that vars are all different.
+        """
+        return _pywrapcp.Solver_IndexExpression(self, vars, value)
+
+    def Min(self, *args) -> "operations_research::IntExpr *":
+        r"""
+        *Overload 1:*
+        std::min(vars)
+
+        |
+
+        *Overload 2:*
+        std::min (left, right)
+
+        |
+
+        *Overload 3:*
+        std::min(expr, value)
+
+        |
+
+        *Overload 4:*
+        std::min(expr, value)
+        """
+        return _pywrapcp.Solver_Min(self, *args)
+
+    def Max(self, *args) -> "operations_research::IntExpr *":
+        r"""
+        *Overload 1:*
+        std::max(vars)
+
+        |
+
+        *Overload 2:*
+        std::max(left, right)
+
+        |
+
+        *Overload 3:*
+        std::max(expr, value)
+
+        |
+
+        *Overload 4:*
+        std::max(expr, value)
+        """
+        return _pywrapcp.Solver_Max(self, *args)
+
+    def ConvexPiecewiseExpr(self, expr: "IntExpr", early_cost: "int64_t", early_date: "int64_t", late_date: "int64_t", late_cost: "int64_t") -> "operations_research::IntExpr *":
+        r""" Convex piecewise function."""
+        return _pywrapcp.Solver_ConvexPiecewiseExpr(self, expr, early_cost, early_date, late_date, late_cost)
+
+    def SemiContinuousExpr(self, expr: "IntExpr", fixed_charge: "int64_t", step: "int64_t") -> "operations_research::IntExpr *":
+        r"""
+        Semi continuous Expression (x <= 0 -> f(x) = 0; x > 0 -> f(x) = ax + b)
+        a >= 0 and b >= 0
+        """
+        return _pywrapcp.Solver_SemiContinuousExpr(self, expr, fixed_charge, step)
+
+    def ConditionalExpression(self, condition: "IntVar", expr: "IntExpr", unperformed_value: "int64_t") -> "operations_research::IntExpr *":
+        r""" Conditional Expr condition ? expr : unperformed_value"""
+        return _pywrapcp.Solver_ConditionalExpression(self, condition, expr, unperformed_value)
+
+    def TrueConstraint(self) -> "operations_research::Constraint *":
+        r""" This constraint always succeeds."""
+        return _pywrapcp.Solver_TrueConstraint(self)
+
+    def FalseConstraint(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_FalseConstraint(self, *args)
+
+    def IsEqualCstCt(self, var: "IntExpr", value: "int64_t", boolvar: "IntVar") -> "operations_research::Constraint *":
+        r""" boolvar == (var == value)"""
+        return _pywrapcp.Solver_IsEqualCstCt(self, var, value, boolvar)
+
+    def IsEqualCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var == value)"""
+        return _pywrapcp.Solver_IsEqualCstVar(self, var, value)
+
+    def IsEqualCt(self, v1: "IntExpr", v2: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (v1 == v2)"""
+        return _pywrapcp.Solver_IsEqualCt(self, v1, v2, b)
+
+    def IsEqualVar(self, v1: "IntExpr", v2: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (v1 == v2)"""
+        return _pywrapcp.Solver_IsEqualVar(self, v1, v2)
+
+    def IsDifferentCstCt(self, var: "IntExpr", value: "int64_t", boolvar: "IntVar") -> "operations_research::Constraint *":
+        r""" boolvar == (var != value)"""
+        return _pywrapcp.Solver_IsDifferentCstCt(self, var, value, boolvar)
+
+    def IsDifferentCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var != value)"""
+        return _pywrapcp.Solver_IsDifferentCstVar(self, var, value)
+
+    def IsDifferentVar(self, v1: "IntExpr", v2: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (v1 != v2)"""
+        return _pywrapcp.Solver_IsDifferentVar(self, v1, v2)
+
+    def IsDifferentCt(self, v1: "IntExpr", v2: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (v1 != v2)"""
+        return _pywrapcp.Solver_IsDifferentCt(self, v1, v2, b)
+
+    def IsLessOrEqualCstCt(self, var: "IntExpr", value: "int64_t", boolvar: "IntVar") -> "operations_research::Constraint *":
+        r""" boolvar == (var <= value)"""
+        return _pywrapcp.Solver_IsLessOrEqualCstCt(self, var, value, boolvar)
+
+    def IsLessOrEqualCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var <= value)"""
+        return _pywrapcp.Solver_IsLessOrEqualCstVar(self, var, value)
+
+    def IsLessOrEqualVar(self, left: "IntExpr", right: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (left <= right)"""
+        return _pywrapcp.Solver_IsLessOrEqualVar(self, left, right)
+
+    def IsLessOrEqualCt(self, left: "IntExpr", right: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (left <= right)"""
+        return _pywrapcp.Solver_IsLessOrEqualCt(self, left, right, b)
+
+    def IsGreaterOrEqualCstCt(self, var: "IntExpr", value: "int64_t", boolvar: "IntVar") -> "operations_research::Constraint *":
+        r""" boolvar == (var >= value)"""
+        return _pywrapcp.Solver_IsGreaterOrEqualCstCt(self, var, value, boolvar)
+
+    def IsGreaterOrEqualCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var >= value)"""
+        return _pywrapcp.Solver_IsGreaterOrEqualCstVar(self, var, value)
+
+    def IsGreaterOrEqualVar(self, left: "IntExpr", right: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (left >= right)"""
+        return _pywrapcp.Solver_IsGreaterOrEqualVar(self, left, right)
+
+    def IsGreaterOrEqualCt(self, left: "IntExpr", right: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (left >= right)"""
+        return _pywrapcp.Solver_IsGreaterOrEqualCt(self, left, right, b)
+
+    def IsGreaterCstCt(self, v: "IntExpr", c: "int64_t", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (v > c)"""
+        return _pywrapcp.Solver_IsGreaterCstCt(self, v, c, b)
+
+    def IsGreaterCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var > value)"""
+        return _pywrapcp.Solver_IsGreaterCstVar(self, var, value)
+
+    def IsGreaterVar(self, left: "IntExpr", right: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (left > right)"""
+        return _pywrapcp.Solver_IsGreaterVar(self, left, right)
+
+    def IsGreaterCt(self, left: "IntExpr", right: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (left > right)"""
+        return _pywrapcp.Solver_IsGreaterCt(self, left, right, b)
+
+    def IsLessCstCt(self, v: "IntExpr", c: "int64_t", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (v < c)"""
+        return _pywrapcp.Solver_IsLessCstCt(self, v, c, b)
+
+    def IsLessCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var < value)"""
+        return _pywrapcp.Solver_IsLessCstVar(self, var, value)
+
+    def IsLessVar(self, left: "IntExpr", right: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (left < right)"""
+        return _pywrapcp.Solver_IsLessVar(self, left, right)
+
+    def IsLessCt(self, left: "IntExpr", right: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (left < right)"""
+        return _pywrapcp.Solver_IsLessCt(self, left, right, b)
+
+    def SumLessOrEqual(self, vars: "std::vector< operations_research::IntVar * > const &", cst: "int64_t") -> "operations_research::Constraint *":
+        r""" Variation on arrays."""
+        return _pywrapcp.Solver_SumLessOrEqual(self, vars, cst)
+
+    def SumGreaterOrEqual(self, vars: "std::vector< operations_research::IntVar * > const &", cst: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_SumGreaterOrEqual(self, vars, cst)
+
+    def SumEquality(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_SumEquality(self, *args)
+
+    def ScalProdEquality(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_ScalProdEquality(self, *args)
+
+    def ScalProdGreaterOrEqual(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_ScalProdGreaterOrEqual(self, *args)
+
+    def ScalProdLessOrEqual(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_ScalProdLessOrEqual(self, *args)
+
+    def MinEquality(self, vars: "std::vector< operations_research::IntVar * > const &", min_var: "IntVar") -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_MinEquality(self, vars, min_var)
+
+    def MaxEquality(self, vars: "std::vector< operations_research::IntVar * > const &", max_var: "IntVar") -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_MaxEquality(self, vars, max_var)
+
+    def ElementEquality(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_ElementEquality(self, *args)
+
+    def AbsEquality(self, var: "IntVar", abs_var: "IntVar") -> "operations_research::Constraint *":
+        r""" Creates the constraint abs(var) == abs_var."""
+        return _pywrapcp.Solver_AbsEquality(self, var, abs_var)
+
+    def IndexOfConstraint(self, vars: "std::vector< operations_research::IntVar * > const &", index: "IntVar", target: "int64_t") -> "operations_research::Constraint *":
+        r"""
+        This constraint is a special case of the element constraint with
+        an array of integer variables, where the variables are all
+        different and the index variable is constrained such that
+        vars[index] == target.
+        """
+        return _pywrapcp.Solver_IndexOfConstraint(self, vars, index, target)
+
+    def ConstraintInitialPropagateCallback(self, ct: "Constraint") -> "operations_research::Demon *":
+        r"""
+        This method is a specialized case of the MakeConstraintDemon
+        method to call the InitiatePropagate of the constraint 'ct'.
+        """
+        return _pywrapcp.Solver_ConstraintInitialPropagateCallback(self, ct)
+
+    def DelayedConstraintInitialPropagateCallback(self, ct: "Constraint") -> "operations_research::Demon *":
+        r"""
+        This method is a specialized case of the MakeConstraintDemon
+        method to call the InitiatePropagate of the constraint 'ct' with
+        low priority.
+        """
+        return _pywrapcp.Solver_DelayedConstraintInitialPropagateCallback(self, ct)
+
+    def ClosureDemon(self, closure: "operations_research::Solver::Closure") -> "operations_research::Demon *":
+        r""" Creates a demon from a closure."""
+        return _pywrapcp.Solver_ClosureDemon(self, closure)
+
+    def BetweenCt(self, expr: "IntExpr", l: "int64_t", u: "int64_t") -> "operations_research::Constraint *":
+        r""" (l <= expr <= u)"""
+        return _pywrapcp.Solver_BetweenCt(self, expr, l, u)
+
+    def IsBetweenCt(self, expr: "IntExpr", l: "int64_t", u: "int64_t", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (l <= expr <= u)"""
+        return _pywrapcp.Solver_IsBetweenCt(self, expr, l, u, b)
+
+    def IsBetweenVar(self, v: "IntExpr", l: "int64_t", u: "int64_t") -> "operations_research::IntVar *":
+        return _pywrapcp.Solver_IsBetweenVar(self, v, l, u)
+
+    def MemberCt(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_MemberCt(self, *args)
+
+    def NotMemberCt(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        expr not in set.
+
+        |
+
+        *Overload 2:*
+        expr should not be in the list of forbidden intervals [start[i]..end[i]].
+
+        |
+
+        *Overload 3:*
+        expr should not be in the list of forbidden intervals [start[i]..end[i]].
+        """
+        return _pywrapcp.Solver_NotMemberCt(self, *args)
+
+    def IsMemberCt(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_IsMemberCt(self, *args)
+
+    def IsMemberVar(self, *args) -> "operations_research::IntVar *":
+        return _pywrapcp.Solver_IsMemberVar(self, *args)
+
+    def Count(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        |{i | vars[i] == value}| == max_count
+
+        |
+
+        *Overload 2:*
+        |{i | vars[i] == value}| == max_count
+        """
+        return _pywrapcp.Solver_Count(self, *args)
+
+    def Distribute(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        Aggregated version of count:  |{i | v[i] == values[j]}| == cards[j]
+
+        |
+
+        *Overload 2:*
+        Aggregated version of count:  |{i | v[i] == values[j]}| == cards[j]
+
+        |
+
+        *Overload 3:*
+        Aggregated version of count:  |{i | v[i] == j}| == cards[j]
+
+        |
+
+        *Overload 4:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1: card_min <= |{i | v[i] == j}| <= card_max
+
+        |
+
+        *Overload 5:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1:
+           card_min[j] <= |{i | v[i] == j}| <= card_max[j]
+
+        |
+
+        *Overload 6:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1:
+           card_min[j] <= |{i | v[i] == j}| <= card_max[j]
+
+        |
+
+        *Overload 7:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1:
+           card_min[j] <= |{i | v[i] == values[j]}| <= card_max[j]
+
+        |
+
+        *Overload 8:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1:
+           card_min[j] <= |{i | v[i] == values[j]}| <= card_max[j]
+        """
+        return _pywrapcp.Solver_Distribute(self, *args)
+
+    def Deviation(self, vars: "std::vector< operations_research::IntVar * > const &", deviation_var: "IntVar", total_sum: "int64_t") -> "operations_research::Constraint *":
+        r"""
+        Deviation constraint:
+        sum_i |n * vars[i] - total_sum| <= deviation_var and
+        sum_i vars[i] == total_sum
+        n = #vars
+        """
+        return _pywrapcp.Solver_Deviation(self, vars, deviation_var, total_sum)
+
+    def AllDifferent(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        All variables are pairwise different. This corresponds to the
+        stronger version of the propagation algorithm.
+
+        |
+
+        *Overload 2:*
+        All variables are pairwise different.  If 'stronger_propagation'
+        is true, stronger, and potentially slower propagation will
+        occur. This API will be deprecated in the future.
+        """
+        return _pywrapcp.Solver_AllDifferent(self, *args)
+
+    def AllDifferentExcept(self, vars: "std::vector< operations_research::IntVar * > const &", escape_value: "int64_t") -> "operations_research::Constraint *":
+        r"""
+        All variables are pairwise different, unless they are assigned to
+        the escape value.
+        """
+        return _pywrapcp.Solver_AllDifferentExcept(self, vars, escape_value)
+
+    def SortingConstraint(self, vars: "std::vector< operations_research::IntVar * > const &", sorted: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint binding the arrays of variables "vars" and
+        "sorted_vars": sorted_vars[0] must be equal to the minimum of all
+        variables in vars, and so on: the value of sorted_vars[i] must be
+        equal to the i-th value of variables invars.
+
+        This constraint propagates in both directions: from "vars" to
+        "sorted_vars" and vice-versa.
+
+        Behind the scenes, this constraint maintains that:
+          - sorted is always increasing.
+          - whatever the values of vars, there exists a permutation that
+            injects its values into the sorted variables.
+
+        For more info, please have a look at:
+          https://mpi-inf.mpg.de/~mehlhorn/ftp/Mehlhorn-Thiel.pdf
+        """
+        return _pywrapcp.Solver_SortingConstraint(self, vars, sorted)
+
+    def LexicalLess(self, left: "std::vector< operations_research::IntVar * > const &", right: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that enforces that left is lexicographically less
+        than right.
+        """
+        return _pywrapcp.Solver_LexicalLess(self, left, right)
+
+    def LexicalLessOrEqual(self, left: "std::vector< operations_research::IntVar * > const &", right: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that enforces that left is lexicographically less
+        than or equal to right.
+        """
+        return _pywrapcp.Solver_LexicalLessOrEqual(self, left, right)
+
+    def InversePermutationConstraint(self, left: "std::vector< operations_research::IntVar * > const &", right: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that enforces that 'left' and 'right' both
+        represent permutations of [0..left.size()-1], and that 'right' is
+        the inverse permutation of 'left', i.e. for all i in
+        [0..left.size()-1], right[left[i]] = i.
+        """
+        return _pywrapcp.Solver_InversePermutationConstraint(self, left, right)
+
+    def NullIntersect(self, first_vars: "std::vector< operations_research::IntVar * > const &", second_vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that states that all variables in the first
+        vector are different from all variables in the second
+        group. Thus the set of values in the first vector does not
+        intersect with the set of values in the second vector.
+        """
+        return _pywrapcp.Solver_NullIntersect(self, first_vars, second_vars)
+
+    def NullIntersectExcept(self, first_vars: "std::vector< operations_research::IntVar * > const &", second_vars: "std::vector< operations_research::IntVar * > const &", escape_value: "int64_t") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that states that all variables in the first
+        vector are different from all variables from the second group,
+        unless they are assigned to the escape value. Thus the set of
+        values in the first vector minus the escape value does not
+        intersect with the set of values in the second vector.
+        """
+        return _pywrapcp.Solver_NullIntersectExcept(self, first_vars, second_vars, escape_value)
+
+    def Circuit(self, nexts: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r""" Force the "nexts" variable to create a complete Hamiltonian path."""
+        return _pywrapcp.Solver_Circuit(self, nexts)
+
+    def SubCircuit(self, nexts: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Force the "nexts" variable to create a complete Hamiltonian path
+        for those that do not loop upon themselves.
+        """
+        return _pywrapcp.Solver_SubCircuit(self, nexts)
+
+    def DelayedPathCumul(self, nexts: "std::vector< operations_research::IntVar * > const &", active: "std::vector< operations_research::IntVar * > const &", cumuls: "std::vector< operations_research::IntVar * > const &", transits: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Delayed version of the same constraint: propagation on the nexts variables
+        is delayed until all constraints have propagated.
+        """
+        return _pywrapcp.Solver_DelayedPathCumul(self, nexts, active, cumuls, transits)
+
+    def PathCumul(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        Creates a constraint which accumulates values along a path such that:
+        cumuls[next[i]] = cumuls[i] + transits[i].
+        Active variables indicate if the corresponding next variable is active;
+        this could be useful to model unperformed nodes in a routing problem.
+
+        |
+
+        *Overload 2:*
+        Creates a constraint which accumulates values along a path such that:
+        cumuls[next[i]] = cumuls[i] + transit_evaluator(i, next[i]).
+        Active variables indicate if the corresponding next variable is active;
+        this could be useful to model unperformed nodes in a routing problem.
+        Ownership of transit_evaluator is taken and it must be a repeatable
+        callback.
+
+        |
+
+        *Overload 3:*
+        Creates a constraint which accumulates values along a path such that:
+        cumuls[next[i]] = cumuls[i] + transit_evaluator(i, next[i]) + slacks[i].
+        Active variables indicate if the corresponding next variable is active;
+        this could be useful to model unperformed nodes in a routing problem.
+        Ownership of transit_evaluator is taken and it must be a repeatable
+        callback.
+        """
+        return _pywrapcp.Solver_PathCumul(self, *args)
+
+    def AllowedAssignments(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        This method creates a constraint where the graph of the relation
+        between the variables is given in extension. There are 'arity'
+        variables involved in the relation and the graph is given by a
+        integer tuple set.
+
+        |
+
+        *Overload 2:*
+        Compatibility layer for Python API.
+        """
+        return _pywrapcp.Solver_AllowedAssignments(self, *args)
+
+    def TransitionConstraint(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_TransitionConstraint(self, *args)
+
+    def NonOverlappingBoxesConstraint(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_NonOverlappingBoxesConstraint(self, *args)
+
+    def Pack(self, vars: "std::vector< operations_research::IntVar * > const &", number_of_bins: "int") -> "operations_research::Pack *":
+        r"""
+        This constraint packs all variables onto 'number_of_bins'
+        variables.  For any given variable, a value of 'number_of_bins'
+        indicates that the variable is not assigned to any bin.
+        Dimensions, i.e., cumulative constraints on this packing, can be
+        added directly from the pack class.
+        """
+        return _pywrapcp.Solver_Pack(self, vars, number_of_bins)
+
+    def FixedDurationIntervalVar(self, *args) -> "operations_research::IntervalVar *":
+        r"""
+        *Overload 1:*
+        Creates an interval var with a fixed duration. The duration must
+        be greater than 0. If optional is true, then the interval can be
+        performed or unperformed. If optional is false, then the interval
+        is always performed.
+
+        |
+
+        *Overload 2:*
+        Creates a performed interval var with a fixed duration. The duration must
+        be greater than 0.
+
+        |
+
+        *Overload 3:*
+        Creates an interval var with a fixed duration, and performed_variable.
+        The duration must be greater than 0.
+        """
+        return _pywrapcp.Solver_FixedDurationIntervalVar(self, *args)
+
+    def FixedInterval(self, start: "int64_t", duration: "int64_t", name: "std::string const &") -> "operations_research::IntervalVar *":
+        r""" Creates a fixed and performed interval."""
+        return _pywrapcp.Solver_FixedInterval(self, start, duration, name)
+
+    def IntervalVar(self, start_min: "int64_t", start_max: "int64_t", duration_min: "int64_t", duration_max: "int64_t", end_min: "int64_t", end_max: "int64_t", optional: "bool", name: "std::string const &") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var by specifying the bounds on start,
+        duration, and end.
+        """
+        return _pywrapcp.Solver_IntervalVar(self, start_min, start_max, duration_min, duration_max, end_min, end_max, optional, name)
+
+    def MirrorInterval(self, interval_var: "IntervalVar") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var that is the mirror image of the given one, that
+        is, the interval var obtained by reversing the axis.
+        """
+        return _pywrapcp.Solver_MirrorInterval(self, interval_var)
+
+    def FixedDurationStartSyncedOnStartIntervalVar(self, interval_var: "IntervalVar", duration: "int64_t", offset: "int64_t") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var with a fixed duration whose start is
+        synchronized with the start of another interval, with a given
+        offset. The performed status is also in sync with the performed
+        status of the given interval variable.
+        """
+        return _pywrapcp.Solver_FixedDurationStartSyncedOnStartIntervalVar(self, interval_var, duration, offset)
+
+    def FixedDurationStartSyncedOnEndIntervalVar(self, interval_var: "IntervalVar", duration: "int64_t", offset: "int64_t") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var with a fixed duration whose start is
+        synchronized with the end of another interval, with a given
+        offset. The performed status is also in sync with the performed
+        status of the given interval variable.
+        """
+        return _pywrapcp.Solver_FixedDurationStartSyncedOnEndIntervalVar(self, interval_var, duration, offset)
+
+    def FixedDurationEndSyncedOnStartIntervalVar(self, interval_var: "IntervalVar", duration: "int64_t", offset: "int64_t") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var with a fixed duration whose end is
+        synchronized with the start of another interval, with a given
+        offset. The performed status is also in sync with the performed
+        status of the given interval variable.
+        """
+        return _pywrapcp.Solver_FixedDurationEndSyncedOnStartIntervalVar(self, interval_var, duration, offset)
+
+    def FixedDurationEndSyncedOnEndIntervalVar(self, interval_var: "IntervalVar", duration: "int64_t", offset: "int64_t") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var with a fixed duration whose end is
+        synchronized with the end of another interval, with a given
+        offset. The performed status is also in sync with the performed
+        status of the given interval variable.
+        """
+        return _pywrapcp.Solver_FixedDurationEndSyncedOnEndIntervalVar(self, interval_var, duration, offset)
+
+    def IntervalRelaxedMin(self, interval_var: "IntervalVar") -> "operations_research::IntervalVar *":
+        r"""
+         Creates and returns an interval variable that wraps around the given one,
+         relaxing the min start and end. Relaxing means making unbounded when
+         optional. If the variable is non-optional, this method returns
+         interval_var.
+
+         More precisely, such an interval variable behaves as follows:
+        When the underlying must be performed, the returned interval variable
+             behaves exactly as the underlying;
+        When the underlying may or may not be performed, the returned interval
+             variable behaves like the underlying, except that it is unbounded on
+             the min side;
+        When the underlying cannot be performed, the returned interval variable
+             is of duration 0 and must be performed in an interval unbounded on
+             both sides.
+
+         This is very useful to implement propagators that may only modify
+         the start max or end max.
+        """
+        return _pywrapcp.Solver_IntervalRelaxedMin(self, interval_var)
+
+    def IntervalRelaxedMax(self, interval_var: "IntervalVar") -> "operations_research::IntervalVar *":
+        r"""
+         Creates and returns an interval variable that wraps around the given one,
+         relaxing the max start and end. Relaxing means making unbounded when
+         optional. If the variable is non optional, this method returns
+         interval_var.
+
+         More precisely, such an interval variable behaves as follows:
+        When the underlying must be performed, the returned interval variable
+             behaves exactly as the underlying;
+        When the underlying may or may not be performed, the returned interval
+             variable behaves like the underlying, except that it is unbounded on
+             the max side;
+        When the underlying cannot be performed, the returned interval variable
+             is of duration 0 and must be performed in an interval unbounded on
+             both sides.
+
+         This is very useful for implementing propagators that may only modify
+         the start min or end min.
+        """
+        return _pywrapcp.Solver_IntervalRelaxedMax(self, interval_var)
+
+    def TemporalDisjunction(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        This constraint implements a temporal disjunction between two
+        interval vars t1 and t2. 'alt' indicates which alternative was
+        chosen (alt == 0 is equivalent to t1 before t2).
+
+        |
+
+        *Overload 2:*
+        This constraint implements a temporal disjunction between two
+        interval vars.
+        """
+        return _pywrapcp.Solver_TemporalDisjunction(self, *args)
+
+    def DisjunctiveConstraint(self, intervals: "std::vector< operations_research::IntervalVar * > const &", name: "std::string const &") -> "operations_research::DisjunctiveConstraint *":
+        r"""
+        This constraint forces all interval vars into an non-overlapping
+        sequence. Intervals with zero duration can be scheduled anywhere.
+        """
+        return _pywrapcp.Solver_DisjunctiveConstraint(self, intervals, name)
+
+    def Cumulative(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        This constraint forces that, for any integer t, the sum of the demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should only contain non-negative values. Zero values are
+        supported, and the corresponding intervals are filtered out, as they
+        neither impact nor are impacted by this constraint.
+
+        |
+
+        *Overload 2:*
+        This constraint forces that, for any integer t, the sum of the demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should only contain non-negative values. Zero values are
+        supported, and the corresponding intervals are filtered out, as they
+        neither impact nor are impacted by this constraint.
+
+        |
+
+        *Overload 3:*
+        This constraint forces that, for any integer t, the sum of the demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should only contain non-negative values. Zero values are
+        supported, and the corresponding intervals are filtered out, as they
+        neither impact nor are impacted by this constraint.
+
+        |
+
+        *Overload 4:*
+        This constraint enforces that, for any integer t, the sum of the demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should only contain non-negative values. Zero values are
+        supported, and the corresponding intervals are filtered out, as they
+        neither impact nor are impacted by this constraint.
+
+        |
+
+        *Overload 5:*
+        This constraint enforces that, for any integer t, the sum of demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should be positive.
+
+        |
+
+        *Overload 6:*
+        This constraint enforces that, for any integer t, the sum of demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should be positive.
+        """
+        return _pywrapcp.Solver_Cumulative(self, *args)
+
+    def Cover(self, vars: "std::vector< operations_research::IntervalVar * > const &", target_var: "IntervalVar") -> "operations_research::Constraint *":
+        r"""
+        This constraint states that the target_var is the convex hull of
+        the intervals. If none of the interval variables is performed,
+        then the target var is unperformed too. Also, if the target
+        variable is unperformed, then all the intervals variables are
+        unperformed too.
+        """
+        return _pywrapcp.Solver_Cover(self, vars, target_var)
+
+    def Assignment(self, *args) -> "operations_research::Assignment *":
+        r"""
+        *Overload 1:*
+        This method creates an empty assignment.
+
+        |
+
+        *Overload 2:*
+        This method creates an assignment which is a copy of 'a'.
+        """
+        return _pywrapcp.Solver_Assignment(self, *args)
+
+    def FirstSolutionCollector(self, *args) -> "operations_research::SolutionCollector *":
+        r"""
+        *Overload 1:*
+        Collect the first solution of the search.
+
+        |
+
+        *Overload 2:*
+        Collect the first solution of the search. The variables will need to
+        be added later.
+        """
+        return _pywrapcp.Solver_FirstSolutionCollector(self, *args)
+
+    def LastSolutionCollector(self, *args) -> "operations_research::SolutionCollector *":
+        r"""
+        *Overload 1:*
+        Collect the last solution of the search.
+
+        |
+
+        *Overload 2:*
+        Collect the last solution of the search. The variables will need to
+        be added later.
+        """
+        return _pywrapcp.Solver_LastSolutionCollector(self, *args)
+
+    def BestValueSolutionCollector(self, *args) -> "operations_research::SolutionCollector *":
+        r"""
+        *Overload 1:*
+        Collect the solution corresponding to the optimal value of the objective
+        of 'assignment'; if 'assignment' does not have an objective no solution is
+        collected. This collector only collects one solution corresponding to the
+        best objective value (the first one found).
+
+        |
+
+        *Overload 2:*
+        Collect the solution corresponding to the optimal value of the
+        objective of 'assignment'; if 'assignment' does not have an objective no
+        solution is collected. This collector only collects one solution
+        corresponding to the best objective value (the first one
+        found). The variables will need to be added later.
+        """
+        return _pywrapcp.Solver_BestValueSolutionCollector(self, *args)
+
+    def AllSolutionCollector(self, *args) -> "operations_research::SolutionCollector *":
+        r"""
+        *Overload 1:*
+        Collect all solutions of the search.
+
+        |
+
+        *Overload 2:*
+        Collect all solutions of the search. The variables will need to
+        be added later.
+        """
+        return _pywrapcp.Solver_AllSolutionCollector(self, *args)
+
+    def Minimize(self, v: "IntVar", step: "int64_t") -> "operations_research::OptimizeVar *":
+        r""" Creates a minimization objective."""
+        return _pywrapcp.Solver_Minimize(self, v, step)
+
+    def Maximize(self, v: "IntVar", step: "int64_t") -> "operations_research::OptimizeVar *":
+        r""" Creates a maximization objective."""
+        return _pywrapcp.Solver_Maximize(self, v, step)
+
+    def Optimize(self, maximize: "bool", v: "IntVar", step: "int64_t") -> "operations_research::OptimizeVar *":
+        r""" Creates a objective with a given sense (true = maximization)."""
+        return _pywrapcp.Solver_Optimize(self, maximize, v, step)
+
+    def WeightedMinimize(self, *args) -> "operations_research::OptimizeVar *":
+        r"""
+        *Overload 1:*
+        Creates a minimization weighted objective. The actual objective is
+        scalar_prod(sub_objectives, weights).
+
+        |
+
+        *Overload 2:*
+        Creates a minimization weighted objective. The actual objective is
+        scalar_prod(sub_objectives, weights).
+        """
+        return _pywrapcp.Solver_WeightedMinimize(self, *args)
+
+    def WeightedMaximize(self, *args) -> "operations_research::OptimizeVar *":
+        r"""
+        *Overload 1:*
+        Creates a maximization weigthed objective.
+
+        |
+
+        *Overload 2:*
+        Creates a maximization weigthed objective.
+        """
+        return _pywrapcp.Solver_WeightedMaximize(self, *args)
+
+    def WeightedOptimize(self, *args) -> "operations_research::OptimizeVar *":
+        r"""
+        *Overload 1:*
+        Creates a weighted objective with a given sense (true = maximization).
+
+        |
+
+        *Overload 2:*
+        Creates a weighted objective with a given sense (true = maximization).
+        """
+        return _pywrapcp.Solver_WeightedOptimize(self, *args)
+
+    def TabuSearch(self, maximize: "bool", v: "IntVar", step: "int64_t", vars: "std::vector< operations_research::IntVar * > const &", keep_tenure: "int64_t", forbid_tenure: "int64_t", tabu_factor: "double") -> "operations_research::SearchMonitor *":
+        r"""
+        MetaHeuristics which try to get the search out of local optima.
+        Creates a Tabu Search monitor.
+        In the context of local search the behavior is similar to MakeOptimize(),
+        creating an objective in a given sense. The behavior differs once a local
+        optimum is reached: thereafter solutions which degrade the value of the
+        objective are allowed if they are not "tabu". A solution is "tabu" if it
+        doesn't respect the following rules:
+        - improving the best solution found so far
+        - variables in the "keep" list must keep their value, variables in the
+        "forbid" list must not take the value they have in the list.
+        Variables with new values enter the tabu lists after each new solution
+        found and leave the lists after a given number of iterations (called
+        tenure). Only the variables passed to the method can enter the lists.
+        The tabu criterion is softened by the tabu factor which gives the number
+        of "tabu" violations which is tolerated; a factor of 1 means no violations
+        allowed; a factor of 0 means all violations are allowed.
+        """
+        return _pywrapcp.Solver_TabuSearch(self, maximize, v, step, vars, keep_tenure, forbid_tenure, tabu_factor)
+
+    def SimulatedAnnealing(self, maximize: "bool", v: "IntVar", step: "int64_t", initial_temperature: "int64_t") -> "operations_research::SearchMonitor *":
+        r""" Creates a Simulated Annealing monitor."""
+        return _pywrapcp.Solver_SimulatedAnnealing(self, maximize, v, step, initial_temperature)
+
+    def LubyRestart(self, scale_factor: "int") -> "operations_research::SearchMonitor *":
+        r"""
+        This search monitor will restart the search periodically.
+        At the iteration n, it will restart after scale_factor * Luby(n) failures
+        where Luby is the Luby Strategy (i.e. 1 1 2 1 1 2 4 1 1 2 1 1 2 4 8...).
+        """
+        return _pywrapcp.Solver_LubyRestart(self, scale_factor)
+
+    def ConstantRestart(self, frequency: "int") -> "operations_research::SearchMonitor *":
+        r"""
+        This search monitor will restart the search periodically after 'frequency'
+        failures.
+        """
+        return _pywrapcp.Solver_ConstantRestart(self, frequency)
+
+    def TimeLimit(self, *args) -> "operations_research::RegularLimit *":
+        return _pywrapcp.Solver_TimeLimit(self, *args)
+
+    def BranchesLimit(self, branches: "int64_t") -> "operations_research::RegularLimit *":
+        r"""
+        Creates a search limit that constrains the number of branches
+        explored in the search tree.
+        """
+        return _pywrapcp.Solver_BranchesLimit(self, branches)
+
+    def FailuresLimit(self, failures: "int64_t") -> "operations_research::RegularLimit *":
+        r"""
+        Creates a search limit that constrains the number of failures
+        that can happen when exploring the search tree.
+        """
+        return _pywrapcp.Solver_FailuresLimit(self, failures)
+
+    def SolutionsLimit(self, solutions: "int64_t") -> "operations_research::RegularLimit *":
+        r"""
+        Creates a search limit that constrains the number of solutions found
+        during the search.
+        """
+        return _pywrapcp.Solver_SolutionsLimit(self, solutions)
+
+    def Limit(self, *args) -> "operations_research::SearchLimit *":
+        r"""
+        *Overload 1:*
+        Limits the search with the 'time', 'branches', 'failures' and
+        'solutions' limits. 'smart_time_check' reduces the calls to the wall
+
+        |
+
+        *Overload 2:*
+        Creates a search limit from its protobuf description
+
+        |
+
+        *Overload 3:*
+        Creates a search limit that is reached when either of the underlying limit
+        is reached. That is, the returned limit is more stringent than both
+        argument limits.
+        """
+        return _pywrapcp.Solver_Limit(self, *args)
+
+    def CustomLimit(self, limiter: "std::function< bool () >") -> "operations_research::SearchLimit *":
+        r"""
+        Callback-based search limit. Search stops when limiter returns true; if
+        this happens at a leaf the corresponding solution will be rejected.
+        """
+        return _pywrapcp.Solver_CustomLimit(self, limiter)
+
+    def SearchLog(self, *args) -> "operations_research::SearchMonitor *":
+        return _pywrapcp.Solver_SearchLog(self, *args)
+
+    def SearchTrace(self, prefix: "std::string const &") -> "operations_research::SearchMonitor *":
+        r"""
+        Creates a search monitor that will trace precisely the behavior of the
+        search. Use this only for low level debugging.
+        """
+        return _pywrapcp.Solver_SearchTrace(self, prefix)
+
+    def PrintModelVisitor(self) -> "operations_research::ModelVisitor *":
+        r""" Prints the model."""
+        return _pywrapcp.Solver_PrintModelVisitor(self)
+
+    def StatisticsModelVisitor(self) -> "operations_research::ModelVisitor *":
+        r""" Displays some nice statistics on the model."""
+        return _pywrapcp.Solver_StatisticsModelVisitor(self)
+
+    def AssignVariableValue(self, var: "IntVar", val: "int64_t") -> "operations_research::Decision *":
+        r""" Decisions."""
+        return _pywrapcp.Solver_AssignVariableValue(self, var, val)
+
+    def VariableLessOrEqualValue(self, var: "IntVar", value: "int64_t") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_VariableLessOrEqualValue(self, var, value)
+
+    def VariableGreaterOrEqualValue(self, var: "IntVar", value: "int64_t") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_VariableGreaterOrEqualValue(self, var, value)
+
+    def SplitVariableDomain(self, var: "IntVar", val: "int64_t", start_with_lower_half: "bool") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_SplitVariableDomain(self, var, val, start_with_lower_half)
+
+    def AssignVariableValueOrFail(self, var: "IntVar", value: "int64_t") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_AssignVariableValueOrFail(self, var, value)
+
+    def AssignVariablesValues(self, vars: "std::vector< operations_research::IntVar * > const &", values: "std::vector< int64_t > const &") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_AssignVariablesValues(self, vars, values)
+
+    def FailDecision(self) -> "operations_research::Decision *":
+        return _pywrapcp.Solver_FailDecision(self)
+
+    def Decision(self, apply: "operations_research::Solver::Action", refute: "operations_research::Solver::Action") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_Decision(self, apply, refute)
+
+    def Compose(self, dbs: "std::vector< operations_research::DecisionBuilder * > const &") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_Compose(self, dbs)
+
+    def Try(self, dbs: "std::vector< operations_research::DecisionBuilder * > const &") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_Try(self, dbs)
+
+    def DefaultPhase(self, *args) -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_DefaultPhase(self, *args)
+
+    def ScheduleOrPostpone(self, var: "IntervalVar", est: "int64_t", marker: "int64_t *const") -> "operations_research::Decision *":
+        r"""
+        Returns a decision that tries to schedule a task at a given time.
+        On the Apply branch, it will set that interval var as performed and set
+        its start to 'est'. On the Refute branch, it will just update the
+        'marker' to 'est' + 1. This decision is used in the
+        INTERVAL_SET_TIMES_FORWARD strategy.
+        """
+        return _pywrapcp.Solver_ScheduleOrPostpone(self, var, est, marker)
+
+    def ScheduleOrExpedite(self, var: "IntervalVar", est: "int64_t", marker: "int64_t *const") -> "operations_research::Decision *":
+        r"""
+        Returns a decision that tries to schedule a task at a given time.
+        On the Apply branch, it will set that interval var as performed and set
+        its end to 'est'. On the Refute branch, it will just update the
+        'marker' to 'est' - 1. This decision is used in the
+        INTERVAL_SET_TIMES_BACKWARD strategy.
+        """
+        return _pywrapcp.Solver_ScheduleOrExpedite(self, var, est, marker)
+
+    def RankFirstInterval(self, sequence: "SequenceVar", index: "int") -> "operations_research::Decision *":
+        r"""
+        Returns a decision that tries to rank first the ith interval var
+        in the sequence variable.
+        """
+        return _pywrapcp.Solver_RankFirstInterval(self, sequence, index)
+
+    def RankLastInterval(self, sequence: "SequenceVar", index: "int") -> "operations_research::Decision *":
+        r"""
+        Returns a decision that tries to rank last the ith interval var
+        in the sequence variable.
+        """
+        return _pywrapcp.Solver_RankLastInterval(self, sequence, index)
+
+    def Phase(self, *args) -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_Phase(self, *args)
+
+    def DecisionBuilderFromAssignment(self, assignment: "Assignment", db: "DecisionBuilder", vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::DecisionBuilder *":
+        r"""
+        Returns a decision builder for which the left-most leaf corresponds
+        to assignment, the rest of the tree being explored using 'db'.
+        """
+        return _pywrapcp.Solver_DecisionBuilderFromAssignment(self, assignment, db, vars)
+
+    def ConstraintAdder(self, ct: "Constraint") -> "operations_research::DecisionBuilder *":
+        r"""
+        Returns a decision builder that will add the given constraint to
+        the model.
+        """
+        return _pywrapcp.Solver_ConstraintAdder(self, ct)
+
+    def SolveOnce(self, db: "DecisionBuilder", monitors: "std::vector< operations_research::SearchMonitor * > const &") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_SolveOnce(self, db, monitors)
+
+    def NestedOptimize(self, *args) -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_NestedOptimize(self, *args)
+
+    def RestoreAssignment(self, assignment: "Assignment") -> "operations_research::DecisionBuilder *":
+        r"""
+        Returns a DecisionBuilder which restores an Assignment
+        (calls void Assignment::Restore())
+        """
+        return _pywrapcp.Solver_RestoreAssignment(self, assignment)
+
+    def StoreAssignment(self, assignment: "Assignment") -> "operations_research::DecisionBuilder *":
+        r"""
+        Returns a DecisionBuilder which stores an Assignment
+        (calls void Assignment::Store())
+        """
+        return _pywrapcp.Solver_StoreAssignment(self, assignment)
+
+    def Operator(self, *args) -> "operations_research::LocalSearchOperator *":
+        return _pywrapcp.Solver_Operator(self, *args)
+
+    def RandomLnsOperator(self, *args) -> "operations_research::LocalSearchOperator *":
+        return _pywrapcp.Solver_RandomLnsOperator(self, *args)
+
+    def MoveTowardTargetOperator(self, *args) -> "operations_research::LocalSearchOperator *":
+        r"""
+        *Overload 1:*
+        Creates a local search operator that tries to move the assignment of some
+        variables toward a target. The target is given as an Assignment. This
+        operator generates neighbors in which the only difference compared to the
+        current state is that one variable that belongs to the target assignment
+        is set to its target value.
+
+        |
+
+        *Overload 2:*
+        Creates a local search operator that tries to move the assignment of some
+        variables toward a target. The target is given either as two vectors: a
+        vector of variables and a vector of associated target values. The two
+        vectors should be of the same length. This operator generates neighbors in
+        which the only difference compared to the current state is that one
+        variable that belongs to the given vector is set to its target value.
+        """
+        return _pywrapcp.Solver_MoveTowardTargetOperator(self, *args)
+
+    def ConcatenateOperators(self, *args) -> "operations_research::LocalSearchOperator *":
+        return _pywrapcp.Solver_ConcatenateOperators(self, *args)
+
+    def RandomConcatenateOperators(self, *args) -> "operations_research::LocalSearchOperator *":
+        r"""
+        *Overload 1:*
+        Randomized version of local search concatenator; calls a random operator
+        at each call to MakeNextNeighbor().
+
+        |
+
+        *Overload 2:*
+        Randomized version of local search concatenator; calls a random operator
+        at each call to MakeNextNeighbor(). The provided seed is used to
+        initialize the random number generator.
+        """
+        return _pywrapcp.Solver_RandomConcatenateOperators(self, *args)
+
+    def NeighborhoodLimit(self, op: "LocalSearchOperator", limit: "int64_t") -> "operations_research::LocalSearchOperator *":
+        r"""
+        Creates a local search operator that wraps another local search
+        operator and limits the number of neighbors explored (i.e., calls
+        to MakeNextNeighbor from the current solution (between two calls
+        to Start()). When this limit is reached, MakeNextNeighbor()
+        returns false. The counter is cleared when Start() is called.
+        """
+        return _pywrapcp.Solver_NeighborhoodLimit(self, op, limit)
+
+    def LocalSearchPhase(self, *args) -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_LocalSearchPhase(self, *args)
+
+    def LocalSearchPhaseParameters(self, *args) -> "operations_research::LocalSearchPhaseParameters *":
+        return _pywrapcp.Solver_LocalSearchPhaseParameters(self, *args)
+
+    def SearchDepth(self) -> "int":
+        r"""
+        Gets the search depth of the current active search. Returns -1 if
+        there is no active search opened.
+        """
+        return _pywrapcp.Solver_SearchDepth(self)
+
+    def SearchLeftDepth(self) -> "int":
+        r"""
+        Gets the search left depth of the current active search. Returns -1 if
+        there is no active search opened.
+        """
+        return _pywrapcp.Solver_SearchLeftDepth(self)
+
+    def SolveDepth(self) -> "int":
+        r"""
+        Gets the number of nested searches. It returns 0 outside search,
+        1 during the top level search, 2 or more in case of nested searches.
+        """
+        return _pywrapcp.Solver_SolveDepth(self)
+
+    def Rand64(self, size: "int64_t") -> "int64_t":
+        r""" Returns a random value between 0 and 'size' - 1;"""
+        return _pywrapcp.Solver_Rand64(self, size)
+
+    def Rand32(self, size: "int32_t") -> "int32_t":
+        r""" Returns a random value between 0 and 'size' - 1;"""
+        return _pywrapcp.Solver_Rand32(self, size)
+
+    def ReSeed(self, seed: "int32_t") -> "void":
+        r""" Reseed the solver random generator."""
+        return _pywrapcp.Solver_ReSeed(self, seed)
+
+    def LocalSearchProfile(self) -> "std::string":
+        r""" Returns local search profiling information in a human readable format."""
+        return _pywrapcp.Solver_LocalSearchProfile(self)
+
+    def Constraints(self) -> "int":
+        r"""
+        Counts the number of constraints that have been added
+        to the solver before the search.
+        """
+        return _pywrapcp.Solver_Constraints(self)
+
+    def Accept(self, visitor: "operations_research::ModelVisitor *const") -> "void":
+        r""" Accepts the given model visitor."""
+        return _pywrapcp.Solver_Accept(self, visitor)
+
+    def FinishCurrentSearch(self) -> "void":
+        r""" Tells the solver to kill or restart the current search."""
+        return _pywrapcp.Solver_FinishCurrentSearch(self)
+
+    def RestartCurrentSearch(self) -> "void":
+        return _pywrapcp.Solver_RestartCurrentSearch(self)
+
+    def ShouldFail(self) -> "void":
+        r"""
+        These methods are only useful for the SWIG wrappers, which need a way
+        to externally cause the Solver to fail.
+        """
+        return _pywrapcp.Solver_ShouldFail(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.Solver___str__(self)
+
+    def Add(self, ct):
+      if isinstance(ct, PyConstraint):
+        self.__python_constraints.append(ct)
+      self.AddConstraint(ct)
+
+
+    def TreeNoCycle(self, nexts: "std::vector< operations_research::IntVar * > const &", active: "std::vector< operations_research::IntVar * > const &", callback: "operations_research::Solver::IndexFilter1"=0) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_TreeNoCycle(self, nexts, active, callback)
+
+    def SearchLogWithCallback(self, period: "int", callback: "std::function< std::string () >") -> "operations_research::SearchMonitor *":
+        return _pywrapcp.Solver_SearchLogWithCallback(self, period, callback)
+
+    def ElementFunction(self, values: "std::function< int64_t (int64_t) >", index: "IntVar") -> "operations_research::IntExpr *":
+        return _pywrapcp.Solver_ElementFunction(self, values, index)
+
+    def VarEvalValStrPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_evaluator: "std::function< int64_t (int64_t) >", val_str: "operations_research::Solver::IntValueStrategy") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarEvalValStrPhase(self, vars, var_evaluator, val_str)
+
+    def VarStrValEvalPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_str: "operations_research::Solver::IntVarStrategy", val_eval: "operations_research::Solver::IndexEvaluator2") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarStrValEvalPhase(self, vars, var_str, val_eval)
+
+    def VarEvalValEvalPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_eval: "std::function< int64_t (int64_t) >", val_eval: "operations_research::Solver::IndexEvaluator2") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarEvalValEvalPhase(self, vars, var_eval, val_eval)
+
+    def VarStrValEvalTieBreakPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_str: "operations_research::Solver::IntVarStrategy", val_eval: "operations_research::Solver::IndexEvaluator2", tie_breaker: "std::function< int64_t (int64_t) >") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarStrValEvalTieBreakPhase(self, vars, var_str, val_eval, tie_breaker)
+
+    def VarEvalValEvalTieBreakPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_eval: "std::function< int64_t (int64_t) >", val_eval: "operations_research::Solver::IndexEvaluator2", tie_breaker: "std::function< int64_t (int64_t) >") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarEvalValEvalTieBreakPhase(self, vars, var_eval, val_eval, tie_breaker)
+
+    def EvalEvalStrPhase(self, vars: "std::vector< operations_research::IntVar * > const &", evaluator: "operations_research::Solver::IndexEvaluator2", str: "operations_research::Solver::EvaluatorStrategy") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_EvalEvalStrPhase(self, vars, evaluator, str)
+
+    def EvalEvalStrTieBreakPhase(self, vars: "std::vector< operations_research::IntVar * > const &", evaluator: "operations_research::Solver::IndexEvaluator2", tie_breaker: "operations_research::Solver::IndexEvaluator1", str: "operations_research::Solver::EvaluatorStrategy") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_EvalEvalStrTieBreakPhase(self, vars, evaluator, tie_breaker, str)
+
+    def GuidedLocalSearch(self, *args) -> "operations_research::SearchMonitor *":
+        return _pywrapcp.Solver_GuidedLocalSearch(self, *args)
+
+    def SumObjectiveFilter(self, vars: "std::vector< operations_research::IntVar * > const &", values: "operations_research::Solver::IndexEvaluator2", filter_enum: "operations_research::Solver::LocalSearchFilterBound") -> "operations_research::LocalSearchFilter *":
+        return _pywrapcp.Solver_SumObjectiveFilter(self, vars, values, filter_enum)
+
+# Register Solver in _pywrapcp:
+_pywrapcp.Solver_swigregister(Solver)
+
+def Solver_DefaultSolverParameters() -> "operations_research::ConstraintSolverParameters":
+    r""" Create a ConstraintSolverParameters proto with all the default values."""
+    return _pywrapcp.Solver_DefaultSolverParameters()
+
+def Solver_MemoryUsage() -> "int64_t":
+    r""" Current memory usage in bytes"""
+    return _pywrapcp.Solver_MemoryUsage()
+
+class BaseObject(object):
+    r"""
+    A BaseObject is the root of all reversibly allocated objects.
+    A DebugString method and the associated << operator are implemented
+    as a convenience.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self):
+        if self.__class__ == BaseObject:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.BaseObject_swiginit(self, _pywrapcp.new_BaseObject(_self, ))
+    __swig_destroy__ = _pywrapcp.delete_BaseObject
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.BaseObject_DebugString(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.BaseObject___str__(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.BaseObject___repr__(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_BaseObject(self)
+        return weakref.proxy(self)
+
+# Register BaseObject in _pywrapcp:
+_pywrapcp.BaseObject_swigregister(BaseObject)
+
+class PropagationBaseObject(BaseObject):
+    r"""
+    NOLINT
+    The PropagationBaseObject is a subclass of BaseObject that is also
+    friend to the Solver class. It allows accessing methods useful when
+    writing new constraints or new expressions.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, s: "Solver"):
+        if self.__class__ == PropagationBaseObject:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.PropagationBaseObject_swiginit(self, _pywrapcp.new_PropagationBaseObject(_self, s))
+    __swig_destroy__ = _pywrapcp.delete_PropagationBaseObject
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.PropagationBaseObject_DebugString(self)
+
+    def solver(self) -> "operations_research::Solver *":
+        return _pywrapcp.PropagationBaseObject_solver(self)
+
+    def Name(self) -> "std::string":
+        r""" Object naming."""
+        return _pywrapcp.PropagationBaseObject_Name(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_PropagationBaseObject(self)
+        return weakref.proxy(self)
+
+# Register PropagationBaseObject in _pywrapcp:
+_pywrapcp.PropagationBaseObject_swigregister(PropagationBaseObject)
+
+class Decision(BaseObject):
+    r"""
+    A Decision represents a choice point in the search tree. The two main
+    methods are Apply() to go left, or Refute() to go right.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self):
+        if self.__class__ == Decision:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.Decision_swiginit(self, _pywrapcp.new_Decision(_self, ))
+    __swig_destroy__ = _pywrapcp.delete_Decision
+
+    def ApplyWrapper(self, s: "Solver") -> "void":
+        r""" Apply will be called first when the decision is executed."""
+        return _pywrapcp.Decision_ApplyWrapper(self, s)
+
+    def RefuteWrapper(self, s: "Solver") -> "void":
+        r""" Refute will be called after a backtrack."""
+        return _pywrapcp.Decision_RefuteWrapper(self, s)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.Decision_DebugString(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.Decision___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.Decision___str__(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_Decision(self)
+        return weakref.proxy(self)
+
+# Register Decision in _pywrapcp:
+_pywrapcp.Decision_swigregister(Decision)
+
+class DecisionBuilder(BaseObject):
+    r"""
+    A DecisionBuilder is responsible for creating the search tree. The
+    important method is Next(), which returns the next decision to execute.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self):
+        if self.__class__ == DecisionBuilder:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.DecisionBuilder_swiginit(self, _pywrapcp.new_DecisionBuilder(_self, ))
+    __swig_destroy__ = _pywrapcp.delete_DecisionBuilder
+
+    def NextWrapper(self, s: "Solver") -> "operations_research::Decision *":
+        r"""
+        This is the main method of the decision builder class. It must
+        return a decision (an instance of the class Decision). If it
+        returns nullptr, this means that the decision builder has finished
+        its work.
+        """
+        return _pywrapcp.DecisionBuilder_NextWrapper(self, s)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.DecisionBuilder_DebugString(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.DecisionBuilder___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.DecisionBuilder___str__(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_DecisionBuilder(self)
+        return weakref.proxy(self)
+
+# Register DecisionBuilder in _pywrapcp:
+_pywrapcp.DecisionBuilder_swigregister(DecisionBuilder)
+
+class Demon(BaseObject):
+    r"""
+    A Demon is the base element of a propagation queue. It is the main
+      object responsible for implementing the actual propagation
+      of the constraint and pruning the inconsistent values in the domains
+      of the variables. The main concept is that demons are listeners that are
+      attached to the variables and listen to their modifications.
+    There are two methods:
+     - Run() is the actual method called when the demon is processed.
+     - priority() returns its priority. Standard priorities are slow, normal
+       or fast. "immediate" is reserved for variables and is treated separately.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self):
+        r"""
+        This indicates the priority of a demon. Immediate demons are treated
+        separately and corresponds to variables.
+        """
+        if self.__class__ == Demon:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.Demon_swiginit(self, _pywrapcp.new_Demon(_self, ))
+    __swig_destroy__ = _pywrapcp.delete_Demon
+
+    def RunWrapper(self, s: "Solver") -> "void":
+        r""" This is the main callback of the demon."""
+        return _pywrapcp.Demon_RunWrapper(self, s)
+
+    def Priority(self) -> "operations_research::Solver::DemonPriority":
+        r"""
+        This method returns the priority of the demon. Usually a demon is
+        fast, slow or normal. Immediate demons are reserved for internal
+        use to maintain variables.
+        """
+        return _pywrapcp.Demon_Priority(self)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.Demon_DebugString(self)
+
+    def Inhibit(self, s: "Solver") -> "void":
+        r"""
+        This method inhibits the demon in the search tree below the
+        current position.
+        """
+        return _pywrapcp.Demon_Inhibit(self, s)
+
+    def Desinhibit(self, s: "Solver") -> "void":
+        r""" This method un-inhibits the demon that was previously inhibited."""
+        return _pywrapcp.Demon_Desinhibit(self, s)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_Demon(self)
+        return weakref.proxy(self)
+
+# Register Demon in _pywrapcp:
+_pywrapcp.Demon_swigregister(Demon)
+
+class Constraint(PropagationBaseObject):
+    r"""
+    A constraint is the main modeling object. It provides two methods:
+      - Post() is responsible for creating the demons and attaching them to
+        immediate demons().
+      - InitialPropagate() is called once just after Post and performs
+        the initial propagation. The subsequent propagations will be performed
+        by the demons Posted during the post() method.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, solver: "Solver"):
+        if self.__class__ == Constraint:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.Constraint_swiginit(self, _pywrapcp.new_Constraint(_self, solver))
+    __swig_destroy__ = _pywrapcp.delete_Constraint
+
+    def Post(self) -> "void":
+        r"""
+        This method is called when the constraint is processed by the
+        solver. Its main usage is to attach demons to variables.
+        """
+        return _pywrapcp.Constraint_Post(self)
+
+    def InitialPropagateWrapper(self) -> "void":
+        r"""
+        This method performs the initial propagation of the
+        constraint. It is called just after the post.
+        """
+        return _pywrapcp.Constraint_InitialPropagateWrapper(self)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.Constraint_DebugString(self)
+
+    def Var(self) -> "operations_research::IntVar *":
+        r"""
+        Creates a Boolean variable representing the status of the constraint
+        (false = constraint is violated, true = constraint is satisfied). It
+        returns nullptr if the constraint does not support this API.
+        """
+        return _pywrapcp.Constraint_Var(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.Constraint___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.Constraint___str__(self)
+
+    def __add__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___add__(self, *args)
+
+    def __radd__(self, v: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___radd__(self, v)
+
+    def __sub__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___sub__(self, *args)
+
+    def __rsub__(self, v: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___rsub__(self, v)
+
+    def __mul__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___mul__(self, *args)
+
+    def __rmul__(self, v: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___rmul__(self, v)
+
+    def __floordiv__(self, v: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___floordiv__(self, v)
+
+    def __neg__(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___neg__(self)
+
+    def __abs__(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___abs__(self)
+
+    def Square(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint_Square(self)
+
+    def __eq__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint___eq__(self, *args)
+
+    def __ne__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint___ne__(self, *args)
+
+    def __ge__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint___ge__(self, *args)
+
+    def __gt__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint___gt__(self, *args)
+
+    def __le__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint___le__(self, *args)
+
+    def __lt__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint___lt__(self, *args)
+
+    def MapTo(self, vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint_MapTo(self, vars)
+
+    def IndexOf(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint_IndexOf(self, *args)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_Constraint(self)
+        return weakref.proxy(self)
+
+# Register Constraint in _pywrapcp:
+_pywrapcp.Constraint_swigregister(Constraint)
+
+class SearchMonitor(BaseObject):
+    r""" A search monitor is a simple set of callbacks to monitor all search events"""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, s: "Solver"):
+        if self.__class__ == SearchMonitor:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.SearchMonitor_swiginit(self, _pywrapcp.new_SearchMonitor(_self, s))
+    __swig_destroy__ = _pywrapcp.delete_SearchMonitor
+
+    def EnterSearch(self) -> "void":
+        r""" Beginning of the search."""
+        return _pywrapcp.SearchMonitor_EnterSearch(self)
+
+    def RestartSearch(self) -> "void":
+        r""" Restart the search."""
+        return _pywrapcp.SearchMonitor_RestartSearch(self)
+
+    def ExitSearch(self) -> "void":
+        r""" End of the search."""
+        return _pywrapcp.SearchMonitor_ExitSearch(self)
+
+    def BeginNextDecision(self, b: "DecisionBuilder") -> "void":
+        r""" Before calling DecisionBuilder::Next."""
+        return _pywrapcp.SearchMonitor_BeginNextDecision(self, b)
+
+    def EndNextDecision(self, b: "DecisionBuilder", d: "Decision") -> "void":
+        r""" After calling DecisionBuilder::Next, along with the returned decision."""
+        return _pywrapcp.SearchMonitor_EndNextDecision(self, b, d)
+
+    def ApplyDecision(self, d: "Decision") -> "void":
+        r""" Before applying the decision."""
+        return _pywrapcp.SearchMonitor_ApplyDecision(self, d)
+
+    def RefuteDecision(self, d: "Decision") -> "void":
+        r""" Before refuting the decision."""
+        return _pywrapcp.SearchMonitor_RefuteDecision(self, d)
+
+    def AfterDecision(self, d: "Decision", apply: "bool") -> "void":
+        r"""
+        Just after refuting or applying the decision, apply is true after Apply.
+        This is called only if the Apply() or Refute() methods have not failed.
+        """
+        return _pywrapcp.SearchMonitor_AfterDecision(self, d, apply)
+
+    def BeginFail(self) -> "void":
+        r""" Just when the failure occurs."""
+        return _pywrapcp.SearchMonitor_BeginFail(self)
+
+    def EndFail(self) -> "void":
+        r""" After completing the backtrack."""
+        return _pywrapcp.SearchMonitor_EndFail(self)
+
+    def BeginInitialPropagation(self) -> "void":
+        r""" Before the initial propagation."""
+        return _pywrapcp.SearchMonitor_BeginInitialPropagation(self)
+
+    def EndInitialPropagation(self) -> "void":
+        r""" After the initial propagation."""
+        return _pywrapcp.SearchMonitor_EndInitialPropagation(self)
+
+    def AcceptSolution(self) -> "bool":
+        r"""
+        This method is called when a solution is found. It asserts whether the
+        solution is valid. A value of false indicates that the solution
+        should be discarded.
+        """
+        return _pywrapcp.SearchMonitor_AcceptSolution(self)
+
+    def AtSolution(self) -> "bool":
+        r"""
+        This method is called when a valid solution is found. If the
+        return value is true, then search will resume after. If the result
+        is false, then search will stop there.
+        """
+        return _pywrapcp.SearchMonitor_AtSolution(self)
+
+    def NoMoreSolutions(self) -> "void":
+        r""" When the search tree is finished."""
+        return _pywrapcp.SearchMonitor_NoMoreSolutions(self)
+
+    def LocalOptimum(self) -> "bool":
+        r"""
+        When a local optimum is reached. If 'true' is returned, the last solution
+        is discarded and the search proceeds with the next one.
+        """
+        return _pywrapcp.SearchMonitor_LocalOptimum(self)
+
+    def AcceptDelta(self, delta: "Assignment", deltadelta: "Assignment") -> "bool":
+        
+        return _pywrapcp.SearchMonitor_AcceptDelta(self, delta, deltadelta)
+
+    def AcceptNeighbor(self) -> "void":
+        r""" After accepting a neighbor during local search."""
+        return _pywrapcp.SearchMonitor_AcceptNeighbor(self)
+
+    def solver(self) -> "operations_research::Solver *":
+        return _pywrapcp.SearchMonitor_solver(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.SearchMonitor___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.SearchMonitor___str__(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_SearchMonitor(self)
+        return weakref.proxy(self)
+
+# Register SearchMonitor in _pywrapcp:
+_pywrapcp.SearchMonitor_swigregister(SearchMonitor)
+
+class IntExpr(PropagationBaseObject):
+    r"""
+    The class IntExpr is the base of all integer expressions in
+    constraint programming.
+    It contains the basic protocol for an expression:
+      - setting and modifying its bound
+      - querying if it is bound
+      - listening to events modifying its bounds
+      - casting it into a variable (instance of IntVar)
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+    def Min(self) -> "int64_t":
+        return _pywrapcp.IntExpr_Min(self)
+
+    def SetMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntExpr_SetMin(self, m)
+
+    def Max(self) -> "int64_t":
+        return _pywrapcp.IntExpr_Max(self)
+
+    def SetMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntExpr_SetMax(self, m)
+
+    def SetRange(self, l: "int64_t", u: "int64_t") -> "void":
+        r""" This method sets both the min and the max of the expression."""
+        return _pywrapcp.IntExpr_SetRange(self, l, u)
+
+    def SetValue(self, v: "int64_t") -> "void":
+        r""" This method sets the value of the expression."""
+        return _pywrapcp.IntExpr_SetValue(self, v)
+
+    def Bound(self) -> "bool":
+        r""" Returns true if the min and the max of the expression are equal."""
+        return _pywrapcp.IntExpr_Bound(self)
+
+    def IsVar(self) -> "bool":
+        r""" Returns true if the expression is indeed a variable."""
+        return _pywrapcp.IntExpr_IsVar(self)
+
+    def Var(self) -> "operations_research::IntVar *":
+        r""" Creates a variable from the expression."""
+        return _pywrapcp.IntExpr_Var(self)
+
+    def VarWithName(self, name: "std::string const &") -> "operations_research::IntVar *":
+        r"""
+        Creates a variable from the expression and set the name of the
+        resulting var. If the expression is already a variable, then it
+        will set the name of the expression, possibly overwriting it.
+        This is just a shortcut to Var() followed by set_name().
+        """
+        return _pywrapcp.IntExpr_VarWithName(self, name)
+
+    def WhenRange(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        Attach a demon that will watch the min or the max of the expression.
+
+        |
+
+        *Overload 2:*
+        Attach a demon that will watch the min or the max of the expression.
+        """
+        return _pywrapcp.IntExpr_WhenRange(self, *args)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.IntExpr___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.IntExpr___str__(self)
+
+    def __add__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___add__(self, *args)
+
+    def __radd__(self, v: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___radd__(self, v)
+
+    def __sub__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___sub__(self, *args)
+
+    def __rsub__(self, v: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___rsub__(self, v)
+
+    def __mul__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___mul__(self, *args)
+
+    def __rmul__(self, v: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___rmul__(self, v)
+
+    def __floordiv__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___floordiv__(self, *args)
+
+    def __mod__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___mod__(self, *args)
+
+    def __neg__(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___neg__(self)
+
+    def __abs__(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___abs__(self)
+
+    def Square(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr_Square(self)
+
+    def __eq__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr___eq__(self, *args)
+
+    def __ne__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr___ne__(self, *args)
+
+    def __ge__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr___ge__(self, *args)
+
+    def __gt__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr___gt__(self, *args)
+
+    def __le__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr___le__(self, *args)
+
+    def __lt__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr___lt__(self, *args)
+
+    def MapTo(self, vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr_MapTo(self, vars)
+
+    def IndexOf(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr_IndexOf(self, *args)
+
+    def IsMember(self, values: "std::vector< int64_t > const &") -> "operations_research::IntVar *":
+        return _pywrapcp.IntExpr_IsMember(self, values)
+
+    def Member(self, values: "std::vector< int64_t > const &") -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr_Member(self, values)
+
+    def NotMember(self, starts: "std::vector< int64_t > const &", ends: "std::vector< int64_t > const &") -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr_NotMember(self, starts, ends)
+
+# Register IntExpr in _pywrapcp:
+_pywrapcp.IntExpr_swigregister(IntExpr)
+
+class IntVarIterator(BaseObject):
+    r"""
+     The class Iterator has two direct subclasses. HoleIterators
+     iterates over all holes, that is value removed between the
+     current min and max of the variable since the last time the
+     variable was processed in the queue. DomainIterators iterates
+     over all elements of the variable domain. Both iterators are not
+     robust to domain changes. Hole iterators can also report values outside
+     the current min and max of the variable.
+     HoleIterators should only be called from a demon attached to the
+     variable that has created this iterator.
+     IntVar* current_var;
+     std::unique_ptr<IntVarIterator> it(current_var->MakeHoleIterator(false));
+     for (const int64_t hole : InitAndGetValues(it)) {
+    use the hole
+     }
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def Init(self) -> "void":
+        r""" This method must be called before each loop."""
+        return _pywrapcp.IntVarIterator_Init(self)
+
+    def Ok(self) -> "bool":
+        r""" This method indicates if we can call Value() or not."""
+        return _pywrapcp.IntVarIterator_Ok(self)
+
+    def Value(self) -> "int64_t":
+        r""" This method returns the current value of the iterator."""
+        return _pywrapcp.IntVarIterator_Value(self)
+
+    def Next(self) -> "void":
+        r""" This method moves the iterator to the next value."""
+        return _pywrapcp.IntVarIterator_Next(self)
+
+    def DebugString(self) -> "std::string":
+        r""" Pretty Print."""
+        return _pywrapcp.IntVarIterator_DebugString(self)
+
+    def __iter__(self):
+      self.Init()
+      return self
+
+    def next(self):
+      if self.Ok():
+        result = self.Value()
+        self.Next()
+        return result
+      else:
+        raise StopIteration()
+
+    def __next__(self):
+      return self.next()
+
+
+# Register IntVarIterator in _pywrapcp:
+_pywrapcp.IntVarIterator_swigregister(IntVarIterator)
+
+class IntVar(IntExpr):
+    r"""
+    The class IntVar is a subset of IntExpr. In addition to the
+    IntExpr protocol, it offers persistence, removing values from the domains,
+    and a finer model for events.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+    def IsVar(self) -> "bool":
+        return _pywrapcp.IntVar_IsVar(self)
+
+    def Var(self) -> "operations_research::IntVar *":
+        return _pywrapcp.IntVar_Var(self)
+
+    def Value(self) -> "int64_t":
+        r"""
+        This method returns the value of the variable. This method checks
+        before that the variable is bound.
+        """
+        return _pywrapcp.IntVar_Value(self)
+
+    def RemoveValue(self, v: "int64_t") -> "void":
+        r""" This method removes the value 'v' from the domain of the variable."""
+        return _pywrapcp.IntVar_RemoveValue(self, v)
+
+    def RemoveInterval(self, l: "int64_t", u: "int64_t") -> "void":
+        r"""
+        This method removes the interval 'l' .. 'u' from the domain of
+        the variable. It assumes that 'l' <= 'u'.
+        """
+        return _pywrapcp.IntVar_RemoveInterval(self, l, u)
+
+    def RemoveValues(self, values: "std::vector< int64_t > const &") -> "void":
+        r""" This method remove the values from the domain of the variable."""
+        return _pywrapcp.IntVar_RemoveValues(self, values)
+
+    def SetValues(self, values: "std::vector< int64_t > const &") -> "void":
+        r""" This method intersects the current domain with the values in the array."""
+        return _pywrapcp.IntVar_SetValues(self, values)
+
+    def WhenBound(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        This method attaches a demon that will be awakened when the
+        variable is bound.
+
+        |
+
+        *Overload 2:*
+        This method attaches a closure that will be awakened when the
+        variable is bound.
+        """
+        return _pywrapcp.IntVar_WhenBound(self, *args)
+
+    def WhenDomain(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        This method attaches a demon that will watch any domain
+        modification of the domain of the variable.
+
+        |
+
+        *Overload 2:*
+        This method attaches a closure that will watch any domain
+        modification of the domain of the variable.
+        """
+        return _pywrapcp.IntVar_WhenDomain(self, *args)
+
+    def Size(self) -> "uint64_t":
+        r""" This method returns the number of values in the domain of the variable."""
+        return _pywrapcp.IntVar_Size(self)
+
+    def Contains(self, v: "int64_t") -> "bool":
+        r"""
+        This method returns whether the value 'v' is in the domain of the
+        variable.
+        """
+        return _pywrapcp.IntVar_Contains(self, v)
+
+    def HoleIteratorAux(self, reversible: "bool") -> "operations_research::IntVarIterator *":
+        r"""
+        Creates a hole iterator. When 'reversible' is false, the returned
+        object is created on the normal C++ heap and the solver does NOT
+        take ownership of the object.
+        """
+        return _pywrapcp.IntVar_HoleIteratorAux(self, reversible)
+
+    def DomainIteratorAux(self, reversible: "bool") -> "operations_research::IntVarIterator *":
+        r"""
+        Creates a domain iterator. When 'reversible' is false, the
+        returned object is created on the normal C++ heap and the solver
+        does NOT take ownership of the object.
+        """
+        return _pywrapcp.IntVar_DomainIteratorAux(self, reversible)
+
+    def OldMin(self) -> "int64_t":
+        r""" Returns the previous min."""
+        return _pywrapcp.IntVar_OldMin(self)
+
+    def OldMax(self) -> "int64_t":
+        r""" Returns the previous max."""
+        return _pywrapcp.IntVar_OldMax(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.IntVar___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.IntVar___str__(self)
+
+    def DomainIterator(self):
+      return iter(self.DomainIteratorAux(False))
+
+    def HoleIterator(self):
+      return iter(self.HoleIteratorAux(False))
+
+
+# Register IntVar in _pywrapcp:
+_pywrapcp.IntVar_swigregister(IntVar)
+
+class SolutionCollector(SearchMonitor):
+    r"""
+    This class is the root class of all solution collectors.
+    It implements a basic query API to be used independently
+    of the collector used.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.SolutionCollector_DebugString(self)
+
+    def Add(self, *args) -> "void":
+        return _pywrapcp.SolutionCollector_Add(self, *args)
+
+    def AddObjective(self, objective: "IntVar") -> "void":
+        return _pywrapcp.SolutionCollector_AddObjective(self, objective)
+
+    def EnterSearch(self) -> "void":
+        r""" Beginning of the search."""
+        return _pywrapcp.SolutionCollector_EnterSearch(self)
+
+    def SolutionCount(self) -> "int":
+        r""" Returns how many solutions were stored during the search."""
+        return _pywrapcp.SolutionCollector_SolutionCount(self)
+
+    def Solution(self, n: "int") -> "operations_research::Assignment *":
+        r""" Returns the nth solution."""
+        return _pywrapcp.SolutionCollector_Solution(self, n)
+
+    def WallTime(self, n: "int") -> "int64_t":
+        r""" Returns the wall time in ms for the nth solution."""
+        return _pywrapcp.SolutionCollector_WallTime(self, n)
+
+    def Branches(self, n: "int") -> "int64_t":
+        r""" Returns the number of branches when the nth solution was found."""
+        return _pywrapcp.SolutionCollector_Branches(self, n)
+
+    def Failures(self, n: "int") -> "int64_t":
+        r"""
+        Returns the number of failures encountered at the time of the nth
+        solution.
+        """
+        return _pywrapcp.SolutionCollector_Failures(self, n)
+
+    def ObjectiveValue(self, n: "int") -> "int64_t":
+        r""" Returns the objective value of the nth solution."""
+        return _pywrapcp.SolutionCollector_ObjectiveValue(self, n)
+
+    def Value(self, n: "int", var: "IntVar") -> "int64_t":
+        r""" This is a shortcut to get the Value of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_Value(self, n, var)
+
+    def StartValue(self, n: "int", var: "IntervalVar") -> "int64_t":
+        r""" This is a shortcut to get the StartValue of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_StartValue(self, n, var)
+
+    def EndValue(self, n: "int", var: "IntervalVar") -> "int64_t":
+        r""" This is a shortcut to get the EndValue of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_EndValue(self, n, var)
+
+    def DurationValue(self, n: "int", var: "IntervalVar") -> "int64_t":
+        r""" This is a shortcut to get the DurationValue of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_DurationValue(self, n, var)
+
+    def PerformedValue(self, n: "int", var: "IntervalVar") -> "int64_t":
+        r""" This is a shortcut to get the PerformedValue of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_PerformedValue(self, n, var)
+
+    def ForwardSequence(self, n: "int", var: "SequenceVar") -> "std::vector< int > const &":
+        r"""
+        This is a shortcut to get the ForwardSequence of 'var' in the
+        nth solution. The forward sequence is the list of ranked interval
+        variables starting from the start of the sequence.
+        """
+        return _pywrapcp.SolutionCollector_ForwardSequence(self, n, var)
+
+    def BackwardSequence(self, n: "int", var: "SequenceVar") -> "std::vector< int > const &":
+        r"""
+        This is a shortcut to get the BackwardSequence of 'var' in the
+        nth solution. The backward sequence is the list of ranked interval
+        variables starting from the end of the sequence.
+        """
+        return _pywrapcp.SolutionCollector_BackwardSequence(self, n, var)
+
+    def Unperformed(self, n: "int", var: "SequenceVar") -> "std::vector< int > const &":
+        r"""
+        This is a shortcut to get the list of unperformed of 'var' in the
+        nth solution.
+        """
+        return _pywrapcp.SolutionCollector_Unperformed(self, n, var)
+
+# Register SolutionCollector in _pywrapcp:
+_pywrapcp.SolutionCollector_swigregister(SolutionCollector)
+
+class OptimizeVar(SearchMonitor):
+    r"""
+    This class encapsulates an objective. It requires the direction
+    (minimize or maximize), the variable to optimize, and the
+    improvement step.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Best(self) -> "int64_t":
+        r""" Returns the best value found during search."""
+        return _pywrapcp.OptimizeVar_Best(self)
+
+    def Var(self) -> "operations_research::IntVar *":
+        r""" Returns the variable that is optimized."""
+        return _pywrapcp.OptimizeVar_Var(self)
+
+    def AcceptDelta(self, delta: "Assignment", deltadelta: "Assignment") -> "bool":
+        r""" Internal methods."""
+        return _pywrapcp.OptimizeVar_AcceptDelta(self, delta, deltadelta)
+
+    def EnterSearch(self) -> "void":
+        return _pywrapcp.OptimizeVar_EnterSearch(self)
+
+    def BeginNextDecision(self, db: "DecisionBuilder") -> "void":
+        return _pywrapcp.OptimizeVar_BeginNextDecision(self, db)
+
+    def RefuteDecision(self, d: "Decision") -> "void":
+        return _pywrapcp.OptimizeVar_RefuteDecision(self, d)
+
+    def AtSolution(self) -> "bool":
+        return _pywrapcp.OptimizeVar_AtSolution(self)
+
+    def AcceptSolution(self) -> "bool":
+        return _pywrapcp.OptimizeVar_AcceptSolution(self)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.OptimizeVar_DebugString(self)
+
+# Register OptimizeVar in _pywrapcp:
+_pywrapcp.OptimizeVar_swigregister(OptimizeVar)
+
+class SearchLimit(SearchMonitor):
+    r""" Base class of all search limits."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+    __swig_destroy__ = _pywrapcp.delete_SearchLimit
+
+    def Crossed(self) -> "bool":
+        r""" Returns true if the limit has been crossed."""
+        return _pywrapcp.SearchLimit_Crossed(self)
+
+    def Check(self) -> "bool":
+        r"""
+        This method is called to check the status of the limit. A return
+        value of true indicates that we have indeed crossed the limit. In
+        that case, this method will not be called again and the remaining
+        search will be discarded.
+        """
+        return _pywrapcp.SearchLimit_Check(self)
+
+    def Init(self) -> "void":
+        r""" This method is called when the search limit is initialized."""
+        return _pywrapcp.SearchLimit_Init(self)
+
+    def EnterSearch(self) -> "void":
+        r""" Internal methods."""
+        return _pywrapcp.SearchLimit_EnterSearch(self)
+
+    def BeginNextDecision(self, b: "DecisionBuilder") -> "void":
+        return _pywrapcp.SearchLimit_BeginNextDecision(self, b)
+
+    def RefuteDecision(self, d: "Decision") -> "void":
+        return _pywrapcp.SearchLimit_RefuteDecision(self, d)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.SearchLimit_DebugString(self)
+
+# Register SearchLimit in _pywrapcp:
+_pywrapcp.SearchLimit_swigregister(SearchLimit)
+
+class IntervalVar(PropagationBaseObject):
+    r"""
+    Interval variables are often used in scheduling. The main characteristics
+    of an IntervalVar are the start position, duration, and end
+    date. All these characteristics can be queried and set, and demons can
+    be posted on their modifications.
+
+    An important aspect is optionality: an IntervalVar can be performed or not.
+    If unperformed, then it simply does not exist, and its characteristics
+    cannot be accessed any more. An interval var is automatically marked
+    as unperformed when it is not consistent anymore (start greater
+    than end, duration < 0...)
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+    def StartMin(self) -> "int64_t":
+        r"""
+        These methods query, set, and watch the start position of the
+        interval var.
+        """
+        return _pywrapcp.IntervalVar_StartMin(self)
+
+    def StartMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_StartMax(self)
+
+    def SetStartMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetStartMin(self, m)
+
+    def SetStartMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetStartMax(self, m)
+
+    def SetStartRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetStartRange(self, mi, ma)
+
+    def OldStartMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldStartMin(self)
+
+    def OldStartMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldStartMax(self)
+
+    def WhenStartRange(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenStartRange(self, *args)
+
+    def WhenStartBound(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenStartBound(self, *args)
+
+    def DurationMin(self) -> "int64_t":
+        r""" These methods query, set, and watch the duration of the interval var."""
+        return _pywrapcp.IntervalVar_DurationMin(self)
+
+    def DurationMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_DurationMax(self)
+
+    def SetDurationMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetDurationMin(self, m)
+
+    def SetDurationMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetDurationMax(self, m)
+
+    def SetDurationRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetDurationRange(self, mi, ma)
+
+    def OldDurationMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldDurationMin(self)
+
+    def OldDurationMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldDurationMax(self)
+
+    def WhenDurationRange(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenDurationRange(self, *args)
+
+    def WhenDurationBound(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenDurationBound(self, *args)
+
+    def EndMin(self) -> "int64_t":
+        r""" These methods query, set, and watch the end position of the interval var."""
+        return _pywrapcp.IntervalVar_EndMin(self)
+
+    def EndMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_EndMax(self)
+
+    def SetEndMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetEndMin(self, m)
+
+    def SetEndMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetEndMax(self, m)
+
+    def SetEndRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetEndRange(self, mi, ma)
+
+    def OldEndMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldEndMin(self)
+
+    def OldEndMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldEndMax(self)
+
+    def WhenEndRange(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenEndRange(self, *args)
+
+    def WhenEndBound(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenEndBound(self, *args)
+
+    def MustBePerformed(self) -> "bool":
+        r"""
+        These methods query, set, and watch the performed status of the
+        interval var.
+        """
+        return _pywrapcp.IntervalVar_MustBePerformed(self)
+
+    def MayBePerformed(self) -> "bool":
+        return _pywrapcp.IntervalVar_MayBePerformed(self)
+
+    def CannotBePerformed(self) -> "bool":
+        return _pywrapcp.IntervalVar_CannotBePerformed(self)
+
+    def IsPerformedBound(self) -> "bool":
+        return _pywrapcp.IntervalVar_IsPerformedBound(self)
+
+    def SetPerformed(self, val: "bool") -> "void":
+        return _pywrapcp.IntervalVar_SetPerformed(self, val)
+
+    def WasPerformedBound(self) -> "bool":
+        return _pywrapcp.IntervalVar_WasPerformedBound(self)
+
+    def WhenPerformedBound(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenPerformedBound(self, *args)
+
+    def WhenAnything(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        Attaches a demon awakened when anything about this interval changes.
+
+        |
+
+        *Overload 2:*
+        Attaches a closure awakened when anything about this interval changes.
+        """
+        return _pywrapcp.IntervalVar_WhenAnything(self, *args)
+
+    def StartExpr(self) -> "operations_research::IntExpr *":
+        r"""
+        These methods create expressions encapsulating the start, end
+        and duration of the interval var. Please note that these must not
+        be used if the interval var is unperformed.
+        """
+        return _pywrapcp.IntervalVar_StartExpr(self)
+
+    def DurationExpr(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_DurationExpr(self)
+
+    def EndExpr(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_EndExpr(self)
+
+    def PerformedExpr(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_PerformedExpr(self)
+
+    def SafeStartExpr(self, unperformed_value: "int64_t") -> "operations_research::IntExpr *":
+        r"""
+        These methods create expressions encapsulating the start, end
+        and duration of the interval var. If the interval var is
+        unperformed, they will return the unperformed_value.
+        """
+        return _pywrapcp.IntervalVar_SafeStartExpr(self, unperformed_value)
+
+    def SafeDurationExpr(self, unperformed_value: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_SafeDurationExpr(self, unperformed_value)
+
+    def SafeEndExpr(self, unperformed_value: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_SafeEndExpr(self, unperformed_value)
+
+    def EndsAfterEnd(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfterEnd(self, other)
+
+    def EndsAfterEndWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfterEndWithDelay(self, other, delay)
+
+    def EndsAfterStart(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfterStart(self, other)
+
+    def EndsAfterStartWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfterStartWithDelay(self, other, delay)
+
+    def EndsAtEnd(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAtEnd(self, other)
+
+    def EndsAtEndWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAtEndWithDelay(self, other, delay)
+
+    def EndsAtStart(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAtStart(self, other)
+
+    def EndsAtStartWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAtStartWithDelay(self, other, delay)
+
+    def StartsAfterEnd(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfterEnd(self, other)
+
+    def StartsAfterEndWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfterEndWithDelay(self, other, delay)
+
+    def StartsAfterStart(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfterStart(self, other)
+
+    def StartsAfterStartWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfterStartWithDelay(self, other, delay)
+
+    def StartsAtEnd(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAtEnd(self, other)
+
+    def StartsAtEndWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAtEndWithDelay(self, other, delay)
+
+    def StartsAtStart(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAtStart(self, other)
+
+    def StartsAtStartWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAtStartWithDelay(self, other, delay)
+
+    def StaysInSync(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StaysInSync(self, other)
+
+    def StaysInSyncWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StaysInSyncWithDelay(self, other, delay)
+
+    def EndsAfter(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfter(self, date)
+
+    def EndsAt(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAt(self, date)
+
+    def EndsBefore(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsBefore(self, date)
+
+    def StartsAfter(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfter(self, date)
+
+    def StartsAt(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAt(self, date)
+
+    def StartsBefore(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsBefore(self, date)
+
+    def CrossesDate(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_CrossesDate(self, date)
+
+    def AvoidsDate(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_AvoidsDate(self, date)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.IntervalVar___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.IntervalVar___str__(self)
+
+# Register IntervalVar in _pywrapcp:
+_pywrapcp.IntervalVar_swigregister(IntervalVar)
+
+class SequenceVar(PropagationBaseObject):
+    r"""
+    A sequence variable is a variable whose domain is a set of possible
+    orderings of the interval variables. It allows ordering of tasks. It
+    has two sets of methods: ComputePossibleFirstsAndLasts(), which
+    returns the list of interval variables that can be ranked first or
+    last; and RankFirst/RankNotFirst/RankLast/RankNotLast, which can be
+    used to create the search decision.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.SequenceVar_DebugString(self)
+
+    def RankFirst(self, index: "int") -> "void":
+        r"""
+        Ranks the index_th interval var first of all unranked interval
+        vars. After that, it will no longer be considered ranked.
+        """
+        return _pywrapcp.SequenceVar_RankFirst(self, index)
+
+    def RankNotFirst(self, index: "int") -> "void":
+        r"""
+        Indicates that the index_th interval var will not be ranked first
+        of all currently unranked interval vars.
+        """
+        return _pywrapcp.SequenceVar_RankNotFirst(self, index)
+
+    def RankLast(self, index: "int") -> "void":
+        r"""
+        Ranks the index_th interval var first of all unranked interval
+        vars. After that, it will no longer be considered ranked.
+        """
+        return _pywrapcp.SequenceVar_RankLast(self, index)
+
+    def RankNotLast(self, index: "int") -> "void":
+        r"""
+        Indicates that the index_th interval var will not be ranked first
+        of all currently unranked interval vars.
+        """
+        return _pywrapcp.SequenceVar_RankNotLast(self, index)
+
+    def Interval(self, index: "int") -> "operations_research::IntervalVar *":
+        r""" Returns the index_th interval of the sequence."""
+        return _pywrapcp.SequenceVar_Interval(self, index)
+
+    def Next(self, index: "int") -> "operations_research::IntVar *":
+        r""" Returns the next of the index_th interval of the sequence."""
+        return _pywrapcp.SequenceVar_Next(self, index)
+
+    def Size(self) -> "int64_t":
+        r""" Returns the number of interval vars in the sequence."""
+        return _pywrapcp.SequenceVar_Size(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.SequenceVar___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.SequenceVar___str__(self)
+
+# Register SequenceVar in _pywrapcp:
+_pywrapcp.SequenceVar_swigregister(SequenceVar)
+
+class AssignmentElement(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Activate(self) -> "void":
+        return _pywrapcp.AssignmentElement_Activate(self)
+
+    def Deactivate(self) -> "void":
+        return _pywrapcp.AssignmentElement_Deactivate(self)
+
+    def Activated(self) -> "bool":
+        return _pywrapcp.AssignmentElement_Activated(self)
+    __swig_destroy__ = _pywrapcp.delete_AssignmentElement
+
+# Register AssignmentElement in _pywrapcp:
+_pywrapcp.AssignmentElement_swigregister(AssignmentElement)
+
+class IntVarElement(AssignmentElement):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Var(self) -> "operations_research::IntVar *":
+        return _pywrapcp.IntVarElement_Var(self)
+
+    def Min(self) -> "int64_t":
+        return _pywrapcp.IntVarElement_Min(self)
+
+    def SetMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntVarElement_SetMin(self, m)
+
+    def Max(self) -> "int64_t":
+        return _pywrapcp.IntVarElement_Max(self)
+
+    def SetMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntVarElement_SetMax(self, m)
+
+    def Value(self) -> "int64_t":
+        return _pywrapcp.IntVarElement_Value(self)
+
+    def Bound(self) -> "bool":
+        return _pywrapcp.IntVarElement_Bound(self)
+
+    def SetRange(self, l: "int64_t", u: "int64_t") -> "void":
+        return _pywrapcp.IntVarElement_SetRange(self, l, u)
+
+    def SetValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntVarElement_SetValue(self, v)
+
+    def __eq__(self, element: "IntVarElement") -> "bool":
+        return _pywrapcp.IntVarElement___eq__(self, element)
+
+    def __ne__(self, element: "IntVarElement") -> "bool":
+        return _pywrapcp.IntVarElement___ne__(self, element)
+    __swig_destroy__ = _pywrapcp.delete_IntVarElement
+
+# Register IntVarElement in _pywrapcp:
+_pywrapcp.IntVarElement_swigregister(IntVarElement)
+
+class IntervalVarElement(AssignmentElement):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Var(self) -> "operations_research::IntervalVar *":
+        return _pywrapcp.IntervalVarElement_Var(self)
+
+    def StartMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_StartMin(self)
+
+    def StartMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_StartMax(self)
+
+    def StartValue(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_StartValue(self)
+
+    def DurationMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_DurationMin(self)
+
+    def DurationMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_DurationMax(self)
+
+    def DurationValue(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_DurationValue(self)
+
+    def EndMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_EndMin(self)
+
+    def EndMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_EndMax(self)
+
+    def EndValue(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_EndValue(self)
+
+    def PerformedMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_PerformedMin(self)
+
+    def PerformedMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_PerformedMax(self)
+
+    def PerformedValue(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_PerformedValue(self)
+
+    def SetStartMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetStartMin(self, m)
+
+    def SetStartMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetStartMax(self, m)
+
+    def SetStartRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetStartRange(self, mi, ma)
+
+    def SetStartValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetStartValue(self, v)
+
+    def SetDurationMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetDurationMin(self, m)
+
+    def SetDurationMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetDurationMax(self, m)
+
+    def SetDurationRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetDurationRange(self, mi, ma)
+
+    def SetDurationValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetDurationValue(self, v)
+
+    def SetEndMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetEndMin(self, m)
+
+    def SetEndMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetEndMax(self, m)
+
+    def SetEndRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetEndRange(self, mi, ma)
+
+    def SetEndValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetEndValue(self, v)
+
+    def SetPerformedMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetPerformedMin(self, m)
+
+    def SetPerformedMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetPerformedMax(self, m)
+
+    def SetPerformedRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetPerformedRange(self, mi, ma)
+
+    def SetPerformedValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetPerformedValue(self, v)
+
+    def __eq__(self, element: "IntervalVarElement") -> "bool":
+        return _pywrapcp.IntervalVarElement___eq__(self, element)
+
+    def __ne__(self, element: "IntervalVarElement") -> "bool":
+        return _pywrapcp.IntervalVarElement___ne__(self, element)
+    __swig_destroy__ = _pywrapcp.delete_IntervalVarElement
+
+# Register IntervalVarElement in _pywrapcp:
+_pywrapcp.IntervalVarElement_swigregister(IntervalVarElement)
+
+class SequenceVarElement(AssignmentElement):
+    r"""
+    The SequenceVarElement stores a partial representation of ranked
+    interval variables in the underlying sequence variable.
+    This representation consists of three vectors:
+      - the forward sequence. That is the list of interval variables
+        ranked first in the sequence.  The first element of the backward
+        sequence is the first interval in the sequence variable.
+      - the backward sequence. That is the list of interval variables
+        ranked last in the sequence. The first element of the backward
+        sequence is the last interval in the sequence variable.
+      - The list of unperformed interval variables.
+     Furthermore, if all performed variables are ranked, then by
+     convention, the forward_sequence will contain all such variables
+     and the backward_sequence will be empty.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Var(self) -> "operations_research::SequenceVar *":
+        return _pywrapcp.SequenceVarElement_Var(self)
+
+    def ForwardSequence(self) -> "std::vector< int > const &":
+        return _pywrapcp.SequenceVarElement_ForwardSequence(self)
+
+    def BackwardSequence(self) -> "std::vector< int > const &":
+        return _pywrapcp.SequenceVarElement_BackwardSequence(self)
+
+    def Unperformed(self) -> "std::vector< int > const &":
+        return _pywrapcp.SequenceVarElement_Unperformed(self)
+
+    def SetSequence(self, forward_sequence: "std::vector< int > const &", backward_sequence: "std::vector< int > const &", unperformed: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarElement_SetSequence(self, forward_sequence, backward_sequence, unperformed)
+
+    def SetForwardSequence(self, forward_sequence: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarElement_SetForwardSequence(self, forward_sequence)
+
+    def SetBackwardSequence(self, backward_sequence: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarElement_SetBackwardSequence(self, backward_sequence)
+
+    def SetUnperformed(self, unperformed: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarElement_SetUnperformed(self, unperformed)
+
+    def __eq__(self, element: "SequenceVarElement") -> "bool":
+        return _pywrapcp.SequenceVarElement___eq__(self, element)
+
+    def __ne__(self, element: "SequenceVarElement") -> "bool":
+        return _pywrapcp.SequenceVarElement___ne__(self, element)
+    __swig_destroy__ = _pywrapcp.delete_SequenceVarElement
+
+# Register SequenceVarElement in _pywrapcp:
+_pywrapcp.SequenceVarElement_swigregister(SequenceVarElement)
+
+class Assignment(PropagationBaseObject):
+    r"""
+    An Assignment is a variable -> domains mapping, used
+    to report solutions to the user.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Clear(self) -> "void":
+        return _pywrapcp.Assignment_Clear(self)
+
+    def Empty(self) -> "bool":
+        return _pywrapcp.Assignment_Empty(self)
+
+    def Size(self) -> "int":
+        return _pywrapcp.Assignment_Size(self)
+
+    def NumIntVars(self) -> "int":
+        return _pywrapcp.Assignment_NumIntVars(self)
+
+    def NumIntervalVars(self) -> "int":
+        return _pywrapcp.Assignment_NumIntervalVars(self)
+
+    def NumSequenceVars(self) -> "int":
+        return _pywrapcp.Assignment_NumSequenceVars(self)
+
+    def Store(self) -> "void":
+        return _pywrapcp.Assignment_Store(self)
+
+    def Restore(self) -> "void":
+        return _pywrapcp.Assignment_Restore(self)
+
+    def Load(self, *args) -> "void":
+        return _pywrapcp.Assignment_Load(self, *args)
+
+    def Save(self, *args) -> "void":
+        return _pywrapcp.Assignment_Save(self, *args)
+
+    def AddObjective(self, v: "IntVar") -> "void":
+        return _pywrapcp.Assignment_AddObjective(self, v)
+
+    def Objective(self) -> "operations_research::IntVar *":
+        return _pywrapcp.Assignment_Objective(self)
+
+    def HasObjective(self) -> "bool":
+        return _pywrapcp.Assignment_HasObjective(self)
+
+    def ObjectiveMin(self) -> "int64_t":
+        return _pywrapcp.Assignment_ObjectiveMin(self)
+
+    def ObjectiveMax(self) -> "int64_t":
+        return _pywrapcp.Assignment_ObjectiveMax(self)
+
+    def ObjectiveValue(self) -> "int64_t":
+        return _pywrapcp.Assignment_ObjectiveValue(self)
+
+    def ObjectiveBound(self) -> "bool":
+        return _pywrapcp.Assignment_ObjectiveBound(self)
+
+    def SetObjectiveMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetObjectiveMin(self, m)
+
+    def SetObjectiveMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetObjectiveMax(self, m)
+
+    def SetObjectiveValue(self, value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetObjectiveValue(self, value)
+
+    def SetObjectiveRange(self, l: "int64_t", u: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetObjectiveRange(self, l, u)
+
+    def Min(self, var: "IntVar") -> "int64_t":
+        return _pywrapcp.Assignment_Min(self, var)
+
+    def Max(self, var: "IntVar") -> "int64_t":
+        return _pywrapcp.Assignment_Max(self, var)
+
+    def Value(self, var: "IntVar") -> "int64_t":
+        return _pywrapcp.Assignment_Value(self, var)
+
+    def Bound(self, var: "IntVar") -> "bool":
+        return _pywrapcp.Assignment_Bound(self, var)
+
+    def SetMin(self, var: "IntVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetMin(self, var, m)
+
+    def SetMax(self, var: "IntVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetMax(self, var, m)
+
+    def SetRange(self, var: "IntVar", l: "int64_t", u: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetRange(self, var, l, u)
+
+    def SetValue(self, var: "IntVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetValue(self, var, value)
+
+    def StartMin(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_StartMin(self, var)
+
+    def StartMax(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_StartMax(self, var)
+
+    def StartValue(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_StartValue(self, var)
+
+    def DurationMin(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_DurationMin(self, var)
+
+    def DurationMax(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_DurationMax(self, var)
+
+    def DurationValue(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_DurationValue(self, var)
+
+    def EndMin(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_EndMin(self, var)
+
+    def EndMax(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_EndMax(self, var)
+
+    def EndValue(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_EndValue(self, var)
+
+    def PerformedMin(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_PerformedMin(self, var)
+
+    def PerformedMax(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_PerformedMax(self, var)
+
+    def PerformedValue(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_PerformedValue(self, var)
+
+    def SetStartMin(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetStartMin(self, var, m)
+
+    def SetStartMax(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetStartMax(self, var, m)
+
+    def SetStartRange(self, var: "IntervalVar", mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetStartRange(self, var, mi, ma)
+
+    def SetStartValue(self, var: "IntervalVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetStartValue(self, var, value)
+
+    def SetDurationMin(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetDurationMin(self, var, m)
+
+    def SetDurationMax(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetDurationMax(self, var, m)
+
+    def SetDurationRange(self, var: "IntervalVar", mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetDurationRange(self, var, mi, ma)
+
+    def SetDurationValue(self, var: "IntervalVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetDurationValue(self, var, value)
+
+    def SetEndMin(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetEndMin(self, var, m)
+
+    def SetEndMax(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetEndMax(self, var, m)
+
+    def SetEndRange(self, var: "IntervalVar", mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetEndRange(self, var, mi, ma)
+
+    def SetEndValue(self, var: "IntervalVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetEndValue(self, var, value)
+
+    def SetPerformedMin(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetPerformedMin(self, var, m)
+
+    def SetPerformedMax(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetPerformedMax(self, var, m)
+
+    def SetPerformedRange(self, var: "IntervalVar", mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetPerformedRange(self, var, mi, ma)
+
+    def SetPerformedValue(self, var: "IntervalVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetPerformedValue(self, var, value)
+
+    def Add(self, *args) -> "void":
+        return _pywrapcp.Assignment_Add(self, *args)
+
+    def ForwardSequence(self, var: "SequenceVar") -> "std::vector< int > const &":
+        return _pywrapcp.Assignment_ForwardSequence(self, var)
+
+    def BackwardSequence(self, var: "SequenceVar") -> "std::vector< int > const &":
+        return _pywrapcp.Assignment_BackwardSequence(self, var)
+
+    def Unperformed(self, var: "SequenceVar") -> "std::vector< int > const &":
+        return _pywrapcp.Assignment_Unperformed(self, var)
+
+    def SetSequence(self, var: "SequenceVar", forward_sequence: "std::vector< int > const &", backward_sequence: "std::vector< int > const &", unperformed: "std::vector< int > const &") -> "void":
+        return _pywrapcp.Assignment_SetSequence(self, var, forward_sequence, backward_sequence, unperformed)
+
+    def SetForwardSequence(self, var: "SequenceVar", forward_sequence: "std::vector< int > const &") -> "void":
+        return _pywrapcp.Assignment_SetForwardSequence(self, var, forward_sequence)
+
+    def SetBackwardSequence(self, var: "SequenceVar", backward_sequence: "std::vector< int > const &") -> "void":
+        return _pywrapcp.Assignment_SetBackwardSequence(self, var, backward_sequence)
+
+    def SetUnperformed(self, var: "SequenceVar", unperformed: "std::vector< int > const &") -> "void":
+        return _pywrapcp.Assignment_SetUnperformed(self, var, unperformed)
+
+    def Activate(self, *args) -> "void":
+        return _pywrapcp.Assignment_Activate(self, *args)
+
+    def Deactivate(self, *args) -> "void":
+        return _pywrapcp.Assignment_Deactivate(self, *args)
+
+    def Activated(self, *args) -> "bool":
+        return _pywrapcp.Assignment_Activated(self, *args)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.Assignment_DebugString(self)
+
+    def IntVarContainer(self) -> "operations_research::Assignment::IntContainer const &":
+        return _pywrapcp.Assignment_IntVarContainer(self)
+
+    def MutableIntVarContainer(self) -> "operations_research::Assignment::IntContainer *":
+        return _pywrapcp.Assignment_MutableIntVarContainer(self)
+
+    def IntervalVarContainer(self) -> "operations_research::Assignment::IntervalContainer const &":
+        return _pywrapcp.Assignment_IntervalVarContainer(self)
+
+    def MutableIntervalVarContainer(self) -> "operations_research::Assignment::IntervalContainer *":
+        return _pywrapcp.Assignment_MutableIntervalVarContainer(self)
+
+    def SequenceVarContainer(self) -> "operations_research::Assignment::SequenceContainer const &":
+        return _pywrapcp.Assignment_SequenceVarContainer(self)
+
+    def MutableSequenceVarContainer(self) -> "operations_research::Assignment::SequenceContainer *":
+        return _pywrapcp.Assignment_MutableSequenceVarContainer(self)
+
+    def __eq__(self, assignment: "Assignment") -> "bool":
+        return _pywrapcp.Assignment___eq__(self, assignment)
+
+    def __ne__(self, assignment: "Assignment") -> "bool":
+        return _pywrapcp.Assignment___ne__(self, assignment)
+
+# Register Assignment in _pywrapcp:
+_pywrapcp.Assignment_swigregister(Assignment)
+
+
+def __lshift__(*args) -> "std::ostream &":
+    return _pywrapcp.__lshift__(*args)
+class Pack(Constraint):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def AddWeightedSumLessOrEqualConstantDimension(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        Dimensions are additional constraints than can restrict what is
+        possible with the pack constraint. It can be used to set capacity
+        limits, to count objects per bin, to compute unassigned
+        penalties...
+        This dimension imposes that for all bins b, the weighted sum
+        (weights[i]) of all objects i assigned to 'b' is less or equal
+        'bounds[b]'.
+
+        |
+
+        *Overload 2:*
+        This dimension imposes that for all bins b, the weighted sum
+        (weights->Run(i)) of all objects i assigned to 'b' is less or
+        equal to 'bounds[b]'. Ownership of the callback is transferred to
+        the pack constraint.
+
+        |
+
+        *Overload 3:*
+        This dimension imposes that for all bins b, the weighted sum
+        (weights->Run(i, b) of all objects i assigned to 'b' is less or
+        equal to 'bounds[b]'. Ownership of the callback is transferred to
+        the pack constraint.
+        """
+        return _pywrapcp.Pack_AddWeightedSumLessOrEqualConstantDimension(self, *args)
+
+    def AddWeightedSumEqualVarDimension(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        This dimension imposes that for all bins b, the weighted sum
+        (weights[i]) of all objects i assigned to 'b' is equal to loads[b].
+
+        |
+
+        *Overload 2:*
+        This dimension imposes that for all bins b, the weighted sum
+        (weights->Run(i, b)) of all objects i assigned to 'b' is equal to
+        loads[b].
+        """
+        return _pywrapcp.Pack_AddWeightedSumEqualVarDimension(self, *args)
+
+    def AddSumVariableWeightsLessOrEqualConstantDimension(self, usage: "std::vector< operations_research::IntVar * > const &", capacity: "std::vector< int64_t > const &") -> "void":
+        r"""
+        This dimension imposes:
+        forall b in bins,
+           sum (i in items: usage[i] * is_assigned(i, b)) <= capacity[b]
+        where is_assigned(i, b) is true if and only if item i is assigned
+        to the bin b.
+
+        This can be used to model shapes of items by linking variables of
+        the same item on parallel dimensions with an allowed assignment
+        constraint.
+        """
+        return _pywrapcp.Pack_AddSumVariableWeightsLessOrEqualConstantDimension(self, usage, capacity)
+
+    def AddWeightedSumOfAssignedDimension(self, weights: "std::vector< int64_t > const &", cost_var: "IntVar") -> "void":
+        r"""
+        This dimension enforces that cost_var == sum of weights[i] for
+        all objects 'i' assigned to a bin.
+        """
+        return _pywrapcp.Pack_AddWeightedSumOfAssignedDimension(self, weights, cost_var)
+
+    def AddCountUsedBinDimension(self, count_var: "IntVar") -> "void":
+        r"""
+        This dimension links 'count_var' to the actual number of bins used in the
+        pack.
+        """
+        return _pywrapcp.Pack_AddCountUsedBinDimension(self, count_var)
+
+    def AddCountAssignedItemsDimension(self, count_var: "IntVar") -> "void":
+        r"""
+        This dimension links 'count_var' to the actual number of items
+        assigned to a bin in the pack.
+        """
+        return _pywrapcp.Pack_AddCountAssignedItemsDimension(self, count_var)
+
+    def Post(self) -> "void":
+        return _pywrapcp.Pack_Post(self)
+
+    def InitialPropagateWrapper(self) -> "void":
+        return _pywrapcp.Pack_InitialPropagateWrapper(self)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.Pack_DebugString(self)
+
+# Register Pack in _pywrapcp:
+_pywrapcp.Pack_swigregister(Pack)
+
+class DisjunctiveConstraint(Constraint):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def SequenceVar(self) -> "operations_research::SequenceVar *":
+        r""" Creates a sequence variable from the constraint."""
+        return _pywrapcp.DisjunctiveConstraint_SequenceVar(self)
+
+    def SetTransitionTime(self, transition_time: "operations_research::Solver::IndexEvaluator2") -> "void":
+        r"""
+        Add a transition time between intervals.  It forces the distance between
+        the end of interval a and start of interval b that follows it to be at
+        least transition_time(a, b). This function must always return
+        a positive or null value.
+        """
+        return _pywrapcp.DisjunctiveConstraint_SetTransitionTime(self, transition_time)
+
+    def TransitionTime(self, before_index: "int", after_index: "int") -> "int64_t":
+        return _pywrapcp.DisjunctiveConstraint_TransitionTime(self, before_index, after_index)
+
+# Register DisjunctiveConstraint in _pywrapcp:
+_pywrapcp.DisjunctiveConstraint_swigregister(DisjunctiveConstraint)
+
+class RevInteger(object):
+    r"""
+    This class adds reversibility to a POD type.
+    It contains the stamp optimization. i.e. the SaveValue call is done
+    only once per node of the search tree.  Please note that actual
+    stamps always starts at 1, thus an initial value of 0 will always
+    trigger the first SaveValue.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, val: "long const &"):
+        _pywrapcp.RevInteger_swiginit(self, _pywrapcp.new_RevInteger(val))
+
+    def Value(self) -> "long const &":
+        return _pywrapcp.RevInteger_Value(self)
+
+    def SetValue(self, s: "Solver", val: "long const &") -> "void":
+        return _pywrapcp.RevInteger_SetValue(self, s, val)
+    __swig_destroy__ = _pywrapcp.delete_RevInteger
+
+# Register RevInteger in _pywrapcp:
+_pywrapcp.RevInteger_swigregister(RevInteger)
+
+class NumericalRevInteger(RevInteger):
+    r""" Subclass of Rev<T> which adds numerical operations."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, val: "long const &"):
+        _pywrapcp.NumericalRevInteger_swiginit(self, _pywrapcp.new_NumericalRevInteger(val))
+
+    def Add(self, s: "Solver", to_add: "long const &") -> "void":
+        return _pywrapcp.NumericalRevInteger_Add(self, s, to_add)
+
+    def Incr(self, s: "Solver") -> "void":
+        return _pywrapcp.NumericalRevInteger_Incr(self, s)
+
+    def Decr(self, s: "Solver") -> "void":
+        return _pywrapcp.NumericalRevInteger_Decr(self, s)
+    __swig_destroy__ = _pywrapcp.delete_NumericalRevInteger
+
+# Register NumericalRevInteger in _pywrapcp:
+_pywrapcp.NumericalRevInteger_swigregister(NumericalRevInteger)
+
+class RevBool(object):
+    r"""
+    This class adds reversibility to a POD type.
+    It contains the stamp optimization. i.e. the SaveValue call is done
+    only once per node of the search tree.  Please note that actual
+    stamps always starts at 1, thus an initial value of 0 will always
+    trigger the first SaveValue.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, val: "bool const &"):
+        _pywrapcp.RevBool_swiginit(self, _pywrapcp.new_RevBool(val))
+
+    def Value(self) -> "bool const &":
+        return _pywrapcp.RevBool_Value(self)
+
+    def SetValue(self, s: "Solver", val: "bool const &") -> "void":
+        return _pywrapcp.RevBool_SetValue(self, s, val)
+    __swig_destroy__ = _pywrapcp.delete_RevBool
+
+# Register RevBool in _pywrapcp:
+_pywrapcp.RevBool_swigregister(RevBool)
+
+class IntVarContainer(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Contains(self, var: "IntVar") -> "bool":
+        return _pywrapcp.IntVarContainer_Contains(self, var)
+
+    def Element(self, index: "int") -> "operations_research::IntVarElement *":
+        return _pywrapcp.IntVarContainer_Element(self, index)
+
+    def Size(self) -> "int":
+        return _pywrapcp.IntVarContainer_Size(self)
+
+    def Store(self) -> "void":
+        return _pywrapcp.IntVarContainer_Store(self)
+
+    def Restore(self) -> "void":
+        return _pywrapcp.IntVarContainer_Restore(self)
+
+    def __eq__(self, container: "IntVarContainer") -> "bool":
+        r"""
+        Returns true if this and 'container' both represent the same V* -> E map.
+        Runs in linear time; requires that the == operator on the type E is well
+        defined.
+        """
+        return _pywrapcp.IntVarContainer___eq__(self, container)
+
+    def __ne__(self, container: "IntVarContainer") -> "bool":
+        return _pywrapcp.IntVarContainer___ne__(self, container)
+    __swig_destroy__ = _pywrapcp.delete_IntVarContainer
+
+# Register IntVarContainer in _pywrapcp:
+_pywrapcp.IntVarContainer_swigregister(IntVarContainer)
+
+class IntervalVarContainer(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Contains(self, var: "IntervalVar") -> "bool":
+        return _pywrapcp.IntervalVarContainer_Contains(self, var)
+
+    def Element(self, index: "int") -> "operations_research::IntervalVarElement *":
+        return _pywrapcp.IntervalVarContainer_Element(self, index)
+
+    def Size(self) -> "int":
+        return _pywrapcp.IntervalVarContainer_Size(self)
+
+    def Store(self) -> "void":
+        return _pywrapcp.IntervalVarContainer_Store(self)
+
+    def Restore(self) -> "void":
+        return _pywrapcp.IntervalVarContainer_Restore(self)
+
+    def __eq__(self, container: "IntervalVarContainer") -> "bool":
+        r"""
+        Returns true if this and 'container' both represent the same V* -> E map.
+        Runs in linear time; requires that the == operator on the type E is well
+        defined.
+        """
+        return _pywrapcp.IntervalVarContainer___eq__(self, container)
+
+    def __ne__(self, container: "IntervalVarContainer") -> "bool":
+        return _pywrapcp.IntervalVarContainer___ne__(self, container)
+    __swig_destroy__ = _pywrapcp.delete_IntervalVarContainer
+
+# Register IntervalVarContainer in _pywrapcp:
+_pywrapcp.IntervalVarContainer_swigregister(IntervalVarContainer)
+
+class SequenceVarContainer(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Contains(self, var: "SequenceVar") -> "bool":
+        return _pywrapcp.SequenceVarContainer_Contains(self, var)
+
+    def Element(self, index: "int") -> "operations_research::SequenceVarElement *":
+        return _pywrapcp.SequenceVarContainer_Element(self, index)
+
+    def Size(self) -> "int":
+        return _pywrapcp.SequenceVarContainer_Size(self)
+
+    def Store(self) -> "void":
+        return _pywrapcp.SequenceVarContainer_Store(self)
+
+    def Restore(self) -> "void":
+        return _pywrapcp.SequenceVarContainer_Restore(self)
+
+    def __eq__(self, container: "SequenceVarContainer") -> "bool":
+        r"""
+        Returns true if this and 'container' both represent the same V* -> E map.
+        Runs in linear time; requires that the == operator on the type E is well
+        defined.
+        """
+        return _pywrapcp.SequenceVarContainer___eq__(self, container)
+
+    def __ne__(self, container: "SequenceVarContainer") -> "bool":
+        return _pywrapcp.SequenceVarContainer___ne__(self, container)
+    __swig_destroy__ = _pywrapcp.delete_SequenceVarContainer
+
+# Register SequenceVarContainer in _pywrapcp:
+_pywrapcp.SequenceVarContainer_swigregister(SequenceVarContainer)
+
+class LocalSearchOperator(BaseObject):
+    r"""
+    This class represent a reversible FIFO structure.
+    The main difference w.r.t a standard FIFO structure is that a Solver is
+    given as parameter to the modifiers such that the solver can store the
+    backtrack information
+    Iterator's traversing order should not be changed, as some algorithm
+    depend on it to be consistent.
+    It's main use is to store a list of demons in the various classes of
+    variables.
+    The base class for all local search operators.
+
+    A local search operator is an object that defines the neighborhood of a
+    solution. In other words, a neighborhood is the set of solutions which can
+    be reached from a given solution using an operator.
+
+    The behavior of the LocalSearchOperator class is similar to iterators.
+    The operator is synchronized with an assignment (gives the
+    current values of the variables); this is done in the Start() method.
+
+    Then one can iterate over the neighbors using the MakeNextNeighbor method.
+    This method returns an assignment which represents the incremental changes
+    to the current solution. It also returns a second assignment representing
+    the changes to the last solution defined by the neighborhood operator; this
+    assignment is empty if the neighborhood operator cannot track this
+    information.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def NextNeighbor(self, delta: "Assignment", deltadelta: "Assignment") -> "bool":
+        return _pywrapcp.LocalSearchOperator_NextNeighbor(self, delta, deltadelta)
+
+    def Start(self, assignment: "Assignment") -> "void":
+        return _pywrapcp.LocalSearchOperator_Start(self, assignment)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_LocalSearchOperator(self)
+        return weakref.proxy(self)
+
+# Register LocalSearchOperator in _pywrapcp:
+_pywrapcp.LocalSearchOperator_swigregister(LocalSearchOperator)
+
+class IntVarLocalSearchOperatorTemplate(LocalSearchOperator):
+    r""" Base operator class for operators manipulating variables."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def Start(self, assignment: "Assignment") -> "void":
+        r"""
+        This method should not be overridden. Override OnStart() instead which is
+        called before exiting this method.
+        """
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_Start(self, assignment)
+
+    def IsIncremental(self) -> "bool":
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_IsIncremental(self)
+
+    def Size(self) -> "int":
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_Size(self)
+
+    def Value(self, index: "int64_t") -> "long const &":
+        r"""
+        Returns the value in the current assignment of the variable of given
+        index.
+        """
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_Value(self, index)
+
+    def OldValue(self, index: "int64_t") -> "long const &":
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_OldValue(self, index)
+
+    def SetValue(self, index: "int64_t", value: "long const &") -> "void":
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_SetValue(self, index, value)
+
+    def OnStart(self) -> "void":
+        r"""
+        Called by Start() after synchronizing the operator with the current
+        assignment. Should be overridden instead of Start() to avoid calling
+        VarLocalSearchOperator::Start explicitly.
+        """
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_OnStart(self)
+
+# Register IntVarLocalSearchOperatorTemplate in _pywrapcp:
+_pywrapcp.IntVarLocalSearchOperatorTemplate_swigregister(IntVarLocalSearchOperatorTemplate)
+
+class IntVarLocalSearchOperator(IntVarLocalSearchOperatorTemplate):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, *args):
+        if self.__class__ == IntVarLocalSearchOperator:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.IntVarLocalSearchOperator_swiginit(self, _pywrapcp.new_IntVarLocalSearchOperator(_self, *args))
+    __swig_destroy__ = _pywrapcp.delete_IntVarLocalSearchOperator
+
+    def NextNeighbor(self, delta: "Assignment", deltadelta: "Assignment") -> "bool":
+        r"""
+        Redefines MakeNextNeighbor to export a simpler interface. The calls to
+        ApplyChanges() and RevertChanges() are factored in this method, hiding
+        both delta and deltadelta from subclasses which only need to override
+        MakeOneNeighbor().
+        Therefore this method should not be overridden. Override MakeOneNeighbor()
+        instead.
+        """
+        return _pywrapcp.IntVarLocalSearchOperator_NextNeighbor(self, delta, deltadelta)
+
+    def OneNeighbor(self) -> "bool":
+        r"""
+        Creates a new neighbor. It returns false when the neighborhood is
+        completely explored.
+        MakeNextNeighbor() in a subclass of IntVarLocalSearchOperator.
+        """
+        return _pywrapcp.IntVarLocalSearchOperator_OneNeighbor(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_IntVarLocalSearchOperator(self)
+        return weakref.proxy(self)
+
+# Register IntVarLocalSearchOperator in _pywrapcp:
+_pywrapcp.IntVarLocalSearchOperator_swigregister(IntVarLocalSearchOperator)
+
+class SequenceVarLocalSearchOperatorTemplate(LocalSearchOperator):
+    r""" Base operator class for operators manipulating variables."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def Start(self, assignment: "Assignment") -> "void":
+        r"""
+        This method should not be overridden. Override OnStart() instead which is
+        called before exiting this method.
+        """
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_Start(self, assignment)
+
+    def IsIncremental(self) -> "bool":
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_IsIncremental(self)
+
+    def Size(self) -> "int":
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_Size(self)
+
+    def Value(self, index: "int64_t") -> "std::vector< int > const &":
+        r"""
+        Returns the value in the current assignment of the variable of given
+        index.
+        """
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_Value(self, index)
+
+    def OldValue(self, index: "int64_t") -> "std::vector< int > const &":
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_OldValue(self, index)
+
+    def SetValue(self, index: "int64_t", value: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_SetValue(self, index, value)
+
+    def OnStart(self) -> "void":
+        r"""
+        Called by Start() after synchronizing the operator with the current
+        assignment. Should be overridden instead of Start() to avoid calling
+        VarLocalSearchOperator::Start explicitly.
+        """
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_OnStart(self)
+
+# Register SequenceVarLocalSearchOperatorTemplate in _pywrapcp:
+_pywrapcp.SequenceVarLocalSearchOperatorTemplate_swigregister(SequenceVarLocalSearchOperatorTemplate)
+
+class SequenceVarLocalSearchOperator(SequenceVarLocalSearchOperatorTemplate):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+# Register SequenceVarLocalSearchOperator in _pywrapcp:
+_pywrapcp.SequenceVarLocalSearchOperator_swigregister(SequenceVarLocalSearchOperator)
+
+class BaseLns(IntVarLocalSearchOperator):
+    r"""
+    This is the base class for building an Lns operator. An Lns fragment is a
+    collection of variables which will be relaxed. Fragments are built with
+    NextFragment(), which returns false if there are no more fragments to build.
+    Optionally one can override InitFragments, which is called from
+    LocalSearchOperator::Start to initialize fragment data.
+
+    Here's a sample relaxing one variable at a time:
+
+    class OneVarLns : public BaseLns {
+     public:
+      OneVarLns(const std::vector<IntVar*>& vars) : BaseLns(vars), index_(0) {}
+      virtual ~OneVarLns() {}
+      virtual void InitFragments() { index_ = 0; }
+      virtual bool NextFragment() {
+        const int size = Size();
+        if (index_ < size) {
+          AppendToFragment(index_);
+          ++index_;
+          return true;
+        } else {
+          return false;
+        }
+      }
+
+     private:
+      int index_;
+    };
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, vars: "std::vector< operations_research::IntVar * > const &"):
+        if self.__class__ == BaseLns:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.BaseLns_swiginit(self, _pywrapcp.new_BaseLns(_self, vars))
+    __swig_destroy__ = _pywrapcp.delete_BaseLns
+
+    def InitFragments(self) -> "void":
+        return _pywrapcp.BaseLns_InitFragments(self)
+
+    def NextFragment(self) -> "bool":
+        return _pywrapcp.BaseLns_NextFragment(self)
+
+    def AppendToFragment(self, index: "int") -> "void":
+        return _pywrapcp.BaseLns_AppendToFragment(self, index)
+
+    def FragmentSize(self) -> "int":
+        return _pywrapcp.BaseLns_FragmentSize(self)
+
+    def __getitem__(self, index: "int") -> "int64_t":
+        return _pywrapcp.BaseLns___getitem__(self, index)
+
+    def __len__(self) -> "int":
+        return _pywrapcp.BaseLns___len__(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_BaseLns(self)
+        return weakref.proxy(self)
+
+# Register BaseLns in _pywrapcp:
+_pywrapcp.BaseLns_swigregister(BaseLns)
+
+class ChangeValue(IntVarLocalSearchOperator):
+    r"""
+    Defines operators which change the value of variables;
+    each neighbor corresponds to *one* modified variable.
+    Sub-classes have to define ModifyValue which determines what the new
+    variable value is going to be (given the current value and the variable).
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, vars: "std::vector< operations_research::IntVar * > const &"):
+        if self.__class__ == ChangeValue:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.ChangeValue_swiginit(self, _pywrapcp.new_ChangeValue(_self, vars))
+    __swig_destroy__ = _pywrapcp.delete_ChangeValue
+
+    def ModifyValue(self, index: "int64_t", value: "int64_t") -> "int64_t":
+        return _pywrapcp.ChangeValue_ModifyValue(self, index, value)
+
+    def OneNeighbor(self) -> "bool":
+        r""" This method should not be overridden. Override ModifyValue() instead."""
+        return _pywrapcp.ChangeValue_OneNeighbor(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_ChangeValue(self)
+        return weakref.proxy(self)
+
+# Register ChangeValue in _pywrapcp:
+_pywrapcp.ChangeValue_swigregister(ChangeValue)
+
+class PathOperator(IntVarLocalSearchOperator):
+    r"""
+    Base class of the local search operators dedicated to path modifications
+    (a path is a set of nodes linked together by arcs).
+    This family of neighborhoods supposes they are handling next variables
+    representing the arcs (var[i] represents the node immediately after i on
+    a path).
+    Several services are provided:
+    - arc manipulators (SetNext(), ReverseChain(), MoveChain())
+    - path inspectors (Next(), Prev(), IsPathEnd())
+    - path iterators: operators need a given number of nodes to define a
+      neighbor; this class provides the iteration on a given number of (base)
+      nodes which can be used to define a neighbor (through the BaseNode method)
+    Subclasses only need to override MakeNeighbor to create neighbors using
+    the services above (no direct manipulation of assignments).
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def Neighbor(self) -> "bool":
+        return _pywrapcp.PathOperator_Neighbor(self)
+
+# Register PathOperator in _pywrapcp:
+_pywrapcp.PathOperator_swigregister(PathOperator)
+
+class LocalSearchFilter(BaseObject):
+    r"""
+    Classes to which this template function can be applied to as of 04/2014.
+    Usage: LocalSearchOperator* op = MakeLocalSearchOperator<Relocate>(...);
+    class TwoOpt;
+    class Relocate;
+    class Exchange;
+    class Cross;
+    class MakeActiveOperator;
+    class MakeInactiveOperator;
+    class MakeChainInactiveOperator;
+    class SwapActiveOperator;
+    class ExtendedSwapActiveOperator;
+    class MakeActiveAndRelocate;
+    class RelocateAndMakeActiveOperator;
+    class RelocateAndMakeInactiveOperator;
+    Local Search Filters are used for fast neighbor pruning.
+    Filtering a move is done in several phases:
+    - in the Relax phase, filters determine which parts of their internals
+      will be changed by the candidate, and modify intermediary State
+    - in the Accept phase, filters check that the candidate is feasible,
+    - if the Accept phase succeeds, the solver may decide to trigger a
+      Synchronize phase that makes filters change their internal representation
+      to the last candidate,
+    - otherwise (Accept fails or the solver does not want to synchronize),
+      a Revert phase makes filters erase any intermediary State generated by the
+      Relax and Accept phases.
+    A given filter has phases called with the following pattern:
+    (Relax.Accept.Synchronize | Relax.Accept.Revert | Relax.Revert)*.
+    Filters's Revert() is always called in the reverse order their Accept() was
+    called, to allow late filters to use state done/undone by early filters'
+    Accept()/Revert().
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def Accept(self, delta: "Assignment", deltadelta: "Assignment", objective_min: "int64_t", objective_max: "int64_t") -> "bool":
+        r"""
+        Accepts a "delta" given the assignment with which the filter has been
+        synchronized; the delta holds the variables which have been modified and
+        their new value.
+        If the filter represents a part of the global objective, its contribution
+        must be between objective_min and objective_max.
+        Sample: supposing one wants to maintain a[0,1] + b[0,1] <= 1,
+        for the assignment (a,1), (b,0), the delta (b,1) will be rejected
+        but the delta (a,0) will be accepted.
+        TODO(user): Remove arguments when there are no more need for those.
+        """
+        return _pywrapcp.LocalSearchFilter_Accept(self, delta, deltadelta, objective_min, objective_max)
+
+    def IsIncremental(self) -> "bool":
+        return _pywrapcp.LocalSearchFilter_IsIncremental(self)
+
+    def Synchronize(self, assignment: "Assignment", delta: "Assignment") -> "void":
+        r"""
+        Synchronizes the filter with the current solution, delta being the
+        difference with the solution passed to the previous call to Synchronize()
+        or IncrementalSynchronize(). 'delta' can be used to incrementally
+        synchronizing the filter with the new solution by only considering the
+        changes in delta.
+        """
+        return _pywrapcp.LocalSearchFilter_Synchronize(self, assignment, delta)
+    __swig_destroy__ = _pywrapcp.delete_LocalSearchFilter
+
+# Register LocalSearchFilter in _pywrapcp:
+_pywrapcp.LocalSearchFilter_swigregister(LocalSearchFilter)
+
+class LocalSearchFilterManager(BaseObject):
+    r"""
+    Filter manager: when a move is made, filters are executed to decide whether
+    the solution is feasible and compute parts of the new cost. This class
+    schedules filter execution and composes costs as a sum.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.LocalSearchFilterManager_DebugString(self)
+
+    def __init__(self, *args):
+        _pywrapcp.LocalSearchFilterManager_swiginit(self, _pywrapcp.new_LocalSearchFilterManager(*args))
+
+    def Accept(self, monitor: "operations_research::LocalSearchMonitor *const", delta: "Assignment", deltadelta: "Assignment", objective_min: "int64_t", objective_max: "int64_t") -> "bool":
+        r"""
+        Returns true iff all filters return true, and the sum of their accepted
+        objectives is between objective_min and objective_max.
+        The monitor has its Begin/EndFiltering events triggered.
+        """
+        return _pywrapcp.LocalSearchFilterManager_Accept(self, monitor, delta, deltadelta, objective_min, objective_max)
+
+    def Synchronize(self, assignment: "Assignment", delta: "Assignment") -> "void":
+        r""" Synchronizes all filters to assignment."""
+        return _pywrapcp.LocalSearchFilterManager_Synchronize(self, assignment, delta)
+    __swig_destroy__ = _pywrapcp.delete_LocalSearchFilterManager
+
+# Register LocalSearchFilterManager in _pywrapcp:
+_pywrapcp.LocalSearchFilterManager_swigregister(LocalSearchFilterManager)
+
+class IntVarLocalSearchFilter(LocalSearchFilter):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, vars: "std::vector< operations_research::IntVar * > const &"):
+        if self.__class__ == IntVarLocalSearchFilter:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.IntVarLocalSearchFilter_swiginit(self, _pywrapcp.new_IntVarLocalSearchFilter(_self, vars))
+    __swig_destroy__ = _pywrapcp.delete_IntVarLocalSearchFilter
+
+    def Synchronize(self, assignment: "Assignment", delta: "Assignment") -> "void":
+        r"""
+        This method should not be overridden. Override OnSynchronize() instead
+        which is called before exiting this method.
+        """
+        return _pywrapcp.IntVarLocalSearchFilter_Synchronize(self, assignment, delta)
+
+    def Size(self) -> "int":
+        return _pywrapcp.IntVarLocalSearchFilter_Size(self)
+
+    def Value(self, index: "int") -> "int64_t":
+        return _pywrapcp.IntVarLocalSearchFilter_Value(self, index)
+
+    def IndexFromVar(self, var: "IntVar") -> "int64_t":
+        return _pywrapcp.IntVarLocalSearchFilter_IndexFromVar(self, var)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_IntVarLocalSearchFilter(self)
+        return weakref.proxy(self)
+
+# Register IntVarLocalSearchFilter in _pywrapcp:
+_pywrapcp.IntVarLocalSearchFilter_swigregister(IntVarLocalSearchFilter)
+
+class BooleanVar(IntVar):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def Min(self) -> "int64_t":
+        return _pywrapcp.BooleanVar_Min(self)
+
+    def SetMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_SetMin(self, m)
+
+    def Max(self) -> "int64_t":
+        return _pywrapcp.BooleanVar_Max(self)
+
+    def SetMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_SetMax(self, m)
+
+    def SetRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_SetRange(self, mi, ma)
+
+    def Bound(self) -> "bool":
+        return _pywrapcp.BooleanVar_Bound(self)
+
+    def Value(self) -> "int64_t":
+        return _pywrapcp.BooleanVar_Value(self)
+
+    def RemoveValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_RemoveValue(self, v)
+
+    def RemoveInterval(self, l: "int64_t", u: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_RemoveInterval(self, l, u)
+
+    def WhenBound(self, d: "Demon") -> "void":
+        return _pywrapcp.BooleanVar_WhenBound(self, d)
+
+    def WhenRange(self, d: "Demon") -> "void":
+        return _pywrapcp.BooleanVar_WhenRange(self, d)
+
+    def WhenDomain(self, d: "Demon") -> "void":
+        return _pywrapcp.BooleanVar_WhenDomain(self, d)
+
+    def Size(self) -> "uint64_t":
+        return _pywrapcp.BooleanVar_Size(self)
+
+    def Contains(self, v: "int64_t") -> "bool":
+        return _pywrapcp.BooleanVar_Contains(self, v)
+
+    def HoleIteratorAux(self, reversible: "bool") -> "operations_research::IntVarIterator *":
+        return _pywrapcp.BooleanVar_HoleIteratorAux(self, reversible)
+
+    def DomainIteratorAux(self, reversible: "bool") -> "operations_research::IntVarIterator *":
+        return _pywrapcp.BooleanVar_DomainIteratorAux(self, reversible)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.BooleanVar_DebugString(self)
+
+# Register BooleanVar in _pywrapcp:
+_pywrapcp.BooleanVar_swigregister(BooleanVar)
+
+
+class PyDecision(Decision):
+
+  def __init__(self):
+    Decision.__init__(self)
+
+  def ApplyWrapper(self, solver):
+    try:
+       self.Apply(solver)
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        solver.ShouldFail()
+      else:
+        raise
+
+  def RefuteWrapper(self, solver):
+    try:
+       self.Refute(solver)
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        solver.ShouldFail()
+      else:
+        raise
+
+  def DebugString(self):
+    return "PyDecision"
+
+
+class PyDecisionBuilder(DecisionBuilder):
+
+  def __init__(self):
+    DecisionBuilder.__init__(self)
+
+  def NextWrapper(self, solver):
+    try:
+      return self.Next(solver)
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        return solver.FailDecision()
+      else:
+        raise
+
+  def DebugString(self):
+    return "PyDecisionBuilder"
+
+
+class PyDemon(Demon):
+
+  def RunWrapper(self, solver):
+    try:
+      self.Run(solver)
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        solver.ShouldFail()
+      else:
+        raise
+
+  def DebugString(self):
+    return "PyDemon"
+
+
+class PyConstraintDemon(PyDemon):
+
+  def __init__(self, ct, method, delayed, *args):
+    PyDemon.__init__(self)
+    self.__constraint = ct
+    self.__method = method
+    self.__delayed = delayed
+    self.__args = args
+
+  def Run(self, solver):
+    self.__method(self.__constraint, *self.__args)
+
+  def Priority(self):
+    return Solver.DELAYED_PRIORITY if self.__delayed else Solver.NORMAL_PRIORITY
+
+  def DebugString(self):
+    return 'PyConstraintDemon'
+
+
+class PyConstraint(Constraint):
+
+  def __init__(self, solver):
+    Constraint.__init__(self, solver)
+    self.__demons = []
+
+  def Demon(self, method, *args):
+    demon = PyConstraintDemon(self, method, False, *args)
+    self.__demons.append(demon)
+    return demon
+
+  def DelayedDemon(self, method, *args):
+    demon = PyConstraintDemon(self, method, True, *args)
+    self.__demons.append(demon)
+    return demon
+
+  def InitialPropagateDemon(self):
+    return self.solver().ConstraintInitialPropagateCallback(self)
+
+  def DelayedInitialPropagateDemon(self):
+    return self.solver().DelayedConstraintInitialPropagateCallback(self)
+
+  def InitialPropagateWrapper(self):
+    try:
+      self.InitialPropagate()
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        self.solver().ShouldFail()
+      else:
+        raise
+
+  def DebugString(self):
+    return "PyConstraint"
+
+
+
+class RoutingIndexManager(object):
+    r"""
+    Manager for any NodeIndex <-> variable index conversion. The routing solver
+    uses variable indices internally and through its API. These variable indices
+    are tricky to manage directly because one Node can correspond to a multitude
+    of variables, depending on the number of times they appear in the model, and
+    if they're used as start and/or end points. This class aims to simplify
+    variable index usage, allowing users to use NodeIndex instead.
+
+    Usage:
+
+      .. code-block:: c++
+
+          auto starts_ends = ...;  /// These are NodeIndex.
+          RoutingIndexManager manager(10, 4, starts_ends);  // 10 nodes, 4 vehicles.
+          RoutingModel model(manager);
+
+    Then, use 'manager.NodeToIndex(node)' whenever model requires a variable
+    index.
+
+    Note: the mapping between node indices and variables indices is subject to
+    change so no assumption should be made on it. The only guarantee is that
+    indices range between 0 and n-1, where n = number of vehicles * 2 (for start
+    and end nodes) + number of non-start or end nodes.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, *args):
+        _pywrapcp.RoutingIndexManager_swiginit(self, _pywrapcp.new_RoutingIndexManager(*args))
+    __swig_destroy__ = _pywrapcp.delete_RoutingIndexManager
+
+    def GetNumberOfNodes(self) -> "int":
+        return _pywrapcp.RoutingIndexManager_GetNumberOfNodes(self)
+
+    def GetNumberOfVehicles(self) -> "int":
+        return _pywrapcp.RoutingIndexManager_GetNumberOfVehicles(self)
+
+    def GetNumberOfIndices(self) -> "int":
+        return _pywrapcp.RoutingIndexManager_GetNumberOfIndices(self)
+
+    def GetStartIndex(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingIndexManager_GetStartIndex(self, vehicle)
+
+    def GetEndIndex(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingIndexManager_GetEndIndex(self, vehicle)
+
+    def NodeToIndex(self, node: "operations_research::RoutingIndexManager::NodeIndex") -> "int64_t":
+        return _pywrapcp.RoutingIndexManager_NodeToIndex(self, node)
+
+    def IndexToNode(self, index: "int64_t") -> "operations_research::RoutingIndexManager::NodeIndex":
+        return _pywrapcp.RoutingIndexManager_IndexToNode(self, index)
+
+# Register RoutingIndexManager in _pywrapcp:
+_pywrapcp.RoutingIndexManager_swigregister(RoutingIndexManager)
+
+
+def DefaultRoutingModelParameters() -> "operations_research::RoutingModelParameters":
+    return _pywrapcp.DefaultRoutingModelParameters()
+
+def DefaultRoutingSearchParameters() -> "operations_research::RoutingSearchParameters":
+    return _pywrapcp.DefaultRoutingSearchParameters()
+
+def FindErrorInRoutingSearchParameters(search_parameters: "operations_research::RoutingSearchParameters const &") -> "std::string":
+    r"""
+    Returns an empty std::string if the routing search parameters are valid, and
+    a non-empty, human readable error description if they're not.
+    """
+    return _pywrapcp.FindErrorInRoutingSearchParameters(search_parameters)
+BOOL_UNSPECIFIED = _pywrapcp.BOOL_UNSPECIFIED
+BOOL_FALSE = _pywrapcp.BOOL_FALSE
+BOOL_TRUE = _pywrapcp.BOOL_TRUE
+class RoutingModel(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+    ROUTING_NOT_SOLVED = _pywrapcp.RoutingModel_ROUTING_NOT_SOLVED
+    r""" Problem not solved yet (before calling RoutingModel::Solve())."""
+    ROUTING_SUCCESS = _pywrapcp.RoutingModel_ROUTING_SUCCESS
+    r""" Problem solved successfully after calling RoutingModel::Solve()."""
+    ROUTING_FAIL = _pywrapcp.RoutingModel_ROUTING_FAIL
+    r""" No solution found to the problem after calling RoutingModel::Solve()."""
+    ROUTING_FAIL_TIMEOUT = _pywrapcp.RoutingModel_ROUTING_FAIL_TIMEOUT
+    r""" Time limit reached before finding a solution with RoutingModel::Solve()."""
+    ROUTING_INVALID = _pywrapcp.RoutingModel_ROUTING_INVALID
+    r""" Model, model parameters or flags are not valid."""
+    ROUTING_INFEASIBLE = _pywrapcp.RoutingModel_ROUTING_INFEASIBLE
+    r""" Problem proven to be infeasible."""
+    PICKUP_AND_DELIVERY_NO_ORDER = _pywrapcp.RoutingModel_PICKUP_AND_DELIVERY_NO_ORDER
+    r""" Any precedence is accepted."""
+    PICKUP_AND_DELIVERY_LIFO = _pywrapcp.RoutingModel_PICKUP_AND_DELIVERY_LIFO
+    r""" Deliveries must be performed in reverse order of pickups."""
+    PICKUP_AND_DELIVERY_FIFO = _pywrapcp.RoutingModel_PICKUP_AND_DELIVERY_FIFO
+    r""" Deliveries must be performed in the same order as pickups."""
+
+    def __init__(self, *args):
+        _pywrapcp.RoutingModel_swiginit(self, _pywrapcp.new_RoutingModel(*args))
+    __swig_destroy__ = _pywrapcp.delete_RoutingModel
+
+    def RegisterUnaryTransitVector(self, values: "std::vector< int64_t >") -> "int":
+        r""" Registers 'callback' and returns its index."""
+        return _pywrapcp.RoutingModel_RegisterUnaryTransitVector(self, values)
+
+    def RegisterUnaryTransitCallback(self, callback: "operations_research::RoutingModel::TransitCallback1") -> "int":
+        return _pywrapcp.RoutingModel_RegisterUnaryTransitCallback(self, callback)
+
+    def RegisterPositiveUnaryTransitCallback(self, callback: "operations_research::RoutingModel::TransitCallback1") -> "int":
+        return _pywrapcp.RoutingModel_RegisterPositiveUnaryTransitCallback(self, callback)
+
+    def RegisterTransitMatrix(self, values: "std::vector< std::vector< int64_t > >") -> "int":
+        return _pywrapcp.RoutingModel_RegisterTransitMatrix(self, values)
+
+    def RegisterTransitCallback(self, callback: "operations_research::RoutingModel::TransitCallback2") -> "int":
+        return _pywrapcp.RoutingModel_RegisterTransitCallback(self, callback)
+
+    def RegisterPositiveTransitCallback(self, callback: "operations_research::RoutingModel::TransitCallback2") -> "int":
+        return _pywrapcp.RoutingModel_RegisterPositiveTransitCallback(self, callback)
+
+    def TransitCallback(self, callback_index: "int") -> "operations_research::RoutingModel::TransitCallback2 const &":
+        return _pywrapcp.RoutingModel_TransitCallback(self, callback_index)
+
+    def UnaryTransitCallbackOrNull(self, callback_index: "int") -> "operations_research::RoutingModel::TransitCallback1 const &":
+        return _pywrapcp.RoutingModel_UnaryTransitCallbackOrNull(self, callback_index)
+
+    def AddDimension(self, evaluator_index: "int", slack_max: "int64_t", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "bool":
+        r"""
+        Model creation
+        Methods to add dimensions to routes; dimensions represent quantities
+        accumulated at nodes along the routes. They represent quantities such as
+        weights or volumes carried along the route, or distance or times.
+        Quantities at a node are represented by "cumul" variables and the increase
+        or decrease of quantities between nodes are represented by "transit"
+        variables. These variables are linked as follows:
+        if j == next(i), cumul(j) = cumul(i) + transit(i) + slack(i)
+        where slack is a positive slack variable (can represent waiting times for
+        a time dimension).
+        Setting the value of fix_start_cumul_to_zero to true will force the
+        "cumul" variable of the start node of all vehicles to be equal to 0.
+        Creates a dimension where the transit variable is constrained to be
+        equal to evaluator(i, next(i)); 'slack_max' is the upper bound of the
+        slack variable and 'capacity' is the upper bound of the cumul variables.
+        'name' is the name used to reference the dimension; this name is used to
+        get cumul and transit variables from the routing model.
+        Returns false if a dimension with the same name has already been created
+        (and doesn't create the new dimension).
+        Takes ownership of the callback 'evaluator'.
+        """
+        return _pywrapcp.RoutingModel_AddDimension(self, evaluator_index, slack_max, capacity, fix_start_cumul_to_zero, name)
+
+    def AddDimensionWithVehicleTransits(self, evaluator_indices: "std::vector< int > const &", slack_max: "int64_t", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "bool":
+        return _pywrapcp.RoutingModel_AddDimensionWithVehicleTransits(self, evaluator_indices, slack_max, capacity, fix_start_cumul_to_zero, name)
+
+    def AddDimensionWithVehicleCapacity(self, evaluator_index: "int", slack_max: "int64_t", vehicle_capacities: "std::vector< int64_t >", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "bool":
+        return _pywrapcp.RoutingModel_AddDimensionWithVehicleCapacity(self, evaluator_index, slack_max, vehicle_capacities, fix_start_cumul_to_zero, name)
+
+    def AddDimensionWithVehicleTransitAndCapacity(self, evaluator_indices: "std::vector< int > const &", slack_max: "int64_t", vehicle_capacities: "std::vector< int64_t >", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "bool":
+        return _pywrapcp.RoutingModel_AddDimensionWithVehicleTransitAndCapacity(self, evaluator_indices, slack_max, vehicle_capacities, fix_start_cumul_to_zero, name)
+
+    def AddConstantDimensionWithSlack(self, value: "int64_t", capacity: "int64_t", slack_max: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "std::pair< int,bool >":
+        r"""
+        Creates a dimension where the transit variable is constrained to be
+        equal to 'value'; 'capacity' is the upper bound of the cumul variables.
+        'name' is the name used to reference the dimension; this name is used to
+        get cumul and transit variables from the routing model.
+        Returns a pair consisting of an index to the registered unary transit
+        callback and a bool denoting whether the dimension has been created.
+        It is false if a dimension with the same name has already been created
+        (and doesn't create the new dimension but still register a new callback).
+        """
+        return _pywrapcp.RoutingModel_AddConstantDimensionWithSlack(self, value, capacity, slack_max, fix_start_cumul_to_zero, name)
+
+    def AddConstantDimension(self, value: "int64_t", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "std::pair< int,bool >":
+        return _pywrapcp.RoutingModel_AddConstantDimension(self, value, capacity, fix_start_cumul_to_zero, name)
+
+    def AddVectorDimension(self, values: "std::vector< int64_t >", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "std::pair< int,bool >":
+        r"""
+        Creates a dimension where the transit variable is constrained to be
+        equal to 'values[i]' for node i; 'capacity' is the upper bound of
+        the cumul variables. 'name' is the name used to reference the dimension;
+        this name is used to get cumul and transit variables from the routing
+        model.
+        Returns a pair consisting of an index to the registered unary transit
+        callback and a bool denoting whether the dimension has been created.
+        It is false if a dimension with the same name has already been created
+        (and doesn't create the new dimension but still register a new callback).
+        """
+        return _pywrapcp.RoutingModel_AddVectorDimension(self, values, capacity, fix_start_cumul_to_zero, name)
+
+    def AddMatrixDimension(self, values: "std::vector< std::vector< int64_t > >", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "std::pair< int,bool >":
+        r"""
+        Creates a dimension where the transit variable is constrained to be
+        equal to 'values[i][next(i)]' for node i; 'capacity' is the upper bound of
+        the cumul variables. 'name' is the name used to reference the dimension;
+        this name is used to get cumul and transit variables from the routing
+        model.
+        Returns a pair consisting of an index to the registered transit callback
+        and a bool denoting whether the dimension has been created.
+        It is false if a dimension with the same name has already been created
+        (and doesn't create the new dimension but still register a new callback).
+        """
+        return _pywrapcp.RoutingModel_AddMatrixDimension(self, values, capacity, fix_start_cumul_to_zero, name)
+
+    def MakePathSpansAndTotalSlacks(self, dimension: "RoutingDimension", spans: "std::vector< operations_research::IntVar * >", total_slacks: "std::vector< operations_research::IntVar * >") -> "operations_research::Constraint *":
+        r"""
+        For every vehicle of the routing model:
+        - if total_slacks[vehicle] is not nullptr, constrains it to be the sum of
+          slacks on that vehicle, that is,
+          dimension->CumulVar(end) - dimension->CumulVar(start) -
+          sum_{node in path of vehicle} dimension->FixedTransitVar(node).
+        - if spans[vehicle] is not nullptr, constrains it to be
+          dimension->CumulVar(end) - dimension->CumulVar(start)
+        This does stronger propagation than a decomposition, and takes breaks into
+        account.
+        """
+        return _pywrapcp.RoutingModel_MakePathSpansAndTotalSlacks(self, dimension, spans, total_slacks)
+
+    def GetAllDimensionNames(self) -> "std::vector< std::string >":
+        r""" Outputs the names of all dimensions added to the routing engine."""
+        return _pywrapcp.RoutingModel_GetAllDimensionNames(self)
+
+    def GetDimensions(self) -> "std::vector< operations_research::RoutingDimension * > const &":
+        r""" Returns all dimensions of the model."""
+        return _pywrapcp.RoutingModel_GetDimensions(self)
+
+    def GetDimensionsWithSoftOrSpanCosts(self) -> "std::vector< operations_research::RoutingDimension * >":
+        r""" Returns dimensions with soft or vehicle span costs."""
+        return _pywrapcp.RoutingModel_GetDimensionsWithSoftOrSpanCosts(self)
+
+    def GetGlobalDimensionCumulOptimizers(self) -> "std::vector< std::unique_ptr< operations_research::GlobalDimensionCumulOptimizer > > const &":
+        r"""
+        Returns [global|local]_dimension_optimizers_, which are empty if the model
+        has not been closed.
+        """
+        return _pywrapcp.RoutingModel_GetGlobalDimensionCumulOptimizers(self)
+
+    def GetGlobalDimensionCumulMPOptimizers(self) -> "std::vector< std::unique_ptr< operations_research::GlobalDimensionCumulOptimizer > > const &":
+        return _pywrapcp.RoutingModel_GetGlobalDimensionCumulMPOptimizers(self)
+
+    def GetLocalDimensionCumulOptimizers(self) -> "std::vector< std::unique_ptr< operations_research::LocalDimensionCumulOptimizer > > const &":
+        return _pywrapcp.RoutingModel_GetLocalDimensionCumulOptimizers(self)
+
+    def GetLocalDimensionCumulMPOptimizers(self) -> "std::vector< std::unique_ptr< operations_research::LocalDimensionCumulOptimizer > > const &":
+        return _pywrapcp.RoutingModel_GetLocalDimensionCumulMPOptimizers(self)
+
+    def GetMutableGlobalCumulOptimizer(self, dimension: "RoutingDimension") -> "operations_research::GlobalDimensionCumulOptimizer *":
+        r"""
+        Returns the global/local dimension cumul optimizer for a given dimension,
+        or nullptr if there is none.
+        """
+        return _pywrapcp.RoutingModel_GetMutableGlobalCumulOptimizer(self, dimension)
+
+    def GetMutableGlobalCumulMPOptimizer(self, dimension: "RoutingDimension") -> "operations_research::GlobalDimensionCumulOptimizer *":
+        return _pywrapcp.RoutingModel_GetMutableGlobalCumulMPOptimizer(self, dimension)
+
+    def GetMutableLocalCumulOptimizer(self, dimension: "RoutingDimension") -> "operations_research::LocalDimensionCumulOptimizer *":
+        return _pywrapcp.RoutingModel_GetMutableLocalCumulOptimizer(self, dimension)
+
+    def GetMutableLocalCumulMPOptimizer(self, dimension: "RoutingDimension") -> "operations_research::LocalDimensionCumulOptimizer *":
+        return _pywrapcp.RoutingModel_GetMutableLocalCumulMPOptimizer(self, dimension)
+
+    def HasDimension(self, dimension_name: "std::string const &") -> "bool":
+        r""" Returns true if a dimension exists for a given dimension name."""
+        return _pywrapcp.RoutingModel_HasDimension(self, dimension_name)
+
+    def GetDimensionOrDie(self, dimension_name: "std::string const &") -> "operations_research::RoutingDimension const &":
+        r""" Returns a dimension from its name. Dies if the dimension does not exist."""
+        return _pywrapcp.RoutingModel_GetDimensionOrDie(self, dimension_name)
+
+    def GetMutableDimension(self, dimension_name: "std::string const &") -> "operations_research::RoutingDimension *":
+        r"""
+        Returns a dimension from its name. Returns nullptr if the dimension does
+        not exist.
+        """
+        return _pywrapcp.RoutingModel_GetMutableDimension(self, dimension_name)
+
+    def SetPrimaryConstrainedDimension(self, dimension_name: "std::string const &") -> "void":
+        r"""
+        Set the given dimension as "primary constrained". As of August 2013, this
+        is only used by ArcIsMoreConstrainedThanArc().
+        "dimension" must be the name of an existing dimension, or be empty, in
+        which case there will not be a primary dimension after this call.
+        """
+        return _pywrapcp.RoutingModel_SetPrimaryConstrainedDimension(self, dimension_name)
+
+    def GetPrimaryConstrainedDimension(self) -> "std::string const &":
+        r""" Get the primary constrained dimension, or an empty string if it is unset."""
+        return _pywrapcp.RoutingModel_GetPrimaryConstrainedDimension(self)
+
+    def AddResourceGroup(self) -> "int":
+        r"""
+        Adds a resource group to the routing model. Returns its index in
+        resource_groups_.
+        """
+        return _pywrapcp.RoutingModel_AddResourceGroup(self)
+
+    def GetDimensionResourceGroupIndices(self, dimension: "RoutingDimension") -> "std::vector< int > const &":
+        r"""
+        Returns the indices of resource groups for this dimension. This method can
+        only be called after the model has been closed.
+        """
+        return _pywrapcp.RoutingModel_GetDimensionResourceGroupIndices(self, dimension)
+
+    def GetDimensionResourceGroupIndex(self, dimension: "RoutingDimension") -> "int":
+        r"""
+        Returns the index of the resource group attached to the dimension.
+        DCHECKS that there's exactly one resource group for this dimension.
+        """
+        return _pywrapcp.RoutingModel_GetDimensionResourceGroupIndex(self, dimension)
+
+    def AddDisjunction(self, *args) -> "operations_research::RoutingModel::DisjunctionIndex":
+        r"""
+        Adds a disjunction constraint on the indices: exactly 'max_cardinality' of
+        the indices are active. Start and end indices of any vehicle cannot be
+        part of a disjunction.
+
+        If a penalty is given, at most 'max_cardinality' of the indices can be
+        active, and if less are active, 'penalty' is payed per inactive index.
+        This is equivalent to adding the constraint:
+            p + Sum(i)active[i] == max_cardinality
+        where p is an integer variable, and the following cost to the cost
+        function:
+            p * penalty.
+        'penalty' must be positive to make the disjunction optional; a negative
+        penalty will force 'max_cardinality' indices of the disjunction to be
+        performed, and therefore p == 0.
+        Note: passing a vector with a single index will model an optional index
+        with a penalty cost if it is not visited.
+        """
+        return _pywrapcp.RoutingModel_AddDisjunction(self, *args)
+
+    def GetDisjunctionIndices(self, index: "int64_t") -> "std::vector< operations_research::RoutingModel::DisjunctionIndex > const &":
+        r""" Returns the indices of the disjunctions to which an index belongs."""
+        return _pywrapcp.RoutingModel_GetDisjunctionIndices(self, index)
+
+    def GetDisjunctionPenalty(self, index: "operations_research::RoutingModel::DisjunctionIndex") -> "int64_t":
+        r""" Returns the penalty of the node disjunction of index 'index'."""
+        return _pywrapcp.RoutingModel_GetDisjunctionPenalty(self, index)
+
+    def GetDisjunctionMaxCardinality(self, index: "operations_research::RoutingModel::DisjunctionIndex") -> "int64_t":
+        r"""
+        Returns the maximum number of possible active nodes of the node
+        disjunction of index 'index'.
+        """
+        return _pywrapcp.RoutingModel_GetDisjunctionMaxCardinality(self, index)
+
+    def GetNumberOfDisjunctions(self) -> "int":
+        r""" Returns the number of node disjunctions in the model."""
+        return _pywrapcp.RoutingModel_GetNumberOfDisjunctions(self)
+
+    def HasMandatoryDisjunctions(self) -> "bool":
+        r"""
+        Returns true if the model contains mandatory disjunctions (ones with
+        kNoPenalty as penalty).
+        """
+        return _pywrapcp.RoutingModel_HasMandatoryDisjunctions(self)
+
+    def HasMaxCardinalityConstrainedDisjunctions(self) -> "bool":
+        r"""
+        Returns true if the model contains at least one disjunction which is
+        constrained by its max_cardinality.
+        """
+        return _pywrapcp.RoutingModel_HasMaxCardinalityConstrainedDisjunctions(self)
+
+    def GetPerfectBinaryDisjunctions(self) -> "std::vector< std::pair< int64_t,int64_t > >":
+        r"""
+        Returns the list of all perfect binary disjunctions, as pairs of variable
+        indices: a disjunction is "perfect" when its variables do not appear in
+        any other disjunction. Each pair is sorted (lowest variable index first),
+        and the output vector is also sorted (lowest pairs first).
+        """
+        return _pywrapcp.RoutingModel_GetPerfectBinaryDisjunctions(self)
+
+    def IgnoreDisjunctionsAlreadyForcedToZero(self) -> "void":
+        r"""
+        SPECIAL: Makes the solver ignore all the disjunctions whose active
+        variables are all trivially zero (i.e. Max() == 0), by setting their
+        max_cardinality to 0.
+        This can be useful when using the BaseBinaryDisjunctionNeighborhood
+        operators, in the context of arc-based routing.
+        """
+        return _pywrapcp.RoutingModel_IgnoreDisjunctionsAlreadyForcedToZero(self)
+
+    def AddSoftSameVehicleConstraint(self, indices: "std::vector< int64_t > const &", cost: "int64_t") -> "void":
+        r"""
+        Adds a soft constraint to force a set of variable indices to be on the
+        same vehicle. If all nodes are not on the same vehicle, each extra vehicle
+        used adds 'cost' to the cost function.
+        """
+        return _pywrapcp.RoutingModel_AddSoftSameVehicleConstraint(self, indices, cost)
+
+    def SetAllowedVehiclesForIndex(self, vehicles: "std::vector< int > const &", index: "int64_t") -> "void":
+        r"""
+        Sets the vehicles which can visit a given node. If the node is in a
+        disjunction, this will not prevent it from being unperformed.
+        Specifying an empty vector of vehicles has no effect (all vehicles
+        will be allowed to visit the node).
+        """
+        return _pywrapcp.RoutingModel_SetAllowedVehiclesForIndex(self, vehicles, index)
+
+    def IsVehicleAllowedForIndex(self, vehicle: "int", index: "int64_t") -> "bool":
+        r""" Returns true if a vehicle is allowed to visit a given node."""
+        return _pywrapcp.RoutingModel_IsVehicleAllowedForIndex(self, vehicle, index)
+
+    def AddPickupAndDelivery(self, pickup: "int64_t", delivery: "int64_t") -> "void":
+        r"""
+        Notifies that index1 and index2 form a pair of nodes which should belong
+        to the same route. This methods helps the search find better solutions,
+        especially in the local search phase.
+        It should be called each time you have an equality constraint linking
+        the vehicle variables of two node (including for instance pickup and
+        delivery problems):
+            Solver* const solver = routing.solver();
+            int64_t index1 = manager.NodeToIndex(node1);
+            int64_t index2 = manager.NodeToIndex(node2);
+            solver->AddConstraint(solver->MakeEquality(
+                routing.VehicleVar(index1),
+                routing.VehicleVar(index2)));
+            routing.AddPickupAndDelivery(index1, index2);
+        """
+        return _pywrapcp.RoutingModel_AddPickupAndDelivery(self, pickup, delivery)
+
+    def AddPickupAndDeliverySets(self, pickup_disjunction: "operations_research::RoutingModel::DisjunctionIndex", delivery_disjunction: "operations_research::RoutingModel::DisjunctionIndex") -> "void":
+        r"""
+        Same as AddPickupAndDelivery but notifying that the performed node from
+        the disjunction of index 'pickup_disjunction' is on the same route as the
+        performed node from the disjunction of index 'delivery_disjunction'.
+        """
+        return _pywrapcp.RoutingModel_AddPickupAndDeliverySets(self, pickup_disjunction, delivery_disjunction)
+
+    def GetPickupIndexPairs(self, node_index: "int64_t") -> "std::vector< std::pair< int,int > > const &":
+        r"""
+        Returns pairs for which the node is a pickup; the first element of each
+        pair is the index in the pickup and delivery pairs list in which the
+        pickup appears, the second element is its index in the pickups list.
+        """
+        return _pywrapcp.RoutingModel_GetPickupIndexPairs(self, node_index)
+
+    def GetDeliveryIndexPairs(self, node_index: "int64_t") -> "std::vector< std::pair< int,int > > const &":
+        r""" Same as above for deliveries."""
+        return _pywrapcp.RoutingModel_GetDeliveryIndexPairs(self, node_index)
+
+    def SetPickupAndDeliveryPolicyOfAllVehicles(self, policy: "operations_research::RoutingModel::PickupAndDeliveryPolicy") -> "void":
+        r"""
+        Sets the Pickup and delivery policy of all vehicles. It is equivalent to
+        calling SetPickupAndDeliveryPolicyOfVehicle on all vehicles.
+        """
+        return _pywrapcp.RoutingModel_SetPickupAndDeliveryPolicyOfAllVehicles(self, policy)
+
+    def SetPickupAndDeliveryPolicyOfVehicle(self, policy: "operations_research::RoutingModel::PickupAndDeliveryPolicy", vehicle: "int") -> "void":
+        return _pywrapcp.RoutingModel_SetPickupAndDeliveryPolicyOfVehicle(self, policy, vehicle)
+
+    def GetPickupAndDeliveryPolicyOfVehicle(self, vehicle: "int") -> "operations_research::RoutingModel::PickupAndDeliveryPolicy":
+        return _pywrapcp.RoutingModel_GetPickupAndDeliveryPolicyOfVehicle(self, vehicle)
+
+    def GetNumOfSingletonNodes(self) -> "int":
+        r"""
+        Returns the number of non-start/end nodes which do not appear in a
+        pickup/delivery pair.
+        """
+        return _pywrapcp.RoutingModel_GetNumOfSingletonNodes(self)
+    TYPE_ADDED_TO_VEHICLE = _pywrapcp.RoutingModel_TYPE_ADDED_TO_VEHICLE
+    r""" When visited, the number of types 'T' on the vehicle increases by one."""
+    ADDED_TYPE_REMOVED_FROM_VEHICLE = _pywrapcp.RoutingModel_ADDED_TYPE_REMOVED_FROM_VEHICLE
+    r"""
+    When visited, one instance of type 'T' previously added to the route
+    (TYPE_ADDED_TO_VEHICLE), if any, is removed from the vehicle.
+    If the type was not previously added to the route or all added instances
+    have already been removed, this visit has no effect on the types.
+    """
+    TYPE_ON_VEHICLE_UP_TO_VISIT = _pywrapcp.RoutingModel_TYPE_ON_VEHICLE_UP_TO_VISIT
+    r"""
+    With the following policy, the visit enforces that type 'T' is
+    considered on the route from its start until this node is visited.
+    """
+    TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED = _pywrapcp.RoutingModel_TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED
+    r"""
+    The visit doesn't have an impact on the number of types 'T' on the
+    route, as it's (virtually) added and removed directly.
+    This policy can be used for visits which are part of an incompatibility
+    or requirement set without affecting the type count on the route.
+    """
+
+    def SetVisitType(self, index: "int64_t", type: "int", type_policy: "operations_research::RoutingModel::VisitTypePolicy") -> "void":
+        return _pywrapcp.RoutingModel_SetVisitType(self, index, type, type_policy)
+
+    def GetVisitType(self, index: "int64_t") -> "int":
+        return _pywrapcp.RoutingModel_GetVisitType(self, index)
+
+    def GetSingleNodesOfType(self, type: "int") -> "std::vector< int > const &":
+        return _pywrapcp.RoutingModel_GetSingleNodesOfType(self, type)
+
+    def GetPairIndicesOfType(self, type: "int") -> "std::vector< int > const &":
+        return _pywrapcp.RoutingModel_GetPairIndicesOfType(self, type)
+
+    def GetVisitTypePolicy(self, index: "int64_t") -> "operations_research::RoutingModel::VisitTypePolicy":
+        return _pywrapcp.RoutingModel_GetVisitTypePolicy(self, index)
+
+    def CloseVisitTypes(self) -> "void":
+        r"""
+        This function should be called once all node visit types have been set and
+        prior to adding any incompatibilities/requirements.
+        "close" types.
+        """
+        return _pywrapcp.RoutingModel_CloseVisitTypes(self)
+
+    def GetNumberOfVisitTypes(self) -> "int":
+        return _pywrapcp.RoutingModel_GetNumberOfVisitTypes(self)
+
+    def AddHardTypeIncompatibility(self, type1: "int", type2: "int") -> "void":
+        r"""
+        Incompatibilities:
+        Two nodes with "hard" incompatible types cannot share the same route at
+        all, while with a "temporal" incompatibility they can't be on the same
+        route at the same time.
+        """
+        return _pywrapcp.RoutingModel_AddHardTypeIncompatibility(self, type1, type2)
+
+    def AddTemporalTypeIncompatibility(self, type1: "int", type2: "int") -> "void":
+        return _pywrapcp.RoutingModel_AddTemporalTypeIncompatibility(self, type1, type2)
+
+    def GetHardTypeIncompatibilitiesOfType(self, type: "int") -> "absl::flat_hash_set< int > const &":
+        r""" Returns visit types incompatible with a given type."""
+        return _pywrapcp.RoutingModel_GetHardTypeIncompatibilitiesOfType(self, type)
+
+    def GetTemporalTypeIncompatibilitiesOfType(self, type: "int") -> "absl::flat_hash_set< int > const &":
+        return _pywrapcp.RoutingModel_GetTemporalTypeIncompatibilitiesOfType(self, type)
+
+    def HasHardTypeIncompatibilities(self) -> "bool":
+        r"""
+        Returns true iff any hard (resp. temporal) type incompatibilities have
+        been added to the model.
+        """
+        return _pywrapcp.RoutingModel_HasHardTypeIncompatibilities(self)
+
+    def HasTemporalTypeIncompatibilities(self) -> "bool":
+        return _pywrapcp.RoutingModel_HasTemporalTypeIncompatibilities(self)
+
+    def AddSameVehicleRequiredTypeAlternatives(self, dependent_type: "int", required_type_alternatives: "absl::flat_hash_set< int >") -> "void":
+        r"""
+        Requirements:
+        NOTE: As of 2019-04, cycles in the requirement graph are not supported,
+        and lead to the dependent nodes being skipped if possible (otherwise
+        the model is considered infeasible).
+        The following functions specify that "dependent_type" requires at least
+        one of the types in "required_type_alternatives".
+
+        For same-vehicle requirements, a node of dependent type type_D requires at
+        least one node of type type_R among the required alternatives on the same
+        route.
+        """
+        return _pywrapcp.RoutingModel_AddSameVehicleRequiredTypeAlternatives(self, dependent_type, required_type_alternatives)
+
+    def AddRequiredTypeAlternativesWhenAddingType(self, dependent_type: "int", required_type_alternatives: "absl::flat_hash_set< int >") -> "void":
+        r"""
+        If type_D depends on type_R when adding type_D, any node_D of type_D and
+        VisitTypePolicy TYPE_ADDED_TO_VEHICLE or
+        TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED requires at least one type_R on its
+        vehicle at the time node_D is visited.
+        """
+        return _pywrapcp.RoutingModel_AddRequiredTypeAlternativesWhenAddingType(self, dependent_type, required_type_alternatives)
+
+    def AddRequiredTypeAlternativesWhenRemovingType(self, dependent_type: "int", required_type_alternatives: "absl::flat_hash_set< int >") -> "void":
+        r"""
+        The following requirements apply when visiting dependent nodes that remove
+        their type from the route, i.e. type_R must be on the vehicle when type_D
+        of VisitTypePolicy ADDED_TYPE_REMOVED_FROM_VEHICLE,
+        TYPE_ON_VEHICLE_UP_TO_VISIT or TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED is
+        visited.
+        """
+        return _pywrapcp.RoutingModel_AddRequiredTypeAlternativesWhenRemovingType(self, dependent_type, required_type_alternatives)
+
+    def GetSameVehicleRequiredTypeAlternativesOfType(self, type: "int") -> "std::vector< absl::flat_hash_set< int > > const &":
+        r"""
+        Returns the set of same-vehicle requirement alternatives for the given
+        type.
+        """
+        return _pywrapcp.RoutingModel_GetSameVehicleRequiredTypeAlternativesOfType(self, type)
+
+    def GetRequiredTypeAlternativesWhenAddingType(self, type: "int") -> "std::vector< absl::flat_hash_set< int > > const &":
+        r""" Returns the set of requirement alternatives when adding the given type."""
+        return _pywrapcp.RoutingModel_GetRequiredTypeAlternativesWhenAddingType(self, type)
+
+    def GetRequiredTypeAlternativesWhenRemovingType(self, type: "int") -> "std::vector< absl::flat_hash_set< int > > const &":
+        r""" Returns the set of requirement alternatives when removing the given type."""
+        return _pywrapcp.RoutingModel_GetRequiredTypeAlternativesWhenRemovingType(self, type)
+
+    def HasSameVehicleTypeRequirements(self) -> "bool":
+        r"""
+        Returns true iff any same-route (resp. temporal) type requirements have
+        been added to the model.
+        """
+        return _pywrapcp.RoutingModel_HasSameVehicleTypeRequirements(self)
+
+    def HasTemporalTypeRequirements(self) -> "bool":
+        return _pywrapcp.RoutingModel_HasTemporalTypeRequirements(self)
+
+    def HasTypeRegulations(self) -> "bool":
+        r"""
+        Returns true iff the model has any incompatibilities or requirements set
+        on node types.
+        """
+        return _pywrapcp.RoutingModel_HasTypeRegulations(self)
+
+    def UnperformedPenalty(self, var_index: "int64_t") -> "int64_t":
+        r"""
+        Get the "unperformed" penalty of a node. This is only well defined if the
+        node is only part of a single Disjunction, and that disjunction has a
+        penalty. For forced active nodes returns max int64_t. In all other cases,
+        this returns 0.
+        """
+        return _pywrapcp.RoutingModel_UnperformedPenalty(self, var_index)
+
+    def UnperformedPenaltyOrValue(self, default_value: "int64_t", var_index: "int64_t") -> "int64_t":
+        r"""
+        Same as above except that it returns default_value instead of 0 when
+        penalty is not well defined (default value is passed as first argument to
+        simplify the usage of the method in a callback).
+        """
+        return _pywrapcp.RoutingModel_UnperformedPenaltyOrValue(self, default_value, var_index)
+
+    def GetDepot(self) -> "int64_t":
+        r"""
+        Returns the variable index of the first starting or ending node of all
+        routes. If all routes start  and end at the same node (single depot), this
+        is the node returned.
+        """
+        return _pywrapcp.RoutingModel_GetDepot(self)
+
+    def SetMaximumNumberOfActiveVehicles(self, max_active_vehicles: "int") -> "void":
+        r"""
+        Constrains the maximum number of active vehicles, aka the number of
+        vehicles which do not have an empty route. For instance, this can be used
+        to limit the number of routes in the case where there are fewer drivers
+        than vehicles and that the fleet of vehicle is heterogeneous.
+        """
+        return _pywrapcp.RoutingModel_SetMaximumNumberOfActiveVehicles(self, max_active_vehicles)
+
+    def GetMaximumNumberOfActiveVehicles(self) -> "int":
+        r""" Returns the maximum number of active vehicles."""
+        return _pywrapcp.RoutingModel_GetMaximumNumberOfActiveVehicles(self)
+
+    def SetArcCostEvaluatorOfAllVehicles(self, evaluator_index: "int") -> "void":
+        r"""
+        Sets the cost function of the model such that the cost of a segment of a
+        route between node 'from' and 'to' is evaluator(from, to), whatever the
+        route or vehicle performing the route.
+        """
+        return _pywrapcp.RoutingModel_SetArcCostEvaluatorOfAllVehicles(self, evaluator_index)
+
+    def SetArcCostEvaluatorOfVehicle(self, evaluator_index: "int", vehicle: "int") -> "void":
+        r""" Sets the cost function for a given vehicle route."""
+        return _pywrapcp.RoutingModel_SetArcCostEvaluatorOfVehicle(self, evaluator_index, vehicle)
+
+    def SetFixedCostOfAllVehicles(self, cost: "int64_t") -> "void":
+        r"""
+        Sets the fixed cost of all vehicle routes. It is equivalent to calling
+        SetFixedCostOfVehicle on all vehicle routes.
+        """
+        return _pywrapcp.RoutingModel_SetFixedCostOfAllVehicles(self, cost)
+
+    def SetFixedCostOfVehicle(self, cost: "int64_t", vehicle: "int") -> "void":
+        r""" Sets the fixed cost of one vehicle route."""
+        return _pywrapcp.RoutingModel_SetFixedCostOfVehicle(self, cost, vehicle)
+
+    def GetFixedCostOfVehicle(self, vehicle: "int") -> "int64_t":
+        r"""
+        Returns the route fixed cost taken into account if the route of the
+        vehicle is not empty, aka there's at least one node on the route other
+        than the first and last nodes.
+        """
+        return _pywrapcp.RoutingModel_GetFixedCostOfVehicle(self, vehicle)
+
+    def SetAmortizedCostFactorsOfAllVehicles(self, linear_cost_factor: "int64_t", quadratic_cost_factor: "int64_t") -> "void":
+        r"""
+        The following methods set the linear and quadratic cost factors of
+        vehicles (must be positive values). The default value of these parameters
+        is zero for all vehicles.
+
+        When set, the cost_ of the model will contain terms aiming at reducing the
+        number of vehicles used in the model, by adding the following to the
+        objective for every vehicle v:
+        INDICATOR(v used in the model) *
+          [linear_cost_factor_of_vehicle_[v]
+           - quadratic_cost_factor_of_vehicle_[v]*(square of length of route v)]
+        i.e. for every used vehicle, we add the linear factor as fixed cost, and
+        subtract the square of the route length multiplied by the quadratic
+        factor. This second term aims at making the routes as dense as possible.
+
+        Sets the linear and quadratic cost factor of all vehicles.
+        """
+        return _pywrapcp.RoutingModel_SetAmortizedCostFactorsOfAllVehicles(self, linear_cost_factor, quadratic_cost_factor)
+
+    def SetAmortizedCostFactorsOfVehicle(self, linear_cost_factor: "int64_t", quadratic_cost_factor: "int64_t", vehicle: "int") -> "void":
+        r""" Sets the linear and quadratic cost factor of the given vehicle."""
+        return _pywrapcp.RoutingModel_SetAmortizedCostFactorsOfVehicle(self, linear_cost_factor, quadratic_cost_factor, vehicle)
+
+    def GetAmortizedLinearCostFactorOfVehicles(self) -> "std::vector< int64_t > const &":
+        return _pywrapcp.RoutingModel_GetAmortizedLinearCostFactorOfVehicles(self)
+
+    def GetAmortizedQuadraticCostFactorOfVehicles(self) -> "std::vector< int64_t > const &":
+        return _pywrapcp.RoutingModel_GetAmortizedQuadraticCostFactorOfVehicles(self)
+
+    def SetVehicleUsedWhenEmpty(self, is_used: "bool", vehicle: "int") -> "void":
+        return _pywrapcp.RoutingModel_SetVehicleUsedWhenEmpty(self, is_used, vehicle)
+
+    def IsVehicleUsedWhenEmpty(self, vehicle: "int") -> "bool":
+        return _pywrapcp.RoutingModel_IsVehicleUsedWhenEmpty(self, vehicle)
+
+    def SetFirstSolutionEvaluator(self, evaluator: "operations_research::Solver::IndexEvaluator2") -> "void":
+        r"""
+        Gets/sets the evaluator used during the search. Only relevant when
+        RoutingSearchParameters.first_solution_strategy = EVALUATOR_STRATEGY.
+        Takes ownership of evaluator.
+        """
+        return _pywrapcp.RoutingModel_SetFirstSolutionEvaluator(self, evaluator)
+
+    def AddLocalSearchOperator(self, ls_operator: "LocalSearchOperator") -> "void":
+        r"""
+        Adds a local search operator to the set of operators used to solve the
+        vehicle routing problem.
+        """
+        return _pywrapcp.RoutingModel_AddLocalSearchOperator(self, ls_operator)
+
+    def AddSearchMonitor(self, monitor: "SearchMonitor") -> "void":
+        r""" Adds a search monitor to the search used to solve the routing model."""
+        return _pywrapcp.RoutingModel_AddSearchMonitor(self, monitor)
+
+    def AddAtSolutionCallback(self, callback: "std::function< void () >") -> "void":
+        r"""
+        Adds a callback called each time a solution is found during the search.
+        This is a shortcut to creating a monitor to call the callback on
+        AtSolution() and adding it with AddSearchMonitor.
+        """
+        return _pywrapcp.RoutingModel_AddAtSolutionCallback(self, callback)
+
+    def AddVariableMinimizedByFinalizer(self, var: "IntVar") -> "void":
+        r"""
+        Adds a variable to minimize in the solution finalizer. The solution
+        finalizer is called each time a solution is found during the search and
+        allows to instantiate secondary variables (such as dimension cumul
+        variables).
+        """
+        return _pywrapcp.RoutingModel_AddVariableMinimizedByFinalizer(self, var)
+
+    def AddVariableMaximizedByFinalizer(self, var: "IntVar") -> "void":
+        r"""
+        Adds a variable to maximize in the solution finalizer (see above for
+        information on the solution finalizer).
+        """
+        return _pywrapcp.RoutingModel_AddVariableMaximizedByFinalizer(self, var)
+
+    def AddWeightedVariableMinimizedByFinalizer(self, var: "IntVar", cost: "int64_t") -> "void":
+        r"""
+        Adds a variable to minimize in the solution finalizer, with a weighted
+        priority: the higher the more priority it has.
+        """
+        return _pywrapcp.RoutingModel_AddWeightedVariableMinimizedByFinalizer(self, var, cost)
+
+    def AddWeightedVariableMaximizedByFinalizer(self, var: "IntVar", cost: "int64_t") -> "void":
+        r"""
+        Adds a variable to maximize in the solution finalizer, with a weighted
+        priority: the higher the more priority it has.
+        """
+        return _pywrapcp.RoutingModel_AddWeightedVariableMaximizedByFinalizer(self, var, cost)
+
+    def AddVariableTargetToFinalizer(self, var: "IntVar", target: "int64_t") -> "void":
+        r"""
+        Add a variable to set the closest possible to the target value in the
+        solution finalizer.
+        """
+        return _pywrapcp.RoutingModel_AddVariableTargetToFinalizer(self, var, target)
+
+    def AddWeightedVariableTargetToFinalizer(self, var: "IntVar", target: "int64_t", cost: "int64_t") -> "void":
+        r"""
+        Same as above with a weighted priority: the higher the cost, the more
+        priority it has to be set close to the target value.
+        """
+        return _pywrapcp.RoutingModel_AddWeightedVariableTargetToFinalizer(self, var, target, cost)
+
+    def CloseModel(self) -> "void":
+        r"""
+        Closes the current routing model; after this method is called, no
+        modification to the model can be done, but RoutesToAssignment becomes
+        available. Note that CloseModel() is automatically called by Solve() and
+        other methods that produce solution.
+        This is equivalent to calling
+        CloseModelWithParameters(DefaultRoutingSearchParameters()).
+        """
+        return _pywrapcp.RoutingModel_CloseModel(self)
+
+    def CloseModelWithParameters(self, search_parameters: "operations_research::RoutingSearchParameters const &") -> "void":
+        r"""
+        Same as above taking search parameters (as of 10/2015 some the parameters
+        have to be set when closing the model).
+        """
+        return _pywrapcp.RoutingModel_CloseModelWithParameters(self, search_parameters)
+
+    def Solve(self, assignment: "Assignment"=None) -> "operations_research::Assignment const *":
+        r"""
+        Solves the current routing model; closes the current model.
+        This is equivalent to calling
+        SolveWithParameters(DefaultRoutingSearchParameters())
+        or
+        SolveFromAssignmentWithParameters(assignment,
+                                          DefaultRoutingSearchParameters()).
+        """
+        return _pywrapcp.RoutingModel_Solve(self, assignment)
+
+    def SolveWithParameters(self, search_parameters: "operations_research::RoutingSearchParameters const &", solutions: "std::vector< operations_research::Assignment const * > *"=None) -> "operations_research::Assignment const *":
+        r"""
+        Solves the current routing model with the given parameters. If 'solutions'
+        is specified, it will contain the k best solutions found during the search
+        (from worst to best, including the one returned by this method), where k
+        corresponds to the 'number_of_solutions_to_collect' in
+        'search_parameters'. Note that the Assignment returned by the method and
+        the ones in solutions are owned by the underlying solver and should not be
+        deleted.
+        """
+        return _pywrapcp.RoutingModel_SolveWithParameters(self, search_parameters, solutions)
+
+    def SolveFromAssignmentWithParameters(self, assignment: "Assignment", search_parameters: "operations_research::RoutingSearchParameters const &", solutions: "std::vector< operations_research::Assignment const * > *"=None) -> "operations_research::Assignment const *":
+        r"""
+        Same as above, except that if assignment is not null, it will be used as
+        the initial solution.
+        """
+        return _pywrapcp.RoutingModel_SolveFromAssignmentWithParameters(self, assignment, search_parameters, solutions)
+
+    def SolveFromAssignmentsWithParameters(self, assignments: "std::vector< operations_research::Assignment const * > const &", search_parameters: "operations_research::RoutingSearchParameters const &", solutions: "std::vector< operations_research::Assignment const * > *"=None) -> "operations_research::Assignment const *":
+        r"""
+        Same as above but will try all assignments in order as first solutions
+        until one succeeds.
+        """
+        return _pywrapcp.RoutingModel_SolveFromAssignmentsWithParameters(self, assignments, search_parameters, solutions)
+
+    def SetAssignmentFromOtherModelAssignment(self, target_assignment: "Assignment", source_model: "RoutingModel", source_assignment: "Assignment") -> "void":
+        r"""
+        Given a "source_model" and its "source_assignment", resets
+        "target_assignment" with the IntVar variables (nexts_, and vehicle_vars_
+        if costs aren't homogeneous across vehicles) of "this" model, with the
+        values set according to those in "other_assignment".
+        The objective_element of target_assignment is set to this->cost_.
+        """
+        return _pywrapcp.RoutingModel_SetAssignmentFromOtherModelAssignment(self, target_assignment, source_model, source_assignment)
+
+    def ComputeLowerBound(self) -> "int64_t":
+        r"""
+        Computes a lower bound to the routing problem solving a linear assignment
+        problem. The routing model must be closed before calling this method.
+        Note that problems with node disjunction constraints (including optional
+        nodes) and non-homogenous costs are not supported (the method returns 0 in
+        these cases).
+        """
+        return _pywrapcp.RoutingModel_ComputeLowerBound(self)
+
+    def status(self) -> "operations_research::RoutingModel::Status":
+        r""" Returns the current status of the routing model."""
+        return _pywrapcp.RoutingModel_status(self)
+
+    def ApplyLocks(self, locks: "std::vector< int64_t > const &") -> "operations_research::IntVar *":
+        r"""
+        Applies a lock chain to the next search. 'locks' represents an ordered
+        vector of nodes representing a partial route which will be fixed during
+        the next search; it will constrain next variables such that:
+        next[locks[i]] == locks[i+1].
+
+        Returns the next variable at the end of the locked chain; this variable is
+        not locked. An assignment containing the locks can be obtained by calling
+        PreAssignment().
+        """
+        return _pywrapcp.RoutingModel_ApplyLocks(self, locks)
+
+    def ApplyLocksToAllVehicles(self, locks: "std::vector< std::vector< int64_t > > const &", close_routes: "bool") -> "bool":
+        r"""
+        Applies lock chains to all vehicles to the next search, such that locks[p]
+        is the lock chain for route p. Returns false if the locks do not contain
+        valid routes; expects that the routes do not contain the depots,
+        i.e. there are empty vectors in place of empty routes.
+        If close_routes is set to true, adds the end nodes to the route of each
+        vehicle and deactivates other nodes.
+        An assignment containing the locks can be obtained by calling
+        PreAssignment().
+        """
+        return _pywrapcp.RoutingModel_ApplyLocksToAllVehicles(self, locks, close_routes)
+
+    def PreAssignment(self) -> "operations_research::Assignment const *const":
+        r"""
+        Returns an assignment used to fix some of the variables of the problem.
+        In practice, this assignment locks partial routes of the problem. This
+        can be used in the context of locking the parts of the routes which have
+        already been driven in online routing problems.
+        """
+        return _pywrapcp.RoutingModel_PreAssignment(self)
+
+    def MutablePreAssignment(self) -> "operations_research::Assignment *":
+        return _pywrapcp.RoutingModel_MutablePreAssignment(self)
+
+    def WriteAssignment(self, file_name: "std::string const &") -> "bool":
+        r"""
+        Writes the current solution to a file containing an AssignmentProto.
+        Returns false if the file cannot be opened or if there is no current
+        solution.
+        """
+        return _pywrapcp.RoutingModel_WriteAssignment(self, file_name)
+
+    def ReadAssignment(self, file_name: "std::string const &") -> "operations_research::Assignment *":
+        r"""
+        Reads an assignment from a file and returns the current solution.
+        Returns nullptr if the file cannot be opened or if the assignment is not
+        valid.
+        """
+        return _pywrapcp.RoutingModel_ReadAssignment(self, file_name)
+
+    def RestoreAssignment(self, solution: "Assignment") -> "operations_research::Assignment *":
+        r"""
+        Restores an assignment as a solution in the routing model and returns the
+        new solution. Returns nullptr if the assignment is not valid.
+        """
+        return _pywrapcp.RoutingModel_RestoreAssignment(self, solution)
+
+    def ReadAssignmentFromRoutes(self, routes: "std::vector< std::vector< int64_t > > const &", ignore_inactive_indices: "bool") -> "operations_research::Assignment *":
+        r"""
+        Restores the routes as the current solution. Returns nullptr if the
+        solution cannot be restored (routes do not contain a valid solution). Note
+        that calling this method will run the solver to assign values to the
+        dimension variables; this may take considerable amount of time, especially
+        when using dimensions with slack.
+        """
+        return _pywrapcp.RoutingModel_ReadAssignmentFromRoutes(self, routes, ignore_inactive_indices)
+
+    def RoutesToAssignment(self, routes: "std::vector< std::vector< int64_t > > const &", ignore_inactive_indices: "bool", close_routes: "bool", assignment: "Assignment") -> "bool":
+        r"""
+        Fills an assignment from a specification of the routes of the
+        vehicles. The routes are specified as lists of variable indices that
+        appear on the routes of the vehicles. The indices of the outer vector in
+        'routes' correspond to vehicles IDs, the inner vector contains the
+        variable indices on the routes for the given vehicle. The inner vectors
+        must not contain the start and end indices, as these are determined by the
+        routing model.  Sets the value of NextVars in the assignment, adding the
+        variables to the assignment if necessary. The method does not touch other
+        variables in the assignment. The method can only be called after the model
+        is closed.  With ignore_inactive_indices set to false, this method will
+        fail (return nullptr) in case some of the route contain indices that are
+        deactivated in the model; when set to true, these indices will be
+        skipped.  Returns true if routes were successfully
+        loaded. However, such assignment still might not be a valid
+        solution to the routing problem due to more complex constraints;
+        it is advisible to call solver()->CheckSolution() afterwards.
+        """
+        return _pywrapcp.RoutingModel_RoutesToAssignment(self, routes, ignore_inactive_indices, close_routes, assignment)
+
+    def AssignmentToRoutes(self, assignment: "Assignment", routes: "std::vector< std::vector< int64_t > > *const") -> "void":
+        r"""
+        Converts the solution in the given assignment to routes for all vehicles.
+        Expects that assignment contains a valid solution (i.e. routes for all
+        vehicles end with an end index for that vehicle).
+        """
+        return _pywrapcp.RoutingModel_AssignmentToRoutes(self, assignment, routes)
+
+    def CompactAssignment(self, assignment: "Assignment") -> "operations_research::Assignment *":
+        r"""
+        Converts the solution in the given assignment to routes for all vehicles.
+        If the returned vector is route_indices, route_indices[i][j] is the index
+        for jth location visited on route i. Note that contrary to
+        AssignmentToRoutes, the vectors do include start and end locations.
+        Returns a compacted version of the given assignment, in which all vehicles
+        with id lower or equal to some N have non-empty routes, and all vehicles
+        with id greater than N have empty routes. Does not take ownership of the
+        returned object.
+        If found, the cost of the compact assignment is the same as in the
+        original assignment and it preserves the values of 'active' variables.
+        Returns nullptr if a compact assignment was not found.
+        This method only works in homogenous mode, and it only swaps equivalent
+        vehicles (vehicles with the same start and end nodes). When creating the
+        compact assignment, the empty plan is replaced by the route assigned to
+        the compatible vehicle with the highest id. Note that with more complex
+        constraints on vehicle variables, this method might fail even if a compact
+        solution exists.
+        This method changes the vehicle and dimension variables as necessary.
+        While compacting the solution, only basic checks on vehicle variables are
+        performed; if one of these checks fails no attempts to repair it are made
+        (instead, the method returns nullptr).
+        """
+        return _pywrapcp.RoutingModel_CompactAssignment(self, assignment)
+
+    def CompactAndCheckAssignment(self, assignment: "Assignment") -> "operations_research::Assignment *":
+        r"""
+        Same as CompactAssignment() but also checks the validity of the final
+        compact solution; if it is not valid, no attempts to repair it are made
+        (instead, the method returns nullptr).
+        """
+        return _pywrapcp.RoutingModel_CompactAndCheckAssignment(self, assignment)
+
+    def AddToAssignment(self, var: "IntVar") -> "void":
+        r""" Adds an extra variable to the vehicle routing assignment."""
+        return _pywrapcp.RoutingModel_AddToAssignment(self, var)
+
+    def AddIntervalToAssignment(self, interval: "IntervalVar") -> "void":
+        return _pywrapcp.RoutingModel_AddIntervalToAssignment(self, interval)
+
+    def PackCumulsOfOptimizerDimensionsFromAssignment(self, original_assignment: "Assignment", duration_limit: "absl::Duration") -> "operations_research::Assignment const *":
+        r"""
+        For every dimension in the model with an optimizer in
+        local/global_dimension_optimizers_, this method tries to pack the cumul
+        values of the dimension, such that:
+        - The cumul costs (span costs, soft lower and upper bound costs, etc) are
+          minimized.
+        - The cumuls of the ends of the routes are minimized for this given
+          minimal cumul cost.
+        - Given these minimal end cumuls, the route start cumuls are maximized.
+        Returns the assignment resulting from allocating these packed cumuls with
+        the solver, and nullptr if these cumuls could not be set by the solver.
+        """
+        return _pywrapcp.RoutingModel_PackCumulsOfOptimizerDimensionsFromAssignment(self, original_assignment, duration_limit)
+
+    def AddLocalSearchFilter(self, filter: "LocalSearchFilter") -> "void":
+        r"""
+        Adds a custom local search filter to the list of filters used to speed up
+        local search by pruning unfeasible variable assignments.
+        Calling this method after the routing model has been closed (CloseModel()
+        or Solve() has been called) has no effect.
+        The routing model does not take ownership of the filter.
+        """
+        return _pywrapcp.RoutingModel_AddLocalSearchFilter(self, filter)
+
+    def Start(self, vehicle: "int") -> "int64_t":
+        r"""
+        Model inspection.
+        Returns the variable index of the starting node of a vehicle route.
+        """
+        return _pywrapcp.RoutingModel_Start(self, vehicle)
+
+    def End(self, vehicle: "int") -> "int64_t":
+        r""" Returns the variable index of the ending node of a vehicle route."""
+        return _pywrapcp.RoutingModel_End(self, vehicle)
+
+    def IsStart(self, index: "int64_t") -> "bool":
+        r""" Returns true if 'index' represents the first node of a route."""
+        return _pywrapcp.RoutingModel_IsStart(self, index)
+
+    def IsEnd(self, index: "int64_t") -> "bool":
+        r""" Returns true if 'index' represents the last node of a route."""
+        return _pywrapcp.RoutingModel_IsEnd(self, index)
+
+    def VehicleIndex(self, index: "int64_t") -> "int":
+        r"""
+        Returns the vehicle of the given start/end index, and -1 if the given
+        index is not a vehicle start/end.
+        """
+        return _pywrapcp.RoutingModel_VehicleIndex(self, index)
+
+    def Next(self, assignment: "Assignment", index: "int64_t") -> "int64_t":
+        r"""
+        Assignment inspection
+        Returns the variable index of the node directly after the node
+        corresponding to 'index' in 'assignment'.
+        """
+        return _pywrapcp.RoutingModel_Next(self, assignment, index)
+
+    def IsVehicleUsed(self, assignment: "Assignment", vehicle: "int") -> "bool":
+        r""" Returns true if the route of 'vehicle' is non empty in 'assignment'."""
+        return _pywrapcp.RoutingModel_IsVehicleUsed(self, assignment, vehicle)
+
+    def NextVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        r"""
+        Returns the next variable of the node corresponding to index. Note that
+        NextVar(index) == index is equivalent to ActiveVar(index) == 0.
+        """
+        return _pywrapcp.RoutingModel_NextVar(self, index)
+
+    def ActiveVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        r""" Returns the active variable of the node corresponding to index."""
+        return _pywrapcp.RoutingModel_ActiveVar(self, index)
+
+    def ActiveVehicleVar(self, vehicle: "int") -> "operations_research::IntVar *":
+        r"""
+        Returns the active variable of the vehicle. It will be equal to 1 iff the
+        route of the vehicle is not empty, 0 otherwise.
+        """
+        return _pywrapcp.RoutingModel_ActiveVehicleVar(self, vehicle)
+
+    def VehicleRouteConsideredVar(self, vehicle: "int") -> "operations_research::IntVar *":
+        r"""
+        Returns the variable specifying whether or not the given vehicle route is
+        considered for costs and constraints. It will be equal to 1 iff the route
+        of the vehicle is not empty OR vehicle_used_when_empty_[vehicle] is true.
+        """
+        return _pywrapcp.RoutingModel_VehicleRouteConsideredVar(self, vehicle)
+
+    def VehicleVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        r"""
+        Returns the vehicle variable of the node corresponding to index. Note that
+        VehicleVar(index) == -1 is equivalent to ActiveVar(index) == 0.
+        """
+        return _pywrapcp.RoutingModel_VehicleVar(self, index)
+
+    def ResourceVar(self, vehicle: "int", resource_group: "int") -> "operations_research::IntVar *":
+        r"""
+        Returns the resource variable for the given vehicle index in the given
+        resource group. If a vehicle doesn't require a resource from the
+        corresponding resource group, then ResourceVar(v, r_g) == -1.
+        """
+        return _pywrapcp.RoutingModel_ResourceVar(self, vehicle, resource_group)
+
+    def CostVar(self) -> "operations_research::IntVar *":
+        r""" Returns the global cost variable which is being minimized."""
+        return _pywrapcp.RoutingModel_CostVar(self)
+
+    def GetArcCostForVehicle(self, from_index: "int64_t", to_index: "int64_t", vehicle: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost of the transit arc between two nodes for a given vehicle.
+        Input are variable indices of node. This returns 0 if vehicle < 0.
+        """
+        return _pywrapcp.RoutingModel_GetArcCostForVehicle(self, from_index, to_index, vehicle)
+
+    def CostsAreHomogeneousAcrossVehicles(self) -> "bool":
+        r""" Whether costs are homogeneous across all vehicles."""
+        return _pywrapcp.RoutingModel_CostsAreHomogeneousAcrossVehicles(self)
+
+    def GetHomogeneousCost(self, from_index: "int64_t", to_index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost of the segment between two nodes supposing all vehicle
+        costs are the same (returns the cost for the first vehicle otherwise).
+        """
+        return _pywrapcp.RoutingModel_GetHomogeneousCost(self, from_index, to_index)
+
+    def GetArcCostForFirstSolution(self, from_index: "int64_t", to_index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost of the arc in the context of the first solution strategy.
+        This is typically a simplification of the actual cost; see the .cc.
+        """
+        return _pywrapcp.RoutingModel_GetArcCostForFirstSolution(self, from_index, to_index)
+
+    def GetArcCostForClass(self, from_index: "int64_t", to_index: "int64_t", cost_class_index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost of the segment between two nodes for a given cost
+        class. Input are variable indices of nodes and the cost class.
+        Unlike GetArcCostForVehicle(), if cost_class is kNoCost, then the
+        returned cost won't necessarily be zero: only some of the components
+        of the cost that depend on the cost class will be omited. See the code
+        for details.
+        """
+        return _pywrapcp.RoutingModel_GetArcCostForClass(self, from_index, to_index, cost_class_index)
+
+    def GetCostClassIndexOfVehicle(self, vehicle: "int64_t") -> "operations_research::RoutingModel::CostClassIndex":
+        r""" Get the cost class index of the given vehicle."""
+        return _pywrapcp.RoutingModel_GetCostClassIndexOfVehicle(self, vehicle)
+
+    def HasVehicleWithCostClassIndex(self, cost_class_index: "operations_research::RoutingModel::CostClassIndex") -> "bool":
+        r"""
+        Returns true iff the model contains a vehicle with the given
+        cost_class_index.
+        """
+        return _pywrapcp.RoutingModel_HasVehicleWithCostClassIndex(self, cost_class_index)
+
+    def GetCostClassesCount(self) -> "int":
+        r""" Returns the number of different cost classes in the model."""
+        return _pywrapcp.RoutingModel_GetCostClassesCount(self)
+
+    def GetNonZeroCostClassesCount(self) -> "int":
+        r""" Ditto, minus the 'always zero', built-in cost class."""
+        return _pywrapcp.RoutingModel_GetNonZeroCostClassesCount(self)
+
+    def GetVehicleClassIndexOfVehicle(self, vehicle: "int64_t") -> "operations_research::RoutingModel::VehicleClassIndex":
+        return _pywrapcp.RoutingModel_GetVehicleClassIndexOfVehicle(self, vehicle)
+
+    def GetVehicleOfClass(self, vehicle_class: "operations_research::RoutingModel::VehicleClassIndex") -> "int":
+        r"""
+        Returns a vehicle of the given vehicle class, and -1 if there are no
+        vehicles for this class.
+        """
+        return _pywrapcp.RoutingModel_GetVehicleOfClass(self, vehicle_class)
+
+    def GetVehicleClassesCount(self) -> "int":
+        r""" Returns the number of different vehicle classes in the model."""
+        return _pywrapcp.RoutingModel_GetVehicleClassesCount(self)
+
+    def GetSameVehicleIndicesOfIndex(self, node: "int") -> "std::vector< int > const &":
+        r""" Returns variable indices of nodes constrained to be on the same route."""
+        return _pywrapcp.RoutingModel_GetSameVehicleIndicesOfIndex(self, node)
+
+    def GetVehicleTypeContainer(self) -> "operations_research::RoutingModel::VehicleTypeContainer const &":
+        return _pywrapcp.RoutingModel_GetVehicleTypeContainer(self)
+
+    def ArcIsMoreConstrainedThanArc(self, _from: "int64_t", to1: "int64_t", to2: "int64_t") -> "bool":
+        r"""
+        Returns whether the arc from->to1 is more constrained than from->to2,
+        taking into account, in order:
+        - whether the destination node isn't an end node
+        - whether the destination node is mandatory
+        - whether the destination node is bound to the same vehicle as the source
+        - the "primary constrained" dimension (see SetPrimaryConstrainedDimension)
+        It then breaks ties using, in order:
+        - the arc cost (taking unperformed penalties into account)
+        - the size of the vehicle vars of "to1" and "to2" (lowest size wins)
+        - the value: the lowest value of the indices to1 and to2 wins.
+        See the .cc for details.
+        The more constrained arc is typically preferable when building a
+        first solution. This method is intended to be used as a callback for the
+        BestValueByComparisonSelector value selector.
+        Args:
+          from: the variable index of the source node
+          to1: the variable index of the first candidate destination node.
+          to2: the variable index of the second candidate destination node.
+        """
+        return _pywrapcp.RoutingModel_ArcIsMoreConstrainedThanArc(self, _from, to1, to2)
+
+    def DebugOutputAssignment(self, solution_assignment: "Assignment", dimension_to_print: "std::string const &") -> "std::string":
+        r"""
+        Print some debugging information about an assignment, including the
+        feasible intervals of the CumulVar for dimension "dimension_to_print"
+        at each step of the routes.
+        If "dimension_to_print" is omitted, all dimensions will be printed.
+        """
+        return _pywrapcp.RoutingModel_DebugOutputAssignment(self, solution_assignment, dimension_to_print)
+
+    def solver(self) -> "operations_research::Solver *":
+        r"""
+        Returns a vector cumul_bounds, for which cumul_bounds[i][j] is a pair
+        containing the minimum and maximum of the CumulVar of the jth node on
+        route i.
+        - cumul_bounds[i][j].first is the minimum.
+        - cumul_bounds[i][j].second is the maximum.
+        Returns the underlying constraint solver. Can be used to add extra
+        constraints and/or modify search algorithms.
+        """
+        return _pywrapcp.RoutingModel_solver(self)
+
+    def CheckLimit(self) -> "bool":
+        r""" Returns true if the search limit has been crossed."""
+        return _pywrapcp.RoutingModel_CheckLimit(self)
+
+    def RemainingTime(self) -> "absl::Duration":
+        r""" Returns the time left in the search limit."""
+        return _pywrapcp.RoutingModel_RemainingTime(self)
+
+    def nodes(self) -> "int":
+        r"""
+        Sizes and indices
+        Returns the number of nodes in the model.
+        """
+        return _pywrapcp.RoutingModel_nodes(self)
+
+    def vehicles(self) -> "int":
+        r""" Returns the number of vehicle routes in the model."""
+        return _pywrapcp.RoutingModel_vehicles(self)
+
+    def Size(self) -> "int64_t":
+        r""" Returns the number of next variables in the model."""
+        return _pywrapcp.RoutingModel_Size(self)
+
+    def GetNumberOfDecisionsInFirstSolution(self, search_parameters: "operations_research::RoutingSearchParameters const &") -> "int64_t":
+        r"""
+        Returns statistics on first solution search, number of decisions sent to
+        filters, number of decisions rejected by filters.
+        """
+        return _pywrapcp.RoutingModel_GetNumberOfDecisionsInFirstSolution(self, search_parameters)
+
+    def GetNumberOfRejectsInFirstSolution(self, search_parameters: "operations_research::RoutingSearchParameters const &") -> "int64_t":
+        return _pywrapcp.RoutingModel_GetNumberOfRejectsInFirstSolution(self, search_parameters)
+
+    def GetAutomaticFirstSolutionStrategy(self) -> "operations_research::FirstSolutionStrategy::Value":
+        r""" Returns the automatic first solution strategy selected."""
+        return _pywrapcp.RoutingModel_GetAutomaticFirstSolutionStrategy(self)
+
+    def IsMatchingModel(self) -> "bool":
+        r""" Returns true if a vehicle/node matching problem is detected."""
+        return _pywrapcp.RoutingModel_IsMatchingModel(self)
+
+    def MakeGuidedSlackFinalizer(self, dimension: "RoutingDimension", initializer: "std::function< int64_t (int64_t) >") -> "operations_research::DecisionBuilder *":
+        r"""
+        The next few members are in the public section only for testing purposes.
+
+        MakeGuidedSlackFinalizer creates a DecisionBuilder for the slacks of a
+        dimension using a callback to choose which values to start with.
+        The finalizer works only when all next variables in the model have
+        been fixed. It has the following two characteristics:
+        1. It follows the routes defined by the nexts variables when choosing a
+           variable to make a decision on.
+        2. When it comes to choose a value for the slack of node i, the decision
+           builder first calls the callback with argument i, and supposingly the
+           returned value is x it creates decisions slack[i] = x, slack[i] = x +
+           1, slack[i] = x - 1, slack[i] = x + 2, etc.
+        """
+        return _pywrapcp.RoutingModel_MakeGuidedSlackFinalizer(self, dimension, initializer)
+
+    def MakeSelfDependentDimensionFinalizer(self, dimension: "RoutingDimension") -> "operations_research::DecisionBuilder *":
+        r"""
+        MakeSelfDependentDimensionFinalizer is a finalizer for the slacks of a
+        self-dependent dimension. It makes an extensive use of the caches of the
+        state dependent transits.
+        In detail, MakeSelfDependentDimensionFinalizer returns a composition of a
+        local search decision builder with a greedy descent operator for the cumul
+        of the start of each route and a guided slack finalizer. Provided there
+        are no time windows and the maximum slacks are large enough, once the
+        cumul of the start of route is fixed, the guided finalizer can find
+        optimal values of the slacks for the rest of the route in time
+        proportional to the length of the route. Therefore the composed finalizer
+        generally works in time O(log(t)*n*m), where t is the latest possible
+        departute time, n is the number of nodes in the network and m is the
+        number of vehicles.
+        """
+        return _pywrapcp.RoutingModel_MakeSelfDependentDimensionFinalizer(self, dimension)
+
+# Register RoutingModel in _pywrapcp:
+_pywrapcp.RoutingModel_swigregister(RoutingModel)
+cvar = _pywrapcp.cvar
+RoutingModel.kNoPenalty = _pywrapcp.cvar.RoutingModel_kNoPenalty
+RoutingModel.kNoDisjunction = _pywrapcp.cvar.RoutingModel_kNoDisjunction
+RoutingModel.kNoDimension = _pywrapcp.cvar.RoutingModel_kNoDimension
+
+class RoutingModelVisitor(BaseObject):
+    r""" Routing model visitor."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self):
+        _pywrapcp.RoutingModelVisitor_swiginit(self, _pywrapcp.new_RoutingModelVisitor())
+    __swig_destroy__ = _pywrapcp.delete_RoutingModelVisitor
+
+# Register RoutingModelVisitor in _pywrapcp:
+_pywrapcp.RoutingModelVisitor_swigregister(RoutingModelVisitor)
+RoutingModelVisitor.kLightElement = _pywrapcp.cvar.RoutingModelVisitor_kLightElement
+RoutingModelVisitor.kLightElement2 = _pywrapcp.cvar.RoutingModelVisitor_kLightElement2
+RoutingModelVisitor.kRemoveValues = _pywrapcp.cvar.RoutingModelVisitor_kRemoveValues
+
+class GlobalVehicleBreaksConstraint(Constraint):
+    r"""
+    GlobalVehicleBreaksConstraint ensures breaks constraints are enforced on
+    all vehicles in the dimension passed to its constructor.
+    It is intended to be used for dimensions representing time.
+    A break constraint ensures break intervals fit on the route of a vehicle.
+    For a given vehicle, it forces break intervals to be disjoint from visit
+    intervals, where visit intervals start at CumulVar(node) and last for
+    node_visit_transit[node]. Moreover, it ensures that there is enough time
+    between two consecutive nodes of a route to do transit and vehicle breaks,
+    i.e. if Next(nodeA) = nodeB, CumulVar(nodeA) = tA and CumulVar(nodeB) = tB,
+    then SlackVar(nodeA) >= sum_{breaks [tA, tB)} duration(break).
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, dimension: "RoutingDimension"):
+        _pywrapcp.GlobalVehicleBreaksConstraint_swiginit(self, _pywrapcp.new_GlobalVehicleBreaksConstraint(dimension))
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.GlobalVehicleBreaksConstraint_DebugString(self)
+
+    def Post(self) -> "void":
+        return _pywrapcp.GlobalVehicleBreaksConstraint_Post(self)
+
+    def InitialPropagateWrapper(self) -> "void":
+        return _pywrapcp.GlobalVehicleBreaksConstraint_InitialPropagateWrapper(self)
+    __swig_destroy__ = _pywrapcp.delete_GlobalVehicleBreaksConstraint
+
+# Register GlobalVehicleBreaksConstraint in _pywrapcp:
+_pywrapcp.GlobalVehicleBreaksConstraint_swigregister(GlobalVehicleBreaksConstraint)
+
+class TypeRegulationsChecker(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+    __swig_destroy__ = _pywrapcp.delete_TypeRegulationsChecker
+
+    def CheckVehicle(self, vehicle: "int", next_accessor: "std::function< int64_t (int64_t) > const &") -> "bool":
+        return _pywrapcp.TypeRegulationsChecker_CheckVehicle(self, vehicle, next_accessor)
+
+# Register TypeRegulationsChecker in _pywrapcp:
+_pywrapcp.TypeRegulationsChecker_swigregister(TypeRegulationsChecker)
+
+class TypeIncompatibilityChecker(TypeRegulationsChecker):
+    r""" Checker for type incompatibilities."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, model: "RoutingModel", check_hard_incompatibilities: "bool"):
+        _pywrapcp.TypeIncompatibilityChecker_swiginit(self, _pywrapcp.new_TypeIncompatibilityChecker(model, check_hard_incompatibilities))
+    __swig_destroy__ = _pywrapcp.delete_TypeIncompatibilityChecker
+
+# Register TypeIncompatibilityChecker in _pywrapcp:
+_pywrapcp.TypeIncompatibilityChecker_swigregister(TypeIncompatibilityChecker)
+
+class TypeRequirementChecker(TypeRegulationsChecker):
+    r""" Checker for type requirements."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, model: "RoutingModel"):
+        _pywrapcp.TypeRequirementChecker_swiginit(self, _pywrapcp.new_TypeRequirementChecker(model))
+    __swig_destroy__ = _pywrapcp.delete_TypeRequirementChecker
+
+# Register TypeRequirementChecker in _pywrapcp:
+_pywrapcp.TypeRequirementChecker_swigregister(TypeRequirementChecker)
+
+class TypeRegulationsConstraint(Constraint):
+    r"""
+    The following constraint ensures that incompatibilities and requirements
+    between types are respected.
+
+    It verifies both "hard" and "temporal" incompatibilities.
+    Two nodes with hard incompatible types cannot be served by the same vehicle
+    at all, while with a temporal incompatibility they can't be on the same
+    route at the same time.
+    The VisitTypePolicy of a node determines how visiting it impacts the type
+    count on the route.
+
+    For example, for
+    - three temporally incompatible types T1 T2 and T3
+    - 2 pairs of nodes a1/r1 and a2/r2 of type T1 and T2 respectively, with
+        - a1 and a2 of VisitTypePolicy TYPE_ADDED_TO_VEHICLE
+        - r1 and r2 of policy ADDED_TYPE_REMOVED_FROM_VEHICLE
+    - 3 nodes A, UV and AR of type T3, respectively with type policies
+      TYPE_ADDED_TO_VEHICLE, TYPE_ON_VEHICLE_UP_TO_VISIT and
+      TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED
+    the configurations
+    UV --> a1 --> r1 --> a2 --> r2,   a1 --> r1 --> a2 --> r2 --> A and
+    a1 --> r1 --> AR --> a2 --> r2 are acceptable, whereas the configurations
+    a1 --> a2 --> r1 --> ..., or A --> a1 --> r1 --> ..., or
+    a1 --> r1 --> UV --> ... are not feasible.
+
+    It also verifies same-vehicle and temporal type requirements.
+    A node of type T_d with a same-vehicle requirement for type T_r needs to be
+    served by the same vehicle as a node of type T_r.
+    Temporal requirements, on the other hand, can take effect either when the
+    dependent type is being added to the route or when it's removed from it,
+    which is determined by the dependent node's VisitTypePolicy.
+    In the above example:
+    - If T3 is required on the same vehicle as T1, A, AR or UV must be on the
+      same vehicle as a1.
+    - If T2 is required when adding T1, a2 must be visited *before* a1, and if
+      r2 is also visited on the route, it must be *after* a1, i.e. T2 must be on
+      the vehicle when a1 is visited:
+      ... --> a2 --> ... --> a1 --> ... --> r2 --> ...
+    - If T3 is required when removing T1, T3 needs to be on the vehicle when
+      r1 is visited:
+      ... --> A --> ... --> r1 --> ...   OR   ... --> r1 --> ... --> UV --> ...
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, model: "RoutingModel"):
+        _pywrapcp.TypeRegulationsConstraint_swiginit(self, _pywrapcp.new_TypeRegulationsConstraint(model))
+
+    def Post(self) -> "void":
+        return _pywrapcp.TypeRegulationsConstraint_Post(self)
+
+    def InitialPropagateWrapper(self) -> "void":
+        return _pywrapcp.TypeRegulationsConstraint_InitialPropagateWrapper(self)
+    __swig_destroy__ = _pywrapcp.delete_TypeRegulationsConstraint
+
+# Register TypeRegulationsConstraint in _pywrapcp:
+_pywrapcp.TypeRegulationsConstraint_swigregister(TypeRegulationsConstraint)
+
+class RoutingDimension(object):
+    r"""
+    Dimensions represent quantities accumulated at nodes along the routes. They
+    represent quantities such as weights or volumes carried along the route, or
+    distance or times.
+
+    Quantities at a node are represented by "cumul" variables and the increase
+    or decrease of quantities between nodes are represented by "transit"
+    variables. These variables are linked as follows:
+
+    if j == next(i),
+    cumuls(j) = cumuls(i) + transits(i) + slacks(i) +
+                state_dependent_transits(i)
+
+    where slack is a positive slack variable (can represent waiting times for
+    a time dimension), and state_dependent_transits is a non-purely functional
+    version of transits_. Favour transits over state_dependent_transits when
+    possible, because purely functional callbacks allow more optimisations and
+    make the model faster and easier to solve.
+    for a given vehicle, it is passed as an external vector, it would be better
+    to have this information here.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+    __swig_destroy__ = _pywrapcp.delete_RoutingDimension
+
+    def model(self) -> "operations_research::RoutingModel *":
+        r""" Returns the model on which the dimension was created."""
+        return _pywrapcp.RoutingDimension_model(self)
+
+    def GetTransitValue(self, from_index: "int64_t", to_index: "int64_t", vehicle: "int64_t") -> "int64_t":
+        r"""
+        Returns the transition value for a given pair of nodes (as var index);
+        this value is the one taken by the corresponding transit variable when
+        the 'next' variable for 'from_index' is bound to 'to_index'.
+        """
+        return _pywrapcp.RoutingDimension_GetTransitValue(self, from_index, to_index, vehicle)
+
+    def GetTransitValueFromClass(self, from_index: "int64_t", to_index: "int64_t", vehicle_class: "int64_t") -> "int64_t":
+        r"""
+        Same as above but taking a vehicle class of the dimension instead of a
+        vehicle (the class of a vehicle can be obtained with vehicle_to_class()).
+        """
+        return _pywrapcp.RoutingDimension_GetTransitValueFromClass(self, from_index, to_index, vehicle_class)
+
+    def CumulVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        r"""
+        Get the cumul, transit and slack variables for the given node (given as
+        int64_t var index).
+        """
+        return _pywrapcp.RoutingDimension_CumulVar(self, index)
+
+    def TransitVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        return _pywrapcp.RoutingDimension_TransitVar(self, index)
+
+    def FixedTransitVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        return _pywrapcp.RoutingDimension_FixedTransitVar(self, index)
+
+    def SlackVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        return _pywrapcp.RoutingDimension_SlackVar(self, index)
+
+    def SetSpanUpperBoundForVehicle(self, upper_bound: "int64_t", vehicle: "int") -> "void":
+        r"""
+        Sets an upper bound on the dimension span on a given vehicle. This is the
+        preferred way to limit the "length" of the route of a vehicle according to
+        a dimension.
+        """
+        return _pywrapcp.RoutingDimension_SetSpanUpperBoundForVehicle(self, upper_bound, vehicle)
+
+    def SetSpanCostCoefficientForVehicle(self, coefficient: "int64_t", vehicle: "int") -> "void":
+        r"""
+        Sets a cost proportional to the dimension span on a given vehicle,
+        or on all vehicles at once. "coefficient" must be nonnegative.
+        This is handy to model costs proportional to idle time when the dimension
+        represents time.
+        The cost for a vehicle is
+          span_cost = coefficient * (dimension end value - dimension start value).
+        """
+        return _pywrapcp.RoutingDimension_SetSpanCostCoefficientForVehicle(self, coefficient, vehicle)
+
+    def SetSpanCostCoefficientForAllVehicles(self, coefficient: "int64_t") -> "void":
+        return _pywrapcp.RoutingDimension_SetSpanCostCoefficientForAllVehicles(self, coefficient)
+
+    def SetGlobalSpanCostCoefficient(self, coefficient: "int64_t") -> "void":
+        r"""
+        Sets a cost proportional to the *global* dimension span, that is the
+        difference between the largest value of route end cumul variables and
+        the smallest value of route start cumul variables.
+        In other words:
+        global_span_cost =
+          coefficient * (Max(dimension end value) - Min(dimension start value)).
+        """
+        return _pywrapcp.RoutingDimension_SetGlobalSpanCostCoefficient(self, coefficient)
+
+    def SetCumulVarSoftUpperBound(self, index: "int64_t", upper_bound: "int64_t", coefficient: "int64_t") -> "void":
+        r"""
+        Sets a soft upper bound to the cumul variable of a given variable index.
+        If the value of the cumul variable is greater than the bound, a cost
+        proportional to the difference between this value and the bound is added
+        to the cost function of the model:
+          cumulVar <= upper_bound -> cost = 0
+           cumulVar > upper_bound -> cost = coefficient * (cumulVar - upper_bound)
+        This is also handy to model tardiness costs when the dimension represents
+        time.
+        """
+        return _pywrapcp.RoutingDimension_SetCumulVarSoftUpperBound(self, index, upper_bound, coefficient)
+
+    def HasCumulVarSoftUpperBound(self, index: "int64_t") -> "bool":
+        r"""
+        Returns true if a soft upper bound has been set for a given variable
+        index.
+        """
+        return _pywrapcp.RoutingDimension_HasCumulVarSoftUpperBound(self, index)
+
+    def GetCumulVarSoftUpperBound(self, index: "int64_t") -> "int64_t":
+        r"""
+        Returns the soft upper bound of a cumul variable for a given variable
+        index. The "hard" upper bound of the variable is returned if no soft upper
+        bound has been set.
+        """
+        return _pywrapcp.RoutingDimension_GetCumulVarSoftUpperBound(self, index)
+
+    def GetCumulVarSoftUpperBoundCoefficient(self, index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost coefficient of the soft upper bound of a cumul variable
+        for a given variable index. If no soft upper bound has been set, 0 is
+        returned.
+        """
+        return _pywrapcp.RoutingDimension_GetCumulVarSoftUpperBoundCoefficient(self, index)
+
+    def SetCumulVarSoftLowerBound(self, index: "int64_t", lower_bound: "int64_t", coefficient: "int64_t") -> "void":
+        r"""
+        Sets a soft lower bound to the cumul variable of a given variable index.
+        If the value of the cumul variable is less than the bound, a cost
+        proportional to the difference between this value and the bound is added
+        to the cost function of the model:
+          cumulVar > lower_bound -> cost = 0
+          cumulVar <= lower_bound -> cost = coefficient * (lower_bound -
+                      cumulVar).
+        This is also handy to model earliness costs when the dimension represents
+        time.
+        """
+        return _pywrapcp.RoutingDimension_SetCumulVarSoftLowerBound(self, index, lower_bound, coefficient)
+
+    def HasCumulVarSoftLowerBound(self, index: "int64_t") -> "bool":
+        r"""
+        Returns true if a soft lower bound has been set for a given variable
+        index.
+        """
+        return _pywrapcp.RoutingDimension_HasCumulVarSoftLowerBound(self, index)
+
+    def GetCumulVarSoftLowerBound(self, index: "int64_t") -> "int64_t":
+        r"""
+        Returns the soft lower bound of a cumul variable for a given variable
+        index. The "hard" lower bound of the variable is returned if no soft lower
+        bound has been set.
+        """
+        return _pywrapcp.RoutingDimension_GetCumulVarSoftLowerBound(self, index)
+
+    def GetCumulVarSoftLowerBoundCoefficient(self, index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost coefficient of the soft lower bound of a cumul variable
+        for a given variable index. If no soft lower bound has been set, 0 is
+        returned.
+        """
+        return _pywrapcp.RoutingDimension_GetCumulVarSoftLowerBoundCoefficient(self, index)
+
+    def SetBreakIntervalsOfVehicle(self, breaks: "std::vector< operations_research::IntervalVar * >", vehicle: "int", node_visit_transits: "std::vector< int64_t >") -> "void":
+        r"""
+        Sets the breaks for a given vehicle. Breaks are represented by
+        IntervalVars. They may interrupt transits between nodes and increase
+        the value of corresponding slack variables.
+        A break may take place before the start of a vehicle, after the end of
+        a vehicle, or during a travel i -> j.
+
+        In that case, the interval [break.Start(), break.End()) must be a subset
+        of [CumulVar(i) + pre_travel(i, j), CumulVar(j) - post_travel(i, j)). In
+        other words, a break may not overlap any node n's visit, given by
+        [CumulVar(n) - post_travel(_, n), CumulVar(n) + pre_travel(n, _)).
+        This formula considers post_travel(_, start) and pre_travel(end, _) to be
+        0; pre_travel will never be called on any (_, start) and post_travel will
+        never we called on any (end, _). If pre_travel_evaluator or
+        post_travel_evaluator is -1, it will be taken as a function that always
+        returns 0.
+        Deprecated, sets pre_travel(i, j) = node_visit_transit[i].
+        """
+        return _pywrapcp.RoutingDimension_SetBreakIntervalsOfVehicle(self, breaks, vehicle, node_visit_transits)
+
+    def SetBreakDistanceDurationOfVehicle(self, distance: "int64_t", duration: "int64_t", vehicle: "int") -> "void":
+        r"""
+        With breaks supposed to be consecutive, this forces the distance between
+        breaks of size at least minimum_break_duration to be at most distance.
+        This supposes that the time until route start and after route end are
+        infinite breaks.
+        """
+        return _pywrapcp.RoutingDimension_SetBreakDistanceDurationOfVehicle(self, distance, duration, vehicle)
+
+    def InitializeBreaks(self) -> "void":
+        r"""
+        Sets up vehicle_break_intervals_, vehicle_break_distance_duration_,
+        pre_travel_evaluators and post_travel_evaluators.
+        """
+        return _pywrapcp.RoutingDimension_InitializeBreaks(self)
+
+    def HasBreakConstraints(self) -> "bool":
+        r""" Returns true if any break interval or break distance was defined."""
+        return _pywrapcp.RoutingDimension_HasBreakConstraints(self)
+
+    def GetPreTravelEvaluatorOfVehicle(self, vehicle: "int") -> "int":
+        return _pywrapcp.RoutingDimension_GetPreTravelEvaluatorOfVehicle(self, vehicle)
+
+    def GetPostTravelEvaluatorOfVehicle(self, vehicle: "int") -> "int":
+        return _pywrapcp.RoutingDimension_GetPostTravelEvaluatorOfVehicle(self, vehicle)
+
+    def base_dimension(self) -> "operations_research::RoutingDimension const *":
+        r""" Returns the parent in the dependency tree if any or nullptr otherwise."""
+        return _pywrapcp.RoutingDimension_base_dimension(self)
+
+    def ShortestTransitionSlack(self, node: "int64_t") -> "int64_t":
+        r"""
+        It makes sense to use the function only for self-dependent dimension.
+        For such dimensions the value of the slack of a node determines the
+        transition cost of the next transit. Provided that
+          1. cumul[node] is fixed,
+          2. next[node] and next[next[node]] (if exists) are fixed,
+        the value of slack[node] for which cumul[next[node]] + transit[next[node]]
+        is minimized can be found in O(1) using this function.
+        """
+        return _pywrapcp.RoutingDimension_ShortestTransitionSlack(self, node)
+
+    def name(self) -> "std::string const &":
+        r""" Returns the name of the dimension."""
+        return _pywrapcp.RoutingDimension_name(self)
+
+    def SetPickupToDeliveryLimitFunctionForPair(self, limit_function: "operations_research::RoutingDimension::PickupToDeliveryLimitFunction", pair_index: "int") -> "void":
+        return _pywrapcp.RoutingDimension_SetPickupToDeliveryLimitFunctionForPair(self, limit_function, pair_index)
+
+    def HasPickupToDeliveryLimits(self) -> "bool":
+        return _pywrapcp.RoutingDimension_HasPickupToDeliveryLimits(self)
+
+    def AddNodePrecedence(self, first_node: "int64_t", second_node: "int64_t", offset: "int64_t") -> "void":
+        return _pywrapcp.RoutingDimension_AddNodePrecedence(self, first_node, second_node, offset)
+
+    def GetSpanUpperBoundForVehicle(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingDimension_GetSpanUpperBoundForVehicle(self, vehicle)
+
+    def GetSpanCostCoefficientForVehicle(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingDimension_GetSpanCostCoefficientForVehicle(self, vehicle)
+
+    def global_span_cost_coefficient(self) -> "int64_t":
+        return _pywrapcp.RoutingDimension_global_span_cost_coefficient(self)
+
+    def GetGlobalOptimizerOffset(self) -> "int64_t":
+        return _pywrapcp.RoutingDimension_GetGlobalOptimizerOffset(self)
+
+    def GetLocalOptimizerOffsetForVehicle(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingDimension_GetLocalOptimizerOffsetForVehicle(self, vehicle)
+
+# Register RoutingDimension in _pywrapcp:
+_pywrapcp.RoutingDimension_swigregister(RoutingDimension)
+
+
+def MakeSetValuesFromTargets(solver: "Solver", variables: "std::vector< operations_research::IntVar * >", targets: "std::vector< int64_t >") -> "operations_research::DecisionBuilder *":
+    r"""
+    A decision builder which tries to assign values to variables as close as
+    possible to target values first.
+    """
+    return _pywrapcp.MakeSetValuesFromTargets(solver, variables, targets)
+
+def SolveModelWithSat(model: "RoutingModel", search_parameters: "operations_research::RoutingSearchParameters const &", initial_solution: "Assignment", solution: "Assignment") -> "bool":
+    r"""
+    Attempts to solve the model using the cp-sat solver. As of 5/2019, will
+    solve the TSP corresponding to the model if it has a single vehicle.
+    Therefore the resulting solution might not actually be feasible. Will return
+    false if a solution could not be found.
+    """
+    return _pywrapcp.SolveModelWithSat(model, search_parameters, initial_solution, solution)
+
+ +
+ +
+
+
+ #   + + + class + DefaultPhaseParameters: +
+ +
+ View Source +
class DefaultPhaseParameters(object):
+    r"""
+    This struct holds all parameters for the default search.
+    DefaultPhaseParameters is only used by Solver::MakeDefaultPhase methods.
+    Note this is for advanced users only.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+    CHOOSE_MAX_SUM_IMPACT = _pywrapcp.DefaultPhaseParameters_CHOOSE_MAX_SUM_IMPACT
+    CHOOSE_MAX_AVERAGE_IMPACT = _pywrapcp.DefaultPhaseParameters_CHOOSE_MAX_AVERAGE_IMPACT
+    CHOOSE_MAX_VALUE_IMPACT = _pywrapcp.DefaultPhaseParameters_CHOOSE_MAX_VALUE_IMPACT
+    SELECT_MIN_IMPACT = _pywrapcp.DefaultPhaseParameters_SELECT_MIN_IMPACT
+    SELECT_MAX_IMPACT = _pywrapcp.DefaultPhaseParameters_SELECT_MAX_IMPACT
+    NONE = _pywrapcp.DefaultPhaseParameters_NONE
+    NORMAL = _pywrapcp.DefaultPhaseParameters_NORMAL
+    VERBOSE = _pywrapcp.DefaultPhaseParameters_VERBOSE
+    var_selection_schema = property(_pywrapcp.DefaultPhaseParameters_var_selection_schema_get, _pywrapcp.DefaultPhaseParameters_var_selection_schema_set, doc=r"""
+    This parameter describes how the next variable to instantiate
+    will be chosen.
+    """)
+    value_selection_schema = property(_pywrapcp.DefaultPhaseParameters_value_selection_schema_get, _pywrapcp.DefaultPhaseParameters_value_selection_schema_set, doc=r""" This parameter describes which value to select for a given var.""")
+    initialization_splits = property(_pywrapcp.DefaultPhaseParameters_initialization_splits_get, _pywrapcp.DefaultPhaseParameters_initialization_splits_set, doc=r"""
+    Maximum number of intervals that the initialization of impacts will scan
+    per variable.
+    """)
+    run_all_heuristics = property(_pywrapcp.DefaultPhaseParameters_run_all_heuristics_get, _pywrapcp.DefaultPhaseParameters_run_all_heuristics_set, doc=r"""
+    The default phase will run heuristics periodically. This parameter
+    indicates if we should run all heuristics, or a randomly selected
+    one.
+    """)
+    heuristic_period = property(_pywrapcp.DefaultPhaseParameters_heuristic_period_get, _pywrapcp.DefaultPhaseParameters_heuristic_period_set, doc=r"""
+    The distance in nodes between each run of the heuristics. A
+    negative or null value will mean that we will not run heuristics
+    at all.
+    """)
+    heuristic_num_failures_limit = property(_pywrapcp.DefaultPhaseParameters_heuristic_num_failures_limit_get, _pywrapcp.DefaultPhaseParameters_heuristic_num_failures_limit_set, doc=r""" The failure limit for each heuristic that we run.""")
+    persistent_impact = property(_pywrapcp.DefaultPhaseParameters_persistent_impact_get, _pywrapcp.DefaultPhaseParameters_persistent_impact_set, doc=r"""
+    Whether to keep the impact from the first search for other searches,
+    or to recompute the impact for each new search.
+    """)
+    random_seed = property(_pywrapcp.DefaultPhaseParameters_random_seed_get, _pywrapcp.DefaultPhaseParameters_random_seed_set, doc=r""" Seed used to initialize the random part in some heuristics.""")
+    display_level = property(_pywrapcp.DefaultPhaseParameters_display_level_get, _pywrapcp.DefaultPhaseParameters_display_level_set, doc=r"""
+    This represents the amount of information displayed by the default search.
+    NONE means no display, VERBOSE means extra information.
+    """)
+    decision_builder = property(_pywrapcp.DefaultPhaseParameters_decision_builder_get, _pywrapcp.DefaultPhaseParameters_decision_builder_set, doc=r""" When defined, this overrides the default impact based decision builder.""")
+
+    def __init__(self):
+        _pywrapcp.DefaultPhaseParameters_swiginit(self, _pywrapcp.new_DefaultPhaseParameters())
+    __swig_destroy__ = _pywrapcp.delete_DefaultPhaseParameters
+
+ +
+ +

This struct holds all parameters for the default search. +DefaultPhaseParameters is only used by Solver::MakeDefaultPhase methods. +Note this is for advanced users only.

+
+ + +
+
#   + + + DefaultPhaseParameters() +
+ +
+ View Source +
    def __init__(self):
+        _pywrapcp.DefaultPhaseParameters_swiginit(self, _pywrapcp.new_DefaultPhaseParameters())
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + CHOOSE_MAX_SUM_IMPACT = 0 +
+ + + + +
+
+
#   + + CHOOSE_MAX_AVERAGE_IMPACT = 1 +
+ + + + +
+
+
#   + + CHOOSE_MAX_VALUE_IMPACT = 2 +
+ + + + +
+
+
#   + + SELECT_MIN_IMPACT = 0 +
+ + + + +
+
+
#   + + SELECT_MAX_IMPACT = 1 +
+ + + + +
+
+
#   + + NONE = 0 +
+ + + + +
+
+
#   + + NORMAL = 1 +
+ + + + +
+
+
#   + + VERBOSE = 2 +
+ + + + +
+
+
#   + + var_selection_schema +
+ + +

This parameter describes how the next variable to instantiate +will be chosen.

+
+ + +
+
+
#   + + value_selection_schema +
+ + +

This parameter describes which value to select for a given var.

+
+ + +
+
+
#   + + initialization_splits +
+ + +

Maximum number of intervals that the initialization of impacts will scan +per variable.

+
+ + +
+
+
#   + + run_all_heuristics +
+ + +

The default phase will run heuristics periodically. This parameter +indicates if we should run all heuristics, or a randomly selected +one.

+
+ + +
+
+
#   + + heuristic_period +
+ + +

The distance in nodes between each run of the heuristics. A +negative or null value will mean that we will not run heuristics +at all.

+
+ + +
+
+
#   + + heuristic_num_failures_limit +
+ + +

The failure limit for each heuristic that we run.

+
+ + +
+
+
#   + + persistent_impact +
+ + +

Whether to keep the impact from the first search for other searches, +or to recompute the impact for each new search.

+
+ + +
+
+
#   + + random_seed +
+ + +

Seed used to initialize the random part in some heuristics.

+
+ + +
+
+
#   + + display_level +
+ + +

This represents the amount of information displayed by the default search. +NONE means no display, VERBOSE means extra information.

+
+ + +
+
+
#   + + decision_builder +
+ + +

When defined, this overrides the default impact based decision builder.

+
+ + +
+
+
+
+ #   + + + class + Solver: +
+ +
+ View Source +
class Solver(object):
+    r"""
+    Solver Class
+
+    A solver represents the main computation engine. It implements the entire
+    range of Constraint Programming protocols:
+      - Reversibility
+      - Propagation
+      - Search
+
+    Usually, Constraint Programming code consists of
+      - the creation of the Solver,
+      - the creation of the decision variables of the model,
+      - the creation of the constraints of the model and their addition to the
+        solver() through the AddConstraint() method,
+      - the creation of the main DecisionBuilder class,
+      - the launch of the solve() method with the decision builder.
+
+    For the time being, Solver is neither MT_SAFE nor MT_HOT.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+    INT_VAR_DEFAULT = _pywrapcp.Solver_INT_VAR_DEFAULT
+    r""" The default behavior is CHOOSE_FIRST_UNBOUND."""
+    INT_VAR_SIMPLE = _pywrapcp.Solver_INT_VAR_SIMPLE
+    r""" The simple selection is CHOOSE_FIRST_UNBOUND."""
+    CHOOSE_FIRST_UNBOUND = _pywrapcp.Solver_CHOOSE_FIRST_UNBOUND
+    r"""
+    Select the first unbound variable.
+    Variables are considered in the order of the vector of IntVars used
+    to create the selector.
+    """
+    CHOOSE_RANDOM = _pywrapcp.Solver_CHOOSE_RANDOM
+    r""" Randomly select one of the remaining unbound variables."""
+    CHOOSE_MIN_SIZE_LOWEST_MIN = _pywrapcp.Solver_CHOOSE_MIN_SIZE_LOWEST_MIN
+    r"""
+    Among unbound variables, select the variable with the smallest size,
+    i.e., the smallest number of possible values.
+    In case of a tie, the selected variables is the one with the lowest min
+    value.
+    In case of a tie, the first one is selected, first being defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_MIN_SIZE_HIGHEST_MIN = _pywrapcp.Solver_CHOOSE_MIN_SIZE_HIGHEST_MIN
+    r"""
+    Among unbound variables, select the variable with the smallest size,
+    i.e., the smallest number of possible values.
+    In case of a tie, the selected variable is the one with the highest min
+    value.
+    In case of a tie, the first one is selected, first being defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_MIN_SIZE_LOWEST_MAX = _pywrapcp.Solver_CHOOSE_MIN_SIZE_LOWEST_MAX
+    r"""
+    Among unbound variables, select the variable with the smallest size,
+    i.e., the smallest number of possible values.
+    In case of a tie, the selected variables is the one with the lowest max
+    value.
+    In case of a tie, the first one is selected, first being defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_MIN_SIZE_HIGHEST_MAX = _pywrapcp.Solver_CHOOSE_MIN_SIZE_HIGHEST_MAX
+    r"""
+    Among unbound variables, select the variable with the smallest size,
+    i.e., the smallest number of possible values.
+    In case of a tie, the selected variable is the one with the highest max
+    value.
+    In case of a tie, the first one is selected, first being defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_LOWEST_MIN = _pywrapcp.Solver_CHOOSE_LOWEST_MIN
+    r"""
+    Among unbound variables, select the variable with the smallest minimal
+    value.
+    In case of a tie, the first one is selected, "first" defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_HIGHEST_MAX = _pywrapcp.Solver_CHOOSE_HIGHEST_MAX
+    r"""
+    Among unbound variables, select the variable with the highest maximal
+    value.
+    In case of a tie, the first one is selected, first being defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_MIN_SIZE = _pywrapcp.Solver_CHOOSE_MIN_SIZE
+    r"""
+    Among unbound variables, select the variable with the smallest size.
+    In case of a tie, the first one is selected, first being defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_MAX_SIZE = _pywrapcp.Solver_CHOOSE_MAX_SIZE
+    r"""
+    Among unbound variables, select the variable with the highest size.
+    In case of a tie, the first one is selected, first being defined by the
+    order in the vector of IntVars used to create the selector.
+    """
+    CHOOSE_MAX_REGRET_ON_MIN = _pywrapcp.Solver_CHOOSE_MAX_REGRET_ON_MIN
+    r"""
+    Among unbound variables, select the variable with the largest
+    gap between the first and the second values of the domain.
+    """
+    CHOOSE_PATH = _pywrapcp.Solver_CHOOSE_PATH
+    r"""
+    Selects the next unbound variable on a path, the path being defined by
+    the variables: var[i] corresponds to the index of the next of i.
+    """
+    INT_VALUE_DEFAULT = _pywrapcp.Solver_INT_VALUE_DEFAULT
+    r""" The default behavior is ASSIGN_MIN_VALUE."""
+    INT_VALUE_SIMPLE = _pywrapcp.Solver_INT_VALUE_SIMPLE
+    r""" The simple selection is ASSIGN_MIN_VALUE."""
+    ASSIGN_MIN_VALUE = _pywrapcp.Solver_ASSIGN_MIN_VALUE
+    r""" Selects the min value of the selected variable."""
+    ASSIGN_MAX_VALUE = _pywrapcp.Solver_ASSIGN_MAX_VALUE
+    r""" Selects the max value of the selected variable."""
+    ASSIGN_RANDOM_VALUE = _pywrapcp.Solver_ASSIGN_RANDOM_VALUE
+    r""" Selects randomly one of the possible values of the selected variable."""
+    ASSIGN_CENTER_VALUE = _pywrapcp.Solver_ASSIGN_CENTER_VALUE
+    r"""
+    Selects the first possible value which is the closest to the center
+    of the domain of the selected variable.
+    The center is defined as (min + max) / 2.
+    """
+    SPLIT_LOWER_HALF = _pywrapcp.Solver_SPLIT_LOWER_HALF
+    r"""
+    Split the domain in two around the center, and choose the lower
+    part first.
+    """
+    SPLIT_UPPER_HALF = _pywrapcp.Solver_SPLIT_UPPER_HALF
+    r"""
+    Split the domain in two around the center, and choose the lower
+    part first.
+    """
+    SEQUENCE_DEFAULT = _pywrapcp.Solver_SEQUENCE_DEFAULT
+    SEQUENCE_SIMPLE = _pywrapcp.Solver_SEQUENCE_SIMPLE
+    CHOOSE_MIN_SLACK_RANK_FORWARD = _pywrapcp.Solver_CHOOSE_MIN_SLACK_RANK_FORWARD
+    CHOOSE_RANDOM_RANK_FORWARD = _pywrapcp.Solver_CHOOSE_RANDOM_RANK_FORWARD
+    INTERVAL_DEFAULT = _pywrapcp.Solver_INTERVAL_DEFAULT
+    r""" The default is INTERVAL_SET_TIMES_FORWARD."""
+    INTERVAL_SIMPLE = _pywrapcp.Solver_INTERVAL_SIMPLE
+    r""" The simple is INTERVAL_SET_TIMES_FORWARD."""
+    INTERVAL_SET_TIMES_FORWARD = _pywrapcp.Solver_INTERVAL_SET_TIMES_FORWARD
+    r"""
+    Selects the variable with the lowest starting time of all variables,
+    and fixes its starting time to this lowest value.
+    """
+    INTERVAL_SET_TIMES_BACKWARD = _pywrapcp.Solver_INTERVAL_SET_TIMES_BACKWARD
+    r"""
+    Selects the variable with the highest ending time of all variables,
+    and fixes the ending time to this highest values.
+    """
+    TWOOPT = _pywrapcp.Solver_TWOOPT
+    r"""
+    Operator which reverses a sub-chain of a path. It is called TwoOpt
+    because it breaks two arcs on the path; resulting paths are called
+    two-optimal.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 -> 5
+    (where (1, 5) are first and last nodes of the path and can therefore not
+    be moved):
+      1 -> [3 -> 2] -> 4  -> 5
+      1 -> [4 -> 3  -> 2] -> 5
+      1 ->  2 -> [4 -> 3] -> 5
+    """
+    OROPT = _pywrapcp.Solver_OROPT
+    r"""
+    Relocate: OROPT and RELOCATE.
+    Operator which moves a sub-chain of a path to another position; the
+    specified chain length is the fixed length of the chains being moved.
+    When this length is 1, the operator simply moves a node to another
+    position.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 -> 5, for a chain
+    length of 2 (where (1, 5) are first and last nodes of the path and can
+    therefore not be moved):
+      1 ->  4 -> [2 -> 3] -> 5
+      1 -> [3 -> 4] -> 2  -> 5
+
+    Using Relocate with chain lengths of 1, 2 and 3 together is equivalent
+    to the OrOpt operator on a path. The OrOpt operator is a limited
+     version of 3Opt (breaks 3 arcs on a path).
+    """
+    RELOCATE = _pywrapcp.Solver_RELOCATE
+    r""" Relocate neighborhood with length of 1 (see OROPT comment)."""
+    EXCHANGE = _pywrapcp.Solver_EXCHANGE
+    r"""
+    Operator which exchanges the positions of two nodes.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 -> 5
+    (where (1, 5) are first and last nodes of the path and can therefore not
+    be moved):
+      1 -> [3] -> [2] ->  4  -> 5
+      1 -> [4] ->  3  -> [2] -> 5
+      1 ->  2  -> [4] -> [3] -> 5
+    """
+    CROSS = _pywrapcp.Solver_CROSS
+    r"""
+    Operator which cross exchanges the starting chains of 2 paths, including
+    exchanging the whole paths.
+    First and last nodes are not moved.
+    Possible neighbors for the paths 1 -> 2 -> 3 -> 4 -> 5 and 6 -> 7 -> 8
+    (where (1, 5) and (6, 8) are first and last nodes of the paths and can
+    therefore not be moved):
+      1 -> [7] -> 3 -> 4 -> 5  6 -> [2] -> 8
+      1 -> [7] -> 4 -> 5       6 -> [2 -> 3] -> 8
+      1 -> [7] -> 5            6 -> [2 -> 3 -> 4] -> 8
+    """
+    MAKEACTIVE = _pywrapcp.Solver_MAKEACTIVE
+    r"""
+    Operator which inserts an inactive node into a path.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 with 5 inactive
+    (where 1 and 4 are first and last nodes of the path) are:
+      1 -> [5] ->  2  ->  3  -> 4
+      1 ->  2  -> [5] ->  3  -> 4
+      1 ->  2  ->  3  -> [5] -> 4
+    """
+    MAKEINACTIVE = _pywrapcp.Solver_MAKEINACTIVE
+    r"""
+    Operator which makes path nodes inactive.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 (where 1 and 4 are
+    first and last nodes of the path) are:
+      1 -> 3 -> 4 with 2 inactive
+      1 -> 2 -> 4 with 3 inactive
+    """
+    MAKECHAININACTIVE = _pywrapcp.Solver_MAKECHAININACTIVE
+    r"""
+    Operator which makes a "chain" of path nodes inactive.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 (where 1 and 4 are
+    first and last nodes of the path) are:
+      1 -> 3 -> 4 with 2 inactive
+      1 -> 2 -> 4 with 3 inactive
+      1 -> 4 with 2 and 3 inactive
+    """
+    SWAPACTIVE = _pywrapcp.Solver_SWAPACTIVE
+    r"""
+    Operator which replaces an active node by an inactive one.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 with 5 inactive
+    (where 1 and 4 are first and last nodes of the path) are:
+      1 -> [5] ->  3  -> 4 with 2 inactive
+      1 ->  2  -> [5] -> 4 with 3 inactive
+    """
+    EXTENDEDSWAPACTIVE = _pywrapcp.Solver_EXTENDEDSWAPACTIVE
+    r"""
+    Operator which makes an inactive node active and an active one inactive.
+    It is similar to SwapActiveOperator except that it tries to insert the
+    inactive node in all possible positions instead of just the position of
+    the node made inactive.
+    Possible neighbors for the path 1 -> 2 -> 3 -> 4 with 5 inactive
+    (where 1 and 4 are first and last nodes of the path) are:
+      1 -> [5] ->  3  -> 4 with 2 inactive
+      1 ->  3  -> [5] -> 4 with 2 inactive
+      1 -> [5] ->  2  -> 4 with 3 inactive
+      1 ->  2  -> [5] -> 4 with 3 inactive
+    """
+    PATHLNS = _pywrapcp.Solver_PATHLNS
+    r"""
+    Operator which relaxes two sub-chains of three consecutive arcs each.
+    Each sub-chain is defined by a start node and the next three arcs. Those
+    six arcs are relaxed to build a new neighbor.
+    PATHLNS explores all possible pairs of starting nodes and so defines
+    n^2 neighbors, n being the number of nodes.
+    Note that the two sub-chains can be part of the same path; they even may
+    overlap.
+    """
+    FULLPATHLNS = _pywrapcp.Solver_FULLPATHLNS
+    r"""
+    Operator which relaxes one entire path and all inactive nodes, thus
+    defining num_paths neighbors.
+    """
+    UNACTIVELNS = _pywrapcp.Solver_UNACTIVELNS
+    r"""
+    Operator which relaxes all inactive nodes and one sub-chain of six
+    consecutive arcs. That way the path can be improved by inserting
+    inactive nodes or swapping arcs.
+    """
+    INCREMENT = _pywrapcp.Solver_INCREMENT
+    r"""
+    Operator which defines one neighbor per variable. Each neighbor tries to
+    increment by one the value of the corresponding variable. When a new
+    solution is found the neighborhood is rebuilt from scratch, i.e., tries
+    to increment values in the variable order.
+    Consider for instance variables x and y. x is incremented one by one to
+    its max, and when it is not possible to increment x anymore, y is
+    incremented once. If this is a solution, then next neighbor tries to
+    increment x.
+    """
+    DECREMENT = _pywrapcp.Solver_DECREMENT
+    r"""
+    Operator which defines a neighborhood to decrement values.
+    The behavior is the same as INCREMENT, except values are decremented
+    instead of incremented.
+    """
+    SIMPLELNS = _pywrapcp.Solver_SIMPLELNS
+    r"""
+    Operator which defines one neighbor per variable. Each neighbor relaxes
+    one variable.
+    When a new solution is found the neighborhood is rebuilt from scratch.
+    Consider for instance variables x and y. First x is relaxed and the
+    solver is looking for the best possible solution (with only x relaxed).
+    Then y is relaxed, and the solver is looking for a new solution.
+    If a new solution is found, then the next variable to be relaxed is x.
+    """
+    GE = _pywrapcp.Solver_GE
+    r""" Move is accepted when the current objective value >= objective.Min."""
+    LE = _pywrapcp.Solver_LE
+    r""" Move is accepted when the current objective value <= objective.Max."""
+    EQ = _pywrapcp.Solver_EQ
+    r"""
+    Move is accepted when the current objective value is in the interval
+    objective.Min .. objective.Max.
+    """
+    DELAYED_PRIORITY = _pywrapcp.Solver_DELAYED_PRIORITY
+    r"""
+    DELAYED_PRIORITY is the lowest priority: Demons will be processed after
+    VAR_PRIORITY and NORMAL_PRIORITY demons.
+    """
+    VAR_PRIORITY = _pywrapcp.Solver_VAR_PRIORITY
+    r""" VAR_PRIORITY is between DELAYED_PRIORITY and NORMAL_PRIORITY."""
+    NORMAL_PRIORITY = _pywrapcp.Solver_NORMAL_PRIORITY
+    r""" NORMAL_PRIORITY is the highest priority: Demons will be processed first."""
+
+    def __init__(self, *args):
+        _pywrapcp.Solver_swiginit(self, _pywrapcp.new_Solver(*args))
+
+        self.__python_constraints = []
+
+
+
+    __swig_destroy__ = _pywrapcp.delete_Solver
+
+    def Parameters(self) -> "operations_research::ConstraintSolverParameters":
+        r""" Stored Parameters."""
+        return _pywrapcp.Solver_Parameters(self)
+
+    @staticmethod
+    def DefaultSolverParameters() -> "operations_research::ConstraintSolverParameters":
+        r""" Create a ConstraintSolverParameters proto with all the default values."""
+        return _pywrapcp.Solver_DefaultSolverParameters()
+
+    def AddConstraint(self, c: "Constraint") -> "void":
+        r"""
+        Adds the constraint 'c' to the model.
+
+        After calling this method, and until there is a backtrack that undoes the
+        addition, any assignment of variables to values must satisfy the given
+        constraint in order to be considered feasible. There are two fairly
+        different use cases:
+
+        - the most common use case is modeling: the given constraint is really
+        part of the problem that the user is trying to solve. In this use case,
+        AddConstraint is called outside of search (i.e., with state() ==
+        OUTSIDE_SEARCH). Most users should only use AddConstraint in this
+        way. In this case, the constraint will belong to the model forever: it
+        cannot not be removed by backtracking.
+
+        - a rarer use case is that 'c' is not a real constraint of the model. It
+        may be a constraint generated by a branching decision (a constraint whose
+        goal is to restrict the search space), a symmetry breaking constraint (a
+        constraint that does restrict the search space, but in a way that cannot
+        have an impact on the quality of the solutions in the subtree), or an
+        inferred constraint that, while having no semantic value to the model (it
+        does not restrict the set of solutions), is worth having because we
+        believe it may strengthen the propagation. In these cases, it happens
+        that the constraint is added during the search (i.e., with state() ==
+        IN_SEARCH or state() == IN_ROOT_NODE). When a constraint is
+        added during a search, it applies only to the subtree of the search tree
+        rooted at the current node, and will be automatically removed by
+        backtracking.
+
+        This method does not take ownership of the constraint. If the constraint
+        has been created by any factory method (Solver::MakeXXX), it will
+        automatically be deleted. However, power users who implement their own
+        constraints should do: solver.AddConstraint(solver.RevAlloc(new
+        MyConstraint(...));
+        """
+        return _pywrapcp.Solver_AddConstraint(self, c)
+
+    def Solve(self, *args) -> "bool":
+        return _pywrapcp.Solver_Solve(self, *args)
+
+    def NewSearch(self, *args) -> "void":
+        return _pywrapcp.Solver_NewSearch(self, *args)
+
+    def NextSolution(self) -> "bool":
+        return _pywrapcp.Solver_NextSolution(self)
+
+    def RestartSearch(self) -> "void":
+        return _pywrapcp.Solver_RestartSearch(self)
+
+    def EndSearch(self) -> "void":
+        return _pywrapcp.Solver_EndSearch(self)
+
+    def SolveAndCommit(self, *args) -> "bool":
+        return _pywrapcp.Solver_SolveAndCommit(self, *args)
+
+    def CheckAssignment(self, solution: "Assignment") -> "bool":
+        r""" Checks whether the given assignment satisfies all relevant constraints."""
+        return _pywrapcp.Solver_CheckAssignment(self, solution)
+
+    def CheckConstraint(self, ct: "Constraint") -> "bool":
+        r"""
+        Checks whether adding this constraint will lead to an immediate
+        failure. It will return false if the model is already inconsistent, or if
+        adding the constraint makes it inconsistent.
+        """
+        return _pywrapcp.Solver_CheckConstraint(self, ct)
+
+    def Fail(self) -> "void":
+        r""" Abandon the current branch in the search tree. A backtrack will follow."""
+        return _pywrapcp.Solver_Fail(self)
+
+    @staticmethod
+    def MemoryUsage() -> "int64_t":
+        r""" Current memory usage in bytes"""
+        return _pywrapcp.Solver_MemoryUsage()
+
+    def WallTime(self) -> "int64_t":
+        r"""
+        DEPRECATED: Use Now() instead.
+        Time elapsed, in ms since the creation of the solver.
+        """
+        return _pywrapcp.Solver_WallTime(self)
+
+    def Branches(self) -> "int64_t":
+        r""" The number of branches explored since the creation of the solver."""
+        return _pywrapcp.Solver_Branches(self)
+
+    def Solutions(self) -> "int64_t":
+        r""" The number of solutions found since the start of the search."""
+        return _pywrapcp.Solver_Solutions(self)
+
+    def Failures(self) -> "int64_t":
+        r""" The number of failures encountered since the creation of the solver."""
+        return _pywrapcp.Solver_Failures(self)
+
+    def AcceptedNeighbors(self) -> "int64_t":
+        r""" The number of accepted neighbors."""
+        return _pywrapcp.Solver_AcceptedNeighbors(self)
+
+    def Stamp(self) -> "uint64_t":
+        r"""
+        The stamp indicates how many moves in the search tree we have performed.
+        It is useful to detect if we need to update same lazy structures.
+        """
+        return _pywrapcp.Solver_Stamp(self)
+
+    def FailStamp(self) -> "uint64_t":
+        r""" The fail_stamp() is incremented after each backtrack."""
+        return _pywrapcp.Solver_FailStamp(self)
+
+    def IntVar(self, *args) -> "operations_research::IntVar *":
+        r"""
+        *Overload 1:*
+        MakeIntVar will create the best range based int var for the bounds given.
+
+        |
+
+        *Overload 2:*
+        MakeIntVar will create a variable with the given sparse domain.
+
+        |
+
+        *Overload 3:*
+        MakeIntVar will create a variable with the given sparse domain.
+
+        |
+
+        *Overload 4:*
+        MakeIntVar will create the best range based int var for the bounds given.
+
+        |
+
+        *Overload 5:*
+        MakeIntVar will create a variable with the given sparse domain.
+
+        |
+
+        *Overload 6:*
+        MakeIntVar will create a variable with the given sparse domain.
+        """
+        return _pywrapcp.Solver_IntVar(self, *args)
+
+    def BoolVar(self, *args) -> "operations_research::IntVar *":
+        r"""
+        *Overload 1:*
+        MakeBoolVar will create a variable with a {0, 1} domain.
+
+        |
+
+        *Overload 2:*
+        MakeBoolVar will create a variable with a {0, 1} domain.
+        """
+        return _pywrapcp.Solver_BoolVar(self, *args)
+
+    def IntConst(self, *args) -> "operations_research::IntVar *":
+        r"""
+        *Overload 1:*
+        IntConst will create a constant expression.
+
+        |
+
+        *Overload 2:*
+        IntConst will create a constant expression.
+        """
+        return _pywrapcp.Solver_IntConst(self, *args)
+
+    def Sum(self, vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::IntExpr *":
+        r""" sum of all vars."""
+        return _pywrapcp.Solver_Sum(self, vars)
+
+    def ScalProd(self, *args) -> "operations_research::IntExpr *":
+        r"""
+        *Overload 1:*
+        scalar product
+
+        |
+
+        *Overload 2:*
+        scalar product
+        """
+        return _pywrapcp.Solver_ScalProd(self, *args)
+
+    def MonotonicElement(self, values: "operations_research::Solver::IndexEvaluator1", increasing: "bool", index: "IntVar") -> "operations_research::IntExpr *":
+        r"""
+        Function based element. The constraint takes ownership of the
+        callback.  The callback must be monotonic. It must be able to
+        cope with any possible value in the domain of 'index'
+        (potentially negative ones too). Furtermore, monotonicity is not
+        checked. Thus giving a non-monotonic function, or specifying an
+        incorrect increasing parameter will result in undefined behavior.
+        """
+        return _pywrapcp.Solver_MonotonicElement(self, values, increasing, index)
+
+    def Element(self, *args) -> "operations_research::IntExpr *":
+        r"""
+        *Overload 1:*
+        values[index]
+
+        |
+
+        *Overload 2:*
+        values[index]
+
+        |
+
+        *Overload 3:*
+        Function-based element. The constraint takes ownership of the
+        callback. The callback must be able to cope with any possible
+        value in the domain of 'index' (potentially negative ones too).
+
+        |
+
+        *Overload 4:*
+        2D version of function-based element expression, values(expr1, expr2).
+
+        |
+
+        *Overload 5:*
+        vars[expr]
+        """
+        return _pywrapcp.Solver_Element(self, *args)
+
+    def IndexExpression(self, vars: "std::vector< operations_research::IntVar * > const &", value: "int64_t") -> "operations_research::IntExpr *":
+        r"""
+        Returns the expression expr such that vars[expr] == value.
+        It assumes that vars are all different.
+        """
+        return _pywrapcp.Solver_IndexExpression(self, vars, value)
+
+    def Min(self, *args) -> "operations_research::IntExpr *":
+        r"""
+        *Overload 1:*
+        std::min(vars)
+
+        |
+
+        *Overload 2:*
+        std::min (left, right)
+
+        |
+
+        *Overload 3:*
+        std::min(expr, value)
+
+        |
+
+        *Overload 4:*
+        std::min(expr, value)
+        """
+        return _pywrapcp.Solver_Min(self, *args)
+
+    def Max(self, *args) -> "operations_research::IntExpr *":
+        r"""
+        *Overload 1:*
+        std::max(vars)
+
+        |
+
+        *Overload 2:*
+        std::max(left, right)
+
+        |
+
+        *Overload 3:*
+        std::max(expr, value)
+
+        |
+
+        *Overload 4:*
+        std::max(expr, value)
+        """
+        return _pywrapcp.Solver_Max(self, *args)
+
+    def ConvexPiecewiseExpr(self, expr: "IntExpr", early_cost: "int64_t", early_date: "int64_t", late_date: "int64_t", late_cost: "int64_t") -> "operations_research::IntExpr *":
+        r""" Convex piecewise function."""
+        return _pywrapcp.Solver_ConvexPiecewiseExpr(self, expr, early_cost, early_date, late_date, late_cost)
+
+    def SemiContinuousExpr(self, expr: "IntExpr", fixed_charge: "int64_t", step: "int64_t") -> "operations_research::IntExpr *":
+        r"""
+        Semi continuous Expression (x <= 0 -> f(x) = 0; x > 0 -> f(x) = ax + b)
+        a >= 0 and b >= 0
+        """
+        return _pywrapcp.Solver_SemiContinuousExpr(self, expr, fixed_charge, step)
+
+    def ConditionalExpression(self, condition: "IntVar", expr: "IntExpr", unperformed_value: "int64_t") -> "operations_research::IntExpr *":
+        r""" Conditional Expr condition ? expr : unperformed_value"""
+        return _pywrapcp.Solver_ConditionalExpression(self, condition, expr, unperformed_value)
+
+    def TrueConstraint(self) -> "operations_research::Constraint *":
+        r""" This constraint always succeeds."""
+        return _pywrapcp.Solver_TrueConstraint(self)
+
+    def FalseConstraint(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_FalseConstraint(self, *args)
+
+    def IsEqualCstCt(self, var: "IntExpr", value: "int64_t", boolvar: "IntVar") -> "operations_research::Constraint *":
+        r""" boolvar == (var == value)"""
+        return _pywrapcp.Solver_IsEqualCstCt(self, var, value, boolvar)
+
+    def IsEqualCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var == value)"""
+        return _pywrapcp.Solver_IsEqualCstVar(self, var, value)
+
+    def IsEqualCt(self, v1: "IntExpr", v2: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (v1 == v2)"""
+        return _pywrapcp.Solver_IsEqualCt(self, v1, v2, b)
+
+    def IsEqualVar(self, v1: "IntExpr", v2: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (v1 == v2)"""
+        return _pywrapcp.Solver_IsEqualVar(self, v1, v2)
+
+    def IsDifferentCstCt(self, var: "IntExpr", value: "int64_t", boolvar: "IntVar") -> "operations_research::Constraint *":
+        r""" boolvar == (var != value)"""
+        return _pywrapcp.Solver_IsDifferentCstCt(self, var, value, boolvar)
+
+    def IsDifferentCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var != value)"""
+        return _pywrapcp.Solver_IsDifferentCstVar(self, var, value)
+
+    def IsDifferentVar(self, v1: "IntExpr", v2: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (v1 != v2)"""
+        return _pywrapcp.Solver_IsDifferentVar(self, v1, v2)
+
+    def IsDifferentCt(self, v1: "IntExpr", v2: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (v1 != v2)"""
+        return _pywrapcp.Solver_IsDifferentCt(self, v1, v2, b)
+
+    def IsLessOrEqualCstCt(self, var: "IntExpr", value: "int64_t", boolvar: "IntVar") -> "operations_research::Constraint *":
+        r""" boolvar == (var <= value)"""
+        return _pywrapcp.Solver_IsLessOrEqualCstCt(self, var, value, boolvar)
+
+    def IsLessOrEqualCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var <= value)"""
+        return _pywrapcp.Solver_IsLessOrEqualCstVar(self, var, value)
+
+    def IsLessOrEqualVar(self, left: "IntExpr", right: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (left <= right)"""
+        return _pywrapcp.Solver_IsLessOrEqualVar(self, left, right)
+
+    def IsLessOrEqualCt(self, left: "IntExpr", right: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (left <= right)"""
+        return _pywrapcp.Solver_IsLessOrEqualCt(self, left, right, b)
+
+    def IsGreaterOrEqualCstCt(self, var: "IntExpr", value: "int64_t", boolvar: "IntVar") -> "operations_research::Constraint *":
+        r""" boolvar == (var >= value)"""
+        return _pywrapcp.Solver_IsGreaterOrEqualCstCt(self, var, value, boolvar)
+
+    def IsGreaterOrEqualCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var >= value)"""
+        return _pywrapcp.Solver_IsGreaterOrEqualCstVar(self, var, value)
+
+    def IsGreaterOrEqualVar(self, left: "IntExpr", right: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (left >= right)"""
+        return _pywrapcp.Solver_IsGreaterOrEqualVar(self, left, right)
+
+    def IsGreaterOrEqualCt(self, left: "IntExpr", right: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (left >= right)"""
+        return _pywrapcp.Solver_IsGreaterOrEqualCt(self, left, right, b)
+
+    def IsGreaterCstCt(self, v: "IntExpr", c: "int64_t", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (v > c)"""
+        return _pywrapcp.Solver_IsGreaterCstCt(self, v, c, b)
+
+    def IsGreaterCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var > value)"""
+        return _pywrapcp.Solver_IsGreaterCstVar(self, var, value)
+
+    def IsGreaterVar(self, left: "IntExpr", right: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (left > right)"""
+        return _pywrapcp.Solver_IsGreaterVar(self, left, right)
+
+    def IsGreaterCt(self, left: "IntExpr", right: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (left > right)"""
+        return _pywrapcp.Solver_IsGreaterCt(self, left, right, b)
+
+    def IsLessCstCt(self, v: "IntExpr", c: "int64_t", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (v < c)"""
+        return _pywrapcp.Solver_IsLessCstCt(self, v, c, b)
+
+    def IsLessCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var < value)"""
+        return _pywrapcp.Solver_IsLessCstVar(self, var, value)
+
+    def IsLessVar(self, left: "IntExpr", right: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (left < right)"""
+        return _pywrapcp.Solver_IsLessVar(self, left, right)
+
+    def IsLessCt(self, left: "IntExpr", right: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (left < right)"""
+        return _pywrapcp.Solver_IsLessCt(self, left, right, b)
+
+    def SumLessOrEqual(self, vars: "std::vector< operations_research::IntVar * > const &", cst: "int64_t") -> "operations_research::Constraint *":
+        r""" Variation on arrays."""
+        return _pywrapcp.Solver_SumLessOrEqual(self, vars, cst)
+
+    def SumGreaterOrEqual(self, vars: "std::vector< operations_research::IntVar * > const &", cst: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_SumGreaterOrEqual(self, vars, cst)
+
+    def SumEquality(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_SumEquality(self, *args)
+
+    def ScalProdEquality(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_ScalProdEquality(self, *args)
+
+    def ScalProdGreaterOrEqual(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_ScalProdGreaterOrEqual(self, *args)
+
+    def ScalProdLessOrEqual(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_ScalProdLessOrEqual(self, *args)
+
+    def MinEquality(self, vars: "std::vector< operations_research::IntVar * > const &", min_var: "IntVar") -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_MinEquality(self, vars, min_var)
+
+    def MaxEquality(self, vars: "std::vector< operations_research::IntVar * > const &", max_var: "IntVar") -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_MaxEquality(self, vars, max_var)
+
+    def ElementEquality(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_ElementEquality(self, *args)
+
+    def AbsEquality(self, var: "IntVar", abs_var: "IntVar") -> "operations_research::Constraint *":
+        r""" Creates the constraint abs(var) == abs_var."""
+        return _pywrapcp.Solver_AbsEquality(self, var, abs_var)
+
+    def IndexOfConstraint(self, vars: "std::vector< operations_research::IntVar * > const &", index: "IntVar", target: "int64_t") -> "operations_research::Constraint *":
+        r"""
+        This constraint is a special case of the element constraint with
+        an array of integer variables, where the variables are all
+        different and the index variable is constrained such that
+        vars[index] == target.
+        """
+        return _pywrapcp.Solver_IndexOfConstraint(self, vars, index, target)
+
+    def ConstraintInitialPropagateCallback(self, ct: "Constraint") -> "operations_research::Demon *":
+        r"""
+        This method is a specialized case of the MakeConstraintDemon
+        method to call the InitiatePropagate of the constraint 'ct'.
+        """
+        return _pywrapcp.Solver_ConstraintInitialPropagateCallback(self, ct)
+
+    def DelayedConstraintInitialPropagateCallback(self, ct: "Constraint") -> "operations_research::Demon *":
+        r"""
+        This method is a specialized case of the MakeConstraintDemon
+        method to call the InitiatePropagate of the constraint 'ct' with
+        low priority.
+        """
+        return _pywrapcp.Solver_DelayedConstraintInitialPropagateCallback(self, ct)
+
+    def ClosureDemon(self, closure: "operations_research::Solver::Closure") -> "operations_research::Demon *":
+        r""" Creates a demon from a closure."""
+        return _pywrapcp.Solver_ClosureDemon(self, closure)
+
+    def BetweenCt(self, expr: "IntExpr", l: "int64_t", u: "int64_t") -> "operations_research::Constraint *":
+        r""" (l <= expr <= u)"""
+        return _pywrapcp.Solver_BetweenCt(self, expr, l, u)
+
+    def IsBetweenCt(self, expr: "IntExpr", l: "int64_t", u: "int64_t", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (l <= expr <= u)"""
+        return _pywrapcp.Solver_IsBetweenCt(self, expr, l, u, b)
+
+    def IsBetweenVar(self, v: "IntExpr", l: "int64_t", u: "int64_t") -> "operations_research::IntVar *":
+        return _pywrapcp.Solver_IsBetweenVar(self, v, l, u)
+
+    def MemberCt(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_MemberCt(self, *args)
+
+    def NotMemberCt(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        expr not in set.
+
+        |
+
+        *Overload 2:*
+        expr should not be in the list of forbidden intervals [start[i]..end[i]].
+
+        |
+
+        *Overload 3:*
+        expr should not be in the list of forbidden intervals [start[i]..end[i]].
+        """
+        return _pywrapcp.Solver_NotMemberCt(self, *args)
+
+    def IsMemberCt(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_IsMemberCt(self, *args)
+
+    def IsMemberVar(self, *args) -> "operations_research::IntVar *":
+        return _pywrapcp.Solver_IsMemberVar(self, *args)
+
+    def Count(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        |{i | vars[i] == value}| == max_count
+
+        |
+
+        *Overload 2:*
+        |{i | vars[i] == value}| == max_count
+        """
+        return _pywrapcp.Solver_Count(self, *args)
+
+    def Distribute(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        Aggregated version of count:  |{i | v[i] == values[j]}| == cards[j]
+
+        |
+
+        *Overload 2:*
+        Aggregated version of count:  |{i | v[i] == values[j]}| == cards[j]
+
+        |
+
+        *Overload 3:*
+        Aggregated version of count:  |{i | v[i] == j}| == cards[j]
+
+        |
+
+        *Overload 4:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1: card_min <= |{i | v[i] == j}| <= card_max
+
+        |
+
+        *Overload 5:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1:
+           card_min[j] <= |{i | v[i] == j}| <= card_max[j]
+
+        |
+
+        *Overload 6:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1:
+           card_min[j] <= |{i | v[i] == j}| <= card_max[j]
+
+        |
+
+        *Overload 7:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1:
+           card_min[j] <= |{i | v[i] == values[j]}| <= card_max[j]
+
+        |
+
+        *Overload 8:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1:
+           card_min[j] <= |{i | v[i] == values[j]}| <= card_max[j]
+        """
+        return _pywrapcp.Solver_Distribute(self, *args)
+
+    def Deviation(self, vars: "std::vector< operations_research::IntVar * > const &", deviation_var: "IntVar", total_sum: "int64_t") -> "operations_research::Constraint *":
+        r"""
+        Deviation constraint:
+        sum_i |n * vars[i] - total_sum| <= deviation_var and
+        sum_i vars[i] == total_sum
+        n = #vars
+        """
+        return _pywrapcp.Solver_Deviation(self, vars, deviation_var, total_sum)
+
+    def AllDifferent(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        All variables are pairwise different. This corresponds to the
+        stronger version of the propagation algorithm.
+
+        |
+
+        *Overload 2:*
+        All variables are pairwise different.  If 'stronger_propagation'
+        is true, stronger, and potentially slower propagation will
+        occur. This API will be deprecated in the future.
+        """
+        return _pywrapcp.Solver_AllDifferent(self, *args)
+
+    def AllDifferentExcept(self, vars: "std::vector< operations_research::IntVar * > const &", escape_value: "int64_t") -> "operations_research::Constraint *":
+        r"""
+        All variables are pairwise different, unless they are assigned to
+        the escape value.
+        """
+        return _pywrapcp.Solver_AllDifferentExcept(self, vars, escape_value)
+
+    def SortingConstraint(self, vars: "std::vector< operations_research::IntVar * > const &", sorted: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint binding the arrays of variables "vars" and
+        "sorted_vars": sorted_vars[0] must be equal to the minimum of all
+        variables in vars, and so on: the value of sorted_vars[i] must be
+        equal to the i-th value of variables invars.
+
+        This constraint propagates in both directions: from "vars" to
+        "sorted_vars" and vice-versa.
+
+        Behind the scenes, this constraint maintains that:
+          - sorted is always increasing.
+          - whatever the values of vars, there exists a permutation that
+            injects its values into the sorted variables.
+
+        For more info, please have a look at:
+          https://mpi-inf.mpg.de/~mehlhorn/ftp/Mehlhorn-Thiel.pdf
+        """
+        return _pywrapcp.Solver_SortingConstraint(self, vars, sorted)
+
+    def LexicalLess(self, left: "std::vector< operations_research::IntVar * > const &", right: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that enforces that left is lexicographically less
+        than right.
+        """
+        return _pywrapcp.Solver_LexicalLess(self, left, right)
+
+    def LexicalLessOrEqual(self, left: "std::vector< operations_research::IntVar * > const &", right: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that enforces that left is lexicographically less
+        than or equal to right.
+        """
+        return _pywrapcp.Solver_LexicalLessOrEqual(self, left, right)
+
+    def InversePermutationConstraint(self, left: "std::vector< operations_research::IntVar * > const &", right: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that enforces that 'left' and 'right' both
+        represent permutations of [0..left.size()-1], and that 'right' is
+        the inverse permutation of 'left', i.e. for all i in
+        [0..left.size()-1], right[left[i]] = i.
+        """
+        return _pywrapcp.Solver_InversePermutationConstraint(self, left, right)
+
+    def NullIntersect(self, first_vars: "std::vector< operations_research::IntVar * > const &", second_vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that states that all variables in the first
+        vector are different from all variables in the second
+        group. Thus the set of values in the first vector does not
+        intersect with the set of values in the second vector.
+        """
+        return _pywrapcp.Solver_NullIntersect(self, first_vars, second_vars)
+
+    def NullIntersectExcept(self, first_vars: "std::vector< operations_research::IntVar * > const &", second_vars: "std::vector< operations_research::IntVar * > const &", escape_value: "int64_t") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that states that all variables in the first
+        vector are different from all variables from the second group,
+        unless they are assigned to the escape value. Thus the set of
+        values in the first vector minus the escape value does not
+        intersect with the set of values in the second vector.
+        """
+        return _pywrapcp.Solver_NullIntersectExcept(self, first_vars, second_vars, escape_value)
+
+    def Circuit(self, nexts: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r""" Force the "nexts" variable to create a complete Hamiltonian path."""
+        return _pywrapcp.Solver_Circuit(self, nexts)
+
+    def SubCircuit(self, nexts: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Force the "nexts" variable to create a complete Hamiltonian path
+        for those that do not loop upon themselves.
+        """
+        return _pywrapcp.Solver_SubCircuit(self, nexts)
+
+    def DelayedPathCumul(self, nexts: "std::vector< operations_research::IntVar * > const &", active: "std::vector< operations_research::IntVar * > const &", cumuls: "std::vector< operations_research::IntVar * > const &", transits: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Delayed version of the same constraint: propagation on the nexts variables
+        is delayed until all constraints have propagated.
+        """
+        return _pywrapcp.Solver_DelayedPathCumul(self, nexts, active, cumuls, transits)
+
+    def PathCumul(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        Creates a constraint which accumulates values along a path such that:
+        cumuls[next[i]] = cumuls[i] + transits[i].
+        Active variables indicate if the corresponding next variable is active;
+        this could be useful to model unperformed nodes in a routing problem.
+
+        |
+
+        *Overload 2:*
+        Creates a constraint which accumulates values along a path such that:
+        cumuls[next[i]] = cumuls[i] + transit_evaluator(i, next[i]).
+        Active variables indicate if the corresponding next variable is active;
+        this could be useful to model unperformed nodes in a routing problem.
+        Ownership of transit_evaluator is taken and it must be a repeatable
+        callback.
+
+        |
+
+        *Overload 3:*
+        Creates a constraint which accumulates values along a path such that:
+        cumuls[next[i]] = cumuls[i] + transit_evaluator(i, next[i]) + slacks[i].
+        Active variables indicate if the corresponding next variable is active;
+        this could be useful to model unperformed nodes in a routing problem.
+        Ownership of transit_evaluator is taken and it must be a repeatable
+        callback.
+        """
+        return _pywrapcp.Solver_PathCumul(self, *args)
+
+    def AllowedAssignments(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        This method creates a constraint where the graph of the relation
+        between the variables is given in extension. There are 'arity'
+        variables involved in the relation and the graph is given by a
+        integer tuple set.
+
+        |
+
+        *Overload 2:*
+        Compatibility layer for Python API.
+        """
+        return _pywrapcp.Solver_AllowedAssignments(self, *args)
+
+    def TransitionConstraint(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_TransitionConstraint(self, *args)
+
+    def NonOverlappingBoxesConstraint(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_NonOverlappingBoxesConstraint(self, *args)
+
+    def Pack(self, vars: "std::vector< operations_research::IntVar * > const &", number_of_bins: "int") -> "operations_research::Pack *":
+        r"""
+        This constraint packs all variables onto 'number_of_bins'
+        variables.  For any given variable, a value of 'number_of_bins'
+        indicates that the variable is not assigned to any bin.
+        Dimensions, i.e., cumulative constraints on this packing, can be
+        added directly from the pack class.
+        """
+        return _pywrapcp.Solver_Pack(self, vars, number_of_bins)
+
+    def FixedDurationIntervalVar(self, *args) -> "operations_research::IntervalVar *":
+        r"""
+        *Overload 1:*
+        Creates an interval var with a fixed duration. The duration must
+        be greater than 0. If optional is true, then the interval can be
+        performed or unperformed. If optional is false, then the interval
+        is always performed.
+
+        |
+
+        *Overload 2:*
+        Creates a performed interval var with a fixed duration. The duration must
+        be greater than 0.
+
+        |
+
+        *Overload 3:*
+        Creates an interval var with a fixed duration, and performed_variable.
+        The duration must be greater than 0.
+        """
+        return _pywrapcp.Solver_FixedDurationIntervalVar(self, *args)
+
+    def FixedInterval(self, start: "int64_t", duration: "int64_t", name: "std::string const &") -> "operations_research::IntervalVar *":
+        r""" Creates a fixed and performed interval."""
+        return _pywrapcp.Solver_FixedInterval(self, start, duration, name)
+
+    def IntervalVar(self, start_min: "int64_t", start_max: "int64_t", duration_min: "int64_t", duration_max: "int64_t", end_min: "int64_t", end_max: "int64_t", optional: "bool", name: "std::string const &") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var by specifying the bounds on start,
+        duration, and end.
+        """
+        return _pywrapcp.Solver_IntervalVar(self, start_min, start_max, duration_min, duration_max, end_min, end_max, optional, name)
+
+    def MirrorInterval(self, interval_var: "IntervalVar") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var that is the mirror image of the given one, that
+        is, the interval var obtained by reversing the axis.
+        """
+        return _pywrapcp.Solver_MirrorInterval(self, interval_var)
+
+    def FixedDurationStartSyncedOnStartIntervalVar(self, interval_var: "IntervalVar", duration: "int64_t", offset: "int64_t") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var with a fixed duration whose start is
+        synchronized with the start of another interval, with a given
+        offset. The performed status is also in sync with the performed
+        status of the given interval variable.
+        """
+        return _pywrapcp.Solver_FixedDurationStartSyncedOnStartIntervalVar(self, interval_var, duration, offset)
+
+    def FixedDurationStartSyncedOnEndIntervalVar(self, interval_var: "IntervalVar", duration: "int64_t", offset: "int64_t") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var with a fixed duration whose start is
+        synchronized with the end of another interval, with a given
+        offset. The performed status is also in sync with the performed
+        status of the given interval variable.
+        """
+        return _pywrapcp.Solver_FixedDurationStartSyncedOnEndIntervalVar(self, interval_var, duration, offset)
+
+    def FixedDurationEndSyncedOnStartIntervalVar(self, interval_var: "IntervalVar", duration: "int64_t", offset: "int64_t") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var with a fixed duration whose end is
+        synchronized with the start of another interval, with a given
+        offset. The performed status is also in sync with the performed
+        status of the given interval variable.
+        """
+        return _pywrapcp.Solver_FixedDurationEndSyncedOnStartIntervalVar(self, interval_var, duration, offset)
+
+    def FixedDurationEndSyncedOnEndIntervalVar(self, interval_var: "IntervalVar", duration: "int64_t", offset: "int64_t") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var with a fixed duration whose end is
+        synchronized with the end of another interval, with a given
+        offset. The performed status is also in sync with the performed
+        status of the given interval variable.
+        """
+        return _pywrapcp.Solver_FixedDurationEndSyncedOnEndIntervalVar(self, interval_var, duration, offset)
+
+    def IntervalRelaxedMin(self, interval_var: "IntervalVar") -> "operations_research::IntervalVar *":
+        r"""
+         Creates and returns an interval variable that wraps around the given one,
+         relaxing the min start and end. Relaxing means making unbounded when
+         optional. If the variable is non-optional, this method returns
+         interval_var.
+
+         More precisely, such an interval variable behaves as follows:
+        When the underlying must be performed, the returned interval variable
+             behaves exactly as the underlying;
+        When the underlying may or may not be performed, the returned interval
+             variable behaves like the underlying, except that it is unbounded on
+             the min side;
+        When the underlying cannot be performed, the returned interval variable
+             is of duration 0 and must be performed in an interval unbounded on
+             both sides.
+
+         This is very useful to implement propagators that may only modify
+         the start max or end max.
+        """
+        return _pywrapcp.Solver_IntervalRelaxedMin(self, interval_var)
+
+    def IntervalRelaxedMax(self, interval_var: "IntervalVar") -> "operations_research::IntervalVar *":
+        r"""
+         Creates and returns an interval variable that wraps around the given one,
+         relaxing the max start and end. Relaxing means making unbounded when
+         optional. If the variable is non optional, this method returns
+         interval_var.
+
+         More precisely, such an interval variable behaves as follows:
+        When the underlying must be performed, the returned interval variable
+             behaves exactly as the underlying;
+        When the underlying may or may not be performed, the returned interval
+             variable behaves like the underlying, except that it is unbounded on
+             the max side;
+        When the underlying cannot be performed, the returned interval variable
+             is of duration 0 and must be performed in an interval unbounded on
+             both sides.
+
+         This is very useful for implementing propagators that may only modify
+         the start min or end min.
+        """
+        return _pywrapcp.Solver_IntervalRelaxedMax(self, interval_var)
+
+    def TemporalDisjunction(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        This constraint implements a temporal disjunction between two
+        interval vars t1 and t2. 'alt' indicates which alternative was
+        chosen (alt == 0 is equivalent to t1 before t2).
+
+        |
+
+        *Overload 2:*
+        This constraint implements a temporal disjunction between two
+        interval vars.
+        """
+        return _pywrapcp.Solver_TemporalDisjunction(self, *args)
+
+    def DisjunctiveConstraint(self, intervals: "std::vector< operations_research::IntervalVar * > const &", name: "std::string const &") -> "operations_research::DisjunctiveConstraint *":
+        r"""
+        This constraint forces all interval vars into an non-overlapping
+        sequence. Intervals with zero duration can be scheduled anywhere.
+        """
+        return _pywrapcp.Solver_DisjunctiveConstraint(self, intervals, name)
+
+    def Cumulative(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        This constraint forces that, for any integer t, the sum of the demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should only contain non-negative values. Zero values are
+        supported, and the corresponding intervals are filtered out, as they
+        neither impact nor are impacted by this constraint.
+
+        |
+
+        *Overload 2:*
+        This constraint forces that, for any integer t, the sum of the demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should only contain non-negative values. Zero values are
+        supported, and the corresponding intervals are filtered out, as they
+        neither impact nor are impacted by this constraint.
+
+        |
+
+        *Overload 3:*
+        This constraint forces that, for any integer t, the sum of the demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should only contain non-negative values. Zero values are
+        supported, and the corresponding intervals are filtered out, as they
+        neither impact nor are impacted by this constraint.
+
+        |
+
+        *Overload 4:*
+        This constraint enforces that, for any integer t, the sum of the demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should only contain non-negative values. Zero values are
+        supported, and the corresponding intervals are filtered out, as they
+        neither impact nor are impacted by this constraint.
+
+        |
+
+        *Overload 5:*
+        This constraint enforces that, for any integer t, the sum of demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should be positive.
+
+        |
+
+        *Overload 6:*
+        This constraint enforces that, for any integer t, the sum of demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should be positive.
+        """
+        return _pywrapcp.Solver_Cumulative(self, *args)
+
+    def Cover(self, vars: "std::vector< operations_research::IntervalVar * > const &", target_var: "IntervalVar") -> "operations_research::Constraint *":
+        r"""
+        This constraint states that the target_var is the convex hull of
+        the intervals. If none of the interval variables is performed,
+        then the target var is unperformed too. Also, if the target
+        variable is unperformed, then all the intervals variables are
+        unperformed too.
+        """
+        return _pywrapcp.Solver_Cover(self, vars, target_var)
+
+    def Assignment(self, *args) -> "operations_research::Assignment *":
+        r"""
+        *Overload 1:*
+        This method creates an empty assignment.
+
+        |
+
+        *Overload 2:*
+        This method creates an assignment which is a copy of 'a'.
+        """
+        return _pywrapcp.Solver_Assignment(self, *args)
+
+    def FirstSolutionCollector(self, *args) -> "operations_research::SolutionCollector *":
+        r"""
+        *Overload 1:*
+        Collect the first solution of the search.
+
+        |
+
+        *Overload 2:*
+        Collect the first solution of the search. The variables will need to
+        be added later.
+        """
+        return _pywrapcp.Solver_FirstSolutionCollector(self, *args)
+
+    def LastSolutionCollector(self, *args) -> "operations_research::SolutionCollector *":
+        r"""
+        *Overload 1:*
+        Collect the last solution of the search.
+
+        |
+
+        *Overload 2:*
+        Collect the last solution of the search. The variables will need to
+        be added later.
+        """
+        return _pywrapcp.Solver_LastSolutionCollector(self, *args)
+
+    def BestValueSolutionCollector(self, *args) -> "operations_research::SolutionCollector *":
+        r"""
+        *Overload 1:*
+        Collect the solution corresponding to the optimal value of the objective
+        of 'assignment'; if 'assignment' does not have an objective no solution is
+        collected. This collector only collects one solution corresponding to the
+        best objective value (the first one found).
+
+        |
+
+        *Overload 2:*
+        Collect the solution corresponding to the optimal value of the
+        objective of 'assignment'; if 'assignment' does not have an objective no
+        solution is collected. This collector only collects one solution
+        corresponding to the best objective value (the first one
+        found). The variables will need to be added later.
+        """
+        return _pywrapcp.Solver_BestValueSolutionCollector(self, *args)
+
+    def AllSolutionCollector(self, *args) -> "operations_research::SolutionCollector *":
+        r"""
+        *Overload 1:*
+        Collect all solutions of the search.
+
+        |
+
+        *Overload 2:*
+        Collect all solutions of the search. The variables will need to
+        be added later.
+        """
+        return _pywrapcp.Solver_AllSolutionCollector(self, *args)
+
+    def Minimize(self, v: "IntVar", step: "int64_t") -> "operations_research::OptimizeVar *":
+        r""" Creates a minimization objective."""
+        return _pywrapcp.Solver_Minimize(self, v, step)
+
+    def Maximize(self, v: "IntVar", step: "int64_t") -> "operations_research::OptimizeVar *":
+        r""" Creates a maximization objective."""
+        return _pywrapcp.Solver_Maximize(self, v, step)
+
+    def Optimize(self, maximize: "bool", v: "IntVar", step: "int64_t") -> "operations_research::OptimizeVar *":
+        r""" Creates a objective with a given sense (true = maximization)."""
+        return _pywrapcp.Solver_Optimize(self, maximize, v, step)
+
+    def WeightedMinimize(self, *args) -> "operations_research::OptimizeVar *":
+        r"""
+        *Overload 1:*
+        Creates a minimization weighted objective. The actual objective is
+        scalar_prod(sub_objectives, weights).
+
+        |
+
+        *Overload 2:*
+        Creates a minimization weighted objective. The actual objective is
+        scalar_prod(sub_objectives, weights).
+        """
+        return _pywrapcp.Solver_WeightedMinimize(self, *args)
+
+    def WeightedMaximize(self, *args) -> "operations_research::OptimizeVar *":
+        r"""
+        *Overload 1:*
+        Creates a maximization weigthed objective.
+
+        |
+
+        *Overload 2:*
+        Creates a maximization weigthed objective.
+        """
+        return _pywrapcp.Solver_WeightedMaximize(self, *args)
+
+    def WeightedOptimize(self, *args) -> "operations_research::OptimizeVar *":
+        r"""
+        *Overload 1:*
+        Creates a weighted objective with a given sense (true = maximization).
+
+        |
+
+        *Overload 2:*
+        Creates a weighted objective with a given sense (true = maximization).
+        """
+        return _pywrapcp.Solver_WeightedOptimize(self, *args)
+
+    def TabuSearch(self, maximize: "bool", v: "IntVar", step: "int64_t", vars: "std::vector< operations_research::IntVar * > const &", keep_tenure: "int64_t", forbid_tenure: "int64_t", tabu_factor: "double") -> "operations_research::SearchMonitor *":
+        r"""
+        MetaHeuristics which try to get the search out of local optima.
+        Creates a Tabu Search monitor.
+        In the context of local search the behavior is similar to MakeOptimize(),
+        creating an objective in a given sense. The behavior differs once a local
+        optimum is reached: thereafter solutions which degrade the value of the
+        objective are allowed if they are not "tabu". A solution is "tabu" if it
+        doesn't respect the following rules:
+        - improving the best solution found so far
+        - variables in the "keep" list must keep their value, variables in the
+        "forbid" list must not take the value they have in the list.
+        Variables with new values enter the tabu lists after each new solution
+        found and leave the lists after a given number of iterations (called
+        tenure). Only the variables passed to the method can enter the lists.
+        The tabu criterion is softened by the tabu factor which gives the number
+        of "tabu" violations which is tolerated; a factor of 1 means no violations
+        allowed; a factor of 0 means all violations are allowed.
+        """
+        return _pywrapcp.Solver_TabuSearch(self, maximize, v, step, vars, keep_tenure, forbid_tenure, tabu_factor)
+
+    def SimulatedAnnealing(self, maximize: "bool", v: "IntVar", step: "int64_t", initial_temperature: "int64_t") -> "operations_research::SearchMonitor *":
+        r""" Creates a Simulated Annealing monitor."""
+        return _pywrapcp.Solver_SimulatedAnnealing(self, maximize, v, step, initial_temperature)
+
+    def LubyRestart(self, scale_factor: "int") -> "operations_research::SearchMonitor *":
+        r"""
+        This search monitor will restart the search periodically.
+        At the iteration n, it will restart after scale_factor * Luby(n) failures
+        where Luby is the Luby Strategy (i.e. 1 1 2 1 1 2 4 1 1 2 1 1 2 4 8...).
+        """
+        return _pywrapcp.Solver_LubyRestart(self, scale_factor)
+
+    def ConstantRestart(self, frequency: "int") -> "operations_research::SearchMonitor *":
+        r"""
+        This search monitor will restart the search periodically after 'frequency'
+        failures.
+        """
+        return _pywrapcp.Solver_ConstantRestart(self, frequency)
+
+    def TimeLimit(self, *args) -> "operations_research::RegularLimit *":
+        return _pywrapcp.Solver_TimeLimit(self, *args)
+
+    def BranchesLimit(self, branches: "int64_t") -> "operations_research::RegularLimit *":
+        r"""
+        Creates a search limit that constrains the number of branches
+        explored in the search tree.
+        """
+        return _pywrapcp.Solver_BranchesLimit(self, branches)
+
+    def FailuresLimit(self, failures: "int64_t") -> "operations_research::RegularLimit *":
+        r"""
+        Creates a search limit that constrains the number of failures
+        that can happen when exploring the search tree.
+        """
+        return _pywrapcp.Solver_FailuresLimit(self, failures)
+
+    def SolutionsLimit(self, solutions: "int64_t") -> "operations_research::RegularLimit *":
+        r"""
+        Creates a search limit that constrains the number of solutions found
+        during the search.
+        """
+        return _pywrapcp.Solver_SolutionsLimit(self, solutions)
+
+    def Limit(self, *args) -> "operations_research::SearchLimit *":
+        r"""
+        *Overload 1:*
+        Limits the search with the 'time', 'branches', 'failures' and
+        'solutions' limits. 'smart_time_check' reduces the calls to the wall
+
+        |
+
+        *Overload 2:*
+        Creates a search limit from its protobuf description
+
+        |
+
+        *Overload 3:*
+        Creates a search limit that is reached when either of the underlying limit
+        is reached. That is, the returned limit is more stringent than both
+        argument limits.
+        """
+        return _pywrapcp.Solver_Limit(self, *args)
+
+    def CustomLimit(self, limiter: "std::function< bool () >") -> "operations_research::SearchLimit *":
+        r"""
+        Callback-based search limit. Search stops when limiter returns true; if
+        this happens at a leaf the corresponding solution will be rejected.
+        """
+        return _pywrapcp.Solver_CustomLimit(self, limiter)
+
+    def SearchLog(self, *args) -> "operations_research::SearchMonitor *":
+        return _pywrapcp.Solver_SearchLog(self, *args)
+
+    def SearchTrace(self, prefix: "std::string const &") -> "operations_research::SearchMonitor *":
+        r"""
+        Creates a search monitor that will trace precisely the behavior of the
+        search. Use this only for low level debugging.
+        """
+        return _pywrapcp.Solver_SearchTrace(self, prefix)
+
+    def PrintModelVisitor(self) -> "operations_research::ModelVisitor *":
+        r""" Prints the model."""
+        return _pywrapcp.Solver_PrintModelVisitor(self)
+
+    def StatisticsModelVisitor(self) -> "operations_research::ModelVisitor *":
+        r""" Displays some nice statistics on the model."""
+        return _pywrapcp.Solver_StatisticsModelVisitor(self)
+
+    def AssignVariableValue(self, var: "IntVar", val: "int64_t") -> "operations_research::Decision *":
+        r""" Decisions."""
+        return _pywrapcp.Solver_AssignVariableValue(self, var, val)
+
+    def VariableLessOrEqualValue(self, var: "IntVar", value: "int64_t") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_VariableLessOrEqualValue(self, var, value)
+
+    def VariableGreaterOrEqualValue(self, var: "IntVar", value: "int64_t") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_VariableGreaterOrEqualValue(self, var, value)
+
+    def SplitVariableDomain(self, var: "IntVar", val: "int64_t", start_with_lower_half: "bool") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_SplitVariableDomain(self, var, val, start_with_lower_half)
+
+    def AssignVariableValueOrFail(self, var: "IntVar", value: "int64_t") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_AssignVariableValueOrFail(self, var, value)
+
+    def AssignVariablesValues(self, vars: "std::vector< operations_research::IntVar * > const &", values: "std::vector< int64_t > const &") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_AssignVariablesValues(self, vars, values)
+
+    def FailDecision(self) -> "operations_research::Decision *":
+        return _pywrapcp.Solver_FailDecision(self)
+
+    def Decision(self, apply: "operations_research::Solver::Action", refute: "operations_research::Solver::Action") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_Decision(self, apply, refute)
+
+    def Compose(self, dbs: "std::vector< operations_research::DecisionBuilder * > const &") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_Compose(self, dbs)
+
+    def Try(self, dbs: "std::vector< operations_research::DecisionBuilder * > const &") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_Try(self, dbs)
+
+    def DefaultPhase(self, *args) -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_DefaultPhase(self, *args)
+
+    def ScheduleOrPostpone(self, var: "IntervalVar", est: "int64_t", marker: "int64_t *const") -> "operations_research::Decision *":
+        r"""
+        Returns a decision that tries to schedule a task at a given time.
+        On the Apply branch, it will set that interval var as performed and set
+        its start to 'est'. On the Refute branch, it will just update the
+        'marker' to 'est' + 1. This decision is used in the
+        INTERVAL_SET_TIMES_FORWARD strategy.
+        """
+        return _pywrapcp.Solver_ScheduleOrPostpone(self, var, est, marker)
+
+    def ScheduleOrExpedite(self, var: "IntervalVar", est: "int64_t", marker: "int64_t *const") -> "operations_research::Decision *":
+        r"""
+        Returns a decision that tries to schedule a task at a given time.
+        On the Apply branch, it will set that interval var as performed and set
+        its end to 'est'. On the Refute branch, it will just update the
+        'marker' to 'est' - 1. This decision is used in the
+        INTERVAL_SET_TIMES_BACKWARD strategy.
+        """
+        return _pywrapcp.Solver_ScheduleOrExpedite(self, var, est, marker)
+
+    def RankFirstInterval(self, sequence: "SequenceVar", index: "int") -> "operations_research::Decision *":
+        r"""
+        Returns a decision that tries to rank first the ith interval var
+        in the sequence variable.
+        """
+        return _pywrapcp.Solver_RankFirstInterval(self, sequence, index)
+
+    def RankLastInterval(self, sequence: "SequenceVar", index: "int") -> "operations_research::Decision *":
+        r"""
+        Returns a decision that tries to rank last the ith interval var
+        in the sequence variable.
+        """
+        return _pywrapcp.Solver_RankLastInterval(self, sequence, index)
+
+    def Phase(self, *args) -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_Phase(self, *args)
+
+    def DecisionBuilderFromAssignment(self, assignment: "Assignment", db: "DecisionBuilder", vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::DecisionBuilder *":
+        r"""
+        Returns a decision builder for which the left-most leaf corresponds
+        to assignment, the rest of the tree being explored using 'db'.
+        """
+        return _pywrapcp.Solver_DecisionBuilderFromAssignment(self, assignment, db, vars)
+
+    def ConstraintAdder(self, ct: "Constraint") -> "operations_research::DecisionBuilder *":
+        r"""
+        Returns a decision builder that will add the given constraint to
+        the model.
+        """
+        return _pywrapcp.Solver_ConstraintAdder(self, ct)
+
+    def SolveOnce(self, db: "DecisionBuilder", monitors: "std::vector< operations_research::SearchMonitor * > const &") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_SolveOnce(self, db, monitors)
+
+    def NestedOptimize(self, *args) -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_NestedOptimize(self, *args)
+
+    def RestoreAssignment(self, assignment: "Assignment") -> "operations_research::DecisionBuilder *":
+        r"""
+        Returns a DecisionBuilder which restores an Assignment
+        (calls void Assignment::Restore())
+        """
+        return _pywrapcp.Solver_RestoreAssignment(self, assignment)
+
+    def StoreAssignment(self, assignment: "Assignment") -> "operations_research::DecisionBuilder *":
+        r"""
+        Returns a DecisionBuilder which stores an Assignment
+        (calls void Assignment::Store())
+        """
+        return _pywrapcp.Solver_StoreAssignment(self, assignment)
+
+    def Operator(self, *args) -> "operations_research::LocalSearchOperator *":
+        return _pywrapcp.Solver_Operator(self, *args)
+
+    def RandomLnsOperator(self, *args) -> "operations_research::LocalSearchOperator *":
+        return _pywrapcp.Solver_RandomLnsOperator(self, *args)
+
+    def MoveTowardTargetOperator(self, *args) -> "operations_research::LocalSearchOperator *":
+        r"""
+        *Overload 1:*
+        Creates a local search operator that tries to move the assignment of some
+        variables toward a target. The target is given as an Assignment. This
+        operator generates neighbors in which the only difference compared to the
+        current state is that one variable that belongs to the target assignment
+        is set to its target value.
+
+        |
+
+        *Overload 2:*
+        Creates a local search operator that tries to move the assignment of some
+        variables toward a target. The target is given either as two vectors: a
+        vector of variables and a vector of associated target values. The two
+        vectors should be of the same length. This operator generates neighbors in
+        which the only difference compared to the current state is that one
+        variable that belongs to the given vector is set to its target value.
+        """
+        return _pywrapcp.Solver_MoveTowardTargetOperator(self, *args)
+
+    def ConcatenateOperators(self, *args) -> "operations_research::LocalSearchOperator *":
+        return _pywrapcp.Solver_ConcatenateOperators(self, *args)
+
+    def RandomConcatenateOperators(self, *args) -> "operations_research::LocalSearchOperator *":
+        r"""
+        *Overload 1:*
+        Randomized version of local search concatenator; calls a random operator
+        at each call to MakeNextNeighbor().
+
+        |
+
+        *Overload 2:*
+        Randomized version of local search concatenator; calls a random operator
+        at each call to MakeNextNeighbor(). The provided seed is used to
+        initialize the random number generator.
+        """
+        return _pywrapcp.Solver_RandomConcatenateOperators(self, *args)
+
+    def NeighborhoodLimit(self, op: "LocalSearchOperator", limit: "int64_t") -> "operations_research::LocalSearchOperator *":
+        r"""
+        Creates a local search operator that wraps another local search
+        operator and limits the number of neighbors explored (i.e., calls
+        to MakeNextNeighbor from the current solution (between two calls
+        to Start()). When this limit is reached, MakeNextNeighbor()
+        returns false. The counter is cleared when Start() is called.
+        """
+        return _pywrapcp.Solver_NeighborhoodLimit(self, op, limit)
+
+    def LocalSearchPhase(self, *args) -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_LocalSearchPhase(self, *args)
+
+    def LocalSearchPhaseParameters(self, *args) -> "operations_research::LocalSearchPhaseParameters *":
+        return _pywrapcp.Solver_LocalSearchPhaseParameters(self, *args)
+
+    def SearchDepth(self) -> "int":
+        r"""
+        Gets the search depth of the current active search. Returns -1 if
+        there is no active search opened.
+        """
+        return _pywrapcp.Solver_SearchDepth(self)
+
+    def SearchLeftDepth(self) -> "int":
+        r"""
+        Gets the search left depth of the current active search. Returns -1 if
+        there is no active search opened.
+        """
+        return _pywrapcp.Solver_SearchLeftDepth(self)
+
+    def SolveDepth(self) -> "int":
+        r"""
+        Gets the number of nested searches. It returns 0 outside search,
+        1 during the top level search, 2 or more in case of nested searches.
+        """
+        return _pywrapcp.Solver_SolveDepth(self)
+
+    def Rand64(self, size: "int64_t") -> "int64_t":
+        r""" Returns a random value between 0 and 'size' - 1;"""
+        return _pywrapcp.Solver_Rand64(self, size)
+
+    def Rand32(self, size: "int32_t") -> "int32_t":
+        r""" Returns a random value between 0 and 'size' - 1;"""
+        return _pywrapcp.Solver_Rand32(self, size)
+
+    def ReSeed(self, seed: "int32_t") -> "void":
+        r""" Reseed the solver random generator."""
+        return _pywrapcp.Solver_ReSeed(self, seed)
+
+    def LocalSearchProfile(self) -> "std::string":
+        r""" Returns local search profiling information in a human readable format."""
+        return _pywrapcp.Solver_LocalSearchProfile(self)
+
+    def Constraints(self) -> "int":
+        r"""
+        Counts the number of constraints that have been added
+        to the solver before the search.
+        """
+        return _pywrapcp.Solver_Constraints(self)
+
+    def Accept(self, visitor: "operations_research::ModelVisitor *const") -> "void":
+        r""" Accepts the given model visitor."""
+        return _pywrapcp.Solver_Accept(self, visitor)
+
+    def FinishCurrentSearch(self) -> "void":
+        r""" Tells the solver to kill or restart the current search."""
+        return _pywrapcp.Solver_FinishCurrentSearch(self)
+
+    def RestartCurrentSearch(self) -> "void":
+        return _pywrapcp.Solver_RestartCurrentSearch(self)
+
+    def ShouldFail(self) -> "void":
+        r"""
+        These methods are only useful for the SWIG wrappers, which need a way
+        to externally cause the Solver to fail.
+        """
+        return _pywrapcp.Solver_ShouldFail(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.Solver___str__(self)
+
+    def Add(self, ct):
+      if isinstance(ct, PyConstraint):
+        self.__python_constraints.append(ct)
+      self.AddConstraint(ct)
+
+
+    def TreeNoCycle(self, nexts: "std::vector< operations_research::IntVar * > const &", active: "std::vector< operations_research::IntVar * > const &", callback: "operations_research::Solver::IndexFilter1"=0) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_TreeNoCycle(self, nexts, active, callback)
+
+    def SearchLogWithCallback(self, period: "int", callback: "std::function< std::string () >") -> "operations_research::SearchMonitor *":
+        return _pywrapcp.Solver_SearchLogWithCallback(self, period, callback)
+
+    def ElementFunction(self, values: "std::function< int64_t (int64_t) >", index: "IntVar") -> "operations_research::IntExpr *":
+        return _pywrapcp.Solver_ElementFunction(self, values, index)
+
+    def VarEvalValStrPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_evaluator: "std::function< int64_t (int64_t) >", val_str: "operations_research::Solver::IntValueStrategy") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarEvalValStrPhase(self, vars, var_evaluator, val_str)
+
+    def VarStrValEvalPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_str: "operations_research::Solver::IntVarStrategy", val_eval: "operations_research::Solver::IndexEvaluator2") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarStrValEvalPhase(self, vars, var_str, val_eval)
+
+    def VarEvalValEvalPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_eval: "std::function< int64_t (int64_t) >", val_eval: "operations_research::Solver::IndexEvaluator2") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarEvalValEvalPhase(self, vars, var_eval, val_eval)
+
+    def VarStrValEvalTieBreakPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_str: "operations_research::Solver::IntVarStrategy", val_eval: "operations_research::Solver::IndexEvaluator2", tie_breaker: "std::function< int64_t (int64_t) >") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarStrValEvalTieBreakPhase(self, vars, var_str, val_eval, tie_breaker)
+
+    def VarEvalValEvalTieBreakPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_eval: "std::function< int64_t (int64_t) >", val_eval: "operations_research::Solver::IndexEvaluator2", tie_breaker: "std::function< int64_t (int64_t) >") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarEvalValEvalTieBreakPhase(self, vars, var_eval, val_eval, tie_breaker)
+
+    def EvalEvalStrPhase(self, vars: "std::vector< operations_research::IntVar * > const &", evaluator: "operations_research::Solver::IndexEvaluator2", str: "operations_research::Solver::EvaluatorStrategy") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_EvalEvalStrPhase(self, vars, evaluator, str)
+
+    def EvalEvalStrTieBreakPhase(self, vars: "std::vector< operations_research::IntVar * > const &", evaluator: "operations_research::Solver::IndexEvaluator2", tie_breaker: "operations_research::Solver::IndexEvaluator1", str: "operations_research::Solver::EvaluatorStrategy") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_EvalEvalStrTieBreakPhase(self, vars, evaluator, tie_breaker, str)
+
+    def GuidedLocalSearch(self, *args) -> "operations_research::SearchMonitor *":
+        return _pywrapcp.Solver_GuidedLocalSearch(self, *args)
+
+    def SumObjectiveFilter(self, vars: "std::vector< operations_research::IntVar * > const &", values: "operations_research::Solver::IndexEvaluator2", filter_enum: "operations_research::Solver::LocalSearchFilterBound") -> "operations_research::LocalSearchFilter *":
+        return _pywrapcp.Solver_SumObjectiveFilter(self, vars, values, filter_enum)
+
+ +
+ +

Solver Class

+ +

A solver represents the main computation engine. It implements the entire +range of Constraint Programming protocols:

+ +
    +
  • Reversibility
  • +
  • Propagation
  • +
  • Search
  • +
+ +

Usually, Constraint Programming code consists of

+ +
    +
  • the creation of the Solver,
  • +
  • the creation of the decision variables of the model,
  • +
  • the creation of the constraints of the model and their addition to the +solver() through the AddConstraint() method,
  • +
  • the creation of the main DecisionBuilder class,
  • +
  • the launch of the solve() method with the decision builder.
  • +
+ +

For the time being, Solver is neither MT_SAFE nor MT_HOT.

+
+ + +
+
#   + + + Solver(*args) +
+ +
+ View Source +
    def __init__(self, *args):
+        _pywrapcp.Solver_swiginit(self, _pywrapcp.new_Solver(*args))
+
+        self.__python_constraints = []
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + INT_VAR_DEFAULT = 0 +
+ + +

The default behavior is CHOOSE_FIRST_UNBOUND.

+
+ + +
+
+
#   + + INT_VAR_SIMPLE = 1 +
+ + +

The simple selection is CHOOSE_FIRST_UNBOUND.

+
+ + +
+
+
#   + + CHOOSE_FIRST_UNBOUND = 2 +
+ + +

Select the first unbound variable. +Variables are considered in the order of the vector of IntVars used +to create the selector.

+
+ + +
+
+
#   + + CHOOSE_RANDOM = 3 +
+ + +

Randomly select one of the remaining unbound variables.

+
+ + +
+
+
#   + + CHOOSE_MIN_SIZE_LOWEST_MIN = 4 +
+ + +

Among unbound variables, select the variable with the smallest size, +i.e., the smallest number of possible values. +In case of a tie, the selected variables is the one with the lowest min +value. +In case of a tie, the first one is selected, first being defined by the +order in the vector of IntVars used to create the selector.

+
+ + +
+
+
#   + + CHOOSE_MIN_SIZE_HIGHEST_MIN = 5 +
+ + +

Among unbound variables, select the variable with the smallest size, +i.e., the smallest number of possible values. +In case of a tie, the selected variable is the one with the highest min +value. +In case of a tie, the first one is selected, first being defined by the +order in the vector of IntVars used to create the selector.

+
+ + +
+
+
#   + + CHOOSE_MIN_SIZE_LOWEST_MAX = 6 +
+ + +

Among unbound variables, select the variable with the smallest size, +i.e., the smallest number of possible values. +In case of a tie, the selected variables is the one with the lowest max +value. +In case of a tie, the first one is selected, first being defined by the +order in the vector of IntVars used to create the selector.

+
+ + +
+
+
#   + + CHOOSE_MIN_SIZE_HIGHEST_MAX = 7 +
+ + +

Among unbound variables, select the variable with the smallest size, +i.e., the smallest number of possible values. +In case of a tie, the selected variable is the one with the highest max +value. +In case of a tie, the first one is selected, first being defined by the +order in the vector of IntVars used to create the selector.

+
+ + +
+
+
#   + + CHOOSE_LOWEST_MIN = 8 +
+ + +

Among unbound variables, select the variable with the smallest minimal +value. +In case of a tie, the first one is selected, "first" defined by the +order in the vector of IntVars used to create the selector.

+
+ + +
+
+
#   + + CHOOSE_HIGHEST_MAX = 9 +
+ + +

Among unbound variables, select the variable with the highest maximal +value. +In case of a tie, the first one is selected, first being defined by the +order in the vector of IntVars used to create the selector.

+
+ + +
+
+
#   + + CHOOSE_MIN_SIZE = 10 +
+ + +

Among unbound variables, select the variable with the smallest size. +In case of a tie, the first one is selected, first being defined by the +order in the vector of IntVars used to create the selector.

+
+ + +
+
+
#   + + CHOOSE_MAX_SIZE = 11 +
+ + +

Among unbound variables, select the variable with the highest size. +In case of a tie, the first one is selected, first being defined by the +order in the vector of IntVars used to create the selector.

+
+ + +
+
+
#   + + CHOOSE_MAX_REGRET_ON_MIN = 12 +
+ + +

Among unbound variables, select the variable with the largest +gap between the first and the second values of the domain.

+
+ + +
+
+
#   + + CHOOSE_PATH = 13 +
+ + +

Selects the next unbound variable on a path, the path being defined by +the variables: var[i] corresponds to the index of the next of i.

+
+ + +
+
+
#   + + INT_VALUE_DEFAULT = 0 +
+ + +

The default behavior is ASSIGN_MIN_VALUE.

+
+ + +
+
+
#   + + INT_VALUE_SIMPLE = 1 +
+ + +

The simple selection is ASSIGN_MIN_VALUE.

+
+ + +
+
+
#   + + ASSIGN_MIN_VALUE = 2 +
+ + +

Selects the min value of the selected variable.

+
+ + +
+
+
#   + + ASSIGN_MAX_VALUE = 3 +
+ + +

Selects the max value of the selected variable.

+
+ + +
+
+
#   + + ASSIGN_RANDOM_VALUE = 4 +
+ + +

Selects randomly one of the possible values of the selected variable.

+
+ + +
+
+
#   + + ASSIGN_CENTER_VALUE = 5 +
+ + +

Selects the first possible value which is the closest to the center +of the domain of the selected variable. +The center is defined as (min + max) / 2.

+
+ + +
+
+
#   + + SPLIT_LOWER_HALF = 6 +
+ + +

Split the domain in two around the center, and choose the lower +part first.

+
+ + +
+
+
#   + + SPLIT_UPPER_HALF = 7 +
+ + +

Split the domain in two around the center, and choose the lower +part first.

+
+ + +
+
+
#   + + SEQUENCE_DEFAULT = 0 +
+ + + + +
+
+
#   + + SEQUENCE_SIMPLE = 1 +
+ + + + +
+
+
#   + + CHOOSE_MIN_SLACK_RANK_FORWARD = 2 +
+ + + + +
+
+
#   + + CHOOSE_RANDOM_RANK_FORWARD = 3 +
+ + + + +
+
+
#   + + INTERVAL_DEFAULT = 0 +
+ + +

The default is INTERVAL_SET_TIMES_FORWARD.

+
+ + +
+
+
#   + + INTERVAL_SIMPLE = 1 +
+ + +

The simple is INTERVAL_SET_TIMES_FORWARD.

+
+ + +
+
+
#   + + INTERVAL_SET_TIMES_FORWARD = 2 +
+ + +

Selects the variable with the lowest starting time of all variables, +and fixes its starting time to this lowest value.

+
+ + +
+
+
#   + + INTERVAL_SET_TIMES_BACKWARD = 3 +
+ + +

Selects the variable with the highest ending time of all variables, +and fixes the ending time to this highest values.

+
+ + +
+
+
#   + + TWOOPT = 0 +
+ + +

Operator which reverses a sub-chain of a path. It is called TwoOpt +because it breaks two arcs on the path; resulting paths are called +two-optimal. +Possible neighbors for the path 1 -> 2 -> 3 -> 4 -> 5 +(where (1, 5) are first and last nodes of the path and can therefore not +be moved): + 1 -> [3 -> 2] -> 4 -> 5 + 1 -> [4 -> 3 -> 2] -> 5 + 1 -> 2 -> [4 -> 3] -> 5

+
+ + +
+
+
#   + + OROPT = 1 +
+ + +

Relocate: OROPT and RELOCATE. +Operator which moves a sub-chain of a path to another position; the +specified chain length is the fixed length of the chains being moved. +When this length is 1, the operator simply moves a node to another +position. +Possible neighbors for the path 1 -> 2 -> 3 -> 4 -> 5, for a chain +length of 2 (where (1, 5) are first and last nodes of the path and can +therefore not be moved): + 1 -> 4 -> [2 -> 3] -> 5 + 1 -> [3 -> 4] -> 2 -> 5

+ +

Using Relocate with chain lengths of 1, 2 and 3 together is equivalent +to the OrOpt operator on a path. The OrOpt operator is a limited + version of 3Opt (breaks 3 arcs on a path).

+
+ + +
+
+
#   + + RELOCATE = 2 +
+ + +

Relocate neighborhood with length of 1 (see OROPT comment).

+
+ + +
+
+
#   + + EXCHANGE = 3 +
+ + +

Operator which exchanges the positions of two nodes. +Possible neighbors for the path 1 -> 2 -> 3 -> 4 -> 5 +(where (1, 5) are first and last nodes of the path and can therefore not +be moved): + 1 -> [3] -> [2] -> 4 -> 5 + 1 -> [4] -> 3 -> [2] -> 5 + 1 -> 2 -> [4] -> [3] -> 5

+
+ + +
+
+
#   + + CROSS = 4 +
+ + +

Operator which cross exchanges the starting chains of 2 paths, including +exchanging the whole paths. +First and last nodes are not moved. +Possible neighbors for the paths 1 -> 2 -> 3 -> 4 -> 5 and 6 -> 7 -> 8 +(where (1, 5) and (6, 8) are first and last nodes of the paths and can +therefore not be moved): + 1 -> [7] -> 3 -> 4 -> 5 6 -> [2] -> 8 + 1 -> [7] -> 4 -> 5 6 -> [2 -> 3] -> 8 + 1 -> [7] -> 5 6 -> [2 -> 3 -> 4] -> 8

+
+ + +
+
+
#   + + MAKEACTIVE = 5 +
+ + +

Operator which inserts an inactive node into a path. +Possible neighbors for the path 1 -> 2 -> 3 -> 4 with 5 inactive +(where 1 and 4 are first and last nodes of the path) are: + 1 -> [5] -> 2 -> 3 -> 4 + 1 -> 2 -> [5] -> 3 -> 4 + 1 -> 2 -> 3 -> [5] -> 4

+
+ + +
+
+
#   + + MAKEINACTIVE = 6 +
+ + +

Operator which makes path nodes inactive. +Possible neighbors for the path 1 -> 2 -> 3 -> 4 (where 1 and 4 are +first and last nodes of the path) are: + 1 -> 3 -> 4 with 2 inactive + 1 -> 2 -> 4 with 3 inactive

+
+ + +
+
+
#   + + MAKECHAININACTIVE = 7 +
+ + +

Operator which makes a "chain" of path nodes inactive. +Possible neighbors for the path 1 -> 2 -> 3 -> 4 (where 1 and 4 are +first and last nodes of the path) are: + 1 -> 3 -> 4 with 2 inactive + 1 -> 2 -> 4 with 3 inactive + 1 -> 4 with 2 and 3 inactive

+
+ + +
+
+
#   + + SWAPACTIVE = 8 +
+ + +

Operator which replaces an active node by an inactive one. +Possible neighbors for the path 1 -> 2 -> 3 -> 4 with 5 inactive +(where 1 and 4 are first and last nodes of the path) are: + 1 -> [5] -> 3 -> 4 with 2 inactive + 1 -> 2 -> [5] -> 4 with 3 inactive

+
+ + +
+
+
#   + + EXTENDEDSWAPACTIVE = 9 +
+ + +

Operator which makes an inactive node active and an active one inactive. +It is similar to SwapActiveOperator except that it tries to insert the +inactive node in all possible positions instead of just the position of +the node made inactive. +Possible neighbors for the path 1 -> 2 -> 3 -> 4 with 5 inactive +(where 1 and 4 are first and last nodes of the path) are: + 1 -> [5] -> 3 -> 4 with 2 inactive + 1 -> 3 -> [5] -> 4 with 2 inactive + 1 -> [5] -> 2 -> 4 with 3 inactive + 1 -> 2 -> [5] -> 4 with 3 inactive

+
+ + +
+
+
#   + + PATHLNS = 10 +
+ + +

Operator which relaxes two sub-chains of three consecutive arcs each. +Each sub-chain is defined by a start node and the next three arcs. Those +six arcs are relaxed to build a new neighbor. +PATHLNS explores all possible pairs of starting nodes and so defines +n^2 neighbors, n being the number of nodes. +Note that the two sub-chains can be part of the same path; they even may +overlap.

+
+ + +
+
+
#   + + FULLPATHLNS = 11 +
+ + +

Operator which relaxes one entire path and all inactive nodes, thus +defining num_paths neighbors.

+
+ + +
+
+
#   + + UNACTIVELNS = 12 +
+ + +

Operator which relaxes all inactive nodes and one sub-chain of six +consecutive arcs. That way the path can be improved by inserting +inactive nodes or swapping arcs.

+
+ + +
+
+
#   + + INCREMENT = 13 +
+ + +

Operator which defines one neighbor per variable. Each neighbor tries to +increment by one the value of the corresponding variable. When a new +solution is found the neighborhood is rebuilt from scratch, i.e., tries +to increment values in the variable order. +Consider for instance variables x and y. x is incremented one by one to +its max, and when it is not possible to increment x anymore, y is +incremented once. If this is a solution, then next neighbor tries to +increment x.

+
+ + +
+
+
#   + + DECREMENT = 14 +
+ + +

Operator which defines a neighborhood to decrement values. +The behavior is the same as INCREMENT, except values are decremented +instead of incremented.

+
+ + +
+
+
#   + + SIMPLELNS = 15 +
+ + +

Operator which defines one neighbor per variable. Each neighbor relaxes +one variable. +When a new solution is found the neighborhood is rebuilt from scratch. +Consider for instance variables x and y. First x is relaxed and the +solver is looking for the best possible solution (with only x relaxed). +Then y is relaxed, and the solver is looking for a new solution. +If a new solution is found, then the next variable to be relaxed is x.

+
+ + +
+
+
#   + + GE = 0 +
+ + +

Move is accepted when the current objective value >= objective.Min.

+
+ + +
+
+
#   + + LE = 1 +
+ + +

Move is accepted when the current objective value <= objective.Max.

+
+ + +
+
+
#   + + EQ = 2 +
+ + +

Move is accepted when the current objective value is in the interval +objective.Min .. objective.Max.

+
+ + +
+
+
#   + + DELAYED_PRIORITY = 0 +
+ + +

DELAYED_PRIORITY is the lowest priority: Demons will be processed after +VAR_PRIORITY and NORMAL_PRIORITY demons.

+
+ + +
+
+
#   + + VAR_PRIORITY = 1 +
+ + +

VAR_PRIORITY is between DELAYED_PRIORITY and NORMAL_PRIORITY.

+
+ + +
+
+
#   + + NORMAL_PRIORITY = 2 +
+ + +

NORMAL_PRIORITY is the highest priority: Demons will be processed first.

+
+ + +
+
+
#   + + + def + Parameters(self) -> 'operations_research::ConstraintSolverParameters': +
+ +
+ View Source +
    def Parameters(self) -> "operations_research::ConstraintSolverParameters":
+        r""" Stored Parameters."""
+        return _pywrapcp.Solver_Parameters(self)
+
+ +
+ +

Stored Parameters.

+
+ + +
+
+
#   + +
@staticmethod
+ + def + DefaultSolverParameters() -> 'operations_research::ConstraintSolverParameters': +
+ +
+ View Source +
    @staticmethod
+    def DefaultSolverParameters() -> "operations_research::ConstraintSolverParameters":
+        r""" Create a ConstraintSolverParameters proto with all the default values."""
+        return _pywrapcp.Solver_DefaultSolverParameters()
+
+ +
+ +

Create a ConstraintSolverParameters proto with all the default values.

+
+ + +
+
+
#   + + + def + AddConstraint(self, c: ortools.constraint_solver.pywrapcp.Constraint) -> 'void': +
+ +
+ View Source +
    def AddConstraint(self, c: "Constraint") -> "void":
+        r"""
+        Adds the constraint 'c' to the model.
+
+        After calling this method, and until there is a backtrack that undoes the
+        addition, any assignment of variables to values must satisfy the given
+        constraint in order to be considered feasible. There are two fairly
+        different use cases:
+
+        - the most common use case is modeling: the given constraint is really
+        part of the problem that the user is trying to solve. In this use case,
+        AddConstraint is called outside of search (i.e., with state() ==
+        OUTSIDE_SEARCH). Most users should only use AddConstraint in this
+        way. In this case, the constraint will belong to the model forever: it
+        cannot not be removed by backtracking.
+
+        - a rarer use case is that 'c' is not a real constraint of the model. It
+        may be a constraint generated by a branching decision (a constraint whose
+        goal is to restrict the search space), a symmetry breaking constraint (a
+        constraint that does restrict the search space, but in a way that cannot
+        have an impact on the quality of the solutions in the subtree), or an
+        inferred constraint that, while having no semantic value to the model (it
+        does not restrict the set of solutions), is worth having because we
+        believe it may strengthen the propagation. In these cases, it happens
+        that the constraint is added during the search (i.e., with state() ==
+        IN_SEARCH or state() == IN_ROOT_NODE). When a constraint is
+        added during a search, it applies only to the subtree of the search tree
+        rooted at the current node, and will be automatically removed by
+        backtracking.
+
+        This method does not take ownership of the constraint. If the constraint
+        has been created by any factory method (Solver::MakeXXX), it will
+        automatically be deleted. However, power users who implement their own
+        constraints should do: solver.AddConstraint(solver.RevAlloc(new
+        MyConstraint(...));
+        """
+        return _pywrapcp.Solver_AddConstraint(self, c)
+
+ +
+ +

Adds the constraint 'c' to the model.

+ +

After calling this method, and until there is a backtrack that undoes the +addition, any assignment of variables to values must satisfy the given +constraint in order to be considered feasible. There are two fairly +different use cases:

+ +
    +
  • the most common use case is modeling: the given constraint is really +part of the problem that the user is trying to solve. In this use case, +AddConstraint is called outside of search (i.e., with state() == +OUTSIDE_SEARCH). Most users should only use AddConstraint in this +way. In this case, the constraint will belong to the model forever: it +cannot not be removed by backtracking.

  • +
  • a rarer use case is that 'c' is not a real constraint of the model. It +may be a constraint generated by a branching decision (a constraint whose +goal is to restrict the search space), a symmetry breaking constraint (a +constraint that does restrict the search space, but in a way that cannot +have an impact on the quality of the solutions in the subtree), or an +inferred constraint that, while having no semantic value to the model (it +does not restrict the set of solutions), is worth having because we +believe it may strengthen the propagation. In these cases, it happens +that the constraint is added during the search (i.e., with state() == +IN_SEARCH or state() == IN_ROOT_NODE). When a constraint is +added during a search, it applies only to the subtree of the search tree +rooted at the current node, and will be automatically removed by +backtracking.

  • +
+ +

This method does not take ownership of the constraint. If the constraint +has been created by any factory method (Solver::MakeXXX), it will +automatically be deleted. However, power users who implement their own +constraints should do: solver.AddConstraint(solver.RevAlloc(new +MyConstraint(...));

+
+ + +
+
+
#   + + + def + Solve(self, *args) -> bool: +
+ +
+ View Source +
    def Solve(self, *args) -> "bool":
+        return _pywrapcp.Solver_Solve(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + NewSearch(self, *args) -> 'void': +
+ +
+ View Source +
    def NewSearch(self, *args) -> "void":
+        return _pywrapcp.Solver_NewSearch(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + NextSolution(self) -> bool: +
+ +
+ View Source +
    def NextSolution(self) -> "bool":
+        return _pywrapcp.Solver_NextSolution(self)
+
+ +
+ + + +
+
+
#   + + + def + RestartSearch(self) -> 'void': +
+ +
+ View Source +
    def RestartSearch(self) -> "void":
+        return _pywrapcp.Solver_RestartSearch(self)
+
+ +
+ + + +
+
+
#   + + + def + EndSearch(self) -> 'void': +
+ +
+ View Source +
    def EndSearch(self) -> "void":
+        return _pywrapcp.Solver_EndSearch(self)
+
+ +
+ + + +
+
+
#   + + + def + SolveAndCommit(self, *args) -> bool: +
+ +
+ View Source +
    def SolveAndCommit(self, *args) -> "bool":
+        return _pywrapcp.Solver_SolveAndCommit(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + CheckAssignment( + self, + solution: ortools.constraint_solver.pywrapcp.Assignment +) -> bool: +
+ +
+ View Source +
    def CheckAssignment(self, solution: "Assignment") -> "bool":
+        r""" Checks whether the given assignment satisfies all relevant constraints."""
+        return _pywrapcp.Solver_CheckAssignment(self, solution)
+
+ +
+ +

Checks whether the given assignment satisfies all relevant constraints.

+
+ + +
+
+
#   + + + def + CheckConstraint(self, ct: ortools.constraint_solver.pywrapcp.Constraint) -> bool: +
+ +
+ View Source +
    def CheckConstraint(self, ct: "Constraint") -> "bool":
+        r"""
+        Checks whether adding this constraint will lead to an immediate
+        failure. It will return false if the model is already inconsistent, or if
+        adding the constraint makes it inconsistent.
+        """
+        return _pywrapcp.Solver_CheckConstraint(self, ct)
+
+ +
+ +

Checks whether adding this constraint will lead to an immediate +failure. It will return false if the model is already inconsistent, or if +adding the constraint makes it inconsistent.

+
+ + +
+
+
#   + + + def + Fail(self) -> 'void': +
+ +
+ View Source +
    def Fail(self) -> "void":
+        r""" Abandon the current branch in the search tree. A backtrack will follow."""
+        return _pywrapcp.Solver_Fail(self)
+
+ +
+ +

Abandon the current branch in the search tree. A backtrack will follow.

+
+ + +
+
+
#   + +
@staticmethod
+ + def + MemoryUsage() -> 'int64_t': +
+ +
+ View Source +
    @staticmethod
+    def MemoryUsage() -> "int64_t":
+        r""" Current memory usage in bytes"""
+        return _pywrapcp.Solver_MemoryUsage()
+
+ +
+ +

Current memory usage in bytes

+
+ + +
+
+
#   + + + def + WallTime(self) -> 'int64_t': +
+ +
+ View Source +
    def WallTime(self) -> "int64_t":
+        r"""
+        DEPRECATED: Use Now() instead.
+        Time elapsed, in ms since the creation of the solver.
+        """
+        return _pywrapcp.Solver_WallTime(self)
+
+ +
+ +

DEPRECATED: Use Now() instead. +Time elapsed, in ms since the creation of the solver.

+
+ + +
+
+
#   + + + def + Branches(self) -> 'int64_t': +
+ +
+ View Source +
    def Branches(self) -> "int64_t":
+        r""" The number of branches explored since the creation of the solver."""
+        return _pywrapcp.Solver_Branches(self)
+
+ +
+ +

The number of branches explored since the creation of the solver.

+
+ + +
+
+
#   + + + def + Solutions(self) -> 'int64_t': +
+ +
+ View Source +
    def Solutions(self) -> "int64_t":
+        r""" The number of solutions found since the start of the search."""
+        return _pywrapcp.Solver_Solutions(self)
+
+ +
+ +

The number of solutions found since the start of the search.

+
+ + +
+
+
#   + + + def + Failures(self) -> 'int64_t': +
+ +
+ View Source +
    def Failures(self) -> "int64_t":
+        r""" The number of failures encountered since the creation of the solver."""
+        return _pywrapcp.Solver_Failures(self)
+
+ +
+ +

The number of failures encountered since the creation of the solver.

+
+ + +
+
+
#   + + + def + AcceptedNeighbors(self) -> 'int64_t': +
+ +
+ View Source +
    def AcceptedNeighbors(self) -> "int64_t":
+        r""" The number of accepted neighbors."""
+        return _pywrapcp.Solver_AcceptedNeighbors(self)
+
+ +
+ +

The number of accepted neighbors.

+
+ + +
+
+
#   + + + def + Stamp(self) -> 'uint64_t': +
+ +
+ View Source +
    def Stamp(self) -> "uint64_t":
+        r"""
+        The stamp indicates how many moves in the search tree we have performed.
+        It is useful to detect if we need to update same lazy structures.
+        """
+        return _pywrapcp.Solver_Stamp(self)
+
+ +
+ +

The stamp indicates how many moves in the search tree we have performed. +It is useful to detect if we need to update same lazy structures.

+
+ + +
+
+
#   + + + def + FailStamp(self) -> 'uint64_t': +
+ +
+ View Source +
    def FailStamp(self) -> "uint64_t":
+        r""" The fail_stamp() is incremented after each backtrack."""
+        return _pywrapcp.Solver_FailStamp(self)
+
+ +
+ +

The fail_stamp() is incremented after each backtrack.

+
+ + +
+
+
#   + + + def + IntVar(self, *args) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IntVar(self, *args) -> "operations_research::IntVar *":
+        r"""
+        *Overload 1:*
+        MakeIntVar will create the best range based int var for the bounds given.
+
+        |
+
+        *Overload 2:*
+        MakeIntVar will create a variable with the given sparse domain.
+
+        |
+
+        *Overload 3:*
+        MakeIntVar will create a variable with the given sparse domain.
+
+        |
+
+        *Overload 4:*
+        MakeIntVar will create the best range based int var for the bounds given.
+
+        |
+
+        *Overload 5:*
+        MakeIntVar will create a variable with the given sparse domain.
+
+        |
+
+        *Overload 6:*
+        MakeIntVar will create a variable with the given sparse domain.
+        """
+        return _pywrapcp.Solver_IntVar(self, *args)
+
+ +
+ +

Overload 1: +MakeIntVar will create the best range based int var for the bounds given.

+ +

|

+ +

Overload 2: +MakeIntVar will create a variable with the given sparse domain.

+ +

|

+ +

Overload 3: +MakeIntVar will create a variable with the given sparse domain.

+ +

|

+ +

Overload 4: +MakeIntVar will create the best range based int var for the bounds given.

+ +

|

+ +

Overload 5: +MakeIntVar will create a variable with the given sparse domain.

+ +

|

+ +

Overload 6: +MakeIntVar will create a variable with the given sparse domain.

+
+ + +
+
+
#   + + + def + BoolVar(self, *args) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def BoolVar(self, *args) -> "operations_research::IntVar *":
+        r"""
+        *Overload 1:*
+        MakeBoolVar will create a variable with a {0, 1} domain.
+
+        |
+
+        *Overload 2:*
+        MakeBoolVar will create a variable with a {0, 1} domain.
+        """
+        return _pywrapcp.Solver_BoolVar(self, *args)
+
+ +
+ +

Overload 1: +MakeBoolVar will create a variable with a {0, 1} domain.

+ +

|

+ +

Overload 2: +MakeBoolVar will create a variable with a {0, 1} domain.

+
+ + +
+
+
#   + + + def + IntConst(self, *args) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IntConst(self, *args) -> "operations_research::IntVar *":
+        r"""
+        *Overload 1:*
+        IntConst will create a constant expression.
+
+        |
+
+        *Overload 2:*
+        IntConst will create a constant expression.
+        """
+        return _pywrapcp.Solver_IntConst(self, *args)
+
+ +
+ +

Overload 1: +IntConst will create a constant expression.

+ +

|

+ +

Overload 2: +IntConst will create a constant expression.

+
+ + +
+
+
#   + + + def + Sum( + self, + vars: 'std::vector< operations_research::IntVar * > const &' +) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def Sum(self, vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::IntExpr *":
+        r""" sum of all vars."""
+        return _pywrapcp.Solver_Sum(self, vars)
+
+ +
+ +

sum of all vars.

+
+ + +
+
+
#   + + + def + ScalProd(self, *args) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def ScalProd(self, *args) -> "operations_research::IntExpr *":
+        r"""
+        *Overload 1:*
+        scalar product
+
+        |
+
+        *Overload 2:*
+        scalar product
+        """
+        return _pywrapcp.Solver_ScalProd(self, *args)
+
+ +
+ +

Overload 1: +scalar product

+ +

|

+ +

Overload 2: +scalar product

+
+ + +
+
+
#   + + + def + MonotonicElement( + self, + values: 'operations_research::Solver::IndexEvaluator1', + increasing: bool, + index: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def MonotonicElement(self, values: "operations_research::Solver::IndexEvaluator1", increasing: "bool", index: "IntVar") -> "operations_research::IntExpr *":
+        r"""
+        Function based element. The constraint takes ownership of the
+        callback.  The callback must be monotonic. It must be able to
+        cope with any possible value in the domain of 'index'
+        (potentially negative ones too). Furtermore, monotonicity is not
+        checked. Thus giving a non-monotonic function, or specifying an
+        incorrect increasing parameter will result in undefined behavior.
+        """
+        return _pywrapcp.Solver_MonotonicElement(self, values, increasing, index)
+
+ +
+ +

Function based element. The constraint takes ownership of the +callback. The callback must be monotonic. It must be able to +cope with any possible value in the domain of 'index' +(potentially negative ones too). Furtermore, monotonicity is not +checked. Thus giving a non-monotonic function, or specifying an +incorrect increasing parameter will result in undefined behavior.

+
+ + +
+
+
#   + + + def + Element(self, *args) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def Element(self, *args) -> "operations_research::IntExpr *":
+        r"""
+        *Overload 1:*
+        values[index]
+
+        |
+
+        *Overload 2:*
+        values[index]
+
+        |
+
+        *Overload 3:*
+        Function-based element. The constraint takes ownership of the
+        callback. The callback must be able to cope with any possible
+        value in the domain of 'index' (potentially negative ones too).
+
+        |
+
+        *Overload 4:*
+        2D version of function-based element expression, values(expr1, expr2).
+
+        |
+
+        *Overload 5:*
+        vars[expr]
+        """
+        return _pywrapcp.Solver_Element(self, *args)
+
+ +
+ +

Overload 1: +values[index]

+ +

|

+ +

Overload 2: +values[index]

+ +

|

+ +

Overload 3: +Function-based element. The constraint takes ownership of the +callback. The callback must be able to cope with any possible +value in the domain of 'index' (potentially negative ones too).

+ +

|

+ +

Overload 4: +2D version of function-based element expression, values(expr1, expr2).

+ +

|

+ +

Overload 5: +vars[expr]

+
+ + +
+
+
#   + + + def + IndexExpression( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + value: 'int64_t' +) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def IndexExpression(self, vars: "std::vector< operations_research::IntVar * > const &", value: "int64_t") -> "operations_research::IntExpr *":
+        r"""
+        Returns the expression expr such that vars[expr] == value.
+        It assumes that vars are all different.
+        """
+        return _pywrapcp.Solver_IndexExpression(self, vars, value)
+
+ +
+ +

Returns the expression expr such that vars[expr] == value. +It assumes that vars are all different.

+
+ + +
+
+
#   + + + def + Min(self, *args) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def Min(self, *args) -> "operations_research::IntExpr *":
+        r"""
+        *Overload 1:*
+        std::min(vars)
+
+        |
+
+        *Overload 2:*
+        std::min (left, right)
+
+        |
+
+        *Overload 3:*
+        std::min(expr, value)
+
+        |
+
+        *Overload 4:*
+        std::min(expr, value)
+        """
+        return _pywrapcp.Solver_Min(self, *args)
+
+ +
+ +

Overload 1: +std::min(vars)

+ +

|

+ +

Overload 2: +std::min (left, right)

+ +

|

+ +

Overload 3: +std::min(expr, value)

+ +

|

+ +

Overload 4: +std::min(expr, value)

+
+ + +
+
+
#   + + + def + Max(self, *args) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def Max(self, *args) -> "operations_research::IntExpr *":
+        r"""
+        *Overload 1:*
+        std::max(vars)
+
+        |
+
+        *Overload 2:*
+        std::max(left, right)
+
+        |
+
+        *Overload 3:*
+        std::max(expr, value)
+
+        |
+
+        *Overload 4:*
+        std::max(expr, value)
+        """
+        return _pywrapcp.Solver_Max(self, *args)
+
+ +
+ +

Overload 1: +std::max(vars)

+ +

|

+ +

Overload 2: +std::max(left, right)

+ +

|

+ +

Overload 3: +std::max(expr, value)

+ +

|

+ +

Overload 4: +std::max(expr, value)

+
+ + +
+
+
#   + + + def + ConvexPiecewiseExpr( + self, + expr: ortools.constraint_solver.pywrapcp.IntExpr, + early_cost: 'int64_t', + early_date: 'int64_t', + late_date: 'int64_t', + late_cost: 'int64_t' +) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def ConvexPiecewiseExpr(self, expr: "IntExpr", early_cost: "int64_t", early_date: "int64_t", late_date: "int64_t", late_cost: "int64_t") -> "operations_research::IntExpr *":
+        r""" Convex piecewise function."""
+        return _pywrapcp.Solver_ConvexPiecewiseExpr(self, expr, early_cost, early_date, late_date, late_cost)
+
+ +
+ +

Convex piecewise function.

+
+ + +
+
+
#   + + + def + SemiContinuousExpr( + self, + expr: ortools.constraint_solver.pywrapcp.IntExpr, + fixed_charge: 'int64_t', + step: 'int64_t' +) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def SemiContinuousExpr(self, expr: "IntExpr", fixed_charge: "int64_t", step: "int64_t") -> "operations_research::IntExpr *":
+        r"""
+        Semi continuous Expression (x <= 0 -> f(x) = 0; x > 0 -> f(x) = ax + b)
+        a >= 0 and b >= 0
+        """
+        return _pywrapcp.Solver_SemiContinuousExpr(self, expr, fixed_charge, step)
+
+ +
+ +

Semi continuous Expression (x <= 0 -> f(x) = 0; x > 0 -> f(x) = ax + b) +a >= 0 and b >= 0

+
+ + +
+
+
#   + + + def + ConditionalExpression( + self, + condition: ortools.constraint_solver.pywrapcp.IntVar, + expr: ortools.constraint_solver.pywrapcp.IntExpr, + unperformed_value: 'int64_t' +) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def ConditionalExpression(self, condition: "IntVar", expr: "IntExpr", unperformed_value: "int64_t") -> "operations_research::IntExpr *":
+        r""" Conditional Expr condition ? expr : unperformed_value"""
+        return _pywrapcp.Solver_ConditionalExpression(self, condition, expr, unperformed_value)
+
+ +
+ +

Conditional Expr condition ? expr : unperformed_value

+
+ + +
+
+
#   + + + def + TrueConstraint(self) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def TrueConstraint(self) -> "operations_research::Constraint *":
+        r""" This constraint always succeeds."""
+        return _pywrapcp.Solver_TrueConstraint(self)
+
+ +
+ +

This constraint always succeeds.

+
+ + +
+
+
#   + + + def + FalseConstraint(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def FalseConstraint(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_FalseConstraint(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + IsEqualCstCt( + self, + var: ortools.constraint_solver.pywrapcp.IntExpr, + value: 'int64_t', + boolvar: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IsEqualCstCt(self, var: "IntExpr", value: "int64_t", boolvar: "IntVar") -> "operations_research::Constraint *":
+        r""" boolvar == (var == value)"""
+        return _pywrapcp.Solver_IsEqualCstCt(self, var, value, boolvar)
+
+ +
+ +

boolvar == (var == value)

+
+ + +
+
+
#   + + + def + IsEqualCstVar( + self, + var: ortools.constraint_solver.pywrapcp.IntExpr, + value: 'int64_t' +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsEqualCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var == value)"""
+        return _pywrapcp.Solver_IsEqualCstVar(self, var, value)
+
+ +
+ +

status var of (var == value)

+
+ + +
+
+
#   + + + def + IsEqualCt( + self, + v1: ortools.constraint_solver.pywrapcp.IntExpr, + v2: ortools.constraint_solver.pywrapcp.IntExpr, + b: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IsEqualCt(self, v1: "IntExpr", v2: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (v1 == v2)"""
+        return _pywrapcp.Solver_IsEqualCt(self, v1, v2, b)
+
+ +
+ +

b == (v1 == v2)

+
+ + +
+
+
#   + + + def + IsEqualVar( + self, + v1: ortools.constraint_solver.pywrapcp.IntExpr, + v2: ortools.constraint_solver.pywrapcp.IntExpr +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsEqualVar(self, v1: "IntExpr", v2: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (v1 == v2)"""
+        return _pywrapcp.Solver_IsEqualVar(self, v1, v2)
+
+ +
+ +

status var of (v1 == v2)

+
+ + +
+
+
#   + + + def + IsDifferentCstCt( + self, + var: ortools.constraint_solver.pywrapcp.IntExpr, + value: 'int64_t', + boolvar: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IsDifferentCstCt(self, var: "IntExpr", value: "int64_t", boolvar: "IntVar") -> "operations_research::Constraint *":
+        r""" boolvar == (var != value)"""
+        return _pywrapcp.Solver_IsDifferentCstCt(self, var, value, boolvar)
+
+ +
+ +

boolvar == (var != value)

+
+ + +
+
+
#   + + + def + IsDifferentCstVar( + self, + var: ortools.constraint_solver.pywrapcp.IntExpr, + value: 'int64_t' +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsDifferentCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var != value)"""
+        return _pywrapcp.Solver_IsDifferentCstVar(self, var, value)
+
+ +
+ +

status var of (var != value)

+
+ + +
+
+
#   + + + def + IsDifferentVar( + self, + v1: ortools.constraint_solver.pywrapcp.IntExpr, + v2: ortools.constraint_solver.pywrapcp.IntExpr +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsDifferentVar(self, v1: "IntExpr", v2: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (v1 != v2)"""
+        return _pywrapcp.Solver_IsDifferentVar(self, v1, v2)
+
+ +
+ +

status var of (v1 != v2)

+
+ + +
+
+
#   + + + def + IsDifferentCt( + self, + v1: ortools.constraint_solver.pywrapcp.IntExpr, + v2: ortools.constraint_solver.pywrapcp.IntExpr, + b: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IsDifferentCt(self, v1: "IntExpr", v2: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (v1 != v2)"""
+        return _pywrapcp.Solver_IsDifferentCt(self, v1, v2, b)
+
+ +
+ +

b == (v1 != v2)

+
+ + +
+
+
#   + + + def + IsLessOrEqualCstCt( + self, + var: ortools.constraint_solver.pywrapcp.IntExpr, + value: 'int64_t', + boolvar: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IsLessOrEqualCstCt(self, var: "IntExpr", value: "int64_t", boolvar: "IntVar") -> "operations_research::Constraint *":
+        r""" boolvar == (var <= value)"""
+        return _pywrapcp.Solver_IsLessOrEqualCstCt(self, var, value, boolvar)
+
+ +
+ +

boolvar == (var <= value)

+
+ + +
+
+
#   + + + def + IsLessOrEqualCstVar( + self, + var: ortools.constraint_solver.pywrapcp.IntExpr, + value: 'int64_t' +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsLessOrEqualCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var <= value)"""
+        return _pywrapcp.Solver_IsLessOrEqualCstVar(self, var, value)
+
+ +
+ +

status var of (var <= value)

+
+ + +
+
+
#   + + + def + IsLessOrEqualVar( + self, + left: ortools.constraint_solver.pywrapcp.IntExpr, + right: ortools.constraint_solver.pywrapcp.IntExpr +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsLessOrEqualVar(self, left: "IntExpr", right: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (left <= right)"""
+        return _pywrapcp.Solver_IsLessOrEqualVar(self, left, right)
+
+ +
+ +

status var of (left <= right)

+
+ + +
+
+
#   + + + def + IsLessOrEqualCt( + self, + left: ortools.constraint_solver.pywrapcp.IntExpr, + right: ortools.constraint_solver.pywrapcp.IntExpr, + b: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IsLessOrEqualCt(self, left: "IntExpr", right: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (left <= right)"""
+        return _pywrapcp.Solver_IsLessOrEqualCt(self, left, right, b)
+
+ +
+ +

b == (left <= right)

+
+ + +
+
+
#   + + + def + IsGreaterOrEqualCstCt( + self, + var: ortools.constraint_solver.pywrapcp.IntExpr, + value: 'int64_t', + boolvar: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IsGreaterOrEqualCstCt(self, var: "IntExpr", value: "int64_t", boolvar: "IntVar") -> "operations_research::Constraint *":
+        r""" boolvar == (var >= value)"""
+        return _pywrapcp.Solver_IsGreaterOrEqualCstCt(self, var, value, boolvar)
+
+ +
+ +

boolvar == (var >= value)

+
+ + +
+
+
#   + + + def + IsGreaterOrEqualCstVar( + self, + var: ortools.constraint_solver.pywrapcp.IntExpr, + value: 'int64_t' +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsGreaterOrEqualCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var >= value)"""
+        return _pywrapcp.Solver_IsGreaterOrEqualCstVar(self, var, value)
+
+ +
+ +

status var of (var >= value)

+
+ + +
+
+
#   + + + def + IsGreaterOrEqualVar( + self, + left: ortools.constraint_solver.pywrapcp.IntExpr, + right: ortools.constraint_solver.pywrapcp.IntExpr +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsGreaterOrEqualVar(self, left: "IntExpr", right: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (left >= right)"""
+        return _pywrapcp.Solver_IsGreaterOrEqualVar(self, left, right)
+
+ +
+ +

status var of (left >= right)

+
+ + +
+
+
#   + + + def + IsGreaterOrEqualCt( + self, + left: ortools.constraint_solver.pywrapcp.IntExpr, + right: ortools.constraint_solver.pywrapcp.IntExpr, + b: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IsGreaterOrEqualCt(self, left: "IntExpr", right: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (left >= right)"""
+        return _pywrapcp.Solver_IsGreaterOrEqualCt(self, left, right, b)
+
+ +
+ +

b == (left >= right)

+
+ + +
+
+
#   + + + def + IsGreaterCstCt( + self, + v: ortools.constraint_solver.pywrapcp.IntExpr, + c: 'int64_t', + b: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IsGreaterCstCt(self, v: "IntExpr", c: "int64_t", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (v > c)"""
+        return _pywrapcp.Solver_IsGreaterCstCt(self, v, c, b)
+
+ +
+ +

b == (v > c)

+
+ + +
+
+
#   + + + def + IsGreaterCstVar( + self, + var: ortools.constraint_solver.pywrapcp.IntExpr, + value: 'int64_t' +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsGreaterCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var > value)"""
+        return _pywrapcp.Solver_IsGreaterCstVar(self, var, value)
+
+ +
+ +

status var of (var > value)

+
+ + +
+
+
#   + + + def + IsGreaterVar( + self, + left: ortools.constraint_solver.pywrapcp.IntExpr, + right: ortools.constraint_solver.pywrapcp.IntExpr +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsGreaterVar(self, left: "IntExpr", right: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (left > right)"""
+        return _pywrapcp.Solver_IsGreaterVar(self, left, right)
+
+ +
+ +

status var of (left > right)

+
+ + +
+
+
#   + + + def + IsGreaterCt( + self, + left: ortools.constraint_solver.pywrapcp.IntExpr, + right: ortools.constraint_solver.pywrapcp.IntExpr, + b: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IsGreaterCt(self, left: "IntExpr", right: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (left > right)"""
+        return _pywrapcp.Solver_IsGreaterCt(self, left, right, b)
+
+ +
+ +

b == (left > right)

+
+ + +
+
+
#   + + + def + IsLessCstCt( + self, + v: ortools.constraint_solver.pywrapcp.IntExpr, + c: 'int64_t', + b: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IsLessCstCt(self, v: "IntExpr", c: "int64_t", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (v < c)"""
+        return _pywrapcp.Solver_IsLessCstCt(self, v, c, b)
+
+ +
+ +

b == (v < c)

+
+ + +
+
+
#   + + + def + IsLessCstVar( + self, + var: ortools.constraint_solver.pywrapcp.IntExpr, + value: 'int64_t' +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsLessCstVar(self, var: "IntExpr", value: "int64_t") -> "operations_research::IntVar *":
+        r""" status var of (var < value)"""
+        return _pywrapcp.Solver_IsLessCstVar(self, var, value)
+
+ +
+ +

status var of (var < value)

+
+ + +
+
+
#   + + + def + IsLessVar( + self, + left: ortools.constraint_solver.pywrapcp.IntExpr, + right: ortools.constraint_solver.pywrapcp.IntExpr +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsLessVar(self, left: "IntExpr", right: "IntExpr") -> "operations_research::IntVar *":
+        r""" status var of (left < right)"""
+        return _pywrapcp.Solver_IsLessVar(self, left, right)
+
+ +
+ +

status var of (left < right)

+
+ + +
+
+
#   + + + def + IsLessCt( + self, + left: ortools.constraint_solver.pywrapcp.IntExpr, + right: ortools.constraint_solver.pywrapcp.IntExpr, + b: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IsLessCt(self, left: "IntExpr", right: "IntExpr", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (left < right)"""
+        return _pywrapcp.Solver_IsLessCt(self, left, right, b)
+
+ +
+ +

b == (left < right)

+
+ + +
+
+
#   + + + def + SumLessOrEqual( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + cst: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def SumLessOrEqual(self, vars: "std::vector< operations_research::IntVar * > const &", cst: "int64_t") -> "operations_research::Constraint *":
+        r""" Variation on arrays."""
+        return _pywrapcp.Solver_SumLessOrEqual(self, vars, cst)
+
+ +
+ +

Variation on arrays.

+
+ + +
+
+
#   + + + def + SumGreaterOrEqual( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + cst: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def SumGreaterOrEqual(self, vars: "std::vector< operations_research::IntVar * > const &", cst: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_SumGreaterOrEqual(self, vars, cst)
+
+ +
+ + + +
+
+
#   + + + def + SumEquality(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def SumEquality(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_SumEquality(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + ScalProdEquality(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def ScalProdEquality(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_ScalProdEquality(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + ScalProdGreaterOrEqual(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def ScalProdGreaterOrEqual(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_ScalProdGreaterOrEqual(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + ScalProdLessOrEqual(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def ScalProdLessOrEqual(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_ScalProdLessOrEqual(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + MinEquality( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + min_var: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def MinEquality(self, vars: "std::vector< operations_research::IntVar * > const &", min_var: "IntVar") -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_MinEquality(self, vars, min_var)
+
+ +
+ + + +
+
+
#   + + + def + MaxEquality( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + max_var: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def MaxEquality(self, vars: "std::vector< operations_research::IntVar * > const &", max_var: "IntVar") -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_MaxEquality(self, vars, max_var)
+
+ +
+ + + +
+
+
#   + + + def + ElementEquality(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def ElementEquality(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_ElementEquality(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + AbsEquality( + self, + var: ortools.constraint_solver.pywrapcp.IntVar, + abs_var: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def AbsEquality(self, var: "IntVar", abs_var: "IntVar") -> "operations_research::Constraint *":
+        r""" Creates the constraint abs(var) == abs_var."""
+        return _pywrapcp.Solver_AbsEquality(self, var, abs_var)
+
+ +
+ +

Creates the constraint abs(var) == abs_var.

+
+ + +
+
+
#   + + + def + IndexOfConstraint( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + index: ortools.constraint_solver.pywrapcp.IntVar, + target: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IndexOfConstraint(self, vars: "std::vector< operations_research::IntVar * > const &", index: "IntVar", target: "int64_t") -> "operations_research::Constraint *":
+        r"""
+        This constraint is a special case of the element constraint with
+        an array of integer variables, where the variables are all
+        different and the index variable is constrained such that
+        vars[index] == target.
+        """
+        return _pywrapcp.Solver_IndexOfConstraint(self, vars, index, target)
+
+ +
+ +

This constraint is a special case of the element constraint with +an array of integer variables, where the variables are all +different and the index variable is constrained such that +vars[index] == target.

+
+ + +
+
+
#   + + + def + ConstraintInitialPropagateCallback( + self, + ct: ortools.constraint_solver.pywrapcp.Constraint +) -> 'operations_research::Demon *': +
+ +
+ View Source +
    def ConstraintInitialPropagateCallback(self, ct: "Constraint") -> "operations_research::Demon *":
+        r"""
+        This method is a specialized case of the MakeConstraintDemon
+        method to call the InitiatePropagate of the constraint 'ct'.
+        """
+        return _pywrapcp.Solver_ConstraintInitialPropagateCallback(self, ct)
+
+ +
+ +

This method is a specialized case of the MakeConstraintDemon +method to call the InitiatePropagate of the constraint 'ct'.

+
+ + +
+
+
#   + + + def + DelayedConstraintInitialPropagateCallback( + self, + ct: ortools.constraint_solver.pywrapcp.Constraint +) -> 'operations_research::Demon *': +
+ +
+ View Source +
    def DelayedConstraintInitialPropagateCallback(self, ct: "Constraint") -> "operations_research::Demon *":
+        r"""
+        This method is a specialized case of the MakeConstraintDemon
+        method to call the InitiatePropagate of the constraint 'ct' with
+        low priority.
+        """
+        return _pywrapcp.Solver_DelayedConstraintInitialPropagateCallback(self, ct)
+
+ +
+ +

This method is a specialized case of the MakeConstraintDemon +method to call the InitiatePropagate of the constraint 'ct' with +low priority.

+
+ + +
+
+
#   + + + def + ClosureDemon( + self, + closure: 'operations_research::Solver::Closure' +) -> 'operations_research::Demon *': +
+ +
+ View Source +
    def ClosureDemon(self, closure: "operations_research::Solver::Closure") -> "operations_research::Demon *":
+        r""" Creates a demon from a closure."""
+        return _pywrapcp.Solver_ClosureDemon(self, closure)
+
+ +
+ +

Creates a demon from a closure.

+
+ + +
+
+
#   + + + def + BetweenCt( + self, + expr: ortools.constraint_solver.pywrapcp.IntExpr, + l: 'int64_t', + u: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def BetweenCt(self, expr: "IntExpr", l: "int64_t", u: "int64_t") -> "operations_research::Constraint *":
+        r""" (l <= expr <= u)"""
+        return _pywrapcp.Solver_BetweenCt(self, expr, l, u)
+
+ +
+ +

(l <= expr <= u)

+
+ + +
+
+
#   + + + def + IsBetweenCt( + self, + expr: ortools.constraint_solver.pywrapcp.IntExpr, + l: 'int64_t', + u: 'int64_t', + b: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IsBetweenCt(self, expr: "IntExpr", l: "int64_t", u: "int64_t", b: "IntVar") -> "operations_research::Constraint *":
+        r""" b == (l <= expr <= u)"""
+        return _pywrapcp.Solver_IsBetweenCt(self, expr, l, u, b)
+
+ +
+ +

b == (l <= expr <= u)

+
+ + +
+
+
#   + + + def + IsBetweenVar( + self, + v: ortools.constraint_solver.pywrapcp.IntExpr, + l: 'int64_t', + u: 'int64_t' +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsBetweenVar(self, v: "IntExpr", l: "int64_t", u: "int64_t") -> "operations_research::IntVar *":
+        return _pywrapcp.Solver_IsBetweenVar(self, v, l, u)
+
+ +
+ + + +
+
+
#   + + + def + MemberCt(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def MemberCt(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_MemberCt(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + NotMemberCt(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def NotMemberCt(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        expr not in set.
+
+        |
+
+        *Overload 2:*
+        expr should not be in the list of forbidden intervals [start[i]..end[i]].
+
+        |
+
+        *Overload 3:*
+        expr should not be in the list of forbidden intervals [start[i]..end[i]].
+        """
+        return _pywrapcp.Solver_NotMemberCt(self, *args)
+
+ +
+ +

Overload 1: +expr not in set.

+ +

|

+ +

Overload 2: +expr should not be in the list of forbidden intervals [start[i]..end[i]].

+ +

|

+ +

Overload 3: +expr should not be in the list of forbidden intervals [start[i]..end[i]].

+
+ + +
+
+
#   + + + def + IsMemberCt(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def IsMemberCt(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_IsMemberCt(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + IsMemberVar(self, *args) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsMemberVar(self, *args) -> "operations_research::IntVar *":
+        return _pywrapcp.Solver_IsMemberVar(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + Count(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def Count(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        |{i | vars[i] == value}| == max_count
+
+        |
+
+        *Overload 2:*
+        |{i | vars[i] == value}| == max_count
+        """
+        return _pywrapcp.Solver_Count(self, *args)
+
+ +
+ +

Overload 1: +|{i | vars[i] == value}| == max_count

+ +

|

+ +

Overload 2: +|{i | vars[i] == value}| == max_count

+
+ + +
+
+
#   + + + def + Distribute(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def Distribute(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        Aggregated version of count:  |{i | v[i] == values[j]}| == cards[j]
+
+        |
+
+        *Overload 2:*
+        Aggregated version of count:  |{i | v[i] == values[j]}| == cards[j]
+
+        |
+
+        *Overload 3:*
+        Aggregated version of count:  |{i | v[i] == j}| == cards[j]
+
+        |
+
+        *Overload 4:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1: card_min <= |{i | v[i] == j}| <= card_max
+
+        |
+
+        *Overload 5:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1:
+           card_min[j] <= |{i | v[i] == j}| <= card_max[j]
+
+        |
+
+        *Overload 6:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1:
+           card_min[j] <= |{i | v[i] == j}| <= card_max[j]
+
+        |
+
+        *Overload 7:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1:
+           card_min[j] <= |{i | v[i] == values[j]}| <= card_max[j]
+
+        |
+
+        *Overload 8:*
+        Aggregated version of count with bounded cardinalities:
+        forall j in 0 .. card_size - 1:
+           card_min[j] <= |{i | v[i] == values[j]}| <= card_max[j]
+        """
+        return _pywrapcp.Solver_Distribute(self, *args)
+
+ +
+ +

Overload 1: +Aggregated version of count: |{i | v[i] == values[j]}| == cards[j]

+ +

|

+ +

Overload 2: +Aggregated version of count: |{i | v[i] == values[j]}| == cards[j]

+ +

|

+ +

Overload 3: +Aggregated version of count: |{i | v[i] == j}| == cards[j]

+ +

|

+ +

Overload 4: +Aggregated version of count with bounded cardinalities: +forall j in 0 .. card_size - 1: card_min <= |{i | v[i] == j}| <= card_max

+ +

|

+ +

Overload 5: +Aggregated version of count with bounded cardinalities: +forall j in 0 .. card_size - 1: + card_min[j] <= |{i | v[i] == j}| <= card_max[j]

+ +

|

+ +

Overload 6: +Aggregated version of count with bounded cardinalities: +forall j in 0 .. card_size - 1: + card_min[j] <= |{i | v[i] == j}| <= card_max[j]

+ +

|

+ +

Overload 7: +Aggregated version of count with bounded cardinalities: +forall j in 0 .. card_size - 1: + card_min[j] <= |{i | v[i] == values[j]}| <= card_max[j]

+ +

|

+ +

Overload 8: +Aggregated version of count with bounded cardinalities: +forall j in 0 .. card_size - 1: + card_min[j] <= |{i | v[i] == values[j]}| <= card_max[j]

+
+ + +
+
+
#   + + + def + Deviation( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + deviation_var: ortools.constraint_solver.pywrapcp.IntVar, + total_sum: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def Deviation(self, vars: "std::vector< operations_research::IntVar * > const &", deviation_var: "IntVar", total_sum: "int64_t") -> "operations_research::Constraint *":
+        r"""
+        Deviation constraint:
+        sum_i |n * vars[i] - total_sum| <= deviation_var and
+        sum_i vars[i] == total_sum
+        n = #vars
+        """
+        return _pywrapcp.Solver_Deviation(self, vars, deviation_var, total_sum)
+
+ +
+ +

Deviation constraint: +sum_i |n * vars[i] - total_sum| <= deviation_var and +sum_i vars[i] == total_sum +n = #vars

+
+ + +
+
+
#   + + + def + AllDifferent(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def AllDifferent(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        All variables are pairwise different. This corresponds to the
+        stronger version of the propagation algorithm.
+
+        |
+
+        *Overload 2:*
+        All variables are pairwise different.  If 'stronger_propagation'
+        is true, stronger, and potentially slower propagation will
+        occur. This API will be deprecated in the future.
+        """
+        return _pywrapcp.Solver_AllDifferent(self, *args)
+
+ +
+ +

Overload 1: +All variables are pairwise different. This corresponds to the +stronger version of the propagation algorithm.

+ +

|

+ +

Overload 2: +All variables are pairwise different. If 'stronger_propagation' +is true, stronger, and potentially slower propagation will +occur. This API will be deprecated in the future.

+
+ + +
+
+
#   + + + def + AllDifferentExcept( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + escape_value: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def AllDifferentExcept(self, vars: "std::vector< operations_research::IntVar * > const &", escape_value: "int64_t") -> "operations_research::Constraint *":
+        r"""
+        All variables are pairwise different, unless they are assigned to
+        the escape value.
+        """
+        return _pywrapcp.Solver_AllDifferentExcept(self, vars, escape_value)
+
+ +
+ +

All variables are pairwise different, unless they are assigned to +the escape value.

+
+ + +
+
+
#   + + + def + SortingConstraint( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + sorted: 'std::vector< operations_research::IntVar * > const &' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def SortingConstraint(self, vars: "std::vector< operations_research::IntVar * > const &", sorted: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint binding the arrays of variables "vars" and
+        "sorted_vars": sorted_vars[0] must be equal to the minimum of all
+        variables in vars, and so on: the value of sorted_vars[i] must be
+        equal to the i-th value of variables invars.
+
+        This constraint propagates in both directions: from "vars" to
+        "sorted_vars" and vice-versa.
+
+        Behind the scenes, this constraint maintains that:
+          - sorted is always increasing.
+          - whatever the values of vars, there exists a permutation that
+            injects its values into the sorted variables.
+
+        For more info, please have a look at:
+          https://mpi-inf.mpg.de/~mehlhorn/ftp/Mehlhorn-Thiel.pdf
+        """
+        return _pywrapcp.Solver_SortingConstraint(self, vars, sorted)
+
+ +
+ +

Creates a constraint binding the arrays of variables "vars" and +"sorted_vars": sorted_vars[0] must be equal to the minimum of all +variables in vars, and so on: the value of sorted_vars[i] must be +equal to the i-th value of variables invars.

+ +

This constraint propagates in both directions: from "vars" to +"sorted_vars" and vice-versa.

+ +

Behind the scenes, this constraint maintains that:

+ +
    +
  • sorted is always increasing.
  • +
  • whatever the values of vars, there exists a permutation that +injects its values into the sorted variables.
  • +
+ +

For more info, please have a look at: + https://mpi-inf.mpg.de/~mehlhorn/ftp/Mehlhorn-Thiel.pdf

+
+ + +
+
+
#   + + + def + LexicalLess( + self, + left: 'std::vector< operations_research::IntVar * > const &', + right: 'std::vector< operations_research::IntVar * > const &' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def LexicalLess(self, left: "std::vector< operations_research::IntVar * > const &", right: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that enforces that left is lexicographically less
+        than right.
+        """
+        return _pywrapcp.Solver_LexicalLess(self, left, right)
+
+ +
+ +

Creates a constraint that enforces that left is lexicographically less +than right.

+
+ + +
+
+
#   + + + def + LexicalLessOrEqual( + self, + left: 'std::vector< operations_research::IntVar * > const &', + right: 'std::vector< operations_research::IntVar * > const &' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def LexicalLessOrEqual(self, left: "std::vector< operations_research::IntVar * > const &", right: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that enforces that left is lexicographically less
+        than or equal to right.
+        """
+        return _pywrapcp.Solver_LexicalLessOrEqual(self, left, right)
+
+ +
+ +

Creates a constraint that enforces that left is lexicographically less +than or equal to right.

+
+ + +
+
+
#   + + + def + InversePermutationConstraint( + self, + left: 'std::vector< operations_research::IntVar * > const &', + right: 'std::vector< operations_research::IntVar * > const &' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def InversePermutationConstraint(self, left: "std::vector< operations_research::IntVar * > const &", right: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that enforces that 'left' and 'right' both
+        represent permutations of [0..left.size()-1], and that 'right' is
+        the inverse permutation of 'left', i.e. for all i in
+        [0..left.size()-1], right[left[i]] = i.
+        """
+        return _pywrapcp.Solver_InversePermutationConstraint(self, left, right)
+
+ +
+ +

Creates a constraint that enforces that 'left' and 'right' both +represent permutations of [0..left.size()-1], and that 'right' is +the inverse permutation of 'left', i.e. for all i in +[0..left.size()-1], right[left[i]] = i.

+
+ + +
+
+
#   + + + def + NullIntersect( + self, + first_vars: 'std::vector< operations_research::IntVar * > const &', + second_vars: 'std::vector< operations_research::IntVar * > const &' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def NullIntersect(self, first_vars: "std::vector< operations_research::IntVar * > const &", second_vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that states that all variables in the first
+        vector are different from all variables in the second
+        group. Thus the set of values in the first vector does not
+        intersect with the set of values in the second vector.
+        """
+        return _pywrapcp.Solver_NullIntersect(self, first_vars, second_vars)
+
+ +
+ +

Creates a constraint that states that all variables in the first +vector are different from all variables in the second +group. Thus the set of values in the first vector does not +intersect with the set of values in the second vector.

+
+ + +
+
+
#   + + + def + NullIntersectExcept( + self, + first_vars: 'std::vector< operations_research::IntVar * > const &', + second_vars: 'std::vector< operations_research::IntVar * > const &', + escape_value: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def NullIntersectExcept(self, first_vars: "std::vector< operations_research::IntVar * > const &", second_vars: "std::vector< operations_research::IntVar * > const &", escape_value: "int64_t") -> "operations_research::Constraint *":
+        r"""
+        Creates a constraint that states that all variables in the first
+        vector are different from all variables from the second group,
+        unless they are assigned to the escape value. Thus the set of
+        values in the first vector minus the escape value does not
+        intersect with the set of values in the second vector.
+        """
+        return _pywrapcp.Solver_NullIntersectExcept(self, first_vars, second_vars, escape_value)
+
+ +
+ +

Creates a constraint that states that all variables in the first +vector are different from all variables from the second group, +unless they are assigned to the escape value. Thus the set of +values in the first vector minus the escape value does not +intersect with the set of values in the second vector.

+
+ + +
+
+
#   + + + def + Circuit( + self, + nexts: 'std::vector< operations_research::IntVar * > const &' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def Circuit(self, nexts: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r""" Force the "nexts" variable to create a complete Hamiltonian path."""
+        return _pywrapcp.Solver_Circuit(self, nexts)
+
+ +
+ +

Force the "nexts" variable to create a complete Hamiltonian path.

+
+ + +
+
+
#   + + + def + SubCircuit( + self, + nexts: 'std::vector< operations_research::IntVar * > const &' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def SubCircuit(self, nexts: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Force the "nexts" variable to create a complete Hamiltonian path
+        for those that do not loop upon themselves.
+        """
+        return _pywrapcp.Solver_SubCircuit(self, nexts)
+
+ +
+ +

Force the "nexts" variable to create a complete Hamiltonian path +for those that do not loop upon themselves.

+
+ + +
+
+
#   + + + def + DelayedPathCumul( + self, + nexts: 'std::vector< operations_research::IntVar * > const &', + active: 'std::vector< operations_research::IntVar * > const &', + cumuls: 'std::vector< operations_research::IntVar * > const &', + transits: 'std::vector< operations_research::IntVar * > const &' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def DelayedPathCumul(self, nexts: "std::vector< operations_research::IntVar * > const &", active: "std::vector< operations_research::IntVar * > const &", cumuls: "std::vector< operations_research::IntVar * > const &", transits: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        r"""
+        Delayed version of the same constraint: propagation on the nexts variables
+        is delayed until all constraints have propagated.
+        """
+        return _pywrapcp.Solver_DelayedPathCumul(self, nexts, active, cumuls, transits)
+
+ +
+ +

Delayed version of the same constraint: propagation on the nexts variables +is delayed until all constraints have propagated.

+
+ + +
+
+
#   + + + def + PathCumul(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def PathCumul(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        Creates a constraint which accumulates values along a path such that:
+        cumuls[next[i]] = cumuls[i] + transits[i].
+        Active variables indicate if the corresponding next variable is active;
+        this could be useful to model unperformed nodes in a routing problem.
+
+        |
+
+        *Overload 2:*
+        Creates a constraint which accumulates values along a path such that:
+        cumuls[next[i]] = cumuls[i] + transit_evaluator(i, next[i]).
+        Active variables indicate if the corresponding next variable is active;
+        this could be useful to model unperformed nodes in a routing problem.
+        Ownership of transit_evaluator is taken and it must be a repeatable
+        callback.
+
+        |
+
+        *Overload 3:*
+        Creates a constraint which accumulates values along a path such that:
+        cumuls[next[i]] = cumuls[i] + transit_evaluator(i, next[i]) + slacks[i].
+        Active variables indicate if the corresponding next variable is active;
+        this could be useful to model unperformed nodes in a routing problem.
+        Ownership of transit_evaluator is taken and it must be a repeatable
+        callback.
+        """
+        return _pywrapcp.Solver_PathCumul(self, *args)
+
+ +
+ +

Overload 1: +Creates a constraint which accumulates values along a path such that: +cumuls[next[i]] = cumuls[i] + transits[i]. +Active variables indicate if the corresponding next variable is active; +this could be useful to model unperformed nodes in a routing problem.

+ +

|

+ +

Overload 2: +Creates a constraint which accumulates values along a path such that: +cumuls[next[i]] = cumuls[i] + transit_evaluator(i, next[i]). +Active variables indicate if the corresponding next variable is active; +this could be useful to model unperformed nodes in a routing problem. +Ownership of transit_evaluator is taken and it must be a repeatable +callback.

+ +

|

+ +

Overload 3: +Creates a constraint which accumulates values along a path such that: +cumuls[next[i]] = cumuls[i] + transit_evaluator(i, next[i]) + slacks[i]. +Active variables indicate if the corresponding next variable is active; +this could be useful to model unperformed nodes in a routing problem. +Ownership of transit_evaluator is taken and it must be a repeatable +callback.

+
+ + +
+
+
#   + + + def + AllowedAssignments(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def AllowedAssignments(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        This method creates a constraint where the graph of the relation
+        between the variables is given in extension. There are 'arity'
+        variables involved in the relation and the graph is given by a
+        integer tuple set.
+
+        |
+
+        *Overload 2:*
+        Compatibility layer for Python API.
+        """
+        return _pywrapcp.Solver_AllowedAssignments(self, *args)
+
+ +
+ +

Overload 1: +This method creates a constraint where the graph of the relation +between the variables is given in extension. There are 'arity' +variables involved in the relation and the graph is given by a +integer tuple set.

+ +

|

+ +

Overload 2: +Compatibility layer for Python API.

+
+ + +
+
+
#   + + + def + TransitionConstraint(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def TransitionConstraint(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_TransitionConstraint(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + NonOverlappingBoxesConstraint(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def NonOverlappingBoxesConstraint(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_NonOverlappingBoxesConstraint(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + Pack( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + number_of_bins: int +) -> 'operations_research::Pack *': +
+ +
+ View Source +
    def Pack(self, vars: "std::vector< operations_research::IntVar * > const &", number_of_bins: "int") -> "operations_research::Pack *":
+        r"""
+        This constraint packs all variables onto 'number_of_bins'
+        variables.  For any given variable, a value of 'number_of_bins'
+        indicates that the variable is not assigned to any bin.
+        Dimensions, i.e., cumulative constraints on this packing, can be
+        added directly from the pack class.
+        """
+        return _pywrapcp.Solver_Pack(self, vars, number_of_bins)
+
+ +
+ +

This constraint packs all variables onto 'number_of_bins' +variables. For any given variable, a value of 'number_of_bins' +indicates that the variable is not assigned to any bin. +Dimensions, i.e., cumulative constraints on this packing, can be +added directly from the pack class.

+
+ + +
+
+
#   + + + def + FixedDurationIntervalVar(self, *args) -> 'operations_research::IntervalVar *': +
+ +
+ View Source +
    def FixedDurationIntervalVar(self, *args) -> "operations_research::IntervalVar *":
+        r"""
+        *Overload 1:*
+        Creates an interval var with a fixed duration. The duration must
+        be greater than 0. If optional is true, then the interval can be
+        performed or unperformed. If optional is false, then the interval
+        is always performed.
+
+        |
+
+        *Overload 2:*
+        Creates a performed interval var with a fixed duration. The duration must
+        be greater than 0.
+
+        |
+
+        *Overload 3:*
+        Creates an interval var with a fixed duration, and performed_variable.
+        The duration must be greater than 0.
+        """
+        return _pywrapcp.Solver_FixedDurationIntervalVar(self, *args)
+
+ +
+ +

Overload 1: +Creates an interval var with a fixed duration. The duration must +be greater than 0. If optional is true, then the interval can be +performed or unperformed. If optional is false, then the interval +is always performed.

+ +

|

+ +

Overload 2: +Creates a performed interval var with a fixed duration. The duration must +be greater than 0.

+ +

|

+ +

Overload 3: +Creates an interval var with a fixed duration, and performed_variable. +The duration must be greater than 0.

+
+ + +
+
+
#   + + + def + FixedInterval( + self, + start: 'int64_t', + duration: 'int64_t', + name: 'std::string const &' +) -> 'operations_research::IntervalVar *': +
+ +
+ View Source +
    def FixedInterval(self, start: "int64_t", duration: "int64_t", name: "std::string const &") -> "operations_research::IntervalVar *":
+        r""" Creates a fixed and performed interval."""
+        return _pywrapcp.Solver_FixedInterval(self, start, duration, name)
+
+ +
+ +

Creates a fixed and performed interval.

+
+ + +
+
+
#   + + + def + IntervalVar( + self, + start_min: 'int64_t', + start_max: 'int64_t', + duration_min: 'int64_t', + duration_max: 'int64_t', + end_min: 'int64_t', + end_max: 'int64_t', + optional: bool, + name: 'std::string const &' +) -> 'operations_research::IntervalVar *': +
+ +
+ View Source +
    def IntervalVar(self, start_min: "int64_t", start_max: "int64_t", duration_min: "int64_t", duration_max: "int64_t", end_min: "int64_t", end_max: "int64_t", optional: "bool", name: "std::string const &") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var by specifying the bounds on start,
+        duration, and end.
+        """
+        return _pywrapcp.Solver_IntervalVar(self, start_min, start_max, duration_min, duration_max, end_min, end_max, optional, name)
+
+ +
+ +

Creates an interval var by specifying the bounds on start, +duration, and end.

+
+ + +
+
+
#   + + + def + MirrorInterval( + self, + interval_var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'operations_research::IntervalVar *': +
+ +
+ View Source +
    def MirrorInterval(self, interval_var: "IntervalVar") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var that is the mirror image of the given one, that
+        is, the interval var obtained by reversing the axis.
+        """
+        return _pywrapcp.Solver_MirrorInterval(self, interval_var)
+
+ +
+ +

Creates an interval var that is the mirror image of the given one, that +is, the interval var obtained by reversing the axis.

+
+ + +
+
+
#   + + + def + FixedDurationStartSyncedOnStartIntervalVar( + self, + interval_var: ortools.constraint_solver.pywrapcp.IntervalVar, + duration: 'int64_t', + offset: 'int64_t' +) -> 'operations_research::IntervalVar *': +
+ +
+ View Source +
    def FixedDurationStartSyncedOnStartIntervalVar(self, interval_var: "IntervalVar", duration: "int64_t", offset: "int64_t") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var with a fixed duration whose start is
+        synchronized with the start of another interval, with a given
+        offset. The performed status is also in sync with the performed
+        status of the given interval variable.
+        """
+        return _pywrapcp.Solver_FixedDurationStartSyncedOnStartIntervalVar(self, interval_var, duration, offset)
+
+ +
+ +

Creates an interval var with a fixed duration whose start is +synchronized with the start of another interval, with a given +offset. The performed status is also in sync with the performed +status of the given interval variable.

+
+ + +
+
+
#   + + + def + FixedDurationStartSyncedOnEndIntervalVar( + self, + interval_var: ortools.constraint_solver.pywrapcp.IntervalVar, + duration: 'int64_t', + offset: 'int64_t' +) -> 'operations_research::IntervalVar *': +
+ +
+ View Source +
    def FixedDurationStartSyncedOnEndIntervalVar(self, interval_var: "IntervalVar", duration: "int64_t", offset: "int64_t") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var with a fixed duration whose start is
+        synchronized with the end of another interval, with a given
+        offset. The performed status is also in sync with the performed
+        status of the given interval variable.
+        """
+        return _pywrapcp.Solver_FixedDurationStartSyncedOnEndIntervalVar(self, interval_var, duration, offset)
+
+ +
+ +

Creates an interval var with a fixed duration whose start is +synchronized with the end of another interval, with a given +offset. The performed status is also in sync with the performed +status of the given interval variable.

+
+ + +
+
+
#   + + + def + FixedDurationEndSyncedOnStartIntervalVar( + self, + interval_var: ortools.constraint_solver.pywrapcp.IntervalVar, + duration: 'int64_t', + offset: 'int64_t' +) -> 'operations_research::IntervalVar *': +
+ +
+ View Source +
    def FixedDurationEndSyncedOnStartIntervalVar(self, interval_var: "IntervalVar", duration: "int64_t", offset: "int64_t") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var with a fixed duration whose end is
+        synchronized with the start of another interval, with a given
+        offset. The performed status is also in sync with the performed
+        status of the given interval variable.
+        """
+        return _pywrapcp.Solver_FixedDurationEndSyncedOnStartIntervalVar(self, interval_var, duration, offset)
+
+ +
+ +

Creates an interval var with a fixed duration whose end is +synchronized with the start of another interval, with a given +offset. The performed status is also in sync with the performed +status of the given interval variable.

+
+ + +
+
+
#   + + + def + FixedDurationEndSyncedOnEndIntervalVar( + self, + interval_var: ortools.constraint_solver.pywrapcp.IntervalVar, + duration: 'int64_t', + offset: 'int64_t' +) -> 'operations_research::IntervalVar *': +
+ +
+ View Source +
    def FixedDurationEndSyncedOnEndIntervalVar(self, interval_var: "IntervalVar", duration: "int64_t", offset: "int64_t") -> "operations_research::IntervalVar *":
+        r"""
+        Creates an interval var with a fixed duration whose end is
+        synchronized with the end of another interval, with a given
+        offset. The performed status is also in sync with the performed
+        status of the given interval variable.
+        """
+        return _pywrapcp.Solver_FixedDurationEndSyncedOnEndIntervalVar(self, interval_var, duration, offset)
+
+ +
+ +

Creates an interval var with a fixed duration whose end is +synchronized with the end of another interval, with a given +offset. The performed status is also in sync with the performed +status of the given interval variable.

+
+ + +
+
+
#   + + + def + IntervalRelaxedMin( + self, + interval_var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'operations_research::IntervalVar *': +
+ +
+ View Source +
    def IntervalRelaxedMin(self, interval_var: "IntervalVar") -> "operations_research::IntervalVar *":
+        r"""
+         Creates and returns an interval variable that wraps around the given one,
+         relaxing the min start and end. Relaxing means making unbounded when
+         optional. If the variable is non-optional, this method returns
+         interval_var.
+
+         More precisely, such an interval variable behaves as follows:
+        When the underlying must be performed, the returned interval variable
+             behaves exactly as the underlying;
+        When the underlying may or may not be performed, the returned interval
+             variable behaves like the underlying, except that it is unbounded on
+             the min side;
+        When the underlying cannot be performed, the returned interval variable
+             is of duration 0 and must be performed in an interval unbounded on
+             both sides.
+
+         This is very useful to implement propagators that may only modify
+         the start max or end max.
+        """
+        return _pywrapcp.Solver_IntervalRelaxedMin(self, interval_var)
+
+ +
+ +

Creates and returns an interval variable that wraps around the given one, + relaxing the min start and end. Relaxing means making unbounded when + optional. If the variable is non-optional, this method returns + interval_var.

+ +

More precisely, such an interval variable behaves as follows: +When the underlying must be performed, the returned interval variable + behaves exactly as the underlying; +When the underlying may or may not be performed, the returned interval + variable behaves like the underlying, except that it is unbounded on + the min side; +When the underlying cannot be performed, the returned interval variable + is of duration 0 and must be performed in an interval unbounded on + both sides.

+ +

This is very useful to implement propagators that may only modify + the start max or end max.

+
+ + +
+
+
#   + + + def + IntervalRelaxedMax( + self, + interval_var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'operations_research::IntervalVar *': +
+ +
+ View Source +
    def IntervalRelaxedMax(self, interval_var: "IntervalVar") -> "operations_research::IntervalVar *":
+        r"""
+         Creates and returns an interval variable that wraps around the given one,
+         relaxing the max start and end. Relaxing means making unbounded when
+         optional. If the variable is non optional, this method returns
+         interval_var.
+
+         More precisely, such an interval variable behaves as follows:
+        When the underlying must be performed, the returned interval variable
+             behaves exactly as the underlying;
+        When the underlying may or may not be performed, the returned interval
+             variable behaves like the underlying, except that it is unbounded on
+             the max side;
+        When the underlying cannot be performed, the returned interval variable
+             is of duration 0 and must be performed in an interval unbounded on
+             both sides.
+
+         This is very useful for implementing propagators that may only modify
+         the start min or end min.
+        """
+        return _pywrapcp.Solver_IntervalRelaxedMax(self, interval_var)
+
+ +
+ +

Creates and returns an interval variable that wraps around the given one, + relaxing the max start and end. Relaxing means making unbounded when + optional. If the variable is non optional, this method returns + interval_var.

+ +

More precisely, such an interval variable behaves as follows: +When the underlying must be performed, the returned interval variable + behaves exactly as the underlying; +When the underlying may or may not be performed, the returned interval + variable behaves like the underlying, except that it is unbounded on + the max side; +When the underlying cannot be performed, the returned interval variable + is of duration 0 and must be performed in an interval unbounded on + both sides.

+ +

This is very useful for implementing propagators that may only modify + the start min or end min.

+
+ + +
+
+
#   + + + def + TemporalDisjunction(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def TemporalDisjunction(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        This constraint implements a temporal disjunction between two
+        interval vars t1 and t2. 'alt' indicates which alternative was
+        chosen (alt == 0 is equivalent to t1 before t2).
+
+        |
+
+        *Overload 2:*
+        This constraint implements a temporal disjunction between two
+        interval vars.
+        """
+        return _pywrapcp.Solver_TemporalDisjunction(self, *args)
+
+ +
+ +

Overload 1: +This constraint implements a temporal disjunction between two +interval vars t1 and t2. 'alt' indicates which alternative was +chosen (alt == 0 is equivalent to t1 before t2).

+ +

|

+ +

Overload 2: +This constraint implements a temporal disjunction between two +interval vars.

+
+ + +
+
+
#   + + + def + DisjunctiveConstraint( + self, + intervals: 'std::vector< operations_research::IntervalVar * > const &', + name: 'std::string const &' +) -> 'operations_research::DisjunctiveConstraint *': +
+ +
+ View Source +
    def DisjunctiveConstraint(self, intervals: "std::vector< operations_research::IntervalVar * > const &", name: "std::string const &") -> "operations_research::DisjunctiveConstraint *":
+        r"""
+        This constraint forces all interval vars into an non-overlapping
+        sequence. Intervals with zero duration can be scheduled anywhere.
+        """
+        return _pywrapcp.Solver_DisjunctiveConstraint(self, intervals, name)
+
+ +
+ +

This constraint forces all interval vars into an non-overlapping +sequence. Intervals with zero duration can be scheduled anywhere.

+
+ + +
+
+
#   + + + def + Cumulative(self, *args) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def Cumulative(self, *args) -> "operations_research::Constraint *":
+        r"""
+        *Overload 1:*
+        This constraint forces that, for any integer t, the sum of the demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should only contain non-negative values. Zero values are
+        supported, and the corresponding intervals are filtered out, as they
+        neither impact nor are impacted by this constraint.
+
+        |
+
+        *Overload 2:*
+        This constraint forces that, for any integer t, the sum of the demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should only contain non-negative values. Zero values are
+        supported, and the corresponding intervals are filtered out, as they
+        neither impact nor are impacted by this constraint.
+
+        |
+
+        *Overload 3:*
+        This constraint forces that, for any integer t, the sum of the demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should only contain non-negative values. Zero values are
+        supported, and the corresponding intervals are filtered out, as they
+        neither impact nor are impacted by this constraint.
+
+        |
+
+        *Overload 4:*
+        This constraint enforces that, for any integer t, the sum of the demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should only contain non-negative values. Zero values are
+        supported, and the corresponding intervals are filtered out, as they
+        neither impact nor are impacted by this constraint.
+
+        |
+
+        *Overload 5:*
+        This constraint enforces that, for any integer t, the sum of demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should be positive.
+
+        |
+
+        *Overload 6:*
+        This constraint enforces that, for any integer t, the sum of demands
+        corresponding to an interval containing t does not exceed the given
+        capacity.
+
+        Intervals and demands should be vectors of equal size.
+
+        Demands should be positive.
+        """
+        return _pywrapcp.Solver_Cumulative(self, *args)
+
+ +
+ +

Overload 1: +This constraint forces that, for any integer t, the sum of the demands +corresponding to an interval containing t does not exceed the given +capacity.

+ +

Intervals and demands should be vectors of equal size.

+ +

Demands should only contain non-negative values. Zero values are +supported, and the corresponding intervals are filtered out, as they +neither impact nor are impacted by this constraint.

+ +

|

+ +

Overload 2: +This constraint forces that, for any integer t, the sum of the demands +corresponding to an interval containing t does not exceed the given +capacity.

+ +

Intervals and demands should be vectors of equal size.

+ +

Demands should only contain non-negative values. Zero values are +supported, and the corresponding intervals are filtered out, as they +neither impact nor are impacted by this constraint.

+ +

|

+ +

Overload 3: +This constraint forces that, for any integer t, the sum of the demands +corresponding to an interval containing t does not exceed the given +capacity.

+ +

Intervals and demands should be vectors of equal size.

+ +

Demands should only contain non-negative values. Zero values are +supported, and the corresponding intervals are filtered out, as they +neither impact nor are impacted by this constraint.

+ +

|

+ +

Overload 4: +This constraint enforces that, for any integer t, the sum of the demands +corresponding to an interval containing t does not exceed the given +capacity.

+ +

Intervals and demands should be vectors of equal size.

+ +

Demands should only contain non-negative values. Zero values are +supported, and the corresponding intervals are filtered out, as they +neither impact nor are impacted by this constraint.

+ +

|

+ +

Overload 5: +This constraint enforces that, for any integer t, the sum of demands +corresponding to an interval containing t does not exceed the given +capacity.

+ +

Intervals and demands should be vectors of equal size.

+ +

Demands should be positive.

+ +

|

+ +

Overload 6: +This constraint enforces that, for any integer t, the sum of demands +corresponding to an interval containing t does not exceed the given +capacity.

+ +

Intervals and demands should be vectors of equal size.

+ +

Demands should be positive.

+
+ + +
+
+
#   + + + def + Cover( + self, + vars: 'std::vector< operations_research::IntervalVar * > const &', + target_var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def Cover(self, vars: "std::vector< operations_research::IntervalVar * > const &", target_var: "IntervalVar") -> "operations_research::Constraint *":
+        r"""
+        This constraint states that the target_var is the convex hull of
+        the intervals. If none of the interval variables is performed,
+        then the target var is unperformed too. Also, if the target
+        variable is unperformed, then all the intervals variables are
+        unperformed too.
+        """
+        return _pywrapcp.Solver_Cover(self, vars, target_var)
+
+ +
+ +

This constraint states that the target_var is the convex hull of +the intervals. If none of the interval variables is performed, +then the target var is unperformed too. Also, if the target +variable is unperformed, then all the intervals variables are +unperformed too.

+
+ + +
+
+
#   + + + def + Assignment(self, *args) -> 'operations_research::Assignment *': +
+ +
+ View Source +
    def Assignment(self, *args) -> "operations_research::Assignment *":
+        r"""
+        *Overload 1:*
+        This method creates an empty assignment.
+
+        |
+
+        *Overload 2:*
+        This method creates an assignment which is a copy of 'a'.
+        """
+        return _pywrapcp.Solver_Assignment(self, *args)
+
+ +
+ +

Overload 1: +This method creates an empty assignment.

+ +

|

+ +

Overload 2: +This method creates an assignment which is a copy of 'a'.

+
+ + +
+
+
#   + + + def + FirstSolutionCollector(self, *args) -> 'operations_research::SolutionCollector *': +
+ +
+ View Source +
    def FirstSolutionCollector(self, *args) -> "operations_research::SolutionCollector *":
+        r"""
+        *Overload 1:*
+        Collect the first solution of the search.
+
+        |
+
+        *Overload 2:*
+        Collect the first solution of the search. The variables will need to
+        be added later.
+        """
+        return _pywrapcp.Solver_FirstSolutionCollector(self, *args)
+
+ +
+ +

Overload 1: +Collect the first solution of the search.

+ +

|

+ +

Overload 2: +Collect the first solution of the search. The variables will need to +be added later.

+
+ + +
+
+
#   + + + def + LastSolutionCollector(self, *args) -> 'operations_research::SolutionCollector *': +
+ +
+ View Source +
    def LastSolutionCollector(self, *args) -> "operations_research::SolutionCollector *":
+        r"""
+        *Overload 1:*
+        Collect the last solution of the search.
+
+        |
+
+        *Overload 2:*
+        Collect the last solution of the search. The variables will need to
+        be added later.
+        """
+        return _pywrapcp.Solver_LastSolutionCollector(self, *args)
+
+ +
+ +

Overload 1: +Collect the last solution of the search.

+ +

|

+ +

Overload 2: +Collect the last solution of the search. The variables will need to +be added later.

+
+ + +
+
+
#   + + + def + BestValueSolutionCollector(self, *args) -> 'operations_research::SolutionCollector *': +
+ +
+ View Source +
    def BestValueSolutionCollector(self, *args) -> "operations_research::SolutionCollector *":
+        r"""
+        *Overload 1:*
+        Collect the solution corresponding to the optimal value of the objective
+        of 'assignment'; if 'assignment' does not have an objective no solution is
+        collected. This collector only collects one solution corresponding to the
+        best objective value (the first one found).
+
+        |
+
+        *Overload 2:*
+        Collect the solution corresponding to the optimal value of the
+        objective of 'assignment'; if 'assignment' does not have an objective no
+        solution is collected. This collector only collects one solution
+        corresponding to the best objective value (the first one
+        found). The variables will need to be added later.
+        """
+        return _pywrapcp.Solver_BestValueSolutionCollector(self, *args)
+
+ +
+ +

Overload 1: +Collect the solution corresponding to the optimal value of the objective +of 'assignment'; if 'assignment' does not have an objective no solution is +collected. This collector only collects one solution corresponding to the +best objective value (the first one found).

+ +

|

+ +

Overload 2: +Collect the solution corresponding to the optimal value of the +objective of 'assignment'; if 'assignment' does not have an objective no +solution is collected. This collector only collects one solution +corresponding to the best objective value (the first one +found). The variables will need to be added later.

+
+ + +
+
+
#   + + + def + AllSolutionCollector(self, *args) -> 'operations_research::SolutionCollector *': +
+ +
+ View Source +
    def AllSolutionCollector(self, *args) -> "operations_research::SolutionCollector *":
+        r"""
+        *Overload 1:*
+        Collect all solutions of the search.
+
+        |
+
+        *Overload 2:*
+        Collect all solutions of the search. The variables will need to
+        be added later.
+        """
+        return _pywrapcp.Solver_AllSolutionCollector(self, *args)
+
+ +
+ +

Overload 1: +Collect all solutions of the search.

+ +

|

+ +

Overload 2: +Collect all solutions of the search. The variables will need to +be added later.

+
+ + +
+
+
#   + + + def + Minimize( + self, + v: ortools.constraint_solver.pywrapcp.IntVar, + step: 'int64_t' +) -> 'operations_research::OptimizeVar *': +
+ +
+ View Source +
    def Minimize(self, v: "IntVar", step: "int64_t") -> "operations_research::OptimizeVar *":
+        r""" Creates a minimization objective."""
+        return _pywrapcp.Solver_Minimize(self, v, step)
+
+ +
+ +

Creates a minimization objective.

+
+ + +
+
+
#   + + + def + Maximize( + self, + v: ortools.constraint_solver.pywrapcp.IntVar, + step: 'int64_t' +) -> 'operations_research::OptimizeVar *': +
+ +
+ View Source +
    def Maximize(self, v: "IntVar", step: "int64_t") -> "operations_research::OptimizeVar *":
+        r""" Creates a maximization objective."""
+        return _pywrapcp.Solver_Maximize(self, v, step)
+
+ +
+ +

Creates a maximization objective.

+
+ + +
+
+
#   + + + def + Optimize( + self, + maximize: bool, + v: ortools.constraint_solver.pywrapcp.IntVar, + step: 'int64_t' +) -> 'operations_research::OptimizeVar *': +
+ +
+ View Source +
    def Optimize(self, maximize: "bool", v: "IntVar", step: "int64_t") -> "operations_research::OptimizeVar *":
+        r""" Creates a objective with a given sense (true = maximization)."""
+        return _pywrapcp.Solver_Optimize(self, maximize, v, step)
+
+ +
+ +

Creates a objective with a given sense (true = maximization).

+
+ + +
+
+
#   + + + def + WeightedMinimize(self, *args) -> 'operations_research::OptimizeVar *': +
+ +
+ View Source +
    def WeightedMinimize(self, *args) -> "operations_research::OptimizeVar *":
+        r"""
+        *Overload 1:*
+        Creates a minimization weighted objective. The actual objective is
+        scalar_prod(sub_objectives, weights).
+
+        |
+
+        *Overload 2:*
+        Creates a minimization weighted objective. The actual objective is
+        scalar_prod(sub_objectives, weights).
+        """
+        return _pywrapcp.Solver_WeightedMinimize(self, *args)
+
+ +
+ +

Overload 1: +Creates a minimization weighted objective. The actual objective is +scalar_prod(sub_objectives, weights).

+ +

|

+ +

Overload 2: +Creates a minimization weighted objective. The actual objective is +scalar_prod(sub_objectives, weights).

+
+ + +
+
+
#   + + + def + WeightedMaximize(self, *args) -> 'operations_research::OptimizeVar *': +
+ +
+ View Source +
    def WeightedMaximize(self, *args) -> "operations_research::OptimizeVar *":
+        r"""
+        *Overload 1:*
+        Creates a maximization weigthed objective.
+
+        |
+
+        *Overload 2:*
+        Creates a maximization weigthed objective.
+        """
+        return _pywrapcp.Solver_WeightedMaximize(self, *args)
+
+ +
+ +

Overload 1: +Creates a maximization weigthed objective.

+ +

|

+ +

Overload 2: +Creates a maximization weigthed objective.

+
+ + +
+
+
#   + + + def + WeightedOptimize(self, *args) -> 'operations_research::OptimizeVar *': +
+ +
+ View Source +
    def WeightedOptimize(self, *args) -> "operations_research::OptimizeVar *":
+        r"""
+        *Overload 1:*
+        Creates a weighted objective with a given sense (true = maximization).
+
+        |
+
+        *Overload 2:*
+        Creates a weighted objective with a given sense (true = maximization).
+        """
+        return _pywrapcp.Solver_WeightedOptimize(self, *args)
+
+ +
+ +

Overload 1: +Creates a weighted objective with a given sense (true = maximization).

+ +

|

+ +

Overload 2: +Creates a weighted objective with a given sense (true = maximization).

+
+ + +
+
+
#   + + + def + TabuSearch( + self, + maximize: bool, + v: ortools.constraint_solver.pywrapcp.IntVar, + step: 'int64_t', + vars: 'std::vector< operations_research::IntVar * > const &', + keep_tenure: 'int64_t', + forbid_tenure: 'int64_t', + tabu_factor: 'double' +) -> 'operations_research::SearchMonitor *': +
+ +
+ View Source +
    def TabuSearch(self, maximize: "bool", v: "IntVar", step: "int64_t", vars: "std::vector< operations_research::IntVar * > const &", keep_tenure: "int64_t", forbid_tenure: "int64_t", tabu_factor: "double") -> "operations_research::SearchMonitor *":
+        r"""
+        MetaHeuristics which try to get the search out of local optima.
+        Creates a Tabu Search monitor.
+        In the context of local search the behavior is similar to MakeOptimize(),
+        creating an objective in a given sense. The behavior differs once a local
+        optimum is reached: thereafter solutions which degrade the value of the
+        objective are allowed if they are not "tabu". A solution is "tabu" if it
+        doesn't respect the following rules:
+        - improving the best solution found so far
+        - variables in the "keep" list must keep their value, variables in the
+        "forbid" list must not take the value they have in the list.
+        Variables with new values enter the tabu lists after each new solution
+        found and leave the lists after a given number of iterations (called
+        tenure). Only the variables passed to the method can enter the lists.
+        The tabu criterion is softened by the tabu factor which gives the number
+        of "tabu" violations which is tolerated; a factor of 1 means no violations
+        allowed; a factor of 0 means all violations are allowed.
+        """
+        return _pywrapcp.Solver_TabuSearch(self, maximize, v, step, vars, keep_tenure, forbid_tenure, tabu_factor)
+
+ +
+ +

MetaHeuristics which try to get the search out of local optima. +Creates a Tabu Search monitor. +In the context of local search the behavior is similar to MakeOptimize(), +creating an objective in a given sense. The behavior differs once a local +optimum is reached: thereafter solutions which degrade the value of the +objective are allowed if they are not "tabu". A solution is "tabu" if it +doesn't respect the following rules:

+ +
    +
  • improving the best solution found so far
  • +
  • variables in the "keep" list must keep their value, variables in the +"forbid" list must not take the value they have in the list. +Variables with new values enter the tabu lists after each new solution +found and leave the lists after a given number of iterations (called +tenure). Only the variables passed to the method can enter the lists. +The tabu criterion is softened by the tabu factor which gives the number +of "tabu" violations which is tolerated; a factor of 1 means no violations +allowed; a factor of 0 means all violations are allowed.
  • +
+
+ + +
+
+
#   + + + def + SimulatedAnnealing( + self, + maximize: bool, + v: ortools.constraint_solver.pywrapcp.IntVar, + step: 'int64_t', + initial_temperature: 'int64_t' +) -> 'operations_research::SearchMonitor *': +
+ +
+ View Source +
    def SimulatedAnnealing(self, maximize: "bool", v: "IntVar", step: "int64_t", initial_temperature: "int64_t") -> "operations_research::SearchMonitor *":
+        r""" Creates a Simulated Annealing monitor."""
+        return _pywrapcp.Solver_SimulatedAnnealing(self, maximize, v, step, initial_temperature)
+
+ +
+ +

Creates a Simulated Annealing monitor.

+
+ + +
+
+
#   + + + def + LubyRestart(self, scale_factor: int) -> 'operations_research::SearchMonitor *': +
+ +
+ View Source +
    def LubyRestart(self, scale_factor: "int") -> "operations_research::SearchMonitor *":
+        r"""
+        This search monitor will restart the search periodically.
+        At the iteration n, it will restart after scale_factor * Luby(n) failures
+        where Luby is the Luby Strategy (i.e. 1 1 2 1 1 2 4 1 1 2 1 1 2 4 8...).
+        """
+        return _pywrapcp.Solver_LubyRestart(self, scale_factor)
+
+ +
+ +

This search monitor will restart the search periodically. +At the iteration n, it will restart after scale_factor * Luby(n) failures +where Luby is the Luby Strategy (i.e. 1 1 2 1 1 2 4 1 1 2 1 1 2 4 8...).

+
+ + +
+
+
#   + + + def + ConstantRestart(self, frequency: int) -> 'operations_research::SearchMonitor *': +
+ +
+ View Source +
    def ConstantRestart(self, frequency: "int") -> "operations_research::SearchMonitor *":
+        r"""
+        This search monitor will restart the search periodically after 'frequency'
+        failures.
+        """
+        return _pywrapcp.Solver_ConstantRestart(self, frequency)
+
+ +
+ +

This search monitor will restart the search periodically after 'frequency' +failures.

+
+ + +
+
+
#   + + + def + TimeLimit(self, *args) -> 'operations_research::RegularLimit *': +
+ +
+ View Source +
    def TimeLimit(self, *args) -> "operations_research::RegularLimit *":
+        return _pywrapcp.Solver_TimeLimit(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + BranchesLimit(self, branches: 'int64_t') -> 'operations_research::RegularLimit *': +
+ +
+ View Source +
    def BranchesLimit(self, branches: "int64_t") -> "operations_research::RegularLimit *":
+        r"""
+        Creates a search limit that constrains the number of branches
+        explored in the search tree.
+        """
+        return _pywrapcp.Solver_BranchesLimit(self, branches)
+
+ +
+ +

Creates a search limit that constrains the number of branches +explored in the search tree.

+
+ + +
+
+
#   + + + def + FailuresLimit(self, failures: 'int64_t') -> 'operations_research::RegularLimit *': +
+ +
+ View Source +
    def FailuresLimit(self, failures: "int64_t") -> "operations_research::RegularLimit *":
+        r"""
+        Creates a search limit that constrains the number of failures
+        that can happen when exploring the search tree.
+        """
+        return _pywrapcp.Solver_FailuresLimit(self, failures)
+
+ +
+ +

Creates a search limit that constrains the number of failures +that can happen when exploring the search tree.

+
+ + +
+
+
#   + + + def + SolutionsLimit(self, solutions: 'int64_t') -> 'operations_research::RegularLimit *': +
+ +
+ View Source +
    def SolutionsLimit(self, solutions: "int64_t") -> "operations_research::RegularLimit *":
+        r"""
+        Creates a search limit that constrains the number of solutions found
+        during the search.
+        """
+        return _pywrapcp.Solver_SolutionsLimit(self, solutions)
+
+ +
+ +

Creates a search limit that constrains the number of solutions found +during the search.

+
+ + +
+
+
#   + + + def + Limit(self, *args) -> 'operations_research::SearchLimit *': +
+ +
+ View Source +
    def Limit(self, *args) -> "operations_research::SearchLimit *":
+        r"""
+        *Overload 1:*
+        Limits the search with the 'time', 'branches', 'failures' and
+        'solutions' limits. 'smart_time_check' reduces the calls to the wall
+
+        |
+
+        *Overload 2:*
+        Creates a search limit from its protobuf description
+
+        |
+
+        *Overload 3:*
+        Creates a search limit that is reached when either of the underlying limit
+        is reached. That is, the returned limit is more stringent than both
+        argument limits.
+        """
+        return _pywrapcp.Solver_Limit(self, *args)
+
+ +
+ +

Overload 1: +Limits the search with the 'time', 'branches', 'failures' and +'solutions' limits. 'smart_time_check' reduces the calls to the wall

+ +

|

+ +

Overload 2: +Creates a search limit from its protobuf description

+ +

|

+ +

Overload 3: +Creates a search limit that is reached when either of the underlying limit +is reached. That is, the returned limit is more stringent than both +argument limits.

+
+ + +
+
+
#   + + + def + CustomLimit( + self, + limiter: 'std::function< bool () >' +) -> 'operations_research::SearchLimit *': +
+ +
+ View Source +
    def CustomLimit(self, limiter: "std::function< bool () >") -> "operations_research::SearchLimit *":
+        r"""
+        Callback-based search limit. Search stops when limiter returns true; if
+        this happens at a leaf the corresponding solution will be rejected.
+        """
+        return _pywrapcp.Solver_CustomLimit(self, limiter)
+
+ +
+ +

Callback-based search limit. Search stops when limiter returns true; if +this happens at a leaf the corresponding solution will be rejected.

+
+ + +
+
+
#   + + + def + SearchLog(self, *args) -> 'operations_research::SearchMonitor *': +
+ +
+ View Source +
    def SearchLog(self, *args) -> "operations_research::SearchMonitor *":
+        return _pywrapcp.Solver_SearchLog(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + SearchTrace( + self, + prefix: 'std::string const &' +) -> 'operations_research::SearchMonitor *': +
+ +
+ View Source +
    def SearchTrace(self, prefix: "std::string const &") -> "operations_research::SearchMonitor *":
+        r"""
+        Creates a search monitor that will trace precisely the behavior of the
+        search. Use this only for low level debugging.
+        """
+        return _pywrapcp.Solver_SearchTrace(self, prefix)
+
+ +
+ +

Creates a search monitor that will trace precisely the behavior of the +search. Use this only for low level debugging.

+
+ + +
+
+
#   + + + def + PrintModelVisitor(self) -> 'operations_research::ModelVisitor *': +
+ +
+ View Source +
    def PrintModelVisitor(self) -> "operations_research::ModelVisitor *":
+        r""" Prints the model."""
+        return _pywrapcp.Solver_PrintModelVisitor(self)
+
+ +
+ +

Prints the model.

+
+ + +
+
+
#   + + + def + StatisticsModelVisitor(self) -> 'operations_research::ModelVisitor *': +
+ +
+ View Source +
    def StatisticsModelVisitor(self) -> "operations_research::ModelVisitor *":
+        r""" Displays some nice statistics on the model."""
+        return _pywrapcp.Solver_StatisticsModelVisitor(self)
+
+ +
+ +

Displays some nice statistics on the model.

+
+ + +
+
+
#   + + + def + AssignVariableValue( + self, + var: ortools.constraint_solver.pywrapcp.IntVar, + val: 'int64_t' +) -> 'operations_research::Decision *': +
+ +
+ View Source +
    def AssignVariableValue(self, var: "IntVar", val: "int64_t") -> "operations_research::Decision *":
+        r""" Decisions."""
+        return _pywrapcp.Solver_AssignVariableValue(self, var, val)
+
+ +
+ +

Decisions.

+
+ + +
+
+
#   + + + def + VariableLessOrEqualValue( + self, + var: ortools.constraint_solver.pywrapcp.IntVar, + value: 'int64_t' +) -> 'operations_research::Decision *': +
+ +
+ View Source +
    def VariableLessOrEqualValue(self, var: "IntVar", value: "int64_t") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_VariableLessOrEqualValue(self, var, value)
+
+ +
+ + + +
+
+
#   + + + def + VariableGreaterOrEqualValue( + self, + var: ortools.constraint_solver.pywrapcp.IntVar, + value: 'int64_t' +) -> 'operations_research::Decision *': +
+ +
+ View Source +
    def VariableGreaterOrEqualValue(self, var: "IntVar", value: "int64_t") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_VariableGreaterOrEqualValue(self, var, value)
+
+ +
+ + + +
+
+
#   + + + def + SplitVariableDomain( + self, + var: ortools.constraint_solver.pywrapcp.IntVar, + val: 'int64_t', + start_with_lower_half: bool +) -> 'operations_research::Decision *': +
+ +
+ View Source +
    def SplitVariableDomain(self, var: "IntVar", val: "int64_t", start_with_lower_half: "bool") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_SplitVariableDomain(self, var, val, start_with_lower_half)
+
+ +
+ + + +
+
+
#   + + + def + AssignVariableValueOrFail( + self, + var: ortools.constraint_solver.pywrapcp.IntVar, + value: 'int64_t' +) -> 'operations_research::Decision *': +
+ +
+ View Source +
    def AssignVariableValueOrFail(self, var: "IntVar", value: "int64_t") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_AssignVariableValueOrFail(self, var, value)
+
+ +
+ + + +
+
+
#   + + + def + AssignVariablesValues( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + values: 'std::vector< int64_t > const &' +) -> 'operations_research::Decision *': +
+ +
+ View Source +
    def AssignVariablesValues(self, vars: "std::vector< operations_research::IntVar * > const &", values: "std::vector< int64_t > const &") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_AssignVariablesValues(self, vars, values)
+
+ +
+ + + +
+
+
#   + + + def + FailDecision(self) -> 'operations_research::Decision *': +
+ +
+ View Source +
    def FailDecision(self) -> "operations_research::Decision *":
+        return _pywrapcp.Solver_FailDecision(self)
+
+ +
+ + + +
+
+
#   + + + def + Decision( + self, + apply: 'operations_research::Solver::Action', + refute: 'operations_research::Solver::Action' +) -> 'operations_research::Decision *': +
+ +
+ View Source +
    def Decision(self, apply: "operations_research::Solver::Action", refute: "operations_research::Solver::Action") -> "operations_research::Decision *":
+        return _pywrapcp.Solver_Decision(self, apply, refute)
+
+ +
+ + + +
+
+
#   + + + def + Compose( + self, + dbs: 'std::vector< operations_research::DecisionBuilder * > const &' +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def Compose(self, dbs: "std::vector< operations_research::DecisionBuilder * > const &") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_Compose(self, dbs)
+
+ +
+ + + +
+
+
#   + + + def + Try( + self, + dbs: 'std::vector< operations_research::DecisionBuilder * > const &' +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def Try(self, dbs: "std::vector< operations_research::DecisionBuilder * > const &") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_Try(self, dbs)
+
+ +
+ + + +
+
+
#   + + + def + DefaultPhase(self, *args) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def DefaultPhase(self, *args) -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_DefaultPhase(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + ScheduleOrPostpone( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + est: 'int64_t', + marker: 'int64_t *const' +) -> 'operations_research::Decision *': +
+ +
+ View Source +
    def ScheduleOrPostpone(self, var: "IntervalVar", est: "int64_t", marker: "int64_t *const") -> "operations_research::Decision *":
+        r"""
+        Returns a decision that tries to schedule a task at a given time.
+        On the Apply branch, it will set that interval var as performed and set
+        its start to 'est'. On the Refute branch, it will just update the
+        'marker' to 'est' + 1. This decision is used in the
+        INTERVAL_SET_TIMES_FORWARD strategy.
+        """
+        return _pywrapcp.Solver_ScheduleOrPostpone(self, var, est, marker)
+
+ +
+ +

Returns a decision that tries to schedule a task at a given time. +On the Apply branch, it will set that interval var as performed and set +its start to 'est'. On the Refute branch, it will just update the +'marker' to 'est' + 1. This decision is used in the +INTERVAL_SET_TIMES_FORWARD strategy.

+
+ + +
+
+
#   + + + def + ScheduleOrExpedite( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + est: 'int64_t', + marker: 'int64_t *const' +) -> 'operations_research::Decision *': +
+ +
+ View Source +
    def ScheduleOrExpedite(self, var: "IntervalVar", est: "int64_t", marker: "int64_t *const") -> "operations_research::Decision *":
+        r"""
+        Returns a decision that tries to schedule a task at a given time.
+        On the Apply branch, it will set that interval var as performed and set
+        its end to 'est'. On the Refute branch, it will just update the
+        'marker' to 'est' - 1. This decision is used in the
+        INTERVAL_SET_TIMES_BACKWARD strategy.
+        """
+        return _pywrapcp.Solver_ScheduleOrExpedite(self, var, est, marker)
+
+ +
+ +

Returns a decision that tries to schedule a task at a given time. +On the Apply branch, it will set that interval var as performed and set +its end to 'est'. On the Refute branch, it will just update the +'marker' to 'est' - 1. This decision is used in the +INTERVAL_SET_TIMES_BACKWARD strategy.

+
+ + +
+
+
#   + + + def + RankFirstInterval( + self, + sequence: ortools.constraint_solver.pywrapcp.SequenceVar, + index: int +) -> 'operations_research::Decision *': +
+ +
+ View Source +
    def RankFirstInterval(self, sequence: "SequenceVar", index: "int") -> "operations_research::Decision *":
+        r"""
+        Returns a decision that tries to rank first the ith interval var
+        in the sequence variable.
+        """
+        return _pywrapcp.Solver_RankFirstInterval(self, sequence, index)
+
+ +
+ +

Returns a decision that tries to rank first the ith interval var +in the sequence variable.

+
+ + +
+
+
#   + + + def + RankLastInterval( + self, + sequence: ortools.constraint_solver.pywrapcp.SequenceVar, + index: int +) -> 'operations_research::Decision *': +
+ +
+ View Source +
    def RankLastInterval(self, sequence: "SequenceVar", index: "int") -> "operations_research::Decision *":
+        r"""
+        Returns a decision that tries to rank last the ith interval var
+        in the sequence variable.
+        """
+        return _pywrapcp.Solver_RankLastInterval(self, sequence, index)
+
+ +
+ +

Returns a decision that tries to rank last the ith interval var +in the sequence variable.

+
+ + +
+
+
#   + + + def + Phase(self, *args) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def Phase(self, *args) -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_Phase(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + DecisionBuilderFromAssignment( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment, + db: ortools.constraint_solver.pywrapcp.DecisionBuilder, + vars: 'std::vector< operations_research::IntVar * > const &' +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def DecisionBuilderFromAssignment(self, assignment: "Assignment", db: "DecisionBuilder", vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::DecisionBuilder *":
+        r"""
+        Returns a decision builder for which the left-most leaf corresponds
+        to assignment, the rest of the tree being explored using 'db'.
+        """
+        return _pywrapcp.Solver_DecisionBuilderFromAssignment(self, assignment, db, vars)
+
+ +
+ +

Returns a decision builder for which the left-most leaf corresponds +to assignment, the rest of the tree being explored using 'db'.

+
+ + +
+
+
#   + + + def + ConstraintAdder( + self, + ct: ortools.constraint_solver.pywrapcp.Constraint +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def ConstraintAdder(self, ct: "Constraint") -> "operations_research::DecisionBuilder *":
+        r"""
+        Returns a decision builder that will add the given constraint to
+        the model.
+        """
+        return _pywrapcp.Solver_ConstraintAdder(self, ct)
+
+ +
+ +

Returns a decision builder that will add the given constraint to +the model.

+
+ + +
+
+
#   + + + def + SolveOnce( + self, + db: ortools.constraint_solver.pywrapcp.DecisionBuilder, + monitors: 'std::vector< operations_research::SearchMonitor * > const &' +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def SolveOnce(self, db: "DecisionBuilder", monitors: "std::vector< operations_research::SearchMonitor * > const &") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_SolveOnce(self, db, monitors)
+
+ +
+ + + +
+
+
#   + + + def + NestedOptimize(self, *args) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def NestedOptimize(self, *args) -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_NestedOptimize(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + RestoreAssignment( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def RestoreAssignment(self, assignment: "Assignment") -> "operations_research::DecisionBuilder *":
+        r"""
+        Returns a DecisionBuilder which restores an Assignment
+        (calls void Assignment::Restore())
+        """
+        return _pywrapcp.Solver_RestoreAssignment(self, assignment)
+
+ +
+ +

Returns a DecisionBuilder which restores an Assignment +(calls void Assignment::Restore())

+
+ + +
+
+
#   + + + def + StoreAssignment( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def StoreAssignment(self, assignment: "Assignment") -> "operations_research::DecisionBuilder *":
+        r"""
+        Returns a DecisionBuilder which stores an Assignment
+        (calls void Assignment::Store())
+        """
+        return _pywrapcp.Solver_StoreAssignment(self, assignment)
+
+ +
+ +

Returns a DecisionBuilder which stores an Assignment +(calls void Assignment::Store())

+
+ + +
+
+
#   + + + def + Operator(self, *args) -> 'operations_research::LocalSearchOperator *': +
+ +
+ View Source +
    def Operator(self, *args) -> "operations_research::LocalSearchOperator *":
+        return _pywrapcp.Solver_Operator(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + RandomLnsOperator(self, *args) -> 'operations_research::LocalSearchOperator *': +
+ +
+ View Source +
    def RandomLnsOperator(self, *args) -> "operations_research::LocalSearchOperator *":
+        return _pywrapcp.Solver_RandomLnsOperator(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + MoveTowardTargetOperator(self, *args) -> 'operations_research::LocalSearchOperator *': +
+ +
+ View Source +
    def MoveTowardTargetOperator(self, *args) -> "operations_research::LocalSearchOperator *":
+        r"""
+        *Overload 1:*
+        Creates a local search operator that tries to move the assignment of some
+        variables toward a target. The target is given as an Assignment. This
+        operator generates neighbors in which the only difference compared to the
+        current state is that one variable that belongs to the target assignment
+        is set to its target value.
+
+        |
+
+        *Overload 2:*
+        Creates a local search operator that tries to move the assignment of some
+        variables toward a target. The target is given either as two vectors: a
+        vector of variables and a vector of associated target values. The two
+        vectors should be of the same length. This operator generates neighbors in
+        which the only difference compared to the current state is that one
+        variable that belongs to the given vector is set to its target value.
+        """
+        return _pywrapcp.Solver_MoveTowardTargetOperator(self, *args)
+
+ +
+ +

Overload 1: +Creates a local search operator that tries to move the assignment of some +variables toward a target. The target is given as an Assignment. This +operator generates neighbors in which the only difference compared to the +current state is that one variable that belongs to the target assignment +is set to its target value.

+ +

|

+ +

Overload 2: +Creates a local search operator that tries to move the assignment of some +variables toward a target. The target is given either as two vectors: a +vector of variables and a vector of associated target values. The two +vectors should be of the same length. This operator generates neighbors in +which the only difference compared to the current state is that one +variable that belongs to the given vector is set to its target value.

+
+ + +
+
+
#   + + + def + ConcatenateOperators(self, *args) -> 'operations_research::LocalSearchOperator *': +
+ +
+ View Source +
    def ConcatenateOperators(self, *args) -> "operations_research::LocalSearchOperator *":
+        return _pywrapcp.Solver_ConcatenateOperators(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + RandomConcatenateOperators(self, *args) -> 'operations_research::LocalSearchOperator *': +
+ +
+ View Source +
    def RandomConcatenateOperators(self, *args) -> "operations_research::LocalSearchOperator *":
+        r"""
+        *Overload 1:*
+        Randomized version of local search concatenator; calls a random operator
+        at each call to MakeNextNeighbor().
+
+        |
+
+        *Overload 2:*
+        Randomized version of local search concatenator; calls a random operator
+        at each call to MakeNextNeighbor(). The provided seed is used to
+        initialize the random number generator.
+        """
+        return _pywrapcp.Solver_RandomConcatenateOperators(self, *args)
+
+ +
+ +

Overload 1: +Randomized version of local search concatenator; calls a random operator +at each call to MakeNextNeighbor().

+ +

|

+ +

Overload 2: +Randomized version of local search concatenator; calls a random operator +at each call to MakeNextNeighbor(). The provided seed is used to +initialize the random number generator.

+
+ + +
+
+
#   + + + def + NeighborhoodLimit( + self, + op: ortools.constraint_solver.pywrapcp.LocalSearchOperator, + limit: 'int64_t' +) -> 'operations_research::LocalSearchOperator *': +
+ +
+ View Source +
    def NeighborhoodLimit(self, op: "LocalSearchOperator", limit: "int64_t") -> "operations_research::LocalSearchOperator *":
+        r"""
+        Creates a local search operator that wraps another local search
+        operator and limits the number of neighbors explored (i.e., calls
+        to MakeNextNeighbor from the current solution (between two calls
+        to Start()). When this limit is reached, MakeNextNeighbor()
+        returns false. The counter is cleared when Start() is called.
+        """
+        return _pywrapcp.Solver_NeighborhoodLimit(self, op, limit)
+
+ +
+ +

Creates a local search operator that wraps another local search +operator and limits the number of neighbors explored (i.e., calls +to MakeNextNeighbor from the current solution (between two calls +to Start()). When this limit is reached, MakeNextNeighbor() +returns false. The counter is cleared when Start() is called.

+
+ + +
+
+
#   + + + def + LocalSearchPhase(self, *args) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def LocalSearchPhase(self, *args) -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_LocalSearchPhase(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + LocalSearchPhaseParameters(self, *args) -> 'operations_research::LocalSearchPhaseParameters *': +
+ +
+ View Source +
    def LocalSearchPhaseParameters(self, *args) -> "operations_research::LocalSearchPhaseParameters *":
+        return _pywrapcp.Solver_LocalSearchPhaseParameters(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + SearchDepth(self) -> int: +
+ +
+ View Source +
    def SearchDepth(self) -> "int":
+        r"""
+        Gets the search depth of the current active search. Returns -1 if
+        there is no active search opened.
+        """
+        return _pywrapcp.Solver_SearchDepth(self)
+
+ +
+ +

Gets the search depth of the current active search. Returns -1 if +there is no active search opened.

+
+ + +
+
+
#   + + + def + SearchLeftDepth(self) -> int: +
+ +
+ View Source +
    def SearchLeftDepth(self) -> "int":
+        r"""
+        Gets the search left depth of the current active search. Returns -1 if
+        there is no active search opened.
+        """
+        return _pywrapcp.Solver_SearchLeftDepth(self)
+
+ +
+ +

Gets the search left depth of the current active search. Returns -1 if +there is no active search opened.

+
+ + +
+
+
#   + + + def + SolveDepth(self) -> int: +
+ +
+ View Source +
    def SolveDepth(self) -> "int":
+        r"""
+        Gets the number of nested searches. It returns 0 outside search,
+        1 during the top level search, 2 or more in case of nested searches.
+        """
+        return _pywrapcp.Solver_SolveDepth(self)
+
+ +
+ +

Gets the number of nested searches. It returns 0 outside search, +1 during the top level search, 2 or more in case of nested searches.

+
+ + +
+
+
#   + + + def + Rand64(self, size: 'int64_t') -> 'int64_t': +
+ +
+ View Source +
    def Rand64(self, size: "int64_t") -> "int64_t":
+        r""" Returns a random value between 0 and 'size' - 1;"""
+        return _pywrapcp.Solver_Rand64(self, size)
+
+ +
+ +

Returns a random value between 0 and 'size' - 1;

+
+ + +
+
+
#   + + + def + Rand32(self, size: 'int32_t') -> 'int32_t': +
+ +
+ View Source +
    def Rand32(self, size: "int32_t") -> "int32_t":
+        r""" Returns a random value between 0 and 'size' - 1;"""
+        return _pywrapcp.Solver_Rand32(self, size)
+
+ +
+ +

Returns a random value between 0 and 'size' - 1;

+
+ + +
+
+
#   + + + def + ReSeed(self, seed: 'int32_t') -> 'void': +
+ +
+ View Source +
    def ReSeed(self, seed: "int32_t") -> "void":
+        r""" Reseed the solver random generator."""
+        return _pywrapcp.Solver_ReSeed(self, seed)
+
+ +
+ +

Reseed the solver random generator.

+
+ + +
+
+
#   + + + def + LocalSearchProfile(self) -> 'std::string': +
+ +
+ View Source +
    def LocalSearchProfile(self) -> "std::string":
+        r""" Returns local search profiling information in a human readable format."""
+        return _pywrapcp.Solver_LocalSearchProfile(self)
+
+ +
+ +

Returns local search profiling information in a human readable format.

+
+ + +
+
+
#   + + + def + Constraints(self) -> int: +
+ +
+ View Source +
    def Constraints(self) -> "int":
+        r"""
+        Counts the number of constraints that have been added
+        to the solver before the search.
+        """
+        return _pywrapcp.Solver_Constraints(self)
+
+ +
+ +

Counts the number of constraints that have been added +to the solver before the search.

+
+ + +
+
+
#   + + + def + Accept(self, visitor: 'operations_research::ModelVisitor *const') -> 'void': +
+ +
+ View Source +
    def Accept(self, visitor: "operations_research::ModelVisitor *const") -> "void":
+        r""" Accepts the given model visitor."""
+        return _pywrapcp.Solver_Accept(self, visitor)
+
+ +
+ +

Accepts the given model visitor.

+
+ + +
+
+
#   + + + def + FinishCurrentSearch(self) -> 'void': +
+ +
+ View Source +
    def FinishCurrentSearch(self) -> "void":
+        r""" Tells the solver to kill or restart the current search."""
+        return _pywrapcp.Solver_FinishCurrentSearch(self)
+
+ +
+ +

Tells the solver to kill or restart the current search.

+
+ + +
+
+
#   + + + def + RestartCurrentSearch(self) -> 'void': +
+ +
+ View Source +
    def RestartCurrentSearch(self) -> "void":
+        return _pywrapcp.Solver_RestartCurrentSearch(self)
+
+ +
+ + + +
+
+
#   + + + def + ShouldFail(self) -> 'void': +
+ +
+ View Source +
    def ShouldFail(self) -> "void":
+        r"""
+        These methods are only useful for the SWIG wrappers, which need a way
+        to externally cause the Solver to fail.
+        """
+        return _pywrapcp.Solver_ShouldFail(self)
+
+ +
+ +

These methods are only useful for the SWIG wrappers, which need a way +to externally cause the Solver to fail.

+
+ + +
+
+
#   + + + def + Add(self, ct): +
+ +
+ View Source +
    def Add(self, ct):
+      if isinstance(ct, PyConstraint):
+        self.__python_constraints.append(ct)
+      self.AddConstraint(ct)
+
+ +
+ + + +
+
+
#   + + + def + TreeNoCycle( + self, + nexts: 'std::vector< operations_research::IntVar * > const &', + active: 'std::vector< operations_research::IntVar * > const &', + callback: 'operations_research::Solver::IndexFilter1' = 0 +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def TreeNoCycle(self, nexts: "std::vector< operations_research::IntVar * > const &", active: "std::vector< operations_research::IntVar * > const &", callback: "operations_research::Solver::IndexFilter1"=0) -> "operations_research::Constraint *":
+        return _pywrapcp.Solver_TreeNoCycle(self, nexts, active, callback)
+
+ +
+ + + +
+
+
#   + + + def + SearchLogWithCallback( + self, + period: int, + callback: 'std::function< std::string () >' +) -> 'operations_research::SearchMonitor *': +
+ +
+ View Source +
    def SearchLogWithCallback(self, period: "int", callback: "std::function< std::string () >") -> "operations_research::SearchMonitor *":
+        return _pywrapcp.Solver_SearchLogWithCallback(self, period, callback)
+
+ +
+ + + +
+
+
#   + + + def + ElementFunction( + self, + values: 'std::function< int64_t (int64_t) >', + index: ortools.constraint_solver.pywrapcp.IntVar +) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def ElementFunction(self, values: "std::function< int64_t (int64_t) >", index: "IntVar") -> "operations_research::IntExpr *":
+        return _pywrapcp.Solver_ElementFunction(self, values, index)
+
+ +
+ + + +
+
+
#   + + + def + VarEvalValStrPhase( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + var_evaluator: 'std::function< int64_t (int64_t) >', + val_str: 'operations_research::Solver::IntValueStrategy' +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def VarEvalValStrPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_evaluator: "std::function< int64_t (int64_t) >", val_str: "operations_research::Solver::IntValueStrategy") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarEvalValStrPhase(self, vars, var_evaluator, val_str)
+
+ +
+ + + +
+
+
#   + + + def + VarStrValEvalPhase( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + var_str: 'operations_research::Solver::IntVarStrategy', + val_eval: 'operations_research::Solver::IndexEvaluator2' +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def VarStrValEvalPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_str: "operations_research::Solver::IntVarStrategy", val_eval: "operations_research::Solver::IndexEvaluator2") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarStrValEvalPhase(self, vars, var_str, val_eval)
+
+ +
+ + + +
+
+
#   + + + def + VarEvalValEvalPhase( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + var_eval: 'std::function< int64_t (int64_t) >', + val_eval: 'operations_research::Solver::IndexEvaluator2' +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def VarEvalValEvalPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_eval: "std::function< int64_t (int64_t) >", val_eval: "operations_research::Solver::IndexEvaluator2") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarEvalValEvalPhase(self, vars, var_eval, val_eval)
+
+ +
+ + + +
+
+
#   + + + def + VarStrValEvalTieBreakPhase( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + var_str: 'operations_research::Solver::IntVarStrategy', + val_eval: 'operations_research::Solver::IndexEvaluator2', + tie_breaker: 'std::function< int64_t (int64_t) >' +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def VarStrValEvalTieBreakPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_str: "operations_research::Solver::IntVarStrategy", val_eval: "operations_research::Solver::IndexEvaluator2", tie_breaker: "std::function< int64_t (int64_t) >") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarStrValEvalTieBreakPhase(self, vars, var_str, val_eval, tie_breaker)
+
+ +
+ + + +
+
+
#   + + + def + VarEvalValEvalTieBreakPhase( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + var_eval: 'std::function< int64_t (int64_t) >', + val_eval: 'operations_research::Solver::IndexEvaluator2', + tie_breaker: 'std::function< int64_t (int64_t) >' +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def VarEvalValEvalTieBreakPhase(self, vars: "std::vector< operations_research::IntVar * > const &", var_eval: "std::function< int64_t (int64_t) >", val_eval: "operations_research::Solver::IndexEvaluator2", tie_breaker: "std::function< int64_t (int64_t) >") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_VarEvalValEvalTieBreakPhase(self, vars, var_eval, val_eval, tie_breaker)
+
+ +
+ + + +
+
+
#   + + + def + EvalEvalStrPhase( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + evaluator: 'operations_research::Solver::IndexEvaluator2', + str: 'operations_research::Solver::EvaluatorStrategy' +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def EvalEvalStrPhase(self, vars: "std::vector< operations_research::IntVar * > const &", evaluator: "operations_research::Solver::IndexEvaluator2", str: "operations_research::Solver::EvaluatorStrategy") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_EvalEvalStrPhase(self, vars, evaluator, str)
+
+ +
+ + + +
+
+
#   + + + def + EvalEvalStrTieBreakPhase( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + evaluator: 'operations_research::Solver::IndexEvaluator2', + tie_breaker: 'operations_research::Solver::IndexEvaluator1', + str: 'operations_research::Solver::EvaluatorStrategy' +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def EvalEvalStrTieBreakPhase(self, vars: "std::vector< operations_research::IntVar * > const &", evaluator: "operations_research::Solver::IndexEvaluator2", tie_breaker: "operations_research::Solver::IndexEvaluator1", str: "operations_research::Solver::EvaluatorStrategy") -> "operations_research::DecisionBuilder *":
+        return _pywrapcp.Solver_EvalEvalStrTieBreakPhase(self, vars, evaluator, tie_breaker, str)
+
+ +
+ + + +
+
+
#   + + + def + GuidedLocalSearch(self, *args) -> 'operations_research::SearchMonitor *': +
+ +
+ View Source +
    def GuidedLocalSearch(self, *args) -> "operations_research::SearchMonitor *":
+        return _pywrapcp.Solver_GuidedLocalSearch(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + SumObjectiveFilter( + self, + vars: 'std::vector< operations_research::IntVar * > const &', + values: 'operations_research::Solver::IndexEvaluator2', + filter_enum: 'operations_research::Solver::LocalSearchFilterBound' +) -> 'operations_research::LocalSearchFilter *': +
+ +
+ View Source +
    def SumObjectiveFilter(self, vars: "std::vector< operations_research::IntVar * > const &", values: "operations_research::Solver::IndexEvaluator2", filter_enum: "operations_research::Solver::LocalSearchFilterBound") -> "operations_research::LocalSearchFilter *":
+        return _pywrapcp.Solver_SumObjectiveFilter(self, vars, values, filter_enum)
+
+ +
+ + + +
+
+
+
#   + + + def + Solver_DefaultSolverParameters() -> 'operations_research::ConstraintSolverParameters': +
+ +
+ View Source +
def Solver_DefaultSolverParameters() -> "operations_research::ConstraintSolverParameters":
+    r""" Create a ConstraintSolverParameters proto with all the default values."""
+    return _pywrapcp.Solver_DefaultSolverParameters()
+
+ +
+ +

Create a ConstraintSolverParameters proto with all the default values.

+
+ + +
+
+
#   + + + def + Solver_MemoryUsage() -> 'int64_t': +
+ +
+ View Source +
def Solver_MemoryUsage() -> "int64_t":
+    r""" Current memory usage in bytes"""
+    return _pywrapcp.Solver_MemoryUsage()
+
+ +
+ +

Current memory usage in bytes

+
+ + +
+
+
+ #   + + + class + BaseObject: +
+ +
+ View Source +
class BaseObject(object):
+    r"""
+    A BaseObject is the root of all reversibly allocated objects.
+    A DebugString method and the associated << operator are implemented
+    as a convenience.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self):
+        if self.__class__ == BaseObject:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.BaseObject_swiginit(self, _pywrapcp.new_BaseObject(_self, ))
+    __swig_destroy__ = _pywrapcp.delete_BaseObject
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.BaseObject_DebugString(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.BaseObject___str__(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.BaseObject___repr__(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_BaseObject(self)
+        return weakref.proxy(self)
+
+ +
+ +

A BaseObject is the root of all reversibly allocated objects. +A DebugString method and the associated << operator are implemented +as a convenience.

+
+ + +
+
#   + + + BaseObject() +
+ +
+ View Source +
    def __init__(self):
+        if self.__class__ == BaseObject:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.BaseObject_swiginit(self, _pywrapcp.new_BaseObject(_self, ))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.BaseObject_DebugString(self)
+
+ +
+ + + +
+
+
+
+ #   + + + class + PropagationBaseObject(BaseObject): +
+ +
+ View Source +
class PropagationBaseObject(BaseObject):
+    r"""
+    NOLINT
+    The PropagationBaseObject is a subclass of BaseObject that is also
+    friend to the Solver class. It allows accessing methods useful when
+    writing new constraints or new expressions.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, s: "Solver"):
+        if self.__class__ == PropagationBaseObject:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.PropagationBaseObject_swiginit(self, _pywrapcp.new_PropagationBaseObject(_self, s))
+    __swig_destroy__ = _pywrapcp.delete_PropagationBaseObject
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.PropagationBaseObject_DebugString(self)
+
+    def solver(self) -> "operations_research::Solver *":
+        return _pywrapcp.PropagationBaseObject_solver(self)
+
+    def Name(self) -> "std::string":
+        r""" Object naming."""
+        return _pywrapcp.PropagationBaseObject_Name(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_PropagationBaseObject(self)
+        return weakref.proxy(self)
+
+ +
+ +

NOLINT +The PropagationBaseObject is a subclass of BaseObject that is also +friend to the Solver class. It allows accessing methods useful when +writing new constraints or new expressions.

+
+ + +
+
#   + + + PropagationBaseObject(s: ortools.constraint_solver.pywrapcp.Solver) +
+ +
+ View Source +
    def __init__(self, s: "Solver"):
+        if self.__class__ == PropagationBaseObject:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.PropagationBaseObject_swiginit(self, _pywrapcp.new_PropagationBaseObject(_self, s))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.PropagationBaseObject_DebugString(self)
+
+ +
+ + + +
+
+
#   + + + def + solver(self) -> 'operations_research::Solver *': +
+ +
+ View Source +
    def solver(self) -> "operations_research::Solver *":
+        return _pywrapcp.PropagationBaseObject_solver(self)
+
+ +
+ + + +
+
+
#   + + + def + Name(self) -> 'std::string': +
+ +
+ View Source +
    def Name(self) -> "std::string":
+        r""" Object naming."""
+        return _pywrapcp.PropagationBaseObject_Name(self)
+
+ +
+ +

Object naming.

+
+ + +
+
+
+
+ #   + + + class + Decision(BaseObject): +
+ +
+ View Source +
class Decision(BaseObject):
+    r"""
+    A Decision represents a choice point in the search tree. The two main
+    methods are Apply() to go left, or Refute() to go right.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self):
+        if self.__class__ == Decision:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.Decision_swiginit(self, _pywrapcp.new_Decision(_self, ))
+    __swig_destroy__ = _pywrapcp.delete_Decision
+
+    def ApplyWrapper(self, s: "Solver") -> "void":
+        r""" Apply will be called first when the decision is executed."""
+        return _pywrapcp.Decision_ApplyWrapper(self, s)
+
+    def RefuteWrapper(self, s: "Solver") -> "void":
+        r""" Refute will be called after a backtrack."""
+        return _pywrapcp.Decision_RefuteWrapper(self, s)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.Decision_DebugString(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.Decision___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.Decision___str__(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_Decision(self)
+        return weakref.proxy(self)
+
+ +
+ +

A Decision represents a choice point in the search tree. The two main +methods are Apply() to go left, or Refute() to go right.

+
+ + +
+
#   + + + Decision() +
+ +
+ View Source +
    def __init__(self):
+        if self.__class__ == Decision:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.Decision_swiginit(self, _pywrapcp.new_Decision(_self, ))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + ApplyWrapper(self, s: ortools.constraint_solver.pywrapcp.Solver) -> 'void': +
+ +
+ View Source +
    def ApplyWrapper(self, s: "Solver") -> "void":
+        r""" Apply will be called first when the decision is executed."""
+        return _pywrapcp.Decision_ApplyWrapper(self, s)
+
+ +
+ +

Apply will be called first when the decision is executed.

+
+ + +
+
+
#   + + + def + RefuteWrapper(self, s: ortools.constraint_solver.pywrapcp.Solver) -> 'void': +
+ +
+ View Source +
    def RefuteWrapper(self, s: "Solver") -> "void":
+        r""" Refute will be called after a backtrack."""
+        return _pywrapcp.Decision_RefuteWrapper(self, s)
+
+ +
+ +

Refute will be called after a backtrack.

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.Decision_DebugString(self)
+
+ +
+ + + +
+
+
+
+ #   + + + class + DecisionBuilder(BaseObject): +
+ +
+ View Source +
class DecisionBuilder(BaseObject):
+    r"""
+    A DecisionBuilder is responsible for creating the search tree. The
+    important method is Next(), which returns the next decision to execute.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self):
+        if self.__class__ == DecisionBuilder:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.DecisionBuilder_swiginit(self, _pywrapcp.new_DecisionBuilder(_self, ))
+    __swig_destroy__ = _pywrapcp.delete_DecisionBuilder
+
+    def NextWrapper(self, s: "Solver") -> "operations_research::Decision *":
+        r"""
+        This is the main method of the decision builder class. It must
+        return a decision (an instance of the class Decision). If it
+        returns nullptr, this means that the decision builder has finished
+        its work.
+        """
+        return _pywrapcp.DecisionBuilder_NextWrapper(self, s)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.DecisionBuilder_DebugString(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.DecisionBuilder___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.DecisionBuilder___str__(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_DecisionBuilder(self)
+        return weakref.proxy(self)
+
+ +
+ +

A DecisionBuilder is responsible for creating the search tree. The +important method is Next(), which returns the next decision to execute.

+
+ + +
+
#   + + + DecisionBuilder() +
+ +
+ View Source +
    def __init__(self):
+        if self.__class__ == DecisionBuilder:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.DecisionBuilder_swiginit(self, _pywrapcp.new_DecisionBuilder(_self, ))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + NextWrapper( + self, + s: ortools.constraint_solver.pywrapcp.Solver +) -> 'operations_research::Decision *': +
+ +
+ View Source +
    def NextWrapper(self, s: "Solver") -> "operations_research::Decision *":
+        r"""
+        This is the main method of the decision builder class. It must
+        return a decision (an instance of the class Decision). If it
+        returns nullptr, this means that the decision builder has finished
+        its work.
+        """
+        return _pywrapcp.DecisionBuilder_NextWrapper(self, s)
+
+ +
+ +

This is the main method of the decision builder class. It must +return a decision (an instance of the class Decision). If it +returns nullptr, this means that the decision builder has finished +its work.

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.DecisionBuilder_DebugString(self)
+
+ +
+ + + +
+
+
+
+ #   + + + class + Demon(BaseObject): +
+ +
+ View Source +
class Demon(BaseObject):
+    r"""
+    A Demon is the base element of a propagation queue. It is the main
+      object responsible for implementing the actual propagation
+      of the constraint and pruning the inconsistent values in the domains
+      of the variables. The main concept is that demons are listeners that are
+      attached to the variables and listen to their modifications.
+    There are two methods:
+     - Run() is the actual method called when the demon is processed.
+     - priority() returns its priority. Standard priorities are slow, normal
+       or fast. "immediate" is reserved for variables and is treated separately.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self):
+        r"""
+        This indicates the priority of a demon. Immediate demons are treated
+        separately and corresponds to variables.
+        """
+        if self.__class__ == Demon:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.Demon_swiginit(self, _pywrapcp.new_Demon(_self, ))
+    __swig_destroy__ = _pywrapcp.delete_Demon
+
+    def RunWrapper(self, s: "Solver") -> "void":
+        r""" This is the main callback of the demon."""
+        return _pywrapcp.Demon_RunWrapper(self, s)
+
+    def Priority(self) -> "operations_research::Solver::DemonPriority":
+        r"""
+        This method returns the priority of the demon. Usually a demon is
+        fast, slow or normal. Immediate demons are reserved for internal
+        use to maintain variables.
+        """
+        return _pywrapcp.Demon_Priority(self)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.Demon_DebugString(self)
+
+    def Inhibit(self, s: "Solver") -> "void":
+        r"""
+        This method inhibits the demon in the search tree below the
+        current position.
+        """
+        return _pywrapcp.Demon_Inhibit(self, s)
+
+    def Desinhibit(self, s: "Solver") -> "void":
+        r""" This method un-inhibits the demon that was previously inhibited."""
+        return _pywrapcp.Demon_Desinhibit(self, s)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_Demon(self)
+        return weakref.proxy(self)
+
+ +
+ +

A Demon is the base element of a propagation queue. It is the main + object responsible for implementing the actual propagation + of the constraint and pruning the inconsistent values in the domains + of the variables. The main concept is that demons are listeners that are + attached to the variables and listen to their modifications.

+ +
There are two methods
+ +
+
    +
  • Run() is the actual method called when the demon is processed.
  • +
  • priority() returns its priority. Standard priorities are slow, normal + or fast. "immediate" is reserved for variables and is treated separately.
  • +
+
+
+ + +
+
#   + + + Demon() +
+ +
+ View Source +
    def __init__(self):
+        r"""
+        This indicates the priority of a demon. Immediate demons are treated
+        separately and corresponds to variables.
+        """
+        if self.__class__ == Demon:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.Demon_swiginit(self, _pywrapcp.new_Demon(_self, ))
+
+ +
+ +

This indicates the priority of a demon. Immediate demons are treated +separately and corresponds to variables.

+
+ + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + RunWrapper(self, s: ortools.constraint_solver.pywrapcp.Solver) -> 'void': +
+ +
+ View Source +
    def RunWrapper(self, s: "Solver") -> "void":
+        r""" This is the main callback of the demon."""
+        return _pywrapcp.Demon_RunWrapper(self, s)
+
+ +
+ +

This is the main callback of the demon.

+
+ + +
+
+
#   + + + def + Priority(self) -> 'operations_research::Solver::DemonPriority': +
+ +
+ View Source +
    def Priority(self) -> "operations_research::Solver::DemonPriority":
+        r"""
+        This method returns the priority of the demon. Usually a demon is
+        fast, slow or normal. Immediate demons are reserved for internal
+        use to maintain variables.
+        """
+        return _pywrapcp.Demon_Priority(self)
+
+ +
+ +

This method returns the priority of the demon. Usually a demon is +fast, slow or normal. Immediate demons are reserved for internal +use to maintain variables.

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.Demon_DebugString(self)
+
+ +
+ + + +
+
+
#   + + + def + Inhibit(self, s: ortools.constraint_solver.pywrapcp.Solver) -> 'void': +
+ +
+ View Source +
    def Inhibit(self, s: "Solver") -> "void":
+        r"""
+        This method inhibits the demon in the search tree below the
+        current position.
+        """
+        return _pywrapcp.Demon_Inhibit(self, s)
+
+ +
+ +

This method inhibits the demon in the search tree below the +current position.

+
+ + +
+
+
#   + + + def + Desinhibit(self, s: ortools.constraint_solver.pywrapcp.Solver) -> 'void': +
+ +
+ View Source +
    def Desinhibit(self, s: "Solver") -> "void":
+        r""" This method un-inhibits the demon that was previously inhibited."""
+        return _pywrapcp.Demon_Desinhibit(self, s)
+
+ +
+ +

This method un-inhibits the demon that was previously inhibited.

+
+ + +
+
+
+
+ #   + + + class + Constraint(PropagationBaseObject): +
+ +
+ View Source +
class Constraint(PropagationBaseObject):
+    r"""
+    A constraint is the main modeling object. It provides two methods:
+      - Post() is responsible for creating the demons and attaching them to
+        immediate demons().
+      - InitialPropagate() is called once just after Post and performs
+        the initial propagation. The subsequent propagations will be performed
+        by the demons Posted during the post() method.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, solver: "Solver"):
+        if self.__class__ == Constraint:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.Constraint_swiginit(self, _pywrapcp.new_Constraint(_self, solver))
+    __swig_destroy__ = _pywrapcp.delete_Constraint
+
+    def Post(self) -> "void":
+        r"""
+        This method is called when the constraint is processed by the
+        solver. Its main usage is to attach demons to variables.
+        """
+        return _pywrapcp.Constraint_Post(self)
+
+    def InitialPropagateWrapper(self) -> "void":
+        r"""
+        This method performs the initial propagation of the
+        constraint. It is called just after the post.
+        """
+        return _pywrapcp.Constraint_InitialPropagateWrapper(self)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.Constraint_DebugString(self)
+
+    def Var(self) -> "operations_research::IntVar *":
+        r"""
+        Creates a Boolean variable representing the status of the constraint
+        (false = constraint is violated, true = constraint is satisfied). It
+        returns nullptr if the constraint does not support this API.
+        """
+        return _pywrapcp.Constraint_Var(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.Constraint___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.Constraint___str__(self)
+
+    def __add__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___add__(self, *args)
+
+    def __radd__(self, v: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___radd__(self, v)
+
+    def __sub__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___sub__(self, *args)
+
+    def __rsub__(self, v: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___rsub__(self, v)
+
+    def __mul__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___mul__(self, *args)
+
+    def __rmul__(self, v: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___rmul__(self, v)
+
+    def __floordiv__(self, v: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___floordiv__(self, v)
+
+    def __neg__(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___neg__(self)
+
+    def __abs__(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint___abs__(self)
+
+    def Square(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint_Square(self)
+
+    def __eq__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint___eq__(self, *args)
+
+    def __ne__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint___ne__(self, *args)
+
+    def __ge__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint___ge__(self, *args)
+
+    def __gt__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint___gt__(self, *args)
+
+    def __le__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint___le__(self, *args)
+
+    def __lt__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint___lt__(self, *args)
+
+    def MapTo(self, vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint_MapTo(self, vars)
+
+    def IndexOf(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint_IndexOf(self, *args)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_Constraint(self)
+        return weakref.proxy(self)
+
+ +
+ +

A constraint is the main modeling object. It provides two methods:

+ +
    +
  • Post() is responsible for creating the demons and attaching them to +immediate demons().
  • +
  • InitialPropagate() is called once just after Post and performs +the initial propagation. The subsequent propagations will be performed +by the demons Posted during the post() method.
  • +
+
+ + +
+ + +
+ View Source +
    def __init__(self, solver: "Solver"):
+        if self.__class__ == Constraint:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.Constraint_swiginit(self, _pywrapcp.new_Constraint(_self, solver))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Post(self) -> 'void': +
+ +
+ View Source +
    def Post(self) -> "void":
+        r"""
+        This method is called when the constraint is processed by the
+        solver. Its main usage is to attach demons to variables.
+        """
+        return _pywrapcp.Constraint_Post(self)
+
+ +
+ +

This method is called when the constraint is processed by the +solver. Its main usage is to attach demons to variables.

+
+ + +
+
+
#   + + + def + InitialPropagateWrapper(self) -> 'void': +
+ +
+ View Source +
    def InitialPropagateWrapper(self) -> "void":
+        r"""
+        This method performs the initial propagation of the
+        constraint. It is called just after the post.
+        """
+        return _pywrapcp.Constraint_InitialPropagateWrapper(self)
+
+ +
+ +

This method performs the initial propagation of the +constraint. It is called just after the post.

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.Constraint_DebugString(self)
+
+ +
+ + + +
+
+
#   + + + def + Var(self) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def Var(self) -> "operations_research::IntVar *":
+        r"""
+        Creates a Boolean variable representing the status of the constraint
+        (false = constraint is violated, true = constraint is satisfied). It
+        returns nullptr if the constraint does not support this API.
+        """
+        return _pywrapcp.Constraint_Var(self)
+
+ +
+ +

Creates a Boolean variable representing the status of the constraint +(false = constraint is violated, true = constraint is satisfied). It +returns nullptr if the constraint does not support this API.

+
+ + +
+
+
#   + + + def + Square(self) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def Square(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint_Square(self)
+
+ +
+ + + +
+
+
#   + + + def + MapTo( + self, + vars: 'std::vector< operations_research::IntVar * > const &' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def MapTo(self, vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        return _pywrapcp.Constraint_MapTo(self, vars)
+
+ +
+ + + +
+
+
#   + + + def + IndexOf(self, *args) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def IndexOf(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.Constraint_IndexOf(self, *args)
+
+ +
+ + + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + SearchMonitor(BaseObject): +
+ +
+ View Source +
class SearchMonitor(BaseObject):
+    r""" A search monitor is a simple set of callbacks to monitor all search events"""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, s: "Solver"):
+        if self.__class__ == SearchMonitor:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.SearchMonitor_swiginit(self, _pywrapcp.new_SearchMonitor(_self, s))
+    __swig_destroy__ = _pywrapcp.delete_SearchMonitor
+
+    def EnterSearch(self) -> "void":
+        r""" Beginning of the search."""
+        return _pywrapcp.SearchMonitor_EnterSearch(self)
+
+    def RestartSearch(self) -> "void":
+        r""" Restart the search."""
+        return _pywrapcp.SearchMonitor_RestartSearch(self)
+
+    def ExitSearch(self) -> "void":
+        r""" End of the search."""
+        return _pywrapcp.SearchMonitor_ExitSearch(self)
+
+    def BeginNextDecision(self, b: "DecisionBuilder") -> "void":
+        r""" Before calling DecisionBuilder::Next."""
+        return _pywrapcp.SearchMonitor_BeginNextDecision(self, b)
+
+    def EndNextDecision(self, b: "DecisionBuilder", d: "Decision") -> "void":
+        r""" After calling DecisionBuilder::Next, along with the returned decision."""
+        return _pywrapcp.SearchMonitor_EndNextDecision(self, b, d)
+
+    def ApplyDecision(self, d: "Decision") -> "void":
+        r""" Before applying the decision."""
+        return _pywrapcp.SearchMonitor_ApplyDecision(self, d)
+
+    def RefuteDecision(self, d: "Decision") -> "void":
+        r""" Before refuting the decision."""
+        return _pywrapcp.SearchMonitor_RefuteDecision(self, d)
+
+    def AfterDecision(self, d: "Decision", apply: "bool") -> "void":
+        r"""
+        Just after refuting or applying the decision, apply is true after Apply.
+        This is called only if the Apply() or Refute() methods have not failed.
+        """
+        return _pywrapcp.SearchMonitor_AfterDecision(self, d, apply)
+
+    def BeginFail(self) -> "void":
+        r""" Just when the failure occurs."""
+        return _pywrapcp.SearchMonitor_BeginFail(self)
+
+    def EndFail(self) -> "void":
+        r""" After completing the backtrack."""
+        return _pywrapcp.SearchMonitor_EndFail(self)
+
+    def BeginInitialPropagation(self) -> "void":
+        r""" Before the initial propagation."""
+        return _pywrapcp.SearchMonitor_BeginInitialPropagation(self)
+
+    def EndInitialPropagation(self) -> "void":
+        r""" After the initial propagation."""
+        return _pywrapcp.SearchMonitor_EndInitialPropagation(self)
+
+    def AcceptSolution(self) -> "bool":
+        r"""
+        This method is called when a solution is found. It asserts whether the
+        solution is valid. A value of false indicates that the solution
+        should be discarded.
+        """
+        return _pywrapcp.SearchMonitor_AcceptSolution(self)
+
+    def AtSolution(self) -> "bool":
+        r"""
+        This method is called when a valid solution is found. If the
+        return value is true, then search will resume after. If the result
+        is false, then search will stop there.
+        """
+        return _pywrapcp.SearchMonitor_AtSolution(self)
+
+    def NoMoreSolutions(self) -> "void":
+        r""" When the search tree is finished."""
+        return _pywrapcp.SearchMonitor_NoMoreSolutions(self)
+
+    def LocalOptimum(self) -> "bool":
+        r"""
+        When a local optimum is reached. If 'true' is returned, the last solution
+        is discarded and the search proceeds with the next one.
+        """
+        return _pywrapcp.SearchMonitor_LocalOptimum(self)
+
+    def AcceptDelta(self, delta: "Assignment", deltadelta: "Assignment") -> "bool":
+        
+        return _pywrapcp.SearchMonitor_AcceptDelta(self, delta, deltadelta)
+
+    def AcceptNeighbor(self) -> "void":
+        r""" After accepting a neighbor during local search."""
+        return _pywrapcp.SearchMonitor_AcceptNeighbor(self)
+
+    def solver(self) -> "operations_research::Solver *":
+        return _pywrapcp.SearchMonitor_solver(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.SearchMonitor___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.SearchMonitor___str__(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_SearchMonitor(self)
+        return weakref.proxy(self)
+
+ +
+ +

A search monitor is a simple set of callbacks to monitor all search events

+
+ + +
+ + +
+ View Source +
    def __init__(self, s: "Solver"):
+        if self.__class__ == SearchMonitor:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.SearchMonitor_swiginit(self, _pywrapcp.new_SearchMonitor(_self, s))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + EnterSearch(self) -> 'void': +
+ +
+ View Source +
    def EnterSearch(self) -> "void":
+        r""" Beginning of the search."""
+        return _pywrapcp.SearchMonitor_EnterSearch(self)
+
+ +
+ +

Beginning of the search.

+
+ + +
+
+
#   + + + def + RestartSearch(self) -> 'void': +
+ +
+ View Source +
    def RestartSearch(self) -> "void":
+        r""" Restart the search."""
+        return _pywrapcp.SearchMonitor_RestartSearch(self)
+
+ +
+ +

Restart the search.

+
+ + +
+
+
#   + + + def + ExitSearch(self) -> 'void': +
+ +
+ View Source +
    def ExitSearch(self) -> "void":
+        r""" End of the search."""
+        return _pywrapcp.SearchMonitor_ExitSearch(self)
+
+ +
+ +

End of the search.

+
+ + +
+
+
#   + + + def + BeginNextDecision( + self, + b: ortools.constraint_solver.pywrapcp.DecisionBuilder +) -> 'void': +
+ +
+ View Source +
    def BeginNextDecision(self, b: "DecisionBuilder") -> "void":
+        r""" Before calling DecisionBuilder::Next."""
+        return _pywrapcp.SearchMonitor_BeginNextDecision(self, b)
+
+ +
+ +

Before calling DecisionBuilder::Next.

+
+ + +
+
+
#   + + + def + EndNextDecision( + self, + b: ortools.constraint_solver.pywrapcp.DecisionBuilder, + d: ortools.constraint_solver.pywrapcp.Decision +) -> 'void': +
+ +
+ View Source +
    def EndNextDecision(self, b: "DecisionBuilder", d: "Decision") -> "void":
+        r""" After calling DecisionBuilder::Next, along with the returned decision."""
+        return _pywrapcp.SearchMonitor_EndNextDecision(self, b, d)
+
+ +
+ +

After calling DecisionBuilder::Next, along with the returned decision.

+
+ + +
+
+
#   + + + def + ApplyDecision(self, d: ortools.constraint_solver.pywrapcp.Decision) -> 'void': +
+ +
+ View Source +
    def ApplyDecision(self, d: "Decision") -> "void":
+        r""" Before applying the decision."""
+        return _pywrapcp.SearchMonitor_ApplyDecision(self, d)
+
+ +
+ +

Before applying the decision.

+
+ + +
+
+
#   + + + def + RefuteDecision(self, d: ortools.constraint_solver.pywrapcp.Decision) -> 'void': +
+ +
+ View Source +
    def RefuteDecision(self, d: "Decision") -> "void":
+        r""" Before refuting the decision."""
+        return _pywrapcp.SearchMonitor_RefuteDecision(self, d)
+
+ +
+ +

Before refuting the decision.

+
+ + +
+
+
#   + + + def + AfterDecision( + self, + d: ortools.constraint_solver.pywrapcp.Decision, + apply: bool +) -> 'void': +
+ +
+ View Source +
    def AfterDecision(self, d: "Decision", apply: "bool") -> "void":
+        r"""
+        Just after refuting or applying the decision, apply is true after Apply.
+        This is called only if the Apply() or Refute() methods have not failed.
+        """
+        return _pywrapcp.SearchMonitor_AfterDecision(self, d, apply)
+
+ +
+ +

Just after refuting or applying the decision, apply is true after Apply. +This is called only if the Apply() or Refute() methods have not failed.

+
+ + +
+
+
#   + + + def + BeginFail(self) -> 'void': +
+ +
+ View Source +
    def BeginFail(self) -> "void":
+        r""" Just when the failure occurs."""
+        return _pywrapcp.SearchMonitor_BeginFail(self)
+
+ +
+ +

Just when the failure occurs.

+
+ + +
+
+
#   + + + def + EndFail(self) -> 'void': +
+ +
+ View Source +
    def EndFail(self) -> "void":
+        r""" After completing the backtrack."""
+        return _pywrapcp.SearchMonitor_EndFail(self)
+
+ +
+ +

After completing the backtrack.

+
+ + +
+
+
#   + + + def + BeginInitialPropagation(self) -> 'void': +
+ +
+ View Source +
    def BeginInitialPropagation(self) -> "void":
+        r""" Before the initial propagation."""
+        return _pywrapcp.SearchMonitor_BeginInitialPropagation(self)
+
+ +
+ +

Before the initial propagation.

+
+ + +
+
+
#   + + + def + EndInitialPropagation(self) -> 'void': +
+ +
+ View Source +
    def EndInitialPropagation(self) -> "void":
+        r""" After the initial propagation."""
+        return _pywrapcp.SearchMonitor_EndInitialPropagation(self)
+
+ +
+ +

After the initial propagation.

+
+ + +
+
+
#   + + + def + AcceptSolution(self) -> bool: +
+ +
+ View Source +
    def AcceptSolution(self) -> "bool":
+        r"""
+        This method is called when a solution is found. It asserts whether the
+        solution is valid. A value of false indicates that the solution
+        should be discarded.
+        """
+        return _pywrapcp.SearchMonitor_AcceptSolution(self)
+
+ +
+ +

This method is called when a solution is found. It asserts whether the +solution is valid. A value of false indicates that the solution +should be discarded.

+
+ + +
+
+
#   + + + def + AtSolution(self) -> bool: +
+ +
+ View Source +
    def AtSolution(self) -> "bool":
+        r"""
+        This method is called when a valid solution is found. If the
+        return value is true, then search will resume after. If the result
+        is false, then search will stop there.
+        """
+        return _pywrapcp.SearchMonitor_AtSolution(self)
+
+ +
+ +

This method is called when a valid solution is found. If the +return value is true, then search will resume after. If the result +is false, then search will stop there.

+
+ + +
+
+
#   + + + def + NoMoreSolutions(self) -> 'void': +
+ +
+ View Source +
    def NoMoreSolutions(self) -> "void":
+        r""" When the search tree is finished."""
+        return _pywrapcp.SearchMonitor_NoMoreSolutions(self)
+
+ +
+ +

When the search tree is finished.

+
+ + +
+
+
#   + + + def + LocalOptimum(self) -> bool: +
+ +
+ View Source +
    def LocalOptimum(self) -> "bool":
+        r"""
+        When a local optimum is reached. If 'true' is returned, the last solution
+        is discarded and the search proceeds with the next one.
+        """
+        return _pywrapcp.SearchMonitor_LocalOptimum(self)
+
+ +
+ +

When a local optimum is reached. If 'true' is returned, the last solution +is discarded and the search proceeds with the next one.

+
+ + +
+
+
#   + + + def + AcceptDelta( + self, + delta: ortools.constraint_solver.pywrapcp.Assignment, + deltadelta: ortools.constraint_solver.pywrapcp.Assignment +) -> bool: +
+ +
+ View Source +
    def AcceptDelta(self, delta: "Assignment", deltadelta: "Assignment") -> "bool":
+        
+        return _pywrapcp.SearchMonitor_AcceptDelta(self, delta, deltadelta)
+
+ +
+ + + +
+
+
#   + + + def + AcceptNeighbor(self) -> 'void': +
+ +
+ View Source +
    def AcceptNeighbor(self) -> "void":
+        r""" After accepting a neighbor during local search."""
+        return _pywrapcp.SearchMonitor_AcceptNeighbor(self)
+
+ +
+ +

After accepting a neighbor during local search.

+
+ + +
+
+
#   + + + def + solver(self) -> 'operations_research::Solver *': +
+ +
+ View Source +
    def solver(self) -> "operations_research::Solver *":
+        return _pywrapcp.SearchMonitor_solver(self)
+
+ +
+ + + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + IntExpr(PropagationBaseObject): +
+ +
+ View Source +
class IntExpr(PropagationBaseObject):
+    r"""
+    The class IntExpr is the base of all integer expressions in
+    constraint programming.
+    It contains the basic protocol for an expression:
+      - setting and modifying its bound
+      - querying if it is bound
+      - listening to events modifying its bounds
+      - casting it into a variable (instance of IntVar)
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+    def Min(self) -> "int64_t":
+        return _pywrapcp.IntExpr_Min(self)
+
+    def SetMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntExpr_SetMin(self, m)
+
+    def Max(self) -> "int64_t":
+        return _pywrapcp.IntExpr_Max(self)
+
+    def SetMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntExpr_SetMax(self, m)
+
+    def SetRange(self, l: "int64_t", u: "int64_t") -> "void":
+        r""" This method sets both the min and the max of the expression."""
+        return _pywrapcp.IntExpr_SetRange(self, l, u)
+
+    def SetValue(self, v: "int64_t") -> "void":
+        r""" This method sets the value of the expression."""
+        return _pywrapcp.IntExpr_SetValue(self, v)
+
+    def Bound(self) -> "bool":
+        r""" Returns true if the min and the max of the expression are equal."""
+        return _pywrapcp.IntExpr_Bound(self)
+
+    def IsVar(self) -> "bool":
+        r""" Returns true if the expression is indeed a variable."""
+        return _pywrapcp.IntExpr_IsVar(self)
+
+    def Var(self) -> "operations_research::IntVar *":
+        r""" Creates a variable from the expression."""
+        return _pywrapcp.IntExpr_Var(self)
+
+    def VarWithName(self, name: "std::string const &") -> "operations_research::IntVar *":
+        r"""
+        Creates a variable from the expression and set the name of the
+        resulting var. If the expression is already a variable, then it
+        will set the name of the expression, possibly overwriting it.
+        This is just a shortcut to Var() followed by set_name().
+        """
+        return _pywrapcp.IntExpr_VarWithName(self, name)
+
+    def WhenRange(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        Attach a demon that will watch the min or the max of the expression.
+
+        |
+
+        *Overload 2:*
+        Attach a demon that will watch the min or the max of the expression.
+        """
+        return _pywrapcp.IntExpr_WhenRange(self, *args)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.IntExpr___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.IntExpr___str__(self)
+
+    def __add__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___add__(self, *args)
+
+    def __radd__(self, v: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___radd__(self, v)
+
+    def __sub__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___sub__(self, *args)
+
+    def __rsub__(self, v: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___rsub__(self, v)
+
+    def __mul__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___mul__(self, *args)
+
+    def __rmul__(self, v: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___rmul__(self, v)
+
+    def __floordiv__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___floordiv__(self, *args)
+
+    def __mod__(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___mod__(self, *args)
+
+    def __neg__(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___neg__(self)
+
+    def __abs__(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr___abs__(self)
+
+    def Square(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr_Square(self)
+
+    def __eq__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr___eq__(self, *args)
+
+    def __ne__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr___ne__(self, *args)
+
+    def __ge__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr___ge__(self, *args)
+
+    def __gt__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr___gt__(self, *args)
+
+    def __le__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr___le__(self, *args)
+
+    def __lt__(self, *args) -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr___lt__(self, *args)
+
+    def MapTo(self, vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr_MapTo(self, vars)
+
+    def IndexOf(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr_IndexOf(self, *args)
+
+    def IsMember(self, values: "std::vector< int64_t > const &") -> "operations_research::IntVar *":
+        return _pywrapcp.IntExpr_IsMember(self, values)
+
+    def Member(self, values: "std::vector< int64_t > const &") -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr_Member(self, values)
+
+    def NotMember(self, starts: "std::vector< int64_t > const &", ends: "std::vector< int64_t > const &") -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr_NotMember(self, starts, ends)
+
+ +
+ +

The class IntExpr is the base of all integer expressions in +constraint programming.

+ +
It contains the basic protocol for an expression
+ +
+
    +
  • setting and modifying its bound
  • +
  • querying if it is bound
  • +
  • listening to events modifying its bounds
  • +
  • casting it into a variable (instance of IntVar)
  • +
+
+
+ + +
+
#   + + + IntExpr(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Min(self) -> 'int64_t': +
+ +
+ View Source +
    def Min(self) -> "int64_t":
+        return _pywrapcp.IntExpr_Min(self)
+
+ +
+ + + +
+
+
#   + + + def + SetMin(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntExpr_SetMin(self, m)
+
+ +
+ + + +
+
+
#   + + + def + Max(self) -> 'int64_t': +
+ +
+ View Source +
    def Max(self) -> "int64_t":
+        return _pywrapcp.IntExpr_Max(self)
+
+ +
+ + + +
+
+
#   + + + def + SetMax(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntExpr_SetMax(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetRange(self, l: 'int64_t', u: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetRange(self, l: "int64_t", u: "int64_t") -> "void":
+        r""" This method sets both the min and the max of the expression."""
+        return _pywrapcp.IntExpr_SetRange(self, l, u)
+
+ +
+ +

This method sets both the min and the max of the expression.

+
+ + +
+
+
#   + + + def + SetValue(self, v: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetValue(self, v: "int64_t") -> "void":
+        r""" This method sets the value of the expression."""
+        return _pywrapcp.IntExpr_SetValue(self, v)
+
+ +
+ +

This method sets the value of the expression.

+
+ + +
+
+
#   + + + def + Bound(self) -> bool: +
+ +
+ View Source +
    def Bound(self) -> "bool":
+        r""" Returns true if the min and the max of the expression are equal."""
+        return _pywrapcp.IntExpr_Bound(self)
+
+ +
+ +

Returns true if the min and the max of the expression are equal.

+
+ + +
+
+
#   + + + def + IsVar(self) -> bool: +
+ +
+ View Source +
    def IsVar(self) -> "bool":
+        r""" Returns true if the expression is indeed a variable."""
+        return _pywrapcp.IntExpr_IsVar(self)
+
+ +
+ +

Returns true if the expression is indeed a variable.

+
+ + +
+
+
#   + + + def + Var(self) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def Var(self) -> "operations_research::IntVar *":
+        r""" Creates a variable from the expression."""
+        return _pywrapcp.IntExpr_Var(self)
+
+ +
+ +

Creates a variable from the expression.

+
+ + +
+
+
#   + + + def + VarWithName(self, name: 'std::string const &') -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def VarWithName(self, name: "std::string const &") -> "operations_research::IntVar *":
+        r"""
+        Creates a variable from the expression and set the name of the
+        resulting var. If the expression is already a variable, then it
+        will set the name of the expression, possibly overwriting it.
+        This is just a shortcut to Var() followed by set_name().
+        """
+        return _pywrapcp.IntExpr_VarWithName(self, name)
+
+ +
+ +

Creates a variable from the expression and set the name of the +resulting var. If the expression is already a variable, then it +will set the name of the expression, possibly overwriting it. +This is just a shortcut to Var() followed by set_name().

+
+ + +
+
+
#   + + + def + WhenRange(self, *args) -> 'void': +
+ +
+ View Source +
    def WhenRange(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        Attach a demon that will watch the min or the max of the expression.
+
+        |
+
+        *Overload 2:*
+        Attach a demon that will watch the min or the max of the expression.
+        """
+        return _pywrapcp.IntExpr_WhenRange(self, *args)
+
+ +
+ +

Overload 1: +Attach a demon that will watch the min or the max of the expression.

+ +

|

+ +

Overload 2: +Attach a demon that will watch the min or the max of the expression.

+
+ + +
+
+
#   + + + def + Square(self) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def Square(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr_Square(self)
+
+ +
+ + + +
+
+
#   + + + def + MapTo( + self, + vars: 'std::vector< operations_research::IntVar * > const &' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def MapTo(self, vars: "std::vector< operations_research::IntVar * > const &") -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr_MapTo(self, vars)
+
+ +
+ + + +
+
+
#   + + + def + IndexOf(self, *args) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def IndexOf(self, *args) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntExpr_IndexOf(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + IsMember( + self, + values: 'std::vector< int64_t > const &' +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def IsMember(self, values: "std::vector< int64_t > const &") -> "operations_research::IntVar *":
+        return _pywrapcp.IntExpr_IsMember(self, values)
+
+ +
+ + + +
+
+
#   + + + def + Member( + self, + values: 'std::vector< int64_t > const &' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def Member(self, values: "std::vector< int64_t > const &") -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr_Member(self, values)
+
+ +
+ + + +
+
+
#   + + + def + NotMember( + self, + starts: 'std::vector< int64_t > const &', + ends: 'std::vector< int64_t > const &' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def NotMember(self, starts: "std::vector< int64_t > const &", ends: "std::vector< int64_t > const &") -> "operations_research::Constraint *":
+        return _pywrapcp.IntExpr_NotMember(self, starts, ends)
+
+ +
+ + + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + IntVarIterator(BaseObject): +
+ +
+ View Source +
class IntVarIterator(BaseObject):
+    r"""
+     The class Iterator has two direct subclasses. HoleIterators
+     iterates over all holes, that is value removed between the
+     current min and max of the variable since the last time the
+     variable was processed in the queue. DomainIterators iterates
+     over all elements of the variable domain. Both iterators are not
+     robust to domain changes. Hole iterators can also report values outside
+     the current min and max of the variable.
+     HoleIterators should only be called from a demon attached to the
+     variable that has created this iterator.
+     IntVar* current_var;
+     std::unique_ptr<IntVarIterator> it(current_var->MakeHoleIterator(false));
+     for (const int64_t hole : InitAndGetValues(it)) {
+    use the hole
+     }
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def Init(self) -> "void":
+        r""" This method must be called before each loop."""
+        return _pywrapcp.IntVarIterator_Init(self)
+
+    def Ok(self) -> "bool":
+        r""" This method indicates if we can call Value() or not."""
+        return _pywrapcp.IntVarIterator_Ok(self)
+
+    def Value(self) -> "int64_t":
+        r""" This method returns the current value of the iterator."""
+        return _pywrapcp.IntVarIterator_Value(self)
+
+    def Next(self) -> "void":
+        r""" This method moves the iterator to the next value."""
+        return _pywrapcp.IntVarIterator_Next(self)
+
+    def DebugString(self) -> "std::string":
+        r""" Pretty Print."""
+        return _pywrapcp.IntVarIterator_DebugString(self)
+
+    def __iter__(self):
+      self.Init()
+      return self
+
+    def next(self):
+      if self.Ok():
+        result = self.Value()
+        self.Next()
+        return result
+      else:
+        raise StopIteration()
+
+    def __next__(self):
+      return self.next()
+
+ +
+ +

The class Iterator has two direct subclasses. HoleIterators + iterates over all holes, that is value removed between the + current min and max of the variable since the last time the + variable was processed in the queue. DomainIterators iterates + over all elements of the variable domain. Both iterators are not + robust to domain changes. Hole iterators can also report values outside + the current min and max of the variable. + HoleIterators should only be called from a demon attached to the + variable that has created this iterator. + IntVar* current_var; + std::unique_ptr it(current_var->MakeHoleIterator(false)); + for (const int64_t hole : InitAndGetValues(it)) { +use the hole + }

+
+ + +
+
#   + + + IntVarIterator(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Init(self) -> 'void': +
+ +
+ View Source +
    def Init(self) -> "void":
+        r""" This method must be called before each loop."""
+        return _pywrapcp.IntVarIterator_Init(self)
+
+ +
+ +

This method must be called before each loop.

+
+ + +
+
+
#   + + + def + Ok(self) -> bool: +
+ +
+ View Source +
    def Ok(self) -> "bool":
+        r""" This method indicates if we can call Value() or not."""
+        return _pywrapcp.IntVarIterator_Ok(self)
+
+ +
+ +

This method indicates if we can call Value() or not.

+
+ + +
+
+
#   + + + def + Value(self) -> 'int64_t': +
+ +
+ View Source +
    def Value(self) -> "int64_t":
+        r""" This method returns the current value of the iterator."""
+        return _pywrapcp.IntVarIterator_Value(self)
+
+ +
+ +

This method returns the current value of the iterator.

+
+ + +
+
+
#   + + + def + Next(self) -> 'void': +
+ +
+ View Source +
    def Next(self) -> "void":
+        r""" This method moves the iterator to the next value."""
+        return _pywrapcp.IntVarIterator_Next(self)
+
+ +
+ +

This method moves the iterator to the next value.

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        r""" Pretty Print."""
+        return _pywrapcp.IntVarIterator_DebugString(self)
+
+ +
+ +

Pretty Print.

+
+ + +
+
+
#   + + + def + next(self): +
+ +
+ View Source +
    def next(self):
+      if self.Ok():
+        result = self.Value()
+        self.Next()
+        return result
+      else:
+        raise StopIteration()
+
+ +
+ + + +
+
+
+
+ #   + + + class + IntVar(IntExpr): +
+ +
+ View Source +
class IntVar(IntExpr):
+    r"""
+    The class IntVar is a subset of IntExpr. In addition to the
+    IntExpr protocol, it offers persistence, removing values from the domains,
+    and a finer model for events.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+    def IsVar(self) -> "bool":
+        return _pywrapcp.IntVar_IsVar(self)
+
+    def Var(self) -> "operations_research::IntVar *":
+        return _pywrapcp.IntVar_Var(self)
+
+    def Value(self) -> "int64_t":
+        r"""
+        This method returns the value of the variable. This method checks
+        before that the variable is bound.
+        """
+        return _pywrapcp.IntVar_Value(self)
+
+    def RemoveValue(self, v: "int64_t") -> "void":
+        r""" This method removes the value 'v' from the domain of the variable."""
+        return _pywrapcp.IntVar_RemoveValue(self, v)
+
+    def RemoveInterval(self, l: "int64_t", u: "int64_t") -> "void":
+        r"""
+        This method removes the interval 'l' .. 'u' from the domain of
+        the variable. It assumes that 'l' <= 'u'.
+        """
+        return _pywrapcp.IntVar_RemoveInterval(self, l, u)
+
+    def RemoveValues(self, values: "std::vector< int64_t > const &") -> "void":
+        r""" This method remove the values from the domain of the variable."""
+        return _pywrapcp.IntVar_RemoveValues(self, values)
+
+    def SetValues(self, values: "std::vector< int64_t > const &") -> "void":
+        r""" This method intersects the current domain with the values in the array."""
+        return _pywrapcp.IntVar_SetValues(self, values)
+
+    def WhenBound(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        This method attaches a demon that will be awakened when the
+        variable is bound.
+
+        |
+
+        *Overload 2:*
+        This method attaches a closure that will be awakened when the
+        variable is bound.
+        """
+        return _pywrapcp.IntVar_WhenBound(self, *args)
+
+    def WhenDomain(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        This method attaches a demon that will watch any domain
+        modification of the domain of the variable.
+
+        |
+
+        *Overload 2:*
+        This method attaches a closure that will watch any domain
+        modification of the domain of the variable.
+        """
+        return _pywrapcp.IntVar_WhenDomain(self, *args)
+
+    def Size(self) -> "uint64_t":
+        r""" This method returns the number of values in the domain of the variable."""
+        return _pywrapcp.IntVar_Size(self)
+
+    def Contains(self, v: "int64_t") -> "bool":
+        r"""
+        This method returns whether the value 'v' is in the domain of the
+        variable.
+        """
+        return _pywrapcp.IntVar_Contains(self, v)
+
+    def HoleIteratorAux(self, reversible: "bool") -> "operations_research::IntVarIterator *":
+        r"""
+        Creates a hole iterator. When 'reversible' is false, the returned
+        object is created on the normal C++ heap and the solver does NOT
+        take ownership of the object.
+        """
+        return _pywrapcp.IntVar_HoleIteratorAux(self, reversible)
+
+    def DomainIteratorAux(self, reversible: "bool") -> "operations_research::IntVarIterator *":
+        r"""
+        Creates a domain iterator. When 'reversible' is false, the
+        returned object is created on the normal C++ heap and the solver
+        does NOT take ownership of the object.
+        """
+        return _pywrapcp.IntVar_DomainIteratorAux(self, reversible)
+
+    def OldMin(self) -> "int64_t":
+        r""" Returns the previous min."""
+        return _pywrapcp.IntVar_OldMin(self)
+
+    def OldMax(self) -> "int64_t":
+        r""" Returns the previous max."""
+        return _pywrapcp.IntVar_OldMax(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.IntVar___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.IntVar___str__(self)
+
+    def DomainIterator(self):
+      return iter(self.DomainIteratorAux(False))
+
+    def HoleIterator(self):
+      return iter(self.HoleIteratorAux(False))
+
+ +
+ +

The class IntVar is a subset of IntExpr. In addition to the +IntExpr protocol, it offers persistence, removing values from the domains, +and a finer model for events.

+
+ + +
+
#   + + + IntVar(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + IsVar(self) -> bool: +
+ +
+ View Source +
    def IsVar(self) -> "bool":
+        return _pywrapcp.IntVar_IsVar(self)
+
+ +
+ +

Returns true if the expression is indeed a variable.

+
+ + +
+
+
#   + + + def + Var(self) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def Var(self) -> "operations_research::IntVar *":
+        return _pywrapcp.IntVar_Var(self)
+
+ +
+ +

Creates a variable from the expression.

+
+ + +
+
+
#   + + + def + Value(self) -> 'int64_t': +
+ +
+ View Source +
    def Value(self) -> "int64_t":
+        r"""
+        This method returns the value of the variable. This method checks
+        before that the variable is bound.
+        """
+        return _pywrapcp.IntVar_Value(self)
+
+ +
+ +

This method returns the value of the variable. This method checks +before that the variable is bound.

+
+ + +
+
+
#   + + + def + RemoveValue(self, v: 'int64_t') -> 'void': +
+ +
+ View Source +
    def RemoveValue(self, v: "int64_t") -> "void":
+        r""" This method removes the value 'v' from the domain of the variable."""
+        return _pywrapcp.IntVar_RemoveValue(self, v)
+
+ +
+ +

This method removes the value 'v' from the domain of the variable.

+
+ + +
+
+
#   + + + def + RemoveInterval(self, l: 'int64_t', u: 'int64_t') -> 'void': +
+ +
+ View Source +
    def RemoveInterval(self, l: "int64_t", u: "int64_t") -> "void":
+        r"""
+        This method removes the interval 'l' .. 'u' from the domain of
+        the variable. It assumes that 'l' <= 'u'.
+        """
+        return _pywrapcp.IntVar_RemoveInterval(self, l, u)
+
+ +
+ +

This method removes the interval 'l' .. 'u' from the domain of +the variable. It assumes that 'l' <= 'u'.

+
+ + +
+
+
#   + + + def + RemoveValues(self, values: 'std::vector< int64_t > const &') -> 'void': +
+ +
+ View Source +
    def RemoveValues(self, values: "std::vector< int64_t > const &") -> "void":
+        r""" This method remove the values from the domain of the variable."""
+        return _pywrapcp.IntVar_RemoveValues(self, values)
+
+ +
+ +

This method remove the values from the domain of the variable.

+
+ + +
+
+
#   + + + def + SetValues(self, values: 'std::vector< int64_t > const &') -> 'void': +
+ +
+ View Source +
    def SetValues(self, values: "std::vector< int64_t > const &") -> "void":
+        r""" This method intersects the current domain with the values in the array."""
+        return _pywrapcp.IntVar_SetValues(self, values)
+
+ +
+ +

This method intersects the current domain with the values in the array.

+
+ + +
+
+
#   + + + def + WhenBound(self, *args) -> 'void': +
+ +
+ View Source +
    def WhenBound(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        This method attaches a demon that will be awakened when the
+        variable is bound.
+
+        |
+
+        *Overload 2:*
+        This method attaches a closure that will be awakened when the
+        variable is bound.
+        """
+        return _pywrapcp.IntVar_WhenBound(self, *args)
+
+ +
+ +

Overload 1: +This method attaches a demon that will be awakened when the +variable is bound.

+ +

|

+ +

Overload 2: +This method attaches a closure that will be awakened when the +variable is bound.

+
+ + +
+
+
#   + + + def + WhenDomain(self, *args) -> 'void': +
+ +
+ View Source +
    def WhenDomain(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        This method attaches a demon that will watch any domain
+        modification of the domain of the variable.
+
+        |
+
+        *Overload 2:*
+        This method attaches a closure that will watch any domain
+        modification of the domain of the variable.
+        """
+        return _pywrapcp.IntVar_WhenDomain(self, *args)
+
+ +
+ +

Overload 1: +This method attaches a demon that will watch any domain +modification of the domain of the variable.

+ +

|

+ +

Overload 2: +This method attaches a closure that will watch any domain +modification of the domain of the variable.

+
+ + +
+
+
#   + + + def + Size(self) -> 'uint64_t': +
+ +
+ View Source +
    def Size(self) -> "uint64_t":
+        r""" This method returns the number of values in the domain of the variable."""
+        return _pywrapcp.IntVar_Size(self)
+
+ +
+ +

This method returns the number of values in the domain of the variable.

+
+ + +
+
+
#   + + + def + Contains(self, v: 'int64_t') -> bool: +
+ +
+ View Source +
    def Contains(self, v: "int64_t") -> "bool":
+        r"""
+        This method returns whether the value 'v' is in the domain of the
+        variable.
+        """
+        return _pywrapcp.IntVar_Contains(self, v)
+
+ +
+ +

This method returns whether the value 'v' is in the domain of the +variable.

+
+ + +
+
+
#   + + + def + HoleIteratorAux(self, reversible: bool) -> 'operations_research::IntVarIterator *': +
+ +
+ View Source +
    def HoleIteratorAux(self, reversible: "bool") -> "operations_research::IntVarIterator *":
+        r"""
+        Creates a hole iterator. When 'reversible' is false, the returned
+        object is created on the normal C++ heap and the solver does NOT
+        take ownership of the object.
+        """
+        return _pywrapcp.IntVar_HoleIteratorAux(self, reversible)
+
+ +
+ +

Creates a hole iterator. When 'reversible' is false, the returned +object is created on the normal C++ heap and the solver does NOT +take ownership of the object.

+
+ + +
+
+
#   + + + def + DomainIteratorAux(self, reversible: bool) -> 'operations_research::IntVarIterator *': +
+ +
+ View Source +
    def DomainIteratorAux(self, reversible: "bool") -> "operations_research::IntVarIterator *":
+        r"""
+        Creates a domain iterator. When 'reversible' is false, the
+        returned object is created on the normal C++ heap and the solver
+        does NOT take ownership of the object.
+        """
+        return _pywrapcp.IntVar_DomainIteratorAux(self, reversible)
+
+ +
+ +

Creates a domain iterator. When 'reversible' is false, the +returned object is created on the normal C++ heap and the solver +does NOT take ownership of the object.

+
+ + +
+
+
#   + + + def + OldMin(self) -> 'int64_t': +
+ +
+ View Source +
    def OldMin(self) -> "int64_t":
+        r""" Returns the previous min."""
+        return _pywrapcp.IntVar_OldMin(self)
+
+ +
+ +

Returns the previous min.

+
+ + +
+
+
#   + + + def + OldMax(self) -> 'int64_t': +
+ +
+ View Source +
    def OldMax(self) -> "int64_t":
+        r""" Returns the previous max."""
+        return _pywrapcp.IntVar_OldMax(self)
+
+ +
+ +

Returns the previous max.

+
+ + +
+
+
#   + + + def + DomainIterator(self): +
+ +
+ View Source +
    def DomainIterator(self):
+      return iter(self.DomainIteratorAux(False))
+
+ +
+ + + +
+
+
#   + + + def + HoleIterator(self): +
+ +
+ View Source +
    def HoleIterator(self):
+      return iter(self.HoleIteratorAux(False))
+
+ +
+ + + +
+ +
+
+
+ #   + + + class + SolutionCollector(SearchMonitor): +
+ +
+ View Source +
class SolutionCollector(SearchMonitor):
+    r"""
+    This class is the root class of all solution collectors.
+    It implements a basic query API to be used independently
+    of the collector used.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.SolutionCollector_DebugString(self)
+
+    def Add(self, *args) -> "void":
+        return _pywrapcp.SolutionCollector_Add(self, *args)
+
+    def AddObjective(self, objective: "IntVar") -> "void":
+        return _pywrapcp.SolutionCollector_AddObjective(self, objective)
+
+    def EnterSearch(self) -> "void":
+        r""" Beginning of the search."""
+        return _pywrapcp.SolutionCollector_EnterSearch(self)
+
+    def SolutionCount(self) -> "int":
+        r""" Returns how many solutions were stored during the search."""
+        return _pywrapcp.SolutionCollector_SolutionCount(self)
+
+    def Solution(self, n: "int") -> "operations_research::Assignment *":
+        r""" Returns the nth solution."""
+        return _pywrapcp.SolutionCollector_Solution(self, n)
+
+    def WallTime(self, n: "int") -> "int64_t":
+        r""" Returns the wall time in ms for the nth solution."""
+        return _pywrapcp.SolutionCollector_WallTime(self, n)
+
+    def Branches(self, n: "int") -> "int64_t":
+        r""" Returns the number of branches when the nth solution was found."""
+        return _pywrapcp.SolutionCollector_Branches(self, n)
+
+    def Failures(self, n: "int") -> "int64_t":
+        r"""
+        Returns the number of failures encountered at the time of the nth
+        solution.
+        """
+        return _pywrapcp.SolutionCollector_Failures(self, n)
+
+    def ObjectiveValue(self, n: "int") -> "int64_t":
+        r""" Returns the objective value of the nth solution."""
+        return _pywrapcp.SolutionCollector_ObjectiveValue(self, n)
+
+    def Value(self, n: "int", var: "IntVar") -> "int64_t":
+        r""" This is a shortcut to get the Value of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_Value(self, n, var)
+
+    def StartValue(self, n: "int", var: "IntervalVar") -> "int64_t":
+        r""" This is a shortcut to get the StartValue of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_StartValue(self, n, var)
+
+    def EndValue(self, n: "int", var: "IntervalVar") -> "int64_t":
+        r""" This is a shortcut to get the EndValue of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_EndValue(self, n, var)
+
+    def DurationValue(self, n: "int", var: "IntervalVar") -> "int64_t":
+        r""" This is a shortcut to get the DurationValue of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_DurationValue(self, n, var)
+
+    def PerformedValue(self, n: "int", var: "IntervalVar") -> "int64_t":
+        r""" This is a shortcut to get the PerformedValue of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_PerformedValue(self, n, var)
+
+    def ForwardSequence(self, n: "int", var: "SequenceVar") -> "std::vector< int > const &":
+        r"""
+        This is a shortcut to get the ForwardSequence of 'var' in the
+        nth solution. The forward sequence is the list of ranked interval
+        variables starting from the start of the sequence.
+        """
+        return _pywrapcp.SolutionCollector_ForwardSequence(self, n, var)
+
+    def BackwardSequence(self, n: "int", var: "SequenceVar") -> "std::vector< int > const &":
+        r"""
+        This is a shortcut to get the BackwardSequence of 'var' in the
+        nth solution. The backward sequence is the list of ranked interval
+        variables starting from the end of the sequence.
+        """
+        return _pywrapcp.SolutionCollector_BackwardSequence(self, n, var)
+
+    def Unperformed(self, n: "int", var: "SequenceVar") -> "std::vector< int > const &":
+        r"""
+        This is a shortcut to get the list of unperformed of 'var' in the
+        nth solution.
+        """
+        return _pywrapcp.SolutionCollector_Unperformed(self, n, var)
+
+ +
+ +

This class is the root class of all solution collectors. +It implements a basic query API to be used independently +of the collector used.

+
+ + +
+
#   + + + SolutionCollector(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.SolutionCollector_DebugString(self)
+
+ +
+ + + +
+
+
#   + + + def + Add(self, *args) -> 'void': +
+ +
+ View Source +
    def Add(self, *args) -> "void":
+        return _pywrapcp.SolutionCollector_Add(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + AddObjective(self, objective: ortools.constraint_solver.pywrapcp.IntVar) -> 'void': +
+ +
+ View Source +
    def AddObjective(self, objective: "IntVar") -> "void":
+        return _pywrapcp.SolutionCollector_AddObjective(self, objective)
+
+ +
+ + + +
+
+
#   + + + def + EnterSearch(self) -> 'void': +
+ +
+ View Source +
    def EnterSearch(self) -> "void":
+        r""" Beginning of the search."""
+        return _pywrapcp.SolutionCollector_EnterSearch(self)
+
+ +
+ +

Beginning of the search.

+
+ + +
+
+
#   + + + def + SolutionCount(self) -> int: +
+ +
+ View Source +
    def SolutionCount(self) -> "int":
+        r""" Returns how many solutions were stored during the search."""
+        return _pywrapcp.SolutionCollector_SolutionCount(self)
+
+ +
+ +

Returns how many solutions were stored during the search.

+
+ + +
+
+
#   + + + def + Solution(self, n: int) -> 'operations_research::Assignment *': +
+ +
+ View Source +
    def Solution(self, n: "int") -> "operations_research::Assignment *":
+        r""" Returns the nth solution."""
+        return _pywrapcp.SolutionCollector_Solution(self, n)
+
+ +
+ +

Returns the nth solution.

+
+ + +
+
+
#   + + + def + WallTime(self, n: int) -> 'int64_t': +
+ +
+ View Source +
    def WallTime(self, n: "int") -> "int64_t":
+        r""" Returns the wall time in ms for the nth solution."""
+        return _pywrapcp.SolutionCollector_WallTime(self, n)
+
+ +
+ +

Returns the wall time in ms for the nth solution.

+
+ + +
+
+
#   + + + def + Branches(self, n: int) -> 'int64_t': +
+ +
+ View Source +
    def Branches(self, n: "int") -> "int64_t":
+        r""" Returns the number of branches when the nth solution was found."""
+        return _pywrapcp.SolutionCollector_Branches(self, n)
+
+ +
+ +

Returns the number of branches when the nth solution was found.

+
+ + +
+
+
#   + + + def + Failures(self, n: int) -> 'int64_t': +
+ +
+ View Source +
    def Failures(self, n: "int") -> "int64_t":
+        r"""
+        Returns the number of failures encountered at the time of the nth
+        solution.
+        """
+        return _pywrapcp.SolutionCollector_Failures(self, n)
+
+ +
+ +

Returns the number of failures encountered at the time of the nth +solution.

+
+ + +
+
+
#   + + + def + ObjectiveValue(self, n: int) -> 'int64_t': +
+ +
+ View Source +
    def ObjectiveValue(self, n: "int") -> "int64_t":
+        r""" Returns the objective value of the nth solution."""
+        return _pywrapcp.SolutionCollector_ObjectiveValue(self, n)
+
+ +
+ +

Returns the objective value of the nth solution.

+
+ + +
+
+
#   + + + def + Value( + self, + n: int, + var: ortools.constraint_solver.pywrapcp.IntVar +) -> 'int64_t': +
+ +
+ View Source +
    def Value(self, n: "int", var: "IntVar") -> "int64_t":
+        r""" This is a shortcut to get the Value of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_Value(self, n, var)
+
+ +
+ +

This is a shortcut to get the Value of 'var' in the nth solution.

+
+ + +
+
+
#   + + + def + StartValue( + self, + n: int, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def StartValue(self, n: "int", var: "IntervalVar") -> "int64_t":
+        r""" This is a shortcut to get the StartValue of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_StartValue(self, n, var)
+
+ +
+ +

This is a shortcut to get the StartValue of 'var' in the nth solution.

+
+ + +
+
+
#   + + + def + EndValue( + self, + n: int, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def EndValue(self, n: "int", var: "IntervalVar") -> "int64_t":
+        r""" This is a shortcut to get the EndValue of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_EndValue(self, n, var)
+
+ +
+ +

This is a shortcut to get the EndValue of 'var' in the nth solution.

+
+ + +
+
+
#   + + + def + DurationValue( + self, + n: int, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def DurationValue(self, n: "int", var: "IntervalVar") -> "int64_t":
+        r""" This is a shortcut to get the DurationValue of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_DurationValue(self, n, var)
+
+ +
+ +

This is a shortcut to get the DurationValue of 'var' in the nth solution.

+
+ + +
+
+
#   + + + def + PerformedValue( + self, + n: int, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def PerformedValue(self, n: "int", var: "IntervalVar") -> "int64_t":
+        r""" This is a shortcut to get the PerformedValue of 'var' in the nth solution."""
+        return _pywrapcp.SolutionCollector_PerformedValue(self, n, var)
+
+ +
+ +

This is a shortcut to get the PerformedValue of 'var' in the nth solution.

+
+ + +
+
+
#   + + + def + ForwardSequence( + self, + n: int, + var: ortools.constraint_solver.pywrapcp.SequenceVar +) -> 'std::vector< int > const &': +
+ +
+ View Source +
    def ForwardSequence(self, n: "int", var: "SequenceVar") -> "std::vector< int > const &":
+        r"""
+        This is a shortcut to get the ForwardSequence of 'var' in the
+        nth solution. The forward sequence is the list of ranked interval
+        variables starting from the start of the sequence.
+        """
+        return _pywrapcp.SolutionCollector_ForwardSequence(self, n, var)
+
+ +
+ +

This is a shortcut to get the ForwardSequence of 'var' in the +nth solution. The forward sequence is the list of ranked interval +variables starting from the start of the sequence.

+
+ + +
+
+
#   + + + def + BackwardSequence( + self, + n: int, + var: ortools.constraint_solver.pywrapcp.SequenceVar +) -> 'std::vector< int > const &': +
+ +
+ View Source +
    def BackwardSequence(self, n: "int", var: "SequenceVar") -> "std::vector< int > const &":
+        r"""
+        This is a shortcut to get the BackwardSequence of 'var' in the
+        nth solution. The backward sequence is the list of ranked interval
+        variables starting from the end of the sequence.
+        """
+        return _pywrapcp.SolutionCollector_BackwardSequence(self, n, var)
+
+ +
+ +

This is a shortcut to get the BackwardSequence of 'var' in the +nth solution. The backward sequence is the list of ranked interval +variables starting from the end of the sequence.

+
+ + +
+
+
#   + + + def + Unperformed( + self, + n: int, + var: ortools.constraint_solver.pywrapcp.SequenceVar +) -> 'std::vector< int > const &': +
+ +
+ View Source +
    def Unperformed(self, n: "int", var: "SequenceVar") -> "std::vector< int > const &":
+        r"""
+        This is a shortcut to get the list of unperformed of 'var' in the
+        nth solution.
+        """
+        return _pywrapcp.SolutionCollector_Unperformed(self, n, var)
+
+ +
+ +

This is a shortcut to get the list of unperformed of 'var' in the +nth solution.

+
+ + +
+ +
+
+
+ #   + + + class + OptimizeVar(SearchMonitor): +
+ +
+ View Source +
class OptimizeVar(SearchMonitor):
+    r"""
+    This class encapsulates an objective. It requires the direction
+    (minimize or maximize), the variable to optimize, and the
+    improvement step.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Best(self) -> "int64_t":
+        r""" Returns the best value found during search."""
+        return _pywrapcp.OptimizeVar_Best(self)
+
+    def Var(self) -> "operations_research::IntVar *":
+        r""" Returns the variable that is optimized."""
+        return _pywrapcp.OptimizeVar_Var(self)
+
+    def AcceptDelta(self, delta: "Assignment", deltadelta: "Assignment") -> "bool":
+        r""" Internal methods."""
+        return _pywrapcp.OptimizeVar_AcceptDelta(self, delta, deltadelta)
+
+    def EnterSearch(self) -> "void":
+        return _pywrapcp.OptimizeVar_EnterSearch(self)
+
+    def BeginNextDecision(self, db: "DecisionBuilder") -> "void":
+        return _pywrapcp.OptimizeVar_BeginNextDecision(self, db)
+
+    def RefuteDecision(self, d: "Decision") -> "void":
+        return _pywrapcp.OptimizeVar_RefuteDecision(self, d)
+
+    def AtSolution(self) -> "bool":
+        return _pywrapcp.OptimizeVar_AtSolution(self)
+
+    def AcceptSolution(self) -> "bool":
+        return _pywrapcp.OptimizeVar_AcceptSolution(self)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.OptimizeVar_DebugString(self)
+
+ +
+ +

This class encapsulates an objective. It requires the direction +(minimize or maximize), the variable to optimize, and the +improvement step.

+
+ + +
+
#   + + + OptimizeVar(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Best(self) -> 'int64_t': +
+ +
+ View Source +
    def Best(self) -> "int64_t":
+        r""" Returns the best value found during search."""
+        return _pywrapcp.OptimizeVar_Best(self)
+
+ +
+ +

Returns the best value found during search.

+
+ + +
+
+
#   + + + def + Var(self) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def Var(self) -> "operations_research::IntVar *":
+        r""" Returns the variable that is optimized."""
+        return _pywrapcp.OptimizeVar_Var(self)
+
+ +
+ +

Returns the variable that is optimized.

+
+ + +
+
+
#   + + + def + AcceptDelta( + self, + delta: ortools.constraint_solver.pywrapcp.Assignment, + deltadelta: ortools.constraint_solver.pywrapcp.Assignment +) -> bool: +
+ +
+ View Source +
    def AcceptDelta(self, delta: "Assignment", deltadelta: "Assignment") -> "bool":
+        r""" Internal methods."""
+        return _pywrapcp.OptimizeVar_AcceptDelta(self, delta, deltadelta)
+
+ +
+ +

Internal methods.

+
+ + +
+
+
#   + + + def + EnterSearch(self) -> 'void': +
+ +
+ View Source +
    def EnterSearch(self) -> "void":
+        return _pywrapcp.OptimizeVar_EnterSearch(self)
+
+ +
+ +

Beginning of the search.

+
+ + +
+
+
#   + + + def + BeginNextDecision( + self, + db: ortools.constraint_solver.pywrapcp.DecisionBuilder +) -> 'void': +
+ +
+ View Source +
    def BeginNextDecision(self, db: "DecisionBuilder") -> "void":
+        return _pywrapcp.OptimizeVar_BeginNextDecision(self, db)
+
+ +
+ +

Before calling DecisionBuilder::Next.

+
+ + +
+
+
#   + + + def + RefuteDecision(self, d: ortools.constraint_solver.pywrapcp.Decision) -> 'void': +
+ +
+ View Source +
    def RefuteDecision(self, d: "Decision") -> "void":
+        return _pywrapcp.OptimizeVar_RefuteDecision(self, d)
+
+ +
+ +

Before refuting the decision.

+
+ + +
+
+
#   + + + def + AtSolution(self) -> bool: +
+ +
+ View Source +
    def AtSolution(self) -> "bool":
+        return _pywrapcp.OptimizeVar_AtSolution(self)
+
+ +
+ +

This method is called when a valid solution is found. If the +return value is true, then search will resume after. If the result +is false, then search will stop there.

+
+ + +
+
+
#   + + + def + AcceptSolution(self) -> bool: +
+ +
+ View Source +
    def AcceptSolution(self) -> "bool":
+        return _pywrapcp.OptimizeVar_AcceptSolution(self)
+
+ +
+ +

This method is called when a solution is found. It asserts whether the +solution is valid. A value of false indicates that the solution +should be discarded.

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.OptimizeVar_DebugString(self)
+
+ +
+ + + +
+ +
+
+
+ #   + + + class + SearchLimit(SearchMonitor): +
+ +
+ View Source +
class SearchLimit(SearchMonitor):
+    r""" Base class of all search limits."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+    __swig_destroy__ = _pywrapcp.delete_SearchLimit
+
+    def Crossed(self) -> "bool":
+        r""" Returns true if the limit has been crossed."""
+        return _pywrapcp.SearchLimit_Crossed(self)
+
+    def Check(self) -> "bool":
+        r"""
+        This method is called to check the status of the limit. A return
+        value of true indicates that we have indeed crossed the limit. In
+        that case, this method will not be called again and the remaining
+        search will be discarded.
+        """
+        return _pywrapcp.SearchLimit_Check(self)
+
+    def Init(self) -> "void":
+        r""" This method is called when the search limit is initialized."""
+        return _pywrapcp.SearchLimit_Init(self)
+
+    def EnterSearch(self) -> "void":
+        r""" Internal methods."""
+        return _pywrapcp.SearchLimit_EnterSearch(self)
+
+    def BeginNextDecision(self, b: "DecisionBuilder") -> "void":
+        return _pywrapcp.SearchLimit_BeginNextDecision(self, b)
+
+    def RefuteDecision(self, d: "Decision") -> "void":
+        return _pywrapcp.SearchLimit_RefuteDecision(self, d)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.SearchLimit_DebugString(self)
+
+ +
+ +

Base class of all search limits.

+
+ + +
+
#   + + + SearchLimit(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Crossed(self) -> bool: +
+ +
+ View Source +
    def Crossed(self) -> "bool":
+        r""" Returns true if the limit has been crossed."""
+        return _pywrapcp.SearchLimit_Crossed(self)
+
+ +
+ +

Returns true if the limit has been crossed.

+
+ + +
+
+
#   + + + def + Check(self) -> bool: +
+ +
+ View Source +
    def Check(self) -> "bool":
+        r"""
+        This method is called to check the status of the limit. A return
+        value of true indicates that we have indeed crossed the limit. In
+        that case, this method will not be called again and the remaining
+        search will be discarded.
+        """
+        return _pywrapcp.SearchLimit_Check(self)
+
+ +
+ +

This method is called to check the status of the limit. A return +value of true indicates that we have indeed crossed the limit. In +that case, this method will not be called again and the remaining +search will be discarded.

+
+ + +
+
+
#   + + + def + Init(self) -> 'void': +
+ +
+ View Source +
    def Init(self) -> "void":
+        r""" This method is called when the search limit is initialized."""
+        return _pywrapcp.SearchLimit_Init(self)
+
+ +
+ +

This method is called when the search limit is initialized.

+
+ + +
+
+
#   + + + def + EnterSearch(self) -> 'void': +
+ +
+ View Source +
    def EnterSearch(self) -> "void":
+        r""" Internal methods."""
+        return _pywrapcp.SearchLimit_EnterSearch(self)
+
+ +
+ +

Internal methods.

+
+ + +
+
+
#   + + + def + BeginNextDecision( + self, + b: ortools.constraint_solver.pywrapcp.DecisionBuilder +) -> 'void': +
+ +
+ View Source +
    def BeginNextDecision(self, b: "DecisionBuilder") -> "void":
+        return _pywrapcp.SearchLimit_BeginNextDecision(self, b)
+
+ +
+ +

Before calling DecisionBuilder::Next.

+
+ + +
+
+
#   + + + def + RefuteDecision(self, d: ortools.constraint_solver.pywrapcp.Decision) -> 'void': +
+ +
+ View Source +
    def RefuteDecision(self, d: "Decision") -> "void":
+        return _pywrapcp.SearchLimit_RefuteDecision(self, d)
+
+ +
+ +

Before refuting the decision.

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.SearchLimit_DebugString(self)
+
+ +
+ + + +
+ +
+
+
+ #   + + + class + IntervalVar(PropagationBaseObject): +
+ +
+ View Source +
class IntervalVar(PropagationBaseObject):
+    r"""
+    Interval variables are often used in scheduling. The main characteristics
+    of an IntervalVar are the start position, duration, and end
+    date. All these characteristics can be queried and set, and demons can
+    be posted on their modifications.
+
+    An important aspect is optionality: an IntervalVar can be performed or not.
+    If unperformed, then it simply does not exist, and its characteristics
+    cannot be accessed any more. An interval var is automatically marked
+    as unperformed when it is not consistent anymore (start greater
+    than end, duration < 0...)
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+    def StartMin(self) -> "int64_t":
+        r"""
+        These methods query, set, and watch the start position of the
+        interval var.
+        """
+        return _pywrapcp.IntervalVar_StartMin(self)
+
+    def StartMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_StartMax(self)
+
+    def SetStartMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetStartMin(self, m)
+
+    def SetStartMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetStartMax(self, m)
+
+    def SetStartRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetStartRange(self, mi, ma)
+
+    def OldStartMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldStartMin(self)
+
+    def OldStartMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldStartMax(self)
+
+    def WhenStartRange(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenStartRange(self, *args)
+
+    def WhenStartBound(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenStartBound(self, *args)
+
+    def DurationMin(self) -> "int64_t":
+        r""" These methods query, set, and watch the duration of the interval var."""
+        return _pywrapcp.IntervalVar_DurationMin(self)
+
+    def DurationMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_DurationMax(self)
+
+    def SetDurationMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetDurationMin(self, m)
+
+    def SetDurationMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetDurationMax(self, m)
+
+    def SetDurationRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetDurationRange(self, mi, ma)
+
+    def OldDurationMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldDurationMin(self)
+
+    def OldDurationMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldDurationMax(self)
+
+    def WhenDurationRange(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenDurationRange(self, *args)
+
+    def WhenDurationBound(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenDurationBound(self, *args)
+
+    def EndMin(self) -> "int64_t":
+        r""" These methods query, set, and watch the end position of the interval var."""
+        return _pywrapcp.IntervalVar_EndMin(self)
+
+    def EndMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_EndMax(self)
+
+    def SetEndMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetEndMin(self, m)
+
+    def SetEndMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetEndMax(self, m)
+
+    def SetEndRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetEndRange(self, mi, ma)
+
+    def OldEndMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldEndMin(self)
+
+    def OldEndMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldEndMax(self)
+
+    def WhenEndRange(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenEndRange(self, *args)
+
+    def WhenEndBound(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenEndBound(self, *args)
+
+    def MustBePerformed(self) -> "bool":
+        r"""
+        These methods query, set, and watch the performed status of the
+        interval var.
+        """
+        return _pywrapcp.IntervalVar_MustBePerformed(self)
+
+    def MayBePerformed(self) -> "bool":
+        return _pywrapcp.IntervalVar_MayBePerformed(self)
+
+    def CannotBePerformed(self) -> "bool":
+        return _pywrapcp.IntervalVar_CannotBePerformed(self)
+
+    def IsPerformedBound(self) -> "bool":
+        return _pywrapcp.IntervalVar_IsPerformedBound(self)
+
+    def SetPerformed(self, val: "bool") -> "void":
+        return _pywrapcp.IntervalVar_SetPerformed(self, val)
+
+    def WasPerformedBound(self) -> "bool":
+        return _pywrapcp.IntervalVar_WasPerformedBound(self)
+
+    def WhenPerformedBound(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenPerformedBound(self, *args)
+
+    def WhenAnything(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        Attaches a demon awakened when anything about this interval changes.
+
+        |
+
+        *Overload 2:*
+        Attaches a closure awakened when anything about this interval changes.
+        """
+        return _pywrapcp.IntervalVar_WhenAnything(self, *args)
+
+    def StartExpr(self) -> "operations_research::IntExpr *":
+        r"""
+        These methods create expressions encapsulating the start, end
+        and duration of the interval var. Please note that these must not
+        be used if the interval var is unperformed.
+        """
+        return _pywrapcp.IntervalVar_StartExpr(self)
+
+    def DurationExpr(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_DurationExpr(self)
+
+    def EndExpr(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_EndExpr(self)
+
+    def PerformedExpr(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_PerformedExpr(self)
+
+    def SafeStartExpr(self, unperformed_value: "int64_t") -> "operations_research::IntExpr *":
+        r"""
+        These methods create expressions encapsulating the start, end
+        and duration of the interval var. If the interval var is
+        unperformed, they will return the unperformed_value.
+        """
+        return _pywrapcp.IntervalVar_SafeStartExpr(self, unperformed_value)
+
+    def SafeDurationExpr(self, unperformed_value: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_SafeDurationExpr(self, unperformed_value)
+
+    def SafeEndExpr(self, unperformed_value: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_SafeEndExpr(self, unperformed_value)
+
+    def EndsAfterEnd(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfterEnd(self, other)
+
+    def EndsAfterEndWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfterEndWithDelay(self, other, delay)
+
+    def EndsAfterStart(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfterStart(self, other)
+
+    def EndsAfterStartWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfterStartWithDelay(self, other, delay)
+
+    def EndsAtEnd(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAtEnd(self, other)
+
+    def EndsAtEndWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAtEndWithDelay(self, other, delay)
+
+    def EndsAtStart(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAtStart(self, other)
+
+    def EndsAtStartWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAtStartWithDelay(self, other, delay)
+
+    def StartsAfterEnd(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfterEnd(self, other)
+
+    def StartsAfterEndWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfterEndWithDelay(self, other, delay)
+
+    def StartsAfterStart(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfterStart(self, other)
+
+    def StartsAfterStartWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfterStartWithDelay(self, other, delay)
+
+    def StartsAtEnd(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAtEnd(self, other)
+
+    def StartsAtEndWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAtEndWithDelay(self, other, delay)
+
+    def StartsAtStart(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAtStart(self, other)
+
+    def StartsAtStartWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAtStartWithDelay(self, other, delay)
+
+    def StaysInSync(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StaysInSync(self, other)
+
+    def StaysInSyncWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StaysInSyncWithDelay(self, other, delay)
+
+    def EndsAfter(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfter(self, date)
+
+    def EndsAt(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAt(self, date)
+
+    def EndsBefore(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsBefore(self, date)
+
+    def StartsAfter(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfter(self, date)
+
+    def StartsAt(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAt(self, date)
+
+    def StartsBefore(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsBefore(self, date)
+
+    def CrossesDate(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_CrossesDate(self, date)
+
+    def AvoidsDate(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_AvoidsDate(self, date)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.IntervalVar___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.IntervalVar___str__(self)
+
+ +
+ +

Interval variables are often used in scheduling. The main characteristics +of an IntervalVar are the start position, duration, and end +date. All these characteristics can be queried and set, and demons can +be posted on their modifications.

+ +

An important aspect is optionality: an IntervalVar can be performed or not. +If unperformed, then it simply does not exist, and its characteristics +cannot be accessed any more. An interval var is automatically marked +as unperformed when it is not consistent anymore (start greater +than end, duration < 0...)

+
+ + +
+
#   + + + IntervalVar(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + StartMin(self) -> 'int64_t': +
+ +
+ View Source +
    def StartMin(self) -> "int64_t":
+        r"""
+        These methods query, set, and watch the start position of the
+        interval var.
+        """
+        return _pywrapcp.IntervalVar_StartMin(self)
+
+ +
+ +

These methods query, set, and watch the start position of the +interval var.

+
+ + +
+
+
#   + + + def + StartMax(self) -> 'int64_t': +
+ +
+ View Source +
    def StartMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_StartMax(self)
+
+ +
+ + + +
+
+
#   + + + def + SetStartMin(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetStartMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetStartMin(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetStartMax(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetStartMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetStartMax(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetStartRange(self, mi: 'int64_t', ma: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetStartRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetStartRange(self, mi, ma)
+
+ +
+ + + +
+
+
#   + + + def + OldStartMin(self) -> 'int64_t': +
+ +
+ View Source +
    def OldStartMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldStartMin(self)
+
+ +
+ + + +
+
+
#   + + + def + OldStartMax(self) -> 'int64_t': +
+ +
+ View Source +
    def OldStartMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldStartMax(self)
+
+ +
+ + + +
+
+
#   + + + def + WhenStartRange(self, *args) -> 'void': +
+ +
+ View Source +
    def WhenStartRange(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenStartRange(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + WhenStartBound(self, *args) -> 'void': +
+ +
+ View Source +
    def WhenStartBound(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenStartBound(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + DurationMin(self) -> 'int64_t': +
+ +
+ View Source +
    def DurationMin(self) -> "int64_t":
+        r""" These methods query, set, and watch the duration of the interval var."""
+        return _pywrapcp.IntervalVar_DurationMin(self)
+
+ +
+ +

These methods query, set, and watch the duration of the interval var.

+
+ + +
+
+
#   + + + def + DurationMax(self) -> 'int64_t': +
+ +
+ View Source +
    def DurationMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_DurationMax(self)
+
+ +
+ + + +
+
+
#   + + + def + SetDurationMin(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetDurationMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetDurationMin(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetDurationMax(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetDurationMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetDurationMax(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetDurationRange(self, mi: 'int64_t', ma: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetDurationRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetDurationRange(self, mi, ma)
+
+ +
+ + + +
+
+
#   + + + def + OldDurationMin(self) -> 'int64_t': +
+ +
+ View Source +
    def OldDurationMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldDurationMin(self)
+
+ +
+ + + +
+
+
#   + + + def + OldDurationMax(self) -> 'int64_t': +
+ +
+ View Source +
    def OldDurationMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldDurationMax(self)
+
+ +
+ + + +
+
+
#   + + + def + WhenDurationRange(self, *args) -> 'void': +
+ +
+ View Source +
    def WhenDurationRange(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenDurationRange(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + WhenDurationBound(self, *args) -> 'void': +
+ +
+ View Source +
    def WhenDurationBound(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenDurationBound(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + EndMin(self) -> 'int64_t': +
+ +
+ View Source +
    def EndMin(self) -> "int64_t":
+        r""" These methods query, set, and watch the end position of the interval var."""
+        return _pywrapcp.IntervalVar_EndMin(self)
+
+ +
+ +

These methods query, set, and watch the end position of the interval var.

+
+ + +
+
+
#   + + + def + EndMax(self) -> 'int64_t': +
+ +
+ View Source +
    def EndMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_EndMax(self)
+
+ +
+ + + +
+
+
#   + + + def + SetEndMin(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetEndMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetEndMin(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetEndMax(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetEndMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetEndMax(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetEndRange(self, mi: 'int64_t', ma: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetEndRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVar_SetEndRange(self, mi, ma)
+
+ +
+ + + +
+
+
#   + + + def + OldEndMin(self) -> 'int64_t': +
+ +
+ View Source +
    def OldEndMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldEndMin(self)
+
+ +
+ + + +
+
+
#   + + + def + OldEndMax(self) -> 'int64_t': +
+ +
+ View Source +
    def OldEndMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVar_OldEndMax(self)
+
+ +
+ + + +
+
+
#   + + + def + WhenEndRange(self, *args) -> 'void': +
+ +
+ View Source +
    def WhenEndRange(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenEndRange(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + WhenEndBound(self, *args) -> 'void': +
+ +
+ View Source +
    def WhenEndBound(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenEndBound(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + MustBePerformed(self) -> bool: +
+ +
+ View Source +
    def MustBePerformed(self) -> "bool":
+        r"""
+        These methods query, set, and watch the performed status of the
+        interval var.
+        """
+        return _pywrapcp.IntervalVar_MustBePerformed(self)
+
+ +
+ +

These methods query, set, and watch the performed status of the +interval var.

+
+ + +
+
+
#   + + + def + MayBePerformed(self) -> bool: +
+ +
+ View Source +
    def MayBePerformed(self) -> "bool":
+        return _pywrapcp.IntervalVar_MayBePerformed(self)
+
+ +
+ + + +
+
+
#   + + + def + CannotBePerformed(self) -> bool: +
+ +
+ View Source +
    def CannotBePerformed(self) -> "bool":
+        return _pywrapcp.IntervalVar_CannotBePerformed(self)
+
+ +
+ + + +
+
+
#   + + + def + IsPerformedBound(self) -> bool: +
+ +
+ View Source +
    def IsPerformedBound(self) -> "bool":
+        return _pywrapcp.IntervalVar_IsPerformedBound(self)
+
+ +
+ + + +
+
+
#   + + + def + SetPerformed(self, val: bool) -> 'void': +
+ +
+ View Source +
    def SetPerformed(self, val: "bool") -> "void":
+        return _pywrapcp.IntervalVar_SetPerformed(self, val)
+
+ +
+ + + +
+
+
#   + + + def + WasPerformedBound(self) -> bool: +
+ +
+ View Source +
    def WasPerformedBound(self) -> "bool":
+        return _pywrapcp.IntervalVar_WasPerformedBound(self)
+
+ +
+ + + +
+
+
#   + + + def + WhenPerformedBound(self, *args) -> 'void': +
+ +
+ View Source +
    def WhenPerformedBound(self, *args) -> "void":
+        return _pywrapcp.IntervalVar_WhenPerformedBound(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + WhenAnything(self, *args) -> 'void': +
+ +
+ View Source +
    def WhenAnything(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        Attaches a demon awakened when anything about this interval changes.
+
+        |
+
+        *Overload 2:*
+        Attaches a closure awakened when anything about this interval changes.
+        """
+        return _pywrapcp.IntervalVar_WhenAnything(self, *args)
+
+ +
+ +

Overload 1: +Attaches a demon awakened when anything about this interval changes.

+ +

|

+ +

Overload 2: +Attaches a closure awakened when anything about this interval changes.

+
+ + +
+
+
#   + + + def + StartExpr(self) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def StartExpr(self) -> "operations_research::IntExpr *":
+        r"""
+        These methods create expressions encapsulating the start, end
+        and duration of the interval var. Please note that these must not
+        be used if the interval var is unperformed.
+        """
+        return _pywrapcp.IntervalVar_StartExpr(self)
+
+ +
+ +

These methods create expressions encapsulating the start, end +and duration of the interval var. Please note that these must not +be used if the interval var is unperformed.

+
+ + +
+
+
#   + + + def + DurationExpr(self) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def DurationExpr(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_DurationExpr(self)
+
+ +
+ + + +
+
+
#   + + + def + EndExpr(self) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def EndExpr(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_EndExpr(self)
+
+ +
+ + + +
+
+
#   + + + def + PerformedExpr(self) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def PerformedExpr(self) -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_PerformedExpr(self)
+
+ +
+ + + +
+
+
#   + + + def + SafeStartExpr( + self, + unperformed_value: 'int64_t' +) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def SafeStartExpr(self, unperformed_value: "int64_t") -> "operations_research::IntExpr *":
+        r"""
+        These methods create expressions encapsulating the start, end
+        and duration of the interval var. If the interval var is
+        unperformed, they will return the unperformed_value.
+        """
+        return _pywrapcp.IntervalVar_SafeStartExpr(self, unperformed_value)
+
+ +
+ +

These methods create expressions encapsulating the start, end +and duration of the interval var. If the interval var is +unperformed, they will return the unperformed_value.

+
+ + +
+
+
#   + + + def + SafeDurationExpr( + self, + unperformed_value: 'int64_t' +) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def SafeDurationExpr(self, unperformed_value: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_SafeDurationExpr(self, unperformed_value)
+
+ +
+ + + +
+
+
#   + + + def + SafeEndExpr( + self, + unperformed_value: 'int64_t' +) -> 'operations_research::IntExpr *': +
+ +
+ View Source +
    def SafeEndExpr(self, unperformed_value: "int64_t") -> "operations_research::IntExpr *":
+        return _pywrapcp.IntervalVar_SafeEndExpr(self, unperformed_value)
+
+ +
+ + + +
+
+
#   + + + def + EndsAfterEnd( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def EndsAfterEnd(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfterEnd(self, other)
+
+ +
+ + + +
+
+
#   + + + def + EndsAfterEndWithDelay( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar, + delay: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def EndsAfterEndWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfterEndWithDelay(self, other, delay)
+
+ +
+ + + +
+
+
#   + + + def + EndsAfterStart( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def EndsAfterStart(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfterStart(self, other)
+
+ +
+ + + +
+
+
#   + + + def + EndsAfterStartWithDelay( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar, + delay: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def EndsAfterStartWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfterStartWithDelay(self, other, delay)
+
+ +
+ + + +
+
+
#   + + + def + EndsAtEnd( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def EndsAtEnd(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAtEnd(self, other)
+
+ +
+ + + +
+
+
#   + + + def + EndsAtEndWithDelay( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar, + delay: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def EndsAtEndWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAtEndWithDelay(self, other, delay)
+
+ +
+ + + +
+
+
#   + + + def + EndsAtStart( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def EndsAtStart(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAtStart(self, other)
+
+ +
+ + + +
+
+
#   + + + def + EndsAtStartWithDelay( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar, + delay: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def EndsAtStartWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAtStartWithDelay(self, other, delay)
+
+ +
+ + + +
+
+
#   + + + def + StartsAfterEnd( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def StartsAfterEnd(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfterEnd(self, other)
+
+ +
+ + + +
+
+
#   + + + def + StartsAfterEndWithDelay( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar, + delay: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def StartsAfterEndWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfterEndWithDelay(self, other, delay)
+
+ +
+ + + +
+
+
#   + + + def + StartsAfterStart( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def StartsAfterStart(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfterStart(self, other)
+
+ +
+ + + +
+
+
#   + + + def + StartsAfterStartWithDelay( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar, + delay: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def StartsAfterStartWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfterStartWithDelay(self, other, delay)
+
+ +
+ + + +
+
+
#   + + + def + StartsAtEnd( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def StartsAtEnd(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAtEnd(self, other)
+
+ +
+ + + +
+
+
#   + + + def + StartsAtEndWithDelay( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar, + delay: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def StartsAtEndWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAtEndWithDelay(self, other, delay)
+
+ +
+ + + +
+
+
#   + + + def + StartsAtStart( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def StartsAtStart(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAtStart(self, other)
+
+ +
+ + + +
+
+
#   + + + def + StartsAtStartWithDelay( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar, + delay: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def StartsAtStartWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAtStartWithDelay(self, other, delay)
+
+ +
+ + + +
+
+
#   + + + def + StaysInSync( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def StaysInSync(self, other: "IntervalVar") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StaysInSync(self, other)
+
+ +
+ + + +
+
+
#   + + + def + StaysInSyncWithDelay( + self, + other: ortools.constraint_solver.pywrapcp.IntervalVar, + delay: 'int64_t' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def StaysInSyncWithDelay(self, other: "IntervalVar", delay: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StaysInSyncWithDelay(self, other, delay)
+
+ +
+ + + +
+
+
#   + + + def + EndsAfter(self, date: 'int64_t') -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def EndsAfter(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAfter(self, date)
+
+ +
+ + + +
+
+
#   + + + def + EndsAt(self, date: 'int64_t') -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def EndsAt(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsAt(self, date)
+
+ +
+ + + +
+
+
#   + + + def + EndsBefore(self, date: 'int64_t') -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def EndsBefore(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_EndsBefore(self, date)
+
+ +
+ + + +
+
+
#   + + + def + StartsAfter(self, date: 'int64_t') -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def StartsAfter(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAfter(self, date)
+
+ +
+ + + +
+
+
#   + + + def + StartsAt(self, date: 'int64_t') -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def StartsAt(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsAt(self, date)
+
+ +
+ + + +
+
+
#   + + + def + StartsBefore(self, date: 'int64_t') -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def StartsBefore(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_StartsBefore(self, date)
+
+ +
+ + + +
+
+
#   + + + def + CrossesDate(self, date: 'int64_t') -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def CrossesDate(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_CrossesDate(self, date)
+
+ +
+ + + +
+
+
#   + + + def + AvoidsDate(self, date: 'int64_t') -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def AvoidsDate(self, date: "int64_t") -> "operations_research::Constraint *":
+        return _pywrapcp.IntervalVar_AvoidsDate(self, date)
+
+ +
+ + + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + SequenceVar(PropagationBaseObject): +
+ +
+ View Source +
class SequenceVar(PropagationBaseObject):
+    r"""
+    A sequence variable is a variable whose domain is a set of possible
+    orderings of the interval variables. It allows ordering of tasks. It
+    has two sets of methods: ComputePossibleFirstsAndLasts(), which
+    returns the list of interval variables that can be ranked first or
+    last; and RankFirst/RankNotFirst/RankLast/RankNotLast, which can be
+    used to create the search decision.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.SequenceVar_DebugString(self)
+
+    def RankFirst(self, index: "int") -> "void":
+        r"""
+        Ranks the index_th interval var first of all unranked interval
+        vars. After that, it will no longer be considered ranked.
+        """
+        return _pywrapcp.SequenceVar_RankFirst(self, index)
+
+    def RankNotFirst(self, index: "int") -> "void":
+        r"""
+        Indicates that the index_th interval var will not be ranked first
+        of all currently unranked interval vars.
+        """
+        return _pywrapcp.SequenceVar_RankNotFirst(self, index)
+
+    def RankLast(self, index: "int") -> "void":
+        r"""
+        Ranks the index_th interval var first of all unranked interval
+        vars. After that, it will no longer be considered ranked.
+        """
+        return _pywrapcp.SequenceVar_RankLast(self, index)
+
+    def RankNotLast(self, index: "int") -> "void":
+        r"""
+        Indicates that the index_th interval var will not be ranked first
+        of all currently unranked interval vars.
+        """
+        return _pywrapcp.SequenceVar_RankNotLast(self, index)
+
+    def Interval(self, index: "int") -> "operations_research::IntervalVar *":
+        r""" Returns the index_th interval of the sequence."""
+        return _pywrapcp.SequenceVar_Interval(self, index)
+
+    def Next(self, index: "int") -> "operations_research::IntVar *":
+        r""" Returns the next of the index_th interval of the sequence."""
+        return _pywrapcp.SequenceVar_Next(self, index)
+
+    def Size(self) -> "int64_t":
+        r""" Returns the number of interval vars in the sequence."""
+        return _pywrapcp.SequenceVar_Size(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywrapcp.SequenceVar___repr__(self)
+
+    def __str__(self) -> "std::string":
+        return _pywrapcp.SequenceVar___str__(self)
+
+ +
+ +

A sequence variable is a variable whose domain is a set of possible +orderings of the interval variables. It allows ordering of tasks. It +has two sets of methods: ComputePossibleFirstsAndLasts(), which +returns the list of interval variables that can be ranked first or +last; and RankFirst/RankNotFirst/RankLast/RankNotLast, which can be +used to create the search decision.

+
+ + +
+
#   + + + SequenceVar(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.SequenceVar_DebugString(self)
+
+ +
+ + + +
+
+
#   + + + def + RankFirst(self, index: int) -> 'void': +
+ +
+ View Source +
    def RankFirst(self, index: "int") -> "void":
+        r"""
+        Ranks the index_th interval var first of all unranked interval
+        vars. After that, it will no longer be considered ranked.
+        """
+        return _pywrapcp.SequenceVar_RankFirst(self, index)
+
+ +
+ +

Ranks the index_th interval var first of all unranked interval +vars. After that, it will no longer be considered ranked.

+
+ + +
+
+
#   + + + def + RankNotFirst(self, index: int) -> 'void': +
+ +
+ View Source +
    def RankNotFirst(self, index: "int") -> "void":
+        r"""
+        Indicates that the index_th interval var will not be ranked first
+        of all currently unranked interval vars.
+        """
+        return _pywrapcp.SequenceVar_RankNotFirst(self, index)
+
+ +
+ +

Indicates that the index_th interval var will not be ranked first +of all currently unranked interval vars.

+
+ + +
+
+
#   + + + def + RankLast(self, index: int) -> 'void': +
+ +
+ View Source +
    def RankLast(self, index: "int") -> "void":
+        r"""
+        Ranks the index_th interval var first of all unranked interval
+        vars. After that, it will no longer be considered ranked.
+        """
+        return _pywrapcp.SequenceVar_RankLast(self, index)
+
+ +
+ +

Ranks the index_th interval var first of all unranked interval +vars. After that, it will no longer be considered ranked.

+
+ + +
+
+
#   + + + def + RankNotLast(self, index: int) -> 'void': +
+ +
+ View Source +
    def RankNotLast(self, index: "int") -> "void":
+        r"""
+        Indicates that the index_th interval var will not be ranked first
+        of all currently unranked interval vars.
+        """
+        return _pywrapcp.SequenceVar_RankNotLast(self, index)
+
+ +
+ +

Indicates that the index_th interval var will not be ranked first +of all currently unranked interval vars.

+
+ + +
+
+
#   + + + def + Interval(self, index: int) -> 'operations_research::IntervalVar *': +
+ +
+ View Source +
    def Interval(self, index: "int") -> "operations_research::IntervalVar *":
+        r""" Returns the index_th interval of the sequence."""
+        return _pywrapcp.SequenceVar_Interval(self, index)
+
+ +
+ +

Returns the index_th interval of the sequence.

+
+ + +
+
+
#   + + + def + Next(self, index: int) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def Next(self, index: "int") -> "operations_research::IntVar *":
+        r""" Returns the next of the index_th interval of the sequence."""
+        return _pywrapcp.SequenceVar_Next(self, index)
+
+ +
+ +

Returns the next of the index_th interval of the sequence.

+
+ + +
+
+
#   + + + def + Size(self) -> 'int64_t': +
+ +
+ View Source +
    def Size(self) -> "int64_t":
+        r""" Returns the number of interval vars in the sequence."""
+        return _pywrapcp.SequenceVar_Size(self)
+
+ +
+ +

Returns the number of interval vars in the sequence.

+
+ + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + AssignmentElement: +
+ +
+ View Source +
class AssignmentElement(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Activate(self) -> "void":
+        return _pywrapcp.AssignmentElement_Activate(self)
+
+    def Deactivate(self) -> "void":
+        return _pywrapcp.AssignmentElement_Deactivate(self)
+
+    def Activated(self) -> "bool":
+        return _pywrapcp.AssignmentElement_Activated(self)
+    __swig_destroy__ = _pywrapcp.delete_AssignmentElement
+
+ +
+ + + +
+
#   + + + AssignmentElement(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Activate(self) -> 'void': +
+ +
+ View Source +
    def Activate(self) -> "void":
+        return _pywrapcp.AssignmentElement_Activate(self)
+
+ +
+ + + +
+
+
#   + + + def + Deactivate(self) -> 'void': +
+ +
+ View Source +
    def Deactivate(self) -> "void":
+        return _pywrapcp.AssignmentElement_Deactivate(self)
+
+ +
+ + + +
+
+
#   + + + def + Activated(self) -> bool: +
+ +
+ View Source +
    def Activated(self) -> "bool":
+        return _pywrapcp.AssignmentElement_Activated(self)
+
+ +
+ + + +
+
+
+
+ #   + + + class + IntVarElement(AssignmentElement): +
+ +
+ View Source +
class IntVarElement(AssignmentElement):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Var(self) -> "operations_research::IntVar *":
+        return _pywrapcp.IntVarElement_Var(self)
+
+    def Min(self) -> "int64_t":
+        return _pywrapcp.IntVarElement_Min(self)
+
+    def SetMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntVarElement_SetMin(self, m)
+
+    def Max(self) -> "int64_t":
+        return _pywrapcp.IntVarElement_Max(self)
+
+    def SetMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntVarElement_SetMax(self, m)
+
+    def Value(self) -> "int64_t":
+        return _pywrapcp.IntVarElement_Value(self)
+
+    def Bound(self) -> "bool":
+        return _pywrapcp.IntVarElement_Bound(self)
+
+    def SetRange(self, l: "int64_t", u: "int64_t") -> "void":
+        return _pywrapcp.IntVarElement_SetRange(self, l, u)
+
+    def SetValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntVarElement_SetValue(self, v)
+
+    def __eq__(self, element: "IntVarElement") -> "bool":
+        return _pywrapcp.IntVarElement___eq__(self, element)
+
+    def __ne__(self, element: "IntVarElement") -> "bool":
+        return _pywrapcp.IntVarElement___ne__(self, element)
+    __swig_destroy__ = _pywrapcp.delete_IntVarElement
+
+ +
+ + + +
+
#   + + + IntVarElement(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Var(self) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def Var(self) -> "operations_research::IntVar *":
+        return _pywrapcp.IntVarElement_Var(self)
+
+ +
+ + + +
+
+
#   + + + def + Min(self) -> 'int64_t': +
+ +
+ View Source +
    def Min(self) -> "int64_t":
+        return _pywrapcp.IntVarElement_Min(self)
+
+ +
+ + + +
+
+
#   + + + def + SetMin(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntVarElement_SetMin(self, m)
+
+ +
+ + + +
+
+
#   + + + def + Max(self) -> 'int64_t': +
+ +
+ View Source +
    def Max(self) -> "int64_t":
+        return _pywrapcp.IntVarElement_Max(self)
+
+ +
+ + + +
+
+
#   + + + def + SetMax(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntVarElement_SetMax(self, m)
+
+ +
+ + + +
+
+
#   + + + def + Value(self) -> 'int64_t': +
+ +
+ View Source +
    def Value(self) -> "int64_t":
+        return _pywrapcp.IntVarElement_Value(self)
+
+ +
+ + + +
+
+
#   + + + def + Bound(self) -> bool: +
+ +
+ View Source +
    def Bound(self) -> "bool":
+        return _pywrapcp.IntVarElement_Bound(self)
+
+ +
+ + + +
+
+
#   + + + def + SetRange(self, l: 'int64_t', u: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetRange(self, l: "int64_t", u: "int64_t") -> "void":
+        return _pywrapcp.IntVarElement_SetRange(self, l, u)
+
+ +
+ + + +
+
+
#   + + + def + SetValue(self, v: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntVarElement_SetValue(self, v)
+
+ +
+ + + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + IntervalVarElement(AssignmentElement): +
+ +
+ View Source +
class IntervalVarElement(AssignmentElement):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Var(self) -> "operations_research::IntervalVar *":
+        return _pywrapcp.IntervalVarElement_Var(self)
+
+    def StartMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_StartMin(self)
+
+    def StartMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_StartMax(self)
+
+    def StartValue(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_StartValue(self)
+
+    def DurationMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_DurationMin(self)
+
+    def DurationMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_DurationMax(self)
+
+    def DurationValue(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_DurationValue(self)
+
+    def EndMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_EndMin(self)
+
+    def EndMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_EndMax(self)
+
+    def EndValue(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_EndValue(self)
+
+    def PerformedMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_PerformedMin(self)
+
+    def PerformedMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_PerformedMax(self)
+
+    def PerformedValue(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_PerformedValue(self)
+
+    def SetStartMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetStartMin(self, m)
+
+    def SetStartMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetStartMax(self, m)
+
+    def SetStartRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetStartRange(self, mi, ma)
+
+    def SetStartValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetStartValue(self, v)
+
+    def SetDurationMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetDurationMin(self, m)
+
+    def SetDurationMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetDurationMax(self, m)
+
+    def SetDurationRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetDurationRange(self, mi, ma)
+
+    def SetDurationValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetDurationValue(self, v)
+
+    def SetEndMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetEndMin(self, m)
+
+    def SetEndMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetEndMax(self, m)
+
+    def SetEndRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetEndRange(self, mi, ma)
+
+    def SetEndValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetEndValue(self, v)
+
+    def SetPerformedMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetPerformedMin(self, m)
+
+    def SetPerformedMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetPerformedMax(self, m)
+
+    def SetPerformedRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetPerformedRange(self, mi, ma)
+
+    def SetPerformedValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetPerformedValue(self, v)
+
+    def __eq__(self, element: "IntervalVarElement") -> "bool":
+        return _pywrapcp.IntervalVarElement___eq__(self, element)
+
+    def __ne__(self, element: "IntervalVarElement") -> "bool":
+        return _pywrapcp.IntervalVarElement___ne__(self, element)
+    __swig_destroy__ = _pywrapcp.delete_IntervalVarElement
+
+ +
+ + + +
+
#   + + + IntervalVarElement(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Var(self) -> 'operations_research::IntervalVar *': +
+ +
+ View Source +
    def Var(self) -> "operations_research::IntervalVar *":
+        return _pywrapcp.IntervalVarElement_Var(self)
+
+ +
+ + + +
+
+
#   + + + def + StartMin(self) -> 'int64_t': +
+ +
+ View Source +
    def StartMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_StartMin(self)
+
+ +
+ + + +
+
+
#   + + + def + StartMax(self) -> 'int64_t': +
+ +
+ View Source +
    def StartMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_StartMax(self)
+
+ +
+ + + +
+
+
#   + + + def + StartValue(self) -> 'int64_t': +
+ +
+ View Source +
    def StartValue(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_StartValue(self)
+
+ +
+ + + +
+
+
#   + + + def + DurationMin(self) -> 'int64_t': +
+ +
+ View Source +
    def DurationMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_DurationMin(self)
+
+ +
+ + + +
+
+
#   + + + def + DurationMax(self) -> 'int64_t': +
+ +
+ View Source +
    def DurationMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_DurationMax(self)
+
+ +
+ + + +
+
+
#   + + + def + DurationValue(self) -> 'int64_t': +
+ +
+ View Source +
    def DurationValue(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_DurationValue(self)
+
+ +
+ + + +
+
+
#   + + + def + EndMin(self) -> 'int64_t': +
+ +
+ View Source +
    def EndMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_EndMin(self)
+
+ +
+ + + +
+
+
#   + + + def + EndMax(self) -> 'int64_t': +
+ +
+ View Source +
    def EndMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_EndMax(self)
+
+ +
+ + + +
+
+
#   + + + def + EndValue(self) -> 'int64_t': +
+ +
+ View Source +
    def EndValue(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_EndValue(self)
+
+ +
+ + + +
+
+
#   + + + def + PerformedMin(self) -> 'int64_t': +
+ +
+ View Source +
    def PerformedMin(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_PerformedMin(self)
+
+ +
+ + + +
+
+
#   + + + def + PerformedMax(self) -> 'int64_t': +
+ +
+ View Source +
    def PerformedMax(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_PerformedMax(self)
+
+ +
+ + + +
+
+
#   + + + def + PerformedValue(self) -> 'int64_t': +
+ +
+ View Source +
    def PerformedValue(self) -> "int64_t":
+        return _pywrapcp.IntervalVarElement_PerformedValue(self)
+
+ +
+ + + +
+
+
#   + + + def + SetStartMin(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetStartMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetStartMin(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetStartMax(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetStartMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetStartMax(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetStartRange(self, mi: 'int64_t', ma: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetStartRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetStartRange(self, mi, ma)
+
+ +
+ + + +
+
+
#   + + + def + SetStartValue(self, v: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetStartValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetStartValue(self, v)
+
+ +
+ + + +
+
+
#   + + + def + SetDurationMin(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetDurationMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetDurationMin(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetDurationMax(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetDurationMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetDurationMax(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetDurationRange(self, mi: 'int64_t', ma: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetDurationRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetDurationRange(self, mi, ma)
+
+ +
+ + + +
+
+
#   + + + def + SetDurationValue(self, v: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetDurationValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetDurationValue(self, v)
+
+ +
+ + + +
+
+
#   + + + def + SetEndMin(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetEndMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetEndMin(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetEndMax(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetEndMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetEndMax(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetEndRange(self, mi: 'int64_t', ma: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetEndRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetEndRange(self, mi, ma)
+
+ +
+ + + +
+
+
#   + + + def + SetEndValue(self, v: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetEndValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetEndValue(self, v)
+
+ +
+ + + +
+
+
#   + + + def + SetPerformedMin(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetPerformedMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetPerformedMin(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetPerformedMax(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetPerformedMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetPerformedMax(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetPerformedRange(self, mi: 'int64_t', ma: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetPerformedRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetPerformedRange(self, mi, ma)
+
+ +
+ + + +
+
+
#   + + + def + SetPerformedValue(self, v: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetPerformedValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.IntervalVarElement_SetPerformedValue(self, v)
+
+ +
+ + + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + SequenceVarElement(AssignmentElement): +
+ +
+ View Source +
class SequenceVarElement(AssignmentElement):
+    r"""
+    The SequenceVarElement stores a partial representation of ranked
+    interval variables in the underlying sequence variable.
+    This representation consists of three vectors:
+      - the forward sequence. That is the list of interval variables
+        ranked first in the sequence.  The first element of the backward
+        sequence is the first interval in the sequence variable.
+      - the backward sequence. That is the list of interval variables
+        ranked last in the sequence. The first element of the backward
+        sequence is the last interval in the sequence variable.
+      - The list of unperformed interval variables.
+     Furthermore, if all performed variables are ranked, then by
+     convention, the forward_sequence will contain all such variables
+     and the backward_sequence will be empty.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Var(self) -> "operations_research::SequenceVar *":
+        return _pywrapcp.SequenceVarElement_Var(self)
+
+    def ForwardSequence(self) -> "std::vector< int > const &":
+        return _pywrapcp.SequenceVarElement_ForwardSequence(self)
+
+    def BackwardSequence(self) -> "std::vector< int > const &":
+        return _pywrapcp.SequenceVarElement_BackwardSequence(self)
+
+    def Unperformed(self) -> "std::vector< int > const &":
+        return _pywrapcp.SequenceVarElement_Unperformed(self)
+
+    def SetSequence(self, forward_sequence: "std::vector< int > const &", backward_sequence: "std::vector< int > const &", unperformed: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarElement_SetSequence(self, forward_sequence, backward_sequence, unperformed)
+
+    def SetForwardSequence(self, forward_sequence: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarElement_SetForwardSequence(self, forward_sequence)
+
+    def SetBackwardSequence(self, backward_sequence: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarElement_SetBackwardSequence(self, backward_sequence)
+
+    def SetUnperformed(self, unperformed: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarElement_SetUnperformed(self, unperformed)
+
+    def __eq__(self, element: "SequenceVarElement") -> "bool":
+        return _pywrapcp.SequenceVarElement___eq__(self, element)
+
+    def __ne__(self, element: "SequenceVarElement") -> "bool":
+        return _pywrapcp.SequenceVarElement___ne__(self, element)
+    __swig_destroy__ = _pywrapcp.delete_SequenceVarElement
+
+ +
+ +

The SequenceVarElement stores a partial representation of ranked +interval variables in the underlying sequence variable.

+ +
This representation consists of three vectors
+ +
+
    +
  • the forward sequence. That is the list of interval variables + ranked first in the sequence. The first element of the backward + sequence is the first interval in the sequence variable.
  • +
  • the backward sequence. That is the list of interval variables + ranked last in the sequence. The first element of the backward + sequence is the last interval in the sequence variable.
  • +
  • The list of unperformed interval variables. + Furthermore, if all performed variables are ranked, then by + convention, the forward_sequence will contain all such variables + and the backward_sequence will be empty.
  • +
+
+
+ + +
+
#   + + + SequenceVarElement(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Var(self) -> 'operations_research::SequenceVar *': +
+ +
+ View Source +
    def Var(self) -> "operations_research::SequenceVar *":
+        return _pywrapcp.SequenceVarElement_Var(self)
+
+ +
+ + + +
+
+
#   + + + def + ForwardSequence(self) -> 'std::vector< int > const &': +
+ +
+ View Source +
    def ForwardSequence(self) -> "std::vector< int > const &":
+        return _pywrapcp.SequenceVarElement_ForwardSequence(self)
+
+ +
+ + + +
+
+
#   + + + def + BackwardSequence(self) -> 'std::vector< int > const &': +
+ +
+ View Source +
    def BackwardSequence(self) -> "std::vector< int > const &":
+        return _pywrapcp.SequenceVarElement_BackwardSequence(self)
+
+ +
+ + + +
+
+
#   + + + def + Unperformed(self) -> 'std::vector< int > const &': +
+ +
+ View Source +
    def Unperformed(self) -> "std::vector< int > const &":
+        return _pywrapcp.SequenceVarElement_Unperformed(self)
+
+ +
+ + + +
+
+
#   + + + def + SetSequence( + self, + forward_sequence: 'std::vector< int > const &', + backward_sequence: 'std::vector< int > const &', + unperformed: 'std::vector< int > const &' +) -> 'void': +
+ +
+ View Source +
    def SetSequence(self, forward_sequence: "std::vector< int > const &", backward_sequence: "std::vector< int > const &", unperformed: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarElement_SetSequence(self, forward_sequence, backward_sequence, unperformed)
+
+ +
+ + + +
+
+
#   + + + def + SetForwardSequence(self, forward_sequence: 'std::vector< int > const &') -> 'void': +
+ +
+ View Source +
    def SetForwardSequence(self, forward_sequence: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarElement_SetForwardSequence(self, forward_sequence)
+
+ +
+ + + +
+
+
#   + + + def + SetBackwardSequence(self, backward_sequence: 'std::vector< int > const &') -> 'void': +
+ +
+ View Source +
    def SetBackwardSequence(self, backward_sequence: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarElement_SetBackwardSequence(self, backward_sequence)
+
+ +
+ + + +
+
+
#   + + + def + SetUnperformed(self, unperformed: 'std::vector< int > const &') -> 'void': +
+ +
+ View Source +
    def SetUnperformed(self, unperformed: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarElement_SetUnperformed(self, unperformed)
+
+ +
+ + + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + Assignment(PropagationBaseObject): +
+ +
+ View Source +
class Assignment(PropagationBaseObject):
+    r"""
+    An Assignment is a variable -> domains mapping, used
+    to report solutions to the user.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Clear(self) -> "void":
+        return _pywrapcp.Assignment_Clear(self)
+
+    def Empty(self) -> "bool":
+        return _pywrapcp.Assignment_Empty(self)
+
+    def Size(self) -> "int":
+        return _pywrapcp.Assignment_Size(self)
+
+    def NumIntVars(self) -> "int":
+        return _pywrapcp.Assignment_NumIntVars(self)
+
+    def NumIntervalVars(self) -> "int":
+        return _pywrapcp.Assignment_NumIntervalVars(self)
+
+    def NumSequenceVars(self) -> "int":
+        return _pywrapcp.Assignment_NumSequenceVars(self)
+
+    def Store(self) -> "void":
+        return _pywrapcp.Assignment_Store(self)
+
+    def Restore(self) -> "void":
+        return _pywrapcp.Assignment_Restore(self)
+
+    def Load(self, *args) -> "void":
+        return _pywrapcp.Assignment_Load(self, *args)
+
+    def Save(self, *args) -> "void":
+        return _pywrapcp.Assignment_Save(self, *args)
+
+    def AddObjective(self, v: "IntVar") -> "void":
+        return _pywrapcp.Assignment_AddObjective(self, v)
+
+    def Objective(self) -> "operations_research::IntVar *":
+        return _pywrapcp.Assignment_Objective(self)
+
+    def HasObjective(self) -> "bool":
+        return _pywrapcp.Assignment_HasObjective(self)
+
+    def ObjectiveMin(self) -> "int64_t":
+        return _pywrapcp.Assignment_ObjectiveMin(self)
+
+    def ObjectiveMax(self) -> "int64_t":
+        return _pywrapcp.Assignment_ObjectiveMax(self)
+
+    def ObjectiveValue(self) -> "int64_t":
+        return _pywrapcp.Assignment_ObjectiveValue(self)
+
+    def ObjectiveBound(self) -> "bool":
+        return _pywrapcp.Assignment_ObjectiveBound(self)
+
+    def SetObjectiveMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetObjectiveMin(self, m)
+
+    def SetObjectiveMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetObjectiveMax(self, m)
+
+    def SetObjectiveValue(self, value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetObjectiveValue(self, value)
+
+    def SetObjectiveRange(self, l: "int64_t", u: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetObjectiveRange(self, l, u)
+
+    def Min(self, var: "IntVar") -> "int64_t":
+        return _pywrapcp.Assignment_Min(self, var)
+
+    def Max(self, var: "IntVar") -> "int64_t":
+        return _pywrapcp.Assignment_Max(self, var)
+
+    def Value(self, var: "IntVar") -> "int64_t":
+        return _pywrapcp.Assignment_Value(self, var)
+
+    def Bound(self, var: "IntVar") -> "bool":
+        return _pywrapcp.Assignment_Bound(self, var)
+
+    def SetMin(self, var: "IntVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetMin(self, var, m)
+
+    def SetMax(self, var: "IntVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetMax(self, var, m)
+
+    def SetRange(self, var: "IntVar", l: "int64_t", u: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetRange(self, var, l, u)
+
+    def SetValue(self, var: "IntVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetValue(self, var, value)
+
+    def StartMin(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_StartMin(self, var)
+
+    def StartMax(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_StartMax(self, var)
+
+    def StartValue(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_StartValue(self, var)
+
+    def DurationMin(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_DurationMin(self, var)
+
+    def DurationMax(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_DurationMax(self, var)
+
+    def DurationValue(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_DurationValue(self, var)
+
+    def EndMin(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_EndMin(self, var)
+
+    def EndMax(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_EndMax(self, var)
+
+    def EndValue(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_EndValue(self, var)
+
+    def PerformedMin(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_PerformedMin(self, var)
+
+    def PerformedMax(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_PerformedMax(self, var)
+
+    def PerformedValue(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_PerformedValue(self, var)
+
+    def SetStartMin(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetStartMin(self, var, m)
+
+    def SetStartMax(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetStartMax(self, var, m)
+
+    def SetStartRange(self, var: "IntervalVar", mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetStartRange(self, var, mi, ma)
+
+    def SetStartValue(self, var: "IntervalVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetStartValue(self, var, value)
+
+    def SetDurationMin(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetDurationMin(self, var, m)
+
+    def SetDurationMax(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetDurationMax(self, var, m)
+
+    def SetDurationRange(self, var: "IntervalVar", mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetDurationRange(self, var, mi, ma)
+
+    def SetDurationValue(self, var: "IntervalVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetDurationValue(self, var, value)
+
+    def SetEndMin(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetEndMin(self, var, m)
+
+    def SetEndMax(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetEndMax(self, var, m)
+
+    def SetEndRange(self, var: "IntervalVar", mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetEndRange(self, var, mi, ma)
+
+    def SetEndValue(self, var: "IntervalVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetEndValue(self, var, value)
+
+    def SetPerformedMin(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetPerformedMin(self, var, m)
+
+    def SetPerformedMax(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetPerformedMax(self, var, m)
+
+    def SetPerformedRange(self, var: "IntervalVar", mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetPerformedRange(self, var, mi, ma)
+
+    def SetPerformedValue(self, var: "IntervalVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetPerformedValue(self, var, value)
+
+    def Add(self, *args) -> "void":
+        return _pywrapcp.Assignment_Add(self, *args)
+
+    def ForwardSequence(self, var: "SequenceVar") -> "std::vector< int > const &":
+        return _pywrapcp.Assignment_ForwardSequence(self, var)
+
+    def BackwardSequence(self, var: "SequenceVar") -> "std::vector< int > const &":
+        return _pywrapcp.Assignment_BackwardSequence(self, var)
+
+    def Unperformed(self, var: "SequenceVar") -> "std::vector< int > const &":
+        return _pywrapcp.Assignment_Unperformed(self, var)
+
+    def SetSequence(self, var: "SequenceVar", forward_sequence: "std::vector< int > const &", backward_sequence: "std::vector< int > const &", unperformed: "std::vector< int > const &") -> "void":
+        return _pywrapcp.Assignment_SetSequence(self, var, forward_sequence, backward_sequence, unperformed)
+
+    def SetForwardSequence(self, var: "SequenceVar", forward_sequence: "std::vector< int > const &") -> "void":
+        return _pywrapcp.Assignment_SetForwardSequence(self, var, forward_sequence)
+
+    def SetBackwardSequence(self, var: "SequenceVar", backward_sequence: "std::vector< int > const &") -> "void":
+        return _pywrapcp.Assignment_SetBackwardSequence(self, var, backward_sequence)
+
+    def SetUnperformed(self, var: "SequenceVar", unperformed: "std::vector< int > const &") -> "void":
+        return _pywrapcp.Assignment_SetUnperformed(self, var, unperformed)
+
+    def Activate(self, *args) -> "void":
+        return _pywrapcp.Assignment_Activate(self, *args)
+
+    def Deactivate(self, *args) -> "void":
+        return _pywrapcp.Assignment_Deactivate(self, *args)
+
+    def Activated(self, *args) -> "bool":
+        return _pywrapcp.Assignment_Activated(self, *args)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.Assignment_DebugString(self)
+
+    def IntVarContainer(self) -> "operations_research::Assignment::IntContainer const &":
+        return _pywrapcp.Assignment_IntVarContainer(self)
+
+    def MutableIntVarContainer(self) -> "operations_research::Assignment::IntContainer *":
+        return _pywrapcp.Assignment_MutableIntVarContainer(self)
+
+    def IntervalVarContainer(self) -> "operations_research::Assignment::IntervalContainer const &":
+        return _pywrapcp.Assignment_IntervalVarContainer(self)
+
+    def MutableIntervalVarContainer(self) -> "operations_research::Assignment::IntervalContainer *":
+        return _pywrapcp.Assignment_MutableIntervalVarContainer(self)
+
+    def SequenceVarContainer(self) -> "operations_research::Assignment::SequenceContainer const &":
+        return _pywrapcp.Assignment_SequenceVarContainer(self)
+
+    def MutableSequenceVarContainer(self) -> "operations_research::Assignment::SequenceContainer *":
+        return _pywrapcp.Assignment_MutableSequenceVarContainer(self)
+
+    def __eq__(self, assignment: "Assignment") -> "bool":
+        return _pywrapcp.Assignment___eq__(self, assignment)
+
+    def __ne__(self, assignment: "Assignment") -> "bool":
+        return _pywrapcp.Assignment___ne__(self, assignment)
+
+ +
+ +

An Assignment is a variable -> domains mapping, used +to report solutions to the user.

+
+ + +
+
#   + + + Assignment(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Clear(self) -> 'void': +
+ +
+ View Source +
    def Clear(self) -> "void":
+        return _pywrapcp.Assignment_Clear(self)
+
+ +
+ + + +
+
+
#   + + + def + Empty(self) -> bool: +
+ +
+ View Source +
    def Empty(self) -> "bool":
+        return _pywrapcp.Assignment_Empty(self)
+
+ +
+ + + +
+
+
#   + + + def + Size(self) -> int: +
+ +
+ View Source +
    def Size(self) -> "int":
+        return _pywrapcp.Assignment_Size(self)
+
+ +
+ + + +
+
+
#   + + + def + NumIntVars(self) -> int: +
+ +
+ View Source +
    def NumIntVars(self) -> "int":
+        return _pywrapcp.Assignment_NumIntVars(self)
+
+ +
+ + + +
+
+
#   + + + def + NumIntervalVars(self) -> int: +
+ +
+ View Source +
    def NumIntervalVars(self) -> "int":
+        return _pywrapcp.Assignment_NumIntervalVars(self)
+
+ +
+ + + +
+
+
#   + + + def + NumSequenceVars(self) -> int: +
+ +
+ View Source +
    def NumSequenceVars(self) -> "int":
+        return _pywrapcp.Assignment_NumSequenceVars(self)
+
+ +
+ + + +
+
+
#   + + + def + Store(self) -> 'void': +
+ +
+ View Source +
    def Store(self) -> "void":
+        return _pywrapcp.Assignment_Store(self)
+
+ +
+ + + +
+
+
#   + + + def + Restore(self) -> 'void': +
+ +
+ View Source +
    def Restore(self) -> "void":
+        return _pywrapcp.Assignment_Restore(self)
+
+ +
+ + + +
+
+
#   + + + def + Load(self, *args) -> 'void': +
+ +
+ View Source +
    def Load(self, *args) -> "void":
+        return _pywrapcp.Assignment_Load(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + Save(self, *args) -> 'void': +
+ +
+ View Source +
    def Save(self, *args) -> "void":
+        return _pywrapcp.Assignment_Save(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + AddObjective(self, v: ortools.constraint_solver.pywrapcp.IntVar) -> 'void': +
+ +
+ View Source +
    def AddObjective(self, v: "IntVar") -> "void":
+        return _pywrapcp.Assignment_AddObjective(self, v)
+
+ +
+ + + +
+
+
#   + + + def + Objective(self) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def Objective(self) -> "operations_research::IntVar *":
+        return _pywrapcp.Assignment_Objective(self)
+
+ +
+ + + +
+
+
#   + + + def + HasObjective(self) -> bool: +
+ +
+ View Source +
    def HasObjective(self) -> "bool":
+        return _pywrapcp.Assignment_HasObjective(self)
+
+ +
+ + + +
+
+
#   + + + def + ObjectiveMin(self) -> 'int64_t': +
+ +
+ View Source +
    def ObjectiveMin(self) -> "int64_t":
+        return _pywrapcp.Assignment_ObjectiveMin(self)
+
+ +
+ + + +
+
+
#   + + + def + ObjectiveMax(self) -> 'int64_t': +
+ +
+ View Source +
    def ObjectiveMax(self) -> "int64_t":
+        return _pywrapcp.Assignment_ObjectiveMax(self)
+
+ +
+ + + +
+
+
#   + + + def + ObjectiveValue(self) -> 'int64_t': +
+ +
+ View Source +
    def ObjectiveValue(self) -> "int64_t":
+        return _pywrapcp.Assignment_ObjectiveValue(self)
+
+ +
+ + + +
+
+
#   + + + def + ObjectiveBound(self) -> bool: +
+ +
+ View Source +
    def ObjectiveBound(self) -> "bool":
+        return _pywrapcp.Assignment_ObjectiveBound(self)
+
+ +
+ + + +
+
+
#   + + + def + SetObjectiveMin(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetObjectiveMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetObjectiveMin(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetObjectiveMax(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetObjectiveMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetObjectiveMax(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetObjectiveValue(self, value: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetObjectiveValue(self, value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetObjectiveValue(self, value)
+
+ +
+ + + +
+
+
#   + + + def + SetObjectiveRange(self, l: 'int64_t', u: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetObjectiveRange(self, l: "int64_t", u: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetObjectiveRange(self, l, u)
+
+ +
+ + + +
+
+
#   + + + def + Min(self, var: ortools.constraint_solver.pywrapcp.IntVar) -> 'int64_t': +
+ +
+ View Source +
    def Min(self, var: "IntVar") -> "int64_t":
+        return _pywrapcp.Assignment_Min(self, var)
+
+ +
+ + + +
+
+
#   + + + def + Max(self, var: ortools.constraint_solver.pywrapcp.IntVar) -> 'int64_t': +
+ +
+ View Source +
    def Max(self, var: "IntVar") -> "int64_t":
+        return _pywrapcp.Assignment_Max(self, var)
+
+ +
+ + + +
+
+
#   + + + def + Value(self, var: ortools.constraint_solver.pywrapcp.IntVar) -> 'int64_t': +
+ +
+ View Source +
    def Value(self, var: "IntVar") -> "int64_t":
+        return _pywrapcp.Assignment_Value(self, var)
+
+ +
+ + + +
+
+
#   + + + def + Bound(self, var: ortools.constraint_solver.pywrapcp.IntVar) -> bool: +
+ +
+ View Source +
    def Bound(self, var: "IntVar") -> "bool":
+        return _pywrapcp.Assignment_Bound(self, var)
+
+ +
+ + + +
+
+
#   + + + def + SetMin( + self, + var: ortools.constraint_solver.pywrapcp.IntVar, + m: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetMin(self, var: "IntVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetMin(self, var, m)
+
+ +
+ + + +
+
+
#   + + + def + SetMax( + self, + var: ortools.constraint_solver.pywrapcp.IntVar, + m: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetMax(self, var: "IntVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetMax(self, var, m)
+
+ +
+ + + +
+
+
#   + + + def + SetRange( + self, + var: ortools.constraint_solver.pywrapcp.IntVar, + l: 'int64_t', + u: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetRange(self, var: "IntVar", l: "int64_t", u: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetRange(self, var, l, u)
+
+ +
+ + + +
+
+
#   + + + def + SetValue( + self, + var: ortools.constraint_solver.pywrapcp.IntVar, + value: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetValue(self, var: "IntVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetValue(self, var, value)
+
+ +
+ + + +
+
+
#   + + + def + StartMin( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def StartMin(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_StartMin(self, var)
+
+ +
+ + + +
+
+
#   + + + def + StartMax( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def StartMax(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_StartMax(self, var)
+
+ +
+ + + +
+
+
#   + + + def + StartValue( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def StartValue(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_StartValue(self, var)
+
+ +
+ + + +
+
+
#   + + + def + DurationMin( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def DurationMin(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_DurationMin(self, var)
+
+ +
+ + + +
+
+
#   + + + def + DurationMax( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def DurationMax(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_DurationMax(self, var)
+
+ +
+ + + +
+
+
#   + + + def + DurationValue( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def DurationValue(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_DurationValue(self, var)
+
+ +
+ + + +
+
+
#   + + + def + EndMin( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def EndMin(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_EndMin(self, var)
+
+ +
+ + + +
+
+
#   + + + def + EndMax( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def EndMax(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_EndMax(self, var)
+
+ +
+ + + +
+
+
#   + + + def + EndValue( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def EndValue(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_EndValue(self, var)
+
+ +
+ + + +
+
+
#   + + + def + PerformedMin( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def PerformedMin(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_PerformedMin(self, var)
+
+ +
+ + + +
+
+
#   + + + def + PerformedMax( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def PerformedMax(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_PerformedMax(self, var)
+
+ +
+ + + +
+
+
#   + + + def + PerformedValue( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'int64_t': +
+ +
+ View Source +
    def PerformedValue(self, var: "IntervalVar") -> "int64_t":
+        return _pywrapcp.Assignment_PerformedValue(self, var)
+
+ +
+ + + +
+
+
#   + + + def + SetStartMin( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + m: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetStartMin(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetStartMin(self, var, m)
+
+ +
+ + + +
+
+
#   + + + def + SetStartMax( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + m: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetStartMax(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetStartMax(self, var, m)
+
+ +
+ + + +
+
+
#   + + + def + SetStartRange( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + mi: 'int64_t', + ma: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetStartRange(self, var: "IntervalVar", mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetStartRange(self, var, mi, ma)
+
+ +
+ + + +
+
+
#   + + + def + SetStartValue( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + value: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetStartValue(self, var: "IntervalVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetStartValue(self, var, value)
+
+ +
+ + + +
+
+
#   + + + def + SetDurationMin( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + m: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetDurationMin(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetDurationMin(self, var, m)
+
+ +
+ + + +
+
+
#   + + + def + SetDurationMax( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + m: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetDurationMax(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetDurationMax(self, var, m)
+
+ +
+ + + +
+
+
#   + + + def + SetDurationRange( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + mi: 'int64_t', + ma: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetDurationRange(self, var: "IntervalVar", mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetDurationRange(self, var, mi, ma)
+
+ +
+ + + +
+
+
#   + + + def + SetDurationValue( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + value: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetDurationValue(self, var: "IntervalVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetDurationValue(self, var, value)
+
+ +
+ + + +
+
+
#   + + + def + SetEndMin( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + m: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetEndMin(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetEndMin(self, var, m)
+
+ +
+ + + +
+
+
#   + + + def + SetEndMax( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + m: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetEndMax(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetEndMax(self, var, m)
+
+ +
+ + + +
+
+
#   + + + def + SetEndRange( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + mi: 'int64_t', + ma: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetEndRange(self, var: "IntervalVar", mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetEndRange(self, var, mi, ma)
+
+ +
+ + + +
+
+
#   + + + def + SetEndValue( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + value: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetEndValue(self, var: "IntervalVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetEndValue(self, var, value)
+
+ +
+ + + +
+
+
#   + + + def + SetPerformedMin( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + m: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetPerformedMin(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetPerformedMin(self, var, m)
+
+ +
+ + + +
+
+
#   + + + def + SetPerformedMax( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + m: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetPerformedMax(self, var: "IntervalVar", m: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetPerformedMax(self, var, m)
+
+ +
+ + + +
+
+
#   + + + def + SetPerformedRange( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + mi: 'int64_t', + ma: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetPerformedRange(self, var: "IntervalVar", mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetPerformedRange(self, var, mi, ma)
+
+ +
+ + + +
+
+
#   + + + def + SetPerformedValue( + self, + var: ortools.constraint_solver.pywrapcp.IntervalVar, + value: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetPerformedValue(self, var: "IntervalVar", value: "int64_t") -> "void":
+        return _pywrapcp.Assignment_SetPerformedValue(self, var, value)
+
+ +
+ + + +
+
+
#   + + + def + Add(self, *args) -> 'void': +
+ +
+ View Source +
    def Add(self, *args) -> "void":
+        return _pywrapcp.Assignment_Add(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + ForwardSequence( + self, + var: ortools.constraint_solver.pywrapcp.SequenceVar +) -> 'std::vector< int > const &': +
+ +
+ View Source +
    def ForwardSequence(self, var: "SequenceVar") -> "std::vector< int > const &":
+        return _pywrapcp.Assignment_ForwardSequence(self, var)
+
+ +
+ + + +
+
+
#   + + + def + BackwardSequence( + self, + var: ortools.constraint_solver.pywrapcp.SequenceVar +) -> 'std::vector< int > const &': +
+ +
+ View Source +
    def BackwardSequence(self, var: "SequenceVar") -> "std::vector< int > const &":
+        return _pywrapcp.Assignment_BackwardSequence(self, var)
+
+ +
+ + + +
+
+
#   + + + def + Unperformed( + self, + var: ortools.constraint_solver.pywrapcp.SequenceVar +) -> 'std::vector< int > const &': +
+ +
+ View Source +
    def Unperformed(self, var: "SequenceVar") -> "std::vector< int > const &":
+        return _pywrapcp.Assignment_Unperformed(self, var)
+
+ +
+ + + +
+
+
#   + + + def + SetSequence( + self, + var: ortools.constraint_solver.pywrapcp.SequenceVar, + forward_sequence: 'std::vector< int > const &', + backward_sequence: 'std::vector< int > const &', + unperformed: 'std::vector< int > const &' +) -> 'void': +
+ +
+ View Source +
    def SetSequence(self, var: "SequenceVar", forward_sequence: "std::vector< int > const &", backward_sequence: "std::vector< int > const &", unperformed: "std::vector< int > const &") -> "void":
+        return _pywrapcp.Assignment_SetSequence(self, var, forward_sequence, backward_sequence, unperformed)
+
+ +
+ + + +
+
+
#   + + + def + SetForwardSequence( + self, + var: ortools.constraint_solver.pywrapcp.SequenceVar, + forward_sequence: 'std::vector< int > const &' +) -> 'void': +
+ +
+ View Source +
    def SetForwardSequence(self, var: "SequenceVar", forward_sequence: "std::vector< int > const &") -> "void":
+        return _pywrapcp.Assignment_SetForwardSequence(self, var, forward_sequence)
+
+ +
+ + + +
+
+
#   + + + def + SetBackwardSequence( + self, + var: ortools.constraint_solver.pywrapcp.SequenceVar, + backward_sequence: 'std::vector< int > const &' +) -> 'void': +
+ +
+ View Source +
    def SetBackwardSequence(self, var: "SequenceVar", backward_sequence: "std::vector< int > const &") -> "void":
+        return _pywrapcp.Assignment_SetBackwardSequence(self, var, backward_sequence)
+
+ +
+ + + +
+
+
#   + + + def + SetUnperformed( + self, + var: ortools.constraint_solver.pywrapcp.SequenceVar, + unperformed: 'std::vector< int > const &' +) -> 'void': +
+ +
+ View Source +
    def SetUnperformed(self, var: "SequenceVar", unperformed: "std::vector< int > const &") -> "void":
+        return _pywrapcp.Assignment_SetUnperformed(self, var, unperformed)
+
+ +
+ + + +
+
+
#   + + + def + Activate(self, *args) -> 'void': +
+ +
+ View Source +
    def Activate(self, *args) -> "void":
+        return _pywrapcp.Assignment_Activate(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + Deactivate(self, *args) -> 'void': +
+ +
+ View Source +
    def Deactivate(self, *args) -> "void":
+        return _pywrapcp.Assignment_Deactivate(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + Activated(self, *args) -> bool: +
+ +
+ View Source +
    def Activated(self, *args) -> "bool":
+        return _pywrapcp.Assignment_Activated(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.Assignment_DebugString(self)
+
+ +
+ + + +
+
+
#   + + + def + IntVarContainer(self) -> 'operations_research::Assignment::IntContainer const &': +
+ +
+ View Source +
    def IntVarContainer(self) -> "operations_research::Assignment::IntContainer const &":
+        return _pywrapcp.Assignment_IntVarContainer(self)
+
+ +
+ + + +
+
+
#   + + + def + MutableIntVarContainer(self) -> 'operations_research::Assignment::IntContainer *': +
+ +
+ View Source +
    def MutableIntVarContainer(self) -> "operations_research::Assignment::IntContainer *":
+        return _pywrapcp.Assignment_MutableIntVarContainer(self)
+
+ +
+ + + +
+
+
#   + + + def + IntervalVarContainer(self) -> 'operations_research::Assignment::IntervalContainer const &': +
+ +
+ View Source +
    def IntervalVarContainer(self) -> "operations_research::Assignment::IntervalContainer const &":
+        return _pywrapcp.Assignment_IntervalVarContainer(self)
+
+ +
+ + + +
+
+
#   + + + def + MutableIntervalVarContainer(self) -> 'operations_research::Assignment::IntervalContainer *': +
+ +
+ View Source +
    def MutableIntervalVarContainer(self) -> "operations_research::Assignment::IntervalContainer *":
+        return _pywrapcp.Assignment_MutableIntervalVarContainer(self)
+
+ +
+ + + +
+
+
#   + + + def + SequenceVarContainer(self) -> 'operations_research::Assignment::SequenceContainer const &': +
+ +
+ View Source +
    def SequenceVarContainer(self) -> "operations_research::Assignment::SequenceContainer const &":
+        return _pywrapcp.Assignment_SequenceVarContainer(self)
+
+ +
+ + + +
+
+
#   + + + def + MutableSequenceVarContainer(self) -> 'operations_research::Assignment::SequenceContainer *': +
+ +
+ View Source +
    def MutableSequenceVarContainer(self) -> "operations_research::Assignment::SequenceContainer *":
+        return _pywrapcp.Assignment_MutableSequenceVarContainer(self)
+
+ +
+ + + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + Pack(Constraint): +
+ +
+ View Source +
class Pack(Constraint):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def AddWeightedSumLessOrEqualConstantDimension(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        Dimensions are additional constraints than can restrict what is
+        possible with the pack constraint. It can be used to set capacity
+        limits, to count objects per bin, to compute unassigned
+        penalties...
+        This dimension imposes that for all bins b, the weighted sum
+        (weights[i]) of all objects i assigned to 'b' is less or equal
+        'bounds[b]'.
+
+        |
+
+        *Overload 2:*
+        This dimension imposes that for all bins b, the weighted sum
+        (weights->Run(i)) of all objects i assigned to 'b' is less or
+        equal to 'bounds[b]'. Ownership of the callback is transferred to
+        the pack constraint.
+
+        |
+
+        *Overload 3:*
+        This dimension imposes that for all bins b, the weighted sum
+        (weights->Run(i, b) of all objects i assigned to 'b' is less or
+        equal to 'bounds[b]'. Ownership of the callback is transferred to
+        the pack constraint.
+        """
+        return _pywrapcp.Pack_AddWeightedSumLessOrEqualConstantDimension(self, *args)
+
+    def AddWeightedSumEqualVarDimension(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        This dimension imposes that for all bins b, the weighted sum
+        (weights[i]) of all objects i assigned to 'b' is equal to loads[b].
+
+        |
+
+        *Overload 2:*
+        This dimension imposes that for all bins b, the weighted sum
+        (weights->Run(i, b)) of all objects i assigned to 'b' is equal to
+        loads[b].
+        """
+        return _pywrapcp.Pack_AddWeightedSumEqualVarDimension(self, *args)
+
+    def AddSumVariableWeightsLessOrEqualConstantDimension(self, usage: "std::vector< operations_research::IntVar * > const &", capacity: "std::vector< int64_t > const &") -> "void":
+        r"""
+        This dimension imposes:
+        forall b in bins,
+           sum (i in items: usage[i] * is_assigned(i, b)) <= capacity[b]
+        where is_assigned(i, b) is true if and only if item i is assigned
+        to the bin b.
+
+        This can be used to model shapes of items by linking variables of
+        the same item on parallel dimensions with an allowed assignment
+        constraint.
+        """
+        return _pywrapcp.Pack_AddSumVariableWeightsLessOrEqualConstantDimension(self, usage, capacity)
+
+    def AddWeightedSumOfAssignedDimension(self, weights: "std::vector< int64_t > const &", cost_var: "IntVar") -> "void":
+        r"""
+        This dimension enforces that cost_var == sum of weights[i] for
+        all objects 'i' assigned to a bin.
+        """
+        return _pywrapcp.Pack_AddWeightedSumOfAssignedDimension(self, weights, cost_var)
+
+    def AddCountUsedBinDimension(self, count_var: "IntVar") -> "void":
+        r"""
+        This dimension links 'count_var' to the actual number of bins used in the
+        pack.
+        """
+        return _pywrapcp.Pack_AddCountUsedBinDimension(self, count_var)
+
+    def AddCountAssignedItemsDimension(self, count_var: "IntVar") -> "void":
+        r"""
+        This dimension links 'count_var' to the actual number of items
+        assigned to a bin in the pack.
+        """
+        return _pywrapcp.Pack_AddCountAssignedItemsDimension(self, count_var)
+
+    def Post(self) -> "void":
+        return _pywrapcp.Pack_Post(self)
+
+    def InitialPropagateWrapper(self) -> "void":
+        return _pywrapcp.Pack_InitialPropagateWrapper(self)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.Pack_DebugString(self)
+
+ +
+ +

A constraint is the main modeling object. It provides two methods:

+ +
    +
  • Post() is responsible for creating the demons and attaching them to +immediate demons().
  • +
  • InitialPropagate() is called once just after Post and performs +the initial propagation. The subsequent propagations will be performed +by the demons Posted during the post() method.
  • +
+
+ + +
+
#   + + + Pack(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + AddWeightedSumLessOrEqualConstantDimension(self, *args) -> 'void': +
+ +
+ View Source +
    def AddWeightedSumLessOrEqualConstantDimension(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        Dimensions are additional constraints than can restrict what is
+        possible with the pack constraint. It can be used to set capacity
+        limits, to count objects per bin, to compute unassigned
+        penalties...
+        This dimension imposes that for all bins b, the weighted sum
+        (weights[i]) of all objects i assigned to 'b' is less or equal
+        'bounds[b]'.
+
+        |
+
+        *Overload 2:*
+        This dimension imposes that for all bins b, the weighted sum
+        (weights->Run(i)) of all objects i assigned to 'b' is less or
+        equal to 'bounds[b]'. Ownership of the callback is transferred to
+        the pack constraint.
+
+        |
+
+        *Overload 3:*
+        This dimension imposes that for all bins b, the weighted sum
+        (weights->Run(i, b) of all objects i assigned to 'b' is less or
+        equal to 'bounds[b]'. Ownership of the callback is transferred to
+        the pack constraint.
+        """
+        return _pywrapcp.Pack_AddWeightedSumLessOrEqualConstantDimension(self, *args)
+
+ +
+ +

Overload 1: +Dimensions are additional constraints than can restrict what is +possible with the pack constraint. It can be used to set capacity +limits, to count objects per bin, to compute unassigned +penalties... +This dimension imposes that for all bins b, the weighted sum +(weights[i]) of all objects i assigned to 'b' is less or equal +'bounds[b]'.

+ +

|

+ +

Overload 2: +This dimension imposes that for all bins b, the weighted sum +(weights->Run(i)) of all objects i assigned to 'b' is less or +equal to 'bounds[b]'. Ownership of the callback is transferred to +the pack constraint.

+ +

|

+ +

Overload 3: +This dimension imposes that for all bins b, the weighted sum +(weights->Run(i, b) of all objects i assigned to 'b' is less or +equal to 'bounds[b]'. Ownership of the callback is transferred to +the pack constraint.

+
+ + +
+
+
#   + + + def + AddWeightedSumEqualVarDimension(self, *args) -> 'void': +
+ +
+ View Source +
    def AddWeightedSumEqualVarDimension(self, *args) -> "void":
+        r"""
+        *Overload 1:*
+        This dimension imposes that for all bins b, the weighted sum
+        (weights[i]) of all objects i assigned to 'b' is equal to loads[b].
+
+        |
+
+        *Overload 2:*
+        This dimension imposes that for all bins b, the weighted sum
+        (weights->Run(i, b)) of all objects i assigned to 'b' is equal to
+        loads[b].
+        """
+        return _pywrapcp.Pack_AddWeightedSumEqualVarDimension(self, *args)
+
+ +
+ +

Overload 1: +This dimension imposes that for all bins b, the weighted sum +(weights[i]) of all objects i assigned to 'b' is equal to loads[b].

+ +

|

+ +

Overload 2: +This dimension imposes that for all bins b, the weighted sum +(weights->Run(i, b)) of all objects i assigned to 'b' is equal to +loads[b].

+
+ + +
+
+
#   + + + def + AddSumVariableWeightsLessOrEqualConstantDimension( + self, + usage: 'std::vector< operations_research::IntVar * > const &', + capacity: 'std::vector< int64_t > const &' +) -> 'void': +
+ +
+ View Source +
    def AddSumVariableWeightsLessOrEqualConstantDimension(self, usage: "std::vector< operations_research::IntVar * > const &", capacity: "std::vector< int64_t > const &") -> "void":
+        r"""
+        This dimension imposes:
+        forall b in bins,
+           sum (i in items: usage[i] * is_assigned(i, b)) <= capacity[b]
+        where is_assigned(i, b) is true if and only if item i is assigned
+        to the bin b.
+
+        This can be used to model shapes of items by linking variables of
+        the same item on parallel dimensions with an allowed assignment
+        constraint.
+        """
+        return _pywrapcp.Pack_AddSumVariableWeightsLessOrEqualConstantDimension(self, usage, capacity)
+
+ +
+ +

This dimension imposes: +forall b in bins, + sum (i in items: usage[i] * is_assigned(i, b)) <= capacity[b] +where is_assigned(i, b) is true if and only if item i is assigned +to the bin b.

+ +

This can be used to model shapes of items by linking variables of +the same item on parallel dimensions with an allowed assignment +constraint.

+
+ + +
+
+
#   + + + def + AddWeightedSumOfAssignedDimension( + self, + weights: 'std::vector< int64_t > const &', + cost_var: ortools.constraint_solver.pywrapcp.IntVar +) -> 'void': +
+ +
+ View Source +
    def AddWeightedSumOfAssignedDimension(self, weights: "std::vector< int64_t > const &", cost_var: "IntVar") -> "void":
+        r"""
+        This dimension enforces that cost_var == sum of weights[i] for
+        all objects 'i' assigned to a bin.
+        """
+        return _pywrapcp.Pack_AddWeightedSumOfAssignedDimension(self, weights, cost_var)
+
+ +
+ +

This dimension enforces that cost_var == sum of weights[i] for +all objects 'i' assigned to a bin.

+
+ + +
+
+
#   + + + def + AddCountUsedBinDimension(self, count_var: ortools.constraint_solver.pywrapcp.IntVar) -> 'void': +
+ +
+ View Source +
    def AddCountUsedBinDimension(self, count_var: "IntVar") -> "void":
+        r"""
+        This dimension links 'count_var' to the actual number of bins used in the
+        pack.
+        """
+        return _pywrapcp.Pack_AddCountUsedBinDimension(self, count_var)
+
+ +
+ +

This dimension links 'count_var' to the actual number of bins used in the +pack.

+
+ + +
+
+
#   + + + def + AddCountAssignedItemsDimension(self, count_var: ortools.constraint_solver.pywrapcp.IntVar) -> 'void': +
+ +
+ View Source +
    def AddCountAssignedItemsDimension(self, count_var: "IntVar") -> "void":
+        r"""
+        This dimension links 'count_var' to the actual number of items
+        assigned to a bin in the pack.
+        """
+        return _pywrapcp.Pack_AddCountAssignedItemsDimension(self, count_var)
+
+ +
+ +

This dimension links 'count_var' to the actual number of items +assigned to a bin in the pack.

+
+ + +
+
+
#   + + + def + Post(self) -> 'void': +
+ +
+ View Source +
    def Post(self) -> "void":
+        return _pywrapcp.Pack_Post(self)
+
+ +
+ +

This method is called when the constraint is processed by the +solver. Its main usage is to attach demons to variables.

+
+ + +
+
+
#   + + + def + InitialPropagateWrapper(self) -> 'void': +
+ +
+ View Source +
    def InitialPropagateWrapper(self) -> "void":
+        return _pywrapcp.Pack_InitialPropagateWrapper(self)
+
+ +
+ +

This method performs the initial propagation of the +constraint. It is called just after the post.

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.Pack_DebugString(self)
+
+ +
+ + + +
+
+
Inherited Members
+
+ + +
+
+
+
+
+ #   + + + class + DisjunctiveConstraint(Constraint): +
+ +
+ View Source +
class DisjunctiveConstraint(Constraint):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def SequenceVar(self) -> "operations_research::SequenceVar *":
+        r""" Creates a sequence variable from the constraint."""
+        return _pywrapcp.DisjunctiveConstraint_SequenceVar(self)
+
+    def SetTransitionTime(self, transition_time: "operations_research::Solver::IndexEvaluator2") -> "void":
+        r"""
+        Add a transition time between intervals.  It forces the distance between
+        the end of interval a and start of interval b that follows it to be at
+        least transition_time(a, b). This function must always return
+        a positive or null value.
+        """
+        return _pywrapcp.DisjunctiveConstraint_SetTransitionTime(self, transition_time)
+
+    def TransitionTime(self, before_index: "int", after_index: "int") -> "int64_t":
+        return _pywrapcp.DisjunctiveConstraint_TransitionTime(self, before_index, after_index)
+
+ +
+ +

A constraint is the main modeling object. It provides two methods:

+ +
    +
  • Post() is responsible for creating the demons and attaching them to +immediate demons().
  • +
  • InitialPropagate() is called once just after Post and performs +the initial propagation. The subsequent propagations will be performed +by the demons Posted during the post() method.
  • +
+
+ + +
+
#   + + + DisjunctiveConstraint(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + SequenceVar(self) -> 'operations_research::SequenceVar *': +
+ +
+ View Source +
    def SequenceVar(self) -> "operations_research::SequenceVar *":
+        r""" Creates a sequence variable from the constraint."""
+        return _pywrapcp.DisjunctiveConstraint_SequenceVar(self)
+
+ +
+ +

Creates a sequence variable from the constraint.

+
+ + +
+
+
#   + + + def + SetTransitionTime( + self, + transition_time: 'operations_research::Solver::IndexEvaluator2' +) -> 'void': +
+ +
+ View Source +
    def SetTransitionTime(self, transition_time: "operations_research::Solver::IndexEvaluator2") -> "void":
+        r"""
+        Add a transition time between intervals.  It forces the distance between
+        the end of interval a and start of interval b that follows it to be at
+        least transition_time(a, b). This function must always return
+        a positive or null value.
+        """
+        return _pywrapcp.DisjunctiveConstraint_SetTransitionTime(self, transition_time)
+
+ +
+ +

Add a transition time between intervals. It forces the distance between +the end of interval a and start of interval b that follows it to be at +least transition_time(a, b). This function must always return +a positive or null value.

+
+ + +
+
+
#   + + + def + TransitionTime(self, before_index: int, after_index: int) -> 'int64_t': +
+ +
+ View Source +
    def TransitionTime(self, before_index: "int", after_index: "int") -> "int64_t":
+        return _pywrapcp.DisjunctiveConstraint_TransitionTime(self, before_index, after_index)
+
+ +
+ + + +
+
+
Inherited Members
+
+ + +
+
+
+
+
+ #   + + + class + RevInteger: +
+ +
+ View Source +
class RevInteger(object):
+    r"""
+    This class adds reversibility to a POD type.
+    It contains the stamp optimization. i.e. the SaveValue call is done
+    only once per node of the search tree.  Please note that actual
+    stamps always starts at 1, thus an initial value of 0 will always
+    trigger the first SaveValue.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, val: "long const &"):
+        _pywrapcp.RevInteger_swiginit(self, _pywrapcp.new_RevInteger(val))
+
+    def Value(self) -> "long const &":
+        return _pywrapcp.RevInteger_Value(self)
+
+    def SetValue(self, s: "Solver", val: "long const &") -> "void":
+        return _pywrapcp.RevInteger_SetValue(self, s, val)
+    __swig_destroy__ = _pywrapcp.delete_RevInteger
+
+ +
+ +

This class adds reversibility to a POD type. +It contains the stamp optimization. i.e. the SaveValue call is done +only once per node of the search tree. Please note that actual +stamps always starts at 1, thus an initial value of 0 will always +trigger the first SaveValue.

+
+ + +
+
#   + + + RevInteger(val: 'long const &') +
+ +
+ View Source +
    def __init__(self, val: "long const &"):
+        _pywrapcp.RevInteger_swiginit(self, _pywrapcp.new_RevInteger(val))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Value(self) -> 'long const &': +
+ +
+ View Source +
    def Value(self) -> "long const &":
+        return _pywrapcp.RevInteger_Value(self)
+
+ +
+ + + +
+
+
#   + + + def + SetValue( + self, + s: ortools.constraint_solver.pywrapcp.Solver, + val: 'long const &' +) -> 'void': +
+ +
+ View Source +
    def SetValue(self, s: "Solver", val: "long const &") -> "void":
+        return _pywrapcp.RevInteger_SetValue(self, s, val)
+
+ +
+ + + +
+
+
+
+ #   + + + class + NumericalRevInteger(RevInteger): +
+ +
+ View Source +
class NumericalRevInteger(RevInteger):
+    r""" Subclass of Rev<T> which adds numerical operations."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, val: "long const &"):
+        _pywrapcp.NumericalRevInteger_swiginit(self, _pywrapcp.new_NumericalRevInteger(val))
+
+    def Add(self, s: "Solver", to_add: "long const &") -> "void":
+        return _pywrapcp.NumericalRevInteger_Add(self, s, to_add)
+
+    def Incr(self, s: "Solver") -> "void":
+        return _pywrapcp.NumericalRevInteger_Incr(self, s)
+
+    def Decr(self, s: "Solver") -> "void":
+        return _pywrapcp.NumericalRevInteger_Decr(self, s)
+    __swig_destroy__ = _pywrapcp.delete_NumericalRevInteger
+
+ +
+ +

Subclass of Rev which adds numerical operations.

+
+ + +
+
#   + + + NumericalRevInteger(val: 'long const &') +
+ +
+ View Source +
    def __init__(self, val: "long const &"):
+        _pywrapcp.NumericalRevInteger_swiginit(self, _pywrapcp.new_NumericalRevInteger(val))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Add( + self, + s: ortools.constraint_solver.pywrapcp.Solver, + to_add: 'long const &' +) -> 'void': +
+ +
+ View Source +
    def Add(self, s: "Solver", to_add: "long const &") -> "void":
+        return _pywrapcp.NumericalRevInteger_Add(self, s, to_add)
+
+ +
+ + + +
+
+
#   + + + def + Incr(self, s: ortools.constraint_solver.pywrapcp.Solver) -> 'void': +
+ +
+ View Source +
    def Incr(self, s: "Solver") -> "void":
+        return _pywrapcp.NumericalRevInteger_Incr(self, s)
+
+ +
+ + + +
+
+
#   + + + def + Decr(self, s: ortools.constraint_solver.pywrapcp.Solver) -> 'void': +
+ +
+ View Source +
    def Decr(self, s: "Solver") -> "void":
+        return _pywrapcp.NumericalRevInteger_Decr(self, s)
+
+ +
+ + + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + RevBool: +
+ +
+ View Source +
class RevBool(object):
+    r"""
+    This class adds reversibility to a POD type.
+    It contains the stamp optimization. i.e. the SaveValue call is done
+    only once per node of the search tree.  Please note that actual
+    stamps always starts at 1, thus an initial value of 0 will always
+    trigger the first SaveValue.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, val: "bool const &"):
+        _pywrapcp.RevBool_swiginit(self, _pywrapcp.new_RevBool(val))
+
+    def Value(self) -> "bool const &":
+        return _pywrapcp.RevBool_Value(self)
+
+    def SetValue(self, s: "Solver", val: "bool const &") -> "void":
+        return _pywrapcp.RevBool_SetValue(self, s, val)
+    __swig_destroy__ = _pywrapcp.delete_RevBool
+
+ +
+ +

This class adds reversibility to a POD type. +It contains the stamp optimization. i.e. the SaveValue call is done +only once per node of the search tree. Please note that actual +stamps always starts at 1, thus an initial value of 0 will always +trigger the first SaveValue.

+
+ + +
+
#   + + + RevBool(val: 'bool const &') +
+ +
+ View Source +
    def __init__(self, val: "bool const &"):
+        _pywrapcp.RevBool_swiginit(self, _pywrapcp.new_RevBool(val))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Value(self) -> 'bool const &': +
+ +
+ View Source +
    def Value(self) -> "bool const &":
+        return _pywrapcp.RevBool_Value(self)
+
+ +
+ + + +
+
+
#   + + + def + SetValue( + self, + s: ortools.constraint_solver.pywrapcp.Solver, + val: 'bool const &' +) -> 'void': +
+ +
+ View Source +
    def SetValue(self, s: "Solver", val: "bool const &") -> "void":
+        return _pywrapcp.RevBool_SetValue(self, s, val)
+
+ +
+ + + +
+
+
+
+ #   + + + class + IntVarContainer: +
+ +
+ View Source +
class IntVarContainer(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Contains(self, var: "IntVar") -> "bool":
+        return _pywrapcp.IntVarContainer_Contains(self, var)
+
+    def Element(self, index: "int") -> "operations_research::IntVarElement *":
+        return _pywrapcp.IntVarContainer_Element(self, index)
+
+    def Size(self) -> "int":
+        return _pywrapcp.IntVarContainer_Size(self)
+
+    def Store(self) -> "void":
+        return _pywrapcp.IntVarContainer_Store(self)
+
+    def Restore(self) -> "void":
+        return _pywrapcp.IntVarContainer_Restore(self)
+
+    def __eq__(self, container: "IntVarContainer") -> "bool":
+        r"""
+        Returns true if this and 'container' both represent the same V* -> E map.
+        Runs in linear time; requires that the == operator on the type E is well
+        defined.
+        """
+        return _pywrapcp.IntVarContainer___eq__(self, container)
+
+    def __ne__(self, container: "IntVarContainer") -> "bool":
+        return _pywrapcp.IntVarContainer___ne__(self, container)
+    __swig_destroy__ = _pywrapcp.delete_IntVarContainer
+
+ +
+ + + +
+
#   + + + IntVarContainer(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Contains(self, var: ortools.constraint_solver.pywrapcp.IntVar) -> bool: +
+ +
+ View Source +
    def Contains(self, var: "IntVar") -> "bool":
+        return _pywrapcp.IntVarContainer_Contains(self, var)
+
+ +
+ + + +
+
+
#   + + + def + Element(self, index: int) -> 'operations_research::IntVarElement *': +
+ +
+ View Source +
    def Element(self, index: "int") -> "operations_research::IntVarElement *":
+        return _pywrapcp.IntVarContainer_Element(self, index)
+
+ +
+ + + +
+
+
#   + + + def + Size(self) -> int: +
+ +
+ View Source +
    def Size(self) -> "int":
+        return _pywrapcp.IntVarContainer_Size(self)
+
+ +
+ + + +
+
+
#   + + + def + Store(self) -> 'void': +
+ +
+ View Source +
    def Store(self) -> "void":
+        return _pywrapcp.IntVarContainer_Store(self)
+
+ +
+ + + +
+
+
#   + + + def + Restore(self) -> 'void': +
+ +
+ View Source +
    def Restore(self) -> "void":
+        return _pywrapcp.IntVarContainer_Restore(self)
+
+ +
+ + + +
+
+
+
+ #   + + + class + IntervalVarContainer: +
+ +
+ View Source +
class IntervalVarContainer(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Contains(self, var: "IntervalVar") -> "bool":
+        return _pywrapcp.IntervalVarContainer_Contains(self, var)
+
+    def Element(self, index: "int") -> "operations_research::IntervalVarElement *":
+        return _pywrapcp.IntervalVarContainer_Element(self, index)
+
+    def Size(self) -> "int":
+        return _pywrapcp.IntervalVarContainer_Size(self)
+
+    def Store(self) -> "void":
+        return _pywrapcp.IntervalVarContainer_Store(self)
+
+    def Restore(self) -> "void":
+        return _pywrapcp.IntervalVarContainer_Restore(self)
+
+    def __eq__(self, container: "IntervalVarContainer") -> "bool":
+        r"""
+        Returns true if this and 'container' both represent the same V* -> E map.
+        Runs in linear time; requires that the == operator on the type E is well
+        defined.
+        """
+        return _pywrapcp.IntervalVarContainer___eq__(self, container)
+
+    def __ne__(self, container: "IntervalVarContainer") -> "bool":
+        return _pywrapcp.IntervalVarContainer___ne__(self, container)
+    __swig_destroy__ = _pywrapcp.delete_IntervalVarContainer
+
+ +
+ + + +
+
#   + + + IntervalVarContainer(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Contains(self, var: ortools.constraint_solver.pywrapcp.IntervalVar) -> bool: +
+ +
+ View Source +
    def Contains(self, var: "IntervalVar") -> "bool":
+        return _pywrapcp.IntervalVarContainer_Contains(self, var)
+
+ +
+ + + +
+
+
#   + + + def + Element(self, index: int) -> 'operations_research::IntervalVarElement *': +
+ +
+ View Source +
    def Element(self, index: "int") -> "operations_research::IntervalVarElement *":
+        return _pywrapcp.IntervalVarContainer_Element(self, index)
+
+ +
+ + + +
+
+
#   + + + def + Size(self) -> int: +
+ +
+ View Source +
    def Size(self) -> "int":
+        return _pywrapcp.IntervalVarContainer_Size(self)
+
+ +
+ + + +
+
+
#   + + + def + Store(self) -> 'void': +
+ +
+ View Source +
    def Store(self) -> "void":
+        return _pywrapcp.IntervalVarContainer_Store(self)
+
+ +
+ + + +
+
+
#   + + + def + Restore(self) -> 'void': +
+ +
+ View Source +
    def Restore(self) -> "void":
+        return _pywrapcp.IntervalVarContainer_Restore(self)
+
+ +
+ + + +
+
+
+
+ #   + + + class + SequenceVarContainer: +
+ +
+ View Source +
class SequenceVarContainer(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Contains(self, var: "SequenceVar") -> "bool":
+        return _pywrapcp.SequenceVarContainer_Contains(self, var)
+
+    def Element(self, index: "int") -> "operations_research::SequenceVarElement *":
+        return _pywrapcp.SequenceVarContainer_Element(self, index)
+
+    def Size(self) -> "int":
+        return _pywrapcp.SequenceVarContainer_Size(self)
+
+    def Store(self) -> "void":
+        return _pywrapcp.SequenceVarContainer_Store(self)
+
+    def Restore(self) -> "void":
+        return _pywrapcp.SequenceVarContainer_Restore(self)
+
+    def __eq__(self, container: "SequenceVarContainer") -> "bool":
+        r"""
+        Returns true if this and 'container' both represent the same V* -> E map.
+        Runs in linear time; requires that the == operator on the type E is well
+        defined.
+        """
+        return _pywrapcp.SequenceVarContainer___eq__(self, container)
+
+    def __ne__(self, container: "SequenceVarContainer") -> "bool":
+        return _pywrapcp.SequenceVarContainer___ne__(self, container)
+    __swig_destroy__ = _pywrapcp.delete_SequenceVarContainer
+
+ +
+ + + +
+
#   + + + SequenceVarContainer(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Contains(self, var: ortools.constraint_solver.pywrapcp.SequenceVar) -> bool: +
+ +
+ View Source +
    def Contains(self, var: "SequenceVar") -> "bool":
+        return _pywrapcp.SequenceVarContainer_Contains(self, var)
+
+ +
+ + + +
+
+
#   + + + def + Element(self, index: int) -> 'operations_research::SequenceVarElement *': +
+ +
+ View Source +
    def Element(self, index: "int") -> "operations_research::SequenceVarElement *":
+        return _pywrapcp.SequenceVarContainer_Element(self, index)
+
+ +
+ + + +
+
+
#   + + + def + Size(self) -> int: +
+ +
+ View Source +
    def Size(self) -> "int":
+        return _pywrapcp.SequenceVarContainer_Size(self)
+
+ +
+ + + +
+
+
#   + + + def + Store(self) -> 'void': +
+ +
+ View Source +
    def Store(self) -> "void":
+        return _pywrapcp.SequenceVarContainer_Store(self)
+
+ +
+ + + +
+
+
#   + + + def + Restore(self) -> 'void': +
+ +
+ View Source +
    def Restore(self) -> "void":
+        return _pywrapcp.SequenceVarContainer_Restore(self)
+
+ +
+ + + +
+
+
+
+ #   + + + class + LocalSearchOperator(BaseObject): +
+ +
+ View Source +
class LocalSearchOperator(BaseObject):
+    r"""
+    This class represent a reversible FIFO structure.
+    The main difference w.r.t a standard FIFO structure is that a Solver is
+    given as parameter to the modifiers such that the solver can store the
+    backtrack information
+    Iterator's traversing order should not be changed, as some algorithm
+    depend on it to be consistent.
+    It's main use is to store a list of demons in the various classes of
+    variables.
+    The base class for all local search operators.
+
+    A local search operator is an object that defines the neighborhood of a
+    solution. In other words, a neighborhood is the set of solutions which can
+    be reached from a given solution using an operator.
+
+    The behavior of the LocalSearchOperator class is similar to iterators.
+    The operator is synchronized with an assignment (gives the
+    current values of the variables); this is done in the Start() method.
+
+    Then one can iterate over the neighbors using the MakeNextNeighbor method.
+    This method returns an assignment which represents the incremental changes
+    to the current solution. It also returns a second assignment representing
+    the changes to the last solution defined by the neighborhood operator; this
+    assignment is empty if the neighborhood operator cannot track this
+    information.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def NextNeighbor(self, delta: "Assignment", deltadelta: "Assignment") -> "bool":
+        return _pywrapcp.LocalSearchOperator_NextNeighbor(self, delta, deltadelta)
+
+    def Start(self, assignment: "Assignment") -> "void":
+        return _pywrapcp.LocalSearchOperator_Start(self, assignment)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_LocalSearchOperator(self)
+        return weakref.proxy(self)
+
+ +
+ +

This class represent a reversible FIFO structure. +The main difference w.r.t a standard FIFO structure is that a Solver is +given as parameter to the modifiers such that the solver can store the +backtrack information +Iterator's traversing order should not be changed, as some algorithm +depend on it to be consistent. +It's main use is to store a list of demons in the various classes of +variables. +The base class for all local search operators.

+ +

A local search operator is an object that defines the neighborhood of a +solution. In other words, a neighborhood is the set of solutions which can +be reached from a given solution using an operator.

+ +

The behavior of the LocalSearchOperator class is similar to iterators. +The operator is synchronized with an assignment (gives the +current values of the variables); this is done in the Start() method.

+ +

Then one can iterate over the neighbors using the MakeNextNeighbor method. +This method returns an assignment which represents the incremental changes +to the current solution. It also returns a second assignment representing +the changes to the last solution defined by the neighborhood operator; this +assignment is empty if the neighborhood operator cannot track this +information.

+
+ + +
+
#   + + + LocalSearchOperator(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + NextNeighbor( + self, + delta: ortools.constraint_solver.pywrapcp.Assignment, + deltadelta: ortools.constraint_solver.pywrapcp.Assignment +) -> bool: +
+ +
+ View Source +
    def NextNeighbor(self, delta: "Assignment", deltadelta: "Assignment") -> "bool":
+        return _pywrapcp.LocalSearchOperator_NextNeighbor(self, delta, deltadelta)
+
+ +
+ + + +
+
+
#   + + + def + Start( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment +) -> 'void': +
+ +
+ View Source +
    def Start(self, assignment: "Assignment") -> "void":
+        return _pywrapcp.LocalSearchOperator_Start(self, assignment)
+
+ +
+ + + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + IntVarLocalSearchOperatorTemplate(LocalSearchOperator): +
+ +
+ View Source +
class IntVarLocalSearchOperatorTemplate(LocalSearchOperator):
+    r""" Base operator class for operators manipulating variables."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def Start(self, assignment: "Assignment") -> "void":
+        r"""
+        This method should not be overridden. Override OnStart() instead which is
+        called before exiting this method.
+        """
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_Start(self, assignment)
+
+    def IsIncremental(self) -> "bool":
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_IsIncremental(self)
+
+    def Size(self) -> "int":
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_Size(self)
+
+    def Value(self, index: "int64_t") -> "long const &":
+        r"""
+        Returns the value in the current assignment of the variable of given
+        index.
+        """
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_Value(self, index)
+
+    def OldValue(self, index: "int64_t") -> "long const &":
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_OldValue(self, index)
+
+    def SetValue(self, index: "int64_t", value: "long const &") -> "void":
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_SetValue(self, index, value)
+
+    def OnStart(self) -> "void":
+        r"""
+        Called by Start() after synchronizing the operator with the current
+        assignment. Should be overridden instead of Start() to avoid calling
+        VarLocalSearchOperator::Start explicitly.
+        """
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_OnStart(self)
+
+ +
+ +

Base operator class for operators manipulating variables.

+
+ + +
+
#   + + + IntVarLocalSearchOperatorTemplate(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Start( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment +) -> 'void': +
+ +
+ View Source +
    def Start(self, assignment: "Assignment") -> "void":
+        r"""
+        This method should not be overridden. Override OnStart() instead which is
+        called before exiting this method.
+        """
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_Start(self, assignment)
+
+ +
+ +

This method should not be overridden. Override OnStart() instead which is +called before exiting this method.

+
+ + +
+
+
#   + + + def + IsIncremental(self) -> bool: +
+ +
+ View Source +
    def IsIncremental(self) -> "bool":
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_IsIncremental(self)
+
+ +
+ + + +
+
+
#   + + + def + Size(self) -> int: +
+ +
+ View Source +
    def Size(self) -> "int":
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_Size(self)
+
+ +
+ + + +
+
+
#   + + + def + Value(self, index: 'int64_t') -> 'long const &': +
+ +
+ View Source +
    def Value(self, index: "int64_t") -> "long const &":
+        r"""
+        Returns the value in the current assignment of the variable of given
+        index.
+        """
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_Value(self, index)
+
+ +
+ +

Returns the value in the current assignment of the variable of given +index.

+
+ + +
+
+
#   + + + def + OldValue(self, index: 'int64_t') -> 'long const &': +
+ +
+ View Source +
    def OldValue(self, index: "int64_t") -> "long const &":
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_OldValue(self, index)
+
+ +
+ + + +
+
+
#   + + + def + SetValue(self, index: 'int64_t', value: 'long const &') -> 'void': +
+ +
+ View Source +
    def SetValue(self, index: "int64_t", value: "long const &") -> "void":
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_SetValue(self, index, value)
+
+ +
+ + + +
+
+
#   + + + def + OnStart(self) -> 'void': +
+ +
+ View Source +
    def OnStart(self) -> "void":
+        r"""
+        Called by Start() after synchronizing the operator with the current
+        assignment. Should be overridden instead of Start() to avoid calling
+        VarLocalSearchOperator::Start explicitly.
+        """
+        return _pywrapcp.IntVarLocalSearchOperatorTemplate_OnStart(self)
+
+ +
+ +

Called by Start() after synchronizing the operator with the current +assignment. Should be overridden instead of Start() to avoid calling +VarLocalSearchOperator::Start explicitly.

+
+ + +
+
+
Inherited Members
+
+ + +
+
+
+
+
+ #   + + + class + IntVarLocalSearchOperator(IntVarLocalSearchOperatorTemplate): +
+ +
+ View Source +
class IntVarLocalSearchOperator(IntVarLocalSearchOperatorTemplate):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, *args):
+        if self.__class__ == IntVarLocalSearchOperator:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.IntVarLocalSearchOperator_swiginit(self, _pywrapcp.new_IntVarLocalSearchOperator(_self, *args))
+    __swig_destroy__ = _pywrapcp.delete_IntVarLocalSearchOperator
+
+    def NextNeighbor(self, delta: "Assignment", deltadelta: "Assignment") -> "bool":
+        r"""
+        Redefines MakeNextNeighbor to export a simpler interface. The calls to
+        ApplyChanges() and RevertChanges() are factored in this method, hiding
+        both delta and deltadelta from subclasses which only need to override
+        MakeOneNeighbor().
+        Therefore this method should not be overridden. Override MakeOneNeighbor()
+        instead.
+        """
+        return _pywrapcp.IntVarLocalSearchOperator_NextNeighbor(self, delta, deltadelta)
+
+    def OneNeighbor(self) -> "bool":
+        r"""
+        Creates a new neighbor. It returns false when the neighborhood is
+        completely explored.
+        MakeNextNeighbor() in a subclass of IntVarLocalSearchOperator.
+        """
+        return _pywrapcp.IntVarLocalSearchOperator_OneNeighbor(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_IntVarLocalSearchOperator(self)
+        return weakref.proxy(self)
+
+ +
+ +

Base operator class for operators manipulating variables.

+
+ + +
+
#   + + + IntVarLocalSearchOperator(*args) +
+ +
+ View Source +
    def __init__(self, *args):
+        if self.__class__ == IntVarLocalSearchOperator:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.IntVarLocalSearchOperator_swiginit(self, _pywrapcp.new_IntVarLocalSearchOperator(_self, *args))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + NextNeighbor( + self, + delta: ortools.constraint_solver.pywrapcp.Assignment, + deltadelta: ortools.constraint_solver.pywrapcp.Assignment +) -> bool: +
+ +
+ View Source +
    def NextNeighbor(self, delta: "Assignment", deltadelta: "Assignment") -> "bool":
+        r"""
+        Redefines MakeNextNeighbor to export a simpler interface. The calls to
+        ApplyChanges() and RevertChanges() are factored in this method, hiding
+        both delta and deltadelta from subclasses which only need to override
+        MakeOneNeighbor().
+        Therefore this method should not be overridden. Override MakeOneNeighbor()
+        instead.
+        """
+        return _pywrapcp.IntVarLocalSearchOperator_NextNeighbor(self, delta, deltadelta)
+
+ +
+ +

Redefines MakeNextNeighbor to export a simpler interface. The calls to +ApplyChanges() and RevertChanges() are factored in this method, hiding +both delta and deltadelta from subclasses which only need to override +MakeOneNeighbor(). +Therefore this method should not be overridden. Override MakeOneNeighbor() +instead.

+
+ + +
+
+
#   + + + def + OneNeighbor(self) -> bool: +
+ +
+ View Source +
    def OneNeighbor(self) -> "bool":
+        r"""
+        Creates a new neighbor. It returns false when the neighborhood is
+        completely explored.
+        MakeNextNeighbor() in a subclass of IntVarLocalSearchOperator.
+        """
+        return _pywrapcp.IntVarLocalSearchOperator_OneNeighbor(self)
+
+ +
+ +

Creates a new neighbor. It returns false when the neighborhood is +completely explored. +MakeNextNeighbor() in a subclass of IntVarLocalSearchOperator.

+
+ + +
+ +
+
+
+ #   + + + class + SequenceVarLocalSearchOperatorTemplate(LocalSearchOperator): +
+ +
+ View Source +
class SequenceVarLocalSearchOperatorTemplate(LocalSearchOperator):
+    r""" Base operator class for operators manipulating variables."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def Start(self, assignment: "Assignment") -> "void":
+        r"""
+        This method should not be overridden. Override OnStart() instead which is
+        called before exiting this method.
+        """
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_Start(self, assignment)
+
+    def IsIncremental(self) -> "bool":
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_IsIncremental(self)
+
+    def Size(self) -> "int":
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_Size(self)
+
+    def Value(self, index: "int64_t") -> "std::vector< int > const &":
+        r"""
+        Returns the value in the current assignment of the variable of given
+        index.
+        """
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_Value(self, index)
+
+    def OldValue(self, index: "int64_t") -> "std::vector< int > const &":
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_OldValue(self, index)
+
+    def SetValue(self, index: "int64_t", value: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_SetValue(self, index, value)
+
+    def OnStart(self) -> "void":
+        r"""
+        Called by Start() after synchronizing the operator with the current
+        assignment. Should be overridden instead of Start() to avoid calling
+        VarLocalSearchOperator::Start explicitly.
+        """
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_OnStart(self)
+
+ +
+ +

Base operator class for operators manipulating variables.

+
+ + +
+
#   + + + SequenceVarLocalSearchOperatorTemplate(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Start( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment +) -> 'void': +
+ +
+ View Source +
    def Start(self, assignment: "Assignment") -> "void":
+        r"""
+        This method should not be overridden. Override OnStart() instead which is
+        called before exiting this method.
+        """
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_Start(self, assignment)
+
+ +
+ +

This method should not be overridden. Override OnStart() instead which is +called before exiting this method.

+
+ + +
+
+
#   + + + def + IsIncremental(self) -> bool: +
+ +
+ View Source +
    def IsIncremental(self) -> "bool":
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_IsIncremental(self)
+
+ +
+ + + +
+
+
#   + + + def + Size(self) -> int: +
+ +
+ View Source +
    def Size(self) -> "int":
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_Size(self)
+
+ +
+ + + +
+
+
#   + + + def + Value(self, index: 'int64_t') -> 'std::vector< int > const &': +
+ +
+ View Source +
    def Value(self, index: "int64_t") -> "std::vector< int > const &":
+        r"""
+        Returns the value in the current assignment of the variable of given
+        index.
+        """
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_Value(self, index)
+
+ +
+ +

Returns the value in the current assignment of the variable of given +index.

+
+ + +
+
+
#   + + + def + OldValue(self, index: 'int64_t') -> 'std::vector< int > const &': +
+ +
+ View Source +
    def OldValue(self, index: "int64_t") -> "std::vector< int > const &":
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_OldValue(self, index)
+
+ +
+ + + +
+
+
#   + + + def + SetValue( + self, + index: 'int64_t', + value: 'std::vector< int > const &' +) -> 'void': +
+ +
+ View Source +
    def SetValue(self, index: "int64_t", value: "std::vector< int > const &") -> "void":
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_SetValue(self, index, value)
+
+ +
+ + + +
+
+
#   + + + def + OnStart(self) -> 'void': +
+ +
+ View Source +
    def OnStart(self) -> "void":
+        r"""
+        Called by Start() after synchronizing the operator with the current
+        assignment. Should be overridden instead of Start() to avoid calling
+        VarLocalSearchOperator::Start explicitly.
+        """
+        return _pywrapcp.SequenceVarLocalSearchOperatorTemplate_OnStart(self)
+
+ +
+ +

Called by Start() after synchronizing the operator with the current +assignment. Should be overridden instead of Start() to avoid calling +VarLocalSearchOperator::Start explicitly.

+
+ + +
+
+
Inherited Members
+
+ + +
+
+
+
+
+ #   + + + class + SequenceVarLocalSearchOperator(SequenceVarLocalSearchOperatorTemplate): +
+ +
+ View Source +
class SequenceVarLocalSearchOperator(SequenceVarLocalSearchOperatorTemplate):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+ +
+ +

Base operator class for operators manipulating variables.

+
+ + +
+
#   + + + SequenceVarLocalSearchOperator(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+ +
+
+
+ #   + + + class + BaseLns(IntVarLocalSearchOperator): +
+ +
+ View Source +
class BaseLns(IntVarLocalSearchOperator):
+    r"""
+    This is the base class for building an Lns operator. An Lns fragment is a
+    collection of variables which will be relaxed. Fragments are built with
+    NextFragment(), which returns false if there are no more fragments to build.
+    Optionally one can override InitFragments, which is called from
+    LocalSearchOperator::Start to initialize fragment data.
+
+    Here's a sample relaxing one variable at a time:
+
+    class OneVarLns : public BaseLns {
+     public:
+      OneVarLns(const std::vector<IntVar*>& vars) : BaseLns(vars), index_(0) {}
+      virtual ~OneVarLns() {}
+      virtual void InitFragments() { index_ = 0; }
+      virtual bool NextFragment() {
+        const int size = Size();
+        if (index_ < size) {
+          AppendToFragment(index_);
+          ++index_;
+          return true;
+        } else {
+          return false;
+        }
+      }
+
+     private:
+      int index_;
+    };
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, vars: "std::vector< operations_research::IntVar * > const &"):
+        if self.__class__ == BaseLns:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.BaseLns_swiginit(self, _pywrapcp.new_BaseLns(_self, vars))
+    __swig_destroy__ = _pywrapcp.delete_BaseLns
+
+    def InitFragments(self) -> "void":
+        return _pywrapcp.BaseLns_InitFragments(self)
+
+    def NextFragment(self) -> "bool":
+        return _pywrapcp.BaseLns_NextFragment(self)
+
+    def AppendToFragment(self, index: "int") -> "void":
+        return _pywrapcp.BaseLns_AppendToFragment(self, index)
+
+    def FragmentSize(self) -> "int":
+        return _pywrapcp.BaseLns_FragmentSize(self)
+
+    def __getitem__(self, index: "int") -> "int64_t":
+        return _pywrapcp.BaseLns___getitem__(self, index)
+
+    def __len__(self) -> "int":
+        return _pywrapcp.BaseLns___len__(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_BaseLns(self)
+        return weakref.proxy(self)
+
+ +
+ +

This is the base class for building an Lns operator. An Lns fragment is a +collection of variables which will be relaxed. Fragments are built with +NextFragment(), which returns false if there are no more fragments to build. +Optionally one can override InitFragments, which is called from +LocalSearchOperator::Start to initialize fragment data.

+ +

Here's a sample relaxing one variable at a time:

+ +

class OneVarLns : public BaseLns { + public: + OneVarLns(const std::vector& vars) : BaseLns(vars), index_(0) {} + virtual ~OneVarLns() {} + virtual void InitFragments() { index_ = 0; } + virtual bool NextFragment() { + const int size = Size(); + if (index_ < size) { + AppendToFragment(index_); + ++index_; + return true; + } else { + return false; + } + }

+ +

private: + int index_; +};

+
+ + +
+
#   + + + BaseLns(vars: 'std::vector< operations_research::IntVar * > const &') +
+ +
+ View Source +
    def __init__(self, vars: "std::vector< operations_research::IntVar * > const &"):
+        if self.__class__ == BaseLns:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.BaseLns_swiginit(self, _pywrapcp.new_BaseLns(_self, vars))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + InitFragments(self) -> 'void': +
+ +
+ View Source +
    def InitFragments(self) -> "void":
+        return _pywrapcp.BaseLns_InitFragments(self)
+
+ +
+ + + +
+
+
#   + + + def + NextFragment(self) -> bool: +
+ +
+ View Source +
    def NextFragment(self) -> "bool":
+        return _pywrapcp.BaseLns_NextFragment(self)
+
+ +
+ + + +
+
+
#   + + + def + AppendToFragment(self, index: int) -> 'void': +
+ +
+ View Source +
    def AppendToFragment(self, index: "int") -> "void":
+        return _pywrapcp.BaseLns_AppendToFragment(self, index)
+
+ +
+ + + +
+
+
#   + + + def + FragmentSize(self) -> int: +
+ +
+ View Source +
    def FragmentSize(self) -> "int":
+        return _pywrapcp.BaseLns_FragmentSize(self)
+
+ +
+ + + +
+ +
+
+
+ #   + + + class + ChangeValue(IntVarLocalSearchOperator): +
+ +
+ View Source +
class ChangeValue(IntVarLocalSearchOperator):
+    r"""
+    Defines operators which change the value of variables;
+    each neighbor corresponds to *one* modified variable.
+    Sub-classes have to define ModifyValue which determines what the new
+    variable value is going to be (given the current value and the variable).
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, vars: "std::vector< operations_research::IntVar * > const &"):
+        if self.__class__ == ChangeValue:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.ChangeValue_swiginit(self, _pywrapcp.new_ChangeValue(_self, vars))
+    __swig_destroy__ = _pywrapcp.delete_ChangeValue
+
+    def ModifyValue(self, index: "int64_t", value: "int64_t") -> "int64_t":
+        return _pywrapcp.ChangeValue_ModifyValue(self, index, value)
+
+    def OneNeighbor(self) -> "bool":
+        r""" This method should not be overridden. Override ModifyValue() instead."""
+        return _pywrapcp.ChangeValue_OneNeighbor(self)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_ChangeValue(self)
+        return weakref.proxy(self)
+
+ +
+ +

Defines operators which change the value of variables; +each neighbor corresponds to one modified variable. +Sub-classes have to define ModifyValue which determines what the new +variable value is going to be (given the current value and the variable).

+
+ + +
+
#   + + + ChangeValue(vars: 'std::vector< operations_research::IntVar * > const &') +
+ +
+ View Source +
    def __init__(self, vars: "std::vector< operations_research::IntVar * > const &"):
+        if self.__class__ == ChangeValue:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.ChangeValue_swiginit(self, _pywrapcp.new_ChangeValue(_self, vars))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + ModifyValue(self, index: 'int64_t', value: 'int64_t') -> 'int64_t': +
+ +
+ View Source +
    def ModifyValue(self, index: "int64_t", value: "int64_t") -> "int64_t":
+        return _pywrapcp.ChangeValue_ModifyValue(self, index, value)
+
+ +
+ + + +
+
+
#   + + + def + OneNeighbor(self) -> bool: +
+ +
+ View Source +
    def OneNeighbor(self) -> "bool":
+        r""" This method should not be overridden. Override ModifyValue() instead."""
+        return _pywrapcp.ChangeValue_OneNeighbor(self)
+
+ +
+ +

This method should not be overridden. Override ModifyValue() instead.

+
+ + +
+ +
+
+
+ #   + + + class + PathOperator(IntVarLocalSearchOperator): +
+ +
+ View Source +
class PathOperator(IntVarLocalSearchOperator):
+    r"""
+    Base class of the local search operators dedicated to path modifications
+    (a path is a set of nodes linked together by arcs).
+    This family of neighborhoods supposes they are handling next variables
+    representing the arcs (var[i] represents the node immediately after i on
+    a path).
+    Several services are provided:
+    - arc manipulators (SetNext(), ReverseChain(), MoveChain())
+    - path inspectors (Next(), Prev(), IsPathEnd())
+    - path iterators: operators need a given number of nodes to define a
+      neighbor; this class provides the iteration on a given number of (base)
+      nodes which can be used to define a neighbor (through the BaseNode method)
+    Subclasses only need to override MakeNeighbor to create neighbors using
+    the services above (no direct manipulation of assignments).
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def Neighbor(self) -> "bool":
+        return _pywrapcp.PathOperator_Neighbor(self)
+
+ +
+ +

Base class of the local search operators dedicated to path modifications +(a path is a set of nodes linked together by arcs). +This family of neighborhoods supposes they are handling next variables +representing the arcs (var[i] represents the node immediately after i on +a path). +Several services are provided:

+ +
    +
  • arc manipulators (SetNext(), ReverseChain(), MoveChain())
  • +
  • path inspectors (Next(), Prev(), IsPathEnd())
  • +
  • path iterators: operators need a given number of nodes to define a +neighbor; this class provides the iteration on a given number of (base) +nodes which can be used to define a neighbor (through the BaseNode method) +Subclasses only need to override MakeNeighbor to create neighbors using +the services above (no direct manipulation of assignments).
  • +
+
+ + +
+
#   + + + PathOperator(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Neighbor(self) -> bool: +
+ +
+ View Source +
    def Neighbor(self) -> "bool":
+        return _pywrapcp.PathOperator_Neighbor(self)
+
+ +
+ + + +
+ +
+
+
+ #   + + + class + LocalSearchFilter(BaseObject): +
+ +
+ View Source +
class LocalSearchFilter(BaseObject):
+    r"""
+    Classes to which this template function can be applied to as of 04/2014.
+    Usage: LocalSearchOperator* op = MakeLocalSearchOperator<Relocate>(...);
+    class TwoOpt;
+    class Relocate;
+    class Exchange;
+    class Cross;
+    class MakeActiveOperator;
+    class MakeInactiveOperator;
+    class MakeChainInactiveOperator;
+    class SwapActiveOperator;
+    class ExtendedSwapActiveOperator;
+    class MakeActiveAndRelocate;
+    class RelocateAndMakeActiveOperator;
+    class RelocateAndMakeInactiveOperator;
+    Local Search Filters are used for fast neighbor pruning.
+    Filtering a move is done in several phases:
+    - in the Relax phase, filters determine which parts of their internals
+      will be changed by the candidate, and modify intermediary State
+    - in the Accept phase, filters check that the candidate is feasible,
+    - if the Accept phase succeeds, the solver may decide to trigger a
+      Synchronize phase that makes filters change their internal representation
+      to the last candidate,
+    - otherwise (Accept fails or the solver does not want to synchronize),
+      a Revert phase makes filters erase any intermediary State generated by the
+      Relax and Accept phases.
+    A given filter has phases called with the following pattern:
+    (Relax.Accept.Synchronize | Relax.Accept.Revert | Relax.Revert)*.
+    Filters's Revert() is always called in the reverse order their Accept() was
+    called, to allow late filters to use state done/undone by early filters'
+    Accept()/Revert().
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def Accept(self, delta: "Assignment", deltadelta: "Assignment", objective_min: "int64_t", objective_max: "int64_t") -> "bool":
+        r"""
+        Accepts a "delta" given the assignment with which the filter has been
+        synchronized; the delta holds the variables which have been modified and
+        their new value.
+        If the filter represents a part of the global objective, its contribution
+        must be between objective_min and objective_max.
+        Sample: supposing one wants to maintain a[0,1] + b[0,1] <= 1,
+        for the assignment (a,1), (b,0), the delta (b,1) will be rejected
+        but the delta (a,0) will be accepted.
+        TODO(user): Remove arguments when there are no more need for those.
+        """
+        return _pywrapcp.LocalSearchFilter_Accept(self, delta, deltadelta, objective_min, objective_max)
+
+    def IsIncremental(self) -> "bool":
+        return _pywrapcp.LocalSearchFilter_IsIncremental(self)
+
+    def Synchronize(self, assignment: "Assignment", delta: "Assignment") -> "void":
+        r"""
+        Synchronizes the filter with the current solution, delta being the
+        difference with the solution passed to the previous call to Synchronize()
+        or IncrementalSynchronize(). 'delta' can be used to incrementally
+        synchronizing the filter with the new solution by only considering the
+        changes in delta.
+        """
+        return _pywrapcp.LocalSearchFilter_Synchronize(self, assignment, delta)
+    __swig_destroy__ = _pywrapcp.delete_LocalSearchFilter
+
+ +
+ +

Classes to which this template function can be applied to as of 04/2014. +Usage: LocalSearchOperator* op = MakeLocalSearchOperator(...); +class TwoOpt; +class Relocate; +class Exchange; +class Cross; +class MakeActiveOperator; +class MakeInactiveOperator; +class MakeChainInactiveOperator; +class SwapActiveOperator; +class ExtendedSwapActiveOperator; +class MakeActiveAndRelocate; +class RelocateAndMakeActiveOperator; +class RelocateAndMakeInactiveOperator; +Local Search Filters are used for fast neighbor pruning. +Filtering a move is done in several phases:

+ +
    +
  • in the Relax phase, filters determine which parts of their internals +will be changed by the candidate, and modify intermediary State
  • +
  • in the Accept phase, filters check that the candidate is feasible,
  • +
  • if the Accept phase succeeds, the solver may decide to trigger a +Synchronize phase that makes filters change their internal representation +to the last candidate,
  • +
  • otherwise (Accept fails or the solver does not want to synchronize), +a Revert phase makes filters erase any intermediary State generated by the +Relax and Accept phases. +A given filter has phases called with the following pattern: +(Relax.Accept.Synchronize | Relax.Accept.Revert | Relax.Revert)*. +Filters's Revert() is always called in the reverse order their Accept() was +called, to allow late filters to use state done/undone by early filters' +Accept()/Revert().
  • +
+
+ + +
+
#   + + + LocalSearchFilter(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Accept( + self, + delta: ortools.constraint_solver.pywrapcp.Assignment, + deltadelta: ortools.constraint_solver.pywrapcp.Assignment, + objective_min: 'int64_t', + objective_max: 'int64_t' +) -> bool: +
+ +
+ View Source +
    def Accept(self, delta: "Assignment", deltadelta: "Assignment", objective_min: "int64_t", objective_max: "int64_t") -> "bool":
+        r"""
+        Accepts a "delta" given the assignment with which the filter has been
+        synchronized; the delta holds the variables which have been modified and
+        their new value.
+        If the filter represents a part of the global objective, its contribution
+        must be between objective_min and objective_max.
+        Sample: supposing one wants to maintain a[0,1] + b[0,1] <= 1,
+        for the assignment (a,1), (b,0), the delta (b,1) will be rejected
+        but the delta (a,0) will be accepted.
+        TODO(user): Remove arguments when there are no more need for those.
+        """
+        return _pywrapcp.LocalSearchFilter_Accept(self, delta, deltadelta, objective_min, objective_max)
+
+ +
+ +

Accepts a "delta" given the assignment with which the filter has been +synchronized; the delta holds the variables which have been modified and +their new value. +If the filter represents a part of the global objective, its contribution +must be between objective_min and objective_max. +Sample: supposing one wants to maintain a[0,1] + b[0,1] <= 1, +for the assignment (a,1), (b,0), the delta (b,1) will be rejected +but the delta (a,0) will be accepted. +TODO(user): Remove arguments when there are no more need for those.

+
+ + +
+
+
#   + + + def + IsIncremental(self) -> bool: +
+ +
+ View Source +
    def IsIncremental(self) -> "bool":
+        return _pywrapcp.LocalSearchFilter_IsIncremental(self)
+
+ +
+ + + +
+
+
#   + + + def + Synchronize( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment, + delta: ortools.constraint_solver.pywrapcp.Assignment +) -> 'void': +
+ +
+ View Source +
    def Synchronize(self, assignment: "Assignment", delta: "Assignment") -> "void":
+        r"""
+        Synchronizes the filter with the current solution, delta being the
+        difference with the solution passed to the previous call to Synchronize()
+        or IncrementalSynchronize(). 'delta' can be used to incrementally
+        synchronizing the filter with the new solution by only considering the
+        changes in delta.
+        """
+        return _pywrapcp.LocalSearchFilter_Synchronize(self, assignment, delta)
+
+ +
+ +

Synchronizes the filter with the current solution, delta being the +difference with the solution passed to the previous call to Synchronize() +or IncrementalSynchronize(). 'delta' can be used to incrementally +synchronizing the filter with the new solution by only considering the +changes in delta.

+
+ + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + LocalSearchFilterManager(BaseObject): +
+ +
+ View Source +
class LocalSearchFilterManager(BaseObject):
+    r"""
+    Filter manager: when a move is made, filters are executed to decide whether
+    the solution is feasible and compute parts of the new cost. This class
+    schedules filter execution and composes costs as a sum.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.LocalSearchFilterManager_DebugString(self)
+
+    def __init__(self, *args):
+        _pywrapcp.LocalSearchFilterManager_swiginit(self, _pywrapcp.new_LocalSearchFilterManager(*args))
+
+    def Accept(self, monitor: "operations_research::LocalSearchMonitor *const", delta: "Assignment", deltadelta: "Assignment", objective_min: "int64_t", objective_max: "int64_t") -> "bool":
+        r"""
+        Returns true iff all filters return true, and the sum of their accepted
+        objectives is between objective_min and objective_max.
+        The monitor has its Begin/EndFiltering events triggered.
+        """
+        return _pywrapcp.LocalSearchFilterManager_Accept(self, monitor, delta, deltadelta, objective_min, objective_max)
+
+    def Synchronize(self, assignment: "Assignment", delta: "Assignment") -> "void":
+        r""" Synchronizes all filters to assignment."""
+        return _pywrapcp.LocalSearchFilterManager_Synchronize(self, assignment, delta)
+    __swig_destroy__ = _pywrapcp.delete_LocalSearchFilterManager
+
+ +
+ +

Filter manager: when a move is made, filters are executed to decide whether +the solution is feasible and compute parts of the new cost. This class +schedules filter execution and composes costs as a sum.

+
+ + +
+
#   + + + LocalSearchFilterManager(*args) +
+ +
+ View Source +
    def __init__(self, *args):
+        _pywrapcp.LocalSearchFilterManager_swiginit(self, _pywrapcp.new_LocalSearchFilterManager(*args))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.LocalSearchFilterManager_DebugString(self)
+
+ +
+ + + +
+
+
#   + + + def + Accept( + self, + monitor: 'operations_research::LocalSearchMonitor *const', + delta: ortools.constraint_solver.pywrapcp.Assignment, + deltadelta: ortools.constraint_solver.pywrapcp.Assignment, + objective_min: 'int64_t', + objective_max: 'int64_t' +) -> bool: +
+ +
+ View Source +
    def Accept(self, monitor: "operations_research::LocalSearchMonitor *const", delta: "Assignment", deltadelta: "Assignment", objective_min: "int64_t", objective_max: "int64_t") -> "bool":
+        r"""
+        Returns true iff all filters return true, and the sum of their accepted
+        objectives is between objective_min and objective_max.
+        The monitor has its Begin/EndFiltering events triggered.
+        """
+        return _pywrapcp.LocalSearchFilterManager_Accept(self, monitor, delta, deltadelta, objective_min, objective_max)
+
+ +
+ +

Returns true iff all filters return true, and the sum of their accepted +objectives is between objective_min and objective_max. +The monitor has its Begin/EndFiltering events triggered.

+
+ + +
+
+
#   + + + def + Synchronize( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment, + delta: ortools.constraint_solver.pywrapcp.Assignment +) -> 'void': +
+ +
+ View Source +
    def Synchronize(self, assignment: "Assignment", delta: "Assignment") -> "void":
+        r""" Synchronizes all filters to assignment."""
+        return _pywrapcp.LocalSearchFilterManager_Synchronize(self, assignment, delta)
+
+ +
+ +

Synchronizes all filters to assignment.

+
+ + +
+
+
+
+ #   + + + class + IntVarLocalSearchFilter(LocalSearchFilter): +
+ +
+ View Source +
class IntVarLocalSearchFilter(LocalSearchFilter):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, vars: "std::vector< operations_research::IntVar * > const &"):
+        if self.__class__ == IntVarLocalSearchFilter:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.IntVarLocalSearchFilter_swiginit(self, _pywrapcp.new_IntVarLocalSearchFilter(_self, vars))
+    __swig_destroy__ = _pywrapcp.delete_IntVarLocalSearchFilter
+
+    def Synchronize(self, assignment: "Assignment", delta: "Assignment") -> "void":
+        r"""
+        This method should not be overridden. Override OnSynchronize() instead
+        which is called before exiting this method.
+        """
+        return _pywrapcp.IntVarLocalSearchFilter_Synchronize(self, assignment, delta)
+
+    def Size(self) -> "int":
+        return _pywrapcp.IntVarLocalSearchFilter_Size(self)
+
+    def Value(self, index: "int") -> "int64_t":
+        return _pywrapcp.IntVarLocalSearchFilter_Value(self, index)
+
+    def IndexFromVar(self, var: "IntVar") -> "int64_t":
+        return _pywrapcp.IntVarLocalSearchFilter_IndexFromVar(self, var)
+    def __disown__(self):
+        self.this.disown()
+        _pywrapcp.disown_IntVarLocalSearchFilter(self)
+        return weakref.proxy(self)
+
+ +
+ +

Classes to which this template function can be applied to as of 04/2014. +Usage: LocalSearchOperator* op = MakeLocalSearchOperator(...); +class TwoOpt; +class Relocate; +class Exchange; +class Cross; +class MakeActiveOperator; +class MakeInactiveOperator; +class MakeChainInactiveOperator; +class SwapActiveOperator; +class ExtendedSwapActiveOperator; +class MakeActiveAndRelocate; +class RelocateAndMakeActiveOperator; +class RelocateAndMakeInactiveOperator; +Local Search Filters are used for fast neighbor pruning. +Filtering a move is done in several phases:

+ +
    +
  • in the Relax phase, filters determine which parts of their internals +will be changed by the candidate, and modify intermediary State
  • +
  • in the Accept phase, filters check that the candidate is feasible,
  • +
  • if the Accept phase succeeds, the solver may decide to trigger a +Synchronize phase that makes filters change their internal representation +to the last candidate,
  • +
  • otherwise (Accept fails or the solver does not want to synchronize), +a Revert phase makes filters erase any intermediary State generated by the +Relax and Accept phases. +A given filter has phases called with the following pattern: +(Relax.Accept.Synchronize | Relax.Accept.Revert | Relax.Revert)*. +Filters's Revert() is always called in the reverse order their Accept() was +called, to allow late filters to use state done/undone by early filters' +Accept()/Revert().
  • +
+
+ + +
+
#   + + + IntVarLocalSearchFilter(vars: 'std::vector< operations_research::IntVar * > const &') +
+ +
+ View Source +
    def __init__(self, vars: "std::vector< operations_research::IntVar * > const &"):
+        if self.__class__ == IntVarLocalSearchFilter:
+            _self = None
+        else:
+            _self = self
+        _pywrapcp.IntVarLocalSearchFilter_swiginit(self, _pywrapcp.new_IntVarLocalSearchFilter(_self, vars))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Synchronize( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment, + delta: ortools.constraint_solver.pywrapcp.Assignment +) -> 'void': +
+ +
+ View Source +
    def Synchronize(self, assignment: "Assignment", delta: "Assignment") -> "void":
+        r"""
+        This method should not be overridden. Override OnSynchronize() instead
+        which is called before exiting this method.
+        """
+        return _pywrapcp.IntVarLocalSearchFilter_Synchronize(self, assignment, delta)
+
+ +
+ +

This method should not be overridden. Override OnSynchronize() instead +which is called before exiting this method.

+
+ + +
+
+
#   + + + def + Size(self) -> int: +
+ +
+ View Source +
    def Size(self) -> "int":
+        return _pywrapcp.IntVarLocalSearchFilter_Size(self)
+
+ +
+ + + +
+
+
#   + + + def + Value(self, index: int) -> 'int64_t': +
+ +
+ View Source +
    def Value(self, index: "int") -> "int64_t":
+        return _pywrapcp.IntVarLocalSearchFilter_Value(self, index)
+
+ +
+ + + +
+
+
#   + + + def + IndexFromVar(self, var: ortools.constraint_solver.pywrapcp.IntVar) -> 'int64_t': +
+ +
+ View Source +
    def IndexFromVar(self, var: "IntVar") -> "int64_t":
+        return _pywrapcp.IntVarLocalSearchFilter_IndexFromVar(self, var)
+
+ +
+ + + +
+
+
Inherited Members
+
+ + +
+
+
+
+
+ #   + + + class + BooleanVar(IntVar): +
+ +
+ View Source +
class BooleanVar(IntVar):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+
+    def Min(self) -> "int64_t":
+        return _pywrapcp.BooleanVar_Min(self)
+
+    def SetMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_SetMin(self, m)
+
+    def Max(self) -> "int64_t":
+        return _pywrapcp.BooleanVar_Max(self)
+
+    def SetMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_SetMax(self, m)
+
+    def SetRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_SetRange(self, mi, ma)
+
+    def Bound(self) -> "bool":
+        return _pywrapcp.BooleanVar_Bound(self)
+
+    def Value(self) -> "int64_t":
+        return _pywrapcp.BooleanVar_Value(self)
+
+    def RemoveValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_RemoveValue(self, v)
+
+    def RemoveInterval(self, l: "int64_t", u: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_RemoveInterval(self, l, u)
+
+    def WhenBound(self, d: "Demon") -> "void":
+        return _pywrapcp.BooleanVar_WhenBound(self, d)
+
+    def WhenRange(self, d: "Demon") -> "void":
+        return _pywrapcp.BooleanVar_WhenRange(self, d)
+
+    def WhenDomain(self, d: "Demon") -> "void":
+        return _pywrapcp.BooleanVar_WhenDomain(self, d)
+
+    def Size(self) -> "uint64_t":
+        return _pywrapcp.BooleanVar_Size(self)
+
+    def Contains(self, v: "int64_t") -> "bool":
+        return _pywrapcp.BooleanVar_Contains(self, v)
+
+    def HoleIteratorAux(self, reversible: "bool") -> "operations_research::IntVarIterator *":
+        return _pywrapcp.BooleanVar_HoleIteratorAux(self, reversible)
+
+    def DomainIteratorAux(self, reversible: "bool") -> "operations_research::IntVarIterator *":
+        return _pywrapcp.BooleanVar_DomainIteratorAux(self, reversible)
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.BooleanVar_DebugString(self)
+
+ +
+ +

The class IntVar is a subset of IntExpr. In addition to the +IntExpr protocol, it offers persistence, removing values from the domains, +and a finer model for events.

+
+ + +
+
#   + + + BooleanVar(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Min(self) -> 'int64_t': +
+ +
+ View Source +
    def Min(self) -> "int64_t":
+        return _pywrapcp.BooleanVar_Min(self)
+
+ +
+ + + +
+
+
#   + + + def + SetMin(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetMin(self, m: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_SetMin(self, m)
+
+ +
+ + + +
+
+
#   + + + def + Max(self) -> 'int64_t': +
+ +
+ View Source +
    def Max(self) -> "int64_t":
+        return _pywrapcp.BooleanVar_Max(self)
+
+ +
+ + + +
+
+
#   + + + def + SetMax(self, m: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetMax(self, m: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_SetMax(self, m)
+
+ +
+ + + +
+
+
#   + + + def + SetRange(self, mi: 'int64_t', ma: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetRange(self, mi: "int64_t", ma: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_SetRange(self, mi, ma)
+
+ +
+ +

This method sets both the min and the max of the expression.

+
+ + +
+
+
#   + + + def + Bound(self) -> bool: +
+ +
+ View Source +
    def Bound(self) -> "bool":
+        return _pywrapcp.BooleanVar_Bound(self)
+
+ +
+ +

Returns true if the min and the max of the expression are equal.

+
+ + +
+
+
#   + + + def + Value(self) -> 'int64_t': +
+ +
+ View Source +
    def Value(self) -> "int64_t":
+        return _pywrapcp.BooleanVar_Value(self)
+
+ +
+ +

This method returns the value of the variable. This method checks +before that the variable is bound.

+
+ + +
+
+
#   + + + def + RemoveValue(self, v: 'int64_t') -> 'void': +
+ +
+ View Source +
    def RemoveValue(self, v: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_RemoveValue(self, v)
+
+ +
+ +

This method removes the value 'v' from the domain of the variable.

+
+ + +
+
+
#   + + + def + RemoveInterval(self, l: 'int64_t', u: 'int64_t') -> 'void': +
+ +
+ View Source +
    def RemoveInterval(self, l: "int64_t", u: "int64_t") -> "void":
+        return _pywrapcp.BooleanVar_RemoveInterval(self, l, u)
+
+ +
+ +

This method removes the interval 'l' .. 'u' from the domain of +the variable. It assumes that 'l' <= 'u'.

+
+ + +
+
+
#   + + + def + WhenBound(self, d: ortools.constraint_solver.pywrapcp.Demon) -> 'void': +
+ +
+ View Source +
    def WhenBound(self, d: "Demon") -> "void":
+        return _pywrapcp.BooleanVar_WhenBound(self, d)
+
+ +
+ +

Overload 1: +This method attaches a demon that will be awakened when the +variable is bound.

+ +

|

+ +

Overload 2: +This method attaches a closure that will be awakened when the +variable is bound.

+
+ + +
+
+
#   + + + def + WhenRange(self, d: ortools.constraint_solver.pywrapcp.Demon) -> 'void': +
+ +
+ View Source +
    def WhenRange(self, d: "Demon") -> "void":
+        return _pywrapcp.BooleanVar_WhenRange(self, d)
+
+ +
+ +

Overload 1: +Attach a demon that will watch the min or the max of the expression.

+ +

|

+ +

Overload 2: +Attach a demon that will watch the min or the max of the expression.

+
+ + +
+
+
#   + + + def + WhenDomain(self, d: ortools.constraint_solver.pywrapcp.Demon) -> 'void': +
+ +
+ View Source +
    def WhenDomain(self, d: "Demon") -> "void":
+        return _pywrapcp.BooleanVar_WhenDomain(self, d)
+
+ +
+ +

Overload 1: +This method attaches a demon that will watch any domain +modification of the domain of the variable.

+ +

|

+ +

Overload 2: +This method attaches a closure that will watch any domain +modification of the domain of the variable.

+
+ + +
+
+
#   + + + def + Size(self) -> 'uint64_t': +
+ +
+ View Source +
    def Size(self) -> "uint64_t":
+        return _pywrapcp.BooleanVar_Size(self)
+
+ +
+ +

This method returns the number of values in the domain of the variable.

+
+ + +
+
+
#   + + + def + Contains(self, v: 'int64_t') -> bool: +
+ +
+ View Source +
    def Contains(self, v: "int64_t") -> "bool":
+        return _pywrapcp.BooleanVar_Contains(self, v)
+
+ +
+ +

This method returns whether the value 'v' is in the domain of the +variable.

+
+ + +
+
+
#   + + + def + HoleIteratorAux(self, reversible: bool) -> 'operations_research::IntVarIterator *': +
+ +
+ View Source +
    def HoleIteratorAux(self, reversible: "bool") -> "operations_research::IntVarIterator *":
+        return _pywrapcp.BooleanVar_HoleIteratorAux(self, reversible)
+
+ +
+ +

Creates a hole iterator. When 'reversible' is false, the returned +object is created on the normal C++ heap and the solver does NOT +take ownership of the object.

+
+ + +
+
+
#   + + + def + DomainIteratorAux(self, reversible: bool) -> 'operations_research::IntVarIterator *': +
+ +
+ View Source +
    def DomainIteratorAux(self, reversible: "bool") -> "operations_research::IntVarIterator *":
+        return _pywrapcp.BooleanVar_DomainIteratorAux(self, reversible)
+
+ +
+ +

Creates a domain iterator. When 'reversible' is false, the +returned object is created on the normal C++ heap and the solver +does NOT take ownership of the object.

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.BooleanVar_DebugString(self)
+
+ +
+ + + +
+ +
+
+
+ #   + + + class + PyDecision(Decision): +
+ +
+ View Source +
class PyDecision(Decision):
+
+  def __init__(self):
+    Decision.__init__(self)
+
+  def ApplyWrapper(self, solver):
+    try:
+       self.Apply(solver)
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        solver.ShouldFail()
+      else:
+        raise
+
+  def RefuteWrapper(self, solver):
+    try:
+       self.Refute(solver)
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        solver.ShouldFail()
+      else:
+        raise
+
+  def DebugString(self):
+    return "PyDecision"
+
+ +
+ +

A Decision represents a choice point in the search tree. The two main +methods are Apply() to go left, or Refute() to go right.

+
+ + +
+
#   + + + PyDecision() +
+ +
+ View Source +
  def __init__(self):
+    Decision.__init__(self)
+
+ +
+ + + +
+
+
#   + + + def + ApplyWrapper(self, solver): +
+ +
+ View Source +
  def ApplyWrapper(self, solver):
+    try:
+       self.Apply(solver)
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        solver.ShouldFail()
+      else:
+        raise
+
+ +
+ +

Apply will be called first when the decision is executed.

+
+ + +
+
+
#   + + + def + RefuteWrapper(self, solver): +
+ +
+ View Source +
  def RefuteWrapper(self, solver):
+    try:
+       self.Refute(solver)
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        solver.ShouldFail()
+      else:
+        raise
+
+ +
+ +

Refute will be called after a backtrack.

+
+ + +
+
+
#   + + + def + DebugString(self): +
+ +
+ View Source +
  def DebugString(self):
+    return "PyDecision"
+
+ +
+ + + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + PyDecisionBuilder(DecisionBuilder): +
+ +
+ View Source +
class PyDecisionBuilder(DecisionBuilder):
+
+  def __init__(self):
+    DecisionBuilder.__init__(self)
+
+  def NextWrapper(self, solver):
+    try:
+      return self.Next(solver)
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        return solver.FailDecision()
+      else:
+        raise
+
+  def DebugString(self):
+    return "PyDecisionBuilder"
+
+ +
+ +

A DecisionBuilder is responsible for creating the search tree. The +important method is Next(), which returns the next decision to execute.

+
+ + +
+
#   + + + PyDecisionBuilder() +
+ +
+ View Source +
  def __init__(self):
+    DecisionBuilder.__init__(self)
+
+ +
+ + + +
+
+
#   + + + def + NextWrapper(self, solver): +
+ +
+ View Source +
  def NextWrapper(self, solver):
+    try:
+      return self.Next(solver)
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        return solver.FailDecision()
+      else:
+        raise
+
+ +
+ +

This is the main method of the decision builder class. It must +return a decision (an instance of the class Decision). If it +returns nullptr, this means that the decision builder has finished +its work.

+
+ + +
+
+
#   + + + def + DebugString(self): +
+ +
+ View Source +
  def DebugString(self):
+    return "PyDecisionBuilder"
+
+ +
+ + + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + PyDemon(Demon): +
+ +
+ View Source +
class PyDemon(Demon):
+
+  def RunWrapper(self, solver):
+    try:
+      self.Run(solver)
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        solver.ShouldFail()
+      else:
+        raise
+
+  def DebugString(self):
+    return "PyDemon"
+
+ +
+ +

A Demon is the base element of a propagation queue. It is the main + object responsible for implementing the actual propagation + of the constraint and pruning the inconsistent values in the domains + of the variables. The main concept is that demons are listeners that are + attached to the variables and listen to their modifications.

+ +
There are two methods
+ +
+
    +
  • Run() is the actual method called when the demon is processed.
  • +
  • priority() returns its priority. Standard priorities are slow, normal + or fast. "immediate" is reserved for variables and is treated separately.
  • +
+
+
+ + +
+
#   + + + def + RunWrapper(self, solver): +
+ +
+ View Source +
  def RunWrapper(self, solver):
+    try:
+      self.Run(solver)
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        solver.ShouldFail()
+      else:
+        raise
+
+ +
+ +

This is the main callback of the demon.

+
+ + +
+
+
#   + + + def + DebugString(self): +
+ +
+ View Source +
  def DebugString(self):
+    return "PyDemon"
+
+ +
+ + + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + PyConstraintDemon(PyDemon): +
+ +
+ View Source +
class PyConstraintDemon(PyDemon):
+
+  def __init__(self, ct, method, delayed, *args):
+    PyDemon.__init__(self)
+    self.__constraint = ct
+    self.__method = method
+    self.__delayed = delayed
+    self.__args = args
+
+  def Run(self, solver):
+    self.__method(self.__constraint, *self.__args)
+
+  def Priority(self):
+    return Solver.DELAYED_PRIORITY if self.__delayed else Solver.NORMAL_PRIORITY
+
+  def DebugString(self):
+    return 'PyConstraintDemon'
+
+ +
+ +

A Demon is the base element of a propagation queue. It is the main + object responsible for implementing the actual propagation + of the constraint and pruning the inconsistent values in the domains + of the variables. The main concept is that demons are listeners that are + attached to the variables and listen to their modifications.

+ +
There are two methods
+ +
+
    +
  • Run() is the actual method called when the demon is processed.
  • +
  • priority() returns its priority. Standard priorities are slow, normal + or fast. "immediate" is reserved for variables and is treated separately.
  • +
+
+
+ + +
+
#   + + + PyConstraintDemon(ct, method, delayed, *args) +
+ +
+ View Source +
  def __init__(self, ct, method, delayed, *args):
+    PyDemon.__init__(self)
+    self.__constraint = ct
+    self.__method = method
+    self.__delayed = delayed
+    self.__args = args
+
+ +
+ +

This indicates the priority of a demon. Immediate demons are treated +separately and corresponds to variables.

+
+ + +
+
+
#   + + + def + Run(self, solver): +
+ +
+ View Source +
  def Run(self, solver):
+    self.__method(self.__constraint, *self.__args)
+
+ +
+ + + +
+
+
#   + + + def + Priority(self): +
+ +
+ View Source +
  def Priority(self):
+    return Solver.DELAYED_PRIORITY if self.__delayed else Solver.NORMAL_PRIORITY
+
+ +
+ +

This method returns the priority of the demon. Usually a demon is +fast, slow or normal. Immediate demons are reserved for internal +use to maintain variables.

+
+ + +
+
+
#   + + + def + DebugString(self): +
+ +
+ View Source +
  def DebugString(self):
+    return 'PyConstraintDemon'
+
+ +
+ + + +
+
+
Inherited Members
+
+ + +
+
+
+
+
+ #   + + + class + PyConstraint(Constraint): +
+ +
+ View Source +
class PyConstraint(Constraint):
+
+  def __init__(self, solver):
+    Constraint.__init__(self, solver)
+    self.__demons = []
+
+  def Demon(self, method, *args):
+    demon = PyConstraintDemon(self, method, False, *args)
+    self.__demons.append(demon)
+    return demon
+
+  def DelayedDemon(self, method, *args):
+    demon = PyConstraintDemon(self, method, True, *args)
+    self.__demons.append(demon)
+    return demon
+
+  def InitialPropagateDemon(self):
+    return self.solver().ConstraintInitialPropagateCallback(self)
+
+  def DelayedInitialPropagateDemon(self):
+    return self.solver().DelayedConstraintInitialPropagateCallback(self)
+
+  def InitialPropagateWrapper(self):
+    try:
+      self.InitialPropagate()
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        self.solver().ShouldFail()
+      else:
+        raise
+
+  def DebugString(self):
+    return "PyConstraint"
+
+ +
+ +

A constraint is the main modeling object. It provides two methods:

+ +
    +
  • Post() is responsible for creating the demons and attaching them to +immediate demons().
  • +
  • InitialPropagate() is called once just after Post and performs +the initial propagation. The subsequent propagations will be performed +by the demons Posted during the post() method.
  • +
+
+ + +
+
#   + + + PyConstraint(solver) +
+ +
+ View Source +
  def __init__(self, solver):
+    Constraint.__init__(self, solver)
+    self.__demons = []
+
+ +
+ + + +
+
+
#   + + + def + Demon(self, method, *args): +
+ +
+ View Source +
  def Demon(self, method, *args):
+    demon = PyConstraintDemon(self, method, False, *args)
+    self.__demons.append(demon)
+    return demon
+
+ +
+ + + +
+
+
#   + + + def + DelayedDemon(self, method, *args): +
+ +
+ View Source +
  def DelayedDemon(self, method, *args):
+    demon = PyConstraintDemon(self, method, True, *args)
+    self.__demons.append(demon)
+    return demon
+
+ +
+ + + +
+
+
#   + + + def + InitialPropagateDemon(self): +
+ +
+ View Source +
  def InitialPropagateDemon(self):
+    return self.solver().ConstraintInitialPropagateCallback(self)
+
+ +
+ + + +
+
+
#   + + + def + DelayedInitialPropagateDemon(self): +
+ +
+ View Source +
  def DelayedInitialPropagateDemon(self):
+    return self.solver().DelayedConstraintInitialPropagateCallback(self)
+
+ +
+ + + +
+
+
#   + + + def + InitialPropagateWrapper(self): +
+ +
+ View Source +
  def InitialPropagateWrapper(self):
+    try:
+      self.InitialPropagate()
+    except Exception as e:
+      if 'CP Solver fail' in str(e):
+        self.solver().ShouldFail()
+      else:
+        raise
+
+ +
+ +

This method performs the initial propagation of the +constraint. It is called just after the post.

+
+ + +
+
+
#   + + + def + DebugString(self): +
+ +
+ View Source +
  def DebugString(self):
+    return "PyConstraint"
+
+ +
+ + + +
+
+
Inherited Members
+
+ + +
+
+
+
+
+ #   + + + class + RoutingIndexManager: +
+ +
+ View Source +
class RoutingIndexManager(object):
+    r"""
+    Manager for any NodeIndex <-> variable index conversion. The routing solver
+    uses variable indices internally and through its API. These variable indices
+    are tricky to manage directly because one Node can correspond to a multitude
+    of variables, depending on the number of times they appear in the model, and
+    if they're used as start and/or end points. This class aims to simplify
+    variable index usage, allowing users to use NodeIndex instead.
+
+    Usage:
+
+      .. code-block:: c++
+
+          auto starts_ends = ...;  /// These are NodeIndex.
+          RoutingIndexManager manager(10, 4, starts_ends);  // 10 nodes, 4 vehicles.
+          RoutingModel model(manager);
+
+    Then, use 'manager.NodeToIndex(node)' whenever model requires a variable
+    index.
+
+    Note: the mapping between node indices and variables indices is subject to
+    change so no assumption should be made on it. The only guarantee is that
+    indices range between 0 and n-1, where n = number of vehicles * 2 (for start
+    and end nodes) + number of non-start or end nodes.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, *args):
+        _pywrapcp.RoutingIndexManager_swiginit(self, _pywrapcp.new_RoutingIndexManager(*args))
+    __swig_destroy__ = _pywrapcp.delete_RoutingIndexManager
+
+    def GetNumberOfNodes(self) -> "int":
+        return _pywrapcp.RoutingIndexManager_GetNumberOfNodes(self)
+
+    def GetNumberOfVehicles(self) -> "int":
+        return _pywrapcp.RoutingIndexManager_GetNumberOfVehicles(self)
+
+    def GetNumberOfIndices(self) -> "int":
+        return _pywrapcp.RoutingIndexManager_GetNumberOfIndices(self)
+
+    def GetStartIndex(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingIndexManager_GetStartIndex(self, vehicle)
+
+    def GetEndIndex(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingIndexManager_GetEndIndex(self, vehicle)
+
+    def NodeToIndex(self, node: "operations_research::RoutingIndexManager::NodeIndex") -> "int64_t":
+        return _pywrapcp.RoutingIndexManager_NodeToIndex(self, node)
+
+    def IndexToNode(self, index: "int64_t") -> "operations_research::RoutingIndexManager::NodeIndex":
+        return _pywrapcp.RoutingIndexManager_IndexToNode(self, index)
+
+ +
+ +

Manager for any NodeIndex <-> variable index conversion. The routing solver +uses variable indices internally and through its API. These variable indices +are tricky to manage directly because one Node can correspond to a multitude +of variables, depending on the number of times they appear in the model, and +if they're used as start and/or end points. This class aims to simplify +variable index usage, allowing users to use NodeIndex instead.

+ +
Usage
+ +
+

.. code-block:: c++

+ +
auto starts_ends = ...;  /// These are NodeIndex.
+RoutingIndexManager manager(10, 4, starts_ends);  // 10 nodes, 4 vehicles.
+RoutingModel model(manager);
+
+
+ +

Then, use 'manager.NodeToIndex(node)' whenever model requires a variable +index.

+ +

Note: the mapping between node indices and variables indices is subject to +change so no assumption should be made on it. The only guarantee is that +indices range between 0 and n-1, where n = number of vehicles * 2 (for start +and end nodes) + number of non-start or end nodes.

+
+ + +
+
#   + + + RoutingIndexManager(*args) +
+ +
+ View Source +
    def __init__(self, *args):
+        _pywrapcp.RoutingIndexManager_swiginit(self, _pywrapcp.new_RoutingIndexManager(*args))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + GetNumberOfNodes(self) -> int: +
+ +
+ View Source +
    def GetNumberOfNodes(self) -> "int":
+        return _pywrapcp.RoutingIndexManager_GetNumberOfNodes(self)
+
+ +
+ + + +
+
+
#   + + + def + GetNumberOfVehicles(self) -> int: +
+ +
+ View Source +
    def GetNumberOfVehicles(self) -> "int":
+        return _pywrapcp.RoutingIndexManager_GetNumberOfVehicles(self)
+
+ +
+ + + +
+
+
#   + + + def + GetNumberOfIndices(self) -> int: +
+ +
+ View Source +
    def GetNumberOfIndices(self) -> "int":
+        return _pywrapcp.RoutingIndexManager_GetNumberOfIndices(self)
+
+ +
+ + + +
+
+
#   + + + def + GetStartIndex(self, vehicle: int) -> 'int64_t': +
+ +
+ View Source +
    def GetStartIndex(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingIndexManager_GetStartIndex(self, vehicle)
+
+ +
+ + + +
+
+
#   + + + def + GetEndIndex(self, vehicle: int) -> 'int64_t': +
+ +
+ View Source +
    def GetEndIndex(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingIndexManager_GetEndIndex(self, vehicle)
+
+ +
+ + + +
+
+
#   + + + def + NodeToIndex( + self, + node: 'operations_research::RoutingIndexManager::NodeIndex' +) -> 'int64_t': +
+ +
+ View Source +
    def NodeToIndex(self, node: "operations_research::RoutingIndexManager::NodeIndex") -> "int64_t":
+        return _pywrapcp.RoutingIndexManager_NodeToIndex(self, node)
+
+ +
+ + + +
+
+
#   + + + def + IndexToNode( + self, + index: 'int64_t' +) -> 'operations_research::RoutingIndexManager::NodeIndex': +
+ +
+ View Source +
    def IndexToNode(self, index: "int64_t") -> "operations_research::RoutingIndexManager::NodeIndex":
+        return _pywrapcp.RoutingIndexManager_IndexToNode(self, index)
+
+ +
+ + + +
+
+
+
#   + + + def + DefaultRoutingModelParameters() -> 'operations_research::RoutingModelParameters': +
+ +
+ View Source +
def DefaultRoutingModelParameters() -> "operations_research::RoutingModelParameters":
+    return _pywrapcp.DefaultRoutingModelParameters()
+
+ +
+ + + +
+
+
#   + + + def + DefaultRoutingSearchParameters() -> 'operations_research::RoutingSearchParameters': +
+ +
+ View Source +
def DefaultRoutingSearchParameters() -> "operations_research::RoutingSearchParameters":
+    return _pywrapcp.DefaultRoutingSearchParameters()
+
+ +
+ + + +
+
+
#   + + + def + FindErrorInRoutingSearchParameters( + search_parameters: 'operations_research::RoutingSearchParameters const &' +) -> 'std::string': +
+ +
+ View Source +
def FindErrorInRoutingSearchParameters(search_parameters: "operations_research::RoutingSearchParameters const &") -> "std::string":
+    r"""
+    Returns an empty std::string if the routing search parameters are valid, and
+    a non-empty, human readable error description if they're not.
+    """
+    return _pywrapcp.FindErrorInRoutingSearchParameters(search_parameters)
+
+ +
+ +

Returns an empty std::string if the routing search parameters are valid, and +a non-empty, human readable error description if they're not.

+
+ + +
+
+
+ #   + + + class + RoutingModel: +
+ +
+ View Source +
class RoutingModel(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+    ROUTING_NOT_SOLVED = _pywrapcp.RoutingModel_ROUTING_NOT_SOLVED
+    r""" Problem not solved yet (before calling RoutingModel::Solve())."""
+    ROUTING_SUCCESS = _pywrapcp.RoutingModel_ROUTING_SUCCESS
+    r""" Problem solved successfully after calling RoutingModel::Solve()."""
+    ROUTING_FAIL = _pywrapcp.RoutingModel_ROUTING_FAIL
+    r""" No solution found to the problem after calling RoutingModel::Solve()."""
+    ROUTING_FAIL_TIMEOUT = _pywrapcp.RoutingModel_ROUTING_FAIL_TIMEOUT
+    r""" Time limit reached before finding a solution with RoutingModel::Solve()."""
+    ROUTING_INVALID = _pywrapcp.RoutingModel_ROUTING_INVALID
+    r""" Model, model parameters or flags are not valid."""
+    ROUTING_INFEASIBLE = _pywrapcp.RoutingModel_ROUTING_INFEASIBLE
+    r""" Problem proven to be infeasible."""
+    PICKUP_AND_DELIVERY_NO_ORDER = _pywrapcp.RoutingModel_PICKUP_AND_DELIVERY_NO_ORDER
+    r""" Any precedence is accepted."""
+    PICKUP_AND_DELIVERY_LIFO = _pywrapcp.RoutingModel_PICKUP_AND_DELIVERY_LIFO
+    r""" Deliveries must be performed in reverse order of pickups."""
+    PICKUP_AND_DELIVERY_FIFO = _pywrapcp.RoutingModel_PICKUP_AND_DELIVERY_FIFO
+    r""" Deliveries must be performed in the same order as pickups."""
+
+    def __init__(self, *args):
+        _pywrapcp.RoutingModel_swiginit(self, _pywrapcp.new_RoutingModel(*args))
+    __swig_destroy__ = _pywrapcp.delete_RoutingModel
+
+    def RegisterUnaryTransitVector(self, values: "std::vector< int64_t >") -> "int":
+        r""" Registers 'callback' and returns its index."""
+        return _pywrapcp.RoutingModel_RegisterUnaryTransitVector(self, values)
+
+    def RegisterUnaryTransitCallback(self, callback: "operations_research::RoutingModel::TransitCallback1") -> "int":
+        return _pywrapcp.RoutingModel_RegisterUnaryTransitCallback(self, callback)
+
+    def RegisterPositiveUnaryTransitCallback(self, callback: "operations_research::RoutingModel::TransitCallback1") -> "int":
+        return _pywrapcp.RoutingModel_RegisterPositiveUnaryTransitCallback(self, callback)
+
+    def RegisterTransitMatrix(self, values: "std::vector< std::vector< int64_t > >") -> "int":
+        return _pywrapcp.RoutingModel_RegisterTransitMatrix(self, values)
+
+    def RegisterTransitCallback(self, callback: "operations_research::RoutingModel::TransitCallback2") -> "int":
+        return _pywrapcp.RoutingModel_RegisterTransitCallback(self, callback)
+
+    def RegisterPositiveTransitCallback(self, callback: "operations_research::RoutingModel::TransitCallback2") -> "int":
+        return _pywrapcp.RoutingModel_RegisterPositiveTransitCallback(self, callback)
+
+    def TransitCallback(self, callback_index: "int") -> "operations_research::RoutingModel::TransitCallback2 const &":
+        return _pywrapcp.RoutingModel_TransitCallback(self, callback_index)
+
+    def UnaryTransitCallbackOrNull(self, callback_index: "int") -> "operations_research::RoutingModel::TransitCallback1 const &":
+        return _pywrapcp.RoutingModel_UnaryTransitCallbackOrNull(self, callback_index)
+
+    def AddDimension(self, evaluator_index: "int", slack_max: "int64_t", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "bool":
+        r"""
+        Model creation
+        Methods to add dimensions to routes; dimensions represent quantities
+        accumulated at nodes along the routes. They represent quantities such as
+        weights or volumes carried along the route, or distance or times.
+        Quantities at a node are represented by "cumul" variables and the increase
+        or decrease of quantities between nodes are represented by "transit"
+        variables. These variables are linked as follows:
+        if j == next(i), cumul(j) = cumul(i) + transit(i) + slack(i)
+        where slack is a positive slack variable (can represent waiting times for
+        a time dimension).
+        Setting the value of fix_start_cumul_to_zero to true will force the
+        "cumul" variable of the start node of all vehicles to be equal to 0.
+        Creates a dimension where the transit variable is constrained to be
+        equal to evaluator(i, next(i)); 'slack_max' is the upper bound of the
+        slack variable and 'capacity' is the upper bound of the cumul variables.
+        'name' is the name used to reference the dimension; this name is used to
+        get cumul and transit variables from the routing model.
+        Returns false if a dimension with the same name has already been created
+        (and doesn't create the new dimension).
+        Takes ownership of the callback 'evaluator'.
+        """
+        return _pywrapcp.RoutingModel_AddDimension(self, evaluator_index, slack_max, capacity, fix_start_cumul_to_zero, name)
+
+    def AddDimensionWithVehicleTransits(self, evaluator_indices: "std::vector< int > const &", slack_max: "int64_t", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "bool":
+        return _pywrapcp.RoutingModel_AddDimensionWithVehicleTransits(self, evaluator_indices, slack_max, capacity, fix_start_cumul_to_zero, name)
+
+    def AddDimensionWithVehicleCapacity(self, evaluator_index: "int", slack_max: "int64_t", vehicle_capacities: "std::vector< int64_t >", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "bool":
+        return _pywrapcp.RoutingModel_AddDimensionWithVehicleCapacity(self, evaluator_index, slack_max, vehicle_capacities, fix_start_cumul_to_zero, name)
+
+    def AddDimensionWithVehicleTransitAndCapacity(self, evaluator_indices: "std::vector< int > const &", slack_max: "int64_t", vehicle_capacities: "std::vector< int64_t >", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "bool":
+        return _pywrapcp.RoutingModel_AddDimensionWithVehicleTransitAndCapacity(self, evaluator_indices, slack_max, vehicle_capacities, fix_start_cumul_to_zero, name)
+
+    def AddConstantDimensionWithSlack(self, value: "int64_t", capacity: "int64_t", slack_max: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "std::pair< int,bool >":
+        r"""
+        Creates a dimension where the transit variable is constrained to be
+        equal to 'value'; 'capacity' is the upper bound of the cumul variables.
+        'name' is the name used to reference the dimension; this name is used to
+        get cumul and transit variables from the routing model.
+        Returns a pair consisting of an index to the registered unary transit
+        callback and a bool denoting whether the dimension has been created.
+        It is false if a dimension with the same name has already been created
+        (and doesn't create the new dimension but still register a new callback).
+        """
+        return _pywrapcp.RoutingModel_AddConstantDimensionWithSlack(self, value, capacity, slack_max, fix_start_cumul_to_zero, name)
+
+    def AddConstantDimension(self, value: "int64_t", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "std::pair< int,bool >":
+        return _pywrapcp.RoutingModel_AddConstantDimension(self, value, capacity, fix_start_cumul_to_zero, name)
+
+    def AddVectorDimension(self, values: "std::vector< int64_t >", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "std::pair< int,bool >":
+        r"""
+        Creates a dimension where the transit variable is constrained to be
+        equal to 'values[i]' for node i; 'capacity' is the upper bound of
+        the cumul variables. 'name' is the name used to reference the dimension;
+        this name is used to get cumul and transit variables from the routing
+        model.
+        Returns a pair consisting of an index to the registered unary transit
+        callback and a bool denoting whether the dimension has been created.
+        It is false if a dimension with the same name has already been created
+        (and doesn't create the new dimension but still register a new callback).
+        """
+        return _pywrapcp.RoutingModel_AddVectorDimension(self, values, capacity, fix_start_cumul_to_zero, name)
+
+    def AddMatrixDimension(self, values: "std::vector< std::vector< int64_t > >", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "std::pair< int,bool >":
+        r"""
+        Creates a dimension where the transit variable is constrained to be
+        equal to 'values[i][next(i)]' for node i; 'capacity' is the upper bound of
+        the cumul variables. 'name' is the name used to reference the dimension;
+        this name is used to get cumul and transit variables from the routing
+        model.
+        Returns a pair consisting of an index to the registered transit callback
+        and a bool denoting whether the dimension has been created.
+        It is false if a dimension with the same name has already been created
+        (and doesn't create the new dimension but still register a new callback).
+        """
+        return _pywrapcp.RoutingModel_AddMatrixDimension(self, values, capacity, fix_start_cumul_to_zero, name)
+
+    def MakePathSpansAndTotalSlacks(self, dimension: "RoutingDimension", spans: "std::vector< operations_research::IntVar * >", total_slacks: "std::vector< operations_research::IntVar * >") -> "operations_research::Constraint *":
+        r"""
+        For every vehicle of the routing model:
+        - if total_slacks[vehicle] is not nullptr, constrains it to be the sum of
+          slacks on that vehicle, that is,
+          dimension->CumulVar(end) - dimension->CumulVar(start) -
+          sum_{node in path of vehicle} dimension->FixedTransitVar(node).
+        - if spans[vehicle] is not nullptr, constrains it to be
+          dimension->CumulVar(end) - dimension->CumulVar(start)
+        This does stronger propagation than a decomposition, and takes breaks into
+        account.
+        """
+        return _pywrapcp.RoutingModel_MakePathSpansAndTotalSlacks(self, dimension, spans, total_slacks)
+
+    def GetAllDimensionNames(self) -> "std::vector< std::string >":
+        r""" Outputs the names of all dimensions added to the routing engine."""
+        return _pywrapcp.RoutingModel_GetAllDimensionNames(self)
+
+    def GetDimensions(self) -> "std::vector< operations_research::RoutingDimension * > const &":
+        r""" Returns all dimensions of the model."""
+        return _pywrapcp.RoutingModel_GetDimensions(self)
+
+    def GetDimensionsWithSoftOrSpanCosts(self) -> "std::vector< operations_research::RoutingDimension * >":
+        r""" Returns dimensions with soft or vehicle span costs."""
+        return _pywrapcp.RoutingModel_GetDimensionsWithSoftOrSpanCosts(self)
+
+    def GetGlobalDimensionCumulOptimizers(self) -> "std::vector< std::unique_ptr< operations_research::GlobalDimensionCumulOptimizer > > const &":
+        r"""
+        Returns [global|local]_dimension_optimizers_, which are empty if the model
+        has not been closed.
+        """
+        return _pywrapcp.RoutingModel_GetGlobalDimensionCumulOptimizers(self)
+
+    def GetGlobalDimensionCumulMPOptimizers(self) -> "std::vector< std::unique_ptr< operations_research::GlobalDimensionCumulOptimizer > > const &":
+        return _pywrapcp.RoutingModel_GetGlobalDimensionCumulMPOptimizers(self)
+
+    def GetLocalDimensionCumulOptimizers(self) -> "std::vector< std::unique_ptr< operations_research::LocalDimensionCumulOptimizer > > const &":
+        return _pywrapcp.RoutingModel_GetLocalDimensionCumulOptimizers(self)
+
+    def GetLocalDimensionCumulMPOptimizers(self) -> "std::vector< std::unique_ptr< operations_research::LocalDimensionCumulOptimizer > > const &":
+        return _pywrapcp.RoutingModel_GetLocalDimensionCumulMPOptimizers(self)
+
+    def GetMutableGlobalCumulOptimizer(self, dimension: "RoutingDimension") -> "operations_research::GlobalDimensionCumulOptimizer *":
+        r"""
+        Returns the global/local dimension cumul optimizer for a given dimension,
+        or nullptr if there is none.
+        """
+        return _pywrapcp.RoutingModel_GetMutableGlobalCumulOptimizer(self, dimension)
+
+    def GetMutableGlobalCumulMPOptimizer(self, dimension: "RoutingDimension") -> "operations_research::GlobalDimensionCumulOptimizer *":
+        return _pywrapcp.RoutingModel_GetMutableGlobalCumulMPOptimizer(self, dimension)
+
+    def GetMutableLocalCumulOptimizer(self, dimension: "RoutingDimension") -> "operations_research::LocalDimensionCumulOptimizer *":
+        return _pywrapcp.RoutingModel_GetMutableLocalCumulOptimizer(self, dimension)
+
+    def GetMutableLocalCumulMPOptimizer(self, dimension: "RoutingDimension") -> "operations_research::LocalDimensionCumulOptimizer *":
+        return _pywrapcp.RoutingModel_GetMutableLocalCumulMPOptimizer(self, dimension)
+
+    def HasDimension(self, dimension_name: "std::string const &") -> "bool":
+        r""" Returns true if a dimension exists for a given dimension name."""
+        return _pywrapcp.RoutingModel_HasDimension(self, dimension_name)
+
+    def GetDimensionOrDie(self, dimension_name: "std::string const &") -> "operations_research::RoutingDimension const &":
+        r""" Returns a dimension from its name. Dies if the dimension does not exist."""
+        return _pywrapcp.RoutingModel_GetDimensionOrDie(self, dimension_name)
+
+    def GetMutableDimension(self, dimension_name: "std::string const &") -> "operations_research::RoutingDimension *":
+        r"""
+        Returns a dimension from its name. Returns nullptr if the dimension does
+        not exist.
+        """
+        return _pywrapcp.RoutingModel_GetMutableDimension(self, dimension_name)
+
+    def SetPrimaryConstrainedDimension(self, dimension_name: "std::string const &") -> "void":
+        r"""
+        Set the given dimension as "primary constrained". As of August 2013, this
+        is only used by ArcIsMoreConstrainedThanArc().
+        "dimension" must be the name of an existing dimension, or be empty, in
+        which case there will not be a primary dimension after this call.
+        """
+        return _pywrapcp.RoutingModel_SetPrimaryConstrainedDimension(self, dimension_name)
+
+    def GetPrimaryConstrainedDimension(self) -> "std::string const &":
+        r""" Get the primary constrained dimension, or an empty string if it is unset."""
+        return _pywrapcp.RoutingModel_GetPrimaryConstrainedDimension(self)
+
+    def AddResourceGroup(self) -> "int":
+        r"""
+        Adds a resource group to the routing model. Returns its index in
+        resource_groups_.
+        """
+        return _pywrapcp.RoutingModel_AddResourceGroup(self)
+
+    def GetDimensionResourceGroupIndices(self, dimension: "RoutingDimension") -> "std::vector< int > const &":
+        r"""
+        Returns the indices of resource groups for this dimension. This method can
+        only be called after the model has been closed.
+        """
+        return _pywrapcp.RoutingModel_GetDimensionResourceGroupIndices(self, dimension)
+
+    def GetDimensionResourceGroupIndex(self, dimension: "RoutingDimension") -> "int":
+        r"""
+        Returns the index of the resource group attached to the dimension.
+        DCHECKS that there's exactly one resource group for this dimension.
+        """
+        return _pywrapcp.RoutingModel_GetDimensionResourceGroupIndex(self, dimension)
+
+    def AddDisjunction(self, *args) -> "operations_research::RoutingModel::DisjunctionIndex":
+        r"""
+        Adds a disjunction constraint on the indices: exactly 'max_cardinality' of
+        the indices are active. Start and end indices of any vehicle cannot be
+        part of a disjunction.
+
+        If a penalty is given, at most 'max_cardinality' of the indices can be
+        active, and if less are active, 'penalty' is payed per inactive index.
+        This is equivalent to adding the constraint:
+            p + Sum(i)active[i] == max_cardinality
+        where p is an integer variable, and the following cost to the cost
+        function:
+            p * penalty.
+        'penalty' must be positive to make the disjunction optional; a negative
+        penalty will force 'max_cardinality' indices of the disjunction to be
+        performed, and therefore p == 0.
+        Note: passing a vector with a single index will model an optional index
+        with a penalty cost if it is not visited.
+        """
+        return _pywrapcp.RoutingModel_AddDisjunction(self, *args)
+
+    def GetDisjunctionIndices(self, index: "int64_t") -> "std::vector< operations_research::RoutingModel::DisjunctionIndex > const &":
+        r""" Returns the indices of the disjunctions to which an index belongs."""
+        return _pywrapcp.RoutingModel_GetDisjunctionIndices(self, index)
+
+    def GetDisjunctionPenalty(self, index: "operations_research::RoutingModel::DisjunctionIndex") -> "int64_t":
+        r""" Returns the penalty of the node disjunction of index 'index'."""
+        return _pywrapcp.RoutingModel_GetDisjunctionPenalty(self, index)
+
+    def GetDisjunctionMaxCardinality(self, index: "operations_research::RoutingModel::DisjunctionIndex") -> "int64_t":
+        r"""
+        Returns the maximum number of possible active nodes of the node
+        disjunction of index 'index'.
+        """
+        return _pywrapcp.RoutingModel_GetDisjunctionMaxCardinality(self, index)
+
+    def GetNumberOfDisjunctions(self) -> "int":
+        r""" Returns the number of node disjunctions in the model."""
+        return _pywrapcp.RoutingModel_GetNumberOfDisjunctions(self)
+
+    def HasMandatoryDisjunctions(self) -> "bool":
+        r"""
+        Returns true if the model contains mandatory disjunctions (ones with
+        kNoPenalty as penalty).
+        """
+        return _pywrapcp.RoutingModel_HasMandatoryDisjunctions(self)
+
+    def HasMaxCardinalityConstrainedDisjunctions(self) -> "bool":
+        r"""
+        Returns true if the model contains at least one disjunction which is
+        constrained by its max_cardinality.
+        """
+        return _pywrapcp.RoutingModel_HasMaxCardinalityConstrainedDisjunctions(self)
+
+    def GetPerfectBinaryDisjunctions(self) -> "std::vector< std::pair< int64_t,int64_t > >":
+        r"""
+        Returns the list of all perfect binary disjunctions, as pairs of variable
+        indices: a disjunction is "perfect" when its variables do not appear in
+        any other disjunction. Each pair is sorted (lowest variable index first),
+        and the output vector is also sorted (lowest pairs first).
+        """
+        return _pywrapcp.RoutingModel_GetPerfectBinaryDisjunctions(self)
+
+    def IgnoreDisjunctionsAlreadyForcedToZero(self) -> "void":
+        r"""
+        SPECIAL: Makes the solver ignore all the disjunctions whose active
+        variables are all trivially zero (i.e. Max() == 0), by setting their
+        max_cardinality to 0.
+        This can be useful when using the BaseBinaryDisjunctionNeighborhood
+        operators, in the context of arc-based routing.
+        """
+        return _pywrapcp.RoutingModel_IgnoreDisjunctionsAlreadyForcedToZero(self)
+
+    def AddSoftSameVehicleConstraint(self, indices: "std::vector< int64_t > const &", cost: "int64_t") -> "void":
+        r"""
+        Adds a soft constraint to force a set of variable indices to be on the
+        same vehicle. If all nodes are not on the same vehicle, each extra vehicle
+        used adds 'cost' to the cost function.
+        """
+        return _pywrapcp.RoutingModel_AddSoftSameVehicleConstraint(self, indices, cost)
+
+    def SetAllowedVehiclesForIndex(self, vehicles: "std::vector< int > const &", index: "int64_t") -> "void":
+        r"""
+        Sets the vehicles which can visit a given node. If the node is in a
+        disjunction, this will not prevent it from being unperformed.
+        Specifying an empty vector of vehicles has no effect (all vehicles
+        will be allowed to visit the node).
+        """
+        return _pywrapcp.RoutingModel_SetAllowedVehiclesForIndex(self, vehicles, index)
+
+    def IsVehicleAllowedForIndex(self, vehicle: "int", index: "int64_t") -> "bool":
+        r""" Returns true if a vehicle is allowed to visit a given node."""
+        return _pywrapcp.RoutingModel_IsVehicleAllowedForIndex(self, vehicle, index)
+
+    def AddPickupAndDelivery(self, pickup: "int64_t", delivery: "int64_t") -> "void":
+        r"""
+        Notifies that index1 and index2 form a pair of nodes which should belong
+        to the same route. This methods helps the search find better solutions,
+        especially in the local search phase.
+        It should be called each time you have an equality constraint linking
+        the vehicle variables of two node (including for instance pickup and
+        delivery problems):
+            Solver* const solver = routing.solver();
+            int64_t index1 = manager.NodeToIndex(node1);
+            int64_t index2 = manager.NodeToIndex(node2);
+            solver->AddConstraint(solver->MakeEquality(
+                routing.VehicleVar(index1),
+                routing.VehicleVar(index2)));
+            routing.AddPickupAndDelivery(index1, index2);
+        """
+        return _pywrapcp.RoutingModel_AddPickupAndDelivery(self, pickup, delivery)
+
+    def AddPickupAndDeliverySets(self, pickup_disjunction: "operations_research::RoutingModel::DisjunctionIndex", delivery_disjunction: "operations_research::RoutingModel::DisjunctionIndex") -> "void":
+        r"""
+        Same as AddPickupAndDelivery but notifying that the performed node from
+        the disjunction of index 'pickup_disjunction' is on the same route as the
+        performed node from the disjunction of index 'delivery_disjunction'.
+        """
+        return _pywrapcp.RoutingModel_AddPickupAndDeliverySets(self, pickup_disjunction, delivery_disjunction)
+
+    def GetPickupIndexPairs(self, node_index: "int64_t") -> "std::vector< std::pair< int,int > > const &":
+        r"""
+        Returns pairs for which the node is a pickup; the first element of each
+        pair is the index in the pickup and delivery pairs list in which the
+        pickup appears, the second element is its index in the pickups list.
+        """
+        return _pywrapcp.RoutingModel_GetPickupIndexPairs(self, node_index)
+
+    def GetDeliveryIndexPairs(self, node_index: "int64_t") -> "std::vector< std::pair< int,int > > const &":
+        r""" Same as above for deliveries."""
+        return _pywrapcp.RoutingModel_GetDeliveryIndexPairs(self, node_index)
+
+    def SetPickupAndDeliveryPolicyOfAllVehicles(self, policy: "operations_research::RoutingModel::PickupAndDeliveryPolicy") -> "void":
+        r"""
+        Sets the Pickup and delivery policy of all vehicles. It is equivalent to
+        calling SetPickupAndDeliveryPolicyOfVehicle on all vehicles.
+        """
+        return _pywrapcp.RoutingModel_SetPickupAndDeliveryPolicyOfAllVehicles(self, policy)
+
+    def SetPickupAndDeliveryPolicyOfVehicle(self, policy: "operations_research::RoutingModel::PickupAndDeliveryPolicy", vehicle: "int") -> "void":
+        return _pywrapcp.RoutingModel_SetPickupAndDeliveryPolicyOfVehicle(self, policy, vehicle)
+
+    def GetPickupAndDeliveryPolicyOfVehicle(self, vehicle: "int") -> "operations_research::RoutingModel::PickupAndDeliveryPolicy":
+        return _pywrapcp.RoutingModel_GetPickupAndDeliveryPolicyOfVehicle(self, vehicle)
+
+    def GetNumOfSingletonNodes(self) -> "int":
+        r"""
+        Returns the number of non-start/end nodes which do not appear in a
+        pickup/delivery pair.
+        """
+        return _pywrapcp.RoutingModel_GetNumOfSingletonNodes(self)
+    TYPE_ADDED_TO_VEHICLE = _pywrapcp.RoutingModel_TYPE_ADDED_TO_VEHICLE
+    r""" When visited, the number of types 'T' on the vehicle increases by one."""
+    ADDED_TYPE_REMOVED_FROM_VEHICLE = _pywrapcp.RoutingModel_ADDED_TYPE_REMOVED_FROM_VEHICLE
+    r"""
+    When visited, one instance of type 'T' previously added to the route
+    (TYPE_ADDED_TO_VEHICLE), if any, is removed from the vehicle.
+    If the type was not previously added to the route or all added instances
+    have already been removed, this visit has no effect on the types.
+    """
+    TYPE_ON_VEHICLE_UP_TO_VISIT = _pywrapcp.RoutingModel_TYPE_ON_VEHICLE_UP_TO_VISIT
+    r"""
+    With the following policy, the visit enforces that type 'T' is
+    considered on the route from its start until this node is visited.
+    """
+    TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED = _pywrapcp.RoutingModel_TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED
+    r"""
+    The visit doesn't have an impact on the number of types 'T' on the
+    route, as it's (virtually) added and removed directly.
+    This policy can be used for visits which are part of an incompatibility
+    or requirement set without affecting the type count on the route.
+    """
+
+    def SetVisitType(self, index: "int64_t", type: "int", type_policy: "operations_research::RoutingModel::VisitTypePolicy") -> "void":
+        return _pywrapcp.RoutingModel_SetVisitType(self, index, type, type_policy)
+
+    def GetVisitType(self, index: "int64_t") -> "int":
+        return _pywrapcp.RoutingModel_GetVisitType(self, index)
+
+    def GetSingleNodesOfType(self, type: "int") -> "std::vector< int > const &":
+        return _pywrapcp.RoutingModel_GetSingleNodesOfType(self, type)
+
+    def GetPairIndicesOfType(self, type: "int") -> "std::vector< int > const &":
+        return _pywrapcp.RoutingModel_GetPairIndicesOfType(self, type)
+
+    def GetVisitTypePolicy(self, index: "int64_t") -> "operations_research::RoutingModel::VisitTypePolicy":
+        return _pywrapcp.RoutingModel_GetVisitTypePolicy(self, index)
+
+    def CloseVisitTypes(self) -> "void":
+        r"""
+        This function should be called once all node visit types have been set and
+        prior to adding any incompatibilities/requirements.
+        "close" types.
+        """
+        return _pywrapcp.RoutingModel_CloseVisitTypes(self)
+
+    def GetNumberOfVisitTypes(self) -> "int":
+        return _pywrapcp.RoutingModel_GetNumberOfVisitTypes(self)
+
+    def AddHardTypeIncompatibility(self, type1: "int", type2: "int") -> "void":
+        r"""
+        Incompatibilities:
+        Two nodes with "hard" incompatible types cannot share the same route at
+        all, while with a "temporal" incompatibility they can't be on the same
+        route at the same time.
+        """
+        return _pywrapcp.RoutingModel_AddHardTypeIncompatibility(self, type1, type2)
+
+    def AddTemporalTypeIncompatibility(self, type1: "int", type2: "int") -> "void":
+        return _pywrapcp.RoutingModel_AddTemporalTypeIncompatibility(self, type1, type2)
+
+    def GetHardTypeIncompatibilitiesOfType(self, type: "int") -> "absl::flat_hash_set< int > const &":
+        r""" Returns visit types incompatible with a given type."""
+        return _pywrapcp.RoutingModel_GetHardTypeIncompatibilitiesOfType(self, type)
+
+    def GetTemporalTypeIncompatibilitiesOfType(self, type: "int") -> "absl::flat_hash_set< int > const &":
+        return _pywrapcp.RoutingModel_GetTemporalTypeIncompatibilitiesOfType(self, type)
+
+    def HasHardTypeIncompatibilities(self) -> "bool":
+        r"""
+        Returns true iff any hard (resp. temporal) type incompatibilities have
+        been added to the model.
+        """
+        return _pywrapcp.RoutingModel_HasHardTypeIncompatibilities(self)
+
+    def HasTemporalTypeIncompatibilities(self) -> "bool":
+        return _pywrapcp.RoutingModel_HasTemporalTypeIncompatibilities(self)
+
+    def AddSameVehicleRequiredTypeAlternatives(self, dependent_type: "int", required_type_alternatives: "absl::flat_hash_set< int >") -> "void":
+        r"""
+        Requirements:
+        NOTE: As of 2019-04, cycles in the requirement graph are not supported,
+        and lead to the dependent nodes being skipped if possible (otherwise
+        the model is considered infeasible).
+        The following functions specify that "dependent_type" requires at least
+        one of the types in "required_type_alternatives".
+
+        For same-vehicle requirements, a node of dependent type type_D requires at
+        least one node of type type_R among the required alternatives on the same
+        route.
+        """
+        return _pywrapcp.RoutingModel_AddSameVehicleRequiredTypeAlternatives(self, dependent_type, required_type_alternatives)
+
+    def AddRequiredTypeAlternativesWhenAddingType(self, dependent_type: "int", required_type_alternatives: "absl::flat_hash_set< int >") -> "void":
+        r"""
+        If type_D depends on type_R when adding type_D, any node_D of type_D and
+        VisitTypePolicy TYPE_ADDED_TO_VEHICLE or
+        TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED requires at least one type_R on its
+        vehicle at the time node_D is visited.
+        """
+        return _pywrapcp.RoutingModel_AddRequiredTypeAlternativesWhenAddingType(self, dependent_type, required_type_alternatives)
+
+    def AddRequiredTypeAlternativesWhenRemovingType(self, dependent_type: "int", required_type_alternatives: "absl::flat_hash_set< int >") -> "void":
+        r"""
+        The following requirements apply when visiting dependent nodes that remove
+        their type from the route, i.e. type_R must be on the vehicle when type_D
+        of VisitTypePolicy ADDED_TYPE_REMOVED_FROM_VEHICLE,
+        TYPE_ON_VEHICLE_UP_TO_VISIT or TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED is
+        visited.
+        """
+        return _pywrapcp.RoutingModel_AddRequiredTypeAlternativesWhenRemovingType(self, dependent_type, required_type_alternatives)
+
+    def GetSameVehicleRequiredTypeAlternativesOfType(self, type: "int") -> "std::vector< absl::flat_hash_set< int > > const &":
+        r"""
+        Returns the set of same-vehicle requirement alternatives for the given
+        type.
+        """
+        return _pywrapcp.RoutingModel_GetSameVehicleRequiredTypeAlternativesOfType(self, type)
+
+    def GetRequiredTypeAlternativesWhenAddingType(self, type: "int") -> "std::vector< absl::flat_hash_set< int > > const &":
+        r""" Returns the set of requirement alternatives when adding the given type."""
+        return _pywrapcp.RoutingModel_GetRequiredTypeAlternativesWhenAddingType(self, type)
+
+    def GetRequiredTypeAlternativesWhenRemovingType(self, type: "int") -> "std::vector< absl::flat_hash_set< int > > const &":
+        r""" Returns the set of requirement alternatives when removing the given type."""
+        return _pywrapcp.RoutingModel_GetRequiredTypeAlternativesWhenRemovingType(self, type)
+
+    def HasSameVehicleTypeRequirements(self) -> "bool":
+        r"""
+        Returns true iff any same-route (resp. temporal) type requirements have
+        been added to the model.
+        """
+        return _pywrapcp.RoutingModel_HasSameVehicleTypeRequirements(self)
+
+    def HasTemporalTypeRequirements(self) -> "bool":
+        return _pywrapcp.RoutingModel_HasTemporalTypeRequirements(self)
+
+    def HasTypeRegulations(self) -> "bool":
+        r"""
+        Returns true iff the model has any incompatibilities or requirements set
+        on node types.
+        """
+        return _pywrapcp.RoutingModel_HasTypeRegulations(self)
+
+    def UnperformedPenalty(self, var_index: "int64_t") -> "int64_t":
+        r"""
+        Get the "unperformed" penalty of a node. This is only well defined if the
+        node is only part of a single Disjunction, and that disjunction has a
+        penalty. For forced active nodes returns max int64_t. In all other cases,
+        this returns 0.
+        """
+        return _pywrapcp.RoutingModel_UnperformedPenalty(self, var_index)
+
+    def UnperformedPenaltyOrValue(self, default_value: "int64_t", var_index: "int64_t") -> "int64_t":
+        r"""
+        Same as above except that it returns default_value instead of 0 when
+        penalty is not well defined (default value is passed as first argument to
+        simplify the usage of the method in a callback).
+        """
+        return _pywrapcp.RoutingModel_UnperformedPenaltyOrValue(self, default_value, var_index)
+
+    def GetDepot(self) -> "int64_t":
+        r"""
+        Returns the variable index of the first starting or ending node of all
+        routes. If all routes start  and end at the same node (single depot), this
+        is the node returned.
+        """
+        return _pywrapcp.RoutingModel_GetDepot(self)
+
+    def SetMaximumNumberOfActiveVehicles(self, max_active_vehicles: "int") -> "void":
+        r"""
+        Constrains the maximum number of active vehicles, aka the number of
+        vehicles which do not have an empty route. For instance, this can be used
+        to limit the number of routes in the case where there are fewer drivers
+        than vehicles and that the fleet of vehicle is heterogeneous.
+        """
+        return _pywrapcp.RoutingModel_SetMaximumNumberOfActiveVehicles(self, max_active_vehicles)
+
+    def GetMaximumNumberOfActiveVehicles(self) -> "int":
+        r""" Returns the maximum number of active vehicles."""
+        return _pywrapcp.RoutingModel_GetMaximumNumberOfActiveVehicles(self)
+
+    def SetArcCostEvaluatorOfAllVehicles(self, evaluator_index: "int") -> "void":
+        r"""
+        Sets the cost function of the model such that the cost of a segment of a
+        route between node 'from' and 'to' is evaluator(from, to), whatever the
+        route or vehicle performing the route.
+        """
+        return _pywrapcp.RoutingModel_SetArcCostEvaluatorOfAllVehicles(self, evaluator_index)
+
+    def SetArcCostEvaluatorOfVehicle(self, evaluator_index: "int", vehicle: "int") -> "void":
+        r""" Sets the cost function for a given vehicle route."""
+        return _pywrapcp.RoutingModel_SetArcCostEvaluatorOfVehicle(self, evaluator_index, vehicle)
+
+    def SetFixedCostOfAllVehicles(self, cost: "int64_t") -> "void":
+        r"""
+        Sets the fixed cost of all vehicle routes. It is equivalent to calling
+        SetFixedCostOfVehicle on all vehicle routes.
+        """
+        return _pywrapcp.RoutingModel_SetFixedCostOfAllVehicles(self, cost)
+
+    def SetFixedCostOfVehicle(self, cost: "int64_t", vehicle: "int") -> "void":
+        r""" Sets the fixed cost of one vehicle route."""
+        return _pywrapcp.RoutingModel_SetFixedCostOfVehicle(self, cost, vehicle)
+
+    def GetFixedCostOfVehicle(self, vehicle: "int") -> "int64_t":
+        r"""
+        Returns the route fixed cost taken into account if the route of the
+        vehicle is not empty, aka there's at least one node on the route other
+        than the first and last nodes.
+        """
+        return _pywrapcp.RoutingModel_GetFixedCostOfVehicle(self, vehicle)
+
+    def SetAmortizedCostFactorsOfAllVehicles(self, linear_cost_factor: "int64_t", quadratic_cost_factor: "int64_t") -> "void":
+        r"""
+        The following methods set the linear and quadratic cost factors of
+        vehicles (must be positive values). The default value of these parameters
+        is zero for all vehicles.
+
+        When set, the cost_ of the model will contain terms aiming at reducing the
+        number of vehicles used in the model, by adding the following to the
+        objective for every vehicle v:
+        INDICATOR(v used in the model) *
+          [linear_cost_factor_of_vehicle_[v]
+           - quadratic_cost_factor_of_vehicle_[v]*(square of length of route v)]
+        i.e. for every used vehicle, we add the linear factor as fixed cost, and
+        subtract the square of the route length multiplied by the quadratic
+        factor. This second term aims at making the routes as dense as possible.
+
+        Sets the linear and quadratic cost factor of all vehicles.
+        """
+        return _pywrapcp.RoutingModel_SetAmortizedCostFactorsOfAllVehicles(self, linear_cost_factor, quadratic_cost_factor)
+
+    def SetAmortizedCostFactorsOfVehicle(self, linear_cost_factor: "int64_t", quadratic_cost_factor: "int64_t", vehicle: "int") -> "void":
+        r""" Sets the linear and quadratic cost factor of the given vehicle."""
+        return _pywrapcp.RoutingModel_SetAmortizedCostFactorsOfVehicle(self, linear_cost_factor, quadratic_cost_factor, vehicle)
+
+    def GetAmortizedLinearCostFactorOfVehicles(self) -> "std::vector< int64_t > const &":
+        return _pywrapcp.RoutingModel_GetAmortizedLinearCostFactorOfVehicles(self)
+
+    def GetAmortizedQuadraticCostFactorOfVehicles(self) -> "std::vector< int64_t > const &":
+        return _pywrapcp.RoutingModel_GetAmortizedQuadraticCostFactorOfVehicles(self)
+
+    def SetVehicleUsedWhenEmpty(self, is_used: "bool", vehicle: "int") -> "void":
+        return _pywrapcp.RoutingModel_SetVehicleUsedWhenEmpty(self, is_used, vehicle)
+
+    def IsVehicleUsedWhenEmpty(self, vehicle: "int") -> "bool":
+        return _pywrapcp.RoutingModel_IsVehicleUsedWhenEmpty(self, vehicle)
+
+    def SetFirstSolutionEvaluator(self, evaluator: "operations_research::Solver::IndexEvaluator2") -> "void":
+        r"""
+        Gets/sets the evaluator used during the search. Only relevant when
+        RoutingSearchParameters.first_solution_strategy = EVALUATOR_STRATEGY.
+        Takes ownership of evaluator.
+        """
+        return _pywrapcp.RoutingModel_SetFirstSolutionEvaluator(self, evaluator)
+
+    def AddLocalSearchOperator(self, ls_operator: "LocalSearchOperator") -> "void":
+        r"""
+        Adds a local search operator to the set of operators used to solve the
+        vehicle routing problem.
+        """
+        return _pywrapcp.RoutingModel_AddLocalSearchOperator(self, ls_operator)
+
+    def AddSearchMonitor(self, monitor: "SearchMonitor") -> "void":
+        r""" Adds a search monitor to the search used to solve the routing model."""
+        return _pywrapcp.RoutingModel_AddSearchMonitor(self, monitor)
+
+    def AddAtSolutionCallback(self, callback: "std::function< void () >") -> "void":
+        r"""
+        Adds a callback called each time a solution is found during the search.
+        This is a shortcut to creating a monitor to call the callback on
+        AtSolution() and adding it with AddSearchMonitor.
+        """
+        return _pywrapcp.RoutingModel_AddAtSolutionCallback(self, callback)
+
+    def AddVariableMinimizedByFinalizer(self, var: "IntVar") -> "void":
+        r"""
+        Adds a variable to minimize in the solution finalizer. The solution
+        finalizer is called each time a solution is found during the search and
+        allows to instantiate secondary variables (such as dimension cumul
+        variables).
+        """
+        return _pywrapcp.RoutingModel_AddVariableMinimizedByFinalizer(self, var)
+
+    def AddVariableMaximizedByFinalizer(self, var: "IntVar") -> "void":
+        r"""
+        Adds a variable to maximize in the solution finalizer (see above for
+        information on the solution finalizer).
+        """
+        return _pywrapcp.RoutingModel_AddVariableMaximizedByFinalizer(self, var)
+
+    def AddWeightedVariableMinimizedByFinalizer(self, var: "IntVar", cost: "int64_t") -> "void":
+        r"""
+        Adds a variable to minimize in the solution finalizer, with a weighted
+        priority: the higher the more priority it has.
+        """
+        return _pywrapcp.RoutingModel_AddWeightedVariableMinimizedByFinalizer(self, var, cost)
+
+    def AddWeightedVariableMaximizedByFinalizer(self, var: "IntVar", cost: "int64_t") -> "void":
+        r"""
+        Adds a variable to maximize in the solution finalizer, with a weighted
+        priority: the higher the more priority it has.
+        """
+        return _pywrapcp.RoutingModel_AddWeightedVariableMaximizedByFinalizer(self, var, cost)
+
+    def AddVariableTargetToFinalizer(self, var: "IntVar", target: "int64_t") -> "void":
+        r"""
+        Add a variable to set the closest possible to the target value in the
+        solution finalizer.
+        """
+        return _pywrapcp.RoutingModel_AddVariableTargetToFinalizer(self, var, target)
+
+    def AddWeightedVariableTargetToFinalizer(self, var: "IntVar", target: "int64_t", cost: "int64_t") -> "void":
+        r"""
+        Same as above with a weighted priority: the higher the cost, the more
+        priority it has to be set close to the target value.
+        """
+        return _pywrapcp.RoutingModel_AddWeightedVariableTargetToFinalizer(self, var, target, cost)
+
+    def CloseModel(self) -> "void":
+        r"""
+        Closes the current routing model; after this method is called, no
+        modification to the model can be done, but RoutesToAssignment becomes
+        available. Note that CloseModel() is automatically called by Solve() and
+        other methods that produce solution.
+        This is equivalent to calling
+        CloseModelWithParameters(DefaultRoutingSearchParameters()).
+        """
+        return _pywrapcp.RoutingModel_CloseModel(self)
+
+    def CloseModelWithParameters(self, search_parameters: "operations_research::RoutingSearchParameters const &") -> "void":
+        r"""
+        Same as above taking search parameters (as of 10/2015 some the parameters
+        have to be set when closing the model).
+        """
+        return _pywrapcp.RoutingModel_CloseModelWithParameters(self, search_parameters)
+
+    def Solve(self, assignment: "Assignment"=None) -> "operations_research::Assignment const *":
+        r"""
+        Solves the current routing model; closes the current model.
+        This is equivalent to calling
+        SolveWithParameters(DefaultRoutingSearchParameters())
+        or
+        SolveFromAssignmentWithParameters(assignment,
+                                          DefaultRoutingSearchParameters()).
+        """
+        return _pywrapcp.RoutingModel_Solve(self, assignment)
+
+    def SolveWithParameters(self, search_parameters: "operations_research::RoutingSearchParameters const &", solutions: "std::vector< operations_research::Assignment const * > *"=None) -> "operations_research::Assignment const *":
+        r"""
+        Solves the current routing model with the given parameters. If 'solutions'
+        is specified, it will contain the k best solutions found during the search
+        (from worst to best, including the one returned by this method), where k
+        corresponds to the 'number_of_solutions_to_collect' in
+        'search_parameters'. Note that the Assignment returned by the method and
+        the ones in solutions are owned by the underlying solver and should not be
+        deleted.
+        """
+        return _pywrapcp.RoutingModel_SolveWithParameters(self, search_parameters, solutions)
+
+    def SolveFromAssignmentWithParameters(self, assignment: "Assignment", search_parameters: "operations_research::RoutingSearchParameters const &", solutions: "std::vector< operations_research::Assignment const * > *"=None) -> "operations_research::Assignment const *":
+        r"""
+        Same as above, except that if assignment is not null, it will be used as
+        the initial solution.
+        """
+        return _pywrapcp.RoutingModel_SolveFromAssignmentWithParameters(self, assignment, search_parameters, solutions)
+
+    def SolveFromAssignmentsWithParameters(self, assignments: "std::vector< operations_research::Assignment const * > const &", search_parameters: "operations_research::RoutingSearchParameters const &", solutions: "std::vector< operations_research::Assignment const * > *"=None) -> "operations_research::Assignment const *":
+        r"""
+        Same as above but will try all assignments in order as first solutions
+        until one succeeds.
+        """
+        return _pywrapcp.RoutingModel_SolveFromAssignmentsWithParameters(self, assignments, search_parameters, solutions)
+
+    def SetAssignmentFromOtherModelAssignment(self, target_assignment: "Assignment", source_model: "RoutingModel", source_assignment: "Assignment") -> "void":
+        r"""
+        Given a "source_model" and its "source_assignment", resets
+        "target_assignment" with the IntVar variables (nexts_, and vehicle_vars_
+        if costs aren't homogeneous across vehicles) of "this" model, with the
+        values set according to those in "other_assignment".
+        The objective_element of target_assignment is set to this->cost_.
+        """
+        return _pywrapcp.RoutingModel_SetAssignmentFromOtherModelAssignment(self, target_assignment, source_model, source_assignment)
+
+    def ComputeLowerBound(self) -> "int64_t":
+        r"""
+        Computes a lower bound to the routing problem solving a linear assignment
+        problem. The routing model must be closed before calling this method.
+        Note that problems with node disjunction constraints (including optional
+        nodes) and non-homogenous costs are not supported (the method returns 0 in
+        these cases).
+        """
+        return _pywrapcp.RoutingModel_ComputeLowerBound(self)
+
+    def status(self) -> "operations_research::RoutingModel::Status":
+        r""" Returns the current status of the routing model."""
+        return _pywrapcp.RoutingModel_status(self)
+
+    def ApplyLocks(self, locks: "std::vector< int64_t > const &") -> "operations_research::IntVar *":
+        r"""
+        Applies a lock chain to the next search. 'locks' represents an ordered
+        vector of nodes representing a partial route which will be fixed during
+        the next search; it will constrain next variables such that:
+        next[locks[i]] == locks[i+1].
+
+        Returns the next variable at the end of the locked chain; this variable is
+        not locked. An assignment containing the locks can be obtained by calling
+        PreAssignment().
+        """
+        return _pywrapcp.RoutingModel_ApplyLocks(self, locks)
+
+    def ApplyLocksToAllVehicles(self, locks: "std::vector< std::vector< int64_t > > const &", close_routes: "bool") -> "bool":
+        r"""
+        Applies lock chains to all vehicles to the next search, such that locks[p]
+        is the lock chain for route p. Returns false if the locks do not contain
+        valid routes; expects that the routes do not contain the depots,
+        i.e. there are empty vectors in place of empty routes.
+        If close_routes is set to true, adds the end nodes to the route of each
+        vehicle and deactivates other nodes.
+        An assignment containing the locks can be obtained by calling
+        PreAssignment().
+        """
+        return _pywrapcp.RoutingModel_ApplyLocksToAllVehicles(self, locks, close_routes)
+
+    def PreAssignment(self) -> "operations_research::Assignment const *const":
+        r"""
+        Returns an assignment used to fix some of the variables of the problem.
+        In practice, this assignment locks partial routes of the problem. This
+        can be used in the context of locking the parts of the routes which have
+        already been driven in online routing problems.
+        """
+        return _pywrapcp.RoutingModel_PreAssignment(self)
+
+    def MutablePreAssignment(self) -> "operations_research::Assignment *":
+        return _pywrapcp.RoutingModel_MutablePreAssignment(self)
+
+    def WriteAssignment(self, file_name: "std::string const &") -> "bool":
+        r"""
+        Writes the current solution to a file containing an AssignmentProto.
+        Returns false if the file cannot be opened or if there is no current
+        solution.
+        """
+        return _pywrapcp.RoutingModel_WriteAssignment(self, file_name)
+
+    def ReadAssignment(self, file_name: "std::string const &") -> "operations_research::Assignment *":
+        r"""
+        Reads an assignment from a file and returns the current solution.
+        Returns nullptr if the file cannot be opened or if the assignment is not
+        valid.
+        """
+        return _pywrapcp.RoutingModel_ReadAssignment(self, file_name)
+
+    def RestoreAssignment(self, solution: "Assignment") -> "operations_research::Assignment *":
+        r"""
+        Restores an assignment as a solution in the routing model and returns the
+        new solution. Returns nullptr if the assignment is not valid.
+        """
+        return _pywrapcp.RoutingModel_RestoreAssignment(self, solution)
+
+    def ReadAssignmentFromRoutes(self, routes: "std::vector< std::vector< int64_t > > const &", ignore_inactive_indices: "bool") -> "operations_research::Assignment *":
+        r"""
+        Restores the routes as the current solution. Returns nullptr if the
+        solution cannot be restored (routes do not contain a valid solution). Note
+        that calling this method will run the solver to assign values to the
+        dimension variables; this may take considerable amount of time, especially
+        when using dimensions with slack.
+        """
+        return _pywrapcp.RoutingModel_ReadAssignmentFromRoutes(self, routes, ignore_inactive_indices)
+
+    def RoutesToAssignment(self, routes: "std::vector< std::vector< int64_t > > const &", ignore_inactive_indices: "bool", close_routes: "bool", assignment: "Assignment") -> "bool":
+        r"""
+        Fills an assignment from a specification of the routes of the
+        vehicles. The routes are specified as lists of variable indices that
+        appear on the routes of the vehicles. The indices of the outer vector in
+        'routes' correspond to vehicles IDs, the inner vector contains the
+        variable indices on the routes for the given vehicle. The inner vectors
+        must not contain the start and end indices, as these are determined by the
+        routing model.  Sets the value of NextVars in the assignment, adding the
+        variables to the assignment if necessary. The method does not touch other
+        variables in the assignment. The method can only be called after the model
+        is closed.  With ignore_inactive_indices set to false, this method will
+        fail (return nullptr) in case some of the route contain indices that are
+        deactivated in the model; when set to true, these indices will be
+        skipped.  Returns true if routes were successfully
+        loaded. However, such assignment still might not be a valid
+        solution to the routing problem due to more complex constraints;
+        it is advisible to call solver()->CheckSolution() afterwards.
+        """
+        return _pywrapcp.RoutingModel_RoutesToAssignment(self, routes, ignore_inactive_indices, close_routes, assignment)
+
+    def AssignmentToRoutes(self, assignment: "Assignment", routes: "std::vector< std::vector< int64_t > > *const") -> "void":
+        r"""
+        Converts the solution in the given assignment to routes for all vehicles.
+        Expects that assignment contains a valid solution (i.e. routes for all
+        vehicles end with an end index for that vehicle).
+        """
+        return _pywrapcp.RoutingModel_AssignmentToRoutes(self, assignment, routes)
+
+    def CompactAssignment(self, assignment: "Assignment") -> "operations_research::Assignment *":
+        r"""
+        Converts the solution in the given assignment to routes for all vehicles.
+        If the returned vector is route_indices, route_indices[i][j] is the index
+        for jth location visited on route i. Note that contrary to
+        AssignmentToRoutes, the vectors do include start and end locations.
+        Returns a compacted version of the given assignment, in which all vehicles
+        with id lower or equal to some N have non-empty routes, and all vehicles
+        with id greater than N have empty routes. Does not take ownership of the
+        returned object.
+        If found, the cost of the compact assignment is the same as in the
+        original assignment and it preserves the values of 'active' variables.
+        Returns nullptr if a compact assignment was not found.
+        This method only works in homogenous mode, and it only swaps equivalent
+        vehicles (vehicles with the same start and end nodes). When creating the
+        compact assignment, the empty plan is replaced by the route assigned to
+        the compatible vehicle with the highest id. Note that with more complex
+        constraints on vehicle variables, this method might fail even if a compact
+        solution exists.
+        This method changes the vehicle and dimension variables as necessary.
+        While compacting the solution, only basic checks on vehicle variables are
+        performed; if one of these checks fails no attempts to repair it are made
+        (instead, the method returns nullptr).
+        """
+        return _pywrapcp.RoutingModel_CompactAssignment(self, assignment)
+
+    def CompactAndCheckAssignment(self, assignment: "Assignment") -> "operations_research::Assignment *":
+        r"""
+        Same as CompactAssignment() but also checks the validity of the final
+        compact solution; if it is not valid, no attempts to repair it are made
+        (instead, the method returns nullptr).
+        """
+        return _pywrapcp.RoutingModel_CompactAndCheckAssignment(self, assignment)
+
+    def AddToAssignment(self, var: "IntVar") -> "void":
+        r""" Adds an extra variable to the vehicle routing assignment."""
+        return _pywrapcp.RoutingModel_AddToAssignment(self, var)
+
+    def AddIntervalToAssignment(self, interval: "IntervalVar") -> "void":
+        return _pywrapcp.RoutingModel_AddIntervalToAssignment(self, interval)
+
+    def PackCumulsOfOptimizerDimensionsFromAssignment(self, original_assignment: "Assignment", duration_limit: "absl::Duration") -> "operations_research::Assignment const *":
+        r"""
+        For every dimension in the model with an optimizer in
+        local/global_dimension_optimizers_, this method tries to pack the cumul
+        values of the dimension, such that:
+        - The cumul costs (span costs, soft lower and upper bound costs, etc) are
+          minimized.
+        - The cumuls of the ends of the routes are minimized for this given
+          minimal cumul cost.
+        - Given these minimal end cumuls, the route start cumuls are maximized.
+        Returns the assignment resulting from allocating these packed cumuls with
+        the solver, and nullptr if these cumuls could not be set by the solver.
+        """
+        return _pywrapcp.RoutingModel_PackCumulsOfOptimizerDimensionsFromAssignment(self, original_assignment, duration_limit)
+
+    def AddLocalSearchFilter(self, filter: "LocalSearchFilter") -> "void":
+        r"""
+        Adds a custom local search filter to the list of filters used to speed up
+        local search by pruning unfeasible variable assignments.
+        Calling this method after the routing model has been closed (CloseModel()
+        or Solve() has been called) has no effect.
+        The routing model does not take ownership of the filter.
+        """
+        return _pywrapcp.RoutingModel_AddLocalSearchFilter(self, filter)
+
+    def Start(self, vehicle: "int") -> "int64_t":
+        r"""
+        Model inspection.
+        Returns the variable index of the starting node of a vehicle route.
+        """
+        return _pywrapcp.RoutingModel_Start(self, vehicle)
+
+    def End(self, vehicle: "int") -> "int64_t":
+        r""" Returns the variable index of the ending node of a vehicle route."""
+        return _pywrapcp.RoutingModel_End(self, vehicle)
+
+    def IsStart(self, index: "int64_t") -> "bool":
+        r""" Returns true if 'index' represents the first node of a route."""
+        return _pywrapcp.RoutingModel_IsStart(self, index)
+
+    def IsEnd(self, index: "int64_t") -> "bool":
+        r""" Returns true if 'index' represents the last node of a route."""
+        return _pywrapcp.RoutingModel_IsEnd(self, index)
+
+    def VehicleIndex(self, index: "int64_t") -> "int":
+        r"""
+        Returns the vehicle of the given start/end index, and -1 if the given
+        index is not a vehicle start/end.
+        """
+        return _pywrapcp.RoutingModel_VehicleIndex(self, index)
+
+    def Next(self, assignment: "Assignment", index: "int64_t") -> "int64_t":
+        r"""
+        Assignment inspection
+        Returns the variable index of the node directly after the node
+        corresponding to 'index' in 'assignment'.
+        """
+        return _pywrapcp.RoutingModel_Next(self, assignment, index)
+
+    def IsVehicleUsed(self, assignment: "Assignment", vehicle: "int") -> "bool":
+        r""" Returns true if the route of 'vehicle' is non empty in 'assignment'."""
+        return _pywrapcp.RoutingModel_IsVehicleUsed(self, assignment, vehicle)
+
+    def NextVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        r"""
+        Returns the next variable of the node corresponding to index. Note that
+        NextVar(index) == index is equivalent to ActiveVar(index) == 0.
+        """
+        return _pywrapcp.RoutingModel_NextVar(self, index)
+
+    def ActiveVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        r""" Returns the active variable of the node corresponding to index."""
+        return _pywrapcp.RoutingModel_ActiveVar(self, index)
+
+    def ActiveVehicleVar(self, vehicle: "int") -> "operations_research::IntVar *":
+        r"""
+        Returns the active variable of the vehicle. It will be equal to 1 iff the
+        route of the vehicle is not empty, 0 otherwise.
+        """
+        return _pywrapcp.RoutingModel_ActiveVehicleVar(self, vehicle)
+
+    def VehicleRouteConsideredVar(self, vehicle: "int") -> "operations_research::IntVar *":
+        r"""
+        Returns the variable specifying whether or not the given vehicle route is
+        considered for costs and constraints. It will be equal to 1 iff the route
+        of the vehicle is not empty OR vehicle_used_when_empty_[vehicle] is true.
+        """
+        return _pywrapcp.RoutingModel_VehicleRouteConsideredVar(self, vehicle)
+
+    def VehicleVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        r"""
+        Returns the vehicle variable of the node corresponding to index. Note that
+        VehicleVar(index) == -1 is equivalent to ActiveVar(index) == 0.
+        """
+        return _pywrapcp.RoutingModel_VehicleVar(self, index)
+
+    def ResourceVar(self, vehicle: "int", resource_group: "int") -> "operations_research::IntVar *":
+        r"""
+        Returns the resource variable for the given vehicle index in the given
+        resource group. If a vehicle doesn't require a resource from the
+        corresponding resource group, then ResourceVar(v, r_g) == -1.
+        """
+        return _pywrapcp.RoutingModel_ResourceVar(self, vehicle, resource_group)
+
+    def CostVar(self) -> "operations_research::IntVar *":
+        r""" Returns the global cost variable which is being minimized."""
+        return _pywrapcp.RoutingModel_CostVar(self)
+
+    def GetArcCostForVehicle(self, from_index: "int64_t", to_index: "int64_t", vehicle: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost of the transit arc between two nodes for a given vehicle.
+        Input are variable indices of node. This returns 0 if vehicle < 0.
+        """
+        return _pywrapcp.RoutingModel_GetArcCostForVehicle(self, from_index, to_index, vehicle)
+
+    def CostsAreHomogeneousAcrossVehicles(self) -> "bool":
+        r""" Whether costs are homogeneous across all vehicles."""
+        return _pywrapcp.RoutingModel_CostsAreHomogeneousAcrossVehicles(self)
+
+    def GetHomogeneousCost(self, from_index: "int64_t", to_index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost of the segment between two nodes supposing all vehicle
+        costs are the same (returns the cost for the first vehicle otherwise).
+        """
+        return _pywrapcp.RoutingModel_GetHomogeneousCost(self, from_index, to_index)
+
+    def GetArcCostForFirstSolution(self, from_index: "int64_t", to_index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost of the arc in the context of the first solution strategy.
+        This is typically a simplification of the actual cost; see the .cc.
+        """
+        return _pywrapcp.RoutingModel_GetArcCostForFirstSolution(self, from_index, to_index)
+
+    def GetArcCostForClass(self, from_index: "int64_t", to_index: "int64_t", cost_class_index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost of the segment between two nodes for a given cost
+        class. Input are variable indices of nodes and the cost class.
+        Unlike GetArcCostForVehicle(), if cost_class is kNoCost, then the
+        returned cost won't necessarily be zero: only some of the components
+        of the cost that depend on the cost class will be omited. See the code
+        for details.
+        """
+        return _pywrapcp.RoutingModel_GetArcCostForClass(self, from_index, to_index, cost_class_index)
+
+    def GetCostClassIndexOfVehicle(self, vehicle: "int64_t") -> "operations_research::RoutingModel::CostClassIndex":
+        r""" Get the cost class index of the given vehicle."""
+        return _pywrapcp.RoutingModel_GetCostClassIndexOfVehicle(self, vehicle)
+
+    def HasVehicleWithCostClassIndex(self, cost_class_index: "operations_research::RoutingModel::CostClassIndex") -> "bool":
+        r"""
+        Returns true iff the model contains a vehicle with the given
+        cost_class_index.
+        """
+        return _pywrapcp.RoutingModel_HasVehicleWithCostClassIndex(self, cost_class_index)
+
+    def GetCostClassesCount(self) -> "int":
+        r""" Returns the number of different cost classes in the model."""
+        return _pywrapcp.RoutingModel_GetCostClassesCount(self)
+
+    def GetNonZeroCostClassesCount(self) -> "int":
+        r""" Ditto, minus the 'always zero', built-in cost class."""
+        return _pywrapcp.RoutingModel_GetNonZeroCostClassesCount(self)
+
+    def GetVehicleClassIndexOfVehicle(self, vehicle: "int64_t") -> "operations_research::RoutingModel::VehicleClassIndex":
+        return _pywrapcp.RoutingModel_GetVehicleClassIndexOfVehicle(self, vehicle)
+
+    def GetVehicleOfClass(self, vehicle_class: "operations_research::RoutingModel::VehicleClassIndex") -> "int":
+        r"""
+        Returns a vehicle of the given vehicle class, and -1 if there are no
+        vehicles for this class.
+        """
+        return _pywrapcp.RoutingModel_GetVehicleOfClass(self, vehicle_class)
+
+    def GetVehicleClassesCount(self) -> "int":
+        r""" Returns the number of different vehicle classes in the model."""
+        return _pywrapcp.RoutingModel_GetVehicleClassesCount(self)
+
+    def GetSameVehicleIndicesOfIndex(self, node: "int") -> "std::vector< int > const &":
+        r""" Returns variable indices of nodes constrained to be on the same route."""
+        return _pywrapcp.RoutingModel_GetSameVehicleIndicesOfIndex(self, node)
+
+    def GetVehicleTypeContainer(self) -> "operations_research::RoutingModel::VehicleTypeContainer const &":
+        return _pywrapcp.RoutingModel_GetVehicleTypeContainer(self)
+
+    def ArcIsMoreConstrainedThanArc(self, _from: "int64_t", to1: "int64_t", to2: "int64_t") -> "bool":
+        r"""
+        Returns whether the arc from->to1 is more constrained than from->to2,
+        taking into account, in order:
+        - whether the destination node isn't an end node
+        - whether the destination node is mandatory
+        - whether the destination node is bound to the same vehicle as the source
+        - the "primary constrained" dimension (see SetPrimaryConstrainedDimension)
+        It then breaks ties using, in order:
+        - the arc cost (taking unperformed penalties into account)
+        - the size of the vehicle vars of "to1" and "to2" (lowest size wins)
+        - the value: the lowest value of the indices to1 and to2 wins.
+        See the .cc for details.
+        The more constrained arc is typically preferable when building a
+        first solution. This method is intended to be used as a callback for the
+        BestValueByComparisonSelector value selector.
+        Args:
+          from: the variable index of the source node
+          to1: the variable index of the first candidate destination node.
+          to2: the variable index of the second candidate destination node.
+        """
+        return _pywrapcp.RoutingModel_ArcIsMoreConstrainedThanArc(self, _from, to1, to2)
+
+    def DebugOutputAssignment(self, solution_assignment: "Assignment", dimension_to_print: "std::string const &") -> "std::string":
+        r"""
+        Print some debugging information about an assignment, including the
+        feasible intervals of the CumulVar for dimension "dimension_to_print"
+        at each step of the routes.
+        If "dimension_to_print" is omitted, all dimensions will be printed.
+        """
+        return _pywrapcp.RoutingModel_DebugOutputAssignment(self, solution_assignment, dimension_to_print)
+
+    def solver(self) -> "operations_research::Solver *":
+        r"""
+        Returns a vector cumul_bounds, for which cumul_bounds[i][j] is a pair
+        containing the minimum and maximum of the CumulVar of the jth node on
+        route i.
+        - cumul_bounds[i][j].first is the minimum.
+        - cumul_bounds[i][j].second is the maximum.
+        Returns the underlying constraint solver. Can be used to add extra
+        constraints and/or modify search algorithms.
+        """
+        return _pywrapcp.RoutingModel_solver(self)
+
+    def CheckLimit(self) -> "bool":
+        r""" Returns true if the search limit has been crossed."""
+        return _pywrapcp.RoutingModel_CheckLimit(self)
+
+    def RemainingTime(self) -> "absl::Duration":
+        r""" Returns the time left in the search limit."""
+        return _pywrapcp.RoutingModel_RemainingTime(self)
+
+    def nodes(self) -> "int":
+        r"""
+        Sizes and indices
+        Returns the number of nodes in the model.
+        """
+        return _pywrapcp.RoutingModel_nodes(self)
+
+    def vehicles(self) -> "int":
+        r""" Returns the number of vehicle routes in the model."""
+        return _pywrapcp.RoutingModel_vehicles(self)
+
+    def Size(self) -> "int64_t":
+        r""" Returns the number of next variables in the model."""
+        return _pywrapcp.RoutingModel_Size(self)
+
+    def GetNumberOfDecisionsInFirstSolution(self, search_parameters: "operations_research::RoutingSearchParameters const &") -> "int64_t":
+        r"""
+        Returns statistics on first solution search, number of decisions sent to
+        filters, number of decisions rejected by filters.
+        """
+        return _pywrapcp.RoutingModel_GetNumberOfDecisionsInFirstSolution(self, search_parameters)
+
+    def GetNumberOfRejectsInFirstSolution(self, search_parameters: "operations_research::RoutingSearchParameters const &") -> "int64_t":
+        return _pywrapcp.RoutingModel_GetNumberOfRejectsInFirstSolution(self, search_parameters)
+
+    def GetAutomaticFirstSolutionStrategy(self) -> "operations_research::FirstSolutionStrategy::Value":
+        r""" Returns the automatic first solution strategy selected."""
+        return _pywrapcp.RoutingModel_GetAutomaticFirstSolutionStrategy(self)
+
+    def IsMatchingModel(self) -> "bool":
+        r""" Returns true if a vehicle/node matching problem is detected."""
+        return _pywrapcp.RoutingModel_IsMatchingModel(self)
+
+    def MakeGuidedSlackFinalizer(self, dimension: "RoutingDimension", initializer: "std::function< int64_t (int64_t) >") -> "operations_research::DecisionBuilder *":
+        r"""
+        The next few members are in the public section only for testing purposes.
+
+        MakeGuidedSlackFinalizer creates a DecisionBuilder for the slacks of a
+        dimension using a callback to choose which values to start with.
+        The finalizer works only when all next variables in the model have
+        been fixed. It has the following two characteristics:
+        1. It follows the routes defined by the nexts variables when choosing a
+           variable to make a decision on.
+        2. When it comes to choose a value for the slack of node i, the decision
+           builder first calls the callback with argument i, and supposingly the
+           returned value is x it creates decisions slack[i] = x, slack[i] = x +
+           1, slack[i] = x - 1, slack[i] = x + 2, etc.
+        """
+        return _pywrapcp.RoutingModel_MakeGuidedSlackFinalizer(self, dimension, initializer)
+
+    def MakeSelfDependentDimensionFinalizer(self, dimension: "RoutingDimension") -> "operations_research::DecisionBuilder *":
+        r"""
+        MakeSelfDependentDimensionFinalizer is a finalizer for the slacks of a
+        self-dependent dimension. It makes an extensive use of the caches of the
+        state dependent transits.
+        In detail, MakeSelfDependentDimensionFinalizer returns a composition of a
+        local search decision builder with a greedy descent operator for the cumul
+        of the start of each route and a guided slack finalizer. Provided there
+        are no time windows and the maximum slacks are large enough, once the
+        cumul of the start of route is fixed, the guided finalizer can find
+        optimal values of the slacks for the rest of the route in time
+        proportional to the length of the route. Therefore the composed finalizer
+        generally works in time O(log(t)*n*m), where t is the latest possible
+        departute time, n is the number of nodes in the network and m is the
+        number of vehicles.
+        """
+        return _pywrapcp.RoutingModel_MakeSelfDependentDimensionFinalizer(self, dimension)
+
+ +
+ + + +
+
#   + + + RoutingModel(*args) +
+ +
+ View Source +
    def __init__(self, *args):
+        _pywrapcp.RoutingModel_swiginit(self, _pywrapcp.new_RoutingModel(*args))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + ROUTING_NOT_SOLVED = 0 +
+ + +

Problem not solved yet (before calling RoutingModel::Solve()).

+
+ + +
+
+
#   + + ROUTING_SUCCESS = 1 +
+ + +

Problem solved successfully after calling RoutingModel::Solve().

+
+ + +
+
+
#   + + ROUTING_FAIL = 2 +
+ + +

No solution found to the problem after calling RoutingModel::Solve().

+
+ + +
+
+
#   + + ROUTING_FAIL_TIMEOUT = 3 +
+ + +

Time limit reached before finding a solution with RoutingModel::Solve().

+
+ + +
+
+
#   + + ROUTING_INVALID = 4 +
+ + +

Model, model parameters or flags are not valid.

+
+ + +
+
+
#   + + ROUTING_INFEASIBLE = 5 +
+ + +

Problem proven to be infeasible.

+
+ + +
+
+
#   + + PICKUP_AND_DELIVERY_NO_ORDER = 0 +
+ + +

Any precedence is accepted.

+
+ + +
+
+
#   + + PICKUP_AND_DELIVERY_LIFO = 1 +
+ + +

Deliveries must be performed in reverse order of pickups.

+
+ + +
+
+
#   + + PICKUP_AND_DELIVERY_FIFO = 2 +
+ + +

Deliveries must be performed in the same order as pickups.

+
+ + +
+
+
#   + + + def + RegisterUnaryTransitVector(self, values: 'std::vector< int64_t >') -> int: +
+ +
+ View Source +
    def RegisterUnaryTransitVector(self, values: "std::vector< int64_t >") -> "int":
+        r""" Registers 'callback' and returns its index."""
+        return _pywrapcp.RoutingModel_RegisterUnaryTransitVector(self, values)
+
+ +
+ +

Registers 'callback' and returns its index.

+
+ + +
+
+
#   + + + def + RegisterUnaryTransitCallback( + self, + callback: 'operations_research::RoutingModel::TransitCallback1' +) -> int: +
+ +
+ View Source +
    def RegisterUnaryTransitCallback(self, callback: "operations_research::RoutingModel::TransitCallback1") -> "int":
+        return _pywrapcp.RoutingModel_RegisterUnaryTransitCallback(self, callback)
+
+ +
+ + + +
+
+
#   + + + def + RegisterPositiveUnaryTransitCallback( + self, + callback: 'operations_research::RoutingModel::TransitCallback1' +) -> int: +
+ +
+ View Source +
    def RegisterPositiveUnaryTransitCallback(self, callback: "operations_research::RoutingModel::TransitCallback1") -> "int":
+        return _pywrapcp.RoutingModel_RegisterPositiveUnaryTransitCallback(self, callback)
+
+ +
+ + + +
+
+
#   + + + def + RegisterTransitMatrix(self, values: 'std::vector< std::vector< int64_t > >') -> int: +
+ +
+ View Source +
    def RegisterTransitMatrix(self, values: "std::vector< std::vector< int64_t > >") -> "int":
+        return _pywrapcp.RoutingModel_RegisterTransitMatrix(self, values)
+
+ +
+ + + +
+
+
#   + + + def + RegisterTransitCallback( + self, + callback: 'operations_research::RoutingModel::TransitCallback2' +) -> int: +
+ +
+ View Source +
    def RegisterTransitCallback(self, callback: "operations_research::RoutingModel::TransitCallback2") -> "int":
+        return _pywrapcp.RoutingModel_RegisterTransitCallback(self, callback)
+
+ +
+ + + +
+
+
#   + + + def + RegisterPositiveTransitCallback( + self, + callback: 'operations_research::RoutingModel::TransitCallback2' +) -> int: +
+ +
+ View Source +
    def RegisterPositiveTransitCallback(self, callback: "operations_research::RoutingModel::TransitCallback2") -> "int":
+        return _pywrapcp.RoutingModel_RegisterPositiveTransitCallback(self, callback)
+
+ +
+ + + +
+
+
#   + + + def + TransitCallback( + self, + callback_index: int +) -> 'operations_research::RoutingModel::TransitCallback2 const &': +
+ +
+ View Source +
    def TransitCallback(self, callback_index: "int") -> "operations_research::RoutingModel::TransitCallback2 const &":
+        return _pywrapcp.RoutingModel_TransitCallback(self, callback_index)
+
+ +
+ + + +
+
+
#   + + + def + UnaryTransitCallbackOrNull( + self, + callback_index: int +) -> 'operations_research::RoutingModel::TransitCallback1 const &': +
+ +
+ View Source +
    def UnaryTransitCallbackOrNull(self, callback_index: "int") -> "operations_research::RoutingModel::TransitCallback1 const &":
+        return _pywrapcp.RoutingModel_UnaryTransitCallbackOrNull(self, callback_index)
+
+ +
+ + + +
+
+
#   + + + def + AddDimension( + self, + evaluator_index: int, + slack_max: 'int64_t', + capacity: 'int64_t', + fix_start_cumul_to_zero: bool, + name: 'std::string const &' +) -> bool: +
+ +
+ View Source +
    def AddDimension(self, evaluator_index: "int", slack_max: "int64_t", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "bool":
+        r"""
+        Model creation
+        Methods to add dimensions to routes; dimensions represent quantities
+        accumulated at nodes along the routes. They represent quantities such as
+        weights or volumes carried along the route, or distance or times.
+        Quantities at a node are represented by "cumul" variables and the increase
+        or decrease of quantities between nodes are represented by "transit"
+        variables. These variables are linked as follows:
+        if j == next(i), cumul(j) = cumul(i) + transit(i) + slack(i)
+        where slack is a positive slack variable (can represent waiting times for
+        a time dimension).
+        Setting the value of fix_start_cumul_to_zero to true will force the
+        "cumul" variable of the start node of all vehicles to be equal to 0.
+        Creates a dimension where the transit variable is constrained to be
+        equal to evaluator(i, next(i)); 'slack_max' is the upper bound of the
+        slack variable and 'capacity' is the upper bound of the cumul variables.
+        'name' is the name used to reference the dimension; this name is used to
+        get cumul and transit variables from the routing model.
+        Returns false if a dimension with the same name has already been created
+        (and doesn't create the new dimension).
+        Takes ownership of the callback 'evaluator'.
+        """
+        return _pywrapcp.RoutingModel_AddDimension(self, evaluator_index, slack_max, capacity, fix_start_cumul_to_zero, name)
+
+ +
+ +

Model creation +Methods to add dimensions to routes; dimensions represent quantities +accumulated at nodes along the routes. They represent quantities such as +weights or volumes carried along the route, or distance or times. +Quantities at a node are represented by "cumul" variables and the increase +or decrease of quantities between nodes are represented by "transit" +variables. These variables are linked as follows: +if j == next(i), cumul(j) = cumul(i) + transit(i) + slack(i) +where slack is a positive slack variable (can represent waiting times for +a time dimension). +Setting the value of fix_start_cumul_to_zero to true will force the +"cumul" variable of the start node of all vehicles to be equal to 0. +Creates a dimension where the transit variable is constrained to be +equal to evaluator(i, next(i)); 'slack_max' is the upper bound of the +slack variable and 'capacity' is the upper bound of the cumul variables. +'name' is the name used to reference the dimension; this name is used to +get cumul and transit variables from the routing model. +Returns false if a dimension with the same name has already been created +(and doesn't create the new dimension). +Takes ownership of the callback 'evaluator'.

+
+ + +
+
+
#   + + + def + AddDimensionWithVehicleTransits( + self, + evaluator_indices: 'std::vector< int > const &', + slack_max: 'int64_t', + capacity: 'int64_t', + fix_start_cumul_to_zero: bool, + name: 'std::string const &' +) -> bool: +
+ +
+ View Source +
    def AddDimensionWithVehicleTransits(self, evaluator_indices: "std::vector< int > const &", slack_max: "int64_t", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "bool":
+        return _pywrapcp.RoutingModel_AddDimensionWithVehicleTransits(self, evaluator_indices, slack_max, capacity, fix_start_cumul_to_zero, name)
+
+ +
+ + + +
+
+
#   + + + def + AddDimensionWithVehicleCapacity( + self, + evaluator_index: int, + slack_max: 'int64_t', + vehicle_capacities: 'std::vector< int64_t >', + fix_start_cumul_to_zero: bool, + name: 'std::string const &' +) -> bool: +
+ +
+ View Source +
    def AddDimensionWithVehicleCapacity(self, evaluator_index: "int", slack_max: "int64_t", vehicle_capacities: "std::vector< int64_t >", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "bool":
+        return _pywrapcp.RoutingModel_AddDimensionWithVehicleCapacity(self, evaluator_index, slack_max, vehicle_capacities, fix_start_cumul_to_zero, name)
+
+ +
+ + + +
+
+
#   + + + def + AddDimensionWithVehicleTransitAndCapacity( + self, + evaluator_indices: 'std::vector< int > const &', + slack_max: 'int64_t', + vehicle_capacities: 'std::vector< int64_t >', + fix_start_cumul_to_zero: bool, + name: 'std::string const &' +) -> bool: +
+ +
+ View Source +
    def AddDimensionWithVehicleTransitAndCapacity(self, evaluator_indices: "std::vector< int > const &", slack_max: "int64_t", vehicle_capacities: "std::vector< int64_t >", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "bool":
+        return _pywrapcp.RoutingModel_AddDimensionWithVehicleTransitAndCapacity(self, evaluator_indices, slack_max, vehicle_capacities, fix_start_cumul_to_zero, name)
+
+ +
+ + + +
+
+
#   + + + def + AddConstantDimensionWithSlack( + self, + value: 'int64_t', + capacity: 'int64_t', + slack_max: 'int64_t', + fix_start_cumul_to_zero: bool, + name: 'std::string const &' +) -> 'std::pair< int,bool >': +
+ +
+ View Source +
    def AddConstantDimensionWithSlack(self, value: "int64_t", capacity: "int64_t", slack_max: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "std::pair< int,bool >":
+        r"""
+        Creates a dimension where the transit variable is constrained to be
+        equal to 'value'; 'capacity' is the upper bound of the cumul variables.
+        'name' is the name used to reference the dimension; this name is used to
+        get cumul and transit variables from the routing model.
+        Returns a pair consisting of an index to the registered unary transit
+        callback and a bool denoting whether the dimension has been created.
+        It is false if a dimension with the same name has already been created
+        (and doesn't create the new dimension but still register a new callback).
+        """
+        return _pywrapcp.RoutingModel_AddConstantDimensionWithSlack(self, value, capacity, slack_max, fix_start_cumul_to_zero, name)
+
+ +
+ +

Creates a dimension where the transit variable is constrained to be +equal to 'value'; 'capacity' is the upper bound of the cumul variables. +'name' is the name used to reference the dimension; this name is used to +get cumul and transit variables from the routing model. +Returns a pair consisting of an index to the registered unary transit +callback and a bool denoting whether the dimension has been created. +It is false if a dimension with the same name has already been created +(and doesn't create the new dimension but still register a new callback).

+
+ + +
+
+
#   + + + def + AddConstantDimension( + self, + value: 'int64_t', + capacity: 'int64_t', + fix_start_cumul_to_zero: bool, + name: 'std::string const &' +) -> 'std::pair< int,bool >': +
+ +
+ View Source +
    def AddConstantDimension(self, value: "int64_t", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "std::pair< int,bool >":
+        return _pywrapcp.RoutingModel_AddConstantDimension(self, value, capacity, fix_start_cumul_to_zero, name)
+
+ +
+ + + +
+
+
#   + + + def + AddVectorDimension( + self, + values: 'std::vector< int64_t >', + capacity: 'int64_t', + fix_start_cumul_to_zero: bool, + name: 'std::string const &' +) -> 'std::pair< int,bool >': +
+ +
+ View Source +
    def AddVectorDimension(self, values: "std::vector< int64_t >", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "std::pair< int,bool >":
+        r"""
+        Creates a dimension where the transit variable is constrained to be
+        equal to 'values[i]' for node i; 'capacity' is the upper bound of
+        the cumul variables. 'name' is the name used to reference the dimension;
+        this name is used to get cumul and transit variables from the routing
+        model.
+        Returns a pair consisting of an index to the registered unary transit
+        callback and a bool denoting whether the dimension has been created.
+        It is false if a dimension with the same name has already been created
+        (and doesn't create the new dimension but still register a new callback).
+        """
+        return _pywrapcp.RoutingModel_AddVectorDimension(self, values, capacity, fix_start_cumul_to_zero, name)
+
+ +
+ +

Creates a dimension where the transit variable is constrained to be +equal to 'values[i]' for node i; 'capacity' is the upper bound of +the cumul variables. 'name' is the name used to reference the dimension; +this name is used to get cumul and transit variables from the routing +model. +Returns a pair consisting of an index to the registered unary transit +callback and a bool denoting whether the dimension has been created. +It is false if a dimension with the same name has already been created +(and doesn't create the new dimension but still register a new callback).

+
+ + +
+
+
#   + + + def + AddMatrixDimension( + self, + values: 'std::vector< std::vector< int64_t > >', + capacity: 'int64_t', + fix_start_cumul_to_zero: bool, + name: 'std::string const &' +) -> 'std::pair< int,bool >': +
+ +
+ View Source +
    def AddMatrixDimension(self, values: "std::vector< std::vector< int64_t > >", capacity: "int64_t", fix_start_cumul_to_zero: "bool", name: "std::string const &") -> "std::pair< int,bool >":
+        r"""
+        Creates a dimension where the transit variable is constrained to be
+        equal to 'values[i][next(i)]' for node i; 'capacity' is the upper bound of
+        the cumul variables. 'name' is the name used to reference the dimension;
+        this name is used to get cumul and transit variables from the routing
+        model.
+        Returns a pair consisting of an index to the registered transit callback
+        and a bool denoting whether the dimension has been created.
+        It is false if a dimension with the same name has already been created
+        (and doesn't create the new dimension but still register a new callback).
+        """
+        return _pywrapcp.RoutingModel_AddMatrixDimension(self, values, capacity, fix_start_cumul_to_zero, name)
+
+ +
+ +

Creates a dimension where the transit variable is constrained to be +equal to 'values[i][next(i)]' for node i; 'capacity' is the upper bound of +the cumul variables. 'name' is the name used to reference the dimension; +this name is used to get cumul and transit variables from the routing +model. +Returns a pair consisting of an index to the registered transit callback +and a bool denoting whether the dimension has been created. +It is false if a dimension with the same name has already been created +(and doesn't create the new dimension but still register a new callback).

+
+ + +
+
+
#   + + + def + MakePathSpansAndTotalSlacks( + self, + dimension: ortools.constraint_solver.pywrapcp.RoutingDimension, + spans: 'std::vector< operations_research::IntVar * >', + total_slacks: 'std::vector< operations_research::IntVar * >' +) -> 'operations_research::Constraint *': +
+ +
+ View Source +
    def MakePathSpansAndTotalSlacks(self, dimension: "RoutingDimension", spans: "std::vector< operations_research::IntVar * >", total_slacks: "std::vector< operations_research::IntVar * >") -> "operations_research::Constraint *":
+        r"""
+        For every vehicle of the routing model:
+        - if total_slacks[vehicle] is not nullptr, constrains it to be the sum of
+          slacks on that vehicle, that is,
+          dimension->CumulVar(end) - dimension->CumulVar(start) -
+          sum_{node in path of vehicle} dimension->FixedTransitVar(node).
+        - if spans[vehicle] is not nullptr, constrains it to be
+          dimension->CumulVar(end) - dimension->CumulVar(start)
+        This does stronger propagation than a decomposition, and takes breaks into
+        account.
+        """
+        return _pywrapcp.RoutingModel_MakePathSpansAndTotalSlacks(self, dimension, spans, total_slacks)
+
+ +
+ +

For every vehicle of the routing model:

+ +
    +
  • if total_slacks[vehicle] is not nullptr, constrains it to be the sum of +slacks on that vehicle, that is, +dimension->CumulVar(end) - dimension->CumulVar(start) - +sum_{node in path of vehicle} dimension->FixedTransitVar(node).
  • +
  • if spans[vehicle] is not nullptr, constrains it to be +dimension->CumulVar(end) - dimension->CumulVar(start) +This does stronger propagation than a decomposition, and takes breaks into +account.
  • +
+
+ + +
+
+
#   + + + def + GetAllDimensionNames(self) -> 'std::vector< std::string >': +
+ +
+ View Source +
    def GetAllDimensionNames(self) -> "std::vector< std::string >":
+        r""" Outputs the names of all dimensions added to the routing engine."""
+        return _pywrapcp.RoutingModel_GetAllDimensionNames(self)
+
+ +
+ +

Outputs the names of all dimensions added to the routing engine.

+
+ + +
+
+
#   + + + def + GetDimensions( + self +) -> 'std::vector< operations_research::RoutingDimension * > const &': +
+ +
+ View Source +
    def GetDimensions(self) -> "std::vector< operations_research::RoutingDimension * > const &":
+        r""" Returns all dimensions of the model."""
+        return _pywrapcp.RoutingModel_GetDimensions(self)
+
+ +
+ +

Returns all dimensions of the model.

+
+ + +
+
+
#   + + + def + GetDimensionsWithSoftOrSpanCosts(self) -> 'std::vector< operations_research::RoutingDimension * >': +
+ +
+ View Source +
    def GetDimensionsWithSoftOrSpanCosts(self) -> "std::vector< operations_research::RoutingDimension * >":
+        r""" Returns dimensions with soft or vehicle span costs."""
+        return _pywrapcp.RoutingModel_GetDimensionsWithSoftOrSpanCosts(self)
+
+ +
+ +

Returns dimensions with soft or vehicle span costs.

+
+ + +
+
+
#   + + + def + GetGlobalDimensionCumulOptimizers( + self +) -> 'std::vector< std::unique_ptr< operations_research::GlobalDimensionCumulOptimizer > > const &': +
+ +
+ View Source +
    def GetGlobalDimensionCumulOptimizers(self) -> "std::vector< std::unique_ptr< operations_research::GlobalDimensionCumulOptimizer > > const &":
+        r"""
+        Returns [global|local]_dimension_optimizers_, which are empty if the model
+        has not been closed.
+        """
+        return _pywrapcp.RoutingModel_GetGlobalDimensionCumulOptimizers(self)
+
+ +
+ +

Returns [global|local]_dimension_optimizers_, which are empty if the model +has not been closed.

+
+ + +
+
+
#   + + + def + GetGlobalDimensionCumulMPOptimizers( + self +) -> 'std::vector< std::unique_ptr< operations_research::GlobalDimensionCumulOptimizer > > const &': +
+ +
+ View Source +
    def GetGlobalDimensionCumulMPOptimizers(self) -> "std::vector< std::unique_ptr< operations_research::GlobalDimensionCumulOptimizer > > const &":
+        return _pywrapcp.RoutingModel_GetGlobalDimensionCumulMPOptimizers(self)
+
+ +
+ + + +
+
+
#   + + + def + GetLocalDimensionCumulOptimizers( + self +) -> 'std::vector< std::unique_ptr< operations_research::LocalDimensionCumulOptimizer > > const &': +
+ +
+ View Source +
    def GetLocalDimensionCumulOptimizers(self) -> "std::vector< std::unique_ptr< operations_research::LocalDimensionCumulOptimizer > > const &":
+        return _pywrapcp.RoutingModel_GetLocalDimensionCumulOptimizers(self)
+
+ +
+ + + +
+
+
#   + + + def + GetLocalDimensionCumulMPOptimizers( + self +) -> 'std::vector< std::unique_ptr< operations_research::LocalDimensionCumulOptimizer > > const &': +
+ +
+ View Source +
    def GetLocalDimensionCumulMPOptimizers(self) -> "std::vector< std::unique_ptr< operations_research::LocalDimensionCumulOptimizer > > const &":
+        return _pywrapcp.RoutingModel_GetLocalDimensionCumulMPOptimizers(self)
+
+ +
+ + + +
+
+
#   + + + def + GetMutableGlobalCumulOptimizer( + self, + dimension: ortools.constraint_solver.pywrapcp.RoutingDimension +) -> 'operations_research::GlobalDimensionCumulOptimizer *': +
+ +
+ View Source +
    def GetMutableGlobalCumulOptimizer(self, dimension: "RoutingDimension") -> "operations_research::GlobalDimensionCumulOptimizer *":
+        r"""
+        Returns the global/local dimension cumul optimizer for a given dimension,
+        or nullptr if there is none.
+        """
+        return _pywrapcp.RoutingModel_GetMutableGlobalCumulOptimizer(self, dimension)
+
+ +
+ +

Returns the global/local dimension cumul optimizer for a given dimension, +or nullptr if there is none.

+
+ + +
+
+
#   + + + def + GetMutableGlobalCumulMPOptimizer( + self, + dimension: ortools.constraint_solver.pywrapcp.RoutingDimension +) -> 'operations_research::GlobalDimensionCumulOptimizer *': +
+ +
+ View Source +
    def GetMutableGlobalCumulMPOptimizer(self, dimension: "RoutingDimension") -> "operations_research::GlobalDimensionCumulOptimizer *":
+        return _pywrapcp.RoutingModel_GetMutableGlobalCumulMPOptimizer(self, dimension)
+
+ +
+ + + +
+
+
#   + + + def + GetMutableLocalCumulOptimizer( + self, + dimension: ortools.constraint_solver.pywrapcp.RoutingDimension +) -> 'operations_research::LocalDimensionCumulOptimizer *': +
+ +
+ View Source +
    def GetMutableLocalCumulOptimizer(self, dimension: "RoutingDimension") -> "operations_research::LocalDimensionCumulOptimizer *":
+        return _pywrapcp.RoutingModel_GetMutableLocalCumulOptimizer(self, dimension)
+
+ +
+ + + +
+
+
#   + + + def + GetMutableLocalCumulMPOptimizer( + self, + dimension: ortools.constraint_solver.pywrapcp.RoutingDimension +) -> 'operations_research::LocalDimensionCumulOptimizer *': +
+ +
+ View Source +
    def GetMutableLocalCumulMPOptimizer(self, dimension: "RoutingDimension") -> "operations_research::LocalDimensionCumulOptimizer *":
+        return _pywrapcp.RoutingModel_GetMutableLocalCumulMPOptimizer(self, dimension)
+
+ +
+ + + +
+
+
#   + + + def + HasDimension(self, dimension_name: 'std::string const &') -> bool: +
+ +
+ View Source +
    def HasDimension(self, dimension_name: "std::string const &") -> "bool":
+        r""" Returns true if a dimension exists for a given dimension name."""
+        return _pywrapcp.RoutingModel_HasDimension(self, dimension_name)
+
+ +
+ +

Returns true if a dimension exists for a given dimension name.

+
+ + +
+
+
#   + + + def + GetDimensionOrDie( + self, + dimension_name: 'std::string const &' +) -> 'operations_research::RoutingDimension const &': +
+ +
+ View Source +
    def GetDimensionOrDie(self, dimension_name: "std::string const &") -> "operations_research::RoutingDimension const &":
+        r""" Returns a dimension from its name. Dies if the dimension does not exist."""
+        return _pywrapcp.RoutingModel_GetDimensionOrDie(self, dimension_name)
+
+ +
+ +

Returns a dimension from its name. Dies if the dimension does not exist.

+
+ + +
+
+
#   + + + def + GetMutableDimension( + self, + dimension_name: 'std::string const &' +) -> 'operations_research::RoutingDimension *': +
+ +
+ View Source +
    def GetMutableDimension(self, dimension_name: "std::string const &") -> "operations_research::RoutingDimension *":
+        r"""
+        Returns a dimension from its name. Returns nullptr if the dimension does
+        not exist.
+        """
+        return _pywrapcp.RoutingModel_GetMutableDimension(self, dimension_name)
+
+ +
+ +

Returns a dimension from its name. Returns nullptr if the dimension does +not exist.

+
+ + +
+
+
#   + + + def + SetPrimaryConstrainedDimension(self, dimension_name: 'std::string const &') -> 'void': +
+ +
+ View Source +
    def SetPrimaryConstrainedDimension(self, dimension_name: "std::string const &") -> "void":
+        r"""
+        Set the given dimension as "primary constrained". As of August 2013, this
+        is only used by ArcIsMoreConstrainedThanArc().
+        "dimension" must be the name of an existing dimension, or be empty, in
+        which case there will not be a primary dimension after this call.
+        """
+        return _pywrapcp.RoutingModel_SetPrimaryConstrainedDimension(self, dimension_name)
+
+ +
+ +

Set the given dimension as "primary constrained". As of August 2013, this +is only used by ArcIsMoreConstrainedThanArc(). +"dimension" must be the name of an existing dimension, or be empty, in +which case there will not be a primary dimension after this call.

+
+ + +
+
+
#   + + + def + GetPrimaryConstrainedDimension(self) -> 'std::string const &': +
+ +
+ View Source +
    def GetPrimaryConstrainedDimension(self) -> "std::string const &":
+        r""" Get the primary constrained dimension, or an empty string if it is unset."""
+        return _pywrapcp.RoutingModel_GetPrimaryConstrainedDimension(self)
+
+ +
+ +

Get the primary constrained dimension, or an empty string if it is unset.

+
+ + +
+
+
#   + + + def + AddResourceGroup(self) -> int: +
+ +
+ View Source +
    def AddResourceGroup(self) -> "int":
+        r"""
+        Adds a resource group to the routing model. Returns its index in
+        resource_groups_.
+        """
+        return _pywrapcp.RoutingModel_AddResourceGroup(self)
+
+ +
+ +

Adds a resource group to the routing model. Returns its index in +resource_groups_.

+
+ + +
+
+
#   + + + def + GetDimensionResourceGroupIndices( + self, + dimension: ortools.constraint_solver.pywrapcp.RoutingDimension +) -> 'std::vector< int > const &': +
+ +
+ View Source +
    def GetDimensionResourceGroupIndices(self, dimension: "RoutingDimension") -> "std::vector< int > const &":
+        r"""
+        Returns the indices of resource groups for this dimension. This method can
+        only be called after the model has been closed.
+        """
+        return _pywrapcp.RoutingModel_GetDimensionResourceGroupIndices(self, dimension)
+
+ +
+ +

Returns the indices of resource groups for this dimension. This method can +only be called after the model has been closed.

+
+ + +
+
+
#   + + + def + GetDimensionResourceGroupIndex( + self, + dimension: ortools.constraint_solver.pywrapcp.RoutingDimension +) -> int: +
+ +
+ View Source +
    def GetDimensionResourceGroupIndex(self, dimension: "RoutingDimension") -> "int":
+        r"""
+        Returns the index of the resource group attached to the dimension.
+        DCHECKS that there's exactly one resource group for this dimension.
+        """
+        return _pywrapcp.RoutingModel_GetDimensionResourceGroupIndex(self, dimension)
+
+ +
+ +

Returns the index of the resource group attached to the dimension. +DCHECKS that there's exactly one resource group for this dimension.

+
+ + +
+
+
#   + + + def + AddDisjunction(self, *args) -> 'operations_research::RoutingModel::DisjunctionIndex': +
+ +
+ View Source +
    def AddDisjunction(self, *args) -> "operations_research::RoutingModel::DisjunctionIndex":
+        r"""
+        Adds a disjunction constraint on the indices: exactly 'max_cardinality' of
+        the indices are active. Start and end indices of any vehicle cannot be
+        part of a disjunction.
+
+        If a penalty is given, at most 'max_cardinality' of the indices can be
+        active, and if less are active, 'penalty' is payed per inactive index.
+        This is equivalent to adding the constraint:
+            p + Sum(i)active[i] == max_cardinality
+        where p is an integer variable, and the following cost to the cost
+        function:
+            p * penalty.
+        'penalty' must be positive to make the disjunction optional; a negative
+        penalty will force 'max_cardinality' indices of the disjunction to be
+        performed, and therefore p == 0.
+        Note: passing a vector with a single index will model an optional index
+        with a penalty cost if it is not visited.
+        """
+        return _pywrapcp.RoutingModel_AddDisjunction(self, *args)
+
+ +
+ +

Adds a disjunction constraint on the indices: exactly 'max_cardinality' of +the indices are active. Start and end indices of any vehicle cannot be +part of a disjunction.

+ +

If a penalty is given, at most 'max_cardinality' of the indices can be +active, and if less are active, 'penalty' is payed per inactive index.

+ +
This is equivalent to adding the constraint
+ +
+

p + Sum(i)active[i] == max_cardinality

+
+ +

where p is an integer variable, and the following cost to the cost +function: + p * penalty. +'penalty' must be positive to make the disjunction optional; a negative +penalty will force 'max_cardinality' indices of the disjunction to be +performed, and therefore p == 0. +Note: passing a vector with a single index will model an optional index +with a penalty cost if it is not visited.

+
+ + +
+
+
#   + + + def + GetDisjunctionIndices( + self, + index: 'int64_t' +) -> 'std::vector< operations_research::RoutingModel::DisjunctionIndex > const &': +
+ +
+ View Source +
    def GetDisjunctionIndices(self, index: "int64_t") -> "std::vector< operations_research::RoutingModel::DisjunctionIndex > const &":
+        r""" Returns the indices of the disjunctions to which an index belongs."""
+        return _pywrapcp.RoutingModel_GetDisjunctionIndices(self, index)
+
+ +
+ +

Returns the indices of the disjunctions to which an index belongs.

+
+ + +
+
+
#   + + + def + GetDisjunctionPenalty( + self, + index: 'operations_research::RoutingModel::DisjunctionIndex' +) -> 'int64_t': +
+ +
+ View Source +
    def GetDisjunctionPenalty(self, index: "operations_research::RoutingModel::DisjunctionIndex") -> "int64_t":
+        r""" Returns the penalty of the node disjunction of index 'index'."""
+        return _pywrapcp.RoutingModel_GetDisjunctionPenalty(self, index)
+
+ +
+ +

Returns the penalty of the node disjunction of index 'index'.

+
+ + +
+
+
#   + + + def + GetDisjunctionMaxCardinality( + self, + index: 'operations_research::RoutingModel::DisjunctionIndex' +) -> 'int64_t': +
+ +
+ View Source +
    def GetDisjunctionMaxCardinality(self, index: "operations_research::RoutingModel::DisjunctionIndex") -> "int64_t":
+        r"""
+        Returns the maximum number of possible active nodes of the node
+        disjunction of index 'index'.
+        """
+        return _pywrapcp.RoutingModel_GetDisjunctionMaxCardinality(self, index)
+
+ +
+ +

Returns the maximum number of possible active nodes of the node +disjunction of index 'index'.

+
+ + +
+
+
#   + + + def + GetNumberOfDisjunctions(self) -> int: +
+ +
+ View Source +
    def GetNumberOfDisjunctions(self) -> "int":
+        r""" Returns the number of node disjunctions in the model."""
+        return _pywrapcp.RoutingModel_GetNumberOfDisjunctions(self)
+
+ +
+ +

Returns the number of node disjunctions in the model.

+
+ + +
+
+
#   + + + def + HasMandatoryDisjunctions(self) -> bool: +
+ +
+ View Source +
    def HasMandatoryDisjunctions(self) -> "bool":
+        r"""
+        Returns true if the model contains mandatory disjunctions (ones with
+        kNoPenalty as penalty).
+        """
+        return _pywrapcp.RoutingModel_HasMandatoryDisjunctions(self)
+
+ +
+ +

Returns true if the model contains mandatory disjunctions (ones with +kNoPenalty as penalty).

+
+ + +
+
+
#   + + + def + HasMaxCardinalityConstrainedDisjunctions(self) -> bool: +
+ +
+ View Source +
    def HasMaxCardinalityConstrainedDisjunctions(self) -> "bool":
+        r"""
+        Returns true if the model contains at least one disjunction which is
+        constrained by its max_cardinality.
+        """
+        return _pywrapcp.RoutingModel_HasMaxCardinalityConstrainedDisjunctions(self)
+
+ +
+ +

Returns true if the model contains at least one disjunction which is +constrained by its max_cardinality.

+
+ + +
+
+
#   + + + def + GetPerfectBinaryDisjunctions(self) -> 'std::vector< std::pair< int64_t,int64_t > >': +
+ +
+ View Source +
    def GetPerfectBinaryDisjunctions(self) -> "std::vector< std::pair< int64_t,int64_t > >":
+        r"""
+        Returns the list of all perfect binary disjunctions, as pairs of variable
+        indices: a disjunction is "perfect" when its variables do not appear in
+        any other disjunction. Each pair is sorted (lowest variable index first),
+        and the output vector is also sorted (lowest pairs first).
+        """
+        return _pywrapcp.RoutingModel_GetPerfectBinaryDisjunctions(self)
+
+ +
+ +

Returns the list of all perfect binary disjunctions, as pairs of variable +indices: a disjunction is "perfect" when its variables do not appear in +any other disjunction. Each pair is sorted (lowest variable index first), +and the output vector is also sorted (lowest pairs first).

+
+ + +
+
+
#   + + + def + IgnoreDisjunctionsAlreadyForcedToZero(self) -> 'void': +
+ +
+ View Source +
    def IgnoreDisjunctionsAlreadyForcedToZero(self) -> "void":
+        r"""
+        SPECIAL: Makes the solver ignore all the disjunctions whose active
+        variables are all trivially zero (i.e. Max() == 0), by setting their
+        max_cardinality to 0.
+        This can be useful when using the BaseBinaryDisjunctionNeighborhood
+        operators, in the context of arc-based routing.
+        """
+        return _pywrapcp.RoutingModel_IgnoreDisjunctionsAlreadyForcedToZero(self)
+
+ +
+ +

SPECIAL: Makes the solver ignore all the disjunctions whose active +variables are all trivially zero (i.e. Max() == 0), by setting their +max_cardinality to 0. +This can be useful when using the BaseBinaryDisjunctionNeighborhood +operators, in the context of arc-based routing.

+
+ + +
+
+
#   + + + def + AddSoftSameVehicleConstraint( + self, + indices: 'std::vector< int64_t > const &', + cost: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def AddSoftSameVehicleConstraint(self, indices: "std::vector< int64_t > const &", cost: "int64_t") -> "void":
+        r"""
+        Adds a soft constraint to force a set of variable indices to be on the
+        same vehicle. If all nodes are not on the same vehicle, each extra vehicle
+        used adds 'cost' to the cost function.
+        """
+        return _pywrapcp.RoutingModel_AddSoftSameVehicleConstraint(self, indices, cost)
+
+ +
+ +

Adds a soft constraint to force a set of variable indices to be on the +same vehicle. If all nodes are not on the same vehicle, each extra vehicle +used adds 'cost' to the cost function.

+
+ + +
+
+
#   + + + def + SetAllowedVehiclesForIndex( + self, + vehicles: 'std::vector< int > const &', + index: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetAllowedVehiclesForIndex(self, vehicles: "std::vector< int > const &", index: "int64_t") -> "void":
+        r"""
+        Sets the vehicles which can visit a given node. If the node is in a
+        disjunction, this will not prevent it from being unperformed.
+        Specifying an empty vector of vehicles has no effect (all vehicles
+        will be allowed to visit the node).
+        """
+        return _pywrapcp.RoutingModel_SetAllowedVehiclesForIndex(self, vehicles, index)
+
+ +
+ +

Sets the vehicles which can visit a given node. If the node is in a +disjunction, this will not prevent it from being unperformed. +Specifying an empty vector of vehicles has no effect (all vehicles +will be allowed to visit the node).

+
+ + +
+
+
#   + + + def + IsVehicleAllowedForIndex(self, vehicle: int, index: 'int64_t') -> bool: +
+ +
+ View Source +
    def IsVehicleAllowedForIndex(self, vehicle: "int", index: "int64_t") -> "bool":
+        r""" Returns true if a vehicle is allowed to visit a given node."""
+        return _pywrapcp.RoutingModel_IsVehicleAllowedForIndex(self, vehicle, index)
+
+ +
+ +

Returns true if a vehicle is allowed to visit a given node.

+
+ + +
+
+
#   + + + def + AddPickupAndDelivery(self, pickup: 'int64_t', delivery: 'int64_t') -> 'void': +
+ +
+ View Source +
    def AddPickupAndDelivery(self, pickup: "int64_t", delivery: "int64_t") -> "void":
+        r"""
+        Notifies that index1 and index2 form a pair of nodes which should belong
+        to the same route. This methods helps the search find better solutions,
+        especially in the local search phase.
+        It should be called each time you have an equality constraint linking
+        the vehicle variables of two node (including for instance pickup and
+        delivery problems):
+            Solver* const solver = routing.solver();
+            int64_t index1 = manager.NodeToIndex(node1);
+            int64_t index2 = manager.NodeToIndex(node2);
+            solver->AddConstraint(solver->MakeEquality(
+                routing.VehicleVar(index1),
+                routing.VehicleVar(index2)));
+            routing.AddPickupAndDelivery(index1, index2);
+        """
+        return _pywrapcp.RoutingModel_AddPickupAndDelivery(self, pickup, delivery)
+
+ +
+ +

Notifies that index1 and index2 form a pair of nodes which should belong +to the same route. This methods helps the search find better solutions, +especially in the local search phase. +It should be called each time you have an equality constraint linking +the vehicle variables of two node (including for instance pickup and +delivery problems): + Solver* const solver = routing.solver(); + int64_t index1 = manager.NodeToIndex(node1); + int64_t index2 = manager.NodeToIndex(node2); + solver->AddConstraint(solver->MakeEquality( + routing.VehicleVar(index1), + routing.VehicleVar(index2))); + routing.AddPickupAndDelivery(index1, index2);

+
+ + +
+
+
#   + + + def + AddPickupAndDeliverySets( + self, + pickup_disjunction: 'operations_research::RoutingModel::DisjunctionIndex', + delivery_disjunction: 'operations_research::RoutingModel::DisjunctionIndex' +) -> 'void': +
+ +
+ View Source +
    def AddPickupAndDeliverySets(self, pickup_disjunction: "operations_research::RoutingModel::DisjunctionIndex", delivery_disjunction: "operations_research::RoutingModel::DisjunctionIndex") -> "void":
+        r"""
+        Same as AddPickupAndDelivery but notifying that the performed node from
+        the disjunction of index 'pickup_disjunction' is on the same route as the
+        performed node from the disjunction of index 'delivery_disjunction'.
+        """
+        return _pywrapcp.RoutingModel_AddPickupAndDeliverySets(self, pickup_disjunction, delivery_disjunction)
+
+ +
+ +

Same as AddPickupAndDelivery but notifying that the performed node from +the disjunction of index 'pickup_disjunction' is on the same route as the +performed node from the disjunction of index 'delivery_disjunction'.

+
+ + +
+
+
#   + + + def + GetPickupIndexPairs( + self, + node_index: 'int64_t' +) -> 'std::vector< std::pair< int,int > > const &': +
+ +
+ View Source +
    def GetPickupIndexPairs(self, node_index: "int64_t") -> "std::vector< std::pair< int,int > > const &":
+        r"""
+        Returns pairs for which the node is a pickup; the first element of each
+        pair is the index in the pickup and delivery pairs list in which the
+        pickup appears, the second element is its index in the pickups list.
+        """
+        return _pywrapcp.RoutingModel_GetPickupIndexPairs(self, node_index)
+
+ +
+ +

Returns pairs for which the node is a pickup; the first element of each +pair is the index in the pickup and delivery pairs list in which the +pickup appears, the second element is its index in the pickups list.

+
+ + +
+
+
#   + + + def + GetDeliveryIndexPairs( + self, + node_index: 'int64_t' +) -> 'std::vector< std::pair< int,int > > const &': +
+ +
+ View Source +
    def GetDeliveryIndexPairs(self, node_index: "int64_t") -> "std::vector< std::pair< int,int > > const &":
+        r""" Same as above for deliveries."""
+        return _pywrapcp.RoutingModel_GetDeliveryIndexPairs(self, node_index)
+
+ +
+ +

Same as above for deliveries.

+
+ + +
+
+
#   + + + def + SetPickupAndDeliveryPolicyOfAllVehicles( + self, + policy: 'operations_research::RoutingModel::PickupAndDeliveryPolicy' +) -> 'void': +
+ +
+ View Source +
    def SetPickupAndDeliveryPolicyOfAllVehicles(self, policy: "operations_research::RoutingModel::PickupAndDeliveryPolicy") -> "void":
+        r"""
+        Sets the Pickup and delivery policy of all vehicles. It is equivalent to
+        calling SetPickupAndDeliveryPolicyOfVehicle on all vehicles.
+        """
+        return _pywrapcp.RoutingModel_SetPickupAndDeliveryPolicyOfAllVehicles(self, policy)
+
+ +
+ +

Sets the Pickup and delivery policy of all vehicles. It is equivalent to +calling SetPickupAndDeliveryPolicyOfVehicle on all vehicles.

+
+ + +
+
+
#   + + + def + SetPickupAndDeliveryPolicyOfVehicle( + self, + policy: 'operations_research::RoutingModel::PickupAndDeliveryPolicy', + vehicle: int +) -> 'void': +
+ +
+ View Source +
    def SetPickupAndDeliveryPolicyOfVehicle(self, policy: "operations_research::RoutingModel::PickupAndDeliveryPolicy", vehicle: "int") -> "void":
+        return _pywrapcp.RoutingModel_SetPickupAndDeliveryPolicyOfVehicle(self, policy, vehicle)
+
+ +
+ + + +
+
+
#   + + + def + GetPickupAndDeliveryPolicyOfVehicle( + self, + vehicle: int +) -> 'operations_research::RoutingModel::PickupAndDeliveryPolicy': +
+ +
+ View Source +
    def GetPickupAndDeliveryPolicyOfVehicle(self, vehicle: "int") -> "operations_research::RoutingModel::PickupAndDeliveryPolicy":
+        return _pywrapcp.RoutingModel_GetPickupAndDeliveryPolicyOfVehicle(self, vehicle)
+
+ +
+ + + +
+
+
#   + + + def + GetNumOfSingletonNodes(self) -> int: +
+ +
+ View Source +
    def GetNumOfSingletonNodes(self) -> "int":
+        r"""
+        Returns the number of non-start/end nodes which do not appear in a
+        pickup/delivery pair.
+        """
+        return _pywrapcp.RoutingModel_GetNumOfSingletonNodes(self)
+
+ +
+ +

Returns the number of non-start/end nodes which do not appear in a +pickup/delivery pair.

+
+ + +
+
+
#   + + TYPE_ADDED_TO_VEHICLE = 0 +
+ + +

When visited, the number of types 'T' on the vehicle increases by one.

+
+ + +
+
+
#   + + ADDED_TYPE_REMOVED_FROM_VEHICLE = 1 +
+ + +

When visited, one instance of type 'T' previously added to the route +(TYPE_ADDED_TO_VEHICLE), if any, is removed from the vehicle. +If the type was not previously added to the route or all added instances +have already been removed, this visit has no effect on the types.

+
+ + +
+
+
#   + + TYPE_ON_VEHICLE_UP_TO_VISIT = 2 +
+ + +

With the following policy, the visit enforces that type 'T' is +considered on the route from its start until this node is visited.

+
+ + +
+
+
#   + + TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED = 3 +
+ + +

The visit doesn't have an impact on the number of types 'T' on the +route, as it's (virtually) added and removed directly. +This policy can be used for visits which are part of an incompatibility +or requirement set without affecting the type count on the route.

+
+ + +
+
+
#   + + + def + SetVisitType( + self, + index: 'int64_t', + type: int, + type_policy: 'operations_research::RoutingModel::VisitTypePolicy' +) -> 'void': +
+ +
+ View Source +
    def SetVisitType(self, index: "int64_t", type: "int", type_policy: "operations_research::RoutingModel::VisitTypePolicy") -> "void":
+        return _pywrapcp.RoutingModel_SetVisitType(self, index, type, type_policy)
+
+ +
+ + + +
+
+
#   + + + def + GetVisitType(self, index: 'int64_t') -> int: +
+ +
+ View Source +
    def GetVisitType(self, index: "int64_t") -> "int":
+        return _pywrapcp.RoutingModel_GetVisitType(self, index)
+
+ +
+ + + +
+
+
#   + + + def + GetSingleNodesOfType(self, type: int) -> 'std::vector< int > const &': +
+ +
+ View Source +
    def GetSingleNodesOfType(self, type: "int") -> "std::vector< int > const &":
+        return _pywrapcp.RoutingModel_GetSingleNodesOfType(self, type)
+
+ +
+ + + +
+
+
#   + + + def + GetPairIndicesOfType(self, type: int) -> 'std::vector< int > const &': +
+ +
+ View Source +
    def GetPairIndicesOfType(self, type: "int") -> "std::vector< int > const &":
+        return _pywrapcp.RoutingModel_GetPairIndicesOfType(self, type)
+
+ +
+ + + +
+
+
#   + + + def + GetVisitTypePolicy( + self, + index: 'int64_t' +) -> 'operations_research::RoutingModel::VisitTypePolicy': +
+ +
+ View Source +
    def GetVisitTypePolicy(self, index: "int64_t") -> "operations_research::RoutingModel::VisitTypePolicy":
+        return _pywrapcp.RoutingModel_GetVisitTypePolicy(self, index)
+
+ +
+ + + +
+
+
#   + + + def + CloseVisitTypes(self) -> 'void': +
+ +
+ View Source +
    def CloseVisitTypes(self) -> "void":
+        r"""
+        This function should be called once all node visit types have been set and
+        prior to adding any incompatibilities/requirements.
+        "close" types.
+        """
+        return _pywrapcp.RoutingModel_CloseVisitTypes(self)
+
+ +
+ +

This function should be called once all node visit types have been set and +prior to adding any incompatibilities/requirements. +"close" types.

+
+ + +
+
+
#   + + + def + GetNumberOfVisitTypes(self) -> int: +
+ +
+ View Source +
    def GetNumberOfVisitTypes(self) -> "int":
+        return _pywrapcp.RoutingModel_GetNumberOfVisitTypes(self)
+
+ +
+ + + +
+
+
#   + + + def + AddHardTypeIncompatibility(self, type1: int, type2: int) -> 'void': +
+ +
+ View Source +
    def AddHardTypeIncompatibility(self, type1: "int", type2: "int") -> "void":
+        r"""
+        Incompatibilities:
+        Two nodes with "hard" incompatible types cannot share the same route at
+        all, while with a "temporal" incompatibility they can't be on the same
+        route at the same time.
+        """
+        return _pywrapcp.RoutingModel_AddHardTypeIncompatibility(self, type1, type2)
+
+ +
+ +

Incompatibilities: +Two nodes with "hard" incompatible types cannot share the same route at +all, while with a "temporal" incompatibility they can't be on the same +route at the same time.

+
+ + +
+
+
#   + + + def + AddTemporalTypeIncompatibility(self, type1: int, type2: int) -> 'void': +
+ +
+ View Source +
    def AddTemporalTypeIncompatibility(self, type1: "int", type2: "int") -> "void":
+        return _pywrapcp.RoutingModel_AddTemporalTypeIncompatibility(self, type1, type2)
+
+ +
+ + + +
+
+
#   + + + def + GetHardTypeIncompatibilitiesOfType(self, type: int) -> 'absl::flat_hash_set< int > const &': +
+ +
+ View Source +
    def GetHardTypeIncompatibilitiesOfType(self, type: "int") -> "absl::flat_hash_set< int > const &":
+        r""" Returns visit types incompatible with a given type."""
+        return _pywrapcp.RoutingModel_GetHardTypeIncompatibilitiesOfType(self, type)
+
+ +
+ +

Returns visit types incompatible with a given type.

+
+ + +
+
+
#   + + + def + GetTemporalTypeIncompatibilitiesOfType(self, type: int) -> 'absl::flat_hash_set< int > const &': +
+ +
+ View Source +
    def GetTemporalTypeIncompatibilitiesOfType(self, type: "int") -> "absl::flat_hash_set< int > const &":
+        return _pywrapcp.RoutingModel_GetTemporalTypeIncompatibilitiesOfType(self, type)
+
+ +
+ + + +
+
+
#   + + + def + HasHardTypeIncompatibilities(self) -> bool: +
+ +
+ View Source +
    def HasHardTypeIncompatibilities(self) -> "bool":
+        r"""
+        Returns true iff any hard (resp. temporal) type incompatibilities have
+        been added to the model.
+        """
+        return _pywrapcp.RoutingModel_HasHardTypeIncompatibilities(self)
+
+ +
+ +

Returns true iff any hard (resp. temporal) type incompatibilities have +been added to the model.

+
+ + +
+
+
#   + + + def + HasTemporalTypeIncompatibilities(self) -> bool: +
+ +
+ View Source +
    def HasTemporalTypeIncompatibilities(self) -> "bool":
+        return _pywrapcp.RoutingModel_HasTemporalTypeIncompatibilities(self)
+
+ +
+ + + +
+
+
#   + + + def + AddSameVehicleRequiredTypeAlternatives( + self, + dependent_type: int, + required_type_alternatives: 'absl::flat_hash_set< int >' +) -> 'void': +
+ +
+ View Source +
    def AddSameVehicleRequiredTypeAlternatives(self, dependent_type: "int", required_type_alternatives: "absl::flat_hash_set< int >") -> "void":
+        r"""
+        Requirements:
+        NOTE: As of 2019-04, cycles in the requirement graph are not supported,
+        and lead to the dependent nodes being skipped if possible (otherwise
+        the model is considered infeasible).
+        The following functions specify that "dependent_type" requires at least
+        one of the types in "required_type_alternatives".
+
+        For same-vehicle requirements, a node of dependent type type_D requires at
+        least one node of type type_R among the required alternatives on the same
+        route.
+        """
+        return _pywrapcp.RoutingModel_AddSameVehicleRequiredTypeAlternatives(self, dependent_type, required_type_alternatives)
+
+ +
+ +

Requirements: +NOTE: As of 2019-04, cycles in the requirement graph are not supported, +and lead to the dependent nodes being skipped if possible (otherwise +the model is considered infeasible). +The following functions specify that "dependent_type" requires at least +one of the types in "required_type_alternatives".

+ +

For same-vehicle requirements, a node of dependent type type_D requires at +least one node of type type_R among the required alternatives on the same +route.

+
+ + +
+
+
#   + + + def + AddRequiredTypeAlternativesWhenAddingType( + self, + dependent_type: int, + required_type_alternatives: 'absl::flat_hash_set< int >' +) -> 'void': +
+ +
+ View Source +
    def AddRequiredTypeAlternativesWhenAddingType(self, dependent_type: "int", required_type_alternatives: "absl::flat_hash_set< int >") -> "void":
+        r"""
+        If type_D depends on type_R when adding type_D, any node_D of type_D and
+        VisitTypePolicy TYPE_ADDED_TO_VEHICLE or
+        TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED requires at least one type_R on its
+        vehicle at the time node_D is visited.
+        """
+        return _pywrapcp.RoutingModel_AddRequiredTypeAlternativesWhenAddingType(self, dependent_type, required_type_alternatives)
+
+ +
+ +

If type_D depends on type_R when adding type_D, any node_D of type_D and +VisitTypePolicy TYPE_ADDED_TO_VEHICLE or +TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED requires at least one type_R on its +vehicle at the time node_D is visited.

+
+ + +
+
+
#   + + + def + AddRequiredTypeAlternativesWhenRemovingType( + self, + dependent_type: int, + required_type_alternatives: 'absl::flat_hash_set< int >' +) -> 'void': +
+ +
+ View Source +
    def AddRequiredTypeAlternativesWhenRemovingType(self, dependent_type: "int", required_type_alternatives: "absl::flat_hash_set< int >") -> "void":
+        r"""
+        The following requirements apply when visiting dependent nodes that remove
+        their type from the route, i.e. type_R must be on the vehicle when type_D
+        of VisitTypePolicy ADDED_TYPE_REMOVED_FROM_VEHICLE,
+        TYPE_ON_VEHICLE_UP_TO_VISIT or TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED is
+        visited.
+        """
+        return _pywrapcp.RoutingModel_AddRequiredTypeAlternativesWhenRemovingType(self, dependent_type, required_type_alternatives)
+
+ +
+ +

The following requirements apply when visiting dependent nodes that remove +their type from the route, i.e. type_R must be on the vehicle when type_D +of VisitTypePolicy ADDED_TYPE_REMOVED_FROM_VEHICLE, +TYPE_ON_VEHICLE_UP_TO_VISIT or TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED is +visited.

+
+ + +
+
+
#   + + + def + GetSameVehicleRequiredTypeAlternativesOfType( + self, + type: int +) -> 'std::vector< absl::flat_hash_set< int > > const &': +
+ +
+ View Source +
    def GetSameVehicleRequiredTypeAlternativesOfType(self, type: "int") -> "std::vector< absl::flat_hash_set< int > > const &":
+        r"""
+        Returns the set of same-vehicle requirement alternatives for the given
+        type.
+        """
+        return _pywrapcp.RoutingModel_GetSameVehicleRequiredTypeAlternativesOfType(self, type)
+
+ +
+ +

Returns the set of same-vehicle requirement alternatives for the given +type.

+
+ + +
+
+
#   + + + def + GetRequiredTypeAlternativesWhenAddingType( + self, + type: int +) -> 'std::vector< absl::flat_hash_set< int > > const &': +
+ +
+ View Source +
    def GetRequiredTypeAlternativesWhenAddingType(self, type: "int") -> "std::vector< absl::flat_hash_set< int > > const &":
+        r""" Returns the set of requirement alternatives when adding the given type."""
+        return _pywrapcp.RoutingModel_GetRequiredTypeAlternativesWhenAddingType(self, type)
+
+ +
+ +

Returns the set of requirement alternatives when adding the given type.

+
+ + +
+
+
#   + + + def + GetRequiredTypeAlternativesWhenRemovingType( + self, + type: int +) -> 'std::vector< absl::flat_hash_set< int > > const &': +
+ +
+ View Source +
    def GetRequiredTypeAlternativesWhenRemovingType(self, type: "int") -> "std::vector< absl::flat_hash_set< int > > const &":
+        r""" Returns the set of requirement alternatives when removing the given type."""
+        return _pywrapcp.RoutingModel_GetRequiredTypeAlternativesWhenRemovingType(self, type)
+
+ +
+ +

Returns the set of requirement alternatives when removing the given type.

+
+ + +
+
+
#   + + + def + HasSameVehicleTypeRequirements(self) -> bool: +
+ +
+ View Source +
    def HasSameVehicleTypeRequirements(self) -> "bool":
+        r"""
+        Returns true iff any same-route (resp. temporal) type requirements have
+        been added to the model.
+        """
+        return _pywrapcp.RoutingModel_HasSameVehicleTypeRequirements(self)
+
+ +
+ +

Returns true iff any same-route (resp. temporal) type requirements have +been added to the model.

+
+ + +
+
+
#   + + + def + HasTemporalTypeRequirements(self) -> bool: +
+ +
+ View Source +
    def HasTemporalTypeRequirements(self) -> "bool":
+        return _pywrapcp.RoutingModel_HasTemporalTypeRequirements(self)
+
+ +
+ + + +
+
+
#   + + + def + HasTypeRegulations(self) -> bool: +
+ +
+ View Source +
    def HasTypeRegulations(self) -> "bool":
+        r"""
+        Returns true iff the model has any incompatibilities or requirements set
+        on node types.
+        """
+        return _pywrapcp.RoutingModel_HasTypeRegulations(self)
+
+ +
+ +

Returns true iff the model has any incompatibilities or requirements set +on node types.

+
+ + +
+
+
#   + + + def + UnperformedPenalty(self, var_index: 'int64_t') -> 'int64_t': +
+ +
+ View Source +
    def UnperformedPenalty(self, var_index: "int64_t") -> "int64_t":
+        r"""
+        Get the "unperformed" penalty of a node. This is only well defined if the
+        node is only part of a single Disjunction, and that disjunction has a
+        penalty. For forced active nodes returns max int64_t. In all other cases,
+        this returns 0.
+        """
+        return _pywrapcp.RoutingModel_UnperformedPenalty(self, var_index)
+
+ +
+ +

Get the "unperformed" penalty of a node. This is only well defined if the +node is only part of a single Disjunction, and that disjunction has a +penalty. For forced active nodes returns max int64_t. In all other cases, +this returns 0.

+
+ + +
+
+
#   + + + def + UnperformedPenaltyOrValue(self, default_value: 'int64_t', var_index: 'int64_t') -> 'int64_t': +
+ +
+ View Source +
    def UnperformedPenaltyOrValue(self, default_value: "int64_t", var_index: "int64_t") -> "int64_t":
+        r"""
+        Same as above except that it returns default_value instead of 0 when
+        penalty is not well defined (default value is passed as first argument to
+        simplify the usage of the method in a callback).
+        """
+        return _pywrapcp.RoutingModel_UnperformedPenaltyOrValue(self, default_value, var_index)
+
+ +
+ +

Same as above except that it returns default_value instead of 0 when +penalty is not well defined (default value is passed as first argument to +simplify the usage of the method in a callback).

+
+ + +
+
+
#   + + + def + GetDepot(self) -> 'int64_t': +
+ +
+ View Source +
    def GetDepot(self) -> "int64_t":
+        r"""
+        Returns the variable index of the first starting or ending node of all
+        routes. If all routes start  and end at the same node (single depot), this
+        is the node returned.
+        """
+        return _pywrapcp.RoutingModel_GetDepot(self)
+
+ +
+ +

Returns the variable index of the first starting or ending node of all +routes. If all routes start and end at the same node (single depot), this +is the node returned.

+
+ + +
+
+
#   + + + def + SetMaximumNumberOfActiveVehicles(self, max_active_vehicles: int) -> 'void': +
+ +
+ View Source +
    def SetMaximumNumberOfActiveVehicles(self, max_active_vehicles: "int") -> "void":
+        r"""
+        Constrains the maximum number of active vehicles, aka the number of
+        vehicles which do not have an empty route. For instance, this can be used
+        to limit the number of routes in the case where there are fewer drivers
+        than vehicles and that the fleet of vehicle is heterogeneous.
+        """
+        return _pywrapcp.RoutingModel_SetMaximumNumberOfActiveVehicles(self, max_active_vehicles)
+
+ +
+ +

Constrains the maximum number of active vehicles, aka the number of +vehicles which do not have an empty route. For instance, this can be used +to limit the number of routes in the case where there are fewer drivers +than vehicles and that the fleet of vehicle is heterogeneous.

+
+ + +
+
+
#   + + + def + GetMaximumNumberOfActiveVehicles(self) -> int: +
+ +
+ View Source +
    def GetMaximumNumberOfActiveVehicles(self) -> "int":
+        r""" Returns the maximum number of active vehicles."""
+        return _pywrapcp.RoutingModel_GetMaximumNumberOfActiveVehicles(self)
+
+ +
+ +

Returns the maximum number of active vehicles.

+
+ + +
+
+
#   + + + def + SetArcCostEvaluatorOfAllVehicles(self, evaluator_index: int) -> 'void': +
+ +
+ View Source +
    def SetArcCostEvaluatorOfAllVehicles(self, evaluator_index: "int") -> "void":
+        r"""
+        Sets the cost function of the model such that the cost of a segment of a
+        route between node 'from' and 'to' is evaluator(from, to), whatever the
+        route or vehicle performing the route.
+        """
+        return _pywrapcp.RoutingModel_SetArcCostEvaluatorOfAllVehicles(self, evaluator_index)
+
+ +
+ +

Sets the cost function of the model such that the cost of a segment of a +route between node 'from' and 'to' is evaluator(from, to), whatever the +route or vehicle performing the route.

+
+ + +
+
+
#   + + + def + SetArcCostEvaluatorOfVehicle(self, evaluator_index: int, vehicle: int) -> 'void': +
+ +
+ View Source +
    def SetArcCostEvaluatorOfVehicle(self, evaluator_index: "int", vehicle: "int") -> "void":
+        r""" Sets the cost function for a given vehicle route."""
+        return _pywrapcp.RoutingModel_SetArcCostEvaluatorOfVehicle(self, evaluator_index, vehicle)
+
+ +
+ +

Sets the cost function for a given vehicle route.

+
+ + +
+
+
#   + + + def + SetFixedCostOfAllVehicles(self, cost: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetFixedCostOfAllVehicles(self, cost: "int64_t") -> "void":
+        r"""
+        Sets the fixed cost of all vehicle routes. It is equivalent to calling
+        SetFixedCostOfVehicle on all vehicle routes.
+        """
+        return _pywrapcp.RoutingModel_SetFixedCostOfAllVehicles(self, cost)
+
+ +
+ +

Sets the fixed cost of all vehicle routes. It is equivalent to calling +SetFixedCostOfVehicle on all vehicle routes.

+
+ + +
+
+
#   + + + def + SetFixedCostOfVehicle(self, cost: 'int64_t', vehicle: int) -> 'void': +
+ +
+ View Source +
    def SetFixedCostOfVehicle(self, cost: "int64_t", vehicle: "int") -> "void":
+        r""" Sets the fixed cost of one vehicle route."""
+        return _pywrapcp.RoutingModel_SetFixedCostOfVehicle(self, cost, vehicle)
+
+ +
+ +

Sets the fixed cost of one vehicle route.

+
+ + +
+
+
#   + + + def + GetFixedCostOfVehicle(self, vehicle: int) -> 'int64_t': +
+ +
+ View Source +
    def GetFixedCostOfVehicle(self, vehicle: "int") -> "int64_t":
+        r"""
+        Returns the route fixed cost taken into account if the route of the
+        vehicle is not empty, aka there's at least one node on the route other
+        than the first and last nodes.
+        """
+        return _pywrapcp.RoutingModel_GetFixedCostOfVehicle(self, vehicle)
+
+ +
+ +

Returns the route fixed cost taken into account if the route of the +vehicle is not empty, aka there's at least one node on the route other +than the first and last nodes.

+
+ + +
+
+
#   + + + def + SetAmortizedCostFactorsOfAllVehicles( + self, + linear_cost_factor: 'int64_t', + quadratic_cost_factor: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetAmortizedCostFactorsOfAllVehicles(self, linear_cost_factor: "int64_t", quadratic_cost_factor: "int64_t") -> "void":
+        r"""
+        The following methods set the linear and quadratic cost factors of
+        vehicles (must be positive values). The default value of these parameters
+        is zero for all vehicles.
+
+        When set, the cost_ of the model will contain terms aiming at reducing the
+        number of vehicles used in the model, by adding the following to the
+        objective for every vehicle v:
+        INDICATOR(v used in the model) *
+          [linear_cost_factor_of_vehicle_[v]
+           - quadratic_cost_factor_of_vehicle_[v]*(square of length of route v)]
+        i.e. for every used vehicle, we add the linear factor as fixed cost, and
+        subtract the square of the route length multiplied by the quadratic
+        factor. This second term aims at making the routes as dense as possible.
+
+        Sets the linear and quadratic cost factor of all vehicles.
+        """
+        return _pywrapcp.RoutingModel_SetAmortizedCostFactorsOfAllVehicles(self, linear_cost_factor, quadratic_cost_factor)
+
+ +
+ +

The following methods set the linear and quadratic cost factors of +vehicles (must be positive values). The default value of these parameters +is zero for all vehicles.

+ +

When set, the cost_ of the model will contain terms aiming at reducing the +number of vehicles used in the model, by adding the following to the +objective for every vehicle v: +INDICATOR(v used in the model) * + [linear_cost_factor_of_vehicle_[v]

+ +
    +
  • quadratic_cost_factor_of_vehicle_[v]*(square of length of route v)] +i.e. for every used vehicle, we add the linear factor as fixed cost, and +subtract the square of the route length multiplied by the quadratic +factor. This second term aims at making the routes as dense as possible.
  • +
+ +

Sets the linear and quadratic cost factor of all vehicles.

+
+ + +
+
+
#   + + + def + SetAmortizedCostFactorsOfVehicle( + self, + linear_cost_factor: 'int64_t', + quadratic_cost_factor: 'int64_t', + vehicle: int +) -> 'void': +
+ +
+ View Source +
    def SetAmortizedCostFactorsOfVehicle(self, linear_cost_factor: "int64_t", quadratic_cost_factor: "int64_t", vehicle: "int") -> "void":
+        r""" Sets the linear and quadratic cost factor of the given vehicle."""
+        return _pywrapcp.RoutingModel_SetAmortizedCostFactorsOfVehicle(self, linear_cost_factor, quadratic_cost_factor, vehicle)
+
+ +
+ +

Sets the linear and quadratic cost factor of the given vehicle.

+
+ + +
+
+
#   + + + def + GetAmortizedLinearCostFactorOfVehicles(self) -> 'std::vector< int64_t > const &': +
+ +
+ View Source +
    def GetAmortizedLinearCostFactorOfVehicles(self) -> "std::vector< int64_t > const &":
+        return _pywrapcp.RoutingModel_GetAmortizedLinearCostFactorOfVehicles(self)
+
+ +
+ + + +
+
+
#   + + + def + GetAmortizedQuadraticCostFactorOfVehicles(self) -> 'std::vector< int64_t > const &': +
+ +
+ View Source +
    def GetAmortizedQuadraticCostFactorOfVehicles(self) -> "std::vector< int64_t > const &":
+        return _pywrapcp.RoutingModel_GetAmortizedQuadraticCostFactorOfVehicles(self)
+
+ +
+ + + +
+
+
#   + + + def + SetVehicleUsedWhenEmpty(self, is_used: bool, vehicle: int) -> 'void': +
+ +
+ View Source +
    def SetVehicleUsedWhenEmpty(self, is_used: "bool", vehicle: "int") -> "void":
+        return _pywrapcp.RoutingModel_SetVehicleUsedWhenEmpty(self, is_used, vehicle)
+
+ +
+ + + +
+
+
#   + + + def + IsVehicleUsedWhenEmpty(self, vehicle: int) -> bool: +
+ +
+ View Source +
    def IsVehicleUsedWhenEmpty(self, vehicle: "int") -> "bool":
+        return _pywrapcp.RoutingModel_IsVehicleUsedWhenEmpty(self, vehicle)
+
+ +
+ + + +
+
+
#   + + + def + SetFirstSolutionEvaluator( + self, + evaluator: 'operations_research::Solver::IndexEvaluator2' +) -> 'void': +
+ +
+ View Source +
    def SetFirstSolutionEvaluator(self, evaluator: "operations_research::Solver::IndexEvaluator2") -> "void":
+        r"""
+        Gets/sets the evaluator used during the search. Only relevant when
+        RoutingSearchParameters.first_solution_strategy = EVALUATOR_STRATEGY.
+        Takes ownership of evaluator.
+        """
+        return _pywrapcp.RoutingModel_SetFirstSolutionEvaluator(self, evaluator)
+
+ +
+ +

Gets/sets the evaluator used during the search. Only relevant when +RoutingSearchParameters.first_solution_strategy = EVALUATOR_STRATEGY. +Takes ownership of evaluator.

+
+ + +
+
+
#   + + + def + AddLocalSearchOperator( + self, + ls_operator: ortools.constraint_solver.pywrapcp.LocalSearchOperator +) -> 'void': +
+ +
+ View Source +
    def AddLocalSearchOperator(self, ls_operator: "LocalSearchOperator") -> "void":
+        r"""
+        Adds a local search operator to the set of operators used to solve the
+        vehicle routing problem.
+        """
+        return _pywrapcp.RoutingModel_AddLocalSearchOperator(self, ls_operator)
+
+ +
+ +

Adds a local search operator to the set of operators used to solve the +vehicle routing problem.

+
+ + +
+
+
#   + + + def + AddSearchMonitor( + self, + monitor: ortools.constraint_solver.pywrapcp.SearchMonitor +) -> 'void': +
+ +
+ View Source +
    def AddSearchMonitor(self, monitor: "SearchMonitor") -> "void":
+        r""" Adds a search monitor to the search used to solve the routing model."""
+        return _pywrapcp.RoutingModel_AddSearchMonitor(self, monitor)
+
+ +
+ +

Adds a search monitor to the search used to solve the routing model.

+
+ + +
+
+
#   + + + def + AddAtSolutionCallback(self, callback: 'std::function< void () >') -> 'void': +
+ +
+ View Source +
    def AddAtSolutionCallback(self, callback: "std::function< void () >") -> "void":
+        r"""
+        Adds a callback called each time a solution is found during the search.
+        This is a shortcut to creating a monitor to call the callback on
+        AtSolution() and adding it with AddSearchMonitor.
+        """
+        return _pywrapcp.RoutingModel_AddAtSolutionCallback(self, callback)
+
+ +
+ +

Adds a callback called each time a solution is found during the search. +This is a shortcut to creating a monitor to call the callback on +AtSolution() and adding it with AddSearchMonitor.

+
+ + +
+
+
#   + + + def + AddVariableMinimizedByFinalizer(self, var: ortools.constraint_solver.pywrapcp.IntVar) -> 'void': +
+ +
+ View Source +
    def AddVariableMinimizedByFinalizer(self, var: "IntVar") -> "void":
+        r"""
+        Adds a variable to minimize in the solution finalizer. The solution
+        finalizer is called each time a solution is found during the search and
+        allows to instantiate secondary variables (such as dimension cumul
+        variables).
+        """
+        return _pywrapcp.RoutingModel_AddVariableMinimizedByFinalizer(self, var)
+
+ +
+ +

Adds a variable to minimize in the solution finalizer. The solution +finalizer is called each time a solution is found during the search and +allows to instantiate secondary variables (such as dimension cumul +variables).

+
+ + +
+
+
#   + + + def + AddVariableMaximizedByFinalizer(self, var: ortools.constraint_solver.pywrapcp.IntVar) -> 'void': +
+ +
+ View Source +
    def AddVariableMaximizedByFinalizer(self, var: "IntVar") -> "void":
+        r"""
+        Adds a variable to maximize in the solution finalizer (see above for
+        information on the solution finalizer).
+        """
+        return _pywrapcp.RoutingModel_AddVariableMaximizedByFinalizer(self, var)
+
+ +
+ +

Adds a variable to maximize in the solution finalizer (see above for +information on the solution finalizer).

+
+ + +
+
+
#   + + + def + AddWeightedVariableMinimizedByFinalizer( + self, + var: ortools.constraint_solver.pywrapcp.IntVar, + cost: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def AddWeightedVariableMinimizedByFinalizer(self, var: "IntVar", cost: "int64_t") -> "void":
+        r"""
+        Adds a variable to minimize in the solution finalizer, with a weighted
+        priority: the higher the more priority it has.
+        """
+        return _pywrapcp.RoutingModel_AddWeightedVariableMinimizedByFinalizer(self, var, cost)
+
+ +
+ +

Adds a variable to minimize in the solution finalizer, with a weighted +priority: the higher the more priority it has.

+
+ + +
+
+
#   + + + def + AddWeightedVariableMaximizedByFinalizer( + self, + var: ortools.constraint_solver.pywrapcp.IntVar, + cost: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def AddWeightedVariableMaximizedByFinalizer(self, var: "IntVar", cost: "int64_t") -> "void":
+        r"""
+        Adds a variable to maximize in the solution finalizer, with a weighted
+        priority: the higher the more priority it has.
+        """
+        return _pywrapcp.RoutingModel_AddWeightedVariableMaximizedByFinalizer(self, var, cost)
+
+ +
+ +

Adds a variable to maximize in the solution finalizer, with a weighted +priority: the higher the more priority it has.

+
+ + +
+
+
#   + + + def + AddVariableTargetToFinalizer( + self, + var: ortools.constraint_solver.pywrapcp.IntVar, + target: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def AddVariableTargetToFinalizer(self, var: "IntVar", target: "int64_t") -> "void":
+        r"""
+        Add a variable to set the closest possible to the target value in the
+        solution finalizer.
+        """
+        return _pywrapcp.RoutingModel_AddVariableTargetToFinalizer(self, var, target)
+
+ +
+ +

Add a variable to set the closest possible to the target value in the +solution finalizer.

+
+ + +
+
+
#   + + + def + AddWeightedVariableTargetToFinalizer( + self, + var: ortools.constraint_solver.pywrapcp.IntVar, + target: 'int64_t', + cost: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def AddWeightedVariableTargetToFinalizer(self, var: "IntVar", target: "int64_t", cost: "int64_t") -> "void":
+        r"""
+        Same as above with a weighted priority: the higher the cost, the more
+        priority it has to be set close to the target value.
+        """
+        return _pywrapcp.RoutingModel_AddWeightedVariableTargetToFinalizer(self, var, target, cost)
+
+ +
+ +

Same as above with a weighted priority: the higher the cost, the more +priority it has to be set close to the target value.

+
+ + +
+
+
#   + + + def + CloseModel(self) -> 'void': +
+ +
+ View Source +
    def CloseModel(self) -> "void":
+        r"""
+        Closes the current routing model; after this method is called, no
+        modification to the model can be done, but RoutesToAssignment becomes
+        available. Note that CloseModel() is automatically called by Solve() and
+        other methods that produce solution.
+        This is equivalent to calling
+        CloseModelWithParameters(DefaultRoutingSearchParameters()).
+        """
+        return _pywrapcp.RoutingModel_CloseModel(self)
+
+ +
+ +

Closes the current routing model; after this method is called, no +modification to the model can be done, but RoutesToAssignment becomes +available. Note that CloseModel() is automatically called by Solve() and +other methods that produce solution. +This is equivalent to calling +CloseModelWithParameters(DefaultRoutingSearchParameters()).

+
+ + +
+
+
#   + + + def + CloseModelWithParameters( + self, + search_parameters: 'operations_research::RoutingSearchParameters const &' +) -> 'void': +
+ +
+ View Source +
    def CloseModelWithParameters(self, search_parameters: "operations_research::RoutingSearchParameters const &") -> "void":
+        r"""
+        Same as above taking search parameters (as of 10/2015 some the parameters
+        have to be set when closing the model).
+        """
+        return _pywrapcp.RoutingModel_CloseModelWithParameters(self, search_parameters)
+
+ +
+ +

Same as above taking search parameters (as of 10/2015 some the parameters +have to be set when closing the model).

+
+ + +
+
+
#   + + + def + Solve( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment = None +) -> 'operations_research::Assignment const *': +
+ +
+ View Source +
    def Solve(self, assignment: "Assignment"=None) -> "operations_research::Assignment const *":
+        r"""
+        Solves the current routing model; closes the current model.
+        This is equivalent to calling
+        SolveWithParameters(DefaultRoutingSearchParameters())
+        or
+        SolveFromAssignmentWithParameters(assignment,
+                                          DefaultRoutingSearchParameters()).
+        """
+        return _pywrapcp.RoutingModel_Solve(self, assignment)
+
+ +
+ +

Solves the current routing model; closes the current model. +This is equivalent to calling +SolveWithParameters(DefaultRoutingSearchParameters()) +or +SolveFromAssignmentWithParameters(assignment, + DefaultRoutingSearchParameters()).

+
+ + +
+
+
#   + + + def + SolveWithParameters( + self, + search_parameters: 'operations_research::RoutingSearchParameters const &', + solutions: 'std::vector< operations_research::Assignment const * > *' = None +) -> 'operations_research::Assignment const *': +
+ +
+ View Source +
    def SolveWithParameters(self, search_parameters: "operations_research::RoutingSearchParameters const &", solutions: "std::vector< operations_research::Assignment const * > *"=None) -> "operations_research::Assignment const *":
+        r"""
+        Solves the current routing model with the given parameters. If 'solutions'
+        is specified, it will contain the k best solutions found during the search
+        (from worst to best, including the one returned by this method), where k
+        corresponds to the 'number_of_solutions_to_collect' in
+        'search_parameters'. Note that the Assignment returned by the method and
+        the ones in solutions are owned by the underlying solver and should not be
+        deleted.
+        """
+        return _pywrapcp.RoutingModel_SolveWithParameters(self, search_parameters, solutions)
+
+ +
+ +

Solves the current routing model with the given parameters. If 'solutions' +is specified, it will contain the k best solutions found during the search +(from worst to best, including the one returned by this method), where k +corresponds to the 'number_of_solutions_to_collect' in +'search_parameters'. Note that the Assignment returned by the method and +the ones in solutions are owned by the underlying solver and should not be +deleted.

+
+ + +
+
+
#   + + + def + SolveFromAssignmentWithParameters( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment, + search_parameters: 'operations_research::RoutingSearchParameters const &', + solutions: 'std::vector< operations_research::Assignment const * > *' = None +) -> 'operations_research::Assignment const *': +
+ +
+ View Source +
    def SolveFromAssignmentWithParameters(self, assignment: "Assignment", search_parameters: "operations_research::RoutingSearchParameters const &", solutions: "std::vector< operations_research::Assignment const * > *"=None) -> "operations_research::Assignment const *":
+        r"""
+        Same as above, except that if assignment is not null, it will be used as
+        the initial solution.
+        """
+        return _pywrapcp.RoutingModel_SolveFromAssignmentWithParameters(self, assignment, search_parameters, solutions)
+
+ +
+ +

Same as above, except that if assignment is not null, it will be used as +the initial solution.

+
+ + +
+
+
#   + + + def + SolveFromAssignmentsWithParameters( + self, + assignments: 'std::vector< operations_research::Assignment const * > const &', + search_parameters: 'operations_research::RoutingSearchParameters const &', + solutions: 'std::vector< operations_research::Assignment const * > *' = None +) -> 'operations_research::Assignment const *': +
+ +
+ View Source +
    def SolveFromAssignmentsWithParameters(self, assignments: "std::vector< operations_research::Assignment const * > const &", search_parameters: "operations_research::RoutingSearchParameters const &", solutions: "std::vector< operations_research::Assignment const * > *"=None) -> "operations_research::Assignment const *":
+        r"""
+        Same as above but will try all assignments in order as first solutions
+        until one succeeds.
+        """
+        return _pywrapcp.RoutingModel_SolveFromAssignmentsWithParameters(self, assignments, search_parameters, solutions)
+
+ +
+ +

Same as above but will try all assignments in order as first solutions +until one succeeds.

+
+ + +
+
+
#   + + + def + SetAssignmentFromOtherModelAssignment( + self, + target_assignment: ortools.constraint_solver.pywrapcp.Assignment, + source_model: ortools.constraint_solver.pywrapcp.RoutingModel, + source_assignment: ortools.constraint_solver.pywrapcp.Assignment +) -> 'void': +
+ +
+ View Source +
    def SetAssignmentFromOtherModelAssignment(self, target_assignment: "Assignment", source_model: "RoutingModel", source_assignment: "Assignment") -> "void":
+        r"""
+        Given a "source_model" and its "source_assignment", resets
+        "target_assignment" with the IntVar variables (nexts_, and vehicle_vars_
+        if costs aren't homogeneous across vehicles) of "this" model, with the
+        values set according to those in "other_assignment".
+        The objective_element of target_assignment is set to this->cost_.
+        """
+        return _pywrapcp.RoutingModel_SetAssignmentFromOtherModelAssignment(self, target_assignment, source_model, source_assignment)
+
+ +
+ +

Given a "source_model" and its "source_assignment", resets +"target_assignment" with the IntVar variables (nexts_, and vehicle_vars_ +if costs aren't homogeneous across vehicles) of "this" model, with the +values set according to those in "other_assignment". +The objective_element of target_assignment is set to this->cost_.

+
+ + +
+
+
#   + + + def + ComputeLowerBound(self) -> 'int64_t': +
+ +
+ View Source +
    def ComputeLowerBound(self) -> "int64_t":
+        r"""
+        Computes a lower bound to the routing problem solving a linear assignment
+        problem. The routing model must be closed before calling this method.
+        Note that problems with node disjunction constraints (including optional
+        nodes) and non-homogenous costs are not supported (the method returns 0 in
+        these cases).
+        """
+        return _pywrapcp.RoutingModel_ComputeLowerBound(self)
+
+ +
+ +

Computes a lower bound to the routing problem solving a linear assignment +problem. The routing model must be closed before calling this method. +Note that problems with node disjunction constraints (including optional +nodes) and non-homogenous costs are not supported (the method returns 0 in +these cases).

+
+ + +
+
+
#   + + + def + status(self) -> 'operations_research::RoutingModel::Status': +
+ +
+ View Source +
    def status(self) -> "operations_research::RoutingModel::Status":
+        r""" Returns the current status of the routing model."""
+        return _pywrapcp.RoutingModel_status(self)
+
+ +
+ +

Returns the current status of the routing model.

+
+ + +
+
+
#   + + + def + ApplyLocks( + self, + locks: 'std::vector< int64_t > const &' +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def ApplyLocks(self, locks: "std::vector< int64_t > const &") -> "operations_research::IntVar *":
+        r"""
+        Applies a lock chain to the next search. 'locks' represents an ordered
+        vector of nodes representing a partial route which will be fixed during
+        the next search; it will constrain next variables such that:
+        next[locks[i]] == locks[i+1].
+
+        Returns the next variable at the end of the locked chain; this variable is
+        not locked. An assignment containing the locks can be obtained by calling
+        PreAssignment().
+        """
+        return _pywrapcp.RoutingModel_ApplyLocks(self, locks)
+
+ +
+ +

Applies a lock chain to the next search. 'locks' represents an ordered +vector of nodes representing a partial route which will be fixed during +the next search; it will constrain next variables such that: +next[locks[i]] == locks[i+1].

+ +

Returns the next variable at the end of the locked chain; this variable is +not locked. An assignment containing the locks can be obtained by calling +PreAssignment().

+
+ + +
+
+
#   + + + def + ApplyLocksToAllVehicles( + self, + locks: 'std::vector< std::vector< int64_t > > const &', + close_routes: bool +) -> bool: +
+ +
+ View Source +
    def ApplyLocksToAllVehicles(self, locks: "std::vector< std::vector< int64_t > > const &", close_routes: "bool") -> "bool":
+        r"""
+        Applies lock chains to all vehicles to the next search, such that locks[p]
+        is the lock chain for route p. Returns false if the locks do not contain
+        valid routes; expects that the routes do not contain the depots,
+        i.e. there are empty vectors in place of empty routes.
+        If close_routes is set to true, adds the end nodes to the route of each
+        vehicle and deactivates other nodes.
+        An assignment containing the locks can be obtained by calling
+        PreAssignment().
+        """
+        return _pywrapcp.RoutingModel_ApplyLocksToAllVehicles(self, locks, close_routes)
+
+ +
+ +

Applies lock chains to all vehicles to the next search, such that locks[p] +is the lock chain for route p. Returns false if the locks do not contain +valid routes; expects that the routes do not contain the depots, +i.e. there are empty vectors in place of empty routes. +If close_routes is set to true, adds the end nodes to the route of each +vehicle and deactivates other nodes. +An assignment containing the locks can be obtained by calling +PreAssignment().

+
+ + +
+
+
#   + + + def + PreAssignment(self) -> 'operations_research::Assignment const *const': +
+ +
+ View Source +
    def PreAssignment(self) -> "operations_research::Assignment const *const":
+        r"""
+        Returns an assignment used to fix some of the variables of the problem.
+        In practice, this assignment locks partial routes of the problem. This
+        can be used in the context of locking the parts of the routes which have
+        already been driven in online routing problems.
+        """
+        return _pywrapcp.RoutingModel_PreAssignment(self)
+
+ +
+ +

Returns an assignment used to fix some of the variables of the problem. +In practice, this assignment locks partial routes of the problem. This +can be used in the context of locking the parts of the routes which have +already been driven in online routing problems.

+
+ + +
+
+
#   + + + def + MutablePreAssignment(self) -> 'operations_research::Assignment *': +
+ +
+ View Source +
    def MutablePreAssignment(self) -> "operations_research::Assignment *":
+        return _pywrapcp.RoutingModel_MutablePreAssignment(self)
+
+ +
+ + + +
+
+
#   + + + def + WriteAssignment(self, file_name: 'std::string const &') -> bool: +
+ +
+ View Source +
    def WriteAssignment(self, file_name: "std::string const &") -> "bool":
+        r"""
+        Writes the current solution to a file containing an AssignmentProto.
+        Returns false if the file cannot be opened or if there is no current
+        solution.
+        """
+        return _pywrapcp.RoutingModel_WriteAssignment(self, file_name)
+
+ +
+ +

Writes the current solution to a file containing an AssignmentProto. +Returns false if the file cannot be opened or if there is no current +solution.

+
+ + +
+
+
#   + + + def + ReadAssignment( + self, + file_name: 'std::string const &' +) -> 'operations_research::Assignment *': +
+ +
+ View Source +
    def ReadAssignment(self, file_name: "std::string const &") -> "operations_research::Assignment *":
+        r"""
+        Reads an assignment from a file and returns the current solution.
+        Returns nullptr if the file cannot be opened or if the assignment is not
+        valid.
+        """
+        return _pywrapcp.RoutingModel_ReadAssignment(self, file_name)
+
+ +
+ +

Reads an assignment from a file and returns the current solution. +Returns nullptr if the file cannot be opened or if the assignment is not +valid.

+
+ + +
+
+
#   + + + def + RestoreAssignment( + self, + solution: ortools.constraint_solver.pywrapcp.Assignment +) -> 'operations_research::Assignment *': +
+ +
+ View Source +
    def RestoreAssignment(self, solution: "Assignment") -> "operations_research::Assignment *":
+        r"""
+        Restores an assignment as a solution in the routing model and returns the
+        new solution. Returns nullptr if the assignment is not valid.
+        """
+        return _pywrapcp.RoutingModel_RestoreAssignment(self, solution)
+
+ +
+ +

Restores an assignment as a solution in the routing model and returns the +new solution. Returns nullptr if the assignment is not valid.

+
+ + +
+
+
#   + + + def + ReadAssignmentFromRoutes( + self, + routes: 'std::vector< std::vector< int64_t > > const &', + ignore_inactive_indices: bool +) -> 'operations_research::Assignment *': +
+ +
+ View Source +
    def ReadAssignmentFromRoutes(self, routes: "std::vector< std::vector< int64_t > > const &", ignore_inactive_indices: "bool") -> "operations_research::Assignment *":
+        r"""
+        Restores the routes as the current solution. Returns nullptr if the
+        solution cannot be restored (routes do not contain a valid solution). Note
+        that calling this method will run the solver to assign values to the
+        dimension variables; this may take considerable amount of time, especially
+        when using dimensions with slack.
+        """
+        return _pywrapcp.RoutingModel_ReadAssignmentFromRoutes(self, routes, ignore_inactive_indices)
+
+ +
+ +

Restores the routes as the current solution. Returns nullptr if the +solution cannot be restored (routes do not contain a valid solution). Note +that calling this method will run the solver to assign values to the +dimension variables; this may take considerable amount of time, especially +when using dimensions with slack.

+
+ + +
+
+
#   + + + def + RoutesToAssignment( + self, + routes: 'std::vector< std::vector< int64_t > > const &', + ignore_inactive_indices: bool, + close_routes: bool, + assignment: ortools.constraint_solver.pywrapcp.Assignment +) -> bool: +
+ +
+ View Source +
    def RoutesToAssignment(self, routes: "std::vector< std::vector< int64_t > > const &", ignore_inactive_indices: "bool", close_routes: "bool", assignment: "Assignment") -> "bool":
+        r"""
+        Fills an assignment from a specification of the routes of the
+        vehicles. The routes are specified as lists of variable indices that
+        appear on the routes of the vehicles. The indices of the outer vector in
+        'routes' correspond to vehicles IDs, the inner vector contains the
+        variable indices on the routes for the given vehicle. The inner vectors
+        must not contain the start and end indices, as these are determined by the
+        routing model.  Sets the value of NextVars in the assignment, adding the
+        variables to the assignment if necessary. The method does not touch other
+        variables in the assignment. The method can only be called after the model
+        is closed.  With ignore_inactive_indices set to false, this method will
+        fail (return nullptr) in case some of the route contain indices that are
+        deactivated in the model; when set to true, these indices will be
+        skipped.  Returns true if routes were successfully
+        loaded. However, such assignment still might not be a valid
+        solution to the routing problem due to more complex constraints;
+        it is advisible to call solver()->CheckSolution() afterwards.
+        """
+        return _pywrapcp.RoutingModel_RoutesToAssignment(self, routes, ignore_inactive_indices, close_routes, assignment)
+
+ +
+ +

Fills an assignment from a specification of the routes of the +vehicles. The routes are specified as lists of variable indices that +appear on the routes of the vehicles. The indices of the outer vector in +'routes' correspond to vehicles IDs, the inner vector contains the +variable indices on the routes for the given vehicle. The inner vectors +must not contain the start and end indices, as these are determined by the +routing model. Sets the value of NextVars in the assignment, adding the +variables to the assignment if necessary. The method does not touch other +variables in the assignment. The method can only be called after the model +is closed. With ignore_inactive_indices set to false, this method will +fail (return nullptr) in case some of the route contain indices that are +deactivated in the model; when set to true, these indices will be +skipped. Returns true if routes were successfully +loaded. However, such assignment still might not be a valid +solution to the routing problem due to more complex constraints; +it is advisible to call solver()->CheckSolution() afterwards.

+
+ + +
+
+
#   + + + def + AssignmentToRoutes( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment, + routes: 'std::vector< std::vector< int64_t > > *const' +) -> 'void': +
+ +
+ View Source +
    def AssignmentToRoutes(self, assignment: "Assignment", routes: "std::vector< std::vector< int64_t > > *const") -> "void":
+        r"""
+        Converts the solution in the given assignment to routes for all vehicles.
+        Expects that assignment contains a valid solution (i.e. routes for all
+        vehicles end with an end index for that vehicle).
+        """
+        return _pywrapcp.RoutingModel_AssignmentToRoutes(self, assignment, routes)
+
+ +
+ +

Converts the solution in the given assignment to routes for all vehicles. +Expects that assignment contains a valid solution (i.e. routes for all +vehicles end with an end index for that vehicle).

+
+ + +
+
+
#   + + + def + CompactAssignment( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment +) -> 'operations_research::Assignment *': +
+ +
+ View Source +
    def CompactAssignment(self, assignment: "Assignment") -> "operations_research::Assignment *":
+        r"""
+        Converts the solution in the given assignment to routes for all vehicles.
+        If the returned vector is route_indices, route_indices[i][j] is the index
+        for jth location visited on route i. Note that contrary to
+        AssignmentToRoutes, the vectors do include start and end locations.
+        Returns a compacted version of the given assignment, in which all vehicles
+        with id lower or equal to some N have non-empty routes, and all vehicles
+        with id greater than N have empty routes. Does not take ownership of the
+        returned object.
+        If found, the cost of the compact assignment is the same as in the
+        original assignment and it preserves the values of 'active' variables.
+        Returns nullptr if a compact assignment was not found.
+        This method only works in homogenous mode, and it only swaps equivalent
+        vehicles (vehicles with the same start and end nodes). When creating the
+        compact assignment, the empty plan is replaced by the route assigned to
+        the compatible vehicle with the highest id. Note that with more complex
+        constraints on vehicle variables, this method might fail even if a compact
+        solution exists.
+        This method changes the vehicle and dimension variables as necessary.
+        While compacting the solution, only basic checks on vehicle variables are
+        performed; if one of these checks fails no attempts to repair it are made
+        (instead, the method returns nullptr).
+        """
+        return _pywrapcp.RoutingModel_CompactAssignment(self, assignment)
+
+ +
+ +

Converts the solution in the given assignment to routes for all vehicles. +If the returned vector is route_indices, route_indices[i][j] is the index +for jth location visited on route i. Note that contrary to +AssignmentToRoutes, the vectors do include start and end locations. +Returns a compacted version of the given assignment, in which all vehicles +with id lower or equal to some N have non-empty routes, and all vehicles +with id greater than N have empty routes. Does not take ownership of the +returned object. +If found, the cost of the compact assignment is the same as in the +original assignment and it preserves the values of 'active' variables. +Returns nullptr if a compact assignment was not found. +This method only works in homogenous mode, and it only swaps equivalent +vehicles (vehicles with the same start and end nodes). When creating the +compact assignment, the empty plan is replaced by the route assigned to +the compatible vehicle with the highest id. Note that with more complex +constraints on vehicle variables, this method might fail even if a compact +solution exists. +This method changes the vehicle and dimension variables as necessary. +While compacting the solution, only basic checks on vehicle variables are +performed; if one of these checks fails no attempts to repair it are made +(instead, the method returns nullptr).

+
+ + +
+
+
#   + + + def + CompactAndCheckAssignment( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment +) -> 'operations_research::Assignment *': +
+ +
+ View Source +
    def CompactAndCheckAssignment(self, assignment: "Assignment") -> "operations_research::Assignment *":
+        r"""
+        Same as CompactAssignment() but also checks the validity of the final
+        compact solution; if it is not valid, no attempts to repair it are made
+        (instead, the method returns nullptr).
+        """
+        return _pywrapcp.RoutingModel_CompactAndCheckAssignment(self, assignment)
+
+ +
+ +

Same as CompactAssignment() but also checks the validity of the final +compact solution; if it is not valid, no attempts to repair it are made +(instead, the method returns nullptr).

+
+ + +
+
+
#   + + + def + AddToAssignment(self, var: ortools.constraint_solver.pywrapcp.IntVar) -> 'void': +
+ +
+ View Source +
    def AddToAssignment(self, var: "IntVar") -> "void":
+        r""" Adds an extra variable to the vehicle routing assignment."""
+        return _pywrapcp.RoutingModel_AddToAssignment(self, var)
+
+ +
+ +

Adds an extra variable to the vehicle routing assignment.

+
+ + +
+
+
#   + + + def + AddIntervalToAssignment( + self, + interval: ortools.constraint_solver.pywrapcp.IntervalVar +) -> 'void': +
+ +
+ View Source +
    def AddIntervalToAssignment(self, interval: "IntervalVar") -> "void":
+        return _pywrapcp.RoutingModel_AddIntervalToAssignment(self, interval)
+
+ +
+ + + +
+
+
#   + + + def + PackCumulsOfOptimizerDimensionsFromAssignment( + self, + original_assignment: ortools.constraint_solver.pywrapcp.Assignment, + duration_limit: 'absl::Duration' +) -> 'operations_research::Assignment const *': +
+ +
+ View Source +
    def PackCumulsOfOptimizerDimensionsFromAssignment(self, original_assignment: "Assignment", duration_limit: "absl::Duration") -> "operations_research::Assignment const *":
+        r"""
+        For every dimension in the model with an optimizer in
+        local/global_dimension_optimizers_, this method tries to pack the cumul
+        values of the dimension, such that:
+        - The cumul costs (span costs, soft lower and upper bound costs, etc) are
+          minimized.
+        - The cumuls of the ends of the routes are minimized for this given
+          minimal cumul cost.
+        - Given these minimal end cumuls, the route start cumuls are maximized.
+        Returns the assignment resulting from allocating these packed cumuls with
+        the solver, and nullptr if these cumuls could not be set by the solver.
+        """
+        return _pywrapcp.RoutingModel_PackCumulsOfOptimizerDimensionsFromAssignment(self, original_assignment, duration_limit)
+
+ +
+ +

For every dimension in the model with an optimizer in +local/global_dimension_optimizers_, this method tries to pack the cumul +values of the dimension, such that:

+ +
    +
  • The cumul costs (span costs, soft lower and upper bound costs, etc) are +minimized.
  • +
  • The cumuls of the ends of the routes are minimized for this given +minimal cumul cost.
  • +
  • Given these minimal end cumuls, the route start cumuls are maximized. +Returns the assignment resulting from allocating these packed cumuls with +the solver, and nullptr if these cumuls could not be set by the solver.
  • +
+
+ + +
+
+
#   + + + def + AddLocalSearchFilter( + self, + filter: ortools.constraint_solver.pywrapcp.LocalSearchFilter +) -> 'void': +
+ +
+ View Source +
    def AddLocalSearchFilter(self, filter: "LocalSearchFilter") -> "void":
+        r"""
+        Adds a custom local search filter to the list of filters used to speed up
+        local search by pruning unfeasible variable assignments.
+        Calling this method after the routing model has been closed (CloseModel()
+        or Solve() has been called) has no effect.
+        The routing model does not take ownership of the filter.
+        """
+        return _pywrapcp.RoutingModel_AddLocalSearchFilter(self, filter)
+
+ +
+ +

Adds a custom local search filter to the list of filters used to speed up +local search by pruning unfeasible variable assignments. +Calling this method after the routing model has been closed (CloseModel() +or Solve() has been called) has no effect. +The routing model does not take ownership of the filter.

+
+ + +
+
+
#   + + + def + Start(self, vehicle: int) -> 'int64_t': +
+ +
+ View Source +
    def Start(self, vehicle: "int") -> "int64_t":
+        r"""
+        Model inspection.
+        Returns the variable index of the starting node of a vehicle route.
+        """
+        return _pywrapcp.RoutingModel_Start(self, vehicle)
+
+ +
+ +

Model inspection. +Returns the variable index of the starting node of a vehicle route.

+
+ + +
+
+
#   + + + def + End(self, vehicle: int) -> 'int64_t': +
+ +
+ View Source +
    def End(self, vehicle: "int") -> "int64_t":
+        r""" Returns the variable index of the ending node of a vehicle route."""
+        return _pywrapcp.RoutingModel_End(self, vehicle)
+
+ +
+ +

Returns the variable index of the ending node of a vehicle route.

+
+ + +
+
+
#   + + + def + IsStart(self, index: 'int64_t') -> bool: +
+ +
+ View Source +
    def IsStart(self, index: "int64_t") -> "bool":
+        r""" Returns true if 'index' represents the first node of a route."""
+        return _pywrapcp.RoutingModel_IsStart(self, index)
+
+ +
+ +

Returns true if 'index' represents the first node of a route.

+
+ + +
+
+
#   + + + def + IsEnd(self, index: 'int64_t') -> bool: +
+ +
+ View Source +
    def IsEnd(self, index: "int64_t") -> "bool":
+        r""" Returns true if 'index' represents the last node of a route."""
+        return _pywrapcp.RoutingModel_IsEnd(self, index)
+
+ +
+ +

Returns true if 'index' represents the last node of a route.

+
+ + +
+
+
#   + + + def + VehicleIndex(self, index: 'int64_t') -> int: +
+ +
+ View Source +
    def VehicleIndex(self, index: "int64_t") -> "int":
+        r"""
+        Returns the vehicle of the given start/end index, and -1 if the given
+        index is not a vehicle start/end.
+        """
+        return _pywrapcp.RoutingModel_VehicleIndex(self, index)
+
+ +
+ +

Returns the vehicle of the given start/end index, and -1 if the given +index is not a vehicle start/end.

+
+ + +
+
+
#   + + + def + Next( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment, + index: 'int64_t' +) -> 'int64_t': +
+ +
+ View Source +
    def Next(self, assignment: "Assignment", index: "int64_t") -> "int64_t":
+        r"""
+        Assignment inspection
+        Returns the variable index of the node directly after the node
+        corresponding to 'index' in 'assignment'.
+        """
+        return _pywrapcp.RoutingModel_Next(self, assignment, index)
+
+ +
+ +

Assignment inspection +Returns the variable index of the node directly after the node +corresponding to 'index' in 'assignment'.

+
+ + +
+
+
#   + + + def + IsVehicleUsed( + self, + assignment: ortools.constraint_solver.pywrapcp.Assignment, + vehicle: int +) -> bool: +
+ +
+ View Source +
    def IsVehicleUsed(self, assignment: "Assignment", vehicle: "int") -> "bool":
+        r""" Returns true if the route of 'vehicle' is non empty in 'assignment'."""
+        return _pywrapcp.RoutingModel_IsVehicleUsed(self, assignment, vehicle)
+
+ +
+ +

Returns true if the route of 'vehicle' is non empty in 'assignment'.

+
+ + +
+
+
#   + + + def + NextVar(self, index: 'int64_t') -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def NextVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        r"""
+        Returns the next variable of the node corresponding to index. Note that
+        NextVar(index) == index is equivalent to ActiveVar(index) == 0.
+        """
+        return _pywrapcp.RoutingModel_NextVar(self, index)
+
+ +
+ +

Returns the next variable of the node corresponding to index. Note that +NextVar(index) == index is equivalent to ActiveVar(index) == 0.

+
+ + +
+
+
#   + + + def + ActiveVar(self, index: 'int64_t') -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def ActiveVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        r""" Returns the active variable of the node corresponding to index."""
+        return _pywrapcp.RoutingModel_ActiveVar(self, index)
+
+ +
+ +

Returns the active variable of the node corresponding to index.

+
+ + +
+
+
#   + + + def + ActiveVehicleVar(self, vehicle: int) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def ActiveVehicleVar(self, vehicle: "int") -> "operations_research::IntVar *":
+        r"""
+        Returns the active variable of the vehicle. It will be equal to 1 iff the
+        route of the vehicle is not empty, 0 otherwise.
+        """
+        return _pywrapcp.RoutingModel_ActiveVehicleVar(self, vehicle)
+
+ +
+ +

Returns the active variable of the vehicle. It will be equal to 1 iff the +route of the vehicle is not empty, 0 otherwise.

+
+ + +
+
+
#   + + + def + VehicleRouteConsideredVar(self, vehicle: int) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def VehicleRouteConsideredVar(self, vehicle: "int") -> "operations_research::IntVar *":
+        r"""
+        Returns the variable specifying whether or not the given vehicle route is
+        considered for costs and constraints. It will be equal to 1 iff the route
+        of the vehicle is not empty OR vehicle_used_when_empty_[vehicle] is true.
+        """
+        return _pywrapcp.RoutingModel_VehicleRouteConsideredVar(self, vehicle)
+
+ +
+ +

Returns the variable specifying whether or not the given vehicle route is +considered for costs and constraints. It will be equal to 1 iff the route +of the vehicle is not empty OR vehicle_used_when_empty_[vehicle] is true.

+
+ + +
+
+
#   + + + def + VehicleVar(self, index: 'int64_t') -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def VehicleVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        r"""
+        Returns the vehicle variable of the node corresponding to index. Note that
+        VehicleVar(index) == -1 is equivalent to ActiveVar(index) == 0.
+        """
+        return _pywrapcp.RoutingModel_VehicleVar(self, index)
+
+ +
+ +

Returns the vehicle variable of the node corresponding to index. Note that +VehicleVar(index) == -1 is equivalent to ActiveVar(index) == 0.

+
+ + +
+
+
#   + + + def + ResourceVar( + self, + vehicle: int, + resource_group: int +) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def ResourceVar(self, vehicle: "int", resource_group: "int") -> "operations_research::IntVar *":
+        r"""
+        Returns the resource variable for the given vehicle index in the given
+        resource group. If a vehicle doesn't require a resource from the
+        corresponding resource group, then ResourceVar(v, r_g) == -1.
+        """
+        return _pywrapcp.RoutingModel_ResourceVar(self, vehicle, resource_group)
+
+ +
+ +

Returns the resource variable for the given vehicle index in the given +resource group. If a vehicle doesn't require a resource from the +corresponding resource group, then ResourceVar(v, r_g) == -1.

+
+ + +
+
+
#   + + + def + CostVar(self) -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def CostVar(self) -> "operations_research::IntVar *":
+        r""" Returns the global cost variable which is being minimized."""
+        return _pywrapcp.RoutingModel_CostVar(self)
+
+ +
+ +

Returns the global cost variable which is being minimized.

+
+ + +
+
+
#   + + + def + GetArcCostForVehicle( + self, + from_index: 'int64_t', + to_index: 'int64_t', + vehicle: 'int64_t' +) -> 'int64_t': +
+ +
+ View Source +
    def GetArcCostForVehicle(self, from_index: "int64_t", to_index: "int64_t", vehicle: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost of the transit arc between two nodes for a given vehicle.
+        Input are variable indices of node. This returns 0 if vehicle < 0.
+        """
+        return _pywrapcp.RoutingModel_GetArcCostForVehicle(self, from_index, to_index, vehicle)
+
+ +
+ +

Returns the cost of the transit arc between two nodes for a given vehicle. +Input are variable indices of node. This returns 0 if vehicle < 0.

+
+ + +
+
+
#   + + + def + CostsAreHomogeneousAcrossVehicles(self) -> bool: +
+ +
+ View Source +
    def CostsAreHomogeneousAcrossVehicles(self) -> "bool":
+        r""" Whether costs are homogeneous across all vehicles."""
+        return _pywrapcp.RoutingModel_CostsAreHomogeneousAcrossVehicles(self)
+
+ +
+ +

Whether costs are homogeneous across all vehicles.

+
+ + +
+
+
#   + + + def + GetHomogeneousCost(self, from_index: 'int64_t', to_index: 'int64_t') -> 'int64_t': +
+ +
+ View Source +
    def GetHomogeneousCost(self, from_index: "int64_t", to_index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost of the segment between two nodes supposing all vehicle
+        costs are the same (returns the cost for the first vehicle otherwise).
+        """
+        return _pywrapcp.RoutingModel_GetHomogeneousCost(self, from_index, to_index)
+
+ +
+ +

Returns the cost of the segment between two nodes supposing all vehicle +costs are the same (returns the cost for the first vehicle otherwise).

+
+ + +
+
+
#   + + + def + GetArcCostForFirstSolution(self, from_index: 'int64_t', to_index: 'int64_t') -> 'int64_t': +
+ +
+ View Source +
    def GetArcCostForFirstSolution(self, from_index: "int64_t", to_index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost of the arc in the context of the first solution strategy.
+        This is typically a simplification of the actual cost; see the .cc.
+        """
+        return _pywrapcp.RoutingModel_GetArcCostForFirstSolution(self, from_index, to_index)
+
+ +
+ +

Returns the cost of the arc in the context of the first solution strategy. +This is typically a simplification of the actual cost; see the .cc.

+
+ + +
+
+
#   + + + def + GetArcCostForClass( + self, + from_index: 'int64_t', + to_index: 'int64_t', + cost_class_index: 'int64_t' +) -> 'int64_t': +
+ +
+ View Source +
    def GetArcCostForClass(self, from_index: "int64_t", to_index: "int64_t", cost_class_index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost of the segment between two nodes for a given cost
+        class. Input are variable indices of nodes and the cost class.
+        Unlike GetArcCostForVehicle(), if cost_class is kNoCost, then the
+        returned cost won't necessarily be zero: only some of the components
+        of the cost that depend on the cost class will be omited. See the code
+        for details.
+        """
+        return _pywrapcp.RoutingModel_GetArcCostForClass(self, from_index, to_index, cost_class_index)
+
+ +
+ +

Returns the cost of the segment between two nodes for a given cost +class. Input are variable indices of nodes and the cost class. +Unlike GetArcCostForVehicle(), if cost_class is kNoCost, then the +returned cost won't necessarily be zero: only some of the components +of the cost that depend on the cost class will be omited. See the code +for details.

+
+ + +
+
+
#   + + + def + GetCostClassIndexOfVehicle( + self, + vehicle: 'int64_t' +) -> 'operations_research::RoutingModel::CostClassIndex': +
+ +
+ View Source +
    def GetCostClassIndexOfVehicle(self, vehicle: "int64_t") -> "operations_research::RoutingModel::CostClassIndex":
+        r""" Get the cost class index of the given vehicle."""
+        return _pywrapcp.RoutingModel_GetCostClassIndexOfVehicle(self, vehicle)
+
+ +
+ +

Get the cost class index of the given vehicle.

+
+ + +
+
+
#   + + + def + HasVehicleWithCostClassIndex( + self, + cost_class_index: 'operations_research::RoutingModel::CostClassIndex' +) -> bool: +
+ +
+ View Source +
    def HasVehicleWithCostClassIndex(self, cost_class_index: "operations_research::RoutingModel::CostClassIndex") -> "bool":
+        r"""
+        Returns true iff the model contains a vehicle with the given
+        cost_class_index.
+        """
+        return _pywrapcp.RoutingModel_HasVehicleWithCostClassIndex(self, cost_class_index)
+
+ +
+ +

Returns true iff the model contains a vehicle with the given +cost_class_index.

+
+ + +
+
+
#   + + + def + GetCostClassesCount(self) -> int: +
+ +
+ View Source +
    def GetCostClassesCount(self) -> "int":
+        r""" Returns the number of different cost classes in the model."""
+        return _pywrapcp.RoutingModel_GetCostClassesCount(self)
+
+ +
+ +

Returns the number of different cost classes in the model.

+
+ + +
+
+
#   + + + def + GetNonZeroCostClassesCount(self) -> int: +
+ +
+ View Source +
    def GetNonZeroCostClassesCount(self) -> "int":
+        r""" Ditto, minus the 'always zero', built-in cost class."""
+        return _pywrapcp.RoutingModel_GetNonZeroCostClassesCount(self)
+
+ +
+ +

Ditto, minus the 'always zero', built-in cost class.

+
+ + +
+
+
#   + + + def + GetVehicleClassIndexOfVehicle( + self, + vehicle: 'int64_t' +) -> 'operations_research::RoutingModel::VehicleClassIndex': +
+ +
+ View Source +
    def GetVehicleClassIndexOfVehicle(self, vehicle: "int64_t") -> "operations_research::RoutingModel::VehicleClassIndex":
+        return _pywrapcp.RoutingModel_GetVehicleClassIndexOfVehicle(self, vehicle)
+
+ +
+ + + +
+
+
#   + + + def + GetVehicleOfClass( + self, + vehicle_class: 'operations_research::RoutingModel::VehicleClassIndex' +) -> int: +
+ +
+ View Source +
    def GetVehicleOfClass(self, vehicle_class: "operations_research::RoutingModel::VehicleClassIndex") -> "int":
+        r"""
+        Returns a vehicle of the given vehicle class, and -1 if there are no
+        vehicles for this class.
+        """
+        return _pywrapcp.RoutingModel_GetVehicleOfClass(self, vehicle_class)
+
+ +
+ +

Returns a vehicle of the given vehicle class, and -1 if there are no +vehicles for this class.

+
+ + +
+
+
#   + + + def + GetVehicleClassesCount(self) -> int: +
+ +
+ View Source +
    def GetVehicleClassesCount(self) -> "int":
+        r""" Returns the number of different vehicle classes in the model."""
+        return _pywrapcp.RoutingModel_GetVehicleClassesCount(self)
+
+ +
+ +

Returns the number of different vehicle classes in the model.

+
+ + +
+
+
#   + + + def + GetSameVehicleIndicesOfIndex(self, node: int) -> 'std::vector< int > const &': +
+ +
+ View Source +
    def GetSameVehicleIndicesOfIndex(self, node: "int") -> "std::vector< int > const &":
+        r""" Returns variable indices of nodes constrained to be on the same route."""
+        return _pywrapcp.RoutingModel_GetSameVehicleIndicesOfIndex(self, node)
+
+ +
+ +

Returns variable indices of nodes constrained to be on the same route.

+
+ + +
+
+
#   + + + def + GetVehicleTypeContainer( + self +) -> 'operations_research::RoutingModel::VehicleTypeContainer const &': +
+ +
+ View Source +
    def GetVehicleTypeContainer(self) -> "operations_research::RoutingModel::VehicleTypeContainer const &":
+        return _pywrapcp.RoutingModel_GetVehicleTypeContainer(self)
+
+ +
+ + + +
+
+
#   + + + def + ArcIsMoreConstrainedThanArc(self, _from: 'int64_t', to1: 'int64_t', to2: 'int64_t') -> bool: +
+ +
+ View Source +
    def ArcIsMoreConstrainedThanArc(self, _from: "int64_t", to1: "int64_t", to2: "int64_t") -> "bool":
+        r"""
+        Returns whether the arc from->to1 is more constrained than from->to2,
+        taking into account, in order:
+        - whether the destination node isn't an end node
+        - whether the destination node is mandatory
+        - whether the destination node is bound to the same vehicle as the source
+        - the "primary constrained" dimension (see SetPrimaryConstrainedDimension)
+        It then breaks ties using, in order:
+        - the arc cost (taking unperformed penalties into account)
+        - the size of the vehicle vars of "to1" and "to2" (lowest size wins)
+        - the value: the lowest value of the indices to1 and to2 wins.
+        See the .cc for details.
+        The more constrained arc is typically preferable when building a
+        first solution. This method is intended to be used as a callback for the
+        BestValueByComparisonSelector value selector.
+        Args:
+          from: the variable index of the source node
+          to1: the variable index of the first candidate destination node.
+          to2: the variable index of the second candidate destination node.
+        """
+        return _pywrapcp.RoutingModel_ArcIsMoreConstrainedThanArc(self, _from, to1, to2)
+
+ +
+ +

Returns whether the arc from->to1 is more constrained than from->to2, +taking into account, in order:

+ +
    +
  • whether the destination node isn't an end node
  • +
  • whether the destination node is mandatory
  • +
  • whether the destination node is bound to the same vehicle as the source
  • +
  • the "primary constrained" dimension (see SetPrimaryConstrainedDimension) +It then breaks ties using, in order:
  • +
  • the arc cost (taking unperformed penalties into account)
  • +
  • the size of the vehicle vars of "to1" and "to2" (lowest size wins)
  • +
  • the value: the lowest value of the indices to1 and to2 wins. +See the .cc for details. +The more constrained arc is typically preferable when building a +first solution. This method is intended to be used as a callback for the +BestValueByComparisonSelector value selector.
  • +
+ +
Args
+ +
    +
  • from: the variable index of the source node
  • +
  • to1: the variable index of the first candidate destination node.
  • +
  • to2: the variable index of the second candidate destination node.
  • +
+
+ + +
+
+
#   + + + def + DebugOutputAssignment( + self, + solution_assignment: ortools.constraint_solver.pywrapcp.Assignment, + dimension_to_print: 'std::string const &' +) -> 'std::string': +
+ +
+ View Source +
    def DebugOutputAssignment(self, solution_assignment: "Assignment", dimension_to_print: "std::string const &") -> "std::string":
+        r"""
+        Print some debugging information about an assignment, including the
+        feasible intervals of the CumulVar for dimension "dimension_to_print"
+        at each step of the routes.
+        If "dimension_to_print" is omitted, all dimensions will be printed.
+        """
+        return _pywrapcp.RoutingModel_DebugOutputAssignment(self, solution_assignment, dimension_to_print)
+
+ +
+ +

Print some debugging information about an assignment, including the +feasible intervals of the CumulVar for dimension "dimension_to_print" +at each step of the routes. +If "dimension_to_print" is omitted, all dimensions will be printed.

+
+ + +
+
+
#   + + + def + solver(self) -> 'operations_research::Solver *': +
+ +
+ View Source +
    def solver(self) -> "operations_research::Solver *":
+        r"""
+        Returns a vector cumul_bounds, for which cumul_bounds[i][j] is a pair
+        containing the minimum and maximum of the CumulVar of the jth node on
+        route i.
+        - cumul_bounds[i][j].first is the minimum.
+        - cumul_bounds[i][j].second is the maximum.
+        Returns the underlying constraint solver. Can be used to add extra
+        constraints and/or modify search algorithms.
+        """
+        return _pywrapcp.RoutingModel_solver(self)
+
+ +
+ +

Returns a vector cumul_bounds, for which cumul_bounds[i][j] is a pair +containing the minimum and maximum of the CumulVar of the jth node on +route i.

+ +
    +
  • cumul_bounds[i][j].first is the minimum.
  • +
  • cumul_bounds[i][j].second is the maximum. +Returns the underlying constraint solver. Can be used to add extra +constraints and/or modify search algorithms.
  • +
+
+ + +
+
+
#   + + + def + CheckLimit(self) -> bool: +
+ +
+ View Source +
    def CheckLimit(self) -> "bool":
+        r""" Returns true if the search limit has been crossed."""
+        return _pywrapcp.RoutingModel_CheckLimit(self)
+
+ +
+ +

Returns true if the search limit has been crossed.

+
+ + +
+
+
#   + + + def + RemainingTime(self) -> 'absl::Duration': +
+ +
+ View Source +
    def RemainingTime(self) -> "absl::Duration":
+        r""" Returns the time left in the search limit."""
+        return _pywrapcp.RoutingModel_RemainingTime(self)
+
+ +
+ +

Returns the time left in the search limit.

+
+ + +
+
+
#   + + + def + nodes(self) -> int: +
+ +
+ View Source +
    def nodes(self) -> "int":
+        r"""
+        Sizes and indices
+        Returns the number of nodes in the model.
+        """
+        return _pywrapcp.RoutingModel_nodes(self)
+
+ +
+ +

Sizes and indices +Returns the number of nodes in the model.

+
+ + +
+
+
#   + + + def + vehicles(self) -> int: +
+ +
+ View Source +
    def vehicles(self) -> "int":
+        r""" Returns the number of vehicle routes in the model."""
+        return _pywrapcp.RoutingModel_vehicles(self)
+
+ +
+ +

Returns the number of vehicle routes in the model.

+
+ + +
+
+
#   + + + def + Size(self) -> 'int64_t': +
+ +
+ View Source +
    def Size(self) -> "int64_t":
+        r""" Returns the number of next variables in the model."""
+        return _pywrapcp.RoutingModel_Size(self)
+
+ +
+ +

Returns the number of next variables in the model.

+
+ + +
+
+
#   + + + def + GetNumberOfDecisionsInFirstSolution( + self, + search_parameters: 'operations_research::RoutingSearchParameters const &' +) -> 'int64_t': +
+ +
+ View Source +
    def GetNumberOfDecisionsInFirstSolution(self, search_parameters: "operations_research::RoutingSearchParameters const &") -> "int64_t":
+        r"""
+        Returns statistics on first solution search, number of decisions sent to
+        filters, number of decisions rejected by filters.
+        """
+        return _pywrapcp.RoutingModel_GetNumberOfDecisionsInFirstSolution(self, search_parameters)
+
+ +
+ +

Returns statistics on first solution search, number of decisions sent to +filters, number of decisions rejected by filters.

+
+ + +
+
+
#   + + + def + GetNumberOfRejectsInFirstSolution( + self, + search_parameters: 'operations_research::RoutingSearchParameters const &' +) -> 'int64_t': +
+ +
+ View Source +
    def GetNumberOfRejectsInFirstSolution(self, search_parameters: "operations_research::RoutingSearchParameters const &") -> "int64_t":
+        return _pywrapcp.RoutingModel_GetNumberOfRejectsInFirstSolution(self, search_parameters)
+
+ +
+ + + +
+
+
#   + + + def + GetAutomaticFirstSolutionStrategy(self) -> 'operations_research::FirstSolutionStrategy::Value': +
+ +
+ View Source +
    def GetAutomaticFirstSolutionStrategy(self) -> "operations_research::FirstSolutionStrategy::Value":
+        r""" Returns the automatic first solution strategy selected."""
+        return _pywrapcp.RoutingModel_GetAutomaticFirstSolutionStrategy(self)
+
+ +
+ +

Returns the automatic first solution strategy selected.

+
+ + +
+
+
#   + + + def + IsMatchingModel(self) -> bool: +
+ +
+ View Source +
    def IsMatchingModel(self) -> "bool":
+        r""" Returns true if a vehicle/node matching problem is detected."""
+        return _pywrapcp.RoutingModel_IsMatchingModel(self)
+
+ +
+ +

Returns true if a vehicle/node matching problem is detected.

+
+ + +
+
+
#   + + + def + MakeGuidedSlackFinalizer( + self, + dimension: ortools.constraint_solver.pywrapcp.RoutingDimension, + initializer: 'std::function< int64_t (int64_t) >' +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def MakeGuidedSlackFinalizer(self, dimension: "RoutingDimension", initializer: "std::function< int64_t (int64_t) >") -> "operations_research::DecisionBuilder *":
+        r"""
+        The next few members are in the public section only for testing purposes.
+
+        MakeGuidedSlackFinalizer creates a DecisionBuilder for the slacks of a
+        dimension using a callback to choose which values to start with.
+        The finalizer works only when all next variables in the model have
+        been fixed. It has the following two characteristics:
+        1. It follows the routes defined by the nexts variables when choosing a
+           variable to make a decision on.
+        2. When it comes to choose a value for the slack of node i, the decision
+           builder first calls the callback with argument i, and supposingly the
+           returned value is x it creates decisions slack[i] = x, slack[i] = x +
+           1, slack[i] = x - 1, slack[i] = x + 2, etc.
+        """
+        return _pywrapcp.RoutingModel_MakeGuidedSlackFinalizer(self, dimension, initializer)
+
+ +
+ +

The next few members are in the public section only for testing purposes.

+ +

MakeGuidedSlackFinalizer creates a DecisionBuilder for the slacks of a +dimension using a callback to choose which values to start with. +The finalizer works only when all next variables in the model have +been fixed. It has the following two characteristics:

+ +
    +
  1. It follows the routes defined by the nexts variables when choosing a +variable to make a decision on.
  2. +
  3. When it comes to choose a value for the slack of node i, the decision +builder first calls the callback with argument i, and supposingly the +returned value is x it creates decisions slack[i] = x, slack[i] = x + +1, slack[i] = x - 1, slack[i] = x + 2, etc.
  4. +
+
+ + +
+
+
#   + + + def + MakeSelfDependentDimensionFinalizer( + self, + dimension: ortools.constraint_solver.pywrapcp.RoutingDimension +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
    def MakeSelfDependentDimensionFinalizer(self, dimension: "RoutingDimension") -> "operations_research::DecisionBuilder *":
+        r"""
+        MakeSelfDependentDimensionFinalizer is a finalizer for the slacks of a
+        self-dependent dimension. It makes an extensive use of the caches of the
+        state dependent transits.
+        In detail, MakeSelfDependentDimensionFinalizer returns a composition of a
+        local search decision builder with a greedy descent operator for the cumul
+        of the start of each route and a guided slack finalizer. Provided there
+        are no time windows and the maximum slacks are large enough, once the
+        cumul of the start of route is fixed, the guided finalizer can find
+        optimal values of the slacks for the rest of the route in time
+        proportional to the length of the route. Therefore the composed finalizer
+        generally works in time O(log(t)*n*m), where t is the latest possible
+        departute time, n is the number of nodes in the network and m is the
+        number of vehicles.
+        """
+        return _pywrapcp.RoutingModel_MakeSelfDependentDimensionFinalizer(self, dimension)
+
+ +
+ +

MakeSelfDependentDimensionFinalizer is a finalizer for the slacks of a +self-dependent dimension. It makes an extensive use of the caches of the +state dependent transits. +In detail, MakeSelfDependentDimensionFinalizer returns a composition of a +local search decision builder with a greedy descent operator for the cumul +of the start of each route and a guided slack finalizer. Provided there +are no time windows and the maximum slacks are large enough, once the +cumul of the start of route is fixed, the guided finalizer can find +optimal values of the slacks for the rest of the route in time +proportional to the length of the route. Therefore the composed finalizer +generally works in time O(log(t)nm), where t is the latest possible +departute time, n is the number of nodes in the network and m is the +number of vehicles.

+
+ + +
+
+
#   + + kNoPenalty = -1 +
+ + + + +
+
+
#   + + kNoDisjunction = <Swig Object of type 'operations_research::RoutingModel::DisjunctionIndex *'> +
+ + + + +
+
+
#   + + kNoDimension = <Swig Object of type 'operations_research::RoutingModel::DimensionIndex *'> +
+ + + + +
+
+
+
+ #   + + + class + RoutingModelVisitor(BaseObject): +
+ +
+ View Source +
class RoutingModelVisitor(BaseObject):
+    r""" Routing model visitor."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self):
+        _pywrapcp.RoutingModelVisitor_swiginit(self, _pywrapcp.new_RoutingModelVisitor())
+    __swig_destroy__ = _pywrapcp.delete_RoutingModelVisitor
+
+ +
+ +

Routing model visitor.

+
+ + +
+
#   + + + RoutingModelVisitor() +
+ +
+ View Source +
    def __init__(self):
+        _pywrapcp.RoutingModelVisitor_swiginit(self, _pywrapcp.new_RoutingModelVisitor())
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + kLightElement = 'LightElement' +
+ + + + +
+
+
#   + + kLightElement2 = 'LightElement2' +
+ + + + +
+
+
#   + + kRemoveValues = 'RemoveValues' +
+ + + + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + GlobalVehicleBreaksConstraint(Constraint): +
+ +
+ View Source +
class GlobalVehicleBreaksConstraint(Constraint):
+    r"""
+    GlobalVehicleBreaksConstraint ensures breaks constraints are enforced on
+    all vehicles in the dimension passed to its constructor.
+    It is intended to be used for dimensions representing time.
+    A break constraint ensures break intervals fit on the route of a vehicle.
+    For a given vehicle, it forces break intervals to be disjoint from visit
+    intervals, where visit intervals start at CumulVar(node) and last for
+    node_visit_transit[node]. Moreover, it ensures that there is enough time
+    between two consecutive nodes of a route to do transit and vehicle breaks,
+    i.e. if Next(nodeA) = nodeB, CumulVar(nodeA) = tA and CumulVar(nodeB) = tB,
+    then SlackVar(nodeA) >= sum_{breaks [tA, tB)} duration(break).
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, dimension: "RoutingDimension"):
+        _pywrapcp.GlobalVehicleBreaksConstraint_swiginit(self, _pywrapcp.new_GlobalVehicleBreaksConstraint(dimension))
+
+    def DebugString(self) -> "std::string":
+        return _pywrapcp.GlobalVehicleBreaksConstraint_DebugString(self)
+
+    def Post(self) -> "void":
+        return _pywrapcp.GlobalVehicleBreaksConstraint_Post(self)
+
+    def InitialPropagateWrapper(self) -> "void":
+        return _pywrapcp.GlobalVehicleBreaksConstraint_InitialPropagateWrapper(self)
+    __swig_destroy__ = _pywrapcp.delete_GlobalVehicleBreaksConstraint
+
+ +
+ +

GlobalVehicleBreaksConstraint ensures breaks constraints are enforced on +all vehicles in the dimension passed to its constructor. +It is intended to be used for dimensions representing time. +A break constraint ensures break intervals fit on the route of a vehicle. +For a given vehicle, it forces break intervals to be disjoint from visit +intervals, where visit intervals start at CumulVar(node) and last for +node_visit_transit[node]. Moreover, it ensures that there is enough time +between two consecutive nodes of a route to do transit and vehicle breaks, +i.e. if Next(nodeA) = nodeB, CumulVar(nodeA) = tA and CumulVar(nodeB) = tB, +then SlackVar(nodeA) >= sum_{breaks [tA, tB)} duration(break).

+
+ + +
+
#   + + + GlobalVehicleBreaksConstraint(dimension: ortools.constraint_solver.pywrapcp.RoutingDimension) +
+ +
+ View Source +
    def __init__(self, dimension: "RoutingDimension"):
+        _pywrapcp.GlobalVehicleBreaksConstraint_swiginit(self, _pywrapcp.new_GlobalVehicleBreaksConstraint(dimension))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + DebugString(self) -> 'std::string': +
+ +
+ View Source +
    def DebugString(self) -> "std::string":
+        return _pywrapcp.GlobalVehicleBreaksConstraint_DebugString(self)
+
+ +
+ + + +
+
+
#   + + + def + Post(self) -> 'void': +
+ +
+ View Source +
    def Post(self) -> "void":
+        return _pywrapcp.GlobalVehicleBreaksConstraint_Post(self)
+
+ +
+ +

This method is called when the constraint is processed by the +solver. Its main usage is to attach demons to variables.

+
+ + +
+
+
#   + + + def + InitialPropagateWrapper(self) -> 'void': +
+ +
+ View Source +
    def InitialPropagateWrapper(self) -> "void":
+        return _pywrapcp.GlobalVehicleBreaksConstraint_InitialPropagateWrapper(self)
+
+ +
+ +

This method performs the initial propagation of the +constraint. It is called just after the post.

+
+ + +
+
+
Inherited Members
+
+ + +
+
+
+
+
+ #   + + + class + TypeRegulationsChecker: +
+ +
+ View Source +
class TypeRegulationsChecker(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+    __repr__ = _swig_repr
+    __swig_destroy__ = _pywrapcp.delete_TypeRegulationsChecker
+
+    def CheckVehicle(self, vehicle: "int", next_accessor: "std::function< int64_t (int64_t) > const &") -> "bool":
+        return _pywrapcp.TypeRegulationsChecker_CheckVehicle(self, vehicle, next_accessor)
+
+ +
+ + + +
+
#   + + + TypeRegulationsChecker(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined - class is abstract")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + CheckVehicle( + self, + vehicle: int, + next_accessor: 'std::function< int64_t (int64_t) > const &' +) -> bool: +
+ +
+ View Source +
    def CheckVehicle(self, vehicle: "int", next_accessor: "std::function< int64_t (int64_t) > const &") -> "bool":
+        return _pywrapcp.TypeRegulationsChecker_CheckVehicle(self, vehicle, next_accessor)
+
+ +
+ + + +
+
+
+
+ #   + + + class + TypeIncompatibilityChecker(TypeRegulationsChecker): +
+ +
+ View Source +
class TypeIncompatibilityChecker(TypeRegulationsChecker):
+    r""" Checker for type incompatibilities."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, model: "RoutingModel", check_hard_incompatibilities: "bool"):
+        _pywrapcp.TypeIncompatibilityChecker_swiginit(self, _pywrapcp.new_TypeIncompatibilityChecker(model, check_hard_incompatibilities))
+    __swig_destroy__ = _pywrapcp.delete_TypeIncompatibilityChecker
+
+ +
+ +

Checker for type incompatibilities.

+
+ + +
+
#   + + + TypeIncompatibilityChecker( + model: ortools.constraint_solver.pywrapcp.RoutingModel, + check_hard_incompatibilities: bool +) +
+ +
+ View Source +
    def __init__(self, model: "RoutingModel", check_hard_incompatibilities: "bool"):
+        _pywrapcp.TypeIncompatibilityChecker_swiginit(self, _pywrapcp.new_TypeIncompatibilityChecker(model, check_hard_incompatibilities))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + TypeRequirementChecker(TypeRegulationsChecker): +
+ +
+ View Source +
class TypeRequirementChecker(TypeRegulationsChecker):
+    r""" Checker for type requirements."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, model: "RoutingModel"):
+        _pywrapcp.TypeRequirementChecker_swiginit(self, _pywrapcp.new_TypeRequirementChecker(model))
+    __swig_destroy__ = _pywrapcp.delete_TypeRequirementChecker
+
+ +
+ +

Checker for type requirements.

+
+ + +
+
#   + + + TypeRequirementChecker(model: ortools.constraint_solver.pywrapcp.RoutingModel) +
+ +
+ View Source +
    def __init__(self, model: "RoutingModel"):
+        _pywrapcp.TypeRequirementChecker_swiginit(self, _pywrapcp.new_TypeRequirementChecker(model))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
Inherited Members
+
+ +
+
+
+
+
+ #   + + + class + TypeRegulationsConstraint(Constraint): +
+ +
+ View Source +
class TypeRegulationsConstraint(Constraint):
+    r"""
+    The following constraint ensures that incompatibilities and requirements
+    between types are respected.
+
+    It verifies both "hard" and "temporal" incompatibilities.
+    Two nodes with hard incompatible types cannot be served by the same vehicle
+    at all, while with a temporal incompatibility they can't be on the same
+    route at the same time.
+    The VisitTypePolicy of a node determines how visiting it impacts the type
+    count on the route.
+
+    For example, for
+    - three temporally incompatible types T1 T2 and T3
+    - 2 pairs of nodes a1/r1 and a2/r2 of type T1 and T2 respectively, with
+        - a1 and a2 of VisitTypePolicy TYPE_ADDED_TO_VEHICLE
+        - r1 and r2 of policy ADDED_TYPE_REMOVED_FROM_VEHICLE
+    - 3 nodes A, UV and AR of type T3, respectively with type policies
+      TYPE_ADDED_TO_VEHICLE, TYPE_ON_VEHICLE_UP_TO_VISIT and
+      TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED
+    the configurations
+    UV --> a1 --> r1 --> a2 --> r2,   a1 --> r1 --> a2 --> r2 --> A and
+    a1 --> r1 --> AR --> a2 --> r2 are acceptable, whereas the configurations
+    a1 --> a2 --> r1 --> ..., or A --> a1 --> r1 --> ..., or
+    a1 --> r1 --> UV --> ... are not feasible.
+
+    It also verifies same-vehicle and temporal type requirements.
+    A node of type T_d with a same-vehicle requirement for type T_r needs to be
+    served by the same vehicle as a node of type T_r.
+    Temporal requirements, on the other hand, can take effect either when the
+    dependent type is being added to the route or when it's removed from it,
+    which is determined by the dependent node's VisitTypePolicy.
+    In the above example:
+    - If T3 is required on the same vehicle as T1, A, AR or UV must be on the
+      same vehicle as a1.
+    - If T2 is required when adding T1, a2 must be visited *before* a1, and if
+      r2 is also visited on the route, it must be *after* a1, i.e. T2 must be on
+      the vehicle when a1 is visited:
+      ... --> a2 --> ... --> a1 --> ... --> r2 --> ...
+    - If T3 is required when removing T1, T3 needs to be on the vehicle when
+      r1 is visited:
+      ... --> A --> ... --> r1 --> ...   OR   ... --> r1 --> ... --> UV --> ...
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, model: "RoutingModel"):
+        _pywrapcp.TypeRegulationsConstraint_swiginit(self, _pywrapcp.new_TypeRegulationsConstraint(model))
+
+    def Post(self) -> "void":
+        return _pywrapcp.TypeRegulationsConstraint_Post(self)
+
+    def InitialPropagateWrapper(self) -> "void":
+        return _pywrapcp.TypeRegulationsConstraint_InitialPropagateWrapper(self)
+    __swig_destroy__ = _pywrapcp.delete_TypeRegulationsConstraint
+
+ +
+ +

The following constraint ensures that incompatibilities and requirements +between types are respected.

+ +

It verifies both "hard" and "temporal" incompatibilities. +Two nodes with hard incompatible types cannot be served by the same vehicle +at all, while with a temporal incompatibility they can't be on the same +route at the same time. +The VisitTypePolicy of a node determines how visiting it impacts the type +count on the route.

+ +

For example, for

+ +
    +
  • three temporally incompatible types T1 T2 and T3
  • +
  • 2 pairs of nodes a1/r1 and a2/r2 of type T1 and T2 respectively, with +
      +
    • a1 and a2 of VisitTypePolicy TYPE_ADDED_TO_VEHICLE
    • +
    • r1 and r2 of policy ADDED_TYPE_REMOVED_FROM_VEHICLE
    • +
  • +
  • 3 nodes A, UV and AR of type T3, respectively with type policies +TYPE_ADDED_TO_VEHICLE, TYPE_ON_VEHICLE_UP_TO_VISIT and +TYPE_SIMULTANEOUSLY_ADDED_AND_REMOVED +the configurations +UV --> a1 --> r1 --> a2 --> r2, a1 --> r1 --> a2 --> r2 --> A and +a1 --> r1 --> AR --> a2 --> r2 are acceptable, whereas the configurations +a1 --> a2 --> r1 --> ..., or A --> a1 --> r1 --> ..., or +a1 --> r1 --> UV --> ... are not feasible.
  • +
+ +

It also verifies same-vehicle and temporal type requirements. +A node of type T_d with a same-vehicle requirement for type T_r needs to be +served by the same vehicle as a node of type T_r. +Temporal requirements, on the other hand, can take effect either when the +dependent type is being added to the route or when it's removed from it, +which is determined by the dependent node's VisitTypePolicy. +In the above example:

+ +
    +
  • If T3 is required on the same vehicle as T1, A, AR or UV must be on the +same vehicle as a1.
  • +
  • If T2 is required when adding T1, a2 must be visited before a1, and if +r2 is also visited on the route, it must be after a1, i.e. T2 must be on +the vehicle when a1 is visited: +... --> a2 --> ... --> a1 --> ... --> r2 --> ...
  • +
  • If T3 is required when removing T1, T3 needs to be on the vehicle when +r1 is visited: +... --> A --> ... --> r1 --> ... OR ... --> r1 --> ... --> UV --> ...
  • +
+
+ + +
+
#   + + + TypeRegulationsConstraint(model: ortools.constraint_solver.pywrapcp.RoutingModel) +
+ +
+ View Source +
    def __init__(self, model: "RoutingModel"):
+        _pywrapcp.TypeRegulationsConstraint_swiginit(self, _pywrapcp.new_TypeRegulationsConstraint(model))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Post(self) -> 'void': +
+ +
+ View Source +
    def Post(self) -> "void":
+        return _pywrapcp.TypeRegulationsConstraint_Post(self)
+
+ +
+ +

This method is called when the constraint is processed by the +solver. Its main usage is to attach demons to variables.

+
+ + +
+
+
#   + + + def + InitialPropagateWrapper(self) -> 'void': +
+ +
+ View Source +
    def InitialPropagateWrapper(self) -> "void":
+        return _pywrapcp.TypeRegulationsConstraint_InitialPropagateWrapper(self)
+
+ +
+ +

This method performs the initial propagation of the +constraint. It is called just after the post.

+
+ + +
+
+
Inherited Members
+
+ + +
+
+
+
+
+ #   + + + class + RoutingDimension: +
+ +
+ View Source +
class RoutingDimension(object):
+    r"""
+    Dimensions represent quantities accumulated at nodes along the routes. They
+    represent quantities such as weights or volumes carried along the route, or
+    distance or times.
+
+    Quantities at a node are represented by "cumul" variables and the increase
+    or decrease of quantities between nodes are represented by "transit"
+    variables. These variables are linked as follows:
+
+    if j == next(i),
+    cumuls(j) = cumuls(i) + transits(i) + slacks(i) +
+                state_dependent_transits(i)
+
+    where slack is a positive slack variable (can represent waiting times for
+    a time dimension), and state_dependent_transits is a non-purely functional
+    version of transits_. Favour transits over state_dependent_transits when
+    possible, because purely functional callbacks allow more optimisations and
+    make the model faster and easier to solve.
+    for a given vehicle, it is passed as an external vector, it would be better
+    to have this information here.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+    __swig_destroy__ = _pywrapcp.delete_RoutingDimension
+
+    def model(self) -> "operations_research::RoutingModel *":
+        r""" Returns the model on which the dimension was created."""
+        return _pywrapcp.RoutingDimension_model(self)
+
+    def GetTransitValue(self, from_index: "int64_t", to_index: "int64_t", vehicle: "int64_t") -> "int64_t":
+        r"""
+        Returns the transition value for a given pair of nodes (as var index);
+        this value is the one taken by the corresponding transit variable when
+        the 'next' variable for 'from_index' is bound to 'to_index'.
+        """
+        return _pywrapcp.RoutingDimension_GetTransitValue(self, from_index, to_index, vehicle)
+
+    def GetTransitValueFromClass(self, from_index: "int64_t", to_index: "int64_t", vehicle_class: "int64_t") -> "int64_t":
+        r"""
+        Same as above but taking a vehicle class of the dimension instead of a
+        vehicle (the class of a vehicle can be obtained with vehicle_to_class()).
+        """
+        return _pywrapcp.RoutingDimension_GetTransitValueFromClass(self, from_index, to_index, vehicle_class)
+
+    def CumulVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        r"""
+        Get the cumul, transit and slack variables for the given node (given as
+        int64_t var index).
+        """
+        return _pywrapcp.RoutingDimension_CumulVar(self, index)
+
+    def TransitVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        return _pywrapcp.RoutingDimension_TransitVar(self, index)
+
+    def FixedTransitVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        return _pywrapcp.RoutingDimension_FixedTransitVar(self, index)
+
+    def SlackVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        return _pywrapcp.RoutingDimension_SlackVar(self, index)
+
+    def SetSpanUpperBoundForVehicle(self, upper_bound: "int64_t", vehicle: "int") -> "void":
+        r"""
+        Sets an upper bound on the dimension span on a given vehicle. This is the
+        preferred way to limit the "length" of the route of a vehicle according to
+        a dimension.
+        """
+        return _pywrapcp.RoutingDimension_SetSpanUpperBoundForVehicle(self, upper_bound, vehicle)
+
+    def SetSpanCostCoefficientForVehicle(self, coefficient: "int64_t", vehicle: "int") -> "void":
+        r"""
+        Sets a cost proportional to the dimension span on a given vehicle,
+        or on all vehicles at once. "coefficient" must be nonnegative.
+        This is handy to model costs proportional to idle time when the dimension
+        represents time.
+        The cost for a vehicle is
+          span_cost = coefficient * (dimension end value - dimension start value).
+        """
+        return _pywrapcp.RoutingDimension_SetSpanCostCoefficientForVehicle(self, coefficient, vehicle)
+
+    def SetSpanCostCoefficientForAllVehicles(self, coefficient: "int64_t") -> "void":
+        return _pywrapcp.RoutingDimension_SetSpanCostCoefficientForAllVehicles(self, coefficient)
+
+    def SetGlobalSpanCostCoefficient(self, coefficient: "int64_t") -> "void":
+        r"""
+        Sets a cost proportional to the *global* dimension span, that is the
+        difference between the largest value of route end cumul variables and
+        the smallest value of route start cumul variables.
+        In other words:
+        global_span_cost =
+          coefficient * (Max(dimension end value) - Min(dimension start value)).
+        """
+        return _pywrapcp.RoutingDimension_SetGlobalSpanCostCoefficient(self, coefficient)
+
+    def SetCumulVarSoftUpperBound(self, index: "int64_t", upper_bound: "int64_t", coefficient: "int64_t") -> "void":
+        r"""
+        Sets a soft upper bound to the cumul variable of a given variable index.
+        If the value of the cumul variable is greater than the bound, a cost
+        proportional to the difference between this value and the bound is added
+        to the cost function of the model:
+          cumulVar <= upper_bound -> cost = 0
+           cumulVar > upper_bound -> cost = coefficient * (cumulVar - upper_bound)
+        This is also handy to model tardiness costs when the dimension represents
+        time.
+        """
+        return _pywrapcp.RoutingDimension_SetCumulVarSoftUpperBound(self, index, upper_bound, coefficient)
+
+    def HasCumulVarSoftUpperBound(self, index: "int64_t") -> "bool":
+        r"""
+        Returns true if a soft upper bound has been set for a given variable
+        index.
+        """
+        return _pywrapcp.RoutingDimension_HasCumulVarSoftUpperBound(self, index)
+
+    def GetCumulVarSoftUpperBound(self, index: "int64_t") -> "int64_t":
+        r"""
+        Returns the soft upper bound of a cumul variable for a given variable
+        index. The "hard" upper bound of the variable is returned if no soft upper
+        bound has been set.
+        """
+        return _pywrapcp.RoutingDimension_GetCumulVarSoftUpperBound(self, index)
+
+    def GetCumulVarSoftUpperBoundCoefficient(self, index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost coefficient of the soft upper bound of a cumul variable
+        for a given variable index. If no soft upper bound has been set, 0 is
+        returned.
+        """
+        return _pywrapcp.RoutingDimension_GetCumulVarSoftUpperBoundCoefficient(self, index)
+
+    def SetCumulVarSoftLowerBound(self, index: "int64_t", lower_bound: "int64_t", coefficient: "int64_t") -> "void":
+        r"""
+        Sets a soft lower bound to the cumul variable of a given variable index.
+        If the value of the cumul variable is less than the bound, a cost
+        proportional to the difference between this value and the bound is added
+        to the cost function of the model:
+          cumulVar > lower_bound -> cost = 0
+          cumulVar <= lower_bound -> cost = coefficient * (lower_bound -
+                      cumulVar).
+        This is also handy to model earliness costs when the dimension represents
+        time.
+        """
+        return _pywrapcp.RoutingDimension_SetCumulVarSoftLowerBound(self, index, lower_bound, coefficient)
+
+    def HasCumulVarSoftLowerBound(self, index: "int64_t") -> "bool":
+        r"""
+        Returns true if a soft lower bound has been set for a given variable
+        index.
+        """
+        return _pywrapcp.RoutingDimension_HasCumulVarSoftLowerBound(self, index)
+
+    def GetCumulVarSoftLowerBound(self, index: "int64_t") -> "int64_t":
+        r"""
+        Returns the soft lower bound of a cumul variable for a given variable
+        index. The "hard" lower bound of the variable is returned if no soft lower
+        bound has been set.
+        """
+        return _pywrapcp.RoutingDimension_GetCumulVarSoftLowerBound(self, index)
+
+    def GetCumulVarSoftLowerBoundCoefficient(self, index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost coefficient of the soft lower bound of a cumul variable
+        for a given variable index. If no soft lower bound has been set, 0 is
+        returned.
+        """
+        return _pywrapcp.RoutingDimension_GetCumulVarSoftLowerBoundCoefficient(self, index)
+
+    def SetBreakIntervalsOfVehicle(self, breaks: "std::vector< operations_research::IntervalVar * >", vehicle: "int", node_visit_transits: "std::vector< int64_t >") -> "void":
+        r"""
+        Sets the breaks for a given vehicle. Breaks are represented by
+        IntervalVars. They may interrupt transits between nodes and increase
+        the value of corresponding slack variables.
+        A break may take place before the start of a vehicle, after the end of
+        a vehicle, or during a travel i -> j.
+
+        In that case, the interval [break.Start(), break.End()) must be a subset
+        of [CumulVar(i) + pre_travel(i, j), CumulVar(j) - post_travel(i, j)). In
+        other words, a break may not overlap any node n's visit, given by
+        [CumulVar(n) - post_travel(_, n), CumulVar(n) + pre_travel(n, _)).
+        This formula considers post_travel(_, start) and pre_travel(end, _) to be
+        0; pre_travel will never be called on any (_, start) and post_travel will
+        never we called on any (end, _). If pre_travel_evaluator or
+        post_travel_evaluator is -1, it will be taken as a function that always
+        returns 0.
+        Deprecated, sets pre_travel(i, j) = node_visit_transit[i].
+        """
+        return _pywrapcp.RoutingDimension_SetBreakIntervalsOfVehicle(self, breaks, vehicle, node_visit_transits)
+
+    def SetBreakDistanceDurationOfVehicle(self, distance: "int64_t", duration: "int64_t", vehicle: "int") -> "void":
+        r"""
+        With breaks supposed to be consecutive, this forces the distance between
+        breaks of size at least minimum_break_duration to be at most distance.
+        This supposes that the time until route start and after route end are
+        infinite breaks.
+        """
+        return _pywrapcp.RoutingDimension_SetBreakDistanceDurationOfVehicle(self, distance, duration, vehicle)
+
+    def InitializeBreaks(self) -> "void":
+        r"""
+        Sets up vehicle_break_intervals_, vehicle_break_distance_duration_,
+        pre_travel_evaluators and post_travel_evaluators.
+        """
+        return _pywrapcp.RoutingDimension_InitializeBreaks(self)
+
+    def HasBreakConstraints(self) -> "bool":
+        r""" Returns true if any break interval or break distance was defined."""
+        return _pywrapcp.RoutingDimension_HasBreakConstraints(self)
+
+    def GetPreTravelEvaluatorOfVehicle(self, vehicle: "int") -> "int":
+        return _pywrapcp.RoutingDimension_GetPreTravelEvaluatorOfVehicle(self, vehicle)
+
+    def GetPostTravelEvaluatorOfVehicle(self, vehicle: "int") -> "int":
+        return _pywrapcp.RoutingDimension_GetPostTravelEvaluatorOfVehicle(self, vehicle)
+
+    def base_dimension(self) -> "operations_research::RoutingDimension const *":
+        r""" Returns the parent in the dependency tree if any or nullptr otherwise."""
+        return _pywrapcp.RoutingDimension_base_dimension(self)
+
+    def ShortestTransitionSlack(self, node: "int64_t") -> "int64_t":
+        r"""
+        It makes sense to use the function only for self-dependent dimension.
+        For such dimensions the value of the slack of a node determines the
+        transition cost of the next transit. Provided that
+          1. cumul[node] is fixed,
+          2. next[node] and next[next[node]] (if exists) are fixed,
+        the value of slack[node] for which cumul[next[node]] + transit[next[node]]
+        is minimized can be found in O(1) using this function.
+        """
+        return _pywrapcp.RoutingDimension_ShortestTransitionSlack(self, node)
+
+    def name(self) -> "std::string const &":
+        r""" Returns the name of the dimension."""
+        return _pywrapcp.RoutingDimension_name(self)
+
+    def SetPickupToDeliveryLimitFunctionForPair(self, limit_function: "operations_research::RoutingDimension::PickupToDeliveryLimitFunction", pair_index: "int") -> "void":
+        return _pywrapcp.RoutingDimension_SetPickupToDeliveryLimitFunctionForPair(self, limit_function, pair_index)
+
+    def HasPickupToDeliveryLimits(self) -> "bool":
+        return _pywrapcp.RoutingDimension_HasPickupToDeliveryLimits(self)
+
+    def AddNodePrecedence(self, first_node: "int64_t", second_node: "int64_t", offset: "int64_t") -> "void":
+        return _pywrapcp.RoutingDimension_AddNodePrecedence(self, first_node, second_node, offset)
+
+    def GetSpanUpperBoundForVehicle(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingDimension_GetSpanUpperBoundForVehicle(self, vehicle)
+
+    def GetSpanCostCoefficientForVehicle(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingDimension_GetSpanCostCoefficientForVehicle(self, vehicle)
+
+    def global_span_cost_coefficient(self) -> "int64_t":
+        return _pywrapcp.RoutingDimension_global_span_cost_coefficient(self)
+
+    def GetGlobalOptimizerOffset(self) -> "int64_t":
+        return _pywrapcp.RoutingDimension_GetGlobalOptimizerOffset(self)
+
+    def GetLocalOptimizerOffsetForVehicle(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingDimension_GetLocalOptimizerOffsetForVehicle(self, vehicle)
+
+ +
+ +

Dimensions represent quantities accumulated at nodes along the routes. They +represent quantities such as weights or volumes carried along the route, or +distance or times.

+ +

Quantities at a node are represented by "cumul" variables and the increase +or decrease of quantities between nodes are represented by "transit" +variables. These variables are linked as follows:

+ +

if j == next(i), +cumuls(j) = cumuls(i) + transits(i) + slacks(i) + + state_dependent_transits(i)

+ +

where slack is a positive slack variable (can represent waiting times for +a time dimension), and state_dependent_transits is a non-purely functional +version of transits_. Favour transits over state_dependent_transits when +possible, because purely functional callbacks allow more optimisations and +make the model faster and easier to solve. +for a given vehicle, it is passed as an external vector, it would be better +to have this information here.

+
+ + +
+
#   + + + RoutingDimension(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + model(self) -> 'operations_research::RoutingModel *': +
+ +
+ View Source +
    def model(self) -> "operations_research::RoutingModel *":
+        r""" Returns the model on which the dimension was created."""
+        return _pywrapcp.RoutingDimension_model(self)
+
+ +
+ +

Returns the model on which the dimension was created.

+
+ + +
+
+
#   + + + def + GetTransitValue( + self, + from_index: 'int64_t', + to_index: 'int64_t', + vehicle: 'int64_t' +) -> 'int64_t': +
+ +
+ View Source +
    def GetTransitValue(self, from_index: "int64_t", to_index: "int64_t", vehicle: "int64_t") -> "int64_t":
+        r"""
+        Returns the transition value for a given pair of nodes (as var index);
+        this value is the one taken by the corresponding transit variable when
+        the 'next' variable for 'from_index' is bound to 'to_index'.
+        """
+        return _pywrapcp.RoutingDimension_GetTransitValue(self, from_index, to_index, vehicle)
+
+ +
+ +

Returns the transition value for a given pair of nodes (as var index); +this value is the one taken by the corresponding transit variable when +the 'next' variable for 'from_index' is bound to 'to_index'.

+
+ + +
+
+
#   + + + def + GetTransitValueFromClass( + self, + from_index: 'int64_t', + to_index: 'int64_t', + vehicle_class: 'int64_t' +) -> 'int64_t': +
+ +
+ View Source +
    def GetTransitValueFromClass(self, from_index: "int64_t", to_index: "int64_t", vehicle_class: "int64_t") -> "int64_t":
+        r"""
+        Same as above but taking a vehicle class of the dimension instead of a
+        vehicle (the class of a vehicle can be obtained with vehicle_to_class()).
+        """
+        return _pywrapcp.RoutingDimension_GetTransitValueFromClass(self, from_index, to_index, vehicle_class)
+
+ +
+ +

Same as above but taking a vehicle class of the dimension instead of a +vehicle (the class of a vehicle can be obtained with vehicle_to_class()).

+
+ + +
+
+
#   + + + def + CumulVar(self, index: 'int64_t') -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def CumulVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        r"""
+        Get the cumul, transit and slack variables for the given node (given as
+        int64_t var index).
+        """
+        return _pywrapcp.RoutingDimension_CumulVar(self, index)
+
+ +
+ +

Get the cumul, transit and slack variables for the given node (given as +int64_t var index).

+
+ + +
+
+
#   + + + def + TransitVar(self, index: 'int64_t') -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def TransitVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        return _pywrapcp.RoutingDimension_TransitVar(self, index)
+
+ +
+ + + +
+
+
#   + + + def + FixedTransitVar(self, index: 'int64_t') -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def FixedTransitVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        return _pywrapcp.RoutingDimension_FixedTransitVar(self, index)
+
+ +
+ + + +
+
+
#   + + + def + SlackVar(self, index: 'int64_t') -> 'operations_research::IntVar *': +
+ +
+ View Source +
    def SlackVar(self, index: "int64_t") -> "operations_research::IntVar *":
+        return _pywrapcp.RoutingDimension_SlackVar(self, index)
+
+ +
+ + + +
+
+
#   + + + def + SetSpanUpperBoundForVehicle(self, upper_bound: 'int64_t', vehicle: int) -> 'void': +
+ +
+ View Source +
    def SetSpanUpperBoundForVehicle(self, upper_bound: "int64_t", vehicle: "int") -> "void":
+        r"""
+        Sets an upper bound on the dimension span on a given vehicle. This is the
+        preferred way to limit the "length" of the route of a vehicle according to
+        a dimension.
+        """
+        return _pywrapcp.RoutingDimension_SetSpanUpperBoundForVehicle(self, upper_bound, vehicle)
+
+ +
+ +

Sets an upper bound on the dimension span on a given vehicle. This is the +preferred way to limit the "length" of the route of a vehicle according to +a dimension.

+
+ + +
+
+
#   + + + def + SetSpanCostCoefficientForVehicle(self, coefficient: 'int64_t', vehicle: int) -> 'void': +
+ +
+ View Source +
    def SetSpanCostCoefficientForVehicle(self, coefficient: "int64_t", vehicle: "int") -> "void":
+        r"""
+        Sets a cost proportional to the dimension span on a given vehicle,
+        or on all vehicles at once. "coefficient" must be nonnegative.
+        This is handy to model costs proportional to idle time when the dimension
+        represents time.
+        The cost for a vehicle is
+          span_cost = coefficient * (dimension end value - dimension start value).
+        """
+        return _pywrapcp.RoutingDimension_SetSpanCostCoefficientForVehicle(self, coefficient, vehicle)
+
+ +
+ +

Sets a cost proportional to the dimension span on a given vehicle, +or on all vehicles at once. "coefficient" must be nonnegative. +This is handy to model costs proportional to idle time when the dimension +represents time. +The cost for a vehicle is + span_cost = coefficient * (dimension end value - dimension start value).

+
+ + +
+
+
#   + + + def + SetSpanCostCoefficientForAllVehicles(self, coefficient: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetSpanCostCoefficientForAllVehicles(self, coefficient: "int64_t") -> "void":
+        return _pywrapcp.RoutingDimension_SetSpanCostCoefficientForAllVehicles(self, coefficient)
+
+ +
+ + + +
+
+
#   + + + def + SetGlobalSpanCostCoefficient(self, coefficient: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetGlobalSpanCostCoefficient(self, coefficient: "int64_t") -> "void":
+        r"""
+        Sets a cost proportional to the *global* dimension span, that is the
+        difference between the largest value of route end cumul variables and
+        the smallest value of route start cumul variables.
+        In other words:
+        global_span_cost =
+          coefficient * (Max(dimension end value) - Min(dimension start value)).
+        """
+        return _pywrapcp.RoutingDimension_SetGlobalSpanCostCoefficient(self, coefficient)
+
+ +
+ +

Sets a cost proportional to the global dimension span, that is the +difference between the largest value of route end cumul variables and +the smallest value of route start cumul variables. +In other words: +global_span_cost = + coefficient * (Max(dimension end value) - Min(dimension start value)).

+
+ + +
+
+
#   + + + def + SetCumulVarSoftUpperBound( + self, + index: 'int64_t', + upper_bound: 'int64_t', + coefficient: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetCumulVarSoftUpperBound(self, index: "int64_t", upper_bound: "int64_t", coefficient: "int64_t") -> "void":
+        r"""
+        Sets a soft upper bound to the cumul variable of a given variable index.
+        If the value of the cumul variable is greater than the bound, a cost
+        proportional to the difference between this value and the bound is added
+        to the cost function of the model:
+          cumulVar <= upper_bound -> cost = 0
+           cumulVar > upper_bound -> cost = coefficient * (cumulVar - upper_bound)
+        This is also handy to model tardiness costs when the dimension represents
+        time.
+        """
+        return _pywrapcp.RoutingDimension_SetCumulVarSoftUpperBound(self, index, upper_bound, coefficient)
+
+ +
+ +

Sets a soft upper bound to the cumul variable of a given variable index. +If the value of the cumul variable is greater than the bound, a cost +proportional to the difference between this value and the bound is added +to the cost function of the model: + cumulVar <= upper_bound -> cost = 0 + cumulVar > upper_bound -> cost = coefficient * (cumulVar - upper_bound) +This is also handy to model tardiness costs when the dimension represents +time.

+
+ + +
+
+
#   + + + def + HasCumulVarSoftUpperBound(self, index: 'int64_t') -> bool: +
+ +
+ View Source +
    def HasCumulVarSoftUpperBound(self, index: "int64_t") -> "bool":
+        r"""
+        Returns true if a soft upper bound has been set for a given variable
+        index.
+        """
+        return _pywrapcp.RoutingDimension_HasCumulVarSoftUpperBound(self, index)
+
+ +
+ +

Returns true if a soft upper bound has been set for a given variable +index.

+
+ + +
+
+
#   + + + def + GetCumulVarSoftUpperBound(self, index: 'int64_t') -> 'int64_t': +
+ +
+ View Source +
    def GetCumulVarSoftUpperBound(self, index: "int64_t") -> "int64_t":
+        r"""
+        Returns the soft upper bound of a cumul variable for a given variable
+        index. The "hard" upper bound of the variable is returned if no soft upper
+        bound has been set.
+        """
+        return _pywrapcp.RoutingDimension_GetCumulVarSoftUpperBound(self, index)
+
+ +
+ +

Returns the soft upper bound of a cumul variable for a given variable +index. The "hard" upper bound of the variable is returned if no soft upper +bound has been set.

+
+ + +
+
+
#   + + + def + GetCumulVarSoftUpperBoundCoefficient(self, index: 'int64_t') -> 'int64_t': +
+ +
+ View Source +
    def GetCumulVarSoftUpperBoundCoefficient(self, index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost coefficient of the soft upper bound of a cumul variable
+        for a given variable index. If no soft upper bound has been set, 0 is
+        returned.
+        """
+        return _pywrapcp.RoutingDimension_GetCumulVarSoftUpperBoundCoefficient(self, index)
+
+ +
+ +

Returns the cost coefficient of the soft upper bound of a cumul variable +for a given variable index. If no soft upper bound has been set, 0 is +returned.

+
+ + +
+
+
#   + + + def + SetCumulVarSoftLowerBound( + self, + index: 'int64_t', + lower_bound: 'int64_t', + coefficient: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def SetCumulVarSoftLowerBound(self, index: "int64_t", lower_bound: "int64_t", coefficient: "int64_t") -> "void":
+        r"""
+        Sets a soft lower bound to the cumul variable of a given variable index.
+        If the value of the cumul variable is less than the bound, a cost
+        proportional to the difference between this value and the bound is added
+        to the cost function of the model:
+          cumulVar > lower_bound -> cost = 0
+          cumulVar <= lower_bound -> cost = coefficient * (lower_bound -
+                      cumulVar).
+        This is also handy to model earliness costs when the dimension represents
+        time.
+        """
+        return _pywrapcp.RoutingDimension_SetCumulVarSoftLowerBound(self, index, lower_bound, coefficient)
+
+ +
+ +

Sets a soft lower bound to the cumul variable of a given variable index. +If the value of the cumul variable is less than the bound, a cost +proportional to the difference between this value and the bound is added +to the cost function of the model: + cumulVar > lower_bound -> cost = 0 + cumulVar <= lower_bound -> cost = coefficient * (lower_bound - + cumulVar). +This is also handy to model earliness costs when the dimension represents +time.

+
+ + +
+
+
#   + + + def + HasCumulVarSoftLowerBound(self, index: 'int64_t') -> bool: +
+ +
+ View Source +
    def HasCumulVarSoftLowerBound(self, index: "int64_t") -> "bool":
+        r"""
+        Returns true if a soft lower bound has been set for a given variable
+        index.
+        """
+        return _pywrapcp.RoutingDimension_HasCumulVarSoftLowerBound(self, index)
+
+ +
+ +

Returns true if a soft lower bound has been set for a given variable +index.

+
+ + +
+
+
#   + + + def + GetCumulVarSoftLowerBound(self, index: 'int64_t') -> 'int64_t': +
+ +
+ View Source +
    def GetCumulVarSoftLowerBound(self, index: "int64_t") -> "int64_t":
+        r"""
+        Returns the soft lower bound of a cumul variable for a given variable
+        index. The "hard" lower bound of the variable is returned if no soft lower
+        bound has been set.
+        """
+        return _pywrapcp.RoutingDimension_GetCumulVarSoftLowerBound(self, index)
+
+ +
+ +

Returns the soft lower bound of a cumul variable for a given variable +index. The "hard" lower bound of the variable is returned if no soft lower +bound has been set.

+
+ + +
+
+
#   + + + def + GetCumulVarSoftLowerBoundCoefficient(self, index: 'int64_t') -> 'int64_t': +
+ +
+ View Source +
    def GetCumulVarSoftLowerBoundCoefficient(self, index: "int64_t") -> "int64_t":
+        r"""
+        Returns the cost coefficient of the soft lower bound of a cumul variable
+        for a given variable index. If no soft lower bound has been set, 0 is
+        returned.
+        """
+        return _pywrapcp.RoutingDimension_GetCumulVarSoftLowerBoundCoefficient(self, index)
+
+ +
+ +

Returns the cost coefficient of the soft lower bound of a cumul variable +for a given variable index. If no soft lower bound has been set, 0 is +returned.

+
+ + +
+
+
#   + + + def + SetBreakIntervalsOfVehicle( + self, + breaks: 'std::vector< operations_research::IntervalVar * >', + vehicle: int, + node_visit_transits: 'std::vector< int64_t >' +) -> 'void': +
+ +
+ View Source +
    def SetBreakIntervalsOfVehicle(self, breaks: "std::vector< operations_research::IntervalVar * >", vehicle: "int", node_visit_transits: "std::vector< int64_t >") -> "void":
+        r"""
+        Sets the breaks for a given vehicle. Breaks are represented by
+        IntervalVars. They may interrupt transits between nodes and increase
+        the value of corresponding slack variables.
+        A break may take place before the start of a vehicle, after the end of
+        a vehicle, or during a travel i -> j.
+
+        In that case, the interval [break.Start(), break.End()) must be a subset
+        of [CumulVar(i) + pre_travel(i, j), CumulVar(j) - post_travel(i, j)). In
+        other words, a break may not overlap any node n's visit, given by
+        [CumulVar(n) - post_travel(_, n), CumulVar(n) + pre_travel(n, _)).
+        This formula considers post_travel(_, start) and pre_travel(end, _) to be
+        0; pre_travel will never be called on any (_, start) and post_travel will
+        never we called on any (end, _). If pre_travel_evaluator or
+        post_travel_evaluator is -1, it will be taken as a function that always
+        returns 0.
+        Deprecated, sets pre_travel(i, j) = node_visit_transit[i].
+        """
+        return _pywrapcp.RoutingDimension_SetBreakIntervalsOfVehicle(self, breaks, vehicle, node_visit_transits)
+
+ +
+ +

Sets the breaks for a given vehicle. Breaks are represented by +IntervalVars. They may interrupt transits between nodes and increase +the value of corresponding slack variables. +A break may take place before the start of a vehicle, after the end of +a vehicle, or during a travel i -> j.

+ +

In that case, the interval [break.Start(), break.End()) must be a subset +of [CumulVar(i) + pre_travel(i, j), CumulVar(j) - post_travel(i, j)). In +other words, a break may not overlap any node n's visit, given by +[CumulVar(n) - post_travel(_, n), CumulVar(n) + pre_travel(n, _)). +This formula considers post_travel(_, start) and pre_travel(end, _) to be +0; pre_travel will never be called on any (_, start) and post_travel will +never we called on any (end, _). If pre_travel_evaluator or +post_travel_evaluator is -1, it will be taken as a function that always +returns 0. +Deprecated, sets pre_travel(i, j) = node_visit_transit[i].

+
+ + +
+
+
#   + + + def + SetBreakDistanceDurationOfVehicle( + self, + distance: 'int64_t', + duration: 'int64_t', + vehicle: int +) -> 'void': +
+ +
+ View Source +
    def SetBreakDistanceDurationOfVehicle(self, distance: "int64_t", duration: "int64_t", vehicle: "int") -> "void":
+        r"""
+        With breaks supposed to be consecutive, this forces the distance between
+        breaks of size at least minimum_break_duration to be at most distance.
+        This supposes that the time until route start and after route end are
+        infinite breaks.
+        """
+        return _pywrapcp.RoutingDimension_SetBreakDistanceDurationOfVehicle(self, distance, duration, vehicle)
+
+ +
+ +

With breaks supposed to be consecutive, this forces the distance between +breaks of size at least minimum_break_duration to be at most distance. +This supposes that the time until route start and after route end are +infinite breaks.

+
+ + +
+
+
#   + + + def + InitializeBreaks(self) -> 'void': +
+ +
+ View Source +
    def InitializeBreaks(self) -> "void":
+        r"""
+        Sets up vehicle_break_intervals_, vehicle_break_distance_duration_,
+        pre_travel_evaluators and post_travel_evaluators.
+        """
+        return _pywrapcp.RoutingDimension_InitializeBreaks(self)
+
+ +
+ +

Sets up vehicle_break_intervals_, vehicle_break_distance_duration_, +pre_travel_evaluators and post_travel_evaluators.

+
+ + +
+
+
#   + + + def + HasBreakConstraints(self) -> bool: +
+ +
+ View Source +
    def HasBreakConstraints(self) -> "bool":
+        r""" Returns true if any break interval or break distance was defined."""
+        return _pywrapcp.RoutingDimension_HasBreakConstraints(self)
+
+ +
+ +

Returns true if any break interval or break distance was defined.

+
+ + +
+
+
#   + + + def + GetPreTravelEvaluatorOfVehicle(self, vehicle: int) -> int: +
+ +
+ View Source +
    def GetPreTravelEvaluatorOfVehicle(self, vehicle: "int") -> "int":
+        return _pywrapcp.RoutingDimension_GetPreTravelEvaluatorOfVehicle(self, vehicle)
+
+ +
+ + + +
+
+
#   + + + def + GetPostTravelEvaluatorOfVehicle(self, vehicle: int) -> int: +
+ +
+ View Source +
    def GetPostTravelEvaluatorOfVehicle(self, vehicle: "int") -> "int":
+        return _pywrapcp.RoutingDimension_GetPostTravelEvaluatorOfVehicle(self, vehicle)
+
+ +
+ + + +
+
+
#   + + + def + base_dimension(self) -> 'operations_research::RoutingDimension const *': +
+ +
+ View Source +
    def base_dimension(self) -> "operations_research::RoutingDimension const *":
+        r""" Returns the parent in the dependency tree if any or nullptr otherwise."""
+        return _pywrapcp.RoutingDimension_base_dimension(self)
+
+ +
+ +

Returns the parent in the dependency tree if any or nullptr otherwise.

+
+ + +
+
+
#   + + + def + ShortestTransitionSlack(self, node: 'int64_t') -> 'int64_t': +
+ +
+ View Source +
    def ShortestTransitionSlack(self, node: "int64_t") -> "int64_t":
+        r"""
+        It makes sense to use the function only for self-dependent dimension.
+        For such dimensions the value of the slack of a node determines the
+        transition cost of the next transit. Provided that
+          1. cumul[node] is fixed,
+          2. next[node] and next[next[node]] (if exists) are fixed,
+        the value of slack[node] for which cumul[next[node]] + transit[next[node]]
+        is minimized can be found in O(1) using this function.
+        """
+        return _pywrapcp.RoutingDimension_ShortestTransitionSlack(self, node)
+
+ +
+ +

It makes sense to use the function only for self-dependent dimension. +For such dimensions the value of the slack of a node determines the +transition cost of the next transit. Provided that

+ +
    +
  1. cumul[node] is fixed,
  2. +
  3. next[node] and next[next[node]] (if exists) are fixed, +the value of slack[node] for which cumul[next[node]] + transit[next[node]] +is minimized can be found in O(1) using this function.
  4. +
+
+ + +
+
+
#   + + + def + name(self) -> 'std::string const &': +
+ +
+ View Source +
    def name(self) -> "std::string const &":
+        r""" Returns the name of the dimension."""
+        return _pywrapcp.RoutingDimension_name(self)
+
+ +
+ +

Returns the name of the dimension.

+
+ + +
+
+
#   + + + def + SetPickupToDeliveryLimitFunctionForPair( + self, + limit_function: 'operations_research::RoutingDimension::PickupToDeliveryLimitFunction', + pair_index: int +) -> 'void': +
+ +
+ View Source +
    def SetPickupToDeliveryLimitFunctionForPair(self, limit_function: "operations_research::RoutingDimension::PickupToDeliveryLimitFunction", pair_index: "int") -> "void":
+        return _pywrapcp.RoutingDimension_SetPickupToDeliveryLimitFunctionForPair(self, limit_function, pair_index)
+
+ +
+ + + +
+
+
#   + + + def + HasPickupToDeliveryLimits(self) -> bool: +
+ +
+ View Source +
    def HasPickupToDeliveryLimits(self) -> "bool":
+        return _pywrapcp.RoutingDimension_HasPickupToDeliveryLimits(self)
+
+ +
+ + + +
+
+
#   + + + def + AddNodePrecedence( + self, + first_node: 'int64_t', + second_node: 'int64_t', + offset: 'int64_t' +) -> 'void': +
+ +
+ View Source +
    def AddNodePrecedence(self, first_node: "int64_t", second_node: "int64_t", offset: "int64_t") -> "void":
+        return _pywrapcp.RoutingDimension_AddNodePrecedence(self, first_node, second_node, offset)
+
+ +
+ + + +
+
+
#   + + + def + GetSpanUpperBoundForVehicle(self, vehicle: int) -> 'int64_t': +
+ +
+ View Source +
    def GetSpanUpperBoundForVehicle(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingDimension_GetSpanUpperBoundForVehicle(self, vehicle)
+
+ +
+ + + +
+
+
#   + + + def + GetSpanCostCoefficientForVehicle(self, vehicle: int) -> 'int64_t': +
+ +
+ View Source +
    def GetSpanCostCoefficientForVehicle(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingDimension_GetSpanCostCoefficientForVehicle(self, vehicle)
+
+ +
+ + + +
+
+
#   + + + def + global_span_cost_coefficient(self) -> 'int64_t': +
+ +
+ View Source +
    def global_span_cost_coefficient(self) -> "int64_t":
+        return _pywrapcp.RoutingDimension_global_span_cost_coefficient(self)
+
+ +
+ + + +
+
+
#   + + + def + GetGlobalOptimizerOffset(self) -> 'int64_t': +
+ +
+ View Source +
    def GetGlobalOptimizerOffset(self) -> "int64_t":
+        return _pywrapcp.RoutingDimension_GetGlobalOptimizerOffset(self)
+
+ +
+ + + +
+
+
#   + + + def + GetLocalOptimizerOffsetForVehicle(self, vehicle: int) -> 'int64_t': +
+ +
+ View Source +
    def GetLocalOptimizerOffsetForVehicle(self, vehicle: "int") -> "int64_t":
+        return _pywrapcp.RoutingDimension_GetLocalOptimizerOffsetForVehicle(self, vehicle)
+
+ +
+ + + +
+
+
+
#   + + + def + MakeSetValuesFromTargets( + solver: ortools.constraint_solver.pywrapcp.Solver, + variables: 'std::vector< operations_research::IntVar * >', + targets: 'std::vector< int64_t >' +) -> 'operations_research::DecisionBuilder *': +
+ +
+ View Source +
def MakeSetValuesFromTargets(solver: "Solver", variables: "std::vector< operations_research::IntVar * >", targets: "std::vector< int64_t >") -> "operations_research::DecisionBuilder *":
+    r"""
+    A decision builder which tries to assign values to variables as close as
+    possible to target values first.
+    """
+    return _pywrapcp.MakeSetValuesFromTargets(solver, variables, targets)
+
+ +
+ +

A decision builder which tries to assign values to variables as close as +possible to target values first.

+
+ + +
+
+
#   + + + def + SolveModelWithSat( + model: ortools.constraint_solver.pywrapcp.RoutingModel, + search_parameters: 'operations_research::RoutingSearchParameters const &', + initial_solution: ortools.constraint_solver.pywrapcp.Assignment, + solution: ortools.constraint_solver.pywrapcp.Assignment +) -> bool: +
+ +
+ View Source +
def SolveModelWithSat(model: "RoutingModel", search_parameters: "operations_research::RoutingSearchParameters const &", initial_solution: "Assignment", solution: "Assignment") -> "bool":
+    r"""
+    Attempts to solve the model using the cp-sat solver. As of 5/2019, will
+    solve the TSP corresponding to the model if it has a single vehicle.
+    Therefore the resulting solution might not actually be feasible. Will return
+    false if a solution could not be found.
+    """
+    return _pywrapcp.SolveModelWithSat(model, search_parameters, initial_solution, solution)
+
+ +
+ +

Attempts to solve the model using the cp-sat solver. As of 5/2019, will +solve the TSP corresponding to the model if it has a single vehicle. +Therefore the resulting solution might not actually be feasible. Will return +false if a solution could not be found.

+
+ + +
+
+ + \ No newline at end of file diff --git a/docs/python/ortools/graph/index.html b/docs/python/ortools/graph/index.html index b0b64f18c3..271e6e1c78 100644 --- a/docs/python/ortools/graph/index.html +++ b/docs/python/ortools/graph/index.html @@ -1,58 +1,7 @@ - + - - - Module List – pdoc 8.0.0 - - - - - - - - + - -
- - pdoc logo - -
-
-
- - \ No newline at end of file + diff --git a/docs/python/ortools/graph/ortools/graph/pywrapgraph.html b/docs/python/ortools/graph/ortools/graph/pywrapgraph.html new file mode 100644 index 0000000000..b98bdcdacc --- /dev/null +++ b/docs/python/ortools/graph/ortools/graph/pywrapgraph.html @@ -0,0 +1,1832 @@ + + + + + + + ortools.graph.pywrapgraph API documentation + + + + + + + + + +
+
+

+ortools.graph.pywrapgraph

+ + +
+ View Source +
# This file was automatically generated by SWIG (http://www.swig.org).
+# Version 4.0.2
+#
+# Do not make changes to this file unless you know what you are doing--modify
+# the SWIG interface file instead.
+
+from sys import version_info as _swig_python_version_info
+if _swig_python_version_info < (2, 7, 0):
+    raise RuntimeError("Python 2.7 or later required")
+
+# Import the low-level C/C++ module
+if __package__ or "." in __name__:
+    from . import _pywrapgraph
+else:
+    import _pywrapgraph
+
+try:
+    import builtins as __builtin__
+except ImportError:
+    import __builtin__
+
+def _swig_repr(self):
+    try:
+        strthis = "proxy of " + self.this.__repr__()
+    except __builtin__.Exception:
+        strthis = ""
+    return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+
+def _swig_setattr_nondynamic_instance_variable(set):
+    def set_instance_attr(self, name, value):
+        if name == "thisown":
+            self.this.own(value)
+        elif name == "this":
+            set(self, name, value)
+        elif hasattr(self, name) and isinstance(getattr(type(self), name), property):
+            set(self, name, value)
+        else:
+            raise AttributeError("You cannot add instance attributes to %s" % self)
+    return set_instance_attr
+
+
+def _swig_setattr_nondynamic_class_variable(set):
+    def set_class_attr(cls, name, value):
+        if hasattr(cls, name) and not isinstance(getattr(cls, name), property):
+            set(cls, name, value)
+        else:
+            raise AttributeError("You cannot add class attributes to %s" % cls)
+    return set_class_attr
+
+
+def _swig_add_metaclass(metaclass):
+    """Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass"""
+    def wrapper(cls):
+        return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy())
+    return wrapper
+
+
+class _SwigNonDynamicMeta(type):
+    """Meta class to enforce nondynamic attributes (no new attributes) for a class"""
+    __setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__)
+
+
+class SimpleMaxFlow(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self):
+        _pywrapgraph.SimpleMaxFlow_swiginit(self, _pywrapgraph.new_SimpleMaxFlow())
+
+    def AddArcWithCapacity(self, tail: "operations_research::NodeIndex", head: "operations_research::NodeIndex", capacity: "operations_research::FlowQuantity") -> "operations_research::ArcIndex":
+        return _pywrapgraph.SimpleMaxFlow_AddArcWithCapacity(self, tail, head, capacity)
+
+    def NumNodes(self) -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMaxFlow_NumNodes(self)
+
+    def NumArcs(self) -> "operations_research::ArcIndex":
+        return _pywrapgraph.SimpleMaxFlow_NumArcs(self)
+
+    def Tail(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMaxFlow_Tail(self, arc)
+
+    def Head(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMaxFlow_Head(self, arc)
+
+    def Capacity(self, arc: "operations_research::ArcIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMaxFlow_Capacity(self, arc)
+    OPTIMAL = _pywrapgraph.SimpleMaxFlow_OPTIMAL
+    POSSIBLE_OVERFLOW = _pywrapgraph.SimpleMaxFlow_POSSIBLE_OVERFLOW
+    BAD_INPUT = _pywrapgraph.SimpleMaxFlow_BAD_INPUT
+    BAD_RESULT = _pywrapgraph.SimpleMaxFlow_BAD_RESULT
+
+    def Solve(self, source: "operations_research::NodeIndex", sink: "operations_research::NodeIndex") -> "operations_research::SimpleMaxFlow::Status":
+        return _pywrapgraph.SimpleMaxFlow_Solve(self, source, sink)
+
+    def OptimalFlow(self) -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMaxFlow_OptimalFlow(self)
+
+    def Flow(self, arc: "operations_research::ArcIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMaxFlow_Flow(self, arc)
+
+    def GetSourceSideMinCut(self) -> "void":
+        return _pywrapgraph.SimpleMaxFlow_GetSourceSideMinCut(self)
+
+    def GetSinkSideMinCut(self) -> "void":
+        return _pywrapgraph.SimpleMaxFlow_GetSinkSideMinCut(self)
+
+    def SetArcCapacity(self, arc: "operations_research::ArcIndex", capacity: "operations_research::FlowQuantity") -> "void":
+        return _pywrapgraph.SimpleMaxFlow_SetArcCapacity(self, arc, capacity)
+    __swig_destroy__ = _pywrapgraph.delete_SimpleMaxFlow
+
+# Register SimpleMaxFlow in _pywrapgraph:
+_pywrapgraph.SimpleMaxFlow_swigregister(SimpleMaxFlow)
+
+class MinCostFlowBase(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+    NOT_SOLVED = _pywrapgraph.MinCostFlowBase_NOT_SOLVED
+    OPTIMAL = _pywrapgraph.MinCostFlowBase_OPTIMAL
+    FEASIBLE = _pywrapgraph.MinCostFlowBase_FEASIBLE
+    INFEASIBLE = _pywrapgraph.MinCostFlowBase_INFEASIBLE
+    UNBALANCED = _pywrapgraph.MinCostFlowBase_UNBALANCED
+    BAD_RESULT = _pywrapgraph.MinCostFlowBase_BAD_RESULT
+    BAD_COST_RANGE = _pywrapgraph.MinCostFlowBase_BAD_COST_RANGE
+
+    def __init__(self):
+        _pywrapgraph.MinCostFlowBase_swiginit(self, _pywrapgraph.new_MinCostFlowBase())
+    __swig_destroy__ = _pywrapgraph.delete_MinCostFlowBase
+
+# Register MinCostFlowBase in _pywrapgraph:
+_pywrapgraph.MinCostFlowBase_swigregister(MinCostFlowBase)
+
+class SimpleMinCostFlow(MinCostFlowBase):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, reserve_num_nodes: "operations_research::NodeIndex"=0, reserve_num_arcs: "operations_research::ArcIndex"=0):
+        _pywrapgraph.SimpleMinCostFlow_swiginit(self, _pywrapgraph.new_SimpleMinCostFlow(reserve_num_nodes, reserve_num_arcs))
+
+    def AddArcWithCapacityAndUnitCost(self, tail: "operations_research::NodeIndex", head: "operations_research::NodeIndex", capacity: "operations_research::FlowQuantity", unit_cost: "operations_research::CostValue") -> "operations_research::ArcIndex":
+        return _pywrapgraph.SimpleMinCostFlow_AddArcWithCapacityAndUnitCost(self, tail, head, capacity, unit_cost)
+
+    def SetNodeSupply(self, node: "operations_research::NodeIndex", supply: "operations_research::FlowQuantity") -> "void":
+        return _pywrapgraph.SimpleMinCostFlow_SetNodeSupply(self, node, supply)
+
+    def Solve(self) -> "operations_research::MinCostFlowBase::Status":
+        return _pywrapgraph.SimpleMinCostFlow_Solve(self)
+
+    def SolveMaxFlowWithMinCost(self) -> "operations_research::MinCostFlowBase::Status":
+        return _pywrapgraph.SimpleMinCostFlow_SolveMaxFlowWithMinCost(self)
+
+    def OptimalCost(self) -> "operations_research::CostValue":
+        return _pywrapgraph.SimpleMinCostFlow_OptimalCost(self)
+
+    def MaximumFlow(self) -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMinCostFlow_MaximumFlow(self)
+
+    def Flow(self, arc: "operations_research::ArcIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMinCostFlow_Flow(self, arc)
+
+    def NumNodes(self) -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMinCostFlow_NumNodes(self)
+
+    def NumArcs(self) -> "operations_research::ArcIndex":
+        return _pywrapgraph.SimpleMinCostFlow_NumArcs(self)
+
+    def Tail(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMinCostFlow_Tail(self, arc)
+
+    def Head(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMinCostFlow_Head(self, arc)
+
+    def Capacity(self, arc: "operations_research::ArcIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMinCostFlow_Capacity(self, arc)
+
+    def Supply(self, node: "operations_research::NodeIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMinCostFlow_Supply(self, node)
+
+    def UnitCost(self, arc: "operations_research::ArcIndex") -> "operations_research::CostValue":
+        return _pywrapgraph.SimpleMinCostFlow_UnitCost(self, arc)
+    __swig_destroy__ = _pywrapgraph.delete_SimpleMinCostFlow
+
+# Register SimpleMinCostFlow in _pywrapgraph:
+_pywrapgraph.SimpleMinCostFlow_swigregister(SimpleMinCostFlow)
+
+class LinearSumAssignment(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self):
+        _pywrapgraph.LinearSumAssignment_swiginit(self, _pywrapgraph.new_LinearSumAssignment())
+
+    def AddArcWithCost(self, left_node: "operations_research::NodeIndex", right_node: "operations_research::NodeIndex", cost: "operations_research::CostValue") -> "operations_research::ArcIndex":
+        return _pywrapgraph.LinearSumAssignment_AddArcWithCost(self, left_node, right_node, cost)
+
+    def NumNodes(self) -> "operations_research::NodeIndex":
+        return _pywrapgraph.LinearSumAssignment_NumNodes(self)
+
+    def NumArcs(self) -> "operations_research::ArcIndex":
+        return _pywrapgraph.LinearSumAssignment_NumArcs(self)
+
+    def LeftNode(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.LinearSumAssignment_LeftNode(self, arc)
+
+    def RightNode(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.LinearSumAssignment_RightNode(self, arc)
+
+    def Cost(self, arc: "operations_research::ArcIndex") -> "operations_research::CostValue":
+        return _pywrapgraph.LinearSumAssignment_Cost(self, arc)
+    OPTIMAL = _pywrapgraph.LinearSumAssignment_OPTIMAL
+    INFEASIBLE = _pywrapgraph.LinearSumAssignment_INFEASIBLE
+    POSSIBLE_OVERFLOW = _pywrapgraph.LinearSumAssignment_POSSIBLE_OVERFLOW
+
+    def Solve(self) -> "operations_research::SimpleLinearSumAssignment::Status":
+        return _pywrapgraph.LinearSumAssignment_Solve(self)
+
+    def OptimalCost(self) -> "operations_research::CostValue":
+        return _pywrapgraph.LinearSumAssignment_OptimalCost(self)
+
+    def RightMate(self, left_node: "operations_research::NodeIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.LinearSumAssignment_RightMate(self, left_node)
+
+    def AssignmentCost(self, left_node: "operations_research::NodeIndex") -> "operations_research::CostValue":
+        return _pywrapgraph.LinearSumAssignment_AssignmentCost(self, left_node)
+    __swig_destroy__ = _pywrapgraph.delete_LinearSumAssignment
+
+# Register LinearSumAssignment in _pywrapgraph:
+_pywrapgraph.LinearSumAssignment_swigregister(LinearSumAssignment)
+
+
+def DijkstraShortestPath(node_count: "int", start_node: "int", end_node: "int", graph: "std::function< int64_t (int,int) >", disconnected_distance: "int64_t") -> "std::vector< int > *":
+    return _pywrapgraph.DijkstraShortestPath(node_count, start_node, end_node, graph, disconnected_distance)
+
+def BellmanFordShortestPath(node_count: "int", start_node: "int", end_node: "int", graph: "std::function< int64_t (int,int) >", disconnected_distance: "int64_t") -> "std::vector< int > *":
+    return _pywrapgraph.BellmanFordShortestPath(node_count, start_node, end_node, graph, disconnected_distance)
+
+def AStarShortestPath(node_count: "int", start_node: "int", end_node: "int", graph: "std::function< int64_t (int,int) >", heuristic: "std::function< int64_t (int) >", disconnected_distance: "int64_t") -> "std::vector< int > *":
+    return _pywrapgraph.AStarShortestPath(node_count, start_node, end_node, graph, heuristic, disconnected_distance)
+
+ +
+ +
+
+
+ #   + + + class + SimpleMaxFlow: +
+ +
+ View Source +
class SimpleMaxFlow(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self):
+        _pywrapgraph.SimpleMaxFlow_swiginit(self, _pywrapgraph.new_SimpleMaxFlow())
+
+    def AddArcWithCapacity(self, tail: "operations_research::NodeIndex", head: "operations_research::NodeIndex", capacity: "operations_research::FlowQuantity") -> "operations_research::ArcIndex":
+        return _pywrapgraph.SimpleMaxFlow_AddArcWithCapacity(self, tail, head, capacity)
+
+    def NumNodes(self) -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMaxFlow_NumNodes(self)
+
+    def NumArcs(self) -> "operations_research::ArcIndex":
+        return _pywrapgraph.SimpleMaxFlow_NumArcs(self)
+
+    def Tail(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMaxFlow_Tail(self, arc)
+
+    def Head(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMaxFlow_Head(self, arc)
+
+    def Capacity(self, arc: "operations_research::ArcIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMaxFlow_Capacity(self, arc)
+    OPTIMAL = _pywrapgraph.SimpleMaxFlow_OPTIMAL
+    POSSIBLE_OVERFLOW = _pywrapgraph.SimpleMaxFlow_POSSIBLE_OVERFLOW
+    BAD_INPUT = _pywrapgraph.SimpleMaxFlow_BAD_INPUT
+    BAD_RESULT = _pywrapgraph.SimpleMaxFlow_BAD_RESULT
+
+    def Solve(self, source: "operations_research::NodeIndex", sink: "operations_research::NodeIndex") -> "operations_research::SimpleMaxFlow::Status":
+        return _pywrapgraph.SimpleMaxFlow_Solve(self, source, sink)
+
+    def OptimalFlow(self) -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMaxFlow_OptimalFlow(self)
+
+    def Flow(self, arc: "operations_research::ArcIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMaxFlow_Flow(self, arc)
+
+    def GetSourceSideMinCut(self) -> "void":
+        return _pywrapgraph.SimpleMaxFlow_GetSourceSideMinCut(self)
+
+    def GetSinkSideMinCut(self) -> "void":
+        return _pywrapgraph.SimpleMaxFlow_GetSinkSideMinCut(self)
+
+    def SetArcCapacity(self, arc: "operations_research::ArcIndex", capacity: "operations_research::FlowQuantity") -> "void":
+        return _pywrapgraph.SimpleMaxFlow_SetArcCapacity(self, arc, capacity)
+    __swig_destroy__ = _pywrapgraph.delete_SimpleMaxFlow
+
+ +
+ + + +
+
#   + + + SimpleMaxFlow() +
+ +
+ View Source +
    def __init__(self):
+        _pywrapgraph.SimpleMaxFlow_swiginit(self, _pywrapgraph.new_SimpleMaxFlow())
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + AddArcWithCapacity( + self, + tail: 'operations_research::NodeIndex', + head: 'operations_research::NodeIndex', + capacity: 'operations_research::FlowQuantity' +) -> 'operations_research::ArcIndex': +
+ +
+ View Source +
    def AddArcWithCapacity(self, tail: "operations_research::NodeIndex", head: "operations_research::NodeIndex", capacity: "operations_research::FlowQuantity") -> "operations_research::ArcIndex":
+        return _pywrapgraph.SimpleMaxFlow_AddArcWithCapacity(self, tail, head, capacity)
+
+ +
+ + + +
+
+
#   + + + def + NumNodes(self) -> 'operations_research::NodeIndex': +
+ +
+ View Source +
    def NumNodes(self) -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMaxFlow_NumNodes(self)
+
+ +
+ + + +
+
+
#   + + + def + NumArcs(self) -> 'operations_research::ArcIndex': +
+ +
+ View Source +
    def NumArcs(self) -> "operations_research::ArcIndex":
+        return _pywrapgraph.SimpleMaxFlow_NumArcs(self)
+
+ +
+ + + +
+
+
#   + + + def + Tail( + self, + arc: 'operations_research::ArcIndex' +) -> 'operations_research::NodeIndex': +
+ +
+ View Source +
    def Tail(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMaxFlow_Tail(self, arc)
+
+ +
+ + + +
+
+
#   + + + def + Head( + self, + arc: 'operations_research::ArcIndex' +) -> 'operations_research::NodeIndex': +
+ +
+ View Source +
    def Head(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMaxFlow_Head(self, arc)
+
+ +
+ + + +
+
+
#   + + + def + Capacity( + self, + arc: 'operations_research::ArcIndex' +) -> 'operations_research::FlowQuantity': +
+ +
+ View Source +
    def Capacity(self, arc: "operations_research::ArcIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMaxFlow_Capacity(self, arc)
+
+ +
+ + + +
+
+
#   + + OPTIMAL = 0 +
+ + + + +
+
+
#   + + POSSIBLE_OVERFLOW = 1 +
+ + + + +
+
+
#   + + BAD_INPUT = 2 +
+ + + + +
+
+
#   + + BAD_RESULT = 3 +
+ + + + +
+
+
#   + + + def + Solve( + self, + source: 'operations_research::NodeIndex', + sink: 'operations_research::NodeIndex' +) -> 'operations_research::SimpleMaxFlow::Status': +
+ +
+ View Source +
    def Solve(self, source: "operations_research::NodeIndex", sink: "operations_research::NodeIndex") -> "operations_research::SimpleMaxFlow::Status":
+        return _pywrapgraph.SimpleMaxFlow_Solve(self, source, sink)
+
+ +
+ + + +
+
+
#   + + + def + OptimalFlow(self) -> 'operations_research::FlowQuantity': +
+ +
+ View Source +
    def OptimalFlow(self) -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMaxFlow_OptimalFlow(self)
+
+ +
+ + + +
+
+
#   + + + def + Flow( + self, + arc: 'operations_research::ArcIndex' +) -> 'operations_research::FlowQuantity': +
+ +
+ View Source +
    def Flow(self, arc: "operations_research::ArcIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMaxFlow_Flow(self, arc)
+
+ +
+ + + +
+
+
#   + + + def + GetSourceSideMinCut(self) -> 'void': +
+ +
+ View Source +
    def GetSourceSideMinCut(self) -> "void":
+        return _pywrapgraph.SimpleMaxFlow_GetSourceSideMinCut(self)
+
+ +
+ + + +
+
+
#   + + + def + GetSinkSideMinCut(self) -> 'void': +
+ +
+ View Source +
    def GetSinkSideMinCut(self) -> "void":
+        return _pywrapgraph.SimpleMaxFlow_GetSinkSideMinCut(self)
+
+ +
+ + + +
+
+
#   + + + def + SetArcCapacity( + self, + arc: 'operations_research::ArcIndex', + capacity: 'operations_research::FlowQuantity' +) -> 'void': +
+ +
+ View Source +
    def SetArcCapacity(self, arc: "operations_research::ArcIndex", capacity: "operations_research::FlowQuantity") -> "void":
+        return _pywrapgraph.SimpleMaxFlow_SetArcCapacity(self, arc, capacity)
+
+ +
+ + + +
+
+
+
+ #   + + + class + MinCostFlowBase: +
+ +
+ View Source +
class MinCostFlowBase(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+    NOT_SOLVED = _pywrapgraph.MinCostFlowBase_NOT_SOLVED
+    OPTIMAL = _pywrapgraph.MinCostFlowBase_OPTIMAL
+    FEASIBLE = _pywrapgraph.MinCostFlowBase_FEASIBLE
+    INFEASIBLE = _pywrapgraph.MinCostFlowBase_INFEASIBLE
+    UNBALANCED = _pywrapgraph.MinCostFlowBase_UNBALANCED
+    BAD_RESULT = _pywrapgraph.MinCostFlowBase_BAD_RESULT
+    BAD_COST_RANGE = _pywrapgraph.MinCostFlowBase_BAD_COST_RANGE
+
+    def __init__(self):
+        _pywrapgraph.MinCostFlowBase_swiginit(self, _pywrapgraph.new_MinCostFlowBase())
+    __swig_destroy__ = _pywrapgraph.delete_MinCostFlowBase
+
+ +
+ + + +
+
#   + + + MinCostFlowBase() +
+ +
+ View Source +
    def __init__(self):
+        _pywrapgraph.MinCostFlowBase_swiginit(self, _pywrapgraph.new_MinCostFlowBase())
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + NOT_SOLVED = 0 +
+ + + + +
+
+
#   + + OPTIMAL = 1 +
+ + + + +
+
+
#   + + FEASIBLE = 2 +
+ + + + +
+
+
#   + + INFEASIBLE = 3 +
+ + + + +
+
+
#   + + UNBALANCED = 4 +
+ + + + +
+
+
#   + + BAD_RESULT = 5 +
+ + + + +
+
+
#   + + BAD_COST_RANGE = 6 +
+ + + + +
+
+
+
+ #   + + + class + SimpleMinCostFlow(MinCostFlowBase): +
+ +
+ View Source +
class SimpleMinCostFlow(MinCostFlowBase):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self, reserve_num_nodes: "operations_research::NodeIndex"=0, reserve_num_arcs: "operations_research::ArcIndex"=0):
+        _pywrapgraph.SimpleMinCostFlow_swiginit(self, _pywrapgraph.new_SimpleMinCostFlow(reserve_num_nodes, reserve_num_arcs))
+
+    def AddArcWithCapacityAndUnitCost(self, tail: "operations_research::NodeIndex", head: "operations_research::NodeIndex", capacity: "operations_research::FlowQuantity", unit_cost: "operations_research::CostValue") -> "operations_research::ArcIndex":
+        return _pywrapgraph.SimpleMinCostFlow_AddArcWithCapacityAndUnitCost(self, tail, head, capacity, unit_cost)
+
+    def SetNodeSupply(self, node: "operations_research::NodeIndex", supply: "operations_research::FlowQuantity") -> "void":
+        return _pywrapgraph.SimpleMinCostFlow_SetNodeSupply(self, node, supply)
+
+    def Solve(self) -> "operations_research::MinCostFlowBase::Status":
+        return _pywrapgraph.SimpleMinCostFlow_Solve(self)
+
+    def SolveMaxFlowWithMinCost(self) -> "operations_research::MinCostFlowBase::Status":
+        return _pywrapgraph.SimpleMinCostFlow_SolveMaxFlowWithMinCost(self)
+
+    def OptimalCost(self) -> "operations_research::CostValue":
+        return _pywrapgraph.SimpleMinCostFlow_OptimalCost(self)
+
+    def MaximumFlow(self) -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMinCostFlow_MaximumFlow(self)
+
+    def Flow(self, arc: "operations_research::ArcIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMinCostFlow_Flow(self, arc)
+
+    def NumNodes(self) -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMinCostFlow_NumNodes(self)
+
+    def NumArcs(self) -> "operations_research::ArcIndex":
+        return _pywrapgraph.SimpleMinCostFlow_NumArcs(self)
+
+    def Tail(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMinCostFlow_Tail(self, arc)
+
+    def Head(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMinCostFlow_Head(self, arc)
+
+    def Capacity(self, arc: "operations_research::ArcIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMinCostFlow_Capacity(self, arc)
+
+    def Supply(self, node: "operations_research::NodeIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMinCostFlow_Supply(self, node)
+
+    def UnitCost(self, arc: "operations_research::ArcIndex") -> "operations_research::CostValue":
+        return _pywrapgraph.SimpleMinCostFlow_UnitCost(self, arc)
+    __swig_destroy__ = _pywrapgraph.delete_SimpleMinCostFlow
+
+ +
+ + + +
+
#   + + + SimpleMinCostFlow( + reserve_num_nodes: 'operations_research::NodeIndex' = 0, + reserve_num_arcs: 'operations_research::ArcIndex' = 0 +) +
+ +
+ View Source +
    def __init__(self, reserve_num_nodes: "operations_research::NodeIndex"=0, reserve_num_arcs: "operations_research::ArcIndex"=0):
+        _pywrapgraph.SimpleMinCostFlow_swiginit(self, _pywrapgraph.new_SimpleMinCostFlow(reserve_num_nodes, reserve_num_arcs))
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + AddArcWithCapacityAndUnitCost( + self, + tail: 'operations_research::NodeIndex', + head: 'operations_research::NodeIndex', + capacity: 'operations_research::FlowQuantity', + unit_cost: 'operations_research::CostValue' +) -> 'operations_research::ArcIndex': +
+ +
+ View Source +
    def AddArcWithCapacityAndUnitCost(self, tail: "operations_research::NodeIndex", head: "operations_research::NodeIndex", capacity: "operations_research::FlowQuantity", unit_cost: "operations_research::CostValue") -> "operations_research::ArcIndex":
+        return _pywrapgraph.SimpleMinCostFlow_AddArcWithCapacityAndUnitCost(self, tail, head, capacity, unit_cost)
+
+ +
+ + + +
+
+
#   + + + def + SetNodeSupply( + self, + node: 'operations_research::NodeIndex', + supply: 'operations_research::FlowQuantity' +) -> 'void': +
+ +
+ View Source +
    def SetNodeSupply(self, node: "operations_research::NodeIndex", supply: "operations_research::FlowQuantity") -> "void":
+        return _pywrapgraph.SimpleMinCostFlow_SetNodeSupply(self, node, supply)
+
+ +
+ + + +
+
+
#   + + + def + Solve(self) -> 'operations_research::MinCostFlowBase::Status': +
+ +
+ View Source +
    def Solve(self) -> "operations_research::MinCostFlowBase::Status":
+        return _pywrapgraph.SimpleMinCostFlow_Solve(self)
+
+ +
+ + + +
+
+
#   + + + def + SolveMaxFlowWithMinCost(self) -> 'operations_research::MinCostFlowBase::Status': +
+ +
+ View Source +
    def SolveMaxFlowWithMinCost(self) -> "operations_research::MinCostFlowBase::Status":
+        return _pywrapgraph.SimpleMinCostFlow_SolveMaxFlowWithMinCost(self)
+
+ +
+ + + +
+
+
#   + + + def + OptimalCost(self) -> 'operations_research::CostValue': +
+ +
+ View Source +
    def OptimalCost(self) -> "operations_research::CostValue":
+        return _pywrapgraph.SimpleMinCostFlow_OptimalCost(self)
+
+ +
+ + + +
+
+
#   + + + def + MaximumFlow(self) -> 'operations_research::FlowQuantity': +
+ +
+ View Source +
    def MaximumFlow(self) -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMinCostFlow_MaximumFlow(self)
+
+ +
+ + + +
+
+
#   + + + def + Flow( + self, + arc: 'operations_research::ArcIndex' +) -> 'operations_research::FlowQuantity': +
+ +
+ View Source +
    def Flow(self, arc: "operations_research::ArcIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMinCostFlow_Flow(self, arc)
+
+ +
+ + + +
+
+
#   + + + def + NumNodes(self) -> 'operations_research::NodeIndex': +
+ +
+ View Source +
    def NumNodes(self) -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMinCostFlow_NumNodes(self)
+
+ +
+ + + +
+
+
#   + + + def + NumArcs(self) -> 'operations_research::ArcIndex': +
+ +
+ View Source +
    def NumArcs(self) -> "operations_research::ArcIndex":
+        return _pywrapgraph.SimpleMinCostFlow_NumArcs(self)
+
+ +
+ + + +
+
+
#   + + + def + Tail( + self, + arc: 'operations_research::ArcIndex' +) -> 'operations_research::NodeIndex': +
+ +
+ View Source +
    def Tail(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMinCostFlow_Tail(self, arc)
+
+ +
+ + + +
+
+
#   + + + def + Head( + self, + arc: 'operations_research::ArcIndex' +) -> 'operations_research::NodeIndex': +
+ +
+ View Source +
    def Head(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.SimpleMinCostFlow_Head(self, arc)
+
+ +
+ + + +
+
+
#   + + + def + Capacity( + self, + arc: 'operations_research::ArcIndex' +) -> 'operations_research::FlowQuantity': +
+ +
+ View Source +
    def Capacity(self, arc: "operations_research::ArcIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMinCostFlow_Capacity(self, arc)
+
+ +
+ + + +
+
+
#   + + + def + Supply( + self, + node: 'operations_research::NodeIndex' +) -> 'operations_research::FlowQuantity': +
+ +
+ View Source +
    def Supply(self, node: "operations_research::NodeIndex") -> "operations_research::FlowQuantity":
+        return _pywrapgraph.SimpleMinCostFlow_Supply(self, node)
+
+ +
+ + + +
+
+
#   + + + def + UnitCost( + self, + arc: 'operations_research::ArcIndex' +) -> 'operations_research::CostValue': +
+ +
+ View Source +
    def UnitCost(self, arc: "operations_research::ArcIndex") -> "operations_research::CostValue":
+        return _pywrapgraph.SimpleMinCostFlow_UnitCost(self, arc)
+
+ +
+ + + +
+ +
+
+
+ #   + + + class + LinearSumAssignment: +
+ +
+ View Source +
class LinearSumAssignment(object):
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self):
+        _pywrapgraph.LinearSumAssignment_swiginit(self, _pywrapgraph.new_LinearSumAssignment())
+
+    def AddArcWithCost(self, left_node: "operations_research::NodeIndex", right_node: "operations_research::NodeIndex", cost: "operations_research::CostValue") -> "operations_research::ArcIndex":
+        return _pywrapgraph.LinearSumAssignment_AddArcWithCost(self, left_node, right_node, cost)
+
+    def NumNodes(self) -> "operations_research::NodeIndex":
+        return _pywrapgraph.LinearSumAssignment_NumNodes(self)
+
+    def NumArcs(self) -> "operations_research::ArcIndex":
+        return _pywrapgraph.LinearSumAssignment_NumArcs(self)
+
+    def LeftNode(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.LinearSumAssignment_LeftNode(self, arc)
+
+    def RightNode(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.LinearSumAssignment_RightNode(self, arc)
+
+    def Cost(self, arc: "operations_research::ArcIndex") -> "operations_research::CostValue":
+        return _pywrapgraph.LinearSumAssignment_Cost(self, arc)
+    OPTIMAL = _pywrapgraph.LinearSumAssignment_OPTIMAL
+    INFEASIBLE = _pywrapgraph.LinearSumAssignment_INFEASIBLE
+    POSSIBLE_OVERFLOW = _pywrapgraph.LinearSumAssignment_POSSIBLE_OVERFLOW
+
+    def Solve(self) -> "operations_research::SimpleLinearSumAssignment::Status":
+        return _pywrapgraph.LinearSumAssignment_Solve(self)
+
+    def OptimalCost(self) -> "operations_research::CostValue":
+        return _pywrapgraph.LinearSumAssignment_OptimalCost(self)
+
+    def RightMate(self, left_node: "operations_research::NodeIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.LinearSumAssignment_RightMate(self, left_node)
+
+    def AssignmentCost(self, left_node: "operations_research::NodeIndex") -> "operations_research::CostValue":
+        return _pywrapgraph.LinearSumAssignment_AssignmentCost(self, left_node)
+    __swig_destroy__ = _pywrapgraph.delete_LinearSumAssignment
+
+ +
+ + + +
+
#   + + + LinearSumAssignment() +
+ +
+ View Source +
    def __init__(self):
+        _pywrapgraph.LinearSumAssignment_swiginit(self, _pywrapgraph.new_LinearSumAssignment())
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + AddArcWithCost( + self, + left_node: 'operations_research::NodeIndex', + right_node: 'operations_research::NodeIndex', + cost: 'operations_research::CostValue' +) -> 'operations_research::ArcIndex': +
+ +
+ View Source +
    def AddArcWithCost(self, left_node: "operations_research::NodeIndex", right_node: "operations_research::NodeIndex", cost: "operations_research::CostValue") -> "operations_research::ArcIndex":
+        return _pywrapgraph.LinearSumAssignment_AddArcWithCost(self, left_node, right_node, cost)
+
+ +
+ + + +
+
+
#   + + + def + NumNodes(self) -> 'operations_research::NodeIndex': +
+ +
+ View Source +
    def NumNodes(self) -> "operations_research::NodeIndex":
+        return _pywrapgraph.LinearSumAssignment_NumNodes(self)
+
+ +
+ + + +
+
+
#   + + + def + NumArcs(self) -> 'operations_research::ArcIndex': +
+ +
+ View Source +
    def NumArcs(self) -> "operations_research::ArcIndex":
+        return _pywrapgraph.LinearSumAssignment_NumArcs(self)
+
+ +
+ + + +
+
+
#   + + + def + LeftNode( + self, + arc: 'operations_research::ArcIndex' +) -> 'operations_research::NodeIndex': +
+ +
+ View Source +
    def LeftNode(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.LinearSumAssignment_LeftNode(self, arc)
+
+ +
+ + + +
+
+
#   + + + def + RightNode( + self, + arc: 'operations_research::ArcIndex' +) -> 'operations_research::NodeIndex': +
+ +
+ View Source +
    def RightNode(self, arc: "operations_research::ArcIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.LinearSumAssignment_RightNode(self, arc)
+
+ +
+ + + +
+
+
#   + + + def + Cost( + self, + arc: 'operations_research::ArcIndex' +) -> 'operations_research::CostValue': +
+ +
+ View Source +
    def Cost(self, arc: "operations_research::ArcIndex") -> "operations_research::CostValue":
+        return _pywrapgraph.LinearSumAssignment_Cost(self, arc)
+
+ +
+ + + +
+
+
#   + + OPTIMAL = 0 +
+ + + + +
+
+
#   + + INFEASIBLE = 1 +
+ + + + +
+
+
#   + + POSSIBLE_OVERFLOW = 2 +
+ + + + +
+
+
#   + + + def + Solve(self) -> 'operations_research::SimpleLinearSumAssignment::Status': +
+ +
+ View Source +
    def Solve(self) -> "operations_research::SimpleLinearSumAssignment::Status":
+        return _pywrapgraph.LinearSumAssignment_Solve(self)
+
+ +
+ + + +
+
+
#   + + + def + OptimalCost(self) -> 'operations_research::CostValue': +
+ +
+ View Source +
    def OptimalCost(self) -> "operations_research::CostValue":
+        return _pywrapgraph.LinearSumAssignment_OptimalCost(self)
+
+ +
+ + + +
+
+
#   + + + def + RightMate( + self, + left_node: 'operations_research::NodeIndex' +) -> 'operations_research::NodeIndex': +
+ +
+ View Source +
    def RightMate(self, left_node: "operations_research::NodeIndex") -> "operations_research::NodeIndex":
+        return _pywrapgraph.LinearSumAssignment_RightMate(self, left_node)
+
+ +
+ + + +
+
+
#   + + + def + AssignmentCost( + self, + left_node: 'operations_research::NodeIndex' +) -> 'operations_research::CostValue': +
+ +
+ View Source +
    def AssignmentCost(self, left_node: "operations_research::NodeIndex") -> "operations_research::CostValue":
+        return _pywrapgraph.LinearSumAssignment_AssignmentCost(self, left_node)
+
+ +
+ + + +
+
+
+
#   + + + def + DijkstraShortestPath( + node_count: int, + start_node: int, + end_node: int, + graph: 'std::function< int64_t (int,int) >', + disconnected_distance: 'int64_t' +) -> 'std::vector< int > *': +
+ +
+ View Source +
def DijkstraShortestPath(node_count: "int", start_node: "int", end_node: "int", graph: "std::function< int64_t (int,int) >", disconnected_distance: "int64_t") -> "std::vector< int > *":
+    return _pywrapgraph.DijkstraShortestPath(node_count, start_node, end_node, graph, disconnected_distance)
+
+ +
+ + + +
+
+
#   + + + def + BellmanFordShortestPath( + node_count: int, + start_node: int, + end_node: int, + graph: 'std::function< int64_t (int,int) >', + disconnected_distance: 'int64_t' +) -> 'std::vector< int > *': +
+ +
+ View Source +
def BellmanFordShortestPath(node_count: "int", start_node: "int", end_node: "int", graph: "std::function< int64_t (int,int) >", disconnected_distance: "int64_t") -> "std::vector< int > *":
+    return _pywrapgraph.BellmanFordShortestPath(node_count, start_node, end_node, graph, disconnected_distance)
+
+ +
+ + + +
+
+
#   + + + def + AStarShortestPath( + node_count: int, + start_node: int, + end_node: int, + graph: 'std::function< int64_t (int,int) >', + heuristic: 'std::function< int64_t (int) >', + disconnected_distance: 'int64_t' +) -> 'std::vector< int > *': +
+ +
+ View Source +
def AStarShortestPath(node_count: "int", start_node: "int", end_node: "int", graph: "std::function< int64_t (int,int) >", heuristic: "std::function< int64_t (int) >", disconnected_distance: "int64_t") -> "std::vector< int > *":
+    return _pywrapgraph.AStarShortestPath(node_count, start_node, end_node, graph, heuristic, disconnected_distance)
+
+ +
+ + + +
+
+ + \ No newline at end of file diff --git a/docs/python/ortools/linear_solver/index.html b/docs/python/ortools/linear_solver/index.html index d9f2a731dc..9eb7e9fc1e 100644 --- a/docs/python/ortools/linear_solver/index.html +++ b/docs/python/ortools/linear_solver/index.html @@ -1,58 +1,7 @@ - + - - - Module List – pdoc 8.0.0 - - - - - - - - + - -
- - pdoc logo - -
-
-
- - \ No newline at end of file + diff --git a/docs/python/ortools/linear_solver/ortools/linear_solver/pywraplp.html b/docs/python/ortools/linear_solver/ortools/linear_solver/pywraplp.html new file mode 100644 index 0000000000..5c0ef11848 --- /dev/null +++ b/docs/python/ortools/linear_solver/ortools/linear_solver/pywraplp.html @@ -0,0 +1,6407 @@ + + + + + + + ortools.linear_solver.pywraplp API documentation + + + + + + + + + +
+
+

+ortools.linear_solver.pywraplp

+ + +
+ View Source +
# This file was automatically generated by SWIG (http://www.swig.org).
+# Version 4.0.2
+#
+# Do not make changes to this file unless you know what you are doing--modify
+# the SWIG interface file instead.
+
+from sys import version_info as _swig_python_version_info
+if _swig_python_version_info < (2, 7, 0):
+    raise RuntimeError("Python 2.7 or later required")
+
+# Import the low-level C/C++ module
+if __package__ or "." in __name__:
+    from . import _pywraplp
+else:
+    import _pywraplp
+
+try:
+    import builtins as __builtin__
+except ImportError:
+    import __builtin__
+
+def _swig_repr(self):
+    try:
+        strthis = "proxy of " + self.this.__repr__()
+    except __builtin__.Exception:
+        strthis = ""
+    return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+
+def _swig_setattr_nondynamic_instance_variable(set):
+    def set_instance_attr(self, name, value):
+        if name == "thisown":
+            self.this.own(value)
+        elif name == "this":
+            set(self, name, value)
+        elif hasattr(self, name) and isinstance(getattr(type(self), name), property):
+            set(self, name, value)
+        else:
+            raise AttributeError("You cannot add instance attributes to %s" % self)
+    return set_instance_attr
+
+
+def _swig_setattr_nondynamic_class_variable(set):
+    def set_class_attr(cls, name, value):
+        if hasattr(cls, name) and not isinstance(getattr(cls, name), property):
+            set(cls, name, value)
+        else:
+            raise AttributeError("You cannot add class attributes to %s" % cls)
+    return set_class_attr
+
+
+def _swig_add_metaclass(metaclass):
+    """Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass"""
+    def wrapper(cls):
+        return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy())
+    return wrapper
+
+
+class _SwigNonDynamicMeta(type):
+    """Meta class to enforce nondynamic attributes (no new attributes) for a class"""
+    __setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__)
+
+
+
+import numbers
+from ortools.linear_solver.linear_solver_natural_api import OFFSET_KEY
+from ortools.linear_solver.linear_solver_natural_api import inf
+from ortools.linear_solver.linear_solver_natural_api import LinearExpr
+from ortools.linear_solver.linear_solver_natural_api import ProductCst
+from ortools.linear_solver.linear_solver_natural_api import Sum
+from ortools.linear_solver.linear_solver_natural_api import SumArray
+from ortools.linear_solver.linear_solver_natural_api import SumCst
+from ortools.linear_solver.linear_solver_natural_api import LinearConstraint
+from ortools.linear_solver.linear_solver_natural_api import VariableExpr
+
+class Solver(object):
+    r"""
+    This mathematical programming (MP) solver class is the main class
+    though which users build and solve problems.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+    CLP_LINEAR_PROGRAMMING = _pywraplp.Solver_CLP_LINEAR_PROGRAMMING
+    GLPK_LINEAR_PROGRAMMING = _pywraplp.Solver_GLPK_LINEAR_PROGRAMMING
+    GLOP_LINEAR_PROGRAMMING = _pywraplp.Solver_GLOP_LINEAR_PROGRAMMING
+    PDLP_LINEAR_PROGRAMMING = _pywraplp.Solver_PDLP_LINEAR_PROGRAMMING
+    SCIP_MIXED_INTEGER_PROGRAMMING = _pywraplp.Solver_SCIP_MIXED_INTEGER_PROGRAMMING
+    GLPK_MIXED_INTEGER_PROGRAMMING = _pywraplp.Solver_GLPK_MIXED_INTEGER_PROGRAMMING
+    CBC_MIXED_INTEGER_PROGRAMMING = _pywraplp.Solver_CBC_MIXED_INTEGER_PROGRAMMING
+    GUROBI_LINEAR_PROGRAMMING = _pywraplp.Solver_GUROBI_LINEAR_PROGRAMMING
+    GUROBI_MIXED_INTEGER_PROGRAMMING = _pywraplp.Solver_GUROBI_MIXED_INTEGER_PROGRAMMING
+    CPLEX_LINEAR_PROGRAMMING = _pywraplp.Solver_CPLEX_LINEAR_PROGRAMMING
+    CPLEX_MIXED_INTEGER_PROGRAMMING = _pywraplp.Solver_CPLEX_MIXED_INTEGER_PROGRAMMING
+    XPRESS_LINEAR_PROGRAMMING = _pywraplp.Solver_XPRESS_LINEAR_PROGRAMMING
+    XPRESS_MIXED_INTEGER_PROGRAMMING = _pywraplp.Solver_XPRESS_MIXED_INTEGER_PROGRAMMING
+    BOP_INTEGER_PROGRAMMING = _pywraplp.Solver_BOP_INTEGER_PROGRAMMING
+    SAT_INTEGER_PROGRAMMING = _pywraplp.Solver_SAT_INTEGER_PROGRAMMING
+
+    def __init__(self, name: "std::string const &", problem_type: "operations_research::MPSolver::OptimizationProblemType"):
+        r""" Create a solver with the given name and underlying solver backend."""
+        _pywraplp.Solver_swiginit(self, _pywraplp.new_Solver(name, problem_type))
+    __swig_destroy__ = _pywraplp.delete_Solver
+
+    @staticmethod
+    def CreateSolver(solver_id: "std::string const &") -> "operations_research::MPSolver *":
+        r"""
+        Recommended factory method to create a MPSolver instance, especially in
+        non C++ languages.
+
+        It returns a newly created solver instance if successful, or a nullptr
+        otherwise. This can occur if the relevant interface is not linked in, or if
+        a needed license is not accessible for commercial solvers.
+
+        Ownership of the solver is passed on to the caller of this method.
+        It will accept both string names of the OptimizationProblemType enum, as
+        well as a short version (i.e. "SCIP_MIXED_INTEGER_PROGRAMMING" or "SCIP").
+
+        solver_id is case insensitive, and the following names are supported:
+          - CLP_LINEAR_PROGRAMMING or CLP
+          - CBC_MIXED_INTEGER_PROGRAMMING or CBC
+          - GLOP_LINEAR_PROGRAMMING or GLOP
+          - BOP_INTEGER_PROGRAMMING or BOP
+          - SAT_INTEGER_PROGRAMMING or SAT or CP_SAT
+          - SCIP_MIXED_INTEGER_PROGRAMMING or SCIP
+          - GUROBI_LINEAR_PROGRAMMING or GUROBI_LP
+          - GUROBI_MIXED_INTEGER_PROGRAMMING or GUROBI or GUROBI_MIP
+          - CPLEX_LINEAR_PROGRAMMING or CPLEX_LP
+          - CPLEX_MIXED_INTEGER_PROGRAMMING or CPLEX or CPLEX_MIP
+          - XPRESS_LINEAR_PROGRAMMING or XPRESS_LP
+          - XPRESS_MIXED_INTEGER_PROGRAMMING or XPRESS or XPRESS_MIP
+          - GLPK_LINEAR_PROGRAMMING or GLPK_LP
+          - GLPK_MIXED_INTEGER_PROGRAMMING or GLPK or GLPK_MIP
+        """
+        return _pywraplp.Solver_CreateSolver(solver_id)
+
+    @staticmethod
+    def SupportsProblemType(problem_type: "operations_research::MPSolver::OptimizationProblemType") -> "bool":
+        r"""
+        Whether the given problem type is supported (this will depend on the
+        targets that you linked).
+        """
+        return _pywraplp.Solver_SupportsProblemType(problem_type)
+
+    def Clear(self) -> "void":
+        r"""
+        Clears the objective (including the optimization direction), all variables
+        and constraints. All the other properties of the MPSolver (like the time
+        limit) are kept untouched.
+        """
+        return _pywraplp.Solver_Clear(self)
+
+    def NumVariables(self) -> "int":
+        r""" Returns the number of variables."""
+        return _pywraplp.Solver_NumVariables(self)
+
+    def variables(self) -> "std::vector< operations_research::MPVariable * > const &":
+        r"""
+        Returns the array of variables handled by the MPSolver. (They are listed in
+        the order in which they were created.)
+        """
+        return _pywraplp.Solver_variables(self)
+
+    def variable(self, index: "int") -> "operations_research::MPVariable *":
+        r"""Returns the variable at position index."""
+        return _pywraplp.Solver_variable(self, index)
+
+    def LookupVariable(self, var_name: "std::string const &") -> "operations_research::MPVariable *":
+        r"""
+        Looks up a variable by name, and returns nullptr if it does not exist. The
+        first call has a O(n) complexity, as the variable name index is lazily
+        created upon first use. Will crash if variable names are not unique.
+        """
+        return _pywraplp.Solver_LookupVariable(self, var_name)
+
+    def Var(self, lb: "double", ub: "double", integer: "bool", name: "std::string const &") -> "operations_research::MPVariable *":
+        r"""
+        Creates a variable with the given bounds, integrality requirement and
+        name. Bounds can be finite or +/- MPSolver::infinity(). The MPSolver owns
+        the variable (i.e. the returned pointer is borrowed). Variable names are
+        optional. If you give an empty name, name() will auto-generate one for you
+        upon request.
+        """
+        return _pywraplp.Solver_Var(self, lb, ub, integer, name)
+
+    def NumVar(self, lb: "double", ub: "double", name: "std::string const &") -> "operations_research::MPVariable *":
+        r""" Creates a continuous variable."""
+        return _pywraplp.Solver_NumVar(self, lb, ub, name)
+
+    def IntVar(self, lb: "double", ub: "double", name: "std::string const &") -> "operations_research::MPVariable *":
+        r""" Creates an integer variable."""
+        return _pywraplp.Solver_IntVar(self, lb, ub, name)
+
+    def BoolVar(self, name: "std::string const &") -> "operations_research::MPVariable *":
+        r""" Creates a boolean variable."""
+        return _pywraplp.Solver_BoolVar(self, name)
+
+    def NumConstraints(self) -> "int":
+        r""" Returns the number of constraints."""
+        return _pywraplp.Solver_NumConstraints(self)
+
+    def constraints(self) -> "std::vector< operations_research::MPConstraint * > const &":
+        r"""
+        Returns the array of constraints handled by the MPSolver.
+
+        They are listed in the order in which they were created.
+        """
+        return _pywraplp.Solver_constraints(self)
+
+    def constraint(self, index: "int") -> "operations_research::MPConstraint *":
+        r""" Returns the constraint at the given index."""
+        return _pywraplp.Solver_constraint(self, index)
+
+    def LookupConstraint(self, constraint_name: "std::string const &") -> "operations_research::MPConstraint *":
+        r"""
+         Looks up a constraint by name, and returns nullptr if it does not exist.
+
+        The first call has a O(n) complexity, as the constraint name index is
+        lazily created upon first use. Will crash if constraint names are not
+        unique.
+        """
+        return _pywraplp.Solver_LookupConstraint(self, constraint_name)
+
+    def Constraint(self, *args) -> "operations_research::MPConstraint *":
+        r"""
+        *Overload 1:*
+
+        Creates a linear constraint with given bounds.
+
+        Bounds can be finite or +/- MPSolver::infinity(). The MPSolver class
+        assumes ownership of the constraint.
+
+        :rtype: :py:class:`MPConstraint`
+        :return: a pointer to the newly created constraint.
+
+        |
+
+        *Overload 2:*
+         Creates a constraint with -infinity and +infinity bounds.
+
+        |
+
+        *Overload 3:*
+         Creates a named constraint with given bounds.
+
+        |
+
+        *Overload 4:*
+         Creates a named constraint with -infinity and +infinity bounds.
+        """
+        return _pywraplp.Solver_Constraint(self, *args)
+
+    def Objective(self) -> "operations_research::MPObjective *":
+        r""" Returns the mutable objective object."""
+        return _pywraplp.Solver_Objective(self)
+    OPTIMAL = _pywraplp.Solver_OPTIMAL
+    r""" optimal."""
+    FEASIBLE = _pywraplp.Solver_FEASIBLE
+    r""" feasible, or stopped by limit."""
+    INFEASIBLE = _pywraplp.Solver_INFEASIBLE
+    r""" proven infeasible."""
+    UNBOUNDED = _pywraplp.Solver_UNBOUNDED
+    r""" proven unbounded."""
+    ABNORMAL = _pywraplp.Solver_ABNORMAL
+    r""" abnormal, i.e., error of some kind."""
+    NOT_SOLVED = _pywraplp.Solver_NOT_SOLVED
+    r""" not been solved yet."""
+
+    def Solve(self, *args) -> "operations_research::MPSolver::ResultStatus":
+        r"""
+        *Overload 1:*
+        Solves the problem using the default parameter values.
+
+        |
+
+        *Overload 2:*
+        Solves the problem using the specified parameter values.
+        """
+        return _pywraplp.Solver_Solve(self, *args)
+
+    def ComputeConstraintActivities(self) -> "std::vector< double >":
+        r"""
+        Advanced usage: compute the "activities" of all constraints, which are the
+        sums of their linear terms. The activities are returned in the same order
+        as constraints(), which is the order in which constraints were added; but
+        you can also use MPConstraint::index() to get a constraint's index.
+        """
+        return _pywraplp.Solver_ComputeConstraintActivities(self)
+
+    def VerifySolution(self, tolerance: "double", log_errors: "bool") -> "bool":
+        r"""
+        Advanced usage: Verifies the *correctness* of the solution.
+
+        It verifies that all variables must be within their domains, all
+        constraints must be satisfied, and the reported objective value must be
+        accurate.
+
+        Usage:
+        - This can only be called after Solve() was called.
+        - "tolerance" is interpreted as an absolute error threshold.
+        - For the objective value only, if the absolute error is too large,
+          the tolerance is interpreted as a relative error threshold instead.
+        - If "log_errors" is true, every single violation will be logged.
+        - If "tolerance" is negative, it will be set to infinity().
+
+        Most users should just set the --verify_solution flag and not bother using
+        this method directly.
+        """
+        return _pywraplp.Solver_VerifySolution(self, tolerance, log_errors)
+
+    def InterruptSolve(self) -> "bool":
+        r"""
+         Interrupts the Solve() execution to terminate processing if possible.
+
+        If the underlying interface supports interruption; it does that and returns
+        true regardless of whether there's an ongoing Solve() or not. The Solve()
+        call may still linger for a while depending on the conditions.  If
+        interruption is not supported; returns false and does nothing.
+        MPSolver::SolverTypeSupportsInterruption can be used to check if
+        interruption is supported for a given solver type.
+        """
+        return _pywraplp.Solver_InterruptSolve(self)
+
+    def FillSolutionResponseProto(self, response: "operations_research::MPSolutionResponse *") -> "void":
+        r""" Encodes the current solution in a solution response protocol buffer."""
+        return _pywraplp.Solver_FillSolutionResponseProto(self, response)
+
+    @staticmethod
+    def SolveWithProto(model_request: "operations_research::MPModelRequest const &", response: "operations_research::MPSolutionResponse *", interrupt: "std::atomic< bool > *"=None) -> "operations_research::MPSolutionResponse *":
+        r"""
+        Solves the model encoded by a MPModelRequest protocol buffer and fills the
+        solution encoded as a MPSolutionResponse. The solve is stopped prematurely
+        if interrupt is non-null at set to true during (or before) solving.
+        Interruption is only supported if SolverTypeSupportsInterruption() returns
+        true for the requested solver. Passing a non-null interruption with any
+        other solver type immediately returns an MPSOLVER_INCOMPATIBLE_OPTIONS
+        error.
+
+        Note(user): This attempts to first use `DirectlySolveProto()` (if
+        implemented). Consequently, this most likely does *not* override any of
+        the default parameters of the underlying solver. This behavior *differs*
+        from `MPSolver::Solve()` which by default sets the feasibility tolerance
+        and the gap limit (as of 2020/02/11, to 1e-7 and 0.0001, respectively).
+        """
+        return _pywraplp.Solver_SolveWithProto(model_request, response, interrupt)
+
+    def ExportModelToProto(self, output_model: "operations_research::MPModelProto *") -> "void":
+        r""" Exports model to protocol buffer."""
+        return _pywraplp.Solver_ExportModelToProto(self, output_model)
+
+    def SetSolverSpecificParametersAsString(self, parameters: "std::string const &") -> "bool":
+        r"""
+        Advanced usage: pass solver specific parameters in text format.
+
+        The format is solver-specific and is the same as the corresponding solver
+        configuration file format. Returns true if the operation was successful.
+        """
+        return _pywraplp.Solver_SetSolverSpecificParametersAsString(self, parameters)
+    FREE = _pywraplp.Solver_FREE
+    AT_LOWER_BOUND = _pywraplp.Solver_AT_LOWER_BOUND
+    AT_UPPER_BOUND = _pywraplp.Solver_AT_UPPER_BOUND
+    FIXED_VALUE = _pywraplp.Solver_FIXED_VALUE
+    BASIC = _pywraplp.Solver_BASIC
+
+    @staticmethod
+    def infinity() -> "double":
+        r"""
+        Infinity.
+
+        You can use -MPSolver::infinity() for negative infinity.
+        """
+        return _pywraplp.Solver_infinity()
+
+    def EnableOutput(self) -> "void":
+        r""" Enables solver logging."""
+        return _pywraplp.Solver_EnableOutput(self)
+
+    def SuppressOutput(self) -> "void":
+        r""" Suppresses solver logging."""
+        return _pywraplp.Solver_SuppressOutput(self)
+
+    def iterations(self) -> "int64_t":
+        r""" Returns the number of simplex iterations."""
+        return _pywraplp.Solver_iterations(self)
+
+    def nodes(self) -> "int64_t":
+        r"""
+        Returns the number of branch-and-bound nodes evaluated during the solve.
+
+        Only available for discrete problems.
+        """
+        return _pywraplp.Solver_nodes(self)
+
+    def ComputeExactConditionNumber(self) -> "double":
+        r"""
+         Advanced usage: computes the exact condition number of the current scaled
+        basis: L1norm(B) * L1norm(inverse(B)), where B is the scaled basis.
+
+        This method requires that a basis exists: it should be called after Solve.
+        It is only available for continuous problems. It is implemented for GLPK
+        but not CLP because CLP does not provide the API for doing it.
+
+        The condition number measures how well the constraint matrix is conditioned
+        and can be used to predict whether numerical issues will arise during the
+        solve: the model is declared infeasible whereas it is feasible (or
+        vice-versa), the solution obtained is not optimal or violates some
+        constraints, the resolution is slow because of repeated singularities.
+
+        The rule of thumb to interpret the condition number kappa is:
+          - o kappa <= 1e7: virtually no chance of numerical issues
+          - o 1e7 < kappa <= 1e10: small chance of numerical issues
+          - o 1e10 < kappa <= 1e13: medium chance of numerical issues
+          - o kappa > 1e13: high chance of numerical issues
+
+        The computation of the condition number depends on the quality of the LU
+        decomposition, so it is not very accurate when the matrix is ill
+        conditioned.
+        """
+        return _pywraplp.Solver_ComputeExactConditionNumber(self)
+
+    def NextSolution(self) -> "bool":
+        r"""
+        Some solvers (MIP only, not LP) can produce multiple solutions to the
+        problem. Returns true when another solution is available, and updates the
+        MPVariable* objects to make the new solution queryable. Call only after
+        calling solve.
+
+        The optimality properties of the additional solutions found, and whether or
+        not the solver computes them ahead of time or when NextSolution() is called
+        is solver specific.
+
+        As of 2020-02-10, only Gurobi and SCIP support NextSolution(), see
+        linear_solver_interfaces_test for an example of how to configure these
+        solvers for multiple solutions. Other solvers return false unconditionally.
+        """
+        return _pywraplp.Solver_NextSolution(self)
+
+    def set_time_limit(self, time_limit_milliseconds: "int64_t") -> "void":
+        return _pywraplp.Solver_set_time_limit(self, time_limit_milliseconds)
+
+    def wall_time(self) -> "int64_t":
+        return _pywraplp.Solver_wall_time(self)
+
+    def LoadModelFromProto(self, input_model: "operations_research::MPModelProto const &") -> "std::string":
+        return _pywraplp.Solver_LoadModelFromProto(self, input_model)
+
+    def LoadModelFromProtoWithUniqueNamesOrDie(self, input_model: "operations_research::MPModelProto const &") -> "std::string":
+        return _pywraplp.Solver_LoadModelFromProtoWithUniqueNamesOrDie(self, input_model)
+
+    def LoadSolutionFromProto(self, *args) -> "bool":
+        return _pywraplp.Solver_LoadSolutionFromProto(self, *args)
+
+    def ExportModelAsLpFormat(self, obfuscated: "bool") -> "std::string":
+        return _pywraplp.Solver_ExportModelAsLpFormat(self, obfuscated)
+
+    def ExportModelAsMpsFormat(self, fixed_format: "bool", obfuscated: "bool") -> "std::string":
+        return _pywraplp.Solver_ExportModelAsMpsFormat(self, fixed_format, obfuscated)
+
+    def SetHint(self, variables: "std::vector< operations_research::MPVariable * > const &", values: "std::vector< double > const &") -> "void":
+        r"""
+        Set a hint for solution.
+
+        If a feasible or almost-feasible solution to the problem is already known,
+        it may be helpful to pass it to the solver so that it can be used. A
+        solver that supports this feature will try to use this information to
+        create its initial feasible solution.
+
+        Note that it may not always be faster to give a hint like this to the
+        solver. There is also no guarantee that the solver will use this hint or
+        try to return a solution "close" to this assignment in case of multiple
+        optimal solutions.
+        """
+        return _pywraplp.Solver_SetHint(self, variables, values)
+
+    def SetNumThreads(self, num_theads: "int") -> "bool":
+        r""" Sets the number of threads to be used by the solver."""
+        return _pywraplp.Solver_SetNumThreads(self, num_theads)
+
+    def Add(self, constraint, name=''):
+      if isinstance(constraint, bool):
+        if constraint:
+          return self.RowConstraint(0, 0, name)
+        else:
+          return self.RowConstraint(1, 1, name)
+      else:
+        return constraint.Extract(self, name)
+
+    def Sum(self, expr_array):
+      result = SumArray(expr_array)
+      return result
+
+    def RowConstraint(self, *args):
+      return self.Constraint(*args)
+
+    def Minimize(self, expr):
+      objective = self.Objective()
+      objective.Clear()
+      objective.SetMinimization()
+      if isinstance(expr, numbers.Number):
+          objective.SetOffset(expr)
+      else:
+          coeffs = expr.GetCoeffs()
+          objective.SetOffset(coeffs.pop(OFFSET_KEY, 0.0))
+          for v, c, in list(coeffs.items()):
+            objective.SetCoefficient(v, float(c))
+
+    def Maximize(self, expr):
+      objective = self.Objective()
+      objective.Clear()
+      objective.SetMaximization()
+      if isinstance(expr, numbers.Number):
+          objective.SetOffset(expr)
+      else:
+          coeffs = expr.GetCoeffs()
+          objective.SetOffset(coeffs.pop(OFFSET_KEY, 0.0))
+          for v, c, in list(coeffs.items()):
+            objective.SetCoefficient(v, float(c))
+
+
+    @staticmethod
+    def Infinity() -> "double":
+        return _pywraplp.Solver_Infinity()
+
+    def SetTimeLimit(self, x: "int64_t") -> "void":
+        return _pywraplp.Solver_SetTimeLimit(self, x)
+
+    def WallTime(self) -> "int64_t":
+        return _pywraplp.Solver_WallTime(self)
+
+    def Iterations(self) -> "int64_t":
+        return _pywraplp.Solver_Iterations(self)
+
+# Register Solver in _pywraplp:
+_pywraplp.Solver_swigregister(Solver)
+
+def Solver_CreateSolver(solver_id: "std::string const &") -> "operations_research::MPSolver *":
+    r"""
+    Recommended factory method to create a MPSolver instance, especially in
+    non C++ languages.
+
+    It returns a newly created solver instance if successful, or a nullptr
+    otherwise. This can occur if the relevant interface is not linked in, or if
+    a needed license is not accessible for commercial solvers.
+
+    Ownership of the solver is passed on to the caller of this method.
+    It will accept both string names of the OptimizationProblemType enum, as
+    well as a short version (i.e. "SCIP_MIXED_INTEGER_PROGRAMMING" or "SCIP").
+
+    solver_id is case insensitive, and the following names are supported:
+      - CLP_LINEAR_PROGRAMMING or CLP
+      - CBC_MIXED_INTEGER_PROGRAMMING or CBC
+      - GLOP_LINEAR_PROGRAMMING or GLOP
+      - BOP_INTEGER_PROGRAMMING or BOP
+      - SAT_INTEGER_PROGRAMMING or SAT or CP_SAT
+      - SCIP_MIXED_INTEGER_PROGRAMMING or SCIP
+      - GUROBI_LINEAR_PROGRAMMING or GUROBI_LP
+      - GUROBI_MIXED_INTEGER_PROGRAMMING or GUROBI or GUROBI_MIP
+      - CPLEX_LINEAR_PROGRAMMING or CPLEX_LP
+      - CPLEX_MIXED_INTEGER_PROGRAMMING or CPLEX or CPLEX_MIP
+      - XPRESS_LINEAR_PROGRAMMING or XPRESS_LP
+      - XPRESS_MIXED_INTEGER_PROGRAMMING or XPRESS or XPRESS_MIP
+      - GLPK_LINEAR_PROGRAMMING or GLPK_LP
+      - GLPK_MIXED_INTEGER_PROGRAMMING or GLPK or GLPK_MIP
+    """
+    return _pywraplp.Solver_CreateSolver(solver_id)
+
+def Solver_SupportsProblemType(problem_type: "operations_research::MPSolver::OptimizationProblemType") -> "bool":
+    r"""
+    Whether the given problem type is supported (this will depend on the
+    targets that you linked).
+    """
+    return _pywraplp.Solver_SupportsProblemType(problem_type)
+
+def Solver_SolveWithProto(model_request: "operations_research::MPModelRequest const &", response: "operations_research::MPSolutionResponse *", interrupt: "std::atomic< bool > *"=None) -> "operations_research::MPSolutionResponse *":
+    r"""
+    Solves the model encoded by a MPModelRequest protocol buffer and fills the
+    solution encoded as a MPSolutionResponse. The solve is stopped prematurely
+    if interrupt is non-null at set to true during (or before) solving.
+    Interruption is only supported if SolverTypeSupportsInterruption() returns
+    true for the requested solver. Passing a non-null interruption with any
+    other solver type immediately returns an MPSOLVER_INCOMPATIBLE_OPTIONS
+    error.
+
+    Note(user): This attempts to first use `DirectlySolveProto()` (if
+    implemented). Consequently, this most likely does *not* override any of
+    the default parameters of the underlying solver. This behavior *differs*
+    from `MPSolver::Solve()` which by default sets the feasibility tolerance
+    and the gap limit (as of 2020/02/11, to 1e-7 and 0.0001, respectively).
+    """
+    return _pywraplp.Solver_SolveWithProto(model_request, response, interrupt)
+
+def Solver_infinity() -> "double":
+    r"""
+    Infinity.
+
+    You can use -MPSolver::infinity() for negative infinity.
+    """
+    return _pywraplp.Solver_infinity()
+
+def Solver_Infinity() -> "double":
+    return _pywraplp.Solver_Infinity()
+
+
+def __lshift__(*args) -> "std::ostream &":
+    return _pywraplp.__lshift__(*args)
+class Objective(object):
+    r""" A class to express a linear objective."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Clear(self) -> "void":
+        r"""
+         Clears the offset, all variables and coefficients, and the optimization
+        direction.
+        """
+        return _pywraplp.Objective_Clear(self)
+
+    def SetCoefficient(self, var: "Variable", coeff: "double") -> "void":
+        r"""
+        Sets the coefficient of the variable in the objective.
+
+        If the variable does not belong to the solver, the function just returns,
+        or crashes in non-opt mode.
+        """
+        return _pywraplp.Objective_SetCoefficient(self, var, coeff)
+
+    def GetCoefficient(self, var: "Variable") -> "double":
+        r"""
+         Gets the coefficient of a given variable in the objective
+
+        It returns 0 if the variable does not appear in the objective).
+        """
+        return _pywraplp.Objective_GetCoefficient(self, var)
+
+    def SetOffset(self, value: "double") -> "void":
+        r""" Sets the constant term in the objective."""
+        return _pywraplp.Objective_SetOffset(self, value)
+
+    def offset(self) -> "double":
+        r""" Gets the constant term in the objective."""
+        return _pywraplp.Objective_offset(self)
+
+    def SetOptimizationDirection(self, maximize: "bool") -> "void":
+        r""" Sets the optimization direction (maximize: true or minimize: false)."""
+        return _pywraplp.Objective_SetOptimizationDirection(self, maximize)
+
+    def SetMinimization(self) -> "void":
+        r""" Sets the optimization direction to minimize."""
+        return _pywraplp.Objective_SetMinimization(self)
+
+    def SetMaximization(self) -> "void":
+        r""" Sets the optimization direction to maximize."""
+        return _pywraplp.Objective_SetMaximization(self)
+
+    def maximization(self) -> "bool":
+        r""" Is the optimization direction set to maximize?"""
+        return _pywraplp.Objective_maximization(self)
+
+    def minimization(self) -> "bool":
+        r""" Is the optimization direction set to minimize?"""
+        return _pywraplp.Objective_minimization(self)
+
+    def Value(self) -> "double":
+        r"""
+        Returns the objective value of the best solution found so far.
+
+        It is the optimal objective value if the problem has been solved to
+        optimality.
+
+        Note: the objective value may be slightly different than what you could
+        compute yourself using ``MPVariable::solution_value();`` please use the
+        --verify_solution flag to gain confidence about the numerical stability of
+        your solution.
+        """
+        return _pywraplp.Objective_Value(self)
+
+    def BestBound(self) -> "double":
+        r"""
+        Returns the best objective bound.
+
+        In case of minimization, it is a lower bound on the objective value of the
+        optimal integer solution. Only available for discrete problems.
+        """
+        return _pywraplp.Objective_BestBound(self)
+
+    def Offset(self) -> "double":
+        return _pywraplp.Objective_Offset(self)
+    __swig_destroy__ = _pywraplp.delete_Objective
+
+# Register Objective in _pywraplp:
+_pywraplp.Objective_swigregister(Objective)
+
+class Variable(object):
+    r""" The class for variables of a Mathematical Programming (MP) model."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+    def name(self) -> "std::string const &":
+        r""" Returns the name of the variable."""
+        return _pywraplp.Variable_name(self)
+
+    def SetInteger(self, integer: "bool") -> "void":
+        r""" Sets the integrality requirement of the variable."""
+        return _pywraplp.Variable_SetInteger(self, integer)
+
+    def integer(self) -> "bool":
+        r""" Returns the integrality requirement of the variable."""
+        return _pywraplp.Variable_integer(self)
+
+    def solution_value(self) -> "double":
+        r"""
+        Returns the value of the variable in the current solution.
+
+        If the variable is integer, then the value will always be an integer (the
+        underlying solver handles floating-point values only, but this function
+        automatically rounds it to the nearest integer; see: man 3 round).
+        """
+        return _pywraplp.Variable_solution_value(self)
+
+    def index(self) -> "int":
+        r""" Returns the index of the variable in the MPSolver::variables_."""
+        return _pywraplp.Variable_index(self)
+
+    def lb(self) -> "double":
+        r""" Returns the lower bound."""
+        return _pywraplp.Variable_lb(self)
+
+    def ub(self) -> "double":
+        r""" Returns the upper bound."""
+        return _pywraplp.Variable_ub(self)
+
+    def SetBounds(self, lb: "double", ub: "double") -> "void":
+        r""" Sets both the lower and upper bounds."""
+        return _pywraplp.Variable_SetBounds(self, lb, ub)
+
+    def reduced_cost(self) -> "double":
+        r"""
+        Advanced usage: returns the reduced cost of the variable in the current
+        solution (only available for continuous problems).
+        """
+        return _pywraplp.Variable_reduced_cost(self)
+
+    def basis_status(self) -> "operations_research::MPSolver::BasisStatus":
+        r"""
+        Advanced usage: returns the basis status of the variable in the current
+        solution (only available for continuous problems).
+
+        See also: MPSolver::BasisStatus.
+        """
+        return _pywraplp.Variable_basis_status(self)
+
+    def branching_priority(self) -> "int":
+        r"""
+        Advanced usage: Certain MIP solvers (e.g. Gurobi or SCIP) allow you to set
+        a per-variable priority for determining which variable to branch on.
+
+        A value of 0 is treated as default, and is equivalent to not setting the
+        branching priority. The solver looks first to branch on fractional
+        variables in higher priority levels. As of 2019-05, only Gurobi and SCIP
+        support setting branching priority; all other solvers will simply ignore
+        this annotation.
+        """
+        return _pywraplp.Variable_branching_priority(self)
+
+    def SetBranchingPriority(self, priority: "int") -> "void":
+        return _pywraplp.Variable_SetBranchingPriority(self, priority)
+
+    def __str__(self) -> "std::string":
+        return _pywraplp.Variable___str__(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywraplp.Variable___repr__(self)
+
+    def __getattr__(self, name):
+      return getattr(VariableExpr(self), name)
+
+
+    def SolutionValue(self) -> "double":
+        return _pywraplp.Variable_SolutionValue(self)
+
+    def Integer(self) -> "bool":
+        return _pywraplp.Variable_Integer(self)
+
+    def Lb(self) -> "double":
+        return _pywraplp.Variable_Lb(self)
+
+    def Ub(self) -> "double":
+        return _pywraplp.Variable_Ub(self)
+
+    def SetLb(self, x: "double") -> "void":
+        return _pywraplp.Variable_SetLb(self, x)
+
+    def SetUb(self, x: "double") -> "void":
+        return _pywraplp.Variable_SetUb(self, x)
+
+    def ReducedCost(self) -> "double":
+        return _pywraplp.Variable_ReducedCost(self)
+    __swig_destroy__ = _pywraplp.delete_Variable
+
+# Register Variable in _pywraplp:
+_pywraplp.Variable_swigregister(Variable)
+
+class Constraint(object):
+    r"""
+    The class for constraints of a Mathematical Programming (MP) model.
+
+    A constraint is represented as a linear equation or inequality.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def name(self) -> "std::string const &":
+        r""" Returns the name of the constraint."""
+        return _pywraplp.Constraint_name(self)
+
+    def Clear(self) -> "void":
+        r""" Clears all variables and coefficients. Does not clear the bounds."""
+        return _pywraplp.Constraint_Clear(self)
+
+    def SetCoefficient(self, var: "Variable", coeff: "double") -> "void":
+        r"""
+        Sets the coefficient of the variable on the constraint.
+
+        If the variable does not belong to the solver, the function just returns,
+        or crashes in non-opt mode.
+        """
+        return _pywraplp.Constraint_SetCoefficient(self, var, coeff)
+
+    def GetCoefficient(self, var: "Variable") -> "double":
+        r"""
+        Gets the coefficient of a given variable on the constraint (which is 0 if
+        the variable does not appear in the constraint).
+        """
+        return _pywraplp.Constraint_GetCoefficient(self, var)
+
+    def lb(self) -> "double":
+        r""" Returns the lower bound."""
+        return _pywraplp.Constraint_lb(self)
+
+    def ub(self) -> "double":
+        r""" Returns the upper bound."""
+        return _pywraplp.Constraint_ub(self)
+
+    def SetBounds(self, lb: "double", ub: "double") -> "void":
+        r""" Sets both the lower and upper bounds."""
+        return _pywraplp.Constraint_SetBounds(self, lb, ub)
+
+    def set_is_lazy(self, laziness: "bool") -> "void":
+        r"""
+        Advanced usage: sets the constraint "laziness".
+
+        **This is only supported for SCIP and has no effect on other
+        solvers.**
+
+        When **laziness** is true, the constraint is only considered by the Linear
+        Programming solver if its current solution violates the constraint. In this
+        case, the constraint is definitively added to the problem. This may be
+        useful in some MIP problems, and may have a dramatic impact on performance.
+
+        For more info see: http://tinyurl.com/lazy-constraints.
+        """
+        return _pywraplp.Constraint_set_is_lazy(self, laziness)
+
+    def index(self) -> "int":
+        r""" Returns the index of the constraint in the MPSolver::constraints_."""
+        return _pywraplp.Constraint_index(self)
+
+    def dual_value(self) -> "double":
+        r"""
+        Advanced usage: returns the dual value of the constraint in the current
+        solution (only available for continuous problems).
+        """
+        return _pywraplp.Constraint_dual_value(self)
+
+    def basis_status(self) -> "operations_research::MPSolver::BasisStatus":
+        r"""
+        Advanced usage: returns the basis status of the constraint.
+
+        It is only available for continuous problems).
+
+        Note that if a constraint "linear_expression in [lb, ub]" is transformed
+        into "linear_expression + slack = 0" with slack in [-ub, -lb], then this
+        status is the same as the status of the slack variable with AT_UPPER_BOUND
+        and AT_LOWER_BOUND swapped.
+
+        See also: MPSolver::BasisStatus.
+        """
+        return _pywraplp.Constraint_basis_status(self)
+
+    def Lb(self) -> "double":
+        return _pywraplp.Constraint_Lb(self)
+
+    def Ub(self) -> "double":
+        return _pywraplp.Constraint_Ub(self)
+
+    def SetLb(self, x: "double") -> "void":
+        return _pywraplp.Constraint_SetLb(self, x)
+
+    def SetUb(self, x: "double") -> "void":
+        return _pywraplp.Constraint_SetUb(self, x)
+
+    def DualValue(self) -> "double":
+        return _pywraplp.Constraint_DualValue(self)
+    __swig_destroy__ = _pywraplp.delete_Constraint
+
+# Register Constraint in _pywraplp:
+_pywraplp.Constraint_swigregister(Constraint)
+
+class MPSolverParameters(object):
+    r"""
+    This class stores parameter settings for LP and MIP solvers. Some parameters
+    are marked as advanced: do not change their values unless you know what you
+    are doing!
+
+    For developers: how to add a new parameter:
+    - Add the new Foo parameter in the DoubleParam or IntegerParam enum.
+    - If it is a categorical param, add a FooValues enum.
+    - Decide if the wrapper should define a default value for it: yes
+      if it controls the properties of the solution (example:
+      tolerances) or if it consistently improves performance, no
+      otherwise. If yes, define kDefaultFoo.
+    - Add a foo_value_ member and, if no default value is defined, a
+      foo_is_default_ member.
+    - Add code to handle Foo in Set...Param, Reset...Param,
+      Get...Param, Reset and the constructor.
+    - In class MPSolverInterface, add a virtual method SetFoo, add it
+      to SetCommonParameters or SetMIPParameters, and implement it for
+      each solver. Sometimes, parameters need to be implemented
+      differently, see for example the INCREMENTALITY implementation.
+    - Add a test in linear_solver_test.cc.
+
+    TODO(user): store the parameter values in a protocol buffer
+    instead. We need to figure out how to deal with the subtleties of
+    the default values.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+    RELATIVE_MIP_GAP = _pywraplp.MPSolverParameters_RELATIVE_MIP_GAP
+    r""" Limit for relative MIP gap."""
+    PRIMAL_TOLERANCE = _pywraplp.MPSolverParameters_PRIMAL_TOLERANCE
+    r"""
+    Advanced usage: tolerance for primal feasibility of basic solutions.
+
+    This does not control the integer feasibility tolerance of integer
+    solutions for MIP or the tolerance used during presolve.
+    """
+    DUAL_TOLERANCE = _pywraplp.MPSolverParameters_DUAL_TOLERANCE
+    r""" Advanced usage: tolerance for dual feasibility of basic solutions."""
+    PRESOLVE = _pywraplp.MPSolverParameters_PRESOLVE
+    r""" Advanced usage: presolve mode."""
+    LP_ALGORITHM = _pywraplp.MPSolverParameters_LP_ALGORITHM
+    r""" Algorithm to solve linear programs."""
+    INCREMENTALITY = _pywraplp.MPSolverParameters_INCREMENTALITY
+    r""" Advanced usage: incrementality from one solve to the next."""
+    SCALING = _pywraplp.MPSolverParameters_SCALING
+    r""" Advanced usage: enable or disable matrix scaling."""
+    PRESOLVE_OFF = _pywraplp.MPSolverParameters_PRESOLVE_OFF
+    r""" Presolve is off."""
+    PRESOLVE_ON = _pywraplp.MPSolverParameters_PRESOLVE_ON
+    r""" Presolve is on."""
+    DUAL = _pywraplp.MPSolverParameters_DUAL
+    r""" Dual simplex."""
+    PRIMAL = _pywraplp.MPSolverParameters_PRIMAL
+    r""" Primal simplex."""
+    BARRIER = _pywraplp.MPSolverParameters_BARRIER
+    r""" Barrier algorithm."""
+    INCREMENTALITY_OFF = _pywraplp.MPSolverParameters_INCREMENTALITY_OFF
+    r""" Start solve from scratch."""
+    INCREMENTALITY_ON = _pywraplp.MPSolverParameters_INCREMENTALITY_ON
+    r"""
+    Reuse results from previous solve as much as the underlying solver
+    allows.
+    """
+    SCALING_OFF = _pywraplp.MPSolverParameters_SCALING_OFF
+    r""" Scaling is off."""
+    SCALING_ON = _pywraplp.MPSolverParameters_SCALING_ON
+    r""" Scaling is on."""
+
+    def __init__(self):
+        r""" The constructor sets all parameters to their default value."""
+        _pywraplp.MPSolverParameters_swiginit(self, _pywraplp.new_MPSolverParameters())
+
+    def SetDoubleParam(self, param: "operations_research::MPSolverParameters::DoubleParam", value: "double") -> "void":
+        r""" Sets a double parameter to a specific value."""
+        return _pywraplp.MPSolverParameters_SetDoubleParam(self, param, value)
+
+    def SetIntegerParam(self, param: "operations_research::MPSolverParameters::IntegerParam", value: "int") -> "void":
+        r""" Sets a integer parameter to a specific value."""
+        return _pywraplp.MPSolverParameters_SetIntegerParam(self, param, value)
+
+    def GetDoubleParam(self, param: "operations_research::MPSolverParameters::DoubleParam") -> "double":
+        r""" Returns the value of a double parameter."""
+        return _pywraplp.MPSolverParameters_GetDoubleParam(self, param)
+
+    def GetIntegerParam(self, param: "operations_research::MPSolverParameters::IntegerParam") -> "int":
+        r""" Returns the value of an integer parameter."""
+        return _pywraplp.MPSolverParameters_GetIntegerParam(self, param)
+    __swig_destroy__ = _pywraplp.delete_MPSolverParameters
+
+# Register MPSolverParameters in _pywraplp:
+_pywraplp.MPSolverParameters_swigregister(MPSolverParameters)
+cvar = _pywraplp.cvar
+MPSolverParameters.kDefaultRelativeMipGap = _pywraplp.cvar.MPSolverParameters_kDefaultRelativeMipGap
+MPSolverParameters.kDefaultPrimalTolerance = _pywraplp.cvar.MPSolverParameters_kDefaultPrimalTolerance
+MPSolverParameters.kDefaultDualTolerance = _pywraplp.cvar.MPSolverParameters_kDefaultDualTolerance
+MPSolverParameters.kDefaultPresolve = _pywraplp.cvar.MPSolverParameters_kDefaultPresolve
+MPSolverParameters.kDefaultIncrementality = _pywraplp.cvar.MPSolverParameters_kDefaultIncrementality
+
+class ModelExportOptions(object):
+    r""" Export options."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self):
+        _pywraplp.ModelExportOptions_swiginit(self, _pywraplp.new_ModelExportOptions())
+    __swig_destroy__ = _pywraplp.delete_ModelExportOptions
+
+# Register ModelExportOptions in _pywraplp:
+_pywraplp.ModelExportOptions_swigregister(ModelExportOptions)
+
+
+def ExportModelAsLpFormat(*args) -> "std::string":
+    return _pywraplp.ExportModelAsLpFormat(*args)
+
+def ExportModelAsMpsFormat(*args) -> "std::string":
+    return _pywraplp.ExportModelAsMpsFormat(*args)
+
+def FindErrorInModelProto(input_model: "operations_research::MPModelProto const &") -> "std::string":
+    return _pywraplp.FindErrorInModelProto(input_model)
+
+def setup_variable_operator(opname):
+  setattr(Variable, opname,
+          lambda self, *args: getattr(VariableExpr(self), opname)(*args))
+for opname in LinearExpr.OVERRIDDEN_OPERATOR_METHODS:
+  setup_variable_operator(opname)
+
+ +
+ +
+
+
+ #   + + + class + Solver: +
+ +
+ View Source +
class Solver(object):
+    r"""
+    This mathematical programming (MP) solver class is the main class
+    though which users build and solve problems.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+    CLP_LINEAR_PROGRAMMING = _pywraplp.Solver_CLP_LINEAR_PROGRAMMING
+    GLPK_LINEAR_PROGRAMMING = _pywraplp.Solver_GLPK_LINEAR_PROGRAMMING
+    GLOP_LINEAR_PROGRAMMING = _pywraplp.Solver_GLOP_LINEAR_PROGRAMMING
+    PDLP_LINEAR_PROGRAMMING = _pywraplp.Solver_PDLP_LINEAR_PROGRAMMING
+    SCIP_MIXED_INTEGER_PROGRAMMING = _pywraplp.Solver_SCIP_MIXED_INTEGER_PROGRAMMING
+    GLPK_MIXED_INTEGER_PROGRAMMING = _pywraplp.Solver_GLPK_MIXED_INTEGER_PROGRAMMING
+    CBC_MIXED_INTEGER_PROGRAMMING = _pywraplp.Solver_CBC_MIXED_INTEGER_PROGRAMMING
+    GUROBI_LINEAR_PROGRAMMING = _pywraplp.Solver_GUROBI_LINEAR_PROGRAMMING
+    GUROBI_MIXED_INTEGER_PROGRAMMING = _pywraplp.Solver_GUROBI_MIXED_INTEGER_PROGRAMMING
+    CPLEX_LINEAR_PROGRAMMING = _pywraplp.Solver_CPLEX_LINEAR_PROGRAMMING
+    CPLEX_MIXED_INTEGER_PROGRAMMING = _pywraplp.Solver_CPLEX_MIXED_INTEGER_PROGRAMMING
+    XPRESS_LINEAR_PROGRAMMING = _pywraplp.Solver_XPRESS_LINEAR_PROGRAMMING
+    XPRESS_MIXED_INTEGER_PROGRAMMING = _pywraplp.Solver_XPRESS_MIXED_INTEGER_PROGRAMMING
+    BOP_INTEGER_PROGRAMMING = _pywraplp.Solver_BOP_INTEGER_PROGRAMMING
+    SAT_INTEGER_PROGRAMMING = _pywraplp.Solver_SAT_INTEGER_PROGRAMMING
+
+    def __init__(self, name: "std::string const &", problem_type: "operations_research::MPSolver::OptimizationProblemType"):
+        r""" Create a solver with the given name and underlying solver backend."""
+        _pywraplp.Solver_swiginit(self, _pywraplp.new_Solver(name, problem_type))
+    __swig_destroy__ = _pywraplp.delete_Solver
+
+    @staticmethod
+    def CreateSolver(solver_id: "std::string const &") -> "operations_research::MPSolver *":
+        r"""
+        Recommended factory method to create a MPSolver instance, especially in
+        non C++ languages.
+
+        It returns a newly created solver instance if successful, or a nullptr
+        otherwise. This can occur if the relevant interface is not linked in, or if
+        a needed license is not accessible for commercial solvers.
+
+        Ownership of the solver is passed on to the caller of this method.
+        It will accept both string names of the OptimizationProblemType enum, as
+        well as a short version (i.e. "SCIP_MIXED_INTEGER_PROGRAMMING" or "SCIP").
+
+        solver_id is case insensitive, and the following names are supported:
+          - CLP_LINEAR_PROGRAMMING or CLP
+          - CBC_MIXED_INTEGER_PROGRAMMING or CBC
+          - GLOP_LINEAR_PROGRAMMING or GLOP
+          - BOP_INTEGER_PROGRAMMING or BOP
+          - SAT_INTEGER_PROGRAMMING or SAT or CP_SAT
+          - SCIP_MIXED_INTEGER_PROGRAMMING or SCIP
+          - GUROBI_LINEAR_PROGRAMMING or GUROBI_LP
+          - GUROBI_MIXED_INTEGER_PROGRAMMING or GUROBI or GUROBI_MIP
+          - CPLEX_LINEAR_PROGRAMMING or CPLEX_LP
+          - CPLEX_MIXED_INTEGER_PROGRAMMING or CPLEX or CPLEX_MIP
+          - XPRESS_LINEAR_PROGRAMMING or XPRESS_LP
+          - XPRESS_MIXED_INTEGER_PROGRAMMING or XPRESS or XPRESS_MIP
+          - GLPK_LINEAR_PROGRAMMING or GLPK_LP
+          - GLPK_MIXED_INTEGER_PROGRAMMING or GLPK or GLPK_MIP
+        """
+        return _pywraplp.Solver_CreateSolver(solver_id)
+
+    @staticmethod
+    def SupportsProblemType(problem_type: "operations_research::MPSolver::OptimizationProblemType") -> "bool":
+        r"""
+        Whether the given problem type is supported (this will depend on the
+        targets that you linked).
+        """
+        return _pywraplp.Solver_SupportsProblemType(problem_type)
+
+    def Clear(self) -> "void":
+        r"""
+        Clears the objective (including the optimization direction), all variables
+        and constraints. All the other properties of the MPSolver (like the time
+        limit) are kept untouched.
+        """
+        return _pywraplp.Solver_Clear(self)
+
+    def NumVariables(self) -> "int":
+        r""" Returns the number of variables."""
+        return _pywraplp.Solver_NumVariables(self)
+
+    def variables(self) -> "std::vector< operations_research::MPVariable * > const &":
+        r"""
+        Returns the array of variables handled by the MPSolver. (They are listed in
+        the order in which they were created.)
+        """
+        return _pywraplp.Solver_variables(self)
+
+    def variable(self, index: "int") -> "operations_research::MPVariable *":
+        r"""Returns the variable at position index."""
+        return _pywraplp.Solver_variable(self, index)
+
+    def LookupVariable(self, var_name: "std::string const &") -> "operations_research::MPVariable *":
+        r"""
+        Looks up a variable by name, and returns nullptr if it does not exist. The
+        first call has a O(n) complexity, as the variable name index is lazily
+        created upon first use. Will crash if variable names are not unique.
+        """
+        return _pywraplp.Solver_LookupVariable(self, var_name)
+
+    def Var(self, lb: "double", ub: "double", integer: "bool", name: "std::string const &") -> "operations_research::MPVariable *":
+        r"""
+        Creates a variable with the given bounds, integrality requirement and
+        name. Bounds can be finite or +/- MPSolver::infinity(). The MPSolver owns
+        the variable (i.e. the returned pointer is borrowed). Variable names are
+        optional. If you give an empty name, name() will auto-generate one for you
+        upon request.
+        """
+        return _pywraplp.Solver_Var(self, lb, ub, integer, name)
+
+    def NumVar(self, lb: "double", ub: "double", name: "std::string const &") -> "operations_research::MPVariable *":
+        r""" Creates a continuous variable."""
+        return _pywraplp.Solver_NumVar(self, lb, ub, name)
+
+    def IntVar(self, lb: "double", ub: "double", name: "std::string const &") -> "operations_research::MPVariable *":
+        r""" Creates an integer variable."""
+        return _pywraplp.Solver_IntVar(self, lb, ub, name)
+
+    def BoolVar(self, name: "std::string const &") -> "operations_research::MPVariable *":
+        r""" Creates a boolean variable."""
+        return _pywraplp.Solver_BoolVar(self, name)
+
+    def NumConstraints(self) -> "int":
+        r""" Returns the number of constraints."""
+        return _pywraplp.Solver_NumConstraints(self)
+
+    def constraints(self) -> "std::vector< operations_research::MPConstraint * > const &":
+        r"""
+        Returns the array of constraints handled by the MPSolver.
+
+        They are listed in the order in which they were created.
+        """
+        return _pywraplp.Solver_constraints(self)
+
+    def constraint(self, index: "int") -> "operations_research::MPConstraint *":
+        r""" Returns the constraint at the given index."""
+        return _pywraplp.Solver_constraint(self, index)
+
+    def LookupConstraint(self, constraint_name: "std::string const &") -> "operations_research::MPConstraint *":
+        r"""
+         Looks up a constraint by name, and returns nullptr if it does not exist.
+
+        The first call has a O(n) complexity, as the constraint name index is
+        lazily created upon first use. Will crash if constraint names are not
+        unique.
+        """
+        return _pywraplp.Solver_LookupConstraint(self, constraint_name)
+
+    def Constraint(self, *args) -> "operations_research::MPConstraint *":
+        r"""
+        *Overload 1:*
+
+        Creates a linear constraint with given bounds.
+
+        Bounds can be finite or +/- MPSolver::infinity(). The MPSolver class
+        assumes ownership of the constraint.
+
+        :rtype: :py:class:`MPConstraint`
+        :return: a pointer to the newly created constraint.
+
+        |
+
+        *Overload 2:*
+         Creates a constraint with -infinity and +infinity bounds.
+
+        |
+
+        *Overload 3:*
+         Creates a named constraint with given bounds.
+
+        |
+
+        *Overload 4:*
+         Creates a named constraint with -infinity and +infinity bounds.
+        """
+        return _pywraplp.Solver_Constraint(self, *args)
+
+    def Objective(self) -> "operations_research::MPObjective *":
+        r""" Returns the mutable objective object."""
+        return _pywraplp.Solver_Objective(self)
+    OPTIMAL = _pywraplp.Solver_OPTIMAL
+    r""" optimal."""
+    FEASIBLE = _pywraplp.Solver_FEASIBLE
+    r""" feasible, or stopped by limit."""
+    INFEASIBLE = _pywraplp.Solver_INFEASIBLE
+    r""" proven infeasible."""
+    UNBOUNDED = _pywraplp.Solver_UNBOUNDED
+    r""" proven unbounded."""
+    ABNORMAL = _pywraplp.Solver_ABNORMAL
+    r""" abnormal, i.e., error of some kind."""
+    NOT_SOLVED = _pywraplp.Solver_NOT_SOLVED
+    r""" not been solved yet."""
+
+    def Solve(self, *args) -> "operations_research::MPSolver::ResultStatus":
+        r"""
+        *Overload 1:*
+        Solves the problem using the default parameter values.
+
+        |
+
+        *Overload 2:*
+        Solves the problem using the specified parameter values.
+        """
+        return _pywraplp.Solver_Solve(self, *args)
+
+    def ComputeConstraintActivities(self) -> "std::vector< double >":
+        r"""
+        Advanced usage: compute the "activities" of all constraints, which are the
+        sums of their linear terms. The activities are returned in the same order
+        as constraints(), which is the order in which constraints were added; but
+        you can also use MPConstraint::index() to get a constraint's index.
+        """
+        return _pywraplp.Solver_ComputeConstraintActivities(self)
+
+    def VerifySolution(self, tolerance: "double", log_errors: "bool") -> "bool":
+        r"""
+        Advanced usage: Verifies the *correctness* of the solution.
+
+        It verifies that all variables must be within their domains, all
+        constraints must be satisfied, and the reported objective value must be
+        accurate.
+
+        Usage:
+        - This can only be called after Solve() was called.
+        - "tolerance" is interpreted as an absolute error threshold.
+        - For the objective value only, if the absolute error is too large,
+          the tolerance is interpreted as a relative error threshold instead.
+        - If "log_errors" is true, every single violation will be logged.
+        - If "tolerance" is negative, it will be set to infinity().
+
+        Most users should just set the --verify_solution flag and not bother using
+        this method directly.
+        """
+        return _pywraplp.Solver_VerifySolution(self, tolerance, log_errors)
+
+    def InterruptSolve(self) -> "bool":
+        r"""
+         Interrupts the Solve() execution to terminate processing if possible.
+
+        If the underlying interface supports interruption; it does that and returns
+        true regardless of whether there's an ongoing Solve() or not. The Solve()
+        call may still linger for a while depending on the conditions.  If
+        interruption is not supported; returns false and does nothing.
+        MPSolver::SolverTypeSupportsInterruption can be used to check if
+        interruption is supported for a given solver type.
+        """
+        return _pywraplp.Solver_InterruptSolve(self)
+
+    def FillSolutionResponseProto(self, response: "operations_research::MPSolutionResponse *") -> "void":
+        r""" Encodes the current solution in a solution response protocol buffer."""
+        return _pywraplp.Solver_FillSolutionResponseProto(self, response)
+
+    @staticmethod
+    def SolveWithProto(model_request: "operations_research::MPModelRequest const &", response: "operations_research::MPSolutionResponse *", interrupt: "std::atomic< bool > *"=None) -> "operations_research::MPSolutionResponse *":
+        r"""
+        Solves the model encoded by a MPModelRequest protocol buffer and fills the
+        solution encoded as a MPSolutionResponse. The solve is stopped prematurely
+        if interrupt is non-null at set to true during (or before) solving.
+        Interruption is only supported if SolverTypeSupportsInterruption() returns
+        true for the requested solver. Passing a non-null interruption with any
+        other solver type immediately returns an MPSOLVER_INCOMPATIBLE_OPTIONS
+        error.
+
+        Note(user): This attempts to first use `DirectlySolveProto()` (if
+        implemented). Consequently, this most likely does *not* override any of
+        the default parameters of the underlying solver. This behavior *differs*
+        from `MPSolver::Solve()` which by default sets the feasibility tolerance
+        and the gap limit (as of 2020/02/11, to 1e-7 and 0.0001, respectively).
+        """
+        return _pywraplp.Solver_SolveWithProto(model_request, response, interrupt)
+
+    def ExportModelToProto(self, output_model: "operations_research::MPModelProto *") -> "void":
+        r""" Exports model to protocol buffer."""
+        return _pywraplp.Solver_ExportModelToProto(self, output_model)
+
+    def SetSolverSpecificParametersAsString(self, parameters: "std::string const &") -> "bool":
+        r"""
+        Advanced usage: pass solver specific parameters in text format.
+
+        The format is solver-specific and is the same as the corresponding solver
+        configuration file format. Returns true if the operation was successful.
+        """
+        return _pywraplp.Solver_SetSolverSpecificParametersAsString(self, parameters)
+    FREE = _pywraplp.Solver_FREE
+    AT_LOWER_BOUND = _pywraplp.Solver_AT_LOWER_BOUND
+    AT_UPPER_BOUND = _pywraplp.Solver_AT_UPPER_BOUND
+    FIXED_VALUE = _pywraplp.Solver_FIXED_VALUE
+    BASIC = _pywraplp.Solver_BASIC
+
+    @staticmethod
+    def infinity() -> "double":
+        r"""
+        Infinity.
+
+        You can use -MPSolver::infinity() for negative infinity.
+        """
+        return _pywraplp.Solver_infinity()
+
+    def EnableOutput(self) -> "void":
+        r""" Enables solver logging."""
+        return _pywraplp.Solver_EnableOutput(self)
+
+    def SuppressOutput(self) -> "void":
+        r""" Suppresses solver logging."""
+        return _pywraplp.Solver_SuppressOutput(self)
+
+    def iterations(self) -> "int64_t":
+        r""" Returns the number of simplex iterations."""
+        return _pywraplp.Solver_iterations(self)
+
+    def nodes(self) -> "int64_t":
+        r"""
+        Returns the number of branch-and-bound nodes evaluated during the solve.
+
+        Only available for discrete problems.
+        """
+        return _pywraplp.Solver_nodes(self)
+
+    def ComputeExactConditionNumber(self) -> "double":
+        r"""
+         Advanced usage: computes the exact condition number of the current scaled
+        basis: L1norm(B) * L1norm(inverse(B)), where B is the scaled basis.
+
+        This method requires that a basis exists: it should be called after Solve.
+        It is only available for continuous problems. It is implemented for GLPK
+        but not CLP because CLP does not provide the API for doing it.
+
+        The condition number measures how well the constraint matrix is conditioned
+        and can be used to predict whether numerical issues will arise during the
+        solve: the model is declared infeasible whereas it is feasible (or
+        vice-versa), the solution obtained is not optimal or violates some
+        constraints, the resolution is slow because of repeated singularities.
+
+        The rule of thumb to interpret the condition number kappa is:
+          - o kappa <= 1e7: virtually no chance of numerical issues
+          - o 1e7 < kappa <= 1e10: small chance of numerical issues
+          - o 1e10 < kappa <= 1e13: medium chance of numerical issues
+          - o kappa > 1e13: high chance of numerical issues
+
+        The computation of the condition number depends on the quality of the LU
+        decomposition, so it is not very accurate when the matrix is ill
+        conditioned.
+        """
+        return _pywraplp.Solver_ComputeExactConditionNumber(self)
+
+    def NextSolution(self) -> "bool":
+        r"""
+        Some solvers (MIP only, not LP) can produce multiple solutions to the
+        problem. Returns true when another solution is available, and updates the
+        MPVariable* objects to make the new solution queryable. Call only after
+        calling solve.
+
+        The optimality properties of the additional solutions found, and whether or
+        not the solver computes them ahead of time or when NextSolution() is called
+        is solver specific.
+
+        As of 2020-02-10, only Gurobi and SCIP support NextSolution(), see
+        linear_solver_interfaces_test for an example of how to configure these
+        solvers for multiple solutions. Other solvers return false unconditionally.
+        """
+        return _pywraplp.Solver_NextSolution(self)
+
+    def set_time_limit(self, time_limit_milliseconds: "int64_t") -> "void":
+        return _pywraplp.Solver_set_time_limit(self, time_limit_milliseconds)
+
+    def wall_time(self) -> "int64_t":
+        return _pywraplp.Solver_wall_time(self)
+
+    def LoadModelFromProto(self, input_model: "operations_research::MPModelProto const &") -> "std::string":
+        return _pywraplp.Solver_LoadModelFromProto(self, input_model)
+
+    def LoadModelFromProtoWithUniqueNamesOrDie(self, input_model: "operations_research::MPModelProto const &") -> "std::string":
+        return _pywraplp.Solver_LoadModelFromProtoWithUniqueNamesOrDie(self, input_model)
+
+    def LoadSolutionFromProto(self, *args) -> "bool":
+        return _pywraplp.Solver_LoadSolutionFromProto(self, *args)
+
+    def ExportModelAsLpFormat(self, obfuscated: "bool") -> "std::string":
+        return _pywraplp.Solver_ExportModelAsLpFormat(self, obfuscated)
+
+    def ExportModelAsMpsFormat(self, fixed_format: "bool", obfuscated: "bool") -> "std::string":
+        return _pywraplp.Solver_ExportModelAsMpsFormat(self, fixed_format, obfuscated)
+
+    def SetHint(self, variables: "std::vector< operations_research::MPVariable * > const &", values: "std::vector< double > const &") -> "void":
+        r"""
+        Set a hint for solution.
+
+        If a feasible or almost-feasible solution to the problem is already known,
+        it may be helpful to pass it to the solver so that it can be used. A
+        solver that supports this feature will try to use this information to
+        create its initial feasible solution.
+
+        Note that it may not always be faster to give a hint like this to the
+        solver. There is also no guarantee that the solver will use this hint or
+        try to return a solution "close" to this assignment in case of multiple
+        optimal solutions.
+        """
+        return _pywraplp.Solver_SetHint(self, variables, values)
+
+    def SetNumThreads(self, num_theads: "int") -> "bool":
+        r""" Sets the number of threads to be used by the solver."""
+        return _pywraplp.Solver_SetNumThreads(self, num_theads)
+
+    def Add(self, constraint, name=''):
+      if isinstance(constraint, bool):
+        if constraint:
+          return self.RowConstraint(0, 0, name)
+        else:
+          return self.RowConstraint(1, 1, name)
+      else:
+        return constraint.Extract(self, name)
+
+    def Sum(self, expr_array):
+      result = SumArray(expr_array)
+      return result
+
+    def RowConstraint(self, *args):
+      return self.Constraint(*args)
+
+    def Minimize(self, expr):
+      objective = self.Objective()
+      objective.Clear()
+      objective.SetMinimization()
+      if isinstance(expr, numbers.Number):
+          objective.SetOffset(expr)
+      else:
+          coeffs = expr.GetCoeffs()
+          objective.SetOffset(coeffs.pop(OFFSET_KEY, 0.0))
+          for v, c, in list(coeffs.items()):
+            objective.SetCoefficient(v, float(c))
+
+    def Maximize(self, expr):
+      objective = self.Objective()
+      objective.Clear()
+      objective.SetMaximization()
+      if isinstance(expr, numbers.Number):
+          objective.SetOffset(expr)
+      else:
+          coeffs = expr.GetCoeffs()
+          objective.SetOffset(coeffs.pop(OFFSET_KEY, 0.0))
+          for v, c, in list(coeffs.items()):
+            objective.SetCoefficient(v, float(c))
+
+
+    @staticmethod
+    def Infinity() -> "double":
+        return _pywraplp.Solver_Infinity()
+
+    def SetTimeLimit(self, x: "int64_t") -> "void":
+        return _pywraplp.Solver_SetTimeLimit(self, x)
+
+    def WallTime(self) -> "int64_t":
+        return _pywraplp.Solver_WallTime(self)
+
+    def Iterations(self) -> "int64_t":
+        return _pywraplp.Solver_Iterations(self)
+
+ +
+ +

This mathematical programming (MP) solver class is the main class +though which users build and solve problems.

+
+ + +
+
#   + + + Solver( + name: 'std::string const &', + problem_type: 'operations_research::MPSolver::OptimizationProblemType' +) +
+ +
+ View Source +
    def __init__(self, name: "std::string const &", problem_type: "operations_research::MPSolver::OptimizationProblemType"):
+        r""" Create a solver with the given name and underlying solver backend."""
+        _pywraplp.Solver_swiginit(self, _pywraplp.new_Solver(name, problem_type))
+
+ +
+ +

Create a solver with the given name and underlying solver backend.

+
+ + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + CLP_LINEAR_PROGRAMMING = 0 +
+ + + + +
+
+
#   + + GLPK_LINEAR_PROGRAMMING = 1 +
+ + + + +
+
+
#   + + GLOP_LINEAR_PROGRAMMING = 2 +
+ + + + +
+
+
#   + + PDLP_LINEAR_PROGRAMMING = 8 +
+ + + + +
+
+
#   + + SCIP_MIXED_INTEGER_PROGRAMMING = 3 +
+ + + + +
+
+
#   + + GLPK_MIXED_INTEGER_PROGRAMMING = 4 +
+ + + + +
+
+
#   + + CBC_MIXED_INTEGER_PROGRAMMING = 5 +
+ + + + +
+
+
#   + + GUROBI_LINEAR_PROGRAMMING = 6 +
+ + + + +
+
+
#   + + GUROBI_MIXED_INTEGER_PROGRAMMING = 7 +
+ + + + +
+
+
#   + + CPLEX_LINEAR_PROGRAMMING = 10 +
+ + + + +
+
+
#   + + CPLEX_MIXED_INTEGER_PROGRAMMING = 11 +
+ + + + +
+
+
#   + + XPRESS_LINEAR_PROGRAMMING = 101 +
+ + + + +
+
+
#   + + XPRESS_MIXED_INTEGER_PROGRAMMING = 102 +
+ + + + +
+
+
#   + + BOP_INTEGER_PROGRAMMING = 12 +
+ + + + +
+
+
#   + + SAT_INTEGER_PROGRAMMING = 14 +
+ + + + +
+
+
#   + +
@staticmethod
+ + def + CreateSolver( + solver_id: 'std::string const &' +) -> 'operations_research::MPSolver *': +
+ +
+ View Source +
    @staticmethod
+    def CreateSolver(solver_id: "std::string const &") -> "operations_research::MPSolver *":
+        r"""
+        Recommended factory method to create a MPSolver instance, especially in
+        non C++ languages.
+
+        It returns a newly created solver instance if successful, or a nullptr
+        otherwise. This can occur if the relevant interface is not linked in, or if
+        a needed license is not accessible for commercial solvers.
+
+        Ownership of the solver is passed on to the caller of this method.
+        It will accept both string names of the OptimizationProblemType enum, as
+        well as a short version (i.e. "SCIP_MIXED_INTEGER_PROGRAMMING" or "SCIP").
+
+        solver_id is case insensitive, and the following names are supported:
+          - CLP_LINEAR_PROGRAMMING or CLP
+          - CBC_MIXED_INTEGER_PROGRAMMING or CBC
+          - GLOP_LINEAR_PROGRAMMING or GLOP
+          - BOP_INTEGER_PROGRAMMING or BOP
+          - SAT_INTEGER_PROGRAMMING or SAT or CP_SAT
+          - SCIP_MIXED_INTEGER_PROGRAMMING or SCIP
+          - GUROBI_LINEAR_PROGRAMMING or GUROBI_LP
+          - GUROBI_MIXED_INTEGER_PROGRAMMING or GUROBI or GUROBI_MIP
+          - CPLEX_LINEAR_PROGRAMMING or CPLEX_LP
+          - CPLEX_MIXED_INTEGER_PROGRAMMING or CPLEX or CPLEX_MIP
+          - XPRESS_LINEAR_PROGRAMMING or XPRESS_LP
+          - XPRESS_MIXED_INTEGER_PROGRAMMING or XPRESS or XPRESS_MIP
+          - GLPK_LINEAR_PROGRAMMING or GLPK_LP
+          - GLPK_MIXED_INTEGER_PROGRAMMING or GLPK or GLPK_MIP
+        """
+        return _pywraplp.Solver_CreateSolver(solver_id)
+
+ +
+ +

Recommended factory method to create a MPSolver instance, especially in +non C++ languages.

+ +

It returns a newly created solver instance if successful, or a nullptr +otherwise. This can occur if the relevant interface is not linked in, or if +a needed license is not accessible for commercial solvers.

+ +

Ownership of the solver is passed on to the caller of this method. +It will accept both string names of the OptimizationProblemType enum, as +well as a short version (i.e. "SCIP_MIXED_INTEGER_PROGRAMMING" or "SCIP").

+ +

solver_id is case insensitive, and the following names are supported:

+ +
    +
  • CLP_LINEAR_PROGRAMMING or CLP
  • +
  • CBC_MIXED_INTEGER_PROGRAMMING or CBC
  • +
  • GLOP_LINEAR_PROGRAMMING or GLOP
  • +
  • BOP_INTEGER_PROGRAMMING or BOP
  • +
  • SAT_INTEGER_PROGRAMMING or SAT or CP_SAT
  • +
  • SCIP_MIXED_INTEGER_PROGRAMMING or SCIP
  • +
  • GUROBI_LINEAR_PROGRAMMING or GUROBI_LP
  • +
  • GUROBI_MIXED_INTEGER_PROGRAMMING or GUROBI or GUROBI_MIP
  • +
  • CPLEX_LINEAR_PROGRAMMING or CPLEX_LP
  • +
  • CPLEX_MIXED_INTEGER_PROGRAMMING or CPLEX or CPLEX_MIP
  • +
  • XPRESS_LINEAR_PROGRAMMING or XPRESS_LP
  • +
  • XPRESS_MIXED_INTEGER_PROGRAMMING or XPRESS or XPRESS_MIP
  • +
  • GLPK_LINEAR_PROGRAMMING or GLPK_LP
  • +
  • GLPK_MIXED_INTEGER_PROGRAMMING or GLPK or GLPK_MIP
  • +
+
+ + +
+
+
#   + +
@staticmethod
+ + def + SupportsProblemType( + problem_type: 'operations_research::MPSolver::OptimizationProblemType' +) -> bool: +
+ +
+ View Source +
    @staticmethod
+    def SupportsProblemType(problem_type: "operations_research::MPSolver::OptimizationProblemType") -> "bool":
+        r"""
+        Whether the given problem type is supported (this will depend on the
+        targets that you linked).
+        """
+        return _pywraplp.Solver_SupportsProblemType(problem_type)
+
+ +
+ +

Whether the given problem type is supported (this will depend on the +targets that you linked).

+
+ + +
+
+
#   + + + def + Clear(self) -> 'void': +
+ +
+ View Source +
    def Clear(self) -> "void":
+        r"""
+        Clears the objective (including the optimization direction), all variables
+        and constraints. All the other properties of the MPSolver (like the time
+        limit) are kept untouched.
+        """
+        return _pywraplp.Solver_Clear(self)
+
+ +
+ +

Clears the objective (including the optimization direction), all variables +and constraints. All the other properties of the MPSolver (like the time +limit) are kept untouched.

+
+ + +
+
+
#   + + + def + NumVariables(self) -> int: +
+ +
+ View Source +
    def NumVariables(self) -> "int":
+        r""" Returns the number of variables."""
+        return _pywraplp.Solver_NumVariables(self)
+
+ +
+ +

Returns the number of variables.

+
+ + +
+
+
#   + + + def + variables(self) -> 'std::vector< operations_research::MPVariable * > const &': +
+ +
+ View Source +
    def variables(self) -> "std::vector< operations_research::MPVariable * > const &":
+        r"""
+        Returns the array of variables handled by the MPSolver. (They are listed in
+        the order in which they were created.)
+        """
+        return _pywraplp.Solver_variables(self)
+
+ +
+ +

Returns the array of variables handled by the MPSolver. (They are listed in +the order in which they were created.)

+
+ + +
+
+
#   + + + def + variable(self, index: int) -> 'operations_research::MPVariable *': +
+ +
+ View Source +
    def variable(self, index: "int") -> "operations_research::MPVariable *":
+        r"""Returns the variable at position index."""
+        return _pywraplp.Solver_variable(self, index)
+
+ +
+ +

Returns the variable at position index.

+
+ + +
+
+
#   + + + def + LookupVariable( + self, + var_name: 'std::string const &' +) -> 'operations_research::MPVariable *': +
+ +
+ View Source +
    def LookupVariable(self, var_name: "std::string const &") -> "operations_research::MPVariable *":
+        r"""
+        Looks up a variable by name, and returns nullptr if it does not exist. The
+        first call has a O(n) complexity, as the variable name index is lazily
+        created upon first use. Will crash if variable names are not unique.
+        """
+        return _pywraplp.Solver_LookupVariable(self, var_name)
+
+ +
+ +

Looks up a variable by name, and returns nullptr if it does not exist. The +first call has a O(n) complexity, as the variable name index is lazily +created upon first use. Will crash if variable names are not unique.

+
+ + +
+
+
#   + + + def + Var( + self, + lb: 'double', + ub: 'double', + integer: bool, + name: 'std::string const &' +) -> 'operations_research::MPVariable *': +
+ +
+ View Source +
    def Var(self, lb: "double", ub: "double", integer: "bool", name: "std::string const &") -> "operations_research::MPVariable *":
+        r"""
+        Creates a variable with the given bounds, integrality requirement and
+        name. Bounds can be finite or +/- MPSolver::infinity(). The MPSolver owns
+        the variable (i.e. the returned pointer is borrowed). Variable names are
+        optional. If you give an empty name, name() will auto-generate one for you
+        upon request.
+        """
+        return _pywraplp.Solver_Var(self, lb, ub, integer, name)
+
+ +
+ +

Creates a variable with the given bounds, integrality requirement and +name. Bounds can be finite or +/- MPSolver::infinity(). The MPSolver owns +the variable (i.e. the returned pointer is borrowed). Variable names are +optional. If you give an empty name, name() will auto-generate one for you +upon request.

+
+ + +
+
+
#   + + + def + NumVar( + self, + lb: 'double', + ub: 'double', + name: 'std::string const &' +) -> 'operations_research::MPVariable *': +
+ +
+ View Source +
    def NumVar(self, lb: "double", ub: "double", name: "std::string const &") -> "operations_research::MPVariable *":
+        r""" Creates a continuous variable."""
+        return _pywraplp.Solver_NumVar(self, lb, ub, name)
+
+ +
+ +

Creates a continuous variable.

+
+ + +
+
+
#   + + + def + IntVar( + self, + lb: 'double', + ub: 'double', + name: 'std::string const &' +) -> 'operations_research::MPVariable *': +
+ +
+ View Source +
    def IntVar(self, lb: "double", ub: "double", name: "std::string const &") -> "operations_research::MPVariable *":
+        r""" Creates an integer variable."""
+        return _pywraplp.Solver_IntVar(self, lb, ub, name)
+
+ +
+ +

Creates an integer variable.

+
+ + +
+
+
#   + + + def + BoolVar( + self, + name: 'std::string const &' +) -> 'operations_research::MPVariable *': +
+ +
+ View Source +
    def BoolVar(self, name: "std::string const &") -> "operations_research::MPVariable *":
+        r""" Creates a boolean variable."""
+        return _pywraplp.Solver_BoolVar(self, name)
+
+ +
+ +

Creates a boolean variable.

+
+ + +
+
+
#   + + + def + NumConstraints(self) -> int: +
+ +
+ View Source +
    def NumConstraints(self) -> "int":
+        r""" Returns the number of constraints."""
+        return _pywraplp.Solver_NumConstraints(self)
+
+ +
+ +

Returns the number of constraints.

+
+ + +
+
+
#   + + + def + constraints(self) -> 'std::vector< operations_research::MPConstraint * > const &': +
+ +
+ View Source +
    def constraints(self) -> "std::vector< operations_research::MPConstraint * > const &":
+        r"""
+        Returns the array of constraints handled by the MPSolver.
+
+        They are listed in the order in which they were created.
+        """
+        return _pywraplp.Solver_constraints(self)
+
+ +
+ +

Returns the array of constraints handled by the MPSolver.

+ +

They are listed in the order in which they were created.

+
+ + +
+
+
#   + + + def + constraint(self, index: int) -> 'operations_research::MPConstraint *': +
+ +
+ View Source +
    def constraint(self, index: "int") -> "operations_research::MPConstraint *":
+        r""" Returns the constraint at the given index."""
+        return _pywraplp.Solver_constraint(self, index)
+
+ +
+ +

Returns the constraint at the given index.

+
+ + +
+
+
#   + + + def + LookupConstraint( + self, + constraint_name: 'std::string const &' +) -> 'operations_research::MPConstraint *': +
+ +
+ View Source +
    def LookupConstraint(self, constraint_name: "std::string const &") -> "operations_research::MPConstraint *":
+        r"""
+         Looks up a constraint by name, and returns nullptr if it does not exist.
+
+        The first call has a O(n) complexity, as the constraint name index is
+        lazily created upon first use. Will crash if constraint names are not
+        unique.
+        """
+        return _pywraplp.Solver_LookupConstraint(self, constraint_name)
+
+ +
+ +

Looks up a constraint by name, and returns nullptr if it does not exist.

+ +

The first call has a O(n) complexity, as the constraint name index is +lazily created upon first use. Will crash if constraint names are not +unique.

+
+ + +
+
+
#   + + + def + Constraint(self, *args) -> 'operations_research::MPConstraint *': +
+ +
+ View Source +
    def Constraint(self, *args) -> "operations_research::MPConstraint *":
+        r"""
+        *Overload 1:*
+
+        Creates a linear constraint with given bounds.
+
+        Bounds can be finite or +/- MPSolver::infinity(). The MPSolver class
+        assumes ownership of the constraint.
+
+        :rtype: :py:class:`MPConstraint`
+        :return: a pointer to the newly created constraint.
+
+        |
+
+        *Overload 2:*
+         Creates a constraint with -infinity and +infinity bounds.
+
+        |
+
+        *Overload 3:*
+         Creates a named constraint with given bounds.
+
+        |
+
+        *Overload 4:*
+         Creates a named constraint with -infinity and +infinity bounds.
+        """
+        return _pywraplp.Solver_Constraint(self, *args)
+
+ +
+ +

Overload 1:

+ +

Creates a linear constraint with given bounds.

+ +

Bounds can be finite or +/- MPSolver::infinity(). The MPSolver class +assumes ownership of the constraint.

+ +

:rtype: MPConstraint +:return: a pointer to the newly created constraint.

+ +

|

+ +

Overload 2: + Creates a constraint with -infinity and +infinity bounds.

+ +

|

+ +

Overload 3: + Creates a named constraint with given bounds.

+ +

|

+ +

Overload 4: + Creates a named constraint with -infinity and +infinity bounds.

+
+ + +
+
+
#   + + + def + Objective(self) -> 'operations_research::MPObjective *': +
+ +
+ View Source +
    def Objective(self) -> "operations_research::MPObjective *":
+        r""" Returns the mutable objective object."""
+        return _pywraplp.Solver_Objective(self)
+
+ +
+ +

Returns the mutable objective object.

+
+ + +
+
+
#   + + OPTIMAL = 0 +
+ + +

optimal.

+
+ + +
+
+
#   + + FEASIBLE = 1 +
+ + +

feasible, or stopped by limit.

+
+ + +
+
+
#   + + INFEASIBLE = 2 +
+ + +

proven infeasible.

+
+ + +
+
+
#   + + UNBOUNDED = 3 +
+ + +

proven unbounded.

+
+ + +
+
+
#   + + ABNORMAL = 4 +
+ + +

abnormal, i.e., error of some kind.

+
+ + +
+
+
#   + + NOT_SOLVED = 6 +
+ + +

not been solved yet.

+
+ + +
+
+
#   + + + def + Solve(self, *args) -> 'operations_research::MPSolver::ResultStatus': +
+ +
+ View Source +
    def Solve(self, *args) -> "operations_research::MPSolver::ResultStatus":
+        r"""
+        *Overload 1:*
+        Solves the problem using the default parameter values.
+
+        |
+
+        *Overload 2:*
+        Solves the problem using the specified parameter values.
+        """
+        return _pywraplp.Solver_Solve(self, *args)
+
+ +
+ +

Overload 1: +Solves the problem using the default parameter values.

+ +

|

+ +

Overload 2: +Solves the problem using the specified parameter values.

+
+ + +
+
+
#   + + + def + ComputeConstraintActivities(self) -> 'std::vector< double >': +
+ +
+ View Source +
    def ComputeConstraintActivities(self) -> "std::vector< double >":
+        r"""
+        Advanced usage: compute the "activities" of all constraints, which are the
+        sums of their linear terms. The activities are returned in the same order
+        as constraints(), which is the order in which constraints were added; but
+        you can also use MPConstraint::index() to get a constraint's index.
+        """
+        return _pywraplp.Solver_ComputeConstraintActivities(self)
+
+ +
+ +

Advanced usage: compute the "activities" of all constraints, which are the +sums of their linear terms. The activities are returned in the same order +as constraints(), which is the order in which constraints were added; but +you can also use MPConstraint::index() to get a constraint's index.

+
+ + +
+
+
#   + + + def + VerifySolution(self, tolerance: 'double', log_errors: bool) -> bool: +
+ +
+ View Source +
    def VerifySolution(self, tolerance: "double", log_errors: "bool") -> "bool":
+        r"""
+        Advanced usage: Verifies the *correctness* of the solution.
+
+        It verifies that all variables must be within their domains, all
+        constraints must be satisfied, and the reported objective value must be
+        accurate.
+
+        Usage:
+        - This can only be called after Solve() was called.
+        - "tolerance" is interpreted as an absolute error threshold.
+        - For the objective value only, if the absolute error is too large,
+          the tolerance is interpreted as a relative error threshold instead.
+        - If "log_errors" is true, every single violation will be logged.
+        - If "tolerance" is negative, it will be set to infinity().
+
+        Most users should just set the --verify_solution flag and not bother using
+        this method directly.
+        """
+        return _pywraplp.Solver_VerifySolution(self, tolerance, log_errors)
+
+ +
+ +

Advanced usage: Verifies the correctness of the solution.

+ +

It verifies that all variables must be within their domains, all +constraints must be satisfied, and the reported objective value must be +accurate.

+ +

Usage:

+ +
    +
  • This can only be called after Solve() was called.
  • +
  • "tolerance" is interpreted as an absolute error threshold.
  • +
  • For the objective value only, if the absolute error is too large, +the tolerance is interpreted as a relative error threshold instead.
  • +
  • If "log_errors" is true, every single violation will be logged.
  • +
  • If "tolerance" is negative, it will be set to infinity().
  • +
+ +

Most users should just set the --verify_solution flag and not bother using +this method directly.

+
+ + +
+
+
#   + + + def + InterruptSolve(self) -> bool: +
+ +
+ View Source +
    def InterruptSolve(self) -> "bool":
+        r"""
+         Interrupts the Solve() execution to terminate processing if possible.
+
+        If the underlying interface supports interruption; it does that and returns
+        true regardless of whether there's an ongoing Solve() or not. The Solve()
+        call may still linger for a while depending on the conditions.  If
+        interruption is not supported; returns false and does nothing.
+        MPSolver::SolverTypeSupportsInterruption can be used to check if
+        interruption is supported for a given solver type.
+        """
+        return _pywraplp.Solver_InterruptSolve(self)
+
+ +
+ +

Interrupts the Solve() execution to terminate processing if possible.

+ +

If the underlying interface supports interruption; it does that and returns +true regardless of whether there's an ongoing Solve() or not. The Solve() +call may still linger for a while depending on the conditions. If +interruption is not supported; returns false and does nothing. +MPSolver::SolverTypeSupportsInterruption can be used to check if +interruption is supported for a given solver type.

+
+ + +
+
+
#   + + + def + FillSolutionResponseProto( + self, + response: 'operations_research::MPSolutionResponse *' +) -> 'void': +
+ +
+ View Source +
    def FillSolutionResponseProto(self, response: "operations_research::MPSolutionResponse *") -> "void":
+        r""" Encodes the current solution in a solution response protocol buffer."""
+        return _pywraplp.Solver_FillSolutionResponseProto(self, response)
+
+ +
+ +

Encodes the current solution in a solution response protocol buffer.

+
+ + +
+
+
#   + +
@staticmethod
+ + def + SolveWithProto( + model_request: 'operations_research::MPModelRequest const &', + response: 'operations_research::MPSolutionResponse *', + interrupt: 'std::atomic< bool > *' = None +) -> 'operations_research::MPSolutionResponse *': +
+ +
+ View Source +
    @staticmethod
+    def SolveWithProto(model_request: "operations_research::MPModelRequest const &", response: "operations_research::MPSolutionResponse *", interrupt: "std::atomic< bool > *"=None) -> "operations_research::MPSolutionResponse *":
+        r"""
+        Solves the model encoded by a MPModelRequest protocol buffer and fills the
+        solution encoded as a MPSolutionResponse. The solve is stopped prematurely
+        if interrupt is non-null at set to true during (or before) solving.
+        Interruption is only supported if SolverTypeSupportsInterruption() returns
+        true for the requested solver. Passing a non-null interruption with any
+        other solver type immediately returns an MPSOLVER_INCOMPATIBLE_OPTIONS
+        error.
+
+        Note(user): This attempts to first use `DirectlySolveProto()` (if
+        implemented). Consequently, this most likely does *not* override any of
+        the default parameters of the underlying solver. This behavior *differs*
+        from `MPSolver::Solve()` which by default sets the feasibility tolerance
+        and the gap limit (as of 2020/02/11, to 1e-7 and 0.0001, respectively).
+        """
+        return _pywraplp.Solver_SolveWithProto(model_request, response, interrupt)
+
+ +
+ +

Solves the model encoded by a MPModelRequest protocol buffer and fills the +solution encoded as a MPSolutionResponse. The solve is stopped prematurely +if interrupt is non-null at set to true during (or before) solving. +Interruption is only supported if SolverTypeSupportsInterruption() returns +true for the requested solver. Passing a non-null interruption with any +other solver type immediately returns an MPSOLVER_INCOMPATIBLE_OPTIONS +error.

+ +

Note(user): This attempts to first use DirectlySolveProto() (if +implemented). Consequently, this most likely does not override any of +the default parameters of the underlying solver. This behavior differs +from MPSolver::Solve() which by default sets the feasibility tolerance +and the gap limit (as of 2020/02/11, to 1e-7 and 0.0001, respectively).

+
+ + +
+
+
#   + + + def + ExportModelToProto(self, output_model: 'operations_research::MPModelProto *') -> 'void': +
+ +
+ View Source +
    def ExportModelToProto(self, output_model: "operations_research::MPModelProto *") -> "void":
+        r""" Exports model to protocol buffer."""
+        return _pywraplp.Solver_ExportModelToProto(self, output_model)
+
+ +
+ +

Exports model to protocol buffer.

+
+ + +
+
+
#   + + + def + SetSolverSpecificParametersAsString(self, parameters: 'std::string const &') -> bool: +
+ +
+ View Source +
    def SetSolverSpecificParametersAsString(self, parameters: "std::string const &") -> "bool":
+        r"""
+        Advanced usage: pass solver specific parameters in text format.
+
+        The format is solver-specific and is the same as the corresponding solver
+        configuration file format. Returns true if the operation was successful.
+        """
+        return _pywraplp.Solver_SetSolverSpecificParametersAsString(self, parameters)
+
+ +
+ +

Advanced usage: pass solver specific parameters in text format.

+ +

The format is solver-specific and is the same as the corresponding solver +configuration file format. Returns true if the operation was successful.

+
+ + +
+
+
#   + + FREE = 0 +
+ + + + +
+
+
#   + + AT_LOWER_BOUND = 1 +
+ + + + +
+
+
#   + + AT_UPPER_BOUND = 2 +
+ + + + +
+
+
#   + + FIXED_VALUE = 3 +
+ + + + +
+
+
#   + + BASIC = 4 +
+ + + + +
+
+
#   + +
@staticmethod
+ + def + infinity() -> 'double': +
+ +
+ View Source +
    @staticmethod
+    def infinity() -> "double":
+        r"""
+        Infinity.
+
+        You can use -MPSolver::infinity() for negative infinity.
+        """
+        return _pywraplp.Solver_infinity()
+
+ +
+ +

Infinity.

+ +

You can use -MPSolver::infinity() for negative infinity.

+
+ + +
+
+
#   + + + def + EnableOutput(self) -> 'void': +
+ +
+ View Source +
    def EnableOutput(self) -> "void":
+        r""" Enables solver logging."""
+        return _pywraplp.Solver_EnableOutput(self)
+
+ +
+ +

Enables solver logging.

+
+ + +
+
+
#   + + + def + SuppressOutput(self) -> 'void': +
+ +
+ View Source +
    def SuppressOutput(self) -> "void":
+        r""" Suppresses solver logging."""
+        return _pywraplp.Solver_SuppressOutput(self)
+
+ +
+ +

Suppresses solver logging.

+
+ + +
+
+
#   + + + def + iterations(self) -> 'int64_t': +
+ +
+ View Source +
    def iterations(self) -> "int64_t":
+        r""" Returns the number of simplex iterations."""
+        return _pywraplp.Solver_iterations(self)
+
+ +
+ +

Returns the number of simplex iterations.

+
+ + +
+
+
#   + + + def + nodes(self) -> 'int64_t': +
+ +
+ View Source +
    def nodes(self) -> "int64_t":
+        r"""
+        Returns the number of branch-and-bound nodes evaluated during the solve.
+
+        Only available for discrete problems.
+        """
+        return _pywraplp.Solver_nodes(self)
+
+ +
+ +

Returns the number of branch-and-bound nodes evaluated during the solve.

+ +

Only available for discrete problems.

+
+ + +
+
+
#   + + + def + ComputeExactConditionNumber(self) -> 'double': +
+ +
+ View Source +
    def ComputeExactConditionNumber(self) -> "double":
+        r"""
+         Advanced usage: computes the exact condition number of the current scaled
+        basis: L1norm(B) * L1norm(inverse(B)), where B is the scaled basis.
+
+        This method requires that a basis exists: it should be called after Solve.
+        It is only available for continuous problems. It is implemented for GLPK
+        but not CLP because CLP does not provide the API for doing it.
+
+        The condition number measures how well the constraint matrix is conditioned
+        and can be used to predict whether numerical issues will arise during the
+        solve: the model is declared infeasible whereas it is feasible (or
+        vice-versa), the solution obtained is not optimal or violates some
+        constraints, the resolution is slow because of repeated singularities.
+
+        The rule of thumb to interpret the condition number kappa is:
+          - o kappa <= 1e7: virtually no chance of numerical issues
+          - o 1e7 < kappa <= 1e10: small chance of numerical issues
+          - o 1e10 < kappa <= 1e13: medium chance of numerical issues
+          - o kappa > 1e13: high chance of numerical issues
+
+        The computation of the condition number depends on the quality of the LU
+        decomposition, so it is not very accurate when the matrix is ill
+        conditioned.
+        """
+        return _pywraplp.Solver_ComputeExactConditionNumber(self)
+
+ +
+ +

Advanced usage: computes the exact condition number of the current scaled +basis: L1norm(B) * L1norm(inverse(B)), where B is the scaled basis.

+ +

This method requires that a basis exists: it should be called after Solve. +It is only available for continuous problems. It is implemented for GLPK +but not CLP because CLP does not provide the API for doing it.

+ +

The condition number measures how well the constraint matrix is conditioned +and can be used to predict whether numerical issues will arise during the +solve: the model is declared infeasible whereas it is feasible (or +vice-versa), the solution obtained is not optimal or violates some +constraints, the resolution is slow because of repeated singularities.

+ +
The rule of thumb to interpret the condition number kappa is
+ +
+
    +
  • o kappa <= 1e7: virtually no chance of numerical issues
  • +
  • o 1e7 < kappa <= 1e10: small chance of numerical issues
  • +
  • o 1e10 < kappa <= 1e13: medium chance of numerical issues
  • +
  • o kappa > 1e13: high chance of numerical issues
  • +
+
+ +

The computation of the condition number depends on the quality of the LU +decomposition, so it is not very accurate when the matrix is ill +conditioned.

+
+ + +
+
+
#   + + + def + NextSolution(self) -> bool: +
+ +
+ View Source +
    def NextSolution(self) -> "bool":
+        r"""
+        Some solvers (MIP only, not LP) can produce multiple solutions to the
+        problem. Returns true when another solution is available, and updates the
+        MPVariable* objects to make the new solution queryable. Call only after
+        calling solve.
+
+        The optimality properties of the additional solutions found, and whether or
+        not the solver computes them ahead of time or when NextSolution() is called
+        is solver specific.
+
+        As of 2020-02-10, only Gurobi and SCIP support NextSolution(), see
+        linear_solver_interfaces_test for an example of how to configure these
+        solvers for multiple solutions. Other solvers return false unconditionally.
+        """
+        return _pywraplp.Solver_NextSolution(self)
+
+ +
+ +

Some solvers (MIP only, not LP) can produce multiple solutions to the +problem. Returns true when another solution is available, and updates the +MPVariable* objects to make the new solution queryable. Call only after +calling solve.

+ +

The optimality properties of the additional solutions found, and whether or +not the solver computes them ahead of time or when NextSolution() is called +is solver specific.

+ +

As of 2020-02-10, only Gurobi and SCIP support NextSolution(), see +linear_solver_interfaces_test for an example of how to configure these +solvers for multiple solutions. Other solvers return false unconditionally.

+
+ + +
+
+
#   + + + def + set_time_limit(self, time_limit_milliseconds: 'int64_t') -> 'void': +
+ +
+ View Source +
    def set_time_limit(self, time_limit_milliseconds: "int64_t") -> "void":
+        return _pywraplp.Solver_set_time_limit(self, time_limit_milliseconds)
+
+ +
+ + + +
+
+
#   + + + def + wall_time(self) -> 'int64_t': +
+ +
+ View Source +
    def wall_time(self) -> "int64_t":
+        return _pywraplp.Solver_wall_time(self)
+
+ +
+ + + +
+
+
#   + + + def + LoadModelFromProto( + self, + input_model: 'operations_research::MPModelProto const &' +) -> 'std::string': +
+ +
+ View Source +
    def LoadModelFromProto(self, input_model: "operations_research::MPModelProto const &") -> "std::string":
+        return _pywraplp.Solver_LoadModelFromProto(self, input_model)
+
+ +
+ + + +
+
+
#   + + + def + LoadModelFromProtoWithUniqueNamesOrDie( + self, + input_model: 'operations_research::MPModelProto const &' +) -> 'std::string': +
+ +
+ View Source +
    def LoadModelFromProtoWithUniqueNamesOrDie(self, input_model: "operations_research::MPModelProto const &") -> "std::string":
+        return _pywraplp.Solver_LoadModelFromProtoWithUniqueNamesOrDie(self, input_model)
+
+ +
+ + + +
+
+
#   + + + def + LoadSolutionFromProto(self, *args) -> bool: +
+ +
+ View Source +
    def LoadSolutionFromProto(self, *args) -> "bool":
+        return _pywraplp.Solver_LoadSolutionFromProto(self, *args)
+
+ +
+ + + +
+
+
#   + + + def + ExportModelAsLpFormat(self, obfuscated: bool) -> 'std::string': +
+ +
+ View Source +
    def ExportModelAsLpFormat(self, obfuscated: "bool") -> "std::string":
+        return _pywraplp.Solver_ExportModelAsLpFormat(self, obfuscated)
+
+ +
+ + + +
+
+
#   + + + def + ExportModelAsMpsFormat(self, fixed_format: bool, obfuscated: bool) -> 'std::string': +
+ +
+ View Source +
    def ExportModelAsMpsFormat(self, fixed_format: "bool", obfuscated: "bool") -> "std::string":
+        return _pywraplp.Solver_ExportModelAsMpsFormat(self, fixed_format, obfuscated)
+
+ +
+ + + +
+
+
#   + + + def + SetHint( + self, + variables: 'std::vector< operations_research::MPVariable * > const &', + values: 'std::vector< double > const &' +) -> 'void': +
+ +
+ View Source +
    def SetHint(self, variables: "std::vector< operations_research::MPVariable * > const &", values: "std::vector< double > const &") -> "void":
+        r"""
+        Set a hint for solution.
+
+        If a feasible or almost-feasible solution to the problem is already known,
+        it may be helpful to pass it to the solver so that it can be used. A
+        solver that supports this feature will try to use this information to
+        create its initial feasible solution.
+
+        Note that it may not always be faster to give a hint like this to the
+        solver. There is also no guarantee that the solver will use this hint or
+        try to return a solution "close" to this assignment in case of multiple
+        optimal solutions.
+        """
+        return _pywraplp.Solver_SetHint(self, variables, values)
+
+ +
+ +

Set a hint for solution.

+ +

If a feasible or almost-feasible solution to the problem is already known, +it may be helpful to pass it to the solver so that it can be used. A +solver that supports this feature will try to use this information to +create its initial feasible solution.

+ +

Note that it may not always be faster to give a hint like this to the +solver. There is also no guarantee that the solver will use this hint or +try to return a solution "close" to this assignment in case of multiple +optimal solutions.

+
+ + +
+
+
#   + + + def + SetNumThreads(self, num_theads: int) -> bool: +
+ +
+ View Source +
    def SetNumThreads(self, num_theads: "int") -> "bool":
+        r""" Sets the number of threads to be used by the solver."""
+        return _pywraplp.Solver_SetNumThreads(self, num_theads)
+
+ +
+ +

Sets the number of threads to be used by the solver.

+
+ + +
+
+
#   + + + def + Add(self, constraint, name=''): +
+ +
+ View Source +
    def Add(self, constraint, name=''):
+      if isinstance(constraint, bool):
+        if constraint:
+          return self.RowConstraint(0, 0, name)
+        else:
+          return self.RowConstraint(1, 1, name)
+      else:
+        return constraint.Extract(self, name)
+
+ +
+ + + +
+
+
#   + + + def + Sum(self, expr_array): +
+ +
+ View Source +
    def Sum(self, expr_array):
+      result = SumArray(expr_array)
+      return result
+
+ +
+ + + +
+
+
#   + + + def + RowConstraint(self, *args): +
+ +
+ View Source +
    def RowConstraint(self, *args):
+      return self.Constraint(*args)
+
+ +
+ + + +
+
+
#   + + + def + Minimize(self, expr): +
+ +
+ View Source +
    def Minimize(self, expr):
+      objective = self.Objective()
+      objective.Clear()
+      objective.SetMinimization()
+      if isinstance(expr, numbers.Number):
+          objective.SetOffset(expr)
+      else:
+          coeffs = expr.GetCoeffs()
+          objective.SetOffset(coeffs.pop(OFFSET_KEY, 0.0))
+          for v, c, in list(coeffs.items()):
+            objective.SetCoefficient(v, float(c))
+
+ +
+ + + +
+
+
#   + + + def + Maximize(self, expr): +
+ +
+ View Source +
    def Maximize(self, expr):
+      objective = self.Objective()
+      objective.Clear()
+      objective.SetMaximization()
+      if isinstance(expr, numbers.Number):
+          objective.SetOffset(expr)
+      else:
+          coeffs = expr.GetCoeffs()
+          objective.SetOffset(coeffs.pop(OFFSET_KEY, 0.0))
+          for v, c, in list(coeffs.items()):
+            objective.SetCoefficient(v, float(c))
+
+ +
+ + + +
+
+
#   + +
@staticmethod
+ + def + Infinity() -> 'double': +
+ +
+ View Source +
    @staticmethod
+    def Infinity() -> "double":
+        return _pywraplp.Solver_Infinity()
+
+ +
+ + + +
+
+
#   + + + def + SetTimeLimit(self, x: 'int64_t') -> 'void': +
+ +
+ View Source +
    def SetTimeLimit(self, x: "int64_t") -> "void":
+        return _pywraplp.Solver_SetTimeLimit(self, x)
+
+ +
+ + + +
+
+
#   + + + def + WallTime(self) -> 'int64_t': +
+ +
+ View Source +
    def WallTime(self) -> "int64_t":
+        return _pywraplp.Solver_WallTime(self)
+
+ +
+ + + +
+
+
#   + + + def + Iterations(self) -> 'int64_t': +
+ +
+ View Source +
    def Iterations(self) -> "int64_t":
+        return _pywraplp.Solver_Iterations(self)
+
+ +
+ + + +
+
+
+
#   + + + def + Solver_CreateSolver( + solver_id: 'std::string const &' +) -> 'operations_research::MPSolver *': +
+ +
+ View Source +
def Solver_CreateSolver(solver_id: "std::string const &") -> "operations_research::MPSolver *":
+    r"""
+    Recommended factory method to create a MPSolver instance, especially in
+    non C++ languages.
+
+    It returns a newly created solver instance if successful, or a nullptr
+    otherwise. This can occur if the relevant interface is not linked in, or if
+    a needed license is not accessible for commercial solvers.
+
+    Ownership of the solver is passed on to the caller of this method.
+    It will accept both string names of the OptimizationProblemType enum, as
+    well as a short version (i.e. "SCIP_MIXED_INTEGER_PROGRAMMING" or "SCIP").
+
+    solver_id is case insensitive, and the following names are supported:
+      - CLP_LINEAR_PROGRAMMING or CLP
+      - CBC_MIXED_INTEGER_PROGRAMMING or CBC
+      - GLOP_LINEAR_PROGRAMMING or GLOP
+      - BOP_INTEGER_PROGRAMMING or BOP
+      - SAT_INTEGER_PROGRAMMING or SAT or CP_SAT
+      - SCIP_MIXED_INTEGER_PROGRAMMING or SCIP
+      - GUROBI_LINEAR_PROGRAMMING or GUROBI_LP
+      - GUROBI_MIXED_INTEGER_PROGRAMMING or GUROBI or GUROBI_MIP
+      - CPLEX_LINEAR_PROGRAMMING or CPLEX_LP
+      - CPLEX_MIXED_INTEGER_PROGRAMMING or CPLEX or CPLEX_MIP
+      - XPRESS_LINEAR_PROGRAMMING or XPRESS_LP
+      - XPRESS_MIXED_INTEGER_PROGRAMMING or XPRESS or XPRESS_MIP
+      - GLPK_LINEAR_PROGRAMMING or GLPK_LP
+      - GLPK_MIXED_INTEGER_PROGRAMMING or GLPK or GLPK_MIP
+    """
+    return _pywraplp.Solver_CreateSolver(solver_id)
+
+ +
+ +

Recommended factory method to create a MPSolver instance, especially in +non C++ languages.

+ +

It returns a newly created solver instance if successful, or a nullptr +otherwise. This can occur if the relevant interface is not linked in, or if +a needed license is not accessible for commercial solvers.

+ +

Ownership of the solver is passed on to the caller of this method. +It will accept both string names of the OptimizationProblemType enum, as +well as a short version (i.e. "SCIP_MIXED_INTEGER_PROGRAMMING" or "SCIP").

+ +

solver_id is case insensitive, and the following names are supported:

+ +
    +
  • CLP_LINEAR_PROGRAMMING or CLP
  • +
  • CBC_MIXED_INTEGER_PROGRAMMING or CBC
  • +
  • GLOP_LINEAR_PROGRAMMING or GLOP
  • +
  • BOP_INTEGER_PROGRAMMING or BOP
  • +
  • SAT_INTEGER_PROGRAMMING or SAT or CP_SAT
  • +
  • SCIP_MIXED_INTEGER_PROGRAMMING or SCIP
  • +
  • GUROBI_LINEAR_PROGRAMMING or GUROBI_LP
  • +
  • GUROBI_MIXED_INTEGER_PROGRAMMING or GUROBI or GUROBI_MIP
  • +
  • CPLEX_LINEAR_PROGRAMMING or CPLEX_LP
  • +
  • CPLEX_MIXED_INTEGER_PROGRAMMING or CPLEX or CPLEX_MIP
  • +
  • XPRESS_LINEAR_PROGRAMMING or XPRESS_LP
  • +
  • XPRESS_MIXED_INTEGER_PROGRAMMING or XPRESS or XPRESS_MIP
  • +
  • GLPK_LINEAR_PROGRAMMING or GLPK_LP
  • +
  • GLPK_MIXED_INTEGER_PROGRAMMING or GLPK or GLPK_MIP
  • +
+
+ + +
+
+
#   + + + def + Solver_SupportsProblemType( + problem_type: 'operations_research::MPSolver::OptimizationProblemType' +) -> bool: +
+ +
+ View Source +
def Solver_SupportsProblemType(problem_type: "operations_research::MPSolver::OptimizationProblemType") -> "bool":
+    r"""
+    Whether the given problem type is supported (this will depend on the
+    targets that you linked).
+    """
+    return _pywraplp.Solver_SupportsProblemType(problem_type)
+
+ +
+ +

Whether the given problem type is supported (this will depend on the +targets that you linked).

+
+ + +
+
+
#   + + + def + Solver_SolveWithProto( + model_request: 'operations_research::MPModelRequest const &', + response: 'operations_research::MPSolutionResponse *', + interrupt: 'std::atomic< bool > *' = None +) -> 'operations_research::MPSolutionResponse *': +
+ +
+ View Source +
def Solver_SolveWithProto(model_request: "operations_research::MPModelRequest const &", response: "operations_research::MPSolutionResponse *", interrupt: "std::atomic< bool > *"=None) -> "operations_research::MPSolutionResponse *":
+    r"""
+    Solves the model encoded by a MPModelRequest protocol buffer and fills the
+    solution encoded as a MPSolutionResponse. The solve is stopped prematurely
+    if interrupt is non-null at set to true during (or before) solving.
+    Interruption is only supported if SolverTypeSupportsInterruption() returns
+    true for the requested solver. Passing a non-null interruption with any
+    other solver type immediately returns an MPSOLVER_INCOMPATIBLE_OPTIONS
+    error.
+
+    Note(user): This attempts to first use `DirectlySolveProto()` (if
+    implemented). Consequently, this most likely does *not* override any of
+    the default parameters of the underlying solver. This behavior *differs*
+    from `MPSolver::Solve()` which by default sets the feasibility tolerance
+    and the gap limit (as of 2020/02/11, to 1e-7 and 0.0001, respectively).
+    """
+    return _pywraplp.Solver_SolveWithProto(model_request, response, interrupt)
+
+ +
+ +

Solves the model encoded by a MPModelRequest protocol buffer and fills the +solution encoded as a MPSolutionResponse. The solve is stopped prematurely +if interrupt is non-null at set to true during (or before) solving. +Interruption is only supported if SolverTypeSupportsInterruption() returns +true for the requested solver. Passing a non-null interruption with any +other solver type immediately returns an MPSOLVER_INCOMPATIBLE_OPTIONS +error.

+ +

Note(user): This attempts to first use DirectlySolveProto() (if +implemented). Consequently, this most likely does not override any of +the default parameters of the underlying solver. This behavior differs +from MPSolver::Solve() which by default sets the feasibility tolerance +and the gap limit (as of 2020/02/11, to 1e-7 and 0.0001, respectively).

+
+ + +
+
+
#   + + + def + Solver_infinity() -> 'double': +
+ +
+ View Source +
def Solver_infinity() -> "double":
+    r"""
+    Infinity.
+
+    You can use -MPSolver::infinity() for negative infinity.
+    """
+    return _pywraplp.Solver_infinity()
+
+ +
+ +

Infinity.

+ +

You can use -MPSolver::infinity() for negative infinity.

+
+ + +
+
+
#   + + + def + Solver_Infinity() -> 'double': +
+ +
+ View Source +
def Solver_Infinity() -> "double":
+    return _pywraplp.Solver_Infinity()
+
+ +
+ + + +
+
+
+ #   + + + class + Objective: +
+ +
+ View Source +
class Objective(object):
+    r""" A class to express a linear objective."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def Clear(self) -> "void":
+        r"""
+         Clears the offset, all variables and coefficients, and the optimization
+        direction.
+        """
+        return _pywraplp.Objective_Clear(self)
+
+    def SetCoefficient(self, var: "Variable", coeff: "double") -> "void":
+        r"""
+        Sets the coefficient of the variable in the objective.
+
+        If the variable does not belong to the solver, the function just returns,
+        or crashes in non-opt mode.
+        """
+        return _pywraplp.Objective_SetCoefficient(self, var, coeff)
+
+    def GetCoefficient(self, var: "Variable") -> "double":
+        r"""
+         Gets the coefficient of a given variable in the objective
+
+        It returns 0 if the variable does not appear in the objective).
+        """
+        return _pywraplp.Objective_GetCoefficient(self, var)
+
+    def SetOffset(self, value: "double") -> "void":
+        r""" Sets the constant term in the objective."""
+        return _pywraplp.Objective_SetOffset(self, value)
+
+    def offset(self) -> "double":
+        r""" Gets the constant term in the objective."""
+        return _pywraplp.Objective_offset(self)
+
+    def SetOptimizationDirection(self, maximize: "bool") -> "void":
+        r""" Sets the optimization direction (maximize: true or minimize: false)."""
+        return _pywraplp.Objective_SetOptimizationDirection(self, maximize)
+
+    def SetMinimization(self) -> "void":
+        r""" Sets the optimization direction to minimize."""
+        return _pywraplp.Objective_SetMinimization(self)
+
+    def SetMaximization(self) -> "void":
+        r""" Sets the optimization direction to maximize."""
+        return _pywraplp.Objective_SetMaximization(self)
+
+    def maximization(self) -> "bool":
+        r""" Is the optimization direction set to maximize?"""
+        return _pywraplp.Objective_maximization(self)
+
+    def minimization(self) -> "bool":
+        r""" Is the optimization direction set to minimize?"""
+        return _pywraplp.Objective_minimization(self)
+
+    def Value(self) -> "double":
+        r"""
+        Returns the objective value of the best solution found so far.
+
+        It is the optimal objective value if the problem has been solved to
+        optimality.
+
+        Note: the objective value may be slightly different than what you could
+        compute yourself using ``MPVariable::solution_value();`` please use the
+        --verify_solution flag to gain confidence about the numerical stability of
+        your solution.
+        """
+        return _pywraplp.Objective_Value(self)
+
+    def BestBound(self) -> "double":
+        r"""
+        Returns the best objective bound.
+
+        In case of minimization, it is a lower bound on the objective value of the
+        optimal integer solution. Only available for discrete problems.
+        """
+        return _pywraplp.Objective_BestBound(self)
+
+    def Offset(self) -> "double":
+        return _pywraplp.Objective_Offset(self)
+    __swig_destroy__ = _pywraplp.delete_Objective
+
+ +
+ +

A class to express a linear objective.

+
+ + +
+
#   + + + Objective(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + Clear(self) -> 'void': +
+ +
+ View Source +
    def Clear(self) -> "void":
+        r"""
+         Clears the offset, all variables and coefficients, and the optimization
+        direction.
+        """
+        return _pywraplp.Objective_Clear(self)
+
+ +
+ +

Clears the offset, all variables and coefficients, and the optimization +direction.

+
+ + +
+
+
#   + + + def + SetCoefficient( + self, + var: ortools.linear_solver.pywraplp.Variable, + coeff: 'double' +) -> 'void': +
+ +
+ View Source +
    def SetCoefficient(self, var: "Variable", coeff: "double") -> "void":
+        r"""
+        Sets the coefficient of the variable in the objective.
+
+        If the variable does not belong to the solver, the function just returns,
+        or crashes in non-opt mode.
+        """
+        return _pywraplp.Objective_SetCoefficient(self, var, coeff)
+
+ +
+ +

Sets the coefficient of the variable in the objective.

+ +

If the variable does not belong to the solver, the function just returns, +or crashes in non-opt mode.

+
+ + +
+
+
#   + + + def + GetCoefficient(self, var: ortools.linear_solver.pywraplp.Variable) -> 'double': +
+ +
+ View Source +
    def GetCoefficient(self, var: "Variable") -> "double":
+        r"""
+         Gets the coefficient of a given variable in the objective
+
+        It returns 0 if the variable does not appear in the objective).
+        """
+        return _pywraplp.Objective_GetCoefficient(self, var)
+
+ +
+ +

Gets the coefficient of a given variable in the objective

+ +

It returns 0 if the variable does not appear in the objective).

+
+ + +
+
+
#   + + + def + SetOffset(self, value: 'double') -> 'void': +
+ +
+ View Source +
    def SetOffset(self, value: "double") -> "void":
+        r""" Sets the constant term in the objective."""
+        return _pywraplp.Objective_SetOffset(self, value)
+
+ +
+ +

Sets the constant term in the objective.

+
+ + +
+
+
#   + + + def + offset(self) -> 'double': +
+ +
+ View Source +
    def offset(self) -> "double":
+        r""" Gets the constant term in the objective."""
+        return _pywraplp.Objective_offset(self)
+
+ +
+ +

Gets the constant term in the objective.

+
+ + +
+
+
#   + + + def + SetOptimizationDirection(self, maximize: bool) -> 'void': +
+ +
+ View Source +
    def SetOptimizationDirection(self, maximize: "bool") -> "void":
+        r""" Sets the optimization direction (maximize: true or minimize: false)."""
+        return _pywraplp.Objective_SetOptimizationDirection(self, maximize)
+
+ +
+ +

Sets the optimization direction (maximize: true or minimize: false).

+
+ + +
+
+
#   + + + def + SetMinimization(self) -> 'void': +
+ +
+ View Source +
    def SetMinimization(self) -> "void":
+        r""" Sets the optimization direction to minimize."""
+        return _pywraplp.Objective_SetMinimization(self)
+
+ +
+ +

Sets the optimization direction to minimize.

+
+ + +
+
+
#   + + + def + SetMaximization(self) -> 'void': +
+ +
+ View Source +
    def SetMaximization(self) -> "void":
+        r""" Sets the optimization direction to maximize."""
+        return _pywraplp.Objective_SetMaximization(self)
+
+ +
+ +

Sets the optimization direction to maximize.

+
+ + +
+
+
#   + + + def + maximization(self) -> bool: +
+ +
+ View Source +
    def maximization(self) -> "bool":
+        r""" Is the optimization direction set to maximize?"""
+        return _pywraplp.Objective_maximization(self)
+
+ +
+ +

Is the optimization direction set to maximize?

+
+ + +
+
+
#   + + + def + minimization(self) -> bool: +
+ +
+ View Source +
    def minimization(self) -> "bool":
+        r""" Is the optimization direction set to minimize?"""
+        return _pywraplp.Objective_minimization(self)
+
+ +
+ +

Is the optimization direction set to minimize?

+
+ + +
+
+
#   + + + def + Value(self) -> 'double': +
+ +
+ View Source +
    def Value(self) -> "double":
+        r"""
+        Returns the objective value of the best solution found so far.
+
+        It is the optimal objective value if the problem has been solved to
+        optimality.
+
+        Note: the objective value may be slightly different than what you could
+        compute yourself using ``MPVariable::solution_value();`` please use the
+        --verify_solution flag to gain confidence about the numerical stability of
+        your solution.
+        """
+        return _pywraplp.Objective_Value(self)
+
+ +
+ +

Returns the objective value of the best solution found so far.

+ +

It is the optimal objective value if the problem has been solved to +optimality.

+ +

Note: the objective value may be slightly different than what you could +compute yourself using MPVariable::solution_value(); please use the +--verify_solution flag to gain confidence about the numerical stability of +your solution.

+
+ + +
+
+
#   + + + def + BestBound(self) -> 'double': +
+ +
+ View Source +
    def BestBound(self) -> "double":
+        r"""
+        Returns the best objective bound.
+
+        In case of minimization, it is a lower bound on the objective value of the
+        optimal integer solution. Only available for discrete problems.
+        """
+        return _pywraplp.Objective_BestBound(self)
+
+ +
+ +

Returns the best objective bound.

+ +

In case of minimization, it is a lower bound on the objective value of the +optimal integer solution. Only available for discrete problems.

+
+ + +
+
+
#   + + + def + Offset(self) -> 'double': +
+ +
+ View Source +
    def Offset(self) -> "double":
+        return _pywraplp.Objective_Offset(self)
+
+ +
+ + + +
+
+
+
+ #   + + + class + Variable: +
+ +
+ View Source +
class Variable(object):
+    r""" The class for variables of a Mathematical Programming (MP) model."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+    def name(self) -> "std::string const &":
+        r""" Returns the name of the variable."""
+        return _pywraplp.Variable_name(self)
+
+    def SetInteger(self, integer: "bool") -> "void":
+        r""" Sets the integrality requirement of the variable."""
+        return _pywraplp.Variable_SetInteger(self, integer)
+
+    def integer(self) -> "bool":
+        r""" Returns the integrality requirement of the variable."""
+        return _pywraplp.Variable_integer(self)
+
+    def solution_value(self) -> "double":
+        r"""
+        Returns the value of the variable in the current solution.
+
+        If the variable is integer, then the value will always be an integer (the
+        underlying solver handles floating-point values only, but this function
+        automatically rounds it to the nearest integer; see: man 3 round).
+        """
+        return _pywraplp.Variable_solution_value(self)
+
+    def index(self) -> "int":
+        r""" Returns the index of the variable in the MPSolver::variables_."""
+        return _pywraplp.Variable_index(self)
+
+    def lb(self) -> "double":
+        r""" Returns the lower bound."""
+        return _pywraplp.Variable_lb(self)
+
+    def ub(self) -> "double":
+        r""" Returns the upper bound."""
+        return _pywraplp.Variable_ub(self)
+
+    def SetBounds(self, lb: "double", ub: "double") -> "void":
+        r""" Sets both the lower and upper bounds."""
+        return _pywraplp.Variable_SetBounds(self, lb, ub)
+
+    def reduced_cost(self) -> "double":
+        r"""
+        Advanced usage: returns the reduced cost of the variable in the current
+        solution (only available for continuous problems).
+        """
+        return _pywraplp.Variable_reduced_cost(self)
+
+    def basis_status(self) -> "operations_research::MPSolver::BasisStatus":
+        r"""
+        Advanced usage: returns the basis status of the variable in the current
+        solution (only available for continuous problems).
+
+        See also: MPSolver::BasisStatus.
+        """
+        return _pywraplp.Variable_basis_status(self)
+
+    def branching_priority(self) -> "int":
+        r"""
+        Advanced usage: Certain MIP solvers (e.g. Gurobi or SCIP) allow you to set
+        a per-variable priority for determining which variable to branch on.
+
+        A value of 0 is treated as default, and is equivalent to not setting the
+        branching priority. The solver looks first to branch on fractional
+        variables in higher priority levels. As of 2019-05, only Gurobi and SCIP
+        support setting branching priority; all other solvers will simply ignore
+        this annotation.
+        """
+        return _pywraplp.Variable_branching_priority(self)
+
+    def SetBranchingPriority(self, priority: "int") -> "void":
+        return _pywraplp.Variable_SetBranchingPriority(self, priority)
+
+    def __str__(self) -> "std::string":
+        return _pywraplp.Variable___str__(self)
+
+    def __repr__(self) -> "std::string":
+        return _pywraplp.Variable___repr__(self)
+
+    def __getattr__(self, name):
+      return getattr(VariableExpr(self), name)
+
+
+    def SolutionValue(self) -> "double":
+        return _pywraplp.Variable_SolutionValue(self)
+
+    def Integer(self) -> "bool":
+        return _pywraplp.Variable_Integer(self)
+
+    def Lb(self) -> "double":
+        return _pywraplp.Variable_Lb(self)
+
+    def Ub(self) -> "double":
+        return _pywraplp.Variable_Ub(self)
+
+    def SetLb(self, x: "double") -> "void":
+        return _pywraplp.Variable_SetLb(self, x)
+
+    def SetUb(self, x: "double") -> "void":
+        return _pywraplp.Variable_SetUb(self, x)
+
+    def ReducedCost(self) -> "double":
+        return _pywraplp.Variable_ReducedCost(self)
+    __swig_destroy__ = _pywraplp.delete_Variable
+
+ +
+ +

The class for variables of a Mathematical Programming (MP) model.

+
+ + +
+
#   + + + Variable(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + name(self) -> 'std::string const &': +
+ +
+ View Source +
    def name(self) -> "std::string const &":
+        r""" Returns the name of the variable."""
+        return _pywraplp.Variable_name(self)
+
+ +
+ +

Returns the name of the variable.

+
+ + +
+
+
#   + + + def + SetInteger(self, integer: bool) -> 'void': +
+ +
+ View Source +
    def SetInteger(self, integer: "bool") -> "void":
+        r""" Sets the integrality requirement of the variable."""
+        return _pywraplp.Variable_SetInteger(self, integer)
+
+ +
+ +

Sets the integrality requirement of the variable.

+
+ + +
+
+
#   + + + def + integer(self) -> bool: +
+ +
+ View Source +
    def integer(self) -> "bool":
+        r""" Returns the integrality requirement of the variable."""
+        return _pywraplp.Variable_integer(self)
+
+ +
+ +

Returns the integrality requirement of the variable.

+
+ + +
+
+
#   + + + def + solution_value(self) -> 'double': +
+ +
+ View Source +
    def solution_value(self) -> "double":
+        r"""
+        Returns the value of the variable in the current solution.
+
+        If the variable is integer, then the value will always be an integer (the
+        underlying solver handles floating-point values only, but this function
+        automatically rounds it to the nearest integer; see: man 3 round).
+        """
+        return _pywraplp.Variable_solution_value(self)
+
+ +
+ +

Returns the value of the variable in the current solution.

+ +

If the variable is integer, then the value will always be an integer (the +underlying solver handles floating-point values only, but this function +automatically rounds it to the nearest integer; see: man 3 round).

+
+ + +
+
+
#   + + + def + index(self) -> int: +
+ +
+ View Source +
    def index(self) -> "int":
+        r""" Returns the index of the variable in the MPSolver::variables_."""
+        return _pywraplp.Variable_index(self)
+
+ +
+ +

Returns the index of the variable in the MPSolver::variables_.

+
+ + +
+
+
#   + + + def + lb(self) -> 'double': +
+ +
+ View Source +
    def lb(self) -> "double":
+        r""" Returns the lower bound."""
+        return _pywraplp.Variable_lb(self)
+
+ +
+ +

Returns the lower bound.

+
+ + +
+
+
#   + + + def + ub(self) -> 'double': +
+ +
+ View Source +
    def ub(self) -> "double":
+        r""" Returns the upper bound."""
+        return _pywraplp.Variable_ub(self)
+
+ +
+ +

Returns the upper bound.

+
+ + +
+
+
#   + + + def + SetBounds(self, lb: 'double', ub: 'double') -> 'void': +
+ +
+ View Source +
    def SetBounds(self, lb: "double", ub: "double") -> "void":
+        r""" Sets both the lower and upper bounds."""
+        return _pywraplp.Variable_SetBounds(self, lb, ub)
+
+ +
+ +

Sets both the lower and upper bounds.

+
+ + +
+
+
#   + + + def + reduced_cost(self) -> 'double': +
+ +
+ View Source +
    def reduced_cost(self) -> "double":
+        r"""
+        Advanced usage: returns the reduced cost of the variable in the current
+        solution (only available for continuous problems).
+        """
+        return _pywraplp.Variable_reduced_cost(self)
+
+ +
+ +

Advanced usage: returns the reduced cost of the variable in the current +solution (only available for continuous problems).

+
+ + +
+
+
#   + + + def + basis_status(self) -> 'operations_research::MPSolver::BasisStatus': +
+ +
+ View Source +
    def basis_status(self) -> "operations_research::MPSolver::BasisStatus":
+        r"""
+        Advanced usage: returns the basis status of the variable in the current
+        solution (only available for continuous problems).
+
+        See also: MPSolver::BasisStatus.
+        """
+        return _pywraplp.Variable_basis_status(self)
+
+ +
+ +

Advanced usage: returns the basis status of the variable in the current +solution (only available for continuous problems).

+ +

See also: MPSolver::BasisStatus.

+
+ + +
+
+
#   + + + def + branching_priority(self) -> int: +
+ +
+ View Source +
    def branching_priority(self) -> "int":
+        r"""
+        Advanced usage: Certain MIP solvers (e.g. Gurobi or SCIP) allow you to set
+        a per-variable priority for determining which variable to branch on.
+
+        A value of 0 is treated as default, and is equivalent to not setting the
+        branching priority. The solver looks first to branch on fractional
+        variables in higher priority levels. As of 2019-05, only Gurobi and SCIP
+        support setting branching priority; all other solvers will simply ignore
+        this annotation.
+        """
+        return _pywraplp.Variable_branching_priority(self)
+
+ +
+ +

Advanced usage: Certain MIP solvers (e.g. Gurobi or SCIP) allow you to set +a per-variable priority for determining which variable to branch on.

+ +

A value of 0 is treated as default, and is equivalent to not setting the +branching priority. The solver looks first to branch on fractional +variables in higher priority levels. As of 2019-05, only Gurobi and SCIP +support setting branching priority; all other solvers will simply ignore +this annotation.

+
+ + +
+
+
#   + + + def + SetBranchingPriority(self, priority: int) -> 'void': +
+ +
+ View Source +
    def SetBranchingPriority(self, priority: "int") -> "void":
+        return _pywraplp.Variable_SetBranchingPriority(self, priority)
+
+ +
+ + + +
+
+
#   + + + def + SolutionValue(self) -> 'double': +
+ +
+ View Source +
    def SolutionValue(self) -> "double":
+        return _pywraplp.Variable_SolutionValue(self)
+
+ +
+ + + +
+
+
#   + + + def + Integer(self) -> bool: +
+ +
+ View Source +
    def Integer(self) -> "bool":
+        return _pywraplp.Variable_Integer(self)
+
+ +
+ + + +
+
+
#   + + + def + Lb(self) -> 'double': +
+ +
+ View Source +
    def Lb(self) -> "double":
+        return _pywraplp.Variable_Lb(self)
+
+ +
+ + + +
+
+
#   + + + def + Ub(self) -> 'double': +
+ +
+ View Source +
    def Ub(self) -> "double":
+        return _pywraplp.Variable_Ub(self)
+
+ +
+ + + +
+
+
#   + + + def + SetLb(self, x: 'double') -> 'void': +
+ +
+ View Source +
    def SetLb(self, x: "double") -> "void":
+        return _pywraplp.Variable_SetLb(self, x)
+
+ +
+ + + +
+
+
#   + + + def + SetUb(self, x: 'double') -> 'void': +
+ +
+ View Source +
    def SetUb(self, x: "double") -> "void":
+        return _pywraplp.Variable_SetUb(self, x)
+
+ +
+ + + +
+
+
#   + + + def + ReducedCost(self) -> 'double': +
+ +
+ View Source +
    def ReducedCost(self) -> "double":
+        return _pywraplp.Variable_ReducedCost(self)
+
+ +
+ + + +
+
+
+
+ #   + + + class + Constraint: +
+ +
+ View Source +
class Constraint(object):
+    r"""
+    The class for constraints of a Mathematical Programming (MP) model.
+
+    A constraint is represented as a linear equation or inequality.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+    __repr__ = _swig_repr
+
+    def name(self) -> "std::string const &":
+        r""" Returns the name of the constraint."""
+        return _pywraplp.Constraint_name(self)
+
+    def Clear(self) -> "void":
+        r""" Clears all variables and coefficients. Does not clear the bounds."""
+        return _pywraplp.Constraint_Clear(self)
+
+    def SetCoefficient(self, var: "Variable", coeff: "double") -> "void":
+        r"""
+        Sets the coefficient of the variable on the constraint.
+
+        If the variable does not belong to the solver, the function just returns,
+        or crashes in non-opt mode.
+        """
+        return _pywraplp.Constraint_SetCoefficient(self, var, coeff)
+
+    def GetCoefficient(self, var: "Variable") -> "double":
+        r"""
+        Gets the coefficient of a given variable on the constraint (which is 0 if
+        the variable does not appear in the constraint).
+        """
+        return _pywraplp.Constraint_GetCoefficient(self, var)
+
+    def lb(self) -> "double":
+        r""" Returns the lower bound."""
+        return _pywraplp.Constraint_lb(self)
+
+    def ub(self) -> "double":
+        r""" Returns the upper bound."""
+        return _pywraplp.Constraint_ub(self)
+
+    def SetBounds(self, lb: "double", ub: "double") -> "void":
+        r""" Sets both the lower and upper bounds."""
+        return _pywraplp.Constraint_SetBounds(self, lb, ub)
+
+    def set_is_lazy(self, laziness: "bool") -> "void":
+        r"""
+        Advanced usage: sets the constraint "laziness".
+
+        **This is only supported for SCIP and has no effect on other
+        solvers.**
+
+        When **laziness** is true, the constraint is only considered by the Linear
+        Programming solver if its current solution violates the constraint. In this
+        case, the constraint is definitively added to the problem. This may be
+        useful in some MIP problems, and may have a dramatic impact on performance.
+
+        For more info see: http://tinyurl.com/lazy-constraints.
+        """
+        return _pywraplp.Constraint_set_is_lazy(self, laziness)
+
+    def index(self) -> "int":
+        r""" Returns the index of the constraint in the MPSolver::constraints_."""
+        return _pywraplp.Constraint_index(self)
+
+    def dual_value(self) -> "double":
+        r"""
+        Advanced usage: returns the dual value of the constraint in the current
+        solution (only available for continuous problems).
+        """
+        return _pywraplp.Constraint_dual_value(self)
+
+    def basis_status(self) -> "operations_research::MPSolver::BasisStatus":
+        r"""
+        Advanced usage: returns the basis status of the constraint.
+
+        It is only available for continuous problems).
+
+        Note that if a constraint "linear_expression in [lb, ub]" is transformed
+        into "linear_expression + slack = 0" with slack in [-ub, -lb], then this
+        status is the same as the status of the slack variable with AT_UPPER_BOUND
+        and AT_LOWER_BOUND swapped.
+
+        See also: MPSolver::BasisStatus.
+        """
+        return _pywraplp.Constraint_basis_status(self)
+
+    def Lb(self) -> "double":
+        return _pywraplp.Constraint_Lb(self)
+
+    def Ub(self) -> "double":
+        return _pywraplp.Constraint_Ub(self)
+
+    def SetLb(self, x: "double") -> "void":
+        return _pywraplp.Constraint_SetLb(self, x)
+
+    def SetUb(self, x: "double") -> "void":
+        return _pywraplp.Constraint_SetUb(self, x)
+
+    def DualValue(self) -> "double":
+        return _pywraplp.Constraint_DualValue(self)
+    __swig_destroy__ = _pywraplp.delete_Constraint
+
+ +
+ +

The class for constraints of a Mathematical Programming (MP) model.

+ +

A constraint is represented as a linear equation or inequality.

+
+ + +
+
#   + + + Constraint(*args, **kwargs) +
+ +
+ View Source +
    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + + def + name(self) -> 'std::string const &': +
+ +
+ View Source +
    def name(self) -> "std::string const &":
+        r""" Returns the name of the constraint."""
+        return _pywraplp.Constraint_name(self)
+
+ +
+ +

Returns the name of the constraint.

+
+ + +
+
+
#   + + + def + Clear(self) -> 'void': +
+ +
+ View Source +
    def Clear(self) -> "void":
+        r""" Clears all variables and coefficients. Does not clear the bounds."""
+        return _pywraplp.Constraint_Clear(self)
+
+ +
+ +

Clears all variables and coefficients. Does not clear the bounds.

+
+ + +
+
+
#   + + + def + SetCoefficient( + self, + var: ortools.linear_solver.pywraplp.Variable, + coeff: 'double' +) -> 'void': +
+ +
+ View Source +
    def SetCoefficient(self, var: "Variable", coeff: "double") -> "void":
+        r"""
+        Sets the coefficient of the variable on the constraint.
+
+        If the variable does not belong to the solver, the function just returns,
+        or crashes in non-opt mode.
+        """
+        return _pywraplp.Constraint_SetCoefficient(self, var, coeff)
+
+ +
+ +

Sets the coefficient of the variable on the constraint.

+ +

If the variable does not belong to the solver, the function just returns, +or crashes in non-opt mode.

+
+ + +
+
+
#   + + + def + GetCoefficient(self, var: ortools.linear_solver.pywraplp.Variable) -> 'double': +
+ +
+ View Source +
    def GetCoefficient(self, var: "Variable") -> "double":
+        r"""
+        Gets the coefficient of a given variable on the constraint (which is 0 if
+        the variable does not appear in the constraint).
+        """
+        return _pywraplp.Constraint_GetCoefficient(self, var)
+
+ +
+ +

Gets the coefficient of a given variable on the constraint (which is 0 if +the variable does not appear in the constraint).

+
+ + +
+
+
#   + + + def + lb(self) -> 'double': +
+ +
+ View Source +
    def lb(self) -> "double":
+        r""" Returns the lower bound."""
+        return _pywraplp.Constraint_lb(self)
+
+ +
+ +

Returns the lower bound.

+
+ + +
+
+
#   + + + def + ub(self) -> 'double': +
+ +
+ View Source +
    def ub(self) -> "double":
+        r""" Returns the upper bound."""
+        return _pywraplp.Constraint_ub(self)
+
+ +
+ +

Returns the upper bound.

+
+ + +
+
+
#   + + + def + SetBounds(self, lb: 'double', ub: 'double') -> 'void': +
+ +
+ View Source +
    def SetBounds(self, lb: "double", ub: "double") -> "void":
+        r""" Sets both the lower and upper bounds."""
+        return _pywraplp.Constraint_SetBounds(self, lb, ub)
+
+ +
+ +

Sets both the lower and upper bounds.

+
+ + +
+
+
#   + + + def + set_is_lazy(self, laziness: bool) -> 'void': +
+ +
+ View Source +
    def set_is_lazy(self, laziness: "bool") -> "void":
+        r"""
+        Advanced usage: sets the constraint "laziness".
+
+        **This is only supported for SCIP and has no effect on other
+        solvers.**
+
+        When **laziness** is true, the constraint is only considered by the Linear
+        Programming solver if its current solution violates the constraint. In this
+        case, the constraint is definitively added to the problem. This may be
+        useful in some MIP problems, and may have a dramatic impact on performance.
+
+        For more info see: http://tinyurl.com/lazy-constraints.
+        """
+        return _pywraplp.Constraint_set_is_lazy(self, laziness)
+
+ +
+ +

Advanced usage: sets the constraint "laziness".

+ +

This is only supported for SCIP and has no effect on other +solvers.

+ +

When laziness is true, the constraint is only considered by the Linear +Programming solver if its current solution violates the constraint. In this +case, the constraint is definitively added to the problem. This may be +useful in some MIP problems, and may have a dramatic impact on performance.

+ +

For more info see: http://tinyurl.com/lazy-constraints.

+
+ + +
+
+
#   + + + def + index(self) -> int: +
+ +
+ View Source +
    def index(self) -> "int":
+        r""" Returns the index of the constraint in the MPSolver::constraints_."""
+        return _pywraplp.Constraint_index(self)
+
+ +
+ +

Returns the index of the constraint in the MPSolver::constraints_.

+
+ + +
+
+
#   + + + def + dual_value(self) -> 'double': +
+ +
+ View Source +
    def dual_value(self) -> "double":
+        r"""
+        Advanced usage: returns the dual value of the constraint in the current
+        solution (only available for continuous problems).
+        """
+        return _pywraplp.Constraint_dual_value(self)
+
+ +
+ +

Advanced usage: returns the dual value of the constraint in the current +solution (only available for continuous problems).

+
+ + +
+
+
#   + + + def + basis_status(self) -> 'operations_research::MPSolver::BasisStatus': +
+ +
+ View Source +
    def basis_status(self) -> "operations_research::MPSolver::BasisStatus":
+        r"""
+        Advanced usage: returns the basis status of the constraint.
+
+        It is only available for continuous problems).
+
+        Note that if a constraint "linear_expression in [lb, ub]" is transformed
+        into "linear_expression + slack = 0" with slack in [-ub, -lb], then this
+        status is the same as the status of the slack variable with AT_UPPER_BOUND
+        and AT_LOWER_BOUND swapped.
+
+        See also: MPSolver::BasisStatus.
+        """
+        return _pywraplp.Constraint_basis_status(self)
+
+ +
+ +

Advanced usage: returns the basis status of the constraint.

+ +

It is only available for continuous problems).

+ +

Note that if a constraint "linear_expression in [lb, ub]" is transformed +into "linear_expression + slack = 0" with slack in [-ub, -lb], then this +status is the same as the status of the slack variable with AT_UPPER_BOUND +and AT_LOWER_BOUND swapped.

+ +

See also: MPSolver::BasisStatus.

+
+ + +
+
+
#   + + + def + Lb(self) -> 'double': +
+ +
+ View Source +
    def Lb(self) -> "double":
+        return _pywraplp.Constraint_Lb(self)
+
+ +
+ + + +
+
+
#   + + + def + Ub(self) -> 'double': +
+ +
+ View Source +
    def Ub(self) -> "double":
+        return _pywraplp.Constraint_Ub(self)
+
+ +
+ + + +
+
+
#   + + + def + SetLb(self, x: 'double') -> 'void': +
+ +
+ View Source +
    def SetLb(self, x: "double") -> "void":
+        return _pywraplp.Constraint_SetLb(self, x)
+
+ +
+ + + +
+
+
#   + + + def + SetUb(self, x: 'double') -> 'void': +
+ +
+ View Source +
    def SetUb(self, x: "double") -> "void":
+        return _pywraplp.Constraint_SetUb(self, x)
+
+ +
+ + + +
+
+
#   + + + def + DualValue(self) -> 'double': +
+ +
+ View Source +
    def DualValue(self) -> "double":
+        return _pywraplp.Constraint_DualValue(self)
+
+ +
+ + + +
+
+
+
+ #   + + + class + MPSolverParameters: +
+ +
+ View Source +
class MPSolverParameters(object):
+    r"""
+    This class stores parameter settings for LP and MIP solvers. Some parameters
+    are marked as advanced: do not change their values unless you know what you
+    are doing!
+
+    For developers: how to add a new parameter:
+    - Add the new Foo parameter in the DoubleParam or IntegerParam enum.
+    - If it is a categorical param, add a FooValues enum.
+    - Decide if the wrapper should define a default value for it: yes
+      if it controls the properties of the solution (example:
+      tolerances) or if it consistently improves performance, no
+      otherwise. If yes, define kDefaultFoo.
+    - Add a foo_value_ member and, if no default value is defined, a
+      foo_is_default_ member.
+    - Add code to handle Foo in Set...Param, Reset...Param,
+      Get...Param, Reset and the constructor.
+    - In class MPSolverInterface, add a virtual method SetFoo, add it
+      to SetCommonParameters or SetMIPParameters, and implement it for
+      each solver. Sometimes, parameters need to be implemented
+      differently, see for example the INCREMENTALITY implementation.
+    - Add a test in linear_solver_test.cc.
+
+    TODO(user): store the parameter values in a protocol buffer
+    instead. We need to figure out how to deal with the subtleties of
+    the default values.
+    """
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+    RELATIVE_MIP_GAP = _pywraplp.MPSolverParameters_RELATIVE_MIP_GAP
+    r""" Limit for relative MIP gap."""
+    PRIMAL_TOLERANCE = _pywraplp.MPSolverParameters_PRIMAL_TOLERANCE
+    r"""
+    Advanced usage: tolerance for primal feasibility of basic solutions.
+
+    This does not control the integer feasibility tolerance of integer
+    solutions for MIP or the tolerance used during presolve.
+    """
+    DUAL_TOLERANCE = _pywraplp.MPSolverParameters_DUAL_TOLERANCE
+    r""" Advanced usage: tolerance for dual feasibility of basic solutions."""
+    PRESOLVE = _pywraplp.MPSolverParameters_PRESOLVE
+    r""" Advanced usage: presolve mode."""
+    LP_ALGORITHM = _pywraplp.MPSolverParameters_LP_ALGORITHM
+    r""" Algorithm to solve linear programs."""
+    INCREMENTALITY = _pywraplp.MPSolverParameters_INCREMENTALITY
+    r""" Advanced usage: incrementality from one solve to the next."""
+    SCALING = _pywraplp.MPSolverParameters_SCALING
+    r""" Advanced usage: enable or disable matrix scaling."""
+    PRESOLVE_OFF = _pywraplp.MPSolverParameters_PRESOLVE_OFF
+    r""" Presolve is off."""
+    PRESOLVE_ON = _pywraplp.MPSolverParameters_PRESOLVE_ON
+    r""" Presolve is on."""
+    DUAL = _pywraplp.MPSolverParameters_DUAL
+    r""" Dual simplex."""
+    PRIMAL = _pywraplp.MPSolverParameters_PRIMAL
+    r""" Primal simplex."""
+    BARRIER = _pywraplp.MPSolverParameters_BARRIER
+    r""" Barrier algorithm."""
+    INCREMENTALITY_OFF = _pywraplp.MPSolverParameters_INCREMENTALITY_OFF
+    r""" Start solve from scratch."""
+    INCREMENTALITY_ON = _pywraplp.MPSolverParameters_INCREMENTALITY_ON
+    r"""
+    Reuse results from previous solve as much as the underlying solver
+    allows.
+    """
+    SCALING_OFF = _pywraplp.MPSolverParameters_SCALING_OFF
+    r""" Scaling is off."""
+    SCALING_ON = _pywraplp.MPSolverParameters_SCALING_ON
+    r""" Scaling is on."""
+
+    def __init__(self):
+        r""" The constructor sets all parameters to their default value."""
+        _pywraplp.MPSolverParameters_swiginit(self, _pywraplp.new_MPSolverParameters())
+
+    def SetDoubleParam(self, param: "operations_research::MPSolverParameters::DoubleParam", value: "double") -> "void":
+        r""" Sets a double parameter to a specific value."""
+        return _pywraplp.MPSolverParameters_SetDoubleParam(self, param, value)
+
+    def SetIntegerParam(self, param: "operations_research::MPSolverParameters::IntegerParam", value: "int") -> "void":
+        r""" Sets a integer parameter to a specific value."""
+        return _pywraplp.MPSolverParameters_SetIntegerParam(self, param, value)
+
+    def GetDoubleParam(self, param: "operations_research::MPSolverParameters::DoubleParam") -> "double":
+        r""" Returns the value of a double parameter."""
+        return _pywraplp.MPSolverParameters_GetDoubleParam(self, param)
+
+    def GetIntegerParam(self, param: "operations_research::MPSolverParameters::IntegerParam") -> "int":
+        r""" Returns the value of an integer parameter."""
+        return _pywraplp.MPSolverParameters_GetIntegerParam(self, param)
+    __swig_destroy__ = _pywraplp.delete_MPSolverParameters
+
+ +
+ +

This class stores parameter settings for LP and MIP solvers. Some parameters +are marked as advanced: do not change their values unless you know what you +are doing!

+ +

For developers: how to add a new parameter:

+ +
    +
  • Add the new Foo parameter in the DoubleParam or IntegerParam enum.
  • +
  • If it is a categorical param, add a FooValues enum.
  • +
  • Decide if the wrapper should define a default value for it: yes +if it controls the properties of the solution (example: +tolerances) or if it consistently improves performance, no +otherwise. If yes, define kDefaultFoo.
  • +
  • Add a foo_value_ member and, if no default value is defined, a +foo_is_default_ member.
  • +
  • Add code to handle Foo in Set...Param, Reset...Param, +Get...Param, Reset and the constructor.
  • +
  • In class MPSolverInterface, add a virtual method SetFoo, add it +to SetCommonParameters or SetMIPParameters, and implement it for +each solver. Sometimes, parameters need to be implemented +differently, see for example the INCREMENTALITY implementation.
  • +
  • Add a test in linear_solver_test.cc.
  • +
+ +

TODO(user): store the parameter values in a protocol buffer +instead. We need to figure out how to deal with the subtleties of +the default values.

+
+ + +
+
#   + + + MPSolverParameters() +
+ +
+ View Source +
    def __init__(self):
+        r""" The constructor sets all parameters to their default value."""
+        _pywraplp.MPSolverParameters_swiginit(self, _pywraplp.new_MPSolverParameters())
+
+ +
+ +

The constructor sets all parameters to their default value.

+
+ + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
#   + + RELATIVE_MIP_GAP = 0 +
+ + +

Limit for relative MIP gap.

+
+ + +
+
+
#   + + PRIMAL_TOLERANCE = 1 +
+ + +

Advanced usage: tolerance for primal feasibility of basic solutions.

+ +

This does not control the integer feasibility tolerance of integer +solutions for MIP or the tolerance used during presolve.

+
+ + +
+
+
#   + + DUAL_TOLERANCE = 2 +
+ + +

Advanced usage: tolerance for dual feasibility of basic solutions.

+
+ + +
+
+
#   + + PRESOLVE = 1000 +
+ + +

Advanced usage: presolve mode.

+
+ + +
+
+
#   + + LP_ALGORITHM = 1001 +
+ + +

Algorithm to solve linear programs.

+
+ + +
+
+
#   + + INCREMENTALITY = 1002 +
+ + +

Advanced usage: incrementality from one solve to the next.

+
+ + +
+
+
#   + + SCALING = 1003 +
+ + +

Advanced usage: enable or disable matrix scaling.

+
+ + +
+
+
#   + + PRESOLVE_OFF = 0 +
+ + +

Presolve is off.

+
+ + +
+
+
#   + + PRESOLVE_ON = 1 +
+ + +

Presolve is on.

+
+ + +
+
+
#   + + DUAL = 10 +
+ + +

Dual simplex.

+
+ + +
+
+
#   + + PRIMAL = 11 +
+ + +

Primal simplex.

+
+ + +
+
+
#   + + BARRIER = 12 +
+ + +

Barrier algorithm.

+
+ + +
+
+
#   + + INCREMENTALITY_OFF = 0 +
+ + +

Start solve from scratch.

+
+ + +
+
+
#   + + INCREMENTALITY_ON = 1 +
+ + +

Reuse results from previous solve as much as the underlying solver +allows.

+
+ + +
+
+
#   + + SCALING_OFF = 0 +
+ + +

Scaling is off.

+
+ + +
+
+
#   + + SCALING_ON = 1 +
+ + +

Scaling is on.

+
+ + +
+
+
#   + + + def + SetDoubleParam( + self, + param: 'operations_research::MPSolverParameters::DoubleParam', + value: 'double' +) -> 'void': +
+ +
+ View Source +
    def SetDoubleParam(self, param: "operations_research::MPSolverParameters::DoubleParam", value: "double") -> "void":
+        r""" Sets a double parameter to a specific value."""
+        return _pywraplp.MPSolverParameters_SetDoubleParam(self, param, value)
+
+ +
+ +

Sets a double parameter to a specific value.

+
+ + +
+
+
#   + + + def + SetIntegerParam( + self, + param: 'operations_research::MPSolverParameters::IntegerParam', + value: int +) -> 'void': +
+ +
+ View Source +
    def SetIntegerParam(self, param: "operations_research::MPSolverParameters::IntegerParam", value: "int") -> "void":
+        r""" Sets a integer parameter to a specific value."""
+        return _pywraplp.MPSolverParameters_SetIntegerParam(self, param, value)
+
+ +
+ +

Sets a integer parameter to a specific value.

+
+ + +
+
+
#   + + + def + GetDoubleParam( + self, + param: 'operations_research::MPSolverParameters::DoubleParam' +) -> 'double': +
+ +
+ View Source +
    def GetDoubleParam(self, param: "operations_research::MPSolverParameters::DoubleParam") -> "double":
+        r""" Returns the value of a double parameter."""
+        return _pywraplp.MPSolverParameters_GetDoubleParam(self, param)
+
+ +
+ +

Returns the value of a double parameter.

+
+ + +
+
+
#   + + + def + GetIntegerParam( + self, + param: 'operations_research::MPSolverParameters::IntegerParam' +) -> int: +
+ +
+ View Source +
    def GetIntegerParam(self, param: "operations_research::MPSolverParameters::IntegerParam") -> "int":
+        r""" Returns the value of an integer parameter."""
+        return _pywraplp.MPSolverParameters_GetIntegerParam(self, param)
+
+ +
+ +

Returns the value of an integer parameter.

+
+ + +
+
+
#   + + kDefaultRelativeMipGap = 0.0001 +
+ + + + +
+
+
#   + + kDefaultPrimalTolerance = 1e-07 +
+ + + + +
+
+
#   + + kDefaultDualTolerance = 1e-07 +
+ + + + +
+
+
#   + + kDefaultPresolve = 1 +
+ + + + +
+
+
#   + + kDefaultIncrementality = 1 +
+ + + + +
+
+
+
+ #   + + + class + ModelExportOptions: +
+ +
+ View Source +
class ModelExportOptions(object):
+    r""" Export options."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self):
+        _pywraplp.ModelExportOptions_swiginit(self, _pywraplp.new_ModelExportOptions())
+    __swig_destroy__ = _pywraplp.delete_ModelExportOptions
+
+ +
+ +

Export options.

+
+ + +
+
#   + + + ModelExportOptions() +
+ +
+ View Source +
    def __init__(self):
+        _pywraplp.ModelExportOptions_swiginit(self, _pywraplp.new_ModelExportOptions())
+
+ +
+ + + +
+
+
#   + + thisown +
+ + +

The membership flag

+
+ + +
+
+
+
#   + + + def + ExportModelAsLpFormat(*args) -> 'std::string': +
+ +
+ View Source +
def ExportModelAsLpFormat(*args) -> "std::string":
+    return _pywraplp.ExportModelAsLpFormat(*args)
+
+ +
+ + + +
+
+
#   + + + def + ExportModelAsMpsFormat(*args) -> 'std::string': +
+ +
+ View Source +
def ExportModelAsMpsFormat(*args) -> "std::string":
+    return _pywraplp.ExportModelAsMpsFormat(*args)
+
+ +
+ + + +
+
+
#   + + + def + FindErrorInModelProto( + input_model: 'operations_research::MPModelProto const &' +) -> 'std::string': +
+ +
+ View Source +
def FindErrorInModelProto(input_model: "operations_research::MPModelProto const &") -> "std::string":
+    return _pywraplp.FindErrorInModelProto(input_model)
+
+ +
+ + + +
+
+
#   + + + def + setup_variable_operator(opname): +
+ +
+ View Source +
def setup_variable_operator(opname):
+  setattr(Variable, opname,
+          lambda self, *args: getattr(VariableExpr(self), opname)(*args))
+
+ +
+ + + +
+
+ + \ No newline at end of file diff --git a/docs/python/ortools/sat/python/cp_model.html b/docs/python/ortools/sat/python/cp_model.html index dd9f4e4554..293bd59a62 100644 --- a/docs/python/ortools/sat/python/cp_model.html +++ b/docs/python/ortools/sat/python/cp_model.html @@ -3,27 +3,27 @@ - + ortools.sat.python.cp_model API documentation - - - - - - -

@@ -494,7 +512,7 @@ ortools.sat.python.cp_model

methods for building and solving CP-SAT models.

    -
  • CpModel: Methods for creating +
  • CpModel: Methods for creating models, including variables and constraints.
  • CPSolver: Methods for solving a model and evaluating solutions.
  • @@ -504,11 +522,11 @@ a model and evaluating solutions. solver calls each time it finds a new solution.

      -
    • CpSolverSolutionCallback: +
    • CpSolverSolutionCallback: A general method for implementing callbacks.
    • -
    • ObjectiveSolutionPrinter: +
    • ObjectiveSolutionPrinter: Print objective values and elapsed time for intermediate solutions.
    • -
    • VarArraySolutionPrinter: +
    • VarArraySolutionPrinter: Print intermediate solutions (variable values, time).
    • [VarArrayAndObjectiveSolutionPrinter] (#cp_model.VarArrayAndObjectiveSolutionPrinter): @@ -518,9 +536,9 @@ Print both intermediate solutions and objective values.
    • Additional methods for solving CP-SAT models:

        -
      • Constraint: A few utility methods for modifying +
      • Constraint: A few utility methods for modifying constraints created by CpModel.
      • -
      • LinearExpr: Methods for creating constraints +
      • LinearExpr: Methods for creating constraints and the objective from large arrays of coefficients.
      @@ -530,7 +548,7 @@ rather than for solving specific optimization problems.

      View Source -
      # Copyright 2010-2021 Google LLC
      +            
      # Copyright 2010-2021 Google LLC
       # Licensed under the Apache License, Version 2.0 (the "License");
       # you may not use this file except in compliance with the License.
       # You may obtain a copy of the License at
      @@ -584,14 +602,14 @@ rather than for solving specific optimization problems.

      from ortools.sat import cp_model_pb2 from ortools.sat import sat_parameters_pb2 from ortools.sat.python import cp_model_helper as cmh -from ortools.sat import pywrapsat -from ortools.util import sorted_interval_list +from ortools.sat.python import swig_helper +from ortools.util.python import sorted_interval_list Domain = sorted_interval_list.Domain # The classes below allow linear expressions to be expressed naturally with the -# usual arithmetic operators +-*/ and with constant numbers, which makes the -# python API very intuitive. See ../samples/*.py for examples. +# usual arithmetic operators + - * / and with constant numbers, which makes the +# python API very intuitive. See../ samples/*.py for examples. INT_MIN = -9223372036854775808 # hardcoded to be platform independent. INT_MAX = 9223372036854775807 @@ -704,7 +722,7 @@ rather than for solving specific optimization problems.

      ``` model.Minimize(cp_model.LinearExpr.Sum(expressions)) - model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0) + model.Add(cp_model.LinearExpr.WeightedSum(expressions, coefficients) >= 0) ``` """ @@ -716,14 +734,14 @@ rather than for solving specific optimization problems.

      return _SumArray(expressions) @classmethod - def ScalProd(cls, expressions, coefficients): + def WeightedSum(cls, expressions, coefficients): """Creates the expression sum(expressions[i] * coefficients[i]).""" if LinearExpr.IsEmptyOrAllNull(coefficients): return 0 elif len(expressions) == 1: return expressions[0] * coefficients[0] else: - return _ScalProd(expressions, coefficients) + return _WeightedSum(expressions, coefficients) @classmethod def Term(cls, expression, coefficient): @@ -761,7 +779,7 @@ rather than for solving specific optimization problems.

      if all_ones: return _SumArray(variables, offset) else: - return _ScalProd(variables, coeffs, offset) + return _WeightedSum(variables, coeffs, offset) def GetIntegerVarValueMap(self): """Scans the expression, and returns (var_coef_map, constant).""" @@ -782,7 +800,7 @@ rather than for solving specific optimization problems.

      for e in expr.Expressions(): to_process.append((e, coeff)) constant += expr.Constant() * coeff - elif isinstance(expr, _ScalProd): + elif isinstance(expr, _WeightedSum): for e, c in zip(expr.Expressions(), expr.Coefficients()): to_process.append((e, coeff * c)) constant += expr.Constant() * coeff @@ -817,7 +835,7 @@ rather than for solving specific optimization problems.

      for e in expr.Expressions(): to_process.append((e, coeff)) constant += expr.Constant() * coeff - elif isinstance(expr, _ScalProd): + elif isinstance(expr, _WeightedSum): for e, c in zip(expr.Expressions(), expr.Coefficients()): to_process.append((e, coeff * c)) constant += expr.Constant() * coeff @@ -1079,8 +1097,8 @@ rather than for solving specific optimization problems.

      return self.__constant -class _ScalProd(LinearExpr): - """Represents the scalar product of expressions with constants and a constant.""" +class _WeightedSum(LinearExpr): + """Represents sum(ai * xi) + b.""" def __init__(self, expressions, coefficients, constant=0): self.__expressions = [] @@ -1088,7 +1106,7 @@ rather than for solving specific optimization problems.

      self.__constant = constant if len(expressions) != len(coefficients): raise TypeError( - 'In the LinearExpr.ScalProd method, the expression array and the ' + 'In the LinearExpr.WeightedSum method, the expression array and the ' ' coefficient array must have the same length.') for e, c in zip(expressions, coefficients): c = cmh.assert_is_a_number(c) @@ -1129,7 +1147,7 @@ rather than for solving specific optimization problems.

      return output def __repr__(self): - return 'ScalProd([{}], [{}], {})'.format( + return 'WeightedSum([{}], [{}], {})'.format( ', '.join(map(repr, self.__expressions)), ', '.join(map(repr, self.__coefficients)), self.__constant) @@ -1328,7 +1346,7 @@ rather than for solving specific optimization problems.

      self.__index = len(constraints) self.__constraint = constraints.add() - def OnlyEnforceIf(self, boolvar): + def OnlyEnforceIf(self, *boolvar): """Adds an enforcement literal to the constraint. This method adds one or more literals (that is, a boolean variable or its @@ -1340,23 +1358,18 @@ rather than for solving specific optimization problems.

      BoolOr, BoolAnd, and linear constraints all support enforcement literals. Args: - boolvar: A boolean literal or a list of boolean literals. + *boolvar: One or more Boolean literals. Returns: self. """ - - if cmh.is_integral(boolvar) and int(boolvar) == 1: - # Always true. Do nothing. - pass - elif isinstance(boolvar, list): - for b in boolvar: - if cmh.is_integral(b) and int(b) == 1: - pass - else: - self.__constraint.enforcement_literal.append(b.Index()) - else: - self.__constraint.enforcement_literal.append(boolvar.Index()) + for lit in ExpandGeneratorOrTuple(boolvar): + if (isinstance(lit, bool) and + bool(lit)) or (cmh.is_integral(lit) and int(lit) == 1): + # Always true. Do nothing. + pass + else: + self.__constraint.enforcement_literal.append(lit.Index()) return self def Index(self): @@ -1592,21 +1605,22 @@ rather than for solving specific optimization problems.

      # General Integer Constraints. - def AddAllDifferent(self, expressions): + def AddAllDifferent(self, *expressions): """Adds AllDifferent(expressions). This constraint forces all expressions to have different values. Args: - expressions: a list of integer affine expressions. + *expressions: simple expressions of the form a * var + constant. Returns: An instance of the `Constraint` class. """ ct = Constraint(self.__model.constraints) model_ct = self.__model.constraints[ct.Index()] + expanded = ExpandGeneratorOrTuple(expressions) model_ct.all_diff.exprs.extend( - [self.ParseLinearExpression(x) for x in expressions]) + [self.ParseLinearExpression(x) for x in expanded]) return ct def AddElement(self, index, variables, target): @@ -1661,6 +1675,44 @@ rather than for solving specific optimization problems.

      model_ct.circuit.literals.append(lit) return ct + def AddMultipleCircuit(self, arcs): + """Adds a multiple circuit constraint, aka the "VRP" constraint. + + The direct graph where arc #i (from tails[i] to head[i]) is present iff + literals[i] is true must satisfy this set of properties: + - #incoming arcs == 1 except for node 0. + - #outgoing arcs == 1 except for node 0. + - for node zero, #incoming arcs == #outgoing arcs. + - There are no duplicate arcs. + - Self-arcs are allowed except for node 0. + - There is no cycle in this graph, except through node 0. + + Args: + arcs: a list of arcs. An arc is a tuple (source_node, destination_node, + literal). The arc is selected in the circuit if the literal is true. + Both source_node and destination_node must be integers between 0 and the + number of nodes - 1. + + Returns: + An instance of the `Constraint` class. + + Raises: + ValueError: If the list of arcs is empty. + """ + if not arcs: + raise ValueError( + 'AddMultipleCircuit expects a non-empty array of arcs') + ct = Constraint(self.__model.constraints) + model_ct = self.__model.constraints[ct.Index()] + for arc in arcs: + tail = cmh.assert_is_int32(arc[0]) + head = cmh.assert_is_int32(arc[1]) + lit = self.GetOrMakeBooleanIndex(arc[2]) + model_ct.routes.tails.append(tail) + model_ct.routes.heads.append(head) + model_ct.routes.literals.append(lit) + return ct + def AddAllowedAssignments(self, variables, tuples_list): """Adds AllowedAssignments(variables, tuples_list). @@ -1990,42 +2042,72 @@ rather than for solving specific optimization problems.

      model_ct.enforcement_literal.append(self.GetOrMakeBooleanIndex(a)) return ct - def AddBoolOr(self, literals): - """Adds `Or(literals) == true`.""" + def AddBoolOr(self, *literals): + """Adds `Or(literals) == true`: Sum(literals) >= 1.""" ct = Constraint(self.__model.constraints) model_ct = self.__model.constraints[ct.Index()] - model_ct.bool_or.literals.extend( - [self.GetOrMakeBooleanIndex(x) for x in literals]) + model_ct.bool_or.literals.extend([ + self.GetOrMakeBooleanIndex(x) + for x in ExpandGeneratorOrTuple(literals) + ]) return ct - def AddBoolAnd(self, literals): + def AddAtLeastOne(self, *literals): + """Same as `AddBoolOr`: `Sum(literals) >= 1`.""" + return self.AddBoolOr(*literals) + + def AddAtMostOne(self, *literals): + """Adds `AtMostOne(literals)`: `Sum(literals) <= 1`.""" + ct = Constraint(self.__model.constraints) + model_ct = self.__model.constraints[ct.Index()] + model_ct.at_most_one.literals.extend([ + self.GetOrMakeBooleanIndex(x) + for x in ExpandGeneratorOrTuple(literals) + ]) + return ct + + def AddExactlyOne(self, *literals): + """Adds `ExactlyOne(literals)`: `Sum(literals) == 1`.""" + ct = Constraint(self.__model.constraints) + model_ct = self.__model.constraints[ct.Index()] + model_ct.exactly_one.literals.extend([ + self.GetOrMakeBooleanIndex(x) + for x in ExpandGeneratorOrTuple(literals) + ]) + return ct + + def AddBoolAnd(self, *literals): """Adds `And(literals) == true`.""" ct = Constraint(self.__model.constraints) model_ct = self.__model.constraints[ct.Index()] - model_ct.bool_and.literals.extend( - [self.GetOrMakeBooleanIndex(x) for x in literals]) + model_ct.bool_and.literals.extend([ + self.GetOrMakeBooleanIndex(x) + for x in ExpandGeneratorOrTuple(literals) + ]) return ct - def AddBoolXOr(self, literals): + def AddBoolXOr(self, *literals): """Adds `XOr(literals) == true`. In contrast to AddBoolOr and AddBoolAnd, it does not support .OnlyEnforceIf(). Args: - literals: the list of literals in the constraint. + *literals: the list of literals in the constraint. Returns: An `Constraint` object. """ ct = Constraint(self.__model.constraints) model_ct = self.__model.constraints[ct.Index()] - model_ct.bool_xor.literals.extend( - [self.GetOrMakeBooleanIndex(x) for x in literals]) + model_ct.bool_xor.literals.extend([ + self.GetOrMakeBooleanIndex(x) + for x in ExpandGeneratorOrTuple(literals) + ]) return ct def AddMinEquality(self, target, exprs): - """Adds `target == Min(variables)`.""" + """Adds `target == Min(exprs)`.""" ct = Constraint(self.__model.constraints) model_ct = self.__model.constraints[ct.Index()] model_ct.lin_max.exprs.extend( @@ -2035,7 +2117,7 @@ rather than for solving specific optimization problems.

      return ct def AddMaxEquality(self, target, exprs): - """Adds `target == Max(variables)`.""" + """Adds `target == Max(exprs)`.""" ct = Constraint(self.__model.constraints) model_ct = self.__model.constraints[ct.Index()] model_ct.lin_max.exprs.extend( @@ -2070,12 +2152,14 @@ rather than for solving specific optimization problems.

      model_ct.int_mod.target.CopyFrom(self.ParseLinearExpression(target)) return ct - def AddMultiplicationEquality(self, target, expressions): - """Adds `target == variables[0] * .. * variables[n]`.""" + def AddMultiplicationEquality(self, target, *expressions): + """Adds `target == expressions[0] * .. * expressions[n]`.""" ct = Constraint(self.__model.constraints) model_ct = self.__model.constraints[ct.Index()] - model_ct.int_prod.exprs.extend( - [self.ParseLinearExpression(expr) for expr in expressions]) + model_ct.int_prod.exprs.extend([ + self.ParseLinearExpression(expr) + for expr in ExpandGeneratorOrTuple(expressions) + ]) model_ct.int_prod.target.CopyFrom(self.ParseLinearExpression(target)) return ct @@ -2489,11 +2573,13 @@ rather than for solving specific optimization problems.

      def ModelStats(self): """Returns a string containing some model statistics.""" - return pywrapsat.CpSatHelper.ModelStats(self.__model) + return swig_helper.CpSatHelper.SerializedModelStats( + self.__model.SerializeToString()) def Validate(self): """Returns a string indicating that the model is invalid.""" - return pywrapsat.CpSatHelper.ValidateModel(self.__model) + return swig_helper.CpSatHelper.SerializedValidateModel( + self.__model.SerializeToString()) def ExportToFile(self, file): """Write the model as a protocol buffer to 'file'. @@ -2506,7 +2592,8 @@ rather than for solving specific optimization problems.

      Returns: True if the model was correctly written. """ - return pywrapsat.CpSatHelper.WriteModelToFile(self.__model, file) + return swig_helper.CpSatHelper.SerializedWriteModelToFile( + self.__model.SerializeToString(), file) def AssertIsBooleanVariable(self, x): if isinstance(x, IntVar): @@ -2541,6 +2628,16 @@ rather than for solving specific optimization problems.

      self.__model.ClearField('assumptions') +def ExpandGeneratorOrTuple(args): + if hasattr(args, '__len__'): # Tuple + if len(args) != 1: + return args + if cmh.is_a_number(args[0]) or isinstance(args[0], LinearExpr): + return args + # Generator + return args[0] + + def EvaluateLinearExpr(expression, solution): """Evaluate a linear expression against a solution.""" if cmh.is_integral(expression): @@ -2564,7 +2661,7 @@ rather than for solving specific optimization problems.

      for e in expr.Expressions(): to_process.append((e, coeff)) value += expr.Constant() * coeff - elif isinstance(expr, _ScalProd): + elif isinstance(expr, _WeightedSum): for e, c in zip(expr.Expressions(), expr.Coefficients()): to_process.append((e, coeff * c)) value += expr.Constant() * coeff @@ -2609,22 +2706,25 @@ rather than for solving specific optimization problems.

      self.__solution: cp_model_pb2.CpSolverResponse = None self.parameters = sat_parameters_pb2.SatParameters() self.log_callback = None - self.__solve_wrapper: pywrapsat.SolveWrapper = None + self.__solve_wrapper: swig_helper.SolveWrapper = None self.__lock = threading.Lock() def Solve(self, model, solution_callback=None): """Solves a problem and passes each solution to the callback if not null.""" with self.__lock: - solve_wrapper = pywrapsat.SolveWrapper() + solve_wrapper = swig_helper.SolveWrapper() - solve_wrapper.SetParameters(self.parameters) + swig_helper.SolveWrapper.SetSerializedParameters( + self.parameters.SerializeToString(), solve_wrapper) if solution_callback is not None: solve_wrapper.AddSolutionCallback(solution_callback) if self.log_callback is not None: solve_wrapper.AddLogCallback(self.log_callback) - self.__solution = solve_wrapper.Solve(model.Proto()) + self.__solution = cp_model_pb2.CpSolverResponse.FromString( + swig_helper.SolveWrapper.SerializedSolve( + model.Proto().SerializeToString(), solve_wrapper)) if solution_callback is not None: solve_wrapper.ClearSolutionCallback(solution_callback) @@ -2732,7 +2832,8 @@ rather than for solving specific optimization problems.

      def ResponseStats(self): """Returns some statistics on the solution found as a string.""" - return pywrapsat.CpSatHelper.SolverResponseStats(self.__solution) + return swig_helper.CpSatHelper.SerializedSolverResponseStats( + self.__solution.SerializeToString()) def ResponseProto(self): """Returns the response object.""" @@ -2751,7 +2852,7 @@ rather than for solving specific optimization problems.

      return self.__solution.solution_info -class CpSolverSolutionCallback(pywrapsat.SolutionCallback): +class CpSolverSolutionCallback(swig_helper.SolutionCallback): """Solution callback. This class implements a callback that will be called at each new solution @@ -2776,7 +2877,7 @@ rather than for solving specific optimization problems.

      """ def __init__(self): - pywrapsat.SolutionCallback.__init__(self) + swig_helper.SolutionCallback.__init__(self) def OnSolutionCallback(self): """Proxy for the same method in snake case.""" @@ -2836,7 +2937,7 @@ rather than for solving specific optimization problems.

      for e in expr.Expressions(): to_process.append((e, coeff)) value += expr.Constant() * coeff - elif isinstance(expr, _ScalProd): + elif isinstance(expr, _WeightedSum): for e, c in zip(expr.Expressions(), expr.Coefficients()): to_process.append((e, coeff * c)) value += expr.Constant() * coeff @@ -2851,6 +2952,11 @@ rather than for solving specific optimization problems.

      return value + def Response(self): + """Returns the current solution response.""" + return cp_model_pb2.CpSolverResponse.FromString( + swig_helper.SolutionCallback.SerializedResponse(self)) + class ObjectiveSolutionPrinter(CpSolverSolutionCallback): """Display the objective value and time of intermediate solutions.""" @@ -2933,9 +3039,9 @@ rather than for solving specific optimization problems.

      DisplayBounds(bounds):
      -
      +
      View Source -
      def DisplayBounds(bounds):
      +            
      def DisplayBounds(bounds):
           """Displays a flattened list of intervals."""
           out = ''
           for i in range(0, len(bounds), 2):
      @@ -2963,9 +3069,9 @@ rather than for solving specific optimization problems.

      ShortName(model, i):
      -
      +
      View Source -
      def ShortName(model, i):
      +            
      def ShortName(model, i):
           """Returns a short name of an integer variable, or its negation."""
           if i < 0:
               return 'Not(%s)' % ShortName(model, -i - 1)
      @@ -2993,9 +3099,9 @@ rather than for solving specific optimization problems.

      ShortExprName(model, e):
      -
      +
      View Source -
      def ShortExprName(model, e):
      +            
      def ShortExprName(model, e):
           """Pretty-print LinearExpressionProto instances."""
           if not e.vars:
               return str(e.offset)
      @@ -3034,9 +3140,9 @@ rather than for solving specific optimization problems.

      LinearExpr:
      -
      +
      View Source -
      class LinearExpr(object):
      +            
      class LinearExpr(object):
           """Holds an integer linear expression.
       
         A linear expression is built from integer constants and variables.
      @@ -3064,7 +3170,7 @@ rather than for solving specific optimization problems.

      ``` model.Minimize(cp_model.LinearExpr.Sum(expressions)) - model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0) + model.Add(cp_model.LinearExpr.WeightedSum(expressions, coefficients) >= 0) ``` """ @@ -3076,14 +3182,14 @@ rather than for solving specific optimization problems.

      return _SumArray(expressions) @classmethod - def ScalProd(cls, expressions, coefficients): + def WeightedSum(cls, expressions, coefficients): """Creates the expression sum(expressions[i] * coefficients[i]).""" if LinearExpr.IsEmptyOrAllNull(coefficients): return 0 elif len(expressions) == 1: return expressions[0] * coefficients[0] else: - return _ScalProd(expressions, coefficients) + return _WeightedSum(expressions, coefficients) @classmethod def Term(cls, expression, coefficient): @@ -3121,7 +3227,7 @@ rather than for solving specific optimization problems.

      if all_ones: return _SumArray(variables, offset) else: - return _ScalProd(variables, coeffs, offset) + return _WeightedSum(variables, coeffs, offset) def GetIntegerVarValueMap(self): """Scans the expression, and returns (var_coef_map, constant).""" @@ -3142,7 +3248,7 @@ rather than for solving specific optimization problems.

      for e in expr.Expressions(): to_process.append((e, coeff)) constant += expr.Constant() * coeff - elif isinstance(expr, _ScalProd): + elif isinstance(expr, _WeightedSum): for e, c in zip(expr.Expressions(), expr.Coefficients()): to_process.append((e, coeff * c)) constant += expr.Constant() * coeff @@ -3177,7 +3283,7 @@ rather than for solving specific optimization problems.

      for e in expr.Expressions(): to_process.append((e, coeff)) constant += expr.Constant() * coeff - elif isinstance(expr, _ScalProd): + elif isinstance(expr, _WeightedSum): for e, c in zip(expr.Expressions(), expr.Coefficients()): to_process.append((e, coeff * c)) constant += expr.Constant() * coeff @@ -3384,7 +3490,7 @@ linear expressions or coefficients as follows:
    model.Minimize(cp_model.LinearExpr.Sum(expressions))
    -model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0)
    +model.Add(cp_model.LinearExpr.WeightedSum(expressions, coefficients) >= 0)
     
    @@ -3396,7 +3502,7 @@ model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0) LinearExpr() - + @@ -3409,9 +3515,9 @@ model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0) Sum(cls, expressions): -
    +
    View Source -
        @classmethod
    +            
        @classmethod
         def Sum(cls, expressions):
             """Creates the expression sum(expressions)."""
             if len(expressions) == 1:
    @@ -3426,26 +3532,26 @@ model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0)
     
     
                                 
    -
    -
    #   +
    +
    #  
    @classmethod
    def - ScalProd(cls, expressions, coefficients): + WeightedSum(cls, expressions, coefficients):
    -
    +
    View Source -
        @classmethod
    -    def ScalProd(cls, expressions, coefficients):
    +            
        @classmethod
    +    def WeightedSum(cls, expressions, coefficients):
             """Creates the expression sum(expressions[i] * coefficients[i])."""
             if LinearExpr.IsEmptyOrAllNull(coefficients):
                 return 0
             elif len(expressions) == 1:
                 return expressions[0] * coefficients[0]
             else:
    -            return _ScalProd(expressions, coefficients)
    +            return _WeightedSum(expressions, coefficients)
     
    @@ -3464,9 +3570,9 @@ model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0) Term(cls, expression, coefficient):
    -
    +
    View Source -
        @classmethod
    +            
        @classmethod
         def Term(cls, expression, coefficient):
             """Creates `expression * coefficient`."""
             if cmh.is_zero(coefficient):
    @@ -3491,9 +3597,9 @@ model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0)
                 IsEmptyOrAllNull(cls, coefficients):
         
    -
    +
    View Source -
        @classmethod
    +            
        @classmethod
         def IsEmptyOrAllNull(cls, coefficients):
             for c in coefficients:
                 if not cmh.is_zero(c):
    @@ -3515,9 +3621,9 @@ model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0)
                 RebuildFromLinearExpressionProto(cls, model, proto):
         
    -
    +
    View Source -
        @classmethod
    +            
        @classmethod
         def RebuildFromLinearExpressionProto(cls, model, proto):
             """Recreate a LinearExpr from a LinearExpressionProto."""
             offset = proto.offset
    @@ -3538,7 +3644,7 @@ model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0)
                 if all_ones:
                     return _SumArray(variables, offset)
                 else:
    -                return _ScalProd(variables, coeffs, offset)
    +                return _WeightedSum(variables, coeffs, offset)
     
    @@ -3556,9 +3662,9 @@ model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0) GetIntegerVarValueMap(self):
    -
    +
    View Source -
        def GetIntegerVarValueMap(self):
    +            
        def GetIntegerVarValueMap(self):
             """Scans the expression, and returns (var_coef_map, constant)."""
             coeffs = collections.defaultdict(int)
             constant = 0
    @@ -3577,7 +3683,7 @@ model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0)
                     for e in expr.Expressions():
                         to_process.append((e, coeff))
                     constant += expr.Constant() * coeff
    -            elif isinstance(expr, _ScalProd):
    +            elif isinstance(expr, _WeightedSum):
                     for e, c in zip(expr.Expressions(), expr.Coefficients()):
                         to_process.append((e, coeff * c))
                     constant += expr.Constant() * coeff
    @@ -3607,9 +3713,9 @@ model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0)
                 GetFloatVarValueMap(self):
         
    -
    +
    View Source -
        def GetFloatVarValueMap(self):
    +            
        def GetFloatVarValueMap(self):
             """Scans the expression. Returns (var_coef_map, constant, is_integer)."""
             coeffs = {}
             constant = 0
    @@ -3630,7 +3736,7 @@ model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0)
                     for e in expr.Expressions():
                         to_process.append((e, coeff))
                     constant += expr.Constant() * coeff
    -            elif isinstance(expr, _ScalProd):
    +            elif isinstance(expr, _WeightedSum):
                     for e, c in zip(expr.Expressions(), expr.Coefficients()):
                         to_process.append((e, coeff * c))
                     constant += expr.Constant() * coeff
    @@ -3673,9 +3779,9 @@ model.Add(cp_model.LinearExpr.ScalProd(expressions, coefficients) >= 0)
             IntVar(LinearExpr):
         
    -
    +
    View Source -
    class IntVar(LinearExpr):
    +            
    class IntVar(LinearExpr):
         """An integer variable.
     
       An IntVar is an object that can take on any integer value within defined
    @@ -3781,9 +3887,9 @@ model is feasible, or optimal if you provided an objective function.

    IntVar(model, domain, name)
    -
    +
    View Source -
        def __init__(self, model, domain, name):
    +            
        def __init__(self, model, domain, name):
             """See CpModel.NewIntVar below."""
             self.__model = model
             self.__negation = None
    @@ -3819,9 +3925,9 @@ model is feasible, or optimal if you provided an objective function.

    Index(self):
    -
    +
    View Source -
        def Index(self):
    +            
        def Index(self):
             """Returns the index of the variable in the model."""
             return self.__index
     
    @@ -3841,9 +3947,9 @@ model is feasible, or optimal if you provided an objective function.

    Proto(self):
    -
    +
    View Source -
        def Proto(self):
    +            
        def Proto(self):
             """Returns the variable protobuf."""
             return self.__var
     
    @@ -3863,9 +3969,9 @@ model is feasible, or optimal if you provided an objective function.

    IsEqualTo(self, other):
    -
    +
    View Source -
        def IsEqualTo(self, other):
    +            
        def IsEqualTo(self, other):
             """Returns true if self == other in the python sense."""
             if not isinstance(other, IntVar):
                 return False
    @@ -3887,9 +3993,9 @@ model is feasible, or optimal if you provided an objective function.

    Name(self):
    -
    +
    View Source -
        def Name(self):
    +            
        def Name(self):
             return self.__var.name
     
    @@ -3906,9 +4012,9 @@ model is feasible, or optimal if you provided an objective function.

    Not(self):
    -
    +
    View Source -
        def Not(self):
    +            
        def Not(self):
             """Returns the negation of a Boolean variable.
     
         This method implements the logical negation of a Boolean variable.
    @@ -3943,7 +4049,7 @@ It is only valid if the variable has a Boolean domain (0 or 1).

    LinearExpr
    Sum
    -
    ScalProd
    +
    WeightedSum
    Term
    IsEmptyOrAllNull
    RebuildFromLinearExpressionProto
    @@ -3963,9 +4069,9 @@ It is only valid if the variable has a Boolean domain (0 or 1).

    BoundedLinearExpression:
    -
    +
    View Source -
    class BoundedLinearExpression(object):
    +            
    class BoundedLinearExpression(object):
         """Represents a linear constraint: `lb <= linear expression <= ub`.
     
       The only use of this class is to be added to the CpModel through
    @@ -4048,9 +4154,9 @@ It is only valid if the variable has a Boolean domain (0 or 1).

    BoundedLinearExpression(expr, bounds)
    -
    +
    View Source -
        def __init__(self, expr, bounds):
    +            
        def __init__(self, expr, bounds):
             self.__expr = expr
             self.__bounds = bounds
     
    @@ -4068,9 +4174,9 @@ It is only valid if the variable has a Boolean domain (0 or 1).

    Expression(self):
    -
    +
    View Source -
        def Expression(self):
    +            
        def Expression(self):
             return self.__expr
     
    @@ -4087,9 +4193,9 @@ It is only valid if the variable has a Boolean domain (0 or 1).

    Bounds(self):
    -
    +
    View Source -
        def Bounds(self):
    +            
        def Bounds(self):
             return self.__bounds
     
    @@ -4108,9 +4214,9 @@ It is only valid if the variable has a Boolean domain (0 or 1).

    Constraint:
    -
    +
    View Source -
    class Constraint(object):
    +            
    class Constraint(object):
         """Base class for constraints.
     
       Constraints are built by the CpModel through the Add<XXX> methods.
    @@ -4129,7 +4235,7 @@ It is only valid if the variable has a Boolean domain (0 or 1).

    self.__index = len(constraints) self.__constraint = constraints.add() - def OnlyEnforceIf(self, boolvar): + def OnlyEnforceIf(self, *boolvar): """Adds an enforcement literal to the constraint. This method adds one or more literals (that is, a boolean variable or its @@ -4141,23 +4247,18 @@ It is only valid if the variable has a Boolean domain (0 or 1).

    BoolOr, BoolAnd, and linear constraints all support enforcement literals. Args: - boolvar: A boolean literal or a list of boolean literals. + *boolvar: One or more Boolean literals. Returns: self. """ - - if cmh.is_integral(boolvar) and int(boolvar) == 1: - # Always true. Do nothing. - pass - elif isinstance(boolvar, list): - for b in boolvar: - if cmh.is_integral(b) and int(b) == 1: - pass - else: - self.__constraint.enforcement_literal.append(b.Index()) - else: - self.__constraint.enforcement_literal.append(boolvar.Index()) + for lit in ExpandGeneratorOrTuple(boolvar): + if (isinstance(lit, bool) and + bool(lit)) or (cmh.is_integral(lit) and int(lit) == 1): + # Always true. Do nothing. + pass + else: + self.__constraint.enforcement_literal.append(lit.Index()) return self def Index(self): @@ -4194,9 +4295,9 @@ model.Add(x + 2 * y == 5).OnlyEnforceIf(b.Not()) Constraint(constraints)
    -
    +
    View Source -
        def __init__(self, constraints):
    +            
        def __init__(self, constraints):
             self.__index = len(constraints)
             self.__constraint = constraints.add()
     
    @@ -4211,12 +4312,12 @@ model.Add(x + 2 * y == 5).OnlyEnforceIf(b.Not()) def - OnlyEnforceIf(self, boolvar): + OnlyEnforceIf(self, *boolvar):
    -
    +
    View Source -
        def OnlyEnforceIf(self, boolvar):
    +            
        def OnlyEnforceIf(self, *boolvar):
             """Adds an enforcement literal to the constraint.
     
         This method adds one or more literals (that is, a boolean variable or its
    @@ -4228,23 +4329,18 @@ model.Add(x + 2 * y == 5).OnlyEnforceIf(b.Not())
         BoolOr, BoolAnd, and linear constraints all support enforcement literals.
     
         Args:
    -      boolvar: A boolean literal or a list of boolean literals.
    +      *boolvar: One or more Boolean literals.
     
         Returns:
           self.
         """
    -
    -        if cmh.is_integral(boolvar) and int(boolvar) == 1:
    -            # Always true. Do nothing.
    -            pass
    -        elif isinstance(boolvar, list):
    -            for b in boolvar:
    -                if cmh.is_integral(b) and int(b) == 1:
    -                    pass
    -                else:
    -                    self.__constraint.enforcement_literal.append(b.Index())
    -        else:
    -            self.__constraint.enforcement_literal.append(boolvar.Index())
    +        for lit in ExpandGeneratorOrTuple(boolvar):
    +            if (isinstance(lit, bool) and
    +                    bool(lit)) or (cmh.is_integral(lit) and int(lit) == 1):
    +                # Always true. Do nothing.
    +                pass
    +            else:
    +                self.__constraint.enforcement_literal.append(lit.Index())
             return self
     
    @@ -4263,7 +4359,7 @@ must be enforced. If it is false, then the constraint is ignored.

    Args
      -
    • boolvar: A boolean literal or a list of boolean literals.
    • +
    • *boolvar: One or more Boolean literals.
    Returns
    @@ -4283,9 +4379,9 @@ must be enforced. If it is false, then the constraint is ignored.

    Index(self):
    -
    +
    View Source -
        def Index(self):
    +            
        def Index(self):
             """Returns the index of the constraint in the model."""
             return self.__index
     
    @@ -4305,9 +4401,9 @@ must be enforced. If it is false, then the constraint is ignored.

    Proto(self):
    -
    +
    View Source -
        def Proto(self):
    +            
        def Proto(self):
             """Returns the constraint protobuf."""
             return self.__constraint
     
    @@ -4329,9 +4425,9 @@ must be enforced. If it is false, then the constraint is ignored.

    IntervalVar:
    -
    +
    View Source -
    class IntervalVar(object):
    +            
    class IntervalVar(object):
         """Represents an Interval variable.
     
       An interval variable is both a constraint and a variable. It is defined by
    @@ -4441,9 +4537,9 @@ intervals into the schedule.

    IntervalVar(model, start, size, end, is_present_index, name)
    -
    +
    View Source -
        def __init__(self, model, start, size, end, is_present_index, name):
    +            
        def __init__(self, model, start, size, end, is_present_index, name):
             self.__model = model
             # As with the IntVar::__init__ method, we hack the __init__ method to
             # support two use cases:
    @@ -4481,9 +4577,9 @@ intervals into the schedule.

    Index(self):
    -
    +
    View Source -
        def Index(self):
    +            
        def Index(self):
             """Returns the index of the interval constraint in the model."""
             return self.__index
     
    @@ -4503,9 +4599,9 @@ intervals into the schedule.

    Proto(self):
    -
    +
    View Source -
        def Proto(self):
    +            
        def Proto(self):
             """Returns the interval protobuf."""
             return self.__ct.interval
     
    @@ -4525,9 +4621,9 @@ intervals into the schedule.

    Name(self):
    -
    +
    View Source -
        def Name(self):
    +            
        def Name(self):
             return self.__ct.name
     
    @@ -4544,9 +4640,9 @@ intervals into the schedule.

    StartExpr(self):
    -
    +
    View Source -
        def StartExpr(self):
    +            
        def StartExpr(self):
             return LinearExpr.RebuildFromLinearExpressionProto(
                 self.__model, self.__ct.interval.start)
     
    @@ -4564,9 +4660,9 @@ intervals into the schedule.

    SizeExpr(self):
    -
    +
    View Source -
        def SizeExpr(self):
    +            
        def SizeExpr(self):
             return LinearExpr.RebuildFromLinearExpressionProto(
                 self.__model, self.__ct.interval.size)
     
    @@ -4584,9 +4680,9 @@ intervals into the schedule.

    EndExpr(self):
    -
    +
    View Source -
        def EndExpr(self):
    +            
        def EndExpr(self):
             return LinearExpr.RebuildFromLinearExpressionProto(
                 self.__model, self.__ct.interval.end)
     
    @@ -4605,9 +4701,9 @@ intervals into the schedule.

    ObjectIsATrueLiteral(literal):
    -
    +
    View Source -
    def ObjectIsATrueLiteral(literal):
    +            
    def ObjectIsATrueLiteral(literal):
         """Checks if literal is either True, or a Boolean literals fixed to True."""
         if isinstance(literal, IntVar):
             proto = literal.Proto()
    @@ -4637,9 +4733,9 @@ intervals into the schedule.

    ObjectIsAFalseLiteral(literal):
    -
    +
    View Source -
    def ObjectIsAFalseLiteral(literal):
    +            
    def ObjectIsAFalseLiteral(literal):
         """Checks if literal is either False, or a Boolean literals fixed to False."""
         if isinstance(literal, IntVar):
             proto = literal.Proto()
    @@ -4670,9 +4766,9 @@ intervals into the schedule.

    CpModel:
    -
    +
    View Source -
    class CpModel(object):
    +            
    class CpModel(object):
         """Methods for building a CP model.
     
       Methods beginning with:
    @@ -4783,21 +4879,22 @@ intervals into the schedule.

    # General Integer Constraints. - def AddAllDifferent(self, expressions): + def AddAllDifferent(self, *expressions): """Adds AllDifferent(expressions). This constraint forces all expressions to have different values. Args: - expressions: a list of integer affine expressions. + *expressions: simple expressions of the form a * var + constant. Returns: An instance of the `Constraint` class. """ ct = Constraint(self.__model.constraints) model_ct = self.__model.constraints[ct.Index()] + expanded = ExpandGeneratorOrTuple(expressions) model_ct.all_diff.exprs.extend( - [self.ParseLinearExpression(x) for x in expressions]) + [self.ParseLinearExpression(x) for x in expanded]) return ct def AddElement(self, index, variables, target): @@ -4852,6 +4949,44 @@ intervals into the schedule.

    model_ct.circuit.literals.append(lit) return ct + def AddMultipleCircuit(self, arcs): + """Adds a multiple circuit constraint, aka the "VRP" constraint. + + The direct graph where arc #i (from tails[i] to head[i]) is present iff + literals[i] is true must satisfy this set of properties: + - #incoming arcs == 1 except for node 0. + - #outgoing arcs == 1 except for node 0. + - for node zero, #incoming arcs == #outgoing arcs. + - There are no duplicate arcs. + - Self-arcs are allowed except for node 0. + - There is no cycle in this graph, except through node 0. + + Args: + arcs: a list of arcs. An arc is a tuple (source_node, destination_node, + literal). The arc is selected in the circuit if the literal is true. + Both source_node and destination_node must be integers between 0 and the + number of nodes - 1. + + Returns: + An instance of the `Constraint` class. + + Raises: + ValueError: If the list of arcs is empty. + """ + if not arcs: + raise ValueError( + 'AddMultipleCircuit expects a non-empty array of arcs') + ct = Constraint(self.__model.constraints) + model_ct = self.__model.constraints[ct.Index()] + for arc in arcs: + tail = cmh.assert_is_int32(arc[0]) + head = cmh.assert_is_int32(arc[1]) + lit = self.GetOrMakeBooleanIndex(arc[2]) + model_ct.routes.tails.append(tail) + model_ct.routes.heads.append(head) + model_ct.routes.literals.append(lit) + return ct + def AddAllowedAssignments(self, variables, tuples_list): """Adds AllowedAssignments(variables, tuples_list). @@ -5181,42 +5316,72 @@ intervals into the schedule.

    model_ct.enforcement_literal.append(self.GetOrMakeBooleanIndex(a)) return ct - def AddBoolOr(self, literals): - """Adds `Or(literals) == true`.""" + def AddBoolOr(self, *literals): + """Adds `Or(literals) == true`: Sum(literals) >= 1.""" ct = Constraint(self.__model.constraints) model_ct = self.__model.constraints[ct.Index()] - model_ct.bool_or.literals.extend( - [self.GetOrMakeBooleanIndex(x) for x in literals]) + model_ct.bool_or.literals.extend([ + self.GetOrMakeBooleanIndex(x) + for x in ExpandGeneratorOrTuple(literals) + ]) return ct - def AddBoolAnd(self, literals): + def AddAtLeastOne(self, *literals): + """Same as `AddBoolOr`: `Sum(literals) >= 1`.""" + return self.AddBoolOr(*literals) + + def AddAtMostOne(self, *literals): + """Adds `AtMostOne(literals)`: `Sum(literals) <= 1`.""" + ct = Constraint(self.__model.constraints) + model_ct = self.__model.constraints[ct.Index()] + model_ct.at_most_one.literals.extend([ + self.GetOrMakeBooleanIndex(x) + for x in ExpandGeneratorOrTuple(literals) + ]) + return ct + + def AddExactlyOne(self, *literals): + """Adds `ExactlyOne(literals)`: `Sum(literals) == 1`.""" + ct = Constraint(self.__model.constraints) + model_ct = self.__model.constraints[ct.Index()] + model_ct.exactly_one.literals.extend([ + self.GetOrMakeBooleanIndex(x) + for x in ExpandGeneratorOrTuple(literals) + ]) + return ct + + def AddBoolAnd(self, *literals): """Adds `And(literals) == true`.""" ct = Constraint(self.__model.constraints) model_ct = self.__model.constraints[ct.Index()] - model_ct.bool_and.literals.extend( - [self.GetOrMakeBooleanIndex(x) for x in literals]) + model_ct.bool_and.literals.extend([ + self.GetOrMakeBooleanIndex(x) + for x in ExpandGeneratorOrTuple(literals) + ]) return ct - def AddBoolXOr(self, literals): + def AddBoolXOr(self, *literals): """Adds `XOr(literals) == true`. In contrast to AddBoolOr and AddBoolAnd, it does not support .OnlyEnforceIf(). Args: - literals: the list of literals in the constraint. + *literals: the list of literals in the constraint. Returns: An `Constraint` object. """ ct = Constraint(self.__model.constraints) model_ct = self.__model.constraints[ct.Index()] - model_ct.bool_xor.literals.extend( - [self.GetOrMakeBooleanIndex(x) for x in literals]) + model_ct.bool_xor.literals.extend([ + self.GetOrMakeBooleanIndex(x) + for x in ExpandGeneratorOrTuple(literals) + ]) return ct def AddMinEquality(self, target, exprs): - """Adds `target == Min(variables)`.""" + """Adds `target == Min(exprs)`.""" ct = Constraint(self.__model.constraints) model_ct = self.__model.constraints[ct.Index()] model_ct.lin_max.exprs.extend( @@ -5226,7 +5391,7 @@ intervals into the schedule.

    return ct def AddMaxEquality(self, target, exprs): - """Adds `target == Max(variables)`.""" + """Adds `target == Max(exprs)`.""" ct = Constraint(self.__model.constraints) model_ct = self.__model.constraints[ct.Index()] model_ct.lin_max.exprs.extend( @@ -5261,12 +5426,14 @@ intervals into the schedule.

    model_ct.int_mod.target.CopyFrom(self.ParseLinearExpression(target)) return ct - def AddMultiplicationEquality(self, target, expressions): - """Adds `target == variables[0] * .. * variables[n]`.""" + def AddMultiplicationEquality(self, target, *expressions): + """Adds `target == expressions[0] * .. * expressions[n]`.""" ct = Constraint(self.__model.constraints) model_ct = self.__model.constraints[ct.Index()] - model_ct.int_prod.exprs.extend( - [self.ParseLinearExpression(expr) for expr in expressions]) + model_ct.int_prod.exprs.extend([ + self.ParseLinearExpression(expr) + for expr in ExpandGeneratorOrTuple(expressions) + ]) model_ct.int_prod.target.CopyFrom(self.ParseLinearExpression(target)) return ct @@ -5680,11 +5847,13 @@ intervals into the schedule.

    def ModelStats(self): """Returns a string containing some model statistics.""" - return pywrapsat.CpSatHelper.ModelStats(self.__model) + return swig_helper.CpSatHelper.SerializedModelStats( + self.__model.SerializeToString()) def Validate(self): """Returns a string indicating that the model is invalid.""" - return pywrapsat.CpSatHelper.ValidateModel(self.__model) + return swig_helper.CpSatHelper.SerializedValidateModel( + self.__model.SerializeToString()) def ExportToFile(self, file): """Write the model as a protocol buffer to 'file'. @@ -5697,7 +5866,8 @@ intervals into the schedule.

    Returns: True if the model was correctly written. """ - return pywrapsat.CpSatHelper.WriteModelToFile(self.__model, file) + return swig_helper.CpSatHelper.SerializedWriteModelToFile( + self.__model.SerializeToString(), file) def AssertIsBooleanVariable(self, x): if isinstance(x, IntVar): @@ -5752,9 +5922,9 @@ intervals into the schedule.

    CpModel()
    -
    +
    View Source -
        def __init__(self):
    +            
        def __init__(self):
             self.__model = cp_model_pb2.CpModelProto()
             self.__constant_map = {}
     
    @@ -5772,9 +5942,9 @@ intervals into the schedule.

    NewIntVar(self, lb, ub, name):
    -
    +
    View Source -
        def NewIntVar(self, lb, ub, name):
    +            
        def NewIntVar(self, lb, ub, name):
             """Create an integer variable with domain [lb, ub].
     
         The CP-SAT solver is limited to integer variables. If you have fractional
    @@ -5826,9 +5996,9 @@ encode them as integers.

    NewIntVarFromDomain(self, domain, name):
    -
    +
    View Source -
        def NewIntVarFromDomain(self, domain, name):
    +            
        def NewIntVarFromDomain(self, domain, name):
             """Create an integer variable from a domain.
     
         A domain is a set of integers specified by a collection of intervals.
    @@ -5877,9 +6047,9 @@ For example, model.NewIntVarFromDomain(cp_model.
                 NewBoolVar(self, name):
         
    -
    +
    View Source -
        def NewBoolVar(self, name):
    +            
        def NewBoolVar(self, name):
             """Creates a 0-1 variable with the given name."""
             return IntVar(self.__model, Domain(0, 1), name)
     
    @@ -5899,9 +6069,9 @@ For example, model.NewIntVarFromDomain(cp_model. NewConstant(self, value):
    -
    +
    View Source -
        def NewConstant(self, value):
    +            
        def NewConstant(self, value):
             """Declares a constant integer."""
             return IntVar(self.__model, self.GetOrMakeIndexFromConstant(value),
                           None)
    @@ -5922,9 +6092,9 @@ For example, model.NewIntVarFromDomain(cp_model.
                 AddLinearConstraint(self, linear_expr, lb, ub):
         
    -
    +
    View Source -
        def AddLinearConstraint(self, linear_expr, lb, ub):
    +            
        def AddLinearConstraint(self, linear_expr, lb, ub):
             """Adds the constraint: `lb <= linear_expr <= ub`."""
             return self.AddLinearExpressionInDomain(linear_expr, Domain(lb, ub))
     
    @@ -5944,9 +6114,9 @@ For example, model.NewIntVarFromDomain(cp_model. AddLinearExpressionInDomain(self, linear_expr, domain):
    -
    +
    View Source -
        def AddLinearExpressionInDomain(self, linear_expr, domain):
    +            
        def AddLinearExpressionInDomain(self, linear_expr, domain):
             """Adds the constraint: `linear_expr` in `domain`."""
             if isinstance(linear_expr, LinearExpr):
                 ct = Constraint(self.__model.constraints)
    @@ -5988,9 +6158,9 @@ For example, model.NewIntVarFromDomain(cp_model.
                 Add(self, ct):
         
    -
    +
    View Source -
        def Add(self, ct):
    +            
        def Add(self, ct):
             """Adds a `BoundedLinearExpression` to the model.
     
         Args:
    @@ -6017,7 +6187,7 @@ For example, model.NewIntVarFromDomain(cp_model.
     
    Args
    Returns
    @@ -6034,26 +6204,27 @@ For example, model.NewIntVarFromDomain(cp_model. def - AddAllDifferent(self, expressions): + AddAllDifferent(self, *expressions):
    -
    +
    View Source -
        def AddAllDifferent(self, expressions):
    +            
        def AddAllDifferent(self, *expressions):
             """Adds AllDifferent(expressions).
     
         This constraint forces all expressions to have different values.
     
         Args:
    -      expressions: a list of integer affine expressions.
    +      *expressions: simple expressions of the form a * var + constant.
     
         Returns:
           An instance of the `Constraint` class.
         """
             ct = Constraint(self.__model.constraints)
             model_ct = self.__model.constraints[ct.Index()]
    +        expanded = ExpandGeneratorOrTuple(expressions)
             model_ct.all_diff.exprs.extend(
    -            [self.ParseLinearExpression(x) for x in expressions])
    +            [self.ParseLinearExpression(x) for x in expanded])
             return ct
     
    @@ -6066,7 +6237,7 @@ For example, model.NewIntVarFromDomain(cp_model.
    Args
      -
    • expressions: a list of integer affine expressions.
    • +
    • *expressions: simple expressions of the form a * var + constant.
    Returns
    @@ -6086,9 +6257,9 @@ For example, model.NewIntVarFromDomain(cp_model. AddElement(self, index, variables, target):
    -
    +
    View Source -
        def AddElement(self, index, variables, target):
    +            
        def AddElement(self, index, variables, target):
             """Adds the element constraint: `variables[index] == target`."""
     
             if not variables:
    @@ -6121,9 +6292,9 @@ For example, model.NewIntVarFromDomain(cp_model.
                 AddCircuit(self, arcs):
         
    -
    +
    View Source -
        def AddCircuit(self, arcs):
    +            
        def AddCircuit(self, arcs):
             """Adds Circuit(arcs).
     
         Adds a circuit constraint from a sparse list of arcs that encode the graph.
    @@ -6187,6 +6358,95 @@ number of nodes - 1.
     
     
    Raises
    +
      +
    • ValueError: If the list of arcs is empty.
    • +
    +
    + + +
    +
    +
    #   + + + def + AddMultipleCircuit(self, arcs): +
    + +
    + View Source +
        def AddMultipleCircuit(self, arcs):
    +        """Adds a multiple circuit constraint, aka the "VRP" constraint.
    +
    +    The direct graph where arc #i (from tails[i] to head[i]) is present iff
    +    literals[i] is true must satisfy this set of properties:
    +    - #incoming arcs == 1 except for node 0.
    +    - #outgoing arcs == 1 except for node 0.
    +    - for node zero, #incoming arcs == #outgoing arcs.
    +    - There are no duplicate arcs.
    +    - Self-arcs are allowed except for node 0.
    +    - There is no cycle in this graph, except through node 0.
    +
    +    Args:
    +      arcs: a list of arcs. An arc is a tuple (source_node, destination_node,
    +        literal). The arc is selected in the circuit if the literal is true.
    +        Both source_node and destination_node must be integers between 0 and the
    +        number of nodes - 1.
    +
    +    Returns:
    +      An instance of the `Constraint` class.
    +
    +    Raises:
    +      ValueError: If the list of arcs is empty.
    +    """
    +        if not arcs:
    +            raise ValueError(
    +                'AddMultipleCircuit expects a non-empty array of arcs')
    +        ct = Constraint(self.__model.constraints)
    +        model_ct = self.__model.constraints[ct.Index()]
    +        for arc in arcs:
    +            tail = cmh.assert_is_int32(arc[0])
    +            head = cmh.assert_is_int32(arc[1])
    +            lit = self.GetOrMakeBooleanIndex(arc[2])
    +            model_ct.routes.tails.append(tail)
    +            model_ct.routes.heads.append(head)
    +            model_ct.routes.literals.append(lit)
    +        return ct
    +
    + +
    + +

    Adds a multiple circuit constraint, aka the "VRP" constraint.

    + +

    The direct graph where arc #i (from tails[i] to head[i]) is present iff +literals[i] is true must satisfy this set of properties:

    + +
      +
    • #incoming arcs == 1 except for node 0.
    • +
    • #outgoing arcs == 1 except for node 0.
    • +
    • for node zero, #incoming arcs == #outgoing arcs.
    • +
    • There are no duplicate arcs.
    • +
    • Self-arcs are allowed except for node 0.
    • +
    • There is no cycle in this graph, except through node 0.
    • +
    + +
    Args
    + +
      +
    • arcs: a list of arcs. An arc is a tuple (source_node, destination_node, +literal). The arc is selected in the circuit if the literal is true. +Both source_node and destination_node must be integers between 0 and the +number of nodes - 1.
    • +
    + +
    Returns
    + +
    +

    An instance of the Constraint class.

    +
    + +
    Raises
    +
    • ValueError: If the list of arcs is empty.
    @@ -6202,9 +6462,9 @@ number of nodes - 1. AddAllowedAssignments(self, variables, tuples_list):
    -
    +
    View Source -
        def AddAllowedAssignments(self, variables, tuples_list):
    +            
        def AddAllowedAssignments(self, variables, tuples_list):
             """Adds AllowedAssignments(variables, tuples_list).
     
         An AllowedAssignments constraint is a constraint on an array of variables,
    @@ -6287,9 +6547,9 @@ variables.
                 AddForbiddenAssignments(self, variables, tuples_list):
         
    -
    +
    View Source -
        def AddForbiddenAssignments(self, variables, tuples_list):
    +            
        def AddForbiddenAssignments(self, variables, tuples_list):
             """Adds AddForbiddenAssignments(variables, [tuples_list]).
     
         A ForbiddenAssignments constraint is a constraint on an array of variables
    @@ -6368,9 +6628,9 @@ variables.
     ):
         
    -
    +
    View Source -
        def AddAutomaton(self, transition_variables, starting_state, final_states,
    +            
        def AddAutomaton(self, transition_variables, starting_state, final_states,
                          transition_triples):
             """Adds an automaton constraint.
     
    @@ -6505,9 +6765,9 @@ following format (current_state, variable_value, next_state).
                 AddInverse(self, variables, inverse_variables):
         
    -
    +
    View Source -
        def AddInverse(self, variables, inverse_variables):
    +            
        def AddInverse(self, variables, inverse_variables):
             """Adds Inverse(variables, inverse_variables).
     
         An inverse constraint enforces that if `variables[i]` is assigned a value
    @@ -6579,9 +6839,9 @@ if they are empty.
                 AddReservoirConstraint(self, times, level_changes, min_level, max_level):
         
    -
    +
    View Source -
        def AddReservoirConstraint(self, times, level_changes, min_level,
    +            
        def AddReservoirConstraint(self, times, level_changes, min_level,
                                    max_level):
             """Adds Reservoir(times, level_changes, min_level, max_level).
     
    @@ -6692,9 +6952,9 @@ than the max level.
                 AddReservoirConstraintWithActive(self, times, level_changes, actives, min_level, max_level):
         
    -
    +
    View Source -
        def AddReservoirConstraintWithActive(self, times, level_changes, actives,
    +            
        def AddReservoirConstraintWithActive(self, times, level_changes, actives,
                                              min_level, max_level):
             """Adds Reservoir(times, level_changes, actives, min_level, max_level).
     
    @@ -6824,9 +7084,9 @@ than the max level.
                 AddMapDomain(self, var, bool_var_array, offset=0):
         
    -
    +
    View Source -
        def AddMapDomain(self, var, bool_var_array, offset=0):
    +            
        def AddMapDomain(self, var, bool_var_array, offset=0):
             """Adds `var == i + offset <=> bool_var_array[i] == true for all i`."""
     
             for i, bool_var in enumerate(bool_var_array):
    @@ -6863,9 +7123,9 @@ than the max level.
                 AddImplication(self, a, b):
         
    -
    +
    View Source -
        def AddImplication(self, a, b):
    +            
        def AddImplication(self, a, b):
             """Adds `a => b` (`a` implies `b`)."""
             ct = Constraint(self.__model.constraints)
             model_ct = self.__model.constraints[ct.Index()]
    @@ -6886,23 +7146,103 @@ than the max level.
     
             
                 def
    -            AddBoolOr(self, literals):
    +            AddBoolOr(self, *literals):
         
    -
    +
    View Source -
        def AddBoolOr(self, literals):
    -        """Adds `Or(literals) == true`."""
    +            
        def AddBoolOr(self, *literals):
    +        """Adds `Or(literals) == true`: Sum(literals) >= 1."""
             ct = Constraint(self.__model.constraints)
             model_ct = self.__model.constraints[ct.Index()]
    -        model_ct.bool_or.literals.extend(
    -            [self.GetOrMakeBooleanIndex(x) for x in literals])
    +        model_ct.bool_or.literals.extend([
    +            self.GetOrMakeBooleanIndex(x)
    +            for x in ExpandGeneratorOrTuple(literals)
    +        ])
             return ct
     
    -

    Adds Or(literals) == true.

    +

    Adds Or(literals) == true: Sum(literals) >= 1.

    +
    + + +
    +
    +
    #   + + + def + AddAtLeastOne(self, *literals): +
    + +
    + View Source +
        def AddAtLeastOne(self, *literals):
    +        """Same as `AddBoolOr`: `Sum(literals) >= 1`."""
    +        return self.AddBoolOr(*literals)
    +
    + +
    + +

    Same as AddBoolOr: Sum(literals) >= 1.

    +
    + + +
    +
    +
    #   + + + def + AddAtMostOne(self, *literals): +
    + +
    + View Source +
        def AddAtMostOne(self, *literals):
    +        """Adds `AtMostOne(literals)`: `Sum(literals) <= 1`."""
    +        ct = Constraint(self.__model.constraints)
    +        model_ct = self.__model.constraints[ct.Index()]
    +        model_ct.at_most_one.literals.extend([
    +            self.GetOrMakeBooleanIndex(x)
    +            for x in ExpandGeneratorOrTuple(literals)
    +        ])
    +        return ct
    +
    + +
    + +

    Adds AtMostOne(literals): Sum(literals) <= 1.

    +
    + + +
    +
    +
    #   + + + def + AddExactlyOne(self, *literals): +
    + +
    + View Source +
        def AddExactlyOne(self, *literals):
    +        """Adds `ExactlyOne(literals)`: `Sum(literals) == 1`."""
    +        ct = Constraint(self.__model.constraints)
    +        model_ct = self.__model.constraints[ct.Index()]
    +        model_ct.exactly_one.literals.extend([
    +            self.GetOrMakeBooleanIndex(x)
    +            for x in ExpandGeneratorOrTuple(literals)
    +        ])
    +        return ct
    +
    + +
    + +

    Adds ExactlyOne(literals): Sum(literals) == 1.

    @@ -6912,17 +7252,19 @@ than the max level. def - AddBoolAnd(self, literals): + AddBoolAnd(self, *literals):
    -
    +
    View Source -
        def AddBoolAnd(self, literals):
    +            
        def AddBoolAnd(self, *literals):
             """Adds `And(literals) == true`."""
             ct = Constraint(self.__model.constraints)
             model_ct = self.__model.constraints[ct.Index()]
    -        model_ct.bool_and.literals.extend(
    -            [self.GetOrMakeBooleanIndex(x) for x in literals])
    +        model_ct.bool_and.literals.extend([
    +            self.GetOrMakeBooleanIndex(x)
    +            for x in ExpandGeneratorOrTuple(literals)
    +        ])
             return ct
     
    @@ -6938,27 +7280,29 @@ than the max level. def - AddBoolXOr(self, literals): + AddBoolXOr(self, *literals):
    -
    +
    View Source -
        def AddBoolXOr(self, literals):
    +            
        def AddBoolXOr(self, *literals):
             """Adds `XOr(literals) == true`.
     
         In contrast to AddBoolOr and AddBoolAnd, it does not support
             .OnlyEnforceIf().
     
         Args:
    -      literals: the list of literals in the constraint.
    +      *literals: the list of literals in the constraint.
     
         Returns:
           An `Constraint` object.
         """
             ct = Constraint(self.__model.constraints)
             model_ct = self.__model.constraints[ct.Index()]
    -        model_ct.bool_xor.literals.extend(
    -            [self.GetOrMakeBooleanIndex(x) for x in literals])
    +        model_ct.bool_xor.literals.extend([
    +            self.GetOrMakeBooleanIndex(x)
    +            for x in ExpandGeneratorOrTuple(literals)
    +        ])
             return ct
     
    @@ -6972,7 +7316,7 @@ than the max level.
    Args
      -
    • literals: the list of literals in the constraint.
    • +
    • *literals: the list of literals in the constraint.
    Returns
    @@ -6992,10 +7336,10 @@ than the max level. AddMinEquality(self, target, exprs):
    -
    +
    View Source -
        def AddMinEquality(self, target, exprs):
    -        """Adds `target == Min(variables)`."""
    +            
        def AddMinEquality(self, target, exprs):
    +        """Adds `target == Min(exprs)`."""
             ct = Constraint(self.__model.constraints)
             model_ct = self.__model.constraints[ct.Index()]
             model_ct.lin_max.exprs.extend(
    @@ -7007,7 +7351,7 @@ than the max level.
     
             
    -

    Adds target == Min(variables).

    +

    Adds target == Min(exprs).

    @@ -7020,10 +7364,10 @@ than the max level. AddMaxEquality(self, target, exprs):
    -
    +
    View Source -
        def AddMaxEquality(self, target, exprs):
    -        """Adds `target == Max(variables)`."""
    +            
        def AddMaxEquality(self, target, exprs):
    +        """Adds `target == Max(exprs)`."""
             ct = Constraint(self.__model.constraints)
             model_ct = self.__model.constraints[ct.Index()]
             model_ct.lin_max.exprs.extend(
    @@ -7034,7 +7378,7 @@ than the max level.
     
             
    -

    Adds target == Max(variables).

    +

    Adds target == Max(exprs).

    @@ -7047,9 +7391,9 @@ than the max level. AddDivisionEquality(self, target, num, denom):
    -
    +
    View Source -
        def AddDivisionEquality(self, target, num, denom):
    +            
        def AddDivisionEquality(self, target, num, denom):
             """Adds `target == num // denom` (integer division rounded towards 0)."""
             ct = Constraint(self.__model.constraints)
             model_ct = self.__model.constraints[ct.Index()]
    @@ -7074,9 +7418,9 @@ than the max level.
                 AddAbsEquality(self, target, expr):
         
    -
    +
    View Source -
        def AddAbsEquality(self, target, expr):
    +            
        def AddAbsEquality(self, target, expr):
             """Adds `target == Abs(var)`."""
             ct = Constraint(self.__model.constraints)
             model_ct = self.__model.constraints[ct.Index()]
    @@ -7101,9 +7445,9 @@ than the max level.
                 AddModuloEquality(self, target, var, mod):
         
    -
    +
    View Source -
        def AddModuloEquality(self, target, var, mod):
    +            
        def AddModuloEquality(self, target, var, mod):
             """Adds `target = var % mod`."""
             ct = Constraint(self.__model.constraints)
             model_ct = self.__model.constraints[ct.Index()]
    @@ -7125,24 +7469,26 @@ than the max level.
     
             
                 def
    -            AddMultiplicationEquality(self, target, expressions):
    +            AddMultiplicationEquality(self, target, *expressions):
         
    -
    +
    View Source -
        def AddMultiplicationEquality(self, target, expressions):
    -        """Adds `target == variables[0] * .. * variables[n]`."""
    +            
        def AddMultiplicationEquality(self, target, *expressions):
    +        """Adds `target == expressions[0] * .. * expressions[n]`."""
             ct = Constraint(self.__model.constraints)
             model_ct = self.__model.constraints[ct.Index()]
    -        model_ct.int_prod.exprs.extend(
    -            [self.ParseLinearExpression(expr) for expr in expressions])
    +        model_ct.int_prod.exprs.extend([
    +            self.ParseLinearExpression(expr)
    +            for expr in ExpandGeneratorOrTuple(expressions)
    +        ])
             model_ct.int_prod.target.CopyFrom(self.ParseLinearExpression(target))
             return ct
     
    -

    Adds target == variables[0] * .. * variables[n].

    +

    Adds target == expressions[0] * .. * expressions[n].

    @@ -7155,9 +7501,9 @@ than the max level. NewIntervalVar(self, start, size, end, name):
    -
    +
    View Source -
        def NewIntervalVar(self, start, size, end, name):
    +            
        def NewIntervalVar(self, start, size, end, name):
             """Creates an interval variable from start, size, and end.
     
         An interval variable is a constraint, that is itself used in other
    @@ -7232,9 +7578,9 @@ expression.
                 NewFixedSizeIntervalVar(self, start, size, name):
         
    -
    +
    View Source -
        def NewFixedSizeIntervalVar(self, start, size, name):
    +            
        def NewFixedSizeIntervalVar(self, start, size, name):
             """Creates an interval variable from start, and a fixed size.
     
         An interval variable is a constraint, that is itself used in other
    @@ -7293,9 +7639,9 @@ expression.
                 NewOptionalIntervalVar(self, start, size, end, is_present, name):
         
    -
    +
    View Source -
        def NewOptionalIntervalVar(self, start, size, end, is_present, name):
    +            
        def NewOptionalIntervalVar(self, start, size, end, is_present, name):
             """Creates an optional interval var from start, size, end, and is_present.
     
         An optional interval variable is a constraint, that is itself used in other
    @@ -7381,9 +7727,9 @@ inactive interval is simply ignored by all constraints.
                 NewOptionalFixedSizeIntervalVar(self, start, size, is_present, name):
         
    -
    +
    View Source -
        def NewOptionalFixedSizeIntervalVar(self, start, size, is_present, name):
    +            
        def NewOptionalFixedSizeIntervalVar(self, start, size, is_present, name):
             """Creates an interval variable from start, and a fixed size.
     
         An interval variable is a constraint, that is itself used in other
    @@ -7447,9 +7793,9 @@ inactive interval is simply ignored by all constraints.
                 AddNoOverlap(self, interval_vars):
         
    -
    +
    View Source -
        def AddNoOverlap(self, interval_vars):
    +            
        def AddNoOverlap(self, interval_vars):
             """Adds NoOverlap(interval_vars).
     
         A NoOverlap constraint ensures that all present intervals do not overlap
    @@ -7498,9 +7844,9 @@ in time.

    AddNoOverlap2D(self, x_intervals, y_intervals):
    -
    +
    View Source -
        def AddNoOverlap2D(self, x_intervals, y_intervals):
    +            
        def AddNoOverlap2D(self, x_intervals, y_intervals):
             """Adds NoOverlap2D(x_intervals, y_intervals).
     
         A NoOverlap2D constraint ensures that all present rectangles do not overlap
    @@ -7561,9 +7907,9 @@ optional.

    AddCumulative(self, intervals, demands, capacity):
    -
    +
    View Source -
        def AddCumulative(self, intervals, demands, capacity):
    +            
        def AddCumulative(self, intervals, demands, capacity):
             """Adds Cumulative(intervals, demands, capacity).
     
         This constraint enforces that:
    @@ -7634,9 +7980,9 @@ positive integer value or variable.
                 CopyFrom(self, other_model):
         
    -
    +
    View Source -
        def CopyFrom(self, other_model):
    +            
        def CopyFrom(self, other_model):
             """Reset the model, and creates a new one from a CpModelProto instance."""
             self.__model.CopyFrom(other_model.Proto())
     
    @@ -7662,9 +8008,9 @@ positive integer value or variable.
                 GetBoolVarFromProtoIndex(self, index):
         
    -
    +
    View Source -
        def GetBoolVarFromProtoIndex(self, index):
    +            
        def GetBoolVarFromProtoIndex(self, index):
             """Returns an already created Boolean variable from its index."""
             if index < 0 or index >= len(self.__model.variables):
                 raise ValueError(
    @@ -7693,9 +8039,9 @@ positive integer value or variable.
                 GetIntVarFromProtoIndex(self, index):
         
    -
    +
    View Source -
        def GetIntVarFromProtoIndex(self, index):
    +            
        def GetIntVarFromProtoIndex(self, index):
             """Returns an already created integer variable from its index."""
             if index < 0 or index >= len(self.__model.variables):
                 raise ValueError(
    @@ -7718,9 +8064,9 @@ positive integer value or variable.
                 GetIntervalVarFromProtoIndex(self, index):
         
    -
    +
    View Source -
        def GetIntervalVarFromProtoIndex(self, index):
    +            
        def GetIntervalVarFromProtoIndex(self, index):
             """Returns an already created interval variable from its index."""
             if index < 0 or index >= len(self.__model.constraints):
                 raise ValueError(
    @@ -7749,9 +8095,9 @@ positive integer value or variable.
                 Proto(self):
         
    -
    +
    View Source -
        def Proto(self):
    +            
        def Proto(self):
             """Returns the underlying CpModelProto."""
             return self.__model
     
    @@ -7771,9 +8117,9 @@ positive integer value or variable. Negated(self, index):
    -
    +
    View Source -
        def Negated(self, index):
    +            
        def Negated(self, index):
             return -index - 1
     
    @@ -7790,9 +8136,9 @@ positive integer value or variable. GetOrMakeIndex(self, arg):
    -
    +
    View Source -
        def GetOrMakeIndex(self, arg):
    +            
        def GetOrMakeIndex(self, arg):
             """Returns the index of a variable, its negation, or a number."""
             if isinstance(arg, IntVar):
                 return arg.Index()
    @@ -7822,9 +8168,9 @@ positive integer value or variable.
                 GetOrMakeBooleanIndex(self, arg):
         
    -
    +
    View Source -
        def GetOrMakeBooleanIndex(self, arg):
    +            
        def GetOrMakeBooleanIndex(self, arg):
             """Returns an index from a boolean expression."""
             if isinstance(arg, IntVar):
                 self.AssertIsBooleanVariable(arg)
    @@ -7855,9 +8201,9 @@ positive integer value or variable.
                 GetIntervalIndex(self, arg):
         
    -
    +
    View Source -
        def GetIntervalIndex(self, arg):
    +            
        def GetIntervalIndex(self, arg):
             if not isinstance(arg, IntervalVar):
                 raise TypeError('NotSupported: model.GetIntervalIndex(%s)' % arg)
             return arg.Index()
    @@ -7876,9 +8222,9 @@ positive integer value or variable.
                 GetOrMakeIndexFromConstant(self, value):
         
    -
    +
    View Source -
        def GetOrMakeIndexFromConstant(self, value):
    +            
        def GetOrMakeIndexFromConstant(self, value):
             if value in self.__constant_map:
                 return self.__constant_map[value]
             index = len(self.__model.variables)
    @@ -7901,9 +8247,9 @@ positive integer value or variable.
                 VarIndexToVarProto(self, var_index):
         
    -
    +
    View Source -
        def VarIndexToVarProto(self, var_index):
    +            
        def VarIndexToVarProto(self, var_index):
             if var_index >= 0:
                 return self.__model.variables[var_index]
             else:
    @@ -7923,9 +8269,9 @@ positive integer value or variable.
                 ParseLinearExpression(self, linear_expr, negate=False):
         
    -
    +
    View Source -
        def ParseLinearExpression(self, linear_expr, negate=False):
    +            
        def ParseLinearExpression(self, linear_expr, negate=False):
             """Returns a LinearExpressionProto built from a LinearExpr instance."""
             result = cp_model_pb2.LinearExpressionProto()
             mult = -1 if negate else 1
    @@ -7964,9 +8310,9 @@ positive integer value or variable.
                 Minimize(self, obj):
         
    -
    +
    View Source -
        def Minimize(self, obj):
    +            
        def Minimize(self, obj):
             """Sets the objective of the model to minimize(obj)."""
             self._SetObjective(obj, minimize=True)
     
    @@ -7986,9 +8332,9 @@ positive integer value or variable. Maximize(self, obj):
    -
    +
    View Source -
        def Maximize(self, obj):
    +            
        def Maximize(self, obj):
             """Sets the objective of the model to maximize(obj)."""
             self._SetObjective(obj, minimize=False)
     
    @@ -8008,9 +8354,9 @@ positive integer value or variable. HasObjective(self):
    -
    +
    View Source -
        def HasObjective(self):
    +            
        def HasObjective(self):
             return self.__model.HasField('objective')
     
    @@ -8027,9 +8373,9 @@ positive integer value or variable. AddDecisionStrategy(self, variables, var_strategy, domain_strategy):
    -
    +
    View Source -
        def AddDecisionStrategy(self, variables, var_strategy, domain_strategy):
    +            
        def AddDecisionStrategy(self, variables, var_strategy, domain_strategy):
             """Adds a search strategy to the model.
     
         Args:
    @@ -8074,11 +8420,12 @@ Currently, this is advanced code: the union of all strategies added to
                 ModelStats(self):
         
    -
    +
    View Source -
        def ModelStats(self):
    +            
        def ModelStats(self):
             """Returns a string containing some model statistics."""
    -        return pywrapsat.CpSatHelper.ModelStats(self.__model)
    +        return swig_helper.CpSatHelper.SerializedModelStats(
    +            self.__model.SerializeToString())
     
    @@ -8096,11 +8443,12 @@ Currently, this is advanced code: the union of all strategies added to Validate(self):
    -
    +
    View Source -
        def Validate(self):
    +            
        def Validate(self):
             """Returns a string indicating that the model is invalid."""
    -        return pywrapsat.CpSatHelper.ValidateModel(self.__model)
    +        return swig_helper.CpSatHelper.SerializedValidateModel(
    +            self.__model.SerializeToString())
     
    @@ -8118,9 +8466,9 @@ Currently, this is advanced code: the union of all strategies added to ExportToFile(self, file):
    -
    +
    View Source -
        def ExportToFile(self, file):
    +            
        def ExportToFile(self, file):
             """Write the model as a protocol buffer to 'file'.
     
         Args:
    @@ -8131,7 +8479,8 @@ Currently, this is advanced code: the union of all strategies added to
         Returns:
           True if the model was correctly written.
         """
    -        return pywrapsat.CpSatHelper.WriteModelToFile(self.__model, file)
    +        return swig_helper.CpSatHelper.SerializedWriteModelToFile(
    +            self.__model.SerializeToString(), file)
     
    @@ -8163,9 +8512,9 @@ be used. AssertIsBooleanVariable(self, x):
    -
    +
    View Source -
        def AssertIsBooleanVariable(self, x):
    +            
        def AssertIsBooleanVariable(self, x):
             if isinstance(x, IntVar):
                 var = self.__model.variables[x.Index()]
                 if len(var.domain) != 2 or var.domain[0] < 0 or var.domain[1] > 1:
    @@ -8189,9 +8538,9 @@ be used.
                 AddHint(self, var, value):
         
    -
    +
    View Source -
        def AddHint(self, var, value):
    +            
        def AddHint(self, var, value):
             """Adds 'var == value' as a hint to the solver."""
             self.__model.solution_hint.vars.append(self.GetOrMakeIndex(var))
             self.__model.solution_hint.values.append(value)
    @@ -8212,9 +8561,9 @@ be used.
                 ClearHints(self):
         
    -
    +
    View Source -
        def ClearHints(self):
    +            
        def ClearHints(self):
             """Remove any solution hint from the model."""
             self.__model.ClearField('solution_hint')
     
    @@ -8234,9 +8583,9 @@ be used. AddAssumption(self, lit):
    -
    +
    View Source -
        def AddAssumption(self, lit):
    +            
        def AddAssumption(self, lit):
             """Add the literal 'lit' to the model as assumptions."""
             self.__model.assumptions.append(self.GetOrMakeBooleanIndex(lit))
     
    @@ -8256,9 +8605,9 @@ be used. AddAssumptions(self, literals):
    -
    +
    View Source -
        def AddAssumptions(self, literals):
    +            
        def AddAssumptions(self, literals):
             """Add the literals to the model as assumptions."""
             for lit in literals:
                 self.AddAssumption(lit)
    @@ -8279,9 +8628,9 @@ be used.
                 ClearAssumptions(self):
         
    -
    +
    View Source -
        def ClearAssumptions(self):
    +            
        def ClearAssumptions(self):
             """Remove all assumptions from the model."""
             self.__model.ClearField('assumptions')
     
    @@ -8293,6 +8642,31 @@ be used.
    +
+
+
#   + + + def + ExpandGeneratorOrTuple(args): +
+ +
+ View Source +
def ExpandGeneratorOrTuple(args):
+    if hasattr(args, '__len__'):  # Tuple
+        if len(args) != 1:
+            return args
+        if cmh.is_a_number(args[0]) or isinstance(args[0], LinearExpr):
+            return args
+    # Generator
+    return args[0]
+
+ +
+ + +
#   @@ -8302,9 +8676,9 @@ be used. EvaluateLinearExpr(expression, solution):
-
+
View Source -
def EvaluateLinearExpr(expression, solution):
+            
def EvaluateLinearExpr(expression, solution):
     """Evaluate a linear expression against a solution."""
     if cmh.is_integral(expression):
         return int(expression)
@@ -8327,7 +8701,7 @@ be used.
             for e in expr.Expressions():
                 to_process.append((e, coeff))
             value += expr.Constant() * coeff
-        elif isinstance(expr, _ScalProd):
+        elif isinstance(expr, _WeightedSum):
             for e, c in zip(expr.Expressions(), expr.Coefficients()):
                 to_process.append((e, coeff * c))
             value += expr.Constant() * coeff
@@ -8356,9 +8730,9 @@ be used.
             EvaluateBooleanExpression(literal, solution):
     
-
+
View Source -
def EvaluateBooleanExpression(literal, solution):
+            
def EvaluateBooleanExpression(literal, solution):
     """Evaluate a boolean expression against a solution."""
     if cmh.is_integral(literal):
         return bool(literal)
@@ -8389,9 +8763,9 @@ be used.
         CpSolver:
     
-
+
View Source -
class CpSolver(object):
+            
class CpSolver(object):
     """Main solver class.
 
   The purpose of this class is to search for a solution to the model provided
@@ -8407,22 +8781,25 @@ be used.
         self.__solution: cp_model_pb2.CpSolverResponse = None
         self.parameters = sat_parameters_pb2.SatParameters()
         self.log_callback = None
-        self.__solve_wrapper: pywrapsat.SolveWrapper = None
+        self.__solve_wrapper: swig_helper.SolveWrapper = None
         self.__lock = threading.Lock()
 
     def Solve(self, model, solution_callback=None):
         """Solves a problem and passes each solution to the callback if not null."""
         with self.__lock:
-            solve_wrapper = pywrapsat.SolveWrapper()
+            solve_wrapper = swig_helper.SolveWrapper()
 
-        solve_wrapper.SetParameters(self.parameters)
+        swig_helper.SolveWrapper.SetSerializedParameters(
+            self.parameters.SerializeToString(), solve_wrapper)
         if solution_callback is not None:
             solve_wrapper.AddSolutionCallback(solution_callback)
 
         if self.log_callback is not None:
             solve_wrapper.AddLogCallback(self.log_callback)
 
-        self.__solution = solve_wrapper.Solve(model.Proto())
+        self.__solution = cp_model_pb2.CpSolverResponse.FromString(
+            swig_helper.SolveWrapper.SerializedSolve(
+                model.Proto().SerializeToString(), solve_wrapper))
 
         if solution_callback is not None:
             solve_wrapper.ClearSolutionCallback(solution_callback)
@@ -8530,7 +8907,8 @@ be used.
 
     def ResponseStats(self):
         """Returns some statistics on the solution found as a string."""
-        return pywrapsat.CpSatHelper.SolverResponseStats(self.__solution)
+        return swig_helper.CpSatHelper.SerializedSolverResponseStats(
+            self.__solution.SerializeToString())
 
     def ResponseProto(self):
         """Returns the response object."""
@@ -8569,14 +8947,14 @@ about the solve procedure.

CpSolver()
-
+
View Source -
    def __init__(self):
+            
    def __init__(self):
         self.__model = None
         self.__solution: cp_model_pb2.CpSolverResponse = None
         self.parameters = sat_parameters_pb2.SatParameters()
         self.log_callback = None
-        self.__solve_wrapper: pywrapsat.SolveWrapper = None
+        self.__solve_wrapper: swig_helper.SolveWrapper = None
         self.__lock = threading.Lock()
 
@@ -8593,21 +8971,24 @@ about the solve procedure.

Solve(self, model, solution_callback=None):
-
+
View Source -
    def Solve(self, model, solution_callback=None):
+            
    def Solve(self, model, solution_callback=None):
         """Solves a problem and passes each solution to the callback if not null."""
         with self.__lock:
-            solve_wrapper = pywrapsat.SolveWrapper()
+            solve_wrapper = swig_helper.SolveWrapper()
 
-        solve_wrapper.SetParameters(self.parameters)
+        swig_helper.SolveWrapper.SetSerializedParameters(
+            self.parameters.SerializeToString(), solve_wrapper)
         if solution_callback is not None:
             solve_wrapper.AddSolutionCallback(solution_callback)
 
         if self.log_callback is not None:
             solve_wrapper.AddLogCallback(self.log_callback)
 
-        self.__solution = solve_wrapper.Solve(model.Proto())
+        self.__solution = cp_model_pb2.CpSolverResponse.FromString(
+            swig_helper.SolveWrapper.SerializedSolve(
+                model.Proto().SerializeToString(), solve_wrapper))
 
         if solution_callback is not None:
             solve_wrapper.ClearSolutionCallback(solution_callback)
@@ -8633,9 +9014,9 @@ about the solve procedure.

SolveWithSolutionCallback(self, model, callback):
-
+
View Source -
    def SolveWithSolutionCallback(self, model, callback):
+            
    def SolveWithSolutionCallback(self, model, callback):
         """DEPRECATED Use Solve() with the callback argument."""
         warnings.warn(
             'SolveWithSolutionCallback is deprecated; use Solve() with' +
@@ -8658,9 +9039,9 @@ about the solve procedure.

SearchForAllSolutions(self, model, callback):
-
+
View Source -
    def SearchForAllSolutions(self, model, callback):
+            
    def SearchForAllSolutions(self, model, callback):
         """DEPRECATED Use Solve() with the right parameter.
 
     Search for all solutions of a satisfiability problem.
@@ -8739,9 +9120,9 @@ Then it feeds the solution to the callback.

StopSearch(self):
-
+
View Source -
    def StopSearch(self):
+            
    def StopSearch(self):
         """Stops the current search asynchronously."""
         with self.__lock:
             if self.__solve_wrapper:
@@ -8763,9 +9144,9 @@ Then it feeds the solution to the callback.

Value(self, expression):
-
+
View Source -
    def Value(self, expression):
+            
    def Value(self, expression):
         """Returns the value of a linear expression after solve."""
         if not self.__solution:
             raise RuntimeError('Solve() has not be called.')
@@ -8787,9 +9168,9 @@ Then it feeds the solution to the callback.

BooleanValue(self, literal):
-
+
View Source -
    def BooleanValue(self, literal):
+            
    def BooleanValue(self, literal):
         """Returns the boolean value of a literal after solve."""
         if not self.__solution:
             raise RuntimeError('Solve() has not be called.')
@@ -8811,9 +9192,9 @@ Then it feeds the solution to the callback.

ObjectiveValue(self):
-
+
View Source -
    def ObjectiveValue(self):
+            
    def ObjectiveValue(self):
         """Returns the value of the objective after solve."""
         return self.__solution.objective_value
 
@@ -8833,9 +9214,9 @@ Then it feeds the solution to the callback.

BestObjectiveBound(self):
-
+
View Source -
    def BestObjectiveBound(self):
+            
    def BestObjectiveBound(self):
         """Returns the best lower (upper) bound found when min(max)imizing."""
         return self.__solution.best_objective_bound
 
@@ -8855,9 +9236,9 @@ Then it feeds the solution to the callback.

StatusName(self, status=None):
-
+
View Source -
    def StatusName(self, status=None):
+            
    def StatusName(self, status=None):
         """Returns the name of the status returned by Solve()."""
         if status is None:
             status = self.__solution.status
@@ -8879,9 +9260,9 @@ Then it feeds the solution to the callback.

NumBooleans(self):
-
+
View Source -
    def NumBooleans(self):
+            
    def NumBooleans(self):
         """Returns the number of boolean variables managed by the SAT solver."""
         return self.__solution.num_booleans
 
@@ -8901,9 +9282,9 @@ Then it feeds the solution to the callback.

NumConflicts(self):
-
+
View Source -
    def NumConflicts(self):
+            
    def NumConflicts(self):
         """Returns the number of conflicts since the creation of the solver."""
         return self.__solution.num_conflicts
 
@@ -8923,9 +9304,9 @@ Then it feeds the solution to the callback.

NumBranches(self):
-
+
View Source -
    def NumBranches(self):
+            
    def NumBranches(self):
         """Returns the number of search branches explored by the solver."""
         return self.__solution.num_branches
 
@@ -8945,9 +9326,9 @@ Then it feeds the solution to the callback.

WallTime(self):
-
+
View Source -
    def WallTime(self):
+            
    def WallTime(self):
         """Returns the wall time in seconds since the creation of the solver."""
         return self.__solution.wall_time
 
@@ -8967,9 +9348,9 @@ Then it feeds the solution to the callback.

UserTime(self):
-
+
View Source -
    def UserTime(self):
+            
    def UserTime(self):
         """Returns the user time in seconds since the creation of the solver."""
         return self.__solution.user_time
 
@@ -8989,11 +9370,12 @@ Then it feeds the solution to the callback.

ResponseStats(self):
-
+
View Source -
    def ResponseStats(self):
+            
    def ResponseStats(self):
         """Returns some statistics on the solution found as a string."""
-        return pywrapsat.CpSatHelper.SolverResponseStats(self.__solution)
+        return swig_helper.CpSatHelper.SerializedSolverResponseStats(
+            self.__solution.SerializeToString())
 
@@ -9011,9 +9393,9 @@ Then it feeds the solution to the callback.

ResponseProto(self):
-
+
View Source -
    def ResponseProto(self):
+            
    def ResponseProto(self):
         """Returns the response object."""
         return self.__solution
 
@@ -9033,9 +9415,9 @@ Then it feeds the solution to the callback.

SufficientAssumptionsForInfeasibility(self):
-
+
View Source -
    def SufficientAssumptionsForInfeasibility(self):
+            
    def SufficientAssumptionsForInfeasibility(self):
         """Returns the indices of the infeasible assumptions."""
         return self.__solution.sufficient_assumptions_for_infeasibility
 
@@ -9055,9 +9437,9 @@ Then it feeds the solution to the callback.

SolutionInfo(self):
-
+
View Source -
    def SolutionInfo(self):
+            
    def SolutionInfo(self):
         """Returns some information on the solve process.
 
     Returns some information on how the solution was found, or the reason
@@ -9083,12 +9465,12 @@ why the model or the parameters are invalid.

class - CpSolverSolutionCallback(ortools.sat.pywrapsat.SolutionCallback): + CpSolverSolutionCallback(ortools.sat.python.swig_helper.SolutionCallback):
-
+
View Source -
class CpSolverSolutionCallback(pywrapsat.SolutionCallback):
+            
class CpSolverSolutionCallback(swig_helper.SolutionCallback):
     """Solution callback.
 
   This class implements a callback that will be called at each new solution
@@ -9113,7 +9495,7 @@ why the model or the parameters are invalid.

""" def __init__(self): - pywrapsat.SolutionCallback.__init__(self) + swig_helper.SolutionCallback.__init__(self) def OnSolutionCallback(self): """Proxy for the same method in snake case.""" @@ -9173,7 +9555,7 @@ why the model or the parameters are invalid.

for e in expr.Expressions(): to_process.append((e, coeff)) value += expr.Constant() * coeff - elif isinstance(expr, _ScalProd): + elif isinstance(expr, _WeightedSum): for e, c in zip(expr.Expressions(), expr.Coefficients()): to_process.append((e, coeff * c)) value += expr.Constant() * coeff @@ -9187,6 +9569,11 @@ why the model or the parameters are invalid.

f'Cannot interpret {expression} as a linear expression.') return value + + def Response(self): + """Returns the current solution response.""" + return cp_model_pb2.CpSolverResponse.FromString( + swig_helper.SolutionCallback.SerializedResponse(self))
@@ -9224,15 +9611,17 @@ and Value() methods.

CpSolverSolutionCallback()
-
+
View Source -
    def __init__(self):
-        pywrapsat.SolutionCallback.__init__(self)
+            
    def __init__(self):
+        swig_helper.SolutionCallback.__init__(self)
 
- +

__init__(self: ortools.sat.python.swig_helper.SolutionCallback) -> None

+
+
@@ -9243,9 +9632,9 @@ and Value() methods.

OnSolutionCallback(self):
-
+
View Source -
    def OnSolutionCallback(self):
+            
    def OnSolutionCallback(self):
         """Proxy for the same method in snake case."""
         self.on_solution_callback()
 
@@ -9265,9 +9654,9 @@ and Value() methods.

BooleanValue(self, lit):
-
+
View Source -
    def BooleanValue(self, lit):
+            
    def BooleanValue(self, lit):
         """Returns the boolean value of a boolean literal.
 
     Args:
@@ -9323,9 +9712,9 @@ and Value() methods.

Value(self, expression):
-
+
View Source -
    def Value(self, expression):
+            
    def Value(self, expression):
         """Evaluates an linear expression in the current solution.
 
     Args:
@@ -9357,7 +9746,7 @@ and Value() methods.

for e in expr.Expressions(): to_process.append((e, coeff)) value += expr.Constant() * coeff - elif isinstance(expr, _ScalProd): + elif isinstance(expr, _WeightedSum): for e, c in zip(expr.Expressions(), expr.Coefficients()): to_process.append((e, coeff * c)) value += expr.Constant() * coeff @@ -9398,26 +9787,49 @@ and Value() methods.

+
+
+
#   + + + def + Response(self): +
+ +
+ View Source +
    def Response(self):
+        """Returns the current solution response."""
+        return cp_model_pb2.CpSolverResponse.FromString(
+            swig_helper.SolutionCallback.SerializedResponse(self))
+
+ +
+ +

Returns the current solution response.

+
+ +
Inherited Members
-
ortools.sat.pywrapsat.SolutionCallback
-
thisown
+
ortools.sat.python.swig_helper.SolutionCallback
+
BestObjectiveBound
+
DeterministicTime
+
HasResponse
+
NumBinaryPropagations
NumBooleans
NumBranches
NumConflicts
-
NumBinaryPropagations
NumIntegerPropagations
-
WallTime
-
UserTime
ObjectiveValue
-
BestObjectiveBound
-
SolutionIntegerValue
+
SerializedResponse
SolutionBooleanValue
+
SolutionIntegerValue
StopSearch
-
Response
-
HasResponse
+
UserTime
+
WallTime
@@ -9432,9 +9844,9 @@ and Value() methods.

ObjectiveSolutionPrinter(CpSolverSolutionCallback):
-
+
View Source -
class ObjectiveSolutionPrinter(CpSolverSolutionCallback):
+            
class ObjectiveSolutionPrinter(CpSolverSolutionCallback):
     """Display the objective value and time of intermediate solutions."""
 
     def __init__(self):
@@ -9468,9 +9880,9 @@ and Value() methods.

ObjectiveSolutionPrinter()
-
+
View Source -
    def __init__(self):
+            
    def __init__(self):
         CpSolverSolutionCallback.__init__(self)
         self.__solution_count = 0
         self.__start_time = time.time()
@@ -9478,7 +9890,9 @@ and Value() methods.

- +

__init__(self: ortools.sat.python.swig_helper.SolutionCallback) -> None

+
+
@@ -9489,9 +9903,9 @@ and Value() methods.

on_solution_callback(self):
-
+
View Source -
    def on_solution_callback(self):
+            
    def on_solution_callback(self):
         """Called on each new solution."""
         current_time = time.time()
         obj = self.ObjectiveValue()
@@ -9515,9 +9929,9 @@ and Value() methods.

solution_count(self):
-
+
View Source -
    def solution_count(self):
+            
    def solution_count(self):
         """Returns the number of solutions found."""
         return self.__solution_count
 
@@ -9536,24 +9950,25 @@ and Value() methods.

OnSolutionCallback
BooleanValue
Value
+
Response
-
ortools.sat.pywrapsat.SolutionCallback
-
thisown
+
ortools.sat.python.swig_helper.SolutionCallback
+
BestObjectiveBound
+
DeterministicTime
+
HasResponse
+
NumBinaryPropagations
NumBooleans
NumBranches
NumConflicts
-
NumBinaryPropagations
NumIntegerPropagations
-
WallTime
-
UserTime
ObjectiveValue
-
BestObjectiveBound
-
SolutionIntegerValue
+
SerializedResponse
SolutionBooleanValue
+
SolutionIntegerValue
StopSearch
-
Response
-
HasResponse
+
UserTime
+
WallTime
@@ -9568,9 +9983,9 @@ and Value() methods.

VarArrayAndObjectiveSolutionPrinter(CpSolverSolutionCallback):
-
+
View Source -
class VarArrayAndObjectiveSolutionPrinter(CpSolverSolutionCallback):
+            
class VarArrayAndObjectiveSolutionPrinter(CpSolverSolutionCallback):
     """Print intermediate solutions (objective, variable values, time)."""
 
     def __init__(self, variables):
@@ -9608,9 +10023,9 @@ and Value() methods.

VarArrayAndObjectiveSolutionPrinter(variables)
-
+
View Source -
    def __init__(self, variables):
+            
    def __init__(self, variables):
         CpSolverSolutionCallback.__init__(self)
         self.__variables = variables
         self.__solution_count = 0
@@ -9619,7 +10034,9 @@ and Value() methods.

- +

__init__(self: ortools.sat.python.swig_helper.SolutionCallback) -> None

+
+
@@ -9630,9 +10047,9 @@ and Value() methods.

on_solution_callback(self):
-
+
View Source -
    def on_solution_callback(self):
+            
    def on_solution_callback(self):
         """Called on each new solution."""
         current_time = time.time()
         obj = self.ObjectiveValue()
@@ -9659,9 +10076,9 @@ and Value() methods.

solution_count(self):
-
+
View Source -
    def solution_count(self):
+            
    def solution_count(self):
         """Returns the number of solutions found."""
         return self.__solution_count
 
@@ -9680,24 +10097,25 @@ and Value() methods.

OnSolutionCallback
BooleanValue
Value
+
Response
-
ortools.sat.pywrapsat.SolutionCallback
-
thisown
+
ortools.sat.python.swig_helper.SolutionCallback
+
BestObjectiveBound
+
DeterministicTime
+
HasResponse
+
NumBinaryPropagations
NumBooleans
NumBranches
NumConflicts
-
NumBinaryPropagations
NumIntegerPropagations
-
WallTime
-
UserTime
ObjectiveValue
-
BestObjectiveBound
-
SolutionIntegerValue
+
SerializedResponse
SolutionBooleanValue
+
SolutionIntegerValue
StopSearch
-
Response
-
HasResponse
+
UserTime
+
WallTime
@@ -9712,9 +10130,9 @@ and Value() methods.

VarArraySolutionPrinter(CpSolverSolutionCallback):
-
+
View Source -
class VarArraySolutionPrinter(CpSolverSolutionCallback):
+            
class VarArraySolutionPrinter(CpSolverSolutionCallback):
     """Print intermediate solutions (variable values, time)."""
 
     def __init__(self, variables):
@@ -9751,9 +10169,9 @@ and Value() methods.

VarArraySolutionPrinter(variables)
-
+
View Source -
    def __init__(self, variables):
+            
    def __init__(self, variables):
         CpSolverSolutionCallback.__init__(self)
         self.__variables = variables
         self.__solution_count = 0
@@ -9762,7 +10180,9 @@ and Value() methods.

- +

__init__(self: ortools.sat.python.swig_helper.SolutionCallback) -> None

+
+
@@ -9773,9 +10193,9 @@ and Value() methods.

on_solution_callback(self):
-
+
View Source -
    def on_solution_callback(self):
+            
    def on_solution_callback(self):
         """Called on each new solution."""
         current_time = time.time()
         print('Solution %i, time = %0.2f s' %
@@ -9801,9 +10221,9 @@ and Value() methods.

solution_count(self):
-
+
View Source -
    def solution_count(self):
+            
    def solution_count(self):
         """Returns the number of solutions found."""
         return self.__solution_count
 
@@ -9822,24 +10242,25 @@ and Value() methods.

OnSolutionCallback
BooleanValue
Value
+
Response
-
ortools.sat.pywrapsat.SolutionCallback
-
thisown
+
ortools.sat.python.swig_helper.SolutionCallback
+
BestObjectiveBound
+
DeterministicTime
+
HasResponse
+
NumBinaryPropagations
NumBooleans
NumBranches
NumConflicts
-
NumBinaryPropagations
NumIntegerPropagations
-
WallTime
-
UserTime
ObjectiveValue
-
BestObjectiveBound
-
SolutionIntegerValue
+
SerializedResponse
SolutionBooleanValue
+
SolutionIntegerValue
StopSearch
-
Response
-
HasResponse
+
UserTime
+
WallTime
diff --git a/docs/python/ortools/util/index.html b/docs/python/ortools/util/index.html index e294a52697..43518eda89 100644 --- a/docs/python/ortools/util/index.html +++ b/docs/python/ortools/util/index.html @@ -1,58 +1,7 @@ - + - - - Module List – pdoc 8.0.0 - - - - - - - - + - -
- - pdoc logo - -
-
-
- - \ No newline at end of file + diff --git a/docs/python/ortools/util/ortools/util/python/sorted_interval_list.html b/docs/python/ortools/util/ortools/util/python/sorted_interval_list.html new file mode 100644 index 0000000000..b9cf161a07 --- /dev/null +++ b/docs/python/ortools/util/ortools/util/python/sorted_interval_list.html @@ -0,0 +1,339 @@ + + + + + + + ortools.util.python.sorted_interval_list API documentation + + + + + + + + + +
+
+

+ortools.util.python.sorted_interval_list

+ + + +
+
+
+ #   + + + class + Domain(pybind11_builtins.pybind11_object): +
+ + + + +
+
#   + + + Domain() +
+ + +

__init__(self: ortools.util.python.sorted_interval_list.Domain, arg0: int, arg1: int) -> None

+
+ + +
+
+
#   + + + def + AllValues(unknown): +
+ + + + + +
+
+
#   + + + def + FromValues(unknown): +
+ + +

FromValues(values: List[int]) -> ortools.util.python.sorted_interval_list.Domain

+
+ + +
+
+
#   + + + def + FromIntervals(unknown): +
+ + +

FromIntervals(intervals: List[List[int]]) -> ortools.util.python.sorted_interval_list.Domain

+
+ + +
+
+
#   + + + def + FromFlatIntervals(unknown): +
+ + +

FromFlatIntervals(flat_intervals: List[int]) -> ortools.util.python.sorted_interval_list.Domain

+
+ + +
+ +
+
#   + + + def + Complement(unknown): +
+ + + + + +
+
+
#   + + + def + Contains(unknown): +
+ + +

Contains(self: ortools.util.python.sorted_interval_list.Domain, value: int) -> bool

+
+ + +
+
+
#   + + + def + FlattenedIntervals(unknown): +
+ + +

FlattenedIntervals(self: ortools.util.python.sorted_interval_list.Domain) -> List[int]

+
+ + +
+
+
#   + + + def + IntersectionWith(unknown): +
+ + + + + +
+
+
#   + + + def + IsEmpty(unknown): +
+ + + + + +
+
+
#   + + + def + Size(unknown): +
+ + + + + +
+
+
#   + + + def + Max(unknown): +
+ + + + + +
+
+
#   + + + def + Min(unknown): +
+ + + + + +
+
+
#   + + + def + Negation(unknown): +
+ + + + + +
+ +
+
+ + \ No newline at end of file