Помогите в разработке хеш-функции для обнаружения дублирующихся записей? - PullRequest
3 голосов
/ 02 декабря 2010

Позвольте мне объяснить мою программу до сих пор. Это решатель кубик Рубика. Мне дают зашифрованный куб (это начальное состояние). Это становится корневым узлом графа. Я использую iterative deepening depth first search, чтобы «перебрать силу» этого зашифрованного куба до узнаваемого состояния, которое затем я могу использовать для распознавания образов.

Как вы можете себе представить, это очень большой график, поэтому я хотел бы предложить некоторую функцию хеширования для обнаружения дублирующих узлов в этом графике (таким образом, ускоряя обход).

Я в значительной степени незнаком с функциями хеширования, но вот что я думаю ... Каждый узел - это, по сути, другое состояние кубика Рубика. Поэтому, если я приду к состоянию куба (узлу), которое уже было видно, я хочу пропустить его. Поэтому мне нужна хеш-функция, которая переносит меня из переменной состояния в контрольную сумму, где переменная состояния представляет собой строку из 54 символов. Допустимые символы: y, r, g, o, b, w (соответствуют цветам).

Любая помощь в разработке этой хэш-функции будет принята с благодарностью.

Ответы [ 5 ]

2 голосов
/ 02 декабря 2010

1) Не используйте хэш У вас есть 9*6 = 54 отдельные лица на кубике Рубика. Даже расточительно используя 1 байт на лицевую сторону, это 432 бита, поэтому хеширование не сэкономит вам слишком много места. Лучшая упаковка из 3 битов на грани достигает 162 бит (21 байт). Для меня это звучит так, будто вам нужен компактный способ изобразить рубик.

OTOH, если вы хотите сохранить множество многих ранее посещенных состояний, я обнаружил, что использование фильтра Блума вместо истинного набора дает мне достойные результаты (но часто неоптимальные) с гораздо меньшим пространством использование.

2) Если вы женаты на идее хеширования: Просто используйте MD5, он немного более компактен, чем предложенные состояния рубика, довольно быстр и обладает хорошими свойствами столкновения - это не то же самое, что злоумышленник, пытающийся вызвать столкновения хеша кубика рубика; -).

РЕДАКТИРОВАТЬ: Использование криптографических хеш-функций, таких как MD4 / MD5, обычно просто, если у вас есть библиотека или функция, реализующая алгоритм (например: OpenSSL, GNU TLS и многие автономные реализации существуют). Обычно это что-то вроде void md5(unsigned char *buf, size_t len, unsigned char *digest), где digest указывает на предварительно выделенный 16-байтовый буфер, а buf - это данные, которые должны быть хешированы (ваша структура кубика Рубика). Вот некоторый непроверенный код C:

#include <openssl/md5.h>
void main()
{
    unsigned char digest[16];
    unsigned char buf[BUFLEN];
    initializeBuffer(buf);
    MD5(buf,BUFLEN,digest);    // This is the openssl function
    printDigest(digest);
}

И обязательно скомпилируйте / свяжите с -lssl.

2 голосов
/ 02 декабря 2010

Для быстрого обнаружения и удаления дубликатов - во-первых, избегайте генерации многих повторяющихся позиций .Это легко сделать и быстрее, чем создать и затем найти повторы.Так, например, если у вас есть движения, такие как F и B, если вы разрешаете подпоследовательность FB, не допускайте также BF, что дает тот же результат.Если вы только что сделали 3F, не следуйте за ним с F. Вы можете создать небольшую справочную таблицу для следующих разрешенных ходов, учитывая последние три хода.

Для оставшихся дубликатов вы хотите быстрый хеш, потому что там много позиций.Чтобы сделать ваш хеш быстрым, как прокомментировали другие, вы хотите, чтобы то, что он хеширует от , представление позиции, было бы маленьким .Есть 12 краевых кубиков и 8 угловых.Для представления положения и ориентации каждого куба требуется всего пять бит на куб, то есть всего 100 бит (12,5 байтов).Для ребер его четыре бита для положения и один для отражения.Для углов три бита для положения и 2 для вращения.Вы можете игнорировать последний край куба, так как его положение и переворот фиксируются другимиС этим представлением у вас уже есть 12 байтов для позиции.

У вас есть около 70 реальных битов информации в позиции кубика Рубика, и 96 битов достаточно близко к 70, чтобы сделать это фактически противодействующим хэшированию этих битов дальше.Т.е. относитесь к этому представлению доски как к вашему хешу.Это может показаться немного странным, но из вашего вопроса я предполагаю, что вы одновременно будете экспериментировать с менее компактным представлением куба, более подходящим для сопоставления с образцом.В этом случае 12-байтовое значение можно рассматривать как хэш , с тем преимуществом, что это хеш, который никогда не имеет коллизии .Это делает повторяющийся код тестирования и ввод нового значения короче, проще и быстрее.Это будет дешевле, чем предлагаемые решения MD5.

