main
Matthew Butterick 6 years ago
parent d8e31ed03f
commit 91e0399ed6

@ -0,0 +1,60 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# PyCharm / Intellij
.idea/

@ -0,0 +1,21 @@
language: python
python:
- "2.7"
- "3.3"
- "3.4"
- "3.5"
- "3.6"
# command to install dependencies
install:
- "pip install -qq flake8"
- "pip install coveralls --quiet"
- "pip install ."
# command to run tests
script:
- nosetests -s -v --with-coverage --cover-package=constraint
- flake8 --ignore E501 constraint examples tests
after_success:
- coveralls

@ -0,0 +1,23 @@
Copyright (c) 2005-2014 - Gustavo Niemeyer <gustavo@niemeyer.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@ -0,0 +1,159 @@
|Build Status| |Code Health| |Code Coverage|
python-constraint
=================
Introduction
------------
The Python constraint module offers solvers for `Constraint Satisfaction Problems (CSPs) <https://en.wikipedia.org/wiki/Constraint_satisfaction_problem>`_ over finite domains in simple and pure Python. CSP is class of problems which may be represented in terms of variables (a, b, ...), domains (a in [1, 2, 3], ...), and constraints (a < b, ...).
Examples
--------
Basics
~~~~~~
This interactive Python session demonstrates the module basic operation:
.. code-block:: python
>>> from constraint import *
>>> problem = Problem()
>>> problem.addVariable("a", [1,2,3])
>>> problem.addVariable("b", [4,5,6])
>>> problem.getSolutions()
[{'a': 3, 'b': 6}, {'a': 3, 'b': 5}, {'a': 3, 'b': 4},
{'a': 2, 'b': 6}, {'a': 2, 'b': 5}, {'a': 2, 'b': 4},
{'a': 1, 'b': 6}, {'a': 1, 'b': 5}, {'a': 1, 'b': 4}]
>>> problem.addConstraint(lambda a, b: a*2 == b,
("a", "b"))
>>> problem.getSolutions()
[{'a': 3, 'b': 6}, {'a': 2, 'b': 4}]
>>> problem = Problem()
>>> problem.addVariables(["a", "b"], [1, 2, 3])
>>> problem.addConstraint(AllDifferentConstraint())
>>> problem.getSolutions()
[{'a': 3, 'b': 2}, {'a': 3, 'b': 1}, {'a': 2, 'b': 3},
{'a': 2, 'b': 1}, {'a': 1, 'b': 2}, {'a': 1, 'b': 3}]
Rooks problem
~~~~~~~~~~~~~
The following example solves the classical Eight Rooks problem:
.. code-block:: python
>>> problem = Problem()
>>> numpieces = 8
>>> cols = range(numpieces)
>>> rows = range(numpieces)
>>> problem.addVariables(cols, rows)
>>> for col1 in cols:
... for col2 in cols:
... if col1 < col2:
... problem.addConstraint(lambda row1, row2: row1 != row2,
... (col1, col2))
>>> solutions = problem.getSolutions()
>>> solutions
>>> solutions
[{0: 7, 1: 6, 2: 5, 3: 4, 4: 3, 5: 2, 6: 1, 7: 0},
{0: 7, 1: 6, 2: 5, 3: 4, 4: 3, 5: 2, 6: 0, 7: 1},
{0: 7, 1: 6, 2: 5, 3: 4, 4: 3, 5: 1, 6: 2, 7: 0},
{0: 7, 1: 6, 2: 5, 3: 4, 4: 3, 5: 1, 6: 0, 7: 2},
...
{0: 7, 1: 5, 2: 3, 3: 6, 4: 2, 5: 1, 6: 4, 7: 0},
{0: 7, 1: 5, 2: 3, 3: 6, 4: 1, 5: 2, 6: 0, 7: 4},
{0: 7, 1: 5, 2: 3, 3: 6, 4: 1, 5: 2, 6: 4, 7: 0},
{0: 7, 1: 5, 2: 3, 3: 6, 4: 1, 5: 4, 6: 2, 7: 0},
{0: 7, 1: 5, 2: 3, 3: 6, 4: 1, 5: 4, 6: 0, 7: 2},
...]
Magic squares
~~~~~~~~~~~~~
This example solves a 4x4 magic square:
.. code-block:: python
>>> problem = Problem()
>>> problem.addVariables(range(0, 16), range(1, 16 + 1))
>>> problem.addConstraint(AllDifferentConstraint(), range(0, 16))
>>> problem.addConstraint(ExactSumConstraint(34), [0, 5, 10, 15])
>>> problem.addConstraint(ExactSumConstraint(34), [3, 6, 9, 12])
>>> for row in range(4):
... problem.addConstraint(ExactSumConstraint(34),
[row * 4 + i for i in range(4)])
>>> for col in range(4):
... problem.addConstraint(ExactSumConstraint(34),
[col + 4 * i for i in range(4)])
>>> solutions = problem.getSolutions()
Features
--------
The following solvers are available:
- Backtracking solver
- Recursive backtracking solver
- Minimum conflicts solver
.. role:: python(code)
:language: python
Predefined constraint types currently available:
- :python:`FunctionConstraint`
- :python:`AllDifferentConstraint`
- :python:`AllEqualConstraint`
- :python:`ExactSumConstraint`
- :python:`MaxSumConstraint`
- :python:`MinSumConstraint`
- :python:`InSetConstraint`
- :python:`NotInSetConstraint`
- :python:`SomeInSetConstraint`
- :python:`SomeNotInSetConstraint`
API documentation
-----------------
Documentation for the module is available at: http://labix.org/doc/constraint/
Download and install
--------------------
.. code-block:: shell
$ pip install python-constraint
Roadmap
-------
This GitHub organization and repository is a global effort to help to
maintain python-constraint which was written by Gustavo Niemeyer
and originaly located at https://labix.org/python-constraint
- Create some unit tests - DONE
- Enable continuous integration - DONE
- Port to Python 3 (Python 2 being also supported) - DONE
- Respect Style Guide for Python Code (PEP8) - DONE
- Improve code coverage writting more unit tests - ToDo
- Move doc to Sphinx or MkDocs - https://readthedocs.org/ - ToDo
Contact
-------
- `Gustavo Niemeyer <https://github.com/niemeyer/>`_ <gustavo@niemeyer.net>
- `Sébastien Celles <https://github.com/scls19fr/>`_ <s.celles@gmail.com>
But it's probably better to `open an issue <https://github.com/python-constraint/python-constraint/issues>`_.
.. |Build Status| image:: https://travis-ci.org/python-constraint/python-constraint.svg?branch=master
:target: https://travis-ci.org/python-constraint/python-constraint
.. |Code Health| image:: https://landscape.io/github/python-constraint/python-constraint/master/landscape.svg?style=flat
:target: https://landscape.io/github/python-constraint/python-constraint/master
:alt: Code Health
.. |Code Coverage| image:: https://coveralls.io/repos/github/python-constraint/python-constraint/badge.svg
:target: https://coveralls.io/github/python-constraint/python-constraint

