Reputation: 3
Okay, so basically my teacher gave us a specific format for facts:
m([first_male_name, second_male_name,...,last_male_name]).
f([first_female_name,...last_female_name).
family([father,mother,[child1,...,childn]]).
and I can't figure out how to get my code to interpret the facts correctly. I've tried a few different ways, but I think there is just something fundamentally wrong with my understanding of this. This is the part of my code relating to the issue:
male(X) :- m(Males), member(X, Males).
female(X) :- f(Females), member(X, Females).
parent(X,Y) :- (family([X,_,Child]); family([_,X,Child])), member(Y,Child).
m(['David', 'Lance', 'Charles', 'George', 'Henry', 'Jose', 'Lenny', 'Vance', 'Rhett', 'Jacob', 'Mike']).
f(['Sarah', 'Tammy', 'Jasmine', 'Cassondra', 'Kat', 'Laura', 'Tamarah', 'Nina', 'Stephanie', 'Christen', 'Shannon', 'Maryalice']).
family(['David', 'Sarah', ['George', 'Kat']]).
but when I try ?- male(Jose). it returns Jose = 'David'. Anyone have some insight into what's wrong? I'd really appreciate the help.
Edit: Thanks for the help. I guess it was just a simple mistake, but I doubt I would have realized it without help. I've got it working now.
Upvotes: 0
Views: 309
Reputation: 58274
This is an answer to a question you didn't ask, so really should be a comment. But it's way to long for a comment. :)
In Prolog, for program organization, flexibility, and efficiency, it's best to assert your facts as individual facts, not as conglomerated lists. For example, in your case for m
you have:
m([first_male_name, second_male_name,...,last_male_name]).
As in other languages, it's also best to give your facts, predicates, and variables sensible names. So let's rename this one:
males([first_male_name, second_male_name,...,last_male_name]).
Let's suppose you have a predicate which has a condition that PersonName
is an male
. With the above fact, here's how it might be done:
some_predicate(...) :-
...
males(ListOfMales),
member(PersonName, ListOfMales),
...
Instead, you should use individual facts:
male(first_male_name).
male(second_male_name).
...
Then your predicate becomes:
some_predicate(...) :-
...
male(PersonName),
...
You don't even need the predicate male/1
that you have now. Similarly for female/1
.
For family
, each relationship should be its own fact. Rather than define a single, complex fact with lists to define a family like this:
family([father,mother,[child1,...,childn]]).
A more common way to define this would be:
parents_child(father, mother, child1).
parents_child(father, mother, child2).
...
Then parent(X, Y)
becomes:
parent(X, Y) :-
parents_child(_, X, Y) ; parents_child(X, _, Y).
Or even, for the most flexibility (e.g., what if it's a broken family, or parents were remarried, etc):
father_child(father, child1). father_child(father, child2). ... mother_child(mother, child1). mother_child(mother, child2). ...
Then you have:
parent(X, Y) :-
father_child(X, Y) ; mother_child(X, Y).
Upvotes: 1
Reputation:
Prolog "variables" start with capital letter. If you want to make them "literals" which is atoms you put them in single quotes.
I found it useful to use in SWI-Prolog char_type to learn the exact rules (for SWI-Prolog I guess)... You can use prolog_var_start
"start a Prolog variable name" or prolog_atom_start
"start a unquoted Prolog atom that is not a symbol"
?- bagof(C, char_type(C, prolog_var_start), Cs) ; true.
Cs = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'|...] [write]
Cs = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ'] ;
true.
?- bagof(C, char_type(C, prolog_atom_start), Cs).
Cs = [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, ª, µ, º, ß, à, á, â, ã, ä, å, æ, ç, è, é, ê, ë, ì, í, î, ï, ð, ñ, ò, ó, ô, õ, ö, ø, ù, ú, û, ü, ý, þ, ÿ].
Upvotes: 0