Compare commits

...

1 Commits

Author SHA1 Message Date
Ozzie Gooen
33487afba8 WIP for pdf fix 2022-05-28 22:01:46 -04:00
3 changed files with 96 additions and 64 deletions

View File

@ -1,5 +1,5 @@
import * as React from "react"; import * as React from "react";
import { lambdaValue, environment, runForeign } from "@quri/squiggle-lang"; import { lambdaValue, environment, runForeign, errorValueToString } from "@quri/squiggle-lang";
import { FunctionChart1Dist } from "./FunctionChart1Dist"; import { FunctionChart1Dist } from "./FunctionChart1Dist";
import { FunctionChart1Number } from "./FunctionChart1Number"; import { FunctionChart1Number } from "./FunctionChart1Number";
import { ErrorBox } from "./ErrorBox"; import { ErrorBox } from "./ErrorBox";
@ -35,38 +35,42 @@ export const FunctionChart: React.FC<FunctionChartProps> = ({
} }
}; };
let validResult = getValidResult(); let validResult = getValidResult();
let resultType = validResult.tag === "Ok" ? validResult.value.tag : "Error";
let component = () => { let component = () => {
switch (resultType) { switch (validResult.tag) {
case "distribution": case "Ok": {
switch (validResult.value.tag) {
case "distribution":
return (
<FunctionChart1Dist
fn={fn}
chartSettings={chartSettings}
environment={environment}
height={height}
/>
);
case "number":
return (
<FunctionChart1Number
fn={fn}
chartSettings={chartSettings}
environment={environment}
height={height}
/>
);
default:
return (
<ErrorBox heading="No Viewer">
There is no function visualization for this type of function
</ErrorBox>
);
}
}
case "Error": {
return ( return (
<FunctionChart1Dist <ErrorBox heading="Error">The function failed to be run {errorValueToString(validResult.value)}</ErrorBox>
fn={fn}
chartSettings={chartSettings}
environment={environment}
height={height}
/>
);
case "number":
return (
<FunctionChart1Number
fn={fn}
chartSettings={chartSettings}
environment={environment}
height={height}
/>
);
case "Error":
return (
<ErrorBox heading="Error">The function failed to be run</ErrorBox>
);
default:
return (
<ErrorBox heading="No Viewer">
There is no function visualization for this type of function
</ErrorBox>
); );
}
} }
}; };

View File