File diff suppressed because it is too large Load Diff

@ -0,0 +1,14 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
PY2 = sys.version_info[0] == 2
PY3 = (sys.version_info[0] >= 3)
if PY3:
string_types = str
xrange = range
else:
string_types = basestring # noqa
xrange = xrange

@ -0,0 +1,8 @@
__author__ = "Gustavo Niemeyer"
__copyright__ = "Copyright (c) 2005-2014 - Gustavo Niemeyer <gustavo@niemeyer.net>"
__credits__ = ["Sebastien Celles"]
__license__ = ""
__version__ = "1.3.1"
__email__ = "gustavo@niemeyer.net"
__status__ = "Development"
__url__ = 'https://github.com/python-constraint/python-constraint'

@ -0,0 +1,37 @@
#!/usr/bin/python
#
# What's the minimum value for:
#
# ABC
# -------
# A+B+C
#
# From http://www.umassd.edu/mathcontest/abc.cfm
#
from constraint import Problem
def solve():
problem = Problem()
problem.addVariables("abc", range(1, 10))
problem.getSolutions()
minvalue = 999 / (9 * 3)
minsolution = {}
for solution in problem.getSolutions():
a = solution["a"]
b = solution["b"]
c = solution["c"]
value = (a * 100 + b * 10 + c) / (a + b + c)
if value < minvalue:
minsolution = solution
return minvalue, minsolution
def main():
minvalue, minsolution = solve()
print(minvalue)
print(minsolution)
if __name__ == "__main__":
main()

@ -0,0 +1,36 @@
#!/usr/bin/python
#
# 100 coins must sum to $5.00
#
# That's kind of a country-specific problem, since depending on the
# country there are different values for coins. Here is presented
# the solution for a given set.
#
from constraint import Problem, ExactSumConstraint
import sys
def solve():
problem = Problem()
total = 5.00
variables = ("0.01", "0.05", "0.10", "0.50", "1.00")
values = [float(x) for x in variables]
for variable, value in zip(variables, values):
problem.addVariable(variable, range(int(total / value)))
problem.addConstraint(ExactSumConstraint(total, values), variables)
problem.addConstraint(ExactSumConstraint(100))
solutions = problem.getSolutionIter()
return solutions, variables
def main():
solutions, variables = solve()
for i, solution in enumerate(solutions):
sys.stdout.write("%03d -> " % (i + 1))
for variable in variables:
sys.stdout.write("%s:%d " % (variable, solution[variable]))
sys.stdout.write("\n")
if __name__ == "__main__":
main()

