executable-engineering 0.1.29__tar.gz → 0.1.32__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.
Files changed (20) hide show
  1. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/PKG-INFO +9 -6
  2. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/executable_engineering/__init__.py +5 -1
  3. executable_engineering-0.1.32/executable_engineering/linearsystems_module.py +95 -0
  4. executable_engineering-0.1.32/executable_engineering/numerical_error_module.py +40 -0
  5. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/executable_engineering.egg-info/PKG-INFO +9 -6
  6. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/executable_engineering.egg-info/SOURCES.txt +2 -0
  7. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/executable_engineering.egg-info/requires.txt +8 -4
  8. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/setup.py +6 -6
  9. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/LICENSE +0 -0
  10. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/README.md +0 -0
  11. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/executable_engineering/closedoptimization_module.py +0 -0
  12. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/executable_engineering/closedrootfinder_module.py +0 -0
  13. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/executable_engineering/gradientoptimization_module.py +0 -0
  14. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/executable_engineering/neuralnet_module.py +0 -0
  15. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/executable_engineering/openoptimization_module.py +0 -0
  16. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/executable_engineering/openrootfinder_module.py +0 -0
  17. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/executable_engineering.egg-info/dependency_links.txt +0 -0
  18. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/executable_engineering.egg-info/top_level.txt +0 -0
  19. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/pyproject.toml +0 -0
  20. {executable_engineering-0.1.29 → executable_engineering-0.1.32}/setup.cfg +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: executable_engineering
3
- Version: 0.1.29
4
- Summary: Tools for ENGPHYS 3NM4
3
+ Version: 0.1.32
4
+ Summary: Demonstrative tools for the Executable Engineering textbook
5
5
  Home-page: https://github.com/themintlab/ExecutableEngineering/tree/main/executable_engineering
6
6
  Author: Michael Welland
7
7
  License: MIT
@@ -14,13 +14,15 @@ License-File: LICENSE
14
14
  Requires-Dist: numpy
15
15
  Requires-Dist: matplotlib
16
16
  Requires-Dist: networkx
17
- Requires-Dist: ipywidgets
18
- Requires-Dist: IPython
19
- Requires-Dist: pyppeteer
20
- Requires-Dist: nbconvert
21
17
  Requires-Dist: scipy
22
18
  Requires-Dist: plotly
23
19
  Requires-Dist: pandas
20
+ Provides-Extra: docs
21
+ Requires-Dist: pyppeteer; extra == "docs"
22
+ Requires-Dist: nbconvert; extra == "docs"
23
+ Provides-Extra: jupyter
24
+ Requires-Dist: ipywidgets; extra == "jupyter"
25
+ Requires-Dist: IPython; extra == "jupyter"
24
26
  Dynamic: author
25
27
  Dynamic: classifier
26
28
  Dynamic: description
@@ -28,6 +30,7 @@ Dynamic: description-content-type
28
30
  Dynamic: home-page
29
31
  Dynamic: license
30
32
  Dynamic: license-file
33
+ Dynamic: provides-extra
31
34
  Dynamic: requires-dist
32
35
  Dynamic: requires-python
33
36
  Dynamic: summary
@@ -4,9 +4,11 @@ from .closedrootfinder_module import RootFinderClosed
4
4
  from .closedoptimization_module import OptimizerClosed
5
5
  from .openoptimization_module import OptimizerOpen
6
6
  from .gradientoptimization_module import OptimizerGrad
7
-
7
+ from .numerical_error_module import python_internal_binary, decimal_to_binary
8
+ from .linearsystems_module import visual_solve_2d
8
9
 
