Further basic cleanup

This commit is contained in:
Ozzie Gooen 2020-11-13 00:08:35 -08:00
parent 905ecf0ad3
commit 9520175795
10 changed files with 46 additions and 179 deletions

View File

@ -329,7 +329,7 @@ let shape: DistTypes.xyShape = {xs: [|1., 4., 8.|], ys: [|8., 9., 2.|]};
// let distPlus = // let distPlus =
// DistPlus.make( // DistPlus.make(
// ~shape=Mixed(mixed), // ~shape=Mixed(mixed),
// ~guesstimatorString=None, // ~squiggleString=None,
// (), // (),
// ); // );
// makeTest("minX", T.minX(distPlus), 1.0); // makeTest("minX", T.minX(distPlus), 1.0);

View File

@ -3,8 +3,7 @@ open Antd.Grid;
module FormConfig = [%lenses module FormConfig = [%lenses
type state = { type state = {
guesstimatorString: string, squiggleString: string,
//
sampleCount: string, sampleCount: string,
outputXYPoints: string, outputXYPoints: string,
downsampleTo: string, downsampleTo: string,
@ -122,18 +121,13 @@ module Styles = {
module DemoDist = { module DemoDist = {
[@react.component] [@react.component]
let make = (~guesstimatorString:string, ~options) => { let make = (~squiggleString:string, ~options) => {
<Antd.Card title={"Distribution" |> R.ste}> <Antd.Card title={"Distribution" |> R.ste}>
<div> <div>
{switch (options) { {switch (options) {
| Some(options) => | Some(options) =>
let distPlusIngredients =
DistPlusRenderer.Inputs.Ingredients.make(
~guesstimatorString,
(),
);
let inputs1 = let inputs1 =
DistPlusRenderer.Inputs.make( ProgramEvaluator.Inputs.make(
~samplingInputs={ ~samplingInputs={
sampleCount: Some(options.sampleCount), sampleCount: Some(options.sampleCount),
outputXYPoints: Some(options.outputXYPoints), outputXYPoints: Some(options.outputXYPoints),
@ -141,7 +135,7 @@ module DemoDist = {
shapeLength: shapeLength:
Some(options.downsampleTo |> E.O.default(1000)), Some(options.downsampleTo |> E.O.default(1000)),
}, },
~distPlusIngredients, ~squiggleString,
~environment= ~environment=
[| [|
("K", `SymbolicDist(`Float(1000.0))), ("K", `SymbolicDist(`Float(1000.0))),
@ -153,7 +147,7 @@ module DemoDist = {
(), (),
); );
let response1 = DistPlusRenderer.run2(inputs1); let response1 = ProgramEvaluator.evaluateProgram(inputs1);
switch (response1) { switch (response1) {
| Ok(`DistPlus(distPlus1)) => | Ok(`DistPlus(distPlus1)) =>
<DistPlusPlot distPlus={DistPlus.T.normalize(distPlus1)} /> <DistPlusPlot distPlus={DistPlus.T.normalize(distPlus1)} />
@ -161,15 +155,15 @@ module DemoDist = {
<ForetoldComponents.NumberShower number=f precision=3 /> <ForetoldComponents.NumberShower number=f precision=3 />
| Ok(`Function((f, a), env)) => | Ok(`Function((f, a), env)) =>
// Problem: When it gets the function, it doesn't save state about previous commands // Problem: When it gets the function, it doesn't save state about previous commands
let foo: DistPlusRenderer.Inputs.inputs = { let foo: ProgramEvaluator.Inputs.inputs = {
distPlusIngredients: inputs1.distPlusIngredients, squiggleString,
samplingInputs: inputs1.samplingInputs, samplingInputs: inputs1.samplingInputs,
environment: env, environment: env,
}; };
let results = let results =
E.A.Floats.range(options.diagramStart, options.diagramStop, options.diagramCount) E.A.Floats.range(options.diagramStart, options.diagramStop, options.diagramCount)
|> E.A.fmap(r => |> E.A.fmap(r =>
DistPlusRenderer.runFunction( ProgramEvaluator.evaluateFunction(
foo, foo,
(f, a), (f, a),
[|`SymbolicDist(`Float(r))|], [|`SymbolicDist(`Float(r))|],
@ -199,18 +193,6 @@ module DemoDist = {
}; };
}; };
// guesstimatorString: "
// us_economy_2018 = (10.5 to 10.6)T
// growth_rate = 1.08 to 1.2
// us_economy(t) = us_economy_2018 * (growth_rate^t)
// us_population_2019 = 320M to 330M
// us_population_growth_rate = 1.01 to 1.02
// us_population(t) = us_population_2019 * (us_population_growth_rate^t)
// gdp_per_person(t) = us_economy(t)/us_population(t)
// gdp_per_person
// ",
[@react.component] [@react.component]
let make = () => { let make = () => {
let (reloader, setReloader) = React.useState(() => 1); let (reloader, setReloader) = React.useState(() => 1);
@ -220,8 +202,8 @@ let make = () => {
~schema, ~schema,
~onSubmit=({state}) => {None}, ~onSubmit=({state}) => {None},
~initialState={ ~initialState={
//guesstimatorString: "mm(normal(-10, 2), uniform(18, 25), lognormal({mean: 10, stdev: 8}), triangular(31,40,50))", //squiggleString: "mm(normal(-10, 2), uniform(18, 25), lognormal({mean: 10, stdev: 8}), triangular(31,40,50))",
guesstimatorString: "mm(normal(5,2), normal(10,2))", squiggleString: "mm(normal(5,2), normal(10,2))",
sampleCount: "1000", sampleCount: "1000",
outputXYPoints: "1000", outputXYPoints: "1000",
downsampleTo: "", downsampleTo: "",
@ -238,7 +220,7 @@ let make = () => {
reform.submit(); reform.submit();
}; };
let guesstimatorString = reform.state.values.guesstimatorString; let squiggleString = reform.state.values.squiggleString;
let sampleCount = reform.state.values.sampleCount |> Js.Float.fromString; let sampleCount = reform.state.values.sampleCount |> Js.Float.fromString;
let outputXYPoints = let outputXYPoints =
reform.state.values.outputXYPoints |> Js.Float.fromString; reform.state.values.outputXYPoints |> Js.Float.fromString;
@ -273,9 +255,9 @@ let make = () => {
let demoDist = let demoDist =
React.useMemo1( React.useMemo1(
() => <DemoDist guesstimatorString options />, () => <DemoDist squiggleString options />,
[| [|
reform.state.values.guesstimatorString, reform.state.values.squiggleString,
reform.state.values.sampleCount, reform.state.values.sampleCount,
reform.state.values.outputXYPoints, reform.state.values.outputXYPoints,
reform.state.values.downsampleTo, reform.state.values.downsampleTo,
@ -307,7 +289,7 @@ let make = () => {
<Row _type=`flex className=Styles.rows> <Row _type=`flex className=Styles.rows>
<Col span=24> <Col span=24>
<FieldText <FieldText
field=FormConfig.GuesstimatorString field=FormConfig.SquiggleString
label="Program" label="Program"
/> />
</Col> </Col>

View File

@ -3,7 +3,7 @@ let plotBlue = `hex("1860ad");
let showAsForm = (distPlus: DistTypes.distPlus) => { let showAsForm = (distPlus: DistTypes.distPlus) => {
<div> <div>
<Antd.Input value={distPlus.guesstimatorString |> E.O.default("")} /> <Antd.Input value={distPlus.squiggleString |> E.O.default("")} />
</div>; </div>;
}; };

View File

@ -11,17 +11,8 @@ module Inputs = {
let defaultRecommendedLength = 100; let defaultRecommendedLength = 100;
let defaultShouldDownsample = true; let defaultShouldDownsample = true;
type ingredients = {guesstimatorString: string};
module Ingredients = {
type t = ingredients;
let make = (~guesstimatorString: string, ()): t => {
guesstimatorString: guesstimatorString,
};
};
type inputs = { type inputs = {
distPlusIngredients: ingredients, squiggleString: string,
samplingInputs: SamplingInputs.t, samplingInputs: SamplingInputs.t,
environment: ExpressionTypes.ExpressionTree.environment, environment: ExpressionTypes.ExpressionTree.environment,
}; };
@ -36,50 +27,41 @@ module Inputs = {
let make = let make =
( (
~samplingInputs=empty, ~samplingInputs=empty,
~distPlusIngredients, ~squiggleString,
~environment=ExpressionTypes.ExpressionTree.Environment.empty, ~environment=ExpressionTypes.ExpressionTree.Environment.empty,
(), (),
) )
: inputs => { : inputs => {
distPlusIngredients,
samplingInputs, samplingInputs,
squiggleString,
environment, environment,
}; };
}; };
module Internals = { module Internals = {
type inputs = {
samplingInputs: Inputs.SamplingInputs.t,
guesstimatorString: string,
environment: ExpressionTypes.ExpressionTree.environment,
};
let addVariable = let addVariable =
({samplingInputs, guesstimatorString, environment}: inputs, str, node) (
: inputs => { {samplingInputs, squiggleString, environment}: Inputs.inputs,
str,
node,
)
: Inputs.inputs => {
samplingInputs, samplingInputs,
guesstimatorString, squiggleString,
environment: environment:
ExpressionTypes.ExpressionTree.Environment.update(environment, str, _ => ExpressionTypes.ExpressionTree.Environment.update(environment, str, _ =>
Some(node) Some(node)
), ),
}; };
let distPlusRenderInputsToInputs = (inputs: Inputs.inputs): inputs => {
{
samplingInputs: inputs.samplingInputs,
guesstimatorString: inputs.distPlusIngredients.guesstimatorString,
environment: inputs.environment,
};
};
type outputs = { type outputs = {
graph: ExpressionTypes.ExpressionTree.node, graph: ExpressionTypes.ExpressionTree.node,
shape: DistTypes.shape, shape: DistTypes.shape,
}; };
let makeOutputs = (graph, shape): outputs => {graph, shape}; let makeOutputs = (graph, shape): outputs => {graph, shape};
let makeInputs = (inputs): ExpressionTypes.ExpressionTree.samplingInputs => { let makeInputs =
(inputs: Inputs.inputs): ExpressionTypes.ExpressionTree.samplingInputs => {
sampleCount: inputs.samplingInputs.sampleCount |> E.O.default(10000), sampleCount: inputs.samplingInputs.sampleCount |> E.O.default(10000),
outputXYPoints: outputXYPoints:
inputs.samplingInputs.outputXYPoints |> E.O.default(10000), inputs.samplingInputs.outputXYPoints |> E.O.default(10000),
@ -91,7 +73,7 @@ module Internals = {
ExpressionTree.toLeaf(makeInputs(inputs), inputs.environment, node); ExpressionTree.toLeaf(makeInputs(inputs), inputs.environment, node);
}; };
let runProgram = (inputs: inputs, p: ExpressionTypes.Program.program) => { let runProgram = (inputs: Inputs.inputs, p: ExpressionTypes.Program.program) => {
let ins = ref(inputs); let ins = ref(inputs);
p p
|> E.A.fmap( |> E.A.fmap(
@ -109,23 +91,19 @@ module Internals = {
|> E.A.R.firstErrorOrOpen; |> E.A.R.firstErrorOrOpen;
}; };
let inputsToLeaf = (inputs: inputs) => { let inputsToLeaf = (inputs: Inputs.inputs) => {
MathJsParser.fromString(inputs.guesstimatorString) MathJsParser.fromString(inputs.squiggleString)
|> E.R.bind(_, g => runProgram(inputs, g)) |> E.R.bind(_, g => runProgram(inputs, g))
|> E.R.bind(_, r => E.A.last(r) |> E.O.toResult("No rendered lines")); |> E.R.bind(_, r => E.A.last(r) |> E.O.toResult("No rendered lines"));
}; };
let outputToDistPlus = (inputs: Inputs.inputs, shape: DistTypes.shape) => { let outputToDistPlus = (inputs: Inputs.inputs, shape: DistTypes.shape) => {
DistPlus.make( DistPlus.make(~shape, ~squiggleString=Some(inputs.squiggleString), ());
~shape,
~guesstimatorString=Some(inputs.distPlusIngredients.guesstimatorString),
(),
);
}; };
}; };
let renderIfNeeded = let renderIfNeeded =
(inputs, node: ExpressionTypes.ExpressionTree.node) (inputs: Inputs.inputs, node: ExpressionTypes.ExpressionTree.node)
: result(ExpressionTypes.ExpressionTree.node, string) => : result(ExpressionTypes.ExpressionTree.node, string) =>
node node
|> ( |> (
@ -133,7 +111,7 @@ let renderIfNeeded =
| `Normalize(_) as n | `Normalize(_) as n
| `SymbolicDist(_) as n => { | `SymbolicDist(_) as n => {
`Render(n) `Render(n)
|> Internals.runNode(Internals.distPlusRenderInputsToInputs(inputs)) |> Internals.runNode(inputs)
|> ( |> (
fun fun
| Ok(`RenderedDist(_)) as r => r | Ok(`RenderedDist(_)) as r => r
@ -144,28 +122,7 @@ let renderIfNeeded =
| n => Ok(n) | n => Ok(n)
); );
let run = (inputs: Inputs.inputs) => { let coersionToExportedTypes =
inputs
|> Internals.distPlusRenderInputsToInputs
|> Internals.inputsToLeaf
|> E.R.bind(_, ((lastIns, r)) =>
r
|> renderIfNeeded(inputs)
|> (
fun
| Ok(`RenderedDist(n)) => Ok(n)
| Ok(n) =>
Error(
"Didn't output a rendered distribution. Format:"
++ ExpressionTree.toString(n),
)
| Error(r) => Error(r)
)
)
|> E.R.fmap(Internals.outputToDistPlus(inputs));
};
let exportDistPlus =
( (
inputs, inputs,
env: ProbExample.ExpressionTypes.ExpressionTree.environment, env: ProbExample.ExpressionTypes.ExpressionTree.environment,
@ -189,42 +146,18 @@ let exportDistPlus =
), ),
); );
// This isn't ok with floats, which can't be done in a function easily let evaluateProgram = (inputs: Inputs.inputs) => {
let exportDistPlus2 =
(
inputs,
env: ProbExample.ExpressionTypes.ExpressionTree.environment,
node: ExpressionTypes.ExpressionTree.node,
) =>
node
|> renderIfNeeded(inputs)
|> E.R.bind(
_,
fun
| `RenderedDist(n) =>
Ok(`DistPlus(Internals.outputToDistPlus(inputs, n)))
| `Function(n) => Ok(`Function((n, env)))
| n =>
Error(
"Didn't output a rendered distribution. Format:"
++ ExpressionTree.toString(n),
),
);
let run2 = (inputs: Inputs.inputs) => {
inputs inputs
|> Internals.distPlusRenderInputsToInputs
|> Internals.inputsToLeaf |> Internals.inputsToLeaf
|> E.R.bind(_, ((a, b)) => exportDistPlus(inputs, a, b)); |> E.R.bind(_, ((a, b)) => coersionToExportedTypes(inputs, a, b));
}; };
let runFunction = let evaluateFunction =
( (
ins: Inputs.inputs, inputs: Inputs.inputs,
fn: (array(string), ExpressionTypes.ExpressionTree.node), fn: (array(string), ExpressionTypes.ExpressionTree.node),
fnInputs, fnInputs,
) => { ) => {
let inputs = ins |> Internals.distPlusRenderInputsToInputs;
let output = let output =
ExpressionTree.runFunction( ExpressionTree.runFunction(
Internals.makeInputs(inputs), Internals.makeInputs(inputs),
@ -232,5 +165,5 @@ let runFunction =
fnInputs, fnInputs,
fn, fn,
); );
output |> E.R.bind(_, exportDistPlus2(ins, inputs.environment)); output |> E.R.bind(_, coersionToExportedTypes(inputs, inputs.environment));
}; };

View File

@ -6,14 +6,14 @@ let shapeIntegral = shape => Shape.T.Integral.get(shape);
let make = let make =
( (
~shape, ~shape,
~guesstimatorString, ~squiggleString,
~domain=Complete, ~domain=Complete,
~unit=UnspecifiedDistribution, ~unit=UnspecifiedDistribution,
(), (),
) )
: t => { : t => {
let integral = shapeIntegral(shape); let integral = shapeIntegral(shape);
{shape, domain, integralCache: integral, unit, guesstimatorString}; {shape, domain, integralCache: integral, unit, squiggleString};
}; };
let update = let update =
@ -22,14 +22,14 @@ let update =
~integralCache=?, ~integralCache=?,
~domain=?, ~domain=?,
~unit=?, ~unit=?,
~guesstimatorString=?, ~squiggleString=?,
t: t, t: t,
) => { ) => {
shape: E.O.default(t.shape, shape), shape: E.O.default(t.shape, shape),
integralCache: E.O.default(t.integralCache, integralCache), integralCache: E.O.default(t.integralCache, integralCache),
domain: E.O.default(t.domain, domain), domain: E.O.default(t.domain, domain),
unit: E.O.default(t.unit, unit), unit: E.O.default(t.unit, unit),
guesstimatorString: E.O.default(t.guesstimatorString, guesstimatorString), squiggleString: E.O.default(t.squiggleString, squiggleString),
}; };
let updateShape = (shape, t) => { let updateShape = (shape, t) => {

View File

@ -68,7 +68,7 @@ module ShapeMonad = {
}; };
type generationSource = type generationSource =
| GuesstimatorString(string) | SquiggleString(string)
| Shape(shape); | Shape(shape);
type distributionUnit = type distributionUnit =
@ -80,7 +80,7 @@ type distPlus = {
domain, domain,
integralCache: continuousShape, integralCache: continuousShape,
unit: distributionUnit, unit: distributionUnit,
guesstimatorString: option(string), squiggleString: option(string),
}; };
module DistributionUnit = { module DistributionUnit = {

View File

@ -1,48 +0,0 @@
// Not yet used
type inputs = {
samplingInputs: ExpressionTypes.ExpressionTree.SamplingInputs.t,
program: string,
environment: ExpressionTypes.ExpressionTree.environment,
};
let addVariable =
({program, samplingInputs, environment}: inputs, str, node): inputs => {
samplingInputs,
program,
environment:
ExpressionTypes.ExpressionTree.Environment.update(environment, str, _ =>
Some(node)
),
};
let runNode = (inputs: inputs, node) => {
ExpressionTree.toLeaf(
ExpressionTypes.ExpressionTree.SamplingInputs.withDefaults(
inputs.samplingInputs,
),
inputs.environment,
node,
);
};
let runProgram = (inputs: inputs, p: ExpressionTypes.Program.program) => {
let ins = ref(inputs);
p
|> E.A.fmap(
fun
| `Assignment(name, node) => {
ins := addVariable(ins^, name, node);
None;
}
| `Expression(node) =>
Some(runNode(ins^, node) |> E.R.fmap(r => (ins, r))),
)
|> E.A.O.concatSomes
|> E.A.R.firstErrorOrOpen;
};
let inputsToLeaf = (inputs: inputs) => {
MathJsParser.fromString(inputs.program)
|> E.R.bind(_, g => runProgram(inputs, g))
|> E.R.bind(_, r => E.A.last(r) |> E.O.toResult("No rendered lines"));
};