@ -0,0 +1,154 @@
#!/usr/bin/python
from constraint import Problem, AllDifferentConstraint
import random
import sys
MINLEN = 3
def main(puzzle, lines):
puzzle = puzzle.rstrip().splitlines()
while puzzle and not puzzle[0]:
del puzzle[0]
# Extract horizontal words
horizontal = []
word = []
predefined = {}
for row in range(len(puzzle)):
for col in range(len(puzzle[row])):
char = puzzle[row][col]
if not char.isspace():
word.append((row, col))
if char != "#":
predefined[row, col] = char
elif word:
if len(word) > MINLEN:
horizontal.append(word[:])
del word[:]
if word:
if len(word) > MINLEN:
horizontal.append(word[:])
del word[:]
# Extract vertical words
vertical = []
validcol = True
col = 0
while validcol:
validcol = False
for row in range(len(puzzle)):
if col >= len(puzzle[row]):
if word:
if len(word) > MINLEN:
vertical.append(word[:])
del word[:]
else:
validcol = True
char = puzzle[row][col]
if not char.isspace():
word.append((row, col))
if char != "#":
predefined[row, col] = char
elif word:
if len(word) > MINLEN:
vertical.append(word[:])
del word[:]
if word:
if len(word) > MINLEN:
vertical.append(word[:])
del word[:]
col += 1
# hnames = ["h%d" % i for i in range(len(horizontal))]
# vnames = ["v%d" % i for i in range(len(vertical))]
# problem = Problem(MinConflictsSolver())
problem = Problem()
for hi, hword in enumerate(horizontal):
for vi, vword in enumerate(vertical):
for hchar in hword:
if hchar in vword:
hci = hword.index(hchar)
vci = vword.index(hchar)
problem.addConstraint(lambda hw, vw, hci=hci, vci=vci:
hw[hci] == vw[vci],
("h%d" % hi, "v%d" % vi))
for char, letter in predefined.items():
for hi, hword in enumerate(horizontal):
if char in hword:
hci = hword.index(char)
problem.addConstraint(lambda hw, hci=hci, letter=letter:
hw[hci] == letter, ("h%d" % hi,))
for vi, vword in enumerate(vertical):
if char in vword:
vci = vword.index(char)
problem.addConstraint(lambda vw, vci=vci, letter=letter:
vw[vci] == letter, ("v%d" % vi,))
wordsbylen = {}
for hword in horizontal:
wordsbylen[len(hword)] = []
for vword in vertical:
wordsbylen[len(vword)] = []
for line in lines:
line = line.strip()
ll = len(line)
if ll in wordsbylen:
wordsbylen[ll].append(line.upper())
for hi, hword in enumerate(horizontal):
words = wordsbylen[len(hword)]
random.shuffle(words)
problem.addVariable("h%d" % hi, words)
for vi, vword in enumerate(vertical):
words = wordsbylen[len(vword)]
random.shuffle(words)
problem.addVariable("v%d" % vi, words)
problem.addConstraint(AllDifferentConstraint())
solution = problem.getSolution()
if not solution:
print("No solution found!")
maxcol = 0
maxrow = 0
for hword in horizontal:
for row, col in hword:
if row > maxrow:
maxrow = row
if col > maxcol:
maxcol = col
for vword in vertical:
for row, col in vword:
if row > maxrow:
maxrow = row
if col > maxcol:
maxcol = col
matrix = []
for row in range(maxrow + 1):
matrix.append([" "] * (maxcol + 1))
for variable in solution:
if variable[0] == "v":
word = vertical[int(variable[1:])]
else:
word = horizontal[int(variable[1:])]
for (row, col), char in zip(word, solution[variable]):
matrix[row][col] = char
for row in range(maxrow + 1):
for col in range(maxcol + 1):
sys.stdout.write(matrix[row][col])
sys.stdout.write("\n")
if __name__ == "__main__":
if len(sys.argv) != 3:
sys.exit("Usage: crosswords.py <maskfile> <wordsfile>")
main(open(sys.argv[1]).read(), open(sys.argv[2]))

@ -0,0 +1,27 @@
# ######## #
# # # # #
######## # #
# # # # #
# # ########
# # # # # #
######## # #
# # # # # #
# # #
######## # #
# # # # #
# ########
# # # # #
# # ########
# # # # # #
# # ########
# # # #
######## # #
# # # # # #
# # # # # #
######## # #
# # # #
# ########
# # # #
######## # #

@ -0,0 +1,19 @@
#
#########
# # #
# # ######
# # #
# # # #
# # # #
######## #
# # #
# # #
#########
# # #
#########
# # #
# #
#######
#

@ -0,0 +1,8 @@
P
Y
####T####
# H #
# O #
####N #
# #
#########

@ -0,0 +1,8 @@
#
#
#########
# #
# # # #
##### # #
# # #
#########

