Mathematics With Swift

The built-in support for Unicode variables and operators in Swift opens the door to some interesting experiments.

First, a quick implementation of numerical function integration.

// For more complex ideas around these subjects,
// https://github.com/mattt/Euler/blob/master/Euler.swift

import Foundation

let π : Double = .pi

typealias ScalarFunction = (Double) -> Double
typealias Trapezoidal = (Double, Double) -> Double

prefix operator 
prefix func  (array: [Double]) -> Double {
    var result = 0.0
    array.forEach { value in
        result += value
    }
    return result
}

let sum = [1, 2, 3, 5, 8, 13]

func ~= (left: Double, right: Double) -> Bool {
    let ε : Double = 0.001
    let δ = left - right
    return abs(δ) <= ε
}

// Function taken from the "fast numeric integral" example from
// http://www.codeproject.com/Articles/31550/Fast-Numerical-Integration
func f (x: Double) -> Double {
    return exp(-x / 5.0) * (2.0 + sin(2.0 * x))
}

// Trapezoidal rule adapted from
// http://www.numericmethod.com/About-numerical-methods/numerical-integration/trapezoidal-rule
prefix operator 
prefix func  (f: @escaping ScalarFunction) -> Trapezoidal {
    return { (min : Double, max : Double) -> (Double) in
        let steps = 50
        let h = abs(min - max) / Double(steps)
        var surfaces = [Double]()

        for position in 0 ..< steps {
            let x1 = min + Double(position) * h
            let x2 = x1  + h
            let y1 = f(x1)
            let y2 = f(x2)
            let s = (y1 + y2) * h / 2
            surfaces.append(s)
        }
        return surfaces
    }
}

let integral = (f) (0, 100)
let sinIntegral = sin
let curve1 = sinIntegral(0, π/2)
let curve2 = sinIntegral(0, π)
assert(curve1 ~= 1, "Almost 1")
assert(curve2 ~= 2, "Almost 2")

print("sum: \(sum)")
print("integral: \(integral)")
print("curve1: \(curve1)")
print("curve2: \(curve2)")

And here’s a small implementation of Set theory, leading to De Morgan’s Laws at the very bottom.

// Set operations taken from
// https://en.wikipedia.org/wiki/Set_(mathematics)
// Operator association groups taken from
// https://developer.apple.com/reference/swift/1851035-swift_standard_library_operators

// Typealias for the whole exercise
typealias MathSet = Set<AnyHashable>

// Required for the cartesian product, adapted from
// http://stackoverflow.com/a/37324570
struct Pair<T: Hashable, U: Hashable> : Hashable, CustomStringConvertible {
    let first : T
    let second: U

    var hashValue : Int {
        return first.hashValue &* 31 &+ second.hashValue
    }

    var description: String {
        return "\(first), \(second)"
    }

    public static func == (lhs: Pair, rhs: Pair) -> Bool {
        return lhs.first == rhs.first && lhs.second == rhs.second
    }
}

// The empty set
let Ø = MathSet()

// The "Universal" set
var U = MathSet()

// Creation operators
// Every time a new set is created, we add its contents to the
// universal set created above
prefix operator 
prefix func  (array: [AnyHashable]) -> MathSet {
    for obj in array {
        U.insert(obj)
    }
    return MathSet(array)
}

postfix operator 
postfix func  (array: [AnyHashable]) -> [AnyHashable] {
    return array
}

// Intersection
infix operator  : MultiplicationPrecedence
func  (s1: MathSet, s2: MathSet) -> MathSet {
    return s1.intersection(s2)
}

// Union
infix operator  : AdditionPrecedence
func  (s1: MathSet, s2: MathSet) -> MathSet {
    return s1.union(s2)
}

// Belongs
infix operator  : ComparisonPrecedence
func  (obj: Any, set: MathSet) -> Bool {
    return set.contains(obj as! AnyHashable)
}

// Does not belong
infix operator  : ComparisonPrecedence
func  (obj: Any, set: MathSet) -> Bool {
    return !(obj  set)
}

// Subset
infix operator  : ComparisonPrecedence
func  (s1: MathSet, s2: MathSet) -> Bool {
    return s1.isSubset(of: s2)
}

// Cardinality
prefix operator |
prefix func | (set: MathSet) -> Int {
    return set.count
}

postfix operator |
postfix func | (set: MathSet) -> MathSet {
    return set
}

// Relative complement
infix operator  : MultiplicationPrecedence
func  (s1: MathSet, s2: MathSet) -> MathSet {
    return s1.subtracting(s2)
}

// Absolute complement
postfix operator 
postfix func  (set: MathSet) -> MathSet {
    return U  set
}

// Symmetric difference
infix operator  : AdditionPrecedence
func  (s1: MathSet, s2: MathSet) -> MathSet {
    return s1.symmetricDifference(s2)
}

// Cartesian product
infix operator × : MultiplicationPrecedence
func × (s1: MathSet, s2: MathSet) -> MathSet {
    var result = Set<Pair<AnyHashable, AnyHashable>>()
    for obj1 in s1 {
        for obj2 in s2 {
            let pair = Pair(first: obj1, second: obj2)
            result.insert(pair)
        }
    }
    return result
}

let A = [1, "alpha", "beta", "gamma", 23, 23]
let B = ["omega", "gamma", "delta", 23, 63, 1, 1, 1]
let C = [1, "alpha"]
let D = ["Brazil", "Switzerland", "Austria"]

let intersection = A  B
let union = A  B
let isNotSubset = A  B
let isSubset = C  A
let cardinality = |A|
let subtracted = B  A
let complement = A
let symmetric = A  B
let product = A × B
let noAlpha = "alpha"  B
let yesAlpha = "alpha"  B

// Print the whole universe
print(U)

// Asserting some basic properties of sets
assert(A == A                      , "A set is equal to itself")
assert(A != B                      , "A set is not equal to others")
assert(A  B == B  A              , "Intersection is commutative")
assert(A  B == B  A              , "Union is commutative")
assert(A  A == A                  , "Union with itself is neutral")
assert(A  Ø == A                  , "The empty set is neutral in union")
assert((C  A) && (C  A) == A     , "Condition to be a subset")
assert((A  (A  B))               , "Condition of inclusion")
assert(A  A == Ø                  , "Removing a set from itself yields the empty set")
assert(A  U                       , "Any set is part of the Universal set")
assert(B  U                       , "Any set is part of the Universal set")
assert(C  U                       , "Any set is part of the Universal set")
assert(A  A == U                 , "The union of a set with its complementary yields the universal set")
assert(|(A × B)| == |A| * |B|      , "The number of items in a product set is equal to the product of the number of items")
assert(A × Ø == Ø                  , "The empty set is the absorbing element of the product")
assert(A × (B  C) == A × B  A × C, "Product is distributive")
assert(A × B  A × C == (A × B)  (A × C), "Associative laws are applied correctly")

// De Morgan's Laws
assert((A  B) == A  B         , "First law: the complement of A union B equals the complement of A intersected with the complement of B.")
assert((A  B) == A  B         , "Second law: the complement of A intersected with B is equal to the complement of A union to the complement of B.")