In [1]:

```
## Import various packages that enable this notebook to work
import sys
!{sys.executable} -m pip install scipy
import numpy
import pylab
from scipy import optimize
```

In [2]:

```
## Define the Benefit and Cost Functions
def Benefit(x):
return x*(4-x)
def Cost(x):
return x*x
```

In [3]:

```
## Define the Payoff functions for both players
def APayoff(a,b): return Benefit(a+b)-Cost(a)
def BPayoff(a,b): return Benefit(a+b)-Cost(b)
```

In [4]:

```
## Suppose A invests a=0.6. How should B respond?
## Let's try all the values from 0 to 1, in increments of 0.1
for b in range(0,11):
print("An investment of b =", b/10, "yields a payoff of", round(BPayoff(0.6,b/10),4))
```

In [5]:

```
## Given an input value for the variable a, this function determines the optimal value of b.
## Thus, after A invests some amount a, this function calculates B's best response move b that maximizes his payoff,
## i.e., minimizes the value of -BPayoff. We do this to take advantage of Python's Optimize.Minimize function.
def GetBestB(a):
def func(x): return -BPayoff(a,x)
BestB = optimize.minimize_scalar(func,bounds=(0,1), method='bounded')
b = BestB.x
return b
```

In [6]:

```
GetBestB(0.6)
```

Out[6]:

In [7]:

```
## Thus, if A selects a=0.6, B will respond with b=0.7, which is the move that maximizes B's payoff.
## Below we see the payoffs for both players.
APayoff(0.6,0.7),BPayoff(0.6,0.7)
```

Out[7]:

In [8]:

```
## Now that we can caculate GetBestB(a) for all values of a, A wants to select the value of a that maximizes her payoff.
## The function below determines this value of a.
def GetBestA():
def f(x): return -APayoff(x,GetBestB(x))
BestA = optimize.minimize_scalar(f,bounds=(0,1), method='bounded')
a = BestA.x
return a
```

In [9]:

```
## Now we have Python determine the optimal values of a and b.
a = GetBestA()
b = GetBestB(a)
print("A's optimal strategy is a =", a)
print("B's optimal strategy is b =", b)
print("The payoff to A is", APayoff(a,b), "and the payoff to B is", BPayoff(a,b))
```

In [10]:

```
## Let's generalize this to other Benefit and Cost functions.
## We'll assume that the Benefit and Cost functions are quadratic, i.e, Benefit(x)=px^2+qx+r and Cost(x)=sx^2+tx+u
## The function below is simply a cut+paste of what we showed above.
def CalculatePayoffs(p,q,r,s,t,u):
def Benefit(x): return p*x*x + q*x + r
def Cost(x): return s*x*x + t*x + u
def APayoff(a,b): return Benefit(a+b)-Cost(a)
def BPayoff(a,b): return Benefit(a+b)-Cost(b)
def GetBestB(a):
def func(x): return -BPayoff(a,x)
BestB = optimize.minimize_scalar(func,bounds=(0,1), method='bounded')
b = BestB.x
return b
def GetBestA():
def f(x): return -APayoff(x,GetBestB(x))
BestA = optimize.minimize_scalar(f,bounds=(0,1), method='bounded')
a = BestA.x
return a
a = GetBestA()
b = GetBestB(a)
print("A's optimal strategy is a =", a)
print("B's optimal strategy is b =", b)
print("The payoff to A is", APayoff(a,b), "and the payoff to B is", BPayoff(a,b))
print()
return
```

In [11]:

```
## Let's double-check our answers for our original question, where Benefit(x)=x(4-x)=-x^2+4x+0 and Cost(x)=x^2.
## Thus, we have p=-1, q=4, r=0, s=1, t=0, u=0 in this example.
CalculatePayoffs(-1,4,0,1,0,0)
```

In [12]:

```
## Now use the SLIDERS below to adjust the values of p,q,r,s,t,u. Instantly we see the optimal values and payoffs.
## Do you notice anything interesting?
from __future__ import print_function
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets
interact(CalculatePayoffs,
p=widgets.IntSlider(min=-10, max=10, step=1, value=-1),
q=widgets.IntSlider(min=-10, max=10, step=1, value=4),
r=widgets.IntSlider(min=-10, max=10, step=1, value=0),
s=widgets.IntSlider(min=-10, max=10, step=1, value=1),
t=widgets.IntSlider(min=-10, max=10, step=1, value=0),
u=widgets.IntSlider(min=-10, max=10, step=1, value=0))
```

Out[12]: