Skip to content

Commit

Permalink
Merge pull request #5 from smucclaw/GenericMathLang
Browse files Browse the repository at this point in the history
WIP: some text on Explainable codebase
  • Loading branch information
inariksit authored May 21, 2024
2 parents fc2d345 + e9b523e commit e8dec42
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 2 deletions.
12 changes: 12 additions & 0 deletions docs/current_system/codebase/explainable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Explainable

## Types

```haskell
type ExplainableIO r st a = RWST (HistoryPath,r) [String] st IO (a,XP)
type Explainable r st a = ExplainableIO r st a
```

## Evaluation

TODO
118 changes: 118 additions & 0 deletions docs/current_system/codebase/generic_mathlang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Generic MathLang

Generic MathLang is meant to be an intermediate step between the [Rule datatype](./rule_ast.md) and [MathLang](./mathlang.md).

Things that get more structured from Rule. A lot of things in Rule are just free text inside a `MTExpr`, but it gets parsed in Generic MathLang.

### Arithmetic expressions

In Rule, a single cell may contain arbitrary expressions. Compare lines 1 and 2:

```
SUM,foo,bar,,,,,,, (1)
,,,,,,,,,
foo + bar,,,,,,,,, (2)
```

Version (1) is parsed as an arithmetic expression in Rule, but version (2) is just free text. Generic MathLang parses everything it can, even inside the cells.

### Records

Text like `foo's,bar's,baz` gets parsed into records: `foo.bar.baz`.

### Functions