@ -0,0 +1,209 @@
#!/usr/bin/python
#
# ALBERT EINSTEIN'S RIDDLE
#
# ARE YOU IN THE TOP 2% OF INTELLIGENT PEOPLE IN THE WORLD?
# SOLVE THE RIDDLE AND FIND OUT.
#
# There are no tricks, just pure logic, so good luck and don't give up.
#
# 1. In a street there are five houses, painted five different colours.
# 2. In each house lives a person of different nationality
# 3. These five homeowners each drink a different kind of beverage, smoke
# different brand of cigar and keep a different pet.
#
# THE QUESTION: WHO OWNS THE FISH?
#
# HINTS
#
# 1. The Brit lives in a red house.
# 2. The Swede keeps dogs as pets.
# 3. The Dane drinks tea.
# 4. The Green house is on the left of the White house.
# 5. The owner of the Green house drinks coffee.
# 6. The person who smokes Pall Mall rears birds.
# 7. The owner of the Yellow house smokes Dunhill.
# 8. The man living in the centre house drinks milk.
# 9. The Norwegian lives in the first house.
# 10. The man who smokes Blends lives next to the one who keeps cats.
# 11. The man who keeps horses lives next to the man who smokes Dunhill.
# 12. The man who smokes Blue Master drinks beer.
# 13. The German smokes Prince.
# 14. The Norwegian lives next to the blue house.
# 15. The man who smokes Blends has a neighbour who drinks water.
#
# ALBERT EINSTEIN WROTE THIS RIDDLE EARLY DURING THE 19th CENTURY. HE
# SAID THAT 98% OF THE WORLD POPULATION WOULD NOT BE ABLE TO SOLVE IT.
from constraint import Problem, AllDifferentConstraint
# Check http://www.csc.fi/oppaat/f95/python/talot.py
def solve():
problem = Problem()
for i in range(1, 6):
problem.addVariable("color%d" % i,
["red", "white", "green", "yellow", "blue"])
problem.addVariable("nationality%d" % i,
["brit", "swede", "dane", "norwegian", "german"])
problem.addVariable("drink%d" % i,
["tea", "coffee", "milk", "beer", "water"])
problem.addVariable("smoke%d" % i,
["pallmall", "dunhill", "blends",
"bluemaster", "prince"])
problem.addVariable("pet%d" % i,
["dogs", "birds", "cats", "horses", "fish"])
problem.addConstraint(AllDifferentConstraint(),
["color%d" % i for i in range(1, 6)])
problem.addConstraint(AllDifferentConstraint(),
["nationality%d" % i for i in range(1, 6)])
problem.addConstraint(AllDifferentConstraint(),
["drink%d" % i for i in range(1, 6)])
problem.addConstraint(AllDifferentConstraint(),
["smoke%d" % i for i in range(1, 6)])
problem.addConstraint(AllDifferentConstraint(),
["pet%d" % i for i in range(1, 6)])
for i in range(1, 6):
# Hint 1
problem.addConstraint(lambda nationality, color:
nationality != "brit" or color == "red",
("nationality%d" % i, "color%d" % i))
# Hint 2
problem.addConstraint(lambda nationality, pet:
nationality != "swede" or pet == "dogs",
("nationality%d" % i, "pet%d" % i))
# Hint 3
problem.addConstraint(lambda nationality, drink:
nationality != "dane" or drink == "tea",
("nationality%d" % i, "drink%d" % i))
# Hint 4
if i < 5:
problem.addConstraint(lambda colora, colorb:
colora != "green" or colorb == "white",
("color%d" % i, "color%d" % (i + 1)))
else:
problem.addConstraint(lambda color: color != "green",
("color%d" % i,))
# Hint 5
problem.addConstraint(lambda color, drink:
color != "green" or drink == "coffee",
("color%d" % i, "drink%d" % i))
# Hint 6
problem.addConstraint(lambda smoke, pet:
smoke != "pallmall" or pet == "birds",
("smoke%d" % i, "pet%d" % i))
# Hint 7
problem.addConstraint(lambda color, smoke:
color != "yellow" or smoke == "dunhill",
("color%d" % i, "smoke%d" % i))
# Hint 8
if i == 3:
problem.addConstraint(lambda drink: drink == "milk",
("drink%d" % i,))
# Hint 9
if i == 1:
problem.addConstraint(lambda nationality:
nationality == "norwegian",
("nationality%d" % i,))
# Hint 10
if 1 < i < 5:
problem.addConstraint(lambda smoke, peta, petb:
smoke != "blends" or peta == "cats" or
petb == "cats",
("smoke%d" % i, "pet%d" % (i - 1),
"pet%d" % (i + 1)))
else:
problem.addConstraint(lambda smoke, pet:
smoke != "blends" or pet == "cats",
("smoke%d" % i,
"pet%d" % (i == 1 and 2 or 4)))
# Hint 11
if 1 < i < 5:
problem.addConstraint(lambda pet, smokea, smokeb:
pet != "horses" or smokea == "dunhill" or
smokeb == "dunhill",
("pet%d" % i, "smoke%d" % (i - 1),
"smoke%d" % (i + 1)))
else:
problem.addConstraint(lambda pet, smoke:
pet != "horses" or smoke == "dunhill",
("pet%d" % i,
"smoke%d" % (i == 1 and 2 or 4)))
# Hint 12
problem.addConstraint(lambda smoke, drink:
smoke != "bluemaster" or drink == "beer",
("smoke%d" % i, "drink%d" % i))
# Hint 13
problem.addConstraint(lambda nationality, smoke:
nationality != "german" or smoke == "prince",
("nationality%d" % i, "smoke%d" % i))
# Hint 14
if 1 < i < 5:
problem.addConstraint(lambda nationality, colora, colorb:
nationality != "norwegian" or
colora == "blue" or colorb == "blue",
("nationality%d" % i, "color%d" % (i - 1),
"color%d" % (i + 1)))
else:
problem.addConstraint(lambda nationality, color:
nationality != "norwegian" or
color == "blue",
("nationality%d" % i,
"color%d" % (i == 1 and 2 or 4)))
# Hint 15
if 1 < i < 5:
problem.addConstraint(lambda smoke, drinka, drinkb:
smoke != "blends" or
drinka == "water" or drinkb == "water",
("smoke%d" % i, "drink%d" % (i - 1),
"drink%d" % (i + 1)))
else:
problem.addConstraint(lambda smoke, drink:
smoke != "blends" or drink == "water",
("smoke%d" % i,
"drink%d" % (i == 1 and 2 or 4)))
solutions = problem.getSolutions()
return solutions
def showSolution(solution):
for i in range(1, 6):
print("House %d" % i)
print("--------")
print("Nationality: %s" % solution["nationality%d" % i])
print("Color: %s" % solution["color%d" % i])
print("Drink: %s" % solution["drink%d" % i])
print("Smoke: %s" % solution["smoke%d" % i])
print("Pet: %s" % solution["pet%d" % i])
print("")
def main():
solutions = solve()
print("Found %d solution(s)!" % len(solutions))
print("")
for solution in solutions:
showSolution(solution)
if __name__ == "__main__":
main()

@ -0,0 +1,54 @@
#!/usr/bin/python
#
# http://mathworld.wolfram.com/QueensProblem.html
#
from constraint import Problem
import sys
def solve():
problem = Problem()
size = 8
cols = range(size)
rows = range(size)
problem.addVariables(cols, rows)
for col1 in cols:
for col2 in cols:
if col1 < col2:
problem.addConstraint(lambda row1, row2, col1=col1, col2=col2:
abs(row1 - row2) != abs(col1 - col2) and
row1 != row2, (col1, col2))
solutions = problem.getSolutions()
return solutions, size
def showSolution(solution, size):
sys.stdout.write(" %s \n" % ("-" * ((size * 4) - 1)))
for i in range(size):
sys.stdout.write(" |")
for j in range(size):
if solution[j] == i:
sys.stdout.write(" %d |" % j)
else:
sys.stdout.write(" |")
sys.stdout.write("\n")
if i != size - 1:
sys.stdout.write(" |%s|\n" % ("-" * ((size * 4) - 1)))
sys.stdout.write(" %s \n" % ("-" * ((size * 4) - 1)))
def main(show=False):
solutions, size = solve()
print("Found %d solution(s)!" % len(solutions))
if show:
for solution in solutions:
showSolution(solution, size)
if __name__ == "__main__":
show = False
if len(sys.argv) == 2 and sys.argv[1] == "-s":
show = True
elif len(sys.argv) != 1:
sys.exit("Usage: queens.py [-s]")
main(show)

