Функция комбинирования пролога - PullRequest
0 голосов
/ 22 сентября 2018

У меня были проблемы с написанием функции комбинаций в прологе, которая следует следующему математическому уравнению: b!/ ((bc)! * c!) Я новичок в прологе и не уверен, что с ним совсем не так.Я получаю ошибку: ОШИБКА: is / 2: Арифметика: `fact1 / 2 'не является функцией

Ниже мой код:

    %fac(0,1).
    %fac(N,X) :- N > 0, M is N - 1, fac(M,Y), X is Y * N.

    fact1(0,Result) :- Result is 1.
    fact1(N,Result) :- N > 0, N1 is N-1,                                                 
    fact1(N1,Result1), Result is Result1*N.

    main :- current_prolog_flag(argv,[BB_S,CC_S]),
        atom_number(BB_S,BB),
        atom_number(CC_S,CC),
        %read_input,
        R1 is 1,
        R2 is 1,
        R3 is 1,
        FB is fact1(BB,R1),
        ABS is abs(BB - CC),
        FE is fact1(ABS,R2),
        FC is fact1(CC,R3),
        TI is FE * FC,
        BF is FB / TI,
        %BF is fac(BB) / (fac(abs(BB-CC)) * fac(CC))),
        write($BF),
        halt.

СпасибоВы за вашу помощь.

Ответы [ 2 ]

0 голосов
/ 22 сентября 2018

Исходя из вопроса, я думаю, у вас неправильное представление о предикатах.Предикаты могут приводить только к true или false (ну, конечно, это может быть ошибка, или они могут зацикливаться вечно, если вы также рассматриваете их как "возможные результаты").Предикат может отвечать значениями , объединяя переменные, которые еще не зафиксированы.Как правило, в Прологе каждый предикат настолько универсален, насколько это возможно, так что можно назвать предикат разнонаправленный .

Вы называете предикат как:

FB is fact1(BB,R1),

Но fact1 не является функцией (функтор, для которого в предикате is/2 семантика известна).

Предикат может вычислять вещи и передавать результаты через объединение , например:

?- fac1(5, X).
X = 120 .

мы, таким образом, вызываем предикат fac1/2 с первым параметром, установленным в 5, и Prolog объединит X в 120.

Мы можемпереписать предикат так:

main :- current_prolog_flag(argv,[BB_S,CC_S]),
    atom_number(BB_S,BB),
    atom_number(CC_S,CC),
    fact1(BB, <b>FB</b>),
    ABS is abs(BB - CC),
    fact1(ABS, <b>FA</b>),
    fact1(CC, <b>FC</b>),
    Res is <b>FB</b> / (<b>FA</b> * <b>FC</b>),
    write(Res).

Мы также можем сделать fac1 более декларативным: сейчас это работает только при фиксированном первом параметре (или в случае, если второй параметр 1).Кроме того, это немного неэффективно, поскольку не использует оптимизацию хвостового вызова (TCO) .Мы можем улучшить предикат с помощью библиотеки clpfd и реализовать ее следующим образом:

:- use_module(library(clpfd)).

fac(0, 1).
fac(I, F) :-
    I #> 0,
    F #= I*F1,
    I1 #= I-1,
    fac(I1, F1).

Теперь мы можем запрашивать факториальное отношение в нескольких направлениях:

?- fac(I, 120).
I = 5 ;
false.

?- fac(I, 130).
false.

?- fac(5, 120).
true ;
false.

?- fac(7, 120).
false.

?- fac(7, Y).
Y = 5040 ;
false.

Таким образом, мы можемзапрос, для которого i, i! равен 120 и т. д.

Мы также можем повысить производительность, внедрив продукт для определенного диапазона, поэтому:

  b
------
 | |
 | |   i
i=a+1

Таким образом, prodrange, который в основном:

prodrange (A, B, P): - fac (A, FA), fac (B, FB), P - FB / FA.

но тогда более эффективно, так как это O (a + b) , и мы можем уменьшить его до O (b - a) , с:

prodrange(A, A, 1).
prodrange(A, B, P) :-
    B > A,
    B1 is B-1,
    prodrange(A, B1, P1),
    P is P1 * B1.

или более декларативный:

prodrange(A, A, 1).
prodrange(A, B, P) :-
    B #> A,
    P #= B*P1,
    B1 #= B-1,
    prodrange(A, B1, P1).

тогда мы можем реализовать предикат comb/3 для вычисления количества комбинаций:

comb(BB, CC, Res) :-
    MX is max(BB, CC),
    MN is min(BB, CC),
    prodrange(MN, MX, Num),
    Abs is MX-MN,
    fac(Abs, Den),
    Res is Num / Den.

тогда main выглядит так:

main :-
    current_prolog_flag(argv,[BB_S,CC_S]),
    atom_number(BB_S,BB),
    atom_number(CC_S,CC),
    comb(BB, CC, BF),
    print('Number of bracelets: '),
    write(BF),
    halt.
0 голосов
/ 22 сентября 2018

Неважно.Я нашел решение.Но для пользы других я разместил решение здесь.Очевидно, что функции не имеют возврата и возврата, помещая значение, которое они генерируют, в данную переменную.

    %fac(0,1).
    %fac(N,X) :- N > 0, M is N - 1, fac(M,Y), X is Y * N.

    fact1(0,Result) :- Result is 1.
    fact1(N,Result) :- N > 0, N1 is N-1, fact1(N1,Result1), Result is Result1*N.

   main :- current_prolog_flag(argv,[BB_S,CC_S]),
       atom_number(BB_S,BB),
       atom_number(CC_S,CC),
       %read_input,
       fact1(BB,FB), %notice change
       ABS is abs(BB - CC),
       fact1(ABS,FE), %notice change
       fact1(CC,FC), %notice change
       TI is FE * FC,
       BF is FB / TI,
       %BF is fac(BB) / (fac(abs(BB-CC)) * fac(CC))),
       print('Number of bracelets: '),
       write(BF),
       halt.
...