This article explains the design and implementation of an advanced equation solver written in Python. The solver takes a mathematical equation as input, parses it, solves for the variable, and optionally plots the graph of the equation. The program uses powerful Python libraries such as SymPy for symbolic mathematics and Matplotlib for graphing.
Overview
The solver accepts input equations in a user-friendly format, allowing expressions such as:
x^4 + 3x - 2 = 0
2(x+1)^2 = x
It then processes these equations by:
- Parsing and simplifying the expressions,
- Solving for the variable
x
, - Displaying the solutions in a readable format,
- Optionally plotting the graph of the equation function over a defined range.
The program runs in a loop to allow multiple queries until the user chooses to exit.
Key Components of the Code
1. Libraries Used
- SymPy: A Python library for symbolic mathematics. It allows parsing, simplification, and solving of algebraic expressions symbolically.
- NumPy: Used here primarily for generating evenly spaced numerical values for plotting.
- Matplotlib: Used for plotting the function graph.
2. Parsing and Cleaning Input
Users often input equations using the caret ^
for exponentiation, which Python does not recognize by default. The function clean_input
replaces ^
with Python’s exponent operator **
.
The parsing step uses SymPy’s parse_expr
with transformations that allow implicit multiplication (e.g., 2(x+1)
instead of 2*(x+1)
). This makes the input more natural.
3. Equation Parsing Function
The parse_equation
function checks if the input contains an equals sign (=
), splits the input into left-hand side (LHS) and right-hand side (RHS) expressions, parses and simplifies them, and constructs a SymPy Eq
object representing the equation.
If the input is invalid, or parsing fails, it returns an informative error message.
4. Solving the Equation
The solve_equation
function uses SymPy’s solve
method to find roots of the equation with respect to the symbol x
. If no roots are found or an error occurs, an appropriate message is returned.
5. Plotting the Graph
The plot_graph
function generates a plot of the function f(x) = LHS - RHS
. This function crosses zero at the roots of the equation, visually representing solutions.
- It generates 400 evenly spaced
x
values in the range [-10, 10]. - Calculates the corresponding
y
values by substitutingx
into the function. - Draws the x- and y-axes for reference.
- Plots the curve and displays it using Matplotlib.
If plotting fails, an error message is printed.
6. User Interaction Loop
The main function run
manages the user interface:
- It prints instructions and examples.
- Accepts equation input repeatedly.
- Handles exit condition if the user types ‘q’.
- Parses, solves, and displays the equation and solutions.
- Asks if the user wants to plot the graph and acts accordingly.
Full Code Listing
import re
import numpy as np
import matplotlib.pyplot as plt
from sympy import symbols, Eq, solve, pretty, simplify
from sympy.parsing.sympy_parser import (
parse_expr, standard_transformations, implicit_multiplication_application
)
# Define the symbolic variable
x = symbols('x')
transformations = standard_transformations + (implicit_multiplication_application,)
def clean_input(expr):
# Replace ^ with ** for exponentiation
expr = expr.replace("^", "**")
return expr
def parse_equation(expr):
try:
expr = clean_input(expr)
if '=' not in expr:
return None, "Error: Equation must contain '=' sign."
left, right = expr.split('=')
left_expr = parse_expr(left.strip(), transformations=transformations)
right_expr = parse_expr(right.strip(), transformations=transformations)
equation = Eq(simplify(left_expr), simplify(right_expr))
return equation, None
except Exception as e:
return None, f"Error: Could not parse the equation: {str(e)}"
def solve_equation(equation):
try:
solutions = solve(equation, x)
if not solutions:
return ["No roots found."]
return solutions
except Exception as e:
return [f"Solution error: {str(e)}"]
def plot_graph(equation):
try:
func = equation.lhs - equation.rhs
f = lambda val: func.subs(x, val).evalf()
x_vals = np.linspace(-10, 10, 400)
y_vals = [f(val) for val in x_vals]
plt.figure(figsize=(7, 4))
plt.axhline(0, color='black', linewidth=0.5)
plt.axvline(0, color='black', linewidth=0.5)
plt.plot(x_vals, y_vals, label='Equation Graph', color='blue')
plt.title("Equation Graph")
plt.xlabel("x")
plt.ylabel("f(x)")
plt.grid(True)
plt.legend()
plt.show()
except Exception as e:
print("Warning: Failed to plot the graph:", str(e))
def run():
print("Advanced Equation Solver v1.0")
print("Example input: x^4 + 3x - 2 = 0 or 2(x+1)^2 = x")
print("Type 'q' to quit.\n")
while True:
user_input = input("Enter the equation: ")
if user_input.lower() == 'q':
print("Exiting the program.")
break
equation, error = parse_equation(user_input)
if error:
print(error)
continue
print("\nEquation:")
print(pretty(equation))
print("\nSolution:")
solutions = solve_equation(equation)
for i, sol in enumerate(solutions, 1):
print(f"Root {i}: {sol}")
plot_request = input("\nWould you like to plot the graph? (y/n): ")
if plot_request.lower() == 'y':
plot_graph(equation)
print("\n" + "-"*50)
if __name__ == "__main__":
run()
Conclusion
This Python program effectively demonstrates the use of symbolic mathematics to solve algebraic equations interactively. It leverages SymPy’s parsing and solving capabilities combined with Matplotlib’s visualization to provide a comprehensive tool suitable for educational and practical purposes.
If you want to extend this solver, you can add support for systems of equations, inequalities, or improve the plotting range dynamically based on solutions.