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, вы можете попытаться найти две лучшие команды, и в большинстве случаев вы получите окончательный ответ. Решение трехстороннего розыгрыша, как указано выше, обычно разрешается с использованием монеты.