# Milkmaid and Cow Problem Display Matplotlib

unknown
python
2 months ago
4.5 kB
2
Indexable
Never
```import numpy as np
import matplotlib.pyplot as plt
import scipy.optimize
from matplotlib.widgets import Slider
import random
from matplotlib import style

def find_root(a, b, x_1, x_2, y_1, y_2, tol=1e-5, max_iter=100):
if distanceDeriv(a, x_1, x_2, y_1, y_2) * distanceDeriv(b, x_1, x_2, y_1, y_2) > 0:
return None  # No root in this interval
for _ in range(max_iter):
c = (a + b) / 2
if distanceDeriv(c, x_1, x_2, y_1, y_2) == 0 or (b - a) / 2 < tol:
return c  # Found the root within tolerance
if distanceDeriv(c, x_1, x_2, y_1, y_2) * distanceDeriv(a, x_1, x_2, y_1, y_2) < 0:
b = c
else:
a = c
return (a + b) / 2  # Return the midpoint as an approximation

def secureRoot(a, b, x_1, x_2, y_1, y_2):
root = None
while root is None:
root = find_root(a, b, x_1, x_2, y_1, y_2, tol=1e-5, max_iter=100)
if distanceDeriv((root-0.0000001), x_1, x_2, y_1, y_2) < 0 and distanceDeriv((root+0.0000001), x_1, x_2, y_1, y_2) > 0 and root is not None:
return root
if root is None:
while root is None:
a = random.randint(-10, 10)
b = random.randint(-10, 10)
if a > b:
a = random.randint(-10, 10)
b = random.randint(-10, 10)
root = find_root(a, b, x_1, x_2, y_1, y_2, tol=1e-5, max_iter=100)
return root

# Create the figure and axis
fig, ax = plt.subplots()

def f(x):
return x**2

def df(x):
return 2*x

def distanceDeriv(x, x_1, x_2, y_1, y_2):

return ((x-x_1)+df(x)*(f(x)-y_1))/(((x-x_1)**2+(f(x)-y_1)**2)**(1/2)) + ((x-x_2)+df(x)*(f(x)-y_2))/(((x-x_2)**2+(f(x)-y_2)**2)**(1/2))

# Define the initial values for a, b, and c
initial_x_1 = 1.0
initial_x_2 = 1.0
initial_y_1 = 0.0
initial_y_2 = 0.0
InitialPointsX = [initial_x_1, initial_x_2, secureRoot(-10, 10, initial_x_1, initial_x_2, initial_y_1, initial_y_2)]
InitialPointsY = [initial_y_1, initial_y_2, f(secureRoot(-10, 10, initial_x_1, initial_x_2, initial_y_1, initial_y_2))]

# Define the function to plot
x = np.linspace(-10, 10, 400)
initial_y = distanceDeriv(x, initial_x_1, initial_x_2, initial_y_1, initial_y_2)
#Uncomment this if you wanna see the derivative function
#line, = ax.plot(x, initial_y, label='D\'(x)')
PointandLine1, = ax.plot([initial_x_1, secureRoot(-10, 10, initial_x_1, initial_x_2, initial_y_1, initial_y_2)], [initial_y_1, f(secureRoot(-10, 10, initial_x_1, initial_x_2, initial_y_1, initial_y_2))], 'ro-')
PointandLine2, = ax.plot([secureRoot(-10, 10, initial_x_1, initial_x_2, initial_y_1, initial_y_2), initial_x_2], [f(secureRoot(-10, 10, initial_x_1, initial_x_2, initial_y_1, initial_y_2)), initial_y_2], 'ro-')
# Define sliders
slider_x_1 = Slider(plt.axes([0.1, 0.20, 0.8, 0.03]), label='x_1', valmin=x.min(), valmax=x.max(), valinit=initial_x_1, valstep=0.1)
slider_x_2 = Slider(plt.axes([0.1, 0.10, 0.8, 0.03]), label='x_2', valmin=x.min(), valmax=x.max(), valinit=initial_x_2, valstep=0.1)
slider_y_1 = Slider(plt.axes([0.1, 0.15, 0.8, 0.03]), label='y_1', valmin=-f(x.min()), valmax=f(x.max()), valinit=initial_y_1, valstep=0.1)
slider_y_2 = Slider(plt.axes([0.1, 0.05, 0.8, 0.03]), label='y_2', valmin=-f(x.min()), valmax=f(x.max()), valinit=initial_y_2, valstep=0.1)
ax.plot(x,f(x))
cow = ax.annotate("Cow", xy=(initial_x_2, initial_y_2), xytext=(initial_x_2-0.55, initial_y_2+3))
milkmaid = ax.annotate("Milkmaid", xy=(initial_x_1, initial_y_1), xytext=(initial_x_1-1.25, initial_y_1+3))
#Define function to update plot when sliders change
def update(val):
x_1 = slider_x_1.val
x_2 = slider_x_2.val
y_1 = slider_y_1.val
y_2 = slider_y_2.val
root = secureRoot(-10, 10, x_1, x_2, y_1, y_2)
y = distanceDeriv(x, x_1, x_2, y_1, y_2)
#Uncomment this if you wanna see the derivative function
#line.set_ydata(y)
#line.set_label('D\'(x)')
PointandLine1.set_xdata([x_1, root])
PointandLine1.set_ydata([y_1, f(root)])
PointandLine2.set_xdata([root, x_2])
PointandLine2.set_ydata([f(root), y_2])
print(root)
cow.set_x(x_2-0.55)
cow.set_y(y_2+3)
milkmaid.set_x(x_1-1.25)
milkmaid.set_y(y_1+3)
plt.draw()

slider_x_1.on_changed(update)
slider_x_2.on_changed(update)
slider_y_1.on_changed(update)
slider_y_2.on_changed(update)

plt.show()```