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,10 +35,11 @@ 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 "Ok": {
switch (validResult.value.tag) {
case "distribution": case "distribution":
return ( return (
<FunctionChart1Dist <FunctionChart1Dist
@ -57,10 +58,6 @@ export const FunctionChart: React.FC<FunctionChartProps> = ({
height={height} height={height}
/> />
); );
case "Error":
return (
<ErrorBox heading="Error">The function failed to be run</ErrorBox>
);
default: default:
return ( return (
<ErrorBox heading="No Viewer"> <ErrorBox heading="No Viewer">
@ -68,6 +65,13 @@ export const FunctionChart: React.FC<FunctionChartProps> = ({
</ErrorBox> </ErrorBox>
); );
} }
}
case "Error": {
return (
<ErrorBox heading="Error">The function failed to be run {errorValueToString(validResult.value)}</ErrorBox>
);
}
}
}; };
return component(); return component();

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);
if (pdf.length < 2) {
return { xs: [], ys: [] };
} else {
// To convert this to a density, we need to find the step size. This is kept // To convert this to a density, we need to find the step size. This is kept
// constant for all y values // constant for all y values
let stepSize = pdf[1].x - pdf[0].x; 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,10 +57,11 @@ 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)
} }
} }
}
let toPointSetDist = ( let toPointSetDist = (
~samples: Internals.T.t, ~samples: Internals.T.t,
@ -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 =>
MixedShapeBuilder.buildSimple(
~continuous=Some(fst(_pdf)),
~discrete=Some(discrete), ~discrete=Some(discrete),
) |> E.O.toResult("BadMan")
) )
let foo = switch pdf {
| Ok(pdf) => {
let pointSetDist =
MixedShapeBuilder.buildSimple(
~continuous=Some(fst(pdf)),
~discrete=Some(discrete),
) |> E.O.toResult("BadMan")
switch pointSetDist {
| Ok(pointSetDist) => {
/* /*
I'm surprised that this doesn't come out normalized. My guess is that the KDE library 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 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. check to see if we still need to do this.
*/ */
let normalized = PointSetDist.T.normalize(pointSetDist)
let normalizedPointSet = pointSetDist->E.O2.fmap(PointSetDist.T.normalize)
let samplesParse: Internals.Types.outputs = { let samplesParse: Internals.Types.outputs = {
continuousParseParams: pdf |> E.O.fmap(snd), continuousParseParams: snd(pdf)->Some,
pointSetDist: normalizedPointSet, pointSetDist: Ok(PointSetDist.T.normalize(pointSetDist)),
} }
Ok(samplesParse)
samplesParse }
| Error(r) => Error(r)
}
}
| Error(r) => Error(r)
}
foo
} }