Генерация минимальных/неприводимых судоку

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

У меня есть базовый алгоритм для создания минимальных судоку:

  • Создайте завершенную головоломку.
  • Visit each cell in a random order. For each visited cell:
    • Tentatively remove its digit
    • Решите головоломку дважды, используя алгоритм рекурсивного поиска с возвратом. Один решатель пробует цифры от 1 до 9 в прямом порядке, другой — в обратном. В некотором смысле решатели обходят дерево поиска, содержащее все возможные конфигурации, но с противоположных концов. Это означает, что два решения совпадут, если головоломка имеет единственное решение.
    • Если головоломка имеет единственное решение, удалите цифру навсегда; в противном случае вставьте его обратно.

Этот метод гарантированно создаст минимальную головоломку, но он довольно медленный (100 мс на моем компьютере, несколько секунд на смартфоне). Я хотел бы уменьшить количество решений, но все очевидные способы, которые я могу придумать, неверны. Например:

  • Добавление цифр, а не их удаление. Преимущество этого заключается в том, что, поскольку минимальные головоломки требуют не менее 17 заполненных цифр, первые 17 цифр гарантированно не будут иметь уникального решения, что снижает объем решения. К сожалению, поскольку ячейки посещаются в случайном порядке, перед одной важной цифрой, которая «блокирует» уникальное решение, будет добавлено много ненужных цифр. Например, если первые 9 добавленных ячеек находятся в одном столбце, там много избыточной информации.
  • Если никакая другая цифра не может заменить текущую, сохраните ее и не решайте головоломку. Поскольку проверка того, является ли место размещения законным, выполняется в тысячи раз быстрее, чем решение головоломки дважды, это может быть огромным экономит время. Однако тот факт, что сейчас нет другой допустимой цифры, не означает, что ее не будет позже, когда мы удалим другие цифры.
  • Поскольку мы сгенерировали исходное решение, решите только один раз для каждой ячейки и посмотрите, совпадает ли оно с исходным. Это не работает, поскольку исходное решение может находиться в любом месте дерева поиска возможных решений. Например, если исходное решение находится рядом с «левой» стороной дерева, и мы начнем поиск слева, мы пропустим решения с правой стороны дерева.

Также хотелось бы оптимизировать сам алгоритм решения. Трудная часть - определить, является ли решение уникальным. Я могу выполнить микрооптимизацию, например создать битовую маску допустимых мест размещения для каждой ячейки, как описано в этот замечательный пост. Однако более продвинутые алгоритмы, такие как Dancing Links или имитация отжига, предназначены не для определения уникальности, а просто для поиска любого решения.

Как мне оптимизировать мой минимальный генератор судоку?


person 1''    schedule 03.01.2013    source источник
comment
Generate a completed puzzle. Пожалуйста, определите полный   -  person wildplasser    schedule 04.01.2013
comment
Я думаю, вы могли бы улучшить исходное решение, используя один решатель с возвратом, а не два. Как только он найдет решение, не останавливайтесь — продолжайте поиск, пока не найдете другое решение. Как только вы найдете второе решение, остановитесь.   -  person mbeckish    schedule 04.01.2013
comment
wildplasser, завершенный означает полностью заполненный. мбекиш, отличная идея!   -  person 1''    schedule 04.01.2013
comment
Кроме того, думаю, у вас должна быть только одна начальная головоломка. После того, как вы создали из него несократимую головоломку, вы можете изменить порядок строк и столбцов в их кластере, изменить порядок строк и столбцов кластеров и перекрасить головоломку. Однако я не уверен, что это приводит к каждой возможной неразрешимой головоломке.   -  person    schedule 04.01.2013
comment
Определенно нет, так как несократимые головоломки могут иметь разное количество элементов. Идея состоит в том, чтобы генерировать головоломки по запросу для приложения для смартфона, а не перечислять все возможные головоломки.   -  person 1''    schedule 04.01.2013
comment
Сравнение с исходным решением было бы быстрым способом исключить удаление. Вероятно, сэкономить много времени эвристически. Если бы оно совпало, вам все равно пришлось бы выполнить второе решение (или, как отмечает @mbeckish, продолжить первый возврат), но если оно не совпало, вы можете немедленно продолжить.   -  person user295691    schedule 04.01.2013
comment
Можно попробовать запомнить все промежуточные состояния вашего решателя при прогонах — т. е. каждый раз, когда ваш решатель просматривает головоломку с определенной конфигурацией, он проверяет таблицу, чтобы увидеть, не было ли уже найдено решение. Если это так, верните это немедленно; если нет, решите головоломку и сохраните результат в таблице. Если вы сделаете это с каждой конфигурацией платы (каждым шагом каждого решателя), то, похоже, вы быстро доберетесь до точки, где ваш решатель почти всегда попадает в стол после пары шагов.   -  person jacobm    schedule 04.01.2013
comment
Это может работать хорошо, но это не так надежно, как предлагают другие оптимизации. Я могу попробовать, если они недостаточно хороши сами по себе.   -  person 1''    schedule 04.01.2013
comment
Dancing Links, безусловно, можно использовать для проверки нескольких решений. См. garethrees.org/2007/06/10/zendoku-generation/ #section-4.4 например.   -  person Reinstate Monica    schedule 04.01.2013
comment
Спасибо, я проверю это.   -  person 1''    schedule 04.01.2013


Ответы (2)


У меня есть идея on the 2nd option, которую вы предложили, будет лучше, если вы добавите 3 дополнительные проверки для первых 17 номеров.

  • найти список из 17 случайных чисел от 1 до 9
  • добавить каждый элемент в случайное указанное место

    1. эти новые добавленные числа не нарушают 3 основных критерия судоку

      • there is no same number in same row
      • нет одинаковых чисел в одном столбце
      • в той же матрице 3x3 нет одинаковых чисел
    2. если условие 1 не выполняется, перейдите к следующему столбцу или строке и снова проверьте 3 основных критерия.

    3. если нет следующей строки (т.е. в 9-м столбце или 9-й строке), добавьте к 1-му столбцу после заполнения 17 символов, запустите логику решателя и найдите свое уникальное решение.
person Naveen Babu    schedule 04.01.2013
comment
Как это позволяет избежать возможного добавления слишком большого количества цифр, прежде чем получить уникальное решение, а затем необходимости убрать некоторые из них, чтобы получить минимальную головоломку? - person 1''; 04.01.2013

Вот основные оптимизации, которые я реализовал с (очень приблизительным) процентным увеличением скорости:

  • Использование битовых масок для отслеживания того, какие ограничения (строка, столбец, поле) удовлетворяются в каждой ячейке. Это значительно ускоряет проверку того, является ли место размещения законным, но замедляет его размещение. Фактор, усложняющий создание головоломок с битовыми масками, а не просто их решение, заключается в том, что цифры, возможно, придется удалить, что означает, что вам нужно отслеживать три типа ограничений как отдельные биты. Небольшая дальнейшая оптимизация заключается в сохранении масок для каждой цифры и каждого ограничения в массивах. 40 %
  • Отключение генерации и перезапуск, если это занимает слишком много времени. См. здесь. Оптимальной стратегией является увеличение периода ожидания после каждого неудачного поколения, чтобы уменьшить вероятность того, что это будет продолжаться бесконечно. 30 %, в основном за счет сокращения времени выполнения в наихудшем случае.
  • предложения mbeckish и user295691 (см. комментарии к исходному сообщению). 25%
person 1''    schedule 12.01.2013