ortools.sat.python.cp_model_helper

helpers methods for the cp_model module.

  1# Copyright 2010-2024 Google LLC
  2# Licensed under the Apache License, Version 2.0 (the "License");
  3# you may not use this file except in compliance with the License.
  4# You may obtain a copy of the License at
  5#
  6#     http://www.apache.org/licenses/LICENSE-2.0
  7#
  8# Unless required by applicable law or agreed to in writing, software
  9# distributed under the License is distributed on an "AS IS" BASIS,
 10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 11# See the License for the specific language governing permissions and
 12# limitations under the License.
 13
 14"""helpers methods for the cp_model module."""
 15
 16import numbers
 17from typing import Any, Union
 18import numpy as np
 19
 20
 21INT_MIN = -9223372036854775808  # hardcoded to be platform independent.
 22INT_MAX = 9223372036854775807
 23INT32_MIN = -2147483648
 24INT32_MAX = 2147483647
 25
 26
 27def is_boolean(x: Any) -> bool:
 28    """Checks if the x is a boolean."""
 29    if isinstance(x, bool):
 30        return True
 31    if isinstance(x, np.bool_):
 32        return True
 33    return False
 34
 35
 36def is_zero(x: Any) -> bool:
 37    """Checks if the x is 0 or 0.0."""
 38    if isinstance(x, numbers.Integral):
 39        return int(x) == 0
 40    if isinstance(x, numbers.Real):
 41        return float(x) == 0.0
 42    return False
 43
 44
 45def is_one(x: Any) -> bool:
 46    """Checks if x is 1 or 1.0."""
 47    if isinstance(x, numbers.Integral):
 48        return int(x) == 1
 49    if isinstance(x, numbers.Real):
 50        return float(x) == 1.0
 51    return False
 52
 53
 54def is_minus_one(x: Any) -> bool:
 55    """Checks if x is -1 or -1.0 ."""
 56    if isinstance(x, numbers.Integral):
 57        return int(x) == -1
 58    if isinstance(x, numbers.Real):
 59        return float(x) == -1.0
 60    return False
 61
 62
 63def assert_is_int64(x: Any) -> int:
 64    """Asserts that x is integer and x is in [min_int_64, max_int_64] and returns it casted to an int."""
 65    if not isinstance(x, numbers.Integral):
 66        raise TypeError(f"Not an integer: {x} of type {type(x)}")
 67    x_as_int = int(x)
 68    if x_as_int < INT_MIN or x_as_int > INT_MAX:
 69        raise OverflowError(f"Does not fit in an int64_t: {x}")
 70    return x_as_int
 71
 72
 73def assert_is_int32(x: Any) -> int:
 74    """Asserts that x is integer and x is in [min_int_32, max_int_32] and returns it casted to an int."""
 75    if not isinstance(x, numbers.Integral):
 76        raise TypeError(f"Not an integer: {x} of type {type(x)}")
 77    x_as_int = int(x)
 78    if x_as_int < INT32_MIN or x_as_int > INT32_MAX:
 79        raise OverflowError(f"Does not fit in an int32_t: {x}")
 80    return x_as_int
 81
 82
 83def assert_is_zero_or_one(x: Any) -> int:
 84    """Asserts that x is 0 or 1 and returns it as an int."""
 85    if not isinstance(x, numbers.Integral):
 86        raise TypeError(f"Not a boolean: {x} of type {type(x)}")
 87    x_as_int = int(x)
 88    if x_as_int < 0 or x_as_int > 1:
 89        raise TypeError(f"Not a boolean: {x}")
 90    return x_as_int
 91
 92
 93def assert_is_a_number(x: Any) -> Union[int, float]:
 94    """Asserts that x is a number and returns it casted to an int or a float."""
 95    if isinstance(x, numbers.Integral):
 96        return int(x)
 97    if isinstance(x, numbers.Real):
 98        return float(x)
 99    raise TypeError(f"Not a number: {x} of type {type(x)}")
100
101
102def to_capped_int64(v: int) -> int:
103    """Restrict v within [INT_MIN..INT_MAX] range."""
104    if v > INT_MAX:
105        return INT_MAX
106    if v < INT_MIN:
107        return INT_MIN
108    return v
109
110
111def capped_subtraction(x: int, y: int) -> int:
112    """Saturated arithmetics. Returns x - y truncated to the int64_t range."""
113    assert_is_int64(x)
114    assert_is_int64(y)
115    if y == 0:
116        return x
117    if x == y:
118        if x == INT_MAX or x == INT_MIN:
119            raise OverflowError("Integer NaN: subtracting INT_MAX or INT_MIN to itself")
120        return 0
121    if x == INT_MAX or x == INT_MIN:
122        return x
123    if y == INT_MAX:
124        return INT_MIN
125    if y == INT_MIN:
126        return INT_MAX
127    return to_capped_int64(x - y)
INT_MIN = -9223372036854775808
INT_MAX = 9223372036854775807
INT32_MIN = -2147483648
INT32_MAX = 2147483647
def is_boolean(x: Any) -> bool:
28def is_boolean(x: Any) -> bool:
29    """Checks if the x is a boolean."""
30    if isinstance(x, bool):
31        return True
32    if isinstance(x, np.bool_):
33        return True
34    return False

