Draft another DSL for labeled polynomials. Add variance.
This commit is contained in:
parent
db19df4329
commit
3a91cb2579
@ -75,7 +75,7 @@ internal constructor(
|
||||
* @param A type of provided underlying ring of constants. It's [Ring] of [C].
|
||||
* @param ring underlying ring of constants of type [A].
|
||||
*/
|
||||
public class LabeledPolynomialSpace<C, A : Ring<C>>(
|
||||
public class LabeledPolynomialSpace<C, out A : Ring<C>>(
|
||||
public override val ring: A,
|
||||
) : MultivariatePolynomialSpace<C, Symbol, LabeledPolynomial<C>>, PolynomialSpaceOverRing<C, LabeledPolynomial<C>, A> {
|
||||
/**
|
||||
|
@ -60,7 +60,7 @@ public data class ListPolynomial<C>(
|
||||
* @param A type of provided underlying ring of constants. It's [Ring] of [C].
|
||||
* @param ring underlying ring of constants of type [A].
|
||||
*/
|
||||
public open class ListPolynomialSpace<C, A : Ring<C>>(
|
||||
public open class ListPolynomialSpace<C, out A : Ring<C>>(
|
||||
public override val ring: A,
|
||||
) : PolynomialSpaceOverRing<C, ListPolynomial<C>, A> {
|
||||
/**
|
||||
@ -366,7 +366,7 @@ public open class ListPolynomialSpace<C, A : Ring<C>>(
|
||||
* @param A type of underlying ring of constants. It's [Ring] of [C].
|
||||
* @param ring underlying ring of constants of type [A].
|
||||
*/
|
||||
public class ScalableListPolynomialSpace<C, A>(
|
||||
public class ScalableListPolynomialSpace<C, out A>(
|
||||
ring: A,
|
||||
) : ListPolynomialSpace<C, A>(ring), ScaleOperations<ListPolynomial<C>> where A : Ring<C>, A : ScaleOperations<C> {
|
||||
override fun scale(a: ListPolynomial<C>, value: Double): ListPolynomial<C> =
|
||||
|
@ -59,7 +59,7 @@ internal constructor(
|
||||
* @param A type of provided underlying ring of constants. It's [Ring] of [C].
|
||||
* @param ring underlying ring of constants of type [A].
|
||||
*/
|
||||
public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
||||
public class NumberedPolynomialSpace<C, out A : Ring<C>>(
|
||||
public override val ring: A,
|
||||
) : PolynomialSpaceOverRing<C, NumberedPolynomial<C>, A> {
|
||||
/**
|
||||
|
@ -252,7 +252,7 @@ public interface PolynomialSpace<C, P: Polynomial<C>> : Ring<P> {
|
||||
* @param A the type of algebraic structure (precisely, of ring) provided for constants.
|
||||
*/
|
||||
@Suppress("INAPPLICABLE_JVM_NAME") // FIXME: Waiting for KT-31420
|
||||
public interface PolynomialSpaceOverRing<C, P: Polynomial<C>, A: Ring<C>> : PolynomialSpace<C, P> {
|
||||
public interface PolynomialSpaceOverRing<C, P: Polynomial<C>, out A: Ring<C>> : PolynomialSpace<C, P> {
|
||||
|
||||
/**
|
||||
* Underlying ring of constants. Its operations on constants are inherited by local operations on constants.
|
||||
|
@ -464,7 +464,7 @@ public interface RationalFunctionSpaceOverRing<
|
||||
C,
|
||||
P: Polynomial<C>,
|
||||
R: RationalFunction<C, P>,
|
||||
A: Ring<C>
|
||||
out A: Ring<C>
|
||||
> : RationalFunctionSpace<C, P, R> {
|
||||
|
||||
/**
|
||||
@ -566,7 +566,7 @@ public interface RationalFunctionSpaceOverPolynomialSpace<
|
||||
C,
|
||||
P: Polynomial<C>,
|
||||
R: RationalFunction<C, P>,
|
||||
AP: PolynomialSpace<C, P>,
|
||||
out AP: PolynomialSpace<C, P>,
|
||||
> : RationalFunctionSpace<C, P, R> {
|
||||
|
||||
/**
|
||||
@ -1341,7 +1341,7 @@ public interface MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpac
|
||||
V,
|
||||
P: Polynomial<C>,
|
||||
R: RationalFunction<C, P>,
|
||||
AP: MultivariatePolynomialSpace<C, V, P>,
|
||||
out AP: MultivariatePolynomialSpace<C, V, P>,
|
||||
> : RationalFunctionSpaceOverPolynomialSpace<C, P, R, AP>, MultivariateRationalFunctionSpace<C, V, P, R> {
|
||||
/**
|
||||
* Returns sum of the variable represented as a monic monomial and the integer represented as a constant polynomial.
|
||||
|
@ -416,6 +416,261 @@ public inline fun <C, A: Ring<C>> LabeledPolynomialSpace<C, A>.LabeledPolynomial
|
||||
@UnstableKMathAPI
|
||||
public inline fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledPolynomialDSL1(initialCapacity: Int? = null, block: DSL1LabeledPolynomialBuilder<C>.() -> Unit) : LabeledPolynomial<C> = DSL1LabeledPolynomialBuilder({ left: C, right: C -> left + right }, initialCapacity).apply(block).build()
|
||||
|
||||
/**
|
||||
* Marks DSL that allows to more simply create [LabeledPolynomial]s with good performance.
|
||||
*
|
||||
* For example, polynomial \(5 a^2 c^3 - 6 b\) can be described as
|
||||
* ```
|
||||
* Int.algebra {
|
||||
* val numberedPolynomial : NumberedPolynomial<Int> = NumberedPolynomial {
|
||||
* 5 { a inPowerOf 2u; c inPowerOf 3u } // 5 a^2 c^3 +
|
||||
* (-6) { b inPowerOf 1u } // (-6) b^1
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* @usesMathJax
|
||||
*/
|
||||
@DslMarker
|
||||
@UnstableKMathAPI
|
||||
internal annotation class LabeledPolynomialBuilderDSL2
|
||||
|
||||
/**
|
||||
* Builder of [LabeledPolynomial]. It should be used as an implicit context for lambdas that describe [LabeledPolynomial].
|
||||
*/
|
||||
@UnstableKMathAPI
|
||||
@LabeledPolynomialBuilderDSL2
|
||||
public class DSL2LabeledPolynomialBuilder<C>(
|
||||
private val ring: Ring<C>,
|
||||
/**
|
||||
* Initial capacity of coefficients map.
|
||||
*/
|
||||
initialCapacity: Int? = null
|
||||
) {
|
||||
/**
|
||||
* Coefficients storage. Any declaration of any monomial updates the storage.
|
||||
* Afterward the storage will be used as a resulting coefficients map.
|
||||
*/
|
||||
private val coefficients: MutableMap<Map<Symbol, UInt>, C> = if (initialCapacity != null) LinkedHashMap(initialCapacity) else LinkedHashMap()
|
||||
|
||||
/**
|
||||
* Builds the resulting coefficients map.
|
||||
*
|
||||
* In fact, it just returns [coefficients] as regular coefficients map of type `Map<Map<Symbol, UInt>, C>`.
|
||||
*/
|
||||
@PublishedApi
|
||||
internal fun build(): LabeledPolynomial<C> = LabeledPolynomial<C>(coefficients)
|
||||
|
||||
public inner class Term internal constructor(
|
||||
internal val signature: Map<Symbol, UInt> = HashMap(),
|
||||
internal val coefficient: C
|
||||
)
|
||||
|
||||
private inline fun submit(signature: Map<Symbol, UInt>, onPut: Ring<C>.() -> C, onChange: Ring<C>.(C) -> C) {
|
||||
coefficients.putOrChange<_, C>(signature, { ring.onPut() }, { ring.onChange(it) })
|
||||
}
|
||||
|
||||
private inline fun submit(signature: Map<Symbol, UInt>, lazyCoefficient: Ring<C>.() -> C) {
|
||||
submit(signature, lazyCoefficient, { it + lazyCoefficient() })
|
||||
}
|
||||
|
||||
private fun submit(signature: Map<Symbol, UInt>, coefficient: C) {
|
||||
submit(signature) { coefficient }
|
||||
}
|
||||
|
||||
// TODO: `@submit` will be resolved differently. Change it to `@C`.
|
||||
private fun C.submit() = submit(emptyMap(), { this@submit })
|
||||
|
||||
private fun Symbol.submit() = submit(mapOf(this to 1u), { one })
|
||||
|
||||
private fun Term.submit(): Submit {
|
||||
submit(signature, coefficient)
|
||||
return Submit
|
||||
}
|
||||
|
||||
public object Submit
|
||||
|
||||
public operator fun C.unaryPlus(): Submit {
|
||||
submit()
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun C.unaryMinus(): Submit {
|
||||
submit(emptyMap(), { -this@unaryMinus }, { it - this@unaryMinus })
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun C.plus(other: C): Submit {
|
||||
submit(emptyMap(), { this@plus + other })
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun C.minus(other: C): Submit {
|
||||
submit(emptyMap(), { this@minus - other })
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun C.times(other: C): C = ring { this@times * other }
|
||||
|
||||
public operator fun C.plus(other: Symbol): Submit {
|
||||
submit(emptyMap(), this)
|
||||
submit(mapOf(other to 1u), ring.one)
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun C.minus(other: Symbol): Submit {
|
||||
submit(emptyMap(), this)
|
||||
submit(mapOf(other to 1u), { -one }, { it - one })
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun C.times(other: Symbol): Term = Term(mapOf(other to 1u), this)
|
||||
|
||||
public operator fun C.plus(other: Term): Submit {
|
||||
submit(emptyMap(), this)
|
||||
other.submit()
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun C.minus(other: Term): Submit {
|
||||
submit(emptyMap(), this)
|
||||
submit(other.signature, { -other.coefficient }, { it - other.coefficient })
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun C.times(other: Term): Term = Term(other.signature, ring { this@times * other.coefficient })
|
||||
|
||||
public operator fun Symbol.plus(other: C): Submit {
|
||||
this.submit()
|
||||
other.submit()
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Symbol.minus(other: C): Submit {
|
||||
this.submit()
|
||||
submit(emptyMap(), { -other }, { it - other })
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Symbol.times(other: C): Term = Term(mapOf(this to 1u), other)
|
||||
|
||||
public operator fun Symbol.unaryPlus(): Submit {
|
||||
this.submit()
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Symbol.unaryMinus(): Submit {
|
||||
submit(mapOf(this to 1u), { -one }, { it - one })
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Symbol.plus(other: Symbol): Submit {
|
||||
this.submit()
|
||||
other.submit()
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Symbol.minus(other: Symbol): Submit {
|
||||
this.submit()
|
||||
submit(mapOf(other to 1u), { -one }, { it - one })
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Symbol.times(other: Symbol): Term =
|
||||
if (this == other) Term(mapOf(this to 2u), ring.one)
|
||||
else Term(mapOf(this to 1u, other to 1u), ring.one)
|
||||
|
||||
public operator fun Symbol.plus(other: Term): Submit {
|
||||
this.submit()
|
||||
other.submit()
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Symbol.minus(other: Term): Submit {
|
||||
this.submit()
|
||||
submit(other.signature, { -other.coefficient }, { it - other.coefficient })
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Symbol.times(other: Term): Term =
|
||||
Term(
|
||||
other.signature.withPutOrChanged(this, 1u) { it -> it + 1u },
|
||||
other.coefficient
|
||||
)
|
||||
|
||||
public operator fun Term.plus(other: C): Submit {
|
||||
this.submit()
|
||||
other.submit()
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Term.minus(other: C): Submit {
|
||||
this.submit()
|
||||
submit(emptyMap(), { -other }, { it - other })
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Term.times(other: C): Term =
|
||||
Term(
|
||||
signature,
|
||||
ring { coefficient * other }
|
||||
)
|
||||
|
||||
public operator fun Term.plus(other: Symbol): Submit {
|
||||
this.submit()
|
||||
other.submit()
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Term.minus(other: Symbol): Submit {
|
||||
this.submit()
|
||||
submit(mapOf(other to 1u), { -one }, { it - one })
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Term.times(other: Symbol): Term =
|
||||
Term(
|
||||
signature.withPutOrChanged(other, 1u) { it -> it + 1u },
|
||||
coefficient
|
||||
)
|
||||
|
||||
public operator fun Term.unaryPlus(): Submit {
|
||||
this.submit()
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Term.unaryMinus(): Submit {
|
||||
submit(signature, { -coefficient }, { it - coefficient })
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Term.plus(other: Term): Submit {
|
||||
this.submit()
|
||||
other.submit()
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Term.minus(other: Term): Submit {
|
||||
this.submit()
|
||||
submit(other.signature, { -other.coefficient }, { it - other.coefficient })
|
||||
return Submit
|
||||
}
|
||||
|
||||
public operator fun Term.times(other: Term): Term =
|
||||
Term(
|
||||
mergeBy(signature, other.signature) { deg1, deg2 -> deg1 + deg2 },
|
||||
ring { coefficient * other.coefficient }
|
||||
)
|
||||
}
|
||||
|
||||
//@UnstableKMathAPI
|
||||
//public fun <C> Ring<C>.LabeledPolynomialDSL2(initialCapacity: Int? = null, block: DSL2LabeledPolynomialBuilder<C>.() -> Unit): LabeledPolynomial<C> = DSL2LabeledPolynomialBuilder(this, initialCapacity).apply(block).build()
|
||||
|
||||
@UnstableKMathAPI
|
||||
public fun <C, A: Ring<C>> LabeledPolynomialSpace<C, A>.LabeledPolynomialDSL2(initialCapacity: Int? = null, block: DSL2LabeledPolynomialBuilder<C>.() -> Unit): LabeledPolynomial<C> = DSL2LabeledPolynomialBuilder(ring, initialCapacity).apply(block).build()
|
||||
|
||||
@UnstableKMathAPI
|
||||
public fun <C, A: Ring<C>> LabeledRationalFunctionSpace<C, A>.LabeledPolynomialDSL2(initialCapacity: Int? = null, block: DSL2LabeledPolynomialBuilder<C>.() -> Unit): LabeledPolynomial<C> = DSL2LabeledPolynomialBuilder(ring, initialCapacity).apply(block).build()
|
||||
|
||||
// Waiting for context receivers :( FIXME: Replace with context receivers when they will be available
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user