diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..088eb14
Binary files /dev/null and b/.DS_Store differ
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..815736f
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "keyToString": {
+ "RunOnceActivity.OpenProjectViewOnStart": "true",
+ "RunOnceActivity.ShowReadmeOnStart": "true",
+ "last_opened_file_path": "C:/Users/papadakk"
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1670007408480
+
+
+ 1670007408480
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/learningAgents/.DS_Store b/learningAgents/.DS_Store
new file mode 100644
index 0000000..f993315
Binary files /dev/null and b/learningAgents/.DS_Store differ
diff --git a/learningAgents/src/.DS_Store b/learningAgents/src/.DS_Store
new file mode 100644
index 0000000..0d8dafa
Binary files /dev/null and b/learningAgents/src/.DS_Store differ
diff --git a/learningAgents/src/LearningAgent_Simulations.ipynb b/learningAgents/src/.ipynb_checkpoints/LearningAgent_Simulations-checkpoint.ipynb
similarity index 99%
rename from learningAgents/src/LearningAgent_Simulations.ipynb
rename to learningAgents/src/.ipynb_checkpoints/LearningAgent_Simulations-checkpoint.ipynb
index c1a21e8..cbf9138 100644
--- a/learningAgents/src/LearningAgent_Simulations.ipynb
+++ b/learningAgents/src/.ipynb_checkpoints/LearningAgent_Simulations-checkpoint.ipynb
@@ -962,7 +962,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3",
+ "display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
diff --git a/learningAgents/src/__pycache__/environment.cpython-39.pyc b/learningAgents/src/__pycache__/environment.cpython-39.pyc
new file mode 100644
index 0000000..e3b7709
Binary files /dev/null and b/learningAgents/src/__pycache__/environment.cpython-39.pyc differ
diff --git a/learningAgents/src/__pycache__/learningAgent.cpython-39.pyc b/learningAgents/src/__pycache__/learningAgent.cpython-39.pyc
new file mode 100644
index 0000000..c737fb3
Binary files /dev/null and b/learningAgents/src/__pycache__/learningAgent.cpython-39.pyc differ
diff --git a/learningAgents/src/environmentModel.py b/learningAgents/src/environmentModel.py
deleted file mode 100644
index 8d1c8b6..0000000
--- a/learningAgents/src/environmentModel.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/learningAgents/src/learningAgents.py b/learningAgents/src/learningAgents.py
deleted file mode 100644
index d68c052..0000000
--- a/learningAgents/src/learningAgents.py
+++ /dev/null
@@ -1,220 +0,0 @@
-import numpy as np
-import torch
-import torch.nn as nn
-from torch.distributions import Categorical
-import sys
-import numpy as np # numerical python
-# printoptions: output limited to 2 digits after decimal point
-np.set_printoptions(precision=2, suppress=False)
-
-
-
-class DemandPotentialGame():
- """
- Fully defines demand Potential Game. It contains game rules, memory and agents strategies.
- """
-
- def __init__(self, totalDemand, tupleCosts, totalStages) -> None:
- self.totalDemand = totalDemand
- self.costs = tupleCosts
- self.T = totalStages
- # first index is always player
- self.demandPotential = None # two lists for the two players
- self.prices = None # prices over T rounds
- self.profit = None # profit in each of T rounds
- self.stage = None
-
-
- def resetGame(self):
- self.demandPotential = [[0]*self.T,[0]*self.T] # two lists for the two players
- self.prices = [[0]*self.T,[0]*self.T] # prices over T rounds
- self.profit = [[0]*self.T,[0]*self.T] # profit in each of T rounds
- self.demandPotential[0][0] = self.totalDemand/2 # initialize first round 0
- self.demandPotential[1][0] = self.totalDemand/2
-
-
- def profits(self, player = 0):
- return self.profit[player][self.stage]
-
- def updatePricesProfitDemand(self, pricepair):
- # pricepair = list of prices for players 0,1 in current round t
- for player in [0,1]:
- price = pricepair[player]
- self.prices[player][self.stage] = price
- self.profit[player][self.stage] = (self.demandPotential[player][self.stage] - price)*(price - self.costs[player])
- if self.stage < self.T-1 :
- self.demandPotential[player][ self.stage + 1] = \
- self.demandPotential[player][self.stage] + (pricepair[1-player] - price)/2
-
-
- def monopolyPrice(self, player, t): # myopic monopoly price
- return (self.demandPotential[player][self.stage] + self.costs[player])/2
-
- def myopic(self, player = 0):
- return self.monopolyPrice(player, self.stage)
-
- def const(self, player, price): # constant price strategy
- if self.stage == T-1:
- return monopolyPrice(player, self.stage)
- return price
-
- def imit(self, player, firstprice): # price imitator strategy
- if self.stage == 0:
- return firstprice
- if self.stage == T-1:
- return monopolyPrice(player, self.stage)
- return self.prices[1-player][t-1]
-
- def fight(self, player, firstprice): # simplified fighting strategy
- if self.stage == 0:
- return firstprice
- if self.stage == T-1:
- return monopolyPrice(player, self.stage)
- aspire = [ 207, 193 ] # aspiration level for demand potential
- D =self.demandPotential[player][self.stage]
- Asp = aspire [player]
- if D >= Asp: # keep price; DANGER: price will never rise
- return self.prices[player][self.stage-1]
- # adjust to get to aspiration level using previous
- # opponent price; own price has to be reduced by twice
- # the negative amount D - Asp to getself.demandPotential to Asp
- P = self.prices[1-player][self.stage-1] + 2*(D - Asp)
- # never price to high because even 125 gives good profits
- P = min(P, 125)
- return P
-
-
- # sophisticated fighting strategy, compare fight()
- # estimate *sales* of opponent as their target, kept between
- # calls in global variable oppsaleguess[]. Assumed behavior
- # of opponent is similar to this strategy itself.
- oppsaleguess = [61, 75] # first guess opponent sales as in monopoly
- def guess(self, player, firstprice): # predictive fighting strategy
- if self.stage == 0:
- oppsaleguess[0] = 61 # always same start
- oppsaleguess[1] = 75 # always same start
- return firstprice
-
- if self.stage == T-1:
- return monopolyPrice(player, self.stage)
- aspire = [ 207, 193 ] # aspiration level
- D =self.demandPotential[player][self.stage]
- Asp = aspire [player]
-
- if D >= Asp: # keep price, but go slightly towards monopoly if good
- pmono = monopolyPrice(player, self.stage)
- pcurrent = self.prices[player][self.stage-1]
- if pcurrent > pmono: # shouldn't happen
- return pmono
- if pcurrent > pmono-7: # no change
- return pcurrent
- # current low price at 60%, be accommodating towards "collusion"
- return .6 * pcurrent + .4 * (pmono-7)
-
- # guess current *opponent price* from previous sales
- prevsales =self.demandPotential[1-player][t-1] - self.prices[1-player][t-1]
- # adjust with weight alpha from previous guess
- alpha = .5
- newsalesguess = alpha * oppsaleguess[player] + (1-alpha)*prevsales
- # update
- oppsaleguess[player] = newsalesguess
- guessoppPrice = 400 - D - newsalesguess
- P = guessoppPrice + 2*(D - Asp)
-
- if player == 0:
- P = min(P, 125)
- if player == 1:
- P = min(P, 130)
- return P
-
-
-class Model(DemandPotentialGame):
- """
- Defines the Problem's Model. It is assumed a Markov Decision Process is defined.
- """
- def __init__(self, totalDemand,tupleCosts,totalStages, initState) -> None:
- super().__init__( totalDemand,tupleCosts,totalStages)
-
- self.rewardFunction = self.profits
- self.initState = initState
- self.episodesMemory = list()
- self.done = False
-
- def reset(self):
- reward = 0
- self.stage = 0
- self.resetGame()
- return torch.tensor(self.initState, dtype=torch.float32), reward, self.done
-
-
- def adversaryChoosePrice(self):
- return self.myopic(player = 1)
-
-
- def step(self, state, action):
- adversaryAction = self.adversaryChoosePrice()
- self.updatePricesProfitDemand( [self.myopic() - action, adversaryAction] )
- newState = [ self.demandPotential[1][self.stage + 1], self.prices[1][self.stage] ]
- reward = self.rewardFunction()
- self.stage = self.stage + 1
-
-
- return torch.tensor(newState, dtype=torch.float32), reward, self.stage == self.T-1
-
-
-
-
-
-class ReinforceAlgorithm():
- """
- Model Solver.
- """
- def __init__(self, Model, policyNet, optim, numberEpisodes) -> None:
- self.env = Model
- self.env.adversaryReturns = np.zeros(numberEpisodes)
- self.returns = np.zeros(numberEpisodes)
- self.policy = policyNet
- self.numberEpisodes = numberEpisodes
- self.optim = optim
- self.episodesMemory = list()
-
- def solver(self):
-
- for episode in range(self.numberEpisodes):
- episodeMemory = list()
- state, reward, done = self.env.reset()
- retu = 0
- while not done:
- prev_state = state
- probs = self.policy(prev_state)
- distAction = Categorical(probs)
- action = distAction.sample()
-
- state, reward, done = self.env.step(prev_state, action.item())
- retu = retu + reward
- episodeMemory.append((prev_state, action, reward))
-
-
- states = torch.stack([item[0] for item in episodeMemory])
- actions = torch.tensor([item[1] for item in episodeMemory])
- rewards = torch.tensor([item[2] for item in episodeMemory])
-
- action_probs = self.policy(states)
- action_dists = Categorical(action_probs)
- action_logprobs = action_dists.log_prob(actions)
-
- returns = self.returnsComputation(rewards, episodeMemory)
-
- loss = - ( torch.sum(returns*action_logprobs) )/len(episodeMemory)
- print(loss)
- self.optim.zero_grad()
- loss.backward()
- self.optim.step()
- self.returns[episode] = retu
-
-
-
- def returnsComputation(self, rewards, episodeMemory):
- gamma = .9
- return torch.tensor( [torch.sum( rewards[i:] * (gamma ** torch.arange(i, len(episodeMemory))) ) for i in range(len(episodeMemory)) ] )
-
diff --git a/qLearning/.DS_Store b/qLearning/.DS_Store
new file mode 100644
index 0000000..6031111
Binary files /dev/null and b/qLearning/.DS_Store differ
diff --git a/qLearning/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb b/qLearning/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
new file mode 100644
index 0000000..7a5d508
--- /dev/null
+++ b/qLearning/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
@@ -0,0 +1,192 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_Demand = 400\n",
+ "agent_Cost = 57\n",
+ "adv_Cost = 71 \n",
+ "tuple_Costs = [57,71]\n",
+ "total_Stages = 25\n",
+ "init_State = [total_Demand/2, total_Demand/2]\n",
+ "adversary_Mode = AdversaryModes.myopic\n",
+ "\n",
+ "game = Model(total_Demand, [agent_Cost,adv_Cost], total_Stages, init_State, adversary_Mode)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "num_Actions = 70\n",
+ "num_States = abs(adv_Cost - agent_Cost) + 2 * num_Actions + 2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+demoninator)\n",
+ "Qtable = QTable(num_States, num_Actions, learning_Rate = [490000,500000])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "numberEpisodes = 50000000\n",
+ "discountFactor = 0.99"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, numberEpisodes, discountFactor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "algorithm.solver()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# print(Qtable.Q_table)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "result = Test(game, Qtable, discountFactor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "156765.9001089289\n",
+ "[ 85 95 100 104 106 105 108 108 108 108 108 108 108 108 108 108 108 108\n",
+ " 108 108 108 108 108 108 108]\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Returns the optimal payoff and actions according to the Qtable\n",
+ "payoff, actions = result.totalPayoff()\n",
+ "print(payoff)\n",
+ "print(actions)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The percentage error of the Qtable\n",
+ "error = result.error()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "5.694704646489295e-05"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "error.mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Adversary_as_QTable/.DS_Store b/qLearning/Adversary_as_QTable/.DS_Store
new file mode 100644
index 0000000..f5319c1
Binary files /dev/null and b/qLearning/Adversary_as_QTable/.DS_Store differ
diff --git a/qLearning/Adversary_as_QTable/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb b/qLearning/Adversary_as_QTable/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
new file mode 100644
index 0000000..384ccf6
--- /dev/null
+++ b/qLearning/Adversary_as_QTable/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
@@ -0,0 +1,359 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np\n",
+ "import os"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_Demand = 400\n",
+ "agent_Cost = 57\n",
+ "adv_Cost = 71\n",
+ "total_Stages = 25\n",
+ "num_Actions = 50\n",
+ "num_States = abs(adv_Cost - agent_Cost) + 2 * num_Actions + 1\n",
+ "Qtable = QTable(num_States, num_Actions, learning_Rate = [4900000,5000000])\n",
+ "adversary = Qtable.myopicReset()\n",
+ "init_State = [total_Demand/2, total_Demand/2]\n",
+ "\n",
+ "game = Model(total_Demand, [agent_Cost,adv_Cost], total_Stages, init_State, adversary)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+demoninator)\n",
+ "Qtable = QTable(num_States, num_Actions, learning_Rate = [4900000,5000000])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "numberEpisodes = 10_000_000\n",
+ "discountFactor = 0.99"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, numberEpisodes, discountFactor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "algorithm.solver()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# print(Qtable.Q_table)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "result = Test(game, Qtable, discountFactor, adversary)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "156721.63152210606\n",
+ "[ 85 95 100 104 106 107 106 108 108 108 108 108 108 108 108 108 108 108\n",
+ " 108 108 108 108 108 108 108]\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Returns the optimal payoff and actions according to the Qtable\n",
+ "payoff, actions = result.totalPayoff()\n",
+ "print(payoff)\n",
+ "print(actions)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The percentage error of the Qtable\n",
+ "error = result.error()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "6.518340237578261e-09"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "error.mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Qtable.save(f\"round_1_with_cost_{agent_Cost}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "110258.78904553386\n",
+ "116640.93660597151\n",
+ "123765.78297511289\n",
+ "132419.5334349324\n",
+ "118895.01299519878\n",
+ "114074.40311244366\n",
+ "128890.11251690678\n",
+ "130223.1057102801\n",
+ "133140.7482414045\n",
+ "116465.83912746499\n",
+ "125063.2006751129\n",
+ "125940.23067511289\n",
+ "125957.97927654626\n",
+ "107272.61069141378\n",
+ "121311.53567749058\n",
+ "113063.16759725903\n",
+ "107458.02632269276\n",
+ "109723.43214403171\n",
+ "118912.159127465\n",
+ "94472.45361610936\n",
+ "96614.7020580578\n",
+ "123660.69922068373\n",
+ "113594.5605369414\n",
+ "133117.6149365891\n",
+ "133121.57493658908\n",
+ "127847.4176639798\n",
+ "116502.51310882121\n",
+ "129115.41814818578\n",
+ "129155.19814818578\n",
+ "109324.66751563683\n",
+ "114853.33971394581\n",
+ "131905.3337538852\n",
+ "123816.51095539633\n",
+ "118572.5288369414\n",
+ "122851.95752179525\n",
+ "103048.15069503624\n",
+ "113477.0171906411\n",
+ "122691.7971424863\n",
+ "113683.66538534917\n",
+ "107785.76389441808\n",
+ "122808.75559409145\n",
+ "105134.93273232372\n",
+ "96306.0441958089\n",
+ "107120.3732147185\n",
+ "143027.0485064772\n",
+ "112219.44224087294\n",
+ "122838.25520234526\n",
+ "116886.20952446072\n",
+ "126461.93717330166\n",
+ "101169.65758887315\n",
+ "123960.36295481244\n",
+ "101252.44419037527\n",
+ "108607.11991306185\n",
+ "108607.11991306185\n",
+ "103322.50399488166\n",
+ "100289.86593895043\n",
+ "107415.77389441806\n",
+ "115939.91433393714\n",
+ "109228.76738794592\n",
+ "120456.13629919032\n",
+ "122644.77824179525\n",
+ "118209.5288369414\n",
+ "118736.2088369414\n",
+ "108018.30515697603\n",
+ "127637.04106066648\n",
+ "128970.16106066648\n",
+ "126036.4802859369\n",
+ "132982.73975397734\n",
+ "117158.41310882122\n",
+ "126623.01573464928\n",
+ "111118.9956393708\n",
+ "138586.0125685975\n",
+ "127113.51418562784\n",
+ "113201.03913289863\n",
+ "112983.7671906411\n",
+ "104925.45933201465\n",
+ "124167.24164533603\n",
+ "124856.23361240039\n",
+ "135133.33758485512\n",
+ "125902.8830124004\n",
+ "124014.97721228783\n",
+ "101776.84593895041\n",
+ "103869.29001352542\n",
+ "128571.35814818578\n",
+ "106289.81030404904\n",
+ "103766.11797623792\n",
+ "105708.44030404904\n",
+ "132776.5164459324\n",
+ "119350.159127465\n",
+ "99883.17118286462\n",
+ "101434.19642315639\n",
+ "97751.11768933678\n",
+ "119882.27058370535\n",
+ "112186.0692310874\n",
+ "129006.58180512131\n",
+ "113658.44728748228\n",
+ "112894.31058913897\n",
+ "102568.19642315639\n",
+ "97131.58402211787\n",
+ "100300.13118286463\n"
+ ]
+ }
+ ],
+ "source": [
+ "num_rounds = 100\n",
+ "payoffs = [0]*num_rounds\n",
+ "actions = np.zeros((num_rounds, total_Stages))\n",
+ "for i in range(num_rounds):\n",
+ " \n",
+ " adversary = Qtable.Q_table\n",
+ " # Swap over players\n",
+ " game = Model(total_Demand, [adv_Cost,agent_Cost], total_Stages, init_State, adversary)\n",
+ " Qtable = QTable(num_States, num_Actions, learning_Rate = [4900000,5000000])\n",
+ " algorithm = LearningAlgorithm(game, Qtable, numberEpisodes, discountFactor)\n",
+ " algorithm.solver()\n",
+ " round = i+1\n",
+ " Qtable.save(f\"round_{round}_with_cost_{adv_Cost}\")\n",
+ "\n",
+ " adversary = Qtable.Q_table\n",
+ " # Swap back over\n",
+ " game = Model(total_Demand, [agent_Cost,adv_Cost], total_Stages, init_State, adversary)\n",
+ " Qtable = QTable(num_States, num_Actions, learning_Rate = [4900000,5000000])\n",
+ " algorithm = LearningAlgorithm(game, Qtable, numberEpisodes, discountFactor)\n",
+ " algorithm.solver()\n",
+ " result = Test(game, Qtable, discountFactor, adversary)\n",
+ " payoff, prices = result.totalPayoff()\n",
+ " payoffs[i] = payoff\n",
+ " print(payoff)\n",
+ " for stage in range(total_Stages):\n",
+ " actions[i][stage] = prices[stage]\n",
+ " round = i+2\n",
+ " Qtable.save(f\"round_{round}_with_cost_{agent_Cost}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import matplotlib.pyplot as plt\n",
+ "plt.plot(payoffs)\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Adversary_as_QTable/QTables/QTable, actions=70, states=156.npy b/qLearning/Adversary_as_QTable/QTables/QTable, actions=70, states=156.npy
new file mode 100644
index 0000000..412befc
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/QTable, actions=70, states=156.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/Test.npy b/qLearning/Adversary_as_QTable/QTables/Test.npy
new file mode 100644
index 0000000..412befc
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/Test.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/myopic.npy b/qLearning/Adversary_as_QTable/QTables/myopic.npy
new file mode 100644
index 0000000..b3a28a0
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/myopic.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_100_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_100_with_cost_57.npy
new file mode 100644
index 0000000..79f48a8
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_100_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_100_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_100_with_cost_71.npy
new file mode 100644
index 0000000..788651b
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_100_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_101_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_101_with_cost_57.npy
new file mode 100644
index 0000000..abe822d
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_101_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_10_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_10_with_cost_57.npy
new file mode 100644
index 0000000..2d3629d
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_10_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_10_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_10_with_cost_71.npy
new file mode 100644
index 0000000..e5470b9
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_10_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_11_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_11_with_cost_57.npy
new file mode 100644
index 0000000..84bed21
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_11_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_11_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_11_with_cost_71.npy
new file mode 100644
index 0000000..aabb338
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_11_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_12_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_12_with_cost_57.npy
new file mode 100644
index 0000000..0148b73
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_12_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_12_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_12_with_cost_71.npy
new file mode 100644
index 0000000..1d2fddd
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_12_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_13_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_13_with_cost_57.npy
new file mode 100644
index 0000000..af45f37
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_13_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_13_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_13_with_cost_71.npy
new file mode 100644
index 0000000..f6b08d2
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_13_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_14_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_14_with_cost_57.npy
new file mode 100644
index 0000000..528cbe4
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_14_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_14_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_14_with_cost_71.npy
new file mode 100644
index 0000000..a344e42
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_14_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_15_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_15_with_cost_57.npy
new file mode 100644
index 0000000..a71deae
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_15_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_15_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_15_with_cost_71.npy
new file mode 100644
index 0000000..2a68436
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_15_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_16_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_16_with_cost_57.npy
new file mode 100644
index 0000000..f78d4c7
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_16_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_16_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_16_with_cost_71.npy
new file mode 100644
index 0000000..f3219d3
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_16_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_17_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_17_with_cost_57.npy
new file mode 100644
index 0000000..7765268
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_17_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_17_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_17_with_cost_71.npy
new file mode 100644
index 0000000..d11ae35
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_17_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_18_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_18_with_cost_57.npy
new file mode 100644
index 0000000..3e65ae1
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_18_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_18_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_18_with_cost_71.npy
new file mode 100644
index 0000000..fa3df32
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_18_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_19_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_19_with_cost_57.npy
new file mode 100644
index 0000000..e0dcc13
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_19_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_19_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_19_with_cost_71.npy
new file mode 100644
index 0000000..28fb3f0
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_19_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_1_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_1_with_cost_57.npy
new file mode 100644
index 0000000..f1e3506
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_1_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_1_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_1_with_cost_71.npy
new file mode 100644
index 0000000..632618a
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_1_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_20_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_20_with_cost_57.npy
new file mode 100644
index 0000000..54b4de7
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_20_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_20_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_20_with_cost_71.npy
new file mode 100644
index 0000000..2d0f94a
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_20_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_21_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_21_with_cost_57.npy
new file mode 100644
index 0000000..1288141
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_21_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_21_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_21_with_cost_71.npy
new file mode 100644
index 0000000..2e0410c
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_21_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_22_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_22_with_cost_57.npy
new file mode 100644
index 0000000..801dbaa
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_22_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_22_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_22_with_cost_71.npy
new file mode 100644
index 0000000..bdc40d6
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_22_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_23_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_23_with_cost_57.npy
new file mode 100644
index 0000000..753be69
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_23_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_23_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_23_with_cost_71.npy
new file mode 100644
index 0000000..ef60f31
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_23_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_24_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_24_with_cost_57.npy
new file mode 100644
index 0000000..0b9a0b4
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_24_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_24_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_24_with_cost_71.npy
new file mode 100644
index 0000000..9862b32
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_24_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_25_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_25_with_cost_57.npy
new file mode 100644
index 0000000..d110d90
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_25_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_25_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_25_with_cost_71.npy
new file mode 100644
index 0000000..2c62295
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_25_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_26_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_26_with_cost_57.npy
new file mode 100644
index 0000000..fde2549
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_26_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_26_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_26_with_cost_71.npy
new file mode 100644
index 0000000..3118f86
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_26_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_27_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_27_with_cost_57.npy
new file mode 100644
index 0000000..4cb6ae8
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_27_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_27_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_27_with_cost_71.npy
new file mode 100644
index 0000000..55474a2
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_27_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_28_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_28_with_cost_57.npy
new file mode 100644
index 0000000..bebda24
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_28_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_28_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_28_with_cost_71.npy
new file mode 100644
index 0000000..3817c2f
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_28_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_29_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_29_with_cost_57.npy
new file mode 100644
index 0000000..831a28d
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_29_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_29_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_29_with_cost_71.npy
new file mode 100644
index 0000000..bb6a5bf
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_29_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_2_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_2_with_cost_57.npy
new file mode 100644
index 0000000..e9feda0
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_2_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_2_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_2_with_cost_71.npy
new file mode 100644
index 0000000..969aa75
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_2_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_30_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_30_with_cost_57.npy
new file mode 100644
index 0000000..41c5785
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_30_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_30_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_30_with_cost_71.npy
new file mode 100644
index 0000000..93d560c
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_30_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_31_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_31_with_cost_57.npy
new file mode 100644
index 0000000..2d5bd57
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_31_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_31_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_31_with_cost_71.npy
new file mode 100644
index 0000000..f04f4bf
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_31_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_32_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_32_with_cost_57.npy
new file mode 100644
index 0000000..04fcba3
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_32_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_32_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_32_with_cost_71.npy
new file mode 100644
index 0000000..cade7cf
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_32_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_33_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_33_with_cost_57.npy
new file mode 100644
index 0000000..4896a44
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_33_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_33_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_33_with_cost_71.npy
new file mode 100644
index 0000000..41a75a0
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_33_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_34_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_34_with_cost_57.npy
new file mode 100644
index 0000000..4289b36
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_34_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_34_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_34_with_cost_71.npy
new file mode 100644
index 0000000..64aeb84
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_34_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_35_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_35_with_cost_57.npy
new file mode 100644
index 0000000..4246725
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_35_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_35_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_35_with_cost_71.npy
new file mode 100644
index 0000000..47abea8
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_35_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_36_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_36_with_cost_57.npy
new file mode 100644
index 0000000..eeeba4f
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_36_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_36_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_36_with_cost_71.npy
new file mode 100644
index 0000000..21edfe3
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_36_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_37_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_37_with_cost_57.npy
new file mode 100644
index 0000000..4750096
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_37_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_37_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_37_with_cost_71.npy
new file mode 100644
index 0000000..4c4c0e5
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_37_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_38_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_38_with_cost_57.npy
new file mode 100644
index 0000000..8c3f7e6
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_38_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_38_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_38_with_cost_71.npy
new file mode 100644
index 0000000..af1ab0e
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_38_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_39_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_39_with_cost_57.npy
new file mode 100644
index 0000000..947015e
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_39_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_39_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_39_with_cost_71.npy
new file mode 100644
index 0000000..87d939e
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_39_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_3_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_3_with_cost_57.npy
new file mode 100644
index 0000000..ea6fe2f
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_3_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_3_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_3_with_cost_71.npy
new file mode 100644
index 0000000..d285df6
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_3_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_40_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_40_with_cost_57.npy
new file mode 100644
index 0000000..439e3b4
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_40_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_40_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_40_with_cost_71.npy
new file mode 100644
index 0000000..2608b41
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_40_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_41_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_41_with_cost_57.npy
new file mode 100644
index 0000000..47e8ef5
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_41_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_41_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_41_with_cost_71.npy
new file mode 100644
index 0000000..49121c9
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_41_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_42_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_42_with_cost_57.npy
new file mode 100644
index 0000000..ba9d16f
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_42_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_42_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_42_with_cost_71.npy
new file mode 100644
index 0000000..c90b959
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_42_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_43_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_43_with_cost_57.npy
new file mode 100644
index 0000000..94f8597
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_43_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_43_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_43_with_cost_71.npy
new file mode 100644
index 0000000..f3e5228
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_43_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_44_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_44_with_cost_57.npy
new file mode 100644
index 0000000..97e3e47
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_44_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_44_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_44_with_cost_71.npy
new file mode 100644
index 0000000..f6390a9
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_44_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_45_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_45_with_cost_57.npy
new file mode 100644
index 0000000..88e5a1b
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_45_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_45_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_45_with_cost_71.npy
new file mode 100644
index 0000000..fa012d9
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_45_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_46_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_46_with_cost_57.npy
new file mode 100644
index 0000000..fc6e3d0
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_46_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_46_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_46_with_cost_71.npy
new file mode 100644
index 0000000..0663ad3
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_46_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_47_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_47_with_cost_57.npy
new file mode 100644
index 0000000..509398e
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_47_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_47_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_47_with_cost_71.npy
new file mode 100644
index 0000000..054915a
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_47_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_48_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_48_with_cost_57.npy
new file mode 100644
index 0000000..d074a1b
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_48_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_48_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_48_with_cost_71.npy
new file mode 100644
index 0000000..8afdaaf
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_48_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_49_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_49_with_cost_57.npy
new file mode 100644
index 0000000..add7fc8
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_49_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_49_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_49_with_cost_71.npy
new file mode 100644
index 0000000..8ebaa14
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_49_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_4_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_4_with_cost_57.npy
new file mode 100644
index 0000000..f308a44
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_4_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_4_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_4_with_cost_71.npy
new file mode 100644
index 0000000..53d1974
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_4_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_50_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_50_with_cost_57.npy
new file mode 100644
index 0000000..0643a5e
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_50_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_50_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_50_with_cost_71.npy
new file mode 100644
index 0000000..e005932
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_50_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_51_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_51_with_cost_57.npy
new file mode 100644
index 0000000..b525a56
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_51_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_51_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_51_with_cost_71.npy
new file mode 100644
index 0000000..47e17aa
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_51_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_52_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_52_with_cost_57.npy
new file mode 100644
index 0000000..4a43729
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_52_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_52_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_52_with_cost_71.npy
new file mode 100644
index 0000000..699ea5d
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_52_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_53_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_53_with_cost_57.npy
new file mode 100644
index 0000000..b460a69
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_53_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_53_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_53_with_cost_71.npy
new file mode 100644
index 0000000..65f60a7
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_53_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_54_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_54_with_cost_57.npy
new file mode 100644
index 0000000..412857b
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_54_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_54_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_54_with_cost_71.npy
new file mode 100644
index 0000000..9380243
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_54_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_55_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_55_with_cost_57.npy
new file mode 100644
index 0000000..1a0de2f
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_55_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_55_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_55_with_cost_71.npy
new file mode 100644
index 0000000..cec110c
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_55_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_56_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_56_with_cost_57.npy
new file mode 100644
index 0000000..eb2bb53
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_56_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_56_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_56_with_cost_71.npy
new file mode 100644
index 0000000..e87f9fc
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_56_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_57_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_57_with_cost_57.npy
new file mode 100644
index 0000000..4d1e317
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_57_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_57_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_57_with_cost_71.npy
new file mode 100644
index 0000000..243e4a3
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_57_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_58_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_58_with_cost_57.npy
new file mode 100644
index 0000000..b449845
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_58_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_58_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_58_with_cost_71.npy
new file mode 100644
index 0000000..8110c95
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_58_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_59_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_59_with_cost_57.npy
new file mode 100644
index 0000000..b142a12
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_59_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_59_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_59_with_cost_71.npy
new file mode 100644
index 0000000..b73fc52
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_59_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_5_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_5_with_cost_57.npy
new file mode 100644
index 0000000..6d351f5
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_5_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_5_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_5_with_cost_71.npy
new file mode 100644
index 0000000..9e1f062
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_5_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_60_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_60_with_cost_57.npy
new file mode 100644
index 0000000..90a6c7b
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_60_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_60_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_60_with_cost_71.npy
new file mode 100644
index 0000000..3268159
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_60_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_61_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_61_with_cost_57.npy
new file mode 100644
index 0000000..ea0c3a0
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_61_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_61_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_61_with_cost_71.npy
new file mode 100644
index 0000000..60b25b8
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_61_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_62_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_62_with_cost_57.npy
new file mode 100644
index 0000000..17181bc
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_62_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_62_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_62_with_cost_71.npy
new file mode 100644
index 0000000..51a15b1
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_62_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_63_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_63_with_cost_57.npy
new file mode 100644
index 0000000..4e90897
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_63_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_63_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_63_with_cost_71.npy
new file mode 100644
index 0000000..ea9bc7d
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_63_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_64_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_64_with_cost_57.npy
new file mode 100644
index 0000000..5a8e59e
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_64_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_64_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_64_with_cost_71.npy
new file mode 100644
index 0000000..a92c61f
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_64_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_65_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_65_with_cost_57.npy
new file mode 100644
index 0000000..7863323
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_65_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_65_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_65_with_cost_71.npy
new file mode 100644
index 0000000..ef0674d
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_65_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_66_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_66_with_cost_57.npy
new file mode 100644
index 0000000..4d616b1
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_66_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_66_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_66_with_cost_71.npy
new file mode 100644
index 0000000..40b9df0
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_66_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_67_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_67_with_cost_57.npy
new file mode 100644
index 0000000..beb2e73
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_67_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_67_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_67_with_cost_71.npy
new file mode 100644
index 0000000..b67ba75
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_67_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_68_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_68_with_cost_57.npy
new file mode 100644
index 0000000..35221d0
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_68_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_68_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_68_with_cost_71.npy
new file mode 100644
index 0000000..73b12f8
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_68_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_69_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_69_with_cost_57.npy
new file mode 100644
index 0000000..6bb6f82
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_69_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_69_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_69_with_cost_71.npy
new file mode 100644
index 0000000..c74399e
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_69_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_6_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_6_with_cost_57.npy
new file mode 100644
index 0000000..d1cc134
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_6_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_6_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_6_with_cost_71.npy
new file mode 100644
index 0000000..e8d0236
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_6_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_70_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_70_with_cost_57.npy
new file mode 100644
index 0000000..72d572e
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_70_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_70_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_70_with_cost_71.npy
new file mode 100644
index 0000000..c8e5b38
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_70_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_71_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_71_with_cost_57.npy
new file mode 100644
index 0000000..784efa4
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_71_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_71_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_71_with_cost_71.npy
new file mode 100644
index 0000000..a5f6cb6
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_71_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_72_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_72_with_cost_57.npy
new file mode 100644
index 0000000..c95759a
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_72_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_72_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_72_with_cost_71.npy
new file mode 100644
index 0000000..60965a0
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_72_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_73_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_73_with_cost_57.npy
new file mode 100644
index 0000000..392994b
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_73_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_73_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_73_with_cost_71.npy
new file mode 100644
index 0000000..16847c3
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_73_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_74_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_74_with_cost_57.npy
new file mode 100644
index 0000000..8eb737d
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_74_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_74_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_74_with_cost_71.npy
new file mode 100644
index 0000000..c0d9ba4
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_74_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_75_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_75_with_cost_57.npy
new file mode 100644
index 0000000..4c9748d
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_75_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_75_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_75_with_cost_71.npy
new file mode 100644
index 0000000..8463030
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_75_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_76_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_76_with_cost_57.npy
new file mode 100644
index 0000000..02b2cb3
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_76_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_76_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_76_with_cost_71.npy
new file mode 100644
index 0000000..d6228e9
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_76_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_77_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_77_with_cost_57.npy
new file mode 100644
index 0000000..3e0e200
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_77_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_77_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_77_with_cost_71.npy
new file mode 100644
index 0000000..48ca81a
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_77_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_78_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_78_with_cost_57.npy
new file mode 100644
index 0000000..d78182c
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_78_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_78_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_78_with_cost_71.npy
new file mode 100644
index 0000000..01da601
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_78_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_79_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_79_with_cost_57.npy
new file mode 100644
index 0000000..09a29f7
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_79_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_79_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_79_with_cost_71.npy
new file mode 100644
index 0000000..3f57770
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_79_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_7_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_7_with_cost_57.npy
new file mode 100644
index 0000000..ac47347
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_7_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_7_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_7_with_cost_71.npy
new file mode 100644
index 0000000..cd6d439
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_7_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_80_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_80_with_cost_57.npy
new file mode 100644
index 0000000..d465f21
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_80_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_80_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_80_with_cost_71.npy
new file mode 100644
index 0000000..305e57e
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_80_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_81_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_81_with_cost_57.npy
new file mode 100644
index 0000000..9c04861
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_81_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_81_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_81_with_cost_71.npy
new file mode 100644
index 0000000..5ff2149
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_81_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_82_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_82_with_cost_57.npy
new file mode 100644
index 0000000..67bafe6
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_82_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_82_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_82_with_cost_71.npy
new file mode 100644
index 0000000..f9a174b
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_82_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_83_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_83_with_cost_57.npy
new file mode 100644
index 0000000..82cba50
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_83_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_83_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_83_with_cost_71.npy
new file mode 100644
index 0000000..406917c
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_83_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_84_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_84_with_cost_57.npy
new file mode 100644
index 0000000..473e87f
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_84_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_84_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_84_with_cost_71.npy
new file mode 100644
index 0000000..0642bc9
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_84_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_85_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_85_with_cost_57.npy
new file mode 100644
index 0000000..b7e5b3d
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_85_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_85_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_85_with_cost_71.npy
new file mode 100644
index 0000000..163bd36
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_85_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_86_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_86_with_cost_57.npy
new file mode 100644
index 0000000..c935b0f
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_86_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_86_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_86_with_cost_71.npy
new file mode 100644
index 0000000..5d78297
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_86_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_87_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_87_with_cost_57.npy
new file mode 100644
index 0000000..3f7003e
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_87_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_87_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_87_with_cost_71.npy
new file mode 100644
index 0000000..84ac05e
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_87_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_88_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_88_with_cost_57.npy
new file mode 100644
index 0000000..14ab424
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_88_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_88_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_88_with_cost_71.npy
new file mode 100644
index 0000000..d831e76
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_88_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_89_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_89_with_cost_57.npy
new file mode 100644
index 0000000..f06cb19
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_89_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_89_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_89_with_cost_71.npy
new file mode 100644
index 0000000..bcc0cb2
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_89_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_8_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_8_with_cost_57.npy
new file mode 100644
index 0000000..8e2575c
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_8_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_8_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_8_with_cost_71.npy
new file mode 100644
index 0000000..ea414fe
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_8_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_90_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_90_with_cost_57.npy
new file mode 100644
index 0000000..6374209
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_90_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_90_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_90_with_cost_71.npy
new file mode 100644
index 0000000..a5b7248
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_90_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_91_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_91_with_cost_57.npy
new file mode 100644
index 0000000..80f6a44
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_91_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_91_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_91_with_cost_71.npy
new file mode 100644
index 0000000..5b85a79
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_91_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_92_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_92_with_cost_57.npy
new file mode 100644
index 0000000..83486c9
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_92_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_92_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_92_with_cost_71.npy
new file mode 100644
index 0000000..f504188
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_92_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_93_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_93_with_cost_57.npy
new file mode 100644
index 0000000..9365843
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_93_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_93_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_93_with_cost_71.npy
new file mode 100644
index 0000000..46052f0
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_93_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_94_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_94_with_cost_57.npy
new file mode 100644
index 0000000..ecdf738
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_94_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_94_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_94_with_cost_71.npy
new file mode 100644
index 0000000..a674e62
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_94_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_95_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_95_with_cost_57.npy
new file mode 100644
index 0000000..460e2d0
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_95_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_95_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_95_with_cost_71.npy
new file mode 100644
index 0000000..ce657df
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_95_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_96_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_96_with_cost_57.npy
new file mode 100644
index 0000000..67e2eb4
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_96_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_96_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_96_with_cost_71.npy
new file mode 100644
index 0000000..d14d3af
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_96_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_97_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_97_with_cost_57.npy
new file mode 100644
index 0000000..068f138
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_97_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_97_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_97_with_cost_71.npy
new file mode 100644
index 0000000..a9d7f8a
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_97_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_98_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_98_with_cost_57.npy
new file mode 100644
index 0000000..beacfe5
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_98_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_98_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_98_with_cost_71.npy
new file mode 100644
index 0000000..98e887a
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_98_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_99_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_99_with_cost_57.npy
new file mode 100644
index 0000000..ae6520e
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_99_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_99_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_99_with_cost_71.npy
new file mode 100644
index 0000000..5120224
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_99_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_9_with_cost_57.npy b/qLearning/Adversary_as_QTable/QTables/round_9_with_cost_57.npy
new file mode 100644
index 0000000..167903b
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_9_with_cost_57.npy differ
diff --git a/qLearning/Adversary_as_QTable/QTables/round_9_with_cost_71.npy b/qLearning/Adversary_as_QTable/QTables/round_9_with_cost_71.npy
new file mode 100644
index 0000000..2cb1fcf
Binary files /dev/null and b/qLearning/Adversary_as_QTable/QTables/round_9_with_cost_71.npy differ
diff --git a/qLearning/Adversary_as_QTable/Qtable.py b/qLearning/Adversary_as_QTable/Qtable.py
new file mode 100644
index 0000000..29935d2
--- /dev/null
+++ b/qLearning/Adversary_as_QTable/Qtable.py
@@ -0,0 +1,47 @@
+# Ed, Galit and Katerina
+# Relates to the Q-Learning approach.
+# Defines the Q-table
+
+import numpy as np
+import os
+
+class QTable():
+
+
+ def __init__(self, num_States, num_Actions, learning_Rate):
+
+ self.num_States= num_States
+ self.num_Actions = num_Actions
+ self.learning_Rate = learning_Rate
+ self.Q_table = np.zeros((self.num_States, self.num_Actions))
+ self.QTable_name=f"QTable, actions={self.num_Actions}, states={self.num_States}"
+
+
+ def reset(self):
+ Qtable = np.zeros((self.num_States, self.num_Actions))
+ return Qtable, self.learning_rate
+
+ def myopicReset(self):
+ Qtable = np.zeros((self.num_States, self.num_Actions))
+ for i in range(self.num_States):
+ Qtable[i][self.num_Actions-1] = 1
+ return Qtable
+
+ def save(self, name = None):
+ if name is None:
+ return np.save(os.path.join('QTables',f'{self.QTable_name}'), self.Q_table)
+ else:
+ return np.save(os.path.join('QTables',name), self.Q_table)
+
+ def load(self,name = None):
+ if name is None:
+ return np.load(os.path.join('QTables',f'{self.QTable_name}'))
+ else:
+ return np.load(os.path.join('QTables',name))
+
+
+
+
+
+
+
diff --git a/qLearning/Adversary_as_QTable/__pycache__/Qtable.cpython-39.pyc b/qLearning/Adversary_as_QTable/__pycache__/Qtable.cpython-39.pyc
new file mode 100644
index 0000000..f23be59
Binary files /dev/null and b/qLearning/Adversary_as_QTable/__pycache__/Qtable.cpython-39.pyc differ
diff --git a/qLearning/Adversary_as_QTable/__pycache__/environment.cpython-39.pyc b/qLearning/Adversary_as_QTable/__pycache__/environment.cpython-39.pyc
new file mode 100644
index 0000000..95e4169
Binary files /dev/null and b/qLearning/Adversary_as_QTable/__pycache__/environment.cpython-39.pyc differ
diff --git a/qLearning/Adversary_as_QTable/__pycache__/learningAgent.cpython-39.pyc b/qLearning/Adversary_as_QTable/__pycache__/learningAgent.cpython-39.pyc
new file mode 100644
index 0000000..ff951d2
Binary files /dev/null and b/qLearning/Adversary_as_QTable/__pycache__/learningAgent.cpython-39.pyc differ
diff --git a/qLearning/Adversary_as_QTable/__pycache__/test.cpython-39.pyc b/qLearning/Adversary_as_QTable/__pycache__/test.cpython-39.pyc
new file mode 100644
index 0000000..d1aa13e
Binary files /dev/null and b/qLearning/Adversary_as_QTable/__pycache__/test.cpython-39.pyc differ
diff --git a/qLearning/Adversary_as_QTable/environment.py b/qLearning/Adversary_as_QTable/environment.py
new file mode 100644
index 0000000..6af7da0
--- /dev/null
+++ b/qLearning/Adversary_as_QTable/environment.py
@@ -0,0 +1,88 @@
+# Katerina, Ed and Galit (and Tommy!)
+# Relates to the Q-Learning approach.
+# Contains DemandPotentialGame Class and the Model of the DemandPotentialGame Class.
+
+from enum import Enum
+import numpy as np # numerical python
+
+# printoptions: output limited to 2 digits after decimal point
+np.set_printoptions(precision=2, suppress=False)
+
+
+class DemandPotentialGame():
+ """
+ Fully defines demand Potential Game. It contains game rules, memory and agents strategies.
+ """
+
+ def __init__(self, totalDemand, tupleCosts, totalStages) -> None:
+ self.totalDemand = totalDemand
+ self.costs = tupleCosts
+ self.T = totalStages
+ # first index is always player
+ self.demandPotential = None # two lists for the two players
+ self.prices = None # prices over T rounds
+ self.profit = None # profit in each of T rounds
+ self.stage = None
+
+ def resetGame(self):
+ """
+ Method resets game memory: Demand Potential, prices, profits
+ """
+ self.demandPotential = [[0] * self.T, [0] * self.T] # two lists for the two players
+ self.prices = [[0] * self.T, [0] * self.T] # prices over T rounds
+ self.profit = [[0] * self.T, [0] * self.T] # profit in each of T rounds
+ self.demandPotential[0][0] = self.totalDemand / 2 # initialise first round 0
+ self.demandPotential[1][0] = self.totalDemand / 2
+
+ def profits(self, player=0):
+ """
+ Computes profits. Player 0 is the learning agent.
+ """
+ return self.profit[player][self.stage]
+
+ def updatePricesProfitDemand(self, pricePair):
+ """
+ Updates Prices, Profit and Demand Potential Memory.
+ Parameters.
+ pricePair: Pair of prices from the Learning agent and adversary.
+ """
+
+ for player in [0, 1]:
+ price = pricePair[player]
+ self.prices[player][self.stage] = price
+ self.profit[player][self.stage] = (self.demandPotential[player][self.stage] - price) * (
+ price - self.costs[player])
+ if self.stage < self.T - 1:
+ self.demandPotential[player][self.stage + 1] = \
+ self.demandPotential[player][self.stage] + (pricePair[1 - player] - price) / 2
+
+ def monopolyPrice(self, player, t): # myopic monopoly price
+ """
+ Computes Monopoly prices.
+ """
+ return (self.demandPotential[player][self.stage] + self.costs[player]) / 2
+
+ """
+ The following adversary strategies have been changed from the policy gradient method to remove
+ the last period effect.
+ """
+
+
+class Model(DemandPotentialGame):
+ """
+ Defines the Problem's Model. It is assumed a Markov Decision Process is defined.
+ The class is a Child from the Demand Potential Game Class.
+ The reason: Model is a conceptualisation of the Game.
+ """
+
+ def __init__(self, totalDemand, tupleCosts, totalStages, initState, adversary) -> None:
+ super().__init__(totalDemand, tupleCosts, totalStages)
+
+ self.rewardFunction = self.profits
+ self.initState = initState
+ self.episodesMemory = list()
+ self.done = False
+ self.adversary = adversary
+
+
+
diff --git a/qLearning/Adversary_as_QTable/learningAgent.py b/qLearning/Adversary_as_QTable/learningAgent.py
new file mode 100644
index 0000000..0d64de7
--- /dev/null
+++ b/qLearning/Adversary_as_QTable/learningAgent.py
@@ -0,0 +1,84 @@
+# Ed, Kat, Galit
+# ReinforceAlgorithm Class: Solver.
+
+import numpy as np
+
+# printoptions: output limited to 2 digits after decimal point
+np.set_printoptions(precision=2, suppress=False)
+
+
+class LearningAlgorithm():
+ """
+ Model Solver.
+ """
+ def __init__(self, Model, Qtable, numberEpisodes, discountFactor) -> None:
+
+ self.env = Model
+ self.Qtable = Qtable.Q_table
+ self.learning_Rate = Qtable.learning_Rate
+ self.numberEpisodes = numberEpisodes
+ self.gamma = discountFactor
+ self.numStates=Qtable.num_States #Qtable dimen - number of states x number of actions
+ if self.numStates % 2 ==0 :
+ print('num of states should be odd')
+ self.numActions=Qtable.num_Actions
+ if self.numActions % 2 ==1 :
+ print('num of actions should be even')
+ self.lowestState = 200-(self.numStates - 1)/2
+ self.highestState = 200+(self.numStates - 1)/2
+
+
+ def resetQtable(self):
+ self.Qtable, self.learning_Rate = self.Qtable.reset()
+
+ """
+ This function will eventually choose and adversary agent to play against
+ and according to that return an action played by that adversary.
+ This could be chosen according to some existing equilibrium dist.
+ """
+ def chooseAdversaryAction(self, state):
+ adversary = self.env.adversary
+ lowestAdversaryState = 200 - (len(adversary) -1)/2
+ adversaryStateIndex = int((400 - state) - lowestAdversaryState) # Declare as int for index reasons
+ row = adversary[adversaryStateIndex]
+ adversaryActionIndex = np.argmax(row)
+ action = adversaryActionIndex + int((400-state) + self.env.costs[1])/2 - len(row) + 1
+ # Highest action is the myopic action. Subtract length of row and add one to get to lowest action.
+ return action
+
+ def StateInd(self, state): # computes state index in Qtable
+ return int(state - self.lowestState) # Declare as int for index reasons
+ #return min(int(state -(200-self.numStates/2)), self.numStates - 1)
+
+ def ActionInd(self, monPrice, action): # computes action index in Qtable
+ return int(action - (monPrice - self.numActions + 1)) #monPrice should have index numActions - 1
+
+ def alpha_n(self, n): # defines the Qlearning rate
+ return self.learning_Rate[0]/(n+self.learning_Rate[1])
+ """
+ Now the Q-learning itself
+ """
+ def solver(self):
+
+ self.resetQtable
+
+ for episode in range(self.numberEpisodes):
+
+ state = np.random.randint(self.lowestState, self.highestState + 1)
+ monPrice = int((state + self.env.costs[0]) / 2)
+ action = np.random.randint(monPrice-self.numActions+1, monPrice + 1)
+ advAction = self.chooseAdversaryAction(state)
+ reward = (state-action)*(action-self.env.costs[0])
+
+ next_state = int(state+.5*(advAction-action))
+
+ opt_value_next = max(self.Qtable[self.StateInd(next_state)])
+
+ # updating the Qtable
+ qvalue = (1-self.alpha_n(episode)) * \
+ self.Qtable[self.StateInd(state), self.ActionInd(monPrice, action)]\
+ + self.alpha_n(episode) * \
+ ((1-self.gamma)*reward + self.gamma*opt_value_next)
+ self.Qtable[self.StateInd(state), self.ActionInd(monPrice, action)]=qvalue
+
+
diff --git a/qLearning/Adversary_as_QTable/qLearningSimulations.ipynb b/qLearning/Adversary_as_QTable/qLearningSimulations.ipynb
new file mode 100644
index 0000000..384ccf6
--- /dev/null
+++ b/qLearning/Adversary_as_QTable/qLearningSimulations.ipynb
@@ -0,0 +1,359 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np\n",
+ "import os"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_Demand = 400\n",
+ "agent_Cost = 57\n",
+ "adv_Cost = 71\n",
+ "total_Stages = 25\n",
+ "num_Actions = 50\n",
+ "num_States = abs(adv_Cost - agent_Cost) + 2 * num_Actions + 1\n",
+ "Qtable = QTable(num_States, num_Actions, learning_Rate = [4900000,5000000])\n",
+ "adversary = Qtable.myopicReset()\n",
+ "init_State = [total_Demand/2, total_Demand/2]\n",
+ "\n",
+ "game = Model(total_Demand, [agent_Cost,adv_Cost], total_Stages, init_State, adversary)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+demoninator)\n",
+ "Qtable = QTable(num_States, num_Actions, learning_Rate = [4900000,5000000])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "numberEpisodes = 10_000_000\n",
+ "discountFactor = 0.99"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, numberEpisodes, discountFactor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "algorithm.solver()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# print(Qtable.Q_table)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "result = Test(game, Qtable, discountFactor, adversary)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "156721.63152210606\n",
+ "[ 85 95 100 104 106 107 106 108 108 108 108 108 108 108 108 108 108 108\n",
+ " 108 108 108 108 108 108 108]\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Returns the optimal payoff and actions according to the Qtable\n",
+ "payoff, actions = result.totalPayoff()\n",
+ "print(payoff)\n",
+ "print(actions)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The percentage error of the Qtable\n",
+ "error = result.error()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "6.518340237578261e-09"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "error.mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Qtable.save(f\"round_1_with_cost_{agent_Cost}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "110258.78904553386\n",
+ "116640.93660597151\n",
+ "123765.78297511289\n",
+ "132419.5334349324\n",
+ "118895.01299519878\n",
+ "114074.40311244366\n",
+ "128890.11251690678\n",
+ "130223.1057102801\n",
+ "133140.7482414045\n",
+ "116465.83912746499\n",
+ "125063.2006751129\n",
+ "125940.23067511289\n",
+ "125957.97927654626\n",
+ "107272.61069141378\n",
+ "121311.53567749058\n",
+ "113063.16759725903\n",
+ "107458.02632269276\n",
+ "109723.43214403171\n",
+ "118912.159127465\n",
+ "94472.45361610936\n",
+ "96614.7020580578\n",
+ "123660.69922068373\n",
+ "113594.5605369414\n",
+ "133117.6149365891\n",
+ "133121.57493658908\n",
+ "127847.4176639798\n",
+ "116502.51310882121\n",
+ "129115.41814818578\n",
+ "129155.19814818578\n",
+ "109324.66751563683\n",
+ "114853.33971394581\n",
+ "131905.3337538852\n",
+ "123816.51095539633\n",
+ "118572.5288369414\n",
+ "122851.95752179525\n",
+ "103048.15069503624\n",
+ "113477.0171906411\n",
+ "122691.7971424863\n",
+ "113683.66538534917\n",
+ "107785.76389441808\n",
+ "122808.75559409145\n",
+ "105134.93273232372\n",
+ "96306.0441958089\n",
+ "107120.3732147185\n",
+ "143027.0485064772\n",
+ "112219.44224087294\n",
+ "122838.25520234526\n",
+ "116886.20952446072\n",
+ "126461.93717330166\n",
+ "101169.65758887315\n",
+ "123960.36295481244\n",
+ "101252.44419037527\n",
+ "108607.11991306185\n",
+ "108607.11991306185\n",
+ "103322.50399488166\n",
+ "100289.86593895043\n",
+ "107415.77389441806\n",
+ "115939.91433393714\n",
+ "109228.76738794592\n",
+ "120456.13629919032\n",
+ "122644.77824179525\n",
+ "118209.5288369414\n",
+ "118736.2088369414\n",
+ "108018.30515697603\n",
+ "127637.04106066648\n",
+ "128970.16106066648\n",
+ "126036.4802859369\n",
+ "132982.73975397734\n",
+ "117158.41310882122\n",
+ "126623.01573464928\n",
+ "111118.9956393708\n",
+ "138586.0125685975\n",
+ "127113.51418562784\n",
+ "113201.03913289863\n",
+ "112983.7671906411\n",
+ "104925.45933201465\n",
+ "124167.24164533603\n",
+ "124856.23361240039\n",
+ "135133.33758485512\n",
+ "125902.8830124004\n",
+ "124014.97721228783\n",
+ "101776.84593895041\n",
+ "103869.29001352542\n",
+ "128571.35814818578\n",
+ "106289.81030404904\n",
+ "103766.11797623792\n",
+ "105708.44030404904\n",
+ "132776.5164459324\n",
+ "119350.159127465\n",
+ "99883.17118286462\n",
+ "101434.19642315639\n",
+ "97751.11768933678\n",
+ "119882.27058370535\n",
+ "112186.0692310874\n",
+ "129006.58180512131\n",
+ "113658.44728748228\n",
+ "112894.31058913897\n",
+ "102568.19642315639\n",
+ "97131.58402211787\n",
+ "100300.13118286463\n"
+ ]
+ }
+ ],
+ "source": [
+ "num_rounds = 100\n",
+ "payoffs = [0]*num_rounds\n",
+ "actions = np.zeros((num_rounds, total_Stages))\n",
+ "for i in range(num_rounds):\n",
+ " \n",
+ " adversary = Qtable.Q_table\n",
+ " # Swap over players\n",
+ " game = Model(total_Demand, [adv_Cost,agent_Cost], total_Stages, init_State, adversary)\n",
+ " Qtable = QTable(num_States, num_Actions, learning_Rate = [4900000,5000000])\n",
+ " algorithm = LearningAlgorithm(game, Qtable, numberEpisodes, discountFactor)\n",
+ " algorithm.solver()\n",
+ " round = i+1\n",
+ " Qtable.save(f\"round_{round}_with_cost_{adv_Cost}\")\n",
+ "\n",
+ " adversary = Qtable.Q_table\n",
+ " # Swap back over\n",
+ " game = Model(total_Demand, [agent_Cost,adv_Cost], total_Stages, init_State, adversary)\n",
+ " Qtable = QTable(num_States, num_Actions, learning_Rate = [4900000,5000000])\n",
+ " algorithm = LearningAlgorithm(game, Qtable, numberEpisodes, discountFactor)\n",
+ " algorithm.solver()\n",
+ " result = Test(game, Qtable, discountFactor, adversary)\n",
+ " payoff, prices = result.totalPayoff()\n",
+ " payoffs[i] = payoff\n",
+ " print(payoff)\n",
+ " for stage in range(total_Stages):\n",
+ " actions[i][stage] = prices[stage]\n",
+ " round = i+2\n",
+ " Qtable.save(f\"round_{round}_with_cost_{agent_Cost}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import matplotlib.pyplot as plt\n",
+ "plt.plot(payoffs)\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Adversary_as_QTable/test.py b/qLearning/Adversary_as_QTable/test.py
new file mode 100644
index 0000000..91ed0c7
--- /dev/null
+++ b/qLearning/Adversary_as_QTable/test.py
@@ -0,0 +1,128 @@
+# Ed, Galit and Katerina
+# Relates to the Q-Learning approach.
+# Testing out the Q-table against a given opponent
+
+import numpy as np
+
+
+class Test():
+
+
+ def __init__(self, Model, Qtable, discountFactor, adversary) -> None:
+
+
+ self.env = Model
+ self.Qtable = Qtable.Q_table
+ self.numStates=Qtable.num_States
+ self.numActions=Qtable.num_Actions
+ self.discountFactor = discountFactor
+ self.episodeLength = Model.T
+ self.adversary = adversary
+
+
+ def chooseAdversaryAction(self, state):
+ adversary = self.adversary
+ lowestAdversaryState = 200 - len(adversary)/2
+ adversaryStateIndex = int((400 - state) - lowestAdversaryState)
+ row = adversary[adversaryStateIndex]
+ adversaryActionIndex = np.argmax(row)
+ action = adversaryActionIndex + int((400-state) + self.env.costs[1])/2 - len(row) + 1
+ return action
+
+
+ def totalPayoff(self):
+
+ utility = 0
+ actions = [0]*self.episodeLength
+ state = 200
+ delta = 1/self.discountFactor
+
+ for i in range(self.episodeLength):
+ delta = delta * self.discountFactor
+ row = self.Qtable[int(state -(200-self.numStates/2))]
+ action = np.argmax(row) + int((state + self.env.costs[0])/2) - self.numActions + 1
+ actions[i] = action
+ utility += (state-action)*(action-self.env.costs[0]) * delta
+ advAction = self.chooseAdversaryAction(state)
+ state = int(state+.5*(advAction-action))
+ return utility, np.transpose(actions)
+
+ def bestResponses(self):
+ states = [0]* self.numStates
+ bestResponses = [0]* self.numStates
+ for i in range(self.numStates):
+ demand = int((200-self.numStates/2)) + i
+ states[i] = demand
+ action = np.argmax(self.Qtable[i]) + int((demand + self.env.costs[0])/2) - self.numActions + 1
+ bestResponses[i] = action
+ return states, bestResponses
+
+
+ def error(self):
+
+ Qtable_error = np.zeros((self.numStates, self.numActions))
+ lowestState = int(200-(self.numStates - 1)/2)
+
+ for stateIndex in range(self.numStates):
+ for actionIndex in range(self.numActions):
+
+ state = stateIndex + lowestState
+ monopoly_price = int((state + self.env.costs[0])/2)
+ action = actionIndex + monopoly_price - self.numActions + 1
+
+ reward = (state - action) * (action - self.env.costs[0])
+ adv_action = self.chooseAdversaryAction(state)
+ next_state = int(state + (adv_action - action)/2)
+
+
+ next_state_index = next_state - lowestState
+ opt_value_next = max(self.Qtable[next_state_index])
+ new_value = (1-self.discountFactor)*reward + self.discountFactor * opt_value_next
+ Qtable_error[stateIndex,actionIndex] = (new_value - self.Qtable[stateIndex,actionIndex])/new_value
+ return Qtable_error
+
+
+
+
+
+ def myopic(self, cost, demand):
+ return (cost + demand)/2
+
+ def payoff(self, cost, demand, price):
+ return (demand - price)*(price - cost)
+
+ def updateDemand(self, demand, pricePair):
+ newDemand = demand + 0.5*(pricePair[1]- pricePair[0])
+ return newDemand
+
+ def utilityOfActions(self, actions):
+ agentDemand = 200
+ opponentDemand = 200
+ totalPayoff = 0
+ delta = 1/self.discountFactor
+ for i in range(self.episodeLength):
+ delta = delta * self.discountFactor
+ agentPrice = int(actions[i])
+ opponentPrice = int(self.myopic(self.env.costs[1],opponentDemand))
+ totalPayoff += self.payoff(self.env.costs[0],agentDemand,agentPrice) * delta
+ agentDemand = int(self.updateDemand(agentDemand, [agentPrice,opponentPrice]))
+ opponentDemand = 400 - agentDemand
+ return totalPayoff
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/qLearning/Episodic_learning/.DS_Store b/qLearning/Episodic_learning/.DS_Store
new file mode 100644
index 0000000..41ea1eb
Binary files /dev/null and b/qLearning/Episodic_learning/.DS_Store differ
diff --git a/qLearning/Episodic_learning/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb b/qLearning/Episodic_learning/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
new file mode 100644
index 0000000..34edbb2
--- /dev/null
+++ b/qLearning/Episodic_learning/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
@@ -0,0 +1,430 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_demand = 400\n",
+ "agent_cost = 57\n",
+ "adversary_cost = 71 \n",
+ "costs = [agent_cost,adversary_cost]\n",
+ "total_stages = 25\n",
+ "initial_state = [total_demand/2, total_demand/2]\n",
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "adversary_probabilities[10]=1 \n",
+ "game = Model(total_demand, costs, total_stages, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "number_actions = 50\n",
+ "number_demands = total_demand + 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+demoninator)\n",
+ "Qtable = QTable(number_demands, number_actions, total_stages , learning_rate = [1000000,1000000])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "number_episodes = 20_000_000\n",
+ "discount_factor = 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, number_episodes, discount_factor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0\n",
+ "113343\n",
+ "115339\n",
+ "120309\n",
+ "121468\n",
+ "124003\n",
+ "125564\n",
+ "250000\n",
+ "500000\n",
+ "750000\n",
+ "1000000\n",
+ "1250000\n",
+ "1500000\n",
+ "1750000\n",
+ "2000000\n",
+ "2250000\n",
+ "2500000\n",
+ "2750000\n",
+ "3000000\n",
+ "3250000\n",
+ "3500000\n",
+ "3750000\n",
+ "4000000\n",
+ "4250000\n",
+ "4500000\n",
+ "4750000\n",
+ "5000000\n",
+ "5250000\n",
+ "5500000\n",
+ "5750000\n",
+ "6000000\n",
+ "6250000\n",
+ "6500000\n",
+ "6750000\n",
+ "7000000\n",
+ "7250000\n",
+ "7500000\n",
+ "7750000\n",
+ "8000000\n",
+ "8250000\n",
+ "8500000\n",
+ "8750000\n",
+ "9000000\n",
+ "9250000\n",
+ "9500000\n",
+ "9750000\n",
+ "10000000\n",
+ "10250000\n",
+ "10500000\n",
+ "10750000\n",
+ "11000000\n",
+ "11250000\n",
+ "11500000\n",
+ "11750000\n",
+ "12000000\n",
+ "12250000\n",
+ "12500000\n",
+ "12750000\n",
+ "13000000\n",
+ "13250000\n",
+ "13500000\n",
+ "13750000\n",
+ "14000000\n",
+ "14250000\n",
+ "14500000\n",
+ "14750000\n",
+ "15000000\n",
+ "15250000\n",
+ "15500000\n",
+ "15750000\n",
+ "16000000\n",
+ "16250000\n",
+ "16500000\n",
+ "16750000\n",
+ "17000000\n",
+ "17250000\n",
+ "17500000\n",
+ "17750000\n",
+ "18000000\n",
+ "18250000\n",
+ "18500000\n",
+ "18750000\n",
+ "19000000\n",
+ "19250000\n",
+ "19500000\n",
+ "19750000\n"
+ ]
+ }
+ ],
+ "source": [
+ "algorithm.solver()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([108095.05, 108192.67, 108633.56, 108727.73, 108963.25, 109053.14,\n",
+ " 109496.51, 109582.56, 110098.32, 110180.11, 110880.8 , 110959.78,\n",
+ " 113413.03, 113487.45, 113706.34, 113776.33, 114005.3 , 114071.45,\n",
+ " 114259.2 , 114321.54, 114524.43, 114584.35, 114738.69, 114792.53,\n",
+ " 114918.66, 114968.5 , 115130.12, 115180.07, 115291.98, 115334.21,\n",
+ " 115448.83, 115486.97, 115579.82, 115615.23, 115674.22, 115704.44,\n",
+ " 115772.47, 115798.18, 116126.49, 116146.8 , 116074.55, 116090.76,\n",
+ " 116006.38, 116021.58, 115944.71, 115954.39, 115863.16, 115869.11,\n",
+ " 115785.82, 115787.28])"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "Qtable.Q_table[200, :, 0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.23619551122194513"
+ ]
+ },
+ "execution_count": 23,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "np.count_nonzero(Qtable.Q_table) / (number_actions * number_demands * total_stages)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "adversary_probabilities[10]=1 # We can test the Q-Table against any strategy. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "result = Test(game, Qtable, discount_factor, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "118943.0\n",
+ "73600.0\n",
+ "[118 130 110 105 105 101 107 99 99 99 102 99 104 96 105 100 101 101\n",
+ " 100 98 101 105 95 115 128]\n",
+ "[132 132 125 94 101 101 101 101 101 101 101 101 101 101 101 101 101 101\n",
+ " 101 101 101 101 101 101 135]\n",
+ "[200. 207. 208. 215. 209. 207. 207. 204. 205. 206. 207. 206. 207. 205.\n",
+ " 207. 205. 205. 205. 205. 205. 206. 206. 204. 207. 200.]\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Returns the optimal payoff and actions according to the Qtable\n",
+ "payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "print(payoff)\n",
+ "print(adversary_payoff)\n",
+ "print(actions)\n",
+ "print(adversary_actions)\n",
+ "print(demand_potential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "-0.1665207586460453"
+ ]
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# The percentage error of the Qtable. This has to be measured against the same opponent that \n",
+ "# it was trained against, as this is a measure of how 'complete' the training is.\n",
+ "result.error(10000)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The following calculates the payoff that the Q-Table gives against the different opponenets. \n",
+ "# It may reach a state in which the Q-Table was not trained. This will cause an error saying \n",
+ "# either 'max demand reached' or 'min demand reached'.\n",
+ "# for i in range(len(AdversaryModes)):\n",
+ "# print(AdversaryModes(i))\n",
+ "# adversaryProbs=[0]*len(AdversaryModes)\n",
+ "# adversaryProbs[i]=1\n",
+ "# result = Test(game, Qtable, discountFactor, adversaryProbs)\n",
+ "# payoff, advPayoff, actions, advActions, demandPotential = result.totalPayoff()\n",
+ "# print(payoff)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Episodic_learning/Qtable.py b/qLearning/Episodic_learning/Qtable.py
new file mode 100644
index 0000000..c8f4f8f
--- /dev/null
+++ b/qLearning/Episodic_learning/Qtable.py
@@ -0,0 +1,31 @@
+# Ed, Galit and Katerina
+# Relates to the Q-Learning approach.
+# Defines the Q-table
+
+import numpy as np
+
+class QTable():
+
+
+ def __init__(self, number_demands, number_actions, number_stages, learning_rate):
+
+ self.number_demands= number_demands
+ self.number_actions = number_actions
+ self.number_stages = number_stages
+ self.learning_rate = learning_rate
+ self.Q_table = np.zeros((self.number_demands, self.number_actions, self.number_stages))
+ self.QTable_name=f"QTable, actions={self.number_actions}, maximum demand={self.number_demands - 1}, stages={self.number_stages}"
+
+
+ def reset(self):
+ Qtable = np.zeros((self.number_demands, self.number_actions, self.number_stages))
+ return Qtable, self.learning_rate
+
+
+ def random_reset(self):
+ random_Qtable = np.random.rand(self.number_demands,self.number_actions, self.number_stages)
+ return random_Qtable, self.learning_rate
+
+
+
+
diff --git a/qLearning/Episodic_learning/Test_Qlearning.xlsx b/qLearning/Episodic_learning/Test_Qlearning.xlsx
new file mode 100644
index 0000000..4e5238b
Binary files /dev/null and b/qLearning/Episodic_learning/Test_Qlearning.xlsx differ
diff --git a/qLearning/Episodic_learning/__pycache__/Qtable.cpython-39.pyc b/qLearning/Episodic_learning/__pycache__/Qtable.cpython-39.pyc
new file mode 100644
index 0000000..e13d139
Binary files /dev/null and b/qLearning/Episodic_learning/__pycache__/Qtable.cpython-39.pyc differ
diff --git a/qLearning/Episodic_learning/__pycache__/environment.cpython-39.pyc b/qLearning/Episodic_learning/__pycache__/environment.cpython-39.pyc
new file mode 100644
index 0000000..daea220
Binary files /dev/null and b/qLearning/Episodic_learning/__pycache__/environment.cpython-39.pyc differ
diff --git a/qLearning/Episodic_learning/__pycache__/learningAgent.cpython-39.pyc b/qLearning/Episodic_learning/__pycache__/learningAgent.cpython-39.pyc
new file mode 100644
index 0000000..883f10e
Binary files /dev/null and b/qLearning/Episodic_learning/__pycache__/learningAgent.cpython-39.pyc differ
diff --git a/qLearning/Episodic_learning/__pycache__/test.cpython-39.pyc b/qLearning/Episodic_learning/__pycache__/test.cpython-39.pyc
new file mode 100644
index 0000000..81c9f03
Binary files /dev/null and b/qLearning/Episodic_learning/__pycache__/test.cpython-39.pyc differ
diff --git a/qLearning/Episodic_learning/environment.py b/qLearning/Episodic_learning/environment.py
new file mode 100644
index 0000000..bcb2b5f
--- /dev/null
+++ b/qLearning/Episodic_learning/environment.py
@@ -0,0 +1,260 @@
+# Katerina, Ed and Galit (and Tommy!)
+# Relates to the Q-Learning approach.
+# Contains DemandPotentialGame Class and the Model of the DemandPotentialGame Class.
+
+from enum import Enum
+import numpy as np # numerical python
+# printoptions: output limited to 2 digits after decimal point
+np.set_printoptions(precision=2, suppress=False)
+
+
+class DemandPotentialGame():
+ """
+ Fully defines Demand Potential Game. It contains game rules, memory and agents strategies.
+ """
+
+ def __init__(self, total_demand, costs, total_stages) -> None:
+ self.total_demand = total_demand
+ self.costs = costs
+ self.total_stages = total_stages
+ # first index is always player
+ self.demand_potential = None # two lists for the two players
+ self.prices = None # prices over T rounds
+ self.profit = None # profit in each of T rounds
+ self.stage = None
+
+ def reset_game(self):
+ """
+ Method resets game memory: Demand Potential, prices, profits
+ """
+ self.demand_potential = [[0]*(self.total_stages), [0]*(self.total_stages)] # two lists for the two players
+ self.prices = [[0]*self.total_stages, [0]*self.total_stages] # prices over T rounds
+ self.profit = [[0]*self.total_stages, [0]*self.total_stages] # profit in each of T rounds
+ self.demand_potential[0][0] = self.total_demand / 2 # initialise first round 0
+ self.demand_potential[1][0] = self.total_demand/2
+
+ def profits(self, player=0):
+ """
+ Computes profits. Player 0 is the learning agent.
+ """
+ return self.profit[player][self.stage]
+
+ def update_prices_profit_demand(self, price_pair):
+ """
+ Updates Prices, Profit and Demand Potential Memory.
+ Parameters.
+ price_pair: Pair of prices from the Learning agent and adversary.
+ """
+
+ for player in [0, 1]:
+ price = int(price_pair[player])
+ self.prices[player][self.stage] = price
+ self.profit[player][self.stage] = int((
+ self.demand_potential[player][self.stage] - price)*(price - self.costs[player]))
+ if self.stage < self.total_stages-1:
+ self.demand_potential[0][self.stage + 1] = \
+ int(self.demand_potential[0][self.stage] + (price_pair[1] - price_pair[0])/2)
+ self.demand_potential[1][self.stage + 1] = 400 - self.demand_potential[0][self.stage + 1]
+
+
+ def monopoly_price(self, player): # myopic monopoly price
+ """
+ Computes Monopoly prices.
+ """
+ return (self.demand_potential[player][self.stage] + self.costs[player])/2
+
+ def myopic(self, player=0):
+ """
+ Adversary follows Myopic strategy
+ """
+ return self.monopoly_price(player)
+
+ def const(self, player, price): # constant price strategy
+ """
+ Adversary follows Constant strategy
+ """
+ return price
+
+ def imit(self, player, firstprice): # price imitator strategy
+ if self.stage == 0:
+ return firstprice
+ return self.prices[1-player][self.stage-1]
+
+ def fight(self, player, firstprice): # simplified fighting strategy
+ if self.stage == 0:
+ return firstprice
+ if self.stage == self.total_stages-1:
+ return self.monopoly_price(player)
+ # aspire = [ 207, 193 ] # aspiration level for demand potential
+ aspire = [0, 0]
+ for i in range(2):
+ aspire[i] = (self.total_demand-self.costs[player] +
+ self.costs[1-player])/2
+
+ D = self.demand_potential[player][self.stage]
+ Asp = aspire[player]
+ if D >= Asp: # keep price; DANGER: price will never rise
+ return self.prices[player][self.stage-1]
+ # adjust to get to aspiration level using previous
+ # opponent price; own price has to be reduced by twice
+ # the negative amount D - Asp to getself.demand_potential to Asp
+ P = self.prices[1-player][self.stage-1] + 2*(D - Asp)
+ # never price to high because even 125 gives good profits
+ # P = min(P, 125)
+ aspire_price = (self.total_demand+self.costs[0]+self.costs[1])/4
+ P = min(P, int(0.95*aspire_price))
+
+ return P
+
+ def fight_lb(self, player, firstprice):
+ P = self.fight(player, firstprice)
+ # never price less than production cost
+ P = max(P, self.costs[player])
+ return P
+
+ # sophisticated fighting strategy, compare fight()
+ # estimate *sales* of opponent as their target, kept between
+ # calls in global variable oppsaleguess[]. Assumed behavior
+ # of opponent is similar to this strategy itself.
+ oppsaleguess = [61, 75] # first guess opponent sales as in monopoly
+
+ def guess(self, player, firstprice): # predictive fighting strategy
+ if self.stage == 0:
+ self.oppsaleguess[0] = 61 # always same start
+ self.oppsaleguess[1] = 75 # always same start
+ return firstprice
+
+ if self.stage == self.total_stages-1:
+ return self.monopoly_price(player)
+ aspire = [207, 193] # aspiration level
+ D = self.demand_potential[player][self.stage]
+ Asp = aspire[player]
+
+ if D >= Asp: # keep price, but go slightly towards monopoly if good
+ pmono = self.monopoly_price(player)
+ pcurrent = self.prices[player][self.stage-1]
+ if pcurrent > pmono: # shouldn't happen
+ return pmono
+ if pcurrent > pmono-7: # no change
+ return pcurrent
+ # current low price at 60%, be accommodating towards "collusion"
+ return .6 * pcurrent + .4 * (pmono-7)
+
+ # guess current *opponent price* from previous sales
+ prevsales = self.demand_potential[1 - player][t-1] - self.prices[1-player][t-1]
+ # adjust with weight alpha from previous guess
+ alpha = .5
+ newsalesguess = alpha * self.oppsaleguess[player] + (1-alpha)*prevsales
+ # update
+ self.oppsaleguess[player] = newsalesguess
+ guess_opponent_price = 400 - D - newsalesguess
+ P = guess_opponent_price + 2*(D - Asp)
+
+ if player == 0:
+ P = min(P, 125)
+ if player == 1:
+ P = min(P, 130)
+ return P
+
+
+class Model(DemandPotentialGame):
+ """
+ Defines the Problem's Model. It is assumed a Markov Decision Process is defined. The class is a Child from the Demand Potential Game Class.
+ The reason: Model is a conceptualization of the Game.
+ """
+
+ def __init__(self, total_demand, costs, total_stages, adversary_probabilities) -> None:
+ super().__init__(total_demand, costs, total_stages)
+
+ self.reward_function = self.profits
+
+ # [stage, agent's demand potential, adv previous action]
+ self.initial_state = [0, total_demand/2, 0]
+ self.episode_memory = list()
+ self.done = False
+ self.adversary_probabilities = adversary_probabilities
+
+ def reset(self):
+ """
+ Reset Model Instantiation.
+ """
+ reward = 0
+ self.stage = 0
+ self.done = False
+ self.reset_game()
+ self.reset_adversary()
+ return self.initial_state, reward, self.done
+
+ def reset_adversary(self):
+ options = list(range(len(self.adversary_probabilities)))
+ adversary_index = np.random.choice(options, 1, p= self.adversary_probabilities)
+ self.adversary_mode = AdversaryModes(adversary_index)
+
+ def adversary_choose_price(self):
+ """
+ Strategy followed by the adversary.
+ """
+
+ if self.adversary_mode == AdversaryModes.constant_132:
+ return self.const(player=1, price=132)
+ elif self.adversary_mode == AdversaryModes.constant_95:
+ return self.const(player=1, price=95)
+ elif self.adversary_mode == AdversaryModes.imitation_128:
+ return self.imit(player=1, firstprice=128)
+ elif self.adversary_mode == AdversaryModes.imitation_132:
+ return self.imit(player=1, firstprice=132)
+ elif self.adversary_mode == AdversaryModes.fight_100:
+ return self.fight(player=1, firstprice=100)
+ elif self.adversary_mode == AdversaryModes.fight_125:
+ return self.fight(player=1, firstprice=125)
+ elif self.adversary_mode == AdversaryModes.fight_lb_125:
+ return self.fight_lb(player=1, firstprice=125)
+ elif self.adversary_mode == AdversaryModes.fight_132:
+ return self.fight(player=1, firstprice=132)
+ elif self.adversary_mode == AdversaryModes.fight_lb_132:
+ return self.fight_lb(player=1, firstprice=132)
+ elif self.adversary_mode == AdversaryModes.guess_125:
+ return self.fight(player=1, firstprice=125)
+ elif self.adversary_mode == AdversaryModes.guess_132:
+ return self.fight(player=1, firstprice=132)
+ else:
+ return self.myopic(player=1)
+
+ def step(self, state, action):
+ """
+ Transition Function.
+ Parameters:
+ - action: Price
+ - state: tupple in the latest stage (stage ,Demand Potential, Adversary Action)
+ """
+ adversary_action = int(self.adversary_choose_price())
+ self.update_prices_profit_demand([action, adversary_action])
+
+
+ done = (self.stage == self.total_stages-1)
+
+
+ if not done:
+ new_state = [self.stage+1, self.demand_potential[0][self.stage + 1], adversary_action]
+ else:
+ new_state = [self.stage+1, 0, adversary_action]
+
+ reward = self.reward_function()
+ self.stage = self.stage + 1
+
+ return new_state, reward, done
+
+
+class AdversaryModes(Enum):
+ myopic = 0
+ constant_132 = 1
+ constant_95 = 2
+ imitation_132 = 3
+ imitation_128 = 4
+ fight_132 = 5
+ fight_lb_132 = 6
+ fight_125 = 7
+ fight_lb_125 = 8
+ fight_100 = 9
+ guess_132 = 10
+ guess_125 = 11
\ No newline at end of file
diff --git a/qLearning/Episodic_learning/learningAgent.py b/qLearning/Episodic_learning/learningAgent.py
new file mode 100644
index 0000000..76b3ce3
--- /dev/null
+++ b/qLearning/Episodic_learning/learningAgent.py
@@ -0,0 +1,95 @@
+# Ed, Kat, Galit
+# ReinforceAlgorithm Class: Solver.
+# Implement an off-policy Q-learning algorithm
+
+import numpy as np #repeated
+
+# printoptions: output limited to 2 digits after decimal point
+np.set_printoptions(precision=2, suppress=False)
+
+
+class LearningAlgorithm():
+ """
+ Model Solver.
+ """
+ def __init__(self, Model, Qtable, number_episodes, discount_factor) -> None:
+
+ self.env = Model
+ self.Qtable = Qtable.Q_table
+ self.learning_rate = Qtable.learning_rate
+ self.number_episodes = number_episodes
+ self.gamma = discount_factor
+ self.number_demands=Qtable.number_demands #Qtable dimen - number of states x number of actions x number of stages
+ self.number_stages=Qtable.number_stages
+ self.number_actions=Qtable.number_actions
+ self.highest_demand = int(self.number_demands - 1)
+
+
+ def reset_Qtable(self):
+ self.Qtable, self.learning_rate = self.Qtable.reset()
+
+
+ def action_index(self, monopoly_price, action): # computes action index in Qtable
+ return int(action - (monopoly_price - self.number_actions + 1)) #monopoly_price should have index number_actions - 1
+
+ def alpha_n(self, n): # defines the Qlearning rate
+ return self.learning_rate[0]/(n+self.learning_rate[1])
+
+ """
+ Now the Q-learning itself
+ """
+
+ def random_policy(self, monopoly_price):
+ random_action = np.random.randint(monopoly_price-self.number_actions+1, monopoly_price + 1)
+ if random_action < 0:
+ random_action = max(0, random_action)
+ if self.env.costs[0] > random_action:
+ random_action = monopoly_price
+ return random_action
+
+ def q_learning(self, state_action_value, optimal_next_value, reward, alpha, gamma):
+ target = reward + gamma * optimal_next_value
+ return state_action_value + alpha * (target - state_action_value)
+
+
+ def solver(self):
+
+ self.reset_Qtable
+ best_payoff = 0
+
+ for episode in range(self.number_episodes):
+ payoff = 0
+ if episode % 250_000 == 0:
+ print(episode)
+
+ state, reward, done = self.env.reset()
+ discount = 1
+ while not done:
+ stage, agent_demand, adversary_previous_action = state
+ if (agent_demand < 0) or (agent_demand > self.highest_demand):
+ break
+ if (stage > 0 and adversary_previous_action < self.env.costs[1]) or (self.highest_demand - agent_demand < adversary_previous_action):
+ break
+ monopoly_price = int((agent_demand + self.env.costs[0]) / 2)
+ action = self.random_policy(monopoly_price)
+ demand_index = int(agent_demand)
+ action_index = self.action_index(monopoly_price, action)
+ if episode % 1000 == 0:
+ action_index = np.argmax(self.Qtable[demand_index, :, stage])
+ action = action_index + int((agent_demand + self.env.costs[0])/2) - self.number_actions + 1
+ state, reward, done = self.env.step(state, action)
+ payoff += reward * discount
+ discount *= self.gamma
+
+ # updating the Qtable
+ if done:
+ optimal_next_value = 0
+ else:
+ optimal_next_value = max(self.Qtable[int(state[1]),:, state[0]])
+
+ current_q_value = self.Qtable[demand_index, action_index, stage]
+ self.Qtable[demand_index, action_index, stage] = self.q_learning(current_q_value, optimal_next_value, reward, self.alpha_n(episode), self.gamma)
+ if(payoff > best_payoff):
+ best_payoff = payoff
+ if episode == self.number_episodes - 1:
+ print(best_payoff)
diff --git a/qLearning/Episodic_learning/main.py b/qLearning/Episodic_learning/main.py
new file mode 100644
index 0000000..253448a
--- /dev/null
+++ b/qLearning/Episodic_learning/main.py
@@ -0,0 +1,67 @@
+from learningAgent import LearningAlgorithm
+from environment import Model, AdversaryModes
+import numpy as np
+
+np.random.seed(10)
+agent_cost = 57
+adv_cost = 71
+
+game = Model(totalDemand = 400,
+ tupleCosts = (agent_cost, adv_cost),
+ totalStages = 25,
+ initState = [400/2,0], adversaryMode=AdversaryModes.myopic)
+
+num_Actions = 50
+num_States = abs(adv_cost - agent_cost) + 2 * num_Actions + 2
+gamma = 0.99
+
+
+Qtable = np.zeros((num_States, num_Actions))
+Qtable_error = np.zeros((num_States, num_Actions))
+
+algorithm = LearningAlgorithm(game, Qtable, numberEpisodes = 10000, discountFactor = gamma)
+
+algorithm.solver()
+
+def bestAction(Qtable, state):
+ row = Qtable[int(state -(200-self.numStates/2))]
+ action = np.argmax(row) + (state + agent_cost)/2- num_Actions+1
+ return action
+
+
+
+
+# printing Qtable for excel
+for s in range(num_States):
+ for a in range(num_Actions):
+ print("%.5f, " % Qtable[s,a], end="")
+ print("")
+
+# Checking the convergence of the Qtable
+
+for s in range(num_States):
+ for a in range(num_Actions):
+ lowestState = int(200-(num_States)/2)
+ highestState = int(200+(num_States)/2 - 1)
+ state = s + lowestState
+
+ monopoly_price = int((state + agent_cost)/2) + 1
+ action = a + monopoly_price - num_Actions + 1
+
+ reward = (state - action) * (action - agent_cost)
+ adv_action = int((400 -state + adv_cost)/2) + 1
+ next_state = int(state + (adv_action - action)/2)
+ #print(state,monopoly_price,action,reward,adv_action, next_state)
+
+ ns = next_state - lowestState
+ opt_value_next = max(Qtable[ns])
+ new_value = (1-gamma)*reward + gamma * opt_value_next
+ Qtable_error[s,a] = (new_value - Qtable[s,a])/new_value
+
+# Printing Qtable error
+for s in range(num_States):
+ for a in range(num_Actions):
+ #print(Qtable[s,a],",", end="")
+ print("%.5f, " % Qtable_error[s,a], end="")
+ print("")
+
diff --git a/qLearning/Episodic_learning/qLearningSimulations.ipynb b/qLearning/Episodic_learning/qLearningSimulations.ipynb
new file mode 100644
index 0000000..a9b964a
--- /dev/null
+++ b/qLearning/Episodic_learning/qLearningSimulations.ipynb
@@ -0,0 +1,322 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_demand = 400\n",
+ "agent_cost = 57\n",
+ "adversary_cost = 71 \n",
+ "costs = [agent_cost,adversary_cost]\n",
+ "total_stages = 25\n",
+ "initial_state = [total_demand/2, total_demand/2]\n",
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "adversary_probabilities[10]=1 \n",
+ "game = Model(total_demand, costs, total_stages, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "number_actions = 50\n",
+ "number_demands = total_demand + 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+demoninator)\n",
+ "Qtable = QTable(number_demands, number_actions, total_stages , learning_rate = [1000000,1000000])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "number_episodes = 1_000_000\n",
+ "discount_factor = 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, number_episodes, discount_factor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0\n",
+ "250000\n",
+ "500000\n",
+ "750000\n",
+ "124696\n",
+ "124696\n",
+ "124696\n"
+ ]
+ }
+ ],
+ "source": [
+ "algorithm.solver()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([113911.83, 114009.83, 114142.18, 114228.91, 114705.89, 114795.89,\n",
+ " 114784.28, 114875.64, 115470.88, 115555.6 , 115793.71, 115871.71,\n",
+ " 116099.54, 116173.23, 116515.16, 116585.15, 116680.51, 116746.51,\n",
+ " 117124.79, 117186.79, 117251.72, 117251.93, 117368.36, 117438.03,\n",
+ " 117952.62, 118002.65, 117871.09, 117917.09, 117905.87, 117947.87,\n",
+ " 118067.29, 118086.84, 118379.51, 118413.51, 118214.4 , 118243.77,\n",
+ " 118520.11, 118546.11, 118767.77, 118790.73, 118630.41, 118648.54,\n",
+ " 118650.85, 118664.85, 118631.47, 118641.47, 118550.13, 118556.13,\n",
+ " 118541.42, 118543.41])"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "Qtable.Q_table[200, :, 0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.22556608478802992"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "np.count_nonzero(Qtable.Q_table) / (number_actions * number_demands * total_stages)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "adversary_probabilities[10]=1 # We can test the Q-Table against any strategy. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "result = Test(game, Qtable, discount_factor, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "99478.0\n",
+ "62067.0\n",
+ "[118 132 107 99 110 97 91 94 98 86 91 77 104 80 90 99 83 95\n",
+ " 85 93 84 95 94 112 122]\n",
+ "[132 132 132 83 91 91 91 91 91 91 91 91 91 91 91 91 91 91\n",
+ " 91 91 91 91 91 91 142]\n",
+ "[200. 207. 207. 219. 211. 201. 198. 198. 196. 192. 194. 194. 201. 194.\n",
+ " 199. 199. 195. 199. 197. 200. 199. 202. 200. 198. 187.]\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Returns the optimal payoff and actions according to the Qtable\n",
+ "payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "print(payoff)\n",
+ "print(adversary_payoff)\n",
+ "print(actions)\n",
+ "print(adversary_actions)\n",
+ "print(demand_potential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n",
+ "Div by zero error\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "-0.13327514527667506"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# The percentage error of the Qtable. This has to be measured against the same opponent that \n",
+ "# it was trained against, as this is a measure of how 'complete' the training is.\n",
+ "result.error(10000)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The following calculates the payoff that the Q-Table gives against the different opponenets. \n",
+ "# It may reach a state in which the Q-Table was not trained. This will cause an error saying \n",
+ "# either 'max demand reached' or 'min demand reached'.\n",
+ "# for i in range(len(AdversaryModes)):\n",
+ "# print(AdversaryModes(i))\n",
+ "# adversaryProbs=[0]*len(AdversaryModes)\n",
+ "# adversaryProbs[i]=1\n",
+ "# result = Test(game, Qtable, discountFactor, adversaryProbs)\n",
+ "# payoff, advPayoff, actions, advActions, demandPotential = result.totalPayoff()\n",
+ "# print(payoff)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Episodic_learning/test.py b/qLearning/Episodic_learning/test.py
new file mode 100644
index 0000000..62042e9
--- /dev/null
+++ b/qLearning/Episodic_learning/test.py
@@ -0,0 +1,146 @@
+# Ed, Galit and Katerina
+# Relates to the Q-Learning approach.
+# Testing out the Q-table against a given opponent
+
+import numpy as np
+from environment import AdversaryModes
+
+
+class Test():
+
+
+ def __init__(self, Model, Qtable, discount_factor, adversary_probabilities) -> None:
+
+
+ self.env = Model
+ self.Qtable = Qtable.Q_table
+ self.number_demands=Qtable.number_demands
+ self.number_actions=Qtable.number_actions
+ self.number_stages=Qtable.number_stages
+ self.discount_factor = discount_factor
+ self.adversary_probabilities = adversary_probabilities
+ self.adversary = None
+
+
+
+ def set_adversary(self):
+ options = list(range(len(self.adversary_probabilities)))
+ adversary_index = int(np.random.choice(options, 1, p= self.adversary_probabilities))
+ self.adversary = AdversaryModes(adversary_index)
+ new_probabilities = [0]*len(self.adversary_probabilities)
+ new_probabilities[adversary_index] = 1
+ self.env.adversary_probabilities = new_probabilities
+
+
+ def total_payoff(self):
+
+ self.set_adversary()
+
+ delta = 1
+ utility = 0
+ adversary_utility = 0
+ actions = [0]*self.number_stages
+ adversary_actions = [0]*self.number_stages
+ demands = [0]*self.number_stages
+ state_vector, reward, done = self.env.reset()
+ demand = state_vector[1]
+
+ for stage in range(self.number_stages):
+ demands[stage] = demand
+ if demand >= self.number_demands:
+ print("max demand reached")
+ demand = self.number_demands - 1
+ if demand < 0:
+ print("min demand reached")
+ demand = 0
+ demand_index = int(demand)
+ action_index = np.argmax(self.Qtable[demand_index, :, stage])
+ action = action_index + int((demand + self.env.costs[0])/2) - self.number_actions + 1
+ actions[stage] = action
+ utility += (demand-action)*(action-self.env.costs[0]) * delta
+ adversary_demand = 400 - demand
+ state_vector, _, _ = self.env.step(state_vector, action)
+ demand = state_vector[1]
+ adversary_actions[stage] = state_vector[2]
+ adversary_utility += (adversary_demand-adversary_actions[stage])*(adversary_actions[stage]-self.env.costs[1]) * delta
+ delta *= self.discount_factor
+ return utility, adversary_utility, np.transpose(actions), np.transpose(adversary_actions), np.transpose(demands)
+
+
+ def q_learning(self, state_action_value, optimal_next_value, reward, alpha, gamma):
+ target = reward + gamma * optimal_next_value
+ return state_action_value + alpha * (target - state_action_value)
+
+ def error(self, number_tests):
+
+ self.set_adversary()
+
+ errors = np.zeros(number_tests)
+
+ for test in range(number_tests):
+ state, reward, done = self.env.reset()
+ stage, demand, _ = state
+
+
+ while not done:
+ if demand >= self.number_demands:
+ print("max demand reached")
+ demand = self.number_demands - 1
+ if demand < 0:
+ print("min demand reached")
+ demand = 0
+ demand_index = int(demand)
+ action_index = np.random.randint(0, self.number_actions)
+ action = action_index + int((demand + self.env.costs[0])/2) - self.number_actions + 1
+ state, reward, done = self.env.step(state, action)
+ stage, demand, _ = state
+
+ if done:
+ optimal_next_value = 0
+ else:
+ optimal_next_value = max(self.Qtable[demand,:, stage])
+
+ new_value = reward + self.discount_factor * optimal_next_value
+ if new_value != 0:
+ errors[test] += (new_value - self.Qtable[demand_index, action_index, stage-1])/new_value
+ if new_value == 0 and self.Qtable[demand_index,action_index, stage-1] != 0:
+ print("Div by zero error") # This should not occur
+ return errors.mean()/self.number_stages
+
+
+
+
+ def myopic(self, cost, demand):
+ return (cost + demand)/2
+
+ def payoff(self, cost, demand, price):
+ return (demand - price)*(price - cost)
+
+ def update_demand(self, demand, price_pair):
+ new_demand = demand + 0.5*(price_pair[1]- price_pair[0])
+ return new_demand
+
+ def utility_of_actions(self, actions):
+ agent_demand = 200
+ opponent_demand = 200
+ total_payoff = 0
+ delta = 1/self.discount_factor
+ for i in range(self.number_stages):
+ delta = delta * self.discount_factor
+ agent_price = int(actions[i])
+ opponent_price = int(self.myopic(self.env.costs[1],opponent_demand))
+ total_payoff += self.payoff(self.env.costs[0],agent_demand,agent_price) * delta
+ agent_demand = int(self.update_demand(agent_demand, [agent_price,opponent_price]))
+ opponent_demand = 400 - agent_demand
+ return total_payoff
+
+
+
+
+
+
+
+
+
+
+
diff --git a/qLearning/Episodic_learning_with_memory/.DS_Store b/qLearning/Episodic_learning_with_memory/.DS_Store
new file mode 100644
index 0000000..d8aabcd
Binary files /dev/null and b/qLearning/Episodic_learning_with_memory/.DS_Store differ
diff --git a/qLearning/Episodic_learning_with_memory/.idea/.gitignore b/qLearning/Episodic_learning_with_memory/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/qLearning/Episodic_learning_with_memory/.idea/Episodic_learning_with_memory.iml b/qLearning/Episodic_learning_with_memory/.idea/Episodic_learning_with_memory.iml
new file mode 100644
index 0000000..949c352
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/.idea/Episodic_learning_with_memory.iml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/qLearning/Episodic_learning_with_memory/.idea/inspectionProfiles/profiles_settings.xml b/qLearning/Episodic_learning_with_memory/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/qLearning/Episodic_learning_with_memory/.idea/misc.xml b/qLearning/Episodic_learning_with_memory/.idea/misc.xml
new file mode 100644
index 0000000..a971a2c
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/qLearning/Episodic_learning_with_memory/.idea/modules.xml b/qLearning/Episodic_learning_with_memory/.idea/modules.xml
new file mode 100644
index 0000000..868e0fb
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/qLearning/Episodic_learning_with_memory/.idea/other.xml b/qLearning/Episodic_learning_with_memory/.idea/other.xml
new file mode 100644
index 0000000..640fd80
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/.idea/other.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/qLearning/Episodic_learning_with_memory/.idea/vcs.xml b/qLearning/Episodic_learning_with_memory/.idea/vcs.xml
new file mode 100644
index 0000000..b2bdec2
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/qLearning/Episodic_learning_with_memory/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb b/qLearning/Episodic_learning_with_memory/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
new file mode 100644
index 0000000..fe88e90
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
@@ -0,0 +1,476 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "import pandas as pd"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(11)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_demand = 400\n",
+ "agent_cost = 57\n",
+ "adversary_cost = 71 \n",
+ "costs = [agent_cost,adversary_cost]\n",
+ "total_stages = 25\n",
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Below is where we decide what adversaries we train against- see environment.py for the numbers\n",
+ "# Replace * and ** with the two number associated with the opponents at the bottom of environment.py\n",
+ "adversary_probabilities[10] = 0.5\n",
+ "adversary_probabilities[11] = 0.5\n",
+ "game = Model(total_demand, costs, total_stages, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2040816\n"
+ ]
+ }
+ ],
+ "source": [
+ "number_actions = 50\n",
+ "number_demands = total_demand + 1\n",
+ "discount_factor = 1\n",
+ "number_episodes = 100_000_000\n",
+ "constant = int(number_episodes/49)\n",
+ "print(constant)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+denominator)\n",
+ "Qtable = QTable(number_demands, number_actions, total_stages , learning_rate = [constant,constant])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, number_episodes, discount_factor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0 0.594349701531621\n",
+ "Current payoff for adversary 1: 34687.0\n",
+ "Current payoff for adversary 2: 79941.0\n",
+ "Current payoff for adversary 1: 73981.0\n",
+ "Current payoff for adversary 2: 70645.0\n",
+ "Current payoff for adversary 1: 78665.0\n",
+ "Current payoff for adversary 2: 101521.0\n",
+ "Current payoff for adversary 1: 98645.0\n",
+ "Current payoff for adversary 2: 83760.0\n",
+ "Current payoff for adversary 1: 99592.0\n",
+ "Current payoff for adversary 2: 84035.0\n",
+ "Current payoff for adversary 1: 92889.0\n",
+ "Current payoff for adversary 2: 91975.0\n",
+ "Current payoff for adversary 1: 82468.0\n",
+ "Current payoff for adversary 2: 81975.0\n",
+ "Current payoff for adversary 1: 92860.0\n",
+ "Current payoff for adversary 2: 98432.0\n",
+ "Current payoff for adversary 1: 85632.0\n",
+ "Current payoff for adversary 2: 97482.0\n",
+ "Current payoff for adversary 1: 96170.0\n",
+ "Current payoff for adversary 2: 99178.0\n",
+ "Current payoff for adversary 1: 98218.0\n",
+ "Current payoff for adversary 2: 92285.0\n",
+ "Current payoff for adversary 1: 98634.0\n",
+ "Current payoff for adversary 2: 96046.0\n",
+ "Current payoff for adversary 1: 95566.0\n",
+ "Current payoff for adversary 2: 68512.0\n",
+ "Current payoff for adversary 1: 100080.0\n",
+ "Current payoff for adversary 2: 105736.0\n",
+ "Current payoff for adversary 1: 95810.0\n",
+ "Current payoff for adversary 2: 64602.0\n",
+ "Current payoff for adversary 1: 111108.0\n",
+ "Current payoff for adversary 2: 85837.0\n",
+ "Current payoff for adversary 1: 92963.0\n",
+ "Current payoff for adversary 2: 94590.0\n",
+ "Current payoff for adversary 1: 90542.0\n",
+ "Current payoff for adversary 2: 94991.0\n",
+ "Current payoff for adversary 1: 91372.0\n",
+ "Current payoff for adversary 2: 98799.0\n",
+ "Current payoff for adversary 1: 100601.0\n",
+ "Current payoff for adversary 2: 102214.0\n",
+ "Current payoff for adversary 1: 101872.0\n",
+ "Current payoff for adversary 2: 105037.0\n",
+ "Current payoff for adversary 1: 107001.0\n",
+ "Current payoff for adversary 2: 94888.0\n",
+ "Current payoff for adversary 1: 111568.0\n",
+ "Current payoff for adversary 2: 96090.0\n",
+ "Current payoff for adversary 1: 87229.0\n",
+ "Current payoff for adversary 2: 77804.0\n",
+ "Current payoff for adversary 1: 90002.0\n",
+ "Current payoff for adversary 2: 71446.0\n",
+ "Current payoff for adversary 1: 91612.0\n",
+ "Current payoff for adversary 2: 88551.0\n",
+ "Current payoff for adversary 1: 79085.0\n",
+ "Current payoff for adversary 2: 97288.0\n",
+ "Current payoff for adversary 1: 93384.0\n",
+ "Current payoff for adversary 2: 81910.0\n",
+ "Current payoff for adversary 1: 113506.0\n",
+ "Current payoff for adversary 2: 97466.0\n",
+ "Current payoff for adversary 1: 59204.0\n",
+ "Current payoff for adversary 2: 106316.0\n",
+ "Current payoff for adversary 1: 89503.0\n",
+ "Current payoff for adversary 2: 104954.0\n",
+ "Current payoff for adversary 1: 84989.0\n",
+ "Current payoff for adversary 2: 105401.0\n",
+ "Current payoff for adversary 1: 98121.0\n",
+ "Current payoff for adversary 2: 88237.0\n",
+ "Current payoff for adversary 1: 112002.0\n",
+ "Current payoff for adversary 2: 106707.0\n",
+ "Current payoff for adversary 1: 99953.0\n",
+ "Current payoff for adversary 2: 106348.0\n",
+ "Current payoff for adversary 1: 80622.0\n",
+ "Current payoff for adversary 2: 88378.0\n",
+ "Current payoff for adversary 1: 91324.0\n",
+ "Current payoff for adversary 2: 100303.0\n",
+ "Current payoff for adversary 1: 109847.0\n",
+ "Current payoff for adversary 2: 100312.0\n",
+ "Current payoff for adversary 1: 109847.0\n",
+ "Current payoff for adversary 2: 99063.0\n",
+ "Current payoff for adversary 1: 102574.0\n",
+ "Current payoff for adversary 2: 100620.0\n",
+ "Current payoff for adversary 1: 104237.0\n",
+ "Current payoff for adversary 2: 99054.0\n",
+ "Current payoff for adversary 1: 85100.0\n",
+ "Current payoff for adversary 2: 100340.0\n",
+ "Current payoff for adversary 1: 85912.0\n",
+ "Current payoff for adversary 2: 99218.0\n",
+ "Current payoff for adversary 1: 96432.0\n",
+ "Current payoff for adversary 2: 101575.0\n",
+ "Current payoff for adversary 1: 83770.0\n",
+ "Current payoff for adversary 2: 100141.0\n",
+ "Current payoff for adversary 1: 114494.0\n",
+ "Current payoff for adversary 2: 101752.0\n",
+ "Current payoff for adversary 1: 84009.0\n",
+ "Current payoff for adversary 2: 99816.0\n",
+ "Current payoff for adversary 1: 98744.0\n",
+ "Current payoff for adversary 2: 94135.0\n",
+ "Current payoff for adversary 1: 99763.0\n",
+ "Current payoff for adversary 2: 94845.0\n",
+ "Current payoff for adversary 1: 105391.0\n",
+ "Current payoff for adversary 2: 95373.0\n",
+ "50 0.0084000959568777\n",
+ "Current payoff for adversary 1: 84719.0\n",
+ "Current payoff for adversary 2: 94776.0\n",
+ "Current payoff for adversary 1: 107171.0\n",
+ "Current payoff for adversary 2: 96068.0\n",
+ "Current payoff for adversary 1: 99437.0\n",
+ "Current payoff for adversary 2: 95768.0\n",
+ "Current payoff for adversary 1: 104199.0\n",
+ "Current payoff for adversary 2: 110675.0\n",
+ "Current payoff for adversary 1: 98113.0\n",
+ "Current payoff for adversary 2: 93863.0\n",
+ "Current payoff for adversary 1: 116006.0\n",
+ "Current payoff for adversary 2: 109634.0\n",
+ "Current payoff for adversary 1: 84889.0\n",
+ "Current payoff for adversary 2: 110741.0\n",
+ "57\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "[]"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# Below is the first stage of learning- actions are chosen randomly.\n",
+ "number_episodes_per_round = 100_000\n",
+ "number_rounds = int(number_episodes / number_episodes_per_round)\n",
+ "errors = np.zeros(number_rounds)\n",
+ "final_round = 0\n",
+ "opponent1_results = list()\n",
+ "opponent2_results = list()\n",
+ "for round_ in range(number_rounds):\n",
+ " algorithm.continue_learning(number_episodes_per_round,number_episodes_per_round * round_ +1)\n",
+ " adversary_probabilities[10] = 0.5\n",
+ " adversary_probabilities[11] = 0.5\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " errors[round_] = result.error(1000)\n",
+ " if round_ % 50 == 0:\n",
+ " print(round_, errors[round_])\n",
+ " if round_ > 10 and np.max(errors[round_-10:round_]) < 0.01:\n",
+ " print(round_)\n",
+ " final_round = round_\n",
+ " break\n",
+ " \n",
+ " adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " adversary_probabilities[10] = 1\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " payoff1, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " opponent1_results.append(payoff1)\n",
+ " print('Current payoff for adversary 1: ', payoff1)\n",
+ " \n",
+ " adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " adversary_probabilities[11] = 1\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " payoff2, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " opponent2_results.append(payoff2)\n",
+ " print('Current payoff for adversary 2: ', payoff2)\n",
+ " \n",
+ " if (round_ == number_rounds - 1):\n",
+ " final_round = round_\n",
+ " \n",
+ "plt.plot(errors[0:final_round+1])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Round 0 of 188\n",
+ "Best payoff: 129293\n",
+ "Best actions: [118, 132, 126, 123, 116, 113, 120, 104, 108, 118, 102, 116, 108, 106, 118, 106, 106, 114, 109, 114, 104, 112, 113, 116, 125]\n",
+ "Current payoff for adversary 1: 126020.0\n",
+ "Current payoff for adversary 2: 116447.0\n",
+ "Round 1 of 188\n",
+ "Best payoff: 130778\n",
+ "Best actions: [113, 122, 125, 125, 124, 129, 116, 116, 111, 111, 114, 112, 120, 106, 112, 112, 112, 112, 114, 107, 111, 116, 111, 114, 130]\n",
+ "Current payoff for adversary 1: 80594.0\n",
+ "Current payoff for adversary 2: 129385.0\n",
+ "Round 2 of 188\n",
+ "Best payoff: 132640\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 122, 117, 119, 113, 111, 115, 113, 112, 111, 112, 117, 111, 113, 114, 111, 112, 116, 113, 130]\n",
+ "Current payoff for adversary 1: 80294.0\n",
+ "Current payoff for adversary 2: 132503.0\n",
+ "Round 3 of 188\n",
+ "Best payoff: 133019\n",
+ "Best actions: [111, 124, 124, 125, 124, 124, 123, 118, 115, 115, 113, 115, 111, 115, 111, 112, 114, 111, 114, 110, 114, 112, 116, 115, 130]\n",
+ "Current payoff for adversary 1: 92906.0\n",
+ "Current payoff for adversary 2: 131876.0\n",
+ "Round 4 of 188\n",
+ "Best payoff: 133293\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 124, 128, 116, 113, 114, 108, 111, 111, 110, 113, 109, 111, 113, 109, 111, 111, 132]\n",
+ "Current payoff for adversary 1: 74975.0\n",
+ "Current payoff for adversary 2: 133196.0\n",
+ "Round 5 of 188\n",
+ "Best payoff: 134193\n",
+ "Best actions: [111, 125, 125, 125, 124, 124, 126, 123, 125, 127, 119, 117, 118, 116, 115, 115, 113, 115, 119, 113, 114, 112, 110, 112, 131]\n",
+ "Current payoff for adversary 1: 100995.0\n",
+ "Current payoff for adversary 2: 133716.0\n",
+ "Round 6 of 188\n",
+ "Best payoff: 134790\n",
+ "Best actions: [111, 124, 125, 125, 125, 125, 125, 125, 125, 125, 129, 118, 121, 112, 119, 116, 114, 116, 119, 113, 114, 118, 115, 112, 132]\n",
+ "Current payoff for adversary 1: 103036.0\n",
+ "Current payoff for adversary 2: 134353.0\n",
+ "Round 7 of 188\n",
+ "Best payoff: 135517\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 127, 122, 121, 120, 122, 117, 115, 115, 120, 110, 116, 122, 111, 106, 128]\n",
+ "Current payoff for adversary 1: 95979.0\n",
+ "Current payoff for adversary 2: 135481.0\n",
+ "Round 8 of 188\n",
+ "Best payoff: 135764\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 124, 127, 118, 118, 113, 113, 114, 114, 116, 114, 112, 114, 116, 131]\n",
+ "Current payoff for adversary 1: 76657.0\n",
+ "Current payoff for adversary 2: 135496.0\n",
+ "Round 9 of 188\n",
+ "Best payoff: 135920\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 124, 118, 116, 115, 116, 112, 114, 116, 112, 113, 114, 116, 131]\n",
+ "Current payoff for adversary 1: 93320.0\n",
+ "Current payoff for adversary 2: 135886.0\n",
+ "Round 10 of 188\n",
+ "Best payoff: 135983\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 124, 118, 116, 115, 114, 114, 114, 116, 112, 113, 114, 116, 131]\n",
+ "Current payoff for adversary 1: 75385.0\n",
+ "Current payoff for adversary 2: 135854.0\n",
+ "Round 11 of 188\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Below is the second stage of learning- actions are chosen according to an epsilon greedy strategy.\n",
+ "episode_counter = (final_round + 1) * number_episodes_per_round\n",
+ "episodes_left = number_episodes - episode_counter\n",
+ "number_episodes_per_round = 500_000\n",
+ "number_rounds = int(episodes_left / number_episodes_per_round)\n",
+ "\n",
+ "for round_ in range(number_rounds): \n",
+ " print('Round ', round_, ' of ', number_rounds)\n",
+ " algorithm.epsilon_greedy_learning(number_episodes_per_round, episode_counter)\n",
+ " \n",
+ " adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " adversary_probabilities[10] = 1\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " payoff1, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " opponent1_results.append(payoff1)\n",
+ " print('Current payoff for adversary 1: ', payoff1)\n",
+ " \n",
+ " adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " adversary_probabilities[11] = 1\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " payoff2, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " opponent2_results.append(payoff2)\n",
+ " print('Current payoff for adversary 2: ', payoff2)\n",
+ " \n",
+ " episode_counter += number_episodes_per_round\n",
+ " \n",
+ "plt.plot(opponent1_results)\n",
+ "plt.plot(opponent2_results)\n",
+ "plt.title(\"Payoff over the rounds\")\n",
+ "plt.xlabel(\"Rounds\")\n",
+ "plt.ylabel(\"Payoff at the end of each round\")\n",
+ "legend = [\"adversary 1\", \"adversary 2\"]\n",
+ "plt.legend(legend)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Qtable.save(\"Qtable_guess132_guess128\")\n",
+ "\n",
+ "df1 = pd.DataFrame(opponent1_results)\n",
+ "df2 = pd.DataFrame(opponent2_results)\n",
+ "\n",
+ "writer = pd.ExcelWriter('payoffs.xlsx', engine='xlsxwriter')\n",
+ "df1.to_excel(writer, sheet_name='payoff1', index=False)\n",
+ "df2.to_excel(writer, sheet_name='payoff2', index=False)\n",
+ "writer.save()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# We now have the trained agent. We want to test it against each opponent individually, so that\n",
+ "# we can compare it against the agent that is just trained against this opponent. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Testing against one type of opponent by changing the * below to be the first number\n",
+ "adversary_probabilities[10] = 1\n",
+ "result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ "payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "print(payoff)\n",
+ "print(adversary_payoff)\n",
+ "print(actions)\n",
+ "print(adversary_actions)\n",
+ "print(demand_potential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Testing against one type of opponent by changing the * below to be the first number\n",
+ "adversary_probabilities[11] = 1\n",
+ "result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ "payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "print(payoff)\n",
+ "print(adversary_payoff)\n",
+ "print(actions)\n",
+ "print(adversary_actions)\n",
+ "print(demand_potential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.7"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Episodic_learning_with_memory/.ipynb_checkpoints/qLearningSimulations-oneAdversary-checkpoint.ipynb b/qLearning/Episodic_learning_with_memory/.ipynb_checkpoints/qLearningSimulations-oneAdversary-checkpoint.ipynb
new file mode 100644
index 0000000..11e556b
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/.ipynb_checkpoints/qLearningSimulations-oneAdversary-checkpoint.ipynb
@@ -0,0 +1,427 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "import pandas as pd"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(11)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_demand = 400\n",
+ "agent_cost = 57\n",
+ "adversary_cost = 71 \n",
+ "costs = [agent_cost,adversary_cost]\n",
+ "total_stages = 25\n",
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Below is where we decide what adversaries we train against- see environment.py for the numbers\n",
+ "# Replace * and ** with the two number associated with the opponents at the bottom of environment.py\n",
+ "# adversary_probabilities[10]= 0.5\n",
+ "adversary_probabilities[10] = 1\n",
+ "game = Model(total_demand, costs, total_stages, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2040816\n"
+ ]
+ }
+ ],
+ "source": [
+ "number_actions = 50\n",
+ "number_demands = total_demand + 1\n",
+ "discount_factor = 1\n",
+ "number_episodes = 100_000_000\n",
+ "constant = int(number_episodes/49)\n",
+ "print(constant)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+denominator)\n",
+ "Qtable = QTable(number_demands, number_actions, total_stages , learning_rate = [constant,constant])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, number_episodes, discount_factor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0 0.5897715369319796\n",
+ "Current payoff for adversary 1: 80171.0\n",
+ "Current payoff for adversary 1: 88691.0\n",
+ "Current payoff for adversary 1: 95241.0\n",
+ "Current payoff for adversary 1: 91616.0\n",
+ "Current payoff for adversary 1: 105628.0\n",
+ "Current payoff for adversary 1: 62523.0\n",
+ "Current payoff for adversary 1: 105138.0\n",
+ "Current payoff for adversary 1: 78727.0\n",
+ "Current payoff for adversary 1: 85785.0\n",
+ "Current payoff for adversary 1: 86745.0\n",
+ "Current payoff for adversary 1: 93727.0\n",
+ "Current payoff for adversary 1: 104096.0\n",
+ "Current payoff for adversary 1: 105856.0\n",
+ "Current payoff for adversary 1: 96217.0\n",
+ "Current payoff for adversary 1: 97545.0\n",
+ "Current payoff for adversary 1: 95933.0\n",
+ "Current payoff for adversary 1: 93805.0\n",
+ "Current payoff for adversary 1: 105549.0\n",
+ "Current payoff for adversary 1: 88906.0\n",
+ "Current payoff for adversary 1: 107502.0\n",
+ "Current payoff for adversary 1: 108536.0\n",
+ "Current payoff for adversary 1: 108047.0\n",
+ "Current payoff for adversary 1: 107102.0\n",
+ "Current payoff for adversary 1: 94372.0\n",
+ "Current payoff for adversary 1: 84036.0\n",
+ "Current payoff for adversary 1: 96009.0\n",
+ "Current payoff for adversary 1: 96923.0\n",
+ "Current payoff for adversary 1: 96544.0\n",
+ "Current payoff for adversary 1: 98038.0\n",
+ "Current payoff for adversary 1: 98316.0\n",
+ "Current payoff for adversary 1: 102918.0\n",
+ "Current payoff for adversary 1: 103174.0\n",
+ "Current payoff for adversary 1: 97146.0\n",
+ "Current payoff for adversary 1: 101444.0\n",
+ "Current payoff for adversary 1: 107079.0\n",
+ "Current payoff for adversary 1: 107258.0\n",
+ "Current payoff for adversary 1: 108273.0\n",
+ "Current payoff for adversary 1: 108879.0\n",
+ "Current payoff for adversary 1: 108815.0\n",
+ "Current payoff for adversary 1: 89023.0\n",
+ "Current payoff for adversary 1: 108685.0\n",
+ "Current payoff for adversary 1: 109782.0\n",
+ "Current payoff for adversary 1: 109246.0\n",
+ "Current payoff for adversary 1: 107501.0\n",
+ "Current payoff for adversary 1: 108430.0\n",
+ "Current payoff for adversary 1: 88807.0\n",
+ "Current payoff for adversary 1: 89579.0\n",
+ "Current payoff for adversary 1: 89104.0\n",
+ "Current payoff for adversary 1: 89185.0\n",
+ "Current payoff for adversary 1: 90581.0\n",
+ "50 0.014010674672339848\n",
+ "Current payoff for adversary 1: 91426.0\n",
+ "Current payoff for adversary 1: 92414.0\n",
+ "Current payoff for adversary 1: 89640.0\n",
+ "Current payoff for adversary 1: 105000.0\n",
+ "Current payoff for adversary 1: 104323.0\n",
+ "Current payoff for adversary 1: 104980.0\n",
+ "Current payoff for adversary 1: 111710.0\n",
+ "Current payoff for adversary 1: 95604.0\n",
+ "Current payoff for adversary 1: 96814.0\n",
+ "Current payoff for adversary 1: 108008.0\n",
+ "Current payoff for adversary 1: 115804.0\n",
+ "Current payoff for adversary 1: 105631.0\n",
+ "Current payoff for adversary 1: 104537.0\n",
+ "Current payoff for adversary 1: 105038.0\n",
+ "Current payoff for adversary 1: 104903.0\n",
+ "Current payoff for adversary 1: 113073.0\n",
+ "Current payoff for adversary 1: 113678.0\n",
+ "Current payoff for adversary 1: 113678.0\n",
+ "Current payoff for adversary 1: 104090.0\n",
+ "Current payoff for adversary 1: 104346.0\n",
+ "Current payoff for adversary 1: 113801.0\n",
+ "Current payoff for adversary 1: 113801.0\n",
+ "72\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "[]"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# Below is the first stage of learning- actions are chosen randomly.\n",
+ "number_episodes_per_round = 100_000\n",
+ "number_rounds = int(number_episodes / number_episodes_per_round)\n",
+ "errors = np.zeros(number_rounds)\n",
+ "final_round = 0\n",
+ "opponent1_results = list()\n",
+ "#opponent2_results = list()\n",
+ "for round_ in range(number_rounds):\n",
+ " algorithm.continue_learning(number_episodes_per_round,number_episodes_per_round * round_ +1)\n",
+ " adversary_probabilities[10]= 1\n",
+ " # adversary_probabilities[11] = 0.5\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " errors[round_] = result.error(1000)\n",
+ " if round_ % 50 == 0:\n",
+ " print(round_, errors[round_])\n",
+ " if round_ > 10 and np.max(errors[round_-10:round_]) < 0.01:\n",
+ " print(round_)\n",
+ " final_round = round_\n",
+ " break\n",
+ " \n",
+ " adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " adversary_probabilities[10]=1\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " payoff1, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " opponent1_results.append(payoff1)\n",
+ " print('Current payoff for adversary 1: ', payoff1)\n",
+ " \n",
+ " # adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " # adversary_probabilities[11]=1\n",
+ " # result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " # payoff2, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " # opponent2_results.append(payoff2)\n",
+ " # print('Current payoff for adversary 2: ', payoff2)\n",
+ " \n",
+ " if (round_ == number_rounds - 1):\n",
+ " final_round = round_\n",
+ " \n",
+ "plt.plot(errors[0:final_round+1])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Round 0 of 185\n",
+ "Best payoff: 127495\n",
+ "Best actions: [121, 128, 125, 123, 122, 114, 115, 106, 112, 109, 108, 107, 102, 114, 101, 113, 104, 109, 107, 107, 110, 105, 105, 112, 130]\n",
+ "Current payoff for adversary 1: 118224.0\n",
+ "Round 1 of 185\n",
+ "Best payoff: 130757\n",
+ "Best actions: [121, 128, 132, 124, 120, 116, 113, 113, 111, 110, 117, 105, 111, 110, 117, 109, 115, 107, 109, 109, 116, 109, 111, 115, 130]\n",
+ "Current payoff for adversary 1: 130519.0\n",
+ "Round 2 of 185\n",
+ "Best payoff: 133134\n",
+ "Best actions: [118, 131, 132, 128, 122, 119, 116, 116, 114, 114, 113, 114, 113, 115, 112, 117, 117, 109, 114, 115, 114, 108, 114, 111, 131]\n",
+ "Current payoff for adversary 1: 132139.0\n",
+ "Round 3 of 185\n",
+ "Best payoff: 133675\n",
+ "Best actions: [118, 131, 132, 128, 128, 123, 119, 119, 114, 114, 116, 112, 114, 114, 116, 116, 115, 119, 109, 119, 114, 108, 114, 108, 133]\n",
+ "Current payoff for adversary 1: 132684.0\n",
+ "Round 4 of 185\n",
+ "Best payoff: 134211\n",
+ "Best actions: [117, 131, 132, 131, 124, 122, 120, 117, 117, 115, 117, 115, 115, 113, 117, 115, 115, 123, 107, 116, 111, 116, 113, 108, 133]\n",
+ "Current payoff for adversary 1: 133626.0\n",
+ "Round 5 of 185\n",
+ "Best payoff: 135075\n",
+ "Best actions: [118, 132, 132, 131, 132, 132, 126, 126, 118, 118, 118, 113, 115, 117, 114, 121, 113, 112, 116, 122, 112, 115, 113, 123, 130]\n",
+ "Current payoff for adversary 1: 134911.0\n",
+ "Round 6 of 185\n",
+ "Best payoff: 135187\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 122, 122, 116, 116, 114, 114, 114, 114, 114, 114, 113, 116, 114, 114, 112, 114, 108, 133]\n",
+ "Current payoff for adversary 1: 134357.0\n",
+ "Round 7 of 185\n",
+ "Best payoff: 135849\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 128, 124, 121, 118, 120, 116, 114, 115, 117, 116, 113, 115, 116, 117, 113, 115, 116, 122, 130]\n",
+ "Current payoff for adversary 1: 135744.0\n",
+ "Round 8 of 185\n",
+ "Best payoff: 136066\n",
+ "Best actions: [117, 132, 131, 131, 131, 131, 126, 124, 122, 120, 118, 119, 114, 115, 115, 118, 116, 113, 116, 117, 113, 115, 115, 111, 133]\n",
+ "Current payoff for adversary 1: 135563.0\n",
+ "Round 9 of 185\n",
+ "Best payoff: 136068\n",
+ "Best actions: [118, 131, 131, 132, 131, 131, 132, 125, 123, 120, 118, 119, 116, 114, 118, 118, 112, 116, 118, 116, 114, 115, 115, 111, 133]\n",
+ "Current payoff for adversary 1: 135121.0\n",
+ "Round 10 of 185\n",
+ "Best payoff: 136307\n",
+ "Best actions: [117, 131, 131, 132, 131, 132, 130, 125, 127, 123, 120, 121, 118, 117, 115, 115, 115, 115, 117, 113, 115, 115, 115, 111, 133]\n",
+ "Current payoff for adversary 1: 135944.0\n",
+ "Round 11 of 185\n",
+ "Best payoff: 136656\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 128, 126, 125, 123, 123, 121, 118, 117, 115, 115, 115, 116, 118, 116, 113, 115, 116, 108, 134]\n",
+ "Current payoff for adversary 1: 135054.0\n",
+ "Round 12 of 185\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Below is the second stage of learning- actions are chosen according to an epsilon greedy strategy.\n",
+ "episode_counter = (final_round + 1) * number_episodes_per_round\n",
+ "episodes_left = number_episodes - episode_counter\n",
+ "number_episodes_per_round = 500_000\n",
+ "number_rounds = int(episodes_left / number_episodes_per_round)\n",
+ "\n",
+ "for round_ in range(number_rounds): \n",
+ " print('Round ', round_, ' of ', number_rounds)\n",
+ " algorithm.epsilon_greedy_learning(number_episodes_per_round, episode_counter)\n",
+ " \n",
+ " adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " adversary_probabilities[10]=1\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " payoff1, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " opponent1_results.append(payoff1)\n",
+ " print('Current payoff for adversary 1: ', payoff1)\n",
+ " \n",
+ "# adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# adversary_probabilities[11]=1\n",
+ "# result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ "# payoff2, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "# opponent2_results.append(payoff2)\n",
+ "# print('Current payoff for adversary 2: ', payoff2)\n",
+ " \n",
+ " episode_counter += number_episodes_per_round\n",
+ " \n",
+ "plt.plot(opponent1_results)\n",
+ "# plt.plot(opponent2_results)\n",
+ "plt.title(\"Payoff over the rounds\")\n",
+ "plt.xlabel(\"Rounds\")\n",
+ "plt.ylabel(\"Payoff at the end of each round\")\n",
+ "legend = [\"adversary 1\"]\n",
+ "plt.legend(legend)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Qtable.save(\"Qtable_guess132\")\n",
+ "\n",
+ "df1 = pd.DataFrame(opponent1_results)\n",
+ "#df2 = pd.DataFrame(opponent2_results)\n",
+ "\n",
+ "writer = pd.ExcelWriter('payoff_10.xlsx', engine='xlsxwriter')\n",
+ "df1.to_excel(writer, sheet_name='payoff_10', index=False)\n",
+ "#df2.to_excel(writer, sheet_name='payoff2', index=False)\n",
+ "writer.save()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# We now have the trained agent. We want to test it against each opponent individually, so that\n",
+ "# we can compare it against the agent that is just trained against this opponent. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Testing against one type of opponent by changing the * below to be the first number\n",
+ "adversary_probabilities[10]=1\n",
+ "result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ "payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "print(payoff)\n",
+ "print(adversary_payoff)\n",
+ "print(actions)\n",
+ "print(adversary_actions)\n",
+ "print(demand_potential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Testing against one type of opponent by changing the * below to be the first number\n",
+ "adversary_probabilities[11]=1\n",
+ "result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ "payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "print(payoff)\n",
+ "print(adversary_payoff)\n",
+ "print(actions)\n",
+ "print(adversary_actions)\n",
+ "print(demand_potential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.7"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Episodic_learning_with_memory/0.5_imitation_132_0.5_guess_132.xlsx b/qLearning/Episodic_learning_with_memory/0.5_imitation_132_0.5_guess_132.xlsx
new file mode 100644
index 0000000..d3a02cf
Binary files /dev/null and b/qLearning/Episodic_learning_with_memory/0.5_imitation_132_0.5_guess_132.xlsx differ
diff --git a/qLearning/Episodic_learning_with_memory/0.5_myopic_0.5_imitation_132.xlsx b/qLearning/Episodic_learning_with_memory/0.5_myopic_0.5_imitation_132.xlsx
new file mode 100644
index 0000000..8d8a932
Binary files /dev/null and b/qLearning/Episodic_learning_with_memory/0.5_myopic_0.5_imitation_132.xlsx differ
diff --git a/qLearning/Episodic_learning_with_memory/QTables/.DS_Store b/qLearning/Episodic_learning_with_memory/QTables/.DS_Store
new file mode 100644
index 0000000..bae5052
Binary files /dev/null and b/qLearning/Episodic_learning_with_memory/QTables/.DS_Store differ
diff --git a/qLearning/Episodic_learning_with_memory/Qtable.py b/qLearning/Episodic_learning_with_memory/Qtable.py
new file mode 100644
index 0000000..e40299e
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/Qtable.py
@@ -0,0 +1,44 @@
+# Ed, Galit and Katerina
+# Relates to the Q-Learning approach.
+# Defines the Q-table
+
+import numpy as np
+import os
+
+class QTable():
+
+
+ def __init__(self, number_demands, number_actions, number_stages, learning_rate):
+
+ self.number_demands= number_demands
+ self.number_actions = number_actions
+ self.number_stages = number_stages
+ self.learning_rate = learning_rate
+ self.Q_table = np.zeros((self.number_demands, self.number_actions, self.number_actions, self.number_stages))
+ self.QTable_name=f"QTable, actions={self.number_actions}, maximum demand={self.number_demands - 1}, stages={self.number_stages}"
+
+
+ def reset(self):
+ Qtable = np.zeros((self.number_demands, self.number_actions, self.number_actions, self.number_stages))
+ return Qtable, self.learning_rate
+
+
+ def random_reset(self):
+ random_Qtable = np.random.rand(self.number_demands, self.number_actions, self.number_actions, self.number_stages)
+ return random_Qtable, self.learning_rate
+
+ def save(self, name = None):
+ if name is None:
+ return np.save(os.path.join('QTables',f'{self.QTable_name}'), self.Q_table)
+ else:
+ return np.save(os.path.join('QTables',name), self.Q_table)
+
+ def load(self,name = None):
+ if name is None:
+ return np.load(os.path.join('QTables',f'{self.QTable_name}'))
+ else:
+ return np.load(os.path.join('QTables',name))
+
+
+
+
diff --git a/qLearning/Episodic_learning_with_memory/__pycache__/Qtable.cpython-39.pyc b/qLearning/Episodic_learning_with_memory/__pycache__/Qtable.cpython-39.pyc
new file mode 100644
index 0000000..3194122
Binary files /dev/null and b/qLearning/Episodic_learning_with_memory/__pycache__/Qtable.cpython-39.pyc differ
diff --git a/qLearning/Episodic_learning_with_memory/__pycache__/environment.cpython-39.pyc b/qLearning/Episodic_learning_with_memory/__pycache__/environment.cpython-39.pyc
new file mode 100644
index 0000000..10bb51e
Binary files /dev/null and b/qLearning/Episodic_learning_with_memory/__pycache__/environment.cpython-39.pyc differ
diff --git a/qLearning/Episodic_learning_with_memory/__pycache__/learningAgent.cpython-39.pyc b/qLearning/Episodic_learning_with_memory/__pycache__/learningAgent.cpython-39.pyc
new file mode 100644
index 0000000..7d57193
Binary files /dev/null and b/qLearning/Episodic_learning_with_memory/__pycache__/learningAgent.cpython-39.pyc differ
diff --git a/qLearning/Episodic_learning_with_memory/__pycache__/test.cpython-39.pyc b/qLearning/Episodic_learning_with_memory/__pycache__/test.cpython-39.pyc
new file mode 100644
index 0000000..20eb6df
Binary files /dev/null and b/qLearning/Episodic_learning_with_memory/__pycache__/test.cpython-39.pyc differ
diff --git a/qLearning/Episodic_learning_with_memory/environment.py b/qLearning/Episodic_learning_with_memory/environment.py
new file mode 100644
index 0000000..9494874
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/environment.py
@@ -0,0 +1,259 @@
+# Katerina, Ed and Galit (and Tommy!)
+# Relates to the Q-Learning approach.
+# Contains DemandPotentialGame Class and the Model of the DemandPotentialGame Class.
+
+from enum import Enum
+import numpy as np # numerical python
+# printoptions: output limited to 2 digits after decimal point
+np.set_printoptions(precision=2, suppress=False)
+
+
+class DemandPotentialGame():
+ """
+ Fully defines Demand Potential Game. It contains game rules, memory and agents strategies.
+ """
+
+ def __init__(self, total_demand, costs, total_stages) -> None:
+ self.total_demand = total_demand
+ self.costs = costs
+ self.total_stages = total_stages
+ # first index is always player
+ self.demand_potential = None # two lists for the two players
+ self.prices = None # prices over T rounds
+ self.profit = None # profit in each of T rounds
+ self.stage = None
+
+ def reset_game(self):
+ """
+ Method resets game memory: Demand Potential, prices, profits
+ """
+ self.demand_potential = [[0]*(self.total_stages), [0]*(self.total_stages)] # two lists for the two players
+ self.prices = [[0]*self.total_stages, [0]*self.total_stages] # prices over T rounds
+ self.profit = [[0]*self.total_stages, [0]*self.total_stages] # profit in each of T rounds
+ self.demand_potential[0][0] = self.total_demand / 2 # initialise first round 0
+ self.demand_potential[1][0] = self.total_demand/2
+
+ def profits(self, player=0):
+ """
+ Computes profits. Player 0 is the learning agent.
+ """
+ return self.profit[player][self.stage]
+
+ def update_prices_profit_demand(self, price_pair):
+ """
+ Updates Prices, Profit and Demand Potential Memory.
+ Parameters.
+ price_pair: Pair of prices from the Learning agent and adversary.
+ """
+
+ for player in [0, 1]:
+ price = int(price_pair[player])
+ self.prices[player][self.stage] = price
+ self.profit[player][self.stage] = int((
+ self.demand_potential[player][self.stage] - price)*(price - self.costs[player]))
+ if self.stage < self.total_stages-1:
+ self.demand_potential[0][self.stage + 1] = \
+ int(self.demand_potential[0][self.stage] + (price_pair[1] - price_pair[0])/2)
+ self.demand_potential[1][self.stage + 1] = 400 - self.demand_potential[0][self.stage + 1]
+
+
+ def monopoly_price(self, player): # myopic monopoly price
+ """
+ Computes Monopoly prices.
+ """
+ return (self.demand_potential[player][self.stage] + self.costs[player])/2
+
+ def myopic(self, player=0):
+ """
+ Adversary follows Myopic strategy
+ """
+ return self.monopoly_price(player)
+
+ def const(self, player, price): # constant price strategy
+ """
+ Adversary follows Constant strategy
+ """
+ return price
+
+ def imit(self, player, firstprice): # price imitator strategy
+ if self.stage == 0:
+ return firstprice
+ return self.prices[1-player][self.stage-1]
+
+ def fight(self, player, firstprice): # simplified fighting strategy
+ if self.stage == 0:
+ return firstprice
+ if self.stage == self.total_stages-1:
+ return self.monopoly_price(player)
+ # aspire = [ 207, 193 ] # aspiration level for demand potential
+ aspire = [0, 0]
+ for i in range(2):
+ aspire[i] = (self.total_demand-self.costs[player] +
+ self.costs[1-player])/2
+
+ D = self.demand_potential[player][self.stage]
+ Asp = aspire[player]
+ if D >= Asp: # keep price; DANGER: price will never rise
+ return self.prices[player][self.stage-1]
+ # adjust to get to aspiration level using previous
+ # opponent price; own price has to be reduced by twice
+ # the negative amount D - Asp to getself.demand_potential to Asp
+ P = self.prices[1-player][self.stage-1] + 2*(D - Asp)
+ # never price too high because even 125 gives good profits
+ # P = min(P, 125)
+ aspire_price = (self.total_demand+self.costs[0]+self.costs[1])/4
+ P = min(P, int(0.95*aspire_price))
+
+ return P
+
+ def fight_lb(self, player, firstprice):
+ P = self.fight(player, firstprice)
+ # never price less than production cost
+ P = max(P, self.costs[player])
+ return P
+
+ # sophisticated fighting strategy, compare fight()
+ # estimate *sales* of opponent as their target, kept between
+ # calls in global variable oppsaleguess[]. Assumed behavior
+ # of opponent is similar to this strategy itself.
+ oppsaleguess = [61, 75] # first guess opponent sales as in monopoly
+
+ def guess(self, player, firstprice): # predictive fighting strategy
+ if self.stage == 0:
+ self.oppsaleguess[0] = 61 # always same start
+ self.oppsaleguess[1] = 75 # always same start
+ return firstprice
+
+ if self.stage == self.total_stages-1:
+ return self.monopoly_price(player)
+ aspire = [207, 193] # aspiration level
+ D = self.demand_potential[player][self.stage]
+ Asp = aspire[player]
+
+ if D >= Asp: # keep price, but go slightly towards monopoly if good
+ pmono = self.monopoly_price(player)
+ pcurrent = self.prices[player][self.stage-1]
+ if pcurrent > pmono: # shouldn't happen
+ return pmono
+ if pcurrent > pmono-7: # no change
+ return pcurrent
+ # current low price at 60%, be accommodating towards "collusion"
+ return .6 * pcurrent + .4 * (pmono-7)
+
+ # guess current *opponent price* from previous sales
+ prevsales = self.demand_potential[1 - player][t-1] - self.prices[1-player][t-1]
+ # adjust with weight alpha from previous guess
+ alpha = .5
+ newsalesguess = alpha * self.oppsaleguess[player] + (1-alpha)*prevsales
+ # update
+ self.oppsaleguess[player] = newsalesguess
+ guess_opponent_price = 400 - D - newsalesguess
+ P = guess_opponent_price + 2*(D - Asp)
+
+ if player == 0:
+ P = min(P, 125)
+ if player == 1:
+ P = min(P, 130)
+ return P
+
+
+class Model(DemandPotentialGame):
+ """
+ Defines the Problem's Model. It is assumed a Markov Decision Process is defined. The class is a Child from the Demand Potential Game Class.
+ The reason: Model is a conceptualization of the Game.
+ """
+
+ def __init__(self, total_demand, costs, total_stages, adversary_probabilities) -> None:
+ super().__init__(total_demand, costs, total_stages)
+
+ self.reward_function = self.profits
+
+ # [stage, agent's demand potential, agent previous action, adv previous action]
+ self.initial_state = [0, total_demand/2, 0, 0]
+ self.episode_memory = list()
+ self.done = False
+ self.adversary_probabilities = adversary_probabilities
+
+ def reset(self):
+ """
+ Reset Model Instantiation.
+ """
+ reward = 0
+ self.stage = 0
+ self.done = False
+ self.reset_game()
+ self.reset_adversary()
+ return self.initial_state, reward, self.done
+
+ def reset_adversary(self):
+ options = list(range(len(self.adversary_probabilities)))
+ adversary_index = np.random.choice(options, 1, p= self.adversary_probabilities)
+ self.adversary_mode = AdversaryModes(adversary_index)
+
+ def adversary_choose_price(self):
+ """
+ Strategy followed by the adversary.
+ """
+
+ if self.adversary_mode == AdversaryModes.constant_132:
+ return self.const(player=1, price=132)
+ elif self.adversary_mode == AdversaryModes.constant_95:
+ return self.const(player=1, price=95)
+ elif self.adversary_mode == AdversaryModes.imitation_128:
+ return self.imit(player=1, firstprice=128)
+ elif self.adversary_mode == AdversaryModes.imitation_132:
+ return self.imit(player=1, firstprice=132)
+ elif self.adversary_mode == AdversaryModes.fight_100:
+ return self.fight(player=1, firstprice=100)
+ elif self.adversary_mode == AdversaryModes.fight_125:
+ return self.fight(player=1, firstprice=125)
+ elif self.adversary_mode == AdversaryModes.fight_lb_125:
+ return self.fight_lb(player=1, firstprice=125)
+ elif self.adversary_mode == AdversaryModes.fight_132:
+ return self.fight(player=1, firstprice=132)
+ elif self.adversary_mode == AdversaryModes.fight_lb_132:
+ return self.fight_lb(player=1, firstprice=132)
+ elif self.adversary_mode == AdversaryModes.guess_125:
+ return self.fight(player=1, firstprice=125)
+ elif self.adversary_mode == AdversaryModes.guess_132:
+ return self.fight(player=1, firstprice=132)
+ else:
+ return self.myopic(player=1)
+
+ def step(self, state, action, action_index):
+ """
+ Transition Function.
+ Parameters:
+ - action: Price
+ - state: tupple in the latest stage (stage ,Demand Potential, Adversary Action)
+ """
+ adversary_action = int(self.adversary_choose_price())
+ self.update_prices_profit_demand([action, adversary_action])
+
+ done = (self.stage == self.total_stages-1)
+
+
+ if not done:
+ new_state = [self.stage+1, self.demand_potential[0][self.stage + 1], action_index, adversary_action]
+ else:
+ new_state = [self.stage+1, 0, action_index, adversary_action]
+
+ reward = self.reward_function()
+ self.stage = self.stage + 1
+
+ return new_state, reward, done
+
+
+class AdversaryModes(Enum):
+ myopic = 0
+ constant_132 = 1
+ constant_95 = 2
+ imitation_132 = 3
+ imitation_128 = 4
+ fight_132 = 5
+ fight_lb_132 = 6
+ fight_125 = 7
+ fight_lb_125 = 8
+ fight_100 = 9
+ guess_132 = 10
+ guess_125 = 11
\ No newline at end of file
diff --git a/qLearning/Episodic_learning_with_memory/learningAgent.py b/qLearning/Episodic_learning_with_memory/learningAgent.py
new file mode 100644
index 0000000..01ee861
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/learningAgent.py
@@ -0,0 +1,195 @@
+# Ed, Kat, Galit
+# ReinforceAlgorithm Class: Solver.
+# Implement an off-policy Q-learning algorithm
+
+import numpy as np
+
+# print options: output limited to 2 digits after decimal point
+np.set_printoptions(precision=2, suppress=False)
+
+
+class LearningAlgorithm():
+ """
+ Model Solver.
+ """
+ def __init__(self, Model, Qtable, number_episodes, discount_factor) -> None:
+
+ self.env = Model
+ self.Qtable = Qtable.Q_table
+ self.learning_rate = Qtable.learning_rate
+ self.number_episodes = number_episodes
+ self.gamma = discount_factor
+ self.number_demands=Qtable.number_demands
+ self.number_stages=Qtable.number_stages
+ self.number_actions=Qtable.number_actions
+ self.highest_demand = int(self.number_demands - 1)
+
+
+ def reset_Qtable(self):
+ self.Qtable, self.learning_rate = self.Qtable.reset()
+
+
+ def action_index(self, monopoly_price, action): # computes action index in Qtable
+ return int(action - (monopoly_price - self.number_actions + 1)) #monopoly_price should have index number_actions - 1
+
+ def alpha_n(self, n): # defines the Qlearning rate
+ return self.learning_rate[0]/(n+self.learning_rate[1])
+
+ """
+ Now the Q-learning itself
+ """
+
+ def random_policy(self, monopoly_price):
+ random_action = np.random.randint(monopoly_price-self.number_actions+1, monopoly_price + 1)
+ if random_action < 0:
+ random_action = max(0, random_action)
+ if self.env.costs[0] > random_action:
+ random_action = monopoly_price
+ return random_action
+
+ def q_learning(self, state_action_value, optimal_next_value, reward, alpha, gamma):
+ target = reward + gamma * optimal_next_value
+ return state_action_value + alpha * (target - state_action_value)
+
+
+ def solver(self):
+
+ self.reset_Qtable
+ best_payoff = 0
+ best_actions = list()
+
+ for episode in range(self.number_episodes):
+
+ payoff = 0
+ actions = list()
+ discount = 1
+ state, reward, done = self.env.reset()
+
+ while not done:
+ stage, agent_demand, agent_previous_action, adversary_previous_action = state
+ if (agent_demand < 0) or (agent_demand > self.highest_demand):
+ break
+ if (stage > 0 and adversary_previous_action < self.env.costs[1]) or (self.highest_demand - agent_demand < adversary_previous_action):
+ break
+ monopoly_price = int((agent_demand + self.env.costs[0]) / 2)
+ action = self.random_policy(monopoly_price)
+ actions.append(action)
+ demand_index = int(agent_demand)
+ action_index = self.action_index(monopoly_price, action)
+ state, reward, done = self.env.step(state, action, action_index)
+ payoff += reward * discount
+ discount *= self.gamma
+
+
+ # updating the Qtable
+ if done:
+ optimal_next_value = 0
+ else:
+ optimal_next_value = max(self.Qtable[int(state[1]),:, action_index, state[0]])
+
+ current_q_value = self.Qtable[demand_index, action_index, agent_previous_action, stage]
+ self.Qtable[demand_index, action_index, agent_previous_action, stage] = self.q_learning(current_q_value, optimal_next_value, reward, self.alpha_n(episode), self.gamma)
+
+ if payoff > best_payoff:
+ best_payoff = payoff
+ best_actions = actions
+ if episode == self.number_episodes - 1:
+ print("Best payoff: ", best_payoff)
+ print("Best actions: ", best_actions)
+
+
+ def continue_learning(self, number_episodes, number_previous_episodes):
+
+ for episode in range(number_episodes):
+
+ state, reward, done = self.env.reset()
+
+ while not done:
+ stage, agent_demand, agent_previous_action, adversary_previous_action = state
+ if (agent_demand < 0) or (agent_demand > self.highest_demand):
+ break
+ if (stage > 0 and adversary_previous_action < self.env.costs[1]) or (self.highest_demand - agent_demand < adversary_previous_action):
+ break
+ monopoly_price = int((agent_demand + self.env.costs[0]) / 2)
+ action = self.random_policy(monopoly_price)
+ demand_index = int(agent_demand)
+ action_index = self.action_index(monopoly_price, action)
+ state, reward, done = self.env.step(state, action, action_index)
+
+
+ # updating the Qtable
+ if done:
+ optimal_next_value = 0
+ else:
+ optimal_next_value = max(self.Qtable[int(state[1]),:, action_index, state[0]])
+
+ current_q_value = self.Qtable[demand_index, action_index, agent_previous_action, stage]
+ self.Qtable[demand_index, action_index, agent_previous_action, stage] = self.q_learning(current_q_value, optimal_next_value, reward, self.alpha_n(episode + number_previous_episodes), self.gamma)
+
+
+ def epsilon_greedy_learning(self, number_episodes, number_previous_episodes):
+
+ best_payoff = 0
+ best_actions = list()
+ final_prob = 0.05
+ constant = (final_prob*number_episodes)/(1-final_prob)
+
+ for episode in range(number_episodes):
+
+ state, reward, done = self.env.reset()
+
+ payoff = 0
+ actions = list()
+ discount = 1
+
+ while not done:
+ stage, agent_demand, agent_previous_action, adversary_previous_action = state
+ if (agent_demand < 0) or (agent_demand > self.highest_demand):
+ break
+ if (stage > 0 and adversary_previous_action < self.env.costs[1]) or (self.highest_demand - agent_demand < adversary_previous_action):
+ break
+ demand_index = int(agent_demand)
+ monopoly_price = int((agent_demand + self.env.costs[0]) / 2)
+ greedy_action_index = np.argmax(self.Qtable[demand_index, :, agent_previous_action, stage])
+ action = self.epsilon_greedy_policy(monopoly_price, episode, number_previous_episodes, greedy_action_index, constant)
+ actions.append(action)
+ action_index = self.action_index(monopoly_price, action)
+ state, reward, done = self.env.step(state, action, action_index)
+ payoff += reward * discount
+ discount *= self.gamma
+
+ # updating the Qtable
+ if done:
+ optimal_next_value = 0
+ else:
+ optimal_next_value = max(self.Qtable[int(state[1]),:, action_index, state[0]])
+
+ current_q_value = self.Qtable[demand_index, action_index, agent_previous_action, stage]
+ self.Qtable[demand_index, action_index, agent_previous_action, stage] = self.q_learning(current_q_value, optimal_next_value, reward, self.alpha_n(episode), self.gamma)
+# if stage == 0 and current_q_value > 95000:
+# print("old", current_q_value)
+# print("new", self.Qtable[demand_index, action_index, agent_previous_action, stage])
+# print(np.max(self.Qtable))
+
+
+ if payoff > best_payoff:
+ best_payoff = payoff
+ best_actions = actions
+ if episode == number_episodes - 1:
+ print("Best payoff: ", best_payoff)
+ print("Best actions: ", best_actions)
+
+
+ def epsilon_greedy_policy(self, monopoly_price, episode, number_previous_episodes, greedy_action_index, constant):
+ epsilon = (constant/(constant + episode)) * (1-(number_previous_episodes /self.number_episodes))
+ if np.random.binomial(1,epsilon) == 1:
+ action = np.random.randint(monopoly_price-self.number_actions+1, monopoly_price + 1)
+ else:
+ action = greedy_action_index + (monopoly_price - self.number_actions + 1)
+ action = max(0, action)
+ if self.env.costs[0] > action:
+ action = monopoly_price
+ return action
+
+
+
diff --git a/qLearning/Episodic_learning_with_memory/qLearningSimulations-oneAdversary.ipynb b/qLearning/Episodic_learning_with_memory/qLearningSimulations-oneAdversary.ipynb
new file mode 100644
index 0000000..4f50cf3
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/qLearningSimulations-oneAdversary.ipynb
@@ -0,0 +1,573 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "import pandas as pd"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(11)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_demand = 400\n",
+ "agent_cost = 57\n",
+ "adversary_cost = 71 \n",
+ "costs = [agent_cost,adversary_cost]\n",
+ "total_stages = 25\n",
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Below is where we decide what adversaries we train against- see environment.py for the numbers\n",
+ "# Replace * and ** with the two number associated with the opponents at the bottom of environment.py\n",
+ "# adversary_probabilities[10]= 0.5\n",
+ "adversary_probabilities[10] = 1\n",
+ "game = Model(total_demand, costs, total_stages, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2040816\n"
+ ]
+ }
+ ],
+ "source": [
+ "number_actions = 50\n",
+ "number_demands = total_demand + 1\n",
+ "discount_factor = 1\n",
+ "number_episodes = 100_000_000\n",
+ "constant = int(number_episodes/49)\n",
+ "print(constant)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+denominator)\n",
+ "Qtable = QTable(number_demands, number_actions, total_stages , learning_rate = [constant,constant])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, number_episodes, discount_factor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0 0.5897715369319796\n",
+ "Current payoff for adversary 1: 80171.0\n",
+ "Current payoff for adversary 1: 88691.0\n",
+ "Current payoff for adversary 1: 95241.0\n",
+ "Current payoff for adversary 1: 91616.0\n",
+ "Current payoff for adversary 1: 105628.0\n",
+ "Current payoff for adversary 1: 62523.0\n",
+ "Current payoff for adversary 1: 105138.0\n",
+ "Current payoff for adversary 1: 78727.0\n",
+ "Current payoff for adversary 1: 85785.0\n",
+ "Current payoff for adversary 1: 86745.0\n",
+ "Current payoff for adversary 1: 93727.0\n",
+ "Current payoff for adversary 1: 104096.0\n",
+ "Current payoff for adversary 1: 105856.0\n",
+ "Current payoff for adversary 1: 96217.0\n",
+ "Current payoff for adversary 1: 97545.0\n",
+ "Current payoff for adversary 1: 95933.0\n",
+ "Current payoff for adversary 1: 93805.0\n",
+ "Current payoff for adversary 1: 105549.0\n",
+ "Current payoff for adversary 1: 88906.0\n",
+ "Current payoff for adversary 1: 107502.0\n",
+ "Current payoff for adversary 1: 108536.0\n",
+ "Current payoff for adversary 1: 108047.0\n",
+ "Current payoff for adversary 1: 107102.0\n",
+ "Current payoff for adversary 1: 94372.0\n",
+ "Current payoff for adversary 1: 84036.0\n",
+ "Current payoff for adversary 1: 96009.0\n",
+ "Current payoff for adversary 1: 96923.0\n",
+ "Current payoff for adversary 1: 96544.0\n",
+ "Current payoff for adversary 1: 98038.0\n",
+ "Current payoff for adversary 1: 98316.0\n",
+ "Current payoff for adversary 1: 102918.0\n",
+ "Current payoff for adversary 1: 103174.0\n",
+ "Current payoff for adversary 1: 97146.0\n",
+ "Current payoff for adversary 1: 101444.0\n",
+ "Current payoff for adversary 1: 107079.0\n",
+ "Current payoff for adversary 1: 107258.0\n",
+ "Current payoff for adversary 1: 108273.0\n",
+ "Current payoff for adversary 1: 108879.0\n",
+ "Current payoff for adversary 1: 108815.0\n",
+ "Current payoff for adversary 1: 89023.0\n",
+ "Current payoff for adversary 1: 108685.0\n",
+ "Current payoff for adversary 1: 109782.0\n",
+ "Current payoff for adversary 1: 109246.0\n",
+ "Current payoff for adversary 1: 107501.0\n",
+ "Current payoff for adversary 1: 108430.0\n",
+ "Current payoff for adversary 1: 88807.0\n",
+ "Current payoff for adversary 1: 89579.0\n",
+ "Current payoff for adversary 1: 89104.0\n",
+ "Current payoff for adversary 1: 89185.0\n",
+ "Current payoff for adversary 1: 90581.0\n",
+ "50 0.014010674672339848\n",
+ "Current payoff for adversary 1: 91426.0\n",
+ "Current payoff for adversary 1: 92414.0\n",
+ "Current payoff for adversary 1: 89640.0\n",
+ "Current payoff for adversary 1: 105000.0\n",
+ "Current payoff for adversary 1: 104323.0\n",
+ "Current payoff for adversary 1: 104980.0\n",
+ "Current payoff for adversary 1: 111710.0\n",
+ "Current payoff for adversary 1: 95604.0\n",
+ "Current payoff for adversary 1: 96814.0\n",
+ "Current payoff for adversary 1: 108008.0\n",
+ "Current payoff for adversary 1: 115804.0\n",
+ "Current payoff for adversary 1: 105631.0\n",
+ "Current payoff for adversary 1: 104537.0\n",
+ "Current payoff for adversary 1: 105038.0\n",
+ "Current payoff for adversary 1: 104903.0\n",
+ "Current payoff for adversary 1: 113073.0\n",
+ "Current payoff for adversary 1: 113678.0\n",
+ "Current payoff for adversary 1: 113678.0\n",
+ "Current payoff for adversary 1: 104090.0\n",
+ "Current payoff for adversary 1: 104346.0\n",
+ "Current payoff for adversary 1: 113801.0\n",
+ "Current payoff for adversary 1: 113801.0\n",
+ "72\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "[]"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# Below is the first stage of learning- actions are chosen randomly.\n",
+ "number_episodes_per_round = 100_000\n",
+ "number_rounds = int(number_episodes / number_episodes_per_round)\n",
+ "errors = np.zeros(number_rounds)\n",
+ "final_round = 0\n",
+ "opponent1_results = list()\n",
+ "#opponent2_results = list()\n",
+ "for round_ in range(number_rounds):\n",
+ " algorithm.continue_learning(number_episodes_per_round,number_episodes_per_round * round_ +1)\n",
+ " adversary_probabilities[10]= 1\n",
+ " # adversary_probabilities[11] = 0.5\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " errors[round_] = result.error(1000)\n",
+ " if round_ % 50 == 0:\n",
+ " print(round_, errors[round_])\n",
+ " if round_ > 10 and np.max(errors[round_-10:round_]) < 0.01:\n",
+ " print(round_)\n",
+ " final_round = round_\n",
+ " break\n",
+ " \n",
+ " adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " adversary_probabilities[10]=1\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " payoff1, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " opponent1_results.append(payoff1)\n",
+ " print('Current payoff for adversary 1: ', payoff1)\n",
+ " \n",
+ " # adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " # adversary_probabilities[11]=1\n",
+ " # result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " # payoff2, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " # opponent2_results.append(payoff2)\n",
+ " # print('Current payoff for adversary 2: ', payoff2)\n",
+ " \n",
+ " if (round_ == number_rounds - 1):\n",
+ " final_round = round_\n",
+ " \n",
+ "plt.plot(errors[0:final_round+1])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Round 0 of 185\n",
+ "Best payoff: 127495\n",
+ "Best actions: [121, 128, 125, 123, 122, 114, 115, 106, 112, 109, 108, 107, 102, 114, 101, 113, 104, 109, 107, 107, 110, 105, 105, 112, 130]\n",
+ "Current payoff for adversary 1: 118224.0\n",
+ "Round 1 of 185\n",
+ "Best payoff: 130757\n",
+ "Best actions: [121, 128, 132, 124, 120, 116, 113, 113, 111, 110, 117, 105, 111, 110, 117, 109, 115, 107, 109, 109, 116, 109, 111, 115, 130]\n",
+ "Current payoff for adversary 1: 130519.0\n",
+ "Round 2 of 185\n",
+ "Best payoff: 133134\n",
+ "Best actions: [118, 131, 132, 128, 122, 119, 116, 116, 114, 114, 113, 114, 113, 115, 112, 117, 117, 109, 114, 115, 114, 108, 114, 111, 131]\n",
+ "Current payoff for adversary 1: 132139.0\n",
+ "Round 3 of 185\n",
+ "Best payoff: 133675\n",
+ "Best actions: [118, 131, 132, 128, 128, 123, 119, 119, 114, 114, 116, 112, 114, 114, 116, 116, 115, 119, 109, 119, 114, 108, 114, 108, 133]\n",
+ "Current payoff for adversary 1: 132684.0\n",
+ "Round 4 of 185\n",
+ "Best payoff: 134211\n",
+ "Best actions: [117, 131, 132, 131, 124, 122, 120, 117, 117, 115, 117, 115, 115, 113, 117, 115, 115, 123, 107, 116, 111, 116, 113, 108, 133]\n",
+ "Current payoff for adversary 1: 133626.0\n",
+ "Round 5 of 185\n",
+ "Best payoff: 135075\n",
+ "Best actions: [118, 132, 132, 131, 132, 132, 126, 126, 118, 118, 118, 113, 115, 117, 114, 121, 113, 112, 116, 122, 112, 115, 113, 123, 130]\n",
+ "Current payoff for adversary 1: 134911.0\n",
+ "Round 6 of 185\n",
+ "Best payoff: 135187\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 122, 122, 116, 116, 114, 114, 114, 114, 114, 114, 113, 116, 114, 114, 112, 114, 108, 133]\n",
+ "Current payoff for adversary 1: 134357.0\n",
+ "Round 7 of 185\n",
+ "Best payoff: 135849\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 128, 124, 121, 118, 120, 116, 114, 115, 117, 116, 113, 115, 116, 117, 113, 115, 116, 122, 130]\n",
+ "Current payoff for adversary 1: 135744.0\n",
+ "Round 8 of 185\n",
+ "Best payoff: 136066\n",
+ "Best actions: [117, 132, 131, 131, 131, 131, 126, 124, 122, 120, 118, 119, 114, 115, 115, 118, 116, 113, 116, 117, 113, 115, 115, 111, 133]\n",
+ "Current payoff for adversary 1: 135563.0\n",
+ "Round 9 of 185\n",
+ "Best payoff: 136068\n",
+ "Best actions: [118, 131, 131, 132, 131, 131, 132, 125, 123, 120, 118, 119, 116, 114, 118, 118, 112, 116, 118, 116, 114, 115, 115, 111, 133]\n",
+ "Current payoff for adversary 1: 135121.0\n",
+ "Round 10 of 185\n",
+ "Best payoff: 136307\n",
+ "Best actions: [117, 131, 131, 132, 131, 132, 130, 125, 127, 123, 120, 121, 118, 117, 115, 115, 115, 115, 117, 113, 115, 115, 115, 111, 133]\n",
+ "Current payoff for adversary 1: 135944.0\n",
+ "Round 11 of 185\n",
+ "Best payoff: 136656\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 128, 126, 125, 123, 123, 121, 118, 117, 115, 115, 115, 116, 118, 116, 113, 115, 116, 108, 134]\n",
+ "Current payoff for adversary 1: 135054.0\n",
+ "Round 12 of 185\n",
+ "Best payoff: 136982\n",
+ "Best actions: [118, 132, 131, 132, 132, 132, 132, 131, 126, 124, 123, 122, 119, 119, 117, 119, 117, 117, 117, 117, 117, 114, 116, 108, 134]\n",
+ "Current payoff for adversary 1: 135056.0\n",
+ "Round 13 of 185\n",
+ "Best payoff: 136625\n",
+ "Best actions: [118, 132, 132, 131, 132, 132, 132, 132, 126, 123, 120, 122, 117, 117, 118, 118, 117, 118, 117, 117, 115, 116, 116, 112, 128]\n",
+ "Current payoff for adversary 1: 135985.0\n",
+ "Round 14 of 185\n",
+ "Best payoff: 137033\n",
+ "Best actions: [118, 131, 131, 132, 132, 131, 132, 132, 132, 125, 123, 120, 122, 118, 115, 117, 117, 119, 117, 117, 115, 116, 116, 112, 132]\n",
+ "Current payoff for adversary 1: 136570.0\n",
+ "Round 15 of 185\n",
+ "Best payoff: 137116\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 126, 123, 120, 119, 120, 116, 117, 120, 118, 117, 117, 115, 116, 116, 114, 132]\n",
+ "Current payoff for adversary 1: 136974.0\n",
+ "Round 16 of 185\n",
+ "Best payoff: 137096\n",
+ "Best actions: [118, 131, 131, 132, 132, 131, 132, 132, 132, 126, 123, 120, 119, 118, 117, 118, 119, 116, 121, 114, 116, 115, 114, 112, 132]\n",
+ "Current payoff for adversary 1: 136052.0\n",
+ "Round 17 of 185\n",
+ "Best payoff: 137502\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 126, 124, 121, 121, 119, 119, 121, 118, 116, 120, 116, 122, 118, 115, 114, 133]\n",
+ "Current payoff for adversary 1: 137104.0\n",
+ "Round 18 of 185\n",
+ "Best payoff: 137622\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 131, 131, 131, 126, 124, 122, 124, 120, 118, 120, 119, 120, 123, 115, 117, 117, 114, 114, 132]\n",
+ "Current payoff for adversary 1: 137226.0\n",
+ "Round 19 of 185\n",
+ "Best payoff: 137677\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 125, 123, 120, 120, 118, 118, 118, 120, 116, 119, 116, 117, 119, 114, 132]\n",
+ "Current payoff for adversary 1: 137540.0\n",
+ "Round 20 of 185\n",
+ "Best payoff: 137881\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 127, 125, 122, 120, 124, 114, 118, 118, 118, 118, 117, 117, 117, 114, 133]\n",
+ "Current payoff for adversary 1: 137316.0\n",
+ "Round 21 of 185\n",
+ "Best payoff: 138068\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 127, 125, 123, 121, 121, 119, 119, 118, 118, 119, 117, 117, 115, 115, 132]\n",
+ "Current payoff for adversary 1: 138004.0\n",
+ "Round 22 of 185\n",
+ "Best payoff: 138092\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 125, 123, 121, 121, 119, 119, 118, 118, 119, 118, 119, 115, 106, 129]\n",
+ "Current payoff for adversary 1: 138065.0\n",
+ "Round 23 of 185\n",
+ "Best payoff: 138325\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 131, 131, 131, 128, 126, 126, 122, 121, 119, 119, 120, 119, 119, 119, 121, 116, 118, 131]\n",
+ "Current payoff for adversary 1: 138278.0\n",
+ "Round 24 of 185\n",
+ "Best payoff: 138348\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 123, 121, 121, 119, 119, 118, 119, 119, 119, 121, 116, 113, 133]\n",
+ "Current payoff for adversary 1: 138337.0\n",
+ "Round 25 of 185\n",
+ "Best payoff: 138438\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 132, 128, 126, 125, 123, 121, 120, 119, 119, 119, 119, 119, 121, 117, 113, 133]\n",
+ "Current payoff for adversary 1: 138424.0\n",
+ "Round 26 of 185\n",
+ "Best payoff: 138584\n",
+ "Best actions: [118, 132, 131, 132, 132, 132, 132, 132, 132, 132, 128, 126, 125, 124, 122, 122, 120, 119, 119, 119, 119, 121, 117, 114, 133]\n",
+ "Current payoff for adversary 1: 138190.0\n",
+ "Round 27 of 185\n",
+ "Best payoff: 138480\n",
+ "Best actions: [118, 132, 131, 132, 132, 132, 132, 132, 132, 131, 131, 127, 125, 122, 121, 120, 120, 122, 118, 122, 118, 119, 118, 116, 132]\n",
+ "Current payoff for adversary 1: 138180.0\n",
+ "Round 28 of 185\n",
+ "Best payoff: 138586\n",
+ "Best actions: [118, 132, 132, 131, 132, 132, 132, 132, 132, 132, 131, 126, 124, 122, 122, 119, 120, 120, 119, 119, 119, 119, 118, 114, 133]\n",
+ "Current payoff for adversary 1: 138281.0\n",
+ "Round 29 of 185\n",
+ "Best payoff: 138617\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 126, 123, 122, 120, 120, 120, 122, 121, 118, 120, 118, 114, 133]\n",
+ "Current payoff for adversary 1: 138595.0\n",
+ "Round 30 of 185\n",
+ "Best payoff: 138618\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 124, 121, 121, 119, 118, 119, 119, 119, 119, 118, 113, 133]\n",
+ "Current payoff for adversary 1: 138422.0\n",
+ "Round 31 of 185\n",
+ "Best payoff: 138757\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 132, 132, 131, 132, 132, 126, 124, 123, 122, 121, 123, 122, 121, 120, 125, 120, 112, 134]\n",
+ "Current payoff for adversary 1: 138757.0\n",
+ "Round 32 of 185\n",
+ "Best payoff: 139021\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 124, 124, 122, 121, 123, 122, 121, 120, 122, 122, 110, 134]\n",
+ "Current payoff for adversary 1: 138065.0\n",
+ "Round 33 of 185\n",
+ "Best payoff: 139130\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 124, 124, 122, 121, 121, 123, 120, 121, 122, 122, 110, 135]\n",
+ "Current payoff for adversary 1: 139083.0\n",
+ "Round 34 of 185\n",
+ "Best payoff: 139128\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 131, 126, 124, 124, 122, 121, 121, 123, 120, 121, 122, 122, 110, 135]\n",
+ "Current payoff for adversary 1: 139063.0\n",
+ "Round 35 of 185\n",
+ "Best payoff: 139257\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 132, 131, 132, 131, 132, 126, 124, 124, 122, 122, 122, 122, 121, 122, 122, 122, 110, 135]\n",
+ "Current payoff for adversary 1: 139171.0\n",
+ "Round 36 of 185\n",
+ "Best payoff: 139215\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 124, 124, 122, 122, 122, 124, 120, 122, 122, 122, 114, 134]\n",
+ "Current payoff for adversary 1: 139209.0\n",
+ "Round 37 of 185\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best payoff: 139210\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 124, 124, 122, 122, 122, 124, 120, 122, 122, 122, 110, 135]\n",
+ "Current payoff for adversary 1: 138765.0\n",
+ "Round 38 of 185\n",
+ "Best payoff: 139210\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 124, 124, 122, 122, 122, 124, 120, 122, 122, 122, 110, 135]\n",
+ "Current payoff for adversary 1: 139148.0\n",
+ "Round 39 of 185\n",
+ "Best payoff: 139210\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 131, 128, 125, 124, 123, 124, 121, 124, 120, 122, 123, 122, 111, 135]\n",
+ "Current payoff for adversary 1: 139107.0\n",
+ "Round 40 of 185\n",
+ "Best payoff: 139273\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 124, 123, 121, 121, 121, 121, 122, 122, 122, 112, 134]\n",
+ "Current payoff for adversary 1: 139019.0\n",
+ "Round 41 of 185\n",
+ "Best payoff: 139282\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 131, 131, 132, 131, 128, 126, 124, 123, 122, 122, 124, 120, 122, 122, 122, 112, 134]\n",
+ "Current payoff for adversary 1: 139167.0\n",
+ "Round 42 of 185\n",
+ "Best payoff: 139273\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 124, 123, 121, 121, 121, 121, 122, 122, 122, 112, 134]\n",
+ "Current payoff for adversary 1: 139134.0\n",
+ "Round 43 of 185\n",
+ "Best payoff: 139240\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 131, 131, 131, 132, 131, 126, 124, 124, 122, 122, 122, 121, 121, 122, 122, 122, 112, 134]\n",
+ "Current payoff for adversary 1: 139126.0\n",
+ "Round 44 of 185\n",
+ "Best payoff: 139265\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 126, 124, 124, 122, 121, 122, 122, 122, 122, 122, 122, 112, 134]\n",
+ "Current payoff for adversary 1: 139111.0\n",
+ "Round 45 of 185\n",
+ "Best payoff: 139297\n",
+ "Best actions: [118, 132, 132, 131, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 124, 126, 120, 122, 122, 122, 122, 122, 122, 112, 134]\n",
+ "Current payoff for adversary 1: 139142.0\n",
+ "Round 46 of 185\n",
+ "Best payoff: 139354\n",
+ "Best actions: [118, 131, 132, 131, 132, 132, 131, 132, 132, 132, 132, 132, 128, 126, 124, 123, 122, 122, 122, 122, 122, 122, 122, 112, 134]\n",
+ "Current payoff for adversary 1: 138858.0\n",
+ "Round 47 of 185\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Below is the second stage of learning- actions are chosen according to an epsilon greedy strategy.\n",
+ "episode_counter = (final_round + 1) * number_episodes_per_round\n",
+ "episodes_left = number_episodes - episode_counter\n",
+ "number_episodes_per_round = 500_000\n",
+ "number_rounds = int(episodes_left / number_episodes_per_round)\n",
+ "\n",
+ "for round_ in range(number_rounds): \n",
+ " print('Round ', round_, ' of ', number_rounds)\n",
+ " algorithm.epsilon_greedy_learning(number_episodes_per_round, episode_counter)\n",
+ " \n",
+ " adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " adversary_probabilities[10]=1\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " payoff1, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " opponent1_results.append(payoff1)\n",
+ " print('Current payoff for adversary 1: ', payoff1)\n",
+ " \n",
+ "# adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# adversary_probabilities[11]=1\n",
+ "# result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ "# payoff2, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "# opponent2_results.append(payoff2)\n",
+ "# print('Current payoff for adversary 2: ', payoff2)\n",
+ " \n",
+ " episode_counter += number_episodes_per_round\n",
+ " \n",
+ "plt.plot(opponent1_results)\n",
+ "# plt.plot(opponent2_results)\n",
+ "plt.title(\"Payoff over the rounds\")\n",
+ "plt.xlabel(\"Rounds\")\n",
+ "plt.ylabel(\"Payoff at the end of each round\")\n",
+ "legend = [\"adversary 1\"]\n",
+ "plt.legend(legend)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Qtable.save(\"Qtable_guess132\")\n",
+ "\n",
+ "df1 = pd.DataFrame(opponent1_results)\n",
+ "#df2 = pd.DataFrame(opponent2_results)\n",
+ "\n",
+ "writer = pd.ExcelWriter('payoff_10.xlsx', engine='xlsxwriter')\n",
+ "df1.to_excel(writer, sheet_name='payoff_10', index=False)\n",
+ "#df2.to_excel(writer, sheet_name='payoff2', index=False)\n",
+ "writer.save()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# We now have the trained agent. We want to test it against each opponent individually, so that\n",
+ "# we can compare it against the agent that is just trained against this opponent. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Testing against one type of opponent by changing the * below to be the first number\n",
+ "adversary_probabilities[10]=1\n",
+ "result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ "payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "print(payoff)\n",
+ "print(adversary_payoff)\n",
+ "print(actions)\n",
+ "print(adversary_actions)\n",
+ "print(demand_potential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Testing against one type of opponent by changing the * below to be the first number\n",
+ "adversary_probabilities[11]=1\n",
+ "result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ "payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "print(payoff)\n",
+ "print(adversary_payoff)\n",
+ "print(actions)\n",
+ "print(adversary_actions)\n",
+ "print(demand_potential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.7"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Episodic_learning_with_memory/qLearningSimulations.ipynb b/qLearning/Episodic_learning_with_memory/qLearningSimulations.ipynb
new file mode 100644
index 0000000..9784326
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/qLearningSimulations.ipynb
@@ -0,0 +1,1388 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "import pandas as pd"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(11)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_demand = 400\n",
+ "agent_cost = 57\n",
+ "adversary_cost = 71 \n",
+ "costs = [agent_cost,adversary_cost]\n",
+ "total_stages = 25\n",
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Below is where we decide what adversaries we train against. See environment.py for the numbers\n",
+ "adversary_probabilities[3]= 0.5\n",
+ "adversary_probabilities[10] = 0.5\n",
+ "game = Model(total_demand, costs, total_stages, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2040816\n"
+ ]
+ }
+ ],
+ "source": [
+ "number_actions = 50\n",
+ "number_demands = total_demand + 1\n",
+ "discount_factor = 1\n",
+ "number_episodes = 100_000_000\n",
+ "constant = int(number_episodes/49)\n",
+ "print(constant)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+denominator)\n",
+ "Qtable = QTable(number_demands, number_actions, total_stages , learning_rate = [constant,constant])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, number_episodes, discount_factor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Round: 0 Errors: 0.22765260584495642\n",
+ "Current payoff against imitation_132 : 130390.0\n",
+ "Current payoff against guess_132 : 72659.0\n",
+ "Round: 5 Errors: 0.15171548618205044\n",
+ "Current payoff against imitation_132 : 131170.0\n",
+ "Current payoff against guess_132 : 101447.0\n",
+ "Round: 10 Errors: 0.10180678462202265\n",
+ "Current payoff against imitation_132 : 130140.0\n",
+ "Current payoff against guess_132 : 105181.0\n",
+ "Round: 15 Errors: 0.08699562465937928\n",
+ "Current payoff against imitation_132 : 131097.0\n",
+ "Current payoff against guess_132 : 99688.0\n",
+ "Round: 20 Errors: 0.08146668519691855\n",
+ "Current payoff against imitation_132 : 131077.0\n",
+ "Current payoff against guess_132 : 105613.0\n",
+ "Round: 25 Errors: 0.07175203174671972\n",
+ "Current payoff against imitation_132 : 131708.0\n",
+ "Current payoff against guess_132 : 104855.0\n",
+ "Round: 30 Errors: 0.0728718381065922\n",
+ "Current payoff against imitation_132 : 131708.0\n",
+ "Current payoff against guess_132 : 101946.0\n",
+ "Round: 35 Errors: 0.07150256021003719\n",
+ "Current payoff against imitation_132 : 131708.0\n",
+ "Current payoff against guess_132 : 103187.0\n",
+ "Round: 40 Errors: 0.07246618295691967\n",
+ "Current payoff against imitation_132 : 131708.0\n",
+ "Current payoff against guess_132 : 111262.0\n",
+ "Round: 45 Errors: 0.06775950489923696\n",
+ "Current payoff against imitation_132 : 131708.0\n",
+ "Current payoff against guess_132 : 110267.0\n",
+ "Round: 50 Errors: 0.06744021669483445\n",
+ "Current payoff against imitation_132 : 131708.0\n",
+ "Current payoff against guess_132 : 114561.0\n",
+ "Round: 55 Errors: 0.06596082294290537\n",
+ "Current payoff against imitation_132 : 131717.0\n",
+ "Current payoff against guess_132 : 90982.0\n",
+ "Round: 60 Errors: 0.06505101543732072\n",
+ "Current payoff against imitation_132 : 131708.0\n",
+ "Current payoff against guess_132 : 91583.0\n",
+ "Round: 65 Errors: 0.06744850616762721\n",
+ "Current payoff against imitation_132 : 131329.0\n",
+ "Current payoff against guess_132 : 91387.0\n",
+ "Round: 70 Errors: 0.0653426407095625\n",
+ "Current payoff against imitation_132 : 131320.0\n",
+ "Current payoff against guess_132 : 92437.0\n",
+ "Round: 75 Errors: 0.06534736217817116\n",
+ "Current payoff against imitation_132 : 131104.0\n",
+ "Current payoff against guess_132 : 92756.0\n",
+ "Round: 80 Errors: 0.06247899393197013\n",
+ "Current payoff against imitation_132 : 131127.0\n",
+ "Current payoff against guess_132 : 93153.0\n",
+ "Round: 85 Errors: 0.061356851274177185\n",
+ "Current payoff against imitation_132 : 131104.0\n",
+ "Current payoff against guess_132 : 92428.0\n"
+ ]
+ },
+ {
+ "ename": "KeyboardInterrupt",
+ "evalue": "",
+ "output_type": "error",
+ "traceback": [
+ "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m",
+ "\u001B[0;31mKeyboardInterrupt\u001B[0m Traceback (most recent call last)",
+ "\u001B[0;32m/var/folders/qp/vv6_63sd0n954kctm_7hhrhh0000gn/T/ipykernel_39685/3769875440.py\u001B[0m in \u001B[0;36m\u001B[0;34m\u001B[0m\n\u001B[1;32m 6\u001B[0m \u001B[0mopponent_results\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0;34m[\u001B[0m\u001B[0mlist\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m \u001B[0;32mfor\u001B[0m \u001B[0mmode\u001B[0m \u001B[0;32min\u001B[0m \u001B[0mAdversaryModes\u001B[0m\u001B[0;34m]\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 7\u001B[0m \u001B[0;32mfor\u001B[0m \u001B[0mround_\u001B[0m \u001B[0;32min\u001B[0m \u001B[0mrange\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mnumber_rounds\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m----> 8\u001B[0;31m \u001B[0malgorithm\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mcontinue_learning\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mnumber_episodes_per_round\u001B[0m\u001B[0;34m,\u001B[0m\u001B[0mnumber_episodes_per_round\u001B[0m \u001B[0;34m*\u001B[0m \u001B[0mround_\u001B[0m \u001B[0;34m+\u001B[0m\u001B[0;36m1\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 9\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 10\u001B[0m \u001B[0mresult\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mTest\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mgame\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mQtable\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mdiscount_factor\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0madversary_probabilities\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n",
+ "\u001B[0;32m~/Documents/GitHub/EquiLearn/qLearning/Episodic_learning_with_memory/learningAgent.py\u001B[0m in \u001B[0;36mcontinue_learning\u001B[0;34m(self, number_episodes, number_previous_episodes)\u001B[0m\n\u001B[1;32m 115\u001B[0m \u001B[0mdemand_index\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mint\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0magent_demand\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 116\u001B[0m \u001B[0maction_index\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0maction_index\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mmonopoly_price\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0maction\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 117\u001B[0;31m \u001B[0mstate\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mreward\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mdone\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0menv\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mstep\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mstate\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0maction\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0maction_index\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 118\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 119\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n",
+ "\u001B[0;32m~/Documents/GitHub/EquiLearn/qLearning/Episodic_learning_with_memory/environment.py\u001B[0m in \u001B[0;36mstep\u001B[0;34m(self, state, action, action_index)\u001B[0m\n\u001B[1;32m 228\u001B[0m \u001B[0;34m-\u001B[0m \u001B[0mstate\u001B[0m\u001B[0;34m:\u001B[0m \u001B[0mtupple\u001B[0m \u001B[0;32min\u001B[0m \u001B[0mthe\u001B[0m \u001B[0mlatest\u001B[0m \u001B[0mstage\u001B[0m \u001B[0;34m(\u001B[0m\u001B[0mstage\u001B[0m \u001B[0;34m,\u001B[0m\u001B[0mDemand\u001B[0m \u001B[0mPotential\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mAdversary\u001B[0m \u001B[0mAction\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 229\u001B[0m \"\"\"\n\u001B[0;32m--> 230\u001B[0;31m \u001B[0madversary_action\u001B[0m \u001B[0;34m=\u001B[0m \u001B[0mint\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0madversary_choose_price\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 231\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mupdate_prices_profit_demand\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0;34m[\u001B[0m\u001B[0maction\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0madversary_action\u001B[0m\u001B[0;34m]\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 232\u001B[0m \u001B[0;34m\u001B[0m\u001B[0m\n",
+ "\u001B[0;32m~/Documents/GitHub/EquiLearn/qLearning/Episodic_learning_with_memory/environment.py\u001B[0m in \u001B[0;36madversary_choose_price\u001B[0;34m(self)\u001B[0m\n\u001B[1;32m 216\u001B[0m \u001B[0;32melif\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0madversary_mode\u001B[0m \u001B[0;34m==\u001B[0m \u001B[0mAdversaryModes\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mguess_125\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 217\u001B[0m \u001B[0;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mfight\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mplayer\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;36m1\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mfirstprice\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;36m125\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0;32m--> 218\u001B[0;31m \u001B[0;32melif\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0madversary_mode\u001B[0m \u001B[0;34m==\u001B[0m \u001B[0mAdversaryModes\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mguess_132\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[0m\u001B[1;32m 219\u001B[0m \u001B[0;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[0;34m.\u001B[0m\u001B[0mfight\u001B[0m\u001B[0;34m(\u001B[0m\u001B[0mplayer\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;36m1\u001B[0m\u001B[0;34m,\u001B[0m \u001B[0mfirstprice\u001B[0m\u001B[0;34m=\u001B[0m\u001B[0;36m132\u001B[0m\u001B[0;34m)\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n\u001B[1;32m 220\u001B[0m \u001B[0;32melse\u001B[0m\u001B[0;34m:\u001B[0m\u001B[0;34m\u001B[0m\u001B[0;34m\u001B[0m\u001B[0m\n",
+ "\u001B[0;31mKeyboardInterrupt\u001B[0m: "
+ ]
+ }
+ ],
+ "source": [
+ "# Below is the first stage of learning: actions are chosen randomly.\n",
+ "number_episodes_per_round = 100_000\n",
+ "number_rounds = int(number_episodes / number_episodes_per_round)\n",
+ "errors = np.zeros(number_rounds)\n",
+ "final_round = 0\n",
+ "opponent_results = [list() for mode in AdversaryModes]\n",
+ "for round_ in range(number_rounds):\n",
+ " algorithm.continue_learning(number_episodes_per_round,number_episodes_per_round * round_ +1)\n",
+ "\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " errors[round_] = result.error(1000)\n",
+ " if errors[round_] < 0.01 or (round_ * number_episodes_per_round > 0.1 * number_episodes):\n",
+ " print(round_)\n",
+ " final_round = round_\n",
+ " break\n",
+ " if round_ % 5 == 0:\n",
+ " print(\"Round:\", round_, \"Errors:\", errors[round_])\n",
+ "\n",
+ " for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " new_adversary_probabilities =[0]*len(AdversaryModes)\n",
+ " new_adversary_probabilities[index] = 1\n",
+ " result = Test(game, Qtable, discount_factor, new_adversary_probabilities)\n",
+ " payoff, _, _, _, _ = result.total_payoff()\n",
+ " opponent_results[index].append(payoff)\n",
+ " if round_ % 5 == 0:\n",
+ " print('Current payoff against', adversary.name, \":\" , payoff)\n",
+ "\n",
+ " if round_ == number_rounds - 1:\n",
+ " final_round = round_\n",
+ " \n",
+ "plt.plot(errors[0:final_round+1])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Round 0 of 199\n",
+ "Best payoff: 136458\n",
+ "Best actions: [118, 131, 128, 126, 123, 121, 121, 119, 119, 119, 119, 120, 119, 119, 117, 119, 118, 119, 123, 115, 118, 122, 114, 112, 131]\n",
+ "Current payoff against imitation_132 : 122143.0\n",
+ "Current payoff against guess_132 : 135123.0\n",
+ "Round 1 of 199\n",
+ "Best payoff: 136691\n",
+ "Best actions: [118, 131, 128, 127, 122, 124, 120, 118, 119, 120, 120, 120, 120, 121, 117, 120, 120, 121, 122, 115, 121, 120, 117, 116, 133]\n",
+ "Current payoff against imitation_132 : 127842.0\n",
+ "Current payoff against guess_132 : 135931.0\n",
+ "Round 2 of 199\n",
+ "Best payoff: 137086\n",
+ "Best actions: [118, 132, 131, 128, 126, 123, 124, 118, 121, 120, 120, 121, 122, 118, 122, 118, 120, 121, 119, 119, 116, 116, 117, 113, 133]\n",
+ "Current payoff against imitation_132 : 127203.0\n",
+ "Current payoff against guess_132 : 136922.0\n",
+ "Round 3 of 199\n",
+ "Best payoff: 137356\n",
+ "Best actions: [118, 132, 132, 131, 128, 126, 123, 125, 119, 120, 120, 120, 120, 120, 121, 120, 121, 122, 123, 119, 120, 118, 116, 116, 132]\n",
+ "Current payoff against imitation_132 : 123985.0\n",
+ "Current payoff against guess_132 : 137048.0\n",
+ "Round 4 of 199\n",
+ "Best payoff: 137826\n",
+ "Best actions: [118, 131, 131, 131, 132, 127, 125, 124, 123, 123, 123, 123, 124, 120, 124, 121, 124, 124, 122, 125, 116, 121, 121, 112, 133]\n",
+ "Current payoff against imitation_132 : 128954.0\n",
+ "Current payoff against guess_132 : 136664.0\n",
+ "Round 5 of 199\n",
+ "Best payoff: 137900\n",
+ "Best actions: [118, 132, 132, 132, 132, 128, 128, 124, 124, 124, 124, 124, 123, 125, 122, 123, 121, 125, 115, 119, 118, 121, 118, 113, 133]\n",
+ "Current payoff against imitation_132 : 127039.0\n",
+ "Current payoff against guess_132 : 137785.0\n",
+ "Round 6 of 199\n",
+ "Best payoff: 138339\n",
+ "Best actions: [118, 131, 132, 131, 132, 132, 128, 128, 124, 124, 124, 124, 124, 123, 123, 123, 124, 121, 121, 118, 118, 121, 116, 115, 133]\n",
+ "Current payoff against imitation_132 : 125952.0\n",
+ "Current payoff against guess_132 : 138060.0\n",
+ "Round 7 of 199\n",
+ "Best payoff: 138186\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 128, 128, 124, 126, 122, 124, 124, 123, 124, 123, 123, 121, 121, 120, 117, 121, 116, 116, 131]\n",
+ "Current payoff against imitation_132 : 128920.0\n",
+ "Current payoff against guess_132 : 137903.0\n",
+ "Round 8 of 199\n",
+ "Best payoff: 138554\n",
+ "Best actions: [118, 131, 132, 131, 131, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 122, 120, 120, 117, 118, 118, 112, 133]\n",
+ "Current payoff against imitation_132 : 127291.0\n",
+ "Current payoff against guess_132 : 137811.0\n",
+ "Round 9 of 199\n",
+ "Best payoff: 138584\n",
+ "Best actions: [118, 132, 132, 131, 131, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 122, 120, 120, 118, 118, 118, 112, 133]\n",
+ "Current payoff against imitation_132 : 126430.0\n",
+ "Current payoff against guess_132 : 138121.0\n",
+ "Round 10 of 199\n",
+ "Best payoff: 138585\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 122, 120, 120, 118, 118, 118, 112, 133]\n",
+ "Current payoff against imitation_132 : 129111.0\n",
+ "Current payoff against guess_132 : 138379.0\n",
+ "Round 11 of 199\n",
+ "Best payoff: 138570\n",
+ "Best actions: [118, 132, 131, 132, 131, 132, 128, 126, 125, 124, 124, 124, 124, 124, 124, 124, 124, 122, 120, 120, 118, 118, 118, 112, 133]\n",
+ "Current payoff against imitation_132 : 130581.0\n",
+ "Current payoff against guess_132 : 138392.0\n",
+ "Round 12 of 199\n",
+ "Best payoff: 138654\n",
+ "Best actions: [118, 132, 132, 132, 131, 131, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 125, 121, 126, 120, 119, 118, 112, 133]\n",
+ "Current payoff against imitation_132 : 126624.0\n",
+ "Current payoff against guess_132 : 138485.0\n",
+ "Round 13 of 199\n",
+ "Best payoff: 138599\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 128, 126, 125, 123, 124, 124, 124, 124, 124, 124, 124, 122, 122, 120, 119, 119, 121, 116, 132]\n",
+ "Current payoff against imitation_132 : 120140.0\n",
+ "Current payoff against guess_132 : 138412.0\n",
+ "Round 14 of 199\n",
+ "Best payoff: 138609\n",
+ "Best actions: [118, 132, 132, 131, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 122, 122, 120, 122, 118, 121, 116, 131]\n",
+ "Current payoff against imitation_132 : 127373.0\n",
+ "Current payoff against guess_132 : 138297.0\n",
+ "Round 15 of 199\n",
+ "Best payoff: 138798\n",
+ "Best actions: [120, 129, 132, 131, 131, 131, 129, 127, 124, 125, 125, 125, 124, 124, 126, 123, 124, 125, 126, 125, 122, 126, 125, 116, 133]\n",
+ "Current payoff against imitation_132 : 123514.0\n",
+ "Current payoff against guess_132 : 137968.0\n",
+ "Round 16 of 199\n",
+ "Best payoff: 138751\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 128, 127, 124, 124, 124, 124, 124, 124, 124, 124, 124, 123, 126, 120, 120, 118, 114, 133]\n",
+ "Current payoff against imitation_132 : 126186.0\n",
+ "Current payoff against guess_132 : 138666.0\n",
+ "Round 17 of 199\n",
+ "Best payoff: 138852\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 130, 127, 124, 124, 125, 124, 125, 124, 125, 125, 125, 126, 122, 130, 119, 120, 112, 134]\n",
+ "Current payoff against imitation_132 : 125643.0\n",
+ "Current payoff against guess_132 : 138796.0\n",
+ "Round 18 of 199\n",
+ "Best payoff: 138890\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 128, 126, 125, 124, 124, 124, 124, 124, 124, 124, 124, 126, 121, 121, 121, 119, 111, 134]\n",
+ "Current payoff against imitation_132 : 124365.0\n",
+ "Current payoff against guess_132 : 138766.0\n",
+ "Round 19 of 199\n",
+ "Best payoff: 139148\n",
+ "Best actions: [118, 131, 131, 132, 131, 132, 131, 128, 126, 125, 123, 124, 124, 124, 124, 124, 124, 124, 123, 126, 122, 126, 122, 114, 134]\n",
+ "Current payoff against imitation_132 : 127625.0\n",
+ "Current payoff against guess_132 : 138672.0\n",
+ "Round 20 of 199\n",
+ "Best payoff: 139172\n",
+ "Best actions: [118, 131, 132, 132, 132, 131, 131, 128, 126, 125, 124, 124, 124, 124, 124, 124, 124, 124, 123, 123, 123, 125, 121, 114, 134]\n",
+ "Current payoff against imitation_132 : 126592.0\n",
+ "Current payoff against guess_132 : 138743.0\n",
+ "Round 21 of 199\n",
+ "Best payoff: 139186\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 128, 127, 124, 124, 124, 124, 124, 124, 124, 124, 124, 123, 123, 125, 121, 114, 134]\n",
+ "Current payoff against imitation_132 : 127125.0\n",
+ "Current payoff against guess_132 : 139092.0\n",
+ "Round 22 of 199\n",
+ "Best payoff: 139304\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 125, 121, 114, 134]\n",
+ "Current payoff against imitation_132 : 124351.0\n",
+ "Current payoff against guess_132 : 139249.0\n",
+ "Round 23 of 199\n",
+ "Best payoff: 139303\n",
+ "Best actions: [118, 132, 132, 131, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 125, 121, 114, 134]\n",
+ "Current payoff against imitation_132 : 120498.0\n",
+ "Current payoff against guess_132 : 138200.0\n",
+ "Round 24 of 199\n",
+ "Best payoff: 139305\n",
+ "Best actions: [118, 132, 132, 132, 131, 131, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 126, 112, 134]\n",
+ "Current payoff against imitation_132 : 124453.0\n",
+ "Current payoff against guess_132 : 139094.0\n",
+ "Round 25 of 199\n",
+ "Best payoff: 139373\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 125, 124, 124, 125, 125, 124, 124, 124, 124, 125, 112, 134]\n",
+ "Current payoff against imitation_132 : 122555.0\n",
+ "Current payoff against guess_132 : 138940.0\n",
+ "Round 26 of 199\n",
+ "Best payoff: 139412\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 130, 126, 125, 125, 125, 124, 125, 125, 125, 124, 124, 124, 124, 123, 113, 134]\n",
+ "Current payoff against imitation_132 : 120775.0\n",
+ "Current payoff against guess_132 : 139367.0\n",
+ "Round 27 of 199\n",
+ "Best payoff: 139472\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 124, 125, 125, 125, 124, 124, 124, 124, 125, 115, 134]\n",
+ "Current payoff against imitation_132 : 128536.0\n",
+ "Current payoff against guess_132 : 139186.0\n",
+ "Round 28 of 199\n",
+ "Best payoff: 139472\n",
+ "Best actions: [118, 132, 131, 131, 131, 132, 132, 132, 131, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123605.0\n",
+ "Current payoff against guess_132 : 139369.0\n",
+ "Round 29 of 199\n",
+ "Best payoff: 139476\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123944.0\n",
+ "Current payoff against guess_132 : 139402.0\n",
+ "Round 30 of 199\n",
+ "Best payoff: 139476\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123292.0\n",
+ "Current payoff against guess_132 : 139322.0\n",
+ "Round 31 of 199\n",
+ "Best payoff: 139476\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 118311.0\n",
+ "Current payoff against guess_132 : 139471.0\n",
+ "Round 32 of 199\n",
+ "Best payoff: 139476\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126812.0\n",
+ "Current payoff against guess_132 : 138929.0\n",
+ "Round 33 of 199\n",
+ "Best payoff: 139476\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125605.0\n",
+ "Current payoff against guess_132 : 139317.0\n",
+ "Round 34 of 199\n",
+ "Best payoff: 139524\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 126, 125, 125, 124, 125, 125, 125, 124, 125, 124, 124, 125, 115, 134]\n",
+ "Current payoff against imitation_132 : 127822.0\n",
+ "Current payoff against guess_132 : 139509.0\n",
+ "Round 35 of 199\n",
+ "Best payoff: 139509\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 126, 125, 125, 124, 125, 125, 125, 124, 124, 124, 124, 125, 115, 134]\n",
+ "Current payoff against imitation_132 : 129368.0\n",
+ "Current payoff against guess_132 : 139509.0\n",
+ "Round 36 of 199\n",
+ "Best payoff: 139566\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 124, 124, 125, 125, 125, 115, 134]\n",
+ "Current payoff against imitation_132 : 128816.0\n",
+ "Current payoff against guess_132 : 139551.0\n",
+ "Round 37 of 199\n",
+ "Best payoff: 139566\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 124, 124, 125, 125, 125, 115, 134]\n",
+ "Current payoff against imitation_132 : 125182.0\n",
+ "Current payoff against guess_132 : 139516.0\n",
+ "Round 38 of 199\n",
+ "Best payoff: 139581\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 125, 124, 125, 125, 125, 115, 134]\n",
+ "Current payoff against imitation_132 : 124683.0\n",
+ "Current payoff against guess_132 : 139536.0\n",
+ "Round 39 of 199\n",
+ "Best payoff: 139579\n",
+ "Best actions: [118, 132, 132, 131, 132, 132, 132, 131, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 125, 124, 125, 125, 125, 115, 134]\n",
+ "Current payoff against imitation_132 : 128068.0\n",
+ "Current payoff against guess_132 : 139505.0\n",
+ "Round 40 of 199\n",
+ "Best payoff: 139581\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 125, 124, 125, 125, 125, 115, 134]\n",
+ "Current payoff against imitation_132 : 129110.0\n",
+ "Current payoff against guess_132 : 139507.0\n",
+ "Round 41 of 199\n",
+ "Best payoff: 139581\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 125, 124, 125, 125, 125, 115, 134]\n",
+ "Current payoff against imitation_132 : 124835.0\n",
+ "Current payoff against guess_132 : 139466.0\n",
+ "Round 42 of 199\n",
+ "Best payoff: 139526\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 125, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125394.0\n",
+ "Current payoff against guess_132 : 139318.0\n",
+ "Round 43 of 199\n",
+ "Best payoff: 139587\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 132, 130, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 111, 135]\n",
+ "Current payoff against imitation_132 : 125711.0\n",
+ "Current payoff against guess_132 : 139526.0\n",
+ "Round 44 of 199\n",
+ "Best payoff: 139599\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 131, 130, 127, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 111, 135]\n",
+ "Current payoff against imitation_132 : 129194.0\n",
+ "Current payoff against guess_132 : 139217.0\n",
+ "Round 45 of 199\n",
+ "Best payoff: 139525\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 132, 128, 126, 125, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125109.0\n",
+ "Current payoff against guess_132 : 139505.0\n",
+ "Round 46 of 199\n",
+ "Best payoff: 139585\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 125, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 111, 135]\n",
+ "Current payoff against imitation_132 : 124178.0\n",
+ "Current payoff against guess_132 : 138917.0\n",
+ "Round 47 of 199\n",
+ "Best payoff: 139582\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 131, 131, 130, 127, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 111, 135]\n",
+ "Current payoff against imitation_132 : 125358.0\n",
+ "Current payoff against guess_132 : 139213.0\n",
+ "Round 48 of 199\n",
+ "Best payoff: 139635\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 132, 132, 132, 131, 130, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 111, 135]\n",
+ "Current payoff against imitation_132 : 126663.0\n",
+ "Current payoff against guess_132 : 139170.0\n",
+ "Round 49 of 199\n",
+ "Best payoff: 139637\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 111, 135]\n",
+ "Current payoff against imitation_132 : 128580.0\n",
+ "Current payoff against guess_132 : 139636.0\n",
+ "Round 50 of 199\n",
+ "Best payoff: 139638\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 130, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 125466.0\n",
+ "Current payoff against guess_132 : 139638.0\n",
+ "Round 51 of 199\n",
+ "Best payoff: 139645\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 129, 127, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 123245.0\n",
+ "Current payoff against guess_132 : 139531.0\n",
+ "Round 52 of 199\n",
+ "Best payoff: 139642\n",
+ "Best actions: [118, 132, 132, 131, 132, 132, 132, 131, 132, 131, 131, 129, 127, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 128415.0\n",
+ "Current payoff against guess_132 : 139530.0\n",
+ "Round 53 of 199\n",
+ "Best payoff: 139641\n",
+ "Best actions: [118, 131, 131, 131, 132, 131, 132, 132, 132, 132, 131, 129, 127, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 124285.0\n",
+ "Current payoff against guess_132 : 139588.0\n",
+ "Round 54 of 199\n",
+ "Best payoff: 139629\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 131, 131, 129, 127, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 126317.0\n",
+ "Current payoff against guess_132 : 139482.0\n",
+ "Round 55 of 199\n",
+ "Best payoff: 139602\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 132, 132, 132, 131, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126808.0\n",
+ "Current payoff against guess_132 : 139419.0\n",
+ "Round 56 of 199\n",
+ "Best payoff: 139642\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 131, 132, 131, 131, 129, 127, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 123863.0\n",
+ "Current payoff against guess_132 : 139469.0\n",
+ "Round 57 of 199\n",
+ "Best payoff: 139604\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 128228.0\n",
+ "Current payoff against guess_132 : 139180.0\n",
+ "Round 58 of 199\n",
+ "Best payoff: 139630\n",
+ "Best actions: [118, 132, 132, 132, 131, 131, 132, 132, 132, 131, 131, 129, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 127624.0\n",
+ "Current payoff against guess_132 : 139380.0\n",
+ "Round 59 of 199\n",
+ "Best payoff: 139649\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 131, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 123537.0\n",
+ "Current payoff against guess_132 : 139508.0\n",
+ "Round 60 of 199\n",
+ "Best payoff: 139598\n",
+ "Best actions: [118, 132, 131, 132, 131, 132, 131, 131, 131, 131, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 128063.0\n",
+ "Current payoff against guess_132 : 139529.0\n",
+ "Round 61 of 199\n",
+ "Best payoff: 139645\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 129, 127, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 126167.0\n",
+ "Current payoff against guess_132 : 139278.0\n",
+ "Round 62 of 199\n",
+ "Best payoff: 139644\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 132, 131, 132, 132, 129, 127, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 121983.0\n",
+ "Current payoff against guess_132 : 139449.0\n",
+ "Round 63 of 199\n",
+ "Best payoff: 139632\n",
+ "Best actions: [118, 132, 131, 132, 132, 131, 132, 131, 131, 132, 132, 130, 127, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 126203.0\n",
+ "Current payoff against guess_132 : 139531.0\n",
+ "Round 64 of 199\n",
+ "Best payoff: 139647\n",
+ "Best actions: [118, 131, 132, 131, 131, 132, 132, 132, 132, 132, 131, 130, 127, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 127493.0\n",
+ "Current payoff against guess_132 : 139182.0\n",
+ "Round 65 of 199\n",
+ "Best payoff: 139606\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 122518.0\n",
+ "Current payoff against guess_132 : 139293.0\n",
+ "Round 66 of 199\n",
+ "Best payoff: 139647\n",
+ "Best actions: [118, 131, 132, 131, 131, 131, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 120403.0\n",
+ "Current payoff against guess_132 : 139494.0\n",
+ "Round 67 of 199\n",
+ "Best payoff: 139651\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 124736.0\n",
+ "Current payoff against guess_132 : 139589.0\n",
+ "Round 68 of 199\n",
+ "Best payoff: 139651\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 128771.0\n",
+ "Current payoff against guess_132 : 139483.0\n",
+ "Round 69 of 199\n",
+ "Best payoff: 139683\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 129, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 123244.0\n",
+ "Current payoff against guess_132 : 139682.0\n",
+ "Round 70 of 199\n",
+ "Best payoff: 139682\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 132, 129, 126, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 127031.0\n",
+ "Current payoff against guess_132 : 139594.0\n",
+ "Round 71 of 199\n",
+ "Best payoff: 139595\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 128, 124, 124, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 127266.0\n",
+ "Current payoff against guess_132 : 139573.0\n",
+ "Round 72 of 199\n",
+ "Best payoff: 139683\n",
+ "Best actions: [118, 132, 132, 131, 132, 132, 132, 132, 132, 132, 131, 132, 130, 127, 124, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 127006.0\n",
+ "Current payoff against guess_132 : 139505.0\n",
+ "Round 73 of 199\n",
+ "Best payoff: 139653\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 132, 128, 126, 125, 124, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 127792.0\n",
+ "Current payoff against guess_132 : 139395.0\n",
+ "Round 74 of 199\n",
+ "Best payoff: 139699\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 128250.0\n",
+ "Current payoff against guess_132 : 139468.0\n",
+ "Round 75 of 199\n",
+ "Best payoff: 139544\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 125, 125, 123, 123, 123, 123, 123, 123, 123, 113, 134]\n",
+ "Current payoff against imitation_132 : 125134.0\n",
+ "Current payoff against guess_132 : 139525.0\n",
+ "Round 76 of 199\n",
+ "Best payoff: 139642\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 131, 131, 132, 132, 132, 131, 130, 128, 123, 124, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 129190.0\n",
+ "Current payoff against guess_132 : 139095.0\n",
+ "Round 77 of 199\n",
+ "Best payoff: 139733\n",
+ "Best actions: [118, 132, 132, 131, 132, 131, 132, 131, 132, 131, 132, 132, 132, 130, 126, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 119770.0\n",
+ "Current payoff against guess_132 : 138801.0\n",
+ "Round 78 of 199\n",
+ "Best payoff: 139736\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 130, 126, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 121474.0\n",
+ "Current payoff against guess_132 : 139353.0\n",
+ "Round 79 of 199\n",
+ "Best payoff: 139716\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 131, 132, 128, 126, 125, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123258.0\n",
+ "Current payoff against guess_132 : 139716.0\n",
+ "Round 80 of 199\n",
+ "Best payoff: 139717\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 128, 126, 125, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125525.0\n",
+ "Current payoff against guess_132 : 138823.0\n",
+ "Round 81 of 199\n",
+ "Best payoff: 139744\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 131, 132, 131, 132, 131, 131, 130, 127, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 118969.0\n",
+ "Current payoff against guess_132 : 139347.0\n",
+ "Round 82 of 199\n",
+ "Best payoff: 139732\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 119748.0\n",
+ "Current payoff against guess_132 : 139658.0\n",
+ "Round 83 of 199\n",
+ "Best payoff: 139732\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 128472.0\n",
+ "Current payoff against guess_132 : 139715.0\n",
+ "Round 84 of 199\n",
+ "Best payoff: 139743\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 132, 129, 127, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 125625.0\n",
+ "Current payoff against guess_132 : 139589.0\n",
+ "Round 85 of 199\n",
+ "Best payoff: 139748\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 124339.0\n",
+ "Current payoff against guess_132 : 139674.0\n",
+ "Round 86 of 199\n",
+ "Best payoff: 139748\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 122685.0\n",
+ "Current payoff against guess_132 : 139540.0\n",
+ "Round 87 of 199\n",
+ "Best payoff: 139718\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 125, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124946.0\n",
+ "Current payoff against guess_132 : 139571.0\n",
+ "Round 88 of 199\n",
+ "Best payoff: 139732\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122323.0\n",
+ "Current payoff against guess_132 : 139203.0\n",
+ "Round 89 of 199\n",
+ "Best payoff: 139732\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126117.0\n",
+ "Current payoff against guess_132 : 139716.0\n",
+ "Round 90 of 199\n",
+ "Best payoff: 139743\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 132, 129, 127, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 126564.0\n",
+ "Current payoff against guess_132 : 139725.0\n",
+ "Round 91 of 199\n",
+ "Best payoff: 139732\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 127477.0\n",
+ "Current payoff against guess_132 : 139471.0\n",
+ "Round 92 of 199\n",
+ "Best payoff: 139745\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 131, 132, 132, 132, 131, 131, 130, 127, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 124436.0\n",
+ "Current payoff against guess_132 : 139458.0\n",
+ "Round 93 of 199\n",
+ "Best payoff: 139747\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 131, 130, 127, 125, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 125974.0\n",
+ "Current payoff against guess_132 : 139243.0\n",
+ "Round 94 of 199\n",
+ "Best payoff: 139732\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123308.0\n",
+ "Current payoff against guess_132 : 139198.0\n",
+ "Round 95 of 199\n",
+ "Best payoff: 139734\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 124, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 128062.0\n",
+ "Current payoff against guess_132 : 139304.0\n",
+ "Round 96 of 199\n",
+ "Best payoff: 139713\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 126, 126, 123, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122276.0\n",
+ "Current payoff against guess_132 : 139435.0\n",
+ "Round 97 of 199\n",
+ "Best payoff: 139617\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 127, 125, 125, 123, 123, 123, 123, 123, 123, 113, 134]\n",
+ "Current payoff against imitation_132 : 121982.0\n",
+ "Current payoff against guess_132 : 139340.0\n",
+ "Round 98 of 199\n",
+ "Best payoff: 139623\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 131, 131, 132, 128, 125, 125, 123, 123, 123, 123, 123, 123, 113, 134]\n",
+ "Current payoff against imitation_132 : 120427.0\n",
+ "Current payoff against guess_132 : 139590.0\n",
+ "Round 99 of 199\n",
+ "Best payoff: 139694\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 128, 127, 123, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123676.0\n",
+ "Current payoff against guess_132 : 139550.0\n",
+ "Round 100 of 199\n",
+ "Best payoff: 139624\n",
+ "Best actions: [118, 132, 131, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 128, 125, 125, 123, 123, 123, 123, 123, 123, 113, 134]\n",
+ "Current payoff against imitation_132 : 127683.0\n",
+ "Current payoff against guess_132 : 139590.0\n",
+ "Round 101 of 199\n",
+ "Best payoff: 139780\n",
+ "Best actions: [118, 132, 132, 131, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 128, 126, 125, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124751.0\n",
+ "Current payoff against guess_132 : 139780.0\n",
+ "Round 102 of 199\n",
+ "Best payoff: 139782\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 125, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 127660.0\n",
+ "Current payoff against guess_132 : 139781.0\n",
+ "Round 103 of 199\n",
+ "Best payoff: 139782\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 125, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 120241.0\n",
+ "Current payoff against guess_132 : 139374.0\n",
+ "Round 104 of 199\n",
+ "Best payoff: 139798\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 124375.0\n",
+ "Current payoff against guess_132 : 139480.0\n",
+ "Round 105 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 128495.0\n",
+ "Current payoff against guess_132 : 139776.0\n",
+ "Round 106 of 199\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 119897.0\n",
+ "Current payoff against guess_132 : 139793.0\n",
+ "Round 107 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125202.0\n",
+ "Current payoff against guess_132 : 139311.0\n",
+ "Round 108 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 128201.0\n",
+ "Current payoff against guess_132 : 139478.0\n",
+ "Round 109 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 118184.0\n",
+ "Current payoff against guess_132 : 139709.0\n",
+ "Round 110 of 199\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 120887.0\n",
+ "Current payoff against guess_132 : 139687.0\n",
+ "Round 111 of 199\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123493.0\n",
+ "Current payoff against guess_132 : 139623.0\n",
+ "Round 112 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 130, 127, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 127457.0\n",
+ "Current payoff against guess_132 : 139720.0\n",
+ "Round 113 of 199\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122835.0\n",
+ "Current payoff against guess_132 : 139538.0\n",
+ "Round 114 of 199\n",
+ "Best payoff: 139794\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 131, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 120283.0\n",
+ "Current payoff against guess_132 : 139721.0\n",
+ "Round 115 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123588.0\n",
+ "Current payoff against guess_132 : 139600.0\n",
+ "Round 116 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123233.0\n",
+ "Current payoff against guess_132 : 139591.0\n",
+ "Round 117 of 199\n",
+ "Best payoff: 139697\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 128, 121, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 127878.0\n",
+ "Current payoff against guess_132 : 139636.0\n",
+ "Round 118 of 199\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 120332.0\n",
+ "Current payoff against guess_132 : 139740.0\n",
+ "Round 119 of 199\n",
+ "Best payoff: 139794\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 131, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121547.0\n",
+ "Current payoff against guess_132 : 139488.0\n",
+ "Round 120 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 127236.0\n",
+ "Current payoff against guess_132 : 139649.0\n",
+ "Round 121 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123551.0\n",
+ "Current payoff against guess_132 : 139317.0\n",
+ "Round 122 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 117272.0\n",
+ "Current payoff against guess_132 : 139761.0\n",
+ "Round 123 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 120416.0\n",
+ "Current payoff against guess_132 : 139522.0\n",
+ "Round 124 of 199\n",
+ "Best payoff: 139722\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 128, 128, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126811.0\n",
+ "Current payoff against guess_132 : 139722.0\n",
+ "Round 125 of 199\n",
+ "Best payoff: 139797\n",
+ "Best actions: [118, 132, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 124396.0\n",
+ "Current payoff against guess_132 : 139644.0\n",
+ "Round 126 of 199\n",
+ "Best payoff: 139794\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 131, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124955.0\n",
+ "Current payoff against guess_132 : 139687.0\n",
+ "Round 127 of 199\n",
+ "Best payoff: 139706\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 128, 126, 127, 122, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126845.0\n",
+ "Current payoff against guess_132 : 139547.0\n",
+ "Round 128 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121342.0\n",
+ "Current payoff against guess_132 : 139774.0\n",
+ "Round 129 of 199\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124208.0\n",
+ "Current payoff against guess_132 : 139302.0\n",
+ "Round 130 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124642.0\n",
+ "Current payoff against guess_132 : 139730.0\n",
+ "Round 131 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 129831.0\n",
+ "Current payoff against guess_132 : 139790.0\n",
+ "Round 132 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126858.0\n",
+ "Current payoff against guess_132 : 139591.0\n",
+ "Round 133 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124900.0\n",
+ "Current payoff against guess_132 : 139761.0\n",
+ "Round 134 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124346.0\n",
+ "Current payoff against guess_132 : 139722.0\n",
+ "Round 135 of 199\n",
+ "Best payoff: 139764\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 125, 123, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125885.0\n",
+ "Current payoff against guess_132 : 139376.0\n",
+ "Round 136 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123267.0\n",
+ "Current payoff against guess_132 : 139658.0\n",
+ "Round 137 of 199\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125430.0\n",
+ "Current payoff against guess_132 : 139793.0\n",
+ "Round 138 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122216.0\n",
+ "Current payoff against guess_132 : 139718.0\n",
+ "Round 139 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124386.0\n",
+ "Current payoff against guess_132 : 139164.0\n",
+ "Round 140 of 199\n",
+ "Best payoff: 139797\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 130, 127, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 127861.0\n",
+ "Current payoff against guess_132 : 139454.0\n",
+ "Round 141 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122956.0\n",
+ "Current payoff against guess_132 : 139326.0\n",
+ "Round 142 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126908.0\n",
+ "Current payoff against guess_132 : 139726.0\n",
+ "Round 143 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122069.0\n",
+ "Current payoff against guess_132 : 139537.0\n",
+ "Round 144 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126233.0\n",
+ "Current payoff against guess_132 : 139723.0\n",
+ "Round 145 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124890.0\n",
+ "Current payoff against guess_132 : 139659.0\n",
+ "Round 146 of 199\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122015.0\n",
+ "Current payoff against guess_132 : 139676.0\n",
+ "Round 147 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123397.0\n",
+ "Current payoff against guess_132 : 139706.0\n",
+ "Round 148 of 199\n",
+ "Best payoff: 139794\n",
+ "Best actions: [118, 132, 132, 131, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124283.0\n",
+ "Current payoff against guess_132 : 139722.0\n",
+ "Round 149 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124896.0\n",
+ "Current payoff against guess_132 : 139694.0\n",
+ "Round 150 of 199\n",
+ "Best payoff: 139782\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 125, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124759.0\n",
+ "Current payoff against guess_132 : 139706.0\n",
+ "Round 151 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124733.0\n",
+ "Current payoff against guess_132 : 139695.0\n",
+ "Round 152 of 199\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126031.0\n",
+ "Current payoff against guess_132 : 139481.0\n",
+ "Round 153 of 199\n",
+ "Best payoff: 139792\n",
+ "Best actions: [118, 131, 132, 132, 131, 131, 132, 132, 132, 132, 132, 132, 131, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122606.0\n",
+ "Current payoff against guess_132 : 139548.0\n",
+ "Round 154 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 119997.0\n",
+ "Current payoff against guess_132 : 139656.0\n",
+ "Round 155 of 199\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 127244.0\n",
+ "Current payoff against guess_132 : 139495.0\n",
+ "Round 156 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122678.0\n",
+ "Current payoff against guess_132 : 139554.0\n",
+ "Round 157 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122730.0\n",
+ "Current payoff against guess_132 : 139273.0\n",
+ "Round 158 of 199\n",
+ "Best payoff: 139794\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 131, 131, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126882.0\n",
+ "Current payoff against guess_132 : 139723.0\n",
+ "Round 159 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123769.0\n",
+ "Current payoff against guess_132 : 139674.0\n",
+ "Round 160 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124264.0\n",
+ "Current payoff against guess_132 : 139687.0\n",
+ "Round 161 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124742.0\n",
+ "Current payoff against guess_132 : 139667.0\n",
+ "Round 162 of 199\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126557.0\n",
+ "Current payoff against guess_132 : 139333.0\n",
+ "Round 163 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125815.0\n",
+ "Current payoff against guess_132 : 139649.0\n",
+ "Round 164 of 199\n",
+ "Best payoff: 139688\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 132, 132, 128, 128, 124, 123, 123, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 128252.0\n",
+ "Current payoff against guess_132 : 139649.0\n",
+ "Round 165 of 199\n",
+ "Best payoff: 139649\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 132, 132, 128, 128, 124, 126, 122, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 127185.0\n",
+ "Current payoff against guess_132 : 139649.0\n",
+ "Round 166 of 199\n",
+ "Best payoff: 139723\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 128, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126977.0\n",
+ "Current payoff against guess_132 : 139723.0\n",
+ "Round 167 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125740.0\n",
+ "Current payoff against guess_132 : 139686.0\n",
+ "Round 168 of 199\n",
+ "Best payoff: 139764\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 132, 128, 126, 125, 123, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123776.0\n",
+ "Current payoff against guess_132 : 139612.0\n",
+ "Round 169 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 127380.0\n",
+ "Current payoff against guess_132 : 139566.0\n",
+ "Round 170 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 127009.0\n",
+ "Current payoff against guess_132 : 139248.0\n",
+ "Round 171 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121933.0\n",
+ "Current payoff against guess_132 : 139550.0\n",
+ "Round 172 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123403.0\n",
+ "Current payoff against guess_132 : 139440.0\n",
+ "Round 173 of 199\n",
+ "Best payoff: 139722\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 128, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124205.0\n",
+ "Current payoff against guess_132 : 139479.0\n",
+ "Round 174 of 199\n",
+ "Best payoff: 139722\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 128, 124, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123561.0\n",
+ "Current payoff against guess_132 : 139479.0\n",
+ "Round 175 of 199\n",
+ "Best payoff: 139798\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, 127, 125, 125, 125, 125, 125, 125, 125, 113, 135]\n",
+ "Current payoff against imitation_132 : 124848.0\n",
+ "Current payoff against guess_132 : 139691.0\n",
+ "Round 176 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121004.0\n",
+ "Current payoff against guess_132 : 139671.0\n",
+ "Round 177 of 199\n",
+ "Best payoff: 139706\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 128, 124, 123, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124130.0\n",
+ "Current payoff against guess_132 : 139689.0\n",
+ "Round 178 of 199\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 132, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124722.0\n",
+ "Current payoff against guess_132 : 139625.0\n",
+ "Round 179 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125666.0\n",
+ "Current payoff against guess_132 : 139697.0\n",
+ "Round 180 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126696.0\n",
+ "Current payoff against guess_132 : 139754.0\n",
+ "Round 181 of 199\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125159.0\n",
+ "Current payoff against guess_132 : 139607.0\n",
+ "Round 182 of 199\n",
+ "Best payoff: 139687\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 127, 121, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 127100.0\n",
+ "Current payoff against guess_132 : 139598.0\n",
+ "Round 183 of 199\n",
+ "Best payoff: 139687\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 127, 121, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 127056.0\n",
+ "Current payoff against guess_132 : 139606.0\n",
+ "Round 184 of 199\n",
+ "Best payoff: 139618\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 126, 127, 121, 123, 123, 123, 123, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125918.0\n",
+ "Current payoff against guess_132 : 139606.0\n",
+ "Round 185 of 199\n",
+ "Best payoff: 139606\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 125, 125, 122, 123, 123, 123, 123, 123, 113, 134]\n",
+ "Current payoff against imitation_132 : 125876.0\n",
+ "Current payoff against guess_132 : 139606.0\n",
+ "Round 186 of 199\n",
+ "Best payoff: 139697\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 128, 121, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123708.0\n",
+ "Current payoff against guess_132 : 139619.0\n",
+ "Round 187 of 199\n",
+ "Best payoff: 139697\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 128, 121, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125825.0\n",
+ "Current payoff against guess_132 : 139669.0\n",
+ "Round 188 of 199\n",
+ "Best payoff: 139697\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 128, 121, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125105.0\n",
+ "Current payoff against guess_132 : 139582.0\n",
+ "Round 189 of 199\n",
+ "Best payoff: 139582\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 127, 125, 124, 122, 123, 123, 123, 123, 123, 113, 134]\n",
+ "Current payoff against imitation_132 : 121143.0\n",
+ "Current payoff against guess_132 : 139582.0\n",
+ "Round 190 of 199\n",
+ "Best payoff: 139697\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 128, 121, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124892.0\n",
+ "Current payoff against guess_132 : 139687.0\n",
+ "Round 191 of 199\n",
+ "Best payoff: 139697\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 128, 121, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125325.0\n",
+ "Current payoff against guess_132 : 139636.0\n",
+ "Round 192 of 199\n",
+ "Best payoff: 139697\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 128, 121, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125529.0\n",
+ "Current payoff against guess_132 : 139687.0\n",
+ "Round 193 of 199\n",
+ "Best payoff: 139697\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 128, 121, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123898.0\n",
+ "Current payoff against guess_132 : 139582.0\n",
+ "Round 194 of 199\n",
+ "Best payoff: 139781\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 128, 126, 125, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126167.0\n",
+ "Current payoff against guess_132 : 139594.0\n",
+ "Round 195 of 199\n",
+ "Best payoff: 139765\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 125, 124, 123, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126167.0\n",
+ "Current payoff against guess_132 : 139529.0\n",
+ "Round 196 of 199\n",
+ "Best payoff: 139597\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 129, 119, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 126052.0\n",
+ "Current payoff against guess_132 : 139596.0\n",
+ "Round 197 of 199\n",
+ "Best payoff: 139597\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 129, 119, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124717.0\n",
+ "Current payoff against guess_132 : 139563.0\n",
+ "Round 198 of 199\n",
+ "Best payoff: 139597\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 129, 119, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124717.0\n",
+ "Current payoff against guess_132 : 139529.0\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Below is the second stage of learning: actions are chosen according to an epsilon greedy strategy.\n",
+ "episode_counter = (final_round + 1) * number_episodes_per_round\n",
+ "episodes_left = number_episodes - episode_counter\n",
+ "number_episodes_per_round = 500_000\n",
+ "number_rounds = int(episodes_left / number_episodes_per_round)\n",
+ "\n",
+ "for round_ in range(number_rounds): \n",
+ " print('Round ', round_, ' of ', number_rounds)\n",
+ " algorithm.epsilon_greedy_learning(number_episodes_per_round, episode_counter)\n",
+ "\n",
+ " for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " new_adversary_probabilities =[0]*len(AdversaryModes)\n",
+ " new_adversary_probabilities[index] = 1\n",
+ " result = Test(game, Qtable, discount_factor, new_adversary_probabilities)\n",
+ " payoff, _, _, _, _ = result.total_payoff()\n",
+ " opponent_results[index].append(payoff)\n",
+ " print('Current payoff against', adversary.name, \":\" , payoff)\n",
+ " \n",
+ " episode_counter += number_episodes_per_round\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "outputs": [
+ {
+ "data": {
+ "text/plain": ""
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "text/plain": "",
+ "image/png": "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lUpkZWVh0KBB0n4zMzP069dP+t6rVy+MGDECPj4+mDp1Kj7++GO+PEDUAjEII6Knio2NDTw8PNCzZ0/84x//QGlpKdauXSvtl8lkKuWFENI2ExMTaVuN8vLyOteo6d6sfU5tuhJNTU0RFxeH//73v/Dy8sL27dvRrVs3pKWlaXwOImr6GIQR0VMtLCwM4eHhePDgAVxdXZGQkKCy/9SpU/D09AQAtGnTBgBUBtmnpKRodT25XA4XFxecOXNG2lZRUYHz58+rlJPJZPD19cXatWuRnJwMCwsLlXFjRNT8cUwYET3Vhg4dih49emD9+vVYuXIlwsLC0LlzZ/Tu3RtRUVFISUnB3r17AQAeHh5o37491qxZg3feeQepqanYsmWL1tdctmwZNm7ciC5dusDT0xMREREqb1yePXsWR44cgZ+fH5ydnXH27FncvXtXCgaJqGVgEEZET73ly5fj5Zdfxi+//IL8/HyEhoYiJycHXl5eOHjwILp06QKguptx3759WLRoEXr16oX+/fvjnXfewdSpU7W6XmhoKLKyshAUFAQTExPMnTsXf/rTn6BUKgEA9vb2OHHiBLZt24b8/Hx07NgRW7ZswdixY/X+24nIeGSC7zwTERERGRzHhBEREREZAYMwIiIiIiNgEEZERERkBAzCiIiIiIyAQRgRERGRETAIIyIiIjICBmFERERERsAgjIiIiMgIGIQRERERGQGDMCIiIiIjYBBGREREZAQMwoiIiIiM4P8BTX5sojmO6z4AAAAASUVORK5CYII=\n"
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "for index, adversary_probability in enumerate(adversary_probabilities):\n",
+ " if adversary_probability > 0:\n",
+ " plt.plot(opponent_results[index])\n",
+ "legend = list()\n",
+ "for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " legend.append(adversary.name)\n",
+ "plt.title(\"Payoff over the rounds\")\n",
+ "plt.xlabel(\"Rounds\")\n",
+ "plt.ylabel(\"Payoff at the end of each round\")\n",
+ "plt.legend(legend)"
+ ],
+ "metadata": {
+ "collapsed": false
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "outputs": [],
+ "source": [
+ "name = \"\"\n",
+ "for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " if name != \"\":\n",
+ " name += \"_\"\n",
+ " name += str(adversary_probabilities[index]) + \"_\" + adversary.name"
+ ],
+ "metadata": {
+ "collapsed": false
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "excel_name = name + \".xlsx\"\n",
+ "writer = pd.ExcelWriter(excel_name, engine='xlsxwriter')\n",
+ "for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " df = pd.DataFrame(opponent_results[index])\n",
+ " name = \"Payoff against \" + adversary.name\n",
+ " df.to_excel(writer, sheet_name= name, index=False)\n",
+ "writer.save()\n",
+ "Qtable.save(name)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# We now have the trained agent. We want to test it against each opponent individually, so that\n",
+ "# we can compare it against the agent that is just trained against this opponent."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Adversary Name: imitation_132\n",
+ "Agent Payoff: 124717.0 Adversary Payoff: 72285.0\n",
+ "Agent Actions: [118 132 117 109 108 111 90 113 107 105 100 106 104 99 97 95 91 106\n",
+ " 103 98 102 102 100 114 130]\n",
+ "Adversary Actions: [132 118 132 117 109 108 111 90 113 107 105 100 106 104 99 97 95 91\n",
+ " 106 103 98 102 102 100 114]\n",
+ "Agent Demand Potential: [200. 207. 200. 207. 211. 211. 209. 219. 207. 210. 211. 213. 210. 211.\n",
+ " 213. 214. 215. 217. 209. 210. 212. 210. 210. 211. 204.]\n",
+ "Adversary Name: guess_132\n",
+ "Agent Payoff: 139529.0 Adversary Payoff: 92466.0\n",
+ "Agent Actions: [118 132 132 132 132 132 132 132 132 132 132 132 132 132 128 126 129 119\n",
+ " 123 123 123 123 124 112 135]\n",
+ "Adversary Actions: [132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 124 124 124\n",
+ " 124 124 124 124 124 124 129]\n",
+ "Agent Demand Potential: [200. 207. 207. 207. 207. 207. 207. 207. 207. 207. 207. 207. 207. 207.\n",
+ " 207. 209. 208. 205. 207. 207. 207. 207. 207. 207. 213.]\n"
+ ]
+ }
+ ],
+ "source": [
+ "for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " new_adversary_probabilities =[0]*len(AdversaryModes)\n",
+ " new_adversary_probabilities[index] = 1\n",
+ " result = Test(game, Qtable, discount_factor, new_adversary_probabilities)\n",
+ " payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " print(\"Adversary Name:\", adversary.name)\n",
+ " print(\"Agent Payoff:\", payoff, \"Adversary Payoff:\", adversary_payoff)\n",
+ " print(\"Agent Actions:\", actions)\n",
+ " print(\"Adversary Actions:\", adversary_actions)\n",
+ " print(\"Agent Demand Potential:\", demand_potential)"
+ ],
+ "metadata": {
+ "collapsed": false
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "outputs": [],
+ "source": [],
+ "metadata": {
+ "collapsed": false
+ }
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Episodic_learning_with_memory/test.py b/qLearning/Episodic_learning_with_memory/test.py
new file mode 100644
index 0000000..b9f1168
--- /dev/null
+++ b/qLearning/Episodic_learning_with_memory/test.py
@@ -0,0 +1,168 @@
+# Ed, Galit and Katerina
+# Relates to the Q-Learning approach.
+# Testing out the Q-table against a given opponent
+
+import numpy as np
+from environment import AdversaryModes
+import matplotlib.pyplot as plt
+
+
+class Test():
+
+
+ def __init__(self, Model, Qtable, discount_factor, adversary_probabilities) -> None:
+
+
+ self.env = Model
+ self.Qtable = Qtable.Q_table
+ self.number_demands=Qtable.number_demands
+ self.highest_demand = self.number_demands - 1
+ self.number_actions=Qtable.number_actions
+ self.number_stages=Qtable.number_stages
+ self.discount_factor = discount_factor
+ self.adversary_probabilities = adversary_probabilities
+ self.adversary = None
+
+
+
+ def set_adversary(self):
+ options = list(range(len(self.adversary_probabilities)))
+ adversary_index = int(np.random.choice(options, 1, p= self.adversary_probabilities))
+ self.adversary = AdversaryModes(adversary_index)
+ new_probabilities = [0]*len(self.adversary_probabilities)
+ new_probabilities[adversary_index] = 1
+ self.env.adversary_probabilities = new_probabilities
+
+
+ def total_payoff(self):
+
+ self.set_adversary()
+
+ delta = 1
+ utility = 0
+ adversary_utility = 0
+ actions = [0]*self.number_stages
+ adversary_actions = [0]*self.number_stages
+ demands = [0]*self.number_stages
+ state_vector, reward, done = self.env.reset()
+ demand = state_vector[1]
+ previous_action = state_vector[2]
+
+ for stage in range(self.number_stages):
+ demands[stage] = demand
+ if demand >= self.number_demands:
+ print("max demand reached")
+ demand = self.number_demands - 1
+ if demand < 0:
+ print("min demand reached")
+ demand = 0
+ demand_index = int(demand)
+ action_index = np.argmax(self.Qtable[demand_index, :, previous_action, stage])
+ action = action_index + int((demand + self.env.costs[0])/2) - self.number_actions + 1
+ actions[stage] = action
+ utility += (demand-action)*(action-self.env.costs[0]) * delta
+ adversary_demand = 400 - demand
+ state_vector, _, _ = self.env.step(state_vector, action, action_index)
+ demand = state_vector[1]
+ previous_action = state_vector[2]
+ adversary_actions[stage] = state_vector[3]
+ adversary_utility += (adversary_demand-adversary_actions[stage])*(adversary_actions[stage]-self.env.costs[1]) * delta
+ delta *= self.discount_factor
+ return utility, adversary_utility, np.transpose(actions), np.transpose(adversary_actions), np.transpose(demands)
+
+
+ def q_learning(self, state_action_value, optimal_next_value, reward, alpha, gamma):
+ target = reward + gamma * optimal_next_value
+ return state_action_value + alpha * (target - state_action_value)
+
+ def random_policy(self, monopoly_price):
+ random_action = np.random.randint(monopoly_price-self.number_actions+1, monopoly_price + 1)
+ if random_action < 0:
+ random_action = max(0, random_action)
+ if self.env.costs[0] > random_action:
+ random_action = monopoly_price
+ return random_action
+
+ def action_index(self, monopoly_price, action): # computes action index in Qtable
+ return int(action - (monopoly_price - self.number_actions + 1)) #monopoly_price should have index number_actions - 1
+
+
+ def error(self, number_tests):
+
+
+
+ errors = list()
+
+ for test in range(number_tests):
+
+ self.set_adversary()
+
+ state, reward, done = self.env.reset()
+
+ while not done:
+ stage, agent_demand, agent_previous_action, adversary_previous_action = state
+ if (agent_demand < 0) or (agent_demand > self.highest_demand):
+ break
+ if (stage > 0 and adversary_previous_action < self.env.costs[1]) or (self.highest_demand - agent_demand < adversary_previous_action):
+ break
+ monopoly_price = int((agent_demand + self.env.costs[0]) / 2)
+ action = self.random_policy(monopoly_price)
+ demand_index = int(agent_demand)
+ action_index = self.action_index(monopoly_price, action)
+ state, reward, done = self.env.step(state, action, action_index)
+
+ if done:
+ optimal_next_value = 0
+ else:
+ optimal_next_value = max(self.Qtable[int(state[1]),:, action_index, state[0]])
+
+ new_value = reward + self.discount_factor * optimal_next_value
+ current_q_value = self.Qtable[demand_index, action_index, agent_previous_action, stage]
+
+ if new_value != 0:
+ errors.append((new_value - current_q_value)/new_value)
+
+# if new_value == 0 and current_q_value != 0:
+# print("Division by zero error")
+
+ error_array = np.array(errors)
+# plt.plot(error_array)
+ return error_array.mean()
+
+
+
+
+# def myopic(self, cost, demand):
+# return (cost + demand)/2
+
+# def payoff(self, cost, demand, price):
+# return (demand - price)*(price - cost)
+
+# def update_demand(self, demand, price_pair):
+# new_demand = demand + 0.5*(price_pair[1]- price_pair[0])
+# return new_demand
+
+# def utility_of_actions(self, actions):
+# agent_demand = 200
+# opponent_demand = 200
+# total_payoff = 0
+# delta = 1/self.discount_factor
+# for i in range(self.number_stages):
+# delta = delta * self.discount_factor
+# agent_price = int(actions[i])
+# opponent_price = int(self.myopic(self.env.costs[1],opponent_demand))
+# total_payoff += self.payoff(self.env.costs[0],agent_demand,agent_price) * delta
+# agent_demand = int(self.update_demand(agent_demand, [agent_price,opponent_price]))
+# opponent_demand = 400 - agent_demand
+# return total_payoff
+
+
+
+
+
+
+
+
+
+
+
diff --git a/qLearning/Memory_and_epsilon_greedy/.DS_Store b/qLearning/Memory_and_epsilon_greedy/.DS_Store
new file mode 100644
index 0000000..1ef06c5
Binary files /dev/null and b/qLearning/Memory_and_epsilon_greedy/.DS_Store differ
diff --git a/qLearning/Memory_and_epsilon_greedy/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb b/qLearning/Memory_and_epsilon_greedy/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
new file mode 100644
index 0000000..62573dc
--- /dev/null
+++ b/qLearning/Memory_and_epsilon_greedy/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
@@ -0,0 +1,1353 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "import pandas as pd"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_demand = 400\n",
+ "agent_cost = 57\n",
+ "adversary_cost = 71 \n",
+ "costs = [agent_cost,adversary_cost]\n",
+ "total_stages = 25\n",
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Below is where we decide what adversaries we train against. See environment.py for the numbers\n",
+ "adversary_probabilities[3]= 0.5\n",
+ "adversary_probabilities[10] = 0.5\n",
+ "game = Model(total_demand, costs, total_stages, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2040816\n"
+ ]
+ }
+ ],
+ "source": [
+ "number_actions = 50\n",
+ "number_demands = total_demand + 1\n",
+ "discount_factor = 1\n",
+ "number_episodes = 100_000_000\n",
+ "constant = int(number_episodes/49)\n",
+ "print(constant)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+denominator)\n",
+ "Qtable = QTable(number_demands, number_actions, total_stages , learning_rate = [constant,constant])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, number_episodes, discount_factor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "opponent_results = [list() for mode in AdversaryModes]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "pycharm": {
+ "is_executing": true
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Round 0 of 200\n",
+ "Best payoff: 131209\n",
+ "Best actions: [123, 109, 103, 120, 118, 106, 118, 124, 126, 96, 114, 102, 129, 107, 122, 122, 110, 108, 123, 116, 121, 122, 107, 111, 129]\n",
+ "Current payoff against imitation_132 : 129237.0\n",
+ "Current payoff against guess_132 : 105869.0\n",
+ "Round 1 of 200\n",
+ "Best payoff: 119340\n",
+ "Best actions: [118, 125, 119, 114, 124, 100, 117, 104, 128, 109, 122, 82, 118, 108, 111, 121, 104, 117, 85, 111, 121, 108, 106, 122, 79]\n",
+ "Current payoff against imitation_132 : 129771.0\n",
+ "Current payoff against guess_132 : 84732.0\n",
+ "Round 2 of 200\n",
+ "Best payoff: 120336\n",
+ "Best actions: [119, 125, 121, 128, 130, 112, 120, 118, 122, 111, 126, 84, 127, 128, 126, 101, 120, 107, 124, 104, 119, 125, 124, 83, 113]\n",
+ "Current payoff against imitation_132 : 131184.0\n",
+ "Current payoff against guess_132 : 101847.0\n",
+ "Round 3 of 200\n",
+ "Best payoff: 121155\n",
+ "Best actions: [120, 122, 119, 118, 120, 121, 116, 113, 111, 118, 112, 129, 83, 108, 122, 119, 78, 126, 99, 117, 108, 113, 116, 94, 106]\n",
+ "Current payoff against imitation_132 : 131996.0\n",
+ "Current payoff against guess_132 : 103929.0\n",
+ "Round 4 of 200\n",
+ "Best payoff: 121215\n",
+ "Best actions: [128, 128, 120, 128, 116, 119, 103, 128, 103, 115, 106, 114, 125, 114, 104, 109, 120, 120, 117, 96, 124, 89, 112, 93, 83]\n",
+ "Current payoff against imitation_132 : 131246.0\n",
+ "Current payoff against guess_132 : 95060.0\n",
+ "Round 5 of 200\n",
+ "Best payoff: 119175\n",
+ "Best actions: [127, 116, 125, 117, 100, 111, 120, 100, 103, 123, 99, 112, 102, 130, 109, 125, 93, 106, 102, 107, 104, 121, 94, 116, 116]\n",
+ "Current payoff against imitation_132 : 129168.0\n",
+ "Current payoff against guess_132 : 124116.0\n",
+ "Round 6 of 200\n",
+ "Best payoff: 124071\n",
+ "Best actions: [121, 123, 132, 110, 118, 130, 122, 118, 109, 117, 122, 125, 123, 109, 116, 121, 126, 122, 99, 107, 101, 120, 121, 104, 101]\n",
+ "Current payoff against imitation_132 : 129107.0\n",
+ "Current payoff against guess_132 : 129024.0\n",
+ "Round 7 of 200\n",
+ "Best payoff: 120909\n",
+ "Best actions: [122, 122, 119, 117, 118, 123, 127, 124, 85, 117, 120, 115, 112, 122, 111, 122, 117, 111, 115, 100, 99, 89, 124, 80, 116]\n",
+ "Current payoff against imitation_132 : 131162.0\n",
+ "Current payoff against guess_132 : 116907.0\n",
+ "Round 8 of 200\n",
+ "Best payoff: 119170\n",
+ "Best actions: [126, 125, 130, 123, 121, 130, 121, 113, 119, 112, 111, 118, 107, 103, 118, 116, 108, 97, 89, 85, 111, 103, 121, 114, 119]\n",
+ "Current payoff against imitation_132 : 130118.0\n",
+ "Current payoff against guess_132 : 109656.0\n",
+ "Round 9 of 200\n",
+ "Best payoff: 121029\n",
+ "Best actions: [120, 130, 121, 128, 102, 125, 114, 110, 92, 114, 127, 99, 122, 118, 100, 112, 103, 102, 124, 123, 82, 114, 119, 94, 120]\n",
+ "Current payoff against imitation_132 : 129276.0\n",
+ "Current payoff against guess_132 : 116401.0\n",
+ "Round 10 of 200\n",
+ "Best payoff: 124031\n",
+ "Best actions: [122, 120, 129, 112, 108, 114, 105, 123, 111, 110, 127, 104, 98, 117, 105, 125, 104, 104, 113, 118, 102, 114, 107, 98, 125]\n",
+ "Current payoff against imitation_132 : 132126.0\n",
+ "Current payoff against guess_132 : 114874.0\n",
+ "Round 11 of 200\n",
+ "Best payoff: 117853\n",
+ "Best actions: [119, 130, 132, 124, 116, 115, 109, 112, 122, 107, 117, 99, 95, 116, 119, 116, 117, 89, 111, 76, 122, 113, 85, 113, 125]\n",
+ "Current payoff against imitation_132 : 132067.0\n",
+ "Current payoff against guess_132 : 118955.0\n",
+ "Round 12 of 200\n",
+ "Best payoff: 121339\n",
+ "Best actions: [117, 127, 126, 130, 117, 116, 123, 107, 110, 116, 117, 128, 123, 104, 107, 125, 85, 105, 125, 100, 125, 85, 119, 102, 118]\n",
+ "Current payoff against imitation_132 : 131864.0\n",
+ "Current payoff against guess_132 : 115270.0\n",
+ "Round 13 of 200\n",
+ "Best payoff: 124572\n",
+ "Best actions: [117, 127, 128, 125, 117, 119, 113, 129, 124, 126, 81, 123, 121, 122, 94, 114, 113, 118, 130, 113, 105, 110, 91, 131, 110]\n",
+ "Current payoff against imitation_132 : 130813.0\n",
+ "Current payoff against guess_132 : 103439.0\n",
+ "Round 14 of 200\n",
+ "Best payoff: 121152\n",
+ "Best actions: [120, 122, 121, 113, 117, 120, 114, 128, 106, 99, 124, 106, 116, 115, 115, 128, 121, 82, 125, 112, 117, 88, 114, 101, 88]\n",
+ "Current payoff against imitation_132 : 131648.0\n",
+ "Current payoff against guess_132 : 118729.0\n",
+ "Round 15 of 200\n",
+ "Best payoff: 119283\n",
+ "Best actions: [121, 122, 115, 113, 118, 107, 129, 109, 120, 104, 115, 108, 90, 131, 107, 108, 102, 116, 113, 125, 114, 89, 100, 97, 130]\n",
+ "Current payoff against imitation_132 : 131090.0\n",
+ "Current payoff against guess_132 : 117797.0\n",
+ "Round 16 of 200\n",
+ "Best payoff: 119735\n",
+ "Best actions: [122, 130, 119, 118, 125, 95, 121, 104, 120, 93, 114, 96, 122, 101, 117, 104, 111, 102, 112, 120, 89, 124, 95, 109, 86]\n",
+ "Current payoff against imitation_132 : 131329.0\n",
+ "Current payoff against guess_132 : 112424.0\n",
+ "Round 17 of 200\n",
+ "Best payoff: 121508\n",
+ "Best actions: [123, 124, 129, 119, 118, 126, 130, 114, 122, 114, 111, 130, 114, 102, 100, 112, 119, 120, 79, 117, 122, 91, 123, 100, 105]\n",
+ "Current payoff against imitation_132 : 131096.0\n",
+ "Current payoff against guess_132 : 96768.0\n",
+ "Round 18 of 200\n",
+ "Best payoff: 121564\n",
+ "Best actions: [128, 121, 124, 124, 125, 108, 121, 116, 130, 120, 124, 100, 112, 108, 118, 107, 111, 106, 104, 111, 120, 105, 110, 79, 98]\n",
+ "Current payoff against imitation_132 : 131670.0\n",
+ "Current payoff against guess_132 : 113417.0\n",
+ "Round 19 of 200\n",
+ "Best payoff: 121528\n",
+ "Best actions: [122, 128, 118, 115, 124, 127, 91, 129, 112, 109, 103, 121, 121, 105, 102, 108, 121, 104, 109, 117, 78, 119, 105, 113, 111]\n",
+ "Current payoff against imitation_132 : 132083.0\n",
+ "Current payoff against guess_132 : 119319.0\n",
+ "Round 20 of 200\n",
+ "Best payoff: 120442\n",
+ "Best actions: [125, 118, 122, 115, 123, 127, 84, 105, 114, 126, 117, 106, 107, 103, 117, 101, 127, 107, 102, 116, 109, 98, 124, 118, 102]\n",
+ "Current payoff against imitation_132 : 131596.0\n",
+ "Current payoff against guess_132 : 118500.0\n",
+ "Round 21 of 200\n",
+ "Best payoff: 124806\n",
+ "Best actions: [120, 127, 125, 119, 121, 124, 123, 121, 89, 113, 130, 97, 118, 108, 106, 110, 122, 112, 112, 103, 114, 118, 104, 115, 130]\n",
+ "Current payoff against imitation_132 : 131519.0\n",
+ "Current payoff against guess_132 : 108825.0\n",
+ "Round 22 of 200\n",
+ "Best payoff: 121898\n",
+ "Best actions: [124, 125, 132, 132, 123, 133, 118, 106, 111, 121, 114, 126, 108, 103, 108, 123, 114, 91, 114, 109, 79, 124, 93, 95, 125]\n",
+ "Current payoff against imitation_132 : 131946.0\n",
+ "Current payoff against guess_132 : 120353.0\n",
+ "Round 23 of 200\n",
+ "Best payoff: 120817\n",
+ "Best actions: [121, 123, 127, 115, 123, 118, 120, 117, 118, 128, 120, 119, 109, 122, 111, 119, 119, 119, 97, 113, 88, 110, 94, 84, 105]\n",
+ "Current payoff against imitation_132 : 129515.0\n",
+ "Current payoff against guess_132 : 119003.0\n",
+ "Round 24 of 200\n",
+ "Best payoff: 120660\n",
+ "Best actions: [118, 131, 128, 126, 121, 121, 124, 115, 119, 113, 116, 108, 114, 104, 113, 119, 92, 91, 128, 101, 93, 113, 88, 117, 89]\n",
+ "Current payoff against imitation_132 : 128539.0\n",
+ "Current payoff against guess_132 : 123110.0\n",
+ "Round 25 of 200\n",
+ "Best payoff: 125847\n",
+ "Best actions: [120, 127, 121, 121, 122, 112, 115, 108, 121, 127, 109, 116, 102, 129, 113, 128, 119, 93, 110, 108, 122, 112, 119, 126, 99]\n",
+ "Current payoff against imitation_132 : 131903.0\n",
+ "Current payoff against guess_132 : 114894.0\n",
+ "Round 26 of 200\n",
+ "Best payoff: 124565\n",
+ "Best actions: [128, 122, 132, 125, 123, 120, 121, 118, 113, 116, 113, 114, 129, 113, 90, 110, 116, 118, 106, 91, 126, 104, 98, 87, 134]\n",
+ "Current payoff against imitation_132 : 130481.0\n",
+ "Current payoff against guess_132 : 114837.0\n",
+ "Round 27 of 200\n",
+ "Best payoff: 124997\n",
+ "Best actions: [125, 123, 123, 130, 106, 131, 114, 105, 113, 111, 129, 110, 125, 108, 108, 123, 110, 128, 88, 116, 127, 109, 94, 130, 111]\n",
+ "Current payoff against imitation_132 : 129467.0\n",
+ "Current payoff against guess_132 : 116194.0\n",
+ "Round 28 of 200\n",
+ "Best payoff: 125660\n",
+ "Best actions: [118, 132, 132, 130, 123, 121, 121, 117, 120, 124, 105, 116, 118, 118, 105, 115, 106, 114, 117, 104, 102, 85, 104, 114, 102]\n",
+ "Current payoff against imitation_132 : 130858.0\n",
+ "Current payoff against guess_132 : 114799.0\n",
+ "Round 29 of 200\n",
+ "Best payoff: 120383\n",
+ "Best actions: [128, 126, 113, 111, 109, 109, 109, 112, 101, 114, 122, 90, 101, 105, 114, 99, 109, 122, 99, 125, 89, 118, 86, 105, 127]\n",
+ "Current payoff against imitation_132 : 131896.0\n",
+ "Current payoff against guess_132 : 115266.0\n",
+ "Round 30 of 200\n",
+ "Best payoff: 123093\n",
+ "Best actions: [127, 128, 122, 128, 116, 120, 113, 114, 114, 110, 124, 107, 117, 91, 101, 124, 89, 113, 130, 90, 110, 100, 101, 98, 124]\n",
+ "Current payoff against imitation_132 : 129698.0\n",
+ "Current payoff against guess_132 : 133242.0\n",
+ "Round 31 of 200\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best payoff: 123927\n",
+ "Best actions: [118, 122, 116, 114, 116, 121, 121, 104, 99, 116, 112, 111, 116, 111, 107, 110, 111, 115, 113, 124, 89, 98, 87, 111, 126]\n",
+ "Current payoff against imitation_132 : 129605.0\n",
+ "Current payoff against guess_132 : 111266.0\n",
+ "Round 32 of 200\n",
+ "Best payoff: 121323\n",
+ "Best actions: [115, 131, 108, 124, 93, 124, 100, 113, 112, 117, 118, 102, 121, 110, 120, 113, 104, 119, 119, 125, 103, 111, 98, 109, 131]\n",
+ "Current payoff against imitation_132 : 131010.0\n",
+ "Current payoff against guess_132 : 123313.0\n",
+ "Round 33 of 200\n",
+ "Best payoff: 125523\n",
+ "Best actions: [117, 132, 132, 129, 123, 121, 127, 120, 110, 127, 117, 111, 126, 102, 101, 131, 92, 107, 107, 119, 105, 95, 126, 115, 100]\n",
+ "Current payoff against imitation_132 : 129907.0\n",
+ "Current payoff against guess_132 : 113485.0\n",
+ "Round 34 of 200\n",
+ "Best payoff: 122937\n",
+ "Best actions: [118, 127, 122, 129, 118, 127, 110, 107, 121, 112, 121, 124, 86, 109, 132, 110, 97, 104, 128, 120, 94, 118, 106, 103, 128]\n",
+ "Current payoff against imitation_132 : 132022.0\n",
+ "Current payoff against guess_132 : 123725.0\n",
+ "Round 35 of 200\n",
+ "Best payoff: 120488\n",
+ "Best actions: [118, 132, 124, 124, 114, 114, 121, 102, 121, 112, 104, 107, 131, 93, 103, 115, 86, 107, 105, 124, 118, 79, 120, 103, 102]\n",
+ "Current payoff against imitation_132 : 131170.0\n",
+ "Current payoff against guess_132 : 113644.0\n",
+ "Round 36 of 200\n",
+ "Best payoff: 121026\n",
+ "Best actions: [118, 132, 132, 123, 121, 121, 116, 110, 122, 113, 101, 90, 120, 100, 98, 92, 109, 107, 110, 111, 80, 114, 117, 111, 124]\n",
+ "Current payoff against imitation_132 : 131154.0\n",
+ "Current payoff against guess_132 : 119114.0\n",
+ "Round 37 of 200\n",
+ "Best payoff: 121944\n",
+ "Best actions: [121, 128, 117, 115, 115, 118, 109, 117, 128, 90, 114, 125, 121, 100, 123, 100, 121, 114, 108, 111, 98, 113, 113, 99, 90]\n",
+ "Current payoff against imitation_132 : 129420.0\n",
+ "Current payoff against guess_132 : 101753.0\n",
+ "Round 38 of 200\n",
+ "Best payoff: 129453\n",
+ "Best actions: [118, 132, 132, 119, 116, 125, 116, 113, 103, 121, 114, 115, 103, 116, 115, 120, 113, 102, 114, 114, 117, 113, 110, 111, 112]\n",
+ "Current payoff against imitation_132 : 128975.0\n",
+ "Current payoff against guess_132 : 120056.0\n",
+ "Round 39 of 200\n",
+ "Best payoff: 126421\n",
+ "Best actions: [118, 130, 125, 120, 118, 128, 107, 129, 112, 125, 123, 116, 116, 89, 129, 104, 118, 123, 100, 119, 115, 112, 116, 112, 105]\n",
+ "Current payoff against imitation_132 : 129178.0\n",
+ "Current payoff against guess_132 : 119629.0\n",
+ "Round 40 of 200\n",
+ "Best payoff: 120076\n",
+ "Best actions: [118, 132, 123, 121, 120, 127, 121, 114, 118, 124, 120, 103, 122, 111, 86, 95, 97, 110, 96, 101, 99, 102, 93, 114, 94]\n",
+ "Current payoff against imitation_132 : 130193.0\n",
+ "Current payoff against guess_132 : 120080.0\n",
+ "Round 41 of 200\n",
+ "Best payoff: 125172\n",
+ "Best actions: [123, 127, 130, 132, 126, 123, 130, 122, 127, 111, 114, 115, 114, 116, 118, 91, 113, 122, 90, 109, 96, 118, 93, 108, 118]\n",
+ "Current payoff against imitation_132 : 129703.0\n",
+ "Current payoff against guess_132 : 107108.0\n",
+ "Round 42 of 200\n",
+ "Best payoff: 125243\n",
+ "Best actions: [118, 131, 123, 126, 111, 122, 110, 111, 118, 116, 112, 115, 128, 119, 125, 109, 116, 119, 88, 110, 112, 117, 126, 111, 93]\n",
+ "Current payoff against imitation_132 : 131307.0\n",
+ "Current payoff against guess_132 : 121693.0\n",
+ "Round 43 of 200\n",
+ "Best payoff: 120824\n",
+ "Best actions: [126, 124, 132, 119, 116, 118, 116, 116, 129, 102, 107, 108, 120, 121, 83, 102, 105, 101, 107, 105, 98, 85, 103, 124, 117]\n",
+ "Current payoff against imitation_132 : 131060.0\n",
+ "Current payoff against guess_132 : 122183.0\n",
+ "Round 44 of 200\n",
+ "Best payoff: 125035\n",
+ "Best actions: [118, 124, 134, 120, 117, 105, 111, 121, 108, 113, 121, 109, 107, 121, 108, 105, 117, 124, 97, 107, 111, 116, 102, 93, 106]\n",
+ "Current payoff against imitation_132 : 129653.0\n",
+ "Current payoff against guess_132 : 105133.0\n",
+ "Round 45 of 200\n",
+ "Best payoff: 125053\n",
+ "Best actions: [128, 127, 128, 130, 131, 122, 117, 133, 109, 111, 123, 101, 118, 113, 101, 119, 111, 116, 106, 113, 101, 130, 99, 108, 112]\n",
+ "Current payoff against imitation_132 : 128445.0\n",
+ "Current payoff against guess_132 : 117996.0\n",
+ "Round 46 of 200\n",
+ "Best payoff: 122825\n",
+ "Best actions: [118, 119, 116, 129, 111, 119, 116, 105, 102, 116, 113, 118, 121, 124, 119, 107, 103, 125, 100, 119, 112, 97, 111, 110, 97]\n",
+ "Current payoff against imitation_132 : 129292.0\n",
+ "Current payoff against guess_132 : 104780.0\n",
+ "Round 47 of 200\n",
+ "Best payoff: 123725\n",
+ "Best actions: [118, 129, 125, 124, 123, 125, 118, 122, 129, 101, 126, 114, 112, 107, 110, 122, 99, 98, 112, 102, 117, 108, 105, 118, 79]\n",
+ "Current payoff against imitation_132 : 129612.0\n",
+ "Current payoff against guess_132 : 123541.0\n",
+ "Round 48 of 200\n",
+ "Best payoff: 122811\n",
+ "Best actions: [118, 132, 132, 132, 128, 120, 112, 110, 114, 117, 119, 98, 123, 101, 102, 110, 100, 100, 104, 118, 125, 96, 91, 118, 128]\n",
+ "Current payoff against imitation_132 : 131026.0\n",
+ "Current payoff against guess_132 : 125236.0\n",
+ "Round 49 of 200\n",
+ "Best payoff: 123310\n",
+ "Best actions: [122, 128, 132, 132, 128, 123, 121, 118, 116, 127, 106, 119, 122, 126, 94, 103, 111, 113, 121, 104, 122, 83, 94, 102, 79]\n",
+ "Current payoff against imitation_132 : 130918.0\n",
+ "Current payoff against guess_132 : 119937.0\n",
+ "Round 50 of 200\n",
+ "Best payoff: 125929\n",
+ "Best actions: [120, 130, 131, 132, 128, 128, 126, 123, 122, 118, 130, 110, 115, 122, 114, 117, 90, 105, 120, 124, 124, 98, 114, 110, 111]\n",
+ "Current payoff against imitation_132 : 130626.0\n",
+ "Current payoff against guess_132 : 117153.0\n",
+ "Round 51 of 200\n",
+ "Best payoff: 130660\n",
+ "Best actions: [118, 129, 125, 123, 121, 130, 113, 119, 122, 123, 121, 109, 130, 108, 113, 120, 119, 119, 129, 121, 109, 118, 112, 112, 93]\n",
+ "Current payoff against imitation_132 : 128372.0\n",
+ "Current payoff against guess_132 : 102666.0\n",
+ "Round 52 of 200\n",
+ "Best payoff: 123135\n",
+ "Best actions: [118, 132, 122, 120, 129, 112, 113, 116, 111, 122, 111, 95, 105, 104, 105, 105, 113, 94, 120, 100, 89, 95, 108, 109, 124]\n",
+ "Current payoff against imitation_132 : 128398.0\n",
+ "Current payoff against guess_132 : 132393.0\n",
+ "Round 53 of 200\n",
+ "Best payoff: 123675\n",
+ "Best actions: [118, 127, 126, 125, 118, 123, 124, 105, 111, 112, 116, 103, 114, 110, 108, 118, 110, 107, 123, 82, 99, 99, 99, 116, 110]\n",
+ "Current payoff against imitation_132 : 130356.0\n",
+ "Current payoff against guess_132 : 118175.0\n",
+ "Round 54 of 200\n",
+ "Best payoff: 127231\n",
+ "Best actions: [118, 132, 129, 125, 123, 118, 116, 117, 122, 103, 117, 115, 122, 117, 107, 119, 100, 122, 110, 121, 122, 124, 107, 114, 125]\n",
+ "Current payoff against imitation_132 : 129369.0\n",
+ "Current payoff against guess_132 : 112634.0\n",
+ "Round 55 of 200\n",
+ "Best payoff: 123463\n",
+ "Best actions: [118, 132, 132, 132, 132, 124, 119, 129, 109, 109, 109, 121, 102, 119, 116, 86, 99, 120, 105, 94, 114, 114, 95, 104, 100]\n",
+ "Current payoff against imitation_132 : 131247.0\n",
+ "Current payoff against guess_132 : 112513.0\n",
+ "Round 56 of 200\n",
+ "Best payoff: 126449\n",
+ "Best actions: [118, 128, 128, 122, 118, 119, 122, 110, 121, 124, 96, 119, 126, 111, 97, 113, 114, 121, 110, 105, 117, 109, 121, 95, 107]\n",
+ "Current payoff against imitation_132 : 128873.0\n",
+ "Current payoff against guess_132 : 117819.0\n",
+ "Round 57 of 200\n",
+ "Best payoff: 124184\n",
+ "Best actions: [123, 126, 132, 127, 125, 132, 112, 114, 128, 95, 110, 109, 103, 131, 117, 91, 103, 107, 116, 118, 113, 89, 100, 115, 116]\n",
+ "Current payoff against imitation_132 : 131109.0\n",
+ "Current payoff against guess_132 : 118124.0\n",
+ "Round 58 of 200\n",
+ "Best payoff: 126593\n",
+ "Best actions: [118, 132, 132, 125, 122, 121, 117, 125, 116, 113, 120, 120, 97, 126, 114, 118, 104, 111, 110, 121, 113, 121, 128, 113, 77]\n",
+ "Current payoff against imitation_132 : 130843.0\n",
+ "Current payoff against guess_132 : 133056.0\n",
+ "Round 59 of 200\n",
+ "Best payoff: 123305\n",
+ "Best actions: [127, 122, 132, 132, 132, 126, 124, 123, 115, 115, 123, 126, 80, 111, 121, 122, 81, 120, 125, 76, 109, 111, 121, 110, 97]\n",
+ "Current payoff against imitation_132 : 132406.0\n",
+ "Current payoff against guess_132 : 130799.0\n",
+ "Round 60 of 200\n",
+ "Best payoff: 124038\n",
+ "Best actions: [118, 126, 124, 124, 132, 111, 119, 122, 119, 112, 118, 114, 123, 109, 125, 116, 105, 114, 103, 108, 106, 84, 127, 112, 77]\n",
+ "Current payoff against imitation_132 : 130704.0\n",
+ "Current payoff against guess_132 : 118072.0\n",
+ "Round 61 of 200\n",
+ "Best payoff: 129460\n",
+ "Best actions: [118, 132, 132, 132, 132, 129, 123, 121, 119, 118, 127, 128, 102, 118, 109, 127, 118, 113, 123, 115, 121, 105, 105, 118, 89]\n",
+ "Current payoff against imitation_132 : 131018.0\n",
+ "Current payoff against guess_132 : 135326.0\n",
+ "Round 62 of 200\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best payoff: 124061\n",
+ "Best actions: [122, 128, 132, 130, 125, 123, 122, 119, 130, 125, 123, 100, 115, 119, 127, 104, 129, 110, 127, 120, 107, 93, 132, 80, 107]\n",
+ "Current payoff against imitation_132 : 130784.0\n",
+ "Current payoff against guess_132 : 121527.0\n",
+ "Round 63 of 200\n",
+ "Best payoff: 126906\n",
+ "Best actions: [118, 132, 126, 124, 121, 119, 119, 121, 121, 111, 114, 127, 109, 113, 120, 118, 121, 87, 118, 102, 105, 117, 122, 108, 89]\n",
+ "Current payoff against imitation_132 : 129366.0\n",
+ "Current payoff against guess_132 : 130976.0\n",
+ "Round 64 of 200\n",
+ "Best payoff: 127324\n",
+ "Best actions: [118, 125, 122, 119, 116, 115, 113, 113, 114, 122, 127, 115, 118, 95, 117, 101, 118, 114, 114, 115, 108, 108, 116, 126, 101]\n",
+ "Current payoff against imitation_132 : 129596.0\n",
+ "Current payoff against guess_132 : 132873.0\n",
+ "Round 65 of 200\n",
+ "Best payoff: 125428\n",
+ "Best actions: [118, 132, 123, 134, 102, 126, 108, 119, 109, 115, 115, 120, 108, 129, 102, 109, 112, 120, 129, 84, 106, 120, 115, 105, 111]\n",
+ "Current payoff against imitation_132 : 131812.0\n",
+ "Current payoff against guess_132 : 125163.0\n",
+ "Round 66 of 200\n",
+ "Best payoff: 126031\n",
+ "Best actions: [118, 131, 132, 124, 127, 128, 117, 114, 109, 106, 116, 116, 118, 116, 113, 118, 108, 120, 96, 101, 101, 98, 102, 87, 106]\n",
+ "Current payoff against imitation_132 : 126246.0\n",
+ "Current payoff against guess_132 : 116904.0\n",
+ "Round 67 of 200\n",
+ "Best payoff: 125542\n",
+ "Best actions: [118, 132, 132, 132, 130, 125, 123, 121, 120, 116, 120, 111, 121, 112, 114, 123, 98, 103, 120, 83, 89, 113, 96, 120, 100]\n",
+ "Current payoff against imitation_132 : 129017.0\n",
+ "Current payoff against guess_132 : 130019.0\n",
+ "Round 68 of 200\n",
+ "Best payoff: 127913\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 125, 122, 119, 122, 130, 103, 118, 113, 115, 125, 117, 116, 109, 107, 92, 103, 114, 99, 114]\n",
+ "Current payoff against imitation_132 : 130494.0\n",
+ "Current payoff against guess_132 : 134926.0\n",
+ "Round 69 of 200\n",
+ "Best payoff: 124749\n",
+ "Best actions: [118, 132, 132, 132, 132, 126, 124, 121, 132, 125, 110, 117, 115, 131, 105, 130, 121, 104, 119, 100, 122, 113, 118, 94, 96]\n",
+ "Current payoff against imitation_132 : 131324.0\n",
+ "Current payoff against guess_132 : 134955.0\n",
+ "Round 70 of 200\n",
+ "Best payoff: 127187\n",
+ "Best actions: [118, 132, 132, 132, 132, 128, 124, 130, 115, 122, 126, 115, 124, 114, 128, 127, 103, 128, 116, 104, 124, 127, 108, 103, 114]\n",
+ "Current payoff against imitation_132 : 129793.0\n",
+ "Current payoff against guess_132 : 134972.0\n",
+ "Round 71 of 200\n",
+ "Best payoff: 128106\n",
+ "Best actions: [118, 132, 132, 131, 131, 132, 125, 122, 128, 122, 114, 125, 115, 117, 114, 121, 113, 107, 109, 105, 100, 129, 102, 79, 127]\n",
+ "Current payoff against imitation_132 : 129926.0\n",
+ "Current payoff against guess_132 : 123766.0\n",
+ "Round 72 of 200\n",
+ "Best payoff: 130416\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 123, 121, 118, 122, 114, 124, 116, 118, 120, 109, 127, 103, 125, 109, 104, 123, 114, 99, 114]\n",
+ "Current payoff against imitation_132 : 131394.0\n",
+ "Current payoff against guess_132 : 121024.0\n",
+ "Round 73 of 200\n",
+ "Best payoff: 128705\n",
+ "Best actions: [127, 122, 132, 132, 128, 126, 123, 118, 117, 116, 113, 111, 117, 117, 115, 105, 123, 114, 127, 124, 100, 91, 131, 115, 127]\n",
+ "Current payoff against imitation_132 : 126864.0\n",
+ "Current payoff against guess_132 : 117929.0\n",
+ "Round 74 of 200\n",
+ "Best payoff: 131027\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 123, 120, 119, 130, 113, 120, 125, 110, 120, 121, 108, 121, 119, 120, 123, 120, 93, 132]\n",
+ "Current payoff against imitation_132 : 129630.0\n",
+ "Current payoff against guess_132 : 133290.0\n",
+ "Round 75 of 200\n",
+ "Best payoff: 129343\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 123, 120, 119, 117, 116, 116, 115, 114, 118, 111, 121, 120, 109, 93, 96, 111, 118, 117]\n",
+ "Current payoff against imitation_132 : 129878.0\n",
+ "Current payoff against guess_132 : 120422.0\n",
+ "Round 76 of 200\n",
+ "Best payoff: 127869\n",
+ "Best actions: [118, 132, 132, 132, 123, 121, 120, 119, 120, 119, 118, 116, 125, 118, 115, 113, 114, 111, 126, 126, 107, 107, 103, 79, 132]\n",
+ "Current payoff against imitation_132 : 129356.0\n",
+ "Current payoff against guess_132 : 125909.0\n",
+ "Round 77 of 200\n",
+ "Best payoff: 131289\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 123, 123, 119, 127, 124, 122, 104, 121, 112, 114, 113, 113, 114, 110, 117, 109, 95, 116]\n",
+ "Current payoff against imitation_132 : 130151.0\n",
+ "Current payoff against guess_132 : 120970.0\n",
+ "Round 78 of 200\n",
+ "Best payoff: 132398\n",
+ "Best actions: [125, 123, 132, 127, 125, 123, 121, 119, 119, 119, 115, 116, 116, 118, 114, 120, 119, 125, 117, 104, 118, 115, 119, 106, 93]\n",
+ "Current payoff against imitation_132 : 130591.0\n",
+ "Current payoff against guess_132 : 125396.0\n",
+ "Round 79 of 200\n",
+ "Best payoff: 134324\n",
+ "Best actions: [120, 130, 132, 132, 132, 132, 126, 123, 120, 120, 117, 119, 116, 120, 119, 119, 113, 124, 117, 123, 108, 111, 121, 115, 125]\n",
+ "Current payoff against imitation_132 : 129584.0\n",
+ "Current payoff against guess_132 : 129895.0\n",
+ "Round 80 of 200\n",
+ "Best payoff: 133600\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 127, 118, 119, 117, 121, 115, 113, 114, 124, 105, 116, 110, 121, 114, 109, 123, 99, 120]\n",
+ "Current payoff against imitation_132 : 128393.0\n",
+ "Current payoff against guess_132 : 121286.0\n",
+ "Round 81 of 200\n",
+ "Best payoff: 131399\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 123, 120, 118, 118, 121, 109, 115, 114, 114, 111, 126, 116, 113, 105, 106, 121, 113, 106]\n",
+ "Current payoff against imitation_132 : 129882.0\n",
+ "Current payoff against guess_132 : 133148.0\n",
+ "Round 82 of 200\n",
+ "Best payoff: 126075\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 124, 120, 113, 112, 106, 109, 118, 92, 102, 101, 102, 94, 100, 100, 96, 115, 112, 123]\n",
+ "Current payoff against imitation_132 : 130378.0\n",
+ "Current payoff against guess_132 : 131746.0\n",
+ "Round 83 of 200\n",
+ "Best payoff: 131473\n",
+ "Best actions: [118, 132, 132, 132, 132, 125, 123, 120, 119, 120, 115, 118, 130, 112, 118, 119, 120, 109, 124, 116, 124, 118, 108, 128, 82]\n",
+ "Current payoff against imitation_132 : 128507.0\n",
+ "Current payoff against guess_132 : 120626.0\n",
+ "Round 84 of 200\n",
+ "Best payoff: 129261\n",
+ "Best actions: [128, 122, 132, 132, 132, 132, 126, 124, 120, 118, 124, 120, 120, 120, 106, 116, 120, 106, 126, 110, 121, 92, 117, 115, 116]\n",
+ "Current payoff against imitation_132 : 131366.0\n",
+ "Current payoff against guess_132 : 133514.0\n",
+ "Round 85 of 200\n",
+ "Best payoff: 132684\n",
+ "Best actions: [125, 124, 132, 132, 132, 132, 126, 124, 121, 119, 118, 120, 117, 114, 113, 115, 109, 115, 113, 110, 117, 117, 103, 111, 129]\n",
+ "Current payoff against imitation_132 : 129388.0\n",
+ "Current payoff against guess_132 : 134738.0\n",
+ "Round 86 of 200\n",
+ "Best payoff: 130788\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 123, 121, 122, 123, 115, 120, 115, 124, 116, 116, 130, 107, 126, 117, 106, 91, 117, 111, 117]\n",
+ "Current payoff against imitation_132 : 127597.0\n",
+ "Current payoff against guess_132 : 124595.0\n",
+ "Round 87 of 200\n",
+ "Best payoff: 132144\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 126, 130, 116, 119, 117, 121, 113, 113, 115, 120, 117, 111, 110, 116, 127, 114, 87, 111, 126]\n",
+ "Current payoff against imitation_132 : 129109.0\n",
+ "Current payoff against guess_132 : 118118.0\n",
+ "Round 88 of 200\n",
+ "Best payoff: 131946\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 128, 124, 121, 119, 119, 117, 123, 111, 116, 117, 117, 110, 118, 113, 97, 96, 98, 116, 127]\n",
+ "Current payoff against imitation_132 : 128886.0\n",
+ "Current payoff against guess_132 : 129152.0\n",
+ "Round 89 of 200\n",
+ "Best payoff: 131533\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 124, 121, 119, 125, 116, 122, 113, 130, 116, 94, 125, 119, 119, 111, 107, 107, 99, 133]\n",
+ "Current payoff against imitation_132 : 129962.0\n",
+ "Current payoff against guess_132 : 134754.0\n",
+ "Round 90 of 200\n",
+ "Best payoff: 132624\n",
+ "Best actions: [122, 128, 132, 132, 132, 132, 126, 124, 129, 122, 115, 124, 125, 120, 124, 117, 121, 118, 120, 111, 116, 97, 115, 85, 129]\n",
+ "Current payoff against imitation_132 : 128408.0\n",
+ "Current payoff against guess_132 : 116988.0\n",
+ "Round 91 of 200\n",
+ "Best payoff: 132725\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 128, 128, 122, 122, 119, 118, 123, 117, 118, 121, 102, 125, 106, 112, 123, 109, 100, 113, 128]\n",
+ "Current payoff against imitation_132 : 126342.0\n",
+ "Current payoff against guess_132 : 132103.0\n",
+ "Round 92 of 200\n",
+ "Best payoff: 131720\n",
+ "Best actions: [123, 126, 132, 132, 132, 131, 126, 124, 121, 121, 119, 119, 117, 116, 113, 121, 121, 94, 119, 102, 122, 113, 101, 113, 111]\n",
+ "Current payoff against imitation_132 : 129684.0\n",
+ "Current payoff against guess_132 : 134001.0\n",
+ "Round 93 of 200\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best payoff: 131178\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 128, 128, 122, 121, 119, 126, 114, 115, 113, 114, 125, 120, 86, 111, 112, 102, 112, 113, 111]\n",
+ "Current payoff against imitation_132 : 127765.0\n",
+ "Current payoff against guess_132 : 132202.0\n",
+ "Round 94 of 200\n",
+ "Best payoff: 133894\n",
+ "Best actions: [120, 130, 132, 132, 132, 132, 128, 125, 122, 122, 120, 118, 117, 116, 125, 115, 110, 112, 122, 117, 121, 118, 109, 120, 128]\n",
+ "Current payoff against imitation_132 : 130559.0\n",
+ "Current payoff against guess_132 : 122075.0\n",
+ "Round 95 of 200\n",
+ "Best payoff: 133698\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 127, 125, 122, 122, 119, 118, 117, 116, 120, 119, 115, 112, 117, 117, 120, 114, 117, 86, 136]\n",
+ "Current payoff against imitation_132 : 129779.0\n",
+ "Current payoff against guess_132 : 133992.0\n",
+ "Round 96 of 200\n",
+ "Best payoff: 133995\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 128, 125, 122, 120, 120, 118, 117, 118, 125, 110, 128, 114, 113, 124, 110, 121, 93, 119, 107]\n",
+ "Current payoff against imitation_132 : 129481.0\n",
+ "Current payoff against guess_132 : 136155.0\n",
+ "Round 97 of 200\n",
+ "Best payoff: 133865\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 128, 125, 122, 120, 120, 118, 125, 109, 123, 119, 114, 118, 128, 112, 124, 120, 113, 119, 128]\n",
+ "Current payoff against imitation_132 : 129069.0\n",
+ "Current payoff against guess_132 : 136183.0\n",
+ "Round 98 of 200\n",
+ "Best payoff: 134674\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 128, 125, 122, 121, 121, 117, 117, 116, 117, 117, 116, 110, 117, 110, 118, 112, 103, 120, 127]\n",
+ "Current payoff against imitation_132 : 130888.0\n",
+ "Current payoff against guess_132 : 126663.0\n",
+ "Round 99 of 200\n",
+ "Best payoff: 134895\n",
+ "Best actions: [121, 128, 131, 132, 132, 131, 128, 125, 122, 122, 122, 118, 119, 121, 119, 119, 119, 119, 121, 117, 131, 103, 105, 118, 127]\n",
+ "Current payoff against imitation_132 : 130150.0\n",
+ "Current payoff against guess_132 : 129425.0\n",
+ "Round 100 of 200\n",
+ "Best payoff: 134648\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 127, 127, 123, 122, 119, 121, 113, 121, 115, 113, 117, 121, 109, 108, 122, 108, 110, 132]\n",
+ "Current payoff against imitation_132 : 130119.0\n",
+ "Current payoff against guess_132 : 126667.0\n",
+ "Round 101 of 200\n",
+ "Best payoff: 134304\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 127, 123, 121, 119, 119, 119, 121, 113, 114, 121, 122, 119, 108, 124, 113, 104, 107, 131]\n",
+ "Current payoff against imitation_132 : 126897.0\n",
+ "Current payoff against guess_132 : 128268.0\n",
+ "Round 102 of 200\n",
+ "Best payoff: 133229\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 126, 124, 124, 118, 120, 117, 107, 125, 110, 110, 113, 112, 123, 118, 108, 104, 113, 132]\n",
+ "Current payoff against imitation_132 : 128071.0\n",
+ "Current payoff against guess_132 : 128993.0\n",
+ "Round 103 of 200\n",
+ "Best payoff: 133644\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 129, 128, 124, 125, 118, 117, 114, 114, 113, 115, 124, 105, 118, 115, 114, 122, 110, 128]\n",
+ "Current payoff against imitation_132 : 129400.0\n",
+ "Current payoff against guess_132 : 135104.0\n",
+ "Round 104 of 200\n",
+ "Best payoff: 134121\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 125, 123, 120, 120, 125, 125, 120, 102, 119, 116, 122, 119, 119, 114, 118, 113, 112, 123]\n",
+ "Current payoff against imitation_132 : 123590.0\n",
+ "Current payoff against guess_132 : 127630.0\n",
+ "Round 105 of 200\n",
+ "Best payoff: 134047\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 126, 123, 120, 120, 118, 120, 116, 120, 117, 118, 130, 112, 115, 117, 111, 116, 106, 94]\n",
+ "Current payoff against imitation_132 : 127386.0\n",
+ "Current payoff against guess_132 : 125785.0\n",
+ "Round 106 of 200\n",
+ "Best payoff: 133560\n",
+ "Best actions: [120, 130, 132, 132, 132, 132, 131, 126, 123, 120, 120, 118, 117, 120, 121, 120, 109, 124, 128, 113, 118, 129, 112, 112, 129]\n",
+ "Current payoff against imitation_132 : 127863.0\n",
+ "Current payoff against guess_132 : 134421.0\n",
+ "Round 107 of 200\n",
+ "Best payoff: 134959\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 132, 126, 123, 120, 118, 118, 116, 116, 115, 116, 116, 123, 113, 112, 120, 126, 115, 107]\n",
+ "Current payoff against imitation_132 : 127999.0\n",
+ "Current payoff against guess_132 : 134793.0\n",
+ "Round 108 of 200\n",
+ "Best payoff: 135158\n",
+ "Best actions: [118, 132, 132, 132, 131, 131, 132, 131, 125, 123, 120, 120, 118, 120, 115, 117, 124, 129, 100, 118, 114, 117, 114, 119, 127]\n",
+ "Current payoff against imitation_132 : 126778.0\n",
+ "Current payoff against guess_132 : 135494.0\n",
+ "Round 109 of 200\n",
+ "Best payoff: 135526\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 132, 126, 123, 121, 121, 122, 116, 116, 118, 122, 117, 119, 128, 119, 120, 116, 114, 130]\n",
+ "Current payoff against imitation_132 : 128621.0\n",
+ "Current payoff against guess_132 : 136063.0\n",
+ "Round 110 of 200\n",
+ "Best payoff: 136126\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 129, 123, 122, 121, 119, 116, 122, 127, 111, 117, 116, 122, 122, 121, 105, 133]\n",
+ "Current payoff against imitation_132 : 125719.0\n",
+ "Current payoff against guess_132 : 132967.0\n",
+ "Round 111 of 200\n",
+ "Best payoff: 136355\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 130, 123, 122, 118, 118, 120, 120, 114, 120, 121, 117, 117, 126, 126, 111, 130]\n",
+ "Current payoff against imitation_132 : 130514.0\n",
+ "Current payoff against guess_132 : 136508.0\n",
+ "Round 112 of 200\n",
+ "Best payoff: 135722\n",
+ "Best actions: [118, 132, 131, 132, 131, 132, 132, 131, 132, 129, 123, 122, 121, 117, 119, 118, 122, 117, 118, 114, 111, 116, 117, 112, 127]\n",
+ "Current payoff against imitation_132 : 128730.0\n",
+ "Current payoff against guess_132 : 136072.0\n",
+ "Round 113 of 200\n",
+ "Best payoff: 136819\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 130, 123, 123, 121, 117, 119, 120, 119, 119, 121, 117, 120, 122, 117, 118, 130]\n",
+ "Current payoff against imitation_132 : 125983.0\n",
+ "Current payoff against guess_132 : 135120.0\n",
+ "Round 114 of 200\n",
+ "Best payoff: 136242\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 126, 124, 121, 121, 119, 123, 114, 123, 121, 115, 119, 121, 117, 120, 122, 117, 118, 130]\n",
+ "Current payoff against imitation_132 : 127293.0\n",
+ "Current payoff against guess_132 : 132069.0\n",
+ "Round 115 of 200\n",
+ "Best payoff: 136741\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 131, 130, 123, 123, 121, 116, 120, 117, 122, 117, 118, 120, 119, 115, 118, 132, 118]\n",
+ "Current payoff against imitation_132 : 128816.0\n",
+ "Current payoff against guess_132 : 128573.0\n",
+ "Round 116 of 200\n",
+ "Best payoff: 136729\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 130, 123, 120, 118, 118, 116, 116, 116, 116, 115, 122, 114, 112, 116, 118, 127]\n",
+ "Current payoff against imitation_132 : 126957.0\n",
+ "Current payoff against guess_132 : 134704.0\n",
+ "Round 117 of 200\n",
+ "Best payoff: 136376\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 130, 122, 120, 118, 118, 116, 115, 116, 116, 115, 122, 112, 119, 113, 108, 133]\n",
+ "Current payoff against imitation_132 : 127395.0\n",
+ "Current payoff against guess_132 : 136036.0\n",
+ "Round 118 of 200\n",
+ "Best payoff: 136772\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 132, 132, 126, 123, 120, 118, 118, 117, 114, 116, 116, 115, 118, 116, 118, 112, 112, 128]\n",
+ "Current payoff against imitation_132 : 129472.0\n",
+ "Current payoff against guess_132 : 136633.0\n",
+ "Round 119 of 200\n",
+ "Best payoff: 136908\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 128, 124, 121, 118, 118, 116, 116, 116, 116, 115, 118, 116, 115, 113, 108, 129]\n",
+ "Current payoff against imitation_132 : 129574.0\n",
+ "Current payoff against guess_132 : 123969.0\n",
+ "Round 120 of 200\n",
+ "Best payoff: 137046\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 128, 124, 121, 123, 118, 117, 118, 120, 120, 119, 117, 116, 115, 112, 115, 131]\n",
+ "Current payoff against imitation_132 : 121800.0\n",
+ "Current payoff against guess_132 : 136614.0\n",
+ "Round 121 of 200\n",
+ "Best payoff: 136913\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 128, 124, 121, 120, 119, 119, 119, 119, 128, 117, 113, 120, 122, 111, 112, 133]\n",
+ "Current payoff against imitation_132 : 128005.0\n",
+ "Current payoff against guess_132 : 136721.0\n",
+ "Round 122 of 200\n",
+ "Best payoff: 137086\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 131, 128, 124, 122, 120, 119, 121, 113, 120, 120, 114, 122, 114, 116, 118, 106, 133]\n",
+ "Current payoff against imitation_132 : 126700.0\n",
+ "Current payoff against guess_132 : 136608.0\n",
+ "Round 123 of 200\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best payoff: 136806\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 132, 132, 128, 124, 122, 120, 118, 117, 115, 115, 119, 111, 119, 114, 113, 118, 114, 131]\n",
+ "Current payoff against imitation_132 : 126872.0\n",
+ "Current payoff against guess_132 : 121361.0\n",
+ "Round 124 of 200\n",
+ "Best payoff: 137206\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 126, 124, 122, 120, 118, 118, 115, 115, 116, 116, 117, 114, 116, 115, 114, 128]\n",
+ "Current payoff against imitation_132 : 129211.0\n",
+ "Current payoff against guess_132 : 136833.0\n",
+ "Round 125 of 200\n",
+ "Best payoff: 137199\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 131, 132, 132, 126, 123, 120, 120, 117, 120, 118, 117, 117, 119, 114, 116, 118, 116, 131]\n",
+ "Current payoff against imitation_132 : 129694.0\n",
+ "Current payoff against guess_132 : 136545.0\n",
+ "Round 126 of 200\n",
+ "Best payoff: 137098\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 131, 126, 123, 120, 118, 117, 116, 116, 117, 116, 113, 115, 116, 118, 116, 130]\n",
+ "Current payoff against imitation_132 : 123976.0\n",
+ "Current payoff against guess_132 : 136427.0\n",
+ "Round 127 of 200\n",
+ "Best payoff: 137275\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 123, 120, 120, 118, 118, 120, 117, 117, 119, 114, 116, 118, 118, 130]\n",
+ "Current payoff against imitation_132 : 127740.0\n",
+ "Current payoff against guess_132 : 137144.0\n",
+ "Round 128 of 200\n",
+ "Best payoff: 137583\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 123, 120, 120, 118, 118, 120, 120, 114, 118, 117, 122, 114, 114, 128]\n",
+ "Current payoff against imitation_132 : 127041.0\n",
+ "Current payoff against guess_132 : 137523.0\n",
+ "Round 129 of 200\n",
+ "Best payoff: 137524\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 123, 120, 120, 118, 118, 120, 119, 113, 118, 117, 122, 114, 114, 128]\n",
+ "Current payoff against imitation_132 : 129016.0\n",
+ "Current payoff against guess_132 : 137588.0\n",
+ "Round 130 of 200\n",
+ "Best payoff: 137672\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 123, 120, 120, 118, 118, 117, 120, 115, 118, 117, 122, 114, 114, 130]\n",
+ "Current payoff against imitation_132 : 128726.0\n",
+ "Current payoff against guess_132 : 137593.0\n",
+ "Round 131 of 200\n",
+ "Best payoff: 137631\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 123, 120, 120, 118, 117, 117, 118, 117, 120, 116, 122, 114, 111, 130]\n",
+ "Current payoff against imitation_132 : 130194.0\n",
+ "Current payoff against guess_132 : 137538.0\n",
+ "Round 132 of 200\n",
+ "Best payoff: 137739\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 132, 132, 132, 126, 124, 121, 120, 119, 120, 116, 120, 116, 120, 116, 122, 114, 111, 132]\n",
+ "Current payoff against imitation_132 : 127508.0\n",
+ "Current payoff against guess_132 : 137698.0\n",
+ "Round 133 of 200\n",
+ "Best payoff: 137698\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 132, 126, 124, 121, 120, 119, 120, 116, 120, 116, 120, 116, 122, 114, 114, 130]\n",
+ "Current payoff against imitation_132 : 124716.0\n",
+ "Current payoff against guess_132 : 137619.0\n",
+ "Round 134 of 200\n",
+ "Best payoff: 137736\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 123, 121, 120, 118, 119, 118, 120, 116, 120, 116, 122, 114, 114, 130]\n",
+ "Current payoff against imitation_132 : 125202.0\n",
+ "Current payoff against guess_132 : 137557.0\n",
+ "Round 135 of 200\n",
+ "Best payoff: 137646\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 123, 121, 120, 119, 119, 118, 120, 116, 118, 120, 118, 122, 111, 130]\n",
+ "Current payoff against imitation_132 : 127877.0\n",
+ "Current payoff against guess_132 : 137280.0\n",
+ "Round 136 of 200\n",
+ "Best payoff: 137626\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 128, 122, 121, 119, 119, 121, 117, 119, 123, 121, 119, 115, 111, 133]\n",
+ "Current payoff against imitation_132 : 128550.0\n",
+ "Current payoff against guess_132 : 137626.0\n",
+ "Round 137 of 200\n",
+ "Best payoff: 137722\n",
+ "Best actions: [118, 132, 132, 131, 131, 131, 131, 132, 132, 131, 128, 125, 122, 123, 119, 118, 121, 119, 118, 123, 119, 120, 118, 110, 132]\n",
+ "Current payoff against imitation_132 : 130921.0\n",
+ "Current payoff against guess_132 : 137298.0\n",
+ "Round 138 of 200\n",
+ "Best payoff: 137891\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 125, 122, 122, 119, 119, 121, 117, 119, 123, 119, 120, 118, 110, 132]\n",
+ "Current payoff against imitation_132 : 128130.0\n",
+ "Current payoff against guess_132 : 137891.0\n",
+ "Round 139 of 200\n",
+ "Best payoff: 137952\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 127, 125, 122, 122, 122, 118, 121, 117, 119, 123, 116, 121, 116, 112, 128]\n",
+ "Current payoff against imitation_132 : 126894.0\n",
+ "Current payoff against guess_132 : 137317.0\n",
+ "Round 140 of 200\n",
+ "Best payoff: 138024\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 131, 132, 128, 125, 122, 122, 120, 119, 121, 120, 118, 123, 116, 118, 116, 120, 130]\n",
+ "Current payoff against imitation_132 : 129201.0\n",
+ "Current payoff against guess_132 : 137978.0\n",
+ "Round 141 of 200\n",
+ "Best payoff: 137940\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 125, 122, 122, 121, 118, 121, 117, 119, 123, 116, 121, 116, 112, 128]\n",
+ "Current payoff against imitation_132 : 126117.0\n",
+ "Current payoff against guess_132 : 136166.0\n",
+ "Round 142 of 200\n",
+ "Best payoff: 137946\n",
+ "Best actions: [118, 132, 132, 132, 131, 131, 131, 132, 131, 132, 127, 125, 122, 121, 122, 118, 122, 120, 118, 123, 116, 121, 116, 112, 129]\n",
+ "Current payoff against imitation_132 : 125970.0\n",
+ "Current payoff against guess_132 : 137289.0\n",
+ "Round 143 of 200\n",
+ "Best payoff: 137977\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 132, 128, 125, 122, 122, 120, 120, 122, 120, 120, 122, 116, 118, 115, 119, 130]\n",
+ "Current payoff against imitation_132 : 126347.0\n",
+ "Current payoff against guess_132 : 137390.0\n",
+ "Round 144 of 200\n",
+ "Best payoff: 138112\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 131, 132, 132, 131, 128, 126, 123, 121, 120, 119, 118, 118, 118, 123, 115, 121, 116, 111, 132]\n",
+ "Current payoff against imitation_132 : 120630.0\n",
+ "Current payoff against guess_132 : 136604.0\n",
+ "Round 145 of 200\n",
+ "Best payoff: 138127\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 127, 127, 125, 121, 121, 122, 116, 118, 123, 115, 121, 116, 111, 132]\n",
+ "Current payoff against imitation_132 : 124501.0\n",
+ "Current payoff against guess_132 : 137700.0\n",
+ "Round 146 of 200\n",
+ "Best payoff: 138139\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 125, 125, 125, 121, 121, 120, 120, 117, 120, 119, 118, 116, 111, 132]\n",
+ "Current payoff against imitation_132 : 127152.0\n",
+ "Current payoff against guess_132 : 137815.0\n",
+ "Round 147 of 200\n",
+ "Best payoff: 138054\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 127, 127, 122, 125, 120, 120, 119, 117, 120, 116, 118, 114, 110, 133]\n",
+ "Current payoff against imitation_132 : 121733.0\n",
+ "Current payoff against guess_132 : 137713.0\n",
+ "Round 148 of 200\n",
+ "Best payoff: 138238\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 132, 131, 127, 125, 126, 121, 121, 120, 119, 118, 120, 116, 122, 115, 111, 132]\n",
+ "Current payoff against imitation_132 : 123422.0\n",
+ "Current payoff against guess_132 : 138206.0\n",
+ "Round 149 of 200\n",
+ "Best payoff: 138297\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 127, 125, 124, 122, 122, 120, 119, 118, 117, 120, 118, 116, 110, 133]\n",
+ "Current payoff against imitation_132 : 127929.0\n",
+ "Current payoff against guess_132 : 137875.0\n",
+ "Round 150 of 200\n",
+ "Best payoff: 138310\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 131, 132, 128, 125, 124, 122, 122, 120, 119, 118, 118, 120, 118, 115, 112, 133]\n",
+ "Current payoff against imitation_132 : 119724.0\n",
+ "Current payoff against guess_132 : 137926.0\n",
+ "Round 151 of 200\n",
+ "Best payoff: 138362\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 131, 131, 132, 131, 128, 125, 124, 123, 121, 120, 119, 119, 119, 118, 119, 115, 122, 130]\n",
+ "Current payoff against imitation_132 : 127926.0\n",
+ "Current payoff against guess_132 : 137734.0\n",
+ "Round 152 of 200\n",
+ "Best payoff: 138399\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 131, 131, 128, 126, 123, 123, 123, 119, 121, 119, 118, 116, 117, 117, 111, 133]\n",
+ "Current payoff against imitation_132 : 121791.0\n",
+ "Current payoff against guess_132 : 138318.0\n",
+ "Round 153 of 200\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best payoff: 138635\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 124, 124, 122, 121, 123, 119, 121, 123, 117, 117, 113, 132]\n",
+ "Current payoff against imitation_132 : 128812.0\n",
+ "Current payoff against guess_132 : 138596.0\n",
+ "Round 154 of 200\n",
+ "Best payoff: 138797\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 124, 123, 121, 121, 121, 121, 121, 120, 119, 117, 113, 133]\n",
+ "Current payoff against imitation_132 : 127257.0\n",
+ "Current payoff against guess_132 : 138665.0\n",
+ "Round 155 of 200\n",
+ "Best payoff: 138802\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 124, 124, 121, 121, 121, 121, 121, 120, 119, 120, 112, 133]\n",
+ "Current payoff against imitation_132 : 129806.0\n",
+ "Current payoff against guess_132 : 138372.0\n",
+ "Round 156 of 200\n",
+ "Best payoff: 138632\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 131, 131, 131, 131, 131, 126, 124, 122, 121, 120, 120, 120, 119, 120, 121, 116, 114, 132]\n",
+ "Current payoff against imitation_132 : 126414.0\n",
+ "Current payoff against guess_132 : 138518.0\n",
+ "Round 157 of 200\n",
+ "Best payoff: 138781\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 128, 124, 122, 122, 119, 119, 119, 120, 119, 118, 114, 133]\n",
+ "Current payoff against imitation_132 : 119531.0\n",
+ "Current payoff against guess_132 : 138571.0\n",
+ "Round 158 of 200\n",
+ "Best payoff: 138926\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 128, 126, 123, 123, 121, 121, 121, 121, 120, 122, 120, 115, 133]\n",
+ "Current payoff against imitation_132 : 125969.0\n",
+ "Current payoff against guess_132 : 138763.0\n",
+ "Round 159 of 200\n",
+ "Best payoff: 138923\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 123, 123, 121, 121, 121, 120, 120, 123, 120, 115, 133]\n",
+ "Current payoff against imitation_132 : 125664.0\n",
+ "Current payoff against guess_132 : 138415.0\n",
+ "Round 160 of 200\n",
+ "Best payoff: 138964\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 124, 124, 122, 121, 121, 121, 123, 121, 118, 108, 134]\n",
+ "Current payoff against imitation_132 : 124467.0\n",
+ "Current payoff against guess_132 : 138569.0\n",
+ "Round 161 of 200\n",
+ "Best payoff: 139068\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 124, 124, 122, 121, 121, 121, 123, 121, 119, 111, 132]\n",
+ "Current payoff against imitation_132 : 123971.0\n",
+ "Current payoff against guess_132 : 139015.0\n",
+ "Round 162 of 200\n",
+ "Best payoff: 139072\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 132, 132, 132, 131, 132, 128, 126, 124, 124, 122, 121, 121, 121, 123, 121, 119, 111, 134]\n",
+ "Current payoff against imitation_132 : 125932.0\n",
+ "Current payoff against guess_132 : 138903.0\n",
+ "Round 163 of 200\n",
+ "Best payoff: 139073\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 128, 126, 124, 124, 122, 121, 121, 121, 123, 121, 119, 111, 134]\n",
+ "Current payoff against imitation_132 : 126893.0\n",
+ "Current payoff against guess_132 : 138995.0\n",
+ "Round 164 of 200\n",
+ "Best payoff: 139057\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 132, 128, 126, 123, 123, 121, 121, 121, 121, 123, 119, 120, 111, 134]\n",
+ "Current payoff against imitation_132 : 124426.0\n",
+ "Current payoff against guess_132 : 138969.0\n",
+ "Round 165 of 200\n",
+ "Best payoff: 139071\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 131, 126, 124, 123, 122, 122, 122, 121, 120, 120, 118, 114, 133]\n",
+ "Current payoff against imitation_132 : 126901.0\n",
+ "Current payoff against guess_132 : 138778.0\n",
+ "Round 166 of 200\n",
+ "Best payoff: 139226\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 123, 123, 121, 121, 121, 121, 120, 120, 111, 134]\n",
+ "Current payoff against imitation_132 : 126376.0\n",
+ "Current payoff against guess_132 : 139225.0\n",
+ "Round 167 of 200\n",
+ "Best payoff: 139225\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 128, 126, 123, 123, 121, 121, 121, 121, 120, 120, 111, 134]\n",
+ "Current payoff against imitation_132 : 127574.0\n",
+ "Current payoff against guess_132 : 138828.0\n",
+ "Round 168 of 200\n",
+ "Best payoff: 139185\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 131, 132, 132, 131, 128, 125, 125, 125, 121, 123, 122, 123, 122, 121, 119, 115, 133]\n",
+ "Current payoff against imitation_132 : 130178.0\n",
+ "Current payoff against guess_132 : 138976.0\n",
+ "Round 169 of 200\n",
+ "Best payoff: 139443\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 128, 125, 124, 123, 123, 123, 123, 122, 123, 121, 111, 134]\n",
+ "Current payoff against imitation_132 : 118628.0\n",
+ "Current payoff against guess_132 : 138979.0\n",
+ "Round 170 of 200\n",
+ "Best payoff: 139444\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 125, 124, 123, 123, 123, 123, 122, 123, 121, 111, 134]\n",
+ "Current payoff against imitation_132 : 126021.0\n",
+ "Current payoff against guess_132 : 139276.0\n",
+ "Round 171 of 200\n",
+ "Best payoff: 139517\n",
+ "Best actions: [118, 132, 131, 132, 131, 132, 132, 131, 131, 132, 131, 132, 131, 128, 126, 126, 124, 124, 123, 123, 124, 123, 121, 112, 133]\n",
+ "Current payoff against imitation_132 : 120757.0\n",
+ "Current payoff against guess_132 : 139075.0\n",
+ "Round 172 of 200\n",
+ "Best payoff: 139555\n",
+ "Best actions: [118, 132, 131, 132, 132, 131, 132, 132, 131, 132, 132, 131, 132, 128, 126, 126, 124, 124, 123, 123, 124, 123, 121, 111, 134]\n",
+ "Current payoff against imitation_132 : 128271.0\n",
+ "Current payoff against guess_132 : 139354.0\n",
+ "Round 173 of 200\n",
+ "Best payoff: 139536\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 126, 125, 124, 124, 123, 123, 124, 123, 121, 117, 133]\n",
+ "Current payoff against imitation_132 : 123249.0\n",
+ "Current payoff against guess_132 : 139373.0\n",
+ "Round 174 of 200\n",
+ "Best payoff: 139545\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 132, 131, 132, 132, 128, 126, 126, 124, 124, 123, 123, 124, 123, 121, 109, 135]\n",
+ "Current payoff against imitation_132 : 127843.0\n",
+ "Current payoff against guess_132 : 139413.0\n",
+ "Round 175 of 200\n",
+ "Best payoff: 139575\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 126, 126, 124, 124, 124, 123, 124, 123, 121, 111, 134]\n",
+ "Current payoff against imitation_132 : 124245.0\n",
+ "Current payoff against guess_132 : 139383.0\n",
+ "Round 176 of 200\n",
+ "Best payoff: 139672\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 122, 114, 133]\n",
+ "Current payoff against imitation_132 : 121925.0\n",
+ "Current payoff against guess_132 : 139601.0\n",
+ "Round 177 of 200\n",
+ "Best payoff: 139672\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 131, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 122, 114, 134]\n",
+ "Current payoff against imitation_132 : 119357.0\n",
+ "Current payoff against guess_132 : 139241.0\n",
+ "Round 178 of 200\n",
+ "Best payoff: 139708\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 127, 124, 124, 124, 124, 124, 124, 124, 114, 133]\n",
+ "Current payoff against imitation_132 : 128031.0\n",
+ "Current payoff against guess_132 : 139470.0\n",
+ "Round 179 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124908.0\n",
+ "Current payoff against guess_132 : 139146.0\n",
+ "Round 180 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121371.0\n",
+ "Current payoff against guess_132 : 139700.0\n",
+ "Round 181 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125154.0\n",
+ "Current payoff against guess_132 : 139436.0\n",
+ "Round 182 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 120103.0\n",
+ "Current payoff against guess_132 : 139685.0\n",
+ "Round 183 of 200\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121621.0\n",
+ "Current payoff against guess_132 : 139563.0\n",
+ "Round 184 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121942.0\n",
+ "Current payoff against guess_132 : 139650.0\n",
+ "Round 185 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124144.0\n",
+ "Current payoff against guess_132 : 139494.0\n",
+ "Round 186 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121872.0\n",
+ "Current payoff against guess_132 : 139322.0\n",
+ "Round 187 of 200\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124209.0\n",
+ "Current payoff against guess_132 : 139690.0\n",
+ "Round 188 of 200\n",
+ "Best payoff: 139794\n",
+ "Best actions: [118, 132, 132, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123080.0\n",
+ "Current payoff against guess_132 : 139764.0\n",
+ "Round 189 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125115.0\n",
+ "Current payoff against guess_132 : 139712.0\n",
+ "Round 190 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122050.0\n",
+ "Current payoff against guess_132 : 139314.0\n",
+ "Round 191 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121005.0\n",
+ "Current payoff against guess_132 : 139320.0\n",
+ "Round 192 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122812.0\n",
+ "Current payoff against guess_132 : 139457.0\n",
+ "Round 193 of 200\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122172.0\n",
+ "Current payoff against guess_132 : 139313.0\n",
+ "Round 194 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123210.0\n",
+ "Current payoff against guess_132 : 139300.0\n",
+ "Round 195 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121612.0\n",
+ "Current payoff against guess_132 : 139561.0\n",
+ "Round 196 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123978.0\n",
+ "Current payoff against guess_132 : 139672.0\n",
+ "Round 197 of 200\n",
+ "Best payoff: 139765\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 125, 123, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125003.0\n",
+ "Current payoff against guess_132 : 139686.0\n",
+ "Round 198 of 200\n",
+ "Best payoff: 139765\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 125, 123, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 116583.0\n",
+ "Current payoff against guess_132 : 139706.0\n",
+ "Round 199 of 200\n",
+ "Best payoff: 139706\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 128, 124, 123, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 116374.0\n",
+ "Current payoff against guess_132 : 139655.0\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Action are only chosen according to an epsilon greedy strategy.\n",
+ "episode_counter = 0\n",
+ "number_episodes_per_round = 500_000\n",
+ "number_rounds = int(number_episodes / number_episodes_per_round)\n",
+ "\n",
+ "for round_ in range(number_rounds): \n",
+ " print('Round ', round_, ' of ', number_rounds)\n",
+ " algorithm.epsilon_greedy_learning(number_episodes_per_round, episode_counter, number_episodes)\n",
+ "\n",
+ " for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " new_adversary_probabilities =[0]*len(AdversaryModes)\n",
+ " new_adversary_probabilities[index] = 1\n",
+ " result = Test(game, Qtable, discount_factor, new_adversary_probabilities)\n",
+ " payoff, _, _, _, _ = result.total_payoff()\n",
+ " opponent_results[index].append(payoff)\n",
+ " print('Current payoff against', adversary.name, \":\" , payoff)\n",
+ " \n",
+ " episode_counter += number_episodes_per_round\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlYAAAHFCAYAAAAwv7dvAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAA9hAAAPYQGoP6dpAAD3Q0lEQVR4nOxdd3xUVf4901uSSW8kJBB671VFFEEUbGsFUeyuq65t17Jrwa6Loj8V2yrY1rIKrKIioPTeIr0HQkhvkzZ93u+P++5r82YyE5IQ8J7PJ5/JvLnz5r43k3kn53vu+Wo4juPAwMDAwMDAwMBwytCe7gkwMDAwMDAwMJwtYMSKgYGBgYGBgaGVwIgVAwMDAwMDA0MrgRErBgYGBgYGBoZWAiNWDAwMDAwMDAytBEasGBgYGBgYGBhaCYxYMTAwMDAwMDC0EhixYmBgYGBgYGBoJTBixcDAwMDAwMDQSmDEioHhLMX8+fOh0WiEH71ej6ysLNxyyy04efLk6Z4ePB4P7r77bmRkZECn02HQoEEAgOrqalx//fVITU2FRqPBFVdccVrn2RpYv349nnnmGdTW1gY9lpubiylTprT/pDowVq5cCY1Gg5UrV57uqTAwRA396Z4AAwND22LevHno1asXnE4nVq9ejZdeegmrVq3Crl27YLPZTtu83n33Xbz//vt46623MHToUMTExAAAnnvuOSxcuBAff/wx8vLykJiYeNrm2FpYv349Zs2ahZkzZyI+Pv50T4eBgaENwYgVA8NZjn79+mHYsGEAgPHjx8Pv9+O5557DokWLMH369NM2r927d8NiseDee+8N2p6Xl3da59YSNDU1wWq1nu5pRAWn0wmLxXK6p8HAcFaBlQIZGP5gGDVqFADg+PHjAIBZs2Zh5MiRSExMRFxcHIYMGYKPPvoI0v7st912GxITE9HU1BS0vwsuuAB9+/YV7rtcLjz++OPo0qULjEYjOnXqhL/85S+yMphGo8G///1vOJ1OoVRJS5fLly/Hvn37hO3hykGBQACvvvoqevXqBZPJhNTUVNx0000oKioSxjzwwAOw2Wyoq6sLev51112HtLQ0eL1eYdvXX3+N0aNHw2azISYmBpMmTcKOHTtkz5s5cyZiYmKwa9cuTJw4EbGxsbjwwgtV5/jMM8/gb3/7GwCgS5cuIY9ryZIlGDJkCCwWC3r16oWPP/44aF+lpaW46667kJWVBaPRiC5dumDWrFnw+XwhzxEFLTkuWLAAgwcPhtlsxqxZswAQMnv55ZcjISEBZrMZgwYNwieffCJ7Pn1/jh07JtuuVrY7//zz0a9fP2zZsgXnnnsurFYrunbtipdffhmBQED2/P379+Piiy+G1WpFcnIy7r77btTX1wfNf8eOHZgyZQpSU1NhMpmQmZmJSy+9VPZeMzB0CHAMDAxnJebNm8cB4LZs2SLb/uabb3IAuA8++IDjOI6bOXMm99FHH3HLli3jli1bxj333HOcxWLhZs2aJTzn999/5wBwH374oWxfe/bs4QBw77zzDsdxHBcIBLhJkyZxer2ee/LJJ7mlS5dys2fP5mw2Gzd48GDO5XJxHMdxGzZs4C655BLOYrFwGzZs4DZs2MCVlpZyGzZs4AYPHsx17dpV2O5wOEIe45133skB4O69915uyZIl3HvvvcelpKRw2dnZXEVFRdi519TUcCaTiXvooYeEbS+88AKn0Wi4W2+9lVu8eDG3YMECbvTo0ZzNZuP27NkjjLv55ps5g8HA5ebmci+99BL366+/cr/88ovqHE+cOMHdd999HABuwYIFQceVk5PDZWVlcX369OE+/fRT7pdffuGuueYaDgC3atUqYT8lJSVcdnY2l5OTw73//vvc8uXLueeee44zmUzczJkzQ54jipycHC4jI4Pr2rUr9/HHH3MrVqzgNm/ezO3fv5+LjY3l8vLyuE8//ZT78ccfuRtuuIEDwL3yyivC8+nnqaCgQLbfFStWcAC4FStWCNvGjRvHJSUlcd27d+fee+89btmyZdw999zDAeA++eQTYVxpaSmXmprKderUiZs3bx73008/cdOnT+c6d+4s22dDQwOXlJTEDRs2jPvmm2+4VatWcV9//TV39913c3v37m322BkY2hOMWDEwnKWgF8KNGzdyXq+Xq6+v5xYvXsylpKRwsbGxXGlpadBz/H4/5/V6uWeffZZLSkriAoGA8Ni4ceO4QYMGycb/+c9/5uLi4rj6+nqO4zhuyZIlHADu1VdflY37+uuvZWSO4wg5sdlsQXMYN24c17dv32aPb9++fRwA7p577pFt37RpEweAe+KJJ4RtQ4YM4caMGSMbN3fuXA4At2vXLo7jOK6wsJDT6/XcfffdJxtXX1/Ppaenc9dee61s7gC4jz/+uNl5chzH/etf/1IlJRxHCI/ZbOaOHz8ubHM6nVxiYiJ31113CdvuuusuLiYmRjaO4zhu9uzZHAAZ8VNDTk4Op9PpuAMHDsi2X3/99ZzJZOIKCwtl2ydPnsxZrVautraW47joiRUAbtOmTbKxffr04SZNmiTcf/TRRzmNRsPl5+fLxl100UWyfW7dupUDwC1atCjsMTIwdASwUiADw1mOUaNGwWAwIDY2FlOmTEF6ejp+/vlnpKWlAQB+++03TJgwAXa7HTqdDgaDAU899RSqqqpQXl4u7Oevf/0r8vPzsW7dOgBAXV0dPvvsM9x8882C8fy3334DQEplUlxzzTWw2Wz49ddfW+24VqxYofpaI0aMQO/evWWvdcstt2D9+vU4cOCAsG3evHkYPnw4+vXrBwD45Zdf4PP5cNNNN8Hn8wk/ZrMZ48aNUy1J/ulPf2qVYxk0aBA6d+4s3DebzejRo4dQrgWAxYsXY/z48cjMzJTNb/LkyQCAVatWNfs6AwYMQI8ePWTbfvvtN1x44YXIzs6WbZ85cyaampqwYcOGFh1Teno6RowYEfT60mNasWIF+vbti4EDB8rGTZs2TXa/W7duSEhIwKOPPor33nsPe/fubdGcGBjaA4xYMTCc5fj000+xZcsW7NixA8XFxdi5cyfGjh0LANi8eTMmTpwIAPjwww+xbt06bNmyBf/4xz8AEHMzxeWXX47c3Fy88847AIjnprGxEX/5y1+EMVVVVdDr9UhJSZHNQaPRID09HVVVVa12XHRfGRkZQY9lZmbKXmv69OkwmUyYP38+AGDv3r3YsmULbrnlFmFMWVkZAGD48OEwGAyyn6+//hqVlZWy17BarYiLi2uVY0lKSgraZjKZZOe/rKwMP/zwQ9DcqL9NOT81qJ2rqqqqkOeQPt4SRHJMVVVVSE9PDxqn3Ga327Fq1SoMGjQITzzxBPr27YvMzEw8/fTTMn8cA0NHAFsVyMBwlqN3797CqkAlvvrqKxgMBixevBhms1nYvmjRoqCxWq0Wf/nLX/DEE0/gtddew9y5c3HhhReiZ8+ewpikpCT4fD5UVFTIyBXHcSgtLcXw4cNb7bjohbukpARZWVmyx4qLi5GcnCzcT0hIwOWXX45PP/0Uzz//PObNmwez2YwbbrhBGEPHf/vtt8jJyWn29TUaTWscRsRITk7GgAED8MILL6g+TolQOKjNOSkpCSUlJUHbi4uLhdcFIHw+3G63bFwkhC4UkpKSUFpaGrRdbVv//v3x1VdfgeM47Ny5E/Pnz8ezzz4Li8WCxx57rMVzYGBobTDFioHhDwwaHKrT6YRtTqcTn332mer422+/HUajEdOnT8eBAweCohLoyrjPP/9ctv27775DY2NjyJVzLcEFF1yg+lpbtmzBvn37gl7rlltuQXFxMX766Sd8/vnnuPLKK2WZUpMmTYJer8eRI0cwbNgw1Z+WwmQyAZArgNFiypQpQhSF2twiIVZquPDCC/Hbb78JRIri008/hdVqFVaR5ubmAgB27twpG/f999+36HUBEv+xZ88e/P7777Lt//nPf0I+R6PRYODAgZgzZw7i4+Oxffv2Fr8+A0NbgClWDAx/YFx66aV4/fXXMW3aNNx5552oqqrC7NmzBSKgRHx8PG666Sa8++67yMnJwdSpU2WPX3TRRZg0aRIeffRR1NXVYezYsdi5cyeefvppDB48GDNmzGi1uffs2RN33nkn3nrrLWi1WkyePBnHjh3Dk08+iezsbDz44IOy8RMnTkRWVhbuuecelJaWysqAACEOzz77LP7xj3/g6NGjuPjii5GQkICysjJs3rwZNptNiCeIFv379wcAvPnmm7j55pthMBjQs2dPxMbGRryPZ599FsuWLcOYMWNw//33o2fPnnC5XDh27Bh++uknvPfee0HKXSR4+umnBf/WU089hcTERHzxxRf48ccf8eqrr8JutwMgJdKePXvikUcegc/nQ0JCAhYuXIi1a9dG/ZoUDzzwAD7++GNceumleP7555GWloYvvvgC+/fvl41bvHgx5s6diyuuuAJdu3YFx3FYsGABamtrcdFFF7X49RkY2gSn2TzPwMDQRggVt6DExx9/zPXs2ZMzmUxc165duZdeeon76KOPQq5iW7lyJQeAe/nll1X353Q6uUcffZTLycnhDAYDl5GRwf35z3/mampqZONOdVUgx5FVjK+88grXo0cPzmAwcMnJydyNN97InThxQnX8E088wQHgsrOzOb/frzpm0aJF3Pjx47m4uDjOZDJxOTk53NVXX80tX7682bmHw+OPP85lZmZyWq1WtuItJyeHu/TSS4PGjxs3jhs3bpxsW0VFBXf//fdzXbp04QwGA5eYmMgNHTqU+8c//sE1NDSEff1Qr8NxHLdr1y5u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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "for index, adversary_probability in enumerate(adversary_probabilities):\n",
+ " if adversary_probability > 0:\n",
+ " plt.plot(opponent_results[index])\n",
+ "legend = list()\n",
+ "for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " legend.append(adversary.name)\n",
+ "plt.title(\"Payoff over the rounds\")\n",
+ "plt.xlabel(\"Rounds\")\n",
+ "plt.ylabel(\"Payoff at the end of each round\")\n",
+ "plt.legend(legend)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[]"
+ ]
+ },
+ "execution_count": 20,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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jCFvv/02ef/998mUKVOIJElk4cKF7PEPPfQQMbuUvfzyywQA2bdvH7utT58+pLS0lAwdOpS89tpr5KOPPiLXXHMNAaA7T1u3biXp6elk6NCh5K233iL//ve/ydSpU0nv3r11+9y3bx9JS0sjF110EXn//ffJf//7X/Lmm2+SGTNmkLq6upjHLnByQhArAYEk4bXXXiMAyHPPPUcIIaSpqYlkZmaSc889l22zadMmAoC88MILuseeffbZZMyYMez3J598kthsNvLVV1/ptnvnnXcIALJ06VJ2GwDi9XpJbW1t1PXJskyCwSB59NFHSX5+PiNnW7duJQDIr371K932b731FgGgI1a33347yczMJAcOHNBt+/TTTxMAZOvWrVHX0KdPHyJJEikvL9fdftFFF5Hs7GzS0tJi+rhQKESCwSC59dZbyejRo3XHdNppp5Ef/OAHuu0vueQS0r9/f3aMzz33HAFA/vnPf+q2+3//7/8RAGT58uXstkmTJpFhw4aZrn3atGlRj48QQpYtW0YAkD/84Q+6299++23dax8MBklRURGZPn26brtf/vKXxOVykePHjxNCCFmzZg0BQJ555hnddgcPHiQej4f88pe/1K0dAPn4449jrpMQQu68805TUkKI8r4qKioijY2N7Laqqipis9nIk08+yW6bOnUqKS0tjfiycNddd5G0tLSY70ur9+/48eNJYWEhaWpqYreFQiEyfPhwUlpayl7bRIlVWlqa7v3b1tZG8vLyyO23385u+/GPf0w8Ho+OtIZCITJ48GDdPunfo/H9LHBqQ5QCBQSShAULFsDj8eC6664DAGRmZuKaa67B559/jl27dgEARowYgTFjxuDll19mj9u+fTvWr1+vK9ksWbIEw4cPxxlnnIFQKMT+TZ06lZWneHz/+99Hbm5uxJo++eQTXHjhhfB6vbDb7XA6nXjwwQdRU1OD6upqAMBnn30GALj22mt1j7366qvhcOhtmEuWLMHkyZNRUlKiW9cll1yi21c0DBs2DKNGjdLdNn36dDQ2NmLjxo3stn/961+YOHEiMjMz4XA44HQ6sWDBAmzfvp1tY7PZcNddd2HJkiWoqKgAAOzZswfLli3Dz372M1Yi+uSTT5CRkYGrr75a97y0zPnxxx/HXHe8+OSTT3T7prjmmmuQkZHBnsvhcOAnP/kJ3nvvPTQ0NAAAZFnG66+/jh/84AfIz88HoJxzSZLwk5/8RHfOi4uLMWrUqIj3Qm5uLr7//e8n5VgmT56MrKws9ntRUREKCwtx4MABAErJ8+OPP8ZVV12F9PR03fouvfRS+Hw+rF27NubzGN+/LS0tWLduHa6++mpkZmay2+12O2bMmIFDhw5hx44d7TqmM844A71792a/p6Wl4fTTT2fHBACffvopLrjgAhQVFeme+8c//nHEvlwuF2677Ta8+uqrEaVZgVMTglgJCCQBu3fvxqpVqzBt2jQQQlBfX4/6+np2Iec9HLfccgvWrFmD7777DgDw8ssvw+124/rrr2fbHD16FJs2bYLT6dT9y8rKAiEEx48f1z2/WYfa+vXrMWXKFADAiy++iC+++AJfffUVfvOb3wAA2traAAA1NTUAoLuIAMqFn17c+XUtXrw4Yl3Dhg0DgIh1maG4uNjyNrqW9957D9deey169eqFN954A2vWrMFXX32FW265BT6fT/fYW265BR6PB8899xwA4G9/+xs8Ho+OqNbU1KC4uDjCi1NYWAiHw8GeNxmoqamBw+FAjx49dLdLkoTi4mLdc9HjWbhwIQDgo48+wpEjR3DzzTezbY4ePQpCCIqKiiLO+9q1a+N6L7QXxtcfANxut+69EwqFMH/+/Ii1XXrppQDie08Y11xXVwdCiOmxlJSUsOduD2IdE913tPcpRf/+/bFy5UoUFhbizjvvRP/+/dG/f3/8+c9/btfaBE4OiK5AAYEk4KWXXgIhBO+88w7eeeediPtfffVV/O53v4Pdbsf111+P2bNn45VXXsHjjz+O119/HVdeeaXuG3tBQQE8Ho+pqZbez8PMvLtw4UI4nU4sWbIEaWlp7Pb3339ftx290Bw9ehS9evVit4dCoYiLV0FBAUaOHInHH3/cdF30ohcNVVVVlrfRtbzxxhvo168f3n77bd2xUaM5D6/Xi5tuugl///vfMXfuXLz88suYPn06cnJydMe4bt06EEJ0+6uurkYoFIo4nyeC/Px8hEIhHDt2TEeuCCGoqqrCWWedxW4bOnQozj77bLz88su4/fbb8fLLL6OkpIQRYkA555Ik4fPPP4fb7Y54PuNtZu+FVCE3N5epSHfeeafpNv369Yu5H+Oac3NzYbPZcOTIkYhtKysrAWh/A/S97ff7deciHkJnhfz8/KjvUx7nnnsuzj33XMiyjA0bNmD+/Pm49957UVRUxNRrgVMLQrESEDhByLKMV199Ff3798enn34a8W/OnDk4cuQI/vOf/wBQLhpXXnklXnvtNSxZsgRVVVURnVuXXXYZ9uzZg/z8fIwdOzbiX9++fWOuS5IkOBwO2O12dltbWxtef/113XbnnXceAODtt9/W3f7OO+9EdPpddtllLI7AbF3xEKutW7fi22+/1d32j3/8A1lZWawTTpIkuFwu3QW3qqoqoiuQ4u6778bx48dx9dVXo76+PiLY8oILLkBzc3MEqXzttdfY/ckC3dcbb7yhu/3dd99FS0tLxHPdfPPNWLduHVavXo3Fixfjpptu0r1ml112GQghOHz4sOk5HzFiRLvXSokIr9YkgvT0dEyePBnffPMNRo4cabo+M4UoFjIyMjBu3Di89957urWFw2G88cYbKC0txemnnw4A7G9h06ZNun0sXry4XccEKCXQjz/+GEePHmW3ybIc8TfCw263Y9y4cawbki9rC5xi6Dx7l4DAyYHFixcTAOT//b//Z3r/sWPHiNvtJldeeSW77aOPPiIASGlpKSktLSWyLOse09zcTEaPHk1KS0vJM888Q1asWEE++ugj8uKLL5JrrrmGrF27lm0LgNx5550Rz/vxxx8TAOTqq68my5cvJ2+99RYZM2YMGThwYISp9/rrryd2u5088MADZMWKFbquwJtvvpltV1lZSfr06UMGDx5Mnn32WfLxxx+TDz/8kPztb38j06ZNIwcPHox6roxdgf/5z39YVyB//l566SUCgNxxxx3k448/Jq+88grp378/W7sZLrnkEgKAfO9734u4j3YFZmVlkXnz5pEVK1aQhx56iDidTtYVSHGi5nXaFeh0OsnDDz9MVqxYQZ555hmSmZmp6wqkqK+vJx6Ph5SWlhIAZMeOHRH7vO2220h6ejr5xS9+QRYvXkw++eQT8uabb5I77riDPPvsszHXbgVq8H7ooYfI2rVryVdffUX8fj8hxPp91adPH11Dw9atW0lubi45++yzycsvv0w+/fRT8sEHH5B58+aRyZMnx1yD1fPQrsBx48aRf/3rX6wzz9gV2NDQQPLy8siIESPIokWLyOLFi8mPfvQj0q9fP1PzutlrOGnSJDJp0iT2++bNm4nH4yFDhw4lCxcuJB988AGZOnUqKSsr0+3z//7v/8g111xDXnnl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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "length = len(opponent_results[np.argmax(adversary_probabilities)])\n",
+ "average = [0] * length\n",
+ "for index, adversary_probability in enumerate(adversary_probabilities):\n",
+ " if adversary_probability > 0:\n",
+ " average += adversary_probability * np.array(opponent_results[index])\n",
+ "plt.title(\"Average payoff over the rounds\")\n",
+ "plt.xlabel(\"Rounds\")\n",
+ "plt.ylabel(\"Payoff at the end of each round\")\n",
+ "plt.plot(average)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = \"\"\n",
+ "for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " if name != \"\":\n",
+ " name += \"_\"\n",
+ " name += str(adversary_probabilities[index]) + \"_\" + adversary.name"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "excel_name = name + \".xlsx\"\n",
+ "writer = pd.ExcelWriter(excel_name, engine='xlsxwriter')\n",
+ "for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " df = pd.DataFrame(opponent_results[index])\n",
+ " name = \"Payoff against \" + adversary.name\n",
+ " df.to_excel(writer, sheet_name= name, index=False)\n",
+ "writer.save()\n",
+ "Qtable.save(name)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# We now have the trained agent. We want to test it against each opponent individually, so that\n",
+ "# we can compare it against the agent that is just trained against this opponent."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Adversary Name: imitation_132\n",
+ "Agent Payoff: 116374.0 Adversary Payoff: 66286.0\n",
+ "Agent Actions: [118 132 115 118 107 114 107 104 91 90 99 90 91 87 94 87 92 95\n",
+ " 94 90 91 98 110 122 126]\n",
+ "Adversary Actions: [132 118 132 115 118 107 114 107 104 91 90 99 90 91 87 94 87 92\n",
+ " 95 94 90 91 98 110 122]\n",
+ "Agent Demand Potential: [200. 207. 200. 208. 206. 211. 207. 210. 211. 217. 217. 212. 216. 215.\n",
+ " 217. 213. 216. 213. 211. 211. 213. 212. 208. 202. 196.]\n",
+ "Adversary Name: guess_132\n",
+ "Agent Payoff: 139655.0 Adversary Payoff: 92413.0\n",
+ "Agent Actions: [118 132 132 132 132 132 132 132 132 132 132 132 132 132 128 128 124 123\n",
+ " 123 123 123 124 124 112 135]\n",
+ "Adversary Actions: [132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 124 124 124\n",
+ " 124 124 124 124 124 124 129]\n",
+ "Agent Demand Potential: [200. 207. 207. 207. 207. 207. 207. 207. 207. 207. 207. 207. 207. 207.\n",
+ " 207. 209. 207. 207. 207. 207. 207. 207. 207. 207. 213.]\n"
+ ]
+ }
+ ],
+ "source": [
+ "for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " new_adversary_probabilities =[0]*len(AdversaryModes)\n",
+ " new_adversary_probabilities[index] = 1\n",
+ " result = Test(game, Qtable, discount_factor, new_adversary_probabilities)\n",
+ " payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " print(\"Adversary Name:\", adversary.name)\n",
+ " print(\"Agent Payoff:\", payoff, \"Adversary Payoff:\", adversary_payoff)\n",
+ " print(\"Agent Actions:\", actions)\n",
+ " print(\"Adversary Actions:\", adversary_actions)\n",
+ " print(\"Agent Demand Potential:\", demand_potential)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Memory_and_epsilon_greedy/0.5_imitation_132_0.5_guess_132.xlsx b/qLearning/Memory_and_epsilon_greedy/0.5_imitation_132_0.5_guess_132.xlsx
new file mode 100644
index 0000000..d495c81
Binary files /dev/null and b/qLearning/Memory_and_epsilon_greedy/0.5_imitation_132_0.5_guess_132.xlsx differ
diff --git a/qLearning/Memory_and_epsilon_greedy/QTables/.DS_Store b/qLearning/Memory_and_epsilon_greedy/QTables/.DS_Store
new file mode 100644
index 0000000..bae5052
Binary files /dev/null and b/qLearning/Memory_and_epsilon_greedy/QTables/.DS_Store differ
diff --git a/qLearning/Memory_and_epsilon_greedy/Qtable.py b/qLearning/Memory_and_epsilon_greedy/Qtable.py
new file mode 100644
index 0000000..e40299e
--- /dev/null
+++ b/qLearning/Memory_and_epsilon_greedy/Qtable.py
@@ -0,0 +1,44 @@
+# Ed, Galit and Katerina
+# Relates to the Q-Learning approach.
+# Defines the Q-table
+
+import numpy as np
+import os
+
+class QTable():
+
+
+ def __init__(self, number_demands, number_actions, number_stages, learning_rate):
+
+ self.number_demands= number_demands
+ self.number_actions = number_actions
+ self.number_stages = number_stages
+ self.learning_rate = learning_rate
+ self.Q_table = np.zeros((self.number_demands, self.number_actions, self.number_actions, self.number_stages))
+ self.QTable_name=f"QTable, actions={self.number_actions}, maximum demand={self.number_demands - 1}, stages={self.number_stages}"
+
+
+ def reset(self):
+ Qtable = np.zeros((self.number_demands, self.number_actions, self.number_actions, self.number_stages))
+ return Qtable, self.learning_rate
+
+
+ def random_reset(self):
+ random_Qtable = np.random.rand(self.number_demands, self.number_actions, self.number_actions, self.number_stages)
+ return random_Qtable, self.learning_rate
+
+ def save(self, name = None):
+ if name is None:
+ return np.save(os.path.join('QTables',f'{self.QTable_name}'), self.Q_table)
+ else:
+ return np.save(os.path.join('QTables',name), self.Q_table)
+
+ def load(self,name = None):
+ if name is None:
+ return np.load(os.path.join('QTables',f'{self.QTable_name}'))
+ else:
+ return np.load(os.path.join('QTables',name))
+
+
+
+
diff --git a/qLearning/Memory_and_epsilon_greedy/__pycache__/Qtable.cpython-39.pyc b/qLearning/Memory_and_epsilon_greedy/__pycache__/Qtable.cpython-39.pyc
new file mode 100644
index 0000000..3194122
Binary files /dev/null and b/qLearning/Memory_and_epsilon_greedy/__pycache__/Qtable.cpython-39.pyc differ
diff --git a/qLearning/Memory_and_epsilon_greedy/__pycache__/environment.cpython-39.pyc b/qLearning/Memory_and_epsilon_greedy/__pycache__/environment.cpython-39.pyc
new file mode 100644
index 0000000..10bb51e
Binary files /dev/null and b/qLearning/Memory_and_epsilon_greedy/__pycache__/environment.cpython-39.pyc differ
diff --git a/qLearning/Memory_and_epsilon_greedy/__pycache__/learningAgent.cpython-39.pyc b/qLearning/Memory_and_epsilon_greedy/__pycache__/learningAgent.cpython-39.pyc
new file mode 100644
index 0000000..5ced285
Binary files /dev/null and b/qLearning/Memory_and_epsilon_greedy/__pycache__/learningAgent.cpython-39.pyc differ
diff --git a/qLearning/Memory_and_epsilon_greedy/__pycache__/test.cpython-39.pyc b/qLearning/Memory_and_epsilon_greedy/__pycache__/test.cpython-39.pyc
new file mode 100644
index 0000000..20eb6df
Binary files /dev/null and b/qLearning/Memory_and_epsilon_greedy/__pycache__/test.cpython-39.pyc differ
diff --git a/qLearning/Memory_and_epsilon_greedy/environment.py b/qLearning/Memory_and_epsilon_greedy/environment.py
new file mode 100644
index 0000000..9494874
--- /dev/null
+++ b/qLearning/Memory_and_epsilon_greedy/environment.py
@@ -0,0 +1,259 @@
+# Katerina, Ed and Galit (and Tommy!)
+# Relates to the Q-Learning approach.
+# Contains DemandPotentialGame Class and the Model of the DemandPotentialGame Class.
+
+from enum import Enum
+import numpy as np # numerical python
+# printoptions: output limited to 2 digits after decimal point
+np.set_printoptions(precision=2, suppress=False)
+
+
+class DemandPotentialGame():
+ """
+ Fully defines Demand Potential Game. It contains game rules, memory and agents strategies.
+ """
+
+ def __init__(self, total_demand, costs, total_stages) -> None:
+ self.total_demand = total_demand
+ self.costs = costs
+ self.total_stages = total_stages
+ # first index is always player
+ self.demand_potential = None # two lists for the two players
+ self.prices = None # prices over T rounds
+ self.profit = None # profit in each of T rounds
+ self.stage = None
+
+ def reset_game(self):
+ """
+ Method resets game memory: Demand Potential, prices, profits
+ """
+ self.demand_potential = [[0]*(self.total_stages), [0]*(self.total_stages)] # two lists for the two players
+ self.prices = [[0]*self.total_stages, [0]*self.total_stages] # prices over T rounds
+ self.profit = [[0]*self.total_stages, [0]*self.total_stages] # profit in each of T rounds
+ self.demand_potential[0][0] = self.total_demand / 2 # initialise first round 0
+ self.demand_potential[1][0] = self.total_demand/2
+
+ def profits(self, player=0):
+ """
+ Computes profits. Player 0 is the learning agent.
+ """
+ return self.profit[player][self.stage]
+
+ def update_prices_profit_demand(self, price_pair):
+ """
+ Updates Prices, Profit and Demand Potential Memory.
+ Parameters.
+ price_pair: Pair of prices from the Learning agent and adversary.
+ """
+
+ for player in [0, 1]:
+ price = int(price_pair[player])
+ self.prices[player][self.stage] = price
+ self.profit[player][self.stage] = int((
+ self.demand_potential[player][self.stage] - price)*(price - self.costs[player]))
+ if self.stage < self.total_stages-1:
+ self.demand_potential[0][self.stage + 1] = \
+ int(self.demand_potential[0][self.stage] + (price_pair[1] - price_pair[0])/2)
+ self.demand_potential[1][self.stage + 1] = 400 - self.demand_potential[0][self.stage + 1]
+
+
+ def monopoly_price(self, player): # myopic monopoly price
+ """
+ Computes Monopoly prices.
+ """
+ return (self.demand_potential[player][self.stage] + self.costs[player])/2
+
+ def myopic(self, player=0):
+ """
+ Adversary follows Myopic strategy
+ """
+ return self.monopoly_price(player)
+
+ def const(self, player, price): # constant price strategy
+ """
+ Adversary follows Constant strategy
+ """
+ return price
+
+ def imit(self, player, firstprice): # price imitator strategy
+ if self.stage == 0:
+ return firstprice
+ return self.prices[1-player][self.stage-1]
+
+ def fight(self, player, firstprice): # simplified fighting strategy
+ if self.stage == 0:
+ return firstprice
+ if self.stage == self.total_stages-1:
+ return self.monopoly_price(player)
+ # aspire = [ 207, 193 ] # aspiration level for demand potential
+ aspire = [0, 0]
+ for i in range(2):
+ aspire[i] = (self.total_demand-self.costs[player] +
+ self.costs[1-player])/2
+
+ D = self.demand_potential[player][self.stage]
+ Asp = aspire[player]
+ if D >= Asp: # keep price; DANGER: price will never rise
+ return self.prices[player][self.stage-1]
+ # adjust to get to aspiration level using previous
+ # opponent price; own price has to be reduced by twice
+ # the negative amount D - Asp to getself.demand_potential to Asp
+ P = self.prices[1-player][self.stage-1] + 2*(D - Asp)
+ # never price too high because even 125 gives good profits
+ # P = min(P, 125)
+ aspire_price = (self.total_demand+self.costs[0]+self.costs[1])/4
+ P = min(P, int(0.95*aspire_price))
+
+ return P
+
+ def fight_lb(self, player, firstprice):
+ P = self.fight(player, firstprice)
+ # never price less than production cost
+ P = max(P, self.costs[player])
+ return P
+
+ # sophisticated fighting strategy, compare fight()
+ # estimate *sales* of opponent as their target, kept between
+ # calls in global variable oppsaleguess[]. Assumed behavior
+ # of opponent is similar to this strategy itself.
+ oppsaleguess = [61, 75] # first guess opponent sales as in monopoly
+
+ def guess(self, player, firstprice): # predictive fighting strategy
+ if self.stage == 0:
+ self.oppsaleguess[0] = 61 # always same start
+ self.oppsaleguess[1] = 75 # always same start
+ return firstprice
+
+ if self.stage == self.total_stages-1:
+ return self.monopoly_price(player)
+ aspire = [207, 193] # aspiration level
+ D = self.demand_potential[player][self.stage]
+ Asp = aspire[player]
+
+ if D >= Asp: # keep price, but go slightly towards monopoly if good
+ pmono = self.monopoly_price(player)
+ pcurrent = self.prices[player][self.stage-1]
+ if pcurrent > pmono: # shouldn't happen
+ return pmono
+ if pcurrent > pmono-7: # no change
+ return pcurrent
+ # current low price at 60%, be accommodating towards "collusion"
+ return .6 * pcurrent + .4 * (pmono-7)
+
+ # guess current *opponent price* from previous sales
+ prevsales = self.demand_potential[1 - player][t-1] - self.prices[1-player][t-1]
+ # adjust with weight alpha from previous guess
+ alpha = .5
+ newsalesguess = alpha * self.oppsaleguess[player] + (1-alpha)*prevsales
+ # update
+ self.oppsaleguess[player] = newsalesguess
+ guess_opponent_price = 400 - D - newsalesguess
+ P = guess_opponent_price + 2*(D - Asp)
+
+ if player == 0:
+ P = min(P, 125)
+ if player == 1:
+ P = min(P, 130)
+ return P
+
+
+class Model(DemandPotentialGame):
+ """
+ Defines the Problem's Model. It is assumed a Markov Decision Process is defined. The class is a Child from the Demand Potential Game Class.
+ The reason: Model is a conceptualization of the Game.
+ """
+
+ def __init__(self, total_demand, costs, total_stages, adversary_probabilities) -> None:
+ super().__init__(total_demand, costs, total_stages)
+
+ self.reward_function = self.profits
+
+ # [stage, agent's demand potential, agent previous action, adv previous action]
+ self.initial_state = [0, total_demand/2, 0, 0]
+ self.episode_memory = list()
+ self.done = False
+ self.adversary_probabilities = adversary_probabilities
+
+ def reset(self):
+ """
+ Reset Model Instantiation.
+ """
+ reward = 0
+ self.stage = 0
+ self.done = False
+ self.reset_game()
+ self.reset_adversary()
+ return self.initial_state, reward, self.done
+
+ def reset_adversary(self):
+ options = list(range(len(self.adversary_probabilities)))
+ adversary_index = np.random.choice(options, 1, p= self.adversary_probabilities)
+ self.adversary_mode = AdversaryModes(adversary_index)
+
+ def adversary_choose_price(self):
+ """
+ Strategy followed by the adversary.
+ """
+
+ if self.adversary_mode == AdversaryModes.constant_132:
+ return self.const(player=1, price=132)
+ elif self.adversary_mode == AdversaryModes.constant_95:
+ return self.const(player=1, price=95)
+ elif self.adversary_mode == AdversaryModes.imitation_128:
+ return self.imit(player=1, firstprice=128)
+ elif self.adversary_mode == AdversaryModes.imitation_132:
+ return self.imit(player=1, firstprice=132)
+ elif self.adversary_mode == AdversaryModes.fight_100:
+ return self.fight(player=1, firstprice=100)
+ elif self.adversary_mode == AdversaryModes.fight_125:
+ return self.fight(player=1, firstprice=125)
+ elif self.adversary_mode == AdversaryModes.fight_lb_125:
+ return self.fight_lb(player=1, firstprice=125)
+ elif self.adversary_mode == AdversaryModes.fight_132:
+ return self.fight(player=1, firstprice=132)
+ elif self.adversary_mode == AdversaryModes.fight_lb_132:
+ return self.fight_lb(player=1, firstprice=132)
+ elif self.adversary_mode == AdversaryModes.guess_125:
+ return self.fight(player=1, firstprice=125)
+ elif self.adversary_mode == AdversaryModes.guess_132:
+ return self.fight(player=1, firstprice=132)
+ else:
+ return self.myopic(player=1)
+
+ def step(self, state, action, action_index):
+ """
+ Transition Function.
+ Parameters:
+ - action: Price
+ - state: tupple in the latest stage (stage ,Demand Potential, Adversary Action)
+ """
+ adversary_action = int(self.adversary_choose_price())
+ self.update_prices_profit_demand([action, adversary_action])
+
+ done = (self.stage == self.total_stages-1)
+
+
+ if not done:
+ new_state = [self.stage+1, self.demand_potential[0][self.stage + 1], action_index, adversary_action]
+ else:
+ new_state = [self.stage+1, 0, action_index, adversary_action]
+
+ reward = self.reward_function()
+ self.stage = self.stage + 1
+
+ return new_state, reward, done
+
+
+class AdversaryModes(Enum):
+ myopic = 0
+ constant_132 = 1
+ constant_95 = 2
+ imitation_132 = 3
+ imitation_128 = 4
+ fight_132 = 5
+ fight_lb_132 = 6
+ fight_125 = 7
+ fight_lb_125 = 8
+ fight_100 = 9
+ guess_132 = 10
+ guess_125 = 11
\ No newline at end of file
diff --git a/qLearning/Memory_and_epsilon_greedy/learningAgent.py b/qLearning/Memory_and_epsilon_greedy/learningAgent.py
new file mode 100644
index 0000000..e1930b3
--- /dev/null
+++ b/qLearning/Memory_and_epsilon_greedy/learningAgent.py
@@ -0,0 +1,113 @@
+# Ed, Kat, Galit
+# ReinforceAlgorithm Class: Solver.
+# Implement an off-policy Q-learning algorithm
+
+import numpy as np
+
+# print options: output limited to 2 digits after decimal point
+np.set_printoptions(precision=2, suppress=False)
+
+
+class LearningAlgorithm():
+ """
+ Model Solver.
+ """
+ def __init__(self, Model, Qtable, number_episodes, discount_factor) -> None:
+
+ self.env = Model
+ self.Qtable = Qtable.Q_table
+ self.learning_rate = Qtable.learning_rate
+ self.number_episodes = number_episodes
+ self.gamma = discount_factor
+ self.number_demands=Qtable.number_demands
+ self.number_stages=Qtable.number_stages
+ self.number_actions=Qtable.number_actions
+ self.highest_demand = int(self.number_demands - 1)
+
+
+ def reset_Qtable(self):
+ self.Qtable, self.learning_rate = self.Qtable.reset()
+
+
+ def action_index(self, monopoly_price, action): # computes action index in Qtable
+ return int(action - (monopoly_price - self.number_actions + 1)) #monopoly_price should have index number_actions - 1
+
+ def alpha_n(self, n): # defines the Qlearning rate
+ return self.learning_rate[0]/(n+self.learning_rate[1])
+
+ """
+ Now the Q-learning itself
+ """
+
+ def q_learning(self, state_action_value, optimal_next_value, reward, alpha, gamma):
+ target = reward + gamma * optimal_next_value
+ return state_action_value + alpha * (target - state_action_value)
+
+
+
+
+
+ def epsilon_greedy_learning(self, number_episodes, number_previous_episodes, total_number_episodes):
+
+ best_payoff = 0
+ best_actions = list()
+
+ for episode in range(number_episodes):
+
+ state, reward, done = self.env.reset()
+
+ payoff = 0
+ actions = list()
+ discount = 1
+
+ while not done:
+ stage, agent_demand, agent_previous_action, adversary_previous_action = state
+ if (agent_demand < 0) or (agent_demand > self.highest_demand):
+ break
+ if (stage > 0 and adversary_previous_action < self.env.costs[1]) or (self.highest_demand - agent_demand < adversary_previous_action):
+ break
+ demand_index = int(agent_demand)
+ monopoly_price = int((agent_demand + self.env.costs[0]) / 2)
+ greedy_action_index = np.argmax(self.Qtable[demand_index, :, agent_previous_action, stage])
+ action = self.epsilon_greedy_policy(monopoly_price, episode, number_previous_episodes, greedy_action_index, total_number_episodes)
+ actions.append(action)
+ action_index = self.action_index(monopoly_price, action)
+ state, reward, done = self.env.step(state, action, action_index)
+ payoff += reward * discount
+ discount *= self.gamma
+
+ # updating the Qtable
+ if done:
+ optimal_next_value = 0
+ else:
+ optimal_next_value = max(self.Qtable[int(state[1]),:, action_index, state[0]])
+
+ current_q_value = self.Qtable[demand_index, action_index, agent_previous_action, stage]
+ self.Qtable[demand_index, action_index, agent_previous_action, stage] = self.q_learning(current_q_value, optimal_next_value, reward, self.alpha_n(episode), self.gamma)
+# if stage == 0 and current_q_value > 95000:
+# print("old", current_q_value)
+# print("new", self.Qtable[demand_index, action_index, agent_previous_action, stage])
+# print(np.max(self.Qtable))
+
+
+ if payoff > best_payoff:
+ best_payoff = payoff
+ best_actions = actions
+ if episode == number_episodes - 1:
+ print("Best payoff: ", best_payoff)
+ print("Best actions: ", best_actions)
+
+
+ def epsilon_greedy_policy(self, monopoly_price, episode, number_previous_episodes, greedy_action_index, total_number_episodes):
+ epsilon = 1 - (episode + number_previous_episodes)/total_number_episodes
+ if np.random.binomial(1,epsilon) == 1:
+ action = np.random.randint(monopoly_price-self.number_actions+1, monopoly_price + 1)
+ else:
+ action = greedy_action_index + (monopoly_price - self.number_actions + 1)
+ action = max(0, action)
+ if self.env.costs[0] > action:
+ action = monopoly_price
+ return action
+
+
+
diff --git a/qLearning/Memory_and_epsilon_greedy/qLearningSimulations.ipynb b/qLearning/Memory_and_epsilon_greedy/qLearningSimulations.ipynb
new file mode 100644
index 0000000..62573dc
--- /dev/null
+++ b/qLearning/Memory_and_epsilon_greedy/qLearningSimulations.ipynb
@@ -0,0 +1,1353 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "import pandas as pd"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_demand = 400\n",
+ "agent_cost = 57\n",
+ "adversary_cost = 71 \n",
+ "costs = [agent_cost,adversary_cost]\n",
+ "total_stages = 25\n",
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Below is where we decide what adversaries we train against. See environment.py for the numbers\n",
+ "adversary_probabilities[3]= 0.5\n",
+ "adversary_probabilities[10] = 0.5\n",
+ "game = Model(total_demand, costs, total_stages, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2040816\n"
+ ]
+ }
+ ],
+ "source": [
+ "number_actions = 50\n",
+ "number_demands = total_demand + 1\n",
+ "discount_factor = 1\n",
+ "number_episodes = 100_000_000\n",
+ "constant = int(number_episodes/49)\n",
+ "print(constant)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+denominator)\n",
+ "Qtable = QTable(number_demands, number_actions, total_stages , learning_rate = [constant,constant])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, number_episodes, discount_factor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "opponent_results = [list() for mode in AdversaryModes]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "pycharm": {
+ "is_executing": true
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Round 0 of 200\n",
+ "Best payoff: 131209\n",
+ "Best actions: [123, 109, 103, 120, 118, 106, 118, 124, 126, 96, 114, 102, 129, 107, 122, 122, 110, 108, 123, 116, 121, 122, 107, 111, 129]\n",
+ "Current payoff against imitation_132 : 129237.0\n",
+ "Current payoff against guess_132 : 105869.0\n",
+ "Round 1 of 200\n",
+ "Best payoff: 119340\n",
+ "Best actions: [118, 125, 119, 114, 124, 100, 117, 104, 128, 109, 122, 82, 118, 108, 111, 121, 104, 117, 85, 111, 121, 108, 106, 122, 79]\n",
+ "Current payoff against imitation_132 : 129771.0\n",
+ "Current payoff against guess_132 : 84732.0\n",
+ "Round 2 of 200\n",
+ "Best payoff: 120336\n",
+ "Best actions: [119, 125, 121, 128, 130, 112, 120, 118, 122, 111, 126, 84, 127, 128, 126, 101, 120, 107, 124, 104, 119, 125, 124, 83, 113]\n",
+ "Current payoff against imitation_132 : 131184.0\n",
+ "Current payoff against guess_132 : 101847.0\n",
+ "Round 3 of 200\n",
+ "Best payoff: 121155\n",
+ "Best actions: [120, 122, 119, 118, 120, 121, 116, 113, 111, 118, 112, 129, 83, 108, 122, 119, 78, 126, 99, 117, 108, 113, 116, 94, 106]\n",
+ "Current payoff against imitation_132 : 131996.0\n",
+ "Current payoff against guess_132 : 103929.0\n",
+ "Round 4 of 200\n",
+ "Best payoff: 121215\n",
+ "Best actions: [128, 128, 120, 128, 116, 119, 103, 128, 103, 115, 106, 114, 125, 114, 104, 109, 120, 120, 117, 96, 124, 89, 112, 93, 83]\n",
+ "Current payoff against imitation_132 : 131246.0\n",
+ "Current payoff against guess_132 : 95060.0\n",
+ "Round 5 of 200\n",
+ "Best payoff: 119175\n",
+ "Best actions: [127, 116, 125, 117, 100, 111, 120, 100, 103, 123, 99, 112, 102, 130, 109, 125, 93, 106, 102, 107, 104, 121, 94, 116, 116]\n",
+ "Current payoff against imitation_132 : 129168.0\n",
+ "Current payoff against guess_132 : 124116.0\n",
+ "Round 6 of 200\n",
+ "Best payoff: 124071\n",
+ "Best actions: [121, 123, 132, 110, 118, 130, 122, 118, 109, 117, 122, 125, 123, 109, 116, 121, 126, 122, 99, 107, 101, 120, 121, 104, 101]\n",
+ "Current payoff against imitation_132 : 129107.0\n",
+ "Current payoff against guess_132 : 129024.0\n",
+ "Round 7 of 200\n",
+ "Best payoff: 120909\n",
+ "Best actions: [122, 122, 119, 117, 118, 123, 127, 124, 85, 117, 120, 115, 112, 122, 111, 122, 117, 111, 115, 100, 99, 89, 124, 80, 116]\n",
+ "Current payoff against imitation_132 : 131162.0\n",
+ "Current payoff against guess_132 : 116907.0\n",
+ "Round 8 of 200\n",
+ "Best payoff: 119170\n",
+ "Best actions: [126, 125, 130, 123, 121, 130, 121, 113, 119, 112, 111, 118, 107, 103, 118, 116, 108, 97, 89, 85, 111, 103, 121, 114, 119]\n",
+ "Current payoff against imitation_132 : 130118.0\n",
+ "Current payoff against guess_132 : 109656.0\n",
+ "Round 9 of 200\n",
+ "Best payoff: 121029\n",
+ "Best actions: [120, 130, 121, 128, 102, 125, 114, 110, 92, 114, 127, 99, 122, 118, 100, 112, 103, 102, 124, 123, 82, 114, 119, 94, 120]\n",
+ "Current payoff against imitation_132 : 129276.0\n",
+ "Current payoff against guess_132 : 116401.0\n",
+ "Round 10 of 200\n",
+ "Best payoff: 124031\n",
+ "Best actions: [122, 120, 129, 112, 108, 114, 105, 123, 111, 110, 127, 104, 98, 117, 105, 125, 104, 104, 113, 118, 102, 114, 107, 98, 125]\n",
+ "Current payoff against imitation_132 : 132126.0\n",
+ "Current payoff against guess_132 : 114874.0\n",
+ "Round 11 of 200\n",
+ "Best payoff: 117853\n",
+ "Best actions: [119, 130, 132, 124, 116, 115, 109, 112, 122, 107, 117, 99, 95, 116, 119, 116, 117, 89, 111, 76, 122, 113, 85, 113, 125]\n",
+ "Current payoff against imitation_132 : 132067.0\n",
+ "Current payoff against guess_132 : 118955.0\n",
+ "Round 12 of 200\n",
+ "Best payoff: 121339\n",
+ "Best actions: [117, 127, 126, 130, 117, 116, 123, 107, 110, 116, 117, 128, 123, 104, 107, 125, 85, 105, 125, 100, 125, 85, 119, 102, 118]\n",
+ "Current payoff against imitation_132 : 131864.0\n",
+ "Current payoff against guess_132 : 115270.0\n",
+ "Round 13 of 200\n",
+ "Best payoff: 124572\n",
+ "Best actions: [117, 127, 128, 125, 117, 119, 113, 129, 124, 126, 81, 123, 121, 122, 94, 114, 113, 118, 130, 113, 105, 110, 91, 131, 110]\n",
+ "Current payoff against imitation_132 : 130813.0\n",
+ "Current payoff against guess_132 : 103439.0\n",
+ "Round 14 of 200\n",
+ "Best payoff: 121152\n",
+ "Best actions: [120, 122, 121, 113, 117, 120, 114, 128, 106, 99, 124, 106, 116, 115, 115, 128, 121, 82, 125, 112, 117, 88, 114, 101, 88]\n",
+ "Current payoff against imitation_132 : 131648.0\n",
+ "Current payoff against guess_132 : 118729.0\n",
+ "Round 15 of 200\n",
+ "Best payoff: 119283\n",
+ "Best actions: [121, 122, 115, 113, 118, 107, 129, 109, 120, 104, 115, 108, 90, 131, 107, 108, 102, 116, 113, 125, 114, 89, 100, 97, 130]\n",
+ "Current payoff against imitation_132 : 131090.0\n",
+ "Current payoff against guess_132 : 117797.0\n",
+ "Round 16 of 200\n",
+ "Best payoff: 119735\n",
+ "Best actions: [122, 130, 119, 118, 125, 95, 121, 104, 120, 93, 114, 96, 122, 101, 117, 104, 111, 102, 112, 120, 89, 124, 95, 109, 86]\n",
+ "Current payoff against imitation_132 : 131329.0\n",
+ "Current payoff against guess_132 : 112424.0\n",
+ "Round 17 of 200\n",
+ "Best payoff: 121508\n",
+ "Best actions: [123, 124, 129, 119, 118, 126, 130, 114, 122, 114, 111, 130, 114, 102, 100, 112, 119, 120, 79, 117, 122, 91, 123, 100, 105]\n",
+ "Current payoff against imitation_132 : 131096.0\n",
+ "Current payoff against guess_132 : 96768.0\n",
+ "Round 18 of 200\n",
+ "Best payoff: 121564\n",
+ "Best actions: [128, 121, 124, 124, 125, 108, 121, 116, 130, 120, 124, 100, 112, 108, 118, 107, 111, 106, 104, 111, 120, 105, 110, 79, 98]\n",
+ "Current payoff against imitation_132 : 131670.0\n",
+ "Current payoff against guess_132 : 113417.0\n",
+ "Round 19 of 200\n",
+ "Best payoff: 121528\n",
+ "Best actions: [122, 128, 118, 115, 124, 127, 91, 129, 112, 109, 103, 121, 121, 105, 102, 108, 121, 104, 109, 117, 78, 119, 105, 113, 111]\n",
+ "Current payoff against imitation_132 : 132083.0\n",
+ "Current payoff against guess_132 : 119319.0\n",
+ "Round 20 of 200\n",
+ "Best payoff: 120442\n",
+ "Best actions: [125, 118, 122, 115, 123, 127, 84, 105, 114, 126, 117, 106, 107, 103, 117, 101, 127, 107, 102, 116, 109, 98, 124, 118, 102]\n",
+ "Current payoff against imitation_132 : 131596.0\n",
+ "Current payoff against guess_132 : 118500.0\n",
+ "Round 21 of 200\n",
+ "Best payoff: 124806\n",
+ "Best actions: [120, 127, 125, 119, 121, 124, 123, 121, 89, 113, 130, 97, 118, 108, 106, 110, 122, 112, 112, 103, 114, 118, 104, 115, 130]\n",
+ "Current payoff against imitation_132 : 131519.0\n",
+ "Current payoff against guess_132 : 108825.0\n",
+ "Round 22 of 200\n",
+ "Best payoff: 121898\n",
+ "Best actions: [124, 125, 132, 132, 123, 133, 118, 106, 111, 121, 114, 126, 108, 103, 108, 123, 114, 91, 114, 109, 79, 124, 93, 95, 125]\n",
+ "Current payoff against imitation_132 : 131946.0\n",
+ "Current payoff against guess_132 : 120353.0\n",
+ "Round 23 of 200\n",
+ "Best payoff: 120817\n",
+ "Best actions: [121, 123, 127, 115, 123, 118, 120, 117, 118, 128, 120, 119, 109, 122, 111, 119, 119, 119, 97, 113, 88, 110, 94, 84, 105]\n",
+ "Current payoff against imitation_132 : 129515.0\n",
+ "Current payoff against guess_132 : 119003.0\n",
+ "Round 24 of 200\n",
+ "Best payoff: 120660\n",
+ "Best actions: [118, 131, 128, 126, 121, 121, 124, 115, 119, 113, 116, 108, 114, 104, 113, 119, 92, 91, 128, 101, 93, 113, 88, 117, 89]\n",
+ "Current payoff against imitation_132 : 128539.0\n",
+ "Current payoff against guess_132 : 123110.0\n",
+ "Round 25 of 200\n",
+ "Best payoff: 125847\n",
+ "Best actions: [120, 127, 121, 121, 122, 112, 115, 108, 121, 127, 109, 116, 102, 129, 113, 128, 119, 93, 110, 108, 122, 112, 119, 126, 99]\n",
+ "Current payoff against imitation_132 : 131903.0\n",
+ "Current payoff against guess_132 : 114894.0\n",
+ "Round 26 of 200\n",
+ "Best payoff: 124565\n",
+ "Best actions: [128, 122, 132, 125, 123, 120, 121, 118, 113, 116, 113, 114, 129, 113, 90, 110, 116, 118, 106, 91, 126, 104, 98, 87, 134]\n",
+ "Current payoff against imitation_132 : 130481.0\n",
+ "Current payoff against guess_132 : 114837.0\n",
+ "Round 27 of 200\n",
+ "Best payoff: 124997\n",
+ "Best actions: [125, 123, 123, 130, 106, 131, 114, 105, 113, 111, 129, 110, 125, 108, 108, 123, 110, 128, 88, 116, 127, 109, 94, 130, 111]\n",
+ "Current payoff against imitation_132 : 129467.0\n",
+ "Current payoff against guess_132 : 116194.0\n",
+ "Round 28 of 200\n",
+ "Best payoff: 125660\n",
+ "Best actions: [118, 132, 132, 130, 123, 121, 121, 117, 120, 124, 105, 116, 118, 118, 105, 115, 106, 114, 117, 104, 102, 85, 104, 114, 102]\n",
+ "Current payoff against imitation_132 : 130858.0\n",
+ "Current payoff against guess_132 : 114799.0\n",
+ "Round 29 of 200\n",
+ "Best payoff: 120383\n",
+ "Best actions: [128, 126, 113, 111, 109, 109, 109, 112, 101, 114, 122, 90, 101, 105, 114, 99, 109, 122, 99, 125, 89, 118, 86, 105, 127]\n",
+ "Current payoff against imitation_132 : 131896.0\n",
+ "Current payoff against guess_132 : 115266.0\n",
+ "Round 30 of 200\n",
+ "Best payoff: 123093\n",
+ "Best actions: [127, 128, 122, 128, 116, 120, 113, 114, 114, 110, 124, 107, 117, 91, 101, 124, 89, 113, 130, 90, 110, 100, 101, 98, 124]\n",
+ "Current payoff against imitation_132 : 129698.0\n",
+ "Current payoff against guess_132 : 133242.0\n",
+ "Round 31 of 200\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best payoff: 123927\n",
+ "Best actions: [118, 122, 116, 114, 116, 121, 121, 104, 99, 116, 112, 111, 116, 111, 107, 110, 111, 115, 113, 124, 89, 98, 87, 111, 126]\n",
+ "Current payoff against imitation_132 : 129605.0\n",
+ "Current payoff against guess_132 : 111266.0\n",
+ "Round 32 of 200\n",
+ "Best payoff: 121323\n",
+ "Best actions: [115, 131, 108, 124, 93, 124, 100, 113, 112, 117, 118, 102, 121, 110, 120, 113, 104, 119, 119, 125, 103, 111, 98, 109, 131]\n",
+ "Current payoff against imitation_132 : 131010.0\n",
+ "Current payoff against guess_132 : 123313.0\n",
+ "Round 33 of 200\n",
+ "Best payoff: 125523\n",
+ "Best actions: [117, 132, 132, 129, 123, 121, 127, 120, 110, 127, 117, 111, 126, 102, 101, 131, 92, 107, 107, 119, 105, 95, 126, 115, 100]\n",
+ "Current payoff against imitation_132 : 129907.0\n",
+ "Current payoff against guess_132 : 113485.0\n",
+ "Round 34 of 200\n",
+ "Best payoff: 122937\n",
+ "Best actions: [118, 127, 122, 129, 118, 127, 110, 107, 121, 112, 121, 124, 86, 109, 132, 110, 97, 104, 128, 120, 94, 118, 106, 103, 128]\n",
+ "Current payoff against imitation_132 : 132022.0\n",
+ "Current payoff against guess_132 : 123725.0\n",
+ "Round 35 of 200\n",
+ "Best payoff: 120488\n",
+ "Best actions: [118, 132, 124, 124, 114, 114, 121, 102, 121, 112, 104, 107, 131, 93, 103, 115, 86, 107, 105, 124, 118, 79, 120, 103, 102]\n",
+ "Current payoff against imitation_132 : 131170.0\n",
+ "Current payoff against guess_132 : 113644.0\n",
+ "Round 36 of 200\n",
+ "Best payoff: 121026\n",
+ "Best actions: [118, 132, 132, 123, 121, 121, 116, 110, 122, 113, 101, 90, 120, 100, 98, 92, 109, 107, 110, 111, 80, 114, 117, 111, 124]\n",
+ "Current payoff against imitation_132 : 131154.0\n",
+ "Current payoff against guess_132 : 119114.0\n",
+ "Round 37 of 200\n",
+ "Best payoff: 121944\n",
+ "Best actions: [121, 128, 117, 115, 115, 118, 109, 117, 128, 90, 114, 125, 121, 100, 123, 100, 121, 114, 108, 111, 98, 113, 113, 99, 90]\n",
+ "Current payoff against imitation_132 : 129420.0\n",
+ "Current payoff against guess_132 : 101753.0\n",
+ "Round 38 of 200\n",
+ "Best payoff: 129453\n",
+ "Best actions: [118, 132, 132, 119, 116, 125, 116, 113, 103, 121, 114, 115, 103, 116, 115, 120, 113, 102, 114, 114, 117, 113, 110, 111, 112]\n",
+ "Current payoff against imitation_132 : 128975.0\n",
+ "Current payoff against guess_132 : 120056.0\n",
+ "Round 39 of 200\n",
+ "Best payoff: 126421\n",
+ "Best actions: [118, 130, 125, 120, 118, 128, 107, 129, 112, 125, 123, 116, 116, 89, 129, 104, 118, 123, 100, 119, 115, 112, 116, 112, 105]\n",
+ "Current payoff against imitation_132 : 129178.0\n",
+ "Current payoff against guess_132 : 119629.0\n",
+ "Round 40 of 200\n",
+ "Best payoff: 120076\n",
+ "Best actions: [118, 132, 123, 121, 120, 127, 121, 114, 118, 124, 120, 103, 122, 111, 86, 95, 97, 110, 96, 101, 99, 102, 93, 114, 94]\n",
+ "Current payoff against imitation_132 : 130193.0\n",
+ "Current payoff against guess_132 : 120080.0\n",
+ "Round 41 of 200\n",
+ "Best payoff: 125172\n",
+ "Best actions: [123, 127, 130, 132, 126, 123, 130, 122, 127, 111, 114, 115, 114, 116, 118, 91, 113, 122, 90, 109, 96, 118, 93, 108, 118]\n",
+ "Current payoff against imitation_132 : 129703.0\n",
+ "Current payoff against guess_132 : 107108.0\n",
+ "Round 42 of 200\n",
+ "Best payoff: 125243\n",
+ "Best actions: [118, 131, 123, 126, 111, 122, 110, 111, 118, 116, 112, 115, 128, 119, 125, 109, 116, 119, 88, 110, 112, 117, 126, 111, 93]\n",
+ "Current payoff against imitation_132 : 131307.0\n",
+ "Current payoff against guess_132 : 121693.0\n",
+ "Round 43 of 200\n",
+ "Best payoff: 120824\n",
+ "Best actions: [126, 124, 132, 119, 116, 118, 116, 116, 129, 102, 107, 108, 120, 121, 83, 102, 105, 101, 107, 105, 98, 85, 103, 124, 117]\n",
+ "Current payoff against imitation_132 : 131060.0\n",
+ "Current payoff against guess_132 : 122183.0\n",
+ "Round 44 of 200\n",
+ "Best payoff: 125035\n",
+ "Best actions: [118, 124, 134, 120, 117, 105, 111, 121, 108, 113, 121, 109, 107, 121, 108, 105, 117, 124, 97, 107, 111, 116, 102, 93, 106]\n",
+ "Current payoff against imitation_132 : 129653.0\n",
+ "Current payoff against guess_132 : 105133.0\n",
+ "Round 45 of 200\n",
+ "Best payoff: 125053\n",
+ "Best actions: [128, 127, 128, 130, 131, 122, 117, 133, 109, 111, 123, 101, 118, 113, 101, 119, 111, 116, 106, 113, 101, 130, 99, 108, 112]\n",
+ "Current payoff against imitation_132 : 128445.0\n",
+ "Current payoff against guess_132 : 117996.0\n",
+ "Round 46 of 200\n",
+ "Best payoff: 122825\n",
+ "Best actions: [118, 119, 116, 129, 111, 119, 116, 105, 102, 116, 113, 118, 121, 124, 119, 107, 103, 125, 100, 119, 112, 97, 111, 110, 97]\n",
+ "Current payoff against imitation_132 : 129292.0\n",
+ "Current payoff against guess_132 : 104780.0\n",
+ "Round 47 of 200\n",
+ "Best payoff: 123725\n",
+ "Best actions: [118, 129, 125, 124, 123, 125, 118, 122, 129, 101, 126, 114, 112, 107, 110, 122, 99, 98, 112, 102, 117, 108, 105, 118, 79]\n",
+ "Current payoff against imitation_132 : 129612.0\n",
+ "Current payoff against guess_132 : 123541.0\n",
+ "Round 48 of 200\n",
+ "Best payoff: 122811\n",
+ "Best actions: [118, 132, 132, 132, 128, 120, 112, 110, 114, 117, 119, 98, 123, 101, 102, 110, 100, 100, 104, 118, 125, 96, 91, 118, 128]\n",
+ "Current payoff against imitation_132 : 131026.0\n",
+ "Current payoff against guess_132 : 125236.0\n",
+ "Round 49 of 200\n",
+ "Best payoff: 123310\n",
+ "Best actions: [122, 128, 132, 132, 128, 123, 121, 118, 116, 127, 106, 119, 122, 126, 94, 103, 111, 113, 121, 104, 122, 83, 94, 102, 79]\n",
+ "Current payoff against imitation_132 : 130918.0\n",
+ "Current payoff against guess_132 : 119937.0\n",
+ "Round 50 of 200\n",
+ "Best payoff: 125929\n",
+ "Best actions: [120, 130, 131, 132, 128, 128, 126, 123, 122, 118, 130, 110, 115, 122, 114, 117, 90, 105, 120, 124, 124, 98, 114, 110, 111]\n",
+ "Current payoff against imitation_132 : 130626.0\n",
+ "Current payoff against guess_132 : 117153.0\n",
+ "Round 51 of 200\n",
+ "Best payoff: 130660\n",
+ "Best actions: [118, 129, 125, 123, 121, 130, 113, 119, 122, 123, 121, 109, 130, 108, 113, 120, 119, 119, 129, 121, 109, 118, 112, 112, 93]\n",
+ "Current payoff against imitation_132 : 128372.0\n",
+ "Current payoff against guess_132 : 102666.0\n",
+ "Round 52 of 200\n",
+ "Best payoff: 123135\n",
+ "Best actions: [118, 132, 122, 120, 129, 112, 113, 116, 111, 122, 111, 95, 105, 104, 105, 105, 113, 94, 120, 100, 89, 95, 108, 109, 124]\n",
+ "Current payoff against imitation_132 : 128398.0\n",
+ "Current payoff against guess_132 : 132393.0\n",
+ "Round 53 of 200\n",
+ "Best payoff: 123675\n",
+ "Best actions: [118, 127, 126, 125, 118, 123, 124, 105, 111, 112, 116, 103, 114, 110, 108, 118, 110, 107, 123, 82, 99, 99, 99, 116, 110]\n",
+ "Current payoff against imitation_132 : 130356.0\n",
+ "Current payoff against guess_132 : 118175.0\n",
+ "Round 54 of 200\n",
+ "Best payoff: 127231\n",
+ "Best actions: [118, 132, 129, 125, 123, 118, 116, 117, 122, 103, 117, 115, 122, 117, 107, 119, 100, 122, 110, 121, 122, 124, 107, 114, 125]\n",
+ "Current payoff against imitation_132 : 129369.0\n",
+ "Current payoff against guess_132 : 112634.0\n",
+ "Round 55 of 200\n",
+ "Best payoff: 123463\n",
+ "Best actions: [118, 132, 132, 132, 132, 124, 119, 129, 109, 109, 109, 121, 102, 119, 116, 86, 99, 120, 105, 94, 114, 114, 95, 104, 100]\n",
+ "Current payoff against imitation_132 : 131247.0\n",
+ "Current payoff against guess_132 : 112513.0\n",
+ "Round 56 of 200\n",
+ "Best payoff: 126449\n",
+ "Best actions: [118, 128, 128, 122, 118, 119, 122, 110, 121, 124, 96, 119, 126, 111, 97, 113, 114, 121, 110, 105, 117, 109, 121, 95, 107]\n",
+ "Current payoff against imitation_132 : 128873.0\n",
+ "Current payoff against guess_132 : 117819.0\n",
+ "Round 57 of 200\n",
+ "Best payoff: 124184\n",
+ "Best actions: [123, 126, 132, 127, 125, 132, 112, 114, 128, 95, 110, 109, 103, 131, 117, 91, 103, 107, 116, 118, 113, 89, 100, 115, 116]\n",
+ "Current payoff against imitation_132 : 131109.0\n",
+ "Current payoff against guess_132 : 118124.0\n",
+ "Round 58 of 200\n",
+ "Best payoff: 126593\n",
+ "Best actions: [118, 132, 132, 125, 122, 121, 117, 125, 116, 113, 120, 120, 97, 126, 114, 118, 104, 111, 110, 121, 113, 121, 128, 113, 77]\n",
+ "Current payoff against imitation_132 : 130843.0\n",
+ "Current payoff against guess_132 : 133056.0\n",
+ "Round 59 of 200\n",
+ "Best payoff: 123305\n",
+ "Best actions: [127, 122, 132, 132, 132, 126, 124, 123, 115, 115, 123, 126, 80, 111, 121, 122, 81, 120, 125, 76, 109, 111, 121, 110, 97]\n",
+ "Current payoff against imitation_132 : 132406.0\n",
+ "Current payoff against guess_132 : 130799.0\n",
+ "Round 60 of 200\n",
+ "Best payoff: 124038\n",
+ "Best actions: [118, 126, 124, 124, 132, 111, 119, 122, 119, 112, 118, 114, 123, 109, 125, 116, 105, 114, 103, 108, 106, 84, 127, 112, 77]\n",
+ "Current payoff against imitation_132 : 130704.0\n",
+ "Current payoff against guess_132 : 118072.0\n",
+ "Round 61 of 200\n",
+ "Best payoff: 129460\n",
+ "Best actions: [118, 132, 132, 132, 132, 129, 123, 121, 119, 118, 127, 128, 102, 118, 109, 127, 118, 113, 123, 115, 121, 105, 105, 118, 89]\n",
+ "Current payoff against imitation_132 : 131018.0\n",
+ "Current payoff against guess_132 : 135326.0\n",
+ "Round 62 of 200\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best payoff: 124061\n",
+ "Best actions: [122, 128, 132, 130, 125, 123, 122, 119, 130, 125, 123, 100, 115, 119, 127, 104, 129, 110, 127, 120, 107, 93, 132, 80, 107]\n",
+ "Current payoff against imitation_132 : 130784.0\n",
+ "Current payoff against guess_132 : 121527.0\n",
+ "Round 63 of 200\n",
+ "Best payoff: 126906\n",
+ "Best actions: [118, 132, 126, 124, 121, 119, 119, 121, 121, 111, 114, 127, 109, 113, 120, 118, 121, 87, 118, 102, 105, 117, 122, 108, 89]\n",
+ "Current payoff against imitation_132 : 129366.0\n",
+ "Current payoff against guess_132 : 130976.0\n",
+ "Round 64 of 200\n",
+ "Best payoff: 127324\n",
+ "Best actions: [118, 125, 122, 119, 116, 115, 113, 113, 114, 122, 127, 115, 118, 95, 117, 101, 118, 114, 114, 115, 108, 108, 116, 126, 101]\n",
+ "Current payoff against imitation_132 : 129596.0\n",
+ "Current payoff against guess_132 : 132873.0\n",
+ "Round 65 of 200\n",
+ "Best payoff: 125428\n",
+ "Best actions: [118, 132, 123, 134, 102, 126, 108, 119, 109, 115, 115, 120, 108, 129, 102, 109, 112, 120, 129, 84, 106, 120, 115, 105, 111]\n",
+ "Current payoff against imitation_132 : 131812.0\n",
+ "Current payoff against guess_132 : 125163.0\n",
+ "Round 66 of 200\n",
+ "Best payoff: 126031\n",
+ "Best actions: [118, 131, 132, 124, 127, 128, 117, 114, 109, 106, 116, 116, 118, 116, 113, 118, 108, 120, 96, 101, 101, 98, 102, 87, 106]\n",
+ "Current payoff against imitation_132 : 126246.0\n",
+ "Current payoff against guess_132 : 116904.0\n",
+ "Round 67 of 200\n",
+ "Best payoff: 125542\n",
+ "Best actions: [118, 132, 132, 132, 130, 125, 123, 121, 120, 116, 120, 111, 121, 112, 114, 123, 98, 103, 120, 83, 89, 113, 96, 120, 100]\n",
+ "Current payoff against imitation_132 : 129017.0\n",
+ "Current payoff against guess_132 : 130019.0\n",
+ "Round 68 of 200\n",
+ "Best payoff: 127913\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 125, 122, 119, 122, 130, 103, 118, 113, 115, 125, 117, 116, 109, 107, 92, 103, 114, 99, 114]\n",
+ "Current payoff against imitation_132 : 130494.0\n",
+ "Current payoff against guess_132 : 134926.0\n",
+ "Round 69 of 200\n",
+ "Best payoff: 124749\n",
+ "Best actions: [118, 132, 132, 132, 132, 126, 124, 121, 132, 125, 110, 117, 115, 131, 105, 130, 121, 104, 119, 100, 122, 113, 118, 94, 96]\n",
+ "Current payoff against imitation_132 : 131324.0\n",
+ "Current payoff against guess_132 : 134955.0\n",
+ "Round 70 of 200\n",
+ "Best payoff: 127187\n",
+ "Best actions: [118, 132, 132, 132, 132, 128, 124, 130, 115, 122, 126, 115, 124, 114, 128, 127, 103, 128, 116, 104, 124, 127, 108, 103, 114]\n",
+ "Current payoff against imitation_132 : 129793.0\n",
+ "Current payoff against guess_132 : 134972.0\n",
+ "Round 71 of 200\n",
+ "Best payoff: 128106\n",
+ "Best actions: [118, 132, 132, 131, 131, 132, 125, 122, 128, 122, 114, 125, 115, 117, 114, 121, 113, 107, 109, 105, 100, 129, 102, 79, 127]\n",
+ "Current payoff against imitation_132 : 129926.0\n",
+ "Current payoff against guess_132 : 123766.0\n",
+ "Round 72 of 200\n",
+ "Best payoff: 130416\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 123, 121, 118, 122, 114, 124, 116, 118, 120, 109, 127, 103, 125, 109, 104, 123, 114, 99, 114]\n",
+ "Current payoff against imitation_132 : 131394.0\n",
+ "Current payoff against guess_132 : 121024.0\n",
+ "Round 73 of 200\n",
+ "Best payoff: 128705\n",
+ "Best actions: [127, 122, 132, 132, 128, 126, 123, 118, 117, 116, 113, 111, 117, 117, 115, 105, 123, 114, 127, 124, 100, 91, 131, 115, 127]\n",
+ "Current payoff against imitation_132 : 126864.0\n",
+ "Current payoff against guess_132 : 117929.0\n",
+ "Round 74 of 200\n",
+ "Best payoff: 131027\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 123, 120, 119, 130, 113, 120, 125, 110, 120, 121, 108, 121, 119, 120, 123, 120, 93, 132]\n",
+ "Current payoff against imitation_132 : 129630.0\n",
+ "Current payoff against guess_132 : 133290.0\n",
+ "Round 75 of 200\n",
+ "Best payoff: 129343\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 123, 120, 119, 117, 116, 116, 115, 114, 118, 111, 121, 120, 109, 93, 96, 111, 118, 117]\n",
+ "Current payoff against imitation_132 : 129878.0\n",
+ "Current payoff against guess_132 : 120422.0\n",
+ "Round 76 of 200\n",
+ "Best payoff: 127869\n",
+ "Best actions: [118, 132, 132, 132, 123, 121, 120, 119, 120, 119, 118, 116, 125, 118, 115, 113, 114, 111, 126, 126, 107, 107, 103, 79, 132]\n",
+ "Current payoff against imitation_132 : 129356.0\n",
+ "Current payoff against guess_132 : 125909.0\n",
+ "Round 77 of 200\n",
+ "Best payoff: 131289\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 123, 123, 119, 127, 124, 122, 104, 121, 112, 114, 113, 113, 114, 110, 117, 109, 95, 116]\n",
+ "Current payoff against imitation_132 : 130151.0\n",
+ "Current payoff against guess_132 : 120970.0\n",
+ "Round 78 of 200\n",
+ "Best payoff: 132398\n",
+ "Best actions: [125, 123, 132, 127, 125, 123, 121, 119, 119, 119, 115, 116, 116, 118, 114, 120, 119, 125, 117, 104, 118, 115, 119, 106, 93]\n",
+ "Current payoff against imitation_132 : 130591.0\n",
+ "Current payoff against guess_132 : 125396.0\n",
+ "Round 79 of 200\n",
+ "Best payoff: 134324\n",
+ "Best actions: [120, 130, 132, 132, 132, 132, 126, 123, 120, 120, 117, 119, 116, 120, 119, 119, 113, 124, 117, 123, 108, 111, 121, 115, 125]\n",
+ "Current payoff against imitation_132 : 129584.0\n",
+ "Current payoff against guess_132 : 129895.0\n",
+ "Round 80 of 200\n",
+ "Best payoff: 133600\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 127, 118, 119, 117, 121, 115, 113, 114, 124, 105, 116, 110, 121, 114, 109, 123, 99, 120]\n",
+ "Current payoff against imitation_132 : 128393.0\n",
+ "Current payoff against guess_132 : 121286.0\n",
+ "Round 81 of 200\n",
+ "Best payoff: 131399\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 123, 120, 118, 118, 121, 109, 115, 114, 114, 111, 126, 116, 113, 105, 106, 121, 113, 106]\n",
+ "Current payoff against imitation_132 : 129882.0\n",
+ "Current payoff against guess_132 : 133148.0\n",
+ "Round 82 of 200\n",
+ "Best payoff: 126075\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 124, 120, 113, 112, 106, 109, 118, 92, 102, 101, 102, 94, 100, 100, 96, 115, 112, 123]\n",
+ "Current payoff against imitation_132 : 130378.0\n",
+ "Current payoff against guess_132 : 131746.0\n",
+ "Round 83 of 200\n",
+ "Best payoff: 131473\n",
+ "Best actions: [118, 132, 132, 132, 132, 125, 123, 120, 119, 120, 115, 118, 130, 112, 118, 119, 120, 109, 124, 116, 124, 118, 108, 128, 82]\n",
+ "Current payoff against imitation_132 : 128507.0\n",
+ "Current payoff against guess_132 : 120626.0\n",
+ "Round 84 of 200\n",
+ "Best payoff: 129261\n",
+ "Best actions: [128, 122, 132, 132, 132, 132, 126, 124, 120, 118, 124, 120, 120, 120, 106, 116, 120, 106, 126, 110, 121, 92, 117, 115, 116]\n",
+ "Current payoff against imitation_132 : 131366.0\n",
+ "Current payoff against guess_132 : 133514.0\n",
+ "Round 85 of 200\n",
+ "Best payoff: 132684\n",
+ "Best actions: [125, 124, 132, 132, 132, 132, 126, 124, 121, 119, 118, 120, 117, 114, 113, 115, 109, 115, 113, 110, 117, 117, 103, 111, 129]\n",
+ "Current payoff against imitation_132 : 129388.0\n",
+ "Current payoff against guess_132 : 134738.0\n",
+ "Round 86 of 200\n",
+ "Best payoff: 130788\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 123, 121, 122, 123, 115, 120, 115, 124, 116, 116, 130, 107, 126, 117, 106, 91, 117, 111, 117]\n",
+ "Current payoff against imitation_132 : 127597.0\n",
+ "Current payoff against guess_132 : 124595.0\n",
+ "Round 87 of 200\n",
+ "Best payoff: 132144\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 126, 130, 116, 119, 117, 121, 113, 113, 115, 120, 117, 111, 110, 116, 127, 114, 87, 111, 126]\n",
+ "Current payoff against imitation_132 : 129109.0\n",
+ "Current payoff against guess_132 : 118118.0\n",
+ "Round 88 of 200\n",
+ "Best payoff: 131946\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 128, 124, 121, 119, 119, 117, 123, 111, 116, 117, 117, 110, 118, 113, 97, 96, 98, 116, 127]\n",
+ "Current payoff against imitation_132 : 128886.0\n",
+ "Current payoff against guess_132 : 129152.0\n",
+ "Round 89 of 200\n",
+ "Best payoff: 131533\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 126, 124, 121, 119, 125, 116, 122, 113, 130, 116, 94, 125, 119, 119, 111, 107, 107, 99, 133]\n",
+ "Current payoff against imitation_132 : 129962.0\n",
+ "Current payoff against guess_132 : 134754.0\n",
+ "Round 90 of 200\n",
+ "Best payoff: 132624\n",
+ "Best actions: [122, 128, 132, 132, 132, 132, 126, 124, 129, 122, 115, 124, 125, 120, 124, 117, 121, 118, 120, 111, 116, 97, 115, 85, 129]\n",
+ "Current payoff against imitation_132 : 128408.0\n",
+ "Current payoff against guess_132 : 116988.0\n",
+ "Round 91 of 200\n",
+ "Best payoff: 132725\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 128, 128, 122, 122, 119, 118, 123, 117, 118, 121, 102, 125, 106, 112, 123, 109, 100, 113, 128]\n",
+ "Current payoff against imitation_132 : 126342.0\n",
+ "Current payoff against guess_132 : 132103.0\n",
+ "Round 92 of 200\n",
+ "Best payoff: 131720\n",
+ "Best actions: [123, 126, 132, 132, 132, 131, 126, 124, 121, 121, 119, 119, 117, 116, 113, 121, 121, 94, 119, 102, 122, 113, 101, 113, 111]\n",
+ "Current payoff against imitation_132 : 129684.0\n",
+ "Current payoff against guess_132 : 134001.0\n",
+ "Round 93 of 200\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best payoff: 131178\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 128, 128, 122, 121, 119, 126, 114, 115, 113, 114, 125, 120, 86, 111, 112, 102, 112, 113, 111]\n",
+ "Current payoff against imitation_132 : 127765.0\n",
+ "Current payoff against guess_132 : 132202.0\n",
+ "Round 94 of 200\n",
+ "Best payoff: 133894\n",
+ "Best actions: [120, 130, 132, 132, 132, 132, 128, 125, 122, 122, 120, 118, 117, 116, 125, 115, 110, 112, 122, 117, 121, 118, 109, 120, 128]\n",
+ "Current payoff against imitation_132 : 130559.0\n",
+ "Current payoff against guess_132 : 122075.0\n",
+ "Round 95 of 200\n",
+ "Best payoff: 133698\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 127, 125, 122, 122, 119, 118, 117, 116, 120, 119, 115, 112, 117, 117, 120, 114, 117, 86, 136]\n",
+ "Current payoff against imitation_132 : 129779.0\n",
+ "Current payoff against guess_132 : 133992.0\n",
+ "Round 96 of 200\n",
+ "Best payoff: 133995\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 128, 125, 122, 120, 120, 118, 117, 118, 125, 110, 128, 114, 113, 124, 110, 121, 93, 119, 107]\n",
+ "Current payoff against imitation_132 : 129481.0\n",
+ "Current payoff against guess_132 : 136155.0\n",
+ "Round 97 of 200\n",
+ "Best payoff: 133865\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 128, 125, 122, 120, 120, 118, 125, 109, 123, 119, 114, 118, 128, 112, 124, 120, 113, 119, 128]\n",
+ "Current payoff against imitation_132 : 129069.0\n",
+ "Current payoff against guess_132 : 136183.0\n",
+ "Round 98 of 200\n",
+ "Best payoff: 134674\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 128, 125, 122, 121, 121, 117, 117, 116, 117, 117, 116, 110, 117, 110, 118, 112, 103, 120, 127]\n",
+ "Current payoff against imitation_132 : 130888.0\n",
+ "Current payoff against guess_132 : 126663.0\n",
+ "Round 99 of 200\n",
+ "Best payoff: 134895\n",
+ "Best actions: [121, 128, 131, 132, 132, 131, 128, 125, 122, 122, 122, 118, 119, 121, 119, 119, 119, 119, 121, 117, 131, 103, 105, 118, 127]\n",
+ "Current payoff against imitation_132 : 130150.0\n",
+ "Current payoff against guess_132 : 129425.0\n",
+ "Round 100 of 200\n",
+ "Best payoff: 134648\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 127, 127, 123, 122, 119, 121, 113, 121, 115, 113, 117, 121, 109, 108, 122, 108, 110, 132]\n",
+ "Current payoff against imitation_132 : 130119.0\n",
+ "Current payoff against guess_132 : 126667.0\n",
+ "Round 101 of 200\n",
+ "Best payoff: 134304\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 127, 123, 121, 119, 119, 119, 121, 113, 114, 121, 122, 119, 108, 124, 113, 104, 107, 131]\n",
+ "Current payoff against imitation_132 : 126897.0\n",
+ "Current payoff against guess_132 : 128268.0\n",
+ "Round 102 of 200\n",
+ "Best payoff: 133229\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 126, 124, 124, 118, 120, 117, 107, 125, 110, 110, 113, 112, 123, 118, 108, 104, 113, 132]\n",
+ "Current payoff against imitation_132 : 128071.0\n",
+ "Current payoff against guess_132 : 128993.0\n",
+ "Round 103 of 200\n",
+ "Best payoff: 133644\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 129, 128, 124, 125, 118, 117, 114, 114, 113, 115, 124, 105, 118, 115, 114, 122, 110, 128]\n",
+ "Current payoff against imitation_132 : 129400.0\n",
+ "Current payoff against guess_132 : 135104.0\n",
+ "Round 104 of 200\n",
+ "Best payoff: 134121\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 125, 123, 120, 120, 125, 125, 120, 102, 119, 116, 122, 119, 119, 114, 118, 113, 112, 123]\n",
+ "Current payoff against imitation_132 : 123590.0\n",
+ "Current payoff against guess_132 : 127630.0\n",
+ "Round 105 of 200\n",
+ "Best payoff: 134047\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 126, 123, 120, 120, 118, 120, 116, 120, 117, 118, 130, 112, 115, 117, 111, 116, 106, 94]\n",
+ "Current payoff against imitation_132 : 127386.0\n",
+ "Current payoff against guess_132 : 125785.0\n",
+ "Round 106 of 200\n",
+ "Best payoff: 133560\n",
+ "Best actions: [120, 130, 132, 132, 132, 132, 131, 126, 123, 120, 120, 118, 117, 120, 121, 120, 109, 124, 128, 113, 118, 129, 112, 112, 129]\n",
+ "Current payoff against imitation_132 : 127863.0\n",
+ "Current payoff against guess_132 : 134421.0\n",
+ "Round 107 of 200\n",
+ "Best payoff: 134959\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 132, 126, 123, 120, 118, 118, 116, 116, 115, 116, 116, 123, 113, 112, 120, 126, 115, 107]\n",
+ "Current payoff against imitation_132 : 127999.0\n",
+ "Current payoff against guess_132 : 134793.0\n",
+ "Round 108 of 200\n",
+ "Best payoff: 135158\n",
+ "Best actions: [118, 132, 132, 132, 131, 131, 132, 131, 125, 123, 120, 120, 118, 120, 115, 117, 124, 129, 100, 118, 114, 117, 114, 119, 127]\n",
+ "Current payoff against imitation_132 : 126778.0\n",
+ "Current payoff against guess_132 : 135494.0\n",
+ "Round 109 of 200\n",
+ "Best payoff: 135526\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 132, 126, 123, 121, 121, 122, 116, 116, 118, 122, 117, 119, 128, 119, 120, 116, 114, 130]\n",
+ "Current payoff against imitation_132 : 128621.0\n",
+ "Current payoff against guess_132 : 136063.0\n",
+ "Round 110 of 200\n",
+ "Best payoff: 136126\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 129, 123, 122, 121, 119, 116, 122, 127, 111, 117, 116, 122, 122, 121, 105, 133]\n",
+ "Current payoff against imitation_132 : 125719.0\n",
+ "Current payoff against guess_132 : 132967.0\n",
+ "Round 111 of 200\n",
+ "Best payoff: 136355\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 130, 123, 122, 118, 118, 120, 120, 114, 120, 121, 117, 117, 126, 126, 111, 130]\n",
+ "Current payoff against imitation_132 : 130514.0\n",
+ "Current payoff against guess_132 : 136508.0\n",
+ "Round 112 of 200\n",
+ "Best payoff: 135722\n",
+ "Best actions: [118, 132, 131, 132, 131, 132, 132, 131, 132, 129, 123, 122, 121, 117, 119, 118, 122, 117, 118, 114, 111, 116, 117, 112, 127]\n",
+ "Current payoff against imitation_132 : 128730.0\n",
+ "Current payoff against guess_132 : 136072.0\n",
+ "Round 113 of 200\n",
+ "Best payoff: 136819\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 130, 123, 123, 121, 117, 119, 120, 119, 119, 121, 117, 120, 122, 117, 118, 130]\n",
+ "Current payoff against imitation_132 : 125983.0\n",
+ "Current payoff against guess_132 : 135120.0\n",
+ "Round 114 of 200\n",
+ "Best payoff: 136242\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 126, 124, 121, 121, 119, 123, 114, 123, 121, 115, 119, 121, 117, 120, 122, 117, 118, 130]\n",
+ "Current payoff against imitation_132 : 127293.0\n",
+ "Current payoff against guess_132 : 132069.0\n",
+ "Round 115 of 200\n",
+ "Best payoff: 136741\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 131, 130, 123, 123, 121, 116, 120, 117, 122, 117, 118, 120, 119, 115, 118, 132, 118]\n",
+ "Current payoff against imitation_132 : 128816.0\n",
+ "Current payoff against guess_132 : 128573.0\n",
+ "Round 116 of 200\n",
+ "Best payoff: 136729\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 130, 123, 120, 118, 118, 116, 116, 116, 116, 115, 122, 114, 112, 116, 118, 127]\n",
+ "Current payoff against imitation_132 : 126957.0\n",
+ "Current payoff against guess_132 : 134704.0\n",
+ "Round 117 of 200\n",
+ "Best payoff: 136376\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 130, 122, 120, 118, 118, 116, 115, 116, 116, 115, 122, 112, 119, 113, 108, 133]\n",
+ "Current payoff against imitation_132 : 127395.0\n",
+ "Current payoff against guess_132 : 136036.0\n",
+ "Round 118 of 200\n",
+ "Best payoff: 136772\n",
+ "Best actions: [118, 131, 132, 132, 132, 132, 132, 132, 132, 126, 123, 120, 118, 118, 117, 114, 116, 116, 115, 118, 116, 118, 112, 112, 128]\n",
+ "Current payoff against imitation_132 : 129472.0\n",
+ "Current payoff against guess_132 : 136633.0\n",
+ "Round 119 of 200\n",
+ "Best payoff: 136908\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 128, 124, 121, 118, 118, 116, 116, 116, 116, 115, 118, 116, 115, 113, 108, 129]\n",
+ "Current payoff against imitation_132 : 129574.0\n",
+ "Current payoff against guess_132 : 123969.0\n",
+ "Round 120 of 200\n",
+ "Best payoff: 137046\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 128, 124, 121, 123, 118, 117, 118, 120, 120, 119, 117, 116, 115, 112, 115, 131]\n",
+ "Current payoff against imitation_132 : 121800.0\n",
+ "Current payoff against guess_132 : 136614.0\n",
+ "Round 121 of 200\n",
+ "Best payoff: 136913\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 128, 124, 121, 120, 119, 119, 119, 119, 128, 117, 113, 120, 122, 111, 112, 133]\n",
+ "Current payoff against imitation_132 : 128005.0\n",
+ "Current payoff against guess_132 : 136721.0\n",
+ "Round 122 of 200\n",
+ "Best payoff: 137086\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 131, 128, 124, 122, 120, 119, 121, 113, 120, 120, 114, 122, 114, 116, 118, 106, 133]\n",
+ "Current payoff against imitation_132 : 126700.0\n",
+ "Current payoff against guess_132 : 136608.0\n",
+ "Round 123 of 200\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best payoff: 136806\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 132, 132, 128, 124, 122, 120, 118, 117, 115, 115, 119, 111, 119, 114, 113, 118, 114, 131]\n",
+ "Current payoff against imitation_132 : 126872.0\n",
+ "Current payoff against guess_132 : 121361.0\n",
+ "Round 124 of 200\n",
+ "Best payoff: 137206\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 126, 124, 122, 120, 118, 118, 115, 115, 116, 116, 117, 114, 116, 115, 114, 128]\n",
+ "Current payoff against imitation_132 : 129211.0\n",
+ "Current payoff against guess_132 : 136833.0\n",
+ "Round 125 of 200\n",
+ "Best payoff: 137199\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 131, 132, 132, 126, 123, 120, 120, 117, 120, 118, 117, 117, 119, 114, 116, 118, 116, 131]\n",
+ "Current payoff against imitation_132 : 129694.0\n",
+ "Current payoff against guess_132 : 136545.0\n",
+ "Round 126 of 200\n",
+ "Best payoff: 137098\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 131, 126, 123, 120, 118, 117, 116, 116, 117, 116, 113, 115, 116, 118, 116, 130]\n",
+ "Current payoff against imitation_132 : 123976.0\n",
+ "Current payoff against guess_132 : 136427.0\n",
+ "Round 127 of 200\n",
+ "Best payoff: 137275\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 123, 120, 120, 118, 118, 120, 117, 117, 119, 114, 116, 118, 118, 130]\n",
+ "Current payoff against imitation_132 : 127740.0\n",
+ "Current payoff against guess_132 : 137144.0\n",
+ "Round 128 of 200\n",
+ "Best payoff: 137583\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 123, 120, 120, 118, 118, 120, 120, 114, 118, 117, 122, 114, 114, 128]\n",
+ "Current payoff against imitation_132 : 127041.0\n",
+ "Current payoff against guess_132 : 137523.0\n",
+ "Round 129 of 200\n",
+ "Best payoff: 137524\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 123, 120, 120, 118, 118, 120, 119, 113, 118, 117, 122, 114, 114, 128]\n",
+ "Current payoff against imitation_132 : 129016.0\n",
+ "Current payoff against guess_132 : 137588.0\n",
+ "Round 130 of 200\n",
+ "Best payoff: 137672\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 123, 120, 120, 118, 118, 117, 120, 115, 118, 117, 122, 114, 114, 130]\n",
+ "Current payoff against imitation_132 : 128726.0\n",
+ "Current payoff against guess_132 : 137593.0\n",
+ "Round 131 of 200\n",
+ "Best payoff: 137631\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 123, 120, 120, 118, 117, 117, 118, 117, 120, 116, 122, 114, 111, 130]\n",
+ "Current payoff against imitation_132 : 130194.0\n",
+ "Current payoff against guess_132 : 137538.0\n",
+ "Round 132 of 200\n",
+ "Best payoff: 137739\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 132, 132, 132, 126, 124, 121, 120, 119, 120, 116, 120, 116, 120, 116, 122, 114, 111, 132]\n",
+ "Current payoff against imitation_132 : 127508.0\n",
+ "Current payoff against guess_132 : 137698.0\n",
+ "Round 133 of 200\n",
+ "Best payoff: 137698\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 132, 126, 124, 121, 120, 119, 120, 116, 120, 116, 120, 116, 122, 114, 114, 130]\n",
+ "Current payoff against imitation_132 : 124716.0\n",
+ "Current payoff against guess_132 : 137619.0\n",
+ "Round 134 of 200\n",
+ "Best payoff: 137736\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 123, 121, 120, 118, 119, 118, 120, 116, 120, 116, 122, 114, 114, 130]\n",
+ "Current payoff against imitation_132 : 125202.0\n",
+ "Current payoff against guess_132 : 137557.0\n",
+ "Round 135 of 200\n",
+ "Best payoff: 137646\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 123, 121, 120, 119, 119, 118, 120, 116, 118, 120, 118, 122, 111, 130]\n",
+ "Current payoff against imitation_132 : 127877.0\n",
+ "Current payoff against guess_132 : 137280.0\n",
+ "Round 136 of 200\n",
+ "Best payoff: 137626\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 128, 122, 121, 119, 119, 121, 117, 119, 123, 121, 119, 115, 111, 133]\n",
+ "Current payoff against imitation_132 : 128550.0\n",
+ "Current payoff against guess_132 : 137626.0\n",
+ "Round 137 of 200\n",
+ "Best payoff: 137722\n",
+ "Best actions: [118, 132, 132, 131, 131, 131, 131, 132, 132, 131, 128, 125, 122, 123, 119, 118, 121, 119, 118, 123, 119, 120, 118, 110, 132]\n",
+ "Current payoff against imitation_132 : 130921.0\n",
+ "Current payoff against guess_132 : 137298.0\n",
+ "Round 138 of 200\n",
+ "Best payoff: 137891\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 125, 122, 122, 119, 119, 121, 117, 119, 123, 119, 120, 118, 110, 132]\n",
+ "Current payoff against imitation_132 : 128130.0\n",
+ "Current payoff against guess_132 : 137891.0\n",
+ "Round 139 of 200\n",
+ "Best payoff: 137952\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 127, 125, 122, 122, 122, 118, 121, 117, 119, 123, 116, 121, 116, 112, 128]\n",
+ "Current payoff against imitation_132 : 126894.0\n",
+ "Current payoff against guess_132 : 137317.0\n",
+ "Round 140 of 200\n",
+ "Best payoff: 138024\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 131, 132, 128, 125, 122, 122, 120, 119, 121, 120, 118, 123, 116, 118, 116, 120, 130]\n",
+ "Current payoff against imitation_132 : 129201.0\n",
+ "Current payoff against guess_132 : 137978.0\n",
+ "Round 141 of 200\n",
+ "Best payoff: 137940\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 125, 122, 122, 121, 118, 121, 117, 119, 123, 116, 121, 116, 112, 128]\n",
+ "Current payoff against imitation_132 : 126117.0\n",
+ "Current payoff against guess_132 : 136166.0\n",
+ "Round 142 of 200\n",
+ "Best payoff: 137946\n",
+ "Best actions: [118, 132, 132, 132, 131, 131, 131, 132, 131, 132, 127, 125, 122, 121, 122, 118, 122, 120, 118, 123, 116, 121, 116, 112, 129]\n",
+ "Current payoff against imitation_132 : 125970.0\n",
+ "Current payoff against guess_132 : 137289.0\n",
+ "Round 143 of 200\n",
+ "Best payoff: 137977\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 132, 128, 125, 122, 122, 120, 120, 122, 120, 120, 122, 116, 118, 115, 119, 130]\n",
+ "Current payoff against imitation_132 : 126347.0\n",
+ "Current payoff against guess_132 : 137390.0\n",
+ "Round 144 of 200\n",
+ "Best payoff: 138112\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 131, 132, 132, 131, 128, 126, 123, 121, 120, 119, 118, 118, 118, 123, 115, 121, 116, 111, 132]\n",
+ "Current payoff against imitation_132 : 120630.0\n",
+ "Current payoff against guess_132 : 136604.0\n",
+ "Round 145 of 200\n",
+ "Best payoff: 138127\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 127, 127, 125, 121, 121, 122, 116, 118, 123, 115, 121, 116, 111, 132]\n",
+ "Current payoff against imitation_132 : 124501.0\n",
+ "Current payoff against guess_132 : 137700.0\n",
+ "Round 146 of 200\n",
+ "Best payoff: 138139\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 125, 125, 125, 121, 121, 120, 120, 117, 120, 119, 118, 116, 111, 132]\n",
+ "Current payoff against imitation_132 : 127152.0\n",
+ "Current payoff against guess_132 : 137815.0\n",
+ "Round 147 of 200\n",
+ "Best payoff: 138054\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 127, 127, 122, 125, 120, 120, 119, 117, 120, 116, 118, 114, 110, 133]\n",
+ "Current payoff against imitation_132 : 121733.0\n",
+ "Current payoff against guess_132 : 137713.0\n",
+ "Round 148 of 200\n",
+ "Best payoff: 138238\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 132, 131, 127, 125, 126, 121, 121, 120, 119, 118, 120, 116, 122, 115, 111, 132]\n",
+ "Current payoff against imitation_132 : 123422.0\n",
+ "Current payoff against guess_132 : 138206.0\n",
+ "Round 149 of 200\n",
+ "Best payoff: 138297\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 127, 125, 124, 122, 122, 120, 119, 118, 117, 120, 118, 116, 110, 133]\n",
+ "Current payoff against imitation_132 : 127929.0\n",
+ "Current payoff against guess_132 : 137875.0\n",
+ "Round 150 of 200\n",
+ "Best payoff: 138310\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 131, 132, 128, 125, 124, 122, 122, 120, 119, 118, 118, 120, 118, 115, 112, 133]\n",
+ "Current payoff against imitation_132 : 119724.0\n",
+ "Current payoff against guess_132 : 137926.0\n",
+ "Round 151 of 200\n",
+ "Best payoff: 138362\n",
+ "Best actions: [118, 132, 132, 132, 132, 131, 132, 131, 131, 132, 131, 128, 125, 124, 123, 121, 120, 119, 119, 119, 118, 119, 115, 122, 130]\n",
+ "Current payoff against imitation_132 : 127926.0\n",
+ "Current payoff against guess_132 : 137734.0\n",
+ "Round 152 of 200\n",
+ "Best payoff: 138399\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 131, 131, 128, 126, 123, 123, 123, 119, 121, 119, 118, 116, 117, 117, 111, 133]\n",
+ "Current payoff against imitation_132 : 121791.0\n",
+ "Current payoff against guess_132 : 138318.0\n",
+ "Round 153 of 200\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best payoff: 138635\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 124, 124, 122, 121, 123, 119, 121, 123, 117, 117, 113, 132]\n",
+ "Current payoff against imitation_132 : 128812.0\n",
+ "Current payoff against guess_132 : 138596.0\n",
+ "Round 154 of 200\n",
+ "Best payoff: 138797\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 124, 123, 121, 121, 121, 121, 121, 120, 119, 117, 113, 133]\n",
+ "Current payoff against imitation_132 : 127257.0\n",
+ "Current payoff against guess_132 : 138665.0\n",
+ "Round 155 of 200\n",
+ "Best payoff: 138802\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 126, 124, 124, 121, 121, 121, 121, 121, 120, 119, 120, 112, 133]\n",
+ "Current payoff against imitation_132 : 129806.0\n",
+ "Current payoff against guess_132 : 138372.0\n",
+ "Round 156 of 200\n",
+ "Best payoff: 138632\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 131, 131, 131, 131, 131, 126, 124, 122, 121, 120, 120, 120, 119, 120, 121, 116, 114, 132]\n",
+ "Current payoff against imitation_132 : 126414.0\n",
+ "Current payoff against guess_132 : 138518.0\n",
+ "Round 157 of 200\n",
+ "Best payoff: 138781\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 128, 124, 122, 122, 119, 119, 119, 120, 119, 118, 114, 133]\n",
+ "Current payoff against imitation_132 : 119531.0\n",
+ "Current payoff against guess_132 : 138571.0\n",
+ "Round 158 of 200\n",
+ "Best payoff: 138926\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 128, 126, 123, 123, 121, 121, 121, 121, 120, 122, 120, 115, 133]\n",
+ "Current payoff against imitation_132 : 125969.0\n",
+ "Current payoff against guess_132 : 138763.0\n",
+ "Round 159 of 200\n",
+ "Best payoff: 138923\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 123, 123, 121, 121, 121, 120, 120, 123, 120, 115, 133]\n",
+ "Current payoff against imitation_132 : 125664.0\n",
+ "Current payoff against guess_132 : 138415.0\n",
+ "Round 160 of 200\n",
+ "Best payoff: 138964\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 124, 124, 122, 121, 121, 121, 123, 121, 118, 108, 134]\n",
+ "Current payoff against imitation_132 : 124467.0\n",
+ "Current payoff against guess_132 : 138569.0\n",
+ "Round 161 of 200\n",
+ "Best payoff: 139068\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 124, 124, 122, 121, 121, 121, 123, 121, 119, 111, 132]\n",
+ "Current payoff against imitation_132 : 123971.0\n",
+ "Current payoff against guess_132 : 139015.0\n",
+ "Round 162 of 200\n",
+ "Best payoff: 139072\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 131, 132, 132, 132, 131, 132, 128, 126, 124, 124, 122, 121, 121, 121, 123, 121, 119, 111, 134]\n",
+ "Current payoff against imitation_132 : 125932.0\n",
+ "Current payoff against guess_132 : 138903.0\n",
+ "Round 163 of 200\n",
+ "Best payoff: 139073\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 128, 126, 124, 124, 122, 121, 121, 121, 123, 121, 119, 111, 134]\n",
+ "Current payoff against imitation_132 : 126893.0\n",
+ "Current payoff against guess_132 : 138995.0\n",
+ "Round 164 of 200\n",
+ "Best payoff: 139057\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 132, 128, 126, 123, 123, 121, 121, 121, 121, 123, 119, 120, 111, 134]\n",
+ "Current payoff against imitation_132 : 124426.0\n",
+ "Current payoff against guess_132 : 138969.0\n",
+ "Round 165 of 200\n",
+ "Best payoff: 139071\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 131, 126, 124, 123, 122, 122, 122, 121, 120, 120, 118, 114, 133]\n",
+ "Current payoff against imitation_132 : 126901.0\n",
+ "Current payoff against guess_132 : 138778.0\n",
+ "Round 166 of 200\n",
+ "Best payoff: 139226\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 123, 123, 121, 121, 121, 121, 120, 120, 111, 134]\n",
+ "Current payoff against imitation_132 : 126376.0\n",
+ "Current payoff against guess_132 : 139225.0\n",
+ "Round 167 of 200\n",
+ "Best payoff: 139225\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 128, 126, 123, 123, 121, 121, 121, 121, 120, 120, 111, 134]\n",
+ "Current payoff against imitation_132 : 127574.0\n",
+ "Current payoff against guess_132 : 138828.0\n",
+ "Round 168 of 200\n",
+ "Best payoff: 139185\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 131, 131, 132, 132, 131, 128, 125, 125, 125, 121, 123, 122, 123, 122, 121, 119, 115, 133]\n",
+ "Current payoff against imitation_132 : 130178.0\n",
+ "Current payoff against guess_132 : 138976.0\n",
+ "Round 169 of 200\n",
+ "Best payoff: 139443\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 128, 125, 124, 123, 123, 123, 123, 122, 123, 121, 111, 134]\n",
+ "Current payoff against imitation_132 : 118628.0\n",
+ "Current payoff against guess_132 : 138979.0\n",
+ "Round 170 of 200\n",
+ "Best payoff: 139444\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 125, 124, 123, 123, 123, 123, 122, 123, 121, 111, 134]\n",
+ "Current payoff against imitation_132 : 126021.0\n",
+ "Current payoff against guess_132 : 139276.0\n",
+ "Round 171 of 200\n",
+ "Best payoff: 139517\n",
+ "Best actions: [118, 132, 131, 132, 131, 132, 132, 131, 131, 132, 131, 132, 131, 128, 126, 126, 124, 124, 123, 123, 124, 123, 121, 112, 133]\n",
+ "Current payoff against imitation_132 : 120757.0\n",
+ "Current payoff against guess_132 : 139075.0\n",
+ "Round 172 of 200\n",
+ "Best payoff: 139555\n",
+ "Best actions: [118, 132, 131, 132, 132, 131, 132, 132, 131, 132, 132, 131, 132, 128, 126, 126, 124, 124, 123, 123, 124, 123, 121, 111, 134]\n",
+ "Current payoff against imitation_132 : 128271.0\n",
+ "Current payoff against guess_132 : 139354.0\n",
+ "Round 173 of 200\n",
+ "Best payoff: 139536\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 126, 125, 124, 124, 123, 123, 124, 123, 121, 117, 133]\n",
+ "Current payoff against imitation_132 : 123249.0\n",
+ "Current payoff against guess_132 : 139373.0\n",
+ "Round 174 of 200\n",
+ "Best payoff: 139545\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 132, 131, 132, 132, 128, 126, 126, 124, 124, 123, 123, 124, 123, 121, 109, 135]\n",
+ "Current payoff against imitation_132 : 127843.0\n",
+ "Current payoff against guess_132 : 139413.0\n",
+ "Round 175 of 200\n",
+ "Best payoff: 139575\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 126, 126, 124, 124, 124, 123, 124, 123, 121, 111, 134]\n",
+ "Current payoff against imitation_132 : 124245.0\n",
+ "Current payoff against guess_132 : 139383.0\n",
+ "Round 176 of 200\n",
+ "Best payoff: 139672\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 122, 114, 133]\n",
+ "Current payoff against imitation_132 : 121925.0\n",
+ "Current payoff against guess_132 : 139601.0\n",
+ "Round 177 of 200\n",
+ "Best payoff: 139672\n",
+ "Best actions: [118, 132, 132, 132, 131, 132, 132, 132, 132, 132, 132, 131, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 122, 114, 134]\n",
+ "Current payoff against imitation_132 : 119357.0\n",
+ "Current payoff against guess_132 : 139241.0\n",
+ "Round 178 of 200\n",
+ "Best payoff: 139708\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 127, 124, 124, 124, 124, 124, 124, 124, 114, 133]\n",
+ "Current payoff against imitation_132 : 128031.0\n",
+ "Current payoff against guess_132 : 139470.0\n",
+ "Round 179 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124908.0\n",
+ "Current payoff against guess_132 : 139146.0\n",
+ "Round 180 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121371.0\n",
+ "Current payoff against guess_132 : 139700.0\n",
+ "Round 181 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125154.0\n",
+ "Current payoff against guess_132 : 139436.0\n",
+ "Round 182 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 120103.0\n",
+ "Current payoff against guess_132 : 139685.0\n",
+ "Round 183 of 200\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121621.0\n",
+ "Current payoff against guess_132 : 139563.0\n",
+ "Round 184 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121942.0\n",
+ "Current payoff against guess_132 : 139650.0\n",
+ "Round 185 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124144.0\n",
+ "Current payoff against guess_132 : 139494.0\n",
+ "Round 186 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121872.0\n",
+ "Current payoff against guess_132 : 139322.0\n",
+ "Round 187 of 200\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 131, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 124209.0\n",
+ "Current payoff against guess_132 : 139690.0\n",
+ "Round 188 of 200\n",
+ "Best payoff: 139794\n",
+ "Best actions: [118, 132, 132, 131, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123080.0\n",
+ "Current payoff against guess_132 : 139764.0\n",
+ "Round 189 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125115.0\n",
+ "Current payoff against guess_132 : 139712.0\n",
+ "Round 190 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122050.0\n",
+ "Current payoff against guess_132 : 139314.0\n",
+ "Round 191 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121005.0\n",
+ "Current payoff against guess_132 : 139320.0\n",
+ "Round 192 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122812.0\n",
+ "Current payoff against guess_132 : 139457.0\n",
+ "Round 193 of 200\n",
+ "Best payoff: 139795\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 131, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 122172.0\n",
+ "Current payoff against guess_132 : 139313.0\n",
+ "Round 194 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123210.0\n",
+ "Current payoff against guess_132 : 139300.0\n",
+ "Round 195 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 121612.0\n",
+ "Current payoff against guess_132 : 139561.0\n",
+ "Round 196 of 200\n",
+ "Best payoff: 139796\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 126, 124, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 123978.0\n",
+ "Current payoff against guess_132 : 139672.0\n",
+ "Round 197 of 200\n",
+ "Best payoff: 139765\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 125, 123, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 125003.0\n",
+ "Current payoff against guess_132 : 139686.0\n",
+ "Round 198 of 200\n",
+ "Best payoff: 139765\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 126, 125, 123, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 116583.0\n",
+ "Current payoff against guess_132 : 139706.0\n",
+ "Round 199 of 200\n",
+ "Best payoff: 139706\n",
+ "Best actions: [118, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 128, 128, 124, 123, 124, 124, 124, 124, 124, 112, 135]\n",
+ "Current payoff against imitation_132 : 116374.0\n",
+ "Current payoff against guess_132 : 139655.0\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Action are only chosen according to an epsilon greedy strategy.\n",
+ "episode_counter = 0\n",
+ "number_episodes_per_round = 500_000\n",
+ "number_rounds = int(number_episodes / number_episodes_per_round)\n",
+ "\n",
+ "for round_ in range(number_rounds): \n",
+ " print('Round ', round_, ' of ', number_rounds)\n",
+ " algorithm.epsilon_greedy_learning(number_episodes_per_round, episode_counter, number_episodes)\n",
+ "\n",
+ " for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " new_adversary_probabilities =[0]*len(AdversaryModes)\n",
+ " new_adversary_probabilities[index] = 1\n",
+ " result = Test(game, Qtable, discount_factor, new_adversary_probabilities)\n",
+ " payoff, _, _, _, _ = result.total_payoff()\n",
+ " opponent_results[index].append(payoff)\n",
+ " print('Current payoff against', adversary.name, \":\" , payoff)\n",
+ " \n",
+ " episode_counter += number_episodes_per_round\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlYAAAHFCAYAAAAwv7dvAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAA9hAAAPYQGoP6dpAAD3Q0lEQVR4nOxdd3xUVf4901uSSW8kJBB671VFFEEUbGsFUeyuq65t17Jrwa6Loj8V2yrY1rIKrKIioPTeIr0HQkhvkzZ93u+P++5r82YyE5IQ8J7PJ5/JvLnz5r43k3kn53vu+Wo4juPAwMDAwMDAwMBwytCe7gkwMDAwMDAwMJwtYMSKgYGBgYGBgaGVwIgVAwMDAwMDA0MrgRErBgYGBgYGBoZWAiNWDAwMDAwMDAytBEasGBgYGBgYGBhaCYxYMTAwMDAwMDC0EhixYmBgYGBgYGBoJTBixcDAwMDAwMDQSmDEioHhLMX8+fOh0WiEH71ej6ysLNxyyy04efLk6Z4ePB4P7r77bmRkZECn02HQoEEAgOrqalx//fVITU2FRqPBFVdccVrn2RpYv349nnnmGdTW1gY9lpubiylTprT/pDowVq5cCY1Gg5UrV57uqTAwRA396Z4AAwND22LevHno1asXnE4nVq9ejZdeegmrVq3Crl27YLPZTtu83n33Xbz//vt46623MHToUMTExAAAnnvuOSxcuBAff/wx8vLykJiYeNrm2FpYv349Zs2ahZkzZyI+Pv50T4eBgaENwYgVA8NZjn79+mHYsGEAgPHjx8Pv9+O5557DokWLMH369NM2r927d8NiseDee+8N2p6Xl3da59YSNDU1wWq1nu5pRAWn0wmLxXK6p8HAcFaBlQIZGP5gGDVqFADg+PHjAIBZs2Zh5MiRSExMRFxcHIYMGYKPPvoI0v7st912GxITE9HU1BS0vwsuuAB9+/YV7rtcLjz++OPo0qULjEYjOnXqhL/85S+yMphGo8G///1vOJ1OoVRJS5fLly/Hvn37hO3hykGBQACvvvoqevXqBZPJhNTUVNx0000oKioSxjzwwAOw2Wyoq6sLev51112HtLQ0eL1eYdvXX3+N0aNHw2azISYmBpMmTcKOHTtkz5s5cyZiYmKwa9cuTJw4EbGxsbjwwgtV5/jMM8/gb3/7GwCgS5cuIY9ryZIlGDJkCCwWC3r16oWPP/44aF+lpaW46667kJWVBaPRiC5dumDWrFnw+XwhzxEFLTkuWLAAgwcPhtlsxqxZswAQMnv55ZcjISEBZrMZgwYNwieffCJ7Pn1/jh07JtuuVrY7//zz0a9fP2zZsgXnnnsurFYrunbtipdffhmBQED2/P379+Piiy+G1WpFcnIy7r77btTX1wfNf8eOHZgyZQpSU1NhMpmQmZmJSy+9VPZeMzB0CHAMDAxnJebNm8cB4LZs2SLb/uabb3IAuA8++IDjOI6bOXMm99FHH3HLli3jli1bxj333HOcxWLhZs2aJTzn999/5wBwH374oWxfe/bs4QBw77zzDsdxHBcIBLhJkyZxer2ee/LJJ7mlS5dys2fP5mw2Gzd48GDO5XJxHMdxGzZs4C655BLOYrFwGzZs4DZs2MCVlpZyGzZs4AYPHsx17dpV2O5wOEIe45133skB4O69915uyZIl3HvvvcelpKRw2dnZXEVFRdi519TUcCaTiXvooYeEbS+88AKn0Wi4W2+9lVu8eDG3YMECbvTo0ZzNZuP27NkjjLv55ps5g8HA5ebmci+99BL366+/cr/88ovqHE+cOMHdd999HABuwYIFQceVk5PDZWVlcX369OE+/fRT7pdffuGuueYaDgC3atUqYT8lJSVcdnY2l5OTw73//vvc8uXLueeee44zmUzczJkzQ54jipycHC4jI4Pr2rUr9/HHH3MrVqzgNm/ezO3fv5+LjY3l8vLyuE8//ZT78ccfuRtuuIEDwL3yyivC8+nnqaCgQLbfFStWcAC4FStWCNvGjRvHJSUlcd27d+fee+89btmyZdw999zDAeA++eQTYVxpaSmXmprKderUiZs3bx73008/cdOnT+c6d+4s22dDQwOXlJTEDRs2jPvmm2+4VatWcV9//TV39913c3v37m322BkY2hOMWDEwnKWgF8KNGzdyXq+Xq6+v5xYvXsylpKRwsbGxXGlpadBz/H4/5/V6uWeffZZLSkriAoGA8Ni4ceO4QYMGycb/+c9/5uLi4rj6+nqO4zhuyZIlHADu1VdflY37+uuvZWSO4wg5sdlsQXMYN24c17dv32aPb9++fRwA7p577pFt37RpEweAe+KJJ4RtQ4YM4caMGSMbN3fuXA4At2vXLo7jOK6wsJDT6/XcfffdJxtXX1/Ppaenc9dee61s7gC4jz/+uNl5chzH/etf/1IlJRxHCI/ZbOaOHz8ubHM6nVxiYiJ31113CdvuuusuLiYmRjaO4zhu9uzZHAAZ8VNDTk4Op9PpuAMHDsi2X3/99ZzJZOIKCwtl2ydPnsxZrVautraW47joiRUAbtOmTbKxffr04SZNmiTcf/TRRzmNRsPl5+fLxl100UWyfW7dupUDwC1atCjsMTIwdASwUiADw1mOUaNGwWAwIDY2FlOmTEF6ejp+/vlnpKWlAQB+++03TJgwAXa7HTqdDgaDAU899RSqqqpQXl4u7Oevf/0r8vPzsW7dOgBAXV0dPvvsM9x8882C8fy3334DQEplUlxzzTWw2Wz49ddfW+24VqxYofpaI0aMQO/evWWvdcstt2D9+vU4cOCAsG3evHkYPnw4+vXrBwD45Zdf4PP5cNNNN8Hn8wk/ZrMZ48aNUy1J/ulPf2qVYxk0aBA6d+4s3DebzejRo4dQrgWAxYsXY/z48cjMzJTNb/LkyQCAVatWNfs6AwYMQI8ePWTbfvvtN1x44YXIzs6WbZ85cyaampqwYcOGFh1Teno6RowYEfT60mNasWIF+vbti4EDB8rGTZs2TXa/W7duSEhIwKOPPor33nsPe/fubdGcGBjaA4xYMTCc5fj000+xZcsW7NixA8XFxdi5cyfGjh0LANi8eTMmTpwIAPjwww+xbt06bNmyBf/4xz8AEHMzxeWXX47c3Fy88847AIjnprGxEX/5y1+EMVVVVdDr9UhJSZHNQaPRID09HVVVVa12XHRfGRkZQY9lZmbKXmv69OkwmUyYP38+AGDv3r3YsmULbrnlFmFMWVkZAGD48OEwGAyyn6+//hqVlZWy17BarYiLi2uVY0lKSgraZjKZZOe/rKwMP/zwQ9DcqL9NOT81qJ2rqqqqkOeQPt4SRHJMVVVVSE9PDxqn3Ga327Fq1SoMGjQITzzxBPr27YvMzEw8/fTTMn8cA0NHAFsVyMBwlqN3797CqkAlvvrqKxgMBixevBhms1nYvmjRoqCxWq0Wf/nLX/DEE0/gtddew9y5c3HhhReiZ8+ewpikpCT4fD5UVFTIyBXHcSgtLcXw4cNb7bjohbukpARZWVmyx4qLi5GcnCzcT0hIwOWXX45PP/0Uzz//PObNmwez2YwbbrhBGEPHf/vtt8jJyWn29TUaTWscRsRITk7GgAED8MILL6g+TolQOKjNOSkpCSUlJUHbi4uLhdcFIHw+3G63bFwkhC4UkpKSUFpaGrRdbVv//v3x1VdfgeM47Ny5E/Pnz8ezzz4Li8WCxx57rMVzYGBobTDFioHhDwwaHKrT6YRtTqcTn332mer422+/HUajEdOnT8eBAweCohLoyrjPP/9ctv27775DY2NjyJVzLcEFF1yg+lpbtmzBvn37gl7rlltuQXFxMX766Sd8/vnnuPLKK2WZUpMmTYJer8eRI0cwbNgw1Z+WwmQyAZArgNFiypQpQhSF2twiIVZquPDCC/Hbb78JRIri008/hdVqFVaR5ubmAgB27twpG/f999+36HUBEv+xZ88e/P7777Lt//nPf0I+R6PRYODAgZgzZw7i4+Oxffv2Fr8+A0NbgClWDAx/YFx66aV4/fXXMW3aNNx5552oqqrC7NmzBSKgRHx8PG666Sa8++67yMnJwdSpU2WPX3TRRZg0aRIeffRR1NXVYezYsdi5cyeefvppDB48GDNmzGi1uffs2RN33nkn3nrrLWi1WkyePBnHjh3Dk08+iezsbDz44IOy8RMnTkRWVhbuuecelJaWysqAACEOzz77LP7xj3/g6NGjuPjii5GQkICysjJs3rwZNptNiCeIFv379wcAvPnmm7j55pthMBjQs2dPxMbGRryPZ599FsuWLcOYMWNw//33o2fPnnC5XDh27Bh++uknvPfee0HKXSR4+umnBf/WU089hcTERHzxxRf48ccf8eqrr8JutwMgJdKePXvikUcegc/nQ0JCAhYuXIi1a9dG/ZoUDzzwAD7++GNceumleP7555GWloYvvvgC+/fvl41bvHgx5s6diyuuuAJdu3YFx3FYsGABamtrcdFFF7X49RkY2gSn2TzPwMDQRggVt6DExx9/zPXs2ZMzmUxc165duZdeeon76KOPQq5iW7lyJQeAe/nll1X353Q6uUcffZTLycnhDAYDl5GRwf35z3/mampqZONOdVUgx5FVjK+88grXo0cPzmAwcMnJydyNN97InThxQnX8E088wQHgsrOzOb/frzpm0aJF3Pjx47m4uDjOZDJxOTk53NVXX80tX7682bmHw+OPP85lZmZyWq1WtuItJyeHu/TSS4PGjxs3jhs3bpxsW0VFBXf//fdzXbp04QwGA5eYmMgNHTqU+8c//sE1NDSEff1Qr8NxHLdr1y5u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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "for index, adversary_probability in enumerate(adversary_probabilities):\n",
+ " if adversary_probability > 0:\n",
+ " plt.plot(opponent_results[index])\n",
+ "legend = list()\n",
+ "for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " legend.append(adversary.name)\n",
+ "plt.title(\"Payoff over the rounds\")\n",
+ "plt.xlabel(\"Rounds\")\n",
+ "plt.ylabel(\"Payoff at the end of each round\")\n",
+ "plt.legend(legend)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "[]"
+ ]
+ },
+ "execution_count": 20,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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jCFvv/02ef/998mUKVOIJElk4cKF7PEPPfQQMbuUvfzyywQA2bdvH7utT58+pLS0lAwdOpS89tpr5KOPPiLXXHMNAaA7T1u3biXp6elk6NCh5K233iL//ve/ydSpU0nv3r11+9y3bx9JS0sjF110EXn//ffJf//7X/Lmm2+SGTNmkLq6upjHLnByQhArAYEk4bXXXiMAyHPPPUcIIaSpqYlkZmaSc889l22zadMmAoC88MILuseeffbZZMyYMez3J598kthsNvLVV1/ptnvnnXcIALJ06VJ2GwDi9XpJbW1t1PXJskyCwSB59NFHSX5+PiNnW7duJQDIr371K932b731FgGgI1a33347yczMJAcOHNBt+/TTTxMAZOvWrVHX0KdPHyJJEikvL9fdftFFF5Hs7GzS0tJi+rhQKESCwSC59dZbyejRo3XHdNppp5Ef/OAHuu0vueQS0r9/f3aMzz33HAFA/vnPf+q2+3//7/8RAGT58uXstkmTJpFhw4aZrn3atGlRj48QQpYtW0YAkD/84Q+6299++23dax8MBklRURGZPn26brtf/vKXxOVykePHjxNCCFmzZg0BQJ555hnddgcPHiQej4f88pe/1K0dAPn4449jrpMQQu68805TUkKI8r4qKioijY2N7Laqqipis9nIk08+yW6bOnUqKS0tjfiycNddd5G0tLSY70ur9+/48eNJYWEhaWpqYreFQiEyfPhwUlpayl7bRIlVWlqa7v3b1tZG8vLyyO23385u+/GPf0w8Ho+OtIZCITJ48GDdPunfo/H9LHBqQ5QCBQSShAULFsDj8eC6664DAGRmZuKaa67B559/jl27dgEARowYgTFjxuDll19mj9u+fTvWr1+vK9ksWbIEw4cPxxlnnIFQKMT+TZ06lZWneHz/+99Hbm5uxJo++eQTXHjhhfB6vbDb7XA6nXjwwQdRU1OD6upqAMBnn30GALj22mt1j7366qvhcOhtmEuWLMHkyZNRUlKiW9cll1yi21c0DBs2DKNGjdLdNn36dDQ2NmLjxo3stn/961+YOHEiMjMz4XA44HQ6sWDBAmzfvp1tY7PZcNddd2HJkiWoqKgAAOzZswfLli3Dz372M1Yi+uSTT5CRkYGrr75a97y0zPnxxx/HXHe8+OSTT3T7prjmmmuQkZHBnsvhcOAnP/kJ3nvvPTQ0NAAAZFnG66+/jh/84AfIz88HoJxzSZLwk5/8RHfOi4uLMWrUqIj3Qm5uLr7//e8n5VgmT56MrKws9ntRUREKCwtx4MABAErJ8+OPP8ZVV12F9PR03fouvfRS+Hw+rF27NubzGN+/LS0tWLduHa6++mpkZmay2+12O2bMmIFDhw5hx44d7TqmM844A71792a/p6Wl4fTTT2fHBACffvopLrjgAhQVFeme+8c//nHEvlwuF2677Ta8+uqrEaVZgVMTglgJCCQBu3fvxqpVqzBt2jQQQlBfX4/6+np2Iec9HLfccgvWrFmD7777DgDw8ssvw+124/rrr2fbHD16FJs2bYLT6dT9y8rKAiEEx48f1z2/WYfa+vXrMWXKFADAiy++iC+++AJfffUVfvOb3wAA2traAAA1NTUAoLuIAMqFn17c+XUtXrw4Yl3Dhg0DgIh1maG4uNjyNrqW9957D9deey169eqFN954A2vWrMFXX32FW265BT6fT/fYW265BR6PB8899xwA4G9/+xs8Ho+OqNbU1KC4uDjCi1NYWAiHw8GeNxmoqamBw+FAjx49dLdLkoTi4mLdc9HjWbhwIQDgo48+wpEjR3DzzTezbY4ePQpCCIqKiiLO+9q1a+N6L7QXxtcfANxut+69EwqFMH/+/Ii1XXrppQDie08Y11xXVwdCiOmxlJSUsOduD2IdE913tPcpRf/+/bFy5UoUFhbizjvvRP/+/dG/f3/8+c9/btfaBE4OiK5AAYEk4KWXXgIhBO+88w7eeeediPtfffVV/O53v4Pdbsf111+P2bNn45VXXsHjjz+O119/HVdeeaXuG3tBQQE8Ho+pqZbez8PMvLtw4UI4nU4sWbIEaWlp7Pb3339ftx290Bw9ehS9evVit4dCoYiLV0FBAUaOHInHH3/cdF30ohcNVVVVlrfRtbzxxhvo168f3n77bd2xUaM5D6/Xi5tuugl///vfMXfuXLz88suYPn06cnJydMe4bt06EEJ0+6uurkYoFIo4nyeC/Px8hEIhHDt2TEeuCCGoqqrCWWedxW4bOnQozj77bLz88su4/fbb8fLLL6OkpIQRYkA555Ik4fPPP4fb7Y54PuNtZu+FVCE3N5epSHfeeafpNv369Yu5H+Oac3NzYbPZcOTIkYhtKysrAWh/A/S97ff7deciHkJnhfz8/KjvUx7nnnsuzj33XMiyjA0bNmD+/Pm49957UVRUxNRrgVMLQrESEDhByLKMV199Ff3798enn34a8W/OnDk4cuQI/vOf/wBQLhpXXnklXnvtNSxZsgRVVVURnVuXXXYZ9uzZg/z8fIwdOzbiX9++fWOuS5IkOBwO2O12dltbWxtef/113XbnnXceAODtt9/W3f7OO+9EdPpddtllLI7AbF3xEKutW7fi22+/1d32j3/8A1lZWawTTpIkuFwu3QW3qqoqoiuQ4u6778bx48dx9dVXo76+PiLY8oILLkBzc3MEqXzttdfY/ckC3dcbb7yhu/3dd99FS0tLxHPdfPPNWLduHVavXo3Fixfjpptu0r1ml112GQghOHz4sOk5HzFiRLvXSokIr9YkgvT0dEyePBnffPMNRo4cabo+M4UoFjIyMjBu3Di89957urWFw2G88cYbKC0txemnnw4A7G9h06ZNun0sXry4XccEKCXQjz/+GEePHmW3ybIc8TfCw263Y9y4cawbki9rC5xi6Dx7l4DAyYHFixcTAOT//b//Z3r/sWPHiNvtJldeeSW77aOPPiIASGlpKSktLSWyLOse09zcTEaPHk1KS0vJM888Q1asWEE++ugj8uKLL5JrrrmGrF27lm0LgNx5550Rz/vxxx8TAOTqq68my5cvJ2+99RYZM2YMGThwYISp9/rrryd2u5088MADZMWKFbquwJtvvpltV1lZSfr06UMGDx5Mnn32WfLxxx+TDz/8kPztb38j06ZNIwcPHox6roxdgf/5z39YVyB//l566SUCgNxxxx3k448/Jq+88grp378/W7sZLrnkEgKAfO9734u4j3YFZmVlkXnz5pEVK1aQhx56iDidTtYVSHGi5nXaFeh0OsnDDz9MVqxYQZ555hmSmZmp6wqkqK+vJx6Ph5SWlhIAZMeOHRH7vO2220h6ejr5xS9+QRYvXkw++eQT8uabb5I77riDPPvsszHXbgVq8H7ooYfI2rVryVdffUX8fj8hxPp91adPH11Dw9atW0lubi45++yzycsvv0w+/fRT8sEHH5B58+aRyZMnx1yD1fPQrsBx48aRf/3rX6wzz9gV2NDQQPLy8siIESPIokWLyOLFi8mPfvQj0q9fP1PzutlrOGnSJDJp0iT2++bNm4nH4yFDhw4lCxcuJB988AGZOnUqKSsr0+3z//7v/8g111xDXnnlFfLJJ5+QpUuXsk7Ljz76KOaxC5ycEMRKQOAEceWVVxKXy0Wqq6stt7nuuuuIw+FgXUayLLMP6d/85jemj2lubib/+7//SwYNGkRcLhdrab/vvvt03UpWFyZCFIIyaNAg4na7yWmnnUaefPJJsmDBgogLjs/nI7NnzyaFhYUkLS2NjB8/nqxZs4Z4vV5y33336fZ57Ngxcvfdd5N+/foRp9NJ8vLyyJgxY8hvfvMb0tzcHPVc0QvbO++8Q4YNG0ZcLhfp27cvmTdvXsS2v//970nfvn2J2+0mQ4YMIS+++KJlBxghhLzyyisEgO6iy6Ompob8z//8D+nZsydxOBykT58+5IEHHoggOidKrAhRiNyvfvUr0qdPH+J0OknPnj3JHXfcYdmCP336dAKATJw40XKfL730Ehk3bhzJyMggHo+H9O/fn9x4441kw4YNMdduBb/fT37605+SHj16EEmSdO+LeIkVIUrswC233EJ69epFnE4n6dGjB5kwYQL53e9+F3MN0d6/n3/+Ofn+97/Pjnn8+PFk8eLFEdutX7+eTJgwgWRkZJBevXqRhx56iMWdtIdYEULIF198QcaPH0/cbjcpLi4mv/jFL8gLL7yg2+eaNWvIVVddRfr06UPcbjfJz88nkyZNIh988EHM4xY4eSERYkjWExAQEADw5ZdfYuLEiXjzzTcxffr0pOyzb9++GD58uGnI5IniRz/6EdauXYv9+/fD6XQmff8CAgIC8UCY1wUEBLBixQqsWbMGY8aMgcfjwbfffovf//73GDhwIH74wx929vIs4ff7sXHjRqxfvx6LFi3CvHnzBKkSEBDoVAhiJSAggOzsbCxfvhx/+tOf0NTUhIKCAlxyySV48skndR2FXQ1HjhzBhAkTkJ2djdtvvx0///nPO3tJAgICpzhEKVBAQEBAQEBAIEkQcQsCAgICAgICAkmCIFYCAgICAgICAkmCIFYCAgICAgICAkmCMK93MMLhMCorK5GVldWhoycEBAQEBAQE2g9CCJqamlBSUgKbzVqXEsSqg1FZWYmysrLOXoaAgICAgIBAO3Dw4EGUlpZa3i+IVQcjKysLgPLCZGdnd/JqBAQEBAQEBOJBY2MjysrK2HXcCoJYdTBo+S87O1sQKwEBAQEBgW6GWDYeYV4XEBAQEBAQEEgSBLESEBAQEBAQEEgSBLESEBAQEBAQEEgSBLESEBAQEBAQEEgSOpVYrVq1CpdffjlKSkogSRLef/993f0PP/wwBg8ejIyMDOTm5uLCCy/EunXrdNucf/75kCRJ9++6667TbVNXV4cZM2bA6/XC6/VixowZqK+v121TUVGByy+/HBkZGSgoKMDdd9+NQCCg22bz5s2YNGkSPB4PevXqhUcffRRi1KKAgICAgIAARacSq5aWFowaNQp//etfTe8//fTT8de//hWbN2/G6tWr0bdvX0yZMgXHjh3TbTdr1iwcOXKE/Xv++ed190+fPh3l5eVYtmwZli1bhvLycsyYMYPdL8sypk2bhpaWFqxevRoLFy7Eu+++izlz5rBtGhsbcdFFF6GkpARfffUV5s+fj6effhrz5s1L4hkREBAQEBAQ6NYgXQQAyKJFi6Ju09DQQACQlStXstsmTZpE7rnnHsvHbNu2jQAga9euZbetWbOGACDfffcdIYSQpUuXEpvNRg4fPsy2eeutt4jb7SYNDQ2EEEKeffZZ4vV6ic/nY9s8+eSTpKSkhITD4biPkx4D3a+AgICAgIBA10e81+9u47EKBAJ44YUX4PV6MWrUKN19b775JgoKCjBs2DDMnTsXTU1N7L41a9bA6/Vi3Lhx7Lbx48fD6/Xiyy+/ZNsMHz4cJSUlbJupU6fC7/fj66+/ZttMmjQJbrdbt01lZSX279+fikMWEBAQEBAQ6Gbo8gGhS5YswXXXXYfW1lb07NkTK1asQEFBAbv/hhtuQL9+/VBcXIwtW7bggQcewLfffosVK1YAAKqqqlBYWBix38LCQlRVVbFtioqKdPfn5ubC5XLptunbt69uG/qYqqoq9OvXz3T9fr8ffr+f/d7Y2JjgGRAQEBAQEBDoLujyxGry5MkoLy/H8ePH8eKLL+Laa6/FunXrGFmaNWsW23b48OEYOHAgxo4di40bN+LMM88EYJ6SSgjR3d6ebYhqXI+Wwvrkk0/ikUceiedQBQQEBAQEBLo5unwpMCMjAwMGDMD48eOxYMECOBwOLFiwwHL7M888E06nE7t27QIAFBcX4+jRoxHbHTt2jClOxcXFTJmiqKurQzAYjLpNdXU1AESoXTweeOABNDQ0sH8HDx6M46gFBAQEBAQEuiO6PLEyghCiK60ZsXXrVgSDQfTs2RMAcM4556ChoQHr169n26xbtw4NDQ2YMGEC22bLli04cuQI22b58uVwu90YM2YM22bVqlW6CIbly5ejpKQkokTIw+12s7mAYj6ggICAgIDAyY1OJVbNzc0oLy9HeXk5AGDfvn0oLy9HRUUFWlpa8Otf/xpr167FgQMHsHHjRvz0pz/FoUOHcM011wAA9uzZg0cffRQbNmzA/v37sXTpUlxzzTUYPXo0Jk6cCAAYMmQILr74YsyaNQtr167F2rVrMWvWLFx22WUYNGgQAGDKlCkYOnQoZsyYgW+++QYff/wx5s6di1mzZjEiNH36dLjdbsycORNbtmzBokWL8MQTT2D27NkxBzIKCAgICAgkE20BWeQodlWkvkHRGp9++ikBEPHvpptuIm1tbeSqq64iJSUlxOVykZ49e5IrrriCrF+/nj2+oqKCnHfeeSQvL4+4XC7Sv39/cvfdd5Oamhrd89TU1JAbbriBZGVlkaysLHLDDTeQuro63TYHDhwg06ZNIx6Ph+Tl5ZG77rpLF61ACCGbNm0i5557LnG73aS4uJg8/PDDCUUtECLiFgQEBAQETgx7jzWT03+zlPzvos2dvZRTCvFevyVCBOXtSDQ2NsLr9aKhoUGUBQUEBAQEEsbC9RW4/73NGN4rG0t+fm5nL+eUQbzX727nsRIQEBAQEDiVUVHbCgDwB8OdvBIBMwhiJSAgICAg0I1wgBKrkCBWXRGCWAkICAgICHQjHGTESu7klQiYQRArAQEBAYEuiaAcxhe7jyMod11lhhCCtkDHEpwKoVh1aQhiJSAgICDQJfH3z/fhhr+vw0ur93X2Uizx8AdbMerR5dh5tCn2xklAQ1sQ9a1BAMJj1VUhiJWAgICAQJfEun01AICv9td28kqs8fF31QiEwtiwv65Dno+WAQHAFxJZVl0RglgJCAgICKQc24806khBvI8BgJ1Hm1OxpBNGayCEQ3VtAIAjDW0d8pwV3DkkBAjKglh1NQhiJSAgICCQUhyub8MP/vYFfrJgXdwKS21LAEcblfFlB+taO9zHFA/2HmthP1fW+zrkOQ/U6MmplYE9JIfx4L+34D+bj5jeL5A6CGIlICAgIJBSrNp5DIFQGAdqWlGn+oNi4buqRvYzIcDu6s5XrQgh+GL3cRxtVEjUrmrNV9UZihVgbWDfWFGP19YcwB8+2pHQ/hd/W4lJT32KrZUN7V7jqQ5BrAQEBAQEUoovdh9nP+873hJlSw3fHdGbwTvKHB4N5QfrccPf1+Hut74BAOziSpRHGjpGsTKWU62IVZNPIbDHm/3stqONPvy7/DBCUbosl22pwoGaVny8vToJqz01IYiVgICAQDdDdzIsh8MEa/bUsN/3x0usVMWKzrjfZVCs/v75Xpz7h08S9m2dCKifasOBOjT7QzoVrbK+rUNelwO1+vPnD5qXAlvU0mmTL8SI1O8+3I57FpZjxbajlvtvU/fXUUTxZIQgVgICAgLdCF8fqMPY363EO18f6uylxIWd1U2oaQmw3+NWrKoUhWp8v3wAwC6DYvXexsM4WNuGtXtrIh6bKrQGQgAAOUywYX+tjlj5Q2HUcseZCgTlMPNy2W0K4/RZRC60+EPs54Y2Rb2iZcS9UV4Deoy03CmQOASxEhAQEOhG+HL3cdS0BPDBt5WdvZS48MVuPfHZVxObWIXkMHaoxOoHZ5QAUAgaj0N1Ckmoj9OzlQw0+zV1aNXO49ivHovLoVxKU63yHKn3QQ4TuBw2FGenAbA2r/PEivra6lTiVx2FNLWpRK1KKFbthiBWAgICAt0IrWqpZncX8BxZ4ViTH/8uPwxfUMaXqr/q7L55AOIrBe6vaYU/FIbHaccFQ4oAAAdr25ia0tAWRKNP+bmuNbUqEQ+erCz65hDCBMhKc2BQURYApRyYSlDFqSzXgzSncvm28li1cl2U9eo5oooa7bY0Q5t6jquEYtVuCGIlICAg0I1AYwcqG3zMoNzV8MRSxctz1bNfYt0+JdzzhvG9ASilwFheJOqvGlSchR5ZbuRnuABonYGH6zQCE2+XYTJgpgINLMxESY6iHqVasaL+qj75GUhz2gFYE6uWgH6t/pCMZnX9R5us10kJWW1LQMwibCcEsRIQOIXwwbeVmLFgHSsJtBdNviD+XX64S89wO1nBX9w7I4IgEArH9N+UH6wHoAR8NvtDyEl3YuqwYtgk5cJ9rMlaMQG0jsAhPRUlaGBRJgAtKJSWAQGc8Hs5ETRz555iYGEWeno9AIDKFEcu0C7EslwP3Gr50cq83sqVLetaA7qSaXUUxcrH7S/adgLWEMRKQOAUwhtrD+DzXcfxxZ7jsTeOgvvf3Yx7Fpbj9TUHkrQygXjRyl34drUjkbw1EMJnaq5UIgjJYfzzq4M4/6lPMf7Jj7GxwnyES2sgxLxHI3p5AQCTTu+BNKcdpbnpAGIb2KliNbg4GwBwulpqowb2w/W8YtXxpUDaqQgopI8pVikMCW32h/DeRqVhYcKAArgd8StWDa1B1DRr56m6yYdw2Fw15EuIojOwfRDESkDgFAK9mJ7I8NZDda34zxYlzfnzXceSsi6B+MEnkO+qTtxnNf+T3bjppfX454aDCT3uJwvW4ZfvbkJlgw+EADurzJ9759FmEAL0yHLj3Tsm4MUbx+Lhy4cBAPoWZACITqx8QRnr9irlwxGlCjEbqBIrmmV1iCsFdoZ5fXRZDrutf2EmU6xSGRK6cH0FGn0h9CvIwIVDiuBWPVa+OBUrnoAGZWJKSAkhLG4BED6r9kIQKwGBUwihsEKoAidQwnt97QHQL7sb9tdBtvjmK5Aa8KXA9szQ23JYSdROpJ1eDhOsVclOrxyFRDRa+LvofL/BxVlwOWy4aGgRclWPVL98VbGK0hm4cvtRNPlD6JXjwRmlOQDAzOHbj1BixZUCk6RYBeUwXl+zPyrpo+eeGuoBYEAPTbE6kbE2b39VgZEPf2SqBAblMF5avQ8AMOvc02C3SVopME6PlTEKwszA7g+FwdvfqjooTf5kgyBWAgKnEIIh5VOzvd6otoCMt7/SlI4mf4hdSE92+IIy/rGuotPb0HlFoT0eK9pZZnVBNgP/fjmnv5IrRbORjPhOfT8M6ZkdcV8/VbGK1hm4aONhAMCVo0tgU7OahpVkQ5IUBaW60adTrOpaA0kJ5vx4+1H89t9b8cTS7ey2L3cfx7wVO9mXB0pWBhdn4X8m9cesc/uhNNfDFKujjb52fdEghGD+J7vR6Avho61V7LanP9qBu/6xEb9+bzMqG3woyHThh2f2AoCYpUBjV2AEsTIxsLca5jFWNQiPVXvg6OwFCAgIdByCVLFK0F9D8e/yw6hvDaI014PTemRi1c5jWLevFsNVL83JjH+sq8CjS7ahV44H//yfc5hy09HgL36H69vQ7A8h0x3fR3lQDjNSksh7gCdW+ZmK+tTYFmnkBoDtVXrjOY++jFiZp6XXNPvx2U6lvHzV6FJ2e4bbgQE9MrGruhmbDzfoPFZBmaAlIMd9DqxAzws/AubxpduxtbIRE/rnY/xp+cy8nuF24P5LBrPtCrPcsElAKExwvNmPIjVjKl5srKhnz79PHey873gL/vrpbt12N0/sx7oBtbiFeHKsIomVWZZVm6GsKEJC2wehWAkInEIIycq36UTUCh5vra8AANx0Tl+cc5qiXKzf13HJ150JWqI5XN+GG15cGzVkMZVoNXSmJaJaVda3MUUlkVZ6+r4BwKIPzEqBhBCmWFHjOY/TCpTuvv01Labm6SWbjiAUJhhZ6sWAwkzdfdRv9eWeGuarounjyegMPKYSqjad0qOft0fJSoZLT+IcdhsjU+3JslrMhb3SUiQd4VOU7caUoUW4ZHgxbjynD9uOKVaqX7K60YdPv6tm6l2r4TiMJVOzUmBbQP/e6qjB0icbBLESEDiFQJWH9pYC99coSsOkQT0w7jQl8HH9vlrLDqOTCdSb5HHasb+mFff9s7xT1kG7Aguz3AASG058oEZTitpTCpQkICedKlaRxKqywYdGXwgOm4T+PTIj7i/JSYPTLsEfCuOICTFd9I1aBjyjV8R9I1VVdNkWpVSWk+5Ej0zlHCTDwE675nhvEh9ICgAtqiE8w22PeHxPb/uyrEJyGEs2acTqQE0r5DBhhPmc0/Lxwo1j8X8/GYOsNCfbjnqsfCpBfuC9zbj5la+wXs0N4xWr+tYgGyuUnaaQQjM1qi2gf09ECxIVsIYgVgICpxCCqvLQnlIgIYSVQrLTnBjRywuP04661iB2H+v4PKWORKMvyEjlszecCQDYcrhzvGVUiRildqYlolgd4EzjCRErlTg77TZkqxd3mnzOg6pVAwoz2ZgXHg67DWVq5MIBg8/qeLMf5QfrIUnA5aNKIh47Uj1eWgYszfUgJ11ZS20CBvbyg/W688A/P6BXrOgg44a2IAghjHSZlR17qqXhRBWrNXtrcLw5gNx0J1wOGwJyGJX1bdijvq60I9II2hVIFSt6XqiHTm9eDzBVb7DqfTMjTZRIprvs6jbWsQwC1hDESkDgFAJVHtpDrNqCMisjZaU54LTbMKZPLgCwdO2Oxpo9NZixYB32pJjYbVVJVK8cDwar3qEWfygppulEEJLD7LUbpZbGjMOJo4FXrBJ5D4TU943TJiHbo5AKqlj5QzJuemk9Hv5gKzYdUlQ9M+M6RWmeQqx4AzqgEcSy3HT0UNU4HkN7ZrPSHwCU5qQjTy1L1sdJrI42+vCj//sSN720PuI+plipqhR/rhvagmgNyKxjLsOEWFHPXaKK1b/LFbXq0hE90Uc9N3uPt7BSoJnyB0Sa11s5EiiHiW44sz8UZoRvSLHy/q02M6+ramjvvHTNM9aSfNVq//EWvL72QLu9nl0dglgJCJxCoBfI9sQtNKkKhd0msW+0Z/fTyoGdgX9uOIjPdx3Ho4u3xdy2oS2Im15aj0XfHEr4ebZWKoRheK9sdlENhckJxVbEi3+XH8YrXyit9nw4KFOsEiCVB2qjlwJf/mIfrnr2iwijMyXkDk6xouWxTYca8NnOY3jly/3MbD242FxlAZTUcAA4WKc3sO9VTdun9cgwfVya086CQgFFscpVy5Lxeqx2VDVBDhNU1LZGKDFMsQrKCIeJ7lw3tgWZAiRJmqLDQyN5Wlny4Q+24saX1jMlyAhCCD75rhqAotLRrsm9x5rZlwWj14xCi1tQ1kmfo7EtqHs+GmZKlawhTLGKJFY+lZxlpTlQoJZZjxo6A5MRr/Lw4q347ftbsHxb1Qnt52BtKx5bsk3XcNAVIIiVgMApBFrSaY/His6ly3Q7IKmf1vRCcCzK7LFUgn7j/WznMXyrjlGxwpe7j+OzncfwWjvS4jer/qrhJV6kO7WLKh/CGAvHmvx4afU+y5gCM/iCMub+61s8vFi5eNAylU3Szn1Vgy9u5YwvgQVMzOsL1x/ENxX1+JDz/ABaCdlpt8HroaVA5ThquIsavegOjqJYlamqzMFaI7FSiAQ1uJthJNd9ypcC450XSMlFmADNHPkghOiSyduCsu61bWgLav4ql/b+50HLg83+INvn62sPYNXOY3hh1V7T9Ryqa0NtSwBOu4TRvXPQTyWVX+6pQWtAhtMuoY+a/WWEcVYgLdPXq+oaoHwJys9ws2MGtNfmWJM/giTRx6U57ZxnTFMWH3hvE8Y9sVL3micKQghTNnkFtT146IOtWLB6ny4CpitAECsBgVMIlFC1pyuQemqy0rQyCP1w951AkvuJgFeM5n+yO8qWmuLWHlJJjevDS71w2G1MLWixUCLM8OLne/Hokm14+6uKuB9zoKaVkZq6lgC78KW7HCjMUi58Sop2bGJBCGHEAjB/D1Dy/OUefadniBErCdkqsfIFw/CHZGaKHlychZ7eNGSlOViwpxmox+qgoRRIFZr+heaKFaB1BgJAaW66pljFWQrkyVwDd84afSHde6klENKPhGkLah2BJsZ1gCdWyna+YJgRl+c/22uaf0bfV6cXZcHtsOM0lSzTiQZ98zPgtJtfprVZgWFd6Y9fa7rLjtx0p+5xAwszYZMUomUkSDRuId1lZ12OvLK1YttRHG8OYEtl+/2FRxv9TBE9kUy42pYAVqnRHIl8WekICGIlIHCKQA4T5hFpj7eBEhPeuBsr/TnV4EnSyu1HsS3KB36TerHhowPiQbM/hL2q0Xp4iXJhp+egJUHFCohfXQE0FQdQFCL+guly2Fj5ycwvY0R1k19HgM3eA/Q1XrO3Rlcqo/lnDruELLeDlZeafCHUqkrPqNIcfDr3fKz+5ffhNVzMeZTlqaVAo2KlnuOoihVHrHrleliie6KKFaC/GBtLSW0BWWdib2gL6jKszMCIlXoOm/za/tuCMp76aEfEY6gSSmcq9lOPnb5OVmVAgDOvh2Rd6a+BU6wyXA5GPgHlfZPhdjAPm9HA3sYR92JVsaJjbQKhMI6rr/WJxFvwgcInMjLnw02VCIVptET8X3A6AoJYCQicIuBJSHtUG3rByOZavlk5wmJeWapBj4OqaC+pXiQzNLdTsdpW2QhCgOLsNHZBSldVi0QUK3phToTU7uU65xp9IZ2iAGiRC/G0xRvLLkYyHA4TVh6rbw1iG3cBDKrbOu022GwSIxGNbVobf16mC2lOe1RSBWiKlUL0ZHUtMiNa/S08VgAwqDgLOelOpLvs6J2XztSYeM3rPLHi4yL4MiCgEGY+roBXgayCSDPV9yAl8LwnEQDe3XiIefUoWIlZJVZ9C/Rlv4HRiBWXY9UaMJYtVQLutrNyKQBGsszUKEBfCiw2xEcc48in0YOXCPj31YkEkFLTPxCZGN/ZEMRKQOAkw/Yjjbj1la9YmYGCJxTtU6yUCxFfCux0xUod0TOxfwGA6IGG1PsSStB8u8Vw8QO0gMhEPFb0W3Ui557vdmzklAiP+vyF6gUynrDS/aq/ihID4zqaAyHdnLgv9xxnP9Nz5rQprzdvYKcXWRocGgs56U62BtoZeKCmFWECZHFqihncDjveu2MCFv1sIjLcjoRKgYQQVNTEqVgFQ3qy0sopVq7oihUlNZTIF2W5MW1ETwCKh41fzxaDYtUj060jbv2jEitNsWrmSWCrtWJFFU5aRjaOteGJO/NYqfMP+bJdvESWru+ehd/gn6oPileVE+2gpDhY24oNB7SZion8HXYEBLESEDjJ8N7GQ/j4u2r84p1NunIOXwI7ka5Ac49V53yw+dXjoGqBP4rXqzlKKbDRF8Sb6w6YfhPfwnUEUlDFqNmfiGKlnKOEFKtjesWqlV3c9YpVdVNsxYqSClpeMiavNxlyqXifldYVqKgv2R4ty4qes7w4iZUkSSg1dAYy43qPDFNjOI/TemRikNp1yMzrLRpJojP27n93k87U39AWZGoS/Z3CSKxa/LJOjWzyh9j5sSoF0r8LSqjoeyMrzYlrzyoDAHy4+Qg7l4fr21DXGoTDJrHjkSSJNSUAMUqBXNxChNGey6PKydAUK/oaFWVblQKVx3mcdvTKSWfrVLbVSFC03LCgHNZtu3rXcfy7vBIPL96KtoCsKwUeb/a3Sz3/QE2qp2+V1k76/LGCIFYCAicZqD9j+5FGLOa6u5KlWGV2KcVKJVbqxS7aOqKZ199cW4HfLNqC51ftibivWr348N1Z9OKaiLeDKhnxjpIhhOg8Vk0+XrFSLqr0AhmPYkWjFk4vUi7WxvdAk2FEzfp9tWwbaqB32KliZVIKjJNYAYrxHAAOqWvaw6IWrImEGfIyIhWrl79QYh8WfnWQjYcB9GVAwEis9EShNaDvCiREIxaZMczrLQEl7415EtMcmNg/HwWZLtS2BLB6l6IE8sb1NK7TlBIrSbLOsAL4WYHhKEZ7c8WKlQIbzBUrj8vOyC8dg8QrVjyRNWL2P7/F+Cc/ZgSKBuu2BmQs3lSJfapyKknKeT0Wx5cCI5ZuPgIAOP/0Hsq6hcdKQEAgleAvmPNW7NTG2IR5xSrxLJom7hs4RWcrVvTYNGJlvQ6mWJmUAmkJ8YDJcGB6bGkO7eJHy0EtCXg7qNoUr1pY0xLQpZs3toXYN/N0RqyoVyYej5VyQaNZUEYSSolA7zwleLM1IGPToXoAWv6ZS1Ws+MiFWjVAkrb1xwNqYKelQNYRGMVfZQY6Xqc1IMMfkrFhfy2eWLo94piASI9ZNMWqNRCKIM1UubFSrPjbWwIhXTyJw27DZSOVNPn3y5WxPUbjOgUdVF2Wm64jXEZoHiu9eT0UJoyspLvsyPFEeqzol4S9x/UZaFrXqdIV6LBJCIUJqpt8OhXKqvRKCMHqXcdACFiproKL+Pjzyl0gRFFaS7zKeyBRA7scJiw89ftDinTr7ioQxEpA4CQDr8gcqGllGS+hE1asIkuBVLEKhYlu/x2FoLEU2E7FioY6mnXX0X3SLixAM68bByJHQ6Lm9T2GUTWNviBXClQ9VqwUGP3iFJLD2HVU2R8NiLRSrLI9DjZge+1epRxISbmDeqw8kR6rvMz4FSstcoGWAtunWGWnOZg5/GBtK+78x0YdceaJVTTFyhg70BKQI0hzZQxi5XbY4FSJZ7MvxF5v+t78wRkKsVq+9ShaAyFsVtP8h5fqiRXN6qIBsFag70dfKMzKzBSH66m65mDkEwDy1deIlh6/q2rSlUtpV6DHaYfdJqFnjkLcD9W16QiQlXm9usnPOjSp2sqH0lJyOqRnNlNbE41cqKxvQyAUhsthY+Z+QawEBARSCqqI0EycdzcqSeP6UmDiH0SaeT1SsQJSVw4MhMJ4/5vDplk1tETFFKtoHiv1ImuWHF3fRolVpPJDVTBTxSpOYqXMmaMdcPGdp72GWXpNvlBEKbAwTsVqV3Uz2oIyMt0OlooeChPduWDE2e1k3Wm0REZLrsxjpb4HKuvb2GsQr3kd4ENC20AIYYqVVeq6FSRJYp2BL32xH0cb/eiTn87IYzMXeUC7Dr0cKaSgx+lR389tJopVpUpWrMzrkiTpDOxaF61y2xllOeiTn462oIx5y3dis6oGGhWr7w8uxOu3no3HfjAs6rFrOVZyBMGnCmy6y6HLsaKK1WkFmXDYJDT5QjoDOV8KBJSxQQBwuK4tLsWK909Rsky9fZR0AsDQkmz0pIpVgsSK/l30zU9n51vELQgIdAAeeG8zbnttQ4fPcusKoErEkBLl4kIv/sEkmdezTRQrwJowtPhD+NmbX2Pxt5Wm98fCkk2VuPftcsz5Z3nEfQFD3EJcpUCTMmiDeqGobvRHvGeoZ41XrDLciZUC/SEtLDJexYp+4+f9TFZxC8eaItfNg5b0hvfKZhdN41r4AFiXXdmGkvFQmJYCqWKlrGm/WjpNd9mjlq2MYFlWda043hxAky8ESVICMRMFVWTe/Vr5AnHjOX2ZGtJoolhRImOmWPVWCZ8St6B/bSlZsQoIBfSRC82GeAZJkvCDM3oBAP6+eh8zrhvH/9hsEs4d2EOnNJmBN68b34e0ky/DbWdZXwCQpxrZXQ4bI7E7qrRZk62cYgWA+awO1bXqyHtda9D0/fYdt699x1sghwlTJa8eU8buUxQr88iHWNin/l30K8hg72WhWAkIpBjhMMFb6yuwfNtRXfbKqQJWHlO/WVNCxRMKGlOQCIwXCkC5CNCLrZXPat2+GizdXIW/f24+1iMW6Af6x99V45BhvpzRYxWNtFDFjYZd8qCKVUAORyhjlKy5dYoV/UCP75syr2xFI7UffFuJkQ9/hH9uOMi+8dOSkD4gVDleGk0QkMO6GXVGfKuOEBlVlsNeL/7YAL0i6XQo6gLz5zHzul6xoubwRIzrgFYKrG8N4mvVi1Oa60mInFFQRcYfCsNhk3DlGSURYZ2ARqyGmxArqlhRJa0tqA8IBSLVUTNkup3seSmpo7cBwE/P7YfbzzsNkwf1wMDCTNw+6bR2HTOgL8M3Gt6zlZxixedY5XE+uEHFyhcvngz5GHFXjrFXruaF45WlQChsSma+4xSrQ3WtqKhVJgc47RJuP+80dt/Qntko9qqlwESJlfqe61eQydTDtoDcpb5EW79DBAS6KfgLZ6Ip2ycD6IU7w0A2+Au61cWdEGLZ7q55rPQBkG6HDQE5bKlY0fJce8fe0PUTouQAzZ06iN0Xb1cgIYQRQ0KUciD15gD6wblHG/06tYCuO03nsUoseZ3fzor87TnWjPvf3YTWgIzfvr+FvX6je+fi813HFcUqoFes3A5lZEldaxBHm3w6dYIHVaxGlebAYbfBbpMgh4luLU06xcqmW2uIxS3oPVb0Ap5IGRBQ3pt5GUqX3K8XbQYAjIwyBica+NfqgiGFyM90s/co76ujHima3k6JlS+o5UBpilXIMvzVymMFaB2Dzf5IjxWgENIHLh2S4BGagydkxtKcFg1hR44nUrEClBFEi78FdlRpZMhYaqbdm9uPNDK1lBra61oDEeeCJ2lhoo3mKc1NR9+CDPzvtCFobAuif48MbK3UB5BGw+7qZka8tYR+TbGiA9H5Lz+dCaFYCZx04EteyZjE3t1A1Sj6IU9JVCzz+u2vb8DUP62yLKeZBYQCgDtGZyA1PscbM2BEQNYet/Crg4YEefVY1TVZmejbgjL4twK/DzlM2EBhINIIHk2xitdjxV+kzc69PyTj7re+QWtAhsMmwR8KM4PwaFWx4j1W6Vw5r4iFhJqrs76gjO+OKBc8SioocfLriJVqXk9zsPl09PyyIcw2fVcgFQkSVawArcxU2xJAT28aHrxsaML7AIA8jljRchPLlFI9VpX1bQgThRzTbChKrGhHoMthYyXEtoDMznWWgTxEV6w0pazZ4u8lWXBxZXgrM3m6ywGXw4bRvXPQ05vGiBIADCrSDOwUVqXArWqop9fjREGmco6MkQuBUBi71YYLWqL+9LtqABph/em5p2H2lEGQJIl5rGKVAj/aWoUL532GR5dsA8ApVj0ydH8HRoWxMyGIlcBJhyB3sUg0ZftkgN9CsYrmsWr0BfHR1qPYebRZl06t3yayKxCInWVFiU57OhGNjzve7MeKbUcBKCoU81hx5RYzNa7ZEH6p7xwL6hLHeYJCCInhsUpOKXD+x7uxtbIRuelOvH/nREZUMlx2RgQafUEubkF7DbS5b+YXqG1HGhEKExRkutArx6M7Fv41a+YUSXrRpmulKrDTkGNFkZdA1AIFLQdmuh14+eazGEFMFDQAsyDThfMHKblGlAxR5YaWAXvnpbP4gca2IMJhwsqABRkuTYkMhNhrRjvjKKIqVqpSxitWRmKWLNhtEjOEWxEr+gXgX7efg//+4nydykU7A/cca2ZfNHwGDx99v9C/l6JsN1NFjSGhe441IxQmyE5z4Jz+SlfpGrWrlM+AoyhWX++qBp+ujPfql/vx60Wb2d/9m+uUoeVLNx9BayDEOgv7FSgDquk56Eo+K0GsBE466NWIzgmu7ExQYkkvAEHDxRFQyAr/YbbrqPat1az7zh+S2QcdT2IArURmpVjRcmx7uwbp89Ln+Yf6QcuTI95QbNYZ2GRQlnhVy+hN4sd88CSIvyjR54v3w5xPaDcjmP/dqXyzf+DSIRjey4v/96ORsEnA2L55rOzmC4aZyd5UsbIIWtx0sB6AUmqjZV5NseI9Vhpx1hQrqnYaAkI9+vdAfgJRCxQ/PqsMo8py8MKNYzC4ODv2AywwuiwXAHDzxH5s3ca5fQdrlYtxWW46W3uYKGN8qHG9IMvNeedkVvoqVpUViqjmdapYcUntmSlSrABNRbUaK0SJosNuiyiT9crxIMNlR1Am2He8BYQQ5hmkJbae3jRdybwoO81yPuN3aklxcM9sNkibfimhihWPQlUd9Ic0X2NQDuPxpdvxj3UVWPTNIVQ3+bBaLSfWtwaxZNMREKK8R+mxUnWtKxEr4bESOOkQMCkVnUqwMnQb/WZBmcClmpR3VGmZSWYmaF7xMV4o+O4k0/WET1CxUo/n+4MLsXRzFQtW5Am0x2Vn3g+zdRgVK/59UW8gkrxixfvC+A7I9ATjFniPldn66EWhj3oBumhoET6Zcz7yM13IcDlYSjU18vOdfSzLykKxosb1kVxeElWszD1WTtYFqKmdVLHSj7ShaE8p8LzTe+A8NTn7RDB1WBHW//oC3YxBo8eKkqceWW6kOe1wO2zKBb01yEqBBZluRlhbA9oQ5hKvXrGKVgrUSpAcsUqRYgUo78lmv0asSnI8LAkf0BQrM9hsEk4vzsI3FfX4rqoJffLTWbmcvr8cdhuKs9OYSlScncZUU6NKRsvNQ4qzImIzzIhVmlPzBx5p8CEn3YXd1c3sPff8Z3vR2BbSlfBf/XI/ACXvjH5JyHA7lAHlXYhYCcVK4KTDqe6xMprXQ2GCcJhEBGPyBJQ3sJopVswM67LrvsECsRUrqqC1V7Gij6MXb3ax5zobnXabbiit1fop+PeF8Zs3P2KD7kuSoOumy0zUvB7DY+UzmIYBJYE7K80Jm01iHZ60y5UvR8VSrL6lxnUucNLMY9XIeYJcBsWKeawsS4GJE6tkQZIkFGan6ZoutLl9yjHR0EpqdOezrGgpMD/DpSPMlOz2jFCsYnusmriAUGOzRzJB3/PUvF6SQNkSAIt62FHVqCMmHk6dpZ2BAFDsTWOetjoDsdquerUG98yOIFZ9LGI0ig3p6/yA5r3HW/CnlTsBAMPU6Bjq9TqNm6dI/2biLct3BASxEjjpwBOIU9FjxUqBfF6RHI4gVrwXbUeMUqBVRyAQW7Gir0FADrerJZoSEdq2TgkhTwwdNon5gkwVK7/+mPhzYTxe3qtEy4puh0134U5P8MO8JUYpkKoAHovWe6oQUULIb6cN1I1UrJp8QS22geu6o6+ZZVcg81jRqA59QGiGywGeXyfaFZhqGD1WlDzTMpaX81kd50qB9HVtC8qWHqtoClQGe94gR6xSp1jR8jQlvhEk0CLMlIIa2HdUNTEi6bRLjEADmoEd0JcC6zhlmxDCwkEHF2fpBkkD5ooVABTT967aGUiJE2sOUZs5nrhqhO5x/P7ZayYUKwGB1IG/WJyKHiujYgUoRMJYCqTbEUJ0IYHmxMq6wymmYsU9b3tUK+btUp9bVjv/KDly2RXSo81OM/FYRTGv09InG2hsolgZs4a0Iczx5ecYzevGx7SZKFY8jOed91j1yLJWrOgsvrwMl05VMiOhuhwrqlgZS4HqSBubTdKVAztTsTJDFmciBzRFJ9dEsaLnqDg7jVOsNI9VCUdW7DZJVxKOeF71fXG82c9IcCpLgS7DWqjZnCI9ih8M0LKsdhxt0lLXDe91vpOwODvN1Lw+/5PdONbkh8thw+lFWUh3OdBTLaEWZrkt39fF6jZMsTqilK3vuXAg+1yZdHoPjCrL0ZEpHbFyan+LXQWCWAmcdDBrxz+VQIkIb7INhCIVK7rdsWa/7tunKbEyyeSh4IfBmkEX89COxHdjujq9zej70TrdItfRHId5nQ4nPtqodSn5OMWKByU2soWnywhjMjZ/HsLcPiwVK4NSqC8FUo9VZPp6De14M5jLjWVTPueLN69rXYH6UqBxTYkMYO4IMPO6jxIrWgrUK1YNbUHWuDGwMJP9zTS2BdlnRzHnscpw2S1z3vjnpWGaNklPgpMNt+H9UpKTmGJFS3aH69rYuTKSoNIcvWJFSTQtBb61vgLzViglu/+dNoS9N+m+zToCKYqzlX1X1LaCEMJKgRMHFOCOSQNgk5SmBAA4b2ABe5yOWLFGElEKFBBIGYTHipIBOyMdQZmwi6Nxu52ccR1ARIozEL0UmGbSus+Df95os/ysoJUCHbrbGLFSSQIlC2altujmdeUCMbBQIVb+UJhFS1gpVnzcQTwGduM2/BrbOEJq9c2ejpAx245PXzeS4poWzZjNw2U4Vy0BLeeLLwVqXYH6UqBxTYkMYO4I8CZyOUy0UmCGXrGqavSxIcEDi7LYeeWJL+9biuVZou9RGnqZ6XZEJWInCiPh58uWkqQPtTVDj0w3XA4bwkQboZRuIGO6UqDXzXxqda1BbKtsxG/UgNe7Jg/Ajef0ZdtS8tM7z3pM0ejeOQCA/+44hv01rWj0heC0SxhYmIW7LxiAbY9ejO+phOrcgVqjg1kpUChWAgIpxCnvsVJJg8th05SHUFjnqaK3AVqbNIWxSw6IXgqkipV1KfAEFSt1nekuO/P1BEJhBEJ6FSWa1ytCseJKxA2qmlHsdTNT9jE1csFvoVjZbVJCbd7G57ciVmkWydFGxSqdI3puh515nGheEwUzZhuIlfFc0deXHpfLUAoMMfM6R6zStLlz0brPOgM8CW8JhJhiRf1BtIy5saIehCi3F6gdmDxcDhvSXQ5GUGISKzazkqqsqTOuA5HvS75sqXSTRid1NpvEFKmdRxViZfwS0VtVnFwOGwoy3Drz+rKtVQgT4PxBPTBnyum6x101uhRDe2bjR2f2snz+Cf3zUZCpJPA//9keAMoXHJfqaeTXMnFAAUaWenHpiGLd6+ARpUABgdSDv3ibpXB3FxBC8MzyHXhHHS4bD+QwYSqd027TBT2GwubEaqdaCqFG1mjmdWM3GBBbseJfA6tyYTTQ19PlsOm8QbzHCogsb+nW74+mWKllIo8LhWwwrKL0+CwUK0ArtcZjYG/1W5cCqb8qzWmDzWZ+IeT9TC6HjeVJUQxVu6ZotAIFjRkwmsuN6h5vXJckic0KpOZ1ul6HLbIUmJ/hSqkq0x6kceSwoTXIOh6NXYEb1TmFpxdlQZKkiFIsVUPo9rGIVSIp7cmAMZsqN8PJ/h7jLUHSrj9aEjU+rjQ3Hb++dDB+/8MRsNkk5GZQ83qAZUxdPKw44j0wpk8ult5zLiYMKIAVHHYbLhtZAgD454aDALQOQCM8Ljs+uOt7ePaGMbrbNfO6KAUKCKQMJ0vy+qG6Nsz/ZDceU0c5xANeHYpQrCzM6zvUb6pn98sDEN28bnahSIs10iZK4ns8oBd/l92uiwmw9ljFLgXqPVaKquNNd3IG9uiKFQCd0TkWjOTLTLGy8lcBeqXQ7IJ5hhql8K0aBkoRr8fKqEhq7xvlfqZYceeBlgK7mnGdgqpHh+raWLI+TV2nRIkqidRfZ7PpyRVVsCiJzIxhBjcSr1SGgwL6Up9DHYgeLwmkoOb0XdW0FBh5jLed1x8/PLMUgNYA4A+FUa6+3yZGIU+xcOVoRdGiH9VDLYiVFdITDOvtCHQqsVq1ahUuv/xylJSUQJIkvP/++7r7H374YQwePBgZGRnIzc3FhRdeiHXr1um28fv9+PnPf46CggJkZGTgiiuuwKFD+m/4dXV1mDFjBrxeL7xeL2bMmIH6+nrdNhUVFbj88suRkZGBgoIC3H333QgE9DkdmzdvxqRJk+DxeNCrVy88+uijXWqitoCCk8VjRYlKIqZMnrg47ZIuj8gsbiEcJuybajRiFS2TJ+ZImzCvWCVOrOh+FcVKiwkIMGJlKAWadgXqj0nXFcgUKycKs8wVK7PhrmysTRweq6ilQDb/z/pCyJcC000IGI1SiCBWqsfKWAo0eqzYuCI10kJ736hxC3SkDaeo0Qu4cd9dBZQkHqxrZb9Tpc9rCDg9vSiT/cwTiwjFKoYZ3EikUhm1ABjmV6p+LrrWeBUr6qGi58lMneWR7rKz90+YKOb0Mos4hXgwqtSLvpzBfViJN8rWJuuhpcB2qOGpQqcSq5aWFowaNQp//etfTe8//fTT8de//hWbN2/G6tWr0bdvX0yZMgXHjh1j29x7771YtGgRFi5ciNWrV6O5uRmXXXYZZG5w6/Tp01FeXo5ly5Zh2bJlKC8vx4wZM9j9sixj2rRpaGlpwerVq7Fw4UK8++67mDNnDtumsbERF110EUpKSvDVV19h/vz5ePrppzFv3rwUnBmBE8HJ4rGSiTYANxzncfAXbBcXmhkwiVvwy2EcqmtDa0CGy2FjF2czYmU1JxCIPYQ5lCzFyqE/HmNoZbRSYKTHSltTAxceWch12AEaSTMzAWvjTxIvBfpNFKtoRmPeKJ5uokTQ8M/dx5p1JJIPv+RhJMNNhtfXaF4PGEbaAFpZraCrKlbqeTqo+s5yuWHNtDuQYqCqWAH6iAJ6rilZiVXaMxKvlJcC+fmVCZYtKSgpohpBLEImSZJu8PWE/u1Xq+j+fnCG5sMa0jMrytaRYOb1OKcgdAQ6daTNJZdcgksuucTy/unTp+t+nzdvHhYsWIBNmzbhggsuQENDAxYsWIDXX38dF154IQDgjTfeQFlZGVauXImpU6di+/btWLZsGdauXYtx48YBAF588UWcc8452LFjBwYNGoTly5dj27ZtOHjwIEpKlHrvM888g5kzZ+Lxxx9HdnY23nzzTfh8Przyyitwu90YPnw4du7ciXnz5mH27NldzmNwKuNk8VjxaltADiPNFvsbKF8ekyRJXwo08VgdaVAyfHrleJh3IhAKwxeUdd9coweERlesAnKSFCueKHJmfGNXoNk6InKsuAwvplila4oVLQVSsmimWLGBvXGUAo3Ezm+iWFl1BAIGxcpkux5ZbvTK8eBwfRs2H2pgvpZ4FSs+wwrQyCpN7Q8Zyq4AcMWoEmyrbMSNE/parrszwRQrlVjxZCpSsdIu5jw5SpSs2G0SMlx2Fq+ResWKG7PESKA2wDse8F1/QPSSNEVuhotlT33vBMqAFD86sxQvfr4XQ3tmJ2z494iuwPYjEAjghRdegNfrxahRowAAX3/9NYLBIKZMmcK2KykpwfDhw/Hll18CANasWQOv18tIFQCMHz8eXq9Xt83w4cMZqQKAqVOnwu/34+uvv2bbTJo0CW63W7dNZWUl9u/fb7luv9+PxsZG3T+B1IJXSLqzYsXzoHgJCb1Q0gsjb17nR8DQbemHUabbgUy3g42rMc4LjB4Qmohi1Q7zuqpA6c3rMmdeVz1WcXQFOmxa/AS9nRJYr8fJzd3z6/bljqJYxWNep9tIXFcjBVWsaEnDDPzFxurCR31W5eoIGyCax8rYFahvTuAJFK928jlWZXnp+NsNZ7Ln7WqgSf0VjFhp54AnVgWZbp1PzGNSCqRNDfEMm+bLgR1pXjeSQDNl0wwRxCoOQka7KyUJOKd/flzPEw2989Px6dzz8fLNZyX8WD4tv6ugyxOrJUuWIDMzE2lpafjjH/+IFStWoKBAYchVVVVwuVzIzc3VPaaoqAhVVVVsm8LCwoj9FhYW6rYpKirS3Z+bmwuXyxV1G/o73cYMTz75JPN2eb1elJWVJXL4Au0AXwrszh4rmfPvmZW3zBDkOugA7QIZCEV2BQZljVh51OBDPjiRRzPz4JjFLaTWY6Xlctl0SkuEx4qa100+YCmxoqoFXRMlkGlOG9KcdpYJRcecaAGh0TxWsV8bWgqk5mlexaOvQVo0xYovBVpsN6pM8aZQn1VrQJt3Z6VYGeMWjKVAQHmfaF2B3UeZz2YeK0WVzbVQrHh/FaBXrKjv7ZaJffGLqYPwk/F9Yj4vr2p1ZNxChqFsGa9i1SPTbRgwHp9iBQBDe2YnrXmhKDutXeeLvkZCsUoAkydPRnl5Ob788ktcfPHFuPbaa1FdXR31MYQQXWnOrEyXjG2ocT1aGfCBBx5AQ0MD+3fw4MGoaxc4cQRPwlJgvKNg/BaKlZl5PRAKMyXF+G3XSKyiB4R2TFeg22EoBRpUFLPBwoCaKu6jxEq5CFAFhhKrHLV8QhUGSsS0gNDoHis5TFBR0xqxDV0rPW7q8zFXrOIsBVooEZqBXYlcoGqV2yRnKrIrUP/6Om08sSKaeT3KOJeuhkyWSaaQZN5jla0jVnpPD6/Y0EiNwuw03Dl5QETQqhn4Lx+pVqz4cj0lGJQo9ivINH2MEZIk6QYtx1MK7KkqeHxoZ2eBze3sQh6rLv9XkpGRgQEDBmD8+PFYsGABHA4HFixYAAAoLi5GIBBAXV2d7jHV1dVMTSouLsbRo0cj9nvs2DHdNkbVqa6uDsFgMOo2lOAZlSwebrcb2dnZun8CqUXgZDGvt4NYsXBQO1WsosctUMMnvVhnWxKraAGhieRYxT6OJZsq8dLqfeyx9DTwpUD9SBuDYmVYhz8UZu8DqlrQx9LUdapkZRo6/aIpVrzH6unlO3DeU5/io62R6jX/gU+fhydWvjg8Vrq4BYsL3/BeXtgkJU28qsGHmhZaBnRHfPmL9Fjpzes2m8SVTblSoK3LXzIYjO9V3mOV5rSz962RWGW4IslKItCVAjvQY0VJ4LVjy/Cfe87FbeedFvd+yrh5gJ44jnnWeafhgUsG445J/RNYbWogSoFJACEEfr/yDWTMmDFwOp1YsWIFu//IkSPYsmULJkyYAAA455xz0NDQgPXr17Nt1q1bh4aGBt02W7ZswZEjR9g2y5cvh9vtxpgxY9g2q1at0kUwLF++HCUlJejbt2/KjlcgcfBeom5dCgyfeCnQzSlWRvVOUaz0aomZYiWHSVQzrqZYWYy04Ycwx1CswmGCX/xrEx5dsg3VjT4dSXY5bKY5Vi5HdI8VJQ2SpB0fJVpUsTKak1sCsjrDz1qx4knYF7uPAwC+qaiP2I6qgm6Hje2f95qxUmDUHKvo5nW6dkoSyg/WaeGgJr4gq+R1/nl4Us5KgfbuUwqkHisKXrECtDE/g4r1xIpXBNsz549XqcxK58mErivQrZHiIT2zmV8yHpQmqFgVZafh9kn94U1PbakzHnRF83pcr/rs2bPj3mEi8QPNzc3YvXs3+33fvn0oLy9HXl4e8vPz8fjjj+OKK65Az549UVNTg2effRaHDh3CNddcAwDwer249dZbMWfOHOTn5yMvLw9z587FiBEjWJfgkCFDcPHFF2PWrFl4/vnnAQC33XYbLrvsMgwaNAgAMGXKFAwdOhQzZszAU089hdraWsydOxezZs1iCtP06dPxyCOPYObMmfj1r3+NXbt24YknnsCDDz4oOgK7GE6WuIUw57Eym39nBi1MMz7FinakGf0ZPLHiO9rMhzBbxxwA+tcjVvJ6TUuAffNs9AV1Xh+XXZ+8bjTqW62DhZu6tOHCIaZY6Yfz8hfF1qAcXbFSP9Cb/EHsqFKywA7WRpYDqQcr0+1gr4tpKTDKRdzlsMHjtKMtKEc1JY8s9eK7qiZsrWxkKoQxaoHuj1+HWZyGy2FDW1A2mNe7z2ddNMUKAB6+Yhi2VTbiTHVeHUW6SXktEfCELvUeq0jzentQyilWqRwanQpQT1xbdyNW33zzje73r7/+GrIsM2Kyc+dO2O12pu7Eiw0bNmDy5Mnsd0rgbrrpJjz33HP47rvv8Oqrr+L48ePIz8/HWWedhc8//xzDhg1jj/njH/8Ih8OBa6+9Fm1tbbjgggvwyiuvwG7X3hxvvvkm7r77btY9eMUVV+iys+x2Oz788EP87Gc/w8SJE+HxeDB9+nQ8/fTTbBuv14sVK1bgzjvvxNixY5Gbm4vZs2cnRDoFOgansseKGbpVFUcrnRF2XiRJyazhPVZaEKLykdDQqimzlJgoOVKRH7pUabEq84XC8Xusjqot3ICigNELv01SMpTcXECodY6V/jkoMcxM07oe6ZrocVKPVZrTBpukBB+2+kMxPFbKudpa2cie0zirj3/+dLc9gtAoxxk7eR1QDOxtQTmqF0sJVzyEbZWN7Ju8WYCnkYQ2mxArpz1S7eS7Ars6jMTKqFhdNLQIFw2NtHHwxDUjRtJ6rOftyFJge0gghU6x6mbEKp3zOhp90Z2FuF6JTz/9lP08b948ZGVl4dVXX2XdeHV1dbj55ptx7rnnJvTk559/ftTk8vfeey/mPtLS0jB//nzMnz/fcpu8vDy88cYbUffTu3dvLFmyJOo2I0aMwKpVq2KuSaBzcdJ4rEg7iJVBxeEVK3ouMlwONPtDStyCP7ZipSWDm3/gat4mq7iF+D1WVQ0asWoLyrrUdf7/QMjMY2VO8ChpyHTzipXBvM7axyVkuBxo8ofQ7A9pcQumHivltgOcad2MWLWyBgFHRDcef3+sC1pWmhNHG/1RtxvSU1HYtx1pRN+CDADmpcAIj5U/0kNHYyyCIYKg+t5xdGOPlZFYWSH9BD1WPBlLfdxCpMeqPUi0FNiVQP8ewkT5u4qVHN8RSPiv5JlnnsGTTz6pizjIzc3F7373OzzzzDNJXZyAQHtw0sQtyImXAo2Dic26AukHcFDWFCv6YUqVG55YBQz7NCLNEb/HKpZiVcUpVm0BOeK5zYiVlmNlUQrkFCtmyKZxC+px8l4RPkbBFyUV3SwssqEtyJLcKah5PYMvBfJDmNXzFlOxUolCtJDKwWpq9ZEGH3ars98KMqIpVkbzOuexYmqnDONcxu4Ao8fKWAq0Al9Sa095TV8K7LiuwHiT1s3Aj6TpbqVAnvx2FZ9VwsSqsbHRtMuuuroaTU1NSVmUgMCJgDevnzyKVXwfGAGjwmOPJCL0gygQ4j1W1uZ1Y8nNiFiKFU90YxFEfSlQ5o7Hrjsef0iOzLGyMK83c6TBYaVYeTQ1g56LWIqV1dw4OnONPT+nCjLFiiOh8SSvA1r7fO8oc9my05zs/nX7agDEVqwIIRFdgQD/3iGmAaFdHRGKVZx5S/yFuj1lMb7815HJ67HmGEZDfoaLfXnobqVAu01i5yGRuaqpRMJ/JVdddRVuvvlmvPPOOzh06BAOHTqEd955B7feeit++MMfpmKNAgIJ4WTxWPHzAeMN1oyuWCn7o99IAzLvsbKOWzB2GhpBFaugTEwVwlAC3Y3GUiCfYQVoJE4ZaaNe7GOMtGEDpN0OprjQ90WDGrfAB0by3X7+KIqV8Zs9fX5jOZB+2GfyHiudYqVXDa3w6A+G4f07J2JCjKTroWo5kCqIZtlLPAltC8rsdTPrCuTVzu7VFcj7xaS41ad014mpQLQT0Calvqzm1hnt2/9ckiThZ+cPwIVDCjHIED/RHcAiF7qIYpXwu+a5557D3Llz8ZOf/ATBoPLh63A4cOutt+Kpp55K+gIFUodwmOCr/bUYWpL4fKaujFPaY2VQFiiR8Ic0AzK9WPi5kTZRFatQ9DIQ3/LtD8kRvpREFCu+FOgPam3+LD6CK6XR0xMreZ2Z190O5hGiniGzjjwtciGGYmW46H5vQAE+/q46ojOQmdc5j5WuKzBOxSrD7YhrfMzQkmws4/K0zOMWtHVQ1c5h05MPp0kZuTspVnyoak66K25Tc7LiFjLdjpQbqXnF6kT9XHdfMPBEl9NpSHc5UNcaZLEwnY2E/0rS09Px7LPPoqamBt988w02btyI2tpaPPvss8jIyEjFGgVShM92HcOPX1iLRxdv6+ylJBUnjceK76ZrdylQ81NRxYpePIMyYf4fj9NoXtckdWPJzQiedJj5rPhZgbEIIl8K5BWr+DxWWscgD1rmykyLVKyM5wvQCFOzPxTDY6Udd2muB0NLFKXIqFi1cMTObRq3EJ/HKl5QxYrCXLHSSqp1tDPSQD7oefUFtZDW7kSs+JJcbgJ5SzqSfQIBoR3xZdVsCPOpCA/XGdgV0O5XIiMjAyNHjkzmWgQ6GHtUc+shdZbWyQLeLG3MbupOCLdDsTIqC2ZEhH4AB0JypMcqnRKrAGtdjuWxstskOO3KdmalPn5WYEzFyqIUaOwK9IfCbKCx8ViN54qZx112pgLSYzKWGgHtm3+rX47bYzWkZzYzAEcSK+0c09KNXrGKryswXlCCR2HWDecyUayM5MNl4lvpTqVAu01CusuO1oCsG8AcC/quwMRfk5GlXoztk4tJp6d+3AtfCjyRHKvujm5fCmxpacHvf/97fPzxx6iurkbYMNh17969SVucQGpBP1B9caoh3QV6xar7eqwSUXoojESEKjRBmY9b0C7uLHndpVesgjJRMpNcjgjflhnSHHYE5ZCpYsWTiGjH0RaQWVAloJjXKVHTkuS1tdvUDr9YAaFMdXLZ2foo2TNTrOiHdCzFileYhhRnMdO4sRTYwpcCTbsC48uxihc9vWnwepxoaAvC63GaeuN4j1WtOvrGaO6m55XvtOpOI20AxTzeGpATVKy4UmA7VKB0lwPv3DEh4ce1B2lCsQLAZ1l1jWtZwq/ET3/6U3z22WeYMWMGevbs2SXCuATah1q1BGDVJt9dwV/Iu7PHqj3J61YRBAFZC9ukF46gTLSMJVWxynDZ4bBJCIUJGtqCOmJFQ0fN4Hba0OQ3H8SsCwiNchy8vwow5FiZqFI0OiGWed3HqU40woKWWY05WYDBvB5FsbJxisiQntmMWB2qa4McJiyMtCUQ0u3XeB7i9VjFC0mSMLRnNtbsrTH1VwHa8YbCRCNWBvJhRqy6k2IFKOf8KPxxZ1gBWqyFwyZ1+UwnoVgpoJ9p3bYU+J///AcffvghJk6cmIr1CHQg6hmx6hosP1k4eTxW2s+Jxi2YB4Tqc6xaAiGtU1D1WEmSBK/HiZqWABragujp9UTs0wxWUQeAUXmzPg6+DAgow4lZqc5piI+QwyBETZenJNJpvga+sy8QooZsfSmQV+N483o0xQoA+uZnYHd1M0b3zkWPLDdcdhsCchhHGtrYmBA+boG+N/k1JluxApRy4Jq9NaYZVoC+9EkJrZF80HPSxpcCE5g/1xVAfU6JlALzM9341cWD4fU4E5q31xnIcNkxZWgRwkTf2XqqoavNC0yYWOXm5iIvLy8VaxHoYNBvqicfseJyrLqxx6p9XYEWSeWylkVEv93Vc0GWvFrCiJV6fyyPFaARH7P3UjBOj9VRg2Ll47sCTTr/iENPHvlON360BVWs0hx2tNmV9VHzul+OVKwosapvDTLTtpliBQCv33o26lqDKPamAVBM7HuPt6CitpURq1bO40UnBdHjMovBSAbGn5aPBav3YWBRpun9/PEeVQmtsRRIt6HlYqdd6nYVCpojlUgpEADuOL9/KpaTdEiShBduHNvZy+h00DFPXYVYJVwwf+yxx/Dggw+itTVydINA9wK9sLaddMSKLwV23zJnOM4SGg9rxUoL1KQlA9oNxg83BiKzrOg5jOWxAiIJoBwm4KdWRSOIZqVAy8BTkwgAXoXhn4eSPbfTxiWvExBCOPM6P4ZE+bmmRZuX6LZQrPIz3RhQqJGXUloOrNUaQpr55HWH9nrwawOQ1FEcFw4pxOK7voffXjbU9H6HTQIVY442UcXKWApUNqDlle40zoZiYKGSyTTY0CkpcHKBfhnqtub1Z555Bnv27EFRURH69u0Lp1P/x7hx48akLU4gtThZFavASVMKbH9XoFGxCnKKFf0QosQp3TBjjJYU6LgXjaxF91gBke8lnuTy+zIDLQVmpznQ6AtF7QoMhMKwSUbzunYc/MwwVgp02Lnk9bBO2TRTrGqa/drxWYSjGtE7T5m5RjsDCSGoblL2k5fhYl9i6OtJLwQ2Kf7niAeSJGFEqTfq/S6HDb5gmJ13YynQ6LHqTuNsKH596WDMOKcP+hWIKKCTGd2+FHjllVemYBkCHQ1CiNYVGAx3mangyYBesTpZiFV8HxiULDCzt4nHipYCqZKUblBKaEmKEpJ4SoFWipWRWEUjiLQU2K8gA98eatCNtHGbECvqf3E5KMGSIEnKcSnny6l7zjSnncux0kdDmI0GoV883A5b3H8b1MB+QCVWRxp8qG0JwG6TMKAwE8dUskaPi/dXdfTfn9uhdEkebVTWZEWsaFxEd8qwonDYbYJUnQLQSoHd1Lz+0EMPpWIdAh2MFm7ALdB1poInA7pZgSeLxyrOzs1oCg/z8hgUKmObNr2AUkKidQUm7rEynv94SoF9eWJl9FhxBM5uiFuQJGVmmC8Y1p0v3oDOJ6/z6pmZeZ0qdokoSQPVcSBbDjcAALZWNiq3F2YizWmPCAhlxKoTOrroe4OWKnMz9NUH4/y17tYRKHDqoKspVt3vK4hAUlDH+UeAk6sceLJ4rHTJ63HOPDSmpLNyTlD7JmccfWFs0zbOs4s3xwowUazCRsXK+n1GTdR98hWFwRcMRxBFt44oRnYrmnUn0jgRt8POyEFIDnPnSmKZWIDWNUl5bSJfOM4sywUA7DvegppmPyNYw3spZTk261B97tYkRy0kAiNhjF0KFJcLga4J+mWo2xIrm80Gu91u+U+ge4DvCANOriyr7uCx8odk3Pzyejz32R7LbdozhNnoh2Lp2X7tA8fYfWac7cd8WaryR89ntFb7NIs5fUbFyspjFQ5rXqR+BUo5TZdjFdHlGDYtUZqFhNIAXF6xCnGKlZEwGomnlXHdDN50JwaqZvaNFfXYWqkQq2FqGjodMUSf2xfQSoEdDWNwqBWxahPESqCLg36m7T3WjGNN/hhbpx4JlwIXLVqk+z0YDOKbb77Bq6++ikceeSRpCxNILWg4KMXJ1BnIK1ZddaTN1wfq8OmOY9ha2Yj/mWTe2q2PW4jXY2WevM5/kzPOPzMSLa3zTvVYqQQraikwAY+VmZ/veIsfoTCBTQLK1JiCtgBfCrTr1xYKI+iIJEYsjoFPew9qHitesTILBwUihytbRS1YYUyfXOyqbsaGA7WsFEgVK+MQ5tZOJFb8cdkkrRuUggbCtrCuQFEKFOiaGNs3D2lOG/Yeb8HFf1qFP1w9EhcMKeq09SRMrH7wgx9E3Hb11Vdj2LBhePvtt3HrrbcmZWECqUV968lcCtQISVdVrCrrlbIX9fGYIdyOrkCjCkMVHJ44RyhWEURCf/E3K7kZkWbZFagcg00Cy4QKyoQZzimONijfMgsy3WyIrT8U2RWoEScZabJKHrl90eOmZIoQwhQrt9Ommdd5xcoRXbGyCge1wpl9crHwq4NYse0ojjT4IEnKLEH+ubqSxwqAaRimy1AKdAjFSqCLoleOB/++83u4Z+E3+K6qCbe+ugGL7/pe1M7YVCJpfynjxo3DypUrk7U7gRSjtuXkVKzkMNGRqWhdgYu+OYR5y3eAkI4nX4fVwdeBUNiS1MY7CoZHpGKl/xN32KQIBcbosXLazYmVK2rcgrlixdLeOZXMTH073qIRK6retAWsc6yCMmHkycxjRZUuJaFdu4+Z12ViOa7G7bDpSEZ7FCsA2HusBYDS5UjJGhvJI0d2BXY0eI9VtEHN1Lwe7fUXEOhsDCrOwr/vmoiffq8ffnRmaaeRKqAdipUZ2traMH/+fJSWliZjdwIdgLoIj9XJQayMpadoQ5gfW7IdtS0B/PDMUvTt4JbsynotQLK+NYhib+SFtX3J63rfkVGNcdiliNusPFY8OeH3aQY6DNaqK9DjsqNJ7T4zI4lUQc3LcDGzeLQcK0ArUZmWAg15UYDqseLN6xaKlSQpMwCb1IHQiSpWpxVkIDfdyf7GhpVoH/B8KZMQkvQ5gYlAR6wyIokVfb2p/1IoVgJdHW6HHf972VCd2t8ZaNdIG94fQQhBU1MT0tPT8cYbbyR1cQKpg7ErMF5zdFeHkVhFi1ugbeb0/45EZYNGrBratJEoPNpXClQu1EaFh8Jps0UEPUZ4rAzDjOMbaUOzr8w9VrQMxytFPGpbFBKSk+5kxCpMNPLkNiGK9PSYm9dVc7hKsCRJORd021CYREQ58Mh0OxixSlSxkiQJY/rkYuX2agDA8BIt9Ztff1AmnGKVlO+4CUGvWEWOfDFTOwUEugNsnfxeTfiv+U9/+pPud5vNhh49emDcuHHIzc1N1roEUoy6k9S8bjSrW5UC+XEm8RrDkwlaCgQi/W4U7RnCbCRBRsO502GDw27TeZ6MuVZ8uQ0AgrTTMKp5XVU3QuYeK6fNBrfDjqAcQiAUxn93VGPp5iN4+IphSHc5DIqV9jw0Hd6KKCrHGlm2o8TKz6IWlJBPNtJGDjNVy6hYAXoDe6KKFaD4rBix6qUpVvqxOzKnWHW8GuSKsxRo9buAgIA5EiZWN910UyrWIdDBMBKrk7cUaE6sdOGoHazWEUJwuF6vWJkh3J5SoDGp3EJ1oONMgMguQeM8u4Q8VkGjYkjLSGoJ0q8cy/xPduPrA3WYdHohpo3syd6POekuuDjiZyRWdBQLX07kCZ8xbkELB1XWxxQrmUQMrObBE6tEFSsAGNNb+5I5jFesuNcjEAp3ssdKe06zUqDx9RaKlYBAfGiX/lxfX48FCxZg+/btkCQJQ4cOxS233AKvt/PMYgKJoa5Fu2DxH/DdHUb/jlVAqC5AsoMVq9qWgO75rToDZYN5PZ6xQ8YOvohSIHc7JVZGf4+xcy0hj5VRsVKPwWGz6fxFdA5ftToAmL4fc9OdkCQJHqcdLQGZESte6XHb9cRK77HSEzw2zkYlEdSUHgqHI0goj0xOxWuPYjW6dy7OHViAnt405HBqkM2mqGa0FKkpVh1fCuTPW048pUDhsRIQiAsJ/6Vs2LAB/fv3xx//+EfU1tbi+PHjmDdvHvr37y8GMHcj0NJLiertOVkCQuP1WPEX5o4+dl6tAoBGC2JlLGPGk75uDAilF3IKY3AoYKJYsRyr+OMWYilWTruki0qgxu7jKsGq40qBgKYwNRoUK+PPxnVZeawoOTKLWzAjVvw5aY9i5XLY8Pqt4/CHq0dF3MfHWXSqYsURxjyTUqDx9Y6WvC8gIKAh4b+U++67D1dccQX279+P9957D4sWLcK+fftw2WWX4d57703BEgVSARoQ2tPrAXAylQLj81jpAiQ7WLGqNBAry1KgYe3xlAPNylv8BdJhomRFeKwicqziGcIcw2Nl1xSrtqCMRp9yzDXNyvuQxn9QdYc3sBvXyxMhmwRDNIKxFKiPVGDJ65yJPmYpsB2KVTTw55cqVsYGgo6AXrGK7bESswIFBOJDwvrzhg0b8OKLL8Lh0B7qcDjwy1/+EmPHjk3q4gRSg7aAzC44PXOoYnWyEKs4PVadqlj5dL8bxwtRyIZ8LX8wDEQ2DzIQYt7p5nLYmDLCe6woLBUrY46VI3GPVZDzWFGCcqzJz7KlqGJFzwHtTrMqTxp/NpK9CPN6SK9YUXIQ5OMWTAhjBkc226NYRQPfddllFKsocQsUlJQKCAhER8J/KdnZ2aioqIi4/eDBg8jKykrKogRSC1p2cdgkFGS6AZw8xIoSCypi0Av7lsMNuHDeZ1i+tQqAYZZcBx877QikF9h4FatYpUA5TBhhsSIfZnlQVnELNBNLKy8mrlhRjxuvWFU1asTyWHMAhBD2nsxlipV1R5ruZyOxYjlWtBRI4x4M5nUubsGMOJ1oV2A08DlhVLFK6xTFijOvm3isIv15QrESEIgHCX9i/PjHP8att96Kt99+GwcPHsShQ4ewcOFC/PSnP8X111+fijUKJBnsIsaFMZ40HiuVBNDQS6pYfbbzGHZXN+M/W1RiFeRLgR177LQUOLhY+SJiaV6PUKyiE0C+DGrmOwI0xYq/35JYGboC25djRc3rWuJ7daM2JPV4k183bJl2pxkVHLeVYmWMBKAjbSy6Aunxy2ESNW4h8wQ9VtHAK4Kt6hrSO1mxMisFOg0KpRjCLCAQHxIuBT799NOQJAk33ngjQiElQM/pdOKOO+7A73//+6QvUCD54Duw6Lfxk6UrkF7I05x2NPtDCIUJCCERpSFe/eloxYqGgw7tmY1NhxosFStjGTMWAdR1yukUK968HqlYGYcOG5PX4/JYOfWEhoI2DzjsNrjUw6lq0BSrmhY/81c57RIbr5NmIBq8usITHaOKQskCPRdsTqCDlgK1Y2gJpC7HKhpcdOxOKAxfF0leN+sKjIjqEIqVgEBcSIhYybKMNWvW4KGHHsKTTz6JPXv2gBCCAQMGID09PVVrFEgy+LKLhylWJwuxooqVdqEKE+5CS9vwO1GxoqVAOpi3wTIg1FAKjEWsOLLIdwKalQVd0RQry1mBURQrh7nySUuBLrsNdEVHmzRi5QuG2fnITXexOIkIYmVR/ovpsVLXo+VYaeeFzcAzjVtIoWJl0hVoPN6OAF1HVprDlDQbbxOKlYBAfEiIWNntdkydOhXbt29HXl4eRowYkap1CaQQPLFKO8mIFSUXfCmJNyrT4wzIneOx8gVl1KgKzVA1ODJpihVHgPi8K31XYKR53XJWoIFYRVMsqKrjC8q6vC26D4ddgiQp2xxt0Jv3d1U3A9CnfxtLgXF7rIxdgdS8ThUrzoDd4terWTxSqVi5WbkyjNZO7AqkhNEsdR0wi7UQipWAQDxI+BNjxIgR2Lt3byrWItBBYKVAbnzISeOxUkkAbwaWw4QRKaOSAXTssVN/VYbLjt55isrb0BY0HRoaNnqsYsRCBC3iA6IpVm6HTRdXwN8XTMC8npehqJ+hMMH2I03s9hAXEMo8Vk1+3WN3HVW2z83QylHxmtcjFStjjpU2q1BZR3yKVXoHdAUGZJmR+s7oCqTrMDOuA2ap/UKxEhCIBwn/pTz++OOYO3culixZgiNHjqCxsVH3T6DrQ1OsnCddKZB6ejzchZkPg6THmYocq0AojPKD9ZYRD4AWDtor1wOvR7mghQnQHIgcBN3eUqBRWXDqSmd6xcror+Lvo89HyVGsUuCE/vkAgE93VLPb+YBQul9jtlhcipWFGd9osI5MXqeKlXK7zSaxjlGqWFkNYaZIumJlFhDaCYrV2X3zMKgoCz8aU2p6f8ScSaFYCQjEhYTN6xdffDEA4IorrtCVG6j8L8snxwX6ZAZNs/Z6nOxCdLKY1ym54D0rcpgfuKyOaeGJVRIUq82HGvCLd77Fd1VN+N9pQ/DTc08z3Y4qViU5HqQ57XA7bPCHwmhoDSI7Ta8cGEPj4zWvGxUYfVeg3rxuVoLizeuEEK0rMEqOFQBMHlyIj7+rxn93VOPOyQMAcF2BdslS8aDEiu9MM8YP8Bf1+BQrlUAHI98PDnUkDlWsUpG8Hg10/c1+mZHnziBWxd40fHTfeZb3RyPoAgIC1kiYWH366aepWIdAB4LOb3M5bOyb/MmiWAVZNpE2yDckhxnh0hSr5HmsXl97AA9/sJVdJI0ja3gcV5PGC7OU/LCcdCeONvrR0BZEmWHbyOT1WHEL5iU7M7M3/T8asVKeMxxXVyAAnD+oBwDg6wN1aGgNwpvuNM2xoshyO9DkD+GYWhrM40uBHJlxOfSeMXdCpUB9QCgAOG0SAojeFZhKxYo+38HaVuV3uy0ipLUrwGkgwmJWoIBAfEj4r3nSpEmpWIdAB0JWL3Z2m8S+KZ80HivOD+Sw2RCQw4ZSoF65Mv7cHixcXwE5TJCV5kCTL2Q5nxCIVJW8Ho1YGWEcIB1LWbNSrKKVAo3GdUBPxKi52rgfM5TmpuP0okzsPNqMVbuO4fJRJTpSZlSGBhRl4puKeva7rhTIET53FKIYaV7XdwVSYsWrTgpBkNHqD0XcR5HS5HV1zd9U1AEABhVnRfjcugJsNglOu8S9hl1vjQICXRHiK8gpCKqs2G2SrpvrZAC9CLjsNtbFJocjc6x4MnWix04JzchSL4BIQsSD3kfLYtRnZTbWxribWMnr/LHz4IkW6wq0U4+ViWLFZz35Q6a3W2HyoEIAms+KdRTapAjCN7AwU/e7rhQYZeiymyvrWeVYGV9nnWKlPqbZb21e74jk9W1HFE/qUDV2oytC11EqzOsCAnFB/KWcgmDESpJOOvN6gCuHURWAj1vwmyhWxjEsiSJoiHgwDoLmETJ8+/d6FDJhpljR5HWPRaq5EbTzMbpipXUDAuaKlc0mse65Fs5UH49icb5KrD7bcQzhMNEFhBqVn4GF+hFYfClQp1hZpKvzx2PcVhtpoypWvMdKJQhUjTMjjG6HDVlpDtgkRHjfThT09aHvExq70RVhpnYKCAhER9cr7AukHHrFSjOv8/lDnYWV244iN8OJMX3y2vV43mjNjy+hhCsgh3VmduDEzev0AklJSiiKskS3tRsUK1NiFab7tatjX6ITwEDI3AtlZvaO5rGijwkFZKZYSRLiKleN7ZuLLLcDNS0BbDvSqHmsTBSrAdEUK6feY2V5PBFGfTXVnHnqzMzrynGEOK+hEZIk4fmfjEF9W5CN2UkWjM83rNsQK/E9XEAgHoi/lFMQIZ5YqReiMImutHQEalsCuO31DfjpqxtASPvWEtQpVlp7P0+kAqGw3rx+gopVwJD2HowSt6CZuZWLOx0lUt8Wmb5Oc6yoetPeuAWXbqSN8jMlC3QItxF855ryOFtcpNtpt6FfjwwAQHWTTyN7DpvBdC6hd75+WkNuO4iVZUAoVawMI20AfZaV8T4eEwYU4NIRPU3vOxEYPWODu3Ap0G1SRhYQEIgOoVidgqAXbLtNQppL++D0hWTTb+8dhfrWAMIEqGsNotEXYmpOIuB9Rk7OYxUweKr8SVSsqEJFCVAwCgHShhLrFatGM/O6rClWQGyTvRYQap1aTp/32rGlcNklXDzcnDhQdYIqVvH4qyjoelv8Mucp0ytWuemuCFKXZ5FjFS0+wkgi6WvQFpQRksOWcQs8Ovo9zz9f3/x0XQdiV4PZnEkBAYHoSPgv5ejRo5gxYwZKSkrgcDhgt9t1/wS6PkKyRqyU8SfK7b5A5/qseOJwrMkXZUtr8CnhOo8VP3Q5JEcQrRNB0ECAjAGYPEKG8TBMsTIzrzPFSrnwxj/SJnZAaFaaEzPO6YseWRaKlZ0qViHd4+IBjQ5o8Yc4T5neY5Wb7kJ2moM9j01SZtZR8B6r6GZ8/X05HBlvaAtGjLQBIhWrjiZW/HkYVuLt0OdOFMJjJSCQOBL+qjRz5kxUVFTgt7/9LXr27NnpnhyBxEEv2A6bBElSyoFtQbnTIxd44lDd6MeAwizUNPuxbGsVrhhVgqw4TMR8KVDnsTIoVHrz+okdt1YKdOjWYAZKujTzemyPlYd1usXqCox/pE0sUFWolRGr+MkH7ahrCci6OYP8OnLSnZAkCQWZLlQ2+JCb7oKNIzzGHCvd8USJW3DYbSz2oq41yBQrfSehtQLWEeCPpysb1wHRFSgg0B4kTKxWr16Nzz//HGeccUYKliPQEaAXd5tKij2qOfpEvUYnCj+nHNF5cn/7dA9e+mIfWvwh3HZe/5j70JnX7eYeK19I1j1XIBRut3GfTyan5aZoOVZa/EDsuAXaFZjOFKtY5nXzgFD9EOb4Lo704k9DNBMjVsp5aPWHNCJp03usqJ8qP9ONygYfU+4oPFyJOlpp00xFyUl3oskXQn1rQBtp4+TPgdFj1bFKu45YdWF/FdA+Ui4gcKoj4b+UsrKydhuLBboGaKI3vcDQMklbB5UC7393E6b95XNdRhJgUKzUUuDe48q4k8r6+EqDuhwrC8XKFwxHZEK1NyRUDhPQPwetFGi9LzkBxSocTsxjpZUC4/ckWUEzr1tnPVmBEsHmQEhHdHUeKzVaoSBTIVi8cR0wmNctQkAB84s93Vdda1DrCuQfY1BeOtxjxa25K3cEAsZoC1GdEBCIBwl/ovzpT3/C/fffj/3796dgOQIdAaNilcbS1zuGWC3ZdARbKxvx3x3HdLcbS4GANluPDo6OBascK7/MlwLlCMN6e4+d76RkXYFRFSst1wmIbl7XFKv4cqyCXAcej/a0zNMLakt7PFZqKbDVL+sUOreuFKjvSjRGGvDEyliqizbSht93XWuAG2kTGbdAkYgxPxmgRK4g02Xpcesq4OdDipE2AgLxIa5SYG5urq5M0tLSgv79+yM9PR1Op17Cr62tTe4KBZIOqprQchT9Nh9rEPNb6ysgAbju7N4n9NxUBflsZzWmjdS60vhSV3WTH4QQHK5TiFVtS3zESj/SRs0rko2lwOQpVkFOnaKdbPElr1PzukICmvwhhOSw7uIly/qA0FjJ6ywgNJrZO87RKZSwNLfHY0W7AgMhXSCqvitQVaxUYpFnUKyidQXq4hZM1Ca67+PNfvYlwh3F8N7RitVpPTIgScD3BhR0eY+q3mPVtdcqINBVEBex+tOf/pTiZQh0JCixohURbayN9YW7yRfEbxZtBgBcNqqk3S3izVz577Odx3TeJl6RqW7yodEXYh4fMw+SGYJclhO9gBq9Yz6TsM12K1YcIdMCQuNJXlfWls11wjX6QsjjlBvZ2BUYY42sDBpFsYqXRDCPlfp6JaJWMPO6P8QyvRTFSiNLlFBeeUYvbDpUj2vGlur2Ea0UGMtjRUuBRxu08jG/P2cndwUOK/Hii1993zJDrCvB1Y73joDAqY64ro433XRTqtch0IGQiV6x8jAPj/WFu7rJD5oiUN3oQ2aPTMtto6HJpxGko41+7DjahMHF2erz83ELflYGBBJQrDhyQUuBrQbvmD8UNikFtlOxYrlUErvIR1OWgoa4Bb6LrbbFrydW6m7i9liFNFLJwyzHKhboY7SxL4mUAu3ssXy8hJl5fVBxFt786fiIfdAokIAcjpFjZVYKVBSrqkaf6WP4BHmb1DlKTEmOp8Ofsz1wtkPtFBA41ZHwV5ClS5fio48+irh9+fLl+M9//pPQvlatWoXLL78cJSUlkCQJ77//PrsvGAziV7/6FUaMGIGMjAyUlJTgxhtvRGVlpW4f559/PiRJ0v277rrrdNvU1dVhxowZ8Hq98Hq9mDFjBurr63XbVFRU4PLLL0dGRgYKCgpw9913IxDQX8w3b96MSZMmwePxoFevXnj00Ue7pZFfG2mj/M5KgVHM68fVLj1AIT3tRZNPb1jnfVYBQymQlgEBJTw0HgRM4hZaDSZ5X1A2KQW212PFPR/tQoymWBnKsABQ4lUusocNBv2wYVZgvMnrLkOeHK86xJuebTSvJ1IKTOdyrIKcod5tUgqMBqqkJhofQUlblapYuRw2XZSDUcHr6uW4zkS0uYwCAgLmSPgv5f7774csR16EwuEw7r///oT21dLSglGjRuGvf/1rxH2tra3YuHEjfvvb32Ljxo147733sHPnTlxxxRUR286aNQtHjhxh/55//nnd/dOnT0d5eTmWLVuGZcuWoby8HDNmzGD3y7KMadOmoaWlBatXr8bChQvx7rvvYs6cOWybxsZGXHTRRSgpKcFXX32F+fPn4+mnn8a8efMSOuauAI1YqR6rOMzrx5r9pj8DSujlE0u345PvjsZ8biOx+owjVrwi0+QLsY5AQGn7j4f8mBGdVsNxmZvXld/jIcr8NvwYGaoURZsVGJIjVaVeuSqx4ogkwM0KdMdWFAHOX+YwKlba7/EatenYlZZ2EKtMVgqUdUOYXSbm9Wig5btEcqyUfSuk7YhKrIzmd55cdrRxvbtBJK8LCCSOhI0yu3btwtChQyNuHzx4MHbv3p3Qvi655BJccsklpvd5vV6sWLFCd9v8+fNx9tlno6KiAr17awbq9PR0FBcXm+5n+/btWLZsGdauXYtx48YBAF588UWcc8452LFjBwYNGoTly5dj27ZtOHjwIEpKSgAAzzzzDGbOnInHH38c2dnZePPNN+Hz+fDKK6/A7XZj+PDh2LlzJ+bNm4fZs2d3q2+9jFjRrkBVsYoWlMkrVrRjj6L8YD1eWLUXi745jPW/Lox6LmgpMC/DhdqWADYcqEWzP4RMtyOi1FV+sF73e31rEEXZ0TOHdB4rVaUwKnF+zrzusEkIhQn8IRnfVTVixoL1uOeCgfjJ+D6m+99zrBk/fPZL3Pq9frj7goG6UE6qQkWbFWjsCgSAXmpZiC99AsmLW+AVrEQVqxZ/4jlW6Zx5nb4VlFIgn7weW7GiJeqoHiuHtcfquPoFgPdXAXq10JiRJaCHPuW++3zGCQh0JhL+CuL1erF3796I23fv3o2MjIykLMoKDQ0NkCQJOTk5utvffPNNFBQUYNiwYZg7dy6amprYfWvWrIHX62WkCgDGjx8Pr9eLL7/8km0zfPhwRqoAYOrUqfD7/fj666/ZNpMmTYLb7dZtU1lZ2e2iJzTFSiVWztg5VtEUK+rDOdbkx97jLVGfmypWQ3pmoU9+OoIywZo9NQAiFZnyinrd7/H4rGjkgMtu7bHyBbWAUBp34AuG8eXuGhxr8uO/O6ot97/k2yNoaAti1U5FaePN6HEpVnQIM1eaon6bwwZiFWLJ68r3n1ilQKvkdV51iNdjZewKdJkQGCvw5nV2fmw2eFx2XH92Ga4eU6rzklmBlkDdTv2a482xovw2zWl9Pjo6db27QRfVIZLXBQTiQsKK1RVXXIF7770XixYtQv/+ShL27t27MWfOHNMyXbLg8/lw//33Y/r06cjO1kL1brjhBvTr1w/FxcXYsmULHnjgAXz77bdM7aqqqkJhYWHE/goLC1FVVcW2KSoq0t2fm5sLl8ul26Zv3766behjqqqq0K9fP9N1+/1++P0aEWlsbEzwyJMPI7GiF7BoyevHmzRSY/RY8SNc1u2tRf8oxnaqWGW5nTijzI0DNa3Yd7wZQFFEea6yQe85iifLSguk5DxWAaPHShtpk+1xoqZFyTuiIZ3RcqjW7lVIIFWHAol6rMwUK6tSIOsKTMy8Hk3hiZcgaeb1ExtpQ8vNVFl68ocj494PHUMTvSvQuhTI9mNQpRyCWMUNnccqAXItIHAqI2Fi9dRTT+Hiiy/G4MGDUVqqtEgfOnQI5557Lp5++umkLxBQjOzXXXcdwuEwnn32Wd19s2bNYj8PHz4cAwcOxNixY7Fx40aceeaZAGBamjKOMGnPNtRrE6309eSTT+KRRx6JdngdDnrB1hQrlVjFq1hFI1b7ajB9nHXOVaOqWGWlOdgFjvqbrIhDmtMGXzCMupbYkQtmRMeoWLUGZKYG0bgDfyjMiJVVDpUvKOPrijrledS1Ul+Tgys9BqPkWNH7+It7LwvFKrIUGGOkjSHKgaI9894oeQla7DMaaI5VIBRmvr32zJmjMxKjBYSaeaQiw0YNHitdKVAQq2gQswIFBBJHwsSKltBWrFiBb7/9Fh6PByNHjsR5552XivUhGAzi2muvxb59+/DJJ5/o1CoznHnmmXA6ndi1axfOPPNMFBcX4+jRSFP1sWPHmOJUXFyMdevW6e6vq6tDMBjUbUPVK4rqaqVkZFS7eDzwwAOYPXs2+72xsRFlZWVRjyHVoMGTxlJgtMiB4xyxqjYQqwCn0KzbWxt17l4TI1ZOEBD1eZWLrxVxGFycjfKD9YkpVhzRoT4hikYu8iGblQJjK1blB+sZoWLEihuh40xAseLLKpRYVTX6dCGhsklXYLRzS7sqjcnr7nb4ZIyEpT1dgQDfVZi42pHpdkbsz7g2s3VluOxw2iX22qQZFCt+LYJYRUeszDABAYFItOtTRZIkTJkyBb/4xS9w1113pZxU7dq1CytXrkR+fn7Mx2zduhXBYBA9eyqJ3ueccw4aGhqwfv16ts26devQ0NCACRMmsG22bNmCI0eOsG2WL18Ot9uNMWPGsG1WrVqli2BYvnw5SkpKIkqEPNxuN7Kzs3X/OhtajpVBsYqiiByLErfAh2RWNfpwoKbVcj+sFJjmYIShjRErZT/5nOLgstswsFApLdbF47GSzTxW+lIgPz7GjFhZeaRoGZBfK9+FyDxWYWLZXRg0kFoAKMxyw2mXIIcJjqrnlpDIGYRhovmuYh07D128QIJDmLXHxX9RdTlsEc/TnnEod5zfHzeM640Lh+i/uNi4zDCzi70kSbquwwjzOrcWUQqMDvresdukbtWgIyDQmWhXfHZLSws+++wzVFRURGQ93X333XHvp7m5WddJuG/fPpSXlyMvLw8lJSW4+uqrsXHjRixZsgSyLDPFKC8vDy6XC3v27MGbb76JSy+9FAUFBdi2bRvmzJmD0aNHY+LEiQCAIUOG4OKLL8asWbNYDMNtt92Gyy67DIMGDQIATJkyBUOHDsWMGTPw1FNPoba2FnPnzsWsWbMYEZo+fToeeeQRzJw5E7/+9a+xa9cuPPHEE3jwwQe73QcOmxVoIFZW5nVCCGqatde5tsUPOUx0s/h4rNtXg74F5o0MTVwpkJbomGKlKmaleemoUUlUz5w05GVqQ3VjgR9pQy+6xlIgVazsNomVrfyhMMvKsiIv1GQPaCVHs6R35XZi6mdi5nWOENhsEnp6PaiobcXhujb0yvEwHxygV2z8obClesQ8VhFxC7xiFWfcQpT09niQ7rYj0Kq9L4xp5/FgTJ9cjOmTa3qfy25DUJYj1DmK3HQn+wIQEbdgE4pVvIhGYAUEBMyRMLH65ptvcOmll6K1tRUtLS3Iy8vD8ePHkZ6ejsLCwoSI1YYNGzB58mT2Oy2Z3XTTTXj44YfxwQcfAADOOOMM3eM+/fRTnH/++XC5XPj444/x5z//Gc3NzSgrK8O0adPw0EMPwc61mL/55pu4++67MWXKFACKAZ/PzrLb7fjwww/xs5/9DBMnToTH48H06dN1njEa/3DnnXdi7NixyM3NxezZs3Vlvu6CcFivWGnmdXOlprEtxIiEJCnKSU2LH4VZaQAi4wXW7a3Fj88y91lRxSo7zckUGc1jpRCgslwPvlWjFkq8HjZHLp6Q0ABnXrdbxC00tqmdbnYbI5V+i1JgRU0r9h5vxrh++fiGi38wlgJ5IgcoBMplIgibmdcBpRxYUdvKIhd4csfPzfMHZctxQjRzyqjQ6IcwJzYrkP2eIAHJcDl0Y4iSnYHkctjQEpAtFbioipUtcQXvVAUlnqIjUEAgfiRMrO677z5cfvnl+L//+z/k5ORg7dq1cDqd+MlPfoJ77rknoX2df/75UQMZY4U1lpWV4bPPPov5PHl5eXjjjTeibtO7d28sWbIk6jYjRozAqlWrYj5fVwdTrCRDKdAiIPRYs9Kdl53mgNtpx7EmP6obOWLFlfBqWgJYu7fG0gvEK1Z+lQRR4kNJUWluOtu+JMfD2udrE/ZY0YBQQylQJXdup5YG7guF0aASLr4UeNdbG7HpUAP65qcjEAqz3KuAoRTI51gpt1uVAvVDmPnjBDQDe5h77zvU8NGgTCzH5YTkMA7WKSXY3nnpuvtiddGZIdq8wXhAx9pQJDsD6bzTe2DD/jr0s1BG+ZwsY1yDQ3is4gYlniLDSkAgfiT8qVJeXo45c+bAbrfDbrfD7/ejrKwMf/jDH/DrX/86FWsUSCLCnBLiiDCvWxArNWqhIMuNHurgWL5LkJKFs/vlwSYpMQnGrCsK3ryepl7U2gylwLI8bY5ar1wP6/KKVQqUw4RlF+k8VgbzOlWm3A6bjlQ2tEWWAmk5ab/qG6OlKWPcAj8rELD2adF9G4kKjVw4pEYu8KVAu00L1zRGUlBU1vvU8qONjcih0I20ibMkFxkymtiF1Wg4T7Zi9efrRuPzX05m0Q5G5EZRrPQ5ViIgNBro6yZS1wUE4kfCfy1Op5MpEUVFRaioqACglMrozwJdFzxpsBlLgZaKlUIuemS60SNLJVZNkcTK63GyEoxVmKfOvG4YpUMN4T29aYwA9MpJY+pDLPM67/VS4hb0HitKtLTQS02xqm8NMpWJ3w+9bWyfXLgcNlw7VunolMMEcpjozOuSJLHnMPNpEUIYYTIqAKWG9HU+sUEhVjbdOTJiX40SzNo3P103Fw9QCGSJNw15GS5kpcVOPAdOXLEylitTMcDXeJw8+FJgpMdKxC3EC1oCFsRKQCB+JFwKHD16NDZs2IDTTz8dkydPxoMPPojjx4/j9ddfx4gRI1KxRoEkQldiUi9MbkN3nhF0nE1BlpuRMJ5Y8flJOelO1LYEdP4aHlSxyuS6Ao1xC2lOO3pkuXGkwYeSHA+7SMaKWwgYiRX1WKn7z05zoK41yLxdboedqRlHG7UwUj4ugZrNf/+jkehXkIG2oIw5//pWeb5QmJvPp5ZMbJKOcPHgyZbRs2IsBcrc62SXeGJl/hrtP06JVWRpzGaTsPSecxEKk7iJxIkSK9rJSGFPAbGKBr4UGE2xEsQqOqhSKUqBAgLxI+FPlSeeeIJFGTz22GPIz8/HHXfcgerqarzwwgtJX6BAchEylJgAXrEyV0N4xaowimLltNuQo8YXmBnNw2GC5oDmsUqziFtwO+z4n0n9ceGQQpzVN4+NP2nyhUwJC1tHiCdWEkv9pqDRChRuh42RSj6biw8I1UbWKGoUXyILhMLsfLoMJROzLCv+NuOFik9f55UtQCFG6aoCRNU2I/apxMrKc5ST7kJBptv0PjNERjYkdmHlS3QuVc3rSOhKgRHJ68K8Hi9c3BcGAQGB+JCwYjV27Fj2c48ePbB06dKkLkggtTB6d4DYHiuqWPXIcjMlQkesmGqj5QeZKVbNgRBTi7LTnJy/Se0KDFJiZcNNE/ripgl9lf3abZAkgBBlv7QcaUSQI0GSJEVcDLLSDEGTXCmQV6x44znzUDHipO3TL8tc0rv+m71ZejufyG4kVj29SiNAW1BGfWswYuwQLa01+6ITK6uYi0SRTPN6Z6gdOdHM6zbeYyWIVTRkq6XjeEvIAgIC7QwIDYVCWLlyJZ5//nk28LiyshLNzc1JXZxA8qEjVqqKYPQ6GRHLY8UM2TYbu6DVt0USK1oGdNqV0lZkQCgtBerflnabxIYlRysH8soZEHlBz06LVKwoueOzrnjjOf2Z5jBJksRIh1IK1Mcn0OcOhKIrVsZSYJrTzhSlw/Vt2tgh9TWipLDJgljtr7EuBbYHJ0ysOPN6Z6gd/FibNKPHSswKjBtn9s7FA5cMxoOXD+3spQgIdBskrFgdOHAAF198MSoqKuD3+3HRRRchKysLf/jDH+Dz+fDcc8+lYp0CSQIlVpIUaV4Pyoo3yHgRpeNsCrJc7IJZ3aQpPAFdKdDaD6UZ15UGCKaUBSJLgUbkprtQ3xqMamAPGIlVDMXK7bCbXlgpUeS7DPlz4rbbEAiFFWJF4xYosbJZK1aUpNkkc+N1r1wPjjf7caiujRFJyr/o2s1KgUE5zLoJrUqBiSKiFJggAeG7AjvD+BzNYyXM6/HDZpNw+6T+nb0MAYFuhYQ/Ve655x6MHTsWdXV18Hi0tu6rrroKH3/8cVIXJ5B8sBIT53nhL4LGlHJAU6cKMt0ozE7T3QboS4H0gtZgVgrkMqwATikL6YmV2cWOdQYmoFhFeKwMipWLU6x4UGLF+7nMso8CcliXm6VsZ1MfG6lYBcN6dcuI4mwtyoJ1D6rHkKXOzWvyRZ7Xg7WtkMMEHqcdRdnx+6ii4URG2gBdoRQYX9yCIFYCAgLJRsKK1erVq/HFF1/A5dJPkO/Tpw8OHz6ctIUJpAasxGQY60GDL1sDIaaWAIrhnI6z6ZHlZl6LloCMFn8IGW6HTrVxu7X4AiOajMSKU8p8QZmRCTMVKTc9dpYVLctREmA0XJuZ141lIkAhn4QQfRefPVLlCITCkSoZ9ViZdQUayopGuFSlLhgKs9eJbppJS4EmihUtA/bJT0+aSfzEPVadq1jlcK911LgFYV4XEBBIMhL+VAmHw5DlSFXj0KFDyMrKSsqiBFIH2WQIMKC1xxsVq/q2ICMY+RluZLjsjBDREiE/1sUbJRqBJp5T9YVXEho5JcasFBgrHwvQj7MxO0ZT87qJYgUoxxQyxDfwjwPUrkDu2AHNO2WWYxW0GGejPYc2ezFsMK+zUqCJx2rfcSW8NFllQCD6IOd4wMctdAaxctht7JxFDmHmPFYWr7+AgIBAe5HwJ95FF12EP/3pT+x3SZLQ3NyMhx56CJdeemky1yaQApgpVoBWDjTO1aPkKSfdCZdDaZunBnYaUcCrNqwUGMW8Ti94bofS7QfoS4dm5Zm8DOsYB4oI83oEsTIqVvYIozxFKBxmREiSDAqfXSNW/EgbQLtom+dYRQ5g5uFiZUQtxsHYFWhmXt+f5I5AILkBoZ3Vqp+vGtg9LmMpUChWAgICqUPCpcA//vGPmDx5MoYOHQqfz4fp06dj165dKCgowFtvvZWKNQokEbJ6cbdSrFoMpSbeX0WRl+FCRW0rU49CnM8ounldG2cDKKQ8zWFXIgZUIkbzoozQFCvrUmCFOnaGDm02eqzcDhtcDhub86eUAq0VK0bUDPuhpMMvh3UjbQBNjYqWY+WwGGirkTItx4rOc6T+MDPzOsuwSlJHIGAy0sbR/pE2VgpdqnHPhQOxaudxnNk7V3e7wyY8VgICAqlDwsSqpKQE5eXlWLhwIb7++muEw2HceuutuOGGG3RmdoGuCSqkGFWEdNVs3GqIXNhyuAEA0Icb7OvmSmGAvhTI4hZMPVbaOBsKj0shVlSxsprdRkNCoylW6/bVAgDG9s1V16M/RpfqqeKJlTHjiCIka2U+o/laF7cQUQqMkmPFMrHMSYqTU6zCBmWReaxMzOvJzrACkqtYJRoumixcNboUV40ujbjdYVLWFRAQEEgWEiZWAODxeHDzzTfj5ptvTvZ6BFIMesG3GUzO6U7lrWAcWLxq1zEAwPcGFrDbqC+FEhRd3IJKrPyhMHxBWedvoYpVNkesqHm8nhuMbAY6/LmittXy2NbtqwEAjDstH0CkKseS1tV1RFOsQmHCAj2NpEJXCjSOtOFUJ7N9mu3PuN9QmFgGhBpLgf6QjMqG5EYtAEkYaePuXI9VNDhFjpWAgEAKIT5VTjGELRQrDzOvaxfu1kAIX+2rAwCcd3oPdjslAH6mWGmlwEy3g+3bWA7kc6wo0tTnpUqU1YVudO8cAMCu6mbUNPsj7j9c34ZDdW2w2ySM6ZNreowuu03nqXI77ZaKVdAkSoHtR6dY0Y5I2omoqU4AsGF/LVbvOq67zcpzRElZIBSpWFkFhCojcJRSbkGmvlP3ROCwSeC5d3cLCI0GY0esgICAQDIhPlVOMTDFynCxo7lD/CDmtXtrEJDDKM314DRODdFKgcq2Qa4bT5Iky3Kg0bwOaJELjapiZXWhy890Y1CR0nW6Xi358Vi3V1GrhpdkM3XH6GVyGRQqlz2KYiUTS08UO345zLKpWCmQ81iFwwQ3v/wVbnnlK7T4Q2x/VgOJeVJGS7bG5HWjx+qgGgxalpu8qAVA8b+diMk7o0srVhy5FsRKQEAgyRCfKqcYqBISoVippcAWrhS4aqeitJx3eg/dRZsnFgCfH6Xc7vXEIlaRqdhaKdC6/X38aXkANC8VD0q2aBkQAOwmSpNbp1jZYDMMVqaKltIVaO6J0o+0Me9EDIYVY3uTP6T87wtxXYFWcQsaKTMS4CzOvE6IVmY8VKeURktzk+9vdHPrdJ6Qeb1rKVY687pdxC0ICAgkF3ERq7/85S/w+ZQRJhUVFboPdoHuBaqaWCpWXCnws52Kv+q8gT1027KuuKCxFKjcrg1i1pcCG83M65RYUfO6RWkO0EjTWlWd4kHJ1rh+eew201IgR9woQaT/uxw2pnYFZS0gNKJDziRuwWkoBYZkws4PoHihrMzwFPocK+U2qljRdclholMV6SibVBArXj1MVHWy27SRRVZdkJ0Fs0wyAQEBgWQhrk+V2bNno7GxEQDQr18/HDt2LKWLEkgdZCvFyhAQWlHTin3HW2C3SZgwIF+3rcuoWBnymXItBjGblQKpYtUQw7wOAGerpOm7qiZdUGh1ow/7jrdAkoCxfTViZSy5GRUrehzUjJ/jcTISEJIJU6MsFSudDysyx4qO6gHUMFFuWLUZWCkwTLTkdfUY0l12lsLOh4RqxCodycaJECtAI4OJRjWkGmIIs4CAQCoRV1dgSUkJ3n33XVx66aUghODQoUNMwTKid+/eSV2gQHJhzEeioF2BLSqx+kztBhzTOzdixl5E3EJI7zPyeqhiZSRWJuZ1leg0xFEKLMh04/SiTOw82oz1+2ogSRL+XX4Yx5sUkjWkOFs3jieim89hVKzsujV4PU6mBgXDmn/KzKsFKOb9gCFuwcElr+sVK+vSIgWbMxjSktcpAZYkpTGg0RdCoy+EwmzlMaksBfLEqj1Bmko5MNDlFCsxhFlAQCCViItY/e///i9+/vOf46677oIkSTjrrLMitiGEQJIk03E3Al0HxjZ+CmMpcPsRRaE8myutUfDEAjArBUampBNCmPE626QUGI9iBQDjT8vHzqPNeOqjHdhzrEV337mnF+h+N4tb4OMfjKVAr8fJVKUQN9LGaVgTJWT6UiA1r2uzAv2cYqUvBVrFLWhqFyPA3DFkpTnR6AvpDOwHa1Xzel7yFSuemLbHJ0VDZ7uax0oMYRYQEEgl4iJWt912G66//nocOHAAI0eOxMqVK5Gfnx/7gQJdDnI4vlIg7dLLN2nhp4Zff0SOlaEUyClWLQEZdHwer1jR52XEKorHClCI1WtrDjBS9eOxZRjeKxtuhx2Xjuyp2zbSY2XXETd6UaVkKyfdydbBm9eNQ5P1swLpSBuavK7lWNHzAyjnipnXY3UFhjV/F89Jsgwhob6gzEYOpUSx4olVOyITaCnQqvTZWRABoQICAqlE3AGhWVlZGD58OF5++WVMnDgRbrc79oMEuhzMlBAgcghzIwvz1JcBAY38BCwUK7NBzJQMODhTM2DmsYrepTWuXx4cNgmhMMHcKafjzskDLGMGzD1WkaVASrayPU7dSJqgVfI6Na/LckTyulYKNCpWYcv9UehKgSYzHSlRoR4r6q/KdDt0JdBkgZIOl93WriiHdBp70cUUqwyXHWerXrwsd7sykgUEBAQskfCnyk033QQA+Prrr7F9+3ZIkoQhQ4bgzDPPTPriBJIPK8WKtsfTgFCqWGWbXLC1gFCaY6V2z6kXYjPzOiUDmWkO3UWaEivZogPPiPxMN168cSwICL4/uCjqtqYeKxPzOl2D1+PUSnnhsGU8Aq9YabMC9aXAoLErMKipWwmVAiW+FKgPCeX9VcnMsGLrceiPKVFkquXlrpZjJUkS3r59PPtZQEBAIJlImFhVV1fjuuuuw3//+1/k5OSAEIKGhgZMnjwZCxcuRI8ePWLvRKDTwLrNjOb1CMVKJVZpkW8RnliEufErzGOlmtcbuFKgTyUZHqdekTL+HqsUCACTBxfG3AawUKxM4hZ4YsVyqGQSYco3Pk6XvO6ITF7nS4EBme8KtFCsbFop0FSxUtXDJr9esUpFRyCgHafRYxYvKFnvrFmB0SAIlYCAQKqQ8Cfmz3/+czQ2NmLr1q2ora1FXV0dtmzZgsbGRtx9992pWKNAEsEUK7uVYkU9Vmop0ESx0iePa+SBXkCpeZ0vBQZkc/UnzWlOWpKBmCNtONM6APTIcutLgWHzETS6uAVjQCifY8WXAoMyVwq0iFtwaKVAsyYDlr7uMxKr1Aw/dzFDfvteE1pGTnNGL+8KCAgInExIWLFatmwZVq5ciSFDhrDbhg4dir/97W+YMmVKUhcnkHxYxi1YKVZmpUAuIJQfNhzRFdgWZN2iIYuogQjFKobHKhEYCYzTLun2T4/jzskDUJaXjstHlWDp5iMA1FKgbK5Y6QJCjSNtbFopMUKxspg9yK+PPtaUWLn15vWDKYxaUNajeazag+vPLkNdawA/PLM0mcsSEBAQ6NJImFiFw2E4nZEXW6fTiTCnXgh0TYQsPVbaEGZfUGbGdLNSoNtEsQEik9cDoTB8wTA8LrvmwzJcpGlXoHHfyYBudIk6x1CvWCnPPaAwE7MvOl19DC3lkZhDmP0mcQvMgG7isbLKxaJwco9lxMrEY9XcQaXAE/VYDSzKwh9/fEYSVyQgICDQ9ZHwVez73/8+7rnnHlRWVrLbDh8+jPvuuw8XXHBBUhcnkHyELXKsaCmwLSgz47pNAjJcZsQqMsfJJmn7zHDZGamh5UBWVjNcpI0KVTweq3jBHyOde6fLsTJ5LrrukBy2LN1RwtEWkEGnO2llM6scq7Clakfh5JQwY/I6oHUFUvP6YVWxKstLUSnQcWKlQAEBAYFTEQl/Yv71r39FU1MT+vbti/79+2PAgAHo168fmpqaMH/+/FSsUSCJCFkSK4VwEAJUNynZSFlpzohYBoBXbGRT75QkSdy8QIWkGb1IFJGKVRJLgQbFStl/9DRxlkMVJpalO/o4PqiTPk4bwqzPsdKNtLEcwqyVAsOmipVmXm8LyDjerJDW1CtWglgJCAgIxIuES4FlZWXYuHEjVqxYge+++w6EEAwdOhQXXnhhKtYnkGSYdZsBeq/TkQZlXFG2x/zt4dJ1xZmX+HLSnTje7Ed9m3Lxt5qTF+mxSmIp0CQI0ix53ewxITn2SJsWbmB1pHk9DF9Qn7zORtrECgjlS4G6rkDNY3W4XlGrstJSk2EFcCqcCNEUEBAQiBvtTse76KKLcNFFFyVzLQIdAGrIthvIgs0mweO0oy0oo6pRJVYm4aCAPm7AauyLMX2deZEMA3mNXYHJTMI2U6zo81HPlRHMfK7zWJmvsdWvESeqNjmjJa/H6grkAkJpT4CZeb3ZF2KjbFKlVgHa6+zqgnEJAgICAl0V4qvoKQamWJlcK2k58GhDdGKlH0JsXi7LcOuN1syvFFOxSl4pkCclVH1haesW5IaZz8PWXXyUcNBjc9olRtI083vYpBQYa6QNLSOGTb1wrBToC+G7qiYAwGkFGab7Sga0+YfiY0JAQEAgXohPzFMMmscq8qWnfqeYpUA+bsCCMLlYSUy530r9MWYcpbIrUHk+lWBZmOQ183m0kTb6WYn8MVHlLiQT+CNKgeq5j2FeD8rarEA+FiOT6wr89mA9AGBUmdd0X8mA8FgJCAgIJA7xiXmKQfPuRN5HOwCPxioFqmTIL/PJ48bMKE25AWCp/kQQqyR2BUqSxBQfur6eXg8kCSjJMe+kY7P+ZE1hsvJYUeiIlUWOlZ8L/bQaSkz3I4cJZPW5+deJj1sop8SqNMd0X8mAIFYCAgICiUNMID3FIMehWDGPlYUpmlesAiFzwuTk5t4BQMAibDOVXYGAUkqTw4StuSTHgw/u/B4Ks82HiPNdgXSkjZFIRRIr7dh1OVaGUiAledZDmLXb6QggsyHMgPIa2SRgeK/UKVZpJp2UAgICAgLRERexamxsjHuH2dnZ7V6MQOoRVbFSh+ZWxemxArSkdiNhYplMBsXKSCrSDBftZF/EHTYJAcOaR5RakxGnrisw+kgb42MA7fgUxUqfY0XJnfUQZhu3vfJYm2FgtctuY+d0YGEW87KlAhcMKcKK7Udx7VllKXsOAQEBgZMNcX0q5+TkxD20VJbl2BsJdBrkKOnfHqfecG7lseLJTwszcBvIBpt7pzwf9QwZYxkcdhucdon5j5JZCgQ0UhQvYWMBoWFi2cVnPAZ9KZD3WOkVK8rPrM3r2n6oYmUkdZlpDtS2KBEWqfRXAUBZXjre/On4lD6HgICAwMmGuIjVp59+yn7ev38/7r//fsycORPnnHMOAGDNmjV49dVX8eSTT6ZmlQJJA0v0NiHK6YaynKVixRGAJpVYGcmGy+CxoiVDszJYmtOOoKzsJ9mlQEqK4t2vbggz9Y9ZjLSh0JcCtRKo3mMlc6VAc5Jnt0mQJCWklWZgGQNaszhiNTKF/ioBAQEBgfYhLmI1adIk9vOjjz6KefPm4frrr2e3XXHFFRgxYgReeOEF3HTTTclfpUDSwBQrE4JDS4EUVh4rm01iKhNTrBzRPVYsasCEVHicdjamJZk5VgAizOuxwJvPrUbaGNUvnWJl1xSviFKgI/oQZrqvQCgMn0rK7AYCzPuszijLieuYBAQEBAQ6DglfxdasWYOxY8dG3D527FisX78+KYsSSB1kkzZ+CloKpDAbwExBFSBKrIylRaPHKmhhXgf0BvZUeKwA8/E1ptvrIg8sPFYWgaHKtlrIp9G8bhVNYbZvqlgZE/JpZ6DLYcOg4qy4jklAQEBAoOOQ8FWsrKwMzz33XMTtzz//PMrKhMm1q0PzWMVRCowyKoWSCao0WZnXg4xYWY9zSXOkkFjZE1SsuCHKIQsyaLNJuuPQ/cx1FfIeq3iGMPP3UVJmLAVmupXXZFhJtohBEBAQEOiCSLil6I9//CN+9KMf4aOPPsL48Yqxde3atdizZw/efffdpC9QILlgipUZsYqzFAhoygpVrFwOcx8SNa9bBYQCQJpOsUqyx8qmjbCJb3uNGJkNmKZwOWwImXREasGoYfj4UmBQRijsULePXgoEOMXKoCxSFTGV+VUCAgICAu1Hwl95L730UuzatQtXXHEFamtrUVNTgx/84AfYuXMnLr300lSsUSCJCEVTrJxG83qUUqDavWcdt2DwWDH1x6wEqTxWkqKTjvYgUY8VP0Q5msLE709XCuTM77quQDm+UiD1ePktSoFXnFGC4b2ycc3Y0riOR0BAQECgY9GuEJzS0lI88cQTyV6LQAfAbAYdRTpnjLZJWhK7Gagy02wVt2DwWEVTf2j6uttiMPKJIGGPFTeEmZJQM7Ln0hnWeY+VNu9PZ14PxlcKpDEVZgGhAHD+oEKcP6gwrmMREBAQEOh4tItY1dfXY/369aiurkY4HNbdd+ONNyZlYQKpQSgaseJKcllpTtNyIQVVaWIRK6pUWWVCAdog5mSXAZXna59iFQwTLlXevBRIwRMv/rj9ksFjFbY28BsfT8uIZq+TgICAgEDXRcLEavHixbjhhhvQ0tKCrKwsncIgSZIgVl0cYTXHyujdAfTEyioclIKazJnHKmJQsbl53bgdwBOr5Jux6eieePetM69HCVM1K/8pP2txC2FuCHNA1sb/mJVh2eNZKVA1rydZwRMQEBAQSC0SvpLNmTMHt9xyC5qamlBfX4+6ujr2r7a2NhVrFEgioitWGpmyCgelMCpWRiWK5loZ4xbMFCs61DnZGVYAVwqM27yuKU5Wg6MBfSlQVxbkSJh6qhlaA+bqnm6/DqNiFdeyBQQEBAS6CBL+2D58+DDuvvtupKenp2I9AilGVI8Vr1jFJFbKtrFKgUbFyiogFEiNYpV4jpXmkYpKBi1KgdH8Uy2q0T+qx8rQFSgUKwEBAYHuhYSvZFOnTsWGDRtSsRaBDgANvYxJrOIsBbb6FQJgLPFpxIrOCrRWfzyuxMbOJAK6jnhnEGqlQMKRwehdgWZDmM2glQKt18JKgXGUDQUEBAQEuh4S9lhNmzYNv/jFL7Bt2zaMGDECTqde2bjiiiuStjiB5EPlCkkrBVp1+0V4rELWxm0aEJrsAcwAcP3ZvREmBN8b0COu7VlyuhzdbG5FrJy2yPMgSdClsEeLlKD7Va1wwrwuICAg0M2Q8JVs1qxZOHjwIB599FFcc801uPLKK9m/q666KqF9rVq1CpdffjlKSkogSRLef/99dl8wGMSvfvUrjBgxAhkZGSgpKcGNN96IyspK3T78fj9+/vOfo6CgABkZGbjiiitw6NAh3TZ1dXWYMWMGvF4vvF4vZsyYgfr6et02FRUVuPzyy5GRkYGCggLcfffdCAQCum02b96MSZMmwePxoFevXnj00UdBiMFI08Uhx61YRSdW7ghPlf53qtxQlSZoMR4G0EbapKIUOG1kT/xj1nj0yHLHtT1vPo+WFq/zWHHrttkk8Ju7HbaI47Iawmz2XNE6MwUEBAQEuh4SvpKFw2HLf7Isx94Bh5aWFowaNQp//etfI+5rbW3Fxo0b8dvf/hYbN27Ee++9h507d0YoYvfeey8WLVqEhQsXYvXq1WhubsZll12mW8v06dNRXl6OZcuWYdmyZSgvL8eMGTPY/bIsY9q0aWhpacHq1auxcOFCvPvuu5gzZw7bprGxERdddBFKSkrw1VdfYf78+Xj66acxb968hI65syFTJcS0KzB+xcqoLsXtsTIhT2kpjFtIFHTdcphE9YXp5wOal0EB5Ty5DMcVrbxnfC6z10lAQEBAoOuiXTlWFD6fD2lpae1+/CWXXIJLLrnE9D6v14sVK1bobps/fz7OPvtsVFRUoHfv3mhoaMCCBQvw+uuv48ILLwQAvPHGGygrK8PKlSsxdepUbN++HcuWLcPatWsxbtw4AMCLL76Ic845Bzt27MCgQYOwfPlybNu2DQcPHkRJSQkA4JlnnsHMmTPx+OOPIzs7G2+++SZ8Ph9eeeUVuN1uDB8+HDt37sS8efMwe/bspAdbpgpUsbJKE3fYJITCJKbHKmIQcSyPFU1eN/EXnVGWgzSnDWf3y4vzKFIHFvAZZVYgAB1ZMiOVtPRnRhajEisD8RSKlYCAgED3QsKKlSzLeOyxx9CrVy9kZmZi7969AIDf/va3WLBgQdIXyKOhoQGSJCEnJwcA8PXXXyMYDGLKlClsm5KSEgwfPhxffvklAGDNmjXwer2MVAHA+PHj4fV6ddsMHz6ckSpAMen7/X58/fXXbJtJkybB7XbrtqmsrMT+/fst1+z3+9HY2Kj715lgswItiCAty8XrsaIwlreMHqtAFCP48F5ebHpoKu6cPCDW8lMOXmljOVax4hYsyqBA4qVAp4FICcVKQEBAoHshYWL1+OOP45VXXsEf/vAHuFwudvuIESPw97//PamL4+Hz+XD//fdj+vTpyM7OBgBUVVXB5XIhNzdXt21RURGqqqrYNoWFkSNACgsLddsUFRXp7s/NzYXL5Yq6Df2dbmOGJ598knm7vF4vysrKEjnspEOOMisQ0MbYxPRYGZSYCNXGYT4r0IpUpCLDqj2gpMjHzfkzU9msktcBfdefy2GLOLZ4hjAb1yMgICAg0D2Q8NXstddewwsvvIAbbrgBdrt2cR05ciS+++67pC6OIhgM4rrrrkM4HMazzz4bc3tCSEQifCq2ocb1aGXABx54AA0NDezfwYMHY64/lWCKlQWxyklXCFVBpsv0fopYZIHNCgxRYkWT17sGgbICJUVtXGo6JYk83BZdgcrvnGLltLMAVONzmCGiFCgUKwEBAYFuhYQ9VocPH8aAAZElm3A4jGAwmJRF8QgGg7j22muxb98+fPLJJ0ytAoDi4mIEAgHU1dXpVKvq6mpMmDCBbXP06NGI/R47dowpTsXFxVi3bp3u/rq6OgSDQd02RmWquroaACKULB5ut1tXPuxsxFKsHv3BcJQfrMMZZTlR92MkVpGeK73HKiBbl9W6EpyGbkYg9kibaCqT22EDDI2jURUrYylQeKwEBAQEuhUSlg+GDRuGzz//POL2f/3rXxg9enRSFkVBSdWuXbuwcuVK5Ofn6+4fM2YMnE6nzuR+5MgRbNmyhRGrc845Bw0NDVi/fj3bZt26dWhoaNBts2XLFhw5coRts3z5crjdbowZM4Zts2rVKl0Ew/Lly1FSUoK+ffsm9bhTCZlEV6zO7peH287rH9OMbyRSsboCtYDQLq5Ymawv1kibCLWOI2Juh03XQWm3SVHPrfH8CMVKQEBAoHshYcXqoYcewowZM3D48GGEw2G899572LFjB1577TUsWbIkoX01Nzdj9+7d7Pd9+/ahvLwceXl5KCkpwdVXX42NGzdiyZIlkGWZKUZ5eXlwuVzwer249dZbMWfOHOTn5yMvLw9z587FiBEjWJfgkCFDcPHFF2PWrFl4/vnnAQC33XYbLrvsMgwaNAgAMGXKFAwdOhQzZszAU089hdraWsydOxezZs1iCtn06dPxyCOPYObMmfj1r3+NXbt24YknnsCDDz7YbToCAc7rdIJKSETcgkVpMBQmCIcJgiFr83pXgvG8WBGh+BUruy7rLNZ5NxI7oVgJCAgIdC8kLB9cfvnlePvtt7F06VJIkoQHH3wQ27dvx+LFi3HRRRcltK8NGzZg9OjRTOmaPXs2Ro8ejQcffBCHDh3CBx98gEOHDuGMM85Az5492T/azQcAf/zjH3HllVfi2muvxcSJE5Geno7Fixfr/F9vvvkmRowYgSlTpmDKlCkYOXIkXn/9dXa/3W7Hhx9+iLS0NEycOBHXXnstrrzySjz99NNsGxr/cOjQIYwdOxY/+9nPMHv2bMyePTvRU9ipCKsX+RPtNotUrAyqDUc8guEwglFSzLsSIjOpzM9TVGLFKVZpTr1iFev4jbEVXfx0CQgICAgY0K4cq6lTp2Lq1Kkn/OTnn39+1OTyeFLN09LSMH/+fMyfP99ym7y8PLzxxhtR99O7d++YituIESOwatWqmGvqyghFGcKcCCLN69aeqyA3d6+re6yMipFZRyBgLAVaq3duh52RWWX/0Y8/IiA0itFdQEBAQKDr4YQCQgW6H8JJIlYx4xa43/1Bmc2+6+pdgRHRCXEoVi6H0WPFdwXaIMt8KTD68UeUArtRmVlAQEBAQBCrUw7JUqyMoZdGQmJXZ+aFCdAa0KILooVjdgUYiY9V6S6RrkDZRrhtYylWxlmB0dcrICAgINC1ID62TzEkS7GKFbcAaIRDR6y6uBnbKo/LCLduVqA1GXM77PptYxAr43kVipWAgIBA94IgVqcYUqdYmWQ9qbe1BEJRt+tKkCRJd24sS4F261IgTx7dhuR1K8+W9ljRFSggICDQndHuq1wgEMCOHTsQCoVibyzQZcC6ApNtXjcZSUNva1MVK5vUPYgCT4ysFLbopUBOsXLadH602OZ1Yymw658vAQEBAQENCROr1tZW3HrrrUhPT8ewYcNQUVEBALj77rvx+9//PukLFEguQjGS1+NFPPPv6HO0+EPqNl1braJwRun4o4hGrJyGHCtXlLJhtP0q2wtiJSAgINCdkPCV7oEHHsC3336L//73v0hLS2O3X3jhhXj77beTujiB5IPNCjxB705EV6AJYaCEg87d6y7EileVLIlVFPLlMCavRxnYHPHchvMoktcFBAQEuhcS7gp8//338fbbb2P8+PG6ROqhQ4diz549SV2cQPKhzQo8MZITTymQbtPip8Sqe5AE/tzEFbcQpSswzWnXkaNYXZFm3ZUCAgICAt0HCROrY8eOobCwMOL2lpaWbjXa5VQFU6xOUDyKlbzO39aqmte7etQChTMexSpKp5/LrleseMQq7UUGhIq/KQEBAYHuhISvdGeddRY+/PBD9jslUy+++CLOOeec5K1MICVIlmIVMSswSimQxi109XBQCn0p0JzYuBPIsUokbkEMYRYQEBDo3khYsXryySdx8cUXY9u2bQiFQvjzn/+MrVu3Ys2aNfjss89SsUaBJEImyVesHDbJtHvNSKy6+jgbCp4kWhFQFzeLMqIUyHusnHbL+0yfW5QCBQQEBLo1Er68TpgwAV988QVaW1vRv39/LF++HEVFRVizZg3GjBmTijUKJAnhMGGjZU7YYxVP5xwjVt2rKzAexUrXFWgcaWNQrFyJmNcjSJogVgICAgLdCe0aaTNixAi8+uqryV6LQIohc8OATzTR22aT4LLbEJDDlmSBEg6mWHUTksCTTisymOaMVgrUe6z4WeIx4xaMpcBucs4EBAQEBBS0i1iFw2Hs3r0b1dXVCIfDuvvOO++8pCxMIPmg/ioAsCehLOdyUGJlThZY3AL1WJl0DnZF8IqVleE+J92FmRP6It1lj8yx0iWv2xHmiVUsj5VB/RIjbQQEBAS6FxImVmvXrsX06dNx4MABEP6rOBQjuyzLFo8U6GzoiFUSLtguhw3wW6s69HY60qb7KFZcKTDKmh++Ypj54w3J62HCD2FObKSNGMIsICAg0L2QMLH6n//5H4wdOxYffvghevbsKSIWuhFCPLFKAsmh3W5GlYXCZTCvdx+PVfxdfOaP13us+C8gscilsRQoFCsBAQGB7oWEidWuXbvwzjvvYMCAAalYj0AKEU4ysaKlPWvFSnmOtm5GrOLJsYr6eF3yuh18tTxWlpeRyImuQAEBAYHuhYSvGuPGjcPu3btTsRaBFCAkh/Hzt77B85/t0SlWybheU3XFKp/KGdEV2D1IQjzm9Whw6pLXbbrMr1jnQASECggICHRvxKVYbdq0if3885//HHPmzEFVVRVGjBgBp9Op23bkyJHJXaHACWHT4QYs/rYSX+w+jitH9wKgXKyTUcKlhMFSsXIYc6y6n2LVHl+YvivQjpDMlwIT6woUxEpAQECgeyEuYnXGGWdAkiSdV+SWW25hP9P7hHm96+FgbSsARTWiilWyLtaUBFhmPXXX5HVesWpHJyM9H5Kk/JyIYmUsBYrkdQEBAYHuhbiI1b59+1K9DoEU4VBdGwDAFwxDVpWTZBmiqcfKSomKnBXYPUiCLiC0PYqVSszcDhskSdKn1ItSoICAgMBJjbiIVZ8+fdjPq1atwoQJE+Bw6B8aCoXw5Zdf6rYV6HwcqmtlPyc79sDtUMa1WClRlHAFVULXfczrPBFKfM2UPNHz47DbYLdJkMMk8ZE2QrESEBAQ6FZI+KoxefJk1NbWRtze0NCAyZMnJ2VRAonjR//3JS6b/zmON/t1tx+sbWM/t/gVYpWsNG+tK9Aied0YnNldFCvu/LRHZaPHzQ9fdsc4VxSSJOmeXySvCwgICHQvJBy3QL1URtTU1CAjIyMpixJIHJsPNyAQCsMX1HvceMWqyZ9cxSpW3ILLQCK6i2LFq1Tt8YXR88t7q9wOG1oDclwKmNNuQygsd5tAVQEBAQEBDXETqx/+8IcAlG/UM2fOhNvtZvfJsoxNmzZhwoQJyV+hQFxw2iQEoE9Xl8MEh+tTp1hpAaHR4xYoTnTwc0fhRLsCNcXKzm5jfrQ49uewS0BQqFUCAgIC3RFxEyuv1wtAUayysrLg8XjYfS6XC+PHj8esWbOSv0KBuEBNzkGutb+6yaf7vdmXbI9VfDlW7HeLhPauBp4Atsdj1Ts/HQDQN19TcCnJike1o+dT+KsEBAQEuh/iJlYvv/wyAKBv376YO3euKPt1MdALNq9Y8f4qAGimilWyugJjxC0YlSxnN1Ss2lMK7N8jE6t+MRmF2Zqqq3VQxj739LUUHYECAgIC3Q8Je6weeuihVKxD4AShKVba/BSaYUXR4qdBnUlSrJxa15sZjB6r7hi30N41U9WKwp1oKRDJSccXEBAQEOhYdA8JQSAmqMrBj62hGVYUNG4hWSWmnHQldd/rcZreH9kV2D3ebvYTLAWaQSNWCZQCBbMSEBAQ6HZIWLES6JqgKofMTfw9WKdXrJpUj1WyLtjXn9UbLrsNV5xRYnp/d41b4ENB2xMQaobMNIV8ZrjtMbbkS4Hdg4gKCAgICGgQxOokgZl5/VCdsRSYXGKVm+HCT889zfL+7qpY8SpVstZ874UDMaRnFiadXhjH8yuvTzc5XQICAgICHBL+6H7ttdfg9/sjbg8EAnjttdeSsiiBxEGN4Wbm9SLVRN2cZGIVCy6H0WPVPZiCMwkeKyPO7J2LBy4ZAo8rAcVKdAUKCAgIdDskfKW7+eab0dDQEHF7U1MTbr755qQsSiBxGM3rQTmMIw0KsTq9KAtAxxMro9pjNLN3VfAG885Q2SixEzlWAgICAt0PCV81rJLXDx06xLKuBDoe9GIcUkuBVQ0+hInS5l+Wp3SoJbsUGHtN3TMglFfWOiP9XMQtCAgICHRfxO2xGj16NCRJgiRJuOCCC3RDmGVZxr59+3DxxRenZJECsUEvwrQrkEYtlOZ4kK7GIjBi1UElpsiA0O5BrPhSYGesWZQCBQQEBLov4iZWV155JQCgvLwcU/9/e3cfFXWV/wH8/R2YGRF1FBGHEVBWzVSIfMqULR9S8AGtdE3UCLTFzXxccLfcX4V62rRN2UorPWVYGye3U+patiSaSq5hJmCihlQoPoCY8qTGg3B/f+h8mWFQZnD4DjO8X+fMEb7fOzP3y53xfs7n3u+94eFo166dfE6j0aBHjx6YOnWq3StI1nGXl1u4ORRoXGrBz6utPK9H8TlW9QMrJ8nAmGbWHLGoqVqevO4cfy8iIqpjdWBlXBi0R48emD59Otq0adNslSLbqeXlFm5mrEp+qwIAdPbUoI3aMYFV/S1snOeuQPtPXrcFhwKJiJyXzcstREdHN0c96C4Z1zwyLrdg/NddJcHjVmBVUV17q6yD5lg5yeR1dTMst9CU97fX1kNERKQcmwOrmpoa/POf/8Qnn3yC/Px8VFVVmZ2/cuWK3SpH1jMOsxkXCDVOYnd3U1nc4q9YYKWqf1egk2SszO4KVD64cedQIBGR07K5p1uxYgUSExPxxBNPoLS0FHFxcZgyZQpUKhWWL1/eDFUka9RfINQ410rtJqGNuv7deY4ZCnSedazsv6WNLYwBKJdbICJyPjb3GsnJyXj33XexdOlSuLu7Y8aMGXjvvffw0ksvIT09vTnqSFaQ9wqU17ES8nHjUKCRUkNMzrqljemQpSMm3MsZK+f4cxERkQmbA6vCwkIEBwcDANq1aycvFhoREYGdO3fat3ZktfrLLRgDLHc3SZ68bqTUXCen3dJG1TLmWDnLul9ERFTH5v+5/fz8UFBQAADo1asXdu3aBQA4fPgwtFqtfWtHVjMGS3JgdetftcpxGSuL5RacJLBqji1tbFE3FKj4WxMR0V2y+b/uxx9/HHv27AEALF68GC+++CJ69+6Np556CnPmzLF7Bck69fcKrDbJWNWfvK7YHCu3+nOsnGNsqzk2Ybbt/Tl5nYjIWdl8V+Dq1avln//whz/A398f//vf/9CrVy9MnjzZrpUj67m5me8VeMNkjlX9oUClJkW7qSRIEiBu7QvtnHcFcrkFIiKyns2BVX1Dhw7F0KFD7VEXugt1yy3cyljduivQdB0rI6UyVpIkQe2mQtWNuuyZMzDWU5IckzXiAqFERM7LOVII1Kj6C4SarmNVP2OlZIetcfCwWlMYJ407YjsbwGRLG2asiIicjnP0dNQoY2dct9xC3TpWjlog1LRegOMCFVt1bKuGSgK8PDUOeX9mrIiInNddDwVSy1D/rsC6LW1UaONuHtAomQkx2x7G3TkCBe92WmyKHoLO7RwTWPl3agsAMHT0cMj7ExFR01mVQnjzzTdRUVEBAMjPz4cwzkamFsM4FGhccd34r7ubBHc3ldmQnJuCmSOzVcydJGMFAKPu9cF9fh0d8t6P9PXBFwt/j+fH3+uQ9ycioqazqqeLi4tDWVkZACAwMBCXLl2yy5unpaVh0qRJMBgMkCQJ27dvNzu/detWhIeHw9vbG5IkISsry+I1Ro4cCUmSzB6RkZFmZYqLixEVFQWdTgedToeoqCiUlJSYlcnPz8ekSZPg6ekJb29vLFq0yGIfxGPHjmHEiBHw8PBAt27dsHLlyhYTZNafvF53V+DN41q1aWClXL007qZzrJwjY+VokiQhqJvOYm4cERG1fFYNBRoMBnz22WeYMGEChBA4d+6cnMGqLyAgwOo3v3btGkJCQjB79mxMnTq1wfOhoaGYNm0aYmNjb/s6sbGxWLlypfy7h4f5EMrMmTNx7tw5pKSkAADmzp2LqKgofP755wBubiw9ceJEdOnSBQcOHMDly5cRHR0NIQTWrVsHACgrK8PYsWMxatQoHD58GKdOnUJMTAw8PT0RHx9v9TU3l7rlFszXsTJmjDzUbiivuHGzrKIZq5v1clfdDHqJiIhcmVWB1QsvvICFCxdiwYIFkCQJQ4YMsSgjhIAkSaipqbH6zcePH4/x48ff9nxUVBQA4PTp03d8nbZt20Kv1zd47uTJk0hJSUF6erq8LMS7776LYcOGIScnB3369MGuXbtw4sQJnD17FgaDAQCwdu1axMTE4O9//zs6dOiA5ORkVFRUYPPmzdBqtQgKCsKpU6eQmJiIuLg4hwcN9RcINc61Mg6/mU5gVzJjJW/PwmwVERG1AlZ1sXPnzsWvv/6Ko0ePQgiB1NRUZGRkmD0yMzORkZHR3PVtUHJyMry9vdG/f38sXboU5eXl8rlvv/0WOp3ObK2tBx98EDqdDgcPHpTLBAUFyUEVAISHh6OyshJHjhyRy4wYMcJs257w8HBcuHCh0cBPCcY7yOoWCK27KxCA2VpWjphj5SxLLRAREd0NqzJWb775JubOnYugoCAkJSVh2LBhFsNtjjJr1iwEBgZCr9cjOzsby5Ytw9GjR5Gamgrg5qbRPj4+Fs/z8fFBYWGhXKZr165m5zt16gSNRmNWpkePHmZljM8pLCxEYGBgg/WrrKxEZWWl/Ltxrpq91S23UO+uwFsBjel8HWXvCpRu/cvAioiIXJ/Nk9fnzJljlhFytNjYWIwZMwZBQUGIjIzEp59+it27d5tlzxoapjMOXd5NGePE9TsNA65atUqeNK/T6eDv72/9xdnAGEDVbcJ8K2N1K5PVxmTyupLDcnUZKw4FEhGR67MqsDJOXj9z5ow8eT0/P7/Bh6MNHDgQarUaubm5AAC9Xo+LFy9alLt06ZKccdLr9XJmyqi4uBjV1dV3LFNUVAQAFtkuU8uWLUNpaan8OHv2bNMv7g6MQ4Hycgv1MlamQ4FK7kEnz7FyoqUWiIiImsqq3u6FF17AkiVL8Lvf/U6evB4YGGj26NGjx22Hw5R0/PhxVFdXw9fXFwAwbNgwlJaW4rvvvpPLHDp0CKWlpRg+fLhcJjs7GwUFBXKZXbt2QavVYtCgQXKZtLQ0syUYdu3aBYPBYDFEaEqr1aJDhw5mj+ZgzAhZ7BVonGNlMnldqb0Cb9br5kdM487AioiIXJ9Vc6zmzp2LGTNm4MyZM7jvvvuwe/dudO7c+a7f/OrVq/jpp5/k3/Py8pCVlQUvLy8EBATgypUryM/Px4ULFwAAOTk5AG5mj/R6PX7++WckJydjwoQJ8Pb2xokTJxAfH48BAwYgNDQUANC3b1+MGzcOsbGx2Lhxo3w9ERER6NOnDwAgLCwM/fr1Q1RUFF577TVcuXIFS5cuRWxsrBwIzZw5EytWrEBMTAz+9re/ITc3F6+88gpeeuklh98RCJjuFWiesTLeLWg6x0ql5F6B7nXLLRAREbk6q7e0ad++vTx5PTQ01OzuuKb6/vvvMWrUKPn3uLg4AEB0dDQ2b96MHTt2YPbs2fJ548KfCQkJWL58OTQaDfbs2YM33ngDV69ehb+/PyZOnIiEhAS4udUFEsnJyVi0aBHCwsIAAJMnT8b69evl825ubti5cyeeffZZhIaGwsPDAzNnzsSaNWvkMjqdDqmpqZg/fz4GDx6MTp06IS4uTq6zo9VfINQYYLk3cFegIzJWnLxOREStgc17BUZHRwMAjhw5gpMnT0KSJPTt2xcDBw60+c1Hjhx5x5XLY2JiEBMTc9vz/v7+2L9/f6Pv4+XlhY8++uiOZQICAvDFF1/csUxwcDDS0tIafT9HMM6lqq53V2BDyy0ombHi5HUiImpNbA6sioqKEBkZiX379qFjx44QQqC0tBSjRo3Cli1b0KVLl+aoJzXC3WLyuvnK622YsSIiImp2Nvd2CxcuRFlZGY4fP44rV66guLgY2dnZKCsrw6JFi5qjjmQF9/rrWNXWuytQ45h1rDTGLW2YsSIiolbA5oxVSkoKdu/ejb59+8rH+vXrh7feekuew0TKq1tuwbgJc/11rNwsyiqBGSsiImpNbO7tamtroVarLY6r1WrU3hqGIuUZA5eaWoHaWoFb8VWD61gpGli5M7AiIqLWw+bebvTo0Vi8eLG8BAIAnD9/Hn/+85/xyCOP2LVyZD3TvQKrTQLcunWsVBZllcDJ60RE1JrYHFitX78e5eXl6NGjB3r27IlevXohMDAQ5eXlWLduXXPUkaxgXK+qplbI86xMj7dxd0zGqm6OFTNWRETk+myeY+Xv74+MjAykpqbixx9/hBAC/fr1w5gxY5qjfmQlY2aqusY8sDIeb6NxTGClvRXQaRlYERFRK2BzYJWXl4fAwECMHTsWY8eObY46UROYLrdgNhSoslzHSsm7AsP6d8WBn37FtMHNs/k0ERFRS2JzGqFXr14YNWoUPvroI1RUVDRHnagJjENtNSYZK3eVJG+3YxZYKTjfqXtnT3ww5wEM63n3WyARERG1dDYHVkePHsWAAQMQHx8PvV6PP/3pTzh06FBz1I1sYMxMVdfWWmxnAzhuHSsiIqLWxObAKigoCImJiTh//jySkpJQWFiIhx56CP3790diYiIuXbrUHPWkRhiDqJpaIQdWxonrgOP2CiQiImpNmjyj2N3dHY8//jg++eQTvPrqq/j555+xdOlS+Pn54amnnkJBQYE960mNqFtuQciLhBrXkAIArbruZyX3CiQiImpNmhxYff/993j22Wfh6+uLxMRELF26FD///DO+/vprnD9/Ho8++qg960mNMM1OVVbfGgo0CaCYsSIiImp+Nt8VmJiYiKSkJOTk5GDChAn48MMPMWHCBKhudeyBgYHYuHEj7r33XrtXlm7PdD5VxY0aAOarnZtuacOMFRERUfOwObB65513MGfOHMyePRt6vb7BMgEBAdi0adNdV46s526Ssfqt6mZgZRpsqd1UULtJqK4RzFgRERE1E5sDq9zc3EbLaDQaREdHN6lC1DSmQdRv1bcCq3oBVBu1G6prbkDFuwKJiIiahc2BldH169eRn5+Pqqoqs+P33XffXVeKbGcaRFVUWw4FAoBB54FTleXwbqdVtG5ERESthc2B1aVLlxATE4OUlJQGz9fU1Nx1pch2kiTBTSWhplbIgZV7vYVA331qMC6WV0Cva+OIKhIREbk8m+8KXLJkCUpKSpCeng4PDw+kpKTggw8+QO/evbFjx47mqCNZyZi1qpDvCjRv3oDObTGkh5fi9SIiImotbM5Yff311/jPf/6DIUOGQKVSoXv37hg7diw6dOiAVatWYeLEic1RT7KCu0pCJermWKkV3LqGiIiImpCxunbtGnx8fAAAXl5e8krrwcHByMjIsG/tyCbG/QLluwJVTV6mjIiIiJrA5p63T58+yMnJAQDcf//92LhxI86fP48NGzbA19fX7hUk69UNBTY8x4qIiIial81DgUuWLMGFCxcAAAkJCQgPD0dycjI0Gg02b95s7/qRDYyBlHEoUOPGjBUREZGSbA6sZs2aJf88YMAAnD59Gj/++CMCAgLg7e1t18qRbYxDf8xYEREROYbVKY3r169j/vz56NatG3x8fDBz5kz8+uuvaNu2LQYOHMigqgWoy1jduiuQGSsiIiJFWd3zJiQkYPPmzZg4cSIiIyORmpqKefPmNWfdyEb151ipuXUNERGRoqweCty6dSs2bdqEyMhIAMCTTz6J0NBQ1NTUwM3NrZFnkxIshwKZsSIiIlKS1T3v2bNn8dBDD8m/P/DAA3B3d5cnspPjyUOBVVzHioiIyBGsDqxqamqg0WjMjrm7u+PGjRt2rxQ1jTwUeIPrWBERETmC1UOBQgjExMRAq63bwLeiogLPPPMMPD095WNbt261bw3JahYLhDJjRUREpCirA6vo6GiLY08++aRdK0N3p/5egWrOsSIiIlKU1YFVUlJSc9aD7MCYoZInr/OuQCIiIkUxpeFCjHOq6jZhZvMSEREpiT2vCzFmqOoCK2asiIiIlMTAyoUYhwKFMP7O5iUiIlISe14XUn95Bc6xIiIiUhYDKxdSf3kFzrEiIiJSFnteF2KRseIcKyIiIkUxsHIh9Yf+1Fx5nYiISFHseV1I/QwVM1ZERETKYmDlQupnrHhXIBERkbLY87qQ+oGUmncFEhERKYqBlQthxoqIiMix2PO6EMvlFpixIiIiUhIDKxdSf7kFrmNFRESkLPa8LsRiKJBzrIiIiBTFwMqF1J9TxTlWREREymLP60IsFgjlHCsiIiJFMbByIRYLhHLldSIiIkWx53UhFutYMWNFRESkKAZWLoTrWBERETmWQ3vetLQ0TJo0CQaDAZIkYfv27Wbnt27divDwcHh7e0OSJGRlZVm8RmVlJRYuXAhvb294enpi8uTJOHfunFmZ4uJiREVFQafTQafTISoqCiUlJWZl8vPzMWnSJHh6esLb2xuLFi1CVVWVWZljx45hxIgR8PDwQLdu3bBy5UoIIezxp7AL3hVIRETkWA4NrK5du4aQkBCsX7/+tudDQ0OxevXq277GkiVLsG3bNmzZsgUHDhzA1atXERERgZqaGrnMzJkzkZWVhZSUFKSkpCArKwtRUVHy+ZqaGkycOBHXrl3DgQMHsGXLFnz22WeIj4+Xy5SVlWHs2LEwGAw4fPgw1q1bhzVr1iAxMdEOfwn7sFwglBkrIiIiRYkWAoDYtm1bg+fy8vIEAJGZmWl2vKSkRKjVarFlyxb52Pnz54VKpRIpKSlCCCFOnDghAIj09HS5zLfffisAiB9//FEIIcSXX34pVCqVOH/+vFzm448/FlqtVpSWlgohhHj77beFTqcTFRUVcplVq1YJg8Egamtrrb7O0tJSAUB+XXvakXVedH/uC/nxa3lF408iIiKiRlnbfzt1SuPIkSOorq5GWFiYfMxgMCAoKAgHDx4EAHz77bfQ6XQYOnSoXObBBx+ETqczKxMUFASDwSCXCQ8PR2VlJY4cOSKXGTFiBLRarVmZCxcu4PTp07etY2VlJcrKyswezYVzrIiIiBzLqXvewsJCaDQadOrUyex4165dUVhYKJfx8fGxeK6Pj49Zma5du5qd79SpEzQazR3LGH83lmnIqlWr5LldOp0O/v7+Nl6l9XhXIBERkWM5dWB1O0IISFJdUGH6sz3LiFsT1xt6rtGyZctQWloqP86ePWv9hdiI61gRERE5llP3vHq9HlVVVSguLjY7XlRUJGeT9Ho9Ll68aPHcS5cumZWpn3UqLi5GdXX1HcsUFRUBgEUmy5RWq0WHDh3MHs2FK68TERE5llMHVoMGDYJarUZqaqp8rKCgANnZ2Rg+fDgAYNiwYSgtLcV3330nlzl06BBKS0vNymRnZ6OgoEAus2vXLmi1WgwaNEguk5aWZrYEw65du2AwGNCjR4/mvEyrmWao3FTSHTNpREREZH8ODayuXr2KrKwseX2qvLw8ZGVlIT8/HwBw5coVZGVl4cSJEwCAnJwcZGVlyZkjnU6Hp59+GvHx8dizZw8yMzPx5JNPIjg4GGPGjAEA9O3bF+PGjUNsbCzS09ORnp6O2NhYREREoE+fPgCAsLAw9OvXD1FRUcjMzMSePXuwdOlSxMbGyhmmmTNnQqvVIiYmBtnZ2di2bRteeeUVxMXFtZgAxnQokGtYEREROYACdyje1t69ewUAi0d0dLQQQoikpKQGzyckJMiv8dtvv4kFCxYILy8v4eHhISIiIkR+fr7Z+1y+fFnMmjVLtG/fXrRv317MmjVLFBcXm5U5c+aMmDhxovDw8BBeXl5iwYIFZksrCCHEDz/8IB566CGh1WqFXq8Xy5cvt2mpBSGad7mFjDNX5KUW+r+UYvfXJyIiaq2s7b8lIVrQ0uGtQFlZGXQ6HUpLS+0+3yr7fCki1h0AAHRsq0bWS2GNPIOIiIisYW3/7dRzrMicm8p0KJBNS0REpDT2vi7E9C5A3hFIRESkPAZWLsTNJEvFfQKJiIiUx97XhZjeCVh/sVAiIiJqfgysXIhpMKXmHCsiIiLFsfd1IaYT1pmxIiIiUh4DKxdiOmG9/obMRERE1PzY+7oQ0+UW1Fx5nYiISHEMrFyI6Z2AHAokIiJSHgMrF2KWseJQIBERkeLY+7oQs+UWOBRIRESkOAZWLkSSJDlrxcnrREREymPv62KMmSpuaUNERKQ8BlYuxji3inOsiIiIlMfe18XIQ4FceZ2IiEhx7H1djHEIkEOBREREymNg5WLqJq8zsCIiIlIaAysXYxwC5FAgERGR8tj7uhgOBRIRETkOAysXw3WsiIiIHIe9r4uRl1vgyutERESKY2DlYpixIiIichz2vi7GGFDxrkAiIiLlMbByMcYtbTTMWBERESmOva+LcZdXXmfGioiISGkMrFyMWh4KZNMSEREpjb2vizFOXuc6VkRERMpzd3QFyL4mBOuRf+U6hgZ2dnRViIiIWh0GVi5m+pAATB8S4OhqEBERtUocCiQiIiKyEwZWRERERHbCwIqIiIjIThhYEREREdkJAysiIiIiO2FgRURERGQnDKyIiIiI7ISBFREREZGdMLAiIiIishMGVkRERER2wsCKiIiIyE4YWBERERHZCQMrIiIiIjthYEVERERkJ+6OrkBrI4QAAJSVlTm4JkRERGQtY79t7Mdvh4GVwsrLywEA/v7+Dq4JERER2aq8vBw6ne625yXRWOhFdlVbW4sLFy6gffv2kCTJbq9bVlYGf39/nD17Fh06dLDb67Ykrn6Nrn59AK/RFbj69QG8RlfQHNcnhEB5eTkMBgNUqtvPpGLGSmEqlQp+fn7N9vodOnRwyS+JKVe/Rle/PoDX6Apc/foAXqMrsPf13SlTZcTJ60RERER2wsCKiIiIyE4YWLkIrVaLhIQEaLVaR1el2bj6Nbr69QG8Rlfg6tcH8BpdgSOvj5PXiYiIiOyEGSsiIiIiO2FgRURERGQnDKyIiIiI7ISBFREREZGdMLByEW+//TYCAwPRpk0bDBo0CN98842jq9Qkq1atwpAhQ9C+fXv4+PjgscceQ05OjlmZmJgYSJJk9njwwQcdVGPbLV++3KL+er1ePi+EwPLly2EwGODh4YGRI0fi+PHjDqyxbXr06GFxfZIkYf78+QCcs/3S0tIwadIkGAwGSJKE7du3m523ps0qKyuxcOFCeHt7w9PTE5MnT8a5c+cUvIo7u9M1VldX47nnnkNwcDA8PT1hMBjw1FNP4cKFC2avMXLkSIu2jYyMVPhKGtZYG1rzuXTmNgTQ4PdSkiS89tprcpmW3IbW9A8t4bvIwMoF/Pvf/8aSJUvwf//3f8jMzMRDDz2E8ePHIz8/39FVs9n+/fsxf/58pKenIzU1FTdu3EBYWBiuXbtmVm7cuHEoKCiQH19++aWDatw0/fv3N6v/sWPH5HP/+Mc/kJiYiPXr1+Pw4cPQ6/UYO3asvM9kS3f48GGza0tNTQUATJs2TS7jbO137do1hISEYP369Q2et6bNlixZgm3btmHLli04cOAArl69ioiICNTU1Ch1GXd0p2u8fv06MjIy8OKLLyIjIwNbt27FqVOnMHnyZIuysbGxZm27ceNGJarfqMbaEGj8c+nMbQjA7NoKCgrw/vvvQ5IkTJ061axcS21Da/qHFvFdFOT0HnjgAfHMM8+YHbv33nvF888/76Aa2U9RUZEAIPbv3y8fi46OFo8++qjjKnWXEhISREhISIPnamtrhV6vF6tXr5aPVVRUCJ1OJzZs2KBQDe1r8eLFomfPnqK2tlYI4fztB0Bs27ZN/t2aNispKRFqtVps2bJFLnP+/HmhUqlESkqKYnW3Vv1rbMh3330nAIgzZ87Ix0aMGCEWL17cvJWzg4aur7HPpSu24aOPPipGjx5tdsxZ2lAIy/6hpXwXmbFyclVVVThy5AjCwsLMjoeFheHgwYMOqpX9lJaWAgC8vLzMju/btw8+Pj645557EBsbi6KiIkdUr8lyc3NhMBgQGBiIyMhI/PLLLwCAvLw8FBYWmrWnVqvFiBEjnLI9q6qq8NFHH2HOnDlmm447e/uZsqbNjhw5gurqarMyBoMBQUFBTtmuwM3vpiRJ6Nixo9nx5ORkeHt7o3///li6dKnTZFqBO38uXa0NL168iJ07d+Lpp5+2OOcsbVi/f2gp30Vuwuzkfv31V9TU1KBr165mx7t27YrCwkIH1co+hBCIi4vD73//ewQFBcnHx48fj2nTpqF79+7Iy8vDiy++iNGjR+PIkSNOsYrw0KFD8eGHH+Kee+7BxYsX8fLLL2P48OE4fvy43GYNteeZM2ccUd27sn37dpSUlCAmJkY+5uztV581bVZYWAiNRoNOnTpZlHHG72lFRQWef/55zJw502yD21mzZiEwMBB6vR7Z2dlYtmwZjh49Kg8Ht2SNfS5drQ0/+OADtG/fHlOmTDE77ixt2FD/0FK+iwysXIRpNgC4+aGrf8zZLFiwAD/88AMOHDhgdnz69Onyz0FBQRg8eDC6d++OnTt3Wvwn0RKNHz9e/jk4OBjDhg1Dz5498cEHH8iTZV2lPTdt2oTx48fDYDDIx5y9/W6nKW3mjO1aXV2NyMhI1NbW4u233zY7FxsbK/8cFBSE3r17Y/DgwcjIyMDAgQOVrqpNmvq5dMY2BID3338fs2bNQps2bcyOO0sb3q5/ABz/XeRQoJPz9vaGm5ubRaRdVFRkEbU7k4ULF2LHjh3Yu3cv/Pz87ljW19cX3bt3R25urkK1sy9PT08EBwcjNzdXvjvQFdrzzJkz2L17N/74xz/esZyzt581babX61FVVYXi4uLblnEG1dXVeOKJJ5CXl4fU1FSzbFVDBg4cCLVa7ZRtW/9z6SptCADffPMNcnJyGv1uAi2zDW/XP7SU7yIDKyen0WgwaNAgizRtamoqhg8f7qBaNZ0QAgsWLMDWrVvx9ddfIzAwsNHnXL58GWfPnoWvr68CNbS/yspKnDx5Er6+vnIK3rQ9q6qqsH//fqdrz6SkJPj4+GDixIl3LOfs7WdNmw0aNAhqtdqsTEFBAbKzs52mXY1BVW5uLnbv3o3OnTs3+pzjx4+jurraKdu2/ufSFdrQaNOmTRg0aBBCQkIaLduS2rCx/qHFfBftMgWeHGrLli1CrVaLTZs2iRMnToglS5YIT09Pcfr0aUdXzWbz5s0TOp1O7Nu3TxQUFMiP69evCyGEKC8vF/Hx8eLgwYMiLy9P7N27VwwbNkx069ZNlJWVObj21omPjxf79u0Tv/zyi0hPTxcRERGiffv2cnutXr1a6HQ6sXXrVnHs2DExY8YM4evr6zTXJ4QQNTU1IiAgQDz33HNmx521/crLy0VmZqbIzMwUAERiYqLIzMyU74izps2eeeYZ4efnJ3bv3i0yMjLE6NGjRUhIiLhx44ajLsvMna6xurpaTJ48Wfj5+YmsrCyz72ZlZaUQQoiffvpJrFixQhw+fFjk5eWJnTt3invvvVcMGDCgRVzjna7P2s+lM7ehUWlpqWjbtq145513LJ7f0tuwsf5BiJbxXWRg5SLeeust0b17d6HRaMTAgQPNlidwJgAafCQlJQkhhLh+/boICwsTXbp0EWq1WgQEBIjo6GiRn5/v2IrbYPr06cLX11eo1WphMBjElClTxPHjx+XztbW1IiEhQej1eqHVasXDDz8sjh075sAa2+6rr74SAEROTo7ZcWdtv7179zb4uYyOjhZCWNdmv/32m1iwYIHw8vISHh4eIiIiokVd952uMS8v77bfzb179wohhMjPzxcPP/yw8PLyEhqNRvTs2VMsWrRIXL582bEXdsudrs/az6Uzt6HRxo0bhYeHhygpKbF4fktvw8b6ByFaxndRulVZIiIiIrpLnGNFREREZCcMrIiIiIjshIEVERERkZ0wsCIiIiKyEwZWRERERHbCwIqIiIjIThhYEREREdkJAysiohYgJiYGjz32mKOrQUR3iYEVEbUaMTExkCQJkiTB3d0dAQEBmDdvnsWGrERETcXAiohalXHjxqGgoACnT5/Ge++9h88//xzPPvuso6tFRC6CgRURtSparRZ6vR5+fn4ICwvD9OnTsWvXLgBAbW0tVq5cCT8/P2i1Wtx///1ISUmRn7tv3z5IkoSSkhL5WFZWFiRJwunTpwEAmzdvRseOHfHVV1+hb9++aNeunRzMGdXU1CAuLg4dO3ZE586d8de//hX1dxf79NNPERwcDA8PD3Tu3BljxozBtWvXmu8PQ0R2wcCKiFqtX375BSkpKVCr1QCAN954A2vXrsWaNWvwww8/IDw8HJMnT0Zubq5Nr3v9+nWsWbMG//rXv5CWlob8/HwsXbpUPr927Vq8//772LRpEw4cOIArV65g27Zt8vmCggLMmDEDc+bMwcmTJ7Fv3z5MmTLFIvgiopbH3dEVICJS0hdffIF27dqhpqYGFRUVAIDExEQAwJo1a/Dcc88hMjISAPDqq69i7969eP311/HWW29Z/R7V1dXYsGEDevbsCQBYsGABVq5cKZ9//fXXsWzZMkydOhUAsGHDBnz11Vfy+YKCAty4cQNTpkxB9+7dAQDBwcF3cdVEpBRmrIioVRk1ahSysrJw6NAhLFy4EOHh4Vi4cCHKyspw4cIFhIaGmpUPDQ3FyZMnbXqPtm3bykEVAPj6+qKoqAgAUFpaioKCAgwbNkw+7+7ujsGDB8u/h4SE4JFHHkFwcDCmTZuGd999lxPsiZwEAysialU8PT3Rq1cv3HfffXjzzTdRWVmJFStWyOclSTIrL4SQj6lUKvmYUXV1tcV7GIcWTV/TlmE8Nzc3pKam4r///S/69euHdevWoU+fPsjLy7P6NYjIMRhYEVGrlpCQgDVr1uDq1aswGAw4cOCA2fmDBw+ib9++AIAuXboAgNlE9KysLJveT6fTwdfXF+np6fKxGzdu4MiRI2blJElCaGgoVqxYgczMTGg0GrN5WETUMnGOFRG1aiNHjkT//v3xyiuv4C9/+QsSEhLQs2dP3H///UhKSkJWVhaSk5MBAL169YK/vz+WL1+Ol19+Gbm5uVi7dq3N77l48WKsXr0avXv3Rt++fZGYmGh2p+GhQ4ewZ88ehIWFwcfHB4cOHcKlS5fkAI+IWi4GVkTU6sXFxWH27Nk4deoUysrKEB8fj6KiIvTr1w87duxA7969Adwc4vv4448xb948hISEYMiQIXj55Zcxbdo0m94vPj4eBQUFiImJgUqlwpw5c/D444+jtLQUANChQwekpaXh9ddfR1lZGbp37461a9di/Pjxdr92IrIvSfD+XSIiIiK74BwrIiIiIjthYEVERERkJwysiIiIiOyEgRURERGRnTCwIiIiIrITBlZEREREdsLAioiIiMhOGFgRERER2QkDKyIiIiI7YWBFREREZCcMrIiIiIjshIEVERERkZ38P2V0V53+BIMSAAAAAElFTkSuQmCC\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "length = len(opponent_results[np.argmax(adversary_probabilities)])\n",
+ "average = [0] * length\n",
+ "for index, adversary_probability in enumerate(adversary_probabilities):\n",
+ " if adversary_probability > 0:\n",
+ " average += adversary_probability * np.array(opponent_results[index])\n",
+ "plt.title(\"Average payoff over the rounds\")\n",
+ "plt.xlabel(\"Rounds\")\n",
+ "plt.ylabel(\"Payoff at the end of each round\")\n",
+ "plt.plot(average)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "name = \"\"\n",
+ "for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " if name != \"\":\n",
+ " name += \"_\"\n",
+ " name += str(adversary_probabilities[index]) + \"_\" + adversary.name"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "excel_name = name + \".xlsx\"\n",
+ "writer = pd.ExcelWriter(excel_name, engine='xlsxwriter')\n",
+ "for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " df = pd.DataFrame(opponent_results[index])\n",
+ " name = \"Payoff against \" + adversary.name\n",
+ " df.to_excel(writer, sheet_name= name, index=False)\n",
+ "writer.save()\n",
+ "Qtable.save(name)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# We now have the trained agent. We want to test it against each opponent individually, so that\n",
+ "# we can compare it against the agent that is just trained against this opponent."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Adversary Name: imitation_132\n",
+ "Agent Payoff: 116374.0 Adversary Payoff: 66286.0\n",
+ "Agent Actions: [118 132 115 118 107 114 107 104 91 90 99 90 91 87 94 87 92 95\n",
+ " 94 90 91 98 110 122 126]\n",
+ "Adversary Actions: [132 118 132 115 118 107 114 107 104 91 90 99 90 91 87 94 87 92\n",
+ " 95 94 90 91 98 110 122]\n",
+ "Agent Demand Potential: [200. 207. 200. 208. 206. 211. 207. 210. 211. 217. 217. 212. 216. 215.\n",
+ " 217. 213. 216. 213. 211. 211. 213. 212. 208. 202. 196.]\n",
+ "Adversary Name: guess_132\n",
+ "Agent Payoff: 139655.0 Adversary Payoff: 92413.0\n",
+ "Agent Actions: [118 132 132 132 132 132 132 132 132 132 132 132 132 132 128 128 124 123\n",
+ " 123 123 123 124 124 112 135]\n",
+ "Adversary Actions: [132 132 132 132 132 132 132 132 132 132 132 132 132 132 132 124 124 124\n",
+ " 124 124 124 124 124 124 129]\n",
+ "Agent Demand Potential: [200. 207. 207. 207. 207. 207. 207. 207. 207. 207. 207. 207. 207. 207.\n",
+ " 207. 209. 207. 207. 207. 207. 207. 207. 207. 207. 213.]\n"
+ ]
+ }
+ ],
+ "source": [
+ "for index, adversary in enumerate(AdversaryModes):\n",
+ " if adversary_probabilities[index] > 0:\n",
+ " new_adversary_probabilities =[0]*len(AdversaryModes)\n",
+ " new_adversary_probabilities[index] = 1\n",
+ " result = Test(game, Qtable, discount_factor, new_adversary_probabilities)\n",
+ " payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " print(\"Adversary Name:\", adversary.name)\n",
+ " print(\"Agent Payoff:\", payoff, \"Adversary Payoff:\", adversary_payoff)\n",
+ " print(\"Agent Actions:\", actions)\n",
+ " print(\"Adversary Actions:\", adversary_actions)\n",
+ " print(\"Agent Demand Potential:\", demand_potential)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Memory_and_epsilon_greedy/test.py b/qLearning/Memory_and_epsilon_greedy/test.py
new file mode 100644
index 0000000..b9f1168
--- /dev/null
+++ b/qLearning/Memory_and_epsilon_greedy/test.py
@@ -0,0 +1,168 @@
+# Ed, Galit and Katerina
+# Relates to the Q-Learning approach.
+# Testing out the Q-table against a given opponent
+
+import numpy as np
+from environment import AdversaryModes
+import matplotlib.pyplot as plt
+
+
+class Test():
+
+
+ def __init__(self, Model, Qtable, discount_factor, adversary_probabilities) -> None:
+
+
+ self.env = Model
+ self.Qtable = Qtable.Q_table
+ self.number_demands=Qtable.number_demands
+ self.highest_demand = self.number_demands - 1
+ self.number_actions=Qtable.number_actions
+ self.number_stages=Qtable.number_stages
+ self.discount_factor = discount_factor
+ self.adversary_probabilities = adversary_probabilities
+ self.adversary = None
+
+
+
+ def set_adversary(self):
+ options = list(range(len(self.adversary_probabilities)))
+ adversary_index = int(np.random.choice(options, 1, p= self.adversary_probabilities))
+ self.adversary = AdversaryModes(adversary_index)
+ new_probabilities = [0]*len(self.adversary_probabilities)
+ new_probabilities[adversary_index] = 1
+ self.env.adversary_probabilities = new_probabilities
+
+
+ def total_payoff(self):
+
+ self.set_adversary()
+
+ delta = 1
+ utility = 0
+ adversary_utility = 0
+ actions = [0]*self.number_stages
+ adversary_actions = [0]*self.number_stages
+ demands = [0]*self.number_stages
+ state_vector, reward, done = self.env.reset()
+ demand = state_vector[1]
+ previous_action = state_vector[2]
+
+ for stage in range(self.number_stages):
+ demands[stage] = demand
+ if demand >= self.number_demands:
+ print("max demand reached")
+ demand = self.number_demands - 1
+ if demand < 0:
+ print("min demand reached")
+ demand = 0
+ demand_index = int(demand)
+ action_index = np.argmax(self.Qtable[demand_index, :, previous_action, stage])
+ action = action_index + int((demand + self.env.costs[0])/2) - self.number_actions + 1
+ actions[stage] = action
+ utility += (demand-action)*(action-self.env.costs[0]) * delta
+ adversary_demand = 400 - demand
+ state_vector, _, _ = self.env.step(state_vector, action, action_index)
+ demand = state_vector[1]
+ previous_action = state_vector[2]
+ adversary_actions[stage] = state_vector[3]
+ adversary_utility += (adversary_demand-adversary_actions[stage])*(adversary_actions[stage]-self.env.costs[1]) * delta
+ delta *= self.discount_factor
+ return utility, adversary_utility, np.transpose(actions), np.transpose(adversary_actions), np.transpose(demands)
+
+
+ def q_learning(self, state_action_value, optimal_next_value, reward, alpha, gamma):
+ target = reward + gamma * optimal_next_value
+ return state_action_value + alpha * (target - state_action_value)
+
+ def random_policy(self, monopoly_price):
+ random_action = np.random.randint(monopoly_price-self.number_actions+1, monopoly_price + 1)
+ if random_action < 0:
+ random_action = max(0, random_action)
+ if self.env.costs[0] > random_action:
+ random_action = monopoly_price
+ return random_action
+
+ def action_index(self, monopoly_price, action): # computes action index in Qtable
+ return int(action - (monopoly_price - self.number_actions + 1)) #monopoly_price should have index number_actions - 1
+
+
+ def error(self, number_tests):
+
+
+
+ errors = list()
+
+ for test in range(number_tests):
+
+ self.set_adversary()
+
+ state, reward, done = self.env.reset()
+
+ while not done:
+ stage, agent_demand, agent_previous_action, adversary_previous_action = state
+ if (agent_demand < 0) or (agent_demand > self.highest_demand):
+ break
+ if (stage > 0 and adversary_previous_action < self.env.costs[1]) or (self.highest_demand - agent_demand < adversary_previous_action):
+ break
+ monopoly_price = int((agent_demand + self.env.costs[0]) / 2)
+ action = self.random_policy(monopoly_price)
+ demand_index = int(agent_demand)
+ action_index = self.action_index(monopoly_price, action)
+ state, reward, done = self.env.step(state, action, action_index)
+
+ if done:
+ optimal_next_value = 0
+ else:
+ optimal_next_value = max(self.Qtable[int(state[1]),:, action_index, state[0]])
+
+ new_value = reward + self.discount_factor * optimal_next_value
+ current_q_value = self.Qtable[demand_index, action_index, agent_previous_action, stage]
+
+ if new_value != 0:
+ errors.append((new_value - current_q_value)/new_value)
+
+# if new_value == 0 and current_q_value != 0:
+# print("Division by zero error")
+
+ error_array = np.array(errors)
+# plt.plot(error_array)
+ return error_array.mean()
+
+
+
+
+# def myopic(self, cost, demand):
+# return (cost + demand)/2
+
+# def payoff(self, cost, demand, price):
+# return (demand - price)*(price - cost)
+
+# def update_demand(self, demand, price_pair):
+# new_demand = demand + 0.5*(price_pair[1]- price_pair[0])
+# return new_demand
+
+# def utility_of_actions(self, actions):
+# agent_demand = 200
+# opponent_demand = 200
+# total_payoff = 0
+# delta = 1/self.discount_factor
+# for i in range(self.number_stages):
+# delta = delta * self.discount_factor
+# agent_price = int(actions[i])
+# opponent_price = int(self.myopic(self.env.costs[1],opponent_demand))
+# total_payoff += self.payoff(self.env.costs[0],agent_demand,agent_price) * delta
+# agent_demand = int(self.update_demand(agent_demand, [agent_price,opponent_price]))
+# opponent_demand = 400 - agent_demand
+# return total_payoff
+
+
+
+
+
+
+
+
+
+
+
diff --git a/qLearning/Memory_and_epsilon_greedy/~$0.5_imitation_132_0.5_guess_132.xlsx b/qLearning/Memory_and_epsilon_greedy/~$0.5_imitation_132_0.5_guess_132.xlsx
new file mode 100644
index 0000000..300d8a2
Binary files /dev/null and b/qLearning/Memory_and_epsilon_greedy/~$0.5_imitation_132_0.5_guess_132.xlsx differ
diff --git a/qLearning/Programmed_adversary/.DS_Store b/qLearning/Programmed_adversary/.DS_Store
new file mode 100644
index 0000000..4bb7591
Binary files /dev/null and b/qLearning/Programmed_adversary/.DS_Store differ
diff --git a/qLearning/Programmed_adversary/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb b/qLearning/Programmed_adversary/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
new file mode 100644
index 0000000..d4e4c89
--- /dev/null
+++ b/qLearning/Programmed_adversary/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
@@ -0,0 +1,304 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_Demand = 400\n",
+ "agent_Cost = 57\n",
+ "adv_Cost = 71 \n",
+ "tuple_Costs = [57,71]\n",
+ "total_Stages = 25\n",
+ "init_State = [total_Demand/2, total_Demand/2]\n",
+ "adversaryProbs=[0]*len(AdversaryModes)\n",
+ "adversaryProbs[0]=1 # We only train against strategies that do not take into account the \n",
+ "# previous actions (myopic or constant strategies).\n",
+ "\n",
+ "game = Model(total_Demand, [agent_Cost,adv_Cost], total_Stages, adversaryProbs)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "num_Actions = 100\n",
+ "num_States = abs(adv_Cost - agent_Cost) + 2 * num_Actions + 2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+demoninator)\n",
+ "Qtable = QTable(num_States, num_Actions, learning_Rate = [490000,500000])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "numberEpisodes = 50_000_000\n",
+ "discountFactor = 0.99"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, numberEpisodes, discountFactor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "algorithm.solver()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# print(Qtable.Q_table)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Qtable.Q_table.mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversaryProbs=[0]*len(AdversaryModes)\n",
+ "adversaryProbs[0]=1 # We can test the Q-Table against any strategy. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "result = Test(game, Qtable, discountFactor, adversaryProbs)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# The following plots what the Q-Table says is the best action in each state\n",
+ "states, bestResponses = result.bestResponses()\n",
+ "plt.scatter(states,bestResponses)\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "156565.81231610497\n",
+ "34811.141650098594\n",
+ "[ 81 98 96 107 102 104 111 104 111 104 111 104 111 104 111 104 111 104\n",
+ " 111 104 111 104 111 104 111]\n",
+ "[135 122 116 111 110 108 107 108 107 108 107 108 107 108 107 108 107 108\n",
+ " 107 108 107 108 107 108 107]\n",
+ "[200. 227. 239. 249. 251. 255. 257. 255. 257. 255. 257. 255. 257. 255.\n",
+ " 257. 255. 257. 255. 257. 255. 257. 255. 257. 255. 257.]\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Returns the optimal payoff and actions according to the Qtable\n",
+ "payoff, advPayoff, actions, advActions, demandPotential = result.totalPayoff()\n",
+ "print(payoff)\n",
+ "print(advPayoff)\n",
+ "print(actions)\n",
+ "print(advActions)\n",
+ "print(demandPotential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The percentage error of the Qtable. This has to be measured against the same opponent that \n",
+ "# it was trained against, as this is a measure of how 'complete' the training is.\n",
+ "error = result.error()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.0004667063216408303"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "error.mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "AdversaryModes.myopic\n",
+ "156565.81231610497\n",
+ "AdversaryModes.constant_132\n",
+ "238979.07730435894\n",
+ "AdversaryModes.constant_95\n",
+ "97548.1311417851\n",
+ "AdversaryModes.imitation_132\n",
+ "98608.19311004323\n",
+ "AdversaryModes.imitation_128\n",
+ "97616.47326097779\n",
+ "AdversaryModes.fight_132\n",
+ "5607.470996872076\n",
+ "AdversaryModes.fight_lb_132\n",
+ "68472.91531876566\n",
+ "AdversaryModes.fight_125\n",
+ "12209.252537274462\n",
+ "AdversaryModes.fight_lb_125\n",
+ "68564.37203485591\n",
+ "AdversaryModes.fight_100\n",
+ "53097.6966852822\n",
+ "AdversaryModes.guess_132\n",
+ "5607.470996872076\n",
+ "AdversaryModes.guess_125\n",
+ "12209.252537274462\n"
+ ]
+ }
+ ],
+ "source": [
+ "# The following calculates the payoff that the Q-Table gives against the different opponenets. \n",
+ "# It may reach a state in which the Q-Table was not trained. This will cause an error saying \n",
+ "# either 'max action reached' or 'min action reached'.\n",
+ "for i in range(len(AdversaryModes)):\n",
+ " print(AdversaryModes(i))\n",
+ " adversaryProbs=[0]*len(AdversaryModes)\n",
+ " adversaryProbs[i]=1\n",
+ " result = Test(game, Qtable, discountFactor, adversaryProbs)\n",
+ " payoff, advPayoff, actions, advActions, demandPotential = result.totalPayoff()\n",
+ " print(payoff)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Programmed_adversary/Qtable.py b/qLearning/Programmed_adversary/Qtable.py
new file mode 100644
index 0000000..35ea4a4
--- /dev/null
+++ b/qLearning/Programmed_adversary/Qtable.py
@@ -0,0 +1,30 @@
+# Ed, Galit and Katerina
+# Relates to the Q-Learning approach.
+# Defines the Q-table
+
+import numpy as np
+
+class QTable():
+
+
+ def __init__(self, num_States, num_Actions, learning_Rate):
+
+ self.num_States= num_States
+ self.num_Actions = num_Actions
+ self.learning_Rate = learning_Rate
+ self.Q_table = np.zeros((self.num_States, self.num_Actions))
+ self.QTable_name=f"QTable, actions={self.num_Actions}, states={self.num_States}"
+
+
+ def reset(self):
+ Qtable = np.zeros((self.num_States, self.num_Actions))
+ return Qtable, self.learning_rate
+
+
+ def randomReset(self):
+ randQtable = np.random.rand(self.num_States,self.num_Actions)
+ return randQtable, self.learning_rate
+
+
+
+
diff --git a/qLearning/Programmed_adversary/Test_Qlearning.xlsx b/qLearning/Programmed_adversary/Test_Qlearning.xlsx
new file mode 100644
index 0000000..4e5238b
Binary files /dev/null and b/qLearning/Programmed_adversary/Test_Qlearning.xlsx differ
diff --git a/qLearning/Programmed_adversary/__pycache__/Qtable.cpython-39.pyc b/qLearning/Programmed_adversary/__pycache__/Qtable.cpython-39.pyc
new file mode 100644
index 0000000..53e04e8
Binary files /dev/null and b/qLearning/Programmed_adversary/__pycache__/Qtable.cpython-39.pyc differ
diff --git a/qLearning/Programmed_adversary/__pycache__/environment.cpython-39.pyc b/qLearning/Programmed_adversary/__pycache__/environment.cpython-39.pyc
new file mode 100644
index 0000000..bf3091d
Binary files /dev/null and b/qLearning/Programmed_adversary/__pycache__/environment.cpython-39.pyc differ
diff --git a/qLearning/Programmed_adversary/__pycache__/learningAgent.cpython-39.pyc b/qLearning/Programmed_adversary/__pycache__/learningAgent.cpython-39.pyc
new file mode 100644
index 0000000..d129f51
Binary files /dev/null and b/qLearning/Programmed_adversary/__pycache__/learningAgent.cpython-39.pyc differ
diff --git a/qLearning/Programmed_adversary/__pycache__/test.cpython-39.pyc b/qLearning/Programmed_adversary/__pycache__/test.cpython-39.pyc
new file mode 100644
index 0000000..3efa999
Binary files /dev/null and b/qLearning/Programmed_adversary/__pycache__/test.cpython-39.pyc differ
diff --git a/qLearning/Programmed_adversary/environment.py b/qLearning/Programmed_adversary/environment.py
new file mode 100644
index 0000000..69c4548
--- /dev/null
+++ b/qLearning/Programmed_adversary/environment.py
@@ -0,0 +1,267 @@
+# Katerina, Ed and Galit (and Tommy!)
+# Relates to the Q-Learning approach.
+# Contains DemandPotentialGame Class and the Model of the DemandPotentialGame Class.
+
+from enum import Enum
+import numpy as np # numerical python
+# printoptions: output limited to 2 digits after decimal point
+np.set_printoptions(precision=2, suppress=False)
+
+
+class DemandPotentialGame():
+ """
+ Fully defines demand Potential Game. It contains game rules, memory and agents strategies.
+ """
+
+ def __init__(self, totalDemand, tupleCosts, totalStages) -> None:
+ self.totalDemand = totalDemand
+ self.costs = tupleCosts
+ self.T = totalStages
+ # first index is always player
+ self.demandPotential = None # two lists for the two players
+ self.prices = None # prices over T rounds
+ self.profit = None # profit in each of T rounds
+ self.stage = None
+
+ def resetGame(self):
+ """
+ Method resets game memory: Demand Potential, prices, profits
+ """
+ self.demandPotential = [[0]*(self.T), [0]*(self.T)] # two lists for the two players
+ self.prices = [[0]*self.T, [0]*self.T] # prices over T rounds
+ self.profit = [[0]*self.T, [0]*self.T] # profit in each of T rounds
+ self.demandPotential[0][0] = self.totalDemand / 2 # initialise first round 0
+ self.demandPotential[1][0] = self.totalDemand/2
+
+ def profits(self, player=0):
+ """
+ Computes profits. Player 0 is the learning agent.
+ """
+ return self.profit[player][self.stage]
+
+ def updatePricesProfitDemand(self, pricePair):
+ """
+ Updates Prices, Profit and Demand Potential Memory.
+ Parameters.
+ pricePair: Pair of prices from the Learning agent and adversary.
+ """
+
+ for player in [0, 1]:
+ price = int(pricePair[player])
+ self.prices[player][self.stage] = price
+ self.profit[player][self.stage] = int((
+ self.demandPotential[player][self.stage] - price)*(price - self.costs[player]))
+ if self.stage < self.T-1:
+ self.demandPotential[0][self.stage + 1] = \
+ int(self.demandPotential[0][self.stage] + (pricePair[1] - pricePair[0])/2)
+ self.demandPotential[1][self.stage + 1] = 400 - self.demandPotential[0][self.stage + 1]
+
+# print(self.prices[0][self.stage],self.prices[1][self.stage],self.profit[0][self.stage], \
+# self.profit[1][self.stage],self.demandPotential[0][self.stage], \
+# self.demandPotential[1][self.stage])
+
+ def monopolyPrice(self, player, t): # myopic monopoly price
+ """
+ Computes Monopoly prices.
+ """
+ return (self.demandPotential[player][self.stage] + self.costs[player])/2
+
+ def myopic(self, player=0):
+ """
+ Adversary follows Myopic strategy
+ """
+ return self.monopolyPrice(player, self.stage)
+
+ def const(self, player, price): # constant price strategy
+ """
+ Adversary follows Constant strategy
+ """
+ if self.stage == self.T-1:
+ return self.monopolyPrice(player, self.stage)
+ return price
+
+ def imit(self, player, firstprice): # price imitator strategy
+ if self.stage == 0:
+ return firstprice
+ if self.stage == self.T-1:
+ return self.monopolyPrice(player, self.stage)
+ return self.prices[1-player][self.stage-1]
+
+ def fight(self, player, firstprice): # simplified fighting strategy
+ if self.stage == 0:
+ return firstprice
+ if self.stage == self.T-1:
+ return self.monopolyPrice(player, self.stage)
+ # aspire = [ 207, 193 ] # aspiration level for demand potential
+ aspire = [0, 0]
+ for i in range(2):
+ aspire[i] = (self.totalDemand-self.costs[player] +
+ self.costs[1-player])/2
+
+ D = self.demandPotential[player][self.stage]
+ Asp = aspire[player]
+ if D >= Asp: # keep price; DANGER: price will never rise
+ return self.prices[player][self.stage-1]
+ # adjust to get to aspiration level using previous
+ # opponent price; own price has to be reduced by twice
+ # the negative amount D - Asp to getself.demandPotential to Asp
+ P = self.prices[1-player][self.stage-1] + 2*(D - Asp)
+ # never price to high because even 125 gives good profits
+ # P = min(P, 125)
+ aspire_price = (self.totalDemand+self.costs[0]+self.costs[1])/4
+ P = min(P, int(0.95*aspire_price))
+
+ return P
+
+ def fight_lb(self, player, firstprice):
+ P = self.fight(player, firstprice)
+ # never price less than production cost
+ P = max(P, self.costs[player])
+ return P
+
+ # sophisticated fighting strategy, compare fight()
+ # estimate *sales* of opponent as their target, kept between
+ # calls in global variable oppsaleguess[]. Assumed behavior
+ # of opponent is similar to this strategy itself.
+ oppsaleguess = [61, 75] # first guess opponent sales as in monopoly
+
+ def guess(self, player, firstprice): # predictive fighting strategy
+ if self.stage == 0:
+ self.oppsaleguess[0] = 61 # always same start
+ self.oppsaleguess[1] = 75 # always same start
+ return firstprice
+
+ if self.stage == self.T-1:
+ return self.monopolyPrice(player, self.stage)
+ aspire = [207, 193] # aspiration level
+ D = self.demandPotential[player][self.stage]
+ Asp = aspire[player]
+
+ if D >= Asp: # keep price, but go slightly towards monopoly if good
+ pmono = self.monopolyPrice(player, self.stage)
+ pcurrent = self.prices[player][self.stage-1]
+ if pcurrent > pmono: # shouldn't happen
+ return pmono
+ if pcurrent > pmono-7: # no change
+ return pcurrent
+ # current low price at 60%, be accommodating towards "collusion"
+ return .6 * pcurrent + .4 * (pmono-7)
+
+ # guess current *opponent price* from previous sales
+ prevsales = self.demandPotential[1 - player][t-1] - self.prices[1-player][t-1]
+ # adjust with weight alpha from previous guess
+ alpha = .5
+ newsalesguess = alpha * self.oppsaleguess[player] + (1-alpha)*prevsales
+ # update
+ self.oppsaleguess[player] = newsalesguess
+ guessoppPrice = 400 - D - newsalesguess
+ P = guessoppPrice + 2*(D - Asp)
+
+ if player == 0:
+ P = min(P, 125)
+ if player == 1:
+ P = min(P, 130)
+ return P
+
+
+class Model(DemandPotentialGame):
+ """
+ Defines the Problem's Model. It is assumed a Markov Decision Process is defined. The class is a Child from the Demand Potential Game Class.
+ The reason: Model is a conceptualization of the Game.
+ """
+
+ def __init__(self, totalDemand, tupleCosts, totalStages, adversaryProbs) -> None:
+ super().__init__(totalDemand, tupleCosts, totalStages)
+
+ self.rewardFunction = self.profits
+
+ # [stage, agent's demand potential, adv previous action]
+ self.initState = [0, totalDemand/2, 0]
+ self.episodesMemory = list()
+ self.done = False
+ self.adversaryProbs = adversaryProbs
+
+ def reset(self):
+ """
+ Reset Model Instantiation.
+ """
+ reward = 0
+ self.stage = 0
+ self.done = False
+ self.resetGame()
+ self.resetAdversary()
+ return self.initState, reward, self.done
+
+ def resetAdversary(self):
+ options = list(range(len(self.adversaryProbs)))
+ adversaryIndex = np.random.choice(options, 1, p= self.adversaryProbs)
+ self.adversaryMode = AdversaryModes(adversaryIndex)
+
+ def adversaryChoosePrice(self):
+ """
+ Strategy followed by the adversary.
+ """
+
+ if self.adversaryMode == AdversaryModes.constant_132:
+ return self.const(player=1, price=132)
+ elif self.adversaryMode == AdversaryModes.constant_95:
+ return self.const(player=1, price=95)
+ elif self.adversaryMode == AdversaryModes.imitation_128:
+ return self.imit(player=1, firstprice=128)
+ elif self.adversaryMode == AdversaryModes.imitation_132:
+ return self.imit(player=1, firstprice=132)
+ elif self.adversaryMode == AdversaryModes.fight_100:
+ return self.fight(player=1, firstprice=100)
+ elif self.adversaryMode == AdversaryModes.fight_125:
+ return self.fight(player=1, firstprice=125)
+ elif self.adversaryMode == AdversaryModes.fight_lb_125:
+ return self.fight_lb(player=1, firstprice=125)
+ elif self.adversaryMode == AdversaryModes.fight_132:
+ return self.fight(player=1, firstprice=132)
+ elif self.adversaryMode == AdversaryModes.fight_lb_132:
+ return self.fight_lb(player=1, firstprice=132)
+ elif self.adversaryMode == AdversaryModes.guess_125:
+ return self.fight(player=1, firstprice=125)
+ elif self.adversaryMode == AdversaryModes.guess_132:
+ return self.fight(player=1, firstprice=132)
+ else:
+ return self.myopic(player=1)
+
+ def step(self, state, action):
+ """
+ Transition Function.
+ Parameters:
+ - action: Price
+ - state: tupple in the latest stage (stage ,Demand Potential, Adversary's prev price)
+ """
+ adversaryAction = int(self.adversaryChoosePrice())
+ self.updatePricesProfitDemand([action, adversaryAction])
+
+
+ done = (self.stage == self.T-1)
+
+
+ if not done:
+ newState = [self.stage+1, self.demandPotential[0][self.stage + 1], adversaryAction]
+ else:
+ newState = [self.stage+1, 0, adversaryAction]
+
+ reward = self.rewardFunction()
+ self.stage = self.stage + 1
+
+ return newState, reward, done
+
+
+class AdversaryModes(Enum):
+ myopic = 0
+ constant_132 = 1
+ constant_95 = 2
+ imitation_132 = 3
+ imitation_128 = 4
+ fight_132 = 5
+ fight_lb_132 = 6
+ fight_125 = 7
+ fight_lb_125 = 8
+ fight_100 = 9
+ guess_132 = 10
+ guess_125 = 11
\ No newline at end of file
diff --git a/qLearning/Programmed_adversary/learningAgent.py b/qLearning/Programmed_adversary/learningAgent.py
new file mode 100644
index 0000000..6264266
--- /dev/null
+++ b/qLearning/Programmed_adversary/learningAgent.py
@@ -0,0 +1,79 @@
+# Ed, Kat, Galit
+# ReinforceAlgorithm Class: Solver.
+
+import numpy as np #repeated
+
+# printoptions: output limited to 2 digits after decimal point
+np.set_printoptions(precision=2, suppress=False)
+
+
+class LearningAlgorithm():
+ """
+ Model Solver.
+ """
+ def __init__(self, Model, Qtable, numberEpisodes, discountFactor) -> None:
+
+ self.env = Model
+ self.Qtable = Qtable.Q_table
+ self.learning_Rate = Qtable.learning_Rate
+ self.numberEpisodes = numberEpisodes
+ self.gamma = discountFactor
+ self.numStates=Qtable.num_States #Qtable dimen - number of states x number of actions
+ if self.numStates % 2 ==1 :
+ print('num of states should be even')
+ self.numActions=Qtable.num_Actions
+ if self.numActions % 2 ==1 :
+ print('num of actions should be even')
+ self.lowestState = int(200-(self.numStates)/2) # Should already be int
+ self.highestState = int(200+(self.numStates)/2 - 1) # Should already be int
+
+
+ def resetQtable(self):
+ self.Qtable, self.learning_Rate = self.Qtable.reset()
+
+ """
+ This function will eventually choose and adversary agent to play against
+ and according to that return an action played by that adversary.
+ This could be chosen according to some existing equilibruim dist.
+ """
+ def chooseAdver(self, state):
+ return int((400 - state + self.env.costs[1])/2) #myopic
+
+ def StateInd(self, state): # computes state index in Qtable
+ return int(state - self.lowestState)
+ #return min(int(state -(200-self.numStates/2)), self.numStates - 1)
+
+ def ActionInd(self, monPrice, action): # computes action index in Qtable
+ return int(action - (monPrice - self.numActions + 1)) #monPrice should have index numActions - 1
+
+ def alpha_n(self, n): # defines the Qlearning rate
+ return self.learning_Rate[0]/(n+self.learning_Rate[1])
+ """
+ Now the Q-learning itself
+ """
+ def solver(self):
+
+ self.resetQtable
+
+ for episode in range(self.numberEpisodes):
+
+ state = np.random.randint(self.lowestState, self.highestState + 1)
+ monPrice = int((state + self.env.costs[0]) / 2)
+ action = np.random.randint(monPrice-self.numActions+1, monPrice + 1)
+ advAction = self.chooseAdver(state)
+ reward = (state-action)*(action-self.env.costs[0])
+
+ next_state = int(state+.5*(advAction-action))
+
+ opt_value_next = max(self.Qtable[self.StateInd(next_state)])
+
+
+ # updating the Qtable
+ qvalue = (1-self.alpha_n(episode)) * \
+ self.Qtable[self.StateInd(state), self.ActionInd(monPrice, action)]\
+ + self.alpha_n(episode) * \
+ ((1-self.gamma)*reward + self.gamma*opt_value_next)
+ self.Qtable[self.StateInd(state), self.ActionInd(monPrice, action)]=qvalue
+
+
+
diff --git a/qLearning/Programmed_adversary/main.py b/qLearning/Programmed_adversary/main.py
new file mode 100644
index 0000000..4ed4821
--- /dev/null
+++ b/qLearning/Programmed_adversary/main.py
@@ -0,0 +1,67 @@
+from learningAgent import LearningAlgorithm
+from environment import Model, AdversaryModes
+import numpy as np
+
+np.random.seed(10)
+agent_cost = 57
+adv_cost = 71
+
+game = Model(totalDemand = 400,
+ tupleCosts = (agent_cost, adv_cost),
+ totalStages = 25,
+ initState = [400/2,0], adversaryMode=AdversaryModes.myopic)
+
+num_Actions = 50
+num_States = abs(adv_cost - agent_cost) + 2 * num_Actions + 2
+gamma = 0.99
+
+
+Qtable = np.zeros((num_States, num_Actions))
+Qtable_error = np.zeros((num_States, num_Actions))
+
+algorithm = LearningAlgorithm(game, Qtable, numberEpisodes = 10000, discountFactor = gamma)
+
+algorithm.solver()
+
+def bestAction(Qtable, state):
+ row = Qtable[int(state -(200-self.numStates/2))]
+ action = np.argmax(row) + (state + agent_cost)/2- num_Actions+1
+ return action
+
+
+
+
+# printing Qtable for excel
+for s in range(num_States):
+ for a in range(num_Actions):
+ print("%.5f, " % Qtable[s,a], end="")
+ print("")
+
+# Checking the convergence of the Qtable
+
+for s in range(num_States):
+ for a in range(num_Actions):
+ lowestState = int(200-(num_States)/2)
+ highestState = int(200+(num_States)/2 - 1)
+ state = s + lowestState
+
+ monopoly_price = int((state + agent_cost)/2) + 1
+ action = a + monopoly_price - num_Actions + 1
+
+ reward = (state - action) * (action - agent_cost)
+ adv_action = int((400 -state + adv_cost)/2) + 1
+ next_state = int(state + (adv_action - action)/2)
+ #print(state,monopoly_price,action,reward,adv_action, next_state)
+
+ ns = next_state - lowestState
+ opt_value_next = max(Qtable[ns])
+ new_value = (1-gamma)*reward + gamma * opt_value_next
+ Qtable_error[s,a] = (new_value - Qtable[s,a])/new_value
+
+# Printing Qtable error
+for s in range(num_States):
+ for a in range(num_Actions):
+ #print(Qtable[s,a],",", end="")
+ print("%.5f, " % Qtable_error[s,a], end="")
+ print("")
+
diff --git a/qLearning/Programmed_adversary/qLearningSimulations.ipynb b/qLearning/Programmed_adversary/qLearningSimulations.ipynb
new file mode 100644
index 0000000..7b48c01
--- /dev/null
+++ b/qLearning/Programmed_adversary/qLearningSimulations.ipynb
@@ -0,0 +1,708 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_Demand = 400\n",
+ "agent_Cost = 57\n",
+ "adv_Cost = 71 \n",
+ "tuple_Costs = [57,71]\n",
+ "total_Stages = 25\n",
+ "init_State = [total_Demand/2, total_Demand/2]\n",
+ "adversaryProbs=[0]*len(AdversaryModes)\n",
+ "adversaryProbs[0]=1 # We only train against strategies that do not take into account the \n",
+ "# previous actions (myopic or constant strategies).\n",
+ "\n",
+ "game = Model(total_Demand, [agent_Cost,adv_Cost], total_Stages, adversaryProbs)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "num_Actions = 100\n",
+ "num_States = abs(adv_Cost - agent_Cost) + 2 * num_Actions + 2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+demoninator)\n",
+ "Qtable = QTable(num_States, num_Actions, learning_Rate = [490000,500000])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "numberEpisodes = 20_000_000\n",
+ "discountFactor = 0.99"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, numberEpisodes, discountFactor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "algorithm.solver()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# print(Qtable.Q_table)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Qtable.Q_table.mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversaryProbs=[0]*len(AdversaryModes)\n",
+ "adversaryProbs[0]=1 # We can test the Q-Table against any strategy. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "result = Test(game, Qtable, discountFactor, adversaryProbs)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# The following plots what the Q-Table says is the best action in each state\n",
+ "states, bestResponses = result.bestResponses()\n",
+ "plt.scatter(states,bestResponses)\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "43\n",
+ "46\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "49\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "156721.63152210606\n",
+ "35726.754399047146\n",
+ "[ 85 95 100 104 106 107 106 108 108 108 108 108 108 108 108 108 108 108\n",
+ " 108 108 108 108 108 108 108]\n",
+ "[135 123 116 112 110 109 108 108 108 108 108 108 108 108 108 108 108 108\n",
+ " 108 108 108 108 108 108 108]\n",
+ "[200. 225. 239. 247. 251. 253. 254. 255. 255. 255. 255. 255. 255. 255.\n",
+ " 255. 255. 255. 255. 255. 255. 255. 255. 255. 255. 255.]\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Returns the optimal payoff and actions according to the Qtable\n",
+ "payoff, advPayoff, actions, advActions, demandPotential = result.totalPayoff()\n",
+ "print(payoff)\n",
+ "print(advPayoff)\n",
+ "print(actions)\n",
+ "print(advActions)\n",
+ "print(demandPotential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The percentage error of the Qtable. This has to be measured against the same opponent that \n",
+ "# it was trained against, as this is a measure of how 'complete' the training is.\n",
+ "error = result.error()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1.2837417934833635e-05"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "error.mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "AdversaryModes.myopic\n",
+ "43\n",
+ "46\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "49\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "48\n",
+ "156721.63152210606\n",
+ "AdversaryModes.constant_132\n",
+ "43\n",
+ "44\n",
+ "46\n",
+ "48\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "max action reached\n",
+ "46\n",
+ "165719.01093671267\n",
+ "AdversaryModes.constant_95\n",
+ "43\n",
+ "46\n",
+ "45\n",
+ "46\n",
+ "43\n",
+ "46\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "98123.03551390873\n",
+ "AdversaryModes.imitation_132\n",
+ "43\n",
+ "44\n",
+ "46\n",
+ "44\n",
+ "46\n",
+ "45\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "95230.3363386929\n",
+ "AdversaryModes.imitation_128\n",
+ "43\n",
+ "46\n",
+ "46\n",
+ "45\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "46\n",
+ "94560.3473074055\n",
+ "AdversaryModes.fight_132\n",
+ "43\n",
+ "44\n",
+ "42\n",
+ "43\n",
+ "39\n",
+ "38\n",
+ "39\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "23414.509051166635\n",
+ "AdversaryModes.fight_lb_132\n",
+ "43\n",
+ "44\n",
+ "45\n",
+ "44\n",
+ "45\n",
+ "44\n",
+ "43\n",
+ "42\n",
+ "41\n",
+ "43\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "44\n",
+ "65713.83085811119\n",
+ "AdversaryModes.fight_125\n",
+ "43\n",
+ "47\n",
+ "43\n",
+ "41\n",
+ "41\n",
+ "42\n",
+ "40\n",
+ "38\n",
+ "39\n",
+ "38\n",
+ "37\n",
+ "40\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "25251.711150534007\n",
+ "AdversaryModes.fight_lb_125\n",
+ "43\n",
+ "47\n",
+ "45\n",
+ "43\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "45\n",
+ "78569.35520109691\n",
+ "AdversaryModes.fight_100\n",
+ "43\n",
+ "44\n",
+ "46\n",
+ "45\n",
+ "42\n",
+ "44\n",
+ "43\n",
+ "42\n",
+ "41\n",
+ "43\n",
+ "40\n",
+ "42\n",
+ "43\n",
+ "43\n",
+ "43\n",
+ "43\n",
+ "43\n",
+ "43\n",
+ "43\n",
+ "43\n",
+ "43\n",
+ "43\n",
+ "43\n",
+ "43\n",
+ "43\n",
+ "53761.456072040615\n",
+ "AdversaryModes.guess_132\n",
+ "43\n",
+ "44\n",
+ "42\n",
+ "43\n",
+ "39\n",
+ "38\n",
+ "39\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "23414.509051166635\n",
+ "AdversaryModes.guess_125\n",
+ "43\n",
+ "47\n",
+ "43\n",
+ "41\n",
+ "41\n",
+ "42\n",
+ "40\n",
+ "38\n",
+ "39\n",
+ "38\n",
+ "37\n",
+ "40\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "min action reached\n",
+ "37\n",
+ "25251.711150534007\n"
+ ]
+ }
+ ],
+ "source": [
+ "# The following calculates the payoff that the Q-Table gives against the different opponenets. \n",
+ "# It may reach a state in which the Q-Table was not trained. This will cause an error saying \n",
+ "# either 'max action reached' or 'min action reached'.\n",
+ "# for i in range(len(AdversaryModes)):\n",
+ "# print(AdversaryModes(i))\n",
+ "# adversaryProbs=[0]*len(AdversaryModes)\n",
+ "# adversaryProbs[i]=1\n",
+ "# result = Test(game, Qtable, discountFactor, adversaryProbs)\n",
+ "# payoff, advPayoff, actions, advActions, demandPotential = result.totalPayoff()\n",
+ "# print(payoff)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Programmed_adversary/test.py b/qLearning/Programmed_adversary/test.py
new file mode 100644
index 0000000..2899dff
--- /dev/null
+++ b/qLearning/Programmed_adversary/test.py
@@ -0,0 +1,142 @@
+# Ed, Galit and Katerina
+# Relates to the Q-Learning approach.
+# Testing out the Q-table against a given opponent
+
+import numpy as np
+from environment import AdversaryModes
+
+
+class Test():
+
+
+ def __init__(self, Model, Qtable, discountFactor, adversaryProbs) -> None:
+
+
+ self.env = Model
+ self.Qtable = Qtable.Q_table
+ self.numStates=Qtable.num_States
+ self.numActions=Qtable.num_Actions
+ self.discountFactor = discountFactor
+ self.episodeLength = Model.T
+ self.adversaryProbs = adversaryProbs
+ self.adversary = None
+
+
+
+ def setAdversary(self):
+ options = list(range(len(self.adversaryProbs)))
+ adversaryIndex = int(np.random.choice(options, 1, p= self.adversaryProbs))
+ self.adversary = AdversaryModes(adversaryIndex)
+ newProbs = [0]*len(self.adversaryProbs)
+ newProbs[adversaryIndex] = 1
+ self.env.adversaryProbs = newProbs
+
+
+ def bestResponses(self):
+ states = [0]* self.numStates
+ bestResponses = [0]* self.numStates
+ for i in range(self.numStates):
+ demand = int((200-self.numStates/2)) + i
+ states[i] = demand
+ action = np.argmax(self.Qtable[i]) + int((demand + self.env.costs[0])/2) - self.numActions + 1
+ bestResponses[i] = action
+ return states, bestResponses
+
+
+ def totalPayoff(self):
+
+ self.setAdversary()
+
+ delta = 1/self.discountFactor
+ utility = 0
+ advUtility = 0
+ actions = [0]*self.episodeLength
+ advActions = [0]*self.episodeLength
+ demands = [0]*self.episodeLength
+ stateVector, reward, done = self.env.reset()
+ demand = stateVector[1]
+
+ for i in range(self.episodeLength):
+ delta = delta * self.discountFactor
+ demands[i] = demand
+ if (int(demand -(200-self.numStates/2)) > len(self.Qtable) -1):
+ print("max action reached")
+ demand = int((200-self.numStates/2) + len(self.Qtable) -1)
+ if (int(demand -(200-self.numStates/2)) < 0):
+ print("min action reached")
+ demand = int((200-self.numStates/2))
+ row = self.Qtable[int(demand -(200-self.numStates/2))]
+ action = np.argmax(row) + int((demand + self.env.costs[0])/2) - self.numActions + 1
+ actions[i] = action
+ utility += (demand-action)*(action-self.env.costs[0]) * delta
+ advDemand = 400 - demand
+ stateVector, reward, done = self.env.step(stateVector, action)
+ demand = stateVector[1]
+ advActions[i] = stateVector[2]
+ advUtility += (advDemand-advActions[i])*(advActions[i]-self.env.costs[1]) * delta
+ return utility, advUtility, np.transpose(actions), np.transpose(advActions), np.transpose(demands)
+
+
+ def error(self):
+
+ Qtable_error = np.zeros((self.numStates, self.numActions))
+ lowestState = int(200-(self.numStates - 1)/2)
+
+ for stateIndex in range(self.numStates):
+ for actionIndex in range(self.numActions):
+
+ state = stateIndex + lowestState
+ monopoly_price = int((state + self.env.costs[0])/2)
+ action = actionIndex + monopoly_price - self.numActions + 1
+
+ reward = (state - action) * (action - self.env.costs[0])
+ adv_action = int(self.chooseAdversaryAction(state))
+ next_state = int(state + (adv_action - action)/2)
+
+
+ next_state_index = next_state - lowestState
+ opt_value_next = max(self.Qtable[next_state_index])
+ new_value = (1-self.discountFactor)*reward + self.discountFactor * opt_value_next
+ Qtable_error[stateIndex,actionIndex] = (new_value - self.Qtable[stateIndex,actionIndex])/new_value
+ return Qtable_error
+
+
+ def chooseAdversaryAction(self, state):
+ return self.myopic(self.env.costs[1],400-state)
+
+
+
+ def myopic(self, cost, demand):
+ return (cost + demand)/2
+
+ def payoff(self, cost, demand, price):
+ return (demand - price)*(price - cost)
+
+ def updateDemand(self, demand, pricePair):
+ newDemand = demand + 0.5*(pricePair[1]- pricePair[0])
+ return newDemand
+
+ def utilityOfActions(self, actions):
+ agentDemand = 200
+ opponentDemand = 200
+ totalPayoff = 0
+ delta = 1/self.discountFactor
+ for i in range(self.episodeLength):
+ delta = delta * self.discountFactor
+ agentPrice = int(actions[i])
+ opponentPrice = int(self.myopic(self.env.costs[1],opponentDemand))
+ totalPayoff += self.payoff(self.env.costs[0],agentDemand,agentPrice) * delta
+ agentDemand = int(self.updateDemand(agentDemand, [agentPrice,opponentPrice]))
+ opponentDemand = 400 - agentDemand
+ return totalPayoff
+
+
+
+
+
+
+
+
+
+
+
diff --git a/qLearning/Programmed_adversary_with_time/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb b/qLearning/Programmed_adversary_with_time/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
new file mode 100644
index 0000000..aa3028a
--- /dev/null
+++ b/qLearning/Programmed_adversary_with_time/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
@@ -0,0 +1,262 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_Demand = 400\n",
+ "agent_Cost = 57\n",
+ "adv_Cost = 71 \n",
+ "tuple_Costs = [57,71]\n",
+ "total_Stages = 25\n",
+ "init_State = [total_Demand/2, total_Demand/2]\n",
+ "adversaryProbs=[0]*len(AdversaryModes)\n",
+ "adversaryProbs[0]=1 # We only train against strategies that do not take into account the \n",
+ "# previous actions (myopic or constant strategies).\n",
+ "\n",
+ "game = Model(total_Demand, [agent_Cost,adv_Cost], total_Stages, adversaryProbs)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "num_Actions = 50\n",
+ "num_States = abs(adv_Cost - agent_Cost) + 2 * num_Actions + 2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+demoninator)\n",
+ "Qtable = QTable(num_States, num_Actions, total_Stages , learning_Rate = [490000,500000])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "numberEpisodes = 50_000_000\n",
+ "discountFactor = 0.9999"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, numberEpisodes, discountFactor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "algorithm.solver()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# print(Qtable.Q_table)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Qtable.Q_table.mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversaryProbs=[0]*len(AdversaryModes)\n",
+ "adversaryProbs[0]=1 # We can test the Q-Table against any strategy. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "result = Test(game, Qtable, discountFactor, adversaryProbs)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#import numpy as np\n",
+ "#import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The following plots what the Q-Table says is the best action in each state\n",
+ "#states, bestResponses = result.bestResponses()\n",
+ "#plt.scatter(states,bestResponses)\n",
+ "#plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "180214.8627812602\n",
+ "41262.33031321998\n",
+ "[ 89 92 100 104 110 110 106 109 107 106 108 108 108 108 108 108 108 108\n",
+ " 108 108 112 113 118 130 147]\n",
+ "[135 124 116 112 110 110 110 109 109 108 108 108 108 108 108 108 108 108\n",
+ " 108 108 108 109 110 112 116]\n",
+ "[200. 223. 239. 247. 251. 251. 251. 253. 253. 254. 255. 255. 255. 255.\n",
+ " 255. 255. 255. 255. 255. 255. 255. 253. 251. 247. 238.]\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Returns the optimal payoff and actions according to the Qtable\n",
+ "payoff, advPayoff, actions, advActions, demandPotential = result.totalPayoff()\n",
+ "print(payoff)\n",
+ "print(advPayoff)\n",
+ "print(actions)\n",
+ "print(advActions)\n",
+ "print(demandPotential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The percentage error of the Qtable. This has to be measured against the same opponent that \n",
+ "# it was trained against, as this is a measure of how 'complete' the training is.\n",
+ "error = result.error()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.0006385809554732589"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "error.mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The following calculates the payoff that the Q-Table gives against the different opponenets. \n",
+ "# It may reach a state in which the Q-Table was not trained. This will cause an error saying \n",
+ "# either 'max action reached' or 'min action reached'.\n",
+ "# for i in range(len(AdversaryModes)):\n",
+ "# print(AdversaryModes(i))\n",
+ "# adversaryProbs=[0]*len(AdversaryModes)\n",
+ "# adversaryProbs[i]=1\n",
+ "# result = Test(game, Qtable, discountFactor, adversaryProbs)\n",
+ "# payoff, advPayoff, actions, advActions, demandPotential = result.totalPayoff()\n",
+ "# print(payoff)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Programmed_adversary_with_time/Qtable.py b/qLearning/Programmed_adversary_with_time/Qtable.py
new file mode 100644
index 0000000..54b7fba
--- /dev/null
+++ b/qLearning/Programmed_adversary_with_time/Qtable.py
@@ -0,0 +1,31 @@
+# Ed, Galit and Katerina
+# Relates to the Q-Learning approach.
+# Defines the Q-table
+
+import numpy as np
+
+class QTable():
+
+
+ def __init__(self, num_States, num_Actions, num_Stages, learning_Rate):
+
+ self.num_States= num_States
+ self.num_Actions = num_Actions
+ self.num_Stages = num_Stages
+ self.learning_Rate = learning_Rate
+ self.Q_table = np.zeros((self.num_States, self.num_Actions, self.num_Stages))
+ self.QTable_name=f"QTable, actions={self.num_Actions}, states={self.num_States}, stages={self.num_Stages}"
+
+
+ def reset(self):
+ Qtable = np.zeros((self.num_States, self.num_Actions, self.num_Stages))
+ return Qtable, self.learning_rate
+
+
+ def randomReset(self):
+ randQtable = np.random.rand(self.num_States,self.num_Actions, self.num_Stages)
+ return randQtable, self.learning_rate
+
+
+
+
diff --git a/qLearning/Programmed_adversary_with_time/Test_Qlearning.xlsx b/qLearning/Programmed_adversary_with_time/Test_Qlearning.xlsx
new file mode 100644
index 0000000..4e5238b
Binary files /dev/null and b/qLearning/Programmed_adversary_with_time/Test_Qlearning.xlsx differ
diff --git a/qLearning/Programmed_adversary_with_time/__pycache__/Qtable.cpython-39.pyc b/qLearning/Programmed_adversary_with_time/__pycache__/Qtable.cpython-39.pyc
new file mode 100644
index 0000000..184f792
Binary files /dev/null and b/qLearning/Programmed_adversary_with_time/__pycache__/Qtable.cpython-39.pyc differ
diff --git a/qLearning/Programmed_adversary_with_time/__pycache__/environment.cpython-39.pyc b/qLearning/Programmed_adversary_with_time/__pycache__/environment.cpython-39.pyc
new file mode 100644
index 0000000..e00e92c
Binary files /dev/null and b/qLearning/Programmed_adversary_with_time/__pycache__/environment.cpython-39.pyc differ
diff --git a/qLearning/Programmed_adversary_with_time/__pycache__/learningAgent.cpython-39.pyc b/qLearning/Programmed_adversary_with_time/__pycache__/learningAgent.cpython-39.pyc
new file mode 100644
index 0000000..ea0d720
Binary files /dev/null and b/qLearning/Programmed_adversary_with_time/__pycache__/learningAgent.cpython-39.pyc differ
diff --git a/qLearning/Programmed_adversary_with_time/__pycache__/test.cpython-39.pyc b/qLearning/Programmed_adversary_with_time/__pycache__/test.cpython-39.pyc
new file mode 100644
index 0000000..17d8861
Binary files /dev/null and b/qLearning/Programmed_adversary_with_time/__pycache__/test.cpython-39.pyc differ
diff --git a/qLearning/Programmed_adversary_with_time/environment.py b/qLearning/Programmed_adversary_with_time/environment.py
new file mode 100644
index 0000000..a4bb5e4
--- /dev/null
+++ b/qLearning/Programmed_adversary_with_time/environment.py
@@ -0,0 +1,267 @@
+# Katerina, Ed and Galit (and Tommy!)
+# Relates to the Q-Learning approach.
+# Contains DemandPotentialGame Class and the Model of the DemandPotentialGame Class.
+
+from enum import Enum
+import numpy as np # numerical python
+# printoptions: output limited to 2 digits after decimal point
+np.set_printoptions(precision=2, suppress=False)
+
+
+class DemandPotentialGame():
+ """
+ Fully defines demand Potential Game. It contains game rules, memory and agents strategies.
+ """
+
+ def __init__(self, totalDemand, tupleCosts, totalStages) -> None:
+ self.totalDemand = totalDemand
+ self.costs = tupleCosts
+ self.T = totalStages
+ # first index is always player
+ self.demandPotential = None # two lists for the two players
+ self.prices = None # prices over T rounds
+ self.profit = None # profit in each of T rounds
+ self.stage = None
+
+ def resetGame(self):
+ """
+ Method resets game memory: Demand Potential, prices, profits
+ """
+ self.demandPotential = [[0]*(self.T), [0]*(self.T)] # two lists for the two players
+ self.prices = [[0]*self.T, [0]*self.T] # prices over T rounds
+ self.profit = [[0]*self.T, [0]*self.T] # profit in each of T rounds
+ self.demandPotential[0][0] = self.totalDemand / 2 # initialise first round 0
+ self.demandPotential[1][0] = self.totalDemand/2
+
+ def profits(self, player=0):
+ """
+ Computes profits. Player 0 is the learning agent.
+ """
+ return self.profit[player][self.stage]
+
+ def updatePricesProfitDemand(self, pricePair):
+ """
+ Updates Prices, Profit and Demand Potential Memory.
+ Parameters.
+ pricePair: Pair of prices from the Learning agent and adversary.
+ """
+
+ for player in [0, 1]:
+ price = int(pricePair[player])
+ self.prices[player][self.stage] = price
+ self.profit[player][self.stage] = int((
+ self.demandPotential[player][self.stage] - price)*(price - self.costs[player]))
+ if self.stage < self.T-1:
+ self.demandPotential[0][self.stage + 1] = \
+ int(self.demandPotential[0][self.stage] + (pricePair[1] - pricePair[0])/2)
+ self.demandPotential[1][self.stage + 1] = 400 - self.demandPotential[0][self.stage + 1]
+
+# print(self.prices[0][self.stage],self.prices[1][self.stage],self.profit[0][self.stage], \
+# self.profit[1][self.stage],self.demandPotential[0][self.stage], \
+# self.demandPotential[1][self.stage])
+
+ def monopolyPrice(self, player, t): # myopic monopoly price
+ """
+ Computes Monopoly prices.
+ """
+ return (self.demandPotential[player][self.stage] + self.costs[player])/2
+
+ def myopic(self, player=0):
+ """
+ Adversary follows Myopic strategy
+ """
+ return self.monopolyPrice(player, self.stage)
+
+ def const(self, player, price): # constant price strategy
+ """
+ Adversary follows Constant strategy
+ """
+ if self.stage == self.T-1:
+ return self.monopolyPrice(player, self.stage)
+ return price
+
+ def imit(self, player, firstprice): # price imitator strategy
+ if self.stage == 0:
+ return firstprice
+ if self.stage == self.T-1:
+ return self.monopolyPrice(player, self.stage)
+ return self.prices[1-player][self.stage-1]
+
+ def fight(self, player, firstprice): # simplified fighting strategy
+ if self.stage == 0:
+ return firstprice
+ if self.stage == self.T-1:
+ return self.monopolyPrice(player, self.stage)
+ # aspire = [ 207, 193 ] # aspiration level for demand potential
+ aspire = [0, 0]
+ for i in range(2):
+ aspire[i] = (self.totalDemand-self.costs[player] +
+ self.costs[1-player])/2
+
+ D = self.demandPotential[player][self.stage]
+ Asp = aspire[player]
+ if D >= Asp: # keep price; DANGER: price will never rise
+ return self.prices[player][self.stage-1]
+ # adjust to get to aspiration level using previous
+ # opponent price; own price has to be reduced by twice
+ # the negative amount D - Asp to getself.demandPotential to Asp
+ P = self.prices[1-player][self.stage-1] + 2*(D - Asp)
+ # never price to high because even 125 gives good profits
+ # P = min(P, 125)
+ aspire_price = (self.totalDemand+self.costs[0]+self.costs[1])/4
+ P = min(P, int(0.95*aspire_price))
+
+ return P
+
+ def fight_lb(self, player, firstprice):
+ P = self.fight(player, firstprice)
+ # never price less than production cost
+ P = max(P, self.costs[player])
+ return P
+
+ # sophisticated fighting strategy, compare fight()
+ # estimate *sales* of opponent as their target, kept between
+ # calls in global variable oppsaleguess[]. Assumed behavior
+ # of opponent is similar to this strategy itself.
+ oppsaleguess = [61, 75] # first guess opponent sales as in monopoly
+
+ def guess(self, player, firstprice): # predictive fighting strategy
+ if self.stage == 0:
+ self.oppsaleguess[0] = 61 # always same start
+ self.oppsaleguess[1] = 75 # always same start
+ return firstprice
+
+ if self.stage == self.T-1:
+ return self.monopolyPrice(player, self.stage)
+ aspire = [207, 193] # aspiration level
+ D = self.demandPotential[player][self.stage]
+ Asp = aspire[player]
+
+ if D >= Asp: # keep price, but go slightly towards monopoly if good
+ pmono = self.monopolyPrice(player, self.stage)
+ pcurrent = self.prices[player][self.stage-1]
+ if pcurrent > pmono: # shouldn't happen
+ return pmono
+ if pcurrent > pmono-7: # no change
+ return pcurrent
+ # current low price at 60%, be accommodating towards "collusion"
+ return .6 * pcurrent + .4 * (pmono-7)
+
+ # guess current *opponent price* from previous sales
+ prevsales = self.demandPotential[1 - player][t-1] - self.prices[1-player][t-1]
+ # adjust with weight alpha from previous guess
+ alpha = .5
+ newsalesguess = alpha * self.oppsaleguess[player] + (1-alpha)*prevsales
+ # update
+ self.oppsaleguess[player] = newsalesguess
+ guessoppPrice = 400 - D - newsalesguess
+ P = guessoppPrice + 2*(D - Asp)
+
+ if player == 0:
+ P = min(P, 125)
+ if player == 1:
+ P = min(P, 130)
+ return P
+
+
+class Model(DemandPotentialGame):
+ """
+ Defines the Problem's Model. It is assumed a Markov Decision Process is defined. The class is a Child from the Demand Potential Game Class.
+ The reason: Model is a conceptualization of the Game.
+ """
+
+ def __init__(self, totalDemand, tupleCosts, totalStages, adversaryProbs) -> None:
+ super().__init__(totalDemand, tupleCosts, totalStages)
+
+ self.rewardFunction = self.profits
+
+ # [stage, agent's demand potential, adv previous action]
+ self.initState = [0, totalDemand/2, 0]
+ self.episodesMemory = list()
+ self.done = False
+ self.adversaryProbs = adversaryProbs
+
+ def reset(self):
+ """
+ Reset Model Instantiation.
+ """
+ reward = 0
+ self.stage = 0
+ self.done = False
+ self.resetGame()
+ self.resetAdversary()
+ return self.initState, reward, self.done
+
+ def resetAdversary(self):
+ options = list(range(len(self.adversaryProbs)))
+ adversaryIndex = np.random.choice(options, 1, p= self.adversaryProbs)
+ self.adversaryMode = AdversaryModes(adversaryIndex)
+
+ def adversaryChoosePrice(self):
+ """
+ Strategy followed by the adversary.
+ """
+
+ if self.adversaryMode == AdversaryModes.constant_132:
+ return self.const(player=1, price=132)
+ elif self.adversaryMode == AdversaryModes.constant_95:
+ return self.const(player=1, price=95)
+ elif self.adversaryMode == AdversaryModes.imitation_128:
+ return self.imit(player=1, firstprice=128)
+ elif self.adversaryMode == AdversaryModes.imitation_132:
+ return self.imit(player=1, firstprice=132)
+ elif self.adversaryMode == AdversaryModes.fight_100:
+ return self.fight(player=1, firstprice=100)
+ elif self.adversaryMode == AdversaryModes.fight_125:
+ return self.fight(player=1, firstprice=125)
+ elif self.adversaryMode == AdversaryModes.fight_lb_125:
+ return self.fight_lb(player=1, firstprice=125)
+ elif self.adversaryMode == AdversaryModes.fight_132:
+ return self.fight(player=1, firstprice=132)
+ elif self.adversaryMode == AdversaryModes.fight_lb_132:
+ return self.fight_lb(player=1, firstprice=132)
+ elif self.adversaryMode == AdversaryModes.guess_125:
+ return self.fight(player=1, firstprice=125)
+ elif self.adversaryMode == AdversaryModes.guess_132:
+ return self.fight(player=1, firstprice=132)
+ else:
+ return self.myopic(player=1)
+
+ def step(self, state, action):
+ """
+ Transition Function.
+ Parameters:
+ - action: Price
+ - state: tupple in the latest stage (stage ,Demand Potential, Adversary's prev price)
+ """
+ adversaryAction = int(self.adversaryChoosePrice())
+ self.updatePricesProfitDemand([action, adversaryAction])
+
+
+ done = (self.stage == self.T-1)
+
+
+ if not done:
+ newState = [self.stage+1, self.demandPotential[0][self.stage + 1], adversaryAction]
+ else:
+ newState = [self.stage+1, 0, adversaryAction]
+
+ reward = self.rewardFunction()
+ self.stage = self.stage + 1
+
+ return newState, reward, done
+
+
+class AdversaryModes(Enum):
+ myopic = 0
+ constant_132 = 1
+ constant_95 = 2
+ imitation_132 = 3
+ imitation_128 = 4
+ fight_132 = 5
+ fight_lb_132 = 6
+ fight_125 = 7
+ fight_lb_125 = 8
+ fight_100 = 9
+ guess_132 = 10
+ guess_125 = 11
\ No newline at end of file
diff --git a/qLearning/Programmed_adversary_with_time/learningAgent.py b/qLearning/Programmed_adversary_with_time/learningAgent.py
new file mode 100644
index 0000000..36925fa
--- /dev/null
+++ b/qLearning/Programmed_adversary_with_time/learningAgent.py
@@ -0,0 +1,82 @@
+# Ed, Kat, Galit
+# ReinforceAlgorithm Class: Solver.
+
+import numpy as np #repeated
+
+# printoptions: output limited to 2 digits after decimal point
+np.set_printoptions(precision=2, suppress=False)
+
+
+class LearningAlgorithm():
+ """
+ Model Solver.
+ """
+ def __init__(self, Model, Qtable, numberEpisodes, discountFactor) -> None:
+
+ self.env = Model
+ self.Qtable = Qtable.Q_table
+ self.learning_Rate = Qtable.learning_Rate
+ self.numberEpisodes = numberEpisodes
+ self.gamma = discountFactor
+ self.numStates=Qtable.num_States #Qtable dimen - number of states x number of actions x number of stages
+ self.numStages=Qtable.num_Stages
+ if self.numStates % 2 ==1 :
+ print('num of states should be even')
+ self.numActions=Qtable.num_Actions
+ if self.numActions % 2 ==1 :
+ print('num of actions should be even')
+ self.lowestState = int(200-(self.numStates)/2) # Should already be int
+ self.highestState = int(200+(self.numStates)/2 - 1) # Should already be int
+
+
+ def resetQtable(self):
+ self.Qtable, self.learning_Rate = self.Qtable.reset()
+
+ """
+ This function will eventually choose and adversary agent to play against
+ and according to that return an action played by that adversary.
+ This could be chosen according to some existing equilibruim dist.
+ """
+ def chooseAdver(self, state):
+ return int((400 - state + self.env.costs[1])/2) #myopic
+
+ def StateInd(self, state): # computes state index in Qtable
+ return int(state - self.lowestState)
+ #return min(int(state -(200-self.numStates/2)), self.numStates - 1)
+
+ def ActionInd(self, monPrice, action): # computes action index in Qtable
+ return int(action - (monPrice - self.numActions + 1)) #monPrice should have index numActions - 1
+
+ def alpha_n(self, n): # defines the Qlearning rate
+ return self.learning_Rate[0]/(n+self.learning_Rate[1])
+ """
+ Now the Q-learning itself
+ """
+ def solver(self):
+
+ self.resetQtable
+
+ for episode in range(self.numberEpisodes):
+
+ state = np.random.randint(self.lowestState, self.highestState + 1)
+ stage = np.random.randint(0, self.numStages)
+ monPrice = int((state + self.env.costs[0]) / 2)
+ action = np.random.randint(monPrice-self.numActions+1, monPrice + 1)
+ advAction = self.chooseAdver(state)
+ reward = (state-action)*(action-self.env.costs[0])
+ next_state = int(state+.5*(advAction-action))
+ if(stage==self.numStages-1):
+ opt_value_next=0
+ else:
+ opt_value_next=max(self.Qtable[self.StateInd(next_state),:, stage+1])
+
+
+ # updating the Qtable
+ qvalue = (1-self.alpha_n(episode)) * \
+ self.Qtable[self.StateInd(state), self.ActionInd(monPrice, action), stage]\
+ + self.alpha_n(episode) * \
+ ((1-self.gamma)*reward + self.gamma*opt_value_next)
+ self.Qtable[self.StateInd(state), self.ActionInd(monPrice, action), stage]=qvalue
+
+
+
diff --git a/qLearning/Programmed_adversary_with_time/main.py b/qLearning/Programmed_adversary_with_time/main.py
new file mode 100644
index 0000000..253448a
--- /dev/null
+++ b/qLearning/Programmed_adversary_with_time/main.py
@@ -0,0 +1,67 @@
+from learningAgent import LearningAlgorithm
+from environment import Model, AdversaryModes
+import numpy as np
+
+np.random.seed(10)
+agent_cost = 57
+adv_cost = 71
+
+game = Model(totalDemand = 400,
+ tupleCosts = (agent_cost, adv_cost),
+ totalStages = 25,
+ initState = [400/2,0], adversaryMode=AdversaryModes.myopic)
+
+num_Actions = 50
+num_States = abs(adv_cost - agent_cost) + 2 * num_Actions + 2
+gamma = 0.99
+
+
+Qtable = np.zeros((num_States, num_Actions))
+Qtable_error = np.zeros((num_States, num_Actions))
+
+algorithm = LearningAlgorithm(game, Qtable, numberEpisodes = 10000, discountFactor = gamma)
+
+algorithm.solver()
+
+def bestAction(Qtable, state):
+ row = Qtable[int(state -(200-self.numStates/2))]
+ action = np.argmax(row) + (state + agent_cost)/2- num_Actions+1
+ return action
+
+
+
+
+# printing Qtable for excel
+for s in range(num_States):
+ for a in range(num_Actions):
+ print("%.5f, " % Qtable[s,a], end="")
+ print("")
+
+# Checking the convergence of the Qtable
+
+for s in range(num_States):
+ for a in range(num_Actions):
+ lowestState = int(200-(num_States)/2)
+ highestState = int(200+(num_States)/2 - 1)
+ state = s + lowestState
+
+ monopoly_price = int((state + agent_cost)/2) + 1
+ action = a + monopoly_price - num_Actions + 1
+
+ reward = (state - action) * (action - agent_cost)
+ adv_action = int((400 -state + adv_cost)/2) + 1
+ next_state = int(state + (adv_action - action)/2)
+ #print(state,monopoly_price,action,reward,adv_action, next_state)
+
+ ns = next_state - lowestState
+ opt_value_next = max(Qtable[ns])
+ new_value = (1-gamma)*reward + gamma * opt_value_next
+ Qtable_error[s,a] = (new_value - Qtable[s,a])/new_value
+
+# Printing Qtable error
+for s in range(num_States):
+ for a in range(num_Actions):
+ #print(Qtable[s,a],",", end="")
+ print("%.5f, " % Qtable_error[s,a], end="")
+ print("")
+
diff --git a/qLearning/Programmed_adversary_with_time/qLearningSimulations.ipynb b/qLearning/Programmed_adversary_with_time/qLearningSimulations.ipynb
new file mode 100644
index 0000000..aa3028a
--- /dev/null
+++ b/qLearning/Programmed_adversary_with_time/qLearningSimulations.ipynb
@@ -0,0 +1,262 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_Demand = 400\n",
+ "agent_Cost = 57\n",
+ "adv_Cost = 71 \n",
+ "tuple_Costs = [57,71]\n",
+ "total_Stages = 25\n",
+ "init_State = [total_Demand/2, total_Demand/2]\n",
+ "adversaryProbs=[0]*len(AdversaryModes)\n",
+ "adversaryProbs[0]=1 # We only train against strategies that do not take into account the \n",
+ "# previous actions (myopic or constant strategies).\n",
+ "\n",
+ "game = Model(total_Demand, [agent_Cost,adv_Cost], total_Stages, adversaryProbs)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "num_Actions = 50\n",
+ "num_States = abs(adv_Cost - agent_Cost) + 2 * num_Actions + 2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+demoninator)\n",
+ "Qtable = QTable(num_States, num_Actions, total_Stages , learning_Rate = [490000,500000])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "numberEpisodes = 50_000_000\n",
+ "discountFactor = 0.9999"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, numberEpisodes, discountFactor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "algorithm.solver()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# print(Qtable.Q_table)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Qtable.Q_table.mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversaryProbs=[0]*len(AdversaryModes)\n",
+ "adversaryProbs[0]=1 # We can test the Q-Table against any strategy. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "result = Test(game, Qtable, discountFactor, adversaryProbs)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#import numpy as np\n",
+ "#import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The following plots what the Q-Table says is the best action in each state\n",
+ "#states, bestResponses = result.bestResponses()\n",
+ "#plt.scatter(states,bestResponses)\n",
+ "#plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "180214.8627812602\n",
+ "41262.33031321998\n",
+ "[ 89 92 100 104 110 110 106 109 107 106 108 108 108 108 108 108 108 108\n",
+ " 108 108 112 113 118 130 147]\n",
+ "[135 124 116 112 110 110 110 109 109 108 108 108 108 108 108 108 108 108\n",
+ " 108 108 108 109 110 112 116]\n",
+ "[200. 223. 239. 247. 251. 251. 251. 253. 253. 254. 255. 255. 255. 255.\n",
+ " 255. 255. 255. 255. 255. 255. 255. 253. 251. 247. 238.]\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Returns the optimal payoff and actions according to the Qtable\n",
+ "payoff, advPayoff, actions, advActions, demandPotential = result.totalPayoff()\n",
+ "print(payoff)\n",
+ "print(advPayoff)\n",
+ "print(actions)\n",
+ "print(advActions)\n",
+ "print(demandPotential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The percentage error of the Qtable. This has to be measured against the same opponent that \n",
+ "# it was trained against, as this is a measure of how 'complete' the training is.\n",
+ "error = result.error()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.0006385809554732589"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "error.mean()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The following calculates the payoff that the Q-Table gives against the different opponenets. \n",
+ "# It may reach a state in which the Q-Table was not trained. This will cause an error saying \n",
+ "# either 'max action reached' or 'min action reached'.\n",
+ "# for i in range(len(AdversaryModes)):\n",
+ "# print(AdversaryModes(i))\n",
+ "# adversaryProbs=[0]*len(AdversaryModes)\n",
+ "# adversaryProbs[i]=1\n",
+ "# result = Test(game, Qtable, discountFactor, adversaryProbs)\n",
+ "# payoff, advPayoff, actions, advActions, demandPotential = result.totalPayoff()\n",
+ "# print(payoff)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.13"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qLearning/Programmed_adversary_with_time/test.py b/qLearning/Programmed_adversary_with_time/test.py
new file mode 100644
index 0000000..8db917f
--- /dev/null
+++ b/qLearning/Programmed_adversary_with_time/test.py
@@ -0,0 +1,146 @@
+# Ed, Galit and Katerina
+# Relates to the Q-Learning approach.
+# Testing out the Q-table against a given opponent
+
+import numpy as np
+from environment import AdversaryModes
+
+
+class Test():
+
+
+ def __init__(self, Model, Qtable, discountFactor, adversaryProbs) -> None:
+
+
+ self.env = Model
+ self.Qtable = Qtable.Q_table
+ self.numStates=Qtable.num_States
+ self.numActions=Qtable.num_Actions
+ self.numStages=Qtable.num_Stages
+ self.discountFactor = discountFactor
+ self.adversaryProbs = adversaryProbs
+ self.adversary = None
+
+
+
+ def setAdversary(self):
+ options = list(range(len(self.adversaryProbs)))
+ adversaryIndex = int(np.random.choice(options, 1, p= self.adversaryProbs))
+ self.adversary = AdversaryModes(adversaryIndex)
+ newProbs = [0]*len(self.adversaryProbs)
+ newProbs[adversaryIndex] = 1
+ self.env.adversaryProbs = newProbs
+
+
+ def bestResponses(self):
+ states = [0]* self.numStates
+ bestResponses = [0]* self.numStates
+ for i in range(self.numStates):
+ demand = int((200-self.numStates/2)) + i
+ states[i] = demand
+ action = np.argmax(self.Qtable[i]) + int((demand + self.env.costs[0])/2) - self.numActions + 1
+ bestResponses[i] = action
+ return states, bestResponses
+
+
+ def totalPayoff(self):
+
+ self.setAdversary()
+
+ delta = 1/self.discountFactor
+ utility = 0
+ advUtility = 0
+ actions = [0]*self.numStages
+ advActions = [0]*self.numStages
+ demands = [0]*self.numStages
+ stateVector, reward, done = self.env.reset()
+ demand = stateVector[1]
+
+ for stage in range(self.numStages):
+ delta = delta * self.discountFactor
+ demands[stage] = demand
+ if (int(demand -(200-self.numStates/2)) > len(self.Qtable) -1):
+ print("max action reached")
+ demand = int((200-self.numStates/2) + len(self.Qtable) -1)
+ if (int(demand -(200-self.numStates/2)) < 0):
+ print("min action reached")
+ demand = int((200-self.numStates/2))
+ demand_index = int(demand -(200-self.numStates/2))
+ action_index = np.argmax(self.Qtable[demand_index, :, stage])
+ action = action_index + int((demand + self.env.costs[0])/2) - self.numActions + 1
+ actions[stage] = action
+ utility += (demand-action)*(action-self.env.costs[0]) * delta
+ advDemand = 400 - demand
+ stateVector, reward, done = self.env.step(stateVector, action)
+ demand = stateVector[1]
+ advActions[stage] = stateVector[2]
+ advUtility += (advDemand-advActions[stage])*(advActions[stage]-self.env.costs[1]) * delta
+ return utility, advUtility, np.transpose(actions), np.transpose(advActions), np.transpose(demands)
+
+
+ def error(self):
+
+ Qtable_error = np.zeros((self.numStates, self.numActions, self.numStages))
+ lowestState = int(200-(self.numStates - 1)/2)
+
+ for stateIndex in range(self.numStates):
+ for actionIndex in range(self.numActions):
+ for stage in range(self.numStages):
+ state = stateIndex + lowestState
+ monopoly_price = int((state + self.env.costs[0])/2)
+ action = actionIndex + monopoly_price - self.numActions + 1
+ reward = (state - action) * (action - self.env.costs[0])
+ adv_action = int(self.chooseAdversaryAction(state))
+ next_state = int(state + (adv_action - action)/2)
+ next_state_index = next_state - lowestState
+ if(stage==self.numStages-1):
+ opt_value_next = 0
+ else:
+ opt_value_next = max(self.Qtable[next_state_index, : , stage+1])
+ new_value = (1-self.discountFactor)*reward + self.discountFactor * opt_value_next
+ if new_value != 0:
+ Qtable_error[stateIndex,actionIndex, stage] = (new_value - self.Qtable[stateIndex,actionIndex, stage])/new_value
+ if new_value == 0 and self.Qtable[stateIndex,actionIndex, stage] != 0:
+ print("Div by zero error") # This should not occur
+ return Qtable_error
+
+
+ def chooseAdversaryAction(self, state):
+ return self.myopic(self.env.costs[1],400-state)
+
+
+
+ def myopic(self, cost, demand):
+ return (cost + demand)/2
+
+ def payoff(self, cost, demand, price):
+ return (demand - price)*(price - cost)
+
+ def updateDemand(self, demand, pricePair):
+ newDemand = demand + 0.5*(pricePair[1]- pricePair[0])
+ return newDemand
+
+ def utilityOfActions(self, actions):
+ agentDemand = 200
+ opponentDemand = 200
+ totalPayoff = 0
+ delta = 1/self.discountFactor
+ for i in range(self.numStages):
+ delta = delta * self.discountFactor
+ agentPrice = int(actions[i])
+ opponentPrice = int(self.myopic(self.env.costs[1],opponentDemand))
+ totalPayoff += self.payoff(self.env.costs[0],agentDemand,agentPrice) * delta
+ agentDemand = int(self.updateDemand(agentDemand, [agentPrice,opponentPrice]))
+ opponentDemand = 400 - agentDemand
+ return totalPayoff
+
+
+
+
+
+
+
+
+
+
+
diff --git a/qLearning/__pycache__/Qtable.cpython-39.pyc b/qLearning/__pycache__/Qtable.cpython-39.pyc
new file mode 100644
index 0000000..ba55b9c
Binary files /dev/null and b/qLearning/__pycache__/Qtable.cpython-39.pyc differ
diff --git a/qLearning/__pycache__/environment.cpython-39.pyc b/qLearning/__pycache__/environment.cpython-39.pyc
new file mode 100644
index 0000000..5f18458
Binary files /dev/null and b/qLearning/__pycache__/environment.cpython-39.pyc differ
diff --git a/qLearning/__pycache__/learningAgent.cpython-39.pyc b/qLearning/__pycache__/learningAgent.cpython-39.pyc
new file mode 100644
index 0000000..04df10f
Binary files /dev/null and b/qLearning/__pycache__/learningAgent.cpython-39.pyc differ
diff --git a/qLearning/__pycache__/test.cpython-39.pyc b/qLearning/__pycache__/test.cpython-39.pyc
new file mode 100644
index 0000000..f82d02f
Binary files /dev/null and b/qLearning/__pycache__/test.cpython-39.pyc differ
diff --git a/qlearning/Episodic_learning_with_memory/.idea/.name b/qlearning/Episodic_learning_with_memory/.idea/.name
new file mode 100644
index 0000000..d72b538
--- /dev/null
+++ b/qlearning/Episodic_learning_with_memory/.idea/.name
@@ -0,0 +1 @@
+Qtable.py
\ No newline at end of file
diff --git a/qlearning/Episodic_learning_with_memory/.ipynb_checkpoints/qLearningSimulations-otherAdversary-checkpoint.ipynb b/qlearning/Episodic_learning_with_memory/.ipynb_checkpoints/qLearningSimulations-otherAdversary-checkpoint.ipynb
new file mode 100644
index 0000000..a1e2988
--- /dev/null
+++ b/qlearning/Episodic_learning_with_memory/.ipynb_checkpoints/qLearningSimulations-otherAdversary-checkpoint.ipynb
@@ -0,0 +1,406 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "import pandas as pd"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(11)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_demand = 400\n",
+ "agent_cost = 57\n",
+ "adversary_cost = 71 \n",
+ "costs = [agent_cost,adversary_cost]\n",
+ "total_stages = 25\n",
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Below is where we decide what adversaries we train against- see environment.py for the numbers\n",
+ "# Replace * and ** with the two number associated with the opponents at the bottom of environment.py\n",
+ "# adversary_probabilities[10]= 0.5\n",
+ "adversary_probabilities[11] = 1\n",
+ "game = Model(total_demand, costs, total_stages, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2040816\n"
+ ]
+ }
+ ],
+ "source": [
+ "number_actions = 50\n",
+ "number_demands = total_demand + 1\n",
+ "discount_factor = 1\n",
+ "number_episodes = 100_000_000\n",
+ "constant = int(number_episodes/49)\n",
+ "print(constant)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+denominator)\n",
+ "Qtable = QTable(number_demands, number_actions, total_stages , learning_rate = [constant,constant])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, number_episodes, discount_factor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0 0.5816011851524414\n",
+ "Current payoff for adversary 1: 68275.0\n",
+ "Current payoff for adversary 1: 91913.0\n",
+ "Current payoff for adversary 1: 54020.0\n",
+ "Current payoff for adversary 1: 82076.0\n",
+ "Current payoff for adversary 1: 84520.0\n",
+ "Current payoff for adversary 1: 92376.0\n",
+ "Current payoff for adversary 1: 97163.0\n",
+ "Current payoff for adversary 1: 96925.0\n",
+ "Current payoff for adversary 1: 98503.0\n",
+ "Current payoff for adversary 1: 102036.0\n",
+ "Current payoff for adversary 1: 91161.0\n",
+ "Current payoff for adversary 1: 81958.0\n",
+ "Current payoff for adversary 1: 104372.0\n",
+ "Current payoff for adversary 1: 93292.0\n",
+ "Current payoff for adversary 1: 100358.0\n",
+ "Current payoff for adversary 1: 86605.0\n",
+ "Current payoff for adversary 1: 95709.0\n",
+ "Current payoff for adversary 1: 94686.0\n",
+ "Current payoff for adversary 1: 100752.0\n",
+ "Current payoff for adversary 1: 101333.0\n",
+ "Current payoff for adversary 1: 82308.0\n",
+ "Current payoff for adversary 1: 94853.0\n",
+ "Current payoff for adversary 1: 67820.0\n",
+ "Current payoff for adversary 1: 87518.0\n",
+ "Current payoff for adversary 1: 72280.0\n",
+ "Current payoff for adversary 1: 88293.0\n",
+ "Current payoff for adversary 1: 96672.0\n",
+ "Current payoff for adversary 1: 81103.0\n",
+ "Current payoff for adversary 1: 97489.0\n",
+ "Current payoff for adversary 1: 107029.0\n",
+ "Current payoff for adversary 1: 105697.0\n",
+ "Current payoff for adversary 1: 107602.0\n",
+ "Current payoff for adversary 1: 88984.0\n",
+ "Current payoff for adversary 1: 107698.0\n",
+ "Current payoff for adversary 1: 106008.0\n",
+ "Current payoff for adversary 1: 95466.0\n",
+ "Current payoff for adversary 1: 99778.0\n",
+ "Current payoff for adversary 1: 100018.0\n",
+ "Current payoff for adversary 1: 100310.0\n",
+ "Current payoff for adversary 1: 100677.0\n",
+ "Current payoff for adversary 1: 100322.0\n",
+ "Current payoff for adversary 1: 100317.0\n",
+ "Current payoff for adversary 1: 100939.0\n",
+ "Current payoff for adversary 1: 101318.0\n",
+ "Current payoff for adversary 1: 101629.0\n",
+ "Current payoff for adversary 1: 101825.0\n",
+ "Current payoff for adversary 1: 89345.0\n",
+ "Current payoff for adversary 1: 94224.0\n",
+ "Current payoff for adversary 1: 93818.0\n",
+ "Current payoff for adversary 1: 93739.0\n",
+ "50 0.011535420930821527\n",
+ "Current payoff for adversary 1: 92876.0\n",
+ "Current payoff for adversary 1: 93741.0\n",
+ "Current payoff for adversary 1: 106375.0\n",
+ "Current payoff for adversary 1: 94702.0\n",
+ "Current payoff for adversary 1: 94339.0\n",
+ "Current payoff for adversary 1: 111527.0\n",
+ "Current payoff for adversary 1: 110836.0\n",
+ "Current payoff for adversary 1: 112527.0\n",
+ "Current payoff for adversary 1: 111546.0\n",
+ "Current payoff for adversary 1: 110972.0\n",
+ "Current payoff for adversary 1: 111047.0\n",
+ "Current payoff for adversary 1: 111939.0\n",
+ "Current payoff for adversary 1: 112083.0\n",
+ "63\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "[]"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# Below is the first stage of learning- actions are chosen randomly.\n",
+ "number_episodes_per_round = 100_000\n",
+ "number_rounds = int(number_episodes / number_episodes_per_round)\n",
+ "errors = np.zeros(number_rounds)\n",
+ "final_round = 0\n",
+ "opponent1_results = list()\n",
+ "#opponent2_results = list()\n",
+ "for round_ in range(number_rounds):\n",
+ " algorithm.continue_learning(number_episodes_per_round,number_episodes_per_round * round_ +1)\n",
+ " adversary_probabilities[11]= 1\n",
+ " # adversary_probabilities[11] = 0.5\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " errors[round_] = result.error(1000)\n",
+ " if round_ % 50 == 0:\n",
+ " print(round_, errors[round_])\n",
+ " if round_ > 10 and np.max(errors[round_-10:round_]) < 0.01:\n",
+ " print(round_)\n",
+ " final_round = round_\n",
+ " break\n",
+ " \n",
+ " adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " adversary_probabilities[11]=1\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " payoff1, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " opponent1_results.append(payoff1)\n",
+ " print('Current payoff for adversary 1: ', payoff1)\n",
+ " \n",
+ " # adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " # adversary_probabilities[11]=1\n",
+ " # result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " # payoff2, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " # opponent2_results.append(payoff2)\n",
+ " # print('Current payoff for adversary 2: ', payoff2)\n",
+ " \n",
+ " if (round_ == number_rounds - 1):\n",
+ " final_round = round_\n",
+ " \n",
+ "plt.plot(errors[0:final_round+1])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Round 0 of 187\n",
+ "Best payoff: 128870\n",
+ "Best actions: [113, 122, 124, 125, 125, 125, 125, 112, 110, 109, 109, 110, 103, 114, 104, 106, 111, 110, 101, 112, 107, 107, 112, 116, 127]\n",
+ "Current payoff for adversary 1: 128294.0\n",
+ "Round 1 of 187\n",
+ "Best payoff: 131295\n",
+ "Best actions: [111, 124, 125, 124, 125, 124, 125, 129, 120, 118, 121, 112, 112, 111, 108, 122, 114, 104, 107, 117, 109, 120, 107, 112, 130]\n",
+ "Current payoff for adversary 1: 130908.0\n",
+ "Round 2 of 187\n",
+ "Best payoff: 132769\n",
+ "Best actions: [111, 125, 125, 125, 125, 124, 124, 125, 132, 116, 132, 114, 119, 106, 113, 110, 116, 108, 111, 114, 114, 111, 109, 112, 131]\n",
+ "Current payoff for adversary 1: 132769.0\n",
+ "Round 3 of 187\n",
+ "Best payoff: 133218\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 124, 125, 132, 117, 121, 116, 121, 108, 112, 110, 116, 108, 111, 114, 114, 111, 109, 112, 131]\n",
+ "Current payoff for adversary 1: 132096.0\n",
+ "Round 4 of 187\n",
+ "Best payoff: 133918\n",
+ "Best actions: [111, 124, 125, 125, 125, 125, 125, 124, 124, 126, 126, 117, 117, 113, 113, 115, 115, 112, 110, 115, 111, 117, 108, 113, 131]\n",
+ "Current payoff for adversary 1: 133221.0\n",
+ "Round 5 of 187\n",
+ "Best payoff: 134831\n",
+ "Best actions: [111, 125, 125, 125, 124, 125, 125, 125, 125, 125, 128, 121, 119, 121, 111, 115, 111, 112, 115, 113, 113, 115, 109, 117, 131]\n",
+ "Current payoff for adversary 1: 134805.0\n",
+ "Round 6 of 187\n",
+ "Best payoff: 134805\n",
+ "Best actions: [111, 125, 124, 125, 125, 125, 125, 125, 125, 125, 128, 121, 119, 120, 111, 115, 111, 112, 115, 113, 113, 115, 109, 117, 131]\n",
+ "Current payoff for adversary 1: 133876.0\n",
+ "Round 7 of 187\n",
+ "Best payoff: 135415\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 124, 124, 128, 119, 119, 121, 113, 116, 115, 115, 114, 113, 115, 109, 115, 131]\n",
+ "Current payoff for adversary 1: 134603.0\n",
+ "Round 8 of 187\n",
+ "Best payoff: 135867\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 128, 119, 121, 119, 113, 116, 116, 118, 115, 120, 118, 110, 113, 130]\n",
+ "Current payoff for adversary 1: 135216.0\n",
+ "Round 9 of 187\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Below is the second stage of learning- actions are chosen according to an epsilon greedy strategy.\n",
+ "episode_counter = (final_round + 1) * number_episodes_per_round\n",
+ "episodes_left = number_episodes - episode_counter\n",
+ "number_episodes_per_round = 500_000\n",
+ "number_rounds = int(episodes_left / number_episodes_per_round)\n",
+ "\n",
+ "for round_ in range(number_rounds): \n",
+ " print('Round ', round_, ' of ', number_rounds)\n",
+ " algorithm.epsilon_greedy_learning(number_episodes_per_round, episode_counter)\n",
+ " \n",
+ " adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " adversary_probabilities[11]=1\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " payoff1, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " opponent1_results.append(payoff1)\n",
+ " print('Current payoff for adversary 1: ', payoff1)\n",
+ " \n",
+ "# adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# adversary_probabilities[11]=1\n",
+ "# result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ "# payoff2, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "# opponent2_results.append(payoff2)\n",
+ "# print('Current payoff for adversary 2: ', payoff2)\n",
+ " \n",
+ " episode_counter += number_episodes_per_round\n",
+ " \n",
+ "plt.plot(opponent1_results)\n",
+ "# plt.plot(opponent2_results)\n",
+ "plt.title(\"Payoff over the rounds\")\n",
+ "plt.xlabel(\"Rounds\")\n",
+ "plt.ylabel(\"Payoff at the end of each round\")\n",
+ "legend = [\"adversary 1\"]\n",
+ "plt.legend(legend)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Qtable.save(\"Qtable_guess125\")\n",
+ "\n",
+ "df1 = pd.DataFrame(opponent1_results)\n",
+ "#df2 = pd.DataFrame(opponent2_results)\n",
+ "\n",
+ "writer = pd.ExcelWriter('payoff_11.xlsx', engine='xlsxwriter')\n",
+ "df1.to_excel(writer, sheet_name='payoff_11', index=False)\n",
+ "#df2.to_excel(writer, sheet_name='payoff2', index=False)\n",
+ "writer.save()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# We now have the trained agent. We want to test it against each opponent individually, so that\n",
+ "# we can compare it against the agent that is just trained against this opponent. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Testing against one type of opponent by changing the * below to be the first number\n",
+ "adversary_probabilities[10]=1\n",
+ "result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ "payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "print(payoff)\n",
+ "print(adversary_payoff)\n",
+ "print(actions)\n",
+ "print(adversary_actions)\n",
+ "print(demand_potential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Testing against one type of opponent by changing the * below to be the first number\n",
+ "adversary_probabilities[11]=1\n",
+ "result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ "payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "print(payoff)\n",
+ "print(adversary_payoff)\n",
+ "print(actions)\n",
+ "print(adversary_actions)\n",
+ "print(demand_potential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.7"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qlearning/Episodic_learning_with_memory/QTables/Qtable_guess132_guess128.zip b/qlearning/Episodic_learning_with_memory/QTables/Qtable_guess132_guess128.zip
new file mode 100644
index 0000000..5ec1362
Binary files /dev/null and b/qlearning/Episodic_learning_with_memory/QTables/Qtable_guess132_guess128.zip differ
diff --git a/qlearning/Episodic_learning_with_memory/payoffs.xlsx b/qlearning/Episodic_learning_with_memory/payoffs.xlsx
new file mode 100644
index 0000000..166b271
Binary files /dev/null and b/qlearning/Episodic_learning_with_memory/payoffs.xlsx differ
diff --git a/qlearning/Episodic_learning_with_memory/qLearningSimulations-otherAdversary.ipynb b/qlearning/Episodic_learning_with_memory/qLearningSimulations-otherAdversary.ipynb
new file mode 100644
index 0000000..465585d
--- /dev/null
+++ b/qlearning/Episodic_learning_with_memory/qLearningSimulations-otherAdversary.ipynb
@@ -0,0 +1,548 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "import pandas as pd"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(11)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_demand = 400\n",
+ "agent_cost = 57\n",
+ "adversary_cost = 71 \n",
+ "costs = [agent_cost,adversary_cost]\n",
+ "total_stages = 25\n",
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Below is where we decide what adversaries we train against- see environment.py for the numbers\n",
+ "# Replace * and ** with the two number associated with the opponents at the bottom of environment.py\n",
+ "# adversary_probabilities[10]= 0.5\n",
+ "adversary_probabilities[11] = 1\n",
+ "game = Model(total_demand, costs, total_stages, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2040816\n"
+ ]
+ }
+ ],
+ "source": [
+ "number_actions = 50\n",
+ "number_demands = total_demand + 1\n",
+ "discount_factor = 1\n",
+ "number_episodes = 100_000_000\n",
+ "constant = int(number_episodes/49)\n",
+ "print(constant)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+denominator)\n",
+ "Qtable = QTable(number_demands, number_actions, total_stages , learning_rate = [constant,constant])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, number_episodes, discount_factor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0 0.5816011851524414\n",
+ "Current payoff for adversary 1: 68275.0\n",
+ "Current payoff for adversary 1: 91913.0\n",
+ "Current payoff for adversary 1: 54020.0\n",
+ "Current payoff for adversary 1: 82076.0\n",
+ "Current payoff for adversary 1: 84520.0\n",
+ "Current payoff for adversary 1: 92376.0\n",
+ "Current payoff for adversary 1: 97163.0\n",
+ "Current payoff for adversary 1: 96925.0\n",
+ "Current payoff for adversary 1: 98503.0\n",
+ "Current payoff for adversary 1: 102036.0\n",
+ "Current payoff for adversary 1: 91161.0\n",
+ "Current payoff for adversary 1: 81958.0\n",
+ "Current payoff for adversary 1: 104372.0\n",
+ "Current payoff for adversary 1: 93292.0\n",
+ "Current payoff for adversary 1: 100358.0\n",
+ "Current payoff for adversary 1: 86605.0\n",
+ "Current payoff for adversary 1: 95709.0\n",
+ "Current payoff for adversary 1: 94686.0\n",
+ "Current payoff for adversary 1: 100752.0\n",
+ "Current payoff for adversary 1: 101333.0\n",
+ "Current payoff for adversary 1: 82308.0\n",
+ "Current payoff for adversary 1: 94853.0\n",
+ "Current payoff for adversary 1: 67820.0\n",
+ "Current payoff for adversary 1: 87518.0\n",
+ "Current payoff for adversary 1: 72280.0\n",
+ "Current payoff for adversary 1: 88293.0\n",
+ "Current payoff for adversary 1: 96672.0\n",
+ "Current payoff for adversary 1: 81103.0\n",
+ "Current payoff for adversary 1: 97489.0\n",
+ "Current payoff for adversary 1: 107029.0\n",
+ "Current payoff for adversary 1: 105697.0\n",
+ "Current payoff for adversary 1: 107602.0\n",
+ "Current payoff for adversary 1: 88984.0\n",
+ "Current payoff for adversary 1: 107698.0\n",
+ "Current payoff for adversary 1: 106008.0\n",
+ "Current payoff for adversary 1: 95466.0\n",
+ "Current payoff for adversary 1: 99778.0\n",
+ "Current payoff for adversary 1: 100018.0\n",
+ "Current payoff for adversary 1: 100310.0\n",
+ "Current payoff for adversary 1: 100677.0\n",
+ "Current payoff for adversary 1: 100322.0\n",
+ "Current payoff for adversary 1: 100317.0\n",
+ "Current payoff for adversary 1: 100939.0\n",
+ "Current payoff for adversary 1: 101318.0\n",
+ "Current payoff for adversary 1: 101629.0\n",
+ "Current payoff for adversary 1: 101825.0\n",
+ "Current payoff for adversary 1: 89345.0\n",
+ "Current payoff for adversary 1: 94224.0\n",
+ "Current payoff for adversary 1: 93818.0\n",
+ "Current payoff for adversary 1: 93739.0\n",
+ "50 0.011535420930821527\n",
+ "Current payoff for adversary 1: 92876.0\n",
+ "Current payoff for adversary 1: 93741.0\n",
+ "Current payoff for adversary 1: 106375.0\n",
+ "Current payoff for adversary 1: 94702.0\n",
+ "Current payoff for adversary 1: 94339.0\n",
+ "Current payoff for adversary 1: 111527.0\n",
+ "Current payoff for adversary 1: 110836.0\n",
+ "Current payoff for adversary 1: 112527.0\n",
+ "Current payoff for adversary 1: 111546.0\n",
+ "Current payoff for adversary 1: 110972.0\n",
+ "Current payoff for adversary 1: 111047.0\n",
+ "Current payoff for adversary 1: 111939.0\n",
+ "Current payoff for adversary 1: 112083.0\n",
+ "63\n"
+ ]
+ },
+ {
+ "data": {
+ "text/plain": [
+ "[]"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# Below is the first stage of learning- actions are chosen randomly.\n",
+ "number_episodes_per_round = 100_000\n",
+ "number_rounds = int(number_episodes / number_episodes_per_round)\n",
+ "errors = np.zeros(number_rounds)\n",
+ "final_round = 0\n",
+ "opponent1_results = list()\n",
+ "#opponent2_results = list()\n",
+ "for round_ in range(number_rounds):\n",
+ " algorithm.continue_learning(number_episodes_per_round,number_episodes_per_round * round_ +1)\n",
+ " adversary_probabilities[11]= 1\n",
+ " # adversary_probabilities[11] = 0.5\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " errors[round_] = result.error(1000)\n",
+ " if round_ % 50 == 0:\n",
+ " print(round_, errors[round_])\n",
+ " if round_ > 10 and np.max(errors[round_-10:round_]) < 0.01:\n",
+ " print(round_)\n",
+ " final_round = round_\n",
+ " break\n",
+ " \n",
+ " adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " adversary_probabilities[11]=1\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " payoff1, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " opponent1_results.append(payoff1)\n",
+ " print('Current payoff for adversary 1: ', payoff1)\n",
+ " \n",
+ " # adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " # adversary_probabilities[11]=1\n",
+ " # result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " # payoff2, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " # opponent2_results.append(payoff2)\n",
+ " # print('Current payoff for adversary 2: ', payoff2)\n",
+ " \n",
+ " if (round_ == number_rounds - 1):\n",
+ " final_round = round_\n",
+ " \n",
+ "plt.plot(errors[0:final_round+1])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Round 0 of 187\n",
+ "Best payoff: 128870\n",
+ "Best actions: [113, 122, 124, 125, 125, 125, 125, 112, 110, 109, 109, 110, 103, 114, 104, 106, 111, 110, 101, 112, 107, 107, 112, 116, 127]\n",
+ "Current payoff for adversary 1: 128294.0\n",
+ "Round 1 of 187\n",
+ "Best payoff: 131295\n",
+ "Best actions: [111, 124, 125, 124, 125, 124, 125, 129, 120, 118, 121, 112, 112, 111, 108, 122, 114, 104, 107, 117, 109, 120, 107, 112, 130]\n",
+ "Current payoff for adversary 1: 130908.0\n",
+ "Round 2 of 187\n",
+ "Best payoff: 132769\n",
+ "Best actions: [111, 125, 125, 125, 125, 124, 124, 125, 132, 116, 132, 114, 119, 106, 113, 110, 116, 108, 111, 114, 114, 111, 109, 112, 131]\n",
+ "Current payoff for adversary 1: 132769.0\n",
+ "Round 3 of 187\n",
+ "Best payoff: 133218\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 124, 125, 132, 117, 121, 116, 121, 108, 112, 110, 116, 108, 111, 114, 114, 111, 109, 112, 131]\n",
+ "Current payoff for adversary 1: 132096.0\n",
+ "Round 4 of 187\n",
+ "Best payoff: 133918\n",
+ "Best actions: [111, 124, 125, 125, 125, 125, 125, 124, 124, 126, 126, 117, 117, 113, 113, 115, 115, 112, 110, 115, 111, 117, 108, 113, 131]\n",
+ "Current payoff for adversary 1: 133221.0\n",
+ "Round 5 of 187\n",
+ "Best payoff: 134831\n",
+ "Best actions: [111, 125, 125, 125, 124, 125, 125, 125, 125, 125, 128, 121, 119, 121, 111, 115, 111, 112, 115, 113, 113, 115, 109, 117, 131]\n",
+ "Current payoff for adversary 1: 134805.0\n",
+ "Round 6 of 187\n",
+ "Best payoff: 134805\n",
+ "Best actions: [111, 125, 124, 125, 125, 125, 125, 125, 125, 125, 128, 121, 119, 120, 111, 115, 111, 112, 115, 113, 113, 115, 109, 117, 131]\n",
+ "Current payoff for adversary 1: 133876.0\n",
+ "Round 7 of 187\n",
+ "Best payoff: 135415\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 124, 124, 128, 119, 119, 121, 113, 116, 115, 115, 114, 113, 115, 109, 115, 131]\n",
+ "Current payoff for adversary 1: 134603.0\n",
+ "Round 8 of 187\n",
+ "Best payoff: 135867\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 128, 119, 121, 119, 113, 116, 116, 118, 115, 120, 118, 110, 113, 130]\n",
+ "Current payoff for adversary 1: 135216.0\n",
+ "Round 9 of 187\n",
+ "Best payoff: 135470\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 124, 125, 125, 125, 125, 129, 121, 118, 115, 115, 113, 113, 113, 115, 111, 112, 112, 115, 131]\n",
+ "Current payoff for adversary 1: 134642.0\n",
+ "Round 10 of 187\n",
+ "Best payoff: 136112\n",
+ "Best actions: [110, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 119, 117, 116, 114, 115, 114, 119, 113, 112, 114, 113, 132]\n",
+ "Current payoff for adversary 1: 136112.0\n",
+ "Round 11 of 187\n",
+ "Best payoff: 136202\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 119, 117, 116, 114, 115, 114, 116, 115, 112, 114, 113, 132]\n",
+ "Current payoff for adversary 1: 136130.0\n",
+ "Round 12 of 187\n",
+ "Best payoff: 136304\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 119, 117, 117, 114, 115, 115, 116, 115, 112, 115, 113, 132]\n",
+ "Current payoff for adversary 1: 136278.0\n",
+ "Round 13 of 187\n",
+ "Best payoff: 136361\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 124, 125, 125, 125, 125, 123, 120, 117, 118, 112, 115, 117, 114, 112, 115, 113, 132]\n",
+ "Current payoff for adversary 1: 136326.0\n",
+ "Round 14 of 187\n",
+ "Best payoff: 136444\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 123, 120, 117, 119, 113, 115, 117, 117, 111, 115, 113, 132]\n",
+ "Current payoff for adversary 1: 136185.0\n",
+ "Round 15 of 187\n",
+ "Best payoff: 136693\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 125, 123, 126, 116, 118, 118, 118, 113, 115, 117, 114, 114, 132]\n",
+ "Current payoff for adversary 1: 136129.0\n",
+ "Round 16 of 187\n",
+ "Best payoff: 136902\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 123, 121, 119, 119, 118, 117, 116, 114, 118, 114, 113, 133]\n",
+ "Current payoff for adversary 1: 136643.0\n",
+ "Round 17 of 187\n",
+ "Best payoff: 136876\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 124, 124, 125, 125, 125, 125, 123, 121, 119, 119, 119, 117, 116, 116, 117, 114, 113, 133]\n",
+ "Current payoff for adversary 1: 136252.0\n",
+ "Round 18 of 187\n",
+ "Best payoff: 137031\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 122, 122, 122, 121, 121, 117, 119, 120, 115, 112, 134]\n",
+ "Current payoff for adversary 1: 136934.0\n",
+ "Round 19 of 187\n",
+ "Best payoff: 137143\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 122, 119, 118, 116, 117, 118, 115, 117, 117, 113, 133]\n",
+ "Current payoff for adversary 1: 137106.0\n",
+ "Round 20 of 187\n",
+ "Best payoff: 137420\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 123, 121, 119, 119, 117, 116, 116, 117, 117, 113, 133]\n",
+ "Current payoff for adversary 1: 137420.0\n",
+ "Round 21 of 187\n",
+ "Best payoff: 137451\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 123, 121, 119, 119, 117, 116, 117, 117, 117, 113, 133]\n",
+ "Current payoff for adversary 1: 136653.0\n",
+ "Round 22 of 187\n",
+ "Best payoff: 137381\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 123, 122, 123, 123, 125, 113, 118, 117, 114, 132]\n",
+ "Current payoff for adversary 1: 137336.0\n",
+ "Round 23 of 187\n",
+ "Best payoff: 137381\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 123, 122, 123, 123, 125, 113, 118, 117, 114, 132]\n",
+ "Current payoff for adversary 1: 137006.0\n",
+ "Round 24 of 187\n",
+ "Best payoff: 137421\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 125, 124, 123, 125, 121, 120, 126, 117, 118, 119, 112, 134]\n",
+ "Current payoff for adversary 1: 136891.0\n",
+ "Round 25 of 187\n",
+ "Best payoff: 137715\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 122, 122, 122, 120, 122, 116, 119, 120, 112, 134]\n",
+ "Current payoff for adversary 1: 137605.0\n",
+ "Round 26 of 187\n",
+ "Best payoff: 137757\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 125, 125, 122, 122, 120, 121, 122, 116, 119, 120, 112, 134]\n",
+ "Current payoff for adversary 1: 137263.0\n",
+ "Round 27 of 187\n",
+ "Best payoff: 137955\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 123, 123, 121, 120, 122, 120, 118, 120, 112, 134]\n",
+ "Current payoff for adversary 1: 137935.0\n",
+ "Round 28 of 187\n",
+ "Best payoff: 137976\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 123, 122, 121, 121, 124, 117, 120, 120, 117, 133]\n",
+ "Current payoff for adversary 1: 137443.0\n",
+ "Round 29 of 187\n",
+ "Best payoff: 138049\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 125, 123, 123, 120, 120, 120, 120, 120, 120, 112, 134]\n",
+ "Current payoff for adversary 1: 137954.0\n",
+ "Round 30 of 187\n",
+ "Best payoff: 138072\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 123, 123, 120, 121, 120, 120, 120, 120, 112, 134]\n",
+ "Current payoff for adversary 1: 137913.0\n",
+ "Round 31 of 187\n",
+ "Best payoff: 138110\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 123, 123, 121, 121, 120, 120, 120, 120, 112, 134]\n",
+ "Current payoff for adversary 1: 137821.0\n",
+ "Round 32 of 187\n",
+ "Best payoff: 138228\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 124, 124, 125, 120, 118, 118, 114, 132]\n",
+ "Current payoff for adversary 1: 138228.0\n",
+ "Round 33 of 187\n",
+ "Best payoff: 138360\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 124, 125, 121, 119, 117, 113, 133]\n",
+ "Current payoff for adversary 1: 138360.0\n",
+ "Round 34 of 187\n",
+ "Best payoff: 138362\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 124, 125, 121, 119, 119, 113, 133]\n",
+ "Current payoff for adversary 1: 138362.0\n",
+ "Round 35 of 187\n",
+ "Best payoff: 138377\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 121, 119, 119, 113, 133]\n",
+ "Current payoff for adversary 1: 138377.0\n",
+ "Round 36 of 187\n",
+ "Best payoff: 138377\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 121, 119, 119, 113, 133]\n",
+ "Current payoff for adversary 1: 138377.0\n",
+ "Round 37 of 187\n"
+ ]
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Best payoff: 138569\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 123, 123, 121, 117, 133]\n",
+ "Current payoff for adversary 1: 138569.0\n",
+ "Round 38 of 187\n",
+ "Best payoff: 138581\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 123, 123, 121, 115, 133]\n",
+ "Current payoff for adversary 1: 138569.0\n",
+ "Round 39 of 187\n",
+ "Best payoff: 138586\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 123, 123, 121, 113, 134]\n",
+ "Current payoff for adversary 1: 138569.0\n",
+ "Round 40 of 187\n",
+ "Best payoff: 138581\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 123, 123, 121, 111, 133]\n",
+ "Current payoff for adversary 1: 138569.0\n",
+ "Round 41 of 187\n",
+ "Best payoff: 138581\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 123, 123, 121, 115, 133]\n",
+ "Current payoff for adversary 1: 138569.0\n",
+ "Round 42 of 187\n",
+ "Best payoff: 138581\n",
+ "Best actions: [111, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 124, 125, 123, 123, 121, 115, 133]\n",
+ "Current payoff for adversary 1: 138581.0\n",
+ "Round 43 of 187\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Below is the second stage of learning- actions are chosen according to an epsilon greedy strategy.\n",
+ "episode_counter = (final_round + 1) * number_episodes_per_round\n",
+ "episodes_left = number_episodes - episode_counter\n",
+ "number_episodes_per_round = 500_000\n",
+ "number_rounds = int(episodes_left / number_episodes_per_round)\n",
+ "\n",
+ "for round_ in range(number_rounds): \n",
+ " print('Round ', round_, ' of ', number_rounds)\n",
+ " algorithm.epsilon_greedy_learning(number_episodes_per_round, episode_counter)\n",
+ " \n",
+ " adversary_probabilities=[0]*len(AdversaryModes)\n",
+ " adversary_probabilities[11]=1\n",
+ " result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ " payoff1, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ " opponent1_results.append(payoff1)\n",
+ " print('Current payoff for adversary 1: ', payoff1)\n",
+ " \n",
+ "# adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# adversary_probabilities[11]=1\n",
+ "# result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ "# payoff2, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "# opponent2_results.append(payoff2)\n",
+ "# print('Current payoff for adversary 2: ', payoff2)\n",
+ " \n",
+ " episode_counter += number_episodes_per_round\n",
+ " \n",
+ "plt.plot(opponent1_results)\n",
+ "# plt.plot(opponent2_results)\n",
+ "plt.title(\"Payoff over the rounds\")\n",
+ "plt.xlabel(\"Rounds\")\n",
+ "plt.ylabel(\"Payoff at the end of each round\")\n",
+ "legend = [\"adversary 1\"]\n",
+ "plt.legend(legend)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Qtable.save(\"Qtable_guess125\")\n",
+ "\n",
+ "df1 = pd.DataFrame(opponent1_results)\n",
+ "#df2 = pd.DataFrame(opponent2_results)\n",
+ "\n",
+ "writer = pd.ExcelWriter('payoff_11.xlsx', engine='xlsxwriter')\n",
+ "df1.to_excel(writer, sheet_name='payoff_11', index=False)\n",
+ "#df2.to_excel(writer, sheet_name='payoff2', index=False)\n",
+ "writer.save()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# We now have the trained agent. We want to test it against each opponent individually, so that\n",
+ "# we can compare it against the agent that is just trained against this opponent. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Testing against one type of opponent by changing the * below to be the first number\n",
+ "adversary_probabilities[10]=1\n",
+ "result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ "payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "print(payoff)\n",
+ "print(adversary_payoff)\n",
+ "print(actions)\n",
+ "print(adversary_actions)\n",
+ "print(demand_potential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "# Testing against one type of opponent by changing the * below to be the first number\n",
+ "adversary_probabilities[11]=1\n",
+ "result = Test(game, Qtable, discount_factor, adversary_probabilities)\n",
+ "payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "print(payoff)\n",
+ "print(adversary_payoff)\n",
+ "print(actions)\n",
+ "print(adversary_actions)\n",
+ "print(demand_potential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.7"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qlearning/Episodic_learning_with_oneperiod_memory/.DS_Store b/qlearning/Episodic_learning_with_oneperiod_memory/.DS_Store
new file mode 100644
index 0000000..f14c032
Binary files /dev/null and b/qlearning/Episodic_learning_with_oneperiod_memory/.DS_Store differ
diff --git a/qlearning/Episodic_learning_with_oneperiod_memory/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb b/qlearning/Episodic_learning_with_oneperiod_memory/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
new file mode 100644
index 0000000..a8a1fc9
--- /dev/null
+++ b/qlearning/Episodic_learning_with_oneperiod_memory/.ipynb_checkpoints/qLearningSimulations-checkpoint.ipynb
@@ -0,0 +1,216 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_demand = 400\n",
+ "agent_cost = 57\n",
+ "adversary_cost = 71 \n",
+ "costs = [agent_cost,adversary_cost]\n",
+ "total_stages = 25\n",
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "adversary_probabilities[10]=1 \n",
+ "game = Model(total_demand, costs, total_stages, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "number_actions = 50\n",
+ "number_demands = total_demand + 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+demoninator)\n",
+ "Qtable = QTable(number_demands, number_actions, total_stages , learning_rate = [1000000,1000000])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "number_episodes = 10_000\n",
+ "discount_factor = 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, number_episodes, discount_factor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "0\n"
+ ]
+ }
+ ],
+ "source": [
+ "algorithm.solver()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "ValueError",
+ "evalue": "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)",
+ "\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_3432/448881527.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mmax\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mQtable\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mQ_table\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m200\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m:\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[1;31mValueError\u001b[0m: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"
+ ]
+ }
+ ],
+ "source": [
+ "max(Qtable.Q_table[200, :, 0, 0, 0])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.count_nonzero(Qtable.Q_table) / (number_actions * number_demands * number_actions* total_stages)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "adversary_probabilities[10]=1 # We can test the Q-Table against any strategy. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "result = Test(game, Qtable, discount_factor, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Returns the optimal payoff and actions according to the Qtable\n",
+ "payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "print(payoff)\n",
+ "print(adversary_payoff)\n",
+ "print(actions)\n",
+ "print(adversary_actions)\n",
+ "print(demand_potential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The percentage error of the Qtable. This has to be measured against the same opponent that \n",
+ "# it was trained against, as this is a measure of how 'complete' the training is.\n",
+ "result.error(10000)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from test import Test"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.7"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qlearning/Episodic_learning_with_oneperiod_memory/Qtable.py b/qlearning/Episodic_learning_with_oneperiod_memory/Qtable.py
new file mode 100644
index 0000000..2c852ac
--- /dev/null
+++ b/qlearning/Episodic_learning_with_oneperiod_memory/Qtable.py
@@ -0,0 +1,32 @@
+# Ed, Galit and Katerina
+# Relates to the Q-Learning approach.
+# Defines the Q-table
+
+import numpy as np
+
+class QTable():
+
+
+ def __init__(self, number_demands, number_actions, number_stages, learning_rate):
+
+ self.number_demands= number_demands
+ self.number_actions = number_actions
+ self.opponent_num_actions = 133
+ self.number_stages = number_stages
+ self.learning_rate = learning_rate
+ self.Q_table = np.zeros((self.number_demands, self.number_actions, self.number_actions, self.opponent_num_actions, self.number_stages))
+ self.QTable_name=f"QTable, actions={self.number_actions}, maximum demand={self.number_demands - 1}, stages={self.number_stages}"
+
+
+ def reset(self):
+ Qtable = np.zeros((self.number_demands, self.number_actions, self.number_actions, self.opponent_num_actions, self.number_stages))
+ return Qtable, self.learning_rate
+
+
+ def random_reset(self):
+ random_Qtable = np.random.rand(self.number_demands, self.number_actions, self.number_actions, self.opponent_num_actions, self.number_stages)
+ return random_Qtable, self.learning_rate
+
+
+
+
diff --git a/qlearning/Episodic_learning_with_oneperiod_memory/__pycache__/Qtable.cpython-39.pyc b/qlearning/Episodic_learning_with_oneperiod_memory/__pycache__/Qtable.cpython-39.pyc
new file mode 100644
index 0000000..deddd1f
Binary files /dev/null and b/qlearning/Episodic_learning_with_oneperiod_memory/__pycache__/Qtable.cpython-39.pyc differ
diff --git a/qlearning/Episodic_learning_with_oneperiod_memory/__pycache__/environment.cpython-39.pyc b/qlearning/Episodic_learning_with_oneperiod_memory/__pycache__/environment.cpython-39.pyc
new file mode 100644
index 0000000..9d4cc4d
Binary files /dev/null and b/qlearning/Episodic_learning_with_oneperiod_memory/__pycache__/environment.cpython-39.pyc differ
diff --git a/qlearning/Episodic_learning_with_oneperiod_memory/__pycache__/learningAgent.cpython-39.pyc b/qlearning/Episodic_learning_with_oneperiod_memory/__pycache__/learningAgent.cpython-39.pyc
new file mode 100644
index 0000000..e158d21
Binary files /dev/null and b/qlearning/Episodic_learning_with_oneperiod_memory/__pycache__/learningAgent.cpython-39.pyc differ
diff --git a/qlearning/Episodic_learning_with_oneperiod_memory/__pycache__/test.cpython-39.pyc b/qlearning/Episodic_learning_with_oneperiod_memory/__pycache__/test.cpython-39.pyc
new file mode 100644
index 0000000..9b60691
Binary files /dev/null and b/qlearning/Episodic_learning_with_oneperiod_memory/__pycache__/test.cpython-39.pyc differ
diff --git a/qlearning/Episodic_learning_with_oneperiod_memory/environment.py b/qlearning/Episodic_learning_with_oneperiod_memory/environment.py
new file mode 100644
index 0000000..9494874
--- /dev/null
+++ b/qlearning/Episodic_learning_with_oneperiod_memory/environment.py
@@ -0,0 +1,259 @@
+# Katerina, Ed and Galit (and Tommy!)
+# Relates to the Q-Learning approach.
+# Contains DemandPotentialGame Class and the Model of the DemandPotentialGame Class.
+
+from enum import Enum
+import numpy as np # numerical python
+# printoptions: output limited to 2 digits after decimal point
+np.set_printoptions(precision=2, suppress=False)
+
+
+class DemandPotentialGame():
+ """
+ Fully defines Demand Potential Game. It contains game rules, memory and agents strategies.
+ """
+
+ def __init__(self, total_demand, costs, total_stages) -> None:
+ self.total_demand = total_demand
+ self.costs = costs
+ self.total_stages = total_stages
+ # first index is always player
+ self.demand_potential = None # two lists for the two players
+ self.prices = None # prices over T rounds
+ self.profit = None # profit in each of T rounds
+ self.stage = None
+
+ def reset_game(self):
+ """
+ Method resets game memory: Demand Potential, prices, profits
+ """
+ self.demand_potential = [[0]*(self.total_stages), [0]*(self.total_stages)] # two lists for the two players
+ self.prices = [[0]*self.total_stages, [0]*self.total_stages] # prices over T rounds
+ self.profit = [[0]*self.total_stages, [0]*self.total_stages] # profit in each of T rounds
+ self.demand_potential[0][0] = self.total_demand / 2 # initialise first round 0
+ self.demand_potential[1][0] = self.total_demand/2
+
+ def profits(self, player=0):
+ """
+ Computes profits. Player 0 is the learning agent.
+ """
+ return self.profit[player][self.stage]
+
+ def update_prices_profit_demand(self, price_pair):
+ """
+ Updates Prices, Profit and Demand Potential Memory.
+ Parameters.
+ price_pair: Pair of prices from the Learning agent and adversary.
+ """
+
+ for player in [0, 1]:
+ price = int(price_pair[player])
+ self.prices[player][self.stage] = price
+ self.profit[player][self.stage] = int((
+ self.demand_potential[player][self.stage] - price)*(price - self.costs[player]))
+ if self.stage < self.total_stages-1:
+ self.demand_potential[0][self.stage + 1] = \
+ int(self.demand_potential[0][self.stage] + (price_pair[1] - price_pair[0])/2)
+ self.demand_potential[1][self.stage + 1] = 400 - self.demand_potential[0][self.stage + 1]
+
+
+ def monopoly_price(self, player): # myopic monopoly price
+ """
+ Computes Monopoly prices.
+ """
+ return (self.demand_potential[player][self.stage] + self.costs[player])/2
+
+ def myopic(self, player=0):
+ """
+ Adversary follows Myopic strategy
+ """
+ return self.monopoly_price(player)
+
+ def const(self, player, price): # constant price strategy
+ """
+ Adversary follows Constant strategy
+ """
+ return price
+
+ def imit(self, player, firstprice): # price imitator strategy
+ if self.stage == 0:
+ return firstprice
+ return self.prices[1-player][self.stage-1]
+
+ def fight(self, player, firstprice): # simplified fighting strategy
+ if self.stage == 0:
+ return firstprice
+ if self.stage == self.total_stages-1:
+ return self.monopoly_price(player)
+ # aspire = [ 207, 193 ] # aspiration level for demand potential
+ aspire = [0, 0]
+ for i in range(2):
+ aspire[i] = (self.total_demand-self.costs[player] +
+ self.costs[1-player])/2
+
+ D = self.demand_potential[player][self.stage]
+ Asp = aspire[player]
+ if D >= Asp: # keep price; DANGER: price will never rise
+ return self.prices[player][self.stage-1]
+ # adjust to get to aspiration level using previous
+ # opponent price; own price has to be reduced by twice
+ # the negative amount D - Asp to getself.demand_potential to Asp
+ P = self.prices[1-player][self.stage-1] + 2*(D - Asp)
+ # never price too high because even 125 gives good profits
+ # P = min(P, 125)
+ aspire_price = (self.total_demand+self.costs[0]+self.costs[1])/4
+ P = min(P, int(0.95*aspire_price))
+
+ return P
+
+ def fight_lb(self, player, firstprice):
+ P = self.fight(player, firstprice)
+ # never price less than production cost
+ P = max(P, self.costs[player])
+ return P
+
+ # sophisticated fighting strategy, compare fight()
+ # estimate *sales* of opponent as their target, kept between
+ # calls in global variable oppsaleguess[]. Assumed behavior
+ # of opponent is similar to this strategy itself.
+ oppsaleguess = [61, 75] # first guess opponent sales as in monopoly
+
+ def guess(self, player, firstprice): # predictive fighting strategy
+ if self.stage == 0:
+ self.oppsaleguess[0] = 61 # always same start
+ self.oppsaleguess[1] = 75 # always same start
+ return firstprice
+
+ if self.stage == self.total_stages-1:
+ return self.monopoly_price(player)
+ aspire = [207, 193] # aspiration level
+ D = self.demand_potential[player][self.stage]
+ Asp = aspire[player]
+
+ if D >= Asp: # keep price, but go slightly towards monopoly if good
+ pmono = self.monopoly_price(player)
+ pcurrent = self.prices[player][self.stage-1]
+ if pcurrent > pmono: # shouldn't happen
+ return pmono
+ if pcurrent > pmono-7: # no change
+ return pcurrent
+ # current low price at 60%, be accommodating towards "collusion"
+ return .6 * pcurrent + .4 * (pmono-7)
+
+ # guess current *opponent price* from previous sales
+ prevsales = self.demand_potential[1 - player][t-1] - self.prices[1-player][t-1]
+ # adjust with weight alpha from previous guess
+ alpha = .5
+ newsalesguess = alpha * self.oppsaleguess[player] + (1-alpha)*prevsales
+ # update
+ self.oppsaleguess[player] = newsalesguess
+ guess_opponent_price = 400 - D - newsalesguess
+ P = guess_opponent_price + 2*(D - Asp)
+
+ if player == 0:
+ P = min(P, 125)
+ if player == 1:
+ P = min(P, 130)
+ return P
+
+
+class Model(DemandPotentialGame):
+ """
+ Defines the Problem's Model. It is assumed a Markov Decision Process is defined. The class is a Child from the Demand Potential Game Class.
+ The reason: Model is a conceptualization of the Game.
+ """
+
+ def __init__(self, total_demand, costs, total_stages, adversary_probabilities) -> None:
+ super().__init__(total_demand, costs, total_stages)
+
+ self.reward_function = self.profits
+
+ # [stage, agent's demand potential, agent previous action, adv previous action]
+ self.initial_state = [0, total_demand/2, 0, 0]
+ self.episode_memory = list()
+ self.done = False
+ self.adversary_probabilities = adversary_probabilities
+
+ def reset(self):
+ """
+ Reset Model Instantiation.
+ """
+ reward = 0
+ self.stage = 0
+ self.done = False
+ self.reset_game()
+ self.reset_adversary()
+ return self.initial_state, reward, self.done
+
+ def reset_adversary(self):
+ options = list(range(len(self.adversary_probabilities)))
+ adversary_index = np.random.choice(options, 1, p= self.adversary_probabilities)
+ self.adversary_mode = AdversaryModes(adversary_index)
+
+ def adversary_choose_price(self):
+ """
+ Strategy followed by the adversary.
+ """
+
+ if self.adversary_mode == AdversaryModes.constant_132:
+ return self.const(player=1, price=132)
+ elif self.adversary_mode == AdversaryModes.constant_95:
+ return self.const(player=1, price=95)
+ elif self.adversary_mode == AdversaryModes.imitation_128:
+ return self.imit(player=1, firstprice=128)
+ elif self.adversary_mode == AdversaryModes.imitation_132:
+ return self.imit(player=1, firstprice=132)
+ elif self.adversary_mode == AdversaryModes.fight_100:
+ return self.fight(player=1, firstprice=100)
+ elif self.adversary_mode == AdversaryModes.fight_125:
+ return self.fight(player=1, firstprice=125)
+ elif self.adversary_mode == AdversaryModes.fight_lb_125:
+ return self.fight_lb(player=1, firstprice=125)
+ elif self.adversary_mode == AdversaryModes.fight_132:
+ return self.fight(player=1, firstprice=132)
+ elif self.adversary_mode == AdversaryModes.fight_lb_132:
+ return self.fight_lb(player=1, firstprice=132)
+ elif self.adversary_mode == AdversaryModes.guess_125:
+ return self.fight(player=1, firstprice=125)
+ elif self.adversary_mode == AdversaryModes.guess_132:
+ return self.fight(player=1, firstprice=132)
+ else:
+ return self.myopic(player=1)
+
+ def step(self, state, action, action_index):
+ """
+ Transition Function.
+ Parameters:
+ - action: Price
+ - state: tupple in the latest stage (stage ,Demand Potential, Adversary Action)
+ """
+ adversary_action = int(self.adversary_choose_price())
+ self.update_prices_profit_demand([action, adversary_action])
+
+ done = (self.stage == self.total_stages-1)
+
+
+ if not done:
+ new_state = [self.stage+1, self.demand_potential[0][self.stage + 1], action_index, adversary_action]
+ else:
+ new_state = [self.stage+1, 0, action_index, adversary_action]
+
+ reward = self.reward_function()
+ self.stage = self.stage + 1
+
+ return new_state, reward, done
+
+
+class AdversaryModes(Enum):
+ myopic = 0
+ constant_132 = 1
+ constant_95 = 2
+ imitation_132 = 3
+ imitation_128 = 4
+ fight_132 = 5
+ fight_lb_132 = 6
+ fight_125 = 7
+ fight_lb_125 = 8
+ fight_100 = 9
+ guess_132 = 10
+ guess_125 = 11
\ No newline at end of file
diff --git a/qlearning/Episodic_learning_with_oneperiod_memory/learningAgent.py b/qlearning/Episodic_learning_with_oneperiod_memory/learningAgent.py
new file mode 100644
index 0000000..700e9c5
--- /dev/null
+++ b/qlearning/Episodic_learning_with_oneperiod_memory/learningAgent.py
@@ -0,0 +1,88 @@
+# Ed, Kat, Galit
+# ReinforceAlgorithm Class: Solver.
+# Implement an off-policy Q-learning algorithm
+
+import numpy as np #repeated
+
+# printoptions: output limited to 2 digits after decimal point
+np.set_printoptions(precision=2, suppress=False)
+
+
+class LearningAlgorithm():
+ """
+ Model Solver.
+ """
+ def __init__(self, Model, Qtable, number_episodes, discount_factor) -> None:
+
+ self.env = Model
+ self.Qtable = Qtable.Q_table
+ self.learning_rate = Qtable.learning_rate
+ self.number_episodes = number_episodes
+ self.gamma = discount_factor
+ self.number_demands=Qtable.number_demands #Qtable dimen - number of states x number of actions x number of stages
+ self.number_stages=Qtable.number_stages
+ self.number_actions=Qtable.number_actions
+ self.highest_demand = int(self.number_demands - 1)
+
+
+ def reset_Qtable(self):
+ self.Qtable, self.learning_rate = self.Qtable.reset()
+
+
+ def action_index(self, monopoly_price, action): # computes action index in Qtable
+ return int(action - (monopoly_price - self.number_actions + 1)) #monopoly_price should have index number_actions - 1
+
+ def alpha_n(self, n): # defines the Qlearning rate
+ return self.learning_rate[0]/(n+self.learning_rate[1])
+
+ """
+ Now the Q-learning itself
+ """
+
+ def random_policy(self, monopoly_price):
+ random_action = np.random.randint(monopoly_price-self.number_actions+1, monopoly_price + 1)
+ if random_action < 0:
+ random_action = max(0, random_action)
+ if self.env.costs[0] > random_action:
+ random_action = monopoly_price
+ return random_action
+
+ def q_learning(self, state_action_value, optimal_next_value, reward, alpha, gamma):
+ target = reward + gamma * optimal_next_value
+ return state_action_value + alpha * (target - state_action_value)
+
+
+ def solver(self):
+
+ self.reset_Qtable
+
+ for episode in range(self.number_episodes):
+
+ if episode % 500_000 == 0:
+ print(episode)
+
+ state, reward, done = self.env.reset()
+
+ while not done:
+ stage, agent_demand, agent_previous_action, adversary_previous_action = state
+ if (agent_demand < 0) or (agent_demand > self.highest_demand):
+ break
+ if (stage > 0 and adversary_previous_action < self.env.costs[1]) or (self.highest_demand - agent_demand < adversary_previous_action):
+ break
+ monopoly_price = int((agent_demand + self.env.costs[0]) / 2)
+ action = self.random_policy(monopoly_price)
+ demand_index = int(agent_demand)
+ action_index = self.action_index(monopoly_price, action)
+ state, reward, done = self.env.step(state, action, action_index)
+
+
+ # updating the Qtable
+ if done:
+ optimal_next_value = 0
+ else:
+ optimal_next_value = max(self.Qtable[int(state[1]),:, action_index, adversary_previous_action, state[0]])
+
+ current_q_value = self.Qtable[demand_index, action_index, agent_previous_action, adversary_previous_action, stage]
+
+ self.Qtable[demand_index, action_index, agent_previous_action, adversary_previous_action, stage] = self.q_learning(current_q_value, optimal_next_value, reward, self.alpha_n(episode), self.gamma)
+
diff --git a/qlearning/Episodic_learning_with_oneperiod_memory/qLearningSimulations.ipynb b/qlearning/Episodic_learning_with_oneperiod_memory/qLearningSimulations.ipynb
new file mode 100644
index 0000000..768fc91
--- /dev/null
+++ b/qlearning/Episodic_learning_with_oneperiod_memory/qLearningSimulations.ipynb
@@ -0,0 +1,209 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from learningAgent import LearningAlgorithm\n",
+ "from environment import Model, AdversaryModes\n",
+ "from Qtable import QTable\n",
+ "from test import Test\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.seed(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "total_demand = 400\n",
+ "agent_cost = 57\n",
+ "adversary_cost = 71 \n",
+ "costs = [agent_cost,adversary_cost]\n",
+ "total_stages = 25\n",
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "adversary_probabilities[10]=1 \n",
+ "game = Model(total_demand, costs, total_stages, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "number_actions = 50\n",
+ "number_demands = total_demand + 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "MemoryError",
+ "evalue": "Unable to allocate 24.8 GiB for an array with shape (401, 50, 50, 133, 25) and data type float64",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[1;31mMemoryError\u001b[0m Traceback (most recent call last)",
+ "\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_27152/403285856.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;31m# Learning rate is given as [numerator,denominator] which gives us a learning rate function of\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;31m# numerator/(n+demoninator)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mQtable\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mQTable\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnumber_demands\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnumber_actions\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtotal_stages\u001b[0m \u001b[1;33m,\u001b[0m \u001b[0mlearning_rate\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m1000000\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m1000000\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[1;32m~\\Documents\\GitHub\\EquiLearn\\qlearning\\Episodic_learning_with_oneperiod_memory\\Qtable.py\u001b[0m in \u001b[0;36m__init__\u001b[1;34m(self, number_demands, number_actions, number_stages, learning_rate)\u001b[0m\n\u001b[0;32m 15\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnumber_stages\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnumber_stages\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 16\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlearning_rate\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mlearning_rate\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 17\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mQ_table\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnumber_demands\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnumber_actions\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnumber_actions\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mopponent_num_actions\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnumber_stages\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 18\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mQTable_name\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34mf\"QTable, actions={self.number_actions}, maximum demand={self.number_demands - 1}, stages={self.number_stages}\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 19\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
+ "\u001b[1;31mMemoryError\u001b[0m: Unable to allocate 24.8 GiB for an array with shape (401, 50, 50, 133, 25) and data type float64"
+ ]
+ }
+ ],
+ "source": [
+ "# Learning rate is given as [numerator,denominator] which gives us a learning rate function of \n",
+ "# numerator/(n+demoninator)\n",
+ "Qtable = QTable(number_demands, number_actions, total_stages , learning_rate = [1000000,1000000])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "number_episodes = 10_000\n",
+ "discount_factor = 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "algorithm = LearningAlgorithm(game, Qtable, number_episodes, discount_factor)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "algorithm.solver()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "max(Qtable.Q_table[200, :, 0, 0, 0])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.count_nonzero(Qtable.Q_table) / (number_actions * number_demands * number_actions* total_stages)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "adversary_probabilities=[0]*len(AdversaryModes)\n",
+ "adversary_probabilities[10]=1 # We can test the Q-Table against any strategy. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "result = Test(game, Qtable, discount_factor, adversary_probabilities)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Returns the optimal payoff and actions according to the Qtable\n",
+ "payoff, adversary_payoff, actions, adversary_actions, demand_potential = result.total_payoff()\n",
+ "print(payoff)\n",
+ "print(adversary_payoff)\n",
+ "print(actions)\n",
+ "print(adversary_actions)\n",
+ "print(demand_potential)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The percentage error of the Qtable. This has to be measured against the same opponent that \n",
+ "# it was trained against, as this is a measure of how 'complete' the training is.\n",
+ "result.error(10000)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from test import Test"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.9.7"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/qlearning/Episodic_learning_with_oneperiod_memory/test.py b/qlearning/Episodic_learning_with_oneperiod_memory/test.py
new file mode 100644
index 0000000..ff3d7f0
--- /dev/null
+++ b/qlearning/Episodic_learning_with_oneperiod_memory/test.py
@@ -0,0 +1,150 @@
+# Ed, Galit and Katerina
+# Relates to the Q-Learning approach.
+# Testing out the Q-table against a given opponent
+
+import numpy as np
+from environment import AdversaryModes
+
+
+class Test():
+
+
+ def __init__(self, Model, Qtable, discount_factor, adversary_probabilities) -> None:
+
+
+ self.env = Model
+ self.Qtable = Qtable.Q_table
+ self.number_demands=Qtable.number_demands
+ self.number_actions=Qtable.number_actions
+ self.number_stages=Qtable.number_stages
+ self.discount_factor = discount_factor
+ self.adversary_probabilities = adversary_probabilities
+ self.adversary = None
+
+
+
+ def set_adversary(self):
+ options = list(range(len(self.adversary_probabilities)))
+ adversary_index = int(np.random.choice(options, 1, p= self.adversary_probabilities))
+ self.adversary = AdversaryModes(adversary_index)
+ new_probabilities = [0]*len(self.adversary_probabilities)
+ new_probabilities[adversary_index] = 1
+ self.env.adversary_probabilities = new_probabilities
+
+
+ def total_payoff(self):
+
+ self.set_adversary()
+
+ delta = 1
+ utility = 0
+ adversary_utility = 0
+ actions = [0]*self.number_stages
+ adversary_actions = [0]*self.number_stages
+ demands = [0]*self.number_stages
+ state_vector, reward, done = self.env.reset()
+ demand = state_vector[1]
+ previous_action = state_vector[2]
+ previous_adversary_action = state_vector[3]
+
+ for stage in range(self.number_stages):
+ demands[stage] = demand
+ if demand >= self.number_demands:
+ print("max demand reached")
+ demand = self.number_demands - 1
+ if demand < 0:
+ print("min demand reached")
+ demand = 0
+ demand_index = int(demand)
+ action_index = np.argmax(self.Qtable[demand_index, :, previous_action, previous_adversary_action, stage])
+ action = action_index + int((demand + self.env.costs[0])/2) - self.number_actions + 1
+ actions[stage] = action
+ utility += (demand-action)*(action-self.env.costs[0]) * delta
+ adversary_demand = 400 - demand
+ state_vector, _, _ = self.env.step(state_vector, action, action_index)
+ demand = state_vector[1]
+ previous_action = state_vector[2]
+ adversary_actions[stage] = state_vector[3]
+ adversary_utility += (adversary_demand-adversary_actions[stage])*(adversary_actions[stage]-self.env.costs[1]) * delta
+ delta *= self.discount_factor
+ return utility, adversary_utility, np.transpose(actions), np.transpose(adversary_actions), np.transpose(demands)
+
+
+ def q_learning(self, state_action_value, optimal_next_value, reward, alpha, gamma):
+ target = reward + gamma * optimal_next_value
+ return state_action_value + alpha * (target - state_action_value)
+
+ def error(self, number_tests):
+
+ self.set_adversary()
+
+ errors = np.zeros(number_tests)
+
+ for test in range(number_tests):
+ state, reward, done = self.env.reset()
+ stage, demand, previous_action, _ = state
+
+
+ while not done:
+ if demand >= self.number_demands:
+ print("max demand reached")
+ demand = self.number_demands - 1
+ if demand < 0:
+ print("min demand reached")
+ demand = 0
+ demand_index = int(demand)
+ action_index = np.random.randint(0, self.number_actions)
+ previous_action = int(previous_action)
+ action = action_index + int((demand + self.env.costs[0])/2) - self.number_actions + 1
+ state, reward, done = self.env.step(state, action, action_index)
+ stage, demand, previous_action, previous_adversary_action = state
+
+ if done:
+ optimal_next_value = 0
+ else:
+ optimal_next_value = max(self.Qtable[demand,:, action_index, previous_adversary_action, stage])
+
+ new_value = reward + self.discount_factor * optimal_next_value
+ if new_value != 0:
+ errors[test] += (new_value - self.Qtable[demand_index, action_index, previous_action, previous_adversary_action, stage-1])/new_value
+ if new_value == 0 and self.Qtable[demand_index,action_index, previous_action, previous_adversary_action, stage-1] != 0:
+ print("Div by zero error") # This should not occur
+ return errors.mean()/self.number_stages
+
+
+
+
+ def myopic(self, cost, demand):
+ return (cost + demand)/2
+
+ def payoff(self, cost, demand, price):
+ return (demand - price)*(price - cost)
+
+ def update_demand(self, demand, price_pair):
+ new_demand = demand + 0.5*(price_pair[1]- price_pair[0])
+ return new_demand
+
+ def utility_of_actions(self, actions):
+ agent_demand = 200
+ opponent_demand = 200
+ total_payoff = 0
+ delta = 1/self.discount_factor
+ for i in range(self.number_stages):
+ delta = delta * self.discount_factor
+ agent_price = int(actions[i])
+ opponent_price = int(self.myopic(self.env.costs[1],opponent_demand))
+ total_payoff += self.payoff(self.env.costs[0],agent_demand,agent_price) * delta
+ agent_demand = int(self.update_demand(agent_demand, [agent_price,opponent_price]))
+ opponent_demand = 400 - agent_demand
+ return total_payoff
+
+
+
+
+
+
+
+
+
+
+