Как отсортировать вывод в Прологе?
У меня есть следующий предикат:
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]; и т.п.