Drasil icon indicating copy to clipboard operation
Drasil copied to clipboard

`QuantityDict`, `DefinedQuantityDict`, & `QDefinition`

Open balacij opened this issue 8 months ago • 4 comments

Notes on QuantityDict (QDs) and DefinedQuantityDict (DQDs):

Difference

The only difference between them is that a QD does not have a description (a Sentence -- the DQD "contains" this through "extending" a ConceptChunk rather than an IdeaDict).

QDefinitions and DefinedQuantityDicts

QDefinitions (QDef) are used to declare formulas (Expr/ModelExpr/Literal) for variables (DefinedQuantityDicts). Here are the constructors:

https://github.com/JacquesCarette/Drasil/blob/0ab5dec39cad09265bc57ad36805d980f6337296/code/drasil-lang/lib/Language/Drasil/Chunk/Eq.hs#L81-L161

Notes:

  1. There are 13 different constructors for QDefs.
  2. 12 are public.
  3. Only 6 have a field for declaring the sentence (fromEqn, fromEqn', fromEqnSt, fromEqnSt', fromEqnSt'', mkQDefSt) -- the rest of the constructors default to EmptyS!

fromEqn*

λ rg "fromEqn" -ths
...

drasil-data/lib/Data/Drasil/Equations/Defining/Physics.hs
35:newtonSLQD = fromEqn' "force" (nounPhraseSP "Newton's second law of motion")

drasil-example/swhs/lib/Drasil/SWHS/TMods.hs
84:sensHtEQD pc eqn desc = fromEqnSt'' "sensHeat" np desc (symbol sensHeat) (sensHeat ^. typ) eqn

...
drasil-example/ssp/lib/Drasil/SSP/TMods.hs
84:mcShrStrgthQD = fromEqnSt' (shrStress ^. uid) (nounPhraseSP "Mohr-Coulumb shear strength")
114:effStressQD = fromEqnSt' (effectiveStress ^. uid) (nounPhraseSP "effective stress")