Checks if the x is a boolean.

def is_zero(x: Any) -> bool:
37def is_zero(x: Any) -> bool:
38    """Checks if the x is 0 or 0.0."""
39    if isinstance(x, numbers.Integral):
40        return int(x) == 0
41    if isinstance(x, numbers.Real):
42        return float(x) == 0.0
43    return False

Checks if the x is 0 or 0.0.

def is_one(x: Any) -> bool:
46def is_one(x: Any) -> bool:
47    """Checks if x is 1 or 1.0."""
48    if isinstance(x, numbers.Integral):
49        return int(x) == 1
50    if isinstance(x, numbers.Real):
51        return float(x) == 1.0
52    return False

Checks if x is 1 or 1.0.

def is_minus_one(x: Any) -> bool:
55def is_minus_one(x: Any) -> bool:
56    """Checks if x is -1 or -1.0 ."""
57    if isinstance(x, numbers.Integral):
58        return int(x) == -1
59    if isinstance(x, numbers.Real):
60        return float(x) == -1.0
61    return False

Checks if x is -1 or -1.0 .

def assert_is_int64(x: Any) -> int:
64def assert_is_int64(x: Any) -> int:
65    """Asserts that x is integer and x is in [min_int_64, max_int_64] and returns it casted to an int."""
66    if not isinstance(x, numbers.Integral):
67        raise TypeError(f"Not an integer: {x} of type {type(x)}")
68    x_as_int = int(x)
69    if x_as_int < INT_MIN or x_as_int > INT_MAX:
70        raise OverflowError(f"Does not fit in an int64_t: {x}")
71    return x_as_int

Asserts that x is integer and x is in [min_int_64, max_int_64] and returns it casted to an int.

def assert_is_int32(x: Any) -> int:
74def assert_is_int32(x: Any) -> int:
75    """Asserts that x is integer and x is in [min_int_32, max_int_32] and returns it casted to an int."""
76    if not isinstance(x, numbers.Integral):
77        raise TypeError(f"Not an integer: {x} of type {type(x)}")
78    x_as_int = int(x)
79    if x_as_int < INT32_MIN or x_as_int > INT32_MAX:
80        raise OverflowError(f"Does not fit in an int32_t: {x}")
81    return x_as_int

Asserts that x is integer and x is in [min_int_32, max_int_32] and returns it casted to an int.

def assert_is_zero_or_one(x: Any) -> int:
84def assert_is_zero_or_one(x: Any) -> int:
85    """Asserts that x is 0 or 1 and returns it as an int."""
86    if not isinstance(x, numbers.Integral):
87        raise TypeError(f"Not a boolean: {x} of type {type(x)}")
88    x_as_int = int(x)
89    if x_as_int < 0 or x_as_int > 1:
90        raise TypeError(f"Not a boolean: {x}")
91    return x_as_int

Asserts that x is 0 or 1 and returns it as an int.

def assert_is_a_number(x: Any) -> Union[int, float]:
 94def assert_is_a_number(x: Any) -> Union[int, float]:
 95    """Asserts that x is a number and returns it casted to an int or a float."""
 96    if isinstance(x, numbers.Integral):
 97        return int(x)
 98    if isinstance(x, numbers.Real):
 99        return float(x)
100    raise TypeError(f"Not a number: {x} of type {type(x)}")

Asserts that x is a number and returns it casted to an int or a float.

def to_capped_int64(v: int) -> int:
103def to_capped_int64(v: int) -> int:
104    """Restrict v within [INT_MIN..INT_MAX] range."""
105    if v > INT_MAX:
106        return INT_MAX
107    if v < INT_MIN:
108        return INT_MIN
109    return v

Restrict v within [INT_MIN..INT_MAX] range.

def capped_subtraction(x: int, y: int) -> int:
112def capped_subtraction(x: int, y: int) -> int:
113    """Saturated arithmetics. Returns x - y truncated to the int64_t range."""
114    assert_is_int64(x)
115    assert_is_int64(y)
116    if y == 0:
117        return x
118    if x == y:
119        if x == INT_MAX or x == INT_MIN:
120            raise OverflowError("Integer NaN: subtracting INT_MAX or INT_MIN to itself")
121        return 0
122    if x == INT_MAX or x == INT_MIN:
123        return x
124    if y == INT_MAX:
125        return INT_MIN
126    if y == INT_MIN:
127        return INT_MAX
128    return to_capped_int64(x - y)

Saturated arithmetics. Returns x - y truncated to the int64_t range.