Its been a long time since I used Prolog in earnest, but I can't find any reference to this by googling, or in the texts I have. This may be a failure of terminology, so apologies if I massacre that.
If I have a program that could have multiple solutions:
likes(mary, joe).
likes(bob, joe).
:- likes(X, joe)
Is there a simple built-in way to have the solver run matching predicates in random order, and therefore give results in a random order (or, equivalently, have the first solution be random)?
Obviously you can get as sophisticated as you like with the word random. I'm thinking of some uniform random sampling from the set of valid predicates at each step of the solver. Something more complex like a uniform random sampling over valid solutions is also fine. The issue is general.
I can probably build a program to do this, using a random number generator, and meta-programming. But I want to check if I'm missing something simple.
Linear selection of matching clauses is an important part of Prolog algorithm (or better SLD resolution) . And each match is a candidate solution. I think you cannot expect Prolog as such to randomize clauses order for you.
I would elaborate on mat' answer:
:- meta_predicate randomize_preds(0).
randomize_preds(C) :-
findall(C, retract(C), Cs),
random_permutation(Cs, Rs),
maplist(assertz, Rs).
:- dynamic likes/2.
likes(alice, joe).
likes(bob, joe).
likes(charlie, joe).
likes(dan, joe).
test:
3 ?- randomize_preds(likes(_,_)),findall(X,likes(X,joe),L).
L = [bob, alice, charlie, dan].
4 ?- randomize_preds(likes(_,_)),findall(X,likes(X,joe),L).
L = [alice, bob, dan, charlie].
Randomizing the solutions is easiest in this case, because you only have finitely many and can thus collect them easily:
?- findall(X, likes(X, joe), Ps0), random_permutation(Ps0, Ps), member(P, Ps).
This gives you all people P that like joe, one by one, in a random order.
Related
As title stated above, how to make this possible?
For example:
**Facts:**
parent(child, parent).
parent(child, parent2).
parent(child2, parent).
parent(child2, parent2).
**Rules:**
childof(X,Y) :- parent(Y, X).
number_of_child(X,Y):- X has Y number of child
How should I implement the number_of_child rules?
My expected answer is Y will show 2 (since there are child and child2) or something like that.
Thank you.
You should learn about setof/3, bagof/3 and findall/3. They are general prolog predicates to find all solutions.
If you want something swi-prolog specific just to count the solutions then you can use aggregate_all.
num_children(X, N) :- aggregate_all(count, child_of(X, _Y), N).
https://www.swi-prolog.org/FAQ/SingletonVar.html
Hi guys :) I have encountered problem during programming in prolog. I have partial order defined as facts, and I have defined maximal and greatest element as predicates. We can think of partial order like greater or equal, so le(6,7) is something like 6 <= 7.
le(6,7).
le(4,4).
le(6,6).
le(5,6).
le(5,5).
le(4,5).
le(4,4).
maximal(X) :-
not((le(X,Z) , X\=Z)).
greatest(X) :-
not(le(X,_)).
minimal(X) :-
not((le(Z,X) , X\=Z)).
smallest(X) :-
not(le(_,X)).
When I have typed query like maximal(7) the prolog output is true, and when I ask prolog to find the solution like maximal(X) it gives mi fail. I am beginner prolog programmer, so sorry if the question is too trivial, but I couldn't find the solution on my own.
Prologs uses pre-defined steps to find the answer and negation is always tricky.
To make a long story short, to make the code easier to reason about most logic should be positive and negation applied to expressions where values of all variables are known.
Here is how you could make the code work.
le(6,7).
le(4,4).
le(6,6).
le(5,6).
le(5,5).
le(4,5).
le(4,4).
is_my_number(X) :- le(X, _).
is_my_number(X) :- le(_, X).
equal_or_not_le(X, Y) :- X = Y.
equal_or_not_le(X, Y) :- not(le(X, Y)).
maximal(X) :- is_my_number(X), forall(is_my_number(Y), equal_or_not_le(X, Y)).
Then query:
?- maximal(X).
X = 7 .
Good luck!
I am attempting to learn basic Prolog. I have read some basic tutorials on the basic structures of lists, variables, and if/and logic. A project I am attempting to do to help learn some of this is to match DNA sequences.
Essentially I want it to match reverse compliments of DNA sequences.
Example outputs can be seen below:
?- dnamatch([t, t, a, c],[g, t, a, a]).
true
While it's most likely relatively simple, being newer to Prolog I am currently figuring it out.
I started by defining basic matching rules for the DNA pairs:
pair(a,t).
pair(g,c).
etc...
I was then going to try to implement this into lists somehow, but am unsure how to make this logic apply to longer lists of sequences. I am unsure if my attempted start is even the correct approach. Any help would be appreciated.
Since your relation is describing lists, you could opt to use DCGs. You can describe the complementary nucleobases like so:
complementary(t) --> % thymine is complementary to
[a]. % adenine
complementary(a) --> % adenine is complementary to
[t]. % thymine
complementary(g) --> % guanine is complementary to
[c]. % cytosine
complementary(c) --> % cytosine is complementary to
[g]. % guanine
This corresponds to your predicate pair/2. To describe a bonding sequence in reverse order you can proceed like so:
bond([]) --> % the empty sequence
[]. % doesn't bond
bond([A|As]) --> % the sequence [A|As] bonds with
bond(As), % a bonding sequence to As (in reverse order)
complementary(A). % followed by the complementary nucleobase of A
The reverse order is achieved by writing the recursive goal first and then the goal that describes the complementary nucleobase to the one in the head of the list. You can query this using phrase/2 like so:
?- phrase(bond([t,t,a,c]),S).
S = [g,t,a,a]
Or you can use a wrapper predicate with a single goal containing phrase/2:
seq_complseq(D,M) :-
phrase(bond(D),M).
And then query it:
?- seq_complseq([t,t,a,c],C).
C = [g,t,a,a]
I find the description of lists with DCGs easier to read than the corresponding predicate version. Of course, describing a complementary sequence in reverse order is a relatively easy task. But once you want to describe more complex structures like, say the cloverleaf structure of tRNA DCGs come in real handy.
A solution with maplist/3 and reverse/2:
dnamatch(A,B) :- reverse(B,C), maplist(pairmatch,A,C).
If you want to avoid traversing twice you can also maybe do it like this?
rev_comp(DNA, RC) :-
rev_comp(DNA, [], RC).
rev_comp([], RC, RC).
rev_comp([X|Xs], RC0, RC) :-
pair(X, Y),
rev_comp(Xs, [Y|RC0], RC).
Then:
?- rev_comp([t,c,g,a], RC).
RC = [t, c, g, a].
This is only hand-coded amalgamation of reverse and maplist. Is it worth it? Maybe, maybe not. Probably not.
Now that I thought about it a little bit, you could also do it with foldl which reverses, but now you really want to reverse so it is more useful than annoying.
rev_comp([], []).
rev_comp([X|Xs], Ys) :-
pair(X, Y),
foldl(rc, Xs, [Y], Ys).
rc(X, Ys, [Y|Ys]) :- pair(X, Y).
But this is even less obvious than solution above and solution above is still less obvious than solution by #Capellic so maybe you can look at code I wrote but please don't write such code unless of course you are answering questions of Stackoverflow and want to look clever or impress a girl that asks your help for exercise in university.
What is the best way to express a total order relation in Prolog ?
For example, say I have a set of facts
person(tim)
person(ana)
person(jack)
...
and I want to express the following truth about a person's fortune: for each two persons X and Y, if not(X==Y), either X is richer than Y or Y is richer than X.
So my problem is that the richer clause should be capable of instantiating its variables and also to ensure that it is never the case that richer(X, Y) and richer(Y, X) at the same time.
Here is a better example to see what I mean:
person(tim).
person(john).
happier(tim, john).
hates(X, Y) :- person(X), person(Y), richer(Y, X).
hates(X, Y) :- person(X), person(Y), richer(X, Y), happier(Y, X).
Now the answer to the query hates(john, tim) should return true, because if richer satisfies the mentioned property, one of those two hates clauses must be true. In a resolution based inference engine I could assert the fact (richer(X, Y) V richer(Y, X)) and the predicate hates(john, tim) could be proved to be true.
I don't expect to be able to express this the same way in Prolog with the same effect. However, how can I implement this condition so the given example will work ?
Note also that I don't know who is richer: tim or john. I just now that one is richer than the other.
Thank you.
you cannot write in pure Prolog that a predicate should be a total order: that would require higher order logic since you want to declare a property about a predicate.
this is a predicate that checks if a relationship is total order on a finite set:
is_total_order(Foo,Set):-
forall(
(member(X,Set),
member(Y,Set)),
(
XY =.. [Foo,X,Y],
YX =.. [Foo,Y,X],
(call(XY);call(YX)), %checking if the relationship is total
\+ (call(XY),call(YX), X\=Y) %checking if it's an order
)
).
the operator =../2 (univ operator) creates a predicate from a list (ie: X =.. [foo,4,2]. -> X = foo(4,2)) and the predicate call/1 calls another predicate.
As you can see we use meta-predicates that operate on other predicates.
For an total order on infinite sets things get more complicated since we cannot check every single pair as we did before. I dont even think that it can be written since proving that a relationship is a total order isn't something trivial.
Still, this doesnt declare that a predicate is a total order; it just checks if it is.
So I believe your question is the best way to represent the relation between these 3 people. If you don't actually care about their wealth #'s, just their relative order, you could add predicates like this -
is_richer(tim, anna).
is_richer(anna, jack).
and then a predicate to find all people who X is richer than -
richer(X, Z) :-
is_richer(X, Z).
richer(X, Z) :-
is_richer(X, Y),
richer(Y, Z).
If your is_richer predicate contains cycles though (in this example, if you added is_richer(jack, tim)), this could explode. You need to track where you have visited in this tree.
An example run of richer would be:
?- richer(X, Y).
X=tim
Y=anna ;
X=anna
Y=jack ;
X=tim
y=jack ;
no
I know how to iterate over lists in Prolog to find the maximum, but what if each thing is a separate clause? For example if I had a bunch of felines and their ages, how would I find the oldest kitty?
cat(sassy, 5).
cat(misty, 3).
cat(princess, 2).
My first thought was "hmm, the oldest cat is the one for which no older exists". But I couldn't really translate that well to prolog.
oldest(X) :- cat(X, AgeX), cat(Y, AgeY), X \= Y, \+ AgeX < AgeY, print(Y).
This still errorenously matches "misty". What's the proper way to do this? Is there some way to more directly just iterate over the ages to choose max?
One way is
oldest(X) :- cat(X, AgeX), \+ Y^(cat(Y, AgeY), Y \= X, AgeX < AgeY).
You can also use setof/3 to get a list of all cats and get the maximum from that.
A cat is the oldest if it's a cat and there is not a cat older than it. Let's write that in Prolog:
oldest(X):- cat(X, _), not( thereAreOlders(X)), !.
thereAreOlders(X):- cat(X, N), cat(C, M), C\=X, M > N.
If you consult:
?- oldest(X).
X = sassy.
Here is a solution that loops through all the solutions, always recording the solution that is better than the previous best. In the end, the best solution is returned.
The recording is done using assert/1, you could also use a non-backtrackable global variable if your Prolog provides that (SWI-Prolog does).
The benefit of this approach is that is considers each solution only once, i.e. complexity O(n). So, even though it looks uglier than starblue's solution, it should run better.
% Data
cat(sassy, 5).
cat(misty, 3).
cat(miisu, 10).
cat(princess, 2).
% Interface
oldest_cat(Name) :-
loop_through_cats,
fetch_oldest_cat(Name).
loop_through_cats :-
cat(Name, Age),
record_cat_age(Name, Age),
fail ; true.
:- dynamic current_oldest_cat/2.
record_cat_age(Name, Age) :-
current_oldest_cat(_, CAge),
!,
Age > CAge,
retract(current_oldest_cat(_, _)),
assert(current_oldest_cat(Name, Age)).
record_cat_age(Name, Age) :-
assert(current_oldest_cat(Name, Age)).
fetch_oldest_cat(Name) :-
retract(current_oldest_cat(Name, _Age)).
Usage example:
?- oldest_cat(Name).
Name = miisu
Miisu is a typical Estonian cat name. ;)
On a stylistic point- there are a few different approaches here (some are very elegant, others more 'readable'). If you're a beginner- chose your own, preferred, way of doing things- however inefficient.
You can learn techniques for efficiency later. Enjoy Prolog- its a beautiful language.
I don't remember much Prolog, but I do know that you shouldn't think about solving problems as you would with an imperative programming language.