9
10
  __all__ = [
11
+ "visual_solve_2d",
10
12
  "init_weights",
11
13
  "tanh",
12
14
  "tanh_derivative",
@@ -29,4 +31,6 @@ __all__ = [
29
31
  "OptimizerClosed",
30
32
  "OptimizerOpen",
31
33
  "OptimizerGrad",
34
+ "python_internal_binary",
35
+ "decimal_to_binary",
32
36
  ]
@@ -0,0 +1,95 @@
1
+ import numpy as np
2
+ import plotly.graph_objects as go
3
+ import plotly.colors as pcolors
4
+
5
+ def visual_solve_2d(A, b, x_range=None, title="Linear System", labels=None):
6
+ """
7
+ Solves and visualizes a 2D linear system Ax = b.
8
+ Plots the lines represented by the rows of A and b, and the solution point.
9
+ Falls back to the pseudoinverse for singular or non-square systems.
10
+
11
+ Args:
12
+ A: (N, 2) array-like of coefficients.
13
+ b: (N,) array-like of constants.
14
+ x_range: Tuple of (xmin, xmax) for plotting. If None, auto-calculated.
15
+ title: Plot title.
16
+ labels: Tuple of (x_label, y_label) for axes.
17
+ """
18
+ if labels is None:
19
+ labels = ("x", "y")
20
+
21
+ A = np.array(A, dtype=float)
22
+ b = np.array(b, dtype=float).flatten()
23
+
24
+ if A.shape[1] != 2:
25
+ raise ValueError("visual_solve_2d only supports 2D systems (A must have 2 columns).")
26
+
27
+ # 1. Solve the system using the pseudoinverse
28
+ # For a square, full-rank matrix, pinv is mathematically identical to the standard inverse.
29
+ # For singular or non-square matrices, it finds the least-squares/minimum-norm solution.
30
+ sol = np.linalg.pinv(A) @ b
31
+
32
+ # Check if the solution is exact AND unique.
33
+ # It is exact if A*x = b. It is unique if the rank of A equals the number of variables (columns).
34
+ is_exact = np.allclose(A @ sol, b)
35
+ is_unique = np.linalg.matrix_rank(A) == A.shape[1]
36
+ is_exact_unique = is_exact and is_unique
37
+
38
+ # 2. Determine plotting range
39
+ if x_range is None:
40
+ center_x = sol[0]
41
+ x_range = (center_x - 10, center_x + 10)
42
+
43
+ x_vals = np.linspace(x_range[0], x_range[1], 100)
44
+
45
+ fig = go.Figure()
46
+
47
+ colors = pcolors.qualitative.Plotly
48
+
49
+ # 3. Plot each line
50
+ for i in range(A.shape[0]):
51
+ a1, a2 = A[i]
52
+ bi = b[i]
53
+
54
+ if np.abs(a2) > 1e-10:
55
+ # y = (bi - a1*x) / a2
56
+ y_vals = (bi - a1 * x_vals) / a2
57
+ line_name = f"{a1:g}{labels[0]} + {a2:g}{labels[1]} = {bi:g}"
58
+ fig.add_trace(go.Scatter(x=x_vals, y=y_vals, mode='lines', name=line_name, line=dict(color=colors[i % len(colors)])))
59
+ else:
60
+ # Vertical line: x = bi / a1
61
+ if np.abs(a1) > 1e-10:
62
+ x_val = bi / a1
63
+ line_name = f"{a1:g}{labels[0]} = {bi:g}"
64
+ fig.add_trace(go.Scatter(x=[x_val, x_val], y=[-100, 100], mode='lines', name=line_name, line=dict(color=colors[i % len(colors)])))
65
+
66
+ # 4. Plot solution point
67
+ if is_unique:
68
+ if is_exact:
69
+ sol_label = "Exact Solution"
70
+ else:
71
+ sol_label = "Best Fit Solution"
72
+
73
+ hover_text = f"{labels[0]}={sol[0]:.4g}, {labels[1]}={sol[1]:.4g}"
74
+ fig.add_trace(go.Scatter(
75
+ x=[sol[0]],
76
+ y=[sol[1]],
77
+ mode='markers',
78
+ marker=dict(color='black', size=12, symbol='star'),
79
+ name=sol_label,
80
+ hoverinfo='text',
81
+ hovertext=hover_text
82
+ ))
83
+
84
+ # Auto-adjust y-range nicely around the solution if not a vertical-only mess
85
+ y_margin = (x_range[1] - x_range[0]) / 2.0
86
+
87
+ fig.update_layout(
88
+ title=title,
89
+ xaxis_title=labels[0],
90
+ yaxis_title=labels[1],
91
+ yaxis=dict(range=[sol[1] - y_margin, sol[1] + y_margin]),
92
+ template="plotly_white"
93
+ )
94
+
95
+ return fig
@@ -0,0 +1,40 @@
1
+ import struct
2
+
3
+ def python_internal_binary(num):
4
+ # Pack the float into 8 bytes using IEEE 754 double-precision ('d')
5
+ # The '!' ensures network byte order (big-endian) so bits read left-to-right
6
+ packed_bytes = struct.pack('!d', float(num))
7
+
8
+ # Unpack those bytes as a single 64-bit unsigned integer ('Q')
9
+ packed_int, = struct.unpack('!Q', packed_bytes)
10
+
11
+ # Format the integer as a 64-bit binary string, padded with leading zeros
12
+ binary_str = f"{packed_int:064b}"
13
+
14
+ # Split into the IEEE 754 components for readability
15
+ sign = binary_str[0] # 1 bit
16
+ exponent = binary_str[1:12] # 11 bits
17
+ fraction = binary_str[12:] # 52 bits
18
+
19
+ return f"{sign} {exponent} {fraction}"
20
+
21
+ def decimal_to_binary(num, precision=20):
22
+ sign = "-" if num < 0 else ""
23
+ num = abs(num)
24
+ int_part = int(num)
25
+ frac = num - int_part
26
+ int_str = bin(int_part)[2:]
27
+
28
+ frac_part = ""
29
+ for _ in range(precision):
30
+ if frac == 0:
31
+ break
32
+ frac *= 2
33
+ bit = int(frac)
34
+ frac_part += str(bit)
35
+ frac -= bit
36
+
37
+ if not frac_part:
38
+ frac_part = "0"
39
+
40
+ return f"{sign}{int_str}.{frac_part}"
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: executable_engineering
3
- Version: 0.1.29
4
- Summary: Tools for ENGPHYS 3NM4
3
+ Version: 0.1.32
4
+ Summary: Demonstrative tools for the Executable Engineering textbook
5
5
  Home-page: https://github.com/themintlab/ExecutableEngineering/tree/main/executable_engineering
6
6
  Author: Michael Welland
7
7
  License: MIT
@@ -14,13 +14,15 @@ License-File: LICENSE
14
14
  Requires-Dist: numpy
15
15
  Requires-Dist: matplotlib
16
16
  Requires-Dist: networkx
17
- Requires-Dist: ipywidgets
18
- Requires-Dist: IPython
19
- Requires-Dist: pyppeteer
20
- Requires-Dist: nbconvert
21
17
  Requires-Dist: scipy
22
18
  Requires-Dist: plotly
23
19
  Requires-Dist: pandas
20
+ Provides-Extra: docs
21
+ Requires-Dist: pyppeteer; extra == "docs"
22
+ Requires-Dist: nbconvert; extra == "docs"
23
+ Provides-Extra: jupyter
24
+ Requires-Dist: ipywidgets; extra == "jupyter"
25
+ Requires-Dist: IPython; extra == "jupyter"
24
26
  Dynamic: author
25
27
  Dynamic: classifier
26
28
  Dynamic: description
@@ -28,6 +30,7 @@ Dynamic: description-content-type
28
30
  Dynamic: home-page
29
31
  Dynamic: license
30
32
  Dynamic: license-file
33
+ Dynamic: provides-extra
31
34
  Dynamic: requires-dist
32
35
  Dynamic: requires-python
33
36
  Dynamic: summary
@@ -6,7 +6,9 @@ executable_engineering/__init__.py
6
6
  executable_engineering/closedoptimization_module.py
7
7
  executable_engineering/closedrootfinder_module.py
8
8
  executable_engineering/gradientoptimization_module.py
9
+ executable_engineering/linearsystems_module.py
9
10
  executable_engineering/neuralnet_module.py
11
+ executable_engineering/numerical_error_module.py
10
12
  executable_engineering/openoptimization_module.py
11
13
  executable_engineering/openrootfinder_module.py
12
14
  executable_engineering.egg-info/PKG-INFO
@@ -1,10 +1,14 @@
1
1
  numpy
2
2
  matplotlib
3
3
  networkx
4
- ipywidgets
5
- IPython
6
- pyppeteer
7
- nbconvert
8
4
  scipy
9
5
  plotly
10
6
  pandas
7
+
8
+ [docs]
9
+ pyppeteer
10
+ nbconvert
11
+
12
+ [jupyter]
13
+ ipywidgets
14
+ IPython
@@ -6,8 +6,8 @@ long_description = (this_directory / "README.md").read_text(encoding="utf-8")
6
6
 
7
7
  setup(
8
8
  name="executable_engineering",
9
- version="0.1.29",
10
- description="Tools for ENGPHYS 3NM4",
9
+ version="0.1.32",
10
+ description="Demonstrative tools for the Executable Engineering textbook",
11
11
  long_description=long_description,
12
12
  long_description_content_type="text/markdown",
13
13
  url="https://github.com/themintlab/ExecutableEngineering/tree/main/executable_engineering",
@@ -18,14 +18,14 @@ setup(
18
18
  "numpy",
19
19
  "matplotlib",
20
20
  "networkx",
21
- "ipywidgets",
22
- "IPython",
23
- "pyppeteer",
24
- "nbconvert",
25
21
  "scipy",
26
22
  "plotly",
27
23
  "pandas",
28
24
  ],
25
+ extras_require={
26
+ "docs": ["pyppeteer", "nbconvert"],
27
+ "jupyter": ["ipywidgets", "IPython"],
28
+ },
29
29
  python_requires=">=3.9",
30
30
  license="MIT",
31
31
  classifiers=[