Arguments not sufficiently instantiated when consulting file - prolog

I'm running SWI-Prolog on a Mac through the Terminal. I'm trying to access an Atom file by writing the usual after opening up swipl in the terminal:
?- [hwk1-my_name].
Instead of swipl having the knowledge base to play with, it's giving me this:
ERROR: Arguments are not sufficiently instantiated
I'm new to Prolog, and my program as it stands now is simply the copied-and-pasted code provided by my professor to get the assignment started. Does this mean that the error is likely due to something within the code below, and if so, what is prompting this? Here is the code provided to me:
father(Dad, Child) :-
parent(Dad, Child),
male(Dad).
mother(Mom, Child) :-
parent(Mom, Child),
female(Mom).
had_a_child(Man, Woman) :-
father(Man, Child),
mother(Woman, Child).
sibling(Sibling1, Sibling2) :-
parent(Parent, Sibling1),
parent(Parent, Sibling2),
Sibling1 \= Sibling2.
brother(Brother, Sib) :-
sibling(Brother, Sib),
male(Brother).
sister(Sister, Sib) :-
sibling(Sister, Sib),
female(Sister).

Your obvious problem is the - inside the file name. The text editor you are using is completely irrelevant. Even confusing, as one of Prolog's data types is the atom.
You have two options:
Use file names that would be valid Prolog atoms even without quoting. This means that they cannot start with a capital or a digit, and can contain only letters, digits, and underscores (_). Then, your file can still have the .pl extension and you can consult it like you do: foo.pl ---> ?- [foo].
Use the complete filename, extension included, and put single quotes around it: foo-bar.baz ---> ?- ['foo-bar.baz'].. As you will see, you don't even need the .pl extension any more.
Whenever you are in doubt about what Prolog sees, you can try write_canonical/1:
?- write_canonical(hwk1-my_name).
-(hwk1, my_name)
true.
In other words, Prolog takes this as the compound term -/2 with the atoms hwk1 and my_name as the first and second argument.

Related

Representing truth regarding beliefs in prolog

How to make this (or something similar) work in Prolog:
belief(john,red(apple)).
belief(peter,red(apple)).
X :- belief(john,X), belief(peter,X).
And get true. for the following query (while consulting above):-
?- red(apple).
First, it's useful to define a little helper to capture when all (relevant) persons believe something:
all_believe(Belief) :-
belief(john, Belief),
belief(peter, Belief).
Then you can define, for example:
red(Object) :-
all_believe(red(Object)).
green(Object) :-
all_believe(green(Object)).
And with your given set of beliefs you get:
?- red(apple).
true.
?- green(apple).
false.
This works. It requires you to define similar rules for any term that you want to use as a belief.
You can make this a bit shorter with macro definitions using term_expansion:
term_expansion(declare_belief(Belief),
Belief :- all_believe(Belief)).
This means that every top-level definition in your source code of the form declare_belief(Belief) should be treated as if you had written Belief :- all_believe(Belief) instead (with the variable Belief substituted appropriately).
So now you can just write this:
declare_belief(red(_)).
declare_belief(green(_)).
and it will be treated exactly like the longer definitions for red(Object) and red(Object) above. You will still have to write this kind of declaration for any term that you want to use as a possible belief.
Prolog does not allow the head of a rule to be just a variable. The head must be a nonvar term, whose functor (i.e., name and arity) identifies the predicate being defined. So, a possible solution would be something like this:
true_belief(X) :-
belief(john, X),
belief(peter, X).
belief(john, red(apple)).
belief(peter, red(apple)).
Examples:
?- true_belief(red(apple)).
true.
?- true_belief(X).
X = red(apple).

My Swi-prolog code return true for every query

