Современные численные методы в объектно-ориентированном изложении на C#

Объектно-ориентированная реализация агентного моделирования

Разбить на страницы
Показывать лекцию целиком

Цель лекции: Дать объектно-ориентированную трактовку агентного моделирования. Реализовать это моделирования языке C# и провести разыгрывание полученной модели.

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

Перейдем к формальному описанию. Пусть в нашей системе задано $$N_A$$ агентов, которых мы будем обозначать:$$A_i,\ i=1,\dots,N_A.$$ Мы будем рассматривать лишь конечное количество агентов. Каждый агент имеет свое множество состояний: $$Q_i$$ - множество состояний агента $$A_i$$, $$i=1,\dots,N_A$$. Кроме того будем рассматривать множество состояний внешней среды. Это множество будем обозначать: $$Q_0$$. В этом множестве состояний выделено два элемента $$q_0,q_f\in Q_0$$. Элемент $$q_0$$ - это начальное состояние внешней среды, а элемент $$q_f$$ - финальное состояние системы. Мы будем рассматривать динамическую систему с дискретным временем $$n=0,1,2,\dots$$. Введем обозначения $$S(i,n)$$:$$S(i,n)\in Q_i,\ i=0,1,\dots,N_A;\ n=0,1,2,\dots,$$ смысл функции $$S(i,n)$$ - это состояние агента (для $$i>0$$ ) или внешней среды (для $$i=0$$ ) в момент $$n$$.

Внешняя среда в заданном порядке предоставляет право агентам изменять свое внутреннее состояние и состояние внешней среды. При этом, разумеется агент имеет право менять состояние внешней среды не произвольно, а лишь выбирая это состояние из заданных возможностей. Эти возможности завися как от состояния самого агента и текущего состояния внешней среды. Введем множества возможностей $$i$$ -го агента, находящегося в состоянии $$A_q\in Q_i$$, когда внешняя среда находится в состоянии $$q\in Q_0$$:$$W_i(A_q,q)\subset Q_0,\ q\in S_0,\ A_q\in S_i,\ i=1,2,\dots,N_A.$$ У каждого агента есть "функция" перехода. Но эта не есть детерминированная функция, а реакция агента. Мы будем это отображение обозначать$$R_i(S(i,n),S(0,n))\in W_i(S(i,n),S(0,n)),$$ $$i=1,2,\dots,N_A,\ n=0,1,2,\dots.$$ При реализации отображения $$R_i$$ могут быть использованы генераторы случайных чисел, поэтому выбор "хода" агента может носить и стохастический характер.

Необходимо еще выбрать функцию определения очередности ходов агентов. Обозначим эту функцию через$$I:\Bbb{N}\times Q_0\to\{1,2,\dots,N_A\}.$$ Мы подчеркиваем, что выбор игрока, которому предлагается изменить свое внутреннее состояние и состояние внешней среды, зависит от текущего времени ( $$n$$ ) и от текущего состояния внешней среды. Часто при разыгрывании ситуации право хода чередуется между агентами. Однако возможны и более сложные случаи.

Мы реализуем игру в "крестики-нолики". Рассматривается квадратное игровое поле $$3\times3$$. В игру играют два игрока: первый ставит отметку "крестиком", второй "ноликом". Цель - выстроить три крестика или нолика в один ряд или по диагонали. Игра завершается либо выигрышем одного из игроков, либо вничью, когда нет более свободных клеток.

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

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

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

$$\begin{verbatim} class TArray { int[] arr; int Count = 9; public TArray() { arr = new int[9]; for (int i = 0; i < 9; i++) { arr[i] = 0; } } public bool Check(int i, int Star) { if (Who(i) == 0) { arr[i] = Star; Count--; return true; } else { return false; } } \end{verbatim}$$ $$\begin{verbatim} public int GetCount() { return Count; } public int Who(int i) { return arr[i]; } public bool IsOver(int Star) { int i; for(i=0;i<3;i++) { if ((arr[i] == Star) (arr[i + 1] == Star) (arr[i + 2] == Star)) { return true; } if ((arr[i] == Star) (arr[i + 3] == Star) (arr[i + 6] == Star)) { return true; } } \end{verbatim}$$ $$\begin{verbatim} if ((arr[0] == Star) (arr[4] == Star) (arr[8] == Star)) { return true; } if ((arr[2] == Star) (arr[4] == Star) (arr[6] == Star)) { return true; } return false; } } \end{verbatim}$$

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

