Skip to content

Commit

Permalink
Reorganized examples
Browse files Browse the repository at this point in the history
  • Loading branch information
yuce committed Oct 20, 2024
1 parent ea1f1df commit 532f44a
Show file tree
Hide file tree
Showing 21 changed files with 100 additions and 363 deletions.
19 changes: 8 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,10 @@ Thanks to all [contributors](CONTRIBUTORS.txt).

```python
from pyswip import Prolog
prolog = Prolog()
prolog.assertz("father(michael,john)")
prolog.assertz("father(michael,gina)")
list(prolog.query("father(michael,X)")) == [{'X': 'john'}, {'X': 'gina'}]
for soln in prolog.query("father(X,Y)"):
Prolog.assertz("father(michael,john)")
Prolog.assertz("father(michael,gina)")
list(Prolog.query("father(michael,X)")) == [{'X': 'john'}, {'X': 'gina'}]
for soln in Prolog.query("father(X,Y)"):
print(soln["X"], "is the father of", soln["Y"])
# michael is the father of john
# michael is the father of gina
Expand All @@ -52,8 +51,7 @@ Assuming the filename "knowledge_base.pl" and the Python is being run in the sam

```python
from pyswip import Prolog
prolog = Prolog()
prolog.consult("knowledge_base.pl")
Prolog.consult("knowledge_base.pl")
```

### Foreign Functions
Expand All @@ -67,10 +65,9 @@ hello.arity = 1

registerForeign(hello)

prolog = Prolog()
prolog.assertz("father(michael,john)")
prolog.assertz("father(michael,gina)")
print(list(prolog.query("father(michael,X), hello(X)")))
Prolog.assertz("father(michael,john)")
Prolog.assertz("father(michael,gina)")
print(list(Prolog.query("father(michael,X), hello(X)")))
```

### Pythonic interface (Experimental)
Expand Down
7 changes: 3 additions & 4 deletions examples/coins/coins.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,16 @@


def main():
prolog = Prolog()
prolog.consult("coins.pl", relative_to=__file__)
Prolog.consult("coins.pl", relative_to=__file__)
count = int(input("How many coins (default: 100)? ") or 100)
total = int(input("What should be the total (default: 500)? ") or 500)
for i, soln in enumerate(prolog.query("coins(S, %d, %d)." % (count, total))):
for i, soln in enumerate(Prolog.query("coins(S, %d, %d)." % (count, total))):
S = zip(soln["S"], [1, 5, 10, 50, 100])
print(i, end=" ")
for c, v in S:
print(f"{c}x{v}", end=" ")
print()
list(prolog.query(f"coins(S, {count}, {total})."))
list(Prolog.query(f"coins(S, {count}, {total})."))


if __name__ == "__main__":
Expand Down
3 changes: 1 addition & 2 deletions examples/coins/coins_new.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@


def main():
prolog = Prolog()
prolog.consult("coins.pl", relative_to=__file__)
Prolog.consult("coins.pl", relative_to=__file__)
count = int(input("How many coins (default: 100)? ") or 100)
total = int(input("What should be the total (default: 500)? ") or 500)
coins = Functor("coins", 3)
Expand Down
4 changes: 1 addition & 3 deletions examples/create_term.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@


def main():
prolog = Prolog()

a1 = PL_new_term_refs(2)
a2 = a1 + 1
t = PL_new_term_ref()
Expand All @@ -42,7 +40,7 @@ def main():
PL_cons_functor_v(ta, assertz, t)
PL_call(ta, None)

print(list(prolog.query("animal(X,Y)", catcherrors=True)))
print(list(Prolog.query("animal(X,Y)", catcherrors=True)))


if __name__ == "__main__":
Expand Down
5 changes: 2 additions & 3 deletions examples/draughts/puzzle1.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@


def main():
prolog = Prolog()
prolog.consult("puzzle1.pl", relative_to=__file__)
Prolog.consult("puzzle1.pl", relative_to=__file__)

for soln in prolog.query("solve(B)."):
for soln in Prolog.query("solve(B)."):
B = soln["B"]

# [NW,N,NE,W,E,SW,S,SE]
Expand Down
10 changes: 4 additions & 6 deletions examples/father.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,12 @@


