Prolog - Assert into a new database - prolog

:-dynamic listofQuestions/2.
myrule:-
write('P = '), write(Percent), write('-'),write(X),
( listofQuestions(Percent,X) -> true ; assert(listofQuestions(Percent,X)) ),
The code snippet might not be required to answer my question.
I want to assert to a blank 'listofQuestions' everytime I call my rule. This only happens if I close my prolog window and restart it.
Any suggestions?

abolish/1 removes all clauses of a given predicate from the database. Hence, just add a call to abolish(PredName/Arity) whenever you need to remove the information about this predicate. Beware that after abolishing the call to the dynamic predicate does not fail but reports an error.
12 ?- f(X,Y).
false.
13 ?- assert(f(a,b)).
true.
14 ?- f(X,Y).
X = a,
Y = b.
15 ?- abolish(f/2).
true.
16 ?- f(X,Y).
ERROR: user://2:67:
toplevel: Undefined procedure: f/2 (DWIM could not correct goal)
In SWI-Prolog, abolish works on static procedures, unless the prolog flag iso is set to true. If you intend to remove only dynamic predicates, you should better try retractall. Observe that in this case removal does not lead to an error being reported but to a failure.
17 ?- [user].
:- dynamic f/2.
|:
% user://3 compiled 0.00 sec, 264 bytes
true.
18 ?- f(X,Y).
false.
19 ?- assert(f(a,b)).
true.
20 ?- f(X,Y).
X = a,
Y = b.
21 ?- retractall(f(X,Y)).
true.
22 ?- f(X,Y).
false.

Related

Prolog argument mode indicator causes output false

I am trying to use Prolog's argument mode indicators in the signature of my method (https://www.swi-prolog.org/pldoc/man?section=argmode).
Without the indicators, my function works as expected (eg. palindrome([1,2,1]) gives true):
palindrome(List) :-
reverse(List, List)
But when I say
palindrome(+List) :-
reverse(List, List)
I get false every time. I don't get any errors or warnings. I also tried the following but had no luck:
palindrome(+List) :-
reverse(+List, +List)
So I'm pretty sure I am using these indicators wrong somehow. Can anyone help? I am using SWI-Prolog and the SWISH online IDE.
Yes, wrong. You shouldn't be using them at all, in the code. Only in the comments.
+ is interpreted as a separate token:
6 ?- atom(+X).
false.
7 ?- +X =.. Z.
Z = [+, X].
8 ?- +X = + X.
true.
9 ?- +X = '+'(X).
true.
You could use the +-using predicate definition as you show, but it's rather pointless:
14 ?- [user].
bar(+X,+X).
|:
true.
15 ?- bar( + 1, +Z).
Z = 1.
There are languages that do let us declare the modes, like I think Mercury does. But not Prolog. In Prolog we only use this as comments, to guide our use and understanding of the code.

SWI Prolog Database

is there a way I can query a SWI Prolog database to check if it doesn't contain an element?
I have tried using "not" but doesn't seem to work with this version of Prolog.
maybe you're looking for clause/2. A dummy session sample
1 ?- [user].
|: a(1).
|: a(2).
|: a(X) :- b(X).
|: b(3).
|: b(4).
% user://1 compiled 0.03 sec, 6 clauses
true.
2 ?- clause(a(X),Body).
X = 1,
Body = true ;
X = 2,
Body = true ;
Body = b(X).
3 ?- clause(b(X),Body).
X = 3,
Body = true ;
X = 4,
Body = true.
4 ?- clause(c(X),Body).
false.
you can see that c/1 is not defined...
Anyway, SWi-Prolog database is a complex beast, and it offers much more control about its contents.

Unification of expanded terms, double negation

