Need help Converting to Prolog rule - prolog

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.

Related

How is it that a clause that requires a ground term works, but that term isn't ground outside of the clause?

I'd like to test whether a term has only one solution.
(Understanding that this might be done in different ways) I've done the following and would like to understand why it doesn't work, if it can be made to work, and if not, what the appropriate implementation would be.
First, I have an "implies" operator (that has seemed to work elsewhere):
:- op(1050,xfy,'==>').
'==>'(A,B) :-·forall(call(A), call(B)).
next I have my singleSolution predicate:
singleSolution(G) :- copy_term(G,G2), (call(G), call(G2)) ==> (G = G2).
Here I'm trying to say: take a term G and make a copy of it, so I can solve them independently. Now if solving both independently implies they are equal, then there must be only one solution.
This works in some simple cases.
BUT.
I have a predicate foo(X,Y,Z) (too large to share) which solves things properly, and for which singleSolution can answer correctly. However, X,Y,Z are not fully ground after singleSolution(foo(X,Y,Z)) is called, even though they would be after directly calling foo(X,Y,Z).
I don't understand that. (As a sanity test: I've verified that I get the same results under swi-prolog and gprolog.)
EDIT: Here is an example of where this fails.
increasing([]).
increasing([_]).
increasing([X,Y|T]) :- X < Y, increasing([Y|T]).
increasingSublist(LL,L) :-·
sublist(L,LL),
length(L, Len),
Len > 1,
increasing(L).
then
| ?- findall(L, singleSolution(increasingSublist([1,2],L)),R).
R = [_]
yes
But we don't know what L is.
This seems to work, but I'm not sure if it's logically sound :)
It uses call_nth/2, a nonstandard but common predicate. It abuses throw to short-circuit the computation. Using bagof/3 instead of findall/3 lets us keep the Goal argument bound (and it will fail where findall/3 would succeed if it finds 0 solutions).
only_once(Goal) :-
catch(bagof(_, only_once_(Goal), _), too_many, fail).
only_once_(Goal) :-
call_nth(Goal, N),
( N > 1
-> throw(too_many)
; true
).
Testing it (on SWI):
?- only_once(member(X, [1])).
X = 1.
?- only_once(member(a, [a, b])).
true.
?- only_once(member(X, [a, b])).
false.
?- only_once(between(1,inf,X)).
false.
Unfortunately, I don't think call_nth/2 is supported in GNU Prolog.
Another possible solution:
single_solution(G) :-
copy_term(G, H),
call(G),
!,
( ground(H)
-> true
; \+ ( call(H), G \= H ) % There is no H different from G
).
p(a).
p(a).
q(b).
q(c).
Examples:
?- single_solution( p(X) ).
X = a.
?- single_solution( q(X) ).
false.
?- single_solution( member(X, [a,a,a]) ).
X = a.
?- single_solution( member(X, [a,b,c]) ).
false.
?- single_solution( repeat ).
true.
?- single_solution( between(1,inf,X) ).
false.
?- single_solution( between(1,inf,5) ).
true.
Here is an another approach I came up with after #gusbro commented that forall/2 doesn't bind variables from the calling goal.
single_solution(G) :-·
% duplicate the goal so we can solve independently
copy_term(G,G2),
% solve the first goal at least / at most once.
G, !,
% can we solve the duplicate differently?
% if so, cut & fail. Otherwise, succeed.
(G2, G2 \= G, !, fail; true).

Why does this rule with `not` always return false?

I have this prolog file:
daughter(anna, vera).
daughter(vera, oleg).
daughter(olga, pavel).
daughter(olga, alla).
daughter(alla, lidia).
man(oleg).
man(victor).
man(pavel).
not(P) :- (call(P) -> fail ; true).
woman(X) :- not(man(X)).
?- woman(X). always returns false. ?- man(X). returns all three male entries though.
I also tried woman(X) :- \+man(X). but certain syntax is not the problem it seems.
If I try to check a certain person it works: ?- woman(anna). returns true.
I'm quite new to prolog and can't even suggest what is wrong here.
UPD. I want all people who are not men to be classified as men. The question is - why can't I do woman(X) and get all non-men?
?- woman(anna).
true.
?- woman(X).
false.
?- man(X).
X = oleg ;
X = victor ;
X = pavel.
UPD2. Solution
The problem was caused by floundering as was pointed out in the comments. I needed woman(X) rule to implement this rule: mothers_names(X, Y) :- not(man(X)), daughter(Y,X).
In a nutshell, inverting the query works: mothers_names(X, Y) :- daughter(Y,X), not(man(X)). because first predicate makes X in not(man(X)) limited to several values.

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.

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.

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