Skip to content

Instantly share code, notes, and snippets.

@JossWhittle
Last active October 30, 2018 22:40
Show Gist options
  • Select an option

  • Save JossWhittle/165842cafe9c15c4ee63e6daa84ff0e1 to your computer and use it in GitHub Desktop.

Select an option

Save JossWhittle/165842cafe9c15c4ee63e6daa84ff0e1 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from ortools.sat.python import cp_model"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# Very lightweight wrapper to allow for a simple callback function to be used to collect results\n",
"class Collector(cp_model.CpSolverSolutionCallback):\n",
" def __init__(self, func):\n",
" cp_model.CpSolverSolutionCallback.__init__(self)\n",
" self.num_solutions = 0\n",
" self.func = func\n",
" \n",
" def OnSolutionCallback(self):\n",
" self.num_solutions += 1\n",
" self.func(self, self.num_solutions)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def solve_nqueens(board_size):\n",
" model = cp_model.CpModel()\n",
"\n",
" # Variable for the queen in column i representing it's row j in [0,boardsize)\n",
" queens = [model.NewIntVar(0, board_size-1, 'q%d' % (i)) for i in range(board_size)]\n",
"\n",
" # Implicit - Queens are in different columns because we are solving for the row of each column\n",
" \n",
" # Explicit - Queens are in different rows \n",
" model.AddAllDifferent(queens)\n",
" \n",
" # Explicit - Queens are in different diagonals\n",
" # q[i] = j therefore q[i] + i = j + i for the queen in column i\n",
" # If any two queens j_1 + i_1 == j_2 + i_2 then they lay on an up-right diagonal\n",
" # If any two queens j_1 - i_1 == j_2 - i_2 then they lay on a down-right diagonal\n",
" \n",
" asc = []\n",
" dsc = []\n",
" for i in range(board_size):\n",
" # Create variables to hold the results of our equations j + i and j - i for the current i\n",
" j_add_i = model.NewIntVar( 0, board_size*2, 'j_add_%d' % (i))\n",
" j_sub_i = model.NewIntVar(-board_size, board_size , 'j_sub_%d' % (i))\n",
" \n",
" # Constrain that these variables must be equal to the results of the equations\n",
" model.Add(j_add_i == queens[i] + i)\n",
" model.Add(j_sub_i == queens[i] - i)\n",
" \n",
" # Append the variables which equal the results of j + i and j - i respectively to seperate lists\n",
" asc += [j_add_i]\n",
" dsc += [j_sub_i]\n",
" \n",
" # Constraining that each list contains all different values ensures that no two share the same value\n",
" # This asserts that queens can never be on the same ascending or descending diagonals\n",
" model.AddAllDifferent(asc)\n",
" model.AddAllDifferent(dsc)\n",
" \n",
" # Callback function to pretty print the solution as a grid\n",
" def on_solution(solution, count):\n",
" print('Solution:', count)\n",
" for i in range(board_size):\n",
" j = int(solution.Value(queens[i]))\n",
" line = '|'.join(['Q' if (k == j) else ' ' for k in range(board_size)])\n",
" print(line + (('\\n' + '-'*len(line)) if (i != board_size-1) else ''))\n",
" print()\n",
" \n",
" # Run the solver\n",
" solver = cp_model.CpSolver()\n",
" status = solver.SearchForAllSolutions(model, Collector(on_solution))"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Solution: 1\n",
" | |Q| | | \n",
"-----------\n",
" | | | | |Q\n",
"-----------\n",
" |Q| | | | \n",
"-----------\n",
" | | | |Q| \n",
"-----------\n",
"Q| | | | | \n",
"-----------\n",
" | | |Q| | \n",
"\n",
"Solution: 2\n",
" | | |Q| | \n",
"-----------\n",
"Q| | | | | \n",
"-----------\n",
" | | | |Q| \n",
"-----------\n",
" |Q| | | | \n",
"-----------\n",
" | | | | |Q\n",
"-----------\n",
" | |Q| | | \n",
"\n",
"Solution: 3\n",
" |Q| | | | \n",
"-----------\n",
" | | |Q| | \n",
"-----------\n",
" | | | | |Q\n",
"-----------\n",
"Q| | | | | \n",
"-----------\n",
" | |Q| | | \n",
"-----------\n",
" | | | |Q| \n",
"\n",
"Solution: 4\n",
" | | | |Q| \n",
"-----------\n",
" | |Q| | | \n",
"-----------\n",
"Q| | | | | \n",
"-----------\n",
" | | | | |Q\n",
"-----------\n",
" | | |Q| | \n",
"-----------\n",
" |Q| | | | \n",
"\n"
]
}
],
"source": [
"solve_nqueens(6)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment