Prolog, Outputting a Variable After a Relation is Used - prolog

This is my first-day learning prolog and I would like to write a program that decides what shoes I should wear based on the weather and what kind of appointment I have at the office. The main "function" would be declared for example:
"go :- outfit(snow, 15, casual, F1), write(F1)."
Where snow is the weather, 15 is the temperature(not relevant now), and casual is the formality of the appointment. "write(F1)" will display the "output" so the variable F1 needs to be the result of said relation(s). Here are the rules for what shoes to wear:
%Rules for weather
rain(Weather) :- (Weather = 'rain').
snow(Weather) :- (Weather = 'snow').
nice(Weather) :- (Weather = 'nice').
clear(Weather) :- (Weather = 'clear').
%Rules for formality
formal(Appointment) :- (Appointment = 'formal').
semiformal(Appointment) :- (Appointment = 'semiformal').
casual(Appointment) :- (Appointment = 'casual').
%Rules for when to wear a type of footwear
dressShoes(Appointment) :- formal(Appointment).
boots(Appointment, Weather) :- not(formal(Appointment)), (rain(Weather);snow(Weather)).
sneakers(Appointment, Weather) :- not(formal(Appointment)), (nice(Weather);clear(Weather)).
This is where my issue is, I am not sure how to tie the last three relations to a single relation that fills the variable "F1" for my final "outfit" function. I am a C++ guy, so I would like to essentially place a string into F1 like "[sneakers]" or "[boots]" but this is part of my growing pains with prolog. Any help is much appreciated.

Some misunderstandings about Prolog I guess. This kind of rule:
rule(Variable) :- (Variable = 'value').
You don't need to quote 'value', it is already an atom. Whatever book you are reading, look up atoms. It becomes:
rule(Variable) :- (Variable = value).
You don't need the extra parentheses in the rule definition. It becomes:
rule(Variable) :- Variable = value.
You don't need the explicit unification in the body. There is nothing else happening between the head and the body. So you don't need a variable, either. It becomes:
rule(value).
Applying this to your program, I get:
rain(rain).
snow(snow).
nice(nice).
clear(clear).
%Rules for formality
formal(formal).
semiformal(semiformal).
casual(casual).
Those rules say pretty much nothing ;-)
Your example at the very top:
go :- outfit(snow, 15, casual, F1), write(F1).
Does exactly the same as just calling outfit(snow, 15, casual, F1). So what is the purpose of the "go" and the "write"? Skip them I guess.
The logic of your program: can you explain it without code? Your code is so unusual that I have to guess.
If you want to say, "If the appointment is formal, put on dress shoes", you could write it like this:
occasion_shoes(Occasion, Shoes) :-
formality_occasion(Formality, Occasion),
formality_shoes(Formality, Shoes).
formality_occasion(formal, evening_party).
formality_occasion(semi_formal, office).
formality_shoes(formal, dress_shoes).
Do you see what is going on? You match the occasion to the shoes. To do that, you look up the formality of the occasion in the table formality_occasion/2 and then match it to the formality of the shoes in the formality_shoes/2 table.
If you are struggling to model your problem, you can also read up on relational database design.

Related

Prolog check for predicate category

I have been working with Prolog since today, and wanted to create a simple test case. The basic idea was to have multiple sports defined, and it looks as follows:
soccer :- category(ball_sport),
check(has_11_players_per_team),
check(large_ball),
check(use_feet).
tennis :- category(ball_sport),
...
category(ball_sport) :-
check(has_a_ball).
Now I wanted to create a testcase, to see if both sports are of the ball_sport category, but have no idea to check these sports against eachother .. I thought it would be something like the code below, but it's obvious not. Is there an easy way to check these predicate categories? Thanks
both_ballsports(sport_one, sport_two) :-
has_category(sport_one, ball_sport),
has_category_sport_two, ball_sport).
It seems that first of all, you want to declaratively state attributes of a sport.
For example:
sport_attributes(soccer, [ball_sport,players(22),ball(large),use(feet)]).
sport_attributes(tennis, [ball_sport,players(2),players(4),ball(small),use(racket)]).
Note that I am relating sports to attributes. For comparison, the goals of the form check(X) you use above all seem to lack a critical argument, namely the actual sport for which they hold (or not). For example, the goal check(use_feet) either holds or not, but there is no means to qualify a unary predicate of this kind and state different facts for different sports.
Note the naming convention: We describe what each argument means, separated by underscores.
With this representation, both_ballsports/2 could look like this:
both_ballsports(Sport1, Sport2) :-
ballsport(Sport1),
ballsport(Sport2).
ballsport(Sport) :-
sport_attributes(Sport, As),
member(ball(_), As).
Sample query and answer:
?- both_ballsports(Sport1, Sport2).
Sport1 = Sport2, Sport2 = soccer ;
Sport1 = soccer,
Sport2 = tennis ;
Sport1 = tennis,
Sport2 = soccer ;
Sport1 = Sport2, Sport2 = tennis ;
false.
This can be used in all directions!

Prolog build rules from atoms

I'm currently trying to to interpret user-entered strings via Prolog. I'm using code I've found on the internet, which converts a string into a list of atoms.
"Men are stupid." => [men,are,stupid,'.'] % Example
From this I would like to create a rule, which then can be used in the Prolog command-line.
% everyone is a keyword for a rule. If the list doesn't contain 'everyone'
% it's a fact.
% [men,are,stupid]
% should become ...
stupid(men).
% [everyone,who,is,stupid,is,tall]
% should become ...
tall(X) :- stupid(X).
% [everyone,who,is,not,tall,is,green]
% should become ...
green(X) :- not(tall(X)).
% Therefore, this query should return true/yes:
?- green(women).
true.
I don't need anything super fancy for this as my input will always follow a couple of rules and therefore just needs to be analyzed according to these rules.
I've been thinking about this for probably an hour now, but didn't come to anything even considerable, so I can't provide you with what I've tried so far. Can anyone push me into the right direction?
Consider using a DCG. For example:
list_clause(List, Clause) :-
phrase(clause_(Clause), List).
clause_(Fact) --> [X,are,Y], { Fact =.. [Y,X] }.
clause_(Head :- Body) --> [everyone,who,is,B,is,A],
{ Head =.. [A,X], Body =.. [B,X] }.
Examples:
?- list_clause([men,are,stupid], Clause).
Clause = stupid(men).
?- list_clause([everyone,who,is,stupid,is,tall], Clause).
Clause = tall(_G2763):-stupid(_G2763).
I leave the remaining example as an easy exercise.
You can use assertz/1 to assert such clauses dynamically:
?- List = <your list>, list_clause(List, Clause), assertz(Clause).
First of all, you could already during the tokenization step make terms instead of lists, and even directly assert rules into the database. Let's take the "men are stupid" example.
You want to write down something like:
?- assert_rule_from_sentence("Men are stupid.").
and end up with a rule of the form stupid(men).
assert_rule_from_sentence(Sentence) :-
phrase(sentence_to_database, Sentence).
sentence_to_database -->
subject(Subject), " ",
"are", " ",
object(Object), " ",
{ Rule =.. [Object, Subject],
assertz(Rule)
}.
(let's assume you know how to write the DCGs for subject and object)
This is it! Of course, your sentence_to_database//0 will need to have more clauses, or use helper clauses and predicates, but this is at least a start.
As #mat says, it is cleaner to first tokenize and then deal with the tokenized sentence. But then, it would go something like this:
tokenize_sentence(be(Subject, Object)) -->
subject(Subject), space,
be, !,
object(Object), end.
(now you also need to probably define what a space and an end of sentence is...)
be -->
"is".
be -->
"are".
assert_tokenized(be(Subject, Object)) :-
Fact =.. [Object, Subject],
assertz(Fact).
The main reason for doing it this way is that you know during the tokenization what sort of sentence you have: subject - verb - object, or subject - modifier - object - modifier etc, and you can use this information to write your assert_tokenized/1 in a more explicit way.
Definite Clause Grammars are Prolog's go-to tool for translating from strings (such as your English sentences) to Prolog terms (such as the Prolog clauses you want to generate), or the other way around. Here are two introductions I'd recommend:
http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse29
http://www.pathwayslms.com/swipltuts/dcg/

Using "=" in Prolog

I'd like to know why I get an error with my SWI Prolog when I try to do this:
(signal(X) = signal(Y)) :- (terminal(X), terminal(Y), connected(X,Y)).
terminal(X) :- ((signal(X) = 1);(signal(X) = 0)).
I get the following error
Error: trabalho.pro:13: No permission to modify static procedure
'(=)/2'
It doesn't recognize the "=" in the first line, but the second one "compiles". I guess it only accepts the "=" after the :- ? Why?
Will I need to create a predicate like: "equal(x,y) :- (x = y)" for this?
Diedre - there are no 'functions' in Prolog. There are predicates. The usual pattern
goes
name(list of args to be unified) :- body of predicate .
Usually you'd want the thing on the left side of the :- operator to be a predicate
name. when you write
(signal(X) = signal(Y))
= is an operator, so you get
'='(signal(X), signal(Y))
But (we assume, it's not clear what you're doing here) that you don't really want to change equals.
Since '=' is already in the standard library, you can't redefine it (and wouldn't want to)
What you probably want is
equal_signal(X, Y) :- ... bunch of stuff... .
or
equal_signal(signal(X), signal(Y)) :- ... bunch of stuff ... .
This seems like a conceptual error problem. You need to have a conversation with somebody who understands it. I might humbly suggest you pop onto ##prolog on freenode.net or
some similar forum and get somebody to explain it.
Because = is a predefined predicate. What you actually write is (the grounding of terms using the Martelli-Montanari algorithm):
=(signal(X),signal(Y)) :- Foo.
You use predicates like functions in Prolog.
You can define something like:
terminal(X) :- signal(X,1);signal(X,0).
where signal/2 is a predicate that contains a key/value pair.
And:
equal_signal(X,Y) :- terminal(X),terminal(Y),connected(X,Y).

Prolog error in loop

I would need help about Prolog.
I posted my code, the problem is that i do not obtain the expected result.
I want planning actions for moving on table all blocks until is possible. To do this I prompt :
?- do(while(some(x, block(x) & -onTable(x)),pi(x,putOnTable(x))),s0,S).
I expect to see a response like :
S = do(putOnTable(e), do(putOnTable(b), do(putOnTable(c), s0)))
but Prolog returns "false" only. Someone can help me??
% Golog interpreter
%:- [golog_swi].
:- discontiguous clear/2, on/3, onTable/2.
:- op(800,xfy,[&]).
do(E,S,do(E,S)):- primitive_action(E),poss(a,S).
% Primitive Action Declarations.
primitive_action(putOn(_,_)).
primitive_action(putOnTable(_)).
poss(putOn(X,Y),S) :- clear(X,S), clear(Y,S), \+ on(X,Y,S), \+ X=Y.
poss(putOnTable(X),S):- clear(X,S), \+(onTable(X,S)).
% Successor State Axioms.
on(X,Y,do(A,S)):- A = putOn(X,Y); on(X,Y,S), \+ (A = putOnTable(X); A = putOn(X,_)).
onTable(X,do(A,S)) :- A = putOnTable(X); onTable(X,S), \+ A= putOn(X,_).
clear(X,do(A,S)) :- on(Y,X,S), (A = putOn(Y,_) ; A = putOnTable(Y)); clear(X,S), \+ A = putOn(_,X).
% Restore suppressed situation arguments
restoreSitArg(onTable(X),S,onTable(X,S)).
restoreSitArg(on(X,Y),S,on(X,Y,S)).
restoreSitArg(clear(X),S,clear(X,S)).
block(X):- member(X,[a,b,c,d,e]).
% iniTial COndition
onTable(a,s0).
on(b,a,s0).
on(c,b,s0).
clear(c,s0).
onTable(d,s0).
on(e,d,s0).
clear(3,s0).
thank you!!!
Your predicate do/3 cannot succeed because the goal primitive_action/1 will fail with your query.
Currently, while/2 is not described in primitive_action/1 and it seems it is missing also from your program. So you need to extend primitive_action/1 by further facts, or add a new rule to do/3. And in addition to that you need to describe what while/2 means.
This question is actually about Golog. Your mistake is pretty mundane: you didn't copy the Golog interpreter code into your source file/directory.
Golog defines a number of high-level programming constructs, including while-loops and non-deterministic picks (pi), used here. I'm sure you don't want to reinvent Golog, so just go and get it. I'm assuming that your question is part of an assignment of sorts, and your teacher probably pointed you to the Golog interpreter. Otherwise, you can always find it on the pages of the cognitive robotics group at the Univ. of Toronto: http://www.cs.toronto.edu/cogrobo/main/systems/index.html

