pyclsp 1.0.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.
- pyclsp-1.0.0/LICENSE +21 -0
- pyclsp-1.0.0/PKG-INFO +259 -0
- pyclsp-1.0.0/README.md +235 -0
- pyclsp-1.0.0/clsp/__init__.py +8 -0
- pyclsp-1.0.0/clsp/clsp.py +232 -0
- pyclsp-1.0.0/clsp/errors.py +22 -0
- pyclsp-1.0.0/clsp/solver.py +274 -0
- pyclsp-1.0.0/clsp/utils.py +314 -0
- pyclsp-1.0.0/pyclsp.egg-info/PKG-INFO +259 -0
- pyclsp-1.0.0/pyclsp.egg-info/SOURCES.txt +13 -0
- pyclsp-1.0.0/pyclsp.egg-info/dependency_links.txt +1 -0
- pyclsp-1.0.0/pyclsp.egg-info/requires.txt +3 -0
- pyclsp-1.0.0/pyclsp.egg-info/top_level.txt +1 -0
- pyclsp-1.0.0/pyproject.toml +43 -0
- pyclsp-1.0.0/setup.cfg +4 -0
pyclsp-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 The Economist
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pyclsp-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyclsp
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Modular Two-Step Convex Optimization Estimator for Ill-Posed Problems
|
|
5
|
+
Author-email: The Economist <29724411+econcz@users.noreply.github.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/econcz/clsp
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/econcz/clsp/issues
|
|
9
|
+
Keywords: estimators,convex-optimization,least-squares,generalized-inverse,regularization
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: numpy>=1.24
|
|
21
|
+
Requires-Dist: scipy>=1.10
|
|
22
|
+
Requires-Dist: cvxpy>=1.3
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# CLSP — Convex Least Squares Programming
|
|
26
|
+
|
|
27
|
+
The **Convex Least Squares Programming (CLSP)** estimator is a two-step method for solving underdetermined, ill-posed, or structurally constrained least-squares problems. It combines pseudoinverse-based estimation with convex-programming correction (e.g., Lasso, Ridge, Elastic Net) to ensure numerical stability, structural coherence, and enhanced interpretability.
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install clsp
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick Example
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
import numpy as np
|
|
39
|
+
from clsp import CLSP
|
|
40
|
+
|
|
41
|
+
# Example allocation problem
|
|
42
|
+
b = np.array([1, 2, 3, 7, 8, 9], dtype=float)
|
|
43
|
+
|
|
44
|
+
# Initialize estimator
|
|
45
|
+
model = CLSP()
|
|
46
|
+
|
|
47
|
+
# Solve the system
|
|
48
|
+
result = model.solve(problem='ap', b=b, m=3, p=3)
|
|
49
|
+
|
|
50
|
+
# Access diagnostics
|
|
51
|
+
print(model.nrmse)
|
|
52
|
+
print(model.ttest())
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## User Reference
|
|
57
|
+
|
|
58
|
+
For comprehensive information on the estimator’s capabilities, advanced configuration options, and implementation details, please refer to the docstrings provided in each of the individual .py source files. These docstrings contain complete descriptions of available methods, their parameters, expected input formats, and output structures.
|
|
59
|
+
|
|
60
|
+
### The `CLSP` Class
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
self.__init__()
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Stores the solution, goodness-of-fit statistics, and ancillary parameters.
|
|
67
|
+
|
|
68
|
+
The class has three core methods: `solve()`, `corr()`, and `ttest()`.
|
|
69
|
+
|
|
70
|
+
**Selected attributes:**
|
|
71
|
+
`self.A` : *np.ndarray*
|
|
72
|
+
design matrix `A` = [`C` | `S`; `M` | `Q`], where `Q` is either a zero matrix or *S_residual*.
|
|
73
|
+
|
|
74
|
+
`self.b` : *np.ndarray*
|
|
75
|
+
vector of the right-hand side.
|
|
76
|
+
|
|
77
|
+
`self.zhat` : *np.ndarray*
|
|
78
|
+
vector of the first-step estimate.
|
|
79
|
+
|
|
80
|
+
`self.r` : *int*
|
|
81
|
+
number of refinement iterations performed in the first step.
|
|
82
|
+
|
|
83
|
+
`self.z` : *np.ndarray*
|
|
84
|
+
vector of the final solution. If the second step is disabled, it equals `self.zhat`.
|
|
85
|
+
|
|
86
|
+
`self.x` : *np.ndarray*
|
|
87
|
+
`m` x `p` matrix or vector containing the variable component of `z`.
|
|
88
|
+
|
|
89
|
+
`self.y` : *np.ndarray*
|
|
90
|
+
vector containing the slack component of `z`.
|
|
91
|
+
|
|
92
|
+
`self.kappaC` : *float*
|
|
93
|
+
spectral κ() for *C_canon*.
|
|
94
|
+
|
|
95
|
+
`self.kappaB` : *float*
|
|
96
|
+
spectral κ() for *B* = *C_canon^+*`A`.
|
|
97
|
+
|
|
98
|
+
`self.kappaA` : *float*
|
|
99
|
+
spectral κ() for `A`.
|
|
100
|
+
|
|
101
|
+
`self.rmsa` : *float*
|
|
102
|
+
total root mean square alignment (RMSA).
|
|
103
|
+
|
|
104
|
+
`self.r2_partial` : *float*
|
|
105
|
+
R^2 for the `M` block in `A`.
|
|
106
|
+
|
|
107
|
+
`self.nrmse` : *float*
|
|
108
|
+
mean square error calculated from `A` and normalized by standard deviation (NRMSE).
|
|
109
|
+
|
|
110
|
+
`self.nrmse_partial` : *float*
|
|
111
|
+
mean square error calculated from the `M` block in `A` and normalized by standard deviation (NRMSE).
|
|
112
|
+
|
|
113
|
+
`self.z_lower` : *np.ndarray*
|
|
114
|
+
lower bound of the diagnostic interval (confidence band) based on κ(`A`).
|
|
115
|
+
|
|
116
|
+
`self.z_upper` : *np.ndarray*
|
|
117
|
+
upper bound of the diagnostic interval (confidence band) based on κ(`A`).
|
|
118
|
+
|
|
119
|
+
### Solver Method: `solve()`
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
self.solve(problem, C, S, M, b, m, p, i, j, zero_diagonal, r, Z, tolerance, iteration_limit, final, alpha)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Solves the Convex Least Squares Programming (CLSP) problem.
|
|
126
|
+
|
|
127
|
+
This method performs a two-step estimation:
|
|
128
|
+
(1) a pseudoinverse-based solution using either the Moore–Penrose or Bott–Duffin inverse, optionally iterated for refinement;
|
|
129
|
+
(2) a convex-programming correction using Lasso, Ridge, or Elastic Net regularization (if enabled).
|
|
130
|
+
|
|
131
|
+
**Parameters:**
|
|
132
|
+
`problem` : *str*, optional
|
|
133
|
+
Structural template for matrix construction. One of:
|
|
134
|
+
- *'ap'* or *'tm'* : allocation (transaction) matrix problem (AP).
|
|
135
|
+
- *'cmls'* or *'rp'* : constrained-model least squares (regression) problem.
|
|
136
|
+
- anything else: general CLSP problem (user-defined `C` and/or `M`).
|
|
137
|
+
|
|
138
|
+
`C`, `S`, `M` : *np.ndarray* or *None*
|
|
139
|
+
Blocks of the design matrix `A` = [`C` | `S`; `M` | `Q`]. If `C` and/or `M` are provided, the matrix `A` is constructed accordingly (please note that for AP, `C` is constructed automatically and known values are specified in `M`).
|
|
140
|
+
|
|
141
|
+
`b` : *np.ndarray* or *None*
|
|
142
|
+
Right-hand side vector. Must have as many rows as `A` (please note that for AP, it should start with row sums). Required.
|
|
143
|
+
|
|
144
|
+
`m`, `p` : *int* or *None*
|
|
145
|
+
Dimensions of X ∈ ℝ^{m×p}, relevant for AP.
|
|
146
|
+
|
|
147
|
+
`i`, `j` : *int*, default = *1*
|
|
148
|
+
Grouping sizes for row and column sum constraints in AP.
|
|
149
|
+
|
|
150
|
+
`zero_diagonal` : *bool*, default = *False*
|
|
151
|
+
If *True*, enforces structural zero diagonals.
|
|
152
|
+
|
|
153
|
+
`r` : *int*, default = *1*
|
|
154
|
+
Number of refinement iterations for the pseudoinverse-based estimator.
|
|
155
|
+
|
|
156
|
+
`Z` : *np.ndarray* or *None*
|
|
157
|
+
A symmetric idempotent matrix (projector) defining the subspace for Bott–Duffin pseudoinversion. If *None*, the identity matrix is used, reducing the Bott–Duffin inverse to the Moore–Penrose case.
|
|
158
|
+
|
|
159
|
+
`tolerance` : *float*, default = *square root of machine epsilon*
|
|
160
|
+
Convergence tolerance for NRMSE change between refinement iterations.
|
|
161
|
+
|
|
162
|
+
`iteration_limit` : *int*, default = *50*
|
|
163
|
+
Maximum number of iterations allowed in the refinement loop.
|
|
164
|
+
|
|
165
|
+
`final` : *bool*, default = *True*
|
|
166
|
+
If *True*, a convex programming problem is solved to refine `zhat`. The resulting solution `z` minimizes a weighted L1/L2 norm around `zhat` subject to `Az` = `b`.
|
|
167
|
+
|
|
168
|
+
`alpha` : *float*, default = *1.0*
|
|
169
|
+
Regularization parameter (weight) in the final convex program:
|
|
170
|
+
- `α = 0`: Lasso (L1 norm)
|
|
171
|
+
- `α = 1`: Tikhonov Regularization/Ridge (L2 norm)
|
|
172
|
+
- `0 < α < 1`: Elastic Net
|
|
173
|
+
|
|
174
|
+
`*args`, `**kwargs` : optional
|
|
175
|
+
CVXPY arguments passed to the CVXPY solver.
|
|
176
|
+
|
|
177
|
+
**Returns:**
|
|
178
|
+
*self*
|
|
179
|
+
|
|
180
|
+
### Correlogram Method: `corr()`
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
self.corr(reset, threshold)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Computes the structural correlogram of the CLSP constraint part.
|
|
187
|
+
|
|
188
|
+
This method performs a row-deletion sensitivity analysis on the canonical constraint matrix `[C` | `S`], denoted as *C_canon*, and evaluates the marginal effect of each constraint row on numerical stability, angular alignment, and estimator sensitivity.
|
|
189
|
+
|
|
190
|
+
For each row `i` in `C_canon`, it computes:
|
|
191
|
+
- The Root Mean Square Alignment (`RMSA_i`) with all other rows `j` ≠ `i`.
|
|
192
|
+
- The change in condition numbers κ(`C`), κ(`B`), and κ(`A`) when row `i` is deleted.
|
|
193
|
+
- The effect on estimation quality: changes in `nrmse`, `zhat`, `z`, and `x` when row `i` is deleted.
|
|
194
|
+
|
|
195
|
+
Additionally, it computes the total `rmsa` statistic across all rows, summarizing the overall angular alignment of *C_canon*.
|
|
196
|
+
|
|
197
|
+
**Parameters:**
|
|
198
|
+
`reset` : *bool*, default = *False*
|
|
199
|
+
If *True*, forces recomputation of all diagnostic values (the results are preserved for eventual reproduction after the method is called).
|
|
200
|
+
|
|
201
|
+
`threshold` : *float*, default = *0*
|
|
202
|
+
If positive, limits the output to constraints with `RMSA_i` ≥ `threshold`.
|
|
203
|
+
|
|
204
|
+
**Returns:**
|
|
205
|
+
*dict* of *list*
|
|
206
|
+
A dictionary containing per-row diagnostic values:
|
|
207
|
+
{
|
|
208
|
+
`"constraint"` : `[1, 2, ..., k]`, # 1-based indices
|
|
209
|
+
`"rmsa_i"` : list of `RMSA_i` values,
|
|
210
|
+
`"rmsa_dkappaC"` : list of Δκ(`C`) after deleting row `i`,
|
|
211
|
+
`"rmsa_dkappaB"` : list of Δκ(`B`) after deleting row `i`,
|
|
212
|
+
`"rmsa_dkappaA"` : list of Δκ(`A`) after deleting row `i`,
|
|
213
|
+
`"rmsa_dnrmse"` : list of Δ`nrmse` after deleting row `i`,
|
|
214
|
+
`"rmsa_dzhat"` : list of Δ`zhat` after deleting row `i`,
|
|
215
|
+
`"rmsa_dz"` : list of Δ`z` after deleting row `i`,
|
|
216
|
+
`"rmsa_dx"` : list of Δ`x` after deleting row `i`,
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
### T-Test Method: `ttest`
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
self.ttest(reset, sample_size, seed, distribution)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Performs a Monte Carlo-based one- or two-sided t-test on the NRMSE statistic.
|
|
226
|
+
|
|
227
|
+
This function simulates right-hand side vectors `b` using a user-defined or default distribution and recomputes the estimator for every new `b`. It
|
|
228
|
+
tests whether the observed NRMSE significantly deviates from the null distribution (under H₀) of simulated NRMSE values. The quality of the test depends on the size of the simulated sample.
|
|
229
|
+
|
|
230
|
+
**Parameters:**
|
|
231
|
+
`reset` : *bool*, default = *False*
|
|
232
|
+
If *True*, forces recomputation of the NRMSE null distribution (under H₀) (the results are preserved for eventual reproduction after the method is called).
|
|
233
|
+
|
|
234
|
+
`sample_size` : *int*, default = *50*
|
|
235
|
+
Size of the Monte Carlo simulated sample under H₀.
|
|
236
|
+
|
|
237
|
+
`seed` : *int* or *None*, optional
|
|
238
|
+
Optional random seed to override the default.
|
|
239
|
+
|
|
240
|
+
`distribution` : *str* or *None*, default = *’normal’*
|
|
241
|
+
Distribution for generating simulated `b` vectors. One of (standard): *'normal'*, *'uniform'*, or *'laplace'*.
|
|
242
|
+
|
|
243
|
+
**Returns:**
|
|
244
|
+
*dict*
|
|
245
|
+
Dictionary with test results and null distribution statistics:
|
|
246
|
+
{
|
|
247
|
+
`'p_one_left'` : P(nrmse ≤ null mean),
|
|
248
|
+
`'p_one_right'` : P(nrmse ≥ null mean),
|
|
249
|
+
`'p_two_sided'` : 2-sided t-test p-value,
|
|
250
|
+
`'nrmse'` : observed value,
|
|
251
|
+
`'mean_null'` : mean of the null distribution (under H₀),
|
|
252
|
+
`'std_null'` : standard deviation of the null distribution (under H₀)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
## Bibliography
|
|
256
|
+
To be added.
|
|
257
|
+
|
|
258
|
+
## License
|
|
259
|
+
MIT License — see the [LICENSE](LICENSE) file.
|
pyclsp-1.0.0/README.md
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# CLSP — Convex Least Squares Programming
|
|
2
|
+
|
|
3
|
+
The **Convex Least Squares Programming (CLSP)** estimator is a two-step method for solving underdetermined, ill-posed, or structurally constrained least-squares problems. It combines pseudoinverse-based estimation with convex-programming correction (e.g., Lasso, Ridge, Elastic Net) to ensure numerical stability, structural coherence, and enhanced interpretability.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install clsp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Example
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
import numpy as np
|
|
15
|
+
from clsp import CLSP
|
|
16
|
+
|
|
17
|
+
# Example allocation problem
|
|
18
|
+
b = np.array([1, 2, 3, 7, 8, 9], dtype=float)
|
|
19
|
+
|
|
20
|
+
# Initialize estimator
|
|
21
|
+
model = CLSP()
|
|
22
|
+
|
|
23
|
+
# Solve the system
|
|
24
|
+
result = model.solve(problem='ap', b=b, m=3, p=3)
|
|
25
|
+
|
|
26
|
+
# Access diagnostics
|
|
27
|
+
print(model.nrmse)
|
|
28
|
+
print(model.ttest())
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## User Reference
|
|
33
|
+
|
|
34
|
+
For comprehensive information on the estimator’s capabilities, advanced configuration options, and implementation details, please refer to the docstrings provided in each of the individual .py source files. These docstrings contain complete descriptions of available methods, their parameters, expected input formats, and output structures.
|
|
35
|
+
|
|
36
|
+
### The `CLSP` Class
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
self.__init__()
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Stores the solution, goodness-of-fit statistics, and ancillary parameters.
|
|
43
|
+
|
|
44
|
+
The class has three core methods: `solve()`, `corr()`, and `ttest()`.
|
|
45
|
+
|
|
46
|
+
**Selected attributes:**
|
|
47
|
+
`self.A` : *np.ndarray*
|
|
48
|
+
design matrix `A` = [`C` | `S`; `M` | `Q`], where `Q` is either a zero matrix or *S_residual*.
|
|
49
|
+
|
|
50
|
+
`self.b` : *np.ndarray*
|
|
51
|
+
vector of the right-hand side.
|
|
52
|
+
|
|
53
|
+
`self.zhat` : *np.ndarray*
|
|
54
|
+
vector of the first-step estimate.
|
|
55
|
+
|
|
56
|
+
`self.r` : *int*
|
|
57
|
+
number of refinement iterations performed in the first step.
|
|
58
|
+
|
|
59
|
+
`self.z` : *np.ndarray*
|
|
60
|
+
vector of the final solution. If the second step is disabled, it equals `self.zhat`.
|
|
61
|
+
|
|
62
|
+
`self.x` : *np.ndarray*
|
|
63
|
+
`m` x `p` matrix or vector containing the variable component of `z`.
|
|
64
|
+
|
|
65
|
+
`self.y` : *np.ndarray*
|
|
66
|
+
vector containing the slack component of `z`.
|
|
67
|
+
|
|
68
|
+
`self.kappaC` : *float*
|
|
69
|
+
spectral κ() for *C_canon*.
|
|
70
|
+
|
|
71
|
+
`self.kappaB` : *float*
|
|
72
|
+
spectral κ() for *B* = *C_canon^+*`A`.
|
|
73
|
+
|
|
74
|
+
`self.kappaA` : *float*
|
|
75
|
+
spectral κ() for `A`.
|
|
76
|
+
|
|
77
|
+
`self.rmsa` : *float*
|
|
78
|
+
total root mean square alignment (RMSA).
|
|
79
|
+
|
|
80
|
+
`self.r2_partial` : *float*
|
|
81
|
+
R^2 for the `M` block in `A`.
|
|
82
|
+
|
|
83
|
+
`self.nrmse` : *float*
|
|
84
|
+
mean square error calculated from `A` and normalized by standard deviation (NRMSE).
|
|
85
|
+
|
|
86
|
+
`self.nrmse_partial` : *float*
|
|
87
|
+
mean square error calculated from the `M` block in `A` and normalized by standard deviation (NRMSE).
|
|
88
|
+
|
|
89
|
+
`self.z_lower` : *np.ndarray*
|
|
90
|
+
lower bound of the diagnostic interval (confidence band) based on κ(`A`).
|
|
91
|
+
|
|
92
|
+
`self.z_upper` : *np.ndarray*
|
|
93
|
+
upper bound of the diagnostic interval (confidence band) based on κ(`A`).
|
|
94
|
+
|
|
95
|
+
### Solver Method: `solve()`
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
self.solve(problem, C, S, M, b, m, p, i, j, zero_diagonal, r, Z, tolerance, iteration_limit, final, alpha)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Solves the Convex Least Squares Programming (CLSP) problem.
|
|
102
|
+
|
|
103
|
+
This method performs a two-step estimation:
|
|
104
|
+
(1) a pseudoinverse-based solution using either the Moore–Penrose or Bott–Duffin inverse, optionally iterated for refinement;
|
|
105
|
+
(2) a convex-programming correction using Lasso, Ridge, or Elastic Net regularization (if enabled).
|
|
106
|
+
|
|
107
|
+
**Parameters:**
|
|
108
|
+
`problem` : *str*, optional
|
|
109
|
+
Structural template for matrix construction. One of:
|
|
110
|
+
- *'ap'* or *'tm'* : allocation (transaction) matrix problem (AP).
|
|
111
|
+
- *'cmls'* or *'rp'* : constrained-model least squares (regression) problem.
|
|
112
|
+
- anything else: general CLSP problem (user-defined `C` and/or `M`).
|
|
113
|
+
|
|
114
|
+
`C`, `S`, `M` : *np.ndarray* or *None*
|
|
115
|
+
Blocks of the design matrix `A` = [`C` | `S`; `M` | `Q`]. If `C` and/or `M` are provided, the matrix `A` is constructed accordingly (please note that for AP, `C` is constructed automatically and known values are specified in `M`).
|
|
116
|
+
|
|
117
|
+
`b` : *np.ndarray* or *None*
|
|
118
|
+
Right-hand side vector. Must have as many rows as `A` (please note that for AP, it should start with row sums). Required.
|
|
119
|
+
|
|
120
|
+
`m`, `p` : *int* or *None*
|
|
121
|
+
Dimensions of X ∈ ℝ^{m×p}, relevant for AP.
|
|
122
|
+
|
|
123
|
+
`i`, `j` : *int*, default = *1*
|
|
124
|
+
Grouping sizes for row and column sum constraints in AP.
|
|
125
|
+
|
|
126
|
+
`zero_diagonal` : *bool*, default = *False*
|
|
127
|
+
If *True*, enforces structural zero diagonals.
|
|
128
|
+
|
|
129
|
+
`r` : *int*, default = *1*
|
|
130
|
+
Number of refinement iterations for the pseudoinverse-based estimator.
|
|
131
|
+
|
|
132
|
+
`Z` : *np.ndarray* or *None*
|
|
133
|
+
A symmetric idempotent matrix (projector) defining the subspace for Bott–Duffin pseudoinversion. If *None*, the identity matrix is used, reducing the Bott–Duffin inverse to the Moore–Penrose case.
|
|
134
|
+
|
|
135
|
+
`tolerance` : *float*, default = *square root of machine epsilon*
|
|
136
|
+
Convergence tolerance for NRMSE change between refinement iterations.
|
|
137
|
+
|
|
138
|
+
`iteration_limit` : *int*, default = *50*
|
|
139
|
+
Maximum number of iterations allowed in the refinement loop.
|
|
140
|
+
|
|
141
|
+
`final` : *bool*, default = *True*
|
|
142
|
+
If *True*, a convex programming problem is solved to refine `zhat`. The resulting solution `z` minimizes a weighted L1/L2 norm around `zhat` subject to `Az` = `b`.
|
|
143
|
+
|
|
144
|
+
`alpha` : *float*, default = *1.0*
|
|
145
|
+
Regularization parameter (weight) in the final convex program:
|
|
146
|
+
- `α = 0`: Lasso (L1 norm)
|
|
147
|
+
- `α = 1`: Tikhonov Regularization/Ridge (L2 norm)
|
|
148
|
+
- `0 < α < 1`: Elastic Net
|
|
149
|
+
|
|
150
|
+
`*args`, `**kwargs` : optional
|
|
151
|
+
CVXPY arguments passed to the CVXPY solver.
|
|
152
|
+
|
|
153
|
+
**Returns:**
|
|
154
|
+
*self*
|
|
155
|
+
|
|
156
|
+
### Correlogram Method: `corr()`
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
self.corr(reset, threshold)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Computes the structural correlogram of the CLSP constraint part.
|
|
163
|
+
|
|
164
|
+
This method performs a row-deletion sensitivity analysis on the canonical constraint matrix `[C` | `S`], denoted as *C_canon*, and evaluates the marginal effect of each constraint row on numerical stability, angular alignment, and estimator sensitivity.
|
|
165
|
+
|
|
166
|
+
For each row `i` in `C_canon`, it computes:
|
|
167
|
+
- The Root Mean Square Alignment (`RMSA_i`) with all other rows `j` ≠ `i`.
|
|
168
|
+
- The change in condition numbers κ(`C`), κ(`B`), and κ(`A`) when row `i` is deleted.
|
|
169
|
+
- The effect on estimation quality: changes in `nrmse`, `zhat`, `z`, and `x` when row `i` is deleted.
|
|
170
|
+
|
|
171
|
+
Additionally, it computes the total `rmsa` statistic across all rows, summarizing the overall angular alignment of *C_canon*.
|
|
172
|
+
|
|
173
|
+
**Parameters:**
|
|
174
|
+
`reset` : *bool*, default = *False*
|
|
175
|
+
If *True*, forces recomputation of all diagnostic values (the results are preserved for eventual reproduction after the method is called).
|
|
176
|
+
|
|
177
|
+
`threshold` : *float*, default = *0*
|
|
178
|
+
If positive, limits the output to constraints with `RMSA_i` ≥ `threshold`.
|
|
179
|
+
|
|
180
|
+
**Returns:**
|
|
181
|
+
*dict* of *list*
|
|
182
|
+
A dictionary containing per-row diagnostic values:
|
|
183
|
+
{
|
|
184
|
+
`"constraint"` : `[1, 2, ..., k]`, # 1-based indices
|
|
185
|
+
`"rmsa_i"` : list of `RMSA_i` values,
|
|
186
|
+
`"rmsa_dkappaC"` : list of Δκ(`C`) after deleting row `i`,
|
|
187
|
+
`"rmsa_dkappaB"` : list of Δκ(`B`) after deleting row `i`,
|
|
188
|
+
`"rmsa_dkappaA"` : list of Δκ(`A`) after deleting row `i`,
|
|
189
|
+
`"rmsa_dnrmse"` : list of Δ`nrmse` after deleting row `i`,
|
|
190
|
+
`"rmsa_dzhat"` : list of Δ`zhat` after deleting row `i`,
|
|
191
|
+
`"rmsa_dz"` : list of Δ`z` after deleting row `i`,
|
|
192
|
+
`"rmsa_dx"` : list of Δ`x` after deleting row `i`,
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
### T-Test Method: `ttest`
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
self.ttest(reset, sample_size, seed, distribution)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Performs a Monte Carlo-based one- or two-sided t-test on the NRMSE statistic.
|
|
202
|
+
|
|
203
|
+
This function simulates right-hand side vectors `b` using a user-defined or default distribution and recomputes the estimator for every new `b`. It
|
|
204
|
+
tests whether the observed NRMSE significantly deviates from the null distribution (under H₀) of simulated NRMSE values. The quality of the test depends on the size of the simulated sample.
|
|
205
|
+
|
|
206
|
+
**Parameters:**
|
|
207
|
+
`reset` : *bool*, default = *False*
|
|
208
|
+
If *True*, forces recomputation of the NRMSE null distribution (under H₀) (the results are preserved for eventual reproduction after the method is called).
|
|
209
|
+
|
|
210
|
+
`sample_size` : *int*, default = *50*
|
|
211
|
+
Size of the Monte Carlo simulated sample under H₀.
|
|
212
|
+
|
|
213
|
+
`seed` : *int* or *None*, optional
|
|
214
|
+
Optional random seed to override the default.
|
|
215
|
+
|
|
216
|
+
`distribution` : *str* or *None*, default = *’normal’*
|
|
217
|
+
Distribution for generating simulated `b` vectors. One of (standard): *'normal'*, *'uniform'*, or *'laplace'*.
|
|
218
|
+
|
|
219
|
+
**Returns:**
|
|
220
|
+
*dict*
|
|
221
|
+
Dictionary with test results and null distribution statistics:
|
|
222
|
+
{
|
|
223
|
+
`'p_one_left'` : P(nrmse ≤ null mean),
|
|
224
|
+
`'p_one_right'` : P(nrmse ≥ null mean),
|
|
225
|
+
`'p_two_sided'` : 2-sided t-test p-value,
|
|
226
|
+
`'nrmse'` : observed value,
|
|
227
|
+
`'mean_null'` : mean of the null distribution (under H₀),
|
|
228
|
+
`'std_null'` : standard deviation of the null distribution (under H₀)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
## Bibliography
|
|
232
|
+
To be added.
|
|
233
|
+
|
|
234
|
+
## License
|
|
235
|
+
MIT License — see the [LICENSE](LICENSE) file.
|