Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| import plotly.graph_objects as go | |
| import plotly.express as px | |
| from plotly.subplots import make_subplots | |
| import pandas as pd | |
| from sys_of_eqn_solver import SystemSolver | |
| import random | |
| # Page configuration | |
| st.set_page_config( | |
| page_title="Systems of Equations - Algebra II", | |
| page_icon="π", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| # Initialize session state | |
| if 'solver' not in st.session_state: | |
| st.session_state.solver = SystemSolver() | |
| if 'show_steps' not in st.session_state: | |
| st.session_state.show_steps = True | |
| # Header | |
| st.title("π Systems of Linear Equations - Algebra II Tutorial") | |
| st.markdown("*Learn to solve systems of equations using multiple methods with real-time visualization*") | |
| # Sidebar configuration | |
| with st.sidebar: | |
| st.header("βοΈ Configuration") | |
| # System size selection | |
| system_size = st.selectbox( | |
| "Select System Size:", | |
| ["2x2 System", "3x3 System"], | |
| help="Choose between 2 equations with 2 variables or 3 equations with 3 variables" | |
| ) | |
| # Method selection | |
| if system_size == "2x2 System": | |
| available_methods = ["All Methods", "Graphical", "Substitution", "Elimination", "Matrix"] | |
| else: | |
| available_methods = ["All Methods", "Matrix", "Elimination"] | |
| selected_method = st.selectbox("Solution Method:", available_methods) | |
| # Display options | |
| st.subheader("Display Options") | |
| show_steps = st.checkbox("Show detailed steps", value=st.session_state.show_steps) | |
| show_verification = st.checkbox("Show solution verification", value=True) | |
| if system_size == "2x2 System": | |
| show_graph = st.checkbox("Show graphical solution", value=True) | |
| graph_range = st.slider("Graph range", min_value=5, max_value=20, value=10) | |
| # Quick examples | |
| st.subheader("π Quick Examples") | |
| if st.button("π― Unique Solution"): | |
| if system_size == "2x2 System": | |
| st.session_state.example_coeffs = [[2, 1], [1, -1]] | |
| st.session_state.example_constants = [7, 1] | |
| else: | |
| st.session_state.example_coeffs = [[1, 2, -1], [2, 1, 1], [1, -1, 2]] | |
| st.session_state.example_constants = [3, 7, 4] | |
| if st.button("π Infinite Solutions"): | |
| if system_size == "2x2 System": | |
| st.session_state.example_coeffs = [[2, 4], [1, 2]] | |
| st.session_state.example_constants = [6, 3] | |
| else: | |
| st.session_state.example_coeffs = [[1, 2, 3], [2, 4, 6], [1, 2, 3]] | |
| st.session_state.example_constants = [6, 12, 6] | |
| if st.button("β No Solution"): | |
| if system_size == "2x2 System": | |
| st.session_state.example_coeffs = [[2, 4], [1, 2]] | |
| st.session_state.example_constants = [6, 4] | |
| else: | |
| st.session_state.example_coeffs = [[1, 2, 3], [2, 4, 6], [1, 2, 3]] | |
| st.session_state.example_constants = [6, 12, 7] | |
| if st.button("π² Random System"): | |
| if system_size == "2x2 System": | |
| st.session_state.example_coeffs = [[random.randint(1, 5), random.randint(1, 5)], | |
| [random.randint(1, 5), random.randint(1, 5)]] | |
| st.session_state.example_constants = [random.randint(1, 15), random.randint(1, 15)] | |
| else: | |
| st.session_state.example_coeffs = [[random.randint(1, 4), random.randint(1, 4), random.randint(1, 4)], | |
| [random.randint(1, 4), random.randint(1, 4), random.randint(1, 4)], | |
| [random.randint(1, 4), random.randint(1, 4), random.randint(1, 4)]] | |
| st.session_state.example_constants = [random.randint(1, 12), random.randint(1, 12), random.randint(1, 12)] | |
| # Main content area | |
| if system_size == "2x2 System": | |
| st.header("2Γ2 System of Linear Equations") | |
| # Input section | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.subheader("π Enter Your System") | |
| # Use example values if they exist | |
| if 'example_coeffs' in st.session_state and len(st.session_state.example_coeffs) == 2: | |
| default_coeffs = st.session_state.example_coeffs | |
| default_constants = st.session_state.example_constants | |
| else: | |
| default_coeffs = [[2, 1], [1, -1]] | |
| default_constants = [7, 1] | |
| # Equation 1 | |
| st.markdown("**Equation 1:** `aβx + bβy = cβ`") | |
| eq1_col1, eq1_col2, eq1_col3 = st.columns(3) | |
| with eq1_col1: | |
| a1 = st.number_input("aβ", value=float(default_coeffs[0][0]), step=0.1, key="a1") | |
| with eq1_col2: | |
| b1 = st.number_input("bβ", value=float(default_coeffs[0][1]), step=0.1, key="b1") | |
| with eq1_col3: | |
| c1 = st.number_input("cβ", value=float(default_constants[0]), step=0.1, key="c1") | |
| # Equation 2 | |
| st.markdown("**Equation 2:** `aβx + bβy = cβ`") | |
| eq2_col1, eq2_col2, eq2_col3 = st.columns(3) | |
| with eq2_col1: | |
| a2 = st.number_input("aβ", value=float(default_coeffs[1][0]), step=0.1, key="a2") | |
| with eq2_col2: | |
| b2 = st.number_input("bβ", value=float(default_coeffs[1][1]), step=0.1, key="b2") | |
| with eq2_col3: | |
| c2 = st.number_input("cβ", value=float(default_constants[1]), step=0.1, key="c2") | |
| # Display the system | |
| st.markdown("### Your System:") | |
| if a1 >= 0 and b1 >= 0: | |
| eq1_str = f"{a1}x + {b1}y = {c1}" | |
| elif a1 >= 0 and b1 < 0: | |
| eq1_str = f"{a1}x - {abs(b1)}y = {c1}" | |
| elif a1 < 0 and b1 >= 0: | |
| eq1_str = f"-{abs(a1)}x + {b1}y = {c1}" | |
| else: | |
| eq1_str = f"-{abs(a1)}x - {abs(b1)}y = {c1}" | |
| if a2 >= 0 and b2 >= 0: | |
| eq2_str = f"{a2}x + {b2}y = {c2}" | |
| elif a2 >= 0 and b2 < 0: | |
| eq2_str = f"{a2}x - {abs(b2)}y = {c2}" | |
| elif a2 < 0 and b2 >= 0: | |
| eq2_str = f"-{abs(a2)}x + {b2}y = {c2}" | |
| else: | |
| eq2_str = f"-{abs(a2)}x - {abs(b2)}y = {c2}" | |
| st.latex(eq1_str) | |
| st.latex(eq2_str) | |
| with col2: | |
| # Solve the system | |
| coefficients = [[a1, b1], [a2, b2]] | |
| constants = [c1, c2] | |
| method_map = { | |
| "All Methods": "all", | |
| "Graphical": "graphical", | |
| "Substitution": "substitution", | |
| "Elimination": "elimination", | |
| "Matrix": "matrix" | |
| } | |
| result = st.session_state.solver.solve_2x2_system( | |
| coefficients, constants, method_map[selected_method] | |
| ) | |
| # System type indicator | |
| system_type = result['system_type'] | |
| if system_type == "unique_solution": | |
| st.success("β **Unique Solution** (Consistent Independent)") | |
| elif system_type == "infinite_solutions": | |
| st.info("π **Infinite Solutions** (Consistent Dependent)") | |
| else: | |
| st.error("β **No Solution** (Inconsistent)") | |
| # Display solutions based on selected method | |
| if selected_method != "All Methods": | |
| method_key = f"{method_map[selected_method]}_solution" | |
| if method_key in result: | |
| solution_data = result[method_key] | |
| st.subheader(f"π {selected_method} Method") | |
| if show_steps and 'steps' in solution_data: | |
| with st.expander("Show Detailed Steps", expanded=True): | |
| for i, step in enumerate(solution_data['steps']): | |
| st.write(f"{i+1}. {step}") | |
| if 'solution' in solution_data and solution_data['solution'] is not None: | |
| if isinstance(solution_data['solution'], dict): | |
| st.markdown("### π― Solution:") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.metric("x =", f"{solution_data['solution']['x']:.4f}") | |
| with col2: | |
| st.metric("y =", f"{solution_data['solution']['y']:.4f}") | |
| # Graphical visualization | |
| if show_graph and ('graphical_solution' in result or selected_method == "All Methods"): | |
| st.header("π Graphical Solution") | |
| fig = go.Figure() | |
| # Generate x values for plotting | |
| x_vals = np.linspace(-graph_range, graph_range, 400) | |
| # Plot first line | |
| if b1 != 0: | |
| y1_vals = (c1 - a1 * x_vals) / b1 | |
| fig.add_trace(go.Scatter( | |
| x=x_vals, y=y1_vals, | |
| mode='lines', | |
| name=eq1_str, | |
| line=dict(color='blue', width=3) | |
| )) | |
| else: | |
| # Vertical line | |
| x_vert = c1 / a1 if a1 != 0 else 0 | |
| fig.add_vline(x=x_vert, line_dash="solid", line_color="blue", | |
| annotation_text=f"x = {x_vert:.2f}") | |
| # Plot second line | |
| if b2 != 0: | |
| y2_vals = (c2 - a2 * x_vals) / b2 | |
| fig.add_trace(go.Scatter( | |
| x=x_vals, y=y2_vals, | |
| mode='lines', | |
| name=eq2_str, | |
| line=dict(color='red', width=3) | |
| )) | |
| else: | |
| # Vertical line | |
| x_vert = c2 / a2 if a2 != 0 else 0 | |
| fig.add_vline(x=x_vert, line_dash="solid", line_color="red", | |
| annotation_text=f"x = {x_vert:.2f}") | |
| # Plot intersection point | |
| if 'graphical_solution' in result and result['graphical_solution']['intersection']: | |
| intersection = result['graphical_solution']['intersection'] | |
| fig.add_trace(go.Scatter( | |
| x=[intersection['x']], y=[intersection['y']], | |
| mode='markers', | |
| name=f"Solution: ({intersection['x']:.3f}, {intersection['y']:.3f})", | |
| marker=dict(color='green', size=12, symbol='circle') | |
| )) | |
| fig.update_layout( | |
| title="Graphical Solution of System", | |
| xaxis_title="x", | |
| yaxis_title="y", | |
| xaxis=dict(range=[-graph_range, graph_range], gridcolor='lightgray'), | |
| yaxis=dict(range=[-graph_range, graph_range], gridcolor='lightgray'), | |
| plot_bgcolor='white', | |
| showlegend=True | |
| ) | |
| st.plotly_chart(fig, use_container_width=True) | |
| else: # 3x3 System | |
| st.header("3Γ3 System of Linear Equations") | |
| # Input section for 3x3 system | |
| col1, col2 = st.columns([1, 1]) | |
| with col1: | |
| st.subheader("π Enter Your 3Γ3 System") | |
| # Use example values if they exist | |
| if 'example_coeffs' in st.session_state and len(st.session_state.example_coeffs) == 3: | |
| default_coeffs = st.session_state.example_coeffs | |
| default_constants = st.session_state.example_constants | |
| else: | |
| default_coeffs = [[1, 2, -1], [2, 1, 1], [1, -1, 2]] | |
| default_constants = [3, 7, 4] | |
| # Create input grid for 3x3 system | |
| st.markdown("**System of equations:** `Ax = b`") | |
| equations = [] | |
| coefficients = [] | |
| constants = [] | |
| for i in range(3): | |
| st.markdown(f"**Equation {i+1}:** `a{i+1}βx + a{i+1}βy + a{i+1}βz = b{i+1}`") | |
| cols = st.columns(4) | |
| row_coeffs = [] | |
| with cols[0]: | |
| val = st.number_input(f"a{i+1}β", value=float(default_coeffs[i][0]), step=0.1, key=f"a{i+1}1") | |
| row_coeffs.append(val) | |
| with cols[1]: | |
| val = st.number_input(f"a{i+1}β", value=float(default_coeffs[i][1]), step=0.1, key=f"a{i+1}2") | |
| row_coeffs.append(val) | |
| with cols[2]: | |
| val = st.number_input(f"a{i+1}β", value=float(default_coeffs[i][2]), step=0.1, key=f"a{i+1}3") | |
| row_coeffs.append(val) | |
| with cols[3]: | |
| val = st.number_input(f"b{i+1}", value=float(default_constants[i]), step=0.1, key=f"b{i+1}") | |
| constants.append(val) | |
| coefficients.append(row_coeffs) | |
| # Format equation string | |
| eq_parts = [] | |
| for j, coeff in enumerate(row_coeffs): | |
| var = ['x', 'y', 'z'][j] | |
| if j == 0: | |
| eq_parts.append(f"{coeff}{var}") | |
| else: | |
| if coeff >= 0: | |
| eq_parts.append(f" + {coeff}{var}") | |
| else: | |
| eq_parts.append(f" - {abs(coeff)}{var}") | |
| equations.append(''.join(eq_parts) + f" = {constants[i]}") | |
| st.markdown("### Your System:") | |
| for eq in equations: | |
| st.latex(eq) | |
| with col2: | |
| # Solve 3x3 system | |
| method_map = {"All Methods": "all", "Matrix": "matrix", "Elimination": "elimination"} | |
| result = st.session_state.solver.solve_3x3_system( | |
| coefficients, constants, method_map[selected_method] | |
| ) | |
| # System type indicator | |
| system_type = result['system_type'] | |
| if system_type == "unique_solution": | |
| st.success("β **Unique Solution** (Consistent Independent)") | |
| elif system_type == "infinite_solutions": | |
| st.info("π **Infinite Solutions** (Consistent Dependent)") | |
| else: | |
| st.error("β **No Solution** (Inconsistent)") | |
| # Display solutions | |
| if selected_method != "All Methods": | |
| method_key = f"{method_map[selected_method]}_solution" | |
| if method_key in result: | |
| solution_data = result[method_key] | |
| st.subheader(f"π {selected_method} Method") | |
| if show_steps and 'steps' in solution_data: | |
| with st.expander("Show Detailed Steps", expanded=True): | |
| for i, step in enumerate(solution_data['steps']): | |
| st.write(f"{i+1}. {step}") | |
| if 'solution' in solution_data and solution_data['solution'] is not None: | |
| if isinstance(solution_data['solution'], dict): | |
| st.markdown("### π― Solution:") | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.metric("x =", f"{solution_data['solution']['x']:.4f}") | |
| with col2: | |
| st.metric("y =", f"{solution_data['solution']['y']:.4f}") | |
| with col3: | |
| st.metric("z =", f"{solution_data['solution']['z']:.4f}") | |
| # Show all methods if selected | |
| if selected_method == "All Methods": | |
| st.header("π All Solution Methods") | |
| methods_to_show = [] | |
| if system_size == "2x2 System": | |
| methods_to_show = ['matrix_solution', 'elimination_solution', 'substitution_solution', 'graphical_solution'] | |
| else: | |
| methods_to_show = ['matrix_solution', 'elimination_solution'] | |
| tabs = st.tabs([method.replace('_solution', '').title() for method in methods_to_show]) | |
| for i, method_key in enumerate(methods_to_show): | |
| with tabs[i]: | |
| if method_key in result: | |
| solution_data = result[method_key] | |
| if 'error' in solution_data: | |
| st.error(f"Error: {solution_data['error']}") | |
| else: | |
| if show_steps and 'steps' in solution_data: | |
| st.subheader("π Steps:") | |
| for j, step in enumerate(solution_data['steps']): | |
| st.write(f"{j+1}. {step}") | |
| if 'solution' in solution_data and solution_data['solution'] is not None: | |
| if isinstance(solution_data['solution'], dict): | |
| st.subheader("π― Solution:") | |
| if system_size == "2x2 System": | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.metric("x =", f"{solution_data['solution']['x']:.4f}") | |
| with col2: | |
| st.metric("y =", f"{solution_data['solution']['y']:.4f}") | |
| else: | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.metric("x =", f"{solution_data['solution']['x']:.4f}") | |
| with col2: | |
| st.metric("y =", f"{solution_data['solution']['y']:.4f}") | |
| with col3: | |
| st.metric("z =", f"{solution_data['solution']['z']:.4f}") | |
| # Solution verification | |
| if show_verification and system_size == "2x2 System": | |
| if 'matrix_solution' in result and result['matrix_solution']['solution']: | |
| st.header("β Solution Verification") | |
| solution = result['matrix_solution']['solution'] | |
| x_val, y_val = solution['x'], solution['y'] | |
| # Check each equation | |
| check1 = a1 * x_val + b1 * y_val | |
| check2 = a2 * x_val + b2 * y_val | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.subheader("Equation 1 Check:") | |
| st.write(f"{a1}({x_val:.4f}) + {b1}({y_val:.4f}) = {check1:.4f}") | |
| if abs(check1 - c1) < 1e-6: | |
| st.success(f"β {check1:.4f} = {c1} β") | |
| else: | |
| st.error(f"β {check1:.4f} β {c1}") | |
| with col2: | |
| st.subheader("Equation 2 Check:") | |
| st.write(f"{a2}({x_val:.4f}) + {b2}({y_val:.4f}) = {check2:.4f}") | |
| if abs(check2 - c2) < 1e-6: | |
| st.success(f"β {check2:.4f} = {c2} β") | |
| else: | |
| st.error(f"β {check2:.4f} β {c2}") | |
| # Educational notes | |
| with st.expander("π Educational Notes"): | |
| if system_size == "2x2 System": | |
| st.markdown(""" | |
| ### 2Γ2 Systems - Key Concepts: | |
| **Types of Solutions:** | |
| - **Unique Solution**: Lines intersect at exactly one point (det β 0) | |
| - **Infinite Solutions**: Lines are identical (same slope, same y-intercept) | |
| - **No Solution**: Lines are parallel (same slope, different y-intercepts) | |
| **Solution Methods:** | |
| 1. **Graphical**: Plot both lines and find intersection point | |
| 2. **Substitution**: Solve one equation for a variable, substitute into the other | |
| 3. **Elimination**: Add/subtract equations to eliminate a variable | |
| 4. **Matrix/Cramer's Rule**: Use determinants to find solution | |
| **When to Use Each Method:** | |
| - **Graphical**: Good for visualization and understanding | |
| - **Substitution**: Best when one variable has coefficient 1 or -1 | |
| - **Elimination**: Good when coefficients are easy to work with | |
| - **Matrix**: Most systematic, especially for larger systems | |
| """) | |
| else: | |
| st.markdown(""" | |
| ### 3Γ3 Systems - Key Concepts: | |
| **Types of Solutions:** | |
| - **Unique Solution**: System has exactly one solution (det β 0) | |
| - **Infinite Solutions**: rank(A) = rank([A|b]) < 3 | |
| - **No Solution**: rank(A) β rank([A|b]) | |
| **Solution Methods:** | |
| 1. **Matrix Method**: Use matrix operations and determinants | |
| 2. **Gaussian Elimination**: Systematic row operations to solve | |
| **Key Skills:** | |
| - Forward elimination to create upper triangular matrix | |
| - Back substitution to find solution | |
| - Recognition of inconsistent and dependent systems | |
| """) | |
| # Footer | |
| st.markdown("---") | |
| st.markdown("*Built with Streamlit for Algebra II students β’ Use the sidebar to explore different examples and methods*") |