How to check if a variable is instantiated in Mercury - mercury

I am a complete beginner in Mercury language, although I have learned Prolog before. One of the new aspects of Mercury is dererminism. The main function has to be deterministic. In order to make it so, I have to check if a variable is unified/bound to a value, but I cannot find how to do that. Particularly see the code:
main(!IO) :-
mother(X,"john"),
( if bound(X) <-----this is my failed try; how to check if X is unified?
then
io.format("%s\n", [s(X)], !IO)
else
io.write_string("Not available\n",!IO)
).
Such main could not fail, i.e. it would (I guess) satisfy the deterministic constraint. So the question is how to check if a variable is bound.

I've translated the family tree from a Prolog example found on this side for comparison.
I have specified all facts (persons) and their relationship with each other and a few helper predicates.
Note that this typed version did actually find the error that you see in the top answer: female(jane).
The main predicate does not have to be deterministic, it can also be cc_multi, which means Mercury will commit (not try other) choices it has;
you can verify this by replacing mother with parent.
You also do not have to check for boundness of your variables, instead you just use any not deterministic term in the if clause, and on succeeding the then part will have guaranteed bound variables, or unbound in the else part.
If you want this example to be more dynamic, you will have to use the lexer or term module to parse input into a person atom.
If you want all solutions you should check the solution module.
%-------------------------------%
% vim: ft=mercury ff=unix ts=4 sw=4 et
%-------------------------------%
% File: relationship.m
%-------------------------------%
% Classical example of family relationship representation,
% based on: https://stackoverflow.com/questions/679728/prolog-family-tree
%-------------------------------%
:- module relationship.
:- interface.
:- import_module io.
%-------------------------------%
:- pred main(io::di, io::uo) is cc_multi.
%-------------------------------%
%-------------------------------%
:- implementation.
:- type person
---> john
; bob
; bill
; ron
; jeff
; mary
; sue
; nancy
; jane
.
:- pred person(person::out) is multi.
person(Person) :- male(Person).
person(Person) :- female(Person).
:- pred male(person).
:- mode male(in) is semidet.
:- mode male(out) is multi.
male(john).
male(bob).
male(bill).
male(ron).
male(jeff).
:- pred female(person).
:- mode female(in) is semidet.
:- mode female(out) is multi.
female(mary).
female(sue).
female(nancy).
female(jane).
:- pred parent(person, person).
:- mode parent(in, in) is semidet.
:- mode parent(in, out) is nondet.
:- mode parent(out, in) is nondet.
:- mode parent(out, out) is multi.
parent(mary, sue).
parent(mary, bill).
parent(sue, nancy).
parent(sue, jeff).
parent(jane, ron).
parent(john, bob).
parent(john, bill).
parent(bob, nancy).
parent(bob, jeff).
parent(bill, ron).
:- pred mother(person, person).
:- mode mother(in, in) is semidet.
:- mode mother(in, out) is nondet.
:- mode mother(out, in) is nondet.
:- mode mother(out, out) is nondet.
mother(Mother, Child) :-
female(Mother),
parent(Mother, Child).
:- pred father(person, person).
:- mode father(in, in) is semidet.
:- mode father(in, out) is nondet.
:- mode father(out, in) is nondet.
:- mode father(out, out) is nondet.
father(Father, Child) :-
male(Father),
parent(Father, Child).
%-------------------------------%
main(!IO) :-
Child = john, % try sue or whatever for the first answer
( if mother(Mother, Child) then
io.write(Mother, !IO),
io.print(" is ", !IO),
io.write(Child, !IO),
io.print_line("'s mother", !IO)
else
io.write(Child, !IO),
io.print_line("'s mother is unknown", !IO)
).
%-------------------------------%
:- end_module relationship.
%-------------------------------%