Существует множество других приемов, которые можно использовать для сокращения работы при поиске повторяющихся позиций.Посмотрите на http://cube20.org/ для идей.

2 голосов
/ 02 декабря 2010

Вы всегда можете попробовать криптографическую хеш-функцию. Поскольку ваша проблема не в безопасности (нет злоумышленника, который намеренно пытается найти различные состояния, которые хэшируют одно и то же значение), вы можете использовать хэш-функцию break . Я рекомендую попробовать MD4 , что довольно быстро. Ваша строка из 54 символов вполне подходит для ввода MD4 (MD4 может обрабатывать вводы до 55 байтов как один блок).

Базовый ПК с частотой 2,4 ГГц может хэшировать около 12 миллионов таких строк в секунду, используя одно ядро, с простой реализацией C (например, такой, которая будет выглядеть как функция MD4Transform() в примере кода, включенного в RFC 1320) , Этого может быть достаточно для ваших нужд.

1 голос
/ 18 января 2016

8 угловых кубов :

  • Вы можете назначить каждому из этих углов 8 позиций, каждая из которых требует 3 бита, чтобы определить, какой угловой куб находится в какой позиции в общей сложности 24 бита.
  • Вы можете дополнительно уменьшить это до записи 7 из 8 позиций, поскольку вы можете легко использовать процесс исключения, чтобы определить, что такое 8-й угол (для 21 бита).
  • Однако это может быть дополнительно уменьшено, поскольку 8 углов могут быть расположены только в 8! = 40320 перестановках, а 40320 может быть представлено в 16 битах.

Каждый угловой куб можно правильно ориентировать или поворачивать на 120 ° по часовой стрелке или против часовой стрелки, чтобы он находился в трех разных положениях (обозначенных как 0, 1 и 2 соответственно).

  • Для представления требуется 2 бита на угол.
  • Однако сумма ориентаций (по модулю 3) всегда равна 0; поэтому, если вы знаете ориентацию 7 из 8, то (при условии, что у вас есть решаемый куб) вы можете рассчитать ориентацию 8-го угла (всего 14 битов).
  • Или для дальнейшего сокращения семь троичных (основание 3) цифр могут представлять ориентацию углов, и это может быть представлено в 12 двоичных цифрах (битах).

Таким образом, кубы углов могут быть представлены в 28 битах, если вы хотите декодировать перестановки, или в 33 битах, если вы хотите напрямую записать позиции углов 7 из 8.

12 кубиков :

  • Каждый может быть представлен в 4 битах (всего 48 бит), которые могут быть уменьшены до 44 бит путем записи только позиции 11 из 12 ребер (всего 44 бита).
  • Однако перестановки ребер 12! = 479001600 можно сохранить в 29 битах.

Каждый край может быть правильно ориентирован или перевернут:

  • Для представления требуется 1 бит.
  • Однако ребра всегда переворачиваются парами, поэтому четность перевернутых ребер всегда будет равна нулю (опять же, это означает, что вам нужно записать только 11 из 12 ориентаций для ребер), что дает в общей сложности 11 битов.

Таким образом, кубы ребер могут быть представлены в 40 битах, если вы хотите декодировать перестановки, или в 55 битах, если вы хотите записать все позиции и щелчки ребер 11 из 12.

6 центральных кубов

Вам не нужно записывать какую-либо информацию о центральных кубах - они зафиксированы относительно шара в центре кубика Рубика (поэтому, если вы не беспокоитесь о ориентации любых логотипов на кубе), они неподвижны.

Total

  • Использование перестановок: 68 бит
  • Использование позиций: 88 бит
1 голос
/ 03 декабря 2010

Просто чтобы установить теоретическое минимальное представление - пространство состояний действительного куба Рубика составляет около 4.3*10^19.Журнал 2 (4.3 * 10 ^ 19) будет затем определять, сколько бит вам нужно для представления этого полного пространства, , потолок которого равен 66 .Так что в теории , если бы вы могли пронумеровать каждое действительное состояние, любое данное состояние могло бы быть уникально представлено в 66 битах.

Хотя вы можете последовать совету других и найти более компактный способпредставления куба, рассмотрите возможность представления состояния в виде ребер, углов и граней.Из-за законов смены законных перемещений куба вы должны иметь возможность объединить последовательность из 12 4-битных краевых местоположений, 8 3-битных угловых местоположений и 6 3-битных местоположений граней.Это должно привести к уникальному представлению, использующему 90 битов.

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

...