GithubHelp home page GithubHelp logo

yuce / pyswip Goto Github PK

View Code? Open in Web Editor NEW
444.0 33.0 94.0 364 KB

PySwip is a 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.

License: MIT License

Prolog 0.76% Python 98.84% Makefile 0.25% TeX 0.15%
python prolog swi-prolog artificial-intelligence expert-systems natural-language-processing robotics logic-programming

pyswip's Introduction

PySwip


Installing the Latest Version

The latest SWI-Prolog supported by Ubuntu 18.04 and 20.04 are 7.6.4. We generally want to support LTS releases of Ubuntu. The compatibility of PySwip with 7.6.4 on master is broken, so we are not able to release a new version until this is fixed. In the meantime, you can use the following to install PySwip from the master branch:

pip install git+https://github.com/yuce/pyswip@master#egg=pyswip

The End of Python 2 Support

Python 2 has reached end of life on January 1st, 2020 as documented here. So, PySwip 0.2.10 will be the last version which officially supports Python 2.

Do you still require Python 2 support? Let us know at: #94


What's New?

See the CHANGELOG.

WARNING! PySwip has no Windows installers! If you are a Windows user, see INSTALL. There are some "free download" sites that claim to be hosting PySwip installers. DO NOT TRUST THEM!

Thanks to all contributors.

Introduction

PySwip is a 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.

Requirements:

  • Python 3.6 and higher.
    • PyPy is currently not supported.
  • SWI-Prolog 8.2 and higher.
  • libswipl as a shared library. This is the default on most platforms.
  • Works on Linux, Windows, MacOS and FreeBSD. Should work on other POSIX.

Install

IMPORTANT: Make sure the SWI-Prolog architecture is the same as the Python architecture. If you are using a 64bit build of Python, use a 64bit build of SWI-Prolog, etc.

See INSTALL for instructions.

Examples

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

An existing knowledge base stored in a Prolog file can also be consulted, and queried. Assuming the filename "knowledge_base.pl" and the Python is being run in the same working directory, it is consulted like so:

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

Foreign Functions

from __future__ import print_function
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)")
print(list(prolog.query("father(michael,X), hello(X)")))

Pythonic interface (Experimental)

from __future__ import print_function
from pyswip import Functor, Variable, Query, call

assertz = Functor("assertz", 1)
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.

Help!

Projects/Publications that Use or Reference PySwip

Do you have a project, video or publication that uses/mentions PySwip? file an issue or send a pull request.

If you would like to reference PySwip in a LaTeX document, you can use the provided BibTeX file.

Books

Publications

Videos

Projects

Blog Posts

Companies using PySwip

  • Magazino GmbH Magazino develops and builds intelligent, mobile robots for intralogistics.

License

Copyright (c) 2007-2020 Yüce Tekol and PySwip contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

pyswip's People

Contributors

a-deluna avatar asherbar avatar david-r-cox avatar dylanlukes avatar flijnzaad avatar g-gemignani avatar girib avatar guyzyl avatar ids1024 avatar janwielemaker avatar jspricke avatar lyzardking avatar maxpeltzer avatar mnd avatar mychaos87 avatar paulbrownmagic avatar prologrules avatar rmanhaeve avatar tobiasgrubenmann avatar vakker avatar vorpalblade avatar yankai14 avatar yuce avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyswip's Issues

Interaction problem

I wrote some rules with variables as follows:
situation_mk(obstancle,situation1):-
ts_hasBT(obstancle,BT),
ts_hasRange(obstancle,R),
ts_hasCT(obstancle,CT),
os_hasCO(ownship,CO),
CT=<CO+BT,R=<3.
I hope to be able to assign the value in python to the capital letter variable in the.pl file, I have tried p.assertz can only manually enter each piece of data, can not change according to the incoming variable in real time, may I ask someone has any way to solve it?

Error "undefined symbol: PL_new_atom" when reading files

When reading files, I always get the following error:

python3: symbol lookup error: /usr/lib64/swipl-7.2.3/lib/x86_64-linux/readutil.so: undefined symbol: PL_new_atom

How to reproduce

  1. Copy the following into read.pl

    read_file(Filename, Strings) :-
      setup_call_cleanup(
      open(Filename, read, Stream),
      read_stream_string(Stream, Strings),
      close(Stream)
    ).
    
    read_stream_string(Stream, Strings) :-
      read_line_to_string(Stream, String),
      ( String == end_of_file -> Strings = []
      ;
        read_stream_string(Stream, RStrings),
        Strings = [String|RStrings]
      ).
    
  2. Copy the following to read.py:

    from pyswip.prolog import Prolog
    from pyswip.core import *
    
    prolog = Prolog()
    prolog.consult('read.pl')
    list(prolog.query('read_file("read.pl", S)'))
    
  3. Run python3 read.py, which will produce the output:

    python3: symbol lookup error: /usr/lib64/swipl-7.2.3/lib/x86_64-linux/readutil.so: undefined symbol: PL_new_atom
    

Workaround

PL_new_atom is defined in libswipl.so, but readutil.so is not linked against libswipl. As a workaround, libswipl.so can be LD_PRELOADed:

$ export LD_PRELOAD=/usr/lib64/swipl-7.2.3/lib/x86_64-linux/libswipl.so.7.2.3
$ python3 read.py