@ -16,17 +16,23 @@ const samplesToContinuousPdf = (
_samples = _.filter(_samples, (r) => r < max); _samples = _.filter(_samples, (r) => r < max);
} }
console.log("19 line", _samples);
// The pdf that's created from this function is not a pdf but a pmf. y values // The pdf that's created from this function is not a pdf but a pmf. y values
// being probability mass and not density. // being probability mass and not density.
// This is awkward, because our code assumes later that y is a density // This is awkward, because our code assumes later that y is a density
let pdf = pdfast.create(_samples, { size, width }); let pdf = pdfast.create(_samples, { size, width });
console.log("24 line", pdf);
// To convert this to a density, we need to find the step size. This is kept if (pdf.length < 2) {
// constant for all y values return { xs: [], ys: [] };
let stepSize = pdf[1].x - pdf[0].x; } else {
// To convert this to a density, we need to find the step size. This is kept
// constant for all y values
let stepSize = pdf[1].x - pdf[0].x;
// We then adjust the y values to density // We then adjust the y values to density
return { xs: pdf.map((r) => r.x), ys: pdf.map((r) => r.y / stepSize) }; return { xs: pdf.map((r) => r.x), ys: pdf.map((r) => r.y / stepSize) };
}
}; };
module.exports = { module.exports = {

View File

@ -11,7 +11,7 @@ module Internals = {
type outputs = { type outputs = {
continuousParseParams: option<samplingStats>, continuousParseParams: option<samplingStats>,
pointSetDist: option<PointSetTypes.pointSetDist>, pointSetDist: result<PointSetTypes.pointSetDist, string>,
} }
} }
@ -32,8 +32,13 @@ module Internals = {
} }
module KDE = { module KDE = {
let normalSampling = (samples, outputXYPoints, kernelWidth) => let normalSampling = (samples, outputXYPoints, kernelWidth): result<
samples |> JS.samplesToContinuousPdf(_, outputXYPoints, kernelWidth) |> JS.jsToDist PointSetTypes.xyShape,
string,
> => {
let foo = samples |> JS.samplesToContinuousPdf(_, outputXYPoints, kernelWidth) |> JS.jsToDist
Ok(foo)
}
} }
module T = { module T = {
@ -52,8 +57,9 @@ module Internals = {
xWidthToUnitWidth(samples, outputXYPoints, suggestedXWidth) xWidthToUnitWidth(samples, outputXYPoints, suggestedXWidth)
} }
let kde = (~samples, ~outputXYPoints, width) => let kde = (~samples, ~outputXYPoints, width) => {
KDE.normalSampling(samples, outputXYPoints, width) KDE.normalSampling(samples, outputXYPoints, width)
}
} }
} }
@ -68,6 +74,7 @@ let toPointSetDist = (
samples, samples,
~minDiscreteWeight=minDiscreteToKeep, ~minDiscreteWeight=minDiscreteToKeep,
) )
Js.log3("Split", continuousPart, discretePart)
let length = samples |> E.A.length |> float_of_int let length = samples |> E.A.length |> float_of_int
let discrete: PointSetTypes.discreteShape = let discrete: PointSetTypes.discreteShape =
discretePart discretePart
@ -99,34 +106,49 @@ let toPointSetDist = (
bandwidthXImplemented: usedWidth, bandwidthXImplemented: usedWidth,
bandwidthUnitImplemented: usedUnitWidth, bandwidthUnitImplemented: usedUnitWidth,
} }
continuousPart let foo =
|> Internals.T.kde( continuousPart |> Internals.T.kde(
~samples=_, ~samples=_,
~outputXYPoints=samplingInputs.outputXYPoints, ~outputXYPoints=samplingInputs.outputXYPoints,
Internals.T.formatUnitWidth(usedUnitWidth), Internals.T.formatUnitWidth(usedUnitWidth),
) )
|> Continuous.make foo->E.R2.fmap(r => (Continuous.make(r), samplingStats))
|> (r => Some((r, samplingStats)))
} }
: None : Error("Bad Stuff")
let pointSetDist = MixedShapeBuilder.buildSimple( let pointSetDist =
~continuous=pdf |> E.O.fmap(fst), pdf |> E.R2.bind(_pdf =>
~discrete=Some(discrete), MixedShapeBuilder.buildSimple(
) ~continuous=Some(fst(_pdf)),
~discrete=Some(discrete),
) |> E.O.toResult("BadMan")
)
/* let foo = switch pdf {
I'm surprised that this doesn't come out normalized. My guess is that the KDE library | Ok(pdf) => {
we're using is standardizing on something else. If we ever change that library, we should let pointSetDist =
check to see if we still need to do this. MixedShapeBuilder.buildSimple(
*/ ~continuous=Some(fst(pdf)),
~discrete=Some(discrete),
let normalizedPointSet = pointSetDist->E.O2.fmap(PointSetDist.T.normalize) ) |> E.O.toResult("BadMan")
switch pointSetDist {
let samplesParse: Internals.Types.outputs = { | Ok(pointSetDist) => {
continuousParseParams: pdf |> E.O.fmap(snd), /*
pointSetDist: normalizedPointSet, I'm surprised that this doesn't come out normalized. My guess is that the KDE library
we're using is standardizing on something else. If we ever change that library, we should
check to see if we still need to do this.
*/
let normalized = PointSetDist.T.normalize(pointSetDist)
let samplesParse: Internals.Types.outputs = {
continuousParseParams: snd(pdf)->Some,
pointSetDist: Ok(PointSetDist.T.normalize(pointSetDist)),
}
Ok(samplesParse)
}
| Error(r) => Error(r)
}
}
| Error(r) => Error(r)
} }
foo
samplesParse
} }