@ -0,0 +1,57 @@
#!/usr/bin/python
#
# http://mathworld.wolfram.com/RooksProblem.html
#
from constraint import Problem
import sys
def factorial(x):
return x == 1 or factorial(x - 1) * x
def solve(size):
problem = Problem()
cols = range(size)
rows = range(size)
problem.addVariables(cols, rows)
for col1 in cols:
for col2 in cols:
if col1 < col2:
problem.addConstraint(lambda row1, row2: row1 != row2,
(col1, col2))
solutions = problem.getSolutions()
return solutions
def main(show=False):
size = 8
solutions = solve(size)
print("Found %d solution(s)!" % len(solutions))
if show:
for solution in solutions:
showSolution(solution, size)
def showSolution(solution, size):
sys.stdout.write(" %s \n" % ("-" * ((size * 4) - 1)))
for i in range(size):
sys.stdout.write(" |")
for j in range(size):
if solution[j] == i:
sys.stdout.write(" %d |" % j)
else:
sys.stdout.write(" |")
sys.stdout.write("\n")
if i != size - 1:
sys.stdout.write(" |%s|\n" % ("-" * ((size * 4) - 1)))
sys.stdout.write(" %s \n" % ("-" * ((size * 4) - 1)))
if __name__ == "__main__":
show = False
if len(sys.argv) == 2 and sys.argv[1] == "-s":
show = True
elif len(sys.argv) != 1:
sys.exit("Usage: rooks.py [-s]")
main(show)

@ -0,0 +1,48 @@
#!/usr/bin/python
#
# http://home.chello.no/~dudley/
#
from constraint import Problem, AllDifferentConstraint, SomeInSetConstraint
import sys
STUDENTDESKS = [[0, 1, 0, 0, 0, 0],
[0, 2, 3, 4, 5, 6],
[0, 7, 8, 9, 10, 0],
[0, 11, 12, 13, 14, 0],
[15, 16, 17, 18, 19, 0],
[0, 0, 0, 0, 20, 0]]
def solve():
problem = Problem()
problem.addVariables(range(1, 21), ["A", "B", "C", "D", "E"])
problem.addConstraint(SomeInSetConstraint(["A"], 4, True))
problem.addConstraint(SomeInSetConstraint(["B"], 4, True))
problem.addConstraint(SomeInSetConstraint(["C"], 4, True))
problem.addConstraint(SomeInSetConstraint(["D"], 4, True))
problem.addConstraint(SomeInSetConstraint(["E"], 4, True))
for row in range(len(STUDENTDESKS) - 1):
for col in range(len(STUDENTDESKS[row]) - 1):
lst = [STUDENTDESKS[row][col], STUDENTDESKS[row][col + 1],
STUDENTDESKS[row + 1][col], STUDENTDESKS[row + 1][col + 1]]
lst = [x for x in lst if x]
problem.addConstraint(AllDifferentConstraint(), lst)
solutions = problem.getSolution()
return solutions
def main():
solutions = solve()
showSolution(solutions)
def showSolution(solution):
for row in range(len(STUDENTDESKS)):
for col in range(len(STUDENTDESKS[row])):
id = STUDENTDESKS[row][col]
sys.stdout.write(" %s" % (id and solution[id] or " "))
sys.stdout.write("\n")
if __name__ == "__main__":
main()

@ -0,0 +1,71 @@
#
# Sudoku puzzle solver by by Luigi Poderico (www.poderico.it).
#
import sys
from constraint import Problem, AllDifferentConstraint
def solve():
problem = Problem()
# Define the variables: 9 rows of 9 variables rangin in 1...9
for i in range(1, 10):
problem.addVariables(range(i * 10 + 1, i * 10 + 10), range(1, 10))
# Each row has different values
for i in range(1, 10):
problem.addConstraint(AllDifferentConstraint(), range(i * 10 + 1, i * 10 + 10))
# Each colum has different values
for i in range(1, 10):
problem.addConstraint(AllDifferentConstraint(), range(10 + i, 100 + i, 10))
# Each 3x3 box has different values
problem.addConstraint(AllDifferentConstraint(), [11, 12, 13, 21, 22, 23, 31, 32, 33])
problem.addConstraint(AllDifferentConstraint(), [41, 42, 43, 51, 52, 53, 61, 62, 63])
problem.addConstraint(AllDifferentConstraint(), [71, 72, 73, 81, 82, 83, 91, 92, 93])
problem.addConstraint(AllDifferentConstraint(), [14, 15, 16, 24, 25, 26, 34, 35, 36])
problem.addConstraint(AllDifferentConstraint(), [44, 45, 46, 54, 55, 56, 64, 65, 66])
problem.addConstraint(AllDifferentConstraint(), [74, 75, 76, 84, 85, 86, 94, 95, 96])
problem.addConstraint(AllDifferentConstraint(), [17, 18, 19, 27, 28, 29, 37, 38, 39])
problem.addConstraint(AllDifferentConstraint(), [47, 48, 49, 57, 58, 59, 67, 68, 69])
problem.addConstraint(AllDifferentConstraint(), [77, 78, 79, 87, 88, 89, 97, 98, 99])
# Some value is given.
initValue = [[0, 9, 0, 7, 0, 0, 8, 6, 0],
[0, 3, 1, 0, 0, 5, 0, 2, 0],
[8, 0, 6, 0, 0, 0, 0, 0, 0],
[0, 0, 7, 0, 5, 0, 0, 0, 6],
[0, 0, 0, 3, 0, 7, 0, 0, 0],
[5, 0, 0, 0, 1, 0, 7, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 9],
[0, 2, 0, 6, 0, 0, 0, 5, 0],
[0, 5, 4, 0, 0, 8, 0, 7, 0]]
for i in range(1, 10):
for j in range(1, 10):
if initValue[i - 1][j - 1] != 0:
problem.addConstraint(lambda var, val=initValue[i - 1][j - 1]:
var == val, (i * 10 + j,))
# Get the solutions.
solutions = problem.getSolutions()
return solutions
def main():
solutions = solve()
# Print the solutions
for solution in solutions:
for i in range(1, 10):
for j in range(1, 10):
index = i * 10 + j
sys.stdout.write("%s " % solution[index])
print("")
print("")
if __name__ == "__main__":
main()

