math-pathlib 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- math_pathlib-0.1.0/PKG-INFO +5 -0
- math_pathlib-0.1.0/README.md +38 -0
- math_pathlib-0.1.0/math_pathlib.egg-info/PKG-INFO +5 -0
- math_pathlib-0.1.0/math_pathlib.egg-info/SOURCES.txt +20 -0
- math_pathlib-0.1.0/math_pathlib.egg-info/dependency_links.txt +1 -0
- math_pathlib-0.1.0/math_pathlib.egg-info/top_level.txt +1 -0
- math_pathlib-0.1.0/matplotlib_pyplot/__init__.py +4 -0
- math_pathlib-0.1.0/matplotlib_pyplot/logic1/1_RFL/P_1_Model_MDP_Components.txt +11 -0
- math_pathlib-0.1.0/matplotlib_pyplot/logic1/1_RFL/P_2_Compare_Bandit_Exploration.txt +16 -0
- math_pathlib-0.1.0/matplotlib_pyplot/logic1/1_RFL/P_3_Implement_TD0_Learning.txt +17 -0
- math_pathlib-0.1.0/matplotlib_pyplot/logic1/1_RFL/P_4_Plot_Policy_Iteration_Convergence.txt +16 -0
- math_pathlib-0.1.0/matplotlib_pyplot/logic1/1_RFL/P_5_Compare_Policy_Value_Iteration.txt +23 -0
- math_pathlib-0.1.0/matplotlib_pyplot/logic1/1_RFL/P_6_Implement_SARSA_Control.txt +17 -0
- math_pathlib-0.1.0/matplotlib_pyplot/logic1/1_RFL/P_7_Compare_On_vs_Off_Policy.txt +22 -0
- math_pathlib-0.1.0/matplotlib_pyplot/logic1/1_RFL/P_8_Implement_First_Visit_Monte_Carlo.txt +24 -0
- math_pathlib-0.1.0/matplotlib_pyplot/logic1/1_RFL/menu.py +60 -0
- math_pathlib-0.1.0/matplotlib_pyplot/logic1/__init__.py +0 -0
- math_pathlib-0.1.0/matplotlib_pyplot/logic1/category_menu.py +55 -0
- math_pathlib-0.1.0/matplotlib_pyplot/logic1/menu.py +63 -0
- math_pathlib-0.1.0/matplotlib_pyplot/menu.py +59 -0
- math_pathlib-0.1.0/pyproject.toml +18 -0
- math_pathlib-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# matplotlib-pyplot
|
|
2
|
+
|
|
3
|
+
Educational and practical Python learning resources.
|
|
4
|
+
|
|
5
|
+
## Current Contents
|
|
6
|
+
|
|
7
|
+
### Logic 1
|
|
8
|
+
|
|
9
|
+
- 1_RFL — Reinforcement Learning
|
|
10
|
+
- 2_NLP — reserved for future content
|
|
11
|
+
- 3_CV — reserved for future content
|
|
12
|
+
|
|
13
|
+
### Reinforcement Learning
|
|
14
|
+
|
|
15
|
+
The current release contains 8 TXT-based learning resources covering topics such as:
|
|
16
|
+
|
|
17
|
+
- MDP components
|
|
18
|
+
- Bandit exploration
|
|
19
|
+
- TD(0) learning
|
|
20
|
+
- Policy iteration
|
|
21
|
+
- Value iteration
|
|
22
|
+
- SARSA
|
|
23
|
+
- On-policy vs Off-policy methods
|
|
24
|
+
- First-Visit Monte Carlo
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
The package provides a menu-driven interface for navigating the learning resources.
|
|
29
|
+
|
|
30
|
+
## Development Status
|
|
31
|
+
|
|
32
|
+
Version 0.1.0
|
|
33
|
+
|
|
34
|
+
This is an initial release. NLP content will be added in a future update.
|
|
35
|
+
|
|
36
|
+
## Python Requirement
|
|
37
|
+
|
|
38
|
+
Python 3.13 or newer.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
math_pathlib.egg-info/PKG-INFO
|
|
4
|
+
math_pathlib.egg-info/SOURCES.txt
|
|
5
|
+
math_pathlib.egg-info/dependency_links.txt
|
|
6
|
+
math_pathlib.egg-info/top_level.txt
|
|
7
|
+
matplotlib_pyplot/__init__.py
|
|
8
|
+
matplotlib_pyplot/menu.py
|
|
9
|
+
matplotlib_pyplot/logic1/__init__.py
|
|
10
|
+
matplotlib_pyplot/logic1/category_menu.py
|
|
11
|
+
matplotlib_pyplot/logic1/menu.py
|
|
12
|
+
matplotlib_pyplot/logic1/1_RFL/P_1_Model_MDP_Components.txt
|
|
13
|
+
matplotlib_pyplot/logic1/1_RFL/P_2_Compare_Bandit_Exploration.txt
|
|
14
|
+
matplotlib_pyplot/logic1/1_RFL/P_3_Implement_TD0_Learning.txt
|
|
15
|
+
matplotlib_pyplot/logic1/1_RFL/P_4_Plot_Policy_Iteration_Convergence.txt
|
|
16
|
+
matplotlib_pyplot/logic1/1_RFL/P_5_Compare_Policy_Value_Iteration.txt
|
|
17
|
+
matplotlib_pyplot/logic1/1_RFL/P_6_Implement_SARSA_Control.txt
|
|
18
|
+
matplotlib_pyplot/logic1/1_RFL/P_7_Compare_On_vs_Off_Policy.txt
|
|
19
|
+
matplotlib_pyplot/logic1/1_RFL/P_8_Implement_First_Visit_Monte_Carlo.txt
|
|
20
|
+
matplotlib_pyplot/logic1/1_RFL/menu.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
matplotlib_pyplot
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import numpy as np, pandas as pd, matplotlib.pyplot as plt
|
|
2
|
+
|
|
3
|
+
P = np.array([[0.7, 0.3], [0.4, 0.6]])
|
|
4
|
+
V = np.array([1.0, 0.0])
|
|
5
|
+
traj = [V @ np.linalg.matrix_power(P, t) for t in range(20)]
|
|
6
|
+
df = pd.DataFrame(traj, columns=["State A", "State B"])
|
|
7
|
+
|
|
8
|
+
df.plot(title="MDP State Transition Trajectory")
|
|
9
|
+
plt.xlabel("Time Step")
|
|
10
|
+
plt.ylabel("Probability")
|
|
11
|
+
plt.show()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
|
|
5
|
+
def bandit(mode, K=5, N=1000):
|
|
6
|
+
q_true, Q, N_a = np.random.randn(K), np.zeros(K), np.zeros(K)
|
|
7
|
+
for t in range(1, N + 1):
|
|
8
|
+
bonus = np.sqrt(2 * np.log(t) / np.maximum(N_a, 1e-9))
|
|
9
|
+
a = np.argmax(Q + bonus) if mode == "ucb" else (np.random.randint(K) if np.random.rand() < 0.1 else np.argmax(Q))
|
|
10
|
+
r = q_true[a] + np.random.randn()
|
|
11
|
+
N_a[a] += 1
|
|
12
|
+
Q[a] += (r - Q[a]) / N_a[a]
|
|
13
|
+
yield r
|
|
14
|
+
|
|
15
|
+
pd.DataFrame({"UCB": bandit("ucb"), "Eps-Greedy": bandit("eps")}).expanding().mean().plot(title="Bandit Exploration")
|
|
16
|
+
plt.show()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
|
|
5
|
+
V, g, a, V_true = np.zeros(5), 0.9, 0.1, 0.9 ** np.arange(3, -1, -1)
|
|
6
|
+
errs = []
|
|
7
|
+
|
|
8
|
+
for _ in range(300):
|
|
9
|
+
s = 0
|
|
10
|
+
while s < 4:
|
|
11
|
+
sn, r = s + 1, float(s == 3)
|
|
12
|
+
V[s] += a * (r + g * V[sn] - V[s])
|
|
13
|
+
s = sn
|
|
14
|
+
errs.append(np.sqrt(np.mean((V[:4] - V_true) ** 2)))
|
|
15
|
+
|
|
16
|
+
pd.Series(errs).plot(title="TD(0) RMSE Convergence", xlabel="Episode", ylabel="RMSE")
|
|
17
|
+
plt.show()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
|
|
5
|
+
S, A, g = 5, 2, 0.9
|
|
6
|
+
P, R = np.random.dirichlet(np.ones(S), size=(S, A)), np.random.randn(S, A)
|
|
7
|
+
pi, history = np.zeros(S, dtype=int), []
|
|
8
|
+
|
|
9
|
+
for _ in range(10):
|
|
10
|
+
V = np.linalg.solve(np.eye(S) - g * P[np.arange(S), pi], R[np.arange(S), pi])
|
|
11
|
+
Q = np.column_stack([R[:, a] + g * P[:, a] @ V for a in range(A)])
|
|
12
|
+
pi = np.argmax(Q, axis=1)
|
|
13
|
+
history.append(V.mean())
|
|
14
|
+
|
|
15
|
+
pd.Series(history).plot(title="Policy Iteration Value Convergence", xlabel="Iteration", ylabel="Mean V")
|
|
16
|
+
plt.show()
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
|
|
5
|
+
S, A, g = 5, 2, 0.9
|
|
6
|
+
P, R = np.random.dirichlet(np.ones(S), size=(S, A)), np.random.randn(S, A)
|
|
7
|
+
|
|
8
|
+
def solve(pi):
|
|
9
|
+
V, pol = np.zeros(S), np.arange(S) % A
|
|
10
|
+
for _ in range(12):
|
|
11
|
+
Q = np.column_stack([R[:, a] + g * P[:, a] @ V for a in range(A)])
|
|
12
|
+
pol = np.argmax(Q, axis=1)
|
|
13
|
+
V = np.linalg.solve(
|
|
14
|
+
np.eye(S) - g * P[np.arange(S), pol],
|
|
15
|
+
R[np.arange(S), pol]
|
|
16
|
+
) if pi else Q.max(axis=1)
|
|
17
|
+
yield V.mean()
|
|
18
|
+
|
|
19
|
+
pd.DataFrame({
|
|
20
|
+
"Policy Iteration": solve(True),
|
|
21
|
+
"Value Iteration": solve(False)
|
|
22
|
+
}).plot(title="PI vs VI Convergence")
|
|
23
|
+
plt.show()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
|
|
5
|
+
def sarsa(episodes=300, Q=np.zeros((5, 2))):
|
|
6
|
+
pi = lambda s: np.random.randint(2) if np.random.rand() < 0.1 else np.argmax(Q[s])
|
|
7
|
+
for _ in range(episodes):
|
|
8
|
+
s, ep_r, a = 0, 0, pi(0)
|
|
9
|
+
while s < 4:
|
|
10
|
+
sn, r = min(4, max(0, s + (1 if a == 1 else -1))), (1.0 if s == 3 and a == 1 else -0.1)
|
|
11
|
+
an = pi(sn)
|
|
12
|
+
Q[s, a] += 0.1 * (r + 0.9 * Q[sn, an] - Q[s, a])
|
|
13
|
+
s, a, ep_r = sn, an, ep_r + r
|
|
14
|
+
yield ep_r
|
|
15
|
+
|
|
16
|
+
pd.Series(sarsa()).rolling(20).mean().plot(title="SARSA Control Learning Curve")
|
|
17
|
+
plt.show()
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
|
|
5
|
+
def run(off_policy, Q=np.zeros((5, 2))):
|
|
6
|
+
pi = lambda s: np.random.randint(2) if np.random.rand() < 0.2 else np.argmax(Q[s])
|
|
7
|
+
for _ in range(300):
|
|
8
|
+
s, ep_r = 0, 0
|
|
9
|
+
while s < 4:
|
|
10
|
+
a = pi(s)
|
|
11
|
+
sn = min(4, max(0, s + (1 if a == 1 else -1)))
|
|
12
|
+
r = 1.0 if s == 3 and a == 1 else -0.1
|
|
13
|
+
target = Q[sn].max() if off_policy else Q[sn, pi(sn)]
|
|
14
|
+
Q[s, a] += 0.1 * (r + 0.9 * target - Q[s, a])
|
|
15
|
+
s, ep_r = sn, ep_r + r
|
|
16
|
+
yield ep_r
|
|
17
|
+
|
|
18
|
+
pd.DataFrame({
|
|
19
|
+
"Q-Learning": run(True),
|
|
20
|
+
"SARSA": run(False)
|
|
21
|
+
}).rolling(20).mean().plot(title="SARSA vs Q-Learning")
|
|
22
|
+
plt.show()
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
|
|
5
|
+
V, returns = np.zeros(5), [[] for _ in range(5)]
|
|
6
|
+
|
|
7
|
+
for _ in range(300):
|
|
8
|
+
s, episode = 0, []
|
|
9
|
+
while s < 4:
|
|
10
|
+
sn, r = s + 1, float(s == 3)
|
|
11
|
+
episode.append((s, r))
|
|
12
|
+
s = sn
|
|
13
|
+
|
|
14
|
+
G = 0
|
|
15
|
+
for state, reward in reversed(episode):
|
|
16
|
+
G = reward + 0.9 * G
|
|
17
|
+
if not any(x[0] == state for x in episode[:episode.index((state, reward))]):
|
|
18
|
+
returns[state].append(G)
|
|
19
|
+
V[state] = np.mean(returns[state])
|
|
20
|
+
|
|
21
|
+
pd.Series(V).plot(kind="bar", title="First-Visit Monte Carlo State Values")
|
|
22
|
+
plt.xlabel("State")
|
|
23
|
+
plt.ylabel("Value")
|
|
24
|
+
plt.show()
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def discover_files():
|
|
5
|
+
"""Discover all TXT files inside the RFL directory."""
|
|
6
|
+
rfl_path = Path(__file__).resolve().parent
|
|
7
|
+
|
|
8
|
+
return sorted(
|
|
9
|
+
rfl_path.glob("*.txt"),
|
|
10
|
+
key=lambda path: path.name
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def display_file(file_path):
|
|
15
|
+
"""Display the complete contents of a selected TXT file."""
|
|
16
|
+
|
|
17
|
+
print("\n========================================")
|
|
18
|
+
print(file_path.name)
|
|
19
|
+
print("========================================\n")
|
|
20
|
+
|
|
21
|
+
content = file_path.read_text(encoding="utf-8")
|
|
22
|
+
|
|
23
|
+
print(content)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def run():
|
|
27
|
+
"""Display and handle the RFL file menu."""
|
|
28
|
+
|
|
29
|
+
while True:
|
|
30
|
+
files = discover_files()
|
|
31
|
+
|
|
32
|
+
print("\n========================================")
|
|
33
|
+
print("1_RFL")
|
|
34
|
+
print()
|
|
35
|
+
|
|
36
|
+
for index, file_path in enumerate(files, start=1):
|
|
37
|
+
print(f"{index}. {file_path.stem}")
|
|
38
|
+
|
|
39
|
+
print(f"{len(files) + 1}. Back")
|
|
40
|
+
print(" E. Exit")
|
|
41
|
+
|
|
42
|
+
choice = input("\nEnter option: ").strip().lower()
|
|
43
|
+
|
|
44
|
+
if choice in {"e", "exit"}:
|
|
45
|
+
print("Exiting matplotlib_pyplot.")
|
|
46
|
+
return
|
|
47
|
+
|
|
48
|
+
if choice.isdigit():
|
|
49
|
+
option = int(choice)
|
|
50
|
+
|
|
51
|
+
if 1 <= option <= len(files):
|
|
52
|
+
display_file(files[option - 1])
|
|
53
|
+
|
|
54
|
+
input("\nPress Enter to return to 1_RFL...")
|
|
55
|
+
continue
|
|
56
|
+
|
|
57
|
+
if option == len(files) + 1:
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
print("Invalid option. Please try again.")
|
|
File without changes
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def run_category(category_path):
|
|
5
|
+
"""Display TXT files inside a category directory."""
|
|
6
|
+
|
|
7
|
+
category_path = Path(category_path)
|
|
8
|
+
|
|
9
|
+
while True:
|
|
10
|
+
files = sorted(
|
|
11
|
+
category_path.glob("*.txt"),
|
|
12
|
+
key=lambda path: path.name
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
print("\n========================================")
|
|
16
|
+
print(category_path.name)
|
|
17
|
+
print()
|
|
18
|
+
|
|
19
|
+
if files:
|
|
20
|
+
for index, file_path in enumerate(files, start=1):
|
|
21
|
+
print(f"{index}. {file_path.stem}")
|
|
22
|
+
else:
|
|
23
|
+
print("No TXT files found.")
|
|
24
|
+
|
|
25
|
+
print(f"{len(files) + 1}. Back")
|
|
26
|
+
print(" E. Exit")
|
|
27
|
+
|
|
28
|
+
choice = input("\nEnter option: ").strip().lower()
|
|
29
|
+
|
|
30
|
+
if choice in {"e", "exit"}:
|
|
31
|
+
return "exit"
|
|
32
|
+
|
|
33
|
+
if choice.isdigit():
|
|
34
|
+
option = int(choice)
|
|
35
|
+
|
|
36
|
+
if 1 <= option <= len(files):
|
|
37
|
+
selected_file = files[option - 1]
|
|
38
|
+
|
|
39
|
+
print("\n========================================")
|
|
40
|
+
print(selected_file.name)
|
|
41
|
+
print("========================================\n")
|
|
42
|
+
|
|
43
|
+
print(
|
|
44
|
+
selected_file.read_text(
|
|
45
|
+
encoding="utf-8"
|
|
46
|
+
)
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
input("\nPress Enter to return...")
|
|
50
|
+
continue
|
|
51
|
+
|
|
52
|
+
if option == len(files) + 1:
|
|
53
|
+
return "back"
|
|
54
|
+
|
|
55
|
+
print("Invalid option. Please try again.")
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from .category_menu import run_category
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def discover_categories():
|
|
7
|
+
"""Discover numbered category directories inside logic1."""
|
|
8
|
+
|
|
9
|
+
logic_path = Path(__file__).resolve().parent
|
|
10
|
+
|
|
11
|
+
categories = []
|
|
12
|
+
|
|
13
|
+
for path in logic_path.iterdir():
|
|
14
|
+
if (
|
|
15
|
+
path.is_dir()
|
|
16
|
+
and "_" in path.name
|
|
17
|
+
and path.name.split("_", 1)[0].isdigit()
|
|
18
|
+
):
|
|
19
|
+
categories.append(path)
|
|
20
|
+
|
|
21
|
+
return sorted(
|
|
22
|
+
categories,
|
|
23
|
+
key=lambda path: int(path.name.split("_", 1)[0])
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def run():
|
|
28
|
+
"""Display and handle the logic1 category menu."""
|
|
29
|
+
|
|
30
|
+
while True:
|
|
31
|
+
categories = discover_categories()
|
|
32
|
+
|
|
33
|
+
print("\n========================================")
|
|
34
|
+
print("LOGIC1")
|
|
35
|
+
print()
|
|
36
|
+
|
|
37
|
+
for index, category in enumerate(categories, start=1):
|
|
38
|
+
print(f"{index}. {category.name}")
|
|
39
|
+
|
|
40
|
+
print(f"{len(categories) + 1}. Back")
|
|
41
|
+
print(" E. Exit")
|
|
42
|
+
|
|
43
|
+
choice = input("\nEnter option: ").strip().lower()
|
|
44
|
+
|
|
45
|
+
if choice in {"e", "exit"}:
|
|
46
|
+
print("Exiting matplotlib_pyplot.")
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
if choice.isdigit():
|
|
50
|
+
option = int(choice)
|
|
51
|
+
|
|
52
|
+
if 1 <= option <= len(categories):
|
|
53
|
+
result = run_category(categories[option - 1])
|
|
54
|
+
|
|
55
|
+
if result == "exit":
|
|
56
|
+
return
|
|
57
|
+
|
|
58
|
+
continue
|
|
59
|
+
|
|
60
|
+
if option == len(categories) + 1:
|
|
61
|
+
return
|
|
62
|
+
|
|
63
|
+
print("Invalid option. Please try again.")
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import importlib
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def discover_logic_modules():
|
|
6
|
+
"""Discover logic directories inside the main package."""
|
|
7
|
+
package_path = Path(__file__).resolve().parent
|
|
8
|
+
|
|
9
|
+
logic_modules = []
|
|
10
|
+
|
|
11
|
+
for path in package_path.iterdir():
|
|
12
|
+
if (
|
|
13
|
+
path.is_dir()
|
|
14
|
+
and path.name.startswith("logic")
|
|
15
|
+
and path.name[5:].isdigit()
|
|
16
|
+
):
|
|
17
|
+
logic_modules.append(path.name)
|
|
18
|
+
|
|
19
|
+
return sorted(
|
|
20
|
+
logic_modules,
|
|
21
|
+
key=lambda name: int(name[5:])
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def run():
|
|
26
|
+
"""Display and handle the main logic menu."""
|
|
27
|
+
|
|
28
|
+
while True:
|
|
29
|
+
logic_modules = discover_logic_modules()
|
|
30
|
+
|
|
31
|
+
print("\n========================================")
|
|
32
|
+
print("LOGIC MENU")
|
|
33
|
+
print()
|
|
34
|
+
|
|
35
|
+
for index, logic_name in enumerate(logic_modules, start=1):
|
|
36
|
+
print(f"{index}. {logic_name}")
|
|
37
|
+
|
|
38
|
+
print(" E. Exit")
|
|
39
|
+
|
|
40
|
+
choice = input("\nEnter option: ").strip().lower()
|
|
41
|
+
|
|
42
|
+
if choice in {"e", "exit"}:
|
|
43
|
+
print("Exiting matplotlib_pyplot.")
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
if choice.isdigit():
|
|
47
|
+
option = int(choice)
|
|
48
|
+
|
|
49
|
+
if 1 <= option <= len(logic_modules):
|
|
50
|
+
selected_logic = logic_modules[option - 1]
|
|
51
|
+
|
|
52
|
+
module = importlib.import_module(
|
|
53
|
+
f"matplotlib_pyplot.{selected_logic}.menu"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
module.run()
|
|
57
|
+
continue
|
|
58
|
+
|
|
59
|
+
print("Invalid option. Please try again.")
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "math_pathlib"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Educational and practical Python learning resources"
|
|
9
|
+
requires-python = ">=3.13"
|
|
10
|
+
dependencies = []
|
|
11
|
+
|
|
12
|
+
[tool.setuptools.packages.find]
|
|
13
|
+
include = ["matplotlib_pyplot*"]
|
|
14
|
+
|
|
15
|
+
[tool.setuptools.package-data]
|
|
16
|
+
matplotlib_pyplot = [
|
|
17
|
+
"logic1/1_RFL/*.txt"
|
|
18
|
+
]
|