Следующие классы описывают поведение игроков.

$$\begin{verbatim} abstract class TAgent { public int Star; public TAgent(int Star) { this.Star = Star; } abstract public int move(TArray Arr, Random rnd); } class TAgent1 : TAgent { public TAgent1(int Star) : base(Star) { } public override int move(TArray Arr, Random rnd) { if (Arr.Who(4) == 0) { Arr.Check(4, Star); return 4; } int[] Angles = new int[4] {0, 2, 6, 8}; int AngCount = 0; int i, I; for (i = 0; i < 4; i++) { if (Arr.Who(Angles[i]) == 0) { AngCount++; } } \end{verbatim}$$ $$\begin{verbatim} if (AngCount > 0) { I = rnd.Next(AngCount); for (i = 0; i < 4; i++) { if (Arr.Who(Angles[i]) == 0) { if (I == 0) { Arr.Check(Angles[i], Star); return Angles[i]; } I--; } } } I = rnd.Next(Arr.GetCount()); for (i = 0; i < 9; i++) { if (Arr.Who(i) == 0) { if (I == 0) { Arr.Check(i, Star); return i; } I--; } } return 0; } } \end{verbatim}$$ $$\begin{verbatim} class TAgent2 : TAgent { public TAgent2(int Star) : base(Star) { } public override int move(TArray Arr, Random rnd) { int I = rnd.Next(Arr.GetCount()); for (int i = 0; i < 9; i++) { if (Arr.Who(i) == 0) { if (I == 0) { Arr.Check(i, Star); return i; } I--; } } return 0; } } \end{verbatim}$$

И последний класс управляет всей игрой. В начале он выбирает очередность ходов, но первый игрок всегда играет "крестиком" (цифрой $$1$$ ), а второй "ноликом" (цифрой $$2$$ ).

$$\begin{verbatim} class TXO { public Random rnd; TArray Arr; TAgent1 A1; TAgent2 A2; public TXO() { rnd = new Random(); Clear(); } void Clear() { Arr = new TArray(); A1 = new TAgent1(1); A2 = new TAgent2(2); } public int Run() { Clear(); int res = 0; TAgent[] Agents = new TAgent[2]; if (rnd.Next(2) == 0) { Agents[0] = A1; Agents[1] = A2; } else { Agents[0] = A2; Agents[1] = A1; } \end{verbatim}$$ $$\begin{verbatim} for (int i = 0; i < 9; i++) { if ((i % 2) == 0) { Console.WriteLine("{0} => {1}", Agents[0].Star, Agents[0].move(Arr, rnd)); if (Arr.IsOver(Agents[0].Star)) { res = Agents[0].Star; break; } } else { Console.WriteLine("{0} => {1}", Agents[1].Star, Agents[1].move(Arr, rnd)); if (Arr.IsOver(Agents[1].Star)) { res = Agents[1].Star; break; } } } return res; } } \end{verbatim}$$

Теперь сыграем $$1000$$ партий.

$$\begin{verbatim} TXO XO = new TXO(); int Res1 = 0; int Res2 = 0; int Star; for (int i = 0; i lt; 1000; i++) { Console.WriteLine("\nNew Game"); Star = XO.Run(); Console.WriteLine("Winner = {0}", Star); if (Star == 1) { Res1++; } else { Res2++; } } Console.WriteLine("1 => {0}\t2 => {1}", Res1, Res2); } \end{verbatim}$$

Типичный результат игры такой:

$$\begin{verbatim} .......... New Game 1 => 4 2 => 1 1 => 6 2 => 3 1 => 2 Winner = 1 1 => 745 2 => 255 \end{verbatim}$$

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

Ключевые термины

Агент - некоторая сущность способная взаимодействовать с внешней средой.

Внешняя среда - программная среда, в которой действуют агенты.

Функция определения очередности ходов агентов - правило, задающее последовательность ходов агентов.

Краткие итоги Реализована нетривиальная динамическая система на основе агентного моделирования. Проведены вычислительные эксперименты, которые дали статистические характеристики агнетов.

Ключевые термины

Агент - некоторая сущность способная взаимодействовать с внешней средой.

Внешняя среда - программная среда, в которой действуют агенты.

Функция определения очередности ходов агентов - правило, задающее последовательность ходов агентов.

Краткие итоги: Реализована нетривиальная динамическая система на основе агентного моделирования. Проведены вычислительные эксперименты, которые дали статистические характеристики агнетов.

