Want to expand the argument q(M,N):- that should evaluate true , only if
we can express M as sum of two numbers , that also these same two numbers would give the the product of N. Meaning something like A+B=M and A*B=N (M,N>0 both Integers)
So I've tried something like :
sum(A,B,M) :- M is A+B.
prod(A,B,N) :- N is A*B.
q(M,N) :- sum(A,B,M),
prod(A,B,N).
But yeah not a great plan.
some expected outcomes should be:
| ?- q(18,45).
yes
| ?- q(45,18).
no
| ?- q(4,4).
yes
| ?- q(5,5).
no
| ?- q(16,64).
yes
| ?- q(12,25).
no
| ?- q(25,24).
yes
| ?- q(36,120).
no
| ?- q(100,2499).
yes
| ?- q(100,267).
no
| ?- q(653,98770).
yes
| ?- q(653,98880).
no
A very basic solution for your problem, using between/3 from swi prolog, without heavilly modifing your program is:
sum(A,B,M) :- M is A+B.
prod(A,B,N) :- N is A*B.
q(M,N) :-
between(0,1000,A),
between(0,1000,B),
sum(A,B,M),
prod(A,B,N).
In this case, all numbers between 0 and 1000 are considered for A and B. However, there are some weakness. For instance, values for A and B can be exchanged (q(18,45) succeeds for A = 3 and B = 15 and A = 15 and B = 3). To remove this redundancy you can impose B < A. To further improve the algorithm, you can set a range for A and B based on the value of the sum and the product. Certainly both A and B must be less than the value M in your code. Like:
q(M,N) :-
between(0,M,A),
between(0,A,B),
M is A+B,
N is A*B.
You can add further constraints to improve the performances, for instance considering cases where the product is 0 etc...
You can use also clpfd library to solve this problem.
Related
I have written a Prolog code to find the cardinality of a list ie number of distinct elements. It gives correct output but it runs multiple times and I cant seem to get my head around it. I have used the debugger but cant understand whats wrong
member(A, [A|_]).
member(A, [_|L]) :- member(A, L).
crdnlty([],0).
crdnlty([A|R],N) :-
(
\+ member(A, R),
crdnlty(R, N1),
N is N1+1
);
(
member(A, R),
crdnlty(R, N)
).
member checks if A is present in the remaining list.
if its not present ie it is the last occurrence of that element cardinality is increased by 1.
for example if i run the query
crdnlty([1,2,1,1], N).
it returns
N = 2 ;
N = 2 ;
false.
but it should return
N = 2 ;
false.
This is not answer but just a testing suggestion that doesn't fit in a comment.
Besides the unwanted duplicated solution, there's also the question on how to test the predicate. A simple alternative solution is to use the ISO Prolog standard predicate sort/2 and the de facto standard predicate length/2. The alternative solution could be:
cardinality(List, Cardinality) :-
sort(List, Sorted),
length(Sorted, Cardinality).
We can use this alternative solution to define a property that your solution must comply with that allows to QuickCheck your solution (ignoring for now the unwanted non-determinism):
property(List) :-
once(crdnlty(List, C)),
sort(List, S),
length(S, C).
Using the QuickCheck implementation provided by Logtalk's lgtunit tool (which you can run in most Prolog systems; in this example I will be using GNU Prolog):
$ gplgt
...
| ?- {lgtunit(loader)}.
...
% (0 warnings)
(578 ms) yes
| ?- lgtunit::quick_check(property(+list(integer)), [n(2000)]).
% 2000 random tests passed
(1589 ms) yes
Of course, QuickCheck can show bugs but cannot prove their absence. That said, a distinctive feature of Logtalk's QuickCheck implementation is that it tries trivial/corner cases for the specified types before generating random values. This help in ensuring that the random testing will not miss obvious test cases (as we illustrate next).
What happens if we test instead the solution provided by Scott Hunter?
| ?- lgtunit::quick_check(property(+list(integer)), [n(2000)]).
* quick check test failure (at test 1 after 0 shrinks):
* property([])
no
In fact, his solution doesn't take into account that the list may be empty. Assuming that's considered a bug, adding the missing clause:
crdnlty([], 0).
Re-testing:
| ?- lgtunit::quick_check(property(+list(integer)), [n(2000)]).
% 2000 random tests passed
(1509 ms) yes
It might be better to build a list of distinct elements & yield its length for the cardinality:
crdnlty([A|R],N) :- distinct(R,N,[A],1).
% distinct(L,N,DL,DN): There are N distinct values in list L+DL,
% assuming there are DN distinct values in list DL alone.
distinct([],N,_,N).
distinct([A|R],N,DL,DN) :-
(
\+ member(A, DL),
DN1 is DN+1,
distinct(R, N, [A|DL], DN1)
);
(
member(A, DL),
distinct(R, N, DL, DN)
).
For some reason, these two pieces of code aren't equivalent, with the first producing very strange (and incorrect results).
-- Method 1
highestElement1([],A,A).
highestElement1([H|T],A,Max) :-
H > A,
highestElement1(T,H,Max);
highestElement1(T,A,Max).
-- Method 2
highestElement2([],A,A).
highestElement2([H|T],A,Max) :-
H > A,
highestElement2(T,H,Max).
highestElement2([H|T],A,Max) :-
H =< A,
highestElement2(T,A,Max).
From my understanding, they should be identical, as I believe(d) that pattern matching and 'or' are basically syntatic sugar for one another. Is this not the case?
Method1 is actually equivalent to:
highestElement2([],A,A).
highestElement2([H|T],A,Max) :-
H > A,
highestElement2(T,H,Max).
highestElement2([H|T],A,Max) :-
highestElement2(T,A,Max).
This is due to the relative priorities of the (,)/2 and (;)/2 operators:
| ?- current_op(Priority, Type, ',').
Priority = 1000
Type = xfy
yes
| ?- current_op(Priority, Type, ';').
Priority = 1100
Type = xfy
yes
I.e. the second clause of highestElement1 is parsed as:
highestElement1([H|T],A,Max) :-
(H > A, highestElement1(T,H,Max))
;
highestElement1(T,A,Max).
One way to visualize how a term is parsed if we're not sure about operator notation is to use the standard write_canonical/1 built-in predicate:
| ?- write_canonical((a :- b,c; d)).
:-(a,;(','(b,c),d))
(1 ms) yes
The output tells us that we have a compound term with name :- and two arguments, a and ;(','(b,c),d). The second argument is also a compound term with name ; and two arguments, ','(b,c) and d.
There is a partially ordered set relation le(X,Y), when Y mod X = 0
(so there are le(1,5), le(5,70), le(7,14) etc.)
I have to make predicates
max(X) is X maximum element
greatest(X) is X the greatest element
defining max(X) is simple, because
max(X) :- \+ le(X,A), le(B,X). (there isn't any greater element and X is in set)
But how about greatest(X)?
For the least upper bound (LUB), you need two sets. First the argument set S, that you are asking for the LUB, and then the partial order T where you are searching for the LUB. So input is as follows:
T the partial order
S the set, S subset T
The code is then very similar as for the max. Just use range restricted formulas, that search over the partial order. This works in ordinary Prolog for finite partial orders.
Here is your divisibility example:
?- [user].
ls(X,Y) :-
Y mod X =:= 0.
bound(M,Y) :-
\+ (member(X,M),
\+ls(X,Y)).
lub(S,T,Y) :-
member(Y,T), bound(S,Y),
\+ (member(Z,T), bound(S,Z),
\+ls(Y,Z)).
^D
And here are some example runs:
?- lub([3,2],[1,2,3,4,5,6,7,8,9,10],Y).
Y = 6 ;
false.
?- lub([5,3],[1,2,3,4,5,6,7,8,9,10],Y).
false.
?- lub([5,3],[1,2,3,4,5,6,7,8,9,10,11,12,14,15,16,17,18,19,20],Y).
Y = 15 ;
false.
The above very general algorithm is not the efficientest, it is of order m^2*n^2, where n is the size of S and m is the size of T. For infinite partial orders you would need to invent something with CLP(X).
I am trying to find a list of all the family members for the kth generation of a given family. We are given the first members of the family and the family tree as well. Below is my KB for the same and also the implementation. I am not able to figure how I can get the kth generation for this family tree? Lets say k = 4. One way of doing it is that I can find 4 times the relation like this:
4thGen(X,Y) :- parent(X,A),parent(A,B),parent(B,C),parent(C,Y)
but this is not the correct way for this I believe.
male(alex).
male(romeo).
male(oscar).
male(peter).
male(bruno).
male(georg).
male(otto).
male(pascal).
male(jean).
female(lina).
female(julia).
female(rosa).
female(eva).
female(ruth).
female(silvia).
female(ida).
female(irma).
female(olga).
female(marie).
female(tina).
parent(alex,julia).
parent(alex,rosa).
parent(lina,julia).
parent(lina,rosa).
parent(romeo,peter).
parent(julia,peter).
parent(rosa,silvia).
parent(oscar,ida).
parent(eva,ida).
parent(eva,bruno).
parent(peter,bruno).
parent(peter,georg).
parent(peter,irma).
parent(ruth,georg).
parent(ruth,irma).
parent(silvia,otto).
parent(silvia,pascal).
parent(irma,olga).
parent(irma,jean).
parent(otto,olga).
parent(otto,jean).
parent(jean,tina).
parent(marie,tina).
father(X,Y):-parent(X,Y),male(X).
grandfather(X,Y):-father(X,Z),parent(Z,Y).
In order to make more general predicates you can use recursion:
kthGen(X,Y,1):-parent(X,Y).
kthGen(X,Y,K) :- parent(X,A),K1 is K-1,kthGen(A,Y,K1).
Here are some queries:
?- kthGen(alex,julia,1).
true ;
false.
?- kthGen(alex,peter,2).
true ;
false.
?- kthGen(alex,bruno,2).
false.
?- kthGen(alex,bruno,3).
true ;
false.
Two important things to notice here:
Firstly your graph is directed (e.g if parent(A,B) you can't have parent(B,A) ), this matters because if it was undirected you could fall into cycles (e.g kthGen(alex,julia,4). would succeed due to the path alex->julia->alex->julia ,you could solve that by adding another list that keeps track persons you've visited).
Secondly if you try:
?- kthGen(alex,bruno,K).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [8] kthGen(alex,bruno,_7630)
ERROR: [7] <user>
So the predicate kthGen/3 does not have relational behavior. You could use library CLPFD:
:- use_module(library(clpfd)).
kthGen(X,Y,1):-parent(X,Y).
kthGen(X,Y,K) :- parent(X,A),K1 #= K-1,kthGen(A,Y,K1).
Now if you try:
?- kthGen(alex,bruno,K).
K = 3 ;
false
much better !!.
UPDATE
In order to find kth generation persons from a person X you could modify accordingly:
:- use_module(library(clpfd)).
kthGen(Y,1,[Y]).
kthGen(X,K,[X|T]) :- parent(X,A),K1 #= K-1,kthGen(A,K1,T).
Example:
?- kthGen(alex,4,L).
L = [alex, julia, peter, bruno] ;
L = [alex, julia, peter, georg] ;
L = [alex, julia, peter, irma] ;
L = [alex, rosa, silvia, otto] ;
L = [alex, rosa, silvia, pascal] ;
false.
This gives all the possible 4th generations from alex. If you want to find more complex e.g 4th gen from alex or lina you could find it separately an write another predicate that concatenates the results...
UPDATE 2
In last update I keep track of all persons until 4th generation. If you want just 4th gen simply modify like:
kthGen(Y,1,[Y]).
kthGen(X,K,L) :- parent(X,A),K1 #= K-1,kthGen(A,K1,L).
Examlpe:
?- kthGen(alex,4,L).
L = [bruno] ;
L = [georg] ;
L = [irma] ;
L = [otto] ;
L = [pascal] ;
false.
Now if you want all results in one list:
?- findall(X,kthGen(alex,4,[X]),L).
L = [bruno, georg, irma, otto, pascal].
I am trying to generate all integers (natural numbers) smaller than a limit, let's say 10.
I have a predicate nat(X) which produces all numbers from 0 to infinity.
Now my problem is, if I do:
nat10(X) :- nat(X), X =< 10.
This will never terminate, as it tries to find other solutions with nat(X) until infinity.
I need a construct that let's me fail the whole predicate if one subgoal fails. How would I go about doing that?
Depending upon the problem being solved, you might want to consider constraint logic programming over finite domains (CLPFD).
But in this context, you need just prevent Prolog from backtracking if X > 10. The current predicate nat10/1 has no such constraint, so we'll add it:
nat10(X) :- nat(X), ( X > 10 -> !, fail ; true ).
So if X > 10, we do a cut (!) to prevent backtracking to nat(X) (thus avoiding generating natural numbers above 10 infinitely) and then simply fail. Otherwise, we succeed (true).
| ?- nat10(X).
X = 1 ? ;
X = 2 ? ;
...
X = 9 ? ;
X = 10 ? ;
(3 ms) no
| ?-
If you can use clpfd, then this answer is for you!
:- use_module(library(clpfd)).
Simply try:
nat10(X) :-
X in 0..10,
indomain(X).