Stream: implementers
Topic: potentially bad invariant in RatioRange
Lee Surprenant (Dec 08 2021 at 13:45):
R4B introduces datatype RatioRange with the following invariant:
One of lowNumerator or highNumerator and denominator SHALL be present, or all are absent. If all are absent, there SHALL be some extension present
Expression:
((lowNumerator.empty() and highNumerator.empty()) xor denominator.exists()) and (lowNumerator.exists() or extension.exists())
I find both the description and the fhirpath a bit dense, but at the outer layer of the expression its an and with (lowNumerator.exists() or extension.exists())
Should the following RatioRange be valid (e.g. in concentration[x] in Ingredient)?
<concentrationRatioRange>
<highNumerator>
<value value="1"/>
<unit value="L"/>
</highNumerator>
<denominator>
<value value="2"/>
<unit value="L"/>
</denominator>
</concentrationRatioRange>
If so, I think the expression is in error.
Josh Mandel (Dec 08 2021 at 14:12):
Reading the English and making a guess about where the parentheses belong, I think your example is valid.
I can't read that FHIRpath expression before coffee ;-)
Lee Surprenant (Dec 08 2021 at 14:13):
I had to make a truth table to convince myself the xor part was right (but i think it is)
image.png
Lee Surprenant (Dec 08 2021 at 14:14):
but maybe we should strive for more readable expressions...
Lee Surprenant (Dec 08 2021 at 14:16):
I think its the mix of .empty()
and .exists()
with various boolean operations in the same expression that made it hard for my feable mind
Grahame Grieve (Dec 08 2021 at 18:55):
totally agree about that. @Rik Smithies can we write a more natural expression that doesn't use xor? (looks like it was translated from xpath to me)
Rik Smithies (Dec 08 2021 at 20:24):
It wasn't me that created that, I just copied the whole datatype into R4B from the main build. Possibly @Jean Duteau ?
Grahame Grieve (Dec 08 2021 at 20:27):
yes it was @Jean Duteau
Jean Duteau (Dec 08 2021 at 21:47):
when this was applied, the invariant was taken from Ratio:
rat-1: (numerator.empty() xor denominator.exists()) and (numerator.exists() or extension.exists())
this became for RatioRange:
inv-1: ((lowNumerator.empty() and highNumerator.empty()) xor denominator.exists()) and (lowNumerator.exists() or extension.exists())
Jean Duteau (Dec 08 2021 at 22:01):
this does miss the case where high and denominator are present, so the invariant isn't quite right.
Jean Duteau (Dec 08 2021 at 22:12):
here is the easier invariant:
((low.exists or high.exists) and denom.exists) or (low.empty and high.empty and denom.empty and extension.exists)
Jean Duteau (Dec 08 2021 at 22:14):
if we want to rewrite the Ratio invariant to not use xor:
(numerator.exists and denominator.exists) or (numerator.empty and denominator.empty and extension.exists)
Lee Surprenant (Dec 08 2021 at 22:24):
I, for one, find those much more readable
Lee Surprenant (Dec 10 2021 at 22:34):
Would it be helpful for me to open a JIRA tracker for this one, or is already being worked?
Jean Duteau (Dec 11 2021 at 04:29):
Open a Jira issue
Lee Surprenant (Dec 11 2021 at 15:19):
Grahame Grieve (Dec 14 2021 at 05:02):
I pre-applied these in R4B
Last updated: Apr 12 2022 at 19:14 UTC