I need to introduce a predicate that will let me negate atoms. So far I have neg(Premise) :- \+ Premise., which gives me following results:
?- assert(a).
true.
?- a.
true.
?- neg(a).
false.
?- neg(neg(a)).
true.
That makes sense and all is dandy, until I tried unification. For instance
[a,_] = [a,123]. returns true.
while
[a,_] = [neg(neg(a)),123]. returns false..
How can I solve this so that the neg(neg(X)) part is being evaluated or otherwise unified with X (since they both are logically equivalent)? So basically, I need X=neg(a), a=neg(X). to succeed.
Edit I found an explanation as to why not(not(<expression>)) is not equivalent to <expression> in prolog. Since <expression> succeeds, not(<expression>) fails. When a goal fails the variables it instantiated get uninstantiated. (source, slide 14).
I'm still not sure how to get around this though.
Reification of truth value will work on your simple case:
4 ?- [user].
|: reify(P, V) :- call(P) -> V = 1 ; V = 0.
% user://1 compiled 0.03 sec, 2 clauses
true.
5 ?- reify(true, V), reify(\+ \+ true, U), V = U.
V = U, U = 1.
using your symbols:
6 ?- [user].
|: a.
|: neg(P) :- \+ P.
% user://2 compiled 0.02 sec, 3 clauses
true.
7 ?- reify(a, V), reify(neg(neg(a)), U), V = U.
V = U, U = 1.
not sure how well this will merge with your code.

Prolog Beginner: Trivial Example that I cannot get to work.

I have some prolog. The lessThanTen and example predicates work as expected however the exam predicate does not work.
lessThanTen(9).
lessThanTen(8).
lessThanTen(7).
lessThanTen(6).
lessThanTen(5).
lessThanTen(4).
lessThanTen(3).
lessThanTen(2).
lessThanTen(1).
lessThanTen(0).
% This should always return 5.
example(X) :-
X is 5.
% This should return all values that are less than ten.
exam(X) :-
X is lessThanTen(Y).
Here is the output:
% swipl
...
?- [addv1].
Warning: /.../addv1.pl:17:
Singleton variables: [Y]
% addv1 compiled 0.00 sec, 1,484 bytes
true.
?- lessThanTen(X).
X = 9 ;
X = 8 ;
X = 7 ;
...
?- example(X).
X = 5.
?- exam(X).
ERROR: is/2: Arithmetic: `lessThanTen/1' is not a function
?- exam(5).
ERROR: is/2: Arithmetic: `lessThanTen/1' is not a function
I am thinking that the warning I am getting is pretty key.
The is operator expects its right-hand argument - your lessThanTen(Y) - to be an arithmetic expression. It, of course, isn't.
Also, exam/1 just looks wrong: what's Y? The clause takes a single argument X.
lessThanTen(9).
lessThanTen(8).
lessThanTen(7).
lessThanTen(6).
lessThanTen(5).
lessThanTen(4).
lessThanTen(3).
lessThanTen(2).
lessThanTen(1).
lessThanTen(0).
example(X) :-
X is 5.
exam(X) :-
lessThanTen(X).

Prolog - ASSERT and RETRACT

I was wondering, I am aware you can use assert to add facts or rules or whatever if you have declared the predicate to be -:dynamic, but this only allows the changes that are made to be kept in that session only, e.g. if you close the Prolog window then the database changes are lost.
So I was wondering, is there any way of making it so that the assert and retract predicates can make permanent changes to the Prolog .pl file?
Thanks
I can suggest you a very simple way of doing this.
1 ?- assert(a(1)).
true.
2 ?- assert(a(2)).
true.
3 ?- assert(a(3)).
true.
4 ?- a(A).
A = 1 ;
A = 2 ;
A = 3.
5 ?- tell('a_db.txt'), listing(a), told.
true.
Then close session, reopen.
1 ?- a(A).
ERROR: toplevel: Undefined procedure: a/1 (DWIM could not correct goal)
2 ?- ['a_db.txt'].
% a_db.txt compiled 0.00 sec, 516 bytes
true.
3 ?- a(A).
A = 1 ;
A = 2 ;
A = 3.
4 ?- listing(a).
:- dynamic a/1.
a(1).
a(2).
a(3).
true.

Resources