![]() Автоматический решатель. построение автоматического решателя математических задач. Обучающие системы. разработка компьютерных интеллектуальных обучающих систем. Ключ: Копировать ключ. одной переменной; * исследовать рациональные функции с помощью производных и построить их график с автоматическим выбором оптимального масштаба; * конвертировать. 3. UMS 5.0 Portable Универсальный математический решатель.rar. 10,580,403.. Игра Балда - это логическая игра на составление слов. На поле, состоящее из 25 клеток, вписывается в центр слово из 5 букв. Игроки должны. Автоматическое решение примеров и задач любой степени трудности. Для школьников и студентов. Оригинальность Универсального Математического Решателя (сокращённо UMS) состоит в его уникальности и широких функциональных возможностях. Как написать простую решалку тсумего / Хабрахабр Примерно год назад друг показал мне что такое го и как в него играют. Хорошо помню как в одной из первых партий я гордо построил цепочку из камней которая соединяла нижнюю сторону доски с верхней, а также цепочку соединяющую левую сторону с правой, на что друг мне сказал, что это конечно хорошо, но я проиграл. У меня тогда ушло много времени, чтобы понять почему. С тех пор я продвинулся до примерно первого дана KGS, а друг перестал со мной играть. Чтобы хорошо играть в го надо видеть на несколько ходов вперед, а этот навык хорошо развивает решение тсумего коих много на goproblems. Естественно, однажды меня посетила мысль, что неплохо было бы написать решалку этих тсумего и, в идеале, встроить её в goproblems, тем более, что adum эту идею одобряет. ![]() Поскольку сам я решаю тсумего методом очень неспешного перебора более- менее осмысленных ходов со скоростью где то 1 ход в пару секунд, при этом регулярно забывая с чего начинался перебор (и этого достаточно, чтобы уверенно решать задачи 3 дана), я прикинул с какой невероятной скоростью и точностью будет работать простейший поиск в глубину, то бишь dfs, и оценил сложность задачи как «на пару дней». Тут же я попробовал по быстрому написать эту решалку «в лоб» через простейший dfs и наткнулся на мелкую неприятность: в процессе поиска одни и те же позиции встречались много раз и пересчитывать их заново было как то совсем неоптимально даже для решалки написанной по быстрому. Недолго думая я завел кеш для храния уже решенных позиций и тут же наткнулся на другую неприятность: решение найденное однажды может быть неправильным если в эту позицию прийти другой последовательностью ходов. Здесь я завис, не зная что делать, но решил, что эта неприятность легко решаемая — надо лишь немного подумать. Думал я довольно долго и решил, что есть смысл посмотреть, что уже есть готового на данную тему — статьи, алгоритмы и т. Первым делом мне на глаза попался некий «lambda depth first proof number search» и посмотрев, что размер статьи всего то несколько страниц, я обрадованно начал читать. В статье оказались ссылки на другие подобные статьи Мартина Мюллера и Акиро Кишимото, в тех статьях ещё ссылки, там появилась ссылка на 2. Кишимото и тут то я осознал масштаб проблемы: решение даже весьма простых тсумего было настолько алгоритмически сложным, что в большинстве случаев вопрос стоит даже не в том, как перебрать все варианты, а как вообще найти тсумего на доске (что даже начинающий игрок делает за секунду), как понять что там надо захватывать или защищать (тоже тривиально для человека) и какие ходы имеют смысл (тоже в большинстве случаев очевидно) и если дело дошло до собственно перебора вариантов, то тсумего можно сказать решено (хотя эффективный алгоритм перебора чрезвычайно заковырист). Вообщем я понял, что моего IQ явно не хватит, чтобы решить такую задачу с ходу и я решил, что будет неплохо если получится хотя бы написать решалку для простейшего случая когда все осмысленные ходы и цель задаются заранее — даже это будет весьма полезно на goproblems. Насколько я знаю есть совсем немного программ которые решают тсумего: — Go. Tools Томаса Вольфа: до 1. Tsumego Explorer Мартина Мюллера (который, кстати, 7 дан): до 3. Java (хотя непонятно где взять), продвинутый l- df- pn- r поиск с очень продвинутым статическим анализом описанным в статьях Мюллера и диссертации Кишимото.— Fuego Мартина Мюллера: полноценный бот 2+ дана (я не могу оценить его силу поскольку он меня явно сильнее) с открытым кодом на C++ (можно скачать на Source. Forge). Ни Мюллер ни adum не слышали о каких либо js решалках (а решалка должна быть на js, чтобы её можно было встроить в goproblems), а раз так, то есть смысл попробовать её написать — тем более, что Мюллер и Кишимото написали много статей и даже программ на эту тему. Слева типичное тсумего. В общем случае задача в том, чтобы найти лучший ход (и нужен ли он вообще) как за черных, так и за белых. Очевидно, что если белые ходят первыми, они захватывают угол. Если черные ходят первыми, то они могут угол сохранить, но одно из решений приводит к ко и если черные проигрывают ко, то теряют угол, а другое решение сохраняет угол без всяких ко, что как правило предпочтительнее. Для простоты, будем считать, что есть некий способ посмотреть на доску и узнать все осмысленные ходы которые надо перебрать для решения (фактически это означает то, что все такие ходы будут заданы вручную). Определим функцию R которая говорит кто выигрывает на доске b: По определению R, чёрные обязаны сделать первый ход даже если он нарушает баланс в секи — это позволяет устранить ситуацию в которой белые и чёрные постоянно пасуют. Аналогично для белых. Если проигрывают и чёрные и белые — это секи. Тогда эту функцию можно рекурсивно определить так: Выглядит немного запутанно, но суть у неё простая: По определению R, чёрные вынуждены сделать какой нибудь ход, поэтому они выбирают лучший среди всех возможных ходов. Отсюда максимум по всем ходам m.
Затем ход переходит к белым и они могут решать делать ход или не делать — отсюда минимум. Если белые делают ход, то результат будет где b+m это доска b к которой добавили черный камень m. Если же белые ход пропускают (и это не противоречит определению R), то у чёрных есть выбор: сделать ход или тоже спасовать, что завершит партию — отсюда второй максимум. Если чёрные делают ход, то получается , а если пасуют, то R(b+m) определяет кто победил (на практике это всего лишь проверка того есть ли на доске камень который надо было захватить). Симметричная формула получается для белых. Если её посчитать «в лоб» то получится прямолинейный dfs с перебором всех вариантов, что даже для простейшего накаде из 5 точек работает весьма неспешно. Написать это можно примерно так: function solve(board: Board, color: Color): Result {. Moves. For(color)) {. Board = board. fork(). For(color, // it's +color's turn, so he chooses. For(- color, // now it's - color's turn. Board, - color), // - color makes a move. For(color, // - color can pass, but then it's +color's turn again. Board, color), // +color makes two moves in a row. Board)))); // neither player makes a move. Обратите внимание, что этот алгоритм потратит много времени впустую на доказательство того, что простейшее секи это секи. Если у белой и черной группы есть только общие свободы и этих свобод много, то этот алгоритм сначала попробует сыграть на первой свободе, выяснит, что выиграть не получается, затем сыграет на второй свободе и опять выяснит, что выиграть нельзя и т. Можно даже составить простую рекурсивную формулу для количества ходов которое сделает этот алгоритм, чтобы перебрать все варианты. Рост более чем экспоненциальный. Решить эту проблему наверно можно только статическим анализом. Теперь надо сделать так, чтобы одна и та же доска два раза не решалась. Например, найдя один раз решение для накаде из 5 точек, можно его повторно использовать если другая позиция сводится к этому накаде. Такой кеш решений обычно называется transposition table (tt). Ключом в этой таблице будет хеш доски + цвет того, кто ходит первым. Поначалу я наивно реализовал это как то так: const tt: { [key: string]: Result } = {}. Board, color: Color): Result {. Moves. For(color)) {. Board = board. fork(). For(color, // it's +color's turn, so he chooses. For(- color, // now it's - color's turn. Board, - color), // - color makes a move. For(color, // - color can pass, but then it's +color's turn again. Board, color), // +color makes two moves in a row. Board)))); // neither player makes a move. Проблема с этим кодом в том, что есть позиции решение которых нельзя определить просто посмотрев на расположение камней. Вот например слева ход белых, но понять кто выигрывает — нельзя, потому что непонятно может ли белый захватить камень чёрных (т. Эта мелкая поправка к правилам — повторять позицию нельзя — воспринимается как нечто само собой разумеющееся во время игры и не доставляет никаких сложностей, а правило супер- ко (т. Как ни странно, даже гипотетическая возможность существования циклов длиной в несколько ходов (ходов этак в 5- 7) непременно реализуется во время алгоритмического перебора и если это не учитывать, то либо результат будет неправильным, либо алгоритм зациклится. Так что эта, казалось бы, виртуальная проблема удостоилась диссертации Кишимото «Correct and Efficient Search Algorithms in The Presence of Repetitions» аж на 2. Решение этой проблемы упоминается много раз в статьях Мюллера и Кишимото и звучит оно так: если в процессе поиска решения не обнаружилось повторений, значит оно не зависит от пути которым пришли в данную позицию. Если вдуматься, то утверждение это совсем не очевидное. Когда мне надоело придумывать доказательство, я написал Мюллеру и он сказал, что да, это весьма сильное и универсальное утверждение и доказательство его кажется было где то в диссертации. Найти это доказательство я там так и не смог, но додумался до своего которое работает если допустить, что все уже решенные и независимые от пути решения никогда не удаляются (по причине нехватки памяти). Для иллюстрации я бессовестно скопировал у кого то картинку : ) Граф возможных ходов обычно выглядит как это дерево на картинке. Вершина в этом графе представляет собой расположение камней на доске, а цвет говорит о том, кто делает ход. Для простоты (и не нарушая общности) будем считать, что позиция 1. Решением является дерево (циклов ведь нет), в котором из каждой чёрной вершины ведёт один ход (больше и не надо потому как суть решения в том, что показать правильный ход в любой позиции), а из каждой белой вершины ведут все возможные ходы (решение должно доказывать, что на каждый ход белых найдётся ход чёрных который приводит к победе чёрных). Теперь допустим, что утверждение не верно и найденное решение для позиции 1. Если бы такой путь не пересекался с деревом решения, то он бы не мог на него повлиять — значит этот гипотетический путь содержит хотя бы одну вершину дерева. Возьмём эту какую нибудь вершину и попробуем пройти по этому пути в вершину 1. Допустим, что мы начинаем из вершины 1.
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. Archives
November 2017
Categories |