@ -0,0 +1,39 @@
#!/usr/bin/python
#
# Assign equal values to equal letters, and different values to
# different letters, in a way that satisfies the following sum:
#
# SEIS
# + SEIS
# ------
# DOZE
#
from constraint import Problem, AllDifferentConstraint
def solve():
problem = Problem()
problem.addVariables("seidoz", range(10))
problem.addConstraint(lambda s, e: (2 * s) % 10 == e, "se")
problem.addConstraint(lambda i, s, z, e: ((10 * 2 * i) + (2 * s)) % 100 ==
z * 10 + e, "isze")
problem.addConstraint(lambda s, e, i, d, o, z:
2 * (s * 1000 + e * 100 + i * 10 + s) ==
d * 1000 + o * 100 + z * 10 + e, "seidoz")
problem.addConstraint(lambda s: s != 0, "s")
problem.addConstraint(lambda d: d != 0, "d")
problem.addConstraint(AllDifferentConstraint())
solutions = problem.getSolutions()
return solutions
def main():
solutions = solve()
print("SEIS+SEIS=DOZE")
for s in solutions:
print("%(s)d%(e)d%(i)d%(s)s+%(s)d%(e)d%(i)d%(s)d="
"%(d)d%(o)d%(z)d%(e)d") % s
if __name__ == "__main__":
main()

@ -0,0 +1,42 @@
#!/usr/bin/python
#
# Assign equal values to equal letters, and different values to
# different letters, in a way that satisfies the following sum:
#
# SEND
# + MORE
# ------
# MONEY
#
from constraint import Problem, NotInSetConstraint, AllDifferentConstraint
def solve():
problem = Problem()
problem.addVariables("sendmory", range(10))
problem.addConstraint(lambda d, e, y: (d + e) % 10 == y, "dey")
problem.addConstraint(lambda n, d, r, e, y: (n * 10 + d + r * 10 + e) % 100 ==
e * 10 + y, "ndrey")
problem.addConstraint(lambda e, n, d, o, r, y:
(e * 100 + n * 10 + d + o * 100 + r * 10 + e) % 1000 ==
n * 100 + e * 10 + y, "endory")
problem.addConstraint(lambda s, e, n, d, m, o, r, y:
1000 * s + 100 * e + 10 * n + d + 1000 * m + 100 * o + 10 * r + e ==
10000 * m + 1000 * o + 100 * n + 10 * e + y, "sendmory")
problem.addConstraint(NotInSetConstraint([0]), "sm")
problem.addConstraint(AllDifferentConstraint())
solutions = problem.getSolutions()
return solutions
def main():
solutions = solve()
print("SEND+MORE=MONEY")
for s in solutions:
print("%(s)d%(e)d%(n)d%(d)d+"
"%(m)d%(o)d%(r)d%(e)d="
"%(m)d%(o)d%(n)d%(e)d%(y)d" % s)
if __name__ == "__main__":
main()

@ -0,0 +1,37 @@
#!/usr/bin/python
#
# Assign equal values to equal letters, and different values to
# different letters, in a way that satisfies the following sum:
#
# TWO
# + TWO
# -----
# FOUR
#
from constraint import Problem, AllDifferentConstraint, NotInSetConstraint
def solve():
problem = Problem()
problem.addVariables("twofur", range(10))
problem.addConstraint(lambda o, r: (2 * o) % 10 == r, "or")
problem.addConstraint(lambda w, o, u,
r: ((10 * 2 * w) + (2 * o)) % 100 == u * 10 + r, "wour")
problem.addConstraint(lambda t, w, o, f, u, r:
2 * (t * 100 + w * 10 + o) ==
f * 1000 + o * 100 + u * 10 + r, "twofur")
problem.addConstraint(NotInSetConstraint([0]), "ft")
problem.addConstraint(AllDifferentConstraint())
solutions = problem.getSolutions()
return solutions
def main():
solutions = solve()
print("TWO+TWO=FOUR")
for s in solutions:
print("%(t)d%(w)d%(o)d+%(t)d%(w)d%(o)d=%(f)d%(o)d%(u)d%(r)d" % s)
if __name__ == "__main__":
main()