drasil-example/hghc/lib/Drasil/HGHC/HeatTransfer.hs
45:htTransCladCool = fromEqn "htTransCladCool" (nounPhraseSP
59:htTransCladFuel = fromEqn "htTransCladFuel" (nounPhraseSP

Of these uses:

  • SSP:
    • mcShrStrgthQD fills in a long description that appears to not really be a description (and which is only displayed through the corresponding TheoryModel, which contains a duplicate copy of the description) -- https://github.com/JacquesCarette/Drasil/blob/0ab5dec39cad09265bc57ad36805d980f6337296/code/drasil-example/ssp/lib/Drasil/SSP/TMods.hs#L75-L102
    • effStressQD ^ same issue -- https://github.com/JacquesCarette/Drasil/blob/0ab5dec39cad09265bc57ad36805d980f6337296/code/drasil-example/ssp/lib/Drasil/SSP/TMods.hs#L105-L121
  • SWHS's sensHtEQD: ^ same issue -- https://github.com/JacquesCarette/Drasil/blob/0ab5dec39cad09265bc57ad36805d980f6337296/code/drasil-example/swhs/lib/Drasil/SWHS/TMods.hs#L64-L97
  • HGHC:
    • htTransCladCool: EmptyS (empty sentence) -- https://github.com/JacquesCarette/Drasil/blob/0ab5dec39cad09265bc57ad36805d980f6337296/code/drasil-example/hghc/lib/Drasil/HGHC/HeatTransfer.hs#L44-L47
    • htTransCladFuel: ^ same -- https://github.com/JacquesCarette/Drasil/blob/0ab5dec39cad09265bc57ad36805d980f6337296/code/drasil-example/hghc/lib/Drasil/HGHC/HeatTransfer.hs#L59-L61
  • Eq/Def/Phy.hs's newtonSLQD: It has a description that is also passed through to a TheoryModel.
File: ./drasil-data/lib/Data/Drasil/Theories/Physics.hs
  30  41   [newtonSLQD] [] [] "NewtonSecLawMot" [newtonSLDesc]

File: ./drasil-data/lib/Data/Drasil/Equations/Defining/Physics.hs
  36   3   newtonSLDesc (eqSymb QP.force) Real newtonSLEqn
  38   1 newtonSLDesc :: Sentence
  39   1 newtonSLDesc = foldlSent [S "The net", getTandS QP.force, S "on a",

Overall, it looks like we're not using the Sentences provided to QDefinitions through fromEqn*

mkQDefSt

There is only one (indirectly two) use:

https://github.com/JacquesCarette/Drasil/blob/0ab5dec39cad09265bc57ad36805d980f6337296/code/drasil-theory/lib/Theory/Drasil/MultiDefn.hs#L99-L119

However, these two functions are never used however. The idea behind these functions is that for a MultiDefn, we can extract a single QDefinition and use it elsewhere. Not a big deal -- and definitely a function I think we should keep.

Summary (Purely operational view to reduce the code size)

  1. At the very least, we should be able to remove fromEqn*, replacing uses with other constructors. It's not clear if this is what we want however.
  2. DefinedQuantityDict appears to not be used as much as was expected. Their corresponding ConceptChunks are normally filled in with EmptyS or things that are never used.
  3. We can investigate removing DefinedQuantityDict. Depending on whether we think QDefinitions should have Descriptions or not, we can move the description field to QDefinition.

Discussion

One issue with removing DefinedQuantityDict is that we would have to remove the Definition typeclass instance for QDef:

instance Definition      (QDefinition e) where defn = qdQua . defn

By extension, this would trickle up to an issue for ModelKind, which depends on this for EquationalModel). Surprisingly, this would not be an issue an issue for DataDefinition (which does not instantiate Definition).

Questions

  1. Currently, QDefinition descriptions aren't used anywhere other than the Notes section (in the few areas I listed above) of our theory description boxes. Are they necessary? Where should they be used?
  2. What are some examples of 'good' descriptions for our QDefinitions that aren't simply of the form: $x$ can be defined with the formula $y$ [optional:, following $z$'s theorem ...]? Or, is this what we want? Would this be usable in the SRS text anywhere?

balacij avatar May 14 '25 13:05 balacij

Ah, I'm realizing there's a bit of confusion in the code as well: Definition $\ne$ Description, Definition $\ne$ Name, and Description $\ne$ Name. Some variable names are using them somewhat interchangeably.

balacij avatar May 14 '25 17:05 balacij

Let's look at mcShrStrgthQD:

 mcShrStrgthQD :: ModelQDef 
 mcShrStrgthQD = fromEqnSt' (shrStress ^. uid) (nounPhraseSP "Mohr-Coulumb shear strength") 
  mcShrStrgthDesc (symbol shrStress) Real mcShrStrgthExpr 

Recall fromEqn*:

-- | Create a 'QDefinition' with a 'UID' (as a 'String'), term ('NP'), definition ('Sentence'), 'Symbol',
-- 'Space', unit, and defining expression.
fromEqn :: IsUnit u => String -> NP -> Sentence -> Symbol -> Space -> u -> e -> QDefinition e
fromEqn nm desc def symb sp un =
  QD (dqd (cc' (mkIdea nm desc Nothing) def) symb sp un) []

-- | Same as 'fromEqn', but has no units.
fromEqn' :: String -> NP -> Sentence -> Symbol -> Space -> e -> QDefinition e
fromEqn' nm desc def symb sp =
  QD (dqd' (cc' (mkIdea nm desc Nothing) def) (const symb) sp Nothing) []

-- | Same as 'fromEqn', but symbol depends on stage.
fromEqnSt :: IsUnit u => UID -> NP -> Sentence -> (Stage -> Symbol) ->
  Space -> u -> e -> QDefinition e
fromEqnSt nm desc def symb sp un =
  QD (dqd' (cc' (nw $ ncUID nm desc) def) symb sp (Just $ unitWrapper un)) []

-- | Same as 'fromEqn', but symbol depends on stage and has no units.
fromEqnSt' :: UID -> NP -> Sentence -> (Stage -> Symbol) -> Space -> e -> QDefinition e
fromEqnSt' nm desc def symb sp =
  QD (dqd' (cc' (nw $ ncUID nm desc) def) symb sp Nothing) []

