EquationKit 0.0.7

EquationKit 0.0.7

Alexander Cyon 维护。



使用纯 Swift 编写方程式,微分和/或评估它们。

let polynomial = (3*x + 5*y - 17) * (7*x - 9*y + 23)
print(polynomial) // 21x² + 8xy - 50x - 45y² + 268y - 391)
let number = polynomial.evaluate() {[ x <- 4, y <- 1 ]}
print(number) // 0

let y' = equation.differentiateWithRespectTo(x)
print(y') // 42x + 8y - 50
y'.evaluate() {[ x <- 1, y <- 1 ]} // 0

let x' = equation.differentiateWithRespectTo(y)
print(x') // 8x - 90y + 268
 x'.evaluate() {[ x <- 11.5,  y <- 4 ]} // 0

泛型

EquationKit 是完全泛型的,并支持任何遵守协议 NumberExpressible 的数字类型,Swift 基础库中的 IntDouble 都遵循此协议。通过遵守 NumberExpressible 协议,你可以使用 EquationKit 与例如出色的 attaswift/BigInt。你需要只复制 BigInt+IntegerNumberExpressible 的代码。

我们想使用操作符重载,使其能够编写 x + yx - 2x*z² - y³ 等等。使用泛型 func + <N: NumberExpressible>(lhs: Variable, rhs: N) -> PolynomialStruct<N> 支持操作符重载会使 Swift 编译器在编译超过 3 项的多项式时花费太长时间(至少在 Xcode 10 beta 6 中)。因此,EquationKit 并不附带任何操作符支持。相反,你自己选择数字类型。如果你不需要 BigInt,则 Double 可能是你想要的。只需将文件 Double_Operators 复制到你的项目中即可!它包含大约 10 个操作符,每个操作符都是 3 行代码。

如果你需要 BigInt 支持,只需复制文件 BigInt_Operators 替代。

变量

你使用自定义操作符 x^^2 编写指数,但对于 29 之间的指数,可以使用unicode 上标符号替代,如下所示

let x = Variable("x")
let y = Variable("y")
let= Exponentiation(x, exponent: 2)
let= Exponentiation(x, exponent: 3)
let x⁴ = Exponentiation(x, exponent: 4)
let x⁵ = Exponentiation(x, exponent: 5)
let x⁶ = Exponentiation(x, exponent: 6)
let x⁷ = Exponentiation(x, exponent: 7)
let x⁸ = Exponentiation(x, exponent: 8)
let x⁹ = Exponentiation(x, exponent: 9)

let= Exponentiation(y, exponent: 2)

您可以将文件 Double_Variables 的内容复制过来或为 BigInt 支持:BigInt_Variables,当然还可以扩展更多你选择的变量。

高级运算符

您可以使用文件夹 MathematicalOperators 提供的一些高级数学运算符,来精确表达你可能有的数学约束。

变量到常量(求值)

让我们看一个最简单的场景

使用特殊的 Unicode 字符 (通常是用于表示 := 赋值运算,常用于文献中),我们可以把求值写成如下:

𝑦² - 𝑥³.evaluate() {[ x  1, y  2 ]} 

而不是

𝑦² - 𝑥³.evaluate() {[ x <- 1, y <- 2 ]} 

复杂示例

以下是如何使用 EllipticCurveKit 通过 EquationKit 表达对椭圆曲线参数的要求的示例。Weierstrass 形式的椭圆曲线要求满足以下同余不等式

𝟜𝑎³ + 𝟚𝟟𝑏² ≢ 𝟘 mod 𝑝

感谢 EquationKit,我们可以在 Swift 中几乎与纯数学表达式一样地表达这个不等式

𝟜𝑎³ + 𝟚𝟟𝑏²  0 % 𝑝 

但这还远远不够,我们还需要使用初始化器传入的参数来评估这个不等式(多项式)。当然,我们可以写成这样:

(𝟜𝑎³ + 𝟚𝟟𝑏²).evaluate(modulus: 𝑝) {[ 𝑎  a, 𝑏  b ]} != 0

但一种稍微更“数学”的语法是

𝟜𝑎³ + 𝟚𝟟𝑏²  𝟘 % 𝑝  [ 𝑎  a, 𝑏  b ]

它评估了给定的 ab 的多项式 𝟜𝑎³ + 𝟚𝟟𝑏²,并对 𝑝 进行模运算,并将其与 0 进行比较。我们当然也可以支持这种语法

// This syntax is not yet supported, but can easily be added
[a𝑎, b𝑏]  𝟜𝑎³ + 𝟚𝟟𝑏²  𝟘 % 𝑝

我们当然也可以不使用任何特殊的 Unicode 字符,就像这样

4*a^^3 + 27*b^^2 =!%= 0 % p <-- [ a  constA, b  constB ]

其中 =!%= 替换了

请通过 提交一个问题 对运算符的选择给出反馈。

let 𝑎 = Variable("𝑎")
let 𝑏 = Variable("𝑏")
let 𝑎³ = Exponentiation(𝑎, exponent: 3)
let 𝑏² = Exponentiation(𝑏, exponent: 2)

let 𝟜𝑎³ = 4*𝑎³
let 𝟚𝟟𝑏² = 27*𝑏²
let 𝟘: BigInt = 0

///
/// Elliptic Curve on Short Weierstraß form (`𝑆`)
/// - Covers all elliptic curves char≠𝟚,𝟛
/// - Mixed Jacobian coordinates have been the speed leader for a long time.
///
///
/// # Equation
///      𝑆: 𝑦² = 𝑥³ + 𝑎𝑥 + 𝑏
/// - Requires: `𝟜𝑎³ + 𝟚𝟟𝑏² ≠ 𝟘 in 𝔽_𝑝 (mod 𝑝)`
///
struct ShortWeierstraßCurve {
    /// Try to initialize an elliptic curve on the ShortWeierstraß form using parameters for `a`, `b` in the given Galois field (mod 𝑝).
    public init(a: BigInt, b: BigInt, field 𝑝: BigInt) throws {
        guard 
            𝟜𝑎³ + 𝟚𝟟𝑏²  𝟘 % 𝑝  [ 𝑎  a, 𝑏  b ]
        else { throw EllipticCurveError.invalidCurveParameters }
        self.a = a
        self.b = b
        self.field = 𝑝
    }
}

支持的

  • 单变量和多元方程(变量数量没有限制,随心所欲!)
  • 对任何单变量或多元方程关于它的某些变量求导
  • 将方程与方程相乘
  • 模运算
  • BigInt 支持

局限性

尚未支持,但已在路线图上

  • 替换 (3*(4*x + 5)^^2 - 2*(4x+5) - 1).substitute() { z <~ (4*x + 5) } // 3*z²-2*z-1
  • 除法
  • 求根(求解)

不支持的且不在路线图上

  • 指数中的变量,如 2^x
  • log/ln 函数
  • 三角函数(sincostan 等)
  • 复数