From cb16f4a79e40c6cc69478c0a484b121e673e3ac5 Mon Sep 17 00:00:00 2001 From: lukelowry Date: Fri, 5 Jun 2026 07:00:52 -0500 Subject: [PATCH 1/6] Use stable sigmoid --- GridKit/CommonMath.hpp | 21 +++++++++++---------- GridKit/CommonMath.md | 4 ++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/GridKit/CommonMath.hpp b/GridKit/CommonMath.hpp index 9bb3a5c3c..05dd9bd1b 100644 --- a/GridKit/CommonMath.hpp +++ b/GridKit/CommonMath.hpp @@ -10,12 +10,15 @@ namespace GridKit { namespace Math { + template + inline constexpr RealT MU = 240.0; + /** * @brief Scaled sigmoid activation function * * @note The sigmoid constant (mu) value is chosen to balance accuracy * and finite derivatives. Large values more closely approximate a step - * function, but lead to inf or NaN derivatives. + * function, but can make the transition numerically stiff. * * @tparam ScalarT - scalar data type * @@ -25,9 +28,8 @@ namespace GridKit template __attribute__((always_inline)) inline ScalarT sigmoid(const ScalarT x) { - using RealT = typename GridKit::ScalarTraits::RealT; - static constexpr RealT MU = 240.0; - return ONE / (ONE + std::exp(-MU * x)); + using RealT = typename GridKit::ScalarTraits::RealT; + return HALF * (ONE + std::tanh(HALF * MU * x)); } /** @@ -44,12 +46,11 @@ namespace GridKit template __attribute__((always_inline)) inline ScalarT ramp(const ScalarT x) { - using RealT = typename GridKit::ScalarTraits::RealT; - static constexpr RealT MU = 240.0; + using RealT = typename GridKit::ScalarTraits::RealT; - ScalarT z = MU * x; - ScalarT a = std::abs(z); - return (HALF * (z + a) + std::log1p(std::exp(-a))) / MU; + RealT mu = MU; + ScalarT a = std::abs(mu * x); + return HALF * (x + a / mu) + std::log1p(std::exp(-a)) / mu; } /** @@ -237,7 +238,7 @@ namespace GridKit __attribute__((always_inline)) inline ScalarT dsigmoid(const ScalarT x) { using RealT = typename GridKit::ScalarTraits::RealT; - return FOUR * sigmoid(x) * (ONE - sigmoid(x)); + return MU * sigmoid(x) * (ONE - sigmoid(x)); } /** diff --git a/GridKit/CommonMath.md b/GridKit/CommonMath.md index a654487a2..3f0035dc1 100644 --- a/GridKit/CommonMath.md +++ b/GridKit/CommonMath.md @@ -32,8 +32,8 @@ q(x) &= x^2\,\sigma(x) ```math \begin{aligned} -\sigma(x) &= \dfrac{1}{1+e^{-\mu x}} \\ -\rho(x) &= \dfrac{(\mu x+\lvert\mu x\rvert)/2+\log(1+e^{-\lvert\mu x\rvert})}{\mu} \\ +\sigma(x) &= \dfrac{1}{2}\left(1+\tanh\left(\dfrac{\mu x}{2}\right)\right) \\ +\rho(x) &= \dfrac{x+\lvert x\rvert}{2}+\dfrac{\ln(1+e^{-\mu\lvert x\rvert})}{\mu} \\ q(x) &= x^2\,\sigma(x) \end{aligned} ``` From 0bc6614476ef2b2336b1ddb66d6efef73615dd50 Mon Sep 17 00:00:00 2001 From: lukelowry Date: Fri, 5 Jun 2026 07:15:06 -0500 Subject: [PATCH 2/6] Remove WILL_FAIL flag --- examples/PhasorDynamics/Medium/NewEngland/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/PhasorDynamics/Medium/NewEngland/CMakeLists.txt b/examples/PhasorDynamics/Medium/NewEngland/CMakeLists.txt index 5c22b422b..bd9b0fb2c 100644 --- a/examples/PhasorDynamics/Medium/NewEngland/CMakeLists.txt +++ b/examples/PhasorDynamics/Medium/NewEngland/CMakeLists.txt @@ -10,4 +10,3 @@ add_test( NAME newengland_ca COMMAND ContingencyAnalysis newengland.solver.json WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) -set_tests_properties(newengland_ca PROPERTIES WILL_FAIL TRUE) From d8ca7dd344cbf4aa07bfe1046a4d1d325cb4061f Mon Sep 17 00:00:00 2001 From: lukelowry Date: Fri, 5 Jun 2026 07:37:36 -0500 Subject: [PATCH 3/6] Adjust test to use MU from CommonMath --- tests/UnitTests/Math/SmoothnessIndicatorTests.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/UnitTests/Math/SmoothnessIndicatorTests.hpp b/tests/UnitTests/Math/SmoothnessIndicatorTests.hpp index 41f6d2ca1..1ce2d8b1f 100644 --- a/tests/UnitTests/Math/SmoothnessIndicatorTests.hpp +++ b/tests/UnitTests/Math/SmoothnessIndicatorTests.hpp @@ -183,7 +183,7 @@ namespace GridKit const ScalarT tol = scalar(kSmoothTolerance); const ScalarT roundoff = scalar(kRoundoffTolerance); - const ScalarT tau = scalar(1.0 / 240.0); + const ScalarT tau = scalar(1.0 / Math::MU); const ScalarT at_zero = tau * std::log(scalar(2.0)); const ScalarT far_above = scalar(4.0); const ScalarT far_below = scalar(-4.0); @@ -251,7 +251,7 @@ namespace GridKit < scalar(kRoundoffTolerance)); const ScalarT point = scalar(0.25); - const ScalarT bias = std::log(scalar(2.0)) / scalar(240.0); + const ScalarT bias = std::log(scalar(2.0)) / scalar(Math::MU); success *= (std::abs(Math::max(point, point) - (point + bias)) < scalar(kRoundoffTolerance)); From d3084f3e96ab3fb2b2b3294accae1f0d5230d16c Mon Sep 17 00:00:00 2001 From: lukelowry Date: Sun, 7 Jun 2026 07:17:24 -0500 Subject: [PATCH 4/6] Add plots and adjust CommonMath header --- GridKit/CommonMath.hpp | 24 +-- GridKit/CommonMath.md | 272 ++++++++++++++------------ docs/Figures/CommonMath/above.svg | 31 +++ docs/Figures/CommonMath/below.svg | 31 +++ docs/Figures/CommonMath/clamp.svg | 32 +++ docs/Figures/CommonMath/deadband1.svg | 32 +++ docs/Figures/CommonMath/deadband2.svg | 29 +++ docs/Figures/CommonMath/inside.svg | 33 ++++ docs/Figures/CommonMath/linseg.svg | 31 +++ docs/Figures/CommonMath/max.svg | 30 +++ docs/Figures/CommonMath/min.svg | 30 +++ docs/Figures/CommonMath/outside.svg | 33 ++++ docs/Figures/CommonMath/qramp.svg | 33 ++++ docs/Figures/CommonMath/ramp.svg | 32 +++ docs/Figures/CommonMath/sigmoid.svg | 33 ++++ docs/Figures/CommonMath/slew.svg | 34 ++++ 16 files changed, 602 insertions(+), 138 deletions(-) create mode 100644 docs/Figures/CommonMath/above.svg create mode 100644 docs/Figures/CommonMath/below.svg create mode 100644 docs/Figures/CommonMath/clamp.svg create mode 100644 docs/Figures/CommonMath/deadband1.svg create mode 100644 docs/Figures/CommonMath/deadband2.svg create mode 100644 docs/Figures/CommonMath/inside.svg create mode 100644 docs/Figures/CommonMath/linseg.svg create mode 100644 docs/Figures/CommonMath/max.svg create mode 100644 docs/Figures/CommonMath/min.svg create mode 100644 docs/Figures/CommonMath/outside.svg create mode 100644 docs/Figures/CommonMath/qramp.svg create mode 100644 docs/Figures/CommonMath/ramp.svg create mode 100644 docs/Figures/CommonMath/sigmoid.svg create mode 100644 docs/Figures/CommonMath/slew.svg diff --git a/GridKit/CommonMath.hpp b/GridKit/CommonMath.hpp index 05dd9bd1b..e4a7ec87f 100644 --- a/GridKit/CommonMath.hpp +++ b/GridKit/CommonMath.hpp @@ -10,6 +10,14 @@ namespace GridKit { namespace Math { + /** + * @brief Smoothing scale shared by CommonMath primitives + * + * Used by @ref sigmoid, @ref ramp, and functions composed from them to set + * the width of smooth transitions. + * + * @tparam RealT - real data type + */ template inline constexpr RealT MU = 240.0; @@ -225,22 +233,6 @@ namespace GridKit return height / (upper - lower) * (ramp(x - lower) - ramp(x - upper)); } - /** - * @brief Derivative of the scaled sigmoid activation function - * (i.e., approximation to the delta dirac function) - * - * @tparam ScalarT - scalar data type - * - * @param[in] x - expected to be of order 1 - * @return value of the sigmoid function - */ - template - __attribute__((always_inline)) inline ScalarT dsigmoid(const ScalarT x) - { - using RealT = typename GridKit::ScalarTraits::RealT; - return MU * sigmoid(x) * (ONE - sigmoid(x)); - } - /** * @brief Smooth above-limit indicator * diff --git a/GridKit/CommonMath.md b/GridKit/CommonMath.md index 3f0035dc1..0a8f81e81 100644 --- a/GridKit/CommonMath.md +++ b/GridKit/CommonMath.md @@ -4,168 +4,196 @@ Smooth, autodiff-friendly replacements for piecewise functions used across GridK ## Primitives -### Descriptions +The scale $\mu=4\cdot f_{\text{sync}}=240$ is chosen so $\sigma$ behaves like a step on inputs while keeping derivatives finite. As $\mu \to \infty$, these functions approach their exact targets. | Name | Description | Usage | |------|-------------|-------| -| `sigmoid` | Step function | `IEEET1` | -| `ramp` | Smooth one-sided ramp | `REGCA` | +| `sigmoid` | Step function | `GENSAL`, `GENROU`, `REGCA`, `REECA` | +| `ramp` | Smooth one-sided ramp | `REGCA`, `REECA`, `REPCA` | | `qramp` | Exact one-sided quadratic ramp | `IEEET1` | -### Exact Equations +### $\sigma$ - `sigmoid` ```math \begin{aligned} -\sigma(x) -&= -\begin{cases} -0 & x \le 0 \\ -1 & x > 0 -\end{cases} -\\ -\rho(x) &= x\,\sigma(x) \\ -q(x) &= x^2\,\sigma(x) +\sigma(x) &= \begin{cases}0 & x\le 0\\ 1 & x>0\end{cases} \\ + &\approx \dfrac{1}{2}\left(1+\tanh\left(\dfrac{\mu x}{2}\right)\right) \end{aligned} ``` -### Smooth Equations +
+ +### $\rho$ - `ramp` + +`ramp` is the softplus approximation to the one-sided ramp. We do not use $x\sigma(x)$ directly because it introduces a negative tail for $x < 0$, while softplus stays nonnegative and approaches $\max(x, 0)$ as the smoothing becomes sharp. ```math \begin{aligned} -\sigma(x) &= \dfrac{1}{2}\left(1+\tanh\left(\dfrac{\mu x}{2}\right)\right) \\ -\rho(x) &= \dfrac{x+\lvert x\rvert}{2}+\dfrac{\ln(1+e^{-\mu\lvert x\rvert})}{\mu} \\ -q(x) &= x^2\,\sigma(x) +\rho(x) &= x\,\sigma(x) \\ + &\approx \dfrac{x+\lvert x\rvert}{2}+\dfrac{\ln\!\left(1+e^{-\mu\lvert x\rvert}\right)}{\mu} \end{aligned} ``` -The scale $\mu=4\cdot f_{\text{sync}}=240$ is chosen so $\sigma$ behaves like a step on inputs of order 1 while keeping derivatives finite. As $\mu \to \infty$, these functions approach their exact targets. (*Note*: the implementation of the quadratic ramp `q(x)` could be optimized with Enzyme features down the road). +
-## Derived Functions +### $q$ - `qramp` + +*Note*: the implementation of the quadratic ramp `q(x)` could be optimized with Enzyme features down the road so that we don't need the smooth approximation. -### Descriptions +```math +q(x)=x^2\,\sigma(x) +``` + +
+ +## Derived Functions | Name | Description | Usage | |------|-------------|-------| -| `max` | Smooth binary maximum | `REECA` | +| `max` | Smooth binary maximum | `REECA`, `REECB` | | `min` | Smooth binary minimum | `REECA` | -| `clamp` | Bounded saturation | `IEEEST` | -| `deadband` | Signed two-sided deadband | `REECA` | +| `clamp` | Bounded saturation | `IEEEST`, `REECA`, `REECB`, `REPCA` | +| `deadband1` | Type 1 no-offset signed two-sided deadband | - | +| `deadband2` | Type 2 offset signed two-sided deadband | `REECA`, `REECB`, `REPCA` | | `slew` | Symmetric slew-rate limiter | - | | `linseg` | Saturated linear segment contribution | `REGCA`, `REECA` | -| `above` | Above-lower-limit indicator | - | +| `above` | Above-lower-limit indicator | `REPCA` | | `below` | Below-upper-limit indicator | - | -| `inside` | Interior pulse indicator | `IEEEST` | -| `outside` | Outside-band indicator | `REECA` | -| `antiwindup` | Anti-windup limited derivative | `IEEET1`, `TGOV1`, `SEXS-PTI`, `REECA` | +| `inside` | Interior pulse indicator | - | +| `outside` | Outside-band indicator | `REECA`, `REECB` | +| `antiwindup` | Anti-windup limited derivative | `IEEET1`, `SEXS-PTI`, `TGOV1`, `REECA`, `REECB`, `REPCA` | + +### `max` + +```math +\begin{aligned} +\text{max}(x,y) &= \begin{cases}x & x>y\\ y & x\le y\end{cases} \\ + &\approx y+\rho(x-y) +\end{aligned} +``` + +
+ +### `min` + +```math +\begin{aligned} +\text{min}(x,y) &= \begin{cases}x & x + +### `clamp` + +```math +\begin{aligned} +\text{clamp}(x;\ell,u) &= \begin{cases}\ell & x<\ell\\ x & \ell\le x\le u\\ u & x>u\end{cases} \\ + &\approx \ell+\rho(x-\ell)-\rho(x-u) +\end{aligned} +``` + +
+ +### `deadband1` + +```math +\begin{aligned} +\text{deadband1}(x;\ell,u) &= \begin{cases}x & x<\ell\\ 0 & \ell\le x\le u\\ x & x>u\end{cases} \\ + &\approx x\left[\sigma(\ell-x)+\sigma(x-u)\right] +\end{aligned} +``` + +
+ +### `deadband2` + +```math +\begin{aligned} +\text{deadband2}(x;\ell,u) &= \begin{cases}x-\ell & x<\ell\\ 0 & \ell\le x\le u\\ x-u & x>u\end{cases} \\ + &\approx \rho(x-u)-\rho(\ell-x) +\end{aligned} +``` + +
-### Exact Equations +### `slew` ```math \begin{aligned} -\text{max}(x,y) -&= -\begin{cases} -x & x > y \\ -y & x \le y -\end{cases} -\\ -\text{min}(x,y) -&= -\begin{cases} -x & x < y \\ -y & x \ge y -\end{cases} -\\ -\text{clamp}(x;\ell,u) -&= -\begin{cases} -\ell & x < \ell \\ -x & \ell \le x \le u \\ -u & x > u -\end{cases} -\\ -\text{deadband}(x;\ell,u) -&= -\begin{cases} -x-\ell & x < \ell \\ -0 & \ell \le x \le u \\ -x-u & x > u -\end{cases} -\\ -\text{slew}(f;r) -&= -\begin{cases} --r & f < -r \\ -f & -r \le f \le r \\ -r & f > r -\end{cases} -\\ -\text{linseg}(x;a,b,h) -&= -\begin{cases} -0 & x < a \\ -\dfrac{h}{b-a}(x-a) & a \le x \le b \\ -h & x > b -\end{cases} -\\ -\text{above}(x;\ell) -&= -\begin{cases} -0 & x \le \ell \\ -1 & x > \ell -\end{cases} -\\ -\text{below}(x;u) -&= -\begin{cases} -1 & x < u \\ -0 & x \ge u -\end{cases} -\\ -\text{inside}(x;\ell,u) -&= -\begin{cases} -1 & \ell < x < u \\ -0 & \text{else} -\end{cases} -\\ -\text{outside}(x;\ell,u) -&= -\begin{cases} -1 & x < \ell \lor x > u \\ -0 & \text{else} -\end{cases} -\\ -\text{antiwindup}(x,f;\ell,u) -&= -\begin{cases} -f & \ell < x < u \\ -f & x \le \ell \land f > 0 \\ -f & x \ge u \land f < 0 \\ -0 & \text{otherwise} -\end{cases} +\text{slew}(f;r) &= \begin{cases}-r & f<-r\\ f & -r\le f\le r\\ r & f>r\end{cases} \\ + &\approx -r+\rho(f+r)-\rho(f-r) \end{aligned} ``` -### Smooth Equations +
+ +### `linseg` + +```math +\begin{aligned} +\text{linseg}(x;a,b,h) &= \begin{cases}0 & xb\end{cases} \\ + &\approx \dfrac{h}{b-a}\left[\rho(x-a)-\rho(x-b)\right] +\end{aligned} +``` + +
+ +### `above` + +```math +\begin{aligned} +\text{above}(x;\ell) &= \begin{cases}0 & x\le \ell\\ 1 & x>\ell\end{cases} \\ + &\approx \sigma(x-\ell) +\end{aligned} +``` + +
+ +### `below` + +```math +\begin{aligned} +\text{below}(x;u) &= \begin{cases}1 & x + +### `inside` + +```math +\begin{aligned} +\text{inside}(x;\ell,u) &= \begin{cases}1 & \ell + +### `outside` + +```math +\begin{aligned} +\text{outside}(x;\ell,u) &= \begin{cases}1 & x<\ell\ \lor\ x>u\\ 0 & \text{else}\end{cases} \\ + &\approx \sigma(\ell-x)+\sigma(x-u) +\end{aligned} +``` + +
+ +### `antiwindup` ```math \begin{aligned} -\text{max}(x,y) &= y+\rho(x-y) \\ -\text{min}(x,y) &= x-\rho(x-y) \\ -\text{clamp}(x;\ell,u) &= \ell+\rho(x-\ell)-\rho(x-u) \\ -\text{deadband}(x;\ell,u) &= \rho(x-u)-\rho(\ell-x) \\ -\text{slew}(f;r) &= -r+\rho(f+r)-\rho(f-r) \\ -\text{linseg}(x;a,b,h) &= \dfrac{h}{b-a}\left[\rho(x-a)-\rho(x-b)\right] \\ -\text{above}(x;\ell) &= \sigma(x-\ell) \\ -\text{below}(x;u) &= \sigma(u-x) \\ -\text{inside}(x;\ell,u) &= \sigma(x-\ell)+\sigma(u-x)-1 \\ -\text{outside}(x;\ell,u) &= \sigma(\ell-x)+\sigma(x-u) \\ +\text{antiwindup}(x,f;\ell,u) &= \begin{cases}f & \ell0\\ f & x\ge u\ \land\ f<0\\ 0 & \text{otherwise}\end{cases} \\ \phi_L &= \text{above}(x;\ell) \\ \phi_U &= \text{below}(x;u) \\ \phi(x,f) &= \phi_L\phi_U+(1-\phi_U)\sigma(-f)+(1-\phi_L)\sigma(f) \\ -\text{antiwindup}(x,f;\ell,u) &= \phi(x,f)f +\text{antiwindup}(x,f;\ell,u) &\approx \phi(x,f)\,f \end{aligned} ``` diff --git a/docs/Figures/CommonMath/above.svg b/docs/Figures/CommonMath/above.svg new file mode 100644 index 000000000..b369d1fa2 --- /dev/null +++ b/docs/Figures/CommonMath/above.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Figures/CommonMath/below.svg b/docs/Figures/CommonMath/below.svg new file mode 100644 index 000000000..1f1e8fb7e --- /dev/null +++ b/docs/Figures/CommonMath/below.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Figures/CommonMath/clamp.svg b/docs/Figures/CommonMath/clamp.svg new file mode 100644 index 000000000..2be22aaf6 --- /dev/null +++ b/docs/Figures/CommonMath/clamp.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Figures/CommonMath/deadband1.svg b/docs/Figures/CommonMath/deadband1.svg new file mode 100644 index 000000000..abb583f1d --- /dev/null +++ b/docs/Figures/CommonMath/deadband1.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Figures/CommonMath/deadband2.svg b/docs/Figures/CommonMath/deadband2.svg new file mode 100644 index 000000000..fc2fa33aa --- /dev/null +++ b/docs/Figures/CommonMath/deadband2.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Figures/CommonMath/inside.svg b/docs/Figures/CommonMath/inside.svg new file mode 100644 index 000000000..143662a8f --- /dev/null +++ b/docs/Figures/CommonMath/inside.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Figures/CommonMath/linseg.svg b/docs/Figures/CommonMath/linseg.svg new file mode 100644 index 000000000..8dd8e81aa --- /dev/null +++ b/docs/Figures/CommonMath/linseg.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Figures/CommonMath/max.svg b/docs/Figures/CommonMath/max.svg new file mode 100644 index 000000000..2f6969fe3 --- /dev/null +++ b/docs/Figures/CommonMath/max.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Figures/CommonMath/min.svg b/docs/Figures/CommonMath/min.svg new file mode 100644 index 000000000..daeb9bcd9 --- /dev/null +++ b/docs/Figures/CommonMath/min.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Figures/CommonMath/outside.svg b/docs/Figures/CommonMath/outside.svg new file mode 100644 index 000000000..432c55d65 --- /dev/null +++ b/docs/Figures/CommonMath/outside.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Figures/CommonMath/qramp.svg b/docs/Figures/CommonMath/qramp.svg new file mode 100644 index 000000000..d7f766974 --- /dev/null +++ b/docs/Figures/CommonMath/qramp.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Figures/CommonMath/ramp.svg b/docs/Figures/CommonMath/ramp.svg new file mode 100644 index 000000000..863668961 --- /dev/null +++ b/docs/Figures/CommonMath/ramp.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Figures/CommonMath/sigmoid.svg b/docs/Figures/CommonMath/sigmoid.svg new file mode 100644 index 000000000..2f3754f46 --- /dev/null +++ b/docs/Figures/CommonMath/sigmoid.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/Figures/CommonMath/slew.svg b/docs/Figures/CommonMath/slew.svg new file mode 100644 index 000000000..988a95f93 --- /dev/null +++ b/docs/Figures/CommonMath/slew.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From a2278c59ac9df8a53f4218f28b32c727b61410f2 Mon Sep 17 00:00:00 2001 From: lukelowry Date: Sun, 7 Jun 2026 07:25:30 -0500 Subject: [PATCH 5/6] Add explanation for primitives --- GridKit/CommonMath.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/GridKit/CommonMath.md b/GridKit/CommonMath.md index 0a8f81e81..77086b132 100644 --- a/GridKit/CommonMath.md +++ b/GridKit/CommonMath.md @@ -14,6 +14,8 @@ The scale $\mu=4\cdot f_{\text{sync}}=240$ is chosen so $\sigma$ behaves like a ### $\sigma$ - `sigmoid` +The sigmoid is also known as the logistic function. The equivalent `tanh` form is used for numerical stability because the exponential form can divide by a very large value. + ```math \begin{aligned} \sigma(x) &= \begin{cases}0 & x\le 0\\ 1 & x>0\end{cases} \\ From 3e350e71fa1c72736e13a49aee4800e6e9502a86 Mon Sep 17 00:00:00 2001 From: Luke Lowery Date: Sun, 7 Jun 2026 09:44:54 -0500 Subject: [PATCH 6/6] Formatting bug in CommonMath.md GitHub MathJax behaves very strangely and is different from VSCode. I am not sure what the issues even was but these changes fixed it --- GridKit/CommonMath.md | 141 ++++++++++++++++++++++++++++++++---------- 1 file changed, 109 insertions(+), 32 deletions(-) diff --git a/GridKit/CommonMath.md b/GridKit/CommonMath.md index 77086b132..9f9f9bdcc 100644 --- a/GridKit/CommonMath.md +++ b/GridKit/CommonMath.md @@ -18,8 +18,13 @@ The sigmoid is also known as the logistic function. The equivalent `tanh` form i ```math \begin{aligned} -\sigma(x) &= \begin{cases}0 & x\le 0\\ 1 & x>0\end{cases} \\ - &\approx \dfrac{1}{2}\left(1+\tanh\left(\dfrac{\mu x}{2}\right)\right) + \sigma(x) + &= + \begin{cases} + 0 & x\le 0 \\[0pt] + 1 & x\gt 0 + \end{cases} \\[0pt] + &\approx \dfrac{1}{2}\left(1+\tanh\left(\dfrac{\mu x}{2}\right)\right) \end{aligned} ``` @@ -27,12 +32,13 @@ The sigmoid is also known as the logistic function. The equivalent `tanh` form i ### $\rho$ - `ramp` -`ramp` is the softplus approximation to the one-sided ramp. We do not use $x\sigma(x)$ directly because it introduces a negative tail for $x < 0$, while softplus stays nonnegative and approaches $\max(x, 0)$ as the smoothing becomes sharp. +`ramp` is the softplus approximation to the one-sided ramp. We do not use $x\sigma(x)$ directly because it introduces a negative tail for $x \lt 0$, while softplus stays nonnegative and approaches $\max(x, 0)$ as the smoothing becomes sharp. ```math \begin{aligned} -\rho(x) &= x\,\sigma(x) \\ - &\approx \dfrac{x+\lvert x\rvert}{2}+\dfrac{\ln\!\left(1+e^{-\mu\lvert x\rvert}\right)}{\mu} + \rho(x) + &= x\,\sigma(x) \\[0pt] + &\approx \dfrac{x+\lvert x\rvert}{2}+\dfrac{\ln\!\left(1+e^{-\mu\lvert x\rvert}\right)}{\mu} \end{aligned} ``` @@ -69,8 +75,13 @@ q(x)=x^2\,\sigma(x) ```math \begin{aligned} -\text{max}(x,y) &= \begin{cases}x & x>y\\ y & x\le y\end{cases} \\ - &\approx y+\rho(x-y) + \text{max}(x,y) + &= + \begin{cases} + x & x\gt y \\[0pt] + y & x\le y + \end{cases} \\[0pt] + &\approx y+\rho(x-y) \end{aligned} ``` @@ -80,8 +91,13 @@ q(x)=x^2\,\sigma(x) ```math \begin{aligned} -\text{min}(x,y) &= \begin{cases}x & xu\end{cases} \\ - &\approx \ell+\rho(x-\ell)-\rho(x-u) + \text{clamp}(x;\ell,u) + &= + \begin{cases} + \ell & x\lt \ell \\[0pt] + x & \ell\le x\le u \\[0pt] + u & x\gt u + \end{cases} \\[0pt] + &\approx \ell+\rho(x-\ell)-\rho(x-u) \end{aligned} ``` @@ -102,8 +124,14 @@ q(x)=x^2\,\sigma(x) ```math \begin{aligned} -\text{deadband1}(x;\ell,u) &= \begin{cases}x & x<\ell\\ 0 & \ell\le x\le u\\ x & x>u\end{cases} \\ - &\approx x\left[\sigma(\ell-x)+\sigma(x-u)\right] + \text{deadband1}(x;\ell,u) + &= + \begin{cases} + x & x\lt \ell \\[0pt] + 0 & \ell\le x\le u \\[0pt] + x & x\gt u + \end{cases} \\[0pt] + &\approx x\left[\sigma(\ell-x)+\sigma(x-u)\right] \end{aligned} ``` @@ -113,8 +141,14 @@ q(x)=x^2\,\sigma(x) ```math \begin{aligned} -\text{deadband2}(x;\ell,u) &= \begin{cases}x-\ell & x<\ell\\ 0 & \ell\le x\le u\\ x-u & x>u\end{cases} \\ - &\approx \rho(x-u)-\rho(\ell-x) + \text{deadband2}(x;\ell,u) + &= + \begin{cases} + x-\ell & x\lt \ell \\[0pt] + 0 & \ell\le x\le u \\[0pt] + x-u & x\gt u + \end{cases} \\[0pt] + &\approx \rho(x-u)-\rho(\ell-x) \end{aligned} ``` @@ -124,8 +158,14 @@ q(x)=x^2\,\sigma(x) ```math \begin{aligned} -\text{slew}(f;r) &= \begin{cases}-r & f<-r\\ f & -r\le f\le r\\ r & f>r\end{cases} \\ - &\approx -r+\rho(f+r)-\rho(f-r) + \text{slew}(f;r) + &= + \begin{cases} + -r & f\lt -r \\[0pt] + f & -r\le f\le r \\[0pt] + r & f\gt r + \end{cases} \\[0pt] + &\approx -r+\rho(f+r)-\rho(f-r) \end{aligned} ``` @@ -135,8 +175,14 @@ q(x)=x^2\,\sigma(x) ```math \begin{aligned} -\text{linseg}(x;a,b,h) &= \begin{cases}0 & xb\end{cases} \\ - &\approx \dfrac{h}{b-a}\left[\rho(x-a)-\rho(x-b)\right] + \text{linseg}(x;a,b,h) + &= + \begin{cases} + 0 & x\lt a \\[0pt] + \dfrac{h}{b-a}(x-a) & a\le x\le b \\[0pt] + h & x\gt b + \end{cases} \\[0pt] + &\approx \dfrac{h}{b-a}\left[\rho(x-a)-\rho(x-b)\right] \end{aligned} ``` @@ -146,8 +192,13 @@ q(x)=x^2\,\sigma(x) ```math \begin{aligned} -\text{above}(x;\ell) &= \begin{cases}0 & x\le \ell\\ 1 & x>\ell\end{cases} \\ - &\approx \sigma(x-\ell) + \text{above}(x;\ell) + &= + \begin{cases} + 0 & x\le \ell \\[0pt] + 1 & x\gt \ell + \end{cases} \\[0pt] + &\approx \sigma(x-\ell) \end{aligned} ``` @@ -157,8 +208,13 @@ q(x)=x^2\,\sigma(x) ```math \begin{aligned} -\text{below}(x;u) &= \begin{cases}1 & xu\\ 0 & \text{else}\end{cases} \\ - &\approx \sigma(\ell-x)+\sigma(x-u) + \text{outside}(x;\ell,u) + &= + \begin{cases} + 1 & x\lt \ell\ \lor\ x\gt u \\[0pt] + 0 & \text{else} + \end{cases} \\[0pt] + &\approx \sigma(\ell-x)+\sigma(x-u) \end{aligned} ``` @@ -192,10 +258,21 @@ q(x)=x^2\,\sigma(x) ```math \begin{aligned} -\text{antiwindup}(x,f;\ell,u) &= \begin{cases}f & \ell0\\ f & x\ge u\ \land\ f<0\\ 0 & \text{otherwise}\end{cases} \\ -\phi_L &= \text{above}(x;\ell) \\ -\phi_U &= \text{below}(x;u) \\ -\phi(x,f) &= \phi_L\phi_U+(1-\phi_U)\sigma(-f)+(1-\phi_L)\sigma(f) \\ -\text{antiwindup}(x,f;\ell,u) &\approx \phi(x,f)\,f + \text{antiwindup}(x,f;\ell,u) + &= + \begin{cases} + f & \ell\lt x\lt u \\[0pt] + f & x\le\ell\ \land\ f\gt 0 \\[0pt] + f & x\ge u\ \land\ f\lt 0 \\[0pt] + 0 & \text{otherwise} + \end{cases} \\[0pt] + \phi_L + &= \text{above}(x;\ell) \\[0pt] + \phi_U + &= \text{below}(x;u) \\[0pt] + \phi(x,f) + &= \phi_L\phi_U+(1-\phi_U)\sigma(-f)+(1-\phi_L)\sigma(f) \\[0pt] + \text{antiwindup}(x,f;\ell,u) + &\approx \phi(x,f)\,f \end{aligned} ```