Сортировать список чего-либо по отношениям - PullRequest
3 голосов
/ 23 ноября 2011

В приложении, которое я делаю, мне дают список элементов, и отношения между ними и мне нужно вычислить отсортированный список. Для забавы, давайте использовать пример оценки экзамена, мы знаем, что:

  1. Джон справился лучше, чем Джейн

  2. Джейн сделала хуже, чем Люк

  3. Люк справился лучше, чем Джейсон

  4. Джейсон сделал хуже, чем Тим

Для этого списка мне нужно вычислить следующий отсортированный список:

  1. John
  2. Люк
  3. Jane
  4. Тим
  5. Jason

Как получить позицию элемента в отсортированном списке на основе оспариваемых отношений?

Ответы [ 2 ]

3 голосов
/ 23 ноября 2011

По сути, сортировка требует линейного порядка .

Ваше отношение должно быть линейным, что означает:

  1. a ≤ a (рефлексивность)
  2. если a ≤ b и b ≤ a, то a = b (антисимметрия)
  3. если a ≤ b и b ≤ c, то a ≤ c (транзитивность)
  4. для всех a и b, a ≤ b или b ≤ a (совокупность)

Итак, что это значит? Большинство обычных отношений линейны. Например, если вы говорите о оценках, которые на самом деле являются действительными числами, то да, оценки могут быть линейно упорядочены. Рейтинги тоже, так как они опять-таки являются только действительными числами.

Но, например, если вы занимаетесь ранжированием шахматистов, вы не можете использовать их историю матчей. Если игрок A побил игрока B в большинстве своих матчей, а B снова победил C в большинстве своих матчей, это НЕ означает, что A> B> C, просто потому что C, возможно, победил A в большинстве своих матчей. матч.

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

Итак, для оценки экзамена у вас просто нет этого линейного порядка. Зачем? Это реальные цифры! Ну, правда, у вас есть этот линейный порядок, но вы не можете задать этот линейный порядок все, вы ограничены предварительно определенным списком сравнения, который находится здесь:

  1. Джон добился большего успеха, чем Джейн
  2. Джейн сделала хуже, чем Люк
  3. Люк справился лучше, чем Джейсон
  4. Джейсон сделал хуже, чем Тим

Итак, ответ: Нет, вообще, вы не можете отсортировать список, если у вас нет сравнения между какой-либо парой элементов.

Сейчас я работаю над "наименее плохим" ответом, но для меня это не тривиально ...


Редактировать: ОК, я что-то придумал. Идея состоит в том, что вы собираетесь извлечь максимально возможную информацию из вашего предварительно определенного списка сравнения. Затем рассматривайте любое сравнение, отсутствующее в расширенном списке сравнения, как равенство.

Итак, как ты это делаешь?

Сначала, для любого сравнения a. Затем вы просматриваете свой предопределенный список сравнения для любого сравнения a a. Если вы знаете, что нет равных (ни один учащийся не имеет одинаковую оценку), он закончен. Иначе, вы должны добавить все отношения рефлексивности и антисимметрии. Вы ничего не можете сделать с тотальностью. Теперь у вас есть расширенный список сравнения.

Теперь возьмите ваш любимый алгоритм сортировки. Если у вас его нет, quicksort приятно, эффективно и коротко написать. Затем каждый раз, когда алгоритм запрашивает сравнение между a и b, вместо этого смотрите на свой расширенный список сравнения. Если сравнение здесь, отлично, обработайте сравнение как a = b. (Обратите внимание, что не имеет значения, если вы знаете, что нет равенств, алгоритму все равно)

Результатом будет отсортированный список «наименее плохо». Обычно существует несколько возможных отсортированных списков «наименее плохо», но этот алгоритм даст вам только один.


Итак, давайте приведем пример. Это почти то же самое, что дано в ОП, с небольшой разницей («Джон сделал хуже, чем Люк» вместо «Джейн сделал хуже, чем Люк»). Итак, начнем с:

  1. Джон добился большего успеха, чем Джейн
  2. Джон сделал хуже, чем Люк
  3. Люк справился лучше, чем Джейсон
  4. Джейсон сделал хуже, чем Тим