You do not need to check variables for their instantiation state. I have never done it in almost 10 years of using Mercury on a daily basis. For each predicate and predicate's mode, Mercury knows statically the instantiation of each variable at each point in the program. So using your example:
% I'm making some assumptions here.
:- pred mother(string::out, string::in) is det.
main(!IO) :-
mother(X,"john"),
io.format("%s\n", [s(X)], !IO).
The declaration for mother says that its first argument is an output argument, this means that after the call to mother its value will be ground. and so it can be printed. If you did use a var predicate (and there is one in the standard library) it would always fail.
To do this Mercury places other requirements on the programmer. For example.
(
X = a,
Y = b
;
X = c
)
io.write(Y, !IO)
The above code is illegal. Because Y is produced in the first case, but not in the second so it's groundness is not well defined. The compiler also knows that the disjunction is a switch (when X is already ground) because only one disjunct can possibly be true. so there it produces only one answer.
Where this static groundness can become tricky is when you have a multi-moded predicate. Mercury may need to re-order your conjunctions to make the program mode correct: eg to put a use of a variable after it's production. Nevertheless the uses and instantiation states of variables will always be statically known.
I understand this is really quite different from Prolog, and may require a fair amount of unlearning.
Hope this helps, all the best.

main(!IO) :-
mother(X,"john"),
( if bound(X) <-----this is my failed try; how to check if X is unified?
then
io.format("%s\n", [s(X)], !IO)
else
io.write_string("Not available\n",!IO)
).
This code doesn't make a lot of sense in Mercury. If X is a standard output variable from mother, it will never succeed with X unbound.
If mother is deterministic (det) in this mode, it will always give you a single value for X. In that case there would be no need to check anything; mother(X, "john") gives you John's mother, end of story, so there's no need for the "Not available case".
Since you're trying to write cases to handle both when mother gives you something and when it doesn't, I'm assuming mother is not deterministic. If it's semidet then there are two possibilities; it succeeds with X bound to something, or it fails. It will not succeed with X unbound.
Your code doesn't say anything about how main (which is required to always succeed) can succeed if mother fails. Remember that the comma is logical conjunction (and). Your code says "main succeeds if mother(X, "john") succeeds AND (if .. then ... else ...) succeeds". But if mother fails, then what? The compiler would reject your code for this reason, even if the rest of your code was valid.
But the if ... then ... else ... construct is exactly designed to allow you to check a goal that may succeed or fail, and specify a case for when the goal succeeds and a case for when it fails, such that the whole if/then/else always succeeds. So all you need to do is put mother(X, "john") in the condition of the if/then/else.
In Mercury you don't switch on variables that are either bound or unbound. Instead just check whether the goal that might have bound the variable succeeded or failed.

Related

PROLOG - Get a list of all the rules an entity verifies

