Skip to content

Commit

Permalink
Merge pull request #283 from kleis-technology/fix/240
Browse files Browse the repository at this point in the history
Close #240.
  • Loading branch information
jedesroches authored Aug 17, 2023
2 parents 6183d3b + 7648ea7 commit 0e17d24
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,25 @@ class SankeyGraphBuilder(
is ProductValue -> {
val parentProcess = allocatedSystem.productToProcessMap[port]!!

val linksWithObservedImpact = (parentProcess.inputs + parentProcess.biosphere).filter { parentProcessExchange ->
portsWithObservedImpact.contains(parentProcessExchange.port()) || parentProcessExchange.port() == sankeyIndicator
}
val linksWithObservedImpact =
(parentProcess.inputs + parentProcess.biosphere).filter { parentProcessExchange ->
portsWithObservedImpact.contains(parentProcessExchange.port()) || parentProcessExchange.port() == sankeyIndicator
}

linksWithObservedImpact.fold(graph.addNode(GraphNode(port.getUID(), port.getShortName()))) { accumulatorGraph, exchange ->
linksWithObservedImpact.fold(
graph.addNode(
GraphNode(
port.getUID(),
port.getShortName()
)
)
) { accumulatorGraph, exchange ->
accumulatorGraph.addLinkIfNoCycle(
observableOrder,
port,
exchange.port(),
impactAmountForExchange(sankeyIndicator, inventory, port, exchange))
impactAmountForExchange(sankeyIndicator, inventory, port, exchange)
)
}
}

Expand Down Expand Up @@ -73,9 +82,14 @@ class SankeyGraphBuilder(
}
}

