Using attribute_goal/2 the right way in SICStus Prolog - prolog

I'm writing a "solver" using the SICStus Prolog attributed variables interface:
:- module(attach2, [attach2/2]).
:- use_module(library(atts)).
:- attribute att/2.
attach2(X,Y) :- put_atts(X,att(X,Y)),
put_atts(Y,att(Y,X)).
verify_attribute(_,_,[]).
attribute_goal(V,(true,G,true,G,true)) :- get_atts(V,att(X,Y)), G = attach2(X,Y).
Sample query:
| ?- attach2(X,Y), copy_term(X,Xc,Xcc), copy_term(Y,Yc,Ycc), copy_term(X+Y,XYc,XYcc).
Xcc = attach2:(true,attach2(Xc,_A),true,attach2(Xc,_A),true),
Ycc = attach2:(true,attach2(Yc,_B),true,attach2(Yc,_B),true),
XYc = _C+_D,
XYcc = (attach2:attach2(_C,_D),attach2:attach2(_D,_C)),
attach2(X,Y),
attach2(Y,X) ? ;
no
If I change attribute_goal/2 to ...
attach2(X,Y) :- put_atts(X,att(X,Y)),
put_atts(Y,att(X,Y)).
... the answer get better:
| ?- attach2(X,Y), copy_term(X,Xc,Xcc), copy_term(Y,Yc,Ycc), copy_term(X+Y,XYc,XYcc).
Xcc = attach2:(true,attach2(Xc,_A),true,attach2(Xc,_A),true),
Ycc = attach2:(true,attach2(_B,Yc),true,attach2(_B,Yc),true),
XYc = _C+_D,
XYcc = attach2:attach2(_C,_D),
attach2(X,Y) ? ;
no
My conclusion from this:
copy_term/3 collects goals from attribute_goal/2 and if it encounters more than one attributed variable, then it removes trivial true and duplicate goals.
It this essentially right?

Related

I wrote a prolog code for my family tree. What's the problem with this code?

/*facts*/
female(Sufia).
female(Bilkis).
female(Nasima).
female(Rabeya).
female(NWife).
female(Eva).
female(Rekha).
female(Shammi).
female(Shanta).
female(TWife).
female(NSWife).
female(Jui).
female(SHWife).
female(TSWife).
male(Anowar).
male(Shahidul).
male(Khazal).
male(Shafik).
male(Nahid).
male(Jahorul).
male(Naim).
male(Tanim).
male(Raiyan).
male(NSon).
male(JHusband).
male(Jubayer).
male(Shoddo).
male(TSon).
male(NSSon).
male(JSon).
male(SHSon).
male(TSSon).
parent(Anowar,Shahidul).
parent(Anowar,Nasima).
parent(Anowar,Shafik).
parent(Shahidul,Nahid).
parent(Shahidul,Eva).
parent(Nasima,Rekha).
parent(Nasima,Shammi).
parent(Nasima,Shanta).
parent(Shafik,Tanim).
parent(Shafik,Raiyan).
parent(Nahid,NSon).
parent(Rekha,Jui).
parent(Rekha,Jubayer).
parent(Shammi,Shoddo).
parent(Tanim,TSon).
parent(NSon,NSSon).
parent(Jui,JSon).
parent(Shoddo,SHSon).
parent(TSon,TSSon).
/*rules*/
mother(X,Y):-parent(X,Y),female(X).
father(X,Y):-parent(X,Y),male(X).
son(X,Y):-parent(X,Y),male(X).
daughter(X,Y) :- female(X),parent(X,Y).
sister(X,Y) :- female(Y),parent(Par,X),parent(Par,Y), X \= Y.
child(X, Y) :-parent(Y, X).
sibling(X,Y):-parent(Z,X),parent(Z,Y),X\=Y.
grandparent(X,Z):-parent(X,Y),parent(Y,Z).
firstCousin(X,Y):-grandparent(Z,X),grandparent(Z,Y),X\=Y.
secondCousin(X,Y):-grandparent(A,X),grandparent(B,Y),sibling(A,B),A\=B.
firstcousinOnceRemoved(X,Y):-child(X,Z),cousin(Z,Y).
firstcousinTwiceRemoved(X,Y):-grandparent(X,Z),cousin(Z,Y).
You need to quote every name, otherwise these symbols are variables, not atoms.
Otherwise, just lowercase the first letter. To illustrate this last option, using my pet project, here is the graph:
as obtained from this source
:- module(answer_so, [answer_so/0]).
:- use_module(genealogy).
answer_so :- genealogy(answer_so, 'Answer SO').
parent_child(P,C) :- parent(P,C).
female(sufia).
female(bilkis).
female(nasima).
female(rabeya).
female(nwife).
female(eva).
female(rekha).
female(shammi).
female(shanta).
female(twife).
female(nswife).
female(jui).
female(shwife).
female(tswife).
male(anowar).
male(shahidul).
male(khazal).
male(shafik).
male(nahid).
male(jahorul).
male(naim).
male(tanim).
male(raiyan).
male(nson).
male(jhusband).
male(jubayer).
male(shoddo).
male(tson).
male(nsson).
male(json).
male(shson).
male(tsson).
parent(anowar,shahidul).
parent(anowar,nasima).
parent(anowar,shafik).
parent(shahidul,nahid).
parent(shahidul,eva).
parent(nasima,rekha).
parent(nasima,shammi).
parent(nasima,shanta).
parent(shafik,tanim).
parent(shafik,raiyan).
parent(nahid,nson).
parent(rekha,jui).
parent(rekha,jubayer).
parent(shammi,shoddo).
parent(tanim,tson).
parent(nson,nsson).
parent(jui,json).
parent(shoddo,shson).
parent(tson,tsson).
Seems there are no marriages...