I'm formalizing linguistic data into predicates and entities and doing some reasoning in prolog. Imagine I begin with:
breathe(X) :- snore(X).
sleep(X) :- snore(X).
rest(X) :- sleep(X).
live(X) :- breathe(X); eat(X); sleep(X).
snore(john).
sleep(lucy).
My data can get big enough and I would like to get a list of entities and predicates in order to iterate them and check how many predicates an entity verifies, the output can be lists like:
[john, [snore, breathe, sleep, rest, live]]
[lucy, [sleep, rest]]
or predicates
participant(john, [snore, breathe, sleep, rest, live]).
participant(lucy, [sleep, rest]).
Thanks for your help, I have no clue at this moment.
Representing live knowledge about an abstract world can get messy. There are a lot of different possibilities, and a lot of variance depending of which Prolog system you're using.
Here is an example of your code running in SWI-Prolog, but the same idea should work (more or less) unchanged on any Prolog out there that provides call/N and setof/3 builtins.
:- module(list_entities_that_verify_a_pred,
[participant/2]).
:- redefine_system_predicate(sleep/1).
:- discontiguous breathe/1,sleep/1,rest/1,live/1,snore/1.
breathe(X) :- snore(X).
sleep(X) :- snore(X).
rest(X) :- sleep(X).
live(X) :- breathe(X); /* eat(X);*/ sleep(X).
snore(john).
sleep(lucy).
to_verify(breathe).
to_verify(sleep).
to_verify(rest).
to_verify(live).
to_verify(snore).
participant(Person,Verified) :-
setof(Pred,(to_verify(Pred),call(Pred,Person)),Verified).
First, note I have commented the call to eat/1, to avoid a missing definition exception, so we can try to call the partecipant/2 predicate:
?- participant(P,L).
P = john,
L = [breathe, live, rest, sleep, snore] ;
P = lucy,
L = [live, rest, sleep].
From an architecture viewpoint, the main point to note it's the introduction of to_verify/1, to ease the workflow.
An alternative is using forward chaining using Constraint Handling Rules, an underappreciated paradigm of computation.
This is done using SWI-Prolog's CHR library. The rule engine is implemented "on top of Prolog" and adding a rule to the "constraint store" looks like calling a Prolog goal. The "constraint store" holding the current state of computation disappears once the goal completes.
Note that I'm currently not 100% certain of CHR semantics (it seems my brain is hardwired to read Prolog now) but this code seems to work.
In file sleep.pl:
:- module(forward,[
snore/1,
sleep/1,
collect/2,
pull/2
]).
:- use_module(library(chr)).
:- chr_constraint snore/1, sleep/1, breathe/1.
:- chr_constraint eat/1, live/1, rest/1, collect/2, pull/2.
snore(X) ==> breathe(X).
snore(X) ==> sleep(X).
sleep(X) ==> rest(X).
breathe(X) ==> live(X).
eat(X) ==> live(X).
sleep(X) ==> live(X).
live(X) \ live(X) <=> true. % eliminates duplicates
collect(Who,L),snore(Who) <=> collect(Who,[snore|L]).
collect(Who,L),sleep(Who) <=> collect(Who,[sleep|L]).
collect(Who,L),breathe(Who) <=> collect(Who,[breathe|L]).
collect(Who,L),eat(Who) <=> collect(Who,[eat|L]).
collect(Who,L),live(Who) <=> collect(Who,[live|L]).
collect(Who,L),rest(Who) <=> collect(Who,[rest|L]).
pull(Who,L) \ collect(Who2,L2) <=> Who = Who2, L = L2.
Now we just need to start SWI-Prolog, and issue these commands:
?- [sleep].
true.
?- sleep(lucy),
collect(lucy,[]),
pull(Who,L).
Who = lucy,
L = [rest,live,sleep],
pull(lucy,[rest,live,sleep]).
?- snore(john),
collect(john,[]),
pull(Who,L).
Who = john,
L = [rest,live,breathe,sleep,snore],
pull(john,[rest,live,breathe,sleep,snore]).
You asked in a comment to Carlo's answer:
Is there a way to expose the eat predicate and the like? It looks like
I'm going to have a lot of unmatched predicate networks like owl and
proton because I'm going to use few facts and a lot of semantic
relations from Wordnet.
The issue here seems to be one of closed-world assumption (CWA) where predicates are declared (and thus can be called without generating errors) but not necessarily defined. In this case, as per CWA, what we cannot prove is true, is assumed to be false. E.g. the eat/1 predicate in your example or the "lot of unmatched predicate networks" in your comment.
A possible solution would be to define your entities as Logtalk objects that implement a protocol (or a set of protocols) that declare all the predicates you want to use. Reusing your example:
:- protocol(predicates).
:- public([
breathe/0, sleep/0, rest/0, live/0,
snore/0, eat/0
]).
:- end_protocol.
:- category(generic,
implements(predicates)).
breathe :- ::snore.
sleep :- ::snore.
rest :- ::sleep.
live :- ::breathe; ::eat; ::sleep.
:- end_category.
:- object(john, imports(generic)).
snore.
:- end_object.
:- object(lucy, imports(generic)).
sleep.
:- end_object.
If we ask an entity (object) about a predicate that it doesn't define, the query will simply fail. For example (using SWI-Prolog as backend here but you can use most Prolog systems; assuming the code above is saved in a code.lgt file):
$ swilgt
...
?- {code}.
...
?- lucy::eat.
false.
If we want to find all objects that satisfy e.g. the sleep/0 predicate:
?- findall(Object,
(current_object(Object),
conforms_to_protocol(Object, predicates),
Object::sleep),
Objects).
Objects = [john, lucy].
If we want to query all predicates satisfied by the objects (here with the simplifying assumption that all those predicates have zero arity):
?- setof(
Name,
Arity^(current_object(Object),
conforms_to_protocol(Object, predicates),
Object::current_predicate(Name/Arity),
Object::Name),
Predicates
).
Object = john,
Predicates = [breathe, live, rest, sleep, snore] ;
Object = lucy,
Predicates = [live, rest, sleep].
But, at least for the most common queries, handy predicate definitions would preferably be added to the generic category.
P.S. For more on the closed-world assumption and predicate semantics and also why Prolog modules fail to provide a sensible alternative solution see e.g. https://logtalk.org/2019/09/30/predicate-semantics.html