def main():
p = Prolog()

father = Functor("father", 2)
mother = Functor("mother", 2)

p.assertz("father(john,mich)")
p.assertz("father(john,gina)")
p.assertz("mother(jane,mich)")
Prolog.assertz("father(john,mich)")
Prolog.assertz("father(john,gina)")
Prolog.assertz("mother(jane,mich)")

Y = Variable()
Z = Variable()
Expand All @@ -46,7 +44,7 @@ def main():
q.closeQuery() # Newer versions of SWI-Prolog do not allow nested queries

print("\nQuery with strings\n")
for s in p.query("father(john,Y),mother(Z,Y)"):
for s in Prolog.query("father(john,Y),mother(Z,Y)"):
print(s["Y"], s["Z"])


Expand Down
5 changes: 2 additions & 3 deletions examples/hanoi/hanoi.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,11 @@ def draw(self):

def main():
n = 3
prolog = Prolog()
tower = Tower(n, True)
notifier = Notifier(tower.move)
registerForeign(notifier.notify)
prolog.consult("hanoi.pl", relative_to=__file__)
list(prolog.query("hanoi(%d)" % n))
Prolog.consult("hanoi.pl", relative_to=__file__)
list(Prolog.query("hanoi(%d)" % n))


if __name__ == "__main__":
Expand Down
5 changes: 2 additions & 3 deletions examples/hanoi/hanoi_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ def notify(t):

notify.arity = 1

prolog = Prolog()
registerForeign(notify)
prolog.consult("hanoi.pl", relative_to=__file__)
list(prolog.query(f"hanoi({N})"))
Prolog.consult("hanoi.pl", relative_to=__file__)
list(Prolog.query(f"hanoi({N})"))


if __name__ == "__main__":
Expand Down
3 changes: 1 addition & 2 deletions examples/register_foreign.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,5 @@ def atom_checksum(*a):
return False


p = Prolog()
registerForeign(atom_checksum, arity=2)
print(list(p.query("X='Python', atom_checksum(X, Y)", catcherrors=False)))
print(list(Prolog.query("X='Python', atom_checksum(X, Y)", catcherrors=False)))
7 changes: 3 additions & 4 deletions examples/register_foreign_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@ def hello(t):

def main():
registerForeign(hello)
prolog = Prolog()
prolog.assertz("father(michael,john)")
prolog.assertz("father(michael,gina)")
list(prolog.query("father(michael,X), hello(X)"))
Prolog.assertz("father(michael,john)")
Prolog.assertz("father(michael,gina)")
list(Prolog.query("father(michael,X), hello(X)"))


if __name__ == "__main__":
Expand Down
5 changes: 2 additions & 3 deletions examples/sendmoremoney/money.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@
from pyswip import Prolog

letters = list("SENDMORY")
prolog = Prolog()
prolog.consult("money.pl", relative_to=__file__)
for result in prolog.query("sendmore(X)"):
Prolog.consult("money.pl", relative_to=__file__)
for result in Prolog.query("sendmore(X)"):
r = result["X"]
for i, letter in enumerate(letters):
print(letter, "=", r[i])
Expand Down
3 changes: 1 addition & 2 deletions examples/sendmoremoney/money_new.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@

def main():
letters = list("SENDMORY")
prolog = Prolog()
sendmore = Functor("sendmore")
prolog.consult("money.pl", relative_to=__file__)
Prolog.consult("money.pl", relative_to=__file__)

X = Variable()
call(sendmore(X))
Expand Down
5 changes: 2 additions & 3 deletions examples/sudoku/sudoku.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ def pretty_print(table):


def solve(problem):
prolog.consult("sudoku.pl", relative_to=__file__)
Prolog.consult("sudoku.pl", relative_to=__file__)
p = str(problem).replace("0", "_")
result = list(prolog.query("L=%s,sudoku(L)" % p, maxresult=1))
result = list(Prolog.query("L=%s,sudoku(L)" % p, maxresult=1))
if result:
result = result[0]
return result["L"]
Expand All @@ -83,5 +83,4 @@ def main():