@ -0,0 +1,48 @@
#!/usr/bin/python
#
# Reorganize the following numbers in a way that each line of
# 5 numbers sum to 27.
#
# 1 6
# 2 7
# 3
# 8 4
# 9 5
#
from constraint import Problem, AllDifferentConstraint
def solve():
problem = Problem()
problem.addVariables("abcdxefgh", range(1, 10))
problem.addConstraint(lambda a, b, c, d, x:
a < b < c < d and a + b + c + d + x == 27, "abcdx")
problem.addConstraint(lambda e, f, g, h, x:
e < f < g < h and e + f + g + h + x == 27, "efghx")
problem.addConstraint(AllDifferentConstraint())
solutions = problem.getSolutions()
return solutions
def main():
solutions = solve()
print("Found %d solutions!" % len(solutions))
showSolutions(solutions)
def showSolutions(solutions):
for solution in solutions:
print(""" %d %d
%d %d
%d
%d %d
%d %d
""" % (solution["a"], solution["e"],
solution["b"], solution["f"],
solution["x"],
solution["g"], solution["c"],
solution["h"], solution["d"]))
if __name__ == "__main__":
main()

@ -0,0 +1,9 @@
[bdist_wheel]
universal = 1
[bdist_rpm]
doc_files = README.rst
use_bzip2 = 1
[sdist]
formats = bztar

@ -0,0 +1,123 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from setuptools import setup, find_packages # Always prefer setuptools over distutils
from codecs import open # To use a consistent encoding
from os import path
import io
NAME = 'python-constraint'
filename = "%s/version.py" % 'constraint'
with open(filename) as f:
exec(f.read())
here = path.abspath(path.dirname(__file__))
def readme():
filename = path.join(here, 'README.rst')
with io.open(filename, 'rt', encoding='UTF-8') as f:
return f.read()
setup(
name=NAME,
# Versions should comply with PEP440. For a discussion on single-sourcing
# the version across setup.py and the project code, see
# https://packaging.python.org/en/latest/development.html#single-sourcing-the-version
#version='0.0.1',
version=__version__,
description="python-constraint is a module implementing support "\
"for handling CSPs (Constraint Solving Problems) over finite domain",
long_description=readme(),
# The project's main homepage.
url=__url__,
# Author details
author=__author__,
author_email=__email__,
# Choose your license
license=__license__,
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
# How mature is this project? Common values are
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
'Development Status :: 3 - Alpha',
# Indicate who your project is intended for
'Environment :: Console',
#'Topic :: Software Development :: Build Tools',
'Intended Audience :: Science/Research',
'Operating System :: OS Independent',
# Specify the Python versions you support here. In particular, ensure
# that you indicate whether you support Python 2, Python 3 or both.
'Programming Language :: Cython',
'Programming Language :: Python',
#'Programming Language :: Python :: 2',
#'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
#'Programming Language :: Python :: 3',
#'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Scientific/Engineering',
# Pick your license as you wish (should match "license" above)
'License :: OSI Approved :: BSD License',
],
# What does your project relate to?
keywords='csp constraint solving problems problem solver',
# You can just specify the packages manually here if your project is
# simple. Or you can use find_packages().
packages=find_packages(exclude=['contrib', 'docs', 'tests*']),
# List run-time dependencies here. These will be installed by pip when your
# project is installed. For an analysis of "install_requires" vs pip's
# requirements files see:
# https://packaging.python.org/en/latest/technical.html#install-requires-vs-requirements-files
install_requires=[],
# List additional groups of dependencies here (e.g. development dependencies).
# You can install these using the following syntax, for example:
# $ pip install -e .[dev,test]
extras_require = {
'dev': ['check-manifest', 'nose'],
'test': ['coverage', 'nose'],
},
# If there are data files included in your packages that need to be
# installed, specify them here. If using Python 2.6 or less, then these
# have to be included in MANIFEST.in as well.
#package_data={
# 'sample': ['logging.conf'],
#},
# Although 'package_data' is the preferred approach, in some case you may
# need to place data files outside of your packages.
# see http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files
# In this case, 'data_file' will be installed into '<sys.prefix>/my_data'
#data_files=[('my_data', ['data/data_file'])],
# To provide executable scripts, use entry points in preference to the
# "scripts" keyword. Entry points provide cross-platform support and allow
# pip to create the appropriate form of executable for the target platform.
#entry_points={
# 'console_scripts': [
# 'sample=sample:main',
# ],
#},
)

@ -0,0 +1,91 @@
import constraint
from examples.abc import abc
from examples.coins import coins
# from examples.crosswords import crosswords
from examples.einstein import einstein
from examples.queens import queens
from examples.rooks import rooks
from examples.studentdesks import studentdesks
# from examples.sudoku import sudoku
# from examples.wordmath import (seisseisdoze, sendmoremoney, twotwofour)
# from examples.xsum import xsum
import constraint.compat as compat
def test_abc():
solutions = abc.solve()
minvalue, minsolution = solutions
assert minvalue == 37
assert minsolution == {'a': 1, 'c': 2, 'b': 1}
def test_coins():
solutions = coins.solve()
assert len(solutions) == 2
def test_einstein():
solutions = einstein.solve()
expected_solutions = [
{
'nationality2': 'dane',
'nationality3': 'brit',
'nationality1': 'norwegian',
'nationality4': 'german',
'nationality5': 'swede',
'color1': 'yellow',
'color3': 'red',
'color2': 'blue',
'color5': 'white',
'color4': 'green',
'drink4': 'coffee',
'drink5': 'beer',
'drink1': 'water',
'drink2': 'tea',
'drink3': 'milk',
'smoke5': 'bluemaster',
'smoke4': 'prince',
'smoke3': 'pallmall',
'smoke2': 'blends',
'smoke1': 'dunhill',
'pet5': 'dogs',
'pet4': 'fish',
'pet1': 'cats',
'pet3': 'birds',
'pet2': 'horses'
}
]
assert solutions == expected_solutions
def test_queens():
solutions, size = queens.solve()
assert size == 8
for solution in solutions:
queens.showSolution(solution, size)
def test_rooks():
size = 8
solutions = rooks.solve(size)
assert len(solutions) == rooks.factorial(size)
def test_studentdesks():
solutions = studentdesks.solve()
expected_solutions = {1: 'A', 2: 'E', 3: 'D', 4: 'E', 5: 'D', 6: 'A', 7: 'C', 8: 'B', 9: 'C', 10: 'B', 11: 'E', 12: 'D', 13: 'E', 14: 'D', 15: 'A', 16: 'C', 17: 'B', 18: 'C', 19: 'B', 20: 'A'}
assert solutions == expected_solutions
def test_constraint_without_variables():
problem = constraint.Problem()
problem.addVariable("a", [1, 2, 3])
problem.addConstraint(lambda a: a * 2 == 6)
solutions = problem.getSolutions()
assert solutions == [{'a': 3}]
def test_version():
assert isinstance(constraint.__version__, compat.string_types)

