Prolog - генерация чисел, соответствующих заданному диапазону

Я хотел бы использовать такие предикаты, как:

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

со смыслом:

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]).

Как красиво закодировать это на Прологе (принимая во внимание производительность решения - глубину рекурсии и т. д.)?

Ожидается, что решение будет работать на GNU-Prolog.

P.S. Вопрос, вдохновленный этим вопросом.


person Grzegorz Wierzowiecki    schedule 24.08.2011    source источник


Ответы (3)


SWI-Prolog имеет предикат between/3. так что вы бы назвали это как between(0,5,X), чтобы получить результаты, которые вы показали выше. Этот предикат выглядит так, как будто он реализован на C.

Если нам нужно написать это на чистом прологе (и скорость и пространство не имеют значения), вы можете попробовать следующее.

range(Low, Low, High).
range(Out,Low,High) :- NewLow is Low+1, range(Out, NewLow, High).
person DaveEdelstein    schedule 24.08.2011
comment
Это применимо к domain() ? - person Grzegorz Wierzowiecki; 24.08.2011
comment
что такое домен? я не мог сказать, что вы ожидали от dom_range в приведенном выше сценарии. это просто еще один способ передать аргументы в диапазон? dom_range(Out, [Низкий, Высокий]): - range(Out, Low, High). - person DaveEdelstein; 25.08.2011
comment
Я прочитал о домене на этом учебник, но я не уверен в деталях, потому что я новичок в Прологе. При проверке руководства по Gnu-Prolog я нашел fd_domain/3, указанный как fd_domain(+fd_variable_list_or_fd_variable, +integer, +integer) — как вы считать ? Может быть другое решение? - person Grzegorz Wierzowiecki; 25.08.2011
comment
fd_domain, по-видимому, является частью библиотеки конечных доменов и не так универсален, как предикаты swi between или my range. если библиотека fd чем-то похожа на clpfd (ограничение линейной обработки конечного домена), то fd_domain просто устанавливает ограничение на переменную (или список). фактические значения не привязываются к переменным до тех пор, пока не будет маркировка< Выполняется предикат /a>, после чего учитываются все ограничения и привязывается значение. - person DaveEdelstein; 06.09.2011
comment
Спасибо за разъяснения. :). Так что оба решения имеют свои плюсы и минусы, так что имхо полезно знать оба :). - person Grzegorz Wierzowiecki; 06.09.2011
comment
Фрагмент, указанный в ответе, для меня не заканчивается на High. - person PROgram52bc; 13.02.2021

Ответ Дэйва почти идеален: нет проверки, чтобы увидеть, является ли низкий ‹ высоким. Я добавил условие, и теперь оно работает нормально (иначе генерирует числа от младших до бесконечности):

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

Надеюсь, это поможет!

person aurik    schedule 22.12.2011

range в Gnu-Prolog можно решить с конечными областями

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

Я не знаю, если dom_range(X,L,H) :- fd_domain(X,L,H) .

P.S. При игре с конечными доменами вы можете использовать fd_set_vector_max/1

person Grzegorz Wierzowiecki    schedule 27.08.2011