Advanced Equation Solver in Python: Explanation and Implementation


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 substituting x 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.