Search code examples
prologminimum

How to find the minimum value of a prolog variable in O(n) time without high order procedures


So I have an assignment to work on and there is one thing I'm confused about. Here is a similar problem to what I'm trying to accomplish. Say I have these rules:

size(3).
size(5).
size(7).
size(1).
size(2).
size(9).

And I want to find the minimum of size by taking the value 3 and comparing it to 5, storing 3 and comparing it to 7, then comparing it to 1, storing 1 and comparing it to 2...returning a value of 1.

The only way I can see of doing that without a high order procedure would be some form of backtracking while there are still size(X) values and each time altering the size variable. However, I don't see how you can both backtrack and save the new minimum value. I was wondering if anyone could help put me on the right track.


Solution

  • your assignment is intended to make you thinking about the peculiar control flow of Prolog, and indeed you are now to the point. I've coded the solution and placed some explanatory comment: fill in the ellipsis to complete the code

    find_min_size(MinSize) :-
        size(Hypothesis),
        !,  % without this cut the minimum is obtained more times...
        find_min_size(Hypothesis, MinSize).
    
    find_min_size(SoFar, MinSize) :-
        % when I should keep searching?
        ...
    
    % the exhaustive search come to end!
    find_min_size(MinSize, MinSize).
    

    I don't think in Prolog is possible to get O(N) performance, without 'higher order procedures' ( do you mean findall etc..? ). The code above will run in O(N^2). Indexing can't play a role, because size/1 will restart with unbound variable...

    An interesting O(N) alternative is using a failure driven loop and the tech that @false explained so well when introducing call_nth, (also, see here a follow up). All of these are in the 'impure' realm of Prolog, though...

    edit here the failure driven loop

    find_min_size(MinSize) :-
        State = (_, _),
        (   size(V),
            arg(1, State, C),
            ( ( var(C) ; V < C ) -> U = V ; U = C ),
            nb_setarg(1, State, U),
            fail
        ;   arg(1, State, MinSize)
        ).