private fun impactAmountForSubstance(observed: MatrixColumnIndex, inventory: Inventory, substance: SubstanceValue): Double {
return inventory.impactFactors.valueRatio(substance, observed).amount *
inventory.supply.quantityOf(substance).amount
private fun impactAmountForSubstance(
observed: MatrixColumnIndex,
inventory: Inventory,
substance: SubstanceValue
): Double {
val a = inventory.impactFactors.valueRatio(substance, observed).referenceValue()
val b = inventory.supply.quantityOf(substance).referenceValue()
return a * b
}

private fun impactAmountForExchange(
Expand All @@ -86,11 +100,11 @@ class SankeyGraphBuilder(
): Double {
val valueRatioForObservedImpact = when {
(exchange.port() == observed) -> 1.0
else -> inventory.impactFactors.valueRatio(exchange.port(), observed).amount
else -> inventory.impactFactors.valueRatio(exchange.port(), observed).referenceValue()
}

return valueRatioForObservedImpact *
inventory.supply.quantityOf(product).amount *
exchange.quantity().amount
inventory.supply.quantityOf(product).referenceValue() *
exchange.quantity().referenceValue()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ class EvaluationTrace {
fun getObservableOrder(): Comparator<MatrixColumnIndex> {
return object : Comparator<MatrixColumnIndex> {
override fun compare(o1: MatrixColumnIndex, o2: MatrixColumnIndex): Int {
val d1 = observableDepthMap[o1] ?: throw EvaluatorException("unknown ${o1}")
val d2 = observableDepthMap[o2] ?: throw EvaluatorException("unknown ${o2}")
val d1 = observableDepthMap[o1] ?: throw EvaluatorException("unknown $o1")
val d2 = observableDepthMap[o2] ?: throw EvaluatorException("unknown $o2")
if (d1 < d2) {
return -1
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,20 @@ class Evaluator(
.let(CompleteTerminals::apply)

val inputProductsModified = everyInputProduct.modify(reduced) { spec: EProductSpec ->
resolveProcessTemplateByProductSpec(spec)?.let { template ->
processResolver.resolve(spec)?.let { template ->
val body = template.body
val labels = spec.fromProcess?.matchLabels
?: MatchLabels(template.body.labels)
val arguments = spec.fromProcess?.arguments
?: template.params.mapValues { entry -> dataReducer.reduce(entry.value) }
val unit = body.products.firstOrNull {
it.product.name == spec.name
}?.product?.referenceUnit?.let {
dataReducer.reduce(it)
} ?: spec.referenceUnit
nextBatch.add(EProcessTemplateApplication(template, arguments))
spec.copy(
referenceUnit = unit,
fromProcess =
FromProcess(
body.name,
Expand Down Expand Up @@ -122,9 +128,5 @@ class Evaluator(
private fun resolveSubstanceCharacterizationBySubstanceSpec(spec: ESubstanceSpec): ESubstanceCharacterization? {
return substanceCharacterizationResolver.resolve(spec)?.takeIf { it.hasImpacts() }
}

private fun resolveProcessTemplateByProductSpec(spec: EProductSpec): EProcessTemplate? {
return processResolver.resolve(spec)
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ object CompleteTerminals {

ETechnoExchange.product
.modify(exchange) {
if (it.referenceUnit == null) {
it.copy(referenceUnit = referenceUnit)
} else it
it.copy(referenceUnit = referenceUnit)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ data class ProductValue(
val name: String,
val referenceUnit: UnitValue,
val fromProcessRef: FromProcessRefValue? = null
) :
Value, MatrixColumnIndex {
) : Value, MatrixColumnIndex {

override fun getDimension(): Dimension {
return referenceUnit.dimension
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ class SankeyGraphBuilderTest : BasePlatformTestCase() {
val comparator: Comparator<MatrixColumnIndex>,
)

private fun getRequiredInformation(@Suppress("SameParameterValue") process: String, vf: VirtualFile): SankeyRequiredInformation {
private fun getRequiredInformation(
@Suppress("SameParameterValue") process: String,
vf: VirtualFile
): SankeyRequiredInformation {
val file = PsiManager.getInstance(project).findFile(vf) as LcaFile
val parser = LcaLangAbstractParser(sequenceOf(file))
val symbolTable = parser.load()
Expand All @@ -59,7 +62,8 @@ class SankeyGraphBuilderTest : BasePlatformTestCase() {
1 m3 my_substance (compartment = "air")
}
}
""".trimIndent())
""".trimIndent()
)
val (sankeyPort, allocatedSystem, inventory, comparator) = getRequiredInformation("p", vf)
val sut = SankeyGraphBuilder(allocatedSystem, inventory, comparator)

Expand Down Expand Up @@ -91,7 +95,8 @@ class SankeyGraphBuilderTest : BasePlatformTestCase() {
1 m3 my_substance (compartment = "air")
}
}
""".trimIndent())
""".trimIndent()
)
val (sankeyPort, allocatedSystem, inventory, comparator) = getRequiredInformation("p", vf)
val sut = SankeyGraphBuilder(allocatedSystem, inventory, comparator)

Expand Down Expand Up @@ -123,7 +128,8 @@ class SankeyGraphBuilderTest : BasePlatformTestCase() {
1 kg my_input
}
}
""".trimIndent())
""".trimIndent()
)
val (sankeyPort, allocatedSystem, inventory, comparator) = getRequiredInformation("p", vf)
val sut = SankeyGraphBuilder(allocatedSystem, inventory, comparator)

Expand Down Expand Up @@ -163,7 +169,8 @@ class SankeyGraphBuilderTest : BasePlatformTestCase() {
2.5 kg my_emission
}
}
""".trimIndent())
""".trimIndent()
)
val (sankeyPort, allocatedSystem, inventory, comparator) = getRequiredInformation("p", vf)
val sut = SankeyGraphBuilder(allocatedSystem, inventory, comparator)

Expand Down Expand Up @@ -206,7 +213,8 @@ class SankeyGraphBuilderTest : BasePlatformTestCase() {
1 m3 my_substance (compartment = "air")
}
}
""".trimIndent())
""".trimIndent()
)
val (sankeyPort, allocatedSystem, inventory, comparator) = getRequiredInformation("p", vf)
val sut = SankeyGraphBuilder(allocatedSystem, inventory, comparator)

Expand Down Expand Up @@ -249,7 +257,8 @@ class SankeyGraphBuilderTest : BasePlatformTestCase() {
1000 g my_indicator
}
}
""".trimIndent())
""".trimIndent()
)
val (sankeyPort, allocatedSystem, inventory, comparator) = getRequiredInformation("p", vf)
val sut = SankeyGraphBuilder(allocatedSystem, inventory, comparator)

Expand All @@ -262,11 +271,11 @@ class SankeyGraphBuilderTest : BasePlatformTestCase() {
GraphNode("my_input from input{}{}", "my_input"),
GraphNode("my_indicator", "my_indicator"),
).addLink(
GraphLink("my_product from p{}{}", "my_input from input{}{}", 500.0),
GraphLink("my_input from input{}{}", "my_indicator", 500.0),
GraphLink("my_product from p{}{}", "my_input from input{}{}", 0.5),
GraphLink("my_input from input{}{}", "my_indicator", 0.5),
)
assertEquals(expected.nodes, graph.nodes)
assertEquals(expected.links, graph.links)
assertEquals(expected.nodes.naturalSorted(), graph.nodes.naturalSorted())
assertEquals(expected.links.naturalSorted(), graph.links.naturalSorted())
}

@Test
Expand All @@ -284,7 +293,8 @@ class SankeyGraphBuilderTest : BasePlatformTestCase() {
2 m3 my_substance (compartment = "air")
}
}
""".trimIndent())
""".trimIndent()
)
val (sankeyPort, allocatedSystem, inventory, comparator) = getRequiredInformation("p", vf)
val sut = SankeyGraphBuilder(allocatedSystem, inventory, comparator)

Expand Down Expand Up @@ -343,7 +353,8 @@ class SankeyGraphBuilderTest : BasePlatformTestCase() {
1 kg my_substance
}
}
""".trimIndent())
""".trimIndent()
)
val (sankeyPort, allocatedSystem, inventory, comparator) = getRequiredInformation("p", vf)
val sut = SankeyGraphBuilder(allocatedSystem, inventory, comparator)

Expand Down Expand Up @@ -405,7 +416,8 @@ class SankeyGraphBuilderTest : BasePlatformTestCase() {
1 m3 my_substance (compartment = "air")
}
}
""".trimIndent())
""".trimIndent()
)
val (sankeyPort, allocatedSystem, inventory, comparator) = getRequiredInformation("p", vf)
val sut = SankeyGraphBuilder(allocatedSystem, inventory, comparator)

Expand Down Expand Up @@ -456,7 +468,8 @@ class SankeyGraphBuilderTest : BasePlatformTestCase() {
1 kg C
}
}
""".trimIndent())
""".trimIndent()
)
val (sankeyPort, allocatedSystem, inventory, comparator) = getRequiredInformation("p1", vf)
val sut = SankeyGraphBuilder(allocatedSystem, inventory, comparator)

Expand Down Expand Up @@ -557,7 +570,8 @@ class SankeyGraphBuilderTest : BasePlatformTestCase() {
1 kg my_emission
}
}
""".trimIndent())
""".trimIndent()
)
val (sankeyPort, allocatedSystem, inventory, comparator) = getRequiredInformation("pA", vf)
val sut = SankeyGraphBuilder(allocatedSystem, inventory, comparator)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class UnitValueFixture {
companion object {
val ton = UnitValue(UnitSymbol.of("ton"), 1000.0, DimensionFixture.mass)
val m = UnitValue(UnitSymbol.of("m"), 1.0, DimensionFixture.length)
val g = UnitValue(UnitSymbol.of("g"), 1.0e-3, DimensionFixture.mass)
val kg = UnitValue(UnitSymbol.of("kg"), 1.0, DimensionFixture.mass)
val l = UnitValue(UnitSymbol.of("l"), 1.0e-3, DimensionFixture.volume)
val percent = UnitValue(UnitSymbol.of("percent"), 1.0e-2, Dimension.None)
Expand Down
36 changes: 36 additions & 0 deletions src/test/kotlin/ch/kleis/lcaplugin/e2e/E2ETest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -972,4 +972,40 @@ class E2ETest : BasePlatformTestCase() {
assertEquals(expected, cf.input.quantity().amount, delta)
assertEquals(UnitValueFixture.unit, cf.input.quantity().unit)
}

@Test
fun test_processInput_whenWrongUnit_thenShouldThrow() {
val pkgName = {}.javaClass.enclosingMethod.name
val vf = myFixture.createFile(
"$pkgName.lca", """
package $pkgName
process p1 {
products {
1 kg out
}
inputs {
1 l in
}
}
process p2 {
products {
1 kg in
}
}
""".trimIndent()
)
val file = PsiManager.getInstance(project).findFile(vf) as LcaFile
val parser = LcaLangAbstractParser(sequenceOf(file))
val symbolTable = parser.load()
val entryPoint = EProcessTemplateApplication(template = symbolTable.getTemplate("p1")!!)

// when/then
val e = assertFailsWith(
EvaluatorException::class,
) {
Evaluator(symbolTable).trace(entryPoint)
}
assertEquals("incompatible dimensions: length³ vs mass for product in", e.message)
}
}

0 comments on commit 0e17d24

Please sign in to comment.