0

How to take user input and substitute it into the solve method? I am trying to make a discord bot that helps you do math. Please assume that each code part has

from sympy import *

My code so far:

equation = input("Put your equation here:\n")
x, y, z, t = symbols('x y z t')
k, m, n = symbols('k m n', integer=True)
f, g, h = symbols('f g h', cls=Function)
equation = equation.split(",")
eqn = Eq(equation[0], equation[1])
await ctx.send(f"```{solve(eqn)}```")

The problem I'm getting:

 SympifyError: SympifyError: 'x+1'

I know what I'm doing wrong, Sympy likes stuff like this:

eqn = Eq(x+1, 8)
solve(eqn)

This outputs 7. But how do I do it from user input?

EDIT: After doing a bit of research, I found that I needed to await returns.

So I awaited Eq(equation[0], equation[1]).

But then I get this error:

Ignoring exception in command solve: Traceback (most recent call last): File "C:\Users\justi_zts5a0w\PycharmProjects\discord.py\venv\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped

ret = await coro(*args, **kwargs)

File "math.py", line 42, in solve eqn = await Eq(parse_expr(equation[0]), parse_expr(equation[1]))

TypeError: object Equality can't be used in 'await' expression

The above exception was the direct cause of the following exception:

Traceback (most recent call last):

File "C:\Users\justi_zts5a0w\PycharmProjects\discord.py\venv\lib\site-packages\discord\ext\commands\bot.py", line 903, in invoke await ctx.command.invoke(ctx)

File "C:\Users\justi_zts5a0w\PycharmProjects\discord.py\venv\lib\site-packages\discord\ext\commands\core.py", line 859, in invoke await injected(*ctx.args, **ctx.kwargs)

File "C:\Users\justi_zts5a0w\PycharmProjects\discord.py\venv\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped raise CommandInvokeError(exc) from exc discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: object Equality can't be used in 'await' expression

I figured out that the problem is with the solve() command. the Eq() command seems to work just fine.

What I tried to do:

@client.command()
async def solve(ctx, equation):
    x, y, z, t = symbols('x y z t')
    k, m, n = symbols('k m n', integer=True)
    f, g, h = symbols('f g h', cls=Function)
    equation = equation.split("=")
    place_hold = 1
    await ctx.send(f"```{await       
    solve(Eq(parse_expr(equation[0]),parse_expr(equation[1])))}```") 

But then this gives me the error:

    ret = await coro(*args, **kwargs)
    File "math.py", line 43, in solve
    await ctx.send(f"```{await solve(Eq(parse_expr(equation[0]), 
    parse_expr(equation[1])))}```")
    File "C:\Users\justi_zts5a0w\PycharmProjects\discord.py\venv\lib\site- 
    packages\discord\ext\commands\core.py", line 374, in __call__
    return await self.callback(*args, **kwargs)
    TypeError: solve() missing 1 required positional argument: 'equation'

I know what the error means, and I suspected it had to do with something in Classes and OOP, the self variable is not filled in and it needs to be filled in. So then I tried putting a place holder before the actual equation, but then that gives me this:

Traceback (most recent call last):
File "C:\Users\justi_zts5a0w\PycharmProjects\discord.py\venv\lib\site- 
packages\discord\ext\commands\bot.py", line 903, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\justi_zts5a0w\PycharmProjects\discord.py\venv\lib\site- 
packages\discord\ext\commands\core.py", line 859, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\justi_zts5a0w\PycharmProjects\discord.py\venv\lib\site- 
packages\discord\ext\commands\core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: 
AttributeError: 'Equality' object has no attribute 'split'

From this, I don't know what to do. It says there is something wrong with the split, but I don't know why something is wrong with it.

Edit: On further inspection, when I printed the type of the variable equation, it showed:

<class 'str'>
<class 'sympy.core.relational.Equality'>

The first one shows that it is a string. But then it appears to change to sympy.core.relational.Equality. So now my problem is: How to split a 'sympy.core.relational.Equality' object?

Kromydas
  • 111
  • 3
  • 11
  • Have you tried the `parse_expr` function? https://docs.sympy.org/latest/modules/parsing.html#sympy.parsing.sympy_parser.parse_expr – Oscar Benjamin Dec 18 '20 at 02:13
  • So do I do parse_expr(equaton[0]) to get the equation[0] into format? – Kromydas Dec 18 '20 at 02:14
  • But now im getting: 'Command.__call__' was never awaited ret = await coro(*args, **kwargs) RuntimeWarning: Enable tracemalloc to get the object allocation traceback This might relates to discord stuff so if you don't know how to do this it is fine, but I wish someone would please tell me. – Kromydas Dec 18 '20 at 02:23
  • I found this: https://stackoverflow.com/questions/54088263/runtimewarning-enable-tracemalloc-to-get-the-object-allocation-traceback-with-a But I don't know how to await coroutine 'Command.__call__' – Kromydas Dec 18 '20 at 02:49

1 Answers1

0

Using sympify in an isympy session:

In [7]: equation = input('>')
>1+x = 0

In [8]: equation = equation.split('=')

In [9]: alist = [sympify(expr) for expr in equation]

In [10]: if len(alist)==2:
    ...:     expr = Eq(alist[0],alist[1])
    ...: 

In [11]: expr
Out[11]: x + 1 = 0

In [12]: solve(expr)
Out[12]: [-1]

Looks like sympify can work with a list of strings:

In [18]: equation
Out[18]: ['1+x ', ' 0']

In [19]: sympify(equation)
Out[19]: [x + 1, 0]

In [20]: Eq(*sympify(equation))
Out[20]: x + 1 = 0

Or with parse_expr:

In [25]: [parse_expr(s) for s in equation]
Out[25]: [x + 1, 0]

This use of split('=') gets around the likely use of '=' to mean equals. '2x' will to translated to '2*x'. Your users may use other expressions that will need to be translated into sympy compatible forms. Don't skip the gotchas in the sympy intros.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • But I tried using parse_expr but it gave me error: 'Command.__call__' was never awaited ret = await coro(*args, **kwargs) RuntimeWarning: Enable tracemalloc to get the object allocation traceback I also said this under comments for my question. – Kromydas Dec 18 '20 at 04:58
  • How are you running this script? The error suggest something other than a simply python call. I ran my code in an `isympy` session which is `ipython` with `sympy` import and setup. – hpaulj Dec 18 '20 at 05:06
  • I also did the first method and the second doesn't work for me, as in like doesn't do anything, I still get the error SympifyError: "x+1" – Kromydas Dec 18 '20 at 05:06
  • Oh yeah, I made a discord bot out of sympi and it gave me an error. Sorry for not replying quickly. – Kromydas Dec 18 '20 at 05:16
  • I can't help you with `discord`. – hpaulj Dec 18 '20 at 05:22
  • Thats ok. Sorry, I was getting a good nights sleep. lul – Kromydas Dec 18 '20 at 15:50
  • If you look at the documentation you will see that `parse_expr` has more options to control how the string is parsed than `sympify` does which you might find useful. – Oscar Benjamin Dec 18 '20 at 16:17
  • My problem is with discord, not sympy right now(I believe). I think I got sympy all down, but then discord is giving me errors. – Kromydas Dec 18 '20 at 16:20