Skip to content

Commit d41a752

Browse files
committed
Add algebra to all consumers and producers
1 parent 9df4318 commit d41a752

File tree

10 files changed

+114
-59
lines changed

10 files changed

+114
-59
lines changed

controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/models/continuous/ContinuousBuffer.kt

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import kotlin.time.Duration.Companion.seconds
1414
* @param U The unit of measurement associated with the buffer contents.
1515
* @param T The amount type representing the measurable quantity stored in the buffer.
1616
* @param context The simulation context in which the buffer operates.
17-
* @param algebra The algebraic operations to manipulate the amount type.
17+
* @param consumerAlgebra The algebraic operations to manipulate the amount type.
1818
* @param bufferCapacity The maximum capacity of the buffer as a device state.
1919
* @param supplyRequest A device state representing the amount requested to be added to the buffer.
2020
* @param consumerRequest A device state representing the amount requested to be consumed from the buffer.
@@ -26,14 +26,16 @@ import kotlin.time.Duration.Companion.seconds
2626
*/
2727
public class ContinuousBuffer<U : UnitsOfMeasurement, T : Amount<U>>(
2828
context: Context,
29-
public val algebra: AmountAlgebra<U, T>,
29+
override val consumerAlgebra: AmountAlgebra<U, T>,
3030
public val bufferCapacity: DeviceState<Numeric<U>>,
31-
override val supplyRequest: LateBindDeviceState<T> = LateBindDeviceState( algebra.zero),
32-
override val consumerRequest: LateBindDeviceState<Numeric<U>> = LateBindDeviceState( Numeric.zero()),
33-
initialLevel: T = algebra.zero,
31+
override val supplyRequest: LateBindDeviceState<T> = LateBindDeviceState(consumerAlgebra.zero),
32+
override val consumerRequest: LateBindDeviceState<Numeric<U>> = LateBindDeviceState(Numeric.zero()),
33+
initialLevel: T = consumerAlgebra.zero,
3434
timeStep: Duration = 1.seconds
3535
) : ModelConstructor(context), ContinuousProducerInterface<U, T>, ContinuousConsumerInterface<U, T> {
3636

37+
override val producerAlgebra: AmountAlgebra<U, T> get() = consumerAlgebra
38+
3739
private val _content: MutableDeviceState<T> = MutableDeviceState(initialLevel)
3840

3941
public val content: DeviceState<T> get() = _content
@@ -49,7 +51,7 @@ public class ContinuousBuffer<U : UnitsOfMeasurement, T : Amount<U>>(
4951
supplyRequest,
5052
content
5153
) { supplyRequest: T, content: T ->
52-
with(algebra) {
54+
with(consumerAlgebra) {
5355
supplyRequest + content
5456
}
5557
}
@@ -59,7 +61,7 @@ public class ContinuousBuffer<U : UnitsOfMeasurement, T : Amount<U>>(
5961
content,
6062
consumerRequest
6163
) { supplyRequest, content, consumeRequest ->
62-
with(algebra) {
64+
with(consumerAlgebra) {
6365
val productionCapacity = supplyRequest + content
6466
productionCapacity.coerceValueIn(Numeric.zero<U>()..consumeRequest)
6567
}
@@ -79,7 +81,7 @@ public class ContinuousBuffer<U : UnitsOfMeasurement, T : Amount<U>>(
7981
content,
8082
consumerRequest
8183
) { supplyRequest: T, bufferCapacity, content, consumationRequest ->
82-
with(algebra) {
84+
with(consumerAlgebra) {
8385
val remainingSpace = bufferCapacity - Numeric<U>(content.value)
8486
val consumationCapacity = remainingSpace + consumationRequest
8587
supplyRequest.coerceValueIn(Numeric.zero<U>()..consumationCapacity)
@@ -91,7 +93,7 @@ public class ContinuousBuffer<U : UnitsOfMeasurement, T : Amount<U>>(
9193
reads = listOf(production, consumation, bufferCapacity),
9294
writes = listOf(content)
9395
) { prev, next ->
94-
with(algebra) {
96+
with(consumerAlgebra) {
9597
delay(timeStep)
9698

9799
val delta = consumation.value - production.value
@@ -132,7 +134,7 @@ public fun <U : UnitsOfMeasurement, T : Amount<U>> ContinuousFlowModel.buffer(
132134
): ContinuousBuffer<U, T> = model(
133135
ContinuousBuffer(
134136
context = context,
135-
algebra = algebra,
137+
consumerAlgebra = algebra,
136138
bufferCapacity = DeviceState(bufferCapacity),
137139
initialLevel = initialLevel,
138140
timeStep = timeStep

controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/models/continuous/ContinuousConsumer.kt

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,19 @@ import space.kscience.controls.constructor.units.*
55
import space.kscience.dataforge.context.Context
66

77
public interface ContinuousConsumerInterface<U : UnitsOfMeasurement, T : Amount<U>> {
8+
public val consumerAlgebra: AmountAlgebra<U, T>
9+
810
public val consumation: DeviceState<T>
911
public val consumationCapacity: DeviceState<Numeric<U>>
1012
public val supplyRequest: LateBindDeviceState<T>
1113
}
1214

1315
public interface ContinuousConsumerWrapper<U : UnitsOfMeasurement, T : Amount<U>> : ContinuousConsumerInterface<U, T> {
1416
public val consumer: ContinuousConsumerInterface<U, T>
17+
18+
override val consumerAlgebra: AmountAlgebra<U, T> get() = consumer.consumerAlgebra
19+
20+
1521
override val consumation: DeviceState<T> get() = consumer.consumation
1622
override val consumationCapacity: DeviceState<Numeric<U>> get() = consumer.consumationCapacity
1723
override val supplyRequest: LateBindDeviceState<T> get() = consumer.supplyRequest
@@ -45,11 +51,11 @@ public fun <U : UnitsOfMeasurement, T : Amount<U>> ContinuousConsumerInterface<U
4551
*/
4652
public class ContinuousConsumer<U : UnitsOfMeasurement, T : Amount<U>>(
4753
context: Context,
48-
public val algebra: AmountAlgebra<U, T>,
54+
override val consumerAlgebra: AmountAlgebra<U, T>,
4955
override val consumationCapacity: DeviceState<Numeric<U>>,
5056
) : ModelConstructor(context), ContinuousConsumerInterface<U, T> {
5157

52-
override val supplyRequest: LateBindDeviceState<T> = LateBindDeviceState(algebra.zero)
58+
override val supplyRequest: LateBindDeviceState<T> = LateBindDeviceState(consumerAlgebra.zero)
5359

5460
init {
5561
registerState(consumationCapacity)
@@ -60,7 +66,7 @@ public class ContinuousConsumer<U : UnitsOfMeasurement, T : Amount<U>>(
6066
supplyRequest,
6167
consumationCapacity
6268
) { request, capacity ->
63-
with(algebra) {
69+
with(consumerAlgebra) {
6470
request.coerceValueIn(Numeric.zero<U>()..capacity)
6571
}
6672
}
@@ -69,7 +75,7 @@ public class ContinuousConsumer<U : UnitsOfMeasurement, T : Amount<U>>(
6975
supplyRequest,
7076
consumationCapacity
7177
) { request, capacity ->
72-
with(algebra) {
78+
with(consumerAlgebra) {
7379
val consumation = request.coerceValueIn(Numeric.zero<U>()..capacity)
7480
consumation.value / capacity.value
7581
}

controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/models/continuous/ContinuousMix.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@ public enum class JoinManagementStrategy {
2727
*/
2828
public class ContinuousMix<U : UnitsOfMeasurement, T : Amount<U>>(
2929
context: Context,
30-
public val algebra: AmountAlgebra<U, T>,
30+
override val producerAlgebra: AmountAlgebra<U, T>,
3131
public val supplyKeys: Collection<String>,
3232
private val joinManagementStrategy: JoinManagementStrategy = JoinManagementStrategy.PROPORTIONAL,
3333
) : ModelConstructor(context), ContinuousProducerInterface<U, T> {
3434

35-
override val consumerRequest: LateBindDeviceState<Numeric<U>> = LateBindDeviceState( Numeric.zero())
35+
override val consumerRequest: LateBindDeviceState<Numeric<U>> = LateBindDeviceState(Numeric.zero())
3636

3737

3838
public val supplyRequest: Map<String, LateBindDeviceState<T>> = supplyKeys.associateWith {
39-
LateBindDeviceState( algebra.zero)
39+
LateBindDeviceState(producerAlgebra.zero)
4040
}
4141

4242

@@ -55,7 +55,7 @@ public class ContinuousMix<U : UnitsOfMeasurement, T : Amount<U>>(
5555
consumerRequest, jointSupplyRequest
5656
) { consumerRequest, supplyRequest: Map<String, T> ->
5757

58-
with(algebra) {
58+
with(producerAlgebra) {
5959
val totalInput: T = sum(supplyRequest.values)
6060
val totalOutput: Numeric<U> = consumerRequest
6161

@@ -98,11 +98,11 @@ public class ContinuousMix<U : UnitsOfMeasurement, T : Amount<U>>(
9898
}
9999

100100
override val productionCapacity: DeviceState<T> = mapState(jointSupplyRequest) { supply: Map<String, T> ->
101-
algebra.sum(supply.values)
101+
producerAlgebra.sum(supply.values)
102102
}
103103

104104
override val production: DeviceState<T> = mapState(consumation) { consume ->
105-
algebra.sum(consume.values)
105+
producerAlgebra.sum(consume.values)
106106
}
107107

108108

@@ -141,6 +141,8 @@ public fun <U : UnitsOfMeasurement, T : Amount<U>> ContinuousMix<U, T>.asConsume
141141
val consumation = individualConsumation[key]!!
142142

143143
object : ContinuousConsumerInterface<U, T> {
144+
override val consumerAlgebra: AmountAlgebra<U, T> get() = this@asConsumer.producerAlgebra
145+
144146
override val consumation: DeviceState<T> get() = consumation
145147
override val consumationCapacity: DeviceState<Numeric<U>> get() = consumation.asNumeric()
146148
override val supplyRequest: LateBindDeviceState<T> get() = input
@@ -165,11 +167,11 @@ public fun <U : UnitsOfMeasurement, T : Amount<U>> ContinuousMix<U, T>.connectPr
165167
public fun <U : UnitsOfMeasurement, T : Amount<U>> ContinuousMix(
166168
producers: Map<String, ContinuousProducer<U, T>>,
167169
consumer: ContinuousConsumer<U, T>,
168-
algebra: AmountAlgebra<U, T> = consumer.algebra,
170+
algebra: AmountAlgebra<U, T> = consumer.consumerAlgebra,
169171
context: Context = producers.values.first().context,
170172
): ContinuousMix<U, T> = ContinuousMix<U, T>(
171173
context = context,
172-
algebra = algebra,
174+
producerAlgebra = algebra,
173175
supplyKeys = producers.keys
174176
).also { join ->
175177
join.connectConsumer(consumer)

controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/models/continuous/ContinuousProducer.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import space.kscience.controls.constructor.units.*
55
import space.kscience.dataforge.context.Context
66

77
public interface ContinuousProducerInterface<U : UnitsOfMeasurement, T : Amount<U>> {
8+
public val producerAlgebra: AmountAlgebra<U, T>
9+
810
public val production: DeviceState<T>
911
public val productionCapacity: DeviceState<T>
1012
public val consumerRequest: LateBindDeviceState<Numeric<U>>
@@ -13,6 +15,8 @@ public interface ContinuousProducerInterface<U : UnitsOfMeasurement, T : Amount<
1315
public interface ContinuousProducerWrapper<U : UnitsOfMeasurement, T : Amount<U>> : ContinuousProducerInterface<U, T> {
1416
public val producer: ContinuousProducerInterface<U, T>
1517

18+
override val producerAlgebra: AmountAlgebra<U, T> get() = producer.producerAlgebra
19+
1620
override val production: DeviceState<T> get() = producer.production
1721
override val productionCapacity: DeviceState<T> get() = producer.productionCapacity
1822
override val consumerRequest: LateBindDeviceState<Numeric<U>> get() = producer.consumerRequest
@@ -48,7 +52,7 @@ public fun <U : UnitsOfMeasurement, T : Amount<U>> ContinuousProducerInterface<U
4852
*/
4953
public class ContinuousProducer<U : UnitsOfMeasurement, T : Amount<U>>(
5054
context: Context,
51-
public val algebra: AmountAlgebra<U, T>,
55+
override val producerAlgebra: AmountAlgebra<U, T>,
5256
override val productionCapacity: DeviceState<T>,
5357
override val consumerRequest: LateBindDeviceState<Numeric<U>> = LateBindDeviceState(Numeric.zero()),
5458
) : ModelConstructor(context), ContinuousProducerInterface<U, T> {
@@ -62,7 +66,7 @@ public class ContinuousProducer<U : UnitsOfMeasurement, T : Amount<U>>(
6266
first = consumerRequest,
6367
second = productionCapacity
6468
) { request: Numeric<U>, capacity: T ->
65-
with(algebra) {
69+
with(producerAlgebra) {
6670
capacity.coerceValueIn(Numeric.zero<U>()..request)
6771
}
6872
}
@@ -71,7 +75,7 @@ public class ContinuousProducer<U : UnitsOfMeasurement, T : Amount<U>>(
7175
consumerRequest,
7276
productionCapacity
7377
) { request, capacity ->
74-
with(algebra) {
78+
with(producerAlgebra) {
7579
val production = capacity.coerceValueIn(Numeric.zero<U>()..request)
7680
production.value / capacity.value
7781
}
@@ -96,7 +100,7 @@ public class ContinuousProducer<U : UnitsOfMeasurement, T : Amount<U>>(
96100
): ContinuousProducer<U, T> {
97101
return ContinuousProducer(
98102
context = consumer.context,
99-
algebra = consumer.algebra,
103+
producerAlgebra = consumer.consumerAlgebra,
100104
productionCapacity = capacity,
101105
).also { producer ->
102106
//provide bi-directional connection

controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/models/continuous/ContinuousReaction.kt

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,19 +70,19 @@ public interface ReactionRule<U : UnitsOfMeasurement, T : Amount<U>> {
7070
* @param U The type of the units of measurement associated with the amounts.
7171
* @param T The type of the amount with units, representing the quantities of substances.
7272
* @param context The simulation context in which the reaction operates.
73-
* @param algebra The algebra defining the operations on the amounts of type T.
73+
* @param producerAlgebra The algebra defining the operations on the amounts of type T.
7474
* @param reaction The reaction rule defining consumption and production behavior
7575
* for given supply and product keys.
7676
*/
7777
public class ContinuousReaction<U : UnitsOfMeasurement, T : Amount<U>>(
7878
context: Context,
79-
public val algebra: AmountAlgebra<U, T>,
79+
override val producerAlgebra: AmountAlgebra<U, T>,
8080
public val reaction: ReactionRule<U, T>,
8181
) : ModelConstructor(context), ContinuousProducerInterface<U, T> {
8282

83-
override val consumerRequest: LateBindDeviceState<Numeric<U>> = LateBindDeviceState( Numeric.zero())
83+
override val consumerRequest: LateBindDeviceState<Numeric<U>> = LateBindDeviceState(Numeric.zero())
8484
public val supplyRequest: Map<String, LateBindDeviceState<T>> = reaction.supplyKeys.associateWith {
85-
LateBindDeviceState( algebra.zero)
85+
LateBindDeviceState(producerAlgebra.zero)
8686
}
8787

8888

@@ -102,11 +102,11 @@ public class ContinuousReaction<U : UnitsOfMeasurement, T : Amount<U>>(
102102
public val consumation: DeviceState<Map<String, T>> = combineState(
103103
consumerRequest, jointSupplyRequest
104104
) { consumerRequest, supplyRequest: Map<String, T> ->
105-
with(algebra) {
105+
with(producerAlgebra) {
106106
//compute expected amount of each supply
107107
val forwardRequest = reaction.forward(supplyRequest)
108108
//limit forward request to consumer capacity
109-
val forward = forwardRequest.coerceIn(algebra.zero..consumerRequest)
109+
val forward = forwardRequest.coerceIn(producerAlgebra.zero..consumerRequest)
110110
//consumation from request
111111
val backward = reaction.backward(forward)
112112

@@ -127,11 +127,11 @@ public class ContinuousReaction<U : UnitsOfMeasurement, T : Amount<U>>(
127127
public val consumationCapacity: DeviceState<Map<String, Numeric<U>>> = combineState(
128128
consumerRequest, jointSupplyRequest
129129
) { consumerRequest: Numeric<U>, supplyRequest: Map<String, T> ->
130-
with(algebra) {
130+
with(producerAlgebra) {
131131
//compute expected amount of each supply
132132
val forwardRequest = reaction.forward(supplyRequest)
133133
//limit forward request to consumer capacity
134-
val forward = forwardRequest.coerceIn(algebra.zero..consumerRequest)
134+
val forward = forwardRequest.coerceIn(producerAlgebra.zero..consumerRequest)
135135
//consumation from request
136136
reaction.backward(forward)
137137
}
@@ -150,7 +150,7 @@ public class ContinuousReaction<U : UnitsOfMeasurement, T : Amount<U>>(
150150
override val production: DeviceState<T> = combineState(
151151
consumerRequest, jointSupplyRequest
152152
) { consumerRequest, supplyRequest: Map<String, T> ->
153-
with(algebra) {
153+
with(producerAlgebra) {
154154
reaction.forward(supplyRequest).coerceValueIn(Numeric.zero<U>()..consumerRequest)
155155
}
156156
}
@@ -172,6 +172,8 @@ public fun <U : UnitsOfMeasurement, T : Amount<U>> ContinuousReaction<U, T>.asCo
172172
key: String
173173
): ContinuousConsumerInterface<U, T> = supplyRequest[key]?.let { input ->
174174
object : ContinuousConsumerInterface<U, T> {
175+
override val consumerAlgebra: AmountAlgebra<U, T> get() = this@asConsumer.producerAlgebra
176+
175177
override val consumation: DeviceState<T> get() = individualConsumation[key]!!
176178
override val consumationCapacity: DeviceState<Numeric<U>> get() = individualConsumationCapacity[key]!!
177179
override val supplyRequest: LateBindDeviceState<T> get() = input

controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/models/continuous/ContinuousSeparate.kt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ public interface SeparationRule<U : UnitsOfMeasurement, T : Amount<U>> {
4040

4141
public class ContinuousSeparate<U : UnitsOfMeasurement, T : Amount<U>>(
4242
context: Context,
43-
public val algebra: AmountAlgebra<U, T>,
43+
override val consumerAlgebra: AmountAlgebra<U, T>,
4444
public val rule: SeparationRule<U, T>,
4545
) : ModelConstructor(context), ContinuousConsumerInterface<U, T> {
4646

47-
override val supplyRequest: LateBindDeviceState<T> = LateBindDeviceState( algebra.zero)
47+
override val supplyRequest: LateBindDeviceState<T> = LateBindDeviceState(consumerAlgebra.zero)
4848

4949
public val consumationRequest: Map<String, LateBindDeviceState<Numeric<U>>> = rule.productionKeys.associateWith {
50-
LateBindDeviceState( Numeric.zero())
50+
LateBindDeviceState(Numeric.zero())
5151
}
5252

5353
private val jointConsumationRequest: DeviceState<Map<String, Numeric<U>>> = combineState(consumationRequest) {
@@ -62,30 +62,30 @@ public class ContinuousSeparate<U : UnitsOfMeasurement, T : Amount<U>>(
6262
val limitingFactor = expectation.minOfOrNull { (key, value) ->
6363
(consumation[key] ?: Numeric.zero()).value / value.value
6464
} ?: 0.0
65-
with(algebra) {
65+
with(consumerAlgebra) {
6666
supply * limitingFactor to expectation.mapValues { (key, value) -> supply * limitingFactor }
6767
}
6868
}
6969

7070
public val production: DeviceState<Map<String, T>> = mapState(balance) { it.second }
7171

7272
public val individualProduction: Map<String, DeviceState<T>> = rule.productionKeys.associateWith { key ->
73-
mapState(production) { it[key] ?: algebra.zero }
73+
mapState(production) { it[key] ?: consumerAlgebra.zero }
7474
}
7575

7676
public val productionCapacity: DeviceState<Map<String, T>> = combineState(
7777
first = supplyRequest,
7878
second = jointConsumationRequest
7979
) { supply: T, consumation: Map<String, Numeric<U>> ->
80-
with(algebra) {
80+
with(consumerAlgebra) {
8181
val productionLimit = rule.backward(consumation)
82-
val expectedProduction = supply.coerceValueIn(zero.. productionLimit)
82+
val expectedProduction = supply.coerceValueIn(zero..productionLimit)
8383
rule.forward(expectedProduction)
8484
}
8585
}
8686

8787
public val individualProductionCapacity: Map<String, DeviceState<T>> = rule.productionKeys.associateWith { key ->
88-
mapState(productionCapacity) { it[key] ?: algebra.zero }
88+
mapState(productionCapacity) { it[key] ?: consumerAlgebra.zero }
8989
}
9090

9191
override val consumation: DeviceState<T> = mapState(balance) { it.first }
@@ -100,6 +100,7 @@ public fun <U : UnitsOfMeasurement, T : Amount<U>> ContinuousSeparate<U, T>.asPr
100100
key: String
101101
): ContinuousProducerInterface<U, T> = consumationRequest[key]?.let { specificConsumationRequest ->
102102
object : ContinuousProducerInterface<U, T> {
103+
override val producerAlgebra: AmountAlgebra<U, T> get() = this@asProducer.consumerAlgebra
103104
override val production: DeviceState<T> get() = individualProduction[key]!!
104105
override val productionCapacity: DeviceState<T> = individualProductionCapacity[key]!!
105106
override val consumerRequest: LateBindDeviceState<Numeric<U>> get() = specificConsumationRequest

0 commit comments

Comments
 (0)