packages = ["numpy", "matplotlib",]
Battle Simulator Using Lanchester's Law for Aimed Fire
target = "sim_output"
def sim():
# Battle Simulator Using Lanchester's Law for Aimed Fire
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['axes.spines.top'] = False
mpl.rcParams['axes.spines.right'] = False
# simulation inputs
# starting troop levels for x, y
x0 = int(Element('x0').element.value)
y0 = int(Element('y0').element.value)
# lethality coefficients for x, y
a = float(Element('a').element.value)
b = float(Element('b').element.value)
dt = .1 # integration timestep
# initializations
time, x, y = 0, x0, y0
timepoints, xpoints, ypoints = [time], [x], [y]
PyScript.write(target, '', append=False)
fig, axis = plt.subplots()
verbose = False
# print output header and starting values
#print (f"{'time':<6} {'x':<6} {'y':<6}") # all columns left justified 6 characters
if verbose: PyScript.write(target, f"{'time':<6} {'x':<6} {'y':<6}", append=True)
#print (f"{time:<6.2f} {x:<6.0f} {y:<6.0f}")
if verbose: PyScript.write(target, f"{time:<6.2f} {x:<6.0f} {y:<6.0f}", append=True)
# integration of troop levels using Euler's method
while x > 0 and y > 0: # run until a troop is eliminated
time += dt
Δx = -b * y
Δy = -a * x
x += Δx * dt
y += Δy * dt
#print (f"{time:<6.2f} {max(x, 0):<6.0f} {max(y, 0):<6.0f}") # max will clip negative end values due to dt timestep approximation
if verbose: PyScript.write(target, f"{time:<6.2f} {max(x, 0):<6.0f} {max(y, 0):<6.0f}", append=True)
timepoints += [time]
xpoints += [x]
ypoints += [y]
axis.set(xlabel = 'Time', ylabel = 'Troops')
plt.plot(timepoints, xpoints, 'red', label='Red')
plt.plot(timepoints, ypoints, 'blue', label='Blue')
axis.legend(loc="upper center", )
pyscript.write(target, fig, append=True)
sim()
def on_click(event): sim()
import random
def plotit(*args, **kwargs):
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([2, 3, 5, random.random()*10])
#print('plotting')
pyscript.write('sim_output', fig)