使用纯 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 基础库中的 Int
和 Double
都遵循此协议。通过遵守 NumberExpressible
协议,你可以使用 EquationKit 与例如出色的 attaswift/BigInt。你需要只复制 BigInt+IntegerNumberExpressible
的代码。
我们想使用操作符重载,使其能够编写 x + y
,x - 2
,x*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
编写指数,但对于 2
和 9
之间的指数,可以使用unicode 上标符号替代,如下所示
let x = Variable("x")
let y = Variable("y")
let x² = Exponentiation(x, exponent: 2)
let x³ = 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 y² = 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 ]
它评估了给定的 a
和 b
的多项式 𝟜𝑎³ + 𝟚𝟟𝑏²
,并对 𝑝
进行模运算,并将其与 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
函数- 三角函数(
sin
、cos
、tan
等) - 复数