Skip to content

Commit 9464c7f

Browse files
committed
Document augmented inverse least squares
1 parent e4684e1 commit 9464c7f

3 files changed

Lines changed: 18 additions & 13 deletions

File tree

examples/example01a - static_inverse_solve_MASTU.ipynb

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -387,19 +387,23 @@
387387
"\n",
388388
"During an inverse solve, a minimisation problem involving the responses, changes in coil currents, and constraints, is repeatedly solved:\n",
389389
"\n",
390-
"$$ \\min_{x} \\| A\\vec{x} - \\vec{b}\\|^2 + \\| \\gamma \\vec{x} \\|^2, $$\n",
390+
"$$ \\min_{x} \\| A\\vec{x} - \\vec{b}\\|^2 + \\vec{x}^{T} \\Gamma \\vec{x}, $$\n",
391391
"\n",
392392
"where\n",
393393
"- $A$ is the fixed response matrix (that determines how a change in coil currents $x$, affects constraint values). \n",
394394
"- $\\vec{x} = \\Delta \\vec{I}^c$ is the step change in active coil currents required to match the constraints. \n",
395395
"- $\\vec{b}$ is the vector of constraint values being enforced. \n",
396-
"- $\\gamma > 0$ is the regularisation parameter/vector.\n",
396+
"- $\\Gamma$ is the non-negative diagonal regularisation matrix: a scalar `l2_reg` gives $\\Gamma = \\mathtt{l2\\_reg} I$, while a vector supplies its diagonal entries.\n",
397397
"\n",
398-
"We solve for $\\vec{x}$ using a gradient-based optimiser. \n",
398+
"Without inequality constraints, FreeGSNKE solves the equivalent augmented system\n",
399+
"\n",
400+
"$$ \\min_x \\left\\| \\begin{bmatrix} A \\\\ \\Gamma^{1/2} \\end{bmatrix} \\vec{x} - \\begin{bmatrix} \\vec{b} \\\\ 0 \\end{bmatrix} \\right\\|^2, $$\n",
401+
"\n",
402+
"using a direct least-squares solve. This avoids forming the normal equations $(A^T A + \\Gamma)\\vec{x} = A^T\\vec{b}$. When coil-current or normalised-flux limits are active, the same regularised objective is handled by the constrained quadratic optimiser instead.\n",
399403
"\n",
400404
"[Song et al. (2024)](https://www.mdpi.com/2571-6182/7/4/45) provide a nice overview of the inverse problem.\n",
401405
"\n",
402-
"The coil limits are handled in a slightly different manner because they are box constraints that cannot be encoded in the minimisation problem. Instead, FreeGSNKE adds additional constraints to the solver that bound the solution $\\Delta \\vec{I}^c$. These bounds have a tolerance (slack) which allows the coils to violate their limits, but penalises violations; this allows the coil limits to be violated 'on the path' to a solution that respects the prescribed limits.\n"
406+
"The coil limits are handled in a slightly different manner because they are box constraints that cannot be represented by the unconstrained augmented least-squares system. Instead, FreeGSNKE adds constraints to the quadratic optimiser that bound the solution $\\Delta \\vec{I}^c$. These bounds have a tolerance (slack) which allows the coils to violate their limits, but penalises violations; this allows the coil limits to be violated 'on the path' to a solution that respects the prescribed limits.\n"
403407
]
404408
},
405409
{
@@ -414,7 +418,7 @@
414418
"\n",
415419
"The `verbose=True` option will provide an indication of the progression of the solve. \n",
416420
"\n",
417-
"The `l2_reg` parameter defines the Tikhonov regularisation (i.e. $\\gamma$ in the cell above) used by the optimiser. This can be set as a scalar or as a vector (equal to the number of coil currents being solved for). Larger values force coil currents to stay closer to their original values while lower values will encourage more freedom. This can be useful in particular for vertical control coils (e.g. the P6 coil in MAST-U), in which we don't want the coil current to \"jump around\" during optimisation and cause vertical instability issues. \n",
421+
"The `l2_reg` parameter defines the diagonal of the Tikhonov regularisation matrix $\\Gamma$ in the cell above. It can be set as a scalar or as a vector (equal to the number of coil currents being solved for). Larger values force coil currents to stay closer to their original values while lower values encourage more freedom. This can be useful in particular for vertical control coils (e.g. the P6 coil in MAST-U), in which we don't want the coil current to \"jump around\" during optimisation and cause vertical instability issues. \n",
418422
"\n",
419423
"\n",
420424
"The solver steps are (roughly):\n",

freegsnke/GSstaticsolver.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,14 +1232,15 @@ def optimize_currents(
12321232
Once A is constructed, the Newton step is computed by solving the
12331233
Tikhonov-regularised least-squares problem:
12341234
1235-
min || A ΔI + b0 ||² + ||R ΔI||²
1235+
min || A ΔI + b0 ||² + ΔIᵀ R ΔI
12361236
12371237
where:
12381238
b0 = current constraint residual
12391239
R = regularisation matrix
12401240
1241-
If current or flux limits are active, a quadratic optimisation
1242-
routine is used instead of the closed-form normal equations.
1241+
Without inequality limits, this is solved as an augmented
1242+
least-squares system. If current or flux limits are active, a
1243+
constrained quadratic optimisation routine is used instead.
12431244
12441245
Parameters
12451246
----------

freegsnke/inverse.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828

2929
def _solve_regularized_lstsq(A, b, regularization):
30-
"""Solve a diagonally regularized least-squares problem without normal equations."""
30+
"""Solve ``min ||A x - b||² + xᵀ diag(regularization) x`` in augmented form."""
3131
regularization = np.asarray(regularization)
3232
if regularization.shape != (A.shape[1],):
3333
raise ValueError(
@@ -1213,13 +1213,13 @@ def optimize_currents(
12131213
12141214
This method computes optimal coil current corrections by solving:
12151215
1216-
min_I || A I − b ||² + λ || I ||²
1216+
min_I || A I − b ||² + Iᵀ R I
12171217
12181218
where:
12191219
12201220
A = combined constraint Jacobian matrix
12211221
b = combined constraint residual vector
1222-
λ = Tikhonov (L2) regularisation parameter
1222+
R = diagonal Tikhonov regularisation matrix
12231223
12241224
The optimisation accounts for:
12251225
@@ -1252,10 +1252,10 @@ def optimize_currents(
12521252
Tikhonov regularisation parameter.
12531253
12541254
If float:
1255-
λ I² penalty is applied uniformly.
1255+
R is the scalar value times the identity matrix.
12561256
12571257
If array:
1258-
Allows coil-wise regularisation weighting.
1258+
R contains the supplied coil-wise values on its diagonal.
12591259
12601260
Returns
12611261
-------

0 commit comments

Comments
 (0)