Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save pauljohanneskraft/05b8ccace00beb628485d5627fd98cd3 to your computer and use it in GitHub Desktop.
Save pauljohanneskraft/05b8ccace00beb628485d5627fd98cd3 to your computer and use it in GitHub Desktop.
A try to model group-like algebraic structures

Modelling group-like algebraic structures

Magma

Requirements: The given operation is closed under the given set.

Semigroup

Requirements: is a Magma, operation is associative. (a • b) • c == a • (b • c)

Monoid

Requirements: is a Semigroup, has neutral element 0. (a • 0) == a

Group

Requirements: is a Monoid, has an inverse element -a for every element in set. (a • -a) == 0

Abelian Group

Requirements: is a Group, operation is commutative. (a • b) = (b • a)

GroupLike

struct, in which the strictest possible group-like structure can be instantiated from, based on the requirements the structure meets.

import Foundation
struct GroupLike<Element where Element : Hashable, Element: Comparable> : SemigroupProtocol, Commutative {
init(set: Set<Element>, op: (Element,Element) -> Element, neutralElement: Element? = nil, inv: ((Element) -> Element)? = nil, sign: Character = "•") {
self.set = set
self.op = op
self.neutralElement = neutralElement
self.inv = inv
self.sign = sign
}
let set : Set<Element>
let op : (Element, Element) -> Element
let eq : (Element, Element) -> Bool = { $0 == $1 }
let neutralElement : Element?
let inv : ((Element) -> Element)?
let sign : Character
var strictestType : Any? {
switch test() {
case ( false , _ , _ , _ , _ ): return nil
case ( true , false , _ , _ , _ ): return try! Magma(self)
case ( true , true , false , _ , _ ): return try! Semigroup(self)
case ( true , true , true , false , _ ): return try! Monoid(self)
case ( true , true , true , true , false ): return try! Group(self)
case ( true , true , true , true , true ): return try! AbelianGroup(self)
}
}
var possibleTypes : (magma: Magma<Element>?, semigroup: Semigroup<Element>?, monoid: Monoid<Element>?, group: Group<Element>?, abelianGroup: AbelianGroup<Element>?) {
return (try? Magma(self), try? Semigroup(self), try? Monoid(self), try? Group(self), try? AbelianGroup(self))
}
func test() -> (closed: Bool, associative: Bool, neutralElement: Bool, invertible: Bool, commutative: Bool) {
return (testClosure(), testAssociative(), testNeutralElement(), testInverse(), testCommutative())
}
func testNeutralElement() -> Bool {
if neutralElement == nil { return false }
for u in set { if !testNeutralElement(u) { return false } }
return true
}
private func testNeutralElement(_ u: Element) -> Bool {
return eq(op(u, neutralElement!), u)
}
func testInverse() -> Bool {
if neutralElement == nil || inv == nil { return false }
for u in set { if !testInverse(u) { return false } }
return true
}
private func testInverse(_ u: Element) -> Bool {
return eq(op(inv!(u), u), neutralElement!)
// return (!u • u) == neutralElement
}
}
struct Magma<Element where Element : Hashable, Element: Comparable> : MagmaProtocol {
init(set: Set<Element>, op: (Element, Element) -> Element, sign: Character = "•") throws {
self.set = set
self.op = op
self.sign = sign
if test() != true {
throw GroupLikeError.TypeNotMatching
}
}
init(_ groupLike: GroupLike<Element>) throws {
self.set = groupLike.set
self.op = groupLike.op
self.sign = groupLike.sign
if test() != true {
throw GroupLikeError.TypeNotMatching
}
}
let set : Set<Element>
let op : (Element, Element) -> Element
var eq : (Element, Element) -> Bool = { $0 == $1 }
let sign : Character
}
struct Semigroup<Element where Element : Hashable, Element: Comparable> : SemigroupProtocol {
init(set: Set<Element>, op: (Element, Element) -> Element, sign: Character = "•") throws {
self.set = set
self.op = op
self.sign = sign
if test() != (true, true) {
throw GroupLikeError.TypeNotMatching
}
}
init(_ groupLike: GroupLike<Element>) throws {
self.set = groupLike.set
self.op = groupLike.op
self.sign = groupLike.sign
if test() != (true, true) {
throw GroupLikeError.TypeNotMatching
}
}
let set : Set<Element>
let op : (Element, Element) -> Element
var eq : (Element, Element) -> Bool = { $0 == $1 }
let sign : Character
}
struct Monoid<Element where Element : Hashable, Element: Comparable> : MonoidProtocol {
init(set: Set<Element>, op: (Element, Element) -> Element, neutralElement: Element, sign: Character = "•") throws {
self.set = set
self.op = op
self.neutralElement = neutralElement
self.sign = sign
if test() != (true, true, true) {
throw GroupLikeError.TypeNotMatching
}
}
init(_ groupLike: GroupLike<Element>) throws {
self.set = groupLike.set
self.op = groupLike.op
self.neutralElement = groupLike.neutralElement!
self.sign = groupLike.sign
if test() != (true, true,true) {
throw GroupLikeError.TypeNotMatching
}
}
let set : Set<Element>
let op : (Element, Element) -> Element
let eq : (Element, Element) -> Bool = { $0 == $1 }
let neutralElement : Element
let sign : Character
}
struct Group<Element where Element : Hashable, Element: Comparable> : GroupProtocol {
init(set: Set<Element>, op: (Element, Element) -> Element, neutralElement: Element, inv: (Element) -> Element, sign: Character = "•") throws {
self.set = set
self.op = op
self.neutralElement = neutralElement
self.inv = inv
self.sign = sign
if test() != (true, true, true, true) {
throw GroupLikeError.TypeNotMatching
}
}
init(_ groupLike: GroupLike<Element>) throws {
self.set = groupLike.set
self.op = groupLike.op
self.neutralElement = groupLike.neutralElement!
self.inv = groupLike.inv!
self.sign = groupLike.sign
if test() != (true, true,true, true) {
throw GroupLikeError.TypeNotMatching
}
}
let set : Set<Element>
let op : (Element, Element) -> Element
let eq : (Element, Element) -> Bool = { $0 == $1 }
let neutralElement : Element
let inv : (Element) -> Element
let sign : Character
}
struct AbelianGroup<Element where Element : Hashable, Element: Comparable> : AbelianGroupProtocol {
init(set: Set<Element>, op: (Element, Element) -> Element, neutralElement: Element, inv: (Element) -> Element, sign: Character = "•") throws {
self.set = set
self.op = op
self.neutralElement = neutralElement
self.inv = inv
self.sign = sign
if test() != (true, true, true, true, true) {
throw GroupLikeError.TypeNotMatching
}
}
init(_ groupLike: GroupLike<Element>) throws {
self.set = groupLike.set
self.op = groupLike.op
self.neutralElement = groupLike.neutralElement!
self.inv = groupLike.inv!
self.sign = groupLike.sign
if test() != (true, true,true, true, true) {
throw GroupLikeError.TypeNotMatching
}
}
let set : Set<Element>
let op : (Element, Element) -> Element
let eq : (Element, Element) -> Bool = { $0 == $1 }
let neutralElement : Element
let inv : (Element) -> Element
let sign : Character
}
protocol MagmaProtocol : CustomStringConvertible {
associatedtype Element : Hashable, Equatable, Comparable
var set : Set<Element> { get }
var op : (Element, Element) -> Element { get }
var sign : Character { get }
var eq : (Element, Element) -> Bool { get }
var description : String { get }
}
extension MagmaProtocol {
var description: String {
return "\(Self.self) ⟨ \(set.sorted()), \(sign) ⟩"
}
func test() -> Bool {
return testClosure()
}
func testClosure() -> Bool {
for u in set { for v in set { if !testClosure(u,v) { return false } } }
return true
}
func testClosure(_ u: Element, _ v: Element) -> Bool {
return set.contains(op(u,v))
}
}
/*
func == <T: MagmaProtocol>(left: T.Element, right: T.Element) -> Bool { return T.eq(left, right) }
infix operator • {}
func • <T: MagmaProtocol>(left: T.Element, right: T.Element) -> T.Element { return T.op(left, right) }
*/
internal protocol Commutative : MagmaProtocol {}
extension Commutative {
func testCommutative() -> Bool {
for u in set { for v in set { if !testCommutative(u,v) { return false } } }
// \forall u,v \in Set : (u • v) = (v • u)
return true
}
func testCommutative(_ u: Element, _ v: Element) -> Bool {
let a = op(v,u)
let b = op(u,v)
return eq(a, b)
}
}
internal protocol hasNeutralElement : MagmaProtocol {
var neutralElement : Element { get }
}
extension hasNeutralElement {
func testNeutralElement() -> Bool {
for u in set { if !testNeutralElement(u) { return false } }
return true
}
func testNeutralElement(_ u: Element) -> Bool {
return eq(op(u, neutralElement), u)
}
}
// prefix func ! <T: Invertible> (element: T.Element) -> T.Element { return T.inverse(element) }
internal protocol Invertible : MagmaProtocol, hasNeutralElement {
var inv : (Element) -> Element { get }
}
extension Invertible {
func testInverse() -> Bool {
for u in set { if !testInverse(u) { return false } }
return true
}
func testInverse(_ u: Element) -> Bool {
return eq(op(inv(u), u), neutralElement)
// return (!u • u) == neutralElement
}
}
internal protocol Idempotent : MagmaProtocol {}
extension Idempotent { // • is idempotent
func testIdempotent() -> Bool {
for u in set { if !testIdempotent(u) { return false } }
return true
}
func testIdempotent(_ u: Element) -> Bool {
return eq(op(u,u), u) // return (u • u) == u
}
}
internal protocol Associative : MagmaProtocol {}
extension Associative {
func testAssociative() -> Bool {
for u in set { for v in set { for w in set { if !testAssociative(u,v,w) { return false } } } }
// \forall u,v,w \in Set : ((u • v) • w) = (u • (v • w))
return true
}
func testAssociative(_ u: Element, _ v: Element, _ w: Element) -> Bool {
return eq(op(op(u,v), w), op(u, op(v,w))) // return ((u • v) • w) == (u • (v • w))
}
}
protocol SemigroupProtocol : MagmaProtocol, Associative {}
extension SemigroupProtocol {
func test() -> (closed: Bool, associative: Bool) {
return (testClosure(), testAssociative())
}
}
protocol MonoidProtocol : SemigroupProtocol, hasNeutralElement {}
extension MonoidProtocol {
func test() -> (closed: Bool, associative: Bool, neutralElement: Bool) {
return (testClosure(), testAssociative(), testNeutralElement())
}
}
protocol GroupProtocol : MonoidProtocol, Invertible {}
extension GroupProtocol {
func test() -> (closed: Bool, associative: Bool, neutralElement: Bool, invertible: Bool) {
return (testClosure(), testAssociative(), testNeutralElement(), testInverse())
}
}
protocol AbelianGroupProtocol : GroupProtocol, Commutative {}
extension AbelianGroupProtocol {
func test() -> (closed: Bool, associative: Bool, neutralElement: Bool, invertible: Bool, commutative: Bool) {
return (testClosure(), testAssociative(), testNeutralElement(), testInverse(), testCommutative())
}
}
protocol SemilatticeProtocol : SemigroupProtocol, Commutative, Idempotent {}
extension SemilatticeProtocol {
func test() -> (closed: Bool, associative: Bool, commutative: Bool, idempotent: Bool) {
return (testClosure(), testAssociative(), testCommutative(), testIdempotent())
}
}
protocol LatinSquareRule {}
// Latin Square Rule
// Each element of the set occurs exactly once in each row and exactly once in each column of the quasigroup's multiplication table
protocol QuasiGroupProtocol : MagmaProtocol, LatinSquareRule {}
extension QuasiGroupProtocol {}
protocol LoopProtocol : QuasiGroupProtocol, hasNeutralElement {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment