SWI-Prolog - Fail to Assert - prolog

I define an operator as follows:
:- op(500, xfx, =>).
When I try something like:
assert(a => b).
Prolog raises an error that says 'No permission to modify static_procedure (=>)/2'.
Any solution?

As a security, you have to warn SWI that you are going to modify a predicate at runtime:
:- dynamic (=>)/2.
put at the top of the file should do it.

You must have meant another symbol in place of (=>)/2. Probably (->)/2 which is a control construct that cannot be modified.
Welcome to SWI-Prolog (Multi-threaded, 32 bits, Version 6.1.3-116-gf1c7e06)
...
?- asserta((a -> b)).
ERROR: asserta/1: No permission to modify static procedure `(->)/2'
ERROR: Defined at /opt/gupu/pl-devel/lib/swipl-6.1.3/boot/init.pl:194
?- op(500, xfx, =>).
true.
?- asserta(a => b).
true.

Related

Separating Knowledge Base from Predicates, get "undefined procedure"

Why isn't father/2 recognized and why can't I load a file that calls father/2?
theogony.pl
father(kronos, zeus).
father(zeus, ares).
mythos.pl
consult('theogony.pl').
%% --
%% X is an ancestor of Y
%% --
ancestor(X,Y) :-
father(X,Y).
ancestor(X,Y) :-
ancestor(X,Z),
ancestor(Z,Y).
swipl
?- consult('mythos.pl').
false.
?- consult('theogony.pl').
true.
?- father(X,zeus).
ERROR: Unknown procedure: father/2 (DWIM could not correct goal)
As noted there are two Prolog files with the file type pl. This code works with both files in the same directory, e.g. 'C:/Users/Groot/Example_01'. You can use another directory but be consistent with the directory name.
Directory: 'C:/Users/Groot/Example_01'
File: 'theogony.pl'
:- module(theogony,
[
father/2
]).
father(kronos, zeus).
father(zeus, ares).
Directory: 'C:/Users/Groot/Example_01'
File: 'mythos.pl'
:- module(mythos,
[
ancestor/2
]).
ancestor(X,Y) :-
father(X,Y).
ancestor(X,Y) :-
ancestor(X,Z),
ancestor(Z,Y).
Start SWI-Prolog
Welcome to SWI-Prolog (threaded, 64 bits, version 8.5.15)
...
?-
I know, there is a newer version but this is so basic even the really old versions should work.
Change the working directory.
?- working_directory(_,'C:/Users/Groot/Example_01').
true.
Use consult which is also done using [] to load the Prolog files.
?- [theogony].
true.
?- [mythos].
true.
Run your query.
?- father(X,zeus).
X = kronos.

How to use assert and retract in SWI-Prolog

In SWI-Prolog, if I use assert and retract at the prompt, I get
?- assert(at(1)).
true.
?- retract(at(1)).
true.
However, if I put these statements into a program file called "test" as
assert(at(1)).
retract(at(1)).
and run SWI-Prolog as
> swipl
?- [test].
I get
ERROR: /....../test:2:
No permission to modify static procedure `retract/1'
true.
What does this mean and how should I deal with it?
Put statements within a predicate, e.g.:
:- dynamic at/1.
test_assert :-
assert(at(1)).
test_retract :-
retract(at(1)).
Load the program, and then run:
?- test_assert.
true.
?- at(X).
X = 1.
?- test_retract.
true.
?- at(X).
false.
The prompt and source code files are different environments with slightly different behaviours. It's like the difference between calling Python len(x) in the repl and writing function len(x): in Python source code - you would be overriding the builtin len() with your own one. Python lets you do that, SWI Prolog also does but not easily.
When you type them at the prompt, you call the existing predicate assert/1 and actually do insert the fact at(1). into the database. When you type retract/1 you actually do retract the fact at(1) from the database.
In a fresh prompt, try ?- listing(at). and get an error, then ?- assert(at(1)). then do the listing again and see the fact, then retract it and try the listing and see only the remains of the dynamic declaration and the fact is gone.
When you put them in a source code file, you would be trying to override the existing builtin predicates with your new ones. Your new ones say "assert/1 is a predicate which succeeds when its arugment unifies with at(1)" and "retract/1 is a predicate which succeeds when its arugment unifies with at(1)".
That is, they don't do any asserting or retracting or database changes.
In your test file, put this:
:- redefine_system_predicate(assert(_)).
:- redefine_system_predicate(retract(_)).
assert(at(1)) :- true.
retract(at(1)) :- true.
Then save and consult it:
?- [testing].
true.
?- listing(at). % <-- your code ran, but did not insert `at(1)`.
ERROR: procedure `at' does not exist (DWIM could not correct goal)
^ Exception: (13) setup_call_catcher_cleanup(system:true, prolog_listing:listing_(user:at, []), _19450, prolog_listing:close_sources) ? abort
% Execution Aborted
?- assert(P). % <-- it's now behaving
P = at(1). % <-- like any other predicate.

Outputting prolog in Mac

I have a problem using prolog on a Mac, I figured out how to run it using SWI-Prolog but when I run it, it gives an error and does not give the expected output
Expected output: homer, bart
male(homer).
male(bart).
female(marge).
female(lisa).
female(maggie).
parent(homer, bart).
parent(homer, lisa).
parent(homer, maggie).
parent(marge, bart).
parent(marge, lisa).
parent(marge, maggie).
mother(X, Y) :- parent(X, Y), female(X).
father(X, Y) :- parent(X, Y), male(X).
son(X, Y) :- parent(Y, X), male(X).
daughter(X, Y) :- parent(Y, X), female(X).
?- male(X).
Here is the error I was speaking about earlier
Warning: /Users/[username]/Desktop/simpsons.pl:19:
Warning: Singleton variables: [X]
true.
And instead of outputting homer, bart it outputs true
When programming in Prolog, you put definitions and queries in different places. Definitions go into source files. Queries do not go into source files. You enter them while interacting with the Prolog system in something called the "toplevel" or "prompt" or "shell" or maybe "REPL" (read-eval-print loop).
For example, these are definitions:
male(homer).
male(bart).
female(marge).
female(lisa).
female(maggie).
You have put them in a source file called simpsons.pl. This is correct.
This is not a definition but a query:
?- male(X).
This does not go in a source file. Do not put it in simpsons.pl. Rather, you:
start your Prolog system
load the simpsons.pl file somehow
enter the query male(X). and observe answers
This video: https://www.youtube.com/watch?v=t6L7O7KiE-Q shows these steps with SWI-Prolog on a Mac.
If you are comfortable using a command line, you might also be able to do this simpler. For example, on my (Linux) machine, I can start SWI-Prolog with a command line argument naming a file to be loaded:
$ swipl simpsons.pl
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).
?-
See that ?-? That is the prompt meaning that the toplevel is now waiting for your input. Here is where you enter your male(X) query. You can use ; or Space to cycle through the various answers:
?- male(X).
X = homer ;
X = bart.

Unable to use user-defined operator in Prolog

I've been stuck for quite some time on this issue, my Prolog program has the following line within its operator definitions:
:- op(100, xfx, [has,gives,'does not',eats,lays,isa]).
and then this fact:
fact :: X isa animal :-
member(X, [cheetah,tiger,giraffe,zebra,ostrich,penguin, albatross]).
When I try to use the operator It says it is undefined and I just do not understand why.
?- peter isa tiger.
ERROR: [Thread pdt_console_client_0_Default Process] toplevel: Undefined
procedure: (isa)/2 (DWIM could not correct goal)
Sorry if its something silly (which it probably is) but I am new to Prolog. Any help is much appreciated.
It is working. See for yourself:
stefan#stefan-Lenovo-G510 ~ $ swipl
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.12)
% ...
?- op(100, xfx, [has,gives,'does not',eats,lays,isa]).
true.
?- Term = (peter isa tiger).
Term = peter isa tiger.
The error message that you got ...
procedure: (isa)/2 (DWIM could not correct goal)
... says that too!
Is it clearer now?

Prolog error in sample code

I was reading a book about prolog and tried pasting their sample code to see how it would work and I get errors. What's wrong with this code.
path(X,Y)←
path(X,Y,[X]).
path(X,X,Visited).
path(X,Z,Visited)←
edge(X,Y),
not member(Y,Visited),
path(Y,Z,[Y|Visited]).
member(X,[X|Y]).
member(X,[Y|Z])←
member(X,Z)
in SWI-Prolog, the following declarations make your code compilable
:- op(1200, xfx, ←).
:- op(900, fy, not).
:- multifile term_expansion/2.
term_expansion((H←B), (H:-B)).
term_expansion((not B), (\+ B)).
path(X,Y)←
path(X,Y,[X]).
path(X,X,Visited).
path(X,Z,Visited)←
edge(X,Y),
not member(Y,Visited),
path(Y,Z,[Y|Visited]).
member(X,[X|Y]).
member(X,[Y|Z])←
member(X,Z).
there are some warnings about singletons, and you're missing the final dot... I provided it

Resources