-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhelper_functions.py
More file actions
116 lines (95 loc) · 3.77 KB
/
helper_functions.py
File metadata and controls
116 lines (95 loc) · 3.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
"""Helper functions used by notebooks in this repository."""
import math
import os
from pathlib import Path
import pandas as pd
def resolve_numerics_dll():
"""Return the path to the Numerics .NET DLL.
Resolution order:
1. NUMERICS_DLL environment variable (explicit override)
2. Global NuGet cache: ~/.nuget/packages/rmc.numerics/*/lib/net8.0/Numerics.dll
(populated by `dotnet add package RMC.Numerics`)
3. Local packages folder: ./packages/RMC.Numerics.*/lib/net8.0/Numerics.dll
(populated by `nuget install RMC.Numerics -OutputDirectory packages`)
Raises FileNotFoundError with install instructions if none of these resolve.
"""
env = os.environ.get("NUMERICS_DLL")
if env:
return Path(env)
cache = Path.home() / ".nuget" / "packages" / "rmc.numerics"
if cache.exists():
hits = sorted(cache.glob("*/lib/net8.0/Numerics.dll"), reverse=True)
if hits:
return hits[0]
for search_root in (Path.cwd(), Path.cwd().parent):
local = sorted(
(search_root / "packages").glob("RMC.Numerics.*/lib/net8.0/Numerics.dll"),
reverse=True,
)
if local:
return local[0]
raise FileNotFoundError(
"Numerics DLL not found. Install via one of:\n"
" dotnet add package RMC.Numerics\n"
" nuget install RMC.Numerics -OutputDirectory packages\n"
"Both commands pull the latest published version by default; append\n"
" --version 2.0.1 (dotnet) or -Version 2.0.1 (nuget) to pin.\n"
"Alternatively set the NUMERICS_DLL environment variable to a local build."
)
def convert_to_dotnet_array(python_list):
"""Convert a Python list into a 1D .NET array of doubles.
Requires that the Numerics .NET runtime has already been loaded
(i.e., clr.AddReference has been called).
"""
from System import Array, Double
dotnet_array = Array.CreateInstance(Double, len(python_list))
for i, val in enumerate(python_list):
dotnet_array[i] = float(val)
return dotnet_array
def convert_to_dotnet_2d_array(matrix):
"""Convert a 2D NumPy array into a .NET 2D array of doubles.
Requires that the Numerics .NET runtime has already been loaded
(i.e., clr.AddReference has been called).
"""
from System import Array, Double
rows, cols = matrix.shape
net_array = Array.CreateInstance(Double, rows, cols)
for i in range(rows):
for j in range(cols):
net_array[i, j] = float(matrix[i, j])
return net_array
def create_comparison_table(
numerics_results,
comparison_package,
comparison_results,
parameter_names,
numerics_time=float("nan"),
comparison_time=float("nan"),
):
"""Create a comparison table between Numerics and another package."""
table = []
for i, param_name in enumerate(parameter_names):
pct_diff = (
(numerics_results[i] - comparison_results[i]) / comparison_results[i] * 100
if comparison_results[i] != 0
else 0
)
table.append(
{
"Parameter": param_name,
"Numerics Result": numerics_results[i],
f"{comparison_package} Result": comparison_results[i],
"Difference": f"{pct_diff:.4f}%",
}
)
if not math.isnan(numerics_time) and not math.isnan(comparison_time):
time_diff = (numerics_time - comparison_time) if comparison_time != 0 else 0
table.append(
{
"Parameter": "Runtime (secs)",
"Numerics Result": f"{numerics_time:.4f}",
f"{comparison_package} Result": f"{comparison_time:.4f}",
"Difference": f"{time_diff:.4f}",
}
)
return pd.DataFrame(table)