text: # Copyright 2010-2018 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.
  """Unit tests for python/constraint_solver.swig. Not exhaustive."""
  
  
  import sys
  import unittest
  from ortools.constraint_solver import pywrapcp
  
  
  class SearchMonitorTest(pywrapcp.SearchMonitor):
      def __init__(self, solver, nexts):
          pywrapcp.SearchMonitor.__init__(self, solver)
          self._nexts = nexts
  
      def BeginInitialPropagation(self):
          print(self._nexts)
  
      def EndInitialPropagation(self):
          print(self._nexts)
  
  
  class DemonTest(pywrapcp.PyDemon):
      def __init__(self, x):
          pywrapcp.PyDemon.__init__(self)
          self._x = x
          print('Demon built')
  
      def Run(self, solver):
          print('in Run(), saw ' + str(self._x))
  
  
  class ConstraintTest(pywrapcp.PyConstraint):
      def __init__(self, solver, x):
          pywrapcp.Constraint.__init__(self, solver)
          self._x = x
          print('Constraint built')
  
      def Post(self):
          print('in Post()')
          self._demon = DemonTest(self._x)
          self._x.WhenBound(self._demon)
          print('out of Post()')
  
      def InitialPropagate(self):
          print('in InitialPropagate()')
          self._x.SetMin(5)
          print(self._x)
          print('out of InitialPropagate()')
  
  
  class InitialPropagateDemon(pywrapcp.PyDemon):
      def __init__(self, ct):
          pywrapcp.Demon.__init__(self)
          self._ct = ct
  
      def Run(self, solver):
          self._ct.InitialPropagate()
  
  
  class DumbGreaterOrEqualToFive(pywrapcp.PyConstraint):
      def __init__(self, solver, x):
          pywrapcp.Constraint.__init__(self, solver)
          self._x = x
  
      def Post(self):
          self._demon = InitialPropagateDemon(self)
          self._x.WhenBound(self._demon)
  
      def InitialPropagate(self):
          if self._x.Bound():
              if self._x.Value() < 5:
                  print('Reject %d' % self._x.Value())
                  self.solver().Fail()
              else:
                  print('Accept %d' % self._x.Value())
  
  
  class WatchDomain(pywrapcp.PyDemon):
      def __init__(self, x):
          pywrapcp.Demon.__init__(self)
          self._x = x
  
      def Run(self, solver):
          for i in self._x.HoleIterator():
              print('Removed %d' % i)
  
  
  class HoleConstraintTest(pywrapcp.PyConstraint):
      def __init__(self, solver, x):
          pywrapcp.Constraint.__init__(self, solver)
          self._x = x
  
      def Post(self):
          self._demon = WatchDomain(self._x)
          self._x.WhenDomain(self._demon)
  
      def InitialPropagate(self):
          self._x.RemoveValue(5)
  
  
  class BinarySum(pywrapcp.PyConstraint):
      def __init__(self, solver, x, y, z):
          pywrapcp.Constraint.__init__(self, solver)
          self._x = x
          self._y = y
          self._z = z
  
      def Post(self):
          self._demon = InitialPropagateDemon(self)
          self._x.WhenRange(self._demon)
          self._y.WhenRange(self._demon)
          self._z.WhenRange(self._demon)
  
      def InitialPropagate(self):
          self._z.SetRange(self._x.Min() + self._y.Min(),
                           self._x.Max() + self._y.Max())
          self._x.SetRange(self._z.Min() - self._y.Max(),
                           self._z.Max() - self._y.Min())
          self._y.SetRange(self._z.Min() - self._x.Max(),
                           self._z.Max() - self._x.Min())
  
  
  class PyWrapCp(unittest.TestCase):
      def test_member(self):
          print('test_member')
          solver = pywrapcp.Solver('test member')
          x = solver.IntVar(1, 10, 'x')
          ct = x.Member([1, 2, 3, 5])
          print(ct)
  
      def test_sparse_var(self):
          print('test_sparse_var')
          solver = pywrapcp.Solver('test_sparse_var')
          x = solver.IntVar([1, 3, 5], 'x')
          print(x)
  
      def test_modulo(self):
          print('test_modulo')
          solver = pywrapcp.Solver('test_modulo')
          x = solver.IntVar(0, 10, 'x')
          y = solver.IntVar(2, 4, 'y')
          print(x % 3)
          print(x % y)
  
      def test_limit(self):
          solver = pywrapcp.Solver('test_limit')
          # TODO(user): expose the proto-based MakeLimit() API in or-tools and test it
          # here.
          time = 10000  # ms
          branches = 10
          failures = sys.maxsize
          solutions = sys.maxsize
          smart_time_check = True
          cumulative = False
          limit = solver.Limit(time, branches, failures, solutions,
                               smart_time_check, cumulative)
          print(limit)
  
      def test_search_monitor(self):
          print('test_search_monitor')
          solver = pywrapcp.Solver('test search_monitor')
          x = solver.IntVar(1, 10, 'x')
          ct = (x == 3)
          solver.Add(ct)
          db = solver.Phase([x], solver.CHOOSE_FIRST_UNBOUND,
                            solver.ASSIGN_MIN_VALUE)
          monitor = SearchMonitorTest(solver, x)
          solver.Solve(db, monitor)
  
      def test_demon(self):
          print('test_demon')
          solver = pywrapcp.Solver('test_demon')
          x = solver.IntVar(1, 10, 'x')
          demon = DemonTest(x)
          demon.Run(solver)
  
      def test_constraint(self):
          print('test_constraint')
          solver = pywrapcp.Solver('test_constraint')
          x = solver.IntVar(1, 10, 'x')
          myct = ConstraintTest(solver, x)
          solver.Add(myct)
          db = solver.Phase([x], solver.CHOOSE_FIRST_UNBOUND,
                            solver.ASSIGN_MIN_VALUE)
          solver.Solve(db)
  
      def test_failing_constraint(self):
          print('test_failing_constraint')
          solver = pywrapcp.Solver('test failing constraint')
          x = solver.IntVar(1, 10, 'x')
          myct = DumbGreaterOrEqualToFive(solver, x)
          solver.Add(myct)
          db = solver.Phase([x], solver.CHOOSE_FIRST_UNBOUND,
                            solver.ASSIGN_MIN_VALUE)
          solver.Solve(db)
  
      def test_domain_iterator(self):
          print('test_domain_iterator')
          solver = pywrapcp.Solver('test_domain_iterator')
          x = solver.IntVar([1, 2, 4, 6], 'x')
          for i in x.DomainIterator():
              print(i)
  
      def test_hole_iterator(self):
          print('test_hole_iterator')
          solver = pywrapcp.Solver('test_hole_iterator')
          x = solver.IntVar(1, 10, 'x')
          myct = HoleConstraintTest(solver, x)
          solver.Add(myct)
          db = solver.Phase([x], solver.CHOOSE_FIRST_UNBOUND,
                            solver.ASSIGN_MIN_VALUE)
          solver.Solve(db)
  
  
      def test_sum_constraint(self):
          print('test_sum_constraint')
          solver = pywrapcp.Solver('test_sum_constraint')
          x = solver.IntVar(1, 5, 'x')
          y = solver.IntVar(1, 5, 'y')
          z = solver.IntVar(1, 5, 'z')
          binary_sum = BinarySum(solver, x, y, z)
          solver.Add(binary_sum)
          db = solver.Phase([x, y, z], solver.CHOOSE_FIRST_UNBOUND,
                            solver.ASSIGN_MIN_VALUE)
          solver.NewSearch(db)
          while solver.NextSolution():
              print('%d + %d == %d' % (x.Value(), y.Value(), z.Value()))
          solver.EndSearch()
  
  
  
  if __name__ == '__main__':
      unittest.main()
  