I'm trying to write Swi-Prolog code for family relations. There are no error but it always returns true. P
man(_Pete).
man(_Mark).
man(_John).
man(_Frank).
man(_Tom).
man(_Matt).
man(_Henry).
man(_Todd).
woman(_Lilly).
woman(_Kate).
woman(_Anne).
woman(_Alice).
woman(_Jenny).
parent(_Pete,_Mark).
parent(_Pete,_Tom).
parent(_Pete,_Anne).
parent(_Mark,_Lilly).
parent(_Mark,_John).
parent(_Mark,_Frank).
parent(_Tom,_Kate).
parent(_Anne,_Alice).
parent(_Anne,_Matt).
parent(_Alice,_Henry).
parent(_Matt,_Jenny).
parent(_Matt,_Todd).
father(X,Y) :- man(X),parent(X,Y).
mother(X,Y) :- woman(X),parent(X,Y).
sibling(X,Y) :- parent(Z,X),parent(Z,Y).
sister(X,Y) :- woman(X),sibling(X,Y).
brother(X,Y) :- man(X), sibling(X,Y).
grandparent(X,Y) :- parent(X,Z),parent(Z,Y).
I'm expecting to check relations. Like if I try a function ?- parent(Pete,John). I believe it should return false, but it actually returns true for every query. This is my first program on Prolog and might need help to understand the problem.
You probably meant to write names but instead you put anonymous variables in there.
Instead of parent(_Matt,_Todd) you should write parent('Matt', 'Todd') or even parent(matt, todd).
This is an anonymous variable: _X.
This is a normal variable: X.
This is a lower-case atom. It is has a length of 1, so it is also a "char": x.
This is an upper-case char: 'X'.
If you wrap anything in single quotes, it becomes an atom. It can also have spaces in it.
If you put an underscore at the front, you get an anonymous variable. It ends at the first space or operator.
If you are getting "Singleton variable" warnings, it is usually one of two things.
Beginners often mean to write 'Bob' but write Bob instead (without the single quotes).
You are defining a predicate and you forget to use one of the variables in it. You either have to make it an anonymous variable, _Bob, if you really don't care about it, or you find where in the predicate you were supposed to use it.

Open .pl file and close current one in SWI - Prolog