Rule may define functions as follows (see [example spreadsheet](https://docs.google.com/spreadsheets/d/1cWAb7Ba4HJovQn1PquZzYJjnjKUuhEPhNHzAH4ZfV4I/edit#gid=2100528279) for larger context):


```
GIVEN x IS A Number
y IS A Number
DECIDE x discounted by y IS x * (1 - y)
```

And we can apply the function (simplified the arguments):
```
DECIDE Answer IS firstArg discounted by secondArg
```

When parsed into rules, we don't have much structure:



```haskell
HC { hHead = RPConstraint
[ MTT "x", MTT "discounted by", MTT "y" ] RPis
[ MTT "x * (1 - y)" ]
, hBody = Nothing}

HC { hHead = RPConstraint
[ MTT "Answer" ] RPis
[ MTT "firstArg"
, MTT "discounted by"
, MTT "secondArg" ]
, hBody = Nothing}
```

The definition becomes as follows:

```haskell
( "discounted by",
(
[ MkVar "x", MkVar "y" ], MkExp
{ exp = ENumOp
{ numOp = OpMul, nopLeft = MkExp
{ exp = EVar
{ var = MkVar "x" }, md = [{- omitted some metadata: line number, type etc. -}]
}, nopRight = MkExp
{ exp = ENumOp
{ numOp = OpMinus, nopLeft = MkExp
{ exp = ELit
{ lit = EInteger 1 }, md = [{- omitted some metadata -}]
}, nopRight = MkExp
{ exp = EVar
{ var = MkVar "y" }, md = [{- omitted some metadata -}]
}
}, md = [{- omitted some metadata -}]
}
}, md = [{- omitted some metadata -}]
}
)
)
```

And the application as follows:

```haskell
EVarSet
{ vsetVar = MkExp
{ exp = EVar { var = MkVar "Answer" }, md = [] }, arg = MkExp
{ exp = EApp
{ func = MkExp
{ exp = EApp
{ func = MkExp
{ exp = EVar
{ var = MkVar "discounted by" }, md = [{- omitted some metadata -}]
}, appArg = MkExp
{ exp = EVar
{ var = MkVar "Step 3" }, md = [{- omitted some metadata -}]
}, md = []
}, appArg = MkExp
{ exp = ERec
{ fieldName = MkExp
{ exp = EVar
{ var = MkVar "risk cap" }, md = [{- omitted some metadata -}]
}, recName = MkExp
{ exp = EVar
{ var = MkVar "accident" }, md = [{- omitted some metadata -}]
}
}, md = []
}
}, md = []
}
}
```

## Types

[](https:/smucclaw/dsl/blob/main/lib/haskell/natural4/src/LS/XPile/MathLang/GenericMathLang/GenericMathLangAST.hs)
7 changes: 5 additions & 2 deletions docs/current_system/codebase/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,17 @@ TODO

## [The 'Explainable' codebase](https:/smucclaw/dsl/tree/main/lib/haskell/explainable)

[TODO]
The Explainable codebase includes the following components.

- [MathLang](./mathlang.md): a DSL for arithmetic expressions and predicates
- [Explainable](./explainable.md): a monad for evaluating MathLang expressions and providing explanations for the (intermediate and final) results

## Visualizations

### [Ladder Diagram](https:/smucclaw/ladder-diagram)

* [The main Ladder Diagram repo](https:/smucclaw/ladder-diagram)
* There are also docs available for this, via
* There are also docs available for this, via
```
npm install jsdoc -g
npm run docs
Expand Down
70 changes: 70 additions & 0 deletions docs/current_system/codebase/mathlang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# MathLang

Hornlikes from [Rule](./rule_ast.md) can be transformed into MathLang expressions. AFAIK there's no attempt to transform other rule types (regulative, constitutive, …).

## Types

The core of MathLang is the following `Expr` type (reordered here, but all constructors are shown).

```haskell
type ExprLabel = Maybe String
data Expr a =
-- I think these are the most relevant constructors
Val ExprLabel a -- ^ simple value
| MathBin ExprLabel MathBinOp (Expr a) (Expr a) -- ^ binary arithmetic operation
| MathVar String -- ^ variable reference
| MathSet String (Expr a) -- ^ variable assignment
| MathITE ExprLabel (Pred a) (Expr a) (Expr a) -- ^ if-then-else
| ListFold ExprLabel SomeFold (ExprList a) -- ^ fold a list of expressions into a single expr value

-- These I find less important / could probably be restructured?
| Parens ExprLabel (Expr a) -- ^ parentheses for grouping (??? why is this needed)
| MathMax ExprLabel (Expr a) (Expr a) -- ^ max of two expressions (ListFold covers this)
| MathMin ExprLabel (Expr a) (Expr a) -- ^ min of two expressions "
| MathApp ExprLabel String [String] (Expr a) -- ^ kind of a hack to allow for function to call another function etc. This constructor is removed in final result and the functions are inlined.
| Undefined ExprLabel -- ^ looks like a quick workaround after realizing there should be a way to recover from failure?

```

There's also similar structure for predicates.

```haskell
-- | conditional predicates: things that evaluate to a boolean
data Pred a
= PredVal ExprLabel Bool
| PredNot ExprLabel (Pred a) -- ^ boolean not
| PredComp ExprLabel Comp (Expr a) (Expr a) -- ^ Ord comparisions: x < y
| PredBin ExprLabel PredBinOp (Pred a) (Pred a) -- ^ predicate and / or / eq / ne
| PredVar String -- ^ boolean variable retrieval
| PredSet String (Pred a) -- ^ boolean variable assignment
| PredITE ExprLabel (Pred a) (Pred a) (Pred a) -- ^ if then else, booleans
| PredFold ExprLabel AndOr (PredList a) -- ^ and / or a list
```

Both expressions and predicates have list versions. PredList is just a type alias, ExprList has constructors for maps, filters etc. There's `MathSection` for partially applying binary functions, for the purpose of mapping over `ExprList`.

```haskell
type PredList a = [Pred a]

-- | We can filter, map, and mapIf over lists of expressions. Here, @a@ is pretty much always a @Double@.
data ExprList a
= MathList ExprLabel [Expr a] -- ^ a basic list of `Expr` expressions
| ListMap ExprLabel (MathSection a) (ExprList a) -- ^ apply the function to everything
| ListFilt ExprLabel (Expr a) Comp (ExprList a) -- ^ eliminate the unwanted elements
| ListMapIf ExprLabel (MathSection a) (Expr a) Comp (ExprList a) -- ^ leaving the unwanted elements unchanged
| ListConcat ExprLabel [ExprList a] -- ^ [[a]] -> [a]
| ListITE ExprLabel (Pred a) (ExprList a) (ExprList a) -- ^ if-then-else for expr lists

data MathSection a
= Id
| MathSection MathBinOp (Expr a)

data MathBinOp = Plus | Minus | Times | Divide | Modulo
```

## Pipeline

1. Spreadsheet gets parsed into a Rule
2. Rule (only Hornlike) gets transformed into [Generic MathLang](./generic_mathlang.md)
3. Generic MathLang is transformed into MathLang.

0 comments on commit e8dec42

Please sign in to comment.