HouseofElectricalEngineers/QuadraticEquationSolver
0
1import io2import numpy as np3import matplotlib.pyplot as plt4import gradio as gr5from PIL import Image6 7# ----- Solver logic -----8def solve_quadratic(a, b, c):9 if a == 0:10 if b == 0:11 return None, None, "degenerate", "No solution" if c != 0 else "Infinite solutions"12 root = -c / b13 return [root], None, "linear", f"Single root x = {root:.6f}"14 discriminant = b**2 - 4 * a * c15 sqrt_disc = np.sqrt(abs(discriminant))16 if discriminant > 0:17 r1 = (-b + sqrt_disc) / (2 * a)18 r2 = (-b - sqrt_disc) / (2 * a)19 nature = "real and distinct"20 roots = [r1, r2]21 elif discriminant == 0:22 r = -b / (2 * a)23 nature = "real and equal"24 roots = [r, r]25 else:26 real_part = -b / (2 * a)27 imag_part = sqrt_disc / (2 * a)28 r1 = complex(real_part, imag_part)29 r2 = complex(real_part, -imag_part)30 nature = "complex conjugates"31 roots = [r1, r2]32 return roots, discriminant, nature, None33 34def format_solution_text(a, b, c, show_steps):35 roots, discriminant, nature, message = solve_quadratic(a, b, c)36 lines = []37 if a == 0:38 if nature == "degenerate":39 lines.append(f"⚠️ {message}")40 elif nature == "linear":41 root = -c / b if b != 0 else None42 lines.append("**Linear equation (a=0):**")43 lines.append(f"{b:.6f}x + {c:.6f} = 0")44 if root is not None:45 lines.append(f"Solution: x = {root:.6f}")46 return "\n".join(lines)47 48 lines.append(f"**Discriminant:** Δ = b² - 4ac = {discriminant:.6f}")49 lines.append(f"**Nature of roots:** {nature.capitalize()}")50 if isinstance(roots, list):51 def fmt(x):52 if isinstance(x, complex):53 return f"{x.real:.6f} {'+' if x.imag >= 0 else '-'} {abs(x.imag):.6f}i"54 else:55 return f"{x:.6f}"56 if len(roots) == 2:57 lines.append(f"**Root 1:** {fmt(roots[0])}")58 lines.append(f"**Root 2:** {fmt(roots[1])}")59 elif len(roots) == 1:60 lines.append(f"**Root:** {fmt(roots[0])}")61 62 if show_steps:63 lines.append("\n**Solution steps:**")64 lines.append(f"1. Compute discriminant: Δ = ({b:.6f})² - 4×({a:.6f})×({c:.6f}) = {discriminant:.6f}")65 lines.append("2. Apply quadratic formula:")66 if discriminant >= 0:67 lines.append(f" x = [ -{b:.6f} ± sqrt({discriminant:.6f}) ] / (2×{a:.6f})")68 else:69 lines.append(f" x = [ -{b:.6f} ± i·sqrt({abs(discriminant):.6f}) ] / (2×{a:.6f})")70 if isinstance(roots, list) and len(roots) == 2:71 if discriminant >= 0:72 lines.append(f"3. Final: x₁ = {roots[0]:.6f}, x₂ = {roots[1]:.6f}")73 else:74 real_part = -b / (2 * a)75 imag_part = np.sqrt(abs(discriminant)) / (2 * a)76 lines.append(f"3. Final: x₁ = {real_part:.6f} + {imag_part:.6f}i, x₂ = {real_part:.6f} - {imag_part:.6f}i")77 return "\n".join(lines)78 79def make_plot(a, b, c, discriminant, roots):80 x = np.linspace(-10, 10, 800)81 y = a * x**2 + b * x + c82 fig, ax = plt.subplots()83 ax.plot(x, y)84 ax.axhline(0, linewidth=0.8)85 ax.set_xlabel("x")86 ax.set_ylabel("f(x)")87 ax.set_title(f"{a}x² + {b}x + {c}")88 if discriminant is not None and discriminant >= 0 and isinstance(roots, list) and len(roots) == 2:89 r1, r2 = roots90 ax.scatter([r1, r2], [0, 0], marker="o")91 ax.annotate(f"x₁={r1:.2f}", (r1, 0), textcoords="offset points", xytext=(0,10), ha="center")92 ax.annotate(f"x₂={r2:.2f}", (r2, 0), textcoords="offset points", xytext=(0,-15), ha="center")93 if a != 0:94 xv = -b / (2 * a)95 yv = a * xv**2 + b * xv + c96 ax.scatter([xv], [yv], marker="x")97 ax.annotate(f"vertex ({xv:.2f}, {yv:.2f})", (xv, yv), textcoords="offset points", xytext=(10,10))98 ax.grid(True)99 fig.tight_layout()100 return fig101 102# ----- Gradio app -----103def gradio_interface(a, b, c, show_steps):104 try:105 roots, discriminant, nature, message = solve_quadratic(a, b, c)106 text = format_solution_text(a, b, c, show_steps)107 disc_for_plot = discriminant if discriminant is not None else 0108 roots_for_plot = roots if roots is not None else []109 fig = make_plot(a, b, c, disc_for_plot, roots_for_plot)110 buf = io.BytesIO()111 fig.savefig(buf, format="png", bbox_inches="tight")112 buf.seek(0)113 img = Image.open(buf).convert("RGB") # convert to PIL image for gradio114 return text, img115 except Exception as e:116 return f"Error computing solution: {e}", None117 118with gr.Blocks(title="Quadratic Equation Solver") as demo:119 gr.Markdown("# Quadratic Equation Solver")120 gr.Markdown(121 "Solve \(ax^2 + bx + c = 0\); shows discriminant, nature of roots, solution steps, and plot."122 )123 with gr.Row():124 with gr.Column():125 a_in = gr.Number(label="Coefficient a", value=1.0)126 b_in = gr.Number(label="Coefficient b", value=0.0)127 c_in = gr.Number(label="Coefficient c", value=0.0)128 show_steps = gr.Checkbox(label="Show solution steps", value=True)129 solve_btn = gr.Button("Solve")130 with gr.Column():131 output_md = gr.Markdown()132 plot_img = gr.Image(type="pil", label="Plot")133 134 solve_btn.click(135 fn=gradio_interface,136 inputs=[a_in, b_in, c_in, show_steps],137 outputs=[output_md, plot_img],138 )139 140if __name__ == "__main__":141 demo.launch(share=False)142 