"""This module contains the `EllCalcCore` class.
This code defines a class called EllCalcCore, which is designed to perform calculations related to ellipsoids in mathematics. An ellipsoid is a 3D shape that's like a stretched or squashed sphere. The class provides methods to calculate various parameters of ellipsoids under different conditions.
The main purpose of this code is to provide a set of tools for working with ellipsoids in optimization problems. It takes in various numerical inputs representing different aspects of an ellipsoid or cuts through it, and produces output values that describe how the ellipsoid should be adjusted or analyzed.
The class is initialized with a single input 'n_f', which represents the dimension of the space the ellipsoid exists in. This value is used to set up several constant values that are used in later calculations.
The class provides several methods, each performing a different type of calculation:
1. calc_central_cut: This calculates parameters for a cut through the center of the ellipsoid.
2. calc_bias_cut and calc_bias_cut_fast: These calculate parameters for a cut that doesn't go through the center.
3. calc_parallel_central_cut and calc_parallel_central_cut_old: These handle cuts that are parallel to a central cut.
4. calc_parallel_bias_cut, calc_parallel_bias_cut_fast, and calc_parallel_bias_cut_old: These deal with parallel cuts that don't go through the center.
Each of these methods takes in one or more numerical inputs (like 'tau', 'beta', 'tsq') that represent different aspects of the cut or the ellipsoid. They then perform a series of mathematical calculations using these inputs and the constants set up during initialization. The calculations involve basic arithmetic, square roots, and some more complex formulas specific to ellipsoid geometry.
The output of each method is typically a tuple of three float values, often represented as (rho, sigma, delta). These values describe how the ellipsoid should be adjusted based on the cut that was calculated.
The code achieves its purpose by encapsulating all these complex mathematical calculations into easy-to-use methods. A programmer can create an instance of EllCalcCore and then call these methods as needed, without having to understand all the underlying mathematics.
The main logic flow in this code is from the input parameters, through the mathematical calculations, to the output tuple. The data transformations happening are primarily mathematical: converting the input parameters into the desired output parameters using the formulas of ellipsoid geometry.
This code is a tool for more complex algorithms that might be using these ellipsoid calculations as part of a larger optimization or analysis process. It provides a clean, object-oriented way to perform these specific mathematical operations.
"""
from math import sqrt
from typing import Tuple
[docs]
class EllCalcCore:
"""The `EllCalcCore` class is used for calculating ellipsoid parameters.
This class provides methods to compute various parameters (rho, sigma, delta) that define
how an ellipsoid should be transformed when cut by different types of hyperplanes. These
parameters are essential in ellipsoid-based optimization algorithms.
Examples:
>>> calc = EllCalcCore(3)
"""
_n_f: float
_half_n: float
_n_plus_1: float
_cst0: float
_cst1: float
_cst2: float
_cst3: float
def __init__(self, n_f: float) -> None:
"""Initialize EllCalcCore instance.
The __init__ method initializes the EllCalcCore object with the provided
n_f parameter. This sets up internal variables used in calculations.
The initialization computes several constants that are frequently used in
the ellipsoid calculations to avoid repeated computation:
- _half_n: Half of the dimension n_f
- _n_plus_1: n_f + 1
- _inv_n: 1/n_f
- _n_sq: n_f squared
- _cst0 to _cst3: Various precomputed constants used in cut calculations
:param n_f: Float value representing the dimension of the space
:type n_f: float
Examples:
>>> calc = EllCalcCore(3)
>>> calc._n_f
3
>>> calc._half_n
1.5
>>> calc._cst0
0.25
>>> calc._cst1
1.125
>>> calc._cst2
0.5
>>> calc._cst3
0.75
"""
self._n_f = n_f
self._half_n = self._n_f / 2.0
self._n_plus_1 = self._n_f + 1.0
self._inv_n = 1.0 / self._n_f
self._n_sq = self._n_f * self._n_f
self._cst0 = 1.0 / self._n_plus_1
self._cst1 = self._n_sq / (self._n_sq - 1.0)
self._cst2 = 2.0 * self._cst0
self._cst3 = self._n_f * self._cst0
[docs]
def calc_central_cut(self, tau: float) -> Tuple[float, float, float]:
r"""Calculate the central cut values.
The `calc_central_cut` method calculates the central cut values ρ, σ, δ
based on the input tau value. A central cut is a hyperplane that passes
through the center of the ellipsoid.
The parameters returned are:
- ρ (rho): Determines the shift of the ellipsoid center
- σ (sigma): Determines how much to scale the ellipsoid
- δ (delta): Determines how much to stretch the ellipsoid
:param tau: The distance parameter for the central cut
:type tau: float
:return: Tuple of (ρ, σ, δ) values for the central cut
:rtype: Tuple[float, float, float]
.. svgbob::
:align: center
_.-'''''''-._
,' | `.
/ | \
. | .
| |
| . |
| |
:\ | /:
| `._ | _.' |
| '-.......-' |
| | |
"-τ" 0 +τ
2
σ = ─────
n + 1
τ
ϱ = ─────
n + 1
2
n
δ = ──────
2
n - 1
Examples:
>>> calc = EllCalcCore(3)
>>> calc.calc_central_cut(4.0)
(1.0, 0.5, 1.125)
"""
rho = self._cst0 * tau
sigma = self._cst2
delta = self._cst1
return (rho, sigma, delta)
[docs]
def calc_bias_cut_fast(
self, beta: float, tau: float, eta: float
) -> Tuple[float, float, float]:
r"""Calculates the deep cut ellipsoid parameters using precomputed eta values.
This is an optimized version of calc_bias_cut that takes a precomputed eta value
(η = τ + n⋅β) as input to avoid redundant calculations when eta is already known.
The method computes parameters for a biased (non-central) cut of the ellipsoid,
where the cut doesn't pass through the center. The parameters determine how to
transform the ellipsoid after the cut.
:param beta: The bias parameter (distance from center to cut hyperplane)
:type beta: float
:param tau: The distance parameter for the cut
:type tau: float
:param eta: Precomputed value of τ + n⋅β
:type eta: float
:return: Tuple of (ρ, σ, δ) values for the biased cut
:rtype: Tuple[float, float, float]
.. svgbob::
:align: center
_.-'''''''-._
,' | `.
/ | \
. | .
| | |
| | . |
| | |
:\ | /:
| `._ | _.' |
| '-.......-' |
| | |
"-τ" "-β" +τ
η
ϱ = ─────
n + 1
2 ⋅ ϱ
σ = ─────
τ + β
2 2 2
n τ - β
δ = ────── ⋅ ───────
2 2
n - 1 τ
Examples:
>>> calc = EllCalcCore(3)
>>> calc.calc_bias_cut_fast(1.0, 2.0, 5.0)
(1.25, 0.8333333333333334, 0.84375)
>>> calc.calc_bias_cut_fast(0.0, 2.0, 2.0)
(0.5, 0.5, 1.125)
"""
alpha = beta / tau
rho = self._cst0 * eta
sigma = self._cst2 * eta / (tau + beta)
delta = self._cst1 * (1.0 - alpha) * (1.0 + alpha)
return (rho, sigma, delta)
[docs]
def calc_bias_cut(self, beta: float, tau: float) -> Tuple[float, float, float]:
r"""Calculate deep cut values.
Calculates the deep cut values ρ, σ, δ for given β and τ. This is the standard
version that computes η internally before calling calc_bias_cut_fast.
A deep cut is a generalization of a central cut where the cutting hyperplane
doesn't necessarily pass through the center of the ellipsoid. The parameters
determine how to transform the ellipsoid after the cut.
:param beta: The bias parameter (distance from center to cut hyperplane)
:type beta: float
:param tau: The distance parameter for the cut
:type tau: float
:return: Tuple of (ρ, σ, δ) values for the biased cut
:rtype: Tuple[float, float, float]
.. svgbob::
:align: center
_.-'''''''-._
,' | `.
/ | \
. | .
| | |
| | . |
| | |
:\ | /:
| `._ | _.' |
| '-.......-' |
| | |
"-τ" "-β" +τ
η = τ + n ⋅ β
η
ϱ = ─────
n + 1
2 ⋅ ϱ
σ = ─────
τ + β
2 2 2
n τ - β
δ = ────── ⋅ ───────
2 2
n - 1 τ
Examples:
>>> calc = EllCalcCore(3)
>>> calc.calc_bias_cut(1.0, 2.0)
(1.25, 0.8333333333333334, 0.84375)
>>> calc.calc_bias_cut(0.0, 2.0)
(0.5, 0.5, 1.125)
"""
return self.calc_bias_cut_fast(beta, tau, tau + self._n_f * beta)
[docs]
def calc_parallel_central_cut(
self, beta1: float, tsq: float
) -> Tuple[float, float, float]:
r"""Calculate Parallel Central Cut (7 mul/div + 1 sqrt)
Computes parameters for a cut that is parallel to a central cut but offset by beta1.
This optimized version uses fewer operations than the old version.
The method calculates:
- ρ: Determines the shift of the ellipsoid center
- σ: Scaling factor for the ellipsoid
- δ: Stretching factor for the ellipsoid
:param beta1: Offset parameter for the parallel cut
:type beta1: float
:param tsq: Square of the distance parameter (τ²)
:type tsq: float
:return: Tuple of (ρ, σ, δ) values for the parallel central cut
:rtype: Tuple[float, float, float]
.. svgbob::
:align: center
_.-'''''''-._
,' | `.
/ | | \
. | | .
| | |
| | . |
| | |
:\ | | /:
| `._ | _.' |
| |'-.......-' |
| | | |
"-τ" "-β" 0 +τ
1
2 2 2
α = β / τ
n 2
k = ─ ⋅ α
2
___________
╱ 2 2
r = k + ╲╱ k + 1 - α
β
ϱ = ─────
r + 1
2
σ = ─────
r + 1
r
δ = ─────────
r - 1 / n
Examples:
>>> calc = EllCalcCore(4)
>>> calc.calc_parallel_central_cut(0.09, 0.01)
(0.020941836487980856, 0.46537414417735234, 1.082031295477563)
"""
a1sq = beta1 * beta1 / tsq
k = self._half_n * a1sq
r = k + sqrt(1.0 - a1sq + k * k)
rho = beta1 / (r + 1.0)
sigma = 2.0 / (r + 1.0)
delta = r / (r - self._inv_n)
return (rho, sigma, delta)
[docs]
def calc_parallel_central_cut_old(
self, beta1: float, tsq: float
) -> Tuple[float, float, float]:
r"""Calculate Parallel Central Cut
Original version of the parallel central cut calculation. This version
uses more operations than the optimized version.
The method calculates parameters for transforming an ellipsoid after
a parallel central cut, where the cut is parallel to a central cut
but offset by beta1.
:param beta1: Offset parameter for the parallel cut
:type beta1: float
:param tsq: Square of the distance parameter (τ²)
:type tsq: float
:return: Tuple of (ρ, σ, δ) values for the parallel central cut
:rtype: Tuple[float, float, float]
.. svgbob::
:align: center
_.-'''''''-._
,' | `.
/ | | \
. | | .
| | |
| | . |
| | |
:\ | | /:
| `._ | _.' |
| |'-.......-' |
| | | |
"-τ" "-β" 0 +τ
1
__________________________
╱ 2
╱ ⎛ 2⎞
╱ ⎜n ⋅ β ⎟
╱ ⎛ 2 2⎞ 2 ⎜ 1⎟
ξ = ╱ ⎜τ - β ⎟ ⋅ τ + ⎜──────⎟
╲╱ ⎝ 1⎠ ⎝ 2 ⎠
⎛ 2 ⎞
n 2 ⋅ ⎝τ - ξ⎠
σ = ───── + ────────────
n + 1 2
(n + 1) ⋅ β
1
σ ⋅ β
1
ϱ = ──────
2
⎛ 2 ⎞
⎜ β ⎟
2 ⎜ 2 1 ξ⎟
n ⋅ ⎜τ - ── + ─⎟
⎝ 2 n⎠
δ = ──────────────────
⎛ 2 ⎞ 2
⎝n - 1⎠ ⋅ τ
Examples:
>>> calc = EllCalcCore(4)
>>> calc.calc_parallel_central_cut_old(0.09, 0.01)
(0.02094183648798086, 0.46537414417735246, 1.082031295477563)
"""
b1sq = beta1 * beta1
# if tsq < b1sq or not self.use_parallel_cut:
# return self.calc_cc(tsq)
# Core calculation
a1sq = b1sq / tsq
xi = sqrt(1.0 - a1sq + (self._half_n * a1sq) ** 2)
sigma = self._cst3 + self._cst2 * (1.0 - xi) / a1sq
rho = sigma * beta1 / 2.0
delta = self._cst1 * (1.0 - a1sq / 2.0 + xi / self._n_f)
return (rho, sigma, delta)
[docs]
def calc_parallel_bias_cut(
self, beta0: float, beta1: float, tsq: float
) -> Tuple[float, float, float]:
r"""Calculation Parallel Deep Cut (15 mul/div + 1 sqrt)
Computes parameters for a biased cut that is parallel to another biased cut.
This version computes intermediate values (b0b1 and eta) internally before
calling the fast version.
The method calculates:
- ρ: Center shift parameter
- σ: Scaling parameter
- δ: Stretching parameter
:param beta0: First bias parameter (for the reference cut)
:type beta0: float
:param beta1: Second bias parameter (for the parallel cut)
:type beta1: float
:param tsq: Square of the distance parameter (τ²)
:type tsq: float
:return: Tuple of (ρ, σ, δ) values for the parallel biased cut
:rtype: Tuple[float, float, float]
.. svgbob::
:align: center
_.-'''''''-._
,' | `.
/ | | \
. | | .
| | | |
| | |. |
| | | |
:\ | | /:
| `._ | _.' |
| |'-.......-' |
| | | |
"-τ" "-β" "-β" +τ
1 0
2
η = τ + n ⋅ β ⋅ β
0 1
β + β
0 1
β = ───────
2
1 ⎛ 2 ⎞ 2
h = ─ ⋅ ⎜τ + β ⋅ β ⎟ + n ⋅ β
2 ⎝ 0 1⎠
_____________________
╱ 2 2
k = h + ╲╱ h - (n + 1) ⋅ η ⋅ β
1 η
σ = ───── = ─
μ + 1 k
1 η
─ = ─────
μ k - η
ϱ = β ⋅ σ
2 2 1 ⎛ 2 ⎞
δ ⋅ τ = τ + ─ ⋅ ⎜β ⋅ σ - β ⋅ β ⎟
μ ⎝ 0 1⎠
Examples:
>>> calc = EllCalcCore(4)
>>> calc.calc_parallel_bias_cut(0.01, 0.11, 0.01)
(0.027228509068282114, 0.45380848447136857, 1.0443438549074862)
>>> calc.calc_parallel_bias_cut(-0.25, 0.25, 1.0)
(0.0, 0.8, 1.25)
>>> calc.calc_parallel_bias_cut(0.0, 0.09, 0.01)
(0.020941836487980856, 0.46537414417735234, 1.082031295477563)
"""
b0b1 = beta0 * beta1
return self.calc_parallel_bias_cut_fast(
beta0, beta1, tsq, b0b1, tsq + self._n_f * b0b1
)
[docs]
def calc_parallel_bias_cut_fast(
self, beta0: float, beta1: float, tsq: float, b0b1: float, eta: float
) -> Tuple[float, float, float]:
r"""Calculation Parallel Deep Cut (13 mul/div + 1 sqrt)
Optimized version of parallel biased cut calculation that takes precomputed
b0b1 (β₀β₁) and eta (η) values as input to reduce computation.
This version is more efficient when the calling code can precompute these
values, saving redundant calculations.
:param beta0: First bias parameter (for the reference cut)
:type beta0: float
:param beta1: Second bias parameter (for the parallel cut)
:type beta1: float
:param tsq: Square of the distance parameter (τ²)
:type tsq: float
:param b0b1: Precomputed product of beta0 and beta1 (β₀β₁)
:type b0b1: float
:param eta: Precomputed value of τ² + n⋅β₀β₁
:type eta: float
:return: Tuple of (ρ, σ, δ) values for the parallel biased cut
:rtype: Tuple[float, float, float]
.. svgbob::
:align: center
_.-'''''''-._
,' | `.
/ | | \
. | | .
| | | |
| | |. |
| | | |
:\ | | /:
| `._ | _.' |
| |'-.......-' |
| | | |
"-τ" "-β" "-β" +τ
1 0
β + β
0 1
β = ───────
2
1 ⎛ 2 ⎞ 2
h = ─ ⋅ ⎜τ + β ⋅ β ⎟ + n ⋅ β
2 ⎝ 0 1⎠
_____________________
╱ 2 2
k = h + ╲╱ h - (n + 1) ⋅ η ⋅ β
1 η
σ = ───── = ─
μ + 1 k
1 η
─ = ─────
μ k - η
ϱ = β ⋅ σ
2 2 1 ⎛ 2 ⎞
δ ⋅ τ = τ + ─ ⋅ ⎜β ⋅ σ - β ⋅ β ⎟
μ ⎝ 0 1⎠
Examples:
>>> calc = EllCalcCore(4)
>>> calc.calc_parallel_bias_cut_fast(0.11, 0.01, 0.01, 0.0011, 0.0144)
(0.027228509068282114, 0.45380848447136857, 1.0443438549074862)
>>> calc.calc_parallel_bias_cut_fast(-0.25, 0.25, 1.0, -0.0625, 0.75)
(0.0, 0.8, 1.25)
"""
bavg = 0.5 * (beta0 + beta1)
bavgsq = bavg * bavg
h = 0.5 * (tsq + b0b1) + self._n_f * bavgsq
k = h + sqrt(h * h - self._n_plus_1 * eta * bavgsq)
sigma = eta / k
inv_mu = eta / (k - eta)
rho = bavg * sigma
delta = (tsq + inv_mu * (bavgsq * sigma - b0b1)) / tsq
return (rho, sigma, delta)
[docs]
def calc_parallel_bias_cut_old(
self, beta0: float, beta1: float, tsq: float
) -> Tuple[float, float, float]:
r"""Calculation Parallel Deep Cut
Original version of the parallel biased cut calculation. This version
uses a different mathematical formulation that requires more computations
than the optimized versions.
The method calculates parameters for transforming an ellipsoid after
a parallel biased cut, where the cut is parallel to another biased cut.
:param beta0: First bias parameter (for the reference cut)
:type beta0: float
:param beta1: Second bias parameter (for the parallel cut)
:type beta1: float
:param tsq: Square of the distance parameter (τ²)
:type tsq: float
:return: Tuple of (ρ, σ, δ) values for the parallel biased cut
:rtype: Tuple[float, float, float]
.. svgbob::
:align: center
_.-'''''''-._
,' | `.
/ | | \
. | | .
| | | |
| | |. |
| | | |
:\ | | /:
| `._ | _.' |
| |'-.......-' |
| | | |
"-τ" "-β" "-β" +τ
1 0
2 2
ζ = τ - β
0 0
2 2
ζ = τ - β
1 1
__________________________
╱ 2
╱ ⎛ ⎛ 2 2⎞⎞
╱ ⎜n ⋅ ⎜β - β ⎟⎟
╱ ⎜ ⎝ 1 0⎠⎟
ξ = ╱ ζ ⋅ ζ + ⎜─────────────⎟
╲╱ 0 1 ⎝ 2 ⎠
⎛ 2 ⎞
2 ⋅ ⎜τ + β ⋅ β - ξ⎟
n ⎝ 0 1 ⎠
σ = ───── + ──────────────────────
n + 1 2
(n + 1) ⋅ ⎛β + β ⎞ <---- Oop!!!
⎝ 0 1⎠
σ ⋅ ⎛β + β ⎞
⎝ 0 1⎠
ϱ = ─────────────
2
⎛ζ + ζ ⎞
2 ⎜ 0 1 ξ⎟
n ⋅ ⎜─────── + ─⎟
⎝ 2 n⎠
δ = ──────────────────
⎛ 2 ⎞ 2
⎝n - 1⎠ ⋅ τ
Examples:
>>> calc = EllCalcCore(4)
>>> calc.calc_parallel_bias_cut_old(0.11, 0.01, 0.01)
(0.02722850906828212, 0.4538084844713687, 1.0443438549074862)
"""
b0b1 = beta0 * beta1
b0sq = beta0 * beta0
b1sq = beta1 * beta1
zeta0 = tsq - b0sq
zeta1 = tsq - b1sq
xi = sqrt(zeta0 * zeta1 + (self._half_n * (b1sq - b0sq)) ** 2)
bsumsq = (beta0 + beta1) ** 2
sigma = self._cst3 + self._cst2 * (tsq + b0b1 - xi) / bsumsq
rho = sigma * (beta0 + beta1) / 2.0
delta = self._cst1 * ((zeta0 + zeta1) / 2.0 + xi / self._n_f) / tsq
return (rho, sigma, delta)