Related
I'm trying to implement n_factors/2 predicate that works in all directions.
:- use_module(library(clpz)).
n_factors(N, Fs) :-
integer(N),
N > 1,
primes(Ps),
n_factors0(N, Fs, Ps),
!.
n_factors(N, Fs) :-
var(N),
primes(Ps),
N #> 1,
above(2, N),
n_factors0(N, Fs, Ps).
above(I, I).
above(I, N) :- I1 is I + 1, above(I1, N).
n_factors0(N, [F|Fs], [P|Ps]) :-
N #> 1,
F #=< N,
P #=< N,
( P * P #> N ->
F = N, Fs = []
; ( N #= N1 * P ->
F #= P, n_factors0(N1, Fs, [P|Ps])
; F #> P, n_factors0(N, [F|Fs], Ps)
)
).
When I am issuing the following query I get:
?- C #> 6, C #< 12, n_factors(A, [B,C]).
C = 7, A = 14, B = 2
; C = 7, A = 21, B = 3
; C = 11, A = 22, B = 2
; C = 11, A = 33, B = 3
; C = 7, A = 35, B = 5
; C = 7, A = 49, B = 7
; C = 11, A = 55, B = 5
; C = 11, A = 77, B = 7
; C = 11, A = 121, B = 11
;
before the program moves on to exploring the realm of rather large numbers. So the question I've go is the following: knowing for certain that the mathematical problem is constraint enough to terminate, how do I find the missing constraint in my program? What I am doing right now is staring at the screen before trying to add "invariant" conditions here and there and see if they help.
primes(Ps) is a "frozen" infinite list with all prime numbers. I don't think the implementation thereof is important for this question but just in case
primes(Ps) :-
Ps = [2,3|T],
primes0(5, Ps, Ps, T),
!.
primes0(C, [D|Ds], Ps, T) :-
( D * D > C ->
T = [C|T1], C1 is C + 2, freeze(T1, primes0(C1, Ps, Ps, T1))
; ( C mod D =:= 0 ->
C1 is C + 2, primes0(C1, Ps, Ps, T)
; primes0(C, Ds, Ps, T)
)
).
help please I need to find ((2n-1)!!) \ (2n)!! but I only know how to write factorial not double.
factorial(0,1).
factorial(N,F) :-
N>0,
N1 is N-1,
factorial(N1,F1),
F is N * F1.
If you look up the Wikipedia entry on double factorial you can easily spot the two candidates for base cases: 0!! = 1 and 1!! = 1. Depending on the number n being odd or even you'll arrive at one of those base cases when calculating n!! recursively because, in the recursive rule, n is decreased by 2 instead of 1 (compared to n!). You can express that in Prolog like so:
doublefactorial(0,1).
doublefactorial(1,1).
doublefactorial(N,F) :-
N > 1,
N2 is N-2,
doublefactorial(N2,F1),
F is N * F1.
If you query this predicate you'll get the desired result:
?- doublefactorial(0,F).
F = 1 ;
false.
?- doublefactorial(1,F).
F = 1 ;
false.
?- doublefactorial(2,F).
F = 2 ;
false.
?- doublefactorial(3,F).
F = 3 ;
false.
?- doublefactorial(4,F).
F = 8 ;
false.
?- doublefactorial(5,F).
F = 15 ;
false.
.
.
.
However, due to the use of >/2 and is/2, this predicate can only be used in one direction:
?- doublefactorial(N,10395).
ERROR: >/2: Arguments are not sufficiently instantiated
?- doublefactorial(N,F).
N = 0,
F = 1 ;
N = F, F = 1 ;
ERROR: >/2: Arguments are not sufficiently instantiated
If you'd like to use the predicate in all directions you could opt to use CLP(FD):
:- use_module(library(clpfd)).
doublefactorial2(0,1).
doublefactorial2(1,1).
doublefactorial2(N,F) :-
N #> 1,
N2 #= N-2,
F #= N * F1,
doublefactorial2(N2,F1).
?- doublefactorial2(N,10395).
N = 11 ;
false.
?- doublefactorial2(N,46080).
N = 12 ;
false.
?- doublefactorial2(N,F).
N = 0,
F = 1 ;
N = F, F = 1 ;
N = F, F = 2 ;
N = F, F = 3 ;
N = 4,
F = 8 ;
N = 5,
F = 15 ;
N = 6,
F = 48 ;
N = 7,
F = 105 ;
N = 8,
F = 384 ;
N = 9,
F = 945 ;
.
.
.
Note how the goal F #= N * F1 can now be put in front of the recursive goal, thus making the predicate tail-recursive, because that equation is now propagated as a constraint. For more information see the SWI-Prolog documentation on CLP(FD).
To calculate (2n)!!/(2n-1)!! or (2n-1)!!/(2n)!! for a particular n you can query the the predicate like this:
?- N=5, X #= 2*N, doublefactorial2(X,F1), Y #= 2*N-1, doublefactorial2(Y,F2), RESULT is F1/F2.
N = 5,
X = 10,
F1 = 3840,
Y = 9,
F2 = 945,
RESULT = 4.063492063492063 ;
false.
?- N=5, X #= 2*N, doublefactorial2(X,F1), Y #= 2*N-1, doublefactorial2(Y,F2), RESULT is F2/F1.
N = 5,
X = 10,
F1 = 3840,
Y = 9,
F2 = 945,
RESULT = 0.24609375 ;
false.
Note that the result is actually calculated using is/2. This is because, in general, the result is not an integer but a rational number, hence you can use CLP(Q) to get the result as a fraction:
?- use_module(library(clpq)).
% library(clpq) compiled into clpq 0.08 sec, 1,189 clauses
true.
?- N=5, X #= 2*N, doublefactorial2(X,F1), Y #= 2*N-1, doublefactorial2(Y,F2), {RESULT = F1/F2}.
N = 5,
X = 10,
F1 = 3840,
Y = 9,
F2 = 945,
RESULT = 256 rdiv 63 ;
false.
?- N=5, X #= 2*N, doublefactorial2(X,F1), Y #= 2*N-1, doublefactorial2(Y,F2), {RESULT = F2/F1}.
N = 5,
X = 10,
F1 = 3840,
Y = 9,
F2 = 945,
RESULT = 63 rdiv 256 ;
false.
For more details see the SWI-Prolog documentation on CLP(Q). Due to the use of CLP(FD) you can also query for a range of n, say 1 to 5:
?- N in 1..5, X #= 2*N, doublefactorial2(X,F1), Y #= 2*N-1, doublefactorial2(Y,F2), {RESULT = F1/F2}.
N = Y, Y = F2, F2 = 1,
X = F1, F1 = RESULT, RESULT = 2 ;
N = 2,
X = 4,
F1 = 8,
Y = F2, F2 = 3,
RESULT = 8 rdiv 3 ;
N = 3,
X = 6,
F1 = 48,
Y = 5,
F2 = 15,
RESULT = 16 rdiv 5 ;
N = 4,
X = 8,
F1 = 384,
Y = 7,
F2 = 105,
RESULT = 128 rdiv 35 ;
N = 5,
X = 10,
F1 = 3840,
Y = 9,
F2 = 945,
RESULT = 256 rdiv 63 ;
false.
You have coins of values 5, 10, 20, 50, 100
whose weights are respectively 2g, 3g, 10g, 25g, 50g.
Your purse is weak so you cannot exceed the weight of 391g.
And you can put inside it only 3 coins having the same value.
Can you say what is the maximum value of your purse?
Query ::: change([(Five,Ten,Twenty,Fifty,Hundred),W,S])
range(I,I,[I]).
range(I,K,[I|L]) :-
I < K,
I1 is I + 1,
range(I1,K,L).
coin(X,L) :-
range(0,3,L1),
member(X,L1).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
change([(Five,Ten,Twenty,Fifty,Hundred),W,S]) :-
coin(Five,L),
coin(Ten,L),
coin(Twenty,L),
coin(Fifty,L),
coin(Hundred,L),
W1 = 50*Hundred + 25*Fifty + 10*Twenty +3*Ten+ 2*Five,
S1 = 5*Five+ 10*Ten+ 20*Twenty + 50*Fifty + 100*Hundred,
W1 < 391,
W is W1,
S is S1,
maximum(S1).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
maximum(S1) :-
S is S1,
threshold(S),
not( S1 < S).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
threshold(S1) :-
M is S1,
not( M < 451).
Use clpfd and simply run the following query:
:- use_module(library(clpfd)).
?- [Hundred,Fifty,Twenty,Ten,Five] ins 0..3,
Weight #=< 391,
Weight #= 50*Hundred + 25*Fifty + 10*Twenty + 3*Ten + 2*Five,
Value #= 100*Hundred + 50*Fifty + 20*Twenty + 10*Ten + 5*Five,
labeling([max(Value)], [Hundred,Fifty,Twenty,Ten,Five]).
Hundred = 3, Fifty = 3, Twenty = 3, Ten = 3, Five = 3, Value = 555, Weight = 270 ;
Hundred = 3, Fifty = 3, Twenty = 3, Ten = 3, Five = 2, Value = 550, Weight = 268 ;
...
'generate and test' performed by library(aggregate):
change(S) :-
aggregate(max(V), P^W^(purse(P, W, V), W < 391), S).
purse(P, W, V) :-
length(P, 5),
maplist(between(0, 3), P),
scalar(P, [2,3,10,25,50], W),
scalar(P, [5,10,20,50,100], V).
scalar(Vs, Fs, S) :-
foldl([V,F,V0,U]>>(U is V0+V*F), Vs, Fs, 0, S).
scalar/3 is a bit of overengineering, take it as a suggestion to look into scalar_product/4 if you go with library(clpfd)
Suppose I want to represent integers like so: integer:Sign:[FirstDigit,SecondDigit,...]. For instance, 42 would be represented as integer:positive:[4,2].
I need a predicate that generates the value of the integer based on this representation and vice versa.
Here is what I came up with:
integer_value_('integer':Sign:[H],E) :-
H in 0..9,
(
Sign = 'positive',
E #= H
;
Sign = 'negative',
E #= -H
).
integer_value_('integer':Sign:[H,I|T],E) :-
H in 0..9,
length([I|T],L),
(
Sign = 'positive',
E #= F + H * 10^L
;
Sign = 'negative',
E #= F - H * 10^L
),
integer_value_('integer':Sign:[I|T],F).
This works as expected. However, it has the unfortunate property of accepting things like integer:positive:[0,1], that is, leading zeroes at the beginning of the list. This is especially problematic when I enumerate all possible integers using integer_value_(I,J), label([J]).: the ones with leading zeroes also show up.
I then attempted to correct this by using integer_value_ only for all but the first digit, and using integer_value for the first one (keeping in mind that we need to accomodate for 0 being represented with a list containing only 0):
integer_value('integer':Sign:[H],E) :-
abs(E) #< 10,
abs(E) #> -1,
integer_value_('integer':Sign:[H],E).
integer_value('integer':Sign:[H,I|T],E) :-
H in 1..9,
length([I|T],L),
(
Sign = 'positive',
E #= F + H * 10^L
;
Sign = 'negative',
E #= F - H * 10^L
),
integer_value_('integer':Sign:[I|T],F).
However now it does not behave properly. For example, integer_value(I,-19). returns I = integer:negative:[1, 9], but if we ask for another answer Prolog goes into an infinite loop for reasons I don't understand (it should say false, or already know there are no other answers).
This problem does not occur with the "opposite" query integer_value(integer:negative:[1,9],Z). which returns Z = 19 and then false, nor does it occur when both arguments are Variables (it enumerates numbers properly, with no leading zeroes), which is surprising to me.
Any idea what that infinite loop occurs, and if there's an easy way to fix it?
To see the problem, it is sufficient to look at a tiny fraction of your program. In fact the following failure-slice is sufficient:
integer_value('integer':Sign:[H],E) :- false,
abs(E) #< 10,
abs(E) #> -1,
integer_value_('integer':Sign:[H],E).
integer_value('integer':Sign:[H,I|T],E) :-
H in 1..9,
length([I|T],L), false,
( Sign = 'positive',
E #= F + H * 10^L
;
Sign = 'negative',
E #= F - H * 10^L
),
integer_value_('integer':Sign:[I|T],F).
L occurs here for the first time, so any length is possible.
You will have to modify the length-goal somehow.
I managed to solve my problem using this other answer pointed out by #false
One of the catch is to decide of the sign of the number as the last step, so that when iterating through possible integers we get alternating answers between positive and negative numbers: after reaching 9 (1 digit), it will unify with -9, then -8, etc. After -1, it will unify with 10, 11, etc. After 99, it will unify with -99, -98, etc. You get the point.
integer_value('integer':Sign:I,E) :-
integer_value('integer':Sign:I,0,E,E).
integer_value('integer':Sign:[H],N0,N,M) :-
H in 0..9,
N1 #= H + N0 * 10,
abs(M) #>= abs(N1),
integer_value_('integer':Sign:[],N1,N,M).
integer_value('integer':Sign:[H,I|T],N0,N,M) :-
H in 1..9,
N1 #= H + N0 * 10,
abs(M) #>= abs(N1),
integer_value_('integer':Sign:[I|T],N1,N,M).
integer_value_('integer':Sign:[],N0,N,_) :-
(
Sign = 'positive',
N #= N0
;
Sign = 'negative',
N #\= 0,
N #= - N0
).
integer_value_('integer':Sign:[H],N0,N,M) :-
H in 0..9,
N1 #= H + N0 * 10,
abs(M) #>= abs(N1),
integer_value_('integer':Sign:[],N1,N,M).
integer_value_('integer':Sign:[H,I|T],N0,N,M) :-
H in 0..9,
N1 #= H + N0 * 10,
abs(M) #>= abs(N1),
integer_value_('integer':Sign:[I|T],N1,N,M).
I'm trying to learn myself Prolog and need a little help.
Could someone solve and explain this problem:
Define a p(A, M/N, K/L), which generates all possible rational fractions M/N and K/L, where:
N>M>0, K>L>0, (M/N)*(K/L) = 2 and (M+K)<A
Your description is not that clear to me, I am rather guessing which values should be known and which are asked. So I will rather use library(clpfd) where I do not have to make such considerations myself.
N>M>0, K>L>0, (M/N)*(K/L) = 2 and (M+K)<A
p(A, M/N, K/L) :-
N #> M, M #> 0,
K #> L, L #> 0,
M+K #< A,
(M/N) * (K/L) #= 2.
?- 3/2 #= F.
F = 1.
?- (3/2)*2 #= F.
F = 2.
Oh, clpfd is on the integers so fractions are truncated. I need some algebra first, multiplying both sides with (N*L) (they are both not 0...):
p(A, M/N, K/L) :-
N #> M, M #> 0,
K #> L, L #> 0,
M+K #< A,
M*K #= 2*N*L.
?- p(A, M/N, K/L).
A in 4..sup, M+K+ -1*A#=< -1, M in 1..sup,
M#=<N+ -1, M*K#=_A, N in 2..sup, 2*N#=_B,
_B in 4..sup, _B*L#=_A, L in 1..sup, L#=<K+ -1,
K in 2..sup, _A in 4..sup.
So Prolog says: Yes! That is true provided all this very fine print is true. The first line is the most interesting A in 4..sup which means that there is no upper bound for A. To get concrete solutions, A must be known:
?- A #= 10, p(A, M/N, K/L).
A = 10, M in 1..7, M+K#=_A, M#=<N+ -1,
M*K#=_B, K in 2..8, L#=<K+ -1, L in 1..7,
_C*L#=_B, _C in 4..56, 2*N#=_C, N in 2..28,
_B in 4..56, _A in 3..9.
Not enough! But now K, L, M, N have all finite domains, so we can enumerate them using labeling([], [K,L,M,N]).
?- A = 10, p(A,M/N,K/L),labeling([],[M,N,K,L]).
A = 10, M = L, L = 1, N = 2, K = 4
; A = 10, M = 1, N = L, L = 2, K = 8
; A = 10, M = L, L = 1, N = 3, K = 6
; ... .