2016-11-27 3 views
3

Есть ли способ показать все решения и/или найти, сколько их имеется в прологе SICSTus? Например, приведенный ниже код может быть использован для решения проблемы окраски карты.SICStus Prolog: Найти все решения

:- use_module(library(clpfd)). 
solve_AUSTRALIA(WA,NT,Q,SA,NSW,V):- 
    domain([WA,NT,Q,SA,NSW,V], 1, 4),%colours represented by integers from 1 to 4 
    WA #\= NT, 
    WA #\= SA, 
    NT #\= SA, 
    NT #\= Q, 
    SA #\= Q, 
    SA #\= NSW, 
    SA #\= V, 
    Q #\= NSW, 
    NSW #\= V, 
    labeling([],[WA,NT,Q,SA,NSW,V]). 

На данный момент я печатаю ; каждый раз, чтобы увидеть дальнейшие решения по Пролог говорит нет. Есть ли способ, которым я могу сказать, что пролог показывает все решения сразу или лучше, способ, которым я могу найти, сколько там. Как и пролог, мне говорят, что есть пять решений проблемы.

+0

Вы можете попытаться использовать 'findall/3',' findall/4', 'bagof/3' или' setof/3'. Они подобны. Например, то, что вы хотите сделать, это предикат вашего решения в 'findall (+ Templagte,: Solution, -Bag)' и исходный набор данных как 'Template', а коллективное решение -' -Bag'. –

+0

Общий совет для clpfd в SICStus: произнесите 'assert (clpfd: full_answer)' на верхнем уровне, чтобы получить полный ответ, включая все связанные ограничения! – false

ответ

3

Для подсчета количества ответов необходимо следующее. Когда вы запрашиваете запрос или выполняете предикат, то, что вы получаете от Prolog, являются ответами. Иногда эти ответы являются решениями, могут содержать более одного решения, бесконечно много решений, а иногда даже и никакого решения.

Самый простой способ - сказать findall(t, Goal_0, Ts), length(Ts, N). Единственным недостатком является то, что для этого требуется пространство, пропорциональное количеству подсчитанных ответов.

Если вы хотите сделать еще один шаг, вам нужен какой-то счетчик. В настоящее время в SICStus 4.3.3 вы можете сделать это следующим образом:

:- meta_predicate count_answers(0, ?). 
:- meta_predicate count_answers1(0, +, ?). % internal 

:- use_module(library(types),[must_be/4]). 

:- use_module(library(structs), 
     [new/2, 
      dispose/1, 
      get_contents/3, 
      put_contents/3]). 

count_answers(G_0, N) :- 
    ( nonvar(N) 
    -> must_be(N, integer, count_answers(G_0, N), 2) 
    ; true 
    ), 
    new(unsigned_64, Ref), 
    call_cleanup(count_answers1(G_0, Ref, N), dispose(Ref)). 

count_answers1(G_0, Ref, N) :- 
    ( call(G_0), 
     get_contents(Ref, contents, N0), 
     N1 is N0+1, 
     put_contents(Ref, contents, N1), 
     fail 
    ; get_contents(Ref, contents, N) 
    ). 

См this answer как счетчики могут быть реализованы в других системах. Пример использования:

| ?- count_answers(member(_,"abcde"),Ans). 
Ans = 5 ? ; 
no 
Смежные вопросы