Variables for predicates in metagol - prolog

The following program noMetagolR is given in:
http://www.doc.ic.ac.uk/~shm/Papers/metagol_gram.pdf page 33.
parse(S,G1,G2) :- parse(s(0),S,[],G1,G2).
parse(Q,X,X,G1,G2) :- abduce(acceptor(Q),G1,G2).
parse(Q,[C|X],Y,G1,G2) :- Skolem(P), abduce(delta1(Q,C,P),G1,G3), parse(P,X,Y,G3,G2).
abduce(X,G,G) :- member(X,G).
abduce(X,G,[X|G]) :- not(member(X,G)).
Skolem(s(0)). Skolem(s(1)). ...
An example query is :
parse([],[],G1), parse([0],G1,G2), parse([0,0],G2,G3), parse([1,1],G3,G4), parse([0,0,0],G4,G5), parse([0,1,1],G5,G6), parse([1,0,1],G6,G),not(parse([1],G,G)), not(parse([0,1],G,G)).
The answer substitutions should return a learnt grammar for parity.
The program is said to run in Yap. I normally use SWI-prolog. Either way,
what do I do to make them understand Skolem/1 ? Presumbly this means that Skolem is a variable? I thought maybe using =.. but this does not work.
Also how many Skolem/1 facts are needed?

in SWI-Prolog, you can place in your source the directive
:- set_prolog_flag(allow_variable_name_as_functor,true).
see current_prolog_flag/2
example on REPL:
1 ?- set_prolog_flag(allow_variable_name_as_functor,true).
true.
2 ?- assert(X(1)).
true.
3 ?- X(Y).
Y = 1.

Related

How do I print dynamic/1 in Prolog

I want to print these all names under each dynamic/1. For example I want to print all names of male under one query for print all males in Prolog.
The easiest way to do this in swi-prolog (and also in gnu-prolog) is to use predicate listing/1:
?- listing(male/1).
:- dynamic male/1.
male(saad).
male(sohaib).
male(salman).
...
true.
If you want more control over display formatting, you can define your own predicate as:
list_facts(Name/Arity) :-
functor(Head, Name, Arity),
forall( clause(Head, true),
format('~w.\n', [Head]) ). % Adjust formatting here!
Example:
?- list_facts(female/1).
female(rida).
female(florida).
female(yasmeen).
...
true.
If you want to show just the names, try:
?- forall(female(Name), format('~w\n', [Name])).
rida
florida
yasmeen
...
true.
REMARK The swi-prolog built-in predicate forall/2is defined as:
forall(Cond, Action) :-
\+ (Cond, \+ Action).
The supplied code works with SWI-Prolog, don't know if this works with other Prolog systems but the basis of the code should be portable.
This is from actual code I use daily so it more production quality code than simple answer code but the basis is to use functor/3 to get a head and then use the head in forall/2 to get the rules (rule/2) and format/3 to output each rule. Normally a rule is a head and body but since this is outputting facts only the heads are output. To convert the rules to individual values =../2 is used. This uses library(options). This also uses current_predicate/1 to check if the predicate exists to avoid an exception if it does not. functor/3 could probably be used but somewhere I recall a corner case that it did now work. The rest should not need explaining.
I only entered 3 of the male facts. Would have used all of them if they were typed as text into the question as then they could have been easily copied.
If the facts are in a different module remember to change the name of the module when calling list_facts/N.
:- module(examples,
[
list_facts/1,
list_facts/2,
list_facts/3
]).
:- dynamic female/1.
:- dynamic male/1.
male(saad).
male(sohaib).
male(salman).
list_facts(Module:Name/Arity) :-
list_facts(user_output,Module:Name/Arity,[]).
list_facts(Output_stream,Module:Name/Arity) :-
list_facts(Output_stream,Module:Name/Arity,[]).
list_facts(Output_stream,Module:Name/Arity,Options) :-
(
current_predicate(Module:Name/Arity)
->
(
option(left_margin_size(Left_margin_size),Options)
->
atomic_list_concat(['~|~',Left_margin_size,'+~|~w'],Format)
;
Format = '~w'
),
(
option(title(Title),Options)
->
format(Output_stream,Format,[Title]),
format(Output_stream,'~n',[])
;
true
),
functor(Head,Name,Arity),
forall(
rule(Module:Head,Rule),
list_fact(Output_stream,Format,Rule)
)
;
format(Output_stream,'No facts found: ~w:~w/~w.~n',[Module,Name,Arity])
).
list_fact(Output_stream,Format,Fact) :-
Fact =.. Fact_values,
list_values(Output_stream,Format,false,Fact_values).
% Recursive case - functor name
list_values(Output_stream,Format,false,[_Value|Values]) :-
!,
list_values(Output_stream,Format,true,Values).
% Recursive case - fact arguments
list_values(Output_stream,Format,true,[Value|Values]) :-
!,
format(Output_stream,Format,[Value]),
list_values(Output_stream,Format,true,Values).
% Base case
list_values(Output_stream,_Format,_Functor_done,[]) :-
format(Output_stream,'~n',[]).
Example usage.
?- working_directory(_,'C:/Users/Groot').
true.
?- [examples].
true.
?- list_facts(examples:male/1).
saad
sohaib
salman
true.
?- list_facts(user_output,examples:male/1,[left_margin_size(3),title('male/1')]).
male/1
saad
sohaib
salman
true.

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.

