Skip to content

Commit

Permalink
Desperate attempts at getting a vector space algebra context working.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikael Vejdemo-Johansson committed Feb 22, 2024
1 parent bf84601 commit 7bb0a20
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 20 deletions.
31 changes: 16 additions & 15 deletions src/commonMain/kotlin/org/appliedtopology/tda4j/Chain.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.appliedtopology.tda4j

import arrow.core.padZip
import space.kscience.kmath.operations.Group

public open class Chain<VertexT, CoefficientT> protected constructor(
public val vertexComparator: Comparator<VertexT>,
Expand Down Expand Up @@ -63,7 +62,8 @@ public class ChainContext<VertexT, CoefficientT> protected constructor(
vertexComparator: Comparator<VertexT>,
public val coefficientContext: FieldContext<CoefficientT>,
) :
Group<Chain<VertexT, CoefficientT>>,
FieldContext<CoefficientT> by coefficientContext,
VectorSpaceContext<CoefficientT, Chain<VertexT, CoefficientT>>,
SimplexContext<VertexT>(vertexComparator) {
public fun Chain<VertexT, CoefficientT>.zipToChain(
other: Chain<VertexT, CoefficientT>,
Expand All @@ -83,26 +83,27 @@ public class ChainContext<VertexT, CoefficientT> protected constructor(
return(Chain(this.vertexComparator, this.simplexComparator, retmap))
}

override val zero: Chain<VertexT, CoefficientT>
override val origin: Chain<VertexT, CoefficientT>
get() = Chain(vertexComparator, SimplexComparator(vertexComparator))

override fun Chain<VertexT, CoefficientT>.unaryMinus(): Chain<VertexT, CoefficientT> =
override fun vectorScale(
scalar: CoefficientT,
vector: Chain<VertexT, CoefficientT>,
): Chain<VertexT, CoefficientT> =
with(coefficientContext) {
vector.mapToChain { scalar * it }
}

override fun vectorNegate(v: Chain<VertexT, CoefficientT>): Chain<VertexT, CoefficientT> =
with(coefficientContext) {
this@unaryMinus.mapToChain { -it }
v.mapToChain { -it }
}

override fun add(
override fun vectorAdd(
left: Chain<VertexT, CoefficientT>,
right: Chain<VertexT, CoefficientT>,
): Chain<VertexT, CoefficientT> = left.zipToChain(right, coefficientContext::add)

public operator fun CoefficientT.times(other: Chain<VertexT, CoefficientT>): Chain<VertexT, CoefficientT> =
other.mapToChain {
with(coefficientContext) {
this@times * it
}
}

public operator fun CoefficientT.times(other: AbstractSimplex<VertexT>): Chain<VertexT, CoefficientT> = this@times * Chain(other)

public fun AbstractSimplex<VertexT>.plus(other: Chain<VertexT, CoefficientT>): Chain<VertexT, CoefficientT> =
Expand Down Expand Up @@ -133,8 +134,8 @@ public class ChainContext<VertexT, CoefficientT> protected constructor(
public val Chain<VertexT, CoefficientT>.boundary: Chain<VertexT, CoefficientT>
get() =
this.chainMap.map { (simplex, coeff) ->
coeff * simplex.boundary
}.fold(zero, ::add)
vectorScale(coeff, simplex.boundary)
}.fold(origin, ::vectorAdd)

public val emptyChain: Chain<VertexT, CoefficientT> =
Chain(
Expand Down
96 changes: 91 additions & 5 deletions src/commonMain/kotlin/org/appliedtopology/tda4j/Field.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,55 @@
package org.appliedtopology.tda4j

import space.kscience.kmath.operations.FieldOps
import space.kscience.kmath.operations.NumericAlgebra
import space.kscience.kmath.operations.Ring
import kotlin.math.abs
import kotlin.math.ulp

public interface Equality<T> {
public infix fun T.eq(other: Any?): Boolean
}

public interface FieldContext<CoefficientT> :
Ring<CoefficientT>, FieldOps<CoefficientT>, NumericAlgebra<CoefficientT>, Equality<CoefficientT>
public interface FieldContext<CoefficientT> : Equality<CoefficientT> {
public val zero: CoefficientT
public val one: CoefficientT

public fun number(x: Number): CoefficientT

public fun add(
left: CoefficientT,
right: CoefficientT,
): CoefficientT

public fun subtract(
left: CoefficientT,
right: CoefficientT,
): CoefficientT = add(left, negate(right))

public fun negate(x: CoefficientT): CoefficientT = subtract(zero, x)

public fun multiply(
left: CoefficientT,
right: CoefficientT,
): CoefficientT

public fun divide(
left: CoefficientT,
right: CoefficientT,
): CoefficientT = multiply(left, inverse(right))

public fun inverse(x: CoefficientT): CoefficientT = divide(one, x)

// Operator overloads
public operator fun CoefficientT.unaryPlus(): CoefficientT = this@unaryPlus

public operator fun CoefficientT.unaryMinus(): CoefficientT = negate(this@unaryMinus)

public operator fun CoefficientT.plus(other: CoefficientT): CoefficientT = add(this@plus, other)

public operator fun CoefficientT.minus(other: CoefficientT): CoefficientT = subtract(this@minus, other)

public operator fun CoefficientT.times(other: CoefficientT): CoefficientT = multiply(this@times, other)

public operator fun CoefficientT.div(other: CoefficientT): CoefficientT = divide(this@div, other)
}

public object DoubleContext : FieldContext<Double> {
override fun divide(
Expand Down Expand Up @@ -45,3 +83,51 @@ public object DoubleContext : FieldContext<Double> {
false
}
}

/**
* A context interface for simultaneously defining a `Field` of one type (`FieldT`) and a
* `Group`of another type (`GroupT`) connected by scalar multiplication.
*
* The contract of this interface expects associativity, commutativity and distributivity
* of all operations.
*
* To avoid ambiguities, the additive unit of the group part is named `origin`, with inspiration
* from the geometry of vector spaces.
*
* A minimal implementation will override `origin`, `add`, `scale` and one of `negate` or `subtract`.
*/
public interface VectorSpaceContext<FieldT, VectorT> : FieldContext<FieldT> {
// A module has addition, subtraction, unit, scalar multiplication

public val origin: VectorT

public fun vectorAdd(
left: VectorT,
right: VectorT,
): VectorT

public fun vectorNegate(v: VectorT): VectorT = vectorSubtract(origin, v)

public fun vectorSubtract(
left: VectorT,
right: VectorT,
): VectorT = vectorAdd(left, vectorNegate(right))

public fun vectorScale(
scalar: FieldT,
vector: VectorT,
): VectorT

// Type extension operators to enable all these within a context block
public operator fun VectorT.unaryPlus(): VectorT = this@unaryPlus

public operator fun VectorT.unaryMinus(): VectorT = vectorNegate(this@unaryMinus)

public operator fun VectorT.plus(other: VectorT): VectorT = vectorAdd(this@plus, other)

public operator fun VectorT.minus(other: VectorT): VectorT = vectorSubtract(this@minus, other)

public operator fun FieldT.times(other: VectorT): VectorT = vectorScale(this@times, other)

public operator fun VectorT.times(other: FieldT): VectorT = vectorScale(other, this@times)
}

0 comments on commit 7bb0a20

Please sign in to comment.