Problems with sympy at streamlit

Hi mates, iā€™m trying to type a equation at streamlit using this piece of code:

import streamlit as st
import pandas as pd
import numpy as np
from pandas import DataFrame
import math
from sympy import *
      
eq = st.text_input('Type your equation here: ')
        func = simplify(eq)
        st.write(func)

but while i run the app, he returns the error:

anyone knows what could be causing this? When i run at jupyter notebook didnā€™t show any problemā€¦

Hi @feliperoque :grinning_face_with_smiling_eyes:

As per Streamlitā€™s execution model, your app runs from top-to-bottom with each interaction. On the first run, however, eq is empty and causes simplify(eq) to throw an error. Instead, you can check if eq contains a value (i.e. evaluates to True) using an if statement and only then execute simplify(eq) like so:

import streamlit as st
import pandas as pd
import numpy as np
import math
from sympy import simplify

eq = st.text_input('Type your equation here: ')
if eq:
    func = simplify(eq)
    st.write(func)

Once you save and run the script, it should work as expected:

On user input:

Happy Streamlit-ing! :balloon:
Snehan

2 Likes

Thanks a lot mate!

1 Like

@snehankekre Brother, iā€™m having another issue while inserting values at streamlit using sympy. The problems is while streamlit run top-to-bottom with each interaction, when i insert the equation and after go to enter with another variables at inputer number, streamlit run automatically all the code returning a problem.

The first one is here:

if option == 'Bissection Method':

    st.markdown('## Equation to Compute: ')

    x, y, z = symbols("x y z")

    # Entrada das equaƧƵes
    eq_inserted = st.text_input('Enter your equation here:')

    if eq_inserted:
        func = simplify(eq_inserted)
        st.write(func)
    
    st.markdown("## Variables to Enter from the Bissection Method: ")

    # DefiniĆ§Ć£o dos intervalos [a,b]
    a = st.number_input('First Interval (a): ')
    b = st.number_input('Second Interval (b): ')

    # DefiniĆ§Ć£o da tolerancia a ser utilizada
    e = st.number_input('Tolerance (e): ')

    # Adicionando os valores dos intervalos [a,b] na funĆ§Ć£o digitada pelo usuĆ”rio
    f_a = func.subs(x, a)  # Problem start here!!!!!!!
    f_b = func.subs(x, b)

    #st.write("a \t\tb \t\tx_media \tf(x_media) \tf(a) \t\tf(b)")

    # Teorema de Bolzano
    if (f_a*f_b) < 0:
        while (math.fabs(b-a)/2 > e):
            x_media = (a+b)/2
            f_x_media = func.subs(x, x_media)
            st.write("{:.6f} \t{:.6f} \t{:.6f} \t{:.6f} \t{:.6f} \t{:.6f}".format(a, b, x_media, f_x_media, a, b))

            if f_x_media == 0:
                st.write("Root is: {}".format(x_media))
            else:
                if f_a*f_x_media < 0:
                    b = x_media
                else:
                    a = x_media
            st.write("\n")
            st.write("Root value is: {}".format(x_media))
            st.write("\n")
    else:
        st.write("There are no root in this interval")

when i reload app first time he returns the following error. But after i inserted a equation, the error disappearā€¦

i tested the code at jupyter notebook before change him with streamlit syntax and worked as well as expectedā€¦

Hi @feliperoque, perhaps you could move the everything under the if statement to within the if block? On the first run (without user input), func is undefined because eq_inserted is empty. So when you try calling func with f_a = func.subs(x, a) on the first run, you are going to get the error.

if eq_inserted:
    func = simplify(eq_inserted)
    st.write(func)

    st.markdown("## Variables to Enter from the Bissection Method: ")

    # DefiniĆ§Ć£o dos intervalos [a,b]
    a = st.number_input('First Interval (a): ')
    b = st.number_input('Second Interval (b): ')

    # DefiniĆ§Ć£o da tolerancia a ser utilizada
    e = st.number_input('Tolerance (e): ')

    # Adicionando os valores dos intervalos [a,b] na funĆ§Ć£o digitada pelo usuĆ”rio
    f_a = func.subs(x, a)  # Problem start here!!!!!!!
    f_b = func.subs(x, b)

    #st.write("a \t\tb \t\tx_media \tf(x_media) \tf(a) \t\tf(b)")

    # Teorema de Bolzano
    if (f_a*f_b) < 0:
        while (math.fabs(b-a)/2 > e):
            x_media = (a+b)/2
            f_x_media = func.subs(x, x_media)
            st.write("{:.6f} \t{:.6f} \t{:.6f} \t{:.6f} \t{:.6f} \t{:.6f}".format(a, b, x_media, f_x_media, a, b))

            if f_x_media == 0:
                st.write("Root is: {}".format(x_media))
            else:
                if f_a*f_x_media < 0:
                    b = x_media
                else:
                    a = x_media
            st.write("\n")
            st.write("Root value is: {}".format(x_media))
            st.write("\n")
    else:
        st.write("There are no root in this interval")