Expanding Prolog clauses without parameters

I am writing a program that transforms other programs by expanding predicates. I usually do this using clause/2, but it doesn't always expand a predicate if it has no parameters:
:- set_prolog_flag('double_quotes','chars').
:- initialization(main).
main :- clause(thing,C),writeln(C).
% this prints "true" instead of "A = 1"
thing :- A = 1.
Is it possible to expand predicates that have no parameters?
Some general remark: Note that this code is highly specific to SWI. In other systems which are ISO conforming you can only access definitions via clause/2, if that predicate happens to be dynamic.
For SWI, say listing. to see what is happening.
?- assert(( thing :- A = 1 )).
true.
?- listing(thing).
:- dynamic thing/0.
thing.
true.
?- assert(( thing :- p(A) = p(1) )).
true.
?- assert(( thing(X) :- Y = 2 )).
true.
?- listing(thing).
:- dynamic thing/0.
thing.
thing :-
p(_)=p(1).
:- dynamic thing/1.
thing(_).
true.
It all looks like some tiny source level optimization.

Need help Converting to Prolog rule

Everybody likes a job if it's fun and it pays
we=>likes(X, Job):-fun(Job), pay_well(Job).
Not sure if it's correct and if it matters that I put Job as a variable?
Just provide definitions for the other two predicates and you have a working program. Something along these lines:
likes_job(_Person, Job) :-
is_fun(Job),
pays_well(Job).
is_fun('scuba diving instructor').
is_fun('tour guide').
pays_well('software developer').
pays_well('scuba diving instructor').
A couple of examples:
?- likes_job('Peter', Job).
Job = 'scuba diving instructor' ;
false.
?- likes_job('Peter', 'software developer').
false.
?- likes_job('Peter', 'tour guide').
false.
?- likes_job('John', 'scuba diving instructor').
true.
?- likes_job(X, 'scuba diving instructor').
true.
Instead of defining the two predicates, you can just declare them as "dynamic" and they are now empty (instead of absent):
likes_job(_Person, Job) :-
is_fun(Job),
pays_well(Job).
:- dynamic is_fun/1.
:- dynamic pays_well/1.
$ swipl -q
?- [likesjob].
true.
?- likes_job(A, B).
false.
?- assertz(is_fun(x)).
true.
?- assertz(pays_well(x)).
true.
?- likes_job(A, B).
B = x.

Prolog - ASP 'not' to Prolog negate

I have an example problem in Answer Set Programming (ASP). When I try to make the equivalent code in Prolog, I keep getting stuck with the not blocked.
This is the ASP code:
road(berlin,potsdam).
road(potsdam,werder).
road(werder,brandenburg).
road(X,Y) :- road(Y,X).
blocked(werder,brandenburg).
route(X,Y) :- road(X,Y), not blocked(X,Y).
route(X,Y) :- route(X,Z), route(Z,Y).
drive(X) :- route(berlin,X).
#show drive/1
The answer is: drive(potsdam), drive(werder), drive(berlin).
In Prolog, I initially thought it would be as simple as changing the not to \+. When I query drive(X)., it recursively generates the X = potsdam answer. I know that Prolog and ASP work differently but I just can't figure it out.
The problem is road(X,Y) :- road(Y,X). This will recurse forever if there is no match among the facts:
is road(X,Y)?
is road(Y,X)?
is road(X,Y)?
is road(Y,X)?
.....
You can replace the predicate:
road(X,Y) :- road(Y,X).
with
road(X,X).
and add:
reachable(X,Y):-
road(X,Y)
; road(Y,X).
and modify:
route(X,Y) :- road(X,Y), \+ blocked(X,Y).
to:
route(X,Y) :- reachable(X,Y), \+ blocked(X,Y).

Resources