Практические советы отладки глубокой рекурсии?

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

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

Теперь я не собираюсь спрашивать вас: "Где проблема в моем коде?" но я ищу общие советы, инструменты, визуализации, что угодно, чтобы отлаживать такой код. Лично я развиваюсь на С#, но приветствуем любые инструменты. Хотя я считаю, что это может быть наиболее применимо к императивным языкам.

Ответ 1

Logging. Войдите в свой код. По моему опыту, регистрация - это решение для этих типов проблем. когда трудно понять, что делает ваш код, его полномасштабное протоколирование является очень хорошим решением, поскольку оно позволяет выводить из вашего кода, что такое внутреннее состояние; это действительно не идеальное решение, но, насколько я видел, он работает лучше, чем любой другой метод.

Ответ 2

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

Ответ 3

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

Ответ 4

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

Если вы настаиваете на отладке, иногда полезно использовать код с инструкциями, которые проверяют заданное значение, поэтому вы можете прикрепить точку останова в это время и поместить в код:

  if ( depth = X && item.id = 32) {
     // Breakpoint here
  }

Ответ 5

У меня когда-то была аналогичная проблема, когда я разрабатывал алгоритм AI для игры в тетрис. После многих попыток потерять много часов при чтении моих собственных журналов и отладке, а также входе и выходе из функций, которые я разработал у меня, это написать быстрый визуализатор и протестировать мой код с помощью FIXED-ввода.

Итак, если время не является проблемой, и вы действительно хотите понять, что происходит, получите фиксированное состояние платы и ПОСМОТРЕТЬ, что ваша программа делает с данными, используя сочетание отладочных журналов/вывода и своего рода собственные инструменты, которые показывают информацию на каждом шаге.

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

Ответ 6

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

Когда я занимался курсом теории компиляторов в колледже, мы использовали библиотеку программного обеспечения для визуализации наших деревьев; это может помочь вам, так как это может помочь вам увидеть, как выглядит дерево. Фактически, вы можете создать приложение WinForms/WPF, чтобы сбрасывать содержимое вашего дерева в элемент управления TreeView - это беспорядочно, но он выполнит эту работу.

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

Имейте в виду, что интеллектуальная отладка с использованием Visual Studio может творить чудеса. Трудно видеть, как меняется состояние при нескольких перерывах, но Visual Studio 2010 действительно должна помочь с этим.

К сожалению, не очень легко помочь вам отлаживать без дополнительной информации. Вы определили первую глубину, на которой он начинает ломаться? Продолжает ли он прерываться с более высокой глубиной поиска? Вы можете оценить свои рабочие случаи и попытаться определить, как они отличаются.

Ответ 7

Поскольку вы говорите, что обход не работает должным образом, я предполагаю, что у вас есть представление о том, где все может пойти не так. Затем проверьте код, чтобы убедиться, что вы не упустили что-то основное.

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

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

Ответ 8

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

Распечатайте дамп вместе с исходным кодом, затем уберите его с компьютера и попробуйте хорошую отладочную бумагу на бумаге за чашкой кофе.