Expanding Prolog clauses without parameters - prolog

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.

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.

Is it possible to write an inconsistent Prolog program using only pure Prolog, cut and `false`?

This one tickled my interest in theory:
Is it possible to write an inconsistent Prolog program, i.e. a program that answers both false and true depending on how it is queried, using only pure Prolog, the cut, and false?
For example, one could query p(1) and the Prolog Processor would says false. But when one queries p(X) the Prolog Processor would give the set of answers 1, 2, 3.
This can be easily achieved with "computational state examination predicates" like var/1 (really better called fresh/1) + el cut:
p(X) :- nonvar(X),!,member(X,[2,3]).
p(X) :- member(X,[1,2,3]).
Then
?- p(1).
false.
?- p(X).
X = 1 ;
X = 2 ;
X = 3.
"Ouch time" ensues if this is high-assurance software. Naturally, any imperative program has no problem going off the rails like this on every other line.
So. can be done without those "computational state examination predicates"?
P.S.
The above illustrates that all the predicates of Prolog are really carrying a threaded hidden argument of the "computational state":
p(X,StateIn,StateOut).
which can be used to explain the behavour of var/1 and friends. The Prolog program is then "pure" when it only calls predicates that neither consult not modify that State. Well, at least that seems to be a good way to look at what is going on. I think.
Here's a very simple one:
f(X,X) :- !, false.
f(0,1).
Then:
| ?- f(0,1).
yes
| ?- f(X,1).
no
| ?- f(0,Y).
no
So Prolog claims there are no solutions to the queries with variables, although f(0,1) is true and would be a solution to both.
Here is one attempt. The basic idea is that X is a variable iff it can be unified with both a and b. But of course we can't write this as X = a, X = b. So we need a "unifiable" test that succeeds without binding variables like =/2 does.
First, we need to define negation ourselves, since it's impure:
my_not(Goal) :-
call(Goal),
!,
false.
my_not(_Goal).
This is only acceptable if your notion of pure Prolog includes call/1. Let's say that it does :-)
Now we can check for unifiability by using =/2 and the "not not" pattern to preserve success while undoing bindings:
unifiable(X, Y) :-
my_not(my_not(X = Y)).
Now we have the tools to define var/nonvar checks:
my_var(X) :-
unifiable(X, a),
unifiable(X, b).
my_nonvar(X) :-
not(my_var(X)).
Let's check this:
?- my_var(X).
true.
?- my_var(1).
false.
?- my_var(a).
false.
?- my_var(f(X)).
false.
?- my_nonvar(X).
false.
?- my_nonvar(1).
true.
?- my_nonvar(a).
true.
?- my_nonvar(f(X)).
true.
The rest is just your definition:
p(X) :-
my_nonvar(X),
!,
member(X, [2, 3]).
p(X) :-
member(X, [1, 2, 3]).
Which gives:
?- p(X).
X = 1 ;
X = 2 ;
X = 3.
?- p(1).
false.
Edit: The use of call/1 is not essential, and it's interesting to write out the solution without it:
not_unifiable(X, Y) :-
X = Y,
!,
false.
not_unifiable(_X, _Y).
unifiable(X, Y) :-
not_unifiable(X, Y),
!,
false.
unifiable(_X, _Y).
Look at those second clauses of each of these predicates. They are the same! Reading these clauses declaratively, any two terms are not unifiable, but also any two terms are unifiable! Of course you cannot read these clauses declaratively because of the cut. But I find this especially striking as an illustration of how catastrophically impure the cut is.

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 - 2 ways for progenitor predicate implementation

Given a set of facts that represent parent-child relationships via the predicate parent/2, what are the differences when defining the relation "progenitor"(ancestor) with the predicates pred1/2 and pred2/2 as shown below?
pred1(X,Z) :- parent(X,Z).
pred1(X,Z) :- parent(X,Y), pred1(Y,Z).
pred2(X,Z) :- parent(X,Z).
pred2(X,Z) :- parent(Y,Z), pred2(X,Y).
The major difference are the termination properties of both, provided there are some cycles in the relation. To understand this, I will use a failure-slice which cuts down the program to its essence w.r.t. termination.
pred1(X,Z) :- false, parent(X,Z).
pred1(X,Z) :- parent(X,Y), pred1(Y,Z). % Z has no influence
pred2(X,Z) :- false, parent(X,Z).
pred2(X,Z) :- parent(Y,Z), pred2(X,Y). % X has no influence
For pred1/2, the second argument has no influence on termination at all, whereas in pred2/2, the first argument has no influence. To see this, try the original definitions with the fact:
parent(a,a).
?- pred1(b, _), false.
false. % terminates
?- pred2(b, _), false.
loops.
?- pred1(_, b), false.
loops.
?- pred2(_, b), false.
false. % terminates
See closure/3 for a general approach to avoid such loops.
For completeness, here is another variation of transitive closure which has some conceptual advantages:
pred3(X,Z) :- parent(X,Z).
pred3(X,Z) :- pred3(X,Y), pred3(Y,Z).
Alas, its termination properties are worst. In fact, it never terminates, as is testified by the following fragment:
pred3(X,Z) :- false, parent(X,Z).
pred3(X,Z) :- pred3(X,Y), false, pred3(Y,Z).
In this fragment, the first argument is only passed on. So, no matter, what the arguments are, the program will always loop!
?- pred3(b,b), false.
loops.

Variables for predicates in metagol

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.

Resources