Spaces:
Runtime error
Runtime error
changed routing from education level to topics in maths
Browse files- README.md +51 -137
- app.py +86 -68
- letter_counter.py +0 -0
- maths/__init__.py +0 -3
- maths/{middleschool โ algebra}/algebra.py +0 -0
- maths/{middleschool โ algebra}/algebra_interface.py +1 -1
- maths/{elementary โ arithmetic}/arithmetic.py +0 -0
- maths/{elementary โ arithmetic}/arithmetic_interface.py +1 -1
- maths/{university โ calculus}/calculus.py +0 -0
- maths/{university โ calculus}/calculus_interface.py +1 -1
- maths/{university โ differential_equations}/differential_equations.py +0 -0
- maths/{university โ differential_equations}/differential_equations_interface.py +1 -1
- maths/elementary/__init__.py +0 -3
- maths/{highschool โ geometry}/trigonometry.py +0 -0
- maths/{highschool โ geometry}/trigonometry_interface.py +1 -1
- maths/highschool/__init__.py +0 -3
- maths/matrices/matrices.py +40 -0
- maths/{university/linear_algebra_interface.py โ matrices/matrices_interface.py} +11 -110
- maths/middleschool/__init__.py +0 -3
- maths/{university/operations_research โ operations_research}/BranchAndBoundSolver.py +0 -0
- maths/{university/operations_research โ operations_research}/DualSimplexSolver.py +0 -0
- maths/{university/operations_research โ operations_research}/bnb.ipynb +0 -0
- maths/{university/operations_research โ operations_research}/dual.ipynb +0 -0
- maths/{university/operations_research โ operations_research}/get_user_input.py +0 -0
- maths/{university/operations_research โ operations_research}/operations_research_interface.py +0 -0
- maths/{university/operations_research โ operations_research}/simplex_solver_with_steps.py +0 -0
- maths/{university/operations_research โ operations_research}/solve_lp_via_dual.py +0 -0
- maths/{university/operations_research โ operations_research}/solve_primal_directly.py +0 -0
- maths/university/__init__.py +0 -9
- maths/university/linear_algebra.py +0 -249
- maths/university/tests/__init__.py +0 -2
- maths/university/tests/test_differential_equations.py +0 -133
- maths/university/tests/test_linear_algebra.py +0 -132
- maths/university/tests/test_operations_research_interface.py +0 -134
- maths/vectors/vectors.py +35 -0
- maths/vectors/vectors_interface.py +83 -0
- utils/__init__.py +0 -3
- utils/text_utils.py +0 -7
- utils/text_utils_interface.py +0 -11
README.md
CHANGED
@@ -1,146 +1,60 @@
|
|
1 |
-
|
2 |
-
title: Math Tools
|
3 |
-
emoji: ๐งฎ
|
4 |
-
colorFrom: blue
|
5 |
-
colorTo: purple
|
6 |
-
sdk: gradio
|
7 |
-
sdk_version: 5.32.1
|
8 |
-
app_file: app.py
|
9 |
-
pinned: false
|
10 |
-
license: mit
|
11 |
-
short_description: Mathematics tools for different educational levels
|
12 |
-
---
|
13 |
|
14 |
-
|
15 |
|
16 |
-
This
|
17 |
|
18 |
## Features
|
19 |
|
20 |
-
|
21 |
-
|
22 |
-
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
-
|
27 |
-
-
|
28 |
-
-
|
29 |
-
-
|
30 |
-
- Greatest Common Divisor (GCD): Find the GCD of two integers.
|
31 |
-
- Least Common Multiple (LCM): Find the LCM of two integers.
|
32 |
-
- Prime Number Checker: Check if a number is prime.
|
33 |
-
- Array Calculation: Perform basic operations on a list of numbers.
|
34 |
-
- Array Calculation with Visualization: Array calculation with a number line plot.
|
35 |
-
|
36 |
-
### Middle School Math
|
37 |
-
|
38 |
-
- Linear Equation Solver: Solve equations of the form ax = b.
|
39 |
-
- Quadratic Expression Evaluator: Calculate the value of axยฒ + bx + c for a given x.
|
40 |
-
- Quadratic Equation Solver: Find roots of axยฒ + bx + c = 0.
|
41 |
-
- Radical Simplifier: Simplify square roots (e.g., โ12 to 2โ3).
|
42 |
-
- Polynomial Operations: Add, subtract, and multiply polynomials.
|
43 |
-
|
44 |
-
### High School Math
|
45 |
-
|
46 |
-
- Trigonometry Calculator: Calculate sine, cosine, and tangent values for angles in degrees.
|
47 |
-
- Inverse Trigonometric Functions: Calculate asin, acos, atan in degrees.
|
48 |
-
- Trigonometric Equation Solver: Solve basic trigonometric equations.
|
49 |
-
- Trigonometric Identities: Demonstrate common identities like sinยฒ(x) + cosยฒ(x) = 1.
|
50 |
-
|
51 |
-
### University Math
|
52 |
-
|
53 |
-
#### Calculus
|
54 |
-
|
55 |
-
- Polynomial Derivative: Find the derivative of a polynomial function.
|
56 |
-
- Polynomial Integration: Find the indefinite integral of a polynomial function.
|
57 |
-
- Limits: Calculate the limit of an expression as a variable approaches a point.
|
58 |
-
- Series Expansion: Compute Taylor series for functions. Includes examples for Fourier series.
|
59 |
-
- Partial Derivatives: Compute partial derivatives of multi-variable expressions.
|
60 |
-
- Multiple Integrals: Evaluate definite multiple integrals.
|
61 |
-
|
62 |
-
#### Linear Algebra
|
63 |
-
|
64 |
-
- Matrix Operations: Addition, subtraction, multiplication.
|
65 |
-
- Matrix Analysis: Determinant and inverse of matrices.
|
66 |
-
- Vector Operations: Addition, subtraction, dot product, and cross product (for 3D vectors).
|
67 |
-
- System Solver: Solve systems of linear equations (Ax = B).
|
68 |
-
|
69 |
-
#### Differential Equations
|
70 |
-
|
71 |
-
- First-Order ODEs: Solve single or systems of first-order ordinary differential equations with initial conditions.
|
72 |
-
- Second-Order ODEs: Solve second-order ordinary differential equations by converting to a system.
|
73 |
-
- Solution Plotting: Visualize solutions for ODEs.
|
74 |
|
75 |
## Project Structure
|
76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
```
|
78 |
-
โโโ app.py # Main Gradio application file
|
79 |
-
โโโ requirements.txt # Python package dependencies
|
80 |
-
โโโ maths/ # Core mathematics modules
|
81 |
-
โ โโโ __init__.py
|
82 |
-
โ โโโ elementary/ # Elementary school level functions and interfaces
|
83 |
-
โ โ โโโ __init__.py
|
84 |
-
โ โ โโโ arithmetic.py # Logic for basic arithmetic, GCD, LCM, primes
|
85 |
-
โ โ โโโ arithmetic_interface.py # Gradio interfaces for arithmetic
|
86 |
-
โ โโโ middleschool/ # Middle school level functions and interfaces
|
87 |
-
โ โ โโโ __init__.py
|
88 |
-
โ โ โโโ algebra.py # Logic for linear/quadratic equations, polynomials
|
89 |
-
โ โ โโโ algebra_interface.py # Gradio interfaces for algebra
|
90 |
-
โ โโโ highschool/ # High school level functions and interfaces
|
91 |
-
โ โ โโโ __init__.py
|
92 |
-
โ โ โโโ trigonometry.py # Logic for trigonometric functions and equations
|
93 |
-
โ โ โโโ trigonometry_interface.py # Gradio interfaces for trigonometry
|
94 |
-
โ โโโ university/ # University level functions and interfaces
|
95 |
-
โ โโโ __init__.py
|
96 |
-
โ โโโ calculus.py # Logic for calculus (limits, derivatives, integrals, series)
|
97 |
-
โ โโโ calculus_interface.py # Gradio interfaces for calculus
|
98 |
-
โ โโโ linear_algebra.py # Logic for matrix/vector operations, linear systems
|
99 |
-
โ โโโ linear_algebra_interface.py # Gradio interfaces for linear algebra
|
100 |
-
โ โโโ differential_equations.py # Logic for solving ODEs
|
101 |
-
โ โโโ differential_equations_interface.py # Gradio interfaces for ODEs
|
102 |
-
โ โโโ tests/ # Unit tests for university level modules
|
103 |
-
โ โโโ __init__.py
|
104 |
-
โ โโโ test_linear_algebra.py
|
105 |
-
โ โโโ test_differential_equations.py
|
106 |
-
โโโ utils/ # Utility functions and interfaces
|
107 |
-
โโโ __init__.py
|
108 |
-
โโโ text_utils.py # Logic for text processing utilities
|
109 |
-
โโโ text_utils_interface.py # Gradio interface for text utils
|
110 |
-
```
|
111 |
-
|
112 |
-
## Getting Started
|
113 |
-
|
114 |
-
1. Install the required packages:
|
115 |
-
|
116 |
-
```bash
|
117 |
-
pip install -r requirements.txt
|
118 |
-
```
|
119 |
-
|
120 |
-
2. Run the application:
|
121 |
-
|
122 |
-
```
|
123 |
-
python app.py
|
124 |
-
```
|
125 |
-
|
126 |
-
3. Open your browser and navigate to the displayed URL (typically http://127.0.0.1:7860)
|
127 |
-
|
128 |
-
## Extending the Project
|
129 |
-
|
130 |
-
To add new mathematical functions or tools:
|
131 |
-
|
132 |
-
1. **Create Logic**: Add your mathematical function/logic to an existing Python file in the appropriate `maths/<level>/` directory or create a new `.py` file for it. Ensure your functions have clear inputs, outputs, and docstrings.
|
133 |
-
2. **Create Interface**: In the corresponding `maths/<level>/` directory (or a subdirectory like `interfaces` if preferred), create a `_interface.py` file (e.g., `newfeature_interface.py`) or add to an existing one. In this file, import your function(s) and create a Gradio interface for each. Define clear input and output components (e.g., `gr.Textbox()`, `gr.Number()`, `gr.Plot()`, `gr.Image()`).
|
134 |
-
3. **Add Tests**: For more complex logic, especially at the university level, add unit tests in a corresponding `maths/<level>/tests/` directory (e.g., `test_newfeature.py`). Use the `unittest` module or `pytest`.
|
135 |
-
4. **Update Main App**: Import your new Gradio interface object(s) in the main `app.py` file. Add the interface object(s) to the list of interfaces for the relevant educational level tab (e.g., `university_interfaces_list`) and provide a corresponding name in the tab names list (e.g., `university_tab_names`).
|
136 |
-
5. **Update `__init__.py` Files**: Ensure your new modules and interface modules are importable by updating the `__init__.py` files in their respective directories if necessary (e.g., `from . import newfeature`, `from . import newfeature_interface`).
|
137 |
-
6. **Update `requirements.txt`**: If your new feature introduces new external dependencies, add them to `requirements.txt`. It's good practice to pin versions (e.g., `new_package==1.2.3`).
|
138 |
-
7. **Update README**: Document your new feature in the "Features" section and update the "Project Structure" if you added new files/directories.
|
139 |
-
|
140 |
-
## License
|
141 |
-
|
142 |
-
MIT
|
143 |
-
|
144 |
-
---
|
145 |
-
|
146 |
-
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
1 |
+
# Math Tools
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
+
## Overview
|
4 |
|
5 |
+
This application provides a suite of mathematical tools organized by topic (e.g., Algebra, Calculus, Differential Equations) rather than by education level. It's built with Python and Gradio to offer interactive calculators for various mathematical domains.
|
6 |
|
7 |
## Features
|
8 |
|
9 |
+
- **Arithmetic**: Addition, Subtraction, Multiplication, Division, Array Calculations (with visualization)
|
10 |
+
- **Number Theory**: GCD, LCM, Prime Checker
|
11 |
+
- **Algebra**: Expression Evaluation, Radical Simplification, Polynomial Operations
|
12 |
+
- **Equations**: Solvers for Linear, Quadratic, Trigonometric, and Linear Systems
|
13 |
+
- **Geometry**: Trigonometric Functions, Inverse Trigonometry, Identities
|
14 |
+
- **Calculus**: Derivatives, Integrals, Limits, Taylor & Fourier Series, Partial Derivatives, Multiple Integrals
|
15 |
+
- **Differential Equations**: First- and Second-Order ODE Solvers
|
16 |
+
- **Matrices**: Addition, Subtraction, Multiplication, Determinant, Inverse
|
17 |
+
- **Vectors**: Addition, Subtraction, Dot Product, Cross Product
|
18 |
+
- **Operations Research**: Branch & Bound, Dual Simplex, Simplex Solver Steps
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
## Project Structure
|
21 |
|
22 |
+
```text
|
23 |
+
counting/
|
24 |
+
โโโ app.py # Main Gradio application with topic-based tabs
|
25 |
+
โโโ requirements.txt # Python dependencies
|
26 |
+
โโโ README.md # Project documentation (this file)
|
27 |
+
โโโ maths/ # Mathematical modules organized by topic
|
28 |
+
โโโ arithmetic/ # Arithmetic logic & interfaces
|
29 |
+
โ โโโ arithmetic.py
|
30 |
+
โ โโโ arithmetic_interface.py
|
31 |
+
โโโ number_theory/ # Number theory logic & interfaces
|
32 |
+
โ โโโ number_theory.py
|
33 |
+
โ โโโ number_theory_interface.py
|
34 |
+
โโโ algebra/ # Algebra logic & interfaces
|
35 |
+
โ โโโ algebra.py
|
36 |
+
โ โโโ algebra_interface.py
|
37 |
+
โโโ equations/ # Equation solvers & interfaces
|
38 |
+
๏ฟฝ๏ฟฝ๏ฟฝ โโโ equations.py
|
39 |
+
โ โโโ equations_interface.py
|
40 |
+
โโโ geometry/ # Trigonometry & geometry logic & interfaces
|
41 |
+
โ โโโ geometry.py
|
42 |
+
โ โโโ geometry_interface.py
|
43 |
+
โโโ calculus/ # Calculus logic & interfaces
|
44 |
+
โ โโโ calculus.py
|
45 |
+
โ โโโ calculus_interface.py
|
46 |
+
โโโ differential_equations/ # ODE solvers & interfaces
|
47 |
+
โ โโโ differential_equations.py
|
48 |
+
โ โโโ differential_equations_interface.py
|
49 |
+
โโโ matrices/ # Matrix operations logic & interfaces
|
50 |
+
โ โโโ matrices.py
|
51 |
+
โ โโโ matrices_interface.py
|
52 |
+
โโโ vectors/ # Vector operations logic & interfaces
|
53 |
+
โ โโโ vectors.py
|
54 |
+
โ โโโ vectors_interface.py
|
55 |
+
โโโ operations_research/ # Operations research solvers & interfaces
|
56 |
+
โโโ operations_research_interface.py
|
57 |
+
โโโ BranchAndBoundSolver.py
|
58 |
+
โโโ DualSimplexSolver.py
|
59 |
+
โโโ simplex_solver_with_steps.py
|
60 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.py
CHANGED
@@ -1,109 +1,127 @@
|
|
1 |
import gradio as gr
|
2 |
-
from
|
3 |
-
from maths.elementary.arithmetic_interface import (
|
4 |
add_interface, subtract_interface, multiply_interface, divide_interface,
|
5 |
array_calc_interface, array_calc_vis_interface,
|
6 |
gcd_interface, lcm_interface, is_prime_interface # Assuming these were added earlier from a subtask
|
7 |
)
|
8 |
-
from maths.
|
9 |
solve_linear_equation_interface, evaluate_expression_interface,
|
10 |
solve_quadratic_interface, simplify_radical_interface, polynomial_interface # Assuming these
|
11 |
)
|
12 |
-
from maths.
|
13 |
trig_interface, inverse_trig_interface, solve_trig_equations_interface, trig_identities_interface # Assuming these
|
14 |
)
|
15 |
-
from maths.
|
16 |
derivative_interface, integral_interface,
|
17 |
limit_interface, taylor_series_interface, fourier_series_interface, # Assuming these
|
18 |
partial_derivative_interface, multiple_integral_interface # Assuming these
|
19 |
)
|
20 |
-
|
|
|
21 |
matrix_add_interface, matrix_subtract_interface, matrix_multiply_interface,
|
22 |
-
matrix_determinant_interface, matrix_inverse_interface
|
23 |
-
|
24 |
-
|
|
|
|
|
|
|
25 |
)
|
26 |
-
|
|
|
27 |
first_order_ode_interface, second_order_ode_interface
|
28 |
)
|
29 |
-
from maths.
|
30 |
branch_and_bound_interface, dual_simplex_interface, simplex_solver_interface
|
31 |
)
|
32 |
|
33 |
-
#
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
gcd_interface, lcm_interface, is_prime_interface, # Added from subtask 1
|
39 |
-
array_calc_interface, array_calc_vis_interface
|
40 |
]
|
41 |
-
|
42 |
"Addition", "Subtraction", "Multiplication", "Division",
|
43 |
-
"
|
44 |
-
"Array Calculation", "Array Calc Viz"
|
45 |
]
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
]
|
51 |
-
|
52 |
-
"Linear
|
53 |
-
"
|
54 |
]
|
55 |
|
56 |
-
|
57 |
-
|
58 |
-
|
|
|
|
|
|
|
|
|
59 |
]
|
60 |
-
|
61 |
-
"
|
62 |
-
"
|
|
|
63 |
]
|
64 |
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
matrix_add_interface, matrix_subtract_interface,
|
70 |
-
|
71 |
-
|
72 |
-
vector_cross_product_interface, solve_linear_system_interface,
|
73 |
-
first_order_ode_interface, second_order_ode_interface
|
74 |
-
# OR Tab will be added below
|
75 |
]
|
76 |
-
|
77 |
-
"
|
78 |
-
"
|
79 |
-
"Partial Derivatives", "Multiple Integrals", # Added from subtask 4
|
80 |
-
"Matrix Add", "Matrix Subtract", "Matrix Multiply",
|
81 |
-
"Matrix Determinant", "Matrix Inverse",
|
82 |
-
"Vector Add", "Vector Subtract", "Vector Dot Product",
|
83 |
-
"Vector Cross Product", "Solve Linear System",
|
84 |
-
"1st Order ODE", "2nd Order ODE"
|
85 |
-
# "Operations Research" will be added below
|
86 |
]
|
87 |
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
# Add OR tab to University interfaces
|
94 |
-
university_interfaces_list.append(or_tab)
|
95 |
-
university_tab_names.append("Operations Research")
|
96 |
|
|
|
|
|
|
|
|
|
97 |
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
|
103 |
-
# Main demo with tabs
|
104 |
demo = gr.TabbedInterface(
|
105 |
-
[
|
106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
)
|
108 |
|
109 |
# Launch the Gradio app
|
|
|
1 |
import gradio as gr
|
2 |
+
from maths.arithmetic.arithmetic_interface import (
|
|
|
3 |
add_interface, subtract_interface, multiply_interface, divide_interface,
|
4 |
array_calc_interface, array_calc_vis_interface,
|
5 |
gcd_interface, lcm_interface, is_prime_interface # Assuming these were added earlier from a subtask
|
6 |
)
|
7 |
+
from maths.algebra.algebra_interface import (
|
8 |
solve_linear_equation_interface, evaluate_expression_interface,
|
9 |
solve_quadratic_interface, simplify_radical_interface, polynomial_interface # Assuming these
|
10 |
)
|
11 |
+
from maths.geometry.trigonometry_interface import (
|
12 |
trig_interface, inverse_trig_interface, solve_trig_equations_interface, trig_identities_interface # Assuming these
|
13 |
)
|
14 |
+
from maths.calculus.calculus_interface import (
|
15 |
derivative_interface, integral_interface,
|
16 |
limit_interface, taylor_series_interface, fourier_series_interface, # Assuming these
|
17 |
partial_derivative_interface, multiple_integral_interface # Assuming these
|
18 |
)
|
19 |
+
|
20 |
+
from maths.matrices.matrices_interface import (
|
21 |
matrix_add_interface, matrix_subtract_interface, matrix_multiply_interface,
|
22 |
+
matrix_determinant_interface, matrix_inverse_interface
|
23 |
+
)
|
24 |
+
|
25 |
+
from maths.vectors.vectors_interface import (
|
26 |
+
vector_add_interface, vector_subtract_interface,
|
27 |
+
vector_dot_product_interface, vector_cross_product_interface
|
28 |
)
|
29 |
+
|
30 |
+
from maths.differential_equations.differential_equations_interface import (
|
31 |
first_order_ode_interface, second_order_ode_interface
|
32 |
)
|
33 |
+
from maths.operations_research.operations_research_interface import (
|
34 |
branch_and_bound_interface, dual_simplex_interface, simplex_solver_interface
|
35 |
)
|
36 |
|
37 |
+
# Categorize interfaces by topics
|
38 |
+
|
39 |
+
arithmetic_interfaces_list = [
|
40 |
+
add_interface, subtract_interface, multiply_interface,
|
41 |
+
divide_interface, array_calc_interface, array_calc_vis_interface
|
|
|
|
|
42 |
]
|
43 |
+
arithmetic_tab_names = [
|
44 |
"Addition", "Subtraction", "Multiplication", "Division",
|
45 |
+
"Array Calculation", "Array Calculation Viz"
|
|
|
46 |
]
|
47 |
|
48 |
+
number_theory_interfaces_list = [gcd_interface, lcm_interface, is_prime_interface]
|
49 |
+
number_theory_tab_names = ["GCD", "LCM", "Prime Check"]
|
50 |
+
|
51 |
+
algebra_interfaces_list = [evaluate_expression_interface, simplify_radical_interface, polynomial_interface]
|
52 |
+
algebra_tab_names = ["Evaluate Expressions", "Radical Simplifier", "Polynomial Ops"]
|
53 |
+
|
54 |
+
equations_interfaces_list = [
|
55 |
+
solve_linear_equation_interface, solve_quadratic_interface,
|
56 |
+
solve_trig_equations_interface
|
57 |
]
|
58 |
+
equations_tab_names = [
|
59 |
+
"Linear Equation Solver", "Quadratic Solver",
|
60 |
+
"Trigonometric Equation Solver"
|
61 |
]
|
62 |
|
63 |
+
geometry_interfaces_list = [trig_interface, inverse_trig_interface, trig_identities_interface]
|
64 |
+
geometry_tab_names = ["Trig Functions", "Inverse Trig", "Trig Identities"]
|
65 |
+
|
66 |
+
calculus_interfaces_list = [
|
67 |
+
derivative_interface, integral_interface, limit_interface,
|
68 |
+
taylor_series_interface, fourier_series_interface,
|
69 |
+
partial_derivative_interface, multiple_integral_interface
|
70 |
]
|
71 |
+
calculus_tab_names = [
|
72 |
+
"Derivative", "Integral", "Limits",
|
73 |
+
"Taylor Series", "Fourier Series",
|
74 |
+
"Partial Derivatives", "Multiple Integrals"
|
75 |
]
|
76 |
|
77 |
+
differential_equations_interfaces_list = [first_order_ode_interface, second_order_ode_interface]
|
78 |
+
differential_equations_tab_names = ["First Order ODE", "Second Order ODE"]
|
79 |
+
|
80 |
+
matrices_interfaces_list = [
|
81 |
+
matrix_add_interface, matrix_subtract_interface,
|
82 |
+
matrix_multiply_interface, matrix_determinant_interface,
|
83 |
+
matrix_inverse_interface
|
|
|
|
|
|
|
84 |
]
|
85 |
+
matrices_tab_names = [
|
86 |
+
"Matrix Addition", "Matrix Subtraction", "Matrix Multiplication",
|
87 |
+
"Matrix Determinant", "Matrix Inverse"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
]
|
89 |
|
90 |
+
vectors_interfaces_list = [
|
91 |
+
vector_add_interface, vector_subtract_interface,
|
92 |
+
vector_dot_product_interface, vector_cross_product_interface
|
93 |
+
]
|
94 |
+
vectors_tab_names = ["Vector Addition", "Vector Subtraction", "Dot Product", "Cross Product"]
|
|
|
|
|
|
|
95 |
|
96 |
+
operations_research_interfaces_list = [
|
97 |
+
branch_and_bound_interface, dual_simplex_interface, simplex_solver_interface
|
98 |
+
]
|
99 |
+
operations_research_tab_names = ["Branch & Bound", "Dual Simplex", "Simplex Steps"]
|
100 |
|
101 |
+
# Create topic-based tabbed interfaces
|
102 |
+
arithmetic_tab = gr.TabbedInterface(arithmetic_interfaces_list, arithmetic_tab_names, title="Arithmetic")
|
103 |
+
number_theory_tab = gr.TabbedInterface(number_theory_interfaces_list, number_theory_tab_names, title="Number Theory")
|
104 |
+
algebra_tab = gr.TabbedInterface(algebra_interfaces_list, algebra_tab_names, title="Algebra")
|
105 |
+
equations_tab = gr.TabbedInterface(equations_interfaces_list, equations_tab_names, title="Equations")
|
106 |
+
geometry_tab = gr.TabbedInterface(geometry_interfaces_list, geometry_tab_names, title="Geometry")
|
107 |
+
calculus_tab = gr.TabbedInterface(calculus_interfaces_list, calculus_tab_names, title="Calculus")
|
108 |
+
differential_equations_tab = gr.TabbedInterface(differential_equations_interfaces_list, differential_equations_tab_names, title="Differential Equations")
|
109 |
+
matrices_tab = gr.TabbedInterface(matrices_interfaces_list, matrices_tab_names, title="Matrices")
|
110 |
+
vectors_tab = gr.TabbedInterface(vectors_interfaces_list, vectors_tab_names, title="Vectors")
|
111 |
+
operations_research_tab = gr.TabbedInterface(operations_research_interfaces_list, operations_research_tab_names, title="Operations Research")
|
112 |
|
113 |
+
# Main demo with topic tabs
|
114 |
demo = gr.TabbedInterface(
|
115 |
+
[
|
116 |
+
arithmetic_tab, number_theory_tab, algebra_tab,
|
117 |
+
equations_tab, geometry_tab, calculus_tab, differential_equations_tab,
|
118 |
+
matrices_tab, vectors_tab, operations_research_tab
|
119 |
+
],
|
120 |
+
[
|
121 |
+
"Arithmetic", "Number Theory", "Algebra",
|
122 |
+
"Equations", "Geometry", "Calculus", "Differential Equations",
|
123 |
+
"Matrices", "Vectors", "Operations Research"
|
124 |
+
]
|
125 |
)
|
126 |
|
127 |
# Launch the Gradio app
|
letter_counter.py
DELETED
File without changes
|
maths/__init__.py
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
"""
|
2 |
-
Mathematics tools organized by educational levels.
|
3 |
-
"""
|
|
|
|
|
|
|
|
maths/{middleschool โ algebra}/algebra.py
RENAMED
File without changes
|
maths/{middleschool โ algebra}/algebra_interface.py
RENAMED
@@ -1,5 +1,5 @@
|
|
1 |
import gradio as gr
|
2 |
-
from maths.
|
3 |
solve_linear_equation, evaluate_expression, solve_quadratic,
|
4 |
simplify_radical, polynomial_operations
|
5 |
)
|
|
|
1 |
import gradio as gr
|
2 |
+
from maths.algebra.algebra import (
|
3 |
solve_linear_equation, evaluate_expression, solve_quadratic,
|
4 |
simplify_radical, polynomial_operations
|
5 |
)
|
maths/{elementary โ arithmetic}/arithmetic.py
RENAMED
File without changes
|
maths/{elementary โ arithmetic}/arithmetic_interface.py
RENAMED
@@ -1,5 +1,5 @@
|
|
1 |
import gradio as gr
|
2 |
-
from maths.
|
3 |
|
4 |
# Elementary Math Tab
|
5 |
add_interface = gr.Interface(
|
|
|
1 |
import gradio as gr
|
2 |
+
from maths.arithmetic.arithmetic import add, subtract, multiply, divide, calculate_array, calculate_array_with_visualization, gcd, lcm, is_prime
|
3 |
|
4 |
# Elementary Math Tab
|
5 |
add_interface = gr.Interface(
|
maths/{university โ calculus}/calculus.py
RENAMED
File without changes
|
maths/{university โ calculus}/calculus_interface.py
RENAMED
@@ -1,5 +1,5 @@
|
|
1 |
import gradio as gr
|
2 |
-
from maths.
|
3 |
derivative_polynomial, integral_polynomial,
|
4 |
calculate_limit, taylor_series_expansion, fourier_series_example,
|
5 |
partial_derivative, multiple_integral
|
|
|
1 |
import gradio as gr
|
2 |
+
from maths.calculus.calculus import (
|
3 |
derivative_polynomial, integral_polynomial,
|
4 |
calculate_limit, taylor_series_expansion, fourier_series_example,
|
5 |
partial_derivative, multiple_integral
|
maths/{university โ differential_equations}/differential_equations.py
RENAMED
File without changes
|
maths/{university โ differential_equations}/differential_equations_interface.py
RENAMED
@@ -14,7 +14,7 @@ import ast # For safer string literal evaluation if needed for parameters
|
|
14 |
import math # To make math functions available in eval scope for ODEs
|
15 |
|
16 |
# Import the solver functions
|
17 |
-
from maths.
|
18 |
|
19 |
# --- Helper Functions ---
|
20 |
|
|
|
14 |
import math # To make math functions available in eval scope for ODEs
|
15 |
|
16 |
# Import the solver functions
|
17 |
+
from maths.differential_equations.differential_equations import solve_first_order_ode, solve_second_order_ode
|
18 |
|
19 |
# --- Helper Functions ---
|
20 |
|
maths/elementary/__init__.py
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
"""
|
2 |
-
Elementary school level mathematics tools.
|
3 |
-
"""
|
|
|
|
|
|
|
|
maths/{highschool โ geometry}/trigonometry.py
RENAMED
File without changes
|
maths/{highschool โ geometry}/trigonometry_interface.py
RENAMED
@@ -1,5 +1,5 @@
|
|
1 |
import gradio as gr
|
2 |
-
from maths.
|
3 |
|
4 |
# High School Math Tab
|
5 |
trig_interface = gr.Interface(
|
|
|
1 |
import gradio as gr
|
2 |
+
from maths.geometry.trigonometry import sin_degrees, cos_degrees, tan_degrees, inverse_trig_functions, solve_trig_equations, trig_identities
|
3 |
|
4 |
# High School Math Tab
|
5 |
trig_interface = gr.Interface(
|
maths/highschool/__init__.py
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
"""
|
2 |
-
Highschool level mathematics tools.
|
3 |
-
"""
|
|
|
|
|
|
|
|
maths/matrices/matrices.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Matrix operations for university level, using NumPy.
|
3 |
+
"""
|
4 |
+
import numpy as np
|
5 |
+
from typing import List, Union
|
6 |
+
|
7 |
+
Matrix = Union[List[List[float]], np.ndarray]
|
8 |
+
|
9 |
+
def matrix_add(matrix1: Matrix, matrix2: Matrix) -> np.ndarray:
|
10 |
+
m1 = np.array(matrix1)
|
11 |
+
m2 = np.array(matrix2)
|
12 |
+
if m1.shape != m2.shape:
|
13 |
+
raise ValueError("Matrices must have the same dimensions for addition.")
|
14 |
+
return np.add(m1, m2)
|
15 |
+
|
16 |
+
def matrix_subtract(matrix1: Matrix, matrix2: Matrix) -> np.ndarray:
|
17 |
+
m1 = np.array(matrix1)
|
18 |
+
m2 = np.array(matrix2)
|
19 |
+
if m1.shape != m2.shape:
|
20 |
+
raise ValueError("Matrices must have the same dimensions for subtraction.")
|
21 |
+
return np.subtract(m1, m2)
|
22 |
+
|
23 |
+
def matrix_multiply(matrix1: Matrix, matrix2: Matrix) -> np.ndarray:
|
24 |
+
m1 = np.array(matrix1)
|
25 |
+
m2 = np.array(matrix2)
|
26 |
+
if m1.shape[1] != m2.shape[0]:
|
27 |
+
raise ValueError("Number of columns in the first matrix must equal number of rows in the second for multiplication.")
|
28 |
+
return np.dot(m1, m2)
|
29 |
+
|
30 |
+
def matrix_determinant(matrix: Matrix) -> float:
|
31 |
+
m = np.array(matrix)
|
32 |
+
if m.shape[0] != m.shape[1]:
|
33 |
+
raise ValueError("Matrix must be square to compute determinant.")
|
34 |
+
return np.linalg.det(m)
|
35 |
+
|
36 |
+
def matrix_inverse(matrix: Matrix) -> np.ndarray:
|
37 |
+
m = np.array(matrix)
|
38 |
+
if m.shape[0] != m.shape[1]:
|
39 |
+
raise ValueError("Matrix must be square to compute inverse.")
|
40 |
+
return np.linalg.inv(m)
|
maths/{university/linear_algebra_interface.py โ matrices/matrices_interface.py}
RENAMED
@@ -1,92 +1,53 @@
|
|
1 |
"""
|
2 |
-
Gradio Interface for
|
3 |
"""
|
4 |
import gradio as gr
|
5 |
import numpy as np
|
6 |
-
import json
|
7 |
from typing import Union
|
8 |
-
|
9 |
-
from maths.university.linear_algebra import (
|
10 |
matrix_add, matrix_subtract, matrix_multiply,
|
11 |
-
matrix_determinant, matrix_inverse
|
12 |
-
vector_add, vector_subtract, vector_dot_product,
|
13 |
-
vector_cross_product, solve_linear_system
|
14 |
)
|
15 |
|
16 |
-
# Helper functions to parse inputs
|
17 |
def parse_matrix(matrix_str: str, allow_empty_rows_cols=False) -> np.ndarray:
|
18 |
-
"""Parses a string representation of a matrix (JSON format or comma/semicolon separated) into a NumPy array."""
|
19 |
try:
|
20 |
-
# Try JSON parsing first for structure like [[1,2],[3,4]]
|
21 |
m = json.loads(matrix_str)
|
22 |
arr = np.array(m, dtype=float)
|
23 |
if not allow_empty_rows_cols and (arr.shape[0] == 0 or (arr.ndim > 1 and arr.shape[1] == 0)):
|
24 |
raise ValueError("Matrix cannot have zero rows or columns.")
|
25 |
-
if arr.ndim == 1 and arr.shape[0] > 0:
|
26 |
-
|
27 |
-
elif arr.ndim == 0 and not allow_empty_rows_cols
|
28 |
raise ValueError("Input is a scalar, not a matrix.")
|
29 |
return arr
|
30 |
except (json.JSONDecodeError, TypeError, ValueError) as e_json:
|
31 |
-
# Fallback for simpler comma/semicolon separated format, e.g. "1,2;3,4"
|
32 |
try:
|
33 |
rows = [list(map(float, row.split(','))) for row in matrix_str.split(';') if row.strip()]
|
34 |
if not rows and not allow_empty_rows_cols:
|
35 |
raise ValueError("Matrix input is empty.")
|
36 |
-
if not rows and allow_empty_rows_cols:
|
37 |
return np.array([])
|
38 |
-
|
39 |
-
# Check for consistent row lengths
|
40 |
if len(rows) > 1:
|
41 |
first_row_len = len(rows[0])
|
42 |
if not all(len(r) == first_row_len for r in rows):
|
43 |
raise ValueError("All rows must have the same number of columns.")
|
44 |
-
|
45 |
arr = np.array(rows, dtype=float)
|
46 |
if not allow_empty_rows_cols and (arr.shape[0] == 0 or (arr.ndim > 1 and arr.shape[1] == 0)):
|
47 |
-
|
48 |
return arr
|
49 |
-
|
50 |
except ValueError as e_csv:
|
51 |
raise gr.Error(f"Invalid matrix format. Use JSON (e.g., [[1,2],[3,4]]) or comma/semicolon (e.g., 1,2;3,4). Error: {e_csv} (Original JSON error: {e_json})")
|
52 |
-
except Exception as e_gen: # Catch any other parsing errors
|
53 |
-
raise gr.Error(f"General error parsing matrix: {e_gen}")
|
54 |
-
|
55 |
-
|
56 |
-
def parse_vector(vector_str: str) -> np.ndarray:
|
57 |
-
"""Parses a string representation of a vector (JSON or comma-separated) into a NumPy array."""
|
58 |
-
try:
|
59 |
-
# Try JSON parsing for lists like [1,2,3]
|
60 |
-
v = json.loads(vector_str)
|
61 |
-
arr = np.array(v, dtype=float)
|
62 |
-
if arr.ndim != 1:
|
63 |
-
raise ValueError("Vector must be 1-dimensional.")
|
64 |
-
if arr.shape[0] == 0:
|
65 |
-
raise ValueError("Vector cannot be empty.")
|
66 |
-
return arr
|
67 |
-
except (json.JSONDecodeError, TypeError, ValueError) as e_json:
|
68 |
-
# Fallback for simpler comma-separated format e.g. "1,2,3"
|
69 |
-
try:
|
70 |
-
if not vector_str.strip():
|
71 |
-
raise ValueError("Vector input is empty.")
|
72 |
-
arr = np.array([float(x.strip()) for x in vector_str.split(',') if x.strip()], dtype=float)
|
73 |
-
if arr.shape[0] == 0: # case like "," or " , "
|
74 |
-
raise ValueError("Vector cannot be empty after parsing.")
|
75 |
-
return arr
|
76 |
-
except ValueError as e_csv:
|
77 |
-
raise gr.Error(f"Invalid vector format. Use JSON (e.g., [1,2,3]) or comma-separated (e.g., 1,2,3). Error: {e_csv} (Original JSON error: {e_json})")
|
78 |
except Exception as e_gen:
|
79 |
-
raise gr.Error(f"General error parsing
|
80 |
|
81 |
def format_output(data: Union[np.ndarray, float, str]) -> str:
|
82 |
-
"""Formats NumPy array or float for display, handling errors."""
|
83 |
if isinstance(data, np.ndarray):
|
84 |
-
return str(data.tolist())
|
85 |
elif isinstance(data, (float, int, str)):
|
86 |
return str(data)
|
87 |
return "Output type not recognized."
|
88 |
|
89 |
-
# --- Matrix Interfaces ---
|
90 |
matrix_add_interface = gr.Interface(
|
91 |
fn=lambda m1_str, m2_str: format_output(matrix_add(parse_matrix(m1_str), parse_matrix(m2_str))),
|
92 |
inputs=[
|
@@ -135,63 +96,3 @@ matrix_inverse_interface = gr.Interface(
|
|
135 |
title="Matrix Inverse",
|
136 |
description="Calculates the inverse of a square matrix. Matrix must be invertible (non-singular)."
|
137 |
)
|
138 |
-
|
139 |
-
# --- Vector Interfaces ---
|
140 |
-
vector_add_interface = gr.Interface(
|
141 |
-
fn=lambda v1_str, v2_str: format_output(vector_add(parse_vector(v1_str), parse_vector(v2_str))),
|
142 |
-
inputs=[
|
143 |
-
gr.Textbox(label="Vector 1 (JSON or CSV format)", placeholder="e.g., [1,2,3] or 1,2,3"),
|
144 |
-
gr.Textbox(label="Vector 2 (JSON or CSV format)", placeholder="e.g., [4,5,6] or 4,5,6")
|
145 |
-
],
|
146 |
-
outputs=gr.Textbox(label="Resulting Vector"),
|
147 |
-
title="Vector Addition",
|
148 |
-
description="Adds two vectors. Ensure they have the same dimensions."
|
149 |
-
)
|
150 |
-
|
151 |
-
vector_subtract_interface = gr.Interface(
|
152 |
-
fn=lambda v1_str, v2_str: format_output(vector_subtract(parse_vector(v1_str), parse_vector(v2_str))),
|
153 |
-
inputs=[
|
154 |
-
gr.Textbox(label="Vector 1 (Minuend)", placeholder="e.g., [4,5,6]"),
|
155 |
-
gr.Textbox(label="Vector 2 (Subtrahend)", placeholder="e.g., [1,2,3]")
|
156 |
-
],
|
157 |
-
outputs=gr.Textbox(label="Resulting Vector"),
|
158 |
-
title="Vector Subtraction",
|
159 |
-
description="Subtracts the second vector from the first. Ensure they have the same dimensions."
|
160 |
-
)
|
161 |
-
|
162 |
-
vector_dot_product_interface = gr.Interface(
|
163 |
-
fn=lambda v1_str, v2_str: format_output(vector_dot_product(parse_vector(v1_str), parse_vector(v2_str))),
|
164 |
-
inputs=[
|
165 |
-
gr.Textbox(label="Vector 1", placeholder="e.g., [1,2,3]"),
|
166 |
-
gr.Textbox(label="Vector 2", placeholder="e.g., [4,5,6]")
|
167 |
-
],
|
168 |
-
outputs=gr.Textbox(label="Dot Product (Scalar)"),
|
169 |
-
title="Vector Dot Product",
|
170 |
-
description="Calculates the dot product of two vectors. Ensure they have the same dimensions."
|
171 |
-
)
|
172 |
-
|
173 |
-
vector_cross_product_interface = gr.Interface(
|
174 |
-
fn=lambda v1_str, v2_str: format_output(vector_cross_product(parse_vector(v1_str), parse_vector(v2_str))),
|
175 |
-
inputs=[
|
176 |
-
gr.Textbox(label="Vector 1 (3D)", placeholder="e.g., [1,2,3]"),
|
177 |
-
gr.Textbox(label="Vector 2 (3D)", placeholder="e.g., [4,5,6]")
|
178 |
-
],
|
179 |
-
outputs=gr.Textbox(label="Resulting Vector (3D)"),
|
180 |
-
title="Vector Cross Product",
|
181 |
-
description="Calculates the cross product of two 3D vectors."
|
182 |
-
)
|
183 |
-
|
184 |
-
# --- Solve Linear System Interface ---
|
185 |
-
solve_linear_system_interface = gr.Interface(
|
186 |
-
fn=lambda A_str, B_str: format_output(solve_linear_system(parse_matrix(A_str), parse_vector(B_str))),
|
187 |
-
inputs=[
|
188 |
-
gr.Textbox(label="Coefficients Matrix (A)", placeholder="For Ax=B. e.g., [[2,1],[1,1]] for 2x+y, x+y"),
|
189 |
-
gr.Textbox(label="Constants Vector (B)", placeholder="For Ax=B. e.g., [1,1] for =1, =1")
|
190 |
-
],
|
191 |
-
outputs=gr.Textbox(label="Solution Vector (x)"),
|
192 |
-
title="Linear System Solver (Ax = B)",
|
193 |
-
description="Solves a system of linear equations Ax = B. Matrix A must be square and invertible."
|
194 |
-
)
|
195 |
-
|
196 |
-
# It might be useful to group these interfaces in a Gradio TabbedInterface or Blocks layout in a main app file.
|
197 |
-
# For now, this file just defines the individual interfaces.
|
|
|
1 |
"""
|
2 |
+
Gradio Interface for Matrix operations.
|
3 |
"""
|
4 |
import gradio as gr
|
5 |
import numpy as np
|
6 |
+
import json
|
7 |
from typing import Union
|
8 |
+
from maths.matrices.matrices import (
|
|
|
9 |
matrix_add, matrix_subtract, matrix_multiply,
|
10 |
+
matrix_determinant, matrix_inverse
|
|
|
|
|
11 |
)
|
12 |
|
|
|
13 |
def parse_matrix(matrix_str: str, allow_empty_rows_cols=False) -> np.ndarray:
|
|
|
14 |
try:
|
|
|
15 |
m = json.loads(matrix_str)
|
16 |
arr = np.array(m, dtype=float)
|
17 |
if not allow_empty_rows_cols and (arr.shape[0] == 0 or (arr.ndim > 1 and arr.shape[1] == 0)):
|
18 |
raise ValueError("Matrix cannot have zero rows or columns.")
|
19 |
+
if arr.ndim == 1 and arr.shape[0] > 0:
|
20 |
+
arr = arr.reshape(1, -1)
|
21 |
+
elif arr.ndim == 0 and not allow_empty_rows_cols:
|
22 |
raise ValueError("Input is a scalar, not a matrix.")
|
23 |
return arr
|
24 |
except (json.JSONDecodeError, TypeError, ValueError) as e_json:
|
|
|
25 |
try:
|
26 |
rows = [list(map(float, row.split(','))) for row in matrix_str.split(';') if row.strip()]
|
27 |
if not rows and not allow_empty_rows_cols:
|
28 |
raise ValueError("Matrix input is empty.")
|
29 |
+
if not rows and allow_empty_rows_cols:
|
30 |
return np.array([])
|
|
|
|
|
31 |
if len(rows) > 1:
|
32 |
first_row_len = len(rows[0])
|
33 |
if not all(len(r) == first_row_len for r in rows):
|
34 |
raise ValueError("All rows must have the same number of columns.")
|
|
|
35 |
arr = np.array(rows, dtype=float)
|
36 |
if not allow_empty_rows_cols and (arr.shape[0] == 0 or (arr.ndim > 1 and arr.shape[1] == 0)):
|
37 |
+
raise ValueError("Matrix cannot have zero rows or columns after parsing.")
|
38 |
return arr
|
|
|
39 |
except ValueError as e_csv:
|
40 |
raise gr.Error(f"Invalid matrix format. Use JSON (e.g., [[1,2],[3,4]]) or comma/semicolon (e.g., 1,2;3,4). Error: {e_csv} (Original JSON error: {e_json})")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
except Exception as e_gen:
|
42 |
+
raise gr.Error(f"General error parsing matrix: {e_gen}")
|
43 |
|
44 |
def format_output(data: Union[np.ndarray, float, str]) -> str:
|
|
|
45 |
if isinstance(data, np.ndarray):
|
46 |
+
return str(data.tolist())
|
47 |
elif isinstance(data, (float, int, str)):
|
48 |
return str(data)
|
49 |
return "Output type not recognized."
|
50 |
|
|
|
51 |
matrix_add_interface = gr.Interface(
|
52 |
fn=lambda m1_str, m2_str: format_output(matrix_add(parse_matrix(m1_str), parse_matrix(m2_str))),
|
53 |
inputs=[
|
|
|
96 |
title="Matrix Inverse",
|
97 |
description="Calculates the inverse of a square matrix. Matrix must be invertible (non-singular)."
|
98 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
maths/middleschool/__init__.py
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
"""
|
2 |
-
Middle school level mathematics tools.
|
3 |
-
"""
|
|
|
|
|
|
|
|
maths/{university/operations_research โ operations_research}/BranchAndBoundSolver.py
RENAMED
File without changes
|
maths/{university/operations_research โ operations_research}/DualSimplexSolver.py
RENAMED
File without changes
|
maths/{university/operations_research โ operations_research}/bnb.ipynb
RENAMED
File without changes
|
maths/{university/operations_research โ operations_research}/dual.ipynb
RENAMED
File without changes
|
maths/{university/operations_research โ operations_research}/get_user_input.py
RENAMED
File without changes
|
maths/{university/operations_research โ operations_research}/operations_research_interface.py
RENAMED
File without changes
|
maths/{university/operations_research โ operations_research}/simplex_solver_with_steps.py
RENAMED
File without changes
|
maths/{university/operations_research โ operations_research}/solve_lp_via_dual.py
RENAMED
File without changes
|
maths/{university/operations_research โ operations_research}/solve_primal_directly.py
RENAMED
File without changes
|
maths/university/__init__.py
DELETED
@@ -1,9 +0,0 @@
|
|
1 |
-
"""
|
2 |
-
University level mathematics tools.
|
3 |
-
"""
|
4 |
-
|
5 |
-
from . import calculus
|
6 |
-
from . import linear_algebra
|
7 |
-
from . import linear_algebra_interface
|
8 |
-
from . import differential_equations
|
9 |
-
from . import differential_equations_interface
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
maths/university/linear_algebra.py
DELETED
@@ -1,249 +0,0 @@
|
|
1 |
-
"""
|
2 |
-
Linear Algebra operations for university level, using NumPy.
|
3 |
-
"""
|
4 |
-
import numpy as np
|
5 |
-
from typing import List, Union, Tuple
|
6 |
-
|
7 |
-
Matrix = Union[List[List[float]], np.ndarray]
|
8 |
-
Vector = Union[List[float], np.ndarray]
|
9 |
-
|
10 |
-
def matrix_add(matrix1: Matrix, matrix2: Matrix) -> np.ndarray:
|
11 |
-
"""
|
12 |
-
Adds two matrices.
|
13 |
-
|
14 |
-
Args:
|
15 |
-
matrix1: The first matrix.
|
16 |
-
matrix2: The second matrix.
|
17 |
-
|
18 |
-
Returns:
|
19 |
-
The resulting matrix as a NumPy array.
|
20 |
-
Raises:
|
21 |
-
ValueError: If matrices have incompatible shapes.
|
22 |
-
"""
|
23 |
-
m1 = np.array(matrix1)
|
24 |
-
m2 = np.array(matrix2)
|
25 |
-
if m1.shape != m2.shape:
|
26 |
-
raise ValueError("Matrices must have the same dimensions for addition.")
|
27 |
-
return np.add(m1, m2)
|
28 |
-
|
29 |
-
def matrix_subtract(matrix1: Matrix, matrix2: Matrix) -> np.ndarray:
|
30 |
-
"""
|
31 |
-
Subtracts the second matrix from the first.
|
32 |
-
|
33 |
-
Args:
|
34 |
-
matrix1: The first matrix.
|
35 |
-
matrix2: The second matrix.
|
36 |
-
|
37 |
-
Returns:
|
38 |
-
The resulting matrix as a NumPy array.
|
39 |
-
Raises:
|
40 |
-
ValueError: If matrices have incompatible shapes.
|
41 |
-
"""
|
42 |
-
m1 = np.array(matrix1)
|
43 |
-
m2 = np.array(matrix2)
|
44 |
-
if m1.shape != m2.shape:
|
45 |
-
raise ValueError("Matrices must have the same dimensions for subtraction.")
|
46 |
-
return np.subtract(m1, m2)
|
47 |
-
|
48 |
-
def matrix_multiply(matrix1: Matrix, matrix2: Matrix) -> np.ndarray:
|
49 |
-
"""
|
50 |
-
Multiplies two matrices.
|
51 |
-
|
52 |
-
Args:
|
53 |
-
matrix1: The first matrix.
|
54 |
-
matrix2: The second matrix.
|
55 |
-
|
56 |
-
Returns:
|
57 |
-
The resulting matrix as a NumPy array.
|
58 |
-
Raises:
|
59 |
-
ValueError: If matrices have incompatible shapes for multiplication.
|
60 |
-
"""
|
61 |
-
m1 = np.array(matrix1)
|
62 |
-
m2 = np.array(matrix2)
|
63 |
-
if m1.shape[1] != m2.shape[0]:
|
64 |
-
raise ValueError("Number of columns in the first matrix must equal number of rows in the second for multiplication.")
|
65 |
-
return np.dot(m1, m2)
|
66 |
-
|
67 |
-
def matrix_determinant(matrix: Matrix) -> float:
|
68 |
-
"""
|
69 |
-
Calculates the determinant of a square matrix.
|
70 |
-
|
71 |
-
Args:
|
72 |
-
matrix: The matrix (must be square).
|
73 |
-
|
74 |
-
Returns:
|
75 |
-
The determinant of the matrix.
|
76 |
-
Raises:
|
77 |
-
ValueError: If the matrix is not square.
|
78 |
-
"""
|
79 |
-
m = np.array(matrix)
|
80 |
-
if m.shape[0] != m.shape[1]:
|
81 |
-
raise ValueError("Matrix must be square to calculate its determinant.")
|
82 |
-
return np.linalg.det(m)
|
83 |
-
|
84 |
-
def matrix_inverse(matrix: Matrix) -> np.ndarray:
|
85 |
-
"""
|
86 |
-
Calculates the inverse of a square matrix.
|
87 |
-
|
88 |
-
Args:
|
89 |
-
matrix: The matrix (must be square and invertible).
|
90 |
-
|
91 |
-
Returns:
|
92 |
-
The inverse of the matrix as a NumPy array.
|
93 |
-
Raises:
|
94 |
-
ValueError: If the matrix is not square.
|
95 |
-
np.linalg.LinAlgError: If the matrix is singular (not invertible).
|
96 |
-
"""
|
97 |
-
m = np.array(matrix)
|
98 |
-
if m.shape[0] != m.shape[1]:
|
99 |
-
raise ValueError("Matrix must be square to calculate its inverse.")
|
100 |
-
return np.linalg.inv(m)
|
101 |
-
|
102 |
-
def vector_add(vector1: Vector, vector2: Vector) -> np.ndarray:
|
103 |
-
"""
|
104 |
-
Adds two vectors.
|
105 |
-
|
106 |
-
Args:
|
107 |
-
vector1: The first vector.
|
108 |
-
vector2: The second vector.
|
109 |
-
|
110 |
-
Returns:
|
111 |
-
The resulting vector as a NumPy array.
|
112 |
-
Raises:
|
113 |
-
ValueError: If vectors have incompatible shapes.
|
114 |
-
"""
|
115 |
-
v1 = np.array(vector1)
|
116 |
-
v2 = np.array(vector2)
|
117 |
-
if v1.shape != v2.shape:
|
118 |
-
raise ValueError("Vectors must have the same dimensions for addition.")
|
119 |
-
return np.add(v1, v2)
|
120 |
-
|
121 |
-
def vector_subtract(vector1: Vector, vector2: Vector) -> np.ndarray:
|
122 |
-
"""
|
123 |
-
Subtracts the second vector from the first.
|
124 |
-
|
125 |
-
Args:
|
126 |
-
vector1: The first vector.
|
127 |
-
vector2: The second vector.
|
128 |
-
|
129 |
-
Returns:
|
130 |
-
The resulting vector as a NumPy array.
|
131 |
-
Raises:
|
132 |
-
ValueError: If vectors have incompatible shapes.
|
133 |
-
"""
|
134 |
-
v1 = np.array(vector1)
|
135 |
-
v2 = np.array(vector2)
|
136 |
-
if v1.shape != v2.shape:
|
137 |
-
raise ValueError("Vectors must have the same dimensions for subtraction.")
|
138 |
-
return np.subtract(v1, v2)
|
139 |
-
|
140 |
-
def vector_dot_product(vector1: Vector, vector2: Vector) -> float:
|
141 |
-
"""
|
142 |
-
Calculates the dot product of two vectors.
|
143 |
-
|
144 |
-
Args:
|
145 |
-
vector1: The first vector.
|
146 |
-
vector2: The second vector.
|
147 |
-
|
148 |
-
Returns:
|
149 |
-
The dot product of the vectors.
|
150 |
-
Raises:
|
151 |
-
ValueError: If vectors have incompatible shapes.
|
152 |
-
"""
|
153 |
-
v1 = np.array(vector1)
|
154 |
-
v2 = np.array(vector2)
|
155 |
-
if v1.shape != v2.shape:
|
156 |
-
raise ValueError("Vectors must have the same dimensions for dot product.")
|
157 |
-
return np.dot(v1, v2)
|
158 |
-
|
159 |
-
def vector_cross_product(vector1: Vector, vector2: Vector) -> np.ndarray:
|
160 |
-
"""
|
161 |
-
Calculates the cross product of two 3D vectors.
|
162 |
-
|
163 |
-
Args:
|
164 |
-
vector1: The first 3D vector.
|
165 |
-
vector2: The second 3D vector.
|
166 |
-
|
167 |
-
Returns:
|
168 |
-
The resulting 3D vector as a NumPy array.
|
169 |
-
Raises:
|
170 |
-
ValueError: If vectors are not 3-dimensional.
|
171 |
-
"""
|
172 |
-
v1 = np.array(vector1)
|
173 |
-
v2 = np.array(vector2)
|
174 |
-
if v1.shape != (3,) or v2.shape != (3,):
|
175 |
-
raise ValueError("Cross product is only defined for 3-dimensional vectors.")
|
176 |
-
return np.cross(v1, v2)
|
177 |
-
|
178 |
-
def solve_linear_system(coefficients_matrix: Matrix, constants_vector: Vector) -> np.ndarray:
|
179 |
-
"""
|
180 |
-
Solves a system of linear equations Ax = B.
|
181 |
-
|
182 |
-
Args:
|
183 |
-
coefficients_matrix (A): The matrix of coefficients.
|
184 |
-
constants_vector (B): The vector of constants.
|
185 |
-
|
186 |
-
Returns:
|
187 |
-
The solution vector (x) as a NumPy array.
|
188 |
-
Raises:
|
189 |
-
ValueError: If the coefficient matrix is not square or dimensions are incompatible.
|
190 |
-
np.linalg.LinAlgError: If the system has no unique solution (e.g., singular matrix).
|
191 |
-
"""
|
192 |
-
A = np.array(coefficients_matrix)
|
193 |
-
B = np.array(constants_vector)
|
194 |
-
|
195 |
-
if A.shape[0] != A.shape[1]:
|
196 |
-
raise ValueError("Coefficient matrix must be square.")
|
197 |
-
if A.shape[0] != B.shape[0]:
|
198 |
-
raise ValueError("Number of rows in coefficient matrix must match number of elements in constants vector.")
|
199 |
-
|
200 |
-
return np.linalg.solve(A, B)
|
201 |
-
|
202 |
-
# Example Usage (can be removed or commented out for production)
|
203 |
-
if __name__ == '__main__':
|
204 |
-
# Matrix examples
|
205 |
-
m_a = [[1, 2], [3, 4]]
|
206 |
-
m_b = [[5, 6], [7, 8]]
|
207 |
-
print("Matrix A+B:", matrix_add(m_a, m_b))
|
208 |
-
print("Matrix A*B:", matrix_multiply(m_a, m_b))
|
209 |
-
m_c = [[1,2,3],[4,5,6],[7,8,9]] # Singular
|
210 |
-
m_d = [[1,2,3],[0,1,4],[5,6,0]]
|
211 |
-
print("Determinant of D:", matrix_determinant(m_d))
|
212 |
-
try:
|
213 |
-
print("Inverse of D:", matrix_inverse(m_d))
|
214 |
-
except np.linalg.LinAlgError as e:
|
215 |
-
print("Error inverting D:", e)
|
216 |
-
try:
|
217 |
-
print("Inverse of C (singular):", matrix_inverse(m_c)) # Should raise error
|
218 |
-
except np.linalg.LinAlgError as e:
|
219 |
-
print("Error inverting C:", e)
|
220 |
-
|
221 |
-
|
222 |
-
# Vector examples
|
223 |
-
v_a = [1, 2, 3]
|
224 |
-
v_b = [4, 5, 6]
|
225 |
-
print("Vector A+B:", vector_add(v_a, v_b))
|
226 |
-
print("Vector A.B (dot):", vector_dot_product(v_a, v_b))
|
227 |
-
print("Vector AxB (cross):", vector_cross_product(v_a, v_b))
|
228 |
-
|
229 |
-
v_c = [1,2]
|
230 |
-
v_d = [3,4]
|
231 |
-
try:
|
232 |
-
print(vector_cross_product(v_c,v_d)) # Should error
|
233 |
-
except ValueError as e:
|
234 |
-
print("Error cross product:", e)
|
235 |
-
|
236 |
-
# Solve linear system example
|
237 |
-
# 2x + y = 1
|
238 |
-
# x + y = 1
|
239 |
-
coeffs = [[2, 1], [1, 1]]
|
240 |
-
consts = [1, 1]
|
241 |
-
print("Solution to 2x+y=1, x+y=1 is:", solve_linear_system(coeffs, consts)) # Expected: [0, 1]
|
242 |
-
|
243 |
-
# Singular system
|
244 |
-
coeffs_singular = [[1, 1], [1, 1]]
|
245 |
-
consts_singular = [1, 2] # No solution
|
246 |
-
try:
|
247 |
-
print("Solution to singular system:", solve_linear_system(coeffs_singular, consts_singular))
|
248 |
-
except np.linalg.LinAlgError as e:
|
249 |
-
print("Error solving singular system:", e)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
maths/university/tests/__init__.py
DELETED
@@ -1,2 +0,0 @@
|
|
1 |
-
# This file makes 'tests' a Python package.
|
2 |
-
# It can be empty.
|
|
|
|
|
|
maths/university/tests/test_differential_equations.py
DELETED
@@ -1,133 +0,0 @@
|
|
1 |
-
import unittest
|
2 |
-
import numpy as np
|
3 |
-
import math
|
4 |
-
from numpy.testing import assert_array_almost_equal
|
5 |
-
|
6 |
-
# Adjust import path as necessary
|
7 |
-
from maths.university.differential_equations import solve_first_order_ode, solve_second_order_ode
|
8 |
-
|
9 |
-
class TestDifferentialEquations(unittest.TestCase):
|
10 |
-
|
11 |
-
def test_solve_simple_first_order_ode_constant_rate(self):
|
12 |
-
"""Test dy/dt = k, e.g., dy/dt = 2 with y(0)=1. Solution y(t) = 2t + 1."""
|
13 |
-
k = 2.0
|
14 |
-
y_initial = 1.0
|
15 |
-
|
16 |
-
def ode_func(t, y):
|
17 |
-
# For a system, y is an array. Here, it's a single equation, so y[0]
|
18 |
-
# solve_ivp always passes y as at least a 1-element array.
|
19 |
-
return k
|
20 |
-
|
21 |
-
t_span = (0, 5)
|
22 |
-
t_eval_count = 50
|
23 |
-
y0 = [y_initial] # Initial condition must be a list or 1D array for solve_ivp
|
24 |
-
|
25 |
-
result = solve_first_order_ode(ode_func, t_span, y0, t_eval_count=t_eval_count)
|
26 |
-
|
27 |
-
self.assertTrue(result['success'], msg=f"Solver failed: {result['message']}")
|
28 |
-
self.assertIsInstance(result['t'], np.ndarray)
|
29 |
-
self.assertIsInstance(result['y'], np.ndarray)
|
30 |
-
|
31 |
-
self.assertEqual(result['t'].shape, (t_eval_count,))
|
32 |
-
# solve_ivp returns y with shape (n_equations, n_timepoints)
|
33 |
-
self.assertEqual(result['y'].shape, (1, t_eval_count))
|
34 |
-
|
35 |
-
# Check analytical solution: y(t) = k*t + y0
|
36 |
-
expected_y = k * result['t'] + y_initial
|
37 |
-
assert_array_almost_equal(result['y'][0], expected_y, decimal=5,
|
38 |
-
err_msg="Numerical solution does not match analytical solution for dy/dt=k.")
|
39 |
-
|
40 |
-
def test_solve_simple_first_order_ode_exponential_decay(self):
|
41 |
-
"""Test dy/dt = -k*y, e.g., dy/dt = -0.5*y with y(0)=10. Solution y(t) = 10*exp(-0.5t)."""
|
42 |
-
k = 0.5
|
43 |
-
y_initial = 10.0
|
44 |
-
|
45 |
-
def ode_func(t, y):
|
46 |
-
return -k * y[0] # y is [y_val]
|
47 |
-
|
48 |
-
t_span = (0, 3)
|
49 |
-
t_eval_count = 30
|
50 |
-
y0 = [y_initial]
|
51 |
-
|
52 |
-
result = solve_first_order_ode(ode_func, t_span, y0, t_eval_count=t_eval_count)
|
53 |
-
|
54 |
-
self.assertTrue(result['success'], msg=f"Solver failed for exponential decay: {result['message']}")
|
55 |
-
self.assertEqual(result['t'].shape, (t_eval_count,))
|
56 |
-
self.assertEqual(result['y'].shape, (1, t_eval_count))
|
57 |
-
|
58 |
-
# Check analytical solution: y(t) = y0 * exp(-k*t)
|
59 |
-
expected_y = y_initial * np.exp(-k * result['t'])
|
60 |
-
assert_array_almost_equal(result['y'][0], expected_y, decimal=5,
|
61 |
-
err_msg="Numerical solution does not match analytical for exponential decay.")
|
62 |
-
|
63 |
-
|
64 |
-
def test_solve_simple_second_order_ode_constant_acceleration(self):
|
65 |
-
"""Test dยฒy/dtยฒ = a, e.g., dยฒy/dtยฒ = 2 with y(0)=1, y'(0)=0.5.
|
66 |
-
Solution y'(t) = a*t + y'(0) => y'(t) = 2t + 0.5
|
67 |
-
Solution y(t) = 0.5*a*tยฒ + y'(0)*t + y(0) => y(t) = tยฒ + 0.5t + 1
|
68 |
-
"""
|
69 |
-
accel = 2.0
|
70 |
-
y_initial = 1.0
|
71 |
-
dy_dt_initial = 0.5
|
72 |
-
|
73 |
-
def ode_func_second_order(t, y_val, dy_dt_val):
|
74 |
-
return accel # dยฒy/dtยฒ = constant
|
75 |
-
|
76 |
-
t_span = (0, 4)
|
77 |
-
t_eval_count = 40
|
78 |
-
|
79 |
-
result = solve_second_order_ode(
|
80 |
-
ode_func_second_order, t_span, y_initial, dy_dt_initial, t_eval_count=t_eval_count
|
81 |
-
)
|
82 |
-
|
83 |
-
self.assertTrue(result['success'], msg=f"Solver failed for 2nd order const accel: {result['message']}")
|
84 |
-
self.assertIsInstance(result['t'], np.ndarray)
|
85 |
-
self.assertIsInstance(result['y'], np.ndarray)
|
86 |
-
self.assertIsInstance(result['dy_dt'], np.ndarray)
|
87 |
-
|
88 |
-
self.assertEqual(result['t'].shape, (t_eval_count,))
|
89 |
-
self.assertEqual(result['y'].shape, (t_eval_count,)) # Output y is 1D array
|
90 |
-
self.assertEqual(result['dy_dt'].shape, (t_eval_count,)) # Output dy_dt is 1D array
|
91 |
-
|
92 |
-
# Check analytical solution for y(t)
|
93 |
-
expected_y = 0.5 * accel * result['t']**2 + dy_dt_initial * result['t'] + y_initial
|
94 |
-
assert_array_almost_equal(result['y'], expected_y, decimal=5,
|
95 |
-
err_msg="Numerical y(t) does not match analytical for const accel.")
|
96 |
-
|
97 |
-
# Check analytical solution for dy/dt(t)
|
98 |
-
expected_dy_dt = accel * result['t'] + dy_dt_initial
|
99 |
-
assert_array_almost_equal(result['dy_dt'], expected_dy_dt, decimal=5,
|
100 |
-
err_msg="Numerical dy/dt(t) does not match analytical for const accel.")
|
101 |
-
|
102 |
-
def test_solve_damped_oscillator_second_order(self):
|
103 |
-
"""Test dยฒy/dtยฒ = -b*(dy/dt) - k*y (damped harmonic oscillator).
|
104 |
-
This is more complex and won't have a trivial analytical solution form for all parameters,
|
105 |
-
so we mainly check if it runs and produces output of the correct shape.
|
106 |
-
"""
|
107 |
-
damping_b = 0.5 # Damping coefficient
|
108 |
-
spring_k = 2.0 # Spring constant (normalized for m=1)
|
109 |
-
y_initial = 1.0
|
110 |
-
dy_dt_initial = 0.0
|
111 |
-
|
112 |
-
def damped_oscillator_func(t, y, dy_dt):
|
113 |
-
return -damping_b * dy_dt - spring_k * y
|
114 |
-
|
115 |
-
t_span = (0, 10)
|
116 |
-
t_eval_count = 100
|
117 |
-
|
118 |
-
result = solve_second_order_ode(
|
119 |
-
damped_oscillator_func, t_span, y_initial, dy_dt_initial, t_eval_count=t_eval_count
|
120 |
-
)
|
121 |
-
|
122 |
-
self.assertTrue(result['success'], msg=f"Solver failed for damped oscillator: {result['message']}")
|
123 |
-
self.assertEqual(result['t'].shape, (t_eval_count,))
|
124 |
-
self.assertEqual(result['y'].shape, (t_eval_count,))
|
125 |
-
self.assertEqual(result['dy_dt'].shape, (t_eval_count,))
|
126 |
-
# For a damped oscillator starting from rest at y=1, y should decrease initially (or oscillate around 0)
|
127 |
-
# This is just a sanity check, not a strict assertion of values.
|
128 |
-
if len(result['y']) > 1:
|
129 |
-
self.assertTrue(result['y'][0] > result['y'][-1] or result['y'][0] < result['y'][-1] or result['y'][0] != result['y'][1])
|
130 |
-
|
131 |
-
|
132 |
-
if __name__ == '__main__':
|
133 |
-
unittest.main(argv=['first-arg-is-ignored'], exit=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
maths/university/tests/test_linear_algebra.py
DELETED
@@ -1,132 +0,0 @@
|
|
1 |
-
import unittest
|
2 |
-
import numpy as np
|
3 |
-
from numpy.testing import assert_array_almost_equal, assert_raises
|
4 |
-
|
5 |
-
# Adjust the import path based on your project structure if necessary
|
6 |
-
# Assuming 'maths' is a top-level directory in PYTHONPATH or current working directory
|
7 |
-
from maths.university.linear_algebra import (
|
8 |
-
matrix_add, matrix_subtract, matrix_multiply,
|
9 |
-
matrix_determinant, matrix_inverse,
|
10 |
-
vector_add, vector_subtract, vector_dot_product,
|
11 |
-
vector_cross_product, solve_linear_system
|
12 |
-
)
|
13 |
-
|
14 |
-
class TestLinearAlgebra(unittest.TestCase):
|
15 |
-
|
16 |
-
def test_matrix_add(self):
|
17 |
-
m1 = np.array([[1, 2], [3, 4]])
|
18 |
-
m2 = np.array([[5, 6], [7, 8]])
|
19 |
-
expected = np.array([[6, 8], [10, 12]])
|
20 |
-
assert_array_almost_equal(matrix_add(m1, m2), expected)
|
21 |
-
assert_array_almost_equal(matrix_add([[1,2],[3,4]], [[5,6],[7,8]]), expected)
|
22 |
-
|
23 |
-
def test_matrix_multiply(self):
|
24 |
-
m1 = np.array([[1, 2], [3, 4]])
|
25 |
-
m2 = np.array([[5, 6], [7, 8]]) # 2x2
|
26 |
-
expected = np.array([[19, 22], [43, 50]]) # (1*5+2*7), (1*6+2*8) etc.
|
27 |
-
assert_array_almost_equal(matrix_multiply(m1, m2), expected)
|
28 |
-
|
29 |
-
m3 = np.array([[1,2,3],[4,5,6]]) # 2x3
|
30 |
-
m4 = np.array([[7,8],[9,10],[11,12]]) # 3x2
|
31 |
-
expected2 = np.array([[58,64],[139,154]])
|
32 |
-
assert_array_almost_equal(matrix_multiply(m3,m4),expected2)
|
33 |
-
|
34 |
-
# Test incompatible shapes
|
35 |
-
with assert_raises(ValueError):
|
36 |
-
matrix_multiply(m1, m3) # 2x2 and 2x3 not compatible like this
|
37 |
-
|
38 |
-
def test_matrix_determinant(self):
|
39 |
-
m1 = np.array([[1, 2], [3, 4]]) # det = 1*4 - 2*3 = 4 - 6 = -2
|
40 |
-
self.assertAlmostEqual(matrix_determinant(m1), -2.0)
|
41 |
-
|
42 |
-
m2 = np.array([[3, 1, 0], [2, 0, 1], [0, 2, 4]])
|
43 |
-
# Det = 3(0-2) - 1(8-0) + 0 = -6 - 8 = -14
|
44 |
-
self.assertAlmostEqual(matrix_determinant(m2), -14.0)
|
45 |
-
|
46 |
-
m_singular = np.array([[1,2],[2,4]]) # det = 0
|
47 |
-
self.assertAlmostEqual(matrix_determinant(m_singular), 0.0)
|
48 |
-
|
49 |
-
def test_matrix_inverse(self):
|
50 |
-
m1 = np.array([[1, 2], [3, 7]]) # det = 7-6 = 1
|
51 |
-
# inv = 1/1 * [[7, -2], [-3, 1]]
|
52 |
-
expected_inv1 = np.array([[7, -2], [-3, 1]])
|
53 |
-
assert_array_almost_equal(matrix_inverse(m1), expected_inv1)
|
54 |
-
|
55 |
-
m_non_square = np.array([[1,2,3],[4,5,6]])
|
56 |
-
with assert_raises(ValueError): # Specific to our implementation if it checks before numpy
|
57 |
-
matrix_inverse(m_non_square)
|
58 |
-
|
59 |
-
m_singular = np.array([[1, 2], [2, 4]]) # Determinant is 0
|
60 |
-
with assert_raises(np.linalg.LinAlgError): # Numpy's error for singular matrix
|
61 |
-
matrix_inverse(m_singular)
|
62 |
-
|
63 |
-
def test_vector_dot_product(self):
|
64 |
-
v1 = np.array([1, 2, 3])
|
65 |
-
v2 = np.array([4, 5, 6])
|
66 |
-
# 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32
|
67 |
-
self.assertAlmostEqual(vector_dot_product(v1, v2), 32.0)
|
68 |
-
self.assertAlmostEqual(vector_dot_product([1,0,-1], [1,1,1]), 0.0) # Orthogonal
|
69 |
-
|
70 |
-
def test_vector_cross_product(self):
|
71 |
-
v1 = np.array([1, 0, 0]) # i
|
72 |
-
v2 = np.array([0, 1, 0]) # j
|
73 |
-
expected_ij = np.array([0, 0, 1]) # k
|
74 |
-
assert_array_almost_equal(vector_cross_product(v1, v2), expected_ij)
|
75 |
-
|
76 |
-
v3 = np.array([1, 2, 3])
|
77 |
-
v4 = np.array([4, 5, 6])
|
78 |
-
# (2*6 - 3*5, 3*4 - 1*6, 1*5 - 2*4)
|
79 |
-
# (12 - 15, 12 - 6, 5 - 8)
|
80 |
-
# (-3, 6, -3)
|
81 |
-
expected_v3v4 = np.array([-3, 6, -3])
|
82 |
-
assert_array_almost_equal(vector_cross_product(v3, v4), expected_v3v4)
|
83 |
-
|
84 |
-
# Test non-3D vectors
|
85 |
-
v_2d_1 = [1,2]
|
86 |
-
v_2d_2 = [3,4]
|
87 |
-
with assert_raises(ValueError):
|
88 |
-
vector_cross_product(v_2d_1, v_2d_2)
|
89 |
-
with assert_raises(ValueError):
|
90 |
-
vector_cross_product(v1, v_2d_1) # One 3D, one 2D
|
91 |
-
|
92 |
-
def test_solve_linear_system(self):
|
93 |
-
# System 1:
|
94 |
-
# 2x + y = 5
|
95 |
-
# x - y = 1
|
96 |
-
# Solution: x=2, y=1
|
97 |
-
A1 = np.array([[2, 1], [1, -1]])
|
98 |
-
B1 = np.array([5, 1])
|
99 |
-
expected_X1 = np.array([2, 1])
|
100 |
-
assert_array_almost_equal(solve_linear_system(A1, B1), expected_X1, decimal=6)
|
101 |
-
|
102 |
-
# System 2:
|
103 |
-
# x + y + z = 6
|
104 |
-
# 2y + 5z = -4
|
105 |
-
# 2x + 5y - z = 27
|
106 |
-
# Solution: x=5, y=3, z=-2 (from online calculator)
|
107 |
-
A2 = np.array([[1, 1, 1], [0, 2, 5], [2, 5, -1]])
|
108 |
-
B2 = np.array([6, -4, 27])
|
109 |
-
expected_X2 = np.array([5, 3, -2])
|
110 |
-
assert_array_almost_equal(solve_linear_system(A2, B2), expected_X2, decimal=6)
|
111 |
-
|
112 |
-
# Singular system (no unique solution)
|
113 |
-
A_singular = np.array([[1, 1], [2, 2]])
|
114 |
-
B_singular = np.array([1, 3]) # Inconsistent
|
115 |
-
with assert_raises(np.linalg.LinAlgError):
|
116 |
-
solve_linear_system(A_singular, B_singular)
|
117 |
-
|
118 |
-
# Non-square coefficient matrix
|
119 |
-
A_non_square = np.array([[1,1,1],[0,2,5]])
|
120 |
-
B_non_square = np.array([6,-4])
|
121 |
-
with assert_raises(ValueError):
|
122 |
-
solve_linear_system(A_non_square, B_non_square)
|
123 |
-
|
124 |
-
# Incompatible dimensions B vector
|
125 |
-
A_valid = np.array([[1,1],[0,2]])
|
126 |
-
B_invalid_dim = np.array([1,2,3])
|
127 |
-
with assert_raises(ValueError): # Or LinAlgError depending on numpy's internal checks order
|
128 |
-
solve_linear_system(A_valid, B_invalid_dim)
|
129 |
-
|
130 |
-
|
131 |
-
if __name__ == '__main__':
|
132 |
-
unittest.main(argv=['first-arg-is-ignored'], exit=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
maths/university/tests/test_operations_research_interface.py
DELETED
@@ -1,134 +0,0 @@
|
|
1 |
-
import pytest
|
2 |
-
import numpy as np
|
3 |
-
import gradio as gr # Import for gr.Error if used in parsing
|
4 |
-
|
5 |
-
# Assuming parsing functions and interface wrappers are in the following module
|
6 |
-
from maths.university.operations_research.operations_research_interface import (
|
7 |
-
parse_vector, parse_matrix, parse_relations, parse_bounds, # Import parsing functions if you want to test them directly too
|
8 |
-
solve_branch_and_bound_interface,
|
9 |
-
solve_dual_simplex_interface,
|
10 |
-
run_simplex_solver_interface
|
11 |
-
)
|
12 |
-
|
13 |
-
# Test for Branch and Bound Interface
|
14 |
-
def test_bnb_interface_valid_input():
|
15 |
-
# Example from its own interface definition
|
16 |
-
c_str = "5,4"
|
17 |
-
A_str = "1,1;2,0;0,1"
|
18 |
-
b_str = "5,6,3"
|
19 |
-
integer_vars_str = "0,1" # Both vars are integer
|
20 |
-
binary_vars_str = "" # No specific binary vars beyond integer_vars
|
21 |
-
maximize_bool = True
|
22 |
-
|
23 |
-
solution_str, objective_str, log_str, fig = solve_branch_and_bound_interface(
|
24 |
-
c_str, A_str, b_str, integer_vars_str, binary_vars_str, maximize_bool
|
25 |
-
)
|
26 |
-
|
27 |
-
# Expected solution for this problem is x0=2, x1=3, objective=22
|
28 |
-
assert "2.000, 3.000" in solution_str or "2, 3" in solution_str # Allow for formatting variations
|
29 |
-
assert "22.000" in objective_str or "22.0" in objective_str
|
30 |
-
assert fig is not None # Check that a figure object is returned
|
31 |
-
assert "Branch and bound completed!" in log_str
|
32 |
-
assert "Optimal objective: 22.0" in log_str # More specific check
|
33 |
-
|
34 |
-
def test_bnb_interface_parsing_error():
|
35 |
-
# Invalid matrix string (row length mismatch)
|
36 |
-
solution_str, objective_str, log_str, fig = solve_branch_and_bound_interface(
|
37 |
-
"1,2", "1,2;3", "10,12", "", "", True # b_str needs two elements if A has two rows
|
38 |
-
)
|
39 |
-
# The error message comes from parse_matrix via gr.Warning, which is then caught by the wrapper.
|
40 |
-
# The wrapper appends to its own log_messages.
|
41 |
-
assert "Error parsing matrix" in log_str or "Could not parse matrix" in log_str
|
42 |
-
assert fig is None
|
43 |
-
|
44 |
-
# Test for Dual Simplex Interface
|
45 |
-
def test_dual_simplex_interface_valid_input():
|
46 |
-
# Example from its own interface definition, but made consistent for Dual Simplex properties
|
47 |
-
# Max Z = -2x1 -x2 (originally Min 2x1+x2)
|
48 |
-
# s.t. -x1 -x2 <= -5 (originally x1+x2 >= 5)
|
49 |
-
# -2x1 -x2 <= -6 (originally 2x1+x2 >= 6)
|
50 |
-
obj_type = "max"
|
51 |
-
c_str = "-2,-1"
|
52 |
-
A_str = "-1,-1;-2,-1"
|
53 |
-
relations_str = "<=,<=" # Correct for typical dual simplex tableau setup
|
54 |
-
b_str = "-5,-6"
|
55 |
-
|
56 |
-
solution_str, objective_str, log_str = solve_dual_simplex_interface(
|
57 |
-
obj_type, c_str, A_str, relations_str, b_str
|
58 |
-
)
|
59 |
-
|
60 |
-
# For Z' = -2x1 -x2 s.t. -x1-x2<=-5, -2x1-x2<=-6. Optimal is x1=1, x2=4, Z'=-6. (Min Z = 6)
|
61 |
-
# The solution string format depends on the solver's _print_results
|
62 |
-
assert "x1: 1.000" in solution_str or "x1=1.000" in solution_str
|
63 |
-
assert "x2: 4.000" in solution_str or "x2=4.000" in solution_str
|
64 |
-
assert "-6.000" in objective_str # Max -Z
|
65 |
-
assert "Optimal Solution Found" in log_str or "Final Solution" in log_str
|
66 |
-
|
67 |
-
def test_dual_simplex_interface_dim_mismatch():
|
68 |
-
solution_str, objective_str, log_str = solve_dual_simplex_interface(
|
69 |
-
"max", "1,2", "1,1;2,2", "<=", "10,12" # relations_str has 1 relation, A has 2 rows
|
70 |
-
)
|
71 |
-
assert "Dimension mismatch" in log_str # Check for error message
|
72 |
-
|
73 |
-
# Test for Simplex Solver Interface
|
74 |
-
def test_simplex_solver_interface_valid_input():
|
75 |
-
# Example from its own interface definition
|
76 |
-
c_str = "3,5"
|
77 |
-
A_str = "1,0;0,2;3,2"
|
78 |
-
b_str = "4,12,18"
|
79 |
-
bounds_str = "0,None;0,None" # Non-negative
|
80 |
-
|
81 |
-
solution_str, objective_str, steps_str = run_simplex_solver_interface(
|
82 |
-
c_str, A_str, b_str, bounds_str
|
83 |
-
)
|
84 |
-
|
85 |
-
# Expected: x1=2, x2=6, Z=36
|
86 |
-
assert "2.000, 6.000" in solution_str or "2, 6" in solution_str
|
87 |
-
assert "36.000" in objective_str or "36.0" in objective_str
|
88 |
-
assert "Simplex Method Complete" in steps_str
|
89 |
-
assert "Initial tableau" in steps_str
|
90 |
-
|
91 |
-
def test_simplex_solver_interface_invalid_bounds():
|
92 |
-
solution_str, objective_str, steps_str = run_simplex_solver_interface(
|
93 |
-
"1,2", "1,1;2,1", "10,12", "0,None;0" # Malformed bounds pair
|
94 |
-
)
|
95 |
-
assert "Error parsing var_bounds" in steps_str or "Could not parse bounds" in steps_str
|
96 |
-
|
97 |
-
|
98 |
-
# Test parsing functions directly
|
99 |
-
def test_parse_matrix_valid():
|
100 |
-
assert np.array_equal(parse_matrix("1,2;3,4"), np.array([[1.0,2.0],[3.0,4.0]]))
|
101 |
-
|
102 |
-
def test_parse_matrix_invalid_char():
|
103 |
-
# parse_matrix issues a gr.Warning and returns an empty np.array([])
|
104 |
-
# The test checks if the returned array is empty.
|
105 |
-
# We cannot directly test gr.Warning without a more complex setup.
|
106 |
-
result = parse_matrix("1,2;3,a")
|
107 |
-
assert isinstance(result, np.ndarray)
|
108 |
-
assert result.size == 0
|
109 |
-
|
110 |
-
def test_parse_matrix_invalid_row_length():
|
111 |
-
result = parse_matrix("1,2;3,4,5")
|
112 |
-
assert isinstance(result, np.ndarray)
|
113 |
-
assert result.size == 0
|
114 |
-
|
115 |
-
def test_parse_vector_valid():
|
116 |
-
assert parse_vector("1,2,3.5") == [1.0, 2.0, 3.5]
|
117 |
-
|
118 |
-
def test_parse_vector_invalid():
|
119 |
-
assert parse_vector("1,a,3") == []
|
120 |
-
|
121 |
-
def test_parse_relations_valid():
|
122 |
-
assert parse_relations("<=,>=,=") == ["<=", ">=", "="]
|
123 |
-
|
124 |
-
def test_parse_relations_invalid():
|
125 |
-
assert parse_relations("<=,>,=") == [] # '>' is invalid
|
126 |
-
|
127 |
-
def test_parse_bounds_valid():
|
128 |
-
assert parse_bounds("0,None;10,20.5;None,5") == [(0.0, None), (10.0, 20.5), (None, 5.0)]
|
129 |
-
|
130 |
-
def test_parse_bounds_invalid_format():
|
131 |
-
assert parse_bounds("0,None;10,20,30") == [] # middle pair has 3 parts
|
132 |
-
|
133 |
-
def test_parse_bounds_invalid_order():
|
134 |
-
assert parse_bounds("10,0") == [] # lower > upper
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
maths/vectors/vectors.py
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Vector operations for university level, using NumPy.
|
3 |
+
"""
|
4 |
+
import numpy as np
|
5 |
+
from typing import List, Union
|
6 |
+
|
7 |
+
Vector = Union[List[float], np.ndarray]
|
8 |
+
|
9 |
+
def vector_add(vector1: Vector, vector2: Vector) -> np.ndarray:
|
10 |
+
v1 = np.array(vector1)
|
11 |
+
v2 = np.array(vector2)
|
12 |
+
if v1.shape != v2.shape:
|
13 |
+
raise ValueError("Vectors must have the same dimensions for addition.")
|
14 |
+
return np.add(v1, v2)
|
15 |
+
|
16 |
+
def vector_subtract(vector1: Vector, vector2: Vector) -> np.ndarray:
|
17 |
+
v1 = np.array(vector1)
|
18 |
+
v2 = np.array(vector2)
|
19 |
+
if v1.shape != v2.shape:
|
20 |
+
raise ValueError("Vectors must have the same dimensions for subtraction.")
|
21 |
+
return np.subtract(v1, v2)
|
22 |
+
|
23 |
+
def vector_dot_product(vector1: Vector, vector2: Vector) -> float:
|
24 |
+
v1 = np.array(vector1)
|
25 |
+
v2 = np.array(vector2)
|
26 |
+
if v1.shape != v2.shape:
|
27 |
+
raise ValueError("Vectors must have the same dimensions for dot product.")
|
28 |
+
return np.dot(v1, v2)
|
29 |
+
|
30 |
+
def vector_cross_product(vector1: Vector, vector2: Vector) -> np.ndarray:
|
31 |
+
v1 = np.array(vector1)
|
32 |
+
v2 = np.array(vector2)
|
33 |
+
if v1.shape != (3,) or v2.shape != (3,):
|
34 |
+
raise ValueError("Both vectors must be 3-dimensional for cross product.")
|
35 |
+
return np.cross(v1, v2)
|
maths/vectors/vectors_interface.py
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Gradio Interface for Vector operations.
|
3 |
+
"""
|
4 |
+
import gradio as gr
|
5 |
+
import numpy as np
|
6 |
+
import json
|
7 |
+
from typing import Union
|
8 |
+
from maths.vectors.vectors import (
|
9 |
+
vector_add, vector_subtract, vector_dot_product, vector_cross_product
|
10 |
+
)
|
11 |
+
|
12 |
+
def parse_vector(vector_str: str) -> np.ndarray:
|
13 |
+
try:
|
14 |
+
v = json.loads(vector_str)
|
15 |
+
arr = np.array(v, dtype=float)
|
16 |
+
if arr.ndim != 1:
|
17 |
+
raise ValueError("Vector must be 1-dimensional.")
|
18 |
+
if arr.shape[0] == 0:
|
19 |
+
raise ValueError("Vector cannot be empty.")
|
20 |
+
return arr
|
21 |
+
except (json.JSONDecodeError, TypeError, ValueError) as e_json:
|
22 |
+
try:
|
23 |
+
if not vector_str.strip():
|
24 |
+
raise ValueError("Vector input is empty.")
|
25 |
+
arr = np.array([float(x.strip()) for x in vector_str.split(',') if x.strip()], dtype=float)
|
26 |
+
if arr.shape[0] == 0:
|
27 |
+
raise ValueError("Vector cannot be empty after parsing.")
|
28 |
+
return arr
|
29 |
+
except ValueError as e_csv:
|
30 |
+
raise gr.Error(f"Invalid vector format. Use JSON (e.g., [1,2,3]) or comma-separated (e.g., 1,2,3). Error: {e_csv} (Original JSON error: {e_json})")
|
31 |
+
except Exception as e_gen:
|
32 |
+
raise gr.Error(f"General error parsing vector: {e_gen}")
|
33 |
+
|
34 |
+
def format_output(data: Union[np.ndarray, float, str]) -> str:
|
35 |
+
if isinstance(data, np.ndarray):
|
36 |
+
return str(data.tolist())
|
37 |
+
elif isinstance(data, (float, int, str)):
|
38 |
+
return str(data)
|
39 |
+
return "Output type not recognized."
|
40 |
+
|
41 |
+
vector_add_interface = gr.Interface(
|
42 |
+
fn=lambda v1_str, v2_str: format_output(vector_add(parse_vector(v1_str), parse_vector(v2_str))),
|
43 |
+
inputs=[
|
44 |
+
gr.Textbox(label="Vector 1 (JSON or CSV format)", placeholder="e.g., [1,2,3] or 1,2,3"),
|
45 |
+
gr.Textbox(label="Vector 2 (JSON or CSV format)", placeholder="e.g., [4,5,6] or 4,5,6")
|
46 |
+
],
|
47 |
+
outputs=gr.Textbox(label="Resulting Vector"),
|
48 |
+
title="Vector Addition",
|
49 |
+
description="Adds two vectors. Ensure they have the same dimensions."
|
50 |
+
)
|
51 |
+
|
52 |
+
vector_subtract_interface = gr.Interface(
|
53 |
+
fn=lambda v1_str, v2_str: format_output(vector_subtract(parse_vector(v1_str), parse_vector(v2_str))),
|
54 |
+
inputs=[
|
55 |
+
gr.Textbox(label="Vector 1 (Minuend)", placeholder="e.g., [4,5,6]"),
|
56 |
+
gr.Textbox(label="Vector 2 (Subtrahend)", placeholder="e.g., [1,2,3]")
|
57 |
+
],
|
58 |
+
outputs=gr.Textbox(label="Resulting Vector"),
|
59 |
+
title="Vector Subtraction",
|
60 |
+
description="Subtracts the second vector from the first. Ensure they have the same dimensions."
|
61 |
+
)
|
62 |
+
|
63 |
+
vector_dot_product_interface = gr.Interface(
|
64 |
+
fn=lambda v1_str, v2_str: format_output(vector_dot_product(parse_vector(v1_str), parse_vector(v2_str))),
|
65 |
+
inputs=[
|
66 |
+
gr.Textbox(label="Vector 1", placeholder="e.g., [1,2,3]"),
|
67 |
+
gr.Textbox(label="Vector 2", placeholder="e.g., [4,5,6]")
|
68 |
+
],
|
69 |
+
outputs=gr.Textbox(label="Dot Product (Scalar)"),
|
70 |
+
title="Vector Dot Product",
|
71 |
+
description="Calculates the dot product of two vectors. Ensure they have the same dimensions."
|
72 |
+
)
|
73 |
+
|
74 |
+
vector_cross_product_interface = gr.Interface(
|
75 |
+
fn=lambda v1_str, v2_str: format_output(vector_cross_product(parse_vector(v1_str), parse_vector(v2_str))),
|
76 |
+
inputs=[
|
77 |
+
gr.Textbox(label="Vector 1 (3D)", placeholder="e.g., [1,2,3]"),
|
78 |
+
gr.Textbox(label="Vector 2 (3D)", placeholder="e.g., [4,5,6]")
|
79 |
+
],
|
80 |
+
outputs=gr.Textbox(label="Resulting Vector (3D)"),
|
81 |
+
title="Vector Cross Product",
|
82 |
+
description="Calculates the cross product of two 3D vectors."
|
83 |
+
)
|
utils/__init__.py
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
"""
|
2 |
-
Utility functions for general purposes.
|
3 |
-
"""
|
|
|
|
|
|
|
|
utils/text_utils.py
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
"""
|
2 |
-
Utility functions for text processing.
|
3 |
-
"""
|
4 |
-
|
5 |
-
def letter_counter(word, letter):
|
6 |
-
"""Count the occurrences of a specific letter in a word."""
|
7 |
-
return word.lower().count(letter.lower())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
utils/text_utils_interface.py
DELETED
@@ -1,11 +0,0 @@
|
|
1 |
-
import gradio as gr
|
2 |
-
from utils.text_utils import letter_counter
|
3 |
-
|
4 |
-
# Text Utils Tab
|
5 |
-
letter_counter_interface = gr.Interface(
|
6 |
-
fn=letter_counter,
|
7 |
-
inputs=["text", "text"],
|
8 |
-
outputs="number",
|
9 |
-
title="Letter Counter",
|
10 |
-
description="Count how many times a letter appears in a word"
|
11 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|