@ -0,0 +1,17 @@
from constraint import Problem, MinConflictsSolver
def test_min_conflicts_solver():
problem = Problem(MinConflictsSolver())
problem.addVariable("x", [0, 1])
problem.addVariable("y", [0, 1])
solution = problem.getSolution()
possible_solutions = [
{'x': 0, 'y': 0},
{'x': 0, 'y': 1},
{'x': 1, 'y': 0},
{'x': 1, 'y': 1}
]
assert solution in possible_solutions

@ -0,0 +1,102 @@
from constraint import Domain, Variable, SomeNotInSetConstraint
def test_empty_constraint():
constrainer = SomeNotInSetConstraint(set())
v1, v2 = variables = [Variable('v1'), Variable('v2')]
assignments = {v1: 'a', v2: 'b'}
assert constrainer(variables, {}, assignments)
def test_no_overlap():
constrainer = SomeNotInSetConstraint(set('zy'))
v1, v2 = variables = [Variable('v1'), Variable('v2')]
assignments = {v1: 'a', v2: 'b'}
assert constrainer(variables, {}, assignments)
def test_some_overlap():
constrainer = SomeNotInSetConstraint(set('b'))
v1, v2 = variables = [Variable('v1'), Variable('v2')]
assignments = {v1: 'a', v2: 'b'}
assert constrainer(variables, {}, assignments)
def test_too_much_overlap():
constrainer = SomeNotInSetConstraint(set('ab'))
v1, v2 = variables = [Variable('v1'), Variable('v2')]
assignments = {v1: 'a', v2: 'b'}
assert not constrainer(variables, {}, assignments)
def test_exact():
constrainer = SomeNotInSetConstraint(set('abc'), n=2, exact=True)
v1, v2, v3 = variables = [Variable('v1'), Variable('v2'), Variable('v3')]
assignments = {v1: 'a', v2: 'y', v3: 'z'}
assert constrainer(variables, {}, assignments)
assignments = {v1: 'a', v2: 'y'}
assert constrainer(variables, {}, assignments)
assignments = {v1: 'a', v2: 'b', v3: 'z'}
assert not constrainer(variables, {}, assignments)
assignments = {v1: 'a', v2: 'b'}
assert not constrainer(variables, {}, assignments)
assignments = {v1: 'a', v2: 'b', v3: 'c'}
assert not constrainer(variables, {}, assignments)
assignments = {v1: 'x', v2: 'y', v3: 'z'}
assert not constrainer(variables, {}, assignments)
def test_forwardcheck():
constrainer = SomeNotInSetConstraint(set('abc'), n=2)
v1, v2, v3 = variables = [Variable('v1'), Variable('v2'), Variable('v3')]
domains = {v1: Domain(['a']), v2: Domain(['b', 'y']),
v3: Domain(['c', 'z'])}
assert constrainer(variables, domains, {v1: 'a'})
assert ['a'] == list(domains[v1])
assert ['b', 'y'] == list(domains[v2])
assert ['c', 'z'] == list(domains[v3])
assert constrainer(variables, domains, {v1: 'a'}, True)
assert ['a'] == list(domains[v1])
assert ['y'] == list(domains[v2])
assert ['z'] == list(domains[v3])
def test_forwardcheck_empty_domain():
constrainer = SomeNotInSetConstraint(set('abc'))
v1, v2 = variables = [Variable('v1'), Variable('v2')]
domains = {v1: Domain(['a']), v2: Domain(['b'])}
assert constrainer(variables, domains, {v1: 'a'})
assert not constrainer(variables, domains, {v1: 'a'}, True)
def test_forwardcheck_exact():
constrainer = SomeNotInSetConstraint(set('abc'), n=2, exact=True)
v1, v2, v3 = variables = [Variable('v1'), Variable('v2'), Variable('v3')]
assignments = {v1: 'a'}
domains = {v1: Domain(['a', 'x']), v2: Domain(['b', 'y']),
v3: Domain(['c', 'z'])}
assert constrainer(variables, domains, assignments)
assert constrainer(variables, domains, assignments, True)
assert 'b' not in domains[v2]
assert 'y' in domains[v2]
assert 'c' not in domains[v3]
assert 'z' in domains[v3]
domains = {v1: Domain(['a', 'x']), v2: Domain(['b', 'y']),
v3: Domain(['c'])}
assert constrainer(variables, domains, assignments)
assert not constrainer(variables, domains, assignments, True)
Loading…
Cancel
Save