Are algebraic predicates supported in Mercury?

I'm very new to Mercury and logic programming in general. I haven't found a numeric example like this in the docs or samples...
Take the example predicate:
:- pred diffThirtyFour(float, float).
:- mode diffThirtyFour(in, out) is det.
diffThirtyFour(A,B) :-
( B = A + 34.0 ).
With this, A must be ground, and B is free. What if I want A to be free and B to be ground (eg, adding mode diffThirtyFour(out,in) is det.). Can this sort of algebra be performed at compile time? I could easily define another predicate, but that doesn't seem very logical...
Update
So, something like this kind of works:
:- pred diffThirtyFour(float, float).
:- mode diffThirtyFour(in, out) is semidet.
:- mode diffThirtyFour(out, in) is semidet.
diffThirtyFour(A,B) :-
( B = A + 34.0, A = B - 34.0 ).
A little wary of the semidet, and the redundancy of the second goal. Is this the only way of doing it?
Update 2
This might be the answer...it issues a warning at compile time about the disjunct never having any solutions. A correct warning, but perhaps unnecessary code-smell? This does what I need, but if there are better solutions out there, feel free to post them...
:- pred diffThirtyFour(float, float).
:- mode diffThirtyFour(in, out) is det.
:- mode diffThirtyFour(out, in) is det.
diffThirtyFour(A,B) :-
( A = B - 34.0,
B = A + 34.0
;
error("The impossible happened...")
).
Just discovered the ability to enter different clauses for different modes. This isn't quite an algebraic solver (which I wouldn't have expected anyway), but offers the precise organizational structure I was looking for:
:- pred diffThirtyFour(float, float).
:- mode diffThirtyFour(in, out) is det.
:- mode diffThirtyFour(out, in) is det.
:- pragma promise_pure(diffThirtyFour/2).
diffThirtyFour(A::out,B::in) :- A = B - 34.0.
diffThirtyFour(A::in, B::out) :- B = A + 34.0.
As described in the link, the promise_pure pragma is required because this feature can be used to break semantic consistency. It would also suffice to use the promise_equivalent_clauses pragma, which promises logical consistency without purity. It is still possible to declare clauses with inconsistent semantics with the impure keyword in the pred declaration.
Interestingly, addition and subtraction in the standard int module are inversible, but not in the float module. Perhaps the choice was made because of possible errors in floating point arithmetic....

Prolog - print true or false in print_solution write method

