11

I'd like to use predicates like:

range(X,0,5)
range(X,4,200)
range(X,-1000000,1000000)
dom_range(X,-1000000,1000000)

with meaning :

range(X,0,5) :- member(X,[0,1,2,3,4,5]).
range(X,4,200) :- member(X,[4,5,6...198,199,200]).
range(X,-1000000,1000000) :- member(X,[-1000000,...,1000000]).
dom_range(X,-1000000,1000000) :- domain(X, [-1000000,...,1000000]).

How to code it in Prolog nicely (taking solution performance into account - depth of recursion etc) ?

Solution is expected to run on GNU-Prolog.

P.S. Question inspired with this question.

Isabelle Newbie
  • 9,258
  • 1
  • 20
  • 32
Grzegorz Wierzowiecki
  • 10,545
  • 9
  • 50
  • 88

3 Answers3

14

SWI-Prolog has the predicate between/3. so you would call it like between(0,5,X) to get the results you showed above. This predicate looks like this is implemented in C though.

If we have to write it in pure prolog (and speed&space is not a factor), you could try this following.

range(Low, Low, High).
range(Out,Low,High) :- NewLow is Low+1, range(Out, NewLow, High).
DaveEdelstein
  • 1,256
  • 8
  • 14
  • Is it applicable to `domain()` ? – Grzegorz Wierzowiecki Aug 24 '11 at 13:45
  • what is domain exactly? i couldnt tell what you expected dom_range to do in the above scenario. is this just another way to pass arguments to range? dom_range(Out, [Low, High]) :- range(Out, Low, High). – DaveEdelstein Aug 24 '11 at 20:46
  • I've read about "domain" at [this tutorial](http://wazniak.mimuw.edu.pl/index.php?title=Sztuczna_inteligencja/SI_Modu%C5%82_3_-_Wnioskowanie_w_PROLOG-u), but I'm unsure about details, cause I'm Prolog beginner. While checking at Gnu-Prolog manual I've found [fd_domain/3](http://www.gprolog.org/manual/gprolog.html#htoc321), specified as [fd_domain(+fd_variable_list_or_fd_variable, +integer, +integer)](http://www.gprolog.org/manual/gprolog.html#htoc321) - how do you think ? Might it be another solution ? – Grzegorz Wierzowiecki Aug 24 '11 at 23:40
  • 2
    fd_domain appears to be part of the Finite Domain library and not exactly as general purpose as swi's between or my range predicates. if the fd library is anything like clpfd (constraint linear processing finite domain), then fd_domain is just setting up a constraint on a variable (or list). actual values are not bound to the variables until some sort of [labeling](http://www.swi-prolog.org/pldoc/doc_for?object=clpfd:labeling/2) predicate is ran, at which point all constraints are considered and a value is bound. – DaveEdelstein Sep 06 '11 at 18:49
  • 1
    Thank you for clarification. :). So both solutions have it's prons and cons, so imho it's good to know both :). – Grzegorz Wierzowiecki Sep 06 '11 at 19:52
  • 1
    Also GNU has between/3 which is part of the [Prolog prologue](http://www.complang.tuwien.ac.at/ulrich/iso-prolog/prologue#between). – false Jun 12 '14 at 20:29
  • The snippet given in the answer doesn't seem to terminate at `High` for me. – PROgram52bc Feb 13 '21 at 14:13
13

Dave's answer is almost perfect: there is no check to see if low < high. I added a condition and now it works fine (otherwise it generates numbers from low to infinity):

range(Low, Low, High).
range(Out,Low,High) :- NewLow is Low+1, NewLow =< High, range(Out, NewLow, High).

Hope that helps!

aurik
  • 151
  • 1
  • 4
1

range in Gnu-Prolog can be solved with finite domains

range(X,Low,High) :- fd_domain(X,Low,High).

I don't know if dom_range(X,L,H) :- fd_domain(X,L,H) .

P.S. When playing with finite domains, you might like to use fd_set_vector_max/1

Grzegorz Wierzowiecki
  • 10,545
  • 9
  • 50
  • 88