1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
# copyright 2002-2021 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of logilab-constraint.
#
# logilab-constraint is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version.
#
# logilab-constraint is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with logilab-constraint. If not, see <http://www.gnu.org/licenses/>.
"""Chess constraints and domains"""
from logilab.constraint import fd
from logilab.constraint.propagation import AbstractConstraint, ConsistencyFailure
class ChessDomain(fd.FiniteDomain):
def __init__(self, size):
values = [(i, j) for i in range(size) for j in range(size)]
fd.FiniteDomain.__init__(self, values)
def __repr__(self):
vals = self.getValues()
vals.sort()
return f"<ChessDomain {str(vals)}>"
class QueensConstraint(AbstractConstraint):
def __init__(self, variables):
AbstractConstraint.__init__(self, variables)
def __repr__(self):
return f"<QueensConstraint {str(self._variables)}>"
def narrow(self, domains):
maybe_entailed = 1
var1 = self._variables[0]
dom1 = domains[var1]
values1 = dom1.getValues()
var2 = self._variables[1]
dom2 = domains[var2]
values2 = dom2.getValues()
keep1 = {}
keep2 = {}
maybe_entailed = 1
for val1 in values1:
val1_0 = val1[0]
val1_1 = val1[1]
for val2 in values2:
if val1 in keep1 and val2 in keep2 and maybe_entailed == 0:
continue
val2_0 = val2[0]
val2_1 = val2[1]
if (
val1_0 < val2_0
and val1_1 != val2_1
and abs(val1_0 - val2_0) != abs(val1_1 - val2_1)
):
keep1[val1] = 1
keep2[val2] = 1
else:
maybe_entailed = 0
try:
dom1.removeValues([val for val in values1 if val not in keep1])
dom2.removeValues([val for val in values2 if val not in keep2])
except ConsistencyFailure:
raise ConsistencyFailure(f"Inconsistency while applying {repr(self)}")
except Exception:
print(self)
raise
return maybe_entailed
|