Как отсортировать вывод в Прологе?

У меня есть следующий предикат:

soln(L,M,O,R,S,V) :-
    permutation([L,M,O,R,S,V],[1,2,3,4,5,6]),
    R=\=S+1,
    R=\=S-1,
    M=:=L+1,
    O>M,
    O<S.

Когда я звоню из REPL, он выводит правильные ответы:

?- soln(L,M,O,R,S,V).
L = 1,
M = 2,
O = 3,
R = 4,
S = 6,
V = 5 ;
L = 1,
M = 2,
O = 3,
R = 6,
S = 4,
V = 5 .

Тем не менее, более полезным для меня будет вывод, где переменные сортируются в соответствии с их значением; использовать предыдущий пример, что-то вроде [L,M,O,R,V,S], [L,M,O,S,V,R], ... было бы идеально.

Я хотел бы быть в состоянии сделать это как в REPL, так и в автономном скрипте.

1 ответ

Решение

Если вы хотите отсортировать имена в соответствии с их значениями, вы должны отслеживать связь между переменными и их именами.

Это связано с тем, что имена переменных, которые вы видите в исходном коде, недоступны в программе Prolog, поэтому вы должны отслеживать имена так, чтобы они были доступны в Prolog.

Один из способов сделать это - отслеживать список пар вида Variable-Name, Таким образом, когда переменная связана со значением, вы все равно знаете ее предполагаемое имя.

Поэтому я предлагаю следующую небольшую переписать:

: - use_module (библиотека (clpfd)). решение (пары):-
        Vs = [L,M,O,R,S,_V], имена = [l,m,o,r,s,v],
        pair_keys_values ​​(пары, Vs, имена), R # \ = S + 1, R # \ = S-1, M # = L + 1, O #> M, O #

Обратите внимание, что я сейчас использую атомы l, m, o и т.д., чтобы обозначить имена переменных, и теперь я рассуждаю о парах. Кроме того, я взял на себя смелость выразить все это с помощью ограничений, поэтому мы получаем выгоду от распространения ограничений вместо того, чтобы пробовать каждую перестановку. Используя ограничения, механизм Prolog может обрезать значительную часть пространства поиска, даже не пробуя его. я использую _V обозначить переменную V, потому что эта переменная не упоминается где-либо еще, и с помощью V поэтому приведет к одноразовому предупреждению.

Мы уже можем попробовать это:

? - решение (пары),
   pair_keys_values ​​(пары, имена, имена),
   этикетки (Vs).Пары = [1-1, 2-м, 3-о, 1-р, 4-с, 1-V], Vs = [1, 2, 3, 1, 4, 1],
Имена = [l, m, o, r, s, v];Пары = [1-1, 2-м, 3-о, 1-р, 4-с, 2-V], Vs = [1, 2, 3, 1, 4, 2],
Имена = [l, m, o, r, s, v];Пары = [1-1, 2-м, 3-о, 1-р, 4-с, 3-V], Vs = [1, 2, 3, 1, 4, 3],
Имена = [l, m, o, r, s, v];
и т.п.

Теперь, чтобы отсортировать имена по значениям этих переменных, используйте предикат ISO keysort/2, который сортирует пары в соответствии с их ключами, то есть их первым компонентом:

? - решение (Pairs0),
   pair_keys_values ​​(Pairs0, Vs0, Names0),
   Этикетка (Vs0),
   сортировка ключей (Pairs0, Pairs),
   пары_значения (пары, имена).
Pairs0 = [1-l, 2-m, 3-o, 1-r, 4-s, 1-v],
Vs0 = [1, 2, 3, 1, 4, 1],
Имена 0 = [l, m, o, r, s, v],
Пары = [1-l, 1-r, 1-v, 2-m, 3-o, 4-s],Имена = [l, r, v, m, o, s]; Pairs0 = [1-l, 2-m, 3-o, 1-r, 4-s, 2-v],
Vs0 = [1, 2, 3, 1, 4, 2],
Имена 0 = [l, m, o, r, s, v],
Пары = [1-l, 1-r, 2-m, 2-v, 3-o, 4-s],Имена = [l, r, m, v, o, s]; Pairs0 = [1-l, 2-m, 3-o, 1-r, 4-s, 3-v],
Vs0 = [1, 2, 3, 1, 4, 3],
Имена 0 = [l, m, o, r, s, v],
Пары = [1-l, 1-r, 2-m, 3-o, 3-v, 4-s],Имена = [l, r, m, o, v, s]; Pairs0 = [1-l, 2-m, 3-o, 1-r, 4-s, 4-v],
Vs0 = [1, 2, 3, 1, 4, 4],
Имена 0 = [l, m, o, r, s, v],
Пары = [1-l, 1-r, 2-m, 3-o, 4-s, 4-v],Имена = [l, r, m, o, s, v]; и т.п.
Другие вопросы по тегам