From this code, we have:

  1. An IdeaDict (nw $ ncUID nm desc) whose UID is shrStress ^. uid, "Term"/Name is "Mohr-Coulumb shear strength"
  2. A ConceptChunk (cc' (mkIdea nm desc Nothing) def) which inherits from the IdeaDict, adding an "English definition" (def; mcShrStrgthDesc).
  3. A DefinedQuantityDict (dqd' (cc' (nw $ ncUID nm desc) def) symb sp Nothing) which inherits from the ConceptChunk adding the (stage-dependant) symbol, space (Real), without a unit.
  4. A QDefinition (QD (dqd' (cc' (nw $ ncUID nm desc) def) symb sp Nothing) []) that pairs a DefinedQuantityDict with a given expression and its input symbols ([], given by their UIDs).

Let $Trg$ = shrStress ^. uid

Notes:

  1. The argument name is "desc" but it is given to the term/name of the IdeaDict. This is really the name being assigned to $Trg$.
  2. The English definition of $Trg$ is provided through a ConceptChunk, which contains a description of the formula that the QDefinition will expose:
  mcShrStrgthDesc :: Sentence
mcShrStrgthDesc = foldlSent [S "In this", phrase model, S "the",
  getTandS shrStress `S.is` S "proportional to the product" `S.ofThe` phrase effNormStress, 
  ch effNormStress `S.onThe` S "plane", 
  S "with its static", phrase friction `S.inThe` S "angular form" +:+.
  eS (tan $ sy fricAngle),
  S "The", ch shrStress, S "versus", ch effNormStress,
  S "relationship" `S.is` S "not truly",
  phrase linear `sC` S "but assuming the", phrase nrmFSubWat, 
  S "is strong enough" `sC` S "it can be approximated with a", phrase linear,
  S "fit", sParen (refS assumpSBSBISL), S "where the", phrase effCohesion, 
  ch effCohesion, S "represents the", ch shrStress,
  S "intercept" `S.ofThe` S "fitted line"]
  1. The DefinedQuantityDict defining $Trg$ appears fine, except for the issue with the ConceptChunk.
  2. The QDefinition defining $Trg$'s name is inherited from the IdeaDict which is also the name of the DQD. The QDefinition inherits the English definition assigned to $Trg$ via the ConceptChunk -- these should be different.

A question I have about DQDs and QDefinitions is: what should their (English) definitions look like? Their descriptions?

Aside: one slightly problematic thing about DQDs and QDs is that for the Table of Symbols, we use the heading "Description" for the column that contains the "Term/Name".

balacij avatar May 14 '25 18:05 balacij

EmptyS is definitely a bad "code smell" that should be closely examined. Using them to fill a field is a user mistake. So mkQuantDef and mkQuantDef' are very suspicious. As is ec, of course.

From the summary:

  1. At the very least, we should be able to remove fromEqn*, replacing uses with other constructors. It's not clear if this is what we want however. In this case, it looks like the Theory contains the real information. Maybe this is a "relic of the past" from when we didn't have real theories, and too much information was packed into single equations' chunks. This seems to be one place where this is the case.
  2. DefinedQuantityDict appears to not be used as much as was expected. Their corresponding ConceptChunks are normally filled in with EmptyS or things that are never used. Most definitely any DQD with an EmptyS description should be made into a QD. (Though I would do that one-at-a-time to see if anything breaks!)
  3. My instinct here would be to try to float such descriptions upwards, to the theory.

As to the questions:

  1. maybe these "descriptions" are not descriptions at all. If they are only used in notes, maybe that's what they are?
  2. only the code can tell us... we need to see what parts of the code uses the description (is that its name?) Lens!

JacquesCarette avatar May 14 '25 18:05 JacquesCarette

For your examination of mcShrStrngthQD, I would run the same exercise in reverse. Take all the information that feeds into it, and make a 2-column table:

  • information -- what it seems to mean / actually be

Try to not let yourself be distracted by our current names. Use the use site of each piece of information to figure out operationally (in the eyes of the human reader of the produced artifacts) what that information seems to 'actually be'.

JacquesCarette avatar May 14 '25 18:05 JacquesCarette