Reversible numerical calculations in Prolog

前端 未结 4 1577
不知归路
不知归路 2020-12-05 11:35

While reading SICP I came across logic programming chapter 4.4. Then I started looking into the Prolog programming language and tried to understand some simple assignments i

4条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-05 11:57

    is/2 is very low-level and limited. As you correctly observe, it cannot be used in all directions and is therefore not a true relation.

    For reversible arithmetic, use your Prolog system's constraint solvers.

    For example, SWI-Prolog's CLP(FD) manual contains the following definition of n_factorial/2:

    :- use_module(library(clpfd)).
    
    n_factorial(0, 1).
    n_factorial(N, F) :- N #> 0, N1 #= N - 1, F #= N * F1, n_factorial(N1, F1).
    

    The following example queries show that it can be used in all directions:

    ?- n_factorial(47, F).
    F = 258623241511168180642964355153611979969197632389120000000000 ;
    false.
    
    ?- n_factorial(N, 1).
    N = 0 ;
    N = 1 ;
    false.
    
    ?- n_factorial(N, 3).
    false.
    

    Of course, this definition still relies on unification, and you can therefore not plug in arbitrary integer expressions. A term like 2-2 (which is -(2,2) in prefix notation) does not unfiy with 0. But you can easily allow this if you rewrite this to:

    :- use_module(library(clpfd)).
    
    n_factorial(N, F) :- N #= 0, F #= 1.
    n_factorial(N, F) :- N #> 0, N1 #= N - 1, F #= N * F1, n_factorial(N1, F1).
    

    Example query and its result:

    ?- n_factorial(2-2, -4+5).
    true .
    

提交回复
热议问题