Теперь, для каждого «X хуже, чем Y», я добавляю «Y лучше, чем X», и наоборот. Новые предложения выделены жирным шрифтом:

  1. Джон добился большего успеха, чем Джейн
  2. Люк справился лучше, чем Джон
  3. Люк справился лучше, чем Джейсон
  4. Тим добился большего успеха, чем Джейсон
  5. Джейнсделал хуже, чем Джон
  6. Джон сделал хуже, чем Люк
  7. Джейсон сделал хуже, чем Люк
  8. Джейсон сделал хуже, чем Тим

Наконец, я просматриваю все возможные предложения «X сделал лучше, чем Y» и «Y сделал лучше, чем Z», и добавляю «X сделал лучше, чем Z»

  1. Джон добился большего успеха, чем Джейн
  2. Люк справился лучше, чем Джон
  3. Люк справился лучше, чем Джейсон
  4. Тим добился большего успеха, чем Джейсон
  5. Люк справился лучше, чем Джейн
  6. Джейн сделала хуже, чем Джон
  7. Джон сделал хуже, чем Люк
  8. Джейсон сделал хуже, чем Люк
  9. Джейсон сделал хуже, чем Тим
  10. Джейн сделала хуже, чем Люк

Расширенный стол закончен.

Давайте теперь посмотрим на псевдокод быстрой сортировки:

  function quicksort('array')
      if length('array') ≤ 1
          return 'array'  // an array of zero or one elements is already sorted
      select and remove a pivot value 'pivot' from 'array'
      create empty lists 'less' and 'greater'
      for each 'x' in 'array'
          if 'x' ≤ 'pivot' then append 'x' to 'less'
          else append 'x' to 'greater'
      return concatenate(quicksort('less'), 'pivot', quicksort('greater'))

Отличие * от стандартной быстрой сортировки состоит в том, что вы вообще не можете знать ответ на вопрос if('x' ≤ 'pivot') .... Так что вместо этого, если x=Luke и pivot = Tim, вы ищите в своей таблице предложение «Люк сделал хуже, чем Тим». Если вы найдете его, то считаете, что ответ true и делаете append 'x' to 'less'. Если вы найдете в таблице «Люк сделал лучше, чем Тим», то вы считаете, что ответ ложный, и вы делаете append 'x' to 'greater'. И, наконец, если вы не можете найти ни одного из двух предложений, упомянутых выше, вы действуете как 'x' == 'pivot', и вы делаете append 'x' to 'less'

2 голосов
/ 23 ноября 2011

Если вы выберете алгоритм http://en.wikipedia.org/wiki/Topological_sorting для этого, вы можете посмотреть на результат, чтобы увидеть, находятся ли какие-либо два человека в фиксированном порядке: если так, то один будет доступен из другого.Если ваши данные непротиворечивы, топологическая сортировка даст вам линейный порядок, который согласуется с вашими данными, но может подразумевать порядок, который ваши данные фактически не поддерживают, из-за отсутствия сравнений, чтобы сказать, действительно ли Адам добился большего успеха, чем Билл.

Если ваши данные не очень особенные, вы, вероятно, найдете несколько случаев, когда на графике есть циклы, и поэтому ни один порядок не является последовательным.Вы можете найти группы людей, связанных в таких циклах с http://en.wikipedia.org/wiki/Strongly_connected_component.

Если вам нужно разрешить зашумленные и противоречивые данные, вам, вероятно, придется обратиться к какой-то статистической системе ранжирования.Сводка сводится к http://en.wikipedia.org/wiki/Pairwise_comparison. Дальнейший веб-поиск покажет вам, что модель Брэдли-Терри можно приспособить различными способами, включая логистическую регрессию, так что это одна из отправных точек, хотя, конечно, естьогромное разнообразие других систем подсчета очков, некоторые из которых связаны со спортом и играми, такими как http://en.wikipedia.org/wiki/Elo_rating_system

...