Skip to content

Commit

Permalink
Merge pull request #272 from kleis-technology/feature/process-impact-…
Browse files Browse the repository at this point in the history
…block

Add impact block to processes
  • Loading branch information
jedesroches authored Aug 11, 2023
2 parents 7d1c733 + ee60cf4 commit 5db6171
Show file tree
Hide file tree
Showing 45 changed files with 707 additions and 768 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,14 @@ class SubstanceWithImpactAccumulator {
@Suppress("SameParameterValue")
private fun impactsContent(pad: Int = 4): String = factorRecords
.filter { it.methodLocation().isBlank() }
.map {
.joinToString("\n") {
"|".plus(
padStart(
"${it.characterizationFactor()} ${it.unit()} ${it.methodName()}",
pad
)
)
}
.joinToString("\n")

private val impactsSubsection: String
get() = if (factorRecords.size > 0) {
Expand All @@ -86,7 +85,7 @@ class SubstanceWithImpactAccumulator {
private fun getSubCompartment(): String {
val sub = substanceSubCompartment
@Suppress("SameParameterValue")
return if (sub.isNullOrBlank()) {
return if (sub.isBlank()) {
""
} else {
" sub_compartment = \"$sub\""
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/ch/kleis/lcaplugin/actions/ActionHelper.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package ch.kleis.lcaplugin.actions

import ch.kleis.lcaplugin.core.lang.evaluator.Evaluator
import ch.kleis.lcaplugin.core.lang.evaluator.EvaluationTrace
import ch.kleis.lcaplugin.core.lang.evaluator.Evaluator
import ch.kleis.lcaplugin.core.lang.expression.EProcessTemplateApplication
import ch.kleis.lcaplugin.language.parser.LcaFileCollector
import ch.kleis.lcaplugin.language.parser.LcaLangAbstractParser
Expand Down Expand Up @@ -29,7 +29,7 @@ fun traceSystemWithIndicator(
indicator.text = "Solving system"
val template =
symbolTable.getTemplate(processName, matchLabels)!! // We are called from a process, so it must exist
val entryPoint = EProcessTemplateApplication(template, emptyMap())
val entryPoint = EProcessTemplateApplication(template = template)

return Evaluator(symbolTable).trace(entryPoint)
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,8 @@ class SankeyGraphBuilder(
else -> inventory.impactFactors.valueRatio(exchange.port(), observed).amount
}

val retVal = valueRatioForObservedImpact *
return valueRatioForObservedImpact *
inventory.supply.quantityOf(product).amount *
exchange.quantity().amount

return retVal
}
}
74 changes: 35 additions & 39 deletions src/main/kotlin/ch/kleis/lcaplugin/core/allocation/Allocation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import ch.kleis.lcaplugin.core.lang.evaluator.EvaluatorException
import ch.kleis.lcaplugin.core.lang.value.*
import kotlin.math.absoluteValue

class Allocation {
object Allocation {
fun apply(system: SystemValue): SystemValue {
val processes = system.processes.flatMap { processValue ->
processValue.products.map { allocateProduct(it, processValue) }
Expand All @@ -16,11 +16,12 @@ class Allocation {
private fun allocateProduct(technoExchangeValue: TechnoExchangeValue, processValue: ProcessValue): ProcessValue {
val totalAllocation = totalAmount(processValue)
return ProcessValue(
processValue.name,
processValue.labels,
listOf(technoExchangeValue.copy(allocation = technoExchangeValue.allocation.copy(amount = 100.0))),
applyAllocationToInputs(processValue.inputs, technoExchangeValue.allocation, totalAllocation),
applyAllocationToBioSphere(processValue.biosphere, technoExchangeValue.allocation, totalAllocation)
name = processValue.name,
labels = processValue.labels,
products = listOf(technoExchangeValue.copy(allocation = technoExchangeValue.allocation.copy(amount = 100.0))),
inputs = processValue.inputs.map(applyAllocationToInput(technoExchangeValue.allocation, totalAllocation)),
biosphere = processValue.biosphere.map(applyAllocationToBioExchange(technoExchangeValue.allocation, totalAllocation)),
impacts = processValue.impacts.map(applyAllocationToImpact(technoExchangeValue.allocation, totalAllocation))
)
}

Expand All @@ -42,48 +43,43 @@ class Allocation {
return processValue.products.sumOf { it.allocation.amount }
}

private fun applyAllocationToInputs(
inputs: List<TechnoExchangeValue>,
allocation: QuantityValue,
totalAllocation: Double
): List<TechnoExchangeValue> {
return inputs.map { applyAllocationToInput(it, allocation, totalAllocation) }
}

private fun applyAllocationToInput(
technoExchangeValue: TechnoExchangeValue,
allocation: QuantityValue,
totalAllocation: Double
): TechnoExchangeValue {
return TechnoExchangeValue(
QuantityValue(
technoExchangeValue.quantity.amount * allocation.referenceValue() / totalAllocation,
technoExchangeValue.quantity.unit
),
technoExchangeValue.product,
technoExchangeValue.allocation,
)
): (TechnoExchangeValue) -> TechnoExchangeValue {
val ratio = allocation.referenceValue() / totalAllocation
return { technoExchangeValue: TechnoExchangeValue ->
technoExchangeValue.copy(
quantity = technoExchangeValue.quantity.copy(
amount = technoExchangeValue.quantity.amount * ratio
)
)
}
}

private fun applyAllocationToBioSphere(
biosphere: List<BioExchangeValue>,
private fun applyAllocationToBioExchange(
allocation: QuantityValue,
totalAllocation: Double
): List<BioExchangeValue> {
return biosphere.map { applyAllocationToBioExchange(it, allocation, totalAllocation) }
): (BioExchangeValue) -> BioExchangeValue {
val ratio = allocation.referenceValue() / totalAllocation
return { bioExchange: BioExchangeValue ->
bioExchange.copy(
quantity = bioExchange.quantity.copy(
amount = bioExchange.quantity.amount * ratio
),
)
}
}

private fun applyAllocationToBioExchange(
bioExchange: BioExchangeValue,
private fun applyAllocationToImpact(
allocation: QuantityValue,
totalAllocation: Double
): BioExchangeValue {
return BioExchangeValue(
QuantityValue(
bioExchange.quantity.amount * allocation.referenceValue() / totalAllocation,
bioExchange.quantity.unit
),
bioExchange.substance
)
totalAllocation: Double,
): (ImpactValue) -> ImpactValue {
val ratio = allocation.referenceValue() / totalAllocation
return { impactValue ->
impactValue.copy(quantity = impactValue.quantity.copy(
amount = impactValue.quantity.amount * ratio
))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Assessment(
val allocatedSystem: SystemValue

init {
allocatedSystem = Allocation().apply(system)
allocatedSystem = Allocation.apply(system)
val processes = allocatedSystem.processes
val substanceCharacterizations = allocatedSystem.substanceCharacterizations

Expand All @@ -47,7 +47,7 @@ class Assessment(
.flatMap { it.biosphere }
.map { it.substance }
.filter { !observableSubstances.contains(it) }
val indicators = substanceCharacterizations
val indicators = (processes + substanceCharacterizations)
.flatMap { it.impacts }
.map { it.indicator }
controllablePorts = IndexedCollection(terminalProducts.plus(terminalSubstances).plus(indicators))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ class Evaluator(
private val reduceLabelSelectors = ReduceLabelSelectors(symbolTable)
private val completeDefaultArguments = CompleteDefaultArguments(symbolTable)
private val reduce = Reduce(symbolTable)
private val completeTerminals = CompleteTerminals()

private val processResolver = ProcessResolver(symbolTable)
private val substanceCharacterizationResolver = SubstanceCharacterizationResolver(symbolTable)
Expand Down Expand Up @@ -73,7 +72,7 @@ class Evaluator(
.let(reduceLabelSelectors::apply)
.let(completeDefaultArguments::apply)
.let(reduce::apply)
.let(completeTerminals::apply)
.let(CompleteTerminals::apply)

val inputProductsModified = everyInputProduct.modify(reduced) { spec: EProductSpec ->
resolveProcessTemplateByProductSpec(spec)?.let { template ->
Expand All @@ -97,7 +96,7 @@ class Evaluator(
resolveSubstanceCharacterizationBySubstanceSpec(spec)?.let {
val substanceCharacterization = it
.let(reduce::apply)
.let(completeTerminals::apply)
.let(CompleteTerminals::apply)
trace.add(substanceCharacterization.toValue())
substanceCharacterization.referenceExchange.substance
} ?: spec
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ fun EProcess.toValue(): ProcessValue {
return ProcessValue(
this.name,
this.labels.mapValues { it.value.toValue() as StringValue },
this.products.map { it.toValue() },
this.inputs.map { it.toValue() },
this.biosphere.map { it.toValue() },
this.products.map(ETechnoExchange::toValue),
this.inputs.map(ETechnoExchange::toValue),
this.biosphere.map(EBioExchange::toValue),
this.impacts.map(EImpact::toValue)
)
}

Expand Down Expand Up @@ -102,13 +103,14 @@ private fun FromProcess.toValue(): FromProcessRefValue {
}

fun DataExpression.toValue(): DataValue {
return when(this) {
return when (this) {
is EStringLiteral -> StringValue(this.value)
is EUnitLiteral -> QuantityValue(1.0, this.toUnitValue())
is EQuantityScale -> when (val b = this.base) {
is EUnitLiteral -> QuantityValue(
this.scale, b.toUnitValue(),
)

else -> throw EvaluatorException("$b is not reduced")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class LcaExpressionReducer(
fun reduceSubstanceCharacterization(expression: ESubstanceCharacterization): ESubstanceCharacterization {
return ESubstanceCharacterization(
reduceBioExchange(expression.referenceExchange),
expression.impacts.map { reduceImpact(it) },
expression.impacts.map(::reduceImpact),
)
}

Expand All @@ -35,9 +35,10 @@ class LcaExpressionReducer(
return EProcess(
expression.name,
expression.labels,
expression.products.map { reduceTechnoExchange(it) },
expression.inputs.map { reduceTechnoExchange(it) },
expression.biosphere.map { reduceBioExchange(it) },
expression.products.map(::reduceTechnoExchange),
expression.inputs.map(::reduceTechnoExchange),
expression.biosphere.map(::reduceBioExchange),
expression.impacts.map(::reduceImpact)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,23 @@ import arrow.optics.Every
import ch.kleis.lcaplugin.core.lang.evaluator.EvaluatorException
import ch.kleis.lcaplugin.core.lang.expression.*

class CompleteTerminals {
object CompleteTerminals {
private val everyInputExchange =
EProcessFinal.expression.inputs compose
Every.list()

fun apply(expression: EProcessFinal): EProcessFinal {
return completeSubstances(completeInputs(expression))
}
fun apply(expression: EProcessFinal): EProcessFinal =
expression
.completeInputs()
.completeSubstances()
.completeProcessIndicators()

fun apply(expression: ESubstanceCharacterization): ESubstanceCharacterization {
return completeIndicators(expression)
}
fun apply(expression: ESubstanceCharacterization): ESubstanceCharacterization =
expression.completeSubstanceIndicators()

private fun completeInputs(reduced: EProcessFinal): EProcessFinal {
private fun EProcessFinal.completeInputs(): EProcessFinal {
return everyInputExchange
.modify(reduced) { exchange ->
.modify(this) { exchange ->
val quantityExpression = exchange.quantity
val referenceUnit = when {
quantityExpression is EUnitLiteral ->
Expand All @@ -38,9 +39,9 @@ class CompleteTerminals {
}
}

private fun completeSubstances(reduced: EProcessFinal): EProcessFinal {
private fun EProcessFinal.completeSubstances(): EProcessFinal {
return (EProcessFinal.expression.biosphere compose Every.list())
.modify(reduced) { exchange ->
.modify(this) { exchange ->
val quantityExpression = exchange.quantity
val referenceUnit = when {
quantityExpression is EUnitLiteral ->
Expand All @@ -61,24 +62,32 @@ class CompleteTerminals {
}
}

private fun completeIndicators(reduced: ESubstanceCharacterization): ESubstanceCharacterization {
return (ESubstanceCharacterization.impacts compose Every.list())
.modify(reduced) { exchange ->
val quantityExpression = exchange.quantity
val referenceUnit = when {
quantityExpression is EUnitLiteral ->
EQuantityScale(1.0, quantityExpression)
private fun completeIndicators(impacts: Collection<EImpact>): List<EImpact> =
impacts.map { impactExchange ->
val quantityExpression = impactExchange.quantity
val referenceUnit = when {
quantityExpression is EUnitLiteral ->
EQuantityScale(1.0, quantityExpression)

quantityExpression is EQuantityScale && quantityExpression.base is EUnitLiteral ->
EQuantityScale(1.0, quantityExpression.base)
quantityExpression is EQuantityScale && quantityExpression.base is EUnitLiteral ->
EQuantityScale(1.0, quantityExpression.base)

else -> throw EvaluatorException("quantity $quantityExpression is not reduced")
else -> throw EvaluatorException("quantity $quantityExpression is not reduced")
}

EImpact.indicator
.modify(impactExchange) {
EIndicatorSpec(it.name, referenceUnit)
}
}

EImpact.indicator
.modify(exchange) {
EIndicatorSpec(it.name, referenceUnit)
}
}
}
private fun EProcessFinal.completeProcessIndicators(): EProcessFinal =
this.copy(
expression = this.expression.copy(
impacts = completeIndicators(this.expression.impacts)
)
)

private fun ESubstanceCharacterization.completeSubstanceIndicators(): ESubstanceCharacterization =
this.copy(impacts = completeIndicators(this.impacts))
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import arrow.optics.optics
data class FromProcess(
val name: String,
val matchLabels: MatchLabels,
val arguments: Map<String, DataExpression>,
val arguments: Map<String, DataExpression> = emptyMap(),
) {
override fun toString(): String {
return "from $name$matchLabels$arguments"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,11 @@ data class EImpact(val quantity: DataExpression, val indicator: EIndicatorSpec)
@optics
data class EProcess(
val name: String,
val labels: Map<String, EStringLiteral>,
val products: List<ETechnoExchange>,
val inputs: List<ETechnoExchange>,
val biosphere: List<EBioExchange>,
val labels: Map<String, EStringLiteral> = emptyMap(),
val products: List<ETechnoExchange> = emptyList(),
val inputs: List<ETechnoExchange> = emptyList(),
val biosphere: List<EBioExchange> = emptyList(),
val impacts: List<EImpact> = emptyList(),
) : LcaExpression {
companion object
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ sealed interface ProcessTemplateExpression : Expression {

@optics
data class EProcessTemplate(
val params: Map<String, DataExpression>,
val locals: Map<String, DataExpression>,
val params: Map<String, DataExpression> = emptyMap(),
val locals: Map<String, DataExpression> = emptyMap(),
val body: EProcess,
) : ProcessTemplateExpression {
companion object
Expand All @@ -19,7 +19,7 @@ data class EProcessTemplate(
@optics
data class EProcessTemplateApplication(
val template: EProcessTemplate,
val arguments: Map<String, DataExpression>
val arguments: Map<String, DataExpression> = emptyMap()
) : ProcessTemplateExpression {
companion object
}
Expand Down
Loading

0 comments on commit 5db6171

Please sign in to comment.