pytmpinv


Namepytmpinv JSON
Version 1.2.0 PyPI version JSON
download
home_pageNone
SummaryTabular Matrix Problems via Pseudoinverse Estimation
upload_time2025-09-19 05:40:08
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseNone
keywords tabular-matrix-problems convex-optimization least-squares generalized-inverse regularization
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Tabular Matrix Problems via Pseudoinverse Estimation

The **Tabular Matrix Problems via Pseudoinverse Estimation (TMPinv)** is a two-stage estimation method that reformulates structured table-based systems — such as allocation problems, transaction matrices, and input–output tables — as structured least-squares problems. Based on the [Convex Least Squares Programming (CLSP)](https://pypi.org/project/pyclsp/ "Convex Least Squares Programming") framework, TMPinv solves systems with row and column constraints, block structure, and optionally reduced dimensionality by (1) constructing a canonical constraint form and applying a pseudoinverse-based projection, followed by (2) a convex-programming refinement stage to improve fit, coherence, and regularization (e.g., via Lasso, Ridge, or Elastic Net). All calculations are performed in numpy.float64 precision.

## Installation

```bash
pip install tmpinv
```

## Quick Example

```python
import numpy             as     np
from   tmpinv            import tmpinv
import matplotlib.pyplot as     plt

# AP (TM), based on a symmetric input-output table, with 10% of known values

seed   = 123456789
rng    = np.random.default_rng(seed)

# sample (dataset)
m, p   = 20, 20                                              # matrix dimensions (m x p)
X_true = np.abs(rng.normal(size=(m, p)))                     # symmetric non-negative X_true
X_true = (X_true + X_true.T) / 2.0
idx    = rng.choice(m * p, size=max(1, int(0.1 * (m * p))),  # random numbers from
                    replace=False)                           # [0,(m * p) - 1], 10% of total

# model
M      = np.eye(m * p)[idx,:]                                # unit matrix
b_row  = X_true.sum(axis=1)                                  # row sums (length m)
b_col  = X_true.sum(axis=0)                                  # column sums (length p)
b_val  = X_true.reshape(-1, 1)[idx]                          # column vector
bounds = (0, None)                                           # non-negativity
result = tmpinv(
             M=M, b_row=b_row, b_col=b_col, b_val=b_val,
             m=m, p=p, bounds=bounds, symmetric=True,
             r=1,                                            # a solution without refinement
             alpha=1.0                                       # a unique MNBLUE estimator
         )

# helpers
def fmt(v):
    v = float(v)
    return f"{v:.4e}" if abs(v) >= 1e6 or (v != 0 and abs(v) < 1e-4) else f"{v:.6f}"

# results
print("true X:")
print(np.round(np.asarray(X_true), 4))
print("X_hat:")
print(np.round(result.x,           4))

print("\nNumerical stability:")
print("  kappaC :", fmt(result.model.kappaC))
print("  kappaB :", fmt(result.model.kappaB))
print("  kappaA :", fmt(result.model.kappaA))
corr = result.model.corr()
plt.figure(figsize=(8, 4))
plt.grid(True, linestyle="--", alpha=0.6)
plt.bar(range(len(corr["rmsa_i"])), corr["rmsa_i"])
plt.xlabel("Constraint index")
plt.ylabel("dRMSA (row deletion effect)")
plt.title(f"CLSP Correlogram (Total RMSA = {result.model.rmsa:.2f})")
plt.tight_layout()
plt.show()

print("\nGoodness-of-fit:")
x_true = X_true.flatten()
x_hat  = result.x.flatten()
ss_res = np.sum((x_true - x_hat) ** 2)
ss_tot = np.sum((x_true - np.mean(x_true)) ** 2)
print("  R2_user_defined      :", fmt(1 - ss_res / ss_tot))
print("  NRMSE                :", fmt(result.model.nrmse))
print("  Diagnostic band (min):", fmt(np.min(result.model.x_lower)))
print("  Diagnostic band (max):", fmt(np.max(result.model.x_upper)))
print("  Monte Carlo t-test:")
for kw, val in result.model.ttest(sample_size=30,                    # NRMSE sample
                                  seed=seed, distribution="normal",  # seed and distribution
                                  partial=True).items():
    print(f"    {kw}: {float(val):.6f}")

# AP (TM), based on a trade matrix, with a zero diagonal and 20% of known values

seed   = 123456789
rng    = np.random.default_rng(seed)

# sample (dataset)
m, p   = 40, 40                                              # matrix dimensions (m x p)
X_true = np.abs(rng.normal(size=(m, p)))                     # non-negative X_true
X_true = X_true * (1 - np.eye(m, p))                         # zero diagonal
idx    = rng.choice(m * p, size=max(1, int(0.2 * (m * p))),  # random numbers from
                    replace=False)                           # [0,(m * p) - 1], 20% of total

# model
M      = np.eye(m * p)[idx,:]                                # unit matrix
b_row  = X_true.sum(axis=1)                                  # row sums (length m)
b_col  = X_true.sum(axis=0)                                  # column sums (length p)
b_val  = X_true.reshape(-1, 1)[idx]                          # column vector
bounds = (0, None)                                           # non-negativity
result = tmpinv(
             M=M, b_row=b_row, b_col=b_col, b_val=b_val,
             m=m, p=p, zero_diagonal=True, reduced=(20,20),  # reduced models of (20, 20)
             bounds=bounds,
             r=1,                                            # a solution without refinement
             alpha=1.0                                       # a unique MNBLUE estimator
         )

# helpers
def fmt(v):
    v = float(v)
    return f"{v:.4e}" if abs(v) >= 1e6 or (v != 0 and abs(v) < 1e-4) else f"{v:.6f}"

# results
print("true X:")
print(np.round(np.asarray(X_true), 4))
print("X_hat:")
print(np.round(result.x,           4))

print("\nNumerical stability (min-max across models):")
kappaC = np.array([CLSP.kappaC for CLSP in result.model])
kappaB = np.array([CLSP.kappaB for CLSP in result.model])
kappaA = np.array([CLSP.kappaA for CLSP in result.model])
print("  kappaC :", fmt(np.min(kappaC)), "-", fmt(np.max(kappaC)))
print("  kappaB :", fmt(np.min(kappaB)), "-", fmt(np.max(kappaB)))
print("  kappaA :", fmt(np.min(kappaA)), "-", fmt(np.max(kappaA)))

print("\nGoodness-of-fit (min-max across models):")
x_true = X_true.flatten()
x_hat  = result.x.flatten()
mask   = np.isfinite(x_true) & np.isfinite(x_hat)
if mask.any():
    ss_res = np.sum((x_true[mask] - x_hat[mask])**2)
    ss_tot = np.sum((x_true[mask] - np.mean(x_true[mask]))**2)
nrmse      = np.array(      [CLSP.nrmse                         for CLSP in result.model])
x_lower    = np.concatenate([np.array(CLSP.x_lower).reshape(-1) for CLSP in result.model])
x_upper    = np.concatenate([np.array(CLSP.x_upper).reshape(-1) for CLSP in result.model])
print("  R2_user_defined      :", fmt(1 - ss_res / ss_tot                             ))
print("  NRMSE                :", fmt(np.min(nrmse)),      "-", fmt(np.max(nrmse)     ))
print("  Diagnostic band (min):", fmt(np.min(x_lower)),    "-", fmt(np.max(x_lower)   ))
print("  Diagnostic band (max):", fmt(np.min(x_upper)),    "-", fmt(np.max(x_upper)   ))
print("  Monte Carlo t-test:")
ttests     = [CLSP.ttest(sample_size=30, seed=seed,
                         distribution="normal")                 for CLSP in result.model]
keys       = ttests[0].keys()
for kw in keys:
    val    = np.array([t[kw] for t in ttests], dtype=float)
    print(f"    {kw}: {fmt(np.min(val))} - {fmt(np.max(val))}")
```

## User Reference

For comprehensive information on the estimator's capabilities, advanced configuration options, and implementation details, please refer to the [pyclsp module](https://pypi.org/project/pyclsp/ "Convex Least Squares Programming"), on which TMPinv is based.

**TMPINV Parameters:**

`S` : *array_like* of shape *(m + p, m + p)*, optional
A diagonal sign slack (surplus) matrix with entries in *{0, ±1}*.
-   *0* enforces equality (== `b_row` or `b_col`),
-  *1* enforces a lower-than-or-equal (≤) condition,
- *–1* enforces a greater-than-or-equal (≥) condition.

The first `m` diagonal entries correspond to row constraints, and the remaining `p` to column constraints. Please note that, in the reduced model, `S` is ignored: slack behavior is derived implicitly from block-wise marginal totals.

`M` : *array_like* of shape *(k, m * p)*, optional
A model matrix with entries in *{0, 1}*. Each row defines a linear restriction on the flattened solution matrix. The corresponding right-hand side values must be provided in `b_val`. This block is used to encode known cell values. Please note that, in the reduced model, `M` must be a unique row subset of an identity matrix (i.e., diagonal-only). Arbitrary or non-diagonal model matrices cannot be mapped to reduced blocks, making the model infeasible.

`b_row` : *array_like* of shape *(m,)*
Right-hand side vector of row totals. Please note that both `b_row` and `b_col` must be provided.

`b_col` : *array_like* of shape *(p,)*
Right-hand side vector of column totals. Please note that both `b_row` and `b_col` must be provided.

`b_val` : *array_like* of shape *(k,)*
Right-hand side vector of known cell values.

`i` : *int*, default = *1*
Number of row groups.

`j` : *int*, default = *1*
Number of column groups.

`zero_diagonal` : *bool*, default = *False*
If *True*, enforces the zero diagonal.

`reduced` : *tuple* of *(int, int)*, optional
Dimensions of the reduced problem. If specified, the problem is estimated as a set of reduced problems constructed from contiguous submatrices of the original table. For example, `reduced` = *(6, 6)* implies *5×5* data blocks with *1* slack row and *1* slack column each (edge blocks may be smaller).

`symmetric` : *bool*, default = *False*
If True, enforces symmetry of the estimated solution matrix as: x = 0.5 * (x + x.T)
Applies to TMPinvResult.x only. For TMPinvResult.model symmetry, add explicit symmetry constraints to M in a full-model solve instead of using this flag.

`bounds` : *sequence* of *(low, high)*, optional
Bounds on cell values. If a single tuple *(low, high)* is given, it is applied to all `m` * `p` cells. Example: *(0, None)*.

`replace_value` : *float* or *None*, default = *np.nan*
Final replacement value for any cell in the solution matrix that violates the specified bounds by more than the given tolerance.

`tolerance` : *float*, default = *square root of machine epsilon*
Convergence tolerance for bounds.

`iteration_limit` : *int*, default = *50*
Maximum number of iterations allowed in the refinement loop.

**CLSP Parameters:**

`r` : *int*, default = *1*
Number of refinement iterations for the pseudoinverse-based estimator.

`Z` : *np.ndarray* or *None*
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.

`final` : *bool*, default = *True*
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`.

`alpha` : *float*, *list[float]* or *None*, default = *None*
    Regularization parameter (weight) in the final convex program:
    - `α = 0`: Lasso (L1 norm)
    - `α = 1`: Tikhonov Regularization/Ridge (L2 norm)
    - `0 < α < 1`: Elastic Net
    If a scalar float is provided, that value is used after clipping to [0, 1].
    If a list/iterable of floats is provided, each candidate is evaluated via a full solve, and the α with the smallest NRMSE is selected.
    If None, α is chosen, based on an error rule: α = min(1.0, NRMSE_{α = 0} / (NRMSE_{α = 0} + NRMSE_{α = 1} + tolerance))

`*args`, `**kwargs` : optional
CVXPY arguments passed to the CVXPY solver.

**Returns:**
*TMPinvResult*

`TMPinvResult.full` : *bool*
Indicates if this result comes from the full (non-reduced) model.

`TMPinvResult.model` : *CLSP* or *list* of *CLSP*
A single CLSP object in the full model, or a list of CLSP objects for each reduced block in the reduced model.

`TMPinvResult.x` : *np.ndarray*
Final estimated solution matrix of shape *(m, p)*.

## Bibliography

To be added.

## License

MIT License — see the [LICENSE](LICENSE) file.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "pytmpinv",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "tabular-matrix-problems, convex-optimization, least-squares, generalized-inverse, regularization",
    "author": null,
    "author_email": "The Economist <29724411+econcz@users.noreply.github.com>",
    "download_url": "https://files.pythonhosted.org/packages/70/bd/59278986d461966ea6595751df6fce18422ef0305ce7356d1bc7e0358577/pytmpinv-1.2.0.tar.gz",
    "platform": null,
    "description": "# Tabular Matrix Problems via Pseudoinverse Estimation\n\nThe **Tabular Matrix Problems via Pseudoinverse Estimation (TMPinv)** is a two-stage estimation method that reformulates structured table-based systems \u2014 such as allocation problems, transaction matrices, and input\u2013output tables \u2014 as structured least-squares problems. Based on the [Convex Least Squares Programming (CLSP)](https://pypi.org/project/pyclsp/ \"Convex Least Squares Programming\") framework, TMPinv solves systems with row and column constraints, block structure, and optionally reduced dimensionality by (1) constructing a canonical constraint form and applying a pseudoinverse-based projection, followed by (2) a convex-programming refinement stage to improve fit, coherence, and regularization (e.g., via Lasso, Ridge, or Elastic Net). All calculations are performed in numpy.float64 precision.\n\n## Installation\n\n```bash\npip install tmpinv\n```\n\n## Quick Example\n\n```python\nimport numpy             as     np\nfrom   tmpinv            import tmpinv\nimport matplotlib.pyplot as     plt\n\n# AP (TM), based on a symmetric input-output table, with 10% of known values\n\nseed   = 123456789\nrng    = np.random.default_rng(seed)\n\n# sample (dataset)\nm, p   = 20, 20                                              # matrix dimensions (m x p)\nX_true = np.abs(rng.normal(size=(m, p)))                     # symmetric non-negative X_true\nX_true = (X_true + X_true.T) / 2.0\nidx    = rng.choice(m * p, size=max(1, int(0.1 * (m * p))),  # random numbers from\n                    replace=False)                           # [0,(m * p) - 1], 10% of total\n\n# model\nM      = np.eye(m * p)[idx,:]                                # unit matrix\nb_row  = X_true.sum(axis=1)                                  # row sums (length m)\nb_col  = X_true.sum(axis=0)                                  # column sums (length p)\nb_val  = X_true.reshape(-1, 1)[idx]                          # column vector\nbounds = (0, None)                                           # non-negativity\nresult = tmpinv(\n             M=M, b_row=b_row, b_col=b_col, b_val=b_val,\n             m=m, p=p, bounds=bounds, symmetric=True,\n             r=1,                                            # a solution without refinement\n             alpha=1.0                                       # a unique MNBLUE estimator\n         )\n\n# helpers\ndef fmt(v):\n    v = float(v)\n    return f\"{v:.4e}\" if abs(v) >= 1e6 or (v != 0 and abs(v) < 1e-4) else f\"{v:.6f}\"\n\n# results\nprint(\"true X:\")\nprint(np.round(np.asarray(X_true), 4))\nprint(\"X_hat:\")\nprint(np.round(result.x,           4))\n\nprint(\"\\nNumerical stability:\")\nprint(\"  kappaC :\", fmt(result.model.kappaC))\nprint(\"  kappaB :\", fmt(result.model.kappaB))\nprint(\"  kappaA :\", fmt(result.model.kappaA))\ncorr = result.model.corr()\nplt.figure(figsize=(8, 4))\nplt.grid(True, linestyle=\"--\", alpha=0.6)\nplt.bar(range(len(corr[\"rmsa_i\"])), corr[\"rmsa_i\"])\nplt.xlabel(\"Constraint index\")\nplt.ylabel(\"dRMSA (row deletion effect)\")\nplt.title(f\"CLSP Correlogram (Total RMSA = {result.model.rmsa:.2f})\")\nplt.tight_layout()\nplt.show()\n\nprint(\"\\nGoodness-of-fit:\")\nx_true = X_true.flatten()\nx_hat  = result.x.flatten()\nss_res = np.sum((x_true - x_hat) ** 2)\nss_tot = np.sum((x_true - np.mean(x_true)) ** 2)\nprint(\"  R2_user_defined      :\", fmt(1 - ss_res / ss_tot))\nprint(\"  NRMSE                :\", fmt(result.model.nrmse))\nprint(\"  Diagnostic band (min):\", fmt(np.min(result.model.x_lower)))\nprint(\"  Diagnostic band (max):\", fmt(np.max(result.model.x_upper)))\nprint(\"  Monte Carlo t-test:\")\nfor kw, val in result.model.ttest(sample_size=30,                    # NRMSE sample\n                                  seed=seed, distribution=\"normal\",  # seed and distribution\n                                  partial=True).items():\n    print(f\"    {kw}: {float(val):.6f}\")\n\n# AP (TM), based on a trade matrix, with a zero diagonal and 20% of known values\n\nseed   = 123456789\nrng    = np.random.default_rng(seed)\n\n# sample (dataset)\nm, p   = 40, 40                                              # matrix dimensions (m x p)\nX_true = np.abs(rng.normal(size=(m, p)))                     # non-negative X_true\nX_true = X_true * (1 - np.eye(m, p))                         # zero diagonal\nidx    = rng.choice(m * p, size=max(1, int(0.2 * (m * p))),  # random numbers from\n                    replace=False)                           # [0,(m * p) - 1], 20% of total\n\n# model\nM      = np.eye(m * p)[idx,:]                                # unit matrix\nb_row  = X_true.sum(axis=1)                                  # row sums (length m)\nb_col  = X_true.sum(axis=0)                                  # column sums (length p)\nb_val  = X_true.reshape(-1, 1)[idx]                          # column vector\nbounds = (0, None)                                           # non-negativity\nresult = tmpinv(\n             M=M, b_row=b_row, b_col=b_col, b_val=b_val,\n             m=m, p=p, zero_diagonal=True, reduced=(20,20),  # reduced models of (20, 20)\n             bounds=bounds,\n             r=1,                                            # a solution without refinement\n             alpha=1.0                                       # a unique MNBLUE estimator\n         )\n\n# helpers\ndef fmt(v):\n    v = float(v)\n    return f\"{v:.4e}\" if abs(v) >= 1e6 or (v != 0 and abs(v) < 1e-4) else f\"{v:.6f}\"\n\n# results\nprint(\"true X:\")\nprint(np.round(np.asarray(X_true), 4))\nprint(\"X_hat:\")\nprint(np.round(result.x,           4))\n\nprint(\"\\nNumerical stability (min-max across models):\")\nkappaC = np.array([CLSP.kappaC for CLSP in result.model])\nkappaB = np.array([CLSP.kappaB for CLSP in result.model])\nkappaA = np.array([CLSP.kappaA for CLSP in result.model])\nprint(\"  kappaC :\", fmt(np.min(kappaC)), \"-\", fmt(np.max(kappaC)))\nprint(\"  kappaB :\", fmt(np.min(kappaB)), \"-\", fmt(np.max(kappaB)))\nprint(\"  kappaA :\", fmt(np.min(kappaA)), \"-\", fmt(np.max(kappaA)))\n\nprint(\"\\nGoodness-of-fit (min-max across models):\")\nx_true = X_true.flatten()\nx_hat  = result.x.flatten()\nmask   = np.isfinite(x_true) & np.isfinite(x_hat)\nif mask.any():\n    ss_res = np.sum((x_true[mask] - x_hat[mask])**2)\n    ss_tot = np.sum((x_true[mask] - np.mean(x_true[mask]))**2)\nnrmse      = np.array(      [CLSP.nrmse                         for CLSP in result.model])\nx_lower    = np.concatenate([np.array(CLSP.x_lower).reshape(-1) for CLSP in result.model])\nx_upper    = np.concatenate([np.array(CLSP.x_upper).reshape(-1) for CLSP in result.model])\nprint(\"  R2_user_defined      :\", fmt(1 - ss_res / ss_tot                             ))\nprint(\"  NRMSE                :\", fmt(np.min(nrmse)),      \"-\", fmt(np.max(nrmse)     ))\nprint(\"  Diagnostic band (min):\", fmt(np.min(x_lower)),    \"-\", fmt(np.max(x_lower)   ))\nprint(\"  Diagnostic band (max):\", fmt(np.min(x_upper)),    \"-\", fmt(np.max(x_upper)   ))\nprint(\"  Monte Carlo t-test:\")\nttests     = [CLSP.ttest(sample_size=30, seed=seed,\n                         distribution=\"normal\")                 for CLSP in result.model]\nkeys       = ttests[0].keys()\nfor kw in keys:\n    val    = np.array([t[kw] for t in ttests], dtype=float)\n    print(f\"    {kw}: {fmt(np.min(val))} - {fmt(np.max(val))}\")\n```\n\n## User Reference\n\nFor comprehensive information on the estimator's capabilities, advanced configuration options, and implementation details, please refer to the [pyclsp module](https://pypi.org/project/pyclsp/ \"Convex Least Squares Programming\"), on which TMPinv is based.\n\n**TMPINV Parameters:**\n\n`S` : *array_like* of shape *(m + p, m + p)*, optional\nA diagonal sign slack (surplus) matrix with entries in *{0, \u00b11}*.\n-   *0* enforces equality (== `b_row` or `b_col`),\n-  *1* enforces a lower-than-or-equal (\u2264) condition,\n- *\u20131* enforces a greater-than-or-equal (\u2265) condition.\n\nThe first `m` diagonal entries correspond to row constraints, and the remaining `p` to column constraints. Please note that, in the reduced model, `S` is ignored: slack behavior is derived implicitly from block-wise marginal totals.\n\n`M` : *array_like* of shape *(k, m * p)*, optional\nA model matrix with entries in *{0, 1}*. Each row defines a linear restriction on the flattened solution matrix. The corresponding right-hand side values must be provided in `b_val`. This block is used to encode known cell values. Please note that, in the reduced model, `M` must be a unique row subset of an identity matrix (i.e., diagonal-only). Arbitrary or non-diagonal model matrices cannot be mapped to reduced blocks, making the model infeasible.\n\n`b_row` : *array_like* of shape *(m,)*\nRight-hand side vector of row totals. Please note that both `b_row` and `b_col` must be provided.\n\n`b_col` : *array_like* of shape *(p,)*\nRight-hand side vector of column totals. Please note that both `b_row` and `b_col` must be provided.\n\n`b_val` : *array_like* of shape *(k,)*\nRight-hand side vector of known cell values.\n\n`i` : *int*, default = *1*\nNumber of row groups.\n\n`j` : *int*, default = *1*\nNumber of column groups.\n\n`zero_diagonal` : *bool*, default = *False*\nIf *True*, enforces the zero diagonal.\n\n`reduced` : *tuple* of *(int, int)*, optional\nDimensions of the reduced problem. If specified, the problem is estimated as a set of reduced problems constructed from contiguous submatrices of the original table. For example, `reduced` = *(6, 6)* implies *5\u00d75* data blocks with *1* slack row and *1* slack column each (edge blocks may be smaller).\n\n`symmetric` : *bool*, default = *False*\nIf True, enforces symmetry of the estimated solution matrix as: x = 0.5 * (x + x.T)\nApplies to TMPinvResult.x only. For TMPinvResult.model symmetry, add explicit symmetry constraints to M in a full-model solve instead of using this flag.\n\n`bounds` : *sequence* of *(low, high)*, optional\nBounds on cell values. If a single tuple *(low, high)* is given, it is applied to all `m` * `p` cells. Example: *(0, None)*.\n\n`replace_value` : *float* or *None*, default = *np.nan*\nFinal replacement value for any cell in the solution matrix that violates the specified bounds by more than the given tolerance.\n\n`tolerance` : *float*, default = *square root of machine epsilon*\nConvergence tolerance for bounds.\n\n`iteration_limit` : *int*, default = *50*\nMaximum number of iterations allowed in the refinement loop.\n\n**CLSP Parameters:**\n\n`r` : *int*, default = *1*\nNumber of refinement iterations for the pseudoinverse-based estimator.\n\n`Z` : *np.ndarray* or *None*\nA symmetric idempotent matrix (projector) defining the subspace for Bott\u2013Duffin pseudoinversion. If *None*, the identity matrix is used, reducing the Bott\u2013Duffin inverse to the Moore\u2013Penrose case.\n\n`final` : *bool*, default = *True*\nIf *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`.\n\n`alpha` : *float*, *list[float]* or *None*, default = *None*\n    Regularization parameter (weight) in the final convex program:\n    - `\u03b1 = 0`: Lasso (L1 norm)\n    - `\u03b1 = 1`: Tikhonov Regularization/Ridge (L2 norm)\n    - `0 < \u03b1 < 1`: Elastic Net\n    If a scalar float is provided, that value is used after clipping to [0, 1].\n    If a list/iterable of floats is provided, each candidate is evaluated via a full solve, and the \u03b1 with the smallest NRMSE is selected.\n    If None, \u03b1 is chosen, based on an error rule: \u03b1 = min(1.0, NRMSE_{\u03b1 = 0} / (NRMSE_{\u03b1 = 0} + NRMSE_{\u03b1 = 1} + tolerance))\n\n`*args`, `**kwargs` : optional\nCVXPY arguments passed to the CVXPY solver.\n\n**Returns:**\n*TMPinvResult*\n\n`TMPinvResult.full` : *bool*\nIndicates if this result comes from the full (non-reduced) model.\n\n`TMPinvResult.model` : *CLSP* or *list* of *CLSP*\nA single CLSP object in the full model, or a list of CLSP objects for each reduced block in the reduced model.\n\n`TMPinvResult.x` : *np.ndarray*\nFinal estimated solution matrix of shape *(m, p)*.\n\n## Bibliography\n\nTo be added.\n\n## License\n\nMIT License \u2014 see the [LICENSE](LICENSE) file.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Tabular Matrix Problems via Pseudoinverse Estimation",
    "version": "1.2.0",
    "project_urls": {
        "Bug Tracker": "https://github.com/econcz/pytmpinv/issues",
        "Homepage": "https://github.com/econcz/pytmpinv"
    },
    "split_keywords": [
        "tabular-matrix-problems",
        " convex-optimization",
        " least-squares",
        " generalized-inverse",
        " regularization"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d0ece592a2643f44c5dc6e75ab13baea0bb0cfec5c664efccdef6626e326c09d",
                "md5": "9038a492d84f964fafccaa81424e5081",
                "sha256": "ec1d82f4dfdec0e11b8ca25625f4899ffdf5672b71fcd0e5d1085cfa832f8054"
            },
            "downloads": -1,
            "filename": "pytmpinv-1.2.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "9038a492d84f964fafccaa81424e5081",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 11176,
            "upload_time": "2025-09-19T05:40:07",
            "upload_time_iso_8601": "2025-09-19T05:40:07.390781Z",
            "url": "https://files.pythonhosted.org/packages/d0/ec/e592a2643f44c5dc6e75ab13baea0bb0cfec5c664efccdef6626e326c09d/pytmpinv-1.2.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "70bd59278986d461966ea6595751df6fce18422ef0305ce7356d1bc7e0358577",
                "md5": "31d2837e0f4b593aaec4bd250b7344e6",
                "sha256": "9ce676893e1d2d7f49d2093a756caa583aa7a9db071996acae239fd1256ed5f5"
            },
            "downloads": -1,
            "filename": "pytmpinv-1.2.0.tar.gz",
            "has_sig": false,
            "md5_digest": "31d2837e0f4b593aaec4bd250b7344e6",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 10643,
            "upload_time": "2025-09-19T05:40:08",
            "upload_time_iso_8601": "2025-09-19T05:40:08.785268Z",
            "url": "https://files.pythonhosted.org/packages/70/bd/59278986d461966ea6595751df6fce18422ef0305ce7356d1bc7e0358577/pytmpinv-1.2.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-19 05:40:08",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "econcz",
    "github_project": "pytmpinv",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "pytmpinv"
}
        
Elapsed time: 2.46026s