if __name__ == "__main__":
prolog = Prolog()
main()
7 changes: 3 additions & 4 deletions examples/sudoku/sudoku_daily.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ def get_daily_sudoku(url):


def solve(problem):
prolog.consult("sudoku.pl", relative_to=__file__)
Prolog.consult("sudoku.pl", relative_to=__file__)
p = str(problem).replace("0", "_")
result = list(prolog.query("Puzzle=%s,sudoku(Puzzle)" % p, maxresult=1))
result = list(Prolog.query(f"Puzzle={p},sudoku(Puzzle)", maxresult=1))
if result:
result = result[0]
return result["Puzzle"]
Expand All @@ -83,9 +83,8 @@ def solve(problem):


if __name__ == "__main__":
URL = "http://www.sudoku.org.uk/daily.asp"
URL = "https://www.sudoku.org.uk/daily.asp"

prolog = Prolog() # having this in `solve` bites! because of __del__
print("Getting puzzle from:", URL)
puzzle = get_daily_sudoku(URL)
print("-- PUZZLE --")
Expand Down
17 changes: 12 additions & 5 deletions src/pyswip/examples/sudoku.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,21 @@
from pyswip.prolog import Prolog


__all__ = "Matrix", "solve"
__all__ = "Matrix", "solve", "prolog_source"

DIMENSION = 9
_DIMENSION = 9
_SOURCE_PATH = "sudoku.pl"


Prolog.consult("sudoku.pl", relative_to=__file__)
Prolog.consult(_SOURCE_PATH, relative_to=__file__)


class Matrix:

def __init__(self, matrix: List[List[int]]) -> None:
if not matrix:
raise ValueError("matrix must be given")
if len(matrix) != DIMENSION:
if len(matrix) != _DIMENSION:
raise ValueError("Matrix dimension must be 9")
self._dimension = len(matrix)
self._validate(self._dimension, matrix)
Expand Down Expand Up @@ -105,6 +106,13 @@ def solve(matrix: Matrix) -> Union[Matrix, Literal[False]]:
return Matrix(result)


def prolog_source() -> str:
from pathlib import Path
path = Path(__file__).parent / _SOURCE_PATH
with open(path) as f:
return f.read()


def main():
puzzle = Matrix.from_text("""
. 6 . 1 . 4 . 5 .
Expand All @@ -123,7 +131,6 @@ def main():
solution = solve(puzzle)
if solution:
solution.pretty_print()
print(repr(solution))
else:
print("This puzzle has no solutions. Is it valid?")

Expand Down
11 changes: 5 additions & 6 deletions src/pyswip/prolog.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,14 +218,13 @@ def query(cls, query, maxresult=-1, catcherrors=True, normalize=True):
If the query is a yes/no question, returns {} for yes, and nothing for no.
Otherwise returns a generator of dicts with variables as keys.
>>> prolog = Prolog()
>>> prolog.assertz("father(michael,john)")
>>> prolog.assertz("father(michael,gina)")
>>> bool(list(prolog.query("father(michael,john)")))
>>> Prolog.assertz("father(michael,john)")
>>> Prolog.assertz("father(michael,gina)")
>>> bool(list(Prolog.query("father(michael,john)")))
True
>>> bool(list(prolog.query("father(michael,olivia)")))
>>> bool(list(Prolog.query("father(michael,olivia)")))
False
>>> print sorted(prolog.query("father(michael,X)"))
>>> print sorted(Prolog.query("father(michael,X)"))
[{'X': 'gina'}, {'X': 'john'}]
"""
return cls._QueryWrapper()(query, maxresult, catcherrors, normalize)
Expand Down
6 changes: 5 additions & 1 deletion tests/examples/test_sudoku.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import unittest

from pyswip.examples.sudoku import Matrix, solve
from pyswip.examples.sudoku import Matrix, solve, prolog_source


class MatrixTestCase(unittest.TestCase):
Expand Down Expand Up @@ -53,3 +53,7 @@ def test_solve_failure(self):
puzzle = Matrix.from_text(fixture)
solution = solve(puzzle)
self.assertFalse(solution)

def test_prolog_source(self):
text = prolog_source()
self.assertIn("Prolog Sudoku Solver", text)
Loading

0 comments on commit 532f44a

Please sign in to comment.