How to allow program to proceed?

How to make the program proceed to menu1/0 after false appear
mylist([a,b,c]).
myprog(X) :- mylist(L), member(X, L).
go :- start_message,menu1.
start_message :-
write('This is a program.'),nl,
write('Below are a list:'),nl,
myprog(X),
write(X),nl,
fail.
menu1 :-
nl,write('Select operation:'),nl,
write('1. Input time'),nl,
write('2. Exit program'),nl.
Below is what I am stuck with:
go.
This is a program.
Below are a list:
a
b
c
false
You can do like this
start_message :-
write('This is a program.'),nl,
write('Below are a list:'),nl,
( myprog(X),
write(X),nl,
fail
; true ).
Now when myprog/1 cannot succeed anymore, control goes to true/0 and start_message/0 succeeds.
Remove the fail statement in the last line of start_message.

Prolog if-elseif-else

As the question says, thats kind of what i wanna simulate in prolog. So i'm making a game,here's some code:
move(X):-
get_char(Y)
get_char(_),
get_char(Z),
not(OldLoc='Z'),
not(NewLoc = 'Z'),
validmove(OldLoc,NewLoc).
move(_):-
write('Thanks for playing!'), nl.
move(X):-
write('Invalid move!'), nl,
write('Try Again?'), nl,
move(X).
what i want to do is if the first predicate check fails at not(OldLoc='Z'),not(NewLoc = 'Z'), then go to the next predicate move(_) and it fails at validmove(OldLoc,NewLoc) then go to the next move(X). I'm very new to prolog and i'm almost completely clueless.
If-then-else:
http://www.swi-prolog.org/pldoc/doc_for?object=send_arrow/2
Another if-then-else:
http://www.swi-prolog.org/pldoc/doc_for?object=(*-%3E)/2
Sample #1:
?- test = test -> print('TRUTH') ; print('FALSE').
TRUTH
Sample #2:
?- test = test -> (test2 = test3 -> print('TRUTH'); print('FALSE2')); print('FALSE').
FALSE2

Prolog Query Exercise - Beginner