I have created two different .pl files in SWI-Prolog for a text adventure game. They are two different missions.
Is there any way at the end of the first mission to open the second mission (the second .pl file) and close the first one?
Also, what would be better: To create N .pl files for my N missions or one big .pl file?
I agree with your initial impulse in thinking that using a number of module files would be best. I imagine that one reason for using different files would be to provide different name spaces for facts and rules which would be best expressed using the same predicates. So that, for instance, Description would be different for room(1, Description) in mission 1 than in mission 2.
One way of achieving this would be by accessing private, non-exported predicates in each of the different mission-modules. (Aside: I read Jan Wielemaker caution against this practice somewhere, but I'm not sure why, nor am I sure that I did read this.)
Here's a possible pattern I threw together:
Given a main file, 'game.pl', with the following program,
:- use_module([mission1, mission2]).
start :-
playing(mission1).
playing(CurrentMission) :-
read(Command),
command(CurrentMission, Command),
playing(CurrentMission).
command(_, quit) :- write('Good bye.'), halt.
command(CurrentMission, Command) :-
( current_predicate(CurrentMission:Command/_) % Makes sure Command is defined in the module.
-> CurrentMission:Command % Call Command in the current mission-module
; write('You can\'t do that.'), % In case Command isn't defined in the mission.
).
and these mission modules,
In file 'mission1.pl':
:- module(mission1, []).
turn_left :-
write('You see a left-over turnip').
eat_turnip :-
write('You are transported to mission2'),
playing(mission2). % Return to the prompt in `game` module, but with the next module.
In file 'mission2.pl':
:- module(mission2, []).
turn_left :-
write('You see a left-leaning turncoat.').
Then we can play this shitty game:
?- start.
|: turn_left.
You see a left-over turnip
|: eat_turnip.
You are transported to mission2
|: turn_left.
You see a left-leaning turncoat.
|: quit
|: .
Good bye.
The specifics of this program are problematic for a number of reasons. For instance, I expect we might rather have a single predicate that handles navigating through places, and that we'd rather describe places and object that react to different commands in our missions, rather than account for every possible command. But the general principle of using the different files would still work.
Another approach would be to use consult/1 and unload_file/1 to load and unload modules, in which case you should be able to use their public, exported predicates instead of calling them by module. Documentation for those and related predicates can be found in the manual in the section "Loading Prolog Source Files".

Converting Terms to Atoms preserving variable names in YAP prolog

Is there a way to configure YAP (and/or SWI prolog) so they will preserve variable names in any call to term_to_atom/2 ?.
For example, when I execute this:
term_to_atom(member(X, [1,2]), A).
I obtain this answer:
A = 'member(_131405,[1,2])'
Where X has been replaced by its internal representation.
However, I would like to get this answer instead:
A = 'member(X,[1,2])'
Thanks for any help!
There are two issues involved. How to get the variable name X into the system, and how to get a term with such a variable into the atom.
The X you type in is read by the top level which converts it to a regular variable which does not have a name associated. Let's see that in YAP:
?- read(Term).
|: X+3*Y+X.
Term = _A+3*_B+_A
The |: is YAP's prompt for input. And we have entered X+3*Y+X. However, the variable Term contains _A and _B (names chosen by the top level) in place of X and Y. So the information is lost and cannot be restored once it is read by read/1.
You have to access that information differently with the more general built-in for reading read_term/2,3 and the option variable_names/1.
?- read_term(T,[variable_names(Eqs)]).
|: X+3*Y+X.
Eqs = ['X'=_A,'Y'=_B],
T = _A+3*_B+_A
So the read option variable_names/1 gives you the information to restore the variable names. For each named variable read by read_term/2 there is a structure Name = Variable where Name is an atom representing the variable name. Above, 'X' is the name capital X.
Anonymous variables, that is variables whose name is _, do not occur in the list of variable names. They can be rapidly extracted like so:
?- read_term(T,[variable_names(Eqs)]),
term_variables(Eqs, Named),
term_variables(Named+T, Vars),
append(Named, Anons, Vars).
So much for the reading.
Now for the writing. We cannot write the term directly but have to accompany it with the list Eqs. Let's call the new predicate term_to_atom(Term, Eqs, Atom). In both YAP and SWI there is with_output_to(Output, Goal) which writes the output of Goal to different destinations like atom(A). So you can now use write_term/2 to write the term as you please. An example:
?- with_output_to(atom(A),write_term('a b'+X,[quoted(true)])).
A = '\'a b\'+_131284'.
The variable _131284 looks very ugly. To get variables associated with their names for printing we can implement term_to_atom/3 as follows:
term_to_atom(T, Eqs, A) :-
with_output_to(atom(A), write_term(T,[variable_names(Eqs),quoted(true)]) ).
And use it like so:
?- read_term(T,[variable_names(Eqs)]), term_to_atom(T, Eqs, Atom).
|: X+3*Y+X.
Atom = 'X+3*Y+X',
Eqs = ['X'=_A,'Y'=_B],
T = _A+3*_B+_A
variable_names/1 exists as a write option in ISO, Minerva, Jekejeke, GNU, B, SWI, YAP, and SICStus.
In SICStus, the originator of writing terms to lists, one writes:
:- use_module(library(codesio)).
term_to_atom(T, Eqs, Atom) :-
write_term_to_codes(T, Codes, [variable_names(Eqs),quoted(true)]),
atom_codes(Atom, Codes).
The following was an ISO incompatible work around for YAP prior to 6.3.4. It is no longer necessary. As for the differences to a separate write option: term_to_atom/3 as defined below interferes with constraints and does not correctly render '$VAR'/1.
But for the moment we can only approximate the ideal option
variable_names/1. To print terms with our own variable names,
variables have to be substituted in YAP by '$VAR'(Codes) where
Codes is a list of character codes. This does not do exactly the
same, but it is very close. This goes into a file:
:- use_module(library(apply)).
:- use_module(library(lambda)).
write_eqs_term(T, Eqs) :-
\+ \+ (
maplist(\Eq^( Eq = (N='$VAR'(Chs)), atom_codes(N,Chs)), Eqs),
write_term(T,[numbervars(true),quoted(true)])
).
term_to_atom(T, Eqs, A) :-
with_output_to(atom(A), write_eqs_term(T, Eqs) ).
For SWI, you would have to replace atom_codes(N,Chs) by N = Ch.
and install library(lambda) first. It's pre-installed in YAP.

Prolog print statement does not work as expected

I was trying to define a functor and print each individual items of list in Prolog, but Prolog is not printing in correct format.
rint(L):-
write(H).
the output is like
rint([a, s,v ,c]).
_L139
true.
This is what I expect to achieve by calling the functor, any help or thought is appreciated, I'm new to Prolog and learning it.
?- rint([a,b,c,d]).
.(a, .(b, .(c, .(d, []))))
I think it should be
rint(L) :- write(L).
Also if you want .(a, .(b, .(c, .(d, [])))) and not [a, b, c, d] in output, use display:
rint(L) :- display(L).
The problem is an error in your rule for rint.
Your definition says that rint(L) succeeds if write(H) succeeds. At that point, the interpreter knows nothing about H. So it writes a value it doesn't know, which is why you see the _L139, the internal representation of an uninitialised variable.
Having done that, write(H) has succeed, is true, so rint(L) is true. The interpreter tells you that: true.
To define your own rint/1 without relying on built-ins such as display/1, you would need to do something like
rint([]) :-
write([]).
rint([H|T]) :-
write('.('),
write(H),
write(', '),
rint(T),
write(')').
If you're trying to display an empty list, just write it. If you're trying to display any other list, write the opening period and parenthesis, write the Head, write the following comma and space, then call itself for the Tail of the list, then write the closing parenthesis.

Resources