https://github.com/sajjon/equationkit
Equations in Swift
https://github.com/sajjon/equationkit
equations mathematics multivariate-polynomials partial-derivative polynomial-arithmetic swift swift-framework
Last synced: 2 months ago
JSON representation
Equations in Swift
- Host: GitHub
- URL: https://github.com/sajjon/equationkit
- Owner: Sajjon
- License: apache-2.0
- Created: 2018-08-08T10:54:30.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2019-11-08T09:26:33.000Z (over 5 years ago)
- Last Synced: 2024-03-15T00:21:23.720Z (over 1 year ago)
- Topics: equations, mathematics, multivariate-polynomials, partial-derivative, polynomial-arithmetic, swift, swift-framework
- Language: Swift
- Size: 385 KB
- Stars: 42
- Watchers: 3
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# EquationKit
## Write equations in pure Swift, differentiate and/or evaluate them.
```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) // 0let y' = polynomial.differentiateWithRespectTo(x)
print(y') // 42x + 8y - 50
y'.evaluate() {[ x <- 1, y <- 1 ]} // 0let x' = polynomial.differentiateWithRespectTo(y)
print(x') // 8x - 90y + 268
x'.evaluate() {[ x <- 11.5, y <- 4 ]} // 0
```# Installation
## Swift Package Manager
```swift
dependencies: [
.package(url: "https://github.com/Sajjon/EquationKit", from: "0.1.0")
]
```# Usage
## Generics
EquationKit is fully generic and supports any number type conforming to the protocol [`NumberExpressible`](Sources/EquationKit/NumberExpressible/NumberExpressible.swift), Swift Foundation's `Int` and `Double` both conforms to said protocol. By conforming to `NumberExpressible` you can use EquationKit with e.g. excellent [attaswift/BigInt](https://github.com/attaswift/BigInt).You need only to `import EquationKitBigIntSupport`
We would like to use operator overloading, making it possible to write `x + y`, `x - 2`, `x*z² - y³` etc. Supporting operator overloading using generic `func + (lhs: Variable, rhs: N) -> PolynomialStruct` results in Swift compiler taking too long time to compile polynomials having over 3 terms (using Xcode 10 beta 6 at least). Thus EquationKit does not come bundled with any operator support at all. Instead, you chose your Number type yourself. If you don't need `BigInt` then `Double` is probably what you want, just `import EquationKitDoubleSupport` and you are good to go! It contains around 10 operators which are all 3 lines of code each.
## Variables
You write powers using the custom operator `x^^2`, but for powers between `2` and `9` you can use the [unicode superscript symbols](https://en.wikipedia.org/wiki/Unicode_subscripts_and_superscripts#Superscripts_and_subscripts_block) instead, like so:
```swift
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)
```## Advanced operators
You can use some of the advanced mathematical operators provided in the folder [MathematicalOperators](Sources/EquationKit/MathematicalOperators) to precisely express the mathematical constraints you might have.### Variable to Constant (evaluation)
Let's have a look at one of the simplest scenario:Using the special Unicode char `≔` (single character for `:=` often used in literature for `assignment` of value.) we can write evaluations as:
```swift
𝑦² - 𝑥³.evaluate() {[ x ≔ 1, y ≔ 2 ]}
```Instead of:
```swift
𝑦² - 𝑥³.evaluate() {[ x <- 1, y <- 2 ]}
```### Complex examples
Below is the example of how [`EllipticCurveKit`](https://github.com/Sajjon/EllipticCurveKit) uses `EquationKit` to express requirements on the elliptic curve parameters. Elliptic curves on the Weierstraß form requires this congruence inequality to hold:
```math
𝟜𝑎³ + 𝟚𝟟𝑏² ≢ 𝟘 mod 𝑝
```Thanks to `EquationKit` we can express said inequality almost identically to pure math in Swift:
```swift
𝟜𝑎³ + 𝟚𝟟𝑏² ≢ 0 % 𝑝
```But that is not enough since we also need to evaluate said inequality (polynomial) using the arguments passed in the initializer. We can of course write
```swift
(𝟜𝑎³ + 𝟚𝟟𝑏²).evaluate(modulus: 𝑝) {[ 𝑎 ≔ a, 𝑏 ≔ b ]} != 0
```But a slightly more "mathy" syntax would be:
```swift
𝟜𝑎³ + 𝟚𝟟𝑏² ≢ 𝟘 % 𝑝 ↤ [ 𝑎 ≔ a, 𝑏 ≔ b ]
```Which evaluates the polynomial `𝟜𝑎³ + 𝟚𝟟𝑏²` given `a` and `b` and performs modulo `𝑝` and compares it to `0`. We could, of course, add support for this syntax as well:
```swift
// This syntax is not yet supported, but can easily be added
[a→𝑎, b→𝑏] ⟼ 𝟜𝑎³ + 𝟚𝟟𝑏² ≢ 𝟘 % 𝑝
```We can of course also write this without using any special unicode char, like so:
```swift
4*a^^3 + 27*b^^2 =!%= 0 % p <-- [ a ≔ constA, b ≔ constB ]
```
where `=!%=` replaces `≢`.Please give feedback on the choice of operators, by [submitting an issue](https://github.com/Sajjon/EquationKit/issues/new).
```swift
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 = 𝑝
}
}
```## Supported
- Single and multivariate equations (no limitation to how many variables, go crazy!)
- Differentiate any single or multivariate equation with respect to some of its variables
- Multiply equations with equations
- Modulus
- BigInt support## Limitations
### Not supported, but on roadmap
- Substitution `(3*(4*x + 5)^^2 - 2*(4x+5) - 1).substitute() { z <~ (4*x + 5) }` // `3*z²-2*z-1`
- Division
- Finding roots (solving)### Not supported and not on the roadmap
- Variables in exponents, such as `2^x`
- `log`/`ln` functions
- Trigonometric functions (`sin`, `cos`, `tan` etc.)
- Complex numbers