I want to print true or false based on some predicate predicate passing. For example, in Greek mythology Athena is not a descendant of Poseidon. I have all of the facts and rules correct to prove it as such, but cannot simply print in the print_solution method whether the predicate is true or not.
I have the rule descendant(athena, poseidon) that will print false in the interpreter as a single statement. E.g. false is printed if I:
$ prolog
['greek_mythology.pl'].
descendant(athena, poseidon).
false
I now want to write the same in my print_solution method:
print_solution :-
write('Athena is a descendant of Poseidon: '), write(?????), nl.
I tried assigning a variable in the solution and printing that:
print_solution :-
Z :- descendant(athena, poseidon),
write('Athena is a descendant of Poseidon: '), write(Z), nl.
but I get the error:
ERROR: /.../greek_mythology.pl:164:17: Syntax error: Operator priority clash
Out of desperation I tried checking to see if poseidon was in the list of descendant(athena, X):
setof(X, descendant(athena, X), Z), // [gaia,kronos,oranos,rheia,zeus]
member(poseidon, Z).
but that just gives back:
Z = [poseidon|_G3320] .
which I don't understand. Apparently member/2 only works on lists, and Z is apparently not a list:
is_list(Z).
false.
How can I simply print true or false in the write function if the predicate returns passes like it does in the interpreter console? Desired output: Athena is a descendant of Poseidon: false.
You can use if/then/else construct in Prolog also
print_solution :-
( descendant(athena, poseidon)
-> Z = true
; Z = false
),
write('Athena is a descendant of Poseidon: '), write(Z), nl.
seems also could be more useful if parametrized
print_solution(Desc, Anc) :-
( descendant(Desc, Anc)
-> Z = true
; Z = false
),
format('~w is a descendant of ~w: ~w~n', [Desc, Anc, Z]).
print_solution :- print_solution(athena, poseidon).
I think (not absolutely sure) that what you want is reification of the success or failure of a query to a truth value. A naive way to do it would be:
goal_success(Goal, true) :-
Goal.
goal_success(Goal, false) :-
\+ Goal.
(This has problems but read on)
Then, you can use it like this:
?- goal_success(descendant(athena, poseidon), S),
/* write whatever */, write(S).
However, what you are trying to do is basically write your own meta-interpreter, and I am not sure it is really that useful. After all, what you show in your question is exactly how you would expect to interact with the Prolog top level (the Prolog interactive prompt). As a programmer (a human) what you want from Prolog is answers to your questions. What you give Prolog, however, is queries, and you get solutions to these queries. Your question is:
Is Athena a descendant of Poseidon?
You evaluate the query:
?- descendant(athena, poseidon).
false.
There is no solution to this query (let's not go into the whole "closed world assumption" discussion now, it is enough to say that not being able to find a proof means that the opposite is true...)
So we interpret this as:
Athena is not a descendant of Poseidon.
Usually, this should be enough. This is why it seems that you want to extend the Prolog top level, and write your own interpreter on top of it, which is of course fine, but more involved. Once you go down that road, you would like to interact with this interpreter like this maybe?
??- Is Athena a descendant to Poseidon?
?>> No, she is not!
Anyway, if you search the internet for "Prolog meta interpreter" you will get enough to get you started. "The Art of Prolog" by Sterling & Shapiro has a whole chapter on that, too.

Skip/pass non-standard prolog code

I'm developing under SWI-Prolog, but my target is Erlog (https://github.com/rvirding/erlog). I need a way to use non-standard Prolog syntax.
Is there a way to write prolog code that will be disregarded by the SWI-compiler i.e. make it invisible.
Here is example how does it look like :
do_stuff(G,Amt) :- ecall(erlog_demo:efunc('Elixir.Blah':stuff({G,Amt})).
I was thinking if there is a way for SWI to skip that and I have another declaration that does nothing.
do_stuff(_,_).
One option probably is to comment it and then use parser to remove the comment before running in Erlog, but this seem cumbersome.
Any other ideas.
======
is_dialect(swi) :- catch(current_prolog_flag(dialect, swi), _, fail).
:- if(is_dialect(swi)).
do_stuff(_,_).
:- else.
do_stuff(G,Amt) :- ecall(erlog_demo:efunc('Elixir.Blah':stuff({G,Amt})).
:- endif.
Syntax error: Operator expected
I use this idiom to keep code running in different implementations
:- if(swi).
gen_hash_lin_probe(Key, HashTable, Value) :-
arg(_, HashTable, E),
nonvar(E),
E = Key-Value.
:- elif(yap).
gen_hash_lin_probe(Key, HashTable, Value) :-
HashTable =.. [htlp|Args],
nth1(_, Args, E),
nonvar(E),
E = Key-Value.
:- endif.
where predicates swi/0 or yap/0 are imported from this module(prolog_impl)
:- module(prolog_impl, [swi/0, yap/0, prolog_impl/1]).
swi :- prolog_impl(swi).
yap :- prolog_impl(yap).
prolog_impl(K) :-
F =.. [K,_,_,_,_],
current_prolog_flag(version_data, F).
One closing parenthesis is missing in the "else" branch.
do_stuff(G,Amt) :- ecall(erlog_demo:efunc('Elixir.Blah':stuff({G,Amt})). % BAD
do_stuff(G,Amt) :- ecall(erlog_demo:efunc('Elixir.Blah':stuff({G,Amt}))). % OK!
Simply count the number of opening parentheses. When . (period, full-step) is reached the difference count of opening vs closing must amount to exactly zero.
Hope that helps!
This answer is based, in part, on
#Capelli's answer and your comments on his candidate solution.
We propose a different way. Follow the dots step-by-step...
For a start, we take the following simplified and shortened snippet.
:- if(true). p(3).
:- elif(false). p(4+3).
:- endif.
In above sample we can see that the "else" branch is never taken, ever.
So... could we, in principle, put arbitrary text and binary data there?
:- if(true). p(3).
:- elif(false). p (4);;[ p())
:- endif.
нет! Upon (re-)loading, we get: ⚠ Syntax error: Operator expected
TIL that all sections between elif and endif must be valid Prolog text.
Let's try something different which was inspired by that phrases you used, in particular: "[...] use non-standard Prolog syntax [...] code that will be disregarded [...] make it invisible [...]"
To me, the phrase "non-standard syntax" indicates that new operator(s) might be introduced (or old ones redefined):
:- op(500,xfx,=>).
:- if(true). p(2).
:- elif(false). p(3 => 3).
:- endif.
Consider the following variation:
:- if(true). p(2).
:- elif(false). :- op(500,xfx,=>). % is moving the `op/3` here ok?
p(3 => 3).
:- endif.
нет! Upon (re-)loading, we get: ⚠ Unterminated conditional compilation from [...]
There is another way! We can proceed by inserting a special-purpose end_of_file fact to tell the Prolog text reader to disregard everything after end_of_file.
We use it like this:
% snip_at_end.pl
xxx1.
xxx2.
end_of_file.
xxx3.
:- op (500, xfx,eat). % broken syntax (pt.1)
1 ]][[ v % broken syntax (pt.2)
Simple test using SICStus Prolog:
$ sicstus
SICStus 4.3.2 (x86_64-linux-glibc2.12): Fri May 8 01:05:09 PDT 2015
[... License information ...]
| ?- compile(snip_at_end).
% compiling /home/stefan/prolog/snip_at_end.pl...
% compiled /home/stefan/prolog/snip_at_end.pl in module user, 40 msec 400672 bytes
yes
| ?- xxx1.
yes
| ?- xxx2.
yes
| ?- xxx3.
! Existence error in user:xxx3/0
! procedure user:xxx3/0 does not exist
! goal: user:xxx3
Hope this helps! I'm curious / interested if my answer fits your problem:)

Setting some order for prolog expressions

I've got a rule in my Prolog program called blanket(X,Y) which checks if X is in a certain kind of set of Y which consists of:
Y's parents
Y's children
Y's coparents
I've defined it as follows :
blanket(Y,X) :- different(Y,X),parent(Y,X);child(Y,X);coparent(Y,X).
However, this doesn't work as I expect. It correctly identifies X's parents, children, and coparents (if any) but it lists itself as both a parent and a coparent, which I do not want. Is it possible to set some kind of order, so that the different(Y,X) evaluates first and independently? I tried something like : different(Y,X),(parent(Y,X);child(Y,X);coparent(Y,X))., of course, but that yields a syntax error as I"m still quite unfamiliar with the language.
Any suggestions would be greatly appreciated.
EDIT: Here are the child, different, and coparent relations:
child(X,Y) :- parent(Y,X).
different(X,Y) :- not(X == Y).
coparent(Y,X) :- parent(Y,Z),parent(X,Z).
For completeness.
blanket(Y,X) :- different(Y,X), parent(Y,X).
blanket(Y,X) :- different(Y,X), child(Y,X).
blanket(Y,X) :- different(Y,X), coparent(Y,X).
The problen is your definition of coparent. It is the statement that allows return itself as a valid result.
I suggest you redefine it, by example as:
coparent(Y,X) :- parent(Y,Z),parent(X,Z), X \= Y.
in this way, you can simply:
blanket(Y,X) :-parent(Y,X);child(Y,X);coparent(Y,X).
Of course, you can keep definition of "coparent" and only modify blanket as:
blanket(Y,X) :-parent(Y,X);child(Y,X);(coparent(Y,X), X\=Y).

Resources