Search code examples
prologlogic

Prolog simple generator


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

Solution

  • 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
    ;  ... .