-2

In order to find the maximums and minimums of a function, I am writing a program that accepts a polynomial imputed from the user and finds where the derivative = 0.

from sympy import Symbol, Derivative
from sympy import symbols, Eq, solve
import sympy as sy
import numpy as np 
import math 



x= Symbol('x', real = True)
function= x**4 +7*x**2 +8

deriv= Derivative(function, x)
yprime = deriv.doit()
y = symbols('x')
eq1 = Eq(yprime,0)
sol = solve(eq1, )

The only reason that the code above is able to take the derivative and find solutions is because the coefficients and exponents are integers. If I ask for user input {e.g., function = input("What is your function: ")}, then the whole thing will become a string and SymPy can not take the derivative.

Is it possible to turn the coefficients and exponents into integers and leave the rest of the function as a string so that I can take the derivative?

  • Integer exponents are part of the definition of [polynomial](https://en.wikipedia.org/wiki/Polynomial). You can find derivatives with non-integer coefficients. – Joffan May 19 '21 at 18:14
  • You need to do some input parsing. `input()` always gives you strings, so you will need to check the values you get and make sure they are able to be treated as numbers (ie. `str.isnumeric()`) and then cast them (`val = int(string_input)`). – Z4-tier May 19 '21 at 18:17
  • You can encode a *n*-degree polynomial as simply the *(n+1)* vector of coefficients - perhaps you should ask the user for those values (interactively if you prefer) and build the string yourself. – Joffan May 19 '21 at 18:20
  • @Blckknght He mentioned it in the text: **If I ask for user input {e.g., function = input("What is your function: ")}** `function` would then be a string. – Barmar May 19 '21 at 19:02
  • @Barmar: Ah, you're right, I had somehow overlooked that part of the text on my first read. – Blckknght May 19 '21 at 19:40

2 Answers2

0

If your equation can be arbitrarily complicated, you might want to use eval to parse it from Python syntax. Now, eval is generally unsafe to use on untrusted user input, but a user replying to an input() prompt is probably trusted (since they're usually sitting at the computer running the code).

So one option is:

function = eval(input("What is your function: "))

If placed just below the definition of x, it will allow that variable to be used in the equation. You could also provide a namespace for eval to use, rather than letting it use your function's local namespace (e.g. function = eval(input(...), {'x': Symbol('x', real=True)})).

If your problem space is more limited, and you only need to handle equations that are polynomials with integer coefficients, then you could write your own logic to input the equation in a much more simplified form. For instance, you could loop, asking for the coefficients in order (probably from the lowest exponent to the highest). Try something like this:

import itertools

from sympy import Symbol

x = Symbol('x', real = True)

function = 0
for exponent in itertools.count():
    coef = input(f"Enter coefficient for x**{exponent} (or give an empty value to be done): ")
    if not coef:
        break
    function += int(coef) * x**exponent
    print("Polynomial so far:", function)

For the example equation in your question, you'd enter 8, 0, 7, 0, 1 and finally an empty input.

Blckknght
  • 100,903
  • 11
  • 120
  • 169
0

The better thing to do is to turn your string into a SymPy expression. As long as the user uses SymPy/python syntax, sympyify will convert it for you:

>>> from sympy import sympify, solve
>>> user='3*x**2-1'
>>> eq = sympify(user)
>>> x = eq.free_symbols.pop()  # assuming there is 1 symbol
>>> solve(eq.diff(x))
[0]
smichr
  • 16,948
  • 2
  • 27
  • 34