\documentclass{article} \input{settings/common-preamble} \input{settings/bmstu-preamble} \input{settings/fancy-listings-preamble} \def\makeyear{2021} \def\grpNum{11М} \begin{document} \pagestyle{empty} \makeBMSTUHeader \makeReportTitle{лабораторной}{2}{Мультиагентные системы}{Распределённые информационные системы}{}{Локтев Д.А.} \newpage \tableofcontents \lstlistoflistings \newpage \section{Результаты выполнения задания} Задания выполнены с применением значений для варианта №11(2) \section{Введение} Целью работы является изучение подходов к проектированию мультиагентных систем и построению искусственного интеллекта, а также их реализация. Доработка алгоритма поведения игрока и компьютеров в игре Pacman реализуется на языке Python второй версии в среде разработки JetBrains PyCharm Community Edition. \section{Улучшение агента ReflexAgent} Комментарий к фукнции \code{evaluationFunction(self, currentGameState, action)} содержал следующие указания: \begin{verbatim} Реализуйте здесь лучшую оценочную функцию Оценочная функция берет текущее и предполагаемое следующее состояние GameStates (pacman.py) и возвращает число (чем больше число, тем лучше). Код ниже содержит полезную информацию о состоянии, такую как оставшуюся еду (newFood) и позицию пакмена после движения (newPos). newScaredTimes содержит число шагов, в течении которых каждый призрак останется напуганным, поскольку пакмен съел гранулу силы. Выведите эти переменные, чтобы посмотреть, что в них находится, и затем комбинируйте их для создания великолепной оценочной функции. \end{verbatim} Улучшенный код рефлексивного агента представлен в листинге \hyperref[lst:betterReflex]{\ref{lst:betterReflex}}. Результаты выполнения тестов, запушенных командой \code{python autograder.py -q -q1 -no-graphics} представлен в выводе \hyperref[fig:result1]{\ref{fig:result1}}. \begin{lstlisting}[language=Python, caption=Улучшенный код агента, style=PyCodeStyle, label={lst:betterReflex}] def evaluationFunction(self, currentGameState, action): # Useful information you can extract from a GameState (pacman.py) successorGameState = currentGameState.generatePacmanSuccessor(action) newPos = successorGameState.getPacmanPosition() newFood = successorGameState.getFood() newGhostStates = successorGameState.getGhostStates() newScaredTimes = [ghostState.scaredTimer for ghostState in newGhostStates] currentPos = currentGameState.getPacmanPosition() currentFood = currentGameState.getFood() currentGhostStates = currentGameState.getGhostStates() currentScaredTimes = [ghostState.scaredTimer for ghostState in currentGhostStates] additional_score = 0 current_distance_to_food = float("inf") current_distance_to_ghost = float("inf") new_distance_to_food = float("inf") new_distance_to_ghost = float("inf") for food in newFood.asList(): d = manhattanDistance(food, newPos) new_distance_to_food = min([new_distance_to_food, d]) pos_x, pos_y = newPos if currentFood[pos_x][pos_y]: additional_score += 10 food_before_action = len(currentFood.asList()) food_after_action = len(newFood.asList()) for ghost in successorGameState.getGhostPositions(): d = manhattanDistance(newPos, ghost) new_distance_to_ghost = min([new_distance_to_ghost, d]) score = 1.0 / new_distance_to_food - food_after_action + additional_score if new_distance_to_ghost < 2: score -= 500 return score \end{lstlisting} \begin{figure}[H] \renewcommand{\figurename}{Вывод} \begin{verbatim} Question q1 =========== Pacman emerges victorious! Score: 1246 Pacman emerges victorious! Score: 1241 Pacman emerges victorious! Score: 1233 Pacman emerges victorious! Score: 1232 Pacman emerges victorious! Score: 1241 Pacman emerges victorious! Score: 1245 Pacman emerges victorious! Score: 1233 Pacman emerges victorious! Score: 1239 Pacman emerges victorious! Score: 1237 Pacman emerges victorious! Score: 1242 Average Score: 1238.9 Scores: 1246.0, 1241.0, 1233.0, 1232.0, 1241.0, 1245.0, 1233.0, 1239.0, 1237.0, 1242.0 Win Rate: 10/10 (1.00) Record: Win, Win, Win, Win, Win, Win, Win, Win, Win, Win *** PASS: test_cases\q1\grade-agent.test (4 of 4 points) *** 1238.9 average score (2 of 2 points) *** Grading scheme: *** < 500: 0 points *** >= 500: 1 points *** >= 1000: 2 points *** 10 games not timed out (0 of 0 points) *** Grading scheme: *** < 10: fail *** >= 10: 0 points *** 10 wins (2 of 2 points) *** Grading scheme: *** < 1: fail *** >= 1: 0 points *** >= 5: 1 points *** >= 10: 2 points ### Question q1: 4/4 ### Finished at 22:04:54 Provisional grades ================== Question q1: 4/4 ------------------ Total: 4/4 Your grades are NOT yet registered. To register your grades, make sure to follow your instructor's guidelines to receive credit on your project. \end{verbatim} \caption{Результат запуска улучшенного рефлексивного агента} \label{fig:result1} \end{figure} \section{Улучшение алгоритма} В рамках персонального задания было необходимо улучшить алгоритм альфа-бета отсечения (вариант 11(2)). Улучшенный код алгоритма представлен в листинге \hyperref[lst:alphaBeta]{\ref{lst:alphaBeta}}. Результаты выполнения тестов алгоритма, запушенных командой \code{python autograder.py -q -q2 -no-graphics} представлен в выводе \hyperref[fig:result2]{\ref{fig:result2}}. \begin{lstlisting}[language=Python, caption=Улучшенный алгоритм Альфа-бета отсечение, style=PyCodeStyle, label={lst:alphaBeta}] class AlphaBetaAgent(MultiAgentSearchAgent): def maxvalue(self ,state, agentIndex, currentdepth, alpha, beta): v = (float("-inf"), "Stop") for action in state.getLegalActions(agentIndex): v = max([v, (self.value(state.generateSuccessor(agentIndex, action), (currentdepth + 1) % self.number_of_agents, currentdepth + 1, alpha, beta), action)], key = lambda item:item[0]) if v[0] > beta: return v alpha = max(alpha, v[0]) return v def minvalue(self, state, agentIndex, currentdepth, alpha, beta): v = (float("inf"), "Stop") for action in state.getLegalActions(agentIndex): v = min([v, (self.value(state.generateSuccessor(agentIndex, action), (currentdepth + 1) % self.number_of_agents, currentdepth + 1, alpha, beta), action)], key = lambda item:item[0]) if v[0] < alpha: return v beta = min(beta, v[0]) return v def value(self, state, agentIndex, currentdepth, alpha, beta): if state.isLose() or state.isWin() or currentdepth >= self.depth * self.number_of_agents: return self.evaluationFunction(state) if (agentIndex == 0): return self.maxvalue(state, agentIndex, currentdepth, alpha, beta)[0] else: return self.minvalue(state, agentIndex, currentdepth, alpha, beta)[0] def getAction(self, gameState): self.number_of_agents = gameState.getNumAgents() alpha = float("-inf") beta = float("inf") path2 = self.maxvalue(gameState, 0, 0, alpha, beta) return path2[1] \end{lstlisting} \begin{figure}[H] \renewcommand{\figurename}{Вывод} \begin{verbatim} Question q2 =========== *** PASS: test_cases\q2\0-lecture-6-tree.test *** PASS: test_cases\q2\0-small-tree.test *** PASS: test_cases\q2\1-1-minmax.test *** PASS: test_cases\q2\1-2-minmax.test *** PASS: test_cases\q2\1-3-minmax.test *** PASS: test_cases\q2\1-4-minmax.test *** PASS: test_cases\q2\1-5-minmax.test *** PASS: test_cases\q2\1-6-minmax.test *** PASS: test_cases\q2\1-7-minmax.test *** PASS: test_cases\q2\1-8-minmax.test *** PASS: test_cases\q2\2-1a-vary-depth.test *** PASS: test_cases\q2\2-1b-vary-depth.test *** PASS: test_cases\q2\2-2a-vary-depth.test *** PASS: test_cases\q2\2-2b-vary-depth.test *** PASS: test_cases\q2\2-3a-vary-depth.test *** PASS: test_cases\q2\2-3b-vary-depth.test *** PASS: test_cases\q2\2-4a-vary-depth.test *** PASS: test_cases\q2\2-4b-vary-depth.test *** PASS: test_cases\q2\2-one-ghost-3level.test *** PASS: test_cases\q2\3-one-ghost-4level.test *** PASS: test_cases\q2\4-two-ghosts-3level.test *** PASS: test_cases\q2\5-two-ghosts-4level.test *** PASS: test_cases\q2\6-tied-root.test *** PASS: test_cases\q2\7-1a-check-depth-one-ghost.test *** PASS: test_cases\q2\7-1b-check-depth-one-ghost.test *** PASS: test_cases\q2\7-1c-check-depth-one-ghost.test *** PASS: test_cases\q2\7-2a-check-depth-two-ghosts.test *** PASS: test_cases\q2\7-2b-check-depth-two-ghosts.test *** PASS: test_cases\q2\7-2c-check-depth-two-ghosts.test *** Running AlphaBetaAgent on smallClassic 1 time(s). Pacman died! Score: 84 Average Score: 84.0 Scores: 84.0 Win Rate: 0/1 (0.00) Record: Loss *** Finished running AlphaBetaAgent on smallClassic after 1 seconds. *** Won 0 out of 1 games. Average score: 84.000000 *** *** PASS: test_cases\q2\8-pacman-game.test ### Question q2: 5/5 ### Finished at 22:41:44 Provisional grades ================== Question q2: 5/5 ------------------ Total: 5/5 Your grades are NOT yet registered. To register your grades, make sure to follow your instructor's guidelines to receive credit on your project. \end{verbatim} \caption{Результаты прохождения тестов алгоритма альфа-бета отсечения} \label{fig:result2} \end{figure} \section{Выводы} В рамках выполнения задания были применены алгоритмы, позволяющие построить искусственный интеллект способный победить в аркадной игре Pacman. Оценочная функция позволяет достаточно быстро и точно, в выбранной метрике, указать оценку вероятности победы конкретного игрока для конкретного расположения фигур, не опираясь на то, каким образом игроки к этому состоянию пришли. Алгоритм альфа-бета отсечения является модификацией алгоритма минимакса, однако, в отличие от него, анализ некоторых ходов может быть не выполнен, то есть, прекратиться досрочно. Агенты позволяют использовать существующее программное обеспечение, в контексте выполнения работы им являлась игра Pacman, для достижения своих целей -- победы. Алгоритмы их работы являются эвристическими и не гарантируют победу, а лишь позволяют с заданной быстротой и точностью достичь поставленной цели -- анализ текущей ситуации и выбор лучшего выхода из неё. \end{document}