Iā€™m unsure if :point_up: will cause additional errors - it really depends on your app logic and isnā€™t strictly a Streamlit question.

Happy Streamlit-ing! :balloon:
Snehan

1 Like

ok, thanks btw. It worked, but when i enter the equation, the next step is to enter the value of the interval [a, b], however streamlit is returning a condition where it should not print unless the condition f_a * f_b < 0 turns true. I noticed after i insert the equation, and type enter he runs the code and show below the following sentece There are no root in this interval even before i type the rest of the input i need.

I was wondering if its something relationed with SessionState, cause after i type the equation and hits enter he auto insert 0 numbers at the all input fields and the code reports there are no root in this interval

It is unrelated to SessionState IMO but related to the control flow of your app logic. You have to check whether your intervals and tolerance have been entered using something like another if statement:

import streamlit as st
import pandas as pd
import numpy as np
import math
from sympy import simplify, symbols

st.markdown('## Equation to Compute: ')

x, y, z = symbols("x y z")

# Entrada das equaƧƵes
eq_inserted = st.text_input('Enter your equation here:')

if eq_inserted:
    func = simplify(eq_inserted)
    st.write(func)

    st.markdown("## Variables to Enter from the Bissection Method: ")

    # DefiniĆ§Ć£o dos intervalos [a,b]
    a = st.number_input('First Interval (a): ')
    b = st.number_input('Second Interval (b): ')

    # DefiniĆ§Ć£o da tolerancia a ser utilizada
    e = st.number_input('Tolerance (e): ')

    # Adicionando os valores dos intervalos [a,b] na funĆ§Ć£o digitada pelo usuĆ”rio
    f_a = func.subs(x, a)  # Problem start here!!!!!!!
    f_b = func.subs(x, b)

    #st.write("a \t\tb \t\tx_media \tf(x_media) \tf(a) \t\tf(b)")
    # check if intervals and tolerance are not the default 0.00
    if a and b and e:
        # Teorema de Bolzano
        if (f_a*f_b) < 0:
            while (math.fabs(b-a)/2 > e):
                x_media = (a+b)/2
                f_x_media = func.subs(x, x_media)
                st.write("{:.6f} \t{:.6f} \t{:.6f} \t{:.6f} \t{:.6f} \t{:.6f}".format(a, b, x_media, f_x_media, a, b))

                if f_x_media == 0:
                    st.write("Root is: {}".format(x_media))
                else:
                    if f_a*f_x_media < 0:
                        b = x_media
                    else:
                        a = x_media
                st.write("\n")
                st.write("Root value is: {}".format(x_media))
                st.write("\n")
        else:
            st.write("There are no root in this interval")

1 Like

Hey @feliperoque!! I have exciting news to share with you :tada: :partying_face: :tada:

Using the brand new st.form and st.form_submit_button commands, you can be sure that the calculations will be performed only once all the parameters are submitted by your users!

Iā€™ve modified your code using the two new commands below:

import streamlit as st
import numpy as np
import math
from sympy import simplify, symbols

st.markdown('## Equation to Compute: ')

x, y, z = symbols("x y z")
# Entrada das equaƧƵes
eq_inserted = st.text_input('Enter your equation here:')
if eq_inserted:
    func = simplify(eq_inserted)
    st.write(func)

with st.form(key="my_form"):
    st.markdown("## Variables to Enter from the Bissection Method: ")
    # DefiniĆ§Ć£o dos intervalos [a,b]
    a = st.number_input('First Interval (a): ')
    b = st.number_input('Second Interval (b): ')
    # DefiniĆ§Ć£o da tolerancia a ser utilizada
    e = st.number_input('Tolerance (e): ')

    submit_button = st.form_submit_button(label="Submit")

    if submit_button:
        f_a = func.subs(x, a)  # Problem start here!!!!!!!
        f_b = func.subs(x, b)


        if (f_a*f_b) < 0:
            while (math.fabs(b-a)/2 > e):
                x_media = (a+b)/2
                f_x_media = func.subs(x, x_media)
                st.write("{:.6f} \t{:.6f} \t{:.6f} \t{:.6f} \t{:.6f} \t{:.6f}".format(a, b, x_media, f_x_media, a, b))

                if f_x_media == 0:
                    st.write("Root is: {}".format(x_media))
                else:
                    if f_a*f_x_media < 0:
                        b = x_media
                    else:
                        a = x_media
                st.write("\n")
                st.write("Root value is: {}".format(x_media))
                st.write("\n")
        else:
            st.write("There are no root in this interval")
    

Hope you are as excited by the submit button and form as I am :fire: :rocket: Let me know if this solves your problem! :grinning_face_with_smiling_eyes:

Upgrade to the latest version to use these awesome commands:

pip install --upgrade streamlit

Happy Streamlit-ing! :balloon:
Snehan

1 Like

Awesome, thatā€™s what i was looking for solve this problem. I didnā€™t notice streamlit release a new update with some new features. Thx a lot mate!

1 Like