Reputation: 11
I try to use the code of this website for some practice. https://developers.google.com/optimization/cp/queens
Now I want to add the constraints that make the position of queens NOT be ascending(or descending) order above some continuous columns.
For example, set board_size
= 5.
(1) satisfied solution
Q _ _ _ _
_ _ Q _ _
_ _ _ _ Q
_ Q _ _ _
_ _ _ Q _
There is no ascending(or descending) order above three continuous columns.
(2) descending order
Q _ _ _ _
_ _ _ Q _
_ Q _ _ _
_ _ _ _ Q
_ _ Q _ _
There is an descending order from column1 to column3. (queen1 > queen2 > queen 3)
I add the following code, but it's not work.
for i in range(2, board_size):
model.Add(queens[i - 2] <= queens[i - 1] <= queens[i])
How can I change the code to get the correct constraint make the position of queens NOT be ascending(or descending) order above some columns?
UPDATED: Here is my code for the problem.
class SolutionPrinter(cp_model.CpSolverSolutionCallback):
"""Print intermediate solutions."""
def __init__(self, variables):
cp_model.CpSolverSolutionCallback.__init__(self)
self.__variables = variables
self.__solution_count = 0
def OnSolutionCallback(self):
self.__solution_count += 1
for v in self.__variables:
print('%s = %i' % (v, self.Value(v)), end = ' ')
print()
def SolutionCount(self):
return self.__solution_count
board_size = 5
model = cp_model.CpModel()
# Creates the variables.
# The array index is the column, and the value is the row.
queens = [model.NewIntVar(0, board_size - 1, 'x%i' % i)
for i in range(board_size)]
# Creates the constraints.
# The following sets the constraint that all queens are in different rows.
model.AddAllDifferent(queens)
# Note: all queens must be in different columns because the indices of queens are all different.
# The following sets the constraint that no two queens can be on the same diagonal.
for i in range(board_size):
# Note: is not used in the inner loop.
diag1 = []
diag2 = []
for j in range(board_size):
# Create variable array for queens(j) + j.
q1 = model.NewIntVar(0, 2 * board_size, 'diag1_%i' % i)
diag1.append(q1)
model.Add(q1 == queens[j] + j)
# Create variable array for queens(j) - j.
q2 = model.NewIntVar(-board_size, board_size, 'diag2_%i' % i)
diag2.append(q2)
model.Add(q2 == queens[j] - j)
model.AddAllDifferent(diag1)
model.AddAllDifferent(diag2)
for i in range(2, board_size):
model.Add(queens[i - 2] <= queens[i - 1])
model.Add(queens[i - 1] <= queens[i])
### Solve model.
solver = cp_model.CpSolver()
solution_printer = SolutionPrinter(queens)
status = solver.SearchForAllSolutions(model, solution_printer)
print()
print('Solutions found : %i' % solution_printer.SolutionCount())
But it shows
Solutions found : 0
.
Upvotes: 1
Views: 278
Reputation: 9271
did you try to use channeling ?
Pseudo-code
# Declare our intermediate boolean variable.
b = [model.NewBoolVar('b') for i in range(board_size-2)]
# Implement b[i] == (queens[i] < queens[i+1]).
for i in range(board_size-2):
model.Add(queens[i] < queens[i+1]).OnlyEnforceIf(b[i])
model.Add(queens[i] > queens[i+1]).OnlyEnforceIf(b[i].Not())
# Create our two half-reified constraints.
# First, b[i] implies (queens[i+1] > queens[i+2]).
model.Add(queens[i+1] > queens[i+2]).OnlyEnforceIf(b[i])
# Second, not(b[i]) implies queens[i+1] < queens[i+2].
model.Add(queens[i+1] < queens[i+2]).OnlyEnforceIf(b[i].Not())
Upvotes: 0
Reputation: 11014
Add two inequalities.
model.Add(queens[i - 2] <= queens[i - 1])
model.Add(queens[i - 1] <= queens[i])
Upvotes: 1