diff options
author | mounderfod <mounderfod@gmail.com> | 2023-07-21 12:25:31 +0200 |
---|---|---|
committer | mounderfod <mounderfod@gmail.com> | 2023-07-21 12:25:31 +0200 |
commit | 1c6ecc8038c19781139830cfbf236411ea521c61 (patch) | |
tree | b874c30870377f57a206d0d3ab129a54ff68d169 | |
parent | 44d18b0ddd81736f938ac75a96ae519195c01c20 (diff) | |
download | pyMathEngine-1c6ecc8038c19781139830cfbf236411ea521c61.tar.gz |
Add equation functionality
-rw-r--r-- | .idea/vcs.xml | 6 | ||||
-rw-r--r-- | Discovery.md | 2 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | app.py | 44 | ||||
-rw-r--r-- | templates/index.html | 163 |
5 files changed, 188 insertions, 29 deletions
diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="$PROJECT_DIR$" vcs="Git" /> + </component> +</project> \ No newline at end of file diff --git a/Discovery.md b/Discovery.md index 7d3c460..42be246 100644 --- a/Discovery.md +++ b/Discovery.md @@ -7,6 +7,6 @@ git: <https://github.com/mounderfod/pyMathEngine> A mathematical engine in the style of Wolfram Alpha. Very useful for homework, assignments, etc. -Currently, the engine can only take univariate expressions, but additional features are being added over time. +Currently, the engine can only take univariate expressions and simple equations, but additional features are being added over time. [(view screenshot)](https://cdn.discordapp.com/attachments/838048982873538572/1131593838285295637/image.png) \ No newline at end of file diff --git a/README.md b/README.md index e699297..a1a1cb5 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,6 @@ A mathematical engine in the style of Wolfram Alpha. Very useful for homework, assignments, etc. -Currently, the engine can only take univariate expressions, but additional features are being added over time. +Currently, the engine can only take univariate expressions and simple equations, but additional features are being added over time.  \ No newline at end of file diff --git a/app.py b/app.py index 51b158b..09b4c5c 100644 --- a/app.py +++ b/app.py @@ -1,7 +1,8 @@ import base64 import os -from sympy import diff, integrate, print_latex, latex, pretty, solve, Eq +import flask +from sympy import diff, integrate, print_latex, latex, pretty, solve, Eq, nsolve, limit, oo, solveset from sympy.parsing.sympy_parser import * from sympy.plotting import plot from io import BytesIO @@ -15,6 +16,31 @@ app = Flask(__name__) def hello_world(): # put application's code here return render_template("index.html", HOSTNAME=os.getenv("DETA_SPACE_APP_HOSTNAME")) +@app.route('/api/equation') +def equation(): + args = request.args + + try: + lhs = parse_expr(args['lhs'], transformations=standard_transformations + (split_symbols, implicit_multiplication, function_exponentiation, convert_xor)) + rhs = parse_expr(args['rhs'], transformations=standard_transformations + (split_symbols, implicit_multiplication, function_exponentiation, convert_xor)) + + response = {'solution': []} + + eq = Eq(lhs, rhs) + try: + for i in eq.atoms(Symbol): + response['solution'].append(latex(i) + "=" + latex(solveset(eq, i))) + except NotImplementedError: + response['solution'] = "\\text{Solution could not be calculated.}" + + response = flask.jsonify(response) + response.headers.add('Access-Control-Allow-Origin', '*') + return response + + except Exception as e: + print(e) + return f"Bad Request", 400 + @app.route('/api/univariate') def plotter(): args = request.args @@ -29,15 +55,25 @@ def plotter(): p._backend.process_series() p._backend.fig.savefig(buf, format="png") + try: + solution = [latex(i) for i in solveset(Eq(exp, 0))] + except NotImplementedError: + solution = "\\text{Solution could not be calculated.}" + data = base64.b64encode(buf.getbuffer()).decode("ascii") - return { + response = flask.jsonify({ "variable": pretty(exp.atoms(Symbol).pop()), "expression": latex(exp), "plot": data, "diff": latex(diff(exp)), "integral": latex(integrate(exp)), - "solution": [latex(i) for i in solve(Eq(exp, 0))] - } + "limit_inf": latex(limit(exp, pretty(exp.atoms(Symbol).pop()), oo)), + "limit_zero": latex(limit(exp, pretty(exp.atoms(Symbol).pop()), 0)), + "solution": solution + }) + response.headers.add('Access-Control-Allow-Origin', '*') + return response + except Exception as e: print(e) return f"Bad Request", 400 diff --git a/templates/index.html b/templates/index.html index e87e7e4..4d44706 100644 --- a/templates/index.html +++ b/templates/index.html @@ -30,40 +30,142 @@ <div class="alert alert-info mb-2" role="alert"> Welcome to <b>pyMathEngine</b>, a mathematical engine in the style of Wolfram Alpha. <br /> - Currently the engine can only take univariate expressions (e.g. \( - x^2+2x+3 \)), but additional features are being added over time.<br /> + Currently, the engine can only take univariate expressions and simple + equations, but additional features are being added over time. , but + additional features are being added over time.<br /> Some notes: <ul> <li>Euler's number (\(e\)) is written as "E" in the box</li> <li>Pi (\(\pi\)) is written as "pi" in the box</li> </ul> </div> - <div class="input-group mb-3"> - <input - id="expression" - type="text" - class="form-control" - placeholder="Enter a univariate expression..." - aria-label="Enter a univariate expression..." - aria-describedby="button-addon" - /> - <button - class="btn btn-secondary" - type="button" - onclick="get()" - id="button-addon" - > - Search - </button> + <div class="row mt-3"> + <div class="col-sm"> + <div class="input-group mb-3"> + <input + id="expression" + type="text" + class="form-control" + placeholder="Enter a univariate expression..." + aria-label="Enter a univariate expression..." + aria-describedby="button-addon" + /> + <button + class="btn btn-secondary" + type="button" + onclick="get_uni()" + id="button-addon" + > + Search + </button> + </div> + </div> + <div class="col-sm"> + <div class="input-group mb-3"> + <input + id="lhs" + type="text" + placeholder="LHS of equation" + class="form-control" + /> + <span class="input-group-text">=</span> + <input + id="rhs" + type="text" + placeholder="RHS of equation" + class="form-control" + /> + <button + class="btn btn-secondary" + type="button" + onclick="get_eq()" + id="button-addon" + > + Search + </button> + </div> + </div> </div> </div> - <div id="response" class="m-5"></div> + <div id="response" class="m-3"></div> </body> <script> - function get() { + function get_eq() { + let lhs = document.getElementById("lhs").value; + let rhs = document.getElementById("rhs").value; + let responseBox = document.getElementById("response"); + responseBox.innerHTML = ` + <div class="d-flex justify-content-center"> + <div class="spinner-border" role="status"> + <span class="visually-hidden">Loading...</span> + </div> + </div> + `; + + fetch( + `http://${"{{ HOSTNAME }}"}/api/equation?lhs=${encodeURIComponent( + lhs + )}&rhs=${encodeURIComponent(rhs)}` + ) + .then((response) => { + if (!response.ok) { + let err = new Error("HTTP error: " + response.status); + err.response = response; + err.status = response.status; + throw err; + } else { + response.json().then((data) => { + console.log(data); + let responseBox = document.getElementById("response"); + + if (data.solution.length == 0) { + solution = "\\text{No solutions exist}"; + } else { + solution = data.solution; + } + + responseBox.innerHTML = ""; + responseBox.innerHTML += ` + <div class="card mt-2"> + <div class="card-header">Solutions</div> + <div class="card-body overflow-auto"><p> + $$ ${solution} $$ + </p></div> + </div> + `; + + MathJax.typeset(); + }); + } + }) + .catch((err) => { + let responseBox = document.getElementById("response"); + + responseBox.innerHTML = ""; + responseBox.innerHTML += ` + <div class="card mt-2"> + <div class="card-header bg-danger text-white">Error</div> + <div class="card-body"> + <p>${err.message}</p> + <p>This is likely because you have entered an invalid expression.</p> + </div> + </div> + `; + }); + } + + function get_uni() { let exp = document.getElementById("expression").value; + let responseBox = document.getElementById("response"); + responseBox.innerHTML = ` + <div class="d-flex justify-content-center"> + <div class="spinner-border" role="status"> + <span class="visually-hidden">Loading...</span> + </div> + </div> + `; fetch( - `https://${"{{ HOSTNAME }}"}/api/univariate?func=${encodeURIComponent( + `http://${"{{ HOSTNAME }}"}/api/univariate?func=${encodeURIComponent( exp )}` ) @@ -78,6 +180,11 @@ response.json().then((data) => { console.log(data); let responseBox = document.getElementById("response"); + if (data.solution.length == 0) { + solution = "\\text{No solutions exist}"; + } else { + solution = data.solution; + } responseBox.innerHTML = ""; responseBox.innerHTML += ` <div class="card mt-2"> @@ -90,7 +197,7 @@ <div class="card mt-2"> <div class="card-header">Solutions (where \\(f(${data.variable}) = 0\\))</div> <div class="card-body overflow-auto"><p> - $$ ${data.solution} $$ + $$ ${solution} $$ </p></div> </div> @@ -115,6 +222,16 @@ </div> </div> + <div class="card mt-2"> + <div class="card-header">Limits</div> + <div class="card-body"> + <p>$$ \\lim_{${data.variable} \\rightarrow \\infty} = ${data.limit_inf}$$</p> + <p>$$ \\lim_{${data.variable} \\rightarrow 0} = ${data.limit_zero}$$</p> + </div> + </div> + + + `; MathJax.typeset(); }); |