First attempt at simple working environment

This commit is contained in:
Ozzie Gooen 2020-07-31 09:00:12 +01:00
parent 67828cf789
commit e1374ee69b
7 changed files with 117 additions and 57 deletions

View File

@ -152,7 +152,7 @@ module DemoDist = {
shapeLength: Some(options.downsampleTo |> E.O.default(1000)) shapeLength: Some(options.downsampleTo |> E.O.default(1000))
}, },
~distPlusIngredients, ~distPlusIngredients,
~inputVariables= ~environment=
[|("p", `SymbolicDist(`Float(1.0)))|] [|("p", `SymbolicDist(`Float(1.0)))|]
->Belt.Map.String.fromArray, ->Belt.Map.String.fromArray,
(), (),

View File

@ -393,6 +393,7 @@ module Draw = {
let normalShape = let normalShape =
ExpressionTree.toShape( ExpressionTree.toShape(
{sampleCount: 10000, outputXYPoints: 10000, kernelWidth: None, shapeLength:numSamples}, {sampleCount: 10000, outputXYPoints: 10000, kernelWidth: None, shapeLength:numSamples},
ExpressionTypes.ExpressionTree.Environment.empty,
`SymbolicDist(normal), `SymbolicDist(normal),
) |> E.R.toExn; ) |> E.R.toExn;
let xyShape: Types.xyShape = let xyShape: Types.xyShape =

View File

@ -1,17 +1,17 @@
open ExpressionTypes.ExpressionTree; open ExpressionTypes.ExpressionTree;
let toLeaf = (samplingInputs, node: node) => { let toLeaf = (samplingInputs, environment, node: node) => {
node node
|> ExpressionTreeEvaluator.toLeaf({ |> ExpressionTreeEvaluator.toLeaf({
samplingInputs, samplingInputs,
environment,
evaluateNode: ExpressionTreeEvaluator.toLeaf, evaluateNode: ExpressionTreeEvaluator.toLeaf,
}); });
}; };
let toShape = (samplingInputs, node: node) => { let toShape = (samplingInputs, environment, node: node) => {
let renderResult = let renderResult =
`Render(`Normalize(node)) `Render(`Normalize(node)) |> toLeaf(samplingInputs, environment);
|> toLeaf(samplingInputs);
switch (renderResult) { switch (renderResult) {
| Ok(`RenderedDist(shape)) => Ok(shape) | Ok(`RenderedDist(shape)) => Ok(shape)

View File

@ -335,6 +335,7 @@ let toLeaf =
| `Normalize(t) => Normalize.operationToLeaf(evaluationParams, t) | `Normalize(t) => Normalize.operationToLeaf(evaluationParams, t)
| `Render(t) => Render.operationToLeaf(evaluationParams, t) | `Render(t) => Render.operationToLeaf(evaluationParams, t)
| `Function(t) => Ok(`Function(t)) | `Function(t) => Ok(`Function(t))
| `Symbol(r) => ExpressionTypes.ExpressionTree.Environment.get(evaluationParams.environment, r) |> E.O.toResult("Undeclared variable " ++ r)
| `CallableFunction(name, args) => | `CallableFunction(name, args) =>
callableFunction(evaluationParams, name, args) callableFunction(evaluationParams, name, args)
}; };

View File

@ -22,6 +22,7 @@ module ExpressionTree = {
| `FloatFromDist(distToFloatOperation, node) | `FloatFromDist(distToFloatOperation, node)
| `Function(node => result(node, string)) | `Function(node => result(node, string))
| `CallableFunction(string, array(node)) | `CallableFunction(string, array(node))
| `Symbol(string)
]; ];
type samplingInputs = { type samplingInputs = {
@ -31,8 +32,18 @@ module ExpressionTree = {
shapeLength: int shapeLength: int
}; };
type environment = Belt.Map.String.t(node);
module Environment = {
type t = environment
let empty:t = [||]->Belt.Map.String.fromArray
let update = (t,str, fn) => Belt.Map.String.update(t, str, fn)
let get = (t,str) => Belt.Map.String.get(t, str)
}
type evaluationParams = { type evaluationParams = {
samplingInputs, samplingInputs,
environment,
evaluateNode: (evaluationParams, node) => Belt.Result.t(node, string), evaluateNode: (evaluationParams, node) => Belt.Result.t(node, string),
}; };

View File

@ -8,7 +8,7 @@ module MathJsonToMathJsAdt = {
| Array(array(arg)) | Array(array(arg))
| Blocks(array(arg)) | Blocks(array(arg))
| Object(Js.Dict.t(arg)) | Object(Js.Dict.t(arg))
| Assignment(arg,arg) | Assignment(arg, arg)
and fn = { and fn = {
name: string, name: string,
args: array(arg), args: array(arg),
@ -44,19 +44,17 @@ module MathJsonToMathJsAdt = {
let items = field("items", array(run), j); let items = field("items", array(run), j);
Some(Array(items |> E.A.O.concatSomes)); Some(Array(items |> E.A.O.concatSomes));
| "SymbolNode" => Some(Symbol(field("name", string, j))) | "SymbolNode" => Some(Symbol(field("name", string, j)))
| "AssignmentNode" => { | "AssignmentNode" =>
let object_ = j |> field("object", run); let object_ = j |> field("object", run);
let value_ = j |> field("value", run); let value_ = j |> field("value", run);
switch(object_, value_){ switch (object_, value_) {
| (Some(o), Some(v)) => Some(Assignment(o,v)) | (Some(o), Some(v)) => Some(Assignment(o, v))
| _ => None | _ => None
} };
} | "BlockNode" =>
| "BlockNode" => {
let block = r => r |> field("node", run); let block = r => r |> field("node", run);
let args = j |> field("blocks", array(block)) |> E.A.O.concatSomes; let args = j |> field("blocks", array(block)) |> E.A.O.concatSomes;
Some(Blocks(args)) Some(Blocks(args));
}
| n => | n =>
Js.log3("Couldn't parse mathjs node", j, n); Js.log3("Couldn't parse mathjs node", j, n);
None; None;
@ -68,10 +66,7 @@ module MathAdtToDistDst = {
open MathJsonToMathJsAdt; open MathJsonToMathJsAdt;
let handleSymbol = (inputVars: inputVars, sym) => { let handleSymbol = (inputVars: inputVars, sym) => {
switch (Belt.Map.String.get(inputVars, sym)) { Ok(`Symbol(sym))
| Some(s) => Ok(s)
| None => Error("Couldn't find symbol " ++ sym)
};
}; };
module MathAdtCleaner = { module MathAdtCleaner = {
@ -100,7 +95,7 @@ module MathAdtToDistDst = {
| Symbol(s) => Symbol(s) | Symbol(s) => Symbol(s)
| Value(v) => Value(v) | Value(v) => Value(v)
| Blocks(args) => Blocks(args |> E.A.fmap(run)) | Blocks(args) => Blocks(args |> E.A.fmap(run))
| Assignment(a,b) => Assignment(a,run(b)) | Assignment(a, b) => Assignment(a, run(b))
| Object(v) => | Object(v) =>
Object( Object(
v v
@ -122,7 +117,10 @@ module MathAdtToDistDst = {
) )
| (_, _, Ok(mu), Ok(sigma)) => | (_, _, Ok(mu), Ok(sigma)) =>
Ok(`CallableFunction(("lognormal", [|mu, sigma|]))) Ok(`CallableFunction(("lognormal", [|mu, sigma|])))
| _ => Error("Lognormal distribution needs either mean and stdev or mu and sigma") | _ =>
Error(
"Lognormal distribution needs either mean and stdev or mu and sigma",
)
}; };
| _ => | _ =>
parseArgs() parseArgs()
@ -293,25 +291,40 @@ module MathAdtToDistDst = {
inputVars => inputVars =>
fun fun
| Value(f) => Ok(`SymbolicDist(`Float(f))) | Value(f) => Ok(`SymbolicDist(`Float(f)))
| Symbol(s) => handleSymbol(inputVars, s) | Symbol(sym) => Ok(`Symbol(sym))
| Fn({name, args}) => | Fn({name, args}) =>
functionParser(nodeParser(inputVars), name, args) functionParser(nodeParser(inputVars), name, args)
| _ => { | _ => {
Error("This type not currently supported"); Error("This type not currently supported");
}; };
let rec topLevel = inputVars => let rec topLevel =
fun (inputVars: inputVars, r)
| Value(_) as r => nodeParser(inputVars, r) : result(ExpressionTypes.Program.program, string) =>
| Fn(_) as r => nodeParser(inputVars, r) switch (r) {
| Value(_) as r =>
nodeParser(inputVars, r) |> E.R.fmap(r => [|`Expression(r)|])
| Fn(_) as r =>
nodeParser(inputVars, r) |> E.R.fmap(r => [|`Expression(r)|])
| Array(_) => Error("Array not valid as top level") | Array(_) => Error("Array not valid as top level")
| Symbol(s) => handleSymbol(inputVars, s) | Symbol(s) =>
handleSymbol(inputVars, s) |> E.R.fmap(r => [|`Expression(r)|])
| Object(_) => Error("Object not valid as top level") | Object(_) => Error("Object not valid as top level")
| Assignment(_) => Error("Assignment not valid as top level") | Assignment(name, value) =>
| Blocks(blocks) => E.A.last(blocks) |> E.O.toResult("no blocks listed") |> E.R.bind(_, topLevel(inputVars)) switch (name) {
| Symbol(symbol) =>
nodeParser(inputVars, value)
|> E.R.fmap(r => [|`Assignment((symbol, r))|])
| _ => Error("Symbol not a string")
}
| Blocks(blocks) =>
blocks
|> E.A.fmap(b => topLevel(inputVars, b))
|> E.A.R.firstErrorOrOpen
|> E.R.fmap(E.A.concatMany)
};
let run = let run = (inputVars, r): result(ExpressionTypes.Program.program, string) =>
(inputVars, r): result(ExpressionTypes.ExpressionTree.node, string) =>
r |> MathAdtCleaner.run |> topLevel(inputVars); r |> MathAdtCleaner.run |> topLevel(inputVars);
}; };

View File

@ -31,29 +31,31 @@ module Inputs = {
unit, unit,
}; };
}; };
type inputs = { type inputs = {
distPlusIngredients: ingredients, distPlusIngredients: ingredients,
samplingInputs: SamplingInputs.t, samplingInputs: SamplingInputs.t,
inputVariables: Belt.Map.String.t(ExpressionTypes.ExpressionTree.node), environment: ExpressionTypes.ExpressionTree.environment
}; };
let empty: SamplingInputs.t = { let empty: SamplingInputs.t = {
sampleCount: None, sampleCount: None,
outputXYPoints: None, outputXYPoints: None,
kernelWidth: None, kernelWidth: None,
shapeLength: None shapeLength: None,
}; };
let make = let make =
( (
~samplingInputs=empty, ~samplingInputs=empty,
~distPlusIngredients, ~distPlusIngredients,
~inputVariables=[||]->Belt.Map.String.fromArray, ~environment=ExpressionTypes.ExpressionTree.Environment.empty,
(), (),
) )
: inputs => { : inputs => {
distPlusIngredients, distPlusIngredients,
samplingInputs, samplingInputs,
inputVariables, environment,
}; };
}; };
@ -61,14 +63,27 @@ module Internals = {
type inputs = { type inputs = {
samplingInputs: Inputs.SamplingInputs.t, samplingInputs: Inputs.SamplingInputs.t,
guesstimatorString: string, guesstimatorString: string,
inputVariables: Belt.Map.String.t(ExpressionTypes.ExpressionTree.node), environment: ExpressionTypes.ExpressionTree.environment,
};
let addVariable =
(
{samplingInputs, guesstimatorString, environment}: inputs,
str,
node,
)
: inputs => {
samplingInputs,
guesstimatorString,
environment:
ExpressionTypes.ExpressionTree.Environment.update(environment, str, _ => Some(node))
}; };
let distPlusRenderInputsToInputs = (inputs: Inputs.inputs): inputs => { let distPlusRenderInputsToInputs = (inputs: Inputs.inputs): inputs => {
{ {
samplingInputs: inputs.samplingInputs, samplingInputs: inputs.samplingInputs,
guesstimatorString: inputs.distPlusIngredients.guesstimatorString, guesstimatorString: inputs.distPlusIngredients.guesstimatorString,
inputVariables: inputs.inputVariables, environment: inputs.environment,
}; };
}; };
@ -78,27 +93,46 @@ module Internals = {
}; };
let makeOutputs = (graph, shape): outputs => {graph, shape}; let makeOutputs = (graph, shape): outputs => {graph, shape};
let inputsToShape = (inputs: inputs) => { let runNode = (inputs, node) => {
MathJsParser.fromString(inputs.guesstimatorString, inputs.inputVariables) Js.log2("Inputs", inputs);
|> E.R.bind(_, g =>
ExpressionTree.toShape( ExpressionTree.toShape(
{ {
sampleCount: sampleCount: inputs.samplingInputs.sampleCount |> E.O.default(10000),
inputs.samplingInputs.sampleCount |> E.O.default(10000),
outputXYPoints: outputXYPoints:
inputs.samplingInputs.outputXYPoints |> E.O.default(10000), inputs.samplingInputs.outputXYPoints |> E.O.default(10000),
kernelWidth: inputs.samplingInputs.kernelWidth, kernelWidth: inputs.samplingInputs.kernelWidth,
shapeLength: inputs.samplingInputs.shapeLength |> E.O.default(10000) shapeLength: inputs.samplingInputs.shapeLength |> E.O.default(10000),
}, },
g, inputs.environment,
) node,
|> E.R.fmap(makeOutputs(g))
); );
}; };
let outputToDistPlus = (inputs: Inputs.inputs, outputs: outputs) => { let runProgram = (inputs: inputs, p: ExpressionTypes.Program.program) => {
let ins = ref(inputs);
p
|> E.A.fmap(statement =>
switch (statement) {
| `Assignment(name, node) =>
ins := addVariable(ins^, name, node);
Js.log4("HIHI", ins, name, node);
None;
| `Expression(node) => Some(runNode(ins^, node))
}
)
|> E.A.O.concatSomes
|> E.A.R.firstErrorOrOpen;
};
let inputsToShape = (inputs: inputs) => {
MathJsParser.fromString(inputs.guesstimatorString, inputs.environment)
|> E.R.bind(_, g => runProgram(inputs, g))
|> E.R.bind(_, r => E.A.last(r) |> E.O.toResult("sdf"));
};
let outputToDistPlus = (inputs: Inputs.inputs, shape: DistTypes.shape) => {
DistPlus.make( DistPlus.make(
~shape=outputs.shape, ~shape,
~domain=inputs.distPlusIngredients.domain, ~domain=inputs.distPlusIngredients.domain,
~unit=inputs.distPlusIngredients.unit, ~unit=inputs.distPlusIngredients.unit,
~guesstimatorString=Some(inputs.distPlusIngredients.guesstimatorString), ~guesstimatorString=Some(inputs.distPlusIngredients.guesstimatorString),