port of PYSWIP package.
This commit is contained in:
parent
0645040602
commit
e94104306c
46
packages/pyswip/CHANGELOG
Normal file
46
packages/pyswip/CHANGELOG
Normal file
@ -0,0 +1,46 @@
|
||||
PySWIP CHANGELOG
|
||||
================
|
||||
|
||||
+ 0.2.2
|
||||
* PySWIP won't rely on the (id of the) functor handle of ``=/2``.
|
||||
* Sebastian Höhn's patch to enable PySWIP to work on MAC OS-X is incorporated.
|
||||
|
||||
+ 0.2.1
|
||||
|
||||
* Importing ``pyswip`` automatically initializes SWI-Prolog.
|
||||
* Fixed a bug with querying lists with the new interface.
|
||||
|
||||
+ 0.2.0
|
||||
|
||||
* All names are included with ``from pyswip import ...``
|
||||
* New *Pythonic* interface
|
||||
* Prolog.query returns real Python datatypes
|
||||
* Markus Triska's Sudoku Solver
|
||||
* Prolog module support
|
||||
* Foreign functions retrieve Python datatypes.
|
||||
|
||||
+ 0.1.3
|
||||
|
||||
* Renamed ``pyswip/util.py`` to ``pyswip/prolog.py``.
|
||||
* New module ``pyswip.easy``.
|
||||
* Now it is possible to register a Python function as a Prolog predicate through SWI-Prolog's Foreign Function Interface.
|
||||
* Additions to the core library.
|
||||
* Added example, *register foreign* which shows how to register a Python function as an SWI-Prolog predicate.
|
||||
* Added example, *Towers of Hanoi*
|
||||
|
||||
+ 0.1.2
|
||||
|
||||
* Renamed ``PrologRunner`` to ``Prolog``.
|
||||
* Removed ``query`` method of ``Prolog``, ``queryGenerator`` is renamed as ``query``.
|
||||
* Added ``asserta``, ``assertz`` and ``consult`` methods to ``Prolog``.
|
||||
* The necessary cleanup is done even if the ``query`` generator doesn't run to the end.
|
||||
* Errors during the execution of ``query`` is caught and ``PrologError`` is raised.
|
||||
* Many new additions to the core library.
|
||||
* Added ``examples`` directory.
|
||||
* Added examples, *coins* and *draughts*.
|
||||
|
||||
+ 0.1.1
|
||||
|
||||
* Added ``queryGenerator`` to PrologRunner, ``query`` calls ``queryGenerator``.
|
||||
* Added example ``send more money``.
|
||||
|
340
packages/pyswip/COPYING
Normal file
340
packages/pyswip/COPYING
Normal file
@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
73
packages/pyswip/INSTALL
Normal file
73
packages/pyswip/INSTALL
Normal file
@ -0,0 +1,73 @@
|
||||
PySWIP INSTALL
|
||||
==============
|
||||
|
||||
PySWIP requires SWI-Prolog as a shared library since it uses ctypes to access SWI-Prolog/C functions. The shared library is present in Win32 installer, but missing by default from the builds made directly from the source.
|
||||
|
||||
Installing on Linux
|
||||
-------------------
|
||||
|
||||
These instructions are tested on a Linux system, but should also work for POSIX systems. Also, you may want to install development packages for readline and libgmp (not required for basics).
|
||||
|
||||
You need to do the following to install a shared library enabled version of SWI-Prolog. We use version 5.6.34 of SWI-Prolog but any other recent version should work fine. Please make the necessary modifications for your environment.
|
||||
|
||||
1) Get the source from: http://www.swi-prolog.org/download.html::
|
||||
|
||||
$ wget http://gollem.science.uva.nl/cgi-bin/nph-download/SWI-Prolog/pl-5.6.34.tar.gz
|
||||
|
||||
2) Extract the archive and cd into it::
|
||||
|
||||
$ tar xzvf pl-5.6.34.tar.gz
|
||||
$ cd pl-5.6.34
|
||||
|
||||
3) Configure the source with shared library enabled::
|
||||
|
||||
$ ./configure --prefix=/usr --enable-shared
|
||||
|
||||
4) Compile the source::
|
||||
|
||||
$ make
|
||||
|
||||
5) Install the source::
|
||||
|
||||
$ sudo make install
|
||||
|
||||
6) clp library is useful for constraint handling problems, so let's install that too::
|
||||
|
||||
$ cd cd packages/clpqr
|
||||
$ ./configure --prefix=/usr --enable-shared
|
||||
$ make && make install
|
||||
|
||||
|
||||
7) Create a soft link to ``libpol.so``::
|
||||
|
||||
$ sudo ln -s /usr/lib/pl-5.6.34/lib/i686-linux/libpl.so.5.6.34 /usr/lib/libpl.so
|
||||
|
||||
8) Next, get and install ctypes from: http://starship.python.net/crew/theller/ctypes . Note that you don't need to install it if you are using Python 2.5.
|
||||
|
||||
9) Unpack PySwIP package and install it with, ``python setup.py install``.
|
||||
|
||||
10) After you install it, you can test it with the following at your Python shell::
|
||||
|
||||
>>> from pyswip import Prolog
|
||||
>>> prolog = Prolog()
|
||||
>>> prolog.assertz("father(michael,john)")
|
||||
|
||||
If you get an error, such as "libpl (shared) not found." or "FATAL ERROR: Resource not found" be sure you have installed SWI-Prolog as a share library. Check your default library directory (usually ``/usr/lib``) for ``libpl.so``.
|
||||
|
||||
|
||||
Installing on Win32
|
||||
-------------------
|
||||
|
||||
1) Get a recent version of SWI-Prolog for Win32 from: http://www.swi-prolog.org/dl-stable.html and install it.
|
||||
|
||||
2) You need to add SWI-Prolog's bin directory ``C:\Program Files\pl\bin`` to *path*, here are two tutorials for that: http://www.computerhope.com/issues/ch000549.htm and http://vlaurie.com/computers2/Articles/environment.htm
|
||||
|
||||
3) Get a Windows installer version of PySWIP and install it.
|
||||
|
||||
4) After you install it, you can test it with the following at your Python console::
|
||||
|
||||
>>> from pyswip import Prolog
|
||||
>>> prolog = Prolog()
|
||||
>>> prolog.assertz("father(michael,john)")
|
||||
|
||||
|
45
packages/pyswip/Makefile.in
Normal file
45
packages/pyswip/Makefile.in
Normal file
@ -0,0 +1,45 @@
|
||||
#
|
||||
# default base directory for YAP installation
|
||||
#
|
||||
#
|
||||
ROOTDIR = @prefix@
|
||||
#
|
||||
# where the binary should be
|
||||
#
|
||||
BINDIR = $(ROOTDIR)/bin
|
||||
#
|
||||
# where YAP should look for binary libraries
|
||||
#
|
||||
LIBDIR=@libdir@
|
||||
YAPLIBDIR=@libdir@/Yap
|
||||
#
|
||||
# where YAP should look for architecture-independent Prolog libraries
|
||||
#
|
||||
SHAREDIR=$(ROOTDIR)/share
|
||||
#
|
||||
#
|
||||
# You shouldn't need to change what follows.
|
||||
#
|
||||
INSTALL=@INSTALL@
|
||||
INSTALL_DATA=@INSTALL_DATA@
|
||||
INSTALL_PROGRAM=@INSTALL_PROGRAM@
|
||||
srcdir=@srcdir@
|
||||
YAP_EXTRAS=@YAP_EXTRAS@
|
||||
|
||||
install:
|
||||
(cd $(srcdir); python setup.py install)
|
||||
|
||||
clean:
|
||||
|
||||
test:
|
||||
(cd $(srcdir)/examples; python create_term.py)
|
||||
(cd $(srcdir)/examples; python knowledgebase.py)
|
||||
(cd $(srcdir)/examples; python knowledgebase.py)
|
||||
(cd $(srcdir)/examples; python register_foreign.py)
|
||||
(cd $(srcdir)/examples; python register_foreign_simple.py)
|
||||
(cd $(srcdir)/examples/coins; python coins.py)
|
||||
(cd $(srcdir)/examples/draughts; python puzzle1.py)
|
||||
(cd $(srcdir)/examples/hanoi; python hanoi.py)
|
||||
(cd $(srcdir)/examples/sendmoremoney; python money.py)
|
||||
(cd $(srcdir)/examples/sudoku; python sudoku.py)
|
||||
(cd $(srcdir)/examples/sudoku; python sudoku_daily.py)
|
98
packages/pyswip/README
Normal file
98
packages/pyswip/README
Normal file
@ -0,0 +1,98 @@
|
||||
PySWIP README
|
||||
============
|
||||
|
||||
:Version:
|
||||
0.2.2
|
||||
|
||||
:Author:
|
||||
Yuce Tekol. <http://www.geocities.com/yucetekol>
|
||||
|
||||
:Project Website:
|
||||
http://code.google.com/p/pyswip
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
PySWIP is a GPL'd Python - SWI-Prolog bridge enabling to query SWI-Prolog in your Python programs. It features an (incomplete) SWI-Prolog foreign language interface, a utility class that makes it easy querying with Prolog and also a Pythonic interface.
|
||||
|
||||
Since PySWIP uses SWI-Prolog as a shared library and ctypes to access it, it doesn't require compilation to be installed.
|
||||
|
||||
Note that this version of PySWIP is slightly incompatible with 0.1.x versions.
|
||||
|
||||
Requirements:
|
||||
-------------
|
||||
|
||||
* Python 2.3 and higher.
|
||||
* ctypes 1.0 and higher.
|
||||
* SWI-Prolog 5.6.x and higher (most probably other versions will also work).
|
||||
* libpl as a shared library.
|
||||
* Works on Linux and Win32, should work for all POSIX.
|
||||
|
||||
Example (Using Prolog):
|
||||
-----------------------
|
||||
|
||||
>>> 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)"):
|
||||
... print soln["X"], "is the father of", soln["Y"]
|
||||
...
|
||||
michael is the father of john
|
||||
michael is the father of gina
|
||||
|
||||
Since version 0.1.3 of PySWIP, it is possible to register a Python function as a Prolog predicate through SWI-Prolog's foreign language interface.
|
||||
|
||||
Example (Foreign Functions):
|
||||
----------------------------
|
||||
|
||||
from pyswip import Prolog, registerForeign
|
||||
|
||||
def hello(t):
|
||||
print "Hello,", t
|
||||
hello.arity = 1
|
||||
|
||||
registerForeign(hello)
|
||||
|
||||
prolog = Prolog()
|
||||
prolog.assertz("father(michael,john)")
|
||||
prolog.assertz("father(michael,gina)")
|
||||
list(prolog.query("father(michael,X), hello(X)"))
|
||||
|
||||
Outputs:
|
||||
Hello, john
|
||||
Hello, gina
|
||||
|
||||
Since version 0.2, PySWIP contains a 'Pythonic' interface which allows writing predicates in pure Python (*Note that interface is experimental.*)
|
||||
|
||||
Example (Pythonic interface):
|
||||
-----------------------------
|
||||
|
||||
from pyswip import Functor, Variable, Query
|
||||
|
||||
assertz = Functor("assertz", 2)
|
||||
father = Functor("father", 2)
|
||||
|
||||
call(assertz(father("michael","john")))
|
||||
call(assertz(father("michael","gina")))
|
||||
|
||||
X = Variable()
|
||||
q = Query(father("michael",X))
|
||||
while q.nextSolution():
|
||||
print "Hello,", X.value
|
||||
q.closeQuery()
|
||||
|
||||
Outputs:
|
||||
Hello, john
|
||||
Hello, gina
|
||||
|
||||
The core functionality of ``Prolog.query`` is based on Nathan Denny's public domain prolog.py found at http://www.ahsc.arizona.edu/~schcats/projects/docs/prolog-0.2.0.html
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Please see ``INSTALL`` for detailed instructions.
|
||||
|
16
packages/pyswip/README.YAP
Normal file
16
packages/pyswip/README.YAP
Normal file
@ -0,0 +1,16 @@
|
||||
This is an experimental port of Yuce Tekol's pyswip package. It
|
||||
supports for 64 bit code, and should work in SWI-Prolog.
|
||||
|
||||
- YAP must be compiled as a dynamic library
|
||||
- libYap.so must be in the ld path: either use --prefix=/usr or
|
||||
LD_LIBRARY_PATH
|
||||
|
||||
Only tested in Linux right now. Use
|
||||
|
||||
make install
|
||||
make tests
|
||||
|
||||
from packages/pyswip
|
||||
|
||||
to see how it goes.
|
||||
|
14
packages/pyswip/examples/README
Normal file
14
packages/pyswip/examples/README
Normal file
@ -0,0 +1,14 @@
|
||||
PySWIP Examples
|
||||
===============
|
||||
|
||||
This directory contains examples for PySWIP.
|
||||
|
||||
The ones marked with (clp) requires clp library of SWI-Prolog.
|
||||
|
||||
+ (clp) coins/
|
||||
+ (clp) draughts/
|
||||
+ hanoi/ : towers of Hanoi
|
||||
+ (clp) sendmoremoney/ : if, SEND + MORE = MONEY, what is S, E, N, D, M, O, R, Y?
|
||||
+ (clp) sudoku/ : Sudoku solver (Prolog code is contributed by Markus Triska)
|
||||
+ create_term.py : shows creating a Prolog term
|
||||
+ register_foreign.py : shows how to call PL_register_foreign
|
42
packages/pyswip/examples/coins/coins.pl
Normal file
42
packages/pyswip/examples/coins/coins.pl
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
% Coins -- 2007 by Yuce Tekol <yucetekol@gmail.com>
|
||||
|
||||
:- use_module(library('clpfd')).
|
||||
|
||||
coins(S, Count, Total) :-
|
||||
% A=1, B=5, C=10, D=50, E=100
|
||||
S = [A, B, C, D, E],
|
||||
|
||||
Av is 1,
|
||||
Bv is 5,
|
||||
Cv is 10,
|
||||
Dv is 50,
|
||||
Ev is 100,
|
||||
|
||||
Aup is Total // Av,
|
||||
Bup is Total // Bv,
|
||||
Cup is Total // Cv,
|
||||
Dup is Total // Dv,
|
||||
Eup is Total // Ev,
|
||||
|
||||
A in 0..Aup,
|
||||
B in 0..Bup,
|
||||
C in 0..Cup,
|
||||
D in 0..Dup,
|
||||
E in 0..Eup,
|
||||
|
||||
VA #= A*Av,
|
||||
VB #= B*Bv,
|
||||
VC #= C*Cv,
|
||||
VD #= D*Dv,
|
||||
VE #= E*Ev,
|
||||
|
||||
sum(S, #=, Count),
|
||||
VA + VB + VC + VD + VE #= Total,
|
||||
|
||||
label(S).
|
||||
|
||||
% :- findall(S, coins(S, 100, 500), Ss), halt.
|
||||
%:- coins(S, 100, 500), writeln(S), fail.
|
||||
|
||||
|
22
packages/pyswip/examples/coins/coins.py
Normal file
22
packages/pyswip/examples/coins/coins.py
Normal file
@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 100 coins must sum to $5.00
|
||||
|
||||
from pyswip.prolog import Prolog
|
||||
|
||||
def main():
|
||||
prolog = Prolog()
|
||||
prolog.consult("coins.pl")
|
||||
count = int(raw_input("How many coins (default: 100)? ") or 100)
|
||||
total = int(raw_input("What should be the total (default: 500)? ") or 500)
|
||||
for i, soln in enumerate(prolog.query("coins(S, %d, %d)." % (count,total))):
|
||||
# [1,5,10,50,100]
|
||||
S = zip(soln["S"], [1, 5, 10, 50, 100])
|
||||
print i,
|
||||
for c, v in S:
|
||||
print "%dx%d" % (c,v),
|
||||
print
|
||||
list(prolog.query("coins(S, %d, %d)." % (count,total)))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
27
packages/pyswip/examples/create_term.py
Normal file
27
packages/pyswip/examples/create_term.py
Normal file
@ -0,0 +1,27 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
from pyswip.core import *
|
||||
from pyswip.prolog import Prolog
|
||||
|
||||
def main():
|
||||
prolog = Prolog()
|
||||
|
||||
a1 = PL_new_term_refs(2)
|
||||
a2 = a1 + 1
|
||||
t = PL_new_term_ref()
|
||||
ta = PL_new_term_ref()
|
||||
|
||||
animal2 = PL_new_functor(PL_new_atom("animal"), 2)
|
||||
assertz = PL_new_functor(PL_new_atom("assertz"), 1)
|
||||
PL_put_atom_chars(a1, "gnu")
|
||||
PL_put_integer(a2, 50)
|
||||
#PL_cons_functor(t, animal2, a1, a2)
|
||||
PL_cons_functor_v(t, animal2, a1)
|
||||
PL_cons_functor_v(ta, assertz, t)
|
||||
PL_call(ta, None)
|
||||
|
||||
# prolog.assertz("animal(gnu, 50)")
|
||||
print list(prolog.query("animal(X,Y)", catcherrors=True))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
18
packages/pyswip/examples/draughts/puzzle1.pl
Normal file
18
packages/pyswip/examples/draughts/puzzle1.pl
Normal file
@ -0,0 +1,18 @@
|
||||
% This example is adapted from http://eclipse.crosscoreop.com/examples/puzzle1.pl.txt
|
||||
|
||||
:- use_module(library('clpfd')).
|
||||
|
||||
solve(Board) :-
|
||||
Board = [NW,N,NE,W,E,SW,S,SE],
|
||||
domains(Board,0..12),
|
||||
sum(Board, #=, 12),
|
||||
NW + N + NE #= 5,
|
||||
NE + E + SE #= 5,
|
||||
NW + W + SW #= 5,
|
||||
SW + S + SE #= 5,
|
||||
label(Board).
|
||||
|
||||
domains([],_).
|
||||
domains([Pos|Board],D) :-
|
||||
Pos in D,
|
||||
domains(Board,D).
|
34
packages/pyswip/examples/draughts/puzzle1.py
Normal file
34
packages/pyswip/examples/draughts/puzzle1.py
Normal file
@ -0,0 +1,34 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This example is adapted from http://eclipse.crosscoreop.com/examples/puzzle1.pl.txt
|
||||
|
||||
# "Twelve draught pieces are arranged in a square frame with four on
|
||||
# each side. Try placing them so there are 5 on each side. (Kordemsky)
|
||||
#
|
||||
# "Maybe this problem is not described very well but I wanted to stick
|
||||
# with the original text from Kordemsky. The problem may be stated in
|
||||
# terms of guards on the wall of a square fort. If a guard stands on a
|
||||
# side wall then he may only watch that particular wall whereas a guard
|
||||
# at a corner may watch two walls. If twelve guards are positioned such
|
||||
# that there are two on each side wall and one at each corner then there
|
||||
# are four guards watching each wall. How can they be rearranged such
|
||||
# that there are five watching each wall?"
|
||||
|
||||
from pyswip.prolog import Prolog
|
||||
|
||||
def main():
|
||||
prolog = Prolog()
|
||||
prolog.consult("puzzle1.pl")
|
||||
for soln in prolog.query("solve(B)."):
|
||||
#B = eval(soln["B"])
|
||||
B = soln["B"]
|
||||
# [NW,N,NE,W,E,SW,S,SE]
|
||||
print "%d %d %d" % tuple(B[:3])
|
||||
print "%d %d" % tuple(B[3:5])
|
||||
print "%d %d %d" % tuple(B[5:])
|
||||
|
||||
cont = raw_input("Press 'n' to finish: ")
|
||||
if cont.lower() == "n": break
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
12
packages/pyswip/examples/hanoi/hanoi.pl
Normal file
12
packages/pyswip/examples/hanoi/hanoi.pl
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
% Towers of Hanoi
|
||||
% Based on: http://en.wikipedia.org/wiki/Prolog
|
||||
|
||||
hanoi(N) :- move(N, left, right, center).
|
||||
move(0, _, _, _) :- !.
|
||||
move(N, A, B, C) :-
|
||||
M is N-1,
|
||||
move(M, A, C, B),
|
||||
notify([A,B]),
|
||||
move(M, C, B, A).
|
||||
|
67
packages/pyswip/examples/hanoi/hanoi.py
Normal file
67
packages/pyswip/examples/hanoi/hanoi.py
Normal file
@ -0,0 +1,67 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from collections import deque
|
||||
from pyswip.prolog import Prolog
|
||||
from pyswip.easy import getList, registerForeign
|
||||
|
||||
class Notifier:
|
||||
def __init__(self, fun):
|
||||
self.fun = fun
|
||||
|
||||
def notify(self, t):
|
||||
#return not self.fun(getList(t))
|
||||
return not self.fun(t)
|
||||
notify.arity = 1
|
||||
|
||||
class Tower:
|
||||
def __init__(self, N=3, interactive=False):
|
||||
"""N is the number of disks
|
||||
"""
|
||||
self.N = N
|
||||
self.disks = dict(left=deque(range(N, 0, -1)), center=deque(), right=deque())
|
||||
self.started = False
|
||||
self.interactive = interactive
|
||||
self.step = 0
|
||||
|
||||
def move(self, r):
|
||||
if not self.started:
|
||||
self.step += 1
|
||||
self.draw()
|
||||
self.started = True
|
||||
disks = self.disks
|
||||
disks[str(r[1])].append(disks[str(r[0])].pop())
|
||||
self.step += 1
|
||||
return self.draw()
|
||||
|
||||
def draw(self):
|
||||
disks = self.disks
|
||||
print "\n Step", self.step
|
||||
for i in range(self.N):
|
||||
n = self.N - i - 1
|
||||
print " ",
|
||||
for pole in ["left", "center", "right"]:
|
||||
if len(disks[pole]) - n > 0:
|
||||
print disks[pole][n],
|
||||
else:
|
||||
print " ",
|
||||
print
|
||||
print "-"*9
|
||||
print " ", "L", "C", "R"
|
||||
if self.interactive:
|
||||
cont = raw_input("Press 'n' to finish: ")
|
||||
return cont.lower() == "n"
|
||||
|
||||
|
||||
def main():
|
||||
N = 3
|
||||
INTERACTIVITY = True
|
||||
|
||||
prolog = Prolog()
|
||||
tower = Tower(N, INTERACTIVITY)
|
||||
notifier = Notifier(tower.move)
|
||||
registerForeign(notifier.notify)
|
||||
prolog.consult("hanoi.pl")
|
||||
list(prolog.query("hanoi(%d)" % N))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
33
packages/pyswip/examples/knowledgebase.py
Normal file
33
packages/pyswip/examples/knowledgebase.py
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
from pyswip import *
|
||||
|
||||
p = Prolog()
|
||||
|
||||
assertz = Functor("assertz")
|
||||
parent = Functor("parent", 2)
|
||||
test1 = newModule("test1")
|
||||
test2 = newModule("test2")
|
||||
|
||||
call(assertz(parent("john", "bob")), module=test1)
|
||||
call(assertz(parent("jane", "bob")), module=test1)
|
||||
|
||||
call(assertz(parent("mike", "bob")), module=test2)
|
||||
call(assertz(parent("gina", "bob")), module=test2)
|
||||
|
||||
print "knowledgebase test1"
|
||||
|
||||
X = Variable()
|
||||
print "ok"
|
||||
q = Query(parent(X, "bob"), module=test1)
|
||||
print "ok"
|
||||
while q.nextSolution():
|
||||
print X.value
|
||||
q.closeQuery()
|
||||
|
||||
print "knowledgebase test2"
|
||||
|
||||
q = Query(parent(X, "bob"), module=test2)
|
||||
while q.nextSolution():
|
||||
print X.value
|
||||
q.closeQuery()
|
||||
|
14
packages/pyswip/examples/register_foreign.py
Normal file
14
packages/pyswip/examples/register_foreign.py
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
from pyswip import Prolog, registerForeign, Atom
|
||||
|
||||
def atom_checksum(*a):
|
||||
if isinstance(a[0], Atom):
|
||||
r = sum(ord(c)&0xFF for c in str(a[0]))
|
||||
a[1].value = r&0xFF
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
p = Prolog()
|
||||
registerForeign(atom_checksum, arity=2)
|
||||
print list(p.query("X='Python', atom_checksum(X, Y)", catcherrors=False))
|
20
packages/pyswip/examples/register_foreign_simple.py
Normal file
20
packages/pyswip/examples/register_foreign_simple.py
Normal file
@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Demonstrates registering a Python function as a Prolog predicate through SWI-Prolog's FFI.
|
||||
|
||||
from pyswip.prolog import Prolog
|
||||
from pyswip.easy import registerForeign, getAtomChars
|
||||
|
||||
def hello(t):
|
||||
print "Hello,", t
|
||||
hello.arity = 1
|
||||
|
||||
def main():
|
||||
registerForeign(hello)
|
||||
prolog = Prolog()
|
||||
prolog.assertz("father(michael,john)")
|
||||
prolog.assertz("father(michael,gina)")
|
||||
list(prolog.query("father(michael,X), hello(X)"))
|
||||
|
||||
if __name__ =="__main__":
|
||||
main()
|
22
packages/pyswip/examples/sendmoremoney/money.pl
Normal file
22
packages/pyswip/examples/sendmoremoney/money.pl
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
% SEND + MORE = MONEY
|
||||
% Adapted from: http://en.wikipedia.org/wiki/Constraint_programming
|
||||
|
||||
:- use_module(library(clpfd)).
|
||||
|
||||
sendmore(Digits) :-
|
||||
Digits = [S,E,N,D,M,O,R,Y], % Create variables
|
||||
allin(Digits, 0..9), % Associate domains to variables
|
||||
S #\= 0, % Constraint: S must be different from 0
|
||||
M #\= 0,
|
||||
all_different(Digits), % all the elements must take different values
|
||||
1000*S + 100*E + 10*N + D % Other constraints
|
||||
+ 1000*M + 100*O + 10*R + E
|
||||
#= 10000*M + 1000*O + 100*N + 10*E + Y,
|
||||
label(Digits). % Start the search
|
||||
|
||||
|
||||
allin([],_).
|
||||
allin([Pos|Board],D) :-
|
||||
Pos in D,
|
||||
allin(Board,D).
|
21
packages/pyswip/examples/sendmoremoney/money.py
Normal file
21
packages/pyswip/examples/sendmoremoney/money.py
Normal file
@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# S E N D
|
||||
# M O R E
|
||||
# + -------
|
||||
# M O N E Y
|
||||
#
|
||||
# So, what should be the values of S, E, N, D, M, O, R, Y
|
||||
# if they are all distinct digits.
|
||||
|
||||
from pyswip import Prolog
|
||||
|
||||
letters = "S E N D M O R Y".split()
|
||||
prolog = Prolog()
|
||||
prolog.consult("money.pl")
|
||||
for result in prolog.query("sendmore(X)"):
|
||||
r = result["X"]
|
||||
for i, letter in enumerate(letters):
|
||||
print letter, "=", r[i]
|
||||
|
||||
print "That's all..."
|
31
packages/pyswip/examples/sudoku/sudoku.pl
Normal file
31
packages/pyswip/examples/sudoku/sudoku.pl
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
% Prolog Sudoku Solver (C) 2007 Markus Triska (triska@gmx.at)
|
||||
% Public domain code.
|
||||
|
||||
:- use_module(library(clpfd)).
|
||||
|
||||
% Pss is a list of lists representing the game board.
|
||||
|
||||
sudoku(Pss) :-
|
||||
flatten(Pss, Ps),
|
||||
allin(Ps, 1..9),
|
||||
maplist(all_different, Pss),
|
||||
Pss = [R1,R2,R3,R4,R5,R6,R7,R8,R9],
|
||||
columns(R1, R2, R3, R4, R5, R6, R7, R8, R9),
|
||||
blocks(R1, R2, R3), blocks(R4, R5, R6), blocks(R7, R8, R9),
|
||||
label(Ps).
|
||||
|
||||
columns([], [], [], [], [], [], [], [], []).
|
||||
columns([A|As],[B|Bs],[C|Cs],[D|Ds],[E|Es],[F|Fs],[G|Gs],[H|Hs],[I|Is]) :-
|
||||
all_different([A,B,C,D,E,F,G,H,I]),
|
||||
columns(As, Bs, Cs, Ds, Es, Fs, Gs, Hs, Is).
|
||||
|
||||
blocks([], [], []).
|
||||
blocks([X1,X2,X3|R1], [X4,X5,X6|R2], [X7,X8,X9|R3]) :-
|
||||
all_different([X1,X2,X3,X4,X5,X6,X7,X8,X9]),
|
||||
blocks(R1, R2, R3).
|
||||
|
||||
allin([],_).
|
||||
allin([Pos|Board],D) :-
|
||||
Pos in D,
|
||||
allin(Board,D).
|
62
packages/pyswip/examples/sudoku/sudoku.py
Normal file
62
packages/pyswip/examples/sudoku/sudoku.py
Normal file
@ -0,0 +1,62 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from pyswip.prolog import Prolog
|
||||
from pyswip.easy import *
|
||||
|
||||
_ = 0
|
||||
puzzle1 = [
|
||||
[_,6,_,1,_,4,_,5,_],
|
||||
[_,_,8,3,_,5,6,_,_],
|
||||
[2,_,_,_,_,_,_,_,1],
|
||||
[8,_,_,4,_,7,_,_,6],
|
||||
[_,_,6,_,_,_,3,_,_],
|
||||
[7,_,_,9,_,1,_,_,4],
|
||||
[5,_,_,_,_,_,_,_,2],
|
||||
[_,_,7,2,_,6,9,_,_],
|
||||
[_,4,_,5,_,8,_,7,_]
|
||||
]
|
||||
|
||||
|
||||
puzzle2 = [
|
||||
[_,_,1,_,8,_,6,_,4],
|
||||
[_,3,7,6,_,_,_,_,_],
|
||||
[5,_,_,_,_,_,_,_,_],
|
||||
[_,_,_,_,_,5,_,_,_],
|
||||
[_,_,6,_,1,_,8,_,_],
|
||||
[_,_,_,4,_,_,_,_,_],
|
||||
[_,_,_,_,_,_,_,_,3],
|
||||
[_,_,_,_,_,7,5,2,_],
|
||||
[8,_,2,_,9,_,7,_,_]
|
||||
]
|
||||
|
||||
def pretty_print(table):
|
||||
print "".join(["/---", "----"*8, "\\"])
|
||||
for row in table:
|
||||
print "".join(["|", "|".join(" %s " % (i or " ") for i in row), "|"])
|
||||
print "".join(["\\---", "----"*8, "/"])
|
||||
|
||||
def solve(problem):
|
||||
prolog.consult("sudoku.pl")
|
||||
p = str(problem).replace("0", "_")
|
||||
result = list(prolog.query("L=%s,sudoku(L)" % p, maxresult=1))
|
||||
if result:
|
||||
result = result[0]
|
||||
return result["L"]
|
||||
else:
|
||||
return False
|
||||
|
||||
def main():
|
||||
puzzle = puzzle1
|
||||
print "-- PUZZLE --"
|
||||
pretty_print(puzzle)
|
||||
print
|
||||
print " -- SOLUTION --"
|
||||
solution = solve(puzzle)
|
||||
if solution:
|
||||
pretty_print(solution)
|
||||
else:
|
||||
print "This puzzle has no solutions [is it valid?]"
|
||||
|
||||
if __name__ == "__main__":
|
||||
prolog = Prolog()
|
||||
main()
|
78
packages/pyswip/examples/sudoku/sudoku_daily.py
Normal file
78
packages/pyswip/examples/sudoku/sudoku_daily.py
Normal file
@ -0,0 +1,78 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Sudoku auto-solver. Get today's sudoku at http://www.sudoku.org.uk/daily.asp
|
||||
# and solve it
|
||||
|
||||
import urllib
|
||||
from HTMLParser import HTMLParser, HTMLParseError
|
||||
from pyswip.prolog import Prolog
|
||||
from pyswip.easy import *
|
||||
|
||||
URL = "http://www.sudoku.org.uk/daily.asp"
|
||||
|
||||
class DailySudokuPuzzle(HTMLParser):
|
||||
def __init__(self):
|
||||
self.puzzle = []
|
||||
self.__in_td = False
|
||||
HTMLParser.__init__(self)
|
||||
|
||||
def handle_starttag(self, tag, attrs):
|
||||
if tag == "td":
|
||||
for attr in attrs:
|
||||
if attr[0] == "class" and attr[1] == "InnerTDone":
|
||||
self.__in_td = True
|
||||
break
|
||||
elif tag == "input":
|
||||
if self.__in_td:
|
||||
self.puzzle.append(0)
|
||||
|
||||
def handle_endtag(self, tag):
|
||||
if tag == "td":
|
||||
self.__in_td = False
|
||||
|
||||
def handle_data(self, data):
|
||||
if self.__in_td:
|
||||
self.puzzle.append(int(data))
|
||||
|
||||
def pretty_print(table):
|
||||
print "".join(["/---", "----"*8, "\\"])
|
||||
for row in table:
|
||||
print "".join(["|", "|".join(" %s " % (i or " ") for i in row), "|"])
|
||||
print "".join(["\\---", "----"*8, "/"])
|
||||
|
||||
def get_daily_sudoku(url):
|
||||
puzzle = DailySudokuPuzzle()
|
||||
f = urllib.urlopen(url)
|
||||
try:
|
||||
puzzle.feed(f.read())
|
||||
except HTMLParseError:
|
||||
pass
|
||||
puzzle = puzzle.puzzle
|
||||
return [puzzle[i*9:i*9+9] for i in range(9)]
|
||||
|
||||
def solve(problem):
|
||||
prolog.consult("sudoku.pl")
|
||||
p = str(problem).replace("0", "_")
|
||||
result = list(prolog.query("Puzzle=%s,sudoku(Puzzle)" % p, maxresult=1))
|
||||
if result:
|
||||
result = result[0]
|
||||
return result["Puzzle"]
|
||||
else:
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
prolog = Prolog() # having this in `solve` bites! because of __del__
|
||||
|
||||
print "Getting puzzle from:", URL
|
||||
|
||||
puzzle = get_daily_sudoku(URL)
|
||||
print "-- PUZZLE --"
|
||||
pretty_print(puzzle)
|
||||
print
|
||||
print " -- SOLUTION --"
|
||||
solution = solve(puzzle)
|
||||
if solution:
|
||||
pretty_print(solution)
|
||||
else:
|
||||
print "This puzzle has no solutions [is it valid?]"
|
||||
|
24
packages/pyswip/pyswip/__init__.py
Normal file
24
packages/pyswip/pyswip/__init__.py
Normal file
@ -0,0 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# pyswip -- Python SWI-Prolog bridge
|
||||
# (c) 2006-2007 Yüce TEKOL
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
|
||||
# PySWIP version
|
||||
__VERSION__ = "0.2.2b"
|
||||
|
||||
from pyswip.prolog import Prolog
|
||||
from pyswip.easy import *
|
595
packages/pyswip/pyswip/core.py
Normal file
595
packages/pyswip/pyswip/core.py
Normal file
@ -0,0 +1,595 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# pyswip -- Python SWI-Prolog bridge
|
||||
# (c) 2006-2007 Yüce TEKOL
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
|
||||
import sys
|
||||
|
||||
try:
|
||||
from ctypes import *
|
||||
except ImportError:
|
||||
print>>sys.stderr, "A required module: 'ctypes' not found."
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
if sys.platform[:3] == "win":
|
||||
# we're on windows
|
||||
_lib = CDLL("libYap.dll")
|
||||
elif sys.platform[:3] == "dar":
|
||||
# we're on Mac OS
|
||||
_lib = CDLL("libYap.dylib")
|
||||
else:
|
||||
# UNIX-like
|
||||
try:
|
||||
_lib = CDLL("libYap.so")
|
||||
except IndexError:
|
||||
# let's try the cwd
|
||||
_lib = CDLL("./libYap.so")
|
||||
|
||||
except OSError:
|
||||
print>>sys.stderr, "libYap (shared) not found. Possible reasons:"
|
||||
print>>sys.stderr, "1) YAP has not been installed as a shared library, use --with-java)"
|
||||
print>>sys.stderr, "1) set LD_LIBRARY_PATH=/usr/local/lib or somewhere elser where libYap.so can be found"
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# PySWIP constants
|
||||
PYSWIP_MAXSTR = 1024
|
||||
c_int_p = POINTER(c_int)
|
||||
c_long_p = POINTER(c_long)
|
||||
c_double_p = POINTER(c_double)
|
||||
|
||||
# constants (from SWI-Prolog.h)
|
||||
# PL_unify_term() arguments
|
||||
PL_VARIABLE = 1 # nothing
|
||||
PL_ATOM = 2 # const char
|
||||
PL_INTEGER = 3 # int
|
||||
PL_FLOAT = 4 # double
|
||||
PL_STRING = 5 # const char *
|
||||
PL_TERM = 6 #
|
||||
# PL_unify_term()
|
||||
PL_FUNCTOR = 10 # functor_t, arg ...
|
||||
PL_LIST = 11 # length, arg ...
|
||||
PL_CHARS = 12 # const char *
|
||||
PL_POINTER = 13 # void *
|
||||
# /* PlArg::PlArg(text, type) */
|
||||
#define PL_CODE_LIST (14) /* [ascii...] */
|
||||
#define PL_CHAR_LIST (15) /* [h,e,l,l,o] */
|
||||
#define PL_BOOL (16) /* PL_set_feature() */
|
||||
#define PL_FUNCTOR_CHARS (17) /* PL_unify_term() */
|
||||
#define _PL_PREDICATE_INDICATOR (18) /* predicate_t (Procedure) */
|
||||
#define PL_SHORT (19) /* short */
|
||||
#define PL_INT (20) /* int */
|
||||
#define PL_LONG (21) /* long */
|
||||
#define PL_DOUBLE (22) /* double */
|
||||
#define PL_NCHARS (23) /* unsigned, const char * */
|
||||
#define PL_UTF8_CHARS (24) /* const char * */
|
||||
#define PL_UTF8_STRING (25) /* const char * */
|
||||
#define PL_INT64 (26) /* int64_t */
|
||||
#define PL_NUTF8_CHARS (27) /* unsigned, const char * */
|
||||
#define PL_NUTF8_CODES (29) /* unsigned, const char * */
|
||||
#define PL_NUTF8_STRING (30) /* unsigned, const char * */
|
||||
#define PL_NWCHARS (31) /* unsigned, const wchar_t * */
|
||||
#define PL_NWCODES (32) /* unsigned, const wchar_t * */
|
||||
#define PL_NWSTRING (33) /* unsigned, const wchar_t * */
|
||||
#define PL_MBCHARS (34) /* const char * */
|
||||
#define PL_MBCODES (35) /* const char * */
|
||||
#define PL_MBSTRING (36) /* const char * */
|
||||
|
||||
# /********************************
|
||||
# * NON-DETERMINISTIC CALL/RETURN *
|
||||
# *********************************/
|
||||
#
|
||||
# Note 1: Non-deterministic foreign functions may also use the deterministic
|
||||
# return methods PL_succeed and PL_fail.
|
||||
#
|
||||
# Note 2: The argument to PL_retry is a 30 bits signed integer (long).
|
||||
|
||||
PL_FIRST_CALL = 0
|
||||
PL_CUTTED = 1
|
||||
PL_REDO = 2
|
||||
|
||||
PL_FA_NOTRACE = 0x01 # foreign cannot be traced
|
||||
PL_FA_TRANSPARENT = 0x02 # foreign is module transparent
|
||||
PL_FA_NONDETERMINISTIC = 0x04 # foreign is non-deterministic
|
||||
PL_FA_VARARGS = 0x08 # call using t0, ac, ctx
|
||||
PL_FA_CREF = 0x10 # Internal: has clause-reference */
|
||||
|
||||
# /*******************************
|
||||
# * CALL-BACK *
|
||||
# *******************************/
|
||||
|
||||
PL_Q_DEBUG = 0x01 # = TRUE for backward compatibility
|
||||
PL_Q_NORMAL = 0x02 # normal usage
|
||||
PL_Q_NODEBUG = 0x04 # use this one
|
||||
PL_Q_CATCH_EXCEPTION = 0x08 # handle exceptions in C
|
||||
PL_Q_PASS_EXCEPTION = 0x10 # pass to parent environment
|
||||
PL_Q_DETERMINISTIC = 0x20 # call was deterministic
|
||||
|
||||
# /*******************************
|
||||
# * BLOBS *
|
||||
# *******************************/
|
||||
|
||||
#define PL_BLOB_MAGIC_B 0x75293a00 /* Magic to validate a blob-type */
|
||||
#define PL_BLOB_VERSION 1 /* Current version */
|
||||
#define PL_BLOB_MAGIC (PL_BLOB_MAGIC_B|PL_BLOB_VERSION)
|
||||
|
||||
#define PL_BLOB_UNIQUE 0x01 /* Blob content is unique */
|
||||
#define PL_BLOB_TEXT 0x02 /* blob contains text */
|
||||
#define PL_BLOB_NOCOPY 0x04 /* do not copy the data */
|
||||
#define PL_BLOB_WCHAR 0x08 /* wide character string */
|
||||
|
||||
# /*******************************
|
||||
# * CHAR BUFFERS *
|
||||
# *******************************/
|
||||
|
||||
CVT_ATOM = 0x0001
|
||||
CVT_STRING = 0x0002
|
||||
CVT_LIST = 0x0004
|
||||
CVT_INTEGER = 0x0008
|
||||
CVT_FLOAT = 0x0010
|
||||
CVT_VARIABLE = 0x0020
|
||||
CVT_NUMBER = CVT_INTEGER | CVT_FLOAT
|
||||
CVT_ATOMIC = CVT_NUMBER | CVT_ATOM | CVT_STRING
|
||||
CVT_WRITE = 0x0040 # as of version 3.2.10
|
||||
CVT_ALL = CVT_ATOMIC | CVT_LIST
|
||||
CVT_MASK = 0x00ff
|
||||
|
||||
BUF_DISCARDABLE = 0x0000
|
||||
BUF_RING = 0x0100
|
||||
BUF_MALLOC = 0x0200
|
||||
|
||||
CVT_EXCEPTION = 0x10000 # throw exception on error
|
||||
|
||||
argv = (c_char_p*(len(sys.argv) + 1))()
|
||||
for i, arg in enumerate(sys.argv):
|
||||
argv[i] = arg
|
||||
|
||||
argv[-1] = None
|
||||
argc = len(sys.argv)
|
||||
|
||||
# types
|
||||
|
||||
atom_t = c_ulong
|
||||
term_t = c_ulong
|
||||
fid_t = c_ulong
|
||||
module_t = c_void_p
|
||||
predicate_t = c_void_p
|
||||
record_t = c_void_p
|
||||
qid_t = c_ulong
|
||||
PL_fid_t = c_ulong
|
||||
control_t = c_void_p
|
||||
PL_engine_t = c_void_p
|
||||
functor_t = c_ulong
|
||||
PL_atomic_t = c_ulong
|
||||
foreign_t = c_ulong
|
||||
pl_wchar_t = c_wchar
|
||||
atom_t_p = c_void_p
|
||||
|
||||
|
||||
##_lib.PL_initialise(len(sys.argv), _argv)
|
||||
|
||||
PL_initialise = _lib.PL_initialise
|
||||
##PL_initialise.argtypes = [c_int, c_c
|
||||
|
||||
PL_open_foreign_frame = _lib.PL_open_foreign_frame
|
||||
PL_open_foreign_frame.restype = fid_t
|
||||
|
||||
PL_new_term_ref = _lib.PL_new_term_ref
|
||||
PL_new_term_ref.restype = term_t
|
||||
|
||||
PL_new_term_refs = _lib.PL_new_term_refs
|
||||
PL_new_term_refs.restype = term_t
|
||||
|
||||
PL_chars_to_term = _lib.PL_chars_to_term
|
||||
PL_chars_to_term.argtypes = [c_char_p, term_t]
|
||||
|
||||
PL_call = _lib.PL_call
|
||||
PL_call.argtypes = [term_t, module_t]
|
||||
|
||||
PL_call_predicate = _lib.PL_call_predicate
|
||||
PL_call_predicate.argtypes = [module_t, c_int, predicate_t, term_t]
|
||||
|
||||
PL_discard_foreign_frame = _lib.PL_discard_foreign_frame
|
||||
PL_discard_foreign_frame.argtypes = [fid_t]
|
||||
|
||||
PL_put_list_chars = _lib.PL_put_list_chars
|
||||
PL_put_list_chars.argtypes = [term_t, c_char_p]
|
||||
|
||||
#PL_EXPORT(void) PL_register_atom(atom_t a);
|
||||
PL_register_atom = _lib.PL_register_atom
|
||||
PL_register_atom.argtypes = [atom_t]
|
||||
|
||||
#PL_EXPORT(void) PL_unregister_atom(atom_t a);
|
||||
PL_unregister_atom = _lib.PL_unregister_atom
|
||||
PL_unregister_atom.argtypes = [atom_t]
|
||||
|
||||
#PL_EXPORT(atom_t) PL_functor_name(functor_t f);
|
||||
PL_functor_name = _lib.PL_functor_name
|
||||
PL_functor_name.argtypes = [functor_t]
|
||||
PL_functor_name.restype = atom_t
|
||||
|
||||
#PL_EXPORT(int) PL_functor_arity(functor_t f);
|
||||
PL_functor_arity = _lib.PL_functor_arity
|
||||
PL_functor_arity.argtypes = [functor_t]
|
||||
|
||||
# /* Get C-values from Prolog terms */
|
||||
#PL_EXPORT(int) PL_get_atom(term_t t, atom_t *a);
|
||||
PL_get_atom = _lib.PL_get_atom
|
||||
PL_get_atom.argtypes = [term_t, atom_t_p]
|
||||
|
||||
|
||||
#PL_EXPORT(int) PL_get_bool(term_t t, int *value);
|
||||
PL_get_bool = _lib.PL_get_bool
|
||||
PL_get_bool.argtypes = [term_t, c_int_p]
|
||||
|
||||
#PL_EXPORT(int) PL_get_atom_chars(term_t t, char **a);
|
||||
PL_get_atom_chars = _lib.PL_get_atom_chars # FIXME
|
||||
PL_get_atom_chars.argtypes = [term_t, POINTER(c_char_p)]
|
||||
|
||||
##define PL_get_string_chars(t, s, l) PL_get_string(t,s,l)
|
||||
# /* PL_get_string() is depricated */
|
||||
#PL_EXPORT(int) PL_get_string(term_t t, char **s, size_t *len);
|
||||
PL_get_string = _lib.PL_get_string
|
||||
PL_get_string.argtypes = [term_t, POINTER(c_char_p), c_int_p]
|
||||
PL_get_string_chars = PL_get_string
|
||||
PL_get_string_chars.argtypes = [term_t, POINTER(c_char_p), c_int_p]
|
||||
|
||||
#PL_EXPORT(int) PL_get_chars(term_t t, char **s, unsigned int flags);
|
||||
PL_get_chars = _lib.PL_get_chars # FIXME:
|
||||
PL_get_chars.argtypes = [term_t, POINTER(c_char_p), c_uint]
|
||||
|
||||
#PL_EXPORT(int) PL_get_list_chars(term_t l, char **s,
|
||||
# unsigned int flags);
|
||||
#PL_EXPORT(int) PL_get_atom_nchars(term_t t, size_t *len, char **a);
|
||||
#PL_EXPORT(int) PL_get_list_nchars(term_t l,
|
||||
# size_t *len, char **s,
|
||||
# unsigned int flags);
|
||||
#PL_EXPORT(int) PL_get_nchars(term_t t,
|
||||
# size_t *len, char **s,
|
||||
# unsigned int flags);
|
||||
#PL_EXPORT(int) PL_get_integer(term_t t, int *i);
|
||||
PL_get_integer = _lib.PL_get_integer
|
||||
PL_get_integer.argtypes = [term_t, POINTER(c_int)]
|
||||
|
||||
#PL_EXPORT(int) PL_get_long(term_t t, long *i);
|
||||
PL_get_long = _lib.PL_get_long
|
||||
PL_get_long.argtypes = [term_t, POINTER(c_long)]
|
||||
|
||||
#PL_EXPORT(int) PL_get_pointer(term_t t, void **ptr);
|
||||
#PL_EXPORT(int) PL_get_float(term_t t, double *f);
|
||||
PL_get_float = _lib.PL_get_float
|
||||
PL_get_float.argtypes = [term_t, c_double_p]
|
||||
|
||||
#PL_EXPORT(int) PL_get_functor(term_t t, functor_t *f);
|
||||
PL_get_functor = _lib.PL_get_functor
|
||||
PL_get_functor.argtypes = [term_t, POINTER(functor_t)]
|
||||
|
||||
#PL_EXPORT(int) PL_get_name_arity(term_t t, atom_t *name, int *arity);
|
||||
PL_get_name_arity = _lib.PL_get_name_arity
|
||||
PL_get_name_arity.argtypes = [term_t, POINTER(atom_t), c_int_p]
|
||||
|
||||
#PL_EXPORT(int) PL_get_module(term_t t, module_t *module);
|
||||
#PL_EXPORT(int) PL_get_arg(int index, term_t t, term_t a);
|
||||
PL_get_arg = _lib.PL_get_arg
|
||||
PL_get_arg.argtypes = [c_int, term_t, term_t]
|
||||
|
||||
#PL_EXPORT(int) PL_get_list(term_t l, term_t h, term_t t);
|
||||
#PL_EXPORT(int) PL_get_head(term_t l, term_t h);
|
||||
PL_get_head = _lib.PL_get_head
|
||||
PL_get_head.argtypes = [term_t, term_t]
|
||||
#PL_EXPORT(int) PL_get_tail(term_t l, term_t t);
|
||||
PL_get_tail = _lib.PL_get_tail
|
||||
PL_get_tail.argtypes = [term_t, term_t]
|
||||
#PL_EXPORT(int) PL_get_nil(term_t l);
|
||||
PL_get_nil = _lib.PL_get_nil
|
||||
PL_get_nil.argtypes = [term_t]
|
||||
#PL_EXPORT(int) PL_get_term_value(term_t t, term_value_t *v);
|
||||
#PL_EXPORT(char *) PL_quote(int chr, const char *data);
|
||||
|
||||
PL_put_atom_chars = _lib.PL_put_atom_chars
|
||||
PL_put_atom_chars.argtypes = [term_t, c_char_p]
|
||||
|
||||
PL_atom_chars = _lib.PL_atom_chars
|
||||
PL_atom_chars.argtypes = [atom_t]
|
||||
PL_atom_chars.restype = c_char_p
|
||||
|
||||
PL_predicate = _lib.PL_predicate
|
||||
PL_predicate.argtypes = [c_char_p, c_int, c_char_p]
|
||||
PL_predicate.restype = predicate_t
|
||||
|
||||
PL_pred = _lib.PL_pred
|
||||
PL_pred.argtypes = [functor_t, module_t]
|
||||
PL_pred.restype = predicate_t
|
||||
|
||||
PL_open_query = _lib.PL_open_query
|
||||
PL_open_query.argtypes = [module_t, c_int, predicate_t, term_t]
|
||||
PL_open_query.restype = qid_t
|
||||
|
||||
PL_next_solution = _lib.PL_next_solution
|
||||
PL_next_solution.argtypes = [qid_t]
|
||||
|
||||
PL_copy_term_ref = _lib.PL_copy_term_ref
|
||||
PL_copy_term_ref.argtypes = [term_t]
|
||||
PL_copy_term_ref.restype = term_t
|
||||
|
||||
PL_get_list = _lib.PL_get_list
|
||||
PL_get_list.argtypes = [term_t, term_t, term_t]
|
||||
|
||||
PL_get_chars = _lib.PL_get_chars
|
||||
PL_get_chars.argtypes = [term_t, POINTER(c_char_p), c_uint]
|
||||
|
||||
PL_close_query = _lib.PL_close_query
|
||||
PL_close_query.argtypes = [qid_t]
|
||||
|
||||
#void PL_cut_query(qid)
|
||||
PL_cut_query = _lib.PL_cut_query
|
||||
PL_cut_query.argtypes = [qid_t]
|
||||
|
||||
PL_halt = _lib.PL_halt
|
||||
PL_halt.argtypes = [c_int]
|
||||
|
||||
PL_unify_integer = _lib.PL_unify_integer
|
||||
PL_unify_integer.argtypes = [term_t,c_long]
|
||||
|
||||
PL_unify = _lib.PL_unify
|
||||
PL_unify.argtypes = [term_t,term_t]
|
||||
|
||||
PL_unify_arg = _lib.PL_unify_arg
|
||||
PL_unify.argtypes = [c_int,term_t,atom_t]
|
||||
|
||||
# Verify types
|
||||
|
||||
PL_term_type = _lib.PL_term_type
|
||||
PL_term_type.argtypes = [term_t]
|
||||
PL_term_type.restype = c_int
|
||||
|
||||
PL_is_variable = _lib.PL_is_variable
|
||||
PL_is_variable.argtypes = [term_t]
|
||||
PL_is_variable.restype = c_int
|
||||
|
||||
PL_is_ground = _lib.PL_is_ground
|
||||
PL_is_ground.argtypes = [term_t]
|
||||
PL_is_ground.restype = c_int
|
||||
|
||||
PL_is_atom = _lib.PL_is_atom
|
||||
PL_is_atom.argtypes = [term_t]
|
||||
PL_is_atom.restype = c_int
|
||||
|
||||
PL_is_integer = _lib.PL_is_integer
|
||||
PL_is_integer.argtypes = [term_t]
|
||||
PL_is_integer.restype = c_int
|
||||
|
||||
PL_is_string = _lib.PL_is_string
|
||||
PL_is_string.argtypes = [term_t]
|
||||
PL_is_string.restype = c_int
|
||||
|
||||
PL_is_float = _lib.PL_is_float
|
||||
PL_is_float.argtypes = [term_t]
|
||||
PL_is_float.restype = c_int
|
||||
|
||||
#PL_is_rational = _lib.PL_is_rational
|
||||
#PL_is_rational.argtypes = [term_t]
|
||||
#PL_is_rational.restype = c_int
|
||||
|
||||
PL_is_compound = _lib.PL_is_compound
|
||||
PL_is_compound.argtypes = [term_t]
|
||||
PL_is_compound.restype = c_int
|
||||
|
||||
PL_is_functor = _lib.PL_is_functor
|
||||
PL_is_functor.argtypes = [term_t, functor_t]
|
||||
PL_is_functor.restype = c_int
|
||||
|
||||
PL_is_list = _lib.PL_is_list
|
||||
PL_is_list.argtypes = [term_t]
|
||||
PL_is_list.restype = c_int
|
||||
|
||||
PL_is_atomic = _lib.PL_is_atomic
|
||||
PL_is_atomic.argtypes = [term_t]
|
||||
PL_is_atomic.restype = c_int
|
||||
|
||||
PL_is_number = _lib.PL_is_number
|
||||
PL_is_number.argtypes = [term_t]
|
||||
PL_is_number.restype = c_int
|
||||
|
||||
# /* Assign to term-references */
|
||||
#PL_EXPORT(void) PL_put_variable(term_t t);
|
||||
PL_put_variable = _lib.PL_put_variable
|
||||
PL_put_variable.argtypes = [term_t]
|
||||
#PL_EXPORT(void) PL_put_atom(term_t t, atom_t a);
|
||||
#PL_EXPORT(void) PL_put_atom_chars(term_t t, const char *chars);
|
||||
#PL_EXPORT(void) PL_put_string_chars(term_t t, const char *chars);
|
||||
#PL_EXPORT(void) PL_put_list_chars(term_t t, const char *chars);
|
||||
#PL_EXPORT(void) PL_put_list_codes(term_t t, const char *chars);
|
||||
#PL_EXPORT(void) PL_put_atom_nchars(term_t t, size_t l, const char *chars);
|
||||
#PL_EXPORT(void) PL_put_string_nchars(term_t t, size_t len, const char *chars);
|
||||
#PL_EXPORT(void) PL_put_list_nchars(term_t t, size_t l, const char *chars);
|
||||
#PL_EXPORT(void) PL_put_list_ncodes(term_t t, size_t l, const char *chars);
|
||||
#PL_EXPORT(void) PL_put_integer(term_t t, long i);
|
||||
PL_put_integer = _lib.PL_put_integer
|
||||
PL_put_integer.argtypes = [term_t, c_long]
|
||||
#PL_EXPORT(void) PL_put_pointer(term_t t, void *ptr);
|
||||
#PL_EXPORT(void) PL_put_float(term_t t, double f);
|
||||
#PL_EXPORT(void) PL_put_functor(term_t t, functor_t functor);
|
||||
PL_put_functor = _lib.PL_put_functor
|
||||
PL_put_functor.argtypes = [term_t, functor_t]
|
||||
#PL_EXPORT(void) PL_put_list(term_t l);
|
||||
PL_put_list = _lib.PL_put_list
|
||||
PL_put_list.argtypes = [term_t]
|
||||
#PL_EXPORT(void) PL_put_nil(term_t l);
|
||||
PL_put_nil = _lib.PL_put_nil
|
||||
PL_put_nil.argtypes = [term_t]
|
||||
#PL_EXPORT(void) PL_put_term(term_t t1, term_t t2);
|
||||
PL_put_term = _lib.PL_put_term
|
||||
PL_put_term.argtypes = [term_t,term_t]
|
||||
|
||||
# /* construct a functor or list-cell */
|
||||
#PL_EXPORT(void) PL_cons_functor(term_t h, functor_t f, ...);
|
||||
#class _PL_cons_functor(object):
|
||||
PL_cons_functor = _lib.PL_cons_functor # FIXME:
|
||||
|
||||
#PL_EXPORT(void) PL_cons_functor_v(term_t h, functor_t fd, term_t a0);
|
||||
PL_cons_functor_v = _lib.PL_cons_functor_v
|
||||
PL_cons_functor_v.argtypes = [term_t, functor_t, term_t]
|
||||
PL_cons_functor_v.restype = None
|
||||
|
||||
#PL_EXPORT(void) PL_cons_list(term_t l, term_t h, term_t t);
|
||||
PL_cons_list = _lib.PL_cons_list
|
||||
|
||||
#
|
||||
# term_t PL_exception(qid_t qid)
|
||||
PL_exception = _lib.PL_exception
|
||||
PL_exception.argtypes = [qid_t]
|
||||
PL_exception.restype = term_t
|
||||
#
|
||||
PL_register_foreign = _lib.PL_register_foreign
|
||||
PL_register_foreign.argtypes = [c_char_p, c_int, c_void_p, c_int]
|
||||
PL_register_foreign.restype = None
|
||||
|
||||
#
|
||||
#PL_EXPORT(atom_t) PL_new_atom(const char *s);
|
||||
PL_new_atom = _lib.PL_new_atom
|
||||
PL_new_atom.argtypes = [c_char_p]
|
||||
PL_new_atom.restype = atom_t
|
||||
|
||||
#PL_EXPORT(functor_t) PL_new_functor(atom_t f, int a);
|
||||
PL_new_functor = _lib.PL_new_functor
|
||||
PL_new_functor.argtypes = [atom_t, c_int]
|
||||
PL_new_functor.restype = functor_t
|
||||
|
||||
# /*******************************
|
||||
# * RECORDED DATABASE *
|
||||
# *******************************/
|
||||
#
|
||||
#PL_EXPORT(record_t) PL_record(term_t term);
|
||||
PL_record = _lib.PL_record
|
||||
PL_record.argtypes = [term_t]
|
||||
PL_record.restype = record_t
|
||||
|
||||
#PL_EXPORT(void) PL_recorded(record_t record, term_t term);
|
||||
PL_recorded = _lib.PL_recorded
|
||||
PL_recorded.argtypes = [record_t,term_t]
|
||||
PL_recorded.restype = None
|
||||
|
||||
#PL_EXPORT(void) PL_erase(record_t record);
|
||||
PL_erase = _lib.PL_erase
|
||||
PL_erase.argtypes = [record_t]
|
||||
PL_erase.restype = None
|
||||
#
|
||||
#PL_EXPORT(char *) PL_record_external(term_t t, size_t *size);
|
||||
#PL_EXPORT(int) PL_recorded_external(const char *rec, term_t term);
|
||||
#PL_EXPORT(int) PL_erase_external(char *rec);
|
||||
|
||||
PL_new_module = _lib.PL_new_module
|
||||
PL_new_module.argtypes = [atom_t]
|
||||
PL_new_module.restype = module_t
|
||||
|
||||
intptr_t = c_long
|
||||
ssize_t = intptr_t
|
||||
wint_t = c_uint
|
||||
|
||||
#typedef struct
|
||||
#{
|
||||
# int __count;
|
||||
# union
|
||||
# {
|
||||
# wint_t __wch;
|
||||
# char __wchb[4];
|
||||
# } __value; /* Value so far. */
|
||||
#} __mbstate_t;
|
||||
|
||||
class _mbstate_t_value(Union):
|
||||
_fields_ = [("__wch",wint_t),
|
||||
("__wchb",c_char*4)]
|
||||
|
||||
class mbstate_t(Structure):
|
||||
_fields_ = [("__count",c_int),
|
||||
("__value",_mbstate_t_value)]
|
||||
|
||||
# stream related funcs
|
||||
Sread_function = CFUNCTYPE(ssize_t, c_void_p, c_char_p, c_size_t)
|
||||
Swrite_function = CFUNCTYPE(ssize_t, c_void_p, c_char_p, c_size_t)
|
||||
Sseek_function = CFUNCTYPE(c_long, c_void_p, c_long, c_int)
|
||||
Sseek64_function = CFUNCTYPE(c_int64, c_void_p, c_int64, c_int)
|
||||
Sclose_function = CFUNCTYPE(c_int, c_void_p)
|
||||
Scontrol_function = CFUNCTYPE(c_int, c_void_p, c_int, c_void_p)
|
||||
|
||||
# IOLOCK
|
||||
IOLOCK = c_void_p
|
||||
|
||||
# IOFUNCTIONS
|
||||
class IOFUNCTIONS(Structure):
|
||||
_fields_ = [("read",Sread_function),
|
||||
("write",Swrite_function),
|
||||
("seek",Sseek_function),
|
||||
("close",Sclose_function),
|
||||
("seek64",Sseek64_function),
|
||||
("reserved",intptr_t*2)]
|
||||
|
||||
# IOENC
|
||||
ENC_UNKNOWN,ENC_OCTET,ENC_ASCII,ENC_ISO_LATIN_1,ENC_ANSI,ENC_UTF8,ENC_UNICODE_BE,ENC_UNICODE_LE,ENC_WCHAR = range(9)
|
||||
IOENC = c_int
|
||||
|
||||
# IOPOS
|
||||
class IOPOS(Structure):
|
||||
_fields_ = [("byteno",c_int64),
|
||||
("charno",c_int64),
|
||||
("lineno",c_int),
|
||||
("linepos",c_int),
|
||||
("reserved", intptr_t*2)]
|
||||
|
||||
# IOSTREAM
|
||||
class IOSTREAM(Structure):
|
||||
_fields_ = [("bufp",c_char_p),
|
||||
("limitp",c_char_p),
|
||||
("buffer",c_char_p),
|
||||
("unbuffer",c_char_p),
|
||||
("lastc",c_int),
|
||||
("magic",c_int),
|
||||
("bufsize",c_int),
|
||||
("flags",c_int),
|
||||
("posbuf",IOPOS),
|
||||
("position",POINTER(IOPOS)),
|
||||
("handle",c_void_p),
|
||||
("functions",IOFUNCTIONS),
|
||||
("locks",c_int),
|
||||
("mutex",IOLOCK),
|
||||
("closure_hook",CFUNCTYPE(None, c_void_p)),
|
||||
("closure",c_void_p),
|
||||
("timeout",c_int),
|
||||
("message",c_char_p),
|
||||
("encoding",IOENC)]
|
||||
IOSTREAM._fields_.extend([("tee",IOSTREAM),
|
||||
("mbstate",POINTER(mbstate_t)),
|
||||
("reserved",intptr_t*6)])
|
||||
|
||||
|
||||
|
||||
#PL_EXPORT(IOSTREAM *) Sopen_string(IOSTREAM *s, char *buf, size_t sz, const char *m);
|
||||
#Sopen_string = _lib.Sopen_string
|
||||
#Sopen_string.argtypes = [POINTER(IOSTREAM), c_char_p, c_size_t, c_char_p]
|
||||
#Sopen_string.restype = POINTER(IOSTREAM)
|
||||
|
||||
#PL_EXPORT(int) Sclose(IOSTREAM *s);
|
||||
#Sclose = _lib.Sclose
|
||||
#Sclose.argtypes = [POINTER(IOSTREAM)]
|
||||
|
||||
|
||||
#PL_EXPORT(int) PL_unify_stream(term_t t, IOSTREAM *s);
|
||||
#PL_unify_stream = _lib.PL_unify_stream
|
||||
#PL_unify_stream.argtypes = [term_t, POINTER(IOSTREAM)]
|
||||
|
476
packages/pyswip/pyswip/easy.py
Normal file
476
packages/pyswip/pyswip/easy.py
Normal file
@ -0,0 +1,476 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# pyswip.easy -- PySWIP helper functions
|
||||
# (c) 2006-2007 Yüce TEKOL
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
|
||||
from pyswip.core import *
|
||||
|
||||
|
||||
class InvalidTypeError(TypeError):
|
||||
def __init__(self, *args):
|
||||
type = args and args[0] or "Unknown"
|
||||
msg = "Term is expected to be of type: '%s'" % type
|
||||
Exception.__init__(self, msg, *args)
|
||||
|
||||
|
||||
class Atom(object):
|
||||
__slots__ = "handle","chars"
|
||||
|
||||
def __init__(self, handleOrChars):
|
||||
"""Create an atom.
|
||||
``handleOrChars``: handle or string of the atom.
|
||||
"""
|
||||
if isinstance(handleOrChars, basestring):
|
||||
self.handle = PL_new_atom(handleOrChars)
|
||||
self.chars = handleOrChars
|
||||
else:
|
||||
self.handle = handleOrChars
|
||||
PL_register_atom(self.handle)
|
||||
self.chars = c_char_p(PL_atom_chars(self.handle)).value
|
||||
|
||||
def fromTerm(cls, term):
|
||||
"""Create an atom from a Term or term handle."""
|
||||
if isinstance(term, Term):
|
||||
term = term.handle
|
||||
|
||||
a = atom_t()
|
||||
if PL_get_atom(term, addressof(a)):
|
||||
return cls(a.value)
|
||||
|
||||
fromTerm = classmethod(fromTerm)
|
||||
|
||||
def __del__(self):
|
||||
PL_unregister_atom(self.handle)
|
||||
|
||||
value = property(lambda s:s.chars)
|
||||
|
||||
def __str__(self):
|
||||
if self.chars is not None:
|
||||
return self.chars
|
||||
else:
|
||||
return self.__repr__()
|
||||
|
||||
def __repr__(self):
|
||||
return str(self.handle).join(["Atom('", "')"])
|
||||
|
||||
class Term(object):
|
||||
__slots__ = "handle","chars","__value","a0"
|
||||
def __init__(self, handle=None, a0=None):
|
||||
if handle:
|
||||
#self.handle = PL_copy_term_ref(handle)
|
||||
self.handle = handle
|
||||
else:
|
||||
self.handle = PL_new_term_ref()
|
||||
self.chars = None
|
||||
self.a0 = a0
|
||||
|
||||
def __invert__(self):
|
||||
return _not(self)
|
||||
|
||||
def get_value(self):
|
||||
pass
|
||||
|
||||
class Variable(object):
|
||||
__slots__ = "handle","chars"
|
||||
|
||||
def __init__(self, handle=None, name=None):
|
||||
self.chars = None
|
||||
if name:
|
||||
self.chars = name
|
||||
if handle:
|
||||
self.handle = handle
|
||||
s = create_string_buffer("\00"*64) # FIXME:
|
||||
ptr = cast(s, c_char_p)
|
||||
if PL_get_chars(handle, byref(ptr), CVT_VARIABLE|BUF_RING):
|
||||
self.chars = ptr.value
|
||||
else:
|
||||
self.handle = PL_new_term_ref()
|
||||
#PL_put_variable(self.handle)
|
||||
|
||||
def unify(self, value):
|
||||
if type(value) == str:
|
||||
fun = PL_unify_atom_chars
|
||||
elif type(value) == int:
|
||||
fun = PL_unify_integer
|
||||
elif type(value) == bool:
|
||||
fun = PL_unify_bool
|
||||
elif type(value) == float:
|
||||
fun = PL_unify_float
|
||||
elif type(value) == list:
|
||||
fun = PL_unify_list
|
||||
else:
|
||||
raise
|
||||
|
||||
t = PL_new_term_ref()
|
||||
fun(self.handle, value)
|
||||
|
||||
def get_value(self):
|
||||
return getTerm(self.handle)
|
||||
|
||||
value = property(get_value, unify)
|
||||
|
||||
def unified(self):
|
||||
return PL_term_type(self.handle) == PL_VARIABLE
|
||||
|
||||
def __str__(self):
|
||||
if self.chars is not None:
|
||||
return self.chars
|
||||
else:
|
||||
return self.__repr__()
|
||||
|
||||
def __repr__(self):
|
||||
return "Variable(%s)" % self.handle
|
||||
|
||||
def put(self, term):
|
||||
#PL_put_variable(term)
|
||||
self.handle = term
|
||||
|
||||
|
||||
class Functor(object):
|
||||
__slots__ = "handle","name","arity","args","__value","a0"
|
||||
func = {}
|
||||
|
||||
def __init__(self, handleOrName, arity=1, args=None, a0=None):
|
||||
"""Create a functor.
|
||||
``handleOrName``: functor handle, a string or an atom.
|
||||
"""
|
||||
|
||||
self.args = args or []
|
||||
self.arity = arity
|
||||
self.a0 = a0
|
||||
|
||||
if isinstance(handleOrName, basestring):
|
||||
self.name = Atom(handleOrName)
|
||||
self.handle = PL_new_functor(self.name.handle, arity)
|
||||
self.__value = "Functor%d" % self.handle
|
||||
elif isinstance(handleOrName, Atom):
|
||||
self.name = handleOrName
|
||||
self.handle = PL_new_functor(self.name.handle, arity)
|
||||
self.__value = "Functor%d" % self.handle
|
||||
else:
|
||||
self.handle = handleOrName
|
||||
self.name = Atom(PL_functor_name(self.handle))
|
||||
self.arity = PL_functor_arity(self.handle)
|
||||
try:
|
||||
self.__value = self.func[self.handle](self.arity, *self.args)
|
||||
except KeyError:
|
||||
self.__value = "Functor%d" % self.handle
|
||||
|
||||
def fromTerm(cls, term):
|
||||
"""Create a functor from a Term or term handle."""
|
||||
if isinstance(term, Term):
|
||||
term = term.handle
|
||||
|
||||
f = functor_t()
|
||||
if PL_get_functor(term, byref(f)):
|
||||
# get args
|
||||
args = []
|
||||
arity = PL_functor_arity(f.value)
|
||||
# let's have all args be consecutive
|
||||
a0 = PL_new_term_refs(arity)
|
||||
for i, a in enumerate(range(1, arity + 1)):
|
||||
if PL_get_arg(a, term, a0 + i):
|
||||
args.append(getTerm(a0 + i))
|
||||
|
||||
return cls(f.value, args=args, a0=a0)
|
||||
|
||||
fromTerm = classmethod(fromTerm)
|
||||
|
||||
value = property(lambda s: s.__value)
|
||||
|
||||
def __call__(self, *args):
|
||||
assert self.arity == len(args)
|
||||
a = PL_new_term_refs(len(args))
|
||||
for i, arg in enumerate(args):
|
||||
putTerm(a + i, arg)
|
||||
|
||||
t = PL_new_term_ref()
|
||||
PL_cons_functor_v(t, self.handle, a)
|
||||
return Term(t)
|
||||
|
||||
def __str__(self):
|
||||
if self.name is not None and self.arity is not None:
|
||||
return "%s(%d)" % (self.name,self.arity)
|
||||
else:
|
||||
return self.__repr__()
|
||||
|
||||
def __repr__(self):
|
||||
return "".join(["Functor(", ",".join(str(x) for x in [self.handle,self.arity]+self.args), ")"])
|
||||
|
||||
def _unifier(arity, *args):
|
||||
assert arity == 2
|
||||
#if PL_is_variable(args[0]):
|
||||
# args[0].unify(args[1])
|
||||
try:
|
||||
return {args[0].chars:args[1].value}
|
||||
except AttributeError:
|
||||
return {args[0].chars:args[1]}
|
||||
|
||||
_unify = Functor("=", 2)
|
||||
Functor.func[_unify.handle] = _unifier
|
||||
_not = Functor("not", 1)
|
||||
_comma = Functor(",", 2)
|
||||
|
||||
def putTerm(term, value):
|
||||
if isinstance(value, Term):
|
||||
PL_put_term(term, value.handle)
|
||||
elif isinstance(value, basestring):
|
||||
PL_put_atom_chars(term, value)
|
||||
elif isinstance(value, int):
|
||||
PL_put_integer(term, value)
|
||||
elif isinstance(value, Variable):
|
||||
value.put(term)
|
||||
elif isinstance(value, list):
|
||||
putList(term, value)
|
||||
elif isinstance(value, Atom):
|
||||
print "ATOM"
|
||||
elif isinstance(value, Functor):
|
||||
PL_put_functor(term, value.handle)
|
||||
else:
|
||||
raise Exception("Not implemented")
|
||||
|
||||
def putList(l, ls):
|
||||
PL_put_nil(l)
|
||||
a = PL_new_term_ref() #PL_new_term_refs(len(ls))
|
||||
for item in reversed(ls):
|
||||
putTerm(a, item)
|
||||
PL_cons_list(l, a, l)
|
||||
#PL_get_head(h, h)
|
||||
|
||||
# deprecated
|
||||
def getAtomChars(t):
|
||||
"""If t is an atom, return it as a string, otherwise raise InvalidTypeError.
|
||||
"""
|
||||
s = c_char_p()
|
||||
if PL_get_atom_chars(t, addressof(s)):
|
||||
return s.value
|
||||
else:
|
||||
raise InvalidTypeError("atom")
|
||||
|
||||
def getAtom(t):
|
||||
"""If t is an atom, return it , otherwise raise InvalidTypeError.
|
||||
"""
|
||||
return Atom.fromTerm(t)
|
||||
|
||||
def getBool(t):
|
||||
"""If t is of type bool, return it, otherwise raise InvalidTypeError.
|
||||
"""
|
||||
b = c_long()
|
||||
if PL_get_long(t, byref(b)):
|
||||
return bool(b.value)
|
||||
else:
|
||||
raise InvalidTypeError("bool")
|
||||
|
||||
def getLong(t):
|
||||
"""If t is of type long, return it, otherwise raise InvalidTypeError.
|
||||
"""
|
||||
i = c_long()
|
||||
if PL_get_long(t, byref(i)):
|
||||
return i.value
|
||||
else:
|
||||
raise InvalidTypeError("long")
|
||||
|
||||
getInteger = getLong # just an alias for getLong
|
||||
|
||||
def getFloat(t):
|
||||
"""If t is of type float, return it, otherwise raise InvalidTypeError.
|
||||
"""
|
||||
d = c_double()
|
||||
if PL_get_float(t, byref(d)):
|
||||
return d.value
|
||||
else:
|
||||
raise InvalidTypeError("float")
|
||||
|
||||
def getString(t):
|
||||
"""If t is of type string, return it, otherwise raise InvalidTypeError.
|
||||
"""
|
||||
slen = c_int()
|
||||
s = c_char_p()
|
||||
if PL_get_string_chars(t, byref(s), byref(slen)):
|
||||
return s.value
|
||||
else:
|
||||
raise InvalidTypeError("string")
|
||||
|
||||
def getTerm(t):
|
||||
p = PL_term_type(t)
|
||||
if p < PL_TERM:
|
||||
return _getterm_router[p](t)
|
||||
elif PL_is_list(t):
|
||||
return getList(t)
|
||||
else:
|
||||
return getFunctor(t)
|
||||
|
||||
def getList(x):
|
||||
"""Return t as a list.
|
||||
"""
|
||||
t = PL_copy_term_ref(x)
|
||||
head = PL_new_term_ref()
|
||||
result = []
|
||||
while PL_get_list(t, head, t):
|
||||
result.append(getTerm(head))
|
||||
|
||||
return result
|
||||
|
||||
def getFunctor(t):
|
||||
"""Return t as a functor
|
||||
"""
|
||||
return Functor.fromTerm(t)
|
||||
|
||||
def getVariable(t):
|
||||
return Variable(t)
|
||||
|
||||
_getterm_router = {
|
||||
PL_VARIABLE:getVariable, PL_ATOM:getAtom, PL_STRING:getString,
|
||||
PL_INTEGER:getInteger, PL_FLOAT:getFloat,
|
||||
PL_TERM:getTerm
|
||||
}
|
||||
|
||||
def _callbackWrapper(arity=1):
|
||||
return CFUNCTYPE(*([foreign_t] + [term_t]*arity))
|
||||
|
||||
def _foreignWrapper(fun):
|
||||
def wrapper(*args):
|
||||
args = [getTerm(arg) for arg in args]
|
||||
r = fun(*args)
|
||||
return (r is None) and True or r
|
||||
return wrapper
|
||||
|
||||
def registerForeign(func, name=None, arity=None, flags=0):
|
||||
"""Register a Python predicate
|
||||
``func``: Function to be registered. The function should return a value in
|
||||
``foreign_t``, ``True`` or ``False``.
|
||||
``name`` : Name of the function. If this value is not used, ``func.func_name``
|
||||
should exist.
|
||||
``arity``: Arity (number of arguments) of the function. If this value is not
|
||||
used, ``func.arity`` should exist.
|
||||
"""
|
||||
if arity is None:
|
||||
arity = func.arity
|
||||
|
||||
if name is None:
|
||||
name = func.func_name
|
||||
|
||||
return PL_register_foreign(name, arity,
|
||||
cast(_callbackWrapper(arity)(_foreignWrapper(func)),c_void_p), (flags))
|
||||
|
||||
newTermRef = PL_new_term_ref
|
||||
|
||||
def newTermRefs(count):
|
||||
a = PL_new_term_refs(count)
|
||||
return range(a, a + count)
|
||||
|
||||
def call(*terms, **kwargs):
|
||||
"""Call term in module.
|
||||
``term``: a Term or term handle
|
||||
"""
|
||||
for kwarg in kwargs:
|
||||
if kwarg not in ["module"]:
|
||||
raise KeyError
|
||||
|
||||
module = kwargs.get("module", None)
|
||||
|
||||
t = terms[0]
|
||||
for tx in terms[1:]:
|
||||
t = _comma(t, tx)
|
||||
|
||||
return PL_call(t.handle, module)
|
||||
|
||||
def newModule(name):
|
||||
"""Create a new module.
|
||||
``name``: An Atom or a string
|
||||
"""
|
||||
if isinstance(name, basestring):
|
||||
name = Atom(name)
|
||||
|
||||
return PL_new_module(name.handle)
|
||||
|
||||
class Query(object):
|
||||
qid = None
|
||||
fid = None
|
||||
|
||||
def __init__(self, *terms, **kwargs):
|
||||
for key in kwargs:
|
||||
if key not in ["flags", "module"]:
|
||||
raise Exception("Invalid kwarg: %s" % key, key)
|
||||
|
||||
flags = kwargs.get("flags", PL_Q_NODEBUG|PL_Q_CATCH_EXCEPTION)
|
||||
module = kwargs.get("module", None)
|
||||
|
||||
t = terms[0]
|
||||
for tx in terms[1:]:
|
||||
t = _comma(t, tx)
|
||||
|
||||
f = Functor.fromTerm(t)
|
||||
p = PL_pred(f.handle, module)
|
||||
Query.fid = PL_open_foreign_frame()
|
||||
Query.qid = PL_open_query(module, flags, p, f.a0)
|
||||
|
||||
# def __del__(self):
|
||||
# self.closeQuery()
|
||||
|
||||
def nextSolution():
|
||||
return PL_next_solution(Query.qid)
|
||||
|
||||
nextSolution = staticmethod(nextSolution)
|
||||
|
||||
def cutQuery():
|
||||
PL_cut_query(Query.qid)
|
||||
|
||||
cutQuery = staticmethod(cutQuery)
|
||||
|
||||
def closeQuery():
|
||||
if Query.qid is not None:
|
||||
PL_close_query(Query.qid)
|
||||
PL_discard_foreign_frame(Query.fid)
|
||||
Query.qid = None
|
||||
Query.fid = None
|
||||
|
||||
closeQuery = staticmethod(closeQuery)
|
||||
|
||||
|
||||
def _test():
|
||||
#from pyswip.prolog import Prolog
|
||||
#p = Prolog()
|
||||
|
||||
#p = _prolog
|
||||
|
||||
assertz = Functor("assertz")
|
||||
a = Functor("a_")
|
||||
b = Functor("b_")
|
||||
|
||||
call(assertz(a(10)))
|
||||
call(assertz(a([1,2,3])))
|
||||
call(assertz(a(11)))
|
||||
call(assertz(b(11)))
|
||||
call(assertz(b(12)))
|
||||
|
||||
X = Variable()
|
||||
|
||||
#q = Query(a(X), ~b(X))
|
||||
#q = Query(b(X), a(X))
|
||||
#while q.nextSolution():
|
||||
# print X.value
|
||||
#print call(a(X),b(X))
|
||||
#print call(_comma(~a(X),a(X)))
|
||||
#q = Query(_comma(a(X), b(X)))
|
||||
q = Query(a(X))
|
||||
while q.nextSolution():
|
||||
print ">", X.value
|
||||
|
||||
if __name__ == "__main__":
|
||||
_test()
|
||||
|
155
packages/pyswip/pyswip/prolog.py
Normal file
155
packages/pyswip/pyswip/prolog.py
Normal file
@ -0,0 +1,155 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# prolog.py -- Prolog class
|
||||
# (c) 2006-2007 Yüce TEKOL
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301, USA.
|
||||
|
||||
import atexit
|
||||
from pyswip.core import *
|
||||
|
||||
def _initialize():
|
||||
plargs = (c_char_p*3)()
|
||||
plargs[0] = "./"
|
||||
plargs[1] = "-q"
|
||||
plargs[2] = "-nosignals"
|
||||
PL_initialise(3, plargs)
|
||||
swipl_fid = PL_open_foreign_frame()
|
||||
swipl_load = PL_new_term_ref()
|
||||
PL_chars_to_term("asserta((pyrun(GoalString,BindingList):-atom_codes(A,GoalString),atom_to_term(A,Goal,BindingList),call(Goal))).", swipl_load)
|
||||
PL_call(swipl_load, None)
|
||||
PL_discard_foreign_frame(swipl_fid)
|
||||
_initialize()
|
||||
|
||||
def _finalize():
|
||||
PL_halt(0)
|
||||
atexit.register(_finalize)
|
||||
|
||||
from pyswip.easy import getTerm
|
||||
|
||||
class PrologError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
#### Prolog ####
|
||||
class Prolog:
|
||||
"""Easily query SWI-Prolog.
|
||||
This is a singleton class
|
||||
"""
|
||||
class _QueryWrapper(object):
|
||||
__slots__ = "swipl_fid","swipl_qid","error"
|
||||
|
||||
def __init__(self):
|
||||
self.error = False
|
||||
|
||||
def __call__(self, query, maxresult, catcherrors, normalize):
|
||||
plq = catcherrors and (PL_Q_NODEBUG|PL_Q_CATCH_EXCEPTION) or PL_Q_NORMAL
|
||||
self.swipl_fid = PL_open_foreign_frame()
|
||||
swipl_head = PL_new_term_ref()
|
||||
swipl_args = PL_new_term_refs(2)
|
||||
swipl_goalCharList = swipl_args
|
||||
swipl_bindingList = swipl_args + 1
|
||||
|
||||
PL_put_list_chars(swipl_goalCharList, query)
|
||||
|
||||
swipl_predicate = PL_predicate("pyrun", 2, None)
|
||||
self.swipl_qid = swipl_qid = PL_open_query(None, plq,
|
||||
swipl_predicate, swipl_args)
|
||||
while maxresult and PL_next_solution(swipl_qid):
|
||||
maxresult -= 1
|
||||
bindings = []
|
||||
swipl_list = PL_copy_term_ref(swipl_bindingList)
|
||||
t = getTerm(swipl_list)
|
||||
if normalize:
|
||||
try:
|
||||
v = t.value
|
||||
except AttributeError:
|
||||
v = {}
|
||||
for r in [x.value for x in t]:
|
||||
v.update(r)
|
||||
yield v
|
||||
else:
|
||||
yield t
|
||||
|
||||
if PL_exception(self.swipl_qid):
|
||||
self.error = True
|
||||
PL_cut_query(self.swipl_qid)
|
||||
PL_discard_foreign_frame(self.swipl_fid)
|
||||
raise PrologError("".join(["Caused by: '", query, "'."]))
|
||||
|
||||
def __del__(self):
|
||||
if not self.error:
|
||||
PL_close_query(self.swipl_qid)
|
||||
PL_discard_foreign_frame(self.swipl_fid)
|
||||
|
||||
def asserta(cls, assertion, catcherrors=False):
|
||||
cls.query(assertion.join(["asserta((", "))."]), catcherrors=catcherrors).next()
|
||||
|
||||
asserta = classmethod(asserta)
|
||||
|
||||
def assertz(cls, assertion, catcherrors=False):
|
||||
cls.query(assertion.join(["assertz((", "))."]), catcherrors=catcherrors).next()
|
||||
|
||||
assertz = classmethod(assertz)
|
||||
|
||||
def consult(cls, filename, catcherrors=False):
|
||||
cls.query(filename.join(["consult('", "')"]), catcherrors=catcherrors).next()
|
||||
|
||||
consult = classmethod(consult)
|
||||
|
||||
def query(cls, query, maxresult=-1, catcherrors=True, normalize=True):
|
||||
"""Run a prolog query and return a generator.
|
||||
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)")))
|
||||
True
|
||||
>>> bool(list(prolog.query("father(michael,olivia)")))
|
||||
False
|
||||
>>> print sorted(prolog.query("father(michael,X)"))
|
||||
[{'X': 'gina'}, {'X': 'john'}]
|
||||
"""
|
||||
#assert cls.initialized
|
||||
return cls._QueryWrapper()(query, maxresult, catcherrors, normalize)
|
||||
|
||||
query = classmethod(query)
|
||||
|
||||
|
||||
def _test():
|
||||
lines = [("assertz(father(michael,john)).","Michael is the father of John"),
|
||||
("assertz(father(michael,gina)).","Michael is the father of Gina"),
|
||||
("father(michael,john).","Is Michael father of John?"),
|
||||
("father(michael,olivia).","Is Michael father of Olivia?"),
|
||||
("father(michael,X).","Michael is the father of whom?"),
|
||||
("father(X,Y).","Who is the father of whom?")]
|
||||
|
||||
prolog = Prolog()
|
||||
|
||||
for code, comment in lines:
|
||||
print "?-", code, "[", comment, "]"
|
||||
print list(prolog.query(code))
|
||||
|
||||
for r in prolog.query("father(X,Y)"):
|
||||
print r["X"], "is the father of", r["Y"]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
#import doctest
|
||||
#doctest.testmod()
|
||||
_test()
|
||||
|
117
packages/pyswip/setup.py
Normal file
117
packages/pyswip/setup.py
Normal file
@ -0,0 +1,117 @@
|
||||
|
||||
# PySWIP setup script
|
||||
|
||||
import sys
|
||||
import os
|
||||
import os.path
|
||||
from distutils.core import setup
|
||||
|
||||
setup(name="pyswip",
|
||||
version="0.2.2",
|
||||
url="http://code.google.com/p/pyswip/",
|
||||
download_url="http://code.google.com/p/pyswip/downloads/list",
|
||||
author="Yuce Tekol",
|
||||
author_email="yucetekol@gmail.com",
|
||||
description="PySWIP enables querying SWI-Prolog and YAP in your Python programs.",
|
||||
long_description="""
|
||||
PySWIP 0.2.2
|
||||
============
|
||||
|
||||
PySWIP is a GPL'd Python - SWI-Prolog bridge enabling to query SWI-Prolog
|
||||
in your Python programs. It features an (incomplete) SWI-Prolog foreign
|
||||
language interface, a utility class that makes it easy querying with Prolog
|
||||
and also a Pythonic interface.
|
||||
|
||||
Since PySWIP uses SWI-Prolog as a shared library and ctypes to access it,
|
||||
it doesn't require compilation to be installed.
|
||||
|
||||
Note that this version of PySWIP is slightly incompatible with 0.1.x versions.
|
||||
|
||||
Requirements:
|
||||
-------------
|
||||
|
||||
* Python 2.3 and higher.
|
||||
* ctypes 1.0 and higher.
|
||||
* SWI-Prolog 5.6.x and higher (most probably other versions will also work).
|
||||
* libpl as a shared library.
|
||||
* Works on Linux and Win32, should work for all POSIX.
|
||||
|
||||
News
|
||||
----
|
||||
|
||||
* Importing ``pyswip`` automatically initializes SWI-Prolog.
|
||||
* Fixed a bug with querying lists with the new interface.
|
||||
|
||||
Example (Using Prolog):
|
||||
-----------------------
|
||||
|
||||
>>> 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)"):
|
||||
... print soln["X"], "is the father of", soln["Y"]
|
||||
...
|
||||
michael is the father of john
|
||||
michael is the father of gina
|
||||
|
||||
Since version 0.1.3 of PySWIP, it is possible to register a Python function as a Prolog predicate through SWI-Prolog's foreign language interface.
|
||||
|
||||
Example (Foreign Functions):
|
||||
----------------------------
|
||||
|
||||
from pyswip import Prolog, registerForeign
|
||||
|
||||
def hello(t):
|
||||
print "Hello,", t
|
||||
hello.arity = 1
|
||||
|
||||
registerForeign(hello)
|
||||
|
||||
prolog = Prolog()
|
||||
prolog.assertz("father(michael,john)")
|
||||
prolog.assertz("father(michael,gina)")
|
||||
list(prolog.query("father(michael,X), hello(X)"))
|
||||
|
||||
Outputs:
|
||||
Hello, john
|
||||
Hello, gina
|
||||
|
||||
Since version 0.2, PySWIP contains a 'Pythonic' interface which allows writing predicates in pure Python (*Note that interface is experimental.*)
|
||||
|
||||
Example (Pythonic interface):
|
||||
-----------------------------
|
||||
|
||||
from pyswip import Functor, Variable, Query
|
||||
|
||||
assertz = Functor("assertz", 2)
|
||||
father = Functor("father", 2)
|
||||
|
||||
call(assertz(father("michael","john")))
|
||||
call(assertz(father("michael","gina")))
|
||||
|
||||
X = Variable()
|
||||
q = Query(father("michael",X))
|
||||
while q.nextSolution():
|
||||
print "Hello,", X.value
|
||||
|
||||
Outputs:
|
||||
Hello, john
|
||||
Hello, gina
|
||||
""",
|
||||
license="GPL",
|
||||
packages=["pyswip"],
|
||||
classifiers=[
|
||||
'Development Status :: 3 - Alpha',
|
||||
'Intended Audience :: Developers',
|
||||
'Intended Audience :: Science/Research',
|
||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
'Topic :: Scientific/Engineering :: Artificial Intelligence',
|
||||
'Topic :: Software Development :: Libraries :: Python Modules'
|
||||
],
|
||||
)
|
||||
|
Reference in New Issue
Block a user