I'm a begginer at Prolog and I need some help with this exercise, this is the knowledge base provided:
album(‘R. Stevie Moore’, ‘Manuscription’).
album(‘Lane Steinberg’, ‘Manuscription’).
album(‘R. Stevie Moore’, ‘The Yung & Moore Show’).
album(‘Yukio Yung’, ‘The Yung & Moore Show’).
album(‘Jessie Evans’, ‘Autonervous’).
album(‘Bettina Koster’, ‘Autonervous’).
album(‘Lucia Pamela’, ‘Walkin on the moon’).
album(‘Shooby Taylor’, ‘The Human Horn’).
album(‘Tiny Tim’, ‘God Bless Tiny Tim’).
album(‘The Legendary Stardust Cowboy’, ‘Rock-It to Stardom’).
vinil(‘Rock-It to Stardom’).
vinil(‘Walking on the Moon’).
cd( ‘God Bless Tiny Tim’).
cd(‘Walking on the Moon’).
cd(‘Autonervous’).
cd(‘Manuscription’).
cassette(‘The Human Horn’).
cassette(‘The Yung & Moore Show’).
mp3(‘Walkin on the Moon’).
I need to make a query that will return to me all the albums that were made by only one musician.
Thanks for your help :)
In the comments you have provided your code album(X,B),album(Y,C), B \= C. Actually, this is not too far away from a correct solution.
A correct solution could be:
one_musician_album(X) :-
album(A, X),
\+ (album(B, X), A \= B).
The meaning of the predicate is: an album X is a "one-musician album" if this album is authored by some musician A and it's not possible to find a different musician B authored the album X.
Test run:
?- one_musician_album(X).
X = 'Walkin on the moon' ;
X = 'The Human Horn' ;
X = 'God Bless Tiny Tim' ;
X = 'Rock-It to Stardom'.
To get all answers you have to type ';' after each answer.
Maybe this is not needed for you, but it's possible to get all answers in a list with findall:
?- findall(X, one_musician_album(X), Albums).
Albums = ['Walkin on the moon', 'The Human Horn', 'God Bless Tiny Tim', 'Rock-It to Stardom'].
Here is a generalization, based on 'all solutions' builtin bagof/3.
Note that
?- bagof(A, album(A,T), As).
T = 'Autonervous',
As = ['Jessie Evans', 'Bettina Koster'] ;
T = 'God Bless Tiny Tim',
As = ['Tiny Tim']
....
then, restricting the authors (As) to be a list of a single element, we get albums with a single author
?- bagof(A, album(A,T), [A]).
A = 'Tiny Tim',
T = 'God Bless Tiny Tim' ;
...
then, we could use findall/3, as in the good answer by Sergey, or, again, bagof/3, with explicit quantification:
?- bagof(T, A^bagof(A, album(A, T), [A]), Ts).
Ts = ['God Bless Tiny Tim', 'Rock-It to Stardom', 'The Human Horn', 'Walkin on the moon'].

"dynamic" predicate in prolog

If I want to make a rule dynamic so i can use assert after the database file has been loaded, how do i do it? I'm using XSB Prolog at the moment, the file is something like this:
:- dynamic likes/2
likes(mary,tom)
when i try to consult the file with XSB i get an error:
? consult('D:\file.P).
not permitted to assert to static predicatelikes/2
forward continuation...blahblah
Any ideas?
The dynamic predicate works as you are expecting, so there is something else wrong if it is not working for you.
If test.P looks like this:
:- dynamic likes/2.
likes(mary,tom).
It can be consulted, and then more likes/2 facts can be asserted:
XSB Version 3.2 (Kopi Lewak) of March 15, 2009
[i686-pc-linux-gnu; mode: optimal; engine: slg-wam; scheduling: local; word size: 32]
| ?- consult('test.P').
[Compiling ./test]
[test compiled, cpu time used: 0.0440 seconds]
[test loaded]
yes
| ?- assert(likes(mary, bob)).
yes
| ?- likes(X,Y).
X = mary
Y = tom;
X = mary
Y = bob;

Resources