Prolog - is the following query satisfied? - prolog

I am doing exercise from the following link
Here is knowledge base:
house_elf(dobby).
witch(hermione).
witch(’McGonagall’).
witch(rita_skeeter).
magic(X):- house_elf(X).
magic(X):- wizard(X).
magic(X):- witch(X).
I am expecting the following query to return true:
?- magic(’McGonagall’).
However, my SWI-Prolog (AMD64, Multi-threaded, version 7.6.4) on Windows 7 returns the following:
ERROR: Stream user_input:450:4 Syntax error: Unexpected end of clause
?- magic('McGonagall').
ERROR: Undefined procedure: wizard/1
ERROR: In:
ERROR: [9] wizard('McGonagall')
ERROR: [8] magic('McGonagall') at c:/users/some_user/google drive/projects/nlp/prolog/code/ex2_2.pl:6
ERROR: [7] <user>
Exception: (9) wizard('McGonagall') ? creep
Exception: (8) magic('McGonagall') ? creep
?-
Why does it fail?

In the magic/1 predicate, you call wizard/1, which is not defined:
magic(X):- house_elf(X).
magic(X):- wizard(X).
magic(X):- witch(X).
The result is that Prolog errors, since it calls a predicate that is nowhere defined.
You can for example define a wizard/1 predicate that always fails:
% a world without wizards (if you do not specify extra wizards)
wizard(_) :- fail.
or populate your "world" with wizards, like:
wizard(dumbledore).
wizard(remus_lupin).
%% ...

Related

Predicate for has triplicate in a list?

I am writing a predicate to print true if a list contains 3 copies of an element and also to print the element. Also the predicate should print alternate solutions if they exist.
The predicate which I have written -
hasTriplicate(List):-hasTriplicateAcc(List,Element,0).
%hasTriplicateAcc is wrapped by predicate hasTriplicate since I wanted the arity of hasTriplicate to be 1.
hasTriplicateAcc(_,Element,3):-write(Element).
hasTriplicateAcc([H|T],H,Ct):-hasTriplicateAcc(T,H,Ct1),Ct1 is Ct+1.
hasTriplicateAcc([Z|T],H,Ct):-hasTriplicateAcc(T,H,Ct),Z=\=H.
The output
hasTriplicate([1,1,1]).
11
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [11] 3 is _10188+1
ERROR: [10] hasTriplicateAcc([1,1],1,_10218) at c:/users/user/desktop/code/hastriplicate.pl:3
ERROR: [9] hasTriplicateAcc([1,1|...],1,0) at c:/users/user/desktop/code/hastriplicate.pl:3
ERROR: [7] <user>
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
Exception: (10) hasTriplicateAcc([1, 1], 1, _10332)
I don't understand the error. It would be good if anyone tells me how to correct my code for the predicate.
I think this solution will work .
hascountminimal(_,_,0):-true,!.
hascountminimal([E|L],E,N):- ! , N1 is N - 1 , N >= 1 , hascountminimal(L,E,N1) .
hascountminimal([_|L],E,N):- hascountminimal(L,E,N).
intripple(L,E):-hascountminimal(L,E,3),write(E).

Running main in prolog

I got following code (from this tutorial)
main:-
open(’houses.txt’,read,Str),
read_houses(Str,Houses),
close(Str),
write(Houses), nl.
read_houses(Stream,[]):-
at_end_of_stream(Stream).
read_houses(Stream,[X|L]):-
\+ at_end_of_stream(Stream),
read(Stream,X),
read_houses(Stream,L).
houses.txt:
gryffindor.
hufflepuff.
ravenclaw.
slytherin.
I load it like this:
$ swipl -s flp18-log.pl
The problem comes when I want to start main "function" ->
?- main.
ERROR: Undefined procedure: main/1
ERROR: However, there are definitions for:
ERROR: main/0
ERROR:
ERROR: In:
ERROR: [9] main([])
ERROR: [8] prolog_main:main at /usr/local/Cellar/swi-prolog/HEAD-e6bbda4/libexec/lib/swipl-7.7.12/library/main.pl:82
ERROR: [7] <user>
Exception: (9) main([]) ?
I spent hours figuring out what's wrong. Unsuccessfully. Can you help?
Is:
open('houses.txt',read,Str)
with ', not with ’.

How to make list constructors (e.g .(a,[]) == [a].) work in Prolog?

I am learning Prolog and .(a,[]) == [a]. should return true in SWI-Prolog, but it gives me an error saying
ERROR: Type error: `dict' expected, found `a' (an atom)
ERROR: In:
ERROR: [11] throw(error(type_error(dict,a),_4020))
ERROR: [10] '$type_error'(dict,a) at /Applications/SWI-
Prolog.app/Contents/swipl/boot/init.pl:3369
ERROR: [9] '$dicts':'.'(a,[],_4086) at /Applications/SWI-
Prolog.app/Contents/swipl/boot/dicts.pl:46
ERROR: [8] '<meta-call>'(user:(...,...)) <foreign>
ERROR: [7] <user>
Anyone knows how to fix this?
Start the SWI Prolog executable with the --traditional command line option (comment due to user:false).
Then it works:
1 ?- .(a,[]) == [a].
true.
2 ?- current_prolog_flag( traditional, X).
X = true.
3 ?- set_prolog_flag( traditional, false).
ERROR: set_prolog_flag/2: No permission to modify flag `traditional'
4 ?-
This is mentioned in the documentation here (see "traditional", near the bottom of the page).
As can be seen, attempting to change it from within the running SWI session, fails.

Existence error on lists

I am using gprolog allong with gplc and I get fatal error: redefining built-in predicate member/2 when I try to compile the following code. I also get uncaught exception: error(existence_error(procedure,member/0),member/0) when I try to consult the same code.
Code:
member(X,[X|T]).
member(X,[H|T]) :- member(X,T).
The query I give:
| ?- member(X,[a,b,c,d,e]).
X = a ? ;
uncaught exception: error(existence_error(procedure,member/0),member/0)

How to use list constructors (./2) in SWI-Prolog

I am trying to use list constructor in SWI-Prolog, but am getting 'dict' expected error.
For example,
.(a, []) == [a].
ERROR: Type error: `dict' expected, found `a' (an atom)
ERROR: In:
ERROR: [11] throw(error(type_error(dict,a),_14808))
ERROR: [10] '$type_error'(dict,a) at /Applications/SWI-Prolog.app/Contents/swipl/boot/init.pl:3369
ERROR: [9] '$dicts':'.'(a,[],_14874) at /Applications/SWI-Prolog.app/Contents/swipl/boot/dicts.pl:46
ERROR: [8] '<meta-call>'(user:(...,...)) <foreign>
ERROR: [7] <user>
Exception: (9) '.'(a, [], _14200) ?
Could anyone help me configure this functionality?
SWI-Prolog 7.x uses a different list constructor, '[|]'/2, instead of the traditional ./2 Prolog constructor:
?- '[|]'(1,[]) == [1].
true.
The change was motivated to free ./2 for other uses, notably in dict terms, as hinted in the error message you got for your query.
Better to use | in conventional notation,
?- X = '[|]'(1,[0]).
X = [1, 0].
can be write like this
?- X = [1|[0]].
X = [1, 0].

Resources