Showing:

0

38

2yrs ago

2

0

# EquationKit

## Write equations in pure Swift, differentiate and/or evaluate them.

``````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＇ = polynomial.differentiateWithRespectTo(x)
print(y＇) // 42x + 8y - 50
y＇.evaluate() {[ x <- 1, y <- 1 ]} // 0

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

# Installation

## Swift Package Manager

``````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`, 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.

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 + <N: NumberExpressible>(lhs: Variable, rhs: N) -> PolynomialStruct<N>` 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 instead, like so:

``````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)
``````

You can use some of the advanced mathematical operators provided in the folder 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:

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

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

### Complex examples

Below is the example of how `EllipticCurveKit` uses `EquationKit` to express requirements on the elliptic curve parameters. Elliptic curves on the Weierstraß form requires this congruence inequality to hold:

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

Thanks to `EquationKit` we can express said inequality almost identically to pure math in 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

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

But a slightly more "mathy" syntax would be:

``````𝟜𝑎³ + 𝟚𝟟𝑏² ≢ 𝟘 % 𝑝 ↤ [ 𝑎 ≔ 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:

``````// 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:

``````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.

``````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

## Rate & Review

Great Documentation0
Easy to Use0
Performant0
Highly Customizable0
Bleeding Edge0
Responsive Maintainers0
Poor Documentation0
Hard to Use0
Slow0
Buggy0
Abandoned0
Unwelcoming Community0
100