Страницы:

Цель лекции: Дать объектно-ориентированную трактовку агентного моделирования. Реализовать это моделирования языке C# и провести разыгрывание полученной модели.

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

Перейдем к формальному описанию. Пусть в нашей системе задано $$N_A$$ агентов, которых мы будем обозначать:$$A_i,\ i=1,\dots,N_A.$$ Мы будем рассматривать лишь конечное количество агентов. Каждый агент имеет свое множество состояний: $$Q_i$$ - множество состояний агента $$A_i$$, $$i=1,\dots,N_A$$. Кроме того будем рассматривать множество состояний внешней среды. Это множество будем обозначать: $$Q_0$$. В этом множестве состояний выделено два элемента $$q_0,q_f\in Q_0$$. Элемент $$q_0$$ - это начальное состояние внешней среды, а элемент $$q_f$$ - финальное состояние системы. Мы будем рассматривать динамическую систему с дискретным временем $$n=0,1,2,\dots$$. Введем обозначения $$S(i,n)$$:$$S(i,n)\in Q_i,\ i=0,1,\dots,N_A;\ n=0,1,2,\dots,$$ смысл функции $$S(i,n)$$ - это состояние агента (для $$i>0$$ ) или внешней среды (для $$i=0$$ ) в момент $$n$$.

Внешняя среда в заданном порядке предоставляет право агентам изменять свое внутреннее состояние и состояние внешней среды. При этом, разумеется агент имеет право менять состояние внешней среды не произвольно, а лишь выбирая это состояние из заданных возможностей. Эти возможности завися как от состояния самого агента и текущего состояния внешней среды. Введем множества возможностей $$i$$ -го агента, находящегося в состоянии $$A_q\in Q_i$$, когда внешняя среда находится в состоянии $$q\in Q_0$$:$$W_i(A_q,q)\subset Q_0,\ q\in S_0,\ A_q\in S_i,\ i=1,2,\dots,N_A.$$ У каждого агента есть "функция" перехода. Но эта не есть детерминированная функция, а реакция агента. Мы будем это отображение обозначать$$R_i(S(i,n),S(0,n))\in W_i(S(i,n),S(0,n)),$$ $$i=1,2,\dots,N_A,\ n=0,1,2,\dots.$$ При реализации отображения $$R_i$$ могут быть использованы генераторы случайных чисел, поэтому выбор "хода" агента может носить и стохастический характер.

Необходимо еще выбрать функцию определения очередности ходов агентов. Обозначим эту функцию через$$I:\Bbb{N}\times Q_0\to\{1,2,\dots,N_A\}.$$ Мы подчеркиваем, что выбор игрока, которому предлагается изменить свое внутреннее состояние и состояние внешней среды, зависит от текущего времени ( $$n$$ ) и от текущего состояния внешней среды. Часто при разыгрывании ситуации право хода чередуется между агентами. Однако возможны и более сложные случаи.

Мы реализуем игру в "крестики-нолики". Рассматривается квадратное игровое поле $$3\times3$$. В игру играют два игрока: первый ставит отметку "крестиком", второй "ноликом". Цель - выстроить три крестика или нолика в один ряд или по диагонали. Игра завершается либо выигрышем одного из игроков, либо вничью, когда нет более свободных клеток.

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

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

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

$$\begin{verbatim} class TArray { int[] arr; int Count = 9; public TArray() { arr = new int[9]; for (int i = 0; i < 9; i++) { arr[i] = 0; } } public bool Check(int i, int Star) { if (Who(i) == 0) { arr[i] = Star; Count--; return true; } else { return false; } } \end{verbatim}$$ $$\begin{verbatim} public int GetCount() { return Count; } public int Who(int i) { return arr[i]; } public bool IsOver(int Star) { int i; for(i=0;i<3;i++) { if ((arr[i] == Star) (arr[i + 1] == Star) (arr[i + 2] == Star)) { return true; } if ((arr[i] == Star) (arr[i + 3] == Star) (arr[i + 6] == Star)) { return true; } } \end{verbatim}$$ $$\begin{verbatim} if ((arr[0] == Star) (arr[4] == Star) (arr[8] == Star)) { return true; } if ((arr[2] == Star) (arr[4] == Star) (arr[6] == Star)) { return true; } return false; } } \end{verbatim}$$

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

Следующие классы описывают поведение игроков.