Guess who-like game in Prolog

I'm developing a Guess Who? game using Prolog. The mechanics of the game are very easy. A player (in this case, the human) chooses one person among many possible ones, and the other player (the computer) starts asking yes/no questions about some attributes of the person. Eventually, with the given answers, there will only be one possible person.
So far, I've been able to make a set of rules and predicates so that the computer can guess the person based on the questions that have been asked so far. I have a set of suspects - those are the people that, with the available clues, could fit.
suspect('Person 1') :- eyes(blue) , age(old) , gender(male).
The predicates for the attributes are defined so that they will be true either if the question regarding that attribute has not been asked yet, or if the question has been asked and the answer matches the attribute of the suspect.
gender(X) :- not(asked_gender) ; value_of(gender, X).
That way, if two suspects share the same eyes and age and different gender, as long as the gender remains unasked, both of them will be plausible suspects.
However, the hard part now is to automate the process of asking those questions. Basically, I'm looking forward to a solution where Prolog were able to get the possible values for the attributes from the suspects' predicates, instead of listing theme somewhere else. I'm pretty sure there must be a way of doing this, given prolog is able to use the program's code as data itself.
How could I do that?
This works in SWI-Prolog :
:- dynamic value/1.
suspect('Person 1') :- eyes(blue) , age(old) , gender(male).
suspect('Person 2') :- eyes(green) , age(young) , gender(male).
suspect('Person 3') :- eyes(brown) , age(young) , gender(male).
fetch(Criterion, Value) :-
retractall(value(_)),
assert(value([])),
forall(clause(suspect(_), Body),
check(Body, Criterion)),
retract(value(Value)).
check((F, T), Criterion) :-
F =..[Criterion, V1],
retract(value(V2)),
( member(V1, V2) -> V3 = V2; V3 = [V1 | V2]),
assert(value(V3)).
check(T, Criterion).
check((_F, T), Criterion) :-
check(T, Criterion).
check((F), Criterion) :-
F =..[Criterion, V1],
retract(value(V2)),
( member(V1, V2) -> V3 = V2; V3 = [V1 | V2]),
assert(value(V3)).
check((_F), _Criterion).
For example :
?- fetch(gender, Value).
Value = [male].
?- fetch(eyes, Value).
Value = [brown,green,blue].
Well, I would imagine a construction like this:
go :-
findall(People,suspect(People),SuspectList),
length(SuspectList,1),
member(Perb,SuspectList),
write('It is '),write(Perb),write('!!'),nl,!.
go :-
askQuestion,
go.
Where in askQuestion/0 you'd ask questions with the read/1 predicate and assert/1 the answers.
This is where you could try and make it 'intelligent' or you could just iterate over the different questions.

Resources