first_order_conditions.py
import%20marimo%0A%0A__generated_with%20%3D%20%220.1.64%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%22%23%20First%20order%20conditions%22).left()%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(torch)%3A%0A%20%20%20%20function%20%3D%20torch.exp%0A%20%20%20%20return%20function%2C%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20x_min%20%3D%20mo.ui.number(%0A%20%20%20%20%20%20%20%20start%3D-10%2C%20stop%3D10%2C%20value%3D-3%2C%20step%3D1%2C%20label%3Dr%22%24x_%5Ctext%7Bmin%7D%24%22%0A%20%20%20%20)%0A%20%20%20%20x_max%20%3D%20mo.ui.number(%0A%20%20%20%20%20%20%20%20start%3D-10%2C%20stop%3D10%2C%20value%3D3%2C%20step%3D1%2C%20label%3Dr%22%24x_%5Ctext%7Bmax%7D%24%22%0A%20%20%20%20)%0A%20%20%20%20parameters%20%3D%20mo.hstack(%5Bx_min%2C%20x_max%5D%2C%20justify%3D%22start%22)%0A%20%20%20%20return%20parameters%2C%20x_max%2C%20x_min%0A%0A%0A%40app.cell%0Adef%20__(function%2C%20mo)%3A%0A%20%20%20%20mo.md(rf%22Is%20the%20function%20%24f(x)%20%3D%20%5Ctext%7B%7B%7Bfunction.__name__%7D%7D%7D(x)%24%20convex%3F%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(mo%2C%20parameters%2C%20x_max%2C%20x_min)%3A%0A%20%20%20%20x%20%3D%20mo.ui.slider(x_min.value%2C%20x_max.value%2C%20value%3Dx_min.value%2C%20step%3D0.1)%0A%20%20%20%20mo.hstack(%5Bparameters%2C%20mo.md(f%22Evaluate%20%24f%24%20at%20%24x%20%3D%24%20%7Bx%7D%22)%5D%2C%20justify%3D%22start%22)%0A%20%20%20%20return%20x%2C%0A%0A%0A%40app.cell%0Adef%20__(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20f%22%22%22%0A%20%20%20%20%20%20%20%20If%20the%20function%20is%20convex%2C%20then%20%0A%0A%20%20%20%20%20%20%20%20%5C%5B%0A%20%20%20%20%20%20%20%20%20%20%20f(y)%20%5Cgeq%20f(x)%20%2B%20f'(x)(y%20-%20x)%0A%20%20%20%20%20%20%20%20%5C%5D%0A%0A%20%20%20%20%20%20%20%20for%20all%20%24x%24%2C%20%24y%24%20in%20the%20domain%20of%20%24f%24.%20In%20other%20words%2C%20the%20first-order%20approximation%0A%20%20%20%20%20%20%20%20of%20%24f%24%20near%20%24x%24%20should%20lie%20below%20the%20graph%20of%20%24f%24.%0A%0A%20%20%20%20%20%20%20%20The%20below%20plot%20visualizes%20this.%20If%20the%20dotted%20line%20lies%20below%20the%20graph%20of%0A%20%20%20%20%20%20%20%20%24f%24%20as%20you%20sweep%20the%20slider%2C%20that%20means%20the%20function%20is%20convex!%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20__(function%2C%20plt%2C%20torch%2C%20x%2C%20x_max%2C%20x_min)%3A%0A%20%20%20%20domain%20%3D%20torch.linspace(x_min.value%2C%20x_max.value%2C%20100%2C%20requires_grad%3DTrue)%0A%20%20%20%20outputs%20%3D%20function(domain)%0A%20%20%20%20summed%20%3D%20outputs.sum()%0A%20%20%20%20summed.backward()%0A%0A%0A%20%20%20%20def%20plot(x)%3A%0A%20%20%20%20%20%20%20%20x%20%3D%20torch.tensor(%5Bx%5D%2C%20requires_grad%3DTrue)%0A%20%20%20%20%20%20%20%20f_x%20%3D%20function(x)%0A%20%20%20%20%20%20%20%20f_x.backward()%0A%20%20%20%20%20%20%20%20f_prime_x%20%3D%20x.grad%0A%0A%20%20%20%20%20%20%20%20with%20torch.no_grad()%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.plot(domain%2C%20outputs)%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.plot(x%2C%20f_x%2C%20marker%3D%22o%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.plot(domain%2C%20f_prime_x%20*%20(domain%20-%20x)%20%2B%20f_x%2C%20linestyle%3D%22--%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20x_buffer%20%3D%20(domain.max()%20-%20domain.min())%20%2F%2010%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.xlim(domain%5B0%5D%2C%20domain%5B-1%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20y_buffer%20%3D%20(outputs.max()%20-%20outputs.min())%20%2F%2010%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.ylim(outputs.min()%20-%20y_buffer%2C%20outputs.max()%20%2B%20y_buffer)%0A%20%20%20%20%20%20%20%20return%20plt.gca()%0A%0A%0A%20%20%20%20plot(x.value)%0A%20%20%20%20return%20domain%2C%20outputs%2C%20plot%2C%20summed%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20mo%2C%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20return%20plt%2C%0A%0A%0A%40app.cell%0Adef%20__()%3A%0A%20%20%20%20import%20torch%0A%20%20%20%20return%20torch%2C%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()