$$\begin{verbatim} abstract class TAgent { public int Star; public TAgent(int Star) { this.Star = Star; } abstract public int move(TArray Arr, Random rnd); } class TAgent1 : TAgent { public TAgent1(int Star) : base(Star) { } public override int move(TArray Arr, Random rnd) { if (Arr.Who(4) == 0) { Arr.Check(4, Star); return 4; } int[] Angles = new int[4] {0, 2, 6, 8}; int AngCount = 0; int i, I; for (i = 0; i < 4; i++) { if (Arr.Who(Angles[i]) == 0) { AngCount++; } } \end{verbatim}$$ $$\begin{verbatim} if (AngCount > 0) { I = rnd.Next(AngCount); for (i = 0; i < 4; i++) { if (Arr.Who(Angles[i]) == 0) { if (I == 0) { Arr.Check(Angles[i], Star); return Angles[i]; } I--; } } } I = rnd.Next(Arr.GetCount()); for (i = 0; i < 9; i++) { if (Arr.Who(i) == 0) { if (I == 0) { Arr.Check(i, Star); return i; } I--; } } return 0; } } \end{verbatim}$$ $$\begin{verbatim} class TAgent2 : TAgent { public TAgent2(int Star) : base(Star) { } public override int move(TArray Arr, Random rnd) { int I = rnd.Next(Arr.GetCount()); for (int i = 0; i < 9; i++) { if (Arr.Who(i) == 0) { if (I == 0) { Arr.Check(i, Star); return i; } I--; } } return 0; } } \end{verbatim}$$

И последний класс управляет всей игрой. В начале он выбирает очередность ходов, но первый игрок всегда играет "крестиком" (цифрой $$1$$ ), а второй "ноликом" (цифрой $$2$$ ).

$$\begin{verbatim} class TXO { public Random rnd; TArray Arr; TAgent1 A1; TAgent2 A2; public TXO() { rnd = new Random(); Clear(); } void Clear() { Arr = new TArray(); A1 = new TAgent1(1); A2 = new TAgent2(2); } public int Run() { Clear(); int res = 0; TAgent[] Agents = new TAgent[2]; if (rnd.Next(2) == 0) { Agents[0] = A1; Agents[1] = A2; } else { Agents[0] = A2; Agents[1] = A1; } \end{verbatim}$$ $$\begin{verbatim} for (int i = 0; i < 9; i++) { if ((i % 2) == 0) { Console.WriteLine("{0} => {1}", Agents[0].Star, Agents[0].move(Arr, rnd)); if (Arr.IsOver(Agents[0].Star)) { res = Agents[0].Star; break; } } else { Console.WriteLine("{0} => {1}", Agents[1].Star, Agents[1].move(Arr, rnd)); if (Arr.IsOver(Agents[1].Star)) { res = Agents[1].Star; break; } } } return res; } } \end{verbatim}$$

Теперь сыграем $$1000$$ партий.

$$\begin{verbatim} TXO XO = new TXO(); int Res1 = 0; int Res2 = 0; int Star; for (int i = 0; i lt; 1000; i++) { Console.WriteLine("\nNew Game"); Star = XO.Run(); Console.WriteLine("Winner = {0}", Star); if (Star == 1) { Res1++; } else { Res2++; } } Console.WriteLine("1 => {0}\t2 => {1}", Res1, Res2); } \end{verbatim}$$

Типичный результат игры такой:

$$\begin{verbatim} .......... New Game 1 => 4 2 => 1 1 => 6 2 => 3 1 => 2 Winner = 1 1 => 745 2 => 255 \end{verbatim}$$

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

Ключевые термины

Агент - некоторая сущность способная взаимодействовать с внешней средой.

Внешняя среда - программная среда, в которой действуют агенты.

Функция определения очередности ходов агентов - правило, задающее последовательность ходов агентов.

Краткие итоги Реализована нетривиальная динамическая система на основе агентного моделирования. Проведены вычислительные эксперименты, которые дали статистические характеристики агнетов.

Ключевые термины

Агент - некоторая сущность способная взаимодействовать с внешней средой.

Внешняя среда - программная среда, в которой действуют агенты.

Функция определения очередности ходов агентов - правило, задающее последовательность ходов агентов.

Краткие итоги: Реализована нетривиальная динамическая система на основе агентного моделирования. Проведены вычислительные эксперименты, которые дали статистические характеристики агнетов.

Вернуться к учебному плану