Sort/2, keysort/2 против samsort/3, predsort/3
ISO-Prolog предоставляет sort/2
и keysort/2
, который опирается на термин порядок (7.2), который часто называют "стандартным срочным порядком".
Обычный способ сортировки списка с другим порядком состоит в том, чтобы сопоставить каждый элемент El
этого списка как-то с списком пар XKey-El
, а затем отсортировать этот список и, наконец, проецировать ключи. В качестве примера рассмотрим, как keysort/2
можно выразить в терминах sort/2
(См. Примечание для реализации).
Во многих ситуациях этот подход намного быстрее, чем использование типичного предиката сортировки реализации, который зависит от пользовательского порядка как SWI predsort(C_3, List, SortedList)
или SICStus samsort(O_2, List, SortedList)
.
Мой вопрос сводится к:
Существуют случаи, когда сортировка с использованием predsort/3
соответственно. samsort/3
не может быть заменено некоторым отображением, sort/2
-инг и проецирование? 1
И для ясности лучше придерживаться конечных, наземных терминов. Ибо бесконечные земные члены не обладают полным лексикографическим порядком, так как это необходимо в качестве расширения конечного случая; и далее неясно, как будет показано сравнение переменных с случаем зависимых от реализации двух разных переменных, приведенное в 7.2.1 ИСО/МЭК 13211-1:1995:
7.2.1 Переменная
Если X
и Y
- переменные, которые не идентичны, то X
term_precedes Y
должен быть зависимым от реализации
за исключением того, что во время создания отсортированного списка (7.1.6.5,
8.10.3.1 j) порядок должен оставаться постоянным.
Так что неясно, будет ли predsort/3
по-прежнему квалифицироваться как
создание отсортированного списка. Ясно, что упорядочение остается неизменным во время sort/2
и keysort/2
.
1 Благодаря @WillNess эта проекция должна по крайней мере включать также reverse/2
— или любое линейное преобразование. Это также означает, что результаты с использованием как дубликатов, так и уникальных могут быть реализованы (аналогично тому, как реализуется keysort/2
).
Ответы
Ответ 1
Во-первых, вы можете "отрицать" атомы Пролога. Позвольте называть его atom_neg/2
(это глупое имя, но оно все равно делает глупо):
atom_neg(A, NK) :-
atom_codes(A, Cs),
maplist(negate, Cs, NCs),
append(NCs, [0], NK).
negate(X, N) :- N is -X.
Я не утверждаю, что это практично, но, по-видимому, это возможно.
Полное упорядочение является слабым порядком, а ключевая функция f на множестве T вместе с полным порядком r на кодомане f, определяет слабый порядок wr (x, y) < == > r (f (x), f (y)).
(Codomain функции в этом контексте является областью значений, возвращаемых функцией.)
Возможно, я ошибаюсь, но наличие отношения требует наличия ключа: вы можете определить отношение в терминах другого отношения, но в конечном итоге вы должны сравнить то, что может существовать и в изоляции: ключ.
Дело в том, что ключ не должен находиться в том же домене, что и предмет, который мы хотим отсортировать, и что для объектов тот же домен. Пролог делает что-то странное здесь: он определяет стандартный порядок терминов для всех возможных терминов. В Prolog также нет правильного понятия "типы" или "домены". Чувство моего чувства говорит мне, что сортировка вещей, не принадлежащих к одному домену, просто не очень полезна, но Prolog явно не согласен.
Вы не можете определить ключевую функцию для двух случаев:
- Предикат сравнения сохраняет свое собственное состояние;
- У вас есть "непрозрачные" объекты (например, определенные в C), которые предоставляют функцию сравнения, но не ключевую функцию.
В любом случае, predsort
может быть полезным: никто не предпочел бы atom_neg/2
над решением Will Ness. Тем не менее, на данный момент у него есть одна серьезная дезинфекция: она не дает стабильного вида. SWI-Prolog уже может использоваться таким образом, все, что потребуется, - это добавить текущее поведение к спецификации и документации predsort/3
.
Ответ 2
edit: ответ от @Boris показывает, как "отрицать" атомы для целей сравнения, поэтому в этом случае он аннулирует мой contr-аргумент. И новое условие в вопросе полностью отменяет его.
В случае сложных критериев сортировки необходимо будет расположить несколько под-клавиш. Если желательно сохранить дубликаты, приращение индексов должно быть префиксом к исходному термину, следуя разделам сортировки, в терминах, построенных для sort/2
для сортировки.
Сложность и количество построенных подразделов могут выйти из-под контроля. Точки сортировки изображений по X сначала, а затем по Y, по восходящим или нисходящим порядкам в некоторых регионах, а по Y сначала, а по X секундам - в других.
Тогда искомое преимущество замены логарифмического числа (предположительно вычислительно тяжелых) сравнений с только линейным числом конструкций ключей и логарифмическим числом (предположительно световых) сравнений в стандартном порядке термов может исчезнуть.
Тривиально, predsort/3
ing, например. список атомов в обратном порядке, с пользовательским предикатом сравнения
comp(<,A,B):- B @< A.
и т.д. не может выполняться sort/2
ing, который работает в "стандартный порядок терминов" (цитируя документацию SWI), С числами мы можем перевернуть знак, но не с именами.
Возможно, вы захотите добавить reverse
к разрешенным действиям.
Если разрешено sort/4
, я не вижу ничего, что бы не сработало. И поскольку он устойчив, вторичные критерии могут быть также учтены вторичными проходами (сначала небольшим, затем основным критерием).
Ответ 3
Я думаю, что у меня может быть правильный ответ на ваш вопрос.
Если у вас есть частичный заказ, вы все равно можете попробовать и сортировать с помощью predsort/3
, и вы можете получить лучший результат, чем просто сказать: "полного заказа не существует".
Вот пример: скажем, у вас есть игра, в которую играют две команды. Каждая игра дает точку только одной из команд, и вы играете, пока одна команда не достигнет определенного количества очков.
Теперь вы организуете турнир, и у него групповой этап, в группах из 4 команд, который является круговым. Только две лучшие команды делают это из групп.
Для каждой игры игроки получают оценку own_points - other_teams_points
. Другими словами, если вы играете до 7, и окончательный счет:
Команда A - 5: 7 - Команда B
их результаты в группе A -2 и в команде 2.
В конце группового этапа вы заказываете команды:
- Общий балл
- Если общий балл один и тот же, команда, выигравшая прямую битву, приказана выше.
В первую очередь, используя эту схему подсчета очков, вы не можете разрешить трехстороннюю ничью, если команда A обыграла команду B, команда B выиграла команду C, а Team C обыграла команду A. "Стабильный", сортировка не имеет смысла в этом контексте.
Однако, используя predsort/3
, вы можете попытаться найти две лучшие команды, и в большинстве случаев вы получите окончательный ответ. Решение трехстороннего розыгрыша, как указано выше, обычно разрешается с использованием монеты.