After preloading the shared lib, the error disappears (and #9 occurs). This show that this is indeed a problem with linking.

I'm not sure if this is an error on the pyswip side or the swipl side, but I assume if you always load libswipl.so, then the error will disappear.

This is on Fedora 25 with SWi-Prolog 7.2.3.

Segfault when the query variable should be a list

I am working on the Mac OS system with the following setting:

  • SWI-Prolog version 7.6.4 for x86_64-darwin18.2.0
  • pyswip build from source using the refactor branch

I am consulting the file: test_list.pl


incr(X, X1) :-
    X1 is X + 1.

get_list(0, []).

get_list(N1, [N1|Ls]):- 
    get_list(N, Ls),
    incr(N, N1).

and try to fetch the result for get list in python:

from pyswip import Prolog
prolog = Prolog()
prolog.consult("test_list.pl")
solu = prolog.query("get_list(3, X)")
for i in solu:
    print (i)
    break

The result I got is:

python spec_verify.py
{'X': [3, 2, 1]}
fish: 'python spec_verify.py' terminated by signal SIGSEGV (Address boundary error)

Any help is appreciated!

proble with unicode characters

I have a test.pl

aka('peñarol' , 'Penarol').

I can query it in prolog with no problems:

swipl7
Cleaning /usr/local/Cellar/swi-prolog/8.0.3
Cleaning /usr/local/Cellar/swi-prolog/7.6.4_1
6 links created for /usr/local/Cellar/swi-prolog/7.6.4_1
Welcome to SWI-Prolog (threaded, 64 bits, version 7.6.4)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit http://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

1 ?- [test].
true.

2 ?- aka(X,Y).
X = peñarol,
Y = 'Penarol'.

However, we I try to query it in pyswipl I get an error:

ipython                                                                                               .env 
/Users/acortis/.pyenv/versions/3.7.3/lib/python3.7/site-packages/IPython/core/interactiveshell.py:931: UserWarning: Attempting to work in a virtualenv. If you encounter problems, please install IPython inside the virtualenv.
  warn("Attempting to work in a virtualenv. If you encounter problems, please "
Python 3.7.3 (default, Jun  8 2019, 16:41:03)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.6.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import pyswip

In [2]: prolog = pyswip.Prolog()

In [3]: prolog.consult("test.pl")

In [4]: prolog.query("aka(X,Y)")
Out[4]: <generator object Prolog._QueryWrapper.__call__ at 0x10332c390>

In [5]: list(prolog.query("aka(X,Y)"))
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
<ipython-input-5-b2e949838bff> in <module>
----> 1 list(prolog.query("aka(X,Y)"))

~/belmont_codes/data_model/.env/lib/python3.7/site-packages/pyswip/prolog.py in __call__(self, query, maxresult, catcherrors, normalize)
    109                     bindings = []
    110                     swipl_list = PL_copy_term_ref(swipl_bindingList)
--> 111                     t = getTerm(swipl_list)
    112                     if normalize:
    113                         try:

~/belmont_codes/data_model/.env/lib/python3.7/site-packages/pyswip/easy.py in getTerm(t)
    402         res = _getterm_router[p](t)
    403     elif PL_is_list(t):
--> 404         res = getList(t)
    405     else:
    406         res = getFunctor(t)

~/belmont_codes/data_model/.env/lib/python3.7/site-packages/pyswip/easy.py in getList(x)
    418     result = []
    419     while PL_get_list(t, head, t):
--> 420         result.append(getTerm(head))
    421         head = PL_new_term_ref()
    422

~/belmont_codes/data_model/.env/lib/python3.7/site-packages/pyswip/easy.py in getTerm(t)
    404         res = getList(t)
    405     else:
--> 406         res = getFunctor(t)
    407     mappedTerms[t] = res
    408     return res

~/belmont_codes/data_model/.env/lib/python3.7/site-packages/pyswip/easy.py in getFunctor(t)
    427     """Return t as a functor
    428     """
--> 429     return Functor.fromTerm(t)
    430
    431

~/belmont_codes/data_model/.env/lib/python3.7/site-packages/pyswip/easy.py in fromTerm(cls, term)
    252                     args.append(getTerm(a0 + i))
    253
--> 254             return cls(f.value, args=args, a0=a0)
    255     fromTerm = classmethod(fromTerm)
    256

~/belmont_codes/data_model/.env/lib/python3.7/site-packages/pyswip/easy.py in __init__(self, handleOrName, arity, args, a0)
    229             self.arity = PL_functor_arity(self.handle)
    230             try:
--> 231                 self.__value = self.func[self.handle](self.arity, *self.args)
    232             except KeyError:
    233                 self.__value = str(self)

~/belmont_codes/data_model/.env/lib/python3.7/site-packages/pyswip/easy.py in _unifier(arity, *args)
    293     #    args[0].unify(args[1])
    294     try:
--> 295         return {args[0].value:args[1].value}
    296     except AttributeError:
    297         return {args[0].value:args[1]}

~/belmont_codes/data_model/.env/lib/python3.7/site-packages/pyswip/easy.py in get_value(self)
     80         ret = self.chars
     81         if not isinstance(ret, str):
---> 82             ret = ret.decode()
     83         return ret
     84

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf1 in position 2: invalid continuation byte

   ...:     421         head = PL_new_term_ref()

NameError("name 'call' is not defined",)

Hello
I got this error when I ran the 'Pythonic interface (Experimental)' example.
Is it because I am missing something?
Thanks

py3.6
swipl1.6.4

Traceback (most recent call last):
File "D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Extensions\Microsoft\Python\Core\ptvsd_launcher.py", line 111, in
vspd.debug(filename, port_num, debug_id, debug_options, run_as)
File "D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Extensions\Microsoft\Python\Core\Packages\ptvsd\debugger.py", line 36, in debug
run(address, filename, *args, **kwargs)
File "D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Extensions\Microsoft\Python\Core\Packages\ptvsd_main.py", line 47, in run_file
run(argv, addr, **kwargs)
File "D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Extensions\Microsoft\Python\Core\Packages\ptvsd_main.py", line 98, in _run
_pydevd.main()
File "D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Extensions\Microsoft\Python\Core\Packages\ptvsd\pydevd\pydevd.py", line 1628, in main
globals = debugger.run(setup['file'], None, None, is_module)
File "D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Extensions\Microsoft\Python\Core\Packages\ptvsd\pydevd\pydevd.py", line 1035, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\Extensions\Microsoft\Python\Core\Packages\ptvsd\pydevd_pydev_imps_pydev_execfile.py", line 25, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "D:\Project\AI_NLP\AI_NLP\test.py", line 9, in
call(assertz(father("michael","john")))
NameError: name 'call' is not defined

Unification result for Prolog lists with variables recorded incorrectly

Consider the query,

?- L = [1,2 | X]

SWI-Prolog interpreter correctly returns L = [1,2 |X] indicating that L is a list with prefix [1,2]. However, the similar program written using pyswip:

from pyswip import Prolog
prolog = Prolog()
for soln in prolog.query("L = [1,2 | X]"):
    print(soln["L"])

prints [1,2] saying that L is the list [1,2]. It should be [1,2 | X] or similar.

But it does not appear to be a unification issue since the following query unifies correctly, but is still displayed incorrectly:

from pyswip import Prolog
prolog = Prolog()
for soln in prolog.query("L = [1,2 | X], X = [3 | Y]"):
    print(soln["L"])

prints [1,2,3]. It should be [1,2,3 | Y] or similar.

Every time I try to call inside a function I get error

When I do this:
prologGoldList = list(prolog.query("at(gold,pos(X,Y))"))
It works, but when I try to use inside a function

def takeAction():
prologGoldList = list(prolog.query("at(gold,pos(X,Y))"))

It says TypeError: 'list' object is not callable

pyswip test error

ERROR: The system was unable to find the specified registry key or value.
on windows

pyswip ERROR

I tried to install pyswip via Pycharm. It can be installed successfully.

OS: Windows 10 64-bit
IDE: Pycharm 2018.3.2
Language: Python 3.6
Pyswip Version: 0.2.8
I run the test
from pyswip import Prolog
prolog = Prolog()
prolog.assertz("father(michael,john)")

This is my error:
File "C:/Users/anlanxuan/Desktop/prolog test/venv/Include/prologtest.py", line 1, in
from pyswip import Prolog
File "C:\Users\anlanxuan\Desktop\prolog test\venv\lib\site-packages\pyswip_init_.py", line 29, in
from pyswip.prolog import Prolog
File "C:\Users\anlanxuan\Desktop\prolog test\venv\lib\site-packages\pyswip\prolog.py", line 28, in
from pyswip.core import *
File "C:\Users\anlanxuan\Desktop\prolog test\venv\lib\site-packages\pyswip\core.py", line 568, in
(_path, SWI_HOME_DIR) = _findSwipl()
File "C:\Users\anlanxuan\Desktop\prolog test\venv\lib\site-packages\pyswip\core.py", line 411, in _findSwipl
(path, swiHome) = _findSwiplWin()
File "C:\Users\anlanxuan\Desktop\prolog test\venv\lib\site-packages\pyswip\core.py", line 208, in _findSwiplWin
match = pattern.match(ret[-1])
IndexError: list index out of range

query doesn't return tuples correctly

When the result contains tuples, it is not printed correctly.

import pyswip                                                                   
p = pyswip.Prolog()                                                             
p.assertz("parents((michael,mary),peter)")                                      
print(list(p.query("parents(X,peter)"))) 

This returns [{'X': ',(michael, mary)'}] (note the extra comma)
Expected result: [{'X': '(michael, mary)'}]

unit test test_father fails with python2

The unit test test_father fails:

$ cd test
$ ./runtests
............F....
======================================================================
FAIL: test_father (test_examples.TestExamples)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_examples.py", line 137, in test_father
    self.assertEqual(len(result), 1)
AssertionError: 4 != 1

----------------------------------------------------------------------
Ran 17 tests in 5.313s

FAILED (failures=1)

When looking at the result, it contains the same result four times:

[{'Y': 'mich', 'Z': 'jane'}, {'Y': 'mich', 'Z': 'jane'}, {'Y': 'mich', 'Z': 'jane'}, {'Y': 'mich', 'Z': 'jane'}]

This is with commit 72771d9 and SWI-Prolog 7.2.3 on Fedora 25.

Impossible to launch a file without error

Hi,

When I try to run my file like this "python test.py'" I get an error like this:

Traceback (most recent call last): File "test.py", line 1, in <module> from pyswip import Prolog File "/home/thomas/pyswip_env/lib/python3.7/site-packages/pyswip/__init__.py", line 29, in <module> from pyswip.prolog import Prolog File "/home/thomas/pyswip_env/lib/python3.7/site-packages/pyswip/prolog.py", line 28, in <module> from pyswip.core import * File "/home/thomas/pyswip_env/lib/python3.7/site-packages/pyswip/core.py", line 568, in <module> (_path, SWI_HOME_DIR) = _findSwipl() File "/home/thomas/pyswip_env/lib/python3.7/site-packages/pyswip/core.py", line 428, in _findSwipl raise ImportError('Could not find the SWI-Prolog library in this ' ImportError: Could not find the SWI-Prolog library in this platform. If you are sure it is installed, please open an issue.

For information I am on Manjaro and swi-pl is well installed.

Thank you in advance.

importing pyswip goes wrong

I had some Problems setting up pyswip.

I installed the current release with the Windows installer und then used pip to installpyswip.
But when I tried to use it, I got an exeption when importing it.
It was an Index Error, while looking for the swipl installation.
So I debugged - and found out, that the code was looking for a folder named 'pl' instead of 'swipl'.
Maybe there went some letters missing accidentally?
After renaming my folder accordingly, swipl was found.
But the I got another Error: Swipl complained, about being called with an unknown argument.
I fixed that one by changing the agrument '-nosignals' to '--signals=false'.

So, just in case, someone encounters the same problem or is inclined to fixing the code, this ist my story

Android/Termux pyswip error

Hello!
I'm struggling to get pyswip working under Termux on Android. The following is a transcript of my current results. As you can see swipl seems to be called but results in command line options being reported to stdin & exiting python. Could you possibly please help? Maybe you have experience of this? Thank you.

Welcome to Termux!

Wiki: https://wiki.termux.
com
Community forum: https://termux.com/c
ommunity
Gitter chat: https://gitter.im/te
rmux/termux
IRC channel: #termux on freenode

Working with packages:

  • Search packages: pkg search
  • Install a package: pkg install
  • Upgrade packages: pkg upgrade

Subscribing to additional repositorie
s:

  • Root: pkg install root-repo
  • Unstable: pkg install unstable-rep
    o
  • X11: pkg install x11-repo

Report issues at https://termux.com/i
ssues

$ python
Python 3.7.4 (default, Jul 28 2019, 2
2:40:01)
[Clang 8.0.7 (https://android.googles
ource.com/toolchain/clang b55f2d4ebfd
35bf6 on linux
Type "help", "copyright", "credits" o
r "license" for more information.

from pyswip import Prolog
Traceback (most recent call last):
File "", line 1, in
File "/data/data/com.termux/files/u
sr/lib/python3.7/site-packages/pyswip
/init.py", line 29, in
from pyswip.prolog import Prolog
File "/data/data/com.termux/files/u
sr/lib/python3.7/site-packages/pyswip
/prolog.py", line 28, in
from pyswip.core import *
File "/data/data/com.termux/files/u
sr/lib/python3.7/site-packages/pyswip
/core.py", line 568, in
(_path, SWI_HOME_DIR) = _findSwip
l()
File "/data/data/com.termux/files/u
sr/lib/python3.7/site-packages/pyswip
/core.py", line 428, in _findSwipl
raise ImportError('Could not find
the SWI-Prolog library in this '
ImportError: Could not find the SWI-P
rolog library in this platform. If yo
u are sure it is installed, please op
en an issue.

[1]+ Stopped python
$ termux-chroot
$ python
Python 3.7.4 (default, Jul 28 2019, 2
2:40:01)
[Clang 8.0.7 (https://android.googles
ource.com/toolchain/clang b55f2d4ebfd
35bf6 on linux
Type "help", "copyright", "credits" o
r "license" for more information.

from pyswip import Prolog
swipl: Usage:
1) swipl [options] prolog-file ..
. [-- arg ...]
2) swipl [options] [-o executable
] -c prolog-file ...
3) swipl --help Display this
message (also -h)
4) swipl --version Display versi
on information
4) swipl --arch Display archi
tecture
6) swipl --dump-runtime-variables
[=format]
Dump link inf
o in sh(1) format

Options:
-x state Start fr
om state (must be first)
-g goal Run goal
(may be repeated)
-t toplevel Toplevel
goal
-f file User ini
tialisation file
-F file Site ini
tialisation file
-l file Script s
ource file
-s file Script s
ource file
-p alias=path Define f
ile search path 'alias'
-O Optimise
d compilation
--tty[=bool] (Dis)all
ow tty control
--signals[=bool] Do (not)
modify signal handling
--threads[=bool] Do (not)
allow for threads
--debug[=bool] Do (not)
generate debug info
--quiet[=bool] (-q) Do (not)
suppress informational messages
--traditional Disable
extensions of version 7
--home=DIR Use DIR
as SWI-Prolog home
--stack_limit=size[BKMG] Specify
maximum size of Prolog stacks
--table_space=size[BKMG] Specify
maximum size of SLG tables
--shared_table_space=size[BKMG] M
aximum size of shared SLG tables
--pce[=bool] Make the
xpce gui available
--pldoc[=port] Start Pl
Doc server [at port]

Boolean options may be written as --n
ame=bool, --name, --no-name or --nona
me
$

Right output on console but wrong by pyswip.query()

I am using pyswip to play with geoquery dataset.

In [1]: from Prolog import prolog

In [2]: prolog.consult('geobase')
In [3]: prolog.consult('geoquery')
In [4]: list(prolog.query('answer(A,(river(A),loc(A,B),const(B,stateid(california)))).'))

It can get right result with prolog but weired output with pyswip:

Answer = [colorado]
Out[71]: [{'A': Variable(68), 'B': Variable(71)}] 

Atom names changed when querying lists

I'm Using Python 3.7.4, Pyswip from PIP.
There seems to be a problem with Prolog atom names in lists.

Prolog code:

problem(Board) :-
    Board = [black].

Python code:

prolog = Prolog()
prolog.consult("main.pl")
print(list(prolog.query("problem(X)")))

returns:
[{'X': [Atom('413701')]}]

If I change [black]. to black, it works OK.

Add Android/Termux support

Recently, SWI Prolog added Android support using Termux or using LinuxOnAndroid.
Pyswip cannot find the libswipl shared library, as it does not search to the appropriate directories. The libswipl path should be e.g. for Termux, $PREFIX/lib/libswipl.so.

Regards and many thanks,
Theodore

Error "'CArgObject' has no len()" when using Prolog strings

When using Prolog strings in a fact, an error is thrown.

import pyswip
p = pyswip.Prolog()
p.assertz('some_string_fact("abc")')
print(list(p.query('some_string_fact(S)')))

This results in an error:

$ python3 pyswip_string.py 
Traceback (most recent call last):
  File "pyswip_string.py", line 23, in <module>
    print(list(p.query('some_string_fact(S)')))
  File "/usr/lib/python3.5/site-packages/pyswip/prolog.py", line 111, in __call__
    t = getTerm(swipl_list)
  File "/usr/lib/python3.5/site-packages/pyswip/easy.py", line 404, in getTerm
    res = getList(t)
  File "/usr/lib/python3.5/site-packages/pyswip/easy.py", line 420, in getList
    result.append(getTerm(head))
  File "/usr/lib/python3.5/site-packages/pyswip/easy.py", line 406, in getTerm
    res = getFunctor(t)
  File "/usr/lib/python3.5/site-packages/pyswip/easy.py", line 429, in getFunctor
    return Functor.fromTerm(t)
  File "/usr/lib/python3.5/site-packages/pyswip/easy.py", line 252, in fromTerm
    args.append(getTerm(a0 + i))
  File "/usr/lib/python3.5/site-packages/pyswip/easy.py", line 402, in getTerm
    res = _getterm_router[p](t)
  File "/usr/lib/python3.5/site-packages/pyswip/easy.py", line 387, in getString
    if PL_get_string_chars(t, byref(s), byref(slen)):
  File "/usr/lib/python3.5/site-packages/pyswip/core.py", line 555, in check_and_call
    args[i] = list_to_bytes_list(arg)
  File "/usr/lib/python3.5/site-packages/pyswip/core.py", line 487, in list_to_bytes_list
    pList = c_char_p * len(strList)
TypeError: object of type 'CArgObject' has no len()

Expected result: No error, but the unification [{'S': "abc"}]

I'm using SWI-Prolog 7.2.3 on Fedora 25 with pyswip commit 72771d9.

Can't query lists

Hi, this example is working:

from pyswip import Prolog
prolog = Prolog()
prolog.assertz("father(michael,john)")
prolog.assertz("father(michael,gina)")
list(prolog.query("father(michael,X)"))

But if I try the same with a list

from pyswip import Prolog
prolog = Prolog()
prolog.assertz("michael([john,gina])")
list(prolog.query("michael(X)")

The output is:

[{'T': [Atom('333316'), Atom('335364')]}]

Windows 10 import error

Hi, I keep having this issue everytime i import pyswip

Traceback (most recent call last):
  File "bot.py", line 3, in <module>
    from pyswip import Prolog
  File "c:\python\python37-32\lib\site-packages\pyswip\__init__.py", line 29, in <module>
    from pyswip.prolog import Prolog
  File "c:\python\python37-32\lib\site-packages\pyswip\prolog.py", line 28, in <module>
    from pyswip.core import *
  File "c:\python\python37-32\lib\site-packages\pyswip\core.py", line 573, in <module>
    _lib = CDLL(_path, mode=RTLD_GLOBAL)
  File "c:\python\python37-32\lib\ctypes\__init__.py", line 356, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 193] %1 is not a valid Win32 application

Please help!

Import on Fedora 29 fails

I have trouble importing pyswip on Fedora.
When I run

from pyswip import Prolog

I get the error message
ImportError: Could not find the SWI-Prolog library in this platform. If you are sure it is installed, please open an issue.

The problem seems to be that there are two libswipl.so files found in the lib folder of the installation: libswipl.so.7.6.4, and a symlink libswipl.so.7.6 to the former.
That's why the glob command in pyswip/core.py at line 145 gets two results, and the variable fullName is therefore set to None (line 151).
The easiest workaround would probably be to change the code in core.py (line 146-151) from

if len(files) == 0:
    fullName = None
elif len(files) == 1:
    fullName = files[0]
else:  # Will this ever happen?
    fullName = None

to

if len(files) == 0:
    fullName = None
else:
    fullName = files[0]

In a foreign function, how do I unify an 'input' Variable with a list?

I have switched to the refactor branch in the meantime.

Now I want to write a function like this:

def my_function(input_var, output_var):
# compute some list of values based on input_var

'assign' / unify this list with output_var, such that it is accessible from within prolog.

return True

Prolog.register(my_function)

I managed, somehow dirty, to assign a list value to output_var._value, which is probably wrong, and which did not pass the value to output_var such that it was accessible.

Is what I want to do possible?

Thanks,
Christoph

Cant import

I got a problem when using ‘pyswip'. Maybe the function re.search miss an argument(‘swi_ver’) ? Is it necessary to input the version of swi-prolog? It never happened to me before.
image
image

pyswip on latest swi-prolog prints --help message

I built the latest swi-prolog version, and pyswip cannot import it succesfully, instead printing the swipl --help cli message.
The SWI_HOME and .so path are set succesfully (from a bit of print debug I tested).
The prolog code works, and the previous version I built worked with pyswip.

Type error when lib.exception is raised

I have met such a problem when I am working on a certain dataset:

<generator object Prolog._query_wrapper at 0x1060ffa20>
Traceback (most recent call last):
  File "spec_lib.py", line 46, in <module>
    print(f"should be false: {get_label_permanance(object_id, label2)}" )
  File "spec_lib.py", line 36, in get_label_permanance
    return is_fact(solu)
  File "spec_lib.py", line 19, in is_fact
    return (not is_empty(solu))
  File "spec_lib.py", line 13, in is_empty
    for item in generator:
  File "/Users/jianihuang/anaconda3/lib/python3.7/site-packages/pyswip-0.9.0-py3.7.egg/pyswip/prolog.py", line 210, in _query_wrapper
TypeError: exceptions must derive from BaseException

In prolog.py, line 210: raise term.norm_value, after I changed it to return term.norm_value, the error is fixed, and the expected answer is obtained. Hope this is useful to someone who met the problem.

unload_file behavior differs from prolog.

It seems I can use pyswip to load a .pl, but not unload one: [update]

from pyswip import Prolog
prolog = Prolog()

filename = "f"  # # f.pl contains just       foo(1,1).

next(prolog.query(filename.join(["load_files('", "',[])"])))
print(list(prolog.query("foo(X,1)")))  # ==> [{X:1}]

query = "unload_file('{}')".format(filename)
print(query)
next(prolog.query(query))

print(list(prolog.query("foo(X,1)")))  # ==> [{X:1}] -- should have failed with missing 'f'

The behavior I get from Prolog is:

?- load_files(f,[]).
true.

?- foo(X,1).
X = 1.

?- unload_file(f).    .
true.

?- foo(X,1).
ERROR: Undefined procedure: foo/2 (DWIM could not correct goal)

Is the different behavior here a bug? (I'd like to load and unload files to keep unit tests independent in Python).

No Support for Dictionaries

from pyswip import Prolog
prolog = Prolog()
list(prolog.query('Customer = customer{age: 26, name: jodie}'))

The output is

[{'Customer': 'dict(customer, jodie, name, 26, age)'}]

This behavior does not match Prolog's. In the SWI-Prolog terminal, the query

Customer = customer{age: 26, name: jodie}.

yields the result

Customer = customer{age:26, name:jodie}.

what features are missing?

Hi @yuce,

Glad to see that this project is still active! I used it briefly a couple of years back. I am wondering, what does "incomplete" stand for in the description of the project? Is there a list somewhere of missing features or a description of what is currently not possible with pyswip? I am thinking of using it in a bigger project, but would be nice to know beforehand the missing features.

Cheers!

readme error

at the last example, "Example (Pythonic interface)":

assertz = Functor("assertz", 2) should be assertz = Functor("assertz", 1)

2 Swi-prolog version regex errors

>>> from pyswip import Prolog
>>> prolog = Prolog()
>>> prolog.assertz("father(michael,john)")
Please enter you SWI-Prolog version in format "X.Y.Z": 8.1.15
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-629572b3dbd4> in <module>
----> 1 from pyswip import Prolog
      2 prolog = Prolog()
      3 prolog.assertz("father(michael,john)")

~/new_terminal_python/lib/python3.7/site-packages/pyswip/__init__.py in <module>
     27 __VERSION__ = "0.2.7"
     28 
---> 29 from pyswip.prolog import Prolog
     30 from pyswip.easy import *

~/new_terminal_python/lib/python3.7/site-packages/pyswip/prolog.py in <module>
     26 import sys
     27 
---> 28 from pyswip.core import *
     29 
     30 

~/new_terminal_python/lib/python3.7/site-packages/pyswip/core.py in <module>
    566 # Find the path and resource file. SWI_HOME_DIR shall be treated as a constant
    567 # by users of this module
--> 568 (_path, SWI_HOME_DIR) = _findSwipl()
    569 _fixWindowsPath(_path)
    570 

~/new_terminal_python/lib/python3.7/site-packages/pyswip/core.py in _findSwipl()
    418 
    419         if path is None:
--> 420             (path, swiHome) = _findSwiplMacOSHome()
    421 
    422     else:

~/new_terminal_python/lib/python3.7/site-packages/pyswip/core.py in _findSwiplMacOSHome()
    340             path = os.environ.get('PLBASE')
    341             if path is None:
--> 342                 swi_ver = get_swi_ver()
    343                 path = '/Applications/SWI-Prolog.app/Contents/swipl-' + swi_ver + '/lib/'
    344 

~/new_terminal_python/lib/python3.7/site-packages/pyswip/core.py in get_swi_ver()
    308     swi_ver = input(
    309                 'Please enter you SWI-Prolog version in format "X.Y.Z": ')
--> 310     match = re.search(r'[0-9]\.[0-9]\.[0-9]')
    311     if match is None:
    312         raise InputError('Error, type normal version')

TypeError: search() missing 1 required positional argument: 'string'

First error is this thing above, that the input has to be passed to the re.search as the second argument. Second error is that the regex needs to capture more than one digit on the version numbers with a + after each [0-9].

table not supported?

Tabling was introduced in SWI 8. It doesn't seem possible to make use of it except through consult:

prolog = Prolog()
if 1:
    prolog.consult("fib.pl")
else:
    prolog.assertz(":- table fib2/2")
    prolog.assertz("fib2(0, 1) :- !")
    prolog.assertz("fib2(1, 1) :- !")
    prolog.assertz("fib(N, F) :- N > 1, N1 is N-1, N2 is N-2, fib(N1, F1), fib(N2, F2), F is F1+F2")

t = time.time()
print(list(prolog.query("fib2(35, F)"))[0]["F"])
print(f"{time.time()-t} seconds")  # 3.3s without tabling   /  0.00075864s with

The non-consult path takes 3.3 seconds (tabling not activated).

Latest version doesn't seem to work in Windows with Python 2.7

If I install from an old (2012) installer, I can run a simple test program with Python 2.7. However, if I remove that and install the most recent from the console using

python -m pip install pyswip

...the package seems to be put in place correctly but the program no longer runs:

File "C:\Python27\lib\site-packages\pyswip\prolog.py", line 111, in call
t = getTerm(swipl_list)
File "C:\Python27\lib\site-packages\pyswip\easy.py", line 404, in getTerm
res = getList(t)
File "C:\Python27\lib\site-packages\pyswip\easy.py", line 420, in getList
result.append(getTerm(head))
File "C:\Python27\lib\site-packages\pyswip\easy.py", line 406, in getTerm
res = getFunctor(t)
File "C:\Python27\lib\site-packages\pyswip\easy.py", line 429, in getFunctor
return Functor.fromTerm(t)
File "C:\Python27\lib\site-packages\pyswip\easy.py", line 241, in fromTerm
raise ArgumentTypeError((str(Term), str(int)), str(type(term)))
pyswip.easy.ArgumentTypeError: Expected an argument of type '("<class 'pyswip.easy.Term'>", "<type 'int'>")' but got '<type 'long'>'

Did I somehow bugger things up by leaving something in place from the original install? (If I switch again by removing the newer version and then executing the old installer again, it works.)

EDIT: Repro'd the same problem on a different machine, this time without having initially used the installer exe.

yes/no check

Hello,

I tried the readme example and it works fine

from pyswip import Functor, Variable, Query, call
from pyswip import Prolog
prolog = Prolog()
prolog.assertz("father(michael,john)")
prolog.assertz("father(michael,gina)")
assert list(prolog.query("father(michael,X)")) == [{'X': 'john'}, {'X': 'gina'}]

However, I am not sure how the simpler query, which should return yes, works.

In [16]: list(prolog.query("father(michael,gina)"))
Out[16]: [{}]

Could you please clarify how this should work? Thanks, Andrea

Incoming variable problem

Hello, my purpose is to generate data through python and pass these data into Prolog for regular query, but I don't know how to pass these data into Prolog through pyswip for instantiation. Is there any method that can guide me?

INSTALL instructions on windows

The INSTALL doc says to install on windows:

Get a Windows installer version of PySWIP and install it.

But I couldn't find a windows installer version anywhere.

This appears to work: Cloning the repo and running:

py -3 setup.py install

Is it that simple or should I be worried about something?

Thanks for a great project btw! So great to have Prolog in python.

Error when importing PySwip

I get this error whenever I try to run from pyswip import Prolog

>>> from pyswip import Prolog
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyswip/__init__.py", line 29, in <module>
    from pyswip.prolog import Prolog
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyswip/prolog.py", line 28, in <module>
    from pyswip.core import *
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyswip/core.py", line 568, in <module>
    (_path, SWI_HOME_DIR) = _findSwipl()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyswip/core.py", line 417, in _findSwipl
    (path, swiHome) = _findSwiplDar()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyswip/core.py", line 371, in _findSwiplDar
    (path, swiHome) = _findSwiplFromExec()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyswip/core.py", line 93, in _findSwiplFromExec
    rtvars = dict((name, value[1:-1]) for name, value in ret) # [1:-1] gets
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyswip/core.py", line 93, in <genexpr>
    rtvars = dict((name, value[1:-1]) for name, value in ret) # [1:-1] gets
ValueError: not enough values to unpack (expected 2, got 1)

I use Prolog 7.6.4
Python 3.8
and macOS

TypeError: cannot use a string pattern on a bytes-like object in python 3.6 on win7

Hi,

Installing pyswip on windows7 via pip or from the repo gives this error on import:

core.py, line 208, in _findSwiplWin
    match = pattern.match(ret[-1])
TypeError: cannot use a string pattern on a bytes-like object

I believe this is because str->bytes handling has changed slightly. Decoding the string before this
match appears to fix the issue:


diff --git a/pyswip/core.py b/pyswip/core.py
index 11ffe79..c1090e1 100644
--- a/pyswip/core.py
+++ b/pyswip/core.py
@@ -203,7 +203,7 @@ def _findSwiplWin():
         #    home        REG_SZ  C:\Program Files\pl
         # (Note: spaces may be \t or spaces in the output)
         ret = ret[0].splitlines()
-        ret = [line for line in ret if len(line) > 0]
+        ret = [line.decode("utf-8") for line in ret if len(line) > 0]
         pattern = re.compile('[^h]*home[^R]*REG_SZ( |\t)*(.*)$')
         match = pattern.match(ret[-1])
         if match is not None:

[patch attached as txt file]

decode_fix_for_py36.txt

Pyswip and thread

Hello,

I think there is a segmentation fault error when pyswip is used in a thread. Here is a simple code to reproduce the error:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import threading
import pyswip

class MyThread(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        p = pyswip.Prolog()
        p.assertz('animal(dog)')
        p.query('animal(X)')


t = MyThread()
t.start()
t.join()

When I debug the program, the segmentation fault error occurs at this line (prolog.py, line 91):
swipl_fid = PL_open_foreign_frame()

Regards,
Bartholomew.

pip pyswip version low

pip install pyswip
from pyswip import *
SWI-Prolog not installed as a shared library. Install SWI-Prolog (5.6.34 works just fine)
core.py not use find_library
use github code success

Tests break on current build

I'm getting consistent failures on many tests in the current build. If I back out the changes from your last commit, they are fixed.

Here's an example from tests/test_foreign.py:

ERROR: atom_chars/2: Arguments are not sufficiently instantiated
EE

ERROR: test_deterministic_foreign (main.MyTestCase)

Traceback (most recent call last):
File "/Users/ericzinda/Enlistments/pyswip/tests/test_foreign.py", line 16, in test_deterministic_foreign
prolog.assertz("father(michael,john)")
File "/Users/ericzinda/Enlistments/pyswip/pyswip/prolog.py", line 140, in assertz
next(cls.query(assertion.join(["assertz((", "))."]), catcherrors=catcherrors))
File "/Users/ericzinda/Enlistments/pyswip/pyswip/prolog.py", line 126, in call
raise PrologError("".join(["Caused by: '", query, "'. ",
pyswip.prolog.PrologError: Caused by: 'assertz((father(michael,john))).'. Returned: 'error(instantiation_error, context(:(system, /(atom_chars, 2)), Variable(72)))'.

======================================================================
ERROR: test_nondeterministic_foreign (main.MyTestCase)

Traceback (most recent call last):
File "/Users/ericzinda/Enlistments/pyswip/tests/test_foreign.py", line 44, in test_nondeterministic_foreign
result = list(prolog.query("nondet(X)"))
File "/Users/ericzinda/Enlistments/pyswip/pyswip/prolog.py", line 126, in call
raise PrologError("".join(["Caused by: '", query, "'. ",
pyswip.prolog.PrologError: Caused by: 'nondet(X)'. Returned: 'error(instantiation_error, context(:(system, /($c_call_prolog, 0)), Variable(72)))'.


Ran 2 tests in 0.003s

FAILED (errors=2)

Can i have two Prolog instances simultaneously?

From looking at the code it seems like Prolog is started when the library is imported.
Is that necessary? For me this library would only be useful if I could start/stop Prolog processes at will.

can't query lists

res = list(prolog.query("combination(%d, %s, L)" % (2,"[1,2]")))
res = list(prolog.query("combination(2, [1,2], L)"))
Both will throw an exception
Traceback (most recent call last):
File "test.py", line 12, in
res = list(prolog.query("combination(2, [1,2], L)"))
File "F:\Python27\lib\site-packages\pyswip\prolog.py", line 111, in call
t = getTerm(swipl_list)
File "F:\Python27\lib\site-packages\pyswip\easy.py", line 404, in getTerm
res = getList(t)
File "F:\Python27\lib\site-packages\pyswip\easy.py", line 420, in getList
result.append(getTerm(head))
File "F:\Python27\lib\site-packages\pyswip\easy.py", line 406, in getTerm
res = getFunctor(t)
File "F:\Python27\lib\site-packages\pyswip\easy.py", line 429, in getFunctor
return Functor.fromTerm(t)
File "F:\Python27\lib\site-packages\pyswip\easy.py", line 241, in fromTerm
raise ArgumentTypeError((str(Term), str(int)), str(type(term)))
pyswip.easy.ArgumentTypeError: Expected an argument of type '("<class 'pyswip.easy.Term'>", "<type 'int'>")' but got '<type 'long'>'

If I change [1,2] to a normal string like "abc", it won't throw any exceptions.
my environment is
python 2.7.13
newest version pyswip
prolog 8.0.2

Non-deterministic foreign functions

Hi

Is there already support for non-deterministic foreign functions? Passing the PL_FA_NONDETERMINISTIC flag to registerForeign doesn't seem to have any impact.

Kind regards,
Robin

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.